ProFound: Source Finding

Aaron Robotham

2023-03-15

Introduction to ProFound Functions

The ProFound source finding and image utilites suite covers the following functions:

Very High Level

High Level

Mid Level

Low Level

Basic ProFound Usage

The profoundProFound function might be the only function many people need to use in order to extract photometry from a target image. In brief, in fully automatic mode using default option, the basic code flow of the source extraction is as follows:

  1. Make a rough sky map
  2. Using this rough sky map, make an initial segmentation map
  3. Using this segmentation map, make a better sky map
  4. Using this better sky map, extract basic photometric properties
  5. Using the current segmentation map, dilate segments and re-measure photometric properties for the new image segments (by default it iterates six times)
  6. Using the iterative dilation statistics, every object is checked for convergence (by default convergence of flux is used)
  7. Make final segmentation map by combining the segments when each source has converged in flux
  8. Make a conservative object mask by aggressively dilating the final segmentation map
  9. Using this conservative objects mask make a final sky map
  10. Using the final segmentation map and the final sky map compute the final comprehensive photometric properties
  11. Return a list containing the input image pixel-matched final segmentation map (called segim), the pre-dilation segmentation map (segim_orig) , the binary object/sky mask (objects), the conservatively dilated binary object/sky mask (objects_redo), the sky image (sky), the sky-RMS image (skyRMS) and the effective surface brightness limit image (SBlim)
  12. Return the data-frame of photometric properties for every detected source (segstats)

Some other simple properties are passed through and included in the output of ProFound: the header (header) if it is attached to the input image, the magnitude zero point specified (magzero), the gain in electrons per astronomical data unit (gain), the pixel scale in arc-seconds per pixel (pixscale) and finally the full function call (call).

Get the latest version of ProFound:

library(devtools)
install_github('asgr/ProFound')

Set global evaluate (basically TRUE for GitHub version and FALSE for CRAN):

evalglobal=TRUE

Load some libraries:

library(ProFound)
## Loading required package: Rfits
## Loading required package: magicaxis
## Loading required package: Rcpp
library(Rfits)
library(Rwcs)

First read in some data.

image = Rfits_read_image(system.file("extdata", 'VIKING/mystery_VIKING_Z.fits',package="ProFound"))

Give it a quick look:

plot(image)

A basic example of the lower level profoundMakeSegim versus the higher level profoundProFound:

out_segim=segim=profoundMakeSegim(image$imDat, magzero=30, pixscale=0.339, header=image$hdr, plot=TRUE)

out_profound=profoundProFound(image, magzero=30, verbose=TRUE, plot=TRUE)
## Running ProFound:
## Using raw flux units
## Supplied image is 356 x 356 pixels
## Extracted pixel scale from header provided: 0.339 asec/pixel
## Supplied image is 2.011 x 2.011 amin,  0.001124 deg-sq
## Making initial sky map - 0.002 sec
##  - Sky statistics :
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
## -2.7399 -0.2272  0.4102  0.5812  1.0496  4.9236
##  - Sky-RMS statistics :
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   8.159   8.857   9.130   9.134   9.307  10.300
## Making initial segmentation image - 0.069 sec
##  - Running MakeSegim:
##  - Skipping making initial local estimate of the sky - User provided sky
##  - Skipping making initial local estimate of the sky RMS - User provided sky RMS
##  - Smoothing the image - 0.001 sec
##  - Watershed de-blending - 0.007 sec
##  - Skipping segmentation plot - plot set to FALSE
##  - Skipping making final local estimate of the sky - User provided sky
##  - Skipping making final local estimate of the sky RMS - User provided sky RMS
##  - Skipping segmentation statistics - segstats set to FALSE or no segments
##  - MakeSegim is finished! - 0.014 sec
## Doing initial aggressive dilation - 0.083 sec
##  - Running MakeSegimDilate:
##  - Dilating segments - 0.001 sec
##  - Skipping segmentation statistics - segstats set to FALSE
##  - profoundMakeSegimDilate is finished! - 0.013 sec
## Making better sky map - 0.099 sec
##  - Sky statistics :
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
## -4.1923 -0.7818 -0.1067 -0.1494  0.4264  3.5583
##  - Sky-RMS statistics :
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   8.246   8.823   8.863   8.903   9.081   9.274
## Calculating initial segstats - 0.138 sec
## Doing dilations:
## Iteration 1 of 6 - 0.144 sec
## Iteration 2 of 6 - 0.149 sec
## Iteration 3 of 6 - 0.158 sec
## Iteration 4 of 6 - 0.166 sec
## Iteration 5 of 6 - 0.172 sec
## Iteration 6 of 6 - 0.187 sec
##  - Running MakeSegimDilate:
##  - Dilating segments - 0 sec
##  - Skipping segmentation statistics - segstats set to FALSE
##  - profoundMakeSegimDilate is finished! - 0.032 sec
## Doing final aggressive dilation - 0.225 sec
## Making final sky map - 0.226 sec
## Making final sky RMS map - 0.241 sec
##  - Sky statistics :
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
## -4.3946 -0.8394 -0.3054 -0.2772  0.3861  2.8269
##  - Sky-RMS statistics :
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   8.247   8.768   8.847   8.871   9.034   9.198
## Calculating final segstats for 50 objects - 0.283 sec
##  - magzero = 30
##  - gain = NULL (ignored)
##  - pixscale = 0.339
##  - rotstats = FALSE
##  - boundstats = FALSE
##  - groupstats = FALSE
##  - deblend = FALSE
## Plotting segments - 0.325 sec
## ProFound is finished! - 0.552 sec

Notice in the two outputs (the first being profoundMakeSegim, the second being profoundProFound) that some segment have converged quickly (i.e. not grown much) but others have expanded a lot in order to capture all the flux present. profoundProFound in default mode with modern survey imaging data tends to extract very close to a true total magnitude, without too much error introduced by sky noise (a consequence of over-growing apertures).

Because it was run in verbose mode, the major profoundProFound steps mentioned above were printed out. For large images (a few thousand by a few thousand pixels plus) this is useful since it can take a few minutes to run with all the bells and whistles turned on, and it is nice to see it making progress. Note for more than a couple of hundred sources, you almost certainly do not want to plot the output, since this will be slow.

Note because we parsed profoundProFound a header we have RA and Dec coordinates in the photometric properties data-frame. We also parsed the appropriate magnitude zero-point and pixel scale so the mag properties are correctly scaled, and R/R50/R90 are in arc-seconds rather than pixels. It is is worth checking the output:

out_profound$segstats[1:10,]
##    segID uniqueID      xcen       ycen  xmax  ymax    RAcen    Deccen    RAmax
## 1      1   222149 220.86569 148.451083 221.5 148.5 352.2866 -31.82508 352.2866
## 2      2   227142 227.18164 140.430571 226.5 141.5 352.2859 -31.82584 352.2860
## 3      3   194148 193.55776 148.078930 193.5 147.5 352.2897 -31.82512 352.2897
## 4      4   122001 120.80654   1.881948 121.5   0.5 352.2977 -31.83888 352.2976
## 5      5   175133 174.30566 133.443022 174.5 132.5 352.2918 -31.82649 352.2918
## 6      6   178179 177.30965 178.807230 177.5 178.5 352.2915 -31.82222 352.2914
## 7      7   175257 174.72609 257.536638 174.5 256.5 352.2917 -31.81481 352.2918
## 8      8   155320 154.08790 319.818916 154.5 319.5 352.2940 -31.80894 352.2940
## 9      9   149074 148.53576  73.770211 148.5  73.5 352.2947 -31.83211 352.2947
## 10    10    48308  47.91953 307.721066  47.5 307.5 352.3058 -31.81008 352.3058
##       Decmax        sep        flux      mag    flux_app  mag_app     cenfrac
## 1  -31.82508 0.21567094 2969722.823 13.81821 571718.0257 15.60705 0.031670102
## 2  -31.82574 0.42991766 1004804.667 14.99480 206110.8329 16.71475 0.033439675
## 3  -31.82517 0.19723180   56603.265 18.11790  10231.1084 19.97519 0.030576097
## 4  -31.83901 0.52415415    4498.573 20.86731   1687.8302 21.93168 0.073662064
## 5  -31.82658 0.32640217   31922.192 18.73977   1591.7650 21.99530 0.007892784
## 6  -31.82225 0.12252168   45409.813 18.35713   1523.2301 22.04309 0.004986304
## 7  -31.81491 0.35968112    8312.662 20.20065   1379.1325 22.15099 0.026853925
## 8  -31.80897 0.17664924    6189.088 20.52093    972.8887 22.52984 0.026077926
## 9  -31.83214 0.09240051    4443.128 20.88078    956.2178 22.54861 0.038715029
## 10 -31.81010 0.16075736    4128.262 20.96058    759.6010 22.79854 0.031051254
##          N50       N90 N100       R50      R90      R100   SB_N50   SB_N90
## 1   28.74951 146.03901 1858 1.1010009 2.481458  8.851060 15.86836 16.99477
## 2   24.17834 141.60705 2061 1.0631039 2.572794  9.815253 16.85694 18.13790
## 3   32.73981 202.88977  386 1.1852932 2.950651  4.069878 20.30916 21.65144
## 4   12.30187  56.67860  126 0.9225479 1.980217  2.952491 21.99581 23.01625
## 5  129.05884 524.53827 1269 2.8030268 5.650957  8.789500 22.42031 23.30460
## 6  184.71767 666.34213 1472 4.4809109 8.510611 12.649285 22.42697 23.18176
## 7   33.73971 122.87166  377 1.1844175 2.260268  3.959176 22.42458 23.18967
## 8   36.12613 139.57809  364 1.1882657 2.335670  3.771842 22.81906 23.64837
## 9   24.10122  90.03224  271 0.9510242 1.838108  3.189016 22.73945 23.53217
## 10  27.09978  94.92620  276 1.0458842 1.957464  3.337761 22.94657 23.66944
##     SB_N100      xsd      ysd       covxy       corxy       con asymm
## 1  19.64182 3.509788 3.543925   1.7629331  0.14173280 0.4436912    NA
## 2  20.93099 4.047922 3.867643   3.7193626  0.23756910 0.4132099    NA
## 3  22.23536 3.209266 3.732403   0.6567635  0.05482956 0.4017057    NA
## 4  23.76924 3.080102 1.611909  -0.1801823 -0.03629165 0.4658822    NA
## 5  24.14942 7.177867 6.900845 -23.2291255 -0.46895931 0.4960270    NA
## 6  23.92789 9.448844 9.427492 -71.0208652 -0.79728042 0.5265087    NA
## 7  24.29250 3.309138 3.455355   1.3825871  0.12091632 0.5240163    NA
## 8  24.57469 3.672123 3.615042  -0.8584764 -0.06466924 0.5087473    NA
## 9  24.61420 3.048265 3.006684   0.1999036  0.02181123 0.5173929    NA
## 10 24.71385 3.209157 3.106886  -0.9326870 -0.09354482 0.5343058    NA
##    flux_reflect mag_reflect   semimaj  semimin     axrat       ang signif
## 1            NA          NA  3.780130 3.279528 0.8675702 136.95342    Inf
## 2            NA          NA  4.420711 3.459526 0.7825723 129.57029    Inf
## 3            NA          NA  3.758896 3.204309 0.8524601 170.05724    Inf
## 4            NA          NA  3.094361 1.636115 0.5287409  88.50274    Inf
## 5            NA          NA  8.542007 5.132662 0.6008731  47.39933    Inf
## 6            NA          NA 12.656367 4.259262 0.3365312  45.08129    Inf
## 7            NA          NA  3.605086 3.171734 0.8797944 144.84086    Inf
## 8            NA          NA  3.774010 3.532214 0.9359311  51.80920    Inf
## 9            NA          NA  3.079871 3.002187 0.9747770 118.90014    Inf
## 10           NA          NA  3.323563 3.011980 0.9062502  54.55007    Inf
##       FPlim   flux_err      mag_err flux_err_sky flux_err_skyRMS flux_err_shot
## 1  2.179146 1084.31883 0.0003964290  1012.147060       388.98028             0
## 2  2.137907  781.72738 0.0008446913   666.866730       407.90496             0
## 3  2.742820  213.38948 0.0040931327   122.551868       174.68860             0
## 4  3.091962   99.33411 0.0239744130     2.812758        99.29428             0
## 5  2.325863  665.04349 0.0226194301   587.151131       312.30817             0
## 6  2.269641 1043.67480 0.0249539790   986.367487       341.08103             0
## 7  2.750559  177.96664 0.0232446385    21.200015       176.69942             0
## 8  2.762035  170.38607 0.0298904017    14.216496       169.79195             0
## 9  2.857004  145.27658 0.0355002201    14.990529       144.50110             0
## 10 2.851196  146.52772 0.0385369067    13.998923       145.85747             0
##    flux_err_cor cor_seg    sky_mean    sky_sum skyRMS_mean Nedge Nsky Nobject
## 1             0       0  1.97133144 3662.73382    9.023775    NA   NA      NA
## 2             0       0  2.16025633 4452.28829    8.984926    NA   NA      NA
## 3             0       0  0.94804952  365.94712    8.891345    NA   NA      NA
## 4             0       0  0.80752502  101.74815    8.845837    NA   NA      NA
## 5             0       0 -0.16146985 -204.90524    8.766927    NA   NA      NA
## 6             0       0 -0.45997731 -677.08660    8.889865    NA   NA      NA
## 7             0       0 -1.30003654 -490.11377    9.100470    NA   NA      NA
## 8             0       0 -0.69339103 -252.39434    8.899496    NA   NA      NA
## 9             0       0  0.06278522   17.01479    8.777816    NA   NA      NA
## 10            0       0 -0.29466196  -81.32670    8.779545    NA   NA      NA
##    Nborder Nmask edge_frac edge_excess flag_border iter  origfrac Norig
## 1       NA    NA        NA          NA          NA    4 0.9980130  1235
## 2       NA    NA        NA          NA          NA    5 0.9940484  1002
## 3       NA    NA        NA          NA          NA    0 1.0000000   386
## 4       NA    NA        NA          NA          NA    1 0.9350449    70
## 5       NA    NA        NA          NA          NA    5 0.8449997   417
## 6       NA    NA        NA          NA          NA    3 0.8864669   637
## 7       NA    NA        NA          NA          NA    2 0.8907488   133
## 8       NA    NA        NA          NA          NA    2 0.8264710   122
## 9       NA    NA        NA          NA          NA    2 0.8322204    77
## 10      NA    NA        NA          NA          NA    2 0.8207472    80
##    skyseg_mean flag_keep
## 1           NA      TRUE
## 2           NA      TRUE
## 3           NA      TRUE
## 4           NA      TRUE
## 5           NA      TRUE
## 6           NA      TRUE
## 7           NA      TRUE
## 8           NA      TRUE
## 9           NA      TRUE
## 10          NA      TRUE

Next we will check the before and after photometry for the brightest 40 sources (the lists differ a bit in detail due to the different sky estimation routines used):

magplot(out_segim$segstats[1:40,c("R50", "SB_N90")], col=hsv(magmap(out_segim$segstats$axrat, flip=TRUE)$map), log='x', xlim=c(0.4,5), ylim=c(22,25), grid=TRUE, xlab='R50 / asec', ylab='mag / asec^2')
points(out_profound$segstats[1:40,c("R50", "SB_N90")], col=hsv(magmap(out_segim$segstats$axrat, flip=TRUE)$map), pch=16)
arrows(out_segim$segstats$R50[1:40], out_segim$segstats$SB_N90[1:40], out_profound$segstats$R50[1:40], out_profound$segstats$SB_N90[1:40], col='lightgrey', length=0)
rect(0.9, 23.5, 1.3, 24.3)
legend('bottomleft', legend=c('profoundProFound', 'profoundMakeSegim'), pch=c(16,1))
magbar('topright', title='Axrat', titleshift=1)

magplot(out_segim$segstats[1:40,c("R50", "con")], col=hsv(magmap(out_segim$segstats$axrat, flip=TRUE)$map), log='x', xlim=c(0.4,5), ylim=c(0,1), grid=TRUE, xlab='R50 / asec', ylab='Concentration')
points(out_profound$segstats[1:40,c("R50", "con")], col=hsv(magmap(out_segim$segstats$axrat, flip=TRUE)$map), pch=16)
arrows(out_segim$segstats$R50[1:40], out_segim$segstats$con[1:40], out_profound$segstats$R50[1:40], out_profound$segstats$con[1:40], col='lightgrey', length=0)
rect(0.9, 0.4, 1.3, 0.6)
legend('bottomleft', legend=c('profoundProFound', 'profoundMakeSegim'), pch=c(16,1))
magbar('topright', title='Axrat', titleshift=1)

magplot(out_segim$segstats[1:40,c("R50", "mag")], col=hsv(magmap(out_segim$segstats$axrat, flip=TRUE)$map), log='x', xlim=c(0.4,5), ylim=c(17,24), grid=TRUE, xlab='R50 / asec', ylab='Mag')
points(out_profound$segstats[1:40,c("R50", "mag")], col=hsv(magmap(out_segim$segstats$axrat, flip=TRUE)$map), pch=16)
arrows(out_segim$segstats$R50[1:40], out_segim$segstats$mag[1:40], out_profound$segstats$R50[1:40], out_profound$segstats$mag[1:40], col='lightgrey', length=0)
rect(0.9, 20, 1.3, 22)
legend('bottomleft', legend=c('profoundProFound', 'profoundMakeSegim'), pch=c(16,1))
magbar('topright', title='Axrat', titleshift=1)

It is notable that low surface brightness objects are seen to systematically grow when processing the image with profoundProFound. The box represents the location of likely stars, where redder objects are more circular sources. It is clear that profoundProFound moves stars onto a more uniform value of R50 (remember for a Gaussian PSF FWHM=2*R50).

The profoundProFound function also returns a sky and sky RMS image matched to the input image:

maghist(out_profound$sky, xlab='Sky')
## Summary of used sample:
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
## -4.3946 -0.8394 -0.3054 -0.2772  0.3861  2.8269
## Pop Std Dev: 0.96505
## MAD: 0.92258
## Half 16-84 Quan (1s): 0.83722
## Half 02-98 Quan (2s): 2.1987
## Using 126736 out of 126736

maghist(out_profound$skyRMS, xlab='Sky RMS')
## Summary of used sample:
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   8.247   8.768   8.847   8.871   9.034   9.198
## Pop Std Dev: 0.18477
## MAD: 0.20228
## Half 16-84 Quan (1s): 0.18993
## Half 02-98 Quan (2s): 0.34799
## Using 126736 out of 126736

plot(image)

Rwcs_image(out_profound$sky, image$keyvalues)

Rwcs_image(out_profound$skyRMS, image$keyvalues)

The background mask we used here (the default 100x100 option) looks to be pretty good, with not much correlation between the image and the sky map. However, even with a slightly too small sky grid the photometric outputs should be mostly pretty robust- differing by at worst a couple of counts per pixel. This is much less than the typical sky RMS (roughly 9 throughout).

maghist(out_profound$segstats[,'N100']/out_profound$segstats[,'flux'], xlab=' Worst case fraction error')
## Summary of used sample:
##      Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
## 0.0006256 0.0662467 0.1208740 0.1243626 0.1601715 0.2831985
## Pop Std Dev: 0.074419
## MAD: 0.080689
## Half 16-84 Quan (1s): 0.072266
## Half 02-98 Quan (2s): 0.13755
## Using 50 out of 50

In summary, you probably want to use profoundProFound, unless you really know what you are doing and are feeling a bit adventurous!

ProFound Flags

ProFound offers a few useful flags that will help extract high fidelity photometry. To access the boundary flags we have to set boundstats=TRUE when we run ProFound:

out_profound=profoundProFound(image, magzero=30, verbose=TRUE, boundstats=TRUE)
## Running ProFound:
## Using raw flux units
## Supplied image is 356 x 356 pixels
## Extracted pixel scale from header provided: 0.339 asec/pixel
## Supplied image is 2.011 x 2.011 amin,  0.001124 deg-sq
## Making initial sky map - 0 sec
##  - Sky statistics :
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
## -2.7399 -0.2272  0.4102  0.5812  1.0496  4.9236
##  - Sky-RMS statistics :
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   8.159   8.857   9.130   9.134   9.307  10.300
## Making initial segmentation image - 0.033 sec
##  - Running MakeSegim:
##  - Skipping making initial local estimate of the sky - User provided sky
##  - Skipping making initial local estimate of the sky RMS - User provided sky RMS
##  - Smoothing the image - 0.002 sec
##  - Watershed de-blending - 0.007 sec
##  - Skipping segmentation plot - plot set to FALSE
##  - Skipping making final local estimate of the sky - User provided sky
##  - Skipping making final local estimate of the sky RMS - User provided sky RMS
##  - Skipping segmentation statistics - segstats set to FALSE or no segments
##  - MakeSegim is finished! - 0.013 sec
## Doing initial aggressive dilation - 0.047 sec
##  - Running MakeSegimDilate:
##  - Dilating segments - 0.009 sec
##  - Skipping segmentation statistics - segstats set to FALSE
##  - profoundMakeSegimDilate is finished! - 0.021 sec
## Making better sky map - 0.068 sec
##  - Sky statistics :
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
## -4.1923 -0.7818 -0.1067 -0.1494  0.4264  3.5583
##  - Sky-RMS statistics :
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   8.246   8.823   8.863   8.903   9.081   9.274
## Calculating initial segstats - 0.107 sec
## Doing dilations:
## Iteration 1 of 6 - 0.113 sec
## Iteration 2 of 6 - 0.118 sec
## Iteration 3 of 6 - 0.124 sec
## Iteration 4 of 6 - 0.138 sec
## Iteration 5 of 6 - 0.144 sec
## Iteration 6 of 6 - 0.152 sec
##  - Running MakeSegimDilate:
##  - Dilating segments - 0.001 sec
##  - Skipping segmentation statistics - segstats set to FALSE
##  - profoundMakeSegimDilate is finished! - 0.037 sec
## Doing final aggressive dilation - 0.211 sec
## Making final sky map - 0.211 sec
## Making final sky RMS map - 0.229 sec
##  - Sky statistics :
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
## -4.3946 -0.8394 -0.3054 -0.2772  0.3861  2.8269
##  - Sky-RMS statistics :
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   8.247   8.768   8.847   8.871   9.034   9.198
## Calculating final segstats for 50 objects - 0.264 sec
##  - magzero = 30
##  - gain = NULL (ignored)
##  - pixscale = 0.339
##  - rotstats = FALSE
##  - boundstats = TRUE
##  - groupstats = TRUE -  0.364 sec
##  - deblend = FALSE
## Skipping segmentation plot - plot = FALSE
## ProFound is finished! - 0.487 sec

The output we get is in segstats is useful, telling us whether or not an object is isolated:

out_profound$segstats[1:10,c("Nedge", "Nsky", "Nobject", "Nborder", "edge_frac", "edge_excess", "flag_border")]
##    Nedge Nsky Nobject Nborder  edge_frac edge_excess flag_border
## 1    201   49     152       0 0.24378109   1.3104724           0
## 2    168   98      70       0 0.58333333   1.0322778           0
## 3     71    3      68       0 0.04225352   1.0145874           0
## 4     43   23       0      20 0.53488372   1.0040090           1
## 5    138   73      65       0 0.52898551   1.0420405           0
## 6    135  107      28       0 0.79259259   0.8108876           0
## 7     62   62       0       0 1.00000000   0.8980127           0
## 8     58   58       0       0 1.00000000   0.8568711           0
## 9     51   51       0       0 1.00000000   0.8738310           0
## 10    52   52       0       0 1.00000000   0.8813643           0

The edge_frac column is simply Nsky/Nedge (the number of segment edge pixels purely touching sky divided by the number of pixels in the segment edge). Where it is 1 the segment must be well isolated, because none of its outer pixels are touching either an image boundary or another object.

We can easily plot the isolated segments and the non-isolated segments:

magimage(out_profound$segim*(out_profound$segim %in% out_profound$segstats[out_profound$segstats$edge_frac==1,"segID"]), col=c(0,rainbow(100)))

magimage(out_profound$segim*(out_profound$segim %in% out_profound$segstats[out_profound$segstats$edge_frac!=1,"segID"]), col=c(0,rainbow(100)))

You might be more interested in removing segments touching an image edge:

magimage(out_profound$segim*(out_profound$segim %in% out_profound$segstats[out_profound$segstats$Nborder==0,"segID"]), col=c(0,rainbow(100)))
legend('topleft',legend='Isolated Segment')

magimage(out_profound$segim*(out_profound$segim %in% out_profound$segstats[out_profound$segstats$Nborder>0,"segID"]), col=c(0,rainbow(100)))
## [1] "Too many same valued pixels: turning off magmap scaling!"
legend('topleft',legend='Non_Isolated Segment')

The edge_excess column tells us how elliptical or non-elliptical the segments are. Generally values less than 1 are probably fairly sensible looking segments (i.e. ellipses). Larger than this and the segments might have weird gemoetry:

magimage(out_profound$segim*(out_profound$segim %in% out_profound$segstats[out_profound$segstats$edge_excess<1,"segID"]), col=c(0,rainbow(100)))
legend('topleft',legend='Fairly Elliptical Segment')

magimage(out_profound$segim*(out_profound$segim %in% out_profound$segstats[out_profound$segstats$edge_excess>1,"segID"]), col=c(0,rainbow(100)))
legend('topleft',legend='Non-Elliptical Segment')

The flag_border column tells us which border of the image the segment touches. The bottom of the image is flagged 1, left=2, top=4 and right=8. A summed combination of these flags indicate the segment is in a corner touching two borders: bottom-left=3, top-left=6, top-right=12, bottom-right=9. In our case we can see we should find segments touching the bottom, left and top of the image:

magimage(out_profound$segim*(out_profound$segim %in% out_profound$segstats[out_profound$segstats$flag_border==1,"segID"]), col=c(0,rainbow(100)))
## [1] "Too many same valued pixels: turning off magmap scaling!"
legend('topleft',legend='Segment Borders Bottom')

magimage(out_profound$segim*(out_profound$segim %in% out_profound$segstats[out_profound$segstats$flag_border==2,"segID"]), col=c(0,rainbow(100)))
## [1] "Too many same valued pixels: turning off magmap scaling!"
legend('topleft',legend='Segment Borders Left')

magimage(out_profound$segim*(out_profound$segim %in% out_profound$segstats[out_profound$segstats$flag_border==4,"segID"]), col=c(0,rainbow(100)))
## [1] "Too many same valued pixels: turning off magmap scaling!"
legend('topleft',legend='Segment Borders Top')

magimage(out_profound$segim*(out_profound$segim %in% out_profound$segstats[out_profound$segstats$flag_border==8,"segID"]), col=c(0,rainbow(100)))
## [1] "Too many same valued pixels: turning off magmap scaling!"
legend('topleft',legend='Segment Borders Right')

Depending on your science requirements, users might want to make use of some or all of these useful flags. Practically the most useful flag is probably edge_frac, where values above 0.8 are usually a good cut off for fairly reliable photometry (i.e. the confused or missing flux is the sub-dominant form of error), but this cannot be treated as a guarantee!

magimage(out_profound$segim*(out_profound$segim %in% out_profound$segstats[out_profound$segstats$edge_frac>0.8,"segID"]), col=c(0,rainbow(100)))
legend('topleft',legend='Reliable Photometry Segments')

magimage(out_profound$segim*(out_profound$segim %in% out_profound$segstats[out_profound$segstats$edge_frac<0.8,"segID"]), col=c(0,rainbow(100)))
legend('topleft',legend='Unreliable Photometry Segments')

Advanced ProFound Usage

The way ProFound handles the various inputs allows for great flexibility and power. AS an example, it is fairly trivial to run it in a mode where you can extract multiband photometry in pixel matched data. AS a pseudo code example imagine you have 3 pixel matched 2k*2K J/H/K band images with the same magnitude zero points. You can use the objects detected in, say, the K band to extract photometry in the others:

pro_det_K=profoundProFound(image=Kim)

Total Photometry

We can then extract matching photometry. Note that in practice pro_K_tot_fix = pro_det_K (since the K band was our detection band already), but we psuedo re-run it for clarity.

pro_J_tot_fix=profoundProFound(image=Jim, segim=pro_det_K$segim, iters=0)
pro_H_tot_fix=profoundProFound(image=Him, segim=pro_det_K$segim, iters=0)
pro_K_tot_fix=profoundProFound(image=Kim, segim=pro_det_K$segim, iters=0)

A second option is to allow each target band to dynamically dilate based on the original segmentation map. The might help in situations where the target image PSFs are quite mismatched. The dynamic dilation will ensure close to total magnitudes regardless of the differing PSFs. Note that in practice pro_K_tot_dil = pro_det_K (since the K band was our detection band already), but we psuedo re-run it for clarity.

pro_J_tot_dil=profoundProFound(image=Jim, segim=pro_det_K$segim_orig, objects=pro_det_K$objects)
pro_H_tot_dil=profoundProFound(image=Him, segim=pro_det_K$segim_orig, objects=pro_det_K$objects)
pro_K_tot_dil=profoundProFound(image=Kim, segim=pro_det_K$segim_orig, objects=pro_det_K$objects)

Colour Photometry

The above options would extract close to total photometry given the K-band detection segments. You often find better colours running with the high surface brightness non-dilated segmentation map, which is also returned by ProFound. In this case you would need to re-run the K too. Notice we also pass the objects matrix to ProFound. This ensures a better sky estimation, since we are now using the brighter inner part of detected objects to extract colour photometry, but we want to know the location of the full object to obtain a good sky estimate.

pro_J_col_fix=profoundProFound(image=Jim, segim=pro_det_K$segim_orig, objects=pro_det_K$objects, iters=0)
pro_H_col_fix=profoundProFound(image=Him, segim=pro_det_K$segim_orig, objects=pro_det_K$objects, iters=0)
pro_K_col_fix=profoundProFound(image=Kim, segim=pro_det_K$segim_orig, objects=pro_det_K$objects, iters=0)