PyIBIS-AMI Demo #1 - Reverse engineering the Tx tap weight equations of an IBIS-AMI model.

Introduction

This IPython Notebook (See http://ipython.org/notebook.html) demonstrates the utility of the PyIBIS-AMI Python package, by using it to reverse engineer the tap weight equations of an IBIS-AMI Model.

Original author:

Original date: March 19, 2015

Copyright (c) 2015 David Banas; all rights reserved World wide.

One common problem faced by serial link designers using IBIS-AMI models is figuring out what numbers to insert into the AMI parameters of a model, in order to get a Tx pre-emphasis filter with a particular set of coefficients. Typically, the AMI model does not offer the user the ability to enter these coefficients directly, but rather offers the user a selection of integers from which to choose. The exact meaning of these integers, with regard to the resultant filter coefficients, is somewhat vague and arbitrary, and not often explained well in the model documentation.

Here, we will see how to determine, empirically and for ourselves, the exact equations, which relate the actual filter coefficients to these arbitrary integers, by making use of the public domain, open source Python package, PyIBIS-AMI, to provide direct access to the model DLL from the Python command prompt. Once we have the DLL loaded in the local Python environment, we are able to bring the full force of our Python library suite to bear on the problem of teasing certain information out of the model.

In addition to wrapping the DLL in a Python-ic way, so that it can be imported into the local Python environment, the PyIBIS-AMI package also provides certain data structures, which make working with the DLL much simpler. Over the course of this demo, we will learn how to use these data structures, to make our work poking and prodding the DLL more convenient.

Preliminaries

One of the greatest things about Python is its dynamic documentation capability. What this means is, object documentation can travel along with an object as a first class attribute known as a "docstring". This means that, once you've imported an object (such as one of the modules included in the PyIBIS-AMI package) into the local Python environment, you can query for its documentation, just as you might for one of its attributes (i.e. - data or method). Let's use this feature to begin learning what the PyIBIS-AMI package offers us...

In [1]:
import pyibisami.amimodel as ami  # All good things in Python begin with an import of something useful.
print ami.__doc__                 # "__doc__" (2 underscores on each side) is the special name given to an object's docstring.

Class definitions for working with IBIS-AMI models

Original Author: David Banas
Original Date:   July 3, 2012

Copyright (c) 2012 David Banas; All rights reserved World wide.


Isn't that cool?! We didn't have to refer to some Web page or book; we just asked the object for its documentation. Awesome sauce!

Note: We did need to know 2 things, in order to get ourselves bootstrapped, above:

  • The name of the module we wanted ("pyibisami"). (Fortunately, there's a practiced convention, in the Python tribe, of forming the top level module name in a package by removing all punctuation from, and lowering the case of, the pacakge name.)
  • The name of the sub-module we wanted ("amimodel"). (In this case, there's only one. So, TAB completion gave it to us for free!)

Now, admittedly, the documentation for the amimodel sub-module is a little sparse. Let's see if there's something more useful attached to any of its attributes. Again, using the TAB completion convenience provided by the Python command prompt, and noticing that only 2 of the options presented to us begin with the letters "AMI", we dig deeper...

In [2]:
print ami.AMIModel.__doc__
 Class defining the structure and behavior of a AMI Model.
        
        Public Methods: (See individual docs.)
          initialize()
          getWave()
        
        Properties: (See individual docs.)
          initOut
          channel_response
          clock
          row_size
          num_aggressors
          sample_interval
          bit_time
          ami_params_in
          ami_params_out
          ami_mem_handle
          msg

        Additional Features:

          - Makes the calling of AMI_Close() automagic, by calling it
            from the destructor.
    

In [3]:
print ami.AMIModelInitializer.__doc__
 Class containing the initialization data for an instance of `AMIModel'.

        Created primarily to facilitate use of the PyAMI package at the
        pylab command prompt, this class can be used by the pylab user,
        in order to store all the data required to initialize an instance
        of class `AMIModel'. In this way, the pylab user may assemble
        the AMIModel initialization data just once, and modify it
        incrementally, as she experiments with different initialization
        settings. In this way, she can avoid having to type a lot of
        redundant constants every time she invokes the AMIModel constructor.
    

Well, that's a bit more interesting. And, judging from the parenthetical comments in the AMIModel docstring, there's even more, if we want to continue digging. I'll leave that as an exercise. (I've always wanted to say that. :) )

Hopefully, I've wet your appetite for learning about Python entities by simply asking them to tell you about themselves. This dynamic documentation is truly one of the greatest features of Python. Now, on with the show...

Step #1: Model import, initialization, and sanity check.

In [4]:
theModel = ami.AMIModel('eASIC_AMI_Tx.dll')
initData = ami.AMIModelInitializer({'root_name' : 'easic_tx'})
theModel.initialize(initData)
(easic_tx )

Above, I've instantiated both data structures we just looked at, using the minimum required initialization information for each. Of course, you can provide more, if you wish. See the docstring of the initialize() function, for instance. With both data structures created, I've used the second to initialize the first.

The 3 lines of code, above, represent the simplest use model available in the PyIBIS-AMI package, and result in a model initialized entirely with its default parameter values. As we progress, we will add additional items to initData's dictionary, recalling initialize() with the updated data structure, in order to exercise more control over the model's initialization.

That (easic_tx ) is the output parameter string returned by the Init() function of the model. In this case, only the AMI root name, easic_tx, is being returned, since we have explicitly configured nothing, leaving the model to use only its defaults.

Now, let's start poking and prodding...

In [5]:
h1 = theModel.initOut
T = theModel.sample_interval
t = [i * T for i in range(len(h1))]
%matplotlib inline
import matplotlib.pyplot as plt
plt.plot(t, h1)
Out[5]:
[<matplotlib.lines.Line2D at 0x74b7630>]

Above, we've plotted the impulse response returned by the model's Init() function.

Let's zoom in a little...

In [6]:
plt.plot(t[:len(t) / 4], h1[:len(t) / 4])
Out[6]:
[<matplotlib.lines.Line2D at 0x751b4b0>]

That's better. Now, let's just confirm what we're seeing...

In [7]:
print h1[4 : 7]
[0.0, 1.098456195345, 0.0]

In [8]:
print T
2.5e-11

Okay, so now we know that, in its default configuration (Note, above, that we supplied nothing to the initializer other than the model root name.), the model:

  • Uses no pre-emphasis.
  • Has a main tap weight of approximately 1.1.

(Not shown or proven, but true, is that the AMIModelInitializer class, by default, uses:

  • a Kronecker Delta sequence (i.e. - [0, 1, 0, 0, ...]) as input to the model Init() function.
  • a sample period of 25 ps. (This one is, actually, shown by our "print T", above.)

)

At this point, the model has:

  • been imported,
  • been initialilzed, and
  • passed a brief sanity check.

And we now know:

  • the position of the main (i.e. - "cursor") tap in the output vector, and
  • the main tap weight used, when no pre-emphasis is engaged.

Step #2: Sweep through the full tap weight parameter space, recording the results.

By looking at the AMI file, we find that this model provides 3 user adjustable taps for pre-emphasis:

  • a pre-cursor tap, named tx_tap_np1,
  • and 2 post-cursor taps, named tx_tap_nm1 and tx_tap_nm2, respectively.

The AMI file, also, gives us the legal range of values for all 3 taps.

We will, now, sweep these taps through the full 3-dimmensional parameter space, which they construct, and record the results for later analysis.

However, we need one more piece of information, in order to do this: the unit interval (UI) spacing, in the output vector. We'll find that, empirically, by temporarily turning on all the taps...

In [9]:
initData.ami_params['tx_tap_np1'] = 1  # Here, as promissed, we're adding additional items to initData's dictionary.
initData.ami_params['tx_tap_nm1'] = 1
initData.ami_params['tx_tap_nm2'] = 1
theModel.initialize(initData)
h1 = theModel.initOut
plt.plot(t[:len(t) / 4], h1[:len(t) / 4])
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 1)(tx_tap_np1 1))

Out[9]:
[<matplotlib.lines.Line2D at 0x778b790>]

And we see that the 4 taps of our Tx pre-emphasis FIR filter (i.e. - 1 pre + main + 2 post) are spaced 4 samples apart, in the output vector, and located at indeces: 1, 5, 9, and 13.

Now, we have everything we need, in order to do our sweep...
(Note that I've hidden the output of the code, below, because it is lengthy and not very informative.)

In [10]:
import numpy as np

gMaxPretapVal   = 6
gMaxPosttap1Val = 9
gMaxPosttap2Val = 3

pretap_weights   = np.zeros((gMaxPretapVal + 1, gMaxPosttap1Val + 1, gMaxPosttap2Val + 1), dtype=float)
maintap_weights  = np.zeros((gMaxPretapVal + 1, gMaxPosttap1Val + 1, gMaxPosttap2Val + 1), dtype=float)
posttap1_weights = np.zeros((gMaxPretapVal + 1, gMaxPosttap1Val + 1, gMaxPosttap2Val + 1), dtype=float)
posttap2_weights = np.zeros((gMaxPretapVal + 1, gMaxPosttap1Val + 1, gMaxPosttap2Val + 1), dtype=float)

for pretap_index in range(gMaxPretapVal + 1):
    for posttap1_index in range(gMaxPosttap1Val + 1):
        for posttap2_index in range(gMaxPosttap2Val + 1):
            # Here, we see the value of maintaining an independent initialization data structure:
            # We can "tweak" it, incrementally, and re-initialize the model, observing the effect of our change.
            # We don't have to supply all initialization data every time we want to re-call Init().
            # This makes sweeps, such as the one we're conducting here, much more convenient.
            initData.ami_params['tx_tap_np1'] = pretap_index
            initData.ami_params['tx_tap_nm1'] = posttap1_index
            initData.ami_params['tx_tap_nm2'] = posttap2_index
            theModel.initialize(initData)
            h1 = theModel.initOut
            pretap_weights  [pretap_index][posttap1_index][posttap2_index] = h1[1]
            maintap_weights [pretap_index][posttap1_index][posttap2_index] = h1[5]
            posttap1_weights[pretap_index][posttap1_index][posttap2_index] = h1[9]
            posttap2_weights[pretap_index][posttap1_index][posttap2_index] = h1[13]
            
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 0)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 0)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 0)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 0)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 1)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 1)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 1)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 1)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 2)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 2)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 2)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 2)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 3)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 3)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 3)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 3)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 4)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 4)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 4)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 4)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 5)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 5)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 5)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 5)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 6)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 6)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 6)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 6)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 7)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 7)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 7)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 7)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 8)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 8)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 8)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 8)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 9)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 9)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 9)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 9)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 0)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 0)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 0)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 0)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 1)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 1)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 1)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 1)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 2)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 2)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 2)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 2)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 3)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 3)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 3)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 3)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 4)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 4)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 4)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 4)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 5)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 5)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 5)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 5)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 6)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 6)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 6)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 6)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 7)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 7)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 7)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 7)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 8)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 8)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 8)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 8)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 9)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 9)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 9)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 9)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 0)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 0)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 0)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 0)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 1)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 1)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 1)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 1)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 2)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 2)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 2)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 2)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 3)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 3)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 3)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 3)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 4)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 4)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 4)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 4)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 5)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 5)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 5)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 5)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 6)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 6)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 6)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 6)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 7)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 7)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 7)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 7)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 8)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 8)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 8)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 8)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 9)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 9)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 9)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 9)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 0)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 0)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 0)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 0)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 1)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 1)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 1)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 1)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 2)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 2)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 2)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 2)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 3)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 3)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 3)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 3)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 4)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 4)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 4)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 4)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 5)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 5)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 5)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 5)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 6)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 6)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 6)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 6)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 7)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 7)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 7)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 7)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 8)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 8)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 8)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 8)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 9)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 9)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 9)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 9)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 0)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 0)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 0)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 0)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 1)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 1)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 1)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 1)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 2)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 2)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 2)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 2)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 3)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 3)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 3)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 3)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 4)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 4)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 4)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 4)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 5)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 5)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 5)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 5)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 6)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 6)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 6)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 6)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 7)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 7)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 7)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 7)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 8)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 8)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 8)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 8)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 9)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 9)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 9)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 9)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 0)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 0)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 0)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 0)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 1)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 1)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 1)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 1)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 2)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 2)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 2)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 2)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 3)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 3)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 3)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 3)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 4)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 4)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 4)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 4)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 5)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 5)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 5)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 5)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 6)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 6)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 6)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 6)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 7)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 7)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 7)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 7)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 8)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 8)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 8)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 8)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 9)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 9)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 9)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 9)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 0)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 0)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 0)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 0)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 1)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 1)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 1)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 1)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 2)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 2)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 2)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 2)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 3)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 3)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 3)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 3)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 4)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 4)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 4)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 4)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 5)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 5)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 5)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 5)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 6)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 6)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 6)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 6)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 7)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 7)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 7)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 7)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 8)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 8)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 8)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 8)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 9)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 9)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 9)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 9)(tx_tap_np1 6))

Step #3: Analyze our sweep results, in order to reveal the equations relating tap indices to weights.

So, now that we have this 3-dimmensional matrix of sweep results showing the actual tap weights for every possible combination of tap indices, how do we convert it into equations, which map from tap indices to tap weights, or vice versa?

Let's start by looking at the sum of the magnitudes of the 4 weights, in order to see if our model is enforcing any sort of constraint on this quantity...

In [11]:
sums = []
i    = 0
for pretap_index in range(gMaxPretapVal + 1):
    for posttap1_index in range(gMaxPosttap1Val + 1):
        for posttap2_index in range(gMaxPosttap2Val + 1):
            sums.append(
                abs(pretap_weights  [pretap_index][posttap1_index][posttap2_index]) +
                abs(maintap_weights [pretap_index][posttap1_index][posttap2_index]) +
                abs(posttap1_weights[pretap_index][posttap1_index][posttap2_index]) +
                abs(posttap2_weights[pretap_index][posttap1_index][posttap2_index])
            )
plt.plot(sums)
Out[11]:
[<matplotlib.lines.Line2D at 0x76db1f0>]

Well, that's weird; The model seems to have two values to which it constrains the sum of the tap weights: 1.1 and 1.0; what's going on?!
It turns out there's an additional contraint on our tap index settings: they cannot sum to a value greater than 10.
Observe...

In [12]:
initData.ami_params['tx_tap_np1'] = 1       # Note the tap values sum to 10.
initData.ami_params['tx_tap_nm1'] = 8
initData.ami_params['tx_tap_nm2'] = 1
theModel.initialize(initData)
h1 = theModel.initOut
plt.plot(t[:len(t) / 4], h1[:len(t) / 4])
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 8)(tx_tap_np1 1))

Out[12]:
[<matplotlib.lines.Line2D at 0x8167170>]

Okay, that certainly looks reasonable, but...

In [13]:
initData.ami_params['tx_tap_np1'] = 1       # Note the tap values sum to 11.
initData.ami_params['tx_tap_nm1'] = 8
initData.ami_params['tx_tap_nm2'] = 2
theModel.initialize(initData)
h1 = theModel.initOut
plt.plot(t[:len(t) / 4], h1[:len(t) / 4])
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 8)(tx_tap_np1 1))

Out[13]:
[<matplotlib.lines.Line2D at 0x833cb50>]

Whoa! what happened?! Our model completely freaked out. Why?
We have an issue with this model: if we send in a combination of tap values, which total more than 10, the model produces the completely nonsensical impulse response shown, above.
So, going forward, we will enforce this constraint:

\[\sum taps <= 10 \]

If we re-plot our sums, enforcing this contraint...

In [14]:
sums = []
i    = 0
for pretap_index in range(gMaxPretapVal + 1):
    for posttap1_index in range(gMaxPosttap1Val + 1):
        for posttap2_index in range(gMaxPosttap2Val + 1):
            if(sum([pretap_index, posttap1_index, posttap2_index]) <= 10): # Note the constraint enforcement.
                sums.append(
                    abs(pretap_weights  [pretap_index][posttap1_index][posttap2_index]) +
                    abs(maintap_weights [pretap_index][posttap1_index][posttap2_index]) +
                    abs(posttap1_weights[pretap_index][posttap1_index][posttap2_index]) +
                    abs(posttap2_weights[pretap_index][posttap1_index][posttap2_index])
                )
plt.plot(sums)
Out[14]:
[<matplotlib.lines.Line2D at 0x83fff90>]

And we find that the sum of the filter tap weights is constrained to the constant value \(1.1\).
This is good, because it is what we, typically, expect from a Tx model. The universe is right. :-)
And, it gives us our first equation:

\[ b_0 = 1.1 - \sum b_k ; k \not= 0 \]

which gives us our main cursor tap weight, in terms of the other tap weights. But, how to find them?

We start by assuming the following model:

\[ b_n = m_n x_n ; n \not= 0 \\ \] where \(m_n\) is a function of all other \(x_m ; m\not= n\), or \(m_n = f(\{x_k\}) ; k \not= n\).

In English, what this says is: the function mapping a particular tap index to the equivalent tap weight is a straight line, passing through the origin, with slope determined by the other tap indices.

(Note that we've adopted the notation: \(b_n\) is the actual coefficient in the filter equation, while \(x_n\) is the user supplied index for tap \(n\).)

So, our task, then, is to find these functions, which determine the slopes, \(m_n\). Let's just plow ahead in brute force, straightforward fashion, focusing on the first post-tap for starters, and see what we can learn...

In [15]:
from scipy import stats

posttap1_slopes = np.zeros((gMaxPretapVal + 1, gMaxPosttap2Val + 1), dtype=float)
posttap1_rvals  = np.zeros((gMaxPretapVal + 1, gMaxPosttap2Val + 1), dtype=float)
for pretap_index in range(gMaxPretapVal + 1):
    initData.ami_params['tx_tap_np1'] = pretap_index
    for posttap2_index in range(gMaxPosttap2Val + 1):
        initData.ami_params['tx_tap_nm2'] = posttap2_index
        weights = []
        for posttap1_index in range(min(gMaxPosttap1Val + 1, 11 - pretap_index - posttap2_index)): # Note the constraint enforcement.
            initData.ami_params['tx_tap_nm1'] = posttap1_index
            theModel.initialize(initData)
            h1 = theModel.initOut
            weights.append(h1[9])
        slope, intercept, r_value, p_value, std_err = stats.linregress(range(len(weights)), weights)
        posttap1_slopes[pretap_index][posttap2_index] = slope
        posttap1_rvals [pretap_index][posttap2_index] = r_value
print "Min. |r_value|:", min(abs(posttap1_rvals.flatten()))
plt.plot(posttap1_slopes[0], label = "Pretap = 0")
plt.plot(posttap1_slopes[1], label = "Pretap = 1")
plt.plot(posttap1_slopes[6], label = "Pretap = 6")
plt.legend()
plt.title("First post-tap equation slope vs. second post-tap value, by pre-tap value.")
plt.xlabel("Second post-tap value")
plt.ylabel("Slope")
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 0)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 1)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 2)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 3)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 4)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 5)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 6)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 7)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 8)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 9)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 0)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 1)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 2)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 3)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 4)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 5)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 6)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 7)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 8)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 9)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 0)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 1)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 2)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 3)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 4)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 5)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 6)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 7)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 8)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 0)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 1)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 2)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 3)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 4)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 5)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 6)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 7)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 0)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 1)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 2)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 3)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 4)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 5)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 6)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 7)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 8)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 9)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 0)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 1)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 2)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 3)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 4)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 5)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 6)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 7)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 8)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 0)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 1)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 2)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 3)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 4)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 5)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 6)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 7)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 0)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 1)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 2)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 3)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 4)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 5)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 6)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 0)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 1)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 2)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 3)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 4)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 5)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 6)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 7)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 8)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 0)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 1)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 2)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 3)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 4)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 5)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 6)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 7)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 0)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 1)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 2)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 3)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 4)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 5)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 6)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 0)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 1)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 2)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 3)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 4)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 5)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 0)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 1)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 2)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 3)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 4)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 5)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 6)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 7)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 0)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 1)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 2)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 3)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 4)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 5)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 6)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 0)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 1)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 2)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 3)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 4)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 5)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 0)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 1)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 2)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 3)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 4)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 0)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 1)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 2)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 3)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 4)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 5)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 6)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 0)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 1)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 2)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 3)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 4)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 5)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 0)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 1)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 2)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 3)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 4)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 0)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 1)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 2)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 3)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 0)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 1)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 2)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 3)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 4)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 5)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 0)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 1)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 2)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 3)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 4)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 0)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 1)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 2)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 3)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 0)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 1)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 2)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 0)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 1)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 2)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 3)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 4)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 0)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 1)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 2)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 3)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 0)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 1)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 2)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 0)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 1)(tx_tap_np1 6))
Min. |r_value|: 1.0

C:\Users\dbanas\AppData\Local\Continuum\Anaconda\lib\site-packages\scipy\stats\stats.py:3029: RuntimeWarning: invalid value encountered in double_scalars
  sterrest = np.sqrt((1-r*r)*ssym / ssxm / df)

Out[15]:
<matplotlib.text.Text at 0x8a78910>

It's clear from the plot, above, that the slope of the first post-tap equation is constant. It is not affected by either the pre-tap or second post-tap values. This is the best case we could hope for, because it suggests that our "tap weight vs. tap index" equations are completely independent of each other. Yeah!

Similar sweeps/plots confirm this suspicion for the other two taps...

In [16]:
posttap2_slopes = np.zeros((gMaxPretapVal + 1, gMaxPosttap1Val + 1), dtype=float)
posttap2_rvals  = np.zeros((gMaxPretapVal + 1, gMaxPosttap1Val + 1), dtype=float)
for pretap_index in range(gMaxPretapVal + 1):
    initData.ami_params['tx_tap_np1'] = pretap_index
    for posttap1_index in range(gMaxPosttap1Val + 1):
        initData.ami_params['tx_tap_nm1'] = posttap1_index
        weights = []
        for posttap2_index in range(min(gMaxPosttap2Val + 1, 11 - pretap_index - posttap1_index)): # Note the constraint enforcement.
            initData.ami_params['tx_tap_nm2'] = posttap2_index
            theModel.initialize(initData)
            h1 = theModel.initOut
            weights.append(h1[13])
        slope, intercept, r_value, p_value, std_err = stats.linregress(range(len(weights)), weights)
        posttap2_slopes[pretap_index][posttap1_index] = slope
        posttap2_rvals [pretap_index][posttap1_index] = r_value
print "Min. |r_value|:", min(abs(posttap2_rvals.flatten()))
plt.plot(posttap2_slopes[0], label = "Pretap = 0")
plt.plot(posttap2_slopes[1], label = "Pretap = 1")
plt.plot(posttap2_slopes[2], label = "Pretap = 2")
plt.plot(posttap2_slopes[3], label = "Pretap = 3")
plt.plot(posttap2_slopes[4], label = "Pretap = 4")
plt.plot(posttap2_slopes[5], label = "Pretap = 5")
plt.plot(posttap2_slopes[6], label = "Pretap = 6")
plt.legend()
plt.title("Second post-tap equation slope vs. first post-tap value, by pre-tap value.")
plt.xlabel("First post-tap value")
plt.ylabel("Slope")
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 0)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 0)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 0)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 0)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 1)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 1)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 1)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 1)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 2)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 2)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 2)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 2)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 3)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 3)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 3)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 3)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 4)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 4)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 4)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 4)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 5)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 5)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 5)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 5)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 6)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 6)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 6)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 6)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 7)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 7)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 7)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 7)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 8)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 8)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 8)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 9)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 9)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 0)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 0)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 0)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 0)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 1)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 1)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 1)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 1)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 2)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 2)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 2)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 2)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 3)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 3)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 3)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 3)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 4)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 4)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 4)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 4)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 5)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 5)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 5)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 5)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 6)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 6)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 6)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 6)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 7)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 7)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 7)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 8)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 8)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 9)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 0)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 0)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 0)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 0)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 1)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 1)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 1)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 1)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 2)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 2)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 2)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 2)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 3)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 3)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 3)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 3)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 4)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 4)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 4)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 4)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 5)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 5)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 5)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 5)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 6)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 6)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 6)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 7)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 7)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 8)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 0)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 0)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 0)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 0)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 1)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 1)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 1)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 1)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 2)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 2)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 2)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 2)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 3)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 3)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 3)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 3)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 4)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 4)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 4)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 4)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 5)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 5)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 5)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 6)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 6)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 7)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 0)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 0)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 0)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 0)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 1)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 1)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 1)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 1)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 2)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 2)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 2)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 2)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 3)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 3)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 3)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 3)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 4)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 4)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 4)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 5)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 5)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 6)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 0)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 0)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 0)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 0)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 1)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 1)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 1)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 1)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 2)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 2)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 2)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 2)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 3)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 3)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 3)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 4)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 4)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 5)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 0)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 0)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 0)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 0)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 1)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 1)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 1)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 1)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 2)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 2)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 2)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 3)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 3)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 4)(tx_tap_np1 6))
Min. |r_value|: 0.0

C:\Users\dbanas\AppData\Local\Continuum\Anaconda\lib\site-packages\scipy\stats\stats.py:3025: RuntimeWarning: invalid value encountered in sqrt
  t = r*np.sqrt(df/((1.0-r+TINY)*(1.0+r+TINY)))
C:\Users\dbanas\AppData\Local\Continuum\Anaconda\lib\site-packages\scipy\stats\stats.py:3026: RuntimeWarning: invalid value encountered in absolute
  prob = distributions.t.sf(np.abs(t),df)*2
C:\Users\dbanas\AppData\Local\Continuum\Anaconda\lib\site-packages\scipy\stats\stats.py:3027: RuntimeWarning: invalid value encountered in double_scalars
  slope = r_num / ssxm
C:\Users\dbanas\AppData\Local\Continuum\Anaconda\lib\site-packages\numpy\core\_methods.py:59: RuntimeWarning: Mean of empty slice.
  warnings.warn("Mean of empty slice.", RuntimeWarning)
C:\Users\dbanas\AppData\Local\Continuum\Anaconda\lib\site-packages\numpy\core\_methods.py:71: RuntimeWarning: invalid value encountered in double_scalars
  ret = ret.dtype.type(ret / rcount)
C:\Users\dbanas\AppData\Local\Continuum\Anaconda\lib\site-packages\numpy\lib\function_base.py:1878: RuntimeWarning: Degrees of freedom <= 0 for slice
  warnings.warn("Degrees of freedom <= 0 for slice", RuntimeWarning)
C:\Users\dbanas\AppData\Local\Continuum\Anaconda\lib\site-packages\numpy\core\_methods.py:69: RuntimeWarning: invalid value encountered in true_divide
  ret, rcount, out=ret, casting='unsafe', subok=False)
C:\Users\dbanas\AppData\Local\Continuum\Anaconda\lib\site-packages\numpy\lib\function_base.py:1889: RuntimeWarning: invalid value encountered in true_divide
  return (dot(X, X.T.conj()) / fact).squeeze()

Out[16]:
<matplotlib.text.Text at 0x8cf1410>
In [17]:
pretap_slopes = np.zeros((gMaxPosttap2Val + 1, gMaxPosttap1Val + 1), dtype=float)
pretap_rvals  = np.zeros((gMaxPosttap2Val + 1, gMaxPosttap1Val + 1), dtype=float)
for posttap2_index in range(gMaxPosttap2Val + 1):
    initData.ami_params['tx_tap_nm2'] = posttap2_index
    for posttap1_index in range(gMaxPosttap1Val + 1):
        initData.ami_params['tx_tap_nm1'] = posttap1_index
        weights = []
        for pretap_index in range(min(gMaxPretapVal + 1, 11 - posttap2_index - posttap1_index)): # Note the constraint enforcement.
            initData.ami_params['tx_tap_np1'] = pretap_index
            theModel.initialize(initData)
            h1 = theModel.initOut
            weights.append(h1[1])
        slope, intercept, r_value, p_value, std_err = stats.linregress(range(len(weights)), weights)
        pretap_slopes[posttap2_index][posttap1_index] = slope
        pretap_rvals [posttap2_index][posttap1_index] = r_value
print "Min. |r_value|:", min(abs(pretap_rvals.flatten()))
plt.plot(pretap_slopes[0], label = "Posttap2 = 0")
plt.plot(pretap_slopes[1], label = "Posttap2 = 1")
plt.plot(pretap_slopes[2], label = "Posttap2 = 2")
plt.plot(pretap_slopes[3], label = "Posttap2 = 3")
plt.legend()
plt.title("Pre-tap equation slope vs. first post-tap value, by second post-tap value.")
plt.xlabel("First post-tap value")
plt.ylabel("Slope")
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 0)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 0)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 0)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 0)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 0)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 0)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 0)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 1)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 1)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 1)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 1)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 1)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 1)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 1)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 2)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 2)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 2)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 2)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 2)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 2)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 2)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 3)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 3)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 3)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 3)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 3)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 3)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 3)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 4)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 4)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 4)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 4)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 4)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 4)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 4)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 5)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 5)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 5)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 5)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 5)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 5)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 6)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 6)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 6)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 6)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 6)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 7)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 7)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 7)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 7)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 8)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 8)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 8)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 9)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 0)(tx_tap_nm1 9)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 0)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 0)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 0)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 0)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 0)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 0)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 0)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 1)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 1)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 1)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 1)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 1)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 1)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 1)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 2)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 2)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 2)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 2)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 2)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 2)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 2)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 3)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 3)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 3)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 3)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 3)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 3)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 3)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 4)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 4)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 4)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 4)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 4)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 4)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 5)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 5)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 5)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 5)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 5)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 6)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 6)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 6)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 6)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 7)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 7)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 7)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 8)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 8)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 9)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 0)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 0)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 0)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 0)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 0)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 0)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 0)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 1)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 1)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 1)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 1)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 1)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 1)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 1)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 2)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 2)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 2)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 2)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 2)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 2)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 2)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 3)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 3)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 3)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 3)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 3)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 3)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 4)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 4)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 4)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 4)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 4)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 5)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 5)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 5)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 5)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 6)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 6)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 6)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 7)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 7)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 2)(tx_tap_nm1 8)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 0)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 0)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 0)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 0)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 0)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 0)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 0)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 1)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 1)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 1)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 1)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 1)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 1)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 1)(tx_tap_np1 6))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 2)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 2)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 2)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 2)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 2)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 2)(tx_tap_np1 5))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 3)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 3)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 3)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 3)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 3)(tx_tap_np1 4))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 4)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 4)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 4)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 4)(tx_tap_np1 3))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 5)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 5)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 5)(tx_tap_np1 2))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 6)(tx_tap_np1 0))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 6)(tx_tap_np1 1))
(easic_tx (tx_tap_nm2 3)(tx_tap_nm1 7)(tx_tap_np1 0))
Min. |r_value|: 0.0

Out[17]:
<matplotlib.text.Text at 0x8cf1d90>

And we see that not only are the slopes independent, but they are also identical. This makes things very easy. The equations governing the weight/index relationships are, simply:

\[b_0 = 1.1 - \sum b_k ; k \not= 0\]

\[b_n = -0.0407 x_n ; n \not= 0\]

and

\[x_n = round(-24.57 b_n) ; n \not= 0\]

As a check on the equations, above, let's use them to attempt to get some precise tap weights.
The weights we'll target are: [-0.03, -0.28, -0.03].
Using the equation, above, we choose, for the user tap values: [1, 7, 1]. We find that the calculated tap values form a legal set, in that:

  • No tap exceeds its maximum value.
  • The sum of the tap values is less than 11.

So, let's plug them in and see if we get back our desired weights...

In [18]:
initData.ami_params['tx_tap_np1'] = 1
initData.ami_params['tx_tap_nm1'] = 7
initData.ami_params['tx_tap_nm2'] = 1
theModel.initialize(initData)
h1 = theModel.initOut
print h1[1], h1[9], h1[13]
(easic_tx (tx_tap_nm2 1)(tx_tap_nm1 7)(tx_tap_np1 1))
-0.0406835627906 -0.284784939534 -0.0406835627906

And we see that, to within the precision available, we have gotten back the tap weights we were intending. Success!