From 8fb9b3f86d81c56cb4ab643020bee91b20931307 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 20 Apr 2026 07:59:16 +0000 Subject: [PATCH 1/7] Add offset_list support to profuseMultiBandFound2Fit Agent-Logs-Url: https://github.com/asgr/ProFuse/sessions/01d5aec8-11cf-4bf5-97fc-610ab52c296c Co-authored-by: asgr <5617132+asgr@users.noreply.github.com> --- R/profuseMultiBand.R | 27 ++++++++++++++++++++------- man/profuseMultiBand.Rd | 13 ++++++++----- vignettes/ProFuse-Multi-Images.Rmd | 2 +- 3 files changed, 29 insertions(+), 13 deletions(-) diff --git a/R/profuseMultiBand.R b/R/profuseMultiBand.R index 18e3bb4..24d21f6 100644 --- a/R/profuseMultiBand.R +++ b/R/profuseMultiBand.R @@ -25,13 +25,14 @@ profuseMultiBandFound2Fit = function(image_list, star_rough = TRUE, fit_rough = FALSE, psf_dim = c(51, 51), - star_con = 2, - star_con_fit = TRUE, - star_circ = TRUE, - tightcrop = TRUE, - wave = NULL, - smooth.parm = NULL, - parm_ProSpect = NULL, + star_con = 2, + star_con_fit = TRUE, + star_circ = TRUE, + tightcrop = TRUE, + offset_list = NULL, + wave = NULL, + smooth.parm = NULL, + parm_ProSpect = NULL, data_ProSpect = NULL, #perhaps need a way to specify extra data going to bulge/disk. Naming or list? logged_ProSpect = NULL, intervals_ProSpect = NULL, @@ -48,6 +49,17 @@ profuseMultiBandFound2Fit = function(image_list, magzero = rep(magzero, Nim) } + if(is.null(offset_list)){ + offset_list = vector("list", Nim) + }else{ + if(length(offset_list) == 1){ + offset_list = rep(offset_list, Nim) + } + if(length(offset_list) != Nim){ + stop("offset_list must be NULL, length 1, or the same length as image_list.") + } + } + for(i in 1:Nim){ if(autoclip){ image_med = median(image_list[[i]], na.rm=TRUE) @@ -267,6 +279,7 @@ profuseMultiBandFound2Fit = function(image_list, magzero = magzero[i], algo.func = 'LD', verbose = FALSE, + offset = offset_list[[i]], rough = fit_rough, nbenchconv = nbenchconv ) diff --git a/man/profuseMultiBand.Rd b/man/profuseMultiBand.Rd index a165ee1..172a2e7 100644 --- a/man/profuseMultiBand.Rd +++ b/man/profuseMultiBand.Rd @@ -15,11 +15,11 @@ profuseMultiBandFound2Fit(image_list, segim_list = NULL, segim_global = NULL, Ncomp = 2, loc = NULL, cutbox = NULL, psf_list = NULL, nbenchconv = 0L, magdiff = 2.5, magzero = NULL, gain = NULL, resamp = NULL, doprofit = NULL, sing_nser = 2, bulge_nser = 4, disk_nser = 1, sing_nser_fit = TRUE, bulge_nser_fit = FALSE, - disk_nser_fit = FALSE, bulge_circ = TRUE, nser_upper = 5.3, star_rough = TRUE, - fit_rough = FALSE, psf_dim = c(51, 51), star_con = 2, star_con_fit = TRUE, - star_circ = TRUE, tightcrop = TRUE, wave = NULL, smooth.parm = NULL, - parm_ProSpect = NULL, data_ProSpect = NULL, logged_ProSpect = NULL, - intervals_ProSpect = NULL, autoclip = TRUE, roughpedestal = TRUE, ...) + disk_nser_fit = FALSE, bulge_circ = TRUE, nser_upper = 5.3, star_rough = TRUE, + fit_rough = FALSE, psf_dim = c(51, 51), star_con = 2, star_con_fit = TRUE, + star_circ = TRUE, tightcrop = TRUE, offset_list = NULL, wave = NULL, smooth.parm = NULL, + parm_ProSpect = NULL, data_ProSpect = NULL, logged_ProSpect = NULL, + intervals_ProSpect = NULL, autoclip = TRUE, roughpedestal = TRUE, ...) profuseMultiBandDoFit(image_list, MF2F = NULL, parm_global = c("sersic.xcen1", "sersic.ycen1", "sersic.re1", "sersic.ang2", "sersic.axrat2"), Ncomp = 2, @@ -123,6 +123,9 @@ Logical; optional, should the star be forced to be circular? If TRUE this means } \item{tightcrop}{ Logical; optional, should the image be cut down to the tightest fitting box that fully contains the segmentation map? This might be a good idea if the parent image is very large (cuts down on memory allocation etc), but might be a bad idea if you want to know the exact position of your source with the frame, e.g. \option{xcen} and \option{ycen} in the \option{modellist} are relative to the new tightly cropped image not the original cropped image. +} + \item{offset_list}{ +List; optional, per-band offsets to pass into \code{\link{profitSetupData}} \option{offset}. This can be used to track known [X,Y] positional shifts between images so a shared physical model is correctly projected into each band. If length 1 it is recycled to all bands. } \item{wave}{ Numeric vector; optional. This is only relevant if you are providing smoothing functions via \option{smooth.parm}. If provided it should be the wavelength of each image in \option{image_list}, where \option{image_list} then needs to be in ascending (blue to red) wavelength order. diff --git a/vignettes/ProFuse-Multi-Images.Rmd b/vignettes/ProFuse-Multi-Images.Rmd index 4ff2a33..f59ab65 100644 --- a/vignettes/ProFuse-Multi-Images.Rmd +++ b/vignettes/ProFuse-Multi-Images.Rmd @@ -203,7 +203,7 @@ HighFit2$parm ## Fully Automatic Multi-band Fitting -**ProFit** v2.0.0 and upwards support highly automated multi-band fitting via the **profuseMultiBandFound2Fit** and **profuseMultiBandDoFit** functions. These require the images provided to be exactly registered and cropped to the desired level (no offset or cut out options here). If this is not the case, then lower level functions (i.e. those above) probably need to be used instead. These functions will find stars and create per band PSFs automatically, so they might well cover the major use cases for many people. +**ProFit** v2.0.0 and upwards support highly automated multi-band fitting via the **profuseMultiBandFound2Fit** and **profuseMultiBandDoFit** functions. These require images to be cropped to the desired level, but now support per-band positional offsets via `offset_list` when required. If this is not the case, then lower level functions (i.e. those above) probably need to be used instead. These functions will find stars and create per band PSFs automatically, so they might well cover the major use cases for many people. As an example we can load in 9 bands of data that come included in the **ProFound** package, and cut out around a bright spiral galaxy: From 27fecbee568549d3fe30f681ec01401e640cba59 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 20 Apr 2026 08:00:13 +0000 Subject: [PATCH 2/7] Address review feedback for offset_list support Agent-Logs-Url: https://github.com/asgr/ProFuse/sessions/01d5aec8-11cf-4bf5-97fc-610ab52c296c Co-authored-by: asgr <5617132+asgr@users.noreply.github.com> --- R/profuseMultiBand.R | 2 +- vignettes/ProFuse-Multi-Images.Rmd | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/R/profuseMultiBand.R b/R/profuseMultiBand.R index 24d21f6..1102ce0 100644 --- a/R/profuseMultiBand.R +++ b/R/profuseMultiBand.R @@ -53,7 +53,7 @@ profuseMultiBandFound2Fit = function(image_list, offset_list = vector("list", Nim) }else{ if(length(offset_list) == 1){ - offset_list = rep(offset_list, Nim) + offset_list = rep(list(offset_list[[1]]), Nim) } if(length(offset_list) != Nim){ stop("offset_list must be NULL, length 1, or the same length as image_list.") diff --git a/vignettes/ProFuse-Multi-Images.Rmd b/vignettes/ProFuse-Multi-Images.Rmd index f59ab65..6087a9a 100644 --- a/vignettes/ProFuse-Multi-Images.Rmd +++ b/vignettes/ProFuse-Multi-Images.Rmd @@ -203,7 +203,7 @@ HighFit2$parm ## Fully Automatic Multi-band Fitting -**ProFit** v2.0.0 and upwards support highly automated multi-band fitting via the **profuseMultiBandFound2Fit** and **profuseMultiBandDoFit** functions. These require images to be cropped to the desired level, but now support per-band positional offsets via `offset_list` when required. If this is not the case, then lower level functions (i.e. those above) probably need to be used instead. These functions will find stars and create per band PSFs automatically, so they might well cover the major use cases for many people. +**ProFit** v2.0.0 and upwards support highly automated multi-band fitting via the **profuseMultiBandFound2Fit** and **profuseMultiBandDoFit** functions. These require images to be cropped to the desired level, and now support per-band positional offsets via `offset_list` when required. If your data still need more complex registration/cutout handling than this, then lower level functions (i.e. those above) probably need to be used instead. These functions will find stars and create per band PSFs automatically, so they might well cover the major use cases for many people. As an example we can load in 9 bands of data that come included in the **ProFound** package, and cut out around a bright spiral galaxy: From 28adc1ae2a1e404156e6cfe5188b50043acd6f69 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 20 Apr 2026 08:00:59 +0000 Subject: [PATCH 3/7] Harden offset_list validation and formatting Agent-Logs-Url: https://github.com/asgr/ProFuse/sessions/01d5aec8-11cf-4bf5-97fc-610ab52c296c Co-authored-by: asgr <5617132+asgr@users.noreply.github.com> --- R/profuseMultiBand.R | 3 +++ 1 file changed, 3 insertions(+) diff --git a/R/profuseMultiBand.R b/R/profuseMultiBand.R index 1102ce0..c564f2c 100644 --- a/R/profuseMultiBand.R +++ b/R/profuseMultiBand.R @@ -52,6 +52,9 @@ profuseMultiBandFound2Fit = function(image_list, if(is.null(offset_list)){ offset_list = vector("list", Nim) }else{ + if(!is.list(offset_list)){ + stop("offset_list must be a list when provided.") + } if(length(offset_list) == 1){ offset_list = rep(list(offset_list[[1]]), Nim) } From c0f714c2fe2fc468344c76b3733e3a0bd172f1e8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 20 Apr 2026 08:02:14 +0000 Subject: [PATCH 4/7] Accept single offset vector and clarify defaults Agent-Logs-Url: https://github.com/asgr/ProFuse/sessions/01d5aec8-11cf-4bf5-97fc-610ab52c296c Co-authored-by: asgr <5617132+asgr@users.noreply.github.com> --- R/profuseMultiBand.R | 3 +++ man/profuseMultiBand.Rd | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/R/profuseMultiBand.R b/R/profuseMultiBand.R index c564f2c..c4aa2de 100644 --- a/R/profuseMultiBand.R +++ b/R/profuseMultiBand.R @@ -52,6 +52,9 @@ profuseMultiBandFound2Fit = function(image_list, if(is.null(offset_list)){ offset_list = vector("list", Nim) }else{ + if(is.numeric(offset_list) && length(offset_list) == 2){ + offset_list = list(offset_list) + } if(!is.list(offset_list)){ stop("offset_list must be a list when provided.") } diff --git a/man/profuseMultiBand.Rd b/man/profuseMultiBand.Rd index 172a2e7..39e1238 100644 --- a/man/profuseMultiBand.Rd +++ b/man/profuseMultiBand.Rd @@ -125,7 +125,7 @@ Logical; optional, should the star be forced to be circular? If TRUE this means Logical; optional, should the image be cut down to the tightest fitting box that fully contains the segmentation map? This might be a good idea if the parent image is very large (cuts down on memory allocation etc), but might be a bad idea if you want to know the exact position of your source with the frame, e.g. \option{xcen} and \option{ycen} in the \option{modellist} are relative to the new tightly cropped image not the original cropped image. } \item{offset_list}{ -List; optional, per-band offsets to pass into \code{\link{profitSetupData}} \option{offset}. This can be used to track known [X,Y] positional shifts between images so a shared physical model is correctly projected into each band. If length 1 it is recycled to all bands. +List; optional, per-band offsets to pass into \code{\link{profitSetupData}} \option{offset}. This can be used to track known [X,Y] positional shifts between images so a shared physical model is correctly projected into each band. If NULL (default) then no offsets are used. If length 1 it is recycled to all bands. A single numeric [X,Y] vector is also accepted and treated as length 1. } \item{wave}{ Numeric vector; optional. This is only relevant if you are providing smoothing functions via \option{smooth.parm}. If provided it should be the wavelength of each image in \option{image_list}, where \option{image_list} then needs to be in ascending (blue to red) wavelength order. From 7766c164a555f6c2cb6f2e47baa6f602985a07ad Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 20 Apr 2026 08:03:08 +0000 Subject: [PATCH 5/7] Normalize formatting and validate numeric offsets Agent-Logs-Url: https://github.com/asgr/ProFuse/sessions/01d5aec8-11cf-4bf5-97fc-610ab52c296c Co-authored-by: asgr <5617132+asgr@users.noreply.github.com> --- R/profuseMultiBand.R | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/R/profuseMultiBand.R b/R/profuseMultiBand.R index c4aa2de..83a1e4a 100644 --- a/R/profuseMultiBand.R +++ b/R/profuseMultiBand.R @@ -25,14 +25,14 @@ profuseMultiBandFound2Fit = function(image_list, star_rough = TRUE, fit_rough = FALSE, psf_dim = c(51, 51), - star_con = 2, - star_con_fit = TRUE, - star_circ = TRUE, - tightcrop = TRUE, - offset_list = NULL, - wave = NULL, - smooth.parm = NULL, - parm_ProSpect = NULL, + star_con = 2, + star_con_fit = TRUE, + star_circ = TRUE, + tightcrop = TRUE, + offset_list = NULL, + wave = NULL, + smooth.parm = NULL, + parm_ProSpect = NULL, data_ProSpect = NULL, #perhaps need a way to specify extra data going to bulge/disk. Naming or list? logged_ProSpect = NULL, intervals_ProSpect = NULL, @@ -52,8 +52,12 @@ profuseMultiBandFound2Fit = function(image_list, if(is.null(offset_list)){ offset_list = vector("list", Nim) }else{ - if(is.numeric(offset_list) && length(offset_list) == 2){ - offset_list = list(offset_list) + if(is.numeric(offset_list)){ + if(length(offset_list) == 2){ + offset_list = list(offset_list) + }else{ + stop("Numeric offset_list input must be a single [X,Y] vector.") + } } if(!is.list(offset_list)){ stop("offset_list must be a list when provided.") From 011902bf8a9a62fdfb0c62d09d7a500385961bc3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 20 Apr 2026 08:03:51 +0000 Subject: [PATCH 6/7] Clarify offset_list length requirement in docs Agent-Logs-Url: https://github.com/asgr/ProFuse/sessions/01d5aec8-11cf-4bf5-97fc-610ab52c296c Co-authored-by: asgr <5617132+asgr@users.noreply.github.com> --- man/profuseMultiBand.Rd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/profuseMultiBand.Rd b/man/profuseMultiBand.Rd index 39e1238..2970135 100644 --- a/man/profuseMultiBand.Rd +++ b/man/profuseMultiBand.Rd @@ -125,7 +125,7 @@ Logical; optional, should the star be forced to be circular? If TRUE this means Logical; optional, should the image be cut down to the tightest fitting box that fully contains the segmentation map? This might be a good idea if the parent image is very large (cuts down on memory allocation etc), but might be a bad idea if you want to know the exact position of your source with the frame, e.g. \option{xcen} and \option{ycen} in the \option{modellist} are relative to the new tightly cropped image not the original cropped image. } \item{offset_list}{ -List; optional, per-band offsets to pass into \code{\link{profitSetupData}} \option{offset}. This can be used to track known [X,Y] positional shifts between images so a shared physical model is correctly projected into each band. If NULL (default) then no offsets are used. If length 1 it is recycled to all bands. A single numeric [X,Y] vector is also accepted and treated as length 1. +List; optional, per-band offsets to pass into \code{\link{profitSetupData}} \option{offset}. This can be used to track known [X,Y] positional shifts between images so a shared physical model is correctly projected into each band. If NULL (default) then no offsets are used. If length 1 it is recycled to all bands. A single numeric [X,Y] vector is also accepted and treated as length 1. Otherwise, \option{offset_list} must have the same length as \option{image_list}. } \item{wave}{ Numeric vector; optional. This is only relevant if you are providing smoothing functions via \option{smooth.parm}. If provided it should be the wavelength of each image in \option{image_list}, where \option{image_list} then needs to be in ascending (blue to red) wavelength order. From ccd97696ebc056b504e5a8959b1e5442cc692438 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 20 Apr 2026 08:05:01 +0000 Subject: [PATCH 7/7] Require list-based per-band offset vectors Agent-Logs-Url: https://github.com/asgr/ProFuse/sessions/01d5aec8-11cf-4bf5-97fc-610ab52c296c Co-authored-by: asgr <5617132+asgr@users.noreply.github.com> --- R/profuseMultiBand.R | 12 +++++------- man/profuseMultiBand.Rd | 2 +- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/R/profuseMultiBand.R b/R/profuseMultiBand.R index 83a1e4a..3edd5e5 100644 --- a/R/profuseMultiBand.R +++ b/R/profuseMultiBand.R @@ -52,13 +52,6 @@ profuseMultiBandFound2Fit = function(image_list, if(is.null(offset_list)){ offset_list = vector("list", Nim) }else{ - if(is.numeric(offset_list)){ - if(length(offset_list) == 2){ - offset_list = list(offset_list) - }else{ - stop("Numeric offset_list input must be a single [X,Y] vector.") - } - } if(!is.list(offset_list)){ stop("offset_list must be a list when provided.") } @@ -68,6 +61,11 @@ profuseMultiBandFound2Fit = function(image_list, if(length(offset_list) != Nim){ stop("offset_list must be NULL, length 1, or the same length as image_list.") } + for(i in 1:Nim){ + if(!is.null(offset_list[[i]]) && (!is.numeric(offset_list[[i]]) || length(offset_list[[i]]) != 2)){ + stop("Each non-NULL offset_list element must be a numeric [X,Y] vector of length 2.") + } + } } for(i in 1:Nim){ diff --git a/man/profuseMultiBand.Rd b/man/profuseMultiBand.Rd index 2970135..eac0fc9 100644 --- a/man/profuseMultiBand.Rd +++ b/man/profuseMultiBand.Rd @@ -125,7 +125,7 @@ Logical; optional, should the star be forced to be circular? If TRUE this means Logical; optional, should the image be cut down to the tightest fitting box that fully contains the segmentation map? This might be a good idea if the parent image is very large (cuts down on memory allocation etc), but might be a bad idea if you want to know the exact position of your source with the frame, e.g. \option{xcen} and \option{ycen} in the \option{modellist} are relative to the new tightly cropped image not the original cropped image. } \item{offset_list}{ -List; optional, per-band offsets to pass into \code{\link{profitSetupData}} \option{offset}. This can be used to track known [X,Y] positional shifts between images so a shared physical model is correctly projected into each band. If NULL (default) then no offsets are used. If length 1 it is recycled to all bands. A single numeric [X,Y] vector is also accepted and treated as length 1. Otherwise, \option{offset_list} must have the same length as \option{image_list}. +List; optional, per-band offsets to pass into \code{\link{profitSetupData}} \option{offset}. This can be used to track known [X,Y] positional shifts between images so a shared physical model is correctly projected into each band. If NULL (default) then no offsets are used. If length 1 it is recycled to all bands. Otherwise, \option{offset_list} must have the same length as \option{image_list}. Each non-NULL element should be a numeric [X,Y] vector of length 2. } \item{wave}{ Numeric vector; optional. This is only relevant if you are providing smoothing functions via \option{smooth.parm}. If provided it should be the wavelength of each image in \option{image_list}, where \option{image_list} then needs to be in ascending (blue to red) wavelength order.