tinaok commited on
Commit
af23075
1 Parent(s): fc2318a

Upload 2 files

Browse files
Files changed (2) hide show
  1. app.py +125 -323
  2. requirements.txt +3 -4
app.py CHANGED
@@ -1,212 +1,67 @@
1
- import cftime
2
- import fsspec
3
-
4
- import matplotlib.pyplot as plt
5
  import numpy as np
6
  import pandas as pd
7
  import panel as pn
8
  import xarray as xr
9
- from ipywidgets import (
10
- Checkbox,
11
- # FloatRangeSlider,
12
- FloatSlider,
13
- IntRangeSlider,
14
- IntSlider,
15
- # interactive,
16
- )
17
-
18
-
19
  import param
20
 
21
- pn.extension("tabulator")
22
-
23
- def greg_0h(jourjul):
24
- import math
25
- # Julian days start and end at noon.
26
- # Julian day 2440000 begins at 00 hours, May 23, 1968.
27
-
28
- # Round the input Julian day number to avoid precision errors
29
- fac = 10**9
30
- jourjul = np.round(fac * jourjul + 0.5) / fac
31
-
32
- # Calculate seconds in the day
33
- secs = (jourjul % 1) * 24 * 3600
34
-
35
- # Round seconds to avoid precision errors
36
- secs = np.round(fac * secs + 0.5) / fac
37
-
38
- # Gregorian calendar conversion
39
- j = math.floor(jourjul) - 1721119
40
- in_ = 4 * j - 1
41
- y = math.floor(in_ / 146097)
42
- j = in_ - 146097 * y
43
- in_ = math.floor(j / 4)
44
- in_ = 4 * in_ + 3
45
- j = math.floor(in_ / 1461)
46
- d = math.floor(((in_ - 1461 * j) + 4) / 4)
47
- in_ = 5 * d - 3
48
- m = math.floor(in_ / 153)
49
- d = math.floor(((in_ - 153 * m) + 5) / 5)
50
- y = y * 100 + j
51
- if m < 10:
52
- mo = m + 3
53
- yr = y
54
- else:
55
- mo = m - 9
56
- yr = y + 1
57
-
58
- hour = math.floor(secs / 3600)
59
- mins = math.floor((secs % 3600) / 60)
60
- sec = int(secs % 60)
61
-
62
- gtime = [yr, mo, d, hour, mins, sec]
63
-
64
- return gtime
65
-
66
-
67
- def fix_time(ds):
68
- from datetime import datetime, timedelta
69
-
70
- time = ds["TIME"]
71
- time2 = time.dropna(dim="MAXT")
72
- time2 = time2.reindex_like(time, method="nearest")
73
- jourjul = [greg_0h(jourjul) for jourjul in time2.values]
74
- date = [
75
- datetime(jourjul[0], jourjul[1], jourjul[2], jourjul[3], jourjul[4], jourjul[5])
76
- for jourjul in jourjul
77
- ]
78
- date = xr.DataArray(date, dims="MAXT")
79
- return ds.assign(TIME=date)
80
-
81
- @pn.cache(max_items=32,policy='LRU',per_session=True)
82
- def load_csv():
83
- df = pd.read_csv('./data/zarr_table.csv',index_col=None)
84
- df.sort_values(by="year") #inplace=True)
85
- return df
86
-
87
- @pn.cache(max_items=4,policy='LRU',per_session=True)
88
- def load_bathymetry():
89
- #url="https://data-eurogoship.ifremer.fr/bathymetrie/bathy6min.nc"
90
- #fs = fsspec.filesystem("https")
91
- return xr.open_dataset('./data/bathy6min.nc', decode_times=False, use_cftime=True)
92
-
93
- @pn.cache(max_items=16,policy='LRU',per_session=True)
94
- def load_zarr(selected_file):
95
- from datatree import open_datatree
96
- tree= open_datatree('./data/1H_file.zarr', engine='zarr')
97
- return tree[selected_file+"/"].ds
98
-
99
- def filter_df(sorted_df,selected_file):
100
- dataframe = sorted_df[sorted_df["file_name"] == selected_file].drop(
101
- columns=[
102
- "file_name",
103
- "title",
104
- "Conventions",
105
- "featureType",
106
- "date_update",
107
- "ADCP_beam_angle",
108
- "ADCP_ship_angle",
109
- "middle_bin1_depth",
110
- "heading_corr",
111
- "pitch_corr",
112
- "ampli_corr",
113
- "pitch_roll_used",
114
- "date_creation",
115
- "ADCP_type",
116
- "data_type",
117
- ]
118
- )
119
- dataframe2 = sorted_df[sorted_df["file_name"] == selected_file].drop(
120
- columns=[
121
- "file_name",
122
- "date_start",
123
- "date_end",
124
- "ADCP_frequency(kHz)",
125
- "bin_length(meter)",
126
- "year",
127
- ]
128
- )
129
- return dataframe.transpose(), dataframe2.transpose()
130
 
131
- def quiver_depth_filterd(ax,ds_filtered, depth1, depth_range_slider, scale_factor_slider, color="blue"):
132
- import cartopy.crs as ccrs
133
- depth_filtered = ds_filtered.where(
134
- (depth1 > depth_range_slider.value[0])
135
- & (depth1 <= depth_range_slider.value[1])
136
- )
137
 
138
- lon = ds_filtered.coords["LONGITUDE"].values
139
- lat = ds_filtered.coords["LATITUDE"].values
140
 
141
- # Moyenne des vecteurs de courant sur la plage de profondeur sélectionnée
142
- u_mean = depth_filtered.UCUR.mean(dim="MAXZ", skipna=True)
143
- v_mean = depth_filtered.VCUR.mean(dim="MAXZ", skipna=True)
144
 
145
- return ax.quiver(
146
- lon,
147
- lat,
148
- u_mean * scale_factor_slider.value,
149
- v_mean * scale_factor_slider.value,
150
- color=color,
151
- scale=2,
152
- width=0.001,
153
- headwidth=3,
154
- transform=ccrs.PlateCarree(),
155
- )
156
 
157
- class SADCP_Viewer(param.Parameterized):
158
  df = load_csv()
159
  bathy = load_bathymetry()
 
160
  file_names = df["file_name"].tolist()
161
  years = sorted(df["year"].unique())
162
 
163
- year_slider = pn.widgets.IntRangeSlider(
164
- name="Year Range", start=df["year"].min(), end=df["year"].max()
165
- )
166
  file_dropdown = pn.widgets.Select(name="File Selector")
167
- data_table = pn.widgets.Tabulator(df, name="metadata", height=200, width=300)
168
- # data_table2 = pn.widgets.Tabulator(df2, name="metadata", height=900, width=400)
169
-
170
- longitude_slider = pn.widgets.RangeSlider(
171
- name="Longitude Range", start=-180, end=180, step=1
172
- )
173
- latitude_slider = pn.widgets.RangeSlider(
174
- name="Latitude Range", start=-90, end=90, step=1
175
- )
176
-
177
- depth_range_slider = pn.widgets.IntRangeSlider(
178
- start=100, end=300, value=(100, 300), step=1, name="Depth Range"
179
- )
180
  depth_2_checkbox = pn.widgets.Checkbox(value=False, name="Depth 2 Checkbox")
181
  depth_3_checkbox = pn.widgets.Checkbox(value=False, name="Depth 3 Checkbox")
182
-
183
- depth2_range_slider = pn.widgets.IntRangeSlider(
184
- start=100, end=300, value=(100, 300), step=1, name="Depth 2 Range"
185
- )
186
- depth3_range_slider = pn.widgets.IntRangeSlider(
187
- start=100, end=300, value=(100, 300), step=1, name="Depth 3 Range"
188
- )
189
-
190
- num_vectors_slider = pn.widgets.IntSlider(
191
- start=40, end=800, step=1, value=100, name="Number of Vectors"
192
- )
193
- scale_factor_slider = pn.widgets.FloatSlider(
194
- start=0.1, end=1, step=0.1, value=0.5, name="Scale Factor"
195
- )
196
  bathy_checkbox = pn.widgets.Checkbox(value=False, name="Bathy Checkbox")
197
 
198
- plot = pn.pane.HoloViews()
199
- plot_map = pn.pane.Matplotlib(width=800, height=600, sizing_mode="fixed")
200
-
201
  data_table = pn.widgets.Tabulator(width=400, height=200)
202
-
203
  metadata_table = pn.widgets.Tabulator(width=600, height=800)
 
204
  download_button = pn.widgets.Button(name="Download", button_type="primary")
205
- # plot = pn.Column()
206
 
207
  def __init__(self, **params):
 
 
 
 
 
 
 
208
  super(SADCP_Viewer, self).__init__(**params)
209
- self.file_dropdown.objects = self.get_file_list()
210
  self.file_dropdown.value = (
211
  self.file_dropdown.objects[0] if self.file_dropdown.objects else None
212
  )
@@ -214,54 +69,50 @@ class SADCP_Viewer(param.Parameterized):
214
 
215
  @param.depends("year_slider.value", "file_dropdown.value", watch=True)
216
  def update_name_options(self):
 
 
 
 
 
 
 
 
217
  start_year, end_year = self.year_slider.value
 
 
218
  mask = (self.df["year"] >= start_year) & (self.df["year"] <= end_year)
219
  sorted_df = self.df[mask].sort_values(by="year")
 
 
220
  files = sorted_df["file_name"].unique().tolist()
221
-
 
222
  self.file_dropdown.options = files
 
223
  if files:
224
  selected_file = self.file_dropdown.value
 
 
225
  if not selected_file or selected_file not in files:
226
  selected_file = files[0]
227
  self.file_dropdown.value = selected_file
228
- self.data_table.value, self.metadata_table.value = filter_df(sorted_df,selected_file)
229
-
230
- self.ds=load_zarr(selected_file)
231
-
232
- lon_range = (
233
- int(self.ds["LONGITUDE"].min().round() - 1),
234
- int(self.ds["LONGITUDE"].max().round() + 1),
235
- )
236
- lat_range = (
237
- int(self.ds["LATITUDE"].min().round() - 1),
238
- int(self.ds["LATITUDE"].max().round() + 1),
239
- )
240
- self.depth1 = abs(self.ds.coords["PROFZ"])
241
- deph_range = (int(self.depth1.min()), int(self.depth1.max()))
242
-
243
- self.longitude_slider.start = lon_range[0]
244
- self.longitude_slider.end = lon_range[1]
245
- self.longitude_slider.value = lon_range
246
-
247
- self.latitude_slider.start = lat_range[0]
248
- self.latitude_slider.end = lat_range[1]
249
- self.latitude_slider.value = lat_range
250
-
251
- self.depth_range_slider.start = deph_range[0]
252
- self.depth_range_slider.end = deph_range[1]
253
- self.depth_range_slider.value = deph_range
254
-
255
- self.depth2_range_slider.start = deph_range[0]
256
- self.depth2_range_slider.end = deph_range[1]
257
- self.depth2_range_slider.value = deph_range
258
-
259
- self.depth3_range_slider.start = deph_range[0]
260
- self.depth3_range_slider.end = deph_range[1]
261
- self.depth3_range_slider.value = deph_range
262
-
263
- # self.update_plots()
264
- self.ds.close()
265
 
266
  @param.depends(
267
  "year_slider.value",
@@ -269,117 +120,60 @@ class SADCP_Viewer(param.Parameterized):
269
  "depth_range_slider.value",
270
  "depth_2_checkbox.value",
271
  "depth_3_checkbox.value",
272
- "depth2_range_slider.value",
273
- "depth3_range_slider.value",
274
  "longitude_slider.value",
275
  "latitude_slider.value",
276
  "num_vectors_slider.value",
277
  "scale_factor_slider.value",
278
  "bathy_checkbox.value",
279
- watch=False,
280
- )
281
  def update_plots(self):
282
- self.ds_filtered = self.filter_data()
283
- # vector_plot = self.vectors_plot()
284
- other_plots = self.hvplot_plots()
285
-
286
- # self.plot_map = pn.pane.Matplotlib(vector_plot, width=800, height=600, sizing_mode="fixed")
287
- self.plot = pn.Column(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
288
  *(pn.pane.HoloViews(plot, width=400, height=200) for plot in other_plots),
289
  sizing_mode="stretch_width"
290
  )
291
- vector_plot = self.vectors_plot() # Update vector plot
292
- self.plot_map.object = vector_plot
293
- # other_plots = self.plots() # Update other plots
294
- # self.plot.objects = [*(pn.pane.HoloViews(p, width=400, height=200) for p in other_plots)]
295
- # self.plot.object=plot
296
-
297
- return pn.Row(self.plot_map, self.plot, sizing_mode="stretch_both")
298
-
299
- def filter_data(self):
300
- return self.ds.where(
301
- (self.ds.LONGITUDE >= self.longitude_slider.start)
302
- & (self.ds.LONGITUDE <= self.longitude_slider.end)
303
- & (self.ds.LATITUDE >= self.latitude_slider.start)
304
- & (self.ds.LATITUDE <= self.latitude_slider.end),
305
- drop=True,
306
- )
307
-
308
- def vectors_plot(self):
309
- import cartopy.crs as ccrs
310
- import cartopy.feature as cfeature
311
 
312
- self.ds_filtered = self.filter_data()
 
313
 
314
- # return self.ds_filtered['VSHIP'].hvplot(x='TIME',width=400, height=200) #if 'BATHY' in self.ds_filtered else hvplot.show(hvplot.text(0, 0, "No data available", fontsize=12))
315
-
316
- fig, ax = plt.subplots(
317
- figsize=(8, 7), subplot_kw={"projection": ccrs.Mercator()}
318
- )
319
- coords = ["LATITUDE", "LONGITUDE"]
320
- corsen = max(1, self.ds_filtered.MAXT.size // self.num_vectors_slider.value)
321
- self.ds_filtered = (
322
- self.ds_filtered.reset_coords(coords)
323
- .coarsen({"MAXT": corsen}, boundary="trim")
324
- .mean()
325
- .set_coords(coords)
326
- )
327
-
328
- # self.ds_filtered =self.ds_filtered.coarsen(MAXT = corsen, side = "center", boundary = "trim").mean()[["LONGITUDE", "LONGITUDE", "TIME"]].isel(MAXZ=0)
329
-
330
- quiver_depth_filterd(ax,self.ds_filtered, self.depth1, self.depth_range_slider,self.scale_factor_slider,color="blue")
331
-
332
- if self.depth_2_checkbox.value:
333
- quiver_depth_filterd(ax,self.ds_filtered, self.depth1, self.depth2_range_slider,self.scale_factor_slider,color="green")
334
-
335
- if self.depth_3_checkbox.value:
336
- quiver_depth_filterd(ax,self.ds_filtered, self.depth1, self.depth3_range_slider,self.scale_factor_slider,color="red")
337
-
338
- ax.add_feature(cfeature.COASTLINE)
339
- ax.add_feature(cfeature.BORDERS, linestyle=":")
340
- ax.add_feature(cfeature.LAND, color="lightgray")
341
-
342
- if self.bathy_checkbox.value:
343
- contour_levels = [-1000]
344
- ax.contour(
345
- self.bathy.longitude,
346
- self.bathy.latitude,
347
- self.bathy.z,
348
- levels=contour_levels,
349
- colors="black",
350
- transform=ccrs.PlateCarree(),
351
- )
352
-
353
- ax.set_extent(
354
- [
355
- self.longitude_slider.value[0],
356
- self.longitude_slider.value[1],
357
- self.latitude_slider.value[0],
358
- self.latitude_slider.value[1],
359
- ]
360
- )
361
- ax.gridlines(draw_labels=True)
362
- plt.ylabel("Latitude", fontsize=15, labelpad=35)
363
- plt.xlabel("Longitude", fontsize=15, labelpad=20)
364
- plt.close()
365
- return fig
366
-
367
- # pn.pane.Matplotlib(fig,width=800, height=600, sizing_mode="fixed", name="Plot")
368
-
369
- # @param.depends( 'file_dropdown.value', 'longitude_slider.value', 'latitude_slider.value', watch=True)
370
- def hvplot_plots(self):
371
- import hvplot.xarray
372
- return [
373
- self.ds_filtered["BATHY"].max(dim="MAXZ").hvplot(x="TIME", width=400, height=200),
374
- self.ds_filtered["USHIP"].max(dim="MAXZ").hvplot(x="TIME", width=400, height=200),
375
- self.ds_filtered["VSHIP"].max(dim="MAXZ").hvplot(x="TIME", width=400, height=200),
376
- self.ds_filtered["BOTTOM_DEPTH"].max(dim="MAXZ").hvplot(x="TIME", width=400, height=200),
377
-
378
- ]
379
-
380
- def get_file_list(self):
381
- return self.file_names
382
 
 
 
383
 
384
  explorer = SADCP_Viewer()
385
  # Instantiate the SADCP_Viewer class and create a template
@@ -394,6 +188,7 @@ tabs = pn.Tabs(
394
  )
395
 
396
  sidebar = [
 
397
  """This application, developed in the frame of Euro Go Shop, helps to interactively visualise and download ship ADCP data.""",
398
  explorer.year_slider,
399
  explorer.file_dropdown,
@@ -403,14 +198,21 @@ sidebar = [
403
  explorer.depth_range_slider,
404
  explorer.depth_2_checkbox,
405
  explorer.depth_3_checkbox,
406
- explorer.depth2_range_slider,
407
- explorer.depth3_range_slider,
408
  explorer.num_vectors_slider,
409
  explorer.scale_factor_slider,
410
  explorer.data_table,
 
 
 
 
 
411
  ]
 
412
  template = pn.template.FastListTemplate(
413
- title="SADCP data Viewer", sidebar=sidebar, main=[tabs]
 
 
414
  )
415
  template.servable()
416
-
 
 
 
 
 
1
  import numpy as np
2
  import pandas as pd
3
  import panel as pn
4
  import xarray as xr
 
 
 
 
 
 
 
 
 
 
5
  import param
6
 
7
+ import hvplot.xarray
8
+ import matplotlib.pyplot as plt
9
+ import cartopy.crs as ccrs
10
+ import cartopy.feature as cfeature
11
+ from datatree import open_datatree
12
+ from xsadcp import get_range, load_csv, load_bathymetry, load_zarr, load_file, filter_df, filter_data, quiver_depth_filtered, bathy_uship_vship_bottom_depth, corsen_data, vectors_plot, fix_time, transform_netCDF, get_info, get_file_names, open_ds
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
 
 
 
 
 
 
 
14
 
 
 
15
 
16
+ class SADCP_Viewer(param.Parameterized):
17
+ """
18
+ A parameterized class for viewing SADCP data.
19
 
20
+ This class provides widgets for selecting data parameters, updating data based on selections,
21
+ and generating plots to visualize the SADCP data.
22
+
23
+ Available functions:
24
+ - update_name_options: Update dropdown options and slider ranges based on selected years and file.
25
+ - update_plots: Update plots based on selected data and parameters.
26
+ """
 
 
 
 
27
 
28
+ # Load data and initialize widgets
29
  df = load_csv()
30
  bathy = load_bathymetry()
31
+ tree=load_zarr()
32
  file_names = df["file_name"].tolist()
33
  years = sorted(df["year"].unique())
34
 
35
+ # Widgets for selecting data parameters
36
+ year_slider = pn.widgets.IntRangeSlider(name="Year Range", start=df["year"].min(), end=df["year"].max())
 
37
  file_dropdown = pn.widgets.Select(name="File Selector")
38
+ longitude_slider = pn.widgets.RangeSlider(name="Longitude Range", start=-180, end=180, step=1)
39
+ latitude_slider = pn.widgets.RangeSlider(name="Latitude Range", start=-90, end=90, step=1)
40
+ depth_range_slider = pn.widgets.IntRangeSlider(start=100, end=300, value=(100, 300), step=1, name="Depth Range")
 
 
 
 
 
 
 
 
 
 
41
  depth_2_checkbox = pn.widgets.Checkbox(value=False, name="Depth 2 Checkbox")
42
  depth_3_checkbox = pn.widgets.Checkbox(value=False, name="Depth 3 Checkbox")
43
+ depth_2_range_slider = pn.widgets.IntRangeSlider(start=100, end=300, value=(100, 300), step=1, name="Depth 2 Range")
44
+ depth_3_range_slider = pn.widgets.IntRangeSlider(start=100, end=300, value=(100, 300), step=1, name="Depth 3 Range")
45
+ num_vectors_slider = pn.widgets.IntSlider(start=40, end=800, step=1, value=100, name="Number of Vectors")
46
+ scale_factor_slider = pn.widgets.FloatSlider(start=0.1, end=1, step=0.1, value=0.5, name="Scale Factor")
 
 
 
 
 
 
 
 
 
 
47
  bathy_checkbox = pn.widgets.Checkbox(value=False, name="Bathy Checkbox")
48
 
49
+
 
 
50
  data_table = pn.widgets.Tabulator(width=400, height=200)
 
51
  metadata_table = pn.widgets.Tabulator(width=600, height=800)
52
+ # Download button is not working : TODO
53
  download_button = pn.widgets.Button(name="Download", button_type="primary")
 
54
 
55
  def __init__(self, **params):
56
+ """
57
+ Initialize the SADCP_Viewer class.
58
+
59
+ Parameters:
60
+ **params: Additional parameters to be passed to the superclass.
61
+ """
62
+
63
  super(SADCP_Viewer, self).__init__(**params)
64
+ self.file_dropdown.objects = self.file_names
65
  self.file_dropdown.value = (
66
  self.file_dropdown.objects[0] if self.file_dropdown.objects else None
67
  )
 
69
 
70
  @param.depends("year_slider.value", "file_dropdown.value", watch=True)
71
  def update_name_options(self):
72
+ """
73
+ Update dropdown options and slider ranges based on selected years and file.
74
+
75
+ This function updates the dropdown options and slider ranges based on the selected years
76
+ and file. It also loads the selected file's data and adjusts slider ranges accordingly.
77
+
78
+ """
79
+ # Extract selected start and end years
80
  start_year, end_year = self.year_slider.value
81
+
82
+ # Filter DataFrame based on selected years and sort by year
83
  mask = (self.df["year"] >= start_year) & (self.df["year"] <= end_year)
84
  sorted_df = self.df[mask].sort_values(by="year")
85
+
86
+ # Get unique file names
87
  files = sorted_df["file_name"].unique().tolist()
88
+
89
+ # Update file dropdown options
90
  self.file_dropdown.options = files
91
+
92
  if files:
93
  selected_file = self.file_dropdown.value
94
+
95
+ # Set default selected file if not selected or not in options
96
  if not selected_file or selected_file not in files:
97
  selected_file = files[0]
98
  self.file_dropdown.value = selected_file
99
+
100
+ # Update data table and metadata table based on selected file
101
+ self.data_table.value, self.metadata_table.value = filter_df(sorted_df, selected_file)
102
+
103
+ # Load selected file's data
104
+ self.ds = load_file(self.tree,selected_file)
105
+
106
+ # Update slider ranges for longitude, latitude, and depth
107
+ for slider, coord in zip([self.longitude_slider, self.latitude_slider, self.depth_range_slider,
108
+ self.depth_2_range_slider, self.depth_3_range_slider],
109
+ [self.ds.LONGITUDE, self.ds.LATITUDE, self.ds.PROFZ,self.ds.PROFZ,self.ds.PROFZ]):
110
+ coord_range = get_range(coord)
111
+ slider.start, slider.end, slider.value = coord_range[0], coord_range[1], coord_range
112
+
113
+
114
+ # Close dataset to free up resources
115
+ # self.ds.close()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
 
117
  @param.depends(
118
  "year_slider.value",
 
120
  "depth_range_slider.value",
121
  "depth_2_checkbox.value",
122
  "depth_3_checkbox.value",
123
+ "depth_2_range_slider.value",
124
+ "depth_3_range_slider.value",
125
  "longitude_slider.value",
126
  "latitude_slider.value",
127
  "num_vectors_slider.value",
128
  "scale_factor_slider.value",
129
  "bathy_checkbox.value",
130
+ watch=False,)
 
131
  def update_plots(self):
132
+ """
133
+ This function updates the plots based on the selected data and parameters.
134
+
135
+ The function filters the data, generates additional plots, and updates the main vector plot based on the selected parameters.
136
+
137
+ Returns:
138
+ pn.Row: A Panel row containing the updated map plot and additional plots.
139
+
140
+ """
141
+ # Filter the data
142
+ self.ds_filtered = filter_data(self.ds,self.longitude_slider.value,self.latitude_slider.value)
143
+
144
+ # Prepare the plots shown in left
145
+ # Update vector plots
146
+ vector_plot = vectors_plot(self.ds_filtered, self.bathy,
147
+ self.longitude_slider.value, self.latitude_slider.value,
148
+ self.depth_range_slider.value, self.depth_2_range_slider.value, self.depth_3_range_slider.value,
149
+ self.scale_factor_slider.value,self.num_vectors_slider.value,
150
+ depth_2_checkbox= self.depth_2_checkbox.value,
151
+ depth_3_checkbox= self.depth_3_checkbox.value,
152
+ bathy_checkbox=self.bathy_checkbox.value,
153
+ )
154
+
155
+
156
+ # Generate plots which will be plotted on the left row.
157
+ self.plot_left = pn.Column(
158
+ # Here adjust the style option later TODO
159
+ # https://panel.holoviz.org/how_to/styling/matplotlib.html
160
+ pn.pane.Matplotlib(vector_plot, dpi=144),
161
+ # Add here the hvplot block of contour TODO
162
+ sizing_mode="stretch_both")
163
+
164
+ # Generate additional plots which will be plotted on the right row.
165
+ other_plots = bathy_uship_vship_bottom_depth(self.ds_filtered)
166
+ self.plot_right = pn.Column(
167
  *(pn.pane.HoloViews(plot, width=400, height=200) for plot in other_plots),
168
  sizing_mode="stretch_width"
169
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170
 
171
+ # Return a Panel row containing the updated map plot and additional plots
172
+ return pn.Row(self.plot_left, self.plot_right, sizing_mode="stretch_both")
173
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
174
 
175
+ pn.extension("tabulator")
176
+ pn.config.theme = 'dark'
177
 
178
  explorer = SADCP_Viewer()
179
  # Instantiate the SADCP_Viewer class and create a template
 
188
  )
189
 
190
  sidebar = [
191
+ pn.panel('./EuroGO-SHIP_logo_wide_tagline_1.2.png',width=300 ),
192
  """This application, developed in the frame of Euro Go Shop, helps to interactively visualise and download ship ADCP data.""",
193
  explorer.year_slider,
194
  explorer.file_dropdown,
 
198
  explorer.depth_range_slider,
199
  explorer.depth_2_checkbox,
200
  explorer.depth_3_checkbox,
201
+ explorer.depth_2_range_slider,
202
+ explorer.depth_3_range_slider,
203
  explorer.num_vectors_slider,
204
  explorer.scale_factor_slider,
205
  explorer.data_table,
206
+ """You can consult detailed information on this data in the metadata tab shown on the right.
207
+ To download full dataset, please go to https://cdi.seadatanet.org/search
208
+ and search with LOCAL_CDI_ID indicated above.""",
209
+ #pn.panel('https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png', ),
210
+ #width=10)
211
  ]
212
+
213
  template = pn.template.FastListTemplate(
214
+ title="SADCP data Viewer", logo='https://avatars.githubusercontent.com/u/123177533?s=200&v=4',
215
+ sidebar=sidebar, main=[tabs]
216
+
217
  )
218
  template.servable()
 
requirements.txt CHANGED
@@ -1,9 +1,7 @@
1
  panel
2
  jupyter
3
- transformers
4
  numpy
5
- torch
6
- aiohttp
7
  cartopy
8
  cftime
9
  hvplot
@@ -11,4 +9,5 @@ xarray==2024.2.0
11
  scipy
12
  matplotlib
13
  xarray-datatree
14
- zarr
 
 
1
  panel
2
  jupyter
 
3
  numpy
4
+ fsspec
 
5
  cartopy
6
  cftime
7
  hvplot
 
9
  scipy
10
  matplotlib
11
  xarray-datatree
12
+ zarr
13
+ lxml