eddbdc846cc73121285f31f4a6674667194917eb
[snark14.git] / tools / Display / eval_helper.cpp
1 /** @file eval_helper.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
8 /** @name eval_helper.hpp
9     @type C++ header file
10     @date March 2004
11     @package snark14Display
12     @purpose to help snark14Display in the interpretation of eval files, broadly speaking.
13     @author deniz, who realizes after 1200 lines that a lot of space and (programmer) time 
14     could have been saved by enumerated-typing of global resolution measure field names
15  *
16     @description this header file contains the implementation of classes, starting with:
17     phantomeas: phantom measurement structure
18     globmeas  : global resolution measurement structure
19     PBPmeas   : point-by-point error measurement structure
20   (1-line measurements in eval: glorified structures with constructors that take "measline_t" (char*))
21  *
22  phantomeas   globmeas    PBPmeas
23    |            |           |
24    |     globmeaset   PBPmeaset (info from a single execution of a single algorithm in a call to EVALUATE)
25    |        |          |
26    |       eval_execution   (info from a single call to EVALUATE, that includes calls like "EVALUATE BOTH")
27    |         |
28    |         |
29   eval_exec_set    (info from all EVALUATE calls of a snark14 run)
30  *
31   You can read "is member of" relationships if you go top down, very intuitive up to abbreviation.
32  *
33   Attempted improvements to Bruno's version (which was < 1.0):
34   - no more segmentation faults due to eval
35   - dynamic parsing and allocation for 'residual', an optional field of a globmeas, that can vary WITHIN a globmeaset
36   - variable number of fields in a point-by-point measurement structure (PBPmeas)
37   - support for multiple EVALUATE calls in snark14
38   - extrema calculated dynamically, "recursively"
39  *
40   Notes:
41   - the number of fields of all PBPmeas structures is uniquely determined by the snark14 produced eval file
42     deniz thinks it is proportional to the logarithm of phantom/reconstruction images' number-of-pixels-on-side
43   - phantomeas can be tied to eval_exec_set due to multiplicity, since there is exactly one phantom in each snark run,
44        but it can occur with OR without residual, in the same.
45  *
46   TO DO:
47   - plot phantomeas with globals.
48  */
49
50 #include <qwidget.h>
51 #include <qpoint.h>
52 #include <qpixmap.h>
53 #include <qpainter.h>
54 #include <qstring.h>
55 #include <exception>
56 #include <stdexcept>
57 #include <cstdio>
58 #include <iostream>
59 #include <deque>
60 #include <vector>
61
62 #include "eval_helper.hpp"
63 #include "displaylines.hpp"
64 #include "chooseRanges.hpp"
65
66 #include "line_real_t.hpp"
67 #include "plot_t.hpp"
68
69 //  typedef char* measline_t;
70 //  typedef char* execname_t;
71
72 // global (resolution) measurements go into global measurement sets
73 // point-by-point resolution measurements go into PBP measurement sets
74 // an evaluation can have
75
76 /** each phantomeas corresponds to a line of phantom stats in the eval file */
77
78 class phantomeas {
79     int region;
80     int area;
81     double average;
82     double variance;
83     double stddev;
84     double* residualp;
85     double* kullbackp;
86 public:
87
88     /** phantomeas 1-arg constructor */
89     phantomeas(measline_t line) {
90         //0     625    0.3622                        0.1860    0.4312
91         //1     4225   0.3574                        0.2795    0.5287 1216.8134
92         double resid;
93         double kullback;
94         int numthingsread =
95                 std::sscanf(line, "%d %d %lg %lg %lg %lg %lg",
96                 &region, &area, &average, &variance, &stddev, &resid, &kullback);
97         if (numthingsread < 5)
98             throw std::invalid_argument("line in phantomeas constructor must have at least 5 numeric fields");
99         if (numthingsread == 5) {
100             residualp = 0;
101             kullbackp = 0;
102         } else if (numthingsread == 6) {
103                 kullbackp = 0;
104             residualp = new double;
105             *residualp = resid;
106         } else if (numthingsread == 7) {
107             residualp = new double;
108             *residualp = resid;
109             kullbackp = new double;
110             *kullbackp = kullback;
111         } else throw std::logic_error("Something very interesting is wrong in phantomeas constructor");
112     } // --phantomeas 1-arg ctor
113
114     /** phantomeas ("deep") copy ctor */
115     phantomeas(const phantomeas& p) {
116         region = p.region;
117         area = p.area;
118         variance = p. variance;
119         stddev = p.stddev;
120         if (p.residualp) {
121             residualp = new double;
122             *residualp = *(p.residualp);
123         } else residualp = 0;
124         if (p.kullbackp) {
125                 kullbackp = new double;
126             *kullbackp = *(p.kullbackp);
127         } else kullbackp = 0;
128     } // --phantomeas::operator=
129
130     /** phantomeas deep-copying assignment operator */
131     phantomeas & operator=(const phantomeas& p) {
132         std::cout << "in phantomeas deep assignment operator!" << std::endl;
133         if (this == &p) return *this; // Gracefully handle self assignment
134         region = p.region;
135         area = p.area;
136         variance = p. variance;
137         stddev = p.stddev;
138         if (p.residualp) {
139             residualp = new double;
140             *residualp = *(p.residualp);
141         } else residualp = 0;
142         if (p.kullbackp) {
143                 kullbackp = new double;
144             *kullbackp = *(p.kullbackp);
145         } else kullbackp = 0;
146         return *this;
147     } // --phantomeas::operator=
148
149     int getRegion() const {
150         return region;
151     }
152     //  int getArea()        const { return area;           }
153
154     double getAverage() const {
155         return average;
156     }
157
158     double getVariance() const {
159         return variance;
160     }
161
162     double getStddev() const {
163         return stddev;
164     }
165
166     bool hasResidual() const {
167         return (0 != residualp);
168     }
169
170     bool hasKullback() const {
171         return (0 != kullbackp);
172     }
173
174     /** getResidual() should not be called without calling hasResidual() */
175     double getResidual() { // defensive programming
176         if (0 == residualp)
177             throw std::logic_error("called phantomeas::getResidual() without calling hasResidual() where there is no residual");
178         // else
179         return (*residualp);
180     }
181
182     /** getKullback() should not be called without calling hasKullback() */
183     double getKullback() { // defensive programming
184         if (0 == kullbackp)
185             throw std::logic_error("called phantomeas::getKullback() without calling hasKullback() where there is no KL distance");
186         // else
187         return (*kullbackp);
188     }
189
190     void setNewResidual(double res) {
191         residualp = new double;
192         *residualp = res;
193     }
194
195     void setNewKullback(double kld) {
196         kullbackp = new double;
197         *kullbackp = kld;
198     }
199
200     double get(globalYVar_t globalYVar) {
201         switch (globalYVar) {
202             case AVERAGE:
203                 return average;
204                 break;
205             case VARIANCE:
206                 return variance;
207                 break;
208             case STDDEV:
209                 return stddev;
210                 break;
211             case RESIDUAL:
212                 if (hasResidual())
213                     return getResidual();
214             case KULLBACK:
215                 if (hasKullback())
216                     return getKullback();
217             default:
218                 // it is likely for this to be called with, say, distance, which phantom has none
219                 return -2.0;
220                 // negative value ought to be be ignored by callee
221         }
222     } // phantomeas::get()
223
224     /** show routine for phantom, for debug  */
225     void show() {
226         std::cout << "> Phantom:" << std::endl;
227         std::cout << "region average variance stddev";
228         if (hasResidual()) std::cout << " residual";
229         if (hasKullback()) std::cout << " KL distance";
230         std::cout << std::endl;
231         std::cout << region << " " << average << " " << variance << " " << stddev;
232         if (hasResidual()) std::cout << " " << getResidual();
233         if (hasKullback()) std::cout << " " << getKullback();
234         std::cout << std::endl;
235         std::cout << "< done showing phantom" << std::endl;
236     } // --show
237
238     ~phantomeas() {
239         //    std::cout << "in phantomeas destructor!" << std::endl;
240         if (residualp) delete residualp;
241         if (kullbackp) delete kullbackp;
242     }
243 }; // --class phantomeas
244
245 /** a globmeas corresponds to one line of global resolution stats in the eval file */
246 class globmeas {
247     // algname now in globmeaset
248     int iter; // some iterations might be missing from eval file => not always 1..n
249     int area;
250     double average;
251     double distance;
252     double relerr;
253     double variance;
254     double stddev;
255     double* residualp; // uninitialized if no residual
256     double* kullbackp; // uninitialized if no kl distance
257     static unsigned NEXT_GMID;
258     unsigned GMID;
259     // setfields(int iter, int area, double average, double distance
260 public:
261
262     globmeas(measline_t line) {
263         GMID = NEXT_GMID++;
264         //    1      4225    0.3850    0.8711    0.8927    0.0122    0.1104 9756.9313
265         //  char *line2 = "  1      4225    0.3850    0.8711    0.8927    0.0122    0.1104 9756.9313";
266         //  char *line2 = "  1      4225    0.3850    0.8711    0.8927    0.0122    0.1104          ";
267         double resid;
268         double kldis;
269         int numthingsread =
270                 std::sscanf(line, "%d %d %lg %lg %lg %lg %lg %lg %lg",
271                 &iter, &area, &average, &distance, &relerr, &variance, &stddev, &resid, &kldis);
272         if (numthingsread < 7)
273             throw std::invalid_argument("line in globmeas constructor must have at least 7 numeric fields");
274         if (numthingsread == 7) {
275             residualp = 0;
276             kullbackp = 0;
277         } else if (numthingsread == 8) {
278             residualp = new double;
279             *residualp = resid;
280             kullbackp = 0;
281         } else if (numthingsread == 9) {
282             residualp = new double;
283             *residualp = resid;
284             kullbackp = new double;
285             *kullbackp = kldis;
286         } else throw std::logic_error("Something very interesting is wrong in globmeas constructor");
287     } // --globmeas 1-arg ctor
288
289     /** globmeas deep copy constructor */
290     globmeas(const globmeas& g) {
291         if (std::verbose >= 5) std::cout << "In deep copy constructor with rhs GMID " << g.getGMID() << std::endl;
292         GMID = g.GMID;
293         iter = g.iter;
294         area = g.area;
295         average = g.average;
296         distance = g.distance;
297         relerr = g.relerr;
298         variance = g. variance;
299         stddev = g.stddev;
300         if (g.residualp) {
301             residualp = new double;
302             *residualp = *(g.residualp);
303         } else residualp = 0;
304         if (g.kullbackp) {
305                 kullbackp = new double;
306             *kullbackp = *(g.kullbackp);
307         } else kullbackp = 0;
308     } // --globmeas copy ctor
309
310     unsigned getGMID() const {
311         return static_cast<unsigned> (GMID);
312     }
313
314     /** globmeas deep-copying assignment operator */
315     globmeas & operator=(const globmeas& g) {
316         if (std::verbose >= 5) std::cout << "In globmeas operator= with rhs GMID " << g.getGMID() << std::endl;
317         if (this == &g) return *this; // Gracefully handle self assignment
318         GMID = g.GMID;
319         iter = g.iter;
320         area = g.area;
321         average = g.average;
322         distance = g.distance;
323         relerr = g.relerr;
324         variance = g. variance;
325         stddev = g.stddev;
326         if (g.residualp) {
327             residualp = new double;
328             *residualp = *(g.residualp);
329         } else residualp = 0;
330         if (g.kullbackp) {
331                 kullbackp = new double;
332             *kullbackp = *(g.kullbackp);
333         } else kullbackp = 0;
334         return *this;
335     } // --globmeas::operator=
336
337     /** globmeas functions that 'get' fields */
338     int getIter() const {
339         return iter;
340     }
341     //  int    getArea()     const { return area; }
342
343     double getAverage() const {
344         return average;
345     }
346
347     double getDistance() const {
348         return distance;
349     }
350
351     double getRelerr() const {
352         return relerr;
353     }
354
355     double getVariance() const {
356         return variance;
357     }
358
359     double getStddev() const {
360         return stddev;
361     }
362
363     bool hasResidual() const {
364         return (0 != residualp);
365     }
366
367     bool hasKullback() const {
368         return (0 != kullbackp);
369     }
370
371     double getResidual() const {
372         if (0 == residualp)
373             throw std::logic_error("called getResidual without calling hasResidual() where there is no residual");
374         // else
375         return (*residualp);
376     }
377
378     double getKullback() const {
379         if (0 == kullbackp)
380             throw std::logic_error("called getKullback without calling hasKullback() where there is no kl distance");
381         // else
382         return (*kullbackp);
383     }
384
385     /** globmeas::show_all() is a debug routine to show all fields of a single global measurement of an iteration */
386     void show_all() {
387         std::cout << iter;
388         std::cout << " ";
389         std::cout << area;
390         std::cout << " ";
391         std::cout << average;
392         std::cout << " ";
393         std::cout << distance;
394         std::cout << " ";
395         std::cout << relerr;
396         std::cout << " ";
397         std::cout << variance;
398         std::cout << " ";
399         std::cout << stddev;
400         if (hasResidual()) {
401             std::cout << " ";
402             std::cout << getResidual();
403         }
404         if (hasKullback()) {
405             std::cout << " ";
406             std::cout << getKullback();
407         }
408         std::cout << std::endl;
409     } // globmeas::show_all()
410
411     ~globmeas() {
412         if (0 != residualp) {
413             if (std::verbose >= 5) std::cout << "Residualp was nonzero, residual " << (*residualp) << " ";
414             delete residualp;
415         }
416         if (0 != kullbackp) {
417             if (std::verbose >= 5) std::cout << "Kullbackp was nonzero, kl distance " << (*kullbackp) << " ";
418             delete kullbackp;
419         }
420         if (std::verbose >= 5) std::cout << "In globmeas " << GMID << " Dtor" << std::endl;
421     } // --globmeas dtor
422 }; // --class globmeas
423
424 // unsigned globmeas::NEXT_GMID = 0; // class variable initialization
425
426 /** a globmeaset is the set of global resolution statistics for one execution of an algorithm */
427 class globmeaset {
428     execname_t execname;
429     //  QString execname;   // name of the execution
430     // note that the same algorithm can have several executions
431     char algname[5]; // name of the algorithm (3 or 4 letters followed by null terminator)
432     std::deque<globmeas> measurements;
433     // why a deque and not a vector?
434     // --all access is sequential
435     // --regular queue does not allow iterator (i think)
436     // --when you push_back something new, it does not destruct all existing elements, ensuring linear runtime
437     // --can be used a lot like a vector (.size() etc are available)
438     double minAverage, maxAverage, minDistance, maxDistance, minRelerr, maxRelerr;
439     double minVariance, maxVariance, minStddev, maxStddev;
440     double minResidual, maxResidual; // both -1 if no line with residual in the set
441     double minKullback, maxKullback; // both -1 if no line with kl distance in the set
442     //  int minArea, maxArea;
443     int minIter, maxIter; // minIter is not necessarily 1
444     static unsigned NEXT_GMSID; // one for all global measurement sets
445     unsigned GMSID; // unique ID for this set
446     bool completed;
447     bool extrema_calculated;
448     char name[512];
449 public:
450
451     globmeaset(execname_t line) {
452         GMSID = NEXT_GMSID++;
453         completed = false;
454         extrema_calculated = false;
455         memset(name, 0, 512);
456         char *p = line;
457         char *q;
458         q = &(name[0]);
459
460         static const char *needle = "xecution name:";
461         p = strstr(p, needle);
462         if (p) {
463             p += strlen(needle);
464             while ((' ' == *p) || ('\t' == *p)) p++;
465             for (int i = 0; (i < 490) && (*p) && ('\n' != *p) && ('\r' != *p); i++) {
466                 *q++ = *p++;
467             }
468         }
469         *q = '\0'; // just to be sure
470         ///    std::cout << "exec name in globmeaset is: `" << name << "'" << std::endl;
471         if (std::verbose >= 4) std::cout << "globmeaset " << GMSID << " ctor" << std::endl;
472     } // --globmeaset ctor
473
474     unsigned getGMSID() const {
475         return GMSID;
476     }
477
478     execname_t getName() {
479         return (&name[0]);
480     }
481
482     /*    void addMeasurement(globmeas& g) {    measurements.push_back(g);    }  */
483
484     /** globmeaset::addMeasurement() */
485     void addMeasurement(measline_t line) {
486         if (completed)
487             throw std::logic_error("Must NOT add to globmeaset once complete() is signalled");
488         // else
489         if (std::verbose >= 6) std::cout << "++ globmeaset::addMeasurement(line)" << std::endl;
490         globmeas g(line);
491         if (std::verbose >= 6) std::cout << "   globmeaset::addMeasurement(line): before push" << std::endl;
492         measurements.push_back(g); // pass by reference, and a copy is made using copy constructor
493         if (std::verbose >= 6) std::cout << "-- globmeaset::addMeasurement(line)" << std::endl;
494     } // --globmeaset::addMeasurement(line)
495
496     unsigned get_num_measurements() const {
497         return (static_cast<unsigned> (measurements.size()));
498     }
499
500     void addGlobVarLine(line_real_set_t& LRS, globalYVar_t globalYVar) {
501         line_real_t LR(getName());
502         for (std::deque<globmeas>::iterator it = measurements.begin();
503                 it != measurements.end(); it++) {
504             switch (globalYVar) {
505                 case AVERAGE:
506                     LR.add(it->getIter(), it->getAverage());
507                     break;
508                 case DISTANCE:
509                     LR.add(it->getIter(), it->getDistance());
510                     break;
511                 case RELERR:
512                     LR.add(it->getIter(), it->getRelerr());
513                     break;
514                 case VARIANCE:
515                     LR.add(it->getIter(), it->getVariance());
516                     break;
517                 case STDDEV:
518                     LR.add(it->getIter(), it->getStddev());
519                     break;
520                 case RESIDUAL:
521                     if (it->hasResidual()) {
522                         LR.add(it->getIter(), it->getResidual());
523                     }
524                 case KULLBACK:
525                     if (it->hasKullback()) {
526                         LR.add(it->getIter(), it->getKullback());
527                     }
528                     break;
529                 default:
530                     std::cerr << "Invalid globalYVar in globmeaset::addGlobVarLine()" << std::endl;
531             } // switch
532         } // for
533         if (!LR.empty()) LRS.add(LR);
534     } // --globmeaset::addGlobVarLine()
535
536     /** globmeaset::complete() invoke to indicate that all elements have been added to this globmeaset */
537     void complete() {
538         if (std::verbose >= 4)
539             std::cout << "Executing globmeaset::complete()" << std::endl;
540         if (measurements.empty()) {
541             throw std::logic_error("empty globmeaset refused to complete() itself");
542         } // else
543         if (completed)
544             throw std::logic_error("complete() already signalled for this globmeaset, must NOT signal again.");
545         // else
546         if (std::verbose >= 5)
547             std::cout << "completed is so far false" << std::endl;
548         completed = true;
549         if (std::verbose >= 5)
550             std::cout << "completed is now set to true" << std::endl;
551     } // globmeaset::complete()
552
553     /** globmeaset::isComplete() whether or not this global measurement set has been completed */
554     bool isComplete() const {
555         return completed;
556     } // globmeaset::isComplete()
557
558     /** globmeaset::calculate_extrema() calculates extrema of all measurments by field
559         assumes that 'iter' field is strictly increasing in the order they were added.
560         should be called as either 0-arg or 3-arg                                       */
561     bool calculate_extrema(bool restrict_domain = false, int min_it_arg = 0, int max_it_arg = 0) {
562         if (!completed)
563             throw std::logic_error("Must NOT calculate extrema of globmeaset before complete() is signalled");
564         // else
565         if (0 == get_num_measurements())
566             throw std::logic_error("Must NOT calculate extrema of empty globmeaset"); // else
567         //    int curArea;
568         double curAverage, curDistance, curRelerr, curVariance, curStddev, curResidual, curKullback;
569         minAverage = maxAverage = minDistance = maxDistance = minRelerr = maxRelerr = -1.0;
570         minVariance = maxVariance = minStddev = maxStddev = minResidual = maxResidual = minKullback = maxKullback = -1.0;
571         extrema_calculated = true; // this is intentionally true even if return value is false
572
573         std::deque<globmeas>::const_iterator it = measurements.begin();
574
575         if (restrict_domain) {
576             if (min_it_arg > max_it_arg)
577                 throw std::invalid_argument("globmeaset::calculate_extrema() called with arguments min>max");
578             while ((it != measurements.end()) && (min_it_arg > (*it).getIter()))
579                 it++;
580             if (it == measurements.end())
581                 return false; // iterations of this globmeaset are out of requested range
582             maxIter = minIter = (*it).getIter();
583         } else {
584             minIter = (*it).getIter();
585             maxIter = measurements.back().getIter(); // and that's that.
586         }
587         //    curArea     = minArea     = maxArea     = (*it).getArea();
588         curAverage = minAverage = maxAverage = (*it).getAverage();
589         curDistance = minDistance = maxDistance = (*it).getDistance();
590         curRelerr = minRelerr = maxRelerr = (*it).getRelerr();
591         curVariance = minVariance = maxVariance = (*it).getVariance();
592         curStddev = minStddev = maxStddev = (*it).getStddev();
593         if ((*it).hasResidual()) { // not necessarily true
594             curResidual = minResidual = maxResidual = (*it).getResidual();
595         }
596         if ((*it).hasKullback()) { // not necessarily true
597             curKullback = minKullback = maxKullback = (*it).getKullback();
598         }
599         it++;
600         for (; it != measurements.end(); it++) {
601             if (restrict_domain) {
602                 if (max_it_arg < (*it).getIter())
603                     break;
604                 else maxIter = (*it).getIter();
605             }
606             //      curArea     = (*it).getArea();
607             curAverage = (*it).getAverage();
608             curDistance = (*it).getDistance();
609             curRelerr = (*it).getRelerr();
610             curVariance = (*it).getVariance();
611             curStddev = (*it).getStddev();
612             //      if(curArea     < minArea)     minArea     = curArea;
613             if (curAverage < minAverage) minAverage = curAverage;
614             if (curDistance < minDistance) minDistance = curDistance;
615             if (curRelerr < minRelerr) minRelerr = curRelerr;
616             if (curVariance < minVariance) minVariance = curVariance;
617             if (curStddev < minStddev) minStddev = curStddev;
618
619             //      if(curArea     > maxArea)     maxArea     = curArea;
620             if (curAverage > maxAverage) maxAverage = curAverage;
621             if (curDistance > maxDistance) maxDistance = curDistance;
622             if (curRelerr > maxRelerr) maxRelerr = curRelerr;
623             if (curVariance > maxVariance) maxVariance = curVariance;
624             if (curStddev > maxStddev) maxStddev = curStddev;
625
626             if ((*it).hasResidual()) {
627                 curResidual = (*it).getResidual();
628                 if (minResidual < 0) { // this is the first residual in measurements
629                     minResidual = maxResidual = curResidual;
630                 } else {
631                     if (curResidual < minResidual) minResidual = curResidual;
632                     if (curResidual > maxResidual) maxResidual = curResidual;
633                 }
634             }
635             if ((*it).hasKullback()) {
636                 curKullback = (*it).getKullback();
637                 if (minKullback < 0) { // this is the first kl distance in measurements
638                     minKullback = maxKullback = curKullback;
639                 } else {
640                     if (curKullback < minKullback) minKullback = curKullback;
641                     if (curKullback > maxKullback) maxKullback = curKullback;
642                 }
643             }
644         } // --foreach measurement
645         return true;
646     } // --globmeaset::calculate_extrema()
647
648     /** these functions return appropriate domain extrema from a single execution of an algorithm */
649     int getMinIter() {
650         if (!extrema_calculated)
651             calculate_extrema();
652         return minIter;
653     } // globmeaset::getMinIter()
654
655     int getMaxIter() {
656         if (!extrema_calculated)
657             calculate_extrema();
658         return maxIter;
659     } // globmeaset::getMaxIter()
660
661     /** these functions return appropriate range extrema from a single execution of an algorithm
662         All will calculate_extrema() with no-args (entire domain) if
663         it has never been called (with any set of arguments, and for a valid set)
664      */
665     double getMinAverage() {
666         if (!extrema_calculated)
667             calculate_extrema();
668         return minAverage;
669     } // globmeaset::getMinAvarage()
670
671     double getMaxAverage() {
672         if (!extrema_calculated)
673             calculate_extrema();
674         return maxAverage;
675     }
676
677     double getMinDistance() {
678         if (extrema_calculated || calculate_extrema())
679             return minDistance;
680         else return -1.0;
681     }
682
683     double getMaxDistance() {
684         if (extrema_calculated || calculate_extrema())
685             return maxDistance;
686         else return -1.0;
687     }
688
689     double getMinRelerr() {
690         if (extrema_calculated || calculate_extrema())
691             return minRelerr;
692         else return -1.0;
693     }
694
695     double getMaxRelerr() {
696         if (extrema_calculated || calculate_extrema())
697             return maxRelerr;
698         else return -1.0;
699     }
700
701     double getMinVariance() {
702         if (extrema_calculated || calculate_extrema())
703             return minVariance;
704         else return -1.0;
705     }
706
707     double getMaxVariance() {
708         if (extrema_calculated || calculate_extrema())
709             return maxVariance;
710         else return -1.0;
711     }
712
713     double getMinStddev() {
714         if (extrema_calculated || calculate_extrema())
715             return minStddev;
716         else return -1.0;
717     }
718
719     double getMaxStddev() {
720         if (extrema_calculated || calculate_extrema())
721             return maxStddev;
722         else return -1.0;
723     }
724
725     /* both of these return -1.0 if no residual */
726     double getMinResidual() {
727         if (extrema_calculated || calculate_extrema())
728             return minResidual;
729         else return -1.0;
730     }
731
732     double getMinKullback() {
733         if (extrema_calculated || calculate_extrema())
734             return minKullback;
735         else return -1.0;
736     }
737
738     double getMaxResidual() {
739         if (extrema_calculated || calculate_extrema())
740             return maxResidual;
741         else return -1.0;
742     }
743
744     double getMaxKullback() {
745         if (extrema_calculated || calculate_extrema())
746             return maxKullback;
747         else return -1.0;
748     }
749
750     bool hasResidual() { // hack: think about whether this actually works
751         if (extrema_calculated || calculate_extrema())
752             return (-0.1 < minResidual);
753         else return false;
754     }
755
756     bool hasKullback() { // hack: think about whether this actually works
757         if (extrema_calculated || calculate_extrema())
758             return (-0.1 < minKullback);
759         else return false;
760     }
761
762     /** globmeaset::show_all() shows all members of this global measurement set */
763     void show_all() {
764         if (!completed)
765             throw std::logic_error("Must NOT show_all globmeaset before complete() is signalled");
766         // else
767         for (std::deque<globmeas>::iterator mit = measurements.begin();
768                 mit != measurements.end(); mit++) {
769             mit->show_all();
770         }
771     } // --globmeaset::show_all()
772
773     ~globmeaset() {
774         if (std::verbose >= 4)
775             std::cout << "globmeaset " << GMSID << " Dtor" << std::endl;
776     }
777 }; // --class globmeaset
778
779 // unsigned globmeas::NEXT_GMID = 0; // class variable initialization
780
781 /** a PBPmeas corresponds to one line of point-by-point statistics in the eval file */
782 class PBPmeas {
783     // the fields are such that there is no reason for deep copies:
784     //   default assignment and copy constructors are fine.
785     // algname now in PBPmeaset
786     int iter;
787     std::vector<double> e; // it's imperative that this is something variable
788     unsigned PMID;
789     static unsigned NEXT_PMID;
790 public:
791     // pre: line starts with whitespace after algname
792     // pre: line points to a (non-static) buffer
793
794     PBPmeas(measline_t line) {
795         // read line into iter and the e vector:
796         ///  if(std::verbose>=5) std::cout << "In PBPmeas " << (PMID+1) << " ctor" << std::endl;
797         double myDouble;
798         char *p;
799         if (std::verbose >= 6) std::cout << "++ PBPmeas ctor(line)" << std::endl;
800         //    std::cout << "PBPmeas beginning--Line is:" << std::endl << line << std::endl;
801         p = line;
802         while (((*p) == ' ') || ((*p) == '\t')) p++; // death to strtok!
803         if (1 != std::sscanf(p, "%d", &iter))
804             throw std::invalid_argument("line in PBPmeas ctor must start with \
805 integer iter");
806         while ((*p) && ((*p) != ' ') && ((*p) != '\t')) p++; // skip iter
807         while (((*p) == ' ') || ((*p) == '\t')) p++; // skip whitespace after iter
808         while ((*p) && ((*p) != '\n') && ((*p) != '\r')) { // read in each double (might have to find out EOF symbol)
809             if (1 == std::sscanf(p, "%lg", &myDouble)) {
810                 e.push_back(myDouble);
811             }
812             while ((*p) && ((*p) != ' ') && ((*p) != '\t')) p++; // skip double
813             while (((*p) == ' ') || ((*p) == '\t')) p++; // skip whitespace after double
814         }
815         if (e.empty()) {
816             std::cout << "e is empty... Line is:" << std::endl << line << std::endl;
817             throw std::invalid_argument("line arg to PBPmeas ctor must have \
818 at least 1 floating point measurement");
819         }
820         PMID = NEXT_PMID++;
821         if (std::verbose >= 6) std::cout << "-- PBPmeas ctor(line)" << std::endl;
822     } // --PBPmeas ctor
823
824     int getIter() const {
825         return iter;
826     }
827
828     unsigned get_num_Es() const {
829         return ( static_cast<unsigned> (e.size()));
830     } // --PBPmeas::get_num_Es()
831
832     double get_E(unsigned ind) {
833         if (ind >= e.size())
834             throw std::invalid_argument("Bad index to PBPmeas::get_E()");
835         // else
836         return e[ind];
837     } // PBPmeas::get_E()
838
839     void show_all() {
840         std::cout << getIter() << " ";
841         for (std::vector<double>::const_iterator it = e.begin();
842                 it != e.end(); it++) {
843             std::cout << (*it) << " ";
844         }
845         std::cout << std::endl;
846     } // --PBPmeas::show_all()
847
848     ~PBPmeas() {
849         if (std::verbose >= 5) std::cout << "In PBPmeas " << PMID << " Dtor" << std::endl;
850     }
851 }; // --class PBPmeas
852
853 // unsigned PBPmeas::NEXT_PMID = 0;  // class variable initialization
854
855 /** a PBPmeaset is the set of point-by-point statistics for one execution of an algorithm */
856 class PBPmeaset {
857     char algname[5]; // name of the algorithm (4 letters)  (not even necessary)
858     char name[512]; // description of the algorithm
859     execname_t execname;
860     //  QString execname; // name of the execution:
861     // snark can execute same algorithm many times with different parameters
862     std::deque<PBPmeas> measurements; // deque is efficient for adding at end and iterating through
863     std::vector<double> minima; // wrappers around simple built-in types: assume efficient
864     std::vector<double> maxima;
865     int minIter, maxIter;
866     unsigned num_Es;
867     static unsigned NEXT_PMSID;
868     unsigned PMSID;
869     bool completed;
870     bool extrema_calculated;
871 public:
872
873     PBPmeaset(execname_t line) {
874         for (int i = 0; i < 4; i++) algname[i] = 'X';
875         algname[4] = '\0'; // just in case
876         PMSID = NEXT_PMSID++;
877         num_Es = 0;
878         minIter = maxIter = -1;
879         completed = false;
880         extrema_calculated = false;
881
882         memset(name, 0, 512);
883         char *p = line;
884         char *q;
885         q = &(name[0]);
886         static const char *needle = "xecution name:";
887         p = strstr(p, needle);
888         if (p) {
889             p += strlen(needle);
890             while ((' ' == *p) || ('\t' == *p)) p++;
891             for (int i = 0; (i < 490) && (*p) && ('\n' != *p) && ('\r' != *p); i++) {
892                 *q++ = *p++;
893             }
894         }
895         *q = '\0'; // just to be sure
896         /// std::cout << "exec name in PBPmeaset is: `" << name << "'" << std::endl;
897
898         if (std::verbose >= 4) std::cout << "PBPmeaset " << PMSID << " ctor" << std::endl;
899     } // --PBPmeaset ctor
900
901     char* getAlgname() {
902         return &(algname[0]);
903     }
904     // so this is a bit baroque... I guess we won't need the 4-letter algnames after all.
905
906     execname_t getName() {
907         return (&name[0]);
908     }
909
910     /** PBPmeaset::skip_algname() */
911     measline_t skip_algname(measline_t line) {
912         // my overkill implementation of strtok functionality (why? why?)
913         measline_t cursor;
914         //    std::cout<< "Input to skip_algname: " << std::endl << line << std::endl;;
915         cursor = line;
916         while ((' ' == (*cursor)) || ('\t' == (*cursor)))
917             cursor++;
918         if ((!(*cursor)) || !((*cursor) >= 'A') && ((*cursor) <= 'Z'))
919             throw std::invalid_argument("bad line passed into PBPmeaset::skip_algname()");
920         while ((*cursor) && ((*cursor) >= 'A') && ((*cursor) <= 'Z'))
921             cursor++;
922         //    std::cout<< "Returning from skip_algname: " << std::endl << cursor << std::endl;;
923         return cursor;
924     }
925
926     /** PBPmeaset::set_algname() */
927     measline_t set_algname(measline_t line) {
928         measline_t cursor;
929         cursor = line;
930         while ((' ' == *cursor) || ('\t' == *cursor)) cursor++;
931         if (!(*cursor >= 'A') && (*cursor <= 'Z'))
932             throw std::invalid_argument("bad line passed into PBPmeaset::set_algname()");
933         for (int i = 0; i < 4; i++)
934             algname[i] = *cursor++;
935         if ((algname[3] == '\t') || (algname[3] == ' ')) // alg is ART
936             algname[3] = '\0';
937         algname[4] = '\0'; // defensive
938         return cursor;
939     }
940
941     //    void addMeasurement(PBPmeas& p) {
942     //      if(completed)
943     //        throw std::logic_error("Must NOT add to PBPmeaset once complete() is signalled");
944     //      measurements.push_back(p);
945     //    }
946
947     /** PBPmeaset::addMeasurement() */
948     void addMeasurement(measline_t line) {
949         measline_t cursor = line;
950         if (completed)
951             throw std::logic_error("Must NOT add to PBPmeaset once complete() is signalled");
952         if (measurements.empty()) // if this is the first line
953             cursor = set_algname(cursor);
954         else {
955             //      std::cout<< "cursor:" << cursor << std::endl;
956             cursor = skip_algname(cursor);
957             //      std::cout<< "cursor:" << cursor << std::endl;
958         }
959         PBPmeas p(cursor);
960         measurements.push_back(p);
961     }
962
963     void complete() {
964         if (measurements.empty()) {
965             throw std::logic_error("empty PBPmeaset refused to complete() itself");
966         }
967         // else
968         if (completed)
969             throw std::logic_error("complete() already signalled for this PBPmeaset, must NOT signal again.");
970         // else
971         completed = true;
972     }
973
974     /** PBPmeaset::isComplete() whether or not this point-by-point measurement set has been completed */
975     bool isComplete() const {
976         return completed;
977     } // PBPmeaset::isComplete()
978
979     /** ++PBPmeaset::get_num_Es() returns number of fields */
980     unsigned get_num_Es() {
981         if (measurements.empty()) {
982             num_Es = 0;
983         } else {
984             num_Es = measurements[0].get_num_Es(); // guaranteed to be the same in all
985         }
986         return num_Es;
987     } // --PBPmeaset::get_num_Es()
988
989     /** PBPmeaset::calculate_extrema(), to be called as 0-arg or 3-arg
990         returns true if input iteration range intersects with data's iteration range ("data domain")
991         makes the assumption that iterations increase in a PBPmeaset (such as (*this) )
992      */
993     bool calculate_extrema(bool restrict_domain = false, int min_it_arg = 0, int max_it_arg = 0) {
994         if (!completed)
995             throw std::logic_error("Must NOT calculate extrema of PBPmeaset before complete() is signalled");
996         // else
997         if (0 == get_num_Es())
998             throw std::logic_error("CANNOT calculate anything for PBPmeaset with no entries!");
999         // else
1000         extrema_calculated = true; // intentionally set this to true even if return false
1001         std::deque<PBPmeas>::iterator it = measurements.begin();
1002         if (restrict_domain) {
1003             while ((it != measurements.end()) && (min_it_arg > (*it).getIter()))
1004                 it++;
1005             if (it == measurements.end())
1006                 return false;
1007         }
1008         minIter = maxIter = (*it).getIter();
1009         for (unsigned myInd = 0; myInd < num_Es; myInd++) {
1010             double cur_E = (*it).get_E(myInd);
1011             minima.push_back(cur_E);
1012             maxima.push_back(cur_E);
1013         }
1014         it++;
1015         for (; it != measurements.end(); it++) { // executes 0 or more times
1016             if (restrict_domain && (max_it_arg < (*it).getIter()))
1017                 break;
1018             maxIter = (*it).getIter(); // last of the small ones
1019             for (unsigned myInd = 0; myInd < num_Es; myInd++) {
1020                 double cur_E = (*it).get_E(myInd);
1021                 if (cur_E < minima[myInd]) minima[myInd] = cur_E;
1022                 if (cur_E > maxima[myInd]) maxima[myInd] = cur_E;
1023             }
1024         }
1025         return true;
1026     } // --PBPmeaset::calculate_extrema()
1027
1028     int getMinIter() {
1029         if (!completed)
1030             throw std::logic_error("getMinIter() MUST not be called before complete() is signalled in PBPmeaset");
1031         if (extrema_calculated) // || calculate_extrema())
1032             return minIter; ///// control shouldn't reach the next line, just defensiveness
1033         else return -1;
1034     } // --PBPmeaset::getMinIter()
1035
1036     int getMaxIter() {
1037         if (!completed)
1038             throw std::logic_error("getMaxIter() MUST not be called before complete() is signalled in PBPmeaset");
1039         if (extrema_calculated) // || calculate_extrema())
1040             return maxIter;
1041         else return -1;
1042     } // --PBPmeaset::getMaxIter()
1043
1044     double getMinE(unsigned ind) {
1045         if (!completed)
1046             throw std::logic_error("getMinE() MUST not be called before complete() is signalled in PBPmeaset");
1047         // else
1048         if (!extrema_calculated)
1049             calculate_extrema(); // which calculates num_Es
1050         if (0 == num_Es)
1051             throw std::logic_error("num_Es cannot be 0 in PBPmeaset::getMinE()");
1052         // else
1053         if (ind >= num_Es)
1054             throw std::invalid_argument("bad parameter to getMinE");
1055         // else
1056         return minima[ind];
1057     } // --PBPmeaset::getMinE()
1058
1059     double getMaxE(unsigned ind) {
1060         if (!completed)
1061             throw std::logic_error("getMaxE() MUST not be called before complete() is signalled in PBPmeaset");
1062         // else
1063         if (!extrema_calculated)
1064             calculate_extrema(); // which calculates num_Es
1065         if (0 == num_Es)
1066             throw std::logic_error("num_Es cannot be 0 in PBPmeaset::getMinE()");
1067         // else
1068         if (ind >= num_Es)
1069             throw std::invalid_argument("bad parameter to getMaxE");
1070         // else
1071         return maxima[ind];
1072     } // --PBPmeaset::getMaxE()
1073
1074     /** shows the extrema of a PBP measurement set (due to a single execution of a single algorithm) */
1075     void show_extrema() {
1076         if (!completed)
1077             throw std::logic_error("Must NOT show extrema of PBPmeaset before complete() is signalled");
1078         if (!extrema_calculated) calculate_extrema(); // the order matters here
1079         if (minima.size() != maxima.size()) // won't really happen
1080             throw std::logic_error("minima and maxima of a PBPmeaset MUST have same size in show_extrema()");
1081         for (unsigned i = 0; i < minima.size(); i++) {
1082             std::cout << minima[i] << " " << maxima[i] << std::endl;
1083         }
1084     } // --PBPmeaset::show_extrema()
1085
1086     /** shows all measurements of a measurement set (for debugging) */
1087     void show_all() {
1088         if (!completed)
1089             throw std::logic_error("Must NOT show_all for PBPmeaset before complete() is signalled");
1090         for (std::deque<PBPmeas>::iterator mit = measurements.begin();
1091                 mit != measurements.end(); mit++) {
1092             mit->show_all();
1093         }
1094     } // --PBPmeaset::show_all()
1095
1096     void addPBPVarLine(line_real_set_t& LRS, unsigned PBPYVar) {
1097         line_real_t LR(getName());
1098         for (std::deque<PBPmeas>::iterator it = measurements.begin();
1099                 it != measurements.end(); it++) {
1100             LR.add(it->getIter(), it->get_E(PBPYVar));
1101         }
1102         if (!LR.empty()) LRS.add(LR);
1103     } // --PBPmeset::addPBPVarLine()
1104
1105     /** PBPmeaset destructor */
1106     ~PBPmeaset() {
1107         if (std::verbose >= 4) std::cout << "PBPmeaset " << PMSID << " Dtor" << std::endl;
1108     }
1109 }; // --class PBPmeaset
1110
1111 // unsigned PBPmeaset::NEXT_PMSID = 0; // class variable initialization
1112
1113 /** contains PBPmeasets and globmeasets that appear in a single EVALUATE result */
1114 class eval_execution {
1115     std::deque<globmeaset> globmeasets;
1116     std::deque<PBPmeaset> PBPmeasets;
1117     bool completed;
1118     bool global_extrema_calculated;
1119     bool PBP_extrema_calculated;
1120     // extrama... none calculated until eval_execution is 'completed', all calculated at once.
1121     // first the global extrema
1122     int minIter, maxIter;
1123     double minAverage, maxAverage, minDistance, maxDistance, minRelerr, maxRelerr;
1124     double minVariance, maxVariance, minStddev, maxStddev, minResidual, maxResidual, minKullback, maxKullback;
1125     // then the PBP extrema...
1126     std::vector<double> PBP_minima; // minima and maxima of each E(0)..E(N-1), N not varying within an eval file.
1127     std::vector<double> PBP_maxima; // calculated over ALL algorithm execution/iterations in this EVALUATE
1128     unsigned num_Es; // 'N' in comment above
1129     phantomeas* phantomeasp; // will be added directly...
1130     // e.g., PBP_minima[2] is the minimum value of all E(2) in all PBPmeasets.
1131     static unsigned NEXT_EEID;
1132     unsigned EEID;
1133     char name[512];
1134 public:
1135
1136     eval_execution() {
1137         EEID = NEXT_EEID++;
1138         completed = global_extrema_calculated = PBP_extrema_calculated = false;
1139         phantomeasp = 0;
1140         num_Es = 0;
1141         minResidual = maxResidual = -1.0; // must initialize to negative value
1142         minKullback = maxKullback = -1.0;
1143         memset(name, 0, 512);
1144     } // --eval_execution ctor
1145
1146     eval_execution(execname_t line) {
1147         ///    std::cout << "++eval_execution::eval_execution(), line is " << line;
1148         EEID = NEXT_EEID++;
1149         completed = global_extrema_calculated = PBP_extrema_calculated = false;
1150         phantomeasp = 0;
1151         num_Es = 0;
1152         minResidual = maxResidual = -1.0; // must initialize to negative value
1153         minKullback = maxKullback = -1.0; // must initialize to negative value
1154         char *p = line;
1155         char *q;
1156         q = &(name[0]);
1157         static const char *needle = "valuation name:";
1158         p = strstr(p, needle); // just in case of preceding whitespace
1159         memset(q, 0, 512); // sort of gratuitous
1160         q = &(name[0]);
1161         if (p) {
1162             p += strlen(needle);
1163             while ((' ' == *p) || ('\t' == *p)) p++;
1164             for (int i = 0; (i < 490) && (*p) && ('\n' != *p) && ('\r' != *p); i++) {
1165                 *q++ = *p++;
1166             }
1167         }
1168         *q = '\0'; // just to be sure
1169         ///    std::cout << "--eval_execution::eval_execution(), name is " << (&(name[0])) << std::endl;
1170     } // --eval_execution ctor
1171
1172     execname_t getName() {
1173         return static_cast<execname_t> (&(name[0]));
1174     } // --eval_execution::getName()
1175
1176     void set_phantom(phantomeas* phanp) { // by pointer!!!
1177         phantomeasp = phanp;
1178     } // eval_execution::set_phantom()
1179
1180     void new_globmeaset(execname_t line) {
1181         if (std::verbose >= 3)
1182             std::cout << "++ eval_execution::new_globmeaset()" << std::endl;
1183         if (completed)
1184             throw std::logic_error("eval_execution::complete() already signalled in eval_execution::new_globmeaset().");
1185         // else
1186         if (!globmeasets.empty()) {
1187             globmeasets.back().complete();
1188         }
1189         globmeaset g(line);
1190         globmeasets.push_back(g);
1191         if (std::verbose >= 3) std::cout << "-- eval_execution::new_globmeaset()" << std::endl;
1192     } // eval_execution::new_globmeaset()
1193
1194     void add_to_globmeaset(measline_t line) {
1195         if (std::verbose >= 4)
1196             std::cout << "++ eval_execution::add_to_globmeaset(line)" << std::endl;
1197         if (completed)
1198             throw std::logic_error("eval_execution::complete() already signalled in eval_execution::add_to_globmeaset().");
1199         // else
1200         if (!hasGlobal())
1201             throw std::logic_error("attempting to add to globmeaset of eval_execution where none exist");
1202         globmeasets.back().addMeasurement(line);
1203         if (std::verbose >= 4)
1204             std::cout << "-- eval_execution::add_to_globmeaset(line)" << std::endl;
1205     }
1206
1207     void new_PBPmeaset(execname_t line) {
1208         if (completed)
1209             throw std::logic_error("eval_execution::complete() already signalled in eval_execution::new_PBPmeaset().");
1210         // else
1211         if (!PBPmeasets.empty()) {
1212             PBPmeasets.back().complete();
1213         }
1214         PBPmeaset p(line);
1215         PBPmeasets.push_back(p);
1216     } // --eval_execution::new_PBPmeaset()
1217
1218     void add_to_PBPmeaset(measline_t line) {
1219         if (completed)
1220             throw std::logic_error("eval_execution::complete() already signalled in eval_execution::add_to_PBPmeaset().");
1221         // else
1222         if (!hasPBP())
1223             throw std::logic_error("attempting to add to PBPmeaset of eval execution where none exist");
1224         // else
1225         PBPmeasets.back().addMeasurement(line); // add measurement to last PBPmeaset
1226     } // --eval_execution::add_to_PBPmeaset()
1227
1228     unsigned get_num_globmeasets() const {
1229         return static_cast<unsigned> (globmeasets.size());
1230     }
1231
1232     unsigned get_num_PBPmeasets() const {
1233         return static_cast<unsigned> (PBPmeasets.size());
1234     }
1235
1236     bool hasGlobal() const {
1237         return (!(globmeasets.empty()));
1238     } // eval_execution::hasGlobal()
1239
1240     bool hasPBP() const {
1241         return (!(PBPmeasets.empty()));
1242     } // eval_execution::hasPBP()
1243
1244     /** Tell this eval_execution object that no more entries will be added to it, and calculations may begin */
1245     void complete() { // verb
1246         if ((!hasGlobal()) && (!hasPBP()))
1247             throw std::logic_error("eval_execution with NOTHING in it was asked to complete() itself!");
1248         // else
1249         if (completed)
1250             throw std::logic_error("attempt to complete() same eval execution twice!");
1251         // else
1252         completed = true;
1253         if (hasGlobal()) {
1254             if (std::verbose >= 3) std::cout << "calling calculate_global_extrema()" << std::endl;
1255             globmeasets.back().complete();
1256             calculate_global_extrema(); // a good place to do this. (is it?)
1257             if (std::verbose >= 3) std::cout << "returned from calculate_global_extrema()" << std::endl;
1258         }
1259         if (hasPBP()) {
1260             PBPmeasets.back().complete();
1261             if (std::verbose >= 3) std::cout << "calling calculate_PBP_extrema()" << std::endl;
1262             calculate_PBP_extrema(); // " " " " " "
1263             if (std::verbose >= 3) std::cout << "returned from calculate_PBP_extrema()" << std::endl;
1264         }
1265     } // --eval_execution::complete()
1266
1267     /** eval_execution::isComplete()
1268         for debugging--ask the eval_execution object whether it has been told that no more data will be added to it */
1269     bool isComplete() const {
1270         return completed;
1271     } // --eval_execution::isComplete()
1272
1273     /** eval_execution::calculate_global_extrema()
1274         calculates global extrema of ALL global measurement sets in this EVALUATE execution
1275         called with 0 or 3 args meaningfully: 0-arg means "calculate over ALL data"         */
1276     bool calculate_global_extrema(bool restrict_domain = false, int min_it_arg = 0, int max_it_arg = 0) {
1277         ///    if(global_extrema_calculated) return false;
1278         if (!completed)
1279             throw std::logic_error("Must NOT calculate extrema of globmeaset before complete() is signalled");
1280         // else
1281         if (!hasGlobal())
1282             throw std::logic_error("Must NOT calculate extrema of empty globmeaset");
1283         // else
1284         std::deque<globmeaset>::iterator it = globmeasets.begin();
1285         // guaranteed to exist and point to an actual globmeaset if control reached here
1286         // skip while current globmeaset's domain does not intersect with input domain
1287         // "allows" to recalculate global extrema regardless
1288         while ((it != globmeasets.end()) &&
1289                 !((*it).calculate_extrema(restrict_domain, min_it_arg, max_it_arg))) {
1290             it++; // boolean expression of while has intentional and possibly necessary side effect
1291         }
1292         if (it == globmeasets.end())
1293             return false; // no globmeaset agrees with domain!  unbelievable!
1294         // else
1295         minIter = (*it).getMinIter(); // return value will automagically be right due to
1296         maxIter = (*it).getMaxIter(); // the above globmeaset::calculate_extrema() call (first that succeeded)
1297
1298         minAverage = (*it).getMinAverage();
1299         minDistance = (*it).getMinDistance();
1300         minRelerr = (*it).getMinRelerr();
1301         minVariance = (*it).getMinVariance();
1302         minStddev = (*it).getMinStddev();
1303
1304         maxAverage = (*it).getMaxAverage();
1305         maxDistance = (*it).getMaxDistance();
1306         maxRelerr = (*it).getMaxRelerr();
1307         maxVariance = (*it).getMaxVariance();
1308         maxStddev = (*it).getMaxStddev();
1309
1310         double tmp;
1311         if (phantomeasp) {
1312             if (minAverage > (tmp = phantomeasp->getAverage())) minAverage = tmp;
1313             else if (maxAverage < tmp) maxAverage = tmp;
1314
1315             if (minVariance > (tmp = phantomeasp->getVariance())) minVariance = tmp;
1316             else if (maxVariance < tmp) maxVariance = tmp;
1317
1318             if (minStddev > (tmp = phantomeasp->getStddev())) minStddev = tmp;
1319             else if (maxStddev < tmp) maxStddev = tmp;
1320         }
1321
1322         if ((*it).hasResidual()) { // not necessarily true in the first globmeaset
1323             double tmp;
1324             minResidual = (*it).getMinResidual(); // won't be nonnegative
1325             maxResidual = (*it).getMaxResidual(); // won't be nonnegative
1326             if (phantomeasp && (phantomeasp->hasResidual())) {
1327                 if (minResidual > (tmp = phantomeasp->getResidual())) minResidual = tmp;
1328                 else if (maxResidual < tmp) maxResidual = tmp;
1329             }
1330         }
1331
1332         if ((*it).hasKullback()) { // not necessarily true in the first globmeaset
1333             double tmp;
1334             minKullback = (*it).getMinKullback(); // won't be nonnegative
1335             maxKullback = (*it).getMaxKullback(); // won't be nonnegative
1336             if (phantomeasp && (phantomeasp->hasKullback())) {
1337                 if (minKullback > (tmp = phantomeasp->getKullback())) minKullback = tmp;
1338                 else if (maxKullback < tmp) maxKullback = tmp;
1339             }
1340         }
1341         it++;
1342         for (; it != globmeasets.end(); it++) {
1343             if (!((*it).calculate_extrema(restrict_domain, min_it_arg, max_it_arg)))
1344                 continue; // don't update as long as (*it)'s domain does not match the arguments
1345             int tmpi;
1346             if (minIter > (tmpi = ((*it).getMinIter()))) minIter = tmpi;
1347             if (maxIter < (tmpi = ((*it).getMaxIter()))) maxIter = tmpi;
1348
1349             double tmp;
1350             if (minAverage > (tmp = ((*it).getMinAverage()))) minAverage = tmp;
1351             if (minDistance > (tmp = ((*it).getMinDistance()))) minDistance = tmp;
1352             if (minRelerr > (tmp = ((*it).getMinRelerr()))) minRelerr = tmp;
1353             if (minVariance > (tmp = ((*it).getMinVariance()))) minVariance = tmp;
1354             if (minStddev > (tmp = ((*it).getMinStddev()))) minStddev = tmp;
1355
1356             if (maxAverage < (tmp = ((*it).getMaxAverage()))) maxAverage = tmp;
1357             if (maxDistance < (tmp = ((*it).getMaxDistance()))) maxDistance = tmp;
1358             if (maxRelerr < (tmp = ((*it).getMaxRelerr()))) maxRelerr = tmp;
1359             if (maxVariance < (tmp = ((*it).getMaxVariance()))) maxVariance = tmp;
1360             if (maxStddev < (tmp = ((*it).getMaxStddev()))) maxStddev = tmp;
1361
1362             if ((*it).hasResidual()) {
1363                 if (minResidual < 0) { // this is the first globmeaset with residual
1364                     minResidual = (*it).getMinResidual();
1365                     maxResidual = (*it).getMaxResidual();
1366                 } else { // we have seen a globmeaset with residual before and now seeing another
1367                     double tmp;
1368                     if (minResidual > (tmp = ((*it).getMinResidual()))) minResidual = tmp;
1369                     if (maxResidual < (tmp = ((*it).getMaxResidual()))) maxResidual = tmp;
1370                 }
1371             }
1372             if ((*it).hasKullback()) {
1373                 if (minKullback < 0) { // this is the first globmeaset with kl distance
1374                     minKullback = (*it).getMinKullback();
1375                     maxKullback = (*it).getMaxKullback();
1376                 } else { // we have seen a globmeaset with kl distance before and now seeing another
1377                     double tmp;
1378                     if (minKullback > (tmp = ((*it).getMinKullback()))) minKullback = tmp;
1379                     if (maxKullback < (tmp = ((*it).getMaxKullback()))) maxKullback = tmp;
1380                 }
1381             }
1382         } // --foreach globmeaset
1383         global_extrema_calculated = true;
1384         return true;
1385     } // --eval_execution::calculate_global_extrema()
1386
1387     /** These require global measurements' extrema to have been calculated */
1388     double getMinAverage() {
1389         if (!hasGlobal())
1390             throw std::logic_error("hasGlobal() is false in eval_execution::getMinAverage()");
1391         if (!completed)
1392             throw std::logic_error("attempt to get info from incomplete eval_execution");
1393         return minAverage;
1394     }
1395
1396     double getMaxAverage() {
1397         if (!hasGlobal())
1398             throw std::logic_error("hasGlobal() is false in eval_execution::getMaxAverage()");
1399         if (!completed)
1400             throw std::logic_error("attempt to get info from incomplete eval_execution");
1401         return maxAverage;
1402     }
1403
1404     double getMinDistance() {
1405         if (!hasGlobal())
1406             throw std::logic_error("hasGlobal() is false in eval_execution::getMinDistance()");
1407         if (!completed)
1408             throw std::logic_error("attempt to get info from incomplete eval_execution");
1409         return minDistance;
1410     } // --eval_execution::getMinDistance()
1411
1412     double getMaxDistance() {
1413         if (!hasGlobal())
1414             throw std::logic_error("hasGlobal() is false in eval_execution::getMaxDistance()");
1415         if (!completed)
1416             throw std::logic_error("attempt to get info from incomplete eval_execution");
1417         return maxDistance;
1418     }
1419
1420     double getMinRelerr() {
1421         if (!hasGlobal())
1422             throw std::logic_error("hasGlobal() is false in eval_execution::getMinRelerr()");
1423         if (!completed)
1424             throw std::logic_error("attempt to get info from incomplete eval_execution");
1425         return minRelerr;
1426     }
1427
1428     double getMaxRelerr() {
1429         if (!hasGlobal())
1430             throw std::logic_error("hasGlobal() is false in eval_execution::getMaxRelerr()");
1431         if (!completed)
1432             throw std::logic_error("attempt to get info from incomplete eval_execution");
1433         return maxRelerr;
1434     } // --eval_execution::getMaxRelerr()
1435
1436     double getMinVariance() {
1437         if (!hasGlobal())
1438             throw std::logic_error("hasGlobal() is false in eval_execution::getMinVariance()");
1439         if (!completed)
1440             throw std::logic_error("attempt to get info from incomplete eval_execution");
1441         return minVariance;
1442     }
1443
1444     double getMaxVariance() {
1445         if (!hasGlobal())
1446             throw std::logic_error("hasGlobal() is false in eval_execution::getMaxVariance()");
1447         if (!completed)
1448             throw std::logic_error("attempt to get info from incomplete eval_execution");
1449         return maxVariance;
1450     }
1451
1452     double getMinStddev() {
1453         if (!hasGlobal())
1454             throw std::logic_error("hasGlobal() is false in eval_execution::getMinStddev()");
1455         if (!completed)
1456             throw std::logic_error("attempt to get info from incomplete eval_execution");
1457         return minStddev;
1458     }
1459
1460     double getMaxStddev() {
1461         if (!hasGlobal())
1462             throw std::logic_error("hasGlobal() is false in eval_execution::getMaxStddev()");
1463         if (!completed)
1464             throw std::logic_error("attempt to get info from incomplete eval_execution");
1465         return maxStddev;
1466     } // --eval_execution::getMaxStddev()
1467
1468     bool hasResidual() { // true if some of its globmeasets have some residual entry
1469         if (!hasGlobal())
1470             throw std::logic_error("hasGlobal() is false in eval_execution::getMaxResidual()");
1471         if (!completed)
1472             throw std::logic_error("attempt to get info from incomplete eval_execution");
1473         return (-0.5 < minResidual);
1474     }
1475
1476     bool hasKullback() { // true if some of its globmeasets have some kl distance entries
1477         if (!hasGlobal())
1478             throw std::logic_error("hasGlobal() is false in eval_execution::getMaxKullback()");
1479         if (!completed)
1480             throw std::logic_error("attempt to get info from incomplete eval_execution");
1481         return (-0.5 < minKullback);
1482     }
1483
1484     // pre: do NOT call these before calling hasResidual() and making sure it's true
1485
1486     double getMinResidual() {
1487         if (!hasGlobal())
1488             throw std::logic_error("hasGlobal() is false in eval_execution::getMinResidual()");
1489         if (!hasResidual())
1490             throw std::logic_error("hasResidual() is false in eval_execution::getMinResidual()");
1491         return minResidual;
1492     }
1493
1494     double getMinKullback() {
1495         if (!hasGlobal())
1496             throw std::logic_error("hasGlobal() is false in eval_execution::getMinKullback()");
1497         if (!hasKullback())
1498             throw std::logic_error("hasKullback() is false in eval_execution::getMinKullback()");
1499         return minKullback;
1500     }
1501
1502     double getMaxResidual() {
1503         if (!hasGlobal())
1504             throw std::logic_error("hasGlobal() is false in eval_execution::getMaxResidual()");
1505         if (!hasResidual())
1506             throw std::logic_error("hasResidual() is false in eval_execution::getMaxResidual()");
1507         return maxResidual;
1508     }
1509
1510     double getMaxKullback() {
1511         if (!hasGlobal())
1512             throw std::logic_error("hasGlobal() is false in eval_execution::getMaxKullback()");
1513         if (!hasKullback())
1514             throw std::logic_error("hasKullback() is false in eval_execution::getMaxKullback()");
1515         return maxKullback;
1516     }
1517
1518     /** eval_execution::calculate_PBP_extrema() */
1519     bool calculate_PBP_extrema(bool restrict_domain = false, int min_it_arg = 0, int max_it_arg = 0) {
1520         /// if(PBP_extrema_calculated) return; // not anymore.
1521         ///// else
1522         if (std::verbose >= 5) std::cout << "++ calculate_PBP_extrema()" << std::endl;
1523         //   PBP_minima.resize(0);
1524         //   PBP_maxima.resize(0);
1525         PBP_minima.clear();
1526         PBP_maxima.clear();
1527         if (!completed) {
1528             std::cerr << "Attempt to calculate_PBP_extrema() before signaling complete() to evaluate_execution";
1529             throw std::logic_error("Attempt to calculate_PBP_extrema() before signaling complete() to evaluate_execution");
1530         }
1531         // else
1532         if (!hasPBP()) {
1533             std::cerr << "Attempt to calculate_PBP_extrema() when no point-by-point data in this evaluate_execution";
1534             throw std::logic_error("Attempt to calculate_PBP_extrema() when no point-by-point data in this evaluate_execution");
1535         }
1536         // else
1537         PBP_extrema_calculated = true;
1538         std::deque<PBPmeaset>::iterator it = PBPmeasets.begin();
1539         num_Es = (*it).get_num_Es(); // this is the same throughout the file.  can use it even if we chuck the data.
1540         while ((it != PBPmeasets.end()) &&
1541                 !((*it).calculate_extrema(restrict_domain, min_it_arg, max_it_arg))) {
1542             it++;
1543         }
1544         if (it == PBPmeasets.end())
1545             return false;
1546         // else
1547         minIter = (*it).getMinIter();
1548         maxIter = (*it).getMaxIter();
1549         PBP_minima.resize(num_Es);
1550         PBP_maxima.resize(num_Es);
1551         for (unsigned myInd = 0; myInd < num_Es; myInd++) {
1552             PBP_minima[myInd] = (*it).getMinE(myInd);
1553             //      PBP_maxima.push_back( (*it).getMaxE(myInd) );
1554             PBP_maxima[myInd] = (*it).getMaxE(myInd);
1555         }
1556         it++;
1557         for (; it != PBPmeasets.end(); it++) {
1558             // empty domain intersection
1559             if (!((*it).calculate_extrema(restrict_domain, min_it_arg, max_it_arg)))
1560                 continue;
1561             //  now:  min_it_arg >= (*it).getMinIter() and max_it_arg <= (*it).getMaxIter()
1562             int tmpi;
1563             if (minIter > (tmpi = (*it).getMinIter())) minIter = tmpi;
1564             if (maxIter < (tmpi = (*it).getMaxIter())) maxIter = tmpi;
1565             for (unsigned myInd = 0; myInd < num_Es; myInd++) {
1566                 double curMinE, curMaxE;
1567                 if (PBP_minima[myInd] > (curMinE = (*it).getMinE(myInd))) PBP_minima[myInd] = curMinE;
1568                 if (PBP_maxima[myInd] < (curMaxE = (*it).getMaxE(myInd))) PBP_maxima[myInd] = curMaxE;
1569             }
1570         }
1571         if (std::verbose >= 5) std::cout << "-- calculate_PBP_extrema()" << std::endl;
1572         return true;
1573     } // --eval_execution::calculate_PBP_extrema()
1574
1575     /** for getMinIter() and getMaxIter(), global and PBP agree (given same restriction) */
1576
1577     /** however, there is no guarantee that both are present.                            */
1578     int getMinIter() {
1579         if (!completed)
1580             throw std::logic_error("attempt to get info from incomplete eval_execution");
1581         // else
1582         if (!global_extrema_calculated && !PBP_extrema_calculated) {
1583             if (hasGlobal()) {
1584                 calculate_global_extrema();
1585             } else if (hasPBP()) {
1586                 calculate_PBP_extrema();
1587             } else throw std::logic_error("no Global, no PBP in eval_execution::getMinIter()");
1588         }
1589         return minIter;
1590     }
1591
1592     int getMaxIter() {
1593         if (!completed)
1594             throw std::logic_error("attempt to get info from incomplete eval_execution");
1595         // else
1596         if (!global_extrema_calculated && !PBP_extrema_calculated) {
1597             if (hasGlobal()) {
1598                 calculate_global_extrema();
1599             } else if (hasPBP()) {
1600                 calculate_PBP_extrema();
1601             } else throw std::logic_error("no Global, no PBP in eval_execution::getMaxIter()");
1602         }
1603         return maxIter;
1604     }
1605
1606     /** eval_execution::get_num_Es() with possible nasty side effect of recalculating PBP extrema! */
1607     unsigned get_num_Es() {
1608         if (!completed)
1609             throw std::logic_error("get_num_Es() MUST not be called before complete() is signalled in eval_execution");
1610         if (!PBP_extrema_calculated)
1611             calculate_PBP_extrema();
1612         return num_Es; // due to the "side effect" of calling calculate_PBP_extrema
1613     }
1614
1615     /** eval_execution::getMinE() to get minimum of a PBP measure attribute through EVALUATE */
1616     double getMinE(unsigned ind) {
1617         if (!completed)
1618             throw std::logic_error("getMinE() MUST not be called before complete() is signalled in eval_execution");
1619         // else
1620         if (!PBP_extrema_calculated)
1621             calculate_PBP_extrema(); // which calculates num_Es
1622         if (0 == num_Es)
1623             throw std::logic_error("num_Es cannot be 0 in PBPmeaset::getMinE()");
1624         // else
1625         if (ind >= num_Es)
1626             throw std::invalid_argument("bad parameter to getMinE");
1627         // else
1628         return PBP_minima[ind];
1629     } // eval_execution::getMinE()
1630
1631     double getMaxE(unsigned ind) {
1632         if (!completed)
1633             throw std::logic_error("getMinE() MUST not be called before complete() is signalled in PBPmeaset");
1634         // else
1635         if (!PBP_extrema_calculated)
1636             calculate_PBP_extrema(); // which calculates num_Es
1637         if (0 == num_Es)
1638             throw std::logic_error("num_Es cannot be 0 in PBPmeaset::getMaxE()");
1639         // else
1640         if (ind >= num_Es)
1641             throw std::invalid_argument("bad parameter to getMaxE");
1642         // else
1643         return PBP_maxima[ind];
1644     } // eval_execution::getMaxE()
1645
1646     /** debug routine: shows all values in the global measurement sets "recursively" */
1647     void show_all_globs() {
1648         if (!completed) {
1649             //        std::cout << "(cout) about to bail" << std::endl;
1650             //        std::cerr << "(cerr) about to bail" << std::endl;
1651             throw std::logic_error("MUST not call show_all_globs() before signalling complete() to an eval_execution");
1652         }
1653         // else
1654         if (globmeasets.empty()) {
1655             std::cout << "## No glob sets to show in eval exec " << EEID << std::endl;
1656         } else {
1657             std::cout << "=>>=showing all globmeasets in eval exec " << EEID << std::endl;
1658             for (unsigned i = 0; i < get_num_globmeasets(); i++) {
1659                 std::cout << "Showing globmeaset " << i << ":" << std::endl;
1660                 globmeasets[i].show_all();
1661             }
1662             std::cout << "=<<=showed all globmeasets in eval exec " << EEID << std::endl;
1663         }
1664     } // --eval_execution::show_all_globs()
1665
1666     /** debug routine: shows all values in the global measurement sets "recursively" */
1667     void show_all_PBPs() {
1668         if (!completed)
1669             throw std::logic_error("MUST not call show_all_ppbs() before signalling complete() to eval_execution");
1670         // else
1671         if (PBPmeasets.empty()) {
1672             std::cout << "## No PBP sets to show in eval exec " << EEID << std::endl;
1673         } else {
1674             std::cout << "=>>=showing all PBPmeasets in eval exec " << EEID << std::endl;
1675             for (unsigned i = 0; i < get_num_PBPmeasets(); i++) {
1676                 std::cout << "Showing PBPmeaset " << i << ": (algname ["
1677                         << PBPmeasets[i].getAlgname() << "])" << std::endl;
1678                 PBPmeasets[i].show_all();
1679             }
1680             std::cout << "=<<=showed all PBPmeasets in eval exec " << EEID << std::endl;
1681         }
1682     } // --eval_execution::show_all_PBPs()
1683
1684     /** eval_execution::show_extrema() */
1685     void show_extrema() {
1686         if (!completed)
1687             throw std::logic_error("Must NOT show extrema of eval_execution before complete() is signalled");
1688         std::cout << "Showing extrema in eval_execution_set among selected eval_executions." << std::endl;
1689         bool successful = false;
1690         if (hasGlobal() && calculate_global_extrema()) {
1691             std::cout << "after global calculation: minIter, maxIter: " << minIter << " " << maxIter << std::endl;
1692             std::cout << "minAverage, maxAverage, minDistance, maxDistance, minRelerr, maxRelerr:" << std::endl
1693                     << minAverage << " " << maxAverage << " " << minDistance << " " << maxDistance << " " << minRelerr << " " << maxRelerr;
1694             std::cout << std::endl;
1695             std::cout << "minVariance, maxVariance, minStddev, maxStddev, minResidual, maxResidual, minKullback, maxKullback:" << std::endl
1696                     << minVariance << " " << maxVariance << " " << minStddev << " " << maxStddev << " " << minResidual << " " << maxResidual << " " << minKullback << " " << maxKullback;
1697             std::cout << std::endl;
1698             successful = true;
1699         }
1700
1701         if (hasPBP() && calculate_PBP_extrema()) {
1702             std::cout << "after PBP calculation: minIter, maxIter: " << minIter << " " << maxIter << std::endl;
1703             for (unsigned i = 0; i < num_Es; i++) {
1704                 std::cout << "PBP_minima[" << i << "] = " << PBP_minima[i] << "; "
1705                         << "PBP_maxima[" << i << "] = " << PBP_maxima[i] << std::endl;
1706             }
1707             successful = true;
1708         }
1709         if (!successful) {
1710             std::cout << "Attempts to calculate both global and PBP extrema were unsuccessful in eval_execution." << std::endl;
1711         }
1712     } // --eval_execution::show_extrema()
1713
1714     void show_all() {
1715         std::cout << "==>>>==entering show_all() for eval exec " << EEID << std::endl;
1716         show_all_globs();
1717         show_all_PBPs();
1718         std::cout << "==<<<==leaving show_all() for eval exec " << EEID << std::endl;
1719     } // --eval_execution::show_all()
1720
1721     void addPBPVarLines(line_real_set_t& LRS, unsigned PBPYVar) {
1722         for (std::deque<PBPmeaset>::iterator it = PBPmeasets.begin();
1723                 it != PBPmeasets.end(); it++) {
1724             it->addPBPVarLine(LRS, PBPYVar);
1725         }
1726     } // --eval_execution::addPBPVarLines()
1727
1728     void addGlobVarLines(line_real_set_t& LRS, globalYVar_t globalYVar) {
1729         for (std::deque<globmeaset>::iterator it = globmeasets.begin();
1730                 it != globmeasets.end(); it++) {
1731             it->addGlobVarLine(LRS, globalYVar);
1732         }
1733     } // --eval_execution::addGlobVarLines()
1734
1735 }; // --class eval_execution
1736
1737 // unsigned eval_execution::NEXT_EEID = 0; // class variable initialization
1738
1739 /** eval_execution_set: superstructure capable of holding information 
1740     given by many eval executions, an entire eval08 file                 */
1741 //  class eval_execution_set {
1742 //    std::deque<eval_execution> execs; // entire output of snark14 EVALUATE executions
1743 //    std::vector<bool> selected; // holds which execs are selected by snark14Display user
1744 //    phantomeas* phantomeasp;
1745 //    bool completed; // holds whether creation of execs is complete (is this really necessary here?)
1746 //    bool extrema_calculated; // holds whether extrema are calculated (ditto.)
1747 //    bool same_x_forall;  // for iter, plotted on x-axis
1748 //    bool same_y_forall;  // for whatever it is that is requested for plotting on y-axis
1749 //    // (almost the same as for eval_execution) extrama...
1750 //    // first the global extrema
1751 //    int minIter, maxIter;
1752 //    double minAverage, maxAverage, minDistance, maxDistance, minRelerr, maxRelerr;
1753 //    double minVariance, maxVariance, minStddev, maxStddev, minResidual, maxResidual;
1754 //    // then the PBP extrema...
1755 //    std::vector<double> PBP_minima; // minima and maxima of each E(0)..E(N-1), N not varying within an eval file.
1756 //    std::vector<double> PBP_maxima; // to be calculated over ALL EVALUATE calls, depending.
1757 //    unsigned num_Es; // 'N' in comment above
1758 //    // e.g., PBP_minima[2] is the minimum value of all E(2) in all PBPmeasets in all execs.
1759
1760 eval_execution_set::eval_execution_set() {
1761     completed = extrema_calculated = false;
1762     same_x_forall = same_y_forall = false; // initialize to use "locally" calculated domain/range bounds
1763     selectionHasResidualvar = false;
1764     selectionHasKullbackvar = false;
1765     phantomeasp = 0;
1766 } // eval_execution_set() ctor
1767
1768 //   void new_exec(eval_execution &ev) {
1769 //     // pseudocode
1770 //     execs.push_back(ev);
1771 //     selected.push_back(false);
1772 //   }
1773
1774 // void eval_execution_set::new_exec() {
1775 //   if (!execs.empty()) {
1776 //     execs.back().set_phantom(phantomeasp);
1777 //     execs.back().complete();
1778 //   }
1779 //   eval_execution exec;
1780 //   execs.push_back(exec);
1781 //   selected.push_back(false);
1782 // }
1783
1784 void eval_execution_set::new_exec(execname_t name) {
1785     if (!execs.empty()) {
1786         execs.back().set_phantom(phantomeasp);
1787         execs.back().complete();
1788     }
1789     eval_execution exec(name);
1790     execs.push_back(exec);
1791     selected.push_back(false);
1792 }
1793
1794 void eval_execution_set::new_globmeaset(execname_t line) {
1795     if (execs.empty())
1796         throw std::logic_error("call to eval_execution_set::new_globmeaset() before ::new_exec()");
1797     // else
1798     execs.back().new_globmeaset(line);
1799 }
1800
1801 void eval_execution_set::add_to_globmeaset(measline_t line) {
1802     if (execs.empty())
1803         throw std::logic_error("call to eval_execution_set::add_to_globmeaset() before ::new_exec()");
1804     execs.back().add_to_globmeaset(line);
1805 }
1806
1807 void eval_execution_set::new_PBPmeaset(execname_t line) {
1808     if (execs.empty())
1809         throw std::logic_error("call to eval_execution_set::new_PBPmeaset() before ::new_exec()");
1810     execs.back().new_PBPmeaset(line);
1811 }
1812
1813 void eval_execution_set::add_to_PBPmeaset(measline_t line) {
1814     if (execs.empty())
1815         throw std::logic_error("call to eval_execution_set::add_to_PBPmeaset() before ::new_exec()");
1816     execs.back().add_to_PBPmeaset(line);
1817 }
1818
1819 /** eval_execution_set::set_phantomeas() sets _the_ phantom measurement of the eval_execution_set
1820     pre: all phantom-related lines in the eval file are identical
1821     barring the possibility of there being residual in some but not others
1822     this function sort of "updates" the value of phantom.
1823     logically, to be considered part of every eval_execution that has at least one globmeaset:
1824     (for applicable fields) both for the purpose of plotting and calculating extrema.
1825     if exists (!=0), DO NOT CHANGE phantomeasp OR YOU'LL SEGFAULT!
1826  */
1827 void eval_execution_set::set_phantomeas(measline_t line) {
1828
1829     if (phantomeasp && phantomeasp->hasResidual() && phantomeasp->hasKullback()) return;
1830     // else
1831     if (!phantomeasp) {
1832         phantomeasp = new phantomeas(line);
1833         return;
1834     }
1835     // else
1836     phantomeas locphan(line);
1837     if (locphan.hasResidual()) {
1838         phantomeasp->setNewResidual(locphan.getResidual()); // set by value
1839     }
1840     if (locphan.hasKullback()) {
1841         phantomeasp->setNewKullback(locphan.getKullback()); // set by value
1842     }
1843 } // --eval_execution_set::set_phantomeas()
1844
1845 bool eval_execution_set::hasPhantom() {
1846     return (0 != phantomeasp);
1847 }
1848
1849 bool eval_execution_set::calculate_global_extrema() {
1850     return calculate_global_extrema(false, 0, 0);
1851 }
1852
1853 /** eval_execution_set::calculate_global_extrema()  */
1854 bool eval_execution_set::calculate_global_extrema(bool restrict_domain, int min_it_arg, int max_it_arg) {
1855     if (!completed)
1856         throw std::logic_error("eval_execution_set::calculate_extrema() cannot be called on incomplete set");
1857     if (selected.size() != execs.size())
1858         throw std::logic_error("selected does not match execs in size");
1859     minResidual = maxResidual = -1.0;
1860     minKullback = maxKullback = -1.0;
1861     bool first_one = true;
1862     unsigned j = 0;
1863     for (std::deque<eval_execution>::iterator it = execs.begin();
1864             it != execs.end(); j++, it++) {
1865         if (selected[j] && ((*it).hasGlobal()) && ((*it).calculate_global_extrema(restrict_domain, min_it_arg, max_it_arg))) {
1866             /// std::cout << "eval_execution_set::calculate_global_extrema() j = " << j << std::endl;
1867             if (first_one) { // for first selected eval_exec with global
1868                 // it is the first one and non-empty intersects with argument domain, if restricted
1869                 minIter = (*it).getMinIter();
1870                 maxIter = (*it).getMaxIter();
1871                 /// std::cout << "minIter: " <<  minIter << ", maxIter: " << maxIter << std::endl;
1872                 minAverage = (*it).getMinAverage();
1873                 minDistance = (*it).getMinDistance();
1874                 minRelerr = (*it).getMinRelerr();
1875                 minVariance = (*it).getMinVariance();
1876                 minStddev = (*it).getMinStddev();
1877
1878                 maxAverage = (*it).getMaxAverage();
1879                 maxDistance = (*it).getMaxDistance();
1880                 maxRelerr = (*it).getMaxRelerr();
1881                 maxVariance = (*it).getMaxVariance();
1882                 maxStddev = (*it).getMaxStddev();
1883
1884                 if ((*it).hasResidual()) { // not necessarily true in the first evaluate
1885                     selectionHasResidualvar = true;
1886                     minResidual = (*it).getMinResidual();
1887                     maxResidual = (*it).getMaxResidual();
1888                 }
1889                 if ((*it).hasKullback()) { // not necessarily true in the first evaluate
1890                     selectionHasKullbackvar = true;
1891                     minKullback = (*it).getMinKullback();
1892                     maxKullback = (*it).getMaxKullback();
1893                 }
1894                 first_one = false;
1895             } else { // for all other selected eval_execs with global with matching domain
1896                 int tmpi;
1897                 if (minIter > (tmpi = (*it).getMinIter())) minIter = tmpi;
1898                 if (maxIter < (tmpi = (*it).getMaxIter())) maxIter = tmpi;
1899                 double tmp;
1900                 if (minAverage > (tmp = ((*it).getMinAverage()))) minAverage = tmp;
1901                 if (minDistance > (tmp = ((*it).getMinDistance()))) minDistance = tmp;
1902                 if (minRelerr > (tmp = ((*it).getMinRelerr()))) minRelerr = tmp;
1903                 if (minVariance > (tmp = ((*it).getMinVariance()))) minVariance = tmp;
1904                 if (minStddev > (tmp = ((*it).getMinStddev()))) minStddev = tmp;
1905
1906                 if (maxAverage < (tmp = ((*it).getMaxAverage()))) maxAverage = tmp;
1907                 if (maxDistance < (tmp = ((*it).getMaxDistance()))) maxDistance = tmp;
1908                 if (maxRelerr < (tmp = ((*it).getMaxRelerr()))) maxRelerr = tmp;
1909                 if (maxVariance < (tmp = ((*it).getMaxVariance()))) maxVariance = tmp;
1910                 if (maxStddev < (tmp = ((*it).getMaxStddev()))) maxStddev = tmp;
1911
1912                 if ((*it).hasResidual()) {
1913                     if (minResidual < 0) { // this is the first globmeaset with residual
1914                         minResidual = (*it).getMinResidual();
1915                         maxResidual = (*it).getMaxResidual();
1916                     } else { // we have seen a globmeaset with residual before and now seeing another
1917                         double tmp;
1918                         if (minResidual > (tmp = ((*it).getMinResidual()))) minResidual = tmp;
1919                         if (maxResidual < (tmp = ((*it).getMaxResidual()))) maxResidual = tmp;
1920                     }
1921                 }
1922                 if ((*it).hasKullback()) {
1923                     if (minKullback < 0) { // this is the first globmeaset with kl distance
1924                         minKullback = (*it).getMinKullback();
1925                         maxKullback = (*it).getMaxKullback();
1926                     } else { // we have seen a globmeaset with kl distance before and now seeing another
1927                         double tmp;
1928                         if (minKullback > (tmp = ((*it).getMinKullback()))) minKullback = tmp;
1929                         if (maxKullback < (tmp = ((*it).getMaxKullback()))) maxKullback = tmp;
1930                     }
1931                 }
1932             } // --not the first one
1933         } // --selected evaluate with global
1934     } // --foreach EVALUATE execution
1935     return (!first_one);
1936     // return true if some execution has global measurements whose domain matches input domain restriction
1937 } // --eval_exec_set::calculate_global_extrema()
1938
1939 bool eval_execution_set::calculate_PBP_extrema() {
1940     return calculate_PBP_extrema(false, 0, 0);
1941 }
1942
1943 /** eval_execution_set::calculate_PBP_extrema()  */
1944 bool eval_execution_set::calculate_PBP_extrema(bool restrict_domain, int min_it_arg, int max_it_arg) {
1945     if (!completed)
1946         throw std::logic_error("eval_execution_set::calculate_extrema() cannot be called on incomplete set");
1947     if (selected.size() != execs.size())
1948         throw std::logic_error("selected does not match execs in size");
1949     num_Es = 0;
1950     //    PBP_minima.resize(0);
1951     //    PBP_maxima.resize(0);
1952     PBP_minima.clear();
1953     PBP_maxima.clear();
1954     bool first_one = true;
1955     unsigned j = 0;
1956     for (std::deque<eval_execution>::iterator it = execs.begin();
1957             it != execs.end(); j++, it++) {
1958         if ((selected[j]) && ((*it).hasPBP()) && ((*it).calculate_PBP_extrema(restrict_domain, min_it_arg, max_it_arg))) {
1959             if (first_one) {
1960                 minIter = (*it).getMinIter();
1961                 maxIter = (*it).getMaxIter();
1962                 num_Es = (*it).get_num_Es(); // this is the same throughout the file.
1963                 PBP_minima.resize(num_Es);
1964                 PBP_maxima.resize(num_Es);
1965                 for (unsigned myInd = 0; myInd < num_Es; myInd++) {
1966                     PBP_minima[myInd] = (*it).getMinE(myInd);
1967                     PBP_maxima[myInd] = (*it).getMaxE(myInd);
1968                 }
1969                 first_one = false;
1970             } else {
1971                 int tmpi;
1972                 if (minIter > (tmpi = (*it).getMinIter())) minIter = tmpi;
1973                 if (maxIter < (tmpi = (*it).getMaxIter())) maxIter = tmpi;
1974                 for (unsigned myInd = 0; myInd < num_Es; myInd++) {
1975                     double tmp;
1976                     if (PBP_minima[myInd] > (tmp = (*it).getMinE(myInd))) PBP_minima[myInd] = tmp;
1977                     if (PBP_maxima[myInd] < (tmp = (*it).getMaxE(myInd))) PBP_maxima[myInd] = tmp;
1978                 }
1979             } // not first one
1980         } // --selected evaluate with point
1981     } // --for
1982     return (!first_one);
1983     // return true if any selected execution has PBP measurements and input domain restriction matches their domain
1984 } // eval_execution_set::calculate_PBP_extrema()
1985
1986 execname_t eval_execution_set::getExecName(unsigned idx) {
1987     return execs[idx].getName();
1988 }
1989
1990 /** by "for all", the selected set of EVALUATE executions are meant.
1991     setSameXForAll(true) to use "global" domain for each plot */
1992 //void eval_execution_set::setSameXForAll(bool val = true) {
1993
1994 void eval_execution_set::setSameXForAll(bool val) {
1995     same_x_forall = val;
1996 }
1997
1998 //void eval_execution_set::setSameYForAll(bool val = true) {
1999
2000 void eval_execution_set::setSameYForAll(bool val) {
2001     same_y_forall = val;
2002 }
2003
2004 bool eval_execution_set::getSameXForAll() {
2005     return same_x_forall;
2006 }
2007
2008 bool eval_execution_set::getSameYForAll() {
2009     return same_y_forall;
2010 }
2011
2012 // i don't even know if this idea will make it to the production version
2013 //void eval_execution_set::useSameExtremaForAll(bool val = true) {
2014
2015 void eval_execution_set::useSameExtremaForAll(bool val) {
2016     setSameXForAll(val);
2017     setSameYForAll(val);
2018 }
2019
2020 void eval_execution_set::useDifferentExtremaForEach() {
2021     useSameExtremaForAll(false);
2022 }
2023
2024 void eval_execution_set::complete() {
2025     if (execs.empty())
2026         throw std::logic_error("attempt to compete() empty eval_execution_set!");
2027     // else
2028     execs.back().set_phantom(phantomeasp);
2029     execs.back().complete();
2030     completed = true;
2031 }
2032
2033 unsigned eval_execution_set::num_eval_execs() {
2034     return static_cast<unsigned> (execs.size());
2035 }
2036
2037 void eval_execution_set::deselect_exec(unsigned idx) {
2038     if (!completed)
2039         throw std::logic_error("Cannot deselect_exec() without having a completed eval_execution_set.");
2040     if (idx >= num_eval_execs())
2041         throw std::invalid_argument("exec index out of range in eval_execution_set::deselect_exec()");
2042     selected[idx] = false;
2043     extrema_calculated = false; // previous extrema calcs annulled
2044 }
2045
2046 void eval_execution_set::select_exec(unsigned idx) { // everything is deselected by default
2047     if (!completed)
2048         throw std::logic_error("Cannot select_exec() without having a completed eval_execution_set.");
2049     if (idx >= num_eval_execs())
2050         throw std::invalid_argument("exec index out of range in eval_execution_set::deselect_exec()");
2051     selected[idx] = true;
2052     extrema_calculated = false; // previous extrema calcs annulled
2053 } // eval_execution_set::select_exec()
2054
2055 void eval_execution_set::deselect_all_execs() {
2056     if (!completed)
2057         throw std::logic_error("Cannot deselect_all_execs() without having a completed eval_execution_set.");
2058     for (std::vector<bool>::iterator it = selected.begin(); it != selected.end(); it++) {
2059         *it = false;
2060     }
2061     extrema_calculated = false; // previous extrema calcs annulled
2062 }
2063
2064 void eval_execution_set::select_all_execs() {
2065     if (!completed)
2066         throw std::logic_error("Cannot select_all_execs() without having a completed eval_execution_set.");
2067     for (std::vector<bool>::iterator it = selected.begin(); it != selected.end(); it++) {
2068         *it = true;
2069     }
2070     extrema_calculated = false; // previous extrema calcs annulled
2071 }
2072
2073 bool eval_execution_set::selectionHasGlobal() {
2074     for (unsigned idx = 0; idx < num_eval_execs(); idx++) {
2075         if ((selected[idx]) && (execs[idx].hasGlobal())) {
2076             return true;
2077         }
2078     }
2079     return false;
2080 }
2081
2082 bool eval_execution_set::selectionHasResidual() {
2083     for (unsigned idx = 0; idx < num_eval_execs(); idx++) {
2084         if ((selected[idx]) && (execs[idx].hasGlobal()) && (execs[idx].hasResidual())) {
2085             return true;
2086         }
2087     }
2088     return false;
2089 }
2090
2091 bool eval_execution_set::selectionHasKullback() {
2092     for (unsigned idx = 0; idx < num_eval_execs(); idx++) {
2093         if ((selected[idx]) && (execs[idx].hasGlobal()) && (execs[idx].hasKullback())) {
2094             return true;
2095         }
2096     }
2097     return false;
2098 }
2099
2100 bool eval_execution_set::selectionHasPBP() {
2101     for (unsigned idx = 0; idx < num_eval_execs(); idx++) {
2102         if ((selected[idx]) && (execs[idx].hasPBP())) {
2103             return true;
2104         }
2105     }
2106     return false;
2107 }
2108
2109 /** eval_execution_set::get_num_Es() returns:
2110     number of PBP fields IF execution selection includes a PBP
2111                        0 otherwise (should? throw exception)
2112  */
2113 unsigned eval_execution_set::get_num_Es() {
2114     for (unsigned idx = 0; idx < num_eval_execs(); idx++) {
2115         if ((selected[idx]) && (execs[idx].hasPBP())) {
2116             return execs[idx].get_num_Es();
2117         }
2118     }
2119     return 0;
2120 }
2121
2122 // really throw exception... arkh.
2123
2124 int eval_execution_set::getMinIterViaGlobal() {
2125     if (calculate_global_extrema())
2126         return minIter;
2127     return -1;
2128 }
2129
2130 int eval_execution_set::getMaxIterViaGlobal() {
2131     if (calculate_global_extrema())
2132         return maxIter;
2133     return -1;
2134 }
2135
2136 int eval_execution_set::getMinIterViaPBP() {
2137     if (calculate_PBP_extrema())
2138         return minIter;
2139     return -1;
2140 }
2141
2142 int eval_execution_set::getMaxIterViaPBP() {
2143     if (calculate_PBP_extrema())
2144         return maxIter;
2145     return -1;
2146 }
2147
2148 double eval_execution_set::getMinYGlobal(globalYVar_t globalYVar) {
2149     if (!calculate_global_extrema()) return -1; // throw exception!
2150     switch (globalYVar) {
2151         case AVERAGE:
2152             return minAverage;
2153             break;
2154         case DISTANCE:
2155             return minDistance;
2156             break;
2157         case RELERR:
2158             return minRelerr;
2159             break;
2160         case VARIANCE:
2161             return minVariance;
2162             break;
2163         case STDDEV:
2164             return minStddev;
2165             break;
2166         case RESIDUAL:
2167             if (selectionHasResidual())
2168                 return minResidual;
2169         case KULLBACK:
2170             if (selectionHasKullback())
2171                 return minKullback;
2172             break;
2173     } // switch
2174     // throw exception!
2175     return -1;
2176 }
2177
2178 double eval_execution_set::getMaxYGlobal(globalYVar_t globalYVar) {
2179     if (!calculate_global_extrema()) return -1; // throw exception!
2180     switch (globalYVar) {
2181         case AVERAGE:
2182             return maxAverage;
2183             break;
2184         case DISTANCE:
2185             return maxDistance;
2186             break;
2187         case RELERR:
2188             return maxRelerr;
2189             break;
2190         case VARIANCE:
2191             return maxVariance;
2192             break;
2193         case STDDEV:
2194             return maxStddev;
2195             break;
2196         case RESIDUAL:
2197             if (selectionHasResidual())
2198                 return maxResidual;
2199         case KULLBACK:
2200             if (selectionHasKullback())
2201                 return maxKullback;
2202             break;
2203     } // --switch
2204     // throw exception!
2205     return -1;
2206 } // --eval_execution_set::getMaxYGlobal(globalYVar_t globalYVar)
2207
2208 double eval_execution_set::getMinYPBP(unsigned idx) {
2209     //   if(idx >= num_Es) {
2210     //     throw std::logic_error("blah");
2211     //   }
2212     calculate_PBP_extrema();
2213     return PBP_minima[idx];
2214 }
2215
2216 double eval_execution_set::getMaxYPBP(unsigned idx) {
2217     calculate_PBP_extrema();
2218     return PBP_maxima[idx];
2219 }
2220
2221 /** eval_execution_set::show_all() and show_selected() are for debugging */
2222 void eval_execution_set::show_all() {
2223     if (hasPhantom()) {
2224         phantomeasp->show();
2225     }
2226     for (std::deque<eval_execution>::iterator it = execs.begin(); it != execs.end(); it++) {
2227         (*it).show_all();
2228     } // --foreach eval_execution
2229 } // eval_execution_set::show_all()
2230
2231 void eval_execution_set::show_selected() {
2232     unsigned j = 0;
2233     for (std::deque<eval_execution>::iterator it = execs.begin();
2234             it != execs.end(); j++, it++) {
2235         if (selected[j]) {
2236             (*it).show_all();
2237         }
2238     } // --foreach eval_execution
2239
2240 } // eval_execution_set::show_selected()
2241
2242 /** eval_execution_set::show_extrema() [mainly for debugging]
2243  *  huge side effect: recalculates all extrema without domain restriction */
2244 void eval_execution_set::show_extrema() {
2245     if (!completed)
2246         throw std::logic_error("Must NOT show extrema of eval_execution_set before complete() is signalled");
2247     std::cout << "Showing extrema in eval_execution_set among selected eval_executions." << std::endl;
2248
2249     // hack...
2250     if (hasPhantom()) {
2251         phantomeasp->show();
2252     }
2253
2254     bool successful = false;
2255     if (calculate_global_extrema()) {
2256         std::cout << "after global calculation: minIter, maxIter: " << minIter << " " << maxIter << std::endl;
2257         std::cout << "minAverage, maxAverage, minDistance, maxDistance, minRelerr, maxRelerr:" << std::endl
2258                 << minAverage << " " << maxAverage << " " << minDistance << " " << maxDistance << " " << minRelerr << " " << maxRelerr;
2259         std::cout << std::endl;
2260         std::cout << "minVariance, maxVariance, minStddev, maxStddev, minResidual, maxResidual, minKullback, maxKullback:" << std::endl
2261                 << minVariance << " " << maxVariance << " " << minStddev << " " << maxStddev << " " << minResidual << " " << maxResidual << " " << minKullback << " " << maxKullback;
2262         std::cout << std::endl;
2263         successful = true;
2264     }
2265
2266     if (calculate_PBP_extrema()) {
2267         std::cout << "after PBP calculation: minIter, maxIter: " << minIter << " " << maxIter << std::endl;
2268         for (unsigned i = 0; i < num_Es; i++) {
2269             std::cout << "PBP_minima[" << i << "] = " << PBP_minima[i] << "; "
2270                     << "PBP_maxima[" << i << "] = " << PBP_maxima[i] << std::endl;
2271         }
2272         successful = true;
2273     }
2274
2275     if (!successful) {
2276         std::cout << "Attempts to calculate both global and PBP extrema were unsuccessful." << std::endl;
2277     }
2278 } // --eval_execution_set::show_extrema()
2279
2280 void eval_execution_set::addPBPVarLines(line_real_set_t& LRS, unsigned PBPYVar, unsigned ee_index) {
2281     execs[ee_index].addPBPVarLines(LRS, PBPYVar); // this is 'inefficient' addressing, so what?
2282 }
2283
2284 void eval_execution_set::addGlobVarLines(line_real_set_t& LRS, globalYVar_t globalYVar, unsigned ee_index) {
2285     double phanval;
2286     // phantom first
2287     if (phantomeasp) {
2288         phanval = phantomeasp->get(globalYVar);
2289     } else {
2290         phanval = -2.0;
2291     }
2292     if (phanval > -0.5) {
2293         line_real_t phantomline("phantom", LRS.getMinX(), LRS.getMaxX(), phanval);
2294         LRS.add(phantomline);
2295     }
2296     // then the other lines
2297     execs[ee_index].addGlobVarLines(LRS, globalYVar);
2298 } // --eval_execution_set::addGlobVarLines()
2299
2300 void eval_execution_set::spawnDialogsGlob(QWidget* parent, globalYVar_t globalYVar) {
2301     if (std::verbose >= 2) {
2302         std::cout << "in eval_execution_set::spawnDialogsGlob()" << std::endl;
2303     }
2304     int posx = parent->pos().x();
2305     int posy = parent->pos().y();
2306     unsigned ee_index = 0;
2307     for (std::deque<eval_execution>::iterator it = execs.begin();
2308             it != execs.end(); ee_index++, it++) {
2309         // if selected and has global and if selected var is residual then has residual
2310         if ((selected[ee_index]) && ((*it).hasGlobal()) && ((globalYVar != RESIDUAL) || ((*it).hasResidual())) && ((globalYVar != KULLBACK) || ((*it).hasKullback()))) {
2311             posx += 20;
2312             posy += 20;
2313             ///      it->show_extrema(); // might have side-effects
2314             it->calculate_global_extrema();
2315             int minX = it->getMinIter(); // to be the defaults in the range dialog window
2316             int maxX = it->getMaxIter();
2317             double minY = 0, maxY = 0; // initialize to shut up the compiler
2318             switch (globalYVar) {
2319                 case AVERAGE: minY = it->getMinAverage();
2320                     maxY = it->getMaxAverage();
2321                     break;
2322                 case DISTANCE: minY = it->getMinDistance();
2323                     maxY = it->getMaxDistance();
2324                     break;
2325                 case RELERR: minY = it->getMinRelerr();
2326                     maxY = it->getMaxRelerr();
2327                     break;
2328                 case VARIANCE: minY = it->getMinVariance();
2329                     maxY = it->getMaxVariance();
2330                     break;
2331                 case STDDEV: minY = it->getMinStddev();
2332                     maxY = it->getMaxStddev();
2333                     break;
2334                 case RESIDUAL: minY = it->getMinResidual();
2335                     maxY = it->getMaxResidual();
2336                     break;
2337                 case KULLBACK: minY = it->getMinKullback();
2338                     maxY = it->getMaxKullback();
2339                     break;
2340                     // default: never happens
2341             }
2342             if (std::verbose >= 2) {
2343                 std::cout << "in eval_execution_set::spawnDialogsGlob() minY is "
2344                         << minY << " and maxY is " << maxY << std::endl;
2345             }
2346             const char* ccp = it->getName();
2347             chooseRangesDialog* crdp =
2348                     new chooseRangesDialog(parent, ccp, false, 0, posx, posy,
2349                     ee_index, false, 0, globalYVar,
2350                     minX, maxX, minY, maxY);
2351             crdp->show();
2352         } // if
2353     } // for
2354 } // --eval_execution_set::spawnDialogsGlob()
2355
2356 /** spawn dialog box to get range for each selected eval execution with PBP */
2357 void eval_execution_set::spawnDialogsPBP(QWidget* parent, unsigned PBPYVar) {
2358     if (std::verbose >= 2) {
2359         std::cout << "in eval_execution_set::spawnDialogsPBP()" << std::endl;
2360     }
2361     int posx = parent->pos().x();
2362     int posy = parent->pos().y();
2363     unsigned ee_index = 0;
2364     for (std::deque<eval_execution>::iterator it = execs.begin();
2365             it != execs.end(); ee_index++, it++) {
2366         if ((selected[ee_index]) && ((*it).hasPBP())) {
2367             posx += 20;
2368             posy += 20;
2369             it->calculate_PBP_extrema();
2370             int minX = it->getMinIter(); // to be the defaults in the range dialog window
2371             int maxX = it->getMaxIter();
2372             double minY = it->getMinE(PBPYVar);
2373             double maxY = it->getMaxE(PBPYVar);
2374             const char* ccp = it->getName();
2375             chooseRangesDialog* crdp =
2376                     new chooseRangesDialog(parent, ccp, false, 0, posx, posy,
2377                     ee_index, true, PBPYVar, AVERAGE,
2378                     minX, maxX, minY, maxY);
2379             crdp->show();
2380         } // if
2381     } // --for
2382 } // --eval_execution_set::spawnDialogsPBP()
2383
2384 void eval_execution_set::spawnAllPlotsGlob(QWidget* parent,
2385         globalYVar_t globalYVar, int userMinXVal, int userMaxXVal,
2386         double userMinYVal, double userMaxYVal, bool isGrayScale) {
2387     /// std::cout << "in eval_execution_set::spawnAllPlotsGlob()" << std::endl;
2388     //  int PMWidth  = 650; // pixmap width, etc
2389     //  sd_line_t::WIDTH  = 650;
2390     int PMWidth = sd_line_t::WIDTH;
2391     //  int PMHeight = 550;
2392     //  sd_line_t::HEIGHT = 550;
2393     int PMHeight = sd_line_t::HEIGHT;
2394     int PMDepth = 24; // number of colors?
2395     unsigned ee_index = 0;
2396     int x = parent->pos().x();
2397     int y = parent->pos().y();
2398     // block for doing phan
2399     double phanval;
2400     if (phantomeasp) {
2401         phanval = phantomeasp->get(globalYVar);
2402     } else {
2403         phanval = -2.0;
2404     }
2405     QString YVarName;
2406     switch (globalYVar) {
2407         case AVERAGE: YVarName = "Average";
2408             break;
2409         case DISTANCE: YVarName = "Distance";
2410             break;
2411         case RELERR: YVarName = "Relative Error";
2412             break;
2413         case VARIANCE: YVarName = "Variance";
2414             break;
2415         case STDDEV: YVarName = "Standard Deviation";
2416             break;
2417         case RESIDUAL: YVarName = "Residual";
2418             break;
2419         case KULLBACK: YVarName = "KL Distance";
2420             break;
2421     }
2422     for (std::deque<eval_execution>::iterator it = execs.begin();
2423             it != execs.end(); ee_index++, it++) {
2424         if ((selected[ee_index]) && ((*it).hasGlobal()) && ((globalYVar != RESIDUAL) || ((*it).hasResidual())) && ((globalYVar != KULLBACK) || ((*it).hasKullback()))) {
2425             line_real_set_t LRS(userMinXVal, userMaxXVal, userMinYVal, userMaxYVal);
2426             QPixmap* myPixmapP = new QPixmap(PMWidth, PMHeight);
2427             myPixmapP->fill(Qt::white);
2428             QPainter* myPainterP = new QPainter;
2429             myPainterP->begin(myPixmapP);
2430             // do the thing with the plot
2431             if (phanval > -0.5) { // if no error getting stuff from phan
2432                 line_real_t phantomline("phantom", LRS.getMinX(), LRS.getMaxX(), phanval);
2433                 LRS.add(phantomline);
2434             }
2435             it->addGlobVarLines(LRS, globalYVar);
2436             plot_t myPlotter(LRS); // now combine LRS with myPainterP
2437             QString evalexecname = it->getName();
2438             QString fullname = evalexecname;
2439             fullname += " :: ";
2440             fullname += YVarName;
2441             myPlotter.setName(fullname);
2442             myPlotter.setYAxisName(YVarName);
2443             QString XAxisName = "Iteration"; // as in all evals
2444             myPlotter.setXAxisName(XAxisName);
2445             // jk 2/2/2009 adding grayScale option for graphs
2446             if (isGrayScale) {
2447                 myPlotter.plotGray(*myPainterP);
2448             } else {
2449                 myPlotter.plot(*myPainterP);
2450             }
2451             x += 20;
2452             y += 20;
2453             displaylineswindow *dwp = new displaylineswindow(parent, fullname, myPixmapP, false, 0, x, y);
2454             dwp->show(); // and display!
2455         }
2456     } // --for
2457 } // --eval_execution_set::spawnAllPlotsGlob()
2458
2459 void eval_execution_set::spawnAllPlotsPBP(QWidget* parent, unsigned PBPYVar,
2460         int userMinXVal, int userMaxXVal, double userMinYVal,
2461         double userMaxYVal, bool isGrayScale) {
2462     ///  std::cout << "in eval_execution_set::spawnAllPlotsPBP()" << std::endl;
2463     //  int PMWidth  = 650; // pixmap width, etc
2464     //  sd_line_t::WIDTH  = 650;
2465     int PMWidth = sd_line_t::WIDTH;
2466     //  int PMHeight = 550;
2467     //  sd_line_t::HEIGHT = 550;
2468     int PMHeight = sd_line_t::HEIGHT;
2469     unsigned ee_index = 0;
2470     int x = parent->pos().x();
2471     int y = parent->pos().y();
2472     QString YVarName = "e(";
2473     QString PBPYVarAsQString;
2474     PBPYVarAsQString.setNum(PBPYVar);
2475     YVarName += PBPYVarAsQString;
2476     YVarName += (')');
2477     for (std::deque<eval_execution>::iterator it = execs.begin();
2478             it != execs.end(); ee_index++, it++) {
2479         if ((selected[ee_index]) && ((*it).hasPBP())) {
2480             line_real_set_t LRS(userMinXVal, userMaxXVal, userMinYVal, userMaxYVal);
2481             QPixmap* myPixmapP = new QPixmap(PMWidth, PMHeight);
2482             myPixmapP->fill(Qt::white);
2483             QPainter* myPainterP = new QPainter;
2484             myPainterP->begin(myPixmapP);
2485             // do the thing with the plot: NO phantom for PBP
2486             it->addPBPVarLines(LRS, PBPYVar);
2487             plot_t myPlotter(LRS); // now combine LRS with myPainterP
2488             // can give name here based on (*it)
2489             QString evalexecname = it->getName();
2490             QString fullname = evalexecname;
2491             fullname += " :: ";
2492             fullname += YVarName;
2493             myPlotter.setName(fullname);
2494             QString xaxname = "Iteration";
2495             myPlotter.setXAxisName(xaxname);
2496             myPlotter.setYAxisName(YVarName);
2497             // jk 2/2/2009 adding grayScale option for graphs
2498             if (isGrayScale) {
2499                 myPlotter.plotGray(*myPainterP);
2500             } else {
2501                 myPlotter.plot(*myPainterP);
2502             }
2503
2504             x += 20;
2505             y += 20;
2506             displaylineswindow *dwp = new displaylineswindow(parent, fullname, myPixmapP, false, 0, x, y);
2507             dwp->show(); // and display!
2508         }
2509     } // --for
2510 } // --eval_execution_set::spawnAllPlotsPBP()
2511
2512 /** eval_execution_set::clear() !!!! erases all information!!! (to allow callee to get on with life) */
2513 void eval_execution_set::clear() {
2514     ///  std::cout << "in eval_execution_set::clear()!!!" << std::endl;
2515     completed = extrema_calculated = false;
2516     same_x_forall = same_y_forall = false; // initialize to use "locally" calculated domain/range bounds
2517     selectionHasResidualvar = false;
2518     selectionHasKullbackvar = false;
2519     num_Es = 0;
2520     if (phantomeasp) delete phantomeasp;
2521     phantomeasp = 0;
2522     PBP_minima.clear();
2523     PBP_maxima.clear();
2524     selected.clear();
2525     execs.clear();
2526     minResidual = maxResidual = -1;
2527     minKullback = maxKullback = -1;
2528 } // --eval_execution_set()
2529
2530 eval_execution_set::~eval_execution_set() {
2531     //  std::cout << "in eval_execution_set destructor!!!" << std::endl;
2532     if (phantomeasp) {
2533         delete phantomeasp; // and make sure no one else does this!
2534     }
2535 } // --eval_execution_set dtor
2536 //// // --class eval_execution_set
2537
2538 unsigned globmeas::NEXT_GMID = 0; // class variable initialization
2539 unsigned globmeaset::NEXT_GMSID = 0; // class variable initialization
2540 unsigned PBPmeas::NEXT_PMID = 0; // class variable initialization
2541 unsigned PBPmeaset::NEXT_PMSID = 0; // class variable initialization
2542 unsigned eval_execution::NEXT_EEID = 0; // class variable initialization
2543
2544 // --eval_helper.cpp