SpikeStream Nemo Plugin
0.2
|
00001 //SpikeStream includes 00002 #include "NemoParametersDialog.h" 00003 #include "ParametersDialog.h" 00004 #include "SpikeStreamException.h" 00005 #include "STDPFunctions.h" 00006 #include "Util.h" 00007 using namespace spikestream; 00008 00009 //Qt includes 00010 #include <QDebug> 00011 #include <QLabel> 00012 #include <QLayout> 00013 #include <QPushButton> 00014 00015 //Other includes 00016 #include "nemo.h" 00017 00018 00019 #define NO_CUDA_DEVICES_TEXT "No CUDA devices available." 00020 00022 NemoParametersDialog::NemoParametersDialog(nemo_configuration_t nemoConfig, unsigned stdpFunctionID, QWidget* parent) : QDialog(parent) { 00023 00024 //Store current nemo config and create a default nemo config 00025 this->currentNemoConfig = nemoConfig; 00026 defaultNemoConfig = nemo_new_configuration(); 00027 this->stdpFunctionID = stdpFunctionID; 00028 00029 //Create layouts to organize dialog 00030 QVBoxLayout* mainVBox = new QVBoxLayout(this); 00031 QGridLayout* gridLayout = new QGridLayout(); 00032 00033 //Tracks rows added. 00034 int rowCntr = 0; 00035 00036 //Nemo version 00037 QString versionStr = "Nemo version "; 00038 gridLayout->addWidget(new QLabel(versionStr + nemo_version()), rowCntr, 0); 00039 ++rowCntr; 00040 00041 //Combo box to select backend 00042 backendCombo = new QComboBox(); 00043 backendCombo->addItem("CUDA Hardware"); 00044 backendCombo->addItem("CPU"); 00045 gridLayout->addWidget(new QLabel("Backend: "), rowCntr, 0); 00046 gridLayout->addWidget(backendCombo, rowCntr, 1); 00047 connect(backendCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(backendChanged(int))); 00048 ++rowCntr; 00049 00050 //CUDA device list 00051 cudaDeviceCombo = new QComboBox(); 00052 getCudaDevices(cudaDeviceCombo); 00053 cudaDeviceLabel = new QLabel("CUDA device: "); 00054 gridLayout->addWidget(cudaDeviceLabel, rowCntr, 0); 00055 gridLayout->addWidget(cudaDeviceCombo, rowCntr, 1); 00056 ++rowCntr; 00057 00058 //Add combo with STDP functions and button to edit parameters 00059 stdpCombo = new QComboBox(); 00060 getStdpFunctions(stdpCombo); 00061 gridLayout->addWidget(stdpCombo, rowCntr, 0); 00062 QPushButton* stdpParamButton = new QPushButton("Parameters"); 00063 connect(stdpParamButton, SIGNAL(clicked()), this, SLOT(stdpParameterButtonClicked())); 00064 gridLayout->addWidget(stdpParamButton, rowCntr, 1); 00065 ++rowCntr; 00066 00067 //Sets the fields to match the config 00068 loadParameters(currentNemoConfig); 00069 if((int)stdpFunctionID > stdpCombo->count()) 00070 throw SpikeStreamException("STDP function ID is out of range: " + QString::number(stdpFunctionID)); 00071 stdpCombo->setCurrentIndex(stdpFunctionID); 00072 00073 //Add the grid layout 00074 mainVBox->addLayout(gridLayout); 00075 00076 //Add the buttons 00077 addButtons(mainVBox); 00078 } 00079 00080 00082 NemoParametersDialog::~NemoParametersDialog(){ 00083 } 00084 00085 00086 /*----------------------------------------------------------*/ 00087 /*----- PRIVATE SLOTS -----*/ 00088 /*----------------------------------------------------------*/ 00089 00092 void NemoParametersDialog::backendChanged(int index){ 00093 if(index == 0){ 00094 cudaDeviceLabel->show(); 00095 cudaDeviceCombo->show(); 00096 } 00097 else if(index == 1){ 00098 cudaDeviceLabel->hide(); 00099 cudaDeviceCombo->hide(); 00100 } 00101 } 00102 00103 00105 void NemoParametersDialog::defaultButtonClicked(){ 00106 loadParameters(defaultNemoConfig); 00107 00108 //Set STDP function 00109 stdpCombo->setCurrentIndex(0);//0 is the default 00110 } 00111 00112 00115 void NemoParametersDialog::okButtonClicked(){ 00116 try{ 00117 //Throws an exception if parameter values are empty or invalid 00118 storeParameterValues(); 00119 this->accept(); 00120 } 00121 catch(SpikeStreamException& ex){ 00122 qWarning()<<ex.getMessage(); 00123 } 00124 } 00125 00126 00130 /*----------------------------------------------------------*/ 00131 /*----- PRIVATE METHODS -----*/ 00132 /*----------------------------------------------------------*/ 00133 00135 void NemoParametersDialog::addButtons(QVBoxLayout* mainVLayout){ 00136 QHBoxLayout *buttonBox = new QHBoxLayout(); 00137 QPushButton* cancelButton = new QPushButton("Cancel"); 00138 buttonBox->addWidget(cancelButton); 00139 connect (cancelButton, SIGNAL(clicked()), this, SLOT(reject())); 00140 QPushButton* defaultsButton = new QPushButton("Load defaults"); 00141 buttonBox->addWidget(defaultsButton); 00142 connect (defaultsButton, SIGNAL(clicked()), this, SLOT(defaultButtonClicked())); 00143 QPushButton* okButton = new QPushButton("Ok"); 00144 buttonBox->addWidget(okButton); 00145 connect (okButton, SIGNAL(clicked()), this, SLOT(okButtonClicked())); 00146 mainVLayout->addLayout(buttonBox); 00147 } 00148 00149 00151 void NemoParametersDialog::checkNemoOutput(nemo_status_t result, const QString& errorMessage){ 00152 if(result != NEMO_OK) 00153 throw SpikeStreamException(errorMessage + ": " + nemo_strerror()); 00154 } 00155 00156 00158 void NemoParametersDialog::getCudaDevices(QComboBox* combo){ 00159 unsigned numCudaDevices = 0; 00160 nemo_status_t result = nemo_cuda_device_count(&numCudaDevices); 00161 if(result != NEMO_OK){ 00162 //combo->addItem("CUDA error: " + QString(nemo_strerror())); 00163 combo->addItem(NO_CUDA_DEVICES_TEXT); 00164 return; 00165 } 00166 00167 if(numCudaDevices == 0){ 00168 combo->addItem(NO_CUDA_DEVICES_TEXT); 00169 return; 00170 } 00171 00172 for(unsigned i=0; i<numCudaDevices; ++i){ 00173 const char* devDesc; 00174 checkNemoOutput(nemo_cuda_device_description(i, &devDesc), "Error getting device description."); 00175 combo->addItem(devDesc); 00176 } 00177 } 00178 00179 00181 void NemoParametersDialog::getStdpFunctions(QComboBox *combo){ 00182 QList<unsigned> functionIDs = STDPFunctions::getFunctionIDs(); 00183 for(int i=0; i<functionIDs.size(); ++i){ 00184 combo->addItem(STDPFunctions::getFunctionDescription(functionIDs.at(i))); 00185 } 00186 combo->setCurrentIndex(stdpFunctionID); 00187 } 00188 00189 00191 void NemoParametersDialog::loadParameters(nemo_configuration_t config){ 00192 //Backend 00193 backend_t backend; 00194 int index = 0; 00195 checkNemoOutput(nemo_backend(config, &backend), "Failed to get NeMo backend."); 00196 if(backend == NEMO_BACKEND_CUDA) 00197 index = 0; 00198 else if (backend == NEMO_BACKEND_CPU) 00199 index = 1; 00200 else 00201 throw SpikeStreamException("Backend not recognized: " + QString::number(backend)); 00202 00203 /* Set backend combo to index and call function to make sure inputs are correctly hidden or shown 00204 It may not change the current index, so need to call this function */ 00205 backendCombo->setCurrentIndex(index); 00206 backendChanged(index); 00207 00208 //CUDA device 00209 int cudaDev; 00210 checkNemoOutput(nemo_cuda_device(config, &cudaDev), "Error getting CUDA device from NeMo"); 00211 if(cudaDev > cudaDeviceCombo->count()){ 00212 throw SpikeStreamException("CUDA device out of range: " + QString::number(cudaDev)); 00213 } 00214 if(cudaDev < 0) 00215 cudaDeviceCombo->setCurrentIndex(0); 00216 else 00217 cudaDeviceCombo->setCurrentIndex(cudaDev); 00218 } 00219 00220 00223 void NemoParametersDialog::storeParameterValues(){ 00224 //Set hardware configuration 00225 if(backendCombo->currentIndex() == 0){//CUDA 00226 if(cudaDeviceCombo->currentText() == NO_CUDA_DEVICES_TEXT) 00227 throw SpikeStreamException("Cannot use CUDA - no CUDA devices are available."); 00228 checkNemoOutput(nemo_set_cuda_backend(currentNemoConfig, cudaDeviceCombo->currentIndex()), "Failed to set CUDA device: "); 00229 } 00230 else if(backendCombo->currentIndex() == 1){//CPU 00231 checkNemoOutput(nemo_set_cpu_backend(currentNemoConfig), "Failed to set backend to CPU: "); 00232 } 00233 else{ 00234 throw SpikeStreamException("Backend combo index not recognized."); 00235 } 00236 00237 //If we have reached this point, hardware configuration is ok 00238 00239 //STDP function 00240 stdpFunctionID = stdpCombo->currentIndex(); 00241 } 00242 00243 00245 void NemoParametersDialog::stdpParameterButtonClicked(){ 00246 try{ 00247 stdpFunctionID = stdpCombo->currentIndex(); 00248 00249 ParametersDialog paramDialog( 00250 STDPFunctions::getParameterInfoList(stdpFunctionID), 00251 STDPFunctions::getDefaultParameters(stdpFunctionID), 00252 STDPFunctions::getParameters(stdpFunctionID), 00253 this 00254 ); 00255 if(paramDialog.exec() == QDialog::Accepted){ 00256 QHash<QString, double> newParameters = paramDialog.getParameters(); 00257 STDPFunctions::setParameters(stdpFunctionID, newParameters); 00258 } 00259 } 00260 catch(SpikeStreamException& ex){ 00261 qCritical()<<ex.getMessage(); 00262 } 00263 } 00264 00265 00266