IBB-Helper 0.4.8.dev21__tar.gz → 0.4.8.dev22__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.
- {ibb_helper-0.4.8.dev21/src/IBB_Helper.egg-info → ibb_helper-0.4.8.dev22}/PKG-INFO +1 -1
- {ibb_helper-0.4.8.dev21 → ibb_helper-0.4.8.dev22}/pyproject.toml +1 -1
- ibb_helper-0.4.8.dev22/src/IBB_Helper/plot_2d.py +239 -0
- {ibb_helper-0.4.8.dev21 → ibb_helper-0.4.8.dev22/src/IBB_Helper.egg-info}/PKG-INFO +1 -1
- ibb_helper-0.4.8.dev21/src/IBB_Helper/plot_2d.py +0 -243
- {ibb_helper-0.4.8.dev21 → ibb_helper-0.4.8.dev22}/LICENSE +0 -0
- {ibb_helper-0.4.8.dev21 → ibb_helper-0.4.8.dev22}/README.md +0 -0
- {ibb_helper-0.4.8.dev21 → ibb_helper-0.4.8.dev22}/setup.cfg +0 -0
- {ibb_helper-0.4.8.dev21 → ibb_helper-0.4.8.dev22}/setup.py +0 -0
- {ibb_helper-0.4.8.dev21 → ibb_helper-0.4.8.dev22}/src/IBB_Helper/__init__.py +0 -0
- {ibb_helper-0.4.8.dev21 → ibb_helper-0.4.8.dev22}/src/IBB_Helper/animate.py +0 -0
- {ibb_helper-0.4.8.dev21 → ibb_helper-0.4.8.dev22}/src/IBB_Helper/combine_plots.py +0 -0
- {ibb_helper-0.4.8.dev21 → ibb_helper-0.4.8.dev22}/src/IBB_Helper/display.py +0 -0
- {ibb_helper-0.4.8.dev21 → ibb_helper-0.4.8.dev22}/src/IBB_Helper/display_eigen.py +0 -0
- {ibb_helper-0.4.8.dev21 → ibb_helper-0.4.8.dev22}/src/IBB_Helper/display_matrix.py +0 -0
- {ibb_helper-0.4.8.dev21 → ibb_helper-0.4.8.dev22}/src/IBB_Helper/extend_plot.py +0 -0
- {ibb_helper-0.4.8.dev21 → ibb_helper-0.4.8.dev22}/src/IBB_Helper/minimize.py +0 -0
- {ibb_helper-0.4.8.dev21 → ibb_helper-0.4.8.dev22}/src/IBB_Helper/num_int.py +0 -0
- {ibb_helper-0.4.8.dev21 → ibb_helper-0.4.8.dev22}/src/IBB_Helper/plot_3d.py +0 -0
- {ibb_helper-0.4.8.dev21 → ibb_helper-0.4.8.dev22}/src/IBB_Helper/plot_param_grid.py +0 -0
- {ibb_helper-0.4.8.dev21 → ibb_helper-0.4.8.dev22}/src/IBB_Helper/symbolic_BSpline.py +0 -0
- {ibb_helper-0.4.8.dev21 → ibb_helper-0.4.8.dev22}/src/IBB_Helper.egg-info/SOURCES.txt +0 -0
- {ibb_helper-0.4.8.dev21 → ibb_helper-0.4.8.dev22}/src/IBB_Helper.egg-info/dependency_links.txt +0 -0
- {ibb_helper-0.4.8.dev21 → ibb_helper-0.4.8.dev22}/src/IBB_Helper.egg-info/requires.txt +0 -0
- {ibb_helper-0.4.8.dev21 → ibb_helper-0.4.8.dev22}/src/IBB_Helper.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: IBB_Helper
|
|
3
|
-
Version: 0.4.8.
|
|
3
|
+
Version: 0.4.8.dev22
|
|
4
4
|
Summary: Helper functions for symbolic math, matrix visualization, and plotting
|
|
5
5
|
Author-email: "University of Stuttgart, Institute for Structural Mechanics (IBB)" <mvs@ibb.uni-stuttgart.de>
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "IBB_Helper"
|
|
7
|
-
version = "0.4.8.
|
|
7
|
+
version = "0.4.8.dev22"
|
|
8
8
|
description = "Helper functions for symbolic math, matrix visualization, and plotting"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "BSD-3-Clause"
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import sympy as sp
|
|
3
|
+
import matplotlib.pyplot as plt
|
|
4
|
+
from sympy import latex, Matrix
|
|
5
|
+
|
|
6
|
+
def plot_2d(exprs, var, labels=None, line_styles=None, colors=None,
|
|
7
|
+
title=None, xlabel=None, ylabel=None,
|
|
8
|
+
xlim=None, ylim=None, resolution=400, show=True, _break_=None,
|
|
9
|
+
fontsize=14, title_size=None, label_size=None,
|
|
10
|
+
tick_size=None, legend_size=None, linewidth=1,
|
|
11
|
+
swap_axes=False, scaling=None):
|
|
12
|
+
|
|
13
|
+
"""
|
|
14
|
+
Plots 2D curves from symbolic expressions or numeric datasets using Matplotlib.
|
|
15
|
+
|
|
16
|
+
Parameters:
|
|
17
|
+
exprs : Expression, tuple, or list of expressions to plot
|
|
18
|
+
var : Symbol or tuple defining the variable and range
|
|
19
|
+
labels : Labels for each curve (default=None)
|
|
20
|
+
line_styles : Line styles or markers for each curve (default=None)
|
|
21
|
+
colors : Colors for each curve (default=None)
|
|
22
|
+
title : Plot title (default=None)
|
|
23
|
+
xlabel : X-axis label (default=None)
|
|
24
|
+
ylabel : Y-axis label (default=None)
|
|
25
|
+
xlim : X-axis limits as (min, max) (default=None)
|
|
26
|
+
ylim : Y-axis limits as (min, max) (default=None)
|
|
27
|
+
resolution : Number of points used to evaluate symbolic expressions (default=400)
|
|
28
|
+
show : Whether to display the plot (default=True)
|
|
29
|
+
_break_ : List of expressions for which discontinuities should be visually broken (default=None)
|
|
30
|
+
fontsize : Base font size for plot text (default=14)
|
|
31
|
+
title_size : Font size for the title (default=None → fontsize+2)
|
|
32
|
+
label_size : Font size for axis labels (default=None → fontsize)
|
|
33
|
+
tick_size : Font size for tick labels (default=None → fontsize-2)
|
|
34
|
+
legend_size : Font size for legend text (default=None → tick_size)
|
|
35
|
+
swap_axes : If True, swaps x and y axes (default=False)
|
|
36
|
+
scaling : 'constrained'→ equal axis units(default=None)
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
matplotlib Axes
|
|
40
|
+
The generated 2D plot axes
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
# 1. Helper: Break visual discontinuities
|
|
44
|
+
def _break_kinks(y_data):
|
|
45
|
+
dy = np.abs(np.diff(y_data))
|
|
46
|
+
max_dy = np.nanmax(dy)
|
|
47
|
+
if max_dy == 0 or np.isnan(max_dy): return y_data
|
|
48
|
+
threshold = max_dy * 0.5
|
|
49
|
+
y_data = y_data.copy()
|
|
50
|
+
for idx in np.where(dy > threshold)[0]:
|
|
51
|
+
y_data[idx] = np.nan
|
|
52
|
+
y_data[idx + 1] = np.nan
|
|
53
|
+
return y_data
|
|
54
|
+
|
|
55
|
+
# 2. Helper: Smart Labels
|
|
56
|
+
def _smart_label(lbl):
|
|
57
|
+
if isinstance(lbl, str):
|
|
58
|
+
if any(c in lbl for c in ['_', '^', '\\']): return f"${lbl}$"
|
|
59
|
+
return lbl
|
|
60
|
+
return f"${latex(lbl)}$"
|
|
61
|
+
|
|
62
|
+
# 3. Sub-function: Handle Parametric Logic
|
|
63
|
+
def _get_parametric_data(expr, x_sym, x_vals_sample):
|
|
64
|
+
"""
|
|
65
|
+
Handles:
|
|
66
|
+
1. (x_expr, y_expr, (t, min, max)) -> Custom range
|
|
67
|
+
2. (x_expr, y_expr) -> Uses global range
|
|
68
|
+
"""
|
|
69
|
+
# Case A: Custom Range (x, y, (t, min, max))
|
|
70
|
+
if len(expr) == 3:
|
|
71
|
+
x_e, y_e, range_info = expr
|
|
72
|
+
t_sym, t_min, t_max = range_info
|
|
73
|
+
|
|
74
|
+
t_vals = np.linspace(float(t_min), float(t_max), resolution)
|
|
75
|
+
f_x = sp.lambdify(t_sym, x_e, modules='numpy')
|
|
76
|
+
f_y = sp.lambdify(t_sym, y_e, modules='numpy')
|
|
77
|
+
|
|
78
|
+
x_res = f_x(t_vals)
|
|
79
|
+
y_res = f_y(t_vals)
|
|
80
|
+
|
|
81
|
+
# Broadcast scalars
|
|
82
|
+
if not hasattr(x_res, '__len__'): x_res = np.full_like(t_vals, x_res)
|
|
83
|
+
if not hasattr(y_res, '__len__'): y_res = np.full_like(t_vals, y_res)
|
|
84
|
+
|
|
85
|
+
return np.array(x_res).flatten(), np.array(y_res).flatten()
|
|
86
|
+
|
|
87
|
+
# Case B: Global Range (x, y)
|
|
88
|
+
elif len(expr) == 2:
|
|
89
|
+
x_data, y_data = expr
|
|
90
|
+
|
|
91
|
+
# Check if symbolic
|
|
92
|
+
if isinstance(x_data, sp.Basic) or isinstance(y_data, sp.Basic):
|
|
93
|
+
f_x = sp.lambdify(x_sym, x_data, modules='numpy')
|
|
94
|
+
f_y = sp.lambdify(x_sym, y_data, modules='numpy')
|
|
95
|
+
x_data = f_x(x_vals_sample)
|
|
96
|
+
y_data = f_y(x_vals_sample)
|
|
97
|
+
|
|
98
|
+
if hasattr(x_data, '__len__') and not hasattr(y_data, '__len__'):
|
|
99
|
+
y_data = np.full_like(x_data, y_data)
|
|
100
|
+
elif not hasattr(x_data, '__len__') and hasattr(y_data, '__len__'):
|
|
101
|
+
x_data = np.full_like(y_data, x_data)
|
|
102
|
+
|
|
103
|
+
# Check for breaks
|
|
104
|
+
if expr in _break_:
|
|
105
|
+
y_data = _break_kinks(y_data)
|
|
106
|
+
|
|
107
|
+
return x_data, y_data
|
|
108
|
+
|
|
109
|
+
return None, None
|
|
110
|
+
|
|
111
|
+
# 4. Sub-function: Handle Standard y=f(x) Logic
|
|
112
|
+
def _get_standard_data(expr, x_sym, x_vals_sample):
|
|
113
|
+
original_expr = expr
|
|
114
|
+
expr = sp.sympify(expr)
|
|
115
|
+
|
|
116
|
+
if not expr.has(x_sym):
|
|
117
|
+
y_vals = np.full_like(x_vals_sample, float(expr))
|
|
118
|
+
else:
|
|
119
|
+
f = sp.lambdify(x_sym, expr, modules='numpy')
|
|
120
|
+
y_vals = np.array(f(x_vals_sample)).flatten()
|
|
121
|
+
|
|
122
|
+
if original_expr in _break_:
|
|
123
|
+
y_vals = _break_kinks(y_vals)
|
|
124
|
+
|
|
125
|
+
return x_vals_sample, y_vals
|
|
126
|
+
|
|
127
|
+
# 5. Sub-function: Apply Padding
|
|
128
|
+
def _apply_padding(ax, all_x, all_y):
|
|
129
|
+
if not all_x or not all_y: return
|
|
130
|
+
|
|
131
|
+
flat_x = np.concatenate([np.atleast_1d(a) for a in all_x])
|
|
132
|
+
flat_y = np.concatenate([np.atleast_1d(a) for a in all_y])
|
|
133
|
+
|
|
134
|
+
min_x, max_x = np.nanmin(flat_x), np.nanmax(flat_x)
|
|
135
|
+
min_y, max_y = np.nanmin(flat_y), np.nanmax(flat_y)
|
|
136
|
+
|
|
137
|
+
pad_x = (max_x - min_x) * 0.1 if max_x != min_x else 0.5
|
|
138
|
+
pad_y = (max_y - min_y) * 0.1 if max_y != min_y else 0.5
|
|
139
|
+
|
|
140
|
+
ax.set_xlim(min_x - pad_x, max_x + pad_x)
|
|
141
|
+
ax.set_ylim(min_y - pad_y, max_y + pad_y)
|
|
142
|
+
|
|
143
|
+
# MAIN EXECUTION
|
|
144
|
+
|
|
145
|
+
# Font/Size Config
|
|
146
|
+
title_size = title_size or fontsize + 2
|
|
147
|
+
label_size = label_size or fontsize
|
|
148
|
+
tick_size = tick_size or fontsize - 2
|
|
149
|
+
legend_size = legend_size or tick_size
|
|
150
|
+
|
|
151
|
+
# Input Normalization
|
|
152
|
+
if not isinstance(exprs, list): exprs = [exprs]
|
|
153
|
+
if _break_ is None: _break_ = []
|
|
154
|
+
|
|
155
|
+
if isinstance(var, tuple):
|
|
156
|
+
x_sym, x_range = var
|
|
157
|
+
else:
|
|
158
|
+
x_sym = var
|
|
159
|
+
x_range = (-1, 1)
|
|
160
|
+
|
|
161
|
+
x_vals_sample = np.linspace(float(x_range[0]), float(x_range[1]), resolution)
|
|
162
|
+
|
|
163
|
+
# Setup Plot
|
|
164
|
+
fig, ax = plt.subplots()
|
|
165
|
+
marker_symbols = ['o', 's', '^', 'x', '*', 'D', 'p', '+', 'v', '<', '>', '1', '2', '3', '4']
|
|
166
|
+
|
|
167
|
+
all_plot_x = []
|
|
168
|
+
all_plot_y = []
|
|
169
|
+
|
|
170
|
+
# Iterate Expressions
|
|
171
|
+
for i, expr in enumerate(exprs):
|
|
172
|
+
# Style extraction
|
|
173
|
+
style = line_styles[i] if line_styles and i < len(line_styles) else 'solid'
|
|
174
|
+
color = colors[i] if colors and i < len(colors) else None
|
|
175
|
+
raw_label = labels[i] if labels and i < len(labels) else None
|
|
176
|
+
label = _smart_label(raw_label) if raw_label is not None else None
|
|
177
|
+
|
|
178
|
+
marker = None
|
|
179
|
+
if isinstance(expr, Matrix):
|
|
180
|
+
expr = np.array(expr).astype(np.float64).flatten()
|
|
181
|
+
|
|
182
|
+
# DISPATCH LOGIC
|
|
183
|
+
final_x = None
|
|
184
|
+
final_y = None
|
|
185
|
+
|
|
186
|
+
# A. Parametric (Tuple/List)
|
|
187
|
+
if isinstance(expr, (tuple, list)):
|
|
188
|
+
final_x, final_y = _get_parametric_data(expr, x_sym, x_vals_sample)
|
|
189
|
+
|
|
190
|
+
# B. Standard (Expression)
|
|
191
|
+
else:
|
|
192
|
+
final_x, final_y = _get_standard_data(expr, x_sym, x_vals_sample)
|
|
193
|
+
|
|
194
|
+
# C. Handle Markers vs Lines
|
|
195
|
+
if style in marker_symbols:
|
|
196
|
+
marker = style
|
|
197
|
+
style = ''
|
|
198
|
+
|
|
199
|
+
# D. Plot & Collect
|
|
200
|
+
if final_x is not None and final_y is not None:
|
|
201
|
+
if swap_axes:
|
|
202
|
+
ax.plot(final_y, final_x, label=label, linestyle=style,
|
|
203
|
+
color=color, marker=marker, linewidth=linewidth)
|
|
204
|
+
all_plot_x.append(final_y)
|
|
205
|
+
all_plot_y.append(final_x)
|
|
206
|
+
else:
|
|
207
|
+
ax.plot(final_x, final_y, label=label, linestyle=style,
|
|
208
|
+
color=color, marker=marker, linewidth=linewidth)
|
|
209
|
+
all_plot_x.append(final_x)
|
|
210
|
+
all_plot_y.append(final_y)
|
|
211
|
+
|
|
212
|
+
# Apply Auto-Padding
|
|
213
|
+
_apply_padding(ax, all_plot_x, all_plot_y)
|
|
214
|
+
|
|
215
|
+
# Final Styling
|
|
216
|
+
if title: ax.set_title(_smart_label(title), fontsize=title_size)
|
|
217
|
+
|
|
218
|
+
if swap_axes:
|
|
219
|
+
if ylabel: ax.set_xlabel(_smart_label(ylabel), fontsize=label_size)
|
|
220
|
+
if xlabel: ax.set_ylabel(_smart_label(xlabel), fontsize=label_size)
|
|
221
|
+
# Apply Manual Limits (Override Padding)
|
|
222
|
+
if ylim: ax.set_xlim(ylim)
|
|
223
|
+
if xlim: ax.set_ylim(xlim)
|
|
224
|
+
else:
|
|
225
|
+
if xlabel: ax.set_xlabel(_smart_label(xlabel), fontsize=label_size)
|
|
226
|
+
if ylabel: ax.set_ylabel(_smart_label(ylabel), fontsize=label_size)
|
|
227
|
+
# Apply Manual Limits (Override Padding)
|
|
228
|
+
if xlim: ax.set_xlim(xlim)
|
|
229
|
+
if ylim: ax.set_ylim(ylim)
|
|
230
|
+
|
|
231
|
+
ax.tick_params(axis='both', labelsize=tick_size)
|
|
232
|
+
if scaling == 'constrained': ax.set_aspect('equal', adjustable='box')
|
|
233
|
+
if labels: ax.legend(fontsize=legend_size)
|
|
234
|
+
ax.grid(True)
|
|
235
|
+
|
|
236
|
+
if show: plt.show()
|
|
237
|
+
else: plt.close()
|
|
238
|
+
|
|
239
|
+
return ax
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: IBB_Helper
|
|
3
|
-
Version: 0.4.8.
|
|
3
|
+
Version: 0.4.8.dev22
|
|
4
4
|
Summary: Helper functions for symbolic math, matrix visualization, and plotting
|
|
5
5
|
Author-email: "University of Stuttgart, Institute for Structural Mechanics (IBB)" <mvs@ibb.uni-stuttgart.de>
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -1,243 +0,0 @@
|
|
|
1
|
-
import numpy as np
|
|
2
|
-
import sympy as sp
|
|
3
|
-
import matplotlib.pyplot as plt
|
|
4
|
-
from sympy import latex, Matrix
|
|
5
|
-
|
|
6
|
-
def plot_2d(exprs, var, labels=None, line_styles=None, colors=None,
|
|
7
|
-
title=None, xlabel=None, ylabel=None,
|
|
8
|
-
xlim=None, ylim=None, resolution=400, show=True, _break_=None,
|
|
9
|
-
fontsize=14, title_size=None, label_size=None,
|
|
10
|
-
tick_size=None, legend_size=None, linewidth=1,
|
|
11
|
-
swap_axes=False, scaling=None):
|
|
12
|
-
|
|
13
|
-
"""
|
|
14
|
-
Plots 2D curves from symbolic expressions or numeric datasets using Matplotlib.
|
|
15
|
-
|
|
16
|
-
Parameters:
|
|
17
|
-
exprs : Expression, tuple, or list of expressions to plot
|
|
18
|
-
var : Symbol or tuple defining the variable and range
|
|
19
|
-
labels : Labels for each curve (default=None)
|
|
20
|
-
line_styles : Line styles or markers for each curve (default=None)
|
|
21
|
-
colors : Colors for each curve (default=None)
|
|
22
|
-
title : Plot title (default=None)
|
|
23
|
-
xlabel : X-axis label (default=None)
|
|
24
|
-
ylabel : Y-axis label (default=None)
|
|
25
|
-
xlim : X-axis limits as (min, max) (default=None)
|
|
26
|
-
ylim : Y-axis limits as (min, max) (default=None)
|
|
27
|
-
resolution : Number of points used to evaluate symbolic expressions (default=400)
|
|
28
|
-
show : Whether to display the plot (default=True)
|
|
29
|
-
_break_ : List of expressions for which discontinuities should be visually broken (default=None)
|
|
30
|
-
fontsize : Base font size for plot text (default=14)
|
|
31
|
-
title_size : Font size for the title (default=None → fontsize+2)
|
|
32
|
-
label_size : Font size for axis labels (default=None → fontsize)
|
|
33
|
-
tick_size : Font size for tick labels (default=None → fontsize-2)
|
|
34
|
-
legend_size : Font size for legend text (default=None → tick_size)
|
|
35
|
-
swap_axes : If True, swaps x and y axes (default=False)
|
|
36
|
-
scaling : 'constrained'→ equal axis units(default=None)
|
|
37
|
-
|
|
38
|
-
Returns:
|
|
39
|
-
matplotlib Axes
|
|
40
|
-
The generated 2D plot axes
|
|
41
|
-
"""
|
|
42
|
-
|
|
43
|
-
# Font size defaults
|
|
44
|
-
title_size = title_size or fontsize + 2
|
|
45
|
-
label_size = label_size or fontsize
|
|
46
|
-
tick_size = tick_size or fontsize - 2
|
|
47
|
-
legend_size = legend_size or tick_size
|
|
48
|
-
|
|
49
|
-
# Helper functions
|
|
50
|
-
def _break_kinks(y_data):
|
|
51
|
-
dy = np.abs(np.diff(y_data))
|
|
52
|
-
max_dy = np.nanmax(dy)
|
|
53
|
-
if max_dy == 0 or np.isnan(max_dy):
|
|
54
|
-
return y_data
|
|
55
|
-
|
|
56
|
-
threshold = max_dy * 0.5
|
|
57
|
-
y_data = y_data.copy()
|
|
58
|
-
break_indices = np.where(dy > threshold)[0]
|
|
59
|
-
for idx in break_indices:
|
|
60
|
-
y_data[idx] = np.nan
|
|
61
|
-
y_data[idx + 1] = np.nan
|
|
62
|
-
return y_data
|
|
63
|
-
|
|
64
|
-
def smart_label(lbl):
|
|
65
|
-
if isinstance(lbl, str):
|
|
66
|
-
if any(c in lbl for c in ['_', '^', '\\']):
|
|
67
|
-
return f"${lbl}$"
|
|
68
|
-
return lbl
|
|
69
|
-
return f"${latex(lbl)}$"
|
|
70
|
-
|
|
71
|
-
# Input normalization
|
|
72
|
-
if not isinstance(exprs, list):
|
|
73
|
-
exprs = [exprs]
|
|
74
|
-
|
|
75
|
-
if _break_ is None:
|
|
76
|
-
_break_ = []
|
|
77
|
-
|
|
78
|
-
if isinstance(var, tuple):
|
|
79
|
-
x_sym, x_range = var
|
|
80
|
-
else:
|
|
81
|
-
x_sym = var
|
|
82
|
-
x_range = (-1, 1)
|
|
83
|
-
|
|
84
|
-
x_vals_sample = np.linspace(float(x_range[0]), float(x_range[1]), resolution)
|
|
85
|
-
|
|
86
|
-
# Plot setup
|
|
87
|
-
fig, ax = plt.subplots()
|
|
88
|
-
|
|
89
|
-
marker_symbols = [
|
|
90
|
-
'o', 's', '^', 'x', '*', 'D', 'p', '+',
|
|
91
|
-
'v', '<', '>', '1', '2', '3', '4'
|
|
92
|
-
]
|
|
93
|
-
|
|
94
|
-
#Initialize lists to collect all plotted data points
|
|
95
|
-
all_plot_x = []
|
|
96
|
-
all_plot_y = []
|
|
97
|
-
|
|
98
|
-
# Plot expressions
|
|
99
|
-
for i, expr in enumerate(exprs):
|
|
100
|
-
style = line_styles[i] if line_styles and i < len(line_styles) else 'solid'
|
|
101
|
-
color = colors[i] if colors and i < len(colors) else None
|
|
102
|
-
|
|
103
|
-
raw_label = labels[i] if labels and i < len(labels) else None
|
|
104
|
-
label = smart_label(raw_label) if raw_label is not None else None
|
|
105
|
-
|
|
106
|
-
marker = None
|
|
107
|
-
|
|
108
|
-
if isinstance(expr, Matrix):
|
|
109
|
-
expr = np.array(expr).astype(np.float64).flatten()
|
|
110
|
-
|
|
111
|
-
# Variable to hold what we actually plot
|
|
112
|
-
final_x_data = None
|
|
113
|
-
final_y_data = None
|
|
114
|
-
|
|
115
|
-
# Parametric or dataset plot
|
|
116
|
-
if isinstance(expr, (tuple, list)) and len(expr) == 2:
|
|
117
|
-
x_data, y_data = expr
|
|
118
|
-
|
|
119
|
-
if isinstance(x_data, sp.Basic) or isinstance(y_data, sp.Basic):
|
|
120
|
-
f_x = sp.lambdify(x_sym, x_data, modules='numpy')
|
|
121
|
-
f_y = sp.lambdify(x_sym, y_data, modules='numpy')
|
|
122
|
-
x_data = f_x(x_vals_sample)
|
|
123
|
-
y_data = f_y(x_vals_sample)
|
|
124
|
-
|
|
125
|
-
if hasattr(x_data, '__len__') and not hasattr(y_data, '__len__'):
|
|
126
|
-
y_data = np.full_like(x_data, y_data)
|
|
127
|
-
elif not hasattr(x_data, '__len__') and hasattr(y_data, '__len__'):
|
|
128
|
-
x_data = np.full_like(y_data, x_data)
|
|
129
|
-
|
|
130
|
-
if expr in _break_:
|
|
131
|
-
y_data = _break_kinks(y_data)
|
|
132
|
-
|
|
133
|
-
if style in marker_symbols:
|
|
134
|
-
marker = style
|
|
135
|
-
style = ''
|
|
136
|
-
|
|
137
|
-
# Assign to final variables
|
|
138
|
-
final_x_data = x_data
|
|
139
|
-
final_y_data = y_data
|
|
140
|
-
|
|
141
|
-
# Standard y = f(x)
|
|
142
|
-
else:
|
|
143
|
-
original_expr = expr
|
|
144
|
-
expr = sp.sympify(expr)
|
|
145
|
-
|
|
146
|
-
if not expr.has(x_sym):
|
|
147
|
-
y_vals = np.full_like(x_vals_sample, float(expr))
|
|
148
|
-
else:
|
|
149
|
-
f = sp.lambdify(x_sym, expr, modules='numpy')
|
|
150
|
-
y_vals = np.array(f(x_vals_sample)).flatten()
|
|
151
|
-
|
|
152
|
-
if original_expr in _break_:
|
|
153
|
-
y_vals = _break_kinks(y_vals)
|
|
154
|
-
|
|
155
|
-
# Assign to final variables
|
|
156
|
-
final_x_data = x_vals_sample
|
|
157
|
-
final_y_data = y_vals
|
|
158
|
-
|
|
159
|
-
# Re-check style for markers (in case it wasn't caught above)
|
|
160
|
-
if style in marker_symbols:
|
|
161
|
-
marker = style
|
|
162
|
-
style = ''
|
|
163
|
-
|
|
164
|
-
# Execute Plot & Collect Data
|
|
165
|
-
if swap_axes:
|
|
166
|
-
ax.plot(
|
|
167
|
-
final_y_data, final_x_data,
|
|
168
|
-
label=label, linestyle=style, color=color,
|
|
169
|
-
marker=marker, linewidth=linewidth
|
|
170
|
-
)
|
|
171
|
-
#Collect data as it appears on screen (Swapped)
|
|
172
|
-
all_plot_x.append(final_y_data)
|
|
173
|
-
all_plot_y.append(final_x_data)
|
|
174
|
-
else:
|
|
175
|
-
ax.plot(
|
|
176
|
-
final_x_data, final_y_data,
|
|
177
|
-
label=label, linestyle=style, color=color,
|
|
178
|
-
marker=marker, linewidth=linewidth
|
|
179
|
-
)
|
|
180
|
-
#Collect data as it appears on screen (Standard)
|
|
181
|
-
all_plot_x.append(final_x_data)
|
|
182
|
-
all_plot_y.append(final_y_data)
|
|
183
|
-
|
|
184
|
-
#Calculate and apply 10% Padding
|
|
185
|
-
if all_plot_x and all_plot_y:
|
|
186
|
-
# Concatenate all arrays to find global min/max
|
|
187
|
-
# np.atleast_1d ensuresconstant functions don't break concatenation
|
|
188
|
-
flat_x = np.concatenate([np.atleast_1d(a) for a in all_plot_x])
|
|
189
|
-
flat_y = np.concatenate([np.atleast_1d(a) for a in all_plot_y])
|
|
190
|
-
|
|
191
|
-
# Use nanmin/nanmax to ignore gaps from _break_kinks
|
|
192
|
-
min_x, max_x = np.nanmin(flat_x), np.nanmax(flat_x)
|
|
193
|
-
min_y, max_y = np.nanmin(flat_y), np.nanmax(flat_y)
|
|
194
|
-
|
|
195
|
-
# Calculate padding (handle case where max == min)
|
|
196
|
-
pad_x = (max_x - min_x) * 0.2 if max_x != min_x else 0.5
|
|
197
|
-
pad_y = (max_y - min_y) * 0.2 if max_y != min_y else 0.5
|
|
198
|
-
|
|
199
|
-
# Apply padded limits
|
|
200
|
-
# These act as the "Auto" default. They will be overwritten below
|
|
201
|
-
# if the user specifically provided xlim/ylim arguments.
|
|
202
|
-
ax.set_xlim(min_x - pad_x, max_x + pad_x)
|
|
203
|
-
ax.set_ylim(min_y - pad_y, max_y + pad_y)
|
|
204
|
-
|
|
205
|
-
# Styling & Labels
|
|
206
|
-
if title is not None:
|
|
207
|
-
ax.set_title(smart_label(title), fontsize=title_size)
|
|
208
|
-
|
|
209
|
-
if swap_axes:
|
|
210
|
-
if ylabel is not None:
|
|
211
|
-
ax.set_xlabel(smart_label(ylabel), fontsize=label_size)
|
|
212
|
-
if xlabel is not None:
|
|
213
|
-
ax.set_ylabel(smart_label(xlabel), fontsize=label_size)
|
|
214
|
-
else:
|
|
215
|
-
if xlabel is not None:
|
|
216
|
-
ax.set_xlabel(smart_label(xlabel), fontsize=label_size)
|
|
217
|
-
if ylabel is not None:
|
|
218
|
-
ax.set_ylabel(smart_label(ylabel), fontsize=label_size)
|
|
219
|
-
|
|
220
|
-
ax.tick_params(axis='both', labelsize=tick_size)
|
|
221
|
-
|
|
222
|
-
# Manual Limits Override (Manual > Auto Padding)
|
|
223
|
-
if swap_axes:
|
|
224
|
-
if ylim: ax.set_xlim(ylim)
|
|
225
|
-
if xlim: ax.set_ylim(xlim)
|
|
226
|
-
else:
|
|
227
|
-
if xlim: ax.set_xlim(xlim)
|
|
228
|
-
if ylim: ax.set_ylim(ylim)
|
|
229
|
-
|
|
230
|
-
if scaling == 'constrained':
|
|
231
|
-
ax.set_aspect('equal', adjustable='box')
|
|
232
|
-
|
|
233
|
-
if labels:
|
|
234
|
-
ax.legend(fontsize=legend_size)
|
|
235
|
-
|
|
236
|
-
ax.grid(True)
|
|
237
|
-
|
|
238
|
-
if show:
|
|
239
|
-
plt.show()
|
|
240
|
-
else:
|
|
241
|
-
plt.close()
|
|
242
|
-
|
|
243
|
-
return ax
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ibb_helper-0.4.8.dev21 → ibb_helper-0.4.8.dev22}/src/IBB_Helper.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|