# Stopping optimization by metric value for demons filters

**URL:** https://discourse.itk.org/t/stopping-optimization-by-metric-value-for-demons-filters/4190
**Category:** Beginner Questions
**Tags:** python, simpleitk
**Created:** [June 8, 2021, 5:46pm UTC](https://discourse.itk.org/t/stopping-optimization-by-metric-value-for-demons-filters/4190 "2021-06-08T17:46:02Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![bbikdash](https://discourse.itk.org/user_avatar/discourse.itk.org/bbikdash/32/2117_2.png) [@bbikdash](https://discourse.itk.org/u/bbikdash)
#### Post date: [June 8, 2021, 5:46pm UTC](https://discourse.itk.org/t/stopping-optimization-by-metric-value-for-demons-filters/4190/1 "2021-06-08T17:46:02Z")

</div>

Hi,

I’m currently using the Python demons registration filters (DemonsRegistrationFilter, DifferomorphicDRF, SymmetricDRF, etc.) from SimpleITK to perform non-rigid image registration on x-rays for my research.

Is there a simple way to set the filters to stop running upon reaching a certain metric value? Right now, the filters run until the maximum number of iterations has been reached regardless of metric value.

I’ve looked through the documentation several times and I can’t seem to find what I’m looking for. I know that one solution would be to run the the filter twice to see what metric value is achieved at each iteration but if registration takes 1000s of iterations I’d prefer not to do it more than once.

Should I be using the ITKv4 registration framework instead to better control optimization?

---

<div class="post-metadata">

### Author: ![zivy](https://discourse.itk.org/user_avatar/discourse.itk.org/zivy/32/1726_2.png) [@zivy](https://discourse.itk.org/u/zivy)
#### Post date: [June 8, 2021, 7:44pm UTC](https://discourse.itk.org/t/stopping-optimization-by-metric-value-for-demons-filters/4190/2 "2021-06-08T19:44:24Z")

</div>

Hello @bbikdash,

Welcome to SimpleITK!

The Demons family of algorithms has a `SetMaximumRMSError` which provides you with an image similarity based stopping criterion, the `SetNumberOfIterations` gives you a known bound on the number of iterations.

Using the observer/callback mechanism you can look at the RMS change `GetRMSChange` and force early termination by changing the caller’s settings (I believe `SetNumberOfIterations(GetElapsedIterations()-1)` will work though haven’t tried it).

---

<div class="post-metadata">

### Author: ![bbikdash](https://discourse.itk.org/user_avatar/discourse.itk.org/bbikdash/32/2117_2.png) [@bbikdash](https://discourse.itk.org/u/bbikdash)
#### Post date: [June 8, 2021, 8:31pm UTC](https://discourse.itk.org/t/stopping-optimization-by-metric-value-for-demons-filters/4190/3 "2021-06-08T20:31:31Z")

</div>

Hi @zivy,

Thanks for your advice. I tried some of what you recommended. I’ve been basing my code on the python version here: [DemonsRegistration1 — SimpleITK 2.0rc2 documentation](https://simpleitk.readthedocs.io/en/master/link_DemonsRegistration1_docs.html)

I experimented with the `SetMaximumRMSError` function and it definitely works to stop iterations. However, when experimenting with two sets of images the final RMS was higher for the more similar images and lower for images that were more different. So, demons registration stopped for images that needed more registration but kept going for images that were registered very well.

When I added a callback to look at the RMS Change values they were all 0.0. The exact modification I did is shown below.

```
def command_iteration(filter):
    print(f"{filter.GetElapsedIterations():3} = {filter.GetMetric():10.5f}\n"
            f"RMS Change: {filter.GetRMSChange():5:10f}")

```

But, if I understand you what told me, the command\_iteration inline function allows me to send callbacks to the demons observable during runtime. I should be able to add a stopping criterion in this inline function based on the metric or RMS error.

I added a stopping criterion based on the current metric value. Here’s my modified function:

```
def command_iteration(filter):
        print(f"{filter.GetElapsedIterations():3} = {filter.GetMetric():10.5f}")

        # This is a test to stop the filter in the middle of iterations
        if filter.GetMetric() < 10.0:
            filter.SetNumberOfIterations(filter.GetElapsedIterations() - 1)
            print(f"{filter.GetNumberOfIterations():3}")

```

I don’t think it stopped iterations. This is an excerpt of the output:

```
    40 = 10.13214
     41 = 10.06969
     42 = 9.95903
     41
     43 = 10.21076
     44 = 9.88058
     43
     45 = 9.95140
     44
     46 = 9.80128
     45
     47 = 9.84532
     46
     48 = 9.81111
     47
     49 = 9.67928
     48
     50 = 9.69624
     49

```

Do you know if there are any other methods that might work?

---

<div class="post-metadata">

### Author: ![zivy](https://discourse.itk.org/user_avatar/discourse.itk.org/zivy/32/1726_2.png) [@zivy](https://discourse.itk.org/u/zivy)
#### Post date: [June 10, 2021, 1:28pm UTC](https://discourse.itk.org/t/stopping-optimization-by-metric-value-for-demons-filters/4190/4 "2021-06-10T13:28:07Z")

</div>

Hello @bbikdash,

Looks like this trick doesn’t work. It is due to the SimpleITK implementation and the interaction with the underlying ITK code. It should be addressed by [this PR](https://github.com/SimpleITK/SimpleITK/pull/1405) which will expose the `StopRegistration` method, allowing the caller to explicitly stop the registration.

To use the functionality you will have to update your version of SimpleITK to [latest](https://github.com/SimpleITK/SimpleITK/releases/tag/latest), once the PR is merged.

---

<div class="post-metadata">

### Author: ![bbikdash](https://discourse.itk.org/user_avatar/discourse.itk.org/bbikdash/32/2117_2.png) [@bbikdash](https://discourse.itk.org/u/bbikdash)
#### Post date: [June 11, 2021, 2:22pm UTC](https://discourse.itk.org/t/stopping-optimization-by-metric-value-for-demons-filters/4190/5 "2021-06-11T14:22:26Z")

</div>

Hi, @zivy,

Thank you for the update. I’m glad I was able to contribute to adding more functionality to SimpleITK.

My last questions are, will the documentation be updated to include this new function and will this update also apply to the Anaconda version of SimpleITK?

Although it seems fairly intuitive, I want to make sure I use it properly.

---

<div class="post-metadata">

### Author: ![zivy](https://discourse.itk.org/user_avatar/discourse.itk.org/zivy/32/1726_2.png) [@zivy](https://discourse.itk.org/u/zivy)
#### Post date: [June 11, 2021, 5:54pm UTC](https://discourse.itk.org/t/stopping-optimization-by-metric-value-for-demons-filters/4190/6 "2021-06-11T17:54:50Z")

</div>

Hi @bbikdash,

Yes documentation will be added and this will be part of the SimpleITK anaconda distribution.

The next official SimpleITK release, 2.1, is expected in the next couple of weeks so you will be able to install that from the toolkit’s anaconda cloud channel. If you are in a hurry you will be able to use the feature once the pull-request is merged and the latest release is updated on GitHub (the install from GitHub works for anaconda too).

---

<div class="post-metadata">

### Author: ![zivy](https://discourse.itk.org/user_avatar/discourse.itk.org/zivy/32/1726_2.png) [@zivy](https://discourse.itk.org/u/zivy)
#### Post date: [June 15, 2021, 12:46pm UTC](https://discourse.itk.org/t/stopping-optimization-by-metric-value-for-demons-filters/4190/7 "2021-06-15T12:46:27Z")

</div>

Hello @bbikdash,

The `StopRegistration` method for all of the Demons based filters is now available, install [latest release from GitHub](https://github.com/SimpleITK/SimpleITK/releases/tag/latest).
