Shared parseCommonInputs utility -- scoped proof-of-concept for #378 - #772
Open
aaravkharwar-hub wants to merge 4 commits into
Open
aaravkharwar-hub wants to merge 4 commits into
aaravkharwar-hub wants to merge 4 commits into
Conversation
This function parses common input options for TIGRE algorithms, handling initialization, verbosity, quality measures, GPU IDs, and ground truth parameters.
Common options (init/initimg, verbose, qualmeas, gpuids, groundtruth) now come from parseCommonInputs; CGLS's own parse_inputs only handles 'restart'. Verified against the original implementation with a side-by-side equivalence test (12 cases including error paths) before pushing.
init_multigrid is a local (file-private) function duplicated inside SART/SIRT/OSEM/etc, not a shared utility -- so parseCommonInputs calling it directly would break algorithms whose own local copy isn't visible from this file. This lets each algorithm pass a handle to its own local init_multigrid, defaulting to a bare @init_multigrid for algorithms (like CGLS) that don't have one, preserving each algorithm's existing behavior exactly. Verified the handle correctly resolves to the caller's local function vs. a decoy global one before pushing.
Common options now come from parseCommonInputs; SIRT's own parse_inputs only handles lambda/lambda_red/nonneg/redundancy_weighting. Passes SIRT's own local init_multigrid as a handle (@init_multigrid) since that function is file-private, not a shared utility -- important so 'init','multigrid' keeps working exactly as before. Verified via a side-by-side equivalence test (14 cases including error paths) plus a targeted test confirming the handle resolves to SIRT's own local function rather than any other init_multigrid.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Addresses #378 -- but scoped intentionally, and I'd like your input on direction before going further.
What this is
parse_inputs()is duplicated across all 26 algorithm files, and most of that duplication is identical:init/initimg,verbose,qualmeas,gpuids,groundtruth. This PR extracts that shared portion intoMATLAB/Utilities/parseCommonInputs.m, and migrates two algorithms (CGLS and SIRT) as a proof of concept, rather than attempting all 26 at once.Each migrated algorithm's own
parse_inputsnow just callsparseCommonInputsfor the common options, then parses its own remaining algorithm-specific options (e.g. CGLS'srestart; SIRT'slambda,lambda_red,nonneg,redundancy_weighting) from the leftover argument list, exactly as before.Why only 2 algorithms, not all 26
This touches option-parsing for real reconstruction algorithms that people run on real scan data, so I didn't want to blind-rewrite all 26 in one pass without your sign-off on the approach. A few things came up even in just these two that I think are worth your eyes before scaling this up:
ind=double.empty(0,1)(present in every algorithm's parse_inputs) relies on MATLAB's classdef static-method syntax and isn't portable (fails under GNU Octave, for instance). Replaced withind=[]-- identical behavior, more portable. I did NOT change this in the other 24 files, only the 2 migrated here.init_multigridis not a shared utility -- it's duplicated as a local (file-private) function inside several algorithms (SART, SIRT, OSEM, OS_SART, SART_TV), each only visible within its own file. A shared parser callinginit_multigrid(...)directly would silently break any algorithm whose own copy isn't globally visible.parseCommonInputstakes an optional function handle for this (multigridFn) so each algorithm can pass its own local implementation; SIRT does this (@init_multigrid, created inside SIRT.m so it correctly captures SIRT's own local function). CGLS doesn't have its owninit_multigridat all today (calling'Init','multigrid'on CGLS already errors with "undefined function" before this PR) -- that's a pre-existing gap, unrelated to this refactor, and I've left it alone.'init','image'is passed without'initimg', every existing algorithm silently leaves the result empty rather than erroring. I kept this exact behavior inparseCommonInputsrather than "fixing" it, since this PR is meant to be structural only. Flagging it here in case it's worth its own issue.Testing
I don't have a MATLAB license in my environment, so I used GNU Octave to actually execute the code rather than just writing it and hoping:
parseCommonInputsdirectly (defaults, every option, error paths, the preserved quirks above).parse_inputsfor both CGLS and SIRT against 12-14 cases each and diffed every output field -- all matched, including error identifiers.multigridFnhandle actually resolves to the caller's own local function and not some otherinit_multigrid, using a deliberately "wrong" decoy to make sure.I have not been able to verify against real MATLAB specifically, only Octave -- flagging that as a limitation.
If this approach looks right to you, I'm happy to continue migrating the remaining 24 algorithms in follow-up PRs. If you'd rather see a different shape (e.g. a struct-based options object instead of a leftover-args split, or algorithm name dispatch as you originally suggested), let me know before I put more algorithms through this pattern.