Skip to content

Commit fd8596b

Browse files
committed
add serialization to regions for json formatted catalog
- supports new region versions e.g., QuadTreeRegion - added region comparison using to_dict method in regions
1 parent 8ac605c commit fd8596b

File tree

3 files changed

+45
-5
lines changed

3 files changed

+45
-5
lines changed

csep/core/catalogs.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
from csep.utils.file import get_file_extension
2525
from csep.utils.plots import plot_catalog
2626

27+
2728
class AbstractBaseCatalog(LoggingMixin):
2829
"""
2930
Abstract catalog base class for PyCSEP catalogs. This class should not and cannot be used on its own. This just
@@ -148,13 +149,17 @@ def from_dict(cls, adict, **kwargs):
148149
This needs to handle reading in region information at some point.
149150
"""
150151

152+
region_loader = {
153+
'CartesianGrid2D': regions.CartesianGrid2D
154+
}
155+
151156
# could these be class values? can be changed later.
152-
exclude = ['_catalog']
157+
exclude = ['_catalog', 'region']
153158
time_members = ['date_accessed', 'start_time', 'end_time']
154159
catalog = adict.get('catalog', None)
155-
156160
out = cls(data=catalog, **kwargs)
157161

162+
# here we are looping over the items in the class and finding the associated value in the dict
158163
for k, v in out.__dict__.items():
159164
if k not in exclude:
160165
if k not in time_members:
@@ -164,6 +169,13 @@ def from_dict(cls, adict, **kwargs):
164169
pass
165170
else:
166171
setattr(out, k, _none_or_datetime(adict[k]))
172+
else:
173+
if k == 'region':
174+
# tries to read class id from
175+
class_id = adict[k].get('class_id', None)
176+
if class_id is None:
177+
class_id = 'CartesianGrid2D'
178+
setattr(out, k, region_loader[class_id].from_dict(adict[k]))
167179
return out
168180

169181
@classmethod

csep/core/regions.py

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,9 @@ def __init__(self, polygons, dh, name='cartesian2d', mask=None):
555555
self.xs = xs
556556
self.ys = ys
557557

558+
def __eq__(self, other):
559+
return self.to_dict() == other.to_dict()
560+
558561
@property
559562
def num_nodes(self):
560563
""" Number of polygons in region """
@@ -650,13 +653,36 @@ def to_dict(self):
650653
adict = {
651654
'name': str(self.name),
652655
'dh': float(self.dh),
653-
'polygons': [{'lat': float(poly.origin[1]), 'lon': float(poly.origin[0])} for poly in self.polygons]
656+
'polygons': [{'lat': float(poly.origin[1]), 'lon': float(poly.origin[0])} for poly in self.polygons],
657+
'class_id': self.__class__.__name__
654658
}
655659
return adict
656660

657661
@classmethod
658662
def from_dict(cls, adict):
659-
raise NotImplementedError("Todo!")
663+
""" Creates a region object from a dictionary """
664+
origins = adict.get('polygons', None)
665+
dh = adict.get('dh', None)
666+
magnitudes = adict.get('magnitudes', None)
667+
name = adict.get('name', 'CartesianGrid2D')
668+
669+
if origins is None:
670+
raise AttributeError("cannot create region object without origins")
671+
if dh is None:
672+
raise AttributeError("cannot create region without dh")
673+
if origins is not None:
674+
try:
675+
origins = numpy.array([[adict['lon'], adict['lat']] for adict in origins])
676+
except:
677+
raise TypeError('origins must be numpy array like.')
678+
if magnitudes is not None:
679+
try:
680+
magnitudes = numpy.array(magnitudes)
681+
except:
682+
raise TypeError('magnitudes must be numpy array like.')
683+
684+
out = cls.from_origins(origins, dh=dh, magnitudes=magnitudes, name=name)
685+
return out
660686

661687
@classmethod
662688
def from_origins(cls, origins, dh=None, magnitudes=None, name=None):

tests/test_spatial.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,9 @@ def test_get_index_of_good(self):
120120
test_idx = self.cart_grid.get_index_of([test[0]], [test[1]])
121121
numpy.testing.assert_allclose(test_idx, 0)
122122

123+
def test_to_from_dict(self):
124+
self.assertEqual(self.cart_grid, CartesianGrid2D.from_dict(self.cart_grid.to_dict()))
125+
123126
class TestCatalogBinning(unittest.TestCase):
124127

125128
def setUp(self):
@@ -226,7 +229,6 @@ def test_bin_spatial_magnitudes(self):
226229
self.assertEqual(test_result[0, 1], 1)
227230
self.assertEqual(test_result[9, 0], 1)
228231

229-
230232
def test_global_region_binning(self):
231233

232234
gr = global_region()

0 commit comments

Comments
 (0)