Symbol COMPONENT_CLASS_CPP::event(Event* event) { switch(event->type) { case EVENT_STATE_SET: { // extract DataML EventStateSet* data = (EventStateSet*) event->data; XMLNode xmlNode(data->state); DataMLNode nodeState(&xmlNode); // obtain the parameters values = nodeState.getField("values").getArrayDOUBLE(); return C_OK; } // CREATE THE PORTS case EVENT_INIT_CONNECT: { // on first call if (event->flags & F_FIRST_CALL) { out.setName("out"); out.create(hComponent); out.setStructure(TYPE_DOUBLE | TYPE_REAL, Dims(values.size()).cdims()); } // on last call if (event->flags & F_LAST_CALL) { } // ok return C_OK; } case EVENT_RUN_SERVICE: { out.setContent(&(values[0])); // ok return C_OK; } } // if we service the event, we return C_OK // if we don't, we should return S_NULL to indicate that we didn't return S_NULL; }
void COMPONENT_CLASS_CPP::event(Event& event) { switch(event.type) { // Stepping event comes first case EVENT_RUN_SERVICE: { // create data structures DOUBLE* idata; vector<VDOUBLE> totals; VDOUBLE neg_total; Symbol hInput; VDOUBLE odata; odata.resize(count, 0); totals.resize(hSets.size()); for (UINT32 i=0; i<totals.size(); i++) { totals[i].resize(count,0); } neg_total.resize(count,0); // get noise VDOUBLE noise_membrane; noise_membrane.resize(count); for (UINT32 i=0; i < count; i++) { // decay membrane membrane[i] *= lambda_membrane[i]; } dev_std_util_rng::fill(hComponent,rng, &noise_membrane[0], count, 1.0, 0.0); // get data and assign based on operation for (UINT32 i=0; i < hInputs.size(); i++) { for (UINT32 j=0; j < numPorts[i]; j++) { Symbol input = iif.getData(hInputs[i][j]); // make up the totals according to the operation types idata = (DOUBLE*)numeric_get_content(input); for (UINT32 k=0; k < count; k++) { if (i == ADD && idata[k] < 0) {neg_total[k] += idata[k];} else {totals[i][k] += idata[k];} // don't let shunt be negative! if (i == SHUNT && j == (hInputs[i].size() - 1) && totals[i][k] < -p_v[k]) { totals[i][k] = -p_v[k]; } } } } // do it for (UINT32 i=0; i < count; i++) { if (!SINGLE_ISINF(pos_reversal_potential[i])) { totals[ADD][i] *= (pos_reversal_potential[i] - membrane[i]); } if (!SINGLE_ISINF(neg_reversal_potential[i])) { neg_total[i] *= (membrane[i] - neg_reversal_potential[i]); } totals[ADD][i] += neg_total[i]; /* ####################################################### */ // combine operation types odata[i] = totals[ADD][i]; // Only do other operations if we have the ports if (hInputs[SHUNT].size() > 0) odata[i] *= (p_v[i] + totals[SHUNT][i]); if (hInputs[SHUNT_DEV].size() > 0) odata[i] /= (p_v[i] + totals[SHUNT_DEV][i]); // /* ####################################################### */ odata[i] *= lambda_membrane_reciprocal[i]; membrane[i] += odata[i]; membrane[i] += noise_membrane[i] * sigma_membrane[i]; } numeric_set_content(oif.getData(hOutput), &membrane[0]); event.response = C_OK; return; } case EVENT_INIT_CONNECT: { // open output port with dimensions given by the state data if (event.flags & F_FIRST_CALL) { hOutput = oif.addPort("dev/std/data/numeric", 0); oif.setPortName(hOutput, "out"); Symbol out = oif.getData(hOutput); numeric_set_structure(out, TYPE_DOUBLE | TYPE_REAL, dims); } // check inputs for veracity... if (event.flags & F_LAST_CALL) { Symbol hInput; for (UINT32 i=0; i<iif.getNumberOfPorts(); i++) { hInput = (iif.getPort(i)); /*Symbol data = iif.getData(hInput); assertClass(data, "dev/std/data/numeric"); numeric_validate(data, TYPE_DOUBLE);*/ } } // check input dimensions against state data /*Dims srcDims = cppdims(structure); if (srcDims[0] != src.dims[0] || srcDims[1] != src.dims[1]) {berr << "Source dimensions of input do not match dims";} }*/ event.response = C_OK; return; } case EVENT_INIT_POSTCONNECT: { // get the ports for the different sets hInputs.resize(hSets.size()); for (UINT32 i=0; i < hSets.size(); i++) { numPorts.push_back(iif.getNumberOfPorts(hSets[i])); for (UINT32 j=0; j < numPorts[i]; j++) { hInputs[i].push_back(iif.getPort(hSets[i], j)); } } // assume ports on the default set are addition and add them to that list numPorts[0] += iif.getNumberOfPorts(); for (UINT32 i=0; i < iif.getNumberOfPorts(); i++) { hInputs[0].push_back(iif.getPort(i)); } event.response = C_OK; return; } case EVENT_STATE_SET: { /* ######################################################### */ // create operation sets hSets.push_back(iif.getSet("add")); hSets.push_back(iif.getSet("shunt")); hSets.push_back(iif.getSet("shunt_dev")); /* ######################################################### */ // create and seed RNG rng = coreCreateUtility(hComponent, "dev/std/util/rng", 0); dev_std_util_rng::select(hComponent, rng, "MT2000.normal"); dev_std_util_rng::seed(hComponent, rng, &(*event.state.seed)[0], event.state.seed->size()); /* Extracting the data from the state MatML file - reality checking as we go... */ MatMLNode nodePars(event.xmlNode); // get dimensions VUINT64 dims_temp = nodePars.getField("dims").getArrayUINT64(); for (UINT32 i=0; i < dims_temp.size(); i++) { dims.push_back(dims_temp[i]); } count = dims.getNumberOfElements(); membrane.resize(count, 0); // get the args if (nodePars.hasField("tau_membrane")) { tau_membrane = nodePars.getField("tau_membrane").getArraySINGLE(); } UINT32 N = tau_membrane.size(); if (nodePars.hasField("sigma_membrane")) { sigma_membrane = nodePars.getField("sigma_membrane").validate(Dims(N)).getArraySINGLE(); } if (nodePars.hasField("p")) { p_v = nodePars.getField("p").validate(Dims(N)).getArraySINGLE(); } if (nodePars.hasField("pos_reversal_potential")) { pos_reversal_potential = nodePars.getField("pos_reversal_potential").validate(Dims(N)).getArraySINGLE(); } if (nodePars.hasField("neg_reversal_potential")) { neg_reversal_potential = nodePars.getField("neg_reversal_potential").validate(Dims(N)).getArraySINGLE(); } lambda_membrane.resize(count); lambda_membrane_reciprocal.resize(count); if (N == 1) { tau_membrane.resize(count, tau_membrane[0]); sigma_membrane.resize(count, sigma_membrane[0]); p_v.resize(count, p_v[0]); pos_reversal_potential.resize(count, pos_reversal_potential[0]); neg_reversal_potential.resize(count, neg_reversal_potential[0]); } else if (N != count) { berr << "pars are of incorrect size!"; } for (UINT32 i=0; i<count; i++) { lambda_membrane[i] = exp(-1.0 / (tau_membrane[i] * sampleRateToRate(time.sampleRate))); lambda_membrane_reciprocal[i] = 1.0 - lambda_membrane[i]; } // ok event.response = C_OK; return; } //#include "events.cpp" } // raise an exception if you run into trouble during event(). the return value // indicates whether you processed the event. }
Symbol COMPONENT_CLASS_CPP::event(Event* event) { switch(event->type) { case EVENT_STATE_SET: { // extract DataML EventStateSet* data = (EventStateSet*) event->data; XMLNode xmlNode(data->state); DataMLNode nodeState(&xmlNode); // obtain the parameters VDOUBLE size = nodeState.getField("sizeIn").getArrayDOUBLE(); numElementsIn = 1; for (unsigned int i = 0; i < size.size(); ++i) { numElementsIn *= size[i]; } size = nodeState.getField("sizeOut").getArrayDOUBLE(); numElementsOut = 1; for (unsigned int i = 0; i < size.size(); ++i) { numElementsOut *= size[i]; } string binpath = nodeState.getField("binpath").getSTRING(); bool _has_delay = false; // get the connectivity if (nodeState.hasField("_bin_file_name")) { string fileName = nodeState.getField("_bin_file_name").getSTRING(); int _num_conn = (int) nodeState.getField("_bin_num_conn").getDOUBLE(); _has_delay = (bool) nodeState.getField("_bin_has_delay").getDOUBLE(); // open the file for reading FILE * binfile; // FIXME: We really need an absolute path here, generated at runtime fileName = binpath + fileName; binfile = fopen(fileName.c_str(),"rb"); if (!binfile) { // That failed; try the default location for // spineml-2-brahms on a Unix system: fileName = "~/spineml-2-brahms/model/" + fileName; binfile = fopen(fileName.c_str(),"rb"); if (!binfile) { berr << "Could not open connectivity file"; } } VDOUBLE delayForConnTemp; srcInds.resize(_num_conn); dstInds.resize(_num_conn); if (_has_delay) { delayForConnTemp.resize(_num_conn); } for (int i_BRAHMS = 0; i_BRAHMS < _num_conn; ++i_BRAHMS) { size_t v = fread(&srcInds[i_BRAHMS], sizeof(unsigned int), 1, binfile); if (v == 0) { bout << "Read 0 bytes from binfile" << D_INFO; if (ferror(binfile)) { berr << "Error reading sources"; } } v = fread(&dstInds[i_BRAHMS], sizeof(unsigned int), 1, binfile); if (v == 0) { bout << "2. Read 0 bytes from binfile" << D_INFO; if (ferror(binfile)) { berr << "Error reading destinations"; } } if (_has_delay) { v = fread(&delayForConnTemp[i_BRAHMS], sizeof(unsigned int), 1, binfile); if (v == 0) { if (ferror(binfile)) { berr << "ferror. read " << v << " uints from " << fileName << " for delayForConnTemp[" << i_BRAHMS << "]"; } if (feof(binfile)) { berr << "feof trying to read delayForConnTemp[" << i_BRAHMS << "]"; } berr << "read " << v << " uints from " << fileName << " for delayForConnTemp[" << i_BRAHMS << "]"; } } } } else { srcInds = nodeState.getField("src").getArrayINT32(); dstInds = nodeState.getField("dst").getArrayINT32(); } if (srcInds.size() != dstInds.size()) berr << "Connectivity src and dst lists have different sizes"; // sanity check for (UINT32 i = 0; i < srcInds.size(); ++i) { if (srcInds[i] >= numElementsIn) { berr << "Index out of range for connection : srcInds[" << i << "] (" << srcInds[i] << ") >= numElementsIn ("<< numElementsIn <<")"; } if (dstInds[i] >= numElementsOut) { berr << "Index out of range for connection : dstInds[" << i << "] (" << dstInds[i] << ") >= numElementsOut ("<< numElementsOut <<")"; } } if (_has_delay) { berr << "Unfortunately, delays in Generic inputs are not supported by SpineML_2_BRAHMS." << D_WARN; } spikesIn = false; impulseIn = false; portFound = false; return C_OK; } // CREATE THE PORTS case EVENT_INIT_CONNECT: { // on each call int numInputs = iif.getNumberOfPorts(); if (numInputs == 1 && portFound == false) { portFound = true; if (in.tryAttach(hComponent, "in")) { out.setName("out"); out.create(hComponent); out.setStructure(TYPE_DOUBLE | TYPE_REAL, Dims(numElementsOut).cdims()); } if (ins.tryAttach(hComponent,"inSpike")) { spikesIn = true; outs.setName("out"); outs.create(hComponent); outs.setCapacity(numElementsIn*numElementsOut); // create lookup for spikes spikeInds.resize(numElementsIn); for (UINT32 i = 0; i < srcInds.size(); ++i) { spikeInds[srcInds[i]].push_back(dstInds[i]); } } if (ini.tryAttach(hComponent,"inImpulse")) { impulseIn = true; outi.setName("out"); outi.create(hComponent); outi.setCapacity(numElementsIn*numElementsOut*3); // create lookup for spikes spikeInds.resize(numElementsIn); for (UINT32 i = 0; i < srcInds.size(); ++i) { spikeInds[srcInds[i]].push_back(dstInds[i]); } } } // on last call if (event->flags & F_LAST_CALL) { } // ok return C_OK; } case EVENT_RUN_SERVICE: { if (!spikesIn && !impulseIn) { DOUBLE * inData; inData = (DOUBLE*) in.getContent(); DOUBLE * outData; outData = (DOUBLE *) out.getContent(); // clear old data memset(outData, 0, 8*numElementsOut); for (UINT32 i = 0; i < srcInds.size(); ++i) { outData[dstInds[i]] += inData[srcInds[i]]; } } if (spikesIn) { INT32 * spikeData; UINT32 numSpikes; numSpikes = ins.getContent(spikeData); VINT32 outData; // for each input spike for (UINT32 i = 0; i < numSpikes; ++i) { // for each target of the source of that spike for (UINT32 j = 0; j < spikeInds[spikeData[i]].size(); ++j) { // add output spike to the list outData.push_back(spikeInds[spikeData[i]][j]); } } outs.setContent(&(outData[0]), outData.size()); } if (impulseIn) { INT32 * data; UINT32 count; count = ini.getContent(data); //DOUBLE totalImpulse = 0; VINT32 outData; // for each impulse for (UINT32 i = 0; i < count; i+=3) { // extract impulses and sum INT32 index; DOUBLE value; getImpulse(data,i,index,value); // for each target of the source of that impulse for (UINT32 j = 0; j < spikeInds[index].size(); ++j) { // add output impulse to the list addImpulse(outData, spikeInds[index][j], value); } } outi.setContent(&(outData[0]), outData.size()); } // ok return C_OK; } } // if we service the event, we return C_OK // if we don't, we should return S_NULL to indicate that we didn't return S_NULL; }
Symbol COMPONENT_CLASS_CPP::event(Event* event) { switch(event->type) { case EVENT_STATE_SET: { // extract DataML EventStateSet* data = (EventStateSet*) event->data; XMLNode xmlNode(data->state); DataMLNode nodeState(&xmlNode); // obtain the parameters size = nodeState.getField("size").getINT32(); numElementsOut = size; // Hard-code dataType initialization. I don't know if theres a // way to set this in the XML. It doesn't seem to get set when // SpineCreator writes out the experiment.xml file. dataType = ANALOG; portno = nodeState.getField("port").getINT32(); // get the server name if (nodeState.hasField("host")) { server = nodeState.getField("host").getSTRING(); } else { server = "localhost"; } // get the connection name if (nodeState.hasField("name")) { conn_name = nodeState.getField("name").getSTRING(); } else { conn_name = "unknown"; } // how often to send an output if (nodeState.hasField("skip")) { skip = nodeState.getField("skip").getDOUBLE(); } else { skip = 0.01; } /*string command = nodeState.getField("command").getSTRING(); // launch the command if it is not blank if (!command.compare("")) { // use fork to run in new thread system(command.c_str()); }*/ // scale buffer buffer.resize(size,0); dt = 1000.0f * time->sampleRate.den / time->sampleRate.num; next_t = 0; return C_OK; } // CREATE THE PORTS case EVENT_INIT_CONNECT: { if (event->flags & F_FIRST_CALL) { switch (dataType) { case EVENT: outs.setName("out"); outs.create(hComponent); outs.setCapacity(numElementsOut); break; case ANALOG: out.setName("out"); out.create(hComponent); out.setStructure(TYPE_DOUBLE | TYPE_REAL, Dims(numElementsOut).cdims()); break; case IMPULSE: { berr << "Not implemented"; break; } default: { berr << "Unknown dataType: " << (int)dataType; break; } } } // on last call if (event->flags & F_LAST_CALL) { // connect the socket: // start client if (!client.createClient(server, portno, size, dataType, RESP_AM_TARGET, conn_name)) { berr << client.getLastError(); } /*client.connectClient(portno); // handshake client.handShake(RESP_AM_TARGET); // send data type bool ok; dataType = client.recvDataType(ok); // get size int confirmSize = client.recvSize(ok); if (size != confirmSize) berr << "Wrong size of data coming into External Source: " << double(confirmSize) << " should be: " << double(size); */ } // ok return C_OK; } case EVENT_RUN_SERVICE: { // current simulation time double t = float(time->now) * dt; //cout << "Input t = " << t << endl; // implement skipping if (t > next_t - dt + 0.00001) { next_t = t + skip; // only analog for now - will add spikes etc.. later switch (dataType) { case EVENT: { berr << "Not implemented"; break; } case ANALOG: client.recvData((char *) &(buffer[0]), buffer.size()*sizeof(double)); break; case IMPULSE: { berr << "Not implemented"; break; } default: { berr << "Bad value for dataType in EVENT_RUN_SERVICE"; break; } } } out.setContent(&(buffer[0])); // ok return C_OK; } case EVENT_RUN_STOP: { //client.sendEnd(); client.disconnectClient(); // ok return C_OK; } } // if we service the event, we return C_OK // if we don't, we should return S_NULL to indicate that we didn't return S_NULL; }