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