Repository 'psy_maps'
hg clone https://toolshed.g2.bx.psu.edu/repos/climate/psy_maps

Changeset 2:e6d1e9d6b399 (2024-09-26)
Previous changeset 1:706666d912d5 (2019-10-05) Next changeset 3:988212a7466a (2024-10-01)
Commit message:
planemo upload for repository https://github.com/NordicESMhub/galaxy-tools/tree/master/tools/psy-maps commit d330adb8ea0000ffb2e1dcc2346fd34409f6618e
modified:
psy-maps.xml
psymap_simple.py
test-data/TS.f2000.T31T31.control.cam.h0.0014-12.png
test-data/TS.f2000.T31T31.control.cam.h0.0014-12_ortho.png
added:
test-data/ESACCI-OC-L3S-CHLOR_A-20220601-RESIZED-fv6.0.nc
test-data/ESACCI-OC-L3S-CHLOR_A-20220601-RESIZED-fv6.0.png
b
diff -r 706666d912d5 -r e6d1e9d6b399 psy-maps.xml
--- a/psy-maps.xml Sat Oct 05 17:11:18 2019 -0400
+++ b/psy-maps.xml Thu Sep 26 10:32:08 2024 +0000
[
@@ -1,16 +1,23 @@
-<tool id="psy_maps" name="map plot" version="1.2.1">
+<tool id="psy_maps" name="map plot" version="1.3.0" profile="23.0">
     <description>gridded (lat/lon) netCDF data</description>
+    <edam_topics>
+      <edam_topic>topic_3855</edam_topic>
+      <edam_topic>topic_3318</edam_topic>
+    </edam_topics>
+    <edam_operations>
+      <edam_operation>operation_0573</edam_operation>
+    </edam_operations>
     <requirements>
         <requirement type="package" version="3">python</requirement>
-        <requirement type="package" version="1.2.1">psyplot</requirement>
-        <requirement type="package" version="1.2.0">psy-maps</requirement>
-        <requirement type="package" version="1.2.0">psy-reg</requirement>
-        <requirement type="package" version="1.4.2">netcdf4</requirement>
+        <requirement type="package" version="1.4.3">psyplot</requirement>
+        <requirement type="package" version="1.4.2">psy-maps</requirement>
+        <requirement type="package" version="1.4.0">psy-reg</requirement>
+        <requirement type="package" version="1.6.5">netcdf4</requirement>
     </requirements>
     <command detect_errors="exit_code"><![CDATA[
-       HOME=`pwd`  &&
        python3 '$__tool_directory__/psymap_simple.py'
             '$ifilename' '$variable'
+            --logscale '$adv.logscale'
             --proj '$adv.projection'
             --cmap '$adv.colormap'
             --output image.png
@@ -44,6 +51,10 @@
                     <param name="title" type="text" value="" label="plot title" />
                 </when>
             </conditional>
+            <param name="logscale" type="select" label="log scale the data">
+                <option value="yes">yes</option>
+                <option value="no" selected="true">no</option>
+            </param>
             <param name="projection" type="select">
                 <option value="" selected="true">PlateCarree</option>
                 <option value="robin">Robinson</option>
@@ -155,6 +166,14 @@
             <param name="colormap" value="RdBu_r" />
             <output name="ofilename" ftype="png" file="TS.f2000.T31T31.control.cam.h0.0014-12_ortho.png" compare="sim_size" delta="500"/>
         </test>
+        <test>
+            <param name="ifilename" value="ESACCI-OC-L3S-CHLOR_A-20220601-RESIZED-fv6.0.nc" />
+            <param name="variable" value="chlor_a" />
+            <param name="projection" value="" />
+            <param name="colormap" value="jet" />
+            <param name="logscale" value="yes" />
+            <output name="ofilename" ftype="png" file="ESACCI-OC-L3S-CHLOR_A-20220601-RESIZED-fv6.0.png" compare="sim_size" delta="1500"/>
+        </test>
     </tests>
     <help><![CDATA[
 
@@ -167,15 +186,17 @@
 .. class:: infomark
 
         The wrappers aims at providing the same functionality as ``psyplot.plot.mapplot`` but it has some limitations.
-        The input file must be in netCDF format and must contain 2D arrays with geographical coordinatates
-        (latitudes, longitudes) given in degrees.
-        TODO: Fill in help.
+        The input file must be in netCDF format and must contain 2D arrays with geographical coordinatates 
+ (latitudes, longitudes) given in degrees.
+        The code may fail when the data is significantly different from what has been tested.
 
 **What it does**
 ----------------
 
 This tools creates an image (png format) corresponding to the visualization on a geographical map of a variable extracted from a
-netCDF file (input file). By default, the projection is ``PlateCarree`` and colormap is ``jet``. These settings can be changed in *Advanced settings*.
+netCDF file (input file). 
+By default, the projection is ``PlateCarree`` and colormap is ``jet``. 
+These settings can be changed in *Advanced settings* alongside an option to log scale the plot.
 
 
 **Usage**
@@ -183,21 +204,22 @@
 ::
 
   usage: psymap_simple.py [-h] [--proj PROJ] [--cmap CMAP] [--output OUTPUT] [--time TIME]
-                          [--format FORMAT] [--title TITLE] [--ncol NCOL] [--nrow NROW] [-v] input varname
+                          [--format FORMAT] [--title TITLE] [--ncol NCOL] [--nrow NROW] [-l] [-v] input varname
 
 
 Positional arguments:
 ~~~~~~~~~~~~~~~~~~~~~
 
 - **input**:            input filename with geographical coordinates (netCDF format)
-- **varname**:          Specify which variable to plot (case sensitive)
+- **varname**:          specify which variable to plot (case sensitive)
 
 Optional arguments:
 ~~~~~~~~~~~~~~~~~~~~~
 
   -h, --help       show this help message and exit
-  --proj PROJ      Specify the projection on which we draw
-  --cmap CMAP      Specify which colormap to use for plotting
+  -l, --logscale   log scale the data
+  --proj PROJ      specify the projection on which we draw
+  --cmap CMAP      specify which colormap to use for plotting
   --output OUTPUT  output filename to store resulting image (png format)
   -v, --verbose    switch on verbose mode
   --time TIME      list of times to plot for multiple plots
@@ -211,5 +233,6 @@
 
     ]]></help>
     <citations>
+        <citation type="doi">10.21105/joss.00363</citation>
     </citations>
 </tool>
b
diff -r 706666d912d5 -r e6d1e9d6b399 psymap_simple.py
--- a/psymap_simple.py Sat Oct 05 17:11:18 2019 -0400
+++ b/psymap_simple.py Thu Sep 26 10:32:08 2024 +0000
[
b'@@ -4,6 +4,7 @@\n # usage: psymap_simple.py [-h] [--proj PROJ]\n #                              [--cmap CMAP]\n #                              [--output OUTPUT]\n+#                              [-l]\n #                              [-v]\n #                              input varname\n #\n@@ -14,6 +15,7 @@\n #\n # optional arguments:\n #  -h, --help       show this help message and exit\n+#  -l, --logscale   log scale the data\n #  --proj PROJ      Specify the projection on which we draw\n #  --cmap CMAP      Specify which colormap to use for plotting\n #  --output OUTPUT  output filename to store resulting image (png format)\n@@ -26,47 +28,63 @@\n #\n \n import argparse\n+import math\n import warnings\n from pathlib import Path\n \n import matplotlib as mpl\n+import psyplot.project as psy  # noqa: I202,E402\n+import xarray\n+\n mpl.use(\'Agg\')\n from matplotlib import pyplot  # noqa: I202,E402\n-\n-import psyplot.project as psy  # noqa: I202,E402\n from psyplot import rcParams   # noqa: I202,E402\n \n \n class PsyPlot ():\n-    def __init__(self, input, proj, varname, cmap, output, verbose=False,\n-                 time=[], nrow=1, ncol=1, format="%B %e, %Y",\n-                 title=""):\n+    def __init__(self, input, varname, output=None, logscale=False, cmap=None,\n+                 proj=None, verbose=False, time=None, nrow=None, ncol=None,\n+                 format=None, title=None):\n         self.input = input\n-        self.proj = proj\n         self.varname = varname\n-        self.cmap = cmap\n-        self.time = time\n+        if proj is None or proj == "":\n+            self.proj = "cyl"\n+        else:\n+            self.proj = proj\n+        self.cmap = cmap if cmap is not None else "jet"\n+        self.time = time if time is not None else []\n+        self.ncol = int(ncol) if ncol is not None else int(1)\n+        self.nrow = int(nrow) if nrow is not None else int(1)\n+\n+        # Open dataset\n+        ds = xarray.open_dataset(input)[varname]\n+        minv = math.log2(ds.data.min())\n+        maxv = math.log2(ds.data.max())\n+        if title is not None:\n+            self.title = title\n+        else:\n+            self.title = ds.long_name\n+            if len(self.title) > 60:\n+                self.title = ds.standard_name\n+        del ds\n+\n+        if logscale:\n+            # Check that data range is sufficient for log scaling\n+            if maxv < (minv * (10.0 ** 2.0)):\n+                print("Not possible to log scale, switching to linear scale")\n+                self.bounds = None\n+            else:\n+                self.bounds = [\'log\', 2]\n+        else:\n+            self.bounds = None\n         if format is None:\n             self.format = ""\n         else:\n-            self.format = format.replace(\'X\', \'%\')\n-        if title is None:\n-            self.title = ""\n-        else:\n-            self.title = title\n-        if ncol is None:\n-            self.ncol = 1\n-        else:\n-            self.ncol = int(ncol)\n-        if nrow is None:\n-            self.nrow = 1\n-        else:\n-            self.nrow = int(nrow)\n+            self.format = "%B %e, %Y"\n         if output is None:\n             self.output = Path(input).stem + \'.png\'\n         else:\n             self.output = output\n-        self.verbose = verbose\n         if verbose:\n             print("input: ", self.input)\n             print("proj: ", self.proj)\n@@ -77,37 +95,32 @@\n             print("nrow: ", self.nrow)\n             print("title: ", self.title)\n             print("date format: ", self.format)\n+            print("logscale: ", self.bounds)\n             print("output: ", self.output)\n \n     def plot(self):\n+        clabel = \'{desc}\'\n         if self.title and self.format:\n             title = self.title + "\\n" + self.format\n         elif not self.title and self.format:\n             title = self.format\n         elif self.title and not self.format:\n             title = self.title\n-        else:\n-            title = \'%(long_name)s\'\n+            clabel = self.title\n \n-        if self.cmap is None and s'..b'  psy.plot.mapplot(self.input, name=self.varname,\n+                             cmap=self.cmap, bounds=self.bounds,\n+                             projection=self.proj,\n+                             title=title,\n+                             clabel=clabel)\n \n         pyplot.savefig(self.output)\n \n@@ -119,32 +132,13 @@\n             title = self.format\n         else:\n             title = self.title + "\\n" + self.format\n+\n         mpl.rcParams[\'figure.figsize\'] = [20, 8]\n         mpl.rcParams.update({\'font.size\': 8})\n         rcParams.update({\'plotter.maps.grid_labelsize\': 8.0})\n-        if self.cmap is None and self.proj is None:\n-            m = psy.plot.mapplot(self.input, name=self.varname,\n-                                 title=title,\n-                                 ax=(self.nrow, self.ncol),\n-                                 time=self.time, sort=[\'time\'],\n-                                 clabel=\'{desc}\')\n-            m.share(keys=\'bounds\')\n-        elif self.proj is None or not self.proj:\n-            m = psy.plot.mapplot(self.input, name=self.varname,\n-                                 title=title,\n-                                 ax=(self.nrow, self.ncol),\n-                                 time=self.time, sort=[\'time\'],\n-                                 cmap=self.cmap, clabel=\'{desc}\')\n-            m.share(keys=\'bounds\')\n-        elif self.cmap is None or not self.cmap:\n-            m = psy.plot.mapplot(self.input, name=self.varname,\n-                                 projection=self.proj,\n-                                 ax=(self.nrow, self.ncol),\n-                                 time=self.time, sort=[\'time\'],\n-                                 title=title,\n-                                 clabel=\'{desc}\')\n-            m.share(keys=\'bounds\')\n-        else:\n+\n+        # Plot using options\n+        if self.bounds is None:\n             m = psy.plot.mapplot(self.input, name=self.varname,\n                                  cmap=self.cmap,\n                                  projection=self.proj,\n@@ -152,17 +146,27 @@\n                                  time=self.time, sort=[\'time\'],\n                                  title=title,\n                                  clabel=\'{desc}\')\n-            m.share(keys=\'bounds\')\n+        else:\n+            m = psy.plot.mapplot(self.input, name=self.varname,\n+                                 cmap=self.cmap, bounds=self.bounds,\n+                                 projection=self.proj,\n+                                 ax=(self.nrow, self.ncol),\n+                                 time=self.time, sort=[\'time\'],\n+                                 title=title,\n+                                 clabel=\'{desc}\')\n+\n+        m.share(keys=\'bounds\')\n \n         pyplot.savefig(self.output)\n \n \n-def psymap_plot(input, proj, varname, cmap, output, verbose, time,\n+def psymap_plot(input, proj, varname, logscale, cmap, output, verbose, time,\n                 nrow, ncol, format, title):\n     """Generate plot from input filename"""\n \n-    p = PsyPlot(input, proj, varname, cmap, output, verbose, time,\n+    p = PsyPlot(input, varname, output, logscale, cmap, proj, verbose, time,\n                 nrow, ncol, format, title)\n+\n     if len(time) == 0:\n         p.plot()\n     else:\n@@ -186,6 +190,10 @@\n         help=\'Specify which variable to plot (case sensitive)\'\n     )\n     parser.add_argument(\n+        "--logscale",\n+        help=\'Plot the log scaled data\'\n+    )\n+    parser.add_argument(\n         \'--cmap\',\n         help=\'Specify which colormap to use for plotting\'\n     )\n@@ -223,6 +231,12 @@\n         time = []\n     else:\n         time = list(map(int, args.time.split(",")))\n-    psymap_plot(args.input, args.proj, args.varname, args.cmap,\n+\n+    if args.logscale == \'no\':\n+        logscale = False\n+    else:\n+        logscale = True\n+\n+    psymap_plot(args.input, args.proj, args.varname, logscale, args.cmap,\n                 args.output, args.verbose, time,\n                 args.nrow, args.ncol, args.format, args.title)\n'
b
diff -r 706666d912d5 -r e6d1e9d6b399 test-data/ESACCI-OC-L3S-CHLOR_A-20220601-RESIZED-fv6.0.nc
b
Binary file test-data/ESACCI-OC-L3S-CHLOR_A-20220601-RESIZED-fv6.0.nc has changed
b
diff -r 706666d912d5 -r e6d1e9d6b399 test-data/ESACCI-OC-L3S-CHLOR_A-20220601-RESIZED-fv6.0.png
b
Binary file test-data/ESACCI-OC-L3S-CHLOR_A-20220601-RESIZED-fv6.0.png has changed
b
diff -r 706666d912d5 -r e6d1e9d6b399 test-data/TS.f2000.T31T31.control.cam.h0.0014-12.png
b
Binary file test-data/TS.f2000.T31T31.control.cam.h0.0014-12.png has changed
b
diff -r 706666d912d5 -r e6d1e9d6b399 test-data/TS.f2000.T31T31.control.cam.h0.0014-12_ortho.png
b
Binary file test-data/TS.f2000.T31T31.control.cam.h0.0014-12_ortho.png has changed