ticoi 0.0.1__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.

Potentially problematic release.


This version of ticoi might be problematic. Click here for more details.

ticoi/mjd2date.py ADDED
@@ -0,0 +1,31 @@
1
+ # From Jeremie Mouginot
2
+
3
+ import jdcal
4
+ import numpy as np
5
+
6
+ # make jdcal external library data-type friendly (-datatime- and -integer- instead tuples)
7
+
8
+
9
+ def mjd2date(date):
10
+ """
11
+ Convert the dates from Modified Julian Date to Gregorian Date
12
+ Modified Julian Date MJD = JD-2400001.5 , 17 November 1858=0.
13
+ :param date: Modified Julian Date, integer
14
+ :return: Gregoryan date, datatime type
15
+ """
16
+
17
+ t = jdcal.jd2gcal(2400000.5, date)
18
+ return np.datetime64(f"{t[0]}-{f'{t[1]:02}'}-{f'{t[2]:02}'}")
19
+
20
+
21
+ def date2mjd(date):
22
+ """Convert from Gregorian Date to Modified Julian Date.
23
+ :param date: Gregorian Date, datatime type
24
+ :return: Modified Julian Date, integer"""
25
+
26
+ try:
27
+ JD = jdcal.gcal2jd(date.year, date.month, date.day)
28
+ except:
29
+ date = date.astype("M8[D]").astype("O")
30
+ JD = jdcal.gcal2jd(date.year, date.month, date.day)
31
+ return int(JD[1])
@@ -0,0 +1,264 @@
1
+ import asyncio
2
+ import itertools
3
+
4
+ import matplotlib.pyplot as plt
5
+ import numpy as np
6
+ from joblib import Parallel, delayed
7
+ from tqdm import tqdm
8
+
9
+ from ticoi.core import chunk_to_block, load_block
10
+ from ticoi.utils import optimize_coef
11
+
12
+
13
+ async def process_block(
14
+ cube,
15
+ block,
16
+ cube_gt,
17
+ load_pixel_kwargs,
18
+ inversion_kwargs,
19
+ interpolation_kwargs,
20
+ optimization_method="stable_ground",
21
+ regu=None,
22
+ flag=None,
23
+ cmin=10,
24
+ cmax=1000,
25
+ step=10,
26
+ coefs=None,
27
+ nb_cpu=8,
28
+ preData_kwargs=None,
29
+ ):
30
+ """Optimize the coef on a given block"""
31
+
32
+ if optimization_method == "stable_ground": # We only compute stable ground pixels
33
+ xy_values = list(
34
+ filter(
35
+ bool,
36
+ [
37
+ (x, y) if flag.sel(x=x, y=y)["flag"].values == 0 else False
38
+ for x in flag["x"].values
39
+ for y in flag["y"].values
40
+ ],
41
+ )
42
+ )
43
+ else:
44
+ xy_values = list(itertools.product(cube.ds["x"].values, cube.ds["y"].values))
45
+
46
+ # Progression bar
47
+ xy_values_tqdm = tqdm(xy_values, total=len(xy_values))
48
+
49
+ # Filter cube
50
+ obs_filt, flag_block = block.filter_cube_before_inversion(**preData_kwargs, flag=flag)
51
+
52
+ # Optimization of the coefficient for every pixels of the block
53
+ # (faster using parallelization here and sequential processing in optimize_coef)
54
+ result_block = Parallel(n_jobs=nb_cpu, verbose=0)(
55
+ delayed(optimize_coef)(
56
+ block,
57
+ cube_gt,
58
+ i,
59
+ j,
60
+ obs_filt,
61
+ load_pixel_kwargs,
62
+ inversion_kwargs,
63
+ interpolation_kwargs,
64
+ method=optimization_method,
65
+ regu=regu,
66
+ flag=flag_block,
67
+ cmin=cmin,
68
+ cmax=cmax,
69
+ step=step,
70
+ coefs=coefs,
71
+ stats=True,
72
+ parallel=False,
73
+ visual=False,
74
+ )
75
+ for i, j in xy_values_tqdm
76
+ )
77
+
78
+ return result_block
79
+
80
+
81
+ async def process_blocks_main(
82
+ cube,
83
+ cube_gt,
84
+ load_pixel_kwargs,
85
+ inversion_kwargs,
86
+ preData_kwargs,
87
+ interpolation_kwargs,
88
+ optimization_method="stable_ground",
89
+ regu=None,
90
+ flag=None,
91
+ cmin=10,
92
+ cmax=1000,
93
+ step=10,
94
+ coefs=None,
95
+ nb_cpu=8,
96
+ block_size=0.5,
97
+ verbose=False,
98
+ ):
99
+ """Main function for the optimization of the coef using a block processing approach"""
100
+
101
+ blocks = chunk_to_block(cube, block_size=block_size, verbose=True)
102
+
103
+ dataf_list = [None] * (cube.nx * cube.ny)
104
+
105
+ loop = asyncio.get_event_loop()
106
+
107
+ for n in range(len(blocks)):
108
+ print(f"Processing block {n + 1}/{len(blocks)}")
109
+
110
+ # Load the first block and start the loop
111
+ if n == 0:
112
+ x_start, x_end, y_start, y_end = blocks[0]
113
+ future = loop.run_in_executor(None, load_block, cube, x_start, x_end, y_start, y_end)
114
+
115
+ block, block_flag, duration = await future
116
+ if verbose:
117
+ print(f"Block {n + 1} loaded in {duration:.2f} s")
118
+
119
+ if n < len(blocks) - 1:
120
+ # Load the next block while processing the current block
121
+ x_start, x_end, y_start, y_end = blocks[n + 1]
122
+ future = loop.run_in_executor(None, load_block, cube, x_start, x_end, y_start, y_end)
123
+
124
+ block_result = await process_block(
125
+ cube,
126
+ block,
127
+ cube_gt,
128
+ load_pixel_kwargs,
129
+ inversion_kwargs,
130
+ interpolation_kwargs,
131
+ optimization_method=optimization_method,
132
+ regu=regu,
133
+ flag=flag,
134
+ cmin=cmin,
135
+ cmax=cmax,
136
+ step=step,
137
+ coefs=coefs,
138
+ nb_cpu=nb_cpu,
139
+ preData_kwargs=preData_kwargs,
140
+ )
141
+
142
+ for i in range(len(block_result)):
143
+ row = i % block.ny + blocks[n][2]
144
+ col = np.floor(i / block.ny) + blocks[n][0]
145
+ idx = int(col * cube.ny + row)
146
+
147
+ dataf_list[idx] = block_result[i]
148
+
149
+ del block_result, block
150
+
151
+ return dataf_list
152
+
153
+
154
+ def find_good_coefs(
155
+ coefs,
156
+ measures,
157
+ method="stable_ground",
158
+ select_method="min-max relative",
159
+ thresh=None,
160
+ mean_disp=None,
161
+ mean_angle=None,
162
+ visual=False,
163
+ ):
164
+ if select_method == "curvature":
165
+ smooth_measures = [
166
+ measures[i - 1] / 4 + measures[i] / 2 + measures[i - 1] / 4 for i in range(1, len(measures) - 1)
167
+ ]
168
+ accel = np.array(
169
+ [
170
+ (smooth_measures[i + 1] - 2 * smooth_measures[i] + smooth_measures[i - 1])
171
+ / ((coefs[i + 2] - coefs[i]) / 2) ** 2
172
+ for i in range(1, len(coefs) - 3)
173
+ ]
174
+ )
175
+
176
+ if visual:
177
+ plt.plot(coefs[2:-2], accel)
178
+ plt.ylim([-2 * 10**-6, 0.5 * 10**-6])
179
+ plt.show()
180
+
181
+ if method in ["ground_truth", "stable_ground"]:
182
+ best_coef = coefs[np.argmin(measures)]
183
+ best_measure = np.min(measures)
184
+ good_measure = measures[np.argmin(accel) + 2]
185
+ good_coefs = coefs[measures < good_measure]
186
+ elif method == "vvc":
187
+ best_coef = coefs[np.argmax(measures)]
188
+ best_measure = np.max(measures)
189
+ good_measure = measures[np.argmax(accel) + 2]
190
+ good_coefs = coefs[measures > good_measure]
191
+
192
+ elif select_method == "min-max relative":
193
+ if method in ["ground_truth", "stable_ground"]:
194
+ best_measure = np.min(measures)
195
+ good_measure = best_measure + (1 - thresh / 100) * (np.max(measures) - best_measure)
196
+ best_coef = coefs[np.argmin(measures)]
197
+ good_coefs = coefs[measures < good_measure]
198
+ elif method == "vvc":
199
+ best_measure = np.max(measures)
200
+ good_measure = best_measure - (1 - thresh / 100) * (best_measure - np.min(measures))
201
+ best_coef = coefs[np.argmax(measures)]
202
+ good_coefs = coefs[measures > good_measure]
203
+
204
+ elif select_method == "max relative":
205
+ if method in ["ground_truth", "stable_ground"]:
206
+ best_measure = np.min(measures)
207
+ good_measure = (1 + thresh / 100) * best_measure
208
+ best_coef = coefs[np.argmin(measures)]
209
+ good_coefs = coefs[measures < good_measure]
210
+ elif method == "vvc":
211
+ best_measure = np.max(measures)
212
+ good_measure = (1 - thresh / 100) * best_measure
213
+ best_coef = coefs[np.argmax(measures)]
214
+ good_coefs = coefs[measures > good_measure]
215
+
216
+ elif select_method == "absolute":
217
+ if method in ["ground_truth", "stable_ground"]:
218
+ best_measure = np.min(measures)
219
+ good_measure = best_measure + thresh
220
+ best_coef = coefs[np.argmin(measures)]
221
+ good_coefs = coefs[measures < good_measure]
222
+ elif method == "vvc":
223
+ best_measure = np.max(measures)
224
+ good_measure = best_measure - thresh
225
+ best_coef = coefs[np.argmax(measures)]
226
+ good_coefs = coefs[measures > good_measure]
227
+
228
+ elif select_method == "vvc_angle_thresh":
229
+ assert mean_angle is not None, (
230
+ "Mean angle to median direction over the area must be given for 'vvc_angle_thresh' selection method"
231
+ )
232
+
233
+ dVVC = abs(-np.sin(mean_angle) / (2 * np.sqrt(2 * (1 + np.cos(mean_angle)))) * thresh)
234
+ if visual:
235
+ print(mean_angle * 360 / (2 * np.pi))
236
+ print(dVVC)
237
+
238
+ return find_good_coefs(coefs, measures, method="vvc", select_method="absolute", thresh=dVVC)
239
+
240
+ elif select_method == "vvc_disp_thresh":
241
+ assert mean_disp is not None, (
242
+ "Mean displacements over the area must be given for 'vvc_disp_thresh' selection method"
243
+ )
244
+
245
+ vx, vy = mean_disp
246
+ v0 = np.array([vx - thresh, vy + thresh])
247
+ v1 = np.array([vx + thresh, vy - thresh])
248
+ d_angle = np.arccos((v0[0] * v1[0] + v0[1] * v1[1]) / (np.linalg.norm(v0) * np.linalg.norm(v1)))
249
+
250
+ if visual:
251
+ print(mean_disp)
252
+ print(d_angle * 360 / (2 * np.pi))
253
+
254
+ return find_good_coefs(
255
+ coefs,
256
+ measures,
257
+ method == "vvc",
258
+ select_method="vvc_angle_thresh",
259
+ thresh=d_angle,
260
+ mean_angle=mean_angle,
261
+ visual=visual,
262
+ )
263
+
264
+ return good_measure, good_coefs, best_measure, best_coef