LSSTApplications  18.1.0
LSSTDataManagementBasePackage
comparison.py
Go to the documentation of this file.
1 #
2 # LSST Data Management System
3 # Copyright 2008-2013 LSST Corporation.
4 #
5 # This product includes software developed by the
6 # LSST Project (http://www.lsst.org/).
7 #
8 # This program is free software: you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation, either version 3 of the License, or
11 # (at your option) any later version.
12 #
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
17 #
18 # You should have received a copy of the LSST License Statement and
19 # the GNU General Public License along with this program. If not,
20 # see <http://www.lsstcorp.org/LegalNotices/>.
21 #
22 """Helper functions for comparing `lsst.pex.config.Config` instancess.
23 
24 Theses function should be use for any comparison in a `lsst.pex.Config.compare`
25 or `lsst.pex.config.Field._compare` implementation, as they take care of
26 writing messages as well as floating-point comparisons and shortcuts.
27 """
28 
29 import numpy
30 
31 __all__ = ("getComparisonName", "compareScalars", "compareConfigs")
32 
33 
34 def getComparisonName(name1, name2):
35  """Create a comparison name that is used for printed output of comparisons.
36 
37  Parameters
38  ----------
39  name1 : `str`
40  Name of the first configuration.
41  name2 : `str`
42  Name of the second configuration.
43 
44  Returns
45  -------
46  name : `str`
47  When ``name1`` and ``name2`` are equal, the returned name is
48  simply one of the names. When they are different the returned name is
49  formatted as ``"{name1} / {name2}"``.
50  """
51  if name1 != name2:
52  return "%s / %s" % (name1, name2)
53  return name1
54 
55 
56 def compareScalars(name, v1, v2, output, rtol=1E-8, atol=1E-8, dtype=None):
57  """Compare two scalar values for equality.
58 
59  This function is a helper for `lsst.pex.config.Config.compare`.
60 
61  Parameters
62  ----------
63  name : `str`
64  Name to use when reporting differences, typically created by
65  `getComparisonName`.
66  v1 : object
67  Left-hand side value to compare.
68  v2 : object
69  Right-hand side value to compare.
70  output : callable or `None`
71  A callable that takes a string, used (possibly repeatedly) to report
72  inequalities (for example, `print`). Set to `None` to disable output.
73  rtol : `float`, optional
74  Relative tolerance for floating point comparisons.
75  atol : `float`, optional
76  Absolute tolerance for floating point comparisons.
77  dtype : class, optional
78  Data type of values for comparison. May be `None` if values are not
79  floating-point.
80 
81  Returns
82  -------
83  areEqual : `bool`
84  `True` if the values are equal, `False` if they are not.
85 
86  See also
87  --------
88  lsst.pex.config.compareConfigs
89 
90  Notes
91  -----
92  Floating point comparisons are performed by `numpy.allclose`.
93  """
94  if v1 is None or v2 is None:
95  result = (v1 == v2)
96  elif dtype in (float, complex):
97  result = numpy.allclose(v1, v2, rtol=rtol, atol=atol) or (numpy.isnan(v1) and numpy.isnan(v2))
98  else:
99  result = (v1 == v2)
100  if not result and output is not None:
101  output("Inequality in %s: %r != %r" % (name, v1, v2))
102  return result
103 
104 
105 def compareConfigs(name, c1, c2, shortcut=True, rtol=1E-8, atol=1E-8, output=None):
106  """Compare two `lsst.pex.config.Config` instances for equality.
107 
108  This function is a helper for `lsst.pex.config.Config.compare`.
109 
110  Parameters
111  ----------
112  name : `str`
113  Name to use when reporting differences, typically created by
114  `getComparisonName`.
115  v1 : `lsst.pex.config.Config`
116  Left-hand side config to compare.
117  v2 : `lsst.pex.config.Config`
118  Right-hand side config to compare.
119  shortcut : `bool`, optional
120  If `True`, return as soon as an inequality is found. Default is `True`.
121  rtol : `float`, optional
122  Relative tolerance for floating point comparisons.
123  atol : `float`, optional
124  Absolute tolerance for floating point comparisons.
125  output : callable, optional
126  A callable that takes a string, used (possibly repeatedly) to report
127  inequalities. For example: `print`.
128 
129  Returns
130  -------
131  areEqual : `bool`
132  `True` when the two `lsst.pex.config.Config` instances are equal.
133  `False` if there is an inequality.
134 
135  See also
136  --------
137  lsst.pex.config.compareScalars
138 
139  Notes
140  -----
141  Floating point comparisons are performed by `numpy.allclose`.
142 
143  If ``c1`` or ``c2`` contain `~lsst.pex.config.RegistryField` or
144  `~lsst.pex.config.ConfigChoiceField` instances, *unselected*
145  `~lsst.pex.config.Config` instances will not be compared.
146  """
147  assert name is not None
148  if c1 is None:
149  if c2 is None:
150  return True
151  else:
152  if output is not None:
153  output("LHS is None for %s" % name)
154  return False
155  else:
156  if c2 is None:
157  if output is not None:
158  output("RHS is None for %s" % name)
159  return False
160  if type(c1) != type(c2):
161  if output is not None:
162  output("Config types do not match for %s: %s != %s" % (name, type(c1), type(c2)))
163  return False
164  equal = True
165  for field in c1._fields.values():
166  result = field._compare(c1, c2, shortcut=shortcut, rtol=rtol, atol=atol, output=output)
167  if not result and shortcut:
168  return False
169  equal = equal and result
170  return equal
def compareConfigs(name, c1, c2, shortcut=True, rtol=1E-8, atol=1E-8, output=None)
Definition: comparison.py:105
table::Key< int > type
Definition: Detector.cc:167
def compareScalars(name, v1, v2, output, rtol=1E-8, atol=1E-8, dtype=None)
Definition: comparison.py:56
def getComparisonName(name1, name2)
Definition: comparison.py:34