diff --git a/R/profuseMultiBand.R b/R/profuseMultiBand.R index 18e3bb4..f49fbee 100644 --- a/R/profuseMultiBand.R +++ b/R/profuseMultiBand.R @@ -28,6 +28,8 @@ profuseMultiBandFound2Fit = function(image_list, star_con = 2, star_con_fit = TRUE, star_circ = TRUE, + log_scat_scale = FALSE, + offset_list = NULL, tightcrop = TRUE, wave = NULL, smooth.parm = NULL, @@ -48,6 +50,37 @@ profuseMultiBandFound2Fit = function(image_list, magzero = rep(magzero, Nim) } + 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) + } + 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.") + } + } + } + + if('log_scat_scale' %in% parm_global){ + stop('log_scat_scale should not be in parm_global, instead set log_scat_scale argument to TRUE') + } + + if (isTRUE(log_scat_scale)) { + if (!is.null(parm_global) && !is.character(parm_global)) { + stop("When log_scat_scale=TRUE, parm_global must be NULL or a character vector of parameter names.") + } + # Put log_scat_scale at the end of parm_global + parm_global = c(parm_global, "log_scat_scale") + } + for(i in 1:Nim){ if(autoclip){ image_med = median(image_list[[i]], na.rm=TRUE) @@ -153,6 +186,7 @@ profuseMultiBandFound2Fit = function(image_list, disk_nser_fit = disk_nser_fit, bulge_circ = bulge_circ, nser_upper = nser_upper, + log_scat_scale = log_scat_scale, tightcrop = FALSE, fit_extra = FALSE, autoclip = FALSE, @@ -266,7 +300,9 @@ profuseMultiBandFound2Fit = function(image_list, constraints = F2Fstack$Data$constraints, magzero = magzero[i], algo.func = 'LD', + log_scat_scale = log_scat_scale, verbose = FALSE, + offset = offset_list[[i]], rough = fit_rough, nbenchconv = nbenchconv ) @@ -406,8 +442,13 @@ profuseMultiBandDoFit = function(image_list, lower_profit[logged_profit] = log10(lower_profit[logged_profit]) upper_profit[logged_profit] = log10(upper_profit[logged_profit]) - lower = c(lower_profit, MF2F$intervals_ProSpect$lo) - upper = c(upper_profit, MF2F$intervals_ProSpect$hi) + if('log_scat_scale' %in% MF2F$parm.names){ + lower = c(lower_profit, -2, MF2F$intervals_ProSpect$lo) + upper = c(upper_profit, 1, MF2F$intervals_ProSpect$hi) + }else{ + lower = c(lower_profit, MF2F$intervals_ProSpect$lo) + upper = c(upper_profit, MF2F$intervals_ProSpect$hi) + } }else{ #This implies we are in smooth.spline fitting mode, i.e. not using ProSpect (we don't use this) @@ -417,7 +458,7 @@ profuseMultiBandDoFit = function(image_list, } message('Running Highander on multi-band data') - if(!requireNamespace("ProFound", quietly = TRUE)){stop('The Highander package is required to run this function!')} + if(!requireNamespace("Highlander", quietly = TRUE)){stop('The Highlander package is required to run this function!')} highfit = Highlander::Highlander( parm = MF2F$init, Data = MF2F, diff --git a/R/profuseMultiImage.R b/R/profuseMultiImage.R index 103bc32..4010016 100644 --- a/R/profuseMultiImage.R +++ b/R/profuseMultiImage.R @@ -10,8 +10,9 @@ profuseMultiImageFound2Fit = function( magzero = NULL, gain = NULL, resamp = NULL, - tightcrop = TRUE, + log_scat_scale = FALSE, offset_list = NULL, + tightcrop = TRUE, ... ){ Nim = length(image_list) @@ -82,8 +83,9 @@ profuseMultiImageFound2Fit = function( magzero = magzero[[i]], gain = gain[[i]], resamp = resamp[[i]], - tightcrop = tightcrop, + log_scat_scale = log_scat_scale, offset = offset_list[[i]], + tightcrop = tightcrop, ... )$Data diff --git a/R/profuseSingleImage.R b/R/profuseSingleImage.R index 521f148..dc043b6 100644 --- a/R/profuseSingleImage.R +++ b/R/profuseSingleImage.R @@ -28,6 +28,7 @@ profuseFound2Fit = function(image, star_con = 2, star_con_fit = TRUE, star_circ = TRUE, + log_scat_scale = FALSE, offset = NULL, tightcrop = TRUE, deblend_extra = FALSE, @@ -724,6 +725,7 @@ profuseFound2Fit = function(image, constraints = constraints, magzero = magzero, algo.func = 'LD', + log_scat_scale = log_scat_scale, verbose = FALSE, offset = offset, rough = fit_rough, diff --git a/man/profuseFound2Fit.Rd b/man/profuseFound2Fit.Rd index aa794bb..ae2c0c7 100644 --- a/man/profuseFound2Fit.Rd +++ b/man/profuseFound2Fit.Rd @@ -16,8 +16,8 @@ profuseFound2Fit(image, sigma = NULL, segim = NULL, mask = NULL, Ncomp = 2, 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, - offset = NULL, tightcrop = TRUE, deblend_extra = FALSE, fit_extra = FALSE, - pos_delta = 10, autoclip = TRUE, roughpedestal = TRUE, ...) + log_scat_scale = FALSE, offset = NULL, tightcrop = TRUE, deblend_extra = FALSE, + fit_extra = FALSE, pos_delta = 10, autoclip = TRUE, roughpedestal = TRUE, ...) profuseDoFit(image, F2F = NULL, Ncomp = 2, psf = NULL, magzero = NULL, psf_dim = c(51,51), plot = FALSE, seed = 666, optim_iters = 5, @@ -117,6 +117,9 @@ Logical; optional, should the Moffat profile concentration index be optimised du } \item{star_circ}{ Logical; optional, should the star be forced to be circular? If TRUE this means the \option{axrat} is fixed to be 1. This is only relevant if the \option{psf} has not been provided and we need to calculate ourself using \code{\link{profuseAllStarDoFit}}. +} + \item{log_scat_scale}{ +Logical; optional. If TRUE, include a log scatter scale hyper-parameter in the likelihood evaluation (see \code{profitLikeModel}) to improve sampling when the image likelihood is under/over-dispersed. } \item{offset}{ Numeric vector; optional. Offset argument to be passed to \code{\link{profitSetupData}} (see description there). diff --git a/man/profuseMultiBand.Rd b/man/profuseMultiBand.Rd index a165ee1..f0f40ae 100644 --- a/man/profuseMultiBand.Rd +++ b/man/profuseMultiBand.Rd @@ -17,9 +17,10 @@ profuseMultiBandFound2Fit(image_list, segim_list = NULL, segim_global = NULL, 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, ...) + star_circ = TRUE, log_scat_scale = FALSE, offset_list = NULL, tightcrop = TRUE, + 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, @@ -120,6 +121,12 @@ Logical; optional, should the Moffat profile concentration index be optimised du } \item{star_circ}{ Logical; optional, should the star be forced to be circular? If TRUE this means the \option{axrat} is fixed to be 1. This is only relevant if the \option{psf} has not been provided and we need to calculate ourself using \code{\link{profuseAllStarDoFit}}. +} + \item{log_scat_scale}{ +Logical; optional. If TRUE, include a log scatter scale hyper-parameter in the likelihood evaluation (see \code{profitLikeModel}) to improve sampling when the image likelihood is under/over-dispersed. +} + \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. 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{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. diff --git a/man/profuseMultiImage.Rd b/man/profuseMultiImage.Rd index 4187830..050f1dd 100644 --- a/man/profuseMultiImage.Rd +++ b/man/profuseMultiImage.Rd @@ -12,7 +12,8 @@ Functions to easily take users from multiple image pixel data all the way to ful \usage{ profuseMultiImageFound2Fit(image_list, segim_list = NULL, mask_list = NULL, Ncomp = 2, loc = NULL, cutbox = NULL, psf_list = NULL, nbenchconv = 0L, - magzero = NULL, gain = NULL, resamp = NULL, tightcrop = TRUE, offset_list = NULL, ...) + magzero = NULL, gain = NULL, resamp = NULL, log_scat_scale = FALSE, + offset_list = NULL, tightcrop = TRUE, ...) profuseMultiImageDoFit(image_list, F2F = NULL, Ncomp = 2, psf_list = NULL, magzero = NULL, psf_dim = c(51, 51), plot = FALSE, seed = 666, @@ -57,11 +58,14 @@ Numeric vector; optional, gains to pass into \code{\link{profuseFound2Fit}} \opt \item{resamp}{ Numeric scalar; optional, resampling factor to pass into \code{\link{profuseFound2Fit}} \option{resamp}. } - \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{log_scat_scale}{ +Logical; optional. If TRUE, include a log scatter scale hyper-parameter in the likelihood evaluation (see \code{profitLikeModel}) to improve sampling when the image likelihood is under/over-dispersed. } \item{offset_list}{ List; optional, offsets to pass into \code{\link{profuseFound2Fit}} \option{offset}. +} + \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{psf_dim}{ Integer vector; optional, the dimensions of the output PSF generated when fitting a star with \option{Ncomp} = 0.5. The PSF will be centrally located in the image. The dimensions will be forced to be odd (adding 1 if required) to ensure the PSF mode is at the centre of the middle pixel.