Boolean network-based analysis of the apoptosis network (Mai and Liu 2009)

 Download zip file   Auto-launch 
Help downloading and running models
Accession:144586
"To understand the design principles of the molecular interaction network associated with the irreversibility of cell apoptosis and the stability of cell surviving, we constructed a Boolean network integrating both the intrinsic and extrinsic pro-apoptotic pathways with pro-survival signal transduction pathways. We performed statistical analyses of the dependences of cell fate on initial states and on input signals. The analyses reproduced the well-known pro- and anti-apoptotic effects of key external signals and network components. We found that the external GF signal by itself did not change the apoptotic ratio from randomly chosen initial states when there is no external TNF signal, but can significantly offset apoptosis induced by the TNF signal. ..."
Reference:
1 . Mai Z, Liu H (2009) Boolean network-based analysis of the apoptosis network: irreversible apoptosis and stable surviving. J Theor Biol 259:760-9 [PubMed]
Citations  Citation Browser
Model Information (Click on a link to find other models with that property)
Model Type: Molecular Network;
Brain Region(s)/Organism: Generic;
Cell Type(s):
Channel(s):
Gap Junctions:
Receptor(s):
Gene(s):
Transmitter(s):
Simulation Environment: NEURON; Python;
Model Concept(s): Methods; Signaling pathways; Boolean network; Apoptosis;
Implementer(s): Neymotin, Sam [Samuel.Neymotin at nki.rfmh.org];
/
anetdemo
readme.html
bnet.mod
misc.mod *
stats.mod *
vecst.mod *
apopnames.txt
apoprules.txt
bnet.py
dbgnames.txt
dbgrules.txt
declist.hoc *
decmat.hoc *
decnqs.hoc *
decvec.hoc *
default.hoc *
grvec.hoc *
init.hoc
local.hoc *
misc.h *
misc.py *
mosinit.py
netstate.gif
network.py
nqs.hoc *
nrnoc.hoc *
pyinit.py *
python.hoc
pywrap.hoc *
simctrl.hoc *
snutils.py
                            
: $Id: bnet.mod,v 1.49 2012/08/09 16:26:55 samn Exp $ 

:* main COMMENT
COMMENT

boolean network 

ENDCOMMENT

:* main VERBATIM block
VERBATIM

#include "misc.h"

// BP gets a pointer to the boonet* that belongs to each BNET object
#define BP (*((boonet**) &(_p_sop)))

// node (can represent a molecule)
typedef struct BNODE {
  char* name;    // name of the node
  int id;        // id
  int state;  // state of the node
  int count;  // temporary counter
  int knockout; // is this node knocked-out? 
  int start; // starting state
  int sthresh; // special threshold for switching the node's state -- 0 means it's a normal node
  int scount; // special count (# of times its rule is activated)
  double x,y,z;  // location of the node
} bnode;

// represents a rule (contains edges or links between nodes)
typedef struct BRULE {
  struct BNODE** psrc; // source (usually 1 node but can be ANDed)
  struct BNODE*  ptarg;   // pointer to target
  int weight;             // weight of the rule ( < 0 == inhib, > 0 == activate )
  int* psrcstate;       // state of source nodes required for this rule
  int nsrc;           // # of sources in the rule
} brule;

// C-level structure/representation of the boolean network (stores nodes)
typedef struct BOONET {
  struct BNODE* pnodes;
  int numnodes;
  int id;
  struct BRULE* prules; // list of outgoing rules (pointers to targets and weights)
  int nrules;  // number of outgoing edges
  int rulebufsz; // prules buffer size (in units of brules)
} boonet;

// set the state of each node to its starting value
void startboonet (boonet* pnet) {
  int i;
  if(verbose) printf("startboonet\n");
  for(i=0;i<pnet->numnodes;i++) {
    pnet->pnodes[i].count = pnet->pnodes[i].scount = 0;
    pnet->pnodes[i].state = pnet->pnodes[i].start; // set to starting
  }
}

// create and return the C-level structure/representation of the boolean network
boonet* makeboonet (int numnodes) {
  int i;
  boonet* pnet;
  pnet = (boonet*) calloc(1, sizeof(boonet)); // allocate memory for the boonet
  pnet->pnodes = (bnode*) calloc(numnodes, sizeof(bnode)); // allocate memory for the nodes
  pnet->numnodes = numnodes; // store # of nodes
  startboonet(pnet);         // set states to starting values
  for(i=0;i<numnodes;i++) pnet->pnodes[i].id = i; // assign the IDs
  return pnet;
}

// free a single bnode
void freebnode(bnode* p) {
  if(p->name) {
    free(p->name);
    p->name = 0x0;
  }
}

// free a single brule's memory
void freebrule(brule* p) {
  if(p->psrc) free(p->psrc);
  if(p->psrcstate) free(p->psrcstate);
}

// free the entire boolean network
void freeboonet (boonet* pnet) {
  int i;
  if(pnet->pnodes) {
    for(i=0;i<pnet->numnodes;i++) freebnode(&pnet->pnodes[i]);
    free(pnet->pnodes);
  }  
  pnet->pnodes = 0x0;
  if(pnet->prules) {
    for(i=0;i<pnet->nrules;i++) freebrule(&pnet->prules[i]);
    free(pnet->prules);
    pnet->prules = 0x0;
  }
  free(pnet);
}

// add a rule from psrc to targid with specified weight and source state
// return pointer to the rule
brule* addrule (boonet* pnet, double* psrc, int targid, double weight, double* psrcstate, int nsrc) {
  int idx,i;
  if(pnet->prules == 0x0) { // take care of memory allocation
    pnet->rulebufsz = 16;
    pnet->prules = (struct BRULE*) calloc(pnet->rulebufsz, sizeof(brule) );
    pnet->nrules = 0;
  } else if(pnet->nrules >= pnet->rulebufsz) {
    pnet->rulebufsz *= 2;
    pnet->prules = (struct BRULE*) realloc(pnet->prules, pnet->rulebufsz * sizeof(brule) );
  }
  idx = pnet->nrules;
  pnet->prules[idx].nsrc = nsrc;           // set # of sources
  pnet->prules[idx].ptarg = &pnet->pnodes[targid]; // set target
  pnet->prules[idx].weight = weight;               // set weight
  // set the sources
  pnet->prules[idx].psrc = (struct BNODE **) calloc(nsrc, sizeof(bnode*));
  for(i=0;i<nsrc;i++) pnet->prules[idx].psrc[i] = &pnet->pnodes[(int)psrc[i]];
  // set source state for rule to be 'on'
  pnet->prules[idx].psrcstate = (int *) calloc(nsrc, sizeof(int));
  for(i=0;i<nsrc;i++) pnet->prules[idx].psrcstate[i] = (int) psrcstate[i]; 
  return &pnet->prules[ pnet->nrules++ ]; // return the new rule and inc # rules
}

// advance the full boolean network by a single iteration
void advanceboonet (boonet* pnet) {
  int i , j, nn = pnet->numnodes, nsrcact;
  bnode *pnodes = pnet->pnodes;
  brule *prule;
  for(i=0;i<nn;i++) pnodes[i].count = 0;      // initialize temporary counts to 0
  for(i=0;i<pnet->nrules;i++) {
    prule = &pnet->prules[i];
    nsrcact = 0; // number of sources that are activated
    for(j=0;j<prule->nsrc;j++) { // go thru the sources of the rule
      if(prule->psrc[j]->knockout) continue; // skip knockouts
      if(prule->psrc[j]->state == prule->psrcstate[j]){//check if source node in correct state
        nsrcact += 1; // count number of source nodes in correct state (for activation of the rule)
      }
    }
    if(prule->nsrc == nsrcact) prule->ptarg->count += prule->weight;//integrate if ALL sources in proper state
  }
  for(i=0;i<nn;i++) { // update the state of each node based on its inputs
    if(pnodes[i].knockout) {pnodes[i].scount=pnodes[i].count=pnodes[i].state=0; continue;}
    if(pnodes[i].count > 0) {       // turn on (more activating vs inhibiting input)     
      if(pnodes[i].sthresh > 0) { // special node?
        pnodes[i].scount += 1;    // increase the special counter
      } else {//normal node so gets turned on when activation count > inhibition count
        pnodes[i].state = 1;
      }      
    } else if(pnodes[i].count<0||(pnodes[i].sthresh>0 && pnodes[i].count==0)){//turn off (inhibitory > activating input) or special node
      pnodes[i].state = 0;
      pnodes[i].scount = 0; // special node count reset to 0
    }     
    if(pnodes[i].sthresh > 0){//set the state of any special nodes here
      if(pnodes[i].scount >= pnodes[i].sthresh) { // passed the threshold? turn on
        pnodes[i].state = 1;
      } else pnodes[i].state = 0;
    }
  }
}

ENDVERBATIM

:* NEURON, PARAMETER, ASSIGNED blocks
NEURON {
  ARTIFICIAL_CELL BNET
  : POINT_PROCESS BNET
  RANGE tstep
  RANGE xloc, yloc, zloc
  GLOBAL verbose, installed
  POINTER sop :::: Structure pointer for the boolean network
}

PARAMETER {
  tstep = 0
  verbose = 0
  sop = 0
}

ASSIGNED {
  installed
}

:* CONSTRUCTOR, DESTRUCTOR, INITIAL
:** CONSTRUCT: create a structure to save the identity of this unit and char integer flags
CONSTRUCTOR {
  VERBATIM 
  boonet* pnet;
  int sz; 
  if((sz = (int)*getarg(1)) < 1) {
    printf("BNET err0: must have a network with positive # of nodes!\n");
    hxe();
  }
  _p_sop = (double*) makeboonet(sz);
  pnet = BP;
  pnet->id = ifarg(2) ? (int) *getarg(2) : 0;
  ENDVERBATIM
}

: setrule(vsource, targid, weight, vsourcestate) - sets the rule from a set of 3 vectors
: vsource has node IDs of sources, targid is ID of target, weight is weight
: vsourcestate has states the source must be in for the given rule to be turned on.
FUNCTION setrule () {
  VERBATIM
  double *psrc, weight, *psrcstate;
  int targid, i, nsrc;
  if (! ifarg(4) ) {
    printf("BNET.setrule(vsource, targid, weight, vsourcestates) - sets a rule.\n");
    printf("vsource has node IDs of sources, targid is ID of target, weight is (-1,1) for inhib/activating\n");
    printf("vsourcestate has states the source must be in for the given rule to be turned on.\n");
    return 0.0;
  }
  if ( (nsrc = vector_arg_px(1,&psrc)) < 1) {
    printf("BNET.setrule WARN0: empty source Vector!\n");
    return 0.0;
  }
  targid = (int) *getarg(2);
  if(targid < 0 || targid >= BP->numnodes) {
    printf("BNET.setrule ERR0: invalid target id : %d\n",targid);
    return 0.0;
  }
  weight = (int) *getarg(3);
  if( nsrc != vector_arg_px(4,&psrcstate) ) {
    printf("BNET.setrule ERR1: vsource, vsourcestate must have same size!\n");
    return 0.0;
  }
  for(i=0;i<nsrc;i++) {
    if( psrc[i] < 0 || psrc[i] >= BP->numnodes) {
      printf("BNET.setrule ERR2: invalid source node id %d. netsize=%d\n",(int)psrc[i],BP->numnodes);
      return 0.0;
    }
    if(verbose>1) printf("adding rule from %d -> %d : w = %g\n",(int)psrc[i],targid,weight);
  }
  addrule(BP, psrc, targid, weight, psrcstate, nsrc);
  return 1.0;
  ENDVERBATIM
}

: get rid of all the edges (but keep the nodes)
PROCEDURE clearrules () {
  VERBATIM
  BP->nrules = 0;
  ENDVERBATIM
}

: print the network
PROCEDURE pr () {
  VERBATIM
  int i, j, k;
  bnode* pnodes = BP->pnodes;
  brule* prule;
  char srcstr[4096], stmp[4096];
  printf("net: numnodes=%d, numrules=%d\n",BP->numnodes,BP->nrules);
  for(i=0;i<BP->numnodes;i++) {
    if(pnodes[i].name) {
      printf("%s: state=%d, count=%d\n",pnodes[i].name,pnodes[i].state,pnodes[i].count);
    } else {
      printf("%d: state=%d, count=%d\n",i,pnodes[i].state,pnodes[i].count);
    }    
  }
  for(i=0;i<BP->nrules;i++) {
    prule = &BP->prules[i];
    srcstr[0]=0;
    for(j=0;j<prule->nsrc;j++) {
      if(prule->psrc[j]->name) {
        sprintf(stmp,"%s%s%s ", j>0?"AND ":"", prule->psrcstate[j]?"":"!", prule->psrc[j]->name);
      } else {
        sprintf(stmp,"%s%s%d ", j>0?"AND ":"", prule->psrcstate[j]?"":"!", prule->psrc[j]->id);
      }
      strcat(srcstr,stmp);
    }
    if(prule->ptarg->name) {
      printf("%s-> %s , w = %d\n",srcstr,prule->ptarg->name,prule->weight);
    } else {
      printf("%s-> %d , w = %d]\n",srcstr,prule->ptarg->id,prule->weight);
    }
  }
  ENDVERBATIM
}

: BNET.graphviz([dotname,imageename,format,L->R direction,width,height,fontsize]) - print the network as a graphviz string,
: and optionally save to a dot file (dotname) and to png/pdf. format should be png or pdf or other output formats
: supported by graphviz.
FUNCTION graphviz () {
  VERBATIM
  int i, j, k, LR, fsz, w, h;
  bnode* pnodes = BP->pnodes;
  brule* prule;
  char buf[4096], *dotname, *fname, fontsize[128];
  double penw; // penwidth
  FILE* fp = 0x0;
  dotname = ifarg(1) ? gargstr(1) : 0x0;
  fname = ifarg(2) ? gargstr(2) : 0x0;
  const char* ext =   ifarg(3) ? gargstr(3) : "gif";
  LR = ifarg(4) ? (int) *getarg(4) : 1;
  w = ifarg(5) ? (int) *getarg(5) : -1;
  h = ifarg(6) ? (int) *getarg(6) : -1;
  fsz = ifarg(7) ? (int) *getarg(7) : -1;
  if(fsz==-1) sprintf(fontsize,"%s"," "); else sprintf(fontsize,"fontsize=%d,",fsz);
  if(fname) if( !(fp = fopen(dotname,"w"))) {
    printf("BNET.graphviz ERR0: could not open %s\n",fname);
    return 0.0;
  }
  sprintf(buf, "%s", "digraph G {\n"); if(fp) fprintf(fp,"%s",buf); else fprintf(stdout,"%s",buf); 
  if(LR){sprintf(buf, "%s", "\trankdir=LR;\n"); if(fp) fprintf(fp,"%s",buf); else fprintf(stdout,"%s",buf); }
  if(w>0 && h>0) {sprintf(buf, "size=\"%d,%d\"\n",w,h); if(fp) fprintf(fp,"%s",buf); else fprintf(stdout,"%s",buf);}
  for(i=0;i<BP->numnodes;i++) {
    const char* ncolor = BP->pnodes[i].knockout ? "white" : BP->pnodes[i].state > 0 ? "black" : "gray";
    const char* fcolor = BP->pnodes[i].knockout ? "black" : "white";
    const char* shape = pnodes[i].sthresh > 0 ? "invtriangle" : "doublecircle";
    if(BP->pnodes[i].name) {
      sprintf(buf,"\t%s [fontcolor=%s,%sstyle=filled,shape=%s,fillcolor=%s,color=%s]\n",
              BP->pnodes[i].name,fcolor,fontsize,shape,ncolor,ncolor);
    } else {
      sprintf(buf,"\t%d [fontcolor=%s,%sstyle=filled,shape=%s,fillcolor=%s,color=%s]\n",
              i,fcolor,fontsize,shape,ncolor,ncolor);
    }
    if(fp) fprintf(fp,"%s",buf); else fprintf(stdout,"%s",buf); 
  }
  for(i=0;i<BP->nrules;i++) {
    prule = &BP->prules[i];
    for(j=0;j<prule->nsrc;j++) {
      penw = prule->psrcstate[j] == prule->psrc[j]->state ? 6.0 : 1.0;
      const char* arrowtype = prule->weight < 0 ? "tee" : "open";
      const char* lstyle = prule->psrcstate[j] == 0 ? ",style=dashed" : " ";
      if(prule->psrc[j]->name) {
        if(prule->ptarg->name) {
          sprintf(buf,"\t%s -> %s [arrowhead=%s,penwidth=%g,color=%s%s]\n",
                  prule->psrc[j]->name,prule->ptarg->name,arrowtype,penw,prule->weight>0?"red":"blue",lstyle);
        } else {
          sprintf(buf,"\t%s -> %d [arrowhead=%s,penwidth=%g,color=%s%s]\n",
                  prule->psrc[j]->name,prule->ptarg->id,arrowtype,penw,prule->weight>0?"red":"blue",lstyle);
        }
      } else if(prule->ptarg->name) {
          sprintf(buf,"\t%d -> %s [arrowhead=%s,penwidth=%g,color=%s%s]\n",
                  prule->psrc[j]->id,prule->ptarg->name,arrowtype,penw,prule->weight>0?"red":"blue",lstyle);
      } else {
          sprintf(buf,"\t%d -> %d [arrowhead=%s,penwidth=%g,color=%s%s]\n",
                  prule->psrc[j]->id,prule->ptarg->id,arrowtype,penw,prule->weight>0?"red":"blue",lstyle);
      }
      if(fp) fprintf(fp,"%s",buf); else fprintf(stdout,"%s",buf); 
    }
  }
  sprintf(buf,"%s","}\n"); if(fp) fprintf(fp,"%s",buf); else fprintf(stdout,"%s",buf); 
  if(fp) fclose(fp);
  if(fname) {
    sprintf(buf,"dot %s -T%s > %s",dotname,ext,fname);
    if(0!=system(buf)) {printf("BNET.graphviz ERR1 : couldn't run %s\n",buf); return 0.0;}
  }
  return 1.0;
  ENDVERBATIM
}

DESTRUCTOR {
  VERBATIM
  freeboonet(BP);
  ENDVERBATIM
}

: all nodes in network set to starting states
PROCEDURE start () {
  tstep = 0
  VERBATIM
  startboonet(BP); 
  ENDVERBATIM
}

:** INITIAL
INITIAL {
  start()
}

: strvalid - return the index to be used for get/setnodevals
FUNCTION strvalid () {
  VERBATIM
  char *pname;
  static char *pnames[6] = {"state", "count", "knockout", "start", "sthresh", "scount"};
  int i;
  pname = gargstr(1);
  for(i=0;i<6;i++) {
    if(!strcmp(pname,pnames[i])) return i;
  }
  return -1;
  ENDVERBATIM
}

:** getscount(vec) - retrieves BNET scount into a vector. each element indexed into the vector
: corresponds to the node with the given id.
PROCEDURE getscount () {
  VERBATIM
  double *ps; int i; void *vs;
  if(!ifarg(1)) {
    printf("BNET.getscount(vec) - returns scount of each node in vec\n");
    return 0; 
  }
  vs = vector_arg(1);
  ps = vector_newsize(vs,BP->numnodes);
  for(i=0;i<BP->numnodes;i++) ps[i] = (double) BP->pnodes[i].scount;
  ENDVERBATIM
}

:** setscount(vec) - sets vector vec into BNET node scount. each element indexed into the vector
: corresponds to the node with the given id.
FUNCTION setscount () {
  VERBATIM
  double *ps; int i, sz;
  if(!ifarg(1)) {
    printf("BNET.setscount(vec) - sets scount of each node in vec\n");
    return 0.0;
  }
  if( (sz = vector_arg_px(1,&ps)) != BP->numnodes ) {
    printf("BNET.setscount ERR0: vec.size(%d) != BNET.numnodes(%d)\n",sz,BP->numnodes);
    return 0.0;
  }
  for(i=0;i<BP->numnodes;i++) BP->pnodes[i].scount = (int) ps[i];
  return 1.0;
  ENDVERBATIM
}

:** getsthresh(vec) - retrieves BNET sthresh into a vector. each element indexed into the vector
: corresponds to the node with the given id.
PROCEDURE getsthresh () {
  VERBATIM
  double *ps; int i; void *vs;
  if(!ifarg(1)) {
    printf("BNET.getsthresh(vec) - returns sthresh of each node in vec\n");
    return 0;
  }
  vs = vector_arg(1);
  ps = vector_newsize(vs,BP->numnodes);
  for(i=0;i<BP->numnodes;i++) ps[i] = (double) BP->pnodes[i].sthresh;
  ENDVERBATIM
}

:** setsthresh(vec) - sets vector vec into BNET node sthresh. each element indexed into the vector
: corresponds to the node with the given id.
FUNCTION setsthresh () {
  VERBATIM
  double *ps; int i, sz;
  if(!ifarg(1)) {
    printf("BNET.setsthresh(vec) - sets sthresh of each node in vec\n");
    return 0.0;
  }
  if( (sz = vector_arg_px(1,&ps)) != BP->numnodes ) {
    printf("BNET.setsthresh ERR0: vec.size(%d) != BNET.numnodes(%d)\n",sz,BP->numnodes);
    return 0.0;
  }
  for(i=0;i<BP->numnodes;i++) BP->pnodes[i].sthresh = (int) ps[i];
  return 1.0;
  ENDVERBATIM
}

:** getcount(vec) - retrieves BNET count into a vector. each element indexed into the vector
: corresponds to the node with the given id.
PROCEDURE getcount () {
  VERBATIM
  double *ps; int i; void *vs;
  if(!ifarg(1)) {
    printf("BNET.getcount(vec) - returns count of each node in vec\n");
    return 0;
  }
  vs = vector_arg(1);
  ps = vector_newsize(vs,BP->numnodes);
  for(i=0;i<BP->numnodes;i++) ps[i] = (double) BP->pnodes[i].count;
  ENDVERBATIM
}

:** setcount(vec) - sets vector vec into BNET node counts. each element indexed into the vector
: corresponds to the node with the given id.
FUNCTION setcount () {
  VERBATIM
  double *ps; int i, sz;
  if(!ifarg(1)) {
    printf("BNET.setcount(vec) - sets count of each node in vec\n");
    return 0.0;
  }
  if( (sz = vector_arg_px(1,&ps)) != BP->numnodes ) {
    printf("BNET.setcount ERR0: vec.size(%d) != BNET.numnodes(%d)\n",sz,BP->numnodes);
    return 0.0;
  }
  for(i=0;i<BP->numnodes;i++) BP->pnodes[i].count = (int) ps[i];
  return 1.0;
  ENDVERBATIM
}

:** getstate(vec) - retrieves BNET state into a vector. each element indexed into the vector
: corresponds to the node with the given id.
PROCEDURE getstate () {
  VERBATIM
  double *ps; int i; void *vs;
  if(!ifarg(1)) {
    printf("BNET.getstate(vec) - returns state of each node in vec\n");
    return 0;
  }
  vs = vector_arg(1);
  ps = vector_newsize(vs,BP->numnodes);
  for(i=0;i<BP->numnodes;i++) ps[i] = (double) BP->pnodes[i].state;
  ENDVERBATIM
}

:** setstate(vec) - sets vector vec into BNET node states. each element indexed into the vector
: corresponds to the node with the given id.
FUNCTION setstate () {
  VERBATIM
  double *ps; int i, sz;
  if(!ifarg(1)) {
    printf("BNET.setstate(vec) - sets state of each node in vec\n");
    return 0.0;
  }
  if( (sz = vector_arg_px(1,&ps)) != BP->numnodes ) {
    printf("BNET.setstate ERR0: vec.size(%d) != BNET.numnodes(%d)\n",sz,BP->numnodes);
    return 0.0;
  }
  for(i=0;i<BP->numnodes;i++) BP->pnodes[i].state = (int) ps[i];
  return 1.0;
  ENDVERBATIM
}

:** getstart(vec) - retrieves BNET start states into a vector. each element indexed into the vector
: corresponds to the node with the given id.
PROCEDURE getstart () {
  VERBATIM
  double *ps; int i; void *vs;
  if(!ifarg(1)) {
    printf("BNET.getstart(vec) - returns start state of each node in vec\n");
    return 0;
  }
  vs = vector_arg(1);
  ps = vector_newsize(vs,BP->numnodes);
  for(i=0;i<BP->numnodes;i++) ps[i] = (double) BP->pnodes[i].start;
  ENDVERBATIM
}

:** setstart(vec) - sets vector vec into BNET node start states. each element indexed into the vector
: corresponds to the node with the given id.
FUNCTION setstart () {
  VERBATIM
  double *ps; int i, sz;
  if(!ifarg(1)) {
    printf("BNET.setstart(vec) - sets start state of each node in vec\n");
    return 0.0;
  }
  if( (sz = vector_arg_px(1,&ps)) != BP->numnodes ) {
    printf("BNET.setstart ERR0: vec.size(%d) != BNET.numnodes(%d)\n",sz,BP->numnodes);
    return 0.0;
  }
  for(i=0;i<BP->numnodes;i++) BP->pnodes[i].start = (int) ps[i];
  return 1.0;
  ENDVERBATIM
}

:** setknockout(vec) - sets vector vec into BNET node knockout flag variables. each element indexed into the vector
: corresponds to the node with the given id.
FUNCTION setknockout () {
  VERBATIM
  double *pk; int i, sz;
  if(!ifarg(1)) {
    printf("BNET.knockout(vec) - sets knockout flag of each node in vec\n");
    return 0.0;
  }
  if( (sz = vector_arg_px(1,&pk)) != BP->numnodes ) {
    printf("BNET.knockout ERR0: vec.size(%d) != BNET.numnodes(%d)\n",sz,BP->numnodes);
    return 0.0;
  }
  for(i=0;i<BP->numnodes;i++) BP->pnodes[i].knockout = (int) pk[i];
  return 1.0;
  ENDVERBATIM
}

:** getknockout(vec) - retrieves BNET knockout flags into a vector. each element indexed into the vector
: corresponds to the node with the given id.
PROCEDURE getknockout () {
  VERBATIM
  double *pk; int i; void *vk;
  if(!ifarg(1)) {
    printf("BNET.getknockout(vec) - returns knockout flag of each node in vec\n");
    return 0;
  }
  vk = vector_arg(1);
  pk = vector_newsize(vk,BP->numnodes);
  for(i=0;i<BP->numnodes;i++) pk[i] = (double) BP->pnodes[i].knockout;
  ENDVERBATIM
}

: BNET.setnname(node id, string name) - set node name
FUNCTION setnname () {
  VERBATIM
  int id, sz; char *name;
  id = (int) *getarg(1);
  if(id < 0 || id >= BP->numnodes) {
    printf("BNET.setnname ERR0: invalid node index %d\n",id);
    return 0.0;    
  }
  name = gargstr(2);
  if(!(sz=strlen(name))) {
    printf("BNET.setnname ERR1: empty string\n");
    return 0.0;
  }
  if(BP->pnodes[id].name) free(BP->pnodes[id].name);
  if(!(BP->pnodes[id].name = (char*) malloc(sizeof(char) * (sz + 1)))) {
    printf("BNET.setnname ERR2: couldn't alloc mem for %s\n",name);
    return 0.0;
  }
  strcpy(BP->pnodes[id].name,name);
  return 1.0;
  ENDVERBATIM
}

: getnname(node id, string) - get node name
FUNCTION getnname () {
  VERBATIM
  int i, id, sz; char **pname, string[BUFSIZ];
  id = (int) *getarg(1);
  if(id < 0 || id >= BP->numnodes) {
    printf("BNET.getnname ERR0: invalid node index %d\n",id);
    return 0.0;    
  }
  if(!BP->pnodes[id].name || !(sz=strlen(BP->pnodes[id].name))) {
    printf("BNET.getnname ERR1: node %d has no name\n",id);
    return 0.0;
  }
  for(i=0;i<sz && i<BUFSIZ;i++) string[i] = BP->pnodes[id].name[i];
  if(i < BUFSIZ) string[i]=0;
  printf("Aname is %s, %s\n",BP->pnodes[id].name,string);
  pname = hoc_pgargstr(2);
  printf("Bname is %s, %s\n",BP->pnodes[id].name,string);
  hoc_assign_str(pname,string);
  return 1.0;
  ENDVERBATIM
}

: advance the BNET by a single iteration - called from a simulation loop
FUNCTION advancebn () {
  VERBATIM
  advanceboonet(BP);  
  tstep = tstep + 1;
  return tstep;
  ENDVERBATIM
}

FUNCTION advancebnfor () {
  VERBATIM
  int i, n;
  n = (int) *getarg(1);
  for(i=0;i<n;i++) advancebn();
  return tstep;
  ENDVERBATIM
}

FUNCTION numnodes () {
  VERBATIM
  return BP->numnodes;
  ENDVERBATIM
}

FUNCTION numrules () {
  VERBATIM
  return BP->nrules;
  ENDVERBATIM
}

: identifier for BNET
FUNCTION id () {
  VERBATIM
  return (double) BP->id;
  ENDVERBATIM
}