Citlali
Loading...
Searching...
No Matches
kernel.h
Go to the documentation of this file.
1#pragma once
2
3#include <string>
4
5#include <boost/math/special_functions/bessel.hpp>
6
10
11namespace timestream {
12
13class Kernel {
14public:
15 std::string filepath, type;
16 std::vector<std::string> img_ext_names;
17
18 // input kernel images
19 std::vector<Eigen::MatrixXd> images;
20
21 // sigma and fwhm from config
23
24 // limit on distance to calc sigma to
25 double sigma_limit = 3;
26
27 // map grouping
28 std::string map_grouping;
29
30 // initial setup
31 void setup(Eigen::Index);
32
33 // symmetric gaussian kernel
34 template<typename apt_t>
36 apt_t &);
37 // asymmetric elliptical gaussian kernel
38 template<typename apt_t>
40 // airy pattern kernel
41 template<typename apt_t>
43
44 // kernel from fits file
45 template<typename apt_t, typename Derived>
47 apt_t &, double, Eigen::DenseBase<Derived> &);
48};
49
50void Kernel::setup(Eigen::Index n_maps) {
51 if (type == "fits") {
52 if (img_ext_names.size()!=n_maps && img_ext_names.size()!=1) {
53 SPDLOG_INFO("mismatch for number of kernel images");
54 std::exit(EXIT_FAILURE);
55 }
56
58 for (auto & img_ext_name : img_ext_names) {
59 images.push_back(fits_io.get_hdu(img_ext_name));
60 }
61 }
62}
63
64template<typename apt_t>
66
67 // dimensions of scan
68 Eigen::Index n_dets = in.scans.data.cols();
69 Eigen::Index n_pts = in.scans.data.rows();
70
71 // resize kernel to match data size
72 in.kernel.data.resize(n_pts,n_dets);
73
74 double sigma = sigma_rad;
75
76 for (Eigen::Index i=0; i<n_dets; ++i) {
77 // calc tangent plane pointing
78 auto [lat, lon] = engine_utils::calc_det_pointing(in.tel_data.data, apt["x_t"](i), apt["y_t"](i),
79 pixel_axes, in.pointing_offsets_arcsec.data, map_grouping);
80
81 // distance to source to truncate it
82 auto dist = ((lat.array()).pow(2) + (lon.array()).pow(2)).sqrt();
83
84 // calculate stddev from apt table if config stddev <=0
85 if (sigma_rad <= 0) {
86 sigma = FWHM_TO_STD * ASEC_TO_RAD*(apt["a_fwhm"](i) + apt["b_fwhm"](i))/2;
87 }
88
89 // loop through samples and calculate
90 for (Eigen::Index j=0; j<n_pts; ++j) {
91 // truncate within radius
92 if (dist(j) <= sigma_limit*sigma) {
93 in.kernel.data(j,i) = exp(-0.5*pow(dist(j)/sigma,2));
94 }
95 else {
96 in.kernel.data(j,i) = 0;
97 }
98 }
99 }
100}
101
102template<typename apt_t>
103void Kernel::create_gaussian_kernel(TCData<TCDataKind::RTC, Eigen::MatrixXd> &in, std::string &pixel_axes, apt_t &apt) {
104
105 // dimensions of scan
106 Eigen::Index n_dets = in.scans.data.cols();
107 Eigen::Index n_pts = in.scans.data.rows();
108
109 // resize kernel to match data size
110 in.kernel.data.resize(n_pts,n_dets);
111
112 // get parameters for current detector
113 double amp = 1.0;
114 double off_lat = 0.0;
115 double off_lon = 0.0;
116
117 // beam standard deviations
118 double sigma_lat = sigma_rad;
119 double sigma_lon = sigma_rad;
120
121 for (Eigen::Index i=0; i<n_dets; ++i) {
122 // calc tangent plane pointing
123 auto [lat, lon] = engine_utils::calc_det_pointing(in.tel_data.data, apt["x_t"](i), apt["y_t"](i),
124 pixel_axes, in.pointing_offsets_arcsec.data, map_grouping);
125
126 // distance to source to truncate it
127 auto dist = ((lat.array()).pow(2) + (lon.array()).pow(2)).sqrt();
128
129 // calculate stddev from apt table if config stddev <=0
130 if (sigma_rad <= 0) {
131 sigma_lat = FWHM_TO_STD * ASEC_TO_RAD * apt["b_fwhm"](i);
132 sigma_lon = FWHM_TO_STD * ASEC_TO_RAD * apt["a_fwhm"](i);
133 }
134
135 // rotation angle
136 double rot_ang = apt["angle"](i);
137
138 auto cost2 = cos(rot_ang) * cos(rot_ang);
139 auto sint2 = sin(rot_ang) * sin(rot_ang);
140 auto sin2t = sin(2. * rot_ang);
141 auto xstd2 = sigma_lon * sigma_lon;
142 auto ystd2 = sigma_lat * sigma_lat;
143 auto a = - 0.5 * ((cost2 / xstd2) + (sint2 / ystd2));
144 auto b = - 0.5 * ((sin2t / xstd2) - (sin2t / ystd2));
145 auto c = - 0.5 * ((sint2 / xstd2) + (cost2 / ystd2));
146
147 double sigma_limit_det = sigma_limit * (sigma_lat + sigma_lon)/2;
148
149 // make elliptical gaussian
150 for (Eigen::Index j=0; j<n_pts; ++j) {
151 // truncate within radius
152 if (dist(j) <= sigma_limit_det) {
153 in.kernel.data(j,i) = amp*exp(pow(lon(j) - off_lon, 2) * a +
154 (lon(j) - off_lon) * (lat(j) - off_lat) * b +
155 pow(lat(j) - off_lat, 2) * c);
156 }
157 else {
158 in.kernel.data(j,i) = 0;
159 }
160 }
161 }
162}
163
164template<typename apt_t>
165void Kernel::create_airy_kernel(TCData<TCDataKind::RTC, Eigen::MatrixXd> &in, std::string &pixel_axes, apt_t &apt) {
166
167 Eigen::Index n_dets = in.scans.data.cols();
168 Eigen::Index n_pts = in.scans.data.rows();
169
170 in.kernel.data.resize(n_pts,n_dets);
171
172 double fwhm = fwhm_rad;
173
174 // loop through detectors
175 for (Eigen::Index i=0; i<n_dets; ++i) {
176 // calc tangent plane pointing
177 auto [lat, lon] = engine_utils::calc_det_pointing(in.tel_data.data, apt["x_t"](i), apt["y_t"](i),
178 pixel_axes, in.pointing_offsets_arcsec.data, map_grouping);
179
180 // distance to source to truncate it
181 auto dist = ((lat.array()).pow(2) + (lon.array()).pow(2)).sqrt();
182
183 // get fwhm from apt if config file fwhm is <= 0
184 if (fwhm_rad <= 0) {
185 fwhm = ASEC_TO_RAD*(apt["a_fwhm"](i) + apt["b_fwhm"](i))/2;
186 }
187
188 // airy pattern factor
189 double factor = pi*(1.028/fwhm);
190
191 for (Eigen::Index j=0; j<n_pts; ++j) {
192 if (dist(j) <= sigma_limit*fwhm) {
193 in.kernel.data(j,i) = pow(2*boost::math::cyl_bessel_j(1,factor*dist(j))/(factor*dist(j)),2);
194 }
195 else {
196 in.kernel.data(j,i) = 0;
197 }
198 }
199 }
200}
201
202template<typename apt_t, typename Derived>
204 double pixel_size_rad, Eigen::DenseBase<Derived> &map_indices) {
205
206 Eigen::Index n_dets = in.scans.data.cols();
207 Eigen::Index n_pts = in.scans.data.rows();
208
209 in.kernel.data.resize(n_pts,n_dets);
210
211 Eigen::Index map_index = 0;
212
213 // loop through detectors
214 for (Eigen::Index i=0; i<n_dets; ++i) {
215 // calc tangent plane pointing
216 auto [lat, lon] = engine_utils::calc_det_pointing(in.tel_data.data, apt["x_t"](i), apt["y_t"](i),
217 pixel_axes, in.pointing_offsets_arcsec.data, map_grouping);
218
219 if (images.size() > 1) {
220 map_index = map_indices(i);
221 }
222
223 // get map buffer row and col indices for lat and lon vectors
224 Eigen::VectorXd irows = lat.array()/pixel_size_rad + (images[map_index].rows())/2.;
225 Eigen::VectorXd icols = lon.array()/pixel_size_rad + (images[map_index].cols())/2.;
226
227 for (Eigen::Index j = 0; j<n_pts; ++j) {
228 // row and col pixel for kernel image
229 Eigen::Index ir = irows(j);
230 Eigen::Index ic = icols(j);
231
232 // check if current sample is on the image and add to the timestream
233 if ((ir >= 0) && (ir < images[map_index].rows()) && (ic >= 0) && (ic < images[map_index].cols())) {
234 in.kernel.data(j,i) = images[map_index](ir,ic);
235 }
236 }
237 }
238}
239} // namespace timestream
Definition fits_io.h:10
auto get_hdu(std::string hdu_name)
Definition fits_io.h:82
Definition kernel.h:13
std::string type
Definition kernel.h:15
double sigma_rad
Definition kernel.h:22
double sigma_limit
Definition kernel.h:25
std::string filepath
Definition kernel.h:15
std::vector< std::string > img_ext_names
Definition kernel.h:16
void create_kernel_from_fits(TCData< TCDataKind::RTC, Eigen::MatrixXd > &, std::string &, apt_t &, double, Eigen::DenseBase< Derived > &)
Definition kernel.h:203
void create_symmetric_gaussian_kernel(TCData< TCDataKind::RTC, Eigen::MatrixXd > &, std::string &, apt_t &)
Definition kernel.h:65
std::vector< Eigen::MatrixXd > images
Definition kernel.h:19
std::string map_grouping
Definition kernel.h:28
void create_gaussian_kernel(TCData< TCDataKind::RTC, Eigen::MatrixXd > &, std::string &, apt_t &)
Definition kernel.h:103
double fwhm_rad
Definition kernel.h:22
void setup(Eigen::Index)
Definition kernel.h:50
void create_airy_kernel(TCData< TCDataKind::RTC, Eigen::MatrixXd > &, std::string &, apt_t &)
Definition kernel.h:165
#define FWHM_TO_STD
Definition constants.h:48
#define ASEC_TO_RAD
Definition constants.h:33
constexpr auto pi
Definition constants.h:6
auto calc_det_pointing(tel_data_t &tel_data, double az_off, double el_off, const std::string pixel_axes, pointing_offset_t &pointing_offsets, const std::string map_grouping)
Definition pointing.h:11
Definition clean.h:10
TC data class.
Definition timestream.h:55