Isis 3 Programmer Reference
CubeCalculator.cpp
1 
6 /* SPDX-License-Identifier: CC0-1.0 */
7 #include "CubeCalculator.h"
8 
9 #include <QVector>
10 
11 #include "Angle.h"
12 #include "Camera.h"
13 #include "Distance.h"
14 #include "IString.h"
15 #include "Statistics.h"
16 
17 using namespace std;
18 
19 namespace Isis {
20 
22  CubeCalculator::CubeCalculator() {
23  m_calculations = NULL;
24  m_methods = NULL;
25  m_dataDefinitions = NULL;
26  m_cubeStats = NULL;
27  m_cubeCameras = NULL;
28  m_cameraBuffers = NULL;
29 
30  m_calculations = new QVector<Calculations>();
31  m_methods = new QVector<void (Calculator:: *)(void)>();
32  m_dataDefinitions = new QVector<DataValue>();
33  m_cubeStats = new QVector<Statistics *>();
34  m_cubeCameras = new QVector<Camera *>();
35  m_cameraBuffers = new QVector<CameraBuffers *>();
36 
37  m_outputSamples = 0;
38  }
39 
40 
42  CubeCalculator::~CubeCalculator() {
43  Clear(); // free dynamic memory in container members
44 
45  delete m_calculations;
46  delete m_methods;
47  delete m_dataDefinitions;
48  delete m_cubeStats;
49  delete m_cubeCameras;
50  delete m_cameraBuffers;
51 
52  m_calculations = NULL;
53  m_methods = NULL;
54  m_dataDefinitions = NULL;
55  m_cubeStats = NULL;
56  m_cubeCameras = NULL;
57  m_cameraBuffers = NULL;
58  }
59 
60 
64  void CubeCalculator::Clear() {
65  Calculator::Clear();
66 
67  if (m_calculations) {
68  m_calculations->clear();
69  }
70 
71  if (m_methods) {
72  m_methods->clear();
73  }
74 
75  if (m_dataDefinitions) {
76  m_dataDefinitions->clear();
77  }
78 
79  // m_cubeStats contains pointers to dynamic memory - need to free
80  if (m_cubeStats) {
81  for (int i = 0; i < m_cubeStats->size(); i++) {
82  delete (*m_cubeStats)[i];
83  (*m_cubeStats)[i] = NULL;
84  }
85  m_cubeStats->clear();
86  }
87 
88  if (m_cubeCameras) {
89  m_cubeCameras->clear();
90  }
91 
92  // m_cameraBuffers contains pointers to dynamic memory - need to free
93  if (m_cameraBuffers) {
94  for (int i = 0; i < m_cameraBuffers->size(); i++) {
95  delete (*m_cameraBuffers)[i];
96  (*m_cameraBuffers)[i] = NULL;
97  }
98  m_cameraBuffers->clear();
99  }
100  }
101 
102 
114  QVector<double> CubeCalculator::runCalculations(QVector<Buffer *> &cubeData,
115  int curLine,
116  int curBand) {
117  // For now we'll only process a single line in this method for our results. In order
118  // to do more powerful indexing, passing a list of cubes and the output cube will
119  // be necessary.
120  int methodIndex = 0;
121  int dataIndex = 0;
122 
123  for (int currentCalculation = 0; currentCalculation < m_calculations->size();
124  currentCalculation++) {
125  if ((*m_calculations)[currentCalculation] == CallNextMethod) {
126  void (Calculator::*aMethod)() = (*m_methods)[methodIndex];
127  (this->*aMethod)();
128  methodIndex ++;
129  }
130  else {
131  DataValue &data = (*m_dataDefinitions)[dataIndex];
132  if (data.type() == DataValue::Constant) {
133  Push(data.constant());
134  }
135  else if (data.type() == DataValue::Band) {
136  Push(curBand);
137  }
138  else if (data.type() == DataValue::Line) {
139  Push(curLine);
140  }
141  else if (data.type() == DataValue::Sample) {
142  QVector<double> samples;
143  samples.resize(m_outputSamples);
144 
145  for (int i = 0; i < m_outputSamples; i++) {
146  samples[i] = i + 1;
147  }
148 
149  Push(samples);
150  }
151  else if (data.type() == DataValue::CubeData) {
152  Push(*cubeData[data.cubeIndex()]);
153  }
154  else if (data.type() == DataValue::InaData) {
155  Push(*((*m_cameraBuffers)[data.cubeIndex()]->inaBuffer(curLine,
156  m_outputSamples,
157  curBand)));
158  }
159  else if (data.type() == DataValue::EmaData) {
160  Push(*((*m_cameraBuffers)[data.cubeIndex()]->emaBuffer(curLine,
161  m_outputSamples,
162  curBand)));
163  }
164  else if (data.type() == DataValue::PhaData) {
165  Push(*((*m_cameraBuffers)[data.cubeIndex()]->phaBuffer(curLine,
166  m_outputSamples,
167  curBand)));
168  }
169  else if (data.type() == DataValue::InalData) {
170  Push(*((*m_cameraBuffers)[data.cubeIndex()]->inalBuffer(curLine,
171  m_outputSamples,
172  curBand)));
173  }
174  else if (data.type() == DataValue::EmalData) {
175  Push(*((*m_cameraBuffers)[data.cubeIndex()]->emalBuffer(curLine,
176  m_outputSamples,
177  curBand)));
178  }
179  else if (data.type() == DataValue::PhalData) {
180  Push(*((*m_cameraBuffers)[data.cubeIndex()]->phalBuffer(curLine,
181  m_outputSamples,
182  curBand)));
183  }
184  else if (data.type() == DataValue::LatData) {
185  Push(*((*m_cameraBuffers)[data.cubeIndex()]->latBuffer(curLine,
186  m_outputSamples,
187  curBand)));
188  }
189  else if (data.type() == DataValue::LonData) {
190  Push(*((*m_cameraBuffers)[data.cubeIndex()]->lonBuffer(curLine,
191  m_outputSamples,
192  curBand)));
193  }
194  else if (data.type() == DataValue::ResData) {
195  Push(*((*m_cameraBuffers)[data.cubeIndex()]->resBuffer(curLine,
196  m_outputSamples,
197  curBand)));
198  }
199  else if (data.type() == DataValue::RadiusData) {
200  Push(*((*m_cameraBuffers)[data.cubeIndex()]->radiusBuffer(curLine,
201  m_outputSamples,
202  curBand)));
203  }
204  else if (data.type() == DataValue::InacData) {
205  Push(*((*m_cameraBuffers)[data.cubeIndex()]->inacBuffer(curLine,
206  m_outputSamples,
207  curBand)));
208  }
209  else if (data.type() == DataValue::EmacData) {
210  Push(*((*m_cameraBuffers)[data.cubeIndex()]->emacBuffer(curLine,
211  m_outputSamples,
212  curBand)));
213  }
214  else if (data.type() == DataValue::PhacData) {
215  Push(*((*m_cameraBuffers)[data.cubeIndex()]->phacBuffer(curLine,
216  m_outputSamples,
217  curBand)));
218  }
219  else {
220  }
221 
222  dataIndex ++;
223  }
224  }
225 
226  if (StackSize() != 1) {
227  string msg = "Too many operands in the equation.";
228  throw IException(IException::Unknown, msg, _FILEINFO_);
229  }
230 
231  return Pop(true);
232  }
233 
234 
249  void CubeCalculator::prepareCalculations(QString equation,
250  QVector<Cube *> &inCubes,
251  Cube *outCube) {
252  Clear();
253 
254  m_outputSamples = outCube->sampleCount();
255 
256  IString eq = equation;
257  while (eq != "") {
258  IString token = eq.Token(" ");
259 
260  // Step through every part of the postfix equation and set up the appropriate
261  // action list based on the current token. Attempting to order if-else conditions
262  // in terms of what would probably be encountered more often.
263 
264  // Scalars
265  if (isdigit(token[0]) || token[0] == '.') {
266  m_calculations->push_back(PushNextData);
267  m_dataDefinitions->push_back(DataValue(DataValue::Constant,
268  token.ToDouble()));
269  }
270  // File, e.g. F1 = first file in list. Must come after any functions starting with 'f' that
271  // is not a cube.
272  else if (token[0] == 'f') {
273  IString tok(token.substr(1));
274  int file = tok.ToInteger() - 1;
275  if (file < 0 || file >= (int)inCubes.size()) {
276  QString msg = "Invalid file number [" + tok.ToQt() + "]";
277  throw IException(IException::Unknown, msg, _FILEINFO_);
278  }
279 
280  m_calculations->push_back(PushNextData);
281  m_dataDefinitions->push_back(DataValue(DataValue::CubeData, file));
282  }
283  else if (token == "band") {
284  m_calculations->push_back(PushNextData);
285  m_dataDefinitions->push_back(DataValue(DataValue::Band));
286  }
287  else if (token == "line") {
288  m_calculations->push_back(PushNextData);
289  m_dataDefinitions->push_back(DataValue(DataValue::Line));
290  }
291  else if (token == "sample") {
292  m_calculations->push_back(PushNextData);
293  m_dataDefinitions->push_back(DataValue(DataValue::Sample));
294  }
295  // Addition
296  else if (token == "+") {
297  addMethodCall(&Calculator::Add);
298  }
299 
300  // Subtraction
301  else if (token == "-") {
302  addMethodCall(&Calculator::Subtract);
303  }
304 
305  // Multiplication
306  else if (token == "*") {
307  addMethodCall(&Calculator::Multiply);
308  }
309 
310  // Division
311  else if (token == "/") {
312  addMethodCall(&Calculator::Divide);
313  }
314 
315  // Modulus
316  else if (token == "%") {
317  addMethodCall(&Calculator::Modulus);
318  }
319 
320  // Exponent
321  else if (token == "^") {
322  addMethodCall(&Calculator::Exponent);
323  }
324 
325  // Negative
326  else if (token == "--") {
327  addMethodCall(&Calculator::Negative);
328  }
329 
330  // Negative
331  else if (token == "neg") {
332  addMethodCall(&Calculator::Negative);
333  }
334 
335  // Left shift
336  else if (token == "<<") {
337  addMethodCall(&Calculator::LeftShift);
338  }
339 
340  // Right shift
341  else if (token == ">>") {
342  addMethodCall(&Calculator::RightShift);
343  }
344 
345  // Maximum In The Line
346  else if (token == "linemax") {
347  addMethodCall(&Calculator::MaximumLine);
348  }
349 
350  // Maximum Pixel on a per-pixel basis
351  else if (token == "max") {
352  addMethodCall(&Calculator::MaximumPixel);
353  }
354 
355  // Minimum In The Line
356  else if (token == "linemin") {
357  addMethodCall(&Calculator::MinimumLine);
358  }
359 
360  // Minimum Pixel on a per-pixel basis
361  else if (token == "min") {
362  addMethodCall(&Calculator::MinimumPixel);
363  }
364 
365  // Absolute value
366  else if (token == "abs") {
367  addMethodCall(&Calculator::AbsoluteValue);
368  }
369 
370  // Square root
371  else if (token == "sqrt") {
372  addMethodCall(&Calculator::SquareRoot);
373  }
374 
375  // Natural Log
376  else if (token == "log" || token == "ln") {
377  addMethodCall(&Calculator::Log);
378  }
379 
380  // Log base 10
381  else if (token == "log10") {
382  addMethodCall(&Calculator::Log10);
383  }
384 
385  // Pi
386  else if (token == "pi") {
387  m_calculations->push_back(PushNextData);
388  m_dataDefinitions->push_back(
389  DataValue(DataValue::Constant, PI)
390  );
391  }
392 
393  // e
394  else if (token == "e") {
395  m_calculations->push_back(PushNextData);
396  m_dataDefinitions->push_back(
397  DataValue(DataValue::Constant, E)
398  );
399  }
400 
401  else if (token == "rads") {
402  m_calculations->push_back(PushNextData);
403  m_dataDefinitions->push_back(
404  DataValue(DataValue::Constant, PI / 180.0)
405  );
406 
407  addMethodCall(&Calculator::Multiply);
408  }
409 
410  else if (token == "degs") {
411  m_calculations->push_back(PushNextData);
412  m_dataDefinitions->push_back(
413  DataValue(DataValue::Constant, 180.0 / PI)
414  );
415  addMethodCall(&Calculator::Multiply);
416  }
417 
418  // Sine
419  else if (token == "sin") {
420  addMethodCall(&Calculator::Sine);
421  }
422 
423  // Cosine
424  else if (token == "cos") {
425  addMethodCall(&Calculator::Cosine);
426  }
427 
428  // Tangent
429  else if (token == "tan") {
430  addMethodCall(&Calculator::Tangent);
431  }
432 
433  // Secant
434  else if (token == "sec") {
435  addMethodCall(&Calculator::Secant);
436  }
437 
438  // Cosecant
439  else if (token == "csc") {
440  addMethodCall(&Calculator::Cosecant);
441  }
442 
443  // Cotangent
444  else if (token == "cot") {
445  addMethodCall(&Calculator::Cotangent);
446  }
447 
448  // Arcsin
449  else if (token == "asin") {
450  addMethodCall(&Calculator::Arcsine);
451  }
452 
453  // Arccos
454  else if (token == "acos") {
455  addMethodCall(&Calculator::Arccosine);
456  }
457 
458  // Arctan
459  else if (token == "atan") {
460  addMethodCall(&Calculator::Arctangent);
461  }
462 
463  // Arctan2
464  else if (token == "atan2") {
465  addMethodCall(&Calculator::Arctangent2);
466  }
467 
468  // SineH
469  else if (token == "sinh") {
470  addMethodCall(&Calculator::SineH);
471  }
472 
473  // CosH
474  else if (token == "cosh") {
475  addMethodCall(&Calculator::CosineH);
476  }
477 
478  // TanH
479  else if (token == "tanh") {
480  addMethodCall(&Calculator::TangentH);
481  }
482 
483  // Less than
484  else if (token == "<") {
485  addMethodCall(&Calculator::LessThan);
486  }
487 
488  // Greater than
489  else if (token == ">") {
490  addMethodCall(&Calculator::GreaterThan);
491  }
492 
493  // Less than or equal
494  else if (token == "<=") {
495  addMethodCall(&Calculator::LessThanOrEqual);
496  }
497 
498  // Greater than or equal
499  else if (token == ">=") {
500  addMethodCall(&Calculator::GreaterThanOrEqual);
501  }
502 
503  // Equal
504  else if (token == "==") {
505  addMethodCall(&Calculator::Equal);
506  }
507 
508  // Not equal
509  else if (token == "!=") {
510  addMethodCall(&Calculator::NotEqual);
511  }
512 
513  // Maximum in a cube
514  else if (token == "cubemax") {
515  int cubeIndex = lastPushToCubeStats(inCubes);
516 
517  m_calculations->push_back(PushNextData);
518  m_dataDefinitions->push_back(
519  DataValue(DataValue::Constant, (*m_cubeStats)[cubeIndex]->Maximum())
520  );
521  //TODO: Test for NULL Maximum
522  }
523 
524  // Maximum in a cube
525  else if (token == "cubemin") {
526  int cubeIndex = lastPushToCubeStats(inCubes);
527 
528  m_calculations->push_back(PushNextData);
529  m_dataDefinitions->push_back(
530  DataValue(DataValue::Constant, (*m_cubeStats)[cubeIndex]->Minimum())
531  );
532  //TODO: Test for NULL Minimum
533  }
534 
535  // Average of a cube
536  else if (token == "cubeavg") {
537  int cubeIndex = lastPushToCubeStats(inCubes);
538 
539  m_calculations->push_back(PushNextData);
540  m_dataDefinitions->push_back(
541  DataValue(DataValue::Constant, (*m_cubeStats)[cubeIndex]->Average())
542  );
543  //TODO: Test for NULL Average
544  }
545 
546  // Standard deviation of a cube
547  else if (token == "cubestd") {
548  int cubeIndex = lastPushToCubeStats(inCubes);
549 
550  m_calculations->push_back(PushNextData);
551  m_dataDefinitions->push_back(
552  DataValue(DataValue::Constant, (*m_cubeStats)[cubeIndex]->StandardDeviation())
553  );
554  //TODO: Test for NULL standard deviation
555  }
556 
557  // Center incidence
558  else if (token == "inac") {
559  int cubeIndex = lastPushToCubeCameras(inCubes);
560  (*m_cameraBuffers)[cubeIndex]->enableInacBuffer();
561 
562  m_calculations->push_back(PushNextData);
563  m_dataDefinitions->push_back(DataValue(DataValue::InacData, cubeIndex));
564  }
565 
566  // Center emission
567  else if (token == "emac") {
568  int cubeIndex = lastPushToCubeCameras(inCubes);
569  (*m_cameraBuffers)[cubeIndex]->enableEmacBuffer();
570 
571  m_calculations->push_back(PushNextData);
572  m_dataDefinitions->push_back(DataValue(DataValue::EmacData, cubeIndex));
573  }
574 
575  // Center phase
576  else if (token == "phac") {
577  int cubeIndex = lastPushToCubeCameras(inCubes);
578  (*m_cameraBuffers)[cubeIndex]->enablePhacBuffer();
579 
580  m_calculations->push_back(PushNextData);
581  m_dataDefinitions->push_back(DataValue(DataValue::PhacData, cubeIndex));
582  }
583 
584  // Incidence on the ellipsoid
585  else if (token == "ina") {
586  int cubeIndex = lastPushToCubeCameras(inCubes);
587  (*m_cameraBuffers)[cubeIndex]->enableInaBuffer();
588 
589  m_calculations->push_back(PushNextData);
590  m_dataDefinitions->push_back(DataValue(DataValue::InaData, cubeIndex));
591  }
592 
593  // Emission on the ellipsoid
594  else if (token == "ema") {
595  int cubeIndex = lastPushToCubeCameras(inCubes);
596  (*m_cameraBuffers)[cubeIndex]->enableEmaBuffer();
597 
598  m_calculations->push_back(PushNextData);
599  m_dataDefinitions->push_back(DataValue(DataValue::EmaData, cubeIndex));
600  }
601 
602  // Phase on the ellipsoid
603  else if (token == "pha") {
604  int cubeIndex = lastPushToCubeCameras(inCubes);
605  (*m_cameraBuffers)[cubeIndex]->enablePhaBuffer();
606 
607  m_calculations->push_back(PushNextData);
608  m_dataDefinitions->push_back(DataValue(DataValue::PhaData, cubeIndex));
609  }
610 
611  // Incidence on the DTM
612  else if (token == "inal") {
613  int cubeIndex = lastPushToCubeCameras(inCubes);
614  (*m_cameraBuffers)[cubeIndex]->enableInalBuffer();
615 
616  m_calculations->push_back(PushNextData);
617  m_dataDefinitions->push_back(DataValue(DataValue::InalData, cubeIndex));
618  }
619 
620  // Emission on the DTM
621  else if (token == "emal") {
622  int cubeIndex = lastPushToCubeCameras(inCubes);
623  (*m_cameraBuffers)[cubeIndex]->enableEmalBuffer();
624 
625  m_calculations->push_back(PushNextData);
626  m_dataDefinitions->push_back(DataValue(DataValue::EmalData, cubeIndex));
627  }
628 
629  // Phase on the ellipsoid
630  else if (token == "phal") {
631  int cubeIndex = lastPushToCubeCameras(inCubes);
632  (*m_cameraBuffers)[cubeIndex]->enablePhalBuffer();
633 
634  m_calculations->push_back(PushNextData);
635  m_dataDefinitions->push_back(DataValue(DataValue::PhalData, cubeIndex));
636  }
637 
638  // Latitude
639  else if (token == "lat") {
640  int cubeIndex = lastPushToCubeCameras(inCubes);
641  (*m_cameraBuffers)[cubeIndex]->enableLatBuffer();
642 
643  m_calculations->push_back(PushNextData);
644  m_dataDefinitions->push_back(DataValue(DataValue::LatData, cubeIndex));
645  }
646 
647  // Longitude
648  else if (token == "lon") {
649  int cubeIndex = lastPushToCubeCameras(inCubes);
650  (*m_cameraBuffers)[cubeIndex]->enableLonBuffer();
651 
652  m_calculations->push_back(PushNextData);
653  m_dataDefinitions->push_back(DataValue(DataValue::LonData, cubeIndex));
654  }
655 
656  // Pixel resolution
657  else if (token == "res") {
658  int cubeIndex = lastPushToCubeCameras(inCubes);
659  (*m_cameraBuffers)[cubeIndex]->enableResBuffer();
660 
661  m_calculations->push_back(PushNextData);
662  m_dataDefinitions->push_back(DataValue(DataValue::ResData, cubeIndex));
663  }
664 
665  // Local Radius
666  else if (token == "radius") {
667  int cubeIndex = lastPushToCubeCameras(inCubes);
668  (*m_cameraBuffers)[cubeIndex]->enableRadiusBuffer();
669 
670  m_calculations->push_back(PushNextData);
671  m_dataDefinitions->push_back(DataValue(DataValue::RadiusData, cubeIndex));
672  }
673 
674  // Ignore empty token
675  else if (token == "") {
676  }
677 
678  else {
679  string msg = "Unidentified operator [";
680  msg += token + "]";
681  throw IException(IException::Unknown, msg, _FILEINFO_);
682  }
683  } // while loop
684  }
685 
686 
699  int CubeCalculator::lastPushToCubeStats(QVector<Cube *> &inCubes) {
700  if (!m_calculations->size()) {
701  string msg = "Not sure which file to get statistics from";
702  throw IException(IException::Unknown, msg, _FILEINFO_);
703  }
704 
705  if ((*m_calculations)[m_calculations->size() - 1] != PushNextData) {
706  string msg = "This function must not contain calculations,";
707  msg += " only input cubes may be specified.";
708  throw IException(IException::Unknown, msg, _FILEINFO_);
709  }
710 
711  m_calculations->pop_back();
712 
713  // This must have data if calculations had data that equaled push data
714  DataValue lastData = (*m_dataDefinitions)[m_dataDefinitions->size() - 1];
715 
716  if (lastData.type() != DataValue::CubeData) {
717  string msg = "This function must not contain constants,";
718  msg += " only input cubes may be specified.";
719  throw IException(IException::Unknown, msg, _FILEINFO_);
720  }
721 
722  int cubeStatsIndex = lastData.cubeIndex();
723  m_dataDefinitions->pop_back();
724 
725  // Member variables are now cleaned up, we need to verify the stats exists
726 
727  // Make sure room exists in the vector
728  while (m_cubeStats->size() < cubeStatsIndex + 1) {
729  m_cubeStats->push_back(NULL);
730  }
731 
732  // Now we can for sure put the stats object in the right place... put it
733  // there
734  if ((*m_cubeStats)[cubeStatsIndex] == NULL) {
735  (*m_cubeStats)[cubeStatsIndex] = inCubes[cubeStatsIndex]->statistics();
736  }
737 
738  return cubeStatsIndex;
739  }
740 
741 
759  int CubeCalculator::lastPushToCubeCameras(QVector<Cube *> &inCubes) {
760  if (!m_calculations->size()) {
761  string msg = "Not sure which file to get cameras from";
762  throw IException(IException::Unknown, msg, _FILEINFO_);
763  }
764 
765  if ((*m_calculations)[m_calculations->size() - 1] != PushNextData) {
766  string msg = "This function must not contain calculations,";
767  msg += " only input cubes may be specified.";
768  throw IException(IException::Unknown, msg, _FILEINFO_);
769  }
770 
771  m_calculations->pop_back();
772 
773  // This must have data if calculations had data that equaled push data
774  DataValue lastData = (*m_dataDefinitions)[m_dataDefinitions->size() - 1];
775 
776  if (lastData.type() != DataValue::CubeData) {
777  string msg = "This function must not contain constants,";
778  msg += " only input cubes may be specified.";
779  throw IException(IException::Unknown, msg, _FILEINFO_);
780  }
781 
782  int cubeIndex = lastData.cubeIndex();
783  m_dataDefinitions->pop_back();
784 
785  // Member variables are now cleaned up, we need to verify the camera exists
786 
787  // Make sure room exists in the vector
788  while (m_cubeCameras->size() < cubeIndex + 1) {
789  m_cubeCameras->push_back(NULL);
790  }
791 
792  while (m_cameraBuffers->size() < cubeIndex + 1) {
793  m_cameraBuffers->push_back(NULL);
794  }
795 
796  // Now we can for sure put the camera object in the right place... put it
797  // there
798  if ((*m_cubeCameras)[cubeIndex] == NULL) {
799  Camera *cam;
800  try {
801  cam = inCubes[cubeIndex]->camera();
802  if (cam == NULL) {
803  string msg = "This function requires a camera and the input cube does";
804  msg += " not have one. You may need to run spiceinit";
805  throw IException(IException::Unknown, msg, _FILEINFO_);
806  }
807  }
808  catch (IException &e) {
809  string msg = "This function requires a camera and the input cube does";
810  msg += " not have one. You may need to run spiceinit";
811  throw IException(e, IException::Unknown, msg, _FILEINFO_);
812  }
813 
814  (*m_cubeCameras)[cubeIndex] = cam;
815  (*m_cameraBuffers)[cubeIndex] = new CameraBuffers(cam);
816  }
817 
818  return cubeIndex;
819  }
820 
821 
828  void CubeCalculator::addMethodCall(void (Calculator::*method)(void)) {
829  m_calculations->push_back(CallNextMethod);
830  m_methods->push_back(method);
831  }
832 
833 
840  DataValue::DataValue() {
841  m_type = (DataValueType) - 1;
842  m_cubeIndex = -1;
843  m_constantValue = 0.0;
844  }
845 
846 
855  DataValue::DataValue(DataValueType type) {
856  m_type = type;
857  m_constantValue = 0.0;
858  m_cubeIndex = -1;
859  }
860 
861 
871  DataValue::DataValue(DataValueType type, int cubeIndex) {
872  m_type = type;
873  m_constantValue = 0.0;
874  m_cubeIndex = cubeIndex;
875  }
876 
877 
888  DataValue::DataValue(DataValueType type, double value) {
889  m_type = type;
890  m_cubeIndex = -1;
891 
892  if (type == Constant) {
893  m_constantValue = value;
894  }
895  }
896 
897 
903  DataValue::DataValueType DataValue::type() {
904  return m_type;
905  }
906 
907 
913  int DataValue::cubeIndex() {
914  return m_cubeIndex;
915  }
916 
917 
923  double DataValue::constant() {
924  return m_constantValue;
925  }
926 
927 
933  CameraBuffers::CameraBuffers(Camera *camera) {
934  m_camera = camera;
935  m_phaBuffer = NULL;
936  m_inaBuffer = NULL;
937  m_emaBuffer = NULL;
938  m_phalBuffer = NULL;
939  m_inalBuffer = NULL;
940  m_emalBuffer = NULL;
941  m_phacBuffer = NULL;
942  m_inacBuffer = NULL;
943  m_emacBuffer = NULL;
944  m_resBuffer = NULL;
945  m_latBuffer = NULL;
946  m_lonBuffer = NULL;
947  m_radiusBuffer = NULL;
948 
949  m_lastLine = -1;
950  }
951 
952 
956  CameraBuffers::~CameraBuffers() {
957  delete m_phaBuffer;
958  delete m_inaBuffer;
959  delete m_emaBuffer;
960  delete m_phalBuffer;
961  delete m_inalBuffer;
962  delete m_emalBuffer;
963  delete m_phacBuffer;
964  delete m_inacBuffer;
965  delete m_emacBuffer;
966  delete m_resBuffer;
967  delete m_latBuffer;
968  delete m_lonBuffer;
969  delete m_radiusBuffer;
970 
971  m_phaBuffer = NULL;
972  m_inaBuffer = NULL;
973  m_emaBuffer = NULL;
974  m_phalBuffer = NULL;
975  m_inalBuffer = NULL;
976  m_emalBuffer = NULL;
977  m_phacBuffer = NULL;
978  m_inacBuffer = NULL;
979  m_emacBuffer = NULL;
980  m_resBuffer = NULL;
981  m_latBuffer = NULL;
982  m_lonBuffer = NULL;
983  m_radiusBuffer = NULL;
984  }
985 
986 
988  void CameraBuffers::enablePhaBuffer() {
989  if (!m_phaBuffer) m_phaBuffer = new QVector<double>;
990  }
991 
992 
994  void CameraBuffers::enableInaBuffer() {
995  if (!m_inaBuffer) m_inaBuffer = new QVector<double>;
996  }
997 
998 
1000  void CameraBuffers::enableEmaBuffer() {
1001  if (!m_emaBuffer) m_emaBuffer = new QVector<double>;
1002  }
1003 
1004 
1006  void CameraBuffers::enableLatBuffer() {
1007  if (!m_latBuffer) m_latBuffer = new QVector<double>;
1008  }
1009 
1010 
1012  void CameraBuffers::enableLonBuffer() {
1013  if (!m_lonBuffer) m_lonBuffer = new QVector<double>;
1014  }
1015 
1016 
1018  void CameraBuffers::enableResBuffer() {
1019  if (!m_resBuffer) m_resBuffer = new QVector<double>;
1020  }
1021 
1022 
1024  void CameraBuffers::enableRadiusBuffer() {
1025  if (!m_radiusBuffer) m_radiusBuffer = new QVector<double>;
1026  }
1027 
1028 
1030  void CameraBuffers::enablePhalBuffer() {
1031  if (!m_phalBuffer) m_phalBuffer = new QVector<double>;
1032  }
1033 
1034 
1036  void CameraBuffers::enableInalBuffer() {
1037  if (!m_inalBuffer) m_inalBuffer = new QVector<double>;
1038  }
1039 
1040 
1042  void CameraBuffers::enableEmalBuffer() {
1043  if (!m_emalBuffer) m_emalBuffer = new QVector<double>;
1044  }
1045 
1046 
1048  void CameraBuffers::enablePhacBuffer() {
1049  if (!m_phacBuffer) m_phacBuffer = new QVector<double>;
1050  }
1051 
1052 
1054  void CameraBuffers::enableInacBuffer() {
1055  if (!m_inacBuffer) m_inacBuffer = new QVector<double>;
1056  }
1057 
1058 
1060  void CameraBuffers::enableEmacBuffer() {
1061  if (!m_emacBuffer) m_emacBuffer = new QVector<double>;
1062  }
1063 
1064 
1065  QVector<double> *CameraBuffers::phaBuffer(int currentLine, int ns, int currentBand) {
1066  loadBuffers(currentLine, ns, currentBand);
1067  return m_phaBuffer;
1068  }
1069 
1070 
1071  QVector<double> *CameraBuffers::inaBuffer(int currentLine, int ns, int currentBand) {
1072  loadBuffers(currentLine, ns, currentBand);
1073  return m_inaBuffer;
1074  }
1075 
1076 
1077  QVector<double> *CameraBuffers::emaBuffer(int currentLine, int ns, int currentBand) {
1078  loadBuffers(currentLine, ns, currentBand);
1079  return m_emaBuffer;
1080  }
1081 
1082 
1083  QVector<double> *CameraBuffers::latBuffer(int currentLine, int ns, int currentBand) {
1084  loadBuffers(currentLine, ns, currentBand);
1085  return m_latBuffer;
1086  }
1087 
1088 
1089  QVector<double> *CameraBuffers::lonBuffer(int currentLine, int ns, int currentBand) {
1090  loadBuffers(currentLine, ns, currentBand);
1091  return m_lonBuffer;
1092  }
1093 
1094 
1095  QVector<double> *CameraBuffers::resBuffer(int currentLine, int ns, int currentBand) {
1096  loadBuffers(currentLine, ns, currentBand);
1097  return m_resBuffer;
1098  }
1099 
1100 
1101  QVector<double> *CameraBuffers::radiusBuffer(int currentLine, int ns, int currentBand) {
1102  loadBuffers(currentLine,ns,currentBand);
1103  return m_radiusBuffer;
1104  }
1105 
1106 
1107  QVector<double> *CameraBuffers::phalBuffer(int currentLine, int ns, int currentBand) {
1108  loadBuffers(currentLine, ns, currentBand);
1109  return m_phalBuffer;
1110  }
1111 
1112 
1113  QVector<double> *CameraBuffers::inalBuffer(int currentLine, int ns, int currentBand) {
1114  loadBuffers(currentLine, ns, currentBand);
1115  return m_inalBuffer;
1116  }
1117 
1118 
1119  QVector<double> *CameraBuffers::emalBuffer(int currentLine, int ns, int currentBand) {
1120  loadBuffers(currentLine, ns, currentBand);
1121  return m_emalBuffer;
1122  }
1123 
1124 
1125  QVector<double> *CameraBuffers::phacBuffer(int currentLine, int ns, int currentBand) {
1126  loadBuffers(currentLine, ns, currentBand);
1127  return m_phacBuffer;
1128  }
1129 
1130 
1131  QVector<double> *CameraBuffers::inacBuffer(int currentLine, int ns, int currentBand) {
1132  loadBuffers(currentLine, ns, currentBand);
1133  return m_inacBuffer;
1134  }
1135 
1136 
1137  QVector<double> *CameraBuffers::emacBuffer(int currentLine, int ns, int currentBand) {
1138  loadBuffers(currentLine, ns, currentBand);
1139  return m_emacBuffer;
1140  }
1141 
1142 
1143  void CameraBuffers::loadBuffers(int currentLine, int ns, int currentBand) {
1144  if (currentLine != m_lastLine) {
1145  m_lastLine = currentLine;
1146 
1147  // Resize buffers if necessary
1148  if (m_phaBuffer) m_phaBuffer->resize(ns);
1149  if (m_inaBuffer) m_inaBuffer->resize(ns);
1150  if (m_emaBuffer) m_emaBuffer->resize(ns);
1151  if (m_latBuffer) m_latBuffer->resize(ns);
1152  if (m_lonBuffer) m_lonBuffer->resize(ns);
1153  if (m_resBuffer) m_resBuffer->resize(ns);
1154  if (m_radiusBuffer) m_radiusBuffer->resize(ns);
1155  if (m_phalBuffer) m_phalBuffer->resize(ns);
1156  if (m_inalBuffer) m_inalBuffer->resize(ns);
1157  if (m_emalBuffer) m_emalBuffer->resize(ns);
1158 
1159  // Center angle buffers will only ever have one item, the center angle value
1160  if (m_phacBuffer) m_phacBuffer->resize(1);
1161  if (m_inacBuffer) m_inacBuffer->resize(1);
1162  if (m_emacBuffer) m_emacBuffer->resize(1);
1163 
1164  m_camera->SetBand(currentBand);
1165 
1166  if (m_phacBuffer || m_inacBuffer || m_emacBuffer) {
1167  QString tokenName; // used for exception
1168  double centerLine = m_camera->Lines() / 2.0 + 0.5;
1169  double centerSamp = m_camera->Samples() / 2.0 + 0.5;
1170 
1171  if (m_camera->SetImage(centerSamp, centerLine)) {
1172  if (m_phacBuffer) {
1173  tokenName = "phac";
1174  (*m_phacBuffer)[0] = m_camera->PhaseAngle();
1175  }
1176  if (m_inacBuffer) {
1177  tokenName = "inac";
1178  (*m_inacBuffer)[0] = m_camera->IncidenceAngle();
1179  }
1180  if (m_emacBuffer) {
1181  tokenName = "emac";
1182  (*m_emacBuffer)[0] = m_camera->EmissionAngle();
1183  }
1184  }
1185  else {
1186  QString msg = "Unable to compute illumination angles at image center for operator ["
1187  + tokenName + "].";
1188  throw IException(IException::Unknown, msg, _FILEINFO_);
1189  }
1190  }
1191 
1192  else {
1193  for (int i = 0; i < ns; i++) {
1194 
1195  if (m_camera->SetImage(i + 1, currentLine)) {
1196  if (m_phaBuffer) (*m_phaBuffer)[i] = m_camera->PhaseAngle();
1197  if (m_inaBuffer) (*m_inaBuffer)[i] = m_camera->IncidenceAngle();
1198  if (m_emaBuffer) (*m_emaBuffer)[i] = m_camera->EmissionAngle();
1199  if (m_latBuffer) (*m_latBuffer)[i] = m_camera->UniversalLatitude();
1200  if (m_lonBuffer) (*m_lonBuffer)[i] = m_camera->UniversalLongitude();
1201  if (m_resBuffer) (*m_resBuffer)[i] = m_camera->PixelResolution();
1202  if (m_radiusBuffer) (*m_radiusBuffer)[i] = m_camera->LocalRadius().meters();
1203  if (m_phalBuffer || m_inalBuffer || m_emalBuffer) {
1204  Angle phal, inal, emal;
1205  bool okay;
1206  m_camera->LocalPhotometricAngles(phal, inal, emal, okay);
1207  if (okay) {
1208  if (m_phalBuffer) (*m_phalBuffer)[i] = phal.degrees();
1209  if (m_inalBuffer) (*m_inalBuffer)[i] = inal.degrees();
1210  if (m_emalBuffer) (*m_emalBuffer)[i] = emal.degrees();
1211  }
1212  else {
1213  if (m_phalBuffer) (*m_phalBuffer)[i] = NAN;
1214  if (m_inalBuffer) (*m_inalBuffer)[i] = NAN;
1215  if (m_emalBuffer) (*m_emalBuffer)[i] = NAN;
1216  }
1217  }
1218  }
1219  else {
1220  if (m_phaBuffer) (*m_phaBuffer)[i] = NAN;
1221  if (m_inaBuffer) (*m_inaBuffer)[i] = NAN;
1222  if (m_emaBuffer) (*m_emaBuffer)[i] = NAN;
1223  if (m_latBuffer) (*m_latBuffer)[i] = NAN;
1224  if (m_lonBuffer) (*m_lonBuffer)[i] = NAN;
1225  if (m_resBuffer) (*m_resBuffer)[i] = NAN;
1226  if (m_radiusBuffer) (*m_radiusBuffer)[i] = NAN;
1227  if (m_phalBuffer) (*m_phalBuffer)[i] = NAN;
1228  if (m_inalBuffer) (*m_inalBuffer)[i] = NAN;
1229  if (m_emalBuffer) (*m_emalBuffer)[i] = NAN;
1230  }
1231  }
1232  }
1233  }
1234  }
1235 
1236 } // End of namespace Isis
1237 
Isis::IString::ToDouble
double ToDouble() const
Returns the floating point value the IString represents.
Definition: IString.cpp:799
Isis::DataValue::constant
double constant()
Accesses the constant value of the DataValue.
Definition: CubeCalculator.cpp:923
Isis::PI
const double PI
The mathematical constant PI.
Definition: Constants.h:40
Isis::Average
Functor for reduce using average functionality.
Definition: Reduce.h:107
Isis::Calculator
Calculator for arrays.
Definition: Calculator.h:55
Isis::DataValue::type
DataValueType type()
Accesses the type of the DataValue.
Definition: CubeCalculator.cpp:903
Isis::Camera
Definition: Camera.h:236
Isis::IString::ToInteger
int ToInteger() const
Returns the object string as an integer.
Definition: IString.cpp:718
Isis::Cube::sampleCount
int sampleCount() const
Definition: Cube.cpp:1807
Isis::DataValue::DataValueType
DataValueType
This is used to tell what kind of data to push onto the RPN calculator.
Definition: CubeCalculator.h:135
Isis::Cube
IO Handler for Isis Cubes.
Definition: Cube.h:167
Isis::DataValue::cubeIndex
int cubeIndex()
Accesses the cube index of the DataValue.
Definition: CubeCalculator.cpp:913
Isis::IException
Isis exception class.
Definition: IException.h:91
std
Namespace for the standard library.
Isis::IString::Token
IString Token(const IString &separator)
Returns the first token in the IString.
Definition: IString.cpp:897
Isis::E
const double E
Sets some basic constants for use in ISIS programming.
Definition: Constants.h:39
Isis::DataValue
This class is used to define what kind of data is being pushed onto the cube calculator.
Definition: CubeCalculator.h:132
Isis::IString
Adds specific functionality to C++ strings.
Definition: IString.h:165
QVector< Calculations >
Isis
This is free and unencumbered software released into the public domain.
Definition: Apollo.h:16
Isis::IString::ToQt
QString ToQt() const
Retuns the object string as a QString.
Definition: IString.cpp:869
Isis::CameraBuffers
This class is used to manage buffers for calculating camera related information, such as angles,...
Definition: CubeCalculator.h:187