Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## [v0.5.2]

### Added

- `update_extent_from_items` method to Collection for updating Extent objects within a collection based on the contained items. ([#168](https://github.com/stac-utils/pystac/pull/168))

## [v0.5.1]

### Added
Expand Down
33 changes: 32 additions & 1 deletion pystac/collection.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from datetime import datetime
import dateutil.parser
from dateutil import tz
from copy import (copy, deepcopy)

from pystac import (STACError, STACObjectType)
from pystac.catalog import Catalog
from pystac.link import Link
Expand Down Expand Up @@ -202,6 +202,37 @@ def from_dict(cls, d, href=None, root=None):

return collection

def update_extent_from_items(self):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice concise implementation 💯

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I have updated the changelog as well.

"""
Update datetime and bbox based on all items to a single bbox and time window.
"""
def extract_extent_props(item):
return item.bbox + [
item.datetime, item.common_metadata.start_datetime,
item.common_metadata.end_datetime
]

xmins, ymins, xmaxs, ymaxs, datetimes, starts, ends = zip(
*map(extract_extent_props, self.get_all_items()))

if not any(datetimes + starts):
start_timestamp = None
else:
start_timestamp = min([
dt if dt.tzinfo else dt.replace(tzinfo=tz.UTC)
for dt in filter(None, datetimes + starts)
])
if not any(datetimes + ends):
end_timestamp = None
else:
end_timestamp = max([
dt if dt.tzinfo else dt.replace(tzinfo=tz.UTC)
for dt in filter(None, datetimes + ends)
])

self.extent.spatial.bboxes = [[min(xmins), min(ymins), max(xmaxs), max(ymaxs)]]
self.extent.temporal.intervals = [[start_timestamp, end_timestamp]]


class Extent:
"""Describes the spatio-temporal extents of a Collection.
Expand Down
44 changes: 44 additions & 0 deletions tests/test_collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from pystac.serialization.identify import STACObjectType
from pystac import (Collection, Item, Extent, SpatialExtent, TemporalExtent, CatalogType)
from pystac.extensions.eo import Band
from pystac.utils import datetime_to_str
from tests.utils import (TestCases, RANDOM_GEOM, RANDOM_BBOX)


Expand Down Expand Up @@ -135,3 +136,46 @@ def test_extra_fields(self):
read_col = pystac.read_file(p)
self.assertTrue('test' in read_col.extra_fields)
self.assertEqual(read_col.extra_fields['test'], 'extra')

def test_update_extents(self):

catalog = TestCases.test_case_2()
base_collection = catalog.get_child('1a8c1632-fa91-4a62-b33e-3a87c2ebdf16')
base_extent = base_collection.extent
collection = base_collection.clone()

item1 = Item(id='test-item-1',
geometry=RANDOM_GEOM,
bbox=[-180, -90, 180, 90],
datetime=datetime.utcnow(),
properties={'key': 'one'},
stac_extensions=['eo', 'commons'])

item2 = Item(id='test-item-1',
geometry=RANDOM_GEOM,
bbox=[-180, -90, 180, 90],
datetime=None,
properties={
'start_datetime': datetime_to_str(datetime(2000, 1, 1, 12, 0, 0, 0)),
'end_datetime': datetime_to_str(datetime(2000, 2, 1, 12, 0, 0, 0))
},
stac_extensions=['eo', 'commons'])

collection.add_item(item1)

collection.update_extent_from_items()
self.assertEqual([[-180, -90, 180, 90]], collection.extent.spatial.bboxes)
self.assertEqual(len(base_extent.spatial.bboxes[0]),
len(collection.extent.spatial.bboxes[0]))

self.assertNotEqual(base_extent.temporal.intervals, collection.extent.temporal.intervals)
collection.remove_item('test-item-1')
collection.update_extent_from_items()
self.assertNotEqual([[-180, -90, 180, 90]], collection.extent.spatial.bboxes)
collection.add_item(item2)

collection.update_extent_from_items()

self.assertEqual(
[[item2.common_metadata.start_datetime, base_extent.temporal.intervals[0][1]]],
collection.extent.temporal.intervals)