Saturday, December 9, 2017

Powershell Encoded Command, sqlcmd, and csv Query Output

A while back I did a post on using sqlcmd and dumping data to Excel.  At the time I was using Microsoft SQL Server's bcp (bulk copy) utility to dump data to a csv file.

Use of bcp is blocked where I am working now.  But Powershell and sqlcmd are very much available on the Windows workstations we use.  Just as with bcp, smithing text for sqlcmd input can be a little tricky, same with Powershell.  But Powershell has an EncodedCommand feature which allows you to feed input to it as a base 64 string.  This will be a quick demo of the use of this feature and output of a faux comma delimited (csv) file with data.

Disclaimer:  scripts that rely extensively on os.system() calls from Python are indeed hacky and mousetrappy.  I think the saying goes "Necessity is a mother," or something similar.  Onward.

Getting the base 64 string from the original string:

First our SQL code that queries a mock table I made in my mock database:

USE test;

SELECT testpk,
       namex,
    [value]
FROM testtable
ORDER BY testpk;

We will call this file selectdata.sql.

Then the call to sqlcmd/Powershell:

sqlcmd -S localhost -i .\selectdata.sql -E -h -1 -s "," -W  | Tee-Object -FilePath .\testoutput

In Python (we have to use Python 2.7 in our environment, so this is Python 2.x specific):

Python 2.7.6 (default, Nov 10 2013, 19:24:24) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import base64
>>> stringx = r'sqlcmd -S localhost -i .\selectdata.sql -E -h -1 -s "," -W | Tee-Object -FilePath .\testoutput'
>>> bytesx = stringx.encode('utf-16-le')
>>> encodedcommandx = base64.b64encode(bytesx)
>>> encodedcommandx
'cwBxAGwAYwBtAGQAIAAtAFMAIABsAG8AYwBhAGwAaABvAHMAdAAgAC0AaQAgAC4AXABzAGUAbABlAGMAdABkAGEAdABhAC4AcwBxAGwAIAAtAEUAIAAtAGgAIAAtADEAIAAtAHMAIAAiACwAIgAgAC0AVwAgAHwAIABUAGUAZQAtAE8AYgBqAGUAYwB0ACAALQBGAGkAbABlAFAAYQB0AGgAIAAuAFwAdABlAHMAdABvAHUAdABwAHUAdAA='
>>>

I had to type out my command in the Python interpreter.  When I pasted it in from GVim, it choked on the UTF encoding.

Now, Powershell:
PS C:\Users\ctrachte> $sqlcmdstring = 'sqlcmd -S localhost -i .\selectdata.sql -E -h -1 -s "," -W | Tee-Object -FilePath
 .\testoutput'
PS C:\Users\ctrachte> $encodedcommand = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($sqlcmdstring))
PS C:\Users\ctrachte> $encodedcommand
cwBxAGwAYwBtAGQAIAAtAFMAIABsAG8AYwBhAGwAaABvAHMAdAAgAC0AaQAgAC4AXABzAGUAbABlAGMAdABkAGEAdABhAC4AcwBxAGwAIAAtAEUAIAAtAGgAIAAtADEAIAAtAHMAIAAiACwAIgAgAC0AVwAgAHwAIABUAGUAZQAtAE8AYgBqAGUAYwB0ACAALQBGAGkAbABlAFAAYQB0AGgAIAAuAFwAdABlAHMAdABvAHUAdABwAHUAdAA=
PS C:\Users\ctrachte>

OK, the two base 64 strings are the same, so we are good.

Command Execution from os.system() call:

import os
>>> os.system(INVOKEPOWERSHELL.format(encodedcommandx))
Changed database context to 'test'.
000001,VOLUME,11.0
000002,YEAR,1999.0
(2 rows affected)
0
>>>

And, thanks to Powershell's version of UNIX-like system's tee command, we have a faux csv file as well as output to the command line.

Stackoverflow gave me much of what I needed to know for this:

Links:

Powershell's encoded command:

https://blogs.technet.microsoft.com/heyscriptingguy/2015/10/27/powertip-encode-string-and-execute-with-powershell/

sqlcmd's output to faux csv:

https://stackoverflow.com/questions/425379/how-to-export-data-as-csv-format-from-sql-server-using-sqlcmd

The UTF encoding stuff just took some trial and error and fiddling.

Thanks for stopping by.





Sunday, February 19, 2017

Filling in Missing Grouping Columns of MSSQL SSRS Report Dumped to Excel

This is another simple but common problem in certain business environments:

1) Data are presented via a Microsoft SQL Server Reporting Services report, BUT

2) The user wants the data in Excel, and, further, wants to play with it (pivot, etc.) there.  The problem is that the grouping column labels are not in every record, only in the one row that begins the list of records for that group (sanitized screenshot below):

But I don't WANT to copy and paste all those groupings for 30,000 records :*-(
I had this assignment recently from a remote request.  It took about four rounds of an e-mail exchange to figure out that it really wasn't a data problem, but a formatting one that needed solving.

It is possible to do the whole thing in Python.  I did the Excel part by hand in order to get a handle on the data:

1) In Excel, delete the extra rows on top of the report leaving just the headers and the data.

2) In Excel, select everything on the data page, format the cells correctly by unselecting the Merge Cells and Wraparound options.

3) In Excel, at this point you should be able to see if there are extra empty columns as space fillers; delete them.  Save the worksheet as a csv file.

4) In a text editor, open your csv file, identify any empty rows, and delete them.  Change column header names as desired.

Now the Python part:

#!python36

"""
Doctor csv dump from unmerged cell
dump of SSRS dump from MSSQL database.

Fill in cell gaps where merged
cells had only one grouping value
so that all rows are complete records.
"""

import pprint

COMMA = ','
EMPTY = ''

INFILE = 'rawdata.csv'
OUTFILE = 'canneddumpfixed.csv'

ERRORFLAG = 'ERROR!'

f = open(INFILE, 'r')
headerline = next(f)
numbercolumns = len(headerline.split(COMMA))

f2 = open(OUTFILE, 'w')

# Assume at least one data column on far right.
missingvalues = (numbercolumns - 1) * [ERRORFLAG]

for linex in f:
    print('Processing line {:s} . . .'.format(linex))
    splitrecord = linex.split(COMMA)
    for slotx in range(0, numbercolumns - 1):
        if splitrecord[slotx] != EMPTY:
            missingvalues[slotx] = splitrecord[slotx]
        else:
            splitrecord[slotx] = missingvalues[slotx]
    f2.write(COMMA.join(splitrecord))

f2.close()

print('Finished')


At this point you've got your data in csv format - you can open it in Excel and go to work.

There may be a free or COTS (commercial off the shelf) utility that does all this somewhere in the Microsoft "ecosystem" (I think that's their fancy enviro-friendly word for vendor-user community) but I don't know of one.


Thanks for stopping by.





Wednesday, February 15, 2017

Crude Testing of Equivalent Code With assert

In engineering and business environments, it is common to have to

1) recreate an equivalent calculation in a different format for a different purpose and check the results against the original calculation.


2) shepherd a calculation process from one vendor system through a transition to another (an upgrade, for example) by hacking a set of provisional scripts together.


3) implement a bunch of linear regressions in calculations.  If I recall correctly, there has been a linear regression functionality in Excel for ages (since the early 90's?); it is the tried and (maybe) true tool of data fitters/forcers everywhere.  Conceivably you could accurately, if not precisely, model just about any curve with enough linear segments.  Mercifully, the ones I show below have only two segments per data set.

This problem embodies all three bullets above.  I've sanitized the code which makes it a little ridiculous, but no less voluminous (sorry).

Here's what we have in the vendor's system - it is Python (2.7) code, but it's run inside special a la carte purchased software that my department doesn't have.  Also, it's full of a bunch of constants that I'm not really comfortable recognizing or maintaining:

"""
Cut and pasted formulas from vendor
specific GUI/Python API.
"""

# LOC1
def loc1fromvendor(CONTROL1,
                   CONTROL2,
                   x):
    """
    Loc1 y calculation from vendor.

    CONTROL1 is the primary code (integer
    or round digit float).
    CONTROL2 is the secondary code (integer
    or round digit float).
    x is the x-axis input.  (float).

    Returns float.
    """
    DEFAULTY = 2.50
   
    if CONTROL1 == 9:
            if CONTROL2 == 1:
                if x > 1.275:
                    Y = (-0.0003 * x) + 6.4781
                else:
                    Y = 2.53
            else:
                Y = 2.54
    elif CONTROL1 == 8:
            Y = 2.6
    elif CONTROL1 == 7:
            if CONTROL2 == 1:
                if x > 1.315:
                    Y = -0.003 * x + 6.548
                else:
                    Y = 2.6
            else:
                Y = -0.0031 * x + 2.958
    elif CONTROL1 == 6:
            if CONTROL2 == 1:
                if x >1.310:
                     Y = -0.0018 * x + 4.9307
                else:
                    Y = 2.57
            else:
                Y = -0.0004 * x + 3.0612
    elif CONTROL1 == 5:
            if CONTROL2 == 1:
                if x >1.250:
                    Y = -0.0026 * x + 5.7152
                else:
                    Y = 2.47
            else:
                Y = -0.0003 * x + 2.8733
    elif CONTROL1 == 4:
            if CONTROL2 == 1:
                if x >1.290:
                    Y = -0.0032 * x + 6.7257
                else:
                    Y = 2.6
            else:
                Y = -0.0002 * x + 2.8215
    elif CONTROL1 == 1:
            if CONTROL2 == 1:
                Y = 2.35
            else:
                Y = 2.45
    else:
            Y = DEFAULTY
    return Y

# LOC2
def loc2fromvendor(CONTROL1,
                   CONTROL2,
                   x):
    """
    Loc2 y calculation from vendor.

    CONTROL1 is the primary code (integer
    or round digit float).
    CONTROL2 is the secondary code (integer
    or round digit float).
    x is the x-axis input.  (float).

    Returns float.
    """
    DEFAULTY = 2.50
   
    if CONTROL1 == 9:
        if CONTROL2 == 1:
                Y = -0.0006 * x + 3.3121
        else:
                Y = -0.0006 * x + 3.3121
    elif CONTROL1 == 8:
            if CONTROL2 == 1:
                if x >1.050:
                    Y = 2.65
                else:
                    Y = 2.65
            else:
                if x >1.050:
                    Y = 2.65
                else:
                    Y = 2.65
    elif CONTROL1 == 7:
            if CONTROL2 == 1:
                if x > 1.050:
                    Y = -0.0012 * x + 3.886
                else:
                    Y = -0.0012 * x + 3.886
            else:
                if x > 1.050:
                    Y = -0.00007 * x + 2.6787
                else:
                    Y = -0.00007 * x + 2.6787
    elif CONTROL1 == 6:
            if CONTROL2 == 1:
                if x >1.050:
                    Y = -0.001 * x + 3.731
                else:
                    Y = -0.001 * x + 3.731
            else:
                if x >1.050:
                    Y = -0.0012 * x + 4.0757
                else:
                    Y = -0.0012 * x + 4.0757
    elif CONTROL1 == 5:
            if CONTROL2 == 1:
                if x >1.050:
                    Y = 2.1
                else:
                    Y = 2.1
            else:
                if x >1.050:
                    Y = -0.0003 * x + 2.9564
                else:
                    Y = -0.0003 * x + 2.9564
    elif CONTROL1 == 4:
            if CONTROL2 == 1:
                if x >1.050:
                    Y = -0.000009 * x + 2.1972
                else:
                    Y = -0.000009 *x + 2.1972
            else:
                if x >1.050:
                    Y = -0.0005 * x + 3.2461
                else:
                    Y = -0.0005 * x + 3.2461               
    elif CONTROL1 == 1:
            if CONTROL2 == 1:
                Y = -0.001 * x + 3.7257
            else:
                Y = -0.001 * x + 3.7257
    else:
            Y = DEFAULTY
    return Y

# LOC3
def loc3fromvendor(CONTROL1,
                   CONTROL2,
                   x):
    """
    Loc3 y calculation from vendor.

    CONTROL1 is the primary code (integer
    or round digit float).
    CONTROL2 is the secondary code (integer
    or round digit float).
    x is the x-axis input.  (float).

    Returns float.
    """
    DEFAULTY = 2.50
   
    if CONTROL1 == 9:
            Y = 2.49
    elif CONTROL1 == 8:
            if x > 1.000:
                Y = -0.0006 * x + 3.3291
            else:
                Y = 2.64
    elif CONTROL1 == 7:
            if x > 1.050:
                Y = -0.0009 * x + 3.5929
            else:
                Y = 2.67
    elif CONTROL1 == 6:
            if x > 1.080:
                Y = -0.0013 * x + 4.0665
            else:
                # Debug.
                # print 'x in vendor function = {:f}'.format(x)
                Y = 2.65
    elif CONTROL1 == 5:
            if x > 950:
                Y = -0.001 * x + 3.4996
            else:
                Y = 2.59
    elif CONTROL1 == 4:
            if x > 1.100:
                Y = -0.0018 * x + 4.6690
            else:
                Y = 2.68
    elif CONTROL1 == 1:
            if x > 1.000:
                Y = -0.0004 * x + 2.8857
            else:
                Y = 2.49
    else:
            Y = DEFAULTY
    return Y

# LOC4
def loc4fromvendor(CONTROL1,
                   CONTROL2,
                   x):
    """
    Loc4 y calculation from vendor.

    CONTROL1 is the primary code (integer
    or round digit float).
    CONTROL2 is the secondary code (integer
    or round digit float).
    x is the x-axis input.  (float).

    Returns float.
    """
    DEFAULTY = 2.50
   
    if CONTROL1 == 9:
        Y = -0.0000008 * x + 2.6761
    elif CONTROL1 == 8:
            Y = -0.000003 * x + 2.6975
    elif CONTROL1 == 7:
            if CONTROL2 == 1:
                if x > 1.000:
                    Y = -0.0018 * x + 4.3902
                else:
                    Y = 2.60
            else:
                Y = -0.00009 * x + 2.7334
    elif CONTROL1 == 6:
            if CONTROL2 == 1:
                if x > 1.100:
                     Y = -0.0013 * x + 4.0322
                else:
                    Y = 2.58
            else:
                Y = -0.0002 * x + 2.8081
    elif CONTROL1 == 5:
            if CONTROL2 == 1:
                Y = -0.0018 * x + 4.2758
            else:
                Y = -0.0001 * x + 2.6535
    elif CONTROL1 == 4:
            if CONTROL2 == 1:
                if x > 1.000:
                    Y = -0.002 * x + 4.5548
                else:
                    Y = 2.60
            else:
                if x > 1125:
                    Y = -0.0011 * x + 3.9184
                else:
                    Y = 2.65
    elif CONTROL1 == 1:
            Y = -0.0003 * x + 2.7802
    else:
            Y = DEFAULTY
    return Y



My code is less multiple function based and more a single function with a bunch of lookup dictionaries rolled into one big dictionary.  I'm not arguing my approach is necessarily better.  For instance, I implemented my x variable ranges with lower bounds based on the precision of my data.  This isn't very portable.

The need to lock down my results to keep them in line with the original led me to use of the assert statement and the writing of a little walk of my dictionary against my function and the vendor's.  This way, when I get a new "vendor function" (actually a snippet of code for a particular location or area) I can paste it into this crude ersatz test suite and see what needs changing.

I caught a few missed decimal places, typos, transposed digits, and plain old omissions in my code using this approach.  It is possible I've gone overboard with constants.  I don't care.  I have to read them and the only way I can keep them straight is by lining up the decimal places and locking them down as named constants (programmatically they are variables, but I'm not changing them).

"But why don't they and why don't you use scientific notation?"

As we used to say in the Navy years ago, "There is the right way, there is the wrong way, and the Navy way."  Guess which one the vendor uses?  Onward.

Here's my code with the "test" of equivalency for the two approaches:

"""
Attempt at generic script to process linear regressions
for multiple areas.
"""

import sys

import vendorformulas as vfx

# Loc abbreviations.
LOC1 = 'loc1'
LOC2 = 'loc2'
LOC3 = 'loc3'
LOC4 = 'loc4'

DEFAULTY = 2.50

CTL2ONE = 1
CTL2TWO = 2

BIGX = 5000.0
LITTLEX = 0.0

TYPE9 = 9
TYPE8 = 8
TYPE7 = 7
TYPE6 = 6
TYPE5 = 5
TYPE4 = 4
TYPE1 = 1
# Undefined control1 type for default for each loc.
UNDEF = 99

slope = 'm'
b = 'b'

# Compute y using formula (y = mx + b), control1, x, control2
# nested dictionaries
#     control2
#         x range
#             m
#             b
# Original logic gives unassigned CONTROL2 block to CTL2TWO interpretation
# Honor this in logic in program.

# Slope values.
NOSLOPE = 0.0

NEG0032000 = -0.0032000
NEG0031000 = -0.0031000
NEG0030000 = -0.0030000
NEG0026000 = -0.0026000
NEG0020000 = -0.0020000
NEG0018000 = -0.0018000
NEG0013000 = -0.0013000
NEG0012000 = -0.0012000
NEG0011000 = -0.0011000
NEG0010000 = -0.0010000
NEG0009000 = -0.0009000
NEG0006000 = -0.0006000
NEG0005000 = -0.0005000
NEG0004000 = -0.0004000
NEG0003000 = -0.0003000
NEG0002000 = -0.0002000
NEG0001000 = -0.0001000
NEG0000900 = -0.0000900
NEG0000700 = -0.0000700
NEG0000090 = -0.0000090
NEG0000030 = -0.0000030
NEG0000008 = -0.0000008

# Intercept values.
T2PT1000 = 2.1000
T2PT1972 = 2.1972
T2PT3500 = 2.3500
T2PT4500 = 2.4500
T2PT4700 = 2.4700
T2PT4900 = 2.4900
T2PT5300 = 2.5300
T2PT5400 = 2.5400
T2PT5700 = 2.5700
T2PT5800 = 2.5800
T2PT5900 = 2.5900
T2PT6000 = 2.6000
T2PT6400 = 2.6400
T2PT6500 = 2.6500
T2PT6535 = 2.6535
T2PT6700 = 2.6700
T2PT6761 = 2.6761
T2PT6787 = 2.6787
T2PT6800 = 2.6800
T2PT6975 = 2.6975
T2PT7334 = 2.7334
T2PT7802 = 2.7802
T2PT8081 = 2.8081
T2PT8215 = 2.8215
T2PT8733 = 2.8733
T2PT8857 = 2.8857
T2PT9564 = 2.9564
T2PT9580 = 2.9580
T3PT0612 = 3.0612
T3PT2461 = 3.2461
T3PT3121 = 3.3121
T3PT3291 = 3.3291
T3PT4996 = 3.4996
T3PT5929 = 3.5929
T3PT7257 = 3.7257
T3PT7310 = 3.7310
T3PT8860 = 3.8860
T3PT9184 = 3.9184
F4PT0322 = 4.0322
F4PT0665 = 4.0665
F4PT0757 = 4.0757
F4PT2758 = 4.2758
F4PT3902 = 4.3902
F4PT5548 = 4.5548
F4PT6690 = 4.6690
F4PT9307 = 4.9307
F5PT7152 = 5.7152
S6PT4781 = 6.4781
S6PT5480 = 6.5480
S6PT7257 = 6.7257

LOC1YS = {TYPE9:
             {CTL2ONE:
                 {(LITTLEX, 1.27500):
                     {slope:NOSLOPE, b:T2PT5300},
                  (1.27501, BIGX):
                     {slope:NEG0003000, b:S6PT4781}},
              CTL2TWO:
                 {(LITTLEX, BIGX):
                     {slope:NOSLOPE, b:T2PT5400}}},
          TYPE8:
             {CTL2ONE:
                 {(LITTLEX, BIGX):
                     {slope:NOSLOPE, b:T2PT6000}},
              CTL2TWO:
                 {(LITTLEX, BIGX):
                     {slope:NOSLOPE, b:T2PT6000}}},
          TYPE7:
             {CTL2ONE:
                 {(LITTLEX, 1.31500):
                     {slope:NOSLOPE, b:T2PT6000},
                  (1.31501, BIGX):
                     {slope:NEG0030000, b:S6PT5480}},
              CTL2TWO:
                 {(LITTLEX, BIGX):
                     {slope:NEG0031000, b:T2PT9580}}},
          TYPE6:
             {CTL2ONE:
                 {(LITTLEX, 1.31000):
                     {slope:NOSLOPE, b:T2PT5700},
                  (1.31001, BIGX):
                     {slope:NEG0018000, b:F4PT9307}},
              CTL2TWO:
                 {(LITTLEX, BIGX):
                     {slope:NEG0004000, b:T3PT0612}}},
          TYPE5:
             {CTL2ONE:
                 {(LITTLEX, 1.25000):
                     {slope:NOSLOPE, b:T2PT4700},
                  (1.25001, BIGX):
                     {slope:NEG0026000, b:F5PT7152}},
              CTL2TWO:
                 {(LITTLEX, BIGX):
                     {slope:NEG0003000, b:T2PT8733}}},
          TYPE4:
             {CTL2ONE:
                 {(LITTLEX, 1.29000):
                     {slope:NOSLOPE, b:T2PT6000},
                  (1.29001, BIGX):
                     {slope:NEG0032000, b:S6PT7257}},
              CTL2TWO:
                 {(LITTLEX, BIGX):
                     {slope:NEG0002000, b:T2PT8215}}},
          TYPE1:
             {CTL2ONE:
                 {(LITTLEX, BIGX):
                     {slope:NOSLOPE, b:T2PT3500}},
              CTL2TWO:
                 {(LITTLEX, BIGX):
                     {slope:NOSLOPE, b:T2PT4500}}},
          UNDEF:
             {CTL2ONE:
                 {(LITTLEX, BIGX):
                     {slope:NOSLOPE, b:DEFAULTY}},
              CTL2TWO:
                 {(LITTLEX, BIGX):
                     {slope:NOSLOPE, b:DEFAULTY}}}}
# END LOC1

# LOC2
LOC2YS = {TYPE9:
             {CTL2ONE:
                 {(LITTLEX, BIGX):
                     {slope:NEG0006000, b:T3PT3121}},
              CTL2TWO:
                 {(LITTLEX, BIGX):
                     {slope:NEG0006000, b:T3PT3121}}},
          TYPE8:
              {CTL2ONE:
                  {(LITTLEX, BIGX):
                      {slope:NOSLOPE, b:T2PT6500}},
               CTL2TWO:
                  {(LITTLEX, BIGX):
                      {slope:NOSLOPE, b:T2PT6500}}},
          TYPE7:{CTL2ONE:
                  {(LITTLEX, BIGX):
                      {slope:NEG0012000, b:T3PT8860}},
               CTL2TWO:
                  {(LITTLEX, BIGX):
                      {slope:NEG0000700, b:T2PT6787}}},
          TYPE6:
             {CTL2ONE:
                 {(LITTLEX, BIGX):
                     {slope:NEG0010000, b:T3PT7310}},
              CTL2TWO:
                 {(LITTLEX, BIGX):
                     {slope:NEG0012000, b:F4PT0757}}},
          TYPE5:
             {CTL2ONE:
                 {(LITTLEX, BIGX):
                     {slope:NOSLOPE, b:T2PT1000}},
              CTL2TWO:
                 {(LITTLEX, BIGX):
                     {slope:NEG0003000, b:T2PT9564}}},
          TYPE4:
             {CTL2ONE:
                 {(LITTLEX, BIGX):
                     {slope:NEG0000090, b:T2PT1972}},
              CTL2TWO:
                 {(LITTLEX, BIGX):
                     {slope:NEG0005000, b:T3PT2461}}},
          TYPE1:
             {CTL2ONE:
                 {(LITTLEX, BIGX):
                     {slope:NEG0010000, b:T3PT7257}},
              CTL2TWO:
                 {(LITTLEX, BIGX):
                     {slope:NEG0010000, b:T3PT7257}}},
          UNDEF:
             {CTL2ONE:
                 {(LITTLEX, BIGX):
                     {slope:NOSLOPE, b:DEFAULTY}},
              CTL2TWO:
                 {(LITTLEX, BIGX):
                     {slope:NOSLOPE, b:DEFAULTY}}}}
# END LOC2

LOC3YS = {TYPE9:
             {CTL2ONE:
                 {(LITTLEX, BIGX):
                     {slope:NOSLOPE, b:T2PT4900}},
              CTL2TWO:
                 {(LITTLEX, BIGX):
                     {slope:NOSLOPE, b:T2PT4900}}},
          TYPE8:{CTL2ONE:
                  {(LITTLEX, 1.00000):
                      {slope:NOSLOPE, b:T2PT6400},
                   (1.00001, BIGX):
                      {slope:NEG0006000, b:T3PT3291}},
               CTL2TWO:
                  {(LITTLEX, 1.00000):
                      {slope:NOSLOPE, b:T2PT6400},
                   (1.00001, BIGX):
                      {slope:NEG0006000, b:T3PT3291}}},
          TYPE7:{CTL2ONE:
                  {(LITTLEX, 1.05000):
                      {slope:NOSLOPE, b:T2PT6700},
                   (1.05001, BIGX):
                      {slope:NEG0009000, b:T3PT5929}},
               CTL2TWO:
                  {(LITTLEX, 1.05000):
                      {slope:NOSLOPE, b:T2PT6700},
                   (1.050001, BIGX):
                      {slope:NEG0009000, b:T3PT5929}}},
          TYPE6:
             {CTL2ONE:
                 {(LITTLEX, 1.08000):
                     {slope:NOSLOPE, b:T2PT6500},
                  (1.08001, BIGX):
                     {slope:NEG0013000, b:F4PT0665}},
              CTL2TWO:
                 {(LITTLEX, 1.08000):
                     {slope:NOSLOPE, b:T2PT6500},
                  (1.08001, BIGX):
                     {slope:NEG0013000, b:F4PT0665}}},
          TYPE5:
             {CTL2ONE:
                 {(LITTLEX, 950.0):
                     {slope:NOSLOPE, b:T2PT5900},
                  (950.01, BIGX):
                     {slope:NEG0010000, b:T3PT4996}},
              CTL2TWO:
                 {(LITTLEX, 950.0):
                     {slope:NOSLOPE, b:T2PT5900},
                  (950.01, BIGX):
                     {slope:NEG0010000, b:T3PT4996}}},
          TYPE4:
             {CTL2ONE:
                 {(LITTLEX, 1.10000):
                     {slope:NOSLOPE, b:T2PT6800},
                  (1.10001, BIGX):
                     {slope:NEG0018000, b:F4PT6690}},
              CTL2TWO:
                 {(LITTLEX, 1.10000):
                     {slope:NOSLOPE, b:T2PT6800},
                  (1.10001, BIGX):
                     {slope:NEG0018000, b:F4PT6690}}},
          TYPE1:
             {CTL2ONE:
                 {(LITTLEX, 1.00000):
                     {slope:NOSLOPE, b:T2PT4900},
                  (1.00001, BIGX):
                     {slope:NEG0004000, b:T2PT8857}},
              CTL2TWO:
                 {(LITTLEX, 1.00000):
                     {slope:NOSLOPE, b:T2PT4900},
                  (1.00001, BIGX):
                     {slope:NEG0004000, b:T2PT8857}}},
          UNDEF:
             {CTL2ONE:
                 {(LITTLEX, BIGX):
                     {slope:NOSLOPE, b:DEFAULTY}},
              CTL2TWO:
                 {(LITTLEX, BIGX):
                     {slope:NOSLOPE, b:DEFAULTY}}}}
# END LOC3

# LOC4
LOC4YS = {TYPE9:
             {CTL2ONE:
                 {(LITTLEX, BIGX):
                     {slope:NEG0000008, b:T2PT6761}},
              CTL2TWO:
                 {(LITTLEX, BIGX):
                     {slope:NEG0000008, b:T2PT6761}}},
          TYPE8:{CTL2ONE:
                  {(LITTLEX, BIGX):
                      {slope:NEG0000030, b:T2PT6975}},
               CTL2TWO:
                  {(LITTLEX, BIGX):
                      {slope:NEG0000030, b:T2PT6975}}},
          TYPE7:
             {CTL2ONE:
                 {(LITTLEX, 1.00000):
                     {slope:NOSLOPE, b:T2PT6000},
                  (1.00001, BIGX):
                     {slope:NEG0018000, b:F4PT3902}},
              CTL2TWO:
                 {(LITTLEX, BIGX):
                     {slope:NEG0000900, b:T2PT7334}}},
          TYPE6:
             {CTL2ONE:
                 {(LITTLEX, 1.10000):
                     {slope:NOSLOPE, b:T2PT5800},
                  (1.10001, BIGX):
                     {slope:NEG0013000, b:F4PT0322}},
              CTL2TWO:
                 {(LITTLEX, BIGX):
                     {slope:NEG0002000, b:T2PT8081}}},
          TYPE5:
             {CTL2ONE:
                 {(LITTLEX, BIGX):
                     {slope:NEG0018000, b:F4PT2758}},
              CTL2TWO:
                 {(LITTLEX, BIGX):
                     {slope:NEG0001000, b:T2PT6535}}},
          TYPE4:
             {CTL2ONE:
                 {(LITTLEX, 1.00000):
                     {slope:NOSLOPE, b:T2PT6000},
                  (1.00001, BIGX):
                     {slope:NEG0020000, b:F4PT5548}},
              CTL2TWO:
                 {(LITTLEX, 1125.0):
                     {slope:NOSLOPE, b:T2PT6500},
                  (1125.01, BIGX):
                     {slope:NEG0011000, b:T3PT9184}}},
          TYPE1:
             {CTL2ONE:
                 {(LITTLEX, BIGX):
                     {slope:NEG0003000, b:T2PT7802}},
              CTL2TWO:
                 {(LITTLEX, BIGX):
                     {slope:NEG0003000, b:T2PT7802}}},
          UNDEF:
             {CTL2ONE:
                 {(LITTLEX, BIGX):
                     {slope:NOSLOPE, b:DEFAULTY}},
              CTL2TWO:
                 {(LITTLEX, BIGX):
                     {slope:NOSLOPE, b:DEFAULTY}}}}
# END LOC4

YS = {LOC1:LOC1YS,
      LOC2:LOC2YS,
      LOC3:LOC3YS,
      LOC4:LOC4YS}

VALIDCONTROL1 = [TYPE9, TYPE8, TYPE7, TYPE6, TYPE5, TYPE4, TYPE1]

RETURNDEFAULTMSG = 'Returning default Y for  {0:s}, {1:2.0f}, {2:2.0f}, {3:8.5f} . .  .'
TESTINGMSG = 'Testing dictionary based y == function based y for {0:s}, {1:d}, {2:d}, {3:8.5f} . .  .'
ASSERTIONERRORMSG = 'Assertion Error for {0:s}, {1:f}, {2:d}, {3:8.5f} . . .'

def gety(loc, control1, x, control2):
    """
    y calculation for y = mx + b.

    loc is the four letter loc abbreviation (loc1).

    control1 is the integer CONTROL1 code.

    x is a float for the x component of y = mx + b.

    control2 is the integer CONTROL2 code.
    """
    # Compute y using formula (y = mx + b), control1, x, control2.
    # Match loc.
    ydictionary = YS[loc]
    # Check if control1 code belongs to recognized types.
    if control1 in VALIDCONTROL1:
        # Match control1.
        for control2x in ydictionary[control1]:
            # match control2.
            for xrangex in ydictionary[control1][control2]:
                # match x range.
                if (x >= xrangex[0] and
                    x <= xrangex[1] and control2x == control2):
                    mxb = ydictionary[control1][control2][xrangex]
                    y = mxb[slope] * x + mxb[b]
                    return y
        # Possible that control2 not defined;
        # Defaults to CONTROL2TWO.
        for xrangex in ydictionary[control1][CTL2TWO]:
            # match elevation range.
            if (x >= xrangex[0] and
                x <= xrangex[1]):
                mxb = ydictionary[control1][CTL2TWO][xrangex]
                y = mxb[slope] * x + mxb[b]
                return y
    # Doesn't matter if CTL2TWO or CTL2ONE or undefined
    #     - default for loc will always be [UNDEF][CTL2TWO].
    print RETURNDEFAULTMSG.format(loc, control1, control2, x)
    return ydictionary[UNDEF][CTL2TWO][(LITTLEX, BIGX)][b]

# TEST Calculations.
TESTFUNCS = {LOC1:vfx.loc1fromvendor,
             LOC2:vfx.loc2fromvendor,
             LOC3:vfx.loc3fromvendor,
             LOC4:vfx.loc4fromvendor}

for locx in YS:
    for control1 in YS[locx]:
        for control2 in YS[locx][control1]:
            for xrangex in YS[locx][control1][control2]:
                for z in xrangex:
                    dictionarybasedy = gety(locx, control1, z, control2)
                    functionbasedy = TESTFUNCS[locx](control1, control2, z)
                    print TESTINGMSG.format(locx, control1, control2, z)
                    print 'dictionarybasedy = {0:8.7f}'.format(dictionarybasedy)
                    print 'functionbasedy = {0:8.7f}'.format(functionbasedy)
                    try:
                        assert dictionarybasedy == functionbasedy
                    except AssertionError:
                        print ASSERTIONERRORMSG.format(locx, control1, control2, z)
                        sys.exit()








And the output:


Testing dictionary based y == function based y for loc2, 1, 1,  0.00000 . .  .
dictionarybasedy = 3.7257000
functionbasedy = 3.7257000
Testing dictionary based y == function based y for loc2, 1, 1, 5000.00000 . .  .
dictionarybasedy = -1.2743000
functionbasedy = -1.2743000
Testing dictionary based y == function based y for loc2, 1, 2,  0.00000 . .  .
dictionarybasedy = 3.7257000
functionbasedy = 3.7257000
Testing dictionary based y == function based y for loc2, 1, 2, 5000.00000 . .  .
dictionarybasedy = -1.2743000
functionbasedy = -1.2743000
Returning default Y for  loc2, 99,  1,  0.00000 . .  .
Testing dictionary based y == function based y for loc2, 99, 1,  0.00000 . .  .
dictionarybasedy = 2.5000000
functionbasedy = 2.5000000
Returning default Y for  loc2, 99,  1, 5000.00000 . .  .
Testing dictionary based y == function based y for loc2, 99, 1, 5000.00000 . .  .
dictionarybasedy = 2.5000000
functionbasedy = 2.5000000
Returning default Y for  loc2, 99,  2,  0.00000 . .  .
Testing dictionary based y == function based y for loc2, 99, 2,  0.00000 . .  .
dictionarybasedy = 2.5000000
functionbasedy = 2.5000000
Returning default Y for  loc2, 99,  2, 5000.00000 . .  .
Testing dictionary based y == function based y for loc2, 99, 2, 5000.00000 . .  .
dictionarybasedy = 2.5000000
functionbasedy = 2.5000000
Testing dictionary based y == function based y for loc2, 4, 1,  0.00000 . .  .
dictionarybasedy = 2.1972000
functionbasedy = 2.1972000
Testing dictionary based y == function based y for loc2, 4, 1, 5000.00000 . .  .
dictionarybasedy = 2.1522000
functionbasedy = 2.1522000
Testing dictionary based y == function based y for loc2, 4, 2,  0.00000 . .  .
dictionarybasedy = 3.2461000
functionbasedy = 3.2461000
Testing dictionary based y == function based y for loc2, 4, 2, 5000.00000 . .  .
dictionarybasedy = 0.7461000
functionbasedy = 0.7461000
Testing dictionary based y == function based y for loc2, 5, 1,  0.00000 . .  .
dictionarybasedy = 2.1000000
functionbasedy = 2.1000000
Testing dictionary based y == function based y for loc2, 5, 1, 5000.00000 . .  .
dictionarybasedy = 2.1000000
functionbasedy = 2.1000000
Testing dictionary based y == function based y for loc2, 5, 2,  0.00000 . .  .
dictionarybasedy = 2.9564000
functionbasedy = 2.9564000
Testing dictionary based y == function based y for loc2, 5, 2, 5000.00000 . .  .
dictionarybasedy = 1.4564000
functionbasedy = 1.4564000
Testing dictionary based y == function based y for loc2, 6, 1,  0.00000 . .  .
dictionarybasedy = 3.7310000
functionbasedy = 3.7310000
Testing dictionary based y == function based y for loc2, 6, 1, 5000.00000 . .  .
dictionarybasedy = -1.2690000
functionbasedy = -1.2690000
Testing dictionary based y == function based y for loc2, 6, 2,  0.00000 . .  .
dictionarybasedy = 4.0757000
functionbasedy = 4.0757000
Testing dictionary based y == function based y for loc2, 6, 2, 5000.00000 . .  .
dictionarybasedy = -1.9243000
functionbasedy = -1.9243000
Testing dictionary based y == function based y for loc2, 7, 1,  0.00000 . .  .
dictionarybasedy = 3.8860000
functionbasedy = 3.8860000
Testing dictionary based y == function based y for loc2, 7, 1, 5000.00000 . .  .
dictionarybasedy = -2.1140000
functionbasedy = -2.1140000
Testing dictionary based y == function based y for loc2, 7, 2,  0.00000 . .  .
dictionarybasedy = 2.6787000
functionbasedy = 2.6787000
Testing dictionary based y == function based y for loc2, 7, 2, 5000.00000 . .  .
dictionarybasedy = 2.3287000
functionbasedy = 2.3287000
Testing dictionary based y == function based y for loc2, 8, 1,  0.00000 . .  .
dictionarybasedy = 2.6500000
functionbasedy = 2.6500000
Testing dictionary based y == function based y for loc2, 8, 1, 5000.00000 . .  .
dictionarybasedy = 2.6500000
functionbasedy = 2.6500000
Testing dictionary based y == function based y for loc2, 8, 2,  0.00000 . .  .
dictionarybasedy = 2.6500000
functionbasedy = 2.6500000
Testing dictionary based y == function based y for loc2, 8, 2, 5000.00000 . .  .
dictionarybasedy = 2.6500000
functionbasedy = 2.6500000
Testing dictionary based y == function based y for loc2, 9, 1,  0.00000 . .  .
dictionarybasedy = 3.3121000
functionbasedy = 3.3121000
Testing dictionary based y == function based y for loc2, 9, 1, 5000.00000 . .  .
dictionarybasedy = 0.3121000
functionbasedy = 0.3121000
Testing dictionary based y == function based y for loc2, 9, 2,  0.00000 . .  .
dictionarybasedy = 3.3121000
functionbasedy = 3.3121000
Testing dictionary based y == function based y for loc2, 9, 2, 5000.00000 . .  .
dictionarybasedy = 0.3121000
functionbasedy = 0.3121000
Testing dictionary based y == function based y for loc3, 1, 1,  0.00000 . .  .
dictionarybasedy = 2.4900000
functionbasedy = 2.4900000
Testing dictionary based y == function based y for loc3, 1, 1,  1.00000 . .  .
dictionarybasedy = 2.4900000
functionbasedy = 2.4900000
Testing dictionary based y == function based y for loc3, 1, 1,  1.00001 . .  .
dictionarybasedy = 2.8853000
functionbasedy = 2.8853000
Testing dictionary based y == function based y for loc3, 1, 1, 5000.00000 . .  .
dictionarybasedy = 0.8857000
functionbasedy = 0.8857000
Testing dictionary based y == function based y for loc3, 1, 2,  0.00000 . .  .
dictionarybasedy = 2.4900000
functionbasedy = 2.4900000
Testing dictionary based y == function based y for loc3, 1, 2,  1.00000 . .  .
dictionarybasedy = 2.4900000
functionbasedy = 2.4900000
Testing dictionary based y == function based y for loc3, 1, 2,  1.00001 . .  .
dictionarybasedy = 2.8853000
functionbasedy = 2.8853000
Testing dictionary based y == function based y for loc3, 1, 2, 5000.00000 . .  .
dictionarybasedy = 0.8857000
functionbasedy = 0.8857000
Returning default Y for  loc3, 99,  1,  0.00000 . .  .
Testing dictionary based y == function based y for loc3, 99, 1,  0.00000 . .  .
dictionarybasedy = 2.5000000
functionbasedy = 2.5000000
Returning default Y for  loc3, 99,  1, 5000.00000 . .  .
Testing dictionary based y == function based y for loc3, 99, 1, 5000.00000 . .  .
dictionarybasedy = 2.5000000
functionbasedy = 2.5000000
Returning default Y for  loc3, 99,  2,  0.00000 . .  .
Testing dictionary based y == function based y for loc3, 99, 2,  0.00000 . .  .
dictionarybasedy = 2.5000000
functionbasedy = 2.5000000
Returning default Y for  loc3, 99,  2, 5000.00000 . .  .
Testing dictionary based y == function based y for loc3, 99, 2, 5000.00000 . .  .
dictionarybasedy = 2.5000000
functionbasedy = 2.5000000
Testing dictionary based y == function based y for loc3, 4, 1,  0.00000 . .  .
dictionarybasedy = 2.6800000
functionbasedy = 2.6800000
Testing dictionary based y == function based y for loc3, 4, 1,  1.10000 . .  .
dictionarybasedy = 2.6800000
functionbasedy = 2.6800000
Testing dictionary based y == function based y for loc3, 4, 1,  1.10001 . .  .
dictionarybasedy = 4.6670200
functionbasedy = 4.6670200
Testing dictionary based y == function based y for loc3, 4, 1, 5000.00000 . .  .
dictionarybasedy = -4.3310000
functionbasedy = -4.3310000
Testing dictionary based y == function based y for loc3, 4, 2,  0.00000 . .  .
dictionarybasedy = 2.6800000
functionbasedy = 2.6800000
Testing dictionary based y == function based y for loc3, 4, 2,  1.10000 . .  .
dictionarybasedy = 2.6800000
functionbasedy = 2.6800000
Testing dictionary based y == function based y for loc3, 4, 2,  1.10001 . .  .
dictionarybasedy = 4.6670200
functionbasedy = 4.6670200
Testing dictionary based y == function based y for loc3, 4, 2, 5000.00000 . .  .
dictionarybasedy = -4.3310000
functionbasedy = -4.3310000
Testing dictionary based y == function based y for loc3, 5, 1, 950.01000 . .  .
dictionarybasedy = 2.5495900
functionbasedy = 2.5495900
Testing dictionary based y == function based y for loc3, 5, 1, 5000.00000 . .  .
dictionarybasedy = -1.5004000
functionbasedy = -1.5004000
Testing dictionary based y == function based y for loc3, 5, 1,  0.00000 . .  .
dictionarybasedy = 2.5900000
functionbasedy = 2.5900000
Testing dictionary based y == function based y for loc3, 5, 1, 950.00000 . .  .
dictionarybasedy = 2.5900000
functionbasedy = 2.5900000
Testing dictionary based y == function based y for loc3, 5, 2, 950.01000 . .  .
dictionarybasedy = 2.5495900
functionbasedy = 2.5495900
Testing dictionary based y == function based y for loc3, 5, 2, 5000.00000 . .  .
dictionarybasedy = -1.5004000
functionbasedy = -1.5004000
Testing dictionary based y == function based y for loc3, 5, 2,  0.00000 . .  .
dictionarybasedy = 2.5900000
functionbasedy = 2.5900000
Testing dictionary based y == function based y for loc3, 5, 2, 950.00000 . .  .
dictionarybasedy = 2.5900000
functionbasedy = 2.5900000
Testing dictionary based y == function based y for loc3, 6, 1,  0.00000 . .  .
dictionarybasedy = 2.6500000
functionbasedy = 2.6500000
Testing dictionary based y == function based y for loc3, 6, 1,  1.08000 . .  .
dictionarybasedy = 2.6500000
functionbasedy = 2.6500000
Testing dictionary based y == function based y for loc3, 6, 1,  1.08001 . .  .
dictionarybasedy = 4.0650960
functionbasedy = 4.0650960
Testing dictionary based y == function based y for loc3, 6, 1, 5000.00000 . .  .
dictionarybasedy = -2.4335000
functionbasedy = -2.4335000
Testing dictionary based y == function based y for loc3, 6, 2,  0.00000 . .  .
dictionarybasedy = 2.6500000
functionbasedy = 2.6500000
Testing dictionary based y == function based y for loc3, 6, 2,  1.08000 . .  .
dictionarybasedy = 2.6500000
functionbasedy = 2.6500000
Testing dictionary based y == function based y for loc3, 6, 2,  1.08001 . .  .
dictionarybasedy = 4.0650960
functionbasedy = 4.0650960
Testing dictionary based y == function based y for loc3, 6, 2, 5000.00000 . .  .
dictionarybasedy = -2.4335000
functionbasedy = -2.4335000
Testing dictionary based y == function based y for loc3, 7, 1,  0.00000 . .  .
dictionarybasedy = 2.6700000
functionbasedy = 2.6700000
Testing dictionary based y == function based y for loc3, 7, 1,  1.05000 . .  .
dictionarybasedy = 2.6700000
functionbasedy = 2.6700000
Testing dictionary based y == function based y for loc3, 7, 1,  1.05001 . .  .
dictionarybasedy = 3.5919550
functionbasedy = 3.5919550
Testing dictionary based y == function based y for loc3, 7, 1, 5000.00000 . .  .
dictionarybasedy = -0.9071000
functionbasedy = -0.9071000
Testing dictionary based y == function based y for loc3, 7, 2,  0.00000 . .  .
dictionarybasedy = 2.6700000
functionbasedy = 2.6700000
Testing dictionary based y == function based y for loc3, 7, 2,  1.05000 . .  .
dictionarybasedy = 2.6700000
functionbasedy = 2.6700000
Testing dictionary based y == function based y for loc3, 7, 2,  1.05000 . .  .
dictionarybasedy = 3.5919550
functionbasedy = 3.5919550
Testing dictionary based y == function based y for loc3, 7, 2, 5000.00000 . .  .
dictionarybasedy = -0.9071000
functionbasedy = -0.9071000
Testing dictionary based y == function based y for loc3, 8, 1,  0.00000 . .  .
dictionarybasedy = 2.6400000
functionbasedy = 2.6400000
Testing dictionary based y == function based y for loc3, 8, 1,  1.00000 . .  .
dictionarybasedy = 2.6400000
functionbasedy = 2.6400000
Testing dictionary based y == function based y for loc3, 8, 1,  1.00001 . .  .
dictionarybasedy = 3.3285000
functionbasedy = 3.3285000
Testing dictionary based y == function based y for loc3, 8, 1, 5000.00000 . .  .
dictionarybasedy = 0.3291000
functionbasedy = 0.3291000
Testing dictionary based y == function based y for loc3, 8, 2,  0.00000 . .  .
dictionarybasedy = 2.6400000
functionbasedy = 2.6400000
Testing dictionary based y == function based y for loc3, 8, 2,  1.00000 . .  .
dictionarybasedy = 2.6400000
functionbasedy = 2.6400000
Testing dictionary based y == function based y for loc3, 8, 2,  1.00001 . .  .
dictionarybasedy = 3.3285000
functionbasedy = 3.3285000
Testing dictionary based y == function based y for loc3, 8, 2, 5000.00000 . .  .
dictionarybasedy = 0.3291000
functionbasedy = 0.3291000
Testing dictionary based y == function based y for loc3, 9, 1,  0.00000 . .  .
dictionarybasedy = 2.4900000
functionbasedy = 2.4900000
Testing dictionary based y == function based y for loc3, 9, 1, 5000.00000 . .  .
dictionarybasedy = 2.4900000
functionbasedy = 2.4900000
Testing dictionary based y == function based y for loc3, 9, 2,  0.00000 . .  .
dictionarybasedy = 2.4900000
functionbasedy = 2.4900000
Testing dictionary based y == function based y for loc3, 9, 2, 5000.00000 . .  .
dictionarybasedy = 2.4900000
functionbasedy = 2.4900000
Testing dictionary based y == function based y for loc1, 1, 1,  0.00000 . .  .
dictionarybasedy = 2.3500000
functionbasedy = 2.3500000
Testing dictionary based y == function based y for loc1, 1, 1, 5000.00000 . .  .
dictionarybasedy = 2.3500000
functionbasedy = 2.3500000
Testing dictionary based y == function based y for loc1, 1, 2,  0.00000 . .  .
dictionarybasedy = 2.4500000
functionbasedy = 2.4500000
Testing dictionary based y == function based y for loc1, 1, 2, 5000.00000 . .  .
dictionarybasedy = 2.4500000
functionbasedy = 2.4500000
Returning default Y for  loc1, 99,  1,  0.00000 . .  .
Testing dictionary based y == function based y for loc1, 99, 1,  0.00000 . .  .
dictionarybasedy = 2.5000000
functionbasedy = 2.5000000
Returning default Y for  loc1, 99,  1, 5000.00000 . .  .
Testing dictionary based y == function based y for loc1, 99, 1, 5000.00000 . .  .
dictionarybasedy = 2.5000000
functionbasedy = 2.5000000
Returning default Y for  loc1, 99,  2,  0.00000 . .  .
Testing dictionary based y == function based y for loc1, 99, 2,  0.00000 . .  .
dictionarybasedy = 2.5000000
functionbasedy = 2.5000000
Returning default Y for  loc1, 99,  2, 5000.00000 . .  .
Testing dictionary based y == function based y for loc1, 99, 2, 5000.00000 . .  .
dictionarybasedy = 2.5000000
functionbasedy = 2.5000000
Testing dictionary based y == function based y for loc1, 4, 1,  1.29001 . .  .
dictionarybasedy = 6.7215720
functionbasedy = 6.7215720
Testing dictionary based y == function based y for loc1, 4, 1, 5000.00000 . .  .
dictionarybasedy = -9.2743000
functionbasedy = -9.2743000
Testing dictionary based y == function based y for loc1, 4, 1,  0.00000 . .  .
dictionarybasedy = 2.6000000
functionbasedy = 2.6000000
Testing dictionary based y == function based y for loc1, 4, 1,  1.29000 . .  .
dictionarybasedy = 2.6000000
functionbasedy = 2.6000000
Testing dictionary based y == function based y for loc1, 4, 2,  0.00000 . .  .
dictionarybasedy = 2.8215000
functionbasedy = 2.8215000
Testing dictionary based y == function based y for loc1, 4, 2, 5000.00000 . .  .
dictionarybasedy = 1.8215000
functionbasedy = 1.8215000
Testing dictionary based y == function based y for loc1, 5, 1,  1.25001 . .  .
dictionarybasedy = 5.7119500
functionbasedy = 5.7119500
Testing dictionary based y == function based y for loc1, 5, 1, 5000.00000 . .  .
dictionarybasedy = -7.2848000
functionbasedy = -7.2848000
Testing dictionary based y == function based y for loc1, 5, 1,  0.00000 . .  .
dictionarybasedy = 2.4700000
functionbasedy = 2.4700000
Testing dictionary based y == function based y for loc1, 5, 1,  1.25000 . .  .
dictionarybasedy = 2.4700000
functionbasedy = 2.4700000
Testing dictionary based y == function based y for loc1, 5, 2,  0.00000 . .  .
dictionarybasedy = 2.8733000
functionbasedy = 2.8733000
Testing dictionary based y == function based y for loc1, 5, 2, 5000.00000 . .  .
dictionarybasedy = 1.3733000
functionbasedy = 1.3733000
Testing dictionary based y == function based y for loc1, 6, 1,  0.00000 . .  .
dictionarybasedy = 2.5700000
functionbasedy = 2.5700000
Testing dictionary based y == function based y for loc1, 6, 1,  1.31000 . .  .
dictionarybasedy = 2.5700000
functionbasedy = 2.5700000
Testing dictionary based y == function based y for loc1, 6, 1,  1.31001 . .  .
dictionarybasedy = 4.9283420
functionbasedy = 4.9283420
Testing dictionary based y == function based y for loc1, 6, 1, 5000.00000 . .  .
dictionarybasedy = -4.0693000
functionbasedy = -4.0693000
Testing dictionary based y == function based y for loc1, 6, 2,  0.00000 . .  .
dictionarybasedy = 3.0612000
functionbasedy = 3.0612000
Testing dictionary based y == function based y for loc1, 6, 2, 5000.00000 . .  .
dictionarybasedy = 1.0612000
functionbasedy = 1.0612000
Testing dictionary based y == function based y for loc1, 7, 1,  1.31501 . .  .
dictionarybasedy = 6.5440550
functionbasedy = 6.5440550
Testing dictionary based y == function based y for loc1, 7, 1, 5000.00000 . .  .
dictionarybasedy = -8.4520000
functionbasedy = -8.4520000
Testing dictionary based y == function based y for loc1, 7, 1,  0.00000 . .  .
dictionarybasedy = 2.6000000
functionbasedy = 2.6000000
Testing dictionary based y == function based y for loc1, 7, 1,  1.31500 . .  .
dictionarybasedy = 2.6000000
functionbasedy = 2.6000000
Testing dictionary based y == function based y for loc1, 7, 2,  0.00000 . .  .
dictionarybasedy = 2.9580000
functionbasedy = 2.9580000
Testing dictionary based y == function based y for loc1, 7, 2, 5000.00000 . .  .
dictionarybasedy = -12.5420000
functionbasedy = -12.5420000
Testing dictionary based y == function based y for loc1, 8, 1,  0.00000 . .  .
dictionarybasedy = 2.6000000
functionbasedy = 2.6000000
Testing dictionary based y == function based y for loc1, 8, 1, 5000.00000 . .  .
dictionarybasedy = 2.6000000
functionbasedy = 2.6000000
Testing dictionary based y == function based y for loc1, 8, 2,  0.00000 . .  .
dictionarybasedy = 2.6000000
functionbasedy = 2.6000000
Testing dictionary based y == function based y for loc1, 8, 2, 5000.00000 . .  .
dictionarybasedy = 2.6000000
functionbasedy = 2.6000000
Testing dictionary based y == function based y for loc1, 9, 1,  0.00000 . .  .
dictionarybasedy = 2.5300000
functionbasedy = 2.5300000
Testing dictionary based y == function based y for loc1, 9, 1,  1.27500 . .  .
dictionarybasedy = 2.5300000
functionbasedy = 2.5300000
Testing dictionary based y == function based y for loc1, 9, 1,  1.27501 . .  .
dictionarybasedy = 6.4777175
functionbasedy = 6.4777175
Testing dictionary based y == function based y for loc1, 9, 1, 5000.00000 . .  .
dictionarybasedy = 4.9781000
functionbasedy = 4.9781000
Testing dictionary based y == function based y for loc1, 9, 2,  0.00000 . .  .
dictionarybasedy = 2.5400000
functionbasedy = 2.5400000
Testing dictionary based y == function based y for loc1, 9, 2, 5000.00000 . .  .
dictionarybasedy = 2.5400000
functionbasedy = 2.5400000
Testing dictionary based y == function based y for loc4, 1, 1,  0.00000 . .  .
dictionarybasedy = 2.7802000
functionbasedy = 2.7802000
Testing dictionary based y == function based y for loc4, 1, 1, 5000.00000 . .  .
dictionarybasedy = 1.2802000
functionbasedy = 1.2802000
Testing dictionary based y == function based y for loc4, 1, 2,  0.00000 . .  .
dictionarybasedy = 2.7802000
functionbasedy = 2.7802000
Testing dictionary based y == function based y for loc4, 1, 2, 5000.00000 . .  .
dictionarybasedy = 1.2802000
functionbasedy = 1.2802000
Returning default Y for  loc4, 99,  1,  0.00000 . .  .
Testing dictionary based y == function based y for loc4, 99, 1,  0.00000 . .  .
dictionarybasedy = 2.5000000
functionbasedy = 2.5000000
Returning default Y for  loc4, 99,  1, 5000.00000 . .  .
Testing dictionary based y == function based y for loc4, 99, 1, 5000.00000 . .  .
dictionarybasedy = 2.5000000
functionbasedy = 2.5000000
Returning default Y for  loc4, 99,  2,  0.00000 . .  .
Testing dictionary based y == function based y for loc4, 99, 2,  0.00000 . .  .
dictionarybasedy = 2.5000000
functionbasedy = 2.5000000
Returning default Y for  loc4, 99,  2, 5000.00000 . .  .
Testing dictionary based y == function based y for loc4, 99, 2, 5000.00000 . .  .
dictionarybasedy = 2.5000000
functionbasedy = 2.5000000
Testing dictionary based y == function based y for loc4, 4, 1,  0.00000 . .  .
dictionarybasedy = 2.6000000
functionbasedy = 2.6000000
Testing dictionary based y == function based y for loc4, 4, 1,  1.00000 . .  .
dictionarybasedy = 2.6000000
functionbasedy = 2.6000000
Testing dictionary based y == function based y for loc4, 4, 1,  1.00001 . .  .
dictionarybasedy = 4.5528000
functionbasedy = 4.5528000
Testing dictionary based y == function based y for loc4, 4, 1, 5000.00000 . .  .
dictionarybasedy = -5.4452000
functionbasedy = -5.4452000
Testing dictionary based y == function based y for loc4, 4, 2,  0.00000 . .  .
dictionarybasedy = 2.6500000
functionbasedy = 2.6500000
Testing dictionary based y == function based y for loc4, 4, 2, 1125.00000 . .  .
dictionarybasedy = 2.6500000
functionbasedy = 2.6500000
Testing dictionary based y == function based y for loc4, 4, 2, 1125.01000 . .  .
dictionarybasedy = 2.6808890
functionbasedy = 2.6808890
Testing dictionary based y == function based y for loc4, 4, 2, 5000.00000 . .  .
dictionarybasedy = -1.5816000
functionbasedy = -1.5816000
Testing dictionary based y == function based y for loc4, 5, 1,  0.00000 . .  .
dictionarybasedy = 4.2758000
functionbasedy = 4.2758000
Testing dictionary based y == function based y for loc4, 5, 1, 5000.00000 . .  .
dictionarybasedy = -4.7242000
functionbasedy = -4.7242000
Testing dictionary based y == function based y for loc4, 5, 2,  0.00000 . .  .
dictionarybasedy = 2.6535000
functionbasedy = 2.6535000
Testing dictionary based y == function based y for loc4, 5, 2, 5000.00000 . .  .
dictionarybasedy = 2.1535000
functionbasedy = 2.1535000
Testing dictionary based y == function based y for loc4, 6, 1,  0.00000 . .  .
dictionarybasedy = 2.5800000
functionbasedy = 2.5800000
Testing dictionary based y == function based y for loc4, 6, 1,  1.10000 . .  .
dictionarybasedy = 2.5800000
functionbasedy = 2.5800000
Testing dictionary based y == function based y for loc4, 6, 1,  1.10001 . .  .
dictionarybasedy = 4.0307700
functionbasedy = 4.0307700
Testing dictionary based y == function based y for loc4, 6, 1, 5000.00000 . .  .
dictionarybasedy = -2.4678000
functionbasedy = -2.4678000
Testing dictionary based y == function based y for loc4, 6, 2,  0.00000 . .  .
dictionarybasedy = 2.8081000
functionbasedy = 2.8081000
Testing dictionary based y == function based y for loc4, 6, 2, 5000.00000 . .  .
dictionarybasedy = 1.8081000
functionbasedy = 1.8081000
Testing dictionary based y == function based y for loc4, 7, 1,  0.00000 . .  .
dictionarybasedy = 2.6000000
functionbasedy = 2.6000000
Testing dictionary based y == function based y for loc4, 7, 1,  1.00000 . .  .
dictionarybasedy = 2.6000000
functionbasedy = 2.6000000
Testing dictionary based y == function based y for loc4, 7, 1,  1.00001 . .  .
dictionarybasedy = 4.3884000
functionbasedy = 4.3884000
Testing dictionary based y == function based y for loc4, 7, 1, 5000.00000 . .  .
dictionarybasedy = -4.6098000
functionbasedy = -4.6098000
Testing dictionary based y == function based y for loc4, 7, 2,  0.00000 . .  .
dictionarybasedy = 2.7334000
functionbasedy = 2.7334000
Testing dictionary based y == function based y for loc4, 7, 2, 5000.00000 . .  .
dictionarybasedy = 2.2834000
functionbasedy = 2.2834000


And that's it.  It bails on an AssertionError - I like to fix problems one at a time.  It took me about six runs to get everything matched.


Thank you for stopping by.