|
| 1 | +# # Plotting ROMS results and input files |
| 2 | + |
| 3 | +#md # *The code here is also available as a notebook [04\_plots.ipynb](04_plots.ipynb).* |
| 4 | +# |
| 5 | +# The aim here is to visualize the model files with generic plotting and analsis packages rather than to use a model specific visualization tool which hides many details and might lack of flexibility. |
| 6 | +# The necessary files are already in the directory containing the model simulation and its |
| 7 | +# parent direction (`ROMS-implementation-test`). Downloading the files is only needed if you did not run the simulation. |
| 8 | + |
| 9 | +using Pkg |
| 10 | +Pkg.activate("makie",shared=true) |
| 11 | + |
| 12 | +grd_name = "roms_grd_liguriansea.nc" |
| 13 | + |
| 14 | +if !isfile(grd_name) |
| 15 | + download("https://dox.ulg.ac.be/index.php/s/J9DXhUPXbyLADJa/download",grd_name) |
| 16 | +end |
| 17 | + |
| 18 | +fname = "roms_his.nc" |
| 19 | +if !isfile(fname) |
| 20 | + download("https://dox.ulg.ac.be/index.php/s/17UWsY7tRNMDf4w/download",fname) |
| 21 | +end |
| 22 | + |
| 23 | +# ## Bathymetry |
| 24 | + |
| 25 | +# In this example, the bathymetry defined in the grid file is visualized. Make sure that your current working directory |
| 26 | +# contains the file `roms_grd_liguriansea.nc` (use e.g. `;cd ~/ROMS-implementation-test`) |
| 27 | + |
| 28 | +using ROMS, NCDatasets, GeoDatasets, Statistics |
| 29 | +using CairoMakie # GeoMakie, GLMakie |
| 30 | +using CairoMakie: Point2f0 |
| 31 | + |
| 32 | +ds_grid = NCDataset("roms_grd_liguriansea.nc"); |
| 33 | +lon = ds_grid["lon_rho"][:,:]; |
| 34 | +lat = ds_grid["lat_rho"][:,:]; |
| 35 | +h = ds_grid["h"][:,:] |
| 36 | +mask_rho = ds_grid["mask_rho"][:,:]; |
| 37 | + |
| 38 | +hmask = copy(h) |
| 39 | +hmask[mask_rho .== 0] .= missing; |
| 40 | + |
| 41 | +fig = Figure(); |
| 42 | +ga = Axis(fig[1, 1]; title = "smoothed bathymetry [m]", |
| 43 | + aspect = AxisAspect(1/cosd(mean(lat)))); |
| 44 | +surf = surface!(ga,lon,lat,hmask, shading = NoShading, interpolate = false); |
| 45 | +Colorbar(fig[1,2],surf) |
| 46 | +xlims!(ga,extrema(lon)) |
| 47 | +ylims!(ga,extrema(lat)) |
| 48 | +save("smoothed_bathymetry.png",fig); nothing # hide |
| 49 | + |
| 50 | +#md #  |
| 51 | + |
| 52 | +# ## Surface temperature |
| 53 | + |
| 54 | +# The surface surface temperature (or salinity) of the model output or |
| 55 | +# climatology file can be visualized as follows. |
| 56 | +# The parameter `n` is the time instance to plot. |
| 57 | +# Make sure that your current working directory |
| 58 | +# contains the file to plot (use e.g. `;cd ~/ROMS-implementation-test/` to plot `roms_his.nc`) |
| 59 | + |
| 60 | + |
| 61 | +## instance to plot |
| 62 | +n = 1 |
| 63 | + |
| 64 | +ds = NCDataset("roms_his.nc") |
| 65 | +temp = ds["temp"][:,:,end,n] |
| 66 | +temp[mask_rho .== 0] .= missing; |
| 67 | + |
| 68 | +if haskey(ds,"time") |
| 69 | + ## for the climatology file |
| 70 | + time = ds["time"][:] |
| 71 | +else |
| 72 | + ## for ROMS output |
| 73 | + time = ds["ocean_time"][:] |
| 74 | +end |
| 75 | + |
| 76 | +fig = Figure() |
| 77 | +ga = Axis(fig[1, 1]; title = "sea surface temperature [degree C]") |
| 78 | +surf = surface!(ga,lon,lat,temp, shading = NoShading, interpolate = false); |
| 79 | +Colorbar(fig[1,2],surf); |
| 80 | +xlims!(ga,extrema(lon)) |
| 81 | +ylims!(ga,extrema(lat)) |
| 82 | +save("SST.png",fig); nothing # hide |
| 83 | + |
| 84 | +#md #  |
| 85 | + |
| 86 | +# Exercise: |
| 87 | +# * Plot salinity |
| 88 | +# * Plot different time instance (`n`) |
| 89 | +# * Where do we specify that the surface values are to be plotted? Plot different layers. |
| 90 | + |
| 91 | + |
| 92 | +# ## Surface velocity and elevation |
| 93 | + |
| 94 | +zeta = nomissing(ds["zeta"][:,:,n],NaN) |
| 95 | +u = nomissing(ds["u"][:,:,end,n],NaN); |
| 96 | +v = nomissing(ds["v"][:,:,end,n],NaN); |
| 97 | + |
| 98 | +mask_u = ds_grid["mask_u"][:,:]; |
| 99 | +mask_v = ds_grid["mask_v"][:,:]; |
| 100 | + |
| 101 | +u[mask_u .== 0] .= NaN; |
| 102 | +v[mask_v .== 0] .= NaN; |
| 103 | +zeta[mask_rho .== 0] .= NaN; |
| 104 | + |
| 105 | +## ROMS uses an Arakawa C grid |
| 106 | +u_r = cat(u[1:1,:], (u[2:end,:] .+ u[1:end-1,:])/2, u[end:end,:], dims=1); |
| 107 | +v_r = cat(v[:,1:1], (v[:,2:end] .+ v[:,1:end-1])/2, v[:,end:end], dims=2); |
| 108 | + |
| 109 | +## all sizes should be the same |
| 110 | +size(u_r), size(v_r), size(mask_rho) |
| 111 | + |
| 112 | +fig = Figure(); |
| 113 | +ga = Axis(fig[1, 1]; title = "surface currents [m/s] and elevation [m]", |
| 114 | + aspect = AxisAspect(1/cosd(mean(lat)))); |
| 115 | +surf = surface!(ga,lon,lat,zeta, shading = NoShading, interpolate = false); |
| 116 | +Colorbar(fig[1,2],surf); |
| 117 | +## plot only a single arrow for r x r grid cells |
| 118 | +r = 3; |
| 119 | +i = 1:r:size(lon,1); |
| 120 | +j = 1:r:size(lon,2); |
| 121 | +s = 0.6; |
| 122 | +arrows!(ga,lon[i,j][:],lat[i,j][:],s*u_r[i,j][:],s*v_r[i,j][:]); |
| 123 | +i=j=5; |
| 124 | +arrows!(ga,[11],[44],[s*1],[0]); |
| 125 | +text!(ga,[11],[44],text="1 m/s") |
| 126 | +xlims!(ga,extrema(lon)) |
| 127 | +ylims!(ga,extrema(lat)) |
| 128 | +save("surface_zeta_uv.png",fig); nothing # hide |
| 129 | + |
| 130 | +#md #  |
| 131 | + |
| 132 | +# Exercise: |
| 133 | +# * The surface currents seems to follow lines of constant surface elevation. Explain why this is to be expected. |
| 134 | + |
| 135 | +# ## Vertical section |
| 136 | + |
| 137 | +# In this example we will plot a vertical section by slicing the |
| 138 | +# model output at a given index. |
| 139 | + |
| 140 | +# It is very important that the parameters (`opt`) defining the vertical layer match the parameters values choosen when ROMS was setup. |
| 141 | + |
| 142 | +opt = ( |
| 143 | + Tcline = 50, # m |
| 144 | + theta_s = 5, # surface refinement |
| 145 | + theta_b = 0.4, # bottom refinement |
| 146 | + nlevels = 32, # number of vertical levels |
| 147 | + Vtransform = 2, |
| 148 | + Vstretching = 4, |
| 149 | +) |
| 150 | + |
| 151 | +hmin = minimum(h) |
| 152 | +hc = min(hmin,opt.Tcline) |
| 153 | +z_r = ROMS.set_depth(opt.Vtransform, opt.Vstretching, |
| 154 | + opt.theta_s, opt.theta_b, hc, opt.nlevels, |
| 155 | + 1, h); |
| 156 | + |
| 157 | +temp = nomissing(ds["temp"][:,:,:,n],NaN); |
| 158 | + |
| 159 | +mask3 = repeat(mask_rho,inner=(1,1,opt.nlevels)) |
| 160 | +lon3 = repeat(lon,inner=(1,1,opt.nlevels)) |
| 161 | +lat3 = repeat(lat,inner=(1,1,opt.nlevels)) |
| 162 | + |
| 163 | +temp[mask3 .== 0] .= NaN; |
| 164 | + |
| 165 | +i = 20; |
| 166 | + |
| 167 | +fig = Figure(); |
| 168 | +ga = Axis(fig[1, 1]; title = "temperature at $(round(lon[i,1],sigdigits=4)) °E", |
| 169 | + xlabel = "latitude", |
| 170 | + ylabel = "depth [m]", |
| 171 | + backgroundcolor=:white, |
| 172 | + ); |
| 173 | +surf = surface!(ga,lat3[i,:,:],z_r[i,:,:],temp[i,:,:],shading = NoShading, interpolate = false); |
| 174 | +xlims!(ga,extrema(lat3[i,:,:])) |
| 175 | +ylims!(ga,-300,0); |
| 176 | +Colorbar(fig[1,2],surf); |
| 177 | +ax2 = Axis( |
| 178 | + fig[1, 1], |
| 179 | + width = Relative(0.4), |
| 180 | + height = Relative(0.3), |
| 181 | + halign = 0.13, |
| 182 | + valign = 0.18, |
| 183 | + aspect = AxisAspect(1/cosd(mean(lat))), |
| 184 | + backgroundcolor=:white); |
| 185 | +## inset plot |
| 186 | +poly!(ax2,Point2f0[(lon[1,1], lat[1,1]), (lon[1,1], lat[1,end]), (lon[end,1], lat[1,end]), (lon[end,1], lat[1,1])], color = [:white, :white, :white, :white]) |
| 187 | +surf = surface!(ax2,lon[:,1],lat[1,:],temp[:,:,end], shading = NoShading, interpolate = false); |
| 188 | +#ax2.pcolormesh(lon,lat,temp[:,:,end]) |
| 189 | +#ax2.set_aspect(1/cosd(mean(lat))) |
| 190 | +lines!(ax2,lon[i,[1,end]],lat[i,[1,end]],color="magenta") |
| 191 | +xlims!(ax2,extrema(lon)) |
| 192 | +ylims!(ax2,extrema(lat)) |
| 193 | + |
| 194 | +save("temp_section1.png",fig); |
| 195 | + |
| 196 | +#md #  |
| 197 | + |
| 198 | +# Exercise: |
| 199 | +# * Plot a section at different longitude and latitude |
| 200 | + |
| 201 | +# ## Horizontal section |
| 202 | + |
| 203 | +# A horizontal at the fixed depth of 200 m is extracted and plotted. |
| 204 | + |
| 205 | +tempi = ROMS.model_interp3(lon,lat,z_r,temp,lon,lat,[-200]) |
| 206 | +mlon,mlat,mdata = GeoDatasets.landseamask(resolution='f', grid=1.25) |
| 207 | + |
| 208 | +ii = findall(minimum(lon) .<= mlon .<= maximum(lon)) |
| 209 | +jj = findall(minimum(lat) .<= mlat .<= maximum(lat)) |
| 210 | + |
| 211 | +mlon = mlon[ii] |
| 212 | +mlat = mlat[jj] |
| 213 | +mdata = mdata[ii,jj] |
| 214 | + |
| 215 | +fig = Figure(); |
| 216 | +ga = Axis(fig[1, 1]; title = "temperature at 200 m [°C]", |
| 217 | + xlabel = "longitude", |
| 218 | + ylabel = "latitude", |
| 219 | + ); |
| 220 | +surf = surface!(ga,lon,lat,tempi[:,:,1],shading = NoShading, interpolate = false); |
| 221 | +Colorbar(fig[1,2],surf); |
| 222 | +contourf!(ga,mlon,mlat,mdata,levels=[0.5, 3],colormap=[:grey]) |
| 223 | +xlims!(ga,extrema(lon)) |
| 224 | +ylims!(ga,extrema(lat)) |
| 225 | +fig |
| 226 | + |
| 227 | +save("temp_hsection_200.png",fig); |
| 228 | + |
| 229 | +#md #  |
| 230 | + |
| 231 | +# ## Arbitrary vertical section |
| 232 | + |
| 233 | +# The vectors `section_lon` and `section_lat` define the coordinates where we want to extract |
| 234 | +# the surface temperature. |
| 235 | + |
| 236 | + |
| 237 | +section_lon = LinRange(8.18, 8.7,100); |
| 238 | +section_lat = LinRange(43.95, 43.53,100); |
| 239 | + |
| 240 | +using Interpolations |
| 241 | + |
| 242 | +function section_interp(v) |
| 243 | + itp = interpolate((lon[:,1],lat[1,:]),v,Gridded(Linear())) |
| 244 | + return itp.(section_lon,section_lat) |
| 245 | +end |
| 246 | + |
| 247 | +section_temp = mapslices(section_interp,temp,dims=(1,2)) |
| 248 | +section_z = mapslices(section_interp,z_r,dims=(1,2)) |
| 249 | +section_x = repeat(section_lon,inner=(1,size(temp,3))) |
| 250 | + |
| 251 | + |
| 252 | +fig = Figure(); |
| 253 | +ga = Axis(fig[1, 1]; title = "temperature section [°C]", |
| 254 | + xlabel = "longitude", |
| 255 | + ylabel = "depth", |
| 256 | + ); |
| 257 | +surf = surface!(ga,section_x,section_z[:,1,:],section_temp[:,1,:],shading = NoShading, interpolate = false) |
| 258 | +ylims!(ga,-500,0) |
| 259 | +Colorbar(fig[1,2],surf); |
| 260 | +## inset plot |
| 261 | +ax2 = Axis( |
| 262 | + fig[1, 1], |
| 263 | + width = Relative(0.4), |
| 264 | + height = Relative(0.3), |
| 265 | + halign = 0.6, |
| 266 | + valign = 0.18, |
| 267 | + aspect = AxisAspect(1/cosd(mean(lat))), |
| 268 | + backgroundcolor=:white); |
| 269 | +poly!(ax2,Point2f0[(lon[1,1], lat[1,1]), (lon[1,1], lat[1,end]), (lon[end,1], lat[1,end]), (lon[end,1], lat[1,1])], color = [:white, :white, :white, :white]) |
| 270 | +surf = surface!(ax2,lon[:,1],lat[1,:],temp[:,:,end], shading = NoShading, interpolate = false); |
| 271 | +xlims!(ax2,extrema(lon)) |
| 272 | +ylims!(ax2,extrema(lat)) |
| 273 | +fig |
| 274 | + |
| 275 | +save("temp_vsection.png",fig); |
| 276 | + |
| 277 | +#md #  |
0 commit comments