Skip to content

Pulling models from trackastra leads to error due to writting restriction in containerized microsam #1124

@rjlopez2

Description

@rjlopez2

We are building a container with napari-microsam in our computer cluster runing on a virtual desktop that runs on an openondemand app.
After loading a sample image and recreate the tutorial for object tracking with trackastra we encounter the following error:

INFO: Computed embeddings for the 'Light Microscopy' model of size 'base'.
---------------------------------------------------------------------------
OSError                                   Traceback (most recent call last)
File /opt/conda/envs/napari-microSAM_env/lib/python3.13/site-packages/micro_sam/sam_annotator/_widgets.py:2013, in AutoSegmentWidget.__call__(self=<micro_sam.sam_annotator._widgets.AutoTrackWidget object>)
   2007     kwargs = {
   2008         "pred_iou_thresh": self.pred_iou_thresh,
   2009         "stability_score_thresh": self.stability_score_thresh,
   2010         "box_nms_thresh": self.box_nms_thresh,
   2011     }
   2012 if self.volumetric and self.apply_to_volume:
-> 2013     worker = self._run_segmentation_3d(kwargs)
        self = <micro_sam.sam_annotator._widgets.AutoTrackWidget object at 0x7fd5c8d09910>
        kwargs = {'center_distance_threshold': 0.4, 'boundary_distance_threshold': 0.5, 'min_size': 100}   2014 elif self.volumetric and not self.apply_to_volume:
   2015     i = int(self._viewer.dims.point[0])

File /opt/conda/envs/napari-microSAM_env/lib/python3.13/site-packages/micro_sam/sam_annotator/_widgets.py:2103, in AutoTrackWidget._run_segmentation_3d(self=<micro_sam.sam_annotator._widgets.AutoTrackWidget object>, kwargs={'boundary_distance_threshold': 0.5, 'center_distance_threshold': 0.4, 'min_size': 100})
   2100     self._viewer.layers["auto_segmentation"].data = segmentation
   2101     self._viewer.layers["auto_segmentation"].refresh()
-> 2103 result = seg_impl()
   2104 update_segmentation(result)

File /opt/conda/envs/napari-microSAM_env/lib/python3.13/site-packages/micro_sam/sam_annotator/_widgets.py:2083, in AutoTrackWidget._run_segmentation_3d.<locals>.seg_impl()
   2080     pbar_signals.pbar_update.emit(1)
   2082 pbar_signals.pbar_reset.emit()
-> 2083 segmentation, lineages = track_across_frames(
        segmentation = array([[[   0,    0, ...,    0,    0],
        [   0,    0, ...,    0,    0],
        ...,
        [   0,    0, ...,    0,    0],
        [   0,    0, ...,    0,    0]],

       [[   0,    0, ...,    0,    0],
        [   0,    0, ...,    0,    0],
        ...,
        [   0,    0, ...,    0,    0],
        [   0,    0, ...,    0,    0]],

       ...,

       [[   0,    0, ..., 1084, 1084],
        [   0,    0, ..., 1084, 1084],
        ...,
        [   0,    0, ...,    0,    0],
        [   0,    0, ...,    0,    0]],

       [[   0,    0, ...,    0,    0],
        [   0,    0, ...,    0,    0],
        ...,
        [   0,    0, ...,    0,    0],
        [   0,    0, ...,    0,    0]]],
      shape=(84, 512, 512), dtype=uint32)
        timeseries = array([[[132, 128, ..., 131, 126],
        [125, 136, ..., 119, 112],
        ...,
        [132, 130, ..., 127, 131],
        [128, 131, ..., 132, 131]],

       [[116, 114, ..., 114, 114],
        [111, 115, ..., 116, 117],
        ...,
        [121, 125, ..., 120, 118],
        [120, 124, ..., 116, 116]],

       ...,

       [[116, 113, ..., 116, 113],
        [115, 119, ..., 121, 113],
        ...,
        [123, 127, ..., 122, 126],
        [122, 123, ..., 115, 127]],

       [[118, 118, ..., 120, 110],
        [118, 119, ..., 127, 116],
        ...,
        [122, 119, ..., 124, 118],
        [117, 121, ..., 126, 121]]], shape=(84, 512, 512), dtype=uint8)
        pbar_signals = <micro_sam.sam_annotator._widgets.PBarSignals object at 0x7fd5c8d0bc80>   2084     timeseries, segmentation,
   2085     verbose=True, pbar_init=pbar_init,
   2086     pbar_update=lambda update: pbar_signals.pbar_update.emit(1),
   2087 )
   2088 pbar_signals.pbar_stop.emit()
   2089 return (segmentation, lineages)

File /opt/conda/envs/napari-microSAM_env/lib/python3.13/site-packages/micro_sam/multi_dimensional_segmentation.py:638, in track_across_frames(timeseries=array([[[132, 128, ..., 131, 126],
        [125,..., 126, 121]]], shape=(84, 512, 512), dtype=uint8), segmentation=array([[[   0,    0, ...,    0,    0],
        [...  0]]],
      shape=(84, 512, 512), dtype=uint32), gap_closing=None, min_time_extent=None, verbose=True, pbar_init=<function AutoTrackWidget._run_segmentation_3d.<locals>.seg_impl.<locals>.pbar_init>, pbar_update=<function AutoTrackWidget._run_segmentation_3d.<locals>.seg_impl.<locals>.<lambda>>, output_folder=None)
    635 if gap_closing is not None and gap_closing > 0:
    636     segmentation = _preprocess_closing(segmentation, gap_closing, pbar_update)
--> 638 segmentation, lineage = _tracking_impl(
        segmentation = array([[[   0,    0, ...,    0,    0],
        [   0,    0, ...,    0,    0],
        ...,
        [   0,    0, ...,    0,    0],
        [   0,    0, ...,    0,    0]],

       [[   0,    0, ...,    0,    0],
        [   0,    0, ...,    0,    0],
        ...,
        [   0,    0, ...,    0,    0],
        [   0,    0, ...,    0,    0]],

       ...,

       [[   0,    0, ..., 1084, 1084],
        [   0,    0, ..., 1084, 1084],
        ...,
        [   0,    0, ...,    0,    0],
        [   0,    0, ...,    0,    0]],

       [[   0,    0, ...,    0,    0],
        [   0,    0, ...,    0,    0],
        ...,
        [   0,    0, ...,    0,    0],
        [   0,    0, ...,    0,    0]]],
      shape=(84, 512, 512), dtype=uint32)
        np = <module 'numpy' from '/opt/conda/envs/napari-microSAM_env/lib/python3.13/site-packages/numpy/__init__.py'>
        timeseries = array([[[132, 128, ..., 131, 126],
        [125, 136, ..., 119, 112],
        ...,
        [132, 130, ..., 127, 131],
        [128, 131, ..., 132, 131]],

       [[116, 114, ..., 114, 114],
        [111, 115, ..., 116, 117],
        ...,
        [121, 125, ..., 120, 118],
        [120, 124, ..., 116, 116]],

       ...,

       [[116, 113, ..., 116, 113],
        [115, 119, ..., 121, 113],
        ...,
        [123, 127, ..., 122, 126],
        [122, 123, ..., 115, 127]],

       [[118, 118, ..., 120, 110],
        [118, 119, ..., 127, 116],
        ...,
        [122, 119, ..., 124, 118],
        [117, 121, ..., 126, 121]]], shape=(84, 512, 512), dtype=uint8)
        min_time_extent = None
        output_folder = None    639     timeseries=np.asarray(timeseries),
    640     segmentation=segmentation,
    641     mode="greedy",
    642     min_time_extent=min_time_extent,
    643     output_folder=output_folder,
    644 )
    645 return segmentation, lineage

File /opt/conda/envs/napari-microSAM_env/lib/python3.13/site-packages/micro_sam/multi_dimensional_segmentation.py:578, in _tracking_impl(timeseries=array([[[132, 128, ..., 131, 126],
        [125,..., 126, 121]]], shape=(84, 512, 512), dtype=uint8), segmentation=array([[[   0,    0, ...,    0,    0],
        [...  0]]],
      shape=(84, 512, 512), dtype=uint32), mode='greedy', min_time_extent=None, output_folder=None)
    576 def _tracking_impl(timeseries, segmentation, mode, min_time_extent, output_folder=None):
    577     device = "cuda" if torch.cuda.is_available() else "cpu"
--> 578     model = Trackastra.from_pretrained("general_2d", device=device)
        device = 'cuda'    579     lineage_graph = model.track(timeseries, segmentation, mode=mode)
    580     track_data, parent_graph, _ = graph_to_napari_tracks(lineage_graph)

File /opt/conda/envs/napari-microSAM_env/lib/python3.13/site-packages/trackastra/model/model_api.py:152, in Trackastra.from_pretrained(cls=<class 'trackastra.model.model_api.Trackastra'>, name='general_2d', device='cuda', download_dir=None)
    136 @classmethod
    137 def from_pretrained(
    138     cls, name: str, device: str | None = None, download_dir: Path | None = None
    139 ):
    140     """Load a pretrained Trackastra model.
    141 
    142     Available pretrained models are described in detail in pretrained.json.
   (...)    150         Trackastra model instance.
    151     """
--> 152     folder = download_pretrained(name, download_dir)
        name = 'general_2d'
        download_dir = None    153     # download zip from github to location/name, then unzip
    154     return cls.from_folder(folder, device=device)

File /opt/conda/envs/napari-microSAM_env/lib/python3.13/site-packages/trackastra/model/pretrained.py:66, in download_pretrained(name='general_2d', download_dir=PosixPath('/opt/conda/envs/napari-microSAM_env/lib/python3.13/site-packages/trackastra/.models'))
     63 else:
     64     download_dir = Path(download_dir)
---> 66 download_dir.mkdir(exist_ok=True, parents=True)
        download_dir = PosixPath('/opt/conda/envs/napari-microSAM_env/lib/python3.13/site-packages/trackastra/.models')     67 try:
     68     url = _MODELS[name]

File /opt/conda/envs/napari-microSAM_env/lib/python3.13/pathlib/_local.py:722, in Path.mkdir(self=PosixPath('/opt/conda/envs/napari-microSAM_env/lib/python3.13/site-packages/trackastra/.models'), mode=511, parents=True, exist_ok=True)
    718 """
    719 Create a new directory at this given path.
    720 """
    721 try:
--> 722     os.mkdir(self, mode)
        self = PosixPath('/opt/conda/envs/napari-microSAM_env/lib/python3.13/site-packages/trackastra/.models')
        mode = 511    723 except FileNotFoundError:
    724     if not parents or self.parent == self:

OSError: [Errno 30] Read-only file system: '/opt/conda/envs/napari-microSAM_env/lib/python3.13/site-packages/trackastra/.models'

our setup ("napari --info" command bellow):

(base) [rl18y689@gnode28 development]$ apptainer exec --nv napari-microSAM-1.6.2.sif /opt/launchers/start_napari.sh --info
WARNING: could not determine DPI
WARNING:vispy:could not determine DPI
WARNING: could not determine DPI
WARNING:vispy:could not determine DPI
WARNING: could not determine DPI
WARNING:vispy:could not determine DPI
WARNING: could not determine DPI
WARNING:vispy:could not determine DPI
napari: 0.6.6 (from conda)
Platform: Linux-5.14.0-570.58.1.el9_6.x86_64-x86_64-with-glibc2.34
System: Rocky Linux 9.7 (Blue Onyx)
Python: 3.13.11 | packaged by conda-forge | (main, Dec  6 2025, 11:24:03) [GCC 14.3.0]
Qt: 5.15.15
PyQt5: 5.15.11
NumPy: 2.3.5
SciPy: 1.16.3
Dask: 2025.11.0
VisPy: 0.15.2
magicgui: 0.10.1
superqt: 0.7.6
in-n-out: 0.2.1
app-model: 0.4.0
psygnal: 0.15.0
npe2: 0.7.9
pydantic: 2.11.10

OpenGL:
  - PyOpenGL: 3.1.10
  - GL version:  4.6.0 NVIDIA 550.163.01
  - MAX_TEXTURE_SIZE: 32768
  - GL_MAX_3D_TEXTURE_SIZE: 16384

Screens:
  - screen 1: resolution 1824x1089, scale 1.0

Optional:
  - numba: 0.63.0
  - triangle not installed
  - napari-plugin-manager: 0.1.8
  - bermuda: 0.1.6
  - PartSegCore: 0.15.14

Experimental Settings:
  - Async: False
  - Autoswap buffers: False
  - Triangulation backend: Fastest available

Settings path:
  - /storage/homefs/rl18y689/.vibe/.config/napari/napari-microSAM_env_6a700390b4d4d8d8b66f95ee9e18d42c59217c64/settings.yaml

Launch command:
  - /opt/conda/envs/napari-microSAM_env/bin/napari --info

Plugins:
  - micro-sam: 1.6.2 (26 contributions)
  - napari: 0.6.6 (88 contributions)
  - napari-console: 0.1.4 (0 contributions)
  - napari-svg: 0.2.1 (2 contributions)
  - skan: 0.13.0 (4 contributions)

and here is the yaml file to recreate our python environment:

name: napari-microSAM_env
channels:
  - conda-forge
dependencies:
  - pip
  - pyqt
  - napari
  - micro_sam
  - pip:
    - git+https://github.com/ChaoningZhang/MobileSAM.git
    - trackastra
  

I wander if there is way to change or allow to choose a safer location where the models would be downloaded to as is done here to pull the sample data?:

by setting the environment variable: MICROSAM_CACHEDIR

Or to use the same cache folder where the example images are downloaded?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions