compphysutils 0.4.2__tar.gz → 0.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {compphysutils-0.4.2/src/compphysutils.egg-info → compphysutils-0.5.0}/PKG-INFO +1 -1
- {compphysutils-0.4.2 → compphysutils-0.5.0}/setup.cfg +1 -1
- compphysutils-0.5.0/src/compphysutils/__init__.py +2 -0
- compphysutils-0.5.0/src/compphysutils/graphics/Figure.py +172 -0
- compphysutils-0.5.0/src/compphysutils/graphics/__init__.py +5 -0
- compphysutils-0.5.0/src/compphysutils/graphics/atom_plot.py +35 -0
- compphysutils-0.5.0/src/compphysutils/graphics/backends/matplotlib.py +226 -0
- compphysutils-0.5.0/src/compphysutils/graphics/backends/pgfplots.py +594 -0
- compphysutils-0.5.0/src/compphysutils/graphics/decorate/arrow.py +35 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/graphics/decorate/line.py +4 -7
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/graphics/decorate/rect.py +2 -5
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/graphics/decorate/text.py +4 -4
- compphysutils-0.5.0/src/compphysutils/graphics/plot3dcoords +176 -0
- compphysutils-0.5.0/src/compphysutils/graphics/plot_types/colorline.py +15 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/graphics/plot_types/colormap.py +23 -29
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/graphics/plot_types/errorbar.py +6 -6
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/graphics/plot_types/fill_between.py +2 -2
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/graphics/plot_types/level.py +1 -1
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/graphics/plot_types/loglog.py +4 -3
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/graphics/plot_types/quiver.py +29 -17
- compphysutils-0.5.0/src/compphysutils/graphics/plot_types/scatter.py +12 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/graphics/plotconfig +2 -1
- compphysutils-0.5.0/src/compphysutils/graphics/plotter.py +378 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/parser/combine_commands/translate.py +33 -13
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/parser/parser.py +40 -31
- compphysutils-0.5.0/src/compphysutils/parser/post_process/__init__.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/parser/savepoint.py +2 -2
- compphysutils-0.5.0/src/compphysutils/util.py +37 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0/src/compphysutils.egg-info}/PKG-INFO +1 -1
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils.egg-info/SOURCES.txt +6 -0
- compphysutils-0.4.2/src/compphysutils/__init__.py +0 -2
- compphysutils-0.4.2/src/compphysutils/graphics/__init__.py +0 -3
- compphysutils-0.4.2/src/compphysutils/graphics/atom_plot.py +0 -13
- compphysutils-0.4.2/src/compphysutils/graphics/decorate/arrow.py +0 -25
- compphysutils-0.4.2/src/compphysutils/graphics/plot3dcoords +0 -87
- compphysutils-0.4.2/src/compphysutils/graphics/plot_types/scatter.py +0 -6
- compphysutils-0.4.2/src/compphysutils/graphics/plotter.py +0 -376
- {compphysutils-0.4.2 → compphysutils-0.5.0}/COPYING.reference +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/LICENSE +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/MANIFEST.in +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/README.md +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/examples/cluster.cfg +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/examples/na_pyramid_100.cfg +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/pyproject.toml +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/crystalgen/Vector.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/crystalgen/VectorReal.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/crystalgen/VectorRepresentation.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/crystalgen/__init__.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/crystalgen/gencluster +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/crystalgen/generator.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/crystalgen/readCrystalChar.py +0 -0
- {compphysutils-0.4.2/src/compphysutils/graphics/decorate → compphysutils-0.5.0/src/compphysutils/graphics/backends}/__init__.py +0 -0
- {compphysutils-0.4.2/src/compphysutils/graphics/fit_types → compphysutils-0.5.0/src/compphysutils/graphics/decorate}/__init__.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/graphics/decorate/image.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/graphics/decorator.py +0 -0
- {compphysutils-0.4.2/src/compphysutils/graphics/plot_types → compphysutils-0.5.0/src/compphysutils/graphics/fit_types}/__init__.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/graphics/fit_types/inverse.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/graphics/fit_types/linear.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/graphics/fit_types/lorentz_peak.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/graphics/fit_types/quadratic.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/graphics/fitter.py +0 -0
- {compphysutils-0.4.2/src/compphysutils/graphics/transforms → compphysutils-0.5.0/src/compphysutils/graphics/plot_types}/__init__.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/graphics/plot_types/coord.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/graphics/plot_types/line.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/graphics/plot_types/linlog.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/graphics/plotcoords +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/graphics/transformer.py +0 -0
- {compphysutils-0.4.2/src/compphysutils/parser/combine_commands → compphysutils-0.5.0/src/compphysutils/graphics/transforms}/__init__.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/graphics/transforms/log.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/parser/__init__.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/parser/combine.py +0 -0
- {compphysutils-0.4.2/src/compphysutils/parser/parsers → compphysutils-0.5.0/src/compphysutils/parser/combine_commands}/__init__.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/parser/combine_commands/average.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/parser/combine_commands/difference.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/parser/combine_commands/integrate-field-axis.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/parser/combine_commands/join-partial.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/parser/combine_commands/join.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/parser/combine_commands/map-to-fermi-window.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/parser/combine_commands/roll-extract.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/parser/combine_commands/scale.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/parser/combine_commands/sum.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/parser/combine_commands/thermal-average.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/parser/combine_commands/tm-orbital-sum.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/parser/combine_commands/union-partial.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/parser/combine_commands/union.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/parser/parsecoords +0 -0
- {compphysutils-0.4.2/src/compphysutils/parser/post_process → compphysutils-0.5.0/src/compphysutils/parser/parsers}/__init__.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/parser/parsers/cols.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/parser/parsers/coord-aims.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/parser/parsers/coord-cub.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/parser/parsers/coord-tm.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/parser/parsers/coord-xyz.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/parser/parsers/csv.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/parser/parsers/eiger.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/parser/parsers/image.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/parser/parsers/tm-mos.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/parser/post_process/average.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/parser/post_process/gap.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/parser/post_process/level-spacing.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/parser/post_process/levels.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/parser/post_process/mirror.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/parser/post_process/plane-rotate.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/parser/post_process/scale.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/parser/post_processor.py +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/parser/runcombine +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils/parser/runparser +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils.egg-info/dependency_links.txt +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils.egg-info/requires.txt +0 -0
- {compphysutils-0.4.2 → compphysutils-0.5.0}/src/compphysutils.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
class Figure():
|
|
2
|
+
|
|
3
|
+
# List of axes present in this figure
|
|
4
|
+
|
|
5
|
+
def __init__(self):
|
|
6
|
+
# TODO : Design API for axes positioning
|
|
7
|
+
self.axes = []
|
|
8
|
+
# List of export formats supported by the backend
|
|
9
|
+
self.allowed_formats = []
|
|
10
|
+
# Default dimensions - in cm - ratio 4/3
|
|
11
|
+
self.width = 16
|
|
12
|
+
self.height = 12
|
|
13
|
+
|
|
14
|
+
def start(self):
|
|
15
|
+
raise NotImplementedError("Start function for figure not implemented")
|
|
16
|
+
|
|
17
|
+
def end(self):
|
|
18
|
+
raise NotImplementedError("End function for figure not implemented")
|
|
19
|
+
|
|
20
|
+
def save(self, name):
|
|
21
|
+
"""
|
|
22
|
+
Write out the figure to a file.
|
|
23
|
+
Extension should be determined by allowed_formats.
|
|
24
|
+
"""
|
|
25
|
+
raise NotImplementedError("Save not implemented in this backend")
|
|
26
|
+
|
|
27
|
+
class Axes():
|
|
28
|
+
|
|
29
|
+
def __init__(self, figure=False):
|
|
30
|
+
# Axes are added to the figure in this method, if provided
|
|
31
|
+
self.xlim = False
|
|
32
|
+
self.ylim = False
|
|
33
|
+
|
|
34
|
+
self.xticks = False
|
|
35
|
+
self.xtick_labels = False
|
|
36
|
+
self.xticks_swap = False
|
|
37
|
+
self.xticks_rotate = 0.0
|
|
38
|
+
self.yticks = False
|
|
39
|
+
self.ytick_labels = False
|
|
40
|
+
self.yticks_swap = False
|
|
41
|
+
self.yticks_rotate = 0.0
|
|
42
|
+
|
|
43
|
+
# Axes width and height - separate from Figure width and height
|
|
44
|
+
# In cm
|
|
45
|
+
self.width = 16
|
|
46
|
+
self.height = 12
|
|
47
|
+
|
|
48
|
+
# Can be set to "x", "y", "both" or False
|
|
49
|
+
# TODO : Make an enum?
|
|
50
|
+
self.hide_axes = False
|
|
51
|
+
|
|
52
|
+
self.xscale = "lin"
|
|
53
|
+
self.yscale = "lin"
|
|
54
|
+
|
|
55
|
+
# width of the x/y axis
|
|
56
|
+
self.axes_linewidth = 1.0
|
|
57
|
+
|
|
58
|
+
# Axes labels
|
|
59
|
+
self.labels = [False,False]
|
|
60
|
+
# TODO : Needed or not?
|
|
61
|
+
#self.labelPos = [False,False]
|
|
62
|
+
|
|
63
|
+
# Show/hide legend
|
|
64
|
+
self.legend = True
|
|
65
|
+
|
|
66
|
+
# Legend position
|
|
67
|
+
self.legend_pos = False
|
|
68
|
+
|
|
69
|
+
# Number of legend columns
|
|
70
|
+
self.legend_cols = 1
|
|
71
|
+
|
|
72
|
+
def plot(self, x, y, label=False, color=False, linestyle=False):
|
|
73
|
+
"""
|
|
74
|
+
Adds a new dataset to the axes and plots it as a line graph.
|
|
75
|
+
Should be stored in an internal buffer
|
|
76
|
+
and only written out on save/show called from the figure controlling figure
|
|
77
|
+
|
|
78
|
+
label here stands for dataset label for the legend
|
|
79
|
+
"""
|
|
80
|
+
raise NotImplementedError("Plot not implemented in this backend")
|
|
81
|
+
|
|
82
|
+
def scatter(self, x, y, label=False, color=False, markerstyle=False, linestyle=False, markersize=False):
|
|
83
|
+
"""
|
|
84
|
+
Similar to plot, but uses scatter graph instead of the line graph, optionally connects
|
|
85
|
+
the scatter points by a line.
|
|
86
|
+
"""
|
|
87
|
+
raise NotImplementedError("Scatter not implemented in this backend")
|
|
88
|
+
|
|
89
|
+
def errorbar(self, x, y, xerr=False, xmerr=False, yerr=False, ymerr=False, label=False, color=False, markerstyle=False, linestyle=False,
|
|
90
|
+
elinewidth=2, capsize=4, linewidth=0):
|
|
91
|
+
"""
|
|
92
|
+
Extension of the scatter plot to include (so far) symmetric error bars
|
|
93
|
+
"""
|
|
94
|
+
raise NotImplementedError("Errorbar not implemented in this backend")
|
|
95
|
+
|
|
96
|
+
def colormap(self, x, y, c, label=False, cmap=False):
|
|
97
|
+
"""
|
|
98
|
+
Colormap, using already mesh of x y c (two dimensional)
|
|
99
|
+
"""
|
|
100
|
+
raise NotImplementedError("Colormap not implemented in this backend")
|
|
101
|
+
|
|
102
|
+
def colorline(self, x, y, c, linestyle="solid", cmap=False, label=False):
|
|
103
|
+
"""
|
|
104
|
+
Plots 3d data by adding color data to the line plot
|
|
105
|
+
"""
|
|
106
|
+
raise NotImplementedError("Colorline not implemented in this backend")
|
|
107
|
+
|
|
108
|
+
def level(self, xs, lineoffset=0, linelength=1.0, orientation="vertical", label=False, color=False, linestyle=False):
|
|
109
|
+
"""
|
|
110
|
+
One-dimensional data, visualised by stacked lines
|
|
111
|
+
"""
|
|
112
|
+
raise NotImplementedError("Level not implemented in this backend")
|
|
113
|
+
|
|
114
|
+
def quiver(self, x, y, u, v, label=False, color=False):
|
|
115
|
+
"""
|
|
116
|
+
Quiver, plotting arows at (x,y) with size (u,v)
|
|
117
|
+
"""
|
|
118
|
+
raise NotImplementedError("Quiver not implemented in this backend")
|
|
119
|
+
|
|
120
|
+
def fill_between(self, x, low, high, color=False, label=False):
|
|
121
|
+
"""
|
|
122
|
+
Fills the area between two lines, with coordinates given by x and values by low and high
|
|
123
|
+
"""
|
|
124
|
+
raise NotImplementedError("Fill between not implemented in this backend")
|
|
125
|
+
|
|
126
|
+
def inset_axes(self, x, y, width, height):
|
|
127
|
+
"""
|
|
128
|
+
Create the inset axes object
|
|
129
|
+
"""
|
|
130
|
+
raise NotImplementedError("Insets not implemented in this backend")
|
|
131
|
+
|
|
132
|
+
def twinx(self):
|
|
133
|
+
"""
|
|
134
|
+
Creates a twin axis sharing the x axis with current axis
|
|
135
|
+
"""
|
|
136
|
+
raise NotImplementedError("twinx not implemented in this backend")
|
|
137
|
+
|
|
138
|
+
def twiny(self):
|
|
139
|
+
"""
|
|
140
|
+
Creates a twin axis sharing the y axis with current axis
|
|
141
|
+
"""
|
|
142
|
+
raise NotImplementedError("twiny not implemented in this backend")
|
|
143
|
+
|
|
144
|
+
def arrow(self, start=(0.0,0.0), end=(0.0,0.0), transform="data", linestyle="solid", width=1, color="black"):
|
|
145
|
+
"""
|
|
146
|
+
Annotates the axes with an arrow
|
|
147
|
+
"""
|
|
148
|
+
raise NotImplementedError("Arrow not implemented in this backend")
|
|
149
|
+
|
|
150
|
+
def axline(self, coord, vert=False, color="black", style="solid"):
|
|
151
|
+
"""
|
|
152
|
+
Plots an additional line parallel to one of the axes
|
|
153
|
+
"""
|
|
154
|
+
raise NotImplementedError("Axline not implemented in this backend")
|
|
155
|
+
|
|
156
|
+
def text(self, coord, text, transform="axes"):
|
|
157
|
+
"""
|
|
158
|
+
Annotates the axes with a text
|
|
159
|
+
"""
|
|
160
|
+
raise NotImplementedError("text not implemented in this backend")
|
|
161
|
+
|
|
162
|
+
def add_patch(self, patch):
|
|
163
|
+
"""
|
|
164
|
+
Add a previously defined patch -- simple annotation object
|
|
165
|
+
"""
|
|
166
|
+
raise NotImplementedError("add_patch not implemented in this backend")
|
|
167
|
+
|
|
168
|
+
def rect_patch(self, pos_vec, rect_vec, relative=False):
|
|
169
|
+
"""
|
|
170
|
+
Prepares the rectangle patch
|
|
171
|
+
"""
|
|
172
|
+
raise NotImplementedError("rect_patch not implemented in this backend")
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
atom_colors = {
|
|
2
|
+
"H" : [255,255,255,255],
|
|
3
|
+
"C" : [ 80, 80, 80,255],
|
|
4
|
+
"N" : [ 48, 80,248,255],
|
|
5
|
+
"O" : [255, 13, 13,255],
|
|
6
|
+
"S" : [255,255, 48,255],
|
|
7
|
+
"BR" : [166, 41, 41,255],
|
|
8
|
+
"FE" : [210,120, 10,255],
|
|
9
|
+
"CR" : [138,153,199,255],
|
|
10
|
+
"I" : [148, 0,148,255],
|
|
11
|
+
"GE" : [102,143,143,255],
|
|
12
|
+
"AS" : [189,128,227,255],
|
|
13
|
+
"IN" : [166,117,115,255],
|
|
14
|
+
"TE" : [162,122, 50,255],
|
|
15
|
+
"AU" : [255,209, 35,255]
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
atom_sizes = {
|
|
19
|
+
"H" : 0.5,
|
|
20
|
+
"C" : 0.7,
|
|
21
|
+
"N" : 0.7,
|
|
22
|
+
"O" : 0.7,
|
|
23
|
+
"S" : 0.7,
|
|
24
|
+
"BR" : 0.9,
|
|
25
|
+
"FE" : 0.9,
|
|
26
|
+
"CR" : 0.9,
|
|
27
|
+
"I" : 1.0,
|
|
28
|
+
"GE" : 0.9,
|
|
29
|
+
"AS" : 1.0,
|
|
30
|
+
"IN" : 1.0,
|
|
31
|
+
"TE" : 0.9,
|
|
32
|
+
"AU" : 1.5
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
wire_color = [120,120,120,40]
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
from compphysutils.graphics import Figure as FigureBase, Axes as AxesBase
|
|
2
|
+
import matplotlib
|
|
3
|
+
|
|
4
|
+
annotate_cs = {
|
|
5
|
+
"data" : "data",
|
|
6
|
+
"axes" : "axes fraction"
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
class Figure(FigureBase):
|
|
10
|
+
def __init__(self):
|
|
11
|
+
super().__init__()
|
|
12
|
+
self.allowed_formats.append("png")
|
|
13
|
+
self.allowed_formats.append("pdf")
|
|
14
|
+
self.allowed_formats.append("svg")
|
|
15
|
+
self._figure = matplotlib.figure.Figure()
|
|
16
|
+
|
|
17
|
+
def save(self, name):
|
|
18
|
+
# Figure width is governed by width in the first axes
|
|
19
|
+
# DEBUG : Decide on figure vs. axes width
|
|
20
|
+
# Inches conversion
|
|
21
|
+
self._figure.set_figwidth(self.width / 2.54)
|
|
22
|
+
self._figure.set_figheight(self.height / 2.54)
|
|
23
|
+
#if len(self.axes) > 0:
|
|
24
|
+
# if self.axes[0].width:
|
|
25
|
+
# # Value passed must be in inches, stored value in cm
|
|
26
|
+
# self._figure.set_figwidth(self.axes[0].width / 2.54)
|
|
27
|
+
# if self.axes[0].height:
|
|
28
|
+
# # Value passed must be in inches, stored value in cm
|
|
29
|
+
# self._figure.set_figheight(self.axes[0].height / 2.54)
|
|
30
|
+
for i in range(len(self.axes)):
|
|
31
|
+
self.axes[i].save()
|
|
32
|
+
self._figure.savefig(name)
|
|
33
|
+
|
|
34
|
+
class Axes(AxesBase):
|
|
35
|
+
|
|
36
|
+
def __init__(self, figure=False, axes_obj=False):
|
|
37
|
+
super().__init__(figure)
|
|
38
|
+
if not axes_obj:
|
|
39
|
+
if not figure:
|
|
40
|
+
raise ValueError("Need to pass axis object or figure to Axes with matplotlib backend")
|
|
41
|
+
else:
|
|
42
|
+
self._axes = figure._figure.add_subplot(1,1,1)
|
|
43
|
+
else:
|
|
44
|
+
self._axes = axes_obj
|
|
45
|
+
# Cumulative for labels -- to disable legend warnings
|
|
46
|
+
self.legend_labels = False
|
|
47
|
+
if figure:
|
|
48
|
+
figure.axes.append(self)
|
|
49
|
+
|
|
50
|
+
def save(self):
|
|
51
|
+
"""
|
|
52
|
+
Sets the various axes options
|
|
53
|
+
"""
|
|
54
|
+
# Axis limits
|
|
55
|
+
if self.xlim:
|
|
56
|
+
if self.xlim[0] or type(self.xlim[0]) != bool:
|
|
57
|
+
self._axes.set_xlim(left=self.xlim[0])
|
|
58
|
+
if self.xlim[1] or type(self.xlim[1]) != bool:
|
|
59
|
+
self._axes.set_xlim(right=self.xlim[1])
|
|
60
|
+
if self.ylim:
|
|
61
|
+
if self.ylim[0] or type(self.ylim[0]) != bool:
|
|
62
|
+
self._axes.set_ylim(bottom=self.ylim[0])
|
|
63
|
+
if self.ylim[1] or type(self.ylim[1]) != bool:
|
|
64
|
+
self._axes.set_ylim(top=self.ylim[1])
|
|
65
|
+
# Ticks
|
|
66
|
+
# xticks
|
|
67
|
+
if self.xticks:
|
|
68
|
+
if self.xtick_labels:
|
|
69
|
+
self._axes.set_xticks(self.xticks, self.xtick_labels)
|
|
70
|
+
else:
|
|
71
|
+
self._axes.set_xticks(self.xticks)
|
|
72
|
+
if self.xticks_swap:
|
|
73
|
+
self._axes.tick_params(axis="x", top=True, bottom=False, labeltop=True, labelbottom=False)
|
|
74
|
+
if self.xticks_rotate != 0.0:
|
|
75
|
+
self._axes.tick_params(axis="x", labelrotation=self.xticks_rotate, labelrotation_mode="xtick")
|
|
76
|
+
# yticks
|
|
77
|
+
if self.yticks:
|
|
78
|
+
if self.ytick_labels:
|
|
79
|
+
self._axes.set_yticks(self.yticks, self.ytick_labels)
|
|
80
|
+
else:
|
|
81
|
+
self._axes.set_yticks(self.yticks)
|
|
82
|
+
if self.yticks_swap:
|
|
83
|
+
self._axes.tick_params(axis="y", left=False, right=True, labelleft=False, labelright=True)
|
|
84
|
+
if self.yticks_rotate != 0.0:
|
|
85
|
+
self._axes.tick_params(axis="y", labelrotation=self.yticks_rotate, labelrotation_mode="ytick")
|
|
86
|
+
# width and height set in figure
|
|
87
|
+
# Hiding axes
|
|
88
|
+
if self.hide_axes == "both":
|
|
89
|
+
self._axes.set_axis_off()
|
|
90
|
+
elif self.hide_axes == "x":
|
|
91
|
+
self._axes.xaxis.set_axis_off()
|
|
92
|
+
elif self.hide_axes == "y":
|
|
93
|
+
self._axes.yaxis.set_axis_off()
|
|
94
|
+
# axis scaling handled in separate functions
|
|
95
|
+
# axes line width
|
|
96
|
+
if self.axes_linewidth:
|
|
97
|
+
for spine in ["top", "bottom", "left", "right"]:
|
|
98
|
+
self._axes.spines[spine].set_linewidth(self.axes_linewidth)
|
|
99
|
+
# Axis labels
|
|
100
|
+
if self.labels[0]:
|
|
101
|
+
self._axes.set_xlabel(self.labels[0])
|
|
102
|
+
if self.labels[1]:
|
|
103
|
+
self._axes.set_ylabel(self.labels[1])
|
|
104
|
+
# Legend
|
|
105
|
+
legend_kwargs = {}
|
|
106
|
+
if self.legend_pos:
|
|
107
|
+
# translate
|
|
108
|
+
pos_args = self.legend_pos.split()
|
|
109
|
+
if len(pos_args) == 1:
|
|
110
|
+
# just forward loc
|
|
111
|
+
legend_kwargs["loc"] = pos_args[0]
|
|
112
|
+
elif len(pos_args) == 2:
|
|
113
|
+
# just forward loc
|
|
114
|
+
legend_kwargs["loc"] = " ".join(pos_args)
|
|
115
|
+
elif len(pos_args) == 3:
|
|
116
|
+
# Two coords, one loc
|
|
117
|
+
legend_kwargs["loc"] = pos_args[0]
|
|
118
|
+
legend_kwargs["bbox_to_anchor"] = (float(pos_args[1]), float(pos_args[2]))
|
|
119
|
+
else:
|
|
120
|
+
# Full spec
|
|
121
|
+
legend_kwargs["loc"] = " ".join(pos_args[0:2])
|
|
122
|
+
legend_kwargs["bbox_to_anchor"] = (float(pos_args[2]), float(pos_args[3]))
|
|
123
|
+
if self.legend_cols:
|
|
124
|
+
legend_kwargs["ncols"] = int(self.legend_cols)
|
|
125
|
+
if self.legend and self.legend_labels:
|
|
126
|
+
self._axes.legend(**legend_kwargs)
|
|
127
|
+
|
|
128
|
+
def set_xscale(self, scale, base=10):
|
|
129
|
+
self._axes.set_xscale(scale, base=base)
|
|
130
|
+
|
|
131
|
+
def set_yscale(self, scale, base=10):
|
|
132
|
+
self._axes.set_yscale(scale, base=base)
|
|
133
|
+
|
|
134
|
+
def plot(self, x, y, label=False, color=False, linestyle=False):
|
|
135
|
+
self._axes.plot(x, y, label=label, color=color, linestyle=linestyle)
|
|
136
|
+
self.legend_labels = self.legend_labels or bool(label)
|
|
137
|
+
|
|
138
|
+
def scatter(self, x, y, label=False, color=False, markerstyle=False, markersize=1.0, linestyle="-"):
|
|
139
|
+
self._axes.scatter(x, y,
|
|
140
|
+
label=label, c=color, marker=markerstyle, s=markersize, linestyle=linestyle)
|
|
141
|
+
self.legend_labels = self.legend_labels or bool(label)
|
|
142
|
+
|
|
143
|
+
def errorbar(self, x, y, xerr=False, xmerr=False, yerr=False, ymerr=False, label=False, color=False, markerstyle=False, linestyle=False,
|
|
144
|
+
elinewidth=2, capsize=4, linewidth=0):
|
|
145
|
+
# TODO : Asymmetric errorbars
|
|
146
|
+
linestyle = linestyle if linestyle else None
|
|
147
|
+
markerstyle = markerstyle if markerstyle else None
|
|
148
|
+
color = color if color else None
|
|
149
|
+
label = label if label else None
|
|
150
|
+
self._axes.errorbar(x, y, xerr, yerr, color=color, linestyle=linestyle, marker=markerstyle, label=label,
|
|
151
|
+
elinewidth=elinewidth, capsize=capsize, linewidth=linewidth)
|
|
152
|
+
self.legend_labels = self.legend_labels or bool(label)
|
|
153
|
+
|
|
154
|
+
def colormap(self, x, y, c, label=None, cmap=None, norm=None, vmin=None, vmax=None):
|
|
155
|
+
# Use pcolormesh, probably better than imshow, in principle also allows for quadriliterals instead of rectangles
|
|
156
|
+
norm_translator = {
|
|
157
|
+
"lin" : "linear"
|
|
158
|
+
}
|
|
159
|
+
self._axes.pcolormesh(x, y, c, label=label, cmap=cmap, shading="gouraud", norm=norm_translator[norm], vmin=vmin, vmax=vmax)
|
|
160
|
+
self.legend_labels = self.legend_labels or bool(label)
|
|
161
|
+
|
|
162
|
+
def colorline(self, x, y, c, linestyle="solid", cmap=None, label=None):
|
|
163
|
+
# Construct a line collection
|
|
164
|
+
segments = []
|
|
165
|
+
colors = []
|
|
166
|
+
for i in range(len(x)-1):
|
|
167
|
+
segments.append([])
|
|
168
|
+
segments[-1].append([x[i],y[i]])
|
|
169
|
+
segments[-1].append([x[i+1],y[i+1]])
|
|
170
|
+
# Interpolate the color
|
|
171
|
+
colors.append(0.5 * (c[i] + c[i+1]))
|
|
172
|
+
self._axes.add_collection(matplotlib.collections.LineCollection(segments, array=colors))
|
|
173
|
+
# TODO : Labels
|
|
174
|
+
|
|
175
|
+
def level(self, xs, lineoffset=0, linelength=1.0, orientation="vertical", label=None, color=None, linestyle=None):
|
|
176
|
+
eplot = self._axes.eventplot(xs, orientation=orientation, linelengths=linelength, lineoffsets=lineoffset, label=label, color=color, linestyles=linestyle)
|
|
177
|
+
self.legend_labels = self.legend_labels or bool(label)
|
|
178
|
+
|
|
179
|
+
def quiver(self, x, y, u, v, label=None, color=None):
|
|
180
|
+
# Call the quiver function
|
|
181
|
+
# TODO : uv vs xy angles?
|
|
182
|
+
self._axes.quiver(x, y, u, v, label=label, color=color, angles="xy", scale_units="xy", scale=1)
|
|
183
|
+
self.legend_labels = self.legend_labels or bool(label)
|
|
184
|
+
|
|
185
|
+
def fill_between(self, x, low, high, color=None, label=None):
|
|
186
|
+
self._axes.fill_between(x, high, low, color=color, label=label)
|
|
187
|
+
self.legend_labels = self.legend_labels or bool(label)
|
|
188
|
+
|
|
189
|
+
def inset_axes(self, x, y, width, height):
|
|
190
|
+
new_axes_obj = self._axes.inset_axes([x,y,width,height])
|
|
191
|
+
new_axes = Axes(axes_obj=new_axes_obj)
|
|
192
|
+
return new_axes
|
|
193
|
+
|
|
194
|
+
def twinx(self):
|
|
195
|
+
new_axes_obj = self._axes.twinx()
|
|
196
|
+
new_axes = Axes(axes_obj=new_axes_obj)
|
|
197
|
+
return new_axes
|
|
198
|
+
|
|
199
|
+
def twiny(self):
|
|
200
|
+
new_axes_obj = self._axes.twiny()
|
|
201
|
+
new_axes = Axes(axes_obj=new_axes_obj)
|
|
202
|
+
return new_axes
|
|
203
|
+
|
|
204
|
+
def arrow(self, start=(0.0,0.0), end=(0.0,0.0), transform="data", linestyle="solid", width=1, color="black"):
|
|
205
|
+
self._axes.annotate("", xy=end, xytext=start, xycoords=annotate_cs[transform], textcoords=annotate_cs[transform],
|
|
206
|
+
arrowprops={"width" : width, "color" : color, "linestyle" : linestyle})
|
|
207
|
+
|
|
208
|
+
def axline(self, coord, vert=False, color="black", style="solid"):
|
|
209
|
+
if vert:
|
|
210
|
+
self._axes.axvline(coord, color=color, linestyle=style)
|
|
211
|
+
else:
|
|
212
|
+
self._axes.axhline(coord, color=color, linestyle=style)
|
|
213
|
+
|
|
214
|
+
def text(self, coord, text, transform="axes"):
|
|
215
|
+
self._axes.annotate(text, xy=coord, xycoords=annotate_cs[transform])
|
|
216
|
+
|
|
217
|
+
def rect_patch(self, pos_vec, rect_vec, relative=False):
|
|
218
|
+
transform=self._axes.transData
|
|
219
|
+
if relative:
|
|
220
|
+
transform=self._axes.transAxes
|
|
221
|
+
rect = matplotlib.patches.Rectangle(xy=pos_vec, width=rect_vec[0], height=rect_vec[1], transform=transform,
|
|
222
|
+
edgecolor="black", fill=False)
|
|
223
|
+
return rect
|
|
224
|
+
|
|
225
|
+
def add_patch(self, patch):
|
|
226
|
+
self._axes.add_patch(patch)
|