Here is my best guess at what you want:
import pygmt
fig = pygmt.Figure()
a = fig.basemap(region = [0, 6, 0, 2], projection = "X12c/4c", frame = True, )
pol = ["n0.9c", "c0.9c", "d0.9c"]
Mog = [
pygmt.makecpt(cmap = "bilbao", series = [-5, 50, 5]),
pygmt.makecpt(cmap = "bilbao", series = [-5, 15, 5]),
pygmt.makecpt(cmap = "bilbao", series = [-8000, 4000])
]
longitude_polyT = [1, 3, 5]
latitude_polyT = [1, 1, 1]
for i, long in enumerate(longitude_polyT):
fig.plot(x = long, y = latitude_polyT[i], style = pol[i], frame = a,
pen = "black",
color = Mog[i], cmap = True)
fig.show()
Then, you can use fig.plot(..., cmap="mycategorical.cpt", color="+z", a="Z=Name") or something along those lines (refer to How to color polygons of a geopandas dataframe in pygmt? and https://www.pygmt.org/v0.3.1/api/generated/pygmt.Figure.plot.html).,I am attempting to plot and color the polygons from a geologic map kml file I converted to a gmt file but I don’t understand how to color the polygons. I’ve been able to plot the polygon outlines using the method here, but I want to color by name of the category or a dictionary of colors matched to the names. However, when I try to assign a category to the names and color by cmap such as in this example, I get the error: “pygmt.exceptions.GMTInvalidInput: Can’t use arrays for color if data is matrix or file.”. How can I color the polygons?,Thank you for helping me with this! I attempted coloring by categorical CPT following the method in the links you provided as best I can, but no figure is generated at the end when I try it. The gmt file is too large to upload to this site, so here is a google drive link that contains the files in addition to the source klm.,Hi @hazardgoat, thanks for trying PyGMT! You may need to convert the dictionary of {names:colors} into a categorical CPT file first (as mentioned in Coloring polygon). The mycategorical.cpt plaintext file should look something like:
The working part of my code that plots the polygon outlines:
import geopandas as gpd import pygmt import pandas as pd gpd.io.file.fiona.drvsupport.supported_drivers['KML'] = 'rw' # reads kml file df_polygons = gpd.read_file('GMC_geo_poly.kml', driver = 'KML') # converts kml file to gmt df_polygons.to_file('GMC_geo_poly.gmt', driver = 'OGR_GMT', ) # reads gmt file df_polygons = gpd.read_file('GMC_geo_poly.gmt', driver = 'OGR_GMT') region = [-125, -122, 39, 41] fig = pygmt.Figure() fig.basemap( region = region, projection = 'M6i', frame = 'f' ) fig.coast( shorelines = '0.5p,black', resolution = 'h', water = 'lightskyblue2', transparency = 50, ) # plots the polygons from the gmt file fig.plot( data = 'GMC_geo_poly.gmt', ) # saves a copy of the generated figure fig.savefig('GMC_geo_poly.png') fig.show()
Hi @hazardgoat, thanks for trying PyGMT! You may need to convert the dictionary of {names:colors} into a categorical CPT file first (as mentioned in Coloring polygon). The mycategorical.cpt
plaintext file should look something like:
Q red
grMz blue
QPc green
The full script is in the google drive, but the fig.plot command I’m using is:
fig.plot(
data = 'GMC_geo_poly.gmt',
cmap = polyColor_cpt,
color = '+z',
a = 'Z = Name',
)
and the cpt file looks like this:
C 255 / 222 / 153
Ca 153 / 128 / 235
D 255 / 179 / 153
E 77 / 179 / 235
E - Ep 77 / 179 / 236
Ec 77 / 153 / 222
Ep 77 / 153 / 204
gb 255 / 153 / 179
gr 204 / 153 / 255
gr - m 204 / 128 / 235
grCz 255 / 204 / 255
grCz ? 255 / 204 / 256
grMz 204 / 179 / 255
grMz ? 204 / 179 / 256
grpC 235 / 77 / 255
grpC ? 235 / 77 / 256
grPz 179 / 102 / 255
J 128 / 255 / 77
J ? 128 / 255 / 78
K 0 / 255 / 179
K ? 0 / 255 / 180
KJf 77 / 222 / 128
KJfm 102 / 204 / 102
KJfs 128 / 235 / 128
Kl 0 / 255 / 128
Kl ? 0 / 255 / 129
Ku 102 / 255 / 153
Ku - Ep 102 / 255 / 154
ls 222 / 153 / 77
m 222 / 153 / 204
mv 222 / 153 / 205
M 0 / 222 / 255
M ? 0 / 222 / 256
M + KJfs 0 / 222 / 257
Mc 0 / 204 / 222
Mzv 0 / 255 / 77
O 128 / 222 / 235
Oc 128 / 204 / 204
Oc ? 128 / 204 / 205
pC 128 / 128 / 204
pCc 128 / 128 / 179
P 179 / 235 / 255
Pm 255 / 255 / 102
Pz 204 / 222 / 102
Pzv 255 / 222 / 128
Q 179 / 255 / 255
Qg 204 / 204 / 204
Qls 0 / 255 / 255
Qoa 102 / 255 / 255
QPc 77 / 222 / 235
Qrv 0 / 153 / 255
Qrvp 0 / 128 / 255
Qs 235 / 255 / 255
Qv 0 / 77 / 255
Qv ? 0 / 77 / 256
Qvp 0 / 77 / 204
Qvp ? 0 / 77 / 205
sch 222 / 204 / 128
SO 255 / 179 / 204
Tc 77 / 179 / 255
Ti 77 / 0 / 245
TK 77 / 222 / 179
Tr 204 / 255 / 102
Tv 102 / 102 / 255
Tvp 102 / 102 / 204
um 255 / 77 / 153
B black
F white
N 127.5
It is also possible to create a custom mapping for a colormap. This is accomplished by creating dictionary that specifies how the RGB channels change from one end of the cmap to the other.,Creating a colormap from a list of colors can be done with the LinearSegmentedColormap.from_list method. You must pass a list of RGB tuples that define the mixture of colors from 0 to 1.,If there are discontinuities, then it is a little more complicated. Label the 3 elements in each row in the cdict entry for a given color as (x, y0, y1). Then for values of x between x[i] and x[i+1] the color value is interpolated between y1[i] and y0[i+1].,Second, create the map explicitly and register it. Like the first method, this method works with any kind of Colormap, not just a LinearSegmentedColormap:
cdict = {
'red': ((0.0, 0.0, 0.0),
(0.5, 1.0, 1.0),
(1.0, 1.0, 1.0)),
'green': ((0.0, 0.0, 0.0),
(0.25, 0.0, 0.0),
(0.75, 1.0, 1.0),
(1.0, 1.0, 1.0)),
'blue': ((0.0, 0.0, 0.0),
(0.5, 0.0, 0.0),
(1.0, 1.0, 1.0))
}
row i: x y0 y1 /
/
row i + 1: x y0 y1
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib.colors
import LinearSegmentedColormap
# Make some illustrative fake data:
x = np.arange(0, np.pi, 0.1)
y = np.arange(0, 2 * np.pi, 0.1)
X, Y = np.meshgrid(x, y)
Z = np.cos(X) * np.sin(Y) * 10
colors = [(1, 0, 0), (0, 1, 0), (0, 0, 1)] # R - > G - > B n_bins = [3, 6, 10, 100] # Discretizes the interpolation into bins cmap_name = 'my_list' fig, axs = plt.subplots(2, 2, figsize = (6, 9)) fig.subplots_adjust(left = 0.02, bottom = 0.06, right = 0.95, top = 0.94, wspace = 0.05) for n_bin, ax in zip(n_bins, axs.flat): # Create the colormap cmap = LinearSegmentedColormap.from_list(cmap_name, colors, N = n_bin) # Fewer bins will result in "coarser" colomap interpolation im = ax.imshow(Z, origin = 'lower', cmap = cmap) ax.set_title("N bins: %s" % n_bin) fig.colorbar(im, ax = ax)
cdict1 = { 'red': ((0.0, 0.0, 0.0), (0.5, 0.0, 0.1), (1.0, 1.0, 1.0)), 'green': ((0.0, 0.0, 0.0), (1.0, 0.0, 0.0)), 'blue': ((0.0, 0.0, 1.0), (0.5, 0.1, 0.0), (1.0, 0.0, 0.0)) } cdict2 = { 'red': ((0.0, 0.0, 0.0), (0.5, 0.0, 1.0), (1.0, 0.1, 1.0)), 'green': ((0.0, 0.0, 0.0), (1.0, 0.0, 0.0)), 'blue': ((0.0, 0.0, 0.1), (0.5, 1.0, 0.0), (1.0, 0.0, 0.0)) } cdict3 = { 'red': ((0.0, 0.0, 0.0), (0.25, 0.0, 0.0), (0.5, 0.8, 1.0), (0.75, 1.0, 1.0), (1.0, 0.4, 1.0)), 'green': ((0.0, 0.0, 0.0), (0.25, 0.0, 0.0), (0.5, 0.9, 0.9), (0.75, 0.0, 0.0), (1.0, 0.0, 0.0)), 'blue': ((0.0, 0.0, 0.4), (0.25, 1.0, 1.0), (0.5, 1.0, 0.8), (0.75, 0.0, 0.0), (1.0, 0.0, 0.0)) } # Make a modified version of cdict3 with some transparency # in the middle of the range. cdict4 = { ** cdict3, 'alpha': ((0.0, 1.0, 1.0), #(0.25, 1.0, 1.0), (0.5, 0.3, 0.3), #(0.75, 1.0, 1.0), (1.0, 1.0, 1.0)), }
blue_red1 = LinearSegmentedColormap('BlueRed1', cdict1)