Skip to content

utils.py

This module contains utility functions used by the image ingestion section of the pipeline.

calc_condon_flux_errors(row, theta_B, theta_b, alpha_maj1=2.5, alpha_min1=0.5, alpha_maj2=0.5, alpha_min2=2.5, alpha_maj3=1.5, alpha_min3=1.5, clean_bias=0.0, clean_bias_error=0.0, frac_flux_cal_error=0.0)

The following code for this function taken from the TraP with a few modifications.

Returns the errors on parameters from Gaussian fits according to the Condon (PASP 109, 166 (1997)) formulae. These formulae are not perfect, but we'll use them for the time being. (See Refregier and Brown (astro-ph/9803279v1) for a more rigorous approach.) It also returns the corrected peak. The peak can be corrected for the overestimate due to the local noise gradient, but this is currently not used in the function.

Parameters:

Name Type Description Default
row Series

The row containing the component information from the Selavy component catalogue.

required
theta_B float

The major axis size of the restoring beam of the image (degrees).

required
theta_b float

The minor axis size of the restoring beam of the image (degrees).

required
alpha_maj1 float

The alpha_M exponent value for x_0.

2.5
alpha_min1 float

The alpha_m exponent value for x_0.

0.5
alpha_maj2 float

The alpha_M exponent value for y_0.

0.5
alpha_min2 float

The alpha_m exponent value for y_0.

2.5
alpha_maj3 float

The alpha_M exponent value for the amplitude error.

1.5
alpha_min3 float

The alpha_m exponent value for the amplitude error.

1.5
clean_bias float

Clean bias value used in the peak flux correction (not currently used).

0.0
clean_bias_error float

The error of the clean bias value used in the peak flux correction (not currently used).

0.0
frac_flux_cal_error float

Flux calibration error value. (Unsure of exact meaning, refer to TraP).

0.0

Returns:

Type Description
float

Peak flux error (Jy).

float

Integrated flux error (Jy).

float

Major axis error (deg).

float

Minor axis error (deg).

float

Position angle error (deg).

float

Right ascension error (deg).

float

Declination error (deg).

Source code in vast_pipeline/image/utils.py
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
def calc_condon_flux_errors(
    row: pd.Series,
    theta_B: float,
    theta_b: float,
    alpha_maj1: float = 2.5,
    alpha_min1: float = 0.5,
    alpha_maj2: float = 0.5,
    alpha_min2: float = 2.5,
    alpha_maj3: float = 1.5,
    alpha_min3: float = 1.5,
    clean_bias: float = 0.0,
    clean_bias_error: float = 0.0,
    frac_flux_cal_error: float = 0.0
) -> Tuple[float, float, float, float, float, float, float]:
    """
    The following code for this function taken from the TraP with a few
    modifications.

    Returns the errors on parameters from Gaussian fits according to
    the Condon (PASP 109, 166 (1997)) formulae.
    These formulae are not perfect, but we'll use them for the
    time being.  (See Refregier and Brown (astro-ph/9803279v1) for
    a more rigorous approach.) It also returns the corrected peak.
    The peak can be corrected for the overestimate due to the local
    noise gradient, but this is currently not used in the function.

    Args:
        row (pd.Series):
            The row containing the component information from the Selavy
            component catalogue.
        theta_B (float):
            The major axis size of the restoring beam of the image (degrees).
        theta_b (float):
            The minor axis size of the restoring beam of the image (degrees).
        alpha_maj1 (float):
            The alpha_M exponent value for x_0.
        alpha_min1 (float):
            The alpha_m exponent value for x_0.
        alpha_maj2 (float):
            The alpha_M exponent value for y_0.
        alpha_min2 (float):
            The alpha_m exponent value for y_0.
        alpha_maj3 (float):
            The alpha_M exponent value for the amplitude error.
        alpha_min3 (float):
            The alpha_m exponent value for the amplitude error.
        clean_bias (float):
            Clean bias value used in the peak flux correction (not currently
             used).
        clean_bias_error (float):
            The error of the clean bias value used in the peak flux correction
            (not currently used).
        frac_flux_cal_error (float):
            Flux calibration error value. (Unsure of exact meaning, refer to
            TraP).

    Returns:
        Peak flux error (Jy).
        Integrated flux error (Jy).
        Major axis error (deg).
        Minor axis error (deg).
        Position angle error (deg).
        Right ascension error (deg).
        Declination error (deg).
    """

    major = row.bmaj / 3600.  # degrees
    minor = row.bmin / 3600.  # degrees
    theta = np.deg2rad(row.pa)
    flux_peak = row['flux_peak']
    flux_int = row['flux_int']
    snr = row['snr']
    noise = row['local_rms']

    variables = [
        theta_B,
        theta_b,
        major,
        minor,
        flux_peak,
        flux_int,
        snr,
        noise
    ]

    # return 0 if the source is unrealistic. Should be rare
    # given that these sources are also filtered out before hand.
    if 0.0 in variables:
        logger.debug(variables)
        return 0., 0., 0., 0., 0., 0., 0.

    try:

        rho_sq1 = ((major * minor / (4. * theta_B * theta_b)) *
                   (1. + (theta_B / major)**2)**alpha_maj1 *
                   (1. + (theta_b / minor)**2)**alpha_min1 *
                   snr**2)
        rho_sq2 = ((major * minor / (4. * theta_B * theta_b)) *
                   (1. + (theta_B / major)**2)**alpha_maj2 *
                   (1. + (theta_b / minor)**2)**alpha_min2 *
                   snr**2)
        rho_sq3 = ((major * minor / (4. * theta_B * theta_b)) *
                   (1. + (theta_B / major)**2)**alpha_maj3 *
                   (1. + (theta_b / minor)**2)**alpha_min3 *
                   snr**2)

        rho1 = np.sqrt(rho_sq1)
        rho2 = np.sqrt(rho_sq2)
        rho3 = np.sqrt(rho_sq3)

        # here we change the TraP code slightly and base it
        # purely on Condon 97 and not the NVSS paper.
        denom1 = np.sqrt(4. * np.log(2.)) * rho1
        denom2 = np.sqrt(4. * np.log(2.)) * rho2

        # these are the 'xo' and 'y0' errors from Condon
        error_par_major = major / denom1
        error_par_minor = minor / denom2

        # ra and dec errors
        errorra = np.sqrt((error_par_major * np.sin(theta))**2 +
                          (error_par_minor * np.cos(theta))**2)
        errordec = np.sqrt((error_par_major * np.cos(theta))**2 +
                           (error_par_minor * np.sin(theta))**2)

        errormajor = np.sqrt(2) * major / rho1
        errorminor = np.sqrt(2) * minor / rho2

        if major > minor:
            errortheta = 2.0 * (major * minor / (major**2 - minor**2)) / rho2
        else:
            errortheta = np.pi
        if errortheta > np.pi:
            errortheta = np.pi

        # correction to flux peak not currently used
        # but might be in the future.
        # Do not remove!
        # flux_peak += -noise**2 / flux_peak + clean_bias

        errorpeaksq = ((frac_flux_cal_error * flux_peak)**2 +
                       clean_bias_error**2 +
                       2. * flux_peak**2 / rho_sq3)

        errorpeak = np.sqrt(errorpeaksq)

        help1 = (errormajor / major)**2
        help2 = (errorminor / minor)**2
        help3 = theta_B * theta_b / (major * minor)
        help4 = np.sqrt(errorpeaksq / flux_peak**2 + help3 * (help1 + help2))
        errorflux = np.abs(flux_int) * help4

        # need to return flux_peak if used.
        return errorpeak, errorflux, errormajor, errorminor, errortheta, errorra, errordec

    except Exception as e:
        logger.debug(
            "Error in the calculation of Condon errors for a source",
            exc_info=True)
        return 0., 0., 0., 0., 0., 0., 0.

calc_error_radius(ra, ra_err, dec, dec_err)

Using the fitted errors from selavy, this function estimates the largest on sky angular size of the uncertainty. The four different combinations of the errors are analysed and the maximum is returned. Logic is taken from the TraP, where this is also used. Function has been vectorised for pandas. All inputs are in degrees.

Parameters:

Name Type Description Default
ra float

The right ascension of the coordinate (degrees).

required
ra_err float

The error associated with the ra value (degrees).

required
dec float

The declination of the coordinate (degrees).

required
dec_err float

The error associated with the declination value (degrees).

required

Returns:

Type Description
float

The calculated error radius (degrees).

Source code in vast_pipeline/image/utils.py
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
def calc_error_radius(ra, ra_err, dec, dec_err) -> float:
    """
    Using the fitted errors from selavy, this function
    estimates the largest on sky angular size of the
    uncertainty. The four different combinations of the
    errors are analysed and the maximum is returned.
    Logic is taken from the TraP, where this is also
    used. Function has been vectorised for pandas. All inputs are in
    degrees.

    Args:
        ra (float): The right ascension of the coordinate (degrees).
        ra_err (float): The error associated with the ra value (degrees).
        dec (float): The declination of the coordinate (degrees).
        dec_err (float): The error associated with the declination
            value (degrees).

    Returns:
        The calculated error radius (degrees).
    """
    ra_1 = np.deg2rad(ra)
    dec_1 = np.deg2rad(dec)

    ra_offsets = [
        (ra + ra_err),
        (ra + ra_err),
        (ra - ra_err),
        (ra - ra_err)
    ]

    dec_offsets = [
        (dec + dec_err),
        (dec - dec_err),
        (dec + dec_err),
        (dec - dec_err)
    ]

    seps = [
        np.rad2deg(on_sky_sep(
            ra_1,
            np.deg2rad(i),
            dec_1,
            np.deg2rad(j)
        )) for i, j in zip(ra_offsets, dec_offsets)
    ]

    seps = np.column_stack(seps)

    return np.amax(seps, 1)

on_sky_sep(ra_1, ra_2, dec_1, dec_2)

Simple on sky distance between two RA and Dec coordinates. Needed for fast calculation on dataframes as astropy is slow. All units are radians.

Parameters:

Name Type Description Default
ra_1 float

The right ascension of coodinate 1 (radians).

required
ra_2 float

The right ascension of coodinate 2 (radians).

required
dec_1 float

The declination of coodinate 1 (radians).

required
dec_2 float

The declination of coodinate 2 (radians).

required

Returns:

Type Description
float

The on-sky separation distance between the two coodinates (radians).

Source code in vast_pipeline/image/utils.py
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
def on_sky_sep(ra_1, ra_2, dec_1, dec_2) -> float:
    """
    Simple on sky distance between two RA and Dec coordinates.
    Needed for fast calculation on dataframes as astropy is
    slow. All units are radians.

    Args:
        ra_1 (float): The right ascension of coodinate 1 (radians).
        ra_2 (float): The right ascension of coodinate 2 (radians).
        dec_1 (float): The declination of coodinate 1 (radians).
        dec_2 (float): The declination of coodinate 2 (radians).

    Returns:
        The on-sky separation distance between the two coodinates (radians).
    """
    separation = (
        np.sin(dec_1) * np.sin(dec_2) +
        np.cos(dec_1) * np.cos(dec_2) * np.cos(ra_1 - ra_2)
    )
    # fix errors on separation values over 1
    separation[separation > 1.] = 1.

    return np.arccos(separation)

open_fits(fits_path, memmap=True)

This function opens both compressed and uncompressed fits files.

Parameters:

Name Type Description Default
fits_path Union[str, Path]

Path to the fits file

required
memmap Optional[bool]

Open the fits file with mmap.

True

Returns:

Type Description

HDUList loaded from the fits file

Source code in vast_pipeline/image/utils.py
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
def open_fits(fits_path: Union[str, Path], memmap: Optional[bool] = True):
    """
    This function opens both compressed and uncompressed fits files.

    Args:
        fits_path: Path to the fits file
        memmap: Open the fits file with mmap.

    Returns:
        HDUList loaded from the fits file
    """

    if isinstance(fits_path, Path):
        fits_path = str(fits_path)

    hdul = fits.open(fits_path, memmap=memmap)

    # This is a messy way to check, but I can't think of a better one
    if len(hdul) == 1:
        return hdul
    elif type(hdul[1]) == fits.hdu.compressed.CompImageHDU:
        return fits.HDUList(hdul[1:])
    else:
        return hdul