smos 0.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- smos/Grid_Point_Mask_USGS.nc +0 -0
- smos/__init__.py +10 -0
- smos/cli.py +25 -0
- smos/grid.py +121 -0
- smos/interface.py +636 -0
- smos/misc.py +91 -0
- smos/reshuffle.py +154 -0
- smos/smos_ic/__init__.py +0 -0
- smos/smos_ic/cli.py +198 -0
- smos/smos_ic/download.py +341 -0
- smos/smos_ic/interface_ic.py +177 -0
- smos/smos_ic/reshuffle_ic.py +123 -0
- smos/smos_l2/__init__.py +0 -0
- smos/smos_l2/cli.py +224 -0
- smos/smos_l2/download.py +318 -0
- smos/smos_l2/reshuffle.py +155 -0
- smos/smos_l3/__init__.py +0 -0
- smos/smos_l3/cli.py +278 -0
- smos/smos_l3/download.py +487 -0
- smos/smos_l3/interface_l3.py +329 -0
- smos/smos_l3/reshuffle.py +195 -0
- smos/smos_l4/__init__.py +0 -0
- smos/smos_l4/cli.py +107 -0
- smos/smos_l4/interface_l4.py +259 -0
- smos/smos_l4/reshuffle_l4.py +123 -0
- smos-0.5.dist-info/METADATA +165 -0
- smos-0.5.dist-info/RECORD +31 -0
- smos-0.5.dist-info/WHEEL +5 -0
- smos-0.5.dist-info/entry_points.txt +3 -0
- smos-0.5.dist-info/licenses/LICENSE.txt +21 -0
- smos-0.5.dist-info/top_level.txt +1 -0
|
Binary file
|
smos/__init__.py
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
2
|
+
|
|
3
|
+
try:
|
|
4
|
+
# Change here if project is renamed and does not equal the package name
|
|
5
|
+
dist_name = __name__
|
|
6
|
+
__version__ = version(dist_name)
|
|
7
|
+
except PackageNotFoundError: # pragma: no cover
|
|
8
|
+
__version__ = "unknown"
|
|
9
|
+
finally:
|
|
10
|
+
del version, PackageNotFoundError
|
smos/cli.py
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Command line interface for all SMOS products: `smos <product> <command>`,
|
|
3
|
+
e.g. `smos l3 download`. See `smos --help`.
|
|
4
|
+
"""
|
|
5
|
+
import click
|
|
6
|
+
|
|
7
|
+
from smos.smos_l2.cli import smos_l2
|
|
8
|
+
from smos.smos_ic.cli import smos_ic
|
|
9
|
+
from smos.smos_l3.cli import smos_l3
|
|
10
|
+
from smos.smos_l4.cli import smos_l4
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@click.group(short_help="SMOS Command Line Programs.", name="smos")
|
|
14
|
+
def smos():
|
|
15
|
+
"""
|
|
16
|
+
Download SMOS data and convert it into time series. Each product has
|
|
17
|
+
its own group of commands, see e.g. `smos l3 --help`.
|
|
18
|
+
"""
|
|
19
|
+
pass
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
smos.add_command(smos_l2, name="l2")
|
|
23
|
+
smos.add_command(smos_ic, name="ic")
|
|
24
|
+
smos.add_command(smos_l3, name="l3")
|
|
25
|
+
smos.add_command(smos_l4, name="l4")
|
smos/grid.py
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
from pygeogrids.grids import CellGrid, BasicGrid, lonlat2cell
|
|
4
|
+
from ease_grid import EASE2_grid
|
|
5
|
+
import numpy as np
|
|
6
|
+
from netCDF4 import Dataset
|
|
7
|
+
import os
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class EASE25CellGrid(CellGrid):
|
|
11
|
+
""" CellGrid version of EASE25 Grid as used in SMOS IC """
|
|
12
|
+
|
|
13
|
+
def __init__(self, bbox=None, only_land=False):
|
|
14
|
+
"""
|
|
15
|
+
Parameters
|
|
16
|
+
----------
|
|
17
|
+
bbox: tuple, optional (default: None)
|
|
18
|
+
(min_lon, min_lat, max_lon, max_lat)
|
|
19
|
+
Bounding box to create subset for, if None is passed a global
|
|
20
|
+
grid is used.
|
|
21
|
+
only_land: bool, optional (default: False)
|
|
22
|
+
If True, restrict the grid to land points only.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
ease25 = EASE2_grid(25000)
|
|
26
|
+
glob_lons, glob_lats = ease25.londim, ease25.latdim
|
|
27
|
+
|
|
28
|
+
lons, lats = np.meshgrid(glob_lons, glob_lats)
|
|
29
|
+
assert lons.shape == lats.shape
|
|
30
|
+
shape = lons.shape
|
|
31
|
+
|
|
32
|
+
lats = np.flipud(lats) # flip lats, so that origin in bottom left
|
|
33
|
+
|
|
34
|
+
globgrid = BasicGrid(lons.flatten(), lats.flatten(), shape=shape)
|
|
35
|
+
|
|
36
|
+
self.bbox = bbox
|
|
37
|
+
self.cellsize = 5.
|
|
38
|
+
|
|
39
|
+
# Start with global grid
|
|
40
|
+
grid = globgrid
|
|
41
|
+
sgpis = globgrid.activegpis
|
|
42
|
+
params = {'subset': sgpis}
|
|
43
|
+
land_mask = None
|
|
44
|
+
|
|
45
|
+
# Get land mask if needed
|
|
46
|
+
if only_land:
|
|
47
|
+
mask_path = os.path.join(os.path.abspath(os.path.dirname(__file__)),
|
|
48
|
+
"Grid_Point_Mask_USGS.nc")
|
|
49
|
+
with Dataset(mask_path) as ds:
|
|
50
|
+
land_mask = ds.variables["USGS_Land_Flag"][:].flatten().filled() == 0.0
|
|
51
|
+
|
|
52
|
+
# Special handling when both land-only and bbox are specified
|
|
53
|
+
if only_land and self.bbox:
|
|
54
|
+
# Get land points from global grid
|
|
55
|
+
land_points = np.ma.masked_array(globgrid.get_grid_points()[0], land_mask)
|
|
56
|
+
land_sgpis = globgrid.activegpis[~land_points.mask]
|
|
57
|
+
|
|
58
|
+
# Get bbox points from global grid
|
|
59
|
+
bbox_sgpis = globgrid.get_bbox_grid_points(
|
|
60
|
+
latmin=self.bbox[1],
|
|
61
|
+
latmax=self.bbox[3],
|
|
62
|
+
lonmin=self.bbox[0],
|
|
63
|
+
lonmax=self.bbox[2]
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
# Create intersection of land points and bbox points
|
|
67
|
+
# (points that are both on land AND within bbox)
|
|
68
|
+
intersection = np.intersect1d(land_sgpis, bbox_sgpis)
|
|
69
|
+
|
|
70
|
+
# Use global grid with the intersection as subset
|
|
71
|
+
grid = globgrid
|
|
72
|
+
sgpis = intersection
|
|
73
|
+
params = {'subset': sgpis}
|
|
74
|
+
shape = (len(sgpis),)
|
|
75
|
+
|
|
76
|
+
# Apply original land mask if only_land is True but no bbox is specified
|
|
77
|
+
# Land points are a subset of the global grid, i.e. the gpis are the
|
|
78
|
+
# same as in the global grid (not renumbered).
|
|
79
|
+
elif only_land:
|
|
80
|
+
land_points = np.ma.masked_array(globgrid.get_grid_points()[0], land_mask)
|
|
81
|
+
sgpis = globgrid.activegpis[~land_points.mask]
|
|
82
|
+
params = {'subset': sgpis}
|
|
83
|
+
shape = (len(sgpis),)
|
|
84
|
+
|
|
85
|
+
# Apply original bbox filter if only bbox is specified (no land mask)
|
|
86
|
+
elif self.bbox:
|
|
87
|
+
bbox_sgpis = grid.get_bbox_grid_points(
|
|
88
|
+
latmin=self.bbox[1],
|
|
89
|
+
latmax=self.bbox[3],
|
|
90
|
+
lonmin=self.bbox[0],
|
|
91
|
+
lonmax=self.bbox[2]
|
|
92
|
+
)
|
|
93
|
+
sgpis = bbox_sgpis
|
|
94
|
+
params = {'subset': sgpis}
|
|
95
|
+
|
|
96
|
+
# Set final grid parameters
|
|
97
|
+
self.grid = grid
|
|
98
|
+
self.subset = sgpis
|
|
99
|
+
self.shape = shape
|
|
100
|
+
|
|
101
|
+
super().__init__(lon=grid.arrlon,
|
|
102
|
+
lat=grid.arrlat,
|
|
103
|
+
cells=lonlat2cell(grid.arrlon, grid.arrlat,
|
|
104
|
+
self.cellsize),
|
|
105
|
+
shape=shape,
|
|
106
|
+
**params)
|
|
107
|
+
|
|
108
|
+
if only_land:
|
|
109
|
+
self.subset_shape = shape
|
|
110
|
+
else:
|
|
111
|
+
self.subset_shape = (len(np.unique(self.activearrlat)),
|
|
112
|
+
len(np.unique(self.activearrlon)))
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def cut(self) -> CellGrid:
|
|
116
|
+
# create a new grid from the active subset
|
|
117
|
+
return BasicGrid(lon=self.activearrlon,
|
|
118
|
+
lat=self.activearrlat,
|
|
119
|
+
gpis=self.activegpis,
|
|
120
|
+
subset=None,
|
|
121
|
+
shape=self.subset_shape).to_cell_grid(self.cellsize)
|