Previous Next Table of Contents

17. Tables and Arrays: The interpol_struct

Although GENESIS does not have array variables, it has several objects that contain one or more data structures called the ``interpol_struct'', or ``interpol.'' This data type is used as a field for handling arrays of doubles.

Objects that use interpol_structs:
Object Names of interpol_structs
ddsyn transf
table table
table2D table
tab2Dchannel X_A X_B Y_A Y_B Z_A Z_B
tabchannel X_A X_B Y_A Y_B Z_A Z_B
tabcurrent G_tab I_tab
tabgate alpha beta
xcell xpts ypts zpts dia color
xplot xpts ypts
xshape xpts ypts zpts

Utility functions that operate on interpol_structs:
Function Applicable objects Operation
duplicatetable All Reallocates interpol
file2tab All Loads interpol from file
loadtab All Loads interpol from command line
scaletabchan tabchannel tabgate Setup HH rate consts
setupNaCa tabcurrent Model Na-Ca exchanger current
setupalpha tabchannel tabgate Setup HH rate consts
setupgate tabgate table Setup HH rate consts
setupghk tabcurrent Solve the GHK equation
setuptau tabchannel tabgate Setup HH rate consts
tab2file All Dumps interpol to file
tweakalpha tabchannel Setup HH rate consts
tweaktau tabchannel Setup HH rate consts

17.1 Using interpol_structs

An interpol_struct can be accessed by the usual GENESIS setfield and getfield commands:

         create table /foo
         call /foo TABCREATE 100 0 100
         setfield /foo table->table[10] 1234
         echo {getfield /foo table->table[10]}

         create table2D /bar
         call /bar TABCREATE 5 0 1 5 0 1
         setfield /bar table->table[0][0] 5.55

The TABCREATE action is called in order to allocate the table. This action, and others that are used for manipulating tables, e.g. TABFILL, are described in the documentation for the particular objects that use interpol_structs.

The tabchannel (and in the future, other objects that use interpol_structs) supports the TABDELETE action. When deleting tabchannels, or the cells or compartments containing them, you must call TABDELETE first, in order to deallocate the memory for the tables. Finally, you have to give the ``reclaim'' command for the memory to actually be freed. Note that the tables are shared among all tabchannels that are created by copy or readcell from a prototype. Therefore, you shouldn't call TABDELETE unless you plan to delete all copies of the tabchannel.

These objects also have special enhancements to the SET action for operations on the interpol_struct. There are also many utility functions, listed above, that make manipulation of interpol_structs easier.

SET Action Enhancements

The SET action is invoked whenever the script command ``setfield'' is used. It is often used when a field needs to receive special treatment. If the field being set is an interpol_struct, then the SET action invokes a function called SetTable. This provides uniform behavior across all classes that use interpol_structs. The SET action in this situation interprets the last argument in a special way. For example, you could say

                 setfield /foo table /bar/table
where /foo and /bar are instances of table objects. In this case /bar/table refers to the table field of /bar, not to an element named /bar/table.

There are three ways in which the destination table (belonging to /foo in the example above) can be manipulated:

  1. The existing entries can have their values changed, without affecting allocation in any way. For example,
            setfield foo table bar/table
  2. The table array of the destination interpol is replaced, and the old one lost. In the current implementation, the old one is NOT freed. If necessary the xdivs field is changed to reflect a change in the size of the array.
            setfield foo &table bar/table
  3. The entire destination interpol_struct is replaced, and the old one (if any) is lost (NOT freed). In later upgrades, the old interpol will be freed conditionally on whether there are other elements still using the interpol. For now, there is no mechanism for freeing old interpols.
            setfield foo &&table bar/table
    The default is 1. To specify 2, prefix the name of the destination table with an &. To specify 3, prefix the name of the destination table with &&. The last argument can be either another table, or a constant. If it is a constant, then cases 2 and 3 above are errors. The assignment in (a) and arithmetical operators in (c) below are legal for constants, but obviously, the pointer operators in (b) are not. If the second argument is a table, there are several possible options:
    1. There can be a direct value assignment. This is the default. In the case of 1 above, this is trivial. In the case of 2 and 3, new tables/interpols are allocated and the values copied over.
              setfield foo table bar/table
    2. There can be a pointer assignment. This is indicated by an & prefix on the second argument. The case 1 above is illogical for this option, and produces an error message. For 2, the pointer to the array in the interpol struct is copied over to the destination. This option is very dangerous since there is no way to manage allocations. It is provided only for special cases and is NOT meant for general use.
              setfield foo &table &bar/table
      For 3, the pointer to the interpol_struct itself is copied over. This is the recommended way of providing access to shared arrays since future extensions will enable the interpol_struct to keep track of the number of elements which are using it.
              setfield foo &&table &bar/table
    3. There can be arithmetical operations. Due to parser problems, all these must be placed between ``='' signs, e.g.
              setfield /foo table =+=/bar/table
      Only option 1 above is allowed. In all cases the results are placed in the first interpol, in this example it is the table on /foo. The following operators are recognized when the second argument is a constant:
      + adds the constant value to all the table entries
      - subtracts the constant from all the table entries
      * multiplies all the table entries by the constant
      / divides all the table entries by the constant
      = assigns all the table entries to the constant
      The following operators are recognized when the second argument is a table. Except for operation `f', the operations are always carried out between table entries with the same index. If the first table has fewer entries than the second, the extra entries are ignored. If it has more entries, then the extra entries in the first table are unaffected.
      + sums the two tables, placing results in the first.
      - subtracts the second table from the first.
      * does an item-by-item product.
      / divides the first table by the second, item-by-item.
      = assigns the values of the first table to the second.
      e A = exp(B), where A is the first table and B the second.
      E A = exp10(B)
      l A = log(B)
      L A = log10(B)
      f fits the source table into the destination using interpolation to
      make sure we get a reasonable approximation to all entries.

Note: The memory handling capabilities for interpols have not been implemented. These will free old interpols which are not used by any elements. At present old interpols just get lost without being freed. Therefore, it is important to call the TABDELETE action before deleting tabchannels or other objects that use interpols and that support this action.

Also see the documentation for all listed objects and functions that operate on interpol_structs, especially the table object.

The following example illustrates some of the uses of setfield with interpol_structs:

 // This example illustrates the use of the extended 'SET' action
 // in manipulating tables.
 // We use the xpts and ypts tables in the shape for displaying
 // the effects of the manipulations.

 create xform /form -wgeom 500
 create xcoredraw /form/draw -xmin -1 -xmax 11 -ymin -1 -ymax 1
 create xlabel /form/label -label "Displaying a plot of table2 vs table1"
 create xbutton /form/continue -label "Continue with example" \
         -script "do_arith_ops"
 xshow /form

 create xshape /form/draw/shape -fg blue -npts 10

 // We will use table1 and table2 for storing the original values
 create table /table1
 create table /table2
 call /table1 TABCREATE 10 0 10
 call /table2 TABCREATE 10 0 10

 int i
 // Set up table 1 as a sine wave. This demonstrates the ordinary
 // set options for tables.
 for (i = 0; i <= 10 ; i = i + 1)
                 setfield /table1 table->table[{i}] {i}
                 setfield /table2 table->table[{i}] {sin {i / 2.0}}
 // use the special set option to copy the values from table1 and 2
 // to xpts and ypts respectively
 setfield /form/draw/shape xpts /table1/table
 setfield /form/draw/shape ypts /table2/table

         // This demonstrates using constants for arithmetic operations
 function do_arith_ops
         setfield /form/draw/shape fg red ypts =/=2.0
         setfield /form/label label "Now all y coords have been halved"
         setfield /form/continue script "do_more_arith_ops"

         // This demonstrates using other tables for arithmetic operations
 function do_more_arith_ops
         setfield /form/draw/shape fg green ypts =-=/table2/table
         setfield /form/label label \
                 "Now table2 has been subtracted from the y coords"
         setfield /form/continue script "do_new_interpol"

 function do_new_interpol
         // This demonstrates allocating a new interpol for ypts
         setfield /form/draw/shape fg yellow &&ypts /table2/table
         setfield /form/label label\
           "Now a new interpol has been allocated. It uses values from table2"
         setfield /form/continue script "do_interpol_ptr"
         // this demonstrates copying over a pointer to an interpol for xpts
 function do_interpol_ptr
         setfield /form/draw/shape fg black &&xpts &/table1/table
         setfield /form/label label \
                 "Now the xpts interpol uses the same pointer as table1"
         setfield /form/continue script "do_interpol_ptr2"

         // This shows that the interpol for table1 and xpts are the same
         // but table2 and ypts are distinct. We change both table1 and 2,
         // but xpts is the only one that is affected.
 function do_interpol_ptr2
         setfield /table1 table->table[0] 1
         setfield /table2 table->table[0] 1
         // This is a hack to force the draw to update, since there is no
         // way for it to know that anything in it has changed.
         setfield /form/draw xmin -1.0001

         setfield /form/label label \
                 "Here we change table1 and 2. Only xpts changes."
         setfield /form/continue script "quit" label "quit"

Previous Next Table of Contents