Fixed text file permissions
[snark14.git] / tools / Display / displaywindow.cpp
1 /** @file displaywindow.cpp
2     @package snark14Display
3     @author Bruno M. Carvalho and Deniz Sarioz
4     licensed under (open-source) QPL v1.0
5     which accompanies this distribution in the file QPL
6         
7     modification: Joanna Klukowska 1/13/2009
8             added choice of grayScale display for plot
9             in addition to color display
10 */
11
12 #include "variables.hpp"
13 #include "verbosity.hpp"
14 #include "displaywidget.hpp"
15 #include "displaywindow.hpp"
16 #include "lines.hpp"
17 #include "line_real_t.hpp"
18 #include "plot_t.hpp"
19 #include "displaylines.hpp"
20
21 #include <iostream>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <math.h>
25 #include <qcolor.h>
26 #include <qfiledialog.h>
27 #include <qfont.h>
28 #include <qlabel.h>
29 #include <qlayout.h>
30 #include <qlineedit.h>
31 #include <qmessagebox.h>
32 #include <qpainter.h>
33 #include <qpalette.h>
34 #include <qpen.h>
35 #include <qpixmap.h>
36 #include <qpoint.h>
37 #include <qpushbutton.h>
38 #include <qslider.h>
39 #include <qstyle.h>
40 #include <qtooltip.h>
41 #include <qwhatsthis.h>
42 #include <qwidget.h>
43 #include <qregexp.h> 
44 #include <qscrollview.h>
45
46 #define EPSILON 0.00000001
47
48 #ifndef MIN
49 #define MIN(a, b) (((a < b) ? (a) : (b)))
50 #endif
51
52 // extern displaywindow **displaywindowset;
53 // QImage rec; // this needs to be an INSTANCE VARIABLE
54 // bool converted; // wouldn't hurt to make this an INSTANCE VARIABLE either (but it's unused??)
55
56 /* 
57  *  Constructs a displaywindow which is a child of 'parent', with the 
58  *  name 'name' and widget flags set to 'f' 
59  *
60  *  The dialog will by default be modeless, unless you set 'modal' to
61  *  TRUE to construct a modal dialog.
62  */
63 displaywindow::displaywindow( QWidget* parent, const char* name, bool modal, WFlags fl , DIGDataFormat dataformat, int imagenumber, int x, int y )
64   //    : QDialog( parent, name, modal, fl )
65   : QWidget(parent, name, fl)
66 {
67                       // -Qt::WStyle_Customize | Qt::WStyle_NoBorder
68 //    std::cerr << "++displaywindow constructor for imagenumber " << imagenumber << std::endl;
69     int i,j;
70     QPixmap disp;
71     recp = 0; // initialize
72     // double **phantomimage;
73     double **phantomimage;
74     QPoint topleft;
75     id=imagenumber;
76     //    displaywindowset[id]=this; // don't need this.
77     setName(imagetitles[id]);
78     imagename=QString(imagetitles[id]);
79     setCaption(imagetitles[id]);
80     //    displaywindowactive[id]=true;
81     status=false;
82     topleft.setX(x);
83     topleft.setY(y);
84     this->move(topleft);
85     imageset[imagenumber]->readImage(imagenumber,dataformat);
86     //printf("max=%f min=%f \n",imageset[imagenumber]->getMax(),imageset[imagenumber]->getMin());
87     if(imageset[imagenumber]->getMax() > globalmax) {
88       globalmax=imageset[imagenumber]->getMax();
89     }
90     if(imageset[imagenumber]->getMin() < globalmin) {
91       globalmin=imageset[imagenumber]->getMin();
92     }
93     maxzoom = 2 * maxSizex / Sizex;
94     if(maxzoom<=1) maxzoom = 2;
95     image = imageset[imagenumber]->getImage();
96     lowthreshold=minval=imageset[imagenumber]->getMin();
97     highthreshold=maxval=imageset[imagenumber]->getMax();
98     range=highthreshold-lowthreshold;
99     Range=highthreshold-lowthreshold;
100     if(phantomexists && id) { // (id) means "image number is not 0" (phantom must be 0)
101       diffimage=(double **)malloc(Sizey*sizeof(double *));
102       if (!diffimage) {
103         std::cerr << "Failed to allocate space for diffimage" << std::endl;
104       }
105       for(j=0;j<Sizey;j++) {
106         diffimage[j]=(double *)malloc(Sizex*sizeof(double));
107         if(!diffimage[j]) {
108           std::cerr << "Failed to allocate space for diffimage" << std::endl;
109         }
110       }  
111       if(!imageset[0]->isLoaded()) {
112         imageset[0]->readImage(0,dataformat);
113         if(imageset[0]->getMax()>globalmax)
114           globalmax=imageset[0]->getMax();
115         if(imageset[0]->getMin()<globalmin)
116           globalmin=imageset[0]->getMin();
117       }
118       phantomimage=imageset[0]->getImage();
119       diffminval=0;
120       diffmaxval=0;
121       for(i=0;i<Sizey;i++) {
122         for(j=0;j<Sizex;j++) {
123           diffimage[i][j]=image[i][j]-phantomimage[i][j];
124           if(diffimage[i][j]>diffmaxval)
125             diffmaxval=diffimage[i][j];
126           if(diffimage[i][j]<diffminval)
127             diffminval=diffimage[i][j];
128         }
129       }
130       if(diffmaxval > globaldiffmax) globaldiffmax = diffmaxval;
131       if(diffminval < globaldiffmin) globaldiffmin = diffminval;
132     }
133
134     int fudge = 105; // "dynamic" replacement of stuff
135     
136     setMinimumSize(200, 500); // good enough
137     //    setMinimumSize( QSize( 190 + MIN(Sizex, maxSizex) +10, 
138     //                     20 + MIN(Sizey,maxSizey) ) );
139     //    resize( QSize( 190+MIN(Sizex, maxSizex), 
140     //             20 + MIN(Sizey,maxSizey) ) ); // no point in this
141     // no maximum size!
142     if(recp) {
143       std::cerr << "Error: recp already assigned!" << std::endl;
144     }
145     recp = new QImage(Sizex,Sizey,8,256);
146     //    rec = QImage(Sizex,Sizey,8,256);
147     QImage& rec = (*recp);
148     for(i=0;i<256;i++)
149       rec.setColor(i,qRgb(i,i,i));
150     for(i=0;i<Sizey;i++)
151       for(j=0;j<Sizex;j++)
152         *(rec.scanLine(i)+j)=(unsigned char)(((image[i][j]-lowthreshold)/range)*255);
153
154     disp = QPixmap(Sizex,Sizey);
155     converted=disp.convertFromImage(rec,QPixmap::Auto);
156
157     //    displaywidget->setGeometry( QRect( 190, 10, Sizex, Sizey ) ); 
158     displaywidget = new displayWidget( this, "displaywidget" );
159     displaywidget->setBackgroundPixmap( disp );
160     //displaywidget->setScaledContents( TRUE );
161     QObject::connect(displaywidget,SIGNAL(clicked(int,int)),this,SLOT(updateClickedPixel(int,int)));
162     zoomlabel = new QLabel( this, "zoomlabel" );
163     zoomlabel->setGeometry( QRect( 65, 5, 45, 20 ) ); 
164     zoomlabel->setText( tr( "Zoom" ) );
165
166     zoomslider = new QSlider( this, "zoomslider" );
167     zoomslider->setGeometry( QRect( 5, 30, 175, 20 ) ); 
168     zoomslider->setOrientation( QSlider::Horizontal );
169     zoomslider->setRange(1,maxzoom);
170     zoomslider->setValue(1);
171     zoomslider->setLineStep(1);
172     zoomslider->setPageStep(2);
173     QObject::connect(zoomslider,SIGNAL(valueChanged(int)),this,SLOT(updateZoom()));
174     zoomval=1;
175
176     zoom = new QLineEdit( this, "zoom" );
177     zoom->setGeometry( QRect( 5, 55, 90, 30 ) ); 
178     zoom->setText("1");
179
180     setzoombutton = new QPushButton( this, "setzoombutton" );
181     setzoombutton->setGeometry( QRect( 95, 50, 90, 40 ) ); 
182     setzoombutton->setText( "Set Value" );
183     QObject::connect(setzoombutton,SIGNAL(clicked()),this,SLOT(updateZoomslider()));
184
185     lowthreshlabel = new QLabel( this, "lowthreshlabel" );
186     //    lowthreshlabel->setGeometry( QRect( 35, 205, 110, 20 ) ); 
187     lowthreshlabel->setGeometry( QRect( 35, 205 - fudge, 110, 20 ) ); 
188     lowthreshlabel->setText( tr( "Low Threshold" ) );
189
190     lowthreshslider = new QSlider( this, "Slider4_2" );
191     lowthreshslider->setGeometry( QRect( 5, 230 - fudge, 175, 20 ) ); 
192     lowthreshslider->setOrientation( QSlider::Horizontal );
193     lowthreshslider->setRange(0,1000000000);
194     lowthreshslider->setValue(0);
195     QObject::connect(lowthreshslider,SIGNAL(valueChanged(int)),this,SLOT(updateLowthresh()));
196
197     lowthresh = new QLineEdit( this, "lowthresh" );
198     lowthresh->setGeometry( QRect( 5, 260 - fudge, 90, 30 ) ); 
199     char s[12];     
200     sprintf(s,"%10.7f",minval);
201     lowthresh->setText(s);
202
203     setlowthreshbutton = new QPushButton( this, "setlowthreshbutton" );
204     setlowthreshbutton->setGeometry( QRect( 95, 255 - fudge, 90, 40 ) ); 
205     setlowthreshbutton->setText( tr( "Set Value" ) );
206     QObject::connect(setlowthreshbutton,SIGNAL(clicked()),this,SLOT(updateLowthreshslider()));
207
208     highthreshlabel = new QLabel( this, "highthreshlabel" );
209     highthreshlabel->setGeometry( QRect( 35, 300 - fudge, 115, 20 ) ); 
210     highthreshlabel->setText( tr( "High Threshold" ) );
211
212     highthreshslider = new QSlider( this, "Slider4_3" );
213     highthreshslider->setGeometry( QRect( 5, 325 -fudge, 175, 20 ) ); 
214     highthreshslider->setOrientation( QSlider::Horizontal );
215     highthreshslider->setRange(0,1000000000);
216     highthreshslider->setValue(1000000000);
217     QObject::connect(highthreshslider,SIGNAL(valueChanged(int)),this,SLOT(updateHighthresh()));
218
219     highthresh = new QLineEdit( this, "highthresh" );
220     highthresh->setGeometry( QRect( 5, 355 - fudge, 90, 30 ) ); 
221     sprintf(s,"%10.7f",maxval);
222     highthresh->setText(s);
223
224     sethighthreshbutton = new QPushButton( this, "sethighthreshbutton" );
225     sethighthreshbutton->setGeometry( QRect( 95, 350 - fudge , 90, 40 ) ); 
226     sethighthreshbutton->setText( tr( "Set Value" ) );
227     QObject::connect(sethighthreshbutton,SIGNAL(clicked()),this,SLOT(updateHighthreshslider()));
228
229     pixelposlabel = new QLabel( this, "pixelposlabel" );
230     pixelposlabel->setGeometry( QRect( 30, 395 - fudge, 45, 20 ) ); 
231     pixelposlabel->setText( tr( "Pixel" ) );
232
233     pixelpos = new QLineEdit( this, "pixelpos" );
234     pixelpos->setGeometry( QRect( 5, 420 - fudge, 80, 30 ) ); 
235
236     pixelvaluelabel = new QLabel( this, "pixelvaluelabel" );
237     pixelvaluelabel->setGeometry( QRect( 110, 395 - fudge, 45, 20 ) ); 
238     pixelvaluelabel->setText( tr( "Value" ) );
239
240     pixelvalue = new QLineEdit( this, "pixelvalue" );
241     pixelvalue->setGeometry( QRect( 90, 420 - fudge, 90, 30 ) );
242
243     savebutton = new QPushButton( this, "savebutton" );
244     savebutton->setGeometry( QRect( 15, 460 - fudge, 150, 40 ) ); 
245     savebutton->setText( tr( "Save Image" ) );
246     QObject::connect(savebutton,SIGNAL(clicked()),this,SLOT(saveImage()));
247
248     linesbutton = new QPushButton( this, "linesbutton" );
249     linesbutton->setGeometry( QRect( 15, 505 - fudge, 150, 40 ) ); 
250     linesbutton->setText( tr( "Display Lines" ) );
251     QObject::connect(linesbutton,SIGNAL(clicked()),this,SLOT(callLines()));
252
253     closebutton = new QPushButton( this, "closebutton" );
254     closebutton->setGeometry( QRect( 15, 550 - fudge, 150, 40 ) ); 
255     closebutton->setText( tr( "Close Window" ) );
256     QObject::connect(closebutton,SIGNAL(clicked()),this,SLOT(closeWindow()));
257
258     scrollv = new QScrollView(this, "qscrollview", Qt::WStyle_Customize | Qt::WStyle_NoBorder );
259     scrollv->viewport()->setBackgroundColor(colorGroup().background());
260     scrollv->setFrameShape(QFrame::NoFrame);
261     scrollv->setGeometry( 190, 10, maxSizex - 200, maxSizey - 100 );
262     scrollv->addChild(displaywidget);
263     useglobal = usedifference = useintensity = false;
264     //    resetImage();
265     // hide(); // don't need, not shown unless show() called
266 }  // --displaywindow ctor
267
268
269
270 /*  
271  *  Destroys the object and frees any allocated resources
272  */
273 displaywindow::~displaywindow()
274 {
275     // no need to delete child widgets, Qt does it all for us
276   displaywindowactive[id]=false;
277   //  delete displaywindowset[id]; // see if this will work?
278   //  displaywindowset[id]= 0; // NULL
279 }  // --displaywindow::~displaywindow()
280
281
282
283 /** non-destructive!  only hide the window, don't lose any information. */
284 void displaywindow::closeWindow()
285 {
286   displaywindowactive[id]=false;
287   hide();
288 }  // --displaywindow::closeWindow()
289
290
291
292 /** do the same thing as closing the window, don't self-destruct! */
293 void displaywindow::closeEvent(QCloseEvent * e)
294 {
295   closeWindow();
296 }  // --displaywindow::closeEvent()
297
298
299 void displaywindow::updateClickedPixel(int cx,int cy)
300 {
301   if(usedifference && !id) return;
302   int ix,iy;
303   char s[12];
304
305   ix=cx/zoomval;
306   iy=cy/zoomval;
307   //printf("pixel(%d,%d) image[%d][%d]=%f\n",cx,cy,iy,ix,image[iy][ix]);
308   sprintf(s,"(%d,%d)",ix,iy);
309   pixelpos->setText(s);
310   if(usedifference)
311     sprintf(s,"%10.7f",diffimage[iy][ix]);
312   else
313     sprintf(s,"%10.7f",image[iy][ix]);
314   pixelvalue->setText(s);
315 }  // --displaywindow::updateClickedPixel()
316
317
318
319 void displaywindow::updateZoom()
320 {
321   char s[12];
322   int v=zoomslider->value();
323   sprintf(s,"%d",v);
324   zoom->setText(s);
325   zoomval=v;
326   if(usedifference) {
327     if(id) resetDiffImage();
328     else {
329       resize(MIN(maxSizex, 200+(Sizex*zoomval)),
330          MIN(maxSizey, 20+(Sizey*zoomval)));
331       scrollv->resizeContents ( Sizex*zoomval + 10, Sizey*zoomval + 10 );      
332     }
333   } else {
334     resetImage();
335   }
336 }  // --displaywindow::updateZoom()
337
338
339
340 void displaywindow::updateZoomslider()
341 {
342   int v;
343   bool ok=false;
344   v=zoom->text().toInt(&ok,10);
345   if(ok && v>0 && v<=maxzoom) 
346     zoomslider->setValue(v);
347   else 
348     QMessageBox::information(this,"SnarkDisplay","Error!\n"
349                                   "Zoom value invalid or out of range.");
350   updateZoom();
351 }  // --displaywindow::updateZoomslider()
352
353
354 void displaywindow::setGlobal(bool on) {
355   useglobal = on;
356   //  globalthresholdbutton->setChecked( on );
357   lowthreshlabel->setEnabled(!on);
358   lowthreshslider->setEnabled(!on);
359   lowthresh->setEnabled(!on);
360   setlowthreshbutton->setEnabled(!on);
361   highthreshlabel->setEnabled(!on);
362   highthreshslider->setEnabled(!on);
363   highthresh->setEnabled(!on);
364   sethighthreshbutton->setEnabled(!on);
365   setDifference(usedifference); // hack!!! // we no like mutual recursion without base case
366 }  // --displaywindow::setGlobal()
367
368
369
370 void displaywindow::setDifference(bool on) {
371   usedifference = on;
372   //  differencebutton->setChecked( on );
373   if(usedifference && !id) return;
374   int l;
375   char s[12];
376   l=imagename.length();
377   if(usedifference) {
378     imagename.replace(l-3,1,"d");
379     setCaption(imagename);
380     if(!useglobal) {
381       //      lowthreshslider->setMinValue((int)(diffminval*1000000000));
382       //      lowthreshslider->setValue((int)(diffminval*1000000000));
383       lowthreshslider->setValue(0);
384       highthreshslider->setValue(1000000000);
385       lowthreshold=diffminval;
386       sprintf(s,"%10.7f",lowthreshold);
387       lowthresh->setText(s);
388       //      highthreshslider->setMaxValue((int)(diffmaxval*1000000000));
389       //      highthreshslider->setValue((int)(diffmaxval*1000000000));
390       highthreshold=diffmaxval;
391       sprintf(s,"%10.7f",highthreshold);
392       highthresh->setText(s);
393       range=diffmaxval-diffminval;
394       Range=diffmaxval-diffminval;
395     }
396     resetDiffImage();
397   }
398   else {
399     imagename.replace(l-3,1,"r");
400     setCaption(imagename);
401     if(!useglobal) {
402       //      lowthreshslider->setMinValue((int)(minval*1000000000));
403       //      lowthreshslider->setValue((int)(minval*1000000000));
404       lowthreshslider->setValue(0);
405       highthreshslider->setValue(1000000000);
406       lowthreshold=minval;
407       sprintf(s,"%10.7f",lowthreshold);
408       lowthresh->setText(s);
409       //      highthreshslider->setMaxValue((int)(maxval*1000000000));
410       //      highthreshslider->setValue((int)(maxval*1000000000));
411       highthreshold=maxval;
412       sprintf(s,"%10.7f",highthreshold);
413       highthresh->setText(s);
414       range=maxval-minval;
415       Range=maxval-minval;
416     }
417     resetImage();
418   }
419 }  // --displaywindow::setDifference()
420
421
422
423 void displaywindow::setIntensity(bool on) {
424   useintensity = on;
425   //  intensitybutton->setChecked(on);
426   int l;
427   l=imagename.length();
428   if(useintensity) {
429     if(id) 
430       imagename.replace(l-1,1,"i");
431     else
432       imagename.append("i");
433     setCaption(imagename);
434   }
435   else {
436     if(id) 
437       imagename.replace(l-1,1,"a");
438     else
439       imagename.remove(l-1,1);
440     setCaption(imagename);
441   }
442   if(usedifference) {
443     if(id) resetDiffImage();
444   } else {
445     resetImage();
446   }
447 }  // --displaywindows::setIntensity()
448
449
450
451 bool displaywindow::isGlobalthreshs()
452 {
453   return useglobal;
454 }  // --displaywindow::isGlobalthreshs()
455
456
457
458 void displaywindow::updateGlobalthreshs()
459 {
460   if(useglobal) {
461     if(usedifference) {
462       if(id) {
463         resetDiffImage();
464       } else {
465         resetImage();
466       }
467     }
468   }
469 }  // --displaywindow::updateGlobalthreshs()
470
471
472
473 void displaywindow::setGlobalthreshs()
474 {
475   if(usedifference && !id) return;
476   if(usedifference) 
477     resetDiffImage();
478   else
479     resetImage();
480 }  // --displaywindow::setGlobalthreshs()
481
482
483 /** update lowthreshold (number) and lowthresh (text) based on lowthreshslider */
484 void displaywindow::updateLowthresh()
485 {
486   if(id || !usedifference) {
487     char s[12];
488     int v = lowthreshslider->value();
489     if(v > highthreshslider->value()) { // cap it
490       lowthreshslider->setValue(highthreshslider->value());
491       lowthreshold = highthreshold;
492       lowthresh->setText(highthresh->text());
493     } else {
494       lowthreshold = (((double)v) / 1000000000) * Range + (usedifference ? diffminval : minval);
495       sprintf(s,"%10.7f",lowthreshold);
496       lowthresh->setText(s);
497     }
498     if(usedifference) {
499       resetDiffImage();
500     } else {
501       resetImage();
502     }
503   }
504 }  // --displaywindow::updateLowthresh()
505
506
507
508 double displaywindow::getLowthresh()
509 {
510   return lowthreshold;
511 }  // --displaywindow::getLowthresh()
512
513
514 /** update lowthreshold and low threshold slider pos based on entered lowthresh */
515 void displaywindow::updateLowthreshslider()
516 {
517   if(id || !usedifference) {
518     double fv;
519     int v=0;
520     bool ok=false;
521     fv=lowthresh->text().toDouble(&ok);
522     if(ok) {
523       if(fv > highthreshold) {
524         QMessageBox::information(this,"SnarkDisplay","Error!\n"
525                                  "Cannot set low threshold higher than high threshold!");
526       } else {
527         if(fv < (usedifference ? diffminval : minval)) {
528           QMessageBox::information(this,"SnarkDisplay","Error!\n"
529                                    "Cannot set low threshold that low!");
530         } else { // GOOD
531           if(fv>0) {
532             v= (int)(((fv - (usedifference ? diffminval : minval)) / Range) * 1000000000 + 0.5);
533           } else {
534             v= (int)(((fv - (usedifference ? diffminval : minval)) / Range) * 1000000000 - 0.5);
535           }
536           lowthreshslider->setValue(v);
537           lowthreshold=fv;
538           if(usedifference) {
539             resetDiffImage();
540           } else {
541             resetImage();
542           }
543           return; // if good
544         }
545       }
546     } else { // not OK
547       QMessageBox::information(this,"SnarkDisplay","Error!\n"
548                                "Low Threshold value invalid.");
549     }
550     char s[12]; // if got here, no good one way or another.
551     sprintf(s,"%10.7f",lowthreshold);
552     lowthresh->setText(s); // old val
553     lowthresh->setFocus();
554   }
555 }  // --displaywindow::updateLowthreshslider()
556
557
558 /** update highthreshold (number) and highthresh (text) based on highthreshslider */
559 void displaywindow::updateHighthresh()
560 {
561   if(id || !usedifference) {
562     char s[12];
563     int v = highthreshslider->value();
564     if(v < lowthreshslider->value()) {
565       highthreshslider->setValue(lowthreshslider->value());
566       highthreshold = lowthreshold;
567       highthresh->setText(lowthresh->text());
568     } else {
569       highthreshold = (((double)v) / 1000000000) * Range + (usedifference ? diffminval : minval);
570       sprintf(s,"%10.7f",highthreshold);
571       highthresh->setText(s);
572     }
573     if(usedifference) {
574       resetDiffImage();
575     } else {
576       resetImage();
577     }
578   }
579 }  // --displaywindow::updateHighthresh()
580
581
582
583 double displaywindow::getHighthresh()
584 {
585   return highthreshold;
586 }
587
588
589
590 void displaywindow::updateHighthreshslider()
591 {
592   if(id || !usedifference) {
593     double fv;
594     int v=0;
595     bool ok=false;
596     fv=highthresh->text().toDouble(&ok);
597     if(ok) {
598       if(fv < lowthreshold) {
599         QMessageBox::information(this,"SnarkDisplay","Error!\n"
600                                  "Cannot set high threshold lower than low threshold!");
601       } else {
602         if(fv > (usedifference ? diffmaxval : maxval)) {
603           QMessageBox::information(this,"SnarkDisplay","Error!\n"
604                                  "Cannot set high threshold that high!");
605         } else { // GOOD
606           if(fv>0) {
607             v=(int)(((fv-(usedifference ? diffminval : minval))/Range)*1000000000+0.5);
608           } else {
609             v=(int)(((fv-(usedifference ? diffminval : minval))/Range)*1000000000+0.5);
610           }
611           highthreshslider->setValue(v);
612           highthreshold=fv;
613           if(usedifference) {
614             resetDiffImage();
615           } else {
616             resetImage();
617           }
618           return; // if good
619         }
620       }
621     } else { // not OK
622       QMessageBox::information(this,"SnarkDisplay","Error!\n"
623                                "High Threshold value invalid.");
624     }
625     char s[12]; // if got here, no good one way or another.
626     sprintf(s,"%10.7f",highthreshold);
627     highthresh->setText(s); // old val
628     highthresh->setFocus();
629   }
630 }  // --displaywindow::updateHighthreshslider()
631
632
633
634 void displaywindow::resetImage()
635 {
636   if(id && usedifference) return;
637   double old_lowthreshold = lowthreshold;  // hack
638   double old_highthreshold = highthreshold;
639   if(useglobal) { // see if we can get away so easily
640     lowthreshold = lowglobalthresh;
641     highthreshold = highglobalthresh;
642   }
643   /* adjust image to current thresholds and zoom */
644   int i,j,m,n,base,point;
645   double t;
646   unsigned char tuc;
647   QPixmap disp;
648   QImage& rec = (*recp);
649   rec = rec.smoothScale(Sizex*zoomval,Sizey*zoomval);
650   rec.setNumColors(256);
651   for(i=0;i<256;i++)
652     rec.setColor(i,qRgb(i,i,i));
653   range=highthreshold-lowthreshold;
654   /* printf("low=%f high=%f range=%f \n",lowthreshold,highthreshold,range); */
655
656   for(i=0;i<Sizey;i++) {
657     base=i*zoomval;
658     for(j=0;j<Sizex;j++) {
659       point=j*zoomval;
660       t=((image[i][j]-lowthreshold)/range);
661       //printf("t=%f\n",t);
662       if(t==0.0 || t<0.0) {
663         //printf("t=%f\n",t);
664         for(m=0;m<zoomval;m++) 
665           for(n=0;n<zoomval;n++) 
666             *(rec.scanLine(base+m)+point+n)=0;
667       }
668       else {
669         //printf("t=%f\n",t);
670         if(t>1.0 || t==1.0) {
671           for(m=0;m<zoomval;m++) 
672             for(n=0;n<zoomval;n++) 
673               *(rec.scanLine(base+m)+point+n)=255;
674           //printf("%d\n",rec.pixelIndex(i,j));
675         }
676         else {
677           //printf("t=%f\n",t);
678           if(useintensity) {
679             tuc=(unsigned char)(sqrt(t)*255);
680             for(m=0;m<zoomval;m++) 
681               for(n=0;n<zoomval;n++) {
682                 //printf("tuc=%d\n",tuc);
683                 *(rec.scanLine(base+m)+point+n)=tuc;
684                 //printf("%d\n",*(rec.scanLine(i)+j));
685               }
686           }
687           else {
688             tuc=(unsigned char)(t*255);
689             for(m=0;m<zoomval;m++) 
690               for(n=0;n<zoomval;n++) {
691                 //printf("tuc=%d\n",tuc);
692                 *(rec.scanLine(base+m)+point+n)=tuc;
693                 //printf("%d\n",*(rec.scanLine(i)+j));
694               }
695           }
696         }
697       }
698     }
699   }
700   converted=disp.convertFromImage(rec,QPixmap::Auto); 
701   displaywidget->resize(Sizex*zoomval,Sizey*zoomval);
702   displaywidget->setBackgroundPixmap( disp );
703   if(useglobal) {
704     lowthreshold = old_lowthreshold;
705     highthreshold = old_highthreshold;
706   }
707   resize(MIN(maxSizex, 200+(Sizex*zoomval)),
708          MIN(maxSizey, 20+(Sizey*zoomval)));
709   scrollv->resizeContents ( Sizex*zoomval + 10, Sizey*zoomval + 10 );
710 } // --displaywindow::resetImage()
711
712
713
714 void displaywindow::resetDiffImage() 
715 {
716   double old_lowthreshold = lowthreshold;  // hack
717   double old_highthreshold = highthreshold;
718   if(useglobal) { // see if we can get away so easily
719     lowthreshold = lowglobalthresh;
720     highthreshold = highglobalthresh;
721   }
722   /* adjust image to current thresholds and zoom */
723   int i,j,m,n,base,point;
724   double t;
725   unsigned char tuc;
726   QPixmap disp;
727   QImage& rec = (*recp);
728   rec = rec.smoothScale(Sizex*zoomval,Sizey*zoomval);
729   rec.setNumColors(256);
730   for(i=0;i<256;i++)
731     rec.setColor(i,qRgb(i,i,i));
732   range=highthreshold-lowthreshold;
733   /* printf("low=%f high=%f range=%f \n",lowthreshold,highthreshold,range); */
734
735   for(i=0;i<Sizey;i++) {
736     base=i*zoomval;
737     for(j=0;j<Sizex;j++) {
738       point=j*zoomval;
739       t=((diffimage[i][j]-lowthreshold)/range);
740       //printf("t=%f\n",t);
741       if(t==0.0 || t<0.0) {
742         //printf("t=%f\n",t);
743         for(m=0;m<zoomval;m++) 
744           for(n=0;n<zoomval;n++) 
745             *(rec.scanLine(base+m)+point+n)=0;
746       }
747       else {
748         //printf("t=%f\n",t);
749         if(t>1.0 || t==1.0) {
750           for(m=0;m<zoomval;m++) 
751             for(n=0;n<zoomval;n++) 
752               *(rec.scanLine(base+m)+point+n)=255;
753           //printf("%d\n",rec.pixelIndex(i,j));
754         }
755         else {
756           //printf("t=%f\n",t);
757           if(useintensity) {
758             tuc=(unsigned char)(sqrt(t)*255);
759             for(m=0;m<zoomval;m++) 
760               for(n=0;n<zoomval;n++) {
761                 //printf("tuc=%d\n",tuc);
762                 *(rec.scanLine(base+m)+point+n)=tuc;
763                 //printf("%d\n",*(rec.scanLine(i)+j));
764               }
765           }
766           else {
767             tuc=(unsigned char)(t*255);
768             for(m=0;m<zoomval;m++) 
769               for(n=0;n<zoomval;n++) {
770                 //printf("tuc=%d\n",tuc);
771                 *(rec.scanLine(base+m)+point+n)=tuc;
772                 //printf("%d\n",*(rec.scanLine(i)+j));
773               }
774           }
775         }
776       }
777     }
778   }
779   converted=disp.convertFromImage(rec,QPixmap::Auto); 
780   displaywidget->resize(Sizex*zoomval,Sizey*zoomval);
781   displaywidget->setBackgroundPixmap( disp );
782   if(useglobal) {
783     lowthreshold = old_lowthreshold;
784     highthreshold = old_highthreshold;
785   }
786   resize(MIN(maxSizex, 200+(Sizex*zoomval)),
787          MIN(maxSizey, 20+(Sizey*zoomval)));
788   scrollv->resizeContents ( Sizex*zoomval + 10, Sizey*zoomval + 10 );
789 }  // --displaywindow::resetDiffImage()
790
791
792
793 void displaywindow::resetImageRange() 
794 {
795   /* adjust image to current thresholds */
796   int i,j;
797   double t;
798   QPixmap disp;
799   QImage& rec = (*recp);
800   range=highthreshold-lowthreshold;
801   /* printf("low=%f high=%f range=%f \n",lowthreshold,highthreshold,range); */
802
803   for(i=0;i<Sizey;i++) 
804     for(j=0;j<Sizex;j++) {
805       t=((image[i][j]-lowthreshold)/range);
806       if(t<=0)
807         *(rec.scanLine(i)+j)=0;
808       else 
809         if(t>=1) 
810           *(rec.scanLine(i)+j)=255;
811         else 
812           *(rec.scanLine(i)+j)=(unsigned char)(t*255);
813     }
814   converted=disp.convertFromImage(rec,QPixmap::Auto); 
815   displaywidget->setBackgroundPixmap( disp );
816
817 }  // --displaywindow::resetImageRange() 
818
819
820
821 /** Starts a lines window 
822 @param void
823 @author Bruno M. Carvalho for version 1.0, Deniz
824 @version 1.4 
825 @description a lot like SnarkDisplay::callLines() defined in SnarkDisplay.cpp
826 */
827 void displaywindow::callLines()
828 {
829   int l[4];
830   int linetype,c,i,j,minx,maxx, topleftx,toplefty;
831   double **img;
832   double miny,maxy;
833   QString title,xaxis,yaxis,temp;
834   QPoint topleft;
835   imagename = imagename.simplifyWhiteSpace();
836   lineswindow* nw = new lineswindow(this,imagename,lowthreshold,highthreshold,true,1);
837   c=nw->exec();
838   if(c==QDialog::Accepted) {
839     linetype=nw->getLinetype(); // default == 0 == row; 1 == column
840     // '0' means 'show for suchandsuch rows all columns within x-selection' etc
841     l[0]=nw->getLine1();
842     l[1]=nw->getLine2();
843     l[2]=nw->getLine3();
844     l[3]=nw->getLine4();
845     title=nw->getTitle();    // bug 227, wei, 6/13/2007
846     xaxis=nw->getXAxis();
847     yaxis=nw->getYAxis();
848     minx=nw->getMinX();
849     maxx=nw->getMaxX();
850     miny=nw->getMinY();
851     maxy=nw->getMaxY();
852     topleft=this->pos();
853     topleftx=topleft.x();
854     toplefty=topleft.y();
855     QString rowOrColumn = ( (linetype) ? ("Column ") : ("Row ") );
856     QString vs = ( (linetype) ? ("Rows") : ("Columns"));
857     // loop through selection
858     for(j=0;j<4;j++) {
859       if(l[j]>=0 && l[j]<Sizex) {
860         // spawn different plot for each valid j!
861         line_real_set_t myLRS(minx,maxx,miny,maxy); // create a brand new LRS for brand new plot
862         myLRS.clear(); // and be sure of it!
863         topleftx+=30;
864         toplefty+=30;
865         QPixmap* pixmap = new QPixmap(sd_line_t::WIDTH, sd_line_t::HEIGHT);
866         pixmap->fill(Qt::white);
867         QPainter picasso;
868         picasso.begin(pixmap);
869         picasso.setBackgroundColor(Qt::white);
870         QString whichRowOrCol;
871         whichRowOrCol.setNum(l[j]);
872         QString plotSuffix = (rowOrColumn + whichRowOrCol);
873         //QString plotName = imagename.simplifyWhiteSpace();
874         QString plotName = title.simplifyWhiteSpace();   // bug 227, wei, 6/13/2007
875         plotName += (" :: " + plotSuffix);
876         line_real_t ourImageLine(imagename);
877         // references for unification -- have to be initialized right here
878         int&row = ( (linetype) ? (i) : (l[j]) );
879         int&col = ( (linetype) ? (l[j]) : (i) );
880
881         // now do the stuff for phantom
882         if((nw->isPhantomChecked()) && id) {
883           if(!imageset[0]->isLoaded())
884             imageset[0]->readImage(0,DIGDataFormat_ASCII);
885           img=imageset[0]->getImage();
886           QString phantomName = imagetitles[0];
887           phantomName = phantomName.simplifyWhiteSpace();
888           line_real_t phantomLine(phantomName);
889           for(i=0;i<Sizey;i++) {
890             phantomLine.add(i, img[row][col]);
891           }
892           myLRS.add(phantomLine);
893         }
894
895
896         double **&ourim = ( (usedifference) ? (diffimage) : (image) );
897         for(i=0;i<Sizey;i++) {
898           ourImageLine.add(i,ourim[row][col]);
899         }
900         myLRS.add(ourImageLine);
901
902         plot_t myPlot(myLRS);
903         myPlot.setName(plotName);    // actual param has to be be a legitimate QString object
904         myPlot.setXAxisName(xaxis);  // for all three of these names
905         myPlot.setYAxisName(yaxis);
906         // jk 1/13/2009 adding grayScale option for graphs
907         if (nw->isGrayScaleChecked()) {
908             myPlot.plotGray(picasso);
909         }
910         else{
911             myPlot.plot(picasso);
912         }
913         /* Call display lines with pixmap as one of the arguments */
914         displaylineswindow* dw=new displaylineswindow(this,plotName,pixmap,false,0,topleftx,toplefty);
915         dw->show();
916       }
917     }
918   }
919 }  // --displaywindow::callLines()
920
921
922
923 /** Saves the current image
924 @param void
925 @author Bruno M. Carvalho
926 @version 1.0 */ 
927 void displaywindow::saveImage()
928 {
929   int i,j;
930   QString prefixForSaving = imagename;
931   prefixForSaving = prefixForSaving.simplifyWhiteSpace();
932   prefixForSaving.replace( QRegExp("\\="), "_EQ_");
933   prefixForSaving.replace( QRegExp("\\+"), "_PLUS_");
934   prefixForSaving.replace( QRegExp("\\@"), "_AT_");
935   //  prefixForSaving.replace( QRegExp("-"), "_MINUS_"); // maybe
936   // convert everything non-alphanumeric to underscore
937   prefixForSaving.replace( QRegExp("[^a-zA-Z0-9]"), "_");
938   // allow maximum of 2 consecutive underscores  
939   prefixForSaving.replace( QRegExp("__+") , "__"); 
940   // chuck underscore from beginning and end
941   prefixForSaving.replace( QRegExp("^_+"), "");
942   prefixForSaving.replace( QRegExp("_+$"), "");
943
944   QString myExtensionFilter = 
945     "png (PNG file);;"
946     "bmp (BMP file);;"
947     "flt (ASCII float file);;"
948     "pbm (PBM file);;"
949     "pgm (PGM file);;"
950     "ppm (PPM file);;"
951     "xbm (XBM file);;"
952     "xpm (XPM file)"   ;
953
954   QString mySaveAs = "Save Image as";
955   QString startInDir = "./";
956   QFileDialog fd(startInDir, myExtensionFilter, this, mySaveAs, true);
957   fd.setMode(QFileDialog::AnyFile);
958   fd.setSelection(prefixForSaving);
959   if (QDialog::Accepted != fd.exec()) {
960     if(std::verbose >=2) std::cout << "--displaywindow::saveImage() in a hurry" << std::endl;
961     return; // happens, say, when cancel is pressed.  just leave, no harm.
962   }
963   QString userFileSavePrefix = fd.selectedFile();
964   QString userFileSaveExtension = fd.selectedFilter();
965   if (userFileSavePrefix.isEmpty()) { // double-check for absurdity
966     if(std::verbose >=2) std::cout << "--displaywindow::saveImage() in a hurry" << std::endl;
967     return; // happens, say, when cancel is pressed.  just leave, no harm.
968   }
969   if(std::verbose >=2) std::cout << "Got file name as: \"" << userFileSavePrefix << "\"" << std::endl;
970   if(std::verbose >=2) std::cout << "Got selected ext: \"" << userFileSaveExtension << "\"" << std::endl;
971   /* NB: userFileSavePrefix now contains directory info as well.
972    * if user entered additional forward-slashes without
973    * knowing that it signified directory, that's NOT our problem.
974    * (the user MAY legitimately enter "a/myImage" as file name if there is a directory "a" 
975    *   within the currently open directory in the save dialog window)
976    * do part only after last forward-slash (i.e., what user entered)...
977    * don't want to burn ourselves if path in fact had legit non-alphanumericounderscore chars
978    */
979   QString justFilePrefix, justPath;
980   // funnylooking because written to work with Qt BOTH 2.3 and 3.3
981   int posLastSlash = userFileSavePrefix.findRev('/'); // returns pos if found, -1 if not.
982   if (-1 != posLastSlash) {
983     justPath = userFileSavePrefix.left(posLastSlash+1); // +1 to include last '/'
984     justFilePrefix = userFileSavePrefix;
985     QRegExp fakeRegex("^" + justPath); // it just *looks* fake...
986     justFilePrefix.replace( fakeRegex, "" ); // chuck away including last '/' for justFilePrefix
987     if(std::verbose >=2) std::cout << "just after regex replace, justFilePrefix: \"" << justFilePrefix << "\"" << std::endl;
988   } else {  // if for some reason no forwardslash, handle that gracefully too.
989     justFilePrefix = userFileSavePrefix;
990     justPath = "";
991   }
992   if(std::verbose >=2) std::cout << "justPath is: \"" << justPath << "\"" << std::endl;
993   if(std::verbose >=2) std::cout << "justFilePrefix is first: \"" << justFilePrefix << "\"" << std::endl;
994   // remove justFilePrefix from ONLY the end of 'userFileSavePrefix'.
995   justFilePrefix.replace( QRegExp("="), "_EQ_");
996   justFilePrefix.replace( QRegExp("+"), "_PLUS_");
997   justFilePrefix.replace( QRegExp("[^a-zA-Z0-9]"), "_"); // no forward slash in regex
998   // allow maximum of 2 consecutive underscores  
999   justFilePrefix.replace( QRegExp("__+") , "__"); 
1000   // chuck underscore from beginning and end
1001   justFilePrefix.replace( QRegExp("^_+"), "");
1002   justFilePrefix.replace( QRegExp("_+$"), "");
1003   if(std::verbose >=2) std::cout << "justFilePrefix is later: \"" << justFilePrefix << "\"" << std::endl;
1004   // reset userFileSavePrefix by putting back together justPath and the refined justFilePrefix
1005   userFileSavePrefix = justPath + justFilePrefix;
1006   userFileSaveExtension.truncate(3);
1007   if(std::verbose >=2) std::cout << "My userFileSavePrefix is \"" << userFileSavePrefix << "\"" << std::endl;
1008   if(std::verbose >=2) std::cout << "My userFileSaveExtension is \"" << userFileSaveExtension << "\"" << std::endl;
1009   QString extensionUpper = userFileSaveExtension.upper();
1010   QString saveFullNameWithPath = userFileSavePrefix + "." + extensionUpper;
1011   if(std::verbose >=2) std::cout << "extensionUpper is now \"" << extensionUpper << "\"" << std::endl;
1012   if(std::verbose >=2) std::cout << "saveFullNameWithPath is now \"" << saveFullNameWithPath << "\"" << std::endl;
1013   if(extensionUpper.compare(QString("FLT"))) { // if NOT "FLT" extension ("FLT" is Bruno's / Linkoping's bunchafloats format)
1014     QImageIO recio;
1015     QImage& rec = (*recp);
1016     recio.setImage(rec);
1017     recio.setFormat(extensionUpper);
1018     recio.setFileName(saveFullNameWithPath);
1019     if ( recio.write() ) {
1020       if(std::verbose >= 1) {
1021         std::cout << "displaywindow::saveImage() successfully saved: \"" << saveFullNameWithPath << "\"" << std::endl;
1022         return;
1023       }
1024     } else {
1025       std::cerr << "Error opening " << saveFullNameWithPath << std::endl;
1026       return;
1027     }
1028   } else {
1029     FILE* fp;
1030     if((fp = fopen(saveFullNameWithPath.latin1(),"w"))==NULL) {
1031       std::cerr << "UNsuccessfully tried to save as: \"" << saveFullNameWithPath << "\"" << std::endl;
1032       return;
1033     } else {
1034       for(i=0;i<Sizey;i++) {
1035         for(j=0;j<Sizex;j++) {
1036           fprintf(fp,"%f ",image[i][j]);
1037           if(!((j+1)%5)) 
1038             fprintf(fp,"\n");
1039         }
1040         fprintf(fp,"\n");
1041       }
1042       fclose(fp);
1043       if(std::verbose>=1) {
1044         std::cout << "(we think) successfully saved: \"" << saveFullNameWithPath << "\"" << std::endl;
1045       }
1046     }
1047   }
1048 }  // --displaywindow::saveImage()