rgwfuncs 0.0.53__py3-none-any.whl → 0.0.55__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- rgwfuncs/algebra_lib.py +54 -38
- {rgwfuncs-0.0.53.dist-info → rgwfuncs-0.0.55.dist-info}/METADATA +2 -2
- {rgwfuncs-0.0.53.dist-info → rgwfuncs-0.0.55.dist-info}/RECORD +7 -7
- {rgwfuncs-0.0.53.dist-info → rgwfuncs-0.0.55.dist-info}/LICENSE +0 -0
- {rgwfuncs-0.0.53.dist-info → rgwfuncs-0.0.55.dist-info}/WHEEL +0 -0
- {rgwfuncs-0.0.53.dist-info → rgwfuncs-0.0.55.dist-info}/entry_points.txt +0 -0
- {rgwfuncs-0.0.53.dist-info → rgwfuncs-0.0.55.dist-info}/top_level.txt +0 -0
rgwfuncs/algebra_lib.py
CHANGED
@@ -744,12 +744,12 @@ def plot_polynomial_functions(
|
|
744
744
|
show_legend : bool
|
745
745
|
Whether to add a legend to the plot (defaults to True).
|
746
746
|
open_file : bool
|
747
|
-
If saving to path is not
|
748
|
-
the file from the actual location using the system's
|
749
|
-
False).
|
747
|
+
If saving to path is not desirable, opens the SVG as a temp file;
|
748
|
+
otherwise opens the file from the actual location using the system's
|
749
|
+
default viewer (defaults to False).
|
750
750
|
save_path : Optional[str]
|
751
|
-
If specified, saves the output string as a .svg at the indicated path
|
752
|
-
None).
|
751
|
+
If specified, saves the output string as a .svg at the indicated path
|
752
|
+
(defaults to None).
|
753
753
|
|
754
754
|
Returns
|
755
755
|
-------
|
@@ -772,33 +772,34 @@ def plot_polynomial_functions(
|
|
772
772
|
|
773
773
|
expr_tmp = re.sub(DIFF_PATTERN, diff_replacer, expr_str)
|
774
774
|
expr_tmp = expr_tmp.replace("np.", "")
|
775
|
+
|
776
|
+
# Attempt to convert basic Pythonic polynomial expressions to LaTeX
|
775
777
|
try:
|
778
|
+
# Suppose you have a helper function python_polynomial_expression_to_latex
|
779
|
+
# If not, you can do a naive replacement or skip
|
780
|
+
from python_latex_helpers import python_polynomial_expression_to_latex
|
776
781
|
latex_expr = python_polynomial_expression_to_latex(expr_tmp)
|
777
782
|
return latex_expr
|
778
783
|
except Exception:
|
779
|
-
# Fallback:
|
784
|
+
# Fallback: naive ** -> ^
|
780
785
|
return expr_tmp.replace("**", "^")
|
781
786
|
|
782
|
-
def handle_open_and_save(
|
783
|
-
|
784
|
-
|
785
|
-
save_path: Optional[str]
|
786
|
-
) -> None:
|
787
|
-
# Save the SVG to a file if a save path is provided
|
788
|
-
if save_path:
|
787
|
+
def handle_open_and_save(svg_string: str, open_it: bool, path: Optional[str]) -> None:
|
788
|
+
# Save the SVG to a file if a path is provided
|
789
|
+
if path:
|
789
790
|
try:
|
790
|
-
with open(
|
791
|
+
with open(path, 'w', encoding='utf-8') as file:
|
791
792
|
file.write(svg_string)
|
792
|
-
print(f"[INFO] SVG saved to: {
|
793
|
+
print(f"[INFO] SVG saved to: {path}")
|
793
794
|
except IOError as e:
|
794
|
-
print(f"[ERROR] Failed to save SVG to {
|
795
|
+
print(f"[ERROR] Failed to save SVG to {path}. IOError: {e}")
|
795
796
|
|
796
797
|
# Handle opening the file if requested
|
797
|
-
if
|
798
|
-
result = subprocess.run(["xdg-open",
|
798
|
+
if open_it and path:
|
799
|
+
result = subprocess.run(["xdg-open", path], stderr=subprocess.DEVNULL)
|
799
800
|
if result.returncode != 0:
|
800
801
|
print("[ERROR] Failed to open the SVG file with the default viewer.")
|
801
|
-
elif
|
802
|
+
elif open_it:
|
802
803
|
with tempfile.NamedTemporaryFile(delete=False, suffix=".svg") as tmpfile:
|
803
804
|
temp_svg_path = tmpfile.name
|
804
805
|
tmpfile.write(svg_string.encode('utf-8'))
|
@@ -810,60 +811,76 @@ def plot_polynomial_functions(
|
|
810
811
|
fig, ax = plt.subplots()
|
811
812
|
|
812
813
|
for entry in functions:
|
814
|
+
# Each entry is something like {"x**2": {"x": "*", "a": ...}}
|
813
815
|
if len(entry) != 1:
|
814
|
-
print("Skipping invalid item. Must have exactly 1 expression->substitutions pair.")
|
816
|
+
print("[WARNING] Skipping invalid item. Must have exactly 1 expression->substitutions pair.")
|
815
817
|
continue
|
816
818
|
|
817
|
-
expression
|
819
|
+
# Extract the expression string and substitutions
|
820
|
+
expression, sub_dict = next(iter(entry.items()))
|
821
|
+
|
822
|
+
# Check presence of "x"
|
818
823
|
if "x" not in sub_dict:
|
819
|
-
print(f"Skipping '{expression}' because
|
824
|
+
print(f"[WARNING] Skipping '{expression}' because there is no 'x' key.")
|
820
825
|
continue
|
821
826
|
|
822
|
-
# If "x" is "*", create a default domain
|
823
827
|
x_val = sub_dict["x"]
|
828
|
+
|
829
|
+
# 1) If x == "*", generate from -zoom..+zoom
|
830
|
+
print("830", x_val)
|
831
|
+
print("830", type(x_val))
|
824
832
|
if isinstance(x_val, str) and x_val == "*":
|
825
833
|
x_values = np.linspace(-zoom, zoom, 1201)
|
826
|
-
sub_dict["x"] = x_values
|
834
|
+
sub_dict["x"] = x_values # might as well update it in place
|
835
|
+
# 2) If x is already a NumPy array, use as-is
|
827
836
|
elif isinstance(x_val, np.ndarray):
|
828
837
|
x_values = x_val
|
829
838
|
else:
|
830
|
-
print(f"Skipping '{expression}' because 'x' is neither '*' nor a NumPy array.")
|
839
|
+
print(f"[WARNING] Skipping '{expression}' because 'x' is neither '*' nor a NumPy array.")
|
831
840
|
continue
|
832
841
|
|
833
|
-
# Evaluate the expression
|
842
|
+
# Evaluate the expression with the variables from sub_dict
|
843
|
+
# We'll inject them into an eval() context, including 'np'
|
834
844
|
try:
|
835
845
|
eval_context = {"np": np}
|
846
|
+
# Put all user-provided variables (like a=1.23) in:
|
836
847
|
eval_context.update(sub_dict)
|
837
848
|
y_values = eval(expression, {"np": np}, eval_context)
|
838
849
|
except Exception as e:
|
839
|
-
print(f"
|
850
|
+
print(f"[ERROR] Could not evaluate '{expression}' -> {e}")
|
840
851
|
continue
|
841
852
|
|
853
|
+
# Check we got a NumPy array
|
842
854
|
if not isinstance(y_values, np.ndarray):
|
843
|
-
print(f"Skipping '{expression}' because it did not produce a NumPy array.")
|
855
|
+
print(f"[WARNING] Skipping '{expression}' because it did not produce a NumPy array.")
|
844
856
|
continue
|
845
857
|
|
846
|
-
# If
|
858
|
+
# If y is shorter (like np.diff), truncate x
|
847
859
|
if len(y_values) < len(x_values):
|
848
860
|
x_values = x_values[:len(y_values)]
|
849
861
|
|
850
|
-
# Convert expression to a
|
862
|
+
# Convert the expression to a LaTeX label
|
851
863
|
label_expr = latexify_expression(expression)
|
852
864
|
ax.plot(x_values, y_values, label=rf"${label_expr}$")
|
853
865
|
|
854
866
|
# Configure axes
|
855
867
|
ax.set_xlim(-zoom, zoom)
|
856
868
|
ax.set_ylim(-zoom, zoom)
|
869
|
+
|
870
|
+
# Place spines at center
|
857
871
|
ax.spines['left'].set_position('zero')
|
858
872
|
ax.spines['bottom'].set_position('zero')
|
873
|
+
# Hide the right and top spines
|
859
874
|
ax.spines['right'].set_color('none')
|
860
875
|
ax.spines['top'].set_color('none')
|
861
|
-
ax.set_aspect('equal', 'box')
|
862
876
|
ax.xaxis.set_ticks_position('bottom')
|
863
877
|
ax.yaxis.set_ticks_position('left')
|
878
|
+
|
879
|
+
# Ensure equal aspect ratio
|
880
|
+
ax.set_aspect('equal', 'box')
|
864
881
|
ax.grid(True)
|
865
882
|
|
866
|
-
#
|
883
|
+
# If requested, show the legend
|
867
884
|
if show_legend:
|
868
885
|
leg = ax.legend(
|
869
886
|
loc='upper center',
|
@@ -872,16 +889,15 @@ def plot_polynomial_functions(
|
|
872
889
|
shadow=True,
|
873
890
|
ncol=1
|
874
891
|
)
|
875
|
-
plt.savefig(
|
876
|
-
buffer,
|
877
|
-
format='svg',
|
878
|
-
bbox_inches='tight',
|
879
|
-
bbox_extra_artists=[leg] # ensures the legend is fully captured
|
880
|
-
)
|
892
|
+
plt.savefig(buffer, format='svg', bbox_inches='tight', bbox_extra_artists=[leg])
|
881
893
|
else:
|
882
894
|
plt.savefig(buffer, format='svg', bbox_inches='tight')
|
883
895
|
|
884
896
|
plt.close(fig)
|
885
897
|
svg_string = buffer.getvalue().decode('utf-8')
|
898
|
+
|
899
|
+
# Optionally open/save the file
|
886
900
|
handle_open_and_save(svg_string, open_file, save_path)
|
901
|
+
|
887
902
|
return svg_string
|
903
|
+
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: rgwfuncs
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.55
|
4
4
|
Summary: A functional programming paradigm for mathematical modelling and data science
|
5
5
|
Home-page: https://github.com/ryangerardwilson/rgwfunc
|
6
6
|
Author: Ryan Gerard Wilson
|
@@ -550,7 +550,7 @@ This function plots polynomial functions described by a list of expressions and
|
|
550
550
|
|
551
551
|
• Displaying the SVG:
|
552
552
|
|
553
|
-
|
553
|
+

|
554
554
|
|
555
555
|
--------------------------------------------------------------------------------
|
556
556
|
|
@@ -1,12 +1,12 @@
|
|
1
1
|
rgwfuncs/__init__.py,sha256=JjkuVeRV_Bkw8vnqSbJsRcYQRm4iCI3futR86cf3tRI,1637
|
2
|
-
rgwfuncs/algebra_lib.py,sha256=
|
2
|
+
rgwfuncs/algebra_lib.py,sha256=YlXv8R-xD4IQoTaatw9AQyAsi5lWh00K1huQ53figC8,36017
|
3
3
|
rgwfuncs/df_lib.py,sha256=qqRQdakheLy8wMZRBfHwKyIp8DmdZIWfAiLKWgq03QU,68977
|
4
4
|
rgwfuncs/docs_lib.py,sha256=y3wSAOPO3qsA4HZ7xAtW8HimM8w-c8hjcEzMRLJ96ao,1960
|
5
5
|
rgwfuncs/interactive_shell_lib.py,sha256=A7EWsYxAfDev_N0-2GjRvAtp0bAwBPHIczXb8Gu9fzI,1107
|
6
6
|
rgwfuncs/str_lib.py,sha256=rtAdRlnSJIu3JhI-tA_A0wCiPK2m-zn5RoGpBxv_g-4,2228
|
7
|
-
rgwfuncs-0.0.
|
8
|
-
rgwfuncs-0.0.
|
9
|
-
rgwfuncs-0.0.
|
10
|
-
rgwfuncs-0.0.
|
11
|
-
rgwfuncs-0.0.
|
12
|
-
rgwfuncs-0.0.
|
7
|
+
rgwfuncs-0.0.55.dist-info/LICENSE,sha256=7EI8xVBu6h_7_JlVw-yPhhOZlpY9hP8wal7kHtqKT_E,1074
|
8
|
+
rgwfuncs-0.0.55.dist-info/METADATA,sha256=2fr5olJy55MoAetAhCcPOsEVa6Ia3CGiDcKBnpiU-0g,57136
|
9
|
+
rgwfuncs-0.0.55.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
10
|
+
rgwfuncs-0.0.55.dist-info/entry_points.txt,sha256=j-c5IOPIQ0252EaOV6j6STio56sbXl2C4ym_fQ0lXx0,43
|
11
|
+
rgwfuncs-0.0.55.dist-info/top_level.txt,sha256=aGuVIzWsKiV1f2gCb6mynx0zx5ma0B1EwPGFKVEMTi4,9
|
12
|
+
rgwfuncs-0.0.55.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|