46 namespace lsst {
namespace meas {
namespace extensions {
namespace psfex {
51 lsst::meas::extensions::psfex::Psf
const&
psf,
53 ) : ImagePsf(), _averagePosition(averagePosition),
55 _comp(psf.impl->npix),
56 _context(psf.impl->poly->
ndim)
59 _poly = poly_copy(psf.impl->poly);
63 std::copy(psf.impl->size, psf.impl->size + psf.impl->dim,
_size.begin());
65 std::copy(psf.impl->comp, psf.impl->comp + psf.impl->npix,
_comp.begin());
67 for (
int i = 0; i != psf.impl->poly->ndim; ++i) {
68 _context[i].first = psf.impl->contextoffset[i];
69 _context[i].second = psf.impl->contextscale[i];
91 return std::make_shared<PsfexPsf>(*this);
102 double pos[MAXCONTEXT];
106 str(boost::format(
"Only spatial variation (ndim == 2) is supported; saw %d")
112 position = _averagePosition;
115 for (
int i = 0; i <
ndim; ++i) {
116 pos[i] = (position[i] - _context[i].first)/_context[i].
second;
119 poly_func(_poly, pos);
126 const int nbasis =
_size.size() > 2 ?
_size[2] : 1;
131 float const dx = 0.0, dy = 0.0;
141 for (
int i = 0; i != nbasis; ++i) {
145 vignet_resample(const_cast<float *>(&
_comp[i*w*h]), w, h,
146 &sampledBasis[0], sampleW, sampleH,
147 -dx*vigstep, -dy*vigstep, vigstep, 1.0);
152 float *pl = &sampledBasis[0];
153 for (
int y = 0; y != sampleH; ++y) {
154 for (
int x = 0; x != sampleW; ++x) {
160 kernels.
push_back(std::make_shared<afw::math::FixedKernel>(kim));
164 _kernel = std::make_shared<afw::math::LinearCombinationKernel>(kernels, weights);
172 return _doComputeImage(position, color, position);
190 int sampleW =
static_cast<int>(w*
_pixstep);
191 int sampleH =
static_cast<int>(h*
_pixstep);
194 if (sampleW % 2 == 0) sampleW += 1;
195 if (sampleH % 2 == 0) sampleH += 1;
197 float dx = center[0] -
static_cast<int>(center[0]);
198 float dy = center[1] -
static_cast<int>(center[1]);
200 if (dx > 0.5) dx -= 1.0;
201 if (dy > 0.5) dy -= 1.0;
205 static_cast<int>(center[1] - dy + 0.5) - sampleH/2),
216 double pos[MAXCONTEXT];
220 str(boost::format(
"Only spatial variation (ndim == 2) is supported; saw %d")
225 for (
int i = 0; i <
ndim; ++i) {
226 pos[i] = (position[i] - _context[i].first)/_context[i].
second;
229 poly_func(_poly, pos);
233 const int nbasis =
_size.size() > 2 ?
_size[2] : 1;
236 int const npix = w*h;
237 for (
int i = 0; i != nbasis; ++i) {
238 float *pl = &fullresIm[0];
239 float const fac = _poly->basis[i];
240 float const *ppc = &
_comp[i*w*h];
242 for (
int j = 0; j != npix; ++j) {
251 float dx = center[0] -
static_cast<int>(center[0]);
252 float dy = center[1] -
static_cast<int>(center[1]);
253 if (dx > 0.5) dx -= 1.0;
254 if (dy > 0.5) dy -= 1.0;
266 vignet_resample(&fullresIm[0], w, h,
267 &sampledIm[0], sampleW, sampleH,
268 -dx*vigstep, -dy*vigstep, vigstep, 1.0);
270 float *pl = &sampledIm[0];
271 float const sum =
std::accumulate(pl, pl + sampleW*sampleH, static_cast<float>(0));
272 for (
int y = 0; y != sampleH; ++y) {
273 for (
int x = 0; x != sampleW; ++x) {
274 (*im)(x, y) = *pl++/sum;
286 namespace table = afw::table;
290 class PsfexPsfSchema1 {
294 ndim(
schema.addField<
int>(
"ndim",
"Number of elements in group")),
295 ngroup(
schema.addField<
int>(
"ngroup",
"Number of elements in degree")),
296 ncoeff(
schema.addField<
int>(
"ncoeff",
"Number of coefficients")),
303 _pixstep(
schema.addField<
float>(
"_pixstep",
"oversampling",
"pixel"))
323 class PsfexPsfSchema2 {
326 int size_size,
int comp_size,
int context_size) :
329 group(
schema.addField<table::Array<int> >(
"group",
"Groups (of coefficients?)", ndim)),
330 degree(
schema.addField<table::Array<int> >(
"degree",
"Degree in each group", ngroup)),
331 basis(
schema.addField<table::Array<double> >(
"basis",
"Values of the basis functions", ncoeff)),
332 coeff(
schema.addField<table::Array<double> >(
"coeff",
"Polynomial coefficients", ncoeff)),
333 _size(
schema.addField<table::Array<int> >(
"_size",
"PSF dimensions", size_size)),
334 _comp(
schema.addField<table::Array<float> >(
"_comp",
"Complete pixel data", comp_size)),
336 "Offset to apply to context data", context_size)),
338 "Scale to apply to context data", context_size))
345 table::Key<table::Array<int> >
group;
347 table::Key<table::Array<double> >
basis;
348 table::Key<table::Array<double> >
coeff;
350 table::Key<table::Array<int> >
_size;
351 table::Key<table::Array<float> >
_comp;
356 std::string getPsfexPsfPersistenceName() {
return "PsfexPsf"; }
366 virtual PTR(table::io::Persistable)
367 read(InputArchive const & archive, CatalogVector const & catalogs)
const {
373 int size_size, comp_size, context_size;
375 PsfexPsfSchema1
const & keys = PsfexPsfSchema1();
381 ndim = record.
get(keys.ndim);
382 ngroup = record.
get(keys.ngroup);
383 ncoeff = record.
get(keys.ncoeff);
385 result->_averagePosition = record.
get(keys.averagePosition);
386 result->_pixstep = record.
get(keys._pixstep);
388 size_size = record.
get(keys._size_size);
389 comp_size = record.
get(keys._comp_size);
390 context_size = record.
get(keys._context_size);
394 PsfexPsfSchema2
const keys(ndim, ngroup, ncoeff,
395 size_size, comp_size, context_size);
404 int const *begin = record.
getElement(keys.group);
405 group.
assign(begin, begin + ndim);
407 for (
int i = 0; i !=
ndim; ++i) {
413 int const *begin = record.
getElement(keys.degree);
414 degree.
assign(begin, begin + ngroup);
416 result->_poly = poly_init(&group[0], group.
size(), °ree[0], degree.
size());
420 double const *begin = record.
getElement(keys.basis);
421 std::copy(begin, begin + ncoeff, result->_poly->basis);
424 double const *begin = record.
getElement(keys.coeff);
425 std::copy(begin, begin + ncoeff, result->_poly->coeff);
429 int const *begin = record.
getElement(keys._size);
430 result->_size.assign(begin, begin + size_size);
433 float const *begin = record.
getElement(keys._comp);
434 result->_comp.assign(begin, begin + comp_size);
437 double const *begin1 = record.
getElement(keys._context_first);
438 double const *begin2 = record.
getElement(keys._context_second);
439 result->_context.resize(context_size);
440 for (
int i = 0; i != context_size; ++i) {
441 result->_context[i].first = begin1[i];
442 result->_context[i].second = begin2[i];
461 std::string PsfexPsf::getPythonModule()
const {
return "lsst.meas.extensions.psfex"; }
463 std::string PsfexPsf::getPersistenceName()
const {
return getPsfexPsfPersistenceName(); }
469 PsfexPsfSchema1
const keys;
474 record->set(keys.ndim, _poly->ndim);
475 record->set(keys.ngroup, _poly->ngroup);
476 record->set(keys.ncoeff, _poly->ncoeff);
478 record->set(keys.averagePosition, _averagePosition);
479 record->set(keys._pixstep,
_pixstep);
480 record->set(keys._size_size,
_size.size());
481 record->set(keys._comp_size,
_comp.size());
482 record->set(keys._context_size, _context.size());
488 PsfexPsfSchema2
const keys(_poly->ndim, _poly->ngroup, _poly->ncoeff,
494 int *begin = record->getElement(keys.group);
495 std::copy(_poly->group, _poly->group + _poly->ndim, begin);
498 int *begin = record->getElement(keys.degree);
499 std::copy(_poly->degree, _poly->degree + _poly->ngroup, begin);
502 double *begin = record->getElement(keys.basis);
503 std::copy(_poly->basis, _poly->basis + _poly->ncoeff, begin);
506 double *begin = record->getElement(keys.coeff);
507 std::copy(_poly->coeff, _poly->coeff + _poly->ncoeff, begin);
511 int *begin = record->getElement(keys._size);
515 float *begin = record->getElement(keys._comp);
519 double *begin1 = record->getElement(keys._context_first);
520 double *begin2 = record->getElement(keys._context_second);
521 for (
unsigned int i = 0; i != _context.size(); ++i) {
522 begin1[i] = _context[i].first;
523 begin2[i] = _context[i].second;
#define LSST_ARCHIVE_ASSERT(EXPR)
table::Key< table::Array< int > > degree
Field< T >::Value get(Key< T > const &key) const
table::Key< int > _size_size
virtual boost::shared_ptr< lsst::afw::detection::Psf > clone() const
Polymorphic deep copy; should usually be unnecessary as Psfs are immutable.x.
PsfexPsfFactory(std::string const &name)
Represent a PSF as a linear combination of PSFEX (== Karhunen-Loeve) basis functions.
virtual boost::shared_ptr< afw::detection::Psf > resized(int width, int height) const
Return a clone with specified kernel dimensions.
table::Key< table::Array< double > > _context_second
ImagePsf(bool isFixed=false)
table::Key< table::Array< int > > _size
table::Key< table::Array< double > > coeff
BaseCatalog makeCatalog(Schema const &schema)
Field< T >::Element * getElement(Key< T > const &key)
table::Key< int > _comp_size
boost::shared_ptr< lsst::afw::math::LinearCombinationKernel const > getKernel(lsst::afw::geom::Point2D=lsst::afw::geom::Point2D(std::numeric_limits< double >::quiet_NaN())) const
Return the PSF's basis functions as a spatially-invariant LinearCombinationKernel with unit weights...
#define LSST_EXCEPT(type,...)
table::Key< table::Array< double > > basis
table::Key< table::Array< float > > _comp
void write(lsst::afw::table::io::OutputArchiveHandle &handle) const
table::Key< table::Array< double > > _context_first
table::Key< int > _context_size
void saveCatalog(BaseCatalog const &catalog)
table::Key< table::Array< int > > group
table::Key< float > _pixstep
table::PointKey< double > averagePosition
std::shared_ptr< RecordT > addNew()