Skip to content

Commit e2b88cb

Browse files
committed
Modified some fields to make them more STAC-compliant
1 parent f927b5b commit e2b88cb

File tree

16 files changed

+153
-62
lines changed

16 files changed

+153
-62
lines changed

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,9 +147,12 @@ settings:
147147
# Folder containing anything that can be used as a side material for processing
148148
extra_data_path: "./data/extra"
149149
# Contains the scrapped results from the WKT projections
150-
wkt_file_name: "wkt_solar_system.csv"
150+
wkt_file_path: "wkt_solar_system.csv"
151151
# Contains all the scraped results by using `psup-scraper get-data-ref -O <psup-inventory-file> -f csv --clean`
152152
psup_inventory_file: "./data/raw/psup_refs.csv"
153+
# For debug purposes, you can pass the number of OMEGA items to generate (optional)
154+
n_omega_items: 10
155+
153156
```
154157
You can find an example from [`converter-params.example.yml`](./converter-params.example.yml)
155158

converter-params.example.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,5 @@ settings:
1616
wkt_file_path: "wkt_solar_system.csv"
1717
# Contains all the scraped results by using `psup-scraper get-data-ref -O <psup-inventory-file> -f csv --clean`
1818
psup_inventory_file: "./data/raw/psup_refs.csv"
19+
# For debug purposes, you can pass the number of OMEGA items to generate (optional)
20+
n_omega_items: 10

notebooks/catalog_reading.py

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,16 @@ def _():
99
import marimo as mo
1010
import pystac
1111
from pathlib import Path
12+
from pystac.extensions.datacube import DatacubeExtension
1213

1314
return Path, mo, pystac
1415

1516

1617
@app.cell
1718
def _(Path, pystac):
18-
catalog = pystac.Catalog.from_file(Path.home() / "data-folder/catalog/catalog.json")
19+
catalog = pystac.Catalog.from_file(
20+
Path.home() / "PDSSP/psup-stac-repo/catalog/catalog.json"
21+
)
1922
catalog.describe()
2023
return (catalog,)
2124

@@ -55,12 +58,27 @@ def _(catalog):
5558

5659

5760
@app.cell
58-
def _(catalog):
59-
items = list(catalog.get_all_items())
61+
def _(catalog, pystac):
62+
for _item in catalog.get_all_items():
63+
try:
64+
_item.validate()
65+
except pystac.errors.STACValidationError as e:
66+
print(f"{_item.id} is invalid")
67+
print(e)
68+
# print("==========================")
69+
# if DatacubeExtension.has_extension(_item):
70+
# cube_item = DatacubeExtension.ext(_item)
71+
# print(cube_item.dimensions)
72+
print("========================== =============================")
73+
else:
74+
pass
75+
# print("Valid!")
76+
return
6077

61-
print(f"Number of items: {len(items)}")
62-
for item in items:
63-
print(f"- {item.id}")
78+
79+
@app.cell
80+
def _(catalog):
81+
catalog.validate_all()
6482
return
6583

6684

notebooks/omega_cubes.py

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ def divide_by_channel(df: pd.DataFrame, name: str):
8181

8282
data_cubes_refs = divide_by_channel(psup_refs, "cubes_L2")
8383
c_channel_refs = divide_by_channel(psup_refs, "cubes_L3")
84+
85+
print("N° items in C channel:", c_channel_refs.index.nunique())
86+
print("N° items in data cubes:", data_cubes_refs.index.nunique())
8487
return c_channel_refs, data_cubes_refs
8588

8689

@@ -887,10 +890,16 @@ def _(dt, ex_nc_ds_l2, re):
887890
return
888891

889892

893+
@app.cell
894+
def _(ex_nc_ds_l2):
895+
ex_nc_ds_l2.isel(wavelength=100)
896+
return
897+
898+
890899
@app.cell
891900
def _(ex_nc_ds_l2, plt):
892-
ex_nc_ds_l2.Reflectance.mean("wavelength").plot(cmap=plt.cm.get_cmap("viridis"))
893-
plt.title("Reflectance map based on wavelengh mean")
901+
ex_nc_ds_l2.Reflectance[100].plot(cmap=plt.cm.get_cmap("viridis"))
902+
plt.title("Reflectance map based on 100th wavelength")
894903
return
895904

896905

@@ -924,16 +933,16 @@ def convert_arr_to_thumbnail(
924933

925934
result = (result - result_min) / (result_max - result_min + 1e-8)
926935
# occult the NaNs and infs
927-
result = np.nan_to_num(result, nan=0.0, posinf=255.0, neginf=0.0)
936+
# result = np.nan_to_num(result, nan=0., posinf=255., neginf=0.)
928937

929938
if cmap is not None:
930939
cm = plt.get_cmap(cmap)
931-
result = cm(data)[..., :4] # includes alpha
940+
result = cm(result)[..., :4] # includes alpha
932941
result = (result * 255).astype(np.uint8)
933942
if mode == "RGB":
934943
result = result[..., :3]
935944
else:
936-
result = (data * 255).astype(np.uint8)
945+
result = (result * 255).astype(np.uint8)
937946
if mode in ["RGB", "RGBA"]:
938947
result = np.stack([result] * (3 if mode == "RGB" else 4), axis=-1)
939948

@@ -944,9 +953,9 @@ def convert_arr_to_thumbnail(
944953

945954
tempdir = TemporaryDirectory()
946955
resized_img = convert_arr_to_thumbnail(
947-
ex_nc_ds_l2.Reflectance.mean("wavelength").values,
956+
getattr(ex_nc_ds_l2.Reflectance, "mean")("wavelength").values,
948957
(256, 256),
949-
mode="RGB",
958+
mode="RGBA",
950959
cmap="viridis",
951960
)
952961

src/psup_stac_converter/_main.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ def create_catalog(
6262
psup_data_inventory_file: Path = None,
6363
wkt_file_path: Path = None,
6464
clean_prev_output: bool = False,
65+
n_omega_items: int | None = None,
6566
**kwargs,
6667
):
6768
catalog_creator = CatalogCreator(
@@ -70,5 +71,6 @@ def create_catalog(
7071
psup_data_inventory_file=psup_data_inventory_file,
7172
wkt_file=wkt_file_path,
7273
log=kwargs.get("logger"),
74+
n_omega_files=n_omega_items,
7375
)
7476
return catalog_creator.create_catalog(clean_previous_output=clean_prev_output)

src/psup_stac_converter/cli.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,12 @@ def create_stac_catalog(
115115
resolve_path=True,
116116
),
117117
] = None,
118+
n_omega_items: Annotated[
119+
int,
120+
typer.Option(
121+
"--n-omega", help="Specifies the limit of OMEGA items to generate"
122+
),
123+
] = None,
118124
clean_previous_output: Annotated[
119125
bool,
120126
typer.Option("--clean/--no-clean", "-c/-nc", help="Cleans the output folder"),
@@ -131,6 +137,7 @@ def create_stac_catalog(
131137
psup_data_inventory_file=psup_inventory_file or settings.psup_inventory_file,
132138
wkt_file_path=wkt_file_path or settings.wkt_file_path,
133139
clean_prev_output=clean_previous_output,
140+
n_omega_items=n_omega_items or settings.n_omega_items,
134141
**{k: v for k, v in ctx.obj.items() if k not in ["settings"]},
135142
)
136143

src/psup_stac_converter/extensions.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,20 @@
1313
type StacInstance = pystac.Catalog | pystac.Collection | pystac.Item
1414

1515

16-
def apply_ssys(
17-
stac_instance: StacInstance, mars_local_time: str | None = None
18-
) -> StacInstance:
16+
def apply_ssys(stac_instance: StacInstance, mars_local_time: str = "") -> StacInstance:
17+
"""Applies Solary Stsem extension over a Stac instance object
18+
19+
Note:
20+
ssys v1.1.0 disallows Nonetypes. If the date has to be fixed somehow,
21+
pass an empty string.
22+
23+
Args:
24+
stac_instance (StacInstance): _description_
25+
mars_local_time (str, optional): _description_. Defaults to "".
26+
27+
Returns:
28+
StacInstance: _description_
29+
"""
1930
if isinstance(stac_instance, pystac.Item):
2031
ssys = SolSysExtension.ext(stac_instance, add_if_missing=True)
2132
ssys.apply(

src/psup_stac_converter/informations/publications.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,72 +3,72 @@
33
omega_map_publications = [
44
Publication(
55
citation="A. Ody, F. Poulet, Y. Langevin, J.-P. Bibring, G. Bellucci, F. Altieri, B. Gondet, M. Vincendon, J.Carter and N. Manaud (2012), Global maps of anhydrous minerals at the surface of Mars from OMEGA/MEx, J. Geophys. Res., 117, E00J14",
6-
doi="doi:10.1029/2012JE004117",
6+
doi="10.1029/2012JE004117",
77
),
88
Publication(
99
citation="M. Vincendon, J. Audouard, F. Altieri, A. Ody (2015), Mars Express measurements of surface albedo changes over 2004–2010, In Icarus, Volume 251, 2015, Pages 145-163, ISSN 0019-1035",
10-
doi="doi:10.1016/j.icarus.2014.10.029",
10+
doi="10.1016/j.icarus.2014.10.029",
1111
),
1212
Publication(
1313
citation="J. Audouard, F. Poulet, M. Vincendon, J.-P. Bibring, F. Forget, Y. Langevin, B. Gondet (2014), Mars surface thermal inertia and heterogeneities from OMEGA/MEX, In Icarus Volume 233, 2014, Pages 194-213",
14-
doi="doi:10.1016/j.icarus.2014.01.045",
14+
doi="10.1016/j.icarus.2014.01.045",
1515
),
1616
Publication(
1717
citation="F. Poulet, C. Quantin-Nataf, H. Ballans, K. Dassas, J. Audouard, J. Carter, B. Gondet, L. Lozac’h, J.-C. Malapert, C. Marmo, L. Riu, A. Séjourné (2018), PSUP: a Planetary SUrface Portal, Planetary and Space Science, Volume 150, 2018, Pages 2-8",
18-
doi="doi:10.1016/j.pss.2017.01.016",
18+
doi="10.1016/j.pss.2017.01.016",
1919
),
2020
]
2121
omega_c_channel = [
2222
Publication(
2323
citation="""
2424
Lucie Riu, John Carter, François Poulet, Alejandro Cardesín-Moinelo, Patrick Martin, Global surficial water content stored in hydrated silicates at Mars from OMEGA/MEx, Icarus, Volume 398, 2023, 115537, ISSN 0019-1035,
2525
""",
26-
doi="https://doi.org/10.1016/j.icarus.2023.115537",
26+
doi="10.1016/j.icarus.2023.115537",
2727
),
2828
Publication(
2929
citation="""
3030
M. Vincendon, J. Audouard, F. Altieri, A. Ody, Mars Express measurements of surface albedo changes over 2004–2010, Icarus, Volume 251, 2015, Pages 145-163, ISSN 0019-1035
3131
""",
32-
doi="https://doi.org/10.1016/j.icarus.2014.10.029",
32+
doi="10.1016/j.icarus.2014.10.029",
3333
),
3434
Publication(
3535
citation="""
3636
Audouard, J., F. Poulet, M. Vincendon, R. E. Milliken, D. Jouglet, J.-P. Bibring, B. Gondet, and Y. Langevin (2014), Water in the Martian regolith from OMEGA/Mars Express, J. Geophys. Res. Planets, 119, 1969–1989
3737
""",
38-
doi="doi:10.1002/2014JE004649",
38+
doi="10.1002/2014JE004649",
3939
),
4040
Publication(
4141
citation="""
4242
Langevin, Y., J.-P. Bibring, F. Montmessin, F. Forget, M. Vincendon, S. Douté, F. Poulet, and B. Gondet (2007), Observations of the south seasonal cap of Mars during recession in 2004–2006 by the OMEGA visible/near-infrared imaging spectrometer on board Mars Express, J. Geophys. Res., 112, E08S12
4343
""",
44-
doi="doi:10.1029/2006JE002841",
44+
doi="10.1029/2006JE002841",
4545
),
4646
]
4747
omega_data_cubes = [
4848
Publication(
4949
citation="M. Vincendon, J. Audouard, F. Altieri, A. Ody (2015), Mars Express measurements of surface albedo changes over 2004–2010, In Icarus, Volume 251, 2015, Pages 145-163, ISSN 0019-1035",
50-
doi="doi:10.1016/j.icarus.2014.10.029",
50+
doi="10.1016/j.icarus.2014.10.029",
5151
),
5252
Publication(
5353
citation="""
5454
Audouard, J., F. Poulet, M. Vincendon, R. E. Milliken, D. Jouglet, J.-P. Bibring, B. Gondet, and Y. Langevin (2014), Water in the Martian regolith from OMEGA/Mars Express, J. Geophys. Res. Planets, 119, 1969–1989
5555
""",
56-
doi="doi:10.1002/2014JE004649",
56+
doi="10.1002/2014JE004649",
5757
),
5858
Publication(
5959
citation="""
6060
Langevin, Y., J.-P. Bibring, F. Montmessin, F. Forget, M. Vincendon, S. Douté, F. Poulet, and B. Gondet (2007), Observations of the south seasonal cap of Mars during recession in 2004–2006 by the OMEGA visible/near-infrared imaging spectrometer on board Mars Express, J. Geophys. Res., 112, E08S12
6161
""",
62-
doi="doi:10.1029/2006JE002841",
62+
doi="10.1029/2006JE002841",
6363
),
6464
Publication(
6565
citation="A. Ody, F. Poulet, Y. Langevin, J.-P. Bibring, G. Bellucci, F. Altieri, B. Gondet, M. Vincendon, J.Carter and N. Manaud (2012), Global maps of anhydrous minerals at the surface of Mars from OMEGA/MEx, J. Geophys. Res., 117, E00J14",
66-
doi="doi:10.1029/2012JE004117",
66+
doi="10.1029/2012JE004117",
6767
),
6868
Publication(
6969
citation="""
7070
Denis Jouglet, François Poulet, Yves Langevin, Jean-Pierre Bibring, Brigitte Gondet, Mathieu Vincendon, Michel Berthe, OMEGA long wavelength channel: Data reduction during non-nominal stages, Planetary and Space Science, Volume 57, Issues 8–9, 2009, Pages 1032-1042, ISSN 0032-0633
7171
""",
72-
doi="https://doi.org/10.1016/j.pss.2008.07.025.",
72+
doi="10.1016/j.pss.2008.07.025.",
7373
),
7474
]

src/psup_stac_converter/omega/_base.py

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,15 @@ def default(self, o: Any) -> Any:
4242

4343

4444
def reformat_nc_info(nc_info: dict[str, Any]) -> dict[str, Any]:
45+
"""Opens previously extracted NetCDF4 datacube info for
46+
catalog input
47+
48+
Args:
49+
nc_info (dict[str, Any]): _description_
50+
51+
Returns:
52+
dict[str, Any]: _description_
53+
"""
4554
for k, v in nc_info["variables"].items():
4655
nc_info["variables"][k] = Variable(properties={**v})
4756
for k, v in nc_info["dimensions"].items():
@@ -171,6 +180,11 @@ def omega_data_ids(self) -> pd.Index:
171180
def n_elements(self) -> int:
172181
return self.omega_data_ids.size
173182

183+
def get_omega_data_ids(self, n_limit: int | None = None) -> pd.Index:
184+
if n_limit is None:
185+
return self.omega_data_ids
186+
return self.omega_data_ids[:n_limit]
187+
174188
def find_info_by_orbit_cube(
175189
self,
176190
orbit_cube_idx: str,
@@ -361,7 +375,7 @@ def find_temporal_extent(self) -> pystac.TemporalExtent:
361375
]
362376
)
363377

364-
def create_collection(self) -> pystac.Collection:
378+
def create_collection(self, n_limit: int | None = None) -> pystac.Collection:
365379
"""Creates a STAC collection based over the OMEGA data series.
366380
367381
Returns:
@@ -388,7 +402,10 @@ def create_collection(self) -> pystac.Collection:
388402
# TODO: make a pystac extension for processing
389403
# collection.extra_fields["processing:level"] = self.processing_level
390404

391-
for omega_data_idx in tqdm(self.omega_data_ids, total=self.n_elements):
405+
for omega_data_idx in tqdm(
406+
self.get_omega_data_ids(n_limit=n_limit),
407+
total=n_limit if n_limit else self.n_elements,
408+
):
392409
try:
393410
omega_data_item = self.create_stac_item(omega_data_idx)
394411
collection.add_item(omega_data_item)
@@ -497,6 +514,7 @@ def create_stac_item(self, orbit_cube_idx: str, **kwargs) -> pystac.Item:
497514
description="PNG thumbnail preview for visualizations",
498515
)
499516
pystac_item.add_asset("thumbnail", thumbn_asset)
517+
self.log.debug(f"Added {thumbn_asset} to item.")
500518
except OSError as ose:
501519
self.log.error(f"[{ose.__class__.__name__}] {ose}")
502520
self.log.error(
@@ -510,6 +528,16 @@ def create_stac_item(self, orbit_cube_idx: str, **kwargs) -> pystac.Item:
510528
self.log.error(f"[{e.__class__.__name__}] {e}")
511529
finally:
512530
nc_data.close()
531+
else:
532+
# Thumbnail
533+
thumbn_asset = pystac.Asset(
534+
href=thumbnail_location.as_posix(),
535+
media_type=pystac.MediaType.PNG,
536+
roles=["thumbnail"],
537+
description="PNG thumbnail preview for visualizations",
538+
)
539+
pystac_item.add_asset("thumbnail", thumbn_asset)
540+
self.log.debug(f"Added {thumbn_asset} to item.")
513541

514542
# extensions
515543
pystac_item = cast(pystac.Item, apply_ssys(pystac_item))
@@ -692,6 +720,8 @@ def retrieve_nc_info_from_saved_state(self, orbit_cube_idx: str) -> dict[str, An
692720

693721
return nc_info
694722

723+
# TODO: revise startegy when this function is called
724+
# You need to pick specific reflectance data for that
695725
def make_thumbnail(
696726
self,
697727
orbit_cube_idx: str,

src/psup_stac_converter/omega/c_channel_proj.py

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,18 +31,9 @@ def __init__(
3131
publications=omega_c_channel,
3232
log=log,
3333
)
34-
self.sav_metadata_folder = psup_io_handler.output_folder / "l3_sav"
35-
self.nc_metadata_folder = psup_io_handler.output_folder / "l3_nc"
36-
self.log.debug(f".sav metadata folder: {self.sav_metadata_folder}")
37-
self.log.debug(f".nc metadata folder: {self.nc_metadata_folder}")
38-
if not self.sav_metadata_folder.exists():
39-
self.sav_metadata_folder.mkdir()
4034

41-
if not self.nc_metadata_folder.exists():
42-
self.nc_metadata_folder.mkdir()
43-
44-
def create_collection(self) -> pystac.Collection:
45-
collection = super().create_collection()
35+
def create_collection(self, n_limit: int | None = None) -> pystac.Collection:
36+
collection = super().create_collection(n_limit=n_limit)
4637

4738
# Only the C band is needed
4839
collection = cast(
@@ -105,7 +96,7 @@ def extract_sav_metadata(self, orbit_cube_idx: str, **kwargs) -> dict[str, Any]:
10596
return {}
10697

10798
def create_stac_item(self, orbit_cube_idx) -> pystac.Item:
108-
text_data: OmegaDataTextItem = cast(
99+
text_data = cast(
109100
OmegaDataTextItem, self.open_file(orbit_cube_idx, "txt", on_disk=True)
110101
)
111102
footprint = json.loads(to_geojson(text_data.bbox))

0 commit comments

Comments
 (0)