/* Version: $Id: wxmodel.cpp 134 2013-11-22 14:30:58Z gk $ Implementation of GUI interface 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 . */ #include "constructs.h" #include "wxglmodel.h" #include "wx/sizer.h" #include "wx/glcanvas.h" #include #include #include // The next global variable controls the animation's state and speed. float RotateAngle = 0.0f; // Angle in degrees of rotation around y-axis float Azimuth = 20.0; // Rotated up or down by this amount float AngleStepSize = 3.0f; // Step three degrees at a time const float AngleStepMax = 10.0f; const float AngleStepMin = 0.1f; int WireFrameOn = 1; // == 1 for wire frame mode GLfloat light_position2[] = { 0, 1,1,0}; 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, }; /* wxDECLARE_EVENT(wxEVT_COMMAND_MYTHREAD_COMPLETED, wxThreadEvent); wxDECLARE_EVENT(wxEVT_COMMAND_MYTHREAD_UPDATE, wxThreadEvent); */ GLuint raw_texture_load(const char *filename, int width, int height) { GLuint texture =0; unsigned char *data; FILE *file; // open texture data file = fopen(filename, "rb"); if (file == NULL) return 0; // allocate buffer int sq; data = (unsigned char*) malloc(sq = width * height *4 ); cout << "sq=" << sq<network; } ~MyThread() {} protected: virtual ExitCode Entry(); LAWindow *m_pHandler; }; wxThread::ExitCode MyThread::Entry() { this->m_network->RunStore2(3, 1, 180, 0); exit(0); return (wxThread::ExitCode)0; // success } LAWindow::LAWindow(const wxString& title, LANetwork* netw) :wxFrame(NULL, wxID_ANY, title, wxDefaultPosition,wxSize(1024, 768)) { Centre(); timersRun =0; int args[] = {WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_DEPTH_SIZE, 16, 0}; this->network = netw; this->network_glpanel = new LAGLPane(this, this->network, args); //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); // Connect(wxEVT_TIMER, wxCommandEventHandler(LAWindow::OnTimer)); } void LAWindow::OnQuit(wxCommandEvent& ev) { printf("cleaning up... \n"); this->network->Cleanup(); Close(true); printf("Done\n"); } void LAWindow::OnTimer(wxCommandEvent& ev) { //printf("Window Timer!\n"); timersRun++; float angle = this->network_glpanel->angle; angle += 0.2; if (angle>360.0) angle =0.; this->network_glpanel->angle =angle; this->network_glpanel->Refresh(false); } /* 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(30, 100, 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 2: break; case 3: break; case 4: break; } } else if (id >= MENU_INTERSTIM) network->Interstim((id - MENU_INTERSTIM)*3600); SetStatusText(wxT("Done!")); printf("Done running\n"); } 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] = { {200, 50,50}, {50, 200,50}, {250 , 250,100}, {200, 190,3}, {255,0,255 }, {4, 3,200}, {255,0,0 }, {128,0,0 }, {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; bool LAApp::OnInit() { this->network = new LANetwork(); LANetwork::SetRandomSeed(1980); this->network->CreateFearNet(20, 20, 10, 6); LAWindow* window = new LAWindow(wxT("LA Model"), this->network); window->network = network; window->timer = new wxTimer(window, 13); window->timer->Start(30); MyThread* m_pThread = new MyThread(window); cout << "Starting thread!!\n"<Create(); if (err != wxTHREAD_NO_ERROR) { perror("TA"); cout << ("Can't create the thread!") << endl; printf("Error %d\n", err); delete m_pThread; m_pThread = NULL; } else { err = m_pThread->Run() ; if ( err != wxTHREAD_NO_ERROR ) { perror("TA"); cout << ("Can't create the thread!") << endl; printf("Error %d\n", err); delete m_pThread; m_pThread = NULL; } } window->Show(true); return true; } IMPLEMENT_APP(LAApp) 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() BEGIN_EVENT_TABLE(LAGLPane, wxGLCanvas) //EVT_MOTION(BasicGLPane::mouseMoved) //EVT_LEFT_DOWN(BasicGLPane::mouseDown) //EVT_LEFT_UP(BasicGLPane::mouseReleased) //EVT_RIGHT_DOWN(BasicGLPane::rightClick) //EVT_LEAVE_WINDOW(BasicGLPane::mouseLeftWindow) //EVT_SIZE(BasicGLPane::resized) //EVT_KEY_DOWN(BasicGLPane::keyPressed) //EVT_KEY_UP(BasicGLPane::keyReleased) //EVT_MOUSEWHEEL(BasicGLPane::mouseWheelMoved) EVT_PAINT(LAGLPane::render) END_EVENT_TABLE() // Vertices and faces of a simple cube to demonstrate 3D render // source: http://www.opengl.org/resources/code/samples/glut_examples/examples/cube.c GLfloat v[8][3]; GLint faces[6][4] = { /* Vertex indices for the 6 faces of a cube. */ {0, 1, 2, 3}, {3, 2, 6, 7}, {7, 6, 5, 4}, {4, 5, 1, 0}, {5, 6, 2, 1}, {7, 4, 0, 3} }; GLfloat light_diffuse[] = {1.0, 1.0, 1.0, 2.0}; /* Red diffuse light. */ LAGLPane::LAGLPane(wxFrame* parent, LANetwork* net, int* args) : wxGLCanvas(parent, wxID_ANY, args, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE) { this->m_context = new wxGLContext(this); SetBackgroundStyle(wxBG_STYLE_CUSTOM); m_sphereTexture = 0; //glClearColor (0.0, 0.0, 0.0, 0.0); this->m_quadric = gluNewQuadric(); m_network = net; angle =0; // To avoid flashing on MSW this->m_sphereq = gluNewQuadric(); } LAGLPane::~LAGLPane() { delete m_context; } void LAGLPane::resized(wxSizeEvent& evt) { // wxGLCanvas::OnSize(evt); Refresh(); } GLfloat light_position[] = { 2, 2,2,0}; GLfloat light_amb[] = { 0.4,0.4, 0.4 } ; GLfloat myglfog[] = {0.8, 0.8,1.0 , 1.}; /** Inits the OpenGL viewport for drawing in 3D. */ void LAGLPane::prepare3DViewport(int topleft_x, int topleft_y, int bottomrigth_x, int bottomrigth_y) { //glClearColor(0.0, 0.0f, 0.0f, 1.0f); // Black Background } /** Inits the OpenGL viewport for drawing in 2D. */ void LAGLPane::prepare2DViewport(int topleft_x, int topleft_y, int bottomrigth_x, int bottomrigth_y) { } int LAGLPane::getWidth() { return GetSize().x; } int LAGLPane::getHeight() { return GetSize().y; } void LAdrawNeuron() { } GLUquadricObj* myReusableQuadric = 0; void LAGLPane::drawPyrNeuron( LANeuron* n) { glPushMatrix(); glRotatef(-90, 1,0,0); float b =n->V/90; if (b < -0.1) b = -0.1; if (n->isSpiking) glColor3f(1.0, 1.0, 1.0); else glColor3f(0.5, 0.5+b, 0.5-b); gluCylinder(this->m_quadric, 0.7, 0.02, 0.9, 16, 16); gluCylinder(this->m_quadric, 0.05, 0.01, 8.2, 8, 8); glRotatef(90, 1,0,0); glTranslatef(0, 1.0, 0); float ang = 0.; pthread_mutex_lock(&n->network->synapses_mutex); for (branch_iter bi = n->branches.begin(); bi != n->branches.end(); ++bi) { LABranch* b = *bi; glTranslatef(0, 0.3, 0); glPushMatrix(); glRotatef(ang, 0,1,0); ang+= 55; glColor3f(0.6, 0.6, 0.6); glBegin(GL_LINES); glVertex3f(0, 0, 0); glVertex3f(0, 0, 2); glEnd(); for (syn_iter si=b->synapses.begin(); si != b->synapses.end(); ++si) { LASynapse* s = *si; if (s->source_nrn->input_id >=0 && s->source_nrn->input_id < 3 ) { int iid = s->source_nrn->input_id; if (s->source_nrn->isSpiking) glColor3f(255, 255, 255); else if (s->source_nrn->input_id <0) { glColor3f(50, 50, 50); } else { int* p = palette[iid]; if (s->source_nrn->nid%2) glColor3f(p[0]/500., p[1]/500., p[2]/500.); else glColor3f(p[0]/300., p[1]/300., p[2]/300.); } glTranslatef(0.0, 0.0, 0.2); //glRotatef(-90, 1,0,0); float height = 0.05 + (0.12*(s->weight/3.0)); gluDisk(this->m_quadric, 0, height, 9, 9); //gluCylinder(this->m_quadric, 0.03, 0.03, height, 8, 8); //glRotatef(90, 1,0,0); } } glTranslatef(0, -0.08, 0); glPopMatrix(); } pthread_mutex_unlock(&n->network->synapses_mutex); glPopMatrix(); glFlush(); } void LAGLPane::render( wxPaintEvent& evt) { if(!IsShown()) return; cout<< "Rendering" <angle, 0.0, 1, .05); glPushMatrix(); glRotatef( 90, 1, 0, 0); gluQuadricDrawStyle(m_sphereq, GLU_LINE); glColor3f(0.3, 0.4, 0.5); gluSphere(m_sphereq, 20.2, 32, 16); glPopMatrix(); /* glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, m_sphereTexture); gluSphere(m_sphereq, 1.2, 32, 32); glDisable(GL_TEXTURE_2D); */ if (this->m_network && this->m_network->pyr_list.size()) { int tot =0; for (nrn_iter ni = this->m_network->pyr_list.begin(); ni != this->m_network->pyr_list.end(); ++ni) { LANeuron* n= *ni; glPushMatrix(); glTranslatef((tot%4)*6.0 - 9., 0., (tot/4)*6.0 - 9.); drawPyrNeuron(n); glPopMatrix(); if (tot++>10) break; } } //glFlush(); SwapBuffers(); }