evodataviewer.cpp
1 /********************************************************************************
2  * FARSA Experiments Library *
3  * Copyright (C) 2007-2012 *
4  * Stefano Nolfi <stefano.nolfi@istc.cnr.it> *
5  * Onofrio Gigliotta <onofrio.gigliotta@istc.cnr.it> *
6  * Gianluca Massera <emmegian@yahoo.it> *
7  * Tomassino Ferrauto <tomassino.ferrauto@istc.cnr.it> *
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  * This program is distributed in the hope that it will be useful, *
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
17  * GNU General Public License for more details. *
18  * *
19  * You should have received a copy of the GNU General Public License *
20  * along with this program; if not, write to the Free Software *
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *
22  ********************************************************************************/
23 
24 #include "evodataviewer.h"
25 
26 #include <QPainter>
27 #include <QPen>
28 #include <QPaintEvent>
29 #include <QApplication>
30 #include <QScrollArea>
31 #include <QDebug>
32 #include <QStringList>
33 #include <QtGui>
34 #include <QtAlgorithms>
35 #include <configurationparameters.h>
36 #include "logger.h"
37 
38 namespace farsa {
39 
41 EvoDataViewer::EvoDataViewer(int nchunks, int chunksize, int style, QWidget* parent, Qt::WindowFlags flags) :
42  QWidget(parent,flags)
43 {
44  //to do: put this stuff within a method
45  this->style=style;
46  panning_width=4;
47  label_width=100;
48  this->setMaximumWidth(chunksize+label_width);
49  this->setMinimumWidth(label_width*2);
50  this->setMinimumHeight(10*nchunks);
51  this->nviewChange=false;
52  vchunks=new int[nchunks];
53 
54  this->setAttribute(Qt::WA_OpaquePaintEvent, true);
55 
56  qpixmap = new QPixmap(width(), height());
57 
58  //initialiazing datachunks
59  this->nchunks = nchunks;
60  this->chunksize = chunksize;
61  this->nvchunks=nchunks;
62 
63  dataChunks = new DataChunk*[nchunks];
64  for(int i=0;i<nchunks;i++)
65  {
66  dataChunks[i] = new DataChunk(QString("chunk"),QColor(255,0,0),chunksize, true);
67  }
68 
69  stepChunk=new DataChunk(QString("step"),QColor(255,0,0),chunksize, false);
70 
71  this->setChunkLabel(0,"Input");
72 
73  this->listVisibleChunks();
74 
75  qtimer=new QTimer(this);
76  qtimer->setInterval(4000);
77  QObject::connect(qtimer,SIGNAL(timeout()),this,SLOT(pickUnvisible()));
78 
79  elw=NULL;
80 
81 
82  pickY = 0;
83  pickX = 0;
84  pickValueVisible = false;
85 
86 }
87 EvoDataViewer::~EvoDataViewer()
88 {
89  for(int i=0;i<nchunks;i++) {
90  delete dataChunks[i];
91  }
92  delete[] dataChunks;
93 
94  delete stepChunk;
95 
96  delete qpixmap;
97  delete elw;
98 }
99 
101 void EvoDataViewer::evoDataPaint()
102 {
103  //draws background and labels and axes
104  QPainter painter(qpixmap);
105  QPen pen(Qt::black, 1);
106  QPen pen2(Qt::lightGray);
107  QPen pen3(Qt::darkGray);
108  painter.setPen(pen);
109  int hh;
110 
111  painter.fillRect(0,0,width(),height(),Qt::white);
112 
113  for(int i=0;i<nvchunks+1;i++)
114  {
115 
116  painter.setPen(pen);
117  if (i<nvchunks)
118  {
119  painter.drawText(4,(int)(vertical_step*(i+1)-vertical_step/2.0),dataChunks[vchunks[i]]->getLabel());
120  painter.drawText(label_width-40,(int)(vertical_step*(i+1))-4,QString::number(dataChunks[vchunks[i]]->getRangeMin()));
121  painter.drawText(label_width-40,(int)(vertical_step*(i+1))-4-(int)(vertical_step-20),QString::number(dataChunks[vchunks[i]]->getRangeMax()));
122  }
123  //drawing range
124 
125  painter.drawLine(0,(int)(vertical_step*i),width(),(int)(vertical_step*i));
126 
127  painter.setPen(pen3);
128  painter.drawLine(0,(int)(vertical_step*i+1),width(),(int)(vertical_step*i+1));
129 
130  painter.setPen(pen2);
131  painter.drawLine(0,(int)(vertical_step*i+2),width(),(int)(vertical_step*i+2));
132  // painter.drawLine(50,50,400,400);
133  //painter.drawText(4,(int)(vertical_step*i),dataChunks[i]->
134 
135  }
136 
137  hh=(int)(vertical_step*(nvchunks));
138  painter.setPen(pen);
139 
140  painter.drawLine(label_width-1,0,label_width-1,hh);
141  painter.setPen(pen2);
142 
143  painter.drawLine(label_width,0,label_width,hh);
144  painter.drawLine(label_width-2,0,label_width-2,hh);
145 }
146 
148 void EvoDataViewer::updateGraphic(int ch)
149 {
150  if (nviewChange) {
151  reset();
152  nviewChange = false;
153  }
154 
155  if (!dataChunks[ch]->isVisible()) {
156  // If the chunk is not visible, we have nothing to do
157  return;
158  }
159 
160  QPainter painter(qpixmap);
161  const QPen pen(Qt::red);
162  const QPen penw(Qt::white);
163  const QPen leadpen(Qt::black);
164 
165  // Computing the index of the chunk excluding invisible ones
166  int i = 0;
167  for (int ii = 0; ii < ch; ii++) {
168  if (dataChunks[ii]->isVisible()) {
169  i++;
170  }
171  }
172 
173  int actualindex = -1;
174  int predindex;
175 
176  if(dataChunks[i]->getIndex() > -1) {
177  actualindex=(int)(dataChunks[vchunks[i]]->getIndex()*dataChunks[vchunks[i]]->getDPRatio());
178  predindex=(int)((dataChunks[vchunks[i]]->getIndex()-1)*dataChunks[vchunks[i]]->getDPRatio());
179  painter.setPen(pen);
180 
181  QPen personalpen(dataChunks[vchunks[i]]->getColor());
182  painter.setPen(personalpen);
183 
185  int zeropoint=(int)((vertical_step-panning_width-1)*dataChunks[vchunks[i]]->getZeroValue());
186 
187  if (style == 0) {
188  painter.drawLine(actualindex+label_width,(int)(vertical_step*(i+1)-1)-zeropoint,actualindex+label_width,(int)(vertical_step*(i+1)-1)-zeropoint-(int)((dataChunks[vchunks[i]]->getValueToDraw()-dataChunks[vchunks[i]]->getZeroValue())*(vertical_step-panning_width)));
189  } else if (style == 1) {
190  painter.drawLine(actualindex+label_width,(int)(vertical_step*(i+1)-1)-zeropoint-(int)((dataChunks[vchunks[i]]->getValueToDraw()-dataChunks[vchunks[i]]->getZeroValue())*(vertical_step-panning_width)),predindex+label_width,(int)(vertical_step*(i+1)-1)-zeropoint-(int)((dataChunks[vchunks[i]]->getValue(dataChunks[vchunks[i]]->getIndex()-1)-dataChunks[vchunks[i]]->getZeroValue())*(vertical_step-panning_width)));
191  }
192 
193  }
194 
195  //white line
196  painter.setPen(penw);
197  painter.drawLine(actualindex+label_width+1,(int)(vertical_step*(i+1)-1),actualindex+label_width+1,(int)(vertical_step*(i+1)-1)-(int)(vertical_step-panning_width));
198 
199  //lead line
200  painter.setPen(leadpen);
201  painter.drawLine(actualindex+label_width+2,(int)(vertical_step*(i+1)-1),actualindex+label_width+2,(int)(vertical_step*(i+1)-1)-(int)(vertical_step-panning_width));
202 }
203 
204 void EvoDataViewer::resizeEvent(QResizeEvent *evt)
205 {
206 
207  evt->accept();
208  if (qpixmap!=NULL) delete qpixmap;
209  qpixmap=new QPixmap(width(), height());
210  reset();
211 }
212 
213 void EvoDataViewer::paintEvent(QPaintEvent *evt)
214 {
215  evt->accept();
216  int offx,offy;
217  offx=0;
218  offy=0;
219  if (pickY<20) offy=20-pickY;
220  if ((width()-pickX)<50) offx=-60;
221 
222  QPainter painter(this);
223  painter.drawPixmap(0, 0, width(), height(), *qpixmap);
224  if(pickValueVisible)
225  {
226  QPen bpen(Qt::black);
227  painter.drawText(pickX+offx,pickY+offy,QString("Val : ")+QString::number(pickValue));
228  painter.drawText(pickX+offx,pickY+10+offy,QString("Step: ")+QString::number(pickStep));
229  }
230 }
231 
233 void EvoDataViewer::setChunkLabel(int ch, const QString &label)
234 {
235  dataChunks[ch]->setLabel(label);
236 }
237 
239 void EvoDataViewer::setChunkValue(int ch, double value)
240 {
241  if ((ch >= 0) && (ch < this->nchunks)) {
242  dataChunks[ch]->setData(value);
243  updateGraphic(ch);
244  }
245 }
246 
248 bool EvoDataViewer::setChunkValue(const QString& name, double value)
249 {
250 
251  for(int i=0;i<nchunks;i++)
252  {
253  if(name == dataChunks[i]->getLabel())
254  {
255  setChunkValue(i, value);
256  return true;
257  }
258  }
259  return false;
260 }
261 
262 
264 void EvoDataViewer::setChunkRange(int ch, double mn, double mx)
265 {
266  dataChunks[ch]->setRange(mn, mx);
267 }
268 
269 void EvoDataViewer::mousePressEvent(QMouseEvent* evt)
270 {
271  //
272  if(evt->button()==Qt::LeftButton)
273  {
274  int xc = evt->x();
275  int yc = evt->y();
276  int nochunk = ((float)yc/vertical_step);
277  if (nochunk >= nvchunks) {
278  return;
279  }
280  int chunkIndex = xc-label_width;
281  float val=dataChunks[vchunks[nochunk]]->getValue((int)((float)chunkIndex/dataChunks[vchunks[nochunk]]->getDPRatio()));
282  val = dataChunks[vchunks[nochunk]]->linearMap(val,0.0, 1.0,dataChunks[vchunks[nochunk]]->getRangeMin(), dataChunks[vchunks[nochunk]]->getRangeMax());
283 
284 
285  pickX=xc;
286  pickY=yc;
287  pickValue=val;
288  pickStep = (int)stepChunk->getValue((int)((float)chunkIndex/dataChunks[vchunks[nochunk]]->getDPRatio()));
289  pickValueVisible=true;
290  qtimer->start();
291 
292  update();
293  }
294 
295  if(evt->button()==Qt::RightButton)
296  {
297  if(elw==NULL)
298  elw = new EvoListViewer (this->dataChunks,this->nchunks, &this->nviewChange);
299 
300  else
301  {
302  elw->restoreSelected();
303  elw->setVisible(true);
304  }
305  }
306 
307 
308 }
310 void EvoDataViewer::pickUnvisible()
311 {
312  pickValueVisible=false;
313  qtimer->stop();
314  update();
315 }
316 
321 {
322  stepChunk->setDataRaw(step);
323 
324 }
326 void EvoDataViewer::setStyle(int style)
327 {
328  switch (style)
329  {
330  case 0:
331  style=0;
332  break;
333  case 1:
334  style=1;
335  break;
336  default:
337  style=1;
338  break;
339 
340  }
341 
342 }
343 int EvoDataViewer::visibleChunks()
344 {
345  int vchunks=0;
346  for(int i=0;i<nchunks;i++)
347  if(dataChunks[i]->isVisible())
348  vchunks++;
349  nvchunks=vchunks;
350  return vchunks;
351 }
352 
355 {
356  int vi=0;
357  for(int i=0;i<this->nchunks;i++)
358  {
359  if (dataChunks[i]->isVisible())
360  {
361  this->vchunks[vi]=i;
362  vi++;
363  }
364 
365  }
366  this->nvchunks=vi;
367  vertical_step=height()/(double)nvchunks;
368 }
369 
370 void EvoDataViewer::setChunkColor(int ch, QColor color)
371 {
372  dataChunks[ch]->setColor(color);
373 }
375 void EvoDataViewer::setChunkProperties(int ch, double rangeMin, double rangeMax, const QString &label, QColor color, bool visible)
376 {
377  dataChunks[ch]->setRange(rangeMin, rangeMax);
378  dataChunks[ch]->setLabel(label);
379  dataChunks[ch]->setColor(color);
380  dataChunks[ch]->setVisible(visible);
381 
382 }
385 {
386  this->listVisibleChunks();
387  vertical_step=height()/(double)nvchunks;
388  //
389  for(int i=0;i<nchunks;i++)
390  {
391  //dataChunks[i]->setDSize(width()-label_width);
392  dataChunks[i]->setDPRatio((double)(width()-label_width)/(double)chunksize);
393  }
394 
395  evoDataPaint();
396 }
397 // DataChunk implementation -------------------------------------------------------------------------------------------------------
398 
399 DataChunk::DataChunk(const QString& label, const QColor& color, int size, bool visible)
400 {
401  this->label=label;
402  this->color=color;
403  this->size=size;
404  this->visible=visible;
405 
406  data= new double[size];
407  this->index=-1;
408  for(int i=0;i<size;i++)
409  data[i]=0;
410  //by default range is set between 0 and 1
411  min=0;
412  max=1;
413  zeroValue=0.0;
414  maxValue=-9999.00;
415 
416 
417 }
418 DataChunk::~DataChunk()
419 {
420  delete[] data;
421 }
422 
423 void DataChunk::setColor(QColor color)
424 {
425  this->color=color;
426 
427 }
428 
429 void DataChunk::setData(double value)
430 {
431  index++;
432 
433  data[index]=linearMap(value, min, max);
434  checkMaxValue(data[index]);
435  //index++;
436  if(index>size-2) index=-1;
437 
438 }
439 void DataChunk::setDataRaw(double value)
440 {
441  index++;
442  data[index]=value;
443  checkMaxValue(value);
444 
445  //index++;
446  if(index>size-2) index=-1;
447 }
448 void DataChunk::setDataRaw(int ind, double value)
449 {
450  if(ind>-1 && ind<size)
451  data[ind]=value;
452  checkMaxValue(value);
453 }
454 
455 void DataChunk::setLabel(const QString& label)
456 {
457  this->label=label;
458 }
459 
460 void DataChunk::setRange(double min, double max)
461 {
462  this->min=min;
463  this->max=max;
464  zeroValue=linearMap(0.0,min,max);
465 }
466 
467 void DataChunk::setStyle(int style)
468 {
469  this->style = style;
470 
471 }
472 const QString& DataChunk::getLabel()
473 {
474 
475  return this->label;
476 }
477 
478 
479 double DataChunk::getValueToDraw()
480 {
481  return data[index];
482 }
483 
484 int DataChunk::getIndex()
485 {
486  return index;
487 
488 }
489 double DataChunk::linearMap(double x, double rmin, double rmax, double outMin, double outMax)
490 {
491  //Reusing here Gianluca Masssera's code.
492  double m = ( outMax-outMin )/( rmax-rmin );
493  double q = outMin - m*rmin;
494  double ret = m*x+q;
495  if (ret < outMin) return outMin;
496  if (ret > outMax) return outMax;
497  return ret;
498 
499 
500 }
501 
502 double DataChunk::getRangeMin()
503 {
504  return min;
505 }
506 
507 
508 double DataChunk::getRangeMax()
509 {
510  return max;
511 }
512 
513 double DataChunk::getZeroValue()
514 {
515  return zeroValue;
516 }
517 
518 void DataChunk::setDPRatio(double val)
519 {
520  dpratio=val;
521  this->index=-1;
522 }
523 
524 double DataChunk::getDPRatio()
525 {
526  return dpratio;
527 }
528 
529 double DataChunk::getValue(int ind)
530 {
531  return data[ind];
532 }
533 
534 bool DataChunk::isVisible()
535 {
536  return visible;
537 }
538 
539 void DataChunk::setVisible(bool vis)
540 {
541  visible=vis;
542 }
543 QColor& DataChunk::getColor()
544 {
545  return color;
546 }
547 double DataChunk::getMaxValue()
548 {
549  return maxValue;
550 }
551 
552 namespace __DataChunk_loadRawData_helpers {
553  // This has been copied from Factory::orderByNumberAfterColon. Perhaps we could put this function into an utility
554  // library, instead of copying it around...
555  bool orderByNumberAfterColon(const QString& s1, const QString& s2)
556  {
557  // If a string doesn't contain any colon, it always follows the other string; this way strings without colons are always
558  // at the end when sorting
559  QStringList list = s1.split(':', QString::SkipEmptyParts);
560  if (list.size() < 2) {
561  return false;
562  }
563  const double ns1 = list[1].toDouble();
564  list = s2.split(':', QString::SkipEmptyParts);
565  if (list.size() < 2) {
566  return true;
567  }
568  const double ns2 = list[1].toDouble();
569 
570  return (ns1 < ns2);
571  }
572 }
573 void DataChunk::checkMaxValue(double val)
574 {
575  if(val>maxValue) maxValue=val;
576 }
577 bool DataChunk::loadRawData(const QString &filename, int column)
578 {
579  // Tomassino: this is really ugly, but I have no better (and quick to implement) idea for the moment
580  if (filename.endsWith(".fit", Qt::CaseInsensitive)) {
581  index = 0;
582  QFile file(filename);
583  QString line;
584  if(file.open(QIODevice::ReadOnly)) {
585  QTextStream in(&file);
586  line = in.readLine();
587 
588  while(!line.isNull()) {
589  //process line
590  QStringList list;
591  list = line.split(" ");
592  if (column<0 && column>=list.size()) {
593  Logger::error(QString("column number %1 does not exist in the loaded file.").arg(column));
594  return false;
595  }
596 
597  QString value=(QString)list.at(column);
598  setDataRaw(index, value.toDouble());
599  index++;
600 
601  line=in.readLine();
602  }
603  file.close();
604 
605  return true;
606  }
607  } else {
608  // Trying to load using ConfigurationParameters
609  farsa::ConfigurationParameters params(true);
610 
611  if (!params.loadParameters(filename)) {
612  return false;
613  }
614 
615  // Getting the parameter name corresponding to the given column
616  QString paramName;
617  switch (column) {
618  case 0:
619  paramName = "bestFitness";
620  break;
621  case 1:
622  paramName = "averageFitness";
623  break;
624  case 2:
625  paramName = "worstFitness";
626  break;
627  default:
628  paramName = "Unknown";
629  break;
630  }
631 
632  // Here we look for all the groups named GENOTYPES:<number> and read some parameters from each
633  QStringList genotypes = params.getGroupsWithPrefixList("/", "GENOTYPES:");
634 
635  qSort(genotypes.begin(), genotypes.end(), __DataChunk_loadRawData_helpers::orderByNumberAfterColon);
636  index = 0;
637  for (int i = 0; i < genotypes.size(); i++) {
638  setDataRaw(index, params.getValue(genotypes[i] + farsa::ConfigurationParameters::GroupSeparator() + paramName).toDouble());
639  index++;
640  }
641 
642  return true;
643  }
644 
645  //use the return value to give feedback instead of standard output
646  return false;
647 }
648 
649 
650 
651 // implementing EvoListViewer -----------------------------------------------------------------------------------------------------
652 
653 EvoListViewer::EvoListViewer(DataChunk **dataChunks, int n, bool *nviewChange , QWidget *parent) :
654  QWidget(parent)
655 {
656  this->dataChunks=dataChunks;
657  this->nchunks=n;
658  this->nvchange=nviewChange;
659  QListWidgetItem *listItem;
660 
661 
662  layout=new QGridLayout();
663  listwidget = new QListWidget();
664  deselectAll = new QPushButton("deselect all");
665  QPushButton *bcancel = new QPushButton("cancel");
666  QPushButton *bok = new QPushButton("ok");
667  for(int i=0;i<n;i++)
668  {
669  //listwidget->insertItem(i,dataChunks[i]->getLabel());
670  listwidget->insertItem(i, new QListWidgetItem());
671 
672  listItem=listwidget->item(i);
673  listItem->setText(dataChunks[i]->getLabel());
674  Qt::ItemFlags mflags;
675  mflags= Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
676  listItem->setFlags(mflags);
677  listItem->setCheckState(Qt::Checked);
678  }
679 
680  //listwidget.insertItem(3,"terzo");
681 
682 
683  layout->addWidget(deselectAll, 0,0);
684  layout->addWidget(listwidget,1,0);
685  layout->addWidget(bcancel,2,0);
686  layout->addWidget(bok,3,0);
687 
688 
689 
690  this->setLayout(layout);
691  this->setWindowTitle("Chunks List");
692 
693  this->setGeometry(50,50,250,300);
694  this->setVisible(true);
695 
696  //QObject::connect(qtimer,SIGNAL(timeout()),this,SLOT(pickUnvisible()));
697  QObject::connect(bok,SIGNAL(clicked()),this,SLOT(okSelected()));
698  QObject::connect(bcancel,SIGNAL(clicked()),this,SLOT(restoreSelected()));
699  QObject::connect(deselectAll, SIGNAL(clicked()),this,SLOT(allOnOrAllOff()));
700 
701  //setting up the gui
702 
703 
704 
705 
706 
707 }
708 
709 void EvoListViewer::okSelected()
710 {
711  for(int i=0;i<nchunks;i++)
712  {
713  if(this->listwidget->item(i)->checkState()== Qt::Checked)
714  dataChunks[i]->setVisible(true);
715  else
716  dataChunks[i]->setVisible(false);
717  }
718  this->setVisible(false);
719  *nvchange=true;
720 }
721 
722 void EvoListViewer::restoreSelected()
723 {
724  //reset choices
725  this->setVisible(false);
726  for(int i=0;i<nchunks;i++)
727  {
728  if(dataChunks[i]->isVisible())
729  this->listwidget->item(i)->setCheckState(Qt::Checked);
730  else
731  this->listwidget->item(i)->setCheckState(Qt::Unchecked);
732 
733 
734  }
735 }
736 
737 void EvoListViewer::allOnOrAllOff()
738 {
739  bool someoneIsChecked = false;
740  for(int i=0;i<nchunks;i++) //check if there are checked items
741  {
742  if(listwidget->item(i)->checkState() == Qt::Checked)
743  someoneIsChecked = true;
744  }
745 
746  bool select;
747  if(someoneIsChecked) //some item(s) is checked
748  {
749  select = false;
750  deselectAll->setText("select all");
751  }
752  else //there are no checked items
753  {
754  select = true;
755  deselectAll->setText("deselect all");
756  }
757 
758  for(int i=0;i<nchunks;i++)
759  {
760  if(select)
761  this->listwidget->item(i)->setCheckState(Qt::Checked);
762  else
763  this->listwidget->item(i)->setCheckState(Qt::Unchecked);
764  }
765 }
766 
767 /*
768 void EvoListViewer::resizeEvent(QResizeEvent *evt)
769 {
770  //layout->
771 }
772 */
773 
774 EvoListViewer::~EvoListViewer()
775 {
776  delete listwidget;
777  delete layout;
778 
779 
780 }
781 
782 //___________________ FitViewer
783 
784 void FitViewer::setValues(int gen, double min, double average, double max)
785 {
786 
787  fitVal[gen][0]=min;
788  fitVal[gen][1]=average;
789  fitVal[gen][2]=max;
790  currentGen=gen;
791 
792  //checking minimum and maximum
793  //if (min<vmin) vmin=min;
794  //if (max>vmax) vmax=max;
795  checkGraphRange(min);
796  checkGraphRange(average);
797  checkGraphRange(max);
798 
799 
800 
801 }
802 int FitViewer::checkGraphRange(double val)
803 {
804  int ret=0;
805  if (val<vmin)
806  {
807  vmin=val;
808  ret++;
809  }
810  if (val>vmax)
811  {
812  vmax=val;
813  ret++;
814  }
815  return ret;
816 }
817 
818 void FitViewer::checkChunkRange(int chunk)
819 {
820  //for(int i=0;i<nchunks;i++)
821  for(int c=0;c<=currentGen;c++)
822  checkGraphRange(dataChunks[chunk]->getValue(c));
823 }
824 
825 FitViewer::FitViewer( QWidget* parent, Qt::WindowFlags flags ) : QWidget( parent, flags )
826 {
827 
828  padding=50;
829  reset();
830 
831  sortedIndex = NULL;
832  dataChunks = NULL;
833 }
834 
835 FitViewer::FitViewer(int nchunks, int chunksize, QWidget* parent, Qt::WindowFlags flags) : QWidget( parent, flags )
836 {
837 
838  padding=100;
839  reset();
840  this->nchunks=nchunks;
841  this->chunksize=chunksize;
842  currentGen=0;
843  sortedIndex=new int[nchunks];
844  dataChunks = new DataChunk*[nchunks];
845  for(int i=0;i<nchunks;i++) {
846  dataChunks[i] = new DataChunk(QString("chunk"),QColor(255,0,0),chunksize, true);
847  sortedIndex[i]=i;
848  }
849 }
850 
851 FitViewer::~FitViewer()
852 {
853  delete[] sortedIndex;
854  if (dataChunks != NULL) {
855  for (int i = 0; i < nchunks; i++) {
856  delete dataChunks[i];
857  }
858  delete[] dataChunks;
859  }
860 }
861 
862 void FitViewer::paintEvent(QPaintEvent* /*evt*/)
863 {
864  QPainter painter(this);
865  QPen blackPen(Qt::black);
866  QPen bluePen(Qt::blue);
867  QPen greenPen(Qt::green);
868  QPen redPen(Qt::red);
869  int xt,yt;
870 
871  painter.fillRect(0,0,width(),height(),Qt::white);
872  painter.setPen(blackPen);
873  painter.setRenderHint(QPainter::Antialiasing, false);
874  xstep=(double)(width()-2*padding)/(double)(currentGen);
875  wyaxes=height()-2*padding;
876 
877  painter.drawRect(padding,padding,width()-2*padding,height()-2*padding);
878  if (vmin>0) zeroy=height()-padding;
879  else
880  {
881  zeroy=((-1*vmin)/(vmax-vmin))*wyaxes;
882  }
883 
884  painter.drawLine(padding,height()-padding-zeroy,width()-padding,height()-padding-zeroy);
885  painter.drawText(padding/2.0,padding,QString::number(vmax));
886  painter.drawText(padding/2.0,height()-padding,QString::number(vmin));
887  painter.drawText(padding/2.0,height()-padding-zeroy,QString::number(0));
888 
889  //drawing zero axes
890  painter.drawText(width()-padding,height()-padding-zeroy,QString::number(currentGen));
891 
892  //graph title
893  painter.drawText(width()/2.0-padding,padding/2.0,gtitle);
894 
895  //drawing xlabel
896  painter.drawText(width()/2.0-padding,height()-padding/2.0,xlabel);
897 
898  //drawing ylabel
899  xt=padding/4.0;
900  yt=height()/2.0;
901  painter.save();
902  painter.translate(xt,yt);
903  painter.rotate(-90.0);
904  painter.drawText(0,0,ylabel);
905  painter.restore();
906 
907 
908  /*
909  painter.setPen(bluePen);
910  painter.drawText(width()/2.0,padding/4.0*3,"Minimum");
911  painter.setPen(greenPen);
912  painter.drawText(width()/2.0,padding/4.0*2,"Average");
913  painter.setPen(redPen);
914  painter.drawText(width()/2.0,padding/4.0*1,"Maximum");
915  */
916 
917  painter.setRenderHint(QPainter::Antialiasing, true);
918  for (int dc=0;dc<nchunks;dc++)
919  {
920  int c=sortedIndex[dc];
921  painter.setPen(dataChunks[c]->getColor());
922  painter.drawText(width()-padding+2,padding+dc*20,dataChunks[c]->getLabel());
923 
924  for (int i=1;i<currentGen+1;i++)
925  {
926  /*
927  painter.setPen(bluePen);
928  painter.drawLine(padding+xstep*(i-1), height()-padding-getYnormValue(fitVal[i-1][0]),padding+xstep*i,height()-padding-getYnormValue(fitVal[i][0]));
929  painter.setPen(greenPen);
930  painter.drawLine(padding+xstep*(i-1), height()-padding-getYnormValue(fitVal[i-1][1]),padding+xstep*i,height()-padding-getYnormValue(fitVal[i][1]));
931  painter.setPen(redPen);
932  painter.drawLine(padding+xstep*(i-1), height()-padding-getYnormValue(fitVal[i-1][2]),padding+xstep*i,height()-padding-getYnormValue(fitVal[i][2]));
933  */
934 
935  checkGraphRange(dataChunks[c]->getValue(i-1));
936  painter.drawLine(padding+xstep*(i-1), height()-padding-getYnormValue(dataChunks[c]->getValue(i-1)),padding+xstep*i,height()-padding-getYnormValue(dataChunks[c]->getValue(i)));
937 
938 
939  }
940  }
941 
942 }
943 
944 double FitViewer::getYnormValue(double val)
945 {
946  if(vmin>0)
947  {
948  return (val/vmax)*wyaxes;
949  }
950  else
951  {
952 
953  return ((val-vmin)/(vmax-vmin))*wyaxes;
954 
955  }
956 }
957 
958 void FitViewer::setChunkLabel(int ch, const QString &label)
959 {
960 
961  dataChunks[ch]->setLabel(label);
962 }
963 void FitViewer::setChunkProperties(int ch, const QString &label, QColor color, bool visible)
964 {
965  dataChunks[ch]->setLabel(label);
966  dataChunks[ch]->setColor(color);
967  dataChunks[ch]->setVisible(visible);
968 }
969 
970 void FitViewer::setChunkValue(int ch,int ind, double value)
971 {
972  if (ch>= 0 && ch < this->nchunks)
973  {
974  dataChunks[ch]->setDataRaw(ind,value);
975  checkGraphRange(value);
976  }
977 }
978 
979 bool FitViewer::setChunkValue(const QString &name,int ind, double value)
980 {
981  for(int i=0;i<nchunks;i++)
982  {
983  if(name == dataChunks[i]->getLabel())
984  {
985  setChunkValue(i,ind, value);
986  checkGraphRange(value);
987  return true;
988  }
989  }
990  return false;
991 
992 }
993 void FitViewer::diplayUntilStep(int st)
994 {
995  currentGen=st;
996 }
997 
998 void FitViewer::setLabels(const QString &title, const QString &xlabel, const QString &ylabel)
999 {
1000  this->gtitle=title;
1001  this->xlabel=xlabel;
1002  this->ylabel=ylabel;
1003 }
1004 
1005 void FitViewer::reset()
1006 {
1007  vmin=-0.0;
1008  vmax=0.0;
1009  padding=90;
1010  setMinimumSize(padding*4,padding*4);
1011  currentGen=0;
1012 }
1013 
1014 bool FitViewer::loadRawData(int nchunk, const QString &filename, int column)
1015 {
1016  bool res;
1017  res=dataChunks[nchunk]->loadRawData(filename,column);
1018  if(res)
1019  {
1020  //currentGen=dataChunks[nchunk]->getIndex()-1;
1021  if((dataChunks[nchunk]->getIndex()-1)>currentGen) currentGen=dataChunks[nchunk]->getIndex()-1;
1022  }
1023  checkChunkRange(nchunk);
1024  return res;
1025 }
1026 
1027 int FitViewer::getCurrentGeneration()
1028 {
1029  return currentGen;
1030 }
1031 
1032 void FitViewer::sortchunks()
1033 {
1034  bool swap=true;
1035  for(int i=0;i<nchunks;i++)
1036  {
1037  sortedIndex[i]=i;
1038  }
1039 
1040  while (swap)
1041  {
1042  swap=false;
1043  int s;
1044  for(int i=0;i<nchunks-1;i++)
1045  {
1046  if (dataChunks[sortedIndex[i]]->getMaxValue()<dataChunks[sortedIndex[i+1]]->getMaxValue())
1047  {
1048  s=sortedIndex[i];
1049  sortedIndex[i]=sortedIndex[i+1];
1050  sortedIndex[i+1]=s;
1051  swap=true;
1052  }
1053  }
1054  }
1055 }
1056 
1057 } //end namespace farsa