IBB-Helper 0.4.8.dev23__tar.gz → 0.4.8.dev24__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.dev23/src/IBB_Helper.egg-info → ibb_helper-0.4.8.dev24}/PKG-INFO +1 -1
- {ibb_helper-0.4.8.dev23 → ibb_helper-0.4.8.dev24}/pyproject.toml +1 -1
- {ibb_helper-0.4.8.dev23 → ibb_helper-0.4.8.dev24}/src/IBB_Helper/combine_plots.py +95 -82
- {ibb_helper-0.4.8.dev23 → ibb_helper-0.4.8.dev24/src/IBB_Helper.egg-info}/PKG-INFO +1 -1
- {ibb_helper-0.4.8.dev23 → ibb_helper-0.4.8.dev24}/LICENSE +0 -0
- {ibb_helper-0.4.8.dev23 → ibb_helper-0.4.8.dev24}/README.md +0 -0
- {ibb_helper-0.4.8.dev23 → ibb_helper-0.4.8.dev24}/setup.cfg +0 -0
- {ibb_helper-0.4.8.dev23 → ibb_helper-0.4.8.dev24}/setup.py +0 -0
- {ibb_helper-0.4.8.dev23 → ibb_helper-0.4.8.dev24}/src/IBB_Helper/__init__.py +0 -0
- {ibb_helper-0.4.8.dev23 → ibb_helper-0.4.8.dev24}/src/IBB_Helper/animate.py +0 -0
- {ibb_helper-0.4.8.dev23 → ibb_helper-0.4.8.dev24}/src/IBB_Helper/display.py +0 -0
- {ibb_helper-0.4.8.dev23 → ibb_helper-0.4.8.dev24}/src/IBB_Helper/display_eigen.py +0 -0
- {ibb_helper-0.4.8.dev23 → ibb_helper-0.4.8.dev24}/src/IBB_Helper/display_matrix.py +0 -0
- {ibb_helper-0.4.8.dev23 → ibb_helper-0.4.8.dev24}/src/IBB_Helper/extend_plot.py +0 -0
- {ibb_helper-0.4.8.dev23 → ibb_helper-0.4.8.dev24}/src/IBB_Helper/minimize.py +0 -0
- {ibb_helper-0.4.8.dev23 → ibb_helper-0.4.8.dev24}/src/IBB_Helper/num_int.py +0 -0
- {ibb_helper-0.4.8.dev23 → ibb_helper-0.4.8.dev24}/src/IBB_Helper/plot_2d.py +0 -0
- {ibb_helper-0.4.8.dev23 → ibb_helper-0.4.8.dev24}/src/IBB_Helper/plot_3d.py +0 -0
- {ibb_helper-0.4.8.dev23 → ibb_helper-0.4.8.dev24}/src/IBB_Helper/plot_param_grid.py +0 -0
- {ibb_helper-0.4.8.dev23 → ibb_helper-0.4.8.dev24}/src/IBB_Helper/symbolic_BSpline.py +0 -0
- {ibb_helper-0.4.8.dev23 → ibb_helper-0.4.8.dev24}/src/IBB_Helper.egg-info/SOURCES.txt +0 -0
- {ibb_helper-0.4.8.dev23 → ibb_helper-0.4.8.dev24}/src/IBB_Helper.egg-info/dependency_links.txt +0 -0
- {ibb_helper-0.4.8.dev23 → ibb_helper-0.4.8.dev24}/src/IBB_Helper.egg-info/requires.txt +0 -0
- {ibb_helper-0.4.8.dev23 → ibb_helper-0.4.8.dev24}/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.dev24
|
|
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.dev24"
|
|
8
8
|
description = "Helper functions for symbolic math, matrix visualization, and plotting"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "BSD-3-Clause"
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import matplotlib.pyplot as plt
|
|
2
2
|
import plotly.graph_objects as go
|
|
3
3
|
import copy
|
|
4
|
+
import numpy as np
|
|
4
5
|
|
|
5
6
|
def combine_plots(plot_list, labels=None, line_styles=None, colors=None,
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
swap_axes=False, show=True, grid=False,
|
|
8
|
+
xlim=None, ylim=None, title=None, xlabel=None, ylabel=None, width=800, height=700):
|
|
8
9
|
"""
|
|
9
10
|
Combines multiple Matplotlib Axes or Plotly Figures into a single plot while preserving styles.
|
|
10
11
|
|
|
@@ -21,69 +22,80 @@ def combine_plots(plot_list, labels=None, line_styles=None, colors=None,
|
|
|
21
22
|
title : Plot title (default=None)
|
|
22
23
|
xlabel : X-axis label (default=None)
|
|
23
24
|
ylabel : Y-axis label (default=None)
|
|
25
|
+
width : width of the Plotly (default=800)
|
|
26
|
+
height : height of the Plotly (default=700)
|
|
24
27
|
|
|
25
28
|
Returns:
|
|
26
29
|
matplotlib Axes or plotly.graph_objects.Figure
|
|
27
30
|
The combined plot object, matching the input plot type
|
|
28
31
|
"""
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
if not plot_list:
|
|
32
|
-
raise ValueError("plot_list cannot be empty")
|
|
33
|
-
|
|
34
|
-
first_plot = plot_list[0]
|
|
35
32
|
|
|
36
|
-
#
|
|
37
|
-
|
|
33
|
+
# Apply Padding (Matplotlib)
|
|
34
|
+
def _apply_padding(ax, all_x, all_y):
|
|
35
|
+
if not all_x or not all_y:
|
|
36
|
+
return
|
|
37
|
+
|
|
38
|
+
# Concatenate all arrays to find global min/max
|
|
39
|
+
flat_x = np.concatenate([np.atleast_1d(a) for a in all_x])
|
|
40
|
+
flat_y = np.concatenate([np.atleast_1d(a) for a in all_y])
|
|
41
|
+
|
|
42
|
+
# Use nanmin/nanmax to ignore NaNs
|
|
43
|
+
min_x, max_x = np.nanmin(flat_x), np.nanmax(flat_x)
|
|
44
|
+
min_y, max_y = np.nanmin(flat_y), np.nanmax(flat_y)
|
|
38
45
|
|
|
39
|
-
|
|
40
|
-
|
|
46
|
+
# Calculate padding (handle case where max == min)
|
|
47
|
+
pad_x = (max_x - min_x) * 0.1 if max_x != min_x else 0.5
|
|
48
|
+
pad_y = (max_y - min_y) * 0.1 if max_y != min_y else 0.5
|
|
49
|
+
|
|
50
|
+
# Apply padded limits (These act as defaults, overridden by user limits later)
|
|
51
|
+
ax.set_xlim(min_x - pad_x, max_x + pad_x)
|
|
52
|
+
ax.set_ylim(min_y - pad_y, max_y + pad_y)
|
|
53
|
+
|
|
54
|
+
# Matplotlib Handler
|
|
55
|
+
def _handle_matplotlib(plot_list):
|
|
41
56
|
fig, ax = plt.subplots()
|
|
57
|
+
marker_symbols = ['o', 's', '^', 'x', '*', 'D', 'p', '+', 'v', '<', '>', '1', '2', '3', '4']
|
|
42
58
|
|
|
59
|
+
# Lists to collect data for padding calculation
|
|
60
|
+
all_plot_x = []
|
|
61
|
+
all_plot_y = []
|
|
62
|
+
|
|
43
63
|
for i, plot_ax in enumerate(plot_list):
|
|
44
64
|
first_line = True
|
|
45
65
|
|
|
46
66
|
for line in plot_ax.lines:
|
|
47
67
|
x, y = line.get_data()
|
|
48
68
|
|
|
49
|
-
#
|
|
69
|
+
# Retrieve Existing Properties
|
|
50
70
|
current_color = line.get_color()
|
|
51
71
|
current_marker = line.get_marker()
|
|
52
72
|
current_linestyle = line.get_linestyle()
|
|
53
73
|
current_markersize = line.get_markersize()
|
|
54
74
|
current_linewidth = line.get_linewidth()
|
|
55
75
|
|
|
56
|
-
# Normalize marker
|
|
57
|
-
if current_marker in ['None', '']:
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
#
|
|
61
|
-
if current_linestyle in ['None', '']:
|
|
62
|
-
current_linestyle = 'None'
|
|
63
|
-
|
|
64
|
-
# --- 2. Apply Overrides from append_plots Arguments (Only for First Line) ---
|
|
76
|
+
# Normalize marker/linestyle
|
|
77
|
+
if current_marker in ['None', '']: current_marker = None
|
|
78
|
+
if current_linestyle in ['None', '']: current_linestyle = 'None'
|
|
79
|
+
|
|
80
|
+
# Apply Overrides (Only for First Line of the plot)
|
|
65
81
|
if first_line:
|
|
66
|
-
#
|
|
82
|
+
# Style Override
|
|
67
83
|
if line_styles and i < len(line_styles):
|
|
68
84
|
new_style = line_styles[i]
|
|
69
|
-
|
|
70
85
|
if new_style in marker_symbols:
|
|
71
|
-
# Case A: User forces a marker (e.g., 'o', 'x')
|
|
72
86
|
current_marker = new_style
|
|
73
|
-
current_linestyle = 'None'
|
|
87
|
+
current_linestyle = 'None'
|
|
74
88
|
else:
|
|
75
|
-
# Case B: User forces a line style (e.g., '--', 'solid')
|
|
76
89
|
current_linestyle = new_style
|
|
77
|
-
current_marker = None
|
|
90
|
+
current_marker = None
|
|
78
91
|
|
|
79
|
-
# Override
|
|
92
|
+
# Color Override
|
|
80
93
|
if colors and i < len(colors):
|
|
81
94
|
current_color = colors[i]
|
|
82
95
|
|
|
83
|
-
# Apply label only to the first line of the current plot_ax
|
|
84
96
|
label_to_use = labels[i] if first_line and labels and i < len(labels) else None
|
|
85
97
|
|
|
86
|
-
#
|
|
98
|
+
# Plot on New Axes
|
|
87
99
|
if swap_axes:
|
|
88
100
|
ax.plot(y, x,
|
|
89
101
|
color=current_color,
|
|
@@ -92,6 +104,9 @@ def combine_plots(plot_list, labels=None, line_styles=None, colors=None,
|
|
|
92
104
|
markersize=current_markersize,
|
|
93
105
|
linewidth=current_linewidth,
|
|
94
106
|
label=label_to_use)
|
|
107
|
+
# Collect data for padding (Swapped)
|
|
108
|
+
all_plot_x.append(y)
|
|
109
|
+
all_plot_y.append(x)
|
|
95
110
|
else:
|
|
96
111
|
ax.plot(x, y,
|
|
97
112
|
color=current_color,
|
|
@@ -100,92 +115,90 @@ def combine_plots(plot_list, labels=None, line_styles=None, colors=None,
|
|
|
100
115
|
markersize=current_markersize,
|
|
101
116
|
linewidth=current_linewidth,
|
|
102
117
|
label=label_to_use)
|
|
118
|
+
# Collect data for padding (Standard)
|
|
119
|
+
all_plot_x.append(x)
|
|
120
|
+
all_plot_y.append(y)
|
|
103
121
|
|
|
104
122
|
first_line = False
|
|
105
|
-
|
|
106
|
-
#
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
if
|
|
112
|
-
|
|
113
|
-
if xlabel:
|
|
114
|
-
|
|
115
|
-
if
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
ax.grid()
|
|
119
|
-
if labels:
|
|
120
|
-
ax.legend()
|
|
123
|
+
|
|
124
|
+
# Apply 10% Padding
|
|
125
|
+
_apply_padding(ax, all_plot_x, all_plot_y)
|
|
126
|
+
|
|
127
|
+
# Final Config
|
|
128
|
+
if xlim: ax.set_xlim(xlim)
|
|
129
|
+
if ylim: ax.set_ylim(ylim)
|
|
130
|
+
if title: ax.set_title(title)
|
|
131
|
+
if xlabel: ax.set_xlabel(xlabel)
|
|
132
|
+
if ylabel: ax.set_ylabel(ylabel)
|
|
133
|
+
if grid: ax.grid(True)
|
|
134
|
+
if labels: ax.legend()
|
|
135
|
+
|
|
121
136
|
if show:
|
|
122
137
|
plt.show()
|
|
123
138
|
else:
|
|
124
139
|
plt.close()
|
|
125
|
-
|
|
140
|
+
|
|
126
141
|
return ax
|
|
127
142
|
|
|
128
|
-
#
|
|
129
|
-
|
|
143
|
+
# Plotly Handler
|
|
144
|
+
def _handle_plotly(plot_list):
|
|
130
145
|
combined_fig = go.Figure()
|
|
131
146
|
|
|
132
147
|
for i, fig in enumerate(plot_list):
|
|
133
148
|
for trace in fig.data:
|
|
134
|
-
# Use deepcopy for safe cloning of the trace
|
|
135
149
|
new_trace = copy.deepcopy(trace)
|
|
136
150
|
|
|
137
|
-
#
|
|
151
|
+
# Color Override
|
|
138
152
|
if colors and i < len(colors):
|
|
139
|
-
if hasattr(new_trace, 'line'):
|
|
140
|
-
|
|
141
|
-
if hasattr(new_trace, 'marker'):
|
|
142
|
-
new_trace.marker.color = colors[i]
|
|
153
|
+
if hasattr(new_trace, 'line'): new_trace.line.color = colors[i]
|
|
154
|
+
if hasattr(new_trace, 'marker'): new_trace.marker.color = colors[i]
|
|
143
155
|
|
|
144
|
-
#
|
|
156
|
+
# Style Override
|
|
145
157
|
if line_styles and i < len(line_styles):
|
|
146
158
|
if isinstance(new_trace, go.Scatter) and hasattr(new_trace, 'line'):
|
|
147
159
|
new_trace.line.dash = line_styles[i]
|
|
148
160
|
|
|
149
|
-
#
|
|
161
|
+
# Label Override
|
|
150
162
|
if labels and i < len(labels):
|
|
151
163
|
new_trace.name = labels[i]
|
|
152
164
|
|
|
153
|
-
#
|
|
165
|
+
# Swap Axes
|
|
154
166
|
if swap_axes and hasattr(new_trace, 'x') and hasattr(new_trace, 'y'):
|
|
155
167
|
new_trace.x, new_trace.y = new_trace.y, new_trace.x
|
|
156
168
|
|
|
157
169
|
combined_fig.add_trace(new_trace)
|
|
158
170
|
|
|
159
|
-
# Final
|
|
160
|
-
if title:
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
if xlim:
|
|
166
|
-
|
|
167
|
-
if
|
|
168
|
-
combined_fig.update_yaxes(range=ylim)
|
|
169
|
-
if grid:
|
|
170
|
-
combined_fig.update_layout(xaxis_showgrid=True, yaxis_showgrid=True)
|
|
171
|
+
# Final Config
|
|
172
|
+
if title: combined_fig.update_layout(title=title)
|
|
173
|
+
combined_fig.update_layout(
|
|
174
|
+
xaxis_title=xlabel if xlabel else None,
|
|
175
|
+
yaxis_title=ylabel if ylabel else None
|
|
176
|
+
)
|
|
177
|
+
if xlim: combined_fig.update_xaxes(range=xlim)
|
|
178
|
+
if ylim: combined_fig.update_yaxes(range=ylim)
|
|
179
|
+
if grid: combined_fig.update_layout(xaxis_showgrid=True, yaxis_showgrid=True)
|
|
171
180
|
|
|
172
181
|
combined_fig.update_layout(
|
|
173
|
-
autosize=False,
|
|
174
|
-
|
|
175
|
-
height=height,
|
|
176
|
-
scene=dict(
|
|
177
|
-
aspectratio=dict(x=1, y=1, z=1),
|
|
178
|
-
camera=dict(eye=dict(x=1.87, y=0.88, z=1.5)),
|
|
179
|
-
),
|
|
182
|
+
autosize=False, width=width, height=height,
|
|
183
|
+
scene=dict(aspectratio=dict(x=1, y=1, z=1), camera=dict(eye=dict(x=1.87, y=0.88, z=1.5))),
|
|
180
184
|
margin=dict(l=10, r=10, t=50, b=10),
|
|
181
185
|
legend=dict(x=0, y=1),
|
|
182
186
|
)
|
|
183
|
-
|
|
184
187
|
|
|
185
|
-
if show:
|
|
186
|
-
combined_fig.show()
|
|
188
|
+
if show: combined_fig.show()
|
|
187
189
|
|
|
188
190
|
return combined_fig
|
|
189
191
|
|
|
192
|
+
# Main Execution
|
|
193
|
+
if not plot_list:
|
|
194
|
+
raise ValueError("plot_list cannot be empty")
|
|
195
|
+
|
|
196
|
+
first_plot = plot_list[0]
|
|
197
|
+
|
|
198
|
+
# Dispatch based on type
|
|
199
|
+
if hasattr(first_plot, 'lines'):
|
|
200
|
+
return _handle_matplotlib(plot_list)
|
|
201
|
+
elif hasattr(first_plot, 'data'):
|
|
202
|
+
return _handle_plotly(plot_list)
|
|
190
203
|
else:
|
|
191
|
-
raise TypeError("Unknown plot object type passed to
|
|
204
|
+
raise TypeError("Unknown plot object type passed to combine_plots.")
|
|
@@ -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.dev24
|
|
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
|
|
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.dev23 → ibb_helper-0.4.8.dev24}/src/IBB_Helper.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|