|
6 | 6 | from glob import glob
|
7 | 7 |
|
8 | 8 | from numba import njit
|
9 |
| -from numpy import arange, array, bincount, empty, uint32, unique |
| 9 | +from numpy import arange, array, bincount, empty, ones, uint32, unique |
10 | 10 |
|
11 | 11 | from ..poly import bbox_intersection, vertice_overlap
|
12 | 12 | from .observation import EddiesObservations
|
@@ -58,6 +58,97 @@ def load_contour(self, filename):
|
58 | 58 | return self.DATA[filename]
|
59 | 59 |
|
60 | 60 |
|
| 61 | +class NetworkObservations(EddiesObservations): |
| 62 | + |
| 63 | + __slots__ = tuple() |
| 64 | + |
| 65 | + NOGROUP = 0 |
| 66 | + |
| 67 | + @property |
| 68 | + def elements(self): |
| 69 | + elements = super().elements |
| 70 | + elements.extend(["track", "segment", "next_obs", "previous_obs"]) |
| 71 | + return list(set(elements)) |
| 72 | + |
| 73 | + @classmethod |
| 74 | + def from_split_network(cls, group_dataset, indexs, **kwargs): |
| 75 | + """ |
| 76 | + Build a NetworkObservations object with Group dataset and indexs |
| 77 | +
|
| 78 | + :param TrackEddiesObservations group_dataset: Group dataset |
| 79 | + :param indexs: result from split_network |
| 80 | + return NetworkObservations |
| 81 | + """ |
| 82 | + index_order = indexs.argsort(order=("group", "track", "time")) |
| 83 | + network = cls.new_like(group_dataset, len(group_dataset), **kwargs) |
| 84 | + network.sign_type = group_dataset.sign_type |
| 85 | + for field in group_dataset.elements: |
| 86 | + if field not in network.elements: |
| 87 | + continue |
| 88 | + network[field][:] = group_dataset[field][index_order] |
| 89 | + network.segment[:] = indexs["track"][index_order] |
| 90 | + # n & p must be re-index |
| 91 | + n, p = indexs["next_obs"][index_order], indexs["previous_obs"][index_order] |
| 92 | + translate = empty(index_order.max() + 1, dtype="i4") |
| 93 | + translate[index_order] = arange(index_order.shape[0]) |
| 94 | + m = n != -1 |
| 95 | + n[m] = translate[n[m]] |
| 96 | + m = p != -1 |
| 97 | + p[m] = translate[p[m]] |
| 98 | + network.next_obs[:] = n |
| 99 | + network.previous_obs[:] = p |
| 100 | + return network |
| 101 | + |
| 102 | + def relative(self, i_obs, order=2, direct=True, only_past=False, only_future=False): |
| 103 | + pass |
| 104 | + |
| 105 | + def only_one_network(self): |
| 106 | + """ |
| 107 | + Raise a warning or error? |
| 108 | + if there are more than one network |
| 109 | + """ |
| 110 | + # TODO |
| 111 | + pass |
| 112 | + |
| 113 | + def display_timeline(self, ax, event=False): |
| 114 | + """ |
| 115 | + Must be call on only one network |
| 116 | + """ |
| 117 | + self.only_one_network() |
| 118 | + j = 0 |
| 119 | + line_kw = dict( |
| 120 | + ls="-", |
| 121 | + marker=".", |
| 122 | + markersize=6, |
| 123 | + zorder=1, |
| 124 | + lw=3, |
| 125 | + ) |
| 126 | + for i, b0, b1 in self.iter_on("segment"): |
| 127 | + x = self.time[i] |
| 128 | + if x.shape[0] == 0: |
| 129 | + continue |
| 130 | + y = b0 * ones(x.shape) |
| 131 | + line = ax.plot(x, y, **line_kw, color=self.COLORS[j % self.NB_COLORS])[0] |
| 132 | + if event: |
| 133 | + event_kw = dict(color=line.get_color(), ls="-", zorder=1) |
| 134 | + i_n, i_p = ( |
| 135 | + self.next_obs[i.stop - 1], |
| 136 | + self.previous_obs[i.start], |
| 137 | + ) |
| 138 | + if i_n != -1: |
| 139 | + ax.plot( |
| 140 | + (x[-1], self.time[i_n]), (b0, self.segment[i_n]), **event_kw |
| 141 | + ) |
| 142 | + ax.plot(x[-1], b0, color="k", marker=">", markersize=10, zorder=-1) |
| 143 | + if i_p != -1: |
| 144 | + ax.plot((x[0], self.time[i_p]), (b0, self.segment[i_p]), **event_kw) |
| 145 | + ax.plot(x[0], b0, color="k", marker="*", markersize=12, zorder=-1) |
| 146 | + j += 1 |
| 147 | + |
| 148 | + def insert_virtual(self): |
| 149 | + pass |
| 150 | + |
| 151 | + |
61 | 152 | class Network:
|
62 | 153 | __slots__ = (
|
63 | 154 | "window",
|
|
0 commit comments