@@ -35,6 +35,8 @@ THE POSSIBILITY OF SUCH DAMAGE.
3535// PatternStim ARTIFICIAL_CELL in thread 0 and attaches the spike raster
3636// data to it.
3737
38+ #include < algorithm>
39+
3840#include " coreneuron/nrnconf.h"
3941#include " coreneuron/nrnoc/multicore.h"
4042#include " coreneuron/nrniv/nrniv_decl.h"
@@ -56,7 +58,7 @@ extern void pattern_stim_setup_helper(int size,
5658 double v);
5759}
5860
59- static int read_raster_file (const char * fname, double ** tvec, int ** gidvec);
61+ static size_t read_raster_file (const char * fname, double ** tvec, int ** gidvec);
6062
6163int nrn_extra_thread0_vdata;
6264
@@ -74,23 +76,28 @@ void nrn_set_extra_thread0_vdata() {
7476}
7577
7678// fname is the filename of an output_spikes.h format raster file.
79+ // todo : add function for memory cleanup (to be called at the end of simulation)
7780void nrn_mkPatternStim (const char * fname) {
7881 int type = nrn_get_mechtype (" PatternStim" );
7982 if (!memb_func[type].sym ) {
8083 printf (" nrn_set_extra_thread_vdata must be called (after mk_mech, and before nrn_setup\n " );
8184 assert (0 );
8285 }
8386
87+ // if there is empty thread then return, don't need patternstim
88+ if (nrn_threads == NULL || nrn_threads->ncell == 0 ) {
89+ return ;
90+ }
91+
8492 double * tvec;
8593 int * gidvec;
86- int size = read_raster_file (fname, &tvec, &gidvec);
87- printf (" raster size = %d\n " , size);
88- #if 0
89- for (int i=0; i < size; ++i) { printf("%g %d\n", tvec[i], gidvec[i]);}
90- #endif
94+
95+ // todo : handle when spike raster will be very large (int < size_t)
96+ size_t size = read_raster_file (fname, &tvec, &gidvec);
9197
9298 Point_process* pnt = nrn_artcell_instantiate (" PatternStim" );
9399 NrnThread* nt = nrn_threads + pnt->_tid ;
100+
94101 Memb_list* ml = nt->_ml_list [type];
95102 int layout = nrn_mech_data_layout_[type];
96103 int sz = nrn_prop_param_size_[type];
@@ -110,30 +117,47 @@ void nrn_mkPatternStim(const char* fname) {
110117 pattern_stim_setup_helper (size, tvec, gidvec, _iml, _cntml, _p, _ppvar, NULL , nt, 0.0 );
111118}
112119
113- int read_raster_file (const char * fname, double ** tvec, int ** gidvec) {
120+ // comparator to sort spikes based on time
121+ typedef std::pair<double , int > spike_type;
122+ static bool spike_comparator (const spike_type& l, const spike_type& r) {
123+ return l.first < r.first ;
124+ }
125+
126+ size_t read_raster_file (const char * fname, double ** tvec, int ** gidvec) {
114127 FILE* f = fopen (fname, " r" );
115- assert (f);
116- int size = 0 ;
117- int bufsize = 10000 ;
118- *tvec = (double *)emalloc (bufsize * sizeof (double ));
119- *gidvec = (int *)emalloc (bufsize * sizeof (int ));
128+ nrn_assert (f);
120129
121- double st;
122- int gid;
130+ // skip first line containing "scatter" string
123131 char dummy[100 ];
124132 nrn_assert (fgets (dummy, 100 , f));
125- while ( fscanf (f, " %lf %d \n " , &st, &gid) == 2 ) {
126- if (size >= bufsize) {
127- bufsize *= 2 ;
128- *tvec = ( double *) erealloc (*tvec, bufsize * sizeof ( double ));
129- *gidvec = ( int *) erealloc (*gidvec, bufsize * sizeof ( int )) ;
130- }
131- (*tvec)[size] = st;
132- (*gidvec)[size] = gid;
133- ++size ;
133+
134+ std::vector<spike_type> spikes;
135+ spikes. reserve ( 10000 ) ;
136+
137+ double stime ;
138+ int gid;
139+
140+ while ( fscanf (f, " %lf %d \n " , &stime, &gid) == 2 ) {
141+ spikes. push_back ( std::make_pair (stime, gid)) ;
134142 }
143+
135144 fclose (f);
136- return size;
145+
146+ // pattern.mod expects sorted spike raster (this is to avoid
147+ // injecting all events at the begining of the simulation).
148+ // sort spikes according to time
149+ std::sort (spikes.begin (), spikes.end (), spike_comparator);
150+
151+ // fill gid and time vectors
152+ *tvec = (double *)emalloc (spikes.size () * sizeof (double ));
153+ *gidvec = (int *)emalloc (spikes.size () * sizeof (int ));
154+
155+ for (size_t i = 0 ; i < spikes.size (); i++) {
156+ (*tvec)[i] = spikes[i].first ;
157+ (*gidvec)[i] = spikes[i].second ;
158+ }
159+
160+ return spikes.size ();
137161}
138162
139163// Opportunistically implemented to create a single PatternStim.
@@ -145,9 +169,10 @@ int read_raster_file(const char* fname, double** tvec, int** gidvec) {
145169
146170Point_process* nrn_artcell_instantiate (const char * mechname) {
147171 int type = nrn_get_mechtype (mechname);
148- printf (" nrn_artcell_instantiate %s type=%d\n " , mechname, type);
149172 NrnThread* nt = nrn_threads + 0 ;
150173
174+ // printf("nrn_artcell_instantiate %s type=%d\n", mechname, type);
175+
151176 // see nrn_setup.cpp:read_phase2 for how it creates NrnThreadMembList instances.
152177 // create and append to nt.tml
153178 assert (nt->_ml_list [type] == NULL ); // FIXME
0 commit comments