rgwfuncs 0.0.51__py3-none-any.whl → 0.0.52__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
rgwfuncs/__init__.py CHANGED
@@ -1,7 +1,7 @@
1
1
  # This file is automatically generated
2
2
  # Dynamically importing functions from modules
3
3
 
4
- from .algebra_lib import cancel_polynomial_expression, compute_constant_expression, compute_constant_expression_involving_matrices, compute_constant_expression_involving_ordered_series, compute_prime_factors, expand_polynomial_expression, factor_polynomial_expression, python_polynomial_expression_to_latex, simplify_polynomial_expression, solve_homogeneous_polynomial_expression
4
+ from .algebra_lib import cancel_polynomial_expression, compute_constant_expression, compute_constant_expression_involving_matrices, compute_constant_expression_involving_ordered_series, compute_prime_factors, expand_polynomial_expression, factor_polynomial_expression, plot_polynomial_functions, python_polynomial_expression_to_latex, simplify_polynomial_expression, solve_homogeneous_polynomial_expression
5
5
  from .df_lib import append_columns, append_percentile_classification_column, append_ranged_classification_column, append_ranged_date_classification_column, append_rows, append_xgb_labels, append_xgb_logistic_regression_predictions, append_xgb_regression_predictions, bag_union_join, bottom_n_unique_values, cascade_sort, delete_rows, drop_duplicates, drop_duplicates_retain_first, drop_duplicates_retain_last, filter_dataframe, filter_indian_mobiles, first_n_rows, from_raw_data, insert_dataframe_in_sqlite_database, last_n_rows, left_join, limit_dataframe, load_data_from_path, load_data_from_query, load_data_from_sqlite_path, mask_against_dataframe, mask_against_dataframe_converse, numeric_clean, order_columns, print_correlation, print_dataframe, print_memory_usage, print_n_frequency_cascading, print_n_frequency_linear, rename_columns, retain_columns, right_join, send_data_to_email, send_data_to_slack, send_dataframe_via_telegram, sync_dataframe_to_sqlite_database, top_n_unique_values, union_join, update_rows
6
6
  from .docs_lib import docs
7
7
  from .interactive_shell_lib import interactive_shell
rgwfuncs/algebra_lib.py CHANGED
@@ -8,7 +8,12 @@ from sympy.parsing.sympy_parser import parse_expr
8
8
  from sympy import __all__ as sympy_functions
9
9
  from sympy.parsing.sympy_parser import (standard_transformations, implicit_multiplication_application)
10
10
 
11
- from typing import Tuple, List, Dict, Optional
11
+ from typing import Tuple, List, Dict, Optional, Any
12
+
13
+
14
+ import numpy as np
15
+ import matplotlib.pyplot as plt
16
+ from io import BytesIO
12
17
 
13
18
 
14
19
  def compute_prime_factors(n: int) -> str:
@@ -285,7 +290,6 @@ def python_polynomial_expression_to_latex(
285
290
  Raises:
286
291
  ValueError: If the expression cannot be parsed due to syntax errors.
287
292
  """
288
-
289
293
  transformations = standard_transformations + (implicit_multiplication_application,)
290
294
 
291
295
  def parse_and_convert_expression(expr_str: str, sym_vars: Dict[str, Expr]) -> Expr:
@@ -701,3 +705,145 @@ def solve_homogeneous_polynomial_expression(
701
705
 
702
706
  except Exception as e:
703
707
  raise ValueError(f"Error solving the expression: {e}")
708
+
709
+
710
+ def plot_polynomial_functions(
711
+ functions: List[Dict[str, Dict[str, Any]]],
712
+ zoom: float = 10.0,
713
+ show_legend: bool = True
714
+ ) -> str:
715
+ """
716
+ Plots expressions described by a list of dictionaries of the form:
717
+ [
718
+ { "expression_string": { "x": "*", "a":..., "b":... } },
719
+ { "expression_string": { "x": np.linspace(...), "a":..., ... } },
720
+ ...
721
+ ]
722
+
723
+ In each top-level dictionary, there is exactly one key (a string
724
+ representing a Python/NumPy expression) and one value (a dictionary of
725
+ substitutions). This substitutions dictionary must have an "x" key:
726
+ • "x": "*" -> Use a default domain from -zoom..+zoom.
727
+ • "x": np.array(...) -> Use that array as the domain.
728
+ Other variables (like "a", "b", etc.) may also appear in the same dict.
729
+
730
+ Additionally, we use latexify_expression(...) to transform the expression
731
+ into a nice LaTeX form for the legend, including a special Δ notation for np.diff(...).
732
+
733
+ Parameters
734
+ ----------
735
+ functions : List[Dict[str, Dict[str, Any]]]
736
+ A list of items. Each item is a dictionary:
737
+ key = expression string (e.g., "x**2", "np.diff(x,2)", etc.)
738
+ value = a dictionary of substitutions. Must contain "x",
739
+ either as "*" or a NumPy array. May contain additional
740
+ parameters like "a", "b", etc.
741
+ zoom : float
742
+ Sets the numeric axis range from -zoom..+zoom in both x and y.
743
+ show_legend : bool
744
+ Whether to add a legend to the plot (defaults to True).
745
+
746
+ Returns
747
+ -------
748
+ str
749
+ The raw SVG markup of the resulting plot.
750
+ """
751
+
752
+ def latexify_expression(expr_str: str) -> str:
753
+ # Regex to locate np.diff(...) with an optional second argument
754
+ DIFF_PATTERN = r"np\.diff\s*\(\s*([^,\)]+)(?:,\s*(\d+))?\)"
755
+
756
+ def diff_replacer(match: re.Match) -> str:
757
+ inside = match.group(1).strip()
758
+ exponent = match.group(2)
759
+ inside_no_np = inside.replace("np.", "")
760
+ if exponent:
761
+ return rf"\Delta^{exponent}\left({inside_no_np}\right)"
762
+ else:
763
+ return rf"\Delta\left({inside_no_np}\right)"
764
+
765
+ expr_tmp = re.sub(DIFF_PATTERN, diff_replacer, expr_str)
766
+ expr_tmp = expr_tmp.replace("np.", "")
767
+ try:
768
+ latex_expr = python_polynomial_expression_to_latex(expr_tmp)
769
+ return latex_expr
770
+ except Exception:
771
+ # Fallback: just do naive **
772
+ return expr_tmp.replace("**", "^")
773
+
774
+ buffer = BytesIO()
775
+ fig, ax = plt.subplots()
776
+
777
+ for entry in functions:
778
+ if len(entry) != 1:
779
+ print("Skipping invalid item. Must have exactly 1 expression->substitutions pair.")
780
+ continue
781
+
782
+ expression, sub_dict = list(entry.items())[0]
783
+ if "x" not in sub_dict:
784
+ print(f"Skipping '{expression}' because sub-dict lacks 'x' key.")
785
+ continue
786
+
787
+ # If "x" is "*", create a default domain
788
+ x_val = sub_dict["x"]
789
+ if isinstance(x_val, str) and x_val == "*":
790
+ x_values = np.linspace(-zoom, zoom, 1201)
791
+ sub_dict["x"] = x_values
792
+ elif isinstance(x_val, np.ndarray):
793
+ x_values = x_val
794
+ else:
795
+ print(f"Skipping '{expression}' because 'x' is neither '*' nor a NumPy array.")
796
+ continue
797
+
798
+ # Evaluate the expression
799
+ try:
800
+ eval_context = {"np": np}
801
+ eval_context.update(sub_dict)
802
+ y_values = eval(expression, {"np": np}, eval_context)
803
+ except Exception as e:
804
+ print(f"Error evaluating expression '{expression}': {e}")
805
+ continue
806
+
807
+ if not isinstance(y_values, np.ndarray):
808
+ print(f"Skipping '{expression}' because it did not produce a NumPy array.")
809
+ continue
810
+
811
+ # If y_values is shorter than x_values (like np.diff), truncate x
812
+ if len(y_values) < len(x_values):
813
+ x_values = x_values[:len(y_values)]
814
+
815
+ # Convert expression to a nice LaTeX string
816
+ label_expr = latexify_expression(expression)
817
+ ax.plot(x_values, y_values, label=rf"${label_expr}$")
818
+
819
+ # Configure axes
820
+ ax.set_xlim(-zoom, zoom)
821
+ ax.set_ylim(-zoom, zoom)
822
+ ax.spines['left'].set_position('zero')
823
+ ax.spines['bottom'].set_position('zero')
824
+ ax.spines['right'].set_color('none')
825
+ ax.spines['top'].set_color('none')
826
+ ax.set_aspect('equal', 'box')
827
+ ax.xaxis.set_ticks_position('bottom')
828
+ ax.yaxis.set_ticks_position('left')
829
+ ax.grid(True)
830
+
831
+ # Show legend
832
+ if show_legend:
833
+ leg = ax.legend(
834
+ loc='upper center',
835
+ bbox_to_anchor=(0.5, -0.03),
836
+ fancybox=True,
837
+ shadow=True,
838
+ ncol=1
839
+ )
840
+ plt.savefig(
841
+ buffer,
842
+ format='svg',
843
+ bbox_inches='tight',
844
+ bbox_extra_artists=[leg] # ensures the legend is fully captured
845
+ )
846
+ else:
847
+ plt.savefig(buffer, format='svg', bbox_inches='tight')
848
+ plt.close(fig)
849
+ return buffer.getvalue().decode('utf-8')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: rgwfuncs
3
- Version: 0.0.51
3
+ Version: 0.0.52
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
@@ -514,6 +514,45 @@ Solves a homogeneous polynomial expression for a specified variable and returns
514
514
 
515
515
  --------------------------------------------------------------------------------
516
516
 
517
+ ### 11. `plot_polynomial_functions`
518
+
519
+ This function plots polynomial functions described by a list of expressions and their corresponding substitution dictionaries. It generates SVG markup of the plots, with options for specifying the domain, axis zoom, and legend display.
520
+
521
+ • Parameters:
522
+ - `functions` (`List[Dict[str, Dict[str, Any]]]`): A list of dictionaries, each containing:
523
+ - A key which is a string representing a Python/NumPy expression (e.g., `"x**2"`, `"np.diff(x,2)"`).
524
+ - A value which is a dictionary containing substitutions for the expression. Must include an `"x"` key, either as `"*"` for default domain or a NumPy array.
525
+ - `zoom` (`float`): Determines the numeric axis range from `-zoom` to `+zoom` for both x and y axes (default is `10.0`).
526
+ - `show_legend` (`bool`): Specifies whether to include a legend in the plot (default is `True`).
527
+
528
+ • Returns:
529
+ - `str`: The raw SVG markup of the resulting plot.
530
+
531
+ • Example:
532
+
533
+ import subprocess
534
+ from rgwfuncs import plot_polynomial_functions
535
+
536
+ # Generate the SVG
537
+ plot_svg_string = plot_polynomial_functions(
538
+ functions=[
539
+ {"x**2": {"x": "*"}}, # Single expression, "*" means plot all discernable points
540
+ {"x**2/(2 + a) + a": {"x": np.linspace(-3, 4, 101), "a": 1.23}},
541
+ {"np.diff(x**3, 2)": {"x": np.linspace(-2, 2, 10)}}
542
+ ],
543
+ zoom=2
544
+ )
545
+
546
+ # Write the SVG to an actual file
547
+ with open("plot.svg", "w", encoding="utf-8") as file:
548
+ file.write(plot_svg_string)
549
+
550
+ • Displaying the SVG:
551
+
552
+ ![Plot](./media/plot_polynomial_functions_example_1.svg)
553
+
554
+ --------------------------------------------------------------------------------
555
+
517
556
  ## String Based Functions
518
557
 
519
558
  ### 1. send_telegram_message
@@ -0,0 +1,12 @@
1
+ rgwfuncs/__init__.py,sha256=JjkuVeRV_Bkw8vnqSbJsRcYQRm4iCI3futR86cf3tRI,1637
2
+ rgwfuncs/algebra_lib.py,sha256=-Q2W63EtRLhwOvGGFuf8KUKVuoLA72ONt-wPhcX6R94,33408
3
+ rgwfuncs/df_lib.py,sha256=qqRQdakheLy8wMZRBfHwKyIp8DmdZIWfAiLKWgq03QU,68977
4
+ rgwfuncs/docs_lib.py,sha256=y3wSAOPO3qsA4HZ7xAtW8HimM8w-c8hjcEzMRLJ96ao,1960
5
+ rgwfuncs/interactive_shell_lib.py,sha256=A7EWsYxAfDev_N0-2GjRvAtp0bAwBPHIczXb8Gu9fzI,1107
6
+ rgwfuncs/str_lib.py,sha256=rtAdRlnSJIu3JhI-tA_A0wCiPK2m-zn5RoGpBxv_g-4,2228
7
+ rgwfuncs-0.0.52.dist-info/LICENSE,sha256=7EI8xVBu6h_7_JlVw-yPhhOZlpY9hP8wal7kHtqKT_E,1074
8
+ rgwfuncs-0.0.52.dist-info/METADATA,sha256=ByUIjumG8zZCcuKbS0d9Ipq5VH0rBfAAumeRHQ5SR90,56826
9
+ rgwfuncs-0.0.52.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
10
+ rgwfuncs-0.0.52.dist-info/entry_points.txt,sha256=j-c5IOPIQ0252EaOV6j6STio56sbXl2C4ym_fQ0lXx0,43
11
+ rgwfuncs-0.0.52.dist-info/top_level.txt,sha256=aGuVIzWsKiV1f2gCb6mynx0zx5ma0B1EwPGFKVEMTi4,9
12
+ rgwfuncs-0.0.52.dist-info/RECORD,,
@@ -1,12 +0,0 @@
1
- rgwfuncs/__init__.py,sha256=vs8xv3IVx7KGpPxEXrIePD3gb_QI1XTXpD_n9817foA,1610
2
- rgwfuncs/algebra_lib.py,sha256=sLQUxXG4mNNO55XclTgIrwVrg5LbwELOFsiSAm_9G20,28212
3
- rgwfuncs/df_lib.py,sha256=qqRQdakheLy8wMZRBfHwKyIp8DmdZIWfAiLKWgq03QU,68977
4
- rgwfuncs/docs_lib.py,sha256=y3wSAOPO3qsA4HZ7xAtW8HimM8w-c8hjcEzMRLJ96ao,1960
5
- rgwfuncs/interactive_shell_lib.py,sha256=A7EWsYxAfDev_N0-2GjRvAtp0bAwBPHIczXb8Gu9fzI,1107
6
- rgwfuncs/str_lib.py,sha256=rtAdRlnSJIu3JhI-tA_A0wCiPK2m-zn5RoGpBxv_g-4,2228
7
- rgwfuncs-0.0.51.dist-info/LICENSE,sha256=7EI8xVBu6h_7_JlVw-yPhhOZlpY9hP8wal7kHtqKT_E,1074
8
- rgwfuncs-0.0.51.dist-info/METADATA,sha256=Q-t10jPxJYG_orABThvIy6q1-WQvwOYwe_3TNLuLYRw,55152
9
- rgwfuncs-0.0.51.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
10
- rgwfuncs-0.0.51.dist-info/entry_points.txt,sha256=j-c5IOPIQ0252EaOV6j6STio56sbXl2C4ym_fQ0lXx0,43
11
- rgwfuncs-0.0.51.dist-info/top_level.txt,sha256=aGuVIzWsKiV1f2gCb6mynx0zx5ma0B1EwPGFKVEMTi4,9
12
- rgwfuncs-0.0.51.dist-info/RECORD,,