5 from astropy.io
import fits
7 import matplotlib.pyplot
as plt
17 from .
import psfexLib
19 afwDisplay.setDefaultMaskTransparency(75)
23 """Compute the FWHM range associated to a series of FWHM measurements.
24 AUTHOR E. Bertin (IAP, Leiden observatory & ESO)
29 fwhm: iterable of `float`
30 Iterable of full width half-maxima.
32 Maximum allowed FWHM variation.
37 plot: `dict`, optional
38 Dict of plotting options.
59 for i
in range(nfwhm - nw):
60 df = fwhm[i + nw] - fwhm[i]
63 fmin = (fwhm[i + nw] + fwhm[i])/2.0
68 dfmin = (maxvar + 1.0)**0.3333333
69 minout = fmin/dfmin
if dfmin > 0.0
else 0.0
73 maxout = fmin*dfmin**2
77 if plt
and plot.get(
"fwhmHistogram"):
79 plt.hist(fwhm, nfwhm//10 + 1, normed=1, facecolor=
'g', alpha=0.75)
81 plt.axvline(fmin, color=
'red')
82 [plt.axvline(_, color=
'blue')
for _
in (minout, maxout)]
86 return fmin, minout, maxout
90 flags, flux, fluxerr, rmsSize, elong, vignet,
91 plot=dict(), title=
""):
92 maxbad = prefs.getBadpixNmax()
93 maxbadflag = prefs.getBadpixFlag()
94 maxelong = (prefs.getMaxellip() + 1.0)/(1.0 - prefs.getMaxellip())
if prefs.getMaxellip() < 1.0
else 100.0
95 minsn = prefs.getMinsn()
97 sn = flux/np.where(fluxerr > 0, fluxerr, 1)
98 sn[fluxerr <= 0] = -psfexLib.BIG
100 plotFlags = plot.get(
"showFlags")
if plt
else False
101 plotRejection = plot.get(
"showRejection")
if plt
else False
103 bad = flags & prefs.getFlagMask() != 0
104 set.setBadFlags(int(sum(bad != 0)))
107 selectionVectors = []
108 selectionVectors.append((bad,
"flags %d" % sum(bad != 0)))
111 set.setBadSN(int(sum(dbad)))
112 bad = np.logical_or(bad, dbad)
114 selectionVectors.append((dbad,
"S/N %d" % sum(dbad)))
116 dbad = rmsSize < frmin
117 set.setBadFrmin(int(sum(dbad)))
118 bad = np.logical_or(bad, dbad)
120 selectionVectors.append((dbad,
"frmin %d" % sum(dbad)))
122 dbad = rmsSize > frmax
123 set.setBadFrmax(int(sum(dbad)))
124 bad = np.logical_or(bad, dbad)
126 selectionVectors.append((dbad,
"frmax %d" % sum(dbad)))
128 dbad = elong > maxelong
129 set.setBadElong(int(sum(dbad)))
130 bad = np.logical_or(bad, dbad)
132 selectionVectors.append((dbad,
"elong %d" % sum(dbad)))
136 nbad = np.array([(v <= -psfexLib.BIG).sum()
for v
in vignet])
138 set.setBadPix(int(sum(dbad)))
139 bad = np.logical_or(bad, dbad)
141 selectionVectors.append((dbad,
"badpix %d" % sum(dbad)))
143 good = np.logical_not(bad)
144 if plotFlags
or plotRejection:
145 imag = -2.5*np.log10(flux)
152 isSet = np.where(flags == 0x0)[0]
153 plt.plot(imag[isSet], rmsSize[isSet],
'o', alpha=alpha, label=
"good")
157 if mask & prefs.getFlagMask():
158 isSet = np.where(np.bitwise_and(flags, mask))[0]
160 plt.plot(imag[isSet], rmsSize[isSet],
'o', alpha=alpha, label=labels[mask])
162 for bad, label
in selectionVectors:
163 plt.plot(imag[bad], rmsSize[bad],
'o', alpha=alpha, label=label)
165 plt.plot(imag[good], rmsSize[good],
'o', color=
"black", label=
"selected")
166 [plt.axhline(_, color=
'red')
for _
in [frmin, frmax]]
167 plt.xlim(np.median(imag[good]) + 5*np.array([-1, 1]))
168 plt.ylim(-0.1, 2*frmax)
170 plt.xlabel(
"Instrumental Magnitude")
171 plt.ylabel(
"rmsSize")
172 plt.title(
"%s %d selected" % (title, sum(good)))
179 def showPsf(psf, set, ext=None, wcsData=None, trim=0, nspot=5,
180 diagnostics=False, outDir="", frame=None, title=None):
181 """Show a PSF on display (e.g., ds9)
189 wcsData = wcsData[ext]
190 wcs, naxis1, naxis2 = wcsData
192 wcs, naxis1, naxis2 =
None,
None,
None
194 naxis = [naxis1, naxis2]
198 cmin, cmax = [set.getContextOffset(i) + d*set.getContextScale(i)
for d
in (-0.5, 0.5)]
199 naxis[i] = cmax + cmin
201 if naxis[0] > naxis[1]:
202 nx, ny = int(nspot*naxis[0]/float(naxis[1]) + 0.5), nspot
204 nx, ny = nspot, int(nspot*naxis[1]/float(naxis[0]) + 0.5)
206 mos = afwDisplay.utils.Mosaic(gutter=2, background=0.02)
208 xpos, ypos = np.linspace(0, naxis[0], nx), np.linspace(0, naxis[1], ny)
213 im = afwImage.ImageF(*psf.getLoc().shape)
214 im.getArray()[:] = psf.getLoc()
215 im /= float(im.getArray().
max())
217 if trim > im.getHeight()//2:
218 trim = im.getHeight()//2
220 im = im[trim:-trim, trim:-trim]
224 mosaic = mos.makeMosaic(mode=nx)
225 if frame
is not None:
226 afwDisplay.Display(frame=frame).
mtv(mosaic, title=title)
236 delta = pos[1][1][i].asDegrees() - pos[0][1][i].asDegrees()
237 CD.append(delta/(pos[1][0][i] - pos[0][0][i]))
243 title =
"%s-%d" % (title, ext)
245 if frame
is not None:
246 afwDisplay.Display(frame=frame).
mtv(mosaic, title=title, wcs=mosWcs)
249 outFile =
"%s-mod.fits" % title
251 outFile = os.path.join(outDir, outFile)
252 mosaic.writeFits(outFile, mosWcs.getFitsMetadata())
254 mos = afwDisplay.utils.Mosaic(gutter=4, background=0.002)
255 for i
in range(set.getNsample()):
257 if ext
is not None and s.getExtindex() != ext:
260 smos = afwDisplay.utils.Mosaic(gutter=2, background=-0.003)
261 for func
in [s.getVig, s.getVigResi]:
264 norm = float(arr.max())
if True else s.getNorm()
267 im = afwImage.ImageF(*arr.shape)
268 im.getArray()[:] = arr
271 mos.append(smos.makeMosaic(mode=
"x"))
273 mosaic = mos.makeMosaic(title=title)
275 if frame
is not None:
276 afwDisplay.Display(frame=frame + 1).
mtv(mosaic, title=title)
279 outFile =
"%s-psfstars.fits" % title
281 outFile = os.path.join(outDir, outFile)
283 mosaic.writeFits(outFile)
288 "base_PixelFlags_flag_edge",
292 "base_PixelFlags_flag_saturatedCenter",
294 "base_PixelFlags_flag_crCenter",
295 "base_PixelFlags_flag_bad",
302 for i, k
in enumerate(flagKeys):
303 flags[1 << i] = re.sub(
r"\_flag",
"",
304 re.sub(
r"^base\_",
"", re.sub(
r"^base\_PixelFlags\_flag\_",
"", k)))
307 for i, k
in enumerate(flagKeys):
310 isSet = tab.get(
"deblend_nChild") > 0
315 flags = np.bitwise_or(flags, np.where(isSet, 1 << i, 0))
322 re.sub(
"/src",
r"", fileName),
323 re.sub(
"(SRC([^.]+))",
r"CORR\2-exp", fileName),
325 if guess != fileName
and os.path.exists(guess):
328 raise RuntimeError(
"Unable to find a calexp to go with %s" % fileName)
332 """This is the python wrapper that reads lsst tables
335 if prefs.getVerboseType() != prefs.QUIET:
336 print(
"----- %d input catalogues:" % prefs.getNcat())
341 fields = psfexLib.vectorField()
342 for cat
in prefs.getCatalogs():
343 field = psfexLib.Field(cat)
345 wcssList.append(wcss)
354 cdMatrix = np.array([1.0, 0.0, 0.0, 1.0])
355 cdMatrix.shape = (2, 2)
360 naxis1, naxis2 = md.getScalar(
"NAXIS1"), md.getScalar(
"NAXIS2")
364 field.addExt(wcs, naxis1, naxis2, md.getScalar(
"NAXIS2"))
366 wcss.append((wcs, naxis1, naxis2))
375 sets = psfexLib.vectorSet()
379 psfexLib.makeit(fields, sets)
381 ret = [[f.getPsfs()
for f
in fields], sets]
388 def read_samplesLsst(prefs, set, filename, frmin, frmax, ext, next, catindex, context, pcval, nobj,
389 plot=dict(showFlags=
False, showRejection=
False)):
392 set = psfexLib.Set(context)
394 cmin, cmax =
None,
None
395 if set.getNcontext():
396 cmin = np.empty(set.getNcontext())
397 cmax = np.empty(set.getNcontext())
398 for i
in range(set.getNcontext()):
400 cmin[i] = set.getContextOffset(i) - set.getContextScale(i)/2.0
401 cmax[i] = cmin[i] + set.getContextScale(i)
403 cmin[i] = psfexLib.BIG
404 cmax[i] = -psfexLib.BIG
408 tab = afwTable.SourceCatalog.readFits(filename)
410 centroid = tab.getCentroidDefinition()
411 xm = tab.get(
"%s.x" % centroid)
412 ym = tab.get(
"%s.y" % centroid)
414 shape = tab.getShapeDefinition()
415 ixx = tab.get(
"%s.xx" % shape)
416 iyy = tab.get(
"%s.yy" % shape)
418 rmsSize = np.sqrt(0.5*(ixx + iyy))
419 elong = 0.5*(ixx - iyy)/(ixx + iyy)
421 flux = tab.get(prefs.getPhotfluxRkey())
422 fluxErr = tab.get(prefs.getPhotfluxerrRkey())
430 set.setVigSize(vigw, vigh)
432 vignet = np.empty(nobj*vigw*vigh,
"float32").reshape(nobj, vigw, vigh)
436 mi = afwImage.MaskedImageF(calexpFile)
437 backnoise2 = np.median(mi.getVariance().getArray())
440 edgeBit = [k
for k, v
in getFlags().
items()
if v ==
"edge"][0]
442 for i, xc, yc
in zip(range(nobj), xm, ym):
444 x, y = int(xc), int(yc)
449 pstamp = mi[x - vigw//2:x + vigw//2 + 1, y - vigh//2:y + vigh//2 + 1]
450 vignet[i] = pstamp.getImage().getArray().transpose()
457 for i, key
in enumerate(context.getName()):
458 if context.getPcflag(i):
459 contextvalp.append(pcval[pc])
463 contextvalp.append(tab.header[key[1:]])
465 raise RuntimeError(
"*Error*: %s parameter not found in the header of %s" %
469 contextvalp.append(tab.get(key))
471 raise RuntimeError(
"*Error*: %s parameter not found in the header of %s" %
473 set.setContextname(i, key)
477 flags, flux, fluxErr, rmsSize, elong, vignet,
478 plot=plot, title=
"%s[%d]" % (filename, ext + 1)
if next > 1
else filename)
482 if not vignet.dtype.isnative:
485 vignet = vignet.byteswap()
487 for i
in np.where(good)[0]:
488 sample = set.newSample()
489 sample.setCatindex(catindex)
490 sample.setExtindex(ext)
492 sample.setVig(vignet[i])
493 sample.setNorm(float(flux[i]))
494 sample.setBacknoise2(backnoise2)
496 sample.setX(float(xm[i]))
497 sample.setY(float(ym[i]))
498 sample.setFluxrad(float(rmsSize[i]))
500 for j
in range(set.getNcontext()):
501 sample.setContext(j, float(contextvalp[j][i]))
503 set.finiSample(sample, prefs.getProfAccuracy())
506 for j
in range(set.getNcontext()):
507 cmin[j] = contextvalp[j][good].
min()
508 cmax[j] = contextvalp[j][good].
max()
512 for i
in range(set.getNcontext()):
513 set.setContextScale(i, cmax[i] - cmin[i])
514 set.setContextOffset(i, (cmin[i] + cmax[i])/2.0)
522 def load_samplesLsst(prefs, context, ext=psfexLib.Prefs.ALL_EXTENSIONS, next=1, plot=dict()):
523 minsn = prefs.getMinsn()
524 maxelong = (prefs.getMaxellip() + 1.0)/(1.0 - prefs.getMaxellip())
if prefs.getMaxellip() < 1.0
else 100
525 min = prefs.getFwhmrange()[0]
526 max = prefs.getFwhmrange()[1]
528 filenames = prefs.getCatalogs()
530 ncat = len(filenames)
531 fwhmmin = np.empty(ncat)
532 fwhmmax = np.empty(ncat)
534 if not prefs.getAutoselectFlag():
535 fwhmmin = np.zeros(ncat) + prefs.getFwhmrange()[0]
536 fwhmmax = np.zeros(ncat) + prefs.getFwhmrange()[1]
537 fwhmmode = (fwhmmin + fwhmmax)/2.0
544 for i, fileName
in enumerate(filenames):
547 if prefs.getVerboseType() != prefs.QUIET:
548 print(
"Examining Catalog #%d" % (i+1))
551 tab = afwTable.SourceCatalog.readFits(fileName)
554 shape = tab.getShapeDefinition()
555 ixx = tab.get(
"%s.xx" % shape)
556 iyy = tab.get(
"%s.yy" % shape)
558 rmsSize = np.sqrt(0.5*(ixx + iyy))
559 elong = 0.5*(ixx - iyy)/(ixx + iyy)
561 flux = tab.get(prefs.getPhotfluxRkey())
562 fluxErr = tab.get(prefs.getPhotfluxerrRkey())
566 good = np.logical_and(flux/fluxErr > minsn,
567 np.logical_not(flags & prefs.getFlagMask()))
568 good = np.logical_and(good, elong < maxelong)
570 good = np.logical_and(good, fwhm >= min)
571 good = np.logical_and(good, fwhm < max)
572 fwhms[i] = fwhm[good]
574 if prefs.getVarType() == prefs.VAR_NONE:
576 fwhms_all = np.empty(sum([len(f)
for f
in fwhms.values()]))
578 for f
in fwhms.values():
579 fwhms_all[i:len(f)] = f
582 prefs.getFwhmrange()[0], prefs.getFwhmrange()[1],
585 raise RuntimeError(
"No source with appropriate FWHM found!!")
586 mode = min = max = 2.35/(1.0 - 1.0/psfexLib.cvar.INTERPFAC)
588 fwhmmin = np.zeros(ncat) + min
589 fwhmmax = np.zeros(ncat) + max
590 fwhmmode = np.zeros(ncat) + mode
592 fwhmmode = np.empty(ncat)
593 fwhmmin = np.empty(ncat)
594 fwhmmax = np.empty(ncat)
596 for i
in range(ncat):
599 fwhmmode[i], fwhmmin[i], fwhmmax[i] = \
601 prefs.getFwhmrange()[0], prefs.getFwhmrange()[1], plot=plot)
603 raise RuntimeError(
"No source with appropriate FWHM found!!")
604 fwhmmode[i] = fwhmmin[i] = fwhmmax[i] = 2.35/(1.0 - 1.0/psfexLib.cvar.INTERPFAC)
610 for i, fileName
in enumerate(filenames):
612 for ext
in range(next):
613 set =
read_samplesLsst(prefs, set, fileName, fwhmmin[i]/2.0, fwhmmax[i]/2.0,
614 ext, next, i, context,
615 context.getPc(i)
if context.getNpc()
else None, nobj, plot=plot)
617 if fwhmmode[i] < mode:
622 if prefs.getVerboseType() != prefs.QUIET:
624 print(
"%d samples loaded." % set.getNsample())
626 raise RuntimeError(
"No appropriate source found!!")
std::vector< SchemaItem< Flag > > * items
Point in an unspecified spherical coordinate system.
def mtv(data, frame=None, title="", wcs=None, *args, **kwargs)
std::shared_ptr< daf::base::PropertyList > readMetadata(std::string const &fileName, int hdu=DEFAULT_HDU, bool strip=false)
Read FITS header.
std::shared_ptr< SkyWcs > makeSkyWcs(daf::base::PropertySet &metadata, bool strip=false)
Construct a SkyWcs from FITS keywords.
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects.
def makeitLsst(prefs, context, saveWcs=False, plot=dict())
def compute_fwhmrange(fwhm, maxvar, minin, maxin, plot=dict(fwhmHistogram=False))
def showPsf(psf, set, ext=None, wcsData=None, trim=0, nspot=5, diagnostics=False, outDir="", frame=None, title=None)
def select_candidates(set, prefs, frmin, frmax, flags, flux, fluxerr, rmsSize, elong, vignet, plot=dict(), title="")
def load_samplesLsst(prefs, context, ext=psfexLib.Prefs.ALL_EXTENSIONS, next=1, plot=dict())
def guessCalexp(fileName)
def read_samplesLsst(prefs, set, filename, frmin, frmax, ext, next, catindex, context, pcval, nobj, plot=dict(showFlags=False, showRejection=False))