Coverage for python/lsst/verify/bin/inspectjob.py: 15%
45 statements
« prev ^ index » next coverage.py v6.4.2, created at 2022-07-24 09:24 +0000
« prev ^ index » next coverage.py v6.4.2, created at 2022-07-24 09:24 +0000
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"""Print the measurements and metadata in lsst.verify JSON files.
23This script takes as arguments one or more lsst.verify JSON files, and prints
24the top-level metadata and a summary of any measurements.
26This script does not print information about metrics or specifications.
27"""
29__all__ = ["main", "inspect_job"]
31import argparse
32import json
34from lsst.verify import Job
37def _is_measurement_metadata(key, metrics):
38 """Test whether a job-level metadata key is really measurement metadata.
40 Parameters
41 ----------
42 key : `str`
43 The metadata key to test.
44 metrics : iterable of `lsst.verify.Name` or of `str`
45 The metrics recorded in the job.
47 Returns
48 -------
49 result : `bool`
50 `True` if ``key`` represents measurement metadata, `False` if it
51 represents purely job-level metadata.
52 """
53 for metric in metrics:
54 if str(metric) in key:
55 return True
56 return False
59def _simplify_key(key, prefix):
60 """Remove a prefix from a key, if it's present.
62 Parameters
63 ----------
64 key : `str`
65 The key to simplify.
66 prefix : `str`
67 The prefix to remove from ``key``.
69 Returns
70 -------
71 simplifiedKey : `str`
72 ``key`` with any initial ``prefix`` removed
73 """
74 if key.startswith(prefix):
75 return key.replace(prefix, "", 1)
76 else:
77 return key
80def _get_first_col_width(job):
81 """Return the width to use for the output's first column.
83 This column displays metadata and metric keys.
85 Parameters
86 ----------
87 job : `lsst.verify.Job`
88 The Job to print.
90 Returns
91 -------
92 width : `int`
93 The minimum width to use to format the Job's values. May be 0 if the
94 Job is empty.
95 """
96 max_meta = max(len(key) for key in job.meta) if job.meta else 0
97 max_meas = max(len(str(metric)) for metric in job.measurements) \
98 if job.measurements else 0
100 return max(max_meta, max_meas)
103def inspect_job(job):
104 """Present the measurements in a Job object.
106 The measurements and any metadata are printed to standard output.
108 Parameters
109 ----------
110 job : `lsst.verify.Job`
111 The Job to examine.
112 """
113 # Leave enough space for output so that all '=' characters are aligned
114 max_metric_length = _get_first_col_width(job)
116 print("Common metadata:")
117 for key, value in job.meta.items():
118 if _is_measurement_metadata(key, job.measurements.keys()):
119 continue
120 print("%*s = %s" % (max_metric_length, key, value))
122 print("\nMeasurements:")
123 for metric, measurement in job.measurements.items():
124 pretty_quantity = measurement.quantity.round(4)
125 if measurement.notes:
126 prefix = str(measurement.metric_name) + "."
127 # Raw representation of measurement.notes hard to read
128 simple_notes = {_simplify_key(key, prefix): value
129 for key, value in measurement.notes.items()}
130 print("%*s = %10s (%s)"
131 % (max_metric_length, metric, pretty_quantity, simple_notes))
132 else:
133 print("%*s = %10s" % (max_metric_length, metric, pretty_quantity))
136def build_argparser():
137 """Construct an argument parser for the ``inspect_job.py`` script.
139 Returns
140 -------
141 argparser : `argparse.ArgumentParser`
142 The argument parser that defines the ``inspect_job.py`` command-line
143 interface.
144 """
145 parser = argparse.ArgumentParser(
146 description=__doc__,
147 formatter_class=argparse.RawDescriptionHelpFormatter,
148 epilog='More information is available at https://pipelines.lsst.io.')
149 parser.add_argument(
150 'json_paths',
151 nargs='+',
152 metavar='json',
153 help='lsst.verify JSON file, or files (``*verify.json``).')
154 return parser
157def main():
158 """Present all Job files.
159 """
160 args = build_argparser().parse_args()
161 for filename in args.json_paths:
162 if len(args.json_paths) > 1:
163 print("\n%s:" % filename)
164 with open(filename) as f:
165 job = Job.deserialize(**json.load(f))
166 inspect_job(job)