IBB-Helper 0.4.8.dev28__tar.gz → 0.4.8.dev30__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.
Files changed (34) hide show
  1. {ibb_helper-0.4.8.dev28/src/IBB_Helper.egg-info → ibb_helper-0.4.8.dev30}/PKG-INFO +1 -1
  2. {ibb_helper-0.4.8.dev28 → ibb_helper-0.4.8.dev30}/pyproject.toml +1 -1
  3. ibb_helper-0.4.8.dev30/src/IBB_Helper/animate.py +249 -0
  4. {ibb_helper-0.4.8.dev28 → ibb_helper-0.4.8.dev30}/src/IBB_Helper/combine_plots.py +14 -3
  5. ibb_helper-0.4.8.dev30/src/IBB_Helper/display.py +65 -0
  6. ibb_helper-0.4.8.dev30/src/IBB_Helper/display_eigen.py +127 -0
  7. ibb_helper-0.4.8.dev30/src/IBB_Helper/display_matrix.py +59 -0
  8. ibb_helper-0.4.8.dev30/src/IBB_Helper/extend_plot.py +221 -0
  9. ibb_helper-0.4.8.dev30/src/IBB_Helper/minimize.py +68 -0
  10. ibb_helper-0.4.8.dev30/src/IBB_Helper/num_int.py +84 -0
  11. {ibb_helper-0.4.8.dev28 → ibb_helper-0.4.8.dev30}/src/IBB_Helper/plot_2d.py +23 -10
  12. ibb_helper-0.4.8.dev30/src/IBB_Helper/plot_3d.py +142 -0
  13. ibb_helper-0.4.8.dev30/src/IBB_Helper/plot_param_grid.py +156 -0
  14. ibb_helper-0.4.8.dev30/src/IBB_Helper/symbolic_BSpline.py +77 -0
  15. {ibb_helper-0.4.8.dev28 → ibb_helper-0.4.8.dev30/src/IBB_Helper.egg-info}/PKG-INFO +1 -1
  16. ibb_helper-0.4.8.dev28/src/IBB_Helper/animate.py +0 -206
  17. ibb_helper-0.4.8.dev28/src/IBB_Helper/display.py +0 -59
  18. ibb_helper-0.4.8.dev28/src/IBB_Helper/display_eigen.py +0 -108
  19. ibb_helper-0.4.8.dev28/src/IBB_Helper/display_matrix.py +0 -47
  20. ibb_helper-0.4.8.dev28/src/IBB_Helper/extend_plot.py +0 -240
  21. ibb_helper-0.4.8.dev28/src/IBB_Helper/minimize.py +0 -64
  22. ibb_helper-0.4.8.dev28/src/IBB_Helper/num_int.py +0 -73
  23. ibb_helper-0.4.8.dev28/src/IBB_Helper/plot_3d.py +0 -136
  24. ibb_helper-0.4.8.dev28/src/IBB_Helper/plot_param_grid.py +0 -102
  25. ibb_helper-0.4.8.dev28/src/IBB_Helper/symbolic_BSpline.py +0 -60
  26. {ibb_helper-0.4.8.dev28 → ibb_helper-0.4.8.dev30}/LICENSE +0 -0
  27. {ibb_helper-0.4.8.dev28 → ibb_helper-0.4.8.dev30}/README.md +0 -0
  28. {ibb_helper-0.4.8.dev28 → ibb_helper-0.4.8.dev30}/setup.cfg +0 -0
  29. {ibb_helper-0.4.8.dev28 → ibb_helper-0.4.8.dev30}/setup.py +0 -0
  30. {ibb_helper-0.4.8.dev28 → ibb_helper-0.4.8.dev30}/src/IBB_Helper/__init__.py +0 -0
  31. {ibb_helper-0.4.8.dev28 → ibb_helper-0.4.8.dev30}/src/IBB_Helper.egg-info/SOURCES.txt +0 -0
  32. {ibb_helper-0.4.8.dev28 → ibb_helper-0.4.8.dev30}/src/IBB_Helper.egg-info/dependency_links.txt +0 -0
  33. {ibb_helper-0.4.8.dev28 → ibb_helper-0.4.8.dev30}/src/IBB_Helper.egg-info/requires.txt +0 -0
  34. {ibb_helper-0.4.8.dev28 → ibb_helper-0.4.8.dev30}/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.dev28
3
+ Version: 0.4.8.dev30
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.dev28"
7
+ version = "0.4.8.dev30"
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,249 @@
1
+ import numpy as np
2
+ import sympy as sp
3
+ import matplotlib.pyplot as plt
4
+ import matplotlib.animation
5
+ from sympy import latex, Matrix
6
+
7
+ def animate(exprs, var,
8
+ # --- Labels & Text ---
9
+ labels=None, title="Animation", xlabel="x", ylabel="y",
10
+ # --- Styling ---
11
+ line_styles=None, colors=None, linewidth=2,
12
+ # --- Limits ---
13
+ xlim=None, ylim=None,
14
+ # --- Animation Config ---
15
+ animation_time=5000, frames=100, resolution=400, show=True):
16
+
17
+ """
18
+ Animates 2D curves from symbolic expressions or numeric datasets using Matplotlib.
19
+
20
+ Parameters:
21
+ exprs : Expression, tuple, or list of expressions (symbolic, parametric, or numeric data)
22
+ var : Symbol or tuple defining variable/range, or array mode ('array', x_values)
23
+
24
+ # --- Labels ---
25
+ labels : Curve labels (strings or SymPy expressions, LaTeX supported) (default=None)
26
+ title : Plot title (default="Animation")
27
+ xlabel : X-axis label (default="x")
28
+ ylabel : Y-axis label (default="y")
29
+
30
+ # --- Styling ---
31
+ line_styles : Line styles for each curve (default=None -> solid)
32
+ colors : Colors for each curve (default=None -> Matplotlib cycle)
33
+ linewidth : Line width(s) as int or list (default=2)
34
+
35
+ # --- Limits ---
36
+ xlim : X-axis limits as (min, max) (default=None -> auto)
37
+ ylim : Y-axis limits as (min, max) (default=None -> auto)
38
+
39
+ # --- Animation Config ---
40
+ animation_time : Total animation duration in milliseconds (default=5000)
41
+ frames : Number of animation frames (default=100)
42
+ resolution : Number of evaluation points for symbolic expressions (default=400)
43
+ show : Whether to display the animation (default=True)
44
+
45
+ Returns:
46
+ matplotlib.animation.FuncAnimation
47
+ The animation object
48
+ """
49
+
50
+ # Configuration
51
+ plt.rcParams["animation.html"] = "jshtml"
52
+ plt.rcParams['figure.dpi'] = 150
53
+ plt.ioff()
54
+
55
+ # Label Formatting
56
+ def _smart_label(lbl):
57
+ """Converts strings or SymPy objects to LaTeX formatted strings."""
58
+ if lbl is None:
59
+ return None
60
+ if isinstance(lbl, str):
61
+ # Check for LaTeX characters
62
+ if any(c in lbl for c in ['_', '^', '\\', '$']):
63
+ return f"${lbl}$" if '$' not in lbl else lbl
64
+ return lbl
65
+ # Convert SymPy expression to LaTeX
66
+ return f"${latex(lbl)}$"
67
+
68
+ # Data Preparation
69
+ def _prepare_data(raw_exprs, variable_def):
70
+ """
71
+ Parses inputs (Symbolic/Numeric) and generates consistent (x, y) arrays.
72
+ """
73
+ # Normalize inputs to lists
74
+ if not isinstance(raw_exprs, list):
75
+ expr_list = [raw_exprs]
76
+ else:
77
+ expr_list = raw_exprs
78
+
79
+ # Determine symbol and range
80
+ is_sympy_mode = True
81
+
82
+ if isinstance(variable_def, tuple):
83
+ if variable_def[0] == 'array':
84
+ is_sympy_mode = False
85
+ x_vals_sample = variable_def[1]
86
+ # If array mode, frames usually equals array length
87
+ nonlocal frames
88
+ frames = len(x_vals_sample)
89
+ x_sym = None
90
+ else:
91
+ x_sym = variable_def[0]
92
+ x_range = variable_def[1]
93
+ x_vals_sample = np.linspace(float(x_range[0]), float(x_range[1]), frames)
94
+ else:
95
+ x_sym = variable_def
96
+ x_range = (-1, 1)
97
+ x_vals_sample = np.linspace(float(x_range[0]), float(x_range[1]), frames)
98
+
99
+ prepared_data = []
100
+
101
+ for expr in expr_list:
102
+ # Handle SymPy Matrices
103
+ if isinstance(expr, Matrix):
104
+ expr = np.array(expr).astype(np.float64).flatten()
105
+
106
+ # Handle Parametric or Data Tuples (x, y)
107
+ if isinstance(expr, (tuple, list)) and len(expr) == 2:
108
+ x_comp, y_comp = expr
109
+
110
+ # Symbolic Parametric
111
+ if isinstance(x_comp, sp.Basic) or isinstance(y_comp, sp.Basic):
112
+ if is_sympy_mode:
113
+ f_x = sp.lambdify(x_sym, x_comp, modules='numpy')
114
+ f_y = sp.lambdify(x_sym, y_comp, modules='numpy')
115
+ x_data = f_x(x_vals_sample)
116
+ y_data = f_y(x_vals_sample)
117
+ else:
118
+ # Fallback if mixed types (shouldn't happen often)
119
+ x_data, y_data = x_comp, y_comp
120
+ else:
121
+ # Numeric Data or Constants
122
+ x_data, y_data = x_comp, y_comp
123
+
124
+ # specific check for constant arrays
125
+ is_x_array = hasattr(x_data, '__len__')
126
+ is_y_array = hasattr(y_data, '__len__')
127
+
128
+ if is_x_array and not is_y_array:
129
+ y_data = np.full_like(x_data, y_data)
130
+ elif not is_x_array and is_y_array:
131
+ x_data = np.full_like(y_data, x_data)
132
+
133
+ prepared_data.append((np.array(x_data), np.array(y_data)))
134
+
135
+ # Handle Single Expressions (y = f(x))
136
+ else:
137
+ expr = sp.sympify(expr)
138
+
139
+ # Constant function check
140
+ if is_sympy_mode and not expr.has(x_sym):
141
+ y_vals = np.full_like(x_vals_sample, float(expr))
142
+ else:
143
+ if is_sympy_mode:
144
+ f = sp.lambdify(x_sym, expr, modules='numpy')
145
+ try:
146
+ y_vals = f(x_vals_sample)
147
+ # Handle case where lambdify returns a scalar for vector input
148
+ if np.isscalar(y_vals):
149
+ y_vals = np.full_like(x_vals_sample, y_vals)
150
+ except Exception:
151
+ # Fallback for complex constant expressions
152
+ y_vals = np.full_like(x_vals_sample, float(expr))
153
+ else:
154
+ y_vals = np.array(expr).flatten()
155
+
156
+ y_vals = np.array(y_vals).flatten()
157
+ prepared_data.append((x_vals_sample, y_vals))
158
+
159
+ return prepared_data
160
+
161
+ # Animation Logic
162
+ def _create_animation_object(plot_data):
163
+ """Sets up the figure, axes, and FuncAnimation object."""
164
+
165
+ # 1. Normalize Styling
166
+ n_plots = len(plot_data)
167
+
168
+ # Thickness
169
+ if isinstance(linewidth, (int, float)):
170
+ lw_list = [linewidth] * n_plots
171
+ else:
172
+ lw_list = linewidth
173
+
174
+ # Limits Calculation (if None)
175
+ nonlocal xlim, ylim
176
+ if xlim is None:
177
+ all_x = np.concatenate([d[0] for d in plot_data])
178
+ x_min, x_max = np.min(all_x), np.max(all_x)
179
+ dx = x_max - x_min if x_max != x_min else 1.0
180
+ xlim = (x_min - 0.05 * dx, x_max + 0.05 * dx)
181
+
182
+ if ylim is None:
183
+ all_y = np.concatenate([d[1] for d in plot_data])
184
+ y_min, y_max = np.min(all_y), np.max(all_y)
185
+ dy = y_max - y_min if y_max != y_min else 1.0
186
+ ylim = (y_min - 0.1 * dy, y_max + 0.1 * dy)
187
+
188
+ # 2. Setup Figure
189
+ fig, ax = plt.subplots(figsize=(10, 6))
190
+
191
+ # 3. Update Function
192
+ def _update_frame(frame):
193
+ ax.clear()
194
+
195
+ # Use 'frame + 1' to ensure we plot at least one point
196
+ idx = int(frame + 1)
197
+
198
+ for i, (x_data, y_data) in enumerate(plot_data):
199
+ # Safe Styling Retrieval
200
+ style = line_styles[i] if line_styles and i < len(line_styles) else 'solid'
201
+ color = colors[i] if colors and i < len(colors) else None
202
+
203
+ # Label Handling
204
+ raw_lbl = labels[i] if labels and i < len(labels) else None
205
+ lbl = _smart_label(raw_lbl)
206
+
207
+ # Slice data for animation effect
208
+ # Ensure we don't index out of bounds if frames > data length
209
+ curr_x = x_data[:min(idx, len(x_data))]
210
+ curr_y = y_data[:min(idx, len(y_data))]
211
+
212
+ ax.plot(curr_x, curr_y,
213
+ label=lbl,
214
+ linestyle=style,
215
+ color=color,
216
+ linewidth=lw_list[i] if i < len(lw_list) else 2)
217
+
218
+ # Apply Layout Settings
219
+ ax.set_xlim(xlim)
220
+ ax.set_ylim(ylim)
221
+ ax.set_title(_smart_label(title))
222
+ ax.set_xlabel(_smart_label(xlabel))
223
+ ax.set_ylabel(_smart_label(ylabel))
224
+
225
+ if labels:
226
+ ax.legend()
227
+ ax.grid(True, alpha=0.3)
228
+
229
+ # 4. Create Animation
230
+ interval = animation_time / frames
231
+ anim = matplotlib.animation.FuncAnimation(
232
+ fig, _update_frame, frames=frames, interval=interval, repeat=True
233
+ )
234
+
235
+ return anim
236
+
237
+ # Main Execution
238
+
239
+ # 1. Prepare Data
240
+ data = _prepare_data(exprs, var)
241
+
242
+ # 2. Create Animation
243
+ anim_obj = _create_animation_object(data)
244
+
245
+ # 3. Display
246
+ if not show:
247
+ plt.close()
248
+
249
+ return anim_obj
@@ -3,9 +3,20 @@ import plotly.graph_objects as go
3
3
  import copy
4
4
  import numpy as np
5
5
 
6
- def combine_plots(plot_list, labels=None, line_styles=None, colors=None,
7
- swap_axes=False, show=True, grid=False,
8
- xlim=None, ylim=None, title=None, xlabel=None, ylabel=None, width=800, height=700):
6
+ def combine_plots(plot_list,
7
+ # --- Plot Labels ---
8
+ title=None, xlabel=None, ylabel=None, labels=None,
9
+ # --- Styling ---
10
+ colors=None, line_styles=None,
11
+ # --- Axis Options ---
12
+ swap_axes=False, grid=False,
13
+ # --- Limits ---
14
+ xlim=None, ylim=None,
15
+ # --- Display ---
16
+ show=True,
17
+ # --- Figure Size ---
18
+ width=800, height=700):
19
+
9
20
  """
10
21
  Combines multiple Matplotlib Axes or Plotly Figures into a single plot while preserving styles.
11
22
 
@@ -0,0 +1,65 @@
1
+ import numpy as np
2
+ import sympy as sp
3
+ from sympy import latex
4
+ import IPython.display as ipy
5
+
6
+ def display(obj, name=None, evalf=False, prec=5, mathrm=False):
7
+ """
8
+ Converts vectors/numbers/matrices to LaTeX with optional simplification using internal helpers.
9
+
10
+ Parameters:
11
+ obj : Input (SymPy or NumPy object)
12
+ name : Name used for display
13
+ evalf : If True, evaluates to decimal form before display (default: False)
14
+ prec : Evaluate the given formula to an accuracy of prec digits (default: 5)
15
+ mathrm : Boolean to display as Roman text
16
+
17
+ Returns:
18
+ None
19
+ """
20
+ # Safe Rounding Helper
21
+ def _safe_round(x):
22
+ try:
23
+ x = sp.sympify(x)
24
+ return x.replace(
25
+ lambda a: isinstance(a, sp.Float),
26
+ lambda a: sp.Float(round(float(a), prec))
27
+ )
28
+ except (TypeError, ValueError):
29
+ return x
30
+
31
+ # Object Preparation
32
+ def _prepare_object(raw_obj):
33
+ # 1. Standardization: Convert to SymPy types
34
+ if isinstance(raw_obj, np.ndarray):
35
+ sym_obj = sp.Matrix(raw_obj)
36
+ elif isinstance(raw_obj, (sp.Matrix, list)):
37
+ sym_obj = sp.Matrix(raw_obj)
38
+ elif isinstance(raw_obj, sp.NDimArray):
39
+ sym_obj = raw_obj
40
+ else:
41
+ sym_obj = sp.sympify(raw_obj)
42
+
43
+ # 2. Evaluation: Apply rounding if requested
44
+ if evalf:
45
+ if hasattr(sym_obj, 'applyfunc'):
46
+ return sym_obj.applyfunc(_safe_round)
47
+ return _safe_round(sym_obj)
48
+
49
+ return sym_obj
50
+
51
+ # Rendering
52
+ def _render(processed_obj):
53
+ latex_str = latex(processed_obj)
54
+
55
+ if mathrm:
56
+ latex_str = rf"\mathrm{{{latex_str}}}"
57
+
58
+ if name is None:
59
+ ipy.display(ipy.Math(latex_str))
60
+ else:
61
+ ipy.display(ipy.Math(f"{name} = {latex_str}"))
62
+
63
+ # Main Execution
64
+ final_obj = _prepare_object(obj)
65
+ _render(final_obj)
@@ -0,0 +1,127 @@
1
+ import numpy as np
2
+ import sympy as sp
3
+ from sympy import latex
4
+ import IPython.display as ipy
5
+
6
+ def display_eigen(A,
7
+ # --- Labeling & Formatting ---
8
+ name="Matrix", evalf=False, prec=5,
9
+ # --- Output Control ---
10
+ show="both", output="default", return_data=False, reverse=False):
11
+
12
+ """
13
+ Computes and displays the eigenvalues and eigenvectors of a matrix A using internal sub-functions.
14
+
15
+ Parameters:
16
+ A : Square matrix (SymPy Matrix or NumPy ndarray)
17
+ name : Label used for the matrix (default="Matrix")
18
+ evalf : If True, show decimal values (default=False)
19
+ prec : Accuracy of decimal evaluation (default: 5)
20
+ show : What to display ("both", "eigvals", "eigvecs", or "none") (default="both")
21
+ output : How to display ("default", "compact", "Maple") (default="default")
22
+ return_data : If True, returns eigenvalues and eigenvectors (default=False)
23
+ reverse : If True, sorts eigenvalues in descending order (default=False)
24
+
25
+ Returns (if return_data=True):
26
+ - sp.Matrix: Column vector of eigenvalues
27
+ - sp.Matrix: Matrix of eigenvectors (stacked columns)
28
+ """
29
+
30
+ threshold = 10**(-10)
31
+
32
+ # Safe Evaluation
33
+ def _safe_eval(x):
34
+ try:
35
+ val = x.evalf(prec)
36
+ if abs(val) < threshold:
37
+ return sp.Integer(0)
38
+ return round(float(val), prec)
39
+ except (TypeError, ValueError):
40
+ return x
41
+
42
+ # Compute & Process Data
43
+ def _compute_eigen_data(matrix_in):
44
+ # Convert NumPy array if needed
45
+ if isinstance(matrix_in, np.ndarray):
46
+ matrix_in = sp.Matrix(matrix_in)
47
+
48
+ # Compute raw eigen data: list of (eigenval, multiplicity, [eigenvecs])
49
+ raw_data = sorted(matrix_in.eigenvects(), key=lambda x: x[0], reverse=reverse)
50
+
51
+ vals_clean = []
52
+ vecs_clean = []
53
+
54
+ for eigval, mult, vects in raw_data:
55
+ for i in range(mult):
56
+ v_raw = vects[i]
57
+
58
+ # Normalize vector by its largest element for cleaner display
59
+ max_val = max(v_raw, key=lambda x: abs(x.evalf()))
60
+ v_norm = v_raw / max_val
61
+
62
+ # Apply numerical formatting if requested
63
+ if evalf:
64
+ val_processed = _safe_eval(eigval)
65
+ vec_processed = v_norm.applyfunc(_safe_eval)
66
+ else:
67
+ val_processed = eigval
68
+ vec_processed = v_norm
69
+
70
+ vals_clean.append(val_processed)
71
+ vecs_clean.append(vec_processed)
72
+
73
+ return vals_clean, vecs_clean
74
+
75
+ # Render Output
76
+ def _render_display(vals, vecs):
77
+ # Header
78
+ if show == "both":
79
+ ipy.display(ipy.Math(f"\\text{{Eigenvalues and Eigenvectors of }} {name}:"))
80
+
81
+ if output == "default":
82
+ for i, (val, vec) in enumerate(zip(vals, vecs)):
83
+ latex_str = f"\\lambda_{{{i+1}}} = {latex(val)}, v_{{{i+1}}} = {latex(vec)} \\qquad"
84
+ ipy.display(ipy.Math(latex_str))
85
+
86
+ elif output == "compact":
87
+ for i, (val, vec) in enumerate(zip(vals, vecs)):
88
+ # Transpose vector for compact row view
89
+ latex_str = f"\\lambda_{{{i+1}}} = {latex(val)}, \\quad v_{{{i+1}}} = {latex(vec.T)}"
90
+ ipy.display(ipy.Math(latex_str))
91
+
92
+ elif output == "maple":
93
+ # Vector of eigenvalues
94
+ ipy.display(ipy.Math(f"\\lambda = {latex(sp.Matrix(vals))}"))
95
+ # Matrix of eigenvectors
96
+ V_matrix = sp.Matrix.hstack(*vecs)
97
+ ipy.display(ipy.Math(f"v = {latex(V_matrix)}"))
98
+
99
+ elif show == "eigvals":
100
+ ipy.display(ipy.Math(f"\\text{{Eigenvalues of }} {name}: \\quad \\lambda = {latex(sp.Matrix(vals))}"))
101
+
102
+ elif show == "eigvecs":
103
+ V_matrix = sp.Matrix.hstack(*vecs)
104
+ ipy.display(ipy.Math(f"\\text{{Eigenvectors of }} {name}: \\quad v = {latex(V_matrix)}"))
105
+
106
+ # Main Execution Flow
107
+
108
+ # Validation
109
+ show_opt = show.lower()
110
+ out_opt = output.lower()
111
+ if show_opt not in ["both", "eigvals", "eigvecs", "none"]:
112
+ raise ValueError(f"Invalid 'show' option: {show}")
113
+ if out_opt not in ["default", "compact", "maple"]:
114
+ raise ValueError(f"Invalid 'output' option: {output}")
115
+
116
+ # Computation
117
+ eig_vals, eig_vecs = _compute_eigen_data(A)
118
+
119
+ # Display
120
+ if show_opt != "none":
121
+ _render_display(eig_vals, eig_vecs)
122
+
123
+ # Return Data
124
+ if return_data:
125
+ return sp.Matrix(eig_vals), sp.Matrix.hstack(*eig_vecs)
126
+
127
+ return None
@@ -0,0 +1,59 @@
1
+ import numpy as np
2
+ import sympy as sp
3
+ from sympy import latex
4
+ from IPython.display import Math, display
5
+
6
+ def display_matrix(matrix, name="Matrix", r=8, c=8, evalf=False, prec=5, mathrm=True):
7
+ """
8
+ Displays a truncated matrix with optional numerical evaluation and rational simplification.
9
+
10
+ Parameters:
11
+ matrix : Input matrix (NumPy array, SymPy Matrix, or list)
12
+ name : Display name (default: "Matrix")
13
+ r : Max rows to display (default: 8)
14
+ c : Max columns to display (default: 8)
15
+ evalf : If True, apply numerical evaluation (default: False)
16
+ prec : Evaluate the given formula to an accuracy of prec digits
17
+ mathrm : Boolean to display as Roman text (default: True)
18
+
19
+ Returns:
20
+ None
21
+ """
22
+
23
+ # Matrix Preparation
24
+ def _prepare_matrix(raw_mat):
25
+ if isinstance(raw_mat, (np.ndarray, list)):
26
+ return sp.Matrix(raw_mat)
27
+ return raw_mat
28
+
29
+ # Processing (Truncation & Evaluation)
30
+ def _process_submatrix(full_mat):
31
+ # Truncate
32
+ sub = full_mat[:min(r, full_mat.rows), :min(c, full_mat.cols)]
33
+
34
+ # Evaluate
35
+ if evalf:
36
+ return sub.applyfunc(lambda x: x.evalf(prec))
37
+ return sub
38
+
39
+ # Rendering
40
+ def _render(processed_sub, original_rows, original_cols):
41
+ # Generate LaTeX with spacing adjustment
42
+ expr = latex(processed_sub).replace(r'\\', r'\\[5pt]')
43
+
44
+ if mathrm:
45
+ expr = rf"\mathrm{{{expr}}}"
46
+
47
+ # Display Main Equation
48
+ label = rf"\large {name} =" if name else r"\large"
49
+ display(Math(rf"{label} {expr}"))
50
+
51
+ # Display Truncation Message
52
+ if original_rows > r or original_cols > c:
53
+ msg = rf"\text{{... Truncated to first {r}x{c} out of {original_rows}x{original_cols} matrix}}"
54
+ display(Math(msg))
55
+
56
+ # Main Execution
57
+ sym_matrix = _prepare_matrix(matrix)
58
+ sub_matrix = _process_submatrix(sym_matrix)
59
+ _render(sub_matrix, sym_matrix.rows, sym_matrix.cols)