Mercurial > repos > climate > psy_maps
comparison psymap_simple.py @ 2:e6d1e9d6b399 draft
planemo upload for repository https://github.com/NordicESMhub/galaxy-tools/tree/master/tools/psy-maps commit d330adb8ea0000ffb2e1dcc2346fd34409f6618e
| author | climate |
|---|---|
| date | Thu, 26 Sep 2024 10:32:08 +0000 |
| parents | 706666d912d5 |
| children |
comparison
equal
deleted
inserted
replaced
| 1:706666d912d5 | 2:e6d1e9d6b399 |
|---|---|
| 2 # | 2 # |
| 3 # | 3 # |
| 4 # usage: psymap_simple.py [-h] [--proj PROJ] | 4 # usage: psymap_simple.py [-h] [--proj PROJ] |
| 5 # [--cmap CMAP] | 5 # [--cmap CMAP] |
| 6 # [--output OUTPUT] | 6 # [--output OUTPUT] |
| 7 # [-l] | |
| 7 # [-v] | 8 # [-v] |
| 8 # input varname | 9 # input varname |
| 9 # | 10 # |
| 10 # positional arguments: | 11 # positional arguments: |
| 11 # input input filename with geographical coordinates (netCDF | 12 # input input filename with geographical coordinates (netCDF |
| 12 # format) | 13 # format) |
| 13 # varname Specify which variable to plot (case sensitive) | 14 # varname Specify which variable to plot (case sensitive) |
| 14 # | 15 # |
| 15 # optional arguments: | 16 # optional arguments: |
| 16 # -h, --help show this help message and exit | 17 # -h, --help show this help message and exit |
| 18 # -l, --logscale log scale the data | |
| 17 # --proj PROJ Specify the projection on which we draw | 19 # --proj PROJ Specify the projection on which we draw |
| 18 # --cmap CMAP Specify which colormap to use for plotting | 20 # --cmap CMAP Specify which colormap to use for plotting |
| 19 # --output OUTPUT output filename to store resulting image (png format) | 21 # --output OUTPUT output filename to store resulting image (png format) |
| 20 # --time TIMES time index from the file for multiple plots ("0 1 2 3") | 22 # --time TIMES time index from the file for multiple plots ("0 1 2 3") |
| 21 # --nrow NROW number of rows for multiple plot grid | 23 # --nrow NROW number of rows for multiple plot grid |
| 24 # --title plot or subplot title | 26 # --title plot or subplot title |
| 25 # -v, --verbose switch on verbose mode | 27 # -v, --verbose switch on verbose mode |
| 26 # | 28 # |
| 27 | 29 |
| 28 import argparse | 30 import argparse |
| 31 import math | |
| 29 import warnings | 32 import warnings |
| 30 from pathlib import Path | 33 from pathlib import Path |
| 31 | 34 |
| 32 import matplotlib as mpl | 35 import matplotlib as mpl |
| 36 import psyplot.project as psy # noqa: I202,E402 | |
| 37 import xarray | |
| 38 | |
| 33 mpl.use('Agg') | 39 mpl.use('Agg') |
| 34 from matplotlib import pyplot # noqa: I202,E402 | 40 from matplotlib import pyplot # noqa: I202,E402 |
| 35 | |
| 36 import psyplot.project as psy # noqa: I202,E402 | |
| 37 from psyplot import rcParams # noqa: I202,E402 | 41 from psyplot import rcParams # noqa: I202,E402 |
| 38 | 42 |
| 39 | 43 |
| 40 class PsyPlot (): | 44 class PsyPlot (): |
| 41 def __init__(self, input, proj, varname, cmap, output, verbose=False, | 45 def __init__(self, input, varname, output=None, logscale=False, cmap=None, |
| 42 time=[], nrow=1, ncol=1, format="%B %e, %Y", | 46 proj=None, verbose=False, time=None, nrow=None, ncol=None, |
| 43 title=""): | 47 format=None, title=None): |
| 44 self.input = input | 48 self.input = input |
| 45 self.proj = proj | |
| 46 self.varname = varname | 49 self.varname = varname |
| 47 self.cmap = cmap | 50 if proj is None or proj == "": |
| 48 self.time = time | 51 self.proj = "cyl" |
| 52 else: | |
| 53 self.proj = proj | |
| 54 self.cmap = cmap if cmap is not None else "jet" | |
| 55 self.time = time if time is not None else [] | |
| 56 self.ncol = int(ncol) if ncol is not None else int(1) | |
| 57 self.nrow = int(nrow) if nrow is not None else int(1) | |
| 58 | |
| 59 # Open dataset | |
| 60 ds = xarray.open_dataset(input)[varname] | |
| 61 minv = math.log2(ds.data.min()) | |
| 62 maxv = math.log2(ds.data.max()) | |
| 63 if title is not None: | |
| 64 self.title = title | |
| 65 else: | |
| 66 self.title = ds.long_name | |
| 67 if len(self.title) > 60: | |
| 68 self.title = ds.standard_name | |
| 69 del ds | |
| 70 | |
| 71 if logscale: | |
| 72 # Check that data range is sufficient for log scaling | |
| 73 if maxv < (minv * (10.0 ** 2.0)): | |
| 74 print("Not possible to log scale, switching to linear scale") | |
| 75 self.bounds = None | |
| 76 else: | |
| 77 self.bounds = ['log', 2] | |
| 78 else: | |
| 79 self.bounds = None | |
| 49 if format is None: | 80 if format is None: |
| 50 self.format = "" | 81 self.format = "" |
| 51 else: | 82 else: |
| 52 self.format = format.replace('X', '%') | 83 self.format = "%B %e, %Y" |
| 53 if title is None: | |
| 54 self.title = "" | |
| 55 else: | |
| 56 self.title = title | |
| 57 if ncol is None: | |
| 58 self.ncol = 1 | |
| 59 else: | |
| 60 self.ncol = int(ncol) | |
| 61 if nrow is None: | |
| 62 self.nrow = 1 | |
| 63 else: | |
| 64 self.nrow = int(nrow) | |
| 65 if output is None: | 84 if output is None: |
| 66 self.output = Path(input).stem + '.png' | 85 self.output = Path(input).stem + '.png' |
| 67 else: | 86 else: |
| 68 self.output = output | 87 self.output = output |
| 69 self.verbose = verbose | |
| 70 if verbose: | 88 if verbose: |
| 71 print("input: ", self.input) | 89 print("input: ", self.input) |
| 72 print("proj: ", self.proj) | 90 print("proj: ", self.proj) |
| 73 print("varname: ", self.varname) | 91 print("varname: ", self.varname) |
| 74 print("cmap: ", self.cmap) | 92 print("cmap: ", self.cmap) |
| 75 print("time: ", self.time) | 93 print("time: ", self.time) |
| 76 print("ncol: ", self.ncol) | 94 print("ncol: ", self.ncol) |
| 77 print("nrow: ", self.nrow) | 95 print("nrow: ", self.nrow) |
| 78 print("title: ", self.title) | 96 print("title: ", self.title) |
| 79 print("date format: ", self.format) | 97 print("date format: ", self.format) |
| 98 print("logscale: ", self.bounds) | |
| 80 print("output: ", self.output) | 99 print("output: ", self.output) |
| 81 | 100 |
| 82 def plot(self): | 101 def plot(self): |
| 102 clabel = '{desc}' | |
| 83 if self.title and self.format: | 103 if self.title and self.format: |
| 84 title = self.title + "\n" + self.format | 104 title = self.title + "\n" + self.format |
| 85 elif not self.title and self.format: | 105 elif not self.title and self.format: |
| 86 title = self.format | 106 title = self.format |
| 87 elif self.title and not self.format: | 107 elif self.title and not self.format: |
| 88 title = self.title | 108 title = self.title |
| 89 else: | 109 clabel = self.title |
| 90 title = '%(long_name)s' | 110 |
| 91 | 111 # Plot with chosen options |
| 92 if self.cmap is None and self.proj is None: | 112 if self.bounds is None: |
| 93 psy.plot.mapplot(self.input, name=self.varname, | |
| 94 title=title, | |
| 95 clabel='{desc}') | |
| 96 elif self.proj is None or not self.proj: | |
| 97 psy.plot.mapplot(self.input, name=self.varname, | |
| 98 title=title, | |
| 99 cmap=self.cmap, clabel='{desc}') | |
| 100 elif self.cmap is None or not self.cmap: | |
| 101 psy.plot.mapplot(self.input, name=self.varname, | |
| 102 projection=self.proj, | |
| 103 title=title, | |
| 104 clabel='{desc}') | |
| 105 else: | |
| 106 psy.plot.mapplot(self.input, name=self.varname, | 113 psy.plot.mapplot(self.input, name=self.varname, |
| 107 cmap=self.cmap, | 114 cmap=self.cmap, |
| 108 projection=self.proj, | 115 projection=self.proj, |
| 109 title=title, | 116 title=title, |
| 110 clabel='{desc}') | 117 clabel=clabel) |
| 118 else: | |
| 119 psy.plot.mapplot(self.input, name=self.varname, | |
| 120 cmap=self.cmap, bounds=self.bounds, | |
| 121 projection=self.proj, | |
| 122 title=title, | |
| 123 clabel=clabel) | |
| 111 | 124 |
| 112 pyplot.savefig(self.output) | 125 pyplot.savefig(self.output) |
| 113 | 126 |
| 114 def multiple_plot(self): | 127 def multiple_plot(self): |
| 115 if not self.format: | 128 if not self.format: |
| 117 | 130 |
| 118 if not self.title: | 131 if not self.title: |
| 119 title = self.format | 132 title = self.format |
| 120 else: | 133 else: |
| 121 title = self.title + "\n" + self.format | 134 title = self.title + "\n" + self.format |
| 135 | |
| 122 mpl.rcParams['figure.figsize'] = [20, 8] | 136 mpl.rcParams['figure.figsize'] = [20, 8] |
| 123 mpl.rcParams.update({'font.size': 8}) | 137 mpl.rcParams.update({'font.size': 8}) |
| 124 rcParams.update({'plotter.maps.grid_labelsize': 8.0}) | 138 rcParams.update({'plotter.maps.grid_labelsize': 8.0}) |
| 125 if self.cmap is None and self.proj is None: | 139 |
| 126 m = psy.plot.mapplot(self.input, name=self.varname, | 140 # Plot using options |
| 127 title=title, | 141 if self.bounds is None: |
| 128 ax=(self.nrow, self.ncol), | |
| 129 time=self.time, sort=['time'], | |
| 130 clabel='{desc}') | |
| 131 m.share(keys='bounds') | |
| 132 elif self.proj is None or not self.proj: | |
| 133 m = psy.plot.mapplot(self.input, name=self.varname, | |
| 134 title=title, | |
| 135 ax=(self.nrow, self.ncol), | |
| 136 time=self.time, sort=['time'], | |
| 137 cmap=self.cmap, clabel='{desc}') | |
| 138 m.share(keys='bounds') | |
| 139 elif self.cmap is None or not self.cmap: | |
| 140 m = psy.plot.mapplot(self.input, name=self.varname, | |
| 141 projection=self.proj, | |
| 142 ax=(self.nrow, self.ncol), | |
| 143 time=self.time, sort=['time'], | |
| 144 title=title, | |
| 145 clabel='{desc}') | |
| 146 m.share(keys='bounds') | |
| 147 else: | |
| 148 m = psy.plot.mapplot(self.input, name=self.varname, | 142 m = psy.plot.mapplot(self.input, name=self.varname, |
| 149 cmap=self.cmap, | 143 cmap=self.cmap, |
| 150 projection=self.proj, | 144 projection=self.proj, |
| 151 ax=(self.nrow, self.ncol), | 145 ax=(self.nrow, self.ncol), |
| 152 time=self.time, sort=['time'], | 146 time=self.time, sort=['time'], |
| 153 title=title, | 147 title=title, |
| 154 clabel='{desc}') | 148 clabel='{desc}') |
| 155 m.share(keys='bounds') | 149 else: |
| 150 m = psy.plot.mapplot(self.input, name=self.varname, | |
| 151 cmap=self.cmap, bounds=self.bounds, | |
| 152 projection=self.proj, | |
| 153 ax=(self.nrow, self.ncol), | |
| 154 time=self.time, sort=['time'], | |
| 155 title=title, | |
| 156 clabel='{desc}') | |
| 157 | |
| 158 m.share(keys='bounds') | |
| 156 | 159 |
| 157 pyplot.savefig(self.output) | 160 pyplot.savefig(self.output) |
| 158 | 161 |
| 159 | 162 |
| 160 def psymap_plot(input, proj, varname, cmap, output, verbose, time, | 163 def psymap_plot(input, proj, varname, logscale, cmap, output, verbose, time, |
| 161 nrow, ncol, format, title): | 164 nrow, ncol, format, title): |
| 162 """Generate plot from input filename""" | 165 """Generate plot from input filename""" |
| 163 | 166 |
| 164 p = PsyPlot(input, proj, varname, cmap, output, verbose, time, | 167 p = PsyPlot(input, varname, output, logscale, cmap, proj, verbose, time, |
| 165 nrow, ncol, format, title) | 168 nrow, ncol, format, title) |
| 169 | |
| 166 if len(time) == 0: | 170 if len(time) == 0: |
| 167 p.plot() | 171 p.plot() |
| 168 else: | 172 else: |
| 169 p.multiple_plot() | 173 p.multiple_plot() |
| 170 | 174 |
| 184 parser.add_argument( | 188 parser.add_argument( |
| 185 'varname', | 189 'varname', |
| 186 help='Specify which variable to plot (case sensitive)' | 190 help='Specify which variable to plot (case sensitive)' |
| 187 ) | 191 ) |
| 188 parser.add_argument( | 192 parser.add_argument( |
| 193 "--logscale", | |
| 194 help='Plot the log scaled data' | |
| 195 ) | |
| 196 parser.add_argument( | |
| 189 '--cmap', | 197 '--cmap', |
| 190 help='Specify which colormap to use for plotting' | 198 help='Specify which colormap to use for plotting' |
| 191 ) | 199 ) |
| 192 parser.add_argument( | 200 parser.add_argument( |
| 193 '--output', | 201 '--output', |
| 221 | 229 |
| 222 if args.time is None: | 230 if args.time is None: |
| 223 time = [] | 231 time = [] |
| 224 else: | 232 else: |
| 225 time = list(map(int, args.time.split(","))) | 233 time = list(map(int, args.time.split(","))) |
| 226 psymap_plot(args.input, args.proj, args.varname, args.cmap, | 234 |
| 235 if args.logscale == 'no': | |
| 236 logscale = False | |
| 237 else: | |
| 238 logscale = True | |
| 239 | |
| 240 psymap_plot(args.input, args.proj, args.varname, logscale, args.cmap, | |
| 227 args.output, args.verbose, time, | 241 args.output, args.verbose, time, |
| 228 args.nrow, args.ncol, args.format, args.title) | 242 args.nrow, args.ncol, args.format, args.title) |
