Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Class Members | File Members

ArchiveStatisticsDialog.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   SpikeStream Application                                               *
00003  *   Copyright (C) 2007 by David Gamez                                     *
00004  *   david@davidgamez.eu                                                   *
00005  *   Version 0.1                                                           *
00006  *                                                                         *
00007  *   This program is free software; you can redistribute it and/or modify  *
00008  *   it under the terms of the GNU General Public License as published by  *
00009  *   the Free Software Foundation; either version 2 of the License, or     *
00010  *   (at your option) any later version.                                   *
00011  *                                                                         *
00012  *   This program is distributed in the hope that it will be useful,       *
00013  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00014  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00015  *   GNU General Public License for more details.                          *
00016  *                                                                         *
00017  *   You should have received a copy of the GNU General Public License     *
00018  *   along with this program; if not, write to the                         *
00019  *   Free Software Foundation, Inc.,                                       *
00020  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00021  ***************************************************************************/
00022 
00023 //SpikeStream includes
00024 #include "ArchiveStatisticsDialog.h"
00025 #include "Utilities.h"
00026 
00027 //Qt includes
00028 #include <qbuttongroup.h>
00029 #include <qlayout.h>
00030 #include <qpushbutton.h>
00031 #include <qmessagebox.h>
00032 #include <qvalidator.h>
00033 #include <qregexp.h>
00034 #include <qlabel.h>
00035 
00036 //Other includes
00037 #include <iostream>
00038 using namespace std;
00039 
00040 
00041 /*! Main Constructor. */
00042 ArchiveStatisticsDialog::ArchiveStatisticsDialog(QWidget* parent, vector<NeuronGroup*> neurGrpVect) : QDialog(parent) {
00043         //Store neuron group vector
00044         neuronGrpVector = neurGrpVect;
00045 
00046         //Set up the graphical components of the dialog
00047         initialiseDialog();
00048 }
00049 
00050 
00051 /*! Constructor used when editing the archive statistics parameters. */
00052 ArchiveStatisticsDialog::ArchiveStatisticsDialog(QWidget* parent, vector<NeuronGroup*> neurGrpVect, ArchiveStatisticsHolder* archStatsHold) : QDialog(parent) {
00053         //Store neuron group vector
00054         neuronGrpVector = neurGrpVect;
00055 
00056         //Set up the graphical components of the dialog
00057         initialiseDialog();
00058 
00059         //Set the name of the archive statistics
00060         archStatsNameText->setText(archStatsHold->description);
00061         
00062         //If the archive statistics is a neuron group, set up the dialog appropriately.
00063         if(archStatsHold->archStatVector.size() == 1 && archStatsHold->archStatVector[0]->getType() == ArchiveStatistic::NEURON_GROUP){
00064                 //Top radio button should be on by default, so just have to set the correct location in the combo box.
00065                 unsigned int tmpNeurGrpID = ((NeuronGrpArchiveStatistic*)archStatsHold->archStatVector[0])->getNeuronGrpID();
00066                 for(int i=0; i < neuronGrpCombo->count(); ++i){
00067                         try{
00068                                 unsigned int comboNeurGrpID = Utilities::getNeuronGrpID(neuronGrpCombo->text(i));
00069                                 if(comboNeurGrpID == tmpNeurGrpID){
00070                                         neuronGrpCombo->setCurrentItem(i);
00071                                         return;
00072                                 }
00073                         }
00074                         catch(std::exception& er){// Catch-all for all std exceptions
00075                                 cerr<<"ArchiveStatisticsDialog: STD EXCEPTION \""<<er.what()<<"\""<<endl;
00076                                 QString errorString = "Exception thrown getting neuron group id: \"";
00077                                 errorString += er.what();
00078                                 errorString += "\"";
00079                                 QMessageBox::critical( 0, "NeuronGrpID Error", errorString);
00080                                 return;
00081                         }
00082                 }
00083                 //There is an error if we have reached this point
00084                 cerr<<"ArchiveStatisticsDialog: COULD NOT FIND NEURON GROUP ID "<<tmpNeurGrpID<<" IN COMBO BOX."<<endl;
00085                 QMessageBox::critical( 0, "NeuronGrpID Error", "Could not find neuron group ID");
00086                 return;
00087         }
00088         /* Otherwise, need to add the appropriate information to the text field, which can be 
00089                 extracted automatically from each class.*/
00090         else{
00091                 //Set the neuron id radio button on
00092                 neurIDRadioButt->setChecked(true);
00093                 neurIDText->setEnabled(true);
00094                 neuronGrpCombo->setEnabled(false);
00095 
00096                 //Add the strings to the text area.
00097                 QString neurIDStr = "";
00098                 for(vector<ArchiveStatistic*>::iterator iter = archStatsHold->archStatVector.begin(); iter != archStatsHold->archStatVector.end(); ++iter){
00099                         neurIDStr += (*iter)->toQString();
00100                         if((iter + 1) != archStatsHold->archStatVector.end())
00101                                 neurIDStr += ", ";
00102                 }
00103                 neurIDText->setText(neurIDStr);
00104         }
00105 }
00106 
00107 
00108 /*! Sets up the dialog. This is placed in a separate method because there are two
00109         different constructors. */
00110 void ArchiveStatisticsDialog::initialiseDialog(){
00111 
00112         //Set title of the dialog
00113         this->setCaption("Statistics");
00114 
00115         //Create vertical layout to organise widget
00116         QVBoxLayout *mainVerticalBox = new QVBoxLayout(this, 5, 10, "vertical1");
00117 
00118         //Add a dialog to get a desription of the statistic
00119         QRegExp regExp( "([0-9]|[A-Z]|[a-z]|_|\\s){1,50}" );
00120         QValidator* archStatsNameValidator = new QRegExpValidator(regExp, this);
00121         QHBoxLayout *archStatsNameBox = new QHBoxLayout();
00122         archStatsNameBox->addSpacing(10);
00123         archStatsNameBox->addWidget(new QLabel("Name", this));
00124         archStatsNameText = new QLineEdit("UNTITLED", this);
00125         archStatsNameText->setValidator(archStatsNameValidator);
00126         archStatsNameBox->addWidget(archStatsNameText);
00127         archStatsNameBox->addSpacing(5);
00128         mainVerticalBox->addLayout(archStatsNameBox);
00129 
00130         //Set up radio buttons to choose between a neuron group or a list of neurons
00131         QButtonGroup* buttonGroup = new QButtonGroup();
00132         neurGrpRadioButt = new QRadioButton("Neuron group", this);
00133         neurGrpRadioButt->setChecked(true);
00134         connect (neurGrpRadioButt, SIGNAL(clicked()), this, SLOT(neurGrpRadioButtonClicked()));
00135         buttonGroup->insert(neurGrpRadioButt);
00136         mainVerticalBox->addWidget(neurGrpRadioButt);
00137 
00138         //Add combo to select neuron group
00139         QHBoxLayout* neurGrpBox = new QHBoxLayout();
00140         neuronGrpCombo = new QComboBox(this);
00141         for(vector<NeuronGroup*>::iterator iter = neuronGrpVector.begin(); iter != neuronGrpVector.end(); ++iter){
00142                 QString tmpNeurGrpName = (*iter)->name;
00143                 tmpNeurGrpName += " [";
00144                 tmpNeurGrpName += QString::number((*iter)->neuronGrpID);
00145                 tmpNeurGrpName += "]";
00146                 neuronGrpCombo->insertItem(tmpNeurGrpName);
00147         }
00148         neurGrpBox->addSpacing(10);
00149         neurGrpBox->addWidget(neuronGrpCombo);
00150         neurGrpBox->addStretch(5);
00151         mainVerticalBox->addLayout(neurGrpBox);
00152 
00153         //Add radio button to insert a list of neurons
00154         neurIDRadioButt = new QRadioButton("Neuron IDs", this);
00155         neurIDRadioButt->setChecked(false);
00156         connect (neurIDRadioButt, SIGNAL(clicked()), this, SLOT(neurIDRadioButtonClicked()));
00157         buttonGroup->insert(neurIDRadioButt);
00158         mainVerticalBox->addWidget(neurIDRadioButt);
00159         
00160         //Add text area to hold lists of neurons
00161         neurIDText = new QTextEdit(this);
00162         neurIDText->setTextFormat(Qt::PlainText);
00163         neurIDText->setEnabled(false);
00164         mainVerticalBox->addWidget(neurIDText);
00165 
00166         //Set up ok and cancel buttons
00167         QHBoxLayout *buttonBox = new QHBoxLayout();
00168         QPushButton* okButton = new QPushButton("Ok", this, "okButton");
00169         QPushButton* cancelButton = new QPushButton("Cancel", this, "cancelButton");    
00170         buttonBox->addWidget(okButton);
00171         buttonBox->addWidget(cancelButton);
00172         mainVerticalBox->addLayout(buttonBox);
00173         
00174         connect (okButton, SIGNAL(clicked()), this, SLOT(okButtonPressed()));
00175         connect (cancelButton, SIGNAL(clicked()), this, SLOT(cancelButtonPressed()));
00176 
00177         //Set dialog size
00178         this->resize(600, 400);
00179 }
00180 
00181 
00182 /*! Destructor. */
00183 ArchiveStatisticsDialog::~ArchiveStatisticsDialog(){
00184         #ifdef MEMORY_DEBUG
00185                 cout<<"DESTROYING ARCHIVE STATISTICS DIALOG"<<endl;
00186         #endif//MEMORY_DEBUG
00187 }
00188 
00189 
00190 //-----------------------------------------------------------------------------
00191 //----------------            PUBLIC METHODS            -----------------------
00192 //-----------------------------------------------------------------------------
00193 
00194 /*! Returns the archive statistics that have been created by the dialog. */
00195 ArchiveStatisticsHolder* ArchiveStatisticsDialog::getArchiveStatistics(){
00196         return archStatsHolder;
00197 }
00198 
00199 
00200 //-----------------------------------------------------------------------------
00201 //----------------             PRIVATE SLOTS            -----------------------
00202 //-----------------------------------------------------------------------------
00203 
00204 /*! Called when the cancel button is pressed and rejects the dialog. */
00205 void ArchiveStatisticsDialog::cancelButtonPressed(){
00206         this->reject();
00207 }
00208 
00209 
00210 /*! Called when the neuron group option is selected. */
00211 void ArchiveStatisticsDialog::neurGrpRadioButtonClicked(){
00212         neurIDText->setEnabled(false);
00213         neuronGrpCombo->setEnabled(true);
00214 }
00215 
00216 
00217 /*! Called when the neuron ID option is selected. */
00218 void ArchiveStatisticsDialog::neurIDRadioButtonClicked(){
00219         neurIDText->setEnabled(true);
00220         neuronGrpCombo->setEnabled(false);
00221 }
00222 
00223 
00224 /*! Called when the ok button is pressed. Either creates a single
00225         archive statistic to monitor the neuron group or a number of archive
00226         statistics to monitor each of the comma separated entries in the text
00227         area. */
00228 void ArchiveStatisticsDialog::okButtonPressed(){
00229         //Create an archive statistic holder, which will hold all of the archive statistics
00230         archStatsHolder = new ArchiveStatisticsHolder;
00231         archStatsHolder->firingNeuronCount = 0;
00232         archStatsHolder->firingNeuronTotal = 0;
00233 
00234         //Get the description of the statistical properties
00235         archStatsHolder->description = archStatsNameText->text().ascii();
00236 
00237         /* If the neuron group option has been selected, monitoring is simple and just
00238                 add the neuron group struct to the statistics structure.*/
00239         if(neurGrpRadioButt->isOn()){
00240                 try{
00241                         unsigned int selectedNeurGrpID = Utilities::getNeuronGrpID(neuronGrpCombo->currentText());
00242                         ArchiveStatistic* tmpArchStat = new NeuronGrpArchiveStatistic(&archStatsHolder->firingNeuronCount, &archStatsHolder->firingNeuronTotal, selectedNeurGrpID);
00243                         archStatsHolder->archStatVector.push_back(tmpArchStat);
00244                         this->accept();
00245                         return;
00246                 }
00247                 catch(std::exception& er){// Catch-all for all std exceptions
00248                         cerr<<"ArchiveStatisticsDialog: STD EXCEPTION \""<<er.what()<<"\""<<endl;
00249                         QString errorString = "Exception thrown getting neuron group id: \"";
00250                         errorString += er.what();
00251                         errorString += "\"";
00252                         QMessageBox::critical( 0, "NeuronGrpID Error", errorString);
00253                         this->reject();
00254                         return;
00255                 }
00256         }
00257 
00258 
00259         /* Otherwise need to validate the list of neuron ids that have been supplied.*/
00260         QString neurIDStr = neurIDText->text();
00261 
00262         //First get rid of all white space
00263         for(unsigned int i=0; i<neurIDStr.length(); ++i){
00264                 if(neurIDStr.at(i).isSpace()){
00265                         neurIDStr.remove(i, 1);
00266                         --i;
00267                 }
00268         }
00269         cout<<"STRIPPED STRING: "<<neurIDStr<<endl;
00270 
00271         //Convert to string list - the neuron id string should be comma separated.
00272         QStringList tempStringList = QStringList::split(",", neurIDStr);
00273 
00274 
00275         /* Need to check that each expression is valid and that each neuron id lies within
00276                 the ranges of the neuron groups. */
00277         int tmpIndex = 0;
00278         neuronIDError = false;
00279         for(unsigned int i=0; i<tempStringList.size(); ++i){
00280                 if((tmpIndex = tempStringList[i].contains('&'))){
00281                         unsigned int firstNeuronID = checkNeuronID(tempStringList[i].section('&', 0, 0));
00282                         unsigned int secondNeuronID = checkNeuronID(tempStringList[i].section('&', -1, -1));
00283                         ArchiveStatistic* tmpArchStat = new AndArchiveStatistic(&archStatsHolder->firingNeuronCount, &archStatsHolder->firingNeuronTotal, firstNeuronID, secondNeuronID);
00284                         archStatsHolder->archStatVector.push_back(tmpArchStat);
00285                 }
00286                 else if((tmpIndex = tempStringList[i].contains('|'))){
00287                         unsigned int firstNeuronID = checkNeuronID(tempStringList[i].section('|', 0, 0));
00288                         unsigned int secondNeuronID = checkNeuronID(tempStringList[i].section('|', -1, -1));
00289                         ArchiveStatistic* tmpArchStat = new OrArchiveStatistic(&archStatsHolder->firingNeuronCount, &archStatsHolder->firingNeuronTotal, firstNeuronID, secondNeuronID);
00290                         archStatsHolder->archStatVector.push_back(tmpArchStat);
00291                 }
00292                 else if((tmpIndex = tempStringList[i].contains('-'))){
00293                         unsigned int firstNeuronID = checkNeuronID(tempStringList[i].section('-', 0, 0));
00294                         unsigned int secondNeuronID = checkNeuronID(tempStringList[i].section('-', -1, -1));
00295                         ArchiveStatistic* tmpArchStat = new RangeArchiveStatistic(&archStatsHolder->firingNeuronCount, &archStatsHolder->firingNeuronTotal, firstNeuronID, secondNeuronID);
00296                         archStatsHolder->archStatVector.push_back(tmpArchStat);
00297                 }
00298                 else {
00299                         unsigned int neuronID = checkNeuronID(tempStringList[i]);
00300                         ArchiveStatistic* tmpArchStat = new NeuronIDArchiveStatistic(&archStatsHolder->firingNeuronCount, &archStatsHolder->firingNeuronTotal, neuronID);
00301                         archStatsHolder->archStatVector.push_back(tmpArchStat);
00302                 }
00303         }
00304         if(neuronIDError){
00305                 QMessageBox::critical( 0, "Neuron ID Error", "Neuron ID information is incorrectly formatted or does not match the available neuron groups.");
00306                 return;
00307         }
00308 
00309         this->accept();
00310 }
00311 
00312 
00313 /*! Checks to see that neuron id string is valid and lies within the range of one of the
00314         available neuron groups. */
00315 unsigned int ArchiveStatisticsDialog::checkNeuronID(QString idStr){
00316         //Check that the string converts to an appropriate integer
00317         unsigned int neuronID = idStr.toUInt();
00318         if(neuronID == 0){
00319                 neuronIDError = true;
00320                 cerr<<"Malformed neuron ID string: "<<idStr<<endl;
00321                 return 0;
00322         }
00323 
00324         //Check that the neuron id lies within the range of one of the neuron groups
00325         for(vector<NeuronGroup*>::iterator iter = neuronGrpVector.begin(); iter != neuronGrpVector.end(); ++iter){
00326                 if( neuronID >= (*iter)->startNeuronID  &&  neuronID < ( (*iter)->startNeuronID  + ((*iter)->width * (*iter)->length) ) ){
00327                         return neuronID;
00328                 }
00329         }
00330 
00331         //If we have reached this point we have not found a neuron group with the appropriate range for the id
00332         neuronIDError = true;
00333         cerr<<"Neuron ID does not lie within the range of any of the available neuron groups: "<<neuronID<<endl;
00334         return 0;
00335 }
00336 

Generated on Mon Sep 3 22:29:04 2007 for SpikeStream Application by  doxygen 1.4.4