Coverage for python/lsst/verify/report.py: 16%

49 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2022-12-16 02:08 -0800

1# This file is part of verify. 

2# 

3# Developed for the LSST Data Management System. 

4# This product includes software developed by the LSST Project 

5# (https://www.lsst.org). 

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

7# for details of code ownership. 

8# 

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

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

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

12# (at your option) any later version. 

13# 

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

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

16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

17# GNU General Public License for more details. 

18# 

19# You should have received a copy of the GNU General Public License 

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

21__all__ = ['Report'] 

22 

23from astropy.table import Table 

24import numpy as np 

25 

26from .naming import Name 

27 

28 

29class Report(object): 

30 r"""Report tabulating specification pass/fail status for a set of 

31 `lsst.verify.Measurement`\ s. 

32 

33 Parameters 

34 ---------- 

35 measurements : `lsst.verify.MeasurementSet` 

36 Measurements to be tested. 

37 specs : `lsst.verify.SpecificationSet` 

38 Specifications to test measurements against. These specifications 

39 are assumed to be relevant to the measurements. Use 

40 `lsst.verify.SpecificationSet.subset`, passing in job metadata 

41 (`lsst.verify.Job.meta`), to ensure this. 

42 """ 

43 

44 def __init__(self, measurements, specs): 

45 self._meas_set = measurements 

46 self._spec_set = specs 

47 

48 def make_table(self): 

49 """Make an table summarizing specification tests of measurements. 

50 

51 Returns 

52 ------- 

53 table : `astropy.table.Table` 

54 Table with columns: 

55 

56 - **Status** 

57 - **Specification** 

58 - **Measurement** 

59 - **Test** 

60 - **Metric Tags** 

61 - **Spec. Tags** 

62 """ 

63 # Columns for the table 

64 statuses = [] 

65 spec_name_items = [] 

66 measurements = [] 

67 tests = [] 

68 metric_tags = [] 

69 spec_tags = [] 

70 

71 spec_names = list(self._spec_set.keys()) 

72 spec_names.sort() 

73 

74 for spec_name in spec_names: 

75 # Test if there is a measurement for this specification, 

76 # if not, we just skip it. 

77 metric_name = Name(package=spec_name.package, 

78 metric=spec_name.metric) 

79 try: 

80 meas = self._meas_set[metric_name] 

81 except KeyError: 

82 # No measurement for this specification, just skip it. 

83 continue 

84 

85 spec = self._spec_set[spec_name] 

86 

87 if np.isnan(meas.quantity): 

88 # Not measured 

89 # https://emojipedia.org/heavy-minus-sign/ 

90 statuses.append(u'\U00002796') 

91 elif spec.check(meas.quantity): 

92 # Passed 

93 # http://emojipedia.org/white-heavy-check-mark/ 

94 statuses.append(u'\U00002705') 

95 else: 

96 # Failed. 

97 # http://emojipedia.org/cross-mark/ 

98 statuses.append(u'\U0000274C') 

99 

100 spec_name_items.append(str(spec_name)) 

101 

102 measurements.append(meas._repr_latex_()) 

103 

104 tests.append(spec._repr_latex_()) 

105 

106 tags = list(spec.tags) 

107 tags.sort() 

108 spec_tags.append(', '.join(tags)) 

109 

110 metric = meas.metric 

111 if metric is None: 

112 # no metric is available, this is the default 

113 metric_tags.append('N/A') 

114 else: 

115 tags = list(metric.tags) 

116 tags.sort() 

117 metric_tags.append(', '.join(tags)) 

118 

119 table = Table([statuses, spec_name_items, measurements, tests, 

120 metric_tags, spec_tags], 

121 names=['Status', 'Specification', 'Measurement', 'Test', 

122 'Metric Tags', 'Spec. Tags']) 

123 return table 

124 

125 def _repr_html_(self): 

126 """HTML representation of the report for Jupyter notebooks.""" 

127 table = self.make_table() 

128 return table._repr_html_() 

129 

130 def show(self): 

131 """Display the report in a Jupyter notebook.""" 

132 table = self.make_table() 

133 return table.show_in_notebook(show_row_index='')