Skip to content

Commit e6c6fcf

Browse files
author
adelepoulle
committed
Improvement of cost_function
1 parent 9ca9758 commit e6c6fcf

File tree

5 files changed

+79
-21
lines changed

5 files changed

+79
-21
lines changed

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
'matplotlib==1.4.3',
3636
'scipy>=0.15.1',
3737
'netCDF4>=1.1.0',
38+
'shapely',
3839
'pyyaml',
3940
'pyproj',
4041
],

src/py_eddy_tracker/__init__.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,8 +243,10 @@ def parse_args(self, *args, **kwargs):
243243
description='observation sequence number (XX day intervals)',
244244
)
245245
),
246-
contour_lon_e=dict(
246+
# contour_lon_e=dict(
247+
contour_lon=dict(
247248
attr_name=None,
249+
# nc_name='contour_lon_e',
248250
nc_name='contour_lon',
249251
nc_type='f4',
250252
output_type='i2',
@@ -256,8 +258,10 @@ def parse_args(self, *args, **kwargs):
256258
description='lons of contour points',
257259
)
258260
),
259-
contour_lat_e=dict(
261+
# contour_lat_e=dict(
262+
contour_lat=dict(
260263
attr_name=None,
264+
# nc_name='contour_lat_e',
261265
nc_name='contour_lat',
262266
nc_type='f4',
263267
output_type='i2',

src/py_eddy_tracker/observations.py

Lines changed: 64 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,11 @@
2929
3030
"""
3131
from numpy import zeros, empty, nan, arange, interp, where, unique, \
32-
ma
32+
ma, concatenate
3333
from netCDF4 import Dataset
3434
from py_eddy_tracker.tools import distance_matrix
35+
from shapely.geometry import Polygon
36+
from shapely.geos import TopologicalError
3537
from . import VAR_DESCR, VAR_DESCR_inv
3638
import logging
3739

@@ -66,6 +68,16 @@ class EddiesObservations(object):
6668
rtime:
6769
Time
6870
"""
71+
72+
ELEMENTS = [
73+
'lon', # 'centlon'
74+
'lat', # 'centlat'
75+
'radius_s', # 'eddy_radius_s'
76+
'radius_e', # 'eddy_radius_e'
77+
'amplitude', # 'amplitude'
78+
'speed_radius', # 'uavg'
79+
'eke', # 'teke'
80+
'time'] # 'rtime'
6981

7082
def __init__(self, size=0, track_extra_variables=None,
7183
track_array_variables=0, array_variables=None):
@@ -108,15 +120,7 @@ def dtype(self):
108120
def elements(self):
109121
"""Return all variable name
110122
"""
111-
elements = [
112-
'lon', # 'centlon'
113-
'lat', # 'centlat'
114-
'radius_s', # 'eddy_radius_s'
115-
'radius_e', # 'eddy_radius_e'
116-
'amplitude', # 'amplitude'
117-
'speed_radius', # 'uavg'
118-
'eke', # 'teke'
119-
'time'] # 'rtime'
123+
elements = [i for i in self.ELEMENTS]
120124
if self.track_array_variables > 0:
121125
elements += self.array_variables
122126

@@ -226,6 +230,13 @@ def load_from_netcdf(filename):
226230
for variable in h_nc.variables:
227231
if array_dim in h_nc.variables[variable].dimensions:
228232
kwargs['array_variables'].append(str(variable))
233+
kwargs['track_extra_variables'] = []
234+
for variable in h_nc.variables:
235+
if variable == 'cyc':
236+
continue
237+
var_inv = VAR_DESCR_inv[variable]
238+
if var_inv not in EddiesObservations.ELEMENTS and var_inv not in kwargs['array_variables']:
239+
kwargs['track_extra_variables'].append(var_inv)
229240

230241
eddies = EddiesObservations(size=nb_obs, ** kwargs)
231242
for variable in h_nc.variables:
@@ -236,35 +247,62 @@ def load_from_netcdf(filename):
236247
eddies.sign_type = h_nc.variables['cyc'][0]
237248
return eddies
238249

239-
def cost_function(self, records_in, records_out):
250+
def cost_function2(self, records_in, records_out, distance):
251+
nb_records = records_in.shape[0]
252+
costs = ma.empty(nb_records,dtype='f4')
253+
for i_record in xrange(nb_records):
254+
poly_in = Polygon(
255+
concatenate((
256+
(records_in[i_record]['contour_lon'],),
257+
(records_in[i_record]['contour_lat'],))
258+
).T
259+
)
260+
poly_out = Polygon(
261+
concatenate((
262+
(records_out[i_record]['contour_lon'],),
263+
(records_out[i_record]['contour_lat'],))
264+
).T
265+
)
266+
try:
267+
costs[i_record] = 1 - poly_in.intersection(poly_out).area / poly_in.area
268+
except TopologicalError:
269+
costs[i_record] = 1
270+
costs.mask = costs == 1
271+
return costs
272+
273+
def cost_function(self, records_in, records_out, distance):
240274
cost = ((records_in['amplitude'] - records_out['amplitude']
241275
) / records_in['amplitude']
242276
) ** 2
243277
cost += ((records_in['radius_s'] - records_out['radius_s']
244278
) / records_in['radius_s']
245279
) ** 2
246-
return cost ** 0.5
280+
cost += (distance / 125) ** 2
281+
cost **= 0.5
282+
# Mask value superior at 60 % of variation
283+
return ma.array(cost, mask=cost > 0.6)
247284

248285
def tracking(self, other):
249286
"""Track obs between self and other
250287
"""
251288
dist = self.distance(other)
252289
# Links available which are close (circle area selection)
253-
mask_accept_dist = dist < 100
290+
mask_accept_dist = dist < 125
254291
indexs_closest = where(mask_accept_dist)
255-
cost_values = self.cost_function(
292+
cost_values = self.cost_function2(
256293
self.obs[indexs_closest[0]],
257-
other.obs[indexs_closest[1]])
294+
other.obs[indexs_closest[1]],
295+
dist[mask_accept_dist])
258296

259297
cost_mat = ma.empty(dist.shape, dtype='f4')
260298
cost_mat.mask = -mask_accept_dist
261299
cost_mat[mask_accept_dist] = cost_values
262300
# Links available which respect a maximal cost
263-
cost = dist
264-
mask_accept_cost = cost < 100
265-
cost = ma.array(cost, mask=-mask_accept_cost, dtype='i2')
301+
# cost = dist
302+
# mask_accept_cost = cost < 100
303+
# cost = ma.array(cost, mask=-mask_accept_cost, dtype='i2')
266304

267-
mask_accept_cost = mask_accept_dist
305+
mask_accept_cost = -cost_mat.mask
268306
cost = cost_mat
269307
# Count number of link by self obs and other obs
270308
self_links = mask_accept_cost.sum(axis=1)
@@ -297,7 +335,13 @@ def tracking(self, other):
297335
matrix_size)
298336

299337
links_resolve = 0
338+
# Arbitrary value
339+
max_iteration = max(cost_reduce.shape)
340+
security_increment = 0
300341
while False in cost_reduce.mask:
342+
if security_increment > max_iteration:
343+
raise Exception('To many iteration: %d' % security_increment)
344+
security_increment += 1
301345
i_min_value = cost_reduce.argmin()
302346
i, j = i_min_value / shape[1], i_min_value % shape[1]
303347
# Set to False all link
@@ -361,6 +405,7 @@ def extract_longer_eddies(self, nb_min, nb_obs, compress_id=True):
361405
logging.info('Selection of %d observations', nb_obs_select)
362406
eddies = TrackEddiesObservations(
363407
size=nb_obs_select,
408+
track_extra_variables=self.track_extra_variables,
364409
track_array_variables=self.track_array_variables,
365410
array_variables=self.array_variables
366411
)

src/py_eddy_tracker/tracking.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,11 @@ def recense_dead_id_to_extend(self):
220220
if nb_virtual_extend > 0:
221221
obs_to_extend = self.previous_virtual_obs.obs[i_virtual_dead_id
222222
][alive_virtual_obs]
223+
for key in obs_b.dtype.fields.keys():
224+
if key in ['lon', 'lat', 'time', 'track', 'segment_size',
225+
'dlon', 'dlat'] or 'contour_' in key:
226+
continue
227+
self.virtual_obs[key][nb_dead:] = obs_to_extend[key]
223228
self.virtual_obs['lon'][nb_dead:
224229
] = obs_to_extend['lon'] + obs_to_extend['dlon']
225230
self.virtual_obs['lat'][nb_dead:
@@ -293,6 +298,7 @@ def merge(self):
293298
# Start create netcdf to agglomerate all eddy
294299
eddies = TrackEddiesObservations(
295300
size=self.nb_obs,
301+
track_extra_variables=self.current_obs.track_extra_variables,
296302
track_array_variables=self.current_obs.track_array_variables,
297303
array_variables=self.current_obs.array_variables,
298304
)

src/scripts/EddyIdentification

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#!/usr/bin/env python
22
# -*- coding: utf-8 -*-
3+
#import matplotlib
4+
#matplotlib.use('wx')
35
"""
46
===============================================================================
57
This file is part of py-eddy-tracker.

0 commit comments

Comments
 (0)