SpikeStream Nemo Plugin  0.2
NemoParametersDialog.cpp
Go to the documentation of this file.
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 
 All Classes Files Functions Variables Typedefs Defines