diff --git a/CHANGELOG.md b/CHANGELOG.md index 0614e64..1c71866 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,23 +6,23 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] -## [v0.4.0-rc1] - 2020-01-26 +## [v0.4.0] - 2020-06-11 ### Added -- In README, Directed users who want to do large scale creation or updating of catalogs to the [PySTAC](https://github.com/azavea/pystac) library instead -- STAC_PATH_TEMPLATE envvar added to store default path template for saving downloaded files, defaults to `${collection}/${id}`, files are then downloaded in that directory with a name equal to `_.` +- README directs users who want to do large scale creation or updating of catalogs to the [PySTAC](https://github.com/azavea/pystac) library instead +- ItemCollections.asset_defnition function for printing info on assets ### Changed -- Environment variable SATUTILS_STAC_VERSION changed to STAC_VERSION -- Default STAC_VERSION changed to 0.9.0 +- Default STAC_VERSION changed to 1.0.0-beta.1 - Item.get_filename replaced with Item.get_path which takes in single template string rather than separate `path` and `filename` arguments -- Collection.add_item() function input keywords changed to `path_template` and `filename_template` +- Collection.add_item() function input keywords changed `filename_template` ### Fixed - Substitution of templates on Windows: [issue](https://github.com/sat-utils/sat-stac/issues/51) ### Removed - Item.get_filename removed in favor of Item.get_path +- Storing search information in an ItemCollections file (and associated functions) ## [v0.3.3] - 2020-01-23 diff --git a/satstac/item.py b/satstac/item.py index 6e6de19..ec4e688 100644 --- a/satstac/item.py +++ b/satstac/item.py @@ -78,7 +78,12 @@ def assets_by_common_name(self): if self._assets_by_common_name is None: self._assets_by_common_name = {} for a in self.assets: - bands = self.assets[a].get('eo:bands', []) + bands = [] + col = self.collection()._data + if 'eo:bands' in self.assets[a]: + bands = self.assets[a]['eo:bands'] + elif 'item_assets' in col: + bands = col['item_assets'][a].get('eo:bands', []) if len(bands) == 1: eo_band = bands[0].get('common_name') if eo_band: @@ -87,7 +92,7 @@ def assets_by_common_name(self): def asset(self, key): """ Get asset for this key OR common_name """ - if key in self.assets: + if key in self.assets.keys(): return self.assets[key] elif key in self.assets_by_common_name: return self.assets_by_common_name[key] diff --git a/satstac/itemcollection.py b/satstac/itemcollection.py index bcc6e2a..25cf48e 100644 --- a/satstac/itemcollection.py +++ b/satstac/itemcollection.py @@ -14,11 +14,10 @@ class ItemCollection(object): """ A GeoJSON FeatureCollection of STAC Items with associated Collections """ - def __init__(self, items, collections=[], search={}): + def __init__(self, items, collections=[]): """ Initialize with a list of Item objects """ self._collections = collections self._items = items - self._search = search # link Items to their Collections cols = {c.id: c for c in self._collections} for i in self._items: @@ -58,7 +57,7 @@ def open(cls, filename): raise STACError('%s does not exist locally' % filename) collections = [Collection(col) for col in data['collections']] items = [Item(feature) for feature in data['features']] - return cls(items, collections=collections, search=data.get('search')) + return cls(items, collections=collections) @classmethod def load(cls, *args, **kwargs): @@ -85,31 +84,6 @@ def collection(self, id): else: return None - def bbox(self): - """ Get bounding box of search """ - if 'intersects' in self._search.get('parameters', {}): - coords = self._search['parameters']['intersects']['geometry']['coordinates'] - lats = [c[1] for c in coords[0]] - lons = [c[0] for c in coords[0]] - return [min(lons), min(lats), max(lons), max(lats)] - else: - return None - - def center(self): - if 'intersects' in self._search.get('parameters', {}): - coords = self._search['parameters']['intersects']['geometry']['coordinates'] - lats = [c[1] for c in coords[0]] - lons = [c[0] for c in coords[0]] - return [(min(lats) + max(lats))/2.0, (min(lons) + max(lons))/2.0] - else: - return None - - def search_geometry(self): - if 'intersects' in self._search.get('parameters', {}): - return self._search['parameters']['intersects'] - else: - return None - def properties(self, key, date=None): """ Set of values for 'key' property in Items, for specific date if provided """ if date is None: @@ -138,6 +112,23 @@ def calendar(self, group='platform'): date_labels[d] = groups[0] return terminal_calendar(date_labels) + def assets_definition(self): + fields = ['Key', 'Title', 'Common Name(s)', 'Type'] + w = [12, 35, 20, 50] + for c in self._collections: + txt = f"Collection: {c.id}\n" + txt += ''.join([f"{fields[i]:{w[i]}}" for i in range(len(w))]) + '\n' + for key in c._data['item_assets']: + asset = c._data['item_assets'][key] + if 'eo:bands' in asset: + bands = ', '.join([b.get('common_name', None) for b in asset['eo:bands'] if 'common_name' in b]) + else: + bands = '' + #import pdb; pdb.set_trace() + vals = [key, asset['title'], bands, asset['type']] + txt += ''.join([f"{vals[i]:{w[i]}}" for i in range(len(w))]) + '\n' + return txt + def save(self, filename): """ Save scene metadata """ with open(filename, 'w') as f: @@ -151,8 +142,6 @@ def geojson(self): 'features': features, 'collections': [c._data for c in self._collections], } - if self._search is not None: - geoj['search'] = self._search return geoj def filter(self, key, values): diff --git a/satstac/version.py b/satstac/version.py index 9b29583..abeeedb 100644 --- a/satstac/version.py +++ b/satstac/version.py @@ -1 +1 @@ -__version__ = '0.4.0-rc2' +__version__ = '0.4.0' diff --git a/test/test_itemcollection.py b/test/test_itemcollection.py index 46375ed..be1b89b 100644 --- a/test/test_itemcollection.py +++ b/test/test_itemcollection.py @@ -48,17 +48,6 @@ def test_no_collection(self): col = items.collection('nosuchcollection') assert(col is None) - def test_bbox(self): - items = self.load_items() - bbox = items.bbox() - assert(len(bbox) == 4) - assert(bbox == [11.984710693359375, 44.815941348210835, 12.752380371093748, 45.67740123855739]) - - def test_center(self): - items = self.load_items() - center = items.center() - assert(center == [45.24667129338411, 12.368545532226562]) - def test_get_properties(self): """ Get set of properties """ items = self.load_items() diff --git a/tutorial-1.ipynb b/tutorial-1.ipynb index e866c76..748db1d 100644 --- a/tutorial-1.ipynb +++ b/tutorial-1.ipynb @@ -126,9 +126,9 @@ "name": "stdout", "output_type": "stream", "text": [ - "\n", - "\n", - "\n" + "\n", + "\n", + "\n" ] } ], @@ -169,7 +169,8 @@ "landsat-8-l1\n", "\n", "**Items**\n", - "LC81530252014153LGN00\n" + "S2B_25WFU_20200610_0_L1C\n", + "LC08_L1TP_152038_20200611_20200611_01_RT\n" ] } ], @@ -362,7 +363,7 @@ "output_type": "stream", "text": [ "Item name: landsat-8-l1\n", - "Item filename: mycat/mykitten/landsat-8-l1/LC81530252014153LGN00.json\n", + "Item filename: mycat/mykitten/landsat-8-l1/LC08_L1TP_152038_20200611_20200611_01_RT.json\n", "\n", "**Item links**\n", "[ {'href': '../../catalog.json', 'rel': 'root'},\n", @@ -424,21 +425,20 @@ "name": "stdout", "output_type": "stream", "text": [ - "Item filename: mycat/mykitten/landsat-8-l1/107/18/2014-06-02/LC81530252014153LGN00.json\n", + "Item filename: mycat/mykitten/landsat-8-l1/107/18/2020-06-11/LC08_L1TP_152038_20200611_20200611_01_RT.json\n", "\n", "**Item links**\n", "[ {'href': '../../../../../catalog.json', 'rel': 'root'},\n", - " {'href': '../catalog.json', 'rel': 'parent'},\n", + " {'href': 'catalog.json', 'rel': 'parent'},\n", " {'href': '../../../catalog.json', 'rel': 'collection'}]\n" ] } ], "source": [ "# save \n", - "path = '${landsat:path}/${landsat:row}'\n", - "filename = '${date}/${id}.json'\n", + "filename = '${landsat:path}/${landsat:row}/${date}/${id}.json'\n", "\n", - "collection.add_item(item, path_template=path, filename_template=filename)\n", + "collection.add_item(item, filename_template=filename)\n", "print('Item filename: ', item.filename)\n", "\n", "print('\\n**Item links**')\n",