Developer Notes

This chapter contains notes for developers who wish to contribute tothe Python Control Systems Library (python-control). It is mainly alisting of the practices that have evolved over the course ofdevelopment since the package was created in 2009.

Package Structure

The python-control package is maintained on GitHub, with documentationhosted by ReadTheDocs and a mailing list on SourceForge:

GitHub repository file and directory layout:
  • python-control/ - main repository

    • LICENSE, Manifest, pyproject.toml, README.rst - package information

    • control/ - primary package source code

      • __init__.py, _version.py, config.py - package definitionand configuration

      • iosys.py, nlsys.py, lti.py, statesp.py, xferfcn.py,frdata.py - I/O system classes

      • bdalg.py, delay.py, canonical.py, margins.py,sysnorm.py, modelsimp.py, passivity.py, robust.py,statefbk.py, stochsys.py - analysis and synthesis routines

      • ctrlplot.py, descfcn.py, freqplot.py, grid.py,nichols.py, pzmap.py, rlocus.py, sisotool.py,timeplot.py, timeresp.py - response and plotting routines

      • ctrlutil.py, dtime.py, exception.py, mateqn.py - utility functions

      • phaseplot.py - phase plot module

      • optimal.py - optimal control module

      • flatsys/ - flat systems subpackage

        • __init__.py, basis.py, bezier.py, bspline.py, flatsys.py,linflat.py, poly.py, systraj.py - subpackage files

      • matlab/ - MATLAB compatibility subpackage

        • __init__.py, timeresp.py, wrappers.py - subpackage files

      • tests/ - unit tests

    • .github/ - GitHub workflows

    • benchmarks/ - benchmarking files (not well-maintained)

    • doc/ - user guide and reference manual

      • index.rst - main documentation index

      • conf.py, Makefile - sphinx configuration files

      • intro.rst, linear.rst, statesp.rst, xferfcn.rst, nonlinear.rst,flatsys.rst, iosys.rst, nlsys.rst, optimal.rst, phaseplot.rst,response.rst, descfcn.rst, stochastic.rst, examples.rst - UserGuide

      • functions.rst, classes.rst, config.rst, matlab.rst, develop.rst -Reference Manual

      • examples/

        • *.py, *.rst - Python scripts (linked to ../examples/*.py)

        • *.ipynb - Jupyter notebooks (linked to ../examples.ipynb)

      • figures/

        • *.pdf, *.png - Figures for inclusion in documentation

    • examples/

      • *.py - Python scripts

      • *.ipynb - Jupyter notebooks

Naming Conventions

Generally speaking, standard Python and NumPy naming conventions areused throughout the package.

Filenames

  • Source files are lower case, usually less than 10 characters (and 8or less is better).

  • Unit tests (incontrol/tests/) are of the formmodule_test.py ormodule_function.py.

Class names

  • Most class names are in camel case, with long form descriptions ofthe object purpose/contents (TimeResponseData).

  • Input/output class names are written out in long form as they aren’ttoo long (StateSpace,TransferFunction), but for very long names‘IO’ can be used in place of ‘InputOutput’ (NonlinearIOSystem) and‘IC’ can be used in place of ‘Interconnected’ (LinearICSystem).

  • Some older classes don’t follow these guidelines (e.g.,LTI insteadofLinearTimeInvariantSystem orLTISystem).

Function names

  • Function names are lower case with words separated by underscores.

  • Function names usually describe what they do(create_statefbk_iosystem,find_operating_points) or what theygenerate (input_output_response,find_operating_point).

  • Some abbreviations and shortened versions are used when names getvery long (e.g.,create_statefbk_iosystem instead ofcreate_state_feedback_input_output_system.

  • Factory functions for I/O systems use short names (partly from MATLABconventions, partly because they are pretty frequently used):frd,flatsys,nlsys,ss, andtf.

  • Short versions of common commands with longer names are created bycreating an object with the shorter name as a copy of the mainobject:bode=bode_plot,step=step_response, etc.

  • The MATLAB compatibility library (control.matlab) uses names thattry to line up with MATLAB (e.g.,lsim instead offorced_response).

Parameter names

Parameter names are not (yet) very uniform across the package. A fewgeneral patterns are emerging:

System-creating commands:

  • Commands that create an I/O system should allow the use of thefollowing standard parameters:

    • name: system name

    • inputs,outputs,states: number or names of inputs, outputs, state

    • input_prefix,output_prefix,state_prefix: change the defaultprefixes used for naming signals.

    • dt: set the timebase. This one takes a bit of care, since if it isnot specified then it defaults toconfig.defaults['control.default_dt']. This is different thansettingdt = None, sodt should always be part of**kwargs.

    These keywords can be parsed in a consistent way using theiosys._process_iosys_keywords function.

System arguments:

  • sys when an argument is a single input/output system(e.g.bandwidth).

  • syslist when an argument is a list of systems (e.g.,interconnect). A single system should also be OK.

  • sysdata when an argument can either be a system, a list ofsystems, or data describing a response (e.g,nyquist_response).

    Todo

    For a future release (v 0.11.x?) we should make this moreconsistent across the package.

Signal arguments:

  • Factory functions useinputs,outputs, andstates to provideeither the number of each signal or a list of labels for thesignals.

Order of arguments for functions taking inputs, outputs, state, time,frequency, etc:

  • The default order for providing arguments in state space models is(t,x,u,params). This is the generic order that should beused in functions that take signals as parameters, but permuted sothat required arguments go first, common arguments go next (askeywords, in the order listed above if they also work as positionalarguments), and infrequent arguments go last (in order listedabove). For example:

    defmodel_update(t,x,u,params)resp=initial_response(sys,timepts,x0)# x0 requiredresp=input_output_response(sys,timepts,u,x0)# u requiredresp=TimeResponseData(timepts,outputs,states=states,inputs=inputs)

    In the last command, note that states precedes inputs because notall TimeResponseData elements have inputs (e.g.,initial_response).

  • The default order for providing arguments in the frequency domain issystem/response first, then frequency:

    resp=frequency_response(sys,omega)sys_frd=frd(sys_tf,omega)sys=frd(response,omega)

Time and frequency responses:

  • Usetimepts for lists of times andomega for lists offrequencies at which systems are evaluated. For example:

    ioresp=ct.input_output_response(sys,timepts,U)cplt=ct.bode_plot(sys,omega)
  • Useinputs,outputs,states,time for time responsedata attributes. These should be used as parameter names whencreatingTimeResponseData objects and also as attributes whenretrieving response data (with dimensions dependent onsqueezeprocessing). These are stored internally in non-squeezed form usingu,y,x, andt, but the internal data should generally notbe accessed directly. For example:

    plt.plot(ioresp.time,ioresp.outputs[0])tresp=ct.TimeResponseData(time,outputs,states,...)# (internal call)
    • Note that the use ofinputs,outputs, andstates for bothfactory function specifications as well as response functionattributes is a bit confusing.

  • Usefrdata,omega for frequency response data attributes. Theseshould be used as parameter names when creatingFrequencyResponseData objects and also as attributes whenretrieving response data. Thefrdata attribute is stored as a 3Darray indexed by outputs, inputs, frequency.

  • Usecomplex,magnitude,phase for frequency responsedata attributes with squeeze processing. For example:

    ax=plt.subplots(2,1)ax[0].loglog(fresp.omega,fresp.magnitude)ax[1].semilogx(fresp.omega,fresp.phase)
    • The frequency response is stored internally in non-squeezed formasfresp, but this is generally not accessed directly by users.

    • Note that when creating time response data the independentvariable (time) is the first argument whereas for frequencyresponse data the independent variable (omega) is the secondargument. This is because we also create frequency response datafrom a linear system using a callfrd(sys,omega), andrename frequency response data using a callfrd(sys,name='newname'), so the system/data need to be the firstargument. For time response data we use the convention that westart with time and then list the arguments in the most frequentlyused order.

  • Useresponse orresp for generic response objects (time,frequency, describing function, Nyquist, etc).

    • Note that when responses are evaluated as tuples, the ordering ofthe dependent and independent variables switches between time andfrequency domain:

      t,y=ct.step_response(sys)mag,phase,omega=ct.frequency_response(sys)

      To avoid confusion, it is better to use response objects:

      tresp=ct.step_response(sys)t,y=tresp.time,tresp.outputsfresp=ct.frequency_response(sys)omega,response=fresp.omega,fresp.responsemag,phase,omega=fresp.magnitude,fresp.phase,fresp.omega

Parameter aliases

As described above, parameter names are generally longer strings thatdescribe the purpose of the parameter. Similar tomatplotlib (e.g.,the use oflw as an alias forlinewidth), some commonly usedparameter names can be specified using an “alias” that allows the useof a shorter key.

Named parameter and keyword variable aliases are processed using theconfig._process_kwargs() andconfig._process_param()functions. These functions allow the specification of a list ofaliases and a list of legacy keys for a given named parameter orkeyword. To make use of these functions, the_process_kwargs() is first called to update thekwargsvariable by replacing aliases with the full key:

_process_kwargs(kwargs,aliases)

The values for named parameters can then be assigned to a localvariable using a call to_process_param() of the form:

var=_process_param('param',param,kwargs,aliases)

whereparam is the named parameter used in the function signatureand var is the local variable in the function (may also beparam,but doesn’t have to be).

For example, the following structure is used ininput_output_response:

definput_output_response(sys,timepts=None,inputs=0.,initial_state=0.,params=None,ignore_errors=False,transpose=False,return_states=False,squeeze=None,solve_ivp_kwargs=None,evaluation_times='T',**kwargs):"""Compute the output response of a system to a given input.    ... rest of docstring ...    """_process_kwargs(kwargs,_timeresp_aliases)T=_process_param('timepts',timepts,kwargs,_timeresp_aliases)U=_process_param('inputs',inputs,kwargs,_timeresp_aliases,sigval=0.)X0=_process_param('initial_state',initial_state,kwargs,_timeresp_aliases,sigval=0.)

Note that named parameters that have a default value other than Nonemust given the signature value (sigval) so that_process_param can detect if the value has been set (andissue an error if there is an attempt to set the value multiple timesusing alias or legacy keys).

The alias mapping is a dictionary that returns a tuple consisting ofvalid aliases and legacy aliases:

alias_mapping={'argument_name_1':(['alias',...],['legacy',...]),...}

If an alias is present in the dictionary of keywords, it will be usedto set the value of the argument. If a legacy keyword is used, awarning is issued.

The following tables summarize the aliases that are currently in usethrough the python-control package:

Time response aliases (viatimeresp._timeresp_aliases):

Key

Aliases

Legacy keys

Comment

evaluation_times

t_eval

List of times to evaluate the time response (defaults totimepts).

final_output

yfinal

Final value of the output (used forstep_info())

initial_state

X0

x0

Initial value of the state variable.

input_indices

input

Index(es) to use for the input (used instep_response(),impulse_response().

inputs

U

u

Value(s) of the input variable (time trace or individual point).

output_indices

output

Index(es) to use for the output (used instep_response(),impulse_response().

outputs

Y

y

Value(s) of the output variable (time trace or individual point).

return_states

return_x

Return the state when accessing a response via a tuple.

timepts

T

List of time points for time response functions.

timepts_num

T_num

Number of points to use (e.g., iftimepts is just the final time).

Optimal control aliases (viaoptimal._optimal_aliases:

Key

Aliases

Comment

final_state

xf

Final state for trajectory generation problems (flatsys, optimal).

final_input

uf

Final input for trajectory generation problems (flatsys).

initial_state

x0, X0

Initial state for optimization problems (flatsys, optimal).

initial_input

u0, U0

Initial input for trajectory generation problems (flatsys).

initial_time

T0

Initial time for optimization problems.

integral_cost

trajectory_cost, cost

Cost function that is integrated along a trajectory.

return_states

return_x

Return the state when accessing a response via a tuple.

trajectory_constraints

constraints

List of constraints that hold along a trajectory (flatsys, optimal)

Documentation Guidelines

The python-control package is documented using docstrings and Sphinx.Reference documentation (class and function descriptions, with detailson parameters) should all go in docstrings. User documentation inmore narrative form should be in therst files indoc/, where itcan be incorporated into the User Guide. All significantfunctionality should have a narrative description in the User Guide inaddition to docstrings.

Generally speaking, standard Python and NumPy documentationconventions are used throughout the package:

General docstring info

The guiding principle used to guide how docstrings are written issimilar to NumPy (as articulated in thenumpydoc style guide):

A guiding principle is that human readers of the text are givenprecedence over contorting docstrings so our tools produce niceoutput. Rather than sacrificing the readability of the docstrings,we have written pre-processors to assist Sphinx in its task.

To that end, docstrings inpython-control should use the followingguidelines:

  • Use single backticks around all Python objects. The Sphinxconfiguration file (doc/conf.py) definesdefault_role to bepy:obj, so everything in a single backtick will be rendered incode form and linked to the appropriate documentation if it exists.

    • Note: consistent with numpydoc recommendations, parameters namesfor functions should be in single backticks, even though theydon’t generate a link (but the font will still be OK).

    • Thedoc/_static/custom.css file defines the style for Pythonobjects and is configured so that linked objects will appear in abolder type, so that it is easier to see what things you can clickon to get more information.

    • By default, the string `sys` in docstrings would normallygenerate a link to thesys Python module. To avoid this,conf.py includes code that converts `sys` in docstrings to:code:`sys`, which renders assys (code style, with nolink). In.rst files this construction should be donemanually, since.rst files are not pre-processed as adocstring.

  • Use double backticks for inline code, such as a Python code fragments.

    • In principle single backticks might actually work OK given the waythat thepy:obj processing works in Sphinx, but the inclusion ofcode is somewhat rare and the extra two backticks seem like asmall sacrifice (and far from a “contortion”).

  • Avoid the use of backticks and :math: for simple formulas wherethe additional annotation or formatting does not add anything. Forexample “-c <= x <= c” (without the double quotes) inrelay_hysteresis_nonlinearity.

    • Some of these formulas might be interpreted as Python codefragments, but they only need to be in double quotes if that makesthe documentation easier to understand.

    • Examples:

      • `dt` > 0 not ``dt > 0`` (dt is a parameter)

      • `squeeze` = True not ``squeeze = True`` nor squeeze = True.

      • -c <= x <= c not ``-c <= x <= c`` nor :math:`-c \leq x\leq c`.

      • :math:`|x| < \epsilon` (becomes|x| < \epsilon)

  • Built-in Python objects (True, False, None) should be written with nobackticks and should be properly capitalized.

    • Another possibility here is to use a single backtick aroundbuilt-in objects, and thepy:obj processing will then generate alink back to the primary Python documentation. That seemsdistracting for built-ins likeTrue,False andNone (writtenhere in single backticks) and using double backticks looks fine inSphinx (True,False,None), but seemed to cross the“contortions” threshold.

  • Strings used as arguments to parameters should be in single(forward) ticks (‘eval’, ‘rows’, etc) and don’t need to be renderedas code if just listed as part of a docstring.

    • The rationale here is similar to built-ins: adding 4 backticksjust to get them in a code font seems unnecessary.

    • Note that if a string is included in Python assignment statement(e.g.,method='slycot') it looks quite ugly in text form tohave it enclosed in double backticks (``method=’slycot’``), soOK to use method=’slycot’ (no backticks) ormethod = ‘slycot’(backticks with extra spaces).

  • References to thedefaults dictionary should be of the form`config.defaults[‘module.param’]` (like a parameter), whichrenders asconfig.defaults['module.param'] in Sphinx.

    • It would be nice to have the term show up as a link to thedocumentation for that parameter (in thePackage Configuration Parameters section of the ReferenceManual), but the special processing to do that hasn’t beenimplemented.

    • Depending on placement, you can end up with lots of white spacearound defaults parameters (also true in the docstrings).

  • Math formulas can be written as plain text unless the requirespecial symbols (this is consistent with numpydoc) or include Pythoncode. Use the:math: directive to handle symbols.

Examples of different styles:

  • Single backticks to a a function:interconnect

  • Single backticks to a parameter (no link):squeeze

  • Double backticks to a code fragment:subsys=sys[i][j].

  • Built-in Python objects: True, False, None

  • Defaults parameter:config.defaults['control.squeeze_time_response']

  • Inline math:\eta = m \xi + \beta

Function docstrings

Follow numpydoc format with the following additional details:

  • All functions should have a short (< 64 character) summary line thatstarts with a capital letter and ends with a period.

  • All parameter descriptions should start with a capital letter andend with a period. An exception is parameters that have a list ofpossible values, in which case a phrase sending in a colon (:)followed by a list (without punctuation) is OK.

  • All parameters and keywords must be documented. Thedocstrings_test.py unit test tries to flag as many of these aspossible.

  • Include an “Examples” section for all non-trivial functions, in aform that can be checked by runningmakedoctest in thedocdirectory. This is also part of the CI checks.

For functions that return a named tuple, bundle object, or classinstance, the return documentation should include the primary elementsof the return value:

Returns-------resp : `TimeResponseData`    Input/output response data object.  When accessed as a tuple, returns    ``time, outputs`` (default) or ``time, outputs, states`` if    `return_states` is True.  The `~TimeResponseData.plot` method can be    used to create a plot of the time response(s) (see `time_response_plot`    for more information).resp.time : array    Time values of the output.resp.outputs : array    Response of the system.  If the system is SISO and `squeeze` is not    True, the array is 1D (indexed by time).  If the system is not SISO or    `squeeze` is False, the array is 2D (indexed by output and time).resp.states : array    Time evolution of the state vector, represented as a 2D array indexed by    state and time.resp.inputs : array    Input(s) to the system, indexed by input and time.

Class docstrings

Follow numpydoc format with the follow additional details:

  • Parameters used in creating an object go in the class docstring andnot in the__init__ docstring (which is not included in theSphinx-based documentation). OK for the__init__ function to haveno docstring.

  • Parameters that are also attributes only need to be documented once(in the “Parameters” or “Additional Parameters” section of the classdocstring).

  • Attributes that are created within a class and that might be ofinterest to the user should be documented in the “Attributes”section of the class docstring.

  • Classes should not include a “Returns” section (since they alwaysreturn an instance of the class).

  • Functions and attributes that are not intended to be accessed byusers should start with an underscore.

I/O system classes:

  • Subclasses ofInputOutputSystem should always have a factoryfunction that is used to create them. The class documentation onlyneeds to document the required parameters; the full list ofparameters (and optional keywords) can and should be documented inthe factory function docstring.

User Guide

The purpose of the User Guide is provide anarrative description ofthe key functions of the package. It is not expected to cover everycommand, but should allow someone who knows about control systemdesign to get up and running quickly.

The User Guide consists of chapters that are each their own separaterst file and each of them generates a separate page. Chapters aredivided into sections whose names appear in the index on the left ofthe web page when that chapter is being viewed. In some cases asection may be in its own file, included in the chapter page by usingtheinclude directive (seenlsys.py for an example).

Sphinx files guidelines:

  • Each file should declare thecurrentmodule at or near the top ofthe file. Except for subpackages (control.flatsys) and modulesthat need to be imported separately (control.optimal),currentmodule should be set to control.

  • When possible, sample code in the User Guide should use Sphinxdoctest directives so that the code is executed bymakedoctest.Two styles are possible: doctest-style blocks (showing code with aprompt and the expected response) and code blocks (using thetestcode directive).

  • When referring to the python-control package, several different formscan be used:

    • Full name: “the Python Control Systems Library (python-control)”(used sparingly, mainly at the tops of chapters).

    • Adjective form: “the python-control package” or “a python-controlmodule” (this is the most common form).

    • Noun form: “python-control” (only used occasionally).

  • Unlike docstrings, the documentation in the User Guide should usebackticks and :math: more liberally when it is appropriate tohighlight/format code properly. However, Python built-ins shouldstill just be written as True, False, and None (no backticks), forformatting consistency.

    • The Sphinx documentation is not read in “raw” form, so OK to addthe additional annotations.

    • The Python built-ins occur frequently and are capitalized, and sothe additional formatting doesn’t add much and would beinconsistent if you jump from the User Guide to the ReferenceManual (e.g., to look at a function more closely via a link in theUser Guide).

Reference Manual

The Reference Manual should provide a fairly comprehensive descriptionof every class, function, and configuration variable in the package.All primary functions and classes bust be included here, since theReference Manual generates the stub files used by Sphinx.

Modules and subpackages

When documenting (independent) modules and subpackages (refereed tohere collectively as modules), use the following guidelines fordocumentation:

  • In module docstrings, refer to module functions and classes withoutincluding the module prefix. This will let Sphinx set up the linksto the functions in the proper way and has the advantage that itkeeps the docstrings shorter.

  • Objects in the parent (control) package should be referenced usingthecontrol prefix, so that Sphinx generates the links properly(otherwise it only looks within the package).

  • In the User Guide, setcurrentmodule tocontrol and refer tothe module objects using the prefixprefix in the text portionsof the document butpx (shortened prefix) in the code sections.This will let users copy and past code from the examples and isconsistent with the use of thect short prefix. Since this is inthe User Guide, the additional characters are not as big an issue.

  • If you include anautosummary of functions in the User Guidesection, list the functions using the regular prefix (without~)to remind everyone the function is in a module.

  • When referring to a module function or class in a docstring or UserGuide section that is not part of the module, use the fullyqualified function or class ('prefix.function').

The main overarching principle should be to make sure that referencesto objects that have more detailed information should show up as alink, not as code.

Utility Functions

The following utility functions can be used to help with standardprocessing and parsing operations:

config._process_legacy_keyword(kwargs, ...)

Utility function for processing legacy keywords.

config._process_kwargs(kwargs, alias_mapping)

Process aliases and legacy keywords.

config._process_param(name, defval, kwargs, ...)

Process named parameter, checking aliases and legacy usage.

exception.cvxopt_check()

Return True if cvxopt is installed, otherwise False.

exception.pandas_check()

Return True if pandas is installed, otherwise False.

exception.slycot_check()

Return True if Slycot is installed, otherwise False.

iosys._process_iosys_keywords([keywords, ...])

Process iosys specification.

mateqn._check_shape(M, n, m[, square, ...])

Check the shape and properties of a 2D array.

statesp._convert_to_statespace(sys[, ...])

Convert a system to state space form (if needed).

statesp._ssmatrix(data[, axis, square, ...])

Convert argument to a (possibly empty) 2D state space matrix.

xferfcn._convert_to_transfer_function(sys[, ...])

Convert a system to transfer function form (if needed).

Sample Files

Code template

The following file is a template for a python-control module. It canbe found inpython-control/doc/examples/template.py.

  1# template.py - template file for python-control module  2# RMM, 3 Jan 2024  3  4"""Template file for python-control module.  5  6This file provides a template that can be used when creating a new  7file/module in python-control.  The key elements of a module are included  8in this template, following the suggestions in the Developer Guidelines.  9 10The first line of a module file should be the name of the file and a short 11description.  The next few lines can contain information about who created 12the file (your name/initials and date).  For this file I used the short 13version (initials, date), but a longer version would be to do something of 14the form:: 15 16  # filename.py - short one line description 17  # 18  # Initial author: Full name 19  # Creation date: date the file was created 20 21After the header comments, the next item is the module docstring, which 22should be a multi-line comment, like this one.  The first line of the 23comment is a one line summary phrase, starting with a capital letter and 24ending in a period (often the same as the line at the very top).  The rest 25of the docstring is an extended summary (this one is a bit longer than 26would be typical). 27 28After the docstring, you should have the following elements (in Python): 29 30  * Package imports, using the `isort -m2` format (library, standard, custom) 31  * __all__ command, listing public objects in the file 32  * Class definitions (if any) 33  * Public function definitions 34  * Internal function definitions (starting with '_') 35  * Function aliases (short = long_name) 36 37The rest of this file contains examples of these elements. 38 39""" 40 41importwarnings# Python packages 42 43importnumpyasnp# Standard external packages 44 45from.importconfig# Other modules/packages in python-control 46from.ltiimportLTI# Public function or class from a module 47 48__all__=['SampleClass','sample_function'] 49 50 51classSampleClass(): 52"""Sample class in the python-control package. 53 54    This is an example of a class definition.  The docstring follows 55    numpydoc format.  The first line should be a summary (which will show 56    up in `autosummary` entries in the Sphinx documentation) and then an 57    extended summary describing what the class does.  Then the usual 58    sections, per numpydoc. 59 60    Additional guidelines on what should be listed in the various sections 61    can be found in the 'Class docstrings' section of the Developer 62    Guidelines. 63 64    Parameters 65    ---------- 66    sys : InputOutputSystem 67        Short description of the parameter. 68 69    Attributes 70    ---------- 71    data : array 72         Short description of an attribute. 73 74    """ 75def__init__(self,sys): 76# No docstring required here 77self.sys=sys# Parameter passed as argument 78self.data=sys.name# Attribute created within class 79 80defsample_method(self,data): 81"""Sample method within a class. 82 83        This is an example of a method within a class.  Document using 84        numpydoc format. 85 86        """ 87returnNone 88 89 90defsample_function(data,option=False,**kwargs): 91"""Sample function in the template module. 92 93    This is an example of a public function within the template module. 94    This function will usually be placed in the `control` namespace by 95    updating `__init__.py` to import the function (often by importing the 96    entire module). 97 98    Docstring should be in standard numpydoc format.  The extended summary 99    (this text) should describe the basic operation of the function, with100    technical details in the "Notes" section.101102    Parameters103    ----------104    data : array105         Sample parameter for sample function, with short docstring.106    option : bool, optional107         Optional parameter, with default value `False`.108109    Returns110    -------111    out : float112        Short description of the function output.113114    Additional Parameters115    ---------------------116    inputs : int, str, or list of str117        Parameters that are less commonly used, in this case a keyword118        parameter.119120    See Also121    --------122    function1, function2123124    Notes125    -----126    This section can contain a more detailed description of how the system127    works.  OK to include some limited mathematics, either via inline math128    directions for a short formula (like this: ..math:`x = \alpha y`) or via a129    displayed equation:130131    ..math::132133        a = \int_0^t f(t) dt134135    The trick in the docstring is to write something that looks good in136    pure text format but is also processed by sphinx correctly.137138    If you refer to parameters, such as the `data` argument to this139    function, but them in single backticks (which will render them in code140    style in Sphinx).  Strings that should be interpreted as Python code141    use double backticks: ``mag, phase, omega = response``.  Python142    built-in objects, like True, False, and None are written on their own.143144    """145inputs=kwargs['inputs']146ifoptionisTrue:147returndata148else:149returnNone150151#152# Internal functions153#154# Functions that are not intended for public use can go anyplace, but I155# usually put them at the bottom of the file (out of the way).  Their name156# should start with an underscore.  Docstrings are optional, but if you157# don't include a docstring, make sure to include comments describing how158# the function works.159#160161162# Sample internal function to process data163def_internal_function(data):164returnNone165166167# Aliases (short versions of long function names)168sf=sample_function

Documentation template

The following file is a template for a documentation file. It can befound inpython-control/doc/examples/template.rst.

 1.. currentmodule:: control 2 3************** 4Sample Chapter 5************** 6 7This is an example of a top-level documentation file, which serves a 8chapter in the User Guide or Reference Manual in the Sphinx 9documentation.  It is not that likely we will create a lot more files10of this sort, so it is probably the internal structure of the file11that is most useful.1213The file in which a chapter is contained will usual start by declaring14`currentmodule` to be `control`, which will allow text enclosed in15backticks to be searched for class and function names and appropriate16links inserted.  The next element of the file is the chapter name,17with asterisks above and below.  Chapters should have a capitalized18title and an introductory paragraph.  If you need to add a reference19to a chapter, insert a sphinx reference (`.. _ch-sample:`) above20the chapter title.2122.. _sec-sample:2324Sample Section25==============2627A chapter is made of up of multiple sections.  Sections use equal28signs below the section title.  Following FBS2e, the section title29should be capitalized.  If you need to insert a reference to the30section, put that above the section title (`.. _sec-sample:`), as31shown here.323334Sample subsection35-----------------3637Subsections use dashes below the subsection title.  The first word of38the title should be capitalized, but the rest of the subsection title39is lower case (unless it has a proper noun).  I usually leave two40blank lines before the start up a subection and one blank line after41the section markers.424344Mathematics45-----------4647Mathematics can be uncluded using the `math` directive.  This can be48done inline using `:math:short formula` (e.g. :math:`a = b`) or as a49displayed equation, using the `.. math::` directive::5051.. math::5253     a(t) = \int_0^t b(\tau) d\tau545556Function summaries57------------------5859Use the `autosummary` directive to include a table with a list of60function sinatures and summary descriptions::6162.. autosummary::6364   input_output_response65   describing_function66   some_other_function676869Module summaries70----------------7172If you have a docstring at the top of a module that you want to pull73into the documentation, you can do that with the `automodule`74directive:7576.. automodule:: control.optimal77   :noindex:78   :no-members:79   :no-inherited-members:80   :no-special-members:8182.. currentmodule:: control8384The `:noindex:` option gets rid of warnings about a module being85indexed twice.  The next three options are used to just bring in the86summary and extended summary in the module docstring, without87including all of the documentation of the classes and functions in the88module.8990Note that we `automodule` will set the current module to the one for91which you just generated documentation, so the `currentmodule` should92be reset to control afterwards (otherwise references to functions in93the `control` namespace won't be recognized.