Skip to content

Commit

Permalink
Wrap text
Browse files Browse the repository at this point in the history
Initial commit for wrapping the text/pstext function raised at #122, to be implemented under base_plotting.py alongside the other mapping related stuff. Original GMT `text` documentation can be found at https://gmt.soest.hawaii.edu/doc/latest/text.html. Storing sample test cases at test_text.py. Current implementation takes in either a text filename or x,y,text triples as input.
  • Loading branch information
weiji14 committed Aug 20, 2019
1 parent 82e9c92 commit 93807e5
Show file tree
Hide file tree
Showing 6 changed files with 159 additions and 0 deletions.
1 change: 1 addition & 0 deletions doc/api/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ Plotting data and laying out the map:
Figure.logo
Figure.image
Figure.shift_origin
Figure.text

Saving and displaying the figure:

Expand Down
68 changes: 68 additions & 0 deletions pygmt/base_plotting.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@
Base class with plot generating commands.
Does not define any special non-GMT methods (savefig, show, etc).
"""
import csv
import numpy as np
import pandas as pd

from .clib import Session
from .exceptions import GMTInvalidInput
from .helpers import (
build_arg_string,
dummy_context,
data_kind,
fmt_docstring,
GMTTempFile,
use_alias,
kwargs_to_strings,
)
Expand Down Expand Up @@ -530,3 +535,66 @@ def image(self, imagefile, **kwargs):
with Session() as lib:
arg_str = " ".join([imagefile, build_arg_string(kwargs)])
lib.call_module("image", arg_str)

@fmt_docstring
@use_alias(R="region", J="projection")
@kwargs_to_strings(R="sequence")
def text(self, textfile=None, x=None, y=None, text=None, **kwargs):
"""
Places text on a map.
Used to be pstext.
Takes in a textfile or (x,y,text) triples as input.
Must provide either *textfile* or *x*, *y*, and *text*.
Full option list at :gmt-docs:`text.html`
{aliases}
Parameters
----------
textfile : str
A text data file name
x, y : float or 1d arrays
The x and y coordinates, or an array of x and y coordinates to plot the text
text : str or 1d array
The text string, or an array of strings to plot on the figure
{J}
{R}
"""
kwargs = self._preprocess(**kwargs)

kind = data_kind(textfile, x, y, text)
if kind == "vectors" and text is None:
raise GMTInvalidInput("Must provide text with x and y.")

with GMTTempFile(suffix=".txt") as tmpfile:
with Session() as lib:
if kind == "file":
file_context = dummy_context(textfile)
elif kind == "vectors":
dataframe = pd.DataFrame.from_dict(
{
"x": np.atleast_1d(x),
"y": np.atleast_1d(y),
"text": np.atleast_1d(text),
}
)
dataframe.to_csv(
tmpfile.name,
sep="\t",
header=False,
index=False,
quoting=csv.QUOTE_NONE,
)
file_context = dummy_context(tmpfile.name)
else:
raise GMTInvalidInput(
"Unrecognized data type: {}".format(type(textfile))
)

with file_context as fname:
arg_str = " ".join([fname, build_arg_string(kwargs)])
lib.call_module("text", arg_str)
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added pygmt/tests/baseline/test_single_line_of_text.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added pygmt/tests/baseline/test_text_input_file.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
90 changes: 90 additions & 0 deletions pygmt/tests/test_text.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# pylint: disable=redefined-outer-name
"""
Tests text
"""
import os

import numpy as np
import pytest

from .. import Figure
from ..exceptions import GMTInvalidInput
from ..helpers import data_kind

TEST_DATA_DIR = os.path.join(os.path.dirname(__file__), "data")
POINTS_DATA = os.path.join(TEST_DATA_DIR, "points.txt")


@pytest.fixture(scope="module")
def projection():
"The projection system"
return "x4i"


@pytest.fixture(scope="module")
def region():
"The data region"
return [0, 5, 0, 2.5]


@pytest.mark.mpl_image_compare
def test_text_single_line_of_text(region, projection):
"""
Place a single line text of text at some x, y location
"""
fig = Figure()
fig.text(
region=region,
projection=projection,
x=1.2,
y=2.4,
text="This is a line of text",
)
return fig


@pytest.mark.mpl_image_compare
def test_text_multiple_lines_of_text(region, projection):
"""
Place multiple lines of text at their respective x, y locations
"""
fig = Figure()
fig.text(
region=region,
projection=projection,
x=[1.2, 1.6],
y=[0.6, 0.3],
text=["This is a line of text", "This is another line of text"],
)
return fig


def test_text_without_text_input(region, projection):
"""
Run text by passing in x and y, but no text
"""
fig = Figure()
with pytest.raises(GMTInvalidInput):
fig.text(region=region, projection=projection, x=1.2, y=2.4)


@pytest.mark.mpl_image_compare
def test_text_input_filename(projection):
"""
Run text by passing in a filename to textfile
"""
fig = Figure()
fig.text(region=[10, 70, -5, 10], projection=projection, textfile=POINTS_DATA)
return fig


@pytest.mark.mpl_image_compare
def test_text_wrong_kind_of_input(projection):
"""
Run text by passing in a data input that is not a file/vectors
"""
fig = Figure()
data = np.loadtxt(POINTS_DATA) # Load points into numpy array
assert data_kind(data) == "matrix"
with pytest.raises(GMTInvalidInput):
fig.text(region=[10, 70, -5, 10], projection=projection, textfile=data)

0 comments on commit 93807e5

Please sign in to comment.