Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

# 

# LSST Data Management System 

# 

# Copyright 2008-2016 AURA/LSST. 

# 

# This product includes software developed by the 

# LSST Project (http://www.lsst.org/). 

# 

# This program is free software: you can redistribute it and/or modify 

# it under the terms of the GNU General Public License as published by 

# the Free Software Foundation, either version 3 of the License, or 

# (at your option) any later version. 

# 

# This program is distributed in the hope that it will be useful, 

# but WITHOUT ANY WARRANTY; without even the implied warranty of 

# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

# GNU General Public License for more details. 

# 

# You should have received a copy of the LSST License Statement and 

# the GNU General Public License along with this program. If not, 

# see <https://www.lsstcorp.org/LegalNotices/>. 

# 

import math 

import os.path 

import unittest 

import pickle 

 

import lsst.utils.tests 

from lsst.obs.hsc import HscMapper 

from lsst.pipe.base import Struct 

from lsst.afw.geom import transformRegistry 

from lsst.afw.cameraGeom import FOCAL_PLANE, FIELD_ANGLE, PIXELS 

 

# Set SAVE_DATA True to save new distortion data; this will make the test fail, 

# to remind you to set it False before committing the code. 

SAVE_DATA = False 

 

DataFileName = "data/distortionData.pickle" # path relative to the tests directory 

 

 

class HscDistortionTestCase(lsst.utils.tests.TestCase): 

"""Testing HscDistortion implementation 

 

HscDistortion is based on the HSC package "distEst". We 

test that it produces the same results. 

""" 

def testDistortion(self): 

"""Test that the distortion data matches the saved data or create new data 

 

If SAVE_DATA is true then save newly created data and then fail the test 

in order to prevent anyone from committing the test with SAVE_DATA true! 

 

Otherwise create new data and compare to the saved data 

""" 

newData = self.makeDistortionData() 

dataPath = os.path.join(os.path.dirname(__file__), DataFileName) 

 

if SAVE_DATA: 

with open(dataPath, "wb") as dataFile: 

pickle.dump(newData, dataFile, protocol=2) 

self.fail("Saved new data to %r; please set SAVE_DATA back to False" % dataPath) 

 

if not os.path.exists(dataPath): 

self.fail("Cannot find saved data %r; set SAVE_DATA = True and run again to save new data" % 

dataPath) 

 

fieldAngleToFocalPlaneTolerance = transformRegistry["hsc"].ConfigClass().tolerance 

 

with open(dataPath, "rb") as dataFile: 

savedData = pickle.load(dataFile) 

maxRoundTripFocalPlaneError = 0 

maxRoundTripPixPosError = 0 

for detectorName, ccdData in newData.items(): 

savedCcdData = savedData[detectorName] 

self.assertEqual(ccdData.serial, savedCcdData.serial) 

for pixPosKey, cornerData in ccdData.cornerDict.items(): 

savedCornerData = savedCcdData.cornerDict[pixPosKey] 

self.assertEqual(cornerData.pixPos, savedCornerData.pixPos) 

self.assertPairsAlmostEqual(cornerData.focalPlane, savedCornerData.focalPlane) 

self.assertPairsAlmostEqual(cornerData.fieldAngle, savedCornerData.fieldAngle) 

maxRoundTripFocalPlaneError = max( 

maxRoundTripFocalPlaneError, 

math.hypot(*(cornerData.focalPlaneRoundTrip - cornerData.focalPlane)) 

) 

self.assertPairsAlmostEqual(cornerData.focalPlaneRoundTrip, cornerData.focalPlane, 

maxDiff=fieldAngleToFocalPlaneTolerance) 

maxRoundTripPixPosError = max(maxRoundTripPixPosError, 

math.hypot(*(cornerData.pixPosRoundTrip - cornerData.pixPos))) 

self.assertPairsAlmostEqual(cornerData.pixPosRoundTrip, cornerData.pixPos) 

print("maxRoundTripFocalPlaneError =", maxRoundTripFocalPlaneError) 

print("maxRoundTripPixPosError =", maxRoundTripPixPosError) 

 

def makeDistortionData(self): 

"""Make distortion data 

 

The data format is a dict of detector name: ccdData, where 

ccdData is a Struct containing these fields: 

- serial: detector.getSerial 

- cornerDict: a dict of pixPosKey, cornerData, where: 

- pixPosKey: self.asKey(pixPos) where pixPos is pixel position 

- cornerData is Struct contains these fields (all of type lsst.afw.geom.Point2D): 

- pixPos: pixel position 

- focalPlane: focal plane position computed from pixPos 

- fieldAngle: fieldAngle position computed from focalPlane 

- focalPlaneRoundTrip: focal plane position computed from fieldAngle 

- pixPosRoundTrip: pixel position computed from focalPlane 

""" 

camera = HscMapper(root=".", calibRoot=".").camera 

focalPlaneToFieldAngle = camera.getTransformMap().getTransform(FOCAL_PLANE, FIELD_ANGLE) 

data = {} # dict of detector name: CcdData 

for detector in camera: 

# for each corner of each CCD: 

# - get pixel position 

# - convert to focal plane coordinates using the detector and record it 

# - convert to field angle (this is the conversion that uses HscDistortion) and record it 

# - convert back to focal plane (testing inverse direction of HscDistortion) and record it 

# - convert back to pixel position and record it; pixel <-> focal plane is affine 

# so there is no reason to doubt the inverse transform, but there is no harm 

pixelsToFocalPlane = detector.getTransform(PIXELS, FOCAL_PLANE) 

cornerDict = {} 

for pixPos in detector.getCorners(PIXELS): 

pixPos = pixPos 

focalPlane = pixelsToFocalPlane.applyForward(pixPos) 

fieldAngle = focalPlaneToFieldAngle.applyForward(focalPlane) 

focalPlaneRoundTrip = focalPlaneToFieldAngle.applyInverse(fieldAngle) 

pixPosRoundTrip = pixelsToFocalPlane.applyInverse(focalPlane) 

cornerDict[self.toKey(pixPos)] = Struct( 

pixPos = pixPos, 

focalPlane = focalPlane, 

fieldAngle = fieldAngle, 

focalPlaneRoundTrip = focalPlaneRoundTrip, 

pixPosRoundTrip = pixPosRoundTrip, 

) 

 

data[detector.getName()] = Struct(serial=detector.getSerial(), cornerDict=cornerDict) 

 

return data 

 

def toKey(self, pixPos): 

return "(%0.1f, %0.1f)" % tuple(pixPos) 

 

 

class TestMemory(lsst.utils.tests.MemoryTestCase): 

def setUp(self): 

HscMapper.clearCache() 

lsst.utils.tests.MemoryTestCase.setUp(self) 

 

 

def setup_module(module): 

lsst.utils.tests.init() 

 

 

153 ↛ 154line 153 didn't jump to line 154, because the condition on line 153 was never trueif __name__ == "__main__": 

lsst.utils.tests.init() 

unittest.main()