/* $Header: /disks/hermosa/public/NEURON/CA1-99/bp/lib/TEST/newshiftsyn.c 2000/02/25 poirazi */ /* Adding a temporal offset for stimulation of trains */ /* $Header: /disks/newport/freeway/brannon/rs/p-and-s/SourceCode/C/newshiftsyn.c,v 1.7 1999/03/24 18:19:21 brannon Exp $ */ /* $Log: newshiftsyn.c,v $ * Revision 1.7 1999/03/24 18:19:21 brannon * Ok, now NEURON should be happy. * * Revision 1.6 1999/03/24 18:09:25 brannon * The end of newshiftsyn files is not compatible with NEURON's vector * scanf() function. Working on this. * * Revision 1.5 1998/10/22 10:05:03 brannon * The compiler croaked on nested comments so I fixed my attempt to * simply comment out and copy the old code by removing the old code and * associated comments. * * Revision 1.4 1998/10/22 10:02:58 brannon * I changed the sprintf which created filenames to write the p_seed in * integer as opposed to float from. * * Revision 1.3 1998/05/07 19:33:44 brannon * rm shiftsyn.log -> rm -f shiftsyn.log * My runs were held up because it was waiting for a reply to removal of * a previous shiftsyn.log * * Revision 1.2 1998/04/08 18:33:29 brannon * Write a \n after each dt of synaptic input. * * Revision 1.1 1998/04/08 18:32:48 brannon * Initial revision * * Revision 1.12 1997/04/15 19:35:59 niebur * *** empty log message *** * * Revision 1.11 1995/02/01 01:55:28 ernst * Eliminated finite loop condition: if s=1, the restart in the main loop after * enforce_refrac failed (cond=1) was ineffective, because make_train_offset * and make-spike trains each time gave identical results. This happened because * the sigmas in them contained terms 1-s and thus became zero. * * This has been corrected by restarting the spiketrain now COMPLETELY * (ie, all synapses) when that occurs. * * PS this condition occurred for " shiftsyn testfile 100 500 0.1 100 1 0.2 6074" * * Revision 1.10 1995/01/28 22:00:46 ernst * Writing now a log file at the beginning of the run which is * deleted at its successful completion. * * Revision 1.9 1995/01/28 08:04:27 ernst * Now enforcing refractory period (in new routine enforce_refrac). * Also found out that the Numerical recipes generator has a problem * if its seed is too large (> 54000, apparently). The reason is * unknown, but I do not allow such large seeds anymore. * * Revision 1.8 1995/01/20 22:13:26 ernst * Added more debugging message in context with the consistency check in write_to_disk. * * Revision 1.7 1995/01/18 02:41:29 ernst * Added a global variable ("errfile") which is identical to outfilename and * which is printed out each time there is an error message. This way, it will * be possible to determine which run makes a problem in a series of many runs * in which the shell might garble the order of messages. * * Revision 1.6 1995/01/18 02:01:03 ernst * removed debugging messages * * Revision 1.5 1994/10/29 02:25:07 ernst * Fixed a problem in make_spike_trains: the sigma of the Gaussian there * was dependend on the total time. There is no reason this should be * the case. * * Revision 1.4 1993/10/04 08:11:56 ernst * Introduced computation and writing to a file of * the total activity at a given time (variable totact). * * Revision 1.3 1993/09/23 01:17:08 ernst * Introduced larger scatter for shift between spike trains. * The scatter is now in units of n_tot, NOT in units of the * average spiking frequency. * */ /* $Id: newshiftsyn.c,v 1.7 1999/03/24 18:19:21 brannon Exp $ */ /***************************************************************************/ /* */ /* Purpose of this program: make time-dependent input for use with NEURON */ /* */ /* Input: explained before 'main' */ /* */ /* Output: file: */ /* */ /* syndata contains spike times for the given number */ /* of synapses (read by NEURON), */ /* */ /* Note: the random number generator is defined in /cit/ernst/num-rec.h */ /* */ /****************************************************************************/ #include "/usr/include/stdlib.h" #include "/usr/include/string.h" //#include "/usr/include/math.h" #include "ken.h" #include "num-rec.h" #define RAND_MAX 2147483647 #define myrand ( (double) random() / RAND_MAX) char errfile[1000]; /* global var for debugging purposes*/ /********************************************************************/ /* */ /* Allocate array space for times (doubles) */ /* */ /********************************************************************/ double *alloctimes(int nelements) { int i; double *p; p = calloc(nelements,sizeof(double)); if(!p) { printf("allocation failure in allocspikes, working on %s\n; aborting", errfile); exit(1); } for(i=0;i1 || f_p<0 || f_s>1 ) { printf("p and s must be from [0..1];, working on %s EXIT!\n\n",errfile); exit(1); } *p_t_tot = f_t_tot; *p_dt = f_dt ; *p_p=f_p; *p_s=f_s; /* Brannon: I dont have the faintest idea why p_seed would be cast as float here. But I do have a non-faint idea as to why I want to make it integer. */ /* making the complete outfile name (NB: dt is in ms):*/ sprintf(outfilename,"%s-%d-%.2f-%.2f-%.2f-%.2f-%.2f-%d-%.2f",\ argv[1],*p_n_syn,f_t_tot,f_dt,f_av_rate,f_s,f_p,*p_seed,*p_offset); /* also write the complete outfile name to global variable which is used in error messages as a signature:*/ sprintf(errfile,"%s-%d-%.2f-%.2f-%.2f-%.2f-%.2f-%d-%.2f",\ argv[1],*p_n_syn,f_t_tot,f_dt,f_av_rate,f_s,f_p,*p_seed,*p_offset); /* making the name for the total activity file:*/ sprintf(totactname,"%s-%d-%.2f-%.2f-%.2f-%.2f-%.2f-%d-%.2f",\ "totact",*p_n_syn,f_t_tot,f_dt,f_av_rate,f_s,f_p,*p_seed,*p_offset); /* t_tot and dt are in ms, therefore also the rate has to be in spikes */ /* per ms and not spikes per second: */ *p_av_rate = f_av_rate/1000.; } /********************************************************************/ /* */ /* make_train_offset: */ /* Compute the offset for the whole spiketrain. */ /* A Gaussian random number with sigma s/(1-s) */ /* */ /* s=0 <==> all spiketrains are completely periodic, */ /* s=1 <==> all spiketrains are completely aperiodic, */ /* s=0.5 <==> spiketrains are distributed with sigma= */ /* */ /********************************************************************/ double make_train_offset(double p, double s, double av_rate, \ double t_tot,int *p_seed) { double offset,delta_t; double sigma_p; delta_t = 1./av_rate; if(s > APRECISION && s<=1.) /* finite value for s */ { sigma_p = p*(1-s)/s * delta_t; /* determine sigma of gaussian */ offset= sigma_p*gasdev(p_seed); } else if(fabs(s) < APRECISION) /* s is zero ==> "infinite sigma" */ { offset= p* t_tot * ran1(p_seed); /* pick random offset */ } else /* error! */ nrerror("error in make_train_offset: s must be 0 <= s <= 1"); return(offset); } /********************************************************************/ /* */ /* dsort: */ /* sorting routine, from numrec. */ /* Identical to routine sort there, exc. for one difference (shown) */ /* */ /********************************************************************/ void dsort(n,ra) int n; double ra[]; /* declaration of ra and rra is the only difference to numrec's sort */ { int l,j,ir,i; double rra; l=(n >> 1)+1; ir=n; for (;;) { if (l > 1) rra=ra[--l]; else { rra=ra[ir]; ra[ir]=ra[1]; if (--ir == 1) { ra[1]=rra; return; } } i=l; j=l << 1; while (j <= ir) { if (j < ir && ra[j] < ra[j+1]) ++j; if (rra < ra[j]) { ra[i]=ra[j]; j += (i=j); } else j=ir+1; } ra[i]=rra; } } /********************************************************************/ /* */ /* sort_train: */ /* bring spikes in range [0..t_tot] and */ /* sort spiketrain in ascending order. */ /* */ /********************************************************************/ sort_train(double *spiketrain,int length_train,double t_tot) { int i; for (i=0;it_tot || spiketrain[i] <0) { printf("sort_train: This cannot happen\n, working on %s",errfile); exit(1); } } /* DEBUG:*/ /* printf("\nNext train, in range 0-%g, unordered (working on %s):\n", t_tot,errfile); for (i=0;i= length_train) return(-1); /* failure; make new spike train*/ while((spiketrain[j]) > spiketrain[j+1]) { spiketrain[j+1] += t_ref; j++; if(j+1 >= length_train) /*make sure j-loop stays w/in array bounds*/ return(-1); /*else: failure; make new spike train*/ } } /*Now spikes are separated by at least t_ref. Check if sth. fell off end:*/ done=1; for (i=1;i t_tot) { /*if yes, put the last one back a bit:*/ spiketrain[i-1] -= t_ref/2.; /*subtract only t_r/2 to keep ordered*/ if(spiketrain[i-1]<0) /*failure; make new spike train*/ return(-1); done=0; /*have to do the while loop again (possibly more than once)*/ } } /* The only interval that has not been checked is the very last one. In the unlikely case this is a problem, we would have to do a major re-ordering (spikes are already ordered!). Therefore, if this happens, declare failure, return with (-1) and make an entirely new spike train:*/ if(spiketrain[length_train-1]-spiketrain[length_train-2] <= t_ref) return(-1); else { /*Debug:*/ /* printf("\nOrdered train %i, in range 0-%g (working on %s):\n", syn,t_tot,errfile); for (i=0;i t_tot) { nexttime[syn] = t_tot+dt; } } else /* synapse has no spike at time t */ { fprintf(outfile,"0"); } if (syn<(n_syn-1)) { fprintf(outfile," "); } } if (t < (t_tot-dt)) { fprintf(outfile,"\n"); } /*write total activity for this time:*/ // fprintf(f_totact,"%g %d\n",t,totact); } /*make sure all spikes have been found (consistency check):*/ // for(syn=0;synAPRECISION && p<=1.) /* finite value for p */ { sigma_g = (1-p)/p * delta_t; /* determine sigma of gaussian */ for(t=0.;t "infinite sigma" */ { for(t=0.;t50000) { printf("seed too large; problem for Num. Recipes random generator\n"); exit(1); } if(t_tot*av_rate<=1) nrerror("run too short (less than one spike on average), EXIT"); else length_train = floor(t_tot*av_rate); spiketrain = alloctimes(length_train); gentrain = alloctimes(length_train); alltrains = alloctimes(n_syn*length_train); outfile = fopen(outfilename, "w"); // f_totact = fopen(totactname, "w"); make_generator_train(gentrain,t_tot,av_rate,p,&seed); for(syn=0;syn