Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion README.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
PyGuide offers image analysis routines for telescope guiding,
including a star finder, centroider and star shape fitter.

See doc/PyGuideManual.html for installation and usage instructions.
See doc/PyGuideManual.html for installation and usage instructions.

Modification of PyGuide code (https://github.com/fmerges/PyGuide and https://github.com/ApachePointObservatory/PyGuide) for python 3. Tested on python 3.12, numpy 1.26.0 and astropy 6.1.2. Need to use python3 version of RO package: https://github.com/pavolgaj/RO3/tree/main.
6 changes: 3 additions & 3 deletions python/Centroid.py
Original file line number Diff line number Diff line change
Expand Up @@ -579,9 +579,9 @@ def checkSignal(
xyCtr = xyCtr,
xySize = (outerRad, outerRad),
)
subMask = subMaskObj.getSubFrame().astype(numpy.bool) # force type and copy
subMask = subMaskObj.getSubFrame().astype(numpy.bool_) # force type and copy
else:
subMask = numpy.zeros(subData.shape, dtype=numpy.bool)
subMask = numpy.zeros(subData.shape, dtype=numpy.bool_)

# create circleMask; a centered circle of radius rad
# with 0s in the middle and 1s outside
Expand Down Expand Up @@ -656,7 +656,7 @@ def conditionMask(mask):
"""
if mask is None:
return None
return conditionArr(mask, numpy.bool)
return conditionArr(mask, numpy.bool_)

def conditionArr(arr, desType):
"""Convert a sequence to a numpy array of the desired type.
Expand Down
2 changes: 1 addition & 1 deletion python/FakeData.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def addNoise(
- sky sky level, in ADU
- ccdInfo a PyGuide.CCDInfo object
"""
outData = numpy.add(data, sky).astype(numpy.int)
outData = numpy.add(data, sky).astype(numpy.int32)
outData = numpy.random.poisson(lam = outData * ccdInfo.ccdGain) / ccdInfo.ccdGain
outData += numpy.random.normal(loc = ccdInfo.bias, scale = ccdInfo.readNoise/float(ccdInfo.ccdGain), size = data.shape)
# truncate data and return as UInt16
Expand Down
33 changes: 31 additions & 2 deletions src/RadProfModule.c
Original file line number Diff line number Diff line change
Expand Up @@ -1103,12 +1103,41 @@ static PyMethodDef radProfMethods[] = {
{NULL, NULL, 0, NULL} /* Sentinel */
};


#if PY_MAJOR_VERSION >= 3
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
"radProf", /* m_name */
radProfModule_doc, /* m_doc */
-1, /* m_size */
radProfMethods, /* m_methods */
NULL, /* m_reload */
NULL, /* m_traverse */
NULL, /* m_clear */
NULL, /* m_free */
};
#endif

// Module initialization function
PyMODINIT_FUNC initradProf(void) {
PyMODINIT_FUNC
#if PY_MAJOR_VERSION >= 3
PyInit_radProf(void)
#else
initradProf(void)
#endif
{
PyObject *m;
#if PY_MAJOR_VERSION >= 3
m = PyModule_Create(&moduledef);
#else
m = Py_InitModule3("radProf", radProfMethods, radProfModule_doc);
#endif
if (m == NULL)
return;
return m;

import_array();

#if PY_MAJOR_VERSION >= 3
return m;
#endif
}
2 changes: 1 addition & 1 deletion tests/Stats.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from __future__ import division, absolute_import, print_function


import math

Expand Down
4 changes: 2 additions & 2 deletions tests/testCentroid.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env python
from __future__ import division, absolute_import, print_function

"""Test PyGuide.centroid with masked data.

History:
Expand Down Expand Up @@ -86,7 +86,7 @@
nPts = ctrData.pix
print("meas err = %6.2f, %6.2f; est err = %.2f, %.2f; nCounts = %.0f; nPts = %d" %
(measCtr[0] - actCtr[0], measCtr[1] - actCtr[1], ctrData.xyErr[0], ctrData.xyErr[1], nCounts, nPts))
mask = numpy.zeros(arrShape, numpy.bool)
mask = numpy.zeros(arrShape, numpy.bool_)
for row in range(maskLim[0], maskLim[1]+1):
mask[row,:] = 1
ctrData = PyGuide.centroid(
Expand Down
84 changes: 42 additions & 42 deletions tests/testCentroidLong.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@

imShape = (ImWidth, ImWidth)
nomCtr = (ImWidth // 2, ImWidth // 2)
mask = numpy.zeros(imShape, numpy.bool)
mask = numpy.zeros(imShape, numpy.bool_)
NaN = float("NaN")

# settings
Expand All @@ -44,36 +44,36 @@
MaskWidthsPerFWHM = (0.0, 0.5, 1.0, 1.5, 2.0) # fractions of a FWHM
NumTries = 20

print "Compare centroid actual error vs estimated error"
print "over a range of fake data"
print
print "Settings:"
print "Thresh =", Thresh
print "Sky =", Sky, "ADU"
print "Read Noise =", CCDInfo.readNoise, "e-"
print "CCD Gain =", CCDInfo.ccdGain, "e-/ADU"
print "Bias =", CCDInfo.bias, "ADU"
print "Amplitudes =", AmplValues, "ADU"
print "FWHMs =", FWHMValues, "pixels"
print "Mask Widths =", MaskWidthsPerFWHM, "fractions of a FWHM"
print "Num Ctrs =", NumTries, "number of centroids per star shape"
print "CCD Size =", ImWidth, "x", ImWidth, "pixels"
print
print "the equation being minimized is:"
print " sum(var(r) * numPts(r))"
print "though the final number reported is a normalized version:"
print " asymm = sum(var(r) * numPts(r)) / (pixNoise^2 * totPts)"
print "where"
print " pixNoise is the noise/pixel due to read noise and sky"
print " totPts = sum(numPts(r))"
print
print "The centroids are randomly distributed over"
print "a range of -FWHM/2, FWHM/2 with respect to the"
print "center of the CCD = the center of the slit."
print
print "The slit is along y so the error along y should be smaller than x."
print
print "fwhm ampl maskWid xErr yErr xUncert yUncert asymm totPix totCts rad msgs"
print("Compare centroid actual error vs estimated error")
print("over a range of fake data")
print()
print("Settings:")
print("Thresh =", Thresh)
print("Sky =", Sky, "ADU")
print("Read Noise =", CCDInfo.readNoise, "e-")
print("CCD Gain =", CCDInfo.ccdGain, "e-/ADU")
print("Bias =", CCDInfo.bias, "ADU")
print("Amplitudes =", AmplValues, "ADU")
print("FWHMs =", FWHMValues, "pixels")
print("Mask Widths =", MaskWidthsPerFWHM, "fractions of a FWHM")
print("Num Ctrs =", NumTries, "number of centroids per star shape")
print("CCD Size =", ImWidth, "x", ImWidth, "pixels")
print()
print("the equation being minimized is:")
print(" sum(var(r) * numPts(r))")
print("though the final number reported is a normalized version:")
print(" asymm = sum(var(r) * numPts(r)) / (pixNoise^2 * totPts)")
print("where")
print(" pixNoise is the noise/pixel due to read noise and sky")
print(" totPts = sum(numPts(r))")
print()
print("The centroids are randomly distributed over")
print("a range of -FWHM/2, FWHM/2 with respect to the")
print("center of the CCD = the center of the slit.")
print()
print("The slit is along y so the error along y should be smaller than x.")
print()
print("fwhm ampl maskWid xErr yErr xUncert yUncert asymm totPix totCts rad msgs")

nBad = 0
ctrXStats = Stats()
Expand Down Expand Up @@ -110,29 +110,29 @@
doSmooth = DoSmooth,
)
if not ctrData.isOK:
print "%s %s %s NaN NaN NaN NaN NaN NaN NaN %s %r" % (
print("%s %s %s NaN NaN NaN NaN NaN NaN NaN %s %r" % (
fwhm, ampl, maskWidth, ctrData.rad, ctrData.msgStr,
)
))
nBad += 1
continue

xyMeasErr = [ctrData.xyCtr[ii] - actCtr[ii] for ii in (0,1)]
print "%s %s %s %.3f %.3f %.3f %.3f %.3f %s %s %s %r" % (
print("%s %s %s %.3f %.3f %.3f %.3f %.3f %s %s %s %r" % (
fwhm, ampl, maskWidth,
xyMeasErr[0], xyMeasErr[1],
ctrData.xyErr[0], ctrData.xyErr[1],
ctrData.asymm, ctrData.pix, ctrData.counts,
ctrData.rad, ctrData.msgStr,
)
))
ctrXStats.append(xyMeasErr[0])
ctrYStats.append(xyMeasErr[1])

print
print "Error statistics (for %d points)" % ctrXStats.nPoints()
print " min max mean stdDev"
print "xErr %8.1f %8.1f %8.1f %8.1f" % (ctrXStats.min(), ctrXStats.max(), ctrXStats.mean(), ctrXStats.stdDev())
print "yErr %8.1f %8.1f %8.1f %8.1f" % (ctrYStats.min(), ctrYStats.max(), ctrYStats.mean(), ctrYStats.stdDev())
print()
print("Error statistics (for %d points)" % ctrXStats.nPoints())
print(" min max mean stdDev")
print("xErr %8.1f %8.1f %8.1f %8.1f" % (ctrXStats.min(), ctrXStats.max(), ctrXStats.mean(), ctrXStats.stdDev()))
print("yErr %8.1f %8.1f %8.1f %8.1f" % (ctrYStats.min(), ctrYStats.max(), ctrYStats.mean(), ctrYStats.stdDev()))

if nBad > 0:
print
print "number of failures =", nBad
print()
print("number of failures =", nBad)
14 changes: 7 additions & 7 deletions tests/testStarShape.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import os.path
import sys
import PyGuide
import pyfits
from astropy.io import fits as pyfits

# these values are probably wrong for the given test image
CCDInfo = PyGuide.CCDInfo(
Expand Down Expand Up @@ -50,7 +50,7 @@
#mask = data < 0
#mask[64:101, 78:92] = 1

print "searching for stars"
print("searching for stars")
ctrDataList, imStats = PyGuide.findStars(
data = data,
mask = mask,
Expand All @@ -62,7 +62,7 @@
for ctrData in ctrDataList:
xyCtr = ctrData.xyCtr
rad = ctrData.rad
print "star xyCtr=%.2f, %.2f, radius=%s" % (xyCtr[0], xyCtr[1], rad)
print("star xyCtr=%.2f, %.2f, radius=%s" % (xyCtr[0], xyCtr[1], rad))

shapeData = PyGuide.starShape(
data,
Expand All @@ -71,8 +71,8 @@
rad = rad,
)
if not shapeData.isOK:
print "starShape failed: %s" % (shapeData.msgStr,)
print("starShape failed: %s" % (shapeData.msgStr,))
else:
print "star ampl=%.1f, fwhm=%.1f, bkgnd=%.1f, chiSq=%.2f" %\
(shapeData.ampl,shapeData.fwhm, shapeData.bkgnd, shapeData.chiSq)
print
print("star ampl=%.1f, fwhm=%.1f, bkgnd=%.1f, chiSq=%.2f" %\
(shapeData.ampl,shapeData.fwhm, shapeData.bkgnd, shapeData.chiSq))
print()
84 changes: 42 additions & 42 deletions tests/testStarShapeLong.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,33 +48,33 @@

imShape = (ImWidth, ImWidth)
nomCtr = (ImWidth // 2, ImWidth // 2)
mask = numpy.zeros(imShape, numpy.bool)
mask = numpy.zeros(imShape, numpy.bool_)

print "Compare star shape fit values to correct values"
print "over a range of fake data"
print
print "Settings:"
print "Sky =", Sky, "ADU"
print "Read Noise =", CCDInfo.readNoise, "e-"
print "CCD Gain =", CCDInfo.ccdGain, "e-/ADU"
print "Bias =", CCDInfo.bias, "ADU"
print "DoCentroid =", DoCentroid
print("Compare star shape fit values to correct values")
print("over a range of fake data")
print()
print("Settings:")
print("Sky =", Sky, "ADU")
print("Read Noise =", CCDInfo.readNoise, "e-")
print("CCD Gain =", CCDInfo.ccdGain, "e-/ADU")
print("Bias =", CCDInfo.bias, "ADU")
print("DoCentroid =", DoCentroid)
if DoCentroid:
print "Thresh =", Thresh
print "Amplitudes =", AmplValues, "ADU"
print "FWHMs =", FWHMValues, "pixels"
print "Mask Widths =", MaskWidthsPerFWHM, "fractions of a FWHM"
print "Num Tries =", NumTries, "number of cases per star shape"
print "CCD Size =", ImWidth, "x", ImWidth, "pixels"
print
print "Each try is a star whose center is randomly distributed over"
print "a range of -FWHM/2, FWHM/2 with respect to the"
print "center of the CCD = the center of the slit."
print
print "Reported errors and statistics on these errors are in percent:"
print "reported error (%) = 100 * (meas value - act value) / act value"
print
print "The slit is along y."
print("Thresh =", Thresh)
print("Amplitudes =", AmplValues, "ADU")
print("FWHMs =", FWHMValues, "pixels")
print("Mask Widths =", MaskWidthsPerFWHM, "fractions of a FWHM")
print("Num Tries =", NumTries, "number of cases per star shape")
print("CCD Size =", ImWidth, "x", ImWidth, "pixels")
print()
print("Each try is a star whose center is randomly distributed over")
print("a range of -FWHM/2, FWHM/2 with respect to the")
print("center of the CCD = the center of the slit.")
print()
print("Reported errors and statistics on these errors are in percent:")
print("reported error (%) = 100 * (meas value - act value) / act value")
print()
print("The slit is along y.")

def pctErr(meas, act):
return (meas - act) * 100.0 / float(act)
Expand All @@ -85,8 +85,8 @@ def pctErr(meas, act):
nBadCtr = 0
nBad = 0

print
print "fwhm ampl bg xCtr yCtr maskWid xCtMeas yCtMeas fitFWHM fitAmpl fitBg chiSq fwhmErr amplErr bgErr msgs"
print()
print("fwhm ampl bg xCtr yCtr maskWid xCtMeas yCtMeas fitFWHM fitAmpl fitBg chiSq fwhmErr amplErr bgErr msgs")
bkgnd = Sky + CCDInfo.bias
for ampl in AmplValues:
for fwhm in FWHMValues:
Expand Down Expand Up @@ -120,11 +120,11 @@ def pctErr(meas, act):
thresh = Thresh,
)
if not ctrData.isOK:
print "%.1f %.1f %.1f %.2f %.2f %.2f NaN NaN NaN NaN NaN NaN NaN NaN NaN %r" % (
print("%.1f %.1f %.1f %.2f %.2f %.2f NaN NaN NaN NaN NaN NaN NaN NaN NaN %r" % (
fwhm, ampl, bkgnd,
xyCtr[0], xyCtr[1], maskWidth,
ctrData.msgStr,
)
))
nBadCtr += 1
continue
else:
Expand All @@ -140,37 +140,37 @@ def pctErr(meas, act):
rad = fwhm * 3,
)
if not shapeData.isOK:
print "%.1f %.1f %.1f %.2f %.2f %.2f %.2f %.2f NaN NaN NaN NaN NaN NaN NaN %r" % (
print("%.1f %.1f %.1f %.2f %.2f %.2f %.2f %.2f NaN NaN NaN NaN NaN NaN NaN %r" % (
fwhm, ampl, bkgnd,
xyCtr[0], xyCtr[1], maskWidth, ctrData.xyCtr[0], ctrData.xyCtr[1],
shapeData.msgStr,
)
))
nBad += 1
continue

fwhmErr = pctErr(shapeData.fwhm, fwhm)
amplErr = pctErr(shapeData.ampl, ampl)
bkgndErr = pctErr(shapeData.bkgnd, bkgnd)
print "%.1f %.1f %.1f %.2f %.2f %.2f %.2f %.2f %.1f %.1f %.1f %.2f %.1f %.1f %.1f %r" % (
print("%.1f %.1f %.1f %.2f %.2f %.2f %.2f %.2f %.1f %.1f %.1f %.2f %.1f %.1f %.1f %r" % (
fwhm, ampl, bkgnd,
xyCtr[0], xyCtr[1], maskWidth, ctrData.xyCtr[0], ctrData.xyCtr[1],
shapeData.fwhm, shapeData.ampl, shapeData.bkgnd, shapeData.chiSq,
fwhmErr, amplErr, bkgndErr,
shapeData.msgStr,
)
))
fwhmStats.append(fwhmErr)
amplStats.append(amplErr)
bkgndStats.append(bkgndErr)

print
print "Error statistics (for %d points)" % fwhmStats.nPoints()
print " min max mean stdDev"
print "fwhm %8.1f %8.1f %8.1f %8.1f" % (fwhmStats.min(), fwhmStats.max(), fwhmStats.mean(), fwhmStats.stdDev())
print "ampl %8.1f %8.1f %8.1f %8.1f" % (amplStats.min(), amplStats.max(), amplStats.mean(), amplStats.stdDev())
print "bkgnd %8.1f %8.1f %8.1f %8.1f" % (bkgndStats.min(), bkgndStats.max(), bkgndStats.mean(), bkgndStats.stdDev())
print()
print("Error statistics (for %d points)" % fwhmStats.nPoints())
print(" min max mean stdDev")
print("fwhm %8.1f %8.1f %8.1f %8.1f" % (fwhmStats.min(), fwhmStats.max(), fwhmStats.mean(), fwhmStats.stdDev()))
print("ampl %8.1f %8.1f %8.1f %8.1f" % (amplStats.min(), amplStats.max(), amplStats.mean(), amplStats.stdDev()))
print("bkgnd %8.1f %8.1f %8.1f %8.1f" % (bkgndStats.min(), bkgndStats.max(), bkgndStats.mean(), bkgndStats.stdDev()))

if (nBad > 0) or (nBadCtr > 0):
print
print "number of shape fit failures =", nBad
print()
print("number of shape fit failures =", nBad)
if DoCentroid:
print "number of centroid failures =", nBadCtr
print("number of centroid failures =", nBadCtr)
Loading