Coverage for src/chebpy/plotting.py: 100%

36 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-07-22 21:50 +0000

1"""Plotting utilities for visualizing functions and their properties. 

2 

3This module provides functions for plotting functions, their coefficients, and 

4other visualizations useful for understanding function approximations. It uses 

5matplotlib for the actual plotting, but is designed to gracefully handle cases 

6where matplotlib is not available. 

7 

8The main functions are: 

9- plotfun: Plot a function over a specified interval 

10- plotfuncoeffs: Plot the coefficients of a function on a semilogy scale 

11 

12These functions are typically used by higher-level classes like Chebfun and 

13Chebtech to provide plotting capabilities. 

14""" 

15 

16from typing import Any 

17 

18import matplotlib.pyplot as plt 

19import numpy as np 

20 

21from .settings import _preferences as prefs 

22 

23 

24def plotfun(fun: Any, support: tuple[float, float], ax: Any = None, n: int | None = None, **kwds: Any) -> Any: 

25 """Plot a function over a specified support interval. 

26 

27 This function plots a callable object over a specified interval using 

28 matplotlib. For complex-valued functions, it plots the real part against 

29 the imaginary part. 

30 

31 Args: 

32 fun (callable): The function to plot. Must be callable and have an 

33 'iscomplex' attribute. 

34 support (tuple): A tuple specifying the interval [a, b] over which to plot. 

35 ax (matplotlib.axes.Axes, optional): The axes on which to plot. If None, 

36 a new axes will be created. Defaults to None. 

37 n (int, optional): Number of points to use for plotting. If None, uses 

38 the value from preferences. Defaults to None. 

39 **kwds: Additional keyword arguments to pass to matplotlib's plot function. 

40 

41 Returns: 

42 matplotlib.axes.Axes: The axes on which the plot was created. 

43 """ 

44 ax = ax or plt.gca() 

45 n = n if n is not None else prefs.N_plot 

46 xx = np.linspace(*support, n) 

47 ff = fun(xx) 

48 if fun.iscomplex: 

49 ax.plot(np.real(ff), np.imag(ff), **kwds) 

50 ax.set_xlabel(kwds.pop("ylabel", "real")) 

51 ax.set_ylabel(kwds.pop("xlabel", "imag")) 

52 else: 

53 ax.plot(xx, ff, **kwds) 

54 return ax 

55 

56 

57def plotfuncoeffs(abscoeffs: np.ndarray, ax: Any = None, **kwds: Any) -> Any: 

58 """Plot the absolute values of function coefficients on a semilogy scale. 

59 

60 This function creates a semilogy plot of the absolute values of function 

61 coefficients, which is useful for visualizing the decay of coefficients 

62 in a Chebyshev series. 

63 

64 Args: 

65 abscoeffs (numpy.ndarray): Array of absolute coefficient values to plot. 

66 ax (matplotlib.axes.Axes, optional): The axes on which to plot. If None, 

67 a new axes will be created. Defaults to None. 

68 **kwds: Additional keyword arguments to pass to matplotlib's semilogy function. 

69 

70 Returns: 

71 matplotlib.axes.Axes: The axes on which the plot was created. 

72 """ 

73 ax = ax or plt.gca() 

74 ax.set_ylabel(kwds.pop("xlabel", "coefficient magnitude")) 

75 ax.set_xlabel(kwds.pop("ylabel", "polynomial degree")) 

76 ax.semilogy(abscoeffs, **kwds) 

77 return ax 

78 

79 

80def plot_chebfun(f: Any, ax: Any = None, **kwds: Any) -> Any: 

81 """Plot a Chebfun over its domain. 

82 

83 For Chebfuns with ``±inf`` endpoints (containing :class:`CompactFun` 

84 pieces), each unbounded endpoint is replaced with the corresponding 

85 ``plot_support`` endpoint of the outermost piece so the decay-to-zero 

86 region is visible. 

87 

88 Args: 

89 f: The Chebfun to plot. 

90 ax (matplotlib.axes.Axes, optional): The axes on which to plot. If None, 

91 a new axes will be created. Defaults to None. 

92 **kwds: Additional keyword arguments to pass to matplotlib's plot function. 

93 

94 Returns: 

95 matplotlib.axes.Axes: The axes on which the plot was created. 

96 """ 

97 a, b = float(f.support[0]), float(f.support[-1]) 

98 if not np.isfinite(a): 

99 left = f.funs[0] 

100 a = float(left.plot_support[0]) if hasattr(left, "plot_support") else a 

101 if not np.isfinite(b): 

102 right = f.funs[-1] 

103 b = float(right.plot_support[1]) if hasattr(right, "plot_support") else b 

104 support = kwds.pop("support", (a, b)) 

105 return plotfun(f, support, ax=ax, **kwds) 

106 

107 

108def plotcoeffs_chebfun(f: Any, ax: Any = None, **kwds: Any) -> Any: 

109 """Plot the per-piece coefficient magnitudes of a Chebfun on a semilogy scale. 

110 

111 Args: 

112 f: The Chebfun whose pieces' coefficients are plotted. 

113 ax (matplotlib.axes.Axes, optional): The axes on which to plot. If None, 

114 a new axes will be created. Defaults to None. 

115 **kwds: Additional keyword arguments to pass to matplotlib's semilogy function. 

116 

117 Returns: 

118 matplotlib.axes.Axes: The axes on which the plot was created. 

119 """ 

120 ax = ax or plt.gca() 

121 for fun in f: 

122 fun.plotcoeffs(ax=ax, **kwds) 

123 return ax