test_plot_implicit.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. from sympy.core.numbers import (I, pi)
  2. from sympy.core.relational import Eq
  3. from sympy.core.symbol import (Symbol, symbols)
  4. from sympy.functions.elementary.complexes import re
  5. from sympy.functions.elementary.exponential import exp
  6. from sympy.functions.elementary.trigonometric import (cos, sin, tan)
  7. from sympy.logic.boolalg import (And, Or)
  8. from sympy.plotting.plot_implicit import plot_implicit
  9. from sympy.plotting.plot import unset_show
  10. from tempfile import NamedTemporaryFile, mkdtemp
  11. from sympy.testing.pytest import skip, warns, XFAIL
  12. from sympy.external import import_module
  13. from sympy.testing.tmpfiles import TmpFileManager
  14. import os
  15. #Set plots not to show
  16. unset_show()
  17. def tmp_file(dir=None, name=''):
  18. return NamedTemporaryFile(
  19. suffix='.png', dir=dir, delete=False).name
  20. def plot_and_save(expr, *args, name='', dir=None, **kwargs):
  21. p = plot_implicit(expr, *args, **kwargs)
  22. p.save(tmp_file(dir=dir, name=name))
  23. # Close the plot to avoid a warning from matplotlib
  24. p._backend.close()
  25. def plot_implicit_tests(name):
  26. temp_dir = mkdtemp()
  27. TmpFileManager.tmp_folder(temp_dir)
  28. x = Symbol('x')
  29. y = Symbol('y')
  30. #implicit plot tests
  31. plot_and_save(Eq(y, cos(x)), (x, -5, 5), (y, -2, 2), name=name, dir=temp_dir)
  32. plot_and_save(Eq(y**2, x**3 - x), (x, -5, 5),
  33. (y, -4, 4), name=name, dir=temp_dir)
  34. plot_and_save(y > 1 / x, (x, -5, 5),
  35. (y, -2, 2), name=name, dir=temp_dir)
  36. plot_and_save(y < 1 / tan(x), (x, -5, 5),
  37. (y, -2, 2), name=name, dir=temp_dir)
  38. plot_and_save(y >= 2 * sin(x) * cos(x), (x, -5, 5),
  39. (y, -2, 2), name=name, dir=temp_dir)
  40. plot_and_save(y <= x**2, (x, -3, 3),
  41. (y, -1, 5), name=name, dir=temp_dir)
  42. #Test all input args for plot_implicit
  43. plot_and_save(Eq(y**2, x**3 - x), dir=temp_dir)
  44. plot_and_save(Eq(y**2, x**3 - x), adaptive=False, dir=temp_dir)
  45. plot_and_save(Eq(y**2, x**3 - x), adaptive=False, points=500, dir=temp_dir)
  46. plot_and_save(y > x, (x, -5, 5), dir=temp_dir)
  47. plot_and_save(And(y > exp(x), y > x + 2), dir=temp_dir)
  48. plot_and_save(Or(y > x, y > -x), dir=temp_dir)
  49. plot_and_save(x**2 - 1, (x, -5, 5), dir=temp_dir)
  50. plot_and_save(x**2 - 1, dir=temp_dir)
  51. plot_and_save(y > x, depth=-5, dir=temp_dir)
  52. plot_and_save(y > x, depth=5, dir=temp_dir)
  53. plot_and_save(y > cos(x), adaptive=False, dir=temp_dir)
  54. plot_and_save(y < cos(x), adaptive=False, dir=temp_dir)
  55. plot_and_save(And(y > cos(x), Or(y > x, Eq(y, x))), dir=temp_dir)
  56. plot_and_save(y - cos(pi / x), dir=temp_dir)
  57. plot_and_save(x**2 - 1, title='An implicit plot', dir=temp_dir)
  58. @XFAIL
  59. def test_no_adaptive_meshing():
  60. matplotlib = import_module('matplotlib', min_module_version='1.1.0', catch=(RuntimeError,))
  61. if matplotlib:
  62. try:
  63. temp_dir = mkdtemp()
  64. TmpFileManager.tmp_folder(temp_dir)
  65. x = Symbol('x')
  66. y = Symbol('y')
  67. # Test plots which cannot be rendered using the adaptive algorithm
  68. # This works, but it triggers a deprecation warning from sympify(). The
  69. # code needs to be updated to detect if interval math is supported without
  70. # relying on random AttributeErrors.
  71. with warns(UserWarning, match="Adaptive meshing could not be applied"):
  72. plot_and_save(Eq(y, re(cos(x) + I*sin(x))), name='test', dir=temp_dir)
  73. finally:
  74. TmpFileManager.cleanup()
  75. else:
  76. skip("Matplotlib not the default backend")
  77. def test_line_color():
  78. x, y = symbols('x, y')
  79. p = plot_implicit(x**2 + y**2 - 1, line_color="green", show=False)
  80. assert p._series[0].line_color == "green"
  81. p = plot_implicit(x**2 + y**2 - 1, line_color='r', show=False)
  82. assert p._series[0].line_color == "r"
  83. def test_matplotlib():
  84. matplotlib = import_module('matplotlib', min_module_version='1.1.0', catch=(RuntimeError,))
  85. if matplotlib:
  86. try:
  87. plot_implicit_tests('test')
  88. test_line_color()
  89. finally:
  90. TmpFileManager.cleanup()
  91. else:
  92. skip("Matplotlib not the default backend")
  93. def test_region_and():
  94. matplotlib = import_module('matplotlib', min_module_version='1.1.0', catch=(RuntimeError,))
  95. if not matplotlib:
  96. skip("Matplotlib not the default backend")
  97. from matplotlib.testing.compare import compare_images
  98. test_directory = os.path.dirname(os.path.abspath(__file__))
  99. try:
  100. temp_dir = mkdtemp()
  101. TmpFileManager.tmp_folder(temp_dir)
  102. x, y = symbols('x y')
  103. r1 = (x - 1)**2 + y**2 < 2
  104. r2 = (x + 1)**2 + y**2 < 2
  105. test_filename = tmp_file(dir=temp_dir, name="test_region_and")
  106. cmp_filename = os.path.join(test_directory, "test_region_and.png")
  107. p = plot_implicit(r1 & r2, x, y)
  108. p.save(test_filename)
  109. compare_images(cmp_filename, test_filename, 0.005)
  110. test_filename = tmp_file(dir=temp_dir, name="test_region_or")
  111. cmp_filename = os.path.join(test_directory, "test_region_or.png")
  112. p = plot_implicit(r1 | r2, x, y)
  113. p.save(test_filename)
  114. compare_images(cmp_filename, test_filename, 0.005)
  115. test_filename = tmp_file(dir=temp_dir, name="test_region_not")
  116. cmp_filename = os.path.join(test_directory, "test_region_not.png")
  117. p = plot_implicit(~r1, x, y)
  118. p.save(test_filename)
  119. compare_images(cmp_filename, test_filename, 0.005)
  120. test_filename = tmp_file(dir=temp_dir, name="test_region_xor")
  121. cmp_filename = os.path.join(test_directory, "test_region_xor.png")
  122. p = plot_implicit(r1 ^ r2, x, y)
  123. p.save(test_filename)
  124. compare_images(cmp_filename, test_filename, 0.005)
  125. finally:
  126. TmpFileManager.cleanup()