lsst-utils 29.2025.1700__tar.gz → 29.2025.1900__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. {lsst_utils-29.2025.1700/python/lsst_utils.egg-info → lsst_utils-29.2025.1900}/PKG-INFO +2 -1
  2. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/pyproject.toml +1 -0
  3. lsst_utils-29.2025.1900/python/lsst/utils/plotting/publication_plots.py +171 -0
  4. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/python/lsst/utils/plotting/rubin.mplstyle +9 -9
  5. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/python/lsst/utils/timer.py +46 -7
  6. lsst_utils-29.2025.1900/python/lsst/utils/version.py +2 -0
  7. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900/python/lsst_utils.egg-info}/PKG-INFO +2 -1
  8. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/python/lsst_utils.egg-info/requires.txt +1 -0
  9. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/tests/test_matplotlib_figures.py +44 -0
  10. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/tests/test_timer.py +32 -0
  11. lsst_utils-29.2025.1700/python/lsst/utils/plotting/publication_plots.py +0 -56
  12. lsst_utils-29.2025.1700/python/lsst/utils/version.py +0 -2
  13. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/COPYRIGHT +0 -0
  14. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/LICENSE +0 -0
  15. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/MANIFEST.in +0 -0
  16. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/README.rst +0 -0
  17. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/doc/lsst.utils/CHANGES.rst +0 -0
  18. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/doc/lsst.utils/index.rst +0 -0
  19. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/python/lsst/__init__.py +0 -0
  20. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/python/lsst/utils/__init__.py +0 -0
  21. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/python/lsst/utils/_packaging.py +0 -0
  22. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/python/lsst/utils/argparsing.py +0 -0
  23. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/python/lsst/utils/classes.py +0 -0
  24. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/python/lsst/utils/db_auth.py +0 -0
  25. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/python/lsst/utils/deprecated.py +0 -0
  26. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/python/lsst/utils/doImport.py +0 -0
  27. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/python/lsst/utils/inheritDoc.py +0 -0
  28. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/python/lsst/utils/introspection.py +0 -0
  29. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/python/lsst/utils/iteration.py +0 -0
  30. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/python/lsst/utils/logging.py +0 -0
  31. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/python/lsst/utils/packages.py +0 -0
  32. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/python/lsst/utils/plotting/__init__.py +0 -0
  33. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/python/lsst/utils/plotting/figures.py +0 -0
  34. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/python/lsst/utils/plotting/limits.py +0 -0
  35. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/python/lsst/utils/py.typed +0 -0
  36. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/python/lsst/utils/tests.py +0 -0
  37. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/python/lsst/utils/threads.py +0 -0
  38. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/python/lsst/utils/usage.py +0 -0
  39. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/python/lsst/utils/wrappers.py +0 -0
  40. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/python/lsst_utils.egg-info/SOURCES.txt +0 -0
  41. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/python/lsst_utils.egg-info/dependency_links.txt +0 -0
  42. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/python/lsst_utils.egg-info/top_level.txt +0 -0
  43. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/python/lsst_utils.egg-info/zip-safe +0 -0
  44. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/setup.cfg +0 -0
  45. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/tests/test_argparsing.py +0 -0
  46. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/tests/test_classes.py +0 -0
  47. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/tests/test_db_auth.py +0 -0
  48. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/tests/test_decorators.py +0 -0
  49. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/tests/test_deprecated.py +0 -0
  50. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/tests/test_doImport.py +0 -0
  51. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/tests/test_executables.py +0 -0
  52. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/tests/test_getPackageDir.py +0 -0
  53. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/tests/test_getTempFilePath.py +0 -0
  54. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/tests/test_import.py +0 -0
  55. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/tests/test_inheritDoc.py +0 -0
  56. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/tests/test_introspection.py +0 -0
  57. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/tests/test_iteration.py +0 -0
  58. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/tests/test_logging.py +0 -0
  59. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/tests/test_ordering.py +0 -0
  60. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/tests/test_packages.py +0 -0
  61. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/tests/test_plotting_limits.py +0 -0
  62. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/tests/test_threads.py +0 -0
  63. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/tests/test_usage.py +0 -0
  64. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/tests/test_utils.py +0 -0
  65. {lsst_utils-29.2025.1700 → lsst_utils-29.2025.1900}/tests/test_wrappers.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lsst-utils
3
- Version: 29.2025.1700
3
+ Version: 29.2025.1900
4
4
  Summary: Utility functions from Rubin Observatory Data Management for the Legacy Survey of Space and Time (LSST).
5
5
  Author-email: Rubin Observatory Data Management <dm-admin@lists.lsst.org>
6
6
  License: BSD 3-Clause License
@@ -27,6 +27,7 @@ Provides-Extra: test
27
27
  Requires-Dist: pytest>=3.2; extra == "test"
28
28
  Provides-Extra: plotting
29
29
  Requires-Dist: matplotlib; extra == "plotting"
30
+ Requires-Dist: seaborn; extra == "plotting"
30
31
  Dynamic: license-file
31
32
 
32
33
  ==========
@@ -38,6 +38,7 @@ test = [
38
38
  ]
39
39
  plotting = [
40
40
  "matplotlib",
41
+ "seaborn",
41
42
  ]
42
43
 
43
44
  [tool.setuptools.packages.find]
@@ -0,0 +1,171 @@
1
+ # This file is part of utils.
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
+ # Use of this source code is governed by a 3-clause BSD-style
10
+ # license that can be found in the LICENSE file.
11
+ """Utilities for making publication-quality figures."""
12
+
13
+ __all__ = [
14
+ "accent_color",
15
+ "divergent_cmap",
16
+ "galaxies_cmap",
17
+ "galaxies_color",
18
+ "get_band_dicts",
19
+ "mk_colormap",
20
+ "set_rubin_plotstyle",
21
+ "stars_cmap",
22
+ "stars_color",
23
+ ]
24
+
25
+ import numpy as np
26
+
27
+ from . import (
28
+ get_multiband_plot_colors,
29
+ get_multiband_plot_linestyles,
30
+ get_multiband_plot_symbols,
31
+ )
32
+
33
+
34
+ def set_rubin_plotstyle() -> None:
35
+ """
36
+ Set the matplotlib style for Rubin publications
37
+ """
38
+ from matplotlib import style
39
+
40
+ style.use("lsst.utils.plotting.rubin")
41
+
42
+
43
+ def mk_colormap(colorNames): # type: ignore
44
+ """Make a colormap from the list of color names.
45
+
46
+ Parameters
47
+ ----------
48
+ colorNames : `list`
49
+ A list of strings that correspond to matplotlib named colors.
50
+
51
+ Returns
52
+ -------
53
+ cmap : `matplotlib.colors.LinearSegmentedColormap`
54
+ A colormap stepping through the supplied list of names.
55
+ """
56
+ from matplotlib import colors
57
+
58
+ blues = []
59
+ greens = []
60
+ reds = []
61
+ alphas = []
62
+
63
+ if len(colorNames) == 1:
64
+ # Alpha is between 0 and 1 really but
65
+ # using 1.5 saturates out the top of the
66
+ # colorscale, this looks good for ComCam data
67
+ # but might want to be changed in the future.
68
+ alphaRange = [0.2, 1.0]
69
+ nums = np.linspace(0, 1, len(alphaRange))
70
+ r, g, b = colors.colorConverter.to_rgb(colorNames[0])
71
+ for num, alpha in zip(nums, alphaRange):
72
+ blues.append((num, b, b))
73
+ greens.append((num, g, g))
74
+ reds.append((num, r, r))
75
+ alphas.append((num, alpha, alpha))
76
+
77
+ else:
78
+ nums = np.linspace(0, 1, len(colorNames))
79
+ if len(colorNames) == 3:
80
+ alphaRange = [1.0, 0.3, 1.0]
81
+ elif len(colorNames) == 5:
82
+ alphaRange = [1.0, 0.7, 0.3, 0.7, 1.0]
83
+ else:
84
+ alphaRange = np.ones(len(colorNames))
85
+
86
+ for num, color, alpha in zip(nums, colorNames, alphaRange):
87
+ r, g, b = colors.colorConverter.to_rgb(color)
88
+ blues.append((num, b, b))
89
+ greens.append((num, g, g))
90
+ reds.append((num, r, r))
91
+ alphas.append((num, alpha, alpha))
92
+
93
+ colorDict = {"blue": blues, "red": reds, "green": greens, "alpha": alphas}
94
+ cmap = colors.LinearSegmentedColormap("newCmap", colorDict)
95
+ return cmap
96
+
97
+
98
+ def divergent_cmap(): # type: ignore
99
+ """
100
+ Make a divergent color map.
101
+ """
102
+ import seaborn as sns
103
+ from matplotlib.colors import ListedColormap
104
+
105
+ cmap = ListedColormap(sns.color_palette("icefire", 256))
106
+
107
+ return cmap
108
+
109
+
110
+ def stars_cmap(single_color=False): # type: ignore
111
+ """Make a color map for stars."""
112
+ import seaborn as sns
113
+ from matplotlib.colors import ListedColormap
114
+
115
+ if single_color:
116
+ cmap = mk_colormap([stars_color()])
117
+ else:
118
+ cmap = ListedColormap(sns.color_palette("mako", 256))
119
+ return cmap
120
+
121
+
122
+ def stars_color() -> str:
123
+ """Return the star color string for lines"""
124
+ return "#357BA3"
125
+
126
+
127
+ def accent_color() -> str:
128
+ """Return a contrasting color for overplotting,
129
+ black is the best for this but if you need two colors
130
+ this works well on blue.
131
+ """
132
+ return "#DE8F05"
133
+
134
+
135
+ def galaxies_cmap(single_color=False): # type: ignore
136
+ """Make a color map for galaxies."""
137
+ if single_color:
138
+ cmap = mk_colormap([galaxies_color()])
139
+ else:
140
+ cmap = "inferno"
141
+ return cmap
142
+
143
+
144
+ def galaxies_color() -> str:
145
+ """Return the galaxy color string for lines"""
146
+ return "#961A45"
147
+
148
+
149
+ def get_band_dicts() -> dict:
150
+ """
151
+ Define palettes, from RTN-045. This includes dicts for colors (bandpass
152
+ colors for white background), colors_black (bandpass colors for
153
+ black background), plot symbols, and line_styles, keyed on band (ugrizy).
154
+
155
+ Returns
156
+ -------
157
+ band_dict : `dict` of `dict`
158
+ Dicts of colors, colors_black, symbols, and line_styles,
159
+ keyed on bands 'u', 'g', 'r', 'i', 'z', and 'y'.
160
+ """
161
+ colors = get_multiband_plot_colors()
162
+ colors_black = get_multiband_plot_colors(dark_background=True)
163
+ symbols = get_multiband_plot_symbols()
164
+ line_styles = get_multiband_plot_linestyles()
165
+
166
+ return {
167
+ "colors": colors,
168
+ "colors_black": colors_black,
169
+ "symbols": symbols,
170
+ "line_styles": line_styles,
171
+ }
@@ -1,19 +1,19 @@
1
1
  axes.labelweight: normal
2
2
  figure.titleweight : normal
3
3
  axes.labelsize : large
4
- axes.linewidth: 2
4
+ axes.linewidth: 1
5
5
  axes.titleweight: normal
6
6
  axes.titlesize : small
7
7
  figure.titlesize: small
8
8
  errorbar.capsize: 3.0
9
9
 
10
- lines.linewidth : 3
10
+ lines.linewidth : 2
11
11
  lines.markersize : 10
12
12
 
13
- xtick.labelsize : large
14
- ytick.labelsize : large
13
+ xtick.labelsize : small
14
+ ytick.labelsize : small
15
15
 
16
- figure.dpi : 150.0
16
+ figure.dpi : 300.0
17
17
  figure.facecolor: White
18
18
  figure.figsize : 6.4, 4.8
19
19
 
@@ -24,16 +24,16 @@ patch.facecolor: 006BA4
24
24
  font.size : 14
25
25
  legend.fontsize: x-small
26
26
 
27
- xtick.major.width: 2.0
28
- xtick.minor.width: 1.5
27
+ xtick.major.width: 1.0
28
+ xtick.minor.width: 0.5
29
29
  xtick.major.size: 7
30
30
  xtick.minor.size: 4
31
31
  xtick.minor.visible: True
32
32
  xtick.direction: in
33
33
  xtick.top: True
34
34
  xtick.bottom: True
35
- ytick.major.width: 2.0
36
- ytick.minor.width: 1.5
35
+ ytick.major.width: 1.0
36
+ ytick.minor.width: 0.5
37
37
  ytick.major.size: 7
38
38
  ytick.minor.size: 4
39
39
  ytick.minor.visible: True
@@ -16,6 +16,7 @@ from __future__ import annotations
16
16
 
17
17
  __all__ = ["duration_from_timeMethod", "logInfo", "profile", "timeMethod", "time_this"]
18
18
 
19
+ import dataclasses
19
20
  import datetime
20
21
  import functools
21
22
  import logging
@@ -338,6 +339,18 @@ def timeMethod(
338
339
  return decorator_timer(_func)
339
340
 
340
341
 
342
+ @dataclasses.dataclass
343
+ class _TimerResult:
344
+ duration: float = 0.0
345
+ """Duration of context in seconds."""
346
+ mem_current_usage: float | None = None
347
+ """Memory usage at end of context in requested units."""
348
+ mem_peak_delta: float | None = None
349
+ """Peak differential between entering and leaving context."""
350
+ mem_current_delta: float | None = None
351
+ """Difference in usage between entering and leaving context."""
352
+
353
+
341
354
  @contextmanager
342
355
  def time_this(
343
356
  log: LsstLoggers | None = None,
@@ -349,7 +362,8 @@ def time_this(
349
362
  mem_child: bool = False,
350
363
  mem_unit: u.Quantity = u.byte,
351
364
  mem_fmt: str = ".0f",
352
- ) -> Iterator[None]:
365
+ force_mem_usage: bool = False,
366
+ ) -> Iterator[_TimerResult]:
353
367
  """Time the enclosed block and issue a log message.
354
368
 
355
369
  Parameters
@@ -372,7 +386,8 @@ def time_this(
372
386
  written to ``msg``.
373
387
  mem_usage : `bool`, optional
374
388
  Flag indicating whether to include the memory usage in the report.
375
- Defaults, to False.
389
+ Defaults, to False. Does nothing if the log message will not be
390
+ generated.
376
391
  mem_child : `bool`, optional
377
392
  Flag indication whether to include memory usage of the child processes.
378
393
  mem_unit : `astropy.units.Unit`, optional
@@ -380,6 +395,16 @@ def time_this(
380
395
  mem_fmt : `str`, optional
381
396
  Format specifier to use when displaying values related to memory usage.
382
397
  Defaults to '.0f'.
398
+ force_mem_usage : `bool`, optional
399
+ If `True` memory usage is always calculated even if the log message
400
+ will not be delivered. Use this if you want the information recorded
401
+ by the context manager.
402
+
403
+ Yields
404
+ ------
405
+ timer_result : `_TimerResult`
406
+ Simple data class containing the duration of the block in seconds via
407
+ the ``duration`` property.
383
408
  """
384
409
  if log is None:
385
410
  log = logging.getLogger()
@@ -391,14 +416,17 @@ def time_this(
391
416
 
392
417
  if mem_usage and not log.isEnabledFor(level):
393
418
  mem_usage = False
419
+ if force_mem_usage:
420
+ mem_usage = True
394
421
 
395
422
  if mem_usage:
396
423
  current_usages_start = get_current_mem_usage()
397
424
  peak_usages_start = get_peak_mem_usage()
398
425
 
426
+ timer_result = _TimerResult()
399
427
  errmsg = ""
400
428
  try:
401
- yield
429
+ yield timer_result
402
430
  except BaseException as e:
403
431
  frame, lineno = list(traceback.walk_tb(e.__traceback__))[-1]
404
432
  errmsg = f"{e!r} @ {frame.f_code.co_filename}:{lineno}"
@@ -416,9 +444,12 @@ def time_this(
416
444
  # mypy stop complaining when additional parameters will be added below.
417
445
  params = list(args) if args else []
418
446
 
447
+ duration = end - start
448
+ timer_result.duration = duration
449
+
419
450
  # Specify stacklevel to ensure the message is reported from the
420
451
  # caller (1 is this file, 2 is contextlib, 3 is user)
421
- params += (": " if msg else "", end - start)
452
+ params += (": " if msg else "", duration)
422
453
  msg += "%sTook %.4f seconds"
423
454
  if errmsg:
424
455
  params += (f" (timed code triggered exception of {errmsg!r})",)
@@ -442,10 +473,18 @@ def time_this(
442
473
  _LOG.warning("Invalid memory unit '%s', using '%s' instead", mem_unit, u.byte)
443
474
  mem_unit = u.byte
444
475
 
476
+ current_usage = current_usage.to(mem_unit)
477
+ current_delta = current_delta.to(mem_unit)
478
+ peak_delta = peak_delta.to(mem_unit)
479
+
480
+ timer_result.mem_current_usage = float(current_usage.value)
481
+ timer_result.mem_current_delta = float(current_delta.value)
482
+ timer_result.mem_peak_delta = float(peak_delta.value)
483
+
445
484
  msg += (
446
- f"; current memory usage: {current_usage.to(mem_unit):{mem_fmt}}"
447
- f", delta: {current_delta.to(mem_unit):{mem_fmt}}"
448
- f", peak delta: {peak_delta.to(mem_unit):{mem_fmt}}"
485
+ f"; current memory usage: {current_usage:{mem_fmt}}"
486
+ f", delta: {current_delta:{mem_fmt}}"
487
+ f", peak delta: {peak_delta:{mem_fmt}}"
449
488
  )
450
489
  log.log(level, msg, *params, stacklevel=3)
451
490
 
@@ -0,0 +1,2 @@
1
+ __all__ = ["__version__"]
2
+ __version__ = "29.2025.1900"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lsst-utils
3
- Version: 29.2025.1700
3
+ Version: 29.2025.1900
4
4
  Summary: Utility functions from Rubin Observatory Data Management for the Legacy Survey of Space and Time (LSST).
5
5
  Author-email: Rubin Observatory Data Management <dm-admin@lists.lsst.org>
6
6
  License: BSD 3-Clause License
@@ -27,6 +27,7 @@ Provides-Extra: test
27
27
  Requires-Dist: pytest>=3.2; extra == "test"
28
28
  Provides-Extra: plotting
29
29
  Requires-Dist: matplotlib; extra == "plotting"
30
+ Requires-Dist: seaborn; extra == "plotting"
30
31
  Dynamic: license-file
31
32
 
32
33
  ==========
@@ -7,6 +7,7 @@ threadpoolctl
7
7
 
8
8
  [plotting]
9
9
  matplotlib
10
+ seaborn
10
11
 
11
12
  [test]
12
13
  pytest>=3.2
@@ -23,12 +23,19 @@ import unittest
23
23
 
24
24
  import lsst.utils.tests
25
25
  from lsst.utils.plotting import (
26
+ accent_color,
27
+ divergent_cmap,
28
+ galaxies_cmap,
29
+ galaxies_color,
26
30
  get_band_dicts,
27
31
  get_multiband_plot_colors,
28
32
  get_multiband_plot_linestyles,
29
33
  get_multiband_plot_symbols,
30
34
  make_figure,
35
+ mk_colormap,
31
36
  set_rubin_plotstyle,
37
+ stars_cmap,
38
+ stars_color,
32
39
  )
33
40
 
34
41
  try:
@@ -90,3 +97,40 @@ class PublicationPlotsTestCase(unittest.TestCase):
90
97
  self.assertEqual(bands_dict["colors_black"]["r"], "#ff7e00")
91
98
  self.assertEqual(bands_dict["symbols"]["r"], "v")
92
99
  self.assertEqual(bands_dict["line_styles"]["r"], "-")
100
+
101
+ def testStarColors(self):
102
+ with lsst.utils.tests.getTempFilePath(".png") as tmpFile:
103
+ fig = make_figure()
104
+ ax = fig.add_subplot(111)
105
+ xs = [0, 1]
106
+ ys = [0, 1]
107
+ for cmap in [stars_cmap(), stars_cmap(single_color=True)]:
108
+ ax.hexbin(xs, ys, cmap=cmap)
109
+ ax.axhline(0, color=stars_color())
110
+ fig.savefig(tmpFile)
111
+
112
+ def testGalaxyColor(self):
113
+ with lsst.utils.tests.getTempFilePath(".png") as tmpFile:
114
+ fig = make_figure()
115
+ ax = fig.add_subplot(111)
116
+ xs = [0, 1]
117
+ ys = [0, 1]
118
+ for cmap in [galaxies_cmap(), galaxies_cmap(single_color=True)]:
119
+ ax.hexbin(xs, ys, cmap=cmap)
120
+ ax.axhline(0, color=galaxies_color())
121
+ fig.savefig(tmpFile)
122
+
123
+ def testDivergentColor(self):
124
+ with lsst.utils.tests.getTempFilePath(".png") as tmpFile:
125
+ fig = make_figure()
126
+ ax = fig.add_subplot(111)
127
+ xs = [0, 1]
128
+ ys = [0, 1]
129
+ ax.hexbin(xs, ys, cmap=divergent_cmap())
130
+ ax.axhline(0, color=accent_color())
131
+ fig.savefig(tmpFile)
132
+
133
+ def testMkColormap(self):
134
+ mk_colormap(["#fde725", "#21918c", "#440154"])
135
+ mk_colormap(["#fde725", "#5ec962", "#21918c", "#3b528b"])
136
+ mk_colormap(["#fde725", "#5ec962", "#21918c", "#3b528b", "#440154"])
@@ -342,6 +342,38 @@ class TimerTestCase(unittest.TestCase):
342
342
  self.assertIn("A problem %s", cm.records[0].message)
343
343
  self.assertEqual(cm.records[0].levelname, "DEBUG")
344
344
 
345
+ def test_time_this_return(self):
346
+ """Test that the context manager returns the duration."""
347
+ # Return duration but not memory usage.
348
+ with self.assertNoLogs(level="INFO"):
349
+ with time_this(level=logging.DEBUG, prefix=None, mem_usage=False) as timer:
350
+ time.sleep(0.01)
351
+ self.assertGreater(timer.duration, 0.0)
352
+ self.assertIsNone(timer.mem_current_usage)
353
+
354
+ # Ask for memory usage that will be calculated.
355
+ with self.assertLogs(level="DEBUG"):
356
+ # mem usage will be requested but not calculated.
357
+ with time_this(level=logging.DEBUG, prefix=None, mem_usage=True) as timer:
358
+ time.sleep(0.01)
359
+ self.assertGreater(timer.duration, 0.0)
360
+ self.assertGreaterEqual(timer.mem_current_delta, 0.0)
361
+
362
+ # Ask for memory usage but will not be calculated.
363
+ with self.assertNoLogs(level="WARNING"):
364
+ # mem usage will be requested but not calculated.
365
+ with time_this(level=logging.DEBUG, prefix=None, mem_usage=True) as timer:
366
+ time.sleep(0.01)
367
+ self.assertGreater(timer.duration, 0.0)
368
+ self.assertIsNone(timer.mem_current_usage)
369
+
370
+ # Require memory usage is returned in context manager.
371
+ with self.assertNoLogs(level="WARNING"):
372
+ with time_this(level=logging.DEBUG, prefix=None, force_mem_usage=True) as timer:
373
+ time.sleep(0.01)
374
+ self.assertGreater(timer.duration, 0.0)
375
+ self.assertGreater(timer.mem_current_usage, 0.0)
376
+
345
377
 
346
378
  class ProfileTestCase(unittest.TestCase):
347
379
  """Test profiling decorator."""
@@ -1,56 +0,0 @@
1
- # This file is part of utils.
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
- # Use of this source code is governed by a 3-clause BSD-style
10
- # license that can be found in the LICENSE file.
11
- """Utilities for making publication-quality figures."""
12
-
13
- __all__ = [
14
- "get_band_dicts",
15
- "set_rubin_plotstyle",
16
- ]
17
-
18
- from . import (
19
- get_multiband_plot_colors,
20
- get_multiband_plot_linestyles,
21
- get_multiband_plot_symbols,
22
- )
23
-
24
-
25
- def set_rubin_plotstyle() -> None:
26
- """
27
- Set the matplotlib style for Rubin publications
28
- """
29
- from matplotlib import style
30
-
31
- style.use("lsst.utils.plotting.rubin")
32
-
33
-
34
- def get_band_dicts() -> dict:
35
- """
36
- Define palettes, from RTN-045. This includes dicts for colors (bandpass
37
- colors for white background), colors_black (bandpass colors for
38
- black background), plot symbols, and line_styles, keyed on band (ugrizy).
39
-
40
- Returns
41
- -------
42
- band_dict : `dict` of `dict`
43
- Dicts of colors, colors_black, symbols, and line_styles,
44
- keyed on bands 'u', 'g', 'r', 'i', 'z', and 'y'.
45
- """
46
- colors = get_multiband_plot_colors()
47
- colors_black = get_multiband_plot_colors(dark_background=True)
48
- symbols = get_multiband_plot_symbols()
49
- line_styles = get_multiband_plot_linestyles()
50
-
51
- return {
52
- "colors": colors,
53
- "colors_black": colors_black,
54
- "symbols": symbols,
55
- "line_styles": line_styles,
56
- }
@@ -1,2 +0,0 @@
1
- __all__ = ["__version__"]
2
- __version__ = "29.2025.1700"