Exception AttributeError: 'NoneType' object has no attribute 'getCellList' while debug the PSF

Recently, I am debuging the PSF and below is my debug code:

def DebugInfo(name):
    di = lsstDebug.getInfo(name)  # N.b. lsstDebug.Info(name) would
                                  # call us recursively
                      
    if name == "lsst.pipe.tasks.measurePsf" :
            di.display = True
            di.displayExposure = True          # display the Exposure + spatialCells
            di.displayPsfCandidates = True     # show mosaic of candidates
            di.displayPsfMosaic = True     # show mosaic of reconstructed PSF(xy)
            di.displayResiduals = True          # show residuals
            di.showBadCandidates = False        # Include bad candidates
            di.normalizeResiduals = False       # Normalise residuals by object amplitude

    return di

And it comes out that:

characterizeImage.detection INFO: Detected 7966 positive peaks in 3522 footprints and 0 negative peaks in 0 footprints to 50 sigma
characterizeImage.detection INFO: Resubtracting the background after object detection
characterizeImage.measurement INFO: Measuring 3522 sources (3522 parents, 0 children) 
characterizeImage.measurePsf INFO: Measuring PSF
characterizeImage.measurePsf INFO: PSF star select 3522 stars
characterizeImage.measurePsf INFO: PSF star selector found 1357 candidates
characterizeImage.measurePsf.reserve INFO: Reserved 271/1357 sources
characterizeImage.measurePsf INFO: Sending 1086 candidates to PSF determiner
characterizeImage.measurePsf.psfDeterminer WARNING: NOT scaling kernelSize by stellar quadrupole moment, but using absolute value
characterizeImage.measurePsf INFO: PSF determination using 1017/1086 stars.
ctrl.mpexec.singleQuantumExecutor ERROR: Execution of task 'characterizeImage' on quantum {instrument: 'WFST', detector: 4, visit: 328, ...} failed. Exception AttributeError: 'NoneType' object has no attribute 'getCellList'
ctrl.mpexec.mpGraphExecutor ERROR: Task <TaskDef(CharacterizeImageTask, label=characterizeImage) dataId={instrument: 'WFST', detector: 4, visit: 328, ...}> failed; processing will continue for remaining tasks.
Traceback (most recent call last):
  File "/home/yu/lsst_stack/23.0.1/stack/miniconda3-py38_4.9.2-0.8.1/Linux64/ctrl_mpexec/g6727979600+15d2600a0d/python/lsst/ctrl/mpexec/mpGraphExecutor.py", line 363, in _executeQuantaInProcess
    self.quantumExecutor.execute(qnode.taskDef, qnode.quantum, butler)
  File "/home/yu/lsst_stack/23.0.1/stack/miniconda3-py38_4.9.2-0.8.1/Linux64/ctrl_mpexec/g6727979600+15d2600a0d/python/lsst/ctrl/mpexec/singleQuantumExecutor.py", line 174, in execute
    self.runQuantum(task, quantum, taskDef, butler)
  File "/home/yu/lsst_stack/23.0.1/stack/miniconda3-py38_4.9.2-0.8.1/Linux64/ctrl_mpexec/g6727979600+15d2600a0d/python/lsst/ctrl/mpexec/singleQuantumExecutor.py", line 464, in runQuantum
    task.runQuantum(butlerQC, inputRefs, outputRefs)
  File "/home/yu/lsst_stack/23.0.1/stack/miniconda3-py38_4.9.2-0.8.1/Linux64/pipe_tasks/gf1799c5b72+6048f86b6d/python/lsst/pipe/tasks/characterizeImage.py", line 342, in runQuantum
    outputs = self.run(**inputs)
  File "/home/yu/lsst_stack/23.0.1/stack/miniconda3-py38_4.9.2-0.8.1/Linux64/pipe_base/g5c83ca0194+970dd35637/python/lsst/pipe/base/timer.py", line 181, in wrapper
    res = func(self, *args, **keyArgs)
  File "/home/yu/lsst_stack/23.0.1/stack/miniconda3-py38_4.9.2-0.8.1/Linux64/pipe_tasks/gf1799c5b72+6048f86b6d/python/lsst/pipe/tasks/characterizeImage.py", line 488, in run
    dmeRes = self.detectMeasureAndEstimatePsf(
  File "/home/yu/lsst_stack/23.0.1/stack/miniconda3-py38_4.9.2-0.8.1/Linux64/pipe_base/g5c83ca0194+970dd35637/python/lsst/pipe/base/timer.py", line 181, in wrapper
    res = func(self, *args, **keyArgs)
  File "/home/yu/lsst_stack/23.0.1/stack/miniconda3-py38_4.9.2-0.8.1/Linux64/pipe_tasks/gf1799c5b72+6048f86b6d/python/lsst/pipe/tasks/characterizeImage.py", line 600, in detectMeasureAndEstimatePsf
    measPsfRes = self.measurePsf.run(exposure=exposure, sources=sourceCat, matches=matches,
  File "/home/yu/lsst_stack/23.0.1/stack/miniconda3-py38_4.9.2-0.8.1/Linux64/pipe_base/g5c83ca0194+970dd35637/python/lsst/pipe/base/timer.py", line 181, in wrapper
    res = func(self, *args, **keyArgs)
  File "/home/yu/lsst_stack/23.0.1/stack/miniconda3-py38_4.9.2-0.8.1/Linux64/pipe_tasks/gf1799c5b72+6048f86b6d/python/lsst/pipe/tasks/measurePsf.py", line 315, in run
    plotPsfCandidates(cellSet, showBadCandidates=showBadCandidates, frame=frame)
  File "/home/yu/lsst_stack/23.0.1/stack/miniconda3-py38_4.9.2-0.8.1/Linux64/pipe_tasks/gf1799c5b72+6048f86b6d/python/lsst/pipe/tasks/measurePsf.py", line 359, in plotPsfCandidates
    for cell in cellSet.getCellList():
AttributeError: 'NoneType' object has no attribute 'getCellList'
ctrl.mpexec.mpGraphExecutor INFO: Executed 1 quanta successfully, 1 failed and 1 remain out of total 3 quanta.

What cause the cellset is ‘NoneType’ object has no attribute ‘getCellList’?
And if I set other config to False, since my aim is primarily to see the residual, the code is below, I didn’t get any figure related to the residual.

def DebugInfo(name):
    di = lsstDebug.getInfo(name)  # N.b. lsstDebug.Info(name) would
                                  # call us recursively
                      
    if name == "lsst.pipe.tasks.measurePsf" :
            di.display = True
            di.displayExposure = False          # display the Exposure + spatialCells
            di.displayPsfCandidates = False     # show mosaic of candidates
            di.displayPsfMosaic = False     # show mosaic of reconstructed PSF(xy)
            di.displayResiduals = True          # show residuals
            di.showBadCandidates = False        # Include bad candidates
            di.normalizeResiduals = False       # Normalise residuals by object amplitude

    return di

So, how to figure out these two question?
Thank you!

I’m not sure how often people use the debug display code in measurePsf. cellSet should normally be non-None given that it’s a return value for this task.

I see that you are using v23.0.1 from 2 years ago. Is it possible to use a newer version of the pipeline code?

Do you know which PSF determiner you have configured?

If you locally patch the code to check for None and report None, do you always get None? That may indicate some problem with how the code is analysing your images. What camera is this data from?

Thank you very much for your reply! We will change to a newer version later, and I find out how to solve my question:
The psfDeterminer(one of the config in MeasurePsfConfig), use psfex as it’s default, and what I need to do is debug deeper, for example, if I debug the lsst.meas.extensions.psfex.psfexPsfDeterminer, things work

def DebugInfo(name):
    di = lsstDebug.getInfo(name)  # N.b. lsstDebug.Info(name) would
                                  # call us recursively
                      
    if name == "lsst.meas.extensions.psfex.psfexPsfDeterminer" :
            di.display = True
            di.displayExposure = True         
            di.displayPsfComponents = False     
            di.showBadCandidates = False     
            di.displayResiduals = True         
            di.displayPsfMosaic = False        
            di.normalizeResiduals = True       

    return di