Page 1 of 1

NMODL: TABLE for procedure with 2 arguments

Posted: Wed May 21, 2008 6:56 am
by bhalterm
What is the proper syntax for TABLE in a procedure with 2 arguments? Also, one of the arguments will only have 3 possible values which are not evenly spaced. Is there a way to have the table constructed with just those 3 values of that argument? I could use an IF block to choose from 3 versions of the procedure with the 2nd argument hard coded in, but that would be super ugly.

Posted: Thu May 22, 2008 1:51 pm
by hines
I'm afraid that TABLE is in fact limited to a single parameter
typically voltage). So
unless your two parameter function is separable so that
a(x, y) = b(c(x), d(y)) in which b is simple or
a(x, y) = b(c(x,y)) in which c is simple, you would be forced to use
the two parameter
FUNCTION_TABLE f(x, y)
For one and two arg FUNCTION_TABLE, linear interpolation is used.
For more than two args, the nearest table point is returned. i.e think of
it as a multidimensional step function.

It is easy to declare this in a mod file. The array itself along with
filling the array with and attaching it to the mod file's f(x,y) is
done in hoc. Let me know if you want to pursue the FUNCTION_TABLE
approach.

Posted: Fri May 23, 2008 10:03 am
by bhalterm
FUNCTION_TABLE sounds like a good solution. I'm familiar with single argument FUNCTION_TABLEs, but more than one argument... not so much. Thanks for the help.

Posted: Fri May 23, 2008 10:32 am
by hines
Here is an example. Consider
ftest.mod

Code: Select all

NEURON {
 SUFFIX nothing
}

FUNCTION_TABLE f(x,y)

PROCEDURE p(x, y) {
 printf("x=%g y=%g f=%g\n", x, y, f(x, y))
}
and ftest.hoc

Code: Select all

double a[1][1]

proc mktable() {
        nx = $1
        ny = $2
        double a[nx][ny] // x then y
        xmin = 0
        xmax = 5
        ymin = -1
        ymax = 1
        table_f(&a[0][0], nx, xmin, xmax,  ny, ymin, ymax)
        fill()
}

proc fill() {local i, j, x, y
        for i=0, nx-1 {
                x = xmin + (xmax - xmin)*i/(nx-1)
                for j=0, ny-1 {
                        y = ymin + (ymax - ymin)*j/(ny-1)
                        a[i][j] = analytic(x, y)
                }
        }
}

func analytic() {
        return exp($1)*cos($2)
}

objref rx, ry

proc test() {local i
        print "table ", $1, $2
        mktable($1, $2)
        rx = new Random(1)
        ry = new Random(2)
        rx.uniform(xmin, xmax)
        ry.uniform(ymin, ymax)
        for i=1, 10 {
                x = rx.repick()
                y = ry.repick()
                printf("%g  ", (f(x, y) - analytic(x, y))/analytic(x, y))
                p(x,y)
        }
}

test(10, 20)
test(100, 200)
then with

Code: Select all

nrniv ftest.hoc
you will see that the accuracy is 2nd order with respect to the table resolution.