Correction Grids

Correction grids can be thought of as lookup tables that provide corrected Petrosian derived values. These grids are typically generated through simulations or theoretical models to offer the best correction for Petrosian profiles. This section discusses the concept of correction grids: how they’re generated, when and why they should be used, and how they enhance accuracy.

Necessity and Implications

Are Correction Grids Always Needed?

The short answer is no, but they are very useful in some cases. Petrosian corrections offer more precise measurements of galaxies. The necessity hinges on your data quality, research goals, and desired precision. Here are key considerations on why the defualt settings are usually good enough:

  1. Standard Practices: Numerous studies, such as those from the Sloan Digital Sky Survey (SDSS), rely on default settings. The parameters \(\eta = 0.2\) and \(\epsilon = 2\) are widely accepted because they typically produce reliable results across many scenarios.

  2. Noise Constraints: If the fainter parts of galaxies in your images are submerged below the noise level, detailed corrections might not significantly impact the outcome since that portion of the galaxy is not meaningfully measurable. Here, the additional steps and computational demands of correction grids might be unwarranted.

  3. Practical Implications: While correction grids can produce improved results, they require optimal background subtraction. Not all datasets might meet this standard.

Correction grids promise enhanced precision but aren’t always essential. For a majority of cases, default settings suffice.

When are Correction Grids Needed?

While the default settings serve most general purposes, there are specific scenarios where correction grids are beneficial:

  1. Galaxy Size Estimation: If your research aims to measure the size of a galaxy which suffers due to poor signal-to-noise, you can estimate its total flux radius based on the corrected epsilon. Remember, this isn’t about recovering the total flux which includes regions submerged under noise, but about the estimating the full extent of the galaxy based on the measurable components of the light profile.

  2. Estimating Sérsic Index: Correction grids can be used to estimate the Sérsic index of single component galaxies.

  3. High-Precision Studies: For projects that require a granular study of galaxy structures, or when analyzing galaxies with distinct features that might get overlooked with standard parameters, correction grids provide the extra precision that may be needed.

  4. Superior Data Quality: If you have high-quality images with excellent background subtraction and reasonable signal-to-noise ratios, the total flux can be estimated to higher accuracy. That is, high quality data allows you to measure the flux up to the corrected total flux radius.

In essence, when the goal shifts from general measurements to intricate, high-resolution studies of galactic structures and sizes, correction grids become a useful tool.

Generating a Correction Grid

Correction grids are essentially lookup tables that map certain observational properties of a galaxy (like Petrosian radius, uncorrected half light radius, and concentration indices) to more intrinsic properties (like Sérsic index and the corrected epsilon value). In this section, we’ll walk through the steps of creating a correction grid.

To start with PetroFit, simply import it as follows:

[2]:
import petrofit as pf

Load PSF (Optional)

We load an HST F105W PSF and normalize it to sum to 1:

[3]:
from matplotlib import pyplot as plt

plt.rcParams['figure.figsize'] = [6, 6]
plt.rcParams['image.origin'] = 'lower'
plt.rcParams['font.size'] = 12
[4]:
from astropy.io import fits

# Load PSF image (2D array)
PSF = fits.getdata('data/f105w_psf.fits.gz')

# Normalize PSF
PSF = PSF / PSF.sum()

# Note that the PSF shape is odd on all sides
print("PSF Shape = {}".format(PSF.shape))

# Plot PSF and use vmax and vmin to show difraction spikes
plt.imshow(PSF, vmin=0, vmax=5e-4)
plt.show()
PSF Shape = (50, 50)
_images/correction_grids_7_1.png

Define Sampling Points

The correction grid is generated along with a set of half-light radii and Sersic indices. The generator loops through the Sersic indices for each half-light radius in the radius list. For this documentation, we define a small set of values, with the Sersic indices of a Gaussian and de Vaucouleurs’ profile.

[5]:
import numpy as np

r_eff_list = np.array([7, 10, 15])
n_list = np.array([0.5, 1., 4.])

Grid Simulation

We do a simple API call to generate the correction grid. We provide a PSF and oversampling rule as well. Oversampling becomes important for small half-light radii since the model needs to be sampled well in the center.

The generate_petrosian_sersic_correction grid follows the following steps to generate the correction grid:

  • Computes the total flux (total_flux) of an ideal Sersic profile with the sampling points using the petrofit.modeling.models.sersic_enclosed function and setting the radius to np.inf.

  • Computes the radius equal to total_flux * 0.99.

  • Makes a PSF convolved Sersic Model image and measures the photometry.

  • Measures the uncorrected Petrosian radius.

  • Computes the correct epsilon value as corrected_epsilon = r(total_flux) / r_petrosian.

  • It also saves other values, such as the uncorrected C2080 which can be used to mapto the Sersic index.

[6]:
output_file_name='temp/example_correction_gid.ecsv'

petrosian_grid = pf.generate_petrosian_sersic_correction(
    output_file_name=output_file_name, # Output file name
    psf=PSF, # PSF (optional)
    r_eff_list=r_eff_list, # List of r_e to sample
    n_list=n_list, # List of n to sample
    oversample=4, # Oversample factor or region, see fitting docs
    out_format='ascii.ecsv', # Output format, should match file name
    overwrite=True, # Overwrite output
    ipython_widget=True, # Progress bar
    n_cpu=None, # int value for number of mp threads
    plot=False, # Plot each step, can not be True if n_cpu > 1

)

[7]:
petrosian_grid
[7]:
Table length=9
nr_effsersic_r_20sersic_r_80sersic_r_99sersic_L_infp02p03p04p05p0502p0302u_epsilonu_epsilon_50u_epsilon_80u_r_50u_r_99u_r_20u_r_80u_c2080u_c5090c_epsilonc_epsilon_50c_epsilon_80c_r_50c_r_99c_r_20c_r_80c_c2080c_c5090
float64int64float64float64float64float64float64float64float64float64float64float64float64float64float64float64float64float64float64float64float64float64float64float64float64float64float64float64float64float64
0.573.949426167451565410.53574315174438618.0429751786938222208.56469495324216.69033806761352414.74294858971794413.19163832766553311.8163632726545310.74990649711596850.26940391210961472.00.47024629951459210.74272187930724517.84856971394278833.384876975395084.40268053610722112.396279255851172.2478708876830881.4772154039318741.58382564747385570.46765745790136030.72947706468950447.80536107221444326.439087817563514.381076215243048512.2558511702340472.23381335001397961.443311364049927
0.5105.642037382073664515.05106164534912225.7756788267054345323.6014182719222.4884976995399119.88537707541508217.7597519503900815.8343668733746750.7617987056259010.2671330675900842.00.47983454901263120.746192848247642510.79075815163032644.982396479295866.077815563112622516.7807561512302432.20532004815750061.3989166475552131.36674289660873380.476454367550257940.72944374421339610.71474294858971830.7371474294858946.04740948189637916.5679135827165422.18849222053944551.3671755462140593
0.5158.46305607311049922.57659246802368438.66351824005819101978.1031911118232.0224044808961828.36467293458691725.3050610122024422.5215043008601730.76428271735702720.263380793394058232.00.48984882558720640.754766366816591715.68613722744548964.054610922184428.8675735147029424.1694338867773552.17730840298542461.35340940016364791.29112978076359690.48628810594702650.73686640093990815.57211442288457641.3412682536507258.82196439287857523.85017003400682.15963089516694851.3247894047084208
1.073.415245598972988612.26987798578664127.68704252003055210929.80566958005718.97759551910382215.49089817963592712.91738347669533810.8419683936787351.21566524560103930.44082293324390932.00.426092822734507550.76146054032402578.0862172434486937.956591318263654.06741348269653914.4506901380276052.7528513239219321.8544007451235291.65166987472571750.42263542358410010.74179386550728128.02060412082416431.3460692138427674.05101020204040714.253850770154032.73184435377372071.8246976026729558
1.0104.878922284247126517.5283971225523539.55291788575800622305.72585628583325.28065613122624520.6387277455491117.06801360272054414.116223244648931.2653491169059380.440527096346199632.00.435447625377834770.771582079159347311.00840168033606850.569913982796565.50850170034006819.5061012202440482.7456849284203041.81213107260928391.6412417931614360.432646504929655450.748745345242534410.937587517503541.4820964192838565.48489697939587919.246449289857972.72591072477056251.7791529983794634
1.0157.3183834263706926.29259568382852759.3293768286370150187.8831766431135.51330266053210528.9275855171034223.7935587117423519.4738947789557921.30469121763087110.445394382440013062.00.44651919946375560.789535348755991915.85737147429485871.02680536107227.90058011602320428.039007801560312.75051830028121061.80753960777360151.7009978570313930.44354507100168420.767603632767211715.75175035007001360.394278855771157.86537307461492227.7221444288857732.73553747337675861.7796966409157084
4.071.933889461317013421.37899838138344132.6058088721295651.86132026452481420.72954590918183412.7353470694138828.9285857171434276.7829565913182632.42585375516417661.05789501857896842.00.3685815472801490.88975846063284677.64052810562112441.46249249849972.92678535707141418.4442888577715543.9973552078470132.68041435434915437.1644235103666330.421695118067685171.11739867723164228.741548309661933148.502300460092023.16763352670534123.914982996599324.38967572736073.312617849643298
4.0102.762699230452876430.541426259119202189.43686981732796105.8394291112751125.80516103220644215.78315663132626610.4420884176835367.6215243048609722.64832367311814881.06756353544914332.00.37947286821705420.91257364341085279.79235847169433951.600920184036813.63172634526905423.5491098219643934.059306892737752.67323034899155547.84671216813025650.44900775193798451.223315041693743311.586717343468694202.506501300260063.99059811962392532.70034006801364.5675713778130813.4406515906900377
4.0154.14404884567931545.8121393886788284.15530472598925238.13871550036933.36667333466693520.40408081616323312.8825765153030618.8817763552710542.87406538093550031.06797937269901172.00.395959232613908860.950923261390887313.21184236847369566.768353670734164.67153430686137331.7291458291658374.1599941908722082.6640624762247488.8603720294307880.489250599520383741.391619136834863216.3246649329866295.68053610722155.31006201240248148.171234246849374.7884409052852273.559459521262453

PetrosianCorrection

The PetrosianCorrection class is designed to compute corrections for Petrosian based on default Petrosian measurements.

Loading and Navigating

  1. Grid Input: To initialize the PetrosianCorrection class, you’ll need a correction grid. This grid is typically an Astropy Table that has been generated with the function petrofit.correction.generate_petrosian_sersic_correction.

[8]:
# Input generated grid table
pc = pf.PetrosianCorrection(petrosian_grid)
  1. Reading and Writing Grids:

    • Use the PetrosianCorrection.read(file_path) class method to read a correction grid from a file.

    • Similarly, to save your correction grid to a file, utilize the write(grid_file, file_format=None) method.

[9]:
# Read F105W grid:
pc = pf.PetrosianCorrection.read(output_file_name)
  1. Working with Grid Data:

    • The grid_keys property will provide you with the column names of your grid.

    • Use unique_grid_values(key) to obtain unique values from a specific column.

    • The filter_grid(key, value) method helps filter the grid based on a specific key and value.

[10]:
# Read ideal Sersic grid:
pc = pf.PetrosianCorrection.read('data/no_psf_corr.ecsv')
[11]:
print(pc.grid_keys)
['n', 'r_eff', 'sersic_r_20', 'sersic_r_80', 'sersic_r_99', 'sersic_L_inf', 'p02', 'p03', 'p04', 'p05', 'p0502', 'p0302', 'u_epsilon', 'u_epsilon_50', 'u_epsilon_80', 'u_r_50', 'u_r_99', 'u_r_20', 'u_r_80', 'u_c2080', 'u_c5090', 'c_epsilon', 'c_epsilon_50', 'c_epsilon_80', 'c_r_50', 'c_r_99', 'c_r_20', 'c_r_80', 'c_c2080', 'c_c5090']
[12]:
# List all Sersic indices available
pc.unique_grid_values('n')
[12]:
array([0.5, 0.6, 0.7, 0.8, 0.9, 1. , 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7,
       1.8, 1.9, 2. , 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9, 3. ,
       3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 4. ])
[13]:
# Provide rows for a grid key's value
# For example all rows with n=1
pc.filter_grid('n', 1.)
[13]:
Table length=9
nr_effsersic_r_20sersic_r_80sersic_r_99sersic_L_infp02p03p04p05p0502p0302u_epsilonu_epsilon_50u_epsilon_80u_r_50u_r_99u_r_20u_r_80u_c2080u_c5090c_epsilonc_epsilon_50c_epsilon_80c_r_50c_r_99c_r_20c_r_80c_c2080c_c5090
float64int64float64float64float64float64float64float64float64float64float64float64float64float64float64float64float64float64float64float64float64float64float64float64float64float64float64float64float64float64
1.083.90313782739770114.0227176980418831.64233430860640414275.6645480229319.07981596319263715.62112422484496812.96059211842368310.77515503100621.240753269580470.434309476344750762.00.42297127280352280.75805200251625088.07021404280856238.1562312462492563.970994198839768314.4634926985397082.8068696403766741.85449053876126541.66359685661747410.42001467812958690.73949959834924058.0138027605521131.7441488297659553.952190438087617614.2942588517703552.79161889644428341.8240139508932398
1.0104.878922284247126517.5283971225523539.55291788575800622305.72585628583323.400080016003219.0200040008001615.687337467493512.9021804360872171.29277115646874360.450033692590721352.00.43110184053275430.772057754943279410.08781756351270346.793158631726344.94198839767953618.066213242648532.81482705301533141.85113643921821041.69343988090580220.42807560460603360.751604395034162310.01700340068013539.617323464692944.91838367673534717.853770754150832.79953774787607261.8226683398980135
1.0125.85470674109655121.0340765470628247.46350146290960532120.2452330515927.6903380676135222.42688537707541518.39347869573914815.0466093218643721.3244480657732730.457796473119775952.00.436188811188811250.781894758134427712.07821564312862655.368473694738955.94258851770354121.6509301860372082.80750450076762851.85310916162788471.71610492497210190.43413714384788770.760203713885892312.02140428085617347.528505701140235.914182836567313521.423684736947392.79499711107405171.821616418480862
1.0146.83049119794597724.53975597157328255.37408504006110443719.2226783202332.0036007201440325.8567713542708521.11302260452090417.2044408881776331.34779140018676750.46312274197825932.00.440057255009813350.789725350968209714.08341668333666763.992998599719956.91078215643128625.274054810962192.8157385987977611.8519497924659291.73157518905972350.43798207343142520.767941380162800614.01700340068013555.425685137027416.87757551510302124.97519503900782.80036760426160441.8225760596660439
1.0167.80627565479540228.0454353960837663.2846686172128157102.6581920917236.33306661332266429.26305261052210623.8565713142628519.3196639327865581.37151243766916320.469912134928263672.00.442589013868930570.794515193058377416.08061612322464472.679935987197447.88217643528705828.867173434686942.8187905477722011.85264268668656971.74266622084752520.440518859873698650.773089832150777316.00540108021604663.315663132626537.88217643528705828.5663132626525322.7960402125175631.8257252368835972
1.0188.78206011164482831.5511148205942471.1952521943645472270.551774366140.6281256251250232.7065413082616526.5853170634126821.4842968593718741.38352821020634950.47096083204250942.00.445657311669128530.798980797636632218.1062212442488581.267653530706148.8951790358071632.461092218443692.8110421738328831.85023349796317631.75292200876845520.4427129492860660.777394679842391217.98659731946389371.219243848769758.83536707341468432.1022204440888152.8015523765699151.8275981446613496
1.0209.75784456849425335.056794245104779.1058357715160189222.9034251433344.9489897979595936.0672134426885429.28585717143428723.5847169433886781.4004463366201990.478036728483634432.00.44805963506898090.802016021361815820.1398279655931289.880576115223059.85217043408681736.04980996199242.81685531753627271.84551825507415361.76023288869546230.44539830885625280.78015912308073720.02020404080816479.114422884576919.85217043408681735.690938187637532.795130240035691.8223189749430866
1.02210.7336290253436838.5624736696151887.01641934866778107959.7131444234149.2698539707941639.487897579515931.9863972794558925.745149029805961.40942932467358250.48058631752742632.00.448826634185952140.804518879415347222.1136227245449198.5533106621324310.86897379475895239.638527705541112.8096448672018151.85003252328300821.76627969531400320.4463987007714170.783149352154375321.99399879975995487.0096019203840910.80916183236647439.279655931186242.8018782794625481.8264491340662061
1.02411.70941348219310342.0681530941256494.92700292581921128480.9809322063753.5907181436287342.9085817163432734.6869373874774927.9055811162232461.41699252999296240.482727085437328952.00.45058603956700260.806618141097424524.147229445889177107.1662332466493311.82596519303860743.227245449089822.8146048281835061.84611710947247861.77151308613264020.44835386338185890.785526302270947924.0276055211042294.9645929185837211.76615323064612942.808561712342472.8044806834505171.8221464723407068
[14]:
# Plotting relations
pc_c_c2080_list = np.sort(pc.unique_grid_values('c_c2080')) # Get corrected c_c2080
approx_n_values = pf.PetroApprox.c2080_to_n(pc_c_c2080_list) # Get n from PetroApprox for comparison

# Plot
plt.scatter( pc.grid['c_c2080'], pc.grid['n'], color='black')
plt.plot(pc_c_c2080_list, approx_n_values, color='red')

plt.xlabel('Corrected $C_{2080}$')
plt.ylabel('n')
plt.show()
_images/correction_grids_22_0.png

Correcting a Petrosian Profile

In the Photometry Chapter we constructed a curve of growth for the football shaped galaxy:

[15]:
import numpy as np
from astropy.table import Table
phot_table = Table.read('data/abell_2744_galaxy_f105w_photometry.ecsv') # Read table

# Load data
r_list = np.array(phot_table['r_list'])
flux_arr = np.array(phot_table['flux_arr'])
area_arr = np.array(phot_table['area_arr'])
error_arr = np.array(phot_table['error_arr'])


# Make Petrosian profile
p = pf.Petrosian(r_list, area_arr, flux_arr, flux_err=error_arr)

p.plot()
plt.show()
_images/correction_grids_24_0.png
  1. Correct Profile:

    • Simply use the correct(p) function to correct the profile.

    • Use plot_correction function to see the closest value.

    • The parameters used for correction are derived directly from the grid. Specifically:

      • 'p02': Represents the Petrosian radius \(P_{02} = R(\eta_{0.2})\).

      • 'u_r_50': Stands for the uncorrected half-light radius.

      • 'u_c2080': Corresponds to the uncorrected concentration index.

[16]:
pc = pf.PetrosianCorrection.read('data/f105w_psf_corr.ecsv')

# Plot grid and uncorrected profile on grid (p)
pc.plot_correction(p)
plt.show()

# Pass uncorrected p to the correct function
p_corrected = pc.correct(p)

# Plot corrected profile
p_corrected.plot()
plt.show()
_images/correction_grids_26_0.png
_images/correction_grids_26_1.png
  1. Estimating Parameters:

    • The method estimate_n(p) will give an estimated Sérsic index n based on the half-light radius and c2080 computed using the default epsilon value.

    • The method estimate_epsilon(p) will provide a corrected epsilon value given the half-light radius and c2080 computed with the default epsilon.

[17]:
n = pc.estimate_n(p)
n
[17]:
2.1
[18]:
corr_epsilon = pc.estimate_epsilon(p)
corr_epsilon
[18]:
2.227805629021434