Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitadcb486

Browse files
authored
Merge branch 'python-control:main' into system-norms
2 parents457c623 +a8a54d1 commitadcb486

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+1399
-805
lines changed

‎.github/conda-env/build-env.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
name:build-env
22
dependencies:
33
-boa
4-
-numpy !=1.23.0
4+
-numpy

‎.github/conda-env/doctest-env.yml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
1-
name:test-env
1+
name:doctest-env
22
dependencies:
3-
-conda-build# for conda index
43
-pip
5-
-coverage
6-
-coveralls
74
-pytest
8-
-pytest-cov
95
-pytest-timeout
106
-pytest-xvfb
117
-numpy

‎.github/conda-env/test-env.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
name:test-env
22
dependencies:
3-
-conda-build# for conda index
43
-pip
54
-coverage
6-
-coveralls
75
-pytest
86
-pytest-cov
97
-pytest-timeout

‎.github/workflows/control-slycot-src.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
-name:Set up Python
1515
uses:actions/setup-python@v4
1616
with:
17-
python-version:'3.11'
17+
python-version:'3.12'
1818
-name:Install Python dependencies and test tools
1919
run:pip install -v './python-control[test]'
2020

‎.github/workflows/doctest.yml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ jobs:
1515
-name:Setup Conda
1616
uses:conda-incubator/setup-miniconda@v2
1717
with:
18-
python-version:3.11
19-
activate-environment:test-env
18+
python-version:3.12
19+
activate-environment:doctest-env
2020
environment-file:.github/conda-env/doctest-env.yml
2121
miniforge-version:latest
2222
miniforge-variant:Mambaforge
@@ -32,8 +32,6 @@ jobs:
3232
3333
-name:Run doctest
3434
shell:bash -l {0}
35-
env:
36-
MPLBACKEND:${{ matrix.mplbackend }}
3735
working-directory:doc
3836
run:|
3937
make html

‎.github/workflows/install_examples.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
--channel conda-forge \
1919
--strict-channel-priority \
2020
--quiet --yes \
21-
python=3.11 pip \
21+
python=3.12 pip \
2222
numpy matplotlib scipy \
2323
slycot pmw jupyter
2424

‎.github/workflows/os-blas-test-matrix.yml

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,24 +21,24 @@ jobs:
2121
-'ubuntu'
2222
-'macos'
2323
python:
24-
-'3.8'
25-
-'3.11'
24+
-'3.10'
25+
-'3.12'
2626
bla_vendor:[ 'unset' ]
2727
include:
2828
-os:'ubuntu'
29-
python:'3.11'
29+
python:'3.12'
3030
bla_vendor:'Generic'
3131
-os:'ubuntu'
32-
python:'3.11'
32+
python:'3.12'
3333
bla_vendor:'OpenBLAS'
3434
-os:'macos'
35-
python:'3.11'
35+
python:'3.12'
3636
bla_vendor:'Apple'
3737
-os:'macos'
38-
python:'3.11'
38+
python:'3.12'
3939
bla_vendor:'Generic'
4040
-os:'macos'
41-
python:'3.11'
41+
python:'3.12'
4242
bla_vendor:'OpenBLAS'
4343

4444
steps:
@@ -108,7 +108,7 @@ jobs:
108108
-'macos'
109109
-'windows'
110110
python:
111-
-'3.9'
111+
# build on one, expand matrix in conda-build from the Sylcot/conda-recipe/conda_build_config.yaml
112112
-'3.11'
113113

114114
steps:
@@ -133,14 +133,14 @@ jobs:
133133
shell:bash -l {0}
134134
run:|
135135
set -e
136-
numpyversion=$(python -c 'import numpy; print(numpy.version.version)')
137-
conda mambabuild --python "${{ matrix.python }}" --numpy $numpyversion conda-recipe
136+
conda mambabuild conda-recipe
138137
# preserve directory structure for custom conda channel
139138
find "${CONDA_PREFIX}/conda-bld" -maxdepth 2 -name 'slycot*.tar.bz2' | while read -r conda_pkg; do
140139
conda_platform=$(basename $(dirname "${conda_pkg}"))
141140
mkdir -p "slycot-conda-pkgs/${conda_platform}"
142141
cp "${conda_pkg}" "slycot-conda-pkgs/${conda_platform}/"
143142
done
143+
conda index --no-progress ./slycot-conda-pkgs
144144
-name:Save to local conda pkg channel
145145
uses:actions/upload-artifact@v3
146146
with:
@@ -247,7 +247,7 @@ jobs:
247247
-name:Install Wheel
248248
run:|
249249
python -m pip install --upgrade pip
250-
pip install matplotlib scipy pytest pytest-cov pytest-timeout coverage coveralls
250+
pip install matplotlib scipy pytest pytest-cov pytest-timeout coverage
251251
pip install slycot-wheels/${{ matrix.packagekey }}/slycot*.whl
252252
pip show slycot
253253
-name:Test with pytest
@@ -316,7 +316,6 @@ jobs:
316316
echo "libblas * *mkl" >> $CONDA_PREFIX/conda-meta/pinned
317317
;;
318318
esac
319-
conda index --no-progress ./slycot-conda-pkgs
320319
mamba install -c ./slycot-conda-pkgs slycot
321320
conda list
322321
-name:Test with pytest

‎.github/workflows/python-package-conda.yml

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@ jobs:
1616
max-parallel:5
1717
fail-fast:false
1818
matrix:
19-
python-version:['3.8', '3.11']
19+
python-version:['3.10', '3.12']
2020
slycot:["", "conda"]
2121
pandas:[""]
2222
cvxopt:["", "conda"]
2323
mplbackend:[""]
2424
include:
25-
-python-version:'3.11'
25+
-python-version:'3.12'
2626
slycot:conda
2727
pandas:conda
2828
cvxopt:conda
@@ -61,20 +61,27 @@ jobs:
6161
shell:bash -l {0}
6262
env:
6363
MPLBACKEND:${{ matrix.mplbackend }}
64-
run:pytest -v --cov=control --cov-config=.coveragerc control/tests
64+
run:|
65+
pytest -v --cov=control --cov-config=.coveragerc control/tests
66+
coverage xml
6567
66-
-name:Coveralls parallel
67-
# https://github.com/coverallsapp/github-action
68-
uses:AndreMiras/coveralls-python-action@develop
68+
-name:report coverage
69+
uses:coverallsapp/github-action@v2
6970
with:
71+
flag-name:conda-pytest_py${{ matrix.python-version }}_${{ matrix.slycot || 'no' }}-Slycot_${{ matrix.pandas || 'no' }}-Pandas_${{ matrix.cvxopt || 'no' }}_CVXOPT-${{ matrix.mplbackend && format('; {0}', matrix.mplbackend) }}
7072
parallel:true
73+
file:coverage.xml
7174

72-
coveralls:
73-
name:coveralls completion
74-
needs:test-linux-conda
75+
coveralls-final:
76+
name:Finalize parallel coveralls
77+
if:always()
78+
needs:
79+
-test-linux-conda
7580
runs-on:ubuntu-latest
7681
steps:
7782
-name:Coveralls Finished
78-
uses:AndreMiras/coveralls-python-action@develop
83+
uses:coverallsapp/github-action@v2
7984
with:
80-
parallel-finished:true
85+
parallel-finished:true
86+
87+

‎control/config.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,20 @@ def __missing__(self, key):
4848
else:
4949
raiseKeyError(key)
5050

51+
# New get function for Python 3.12+ to replicate old behavior
52+
defget(self,key,defval=None):
53+
# If the key exists, return it
54+
ifself.__contains__(key):
55+
returnself[key]
56+
57+
# If not, see if it is deprecated
58+
repl=self._check_deprecation(key)
59+
ifself.__contains__(repl):
60+
returnself.get(repl,defval)
61+
62+
# Otherwise, call the usual dict.get() method
63+
returnsuper().get(key,defval)
64+
5165
def_check_deprecation(self,key):
5266
ifself.__contains__(f"deprecated.{key}"):
5367
repl=self[f"deprecated.{key}"]

‎control/flatsys/linflat.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,10 @@ def forward(self, x, u, params):
119119
x=np.reshape(x, (-1,1))
120120
u=np.reshape(u, (1,-1))
121121
zflag= [np.zeros(self.nstates+1)]
122-
zflag[0][0]=self.Cf @x
122+
zflag[0][0]=(self.Cf @x).item()
123123
H=self.Cf# initial state transformation
124124
foriinrange(1,self.nstates+1):
125-
zflag[0][i]=H @ (self.A @x+self.B @u)
125+
zflag[0][i]=(H @ (self.A @x+self.B @u)).item()
126126
H=H @self.A# derivative for next iteration
127127
returnzflag
128128

‎control/freqplot.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ def bode_plot(
162162
values with no plot.
163163
rcParams : dict
164164
Override the default parameters used for generating plots.
165-
Default is setup config.default['freqplot.rcParams'].
165+
Default is setby config.default['freqplot.rcParams'].
166166
wrap_phase : bool or float
167167
If wrap_phase is `False` (default), then the phase will be unwrapped
168168
so that it is continuously increasing or decreasing. If wrap_phase is
@@ -473,7 +473,7 @@ def bode_plot(
473473
ifaxisNone:
474474
withplt.rc_context(_freqplot_rcParams):
475475
ax_array=fig.subplots(nrows,ncols,squeeze=False)
476-
fig.set_tight_layout(True)
476+
fig.set_layout_engine('tight')
477477
fig.align_labels()
478478

479479
# Set up default sharing of axis limits if not specified

‎control/grid.py

Lines changed: 52 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,21 @@
1-
importnumpyasnp
2-
fromnumpyimportcos,sin,sqrt,linspace,pi,exp
1+
# grid.py - code to add gridlines to root locus and pole-zero diagrams
2+
#
3+
# This code generates grids for pole-zero diagrams (including root locus
4+
# diagrams). Rather than just draw a grid in place, it uses the AxisArtist
5+
# package to generate a custom grid that will scale with the figure.
6+
#
7+
38
importmatplotlib.pyplotasplt
4-
frommpl_toolkits.axisartistimportSubplotHost
5-
frommpl_toolkits.axisartist.grid_helper_curvelinear \
6-
importGridHelperCurveLinear
79
importmpl_toolkits.axisartist.angle_helperasangle_helper
10+
importnumpyasnp
811
frommatplotlib.projectionsimportPolarAxes
912
frommatplotlib.transformsimportAffine2D
13+
frommpl_toolkits.axisartistimportSubplotHost
14+
frommpl_toolkits.axisartist.grid_helper_curvelinearimport \
15+
GridHelperCurveLinear
16+
fromnumpyimportcos,exp,linspace,pi,sin,sqrt
17+
18+
from .iosysimportisdtime
1019

1120

1221
classFormatterDMS(object):
@@ -65,14 +74,15 @@ def __call__(self, transform_xy, x1, y1, x2, y2):
6574
returnlon_min,lon_max,lat_min,lat_max
6675

6776

68-
defsgrid():
77+
defsgrid(scaling=None):
6978
# From matplotlib demos:
7079
# https://matplotlib.org/gallery/axisartist/demo_curvelinear_grid.html
7180
# https://matplotlib.org/gallery/axisartist/demo_floating_axis.html
7281

7382
# PolarAxes.PolarTransform takes radian. However, we want our coordinate
74-
# system indegree
83+
# system indegrees
7584
tr=Affine2D().scale(np.pi/180.,1.)+PolarAxes.PolarTransform()
85+
7686
# polar projection, which involves cycle, and also has limits in
7787
# its coordinates, needs a special method to find the extremes
7888
# (min, max of the coordinate within the view).
@@ -89,6 +99,7 @@ def sgrid():
8999
tr,extreme_finder=extreme_finder,grid_locator1=grid_locator1,
90100
tick_formatter1=tick_formatter1)
91101

102+
# Set up an axes with a specialized grid helper
92103
fig=plt.gcf()
93104
ax=SubplotHost(fig,1,1,1,grid_helper=grid_helper)
94105

@@ -97,15 +108,20 @@ def sgrid():
97108
ax.axis[:].major_ticklabels.set_visible(visible)
98109
ax.axis[:].major_ticks.set_visible(False)
99110
ax.axis[:].invert_ticklabel_direction()
111+
ax.axis[:].major_ticklabels.set_color('gray')
100112

113+
# Set up internal tickmarks and labels along the real/imag axes
101114
ax.axis["wnxneg"]=axis=ax.new_floating_axis(0,180)
102115
axis.set_ticklabel_direction("-")
103116
axis.label.set_visible(False)
117+
104118
ax.axis["wnxpos"]=axis=ax.new_floating_axis(0,0)
105119
axis.label.set_visible(False)
120+
106121
ax.axis["wnypos"]=axis=ax.new_floating_axis(0,90)
107122
axis.label.set_visible(False)
108-
axis.set_axis_direction("left")
123+
axis.set_axis_direction("right")
124+
109125
ax.axis["wnyneg"]=axis=ax.new_floating_axis(0,270)
110126
axis.label.set_visible(False)
111127
axis.set_axis_direction("left")
@@ -119,43 +135,41 @@ def sgrid():
119135
ax.axis["bottom"].get_helper().nth_coord_ticks=0
120136

121137
fig.add_subplot(ax)
122-
123-
# RECTANGULAR X Y AXES WITH SCALE
124-
# par2 = ax.twiny()
125-
# par2.axis["top"].toggle(all=False)
126-
# par2.axis["right"].toggle(all=False)
127-
# new_fixed_axis = par2.get_grid_helper().new_fixed_axis
128-
# par2.axis["left"] = new_fixed_axis(loc="left",
129-
# axes=par2,
130-
# offset=(0, 0))
131-
# par2.axis["bottom"] = new_fixed_axis(loc="bottom",
132-
# axes=par2,
133-
# offset=(0, 0))
134-
# FINISH RECTANGULAR
135-
136138
ax.grid(True,zorder=0,linestyle='dotted')
137139

138-
_final_setup(ax)
140+
_final_setup(ax,scaling=scaling)
139141
returnax,fig
140142

141143

142-
def_final_setup(ax):
144+
# Utility function used by all grid code
145+
def_final_setup(ax,scaling=None):
143146
ax.set_xlabel('Real')
144147
ax.set_ylabel('Imaginary')
145-
ax.axhline(y=0,color='black',lw=1)
146-
ax.axvline(x=0,color='black',lw=1)
147-
plt.axis('equal')
148+
ax.axhline(y=0,color='black',lw=0.25)
149+
ax.axvline(x=0,color='black',lw=0.25)
148150

151+
# Set up the scaling for the axes
152+
scaling='equal'ifscalingisNoneelsescaling
153+
plt.axis(scaling)
149154

150-
defnogrid():
151-
f=plt.gcf()
152-
ax=plt.axes()
153155

154-
_final_setup(ax)
155-
returnax,f
156+
# If not grid is given, at least separate stable/unstable regions
157+
defnogrid(dt=None,ax=None,scaling=None):
158+
fig=plt.gcf()
159+
ifaxisNone:
160+
ax=fig.gca()
161+
162+
# Draw the unit circle for discrete time systems
163+
ifisdtime(dt=dt,strict=True):
164+
s=np.linspace(0,2*pi,100)
165+
ax.plot(np.cos(s),np.sin(s),'k--',lw=0.5,dashes=(5,5))
156166

167+
_final_setup(ax,scaling=scaling)
168+
returnax,fig
157169

158-
defzgrid(zetas=None,wns=None,ax=None):
170+
# Grid for discrete time system (drawn, not rendered by AxisArtist)
171+
# TODO (at some point): think about using customized grid generator?
172+
defzgrid(zetas=None,wns=None,ax=None,scaling=None):
159173
"""Draws discrete damping and frequency grid"""
160174

161175
fig=plt.gcf()
@@ -206,5 +220,9 @@ def zgrid(zetas=None, wns=None, ax=None):
206220
ax.annotate(r"$\frac{"+num+r"\pi}{T}$",xy=(an_x,an_y),
207221
xytext=(an_x,an_y),size=9)
208222

209-
_final_setup(ax)
223+
# Set default axes to allow some room around the unit circle
224+
ax.set_xlim([-1.1,1.1])
225+
ax.set_ylim([-1.1,1.1])
226+
227+
_final_setup(ax,scaling=scaling)
210228
returnax,fig

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp