Skip to content

Fix Nyquist indentation geometry and automatic direction selection - #1265

Closed
dongxuelian2 wants to merge 1 commit into
python-control:mainfrom
dongxuelian2:codex/nyquist-indent-geometry
Closed

dongxuelian2 wants to merge 1 commit into
python-control:mainfrom
dongxuelian2:codex/nyquist-indent-geometry

Conversation

@dongxuelian2

Copy link
Copy Markdown

Follow-up to #1223 for #1194 and #1191.

The explicit-direction fix still reflects the right-hand offset when indenting left. For example:

ct.nyquist_response(
    ct.tf([1], [1, .05]), indent_radius=.1, indent_direction='left')

On current main this places the contour on the pole and raises RuntimeError: attempt to evaluate at a pole. The corrected contour starts at -0.15, exactly 0.1 from the pole.

This change:

  • makes None the automatic mode, preserving the previous default side selection (right of stable/on-axis poles, left of unstable poles);
  • applies explicit left/right choices consistently through keywords and configuration, including an explicit None override;
  • centers both indentation directions on the pole and samples the full connecting circular arc when forcing a detour across an off-axis pole;
  • uses the poles enclosed by the indented contour for the encirclement check and retains warnings when a detour can cross a closed-loop pole.

Regression tests cover continuous/discrete systems, poles at the origin and at nonzero imaginary frequencies, either sign of a tiny real part, distances inside/on/outside the radius, automatic/manual frequency selection, configuration precedence, and the original #1191 transfer function in TF and state-space form. I also reproduced the ignored-direction behavior using the 0.10.2 response code.

Validation (Python 3.13.1, NumPy 2.2.5, SciPy 1.16.1, Matplotlib 3.10.1, Slycot installed):

  • MPLBACKEND=Agg python -m pytest control/tests/nyquist_test.py control/tests/freqplot_test.py control/tests/response_test.py control/tests/config_test.py control/tests/docstrings_test.py -q: 435 passed, 8 skipped, 1 xfailed.
  • MPLBACKEND=Agg python -m pytest control/tests --ignore=control/tests/optimal_test.py -q --timeout=60: 4577 passed, 51 skipped, 6 xfailed.
  • Ruff, compilation, and git diff --check passed.

The unrestricted suite hit the 60-second timeout in optimal_test.py::test_optimal_doc, in SciPy optimization/integration; the optimization module was excluded from the broader completed run.

AI disclosure: OpenAI Codex generated the implementation, tests, and documentation, investigated and reproduced the bugs, and ran the validation commands. This PR is submitted at the account owner's explicit request.

@slivingston

Copy link
Copy Markdown
Member

@dongxuelian2 Did you write this PR text or did the chat bot entirely write it?

@slivingston slivingston closed this Nov 3, 2026
@slivingston

Copy link
Copy Markdown
Member

Actually, I am just going to close it, as the AI disclosure implies that the human did nothing at all (not even running validation).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants