% MIIR IIR filter object class constructor.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% DESCRIPTION: MIIR IIR filter object class constructor.
%              Create a miir object.
%
%
% CONSTRUCTORS:
%
%       f = miir()              - creates an empty miir object.
%       f = miir(fi)            - creates a copy of the input miir object, fi.
%       f = miir(pzm)           - creates a miir object from a pole/zero model
%       f = miir(pf)            - creates a vector of miir objects from a parfrac model
%       f = miir(a,b,fs)        - creates a miir object from the coefficient
%                                 vectors 'a' and 'b' **.
%                                 The sample rate for which the filter is
%                                 designed should be specified as well.
%       f = miir('foo_iir.fil') - create a miir object from a
%                                 LISO IIR .fil file.
%       f = miir('foo_iir.xml') - create a miir object loading the miir object
%                                 from disk.
%       f = miir('foo_iir.mat') - create a miir object loading the miir object
%                                 from disk.
%       f = miir(pl)            - create a miir object from the description
%                                 given in the parameter list.
%
%
% EXAMPLE 1:   Create an order 1 highpass filter with high frequency gain 2.
%              Filter is designed for 10 Hz sampled data and has a cut-off
%              frequency of 0.2 Hz.
%
%              >> pl = plist('type', 'highpass', ...
%                            'order', 1,         ...
%                            'gain',  2.0,       ...
%                            'fs',    10,        ...
%                            'fc',    0.2);
%              >> f = miir(pl)
%
% NOTES:    ** The convention used here for naming the filter coefficients is
%              the opposite to MATLAB's convention. The recursion formula
%              for this convention is
%
%              b(1)*y(n) = a(1)*x(n) + a(2)*x(n-1) + ... + a(na+1)*x(n-na)
%                           - b(2)*y(n-1) - ... - b(nb+1)*y(n-nb)
%
% <a href="matlab:utils.helper.displayMethodInfo('miir', 'miir')">Parameters Description</a>
%
%
% VERSION:     $Id: miir.m,v 1.130 2011/08/15 12:22:57 hewitson Exp $
%
% SEE ALSO:    mfir, ltpda_filter, ltpda_uoh, ltpda_uo, ltpda_obj, plist
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

classdef miir < ltpda_filter
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                            Property definition                            %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  
  %---------- Public (read/write) Properties  ----------
  properties
  end
  
  %---------- Protected read-only Properties ----------
  properties (SetAccess = protected)
    b       = []; % set of denominator coefficients
    histin  = []; % input history values to filter
  end
  
  %---------- Protected read-only Properties ----------
  properties (SetAccess = protected, Dependent = true)
    ntaps % number of coefficients in the filter
  end
  
  %---------- Private Properties ----------
  properties (GetAccess = protected, SetAccess = protected)
  end
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                          Check property setting                           %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  
  methods
    function set.histin(obj, val)
      if ~isempty(val)
        if ~isnumeric(val) || ~isreal(val)
          error('### The value for the property ''histin'' must be a real number(s)');
        end
      end
      obj.histin = val;
    end
    function set.b(obj, val)
      if ~isempty(val)
        if ~isnumeric(val)
          error('### The value for the property ''b'' must be a number(s)');
        end
      end
      obj.b = val;
    end
    function set.ntaps(obj, val)
      error('### Don''t set the property ''ntaps''. It is computed by max(length(a), length(b)).');
    end
  end
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                     Compute the Dependent properties                      %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  
  methods
    function val = get.ntaps(obj)
      val = max(length(obj.a), length(obj.b));
    end
  end
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                Constructor                                %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  
  methods
    function obj = miir(varargin)
      
      import utils.const.*
      utils.helper.msg(msg.PROC3, 'running %s/%s', mfilename('class'), mfilename);
      
      % Collect all miir objects
      [fs, invars, rest] = utils.helper.collect_objects(varargin(:), 'miir');
      
      if isempty(rest) && ~isempty(fs)
        % Do copy constructor and return
        utils.helper.msg(msg.OPROC1, 'copy constructor');
        obj = copy(fs, 1);
        for kk=1:numel(obj)
          obj(kk).addHistory(miir.getInfo('miir', 'None'), [], [], obj(kk).hist);
        end
        return
      end
      
      if nargin == 0
        %%%%%%%%%%  f = miir()   %%%%%%%%%%
        utils.helper.msg(msg.OPROC1, 'empty constructor');
        obj.addHistory(miir.getInfo('miir', 'None'), plist(), [], []);
        
      elseif nargin == 1
        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        %%%%%%%%%%%%%%%%%%%%%%%%%%%   one input   %%%%%%%%%%%%%%%%%%%%%%%%%%%
        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        
        if ischar(varargin{1})
          %%%%%%%%%%  f = miir('foo.mat')   %%%%%%%%%%
          %%%%%%%%%%  f = miir('foo.xml')   %%%%%%%%%%
          utils.helper.msg(msg.OPROC1, 'constructing from file %s', varargin{1});
          obj = fromFile(obj, plist('filename', varargin{1}));
          
        elseif isstruct(varargin{1})
          %%%%%%%%%%  f = miir(struct)   %%%%%%%%%%
          utils.helper.msg(msg.OPROC1, 'constructing from struct');
          obj = fromStruct(obj, varargin{1});
          
        elseif isa(varargin{1}, 'parfrac')
          %%%%%%%%%%  f = miir(plist-object)   %%%%%%%%%%
          utils.helper.msg(msg.OPROC1, 'constructing from parfrac');
          obj = fromParfrac(obj, plist('parfrac', varargin{1}));
          
        elseif isa(varargin{1}, 'pzmodel')
          %%%%%%%%%%  f = miir(pzmodel-object)   %%%%%%%%%%
          utils.helper.msg(msg.OPROC1, 'constructing from pzmodel %s', varargin{1}.name);
%           obj = fromPzmodel(obj, plist('pzmodel', varargin{1}));
          obj = fromPzmodel(obj, varargin{1}, []); 
          
        elseif isa(varargin{1}, 'plist')
          %%%%%%%%%%  f = miir(plist-object)   %%%%%%%%%%
          pl       = varargin{1};
          
          % Selection of construction method
          if pl.isparam('filename')
            utils.helper.msg(msg.OPROC1, 'constructing from file %s', pl.find('filename'));
            obj = fromFile(obj, pl);
            
          elseif pl.isparam('hostname') || pl.isparam('conn')
            utils.helper.msg(msg.OPROC1, 'constructing from repository %s', pl.find('hostname'));
            obj = obj.fromRepository(pl);
            
          elseif pl.isparam('delay')
            
            utils.helper.msg(msg.OPROC1, 'constructing allpass');
            obj = fromAllpass(obj, pl);
            
          elseif pl.isparam('type')
            utils.helper.msg(msg.OPROC1, 'constructing from standard %s', pl.find('type'));
            obj = fromStandard(obj, pl);
            
          elseif pl.isparam('pzmodel')
            utils.helper.msg(msg.OPROC1, 'constructing from pzmodel');
            obj = fromPzmodel(obj, [], pl);
%             obj = fromPzmodel(obj, pl);
            
          elseif pl.isparam('a')
            utils.helper.msg(msg.OPROC1, 'constructing from A/B coefficients');
            obj = fromAB(obj, pl);
            
          elseif pl.isparam('parfrac')
            utils.helper.msg(msg.OPROC1, 'constructing from parfrac object');
            obj = fromParfrac(obj, pl);
            
          elseif pl.isparam('built-in')
            utils.helper.msg(msg.OPROC1, 'constructing from built-in model');
            obj = fromModel(obj, pl);
            
          elseif pl.isparam('plist')
            %--- Construct from plist
            % if the plist is empty, we return an empty MIIR
            ipl = find(pl, 'plist');
            if nparams(ipl) == 0
              obj = miir();
            else
              % do plist constructor
              obj = miir(ipl);
            end
            
          else
            obj.setObjectProperties(pl);
            obj.addHistory(miir.getInfo('miir', 'None'), pl, [], []);
          end
          
        else
          error('### Unknown single argument constructor.');
        end
      elseif nargin == 2
        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        %%%%%%%%%%%%%%%%%%%%%%%%%%%   two input   %%%%%%%%%%%%%%%%%%%%%%%%%%%
        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        
        if isa(varargin{1}, 'pzmodel') && isa(varargin{2}, 'plist')
          %%%%%%%%%%  f = miir(pzmodel-object, plist-object)   %%%%%%%%%%
          utils.helper.msg(msg.OPROC1, 'constructing from pzmodel %s', varargin{1}.name);
%           obj = fromPzmodel(obj, combine(plist('pzmodel', varargin{1}), varargin{2}));
          obj = fromPzmodel(obj, varargin{1}, varargin{2});
          
        elseif (isa(varargin{1}, 'miir') || isa(varargin{1}, 'parfrac')) && isa(varargin{2}, 'plist') &&  isempty(varargin{2}.params)
          %%%%%%%%%%  f = miir(miir-object,    <empty plist>)   %%%%%%%%%%
          %%%%%%%%%%  f = miir(parfrac-object, <empty plist>)   %%%%%%%%%%
          % pass to copy constructor
          obj = miir(varargin{1});
          
        elseif (isa(varargin{1}, 'parfrac')) && isa(varargin{2}, 'plist') &&  ~isempty(varargin{2}.params)
          %%%%%%%%%%  f = miir(parfrac-object, plist-object)   %%%%%%%%%%
          plf = combine(plist('parfrac', varargin{1}),varargin{2});
          obj =  fromParfrac(obj, plf);
          
        elseif (isa(varargin{1}, 'database') || isa(varargin{1}, 'java.sql.Connection')) && isnumeric(varargin{2})
          %%%%%%%%%%  f = miir(<database-object>, [IDs])   %%%%%%%%%%
          utils.helper.msg(msg.OPROC1, 'retrieve from repository');
          obj = obj.fromRepository(plist('conn', varargin{1}, 'id', varargin{2}));
          
        elseif isa(varargin{1}, 'org.apache.xerces.dom.DeferredElementImpl') && ...
            isa(varargin{2}, 'history')
          %%%%%%%%%%   obj = miir(DOM node, history-objects)   %%%%%%%%%%
          obj = fromDom(obj, varargin{1}, varargin{2});
          
        elseif isa(varargin{1}, 'ltpda_uoh') && isa(varargin{2}, 'plist')
          %%%%%%%%%%%   miir(<ltpda_uoh>-object, plist-object)   %%%%%%%%%%
          % always recreate from plist
          
          % If we are trying to load from file, and the file exists, do
          % that. Otherwise, copy the input object.
          if varargin{2}.isparam('filename')
            if exist(fullfile('.', find(varargin{2}, 'filename')), 'file')==2
              obj = miir(varargin{2});
            else
              obj = miir(varargin{1});
            end
          else
            obj = miir(varargin{2});
          end
        else
          error('### Unknown 2 argument constructor.');
        end
        
      elseif nargin == 3
        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        %%%%%%%%%%%%%%%%%%%%%%%%%%   three input   %%%%%%%%%%%%%%%%%%%%%%%%%%
        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        
        utils.helper.msg(msg.OPROC1, 'constructing from A/B coefficients');
        %%%%%%%%%%  f = miir(a, b, fs)   %%%%%%%%%%
        % a,b,fs constructor
        obj = fromAB(obj, plist('a', varargin{1}, 'b', varargin{2}, 'fs', varargin{3}));
      else
        [iirs, invars, rest] = utils.helper.collect_objects(args, 'miir');
        
        %%% Do we have a list of MIIR objects as input
        if ~isempty(iirs) && isempty(rest)
          obj = miir(iirs);
        else
          error('### Unknown number of constructor arguments.');
        end
      end
    end % End constructor
    
  end % End public methods
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                            Methods (static)                               %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  methods (Static)
    
    function mdls = getBuiltInModels(varargin)
      mdls = ltpda_uo.getBuiltInModels('miir');
    end
    
    function out = VEROUT()
      out = '$Id: miir.m,v 1.130 2011/08/15 12:22:57 hewitson Exp $';
    end
    
    function ii = getInfo(varargin)
      ii = utils.helper.generic_getInfo(varargin{:}, 'miir');
    end
    
    function out = SETS()
      out = [SETS@ltpda_uoh,    ...
        {'From LISO File'},     ...
        {'From Standard Type'}, ...
        {'Allpass'}, ...
        {'From Parfrac'},       ...
        {'From Pzmodel'},       ...
        {'From AB'}];
    end
    
    function plout = getDefaultPlist(set)
      persistent pl;
      persistent lastset;
      if exist('pl', 'var')==0 || isempty(pl) || ~strcmp(lastset, set)
        pl = miir.buildplist(set);
        lastset = set;
      end
      plout = pl;
    end
    
    function out = buildplist(set)
      
      if ~utils.helper.ismember(lower(miir.SETS), lower(set))
        error('### Unknown set [%s]', set);
      end
      
      out = plist();
      out = miir.addGlobalKeys(out);
      out = buildplist@ltpda_uoh(out, set);
      
      switch lower(set)
        case 'allpass'
          
          % Delay
          p = param({'delay','The allpass delay.'}, paramValue.EMPTY_DOUBLE);
          out.append(p);
          
          % N
          p = param({'N','The filter order.'}, paramValue.DOUBLE_VALUE(1));
          out.append(p);
          
          % Method
          p = param({'method','The method for generating the filter.'}, {1, {'thirlen'}, paramValue.SINGLE});
          out.append(p);
          
          % Iunits
          p = param({'iunits','The input units of the filter.'}, paramValue.EMPTY_STRING);
          out.append(p);
          
          % Ounits
          p = param({'ounits','The output units of the filter.'}, paramValue.EMPTY_STRING);
          out.append(p);
          
        case 'from ab'
          
          % A
          p = param({'a','Set of numerator coefficients.'}, paramValue.EMPTY_DOUBLE);
          out.append(p);
          
          % B
          p = param({'b','Set of denominator coefficients.'}, paramValue.EMPTY_DOUBLE);
          out.append(p);
          
          % Fs
          p = param({'fs','The sampling frequency to design for.'}, paramValue.EMPTY_DOUBLE);
          out.append(p);
          
          % Iunits
          p = param({'iunits','The input units of the filter.'}, paramValue.EMPTY_STRING);
          out.append(p);
          
          % Ounits
          p = param({'ounits','The output units of the filter.'}, paramValue.EMPTY_STRING);
          out.append(p);
          
        case 'from standard type'
          
          % Type
          p = param({'type','Choose the filter type.'}, {2, {'highpass', 'lowpass', 'bandpass', 'bandreject'}, paramValue.SINGLE});
          out.append(p);
          
          % Fc
          p = param({'fc','The roll-off frequency [Hz].'},  paramValue.DOUBLE_VALUE(0.1));
          out.append(p);
          
          % Gain
          p = param({'gain','The gain of the filter.'},  paramValue.DOUBLE_VALUE(1));
          out.append(p);
          
          % Fs
          p = param({'fs','The sampling frequency to design for.'}, paramValue.DOUBLE_VALUE(1));
          out.append(p);
          
          % Order
          p = param({'order', 'The filter order.'}, paramValue.DOUBLE_VALUE(1));
          out.append(p);
          
          % Ripple
          p = param({'ripple', 'Pass/stop-band ripple (%) for bandpass and bandreject filters.'}, paramValue.DOUBLE_VALUE(0.5));
          out.append(p);
          
%           % Win
%           p = param({'win', 'A window to design with.'}, paramValue.WINDOW);
%           out.append(p);
%           
          % Iunits
          p = param({'iunits','The input units of the filter.'}, paramValue.EMPTY_STRING);
          out.append(p);
          
          % Ounits
          p = param({'ounits','The output units of the filter.'}, paramValue.EMPTY_STRING);
          out.append(p);
          
        case 'from parfrac'
          
          % Parfrac
          p = param({'parfrac','Parfrac object to design from.'}, {1, {parfrac}, paramValue.OPTIONAL});
          out.append(p);
          
          % Fs
          p = param({'fs','The sampling frequency to design for.'}, paramValue.EMPTY_DOUBLE);
          out.append(p);
          
          % Iunits
          p = param({'iunits','The input units of the transfer function.'}, paramValue.EMPTY_STRING);
          out.append(p);
          
          % Ounits
          p = param({'ounits','The output units of the transfer function.'}, paramValue.EMPTY_STRING);
          out.append(p);
          
        case 'from pzmodel'
          
          % pzmodel
          p = param({'pzmodel','Pole/zero model object to design from.'}, {1, {pzmodel}, paramValue.OPTIONAL});
          out.append(p);
          
          % Fs
          p = param({'fs','The sampling frequency to design for.'}, paramValue.EMPTY_DOUBLE);
          out.append(p);
          
          % Iunits
          p = param({'iunits','The input units of the transfer function.'}, paramValue.EMPTY_STRING);
          out.append(p);
          
          % Ounits
          p = param({'ounits','The output units of the transfer function.'}, paramValue.EMPTY_STRING);
          out.append(p);
          
        case 'from liso file'
          
          % Filename
          p = param({'filename','LISO filename.'}, paramValue.EMPTY_STRING);
          out.append(p);
      end
    end % function out = getDefaultPlist(varargin)
    
    function obj = initObjectWithSize(n,m)
      obj = miir.newarray([n m]);
    end
    
  end % End static methods
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                         Methods (static, private)                         %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  
  methods (Static, Access=private)
    
    f   = filload(filename)
    plo = parseFilterParams(pl)
    
  end % End static, private methods
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                         Methods (static, hidden)                          % 
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  
  methods (Static = true, Hidden = true)
    varargout = loadobj(varargin)
    varargout = update_struct(varargin);
  end
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                              Methods (public)                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  
  methods
    varargout = char(varargin);
    varargout = copy(varargin)
    varargout = display(varargin);
    
    varargout = setHistin(varargin)
    varargout = setB(varargin)
    varargout = redesign(varargin)
  end
  
  methods (Hidden = true)
    varargout = attachToDom(varargin)
  end
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                              Methods (protected)                          %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  
  methods (Access = protected)
    varargout = fromLISO(varargin)
    varargout = fromStruct(varargin)
    varargout = fromDom(varargin)
  end
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                               Methods (private)                           %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  
  methods (Access = private)
    varargout = fromPzmodel(varargin)
    f = fromParfrac(f, pli)
    f = fromAB(f, pli)
    f = fromStandard(f, pli)
    
    f = mklowpass(f, pl)
    f = mkhighpass(f, pl)
    f = mkbandpass(f, pl)
    f = mkbandreject(f, pl)
  end
  
end % End classdef

% END

% Parameter sets for plist constructor (in order of priority):
%
% From XML File
% -------------
%
%   Construct an MIIR by loading it from an XML file.
%
%   'filename' - construct an MIIR from a filename.
%                Example: plist('filename', 'm1.xml')
%                [default: empty string]
%
% From MAT File
% -------------
%
%   Construct an MIIR by loading it from a MAT file.
%
%   'filename' - construct an MIIR from a filename.
%                Example: plist('filename', 'm1.mat')
%                [default: empty string]
%
% From LISO File
% --------------
%
%   Construct an MIIR by loading it from a LISO file.
%
%   'filename' - construct an MIIR from a filename.
%                Example: plist('filename', 'm1.fil')
%                [default: empty string]
%
% From Repository
% ---------------
%
%   Construct an MIIR by retrieving it from an LTPDA repository.
%
%   'Hostname' - the repository hostname. Only those objects which
%                are MIIRs are returned.
%                [default: 'localhost'];
%
%                Additional parameters:
%                'Database'   - The database name [default: 'ltpda']
%                'ID'         - A vector of object IDs. [default: []]
%                'CID'        - Retrieve all MIIR objects from a particular
%                               collection.
%                'Binary'     - Set to 'yes' to retrieve from stored binary
%                               representation (not always available).
%
% From AB
% -------
%
%   Construct an MIIR from the A and B coefficients.
%
%   'a'    - vector of A coefficients (see note ** below) [default: empty]
%   'b'    - vector of B coefficients (see note ** below) [default: empty]
%   'fs'   - sampling frequency of the filter [default: empty]
%   'name' - name of filter [default: 'None']
%
%
% From Standard Type
% ------------------
%
%   Construct an MIIR of a standard type.
%
%   'type'    - one of the types: 'highpass', 'lowpass',
%               'bandpass', 'bandreject'            [default: 'lowpass']
%
%                You can also specify optional parameters:
%                   'gain'   - the gain of the filter [default: 1]
%                   'fc'     - the roll-off frequency    [default: 0.1 Hz]
%                   'fs'     - the sampling frequency to design for [default: 1 Hz]
%                   'order'  - the filter order [default: 1]
%                   'ripple' - pass/stop-band ripple for bandpass
%                              and bandreject filters [default: 0.5]
%                   'iunits' - the input unit of the filter
%                   'ounits' - the output unit of the filter
%
% From Parfrac
% ------------
%
%   Construct an MIIR from a parfrac.
%
%   'parfrac'    - a parfrac object to construct the filters from [default: empty parfrac]
%   'fs'         - sample rate for the filter(s)
%
% From Pzmodel
% ------------
%
%   Construct an MIIR from a pzmodel.
%
%   'pzmodel'    - a pzmodel object to construct the filter from [default: empty pzmodel]
%   'fs'         - sample rate for the filter
%
% From Plist
% ----------
%
%   'Plist'    - construct from a plist. The value passed should be a plist
%                object.
%                [default: empty plist]
