passagemath-plot 10.6.31rc3__cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of passagemath-plot might be problematic. Click here for more details.

Files changed (81) hide show
  1. passagemath_plot-10.6.31rc3.dist-info/METADATA +172 -0
  2. passagemath_plot-10.6.31rc3.dist-info/RECORD +81 -0
  3. passagemath_plot-10.6.31rc3.dist-info/WHEEL +6 -0
  4. passagemath_plot-10.6.31rc3.dist-info/top_level.txt +2 -0
  5. passagemath_plot.libs/libgfortran-e1b7dfc8.so.5.0.0 +0 -0
  6. passagemath_plot.libs/libgsl-e3525837.so.28.0.0 +0 -0
  7. passagemath_plot.libs/libopenblasp-r0-4c5b64b1.3.29.so +0 -0
  8. sage/all__sagemath_plot.py +15 -0
  9. sage/ext_data/threejs/animation.css +195 -0
  10. sage/ext_data/threejs/animation.html +85 -0
  11. sage/ext_data/threejs/animation.js +273 -0
  12. sage/ext_data/threejs/fat_lines.js +48 -0
  13. sage/ext_data/threejs/threejs-version.txt +1 -0
  14. sage/ext_data/threejs/threejs_template.html +597 -0
  15. sage/interfaces/all__sagemath_plot.py +1 -0
  16. sage/interfaces/gnuplot.py +196 -0
  17. sage/interfaces/jmoldata.py +208 -0
  18. sage/interfaces/povray.py +56 -0
  19. sage/plot/all.py +42 -0
  20. sage/plot/animate.py +1796 -0
  21. sage/plot/arc.py +504 -0
  22. sage/plot/arrow.py +671 -0
  23. sage/plot/bar_chart.py +205 -0
  24. sage/plot/bezier_path.py +400 -0
  25. sage/plot/circle.py +435 -0
  26. sage/plot/colors.py +1606 -0
  27. sage/plot/complex_plot.cpython-314-aarch64-linux-gnu.so +0 -0
  28. sage/plot/complex_plot.pyx +1446 -0
  29. sage/plot/contour_plot.py +1792 -0
  30. sage/plot/density_plot.py +318 -0
  31. sage/plot/disk.py +373 -0
  32. sage/plot/ellipse.py +375 -0
  33. sage/plot/graphics.py +3580 -0
  34. sage/plot/histogram.py +354 -0
  35. sage/plot/hyperbolic_arc.py +404 -0
  36. sage/plot/hyperbolic_polygon.py +416 -0
  37. sage/plot/hyperbolic_regular_polygon.py +296 -0
  38. sage/plot/line.py +626 -0
  39. sage/plot/matrix_plot.py +629 -0
  40. sage/plot/misc.py +509 -0
  41. sage/plot/multigraphics.py +1294 -0
  42. sage/plot/plot.py +4183 -0
  43. sage/plot/plot3d/all.py +23 -0
  44. sage/plot/plot3d/base.cpython-314-aarch64-linux-gnu.so +0 -0
  45. sage/plot/plot3d/base.pxd +12 -0
  46. sage/plot/plot3d/base.pyx +3378 -0
  47. sage/plot/plot3d/implicit_plot3d.py +659 -0
  48. sage/plot/plot3d/implicit_surface.cpython-314-aarch64-linux-gnu.so +0 -0
  49. sage/plot/plot3d/implicit_surface.pyx +1453 -0
  50. sage/plot/plot3d/index_face_set.cpython-314-aarch64-linux-gnu.so +0 -0
  51. sage/plot/plot3d/index_face_set.pxd +32 -0
  52. sage/plot/plot3d/index_face_set.pyx +1873 -0
  53. sage/plot/plot3d/introduction.py +131 -0
  54. sage/plot/plot3d/list_plot3d.py +649 -0
  55. sage/plot/plot3d/parametric_plot3d.py +1130 -0
  56. sage/plot/plot3d/parametric_surface.cpython-314-aarch64-linux-gnu.so +0 -0
  57. sage/plot/plot3d/parametric_surface.pxd +12 -0
  58. sage/plot/plot3d/parametric_surface.pyx +893 -0
  59. sage/plot/plot3d/platonic.py +601 -0
  60. sage/plot/plot3d/plot3d.py +1442 -0
  61. sage/plot/plot3d/plot_field3d.py +162 -0
  62. sage/plot/plot3d/point_c.pxi +148 -0
  63. sage/plot/plot3d/revolution_plot3d.py +309 -0
  64. sage/plot/plot3d/shapes.cpython-314-aarch64-linux-gnu.so +0 -0
  65. sage/plot/plot3d/shapes.pxd +22 -0
  66. sage/plot/plot3d/shapes.pyx +1382 -0
  67. sage/plot/plot3d/shapes2.py +1512 -0
  68. sage/plot/plot3d/tachyon.py +1779 -0
  69. sage/plot/plot3d/texture.py +453 -0
  70. sage/plot/plot3d/transform.cpython-314-aarch64-linux-gnu.so +0 -0
  71. sage/plot/plot3d/transform.pxd +21 -0
  72. sage/plot/plot3d/transform.pyx +268 -0
  73. sage/plot/plot3d/tri_plot.py +589 -0
  74. sage/plot/plot_field.py +362 -0
  75. sage/plot/point.py +624 -0
  76. sage/plot/polygon.py +562 -0
  77. sage/plot/primitive.py +249 -0
  78. sage/plot/scatter_plot.py +199 -0
  79. sage/plot/step.py +85 -0
  80. sage/plot/streamline_plot.py +328 -0
  81. sage/plot/text.py +432 -0
sage/plot/misc.py ADDED
@@ -0,0 +1,509 @@
1
+ # sage_setup: distribution = sagemath-plot
2
+ # sage.doctest: needs sage.symbolic
3
+ """
4
+ Plotting utilities
5
+ """
6
+
7
+ # ****************************************************************************
8
+ # Distributed under the terms of the GNU General Public License (GPL)
9
+ #
10
+ # This code is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ # General Public License for more details.
14
+ #
15
+ # The full text of the GPL is available at:
16
+ #
17
+ # https://www.gnu.org/licenses/
18
+ # ****************************************************************************
19
+ from sage.ext.fast_callable import FastCallableFloatWrapper
20
+ from collections.abc import Iterable
21
+
22
+
23
+ def setup_for_eval_on_grid(funcs,
24
+ ranges,
25
+ plot_points=None,
26
+ return_vars=False,
27
+ imaginary_tolerance=1e-8):
28
+ r"""
29
+ Calculate the necessary parameters to construct a list of points,
30
+ and make the functions fast_callable.
31
+
32
+ INPUT:
33
+
34
+ - ``funcs`` -- a function, or a list, tuple, or vector of functions
35
+
36
+ - ``ranges`` -- list of ranges. A range can be a 2-tuple of
37
+ numbers specifying the minimum and maximum, or a 3-tuple giving
38
+ the variable explicitly.
39
+
40
+ - ``plot_points`` -- tuple of integers specifying the number of
41
+ plot points for each range. If a single number is specified, it
42
+ will be the value for all ranges. This defaults to 2.
43
+
44
+ - ``return_vars`` -- (default: ``False``) if ``True``, return the variables,
45
+ in order
46
+
47
+ - ``imaginary_tolerance`` -- (default: ``1e-8``) if an imaginary
48
+ number arises (due, for example, to numerical issues), this
49
+ tolerance specifies how large it has to be in magnitude before
50
+ we raise an error. In other words, imaginary parts smaller than
51
+ this are ignored in your plot points.
52
+
53
+ OUTPUT:
54
+
55
+ - ``fast_funcs`` -- if only one function passed, then a fast
56
+ callable function. If funcs is a list or tuple, then a tuple
57
+ of fast callable functions is returned.
58
+
59
+ - ``range_specs`` -- list of range_specs: for each range, a
60
+ tuple is returned of the form (range_min, range_max,
61
+ range_step) such that ``srange(range_min, range_max,
62
+ range_step, include_endpoint=True)`` gives the correct points
63
+ for evaluation.
64
+
65
+ EXAMPLES::
66
+
67
+ sage: x,y,z = var('x,y,z')
68
+ sage: f(x,y) = x+y-z
69
+ sage: g(x,y) = x+y
70
+ sage: h(y) = -y
71
+ sage: sage.plot.misc.setup_for_eval_on_grid(f, [(0, 2),(1,3),(-4,1)], plot_points=5)
72
+ (<sage...>, [(0.0, 2.0, 0.5), (1.0, 3.0, 0.5), (-4.0, 1.0, 1.25)])
73
+ sage: sage.plot.misc.setup_for_eval_on_grid([g,h], [(0, 2),(-1,1)], plot_points=5)
74
+ ((<sage...>, <sage...>), [(0.0, 2.0, 0.5), (-1.0, 1.0, 0.5)])
75
+ sage: sage.plot.misc.setup_for_eval_on_grid([sin,cos], [(-1,1)], plot_points=9)
76
+ ((<sage...>, <sage...>), [(-1.0, 1.0, 0.25)])
77
+ sage: sage.plot.misc.setup_for_eval_on_grid([lambda x: x^2,cos], [(-1,1)], plot_points=9)
78
+ ((<function <lambda> ...>, <sage...>), [(-1.0, 1.0, 0.25)])
79
+ sage: sage.plot.misc.setup_for_eval_on_grid([x+y], [(x,-1,1),(y,-2,2)])
80
+ ((<sage...>,), [(-1.0, 1.0, 2.0), (-2.0, 2.0, 4.0)])
81
+ sage: sage.plot.misc.setup_for_eval_on_grid(x+y, [(x,-1,1),(y,-1,1)], plot_points=[4,9])
82
+ (<sage...>, [(-1.0, 1.0, 0.6666666666666666), (-1.0, 1.0, 0.25)])
83
+ sage: sage.plot.misc.setup_for_eval_on_grid(x+y, [(x,-1,1),(y,-1,1)], plot_points=[4,9,10])
84
+ Traceback (most recent call last):
85
+ ...
86
+ ValueError: plot_points must be either an integer or a list of integers, one for each range
87
+ sage: sage.plot.misc.setup_for_eval_on_grid(x+y, [(1,-1),(y,-1,1)], plot_points=[4,9,10])
88
+ Traceback (most recent call last):
89
+ ...
90
+ ValueError: Some variable ranges specify variables while others do not
91
+
92
+ Beware typos: a comma which should be a period, for instance::
93
+
94
+ sage: sage.plot.misc.setup_for_eval_on_grid(x+y, [(x, 1, 2), (y, 0,1, 0.2)], plot_points=[4,9,10])
95
+ Traceback (most recent call last):
96
+ ...
97
+ ValueError: At least one variable range has more than 3 entries: each should either have 2 or 3 entries, with one of the forms (xmin, xmax) or (x, xmin, xmax)
98
+
99
+ sage: sage.plot.misc.setup_for_eval_on_grid(x+y, [(y,1,-1),(x,-1,1)], plot_points=5)
100
+ (<sage...>, [(-1.0, 1.0, 0.5), (-1.0, 1.0, 0.5)])
101
+ sage: sage.plot.misc.setup_for_eval_on_grid(x+y, [(x,1,-1),(x,-1,1)], plot_points=5)
102
+ Traceback (most recent call last):
103
+ ...
104
+ ValueError: range variables should be distinct, but there are duplicates
105
+ sage: sage.plot.misc.setup_for_eval_on_grid(x+y, [(x,1,1),(y,-1,1)])
106
+ Traceback (most recent call last):
107
+ ...
108
+ ValueError: plot start point and end point must be different
109
+ sage: sage.plot.misc.setup_for_eval_on_grid(x+y, [(x,1,-1),(y,-1,1)], return_vars=True)
110
+ (<sage...>, [(-1.0, 1.0, 2.0), (-1.0, 1.0, 2.0)], [x, y])
111
+ sage: sage.plot.misc.setup_for_eval_on_grid(x+y, [(y,1,-1),(x,-1,1)], return_vars=True)
112
+ (<sage...>, [(-1.0, 1.0, 2.0), (-1.0, 1.0, 2.0)], [y, x])
113
+
114
+ TESTS:
115
+
116
+ Ensure that we can plot expressions with intermediate complex
117
+ terms as in :issue:`8450`::
118
+
119
+ sage: x, y = SR.var('x y')
120
+ sage: contour_plot(abs(x+i*y), (x,-1,1), (y,-1,1))
121
+ Graphics object consisting of 1 graphics primitive
122
+ sage: density_plot(abs(x+i*y), (x,-1,1), (y,-1,1))
123
+ Graphics object consisting of 1 graphics primitive
124
+ sage: plot3d(abs(x+i*y), (x,-1,1),(y,-1,1))
125
+ Graphics3d Object
126
+ sage: streamline_plot(abs(x+i*y), (x,-1,1),(y,-1,1))
127
+ Graphics object consisting of 1 graphics primitive
128
+ """
129
+ if max(map(len, ranges)) > 3:
130
+ raise ValueError("At least one variable range has more than 3 entries: each should either have 2 or 3 entries, with one of the forms (xmin, xmax) or (x, xmin, xmax)")
131
+ if max(map(len, ranges)) != min(map(len, ranges)):
132
+ raise ValueError("Some variable ranges specify variables while others do not")
133
+
134
+ if len(ranges[0]) == 3:
135
+ vars = [r[0] for r in ranges]
136
+ ranges = [r[1:] for r in ranges]
137
+ if len(set(vars)) < len(vars):
138
+ raise ValueError("range variables should be distinct, but there are duplicates")
139
+ else:
140
+ vars, free_vars = unify_arguments(funcs)
141
+
142
+ # check for invalid range (xmin > xmax or ymin > ymax) and swap
143
+ if len(ranges) > 1:
144
+ for i in range(len(ranges)):
145
+ if ranges[i][-2] > ranges[i][-1]:
146
+ ranges[i] = list(ranges[i])
147
+ ranges[i][-1], ranges[i][-2] = ranges[i][-2], ranges[i][-1]
148
+ ranges[i] = tuple(ranges[i])
149
+
150
+ # pad the variables if we don't have enough
151
+ nargs = len(ranges)
152
+ if len(vars) < nargs:
153
+ vars += ('_',) * (nargs - len(vars))
154
+
155
+ ranges = [[float(z) for z in r] for r in ranges]
156
+
157
+ if plot_points is None:
158
+ plot_points = 2
159
+
160
+ if not isinstance(plot_points, (list, tuple)):
161
+ plot_points = [plot_points] * len(ranges)
162
+ elif len(plot_points) != nargs:
163
+ raise ValueError("plot_points must be either an integer or a list of integers, one for each range")
164
+
165
+ plot_points = [int(p) if p >= 2 else 2 for p in plot_points]
166
+ range_steps = [abs(range[1] - range[0]) / (p - 1)
167
+ for range, p in zip(ranges, plot_points)]
168
+ if min(range_steps) == float(0):
169
+ raise ValueError("plot start point and end point must be different")
170
+
171
+ eov = False # eov = "expect one value"
172
+ if nargs == 1:
173
+ eov = True
174
+
175
+ from sage.ext.fast_callable import fast_callable
176
+
177
+ def try_make_fast(f):
178
+ # If "f" supports fast_callable(), use it. We can't guarantee
179
+ # that our arguments will actually support fast_callable()
180
+ # because, for example, the user may already have done it
181
+ # himself, and the result of fast_callable() can't be
182
+ # fast-callabled again.
183
+ from sage.rings.complex_double import CDF
184
+ from sage.ext.interpreters.wrapper_cdf import Wrapper_cdf
185
+
186
+ if hasattr(f, '_fast_callable_'):
187
+ ff = fast_callable(f, vars=vars, expect_one_var=eov, domain=CDF)
188
+ return FastCallablePlotWrapper(ff, imag_tol=imaginary_tolerance)
189
+ elif isinstance(f, Wrapper_cdf):
190
+ # Already a fast-callable, just wrap it. This can happen
191
+ # if, for example, a symbolic expression is passed to a
192
+ # higher-level plot() function that converts it to a
193
+ # fast-callable with expr._plot_fast_callable() before
194
+ # we ever see it.
195
+ return FastCallablePlotWrapper(f, imag_tol=imaginary_tolerance)
196
+ elif callable(f):
197
+ # This will catch python functions, among other things. We don't
198
+ # wrap these yet because we don't know what type they'll return.
199
+ return f
200
+ else:
201
+ # Convert things like ZZ(0) into constant functions.
202
+ from sage.symbolic.ring import SR
203
+ ff = fast_callable(SR(f),
204
+ vars=vars,
205
+ expect_one_var=eov,
206
+ domain=CDF)
207
+ return FastCallablePlotWrapper(ff, imag_tol=imaginary_tolerance)
208
+
209
+ # Handle vectors, lists, tuples, etc.
210
+ if isinstance(funcs, Iterable):
211
+ funcs = tuple(try_make_fast(f) for f in funcs)
212
+ else:
213
+ funcs = try_make_fast(funcs)
214
+
215
+ # TODO: raise an error if there is a function/method in funcs that
216
+ # takes more values than we have ranges
217
+
218
+ if return_vars:
219
+ return (funcs,
220
+ [tuple(_range + [range_step])
221
+ for _range, range_step in zip(ranges, range_steps)],
222
+ vars)
223
+ else:
224
+ return (funcs,
225
+ [tuple(_range + [range_step])
226
+ for _range, range_step in zip(ranges, range_steps)])
227
+
228
+
229
+ def unify_arguments(funcs):
230
+ """
231
+ Return a tuple of variables of the functions, as well as the
232
+ number of "free" variables (i.e., variables that defined in a
233
+ callable function).
234
+
235
+ INPUT:
236
+
237
+ - ``funcs`` -- list of functions; these can be symbolic
238
+ expressions, polynomials, etc.
239
+
240
+ OUTPUT: functions, expected arguments
241
+
242
+ - A tuple of variables in the functions
243
+
244
+ - A tuple of variables that were "free" in the functions
245
+
246
+ EXAMPLES::
247
+
248
+ sage: x,y,z = var('x,y,z')
249
+ sage: f(x,y) = x+y-z
250
+ sage: g(x,y) = x+y
251
+ sage: h(y) = -y
252
+ sage: sage.plot.misc.unify_arguments((f,g,h))
253
+ ((x, y, z), (z,))
254
+ sage: sage.plot.misc.unify_arguments((g,h))
255
+ ((x, y), ())
256
+ sage: sage.plot.misc.unify_arguments((f,z))
257
+ ((x, y, z), (z,))
258
+ sage: sage.plot.misc.unify_arguments((h,z))
259
+ ((y, z), (z,))
260
+ sage: sage.plot.misc.unify_arguments((x+y,x-y))
261
+ ((x, y), (x, y))
262
+ """
263
+ vars = set()
264
+ free_variables = set()
265
+ if not isinstance(funcs, (list, tuple)):
266
+ funcs = [funcs]
267
+
268
+ from sage.structure.element import Expression
269
+ for f in funcs:
270
+ if isinstance(f, Expression) and f.is_callable():
271
+ f_args = set(f.arguments())
272
+ vars.update(f_args)
273
+ else:
274
+ f_args = set()
275
+
276
+ try:
277
+ free_vars = set(f.variables()).difference(f_args)
278
+ vars.update(free_vars)
279
+ free_variables.update(free_vars)
280
+ except AttributeError:
281
+ # we probably have a constant
282
+ pass
283
+ return tuple(sorted(vars, key=str)), tuple(sorted(free_variables, key=str))
284
+
285
+
286
+ def _multiple_of_constant(n, pos, const):
287
+ r"""
288
+ Function for internal use in formatting ticks on axes with
289
+ nice-looking multiples of various symbolic constants, such
290
+ as `\pi` or `e`.
291
+
292
+ This should only be used via keyword argument
293
+ ``tick_formatter`` in :meth:`plot.show`. See documentation
294
+ for the matplotlib.ticker module for more details.
295
+
296
+ EXAMPLES:
297
+
298
+ Here is the intended use::
299
+
300
+ sage: plot(sin(x), (x,0,2*pi), ticks=pi/3, tick_formatter=pi)
301
+ Graphics object consisting of 1 graphics primitive
302
+
303
+ Here is an unintended use, which yields unexpected (and probably
304
+ undesired) results::
305
+
306
+ sage: plot(x^2, (x, -2, 2), tick_formatter=pi)
307
+ Graphics object consisting of 1 graphics primitive
308
+
309
+ We can also use more unusual constant choices::
310
+
311
+ sage: plot(ln(x), (x,0,10), ticks=e, tick_formatter=e)
312
+ Graphics object consisting of 1 graphics primitive
313
+ sage: plot(x^2, (x,0,10), ticks=[sqrt(2),8], tick_formatter=sqrt(2))
314
+ Graphics object consisting of 1 graphics primitive
315
+ """
316
+ from sage.misc.latex import latex
317
+ from sage.rings.continued_fraction import continued_fraction
318
+ from sage.rings.infinity import Infinity
319
+ cf = continued_fraction(n / const)
320
+ k = 1
321
+ while cf.quotient(k) != Infinity and cf.denominator(k) < 12:
322
+ k += 1
323
+ return '$%s$' % latex(cf.convergent(k - 1) * const)
324
+
325
+
326
+ def get_matplotlib_linestyle(linestyle, return_type):
327
+ """
328
+ Function which translates between matplotlib linestyle in short notation
329
+ (i.e. '-', '--', ':', '-.') and long notation (i.e. 'solid', 'dashed',
330
+ 'dotted', 'dashdot' ).
331
+
332
+ If linestyle is none of these allowed options, the function raises
333
+ a :exc:`ValueError`.
334
+
335
+ INPUT:
336
+
337
+ - ``linestyle`` -- the style of the line, which is one of
338
+ - ``'-'`` or ``'solid'``
339
+ - ``'--'`` or ``'dashed'``
340
+ - ``'-.'`` or ``'dash dot'``
341
+ - ``':'`` or ``'dotted'``
342
+ - ``"None"`` or ``" "`` or ``""`` (nothing)
343
+
344
+ The linestyle can also be prefixed with a drawing style (e.g., ``'steps--'``)
345
+
346
+ - ``'default'`` (connect the points with straight lines)
347
+ - ``'steps'`` or ``'steps-pre'`` (step function; horizontal
348
+ line is to the left of point)
349
+ - ``'steps-mid'`` (step function; points are in the middle of
350
+ horizontal lines)
351
+ - ``'steps-post'`` (step function; horizontal line is to the
352
+ right of point)
353
+
354
+ If ``linestyle`` is ``None`` (of type NoneType), then we return it
355
+ back unmodified.
356
+
357
+ - ``return_type`` -- the type of linestyle that should be output. This
358
+ argument takes only two values - ``'long'`` or ``'short'``
359
+
360
+ EXAMPLES:
361
+
362
+ Here is an example how to call this function::
363
+
364
+ sage: from sage.plot.misc import get_matplotlib_linestyle
365
+ sage: get_matplotlib_linestyle(':', return_type='short')
366
+ ':'
367
+
368
+ sage: get_matplotlib_linestyle(':', return_type='long')
369
+ 'dotted'
370
+
371
+ TESTS:
372
+
373
+ Make sure that if the input is already in the desired format, then it
374
+ is unchanged::
375
+
376
+ sage: get_matplotlib_linestyle(':', 'short')
377
+ ':'
378
+
379
+ Empty linestyles should be handled properly::
380
+
381
+ sage: get_matplotlib_linestyle("", 'short')
382
+ ''
383
+ sage: get_matplotlib_linestyle("", 'long')
384
+ 'None'
385
+ sage: get_matplotlib_linestyle(None, 'short') is None
386
+ True
387
+
388
+ Linestyles with ``'default'`` or ``'steps'`` in them should also be
389
+ properly handled. For instance, matplotlib understands only the short
390
+ version when ``'steps'`` is used::
391
+
392
+ sage: get_matplotlib_linestyle("default", "short")
393
+ ''
394
+ sage: get_matplotlib_linestyle("steps--", "short")
395
+ 'steps--'
396
+ sage: get_matplotlib_linestyle("steps-predashed", "long")
397
+ 'steps-pre--'
398
+
399
+ Finally, raise error on invalid linestyles::
400
+
401
+ sage: get_matplotlib_linestyle("isthissage", "long")
402
+ Traceback (most recent call last):
403
+ ...
404
+ ValueError: WARNING: Unrecognized linestyle 'isthissage'. Possible
405
+ linestyle options are:
406
+ {'solid', 'dashed', 'dotted', dashdot', 'None'}, respectively {'-',
407
+ '--', ':', '-.', ''}
408
+ """
409
+ long_to_short_dict = {'solid': '-',
410
+ 'dashed': '--',
411
+ 'dotted': ':',
412
+ 'dashdot': '-.'}
413
+ short_to_long_dict = {'-': 'solid',
414
+ '--': 'dashed',
415
+ ':': 'dotted',
416
+ '-.': 'dashdot'}
417
+
418
+ # We need this to take care of region plot. Essentially, if None is
419
+ # passed, then we just return back the same thing.
420
+ if linestyle is None:
421
+ return None
422
+
423
+ if linestyle.startswith("default"):
424
+ return get_matplotlib_linestyle(linestyle.strip("default"), "short")
425
+ elif linestyle.startswith("steps"):
426
+ if linestyle.startswith("steps-mid"):
427
+ return "steps-mid" + get_matplotlib_linestyle(
428
+ linestyle.strip("steps-mid"), "short")
429
+ elif linestyle.startswith("steps-post"):
430
+ return "steps-post" + get_matplotlib_linestyle(
431
+ linestyle.strip("steps-post"), "short")
432
+ elif linestyle.startswith("steps-pre"):
433
+ return "steps-pre" + get_matplotlib_linestyle(
434
+ linestyle.strip("steps-pre"), "short")
435
+ else:
436
+ return "steps" + get_matplotlib_linestyle(
437
+ linestyle.strip("steps"), "short")
438
+
439
+ if return_type == 'short':
440
+ if linestyle in short_to_long_dict.keys():
441
+ return linestyle
442
+ elif linestyle == "" or linestyle == " " or linestyle == "None":
443
+ return ''
444
+ elif linestyle in long_to_short_dict.keys():
445
+ return long_to_short_dict[linestyle]
446
+ else:
447
+ raise ValueError("WARNING: Unrecognized linestyle '%s'. "
448
+ "Possible linestyle options are:\n{'solid', "
449
+ "'dashed', 'dotted', dashdot', 'None'}, "
450
+ "respectively {'-', '--', ':', '-.', ''}" %
451
+ (linestyle))
452
+
453
+ elif return_type == 'long':
454
+ if linestyle in long_to_short_dict.keys():
455
+ return linestyle
456
+ elif linestyle == "" or linestyle == " " or linestyle == "None":
457
+ return "None"
458
+ elif linestyle in short_to_long_dict.keys():
459
+ return short_to_long_dict[linestyle]
460
+ else:
461
+ raise ValueError("WARNING: Unrecognized linestyle '%s'. "
462
+ "Possible linestyle options are:\n{'solid', "
463
+ "'dashed', 'dotted', dashdot', 'None'}, "
464
+ "respectively {'-', '--', ':', '-.', ''}" %
465
+ (linestyle))
466
+
467
+
468
+ class FastCallablePlotWrapper(FastCallableFloatWrapper):
469
+ r"""
470
+ A fast-callable wrapper for plotting that returns ``nan`` instead
471
+ of raising an error whenever the imaginary tolerance is exceeded.
472
+
473
+ A detailed rationale for this can be found in the superclass
474
+ documentation.
475
+
476
+ EXAMPLES:
477
+
478
+ The ``float`` incarnation of "not a number" is returned instead
479
+ of an error being thrown if the answer is complex::
480
+
481
+ sage: from sage.plot.misc import FastCallablePlotWrapper
482
+ sage: f = sqrt(x)
483
+ sage: ff = fast_callable(f, vars=[x], domain=CDF)
484
+ sage: fff = FastCallablePlotWrapper(ff, imag_tol=1e-8)
485
+ sage: fff(1)
486
+ 1.0
487
+ sage: fff(-1)
488
+ nan
489
+ """
490
+ def __call__(self, *args):
491
+ r"""
492
+ Evaluate the underlying fast-callable and convert the result to
493
+ ``float``.
494
+
495
+ TESTS:
496
+
497
+ Evaluation never fails and always returns a ``float``::
498
+
499
+ sage: from sage.plot.misc import FastCallablePlotWrapper
500
+ sage: f = x
501
+ sage: ff = fast_callable(f, vars=[x], domain=CDF)
502
+ sage: fff = FastCallablePlotWrapper(ff, imag_tol=0.1)
503
+ sage: type(fff(CDF.random_element())) is float
504
+ True
505
+ """
506
+ try:
507
+ return super().__call__(*args)
508
+ except ValueError:
509
+ return float("nan")