Skip to content
This repository was archived by the owner on Mar 20, 2023. It is now read-only.

Commit 4cf570a

Browse files
authored
Fix issues with spike replay / patternstim (#67)
- pattern.mod expects spike raster to be sorted (to avoid injecting large events at the begining of simulation itself). Refactor patternstim implementation to sort spike raster - if rank is empty then don't create patternstim (avoid segfault) - prcellstate file name time format changed simular to NEURON Note that patternstim functionality in NEURON expects sorted spike (using `sortspike` script which sorts based on time as well gid)
1 parent 38ca26d commit 4cf570a

File tree

2 files changed

+52
-27
lines changed

2 files changed

+52
-27
lines changed

coreneuron/nrniv/main1.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -218,12 +218,12 @@ void call_prcellstate_for_prcellgid(int prcellgid, int compute_gpu, int is_init)
218218
if (is_init)
219219
sprintf(prcellname, "%s_gpu_init", prprefix);
220220
else
221-
sprintf(prcellname, "%s_gpu_t%g", prprefix, t);
221+
sprintf(prcellname, "%s_gpu_t%f", prprefix, t);
222222
} else {
223223
if (is_init)
224224
strcpy(prcellname, "cpu_init");
225225
else
226-
sprintf(prcellname, "cpu_t%g", t);
226+
sprintf(prcellname, "cpu_t%f", t);
227227
}
228228
update_nrnthreads_on_host(nrn_threads, nrn_nthread);
229229
prcellstate(prcellgid, prcellname);

coreneuron/nrniv/patternstim.cpp

Lines changed: 50 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -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

6163
int 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)
7780
void 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

146170
Point_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

Comments
 (0)