Skip to content

Commit

Permalink
Fix code transforming between focal plane position and Amp pixels, Us…
Browse files Browse the repository at this point in the history
…e physical pixels starting from 0., Use float pixel locations instead of int
  • Loading branch information
aaronroodman committed Mar 3, 2025
1 parent 1bba609 commit 015545c
Showing 1 changed file with 39 additions and 46 deletions.
85 changes: 39 additions & 46 deletions python/lsst/obs/lsst/cameraTransforms.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,9 @@ def ampPixelToCcdPixel(self, ampX, ampY, channel, detectorName=None):
Parameters
----------
ampX : `int`
ampX : `float`
column on amp segment.
ampY : `int`
ampY : `float`
row on amp segment.
channel : `int`
Channel number of amplifier (1-indexed; identical to HDU).
Expand All @@ -100,9 +100,9 @@ def ampPixelToCcdPixel(self, ampX, ampY, channel, detectorName=None):
Returns
-------
ccdX : `int`
ccdX : `float`
The column pixel position relative to the corner of the detector.
ccdY : `int`
ccdY : `float`
The row pixel position relative to the corner of the detector.
"""

Expand All @@ -113,9 +113,9 @@ def ccdPixelToAmpPixel(self, ccdX, ccdY, detectorName=None):
Parameters
----------
ccdX : `int`
ccdX : `float`
Column pixel position within detector.
ccdY : `int`
ccdY : `float`
Row pixel position within detector.
detectorName : `str`
Name of detector (or default from setDetectorName() if None).
Expand All @@ -129,10 +129,10 @@ def ccdPixelToAmpPixel(self, ccdX, ccdY, detectorName=None):
-------
ampName: `str`
Amplifier name, eg. 'C10'
ampX : `int`
ampX : `float`
The column coordinate relative to the corner of the single-amp
image.
ampY : `int`
ampY : `float`
The row coordinate relative to the corner of the single-amp image.
Raises
Expand All @@ -151,9 +151,9 @@ def ccdPixelToFocalMm(self, ccdX, ccdY, detectorName=None):
Parameters
----------
ccdX : `int`
ccdX : `float`
column pixel position within detector.
ccdY : `int`
ccdY : `float`
row pixel position within detector.
detectorName : `str`
Name of detector (or default from setDetectorName() if None).
Expand All @@ -180,9 +180,9 @@ def ccdPixelToFocalMm(self, ccdX, ccdY, detectorName=None):
def ampPixelToFocalMm(self, ampX, ampY, channel, detectorName=None):
r"""Given position within an amplifier return the focal plane position.
ampX : `int`
ampX : `float`
column on amp segment.
ampY : `int`
ampY : `float`
row on amp segment.
channel: `int`
Channel number of amplifier (1-indexed; identical to HDU).
Expand Down Expand Up @@ -238,9 +238,9 @@ def focalMmToCcdPixel(self, focalPlaneX, focalPlaneY):
-------
detectorName : `str`
The name of the detector.
ccdX : `int`
ccdX : `float`
The column pixel position relative to the corner of the detector.
ccdY : `int`
ccdY : `float`
The row pixel position relative to the corner of the detector.
Raises
Expand Down Expand Up @@ -277,11 +277,11 @@ def focalMmToAmpPixel(self, focalPlaneX, focalPlaneY):
The name of the detector.
ampName: `str`
The name of the amplifier.
ampX : `int`
The column coordinate relative to the corner of the single-amp
ampX : `float`
The physical column coordinate relative to the corner of the single-amp
image.
ampY : `int`
The row coordinate relative to the corner of the single-amp image.
ampY : `float`
The physical row coordinate relative to the corner of the single-amp image.
Raises
------
Expand All @@ -301,43 +301,38 @@ def ampPixelToCcdPixel(x, y, detector, channel):
Parameters
----------
x : `int`
column on amp segment.
y : `int`
row on amp segment.
x : `float`
physical column on amp segment.
y : `float`
physical row on amp segment.
detector : `lsst.afw.cameraGeom.Detector`
The requested detector.
channel : `str`
The name of the amplifier.
Returns
-------
ccdX : `int`
ccdX : `float`
The column pixel position relative to the corner of the detector.
ccdY : `int`
ccdY : `float`
The row pixel position relative to the corner of the detector.
"""

amp = detector[channel]
rawBBox, rawDataBBox = amp.getRawBBox(), amp.getRawDataBBox()
ampBBox = amp.getBBox()
# Allow for flips (due e.g. to physical location of the amplifiers)
w, h = rawBBox.getDimensions()
w, h = ampBBox.getDimensions()
if amp.getRawFlipX():
rawBBox.flipLR(w)
rawDataBBox.flipLR(w)

x = rawBBox.getWidth() - x - 1
ampBBox.flipLR(w)
x = w - x - 1

if amp.getRawFlipY():
rawBBox.flipTB(h)
rawDataBBox.flipTB(h)

y = rawBBox.getHeight() - y - 1
ampBBox.flipTB(h)
y = h - y - 1

dxy = rawBBox.getBegin() - rawDataBBox.getBegin() # correction for overscan etc.

return amp.getBBox().getBegin() + dxy + geom.ExtentI(x, y)
xyout = amp.getBBox().getBegin() + geom.ExtentD(x, y)

return xyout

def ccdPixelToAmpPixel(xy, detector):
r"""Given an position within a detector return position within an
Expand All @@ -359,37 +354,35 @@ def ccdPixelToAmpPixel(xy, detector):
-------
amp : `lsst.afw.table.AmpInfoRecord`
The amplifier that the pixel lies in.
ampXY : `lsst.geom.PointI`
The pixel coordinate relative to the corner of the single-amp image.
ampXY : `lsst.geom.PointD`
The physical pixel coordinate relative to the corner of the single-amp image.
Raises
------
RuntimeError
If the requested pixel doesn't lie on the detector.
"""

found = False
for amp in detector:
if geom.BoxD(amp.getBBox()).contains(xy):
found = True
xy = geom.PointI(xy) # pixel coordinates as ints
break

if not found:
raise RuntimeError("Point (%g, %g) does not lie on detector %s" % (xy[0], xy[1], detector.getName()))

x, y = xy - amp.getBBox().getBegin() # offset from origin of amp's data segment

# Allow for flips (due e.g. to physical location of the amplifiers)
w, h = amp.getRawDataBBox().getDimensions()
# Allow for flips (due e.g. to physical location and orientation of the amplifiers)
w, h = amp.getBBox().getDimensions()
if amp.getRawFlipX():
x = w - x - 1

if amp.getRawFlipY():
y = h - y - 1

dxy = amp.getRawBBox().getBegin() - amp.getRawDataBBox().getBegin() # correction for overscan etc.
xy = geom.ExtentI(x, y) - dxy
xy = geom.ExtentD (x, y)

return amp, xy

Expand Down Expand Up @@ -429,4 +422,4 @@ def focalMmToCcdPixel(camera, focalPlaneXY):
if geom.BoxD(detector.getBBox()).contains(ccdXY):
return detector, ccdXY

raise RuntimeError("Failed to map focal plane position (%.3f, %.3f) to a detector" % (focalPlaneXY))
raise RuntimeError("Failed to map focal plane position (%.3f, %.3f) to a detector" % (focalPlaneXY))

0 comments on commit 015545c

Please sign in to comment.