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