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

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

# This file is part of ap_association. 

# 

# Developed for the LSST Data Management System. 

# This product includes software developed by the LSST Project 

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

# See the COPYRIGHT file at the top-level directory of this distribution 

# for details of code ownership. 

# 

# 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 GNU General Public License 

# along with this program. If not, see <http://www.gnu.org/licenses/>. 

# 

 

__all__ = ["NumberNewDiaObjectsMetricTask", 

"NumberUnassociatedDiaObjectsMetricTask", 

"FractionUpdatedDiaObjectsMetricTask", 

"TotalUnassociatedDiaObjectsMetricTask", 

] 

 

 

import astropy.units as u 

 

from lsst.verify import Measurement 

from lsst.verify.gen2tasks import register 

from lsst.verify.tasks import MetadataMetricTask, ApdbMetricTask, MetricComputationError 

 

 

@register("numNewDiaObjects") 

class NumberNewDiaObjectsMetricTask(MetadataMetricTask): 

"""Task that computes the number of DIASources that create new DIAObjects 

in an image, visit, etc.. 

""" 

_DefaultName = "numNewDiaObjects" 

 

def makeMeasurement(self, values): 

"""Compute the number of new DIAObjects. 

 

Parameters 

---------- 

values : `dict` [`str`, `int` or `None`] 

A `dict` representation of the metadata. Each `dict` has the 

following key: 

 

``"newObjects"`` 

The number of new objects created for this image (`int` 

or `None`). May be `None` if the image was not successfully 

associated. 

 

Returns 

------- 

measurement : `lsst.verify.Measurement` or `None` 

The total number of new objects. 

""" 

if values["newObjects"] is not None: 

try: 

nNew = int(values["newObjects"]) 

except (ValueError, TypeError) as e: 

raise MetricComputationError("Corrupted value of numNewDiaObjects") from e 

else: 

return Measurement(self.getOutputMetricName(self.config), 

nNew * u.count) 

else: 

self.log.info("Nothing to do: no association results found.") 

return None 

 

@classmethod 

def getInputMetadataKeys(cls, config): 

return {"newObjects": ".numNewDiaObjects"} 

 

@classmethod 

def getOutputMetricName(cls, config): 

return "ap_association.numNewDiaObjects" 

 

 

@register("numUnassociatedDiaObjects") 

class NumberUnassociatedDiaObjectsMetricTask(MetadataMetricTask): 

"""Task that computes the number of previously-known DIAObjects that do 

not have detected DIASources in an image, visit, etc.. 

""" 

_DefaultName = "numUnassociatedDiaObjects" 

 

def makeMeasurement(self, values): 

"""Compute the number of non-updated DIAObjects. 

 

Parameters 

---------- 

values : `dict` [`str`, `int` or `None`] 

A `dict` representation of the metadata. Each `dict` has the 

following key: 

 

``"unassociatedObjects"`` 

The number of DIAObjects not associated with a DiaSource in 

this image (`int` or `None`). May be `None` if the image was 

not successfully associated. 

 

Returns 

------- 

measurement : `lsst.verify.Measurement` or `None` 

The total number of unassociated objects. 

""" 

if values["unassociatedObjects"] is not None: 

try: 

nNew = int(values["unassociatedObjects"]) 

except (ValueError, TypeError) as e: 

raise MetricComputationError("Corrupted value of numUnassociatedDiaObjects") from e 

else: 

return Measurement(self.getOutputMetricName(self.config), 

nNew * u.count) 

else: 

self.log.info("Nothing to do: no association results found.") 

return None 

 

@classmethod 

def getInputMetadataKeys(cls, config): 

return {"unassociatedObjects": ".numUnassociatedDiaObjects"} 

 

@classmethod 

def getOutputMetricName(cls, config): 

return "ap_association.numUnassociatedDiaObjects" 

 

 

@register("fracUpdatedDiaObjects") 

class FractionUpdatedDiaObjectsMetricTask(MetadataMetricTask): 

"""Task that computes the fraction of previously created DIAObjects that 

have a new association in this image, visit, etc.. 

""" 

_DefaultName = "fracUpdatedDiaObjects" 

 

def makeMeasurement(self, values): 

"""Compute the number of non-updated DIAObjects. 

 

AssociationTask reports each pre-existing DIAObject as either updated 

(associated with a new DIASource) or unassociated. 

 

Parameters 

---------- 

values : `dict` [`str`, `int` or `None`] 

A `dict` representation of the metadata. Each `dict` has the 

following keys: 

 

``"updatedObjects"`` 

The number of DIAObjects updated for this image (`int` or 

`None`). May be `None` if the image was not 

successfully associated. 

``"unassociatedObjects"`` 

The number of DIAObjects not associated with a DiaSource in 

this image (`int` or `None`). May be `None` if the image was 

not successfully associated. 

 

Returns 

------- 

measurement : `lsst.verify.Measurement` or `None` 

The total number of unassociated objects. 

""" 

if values["updatedObjects"] is not None \ 

and values["unassociatedObjects"] is not None: 

try: 

nUpdated = int(values["updatedObjects"]) 

nUnassociated = int(values["unassociatedObjects"]) 

except (ValueError, TypeError) as e: 

raise MetricComputationError("Corrupted value of numUpdatedDiaObjects " 

"or numUnassociatedDiaObjects") from e 

else: 

if nUpdated <= 0 and nUnassociated <= 0: 

return None # No pre-existing DIAObjects; no fraction to compute 

else: 

fraction = nUpdated / (nUpdated + nUnassociated) 

return Measurement(self.getOutputMetricName(self.config), 

fraction * u.dimensionless_unscaled) 

else: 

self.log.info("Nothing to do: no association results found.") 

return None 

 

@classmethod 

def getInputMetadataKeys(cls, config): 

return {"updatedObjects": ".numUpdatedDiaObjects", 

"unassociatedObjects": ".numUnassociatedDiaObjects"} 

 

@classmethod 

def getOutputMetricName(cls, config): 

return "ap_association.fracUpdatedDiaObjects" 

 

 

@register("totalUnassociatedDiaObjects") 

class TotalUnassociatedDiaObjectsMetricTask(ApdbMetricTask): 

"""Task that computes the number of DIAObjects with only one 

associated DIASource. 

""" 

_DefaultName = "totalUnassociatedDiaObjects" 

 

def makeMeasurement(self, dbHandle, outputDataId): 

"""Compute the number of unassociated DIAObjects. 

 

Parameters 

---------- 

dbHandle : `lsst.dax.apdb.Apdb` 

A database instance. 

outputDataId : any data ID type 

The subset of the database to which this measurement applies. 

Must be empty, as the number of unassociated sources is 

ill-defined for subsets of the dataset. 

 

Returns 

------- 

measurement : `lsst.verify.Measurement` 

The total number of unassociated objects. 

 

Raises 

------ 

MetricComputationError 

Raised on any failure to query the database. 

ValueError 

Raised if outputDataId is not empty 

""" 

# All data ID types define keys() 

if outputDataId.keys(): 

raise ValueError("%s must not be associated with specific data IDs." 

% self.getOutputMetricName(self.config)) 

 

try: 

nUnassociatedDiaObjects = dbHandle.countUnassociatedObjects() 

except Exception as e: 

raise MetricComputationError("Could not get unassociated objects from database") from e 

 

meas = Measurement(self.getOutputMetricName(self.config), nUnassociatedDiaObjects * u.count) 

return meas 

 

@classmethod 

def getOutputMetricName(cls, config): 

return "ap_association.totalUnassociatedDiaObjects"