|
| 1 | +# Frankenstein: 1D disc brightness profile reconstruction from Fourier data |
| 2 | +# using non-parametric Gaussian Processes |
| 3 | +# |
| 4 | +# Copyright (C) 2019-2020 R. Booth, J. Jennings, M. Tazzari |
| 5 | +# |
| 6 | +# This program is free software: you can redistribute it and/or modify |
| 7 | +# it under the terms of the GNU General Public License as published by |
| 8 | + |
| 9 | +# the Free Software Foundation, either version 3 of the License, or |
| 10 | +# (at your option) any later version. |
| 11 | +# |
| 12 | +# This program is distributed in the hope that it will be useful, |
| 13 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | +# GNU General Public License for more details. |
| 16 | +# |
| 17 | +# You should have received a copy of the GNU General Public License |
| 18 | +# along with this program. If not, see <https://www.gnu.org/licenses/> |
| 19 | +# |
| 20 | +"""This module contains methods for fitting a radial brightness profile to a set |
| 21 | + of deprojected visibities. Routines in this file assume that the emission is |
| 22 | + optically thin with a Gaussian vertical structure. |
| 23 | +""" |
| 24 | +import abc |
| 25 | +from collections import defaultdict |
| 26 | +import logging |
| 27 | +import numpy as np |
| 28 | + |
| 29 | +from frank.radial_fitters import FourierBesselFitter, FrankFitter |
| 30 | + |
| 31 | +class FourierBesselDebrisFitter(FourierBesselFitter): |
| 32 | + """ |
| 33 | + Fourier-Bessel series optically-thin model for fitting visibilities. |
| 34 | +
|
| 35 | + The brightness model is :math:`I(R, z) = I(R) exp(-z^2/2H(R)^2)`, where |
| 36 | + :math:`H(R)` is the (known) scale-height. |
| 37 | +
|
| 38 | + Parameters |
| 39 | + ---------- |
| 40 | + Rmax : float, unit = arcsec |
| 41 | + Radius of support for the functions to transform, i.e., |
| 42 | + f(r) = 0 for R >= Rmax |
| 43 | + N : int |
| 44 | + Number of collocation points |
| 45 | + geometry : SourceGeometry object |
| 46 | + Geometry used to deproject the visibilities before fitting |
| 47 | + scale_height : function R --> H |
| 48 | + Specifies the thickness of disc as a function of radius. Both |
| 49 | + units should be in arcsec. |
| 50 | + nu : int, default = 0 |
| 51 | + Order of the discrete Hankel transform (DHT) |
| 52 | + block_data : bool, default = True |
| 53 | + Large temporary matrices are needed to set up the data. If block_data |
| 54 | + is True, we avoid this, limiting the memory requirement to block_size |
| 55 | + elements. |
| 56 | + block_size : int, default = 10**5 |
| 57 | + Size of the matrices if blocking is used |
| 58 | + verbose : bool, default = False |
| 59 | + Whether to print notification messages |
| 60 | + """ |
| 61 | + |
| 62 | + def __init__(self, Rmax, N, geometry, scale_height, nu=0, block_data=True, |
| 63 | + block_size=10 ** 5, verbose=True): |
| 64 | + |
| 65 | + # All functionality is provided by the base class. |
| 66 | + # FourierBesselDebrisFitter is just a sub-set of FourierBesselFitter |
| 67 | + super(FourierBesselDebrisFitter, self).__init__( |
| 68 | + Rmax, N, geometry, nu=nu, block_data=block_data, |
| 69 | + assume_optically_thick=False, scale_height=scale_height, |
| 70 | + block_size=block_size, verbose=verbose |
| 71 | + ) |
| 72 | + |
| 73 | +class FrankDebrisFitter(FrankFitter): |
| 74 | + """ |
| 75 | + Fit a Gaussian process model using the Discrete Hankel Transform of |
| 76 | + Baddour & Chouinard (2015). |
| 77 | +
|
| 78 | + The brightness model is :math:`I(R, z) = I(R) exp(-z^2/2H(R)^2)`, where |
| 79 | + :math:`H(R)` is the (known) scale-height. |
| 80 | +
|
| 81 | + The GP model is based upon Oppermann et al. (2013), which use a maximum |
| 82 | + a posteriori estimate for the power spectrum as the GP prior for the |
| 83 | + real-space coefficients. |
| 84 | +
|
| 85 | + Parameters |
| 86 | + ---------- |
| 87 | + Rmax : float, unit = arcsec |
| 88 | + Radius of support for the functions to transform, i.e., f(r) = 0 for |
| 89 | + R >= Rmax. |
| 90 | + N : int |
| 91 | + Number of collaction points |
| 92 | + geometry : SourceGeometry object |
| 93 | + Geometry used to deproject the visibilities before fitting |
| 94 | + scale_height : function R --> H |
| 95 | + Specifies the thickness of disc as a function of radius. Both |
| 96 | + units should be in arcsec. |
| 97 | + nu : int, default = 0 |
| 98 | + Order of the discrete Hankel transform, given by J_nu(r) |
| 99 | + block_data : bool, default = True |
| 100 | + Large temporary matrices are needed to set up the data. If block_data |
| 101 | + is True, we avoid this, limiting the memory requirement to block_size |
| 102 | + elements |
| 103 | + block_size : int, default = 10**5 |
| 104 | + Size of the matrices if blocking is used |
| 105 | + alpha : float >= 1, default = 1.05 |
| 106 | + Order parameter of the inverse gamma prior for the power spectrum |
| 107 | + coefficients |
| 108 | + p_0 : float >= 0, default = None, unit=Jy^2 |
| 109 | + Scale parameter of the inverse gamma prior for the power spectrum |
| 110 | + coefficients. If not provided p_0 = 1e-15 (method="Normal") or |
| 111 | + 1e-35 (method="LogNormal") will be used. |
| 112 | + weights_smooth : float >= 0, default = 1e-4 |
| 113 | + Spectral smoothness prior parameter. Zero is no smoothness prior |
| 114 | + tol : float > 0, default = 1e-3 |
| 115 | + Tolerence for convergence of the power spectrum iteration |
| 116 | + method : string, default="Normal" |
| 117 | + Model used for the brightness reconstrution. This must be one of |
| 118 | + "Normal" of "LogNormal". |
| 119 | + I_scale : float, default = 1e5, unit= Jy/Sr |
| 120 | + Brightness scale. Only used in the LogNormal model. Notet the |
| 121 | + LogNormal model produces I(Rmax) = I_scale. |
| 122 | + max_iter: int, default = 2000 |
| 123 | + Maximum number of fit iterations |
| 124 | + check_qbounds: bool, default = True |
| 125 | + Whether to check if the first (last) collocation point is smaller |
| 126 | + (larger) than the shortest (longest) deprojected baseline in the dataset |
| 127 | + store_iteration_diagnostics: bool, default = False |
| 128 | + Whether to store the power spectrum parameters and brightness profile |
| 129 | + for each fit iteration |
| 130 | + verbose: |
| 131 | + Whether to print notification messages |
| 132 | +
|
| 133 | + References |
| 134 | + ---------- |
| 135 | + Baddour & Chouinard (2015) |
| 136 | + DOI: https://doi.org/10.1364/JOSAA.32.000611 |
| 137 | + Oppermann et al. (2013) |
| 138 | + DOI: https://doi.org/10.1103/PhysRevE.87.032136 |
| 139 | + """ |
| 140 | + |
| 141 | + def __init__(self, Rmax, N, geometry, scale_height, nu=0, block_data=True, |
| 142 | + block_size=10 ** 5, alpha=1.05, p_0=None, weights_smooth=1e-4, |
| 143 | + tol=1e-3, method='Normal', I_scale=1e5, max_iter=2000, check_qbounds=True, |
| 144 | + store_iteration_diagnostics=False, verbose=True): |
| 145 | + |
| 146 | + # All functionality is provided by the base class. FrankDebrisFitter is just a |
| 147 | + # sub-set of FrankFitter |
| 148 | + super(FrankDebrisFitter, self).__init__( |
| 149 | + Rmax, N, geometry, nu=nu, block_data=block_data, |
| 150 | + block_size=block_size, alpha=alpha, p_0=p_0, weights_smooth=weights_smooth, |
| 151 | + tol=tol, method=method, I_scale=I_scale, max_iter=max_iter, |
| 152 | + check_qbounds=check_qbounds, store_iteration_diagnostics=store_iteration_diagnostics, |
| 153 | + assume_optically_thick=False, scale_height=scale_height, verbose=verbose) |
0 commit comments