• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

morganjwilliams / pyrolite / 9114710863

16 May 2024 03:06PM UTC coverage: 91.635% (-0.03%) from 91.661%
9114710863

Pull #104

github

web-flow
Merge dd85a1027 into d3f5b518a
Pull Request #104: Checks for negative entries in close and normalise functions of codata.py

14 of 15 new or added lines in 1 file covered. (93.33%)

1 existing line in 1 file now uncovered.

6211 of 6778 relevant lines covered (91.63%)

2.75 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.24
/pyrolite/util/plot/interpolation.py
1
"""
2
Line interpolation for matplotlib lines and paths.
3
"""
4

5
import matplotlib.collections
3✔
6
import matplotlib.path
3✔
7
import numpy as np
3✔
8
import scipy.interpolate
3✔
9

10
from ..log import Handle
3✔
11

12
logger = Handle(__name__)
3✔
13

14

15
def interpolate_path(
3✔
16
    path, resolution=100, periodic=False, aspath=True, closefirst=False, **kwargs
17
):
18
    """
19
    Obtain the interpolation of an existing path at a given
20
    resolution. Keyword arguments are forwarded to
21
    :func:`scipy.interpolate.splprep`.
22

23
    Parameters
24
    -----------
25
    path : :class:`matplotlib.path.Path`
26
        Path to interpolate.
27
    resolution :class:`int`
28
        Resolution at which to obtain the new path. The verticies of
29
        the new path will have shape (`resolution`, 2).
30
    periodic : :class:`bool`
31
        Whether to use a periodic spline.
32
    periodic : :class:`bool`
33
        Whether to return a :code:`matplotlib.path.Path`, or simply
34
        a tuple of x-y arrays.
35
    closefirst : :class:`bool`
36
        Whether to first close the path by appending the first point again.
37

38
    Returns
39
    --------
40
    :class:`matplotlib.path.Path` | :class:`tuple`
41
        Interpolated :class:`~matplotlib.path.Path` object, if
42
        `aspath` is :code:`True`, else a tuple of x-y arrays.
43
    """
44
    x, y = path.vertices.T
3✔
45
    if x.size > 4:
3✔
46
        if closefirst:
3✔
47
            x = np.append(x, x[0])
3✔
48
            y = np.append(y, y[0])
3✔
49
        # s=0 forces the interpolation to go through every point
50

51
        tck, _ = scipy.interpolate.splprep(
3✔
52
            [x[:-1], y[:-1]], s=0, per=periodic, **kwargs
53
        )
54
        xi, yi = scipy.interpolate.splev(np.linspace(0.0, 1.0, resolution), tck)
3✔
55
        # could get control points for path and construct codes here
56
        codes = None
3✔
57
        pth = matplotlib.path.Path(np.vstack([xi, yi]).T, codes=codes)
3✔
58
        if aspath:
3✔
59
            return pth
3✔
60
        else:
61
            return pth.vertices.T
3✔
62
    else:
63
        return path.vertices.T
×
64

65

66
def interpolated_patch_path(patch, resolution=100, **kwargs):
3✔
67
    """
68
    Obtain the periodic interpolation of the existing path of a patch at a
69
    given resolution.
70

71
    Parameters
72
    -----------
73
    patch : :class:`matplotlib.patches.Patch`
74
        Patch to obtain the original path from.
75
    resolution :class:`int`
76
        Resolution at which to obtain the new path. The verticies of the new path
77
        will have shape (`resolution`, 2).
78

79
    Returns
80
    --------
81
    :class:`matplotlib.path.Path`
82
        Interpolated :class:`~matplotlib.path.Path` object.
83
    """
84
    pth = patch.get_path()
3✔
85
    tfm = patch.get_transform()
3✔
86
    pathtfm = tfm.transform_path(pth)
3✔
87
    return interpolate_path(
3✔
88
        pathtfm, resolution=resolution, aspath=True, periodic=True, **kwargs
89
    )
90

91

92
def get_contour_paths(src, resolution=100, minsize=3):
3✔
93
    """
94
    Extract the paths of contours from a contour plot.
95

96
    Parameters
97
    ------------
98
    ax : :class:`matplotlib.axes.Axes` |
99
        Axes to extract contours from.
100
    resolution : :class:`int`
101
        Resolution of interpolated splines to return.
102

103
    Returns
104
    --------
105
    contourspaths : :class:`list` (:class:`list`)
106
        List of lists, each represnting one line collection (a single contour). In the
107
        case where this contour is multimodal, there will be multiple paths for each
108
        contour.
109
    contournames : :class:`list`
110
        List of names for contours, where they have been labelled, and there are no
111
        other text artists on the figure.
112
    contourstyles : :class:`list`
113
        List of styles for contours.
114

115
    Notes
116
    ------
117
        This method assumes that contours are the only
118
        :code:`matplotlib.collections.LineCollection` objects within an axes;
119
        and when this is not the case, additional non-contour objects will be returned.
120
    """
121
    if isinstance(src, matplotlib.axes.Axes):
3✔
122

123
        def _iscontour(c):
3✔
124
            # contours/default lines don't have markers - allows distinguishing scatter
125
            return (
3✔
126
                isinstance(c, matplotlib.collections.PathCollection)
127
                and c.get_sizes().size == 0
128
            ) or isinstance(c, matplotlib.collections.LineCollection)
129

130
        linecolls = [
3✔
131
            c for c in src.collections if (_iscontour(c) and len(c.get_paths()))
132
        ]
133
        names = [None for lc in linecolls]
3✔
134
        if all([len(a.get_text()) for a in src.texts]):
3✔
135
            if len(src.texts) == len(linecolls):
3✔
136
                names = [a.get_text() for a in src.texts]
3✔
137
            else:
UNCOV
138
                logger.debug("Can't line up labels/text with contours.")
×
139
    elif isinstance(src, matplotlib.contour.ContourSet):
3✔
140
        names = src.labelTexts
3✔
141
        linecolls = src.collections
3✔
142
        linecolls = [c for c in src.collections if len(c.get_paths())]
3✔
143

144
    rgba = [lc.get_edgecolors() for lc in linecolls]
3✔
145
    styles = [{"color": c} for c in rgba]
3✔
146
    return (
3✔
147
        [
148
            [
149
                interpolate_path(
150
                    p,
151
                    resolution=resolution,
152
                    periodic=True,
153
                    aspath=False,
154
                )
155
                for p in lc.get_paths()
156
            ]
157
            for lc in linecolls
158
        ],
159
        names,
160
        styles,
161
    )
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc