//
// Version: $Id: wxmodel.cpp 162 2014-01-08 15:09:14Z gk $
// Implementation of GUI interface
//
/*
Version: $Id: constructs.h 170 2014-01-29 14:00:04Z gk $
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "constructs.h"
#include "wxmodel.h"
enum {
MENU_RUN=1,
MENU_1Hour,
MENU_REFRESH,
MENU_QUIT,
MENU_CS = 100,
MENU_CSUS = 300,
MENU_STRONGTRAIN = 400,
MENU_INTERSTIM = 500,
MENU_PROTO = 600,
};
LAWindow::LAWindow(const wxString& title, LANetwork* net)
:wxFrame(NULL, wxID_ANY, title, wxDefaultPosition,wxSize(1000, 600))
{
CreateStatusBar();
SetStatusText(wxT("Ready"));
Centre();
this->network = new LANetwork();
//this->network_panel = new LAPanel(this);
this->network_panel->network = this->network;
this->network->wx_window = this;
//this->network_panel->SetFocus();
wxMenu* m = new wxMenu;
m->Append(MENU_RUN, _("&Run"));
m->Append(MENU_REFRESH, _("Re&fresh"));
m->Append(MENU_QUIT, _("&Quit"));
wxMenuBar* mb = new wxMenuBar;
mb->Append(m, _("&Simulation"));
m = new wxMenu;
for (int i =0; i < network->n_inputs; i++)
m->Append(MENU_CS+i, wxString::Format(wxT("CS %d"), i));
mb->Append(m, _("Run CS"));
m = new wxMenu;
for (int i =0; i < network->n_inputs; i++)
m->Append(MENU_CSUS+i, wxString::Format(wxT("CS+US %d"), i));
mb->Append(m, _("Train"));
m = new wxMenu;
for (int i =1; i < 5; i++)
m->Append(MENU_INTERSTIM+i, wxString::Format(wxT("Interstim %d hours"), i));
mb->Append(m, _("Interstim"));
wxString mprotos[] = {
wxT("Coallocation Protocol"),
wxT("Capacity Protocol"),
};
m = new wxMenu;
for (size_t i =0; i < 2; i++)
{
m->Append(MENU_PROTO+i, mprotos[i]);
}
mb->Append(m, _("Protocols"));
SetMenuBar(mb);
//Refresh();
}
void LAWindow::OnQuit(wxCommandEvent& ev)
{
printf("cleaning up... \n");
this->network->Cleanup();
Close(true);
printf("Done\n");
}
/* Menu handlers */
void LAWindow::OnRun(wxCommandEvent& ev)
{
int id = ev.GetId();
printf("Running %d!\n", id);
SetStatusText(wxString::Format(wxT("Wait, running %d..."), id));
if (id >= MENU_PROTO) // Protocols
{
int n = id - MENU_PROTO;
switch (n)
{
case 0:
{
this->network->CreateFearNet(100,20, 10, 4);
for (int i =0; i < network->n_inputs; i++)
{
SetStatusText(wxString::Format(wxT("Training # %d..."), i));
network->Stimulate(i, 2);
int mins = 50;
SetStatusText(wxString::Format(wxT("Waiting %d minutes ..."), mins) );
network->Interstim(mins*60);
}
SetStatusText(wxString::Format(wxT("Waiting 8 Hours...")));
network->Interstim((60*8)*60);
FILE* f = fopen("./data/0/memorytest.dat", "w");
network->enablePlasticity = false;
network->ResetCrebLevels();
for (int i =0; i < network->n_inputs; i++)
{
SetStatusText(wxString::Format(wxT("Testing # %d..."), i));
network->Stimulate(i, 1);
for (nrn_iter ni = network->pyr_list.begin(); ni != network->pyr_list.end(); ++ni)
{
fprintf(f , "%d ", (*ni)->total_spikes);
}
fprintf(f, "\n");
}
network->enablePlasticity = true;
fclose(f);
f = fopen("./data/0/synweights.txt", "w") ;
for (syn_iter si = network->synapses.begin(); si != network->synapses.end(); ++si)
{
LASynapse* syn = *si;
if (syn->isPlastic != -1)
fprintf(f, "%d %d %d %d %f\n", syn->sid, syn->target_branch->bid, syn->target_nrn->nid, syn->source_nrn->input_id, syn->weight);
}
fclose(f);
}
break;
case 1:
{
this->network->CreateFearNet(100, 20, 10, 6);
this->network->RunStoreTest(10, 1, 60, 0);
printf("Done\n");
//this->network->StoreDataFiles("./data/0/");
}
break;
case 2:
break;
case 3:
break;
case 4:
break;
}
}
else if (id >= MENU_INTERSTIM)
network->Interstim((id - MENU_INTERSTIM)*3600);
else if (id >= MENU_CSUS)
network->Stimulate( id - MENU_CSUS, 2);
else if (id >= MENU_CS)
network->Stimulate( id - MENU_CS, 1);
SetStatusText(wxT("Done!"));
printf("Done running\n");
}
void LAPanel::OnTimer(wxCommandEvent& ev)
{
}
void LAPanel::OnClick(wxMouseEvent& e)
{
/* Find out the nearest clicked neuron, and print properties in the console */
for (pt_iterator pi = nrnpoints.begin(); pi != nrnpoints.end(); ++pi)
{
wxPoint p = pi->second;
if ( e.m_x >=p.x && e.m_x <= p.x + 80 && e.m_y <= p.y && e.m_y >= p.y-80)
{
int nid = pi->first;
LANeuron* nrn = network->neurons[nid];
printf("NID %d (%s) p=%f pr=%f\n", nid, nrn->type == 'I'? "in" :"pyr" , nrn->protein, nrn->proteinRate);
for (branch_iter bi = nrn->branches.begin(); bi != nrn->branches.end(); ++bi)
{
LABranch* b = *bi;
printf(" branch %d str=%f (tag %f) pb=%f pbr=%f depol=%f\n", b->bid, b->strength, b->strengthTag, b->protein, b->proteinRate, b->depol);
for (syn_iter si=b->synapses.begin(); si != b->synapses.end(); ++si)
{
LASynapse* s = *si;
printf(" syn %d from=%d (%d) calc=%f stag=%f eltp=%f w=%f\n", s->sid, s->source_nrn->input_id, s->source_nrn->nid, s->calcium, s->stag, s->eltp, s->weight);
}
}
}
}
fflush(stdout);
}
LAPanel::LAPanel(wxFrame* parent)
: wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE | wxFULL_REPAINT_ON_RESIZE)
{
Connect(wxEVT_PAINT, wxPaintEventHandler(LAPanel::OnPaint));
Connect(wxEVT_LEFT_UP, wxMouseEventHandler(LAPanel::OnClick));
hasStarted =0;
}
inline static void colormap1(wxBrush& pen, float value )
{
pen.SetColour(250, 250-value*200, value*200);
}
inline static void colormap1(wxPen& pen, float value )
{
pen.SetColour(value*240.0, 0, 250 - value*200.0);
}
/*
static int palette[][3] = {
{4, 3,200},
{4, 200,3},
{220, 200,1},
{200, 190,3},
{255,255,0},
{255,0,255 },
{255,0,0 },
{128,0,0 },
{192,192,192 },
{128,128,128 },
{250, 3,3},
{0,255,0},
{128,128,0},
{200, 190,3},
{0,128,0},
{128,0,128},
{0,255,255},
{0,128,128},
{ 50,50,255 },
{4, 200,3},
};
*/
static wxPoint somap[7] = {
wxPoint(30, 10),
wxPoint(30, 10),
wxPoint(40, 10),
wxPoint(40, 10),
wxPoint(40, 10),
wxPoint(35, 1),
wxPoint(30, 10)
};
static wxColour pyrcolor(150, 200, 150);
static wxColour incolor(200, 100, 100);
static wxColour syncolor(30, 200, 20);
static wxColour eltpcolor(200, 30, 20);
static wxColour calccolor(20, 30, 200);
static wxColour firecolor(255, 30,30);
static wxColour branchfirecolor(250, 100,30);
static wxPen pen;
void LAPanel::drawPyrCell(wxPaintDC& dc, LANeuron* n, int x , int y)
{
int nrnheight = this->network->n_branches_per_neuron* 16;
dc.SetFont(*wxSMALL_FONT);
pen.SetColour(0,0,0);
pen.SetStyle(wxCAP_PROJECTING);
float v = (n->V - (-param_E_L)) / 20.0;
if (v > 1.0) v = 1.0;
else if (v < 0.0) v = 0.0;
wxColor* nrncolor = &pyrcolor;
if (n->V > 35.0)
nrncolor = &firecolor;
//pen.SetColour(0,0,0);
dc.SetBrush(wxBrush(*nrncolor, wxSOLID));
pen.SetColour(*nrncolor);
pen.SetWidth(3);
dc.SetPen(pen);
wxPoint px1(x+60, y);
wxPoint px2(x+60, y-nrnheight-10);
dc.DrawLine(px1, px2);
pen.SetWidth(2);
dc.SetPen(pen);
dc.DrawPolygon(7, somap, x+25, y);
dc.DrawText(wxString::Format(wxT("%f %d %f"), n->exc_cur, n->total_spikes, n->totcalc), x+50, y+14);
float yy = y-10;
int nbr =0;
for (branch_iter bi = n->branches.begin(); bi != n->branches.end(); ++bi)
{
//nbr = 0; // XXX
LABranch* b = *bi;
yy -= 15;
wxPoint pt1(x+60, yy);
int dx = x+60+56;
wxPoint pt2(dx, yy);
if (nbr%2)
{
pt2.x = x;
}
float hh = b->strength*3.0;
pen.SetWidth(hh);
if (b->dspike > 10.0)
pen.SetColour( branchfirecolor);
else
pen.SetColour( pyrcolor);
dc.SetPen(pen);
dc.DrawLine(pt2, pt1);
dc.DrawText(wxString::Format(wxT("%d %.3f "), b->branch_spikes, b->totcalc ), x+110, yy);
int xxx = x+66;
if (nbr%2) xxx = x+54;
int lastinput = -1;
for (syn_iter si=b->synapses.begin(); si != b->synapses.end(); ++si)
{
LASynapse* s = *si;
if (s->source_nrn->isSpiking)
{
pen.SetColour(firecolor);
}
else if (s->source_nrn->input_type == TYPE_CS && s->source_nrn->input_id >=0)
{
pen.SetColour(syncolor);
//pen.SetColour( palette[s->source_nrn->input_id][0], palette[s->source_nrn->input_id][1], palette[s->source_nrn->input_id][2]);
}
else
{
//continue;
pen.SetColour(220, 220, 220);
//pen.SetColour(255.*(s->stag+1.0) / 2.0, 255.*(s->eltp+1.0)/2.0, 200. );
}
int space =1;
if (lastinput == -1) lastinput = s->source_nrn->input_id;
else if ( s->source_nrn->input_id != lastinput)
{
space = 4;
lastinput = s->source_nrn->input_id;
}
if ( nbr%2)
xxx -= space;
else
xxx += space;
wxPoint sp1(xxx, yy-1);
int ddd = yy -1 - ( s->weight)*10.0;
int ddd2 = ddd - (s->stag)*10.0;
wxPoint sp2(xxx, ddd-1);
wxPoint sp3(xxx, ddd2-1);
wxPoint sp4(xxx, ddd2-1 - s->calcium*10.);
pen.SetWidth(1);
dc.SetPen(pen);
dc.DrawLine(sp1, sp2);
pen.SetColour(eltpcolor);
dc.SetPen(pen);
dc.DrawLine(sp2, sp3);
//pen.SetColour(calccolor);
//dc.SetPen(pen);
//dc.DrawLine(sp3, sp4);
}
nbr++;
}
}
void LAPanel::drawInCell(wxPaintDC& dc, LANeuron* n, int x , int y)
{
int nrnheight = this->network->n_branches_per_neuron* 16;
pen.SetColour(0,0,0);
pen.SetStyle(wxCAP_PROJECTING);
//pen.SetColour(0,0,0);
wxColor* nrncolor = &incolor;
if (n->V > 18.)
nrncolor = &firecolor;
pen.SetColour( *nrncolor);
pen.SetWidth(3);
dc.SetBrush(wxBrush(*nrncolor, wxSOLID));
dc.SetPen(pen);
dc.DrawCircle(x+60, y+8, 5);
wxPoint px1(x+60, y);
wxPoint px2(x+60, y-nrnheight-10);
dc.DrawLine(px1, px2);
/*
if (n->V ==0.0)
pen.SetColour(240, 100, 20);
else
pen.SetColour(20, 180, 20);
*/
pen.SetWidth(2);
dc.SetPen(pen);
//dc.DrawRectangle(x-4, y-4, 8,8);
dc.DrawText(wxString::Format(wxT("%d"), n->total_spikes), x, y+4);
//float xx = x;
float yy = y-10;
int nbr =0;
for (branch_iter bi = n->branches.begin(); bi != n->branches.end(); ++bi)
{
LABranch* b = *bi;
yy -= 15;
//float v = b->depol / 20.0;
//if (v > 1.0) v = 1.0;
wxPoint pt1(x+60, yy);
int dx = x+60+56;
wxPoint pt2(dx, yy);
if (nbr%2)
{
pt2.x = x;
}
//dc.DrawText(wxString::Format(wxT("%d"), b->branch_spikes), x+70, yy-6);
if (b->strength > 1.0)
pen.SetWidth( b->strength*1.0);
else
pen.SetWidth(1);
pen.SetColour( *nrncolor);
dc.SetPen(pen);
dc.DrawLine(pt2, pt1);
int xxx = x+66;
if (nbr%2) xxx = x+54;
int lastinput = -1;
for (syn_iter si=b->synapses.begin(); si != b->synapses.end(); ++si)
{
LASynapse* s = *si;
int space =1;
if (lastinput == -1) lastinput = s->source_nrn->input_id;
else if ( s->source_nrn->input_id != lastinput)
{
space = 3;
lastinput = s->source_nrn->input_id;
}
if ( nbr%2)
xxx -= space;
else
xxx+= space;
wxPoint sp1(xxx, yy);
int ddd = yy - ( s->weight )*7.0;
wxPoint sp2(xxx, ddd);
//if (s->source_nrn->V > -10)
// pen.SetColour(200.0, 180.0, 0);
pen.SetColour(200, 200, 200);
pen.SetWidth(1);
dc.SetPen(pen);
dc.DrawLine(sp1, sp2);
}
//nbr++;
}
}
void LAPanel::OnPaint(wxPaintEvent& event)
{
wxPaintDC dc(this);
wxSize size = GetClientSize();
int width = size.GetWidth();
dc.Clear();
wxPen pen ;
wxBrush brush;
if (!this->network || !this->network->neurons.size()) return;
int nrnheight = this->network->n_branches_per_neuron* 20;
int nrnwidth = 160;
int x = 20;
int y = nrnheight+40;
pen.SetColour(0,0,0);
pen.SetStyle(wxCAP_PROJECTING);
nrn_iter pc = network->pyr_list.begin();
nrn_iter ic = network->in_list.begin();
int nni =0;
int totshown =0;
while(totshown++ < 10)
{
if (x+100 >= width)
{
x = 20;
y +=nrnheight+80;
}
LANeuron* n;
if (nni++%5 !=0)
{
n = *pc;
drawPyrCell(dc, n, x, y);
pc++;
}
else
{
n = *ic;
drawInCell(dc, n, x, y);
ic++;
}
nrnpoints[n->nid] = wxPoint(x, y);
x += nrnwidth;
if (pc == network->pyr_list.end() || ic == network->in_list.end())
break;
}
}
bool LAApp::OnInit()
{
LAWindow* window = new LAWindow(wxT("LA Model"), NULL);
//window->network->window = window;
window->Show(true);
return true;
}
BEGIN_EVENT_TABLE(LAWindow, wxFrame)
EVT_MENU(MENU_RUN, LAWindow::OnRun)
EVT_MENU_RANGE(MENU_CS, MENU_CS+20, LAWindow::OnRun)
//EVT_MENU_RANGE(MENU_CSUS, MENU_CSUS+20, LAWindow::OnRun)
EVT_MENU_RANGE(MENU_INTERSTIM, MENU_INTERSTIM+5, LAWindow::OnRun)
//EVT_MENU_RANGE(MENU_STRONGTRAIN, MENU_STRONGTRAIN, LAWindow::OnRun)
EVT_MENU_RANGE(MENU_PROTO, MENU_PROTO+4, LAWindow::OnRun)
EVT_MENU(MENU_QUIT, LAWindow::OnQuit)
END_EVENT_TABLE()
IMPLEMENT_APP(LAApp)