SourceXtractorPlusPlus
0.21
SourceXtractor++, the next generation SExtractor
Loading...
Searching...
No Matches
SEImplementation
src
lib
Plugin
Psf
PsfPluginConfig.cpp
Go to the documentation of this file.
1
17
/*
18
* PsfPluginConfig.cpp
19
*
20
* Created on: Jun 25, 2018
21
* Author: Alejandro Álvarez Ayllón (greatly adapted from mschefer's code)
22
*/
23
#include <boost/algorithm/string.hpp>
24
25
#include "
SEImplementation/Plugin/Psf/PsfPluginConfig.h
"
26
#include "
SEFramework/Psf/VariablePsf.h
"
27
#include "
SEFramework/Psf/VariablePsfStack.h
"
28
#include "
SEImplementation/Plugin/Psf/PsfTask.h
"
29
#include <CCfits/CCfits>
30
#include <Configuration/ProgramOptionsHelper.h>
31
#include <ElementsKernel/Logging.h>
32
33
namespace
po = boost::program_options;
34
using
Euclid::Configuration::Configuration
;
35
36
static
auto
logger
=
Elements::Logging::getLogger
(
"PsfPlugin"
);
37
38
namespace
fs = boost::filesystem;
39
40
namespace
SourceXtractor
{
41
42
static
const
std::string
PSF_FILE
{
"psf-filename"
};
43
static
const
std::string
PSF_FWHM
{
"psf-fwhm"
};
44
static
const
std::string
PSF_PIXEL_SAMPLING
{
"psf-pixel-sampling"
};
45
46
/*
47
* Reading in a stacked PSF as it is being developed for co-added images in Euclid
48
*/
49
static
std::shared_ptr<VariablePsfStack>
readStackedPsf
(
std::unique_ptr<CCfits::FITS>
&
pFits
) {
50
logger
.debug() <<
"Loading a PSF stack file."
;
51
std::shared_ptr<VariablePsfStack>
act_stack
=
std::make_shared<VariablePsfStack>
(
std::move
(
pFits
));
52
return
act_stack
;
53
}
54
55
static
std::shared_ptr<VariablePsf>
readPsfEx
(
std::unique_ptr<CCfits::FITS>
&
pFits
) {
56
try
{
57
CCfits::ExtHDU&
psf_data
=
pFits
->extension(
"PSF_DATA"
);
58
59
int
n_components
;
60
psf_data
.readKey(
"POLNAXIS"
,
n_components
);
61
62
double
pixel_sampling
;
63
psf_data
.readKey(
"PSF_SAMP"
,
pixel_sampling
);
64
65
std::vector<VariablePsf::Component>
components
(
n_components
);
66
67
for
(
int
i
= 0;
i
<
n_components
; ++
i
) {
68
auto
index_str
=
std::to_string
(
i
+ 1);
69
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);
74
75
// Groups in the FITS file are indexed starting at 1, but we use a zero-based index
76
--
components
[
i
].group_id;
77
}
78
79
int
n_groups
;
80
psf_data
.readKey(
"POLNGRP"
,
n_groups
);
81
82
std::vector<int>
group_degrees
(
n_groups
);
83
84
for
(
int
i
= 0;
i
<
n_groups
; ++
i
) {
85
auto
index_str
=
std::to_string
(
i
+ 1);
86
87
psf_data
.readKey(
"POLDEG"
+
index_str
,
group_degrees
[
i
]);
88
}
89
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
);
94
95
if
(width != height) {
96
throw
Elements::Exception
() <<
"Non square PSFEX format PSF ("
<< width <<
'X'
<< height <<
')'
;
97
}
98
if
(width % 2 == 0) {
99
throw
Elements::Exception
() <<
"PSF kernel must have odd size"
;
100
}
101
102
n_pixels
= width * height;
103
104
std::vector<std::valarray<SeFloat>
>
all_data
;
105
psf_data
.column(
"PSF_MASK"
).readArrays(
all_data
, 0, 0);
106
auto
&
raw_coeff_data
=
all_data
[0];
107
108
std::vector<std::shared_ptr<VectorImage<SeFloat>
>>
coefficients
(
n_coeffs
);
109
110
for
(
int
i
= 0;
i
<
n_coeffs
; ++
i
) {
111
auto
offset =
std::begin
(
raw_coeff_data
) +
i
*
n_pixels
;
112
coefficients
[
i
] =
VectorImage<SeFloat>::create
(width, height, offset, offset +
n_pixels
);
113
}
114
115
logger
.debug() <<
"Loaded variable PSF "
<<
pFits
->name() <<
" ("
<< width <<
", "
<< height <<
") with "
<<
n_coeffs
116
<<
" coefficients"
;
117
auto
ll
=
logger
.debug();
118
ll
<<
"Components: "
;
119
for
(
auto
c
:
components
) {
120
ll
<<
c
.name <<
" "
;
121
if
(
PsfTask::component_value_getters
.
find
(
c
.name) ==
PsfTask::component_value_getters
.end()) {
122
throw
Elements::Exception
() <<
"Can not find a getter for the component "
<<
c
.name;
123
}
124
}
125
126
return
std::make_shared<VariablePsf>
(
pixel_sampling
,
components
,
group_degrees
,
coefficients
);
127
}
catch
(CCfits::FITS::NoSuchHDU&) {
128
throw
;
129
}
catch
(CCfits::FitsException &e) {
130
throw
Elements::Exception
() <<
"Error loading PSFEx file: "
<< e.message();
131
}
132
}
133
134
// templated to work around CCfits limitation that primary and extension HDUs are different classes
135
template
<
typename
T>
136
static
std::shared_ptr<VariablePsf>
readImage
(T& image_hdu) {
137
double
pixel_sampling
;
138
try
{
139
image_hdu.readKey(
"SAMPLING"
,
pixel_sampling
);
140
}
141
catch
(CCfits::HDU::NoSuchKeyword&) {
142
pixel_sampling
= 1.;
143
}
144
145
if
(image_hdu.axis(0) != image_hdu.axis(1)) {
146
throw
Elements::Exception
() <<
"Non square image PSF ("
<< image_hdu.axis(0) <<
'X'
147
<< image_hdu.axis(1) <<
')'
;
148
}
149
150
auto
size = image_hdu.axis(0);
151
152
std::valarray<double>
data{};
153
image_hdu.read(data);
154
auto
kernel
=
VectorImage<SeFloat>::create
(size, size);
155
std::copy
(
begin
(data),
end
(data),
kernel
->getData().begin());
156
157
logger
.debug() <<
"Loaded image PSF("
<< size <<
", "
<< size <<
") with sampling step "
<<
pixel_sampling
;
158
159
return
std::make_shared<VariablePsf>
(
pixel_sampling
,
kernel
);
160
}
161
164
std::shared_ptr<Psf>
PsfPluginConfig::readPsf
(
const
std::string
& filename,
int
hdu_number
) {
165
166
// check whether the filename points to a delta function as PSF or NOPSF
167
if
(boost::to_upper_copy(fs::path(filename).filename().
string
())==
"NOPSF"
) {
168
return
nullptr
;
169
}
170
171
try
{
172
// Read the HDU from the file
173
std::unique_ptr<CCfits::FITS>
pFits
{
new
CCfits::FITS(filename, CCfits::Read)};
174
auto
& image_hdu =
pFits
->pHDU();
175
176
auto
axes
= image_hdu.axes();
177
// PSF as image
178
if
(
axes
== 2) {
179
if
(
hdu_number
== 1) {
180
return
readImage
(image_hdu);
181
}
else
{
182
auto
&
extension
=
pFits
->extension(
hdu_number
- 1);
183
return
readImage
(
extension
);
184
}
185
}
else
{
186
try
{
187
// PSFEx format
188
return
readPsfEx
(
pFits
);
189
}
catch
(CCfits::FITS::NoSuchHDU& e) {
190
logger
.
debug
() <<
"Failed Reading a PsfEx file!"
;
191
return
readStackedPsf
(
pFits
);
192
}
193
}
194
}
catch
(CCfits::FitsException& e) {
195
throw
Elements::Exception
() <<
"Error loading PSF file: "
<< e.message();
196
}
197
}
198
199
std::shared_ptr<Psf>
PsfPluginConfig::generateGaussianPsf
(
SeFloat
fwhm
,
SeFloat
pixel_sampling
) {
200
int
size =
int
(
fwhm
/
pixel_sampling
+ 1) * 6 + 1;
201
auto
kernel
=
VectorImage<SeFloat>::create
(size, size);
202
203
// convert full width half maximum to standard deviation
204
double
sigma_squared
= (
fwhm
/ (
pixel_sampling
* 2.355)) * (
fwhm
/ (
pixel_sampling
* 2.355));
205
206
double
total = 0;
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
);
214
}
215
}
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);
219
}
220
}
221
222
logger
.
info
() <<
"Using gaussian PSF("
<<
fwhm
<<
") with pixel sampling step size "
<<
pixel_sampling
<<
" (size "
<< size <<
")"
;
223
224
return
std::make_shared<VariablePsf>
(
pixel_sampling
,
kernel
);
225
}
226
227
std::map<std::string, Configuration::OptionDescriptionList>
PsfPluginConfig::getProgramOptions
() {
228
return
{{
"Variable PSF"
, {
229
{
PSF_FILE
.c_str(), po::value<std::string>(),
230
"Psf file (PSFEx/psfStack/image/NOPSF)."
},
231
{
PSF_FWHM
.c_str(), po::value<double>(),
232
"Generate a gaussian PSF with the given full-width half-maximum (in pixels)"
},
233
{
PSF_PIXEL_SAMPLING
.c_str(), po::value<double>(),
234
"Generate a gaussian PSF with the given pixel sampling step size"
}
235
}}};
236
}
237
238
void
PsfPluginConfig::preInitialize
(
const
Euclid::Configuration::Configuration::UserValues
&
args
) {
239
// Fail if there is no PSF file, but PSF_FWHM is set and PSF_PIXEL_SAMPLING is not
240
if
(
args
.find(
PSF_FILE
) ==
args
.end() &&
args
.find(
PSF_FWHM
) !=
args
.end() &&
241
args
.find(
PSF_PIXEL_SAMPLING
) ==
args
.end()) {
242
throw
Elements::Exception
(
PSF_PIXEL_SAMPLING
+
" is required when using "
+
PSF_FWHM
);
243
}
244
}
245
246
void
PsfPluginConfig::initialize
(
const
UserValues
&
args
) {
247
if
(
args
.find(
PSF_FILE
) !=
args
.end()) {
248
auto
psf_file =
args
.find(
PSF_FILE
)->second.as<
std::string
>();
249
logger
.
debug
() <<
"Provided by user: "
<< psf_file;
250
if
(boost::to_upper_copy(psf_file) ==
"NOPSF"
){
251
m_vpsf
=
nullptr
;
252
}
else
{
253
m_vpsf
=
readPsf
(
args
.find(
PSF_FILE
)->second.as<
std::string
>());
254
}
255
}
else
if
(
args
.find(
PSF_FWHM
) !=
args
.end()) {
256
m_vpsf
=
generateGaussianPsf
(
args
.find(
PSF_FWHM
)->second.as<
double
>(),
257
args
.find(
PSF_PIXEL_SAMPLING
)->second.as<
double
>());
258
}
259
}
260
261
const
std::shared_ptr<Psf>
&
PsfPluginConfig::getPsf
()
const
{
262
return
m_vpsf
;
263
}
264
265
}
// end SourceXtractor
x
std::shared_ptr< DependentParameter< std::shared_ptr< EngineParameter > > > x
Definition
MoffatModelFittingTask.cpp:94
y
std::shared_ptr< DependentParameter< std::shared_ptr< EngineParameter > > > y
Definition
MoffatModelFittingTask.cpp:94
logger
static auto logger
Definition
PsfPluginConfig.cpp:36
PsfPluginConfig.h
PsfTask.h
VariablePsfStack.h
VariablePsf.h
std::string
std::begin
T begin(T... args)
Elements::Exception
Elements::Logging::debug
void debug(const std::string &logMessage)
Elements::Logging::getLogger
static Logging getLogger(const std::string &name="")
Elements::Logging::info
void info(const std::string &logMessage)
Euclid::Configuration::Configuration
SourceXtractor::PsfPluginConfig::getProgramOptions
std::map< std::string, OptionDescriptionList > getProgramOptions() override
Definition
PsfPluginConfig.cpp:227
SourceXtractor::PsfPluginConfig::m_vpsf
std::shared_ptr< Psf > m_vpsf
Definition
PsfPluginConfig.h:49
SourceXtractor::PsfPluginConfig::initialize
void initialize(const UserValues &args) override
Definition
PsfPluginConfig.cpp:246
SourceXtractor::PsfPluginConfig::readPsf
static std::shared_ptr< Psf > readPsf(const std::string &filename, int hdu_number=1)
Definition
PsfPluginConfig.cpp:164
SourceXtractor::PsfPluginConfig::getPsf
const std::shared_ptr< Psf > & getPsf() const
Definition
PsfPluginConfig.cpp:261
SourceXtractor::PsfPluginConfig::generateGaussianPsf
static std::shared_ptr< Psf > generateGaussianPsf(SeFloat fwhm, SeFloat pixel_sampling)
Definition
PsfPluginConfig.cpp:199
SourceXtractor::PsfPluginConfig::preInitialize
void preInitialize(const UserValues &args) override
Definition
PsfPluginConfig.cpp:238
SourceXtractor::PsfTask::component_value_getters
static std::map< std::string, ValueGetter > component_value_getters
Definition
PsfTask.h:41
SourceXtractor::VectorImage::create
static std::shared_ptr< VectorImage< T > > create(Args &&... args)
Definition
VectorImage.h:100
std::copy
T copy(T... args)
std::end
T end(T... args)
std::exp
T exp(T... args)
std::find
T find(T... args)
std::function
std::map
std::move
T move(T... args)
Euclid::Configuration::logger
static Elements::Logging logger
SourceXtractor
Definition
Aperture.h:30
SourceXtractor::PSF_PIXEL_SAMPLING
static const std::string PSF_PIXEL_SAMPLING
Definition
PsfPluginConfig.cpp:44
SourceXtractor::readStackedPsf
static std::shared_ptr< VariablePsfStack > readStackedPsf(std::unique_ptr< CCfits::FITS > &pFits)
Definition
PsfPluginConfig.cpp:49
SourceXtractor::readImage
static std::shared_ptr< VariablePsf > readImage(T &image_hdu)
Definition
PsfPluginConfig.cpp:136
SourceXtractor::PSF_FILE
static const std::string PSF_FILE
Definition
PsfPluginConfig.cpp:42
SourceXtractor::SeFloat
SeFloat32 SeFloat
Definition
Types.h:32
SourceXtractor::PSF_FWHM
static const std::string PSF_FWHM
Definition
PsfPluginConfig.cpp:43
SourceXtractor::readPsfEx
static std::shared_ptr< VariablePsf > readPsfEx(std::unique_ptr< CCfits::FITS > &pFits)
Definition
PsfPluginConfig.cpp:55
std::to_string
T to_string(T... args)
Generated by
1.10.0