23#include <boost/algorithm/string.hpp>
29#include <CCfits/CCfits>
33namespace po = boost::program_options;
38namespace fs = boost::filesystem;
57 CCfits::ExtHDU& psf_data = pFits->extension(
"PSF_DATA");
60 psf_data.readKey(
"POLNAXIS", n_components);
62 double pixel_sampling;
63 psf_data.readKey(
"PSF_SAMP", pixel_sampling);
67 for (
int i = 0; i < n_components; ++i) {
70 psf_data.readKey(
"POLGRP" + index_str, components[i].group_id);
71 psf_data.readKey(
"POLNAME" + index_str, components[i].name);
72 psf_data.readKey(
"POLZERO" + index_str, components[i].offset);
73 psf_data.readKey(
"POLSCAL" + index_str, components[i].scale);
76 --components[i].group_id;
80 psf_data.readKey(
"POLNGRP", n_groups);
84 for (
int i = 0; i < n_groups; ++i) {
87 psf_data.readKey(
"POLDEG" + index_str, group_degrees[i]);
90 int width, height, n_coeffs, n_pixels;
91 psf_data.readKey(
"PSFAXIS1", width);
92 psf_data.readKey(
"PSFAXIS2", height);
93 psf_data.readKey(
"PSFAXIS3", n_coeffs);
95 if (width != height) {
96 throw Elements::Exception() <<
"Non square PSFEX format PSF (" << width <<
'X' << height <<
')';
102 n_pixels = width * height;
105 psf_data.column(
"PSF_MASK").readArrays(all_data, 0, 0);
106 auto& raw_coeff_data = all_data[0];
110 for (
int i = 0; i < n_coeffs; ++i) {
111 auto offset =
std::begin(raw_coeff_data) + i * n_pixels;
115 logger.
debug() <<
"Loaded variable PSF " << pFits->name() <<
" (" << width <<
", " << height <<
") with " << n_coeffs
118 ll <<
"Components: ";
119 for (
auto c : components) {
126 return std::make_shared<VariablePsf>(pixel_sampling, components, group_degrees, coefficients);
127 }
catch (CCfits::FITS::NoSuchHDU&) {
129 }
catch (CCfits::FitsException &
e) {
137 double pixel_sampling;
139 image_hdu.readKey(
"SAMPLING", pixel_sampling);
141 catch (CCfits::HDU::NoSuchKeyword&) {
145 if (image_hdu.axis(0) != image_hdu.axis(1)) {
147 << image_hdu.axis(1) <<
')';
150 auto size = image_hdu.axis(0);
153 image_hdu.read(data);
157 logger.
debug() <<
"Loaded image PSF(" << size <<
", " << size <<
") with sampling step " << pixel_sampling;
159 return std::make_shared<VariablePsf>(pixel_sampling, kernel);
167 if (boost::to_upper_copy(fs::path(filename).filename().
string())==
"NOPSF") {
174 auto& image_hdu = pFits->pHDU();
176 auto axes = image_hdu.axes();
179 if (hdu_number == 1) {
182 auto& extension = pFits->extension(hdu_number - 1);
189 }
catch (CCfits::FITS::NoSuchHDU&
e) {
194 }
catch (CCfits::FitsException&
e) {
200 int size = int(fwhm / pixel_sampling + 1) * 6 + 1;
204 double sigma_squared = (fwhm / (pixel_sampling * 2.355)) * (fwhm / (pixel_sampling * 2.355));
207 for (
int y = 0;
y < size;
y++) {
208 for (
int x = 0;
x < size;
x++) {
209 double sx = (
x - size / 2);
210 double sy = (
y - size / 2);
211 double pixel_value =
exp(-(sx * sx + sy * sy) / (2 * sigma_squared));
212 total += pixel_value;
213 kernel->setValue(
x,
y, pixel_value);
216 for (
int y = 0;
y < size;
y++) {
217 for (
int x = 0;
x < size;
x++) {
218 kernel->setValue(
x,
y, kernel->getValue(
x,
y) / total);
222 logger.
info() <<
"Using gaussian PSF(" << fwhm <<
") with pixel sampling step size " << pixel_sampling <<
" (size " << size <<
")";
224 return std::make_shared<VariablePsf>(pixel_sampling, kernel);
228 return {{
"Variable PSF", {
230 "Psf file (PSFEx/psfStack/image/NOPSF)."},
232 "Generate a gaussian PSF with the given full-width half-maximum (in pixels)"},
234 "Generate a gaussian PSF with the given pixel sampling step size"}
249 logger.
debug() <<
"Provided by user: " << psf_file;
250 if (boost::to_upper_copy(psf_file) ==
"NOPSF"){
std::shared_ptr< DependentParameter< std::shared_ptr< EngineParameter > > > x
std::shared_ptr< DependentParameter< std::shared_ptr< EngineParameter > > > y
void debug(const std::string &logMessage)
static Logging getLogger(const std::string &name="")
void info(const std::string &logMessage)
static Elements::Logging logger