"""Operator to aggregate analytical features and create raster and render image"""
from __future__ import annotations
from typing import Union
import math
import tracklib.core.Utils as utils
from tracklib.core.Raster import Raster
from tracklib.core.RasterBand import RasterBand
from tracklib.core.RasterBand import NO_DATA_VALUE
from tracklib.core.TrackCollection import TrackCollection
[docs]def getMeasureName(af_algo:Union[int, str], aggregate=None):
"""
Return the identifier of the measure defined by: af + aggregate operator
"""
if af_algo != "uid":
if isinstance(af_algo, str):
cle = af_algo + "#" + aggregate.__name__
else:
cle = af_algo.__name__ + "#" + aggregate.__name__
else:
cle = "uid" + "#" + aggregate.__name__
return cle
[docs]def summarize(collection: TrackCollection, af_algos, aggregates,
resolution=None, margin:float=0.05, verbose:bool=True):
"""
Example:
af_algos = [algo.speed, algo.speed]
cell_operators = [celloperator.co_avg, celloperator.co_max]
"""
af_algos = utils.listify(af_algos)
aggregates = utils.listify(aggregates)
if len(af_algos) == 0:
print("Error: af_algos is empty")
return 0
if len(af_algos) != len(aggregates):
print("Error: af_names and aggregates must have the same number elements")
return 0
# Pour chaque algo-agg on crée une grille
grilles = []
for idx, af_algo in enumerate(af_algos):
aggregate = aggregates[idx]
# if isinstance(af_algo, str):
# name = af_algo
# else:
# name = af_algo.__name__
# cle = name + "#" + aggregate.__name__
cle = getMeasureName(af_algo, aggregate)
#print (cle)
grille = RasterBand(collection.bbox(), resolution, margin, name = cle)
#print (grille.name)
# ---------------------------------------------------------------------
# On ajoute les valeurs des af dans les cellules
CUBE = []
for i in range(grille.nrow):
CUBE.append([])
for j in range(grille.ncol):
CUBE[i].append([])
# On dispatch les valeurs de l'AF dans les cellules.
# Avant on vérifie si l'AF existe, sinon on la calcule.
for trace in collection.getTracks():
if not isinstance(af_algo, str):
# On calcule l'AF si ce n'est pas fait
trace.addAnalyticalFeature(af_algo)
# On eparpille dans les cellules
for i in range(trace.size()):
obs = trace.getObs(i)
(idx, idy) = grille.getCell(obs.position)
# print (obs.position, idx, idy)
# Cas des bordures
if idx == grille.ncol:
column = math.floor(idx) - 1
else:
column = math.floor(idx)
if idy.is_integer() and int(idy) > -1:
line = int(idy)
elif idy.is_integer() and int(idy) == -1:
line = int(idy) + 1
else:
line = math.floor(idy) + 1 # il faut arrondir par le dessus!
# print (' ', obs.position, column, line)
if (
0 <= column
and column <= grille.ncol
and 0 <= line
and line <= grille.nrow
):
if not isinstance(af_algo, str):
val = trace.getObsAnalyticalFeature(af_algo.__name__, i)
elif af_algo != "uid":
val = trace.getObsAnalyticalFeature(af_algo, i)
else:
val = trace.uid
# val = int(startpixel + (255 - startpixel) * (valmax - val) / valmax)
CUBE[line][column].append(val)
# print (CUBE[0][0])
# ---------------------------------------------------------------------
# On calcule les agregats
# print (aggregates[0].__name__)
for i in range(grille.nrow):
for j in range(grille.ncol):
#ii = grille.nrow - 1 - i
tarray = CUBE[i][j]
sumval = aggregate(tarray)
# print (sumval)
if utils.isnan(sumval):
grille.grid[i][j] = NO_DATA_VALUE
# # elif valmax != None and val > valmax:
else:
grille.grid[i][j] = sumval
# ---------------------------------------------------------------------
# On ajoute la grille au tableau de grilles
# print (grille.grid)
grilles.append(grille)
raster = Raster(grilles)
return raster
#return None
[docs]def co_sum(tarray):
"""TODO"""
tarray = utils.listify(tarray)
somme = 0
for i in range(len(tarray)):
val = tarray[i]
if utils.isnan(val):
continue
somme += val
return somme
[docs]def co_min(tarray):
"""TODO"""
tarray = utils.listify(tarray)
if len(tarray) <= 0:
return utils.NAN
min = tarray[0]
for i in range(1, len(tarray)):
val = tarray[i]
if utils.isnan(val):
continue
if val < min:
min = val
return min
[docs]def co_max(tarray):
"""TODO"""
tarray = utils.listify(tarray)
if len(tarray) <= 0:
return utils.NAN
max = tarray[0]
for i in range(1, len(tarray)):
val = tarray[i]
if utils.isnan(val):
continue
if val > max:
max = val
return max
[docs]def co_count(tarray):
"""TODO"""
tarray = utils.listify(tarray)
count = 0
for i in range(len(tarray)):
val = tarray[i]
if utils.isnan(val):
continue
count += 1
return count
[docs]def co_avg(tarray):
"""TODO"""
tarray = utils.listify(tarray)
if len(tarray) <= 0:
return utils.NAN
mean = 0
count = 0
for i in range(len(tarray)):
val = tarray[i]
if utils.isnan(val):
continue
count += 1
mean += val
if count == 0:
return utils.NAN
return mean / count
[docs]def co_dominant(tarray):
"""TODO"""
tarray = utils.listify(tarray)
if len(tarray) <= 0:
return utils.NAN
# Dico : clé - nb occurence
cles_count_dictionnary = {}
# On alimente le dictionnaire
for val in tarray:
if val not in cles_count_dictionnary:
cles_count_dictionnary[val] = 1
else:
cles_count_dictionnary[val] += 1
# On cherche le plus fréquent i.e. celui qui a le max d'occurence
nbocc = 0
dominant_value = ""
for val in cles_count_dictionnary:
if cles_count_dictionnary[val] > nbocc:
nbocc = cles_count_dictionnary[val]
dominant_value = val
return dominant_value