trufl 0.0.2__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.
- trufl/__init__.py +1 -0
- trufl/_modidx.py +81 -0
- trufl/callbacks.py +184 -0
- trufl/collector.py +35 -0
- trufl/mcdm.py +688 -0
- trufl/optimizer.py +47 -0
- trufl/reader.py +14 -0
- trufl/sampler.py +36 -0
- trufl/utils.py +110 -0
- trufl-0.0.2.dist-info/LICENSE +201 -0
- trufl-0.0.2.dist-info/METADATA +298 -0
- trufl-0.0.2.dist-info/RECORD +15 -0
- trufl-0.0.2.dist-info/WHEEL +5 -0
- trufl-0.0.2.dist-info/entry_points.txt +2 -0
- trufl-0.0.2.dist-info/top_level.txt +1 -0
trufl/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.0.2"
|
trufl/_modidx.py
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Autogenerated by nbdev
|
|
2
|
+
|
|
3
|
+
d = { 'settings': { 'branch': 'main',
|
|
4
|
+
'doc_baseurl': '/trufl',
|
|
5
|
+
'doc_host': 'https://franckalbinet.github.io',
|
|
6
|
+
'git_url': 'https://github.com/franckalbinet/trufl',
|
|
7
|
+
'lib_path': 'trufl'},
|
|
8
|
+
'syms': { 'trufl.callbacks': { 'trufl.callbacks.Callback': ('callbacks.html#callback', 'trufl/callbacks.py'),
|
|
9
|
+
'trufl.callbacks.CountCB': ('callbacks.html#countcb', 'trufl/callbacks.py'),
|
|
10
|
+
'trufl.callbacks.CountCB.__call__': ('callbacks.html#countcb.__call__', 'trufl/callbacks.py'),
|
|
11
|
+
'trufl.callbacks.CountCB.__init__': ('callbacks.html#countcb.__init__', 'trufl/callbacks.py'),
|
|
12
|
+
'trufl.callbacks.MaxCB': ('callbacks.html#maxcb', 'trufl/callbacks.py'),
|
|
13
|
+
'trufl.callbacks.MaxCB.__call__': ('callbacks.html#maxcb.__call__', 'trufl/callbacks.py'),
|
|
14
|
+
'trufl.callbacks.MaxCB.__init__': ('callbacks.html#maxcb.__init__', 'trufl/callbacks.py'),
|
|
15
|
+
'trufl.callbacks.MinCB': ('callbacks.html#mincb', 'trufl/callbacks.py'),
|
|
16
|
+
'trufl.callbacks.MinCB.__call__': ('callbacks.html#mincb.__call__', 'trufl/callbacks.py'),
|
|
17
|
+
'trufl.callbacks.MinCB.__init__': ('callbacks.html#mincb.__init__', 'trufl/callbacks.py'),
|
|
18
|
+
'trufl.callbacks.MoranICB': ('callbacks.html#moranicb', 'trufl/callbacks.py'),
|
|
19
|
+
'trufl.callbacks.MoranICB.__call__': ('callbacks.html#moranicb.__call__', 'trufl/callbacks.py'),
|
|
20
|
+
'trufl.callbacks.MoranICB.__init__': ('callbacks.html#moranicb.__init__', 'trufl/callbacks.py'),
|
|
21
|
+
'trufl.callbacks.MoranICB._weights': ('callbacks.html#moranicb._weights', 'trufl/callbacks.py'),
|
|
22
|
+
'trufl.callbacks.PriorCB': ('callbacks.html#priorcb', 'trufl/callbacks.py'),
|
|
23
|
+
'trufl.callbacks.PriorCB.__call__': ('callbacks.html#priorcb.__call__', 'trufl/callbacks.py'),
|
|
24
|
+
'trufl.callbacks.PriorCB.__init__': ('callbacks.html#priorcb.__init__', 'trufl/callbacks.py'),
|
|
25
|
+
'trufl.callbacks.State': ('callbacks.html#state', 'trufl/callbacks.py'),
|
|
26
|
+
'trufl.callbacks.State.__call__': ('callbacks.html#state.__call__', 'trufl/callbacks.py'),
|
|
27
|
+
'trufl.callbacks.State.__init__': ('callbacks.html#state.__init__', 'trufl/callbacks.py'),
|
|
28
|
+
'trufl.callbacks.State._flatten': ('callbacks.html#state._flatten', 'trufl/callbacks.py'),
|
|
29
|
+
'trufl.callbacks.State.expand_to_k_nearest': ( 'callbacks.html#state.expand_to_k_nearest',
|
|
30
|
+
'trufl/callbacks.py'),
|
|
31
|
+
'trufl.callbacks.State.get': ('callbacks.html#state.get', 'trufl/callbacks.py'),
|
|
32
|
+
'trufl.callbacks.State.run_cbs': ('callbacks.html#state.run_cbs', 'trufl/callbacks.py'),
|
|
33
|
+
'trufl.callbacks.StdCB': ('callbacks.html#stdcb', 'trufl/callbacks.py'),
|
|
34
|
+
'trufl.callbacks.StdCB.__call__': ('callbacks.html#stdcb.__call__', 'trufl/callbacks.py'),
|
|
35
|
+
'trufl.callbacks.StdCB.__init__': ('callbacks.html#stdcb.__init__', 'trufl/callbacks.py'),
|
|
36
|
+
'trufl.callbacks.Variable': ('callbacks.html#variable', 'trufl/callbacks.py')},
|
|
37
|
+
'trufl.collector': { 'trufl.collector.DataCollector': ('collector.html#datacollector', 'trufl/collector.py'),
|
|
38
|
+
'trufl.collector.DataCollector.__init__': ('collector.html#datacollector.__init__', 'trufl/collector.py'),
|
|
39
|
+
'trufl.collector.DataCollector.collect': ('collector.html#datacollector.collect', 'trufl/collector.py'),
|
|
40
|
+
'trufl.collector.DataCollector.get_values': ( 'collector.html#datacollector.get_values',
|
|
41
|
+
'trufl/collector.py')},
|
|
42
|
+
'trufl.mcdm': { 'trufl.mcdm.abspearson': ('mcdm.html#abspearson', 'trufl/mcdm.py'),
|
|
43
|
+
'trufl.mcdm.check_normalization_input': ('mcdm.html#check_normalization_input', 'trufl/mcdm.py'),
|
|
44
|
+
'trufl.mcdm.check_scoring_input': ('mcdm.html#check_scoring_input', 'trufl/mcdm.py'),
|
|
45
|
+
'trufl.mcdm.check_weighting_input': ('mcdm.html#check_weighting_input', 'trufl/mcdm.py'),
|
|
46
|
+
'trufl.mcdm.correlate': ('mcdm.html#correlate', 'trufl/mcdm.py'),
|
|
47
|
+
'trufl.mcdm.cp': ('mcdm.html#cp', 'trufl/mcdm.py'),
|
|
48
|
+
'trufl.mcdm.critic': ('mcdm.html#critic', 'trufl/mcdm.py'),
|
|
49
|
+
'trufl.mcdm.dcor': ('mcdm.html#dcor', 'trufl/mcdm.py'),
|
|
50
|
+
'trufl.mcdm.dist_matrix': ('mcdm.html#dist_matrix', 'trufl/mcdm.py'),
|
|
51
|
+
'trufl.mcdm.em': ('mcdm.html#em', 'trufl/mcdm.py'),
|
|
52
|
+
'trufl.mcdm.is_normalized_matrix': ('mcdm.html#is_normalized_matrix', 'trufl/mcdm.py'),
|
|
53
|
+
'trufl.mcdm.is_normalized_vector': ('mcdm.html#is_normalized_vector', 'trufl/mcdm.py'),
|
|
54
|
+
'trufl.mcdm.lin_func': ('mcdm.html#lin_func', 'trufl/mcdm.py'),
|
|
55
|
+
'trufl.mcdm.linear1': ('mcdm.html#linear1', 'trufl/mcdm.py'),
|
|
56
|
+
'trufl.mcdm.linear2': ('mcdm.html#linear2', 'trufl/mcdm.py'),
|
|
57
|
+
'trufl.mcdm.linear3': ('mcdm.html#linear3', 'trufl/mcdm.py'),
|
|
58
|
+
'trufl.mcdm.mw': ('mcdm.html#mw', 'trufl/mcdm.py'),
|
|
59
|
+
'trufl.mcdm.normalize': ('mcdm.html#normalize', 'trufl/mcdm.py'),
|
|
60
|
+
'trufl.mcdm.pearson': ('mcdm.html#pearson', 'trufl/mcdm.py'),
|
|
61
|
+
'trufl.mcdm.score': ('mcdm.html#score', 'trufl/mcdm.py'),
|
|
62
|
+
'trufl.mcdm.sd': ('mcdm.html#sd', 'trufl/mcdm.py'),
|
|
63
|
+
'trufl.mcdm.squared_dcor': ('mcdm.html#squared_dcor', 'trufl/mcdm.py'),
|
|
64
|
+
'trufl.mcdm.squared_dcov': ('mcdm.html#squared_dcov', 'trufl/mcdm.py'),
|
|
65
|
+
'trufl.mcdm.squared_dcov_matrix': ('mcdm.html#squared_dcov_matrix', 'trufl/mcdm.py'),
|
|
66
|
+
'trufl.mcdm.topsis': ('mcdm.html#topsis', 'trufl/mcdm.py'),
|
|
67
|
+
'trufl.mcdm.vector': ('mcdm.html#vector', 'trufl/mcdm.py'),
|
|
68
|
+
'trufl.mcdm.vic': ('mcdm.html#vic', 'trufl/mcdm.py'),
|
|
69
|
+
'trufl.mcdm.weigh': ('mcdm.html#weigh', 'trufl/mcdm.py')},
|
|
70
|
+
'trufl.optimizer': { 'trufl.optimizer.Optimizer': ('optimizer.html#optimizer', 'trufl/optimizer.py'),
|
|
71
|
+
'trufl.optimizer.Optimizer.__init__': ('optimizer.html#optimizer.__init__', 'trufl/optimizer.py'),
|
|
72
|
+
'trufl.optimizer.Optimizer.rank': ('optimizer.html#optimizer.rank', 'trufl/optimizer.py')},
|
|
73
|
+
'trufl.reader': { 'trufl.reader.read_geojson': ('reader.html#read_geojson', 'trufl/reader.py'),
|
|
74
|
+
'trufl.reader.read_shapefile': ('reader.html#read_shapefile', 'trufl/reader.py')},
|
|
75
|
+
'trufl.sampler': { 'trufl.sampler.Sampler': ('sampler.html#sampler', 'trufl/sampler.py'),
|
|
76
|
+
'trufl.sampler.Sampler.__init__': ('sampler.html#sampler.__init__', 'trufl/sampler.py'),
|
|
77
|
+
'trufl.sampler.Sampler.loc_ids': ('sampler.html#sampler.loc_ids', 'trufl/sampler.py'),
|
|
78
|
+
'trufl.sampler.Sampler.sample': ('sampler.html#sampler.sample', 'trufl/sampler.py')},
|
|
79
|
+
'trufl.utils': { 'trufl.utils.anonymize_raster': ('utils.html#anonymize_raster', 'trufl/utils.py'),
|
|
80
|
+
'trufl.utils.gridder': ('utils.html#gridder', 'trufl/utils.py'),
|
|
81
|
+
'trufl.utils.reproject_raster': ('utils.html#reproject_raster', 'trufl/utils.py')}}}
|
trufl/callbacks.py
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/04_callbacks.ipynb.
|
|
2
|
+
|
|
3
|
+
# %% auto 0
|
|
4
|
+
__all__ = ['Variable', 'Callback', 'State', 'MaxCB', 'MinCB', 'StdCB', 'CountCB', 'MoranICB', 'PriorCB']
|
|
5
|
+
|
|
6
|
+
# %% ../nbs/04_callbacks.ipynb 2
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
|
|
9
|
+
import warnings
|
|
10
|
+
warnings.filterwarnings("ignore", category=UserWarning, message="The weights matrix is not fully connected")
|
|
11
|
+
|
|
12
|
+
# %% ../nbs/04_callbacks.ipynb 3
|
|
13
|
+
from pysal.lib import weights
|
|
14
|
+
from pysal.explore import esda
|
|
15
|
+
import itertools
|
|
16
|
+
import fastcore.all as fc
|
|
17
|
+
from fastcore.basics import patch
|
|
18
|
+
import numpy as np
|
|
19
|
+
from scipy.spatial import KDTree
|
|
20
|
+
import geopandas as gpd
|
|
21
|
+
from typing import List
|
|
22
|
+
from collections.abc import Callable
|
|
23
|
+
import rasterio
|
|
24
|
+
from rasterio.mask import mask
|
|
25
|
+
import pandas as pd
|
|
26
|
+
from typing import Type
|
|
27
|
+
|
|
28
|
+
# %% ../nbs/04_callbacks.ipynb 5
|
|
29
|
+
@dataclass
|
|
30
|
+
class Variable:
|
|
31
|
+
"State variable"
|
|
32
|
+
name: str
|
|
33
|
+
value: float
|
|
34
|
+
|
|
35
|
+
# %% ../nbs/04_callbacks.ipynb 6
|
|
36
|
+
class Callback(): pass
|
|
37
|
+
|
|
38
|
+
# %% ../nbs/04_callbacks.ipynb 8
|
|
39
|
+
class State:
|
|
40
|
+
def __init__(self,
|
|
41
|
+
measurements:gpd.GeoDataFrame, # Measurements data with `loc_id`, `geometry` and `value` columns.
|
|
42
|
+
smp_areas:gpd.GeoDataFrame, # Grid of areas/polygons of interest with `loc_id` and `geometry`.
|
|
43
|
+
cbs:List[Callable], # List of Callback functions returning `Variable`s.
|
|
44
|
+
):
|
|
45
|
+
"Collect various variables/metrics per grid cell/administrative unit."
|
|
46
|
+
fc.store_attr()
|
|
47
|
+
self.unsampled_locs = self.smp_areas.index.difference(self.measurements.index)
|
|
48
|
+
|
|
49
|
+
# %% ../nbs/04_callbacks.ipynb 9
|
|
50
|
+
@patch
|
|
51
|
+
def get(self:State,
|
|
52
|
+
loc_id:str, # Unique id of the Point feature
|
|
53
|
+
as_numpy=False # Whether or not to return a list of `Variable` or a tuple of numpy arrays.
|
|
54
|
+
):
|
|
55
|
+
"Get the state variables as defined by `cbs` for a given location (`loc_id`)."
|
|
56
|
+
variables = self.run_cbs(loc_id)
|
|
57
|
+
if as_numpy:
|
|
58
|
+
return (np.array([v.name for v in variables]),
|
|
59
|
+
np.array([v.value for v in variables]))
|
|
60
|
+
else:
|
|
61
|
+
return variables
|
|
62
|
+
|
|
63
|
+
# %% ../nbs/04_callbacks.ipynb 10
|
|
64
|
+
@patch
|
|
65
|
+
def __call__(self:State, loc_id=None, **kwargs):
|
|
66
|
+
"Get the state variables as defined by `cbs` for all `loc_id`s as a dataframe."
|
|
67
|
+
loc_ids = self.smp_areas.index
|
|
68
|
+
results = [{v.name: v.value for v in self.run_cbs(loc_id)} | {'loc_id': loc_id} for loc_id in loc_ids]
|
|
69
|
+
return pd.DataFrame(results).set_index('loc_id')
|
|
70
|
+
|
|
71
|
+
# %% ../nbs/04_callbacks.ipynb 11
|
|
72
|
+
@patch
|
|
73
|
+
def expand_to_k_nearest(self:State,
|
|
74
|
+
subset_measurements:gpd.GeoDataFrame, # Measurements for which Variables are computed.
|
|
75
|
+
k:int=5, # Number of nearest neighbours (possibly belonging to adjacent cells/admin. units to consider).
|
|
76
|
+
):
|
|
77
|
+
"Expand measurements of concern possibly to nearest neighbors of surrounding grid cells."
|
|
78
|
+
tree = KDTree(self.measurements.geometry.apply(lambda p: (p.x, p.y)).tolist());
|
|
79
|
+
_, indices = tree.query(subset_measurements.geometry.apply(lambda p: (p.x, p.y)).tolist(), k=k)
|
|
80
|
+
return self.measurements.iloc[indices.flatten()].reset_index(drop=True)
|
|
81
|
+
|
|
82
|
+
# %% ../nbs/04_callbacks.ipynb 12
|
|
83
|
+
@patch
|
|
84
|
+
def _flatten(self:State, variables):
|
|
85
|
+
"Flatten list of variables potentially containing both scalar and tuples."
|
|
86
|
+
return list(itertools.chain(*(v if isinstance(v, tuple) else (v,)
|
|
87
|
+
for v in variables)))
|
|
88
|
+
|
|
89
|
+
# %% ../nbs/04_callbacks.ipynb 13
|
|
90
|
+
@patch
|
|
91
|
+
def run_cbs(self:State, loc_id):
|
|
92
|
+
"Run Callbacks sequentially and flatten the results if required."
|
|
93
|
+
variables = []
|
|
94
|
+
for cb in self.cbs:
|
|
95
|
+
variables.append(cb(loc_id, self))
|
|
96
|
+
return self._flatten(variables)
|
|
97
|
+
|
|
98
|
+
# %% ../nbs/04_callbacks.ipynb 15
|
|
99
|
+
class MaxCB(Callback):
|
|
100
|
+
"Compute Maximum value of measurements at given location."
|
|
101
|
+
def __init__(self, name='Max'): fc.store_attr()
|
|
102
|
+
def __call__(self,
|
|
103
|
+
loc_id:int, # Unique id of an individual area of interest.
|
|
104
|
+
o:Type[State] # A State's object
|
|
105
|
+
):
|
|
106
|
+
if loc_id in o.unsampled_locs: return Variable(self.name, np.nan)
|
|
107
|
+
return Variable(self.name,
|
|
108
|
+
np.max(o.measurements.loc[[loc_id]].value.values))
|
|
109
|
+
|
|
110
|
+
# %% ../nbs/04_callbacks.ipynb 16
|
|
111
|
+
class MinCB(Callback):
|
|
112
|
+
"Compute Minimum value of measurements at given location."
|
|
113
|
+
def __init__(self, name='Min'): fc.store_attr()
|
|
114
|
+
def __call__(self,
|
|
115
|
+
loc_id:int, # Unique id of an individual area of interest.
|
|
116
|
+
o:Type[State] # A State's object
|
|
117
|
+
):
|
|
118
|
+
if loc_id in o.unsampled_locs: return Variable(self.name, np.nan)
|
|
119
|
+
return Variable(self.name,
|
|
120
|
+
np.min(o.measurements.loc[[loc_id]].value.values))
|
|
121
|
+
|
|
122
|
+
# %% ../nbs/04_callbacks.ipynb 17
|
|
123
|
+
class StdCB(Callback):
|
|
124
|
+
"Compute Standard deviation of measurements at given location."
|
|
125
|
+
def __init__(self, name='Standard Deviation'): fc.store_attr()
|
|
126
|
+
def __call__(self,
|
|
127
|
+
loc_id:int, # Unique id of an individual area of interest.
|
|
128
|
+
o:Type[State] # A State's object
|
|
129
|
+
):
|
|
130
|
+
if loc_id in o.unsampled_locs: return Variable(self.name, np.nan)
|
|
131
|
+
return Variable(self.name,
|
|
132
|
+
np.std(o.measurements.loc[[loc_id]].value.values))
|
|
133
|
+
|
|
134
|
+
# %% ../nbs/04_callbacks.ipynb 18
|
|
135
|
+
class CountCB(Callback):
|
|
136
|
+
"Compute the number of measurements at given location."
|
|
137
|
+
def __init__(self, name='Count'): fc.store_attr()
|
|
138
|
+
def __call__(self,
|
|
139
|
+
loc_id:int, # Unique id of an individual area of interest.
|
|
140
|
+
o:Type[State] # A State's object
|
|
141
|
+
):
|
|
142
|
+
if loc_id in o.unsampled_locs: return Variable(self.name, np.nan)
|
|
143
|
+
return Variable(self.name,
|
|
144
|
+
len(o.measurements.loc[[loc_id]].value.values))
|
|
145
|
+
|
|
146
|
+
# %% ../nbs/04_callbacks.ipynb 19
|
|
147
|
+
class MoranICB(Callback):
|
|
148
|
+
"Compute Moran.I of measurements at given location. Return NaN if p_sim above threshold."
|
|
149
|
+
def __init__(self, k=5, p_threshold=0.05, name='Moran.I', min_n=5): fc.store_attr()
|
|
150
|
+
|
|
151
|
+
def _weights(self, measurements):
|
|
152
|
+
w = weights.KNN.from_dataframe(measurements, k=self.k)
|
|
153
|
+
w.transform = "R" # Row-standardization
|
|
154
|
+
return w
|
|
155
|
+
|
|
156
|
+
def __call__(self,
|
|
157
|
+
loc_id:int, # Unique id of an individual area of interest.
|
|
158
|
+
o:Type[State] # A State's object
|
|
159
|
+
):
|
|
160
|
+
if loc_id in o.unsampled_locs: return Variable(self.name, np.nan)
|
|
161
|
+
subset = o.measurements.loc[[loc_id]]
|
|
162
|
+
if len(subset) <= self.min_n: return Variable(self.name, np.nan)
|
|
163
|
+
expanded_measurements = o.expand_to_k_nearest(subset, k=self.k)
|
|
164
|
+
moran = esda.moran.Moran(expanded_measurements['value'], self._weights(expanded_measurements))
|
|
165
|
+
return Variable(self.name, moran.I if moran.p_sim < self.p_threshold else np.nan)
|
|
166
|
+
|
|
167
|
+
# %% ../nbs/04_callbacks.ipynb 20
|
|
168
|
+
class PriorCB(Callback):
|
|
169
|
+
"Emulate a prior by taking the mean of measurement over a single grid cell."
|
|
170
|
+
def __init__(self,
|
|
171
|
+
fname_raster:str, # Name of raster file
|
|
172
|
+
name:str='Prior' # Name of the State variable
|
|
173
|
+
):
|
|
174
|
+
fc.store_attr()
|
|
175
|
+
|
|
176
|
+
def __call__(self,
|
|
177
|
+
loc_id:int, # Unique id of an individual area of interest.
|
|
178
|
+
o:Type[State] # A State's object
|
|
179
|
+
):
|
|
180
|
+
polygon = o.smp_areas.loc[o.smp_areas.reset_index().loc_id == loc_id].geometry
|
|
181
|
+
with rasterio.open(self.fname_raster) as src:
|
|
182
|
+
out_image, out_transform = mask(src, polygon, crop=True)
|
|
183
|
+
mean_value = np.mean(out_image)
|
|
184
|
+
return Variable(self.name, mean_value)
|
trufl/collector.py
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/06_collector.ipynb.
|
|
2
|
+
|
|
3
|
+
# %% auto 0
|
|
4
|
+
__all__ = ['DataCollector']
|
|
5
|
+
|
|
6
|
+
# %% ../nbs/06_collector.ipynb 3
|
|
7
|
+
import rasterio
|
|
8
|
+
import fastcore.all as fc
|
|
9
|
+
import geopandas as gpd
|
|
10
|
+
from rasterio import transform
|
|
11
|
+
|
|
12
|
+
# %% ../nbs/06_collector.ipynb 5
|
|
13
|
+
class DataCollector:
|
|
14
|
+
def __init__(self,
|
|
15
|
+
fname_raster:str, # The path to the raster file.
|
|
16
|
+
band:int=1, # The band number to use. Defaults to 1.
|
|
17
|
+
):
|
|
18
|
+
"Emulate data collection. Provided a set of location, return values sampled from given raster file."
|
|
19
|
+
fc.store_attr()
|
|
20
|
+
with rasterio.open(fname_raster) as src:
|
|
21
|
+
self.band_data = src.read(band)
|
|
22
|
+
self.affine = src.transform
|
|
23
|
+
self.bounds = src.bounds
|
|
24
|
+
|
|
25
|
+
def get_values(self,
|
|
26
|
+
gdf:gpd.GeoDataFrame # loc_id and Point/Multipoint geometry of samples where to measure.
|
|
27
|
+
):
|
|
28
|
+
coords = [(x, y) for x, y in gdf.get_coordinates().values]
|
|
29
|
+
pixel_coords = [transform.rowcol(self.affine, *pair) for pair in coords]
|
|
30
|
+
return [self.band_data[int(x), int(y)] for (x, y) in pixel_coords]
|
|
31
|
+
|
|
32
|
+
def collect(self,
|
|
33
|
+
gdf:gpd.GeoDataFrame # loc_id and Point/Multipoint geometry of samples where to measure.
|
|
34
|
+
) -> gpd.GeoDataFrame:
|
|
35
|
+
return gdf.explode(index_parts=False).assign(value=self.get_values(gdf))
|