Skip to content

Commit 289a431

Browse files
committed
rename the functions to return the results as a dataframe or a pandas series following convention in xarray (to_dataframe) and in the same way in ActiveResult and PassiveResult
1 parent 226969f commit 289a431

File tree

2 files changed

+71
-36
lines changed

2 files changed

+71
-36
lines changed

smrt/core/result.py

Lines changed: 40 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -110,13 +110,7 @@ def sel_data(self, channel=None, **kwargs):
110110
raise NotImplementedError("must be implemented in a subclass")
111111

112112
def return_as_dataframe(self, name, channel_axis=None, **kwargs):
113-
"""return the result as a dataframe. The dataframe organization is different depending on channel_axis.
114-
115-
:param name: name of the data frame column
116-
:param channel_axis: if channel_axis=None, the dataframe has hierarchical indexes with frequency, polarization, etc.
117-
If channel_axis="column", each channel defined in the sensor is one column.
118-
If channel_axis="index", each channel defined in the sensor is one index.
119-
"""
113+
# is to be called from child classes called to_dataframe
120114

121115
def xr_to_dataframe(x, name):
122116
# workaround for when the resulting array has no dims anymore
@@ -150,12 +144,12 @@ def xr_to_dataframe(x, name):
150144
else:
151145
return xr_to_dataframe(self.sel_data(**kwargs), name=name)
152146

153-
def return_as_series(self):
154-
"""return the result as a series with the channels defined in the sensor as index.
147+
def to_series(self, **kwargs):
148+
"""return the result as a series with the channels defined in the sensor as index.
155149
This requires that the sensor has declared a channel list.
156150
157151
"""
158-
return self.return_as_dataframe('out', channel_axis='index')['out']
152+
return self.return_as_dataframe('out', channel_axis='column', **kwargs).iloc[0]
159153

160154

161155
class PassiveResult(Result):
@@ -182,21 +176,27 @@ def Tb(self, channel=None, **kwargs):
182176
"""
183177
return _strongsqueeze(self.sel_data(channel=channel, **kwargs))
184178

185-
def Tb_as_dataframe(self, channel_axis=None, **kwargs):
186-
"""Return brightness temperature as a pandas.DataFrame or pandas.Series. Any parameter can be added to slice the results
179+
def Tb_as_dataframe(self, **kwargs):
180+
"""See :py:meth:`PassiveResult`.to_dataframe
181+
"""
182+
183+
return self.to_dataframe(**kwargs)
184+
185+
def to_dataframe(self, channel_axis=None, **kwargs):
186+
"""Return brightness temperature as a pandas.DataFrame. Any parameter can be added to slice the results
187187
(e.g. frequency=37e9 or polarization='V'). See xarray slicing with sel method (to document).
188-
In addition channel_axis controls the format of the output. If set to None, the DataFrame has a multi-index formed with all the
188+
In addition channel_axis controls the format of the output. If set to None, the DataFrame has a multi-index with all the
189189
dimensions (frequency, polarization, ...).
190-
If channel_axis is set to "column", and if the sensor has named channels (channel_map in SMRT wording), the channel are
190+
If channel_axis is set to "column", and if the sensor has a channel list, the channels are
191191
in columns and the other dimensions are in index. If set to "index", the channel are in index with all the other dimensions.
192192
193-
The most conviennent is probably channel_axis="column" while channel_axis=None (default) contains all the data even those
193+
The most conviennent is probably channel_axis="column" while channel_axis=None (default) contains all the data even those
194194
not corresponding to a channel and applies to any sensor even those without channel_map.
195195
196196
:param channel_axis: controls whether to use the sensor channel or not and if yes, as a column or index.
197197
"""
198198

199-
return self.return_as_dataframe(name='Tb', channel_axis=channel_axis, **kwargs)
199+
return super().return_as_dataframe(name='Tb', channel_axis=channel_axis, **kwargs)
200200

201201
def TbV(self, **kwargs):
202202
"""Return V polarization. Any parameter can be added to slice the results (e.g. frequency=37e9).
@@ -276,42 +276,54 @@ def sigma(self, channel=None, **kwargs):
276276
return _strongsqueeze(self.sel_data(channel=channel, return_backscatter="natural", **kwargs))
277277

278278
def sigma_dB(self, channel=None, **kwargs):
279-
"""Return backscattering coefficient. Any parameter can be added to slice the results (e.g. frequency=37e9, polarization_inc='V', polarization='V').
280-
See xarray slicing with sel method (to document)"""
279+
"""Return backscattering coefficient. Any parameter can be added to slice the results (e.g. frequency=37e9,
280+
polarization_inc='V', polarization='V'). See xarray slicing with sel method (to document)
281+
"""
281282

282283
return _strongsqueeze(self.sel_data(channel=channel, return_backscatter="dB", **kwargs))
283284

284285
def sigma_as_dataframe(self, channel_axis=None, **kwargs):
285-
"""Return backscattering coefficient as a pandas.DataFrame or pandas.Series. Any parameter can be added to slice the results
286+
"""Return backscattering coefficient as a pandas.DataFrame. Any parameter can be added to slice the results
286287
(e.g. frequency=37e9 or polarization='V'). See xarray slicing with sel method (to document).
287288
In addition channel_axis controls the format of the output. If set to None, the DataFrame has a multi-index formed with all the
288289
dimensions (frequency, polarization, ...).
289-
If channel_axis is set to "column", and if the sensor has named channels (channel_map in SMRT wording), the channel are
290+
If channel_axis is set to "column", and if the sensor has named channels (channel_map in SMRT wording), the channel are
290291
in columns and the other dimensions are in index. If set to "index", the channel are in index with all the other dimensions.
291292
292-
The most conviennent is probably channel_axis="column" while channel_axis=None (default) contains all the data even those
293+
The most conviennent is probably channel_axis="column" while channel_axis=None (default) contains all the data even those
293294
not corresponding to a channel and applies to any sensor even those without channel_map.
294295
295296
:param channel_axis: controls whether to use the sensor channel or not and if yes, as a column or index.
296297
"""
297298

298-
return self.return_as_dataframe(name='sigma', channel_axis=channel_axis, return_backscatter="natural", **kwargs)
299+
return super().return_as_dataframe(name='sigma', channel_axis=channel_axis, return_backscatter="natural", **kwargs)
299300

300-
def sigma_dB_as_dataframe(self, channel_axis=None, **kwargs):
301-
"""Return backscattering coefficient in dB as a pandas.DataFrame or pandas.Series. Any parameter can be added to slice the results
301+
def sigma_dB_as_dataframe(self, **kwargs):
302+
"""See :py:meth:`ActiveResult`.to_dataframe
303+
"""
304+
return self.to_dataframe(**kwargs)
305+
306+
def to_dataframe(self, channel_axis=None, **kwargs):
307+
"""Return backscattering coefficient in dB as a pandas.DataFrame. Any parameter can be added to slice the results
302308
(e.g. frequency=37e9 or polarization='V'). See xarray slicing with sel method (to document).
303-
In addition channel_axis controls the format of the output. If set to None, the DataFrame has a multi-index formed with all the
309+
In addition channel_axis controls the format of the output. If set to None, the DataFrame has a multi-index with all the
304310
dimensions (frequency, polarization, ...).
305-
If channel_axis is set to "column", and if the sensor has named channels (channel_map in SMRT wording), the channel are
311+
If channel_axis is set to "column", and if the sensor has named channels (channel_map in SMRT wording), the channel are
306312
in columns and the other dimensions are in index. If set to "index", the channel are in index with all the other dimensions.
307313
308-
The most conviennent is probably channel_axis="column" while channel_axis=None (default) contains all the data even those
314+
The most conviennent is probably channel_axis="column" while channel_axis=None (default) contains all the data even those
309315
not corresponding to a channel and applies to any sensor even those without channel_map.
310316
311317
:param channel_axis: controls whether to use the sensor channel or not and if yes, as a column or index.
312318
"""
319+
return super().return_as_dataframe(name='sigma', channel_axis=channel_axis, return_backscatter="dB", **kwargs)
313320

314-
return self.return_as_dataframe(name='sigma', channel_axis=channel_axis, return_backscatter="dB", **kwargs)
321+
def to_series(self, **kwargs):
322+
"""return backscattering coefficients in dB as a series with the channels defined in the sensor as index.
323+
This requires that the sensor has declared a channel list.
324+
325+
"""
326+
return super().to_series(return_backscatter="dB", **kwargs)
315327

316328
def sigmaVV(self, **kwargs):
317329
"""Return VV backscattering coefficient. Any parameter can be added to slice the results (e.g. frequency=37e9).
@@ -353,7 +365,6 @@ def sigmaVH_dB(self, **kwargs):
353365
See xarray slicing with sel method (to document)"""
354366
return dB(self.sigmaVH(**kwargs))
355367

356-
357368
# def groupby(self, variable):
358369
# """iterated over a given variable. Variable is typically frequency, theta, polarization or snowpack"""
359370
#

smrt/core/test_result.py

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,12 @@
66

77
# Tests written in response to -ve intensity bug in result.py
88
res_example = result.ActiveResult([[[[4.01445680e-03, 3.77746658e-03, 0.00000000e+00]],
9-
[[3.83889082e-03, 3.85904771e-03, 0.00000000e+00]],
10-
[[2.76453599e-20, -2.73266027e-20, 0.00000000e+00]]]],
11-
coords = [('theta', [35]), ('polarization', ['V','H','U']),
12-
('theta_inc', [35]), ('polarization_inc', ['V','H','U'])],
13-
channel_map={'VV': dict(polarization='V', polarization_inc='V'),
14-
'VH': dict(polarization='H', polarization_inc='V')})
15-
9+
[[3.83889082e-03, 3.85904771e-03, 0.00000000e+00]],
10+
[[2.76453599e-20, -2.73266027e-20, 0.00000000e+00]]]],
11+
coords=[('theta', [35]), ('polarization', ['V', 'H', 'U']),
12+
('theta_inc', [35]), ('polarization_inc', ['V', 'H', 'U'])],
13+
channel_map={'VV': dict(polarization='V', polarization_inc='V'),
14+
'VH': dict(polarization='H', polarization_inc='V')})
1615

1716

1817
def test_methods():
@@ -45,5 +44,30 @@ def test_sigma_dB():
4544

4645
def test_sigma_dB_as_dataframe():
4746
df = res_example.sigma_dB_as_dataframe(channel_axis='column')
47+
48+
assert 'VV' in df.columns
49+
assert 'VH' in df.columns
50+
4851
np.testing.assert_allclose(df['VV'], -13.8379882755357)
4952
np.testing.assert_allclose(df['VH'], -14.0321985560285)
53+
54+
55+
def test_to_dataframe():
56+
df = res_example.to_dataframe(channel_axis='column')
57+
58+
assert 'VV' in df.columns
59+
assert 'VH' in df.columns
60+
61+
np.testing.assert_allclose(df['VV'], -13.8379882755357)
62+
np.testing.assert_allclose(df['VH'], -14.0321985560285)
63+
64+
65+
def test_return_as_series():
66+
series = res_example.to_series()
67+
print(series)
68+
69+
assert 'VV' in series.index
70+
assert 'VH' in series.index
71+
72+
np.testing.assert_allclose(series.loc['VV'], -13.8379882755357)
73+
np.testing.assert_allclose(series.loc['VH'], -14.0321985560285)

0 commit comments

Comments
 (0)