(*
Transfer Function Analysis by Manipulation of Poles and Zeros 
by Nasser M. Abbasi
version April 12 2009*)

Manipulate[
 
 Module[{graphicsOptions, frameThickness = 0.001},
  
  If[plotType == "root Locus", useClosedLoop = False];
  
  graphicsOptions = {ImageSize -> {240, 240}, ImagePadding -> 0,
    Axes -> True,
    PlotRange -> {{-ext - 3 del, ext + 3 del}, {-ext - 3 del, 
       ext + 3 del}},
    GridLines -> {Range[-ext - 3 del, ext + 3 del, del], 
      Range[-ext - 3 del, ext + 3 del, del]},
    GridLinesStyle -> 
     Directive[{LightGray, Thickness[frameThickness]}],
    AspectRatio -> 1,
    Background -> White,
    TicksStyle -> Small,
    Ticks -> {{-1, -0.5, 0, 0.5, 1}, {-1, -0.5, 0, 0.5, 1}},
    AxesStyle -> Directive[{Blue, Thickness[frameThickness]}]};
  
  If[showGrid,
   baseGraphics = {{LightGray, 
      Rectangle[{-ext - 3 del, -ext - 3 del}, {ext + 3 del, 
        ext + 3 del}]},
     {White, Rectangle[{-ext, -ext}, {ext, ext}]},
     {Gray, PointSize[0.001], 
      Point[#] & /@ 
       Flatten[Outer[List, Range[-ext , ext , del], 
         Range[-ext , ext , del]], 1]},
     {Black, Circle[{0, 0}, 1]}}
   ,
   baseGraphics = {{LightGray, 
      Rectangle[{-ext - 3 del, -ext - 3 del}, {ext + 3 del, 
        ext + 3 del}]},
     {White, Rectangle[{-ext, -ext}, {ext, ext}]},
     {Black, Circle[{0, 0}, 1]}}
   ];
  
  mousePos = If[showToolTip, MousePosition["Graphics"], 0];
  
  Row[{
    Grid[{
      {Dynamic[formatedTransferFunctions], SpanFromLeft},
      {
       Switch[pointType,
        POLE,
        LocatorPane[Dynamic[poles], Graphics[
          {
           Sequence@baseGraphics,
           
           
           Dynamic@
            If[showToolTip, 
             formatRadialLine[MousePosition["Graphics"], ts], 
             Text["", {0, 0}], Enabled -> showToolTip == True],
           
           
           Dynamic[
            Refresh[format[Chop@poles, Chop@zeros, ext], 
             TrackedSymbols -> {poles}], 
            Enabled -> showToolTip == False]
           
           }, graphicsOptions],
         {{-ext - 2 del, 0}, {ext + 2 del, ext + 2 del}, {gridSpacing,
            gridSpacing}},
         Appearance -> None, LocatorAutoCreate -> {All}, 
         AutoAction -> False, Enabled -> showToolTip == False
         ],
        _,
        LocatorPane[Dynamic[zeros], Graphics[
          {
           Sequence@baseGraphics,
           
           
           Dynamic@
            If[showToolTip, 
             formatRadialLine[MousePosition["Graphics"], ts], 
             Text["", {0, 0}], Enabled -> showToolTip == True],
           
           
           Dynamic[
            Refresh[format[Chop@poles, Chop@zeros, ext], 
             TrackedSymbols -> {zeros}], 
            Enabled -> showToolTip == False]
           
           }, graphicsOptions],
         {{-ext - 2 del, 0}, {ext + 2 del, ext + 2 del}, {gridSpacing,
            gridSpacing}},
         Appearance -> None, LocatorAutoCreate -> {All}, 
         AutoAction -> False, Enabled -> showToolTip == False
         ]
        ],
       
       Dynamic[processResult]
       }
      }, Spacings -> {0, 0}, Frame -> All, Alignment -> Center, 
     FrameStyle -> Directive[Thickness[frameThickness], Gray]],
    
    (*format returned is {order,{x,y}} *)
    Dynamic[
     Refresh[internalPoles = findInternalPoints[Chop@poles, ext]; "", 
      TrackedSymbols -> {poles}]],
    
    Dynamic[
     Refresh[internalZeros = findInternalPoints[Chop@zeros, ext]; "", 
      TrackedSymbols -> {zeros}]],
    
    Dynamic[
     Refresh[hz = 
       makeHz[internalPoles, internalZeros, z, useClosedLoop]; "", 
      TrackedSymbols -> {poles, zeros, useClosedLoop}]],
    
    Dynamic[
     Refresh[{formatedTransferFunctions, tf, sys, statusOfConversion, 
        statusMessage, polesInSPlane , zerosInSPlane} = 
       formatTransferFunctions[{z, s, y, t}, internalPoles, 
        internalZeros, hz, conversionType, ts]; "", 
      TrackedSymbols -> {poles, zeros, conversionType, ts, 
        useClosedLoop}]],
    
    Dynamic[
     Refresh[processResult = 
       First@process[z, ts, plotType, simulationTime, rootLocusK, 
         bodeMagScales, bodePhaseScales, mousePos, showToolTip, 
         responseJoined, showPlotsGrid, showStabilityMargins, tf, sys,
          internalPoles, internalZeros, hz, addContResponse, 
         statusOfConversion, statusMessage, polesInSPlane , 
         zerosInSPlane, conversionType, forcingFrequency]; "", 
      TrackedSymbols -> {mousePos, poles, zeros, ts, plotType, 
        simulationTime, rootLocusK, bodeMagScales, bodePhaseScales, 
        responseJoined, showPlotsGrid, showStabilityMargins, 
        addContResponse, conversionType, forcingFrequency, 
        useClosedLoop}
      ], ContinuousAction -> True
     ]
    
    }](*Row*)
  ],(*Manipulate expression completed*)
 
 (*control variables layout. Top panel*)
 Item[
  Grid[{{
     
     Grid[{{
        Grid[{
          
          {Control[{{pointType, POLE, ""}, {POLE -> Style["pole", 11],
               ZERO -> Style["zero", 11]}, 
             ControlType -> RadioButtonBar, ImageSize -> Tiny, 
             ImageMargins -> 0, Appearance -> "Vertical", 
             Background -> LightGray}]}
          }, Spacings -> {0, .2}],
        
        Grid[{
          {Text@Style["plot type", 12]},
          {Control[{ {plotType, "step", 
              ""}, (# -> Text@Style[#, 12]) & /@ {"Bode", 
               "root Locus", "Nyquist", "Nichols", "H(z) margins", 
               "H(s) margins", "S-plane map", "impulse", "step", 
               "ramp", "cos(2\[Pi]fn)", 
               "\!\(\*SuperscriptBox[\(\[ExponentialE]\), \
\(-n\)]\)cos(2\[Pi]fn)"},
             ControlType -> PopupMenu, ImageSize -> All}]
           }
          }, Spacings -> {0, .2}]
        
        }}, Frame -> True, 
      FrameStyle -> Directive[Thickness[.001], Gray], 
      Spacings -> {-.5, .4}]
     ,
     Grid[{
       {Text@Row[{Style[" k", Italic, 12]}],
        Control[{{rootLocusK, 3, ""}, 1, 20, 1, ImageSize -> Tiny, 
          Enabled -> plotType == "root Locus"}], 
        Text@Row[{" ", Style[Dynamic[rootLocusK], 10]}]
        },
       {
        Text@Row[{Style[" f", Italic, 12]}],
        Control[{{forcingFrequency, 1, ""}, 0, 2, 0.05, 
          ImageSize -> Tiny, 
          Enabled -> 
           plotType == "cos(2\[Pi]fn)" || 
            plotType == 
             "\!\(\*SuperscriptBox[\(\[ExponentialE]\), \
\(-n\)]\)cos(2\[Pi]fn)"}], 
        Text@Row[{" ", 
           Style[Dynamic[padIt1[forcingFrequency, {2, 2}]], 10]}]
        }
       }, Frame -> True, Alignment -> Left, 
      FrameStyle -> Directive[Thickness[.001], Gray], 
      Spacings -> {0, 0.3}
      ],
     
     Grid[{
       {Text@Style["Bode units (mag)", 12],
        Text@Style["Bode units (phase)", 12]
        },
       {Control[{ {bodeMagScales, {"Linear", "Absolute"}, 
           ""}, (# -> Style[#, 10]) & /@ {{"Log10", "dB"}, {"Log10", 
             "Absolute"}, {"Linear", "dB"}, {"Linear", "Absolute"}},
          ControlType -> PopupMenu, ImageSize -> All, 
          Enabled -> plotType == "Bode"}],
        Control[{ {bodePhaseScales, {"Linear", "Degree"}, 
           ""}, (# -> Style[#, 10]) & /@ {{"Log10", 
             "Degree"}, {"Log10", "Radian"}, {"Linear", 
             "Degree"}, {"Linear", "Radian"}},
          ControlType -> PopupMenu, ImageSize -> All, 
          Enabled -> plotType == "Bode"}]
        }
       }, Frame -> True, 
      FrameStyle -> Directive[Thickness[.001], Gray], 
      Spacings -> {0, 0.3}],
     
     Grid[{
       {Text@Style["grid lines", 10], 
        Control[{{showPlotsGrid, True, ""}, {True, False}, 
          ImageSize -> Tiny, ImagePadding -> 0,
          
          Enabled -> 
           plotType == "Bode" || plotType == "Nyquist" || 
            plotType == "Nichols" || plotType == "impulse" || 
            plotType == "step" || plotType == "ramp" || 
            plotType == "cos(2\[Pi]fn)" || 
            plotType == 
             "\!\(\*SuperscriptBox[\(\[ExponentialE]\), \
\(-n\)]\)cos(2\[Pi]fn)"}]
        },
       {Text@Style["margins", 10], 
        Control[{{showStabilityMargins, False, ""}, {True, False}, 
          ImageSize -> Tiny, ImagePadding -> 0, 
          Enabled -> 
           plotType == "Bode" || plotType == "Nyquist" || 
            plotType == "Nichols" || plotType == "root Locus"}]
        },
       {Text@Style["closed loop", 10], 
        Control[{{useClosedLoop, False, ""}, {True, False}, 
          ImageSize -> Tiny, ImagePadding -> 0, 
          Enabled -> plotType != "root Locus"}]
        }
       }, Frame -> True, 
      FrameStyle -> Directive[Thickness[.001], Gray], 
      Spacings -> {.5, 0}, Alignment -> Left]
     
     }}, Frame -> None, 
   FrameStyle -> Directive[Thickness[.001], Gray], 
   Spacings -> {.1, 0}, Alignment -> Center
   ], ControlPlacement -> Top, ItemSize -> All, Alignment -> Left],
 
 (*Bottom panel*)
 Item[
  Grid[{
    {
     Grid[{
       {Text@Style["background", 11], 
        Control[{{showGrid, True, ""}, {True, False}, 
          ControlType -> Checkbox, ImageSize -> Tiny}]},
       {Text@Style["tooltip", 11], 
        Control[{{showToolTip, False, ""}, {True, False}, 
          ControlType -> Checkbox, ImageSize -> Tiny}]}
       }, Alignment -> Left, Frame -> True, 
      FrameStyle -> Directive[Thickness[.001], Gray], 
      Spacings -> {0.3, 0.6}],
     
     Grid[{
       {Text@Style[" grid spacing", 10]},
       {Control[{ {gridSpacing, 0.1, ""}, {0.1 -> Style["0.1", 10], 
           0 -> Style["0", 10]},
          ControlType -> PopupMenu, ImageSize -> All}]
        }
       }, Frame -> True, 
      FrameStyle -> Directive[Thickness[.001], Gray], 
      Spacings -> {0.2, 0.3}],
     
     Grid[{
       {Text@Style["time", 11],
        Control[{{simulationTime, 25, ""}, 2, 50, 1, 
          ImageSize -> Tiny}],
        Text@Style[Dynamic[simulationTime], 10]
        },
       {Text@Style["\!\(\*SubscriptBox[\(T\), \(s\)]\)", 11],
        Control[{{ts, 1, ""}, 1, 4, 0.1, ImageSize -> Tiny, 
          ImagePadding -> 0}],
        Text@Style[Dynamic[padIt1[ts, {2, 2}]], 10]
        }
       }
      , Frame -> True, FrameStyle -> Directive[Thickness[.001], Gray],
       Spacings -> {.2, .3}],
     
     Grid[{
       {Text[Style["response shape", 11]]},
       {Control[{{responseJoined, True, 
           Text@Style["joined plot ", 10]}, {True, False}, 
          ImageSize -> Tiny, ImagePadding -> 0, 
          Enabled -> 
           plotType == "impulse" || plotType == "step" || 
            plotType == "ramp" || plotType == "cos(2\[Pi]fn)" || 
            plotType == 
             "\!\(\*SuperscriptBox[\(\[ExponentialE]\), \
\(-n\)]\)cos(2\[Pi]fn)"}]
        },
       {Control[{{addContResponse, True, 
           Text@Style["superimpose", 10]}, {True, False}, 
          ImageSize -> Tiny, ImagePadding -> 0, 
          Enabled -> 
           plotType == "impulse" || plotType == "step" || 
            plotType == "ramp" || plotType == "cos(2\[Pi]fn)" || 
            plotType == 
             "\!\(\*SuperscriptBox[\(\[ExponentialE]\), \
\(-n\)]\)cos(2\[Pi]fn)"}]
        }
       }, Frame -> True, 
      FrameStyle -> Directive[Thickness[.001], Gray], 
      Spacings -> {.5, .1}, Alignment -> Left],
     
     Grid[{
       {Text@Style["conversion method", 12]},
       {Control[{ {conversionType, "BilinearTransform", 
           ""}, (#[[2]] -> 
              Text@Style[#[[2]], 11]) & /@ {"FirstOrderHold" -> 
             "FirstOrderHold", "ZeroOrderHold" -> "ZeroOrderHold", 
            "ZeroPoleMapping" -> "ZeroPoleMapping", 
            "BilinearTransform" -> "BilinearTransform", 
            "BackwardRectangularRule" -> "BackwardRectangularRule", 
            "ForwardRectangularRule" -> "ForwardRectangularRule"},
          ControlType -> PopupMenu, ImageSize -> All}]
        }
       }, Frame -> True, 
      FrameStyle -> Directive[Thickness[.001], Gray], 
      Spacings -> {0, 0.3}],
     
     Button[
      Text@Style["init", 10], {showGrid = True; showToolTip = False; 
       gridSpacing = 0.1; ts = 1; showPlotsGrid = True; 
       simulationTime = 25; rootLocusK = 2; 
       bodePhaseScales = {"Linear", "Degree"}; 
       bodeMagScales = {"Linear", "Absolute"}; plotType = "impulse"; 
       poles = {{0.7, .1}, {1.3, .1}, {1.3, .3}, {1.3, .5}}; 
       zeros = {{0, 0}, {-1.3, .1}, {-1.3, .3}, {-1.3, .5}}}, 
      ImageSize -> {30, 50}]
     
     }}, Frame -> None, 
   FrameStyle -> Directive[Thickness[.001], Gray], 
   Spacings -> {.1, 0}, Alignment -> Center
   ], ControlPlacement -> Bottom],
 
 {{POLE, 2}, ControlType -> None},
 {{ZERO, 3}, ControlType -> None},
 {{poles, {{0.2, 0.8}, {1.3, .1}, {1.3, .3}, {1.3, .5}}}, 
  ControlType -> None},
 {{zeros, {{0.0, 0.0}, {-1.3, .1}, {-1.3, .3}, {-1.3, .5}}}, 
  ControlType -> None},
 {{ext, 1.2}, ControlType -> None},
 {{del, 0.1}, ControlType -> None},(*grid size*)
 
 {{statusOfConversion, True}, ControlType -> None},
 {{statusMessage, ""}, ControlType -> None},
 {{polesInSPlane, {}}, ControlType -> None},
 {{zerosInSPlane , {}}, ControlType -> None},
 {{internalPoles, {{1, {0.2, 0.8}}}}, ControlType -> None},
 {{internalZeros, {{1, {0.0, 0.0}}}}, ControlType -> None},
 {{hz, z/(z^2 - 0.4 z + 0.68)}, ControlType -> None},
 {{mousePos, 0}, ControlType -> None},
 {{processResult, {}}, ControlType -> None},
 
 (*This below is initialized here for proper use with AutoRunSequence*)
\

 {{formatedTransferFunctions, Grid[{
     {Graphics[
       Text@
        Row[{ Style["H(z)", Italic, 12], Style[" = "], 
          Style["\!\(\*FractionBox[\(z\), \(\*SuperscriptBox[\(z\), \
\(2\)] - 0.4  z + 0.68\)]\)", 14], Style[" ROC |", 9], 
          Style["z", Italic, 12], Style["| > ", 12], 0.825, 
          Style[" " <> "stable", 12]}], ImageSize -> {527, 28}
       ]
      },
     {
      Graphics[
       Text@Row[{Style["H(s)", Italic, 12], Style[" = "], 
          Style["\!\(\*FractionBox[\(1 - 0.25 \*SuperscriptBox[\(s\), \
\(2\)]\), \(0.52 \*SuperscriptBox[\(s\), \(2\)] + 0.32  s + \
1.28\)]\)", 14]}], ImageSize -> {527, 30}]
      },
     {
      Graphics[
       Text@Row[{Style["0.52 y''(t)+0.32 y(t)+1.28 y(t)", 10]}], 
       ImageSize -> {527, 15}]
      }
     }, Spacings -> 0, Frame -> None]}, ControlType -> None},
 
 TrackedSymbols :> {pointType, showGrid, showToolTip, gridSpacing, 
   responseJoined, responseGrid, showPlotsGrid, showStabilityMargins, 
   addContResponse, plotType, mousePos, useClosedLoop, 
   forcingFrequency},
 
 ImageMargins -> 0,
 Alignment -> Center,
 FrameMargins -> 0,
 ContinuousAction -> True,
 AutoAction -> False,
 SynchronousUpdating -> True,
 ContentSize -> Automatic,
 AutorunSequencing -> {{13, 1}},
 
 Initialization :> 
  (
   $MinPrecision = $MachinePrecision;
   $MaxPrecision = $MachinePrecision;
   
   (*---------------------------------------------------------*)
   makeHz[internalPoles_List,
     internalZeros_List,
     z_,
     useClosedLoop_ /; Element[useClosedLoop, Booleans]] := 
    Module[{num, den, numCoeffList, denCoeffList, plant},
     den = 
      Replace[internalPoles, {o_, {x_, y_}} :> (z - (x + I y))^o, {1}];
     num = 
      Replace[internalZeros, {o_, {x_, y_}} :> (z - (x + I y))^o, {1}];
     
     numCoeffList = Chop@CoefficientList[Expand@Apply[Times, num], z];
     denCoeffList = Chop@CoefficientList[Expand@Apply[Times, den], z];
     
     plant = 
      Expand@FromDigits[Reverse[numCoeffList], z]/
       Expand@FromDigits[Reverse[denCoeffList], z];
     
     If[useClosedLoop, Simplify[plant/Expand[1 + plant]], plant]
     ];
   
   (*---------------------------------------------------------*)
   (*input format {order,{x,y}}*)
   polesAndZerosAsList[p_List, z_List] := {
     Flatten[Replace[p, {n_, {x_, y_}} :> Table[{x, y}, {n}], {1}], 
      1], Flatten[
      Replace[z, {n_, {x_, y_}} :> Table[{x, y}, {n}], {1}], 1]
     };
   
   (*---------------------------------------------------------*)
   getContinuouseTimeTFfromHz[{z_, s_, t_, y_},
     hz_,
     conversionType_String,
     ts_?(NumberQ[#] && Positive[#] &),
     poles_List,
     zeros_List] := 
    Module[{tf, sys, statusOfConversion = True, statusMessage = "", 
      polesInSPlane = {}, zerosInSPlane = {}, poly, num, den, lap, 
      out, odeOutput, numberOfPoles, numberOfZeros},
     
     tf = TransferFunctionModel[1.*hz, z, SamplingPeriod -> ts];
     numberOfPoles = Length[poles[[All, 2]]];
     numberOfZeros = Length[zeros[[All, 2]]];
     
     If[ Length[
         Cases[poles, {xx_, yy_} /; ( 
            Abs[yy] < $MachineEpsilon && xx <= 0)]] > 0 || 
       numberOfZeros > numberOfPoles,
      (
       If[conversionType == "ZeroOrderHold", 
        (
         statusOfConversion = False;
         statusMessage = 
          "Warning: Negative pure real pole using ZeroOrderHold \
detected"
         )
        ]
       ),
      (
       If[
        Length[Cases[
           poles, {xx_, yy_} /; ( 
             Abs[yy] < $MachineEpsilon && (Abs[
                 xx - 1] < $MachineEpsilon))]] > 0,
        If[
         conversionType == "ZeroOrderHold" || 
          conversionType == "FirstOrderHold", 
         (
          statusOfConversion = False;
          
          statusMessage = 
           "Warning: Pole at 1 using ZeroOrderHold or FirstOrderHold \
detected"
          )
         ]
        ]
       )
      ];
     
     If[statusOfConversion == False,
      (
       odeOutput = "";
       out = Style[statusMessage, Red, 10]
       ),
      (
       sys = ToContinuousTimeModel[tf, s, Method -> conversionType];
       lap = Chop@Expand@Denominator@First@sys[s][[1]];
       
       If[lap === 1,
        (
         polesInSPlane = {0, 0};
         zerosInSPlane = {0, 0}
         ),
        (
         polesInSPlane = s /. NSolve[lap == 0, s];
         If[polesInSPlane === s, polesInSPlane = {0, 0}];
         zerosInSPlane = 
          s /. NSolve[Chop@Expand@Numerator@First@sys[s][[1]] == 0, s];
         If[zerosInSPlane === s, zerosInSPlane = {0, 0}]
         )
        ];
       
       odeOutput = InverseLaplaceTransform[lap, s, t];
       odeOutput = 
        ReplaceAll[
         odeOutput, {a_. DiracDelta[t] :> round[Chop@a, 2] y[t], 
          b_. Derivative[n_][DiracDelta][t] :> 
           round[Chop@b, 2] Derivative[n][y][t]}];
       
       poly = First@sys;
       num = First@CoefficientRules[First@poly[[1]], s];
       num = 
        Table[num[[i, 1]] -> round[Chop@num[[i, 2]], 2], {i, 1, 
          Length[num]}];
       
       den = poly[[2]];
       den = CoefficientRules[First@Flatten[{den}], s];
       den = 
        Table[den[[i, 1]] -> round[Chop@den[[i, 2]], 2], {i, 1, 
          Length[den]}];
       out = FromCoefficientRules[num, s]/FromCoefficientRules[den, s]
       )
      ];
     
     {tf, sys, statusOfConversion, statusMessage, polesInSPlane , 
      zerosInSPlane, out, odeOutput}
     ];
   
   (*---------------------------------------------------------*)
   formatTransferFunctions[{z_, s_, y_, t_},
     internalPoles_List,
     internalZeros_List,
     hz_,
     conversionType_String,
     ts_?(NumberQ[#] && Positive[#] &)
     ] := 
    Module[{largestPole, stable, poles, zeros, tf, sys, out, 
      odeOutput, fontSize = 12, statusOfConversion, statusMessage, 
      zerosInSPlane, polesInSPlane},
     
     {poles, zeros} = 
      polesAndZerosAsList[internalPoles, internalZeros];
     
     {tf, sys, statusOfConversion, statusMessage, polesInSPlane , 
       zerosInSPlane, out, odeOutput} = 
      getContinuouseTimeTFfromHz[{z, s, t, y}, hz, conversionType, ts,
        poles, zeros];
     
     largestPole = Max[Norm[#] & /@ poles];
     
     Which[largestPole < 1, stable = "stable",
      Abs[largestPole - 1] <= $MachineEpsilon, stable = "marginal",
      True, stable = "unstable"
      ];
     
     {
      Grid[{
        {Graphics[
          
          Text@Row[{ Style["H(z)", Italic, fontSize], Style[" = "], 
             Style[NumberForm[hz, 3], 16], Style[" ROC |", fontSize], 
             Style["z", Italic, fontSize], Style["| > ", fontSize], 
             NumberForm[largestPole, 3], 
             Style[" " <> stable, fontSize]}], ImageSize -> {527, 28}
          ]
         },
        {
         Graphics[
          Text@Row[{Style["H(s)", Italic, fontSize], Style[" = "], 
             Style[out, 16]}], ImageSize -> {527, 30}]
         },
        
        {
         Graphics[Text@Row[{Style[odeOutput, 10]}], 
          ImageSize -> {527, 15}]
         }
        
        }, Spacings -> 0, Frame -> None]
      , tf, sys, statusOfConversion, statusMessage, polesInSPlane , 
      zerosInSPlane 
      }
     ];
   
   (*---------------------------------------------------------*)
   formatRadialLine[pt_, ts_?(NumberQ[#] && Positive[#] &)] := 
    Module[{norm, line, text, point, angle, displayedAngle, offset, 
      at},
     
     norm = Norm[pt];
     
     If[pt === None ,
      (
       line = Line[{{0, 0}, {0, 0}}];
       text = Text["", {0, 0}];
       point = {PointSize[0], Point[{0, 0}]}
       )
      ,
      (
       angle = ArcTan[pt[[1]], pt[[2]]];
       displayedAngle = angle;
       
       If[angle <= 0.0, displayedAngle = 2 Pi + angle];
       Which[displayedAngle >= 3/2 Pi || displayedAngle <= Pi/2, 
        offset = {1.3, 0},
        displayedAngle > Pi/2 || displayedAngle < 3/2 Pi, 
        offset = {-1.3, 0}
        ];
       
       If[norm > 0.8 && norm < 1.2,
        (
         at = {Cos[angle], Sin[angle]};
         line = {Thick, Dashed, Red, Arrow[{{0, 0}, at}]};
         point = {PointSize[0.03], Blue, Point[at]};
         text = Text[Grid[{
             {Row[{Style[NumberForm[(1/(2 Pi ts))*displayedAngle, 3], 
                 12, Red], Style[" hz", 10]}]}
             }, Spacings -> {0.1, 0.1}, Alignment -> Left, 
            Frame -> None], at, offset]
         ),
        (
         line = Line[{{0, 0}, {0, 0}}];
         text = Text["", {0, 0}];
         point = {PointSize[0], Point[{0, 0}]}
         )
        ]
       )
      ];
     
     {line, text, point}
     ];
   
   (*---------------------------------------------------------*)
   round2[digit_, delta_?(IntegerQ[#] && Positive[#] &)] := 
    Module[{f, d, dd, r, res},
     
     If[Abs[digit] <= $MachineEpsilon,
      (
       res = digit
       ),
      (
       f = FractionalPart[digit];
       d = RealDigits[f, 10, 10];
       r = Flatten[Prepend[d[[1]], Table[0, {Abs[d[[2]] ]}]]];
       
       dd = If[Length[r] <= delta, FromDigits[r]/10^Length[r],
         Round[ FromDigits[r[[1 ;; delta + 1]]]/10^(delta + 1), 
          1/10^delta]
         ];
       res = N[IntegerPart[digit] + Sign[digit]*dd]
       )
      ];
     
     If[res == 1.0, res = 1];
     If[res == -1.0, res = -1];
     
     res
     ];
   
   (*---------------------------------------------------------*)
   round[digit_, delta_?(IntegerQ[#] && Positive[#] &)] := Module[{},
     Chop@round2[N@Re[digit], delta] + 
      Chop@round2[N@Im[digit], delta] I
     ];
   
   (*---------------------------------------------------------*)
   padIt1[v_?(NumberQ[#] &), f_List] := 
    AccountingForm[Chop[v] , f, NumberSigns -> {"", ""}, 
     NumberPadding -> {"0", "0"}, SignPadding -> True
     ];
   
   (*---------------------------------------------------------*)
   padIt2[v_?(NumberQ[#] &), f_List] := 
    AccountingForm[Chop[v] , f, NumberSigns -> {"-", "+"}, 
     NumberPadding -> {"0", "0"}, SignPadding -> True
     ];
   
   (*---------------------------------------------------------*)
   findInternalPoints[points_List, 
     ext_?(NumberQ[#] && Positive[#] &)] := Module[{pointsFound},
     
     (*find points inside region*)
     pointsFound = 
      Cases[points, {x_, y_} /; (Abs[x] - ext) <= $MachineEpsilon];
     
     (*generate order, convert {x,y} to {order,{x,y}} *)
     pointsFound = 
      Union[
       Replace[pointsFound, {x_, 
          y_} :> {Length[Cases[pointsFound, {x, y}]], {x, y}}, {1}]];
     
     (*add complex conjugate points*)
     Replace[
      pointsFound, {o_, {x_, y_}} /; y > 0.0 :> 
       Sequence[{o, {x, y}}, {o, {x, -y}}], {1}]
     
     ];
   
   (*-----------------------------------*)
   findExternalPoints[points_List, 
     ext_?(NumberQ[#] && Positive[#] &)] := Module[{pointsFound},
     
     pointsFound = Cases[points, {x_, y_} /; Abs[x] > ext];
     
     (*add complex conjugate points*)
     Union[
      Replace[pointsFound, {x_, 
         y_} :> {Length[Cases[pointsFound, {x, y}]], {x, y}}, {1}]
      ]
     ];
   
   (*---------------------------------------------------------*)
   format[poles_List, zeros_List, 
     ext_?(NumberQ[#] && Positive[#] &)] := Module[{p, z},
     
     padIt1[x_] := NumberForm[N[x], 3];
     
     p = Join[findInternalPoints[poles, ext], 
       findExternalPoints[poles, ext]];
     z = Join[findInternalPoints[zeros, ext], 
       findExternalPoints[zeros, ext]];
     
     (* each entry in the p and z is now in the form {order,{x,
     y}} *)
     {
      Replace[p, {
        {o_, {x_, y_}} /; o > 1 :>
         Sequence[{Tooltip[
            Text[Style["\[Times]", Red, 16], {x, y}], {padIt1[x], 
             padIt1[y]}]}, {Text[
            Style[o, Blue, 10], {x, y}, {-2, 0}]}],
        {o_, {x_, y_}} :> 
         Tooltip[Text[Style["\[Times]", Red, 16], {x, y}], {padIt1[x],
            padIt1[y]}]}, {1}]
      ,
      Replace[z, {
        {o_, {x_, y_}} /; o > 1 :>
         Sequence[{Tooltip[
            Text[Style["\[EmptyCircle]", Black, 16], {x, y}], {padIt1[
              x], padIt1[y]}]}, {Text[
            Style[o, Blue, 10], {x, y}, {-2, 0}]}],
        {o_, {x_, y_}} :> 
         Tooltip[Text[
           Style["\[EmptyCircle]", Black, 16], {x, y}], {padIt1[x], 
           padIt1[y]}]}, {1}]
      
      }
     ];
   
   (*---------------------------------------------------------*)
   phaseBodePlot[phasePlot_, {xScale_, yScale_}, bodePlotOptions_, 
     bodePhaseTicks_, opt___] := 
    Module[{x, y, yToUse, xToUse, yPlotRange, data, p},
     
     data = Cases[Normal@phasePlot, Line[pts_] -> pts, Infinity];
     
     x = data[[1, All, 1]];
     y = data[[1, All, 2]];
     
     xToUse = x;
     If[yScale == "Degree",
      (
       yToUse = Mod[y, 360, -180];
       yPlotRange = {-180, 180};
       If[xScale == "Linear",
        (
         p = 
          ListPlot[Transpose[{xToUse, yToUse}], 
           Evaluate@bodePlotOptions, Ticks -> Evaluate@bodePhaseTicks,
            Evaluate@opt, PlotRange -> {Automatic, {-200, 200}}]
         ),
        (
         p = ListPlot[Transpose[{xToUse, yToUse}],
           GridLinesStyle -> Black,
           (*Evaluate@First@AbsoluteOptions[phasePlot,GridLines],*)
           PlotRange -> {Automatic, yPlotRange},
           Evaluate@bodePlotOptions,
           Evaluate@opt,
           
           Ticks -> {{{-3, 0.001}, {-2, 0.01}, {-1, 0.1}, {0, 1}, {10,
                1}}, Automatic},
           AxesOrigin -> {Min[xToUse], 0},
           PlotRange -> {Automatic, {-185, 185}}
           ]
         )]
       ),
      (
       yToUse = Mod[y, 2 Pi, -Pi];
       yPlotRange = {-Pi, Pi};
       If[xScale == "Linear",
        (
         p = 
          ListPlot[Transpose[{xToUse, yToUse}], 
           Evaluate@bodePlotOptions, Ticks -> Evaluate@bodePhaseTicks,
            Evaluate@opt, PlotRange -> {Automatic, {-1.2 Pi, 1.2 Pi}}]
         ),
        (
         p = ListPlot[Transpose[{xToUse, yToUse}],
           GridLinesStyle -> Black(*,
           Evaluate@First@AbsoluteOptions[phasePlot,GridLines]*),
           PlotRange -> {Automatic, yPlotRange}, 
           Evaluate@bodePlotOptions, Evaluate@opt, 
           Ticks -> {{{-3, 0.001}, {-2, 0.01}, {-1, 0.1}, {0, 1}, {10,
                1}}, Automatic}, AxesOrigin -> {Min[xToUse], 0}, 
           PlotRange -> {Automatic, {- Pi, Pi}}]
         )
        ]
       )
      ];
     
     p
     ];
   
   (*---------------------------------------------------------*)
   makeBodeDiagrams[mousePtIn_,
     z_,
     ts_?(NumberQ[#] && Positive[#] &),
     bodeMagScales_List,
     bodePhaseScales_List,
     showToolTip_ /; (Element[showToolTip, Booleans]),
     hzIn_,
     tf_,
     showPlotsGrid_ /; (Element[showPlotsGrid, Booleans]),
     showStabilityMargins_ /; (Element[showStabilityMargins, 
        Booleans])] := 
    Module[{bodePhase, bodePlotOptions, yLabelBodeMag, xLabelBodeMag, 
      yLabelBodePhase, xLabelBodePhase, xForBodeMag, yForBodeMag, 
      xForBodePhase, yForBodePhase, bodePlot, w, pt, norm, freq = 0, 
      bodeMagTicks, bodePhaseTicks, scaledFreq, ticks, hz = hzIn, 
      bodeMagTicksX, bodeMagTicksY, xLabel, mousePt = mousePtIn, 
      labelFontSize = 9},
     
     If[Not[showToolTip], mousePt = None];
     
     If[Not[mousePt === None],
      (
       freq = ArcTan[mousePt[[1]], mousePt[[2]]];
       If[freq <= 0.0, freq = 2 Pi + freq];
       norm = Norm[mousePt];
       pt = mousePt
       )
      ,
      (
       norm = Infinity
       )
      ];
     
     If[norm < 0.9 || norm > 1.1, 
      pt = None];(*do not tooltip if far from circle*)
     hz = 
      ReplaceAll[hz, 
       z -> Exp[I*w]];(*needed just for the tracking point *)
     scaledFreq = freq/ts;
     xLabel = 
      Grid[{{Style["\[Omega]", labelFontSize]}, {Style["rad/sec", 
          labelFontSize]}}, Spacings -> {0, -0.2}];
     xLabelBodeMag = xLabel;
     
     (*find tracking point coordinates for Magnitude plot*)
     If[Order[bodeMagScales[[1]], "Linear"] == 0,
      (
       xForBodeMag = scaledFreq;
       bodeMagTicksX = {0, Pi/4, Pi/2, 3/4 Pi, Pi, (5 Pi)/4, (3 Pi)/2,
          7/4 Pi, 2 Pi};
       bodeMagTicksY = Automatic;
       bodeMagTicks = {bodeMagTicksX, bodeMagTicksY}
       ),
      (
       xForBodeMag = Log[10, scaledFreq];
       bodeMagTicksX = Automatic;
       bodeMagTicksY = Automatic;
       bodeMagTicks = {bodeMagTicksX, bodeMagTicksY}
       )
      ];
     
     If[Order[bodeMagScales[[2]], "Absolute"] == 0,
      (
       yLabelBodeMag = Text@Style["|H(\[Omega])|", labelFontSize];
       yForBodeMag = Abs[hz /. w -> freq]
       ),
      (
       yLabelBodeMag = 
        Text@Row[{Style["|H(\[Omega])| dB", labelFontSize]}];
       yForBodeMag = 20*Log[10, Abs[hz /. w -> freq]]
       )
      ];
     
     (*find tracking point coordinates for Phase plot*)
     xLabelBodePhase = xLabel;
     If[Order[bodePhaseScales[[1]], "Linear"] == 0,
      (
       xForBodePhase = scaledFreq;
       bodePhaseTicks = {{0, Pi/4, Pi/2, 3/4 Pi, Pi, (5 Pi)/4, (3 Pi)/
          2, 7/4 Pi, 2 Pi}, Automatic}
       ),
      (
       xForBodePhase = Log[10, scaledFreq];
       bodePhaseTicks = {Automatic, Automatic}
       )
      ];
     
     If[Order[bodePhaseScales[[2]], "Degree"] == 0,
      (
       yLabelBodePhase = Text@Style["phase (deg)", labelFontSize];
       yForBodePhase = Arg[hz /. w -> freq]*180/Pi
       ),
      (
       yLabelBodePhase = Style["phase (rad)", labelFontSize];
       yForBodePhase = Arg[hz /. w -> freq]
       )
      ];
     
     ticks = Ticks -> {bodeMagTicks, bodePhaseTicks};
     
     bodePlotOptions = {If[
        showPlotsGrid, {GridLines -> Automatic, 
         GridLinesStyle -> Directive[{LightGray, Thickness[0.001]}]}, 
        GridLines -> None], PlotStyle -> Red, AspectRatio -> 0.25, 
       PlotRangeClipping -> False};
     
     bodePlot = BodePlot[tf, {0.001, 2*Pi - 0.0001},
       Evaluate@
        If[showStabilityMargins, {StabilityMargins -> True, 
          StabilityMarginsStyle -> {Blue, Blue}}, 
         StabilityMargins -> False],
       Frame -> False,
       ScalingFunctions -> {bodeMagScales, bodePhaseScales},
       Evaluate@bodePlotOptions,
       ImageSize -> {{280, 121}, {280, 121}}, 
       ImagePadding -> {{{25, 30}, {25, 25}}, {{25, 30}, {25, 25}}}, 
       TicksStyle -> {Directive[8], Directive[8]},
       PlotLayout -> "List",
       PlotLabel -> 
        Evaluate@If[pt === None || Not[showToolTip ], {"", ""},
          
          {Row[{Style["\[VerticalSeparator]H(", 10], 
             Style[padIt1[scaledFreq*180/Pi, {5, 2}], 10], 
             Style["\[Degree])\[VerticalSeparator] = ", 10], 
             Style[padIt1[yForBodeMag, {5, 2}], 10]}],
           
           Row[{Style["Arg(H(", 10], 
             Style[padIt1[scaledFreq*180/Pi, {5, 2}], 10], 
             Style["\[Degree]) = ", 10], 
             Style[padIt2[yForBodePhase, {5, 2}], 10]}]
           }
          ],
       Evaluate@ticks,
       PlotRange -> {{Full, Full}, {Full, Full}},
       AxesLabel -> {{xLabelBodeMag, yLabelBodeMag}, {xLabelBodePhase,
           yLabelBodePhase}}];
     
     bodePhase = phaseBodePlot[bodePlot[[2]],
       bodePhaseScales,
       bodePlotOptions,
       bodePhaseTicks,
       {ImageSize -> {280, 121},
        AspectRatio -> 0.33,
        ImagePadding -> {{25, 30}, {5, 25}},
        TicksStyle -> Directive[8],
        Frame -> False,
        Joined -> True,
        Axes -> True,
        AxesLabel -> {xLabelBodePhase, yLabelBodePhase},
        PlotLabel -> Evaluate@If[pt === None || Not[showToolTip ], "",
           
           Row[{Style["Arg(H(", 10], 
             Style[padIt1[scaledFreq*180/Pi, {5, 2}], 10], 
             Style["\[Degree]) = ", 10], 
             Style[padIt2[yForBodePhase, {5, 2}], 10]}]]
        }];
     
     If[pt === None || Not[showToolTip ],
      Grid[{
        {bodePlot[[1]]},
        {bodePhase}
        }, Spacings -> {0, 0}, Frame -> All, 
       FrameStyle -> Directive[Thickness[.001], LightGray], 
       Alignment -> Center],
      Grid[{
        {
         Show[
          bodePlot[[1]],
          
          Graphics[{PointSize[0.03], Blue, 
            Point[{xForBodeMag, yForBodeMag}]}],
          PlotRange -> All
          ]
         },
        {
         Show[
          bodePhase,
          
          Graphics[{PointSize[0.03], Blue, 
            Point[{xForBodePhase, yForBodePhase}]}],
          PlotRange -> All
          ]
         
         }}, Spacings -> {0, 0}, Frame -> All, 
       FrameStyle -> Directive[Thickness[.001], LightGray], 
       Alignment -> Center]
      ]
     ];
   
   (*---------------------------------------------------------*)
   formatSPlane[p_, z_, ts_?(NumberQ[#] && Positive[#] &)] := 
    Module[{},
     {
      Replace[
       p, {x_, y_} :> 
        Tooltip[{PointSize[.2], White, Opacity -> 0, Point[{x, y}]},
         Grid[{
           {Row[{Style["(", 14], round[Chop@x, 2], Style[" , ", 10], 
              round[Chop@y, 2], Style[")", 14]}], SpanFromLeft},
           {Style["\[Omega] = ", 10], 
            round[(Chop@Norm[{x, y}]*ts)/(2 Pi), 2], 
            Style["hz", Italic, 10]},
           {Style["\[Zeta] = ", 
             10], -round[
              Chop@Cos[If[Abs[x] < $MachineEpsilon, 0, ArcTan[x, y]]],
               2]}
           }, Spacings -> {0, 0}, Alignment -> Left]], {1}]
      ,
      Replace[
       z, {x_, y_} :> 
        Tooltip[{PointSize[.2], White, Opacity -> 0, Point[{x, y}]},
         Grid[{
           {Row[{Style["(", 14], round[Chop@x, 2], Style[" , ", 10], 
              round[Chop@y, 2], Style[")", 14]}]}
           }, Spacings -> {0, 0}, Alignment -> Left]], {1}]
      }
     ];
   
   (*---------------------------------------------------------*)
   gainPhaseMargins[tf_TransferFunctionModel, title_] := 
    Module[{phasecross, gaincross, g, roundDelta = 3, len, 
      emptySpace = Text@Style[" ", 12]},
     g = GainPhaseMargins[tf];
     phasecross = g[[1]];
     gaincross = g[[2]];
     
     phasecross = 
      Replace[
       phasecross, {{None, y_} :> {Text@Style["None", 12], 
          Text@Style[y, 12]}, {x_, 
          y_} :> {Text@Style[round2[x/(2*Pi), roundDelta], 12], 
          Text@Style[round2[y, roundDelta], 12]}}, {1}];
     
     PrependTo[
      phasecross, {Text@Style["phase crossover (hz)", 12], 
       Text@Style["gain margins", 12]}];
     len = Length[phasecross];
     If[len < 5, 
      Table[AppendTo[phasecross, {emptySpace, emptySpace}], {i, 1, 
        5 - len}]];
     
     
     
     gaincross = 
      Replace[gaincross, {{None, y_} :> {Text@Style["None", 12], 
          Text@Style[y, 12]}, {x_, 
          y_} :> {Text@Style[round2[x/(2*Pi), roundDelta], 12], 
          Text@Style[round2[y*180/Pi, roundDelta], 12]}}, {1}];
     
     PrependTo[
      gaincross, {Text@Style["gain crossover (hz)", 12], 
       Text@Style["phase margins (deg)", 12]}];
     len = Length[gaincross];
     If[len < 5, 
      Table[AppendTo[gaincross, {emptySpace, emptySpace}], {i, 1, 
        5 - len}]];
     
     Grid[{
       {title},
       {Grid[phasecross, Alignment -> Left, Spacings -> {.4, .2}, 
         Frame -> All, 
         FrameStyle -> Directive[Thickness[.001], Gray]]},
       {Grid[gaincross, Alignment -> Left, Spacings -> {.4, .2}, 
         Frame -> All, FrameStyle -> Directive[Thickness[.001], Gray]]}
       }, Frame -> None, Alignment -> Left, Spacings -> {0, 1}]
     
     ];
   
   (*---------------------------------------------------------*)
   process[z_,
     ts_?(NumberQ[#] && Positive[#] &),
     plotType_String,
     simulationTime_?(NumberQ[#] && Positive[#] &),
     rootLocusK_?(IntegerQ[#] &),
     bodeMagScales_List,
     bodePhaseScales_List,
     mousePt_,
     showToolTip_ /; (Element[showToolTip, Booleans]),
     responseJoined_ /; (Element[responseJoined, Booleans]),
     showPlotsGrid_ /; (Element[showPlotsGrid, Booleans]), 
     showStabilityMargins_ /; (Element[showStabilityMargins, 
        Booleans]),
     tf_,
     sys_,
     ppoles_List,
     zzeros_List,
     hz_,
     addContResponse_ /; (Element[addContResponse, Booleans]),
     statusOfConversion_,
     statusMessage_String,
     polesInSPlane_List,
     zerosInSPlane_List,
     conversionType_String,
     forcingFrequency_?(NumberQ[#] &)] := 
    Module[{input, res, largestPole, numberOfZeros, numberOfPoles, n, 
      imageSize = {280, 240}, t, contResponse, poles, zeros, labels, 
      okToDisplayContPlot = True, discretePlotOptions, 
      analogPlotOptions},
     
     {poles, zeros} = polesAndZerosAsList[ppoles, zzeros];
     
     (*do not display analog repsonse for Bilinear when poles<-1*)
     If[Length[Cases[poles, {x_, y_} /; x <= -1]] > 0,
      If[conversionType == "BilinearTransform" || 
        conversionType == "BackwardRectangularRule",
       okToDisplayContPlot = False
       ]
      ];
     
     If[Length[Cases[poles, {x_, y_} /; x <= 0]] > 0 && 
       conversionType == "BackwardRectangularRule",
      okToDisplayContPlot = False
      ];
     
     largestPole = Max[Norm[#] & /@ poles];
     numberOfPoles = Length[poles];
     numberOfZeros = Length[zeros];
     
     If[numberOfZeros > numberOfPoles,
      Framed[
       Text@Grid[{
          {Style["Warning:", Red, 12]}
          , {Row[{Style["number of zeros (", 12], numberOfZeros, 
             Style[")", 12]}]}
          , {Row[{Style["is larger than number of poles (", 12], 
             numberOfPoles, ")."}]}
          , {Style["Not a physical system.", 12]}
          }, Spacings -> {0, 0}, Alignment -> Left]
       ],
      {
       discretePlotOptions = {Evaluate@
          If[responseJoined, 
           Sequence[{Joined -> True, 
             InterpolationOrder -> 0}], {Filling -> Axis, 
            FillingStyle -> Red, 
            PlotMarkers -> 
             Graphics[{PointSize[0.05], Point[{0, 0}]}]}],
         Evaluate@
          If[showPlotsGrid, {GridLines -> Automatic, 
            
            GridLinesStyle -> 
             Directive[{LightGray, Thickness[0.001]}]}, 
           GridLines -> None],
         PlotRange -> All,
         ImageSize -> imageSize,
         ImagePadding -> {{40, 10}, {35, 10}},
         AspectRatio -> 0.8,
         AxesOrigin -> {0, 0},
         FrameLabel -> {{None, None}, {Text[Style["time (sec)", 10]], 
            None}},
         Frame -> True,
         PlotStyle -> Red,
         FrameTicksStyle -> Directive[Black, 8],
         Axes -> None,
         DataRange -> {0, simulationTime}};
       
       analogPlotOptions = {Joined -> True, InterpolationOrder -> 0,
         PlotRange -> All,
         ImageSize -> imageSize,
         ImagePadding -> {{40, 10}, {35, 10}},
         AspectRatio -> 0.9,
         AxesOrigin -> {0, 0},
         PlotStyle -> {Dashed, Black},
         FrameTicksStyle -> Directive[Black, 8],
         DataRange -> {0, simulationTime},
         Axes -> None};
       
       Which[plotType == "Bode",
        (
         makeBodeDiagrams[mousePt, z, ts, bodeMagScales, 
          bodePhaseScales, showToolTip, hz, tf, showPlotsGrid, 
          showStabilityMargins]
         ),
        
        plotType == "root Locus",
        (
         RootLocusPlot[
          TransferFunctionModel[n hz, z, SamplingPeriod -> ts], {n, 0,
            rootLocusK}, AspectRatio -> 0.7, 
          PlotRange -> {{-2, 2}, {-2, 2}}, 
          PoleZeroMarkers -> {Text[Style["\[Times]", Red, 16]], 
            Automatic, Text[Style["\[EmptyCircle]", Black, 16]]}, 
          ImageSize -> imageSize, 
          ImagePadding -> {{30, 10}, {25, 30}}, 
          PerformanceGoal -> "Speed", MaxRecursion -> 1, 
          Method -> "NDSolve", PlotPoints -> 7]
         ),
        
        plotType == "Nyquist",
        (
         Quiet[
          NyquistPlot[tf, {-Pi, Pi}, 
           ImagePadding -> {{30, 30}, {25, 30}}, Exclusions -> True, 
           PlotRange -> Automatic, ImageSize -> imageSize, 
           AxesLabel -> {"Re", "Im"}, 
           
           Evaluate@
            If[showPlotsGrid, NyquistGridLines -> Automatic, 
             NyquistGridLines -> None], PlotStyle -> Red, 
           PerformanceGoal -> "Speed", MaxRecursion -> 1, 
           Method -> "NDSolve", PlotPoints -> Automatic, 
           Evaluate@
            If[showStabilityMargins, {StabilityMargins -> True, 
              StabilityMarginsStyle -> Blue}, 
             StabilityMargins -> False], AspectRatio -> 1]]
         ),
        
        plotType == "Nichols",
        (
         NicholsPlot[tf, {-Pi, Pi},
          
          Evaluate@
           If[showPlotsGrid, NicholsGridLines -> Automatic, 
            NicholsGridLines -> None],
          ImagePadding -> {{30, 40}, {25, 30}},
          ScalingFunctions -> {"Degree", "Absolute"},
          
          AxesLabel -> {Text@
             Column[{Style["phase", 10], Style["(deg)", 10]}, 
              Alignment -> Center], Text[Style["magnitude", 10]]}, 
          ImageSize -> imageSize,
          PlotStyle -> Red,
          AspectRatio -> 0.8,
          PerformanceGoal -> "Speed", MaxRecursion -> 1, 
          Method -> "NDSolve",
          
          Evaluate@
           If[showStabilityMargins, {StabilityMargins -> True, 
             StabilityMarginsStyle -> Blue}, 
            StabilityMargins -> False]]
         ),
        
        plotType == "impulse",
        (
         res = 
          First@Simplify@
            OutputResponse[tf, 
             DiscreteDelta[n], {n, 0, Ceiling[simulationTime/ts]}];
         
         If[okToDisplayContPlot,
          (
           If[addContResponse && statusOfConversion,
            (
             
             contResponse = 
              Chop@First@
                Simplify@
                 OutputResponse[sys, 
                  DiracDelta[t], {t, 0, simulationTime}]
             )
            ,
            contResponse = {}
            ]
           ),
          contResponse = {}
          ];
         
         Show[
          ListPlot[res, Sequence@discretePlotOptions],
          
          Plot[ts*contResponse, {t, 0, simulationTime }, 
           PlotRange -> All],
          PlotRange -> All
          ]
         
         ),
        
        plotType == "step",
        (
         input = 
          Table[{n, UnitStep[n]}, {n, 0, Ceiling[simulationTime/ts]}];
         res = 
          First@Simplify@
            OutputResponse[tf, UnitStep[n], {n, 0, simulationTime}];
         
         If[okToDisplayContPlot,
          (
           If[addContResponse && statusOfConversion,
            
            contResponse = 
             Chop@First@
               OutputResponse[sys, UnitStep[t], {t, 0, simulationTime}]
            ,
            contResponse = {}
            ]
           ),
          contResponse = {}
          ];
         
         Show[
          
          ListPlot[res, Sequence@discretePlotOptions],
          ListPlot[input[[All, 2]], Sequence@analogPlotOptions],
          
          Plot[contResponse, {t, 0.001, simulationTime}, 
           PlotRange -> All],
          PlotRange -> All
          ]
         ),
        
        plotType == "ramp",
        (
         input = Table[{n, n}, {n, 0, Ceiling[simulationTime/ts]}];
         res = Simplify@OutputResponse[tf, input[[All, 2]]][[1]];
         
         If[okToDisplayContPlot,
          (
           If[addContResponse && statusOfConversion,
            (
             
             contResponse = 
              First@Simplify@
                OutputResponse[sys, t UnitStep[t], {t, simulationTime}]
             ),
            (
             contResponse = {}
             )
            ]
           ),
          contResponse = {}
          ];
         
         Show[
          ListPlot[res, Sequence@discretePlotOptions],
          ListPlot[input[[All, 2]], Sequence@analogPlotOptions],
          
          Plot[contResponse, {t, 0.001, simulationTime}, 
           PlotRange -> All],
          PlotRange -> All
          ]
         ),
        
        plotType == "cos(2\[Pi]fn)",
        (
         input = 
          Table[{n, Cos[2 Pi forcingFrequency n]}, {n, 0, 
            Ceiling[simulationTime/ts]}];
         res = Simplify@OutputResponse[tf, input[[All, 2]]][[1]];
         
         If[okToDisplayContPlot,
          (
           If[addContResponse && statusOfConversion,
            (
             
             contResponse = 
              First@Simplify@
                OutputResponse[sys, 
                 Cos[2 Pi forcingFrequency t], {t, 0, simulationTime}]
             ),
            (
             contResponse = {}
             )
            ]
           ),
          contResponse = {}
          ];
         
         Show[
          ListPlot[res, Sequence@discretePlotOptions],
          ListPlot[input[[All, 2]], Sequence@analogPlotOptions],
          Plot[contResponse, {t, 0, simulationTime}, PlotRange -> All],
          PlotRange -> All
          ]
         
         ),
        
        plotType == 
         "\!\(\*SuperscriptBox[\(\[ExponentialE]\), \(-n\)]\)cos(2\
\[Pi]fn)",
        (
         input = 
          Table[{n, Exp[-n] Cos[2 Pi forcingFrequency n]}, {n, 0, 
            Ceiling[simulationTime/ts]}];
         res = Simplify@OutputResponse[tf, input[[All, 2]]][[1]];
         
         If[okToDisplayContPlot,
          (
           If[addContResponse && statusOfConversion,
            (
             
             contResponse = 
              First@Simplify@
                OutputResponse[sys, 
                 Exp[-t] Cos[2 Pi forcingFrequency t], {t, 0, 
                  simulationTime}]
             ),
            (
             contResponse = {}
             )
            ]
           ),
          contResponse = {}
          ];
         
         Show[
          ListPlot[res, Sequence@discretePlotOptions],
          ListPlot[input[[All, 2]], Sequence@analogPlotOptions],
          Plot[contResponse, {t, 0, simulationTime}, PlotRange -> All],
          PlotRange -> All
          ]
         ),
        
        plotType == "H(z) margins",
        (
         gainPhaseMargins[tf, 
          Text@Style["discrete system gain phase margins", 12]]
         ),
        plotType == "H(s) margins",
        (
         gainPhaseMargins[sys, 
          Text@Style["continuous system gain phase margins", 12]]
         ),
        
        plotType == "S-plane map",
        (
         If[statusOfConversion,
          (
           sPoles = Replace[polesInSPlane, x_ :> {Re[x], Im[x]}, {1}];
           sZeros = Replace[zerosInSPlane, x_ :> {Re[x], Im[x]}, {1}];
           labels = formatSPlane[sPoles, sZeros, ts];
           
           Show[
            ListPlot[{sPoles, sZeros},
             AxesOrigin -> {0, 0},
             
             PlotMarkers -> {Style["\[Cross]", 18, Bold, Red], 
               Style["\[EmptyCircle]", 16, Bold, Red]}, 
             PlotRange -> {Automatic, Automatic},
             ImageSize -> imageSize,
             ImagePadding -> {{45, 45}, {25, 25}},
             Frame -> False,
             Axes -> True,
             AxesStyle -> Thick,
             Ticks -> None,
             PlotRangeClipping -> False,
             GridLines -> Automatic,
             
             GridLinesStyle -> {{Thickness[0.005], 
                LightGray}, {Thickness[0.005], LightGray}},
             AspectRatio -> 1,
             
             AxesLabel -> {Text@
                Row[{Style["Re(", 10], Style["s", Italic, 10], 
                  Style[")", 10]}], 
               Text@Row[{Style["Im(", 10], Style["s", Italic, 10], 
                  Style[")", 10]}]},
             ImageMargins -> 0, Epilog -> {labels}],
            PlotRange -> All
            ]
           ),
          (
           
           Graphics[Text[Style[statusMessage, Red, 10]], 
            ImageSize -> imageSize]
           )
          ]
         
         )
        ]
       }
      ]
     ];
   )
 ]