27     import matplotlib.pyplot 
as plt
    36 from . 
import psfexLib
    37 from .psfex 
import compute_fwhmrange
    39 __all__ = [
"PsfexStarSelectorConfig", 
"PsfexStarSelectorTask"]
    43     fluxName = pexConfig.Field(
    45         doc=
"Name of photometric flux key ",
    46         default=
"base_PsfFlux",
    48     fluxErrName = pexConfig.Field(
    50         doc=
"Name of phot. flux err. key",
    53     minFwhm = pexConfig.Field(
    55         doc=
"Maximum allowed FWHM ",
    58     maxFwhm = pexConfig.Field(
    60         doc=
"Minimum allowed FWHM ",
    63     maxFwhmVariability = pexConfig.Field(
    65         doc=
"Allowed FWHM variability (1.0 = 100%)",
    68     maxbad = pexConfig.Field(
    70         doc=
"Max number of bad pixels ",
    72         check=
lambda x: x >= 0,
    74     maxbadflag = pexConfig.Field(
    76         doc=
"Filter bad pixels? ",
    79     maxellip = pexConfig.Field(
    81         doc=
"Maximum (A-B)/(A+B) ",
    83         check=
lambda x: x >= 0.0,
    85     minsn = pexConfig.Field(
    87         doc=
"Minimum S/N for candidates",
    89         check=
lambda x: x >= 0.0,
    93         pexConfig.Config.validate(self)
    98             raise pexConfig.FieldValidationError(
"fluxErrName (%s) doesn't correspond to fluxName (%s)"   102             raise pexConfig.FieldValidationError(
"minFwhm (%f) > maxFwhm (%f)" % (self.
minFwhm, self.
maxFwhm))
   106             "base_PixelFlags_flag_edge",
   107             "base_PixelFlags_flag_saturatedCenter",
   108             "base_PixelFlags_flag_crCenter",
   109             "base_PixelFlags_flag_bad",
   110             "base_PixelFlags_flag_suspectCenter",
   117     """A class to handle key strokes with matplotlib displays   120     def __init__(self, axes, xs, ys, x, y, frames=[0]):
   128         self.
cid = self.
axes.figure.canvas.mpl_connect(
'key_press_event', self)
   131         if ev.inaxes != self.
axes:
   134         if ev.key 
and ev.key 
in (
"p"):
   135             dist = np.hypot(self.
xs - ev.xdata, self.
ys - ev.ydata)
   136             dist[np.where(np.isnan(dist))] = 1e30
   138             which = np.where(dist == 
min(dist))
   143                 ds9.pan(x, y, frame=frame)
   144             ds9.cmdBuffer.flush()
   151 def plot(mag, width, centers, clusterId, marker="o", markersize=2, markeredgewidth=0, ltype='-',
   163     axes = fig.add_axes((0.1, 0.1, 0.85, 0.80))
   165     xmin = sorted(mag)[
int(0.05*len(mag))]
   166     xmax = sorted(mag)[
int(0.95*len(mag))]
   168     axes.set_xlim(-17.5, -13)
   169     axes.set_xlim(xmin - 0.1*(xmax - xmin), xmax + 0.1*(xmax - xmin))
   172     colors = [
"r", "g", "b", "c", "m", "k", ]
   173     for k, mean 
in enumerate(centers):
   175             axes.plot(axes.get_xlim(), (mean, mean,), 
"k%s" % ltype)
   178         axes.plot(mag[l], width[l], marker, markersize=markersize, markeredgewidth=markeredgewidth,
   179                   color=colors[k%len(colors)])
   181     l = (clusterId == -1)
   182     axes.plot(mag[l], width[l], marker, markersize=markersize, markeredgewidth=markeredgewidth,
   186         axes.set_xlabel(
"model")
   187         axes.set_ylabel(
r"$\sqrt{I_{xx} + I_{yy}}$")
   199 @pexConfig.registerConfigurable(
"psfex", sourceSelectorRegistry)
   201     """A star selector whose algorithm is not yet documented.   203     @anchor PsfexStarSelectorTask_   205     @section meas_extensions_psfex_psfexStarSelectorStarSelector_Contents  Contents   207      - @ref meas_extensions_psfex_psfexStarSelectorStarSelector_Purpose   208      - @ref meas_extensions_psfex_psfexStarSelectorStarSelector_Initialize   209      - @ref meas_extensions_psfex_psfexStarSelectorStarSelector_IO   210      - @ref meas_extensions_psfex_psfexStarSelectorStarSelector_Config   211      - @ref meas_extensions_psfex_psfexStarSelectorStarSelector_Debug   213     @section meas_extensions_psfex_psfexStarSelectorStarSelector_Purpose  Description   215     A star selector whose algorithm is not yet documented   217     @section meas_extensions_psfex_psfexStarSelectorStarSelector_Initialize  Task initialisation   219     @copydoc \_\_init\_\_   221     @section meas_extensions_psfex_psfexStarSelectorStarSelector_IO  Invoking the Task   223     Like all star selectors, the main method is `run`.   225     @section meas_extensions_psfex_psfexStarSelectorStarSelector_Config  Configuration parameters   227     See @ref PsfexStarSelectorConfig   229     @section meas_extensions_psfex_psfexStarSelectorStarSelector_Debug  Debug variables   231     PsfexStarSelectorTask has a debug dictionary with the following keys:   234     <dd>bool; if True display debug information   236     <dd>bool; if True display the exposure and spatial cells   237     <dt>plotFwhmHistogram   238     <dd>bool; if True plot histogram of FWHM   240     <dd>bool: if True plot the sources coloured by their flags   242     <dd>bool; if True plot why sources are rejected   245     For example, put something like:   249             di = lsstDebug.getInfo(name)  # N.b. lsstDebug.Info(name) would call us recursively   250             if name.endswith("objectSizeStarSelector"):   252                 di.displayExposure = True   253                 di.plotFwhmHistogram = True   257         lsstDebug.Info = DebugInfo   259     into your `debug.py` file and run your task with the `--debug` flag.   261     ConfigClass = PsfexStarSelectorConfig
   265         """Return a selection of psf-like objects.   269         sourceCat : `lsst.afw.table.SourceCatalog`   270             Catalog of sources to select from.   271             This catalog must be contiguous in memory.   272         matches : `list` of `lsst.afw.table.ReferenceMatch` or None   273             Ignored by this source selector.   274         exposure : `lsst.afw.image.Exposure` or None   275             The exposure the catalog was built from; used for debug display.   279         struct : `lsst.pipe.base.Struct`   280             The struct contains the following data:   282             - selected : `numpy.ndarray` of `bool``   283                 Boolean array of sources that were selected, same length as   289         displayExposure = display 
and \
   291         plotFwhmHistogram = display 
and plt 
and \
   293         plotFlags = display 
and plt 
and \
   295         plotRejection = display 
and plt 
and \
   300         fluxName = self.config.fluxName
   301         fluxErrName = self.config.fluxErrName
   302         minFwhm = self.config.minFwhm
   303         maxFwhm = self.config.maxFwhm
   304         maxFwhmVariability = self.config.maxFwhmVariability
   305         maxbad = self.config.maxbad
   306         maxbadflag = self.config.maxbadflag
   307         maxellip = self.config.maxellip
   308         minsn = self.config.minsn
   310         maxelong = (maxellip + 1.0)/(1.0 - maxellip) 
if maxellip < 1.0 
else 100
   313         shape = sourceCat.getShapeDefinition()
   314         ixx = sourceCat.get(
"%s.xx" % shape)
   315         iyy = sourceCat.get(
"%s.yy" % shape)
   317         fwhm = 2*np.sqrt(2*np.log(2))*np.sqrt(0.5*(ixx + iyy))
   318         elong = 0.5*(ixx - iyy)/(ixx + iyy)
   320         flux = sourceCat.get(fluxName)
   321         fluxErr = sourceCat.get(fluxErrName)
   322         sn = flux/np.where(fluxErr > 0, fluxErr, 1)
   323         sn[fluxErr <= 0] = -psfexLib.BIG
   326         for i, f 
in enumerate(self.config.badFlags):
   327             flags = np.bitwise_or(flags, np.where(sourceCat.get(f), 1 << i, 0))
   331         good = np.logical_and(sn > minsn, np.logical_not(flags))
   332         good = np.logical_and(good, elong < maxelong)
   333         good = np.logical_and(good, fwhm >= minFwhm)
   334         good = np.logical_and(good, fwhm < maxFwhm)
   336         fwhmMode, fwhmMin, fwhmMax = 
compute_fwhmrange(fwhm[good], maxFwhmVariability, minFwhm, maxFwhm,
   337                                                        plot=dict(fwhmHistogram=plotFwhmHistogram))
   349             selectionVectors = []
   350             selectionVectors.append((bad, 
"flags %d" % sum(bad)))
   354         bad = np.logical_or(bad, dbad)
   356             selectionVectors.append((dbad, 
"S/N %d" % sum(dbad)))
   358         dbad = fwhm < fwhmMin
   360         bad = np.logical_or(bad, dbad)
   362             selectionVectors.append((dbad, 
"fwhmMin %d" % sum(dbad)))
   364         dbad = fwhm > fwhmMax
   366         bad = np.logical_or(bad, dbad)
   368             selectionVectors.append((dbad, 
"fwhmMax %d" % sum(dbad)))
   370         dbad = elong > maxelong
   372         bad = np.logical_or(bad, dbad)
   374             selectionVectors.append((dbad, 
"elong %d" % sum(dbad)))
   378             nbad = np.array([(v <= -psfexLib.BIG).sum() 
for v 
in vignet])
   381             bad = np.logical_or(bad, dbad)
   383                 selectionVectors.append((dbad, 
"badpix %d" % sum(dbad)))
   385         good = np.logical_not(bad)
   391             mi = exposure.getMaskedImage()
   393             ds9.mtv(mi, frame=frame, title=
"PSF candidates")
   395             with ds9.Buffering():
   396                 for i, source 
in enumerate(sourceCat):
   402                     ds9.dot(
"+", source.getX() - mi.getX0(), source.getY() - mi.getY0(),
   403                             frame=frame, ctype=ctype)
   405         if plotFlags 
or plotRejection:
   406             imag = -2.5*np.log10(flux)
   411                 isSet = np.where(flags == 0x0)[0]
   412                 plt.plot(imag[isSet], fwhm[isSet], 
'o', alpha=alpha, label=
"good")
   414                 for i, f 
in enumerate(self.config.badFlags):
   416                     isSet = np.where(np.bitwise_and(flags, mask))[0]
   418                         if np.isfinite(imag[isSet] + fwhm[isSet]).
any():
   419                             label = re.sub(
r"\_flag", 
"",
   420                                            re.sub(
r"^base\_", 
"",
   421                                                   re.sub(
r"^.*base\_PixelFlags\_flag\_", 
"", f)))
   422                             plt.plot(imag[isSet], fwhm[isSet], 
'o', alpha=alpha, label=label)
   424                 for bad, label 
in selectionVectors:
   425                     plt.plot(imag[bad], fwhm[bad], 
'o', alpha=alpha, label=label)
   427             plt.plot(imag[good], fwhm[good], 
'o', color=
"black", label=
"selected")
   428             [plt.axhline(_, color=
'red') 
for _ 
in [fwhmMin, fwhmMax]]
   429             plt.xlim(np.median(imag[good]) + 5*np.array([-1, 1]))
   430             plt.ylim(fwhm[np.where(np.isfinite(fwhm + imag))].
min(), 2*fwhmMax)
   432             plt.xlabel(
"Instrumental %s Magnitude" % fluxName.split(
".")[-1].title())
   434             title = 
"PSFEX Star Selection"   435             plt.title(
"%s %d selected" % (title, sum(good)))
   439             eventHandler = 
EventHandler(plt.axes(), imag, fwhm, sourceCat.getX(), sourceCat.getY(),
   442         if plotFlags 
or plotRejection:
   445                     reply = input(
"continue? [y[es] h(elp) p(db) q(uit)] ").
strip()
   454 At this prompt, you can continue with almost any key; 'p' enters pdb,   455                                                       'q' returns to the shell, and   461 If you put the cursor on a point in the matplotlib scatter plot and hit 'p' you'll see it in ds9.""")
   462                 elif reply[0] == 
"p":
   465                 elif reply[0] == 
'q':
   470         return Struct(selected=good)
 
def selectSources(self, sourceCat, matches=None, exposure=None)
Fit spatial kernel using approximate fluxes for candidates, and solving a linear system of equations...
bool any(CoordinateExpr< N > const &expr) noexcept
Return true if any elements are true. 
def compute_fwhmrange(fwhm, maxvar, minin, maxin, plot=dict(fwhmHistogram=False))
def __init__(self, axes, xs, ys, x, y, frames=[0])
def plot(mag, width, centers, clusterId, marker="o", markersize=2, markeredgewidth=0, ltype='-', clear=True)