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) |