Skip to content

Add Photocurrent Mapping Reconstruction#165

Merged
AnderBiguri merged 19 commits into
CambridgeCIA:mainfrom
trung-vt:general_op_and_pcm
Dec 10, 2025
Merged

Add Photocurrent Mapping Reconstruction#165
AnderBiguri merged 19 commits into
CambridgeCIA:mainfrom
trung-vt:general_op_and_pcm

Conversation

@trung-vt

@trung-vt trung-vt commented Nov 26, 2025

Copy link
Copy Markdown
Contributor

Main changes:

  • Add general Operator class to support new operators. This is mainly to create a common interface for all algorithms which expect a forward operation and a adjoint operation.
  • Update make_operator to return a TomographicProjOp which is a wrapper around tomosipo Operator). Ensure backward compatibility and autograd functionality so that all current code using make_operator still works.
  • Add PhotocurrentMapOp for photocurrent mapping (PCM) and other operators
  • Add example baseline compressed-sensing (CS) reconstruction for PCM using SPGL1 (basis pursuit) or FISTA (L1 minimisation) with Daubechies 4 (DB4) wavelet transform
  • Add example PnP-ADMM reconstruction for PCM
  • Phase out Numpy support and focus on PyTorch: make power_method work with tensor instead of ndarray, assume TomographicProjOp also only works with tensor

Other important changes:

  • Add support for torch tensors in JSON encoder for persisting LIONParameter: convert list of angles stored in tensor to python list
  • Unit tests for the operators, mainly focusing on checking adjointness, autograd functionality, and backward compatibility for tomosipo
  • Unit tests for power method
  • Unit/Smoke tests for FISTA, SPGL1
  • Update pyproject.toml: Add dependencies for wavelet transform, ignore some import warnings so that tests can run, ...
  • Update installation instructions for README.md (TODO: Rename env_base.yml to env.yml and place the old one in misc)

Minor changes:

  • Refactoring: Add from __future__ import annotations to enable safe usage of | in function signatures, reorder imports for consistency, switch from np.product to np.prod, ...
  • Documentation: Add badge to note PyTorch support and black code style to RAEDME.md, remove trailing whitespaces, add description for new operators, ...

Notes:

  • scripts/example_scripts/LPD.py ran without issues

Future improvements:

  • Update README files (2 of them?): LION now supports any operator
  • Currently FISTA and SPGL1 are using PyWavelets and spgl1 which use numpy backend. Implement PyTorch versions.
  • Add running pytest to Github action and set it to manual so that reviewers can choose to run them just before merging to save Github compute allowance. Only allow tests to run on CPU on Github.
  • Check coverage for LION.operators (no need to check for all correctness, just test execute (cover) every line)
  • readthedocs: https://example-lion-docs-1.netlify.app/

return torch.sign(v) * torch.clamp(torch.abs(v) - tau, min=0.0)


def estimate_lipschitz(

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.

This already exists :)

from LION.utils.math import power_method

@trung-vt trung-vt Nov 26, 2025

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thank you for pointing that out! I can see that LION.utils.math.power_method is using numpy. Is it ok to edit it to use torch.Tensor instead? If it breaks some existing code maybe we can add a separate power_method_torch?

An alternative would be to convert from torch.Tensor to/from np.ndarray before/after the call, either inside or outside the function.

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.

Agree, maybe worth making the already existing one take either torch or numpy? flexible to both?

@trung-vt trung-vt Nov 27, 2025

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Great idea! This might not be a problem right now but just in case there's some special kind of experiment where this function is called multiple times, I think it would be nice to also have a sub-function that just inputs tensors, computes on tensors, and returns tensors without ever leaving the GPU and making extra if checks. We can then wrap both numpy and torch versions together, perhaps have a power_method_np and power_method_torch, and then have a common power_method that does a check and choose the appropriate backend? This way we can be flexible: power_method for quick prototyping, and power_method_torch for training/GPU-only processing where performance is more critical? There may be a bit of code duplication in the two sub-functions but it might be worth the compromise, perhaps we might even find that one backend benefits more from a slightly different implementation than the other's, in which case it would be easier if they were already in separate places 😄

I'd also like to add unit tests for the power method where we have analytically computed values that we can check against, would appreciate any suggestions!

@trung-vt trung-vt Nov 27, 2025

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Also a general direction question: for all operators, should we aim for supporting both np.ndarray and torch.Tensor like Tomosipo? Personally I think it's much simpler to focus on torch.Tensor (Tomosipo can remain a special case but we could encourage users to use Pytorch anyway) since, if I understand correctly, we mainly provide tools for training models. Adding numpy support for everything might make code more complicated and brittle since numpy and Pytorch don't always have the same API (e.g. numpy uses .ndim while Pytorch uses .dim())

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.

Sounds good! but in any case, a type check in an if condition should be computationally free, so that should not be an issue. But your solution sounds great. For the unit test, that is hard to do without an explicit matrix where we can compute the biggest eigenvalue. The method itself should converge, maybe that is what we can do as unit test, but I think this is more a thing to use in the opposite way: use power method as unit test for operators not changing.

for operators: agree. We can just support Torch for sure, and numpy optional. Specific operators can chose to support it or error otherwise (we can have an overridable method that errors by default, or something like that).

@trung-vt trung-vt force-pushed the general_op_and_pcm branch 3 times, most recently from c138322 to 5e284e0 Compare November 27, 2025 21:21
@trung-vt trung-vt marked this pull request as ready for review November 29, 2025 21:49
@AnderBiguri

Copy link
Copy Markdown
Member

Can we change TomopgarphicProjOP to CTOP or something like that? tomography is quite wider than the Radon transform, and even within Radon there is much more geometries than CT, so this uniquely for CT.

@AnderBiguri

AnderBiguri commented Dec 4, 2025

Copy link
Copy Markdown
Member

Also, lets put iphython notebooks in a separate folder, I prefer example scripts to be purely python for now
(or, if its the same code, maybe we can keep them out for now? to minimize maintenance)

@AnderBiguri

Copy link
Copy Markdown
Member

great! should I merge?

@trung-vt

Copy link
Copy Markdown
Contributor Author

Yes, I believe it's ok for this PR now! I made some further small changes:

  • rename spgl1 to spgl1_torch to avoid potential naming clashes
  • remove plt.show() to make sure scripts don't show interactive windows
  • update documentation to the new CTProjectionOp name
  • small refactoring

@AnderBiguri AnderBiguri merged commit 85030c3 into CambridgeCIA:main Dec 10, 2025
1 check passed
keerfish pushed a commit to keerfish/LION that referenced this pull request Jan 12, 2026
Sign up for free to 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.

2 participants