35
35
import lsst .afw .image as afwImage
36
36
import lsst .geom as geom
37
37
from lsst .meas .algorithms import ScienceSourceSelectorTask
38
+ from lsst .meas .algorithms .computeExPsf import ComputeExPsfTask , ComputeExPsfConfig
38
39
from lsst .utils .timer import timeMethod
39
40
import lsst .ip .isr as ipIsr
40
41
@@ -137,6 +138,22 @@ class ComputeExposureSummaryStatsConfig(pexConfig.Config):
137
138
doc = "Signal-to-noise ratio for computing the magnitude limit depth." ,
138
139
default = 5.0
139
140
)
141
+ psfTE1TreecorrConfig = pexConfig .ConfigField (
142
+ dtype = ComputeExPsfConfig ,
143
+ doc = "Treecorr config for computing scalar value of TE1." ,
144
+ )
145
+ psfTE2TreecorrConfig = pexConfig .ConfigField (
146
+ dtype = ComputeExPsfConfig ,
147
+ doc = "Treecorr config for computing scalar value of TE1." ,
148
+ )
149
+ psfTE3TreecorrConfig = pexConfig .ConfigField (
150
+ dtype = ComputeExPsfConfig ,
151
+ doc = "Treecorr config for computing scalar value of TE1." ,
152
+ )
153
+ psfTE4TreecorrConfig = pexConfig .ConfigField (
154
+ dtype = ComputeExPsfConfig ,
155
+ doc = "Treecorr config for computing scalar value of TE1." ,
156
+ )
140
157
141
158
def setDefaults (self ):
142
159
super ().setDefaults ()
@@ -159,6 +176,22 @@ def setDefaults(self):
159
176
self .starSelector .signalToNoise .fluxField = "slot_PsfFlux_instFlux"
160
177
self .starSelector .signalToNoise .errField = "slot_PsfFlux_instFluxErr"
161
178
179
+ min_theta = [1e-6 , 5.0 , 1e-6 , 5.0 ]
180
+ max_theta = [1.0 , 100.0 , 5.0 , 20.0 ]
181
+ TExTreecorrConfig = [
182
+ self .psfTE1TreecorrConfig ,
183
+ self .psfTE2TreecorrConfig ,
184
+ self .psfTE3TreecorrConfig ,
185
+ self .psfTE4TreecorrConfig ,
186
+ ]
187
+
188
+ for texc , mint , maxt in zip (TExTreecorrConfig , min_theta , max_theta ):
189
+ texc .treecorr .min_sep = mint / 60.0
190
+ texc .treecorr .max_sep = maxt / 60.0
191
+ texc .treecorr .nbins = 1
192
+ texc .treecorr .bin_type = "Linear"
193
+ texc .treecorr .sep_units = "degree"
194
+
162
195
163
196
class ComputeExposureSummaryStatsTask (pipeBase .Task ):
164
197
"""Task to compute exposure summary statistics.
@@ -199,6 +232,18 @@ class ComputeExposureSummaryStatsTask(pipeBase.Task):
199
232
- maxDistToNearestPsf
200
233
- psfTraceRadiusDelta
201
234
- psfApFluxDelta
235
+ - psfTE1E1
236
+ - psfTE1E2
237
+ - psfTE1Ex
238
+ - psfTE2E1
239
+ - psfTE2E2
240
+ - psfTE2Ex
241
+ - psfTE3E1
242
+ - psfTE3E2
243
+ - psfTE3Ex
244
+ - psfTE4E1
245
+ - psfTE4E2
246
+ - psfTE4Ex
202
247
203
248
This quantity is computed based on the aperture correction map, the
204
249
psfSigma, and the image mask to assess the robustness of the aperture
@@ -325,6 +370,18 @@ def update_psf_stats(
325
370
summary .psfTraceRadiusDelta = nan
326
371
summary .psfApFluxDelta = nan
327
372
summary .psfApCorrSigmaScaledDelta = nan
373
+ summary .psfTE1E1 = nan
374
+ summary .psfTE1E2 = nan
375
+ summary .psfTE1Ex = nan
376
+ summary .psfTE2E1 = nan
377
+ summary .psfTE2E2 = nan
378
+ summary .psfTE2Ex = nan
379
+ summary .psfTE3E1 = nan
380
+ summary .psfTE3E2 = nan
381
+ summary .psfTE3Ex = nan
382
+ summary .psfTE4E1 = nan
383
+ summary .psfTE4E2 = nan
384
+ summary .psfTE4Ex = nan
328
385
329
386
if psf is None :
330
387
return
@@ -410,10 +467,13 @@ def update_psf_stats(
410
467
psfE1 = (psfXX - psfYY )/ (psfXX + psfYY )
411
468
psfE2 = 2 * psfXY / (psfXX + psfYY )
412
469
413
- psfStarDeltaE1Median = np .median (starE1 - psfE1 )
414
- psfStarDeltaE1Scatter = sigmaMad (starE1 - psfE1 , scale = 'normal' )
415
- psfStarDeltaE2Median = np .median (starE2 - psfE2 )
416
- psfStarDeltaE2Scatter = sigmaMad (starE2 - psfE2 , scale = 'normal' )
470
+ e1Residuals = starE1 - psfE1
471
+ e2Residuals = starE2 - psfE2
472
+
473
+ psfStarDeltaE1Median = np .median (e1Residuals )
474
+ psfStarDeltaE1Scatter = sigmaMad (e1Residuals , scale = 'normal' )
475
+ psfStarDeltaE2Median = np .median (e2Residuals )
476
+ psfStarDeltaE2Scatter = sigmaMad (e2Residuals , scale = 'normal' )
417
477
418
478
psfStarDeltaSizeMedian = np .median (starSize - psfSize )
419
479
psfStarDeltaSizeScatter = sigmaMad (starSize - psfSize , scale = 'normal' )
@@ -427,6 +487,46 @@ def update_psf_stats(
427
487
summary .psfStarDeltaSizeScatter = float (psfStarDeltaSizeScatter )
428
488
summary .psfStarScaledDeltaSizeScatter = float (psfStarScaledDeltaSizeScatter )
429
489
490
+ ra = psf_cat ["coord_ra" ]
491
+ dec = psf_cat ["coord_dec" ]
492
+
493
+ # Comp TEx
494
+
495
+ TExTreecorrConfig = [
496
+ self .config .psfTE1TreecorrConfig ,
497
+ self .config .psfTE2TreecorrConfig ,
498
+ self .config .psfTE3TreecorrConfig ,
499
+ self .config .psfTE4TreecorrConfig ,
500
+ ]
501
+
502
+ TExOutput = [
503
+ [summary .psfTE1E1 , summary .psfTE1E2 , summary .psfTE1Ex ],
504
+ [summary .psfTE2E1 , summary .psfTE2E2 , summary .psfTE2Ex ],
505
+ [summary .psfTE3E1 , summary .psfTE3E2 , summary .psfTE3Ex ],
506
+ [summary .psfTE4E1 , summary .psfTE4E2 , summary .psfTE4Ex ],
507
+ ]
508
+
509
+ isNotNan = np .array ([True ] * len (ra ))
510
+ isNotNan &= np .isfinite (ra )
511
+ isNotNan &= np .isfinite (dec )
512
+ isNotNan &= np .isfinite (e1Residuals )
513
+ isNotNan &= np .isfinite (e2Residuals )
514
+
515
+ if np .sum (isNotNan ) > 1 :
516
+
517
+ for config , texoutput in zip (TExTreecorrConfig , TExOutput ):
518
+
519
+ task = ComputeExPsfTask (config )
520
+ output = task .run (
521
+ e1Residuals [isNotNan ], e2Residuals [isNotNan ],
522
+ ra [isNotNan ], dec [isNotNan ],
523
+ units = "degree" ,
524
+ )
525
+
526
+ texoutput [0 ] = output .metric_E1
527
+ texoutput [1 ] = output .metric_E2
528
+ texoutput [2 ] = output .metric_Ex
529
+
430
530
if image_mask is not None :
431
531
maxDistToNearestPsf = maximum_nearest_psf_distance (
432
532
image_mask ,
0 commit comments