pyadps 0.2.1b0__py3-none-any.whl → 0.3.0b0__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.
pyadps/utils/plotgen.py CHANGED
@@ -2,6 +2,505 @@ import matplotlib.pyplot as plt
2
2
  import numpy as np
3
3
  from matplotlib.widgets import Button, Slider, TextBox
4
4
 
5
+ class CutBins:
6
+ def __init__(
7
+ self, data, mask, newmask=False, t1=0, t2=200, tinc=500, z1=0, z2=-1, zinc=0
8
+ ):
9
+ # DATA SETUP
10
+ self.orig_data = data
11
+ self.orig_shape = np.shape(self.orig_data)
12
+ self.fill = 999
13
+ self.maskarray = mask
14
+ if not newmask:
15
+ self.orig_data[self.maskarray == 1] = self.fill
16
+
17
+ self.t1, self.t2, self.tinc = t1, t2, tinc
18
+ self.z1, self.z2, self.zinc = z1, z2, zinc
19
+ if z2 == -1:
20
+ self.z2 = self.orig_shape[0]
21
+
22
+ self.data = self.orig_data[self.z1 : self.z2, self.t1 : self.t2]
23
+ self.orig_subset = self.orig_data[self.z1 : self.z2, self.t1 : self.t2]
24
+ self.datacopy = np.copy(self.orig_data)
25
+ self.datamin = np.min(self.orig_data)
26
+ self.datamax = np.max(self.orig_data)
27
+ self.shape = np.shape(self.data)
28
+
29
+ # PLOT SETUP
30
+ self.t = np.arange(self.t1, self.t2)
31
+ self.z = np.arange(self.z1, self.z2)
32
+ self.tickinterval = int((self.t2 - self.t1) / 5)
33
+ self.xticks = np.arange(self.t1, self.t2, self.tickinterval)
34
+ self.X, self.Y = np.meshgrid(self.t, self.z)
35
+ self.fig, self.axs = plt.subplot_mosaic(
36
+ [["a", "b"], ["c", "b"]],
37
+ figsize=(12, 10),
38
+ width_ratios=[2, 1],
39
+ height_ratios=[1.75, 1],
40
+ )
41
+ self.fig.set_facecolor("darkgrey")
42
+ plt.subplots_adjust(top=0.82, right=0.95)
43
+
44
+ # ADDING WIDGET AXES
45
+ self.ax_clear_button = self.fig.add_axes(rect=(0.125, 0.90, 0.08, 0.025))
46
+ self.ax_delete_button = self.fig.add_axes(rect=(0.225, 0.90, 0.08, 0.025))
47
+ self.ax_refill_button = self.fig.add_axes(rect=(0.325, 0.90, 0.08, 0.025))
48
+ self.ax_next_button = self.fig.add_axes(rect=(0.630, 0.65, 0.02, 0.050))
49
+ self.ax_previous_button = self.fig.add_axes(rect=(0.075, 0.65, 0.02, 0.050))
50
+ self.ax_radio_button = self.fig.add_axes(rect=(0.725, 0.87, 0.10, 0.10))
51
+ self.ax_exit_button = self.fig.add_axes(rect=(0.825, 0.025, 0.08, 0.035))
52
+ self.ax_hslider = self.fig.add_axes(rect=(0.125, 0.85, 0.50, 0.03))
53
+ self.ax_vslider = self.fig.add_axes(rect=(0.04, 0.25, 0.03, 0.50))
54
+
55
+ self.ax_delete_button.set_visible(False)
56
+ self.ax_refill_button.set_visible(False)
57
+
58
+ # --- Slider settings ---
59
+ # Initial slider settings
60
+ self.hevent = 0
61
+ self.vevent = 0
62
+
63
+ # Slider options
64
+ self.hslider = Slider(
65
+ ax=self.ax_hslider,
66
+ label="Ensemble",
67
+ valmin=self.t1,
68
+ valmax=self.t2,
69
+ valinit=self.hevent,
70
+ valfmt="%i",
71
+ valstep=1,
72
+ )
73
+
74
+ self.vslider = Slider(
75
+ ax=self.ax_vslider,
76
+ label="Bins",
77
+ valmin=self.z1,
78
+ valmax=self.z2,
79
+ valinit=self.vevent,
80
+ valfmt="%i",
81
+ valstep=1,
82
+ orientation="vertical",
83
+ )
84
+
85
+ # Button Labels
86
+ self.clear_button = Button(self.ax_clear_button, "Clear")
87
+ self.delete_button = Button(self.ax_delete_button, "Delete")
88
+ self.refill_button = Button(self.ax_refill_button, "Refill")
89
+ self.previous_button = Button(self.ax_previous_button, "<")
90
+ self.next_button = Button(self.ax_next_button, ">")
91
+ self.exit_button = Button(self.ax_exit_button, "Save & Exit")
92
+ # self.cell_button = Button(self.ax_cell_button, "Cell")
93
+ # self.ensemble_button = Button(self.ax_ensemble_button, "Ensemble")
94
+ self.radio_button = RadioButtons(
95
+ self.ax_radio_button, ("Bin", "Ensemble", "Cell", "Region")
96
+ )
97
+
98
+ # --------------PLOTS---------------------
99
+
100
+ # Settings colorbar extreme to black
101
+ cmap = mpl.cm.turbo.with_extremes(over="k")
102
+ # FILL PLOT
103
+ self.mesh = self.axs["a"].pcolormesh(
104
+ self.X, self.Y, self.data, cmap=cmap, picker=True, vmin=0, vmax=255
105
+ )
106
+ plt.colorbar(self.mesh, orientation="horizontal")
107
+ self.axs["a"].set_xlim([self.t1, self.t2])
108
+ self.axs["a"].set_ylim([self.z1, self.z2])
109
+ # Draw vertical and horizontal lines
110
+ (self.vline,) = self.axs["a"].plot(
111
+ [self.t1, self.t1], [self.z1, self.z2], color="r", linewidth=2.5
112
+ )
113
+ (self.hline,) = self.axs["a"].plot(
114
+ [self.t1, self.t2], [self.z1, self.z1], color="r", linewidth=2.5
115
+ )
116
+
117
+ # PROFILE
118
+ (self.profile,) = self.axs["b"].plot(
119
+ self.data[self.z1 : self.z2, self.t1 + self.hevent], range(self.z1, self.z2)
120
+ )
121
+
122
+ self.axs["b"].set_xlim([self.datamin, self.datamax])
123
+ self.profile_text = self.axs["b"].text(
124
+ 0.95,
125
+ 0.95,
126
+ f"Ensemble No.: {self.t1 + self.hevent}",
127
+ verticalalignment="bottom",
128
+ horizontalalignment="right",
129
+ transform=self.axs["b"].transAxes,
130
+ color="k",
131
+ fontsize=12,
132
+ )
133
+
134
+ # TIME SERIES
135
+ (self.tseries,) = self.axs["c"].plot(
136
+ range(self.t1, self.t2), self.data[self.z1 + self.vevent, self.t1 : self.t2]
137
+ )
138
+ self.axs["c"].set_ylim([self.datamin, self.datamax])
139
+ self.tseries_text = self.axs["c"].text(
140
+ 0.90,
141
+ 0.90,
142
+ f"Bin No.: {self.z1 + self.vevent}",
143
+ verticalalignment="bottom",
144
+ horizontalalignment="right",
145
+ transform=self.axs["c"].transAxes,
146
+ color="k",
147
+ fontsize=12,
148
+ )
149
+ # --------------END PLOTS---------------------
150
+
151
+ # EVENTS
152
+ self.onclick = self.onclick_bin
153
+ self.hslider.on_changed(self.hupdate)
154
+ self.vslider.on_changed(self.vupdate)
155
+ self.clear_button.on_clicked(self.clear)
156
+ self.radio_button.on_clicked(self.radio)
157
+ self.cid = self.fig.canvas.mpl_connect("pick_event", self.onclick)
158
+
159
+ self.delete_button.on_clicked(self.boxdelete)
160
+ self.refill_button.on_clicked(self.boxrefill)
161
+ self.next_button.on_clicked(self.next)
162
+ self.previous_button.on_clicked(self.previous)
163
+ self.exit_button.on_clicked(self.exit)
164
+
165
+ def next(self, event):
166
+ if self.t2 <= self.orig_shape[1]:
167
+ # Next works till the last subset. The if statement checks for last subset.
168
+ self.t1 = self.t1 + self.tinc
169
+ self.t2 = self.t2 + self.tinc
170
+ if self.t2 > (self.orig_shape[1]):
171
+ # If in last subset create a dummy data set with missing value.
172
+ self.data = self.datacopy[
173
+ self.z1 : self.z2, self.t1 : self.orig_shape[1]
174
+ ]
175
+ self.orig_subset = self.orig_data[
176
+ self.z1 : self.z2, self.t1 : self.orig_shape[1]
177
+ ]
178
+ self.missing = (
179
+ np.ones((self.z2 - self.z1, self.t2 - self.orig_shape[1]))
180
+ * self.fill
181
+ )
182
+ # self.data consist of data along with flagged value
183
+ self.data = np.append(self.data, self.missing, axis=1)
184
+ # self.orig_subset contains only the subset of the original data
185
+ # Useful for plotting time series and profiles
186
+ self.orig_subset = np.append(self.orig_subset, self.missing, axis=1)
187
+ else:
188
+ self.data = self.datacopy[self.z1 : self.z2, self.t1 : self.t2]
189
+ self.orig_subset = self.orig_data[self.z1 : self.z2, self.t1 : self.t2]
190
+
191
+ self.mesh.set_array(self.data)
192
+ self.tick = np.arange(self.t1, self.t2, self.tickinterval)
193
+ self.axs["a"].set_xticks(self.xticks, self.tick)
194
+
195
+ self.profile.set_xdata(self.orig_subset[:, self.hevent])
196
+ self.profile_text.set_text(f"Ensemble No.: {self.t1 + self.hevent}")
197
+ self.vline.set_xdata([self.hevent, self.hevent])
198
+
199
+ self.tseries.set_ydata(self.orig_subset[self.vevent, :])
200
+ self.tseries_text.set_text(f"Bin No.: {self.z1 + self.vevent}")
201
+ self.hline.set_ydata([self.vevent, self.vevent])
202
+
203
+ self.fig.canvas.draw()
204
+
205
+ def previous(self, event):
206
+ if self.t1 >= self.tinc:
207
+ self.t1 = self.t1 - self.tinc
208
+ self.t2 = self.t2 - self.tinc
209
+ self.tick = np.arange(self.t1, self.t2, self.tickinterval)
210
+ self.data = self.datacopy[self.z1 : self.z2, self.t1 : self.t2]
211
+ self.axs["a"].set_xticks(self.xticks, self.tick)
212
+ self.mesh.set_array(self.data)
213
+
214
+ # Reset sliders
215
+ self.profile.set_xdata(self.orig_data[self.z1 : self.z2, self.hevent])
216
+ self.profile_text.set_text(f"Ensemble No.: {self.hevent}")
217
+ self.vline.set_xdata([self.hevent, self.hevent])
218
+
219
+ self.tseries.set_ydata(self.orig_data[self.vevent, self.t1 : self.t2])
220
+ self.tseries_text.set_text(f"Bin No.: {self.z1 + self.vevent}")
221
+ self.hline.set_ydata([self.vevent, self.vevent])
222
+
223
+ self.fig.canvas.draw()
224
+
225
+ def radio(self, event):
226
+ self.fig.canvas.mpl_disconnect(self.cid)
227
+ if event == "Bin":
228
+ self.cid = self.fig.canvas.mpl_connect("pick_event", self.onclick_bin)
229
+ elif event == "Ensemble":
230
+ self.cid = self.fig.canvas.mpl_connect("pick_event", self.onclick_ens)
231
+ elif event == "Cell":
232
+ self.cid = self.fig.canvas.mpl_connect("pick_event", self.onclick_cell)
233
+ else:
234
+ self.rid = RectangleSelector(
235
+ self.axs["a"],
236
+ self.onclick_box,
237
+ useblit=True,
238
+ minspanx=2,
239
+ minspany=2,
240
+ interactive=True,
241
+ )
242
+
243
+ def clear(self, event):
244
+ if event.button == 1:
245
+ self.datacopy = np.copy(self.orig_data)
246
+ if self.t2 >= (self.orig_shape[1]):
247
+ test = self.datacopy[self.z1 : self.z2, self.t1 : self.t2]
248
+ test = np.append(test, self.missing, axis=1)
249
+ else:
250
+ test = self.datacopy[self.z1 : self.z2, self.t1 : self.t2]
251
+
252
+ # self.mesh.set_array(self.datacopy[self.z1 : self.z2, self.t1 : self.t2])
253
+ self.mesh.set_array(test)
254
+ self.fig.canvas.draw()
255
+
256
+ def hupdate(self, event):
257
+ self.hevent = event
258
+ self.profile.set_xdata(self.orig_subset[:, self.hevent])
259
+ self.profile_text.set_text(f"Ensemble No.: {self.t1 + self.hevent}")
260
+ self.vline.set_xdata([self.hevent, self.hevent])
261
+
262
+ def vupdate(self, event):
263
+ self.vevent = event
264
+ self.tseries.set_ydata(self.orig_subset[self.vevent, :])
265
+ self.tseries_text.set_text(f"Bin No.: {self.z1 + self.vevent}")
266
+ self.hline.set_ydata([self.vevent, self.vevent])
267
+
268
+ def onclick_bin(self, event):
269
+ ind = event.ind
270
+ x = ind // (self.t[-1] + 1)
271
+ # y = ind % (self.t[-1] + 1)
272
+ xx = self.z1 + x
273
+ # yy = self.t1 + y
274
+ if np.all(self.datacopy[xx, :] == self.fill):
275
+ self.datacopy[xx, :] = np.copy(self.orig_data[xx, :])
276
+
277
+ else:
278
+ self.datacopy[xx, :] = self.fill
279
+
280
+ if self.t2 >= (self.orig_shape[1]):
281
+ test = self.datacopy[self.z1 : self.z2, self.t1 : self.t2]
282
+ test = np.append(test, self.missing, axis=1)
283
+ else:
284
+ test = self.datacopy[self.z1 : self.z2, self.t1 : self.t2]
285
+
286
+ # self.mesh.set_array(self.datacopy[self.z1 : self.z2, self.t1 : self.t2])
287
+ self.mesh.set_array(test)
288
+ self.hline.set_ydata([x, x])
289
+ self.vslider.set_val(x[0])
290
+ self.fig.canvas.draw()
291
+
292
+ def onclick_ens(self, event):
293
+ ind = event.ind
294
+ if np.size(ind) != 1:
295
+ return
296
+ # x = ind // (self.t[-1] + 1)
297
+ y = ind % (self.t[-1] + 1)
298
+ yy = self.t1 + y
299
+
300
+ if yy < self.orig_shape[1]:
301
+ if np.all(self.datacopy[:, yy] == self.fill):
302
+ self.datacopy[:, yy] = np.copy(self.orig_data[:, yy])
303
+ else:
304
+ self.datacopy[:, yy] = self.fill
305
+
306
+ if self.t2 >= (self.orig_shape[1]):
307
+ test = self.datacopy[self.z1 : self.z2, self.t1 : self.t2]
308
+ test = np.append(test, self.missing, axis=1)
309
+ else:
310
+ test = self.datacopy[self.z1 : self.z2, self.t1 : self.t2]
311
+ # self.mesh.set_array(self.datacopy[self.z1 : self.z2, self.t1 : self.t2])
312
+ self.mesh.set_array(test)
313
+ self.hline.set_xdata([y, y])
314
+ self.hslider.set_val(y[0])
315
+ self.fig.canvas.draw()
316
+
317
+ def onclick_cell(self, event):
318
+ ind = event.ind
319
+ if np.size(ind) != 1:
320
+ return
321
+ x = ind // (self.t[-1] + 1)
322
+ y = ind % (self.t[-1] + 1)
323
+ xx = self.z1 + x
324
+ yy = self.t1 + y
325
+
326
+ if yy < self.orig_shape[1]:
327
+ if self.datacopy[xx, yy] == self.fill:
328
+ self.datacopy[xx, yy] = np.copy(self.orig_data[x, y])
329
+ else:
330
+ self.datacopy[xx, yy] = self.fill
331
+
332
+ if self.t2 > (self.orig_shape[1]):
333
+ test = self.datacopy[self.z1 : self.z2, self.t1 : self.t2]
334
+ test = np.append(test, self.missing, axis=1)
335
+ else:
336
+ test = self.datacopy[self.z1 : self.z2, self.t1 : self.t2]
337
+
338
+ # self.mesh.set_array(self.datacopy[self.z1 : self.z2, self.t1 : self.t2])
339
+ self.mesh.set_array(test)
340
+ self.vline.set_xdata([y, y])
341
+ self.hline.set_ydata([x, x])
342
+ self.hslider.set_val(y[0])
343
+ self.vslider.set_val(x[0])
344
+ self.fig.canvas.draw()
345
+
346
+ def onclick_box(self, eclick, erelease):
347
+ self.ax_delete_button.set_visible(True)
348
+ self.ax_refill_button.set_visible(True)
349
+ plt.gcf().canvas.draw()
350
+ self.x11, self.y11 = int(eclick.xdata), int(eclick.ydata)
351
+ self.x22, self.y22 = int(erelease.xdata) + 1, int(erelease.ydata) + 1
352
+
353
+ print(
354
+ f"({self.x11:3.2f}, {self.y11:3.2f}) --> ({self.x22:3.2f}, {self.y22:3.2f})"
355
+ )
356
+ print(f" The buttons you used were: {eclick.button} {erelease.button}")
357
+
358
+ def boxdelete(self, event):
359
+ z1 = self.z1 + self.y11 + 1
360
+ z2 = self.z1 + self.y22
361
+ t1 = self.t1 + self.x11 + 1
362
+ t2 = self.t1 + self.x22
363
+ self.datacopy[z1:z2, t1:t2] = self.fill
364
+
365
+ if self.t2 > (self.orig_shape[1]):
366
+ test = self.datacopy[self.z1 : self.z2, self.t1 : self.t2]
367
+ test = np.append(test, self.missing, axis=1)
368
+ else:
369
+ test = self.datacopy[self.z1 : self.z2, self.t1 : self.t2]
370
+
371
+ # self.mesh.set_array(self.datacopy[self.z1 : self.z2, self.t1 : self.t2])
372
+ self.mesh.set_array(test)
373
+ self.fig.canvas.draw()
374
+
375
+ def boxrefill(self, event):
376
+ z1 = self.z1 + self.y11 + 1
377
+ z2 = self.z1 + self.y22
378
+ t1 = self.t1 + self.x11 + 1
379
+ t2 = self.t1 + self.x22
380
+ self.datacopy[z1:z2, t1:t2] = self.orig_data[z1:z2, t1:t2]
381
+
382
+ if self.t2 > (self.orig_shape[1]):
383
+ test = self.datacopy[self.z1 : self.z2, self.t1 : self.t2]
384
+ test = np.append(test, self.missing, axis=1)
385
+ else:
386
+ test = self.datacopy[self.z1 : self.z2, self.t1 : self.t2]
387
+ # self.mesh.set_array(self.datacopy[self.z1 : self.z2, self.t1 : self.t2])
388
+ self.mesh.set_array(test)
389
+ self.fig.canvas.draw()
390
+
391
+ def exit(self, event):
392
+ plt.close()
393
+
394
+ def mask(self):
395
+ self.maskarray[self.datacopy == self.fill] = 1
396
+ return self.maskarray
397
+
398
+
399
+ class PlotEnds:
400
+ def __init__(self, pressure, delta=10):
401
+ self.dep = pressure / 980
402
+
403
+ self.n = np.size(self.dep)
404
+ self.delta = delta
405
+ self.nmin = 0
406
+ self.nmax = self.nmin + self.delta
407
+ self.mmax = 0
408
+ self.mmin = self.mmax - self.delta
409
+
410
+ self.x = np.arange(0, self.n)
411
+
412
+ self.start_ens = 0
413
+ self.end_ens = 0
414
+
415
+ self.fig, self.axs = plt.subplots(1, 2, figsize=(12, 8))
416
+ self.fig.set_facecolor("darkgrey")
417
+ plt.subplots_adjust(bottom=0.28, right=0.72)
418
+
419
+ self.ax_end = self.fig.add_axes(rect=(0.25, 0.08, 0.47, 0.03))
420
+ self.ax_start = self.fig.add_axes(rect=(0.25, 0.15, 0.47, 0.03))
421
+ self.ax_button = self.fig.add_axes(rect=(0.81, 0.05, 0.15, 0.075))
422
+ # self.ax_depmaxbutton = self.fig.add_axes(rect=(0.68, 0.13, 0.04, 0.02))
423
+ # self.ax_depminbutton = self.fig.add_axes(rect=(0.25, 0.13, 0.04, 0.02))
424
+ # self.ax_recmaxbutton = self.fig.add_axes(rect=(0.68, 0.06, 0.04, 0.02))
425
+ # self.ax_recminbutton = self.fig.add_axes(rect=(0.25, 0.06, 0.04, 0.02))
426
+
427
+ # Plot
428
+ self.axs[0].scatter(self.x, self.dep, color="k")
429
+ self.axs[1].scatter(self.x, self.dep, color="k")
430
+
431
+ # Figure Labels
432
+ for i in range(2):
433
+ self.axs[i].set_xlabel("Ensemble")
434
+ self.axs[0].set_xlim([self.nmin - 1, self.nmax])
435
+ self.axs[1].set_xlim([self.n - self.delta, self.n])
436
+ self.axs[0].set_ylabel("Depth (m)")
437
+ self.fig.suptitle("Trim Ends")
438
+
439
+ # Display statistics
440
+ self.axs[0].text(0.82, 0.60, "Statistics", transform=plt.gcf().transFigure)
441
+ self.max = np.round(np.max(self.dep), decimals=2)
442
+ self.min = np.round(np.min(self.dep), decimals=2)
443
+ self.median = np.round(np.median(self.dep), decimals=2)
444
+ self.mean = np.round(np.mean(self.dep), decimals=2)
445
+ self.t1 = self.axs[0].text(
446
+ 0.75,
447
+ 0.50,
448
+ f"Dep. Max = {self.max} \nDep. Min = {self.min} \nDep. Median = {self.median}",
449
+ transform=plt.gcf().transFigure,
450
+ )
451
+
452
+ self.sl_start = Slider(
453
+ ax=self.ax_start,
454
+ label="Dep. Ensemble",
455
+ valmin=self.nmin,
456
+ valmax=self.nmax,
457
+ valinit=0,
458
+ valfmt="%i",
459
+ valstep=1,
460
+ )
461
+
462
+ self.sl_end = Slider(
463
+ ax=self.ax_end,
464
+ label="Rec. Ensemble",
465
+ valmin=self.mmin,
466
+ valmax=self.mmax,
467
+ valinit=0,
468
+ valfmt="%i",
469
+ valstep=1,
470
+ )
471
+
472
+ self.sl_start.on_changed(self.update1)
473
+ self.sl_end.on_changed(self.update2)
474
+ self.button = Button(self.ax_button, "Save & Exit")
475
+ # self.depminbutton = Button(self.ax_depminbutton, "<<")
476
+ # self.depmaxbutton = Button(self.ax_depmaxbutton, ">>")
477
+ # self.recminbutton = Button(self.ax_recminbutton, "<<")
478
+ # self.recmaxbutton = Button(self.ax_recmaxbutton, ">>")
479
+
480
+ self.button.on_clicked(self.exitwin)
481
+
482
+ def update1(self, value):
483
+ self.axs[0].scatter(self.x, self.dep, color="k")
484
+ self.axs[0].scatter(self.x[0:value], self.dep[0:value], color="r")
485
+ self.start_ens = value
486
+
487
+ def update2(self, value):
488
+ self.axs[1].scatter(self.x, self.dep, color="k")
489
+ if value < 0:
490
+ self.axs[1].scatter(
491
+ self.x[self.n + value : self.n],
492
+ self.dep[self.n + value : self.n],
493
+ color="r",
494
+ )
495
+ self.end_ens = value
496
+
497
+ def show(self):
498
+ plt.show()
499
+
500
+ def exitwin(self, event):
501
+ plt.close()
502
+
503
+
5
504
 
6
505
  class PlotNoise:
7
506
  def __init__(self, echo):