aboutsummaryrefslogtreecommitdiff
path: root/docs/plot/plot.py
diff options
context:
space:
mode:
Diffstat (limited to 'docs/plot/plot.py')
-rw-r--r--docs/plot/plot.py177
1 files changed, 177 insertions, 0 deletions
diff --git a/docs/plot/plot.py b/docs/plot/plot.py
new file mode 100644
index 00000000..42581f33
--- /dev/null
+++ b/docs/plot/plot.py
@@ -0,0 +1,177 @@
+'''
+Plot map data in different projections supported by proj.4
+
+Can be called either as
+
+> python plot.py definitions.txt [out]
+
+or
+
+> python plotproj.py "+proj=lcc +lat_1=20" [out]
+
+The output dir is optional. Uses current dir if not set.
+
+Change PROJ and COASTLINE_DATA to path on your local system
+before running the script.
+'''
+
+import os
+import sys
+import json
+import subprocess
+
+import numpy as np
+import matplotlib.pyplot as plt
+
+PROJ = 'proj'
+
+COASTLINE_DATA = 'data/coastline.geojson'
+
+GRATICULE_WIDTH = 15
+N_POINTS = 100
+
+LAT_MIN = -90
+LAT_MAX = 90
+LON_MIN = -180
+LON_MAX = 180
+
+def project(coordinates, proj_string, in_radians=False):
+ '''
+ Project geographical coordinates
+
+ Input:
+ ------
+ coordinates: numpy ndarray of size (N,2) and type double.
+ longitude, latitude
+ proj_string: Definition of output projection
+
+ Out:
+ ----
+ numpy ndarray with shape (N,2) with N pairs of 2D
+ coordinates (x, y).
+ '''
+
+ # proj expects binary input to be in radians
+ if not in_radians:
+ coordinates = np.deg2rad(coordinates)
+
+ # set up cmd call. -b for binary in/out
+ args = [PROJ, '-b']
+ args.extend(proj_string.split(' '))
+
+ proc = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
+ stdout, _ = proc.communicate(coordinates.tobytes())
+
+ out = np.frombuffer(stdout, dtype=np.double)
+ return np.reshape(out, coordinates.shape)
+
+def meridian(lon, lat_min, lat_max):
+ '''
+ Calculate meridian coordinates.
+ '''
+ coords = np.zeros((N_POINTS, 2))
+ coords[:, 0] = lon
+ coords[:, 1] = np.linspace(lat_min, lat_max, N_POINTS)
+ return coords
+
+def parallel(lat, lon_min, lon_max):
+ '''
+ Calculate parallell coordinates.
+ '''
+ coords = np.zeros((N_POINTS, 2))
+ coords[:, 0] = np.linspace(lon_min, lon_max, N_POINTS)
+ coords[:, 1] = lat
+ return coords
+
+def plotproj(proj_str, coastline, frame, graticule, outdir):
+ '''
+ Plot map.
+ '''
+ fig = plt.figure()
+ axes = fig.add_subplot(111)
+
+ # Plot frame
+ for line in frame:
+ line = project(line, proj_str)
+ x, y = zip(*line)
+ plt.plot(x, y, '-k')
+
+ # Plot coastline
+ for feature in coastline['features']:
+ C = np.array(feature['geometry']['coordinates'])
+
+ if np.any(C[:, 0] > 180.0):
+ C[C[:, 0] > 180.0, 0] = 180.0
+
+ if np.any(C[:, 0] < -180.0):
+ C[C[:, 0] < -180.0, 0] = -180.0
+
+ if np.any(C[:, 1] > 90.0):
+ C[C[:, 1] > 90.0, 1] = 90.0
+
+ if np.any(C[:, 1] < -90.0):
+ C[C[:, 1] < -90.0, 1] = -90.0
+
+ coords = project(C, proj_str)
+ x, y = zip(*coords)
+ plt.plot(x, y, '-k', linewidth=0.5)
+
+ # Plot graticule
+ graticule = project(graticule, proj_str)
+ for feature in graticule:
+ x, y = zip(*feature)
+ plt.plot(x, y, '-k', linewidth=0.2)
+
+ axes.axis('off')
+ font = {'family': 'serif',
+ 'color': 'black',
+ 'style': 'italic',
+ 'size': 12}
+ plt.suptitle(proj_str, fontdict=font)
+
+ plt.autoscale(tight=True)
+ name = proj_str.split()[0].split('=')[1]
+ plt.savefig(outdir + '/' + name + '.png', dpi=300)
+
+ # Clean up
+ fig = None
+ del fig
+ axes = None
+ del axes
+ plt.close()
+
+if __name__ == "__main__":
+ '''
+ '''
+
+ with open(COASTLINE_DATA) as data:
+ coastline = json.load(data)
+
+ if os.path.exists(sys.argv[1]):
+ # it must be a file with proj-strings
+ with open(sys.argv[1]) as projs:
+ projs = projs.readlines()
+ else:
+ #assumes it is a single roj string
+ projs = [sys.argv[1]]
+
+ outdir = '.'
+ if len(sys.argv) > 2:
+ outdir = sys.argv[2]
+
+ frame = []
+ frame.append(parallel(LAT_MIN, LON_MIN, LON_MAX))
+ frame.append(parallel(LAT_MAX, LON_MIN, LON_MAX))
+
+ # build graticule
+ graticule = []
+ for lon in range(LON_MIN, LON_MAX+1, GRATICULE_WIDTH):
+ graticule.append(meridian(lon, LAT_MIN, LAT_MAX))
+
+ for lat in range(LAT_MIN, LAT_MAX+1, GRATICULE_WIDTH):
+ graticule.append(parallel(lat, LON_MIN, LON_MAX))
+
+ for i, proj in enumerate(projs):
+ proj_str = proj.strip()
+ print(i, proj_str)
+ plotproj(proj_str, coastline, frame, graticule, outdir)