59 namespace extensions {
 
   65     lsst::meas::extensions::psfex::Psf 
const& 
psf,
 
   73     _poly = poly_copy(
psf.impl->poly);
 
   75     _pixstep = 
psf.impl->pixstep;
 
   81     for (
int i = 0; i != 
psf.impl->poly->ndim; ++i) {
 
   82         _context[i].first = 
psf.impl->contextoffset[i];
 
   83         _context[i].second = 
psf.impl->contextscale[i];
 
   87     PsfexPsf::PsfexPsf() : ImagePsf(),
 
  105     return std::make_shared<PsfexPsf>(*
this);
 
  116     double pos[MAXCONTEXT];
 
  117     int const ndim = _context.size();
 
  120                           str(
boost::format(
"Only spatial variation (ndim == 2) is supported; saw %d")
 
  126         position = _averagePosition;
 
  129     for (
int i = 0; i < 
ndim; ++i) {
 
  130         pos[i] = (position[i] - _context[i].first)/_context[i].
second;
 
  133     poly_func(_poly, pos);              
 
  140     const int nbasis = 
_size.size() > 2 ? 
_size[2] : 1; 
 
  145     float const dx = 0.0, dy = 0.0;
 
  150     int sampleW = 
bbox.getWidth();
 
  151     int sampleH = 
bbox.getHeight();
 
  155     for (
int i = 0; i != nbasis; ++i) {
 
  159         vignet_resample(
const_cast<float *
>(&
_comp[i*
w*h]), 
w, h,
 
  160                         &sampledBasis[0],  sampleW, sampleH,
 
  161                         -dx*vigstep, -dy*vigstep, vigstep, 1.0);
 
  166             float *pl = &sampledBasis[0];
 
  167             for (
int y = 0; 
y != sampleH; ++
y) {
 
  168                 for (
int x = 0; 
x != sampleW; ++
x) {
 
  174         kernels.
push_back(std::make_shared<afw::math::FixedKernel>(kim));
 
  178     _kernel = std::make_shared<afw::math::LinearCombinationKernel>(kernels, weights);
 
  186     return _doComputeImage(position, color, position);
 
  190 PsfexPsf::doComputeKernelImage(
geom::Point2D const& position,
 
  193     return _doComputeImage(position, color, 
geom::Point2D(0, 0));
 
  203     int const w = _size[0], h = _size[1];
 
  204     int sampleW = 
static_cast<int>(
w*_pixstep);
 
  205     int sampleH = 
static_cast<int>(h*_pixstep);
 
  208     if (sampleW % 2 == 0) sampleW += 1;
 
  209     if (sampleH % 2 == 0) sampleH += 1;
 
  211     float dx = center[0] - 
static_cast<int>(center[0]);
 
  212     float dy = center[1] - 
static_cast<int>(center[1]);
 
  214     if (dx > 0.5) dx -= 1.0;
 
  215     if (dy > 0.5) dy -= 1.0;
 
  219                                              static_cast<int>(center[1] - dy + 0.5) - sampleH/2),
 
  226                           afw::image::Color 
const& color,
 
  230     double pos[MAXCONTEXT];
 
  234                           str(
boost::format(
"Only spatial variation (ndim == 2) is supported; saw %d")
 
  239     for (
int i = 0; i < 
ndim; ++i) {
 
  240         pos[i] = (position[i] - _context[i].first)/_context[i].
second;
 
  243     poly_func(_poly, pos);              
 
  245     int const w = _size[0], h = _size[1];
 
  247     const int nbasis = _size.
size() > 2 ? _size[2] : 1; 
 
  250     int const npix = 
w*h;
 
  251     for (
int i = 0; i != nbasis; ++i) {
 
  252         float *pl = &fullresIm[0];
 
  253         float const fac = _poly->basis[i];
 
  254         float const *ppc = &_comp[i*
w*h];
 
  256         for (
int j = 0; j != npix; ++j) {
 
  264     float const vigstep = 1/_pixstep;
 
  265     float dx = center[0] - 
static_cast<int>(center[0]);
 
  266     float dy = center[1] - 
static_cast<int>(center[1]);
 
  267     if (dx > 0.5) dx -= 1.0;
 
  268     if (dy > 0.5) dy -= 1.0;
 
  275     int sampleW = 
bbox.getWidth();
 
  276     int sampleH = 
bbox.getHeight();
 
  280     vignet_resample(&fullresIm[0], 
w, h,
 
  281                     &sampledIm[0], sampleW, sampleH,
 
  282                     -dx*vigstep, -dy*vigstep, vigstep, 1.0);
 
  284         float *pl = &sampledIm[0];
 
  285         float const sum = 
std::accumulate(pl, pl + sampleW*sampleH, 
static_cast<float>(0));
 
  286         for (
int y = 0; 
y != sampleH; ++
y) {
 
  287             for (
int x = 0; 
x != sampleW; ++
x) {
 
  288                 (*im)(
x, 
y) = *pl++/sum;
 
  300 namespace table = afw::table;
 
  304 class PsfexPsfSchema1 {
 
  308         ndim(
schema.addField<int>(
"ndim", 
"Number of elements in group")),
 
  309         ngroup(
schema.addField<int>(
"ngroup", 
"Number of elements in degree")),
 
  310         ncoeff(
schema.addField<int>(
"ncoeff", 
"Number of coefficients")),
 
  316         averagePosition(
afw::table::PointKey<double>::addFields(
schema,
"averagePosition",
"average position of stars used to make the PSF",
"pixel")),
 
  317         _pixstep(
schema.addField<float>(
"_pixstep", 
"oversampling", 
"pixel"))
 
  337 class PsfexPsfSchema2 {
 
  340                     int size_size, 
int comp_size, 
int context_size) :
 
  343         group(
schema.addField<table::Array<int> >(
"group", 
"Groups (of coefficients?)", 
ndim)),
 
  344         degree(
schema.addField<table::Array<int> >(
"degree", 
"Degree in each group", 
ngroup)),
 
  345         basis(
schema.addField<table::Array<double> >(
"basis", 
"Values of the basis functions", 
ncoeff)),
 
  346         coeff(
schema.addField<table::Array<double> >(
"coeff", 
"Polynomial coefficients", 
ncoeff)),
 
  347         _size(
schema.addField<table::Array<int> >(
"_size", 
"PSF dimensions", size_size)),
 
  348         _comp(
schema.addField<table::Array<float> >(
"_comp", 
"Complete pixel data", comp_size)),
 
  350                                                    "Offset to apply to context data", context_size)),
 
  352                                                    "Scale to apply to context data", context_size))
 
  359     table::Key<table::Array<int> > 
group;              
 
  361     table::Key<table::Array<double> > 
basis;           
 
  362     table::Key<table::Array<double> > 
coeff;           
 
  364     table::Key<table::Array<int> > 
_size;
 
  365     table::Key<table::Array<float> > 
_comp;
 
  370 std::string getPsfexPsfPersistenceName() { 
return "PsfexPsf"; }
 
  380 virtual PTR(table::io::Persistable)
 
  381 read(InputArchive const & archive, CatalogVector const & catalogs)
 const {
 
  387     int size_size, comp_size, context_size;
 
  389         PsfexPsfSchema1 
const & 
keys = PsfexPsfSchema1();
 
  402         size_size = record.
get(
keys._size_size);
 
  403         comp_size = record.
get(
keys._comp_size);
 
  404         context_size = record.
get(
keys._context_size);
 
  409                                    size_size, comp_size, context_size);
 
  421             for (
int i = 0; i != 
ndim; ++i) {
 
  444             result->_size.assign(begin, begin + size_size);
 
  448             result->_comp.assign(begin, begin + comp_size);
 
  453             result->_context.resize(context_size);
 
  454             for (
int i = 0; i != context_size; ++i) {
 
  455                 result->_context[i].first  = begin1[i];
 
  456                 result->_context[i].second = begin2[i];
 
  470     detail::PsfexPsfFactory registration(getPsfexPsfPersistenceName());
 
  475 std::string PsfexPsf::getPythonModule()
 const { 
return "lsst.meas.extensions.psfex"; }
 
  477 std::string PsfexPsf::getPersistenceName()
 const { 
return getPsfexPsfPersistenceName(); }
 
  483         PsfexPsfSchema1 
const keys;
 
  488         record->set(
keys.ndim, _poly->ndim);
 
  489         record->set(
keys.ngroup, _poly->ngroup);
 
  490         record->set(
keys.ncoeff, _poly->ncoeff);
 
  492         record->set(
keys.averagePosition, _averagePosition);
 
  493         record->set(
keys._pixstep, _pixstep);
 
  494         record->set(
keys._size_size, _size.
size());
 
  495         record->set(
keys._comp_size, _comp.
size());
 
  496         record->set(
keys._context_size, _context.
size());
 
  502         PsfexPsfSchema2 
const keys(_poly->ndim, _poly->ngroup, _poly->ncoeff,
 
  508             int *begin = record->getElement(
keys.group);
 
  509             std::copy(_poly->group, _poly->group + _poly->ndim, begin);
 
  512             int *begin = record->getElement(
keys.degree);
 
  513             std::copy(_poly->degree, _poly->degree + _poly->ngroup, begin);
 
  516             double *begin = record->getElement(
keys.basis);
 
  517             std::copy(_poly->basis, _poly->basis + _poly->ncoeff, begin);
 
  520             double *begin = record->getElement(
keys.coeff);
 
  521             std::copy(_poly->coeff, _poly->coeff + _poly->ncoeff, begin);
 
  525             int *begin = record->getElement(
keys._size);
 
  529             float *begin = record->getElement(
keys._comp);
 
  533             double *begin1 = record->getElement(
keys._context_first);
 
  534             double *begin2 = record->getElement(
keys._context_second);
 
  535             for (
unsigned int i = 0; i != _context.
size(); ++i) {
 
  536                 begin1[i] = _context[i].first;
 
  537                 begin2[i] = _context[i].second;