# Detecting which segments have been modified

**URL:** <https://discourse.slicer.org/t/detecting-which-segments-have-been-modified/44453>\
**Category:** Development\
**Tags:** segmentation\
**Created:** [September 11, 2025, 9:28pm UTC](https://discourse.slicer.org/t/detecting-which-segments-have-been-modified/44453 "2025-09-11T21:28:34Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![pieper](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/pieper/32/8_2.png) [@pieper](https://discourse.slicer.org/u/pieper)\
**Post date:** [September 11, 2025, 9:28pm UTC](https://discourse.slicer.org/t/detecting-which-segments-have-been-modified/44453/1 "2025-09-11T21:28:34Z")

</div>

I’m observing `vtkSegmentation.SourceRepresentationModified` and in the callback method I want to figure out which of the segments have been modified. Does anyone know a good way to do this?

I tried checking the MTimes of the `vtkSegment`s but they don’t change when I edit. If I call

```auto
representation = segmentation.GetSourceRepresentationName()
segmentation.GetSegment(segmentID).GetRepresentation(representation).GetMTime())

```

then the MTime changes, but since all the segments share the same representation I can’t tell which one changed.

I’d rather not have to look into the representation and compare the data.

---

<div class="post-metadata">

**Author:** ![jcfr](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/jcfr/32/17825_2.png) [@jcfr](https://discourse.slicer.org/u/jcfr)\
**Post date:** [September 11, 2025, 9:47pm UTC](https://discourse.slicer.org/t/detecting-which-segments-have-been-modified/44453/2 "2025-09-11T21:47:57Z")

</div>

The event `vtkSegmentation::SegmentModified` is probably what you are looking for, the call data will be segment identifier.

---

<div class="post-metadata">

**Author:** ![pieper](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/pieper/32/8_2.png) [@pieper](https://discourse.slicer.org/u/pieper)\
**Post date:** [September 11, 2025, 11:43pm UTC](https://discourse.slicer.org/t/detecting-which-segments-have-been-modified/44453/3 "2025-09-11T23:43:10Z")

</div>

Thanks @jcfr, I did look at that. From [what is posted here](https://discourse.slicer.org/t/observe-modified-segment/7528/2) that is only fired when the segment metadata is modified, not the contents. For now I’ve just disable the feature I was hoping to use.

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [September 12, 2025, 12:13am UTC](https://discourse.slicer.org/t/detecting-which-segments-have-been-modified/44453/4 "2025-09-12T00:13:12Z")

</div>

The easiest way to check if a segment was modified is to use the segment status. It is changed from the default `NotStarted` to `InProgress` whenever the user modifies a segment.

I used this to speed up saving of ~~nnUnet~~ TotalSegmentator-training-data-style (single segment per file) segmentations after manual editing. I submitted a [pull request that implements the complete workflow of iterating through TotalSegmentator datasets and allows the user to fix up the segmentations using nnInteractive and save the modified segments](https://github.com/JoostJM/SlicerCaseIterator/pull/22). This would have revitalized the CaseIterator a bit (and the changes to existing code were quite minimal) but the PR was not merged. This triggered the whole discussion about transferring the ownership of CaseIterator.

@pieper It would be great if you could make use of this code in your new AI training data editor extension.

---

<div class="post-metadata">

**Author:** ![muratmaga](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/muratmaga/32/3622_2.png) [@muratmaga](https://discourse.slicer.org/u/muratmaga)\
**Post date:** [September 12, 2025, 12:37am UTC](https://discourse.slicer.org/t/detecting-which-segments-have-been-modified/44453/5 "2025-09-12T00:37:21Z")

</div>

> [@lassoan](#):
>
> The easiest way to check if a segment was modified is to use the segment status. It is changed from the default `NotStarted` to `InProgress` whenever the user modifies a segment.

But this would not recognize a case when a segment is not modified since it is last saved (because it would be still `InProgess` unless the user chooses another state)?

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [September 12, 2025, 12:52am UTC](https://discourse.slicer.org/t/detecting-which-segments-have-been-modified/44453/6 "2025-09-12T00:52:16Z")

</div>

> [@muratmaga](#):
>
> this would not recognize a case when a segment is not modified since it is last saved (because it would be still `InProgess` unless the user chooses another state)?

When a segment is not modified then it does not have to be saved. It is useful for editing TotalSegmentator training data, in which each segment is stored in a separate file. Skipping saving of unchanged segments saves a lot of time when iterating through images.

If all the segments are stored in a single file then the segment state does not matter much, because then all the segments are saved into the file anyway.

---

<div class="post-metadata">

**Author:** ![mau\_igna\_06](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/mau_igna_06/32/9056_2.png) [@mau\_igna\_06](https://discourse.slicer.org/u/mau_igna_06)\
**Post date:** [September 12, 2025, 1:24am UTC](https://discourse.slicer.org/t/detecting-which-segments-have-been-modified/44453/7 "2025-09-12T01:24:47Z")

</div>

Maybe this is what you want Steve:

```python
# add a sample CT and open the segment editor 
# and add a few segments

@vtk.calldata_type(vtk.VTK_LONG)
def myfunc(caller, eventId, callData):
  print('segment modified: ', callData)

seg = getNode('Segmentation')
seg.AddObserver(slicer.vtkSegmentation.SourceRepresentationModified, myfunc)

# modify segments and check out the printed number by myfunc

```

Tested on Slicer Preview

---

<div class="post-metadata">

**Author:** ![pieper](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/pieper/32/8_2.png) [@pieper](https://discourse.slicer.org/u/pieper)\
**Post date:** [September 12, 2025, 8:24pm UTC](https://discourse.slicer.org/t/detecting-which-segments-have-been-modified/44453/8 "2025-09-12T20:24:10Z")

</div>

Thanks for all the help everyone.

@mau_igna_06 that looks pretty good, and I get a unique value for each segment I tried but the call data seems to be a pointer like `4048792338560069170` or `3834588781771632178` and it’s not clear now to map that to segment IDs.

@lassoan thanks for the pointer to the iterator code. It helped to see how the `Status` is used.

For my use case I am loading segmentations that already exist, so the `Status` may already be something other than `NotStarted` but since we aren’t using the status for anything else at this point I can set them all to `NotStarted` with `segmentationLogic.SetSegmentStatus(segment, segmentationLogic.NotStarted)` and then check the status later.

As a side note, before I learned about `GetSegmentStatus` I thought I would need to access the `vtkSegment` tags directly but I didn’t see a way to access them directly through python. It would be nice to have a method signature that wraps. Or is there another way to call it?

```auto
>>> status = ""
>>> seg.GetTag('Segmentation.Status', status)
Traceback (most recent call last):
File "<console>", line 1, in <module>
TypeError: GetTag argument 2:

```

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [September 12, 2025, 9:03pm UTC](https://discourse.slicer.org/t/detecting-which-segments-have-been-modified/44453/9 "2025-09-12T21:03:15Z")

</div>

The API is Python-wrapped, see how it is used here:

> <https://github.com/lassoan/SlicerSegmentEditorExtraEffects/blob/784997471e8e4dfede24ab9618519b95be5b4e4d/SegmentEditorDrawTube/SegmentEditorDrawTubeLib/SegmentEditorEffect.py#L297>

But this mutable variable is quite esoteric, so I agree it would be nice to have a simpler, more Pythonic API (and a method to get all the tag names).

---

<div class="post-metadata">

**Author:** ![chir.set](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/chir.set/32/66982_2.png) [@chir.set](https://discourse.slicer.org/u/chir.set)\
**Post date:** [September 12, 2025, 9:10pm UTC](https://discourse.slicer.org/t/detecting-which-segments-have-been-modified/44453/10 "2025-09-12T21:10:05Z")

</div>

> [@pieper](#):
>
> a way to access them directly through python

Using [vtk.reference()](https://github.com/vmtk/SlicerExtension-VMTK/blob/6e787f8d7b6871c1bc450abca1283c3e36985e0c/GuidedVeinSegmentation/GuidedVeinSegmentation.py#L395) seems to do the trick too. I have no idea how it differs from `vtk.mutable()`.

There’s a nice `vtkSegment::GetTags()` in C++, it does not seem to be wrapped for Python indeed.

I’m also interested in detecting a change in a segment selectively and didn’t find a way for that. I’ll dig more about @lassoan 's solution above.

---

<div class="post-metadata">

**Author:** ![pieper](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/pieper/32/8_2.png) [@pieper](https://discourse.slicer.org/u/pieper)\
**Post date:** [September 13, 2025, 2:14am UTC](https://discourse.slicer.org/t/detecting-which-segments-have-been-modified/44453/11 "2025-09-13T02:14:53Z")

</div>

For the record, here’s what I ended up doing for now:

> <https://github.com/MorphoCloud/SlicerMorphoDepot/blob/main/MorphoDepot/MorphoDepot.py#L451-L520>

Thanks again everyone!
