Improve regularisation documentation and add ADMT demo - #427

Merged
jacklovell merged 24 commits into
developmentfrom
feature/admt-demo
Aug 20, 2026
Merged

Improve regularisation documentation and add ADMT demo#427
jacklovell merged 24 commits into
developmentfrom
feature/admt-demo

Conversation

@jacklovell

@jacklovelljacklovell commented Mar 11, 2024

Copy link
Copy Markdown
Member
  • Add a Regularisation section to the tomography documentation, describing the functionality inside the admt_utils module.
  • Fixup the docstrings in admt_utils.
  • Add calculation of "skewed" second derivative operators, which operate along the diagonals of the grid.
  • Add a bolometer diagonstic system to Generomak.
  • Add a new example using the Generomak bolometers and the regularisation operators to perform isotropic and ADMT inversions.
  • Add a regularised NNLS function which uses sparse matrices.
  • Enable the functions in admt_utils to optionally output sparse matrices depending on the input.

Fixes#382 and #380

* Add a Regularisation section to the tomography documentation,
describing the functionality inside the admt_utils module.
* Fixup the docstrings in admt_utils.
* Add calculation of "skewed" second derivative operators, which
operate along the diagonals of the grid.
* Add a bolometer diagonstic system to Generomak.
* Add a new example using the Generomak bolometers and the
regularisation operators to perform isotropic and ADMT inversions.

@vsnevervsnever left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @jacklovell, very valuable demo. A similar regularisation is used in ITER divertor bolometry to reconstruct the radiation power density profile. Generomak also receives the first diagnostics, which in itself is great.

I think the changelog should reflect that this demo has been added, and also that the bolometric diagnostic model has been added to Generomak.

I also have some comments and a few suggestions.

Comment threaddocs/source/tools/tomography.rst Outdated
Comment threaddemos/observers/bolometry/admt_tomographic_inversion.py
Comment threaddemos/observers/bolometry/admt_tomographic_inversion.py
Comment threadcherab/generomak/diagnostics/bolometers.py Outdated
Comment threadcherab/generomak/diagnostics/bolometers.py Outdated
Comment threadcherab/generomak/diagnostics/bolometers.py Outdated
Comment threadcherab/generomak/diagnostics/bolometers.py Outdated
Comment threadcherab/tools/inversions/admt_utils.py
Comment threaddemos/observers/bolometry/admt_tomographic_inversion.py
jacklovelland others added 6 commits May 18, 2026 09:39
* Fix the series of transforms to position and orient the bolometer
cameras.
* Update geometry parameters such that the lines of sight all follow a
consistant convention and specify the channel ordering in the
docstring. This required adding the ability to rotate the sensors
about the viewing axis to reverse the channel order of the
horizontal-poloidal camera.
* Correct the docstring of load_bolometers to specify the correct
number of 4-channel sensors in each camera.
* Expand docstrings and comments to better describe the intricacies of
setting up the bolometer geometry.
* More thorough commenting of the function to make it easier to follow
what is going on and why.
* Exploit the sparsity of the derivative opreators but using a
dictionary-of-keys representation instead of dense numpy arrays. A
dictionary is faster to insert single elements into inside the loop
than a numpy array too.
* Remove the `np.isnan` checkc which are slow for single elements,
replace with a cheap check for `None`.
* Support returning the operators as Scipy sparse arrays for use
downstream. Default to returning as Numpy arrays for backwards
compatibility.
These changes result in an order of magnitude speedup in this function.
This is done automatically if the derivative operators are
sparse. A dense operator is returned otherwise.
An alternative to `invert_regularised_nnls` using sparse weight and
penalty matrices. The numerical algorithm used is slightly different
to `scipy.optimize.nnls`, as it uses the TRF variant of a bounded
`scipy.optimize.lsq_linear` with the lower bound set to 0 to enforce
positivity. Since the results differ due to floating point precision,
the sparse variant is implemented as a separate function to maintain
backwards compatibility.
* Produce additional inversions which incorporate Generomak's
tangentially-viewing channels, for comparison with the poloidal-only
inversions.
* Correctly scale the emissivity.
* Fix removing the ray transfer grid from the world before
forward-modelling the bolometer measurements.
* Better explain why we're building the 1D <-> 2D maps by hand instead
of just using the ray transfer matrix capabilities directly: this is
for generality.
* Use the sparse variant of the NNLS inversion for speed and memory
efficiency. The grid is large enough for this to be worthwhile.
@jacklovelljacklovell changed the title WIP: Improve regularisation documentation and add ADMT demoImprove regularisation documentation and add ADMT demoJul 15, 2026
@MateasekMateasek mentioned this pull request Jul 16, 2026
12 tasks
Comment threadcherab/generomak/diagnostics/bolometers.py
Comment threadcherab/generomak/diagnostics/bolometers.py
Comment threadcherab/tools/inversions/nnls.py
This makes it easier for users to explore the geometry and potentially
even edit it for testing purposes.
This is a more common term in the literature for a bolometer unit
integrating several (typically 4) channels.
* The 1D-to-2D and 2D-to-1D maps are the inverse of one another, so
one can be computed from the other. Depending on how the end user
forms their inversion grid it may be simpler to calculate the
1D-to-2D or the 2D-to-1D, so allow the caller to pass either and
compute any missing mapping. If the caller already has both
mappings (machine packages like cherab-jet, cherab-mastu and
cherab-aug already generate both) then accept both too.
* Add tests for auto-computing missing mappings.
* Tests uncovered a bug converting the Dyy sparse operator to dense
when `sparse=False` was passed: fix that and complete test coverage
for `admt_utils`.
* Simplify the ADMT script by only computing the 1D-to-2D map as this
is fairly trivially obtained from the Ray Transfer object.
@jacklovell
jacklovell requested a review from skuba31July 31, 2026 16:19
@jacklovell

Copy link
Copy Markdown
MemberAuthor

I've implemented the changes from both reviews now: thanks to @vsnever and @skuba31. I am going to hold firm on the formulism in generate_derivative_operators though, as I think the benefits of sparseness and explicitness outweigh any potential performance gains or loss of generality of the vectorized version Vlad proposed before the iterative improvements from the reviews. As a compromise the function is now better commented and the interface is a bit easier to use for callers as reflected in the demo.

Once this is approved I'll do a squash merge as the commit history is longer than necessary to keep going forwards.

Comment threadcherab/generomak/diagnostics/bolometers.py
Comment threaddemos/observers/bolometry/admt_tomographic_inversion.py Outdated

@skuba31skuba31 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work @jacklovell . I think that the documentation and code readability is significantly improved. The sparse support and ADMT demo are very useful additions. I have added a few minor comments for consideration before final approval.

@skuba31skuba31 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I consider this PR to be ready for merge now.

@jacklovell
jacklovell merged commit fcdeaf7 into developmentAug 20, 2026
12 checks passed
@jacklovell
jacklovell deleted the feature/admt-demo branch August 20, 2026 15:05
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@jacklovell@vsnever@skuba31
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Improve regularisation documentation and add ADMT demo - #427

Merged
jacklovell merged 24 commits into
developmentfrom
feature/admt-demo
Aug 20, 2026
Merged

Improve regularisation documentation and add ADMT demo#427
jacklovell merged 24 commits into
developmentfrom
feature/admt-demo

Conversation

@jacklovell

@jacklovelljacklovell commented Mar 11, 2024

Copy link
Copy Markdown
Member
  • Add a Regularisation section to the tomography documentation, describing the functionality inside the admt_utils module.
  • Fixup the docstrings in admt_utils.
  • Add calculation of "skewed" second derivative operators, which operate along the diagonals of the grid.
  • Add a bolometer diagonstic system to Generomak.
  • Add a new example using the Generomak bolometers and the regularisation operators to perform isotropic and ADMT inversions.
  • Add a regularised NNLS function which uses sparse matrices.
  • Enable the functions in admt_utils to optionally output sparse matrices depending on the input.

Fixes#382 and #380

* Add a Regularisation section to the tomography documentation,
describing the functionality inside the admt_utils module.
* Fixup the docstrings in admt_utils.
* Add calculation of "skewed" second derivative operators, which
operate along the diagonals of the grid.
* Add a bolometer diagonstic system to Generomak.
* Add a new example using the Generomak bolometers and the
regularisation operators to perform isotropic and ADMT inversions.

@vsnevervsnever left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @jacklovell, very valuable demo. A similar regularisation is used in ITER divertor bolometry to reconstruct the radiation power density profile. Generomak also receives the first diagnostics, which in itself is great.

I think the changelog should reflect that this demo has been added, and also that the bolometric diagnostic model has been added to Generomak.

I also have some comments and a few suggestions.

Comment threaddocs/source/tools/tomography.rst Outdated
Comment threaddemos/observers/bolometry/admt_tomographic_inversion.py
Comment threaddemos/observers/bolometry/admt_tomographic_inversion.py
Comment threadcherab/generomak/diagnostics/bolometers.py Outdated
Comment threadcherab/generomak/diagnostics/bolometers.py Outdated
Comment threadcherab/generomak/diagnostics/bolometers.py Outdated
Comment threadcherab/generomak/diagnostics/bolometers.py Outdated
Comment threadcherab/tools/inversions/admt_utils.py
Comment threaddemos/observers/bolometry/admt_tomographic_inversion.py
jacklovelland others added 6 commits May 18, 2026 09:39
* Fix the series of transforms to position and orient the bolometer
cameras.
* Update geometry parameters such that the lines of sight all follow a
consistant convention and specify the channel ordering in the
docstring. This required adding the ability to rotate the sensors
about the viewing axis to reverse the channel order of the
horizontal-poloidal camera.
* Correct the docstring of load_bolometers to specify the correct
number of 4-channel sensors in each camera.
* Expand docstrings and comments to better describe the intricacies of
setting up the bolometer geometry.
* More thorough commenting of the function to make it easier to follow
what is going on and why.
* Exploit the sparsity of the derivative opreators but using a
dictionary-of-keys representation instead of dense numpy arrays. A
dictionary is faster to insert single elements into inside the loop
than a numpy array too.
* Remove the `np.isnan` checkc which are slow for single elements,
replace with a cheap check for `None`.
* Support returning the operators as Scipy sparse arrays for use
downstream. Default to returning as Numpy arrays for backwards
compatibility.
These changes result in an order of magnitude speedup in this function.
This is done automatically if the derivative operators are
sparse. A dense operator is returned otherwise.
An alternative to `invert_regularised_nnls` using sparse weight and
penalty matrices. The numerical algorithm used is slightly different
to `scipy.optimize.nnls`, as it uses the TRF variant of a bounded
`scipy.optimize.lsq_linear` with the lower bound set to 0 to enforce
positivity. Since the results differ due to floating point precision,
the sparse variant is implemented as a separate function to maintain
backwards compatibility.
* Produce additional inversions which incorporate Generomak's
tangentially-viewing channels, for comparison with the poloidal-only
inversions.
* Correctly scale the emissivity.
* Fix removing the ray transfer grid from the world before
forward-modelling the bolometer measurements.
* Better explain why we're building the 1D <-> 2D maps by hand instead
of just using the ray transfer matrix capabilities directly: this is
for generality.
* Use the sparse variant of the NNLS inversion for speed and memory
efficiency. The grid is large enough for this to be worthwhile.
@jacklovelljacklovell changed the title WIP: Improve regularisation documentation and add ADMT demoImprove regularisation documentation and add ADMT demoJul 15, 2026
@MateasekMateasek mentioned this pull request Jul 16, 2026
12 tasks
Comment threadcherab/generomak/diagnostics/bolometers.py
Comment threadcherab/generomak/diagnostics/bolometers.py
Comment threadcherab/tools/inversions/nnls.py
This makes it easier for users to explore the geometry and potentially
even edit it for testing purposes.
This is a more common term in the literature for a bolometer unit
integrating several (typically 4) channels.
* The 1D-to-2D and 2D-to-1D maps are the inverse of one another, so
one can be computed from the other. Depending on how the end user
forms their inversion grid it may be simpler to calculate the
1D-to-2D or the 2D-to-1D, so allow the caller to pass either and
compute any missing mapping. If the caller already has both
mappings (machine packages like cherab-jet, cherab-mastu and
cherab-aug already generate both) then accept both too.
* Add tests for auto-computing missing mappings.
* Tests uncovered a bug converting the Dyy sparse operator to dense
when `sparse=False` was passed: fix that and complete test coverage
for `admt_utils`.
* Simplify the ADMT script by only computing the 1D-to-2D map as this
is fairly trivially obtained from the Ray Transfer object.
@jacklovell
jacklovell requested a review from skuba31July 31, 2026 16:19
@jacklovell

Copy link
Copy Markdown
MemberAuthor

I've implemented the changes from both reviews now: thanks to @vsnever and @skuba31. I am going to hold firm on the formulism in generate_derivative_operators though, as I think the benefits of sparseness and explicitness outweigh any potential performance gains or loss of generality of the vectorized version Vlad proposed before the iterative improvements from the reviews. As a compromise the function is now better commented and the interface is a bit easier to use for callers as reflected in the demo.

Once this is approved I'll do a squash merge as the commit history is longer than necessary to keep going forwards.

Comment threadcherab/generomak/diagnostics/bolometers.py
Comment threaddemos/observers/bolometry/admt_tomographic_inversion.py Outdated

@skuba31skuba31 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work @jacklovell . I think that the documentation and code readability is significantly improved. The sparse support and ADMT demo are very useful additions. I have added a few minor comments for consideration before final approval.

@skuba31skuba31 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I consider this PR to be ready for merge now.

@jacklovell
jacklovell merged commit fcdeaf7 into developmentAug 20, 2026
12 checks passed
@jacklovell
jacklovell deleted the feature/admt-demo branch August 20, 2026 15:05
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@jacklovell@vsnever@skuba31
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Improve regularisation documentation and add ADMT demo - #427

Merged
jacklovell merged 24 commits into
developmentfrom
feature/admt-demo
Aug 20, 2026
Merged

Improve regularisation documentation and add ADMT demo#427
jacklovell merged 24 commits into
developmentfrom
feature/admt-demo

Conversation

@jacklovell

@jacklovelljacklovell commented Mar 11, 2024

Copy link
Copy Markdown
Member
  • Add a Regularisation section to the tomography documentation, describing the functionality inside the admt_utils module.
  • Fixup the docstrings in admt_utils.
  • Add calculation of "skewed" second derivative operators, which operate along the diagonals of the grid.
  • Add a bolometer diagonstic system to Generomak.
  • Add a new example using the Generomak bolometers and the regularisation operators to perform isotropic and ADMT inversions.
  • Add a regularised NNLS function which uses sparse matrices.
  • Enable the functions in admt_utils to optionally output sparse matrices depending on the input.

Fixes#382 and #380

* Add a Regularisation section to the tomography documentation,
describing the functionality inside the admt_utils module.
* Fixup the docstrings in admt_utils.
* Add calculation of "skewed" second derivative operators, which
operate along the diagonals of the grid.
* Add a bolometer diagonstic system to Generomak.
* Add a new example using the Generomak bolometers and the
regularisation operators to perform isotropic and ADMT inversions.

@vsnevervsnever left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @jacklovell, very valuable demo. A similar regularisation is used in ITER divertor bolometry to reconstruct the radiation power density profile. Generomak also receives the first diagnostics, which in itself is great.

I think the changelog should reflect that this demo has been added, and also that the bolometric diagnostic model has been added to Generomak.

I also have some comments and a few suggestions.

Comment threaddocs/source/tools/tomography.rst Outdated
Comment threaddemos/observers/bolometry/admt_tomographic_inversion.py
Comment threaddemos/observers/bolometry/admt_tomographic_inversion.py
Comment threadcherab/generomak/diagnostics/bolometers.py Outdated
Comment threadcherab/generomak/diagnostics/bolometers.py Outdated
Comment threadcherab/generomak/diagnostics/bolometers.py Outdated
Comment threadcherab/generomak/diagnostics/bolometers.py Outdated
Comment threadcherab/tools/inversions/admt_utils.py
Comment threaddemos/observers/bolometry/admt_tomographic_inversion.py
jacklovelland others added 6 commits May 18, 2026 09:39
* Fix the series of transforms to position and orient the bolometer
cameras.
* Update geometry parameters such that the lines of sight all follow a
consistant convention and specify the channel ordering in the
docstring. This required adding the ability to rotate the sensors
about the viewing axis to reverse the channel order of the
horizontal-poloidal camera.
* Correct the docstring of load_bolometers to specify the correct
number of 4-channel sensors in each camera.
* Expand docstrings and comments to better describe the intricacies of
setting up the bolometer geometry.
* More thorough commenting of the function to make it easier to follow
what is going on and why.
* Exploit the sparsity of the derivative opreators but using a
dictionary-of-keys representation instead of dense numpy arrays. A
dictionary is faster to insert single elements into inside the loop
than a numpy array too.
* Remove the `np.isnan` checkc which are slow for single elements,
replace with a cheap check for `None`.
* Support returning the operators as Scipy sparse arrays for use
downstream. Default to returning as Numpy arrays for backwards
compatibility.
These changes result in an order of magnitude speedup in this function.
This is done automatically if the derivative operators are
sparse. A dense operator is returned otherwise.
An alternative to `invert_regularised_nnls` using sparse weight and
penalty matrices. The numerical algorithm used is slightly different
to `scipy.optimize.nnls`, as it uses the TRF variant of a bounded
`scipy.optimize.lsq_linear` with the lower bound set to 0 to enforce
positivity. Since the results differ due to floating point precision,
the sparse variant is implemented as a separate function to maintain
backwards compatibility.
* Produce additional inversions which incorporate Generomak's
tangentially-viewing channels, for comparison with the poloidal-only
inversions.
* Correctly scale the emissivity.
* Fix removing the ray transfer grid from the world before
forward-modelling the bolometer measurements.
* Better explain why we're building the 1D <-> 2D maps by hand instead
of just using the ray transfer matrix capabilities directly: this is
for generality.
* Use the sparse variant of the NNLS inversion for speed and memory
efficiency. The grid is large enough for this to be worthwhile.
@jacklovelljacklovell changed the title WIP: Improve regularisation documentation and add ADMT demoImprove regularisation documentation and add ADMT demoJul 15, 2026
@MateasekMateasek mentioned this pull request Jul 16, 2026
12 tasks
Comment threadcherab/generomak/diagnostics/bolometers.py
Comment threadcherab/generomak/diagnostics/bolometers.py
Comment threadcherab/tools/inversions/nnls.py
This makes it easier for users to explore the geometry and potentially
even edit it for testing purposes.
This is a more common term in the literature for a bolometer unit
integrating several (typically 4) channels.
* The 1D-to-2D and 2D-to-1D maps are the inverse of one another, so
one can be computed from the other. Depending on how the end user
forms their inversion grid it may be simpler to calculate the
1D-to-2D or the 2D-to-1D, so allow the caller to pass either and
compute any missing mapping. If the caller already has both
mappings (machine packages like cherab-jet, cherab-mastu and
cherab-aug already generate both) then accept both too.
* Add tests for auto-computing missing mappings.
* Tests uncovered a bug converting the Dyy sparse operator to dense
when `sparse=False` was passed: fix that and complete test coverage
for `admt_utils`.
* Simplify the ADMT script by only computing the 1D-to-2D map as this
is fairly trivially obtained from the Ray Transfer object.
@jacklovell
jacklovell requested a review from skuba31July 31, 2026 16:19
@jacklovell

Copy link
Copy Markdown
MemberAuthor

I've implemented the changes from both reviews now: thanks to @vsnever and @skuba31. I am going to hold firm on the formulism in generate_derivative_operators though, as I think the benefits of sparseness and explicitness outweigh any potential performance gains or loss of generality of the vectorized version Vlad proposed before the iterative improvements from the reviews. As a compromise the function is now better commented and the interface is a bit easier to use for callers as reflected in the demo.

Once this is approved I'll do a squash merge as the commit history is longer than necessary to keep going forwards.

Comment threadcherab/generomak/diagnostics/bolometers.py
Comment threaddemos/observers/bolometry/admt_tomographic_inversion.py Outdated

@skuba31skuba31 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work @jacklovell . I think that the documentation and code readability is significantly improved. The sparse support and ADMT demo are very useful additions. I have added a few minor comments for consideration before final approval.

@skuba31skuba31 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I consider this PR to be ready for merge now.

@jacklovell
jacklovell merged commit fcdeaf7 into developmentAug 20, 2026
12 checks passed
@jacklovell
jacklovell deleted the feature/admt-demo branch August 20, 2026 15:05
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@jacklovell@vsnever@skuba31
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Improve regularisation documentation and add ADMT demo - #427

Merged
jacklovell merged 24 commits into
developmentfrom
feature/admt-demo
Aug 20, 2026
Merged

Improve regularisation documentation and add ADMT demo#427
jacklovell merged 24 commits into
developmentfrom
feature/admt-demo

Conversation

@jacklovell

@jacklovelljacklovell commented Mar 11, 2024

Copy link
Copy Markdown
Member
  • Add a Regularisation section to the tomography documentation, describing the functionality inside the admt_utils module.
  • Fixup the docstrings in admt_utils.
  • Add calculation of "skewed" second derivative operators, which operate along the diagonals of the grid.
  • Add a bolometer diagonstic system to Generomak.
  • Add a new example using the Generomak bolometers and the regularisation operators to perform isotropic and ADMT inversions.
  • Add a regularised NNLS function which uses sparse matrices.
  • Enable the functions in admt_utils to optionally output sparse matrices depending on the input.

Fixes#382 and #380

* Add a Regularisation section to the tomography documentation,
describing the functionality inside the admt_utils module.
* Fixup the docstrings in admt_utils.
* Add calculation of "skewed" second derivative operators, which
operate along the diagonals of the grid.
* Add a bolometer diagonstic system to Generomak.
* Add a new example using the Generomak bolometers and the
regularisation operators to perform isotropic and ADMT inversions.

@vsnevervsnever left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @jacklovell, very valuable demo. A similar regularisation is used in ITER divertor bolometry to reconstruct the radiation power density profile. Generomak also receives the first diagnostics, which in itself is great.

I think the changelog should reflect that this demo has been added, and also that the bolometric diagnostic model has been added to Generomak.

I also have some comments and a few suggestions.

Comment threaddocs/source/tools/tomography.rst Outdated
Comment threaddemos/observers/bolometry/admt_tomographic_inversion.py
Comment threaddemos/observers/bolometry/admt_tomographic_inversion.py
Comment threadcherab/generomak/diagnostics/bolometers.py Outdated
Comment threadcherab/generomak/diagnostics/bolometers.py Outdated
Comment threadcherab/generomak/diagnostics/bolometers.py Outdated
Comment threadcherab/generomak/diagnostics/bolometers.py Outdated
Comment threadcherab/tools/inversions/admt_utils.py
Comment threaddemos/observers/bolometry/admt_tomographic_inversion.py
jacklovelland others added 6 commits May 18, 2026 09:39
* Fix the series of transforms to position and orient the bolometer
cameras.
* Update geometry parameters such that the lines of sight all follow a
consistant convention and specify the channel ordering in the
docstring. This required adding the ability to rotate the sensors
about the viewing axis to reverse the channel order of the
horizontal-poloidal camera.
* Correct the docstring of load_bolometers to specify the correct
number of 4-channel sensors in each camera.
* Expand docstrings and comments to better describe the intricacies of
setting up the bolometer geometry.
* More thorough commenting of the function to make it easier to follow
what is going on and why.
* Exploit the sparsity of the derivative opreators but using a
dictionary-of-keys representation instead of dense numpy arrays. A
dictionary is faster to insert single elements into inside the loop
than a numpy array too.
* Remove the `np.isnan` checkc which are slow for single elements,
replace with a cheap check for `None`.
* Support returning the operators as Scipy sparse arrays for use
downstream. Default to returning as Numpy arrays for backwards
compatibility.
These changes result in an order of magnitude speedup in this function.
This is done automatically if the derivative operators are
sparse. A dense operator is returned otherwise.
An alternative to `invert_regularised_nnls` using sparse weight and
penalty matrices. The numerical algorithm used is slightly different
to `scipy.optimize.nnls`, as it uses the TRF variant of a bounded
`scipy.optimize.lsq_linear` with the lower bound set to 0 to enforce
positivity. Since the results differ due to floating point precision,
the sparse variant is implemented as a separate function to maintain
backwards compatibility.
* Produce additional inversions which incorporate Generomak's
tangentially-viewing channels, for comparison with the poloidal-only
inversions.
* Correctly scale the emissivity.
* Fix removing the ray transfer grid from the world before
forward-modelling the bolometer measurements.
* Better explain why we're building the 1D <-> 2D maps by hand instead
of just using the ray transfer matrix capabilities directly: this is
for generality.
* Use the sparse variant of the NNLS inversion for speed and memory
efficiency. The grid is large enough for this to be worthwhile.
@jacklovelljacklovell changed the title WIP: Improve regularisation documentation and add ADMT demoImprove regularisation documentation and add ADMT demoJul 15, 2026
@MateasekMateasek mentioned this pull request Jul 16, 2026
12 tasks
Comment threadcherab/generomak/diagnostics/bolometers.py
Comment threadcherab/generomak/diagnostics/bolometers.py
Comment threadcherab/tools/inversions/nnls.py
This makes it easier for users to explore the geometry and potentially
even edit it for testing purposes.
This is a more common term in the literature for a bolometer unit
integrating several (typically 4) channels.
* The 1D-to-2D and 2D-to-1D maps are the inverse of one another, so
one can be computed from the other. Depending on how the end user
forms their inversion grid it may be simpler to calculate the
1D-to-2D or the 2D-to-1D, so allow the caller to pass either and
compute any missing mapping. If the caller already has both
mappings (machine packages like cherab-jet, cherab-mastu and
cherab-aug already generate both) then accept both too.
* Add tests for auto-computing missing mappings.
* Tests uncovered a bug converting the Dyy sparse operator to dense
when `sparse=False` was passed: fix that and complete test coverage
for `admt_utils`.
* Simplify the ADMT script by only computing the 1D-to-2D map as this
is fairly trivially obtained from the Ray Transfer object.
@jacklovell
jacklovell requested a review from skuba31July 31, 2026 16:19
@jacklovell

Copy link
Copy Markdown
MemberAuthor

I've implemented the changes from both reviews now: thanks to @vsnever and @skuba31. I am going to hold firm on the formulism in generate_derivative_operators though, as I think the benefits of sparseness and explicitness outweigh any potential performance gains or loss of generality of the vectorized version Vlad proposed before the iterative improvements from the reviews. As a compromise the function is now better commented and the interface is a bit easier to use for callers as reflected in the demo.

Once this is approved I'll do a squash merge as the commit history is longer than necessary to keep going forwards.

Comment threadcherab/generomak/diagnostics/bolometers.py
Comment threaddemos/observers/bolometry/admt_tomographic_inversion.py Outdated

@skuba31skuba31 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work @jacklovell . I think that the documentation and code readability is significantly improved. The sparse support and ADMT demo are very useful additions. I have added a few minor comments for consideration before final approval.

@skuba31skuba31 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I consider this PR to be ready for merge now.

@jacklovell
jacklovell merged commit fcdeaf7 into developmentAug 20, 2026
12 checks passed
@jacklovell
jacklovell deleted the feature/admt-demo branch August 20, 2026 15:05
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@jacklovell@vsnever@skuba31
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Improve regularisation documentation and add ADMT demo - #427

Merged
jacklovell merged 24 commits into
developmentfrom
feature/admt-demo
Aug 20, 2026
Merged

Improve regularisation documentation and add ADMT demo#427
jacklovell merged 24 commits into
developmentfrom
feature/admt-demo

Conversation

@jacklovell

@jacklovelljacklovell commented Mar 11, 2024

Copy link
Copy Markdown
Member
  • Add a Regularisation section to the tomography documentation, describing the functionality inside the admt_utils module.
  • Fixup the docstrings in admt_utils.
  • Add calculation of "skewed" second derivative operators, which operate along the diagonals of the grid.
  • Add a bolometer diagonstic system to Generomak.
  • Add a new example using the Generomak bolometers and the regularisation operators to perform isotropic and ADMT inversions.
  • Add a regularised NNLS function which uses sparse matrices.
  • Enable the functions in admt_utils to optionally output sparse matrices depending on the input.

Fixes#382 and #380

* Add a Regularisation section to the tomography documentation,
describing the functionality inside the admt_utils module.
* Fixup the docstrings in admt_utils.
* Add calculation of "skewed" second derivative operators, which
operate along the diagonals of the grid.
* Add a bolometer diagonstic system to Generomak.
* Add a new example using the Generomak bolometers and the
regularisation operators to perform isotropic and ADMT inversions.

@vsnevervsnever left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @jacklovell, very valuable demo. A similar regularisation is used in ITER divertor bolometry to reconstruct the radiation power density profile. Generomak also receives the first diagnostics, which in itself is great.

I think the changelog should reflect that this demo has been added, and also that the bolometric diagnostic model has been added to Generomak.

I also have some comments and a few suggestions.

Comment threaddocs/source/tools/tomography.rst Outdated
Comment threaddemos/observers/bolometry/admt_tomographic_inversion.py
Comment threaddemos/observers/bolometry/admt_tomographic_inversion.py
Comment threadcherab/generomak/diagnostics/bolometers.py Outdated
Comment threadcherab/generomak/diagnostics/bolometers.py Outdated
Comment threadcherab/generomak/diagnostics/bolometers.py Outdated
Comment threadcherab/generomak/diagnostics/bolometers.py Outdated
Comment threadcherab/tools/inversions/admt_utils.py
Comment threaddemos/observers/bolometry/admt_tomographic_inversion.py
jacklovelland others added 6 commits May 18, 2026 09:39
* Fix the series of transforms to position and orient the bolometer
cameras.
* Update geometry parameters such that the lines of sight all follow a
consistant convention and specify the channel ordering in the
docstring. This required adding the ability to rotate the sensors
about the viewing axis to reverse the channel order of the
horizontal-poloidal camera.
* Correct the docstring of load_bolometers to specify the correct
number of 4-channel sensors in each camera.
* Expand docstrings and comments to better describe the intricacies of
setting up the bolometer geometry.
* More thorough commenting of the function to make it easier to follow
what is going on and why.
* Exploit the sparsity of the derivative opreators but using a
dictionary-of-keys representation instead of dense numpy arrays. A
dictionary is faster to insert single elements into inside the loop
than a numpy array too.
* Remove the `np.isnan` checkc which are slow for single elements,
replace with a cheap check for `None`.
* Support returning the operators as Scipy sparse arrays for use
downstream. Default to returning as Numpy arrays for backwards
compatibility.
These changes result in an order of magnitude speedup in this function.
This is done automatically if the derivative operators are
sparse. A dense operator is returned otherwise.
An alternative to `invert_regularised_nnls` using sparse weight and
penalty matrices. The numerical algorithm used is slightly different
to `scipy.optimize.nnls`, as it uses the TRF variant of a bounded
`scipy.optimize.lsq_linear` with the lower bound set to 0 to enforce
positivity. Since the results differ due to floating point precision,
the sparse variant is implemented as a separate function to maintain
backwards compatibility.
* Produce additional inversions which incorporate Generomak's
tangentially-viewing channels, for comparison with the poloidal-only
inversions.
* Correctly scale the emissivity.
* Fix removing the ray transfer grid from the world before
forward-modelling the bolometer measurements.
* Better explain why we're building the 1D <-> 2D maps by hand instead
of just using the ray transfer matrix capabilities directly: this is
for generality.
* Use the sparse variant of the NNLS inversion for speed and memory
efficiency. The grid is large enough for this to be worthwhile.
@jacklovelljacklovell changed the title WIP: Improve regularisation documentation and add ADMT demoImprove regularisation documentation and add ADMT demoJul 15, 2026
@MateasekMateasek mentioned this pull request Jul 16, 2026
12 tasks
Comment threadcherab/generomak/diagnostics/bolometers.py
Comment threadcherab/generomak/diagnostics/bolometers.py
Comment threadcherab/tools/inversions/nnls.py
This makes it easier for users to explore the geometry and potentially
even edit it for testing purposes.
This is a more common term in the literature for a bolometer unit
integrating several (typically 4) channels.
* The 1D-to-2D and 2D-to-1D maps are the inverse of one another, so
one can be computed from the other. Depending on how the end user
forms their inversion grid it may be simpler to calculate the
1D-to-2D or the 2D-to-1D, so allow the caller to pass either and
compute any missing mapping. If the caller already has both
mappings (machine packages like cherab-jet, cherab-mastu and
cherab-aug already generate both) then accept both too.
* Add tests for auto-computing missing mappings.
* Tests uncovered a bug converting the Dyy sparse operator to dense
when `sparse=False` was passed: fix that and complete test coverage
for `admt_utils`.
* Simplify the ADMT script by only computing the 1D-to-2D map as this
is fairly trivially obtained from the Ray Transfer object.
@jacklovell
jacklovell requested a review from skuba31July 31, 2026 16:19
@jacklovell

Copy link
Copy Markdown
MemberAuthor

I've implemented the changes from both reviews now: thanks to @vsnever and @skuba31. I am going to hold firm on the formulism in generate_derivative_operators though, as I think the benefits of sparseness and explicitness outweigh any potential performance gains or loss of generality of the vectorized version Vlad proposed before the iterative improvements from the reviews. As a compromise the function is now better commented and the interface is a bit easier to use for callers as reflected in the demo.

Once this is approved I'll do a squash merge as the commit history is longer than necessary to keep going forwards.

Comment threadcherab/generomak/diagnostics/bolometers.py
Comment threaddemos/observers/bolometry/admt_tomographic_inversion.py Outdated

@skuba31skuba31 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work @jacklovell . I think that the documentation and code readability is significantly improved. The sparse support and ADMT demo are very useful additions. I have added a few minor comments for consideration before final approval.

@skuba31skuba31 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I consider this PR to be ready for merge now.

@jacklovell
jacklovell merged commit fcdeaf7 into developmentAug 20, 2026
12 checks passed
@jacklovell
jacklovell deleted the feature/admt-demo branch August 20, 2026 15:05
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@jacklovell@vsnever@skuba31
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Improve regularisation documentation and add ADMT demo - #427

Merged
jacklovell merged 24 commits into
developmentfrom
feature/admt-demo
Aug 20, 2026
Merged

Improve regularisation documentation and add ADMT demo#427
jacklovell merged 24 commits into
developmentfrom
feature/admt-demo

Conversation

@jacklovell

@jacklovelljacklovell commented Mar 11, 2024

Copy link
Copy Markdown
Member
  • Add a Regularisation section to the tomography documentation, describing the functionality inside the admt_utils module.
  • Fixup the docstrings in admt_utils.
  • Add calculation of "skewed" second derivative operators, which operate along the diagonals of the grid.
  • Add a bolometer diagonstic system to Generomak.
  • Add a new example using the Generomak bolometers and the regularisation operators to perform isotropic and ADMT inversions.
  • Add a regularised NNLS function which uses sparse matrices.
  • Enable the functions in admt_utils to optionally output sparse matrices depending on the input.

Fixes#382 and #380

* Add a Regularisation section to the tomography documentation,
describing the functionality inside the admt_utils module.
* Fixup the docstrings in admt_utils.
* Add calculation of "skewed" second derivative operators, which
operate along the diagonals of the grid.
* Add a bolometer diagonstic system to Generomak.
* Add a new example using the Generomak bolometers and the
regularisation operators to perform isotropic and ADMT inversions.

@vsnevervsnever left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @jacklovell, very valuable demo. A similar regularisation is used in ITER divertor bolometry to reconstruct the radiation power density profile. Generomak also receives the first diagnostics, which in itself is great.

I think the changelog should reflect that this demo has been added, and also that the bolometric diagnostic model has been added to Generomak.

I also have some comments and a few suggestions.

Comment threaddocs/source/tools/tomography.rst Outdated
Comment threaddemos/observers/bolometry/admt_tomographic_inversion.py
Comment threaddemos/observers/bolometry/admt_tomographic_inversion.py
Comment threadcherab/generomak/diagnostics/bolometers.py Outdated
Comment threadcherab/generomak/diagnostics/bolometers.py Outdated
Comment threadcherab/generomak/diagnostics/bolometers.py Outdated
Comment threadcherab/generomak/diagnostics/bolometers.py Outdated
Comment threadcherab/tools/inversions/admt_utils.py
Comment threaddemos/observers/bolometry/admt_tomographic_inversion.py
jacklovelland others added 6 commits May 18, 2026 09:39
* Fix the series of transforms to position and orient the bolometer
cameras.
* Update geometry parameters such that the lines of sight all follow a
consistant convention and specify the channel ordering in the
docstring. This required adding the ability to rotate the sensors
about the viewing axis to reverse the channel order of the
horizontal-poloidal camera.
* Correct the docstring of load_bolometers to specify the correct
number of 4-channel sensors in each camera.
* Expand docstrings and comments to better describe the intricacies of
setting up the bolometer geometry.
* More thorough commenting of the function to make it easier to follow
what is going on and why.
* Exploit the sparsity of the derivative opreators but using a
dictionary-of-keys representation instead of dense numpy arrays. A
dictionary is faster to insert single elements into inside the loop
than a numpy array too.
* Remove the `np.isnan` checkc which are slow for single elements,
replace with a cheap check for `None`.
* Support returning the operators as Scipy sparse arrays for use
downstream. Default to returning as Numpy arrays for backwards
compatibility.
These changes result in an order of magnitude speedup in this function.
This is done automatically if the derivative operators are
sparse. A dense operator is returned otherwise.
An alternative to `invert_regularised_nnls` using sparse weight and
penalty matrices. The numerical algorithm used is slightly different
to `scipy.optimize.nnls`, as it uses the TRF variant of a bounded
`scipy.optimize.lsq_linear` with the lower bound set to 0 to enforce
positivity. Since the results differ due to floating point precision,
the sparse variant is implemented as a separate function to maintain
backwards compatibility.
* Produce additional inversions which incorporate Generomak's
tangentially-viewing channels, for comparison with the poloidal-only
inversions.
* Correctly scale the emissivity.
* Fix removing the ray transfer grid from the world before
forward-modelling the bolometer measurements.
* Better explain why we're building the 1D <-> 2D maps by hand instead
of just using the ray transfer matrix capabilities directly: this is
for generality.
* Use the sparse variant of the NNLS inversion for speed and memory
efficiency. The grid is large enough for this to be worthwhile.
@jacklovelljacklovell changed the title WIP: Improve regularisation documentation and add ADMT demoImprove regularisation documentation and add ADMT demoJul 15, 2026
@MateasekMateasek mentioned this pull request Jul 16, 2026
12 tasks
Comment threadcherab/generomak/diagnostics/bolometers.py
Comment threadcherab/generomak/diagnostics/bolometers.py
Comment threadcherab/tools/inversions/nnls.py
This makes it easier for users to explore the geometry and potentially
even edit it for testing purposes.
This is a more common term in the literature for a bolometer unit
integrating several (typically 4) channels.
* The 1D-to-2D and 2D-to-1D maps are the inverse of one another, so
one can be computed from the other. Depending on how the end user
forms their inversion grid it may be simpler to calculate the
1D-to-2D or the 2D-to-1D, so allow the caller to pass either and
compute any missing mapping. If the caller already has both
mappings (machine packages like cherab-jet, cherab-mastu and
cherab-aug already generate both) then accept both too.
* Add tests for auto-computing missing mappings.
* Tests uncovered a bug converting the Dyy sparse operator to dense
when `sparse=False` was passed: fix that and complete test coverage
for `admt_utils`.
* Simplify the ADMT script by only computing the 1D-to-2D map as this
is fairly trivially obtained from the Ray Transfer object.
@jacklovell
jacklovell requested a review from skuba31July 31, 2026 16:19
@jacklovell

Copy link
Copy Markdown
MemberAuthor

I've implemented the changes from both reviews now: thanks to @vsnever and @skuba31. I am going to hold firm on the formulism in generate_derivative_operators though, as I think the benefits of sparseness and explicitness outweigh any potential performance gains or loss of generality of the vectorized version Vlad proposed before the iterative improvements from the reviews. As a compromise the function is now better commented and the interface is a bit easier to use for callers as reflected in the demo.

Once this is approved I'll do a squash merge as the commit history is longer than necessary to keep going forwards.

Comment threadcherab/generomak/diagnostics/bolometers.py
Comment threaddemos/observers/bolometry/admt_tomographic_inversion.py Outdated

@skuba31skuba31 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work @jacklovell . I think that the documentation and code readability is significantly improved. The sparse support and ADMT demo are very useful additions. I have added a few minor comments for consideration before final approval.

@skuba31skuba31 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I consider this PR to be ready for merge now.

@jacklovell
jacklovell merged commit fcdeaf7 into developmentAug 20, 2026
12 checks passed
@jacklovell
jacklovell deleted the feature/admt-demo branch August 20, 2026 15:05
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@jacklovell@vsnever@skuba31
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Improve regularisation documentation and add ADMT demo - #427

Merged
jacklovell merged 24 commits into
developmentfrom
feature/admt-demo
Aug 20, 2026
Merged

Improve regularisation documentation and add ADMT demo#427
jacklovell merged 24 commits into
developmentfrom
feature/admt-demo

Conversation

@jacklovell

@jacklovelljacklovell commented Mar 11, 2024

Copy link
Copy Markdown
Member
  • Add a Regularisation section to the tomography documentation, describing the functionality inside the admt_utils module.
  • Fixup the docstrings in admt_utils.
  • Add calculation of "skewed" second derivative operators, which operate along the diagonals of the grid.
  • Add a bolometer diagonstic system to Generomak.
  • Add a new example using the Generomak bolometers and the regularisation operators to perform isotropic and ADMT inversions.
  • Add a regularised NNLS function which uses sparse matrices.
  • Enable the functions in admt_utils to optionally output sparse matrices depending on the input.

Fixes#382 and #380

* Add a Regularisation section to the tomography documentation,
describing the functionality inside the admt_utils module.
* Fixup the docstrings in admt_utils.
* Add calculation of "skewed" second derivative operators, which
operate along the diagonals of the grid.
* Add a bolometer diagonstic system to Generomak.
* Add a new example using the Generomak bolometers and the
regularisation operators to perform isotropic and ADMT inversions.

@vsnevervsnever left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @jacklovell, very valuable demo. A similar regularisation is used in ITER divertor bolometry to reconstruct the radiation power density profile. Generomak also receives the first diagnostics, which in itself is great.

I think the changelog should reflect that this demo has been added, and also that the bolometric diagnostic model has been added to Generomak.

I also have some comments and a few suggestions.

Comment threaddocs/source/tools/tomography.rst Outdated
Comment threaddemos/observers/bolometry/admt_tomographic_inversion.py
Comment threaddemos/observers/bolometry/admt_tomographic_inversion.py
Comment threadcherab/generomak/diagnostics/bolometers.py Outdated
Comment threadcherab/generomak/diagnostics/bolometers.py Outdated
Comment threadcherab/generomak/diagnostics/bolometers.py Outdated
Comment threadcherab/generomak/diagnostics/bolometers.py Outdated
Comment threadcherab/tools/inversions/admt_utils.py
Comment threaddemos/observers/bolometry/admt_tomographic_inversion.py
jacklovelland others added 6 commits May 18, 2026 09:39
* Fix the series of transforms to position and orient the bolometer
cameras.
* Update geometry parameters such that the lines of sight all follow a
consistant convention and specify the channel ordering in the
docstring. This required adding the ability to rotate the sensors
about the viewing axis to reverse the channel order of the
horizontal-poloidal camera.
* Correct the docstring of load_bolometers to specify the correct
number of 4-channel sensors in each camera.
* Expand docstrings and comments to better describe the intricacies of
setting up the bolometer geometry.
* More thorough commenting of the function to make it easier to follow
what is going on and why.
* Exploit the sparsity of the derivative opreators but using a
dictionary-of-keys representation instead of dense numpy arrays. A
dictionary is faster to insert single elements into inside the loop
than a numpy array too.
* Remove the `np.isnan` checkc which are slow for single elements,
replace with a cheap check for `None`.
* Support returning the operators as Scipy sparse arrays for use
downstream. Default to returning as Numpy arrays for backwards
compatibility.
These changes result in an order of magnitude speedup in this function.
This is done automatically if the derivative operators are
sparse. A dense operator is returned otherwise.
An alternative to `invert_regularised_nnls` using sparse weight and
penalty matrices. The numerical algorithm used is slightly different
to `scipy.optimize.nnls`, as it uses the TRF variant of a bounded
`scipy.optimize.lsq_linear` with the lower bound set to 0 to enforce
positivity. Since the results differ due to floating point precision,
the sparse variant is implemented as a separate function to maintain
backwards compatibility.
* Produce additional inversions which incorporate Generomak's
tangentially-viewing channels, for comparison with the poloidal-only
inversions.
* Correctly scale the emissivity.
* Fix removing the ray transfer grid from the world before
forward-modelling the bolometer measurements.
* Better explain why we're building the 1D <-> 2D maps by hand instead
of just using the ray transfer matrix capabilities directly: this is
for generality.
* Use the sparse variant of the NNLS inversion for speed and memory
efficiency. The grid is large enough for this to be worthwhile.
@jacklovelljacklovell changed the title WIP: Improve regularisation documentation and add ADMT demoImprove regularisation documentation and add ADMT demoJul 15, 2026
@MateasekMateasek mentioned this pull request Jul 16, 2026
12 tasks
Comment threadcherab/generomak/diagnostics/bolometers.py
Comment threadcherab/generomak/diagnostics/bolometers.py
Comment threadcherab/tools/inversions/nnls.py
This makes it easier for users to explore the geometry and potentially
even edit it for testing purposes.
This is a more common term in the literature for a bolometer unit
integrating several (typically 4) channels.
* The 1D-to-2D and 2D-to-1D maps are the inverse of one another, so
one can be computed from the other. Depending on how the end user
forms their inversion grid it may be simpler to calculate the
1D-to-2D or the 2D-to-1D, so allow the caller to pass either and
compute any missing mapping. If the caller already has both
mappings (machine packages like cherab-jet, cherab-mastu and
cherab-aug already generate both) then accept both too.
* Add tests for auto-computing missing mappings.
* Tests uncovered a bug converting the Dyy sparse operator to dense
when `sparse=False` was passed: fix that and complete test coverage
for `admt_utils`.
* Simplify the ADMT script by only computing the 1D-to-2D map as this
is fairly trivially obtained from the Ray Transfer object.
@jacklovell
jacklovell requested a review from skuba31July 31, 2026 16:19
@jacklovell

Copy link
Copy Markdown
MemberAuthor

I've implemented the changes from both reviews now: thanks to @vsnever and @skuba31. I am going to hold firm on the formulism in generate_derivative_operators though, as I think the benefits of sparseness and explicitness outweigh any potential performance gains or loss of generality of the vectorized version Vlad proposed before the iterative improvements from the reviews. As a compromise the function is now better commented and the interface is a bit easier to use for callers as reflected in the demo.

Once this is approved I'll do a squash merge as the commit history is longer than necessary to keep going forwards.

Comment threadcherab/generomak/diagnostics/bolometers.py
Comment threaddemos/observers/bolometry/admt_tomographic_inversion.py Outdated

@skuba31skuba31 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work @jacklovell . I think that the documentation and code readability is significantly improved. The sparse support and ADMT demo are very useful additions. I have added a few minor comments for consideration before final approval.

@skuba31skuba31 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I consider this PR to be ready for merge now.

@jacklovell
jacklovell merged commit fcdeaf7 into developmentAug 20, 2026
12 checks passed
@jacklovell
jacklovell deleted the feature/admt-demo branch August 20, 2026 15:05
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@jacklovell@vsnever@skuba31
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Improve regularisation documentation and add ADMT demo - #427

Merged
jacklovell merged 24 commits into
developmentfrom
feature/admt-demo
Aug 20, 2026
Merged

Improve regularisation documentation and add ADMT demo#427
jacklovell merged 24 commits into
developmentfrom
feature/admt-demo

Conversation

@jacklovell

@jacklovelljacklovell commented Mar 11, 2024

Copy link
Copy Markdown
Member
  • Add a Regularisation section to the tomography documentation, describing the functionality inside the admt_utils module.
  • Fixup the docstrings in admt_utils.
  • Add calculation of "skewed" second derivative operators, which operate along the diagonals of the grid.
  • Add a bolometer diagonstic system to Generomak.
  • Add a new example using the Generomak bolometers and the regularisation operators to perform isotropic and ADMT inversions.
  • Add a regularised NNLS function which uses sparse matrices.
  • Enable the functions in admt_utils to optionally output sparse matrices depending on the input.

Fixes#382 and #380

* Add a Regularisation section to the tomography documentation,
describing the functionality inside the admt_utils module.
* Fixup the docstrings in admt_utils.
* Add calculation of "skewed" second derivative operators, which
operate along the diagonals of the grid.
* Add a bolometer diagonstic system to Generomak.
* Add a new example using the Generomak bolometers and the
regularisation operators to perform isotropic and ADMT inversions.

@vsnevervsnever left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @jacklovell, very valuable demo. A similar regularisation is used in ITER divertor bolometry to reconstruct the radiation power density profile. Generomak also receives the first diagnostics, which in itself is great.

I think the changelog should reflect that this demo has been added, and also that the bolometric diagnostic model has been added to Generomak.

I also have some comments and a few suggestions.

Comment threaddocs/source/tools/tomography.rst Outdated
Comment threaddemos/observers/bolometry/admt_tomographic_inversion.py
Comment threaddemos/observers/bolometry/admt_tomographic_inversion.py
Comment threadcherab/generomak/diagnostics/bolometers.py Outdated
Comment threadcherab/generomak/diagnostics/bolometers.py Outdated
Comment threadcherab/generomak/diagnostics/bolometers.py Outdated
Comment threadcherab/generomak/diagnostics/bolometers.py Outdated
Comment threadcherab/tools/inversions/admt_utils.py
Comment threaddemos/observers/bolometry/admt_tomographic_inversion.py
jacklovelland others added 6 commits May 18, 2026 09:39
* Fix the series of transforms to position and orient the bolometer
cameras.
* Update geometry parameters such that the lines of sight all follow a
consistant convention and specify the channel ordering in the
docstring. This required adding the ability to rotate the sensors
about the viewing axis to reverse the channel order of the
horizontal-poloidal camera.
* Correct the docstring of load_bolometers to specify the correct
number of 4-channel sensors in each camera.
* Expand docstrings and comments to better describe the intricacies of
setting up the bolometer geometry.
* More thorough commenting of the function to make it easier to follow
what is going on and why.
* Exploit the sparsity of the derivative opreators but using a
dictionary-of-keys representation instead of dense numpy arrays. A
dictionary is faster to insert single elements into inside the loop
than a numpy array too.
* Remove the `np.isnan` checkc which are slow for single elements,
replace with a cheap check for `None`.
* Support returning the operators as Scipy sparse arrays for use
downstream. Default to returning as Numpy arrays for backwards
compatibility.
These changes result in an order of magnitude speedup in this function.
This is done automatically if the derivative operators are
sparse. A dense operator is returned otherwise.
An alternative to `invert_regularised_nnls` using sparse weight and
penalty matrices. The numerical algorithm used is slightly different
to `scipy.optimize.nnls`, as it uses the TRF variant of a bounded
`scipy.optimize.lsq_linear` with the lower bound set to 0 to enforce
positivity. Since the results differ due to floating point precision,
the sparse variant is implemented as a separate function to maintain
backwards compatibility.
* Produce additional inversions which incorporate Generomak's
tangentially-viewing channels, for comparison with the poloidal-only
inversions.
* Correctly scale the emissivity.
* Fix removing the ray transfer grid from the world before
forward-modelling the bolometer measurements.
* Better explain why we're building the 1D <-> 2D maps by hand instead
of just using the ray transfer matrix capabilities directly: this is
for generality.
* Use the sparse variant of the NNLS inversion for speed and memory
efficiency. The grid is large enough for this to be worthwhile.
@jacklovelljacklovell changed the title WIP: Improve regularisation documentation and add ADMT demoImprove regularisation documentation and add ADMT demoJul 15, 2026
@MateasekMateasek mentioned this pull request Jul 16, 2026
12 tasks
Comment threadcherab/generomak/diagnostics/bolometers.py
Comment threadcherab/generomak/diagnostics/bolometers.py
Comment threadcherab/tools/inversions/nnls.py
This makes it easier for users to explore the geometry and potentially
even edit it for testing purposes.
This is a more common term in the literature for a bolometer unit
integrating several (typically 4) channels.
* The 1D-to-2D and 2D-to-1D maps are the inverse of one another, so
one can be computed from the other. Depending on how the end user
forms their inversion grid it may be simpler to calculate the
1D-to-2D or the 2D-to-1D, so allow the caller to pass either and
compute any missing mapping. If the caller already has both
mappings (machine packages like cherab-jet, cherab-mastu and
cherab-aug already generate both) then accept both too.
* Add tests for auto-computing missing mappings.
* Tests uncovered a bug converting the Dyy sparse operator to dense
when `sparse=False` was passed: fix that and complete test coverage
for `admt_utils`.
* Simplify the ADMT script by only computing the 1D-to-2D map as this
is fairly trivially obtained from the Ray Transfer object.
@jacklovell
jacklovell requested a review from skuba31July 31, 2026 16:19
@jacklovell

Copy link
Copy Markdown
MemberAuthor

I've implemented the changes from both reviews now: thanks to @vsnever and @skuba31. I am going to hold firm on the formulism in generate_derivative_operators though, as I think the benefits of sparseness and explicitness outweigh any potential performance gains or loss of generality of the vectorized version Vlad proposed before the iterative improvements from the reviews. As a compromise the function is now better commented and the interface is a bit easier to use for callers as reflected in the demo.

Once this is approved I'll do a squash merge as the commit history is longer than necessary to keep going forwards.

Comment threadcherab/generomak/diagnostics/bolometers.py
Comment threaddemos/observers/bolometry/admt_tomographic_inversion.py Outdated

@skuba31skuba31 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work @jacklovell . I think that the documentation and code readability is significantly improved. The sparse support and ADMT demo are very useful additions. I have added a few minor comments for consideration before final approval.

@skuba31skuba31 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I consider this PR to be ready for merge now.

@jacklovell
jacklovell merged commit fcdeaf7 into developmentAug 20, 2026
12 checks passed
@jacklovell
jacklovell deleted the feature/admt-demo branch August 20, 2026 15:05
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@jacklovell@vsnever@skuba31