Skip to content

Commit

Permalink
v.scatterplot: add option for dot color and size (#992)
Browse files Browse the repository at this point in the history
Add option to color dots according to RGB column and to set the dot size. Updated examples.
  • Loading branch information
ecodiv committed Dec 9, 2023
1 parent 9d6418d commit 4459d47
Show file tree
Hide file tree
Showing 5 changed files with 168 additions and 83 deletions.
118 changes: 81 additions & 37 deletions src/vector/v.scatterplot/v.scatterplot.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,90 +3,134 @@ <h2>DESCRIPTION</h2>
<p>
<em>v.scatterplot</em> draws a scatterplot of the value in one
column against the values in another column. Optionally, a linear or
polynomial trendline with user-defined degrees can be drawn on top.
polynomial trend line with user-defined degrees can be drawn on top.

<p>
There are a few additional layout options, including the option to
set the color of the dots, the color, line type, and width of the
trendline, and the font size of the axis and tic labels.
Trend line, and the font size of the axis and tic labels.

<p>
Instead of a fixed color, dots can be colored by the spatial
density of nearby points, using the option <em>type=density</em>. The
spatial density is computed by grouping the points in 2D bins. The
number of bins along the x-axis and y-axis is user-defined.
Instead of a fixed color, dots can be colored using colors from a
user-defined column, or by the spatial density of nearby points, using
the option <em>type=density</em>. The spatial density is computed by
grouping the points in 2D bins. The number of bins along the x-axis and
y-axis is user-defined.

<p>
By default, the resulting plot is displayed on screen (default).
However, the user can also save the plot to a file using the
<em>file_name</em> option. The format is determined by the extension
given by the user. So, if file_name = outputfile.png, the plot will be
saved as a png file.
saved as a PNG file.

<h2>EXAMPLE</h2>
<h2>EXAMPLES</h2>

<h3>Example 1</h3>

Download the NC sample dataset and MODIS Land
Surface Temperature mapset from <a
href="https://grass.osgeo.org/download/data/">GRASS GIS website</a>

<p>
Use the raster layers <em>elev_state_500m</em> from the PERMANENT
mapset of the NC sample dataset to set the region and mask.
For the examples below, the NCA sample data set from <a
href="https://grass.osgeo.org/download/data/">GRASS GIS website</a>
will be used

<p> Create a new mapset and Use the layer
<i>lsat7_2002_10@PERMANENT</i> to set the region.

<div class="code"><pre>
g.region raster=slope
r.mask raster=elev_state_500m
g.mapset -c mapset=scatterplot
g.region raster=lsat7_2002_10@PERMANENT
</pre>
</div>

Create a vector point layer with 1000 random points. Add an attribute
table with two columns <em>slope</em> and <em>elevation</em>
<p>
Get the list of Landsat layers from the Permanent mapset. Use this as
input for <em>i.pca</em> to create principal component layers.

<div class="code"><pre>
r.random input=elev_state_500m npoints=1000 vector=randompoints seed=10
lcc=`g.list type="raster" mapset="PERMANENT" pattern="lsat7_*" sep=,`
i.pca -n input=$lcc output=pca rescale=0,100
</pre>
</div>

Sample the raster values of the raster layers <em>elev_state_500m</em>
from the PERMANENT MAPSET and
<em>MOD11B3.A2016336.h11v05.single_LST_Day_6km</em> from the modis_lst
mapset.
<p>
Create 5000 random points, retrieve the raster value from the first two
PCA layers for each point location of the random points, and write
these values to the columns <i>pca_1</i> and <i>pca_2</i> in the
attribute table of <i>randompoints</i>.

<div class="code"><pre>
v.what.rast map=randompoints raster=elev_state_500m column=elevation
v.what.rast map=randompoints raster=MOD11B3.A2016336.h11v05.single_LST_Day_6km@modis_lst column=temperature
r.random input=elevation npoints=5000 vector=randompoints seed=10
v.what.rast map=randompoints raster=pca.1 column=pca_1
v.what.rast map=randompoints raster=pca.2 column=pca_2
</pre>
</div>

Draw a scatterplot of the elevation values against the slope values.
<p>
Create a scatterplot, plotting the values from the column
<i>pca_1</i> on the X-axis and <i>pca_2</i> on the Y-asix, with
blue dots.

<div class="code"><pre>
v.scatterplot map=randompoints x=elevation y=temperature
v.scatterplot map=randompoints x=pca_1 y=pca_2 color=blue
</pre>
</div>

<p>
<img src="v_scatterplot_01.png"><br> <em>Figure 1. Scatterplot of
elevation against temperature in 1000 randomly selected locations</em>
pca_1 against pca_1</em>


Draw a density scatter of the elevation values against the slope
values. Add a dashed linear trendline with a red color.
<h3>Example 2</h3>

<p>
Create a density scatter of the values from <i>pca_1</i> and
<i>pca_2</i>. Add a red dashed polynomial trend line with degree 2.

<div class="code"><pre>
v.scatterplot map=randompoints x=elevation y=temperature \
line_color=252:0:0:255 type=density bins=10,10 \
trendline=linear
v.scatterplot map=randompoints x=pca_1 y=pca_2 trendline=polynomial \
degree=2 line_color=red type=density bins=10,10
</pre>
</div>

<p>
<img src="v_scatterplot_02.png"><br> <em>Figure 1. Density
scatterplot of elevation against temperature in 1000 randomly selected
locations. Dashed red line is the trendline.</em>
<img src="v_scatterplot_02.png"><br> <em>Figure 2. Density scatterplot
of pca_1 against pca_1</em>. The dashed red line gives the polynomial trend line (R&sup2;=0.149)

<h3>Example 3</h3>

<p>
Retrieves raster value from the raster layer <i>landclass96</i>,
and write these values to the column <i>landuse</i> in the attribute
table of <i>randompoints</i>. Next, transfer the raster colors of the
raster layer <i>landclass96</i> to the new column <i>RGB</i> of the
attribute table of <i>randompoints</i>.


<div class="code"><pre>
v.what.rast map=randompoints raster=landclass96 column=landuse
v.colors map=randompoints use=attr column=landuse \
raster=landclass96@PERMANENT rgb_column=RGB
</pre>
</div>

<p>
Create a scatterplot, using the colors from the RGB column. Set the
size of the dots to 8.

<div class="code"><pre>
v.scatterplot map=randompoints x=pca_1 y=pca_2 s=8 rgbcolumn=RGB
</pre>
</div>

<p>
<img src="v_scatterplot_03.png"><br> <em>Figure 3. Scatterplot of
pca_1 against pca_1. Colors represent the land use categories in the
point locations based on the landclass96 map.</em>

<h2>AUTHOR</h2>

Paulo van Breugel
Paulo van Breugel
Applied Geo-information Sciences
HAS green academy, University of Applied Sciences


133 changes: 87 additions & 46 deletions src/vector/v.scatterplot/v.scatterplot.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,47 @@
# % guisection: Output
# %end

# %option
# % key: type
# % type: string
# % label: plot type
# % description: Type of plot (scatter, density)
# % required: no
# % answer: scatter
# % options: scatter, density
# % guisection: Stats
# %end

# %option
# % key: bins
# % type: string
# % label: 2D bins
# % description: The number of bins in x and y dimension.
# % required: no
# % answer: 30,30
# % guisection: Stats
# %end

# %option
# % key: trendline
# % type: string
# % label: Trendline
# % description: Plot trendline
# % required: no
# % options: linear, polynomial
# % guisection: Stats
# %end

# %option
# % key: degree
# % type: integer
# % label: Degree
# % description: Degree polynomial trendline
# % required: no
# % answer: 1
# % guisection: Stats
# %end

# %option
# % key: title
# % type: string
Expand All @@ -72,16 +113,37 @@
# % guisection: Aesthetics
# %end

# %option
# % key: s
# % type: double
# % label: Marker size
# % description: Set marker size
# % required: no
# % guisection: Aesthetics
# %end

# %option G_OPT_C
# % key: color
# % type: string
# % label: Dot color
# % description: Color of dots
# % required: no
# % answer: blue
# % guisection: Aesthetics
# %end

# %option G_OPT_DB_COLUMN
# % key: rgbcolumn
# % type: string
# % label: RGB column
# % description: Column with RGB values defining the dot colors
# % required: no
# % guisection: Aesthetics
# %end

# %rules
# % exclusive: color,rgbcolumn
# %end

# %option G_OPT_C
# % key: line_color
# % type: string
Expand Down Expand Up @@ -142,47 +204,6 @@
# % guisection: Output
# %end

# %option
# % key: type
# % type: string
# % label: plot type
# % description: Type of plot (scatter, density)
# % required: no
# % answer: scatter
# % options: scatter, density
# % guisection: Stats
# %end

# %option
# % key: bins
# % type: string
# % label: 2D bins
# % description: The number of bins in x and y dimension.
# % required: no
# % answer: 30,30
# % guisection: Stats
# %end

# %option
# % key: trendline
# % type: string
# % label: Trendline
# % description: Plot trendline
# % required: no
# % options: linear, polynomial
# % guisection: Stats
# %end

# %option
# % key: degree
# % type: integer
# % label: Degree
# % description: Degree polynomial trendline
# % required: no
# % answer: 1
# % guisection: Stats
# %end

import atexit
import sys
import uuid
Expand Down Expand Up @@ -242,7 +263,7 @@ def lazy_import_scipy():
return "noscipy"


def scatter_plot(X, Y, X_name, Y_name, title, color, marker, dimensions, fontsize):
def scatter_plot(X, Y, X_name, Y_name, title, color, marker, s, dimensions, fontsize):
"""
Create scatterplot
Expand All @@ -253,6 +274,7 @@ def scatter_plot(X, Y, X_name, Y_name, title, color, marker, dimensions, fontsiz
:param str title: label for plot title (empty is not title)
:param str color: color of the dots in the scatterplot
:param str marker: the mark type for the scatterplot dots
:param float s: size of marker
:param list dimensions: plot dimensions (width, height)
:param float fontsize: fontsize of all text (tic labes are 1pnt smaller)
Expand All @@ -263,7 +285,10 @@ def scatter_plot(X, Y, X_name, Y_name, title, color, marker, dimensions, fontsiz
plt.rcParams["font.size"] = fontsize
for label in ax.get_xticklabels() + ax.get_yticklabels():
label.set_fontsize(fontsize - 1)
ax.scatter(X, Y, color=color, marker=marker)
if s:
ax.scatter(X, Y, color=color, marker=marker, s=s)
else:
ax.scatter(X, Y, color=color, marker=marker)
plt.xlabel(X_name, fontsize=fontsize)
plt.ylabel(Y_name, fontsize=fontsize)
if len(title) != 0:
Expand Down Expand Up @@ -327,7 +352,7 @@ def main(options, flags):
Optionally, color the dots according to their density
"""

# lazy import matplotlib
# lazy import modules
lazy_import_matplotlib()
if options["type"] == "density":
has_scipy = lazy_import_scipy()
Expand All @@ -351,11 +376,26 @@ def main(options, flags):
plot_title = options["title"]
file_name = options["file_name"]
bins = [int(x) for x in options["bins"].split(",")]
dot_color = get_valid_color(options["color"])
if options["rgbcolumn"]:
rgbcolumn = gs.read_command(
"v.db.select",
map=options["map"],
columns=options["rgbcolumn"],
flags="c",
).splitlines()
dot_color = [get_valid_color(x) for x in rgbcolumn]
elif options["color"]:
dot_color = get_valid_color(options["color"])
else:
dot_color = get_valid_color("blue")
line_color = get_valid_color(options["line_color"])
line_style = options["line_style"]
line_width = options["line_width"]
dot_marker = options["marker"]
if options["s"]:
s = float(options["s"])
else:
s = False

# Plot scatterplot
if options["type"] == "scatter":
Expand All @@ -367,6 +407,7 @@ def main(options, flags):
title=plot_title,
color=dot_color,
marker=dot_marker,
s=s,
dimensions=plot_dimensions,
fontsize=float(options["fontsize"]),
)
Expand Down
Binary file modified src/vector/v.scatterplot/v_scatterplot_01.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/vector/v.scatterplot/v_scatterplot_02.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/vector/v.scatterplot/v_scatterplot_03.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 4459d47

Please sign in to comment.