USGS

Isis 3.0 Object Programmers' Reference

Home

Process.cpp
Go to the documentation of this file.
1 
23 #include <sstream>
24 #include <fstream>
25 
26 #include <QSet>
27 
28 #include "SessionLog.h"
29 #include "Process.h"
30 #include "FileName.h"
31 #include "Message.h"
32 #include "IException.h"
33 #include "IString.h"
34 #include "Preference.h"
35 #include "Application.h"
36 #include "History.h"
37 #include "OriginalLabel.h"
38 #include "LineManager.h"
39 
40 using namespace std;
41 namespace Isis {
42 
44  Process::Process() {
45  m_ownedCubes = NULL;
46 
47  p_progress = new Isis::Progress();
48  p_progress->SetText("Working");
49  p_propagateLabels = true;
50  p_propagateTables = true;
51  p_propagatePolygons = true;
52  p_propagateHistory = true;
53  p_propagateOriginalLabel = true;
54 
55  m_ownedCubes = new QSet<Cube *>;
56  }
57 
59  Process::~Process() {
60  EndProcess();
61  delete p_progress;
62 
63  delete m_ownedCubes;
64  m_ownedCubes = NULL;
65  }
66 
82  Isis::Cube *Process::SetInputCube(const QString &fname,
83  const Isis::CubeAttributeInput &att,
84  int requirements) {
85  Isis::Cube *cube = new Isis::Cube;
86  if(att.bands().size() != 0) {
87  vector<QString> lame = att.bands();
88  cube->setVirtualBands(lame);
89  }
90 
91  try {
92  if(requirements & Isis::ReadWrite) {
93  cube->open(fname, "rw");
94  }
95  else {
96  cube->open(fname);
97  }
98  }
99  catch(IException &e) {
100  delete cube;
101  throw;
102  }
103 
104  // Test for same size or one in all dimensions
105  if(requirements & Isis::AllMatchOrOne) {
106  if(InputCubes.size() > 0) {
107  if(cube->lineCount() != 1) {
108  if(cube->lineCount() != InputCubes[0]->lineCount()) {
109  QString message = "The number of lines in the secondary input cubes must match";
110  message += " the primary input cube or be exactly one";
111  throw IException(IException::User, message, _FILEINFO_);
112  }
113  }
114 
115  if(cube->sampleCount() != 1) {
116  if(cube->sampleCount() != InputCubes[0]->sampleCount()) {
117  QString message = "The number of samples in the secondary input cubes must match";
118  message += " the primary input cube or be exactly one";
119  throw IException(IException::User, message, _FILEINFO_);
120  }
121  }
122  if(cube->bandCount() != 1) {
123  if(cube->bandCount() != InputCubes[0]->bandCount()) {
124  QString message = "The number of bands in the secondary input cubes must match";
125  message += " the primary input cube or be exactly one";
126  throw IException(IException::User, message, _FILEINFO_);
127  }
128  }
129 
130  // Do not do a spatial match if this flag was set
131  requirements = requirements & !Isis::SpatialMatch;
132  }
133  }
134 
135  // Test for size match if requested
136  if(requirements & Isis::SizeMatch) {
137  if(InputCubes.size() > 0) {
138  if(cube->lineCount() != InputCubes[0]->lineCount()) {
139  QString message = "The number of lines in the input cubes must match";
140  throw IException(IException::User, message, _FILEINFO_);
141  }
142  if(cube->sampleCount() != InputCubes[0]->sampleCount()) {
143  QString message = "The number of samples in the input cubes must match";
144  throw IException(IException::User, message, _FILEINFO_);
145  }
146  if(cube->bandCount() != InputCubes[0]->bandCount()) {
147  QString message = "The number of bands in the input cubes must match";
148  throw IException(IException::User, message, _FILEINFO_);
149  }
150  }
151  }
152 
153  // Test for spatial match if requested
154  if(requirements & Isis::SpatialMatch) {
155  if(InputCubes.size() > 0) {
156  if(cube->lineCount() != InputCubes[0]->lineCount()) {
157  QString message = "The number of lines in the input cubes must match";
158  throw IException(IException::User, message, _FILEINFO_);
159  }
160  if(cube->sampleCount() != InputCubes[0]->sampleCount()) {
161  QString message = "The number of samples in the input cubes must match";
162  throw IException(IException::User, message, _FILEINFO_);
163  }
164  }
165  }
166 
167  // Test for one band
168  if(requirements & Isis::OneBand) {
169  if(cube->bandCount() != 1) {
170  QString message = "Input cube [" + fname + "] must have one band";
171  throw IException(IException::User, message, _FILEINFO_);
172  }
173  }
174 
175  // Test for same bands or one band
176  if(requirements & Isis::BandMatchOrOne) {
177  if(cube->bandCount() != 1) {
178  if(InputCubes.size() > 0) {
179  if(cube->bandCount() != InputCubes[0]->bandCount()) {
180  QString message = "The number of bands in the secondary input cubes must match";
181  message += " the primary input cube or be exactly one";
182  throw IException(IException::User, message, _FILEINFO_);
183  }
184  }
185  }
186  }
187 
188  // Everything is good so save the cube on the stack
189  AddInputCube(cube);
190  return cube;
191  }
192 
201  void Process::SetInputCube(Isis::Cube *inCube)
202  {
203  if(inCube != NULL && inCube->isOpen()) {
204  AddInputCube(inCube, false);
205  }
206  else {
207  QString message = "Input cube does not exist";
208  throw IException(IException::User, message, _FILEINFO_);
209  }
210  }
211 
243  Isis::Cube *Process::SetInputCube(const QString &parameter,
244  const int requirements) {
245  QString fname = Application::GetUserInterface().GetFileName(parameter);
246  Isis::CubeAttributeInput &att = Application::GetUserInterface().GetInputAttribute(parameter);
247  return SetInputCube(fname, att, requirements);
248  }
249 
266  Isis::Cube *Process::SetOutputCube(const QString &parameter) {
267  // Make sure we have an input cube to get a default size from
268  if(InputCubes.size() == 0) {
269  QString message = "No input images have been selected ... therefore";
270  message += "the output image size can not be determined";
271  throw IException(IException::Programmer, message, _FILEINFO_);
272  }
273 
274  int nl = InputCubes[0]->lineCount();
275  int ns = InputCubes[0]->sampleCount();
276  int nb = InputCubes[0]->bandCount();
277  return SetOutputCube(parameter, ns, nl, nb);
278  }
279 
302  Isis::Cube *Process::SetOutputCube(const QString &parameter, const int ns,
303  const int nl, const int nb) {
304  // Make sure we have good dimensions
305  if((ns <= 0) || (nl <= 0) || (nb <= 0)) {
306  ostringstream message;
307  message << "Invalid cube size specifications [ns=" << ns << ",nl=" << nl
308  << ",nb=" << nb << "]";
309  throw IException(IException::Programmer, message.str().c_str(), _FILEINFO_);
310  }
311 
312  QString fname = Application::GetUserInterface().GetFileName(parameter);
313  Isis::CubeAttributeOutput &atts = Application::GetUserInterface().GetOutputAttribute(parameter);
314  return SetOutputCube(fname, atts, ns, nl, nb);
315  }
316 
334  Isis::Cube *Process::SetOutputCube(const QString &fname,
335  const Isis::CubeAttributeOutput &att,
336  const int ns, const int nl,
337  const int nb) {
338  // Make sure we have good dimensions
339  if ((ns <= 0) || (nl <= 0) || (nb <= 0)) {
340  ostringstream message;
341  message << "Invalid cube size specifications [ns=" << ns << ",nl=" << nl
342  << ",nb=" << nb << "]";
343  throw IException(IException::Programmer, message.str().c_str(), _FILEINFO_);
344  }
345 
346  // Setup the cube
347  Isis::Cube *cube = new Isis::Cube;
348  try {
349  cube->setDimensions(ns, nl, nb);
350  cube->setByteOrder(att.byteOrder());
351  cube->setFormat(att.fileFormat());
352  cube->setLabelsAttached(att.labelAttachment() == AttachedLabel);
353 
354  if(att.propagatePixelType()) {
355  if(InputCubes.size() > 0) {
356  cube->setPixelType(InputCubes[0]->pixelType());
357  }
358  else {
359  QString msg = "You told me to propagate PixelType from input to output";
360  msg += " cube but there are no input cubes loaded";
361  throw IException(IException::Programmer, msg, _FILEINFO_);
362  }
363  }
364  else {
365  cube->setPixelType(att.pixelType());
366  }
367 
368  if(att.propagateMinimumMaximum()) {
369  if(cube->pixelType() == Isis::Real) {
370  cube->setBaseMultiplier(0.0, 1.0);
371  }
372  else if(InputCubes.size() == 0) {
373  QString msg = "You told me to propagate base/multiplier from input to output";
374  msg += " cube but there are no input cubes loaded";
375  throw IException(IException::Programmer, msg, _FILEINFO_);
376  }
377  else if(cube->pixelType() >= InputCubes[0]->pixelType()) {
378  double base = InputCubes[0]->base();
379  double mult = InputCubes[0]->multiplier();
380  cube->setBaseMultiplier(base, mult);
381  }
382  else if((cube->pixelType() != Isis::Real) &&
383  (cube->pixelType() != Isis::UnsignedByte) &&
384  (cube->pixelType() != Isis::SignedWord)) {
385  QString msg = "Looks like your refactoring to add different pixel types";
386  msg += " you'll need to make changes here";
387  throw IException(IException::Programmer, msg, _FILEINFO_);
388  }
389  else {
390  QString msg = "You've chosen to reduce your output PixelType for [" +
391  fname + "] you must specify the output pixel range too";
392  throw IException(IException::User, msg, _FILEINFO_);
393  }
394  }
395  else {
396  // Not propagating so either the user entered or the programmer did
397  cube->setMinMax(att.minimum(), att.maximum());
398  }
399 
400  if(InputCubes.size() > 0) {
401  int needLabBytes = InputCubes[0]->labelSize(true) + (1024 * 6);
402  if(needLabBytes > cube->labelSize()) {
403  cube->setLabelSize(needLabBytes);
404  }
405  }
406 
407  // Allocate the cube
408  cube->create(fname);
409 
410  // Transfer labels from the first input cube
411  if((p_propagateLabels) && (InputCubes.size() > 0)) {
412  Isis::PvlObject &incube =
413  InputCubes[0]->label()->findObject("IsisCube");
414  Isis::PvlObject &outcube = cube->label()->findObject("IsisCube");
415  for(int i = 0; i < incube.groups(); i++) {
416  outcube.addGroup(incube.group(i));
417  }
418 
419  if (InputCubes[0]->label()->hasObject("NaifKeywords")) {
420  cube->label()->addObject(
421  InputCubes[0]->label()->findObject("NaifKeywords"));
422  }
423  }
424 
425  // Transfer tables from the first input cube
426  if((p_propagateTables) && (InputCubes.size() > 0)) {
427  Isis::Pvl &inlab = *InputCubes[0]->label();
428  for(int i = 0; i < inlab.objects(); i++) {
429  if(inlab.object(i).isNamed("Table")) {
430  Isis::Blob t((QString)inlab.object(i)["Name"], inlab.object(i).name());
431  InputCubes[0]->read(t);
432  cube->write(t);
433  }
434  }
435  }
436 
437  // Transfer blobs from the first input cube
438  if((p_propagatePolygons) && (InputCubes.size() > 0)) {
439  Isis::Pvl &inlab = *InputCubes[0]->label();
440  for(int i = 0; i < inlab.objects(); i++) {
441  if(inlab.object(i).isNamed("Polygon")) {
442  Isis::Blob t((QString)inlab.object(i)["Name"], inlab.object(i).name());
443  InputCubes[0]->read(t);
444  cube->write(t);
445  }
446  }
447  }
448 
449  // Transfer tables from the first input cube
450  if((p_propagateOriginalLabel) && (InputCubes.size() > 0)) {
451  Isis::Pvl &inlab = *InputCubes[0]->label();
452  for(int i = 0; i < inlab.objects(); i++) {
453  if(inlab.object(i).isNamed("OriginalLabel")) {
455  InputCubes[0]->read(ol);
456  cube->write(ol);
457  }
458  }
459  }
460 
461  // Transfer history from the first input cube
462  WriteHistory(*cube);
463  }
464  catch (IException &e) {
465  delete cube;
466  throw;
467  }
468 
469  // Everything is fine so save the cube on the stack
470  AddOutputCube(cube);
471  return cube;
472  }
473 
480  void Process::EndProcess() {
481  Process::Finalize();
482  }
483 
488  void Process::Finalize() {
489  ClearCubes();
490  }
491 
492  void Process::AddInputCube(Cube *cube, bool owned) {
493  InputCubes.push_back(cube);
494  if (owned) m_ownedCubes->insert(cube);
495  }
496 
497  void Process::AddOutputCube(Cube *cube, bool owned) {
498  OutputCubes.push_back(cube);
499  if (owned) m_ownedCubes->insert(cube);
500  }
501 
502 
506  void Process::ClearCubes() {
507  // Close the cubes
508  ClearInputCubes();
509  ClearOutputCubes();
510  m_ownedCubes->clear();
511  }
512 
516  void Process::ClearInputCubes() {
517  // Close the cubes
518  for (unsigned int i = 0; i < InputCubes.size(); i++) {
519  if (m_ownedCubes->contains(InputCubes[i])) {
520  InputCubes[i]->close();
521  delete InputCubes[i];
522  }
523  }
524  InputCubes.clear();
525  }
526 
530  void Process::ClearOutputCubes() {
531  // Close the cubes
532  for (unsigned int i = 0; i < OutputCubes.size(); i++) {
533  if (m_ownedCubes->contains(OutputCubes[i])) {
534  OutputCubes[i]->close();
535  delete OutputCubes[i];
536  }
537  }
538  OutputCubes.clear();
539  }
540 
552  void Process::PropagateLabels(const bool prop) {
553  p_propagateLabels = prop;
554  }
555 
563  void Process::PropagateLabels(const QString &cube) {
564  // Open the Pvl file
565  Isis::Pvl inLabels(cube);
566 
567  // Loop for each output cube
568  for(int i = 0; i < (int)OutputCubes.size(); i++) {
569  Isis::PvlObject &inCubeLabels = inLabels.findObject("IsisCube");
570 
571  Isis::Pvl &outLabels(*OutputCubes[i]->label());
572  Isis::PvlObject &outCubeLabels = outLabels.findObject("IsisCube");
573 
574  for(int g = 0; g < inCubeLabels.groups(); g++) {
575  outCubeLabels.addGroup(inCubeLabels.group(g));
576  }
577 
578  if (inLabels.hasObject("NaifKeywords")) {
579  outLabels.addObject(inLabels.findObject("NaifKeywords"));
580  }
581  }
582  }
583 
591  void Process::PropagateTables(const bool prop) {
592  p_propagateTables = prop;
593  }
594 
600  void Process::PropagateTables(const QString &fromName) {
601  Cube *fromCube = new Isis::Cube;
602  fromCube->open(fromName);
603  const Pvl *fromLabels = fromCube->label();
604 
605  for (unsigned int i = 0; i < OutputCubes.size(); i++) {
606  for (int j = 0; j < fromLabels->objects(); j++) {
607  const PvlObject &object = fromLabels->object(j);
608 
609  if (object.isNamed("Table")) {
610  Blob table((QString) object["Name"], object.name());
611  fromCube->read(table);
612  OutputCubes[i]->write(table);
613  }
614  }
615  }
616  }
617 
625  void Process::PropagatePolygons(const bool prop) {
626  p_propagatePolygons = prop;
627  }
628 
635  void Process::PropagateHistory(const bool prop) {
636  p_propagateHistory = prop;
637  }
638 
646  void Process::PropagateOriginalLabel(const bool prop) {
647  p_propagateOriginalLabel = prop;
648  }
649 
666  QString Process::MissionData(const QString &mission, const QString &file,
667  bool highestVersion) {
668  Isis::PvlGroup &dataDir = Isis::Preference::Preferences().findGroup("DataDirectory");
669  QString dir = dataDir[mission];
670 
671  // See if the data directory is installed
672  Isis::FileName installed(dir);
673  if(!installed.fileExists()) {
674  QString message = "Data directory for mission [" + mission + "] " +
675  "is not installed at your site";
676  throw IException(IException::Io, message, _FILEINFO_);
677  }
678 
679  Isis::FileName expanded(dir + "/" + file);
680  if(highestVersion) expanded = expanded.highestVersion();
681  return expanded.expanded();
682  }
683 
687  void Process::WriteHistory(Cube &cube) {
688  if(p_propagateHistory) {
689  bool addedHist = false;
690  if(InputCubes.size() > 0) {
691  Isis::Pvl & inlab = *InputCubes[0]->label();
692  for(int i = 0; i < inlab.objects(); i++) {
693  if(inlab.object(i).isNamed("History") && Isis::iApp != NULL) {
694  Isis::History h((QString)inlab.object(i)["Name"]);
695  InputCubes[0]->read(h);
696  h.AddEntry();
697  cube.write(h);
698  addedHist = true;
699  }
700  }
701  }
702 
703  if(!addedHist && Isis::iApp != NULL) {
704  Isis::History h("IsisCube");
705  h.AddEntry();
706  cube.write(h);
707  }
708  }
709  }
710 
721  void Process::CalculateStatistics() {
722  for(unsigned cubeNum = 0; cubeNum < InputCubes.size(); cubeNum++) {
723  Cube *cube = InputCubes[cubeNum];
724 
725  // Construct a line buffer manager and a statistics object
726  Isis::LineManager line(*cube);
727  Isis::Statistics *cubeStats = new Isis::Statistics();
728 
729  int bandStart = 1;
730  int bandStop = cube->bandCount();
731  int maxSteps = cube->lineCount() * cube->bandCount();
732 
733  QString cubeNumStr = toString(cubeNum + 1);
734  QString totalCubes = toString((int)InputCubes.size());
735  QString msg = "Calculating statistics for cube " + cubeNumStr + " of " + totalCubes;
736 
737  Isis::Progress progress;
738  progress.SetText(msg);
739  progress.SetMaximumSteps(maxSteps);
740  progress.CheckStatus();
741 
742  // Loop and get the statistics for a good minimum/maximum
743  vector<Statistics *> allBandStats;
744  for(int useBand = bandStart; useBand <= bandStop; useBand++) {
745  Isis::Statistics *bandStats = new Isis::Statistics();
746 
747  for(int i = 1; i <= cube->lineCount(); i++) {
748  line.SetLine(i, useBand);
749  cube->read(line);
750  bandStats->AddData(line.DoubleBuffer(), line.size());
751  cubeStats->AddData(line.DoubleBuffer(), line.size());
752  progress.CheckStatus();
753  }
754 
755  allBandStats.push_back(bandStats);
756  }
757 
758  p_bandStats.push_back(allBandStats);
759  p_cubeStats.push_back(cubeStats);
760  }
761  }
762 
763 } // end namespace isis
764