Skip to content

Commit

Permalink
Merge pull request #45 from NREL/ascii_plots
Browse files Browse the repository at this point in the history
ASCII Histograms
  • Loading branch information
mjgleason authored Aug 16, 2023
2 parents d658bf1 + 8a9905a commit 867f7e4
Show file tree
Hide file tree
Showing 12 changed files with 392 additions and 3 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/pull_request_tests_unix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ jobs:
fetch-depth: 1

- uses: nanasess/setup-chromedriver@v2
with:
chromedriver-version: '115.0.5790.170'
- name: Install Chrome Driver
run: |
export DISPLAY=:99
Expand Down
25 changes: 25 additions & 0 deletions USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Options:
--help Show this message and exit.
Commands:
histogram Plots a histogram in the terminal for the specified column(s) from the input SUPPLY_CURVE_CSV.
make-maps Generates standardized, presentation-quality maps for the input supply curve, including maps for each of the following attributes: Capacity (capacity), All-in LCOE (total_lcoe), Project LCOE (mean_lcoe), LCOT (lcot), Capacity Density (derived column) [wind only]
map-column Generates a single map from an input supply curve for the specified column, with basic options for formatting.
Expand All @@ -23,6 +24,30 @@ Commands:
unpack-turbines Unpack individual turbines from each reV project site in a reV supply curve CSV, produced using "bespoke" (i.e., SROM) turbine placement.
```

## Plotting Histograms (in the terminal)
The `histogram` function is intended to make it easy to review the distribution of data contained in a supply curve CSV. It can be used to plot a histogram of the selected CSV column(s) directly in the terminal.

This command can be run according to the following usage:
```commandline
Usage: reView-tools histogram [OPTIONS] SUPPLY_CURVE_CSV
Plots a histogram in the terminal for the specified column(s) from the input SUPPLY_CURVE_CSV.
Options:
-c, --column TEXT Value column from the input CSV to plot. Multiple value columnscan be specified: e.g., -c area_sq_km -c capacity_mw [required]
-N, --nbins INTEGER RANGE Number of bins to use in the histogram. If not specified, default is 20 bins. [x>=1]
-W, --width INTEGER RANGE Width of output histogram. If not specified, default width is 80% of the termimal width. [0<=x<=500]
-H, --height INTEGER RANGE Height of output histogram. If not specified, default height is the smaller of 50% of the terminal width or 100% of the terminal height. [0<=x<=500]
--help Show this message and exit.
```

For most use cases, users need to only specify the `SUPPLY_CURVE_CSV` and the column or columns they want to plot. For example, to plot the `area_sq_km` and `capacity_mw` columns:
```commandline
reView-tools histogram some_supply_curve.csv -c area_sq_km -c capacity_mw
```

For more advanced cases, the user may want to adjust the number of bins in the histogram using the `--nbins` argument and/or the size of the output plot with the `--width` and/or `--height` arguments.

## Making Standardized Maps
The `make-maps` command can be used to generate a small set of standardized, report/presentation-qualiity maps from an input supply curve. For a solar supply curve, 4 maps are created, including one for each of the following supply curve columns: Capacity (capacity), All-in LCOE (total_lcoe), Project LCOE (mean_lcoe), LCOT (lcot). For a wind supply curve, the same 4 maps are created and, in addition, a map is also created for Capacity Density (a derived column).

Expand Down
47 changes: 45 additions & 2 deletions reView/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -408,11 +408,10 @@ def map_column(
f"Column {column} could not be found in input supply curve."
)

cap_col = find_capacity_column(supply_curve_df)

if keep_zero:
supply_curve_subset_df = supply_curve_df
else:
cap_col = find_capacity_column(supply_curve_df)
supply_curve_subset_df = supply_curve_df[
supply_curve_df[cap_col] > 0
].copy()
Expand Down Expand Up @@ -494,3 +493,47 @@ def map_column(
out_image_path = out_path.joinpath(out_image_name)
g.figure.savefig(out_image_path, dpi=dpi, transparent=True)
plt.close(g.figure)


@main.command()
@click.argument('supply_curve_csv',
type=click.Path(exists=True, dir_okay=False, file_okay=True)
)
@click.option('--column', '-c', required=True, multiple=True,
default=None,
type=click.STRING,
help=(
"Value column from the input CSV to plot. Multiple value "
"columnscan be specified: e.g., -c area_sq_km -c capacity_mw"
))
@click.option('--nbins', '-N', required=False,
default=20,
type=click.IntRange(min=1),
help=("Number of bins to use in the histogram. If not "
"specified, default is 20 bins."))
@click.option('--width', '-W', required=False,
default=None,
type=click.IntRange(min=0, max=500),
help=("Width of output histogram. If not specified, default "
"width is 80% of the terminal width."))
@click.option('--height', '-H', required=False,
default=None,
type=click.IntRange(min=0, max=500),
help=("Height of output histogram. If not specified, default "
"height is the smaller of 20% of the terminal width or "
"100% of the terminal height."))
def histogram(supply_curve_csv, column, nbins, width, height):
"""
Plots a histogram in the terminal for the specified column(s) from the
input SUPPLY_CURVE_CSV.
"""

df = pd.read_csv(supply_curve_csv)
for column_name in column:
try:
plots.ascii_histogram(
df, column_name, nbins=nbins, width=width, height=height
)
print("\n")
except TypeError as e:
print(f"Unable to plot column '{column_name}': {e}")
56 changes: 56 additions & 0 deletions reView/utils/plots.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import mapclassify as mc
from matplotlib.patheffects import SimpleLineShadow, Normal
import geoplot as gplt
import plotext
from pandas.api.types import is_numeric_dtype


# pylint: disable=no-member, arguments-differ
Expand Down Expand Up @@ -308,3 +310,57 @@ def map_geodataframe_column( # noqa: C901
ax.set_title(map_title)

return ax


def ascii_histogram(df, column, nbins=20, width=None, height=None):
"""
Prints a histogram for the selected column of the input dataframe to the
terminal.
Parameters
----------
df : pandas.DataFrame
Input DataFrame
column : str
Name of column to plot. Must have a numeric dtype.
nbins : int, optional
Number of bins to plot in the histogram, by default 20.
width : int, optional
Width of the histogram plot (in characters). By default None, which
will set the width to 80% of the terminal width.
height : int, optional
Height of the histogram plot (in characters). By default None, which
will set the width to the smaller of either 20% of the terminal width
or 100% of the terminal height.
Raises
------
TypeError
A TypeError will be raised if the specified column does not have a
numeric data type.
"""

if not is_numeric_dtype(df[column]):
raise TypeError("Input column must have a numeric dtype.")

x_values = df[column].tolist()

plotext.clear_data()
plotext.clear_figure()

if width is None:
width = plotext.terminal_width() * 0.8
if height is None:
height = min(plotext.terminal_width()/5, plotext.terminal_height())

plotext.hist(x_values, bins=nbins, width=1)
plotext.plotsize(width, height)
plotext.axes_color("black")
plotext.canvas_color("black")
plotext.ticks_color("gray")
plotext.xfrequency(nbins+1)
plotext.title(column)

plotext.show()
plotext.clear_data()
plotext.clear_figure()
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ pygeopkg>=0.1.2,<1
pyarrow>=11.0.0,<12
scikit-learn>=1.1.1,<2
us>=2.0.2,<2.0.3
plotext>=5.2.8,<5.3
56 changes: 56 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,62 @@ def output_map_names():
return map_names


@pytest.fixture
def histogram_plot_area_sq_km():
"""Returns contents of ASCII histogram with default 20 bins for area_sq_km
column of map_supply_curve_wind"""

ascii_histogram_contents_src = Path(TEST_DATA_DIR).joinpath(
"plots", "histogram_area_sq_km.txt"
)
with open(ascii_histogram_contents_src, "r", encoding="utf-8") as f:
contents = f.read()

return contents


@pytest.fixture
def histogram_plot_capacity_mw():
"""Returns contents of ASCII histogram with default 20 bins for
capacity_mw column of map_supply_curve_wind"""

ascii_histogram_contents_src = Path(TEST_DATA_DIR).joinpath(
"plots", "histogram_capacity_mw.txt"
)
with open(ascii_histogram_contents_src, "r", encoding="utf-8") as f:
contents = f.read()

return contents


@pytest.fixture
def histogram_plot_area_sq_km_5bins():
"""Returns contents of ASCII histogram with 5 bins for area_sq_km column
of map_supply_curve_wind"""

ascii_histogram_contents_src = Path(TEST_DATA_DIR).joinpath(
"plots", "histogram_area_sq_km_5bins.txt"
)
with open(ascii_histogram_contents_src, "r", encoding="utf-8") as f:
contents = f.read()

return contents


@pytest.fixture
def histogram_plot_capacity_mw_5bins():
"""Returns contents of ASCII histogram with 5 bins for capacity_mw column
of map_supply_curve_wind"""

ascii_histogram_contents_src = Path(TEST_DATA_DIR).joinpath(
"plots", "histogram_capacity_mw_5bins.txt"
)
with open(ascii_histogram_contents_src, "r", encoding="utf-8") as f:
contents = f.read()

return contents


def pytest_setup_options():
"""Recommended setup based on https://dash.plotly.com/testing."""
options = Options()
Expand Down
16 changes: 16 additions & 0 deletions tests/data/plots/histogram_area_sq_km.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Backend MacOSX is interactive backend. Turning interactive mode on.
 area_sq_km 
 ┌──────────────────────────────────────────────────────────────────────┐
156┤ █████ │
 │ █████ │
130┤ ███████████│
104┤ ███████████████│
 │ ███████████████│
 78┤ ██████████████████████│
 │ ██████████████████████│
 52┤████ █████████████████████████│
 26┤████████ ████████████ ███████████████████████████████████████│
 │██████████████████████████████████████████████████████████████████████│
 0┤██████████████████████████████████████████████████████████████████████│
 └┬──────┬──────┬──────┬──────┬──────┬─────┬───┬──────┬──────┬──────┬───┘
 -3.1 10.6 24.4 38.2 51.9 65.7 79.5 86.4 100.1 113.9 127.6 
15 changes: 15 additions & 0 deletions tests/data/plots/histogram_area_sq_km_5bins.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
 area_sq_km 
 ┌────────────────────────────────────────────────────────────────────┐
509.0┤ ██████████████│
 │ ██████████████│
424.2┤ ██████████████│
339.3┤ ██████████████│
 │ ██████████████│
254.5┤ ████████████████████████████│
 │ ████████████████████████████│
169.7┤ ████████████████████████████│
 84.8┤████████████████████████████████████████████████████████████████████│
 │████████████████████████████████████████████████████████████████████│
 0.0┤████████████████████████████████████████████████████████████████████│
 └┬────────────┬─────────────┬────────────┬─────────────┬────────────┬┘
 -16.0 16.7 49.4 82.0 114.7 147.4 
Loading

0 comments on commit 867f7e4

Please sign in to comment.