Skip to content

PhasePortrait2D

PhasePortrait2D

Makes a phase portrait of a 2D system.

Examples

from phaseportrait import PhasePortrait2D

def dF(r, θ, *, μ=0.5,η=0):
    return μ*r*(1 - r*r), 1+η*θ


example = PhasePortrait2D(dF, [-3, 3], Density=2, Polar=True, Title='Limit cycle')
example.add_slider('μ', valinit=0.5)
example.add_slider('η', valinit=0.0)
example.add_nullclines()
example.plot()

image

Defining Range

  1. A single number. In this case the range is defined from zero to the given number in both axes.

  2. A range, such [lowerLimit , upperLimit]. Both axes will take the same limits.

  3. Two ranges, such that [[xAxisLowerLimit , xAxisUpperLimit], [yAxisLowerLimit , yAxisUpperLimit]]

Methods

  • draw_plot: Draws the streamplot. Is internaly used by method plot.
  • add_function: Adds a function to the dF plot.
  • add_slider: Adds a Slider for the dF function.
  • plot: Prepares the plots and computes the values. Returns the axis and the figure.
Source code in phaseportrait/PhasePortrait2D.py
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
class PhasePortrait2D:
    """
    Makes a phase portrait of a 2D system.

    Examples
    -------
    ```py
    from phaseportrait import PhasePortrait2D

    def dF(r, θ, *, μ=0.5,η=0):
        return μ*r*(1 - r*r), 1+η*θ


    example = PhasePortrait2D(dF, [-3, 3], Density=2, Polar=True, Title='Limit cycle')
    example.add_slider('μ', valinit=0.5)
    example.add_slider('η', valinit=0.0)
    example.add_nullclines()
    example.plot()
    ``` 
    * [Click here to see more examples.](../legacy/phaseportrait2d_examples.md)

    ![image](../../imgs/doc_examples/pp2d_example.png)

    Defining Range
    -------

    1. A single number. In this case the range is defined from zero to the given number in both axes.

    2. A range, such `[lowerLimit , upperLimit]`.  Both axes will take the same limits.

    3. Two ranges, such that `[[xAxisLowerLimit , xAxisUpperLimit], [yAxisLowerLimit , yAxisUpperLimit]]`

    Methods
    -------    
    * draw_plot: Draws the streamplot. Is internaly used by method `plot`.
    * add_function:  Adds a function to the `dF` plot.
    * add_slider: Adds a `Slider` for the `dF` function.
    * plot: Prepares the plots and computes the values. Returns the axis and the figure.
    """
    _name_ = 'PhasePortrait2D'
    def __init__(self, dF, Range, *, MeshDim=30, dF_args={}, Density = 1, Polar = False, Title = 'Phase Portrait', xlabel = 'X', ylabel = "$\\dot{X}$", 
                 color='rainbow', xScale='linear', yScale='linear', maxLen=500, odeint_method="scipy", **kargs):
        """PhasePortrait2D

        Args:
            dF (callable): A dF type function.
            Range ([x_range, y_range]): Ranges of the axis in the main plot.
            MeshDim (int, optional): Number of elements in the arrows grid. Defaults to 30.
            dF_args (dict, optional): If necesary, must contain the kargs for the `dF` function. Defaults to {}.
            Density (int, optional): [Deprecated] Number of elements in the arrows grid plot. Defaults to 1.
            Polar (bool, optional): Whether to use polar coordinates or not. Defaults to False.
            Title (str, optional): title of the plot. Defaults to 'Phase Portrait'.
            xlabel (str, optional): x label of the plot. Defaults to 'X'.
            ylabel (regexp, optional): y label of the plot. Defaults to r"$\dot{X}$".
            color (str, optional): Matplotlib `Cmap`. Defaults to 'rainbow'.
            xScale (str, optional): x axis scale. Can be `linear`, `log`, `symlog`, `logit`. Defaults to 'linear'.
            yScale (str, optional): y axis scale. Can be `linear`, `log`, `symlog`, `logit`. Defaults to 'linear'.
            maxLen (int, optional): Max integrations per line of streamlines. Defaults to 500.
            odeint_method (str, optional): Selects integration method, by default uses scipy.odeint. `euler` and `rungekutta3` are also available. Defaults to "scipy".
        """        

        self.sliders = {}
        self.nullclines = []

        self.dF_args = dF_args.copy()                    # dF function's args
        self.dF = dF                                     # Function containing system's equations


        self.MeshDim  = MeshDim
        self.Density = Density                           # Controls concentration of nearby trajectories
        self.Polar = Polar                               # If dF expression given in polar coord. mark as True
        self.Title = Title                               # Title of the plot
        self.xlabel = xlabel                             # Title on X axis
        self.ylabel = ylabel                             # Title on Y axis

        self.xScale = xScale                             # x axis scale
        self.yScale = yScale                             # x axis scale 

        self.Range = Range                               # Range of graphical representation

        self.streamplot_callback = Streamlines_Velocity_Color_Gradient

        # Variables for plotting
        self.fig = kargs.get('fig', None)
        if self.fig:
            self.ax = self.fig.gca()
        else:
            self.fig, self.ax = plt.subplots()

        self.color = color
        self.grid = True

        self.streamplot_args = {"maxLen": maxLen, "odeint_method": odeint_method}

        self.manager = manager.Manager(self)


    def _create_arrays(self):
        # If scale is log and min range value is 0 or negative the plots is not correct
        _Range = self.Range.copy().astype(np.float64)
        for i, (scale, Range) in enumerate(zip([self.xScale, self.yScale], self.Range)):
            if scale == 'log':
                for j in range(len(Range)):
                    if Range[j]<=0:
                        _Range[i,j] = abs(max(Range))/100 if j==0 else abs(max(Range))
        self._Range = _Range

        for i, (_P, scale, Range) in enumerate(zip(["_X", "_Y"],[self.xScale, self.yScale], self.Range)):
            if scale == 'linear':
                setattr(self, _P, np.linspace(Range[0], Range[1], self.MeshDim))
            if scale == 'log':
                setattr(self, _P, np.logspace(np.log10(Range[0]), np.log10(Range[1]), self.MeshDim))
            if scale == 'symlog':
                setattr(self, _P, np.linspace(Range[0], Range[1], self.MeshDim))

        self._X, self._Y = np.meshgrid(self._X, self._Y)

        # self._X, self._Y = np.meshgrid(np.linspace(*self.Range[0,:], self.MeshDim), np.linspace(*self.Range[1,:], self.MeshDim))

        if self.Polar:   
            self._R, self._Theta = (self._X**2 + self._Y**2)**0.5, np.arctan2(self._Y, self._X)


    def plot(self, *, color=None, grid=None):
        """Prepares th plots and computes the values

        Args:
            color (str, optional): Matplotlib `Cmap`. Defaults to None.
            grid (bool, optional): Overrides general configuration of grid. Defaults to None.

        Returns:
            (Figure, Axes): returns the figure and axes in which the streamplot was drawn.
        """
        if color is not None:
            self.color = color
        if grid is not None:
            self.grid = grid

        self.stream = self.draw_plot(color=self.color, grid=grid)

        if hasattr(self, "colorbar_ax"):
            cb = plt.colorbar(mplcm.ScalarMappable(
                    norm=self.stream._velocity_normalization(), 
                    cmap=self.color),
                ax=self.ax,
                cax=self.colorbar_ax)

            self.colorbar_ax = cb.ax

        self.fig.canvas.draw_idle()

        return self.fig, self.ax 

    def colorbar(self, toggle=True):
        """Adds a colrobar for speed.

        Args:
            toggle (bool, optional): If `True` colorbar is visible. Defaults to True.
        """
        if (not hasattr(self, "colorbar_ax")) and toggle:
            self.colorbar_ax = None
        else:
            if hasattr(self, "colorbar_ax"):
                self.colorbar_ax.remove()
                del(self.colorbar_ax)

    def draw_plot(self, *, color=None, grid=None):
        """Draws the streamplot. Is internaly uesd by method `plot`.

        Args:
            color (str, optional): Matplotlib `Cmap`.. Defaults to None.
            grid (bool, optional): Overrides general configuration of grid. Defaults to None.

        Returns:
            (matplotlib.Streamplot): Streamplot drawn.
        """
        self.dF_args.update({name: slider.value for name, slider in self.sliders.items() if slider.value!= None})

        # Re-create arrays in case Range or scale is changed
        self._create_arrays()

        try:
            for nullcline in self.nullclines:
                nullcline.plot()
        except AttributeError:
            pass

        if color is not None:
            self.color = color


        stream = self.streamplot_callback(self.dF, self._X, self._Y, 
            dF_args=self.dF_args, polar=self.Polar, **self.streamplot_args)

        try:
            norm = stream._velocity_normalization()
        except AttributeError:
            norm = None
        cmap = plt.get_cmap(self.color)

        stream.plot(self.ax, cmap, norm, arrowsize=self.streamplot_args.get('arrow_width', 1))


        self.ax.set_xlim(self.Range[0,:])
        self.ax.set_ylim(self.Range[1,:])

        self.ax.set_title(f'{self.Title}')
        self.ax.set_xlabel(f'{self.xlabel}')
        self.ax.set_ylabel(f'{self.ylabel}')
        self.ax.set_xscale(self.xScale)
        self.ax.set_yscale(self.yScale)
        self.ax.grid(grid if grid is not None else self.grid)

        return stream



    def add_nullclines(self, *, precision=0.01, xprecision=None, yprecision=None, show: Literal['x', 'y', None]=None, offset=0., density=50, xRange=None, yRange=None, dF_args=None, xcolor='r', ycolor='g', bgcolor='w', alpha=0):
        """Adds nullclines for both axis.

        Args:
            precision (float, optional): Precision if not specific axis precision is specified. Defaults to 0.01.
            xprecision (float, optional): Precision for x axis nullcline. Defaults to None.
            yprecision (float, optional): Precision for y axis nullcline. Defaults to None.
            show (Literal['x', 'y', None], optinal) : Used to show only x or y nullclines, both if None. Defaults to None.
            offset (float, optional): Specifies the value in which the countours will be drawn. Defaults to 0.
            density (int, optional): Density of grid used in interpolation. Defaults to 50.
            xRange (list[float], optional): Range of x nullcline, by default global range. Defaults to None.
            yRange (list[float], optional): Range of y nullcline, by default global range. Defaults to None.
            dF_args (dict, optional): Overrides general `dFargs` if is not None. Defaults to None.
            xcolor (str, optional): Color for x nullcline. Defaults to 'r'.
            ycolor (str, optional): Color for y nullcline. Defaults to 'g'.
            bgcolor (str, optional): Color for background. Defaults to 'w'.
            alpha (int, optional): Alpha of nullclines and background. Defaults to 0.
        """        
        self.nullclines.append(Nullcline2D(self, self.dF,
                                          precision=precision, xprecision=xprecision, yprecision=yprecision, show=show, offset=offset, density=density, 
                                          xRange=xRange, yRange=yRange, dF_args=dF_args, 
                                          xcolor=xcolor, ycolor=ycolor, bgcolor=bgcolor, alpha=alpha, polar=self.Polar))



    def add_slider(self, param_name, *, valinit=None, valstep=0.1, valinterval=10):
        """
        Adds a slider which can change the value of a parameter in execution time.

        Args:
            param_name (str): It takes the name of the parameter on which the slider will be defined. Must be the same as the one appearing as karg in the `dF` function.
            valinit (float, optional): Initial value of *param_name* variable. Default value is 0.5.   
            valstep (flaot, optional): Slider step value. Default value is 0.1.
            valinterval : (float|list[float], optional): Slider range. Default value is [-10, 10].
        """

        self.sliders.update({param_name: sliders.Slider(self, param_name, valinit=valinit, valstep=valstep, valinterval=valinterval)})

        self.fig.subplots_adjust(bottom=0.25)

        self.sliders[param_name].slider.on_changed(self.sliders[param_name])

    def _PolarTransformation(self):
        """
        Computes the expression of the velocity field if coordinates are given in polar representation.
        """
        if not hasattr(self, "_dR") or not hasattr(self, "_dTheta"):
            self._R, self._Theta = (self._X**2 + self._Y**2)**0.5, np.arctan2(self._Y, self._X)

        self._dR, self._dTheta = self.dF(self._R, self._Theta, **self.dF_args)
        self._dX, self._dY = self._dR*np.cos(self._Theta) - self._R*np.sin(self._Theta)*self._dTheta, self._dR*np.sin(self._Theta)+self._R*np.cos(self._Theta)*self._dTheta



    @property
    def dF(self):
        return self._dF

    @dF.setter
    def dF(self, func):
        if not callable(func):
            raise exceptions.dFNotCallable(func)
        sig = signature(func)
        if len(sig.parameters)<2 + len(self.dF_args):
            raise exceptions.dFInvalid(sig, self.dF_args)

        # TODO: when a slider is created it should create and append an axis to the figure. For easier cleaning
        for s in self.sliders.copy():
            if s not in sig.parameters:
                raise exceptions.dF_argsInvalid(self.dF_args)

        self._dF = func

    @property
    def Range(self):
        return self._Range


    @Range.setter
    def Range(self, value):
        self._Range = np.array(utils.construct_interval(value, dim=2))
        self._create_arrays()

    @property
    def dF_args(self):
        return self._dF_args

    @dF_args.setter
    def dF_args(self, value):
        if value:
            if not isinstance(value, dict):
                raise exceptions.dF_argsInvalid(value)
        self._dF_args = value

__init__(dF, Range, *, MeshDim=30, dF_args={}, Density=1, Polar=False, Title='Phase Portrait', xlabel='X', ylabel='$\\dot{X}$', color='rainbow', xScale='linear', yScale='linear', maxLen=500, odeint_method='scipy', **kargs)

PhasePortrait2D

Parameters:

Name Type Description Default
dF callable

A dF type function.

required
Range [x_range, y_range]

Ranges of the axis in the main plot.

required
MeshDim int

Number of elements in the arrows grid. Defaults to 30.

30
dF_args dict

If necesary, must contain the kargs for the dF function. Defaults to {}.

{}
Density int

[Deprecated] Number of elements in the arrows grid plot. Defaults to 1.

1
Polar bool

Whether to use polar coordinates or not. Defaults to False.

False
Title str

title of the plot. Defaults to 'Phase Portrait'.

'Phase Portrait'
xlabel str

x label of the plot. Defaults to 'X'.

'X'
ylabel regexp

y label of the plot. Defaults to r"$\dot{X}$".

'$\\dot{X}$'
color str

Matplotlib Cmap. Defaults to 'rainbow'.

'rainbow'
xScale str

x axis scale. Can be linear, log, symlog, logit. Defaults to 'linear'.

'linear'
yScale str

y axis scale. Can be linear, log, symlog, logit. Defaults to 'linear'.

'linear'
maxLen int

Max integrations per line of streamlines. Defaults to 500.

500
odeint_method str

Selects integration method, by default uses scipy.odeint. euler and rungekutta3 are also available. Defaults to "scipy".

'scipy'
Source code in phaseportrait/PhasePortrait2D.py
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
def __init__(self, dF, Range, *, MeshDim=30, dF_args={}, Density = 1, Polar = False, Title = 'Phase Portrait', xlabel = 'X', ylabel = "$\\dot{X}$", 
             color='rainbow', xScale='linear', yScale='linear', maxLen=500, odeint_method="scipy", **kargs):
    """PhasePortrait2D

    Args:
        dF (callable): A dF type function.
        Range ([x_range, y_range]): Ranges of the axis in the main plot.
        MeshDim (int, optional): Number of elements in the arrows grid. Defaults to 30.
        dF_args (dict, optional): If necesary, must contain the kargs for the `dF` function. Defaults to {}.
        Density (int, optional): [Deprecated] Number of elements in the arrows grid plot. Defaults to 1.
        Polar (bool, optional): Whether to use polar coordinates or not. Defaults to False.
        Title (str, optional): title of the plot. Defaults to 'Phase Portrait'.
        xlabel (str, optional): x label of the plot. Defaults to 'X'.
        ylabel (regexp, optional): y label of the plot. Defaults to r"$\dot{X}$".
        color (str, optional): Matplotlib `Cmap`. Defaults to 'rainbow'.
        xScale (str, optional): x axis scale. Can be `linear`, `log`, `symlog`, `logit`. Defaults to 'linear'.
        yScale (str, optional): y axis scale. Can be `linear`, `log`, `symlog`, `logit`. Defaults to 'linear'.
        maxLen (int, optional): Max integrations per line of streamlines. Defaults to 500.
        odeint_method (str, optional): Selects integration method, by default uses scipy.odeint. `euler` and `rungekutta3` are also available. Defaults to "scipy".
    """        

    self.sliders = {}
    self.nullclines = []

    self.dF_args = dF_args.copy()                    # dF function's args
    self.dF = dF                                     # Function containing system's equations


    self.MeshDim  = MeshDim
    self.Density = Density                           # Controls concentration of nearby trajectories
    self.Polar = Polar                               # If dF expression given in polar coord. mark as True
    self.Title = Title                               # Title of the plot
    self.xlabel = xlabel                             # Title on X axis
    self.ylabel = ylabel                             # Title on Y axis

    self.xScale = xScale                             # x axis scale
    self.yScale = yScale                             # x axis scale 

    self.Range = Range                               # Range of graphical representation

    self.streamplot_callback = Streamlines_Velocity_Color_Gradient

    # Variables for plotting
    self.fig = kargs.get('fig', None)
    if self.fig:
        self.ax = self.fig.gca()
    else:
        self.fig, self.ax = plt.subplots()

    self.color = color
    self.grid = True

    self.streamplot_args = {"maxLen": maxLen, "odeint_method": odeint_method}

    self.manager = manager.Manager(self)

add_nullclines(*, precision=0.01, xprecision=None, yprecision=None, show=None, offset=0.0, density=50, xRange=None, yRange=None, dF_args=None, xcolor='r', ycolor='g', bgcolor='w', alpha=0)

Adds nullclines for both axis.

Parameters:

Name Type Description Default
precision float

Precision if not specific axis precision is specified. Defaults to 0.01.

0.01
xprecision float

Precision for x axis nullcline. Defaults to None.

None
yprecision float

Precision for y axis nullcline. Defaults to None.

None
show Literal['x', 'y', None], optinal)

Used to show only x or y nullclines, both if None. Defaults to None.

None
offset float

Specifies the value in which the countours will be drawn. Defaults to 0.

0.0
density int

Density of grid used in interpolation. Defaults to 50.

50
xRange list[float]

Range of x nullcline, by default global range. Defaults to None.

None
yRange list[float]

Range of y nullcline, by default global range. Defaults to None.

None
dF_args dict

Overrides general dFargs if is not None. Defaults to None.

None
xcolor str

Color for x nullcline. Defaults to 'r'.

'r'
ycolor str

Color for y nullcline. Defaults to 'g'.

'g'
bgcolor str

Color for background. Defaults to 'w'.

'w'
alpha int

Alpha of nullclines and background. Defaults to 0.

0
Source code in phaseportrait/PhasePortrait2D.py
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
def add_nullclines(self, *, precision=0.01, xprecision=None, yprecision=None, show: Literal['x', 'y', None]=None, offset=0., density=50, xRange=None, yRange=None, dF_args=None, xcolor='r', ycolor='g', bgcolor='w', alpha=0):
    """Adds nullclines for both axis.

    Args:
        precision (float, optional): Precision if not specific axis precision is specified. Defaults to 0.01.
        xprecision (float, optional): Precision for x axis nullcline. Defaults to None.
        yprecision (float, optional): Precision for y axis nullcline. Defaults to None.
        show (Literal['x', 'y', None], optinal) : Used to show only x or y nullclines, both if None. Defaults to None.
        offset (float, optional): Specifies the value in which the countours will be drawn. Defaults to 0.
        density (int, optional): Density of grid used in interpolation. Defaults to 50.
        xRange (list[float], optional): Range of x nullcline, by default global range. Defaults to None.
        yRange (list[float], optional): Range of y nullcline, by default global range. Defaults to None.
        dF_args (dict, optional): Overrides general `dFargs` if is not None. Defaults to None.
        xcolor (str, optional): Color for x nullcline. Defaults to 'r'.
        ycolor (str, optional): Color for y nullcline. Defaults to 'g'.
        bgcolor (str, optional): Color for background. Defaults to 'w'.
        alpha (int, optional): Alpha of nullclines and background. Defaults to 0.
    """        
    self.nullclines.append(Nullcline2D(self, self.dF,
                                      precision=precision, xprecision=xprecision, yprecision=yprecision, show=show, offset=offset, density=density, 
                                      xRange=xRange, yRange=yRange, dF_args=dF_args, 
                                      xcolor=xcolor, ycolor=ycolor, bgcolor=bgcolor, alpha=alpha, polar=self.Polar))

add_slider(param_name, *, valinit=None, valstep=0.1, valinterval=10)

Adds a slider which can change the value of a parameter in execution time.

Parameters:

Name Type Description Default
param_name str

It takes the name of the parameter on which the slider will be defined. Must be the same as the one appearing as karg in the dF function.

required
valinit float

Initial value of param_name variable. Default value is 0.5.

None
valstep flaot

Slider step value. Default value is 0.1.

0.1
valinterval

(float|list[float], optional): Slider range. Default value is [-10, 10].

10
Source code in phaseportrait/PhasePortrait2D.py
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
def add_slider(self, param_name, *, valinit=None, valstep=0.1, valinterval=10):
    """
    Adds a slider which can change the value of a parameter in execution time.

    Args:
        param_name (str): It takes the name of the parameter on which the slider will be defined. Must be the same as the one appearing as karg in the `dF` function.
        valinit (float, optional): Initial value of *param_name* variable. Default value is 0.5.   
        valstep (flaot, optional): Slider step value. Default value is 0.1.
        valinterval : (float|list[float], optional): Slider range. Default value is [-10, 10].
    """

    self.sliders.update({param_name: sliders.Slider(self, param_name, valinit=valinit, valstep=valstep, valinterval=valinterval)})

    self.fig.subplots_adjust(bottom=0.25)

    self.sliders[param_name].slider.on_changed(self.sliders[param_name])

colorbar(toggle=True)

Adds a colrobar for speed.

Parameters:

Name Type Description Default
toggle bool

If True colorbar is visible. Defaults to True.

True
Source code in phaseportrait/PhasePortrait2D.py
169
170
171
172
173
174
175
176
177
178
179
180
def colorbar(self, toggle=True):
    """Adds a colrobar for speed.

    Args:
        toggle (bool, optional): If `True` colorbar is visible. Defaults to True.
    """
    if (not hasattr(self, "colorbar_ax")) and toggle:
        self.colorbar_ax = None
    else:
        if hasattr(self, "colorbar_ax"):
            self.colorbar_ax.remove()
            del(self.colorbar_ax)

draw_plot(*, color=None, grid=None)

Draws the streamplot. Is internaly uesd by method plot.

Parameters:

Name Type Description Default
color str

Matplotlib Cmap.. Defaults to None.

None
grid bool

Overrides general configuration of grid. Defaults to None.

None

Returns:

Type Description
matplotlib.Streamplot

Streamplot drawn.

Source code in phaseportrait/PhasePortrait2D.py
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
def draw_plot(self, *, color=None, grid=None):
    """Draws the streamplot. Is internaly uesd by method `plot`.

    Args:
        color (str, optional): Matplotlib `Cmap`.. Defaults to None.
        grid (bool, optional): Overrides general configuration of grid. Defaults to None.

    Returns:
        (matplotlib.Streamplot): Streamplot drawn.
    """
    self.dF_args.update({name: slider.value for name, slider in self.sliders.items() if slider.value!= None})

    # Re-create arrays in case Range or scale is changed
    self._create_arrays()

    try:
        for nullcline in self.nullclines:
            nullcline.plot()
    except AttributeError:
        pass

    if color is not None:
        self.color = color


    stream = self.streamplot_callback(self.dF, self._X, self._Y, 
        dF_args=self.dF_args, polar=self.Polar, **self.streamplot_args)

    try:
        norm = stream._velocity_normalization()
    except AttributeError:
        norm = None
    cmap = plt.get_cmap(self.color)

    stream.plot(self.ax, cmap, norm, arrowsize=self.streamplot_args.get('arrow_width', 1))


    self.ax.set_xlim(self.Range[0,:])
    self.ax.set_ylim(self.Range[1,:])

    self.ax.set_title(f'{self.Title}')
    self.ax.set_xlabel(f'{self.xlabel}')
    self.ax.set_ylabel(f'{self.ylabel}')
    self.ax.set_xscale(self.xScale)
    self.ax.set_yscale(self.yScale)
    self.ax.grid(grid if grid is not None else self.grid)

    return stream

plot(*, color=None, grid=None)

Prepares th plots and computes the values

Parameters:

Name Type Description Default
color str

Matplotlib Cmap. Defaults to None.

None
grid bool

Overrides general configuration of grid. Defaults to None.

None

Returns:

Type Description
Figure, Axes

returns the figure and axes in which the streamplot was drawn.

Source code in phaseportrait/PhasePortrait2D.py
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
def plot(self, *, color=None, grid=None):
    """Prepares th plots and computes the values

    Args:
        color (str, optional): Matplotlib `Cmap`. Defaults to None.
        grid (bool, optional): Overrides general configuration of grid. Defaults to None.

    Returns:
        (Figure, Axes): returns the figure and axes in which the streamplot was drawn.
    """
    if color is not None:
        self.color = color
    if grid is not None:
        self.grid = grid

    self.stream = self.draw_plot(color=self.color, grid=grid)

    if hasattr(self, "colorbar_ax"):
        cb = plt.colorbar(mplcm.ScalarMappable(
                norm=self.stream._velocity_normalization(), 
                cmap=self.color),
            ax=self.ax,
            cax=self.colorbar_ax)

        self.colorbar_ax = cb.ax

    self.fig.canvas.draw_idle()

    return self.fig, self.ax