lsst-utils 29.2025.1700__py3-none-any.whl → 29.2025.1900__py3-none-any.whl
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.
- lsst/utils/plotting/publication_plots.py +115 -0
- lsst/utils/plotting/rubin.mplstyle +9 -9
- lsst/utils/timer.py +46 -7
- lsst/utils/version.py +1 -1
- {lsst_utils-29.2025.1700.dist-info → lsst_utils-29.2025.1900.dist-info}/METADATA +2 -1
- {lsst_utils-29.2025.1700.dist-info → lsst_utils-29.2025.1900.dist-info}/RECORD +11 -11
- {lsst_utils-29.2025.1700.dist-info → lsst_utils-29.2025.1900.dist-info}/WHEEL +1 -1
- {lsst_utils-29.2025.1700.dist-info → lsst_utils-29.2025.1900.dist-info}/licenses/COPYRIGHT +0 -0
- {lsst_utils-29.2025.1700.dist-info → lsst_utils-29.2025.1900.dist-info}/licenses/LICENSE +0 -0
- {lsst_utils-29.2025.1700.dist-info → lsst_utils-29.2025.1900.dist-info}/top_level.txt +0 -0
- {lsst_utils-29.2025.1700.dist-info → lsst_utils-29.2025.1900.dist-info}/zip-safe +0 -0
|
@@ -11,10 +11,19 @@
|
|
|
11
11
|
"""Utilities for making publication-quality figures."""
|
|
12
12
|
|
|
13
13
|
__all__ = [
|
|
14
|
+
"accent_color",
|
|
15
|
+
"divergent_cmap",
|
|
16
|
+
"galaxies_cmap",
|
|
17
|
+
"galaxies_color",
|
|
14
18
|
"get_band_dicts",
|
|
19
|
+
"mk_colormap",
|
|
15
20
|
"set_rubin_plotstyle",
|
|
21
|
+
"stars_cmap",
|
|
22
|
+
"stars_color",
|
|
16
23
|
]
|
|
17
24
|
|
|
25
|
+
import numpy as np
|
|
26
|
+
|
|
18
27
|
from . import (
|
|
19
28
|
get_multiband_plot_colors,
|
|
20
29
|
get_multiband_plot_linestyles,
|
|
@@ -31,6 +40,112 @@ def set_rubin_plotstyle() -> None:
|
|
|
31
40
|
style.use("lsst.utils.plotting.rubin")
|
|
32
41
|
|
|
33
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
|
+
|
|
34
149
|
def get_band_dicts() -> dict:
|
|
35
150
|
"""
|
|
36
151
|
Define palettes, from RTN-045. This includes dicts for colors (bandpass
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
axes.labelweight: normal
|
|
2
2
|
figure.titleweight : normal
|
|
3
3
|
axes.labelsize : large
|
|
4
|
-
axes.linewidth:
|
|
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 :
|
|
10
|
+
lines.linewidth : 2
|
|
11
11
|
lines.markersize : 10
|
|
12
12
|
|
|
13
|
-
xtick.labelsize :
|
|
14
|
-
ytick.labelsize :
|
|
13
|
+
xtick.labelsize : small
|
|
14
|
+
ytick.labelsize : small
|
|
15
15
|
|
|
16
|
-
figure.dpi :
|
|
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:
|
|
28
|
-
xtick.minor.width:
|
|
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:
|
|
36
|
-
ytick.minor.width:
|
|
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
|
lsst/utils/timer.py
CHANGED
|
@@ -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
|
-
|
|
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 "",
|
|
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
|
|
447
|
-
f", delta: {current_delta
|
|
448
|
-
f", peak delta: {peak_delta
|
|
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
|
|
lsst/utils/version.py
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
__all__ = ["__version__"]
|
|
2
|
-
__version__ = "29.2025.
|
|
2
|
+
__version__ = "29.2025.1900"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: lsst-utils
|
|
3
|
-
Version: 29.2025.
|
|
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
|
==========
|
|
@@ -14,19 +14,19 @@ lsst/utils/packages.py,sha256=D2eD2Qy3P_Os7RbUKsG2mPyLoSLjqejUX6lNhaC16wg,27455
|
|
|
14
14
|
lsst/utils/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
15
|
lsst/utils/tests.py,sha256=1cjyXtEL2LNhnPKjtiTt9cdPmlaEWgaWBx9BfM-xSmA,39152
|
|
16
16
|
lsst/utils/threads.py,sha256=WNl3uvbE7bx5UyxTX0fwN5AkU3Yty_m8y_pMKcMCdv8,2551
|
|
17
|
-
lsst/utils/timer.py,sha256=
|
|
17
|
+
lsst/utils/timer.py,sha256=Vt5yTuyGL-EAQ9ZE9rtzYLNRQDQ3njN97J5_kZn9Kh4,19923
|
|
18
18
|
lsst/utils/usage.py,sha256=qunydx-KlcbNp-vFcBtvBayWwZAa0tHtSWvz5BycvLA,4598
|
|
19
|
-
lsst/utils/version.py,sha256=
|
|
19
|
+
lsst/utils/version.py,sha256=duakYcQBT5t4KBaOX14WCtq_sSvpoXvNcxi3sUb8GvI,55
|
|
20
20
|
lsst/utils/wrappers.py,sha256=KCvsrGXziLQ5pC8ytiFEXeDH9mBSo8eCZ8g08f7s404,19209
|
|
21
21
|
lsst/utils/plotting/__init__.py,sha256=OEAZv2W12UAcUfDxH5H_k8v7cK4fVTOssuqNksZTuIs,507
|
|
22
22
|
lsst/utils/plotting/figures.py,sha256=dPJfP0W-GkRhv6bEiPzH7kLV0a4MIrtavmLbGv7Wt9E,4167
|
|
23
23
|
lsst/utils/plotting/limits.py,sha256=6ilPmb4wg4aVtjlBgm75FPBrjDVSkW_ywZrj_QIQD2U,5839
|
|
24
|
-
lsst/utils/plotting/publication_plots.py,sha256=
|
|
25
|
-
lsst/utils/plotting/rubin.mplstyle,sha256=
|
|
26
|
-
lsst_utils-29.2025.
|
|
27
|
-
lsst_utils-29.2025.
|
|
28
|
-
lsst_utils-29.2025.
|
|
29
|
-
lsst_utils-29.2025.
|
|
30
|
-
lsst_utils-29.2025.
|
|
31
|
-
lsst_utils-29.2025.
|
|
32
|
-
lsst_utils-29.2025.
|
|
24
|
+
lsst/utils/plotting/publication_plots.py,sha256=nwttKC3818okJFZrquuRDDsnOys3WflGGZOmpZ0hcLI,4739
|
|
25
|
+
lsst/utils/plotting/rubin.mplstyle,sha256=SaonqdWUIOT8Z4f5oplS21Z6wmYVjuCs--PyJnjS8us,1084
|
|
26
|
+
lsst_utils-29.2025.1900.dist-info/licenses/COPYRIGHT,sha256=I6Bxnp_LkIqDjafZNIXM8jfjYWC4XIlpNpZ7jkdeZK0,361
|
|
27
|
+
lsst_utils-29.2025.1900.dist-info/licenses/LICENSE,sha256=7wrtgl8meQ0_RIuv2TjIKpAnNrl-ODH-QLwyHe9citI,1516
|
|
28
|
+
lsst_utils-29.2025.1900.dist-info/METADATA,sha256=ANxPW4PKoqla8ES6HaY8F90hyFSo9FDLoWSgrprRwA8,1691
|
|
29
|
+
lsst_utils-29.2025.1900.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
|
|
30
|
+
lsst_utils-29.2025.1900.dist-info/top_level.txt,sha256=eUWiOuVVm9wwTrnAgiJT6tp6HQHXxIhj2QSZ7NYZH80,5
|
|
31
|
+
lsst_utils-29.2025.1900.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
32
|
+
lsst_utils-29.2025.1900.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|