99import progressbar
1010import xarray
1111from matplotlib .collections import PatchCollection
12- from matplotlib .colors import LogNorm
12+ from matplotlib .colors import LogNorm , SymLogNorm
1313from matplotlib .patches import Polygon
1414
1515
@@ -77,7 +77,7 @@ def __init__(self, inFolder='.', outFolder='plots', expt='Ocean0',
7777
7878 plt .switch_backend ('Agg' )
7979
80- def plot_melt_time_series (self , sshMax = None ):
80+ def plot_melt_time_series (self , sshMax = None , wctMax = None ):
8181 """
8282 Plot a series of image for each of several variables related to melt
8383 at the ice shelf-ocean interface: mean melt rate, total melt flux,
@@ -89,21 +89,28 @@ def plot_melt_time_series(self, sshMax=None):
8989 rho_fw = 1000.
9090 secPerYear = 365 * 24 * 60 * 60
9191
92+ suffix = ''
9293 areaCell = self .dsMesh .areaCell
9394 iceMask = self .ds .timeMonthly_avg_landIceFraction
9495 meltFlux = self .ds .timeMonthly_avg_landIceFreshwaterFlux
9596 if sshMax is not None :
9697 ssh = self .ds .timeMonthly_avg_ssh
9798 iceMask = iceMask .where (ssh < sshMax )
99+ suffix = f'_sshMax{ sshMax } '
100+ elif wctMax is not None :
101+ H = self .ds .timeMonthly_avg_layerThickness .sum (dim = 'nVertLevels' )
102+ iceMask = iceMask .where (H < wctMax )
103+ suffix = f'_wctMax{ wctMax } '
98104
99105 totalMeltFlux = (meltFlux * areaCell * iceMask ).sum (dim = 'nCells' )
100106 totalArea = (areaCell * iceMask ).sum (dim = 'nCells' )
101107 meanMeltRate = totalMeltFlux / totalArea / rho_fw * secPerYear
102108 self .plot_time_series (meanMeltRate , 'mean melt rate' , 'meanMeltRate' ,
103109 'm/yr' )
110+ print (meanMeltRate .values )
104111
105112 self .plot_time_series (1e-6 * totalMeltFlux , 'total melt flux' ,
106- 'totalMeltFlux' , 'kT/yr' )
113+ f 'totalMeltFlux{ suffix } ' , 'kT/yr' )
107114
108115 prefix = 'timeMonthly_avg_landIceBoundaryLayerTracers_'
109116 boundary_layer_temperature = \
@@ -115,13 +122,13 @@ def plot_melt_time_series(self, sshMax=None):
115122 da = (da * areaCell * iceMask ).sum (dim = 'nCells' ) / totalArea
116123
117124 self .plot_time_series (da , 'mean thermal driving' ,
118- 'meanThermalDriving' , 'deg C' )
125+ f 'meanThermalDriving{ suffix } ' , 'deg C' )
119126
120127 da = self .ds .timeMonthly_avg_landIceFrictionVelocity
121128 da = (da * areaCell * iceMask ).sum (dim = 'nCells' ) / totalArea
122129
123130 self .plot_time_series (da , 'mean friction velocity' ,
124- 'meanFrictionVelocity' , 'm/s' )
131+ f 'meanFrictionVelocity{ suffix } ' , 'm/s' )
125132
126133 def plot_time_series (self , da , nameInTitle , prefix , units = None ,
127134 figsize = (12 , 6 ), color = None , overwrite = True ):
@@ -344,7 +351,7 @@ def plot_overturning_streamfunction(self, vmin=-0.3, vmax=0.3):
344351 if self .showProgress :
345352 bar .finish ()
346353
347- def plot_melt_rates (self , vmin = - 100 . , vmax = 100 . ):
354+ def plot_melt_rates (self , vmin = 0 . , vmax = 50 . ):
348355 """
349356 Plot a series of image of the melt rate
350357
@@ -363,7 +370,7 @@ def plot_melt_rates(self, vmin=-100., vmax=100.):
363370
364371 self .plot_horiz_series (da , 'melt rate' , prefix = 'meltRate' ,
365372 oceanDomain = False , units = 'm/yr' , vmin = vmin ,
366- vmax = vmax , cmap = 'cmo.curl ' )
373+ vmax = vmax , cmap = 'cmo.amp ' )
367374
368375 def plot_ice_shelf_boundary_variables (self ):
369376 """
@@ -401,7 +408,7 @@ def plot_ice_shelf_boundary_variables(self):
401408 self .plot_horiz_series (da , 'thermal driving' ,
402409 prefix = 'thermalDriving' ,
403410 oceanDomain = False , units = 'deg C' ,
404- vmin = - 2 , vmax = 2 , cmap = 'cmo.thermal ' )
411+ vmin = - 2 , vmax = 2 , cmap = 'cmo.curl ' )
405412
406413 da = boundary_layer_salinity - interface_salinity
407414 self .plot_horiz_series (da , 'haline driving' ,
@@ -412,8 +419,9 @@ def plot_ice_shelf_boundary_variables(self):
412419 self .plot_horiz_series (self .ds .timeMonthly_avg_landIceFrictionVelocity ,
413420 'friction velocity' ,
414421 prefix = 'frictionVelocity' ,
415- oceanDomain = True , units = 'm/s' ,
416- vmin = 0 , vmax = 0.05 , cmap = 'cmo.speed' )
422+ oceanDomain = False , units = 'm/s' ,
423+ vmin = 1.e-4 , vmax = 1.e-1 , cmap = 'cmo.speed' ,
424+ cmap_scale = 'log' )
417425
418426 def plot_temperature (self ):
419427 """
@@ -438,8 +446,8 @@ def plot_salinity(self):
438446 self .plot_3d_field_top_bot_section (da ,
439447 nameInTitle = 'salinity' ,
440448 prefix = 'Salinity' , units = 'PSU' ,
441- vmin = 33.8 , vmax = 34.7 ,
442- cmap = 'cmo.haline' )
449+ vmin = 1. , vmax = 34.6 ,
450+ cmap = 'cmo.haline' , cmap_scale = 'log' )
443451
444452 def plot_potential_density (self ):
445453 """
@@ -478,7 +486,7 @@ def plot_horiz_series(self, da, nameInTitle, prefix, oceanDomain,
478486 units = None , vmin = None , vmax = None , cmap = None ,
479487 cmap_set_under = None , cmap_set_over = None ,
480488 cmap_scale = 'linear' , time_indices = None ,
481- figsize = (9 , 3 )):
489+ figsize = (9 , 3 ), contour_field = None ):
482490 """
483491 Plot a series of image of a given variable
484492
@@ -533,6 +541,8 @@ def plot_horiz_series(self, da, nameInTitle, prefix, oceanDomain,
533541 for tIndex in time_indices :
534542 self .update_date (tIndex )
535543 field = da .isel (Time = tIndex ).values
544+ if contour_field is not None :
545+ contour_field = contour_field .isel (Time = tIndex ).values
536546 outFileName = '{}/{}/{}_{:04d}.png' .format (
537547 self .outFolder , prefix , prefix , tIndex + 1 )
538548 if units is None :
@@ -544,15 +554,17 @@ def plot_horiz_series(self, da, nameInTitle, prefix, oceanDomain,
544554 vmax = vmax , cmap = cmap ,
545555 cmap_set_under = cmap_set_under ,
546556 cmap_set_over = cmap_set_over ,
547- cmap_scale = cmap_scale , figsize = figsize )
557+ cmap_scale = cmap_scale , figsize = figsize ,
558+ contour_field = contour_field )
548559 if self .showProgress :
549560 bar .update (tIndex + 1 )
550561 if self .showProgress :
551562 bar .finish ()
552563
553564 def plot_3d_field_top_bot_section (self , da , nameInTitle , prefix ,
554565 units = None , vmin = None , vmax = None ,
555- cmap = None , cmap_set_under = None ,
566+ cmap = None , cmap_scale = 'linear' ,
567+ cmap_set_under = None ,
556568 cmap_set_over = None ):
557569 """
558570 Plot a series of images of a given 3D variable showing the value
@@ -608,6 +620,7 @@ def plot_3d_field_top_bot_section(self, da, nameInTitle, prefix,
608620 'top {}' .format (nameInTitle ),
609621 'top{}' .format (prefix ), oceanDomain = True ,
610622 vmin = vmin , vmax = vmax , cmap = cmap ,
623+ cmap_scale = cmap_scale ,
611624 cmap_set_under = cmap_set_under ,
612625 cmap_set_over = cmap_set_over )
613626
@@ -630,7 +643,8 @@ def plot_3d_field_top_bot_section(self, da, nameInTitle, prefix,
630643 self .plot_horiz_series (daBot ,
631644 'bot {}' .format (nameInTitle ),
632645 'bot{}' .format (prefix ), oceanDomain = True ,
633- vmin = vmin , vmax = vmax , cmap = cmap )
646+ vmin = vmin , vmax = vmax , cmap_scale = cmap_scale ,
647+ cmap = cmap )
634648
635649 daSection = da .isel (nCells = self .sectionCellIndices )
636650
@@ -659,7 +673,8 @@ def plot_3d_field_top_bot_section(self, da, nameInTitle, prefix,
659673 self ._plot_vert_field (self .X , self .Z [tIndex , :, :],
660674 field , title = title ,
661675 outFileName = outFileName ,
662- vmin = vmin , vmax = vmax , cmap = cmap )
676+ vmin = vmin , vmax = vmax , cmap = cmap ,
677+ show_boundaries = False , cmap_scale = cmap_scale )
663678 if self .showProgress :
664679 bar .update (tIndex + 1 )
665680 if self .showProgress :
@@ -718,6 +733,7 @@ def plot_layer_interfaces(self, figsize=(9, 5)):
718733 plt .plot (1e-3 * X [z_index , :], Z [z_index , :], 'k' )
719734 plt .plot (1e-3 * X [0 , :], Z [0 , :], 'b' )
720735 plt .plot (1e-3 * X [0 , :], self .zBotSection , 'g' )
736+ plt .plot (1e-3 * X [0 , :], self .landIceDraft , 'r' )
721737
722738 ax .autoscale (tight = True )
723739 x1 , x2 , y1 , y2 = 420 , 470 , - 650 , - 520
@@ -729,6 +745,7 @@ def plot_layer_interfaces(self, figsize=(9, 5)):
729745 axins .plot (1e-3 * X [z_index , :], Z [z_index , :], 'k' )
730746 axins .plot (1e-3 * X [0 , :], Z [0 , :], 'b' )
731747 axins .plot (1e-3 * X [0 , :], self .zBotSection , 'g' )
748+ axins .plot (1e-3 * X [0 , :], self .landIceDraft , 'r' )
732749 axins .set_xlim (x1 , x2 )
733750 axins .set_ylim (y1 , y2 )
734751 axins .set_xticklabels ([])
@@ -793,7 +810,7 @@ def update_date(self, tIndex):
793810 def _plot_horiz_field (self , field , title , outFileName , oceanDomain = True ,
794811 vmin = None , vmax = None , figsize = (9 , 3 ), cmap = None ,
795812 cmap_set_under = None , cmap_set_over = None ,
796- cmap_scale = 'linear' ):
813+ cmap_scale = 'linear' , contour_field = None ):
797814
798815 try :
799816 os .makedirs (os .path .dirname (outFileName ))
@@ -824,10 +841,21 @@ def _plot_horiz_field(self, field, title, outFileName, oceanDomain=True,
824841 if cmap_scale == 'log' :
825842 localPatches .set_norm (LogNorm (vmin = max (1e-10 , vmin ),
826843 vmax = vmax , clip = False ))
844+ elif cmap_scale == 'symlog' :
845+ localPatches .set_norm (SymLogNorm (vmin = vmin , vmax = vmax , clip = False ,
846+ linthresh = vmax / 1e2 ))
827847
828848 plt .figure (figsize = figsize )
829849 ax = plt .subplot (111 )
830850 ax .add_collection (localPatches )
851+ if contour_field is not None :
852+ dsMesh = self .dsMesh
853+ ax .tricontour (dsMesh .xCell / 1.e3 , dsMesh .yCell / 1.e3 ,
854+ contour_field ,
855+ colors = 'k' , levels = [1.1e-2 + 1.e-8 ])
856+ ax .tricontour (dsMesh .xCell / 1.e3 , dsMesh .yCell / 1.e3 ,
857+ contour_field ,
858+ colors = 'grey' , levels = numpy .arange (50. , 700. , 50. ))
831859 plt .colorbar (localPatches , extend = 'both' )
832860 plt .axis ([0 , 500 , 0 , 1000 ])
833861 ax .set_aspect ('equal' )
@@ -839,7 +867,7 @@ def _plot_horiz_field(self, field, title, outFileName, oceanDomain=True,
839867
840868 def _plot_vert_field (self , inX , inZ , field , title , outFileName ,
841869 vmin = None , vmax = None , figsize = (9 , 5 ), cmap = None ,
842- show_boundaries = True ):
870+ show_boundaries = True , cmap_scale = 'linear' ):
843871 try :
844872 os .makedirs (os .path .dirname (outFileName ))
845873 except OSError :
@@ -850,24 +878,40 @@ def _plot_vert_field(self, inX, inZ, field, title, outFileName,
850878
851879 plt .figure (figsize = figsize )
852880 ax = plt .subplot (111 )
853- if show_boundaries :
854- z_mask = numpy .ones (self .X .shape )
855- z_mask [0 :- 1 , 0 :- 1 ] *= numpy .where (self .sectionMask , 1. , numpy .nan )
881+ z_mask = numpy .ones (self .X .shape )
882+ z_mask [0 :- 1 , 0 :- 1 ] *= numpy .where (self .sectionMask , 1. , numpy .nan )
856883
857- tIndex = 0
858- Z = numpy .array (self .Z [tIndex , :, :])
859- Z *= z_mask
860- X = self .X
884+ tIndex = 0
885+ Z = numpy .array (self .Z [tIndex , :, :])
886+ Z *= z_mask
887+ X = self .X
861888
862- plt .fill_between (1e-3 * X [0 , :], self .zBotSection , y2 = 0 ,
863- facecolor = 'lightsteelblue' , zorder = 2 )
864- plt .fill_between (1e-3 * X [0 , :], self .zBotSection , y2 = - 750 ,
865- facecolor = 'grey' , zorder = 1 )
889+ plt .fill_between (1e-3 * X [0 , :], self .zBotSection , y2 = 0 ,
890+ facecolor = 'lightsteelblue' , zorder = 2 )
891+ plt .fill_between (1e-3 * X [0 , :], self .zBotSection , y2 = - 750 ,
892+ facecolor = 'grey' , zorder = 1 )
893+ if show_boundaries :
866894 for z_index in range (1 , X .shape [0 ]):
867895 plt .plot (1e-3 * X [z_index , :], Z [z_index , :], 'k' , zorder = 4 )
868896 plt .pcolormesh (1e-3 * inX , inZ , field , vmin = vmin , vmax = vmax , cmap = cmap ,
869897 zorder = 3 )
870898 plt .colorbar ()
899+ x1 , x2 , y1 , y2 = 455 , 470 , - 640 , - 540
900+ axins = ax .inset_axes ([0.01 , 0.6 , 0.3 , 0.39 ])
901+ axins .fill_between (1e-3 * X [0 , :], self .zBotSection , y2 = 0 ,
902+ facecolor = 'lightsteelblue' , zorder = 2 )
903+ axins .fill_between (1e-3 * X [0 , :], self .zBotSection , y2 = - 750 ,
904+ facecolor = 'grey' , zorder = 1 )
905+ if show_boundaries :
906+ for z_index in range (1 , X .shape [0 ]):
907+ axins .plot (1e-3 * X [z_index , :], Z [z_index , :], 'k' , zorder = 4 )
908+ axins .pcolormesh (1e-3 * inX , inZ , field , vmin = vmin , vmax = vmax ,
909+ cmap = cmap , zorder = 3 )
910+ axins .set_xlim (x1 , x2 )
911+ axins .set_ylim (y1 , y2 )
912+ axins .set_xticklabels ([])
913+ axins .set_yticklabels ([])
914+ ax .indicate_inset_zoom (axins , edgecolor = "black" )
871915 ax .autoscale (tight = True )
872916 plt .ylim ([numpy .amin (inZ ), 20 ])
873917 plt .xlim ([400 , 800 ])
@@ -918,6 +962,15 @@ def _compute_section_x_z(self):
918962 layerThickness [:, zIndex ])
919963 self .Z [tIndex , zIndex , :] = self .Z [tIndex , zIndex + 1 , :] + \
920964 layerThicknessSection
965+ if 'timeMonthly_avg_landIceDraft' in self .ds :
966+ var = 'timeMonthly_avg_landIceDraft'
967+ else :
968+ var = 'landIceDraft'
969+ landIceDraft = self .ds [var ].isel (
970+ Time = tIndex , nCells = self .sectionCellIndices )
971+ landIceDraft = landIceDraft .values * self .sectionMask [0 , :].T
972+ landIceDraft = numpy .nan_to_num (landIceDraft )
973+ self .landIceDraft = _interp_extrap_corner (landIceDraft )
921974
922975
923976def _compute_cell_patches (dsMesh , mask ):
0 commit comments