-
Notifications
You must be signed in to change notification settings - Fork 1
/
header.py
171 lines (140 loc) · 5.4 KB
/
header.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
'''
Phi - Programmation Heuristique Interface
header.py - Header text for compiled phi files
----------------
Author: Tanay Kar
----------------
'''
___plot_limit___ = 15 # Change this to change the plot domain
___resolution_factor___ = 100 # Change this to change the resolution of the plot
___graph_theme_dark___ = True # Change this to change the theme of the plot
___bidirectional___ = True # Change this to chose whether to plot the function in negative domain or not
___y_scale___ = 'linear' # Change this to change the y scale of the plot
___equiscaled___ = True # Change this to make the plot scaled equally in both axes
___define_iota___ = False # Change this to define iota as a constant
from sys import modules
header = f'''
from math import *
import math
import sympy as sp
import numpy as np
import inspect
from matplotlib import pyplot as plt
import matplotlib as mpl
from cycler import cycler
from mpl_interactions import panhandler, zoom_factory
try:
from ing_theme_matplotlib import mpl_style
except ImportError:
from qbstyles import mpl_style
'''
modules = f'''
mpl_style(dark={___graph_theme_dark___},minor_ticks=False)
mpl.rcParams['axes.prop_cycle'] = cycler('color', ['#ff7f0e', '#2ca02c', '#d62728', '#9467bd', '#8c564b', '#e377c2', '#7f7f7f', '#bcbd22', '#17becf','#1f77b4'])
with plt.ioff() :
fig, ax = plt.subplots()
table_used = False
i = sp.I if {___define_iota___} else 1j
def __plot__(func,name,integration=False,integration_limits=[0,0]):
global table_used
table_used = True
x = np.linspace(-15, 15, 3000)
try:
y = np.vectorize(func)(x)
except Exception as e:
y = np.empty_like(x)
# Calculate the function values and handle points outside the domain
for i, x_val in enumerate(x):
try:
y[i] = func(x_val)
except Exception as e:
y[i] = np.nan
plt.plot(x, y,label=name)
if integration:
if integration_limits == "calculated":
integration_limits = [min(x),max(x)]
plt.fill_between(x, y, where=((x>integration_limits[0]) & (x<integration_limits[1])), alpha=0.5)
def __create_namespace__():
# This is just a helper function to create/destroy a namespace for sympy functions
# In other words , this is just a tranquilizer for sympy's overly sensitive namespace
# conflict. It encloses all the sympy dependent functions and forms a blanket namespace
# for them.
sympy_names = [name for name in dir(sp)]
# Filter the list to include only the names also present in the math module
joint_names = [name for name in sympy_names if hasattr(math, name)]
# Import the matching SymPy names
for name in joint_names:
globals()[name] = getattr(sp, name)
def __solve__(func,func_name,func_str):
print(f'\\nSolving {{func_str}} = {{func}} ...')
roots = sp.solve(func)
# Separate real and complex roots during iteration
real_roots = []
complex_roots = []
for root in roots:
if root.is_real:
real_roots.append(root)
else:
complex_roots.append(root)
# Print the results
if not roots:
print('No solutions found')
else:
if real_roots:
print("\\nReal Roots:")
for root in real_roots:
print(f"x = {{root:.2f}}")
if complex_roots:
print("\\nComplex Roots:")
for root in complex_roots:
real_part = sp.re(root)
imag_part = sp.im(root)
print(f"x = {{real_part:.2f}} + {{imag_part:.2f}}i")
def __integrate__(func,func_name,func_str,var,indefinite=True,integration_limits=[0,0]):
print(f'\\nIntegrating {{func_str}} = {{func}} with respect to {{var}} ...')
var = sp.Symbol(var)
if indefinite:
func_integral = sp.integrate(func,var)
print(f'\\nIntegral of {{func_str}} = {{func_integral}}')
else:
func_integral = sp.integrate(func,(var,integration_limits[0],integration_limits[1]))
print(f'\\nIntegral of {{func_str}} from {{integration_limits[0]}} to {{integration_limits[1]}} = {{func_integral}}')
def __eqsolve__(eq_set,var_set):
print(f'\\nSolving {{len(eq_set)}} equation{{"s" if len(eq_set)>1 else ""}} for {{var_set}} ...')
for i in eq_set:
print(i.lhs,'=',i.rhs)
roots = sp.solve(eq_set,var_set,dict=True)
if not roots:
print('No solutions found')
return
print('\\nSolution set:')
if type(roots) == dict:
for i in roots:
print(f'{{i}} = {{roots[i]}}',end=' , ')
elif type(roots) == list and len(roots) == 1:
for i in roots[0]:
print(f'{{i}} = {{roots[0][i]}}',end=' , ')
print()
else:
for i in roots:
for j in i:
print(f'{{j}} = {{i[j]}}',sep=' , ')
print()
'''
footer = f'''
if table_used:
plt.axhline(y=0, color='grey')
plt.axvline(x=0, color='grey')
plt.axis('auto')
plt.grid(linestyle=':')
plt.legend()
plt.yscale(\'{___y_scale___}\')
disconnect_zoom = zoom_factory(ax)
pan_handler = panhandler(fig)
if {___equiscaled___}:
if {___bidirectional___}:
plt.axis([{-___plot_limit___}, {___plot_limit___}, {-___plot_limit___}, {___plot_limit___}])
else:
plt.axis([0, {___plot_limit___}, 0, {___plot_limit___}])
plt.show()
'''