Skip to content

Simplify profitLikeModel using ParmOff for argument matching, interval clamping, and log-unlogging#17

Merged
asgr merged 10 commits into
masterfrom
copilot/simplify-profit-like-model
May 26, 2026
Merged

Simplify profitLikeModel using ParmOff for argument matching, interval clamping, and log-unlogging#17
asgr merged 10 commits into
masterfrom
copilot/simplify-profit-like-model

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented May 13, 2026

Summary

Refactors profitLikeModel.R to use the ParmOff package for function argument matching, eliminating manual arg filtering, suffix stripping, interval clamping, log-unlogging, and do.call boilerplate.

Changes

DESCRIPTION / NAMESPACE

  • Added ParmOff to Imports (required at load time since it's used in the core evaluation path)
  • Added asgr/ParmOff to Remotes
  • Added importFrom("ParmOff", "ParmOff") to NAMESPACE

.profitLikeModelEvaluation — merged duplicate profitMakeModel calls

The old code had two near-identical profitMakeModel calls (one with calcregion/docalcregion, one without), branched on Data$usecalcregion. Replaced with a single ParmOff(profitMakeModel, .args=makemodel_args, ...) call where the calcregion args are conditionally added to the args list beforehand.

ProSpect SED loop — simplified arg stripping, data merging, interval clamping, and log-unlogging

The old for(i in 1:Data$Ncomp) loop did:

  • Manual sub()/names() to strip _i suffix from param names
  • A 10-line conditional branch (if(Ncomp==1) vs multi-component) to merge data_ProSpect, with grepl/data_loc_global filtering
  • A pre-loop pmin/pmax block to clamp parameters via Data$intervals_ProSpect
  • A pre-loop 10^parm unlogging block driven by Data$logged_ProSpect, with branching for single-logical vs logical-vector cases
  • A parm[args_loc] = parm_logged write-back to propagate processed values into the loop

All of this is replaced by passing .strip, .lower, .upper, and .logged to a single ParmOff(ProSpect::ProSpectSED, ...) call per component:

  • .strip handles suffix removal automatically
  • .lower/.upper (named lists built from Data$intervals_ProSpect$lo/hi) handle interval clamping
  • .logged (character vector of param names derived from Data$logged_ProSpect) handles 10^x unlogging
  • ParmOff's formal-matching filters out wrong-component data_ProSpect entries, eliminating the if(Ncomp==1) branch entirely
  • The pre-loop processing block and parm write-back are removed

Summary by Sourcery

Refactor profitLikeModel to delegate argument handling and ProSpect SED evaluation to ParmOff while adding configurable scatter scaling to normal likelihood calculations.

New Features:

  • Support a scat_scale (or log_scat_scale) likelihood parameter to control the dispersion used in normal log-likelihood evaluations for both unresolved ProSpect photometry and image-domain Gaussian likelihoods.

Enhancements:

  • Replace duplicated profitMakeModel branches with a single ParmOff-based invocation that conditionally includes calcregion arguments.
  • Simplify the ProSpect SED component loop by using ParmOff for argument stripping, interval clamping, and log-unlogging, reducing custom name and bounds handling logic.

Build:

  • Add ParmOff to DESCRIPTION imports and configure it as a remote dependency, with corresponding NAMESPACE import entry.

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented May 13, 2026

Reviewer's Guide

Refactors profitLikeModel evaluation to use the ParmOff package for argument matching and preprocessing when calling profitMakeModel and ProSpect::ProSpectSED, consolidating duplicated code paths, simplifying ProSpect SED handling, and adding a configurable scatter scaling parameter for likelihood calculations.

Sequence diagram for ParmOff-mediated ProSpectSED evaluation in profitLikeModel

sequenceDiagram
  participant profitLikeModel
  participant ParmOff
  participant ProSpectSED as ProSpect::ProSpectSED
  participant Jansky2magAB as ProSpect::Jansky2magAB

  profitLikeModel->>profitLikeModel: build args_list, lower_i, upper_i, logged_i
  profitLikeModel->>ParmOff: ParmOff(ProSpect::ProSpectSED, .args=args_list, .strip=_i, .lower=lower_i, .upper=upper_i, .logged=logged_i, .check=FALSE, returnall=FALSE)
  ParmOff->>ProSpectSED: ProSpect::ProSpectSED(filtered_args)
  ProSpectSED-->>ParmOff: sed_flux
  ParmOff-->>profitLikeModel: sed_flux
  profitLikeModel->>Jansky2magAB: ProSpect::Jansky2magAB(sed_flux)
  Jansky2magAB-->>profitLikeModel: outSED (magnitudes)
  profitLikeModel->>profitLikeModel: update Data[[j]]$modellist[[1]]$mag[i]
Loading

Sequence diagram for ParmOff-mediated profitMakeModel call in .profitLikeModelEvaluation

sequenceDiagram
  participant profitLikeModel
  participant profitLikeModelEval as .profitLikeModelEvaluation
  participant ParmOff
  participant profitMakeModel

  profitLikeModel->>profitLikeModelEval: .profitLikeModelEvaluation(Data, modellistnew,...)
  profitLikeModelEval->>profitLikeModelEval: makemodel_args = list(..., adjust_calcregion=FALSE)
  profitLikeModelEval->>profitLikeModelEval: [if Data$usecalcregion] add calcregion, docalcregion
  profitLikeModelEval->>ParmOff: ParmOff(profitMakeModel, .args=makemodel_args, .check=FALSE, ...)
  ParmOff->>profitMakeModel: profitMakeModel(matched_args)
  profitMakeModel-->>ParmOff: model
  ParmOff-->>profitLikeModelEval: model
  profitLikeModelEval-->>profitLikeModel: model
Loading

File-Level Changes

Change Details Files
Route profitMakeModel calls through ParmOff and remove duplicated calcregion branches.
  • Introduce a makemodel_args list capturing common profitMakeModel arguments, including OpenCL options and threading.
  • Conditionally add calcregion and docalcregion entries to makemodel_args when Data$usecalcregion is TRUE instead of maintaining two separate calls.
  • Replace direct profitMakeModel invocation with ParmOff(profitMakeModel, .args=makemodel_args, .check=FALSE, ...) to handle formal matching and argument filtering.
  • Return the resulting model from the unified .profitLikeModelEvaluation path.
R/profitLikeModel.R
Refactor ProSpect SED component loop to delegate suffix stripping, interval clamping, and log-unlogging to ParmOff.
  • Identify ProSpect-related parameters via Data$parm_ProSpect name matching and compute their positions once (args_loc).
  • Precompute per-parameter lower and upper bound lists from Data$intervals_ProSpect$lo/hi, keyed by full argument names (including _i suffixes).
  • Derive the set of logged parameters (including _i suffixes) from Data$logged_ProSpect, handling both scalar and vector logical forms.
  • Within the SED component loop, construct per-component args_list from parm using names with _i suffixes and append Data$data_ProSpect as-is.
  • Strip ProSpect parameters for each component out of parm/Data$parm.names once they are moved into args_list to avoid re-use.
  • For each component, derive component-specific lower/upper bound lists and logged name vectors by filtering on the i suffix and stripping it from names for ParmOff.
  • Replace do.call(ProSpect::ProSpectSED, ...) plus manual pre-loop pmin/pmax clamping and 10^x transforms with ProSpect::Jansky2magAB(ParmOff(ProSpect::ProSpectSED, .args=args_list, .strip=paste0('',i), .lower=lower_i, .upper=upper_i, .logged=logged_i, .check=FALSE, returnall=FALSE)).
  • Rely on ParmOff’s formal-matching to drop data_ProSpect entries that do not correspond to the current component, eliminating Ncomp-dependent branching and grepl-based filtering.
R/profitLikeModel.R
Introduce scatter scaling parameter handling and use it in likelihood calculations.
  • Detect a scat_scale or log_scat_scale parameter in Data$parm.names, extract its value from parm, and remove it and its name from the parameter vector and names list.
  • When using log_scat_scale, exponentiate with base 10 to obtain scat_scale in linear space.
  • Set a default scat_scale of 1 when neither scat_scale nor log_scat_scale is present.
  • Use scat_scale as the sd argument in dnorm calls for both unresolved ProSpect-only likelihoods and the standard normal-pixel likelihood case.
R/profitLikeModel.R
Wire up ParmOff as a package dependency and import.
  • Add ParmOff to the Imports field in DESCRIPTION so it is available at load time in core evaluation paths.
  • Declare the remote repository asgr/ParmOff in the Remotes field to ensure installation from GitHub.
  • Add importFrom("ParmOff","ParmOff") to NAMESPACE to make the function available without fully qualifying it.
DESCRIPTION
NAMESPACE

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@asgr
Copy link
Copy Markdown
Collaborator

asgr commented May 14, 2026

@copilot logging and intervals can be dealt with via ParmOff (https://github.com/asgr/ParmOff/blob/main/R/ParmOff.R) rewrite relevant profitLikeModel code to make use of that capability, ideally simplifying the code within profitLikeModel.

Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 14, 2026

@copilot logging and intervals can be dealt with via ParmOff (https://github.com/asgr/ParmOff/blob/main/R/ParmOff.R) rewrite relevant profitLikeModel code to make use of that capability, ideally simpl...

Done in 16b7e96. The pre-loop pmin/pmax interval clamping and 10^parm unlogging blocks are replaced by passing .lower, .upper, and .logged directly to ParmOff inside the per-component loop:

  • Data$intervals_ProSpect$lo/hi are converted to named lists (keyed by full param names with _i suffix) before the loop; inside the loop each component's subset is filtered and the suffix stripped to match ParmOff's post-strip name matching
  • Data$logged_ProSpect (single logical or logical vector) is converted to a character vector of full param names before the loop; the per-component subset is similarly filtered and stripped

ParmOff then applies clamping (.lower/.upper) and unlogging (.logged) internally when calling ProSpectSED, removing the manual pre-loop code entirely.

Copilot AI changed the title Simplify profitLikeModel using ParmOff for argument matching Simplify profitLikeModel using ParmOff for argument matching, interval clamping, and log-unlogging May 14, 2026
Copilot finished work on behalf of asgr May 14, 2026 03:11
@asgr
Copy link
Copy Markdown
Collaborator

asgr commented May 22, 2026

@copilot Given what ParmOff can now do (https://github.com/asgr/ParmOff) with functional parameter passing, are there any other simplifications or improvements that can be made in ProSpectSEDlike.

Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 22, 2026

@copilot Given what ParmOff can now do (https://github.com/asgr/ParmOff) with functional parameter passing, are there any other simplifications or improvements that can be made in ProSpectSEDlike.

Since ProSpectSEDlike is in the ProSpect package rather than ProFit, I can't push changes to it from this PR, but here are the specific simplifications ParmOff's current API enables:


1. intervals + logged pre-processing (≈25 lines → 0)

The current manual block:

if (!is.null(Data$intervals)) {
  parm = pmin(pmax(parm, Data$intervals$lo), Data$intervals$hi)
}
if (!is.null(Data$logged)) {
  if (length(Data$logged) == 1) {
    if (Data$logged) { parmlist = 10^parm } else { parmlist = parm }
  } else {
    parmlist = parm
    parmlist[Data$logged] = 10^parm[Data$logged]
  }
} else { parmlist = parm }

can be removed entirely — ParmOff's .lower/.upper/.logged handle it inside the call (exactly the same transformation we just applied in profitLikeModel).


2. Two near-identical do.call('ProSpectSED', ...) calls → one ParmOff call

The returnall=TRUE and returnall=FALSE branches differ only in that one list element; both could collapse to:

SEDout = ParmOff(
  ProSpectSED,
  .args = c(as.list(parm), Data$arglist,
            list(SFH=Data$SFH, speclib=Data$speclib, Dale=Data$Dale,
                 AGN=Data$AGN, filtout=filtout, filters=NULL,
                 returnall=returnall)),
  .lower = if(!is.null(Data$intervals)) as.list(setNames(Data$intervals$lo, Data$parm.names)),
  .upper = if(!is.null(Data$intervals)) as.list(setNames(Data$intervals$hi, Data$parm.names)),
  .logged = logged_names  # derived from Data$logged as in profitLikeModel
)

3. scat_scale extraction → .rem_args

The current manual extraction:

if('scat_scale' %in% Data$parm.names){
  sel = which('scat_scale' == Data$parm.names)
  scat_scale = parmlist[sel]
  parmlist = parmlist[-sel]
  Data$parm.names = Data$parm.names[-sel]
} else { scat_scale = 1 }

can be replaced by:

scat_scale = if('scat_scale' %in% names(parm)) parm['scat_scale'] else 1
# then pass .rem_args = 'scat_scale' to ParmOff so it's excluded from the ProSpectSED call

Net effect: the three code blocks above total ≈40 lines and collapse to a single ParmOff(ProSpectSED, ...) call with .lower/.upper/.logged/.rem_args.

Copilot finished work on behalf of asgr May 22, 2026 02:21
@asgr asgr marked this pull request as ready for review May 22, 2026 02:26
Copilot AI review requested due to automatic review settings May 22, 2026 02:26
Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey - I've found 1 issue, and left some high level feedback:

  • In the single-image code path (non-MultiBand/MultiImage), scat_scale is now used in the dnorm call but is only defined inside the earlier inherits(Data, 'list') & inherits(Data[[1]], 'profit.data') branch, so scat_scale will be undefined for standard profit.data inputs; you likely want to factor the scat_scale extraction out so it runs for both paths.
  • Given that ParmOff is called with .check = FALSE in performance-critical paths, consider whether there should be a way (e.g. via a flag in Data) to enable checks during debugging or when integrating new parameters, as silent mismatches or dropped arguments could otherwise be harder to diagnose.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In the single-image code path (non-MultiBand/MultiImage), `scat_scale` is now used in the `dnorm` call but is only defined inside the earlier `inherits(Data, 'list') & inherits(Data[[1]], 'profit.data')` branch, so `scat_scale` will be undefined for standard `profit.data` inputs; you likely want to factor the `scat_scale` extraction out so it runs for both paths.
- Given that `ParmOff` is called with `.check = FALSE` in performance-critical paths, consider whether there should be a way (e.g. via a flag in `Data`) to enable checks during debugging or when integrating new parameters, as silent mismatches or dropped arguments could otherwise be harder to diagnose.

## Individual Comments

### Comment 1
<location path="R/profitLikeModel.R" line_range="117-129" />
<code_context>
+        }
+
+        # Filter bounds and logged names to this component, strip _i suffix for ParmOff
+        strip_i = paste0('_', i)
+        lower_i = NULL
+        upper_i = NULL
+        if(!is.null(lower_ProSpect)) {
+          sel = grepl(strip_i, names(lower_ProSpect))
+          if(any(sel)) {
+            stripped_names = sub(strip_i, '', names(lower_ProSpect)[sel])
+            lower_i = setNames(lower_ProSpect[sel], stripped_names)
+            upper_i = setNames(upper_ProSpect[sel], stripped_names)
           }
         }
-        outSED = ProSpect::Jansky2magAB(do.call(ProSpect::ProSpectSED, c(args_list, returnall=FALSE), quote=TRUE))
+        logged_i = sub(strip_i, '', all_logged_names[grepl(strip_i, all_logged_names)])
+
+        outSED = ProSpect::Jansky2magAB(ParmOff(ProSpect::ProSpectSED,
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Component selection via `grepl(strip_i, ...)` may unintentionally match parameter names containing `_<i>` in non-suffix positions.

Here `grepl(paste0('_', i), param_name)` will also match `_<i>` anywhere in the name. If any ProSpect parameters contain `"_1"`, `"_2"`, etc. in the middle of the name, they’ll be treated as component-specific, have that substring stripped, and may end up with incorrect names and lower/upper/logged metadata. If the convention guarantees `_<i>` only as a terminal suffix this is safe; otherwise, consider anchoring to the end (e.g. `grepl(paste0('_', i, '$'), ...)`) to avoid accidental matches.

```suggestion
        # Filter bounds and logged names to this component, strip _i suffix for ParmOff
        strip_i = paste0('_', i)
        strip_pattern = paste0(strip_i, '$')
        lower_i = NULL
        upper_i = NULL
        if(!is.null(lower_ProSpect)) {
          sel = grepl(strip_pattern, names(lower_ProSpect))
          if(any(sel)) {
            stripped_names = sub(strip_pattern, '', names(lower_ProSpect)[sel])
            lower_i = setNames(lower_ProSpect[sel], stripped_names)
            upper_i = setNames(upper_ProSpect[sel], stripped_names)
          }
        }
        logged_i = sub(strip_pattern, '', all_logged_names[grepl(strip_pattern, all_logged_names)])
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread R/profitLikeModel.R Outdated
Comment on lines +117 to +129
# Filter bounds and logged names to this component, strip _i suffix for ParmOff
strip_i = paste0('_', i)
lower_i = NULL
upper_i = NULL
if(!is.null(lower_ProSpect)) {
sel = grepl(strip_i, names(lower_ProSpect))
if(any(sel)) {
stripped_names = sub(strip_i, '', names(lower_ProSpect)[sel])
lower_i = setNames(lower_ProSpect[sel], stripped_names)
upper_i = setNames(upper_ProSpect[sel], stripped_names)
}
}
outSED = ProSpect::Jansky2magAB(do.call(ProSpect::ProSpectSED, c(args_list, returnall=FALSE), quote=TRUE))
logged_i = sub(strip_i, '', all_logged_names[grepl(strip_i, all_logged_names)])
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

suggestion (bug_risk): Component selection via grepl(strip_i, ...) may unintentionally match parameter names containing _<i> in non-suffix positions.

Here grepl(paste0('_', i), param_name) will also match _<i> anywhere in the name. If any ProSpect parameters contain "_1", "_2", etc. in the middle of the name, they’ll be treated as component-specific, have that substring stripped, and may end up with incorrect names and lower/upper/logged metadata. If the convention guarantees _<i> only as a terminal suffix this is safe; otherwise, consider anchoring to the end (e.g. grepl(paste0('_', i, '$'), ...)) to avoid accidental matches.

Suggested change
# Filter bounds and logged names to this component, strip _i suffix for ParmOff
strip_i = paste0('_', i)
lower_i = NULL
upper_i = NULL
if(!is.null(lower_ProSpect)) {
sel = grepl(strip_i, names(lower_ProSpect))
if(any(sel)) {
stripped_names = sub(strip_i, '', names(lower_ProSpect)[sel])
lower_i = setNames(lower_ProSpect[sel], stripped_names)
upper_i = setNames(upper_ProSpect[sel], stripped_names)
}
}
outSED = ProSpect::Jansky2magAB(do.call(ProSpect::ProSpectSED, c(args_list, returnall=FALSE), quote=TRUE))
logged_i = sub(strip_i, '', all_logged_names[grepl(strip_i, all_logged_names)])
# Filter bounds and logged names to this component, strip _i suffix for ParmOff
strip_i = paste0('_', i)
strip_pattern = paste0(strip_i, '$')
lower_i = NULL
upper_i = NULL
if(!is.null(lower_ProSpect)) {
sel = grepl(strip_pattern, names(lower_ProSpect))
if(any(sel)) {
stripped_names = sub(strip_pattern, '', names(lower_ProSpect)[sel])
lower_i = setNames(lower_ProSpect[sel], stripped_names)
upper_i = setNames(upper_ProSpect[sel], stripped_names)
}
}
logged_i = sub(strip_pattern, '', all_logged_names[grepl(strip_pattern, all_logged_names)])

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@copilot implement these suggestions

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Refactors profitLikeModel’s core evaluation path to delegate argument matching and parameter preprocessing (suffix stripping, interval clamping, log→linear transforms) to ParmOff, reducing duplicated/manual do.call and filtering logic in both model construction and the ProSpect SED component loop.

Changes:

  • Replaced duplicated profitMakeModel call branches with a single ParmOff(profitMakeModel, .args=...) invocation.
  • Simplified the ProSpect SED loop by using ParmOff(ProSpect::ProSpectSED, .strip/.lower/.upper/.logged=...) instead of manual suffix stripping, bounds clamping, and unlogging.
  • Added ParmOff as an imported dependency and declared its remote.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
R/profitLikeModel.R Refactors model evaluation + ProSpect SED argument handling to use ParmOff; introduces scat_scale usage in normal likelihood paths.
NAMESPACE Imports ParmOff::ParmOff for unqualified use in R code.
DESCRIPTION Adds ParmOff to Imports and asgr/ParmOff to Remotes.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread R/profitLikeModel.R
Comment on lines 292 to 296
skewtparm = Data$skewtparm

if(isnorm){
LL=sum(dnorm(cutsig, log=TRUE))
LL=sum(dnorm(cutsig, mean=0, sd=scat_scale, log=TRUE))
} else if(ischisq) {
Comment thread R/profitLikeModel.R Outdated
Comment on lines +60 to +72
if('scat_scale' %in% Data$parm.names){
sel = which(Data$parm.names == 'scat_scale')
scat_scale = parm[sel]
parm = parm[-sel]
Data$parm.names = Data$parm.names[-sel]
}else if('log_scat_scale' %in% Data$parm.names){
sel = which(Data$parm.names == 'log_scat_scale')
scat_scale = 10^parm[sel]
parm = parm[-sel]
Data$parm.names = Data$parm.names[-sel]
}else{
scat_scale = 1
}
Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 22, 2026

@copilot logging and intervals can be dealt with via ParmOff (https://github.com/asgr/ParmOff/blob/main/R/ParmOff.R) rewrite relevant profitLikeModel code to make use of that capability, ideally simpl...

Implemented in commit 16b7e96: the ProSpect loop now uses ParmOff(..., .lower, .upper, .logged) for interval clamping and log-unlogging, and the previous manual clamping/unlogging block was removed.

@copilot Given what ParmOff can now do (https://github.com/asgr/ParmOff) with functional parameter passing, are there any other simplifications or improvements that can be made in ProSpectSEDlike.

I made one more simplification in this PR in commit 2feed91: scat_scale / log_scat_scale extraction is now handled once at the top of profitLikeModel, so both MultiBand and single-image norm likelihood paths use the same logic (with positive sd enforcement). There isn’t a ProSpectSEDlike implementation in this repo to directly refactor further from here.

Copilot finished work on behalf of asgr May 22, 2026 02:33
@asgr
Copy link
Copy Markdown
Collaborator

asgr commented May 22, 2026

@copilot Given what ParmOff can now do (https://github.com/asgr/ParmOff) with functional parameter passing, are there any other simplifications or improvements that can be made in profitLikeModel.

Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 22, 2026

@copilot Given what ParmOff can now do (https://github.com/asgr/ParmOff) with functional parameter passing, are there any other simplifications or improvements that can be made in profitLikeModel.

Yes—implemented one additional improvement in 960af99: component suffix matching/stripping is now anchored to end-of-name (_i$) in the ProSpect loop (args_names_comp, bounds, logged names, and .strip). This keeps the ParmOff flow simpler/safer by avoiding accidental cross-component matches (e.g. _1 matching _10). No UI changes were involved in this update.

Copilot finished work on behalf of asgr May 22, 2026 02:40
@asgr asgr merged commit e81bdd6 into master May 26, 2026
6 checks passed
@asgr asgr deleted the copilot/simplify-profit-like-model branch May 26, 2026 07:51
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.

3 participants