xiaoanyu123 commited on
Commit
de0eaa8
·
verified ·
1 Parent(s): 50d40e6

Add files using upload-large-folder tool

Browse files
Files changed (20) hide show
  1. pythonProject/.venv/Lib/site-packages/sympy/physics/__pycache__/__init__.cpython-310.pyc +0 -0
  2. pythonProject/.venv/Lib/site-packages/sympy/physics/__pycache__/hydrogen.cpython-310.pyc +0 -0
  3. pythonProject/.venv/Lib/site-packages/sympy/physics/__pycache__/matrices.cpython-310.pyc +0 -0
  4. pythonProject/.venv/Lib/site-packages/sympy/physics/__pycache__/paulialgebra.cpython-310.pyc +0 -0
  5. pythonProject/.venv/Lib/site-packages/sympy/physics/__pycache__/pring.cpython-310.pyc +0 -0
  6. pythonProject/.venv/Lib/site-packages/sympy/physics/__pycache__/qho_1d.cpython-310.pyc +0 -0
  7. pythonProject/.venv/Lib/site-packages/sympy/physics/__pycache__/secondquant.cpython-310.pyc +0 -0
  8. pythonProject/.venv/Lib/site-packages/sympy/physics/__pycache__/sho.cpython-310.pyc +0 -0
  9. pythonProject/.venv/Lib/site-packages/sympy/physics/__pycache__/wigner.cpython-310.pyc +0 -0
  10. pythonProject/.venv/Lib/site-packages/sympy/physics/vector/__pycache__/__init__.cpython-310.pyc +0 -0
  11. pythonProject/.venv/Lib/site-packages/sympy/physics/vector/__pycache__/dyadic.cpython-310.pyc +0 -0
  12. pythonProject/.venv/Lib/site-packages/sympy/physics/vector/__pycache__/fieldfunctions.cpython-310.pyc +0 -0
  13. pythonProject/.venv/Lib/site-packages/sympy/physics/vector/__pycache__/frame.cpython-310.pyc +0 -0
  14. pythonProject/.venv/Lib/site-packages/sympy/physics/vector/__pycache__/functions.cpython-310.pyc +0 -0
  15. pythonProject/.venv/Lib/site-packages/sympy/physics/vector/__pycache__/point.cpython-310.pyc +0 -0
  16. pythonProject/.venv/Lib/site-packages/sympy/physics/vector/__pycache__/printing.cpython-310.pyc +0 -0
  17. pythonProject/.venv/Lib/site-packages/sympy/physics/vector/__pycache__/vector.cpython-310.pyc +0 -0
  18. pythonProject/.venv/Lib/site-packages/sympy/plotting/experimental_lambdify.py +641 -0
  19. pythonProject/.venv/Lib/site-packages/sympy/plotting/plot.py +1234 -0
  20. pythonProject/.venv/Lib/site-packages/sympy/plotting/plotgrid.py +188 -0
pythonProject/.venv/Lib/site-packages/sympy/physics/__pycache__/__init__.cpython-310.pyc ADDED
Binary file (411 Bytes). View file
 
pythonProject/.venv/Lib/site-packages/sympy/physics/__pycache__/hydrogen.cpython-310.pyc ADDED
Binary file (7.35 kB). View file
 
pythonProject/.venv/Lib/site-packages/sympy/physics/__pycache__/matrices.cpython-310.pyc ADDED
Binary file (3.63 kB). View file
 
pythonProject/.venv/Lib/site-packages/sympy/physics/__pycache__/paulialgebra.cpython-310.pyc ADDED
Binary file (6.13 kB). View file
 
pythonProject/.venv/Lib/site-packages/sympy/physics/__pycache__/pring.cpython-310.pyc ADDED
Binary file (2.58 kB). View file
 
pythonProject/.venv/Lib/site-packages/sympy/physics/__pycache__/qho_1d.cpython-310.pyc ADDED
Binary file (2.42 kB). View file
 
pythonProject/.venv/Lib/site-packages/sympy/physics/__pycache__/secondquant.cpython-310.pyc ADDED
Binary file (83.8 kB). View file
 
pythonProject/.venv/Lib/site-packages/sympy/physics/__pycache__/sho.cpython-310.pyc ADDED
Binary file (2.8 kB). View file
 
pythonProject/.venv/Lib/site-packages/sympy/physics/__pycache__/wigner.cpython-310.pyc ADDED
Binary file (37.9 kB). View file
 
pythonProject/.venv/Lib/site-packages/sympy/physics/vector/__pycache__/__init__.cpython-310.pyc ADDED
Binary file (1.07 kB). View file
 
pythonProject/.venv/Lib/site-packages/sympy/physics/vector/__pycache__/dyadic.cpython-310.pyc ADDED
Binary file (16.1 kB). View file
 
pythonProject/.venv/Lib/site-packages/sympy/physics/vector/__pycache__/fieldfunctions.cpython-310.pyc ADDED
Binary file (7.74 kB). View file
 
pythonProject/.venv/Lib/site-packages/sympy/physics/vector/__pycache__/frame.cpython-310.pyc ADDED
Binary file (50.3 kB). View file
 
pythonProject/.venv/Lib/site-packages/sympy/physics/vector/__pycache__/functions.cpython-310.pyc ADDED
Binary file (19.6 kB). View file
 
pythonProject/.venv/Lib/site-packages/sympy/physics/vector/__pycache__/point.cpython-310.pyc ADDED
Binary file (18.8 kB). View file
 
pythonProject/.venv/Lib/site-packages/sympy/physics/vector/__pycache__/printing.cpython-310.pyc ADDED
Binary file (10.7 kB). View file
 
pythonProject/.venv/Lib/site-packages/sympy/physics/vector/__pycache__/vector.cpython-310.pyc ADDED
Binary file (23.6 kB). View file
 
pythonProject/.venv/Lib/site-packages/sympy/plotting/experimental_lambdify.py ADDED
@@ -0,0 +1,641 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """ rewrite of lambdify - This stuff is not stable at all.
2
+
3
+ It is for internal use in the new plotting module.
4
+ It may (will! see the Q'n'A in the source) be rewritten.
5
+
6
+ It's completely self contained. Especially it does not use lambdarepr.
7
+
8
+ It does not aim to replace the current lambdify. Most importantly it will never
9
+ ever support anything else than SymPy expressions (no Matrices, dictionaries
10
+ and so on).
11
+ """
12
+
13
+
14
+ import re
15
+ from sympy.core.numbers import (I, NumberSymbol, oo, zoo)
16
+ from sympy.core.symbol import Symbol
17
+ from sympy.utilities.iterables import numbered_symbols
18
+
19
+ # We parse the expression string into a tree that identifies functions. Then
20
+ # we translate the names of the functions and we translate also some strings
21
+ # that are not names of functions (all this according to translation
22
+ # dictionaries).
23
+ # If the translation goes to another module (like numpy) the
24
+ # module is imported and 'func' is translated to 'module.func'.
25
+ # If a function can not be translated, the inner nodes of that part of the
26
+ # tree are not translated. So if we have Integral(sqrt(x)), sqrt is not
27
+ # translated to np.sqrt and the Integral does not crash.
28
+ # A namespace for all this is generated by crawling the (func, args) tree of
29
+ # the expression. The creation of this namespace involves many ugly
30
+ # workarounds.
31
+ # The namespace consists of all the names needed for the SymPy expression and
32
+ # all the name of modules used for translation. Those modules are imported only
33
+ # as a name (import numpy as np) in order to keep the namespace small and
34
+ # manageable.
35
+
36
+ # Please, if there is a bug, do not try to fix it here! Rewrite this by using
37
+ # the method proposed in the last Q'n'A below. That way the new function will
38
+ # work just as well, be just as simple, but it wont need any new workarounds.
39
+ # If you insist on fixing it here, look at the workarounds in the function
40
+ # sympy_expression_namespace and in lambdify.
41
+
42
+ # Q: Why are you not using Python abstract syntax tree?
43
+ # A: Because it is more complicated and not much more powerful in this case.
44
+
45
+ # Q: What if I have Symbol('sin') or g=Function('f')?
46
+ # A: You will break the algorithm. We should use srepr to defend against this?
47
+ # The problem with Symbol('sin') is that it will be printed as 'sin'. The
48
+ # parser will distinguish it from the function 'sin' because functions are
49
+ # detected thanks to the opening parenthesis, but the lambda expression won't
50
+ # understand the difference if we have also the sin function.
51
+ # The solution (complicated) is to use srepr and maybe ast.
52
+ # The problem with the g=Function('f') is that it will be printed as 'f' but in
53
+ # the global namespace we have only 'g'. But as the same printer is used in the
54
+ # constructor of the namespace there will be no problem.
55
+
56
+ # Q: What if some of the printers are not printing as expected?
57
+ # A: The algorithm wont work. You must use srepr for those cases. But even
58
+ # srepr may not print well. All problems with printers should be considered
59
+ # bugs.
60
+
61
+ # Q: What about _imp_ functions?
62
+ # A: Those are taken care for by evalf. A special case treatment will work
63
+ # faster but it's not worth the code complexity.
64
+
65
+ # Q: Will ast fix all possible problems?
66
+ # A: No. You will always have to use some printer. Even srepr may not work in
67
+ # some cases. But if the printer does not work, that should be considered a
68
+ # bug.
69
+
70
+ # Q: Is there same way to fix all possible problems?
71
+ # A: Probably by constructing our strings ourself by traversing the (func,
72
+ # args) tree and creating the namespace at the same time. That actually sounds
73
+ # good.
74
+
75
+ from sympy.external import import_module
76
+ import warnings
77
+
78
+ #TODO debugging output
79
+
80
+
81
+ class vectorized_lambdify:
82
+ """ Return a sufficiently smart, vectorized and lambdified function.
83
+
84
+ Returns only reals.
85
+
86
+ Explanation
87
+ ===========
88
+
89
+ This function uses experimental_lambdify to created a lambdified
90
+ expression ready to be used with numpy. Many of the functions in SymPy
91
+ are not implemented in numpy so in some cases we resort to Python cmath or
92
+ even to evalf.
93
+
94
+ The following translations are tried:
95
+ only numpy complex
96
+ - on errors raised by SymPy trying to work with ndarray:
97
+ only Python cmath and then vectorize complex128
98
+
99
+ When using Python cmath there is no need for evalf or float/complex
100
+ because Python cmath calls those.
101
+
102
+ This function never tries to mix numpy directly with evalf because numpy
103
+ does not understand SymPy Float. If this is needed one can use the
104
+ float_wrap_evalf/complex_wrap_evalf options of experimental_lambdify or
105
+ better one can be explicit about the dtypes that numpy works with.
106
+ Check numpy bug http://projects.scipy.org/numpy/ticket/1013 to know what
107
+ types of errors to expect.
108
+ """
109
+ def __init__(self, args, expr):
110
+ self.args = args
111
+ self.expr = expr
112
+ self.np = import_module('numpy')
113
+
114
+ self.lambda_func_1 = experimental_lambdify(
115
+ args, expr, use_np=True)
116
+ self.vector_func_1 = self.lambda_func_1
117
+
118
+ self.lambda_func_2 = experimental_lambdify(
119
+ args, expr, use_python_cmath=True)
120
+ self.vector_func_2 = self.np.vectorize(
121
+ self.lambda_func_2, otypes=[complex])
122
+
123
+ self.vector_func = self.vector_func_1
124
+ self.failure = False
125
+
126
+ def __call__(self, *args):
127
+ np = self.np
128
+
129
+ try:
130
+ temp_args = (np.array(a, dtype=complex) for a in args)
131
+ results = self.vector_func(*temp_args)
132
+ results = np.ma.masked_where(
133
+ np.abs(results.imag) > 1e-7 * np.abs(results),
134
+ results.real, copy=False)
135
+ return results
136
+ except ValueError:
137
+ if self.failure:
138
+ raise
139
+
140
+ self.failure = True
141
+ self.vector_func = self.vector_func_2
142
+ warnings.warn(
143
+ 'The evaluation of the expression is problematic. '
144
+ 'We are trying a failback method that may still work. '
145
+ 'Please report this as a bug.')
146
+ return self.__call__(*args)
147
+
148
+
149
+ class lambdify:
150
+ """Returns the lambdified function.
151
+
152
+ Explanation
153
+ ===========
154
+
155
+ This function uses experimental_lambdify to create a lambdified
156
+ expression. It uses cmath to lambdify the expression. If the function
157
+ is not implemented in Python cmath, Python cmath calls evalf on those
158
+ functions.
159
+ """
160
+
161
+ def __init__(self, args, expr):
162
+ self.args = args
163
+ self.expr = expr
164
+ self.lambda_func_1 = experimental_lambdify(
165
+ args, expr, use_python_cmath=True, use_evalf=True)
166
+ self.lambda_func_2 = experimental_lambdify(
167
+ args, expr, use_python_math=True, use_evalf=True)
168
+ self.lambda_func_3 = experimental_lambdify(
169
+ args, expr, use_evalf=True, complex_wrap_evalf=True)
170
+ self.lambda_func = self.lambda_func_1
171
+ self.failure = False
172
+
173
+ def __call__(self, args):
174
+ try:
175
+ #The result can be sympy.Float. Hence wrap it with complex type.
176
+ result = complex(self.lambda_func(args))
177
+ if abs(result.imag) > 1e-7 * abs(result):
178
+ return None
179
+ return result.real
180
+ except (ZeroDivisionError, OverflowError):
181
+ return None
182
+ except TypeError as e:
183
+ if self.failure:
184
+ raise e
185
+
186
+ if self.lambda_func == self.lambda_func_1:
187
+ self.lambda_func = self.lambda_func_2
188
+ return self.__call__(args)
189
+
190
+ self.failure = True
191
+ self.lambda_func = self.lambda_func_3
192
+ warnings.warn(
193
+ 'The evaluation of the expression is problematic. '
194
+ 'We are trying a failback method that may still work. '
195
+ 'Please report this as a bug.', stacklevel=2)
196
+ return self.__call__(args)
197
+
198
+
199
+ def experimental_lambdify(*args, **kwargs):
200
+ l = Lambdifier(*args, **kwargs)
201
+ return l
202
+
203
+
204
+ class Lambdifier:
205
+ def __init__(self, args, expr, print_lambda=False, use_evalf=False,
206
+ float_wrap_evalf=False, complex_wrap_evalf=False,
207
+ use_np=False, use_python_math=False, use_python_cmath=False,
208
+ use_interval=False):
209
+
210
+ self.print_lambda = print_lambda
211
+ self.use_evalf = use_evalf
212
+ self.float_wrap_evalf = float_wrap_evalf
213
+ self.complex_wrap_evalf = complex_wrap_evalf
214
+ self.use_np = use_np
215
+ self.use_python_math = use_python_math
216
+ self.use_python_cmath = use_python_cmath
217
+ self.use_interval = use_interval
218
+
219
+ # Constructing the argument string
220
+ # - check
221
+ if not all(isinstance(a, Symbol) for a in args):
222
+ raise ValueError('The arguments must be Symbols.')
223
+ # - use numbered symbols
224
+ syms = numbered_symbols(exclude=expr.free_symbols)
225
+ newargs = [next(syms) for _ in args]
226
+ expr = expr.xreplace(dict(zip(args, newargs)))
227
+ argstr = ', '.join([str(a) for a in newargs])
228
+ del syms, newargs, args
229
+
230
+ # Constructing the translation dictionaries and making the translation
231
+ self.dict_str = self.get_dict_str()
232
+ self.dict_fun = self.get_dict_fun()
233
+ exprstr = str(expr)
234
+ newexpr = self.tree2str_translate(self.str2tree(exprstr))
235
+
236
+ # Constructing the namespaces
237
+ namespace = {}
238
+ namespace.update(self.sympy_atoms_namespace(expr))
239
+ namespace.update(self.sympy_expression_namespace(expr))
240
+ # XXX Workaround
241
+ # Ugly workaround because Pow(a,Half) prints as sqrt(a)
242
+ # and sympy_expression_namespace can not catch it.
243
+ from sympy.functions.elementary.miscellaneous import sqrt
244
+ namespace.update({'sqrt': sqrt})
245
+ namespace.update({'Eq': lambda x, y: x == y})
246
+ namespace.update({'Ne': lambda x, y: x != y})
247
+ # End workaround.
248
+ if use_python_math:
249
+ namespace.update({'math': __import__('math')})
250
+ if use_python_cmath:
251
+ namespace.update({'cmath': __import__('cmath')})
252
+ if use_np:
253
+ try:
254
+ namespace.update({'np': __import__('numpy')})
255
+ except ImportError:
256
+ raise ImportError(
257
+ 'experimental_lambdify failed to import numpy.')
258
+ if use_interval:
259
+ namespace.update({'imath': __import__(
260
+ 'sympy.plotting.intervalmath', fromlist=['intervalmath'])})
261
+ namespace.update({'math': __import__('math')})
262
+
263
+ # Construct the lambda
264
+ if self.print_lambda:
265
+ print(newexpr)
266
+ eval_str = 'lambda %s : ( %s )' % (argstr, newexpr)
267
+ self.eval_str = eval_str
268
+ exec("MYNEWLAMBDA = %s" % eval_str, namespace)
269
+ self.lambda_func = namespace['MYNEWLAMBDA']
270
+
271
+ def __call__(self, *args, **kwargs):
272
+ return self.lambda_func(*args, **kwargs)
273
+
274
+
275
+ ##############################################################################
276
+ # Dicts for translating from SymPy to other modules
277
+ ##############################################################################
278
+ ###
279
+ # builtins
280
+ ###
281
+ # Functions with different names in builtins
282
+ builtin_functions_different = {
283
+ 'Min': 'min',
284
+ 'Max': 'max',
285
+ 'Abs': 'abs',
286
+ }
287
+
288
+ # Strings that should be translated
289
+ builtin_not_functions = {
290
+ 'I': '1j',
291
+ # 'oo': '1e400',
292
+ }
293
+
294
+ ###
295
+ # numpy
296
+ ###
297
+
298
+ # Functions that are the same in numpy
299
+ numpy_functions_same = [
300
+ 'sin', 'cos', 'tan', 'sinh', 'cosh', 'tanh', 'exp', 'log',
301
+ 'sqrt', 'floor', 'conjugate', 'sign',
302
+ ]
303
+
304
+ # Functions with different names in numpy
305
+ numpy_functions_different = {
306
+ "acos": "arccos",
307
+ "acosh": "arccosh",
308
+ "arg": "angle",
309
+ "asin": "arcsin",
310
+ "asinh": "arcsinh",
311
+ "atan": "arctan",
312
+ "atan2": "arctan2",
313
+ "atanh": "arctanh",
314
+ "ceiling": "ceil",
315
+ "im": "imag",
316
+ "ln": "log",
317
+ "Max": "amax",
318
+ "Min": "amin",
319
+ "re": "real",
320
+ "Abs": "abs",
321
+ }
322
+
323
+ # Strings that should be translated
324
+ numpy_not_functions = {
325
+ 'pi': 'np.pi',
326
+ 'oo': 'np.inf',
327
+ 'E': 'np.e',
328
+ }
329
+
330
+ ###
331
+ # Python math
332
+ ###
333
+
334
+ # Functions that are the same in math
335
+ math_functions_same = [
336
+ 'sin', 'cos', 'tan', 'asin', 'acos', 'atan', 'atan2',
337
+ 'sinh', 'cosh', 'tanh', 'asinh', 'acosh', 'atanh',
338
+ 'exp', 'log', 'erf', 'sqrt', 'floor', 'factorial', 'gamma',
339
+ ]
340
+
341
+ # Functions with different names in math
342
+ math_functions_different = {
343
+ 'ceiling': 'ceil',
344
+ 'ln': 'log',
345
+ 'loggamma': 'lgamma'
346
+ }
347
+
348
+ # Strings that should be translated
349
+ math_not_functions = {
350
+ 'pi': 'math.pi',
351
+ 'E': 'math.e',
352
+ }
353
+
354
+ ###
355
+ # Python cmath
356
+ ###
357
+
358
+ # Functions that are the same in cmath
359
+ cmath_functions_same = [
360
+ 'sin', 'cos', 'tan', 'asin', 'acos', 'atan',
361
+ 'sinh', 'cosh', 'tanh', 'asinh', 'acosh', 'atanh',
362
+ 'exp', 'log', 'sqrt',
363
+ ]
364
+
365
+ # Functions with different names in cmath
366
+ cmath_functions_different = {
367
+ 'ln': 'log',
368
+ 'arg': 'phase',
369
+ }
370
+
371
+ # Strings that should be translated
372
+ cmath_not_functions = {
373
+ 'pi': 'cmath.pi',
374
+ 'E': 'cmath.e',
375
+ }
376
+
377
+ ###
378
+ # intervalmath
379
+ ###
380
+
381
+ interval_not_functions = {
382
+ 'pi': 'math.pi',
383
+ 'E': 'math.e'
384
+ }
385
+
386
+ interval_functions_same = [
387
+ 'sin', 'cos', 'exp', 'tan', 'atan', 'log',
388
+ 'sqrt', 'cosh', 'sinh', 'tanh', 'floor',
389
+ 'acos', 'asin', 'acosh', 'asinh', 'atanh',
390
+ 'Abs', 'And', 'Or'
391
+ ]
392
+
393
+ interval_functions_different = {
394
+ 'Min': 'imin',
395
+ 'Max': 'imax',
396
+ 'ceiling': 'ceil',
397
+
398
+ }
399
+
400
+ ###
401
+ # mpmath, etc
402
+ ###
403
+ #TODO
404
+
405
+ ###
406
+ # Create the final ordered tuples of dictionaries
407
+ ###
408
+
409
+ # For strings
410
+ def get_dict_str(self):
411
+ dict_str = dict(self.builtin_not_functions)
412
+ if self.use_np:
413
+ dict_str.update(self.numpy_not_functions)
414
+ if self.use_python_math:
415
+ dict_str.update(self.math_not_functions)
416
+ if self.use_python_cmath:
417
+ dict_str.update(self.cmath_not_functions)
418
+ if self.use_interval:
419
+ dict_str.update(self.interval_not_functions)
420
+ return dict_str
421
+
422
+ # For functions
423
+ def get_dict_fun(self):
424
+ dict_fun = dict(self.builtin_functions_different)
425
+ if self.use_np:
426
+ for s in self.numpy_functions_same:
427
+ dict_fun[s] = 'np.' + s
428
+ for k, v in self.numpy_functions_different.items():
429
+ dict_fun[k] = 'np.' + v
430
+ if self.use_python_math:
431
+ for s in self.math_functions_same:
432
+ dict_fun[s] = 'math.' + s
433
+ for k, v in self.math_functions_different.items():
434
+ dict_fun[k] = 'math.' + v
435
+ if self.use_python_cmath:
436
+ for s in self.cmath_functions_same:
437
+ dict_fun[s] = 'cmath.' + s
438
+ for k, v in self.cmath_functions_different.items():
439
+ dict_fun[k] = 'cmath.' + v
440
+ if self.use_interval:
441
+ for s in self.interval_functions_same:
442
+ dict_fun[s] = 'imath.' + s
443
+ for k, v in self.interval_functions_different.items():
444
+ dict_fun[k] = 'imath.' + v
445
+ return dict_fun
446
+
447
+ ##############################################################################
448
+ # The translator functions, tree parsers, etc.
449
+ ##############################################################################
450
+
451
+ def str2tree(self, exprstr):
452
+ """Converts an expression string to a tree.
453
+
454
+ Explanation
455
+ ===========
456
+
457
+ Functions are represented by ('func_name(', tree_of_arguments).
458
+ Other expressions are (head_string, mid_tree, tail_str).
459
+ Expressions that do not contain functions are directly returned.
460
+
461
+ Examples
462
+ ========
463
+
464
+ >>> from sympy.abc import x, y, z
465
+ >>> from sympy import Integral, sin
466
+ >>> from sympy.plotting.experimental_lambdify import Lambdifier
467
+ >>> str2tree = Lambdifier([x], x).str2tree
468
+
469
+ >>> str2tree(str(Integral(x, (x, 1, y))))
470
+ ('', ('Integral(', 'x, (x, 1, y)'), ')')
471
+ >>> str2tree(str(x+y))
472
+ 'x + y'
473
+ >>> str2tree(str(x+y*sin(z)+1))
474
+ ('x + y*', ('sin(', 'z'), ') + 1')
475
+ >>> str2tree('sin(y*(y + 1.1) + (sin(y)))')
476
+ ('', ('sin(', ('y*(y + 1.1) + (', ('sin(', 'y'), '))')), ')')
477
+ """
478
+ #matches the first 'function_name('
479
+ first_par = re.search(r'(\w+\()', exprstr)
480
+ if first_par is None:
481
+ return exprstr
482
+ else:
483
+ start = first_par.start()
484
+ end = first_par.end()
485
+ head = exprstr[:start]
486
+ func = exprstr[start:end]
487
+ tail = exprstr[end:]
488
+ count = 0
489
+ for i, c in enumerate(tail):
490
+ if c == '(':
491
+ count += 1
492
+ elif c == ')':
493
+ count -= 1
494
+ if count == -1:
495
+ break
496
+ func_tail = self.str2tree(tail[:i])
497
+ tail = self.str2tree(tail[i:])
498
+ return (head, (func, func_tail), tail)
499
+
500
+ @classmethod
501
+ def tree2str(cls, tree):
502
+ """Converts a tree to string without translations.
503
+
504
+ Examples
505
+ ========
506
+
507
+ >>> from sympy.abc import x, y, z
508
+ >>> from sympy import sin
509
+ >>> from sympy.plotting.experimental_lambdify import Lambdifier
510
+ >>> str2tree = Lambdifier([x], x).str2tree
511
+ >>> tree2str = Lambdifier([x], x).tree2str
512
+
513
+ >>> tree2str(str2tree(str(x+y*sin(z)+1)))
514
+ 'x + y*sin(z) + 1'
515
+ """
516
+ if isinstance(tree, str):
517
+ return tree
518
+ else:
519
+ return ''.join(map(cls.tree2str, tree))
520
+
521
+ def tree2str_translate(self, tree):
522
+ """Converts a tree to string with translations.
523
+
524
+ Explanation
525
+ ===========
526
+
527
+ Function names are translated by translate_func.
528
+ Other strings are translated by translate_str.
529
+ """
530
+ if isinstance(tree, str):
531
+ return self.translate_str(tree)
532
+ elif isinstance(tree, tuple) and len(tree) == 2:
533
+ return self.translate_func(tree[0][:-1], tree[1])
534
+ else:
535
+ return ''.join([self.tree2str_translate(t) for t in tree])
536
+
537
+ def translate_str(self, estr):
538
+ """Translate substrings of estr using in order the dictionaries in
539
+ dict_tuple_str."""
540
+ for pattern, repl in self.dict_str.items():
541
+ estr = re.sub(pattern, repl, estr)
542
+ return estr
543
+
544
+ def translate_func(self, func_name, argtree):
545
+ """Translate function names and the tree of arguments.
546
+
547
+ Explanation
548
+ ===========
549
+
550
+ If the function name is not in the dictionaries of dict_tuple_fun then the
551
+ function is surrounded by a float((...).evalf()).
552
+
553
+ The use of float is necessary as np.<function>(sympy.Float(..)) raises an
554
+ error."""
555
+ if func_name in self.dict_fun:
556
+ new_name = self.dict_fun[func_name]
557
+ argstr = self.tree2str_translate(argtree)
558
+ return new_name + '(' + argstr
559
+ elif func_name in ['Eq', 'Ne']:
560
+ op = {'Eq': '==', 'Ne': '!='}
561
+ return "(lambda x, y: x {} y)({}".format(op[func_name], self.tree2str_translate(argtree))
562
+ else:
563
+ template = '(%s(%s)).evalf(' if self.use_evalf else '%s(%s'
564
+ if self.float_wrap_evalf:
565
+ template = 'float(%s)' % template
566
+ elif self.complex_wrap_evalf:
567
+ template = 'complex(%s)' % template
568
+
569
+ # Wrapping should only happen on the outermost expression, which
570
+ # is the only thing we know will be a number.
571
+ float_wrap_evalf = self.float_wrap_evalf
572
+ complex_wrap_evalf = self.complex_wrap_evalf
573
+ self.float_wrap_evalf = False
574
+ self.complex_wrap_evalf = False
575
+ ret = template % (func_name, self.tree2str_translate(argtree))
576
+ self.float_wrap_evalf = float_wrap_evalf
577
+ self.complex_wrap_evalf = complex_wrap_evalf
578
+ return ret
579
+
580
+ ##############################################################################
581
+ # The namespace constructors
582
+ ##############################################################################
583
+
584
+ @classmethod
585
+ def sympy_expression_namespace(cls, expr):
586
+ """Traverses the (func, args) tree of an expression and creates a SymPy
587
+ namespace. All other modules are imported only as a module name. That way
588
+ the namespace is not polluted and rests quite small. It probably causes much
589
+ more variable lookups and so it takes more time, but there are no tests on
590
+ that for the moment."""
591
+ if expr is None:
592
+ return {}
593
+ else:
594
+ funcname = str(expr.func)
595
+ # XXX Workaround
596
+ # Here we add an ugly workaround because str(func(x))
597
+ # is not always the same as str(func). Eg
598
+ # >>> str(Integral(x))
599
+ # "Integral(x)"
600
+ # >>> str(Integral)
601
+ # "<class 'sympy.integrals.integrals.Integral'>"
602
+ # >>> str(sqrt(x))
603
+ # "sqrt(x)"
604
+ # >>> str(sqrt)
605
+ # "<function sqrt at 0x3d92de8>"
606
+ # >>> str(sin(x))
607
+ # "sin(x)"
608
+ # >>> str(sin)
609
+ # "sin"
610
+ # Either one of those can be used but not all at the same time.
611
+ # The code considers the sin example as the right one.
612
+ regexlist = [
613
+ r'<class \'sympy[\w.]*?.([\w]*)\'>$',
614
+ # the example Integral
615
+ r'<function ([\w]*) at 0x[\w]*>$', # the example sqrt
616
+ ]
617
+ for r in regexlist:
618
+ m = re.match(r, funcname)
619
+ if m is not None:
620
+ funcname = m.groups()[0]
621
+ # End of the workaround
622
+ # XXX debug: print funcname
623
+ args_dict = {}
624
+ for a in expr.args:
625
+ if (isinstance(a, (Symbol, NumberSymbol)) or a in [I, zoo, oo]):
626
+ continue
627
+ else:
628
+ args_dict.update(cls.sympy_expression_namespace(a))
629
+ args_dict.update({funcname: expr.func})
630
+ return args_dict
631
+
632
+ @staticmethod
633
+ def sympy_atoms_namespace(expr):
634
+ """For no real reason this function is separated from
635
+ sympy_expression_namespace. It can be moved to it."""
636
+ atoms = expr.atoms(Symbol, NumberSymbol, I, zoo, oo)
637
+ d = {}
638
+ for a in atoms:
639
+ # XXX debug: print 'atom:' + str(a)
640
+ d[str(a)] = a
641
+ return d
pythonProject/.venv/Lib/site-packages/sympy/plotting/plot.py ADDED
@@ -0,0 +1,1234 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Plotting module for SymPy.
2
+
3
+ A plot is represented by the ``Plot`` class that contains a reference to the
4
+ backend and a list of the data series to be plotted. The data series are
5
+ instances of classes meant to simplify getting points and meshes from SymPy
6
+ expressions. ``plot_backends`` is a dictionary with all the backends.
7
+
8
+ This module gives only the essential. For all the fancy stuff use directly
9
+ the backend. You can get the backend wrapper for every plot from the
10
+ ``_backend`` attribute. Moreover the data series classes have various useful
11
+ methods like ``get_points``, ``get_meshes``, etc, that may
12
+ be useful if you wish to use another plotting library.
13
+
14
+ Especially if you need publication ready graphs and this module is not enough
15
+ for you - just get the ``_backend`` attribute and add whatever you want
16
+ directly to it. In the case of matplotlib (the common way to graph data in
17
+ python) just copy ``_backend.fig`` which is the figure and ``_backend.ax``
18
+ which is the axis and work on them as you would on any other matplotlib object.
19
+
20
+ Simplicity of code takes much greater importance than performance. Do not use it
21
+ if you care at all about performance. A new backend instance is initialized
22
+ every time you call ``show()`` and the old one is left to the garbage collector.
23
+ """
24
+
25
+ from sympy.concrete.summations import Sum
26
+ from sympy.core.containers import Tuple
27
+ from sympy.core.expr import Expr
28
+ from sympy.core.function import Function, AppliedUndef
29
+ from sympy.core.symbol import (Dummy, Symbol, Wild)
30
+ from sympy.external import import_module
31
+ from sympy.functions import sign
32
+ from sympy.plotting.backends.base_backend import Plot
33
+ from sympy.plotting.backends.matplotlibbackend import MatplotlibBackend
34
+ from sympy.plotting.backends.textbackend import TextBackend
35
+ from sympy.plotting.series import (
36
+ LineOver1DRangeSeries, Parametric2DLineSeries, Parametric3DLineSeries,
37
+ ParametricSurfaceSeries, SurfaceOver2DRangeSeries, ContourSeries)
38
+ from sympy.plotting.utils import _check_arguments, _plot_sympify
39
+ from sympy.tensor.indexed import Indexed
40
+ # to maintain back-compatibility
41
+ from sympy.plotting.plotgrid import PlotGrid # noqa: F401
42
+ from sympy.plotting.series import BaseSeries # noqa: F401
43
+ from sympy.plotting.series import Line2DBaseSeries # noqa: F401
44
+ from sympy.plotting.series import Line3DBaseSeries # noqa: F401
45
+ from sympy.plotting.series import SurfaceBaseSeries # noqa: F401
46
+ from sympy.plotting.series import List2DSeries # noqa: F401
47
+ from sympy.plotting.series import GenericDataSeries # noqa: F401
48
+ from sympy.plotting.series import centers_of_faces # noqa: F401
49
+ from sympy.plotting.series import centers_of_segments # noqa: F401
50
+ from sympy.plotting.series import flat # noqa: F401
51
+ from sympy.plotting.backends.base_backend import unset_show # noqa: F401
52
+ from sympy.plotting.backends.matplotlibbackend import _matplotlib_list # noqa: F401
53
+ from sympy.plotting.textplot import textplot # noqa: F401
54
+
55
+
56
+ __doctest_requires__ = {
57
+ ('plot3d',
58
+ 'plot3d_parametric_line',
59
+ 'plot3d_parametric_surface',
60
+ 'plot_parametric'): ['matplotlib'],
61
+ # XXX: The plot doctest possibly should not require matplotlib. It fails at
62
+ # plot(x**2, (x, -5, 5)) which should be fine for text backend.
63
+ ('plot',): ['matplotlib'],
64
+ }
65
+
66
+
67
+ def _process_summations(sum_bound, *args):
68
+ """Substitute oo (infinity) in the lower/upper bounds of a summation with
69
+ some integer number.
70
+
71
+ Parameters
72
+ ==========
73
+
74
+ sum_bound : int
75
+ oo will be substituted with this integer number.
76
+ *args : list/tuple
77
+ pre-processed arguments of the form (expr, range, ...)
78
+
79
+ Notes
80
+ =====
81
+ Let's consider the following summation: ``Sum(1 / x**2, (x, 1, oo))``.
82
+ The current implementation of lambdify (SymPy 1.12 at the time of
83
+ writing this) will create something of this form:
84
+ ``sum(1 / x**2 for x in range(1, INF))``
85
+ The problem is that ``type(INF)`` is float, while ``range`` requires
86
+ integers: the evaluation fails.
87
+ Instead of modifying ``lambdify`` (which requires a deep knowledge), just
88
+ replace it with some integer number.
89
+ """
90
+ def new_bound(t, bound):
91
+ if (not t.is_number) or t.is_finite:
92
+ return t
93
+ if sign(t) >= 0:
94
+ return bound
95
+ return -bound
96
+
97
+ args = list(args)
98
+ expr = args[0]
99
+
100
+ # select summations whose lower/upper bound is infinity
101
+ w = Wild("w", properties=[
102
+ lambda t: isinstance(t, Sum),
103
+ lambda t: any((not a[1].is_finite) or (not a[2].is_finite) for i, a in enumerate(t.args) if i > 0)
104
+ ])
105
+
106
+ for t in list(expr.find(w)):
107
+ sums_args = list(t.args)
108
+ for i, a in enumerate(sums_args):
109
+ if i > 0:
110
+ sums_args[i] = (a[0], new_bound(a[1], sum_bound),
111
+ new_bound(a[2], sum_bound))
112
+ s = Sum(*sums_args)
113
+ expr = expr.subs(t, s)
114
+ args[0] = expr
115
+ return args
116
+
117
+
118
+ def _build_line_series(*args, **kwargs):
119
+ """Loop over the provided arguments and create the necessary line series.
120
+ """
121
+ series = []
122
+ sum_bound = int(kwargs.get("sum_bound", 1000))
123
+ for arg in args:
124
+ expr, r, label, rendering_kw = arg
125
+ kw = kwargs.copy()
126
+ if rendering_kw is not None:
127
+ kw["rendering_kw"] = rendering_kw
128
+ # TODO: _process_piecewise check goes here
129
+ if not callable(expr):
130
+ arg = _process_summations(sum_bound, *arg)
131
+ series.append(LineOver1DRangeSeries(*arg[:-1], **kw))
132
+ return series
133
+
134
+
135
+ def _create_series(series_type, plot_expr, **kwargs):
136
+ """Extract the rendering_kw dictionary from the provided arguments and
137
+ create an appropriate data series.
138
+ """
139
+ series = []
140
+ for args in plot_expr:
141
+ kw = kwargs.copy()
142
+ if args[-1] is not None:
143
+ kw["rendering_kw"] = args[-1]
144
+ series.append(series_type(*args[:-1], **kw))
145
+ return series
146
+
147
+
148
+ def _set_labels(series, labels, rendering_kw):
149
+ """Apply the `label` and `rendering_kw` keyword arguments to the series.
150
+ """
151
+ if not isinstance(labels, (list, tuple)):
152
+ labels = [labels]
153
+ if len(labels) > 0:
154
+ if len(labels) == 1 and len(series) > 1:
155
+ # if one label is provided and multiple series are being plotted,
156
+ # set the same label to all data series. It maintains
157
+ # back-compatibility
158
+ labels *= len(series)
159
+ if len(series) != len(labels):
160
+ raise ValueError("The number of labels must be equal to the "
161
+ "number of expressions being plotted.\nReceived "
162
+ f"{len(series)} expressions and {len(labels)} labels")
163
+
164
+ for s, l in zip(series, labels):
165
+ s.label = l
166
+
167
+ if rendering_kw:
168
+ if isinstance(rendering_kw, dict):
169
+ rendering_kw = [rendering_kw]
170
+ if len(rendering_kw) == 1:
171
+ rendering_kw *= len(series)
172
+ elif len(series) != len(rendering_kw):
173
+ raise ValueError("The number of rendering dictionaries must be "
174
+ "equal to the number of expressions being plotted.\nReceived "
175
+ f"{len(series)} expressions and {len(labels)} labels")
176
+ for s, r in zip(series, rendering_kw):
177
+ s.rendering_kw = r
178
+
179
+
180
+ def plot_factory(*args, **kwargs):
181
+ backend = kwargs.pop("backend", "default")
182
+ if isinstance(backend, str):
183
+ if backend == "default":
184
+ matplotlib = import_module('matplotlib',
185
+ min_module_version='1.1.0', catch=(RuntimeError,))
186
+ if matplotlib:
187
+ return MatplotlibBackend(*args, **kwargs)
188
+ return TextBackend(*args, **kwargs)
189
+ return plot_backends[backend](*args, **kwargs)
190
+ elif (type(backend) == type) and issubclass(backend, Plot):
191
+ return backend(*args, **kwargs)
192
+ else:
193
+ raise TypeError("backend must be either a string or a subclass of ``Plot``.")
194
+
195
+
196
+ plot_backends = {
197
+ 'matplotlib': MatplotlibBackend,
198
+ 'text': TextBackend,
199
+ }
200
+
201
+
202
+ ####New API for plotting module ####
203
+
204
+ # TODO: Add color arrays for plots.
205
+ # TODO: Add more plotting options for 3d plots.
206
+ # TODO: Adaptive sampling for 3D plots.
207
+
208
+ def plot(*args, show=True, **kwargs):
209
+ """Plots a function of a single variable as a curve.
210
+
211
+ Parameters
212
+ ==========
213
+
214
+ args :
215
+ The first argument is the expression representing the function
216
+ of single variable to be plotted.
217
+
218
+ The last argument is a 3-tuple denoting the range of the free
219
+ variable. e.g. ``(x, 0, 5)``
220
+
221
+ Typical usage examples are in the following:
222
+
223
+ - Plotting a single expression with a single range.
224
+ ``plot(expr, range, **kwargs)``
225
+ - Plotting a single expression with the default range (-10, 10).
226
+ ``plot(expr, **kwargs)``
227
+ - Plotting multiple expressions with a single range.
228
+ ``plot(expr1, expr2, ..., range, **kwargs)``
229
+ - Plotting multiple expressions with multiple ranges.
230
+ ``plot((expr1, range1), (expr2, range2), ..., **kwargs)``
231
+
232
+ It is best practice to specify range explicitly because default
233
+ range may change in the future if a more advanced default range
234
+ detection algorithm is implemented.
235
+
236
+ show : bool, optional
237
+ The default value is set to ``True``. Set show to ``False`` and
238
+ the function will not display the plot. The returned instance of
239
+ the ``Plot`` class can then be used to save or display the plot
240
+ by calling the ``save()`` and ``show()`` methods respectively.
241
+
242
+ line_color : string, or float, or function, optional
243
+ Specifies the color for the plot.
244
+ See ``Plot`` to see how to set color for the plots.
245
+ Note that by setting ``line_color``, it would be applied simultaneously
246
+ to all the series.
247
+
248
+ title : str, optional
249
+ Title of the plot. It is set to the latex representation of
250
+ the expression, if the plot has only one expression.
251
+
252
+ label : str, optional
253
+ The label of the expression in the plot. It will be used when
254
+ called with ``legend``. Default is the name of the expression.
255
+ e.g. ``sin(x)``
256
+
257
+ xlabel : str or expression, optional
258
+ Label for the x-axis.
259
+
260
+ ylabel : str or expression, optional
261
+ Label for the y-axis.
262
+
263
+ xscale : 'linear' or 'log', optional
264
+ Sets the scaling of the x-axis.
265
+
266
+ yscale : 'linear' or 'log', optional
267
+ Sets the scaling of the y-axis.
268
+
269
+ axis_center : (float, float), optional
270
+ Tuple of two floats denoting the coordinates of the center or
271
+ {'center', 'auto'}
272
+
273
+ xlim : (float, float), optional
274
+ Denotes the x-axis limits, ``(min, max)```.
275
+
276
+ ylim : (float, float), optional
277
+ Denotes the y-axis limits, ``(min, max)```.
278
+
279
+ annotations : list, optional
280
+ A list of dictionaries specifying the type of annotation
281
+ required. The keys in the dictionary should be equivalent
282
+ to the arguments of the :external:mod:`matplotlib`'s
283
+ :external:meth:`~matplotlib.axes.Axes.annotate` method.
284
+
285
+ markers : list, optional
286
+ A list of dictionaries specifying the type the markers required.
287
+ The keys in the dictionary should be equivalent to the arguments
288
+ of the :external:mod:`matplotlib`'s :external:func:`~matplotlib.pyplot.plot()` function
289
+ along with the marker related keyworded arguments.
290
+
291
+ rectangles : list, optional
292
+ A list of dictionaries specifying the dimensions of the
293
+ rectangles to be plotted. The keys in the dictionary should be
294
+ equivalent to the arguments of the :external:mod:`matplotlib`'s
295
+ :external:class:`~matplotlib.patches.Rectangle` class.
296
+
297
+ fill : dict, optional
298
+ A dictionary specifying the type of color filling required in
299
+ the plot. The keys in the dictionary should be equivalent to the
300
+ arguments of the :external:mod:`matplotlib`'s
301
+ :external:meth:`~matplotlib.axes.Axes.fill_between` method.
302
+
303
+ adaptive : bool, optional
304
+ The default value is set to ``True``. Set adaptive to ``False``
305
+ and specify ``n`` if uniform sampling is required.
306
+
307
+ The plotting uses an adaptive algorithm which samples
308
+ recursively to accurately plot. The adaptive algorithm uses a
309
+ random point near the midpoint of two points that has to be
310
+ further sampled. Hence the same plots can appear slightly
311
+ different.
312
+
313
+ depth : int, optional
314
+ Recursion depth of the adaptive algorithm. A depth of value
315
+ `n` samples a maximum of `2^{n}` points.
316
+
317
+ If the ``adaptive`` flag is set to ``False``, this will be
318
+ ignored.
319
+
320
+ n : int, optional
321
+ Used when the ``adaptive`` is set to ``False``. The function
322
+ is uniformly sampled at ``n`` number of points. If the ``adaptive``
323
+ flag is set to ``True``, this will be ignored.
324
+ This keyword argument replaces ``nb_of_points``, which should be
325
+ considered deprecated.
326
+
327
+ size : (float, float), optional
328
+ A tuple in the form (width, height) in inches to specify the size of
329
+ the overall figure. The default value is set to ``None``, meaning
330
+ the size will be set by the default backend.
331
+
332
+ Examples
333
+ ========
334
+
335
+ .. plot::
336
+ :context: close-figs
337
+ :format: doctest
338
+ :include-source: True
339
+
340
+ >>> from sympy import symbols
341
+ >>> from sympy.plotting import plot
342
+ >>> x = symbols('x')
343
+
344
+ Single Plot
345
+
346
+ .. plot::
347
+ :context: close-figs
348
+ :format: doctest
349
+ :include-source: True
350
+
351
+ >>> plot(x**2, (x, -5, 5))
352
+ Plot object containing:
353
+ [0]: cartesian line: x**2 for x over (-5.0, 5.0)
354
+
355
+ Multiple plots with single range.
356
+
357
+ .. plot::
358
+ :context: close-figs
359
+ :format: doctest
360
+ :include-source: True
361
+
362
+ >>> plot(x, x**2, x**3, (x, -5, 5))
363
+ Plot object containing:
364
+ [0]: cartesian line: x for x over (-5.0, 5.0)
365
+ [1]: cartesian line: x**2 for x over (-5.0, 5.0)
366
+ [2]: cartesian line: x**3 for x over (-5.0, 5.0)
367
+
368
+ Multiple plots with different ranges.
369
+
370
+ .. plot::
371
+ :context: close-figs
372
+ :format: doctest
373
+ :include-source: True
374
+
375
+ >>> plot((x**2, (x, -6, 6)), (x, (x, -5, 5)))
376
+ Plot object containing:
377
+ [0]: cartesian line: x**2 for x over (-6.0, 6.0)
378
+ [1]: cartesian line: x for x over (-5.0, 5.0)
379
+
380
+ No adaptive sampling.
381
+
382
+ .. plot::
383
+ :context: close-figs
384
+ :format: doctest
385
+ :include-source: True
386
+
387
+ >>> plot(x**2, adaptive=False, n=400)
388
+ Plot object containing:
389
+ [0]: cartesian line: x**2 for x over (-10.0, 10.0)
390
+
391
+ See Also
392
+ ========
393
+
394
+ Plot, LineOver1DRangeSeries
395
+
396
+ """
397
+ args = _plot_sympify(args)
398
+ plot_expr = _check_arguments(args, 1, 1, **kwargs)
399
+ params = kwargs.get("params", None)
400
+ free = set()
401
+ for p in plot_expr:
402
+ if not isinstance(p[1][0], str):
403
+ free |= {p[1][0]}
404
+ else:
405
+ free |= {Symbol(p[1][0])}
406
+ if params:
407
+ free = free.difference(params.keys())
408
+ x = free.pop() if free else Symbol("x")
409
+ kwargs.setdefault('xlabel', x)
410
+ kwargs.setdefault('ylabel', Function('f')(x))
411
+
412
+ labels = kwargs.pop("label", [])
413
+ rendering_kw = kwargs.pop("rendering_kw", None)
414
+ series = _build_line_series(*plot_expr, **kwargs)
415
+ _set_labels(series, labels, rendering_kw)
416
+
417
+ plots = plot_factory(*series, **kwargs)
418
+ if show:
419
+ plots.show()
420
+ return plots
421
+
422
+
423
+ def plot_parametric(*args, show=True, **kwargs):
424
+ """
425
+ Plots a 2D parametric curve.
426
+
427
+ Parameters
428
+ ==========
429
+
430
+ args
431
+ Common specifications are:
432
+
433
+ - Plotting a single parametric curve with a range
434
+ ``plot_parametric((expr_x, expr_y), range)``
435
+ - Plotting multiple parametric curves with the same range
436
+ ``plot_parametric((expr_x, expr_y), ..., range)``
437
+ - Plotting multiple parametric curves with different ranges
438
+ ``plot_parametric((expr_x, expr_y, range), ...)``
439
+
440
+ ``expr_x`` is the expression representing $x$ component of the
441
+ parametric function.
442
+
443
+ ``expr_y`` is the expression representing $y$ component of the
444
+ parametric function.
445
+
446
+ ``range`` is a 3-tuple denoting the parameter symbol, start and
447
+ stop. For example, ``(u, 0, 5)``.
448
+
449
+ If the range is not specified, then a default range of (-10, 10)
450
+ is used.
451
+
452
+ However, if the arguments are specified as
453
+ ``(expr_x, expr_y, range), ...``, you must specify the ranges
454
+ for each expressions manually.
455
+
456
+ Default range may change in the future if a more advanced
457
+ algorithm is implemented.
458
+
459
+ adaptive : bool, optional
460
+ Specifies whether to use the adaptive sampling or not.
461
+
462
+ The default value is set to ``True``. Set adaptive to ``False``
463
+ and specify ``n`` if uniform sampling is required.
464
+
465
+ depth : int, optional
466
+ The recursion depth of the adaptive algorithm. A depth of
467
+ value $n$ samples a maximum of $2^n$ points.
468
+
469
+ n : int, optional
470
+ Used when the ``adaptive`` flag is set to ``False``. Specifies the
471
+ number of the points used for the uniform sampling.
472
+ This keyword argument replaces ``nb_of_points``, which should be
473
+ considered deprecated.
474
+
475
+ line_color : string, or float, or function, optional
476
+ Specifies the color for the plot.
477
+ See ``Plot`` to see how to set color for the plots.
478
+ Note that by setting ``line_color``, it would be applied simultaneously
479
+ to all the series.
480
+
481
+ label : str, optional
482
+ The label of the expression in the plot. It will be used when
483
+ called with ``legend``. Default is the name of the expression.
484
+ e.g. ``sin(x)``
485
+
486
+ xlabel : str, optional
487
+ Label for the x-axis.
488
+
489
+ ylabel : str, optional
490
+ Label for the y-axis.
491
+
492
+ xscale : 'linear' or 'log', optional
493
+ Sets the scaling of the x-axis.
494
+
495
+ yscale : 'linear' or 'log', optional
496
+ Sets the scaling of the y-axis.
497
+
498
+ axis_center : (float, float), optional
499
+ Tuple of two floats denoting the coordinates of the center or
500
+ {'center', 'auto'}
501
+
502
+ xlim : (float, float), optional
503
+ Denotes the x-axis limits, ``(min, max)```.
504
+
505
+ ylim : (float, float), optional
506
+ Denotes the y-axis limits, ``(min, max)```.
507
+
508
+ size : (float, float), optional
509
+ A tuple in the form (width, height) in inches to specify the size of
510
+ the overall figure. The default value is set to ``None``, meaning
511
+ the size will be set by the default backend.
512
+
513
+ Examples
514
+ ========
515
+
516
+ .. plot::
517
+ :context: reset
518
+ :format: doctest
519
+ :include-source: True
520
+
521
+ >>> from sympy import plot_parametric, symbols, cos, sin
522
+ >>> u = symbols('u')
523
+
524
+ A parametric plot with a single expression:
525
+
526
+ .. plot::
527
+ :context: close-figs
528
+ :format: doctest
529
+ :include-source: True
530
+
531
+ >>> plot_parametric((cos(u), sin(u)), (u, -5, 5))
532
+ Plot object containing:
533
+ [0]: parametric cartesian line: (cos(u), sin(u)) for u over (-5.0, 5.0)
534
+
535
+ A parametric plot with multiple expressions with the same range:
536
+
537
+ .. plot::
538
+ :context: close-figs
539
+ :format: doctest
540
+ :include-source: True
541
+
542
+ >>> plot_parametric((cos(u), sin(u)), (u, cos(u)), (u, -10, 10))
543
+ Plot object containing:
544
+ [0]: parametric cartesian line: (cos(u), sin(u)) for u over (-10.0, 10.0)
545
+ [1]: parametric cartesian line: (u, cos(u)) for u over (-10.0, 10.0)
546
+
547
+ A parametric plot with multiple expressions with different ranges
548
+ for each curve:
549
+
550
+ .. plot::
551
+ :context: close-figs
552
+ :format: doctest
553
+ :include-source: True
554
+
555
+ >>> plot_parametric((cos(u), sin(u), (u, -5, 5)),
556
+ ... (cos(u), u, (u, -5, 5)))
557
+ Plot object containing:
558
+ [0]: parametric cartesian line: (cos(u), sin(u)) for u over (-5.0, 5.0)
559
+ [1]: parametric cartesian line: (cos(u), u) for u over (-5.0, 5.0)
560
+
561
+ Notes
562
+ =====
563
+
564
+ The plotting uses an adaptive algorithm which samples recursively to
565
+ accurately plot the curve. The adaptive algorithm uses a random point
566
+ near the midpoint of two points that has to be further sampled.
567
+ Hence, repeating the same plot command can give slightly different
568
+ results because of the random sampling.
569
+
570
+ If there are multiple plots, then the same optional arguments are
571
+ applied to all the plots drawn in the same canvas. If you want to
572
+ set these options separately, you can index the returned ``Plot``
573
+ object and set it.
574
+
575
+ For example, when you specify ``line_color`` once, it would be
576
+ applied simultaneously to both series.
577
+
578
+ .. plot::
579
+ :context: close-figs
580
+ :format: doctest
581
+ :include-source: True
582
+
583
+ >>> from sympy import pi
584
+ >>> expr1 = (u, cos(2*pi*u)/2 + 1/2)
585
+ >>> expr2 = (u, sin(2*pi*u)/2 + 1/2)
586
+ >>> p = plot_parametric(expr1, expr2, (u, 0, 1), line_color='blue')
587
+
588
+ If you want to specify the line color for the specific series, you
589
+ should index each item and apply the property manually.
590
+
591
+ .. plot::
592
+ :context: close-figs
593
+ :format: doctest
594
+ :include-source: True
595
+
596
+ >>> p[0].line_color = 'red'
597
+ >>> p.show()
598
+
599
+ See Also
600
+ ========
601
+
602
+ Plot, Parametric2DLineSeries
603
+ """
604
+ args = _plot_sympify(args)
605
+ plot_expr = _check_arguments(args, 2, 1, **kwargs)
606
+
607
+ labels = kwargs.pop("label", [])
608
+ rendering_kw = kwargs.pop("rendering_kw", None)
609
+ series = _create_series(Parametric2DLineSeries, plot_expr, **kwargs)
610
+ _set_labels(series, labels, rendering_kw)
611
+
612
+ plots = plot_factory(*series, **kwargs)
613
+ if show:
614
+ plots.show()
615
+ return plots
616
+
617
+
618
+ def plot3d_parametric_line(*args, show=True, **kwargs):
619
+ """
620
+ Plots a 3D parametric line plot.
621
+
622
+ Usage
623
+ =====
624
+
625
+ Single plot:
626
+
627
+ ``plot3d_parametric_line(expr_x, expr_y, expr_z, range, **kwargs)``
628
+
629
+ If the range is not specified, then a default range of (-10, 10) is used.
630
+
631
+ Multiple plots.
632
+
633
+ ``plot3d_parametric_line((expr_x, expr_y, expr_z, range), ..., **kwargs)``
634
+
635
+ Ranges have to be specified for every expression.
636
+
637
+ Default range may change in the future if a more advanced default range
638
+ detection algorithm is implemented.
639
+
640
+ Arguments
641
+ =========
642
+
643
+ expr_x : Expression representing the function along x.
644
+
645
+ expr_y : Expression representing the function along y.
646
+
647
+ expr_z : Expression representing the function along z.
648
+
649
+ range : (:class:`~.Symbol`, float, float)
650
+ A 3-tuple denoting the range of the parameter variable, e.g., (u, 0, 5).
651
+
652
+ Keyword Arguments
653
+ =================
654
+
655
+ Arguments for ``Parametric3DLineSeries`` class.
656
+
657
+ n : int
658
+ The range is uniformly sampled at ``n`` number of points.
659
+ This keyword argument replaces ``nb_of_points``, which should be
660
+ considered deprecated.
661
+
662
+ Aesthetics:
663
+
664
+ line_color : string, or float, or function, optional
665
+ Specifies the color for the plot.
666
+ See ``Plot`` to see how to set color for the plots.
667
+ Note that by setting ``line_color``, it would be applied simultaneously
668
+ to all the series.
669
+
670
+ label : str
671
+ The label to the plot. It will be used when called with ``legend=True``
672
+ to denote the function with the given label in the plot.
673
+
674
+ If there are multiple plots, then the same series arguments are applied to
675
+ all the plots. If you want to set these options separately, you can index
676
+ the returned ``Plot`` object and set it.
677
+
678
+ Arguments for ``Plot`` class.
679
+
680
+ title : str
681
+ Title of the plot.
682
+
683
+ size : (float, float), optional
684
+ A tuple in the form (width, height) in inches to specify the size of
685
+ the overall figure. The default value is set to ``None``, meaning
686
+ the size will be set by the default backend.
687
+
688
+ Examples
689
+ ========
690
+
691
+ .. plot::
692
+ :context: reset
693
+ :format: doctest
694
+ :include-source: True
695
+
696
+ >>> from sympy import symbols, cos, sin
697
+ >>> from sympy.plotting import plot3d_parametric_line
698
+ >>> u = symbols('u')
699
+
700
+ Single plot.
701
+
702
+ .. plot::
703
+ :context: close-figs
704
+ :format: doctest
705
+ :include-source: True
706
+
707
+ >>> plot3d_parametric_line(cos(u), sin(u), u, (u, -5, 5))
708
+ Plot object containing:
709
+ [0]: 3D parametric cartesian line: (cos(u), sin(u), u) for u over (-5.0, 5.0)
710
+
711
+
712
+ Multiple plots.
713
+
714
+ .. plot::
715
+ :context: close-figs
716
+ :format: doctest
717
+ :include-source: True
718
+
719
+ >>> plot3d_parametric_line((cos(u), sin(u), u, (u, -5, 5)),
720
+ ... (sin(u), u**2, u, (u, -5, 5)))
721
+ Plot object containing:
722
+ [0]: 3D parametric cartesian line: (cos(u), sin(u), u) for u over (-5.0, 5.0)
723
+ [1]: 3D parametric cartesian line: (sin(u), u**2, u) for u over (-5.0, 5.0)
724
+
725
+
726
+ See Also
727
+ ========
728
+
729
+ Plot, Parametric3DLineSeries
730
+
731
+ """
732
+ args = _plot_sympify(args)
733
+ plot_expr = _check_arguments(args, 3, 1, **kwargs)
734
+ kwargs.setdefault("xlabel", "x")
735
+ kwargs.setdefault("ylabel", "y")
736
+ kwargs.setdefault("zlabel", "z")
737
+
738
+ labels = kwargs.pop("label", [])
739
+ rendering_kw = kwargs.pop("rendering_kw", None)
740
+ series = _create_series(Parametric3DLineSeries, plot_expr, **kwargs)
741
+ _set_labels(series, labels, rendering_kw)
742
+
743
+ plots = plot_factory(*series, **kwargs)
744
+ if show:
745
+ plots.show()
746
+ return plots
747
+
748
+
749
+ def _plot3d_plot_contour_helper(Series, *args, **kwargs):
750
+ """plot3d and plot_contour are structurally identical. Let's reduce
751
+ code repetition.
752
+ """
753
+ # NOTE: if this import would be at the top-module level, it would trigger
754
+ # SymPy's optional-dependencies tests to fail.
755
+ from sympy.vector import BaseScalar
756
+
757
+ args = _plot_sympify(args)
758
+ plot_expr = _check_arguments(args, 1, 2, **kwargs)
759
+
760
+ free_x = set()
761
+ free_y = set()
762
+ _types = (Symbol, BaseScalar, Indexed, AppliedUndef)
763
+ for p in plot_expr:
764
+ free_x |= {p[1][0]} if isinstance(p[1][0], _types) else {Symbol(p[1][0])}
765
+ free_y |= {p[2][0]} if isinstance(p[2][0], _types) else {Symbol(p[2][0])}
766
+ x = free_x.pop() if free_x else Symbol("x")
767
+ y = free_y.pop() if free_y else Symbol("y")
768
+ kwargs.setdefault("xlabel", x)
769
+ kwargs.setdefault("ylabel", y)
770
+ kwargs.setdefault("zlabel", Function('f')(x, y))
771
+
772
+ # if a polar discretization is requested and automatic labelling has ben
773
+ # applied, hide the labels on the x-y axis.
774
+ if kwargs.get("is_polar", False):
775
+ if callable(kwargs["xlabel"]):
776
+ kwargs["xlabel"] = ""
777
+ if callable(kwargs["ylabel"]):
778
+ kwargs["ylabel"] = ""
779
+
780
+ labels = kwargs.pop("label", [])
781
+ rendering_kw = kwargs.pop("rendering_kw", None)
782
+ series = _create_series(Series, plot_expr, **kwargs)
783
+ _set_labels(series, labels, rendering_kw)
784
+ plots = plot_factory(*series, **kwargs)
785
+ if kwargs.get("show", True):
786
+ plots.show()
787
+ return plots
788
+
789
+
790
+ def plot3d(*args, show=True, **kwargs):
791
+ """
792
+ Plots a 3D surface plot.
793
+
794
+ Usage
795
+ =====
796
+
797
+ Single plot
798
+
799
+ ``plot3d(expr, range_x, range_y, **kwargs)``
800
+
801
+ If the ranges are not specified, then a default range of (-10, 10) is used.
802
+
803
+ Multiple plot with the same range.
804
+
805
+ ``plot3d(expr1, expr2, range_x, range_y, **kwargs)``
806
+
807
+ If the ranges are not specified, then a default range of (-10, 10) is used.
808
+
809
+ Multiple plots with different ranges.
810
+
811
+ ``plot3d((expr1, range_x, range_y), (expr2, range_x, range_y), ..., **kwargs)``
812
+
813
+ Ranges have to be specified for every expression.
814
+
815
+ Default range may change in the future if a more advanced default range
816
+ detection algorithm is implemented.
817
+
818
+ Arguments
819
+ =========
820
+
821
+ expr : Expression representing the function along x.
822
+
823
+ range_x : (:class:`~.Symbol`, float, float)
824
+ A 3-tuple denoting the range of the x variable, e.g. (x, 0, 5).
825
+
826
+ range_y : (:class:`~.Symbol`, float, float)
827
+ A 3-tuple denoting the range of the y variable, e.g. (y, 0, 5).
828
+
829
+ Keyword Arguments
830
+ =================
831
+
832
+ Arguments for ``SurfaceOver2DRangeSeries`` class:
833
+
834
+ n1 : int
835
+ The x range is sampled uniformly at ``n1`` of points.
836
+ This keyword argument replaces ``nb_of_points_x``, which should be
837
+ considered deprecated.
838
+
839
+ n2 : int
840
+ The y range is sampled uniformly at ``n2`` of points.
841
+ This keyword argument replaces ``nb_of_points_y``, which should be
842
+ considered deprecated.
843
+
844
+ Aesthetics:
845
+
846
+ surface_color : Function which returns a float
847
+ Specifies the color for the surface of the plot.
848
+ See :class:`~.Plot` for more details.
849
+
850
+ If there are multiple plots, then the same series arguments are applied to
851
+ all the plots. If you want to set these options separately, you can index
852
+ the returned ``Plot`` object and set it.
853
+
854
+ Arguments for ``Plot`` class:
855
+
856
+ title : str
857
+ Title of the plot.
858
+
859
+ size : (float, float), optional
860
+ A tuple in the form (width, height) in inches to specify the size of the
861
+ overall figure. The default value is set to ``None``, meaning the size will
862
+ be set by the default backend.
863
+
864
+ Examples
865
+ ========
866
+
867
+ .. plot::
868
+ :context: reset
869
+ :format: doctest
870
+ :include-source: True
871
+
872
+ >>> from sympy import symbols
873
+ >>> from sympy.plotting import plot3d
874
+ >>> x, y = symbols('x y')
875
+
876
+ Single plot
877
+
878
+ .. plot::
879
+ :context: close-figs
880
+ :format: doctest
881
+ :include-source: True
882
+
883
+ >>> plot3d(x*y, (x, -5, 5), (y, -5, 5))
884
+ Plot object containing:
885
+ [0]: cartesian surface: x*y for x over (-5.0, 5.0) and y over (-5.0, 5.0)
886
+
887
+
888
+ Multiple plots with same range
889
+
890
+ .. plot::
891
+ :context: close-figs
892
+ :format: doctest
893
+ :include-source: True
894
+
895
+ >>> plot3d(x*y, -x*y, (x, -5, 5), (y, -5, 5))
896
+ Plot object containing:
897
+ [0]: cartesian surface: x*y for x over (-5.0, 5.0) and y over (-5.0, 5.0)
898
+ [1]: cartesian surface: -x*y for x over (-5.0, 5.0) and y over (-5.0, 5.0)
899
+
900
+
901
+ Multiple plots with different ranges.
902
+
903
+ .. plot::
904
+ :context: close-figs
905
+ :format: doctest
906
+ :include-source: True
907
+
908
+ >>> plot3d((x**2 + y**2, (x, -5, 5), (y, -5, 5)),
909
+ ... (x*y, (x, -3, 3), (y, -3, 3)))
910
+ Plot object containing:
911
+ [0]: cartesian surface: x**2 + y**2 for x over (-5.0, 5.0) and y over (-5.0, 5.0)
912
+ [1]: cartesian surface: x*y for x over (-3.0, 3.0) and y over (-3.0, 3.0)
913
+
914
+
915
+ See Also
916
+ ========
917
+
918
+ Plot, SurfaceOver2DRangeSeries
919
+
920
+ """
921
+ kwargs.setdefault("show", show)
922
+ return _plot3d_plot_contour_helper(
923
+ SurfaceOver2DRangeSeries, *args, **kwargs)
924
+
925
+
926
+ def plot3d_parametric_surface(*args, show=True, **kwargs):
927
+ """
928
+ Plots a 3D parametric surface plot.
929
+
930
+ Explanation
931
+ ===========
932
+
933
+ Single plot.
934
+
935
+ ``plot3d_parametric_surface(expr_x, expr_y, expr_z, range_u, range_v, **kwargs)``
936
+
937
+ If the ranges is not specified, then a default range of (-10, 10) is used.
938
+
939
+ Multiple plots.
940
+
941
+ ``plot3d_parametric_surface((expr_x, expr_y, expr_z, range_u, range_v), ..., **kwargs)``
942
+
943
+ Ranges have to be specified for every expression.
944
+
945
+ Default range may change in the future if a more advanced default range
946
+ detection algorithm is implemented.
947
+
948
+ Arguments
949
+ =========
950
+
951
+ expr_x : Expression representing the function along ``x``.
952
+
953
+ expr_y : Expression representing the function along ``y``.
954
+
955
+ expr_z : Expression representing the function along ``z``.
956
+
957
+ range_u : (:class:`~.Symbol`, float, float)
958
+ A 3-tuple denoting the range of the u variable, e.g. (u, 0, 5).
959
+
960
+ range_v : (:class:`~.Symbol`, float, float)
961
+ A 3-tuple denoting the range of the v variable, e.g. (v, 0, 5).
962
+
963
+ Keyword Arguments
964
+ =================
965
+
966
+ Arguments for ``ParametricSurfaceSeries`` class:
967
+
968
+ n1 : int
969
+ The ``u`` range is sampled uniformly at ``n1`` of points.
970
+ This keyword argument replaces ``nb_of_points_u``, which should be
971
+ considered deprecated.
972
+
973
+ n2 : int
974
+ The ``v`` range is sampled uniformly at ``n2`` of points.
975
+ This keyword argument replaces ``nb_of_points_v``, which should be
976
+ considered deprecated.
977
+
978
+ Aesthetics:
979
+
980
+ surface_color : Function which returns a float
981
+ Specifies the color for the surface of the plot. See
982
+ :class:`~Plot` for more details.
983
+
984
+ If there are multiple plots, then the same series arguments are applied for
985
+ all the plots. If you want to set these options separately, you can index
986
+ the returned ``Plot`` object and set it.
987
+
988
+
989
+ Arguments for ``Plot`` class:
990
+
991
+ title : str
992
+ Title of the plot.
993
+
994
+ size : (float, float), optional
995
+ A tuple in the form (width, height) in inches to specify the size of the
996
+ overall figure. The default value is set to ``None``, meaning the size will
997
+ be set by the default backend.
998
+
999
+ Examples
1000
+ ========
1001
+
1002
+ .. plot::
1003
+ :context: reset
1004
+ :format: doctest
1005
+ :include-source: True
1006
+
1007
+ >>> from sympy import symbols, cos, sin
1008
+ >>> from sympy.plotting import plot3d_parametric_surface
1009
+ >>> u, v = symbols('u v')
1010
+
1011
+ Single plot.
1012
+
1013
+ .. plot::
1014
+ :context: close-figs
1015
+ :format: doctest
1016
+ :include-source: True
1017
+
1018
+ >>> plot3d_parametric_surface(cos(u + v), sin(u - v), u - v,
1019
+ ... (u, -5, 5), (v, -5, 5))
1020
+ Plot object containing:
1021
+ [0]: parametric cartesian surface: (cos(u + v), sin(u - v), u - v) for u over (-5.0, 5.0) and v over (-5.0, 5.0)
1022
+
1023
+
1024
+ See Also
1025
+ ========
1026
+
1027
+ Plot, ParametricSurfaceSeries
1028
+
1029
+ """
1030
+
1031
+ args = _plot_sympify(args)
1032
+ plot_expr = _check_arguments(args, 3, 2, **kwargs)
1033
+ kwargs.setdefault("xlabel", "x")
1034
+ kwargs.setdefault("ylabel", "y")
1035
+ kwargs.setdefault("zlabel", "z")
1036
+
1037
+ labels = kwargs.pop("label", [])
1038
+ rendering_kw = kwargs.pop("rendering_kw", None)
1039
+ series = _create_series(ParametricSurfaceSeries, plot_expr, **kwargs)
1040
+ _set_labels(series, labels, rendering_kw)
1041
+
1042
+ plots = plot_factory(*series, **kwargs)
1043
+ if show:
1044
+ plots.show()
1045
+ return plots
1046
+
1047
+ def plot_contour(*args, show=True, **kwargs):
1048
+ """
1049
+ Draws contour plot of a function
1050
+
1051
+ Usage
1052
+ =====
1053
+
1054
+ Single plot
1055
+
1056
+ ``plot_contour(expr, range_x, range_y, **kwargs)``
1057
+
1058
+ If the ranges are not specified, then a default range of (-10, 10) is used.
1059
+
1060
+ Multiple plot with the same range.
1061
+
1062
+ ``plot_contour(expr1, expr2, range_x, range_y, **kwargs)``
1063
+
1064
+ If the ranges are not specified, then a default range of (-10, 10) is used.
1065
+
1066
+ Multiple plots with different ranges.
1067
+
1068
+ ``plot_contour((expr1, range_x, range_y), (expr2, range_x, range_y), ..., **kwargs)``
1069
+
1070
+ Ranges have to be specified for every expression.
1071
+
1072
+ Default range may change in the future if a more advanced default range
1073
+ detection algorithm is implemented.
1074
+
1075
+ Arguments
1076
+ =========
1077
+
1078
+ expr : Expression representing the function along x.
1079
+
1080
+ range_x : (:class:`Symbol`, float, float)
1081
+ A 3-tuple denoting the range of the x variable, e.g. (x, 0, 5).
1082
+
1083
+ range_y : (:class:`Symbol`, float, float)
1084
+ A 3-tuple denoting the range of the y variable, e.g. (y, 0, 5).
1085
+
1086
+ Keyword Arguments
1087
+ =================
1088
+
1089
+ Arguments for ``ContourSeries`` class:
1090
+
1091
+ n1 : int
1092
+ The x range is sampled uniformly at ``n1`` of points.
1093
+ This keyword argument replaces ``nb_of_points_x``, which should be
1094
+ considered deprecated.
1095
+
1096
+ n2 : int
1097
+ The y range is sampled uniformly at ``n2`` of points.
1098
+ This keyword argument replaces ``nb_of_points_y``, which should be
1099
+ considered deprecated.
1100
+
1101
+ Aesthetics:
1102
+
1103
+ surface_color : Function which returns a float
1104
+ Specifies the color for the surface of the plot. See
1105
+ :class:`sympy.plotting.Plot` for more details.
1106
+
1107
+ If there are multiple plots, then the same series arguments are applied to
1108
+ all the plots. If you want to set these options separately, you can index
1109
+ the returned ``Plot`` object and set it.
1110
+
1111
+ Arguments for ``Plot`` class:
1112
+
1113
+ title : str
1114
+ Title of the plot.
1115
+
1116
+ size : (float, float), optional
1117
+ A tuple in the form (width, height) in inches to specify the size of
1118
+ the overall figure. The default value is set to ``None``, meaning
1119
+ the size will be set by the default backend.
1120
+
1121
+ See Also
1122
+ ========
1123
+
1124
+ Plot, ContourSeries
1125
+
1126
+ """
1127
+ kwargs.setdefault("show", show)
1128
+ return _plot3d_plot_contour_helper(ContourSeries, *args, **kwargs)
1129
+
1130
+
1131
+ def check_arguments(args, expr_len, nb_of_free_symbols):
1132
+ """
1133
+ Checks the arguments and converts into tuples of the
1134
+ form (exprs, ranges).
1135
+
1136
+ Examples
1137
+ ========
1138
+
1139
+ .. plot::
1140
+ :context: reset
1141
+ :format: doctest
1142
+ :include-source: True
1143
+
1144
+ >>> from sympy import cos, sin, symbols
1145
+ >>> from sympy.plotting.plot import check_arguments
1146
+ >>> x = symbols('x')
1147
+ >>> check_arguments([cos(x), sin(x)], 2, 1)
1148
+ [(cos(x), sin(x), (x, -10, 10))]
1149
+
1150
+ >>> check_arguments([x, x**2], 1, 1)
1151
+ [(x, (x, -10, 10)), (x**2, (x, -10, 10))]
1152
+ """
1153
+ if not args:
1154
+ return []
1155
+ if expr_len > 1 and isinstance(args[0], Expr):
1156
+ # Multiple expressions same range.
1157
+ # The arguments are tuples when the expression length is
1158
+ # greater than 1.
1159
+ if len(args) < expr_len:
1160
+ raise ValueError("len(args) should not be less than expr_len")
1161
+ for i in range(len(args)):
1162
+ if isinstance(args[i], Tuple):
1163
+ break
1164
+ else:
1165
+ i = len(args) + 1
1166
+
1167
+ exprs = Tuple(*args[:i])
1168
+ free_symbols = list(set().union(*[e.free_symbols for e in exprs]))
1169
+ if len(args) == expr_len + nb_of_free_symbols:
1170
+ #Ranges given
1171
+ plots = [exprs + Tuple(*args[expr_len:])]
1172
+ else:
1173
+ default_range = Tuple(-10, 10)
1174
+ ranges = []
1175
+ for symbol in free_symbols:
1176
+ ranges.append(Tuple(symbol) + default_range)
1177
+
1178
+ for i in range(len(free_symbols) - nb_of_free_symbols):
1179
+ ranges.append(Tuple(Dummy()) + default_range)
1180
+ plots = [exprs + Tuple(*ranges)]
1181
+ return plots
1182
+
1183
+ if isinstance(args[0], Expr) or (isinstance(args[0], Tuple) and
1184
+ len(args[0]) == expr_len and
1185
+ expr_len != 3):
1186
+ # Cannot handle expressions with number of expression = 3. It is
1187
+ # not possible to differentiate between expressions and ranges.
1188
+ #Series of plots with same range
1189
+ for i in range(len(args)):
1190
+ if isinstance(args[i], Tuple) and len(args[i]) != expr_len:
1191
+ break
1192
+ if not isinstance(args[i], Tuple):
1193
+ args[i] = Tuple(args[i])
1194
+ else:
1195
+ i = len(args) + 1
1196
+
1197
+ exprs = args[:i]
1198
+ assert all(isinstance(e, Expr) for expr in exprs for e in expr)
1199
+ free_symbols = list(set().union(*[e.free_symbols for expr in exprs
1200
+ for e in expr]))
1201
+
1202
+ if len(free_symbols) > nb_of_free_symbols:
1203
+ raise ValueError("The number of free_symbols in the expression "
1204
+ "is greater than %d" % nb_of_free_symbols)
1205
+ if len(args) == i + nb_of_free_symbols and isinstance(args[i], Tuple):
1206
+ ranges = Tuple(*list(args[
1207
+ i:i + nb_of_free_symbols]))
1208
+ plots = [expr + ranges for expr in exprs]
1209
+ return plots
1210
+ else:
1211
+ # Use default ranges.
1212
+ default_range = Tuple(-10, 10)
1213
+ ranges = []
1214
+ for symbol in free_symbols:
1215
+ ranges.append(Tuple(symbol) + default_range)
1216
+
1217
+ for i in range(nb_of_free_symbols - len(free_symbols)):
1218
+ ranges.append(Tuple(Dummy()) + default_range)
1219
+ ranges = Tuple(*ranges)
1220
+ plots = [expr + ranges for expr in exprs]
1221
+ return plots
1222
+
1223
+ elif isinstance(args[0], Tuple) and len(args[0]) == expr_len + nb_of_free_symbols:
1224
+ # Multiple plots with different ranges.
1225
+ for arg in args:
1226
+ for i in range(expr_len):
1227
+ if not isinstance(arg[i], Expr):
1228
+ raise ValueError("Expected an expression, given %s" %
1229
+ str(arg[i]))
1230
+ for i in range(nb_of_free_symbols):
1231
+ if not len(arg[i + expr_len]) == 3:
1232
+ raise ValueError("The ranges should be a tuple of "
1233
+ "length 3, got %s" % str(arg[i + expr_len]))
1234
+ return args
pythonProject/.venv/Lib/site-packages/sympy/plotting/plotgrid.py ADDED
@@ -0,0 +1,188 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ from sympy.external import import_module
3
+ import sympy.plotting.backends.base_backend as base_backend
4
+
5
+
6
+ # N.B.
7
+ # When changing the minimum module version for matplotlib, please change
8
+ # the same in the `SymPyDocTestFinder`` in `sympy/testing/runtests.py`
9
+
10
+
11
+ __doctest_requires__ = {
12
+ ("PlotGrid",): ["matplotlib"],
13
+ }
14
+
15
+
16
+ class PlotGrid:
17
+ """This class helps to plot subplots from already created SymPy plots
18
+ in a single figure.
19
+
20
+ Examples
21
+ ========
22
+
23
+ .. plot::
24
+ :context: close-figs
25
+ :format: doctest
26
+ :include-source: True
27
+
28
+ >>> from sympy import symbols
29
+ >>> from sympy.plotting import plot, plot3d, PlotGrid
30
+ >>> x, y = symbols('x, y')
31
+ >>> p1 = plot(x, x**2, x**3, (x, -5, 5))
32
+ >>> p2 = plot((x**2, (x, -6, 6)), (x, (x, -5, 5)))
33
+ >>> p3 = plot(x**3, (x, -5, 5))
34
+ >>> p4 = plot3d(x*y, (x, -5, 5), (y, -5, 5))
35
+
36
+ Plotting vertically in a single line:
37
+
38
+ .. plot::
39
+ :context: close-figs
40
+ :format: doctest
41
+ :include-source: True
42
+
43
+ >>> PlotGrid(2, 1, p1, p2)
44
+ PlotGrid object containing:
45
+ Plot[0]:Plot object containing:
46
+ [0]: cartesian line: x for x over (-5.0, 5.0)
47
+ [1]: cartesian line: x**2 for x over (-5.0, 5.0)
48
+ [2]: cartesian line: x**3 for x over (-5.0, 5.0)
49
+ Plot[1]:Plot object containing:
50
+ [0]: cartesian line: x**2 for x over (-6.0, 6.0)
51
+ [1]: cartesian line: x for x over (-5.0, 5.0)
52
+
53
+ Plotting horizontally in a single line:
54
+
55
+ .. plot::
56
+ :context: close-figs
57
+ :format: doctest
58
+ :include-source: True
59
+
60
+ >>> PlotGrid(1, 3, p2, p3, p4)
61
+ PlotGrid object containing:
62
+ Plot[0]:Plot object containing:
63
+ [0]: cartesian line: x**2 for x over (-6.0, 6.0)
64
+ [1]: cartesian line: x for x over (-5.0, 5.0)
65
+ Plot[1]:Plot object containing:
66
+ [0]: cartesian line: x**3 for x over (-5.0, 5.0)
67
+ Plot[2]:Plot object containing:
68
+ [0]: cartesian surface: x*y for x over (-5.0, 5.0) and y over (-5.0, 5.0)
69
+
70
+ Plotting in a grid form:
71
+
72
+ .. plot::
73
+ :context: close-figs
74
+ :format: doctest
75
+ :include-source: True
76
+
77
+ >>> PlotGrid(2, 2, p1, p2, p3, p4)
78
+ PlotGrid object containing:
79
+ Plot[0]:Plot object containing:
80
+ [0]: cartesian line: x for x over (-5.0, 5.0)
81
+ [1]: cartesian line: x**2 for x over (-5.0, 5.0)
82
+ [2]: cartesian line: x**3 for x over (-5.0, 5.0)
83
+ Plot[1]:Plot object containing:
84
+ [0]: cartesian line: x**2 for x over (-6.0, 6.0)
85
+ [1]: cartesian line: x for x over (-5.0, 5.0)
86
+ Plot[2]:Plot object containing:
87
+ [0]: cartesian line: x**3 for x over (-5.0, 5.0)
88
+ Plot[3]:Plot object containing:
89
+ [0]: cartesian surface: x*y for x over (-5.0, 5.0) and y over (-5.0, 5.0)
90
+
91
+ """
92
+ def __init__(self, nrows, ncolumns, *args, show=True, size=None, **kwargs):
93
+ """
94
+ Parameters
95
+ ==========
96
+
97
+ nrows :
98
+ The number of rows that should be in the grid of the
99
+ required subplot.
100
+ ncolumns :
101
+ The number of columns that should be in the grid
102
+ of the required subplot.
103
+
104
+ nrows and ncolumns together define the required grid.
105
+
106
+ Arguments
107
+ =========
108
+
109
+ A list of predefined plot objects entered in a row-wise sequence
110
+ i.e. plot objects which are to be in the top row of the required
111
+ grid are written first, then the second row objects and so on
112
+
113
+ Keyword arguments
114
+ =================
115
+
116
+ show : Boolean
117
+ The default value is set to ``True``. Set show to ``False`` and
118
+ the function will not display the subplot. The returned instance
119
+ of the ``PlotGrid`` class can then be used to save or display the
120
+ plot by calling the ``save()`` and ``show()`` methods
121
+ respectively.
122
+ size : (float, float), optional
123
+ A tuple in the form (width, height) in inches to specify the size of
124
+ the overall figure. The default value is set to ``None``, meaning
125
+ the size will be set by the default backend.
126
+ """
127
+ self.matplotlib = import_module('matplotlib',
128
+ import_kwargs={'fromlist': ['pyplot', 'cm', 'collections']},
129
+ min_module_version='1.1.0', catch=(RuntimeError,))
130
+ self.nrows = nrows
131
+ self.ncolumns = ncolumns
132
+ self._series = []
133
+ self._fig = None
134
+ self.args = args
135
+ for arg in args:
136
+ self._series.append(arg._series)
137
+ self.size = size
138
+ if show and self.matplotlib:
139
+ self.show()
140
+
141
+ def _create_figure(self):
142
+ gs = self.matplotlib.gridspec.GridSpec(self.nrows, self.ncolumns)
143
+ mapping = {}
144
+ c = 0
145
+ for i in range(self.nrows):
146
+ for j in range(self.ncolumns):
147
+ if c < len(self.args):
148
+ mapping[gs[i, j]] = self.args[c]
149
+ c += 1
150
+
151
+ kw = {} if not self.size else {"figsize": self.size}
152
+ self._fig = self.matplotlib.pyplot.figure(**kw)
153
+ for spec, p in mapping.items():
154
+ kw = ({"projection": "3d"} if (len(p._series) > 0 and
155
+ p._series[0].is_3D) else {})
156
+ cur_ax = self._fig.add_subplot(spec, **kw)
157
+ p._plotgrid_fig = self._fig
158
+ p._plotgrid_ax = cur_ax
159
+ p.process_series()
160
+
161
+ @property
162
+ def fig(self):
163
+ if not self._fig:
164
+ self._create_figure()
165
+ return self._fig
166
+
167
+ @property
168
+ def _backend(self):
169
+ return self
170
+
171
+ def close(self):
172
+ self.matplotlib.pyplot.close(self.fig)
173
+
174
+ def show(self):
175
+ if base_backend._show:
176
+ self.fig.tight_layout()
177
+ self.matplotlib.pyplot.show()
178
+ else:
179
+ self.close()
180
+
181
+ def save(self, path):
182
+ self.fig.savefig(path)
183
+
184
+ def __str__(self):
185
+ plot_strs = [('Plot[%d]:' % i) + str(plot)
186
+ for i, plot in enumerate(self.args)]
187
+
188
+ return 'PlotGrid object containing:\n' + '\n'.join(plot_strs)