Skip to content

Commit 0078c8a

Browse files
committed
Implement Butler.get for matplotlib generated png files
1 parent 42f2c38 commit 0078c8a

File tree

4 files changed

+34
-3
lines changed

4 files changed

+34
-3
lines changed

mypy.ini

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ ignore_missing_imports = True
1818
[mypy-numpy.*]
1919
ignore_missing_imports = True
2020

21+
[mypy-matplotlib.*]
22+
ignore_missing_imports = True
23+
2124
[mypy-pyarrow.*]
2225
ignore_missing_imports = True
2326

python/lsst/daf/butler/configs/storageClasses.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,10 +342,14 @@ storageClasses:
342342
dict: lsst.utils.packages.Packages
343343
NumpyArray:
344344
pytype: numpy.ndarray
345+
converters:
346+
matplotlib.figure.Figure: lsst.daf.butler.formatters.matplotlib.MatplotlibFormatter.dummyConverter
345347
Thumbnail:
346348
pytype: numpy.ndarray
347349
Plot:
348350
pytype: matplotlib.figure.Figure
351+
converters:
352+
numpy.ndarray: lsst.daf.butler.formatters.matplotlib.MatplotlibFormatter.fromArray
349353
MetricValue:
350354
pytype: lsst.verify.Measurement
351355
StampsBase:

python/lsst/daf/butler/formatters/matplotlib.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@
2727

2828
from typing import Any
2929

30+
import matplotlib.pyplot as plt
31+
import numpy as np
32+
3033
from .file import FileFormatter
3134

3235

@@ -38,8 +41,22 @@ class MatplotlibFormatter(FileFormatter):
3841

3942
def _readFile(self, path: str, pytype: type[Any] | None = None) -> Any:
4043
# docstring inherited from FileFormatter._readFile
41-
raise NotImplementedError(f"matplotlib figures cannot be read by the butler; path is {path}")
44+
return plt.imread(path)
4245

4346
def _writeFile(self, inMemoryDataset: Any) -> None:
4447
# docstring inherited from FileFormatter._writeFile
4548
inMemoryDataset.savefig(self.fileDescriptor.location.path)
49+
50+
@staticmethod
51+
def fromArray(cls: np.ndarray) -> plt.Figure:
52+
"""Convert an array into a Figure."""
53+
fig = plt.figure()
54+
plt.imshow(cls)
55+
return fig
56+
57+
@staticmethod
58+
def dummyCovnerter(cls: np.ndarray) -> np.ndarray:
59+
"""This converter exists to trick the Butler into allowing
60+
a numpy array on read with ``storageClass='NumpyArray'``.
61+
"""
62+
return cls

tests/test_matplotlibFormatter.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
import unittest
2828
from random import Random
2929

30+
import numpy as np
31+
3032
try:
3133
import matplotlib
3234

@@ -78,8 +80,13 @@ def testMatplotlibFormatter(self):
7880
pyplot.gcf().savefig(file.name)
7981
self.assertTrue(filecmp.cmp(local.ospath, file.name, shallow=True))
8082
self.assertTrue(butler.exists(ref))
81-
with self.assertRaises(ValueError):
82-
butler.get(ref)
83+
84+
fig = butler.get(ref)
85+
# Ensure that the result is a figure
86+
self.assertTrue(isinstance(fig, pyplot.Figure))
87+
image = butler.get(ref, storageClass="NumpyArray")
88+
self.assertTrue(isinstance(image, np.ndarray))
89+
8390
butler.pruneDatasets([ref], unstore=True, purge=True)
8491
self.assertFalse(butler.exists(ref))
8592

0 commit comments

Comments
 (0)