Isis 3 Programmer Reference
Cube.cpp
Go to the documentation of this file.
1 
23 #include "IsisDebug.h"
24 #include "Cube.h"
25 
26 #include <sstream>
27 #include <unistd.h>
28 
29 #include <QDebug>
30 #include <QDir>
31 #include <QFile>
32 #include <QFileInfo>
33 #include <QMutex>
34 
35 #include "Application.h"
36 #include "Camera.h"
37 #include "CameraFactory.h"
38 #include "CubeAttribute.h"
39 #include "CubeBsqHandler.h"
40 #include "CubeTileHandler.h"
41 #include "Endian.h"
42 #include "FileName.h"
43 #include "Histogram.h"
44 #include "IException.h"
45 #include "LineManager.h"
46 #include "Message.h"
47 #include "Preference.h"
48 #include "ProgramLauncher.h"
49 #include "Projection.h"
50 #include "SpecialPixel.h"
51 #include "Statistics.h"
52 #include "TProjection.h"
53 
54 using namespace std;
55 
56 namespace Isis {
58  Cube::Cube() {
59  construct();
60  }
61 
70  Cube::Cube(const FileName &fileName, QString access) {
71  construct();
72  open(fileName.toString(), access);
73  }
74 
75 
77  Cube::~Cube() {
78  close();
79 
80  delete m_mutex;
81  m_mutex = NULL;
82 
83  delete m_camera;
84  m_camera = NULL;
85 
86 
87  delete m_projection;
88  m_projection = NULL;
89 
90  delete m_formatTemplateFile;
91  m_formatTemplateFile = NULL;
92  }
93 
94 
100  bool Cube::isOpen() const {
101  bool open = (m_ioHandler != NULL);
102 
103  ASSERT(open == (bool)m_labelFile);
104  ASSERT(open == (bool)m_labelFileName);
105  ASSERT(open == (bool)m_label);
106 
107  return open;
108  }
109 
110 
119  bool Cube::isProjected() const {
120  return label()->findObject("IsisCube").hasGroup("Mapping");
121  }
122 
123 
130  bool Cube::isReadOnly() const {
131  bool readOnly = false;
132 
133  if (!isOpen()) {
134  QString msg = "No cube opened";
135  throw IException(IException::Programmer, msg, _FILEINFO_);
136  }
137 
138  if ((m_labelFile->openMode() & QIODevice::ReadWrite) != QIODevice::ReadWrite)
139  readOnly = true;
140 
141  return readOnly;
142  }
143 
144 
152  bool Cube::isReadWrite() const {
153  return !isReadOnly();
154  }
155 
156 
165  bool Cube::labelsAttached() const {
166  return m_attached;
167  }
168 
169 
177  void Cube::close(bool removeIt) {
178  if (isOpen() && isReadWrite())
179  writeLabels();
180 
181  cleanUp(removeIt);
182  }
183 
184 
193  Cube *Cube::copy(FileName newFile, const CubeAttributeOutput &newFileAttributes) {
194  if (!isOpen()) {
195  throw IException(IException::Unknown,
196  QObject::tr("Cube::copy requires the originating cube to be open"),
197  _FILEINFO_);
198  }
199 
200 
201  Cube *result = new Cube;
202 
203  if (newFileAttributes.labelAttachment() != ExternalLabel) {
204  result->setDimensions(sampleCount(), lineCount(), bandCount());
205  result->setByteOrder(newFileAttributes.byteOrder());
206  result->setFormat(newFileAttributes.fileFormat());
207 
208  if (newFileAttributes.labelAttachment() == DetachedLabel) {
209  result->setLabelsAttached(false);
210  }
211 
212  if (newFileAttributes.propagatePixelType()) {
213  result->setPixelType(pixelType());
214  }
215  else {
216  result->setPixelType(newFileAttributes.pixelType());
217  }
218 
219  if (newFileAttributes.propagateMinimumMaximum()) {
220  if(result->pixelType() == Isis::Real) {
221  result->setBaseMultiplier(0.0, 1.0);
222  }
223  else if(result->pixelType() >= pixelType()) {
224  result->setBaseMultiplier(base(), multiplier());
225  }
226  else {
227  QString msg =
228  QObject::tr("Cannot reduce the output PixelType for [%1] from [%2] without output "
229  "pixel range").arg(newFile.original()).arg(fileName());
230  throw IException(IException::User, msg, _FILEINFO_);
231  }
232  }
233  else {
234  // Not propagating so either the user entered or the programmer did
235  result->setMinMax(newFileAttributes.minimum(), newFileAttributes.maximum());
236  }
237 
238  result->setLabelSize(labelSize(true) + (1024 * 6));
239  }
240  else {
241  if (isReadWrite()) {
242  writeLabels();
243  m_ioHandler->clearCache(true);
244  }
245 
246  result->setExternalDnData(fileName());
247  }
248 
249  // Allocate the cube
250  result->create(newFile.expanded());
251 
252  PvlObject &isisCube = label()->findObject("IsisCube");
253  PvlObject &outIsisCube = result->label()->findObject("IsisCube");
254  for(int i = 0; i < isisCube.groups(); i++) {
255  outIsisCube.addGroup(isisCube.group(i));
256  }
257 
258  if (label()->hasObject("NaifKeywords")) {
259  result->label()->addObject(
260  label()->findObject("NaifKeywords"));
261  }
262 
263  for (int i = 0; i < m_label->objects(); i++) {
264  PvlObject &obj = m_label->object(i);
265  if (obj.isNamed("Table") || obj.isNamed("Polygon") || obj.isNamed("OriginalLabel") ||
266  obj.isNamed("History")) {
267  Isis::Blob t((QString)obj["Name"], obj.name());
268  read(t);
269  result->write(t);
270  }
271  }
272 
273  if (newFileAttributes.labelAttachment() != ExternalLabel) {
274  BufferManager input(sampleCount(), lineCount(), bandCount(),
275  sampleCount(), 1, 1,
276  pixelType());
277  BufferManager output(sampleCount(), lineCount(), bandCount(),
278  sampleCount(), 1, 1,
279  result->pixelType());
280 
281  input.begin();
282  output.begin();
283 
284  while (!input.end()) {
285  read(input);
286  output.Copy(input, false);
287 
288  result->write(output);
289 
290  input.next();
291  output.next();
292  }
293  }
294 
295 // Just in case the orig label doesn't work... here's original code:
296 // if((p_propagateOriginalLabel) && (InputCubes.size() > 0)) {
297 // Isis::Pvl &inlab = *InputCubes[0]->label();
298 // for(int i = 0; i < inlab.objects(); i++) {
299 // if(inlab.Object(i).isNamed("OriginalLabel")) {
300 // Isis::OriginalLabel ol;
301 // InputCubes[0]->read(ol);
302 // cube->write(ol);
303 // }
304 // }
305 // }
306 
307  return result;
308  }
309 
310 
331  void Cube::create(const QString &cubeFileName) {
332  // Already opened?
333  if (isOpen()) {
334  string msg = "You already have a cube opened";
335  throw IException(IException::Programmer, msg, _FILEINFO_);
336  }
337 
338  if (m_samples < 1 || m_lines < 1 || m_bands < 1) {
339  QString msg = "Number of samples [" + toString(m_samples) +
340  "], lines [" + toString(m_lines) + "], or bands [" + toString(m_bands) +
341  "] cannot be less than 1";
342  throw IException(IException::Programmer, msg, _FILEINFO_);
343  }
344 
345  if (m_pixelType == None) {
346  throw IException(IException::Unknown,
347  QString("Cannot create the cube [%1] with a pixel type set to None")
348  .arg(cubeFileName),
349  _FILEINFO_);
350  }
351 
352  if (m_storesDnData) {
353  // Make sure the cube is not going to exceed the maximum size preference
354  BigInt size = (BigInt)m_samples * m_lines *
355  (BigInt)m_bands * (BigInt)SizeOf(m_pixelType);
356 
357  size = size / 1024; // kb
358  size = size / 1024; // mb
359  size = size / 1024; // gb
360 
361  int maxSizePreference = 0;
362 
363  maxSizePreference =
364  Preference::Preferences().findGroup("CubeCustomization")["MaximumSize"];
365 
366  if (size > maxSizePreference) {
367  QString msg;
368  msg += "The cube you are attempting to create [" + cubeFileName + "] is ["
369  + toString(size) + "GB]. This is larger than the current allowed "
370  "size of [" + toString(maxSizePreference) + "GB]. The cube "
371  "dimensions were (S,L,B) [" + toString(m_samples) + ", " +
372  toString(m_lines) + ", " + toString(m_bands) + "] with [" +
373  toString(SizeOf(m_pixelType)) + "] bytes per pixel. If you still "
374  "wish to create this cube, the maximum value can be changed in your personal "
375  "preference file located in [~/.Isis/IsisPreferences] within the group "
376  "CubeCustomization, keyword MaximumSize. If you do not have an ISISPreference file, "
377  "please refer to the documentation \"Environment and Preference Setup\". Error ";
378  throw IException(IException::User, msg, _FILEINFO_);
379  }
380  }
381 
382  // Expand output name
383  FileName cubFile(cubeFileName);
384  PvlObject isiscube("IsisCube");
385  PvlObject core("Core");
386 
387  if (m_storesDnData) {
388  cubFile = cubFile.addExtension("cub");
389 
390  // See if we have attached or detached labels
391  if (m_attached) {
392  // StartByte is 1-based (why!!) so we need to do + 1
393  core += PvlKeyword("StartByte", toString(m_labelBytes + 1));
394  m_labelFileName = new FileName(cubFile);
395  m_dataFileName = new FileName(cubFile);
396  m_labelFile = new QFile(m_labelFileName->expanded());
397  }
398  else {
399  core += PvlKeyword("StartByte", toString(1));
400  core += PvlKeyword("^Core", cubFile.name());
401  m_dataFileName = new FileName(cubFile);
402  m_dataFile = new QFile(realDataFileName().expanded());
403 
404  FileName labelFileName(cubFile);
405  labelFileName = labelFileName.setExtension("lbl");
406  m_labelFileName = new FileName(labelFileName);
407  m_labelFile = new QFile(m_labelFileName->expanded());
408  }
409 
410  // Create the size of the core
411  PvlGroup dims("Dimensions");
412  dims += PvlKeyword("Samples", toString(m_samples));
413  dims += PvlKeyword("Lines", toString(m_lines));
414  dims += PvlKeyword("Bands", toString(m_bands));
415  core.addGroup(dims);
416 
417  // Create the pixel type
418  PvlGroup ptype("Pixels");
419  ptype += PvlKeyword("Type", PixelTypeName(m_pixelType));
420 
421  // And the byte ordering
422  ptype += PvlKeyword("ByteOrder", ByteOrderName(m_byteOrder));
423  ptype += PvlKeyword("Base", toString(m_base));
424  ptype += PvlKeyword("Multiplier", toString(m_multiplier));
425  core.addGroup(ptype);
426  }
427  else {
428  cubFile = cubFile.addExtension("ecub");
429 
430  ASSERT(m_dataFileName);
431 
432  core += PvlKeyword("^DnFile", m_dataFileName->original());
433 // m_dataFileName = new FileName(cubFile);
434  m_dataFile = new QFile(realDataFileName().expanded());
435 
436  m_labelFileName = new FileName(cubFile);
437  m_labelFile = new QFile(cubFile.expanded());
438  }
439 
440  isiscube.addObject(core);
441 
442  m_label = new Pvl;
443  m_label->addObject(isiscube);
444 
445  // Setup storage reserved for the label
446  PvlObject lbl("Label");
447  lbl += PvlKeyword("Bytes", toString(m_labelBytes));
448  m_label->addObject(lbl);
449 
450  const PvlGroup &pref =
451  Preference::Preferences().findGroup("CubeCustomization");
452  bool overwrite = pref["Overwrite"][0].toUpper() == "ALLOW";
453  if (!overwrite && m_labelFile->exists() && m_labelFile->size()) {
454  QString msg = "Cube file [" + m_labelFileName->original() + "] exists, " +
455  "user preference does not allow overwrite";
456  throw IException(IException::User, msg, _FILEINFO_);
457  }
458 
459  if (!m_labelFile->open(QIODevice::Truncate | QIODevice::ReadWrite)) {
460  QString msg = "Failed to create [" + m_labelFile->fileName() + "]. ";
461  msg += "Verify the output path exists and you have permission to write to the path.";
462  cleanUp(false);
463  throw IException(IException::Io, msg, _FILEINFO_);
464  }
465 
466  if (m_dataFile) {
467  if (m_storesDnData && !m_dataFile->open(QIODevice::Truncate | QIODevice::ReadWrite)) {
468  QString msg = "Failed to create [" + m_dataFile->fileName() + "]. ";
469  msg += "Verify the output path exists and you have permission to write to the path.";
470  cleanUp(false);
471  throw IException(IException::Io, msg, _FILEINFO_);
472  }
473  else if (!m_storesDnData && !m_dataFile->open(QIODevice::ReadOnly)) {
474  QString msg = "Failed to open [" + m_dataFile->fileName() + "] for reading. ";
475  msg += "Verify the output path exists and you have permission to read from the path.";
476  cleanUp(false);
477  throw IException(IException::Io, msg, _FILEINFO_);
478  }
479  }
480 
481  bool dataAlreadyOnDisk = m_storesDnData ? false : true;
482 
483  if (m_format == Bsq) {
484  m_ioHandler = new CubeBsqHandler(dataFile(), m_virtualBandList, realDataFileLabel(),
485  dataAlreadyOnDisk);
486  }
487  else {
488  m_ioHandler = new CubeTileHandler(dataFile(), m_virtualBandList, realDataFileLabel(),
489  dataAlreadyOnDisk);
490  }
491 
492  if (m_storesDnData)
493  m_ioHandler->updateLabels(*m_label);
494 
495  // Write the labels
496  writeLabels();
497  }
498 
499 
521  void Cube::create(
522  const QString &cubeFileName, const CubeAttributeOutput &att) {
523 
524  setByteOrder(att.byteOrder());
525  setFormat(att.fileFormat());
526  setLabelsAttached(att.labelAttachment() == AttachedLabel);
527  if (!att.propagatePixelType())
528  setPixelType(att.pixelType());
529  setMinMax(att.minimum(), att.maximum());
530 
531  // Allocate the cube
532  create(cubeFileName);
533  }
534 
535 
544  void Cube::open(const QString &cubeFileName, QString access) {
545  // Already opened?
546 
547  if (isOpen()) {
548  string msg = "You already have a cube opened";
549  throw IException(IException::Programmer, msg, _FILEINFO_);
550  }
551 
552  initLabelFromFile(cubeFileName, (access == "rw"));
553 
554  // Figure out the name of the data file
555  try {
556  PvlObject &core = m_label->findObject("IsisCube").findObject("Core");
557  // Detached labels
558  if (core.hasKeyword("^Core")) {
559  FileName temp(core["^Core"][0]);
560 
561  if (!temp.originalPath().startsWith("/")) {
562  m_dataFileName = new FileName(m_labelFileName->path() + "/" + temp.original());
563  }
564  else {
565  m_dataFileName = new FileName(temp);
566  }
567 
568  m_attached = false;
569  m_storesDnData = true;
570 
571  m_dataFile = new QFile(realDataFileName().expanded());
572  }
573  // External cube files (ecub), ecub contains all labels and SPICE blobs, history
574  else if (core.hasKeyword("^DnFile")) {
575  FileName dataFileName(core["^DnFile"][0]);
576 
577  if (dataFileName.originalPath() == ".") {
578  m_dataFileName = new FileName(m_labelFileName->path() + "/" + dataFileName.name());
579  }
580  else {
581  m_dataFileName = new FileName(dataFileName);
582  }
583 
584  m_attached = true;
585  m_storesDnData = false;
586  *m_dataFileName = FileName(realDataFileName().expanded());
587  m_dataFile = new QFile(realDataFileName().expanded());
588  }
589  // Typical cube containing labels, SPICE, history and dn data
590  else {
591  m_dataFileName = new FileName(*m_labelFileName);
592  m_attached = true;
593  m_storesDnData = true;
594  }
595  }
596  catch (IException &e) {
597  cleanUp(false);
598  throw;
599  }
600 
601  if (access == "r") {
602  if (!m_labelFile->open(QIODevice::ReadOnly)) {
603  QString msg = "Failed to open [" + m_labelFile->fileName() + "] with "
604  "read only access";
605  cleanUp(false);
606  throw IException(IException::Io, msg, _FILEINFO_);
607  }
608 
609  if (m_dataFile) {
610  if (!m_dataFile->open(QIODevice::ReadOnly)) {
611  QString msg = "Failed to open [" + m_dataFile->fileName() + "] with "
612  "read only access";
613  cleanUp(false);
614  throw IException(IException::Io, msg, _FILEINFO_);
615  }
616  }
617  }
618 
619  else if (access == "rw") {
620  if (!m_labelFile->open(QIODevice::ReadWrite)) {
621  QString msg = "Failed to open [" + m_labelFile->fileName() + "] with "
622  "read/write access";
623  cleanUp(false);
624  throw IException(IException::Io, msg, _FILEINFO_);
625  }
626 
627  if (m_dataFile) {
628  if (m_storesDnData && !m_dataFile->open(QIODevice::ReadWrite)) {
629  QString msg = "Failed to open [" + m_dataFile->fileName() + "] with "
630  "read/write access";
631  cleanUp(false);
632  throw IException(IException::Io, msg, _FILEINFO_);
633  }
634  else if (!m_storesDnData && !m_dataFile->open(QIODevice::ReadOnly)) {
635  QString msg = "Failed to open [" + m_dataFile->fileName() + "] with "
636  "read access";
637  cleanUp(false);
638  throw IException(IException::Io, msg, _FILEINFO_);
639  }
640  }
641  }
642  else {
643  QString msg = "Unknown value for access [" + access + "]. Expected 'r' "
644  " or 'rw'";
645  cleanUp(false);
646  throw IException(IException::Programmer, msg, _FILEINFO_);
647  }
648 
649  initCoreFromLabel(*m_label);
650 
651  // Determine the number of bytes in the label
652  if (m_attached) {
653  m_labelBytes = m_label->findObject("Label")["Bytes"];
654  }
655  else {
656  m_labelBytes = labelSize(true);
657  }
658 
659  QPair<bool, Pvl *> dataLabel = qMakePair(false, m_label);
660  if (!m_storesDnData) {
661  dataLabel = qMakePair(true, new Pvl(m_dataFileName->expanded()));
662  }
663 
664  // Now examine the format to see which type of handler to create
665  if (m_format == Bsq) {
666  m_ioHandler = new CubeBsqHandler(dataFile(), m_virtualBandList,
667  realDataFileLabel(), true);
668  }
669  else {
670  m_ioHandler = new CubeTileHandler(dataFile(), m_virtualBandList,
671  realDataFileLabel(), true);
672  }
673 
674  if (dataLabel.first) {
675  delete dataLabel.second;
676  dataLabel.second = NULL;
677  }
678 
679  applyVirtualBandsToLabel();
680  }
681 
682 
691  void Cube::reopen(QString access) {
692  if (!m_labelFile) {
693  QString msg = "Cube has not been opened yet. The filename to re-open is "
694  "unknown";
695  throw IException(IException::Programmer, msg, _FILEINFO_);
696  }
697 
698  // Preserve filename and virtual bands when re-opening
699  FileName filename = *m_labelFileName;
700  QList<int> virtualBandList;
701 
702  if (m_virtualBandList)
703  virtualBandList = *m_virtualBandList;
704 
705  close();
706  open(filename.expanded(), access);
707 
708  if (virtualBandList.size()) {
709  if (m_virtualBandList)
710  *m_virtualBandList = virtualBandList;
711  else
712  m_virtualBandList = new QList<int>(virtualBandList);
713  }
714  }
715 
716 
724  void Cube::read(Blob &blob) const {
725  if (!isOpen()) {
726  string msg = "The cube is not opened so you can't read a blob from it";
727  throw IException(IException::Programmer, msg, _FILEINFO_);
728  }
729 
730  FileName cubeFile = *m_labelFileName;
731  if (m_tempCube)
732  cubeFile = *m_tempCube;
733 
734  QMutexLocker locker(m_mutex);
735  QMutexLocker locker2(m_ioHandler->dataFileMutex());
736  blob.Read(cubeFile.toString(), *label());
737  }
738 
739 
746  void Cube::read(Buffer &bufferToFill) const {
747  if (!isOpen()) {
748  string msg = "Try opening a file before you read it";
749  throw IException(IException::Programmer, msg, _FILEINFO_);
750  }
751 
752  QMutexLocker locker(m_mutex);
753  m_ioHandler->read(bufferToFill);
754  }
755 
756 
763  void Cube::write(Blob &blob) {
764  if (!isOpen()) {
765  string msg = "The cube is not opened so you can't write a blob to it";
766  throw IException(IException::Programmer, msg, _FILEINFO_);
767  }
768 
769  if (!m_labelFile->isWritable()) {
770  string msg = "The cube must be opened in read/write mode, not readOnly";
771  throw IException(IException::Programmer, msg, _FILEINFO_);
772  }
773 
774  // Write an attached blob
775  if (m_attached) {
776  QMutexLocker locker(m_mutex);
777  QMutexLocker locker2(m_ioHandler->dataFileMutex());
778 
779  // Compute the number of bytes in the cube + label bytes and if the
780  // endpos of the file // is not greater than this then seek to that position.
781  fstream stream(m_labelFileName->expanded().toLatin1().data(),
782  ios::in | ios::out | ios::binary);
783  stream.seekp(0, ios::end);
784 
785  // End byte = end byte of the file (aka eof position, file size)
786  streampos endByte = stream.tellp();
787  // maxbyte = position after the cube DN data and labels
788  streampos maxbyte = (streampos) m_labelBytes;
789 
790  if (m_storesDnData) {
791  maxbyte += (streampos) m_ioHandler->getDataSize();
792  }
793 
794  // If EOF is too early, allocate space up to where we want the blob
795  if (endByte < maxbyte) {
796  stream.seekp(maxbyte, ios::beg);
797  }
798 
799  blob.Write(*m_label, stream);
800  }
801 
802  // Write a detached blob
803  else {
804  FileName blobFileName = fileName();
805  blobFileName = blobFileName.removeExtension();
806  blobFileName = blobFileName.addExtension(blob.Type());
807  blobFileName = blobFileName.addExtension(blob.Name());
808  QString blobFile(blobFileName.expanded());
809  ios::openmode flags = ios::in | ios::binary | ios::out | ios::trunc;
810  fstream detachedStream;
811  detachedStream.open(blobFile.toLatin1().data(), flags);
812  if (!detachedStream) {
813  QString message = "Unable to open data file [" +
814  blobFileName.expanded() + "]";
815  throw IException(IException::Io, message, _FILEINFO_);
816  }
817 
818 // Changed to work with mods to FileName class
819 // blob.Write(p_cube.label,detachedStream,blobFileName.baseName()+"."+
820 // blob.Type()+"."+
821 // blobFileName.extension());
822  blob.Write(*m_label, detachedStream, blobFileName.name());
823  }
824  }
825 
826 
833  void Cube::write(Buffer &bufferToWrite) {
834  if (!isOpen()) {
835  string msg = "Tried to write to a cube before opening/creating it";
836  throw IException(IException::Programmer, msg, _FILEINFO_);
837  }
838 
839  if (isReadOnly()) {
840  QString msg = "Cannot write to the cube [" + (QString)QFileInfo(fileName()).fileName() +
841  "] because it is opened read-only";
842  throw IException(IException::Programmer, msg, _FILEINFO_);
843  }
844 
845  if (!m_storesDnData) {
846  QString msg = "The cube [" + QFileInfo(fileName()).fileName() +
847  "] does not support storing DN data because it is using an external file for DNs";
848  throw IException(IException::Unknown, msg, _FILEINFO_);
849  }
850 
851  QMutexLocker locker(m_mutex);
852  m_ioHandler->write(bufferToWrite);
853  }
854 
855 
866  void Cube::setBaseMultiplier(double base, double mult) {
867  openCheck();
868  m_base = base;
869  m_multiplier = mult;
870  }
871 
872 
883  void Cube::setMinMax(double min, double max) {
884  openCheck();
885 
886  m_base = 0.0;
887  m_multiplier = 1.0;
888 
889  double x1, x2;
890  if (m_pixelType == UnsignedByte) {
891  x1 = VALID_MIN1;
892  x2 = VALID_MAX1;
893  m_multiplier = (max - min) / (x2 - x1);
894  m_base = min - m_multiplier * x1;
895  }
896  else if (m_pixelType == SignedWord) {
897  x1 = VALID_MIN2;
898  x2 = VALID_MAX2;
899  m_multiplier = (max - min) / (x2 - x1);
900  m_base = min - m_multiplier * x1;
901  }
902  else if (m_pixelType == UnsignedWord) {
903  x1 = VALID_MINU2;
904  x2 = VALID_MAXU2;
905  m_multiplier = (max - min) / (x2 - x1);
906  m_base = min - m_multiplier * x1;
907  }
908  }
909 
910 
917  void Cube::setByteOrder(ByteOrder byteOrder) {
918  openCheck();
919  m_byteOrder = byteOrder;
920  }
921 
922 
932  void Cube::setDimensions(int ns, int nl, int nb) {
933  openCheck();
934  if ((ns < 1) || (nl < 1) || (nb < 1)) {
935  string msg = "SetDimensions: Invalid number of sample, lines or bands";
936  throw IException(IException::Programmer, msg, _FILEINFO_);
937  }
938  m_samples = ns;
939  m_lines = nl;
940  m_bands = nb;
941  }
942 
943 
949  void Cube::setExternalDnData(FileName cubeFileWithDnData) {
950  try {
951  initLabelFromFile(cubeFileWithDnData, false);
952  initCoreFromLabel(*m_label);
953 
954  delete m_label;
955  m_label = NULL;
956  }
957  catch (IException &) {
958  delete m_label;
959  m_label = NULL;
960  throw;
961  }
962 
963  m_storesDnData = false;
964  m_dataFileName = new FileName(cubeFileWithDnData);
965 
966  delete m_labelFile;
967  m_labelFile = NULL;
968 
969  delete m_labelFileName;
970  m_labelFileName = NULL;
971  }
972 
973 
981  void Cube::setFormat(Format format) {
982  openCheck();
983  m_format = format;
984  }
985 
986 
993  void Cube::setLabelsAttached(bool attach) {
994  openCheck();
995  m_attached = attach;
996  }
997 
998 
1006  void Cube::setLabelSize(int labelBytes) {
1007  openCheck();
1008  m_labelBytes = labelBytes;
1009  }
1010 
1011 
1019  void Cube::setPixelType(PixelType pixelType) {
1020  openCheck();
1021  m_pixelType = pixelType;
1022  }
1023 
1024 
1036  void Cube::setVirtualBands(const QList<QString> &vbands) {
1037  openCheck();
1038  if (m_virtualBandList)
1039  m_virtualBandList->clear();
1040  else
1041  m_virtualBandList = new QList<int>;
1042 
1043  if (vbands.size() > 0) {
1044  QListIterator<QString> it(vbands);
1045  while (it.hasNext()) {
1046  m_virtualBandList->append(toInt(it.next()));
1047  }
1048  }
1049  else {
1050  delete m_virtualBandList;
1051  m_virtualBandList = NULL;
1052  }
1053 
1054  if (m_ioHandler) {
1055  m_ioHandler->setVirtualBands(m_virtualBandList);
1056  }
1057  }
1058 
1059 
1066  void Cube::setVirtualBands(const std::vector<QString> &vbands) {
1067  QList<QString> realVBands;
1068 
1069  for(unsigned int i = 0; i < vbands.size(); i++)
1070  realVBands << vbands[i];
1071 
1072  setVirtualBands(realVBands);
1073  }
1074 
1075 
1081  void Cube::relocateDnData(FileName dnDataFile) {
1082  if (!isOpen()) {
1083  throw IException(IException::Unknown,
1084  QString("Cannot relocate the DN data to [%1] for an external cube label "
1085  "file which is not open.")
1086  .arg(dnDataFile.original()),
1087  _FILEINFO_);
1088  }
1089 
1090 
1091  if (m_storesDnData) {
1092  throw IException(IException::Unknown,
1093  QString("The cube [%1] stores DN data. It cannot be relocated to [%2] - "
1094  "this is only supported for external cube label files.")
1095  .arg(m_labelFileName->original()).arg(dnDataFile.original()),
1096  _FILEINFO_);
1097  }
1098 
1099  m_label->findObject("IsisCube").findObject("Core").findKeyword("^DnFile")[0] =
1100  dnDataFile.original();
1101  reopen(m_labelFile->isWritable()? "rw" : "r");
1102  }
1103 
1104 
1105 // void Cube::relocateDnData(FileName externalLabelFile, FileName dnDataFile) {
1106 // try {
1107 // Pvl externalLabelData(externalLabelFile.expanded());
1108 // externalLabelData.FindObject("IsisCube").FindObject("Core").FindKeyword("^DnFile")[0] =
1109 // dnDataFile.original();
1110 // }
1111 // catch (IException &e) {
1112 // throw IException(e, IException::Io,
1113 // QString("File [%1] does not appear to be an external cube label file")
1114 // .arg(externalLabelFile.original().ToQt()),
1115 // _FILEINFO_);
1116 // }
1117 // }
1118 
1119 
1125  int Cube::bandCount() const {
1126  int numBands = m_bands;
1127  if (m_virtualBandList)
1128  numBands = m_virtualBandList->size();
1129  return numBands;
1130  }
1131 
1132 
1142  double Cube::base() const {
1143  return m_base;
1144  }
1145 
1146 
1154  ByteOrder Cube::byteOrder() const {
1155  return m_byteOrder;
1156  }
1157 
1158 
1166  Camera *Cube::camera() {
1167  if (m_camera == NULL && isOpen()) {
1168  m_camera = CameraFactory::Create(*this);
1169  }
1170  return m_camera;
1171  }
1172 
1173 
1180  FileName Cube::externalCubeFileName() const {
1181  if (!isOpen()) {
1182  throw IException(IException::Unknown,
1183  "An external cube label file must be opened in order to use "
1184  "Cube::getExternalCubeFileName",
1185  _FILEINFO_);
1186  }
1187 
1188  if (storesDnData()) {
1189  throw IException(IException::Unknown,
1190  "Cube::getExternalCubeFileName can only be called on an external cube label "
1191  "file",
1192  _FILEINFO_);
1193  }
1194 
1195 
1196  PvlObject &core = m_label->findObject("IsisCube").findObject("Core");
1197 
1198  return core["^DnFile"][0];
1199  }
1200 
1201 
1208  QString Cube::fileName() const {
1209  if (isOpen())
1210  return m_labelFileName->expanded();
1211  else
1212  return "";
1213  }
1214 
1215 
1220  Cube::Format Cube::format() const {
1221  return m_format;
1222  }
1223 
1224 
1244  Histogram *Cube::histogram(const int &band, QString msg) {
1245  return histogram(band, ValidMinimum, ValidMaximum, msg);
1246  }
1247 
1248 
1274  Histogram *Cube::histogram(const int &band, const double &validMin,
1275  const double &validMax, QString msg) {
1276  // Make sure cube is open
1277  if ( !isOpen() ) {
1278  QString msg = "Cannot create histogram object for an unopened cube";
1279  throw IException(IException::Programmer, msg, _FILEINFO_);
1280  }
1281 
1282  // Make sure band is valid
1283  if ((band < 0) || (band > bandCount())) {
1284  QString msg = "Invalid band in [CubeInfo::Histogram]";
1285  throw IException(IException::Programmer, msg, _FILEINFO_);
1286  }
1287 
1288  int bandStart = band;
1289  int bandStop = band;
1290  int maxSteps = lineCount();
1291  if (band == 0) {
1292  bandStart = 1;
1293  bandStop = bandCount();
1294  maxSteps = lineCount() * bandCount();
1295  }
1296 
1297  Progress progress;
1298  Histogram *hist = new Histogram(*this, band, &progress);
1299  LineManager line(*this);
1300 
1301  // This range is for throwing out data; the default parameters are OK always
1302  //hist->SetValidRange(validMin, validMax);
1303 
1304  // We now need to know the binning range - ValidMinimum/Maximum are no longer
1305  // acceptable, default to the bin range start/end.
1306  double binMin = validMin;
1307  double binMax = validMax;
1308  if (binMin == ValidMinimum) {
1309  binMin = hist->BinRangeStart();
1310  }
1311 
1312  if (binMax == ValidMaximum) {
1313  binMax = hist->BinRangeEnd();
1314  }
1315 
1316  //hist->SetBinRange(binMin, binMax);
1317  hist->SetValidRange(binMin,binMax);
1318 
1319  // Loop and get the histogram
1320  progress.SetText(msg);
1321  progress.SetMaximumSteps(maxSteps);
1322  progress.CheckStatus();
1323 
1324  for(int useBand = bandStart ; useBand <= bandStop ; useBand++) {
1325  for(int i = 1; i <= lineCount(); i++) {
1326  line.SetLine(i, useBand);
1327  read(line);
1328  hist->AddData(line.DoubleBuffer(), line.size());
1329  progress.CheckStatus();
1330  }
1331  }
1332 
1333  return hist;
1334  }
1335 
1336 
1346  Pvl *Cube::label() const {
1347  return m_label;
1348  }
1349 
1350 
1358  int Cube::labelSize(bool actual) const {
1359  int labelSize = m_labelBytes;
1360 
1361  if (actual && m_label) {
1362  ostringstream s;
1363  s << *m_label << endl;
1364  labelSize = s.tellp();
1365  }
1366  else if (actual) {
1367  labelSize = 0;
1368  }
1369 
1370  return labelSize;
1371  }
1372 
1373 
1379  int Cube::lineCount() const {
1380  return m_lines;
1381  }
1382 
1383 
1393  double Cube::multiplier() const {
1394  return m_multiplier;
1395  }
1396 
1397 
1403  PixelType Cube::pixelType() const {
1404  return m_pixelType;
1405  }
1406 
1407 
1418  int Cube::physicalBand(const int &virtualBand) const {
1419  int physicalBand = virtualBand;
1420 
1421  if (m_virtualBandList) {
1422  if ((virtualBand < 1) ||
1423  (virtualBand > m_virtualBandList->size())) {
1424  QString msg = "Out of array bounds [" + toString(virtualBand) + "]";
1425  throw IException(IException::Programmer, msg, _FILEINFO_);
1426  }
1427  physicalBand = m_virtualBandList->at(virtualBand - 1);
1428  }
1429 
1430  return physicalBand;
1431  }
1432 
1433 
1439  Projection *Cube::projection() {
1440  if (m_projection == NULL && isOpen()) {
1441  m_projection = ProjectionFactory::CreateFromCube(*label());
1442  }
1443  return m_projection;
1444  }
1445 
1446 
1452  int Cube::sampleCount() const {
1453  return m_samples;
1454  }
1455 
1456 
1475  Statistics *Cube::statistics(const int &band, QString msg) {
1476  return statistics(band, ValidMinimum, ValidMaximum, msg);
1477  }
1478 
1479 
1496  Statistics *Cube::statistics(const int &band, const double &validMin,
1497  const double &validMax, QString msg) {
1498  // Make sure cube is open
1499  if ( !isOpen() ) {
1500  QString msg = "Cannot create statistics object for an unopened cube";
1501  throw IException(IException::Programmer, msg, _FILEINFO_);
1502  }
1503 
1504  // Make sure band is valid
1505  if ((band < 0) || (band > bandCount())) {
1506  string msg = "Invalid band in [CubeInfo::Statistics]";
1507  throw IException(IException::Programmer, msg, _FILEINFO_);
1508  }
1509 
1510  // Construct a line buffer manager and a statistics object
1511  LineManager line(*this);
1512  Statistics *stats = new Statistics();
1513 
1514  stats->SetValidRange(validMin, validMax);
1515 
1516  int bandStart = band;
1517  int bandStop = band;
1518  int maxSteps = lineCount();
1519  if (band == 0) {
1520  bandStart = 1;
1521  bandStop = bandCount();
1522  maxSteps = lineCount() * bandCount();
1523  }
1524 
1525  Progress progress;
1526  progress.SetText(msg);
1527  progress.SetMaximumSteps(maxSteps);
1528  progress.CheckStatus();
1529 
1530  // Loop and get the statistics for a good minimum/maximum
1531  for(int useBand = bandStart ; useBand <= bandStop ; useBand++) {
1532  for(int i = 1; i <= lineCount(); i++) {
1533  line.SetLine(i, useBand);
1534  read(line);
1535  stats->AddData(line.DoubleBuffer(), line.size());
1536  progress.CheckStatus();
1537  }
1538  }
1539 
1540  return stats;
1541  }
1542 
1543 
1549  bool Cube::storesDnData() const {
1550  return m_storesDnData;
1551  }
1552 
1553 
1567  void Cube::addCachingAlgorithm(CubeCachingAlgorithm *algorithm) {
1568 
1569  if (isOpen() && m_ioHandler) {
1570  m_ioHandler->addCachingAlgorithm(algorithm);
1571  }
1572  else if (!isOpen()) {
1573  QString msg = "Cannot add a caching algorithm until the cube is open";
1574  throw IException(IException::Programmer, msg, _FILEINFO_);
1575  }
1576  }
1577 
1583  void Cube::clearIoCache() {
1584  if (m_ioHandler) {
1585  QMutexLocker locker(m_mutex);
1586  m_ioHandler->clearCache();
1587  }
1588  }
1589 
1590 
1600  bool Cube::deleteBlob(QString BlobType, QString BlobName) {
1601  for(int i = 0; i < m_label->objects(); i++) {
1602  PvlObject obj = m_label->object(i);
1603  if (obj.name().compare(BlobType) == 0) {
1604  if (obj.findKeyword("Name")[0] == BlobName) {
1605  m_label->deleteObject(i);
1606  return true;
1607  }
1608  }
1609  }
1610  return false;
1611  }
1612 
1613 
1622  void Cube::deleteGroup(const QString &group) {
1623  PvlObject &isiscube = label()->findObject("IsisCube");
1624  if (!isiscube.hasGroup(group)) return;
1625  isiscube.deleteGroup(group);
1626  }
1627 
1628 
1636  PvlGroup &Cube::group(const QString &group) const {
1637  PvlObject &isiscube = label()->findObject("IsisCube");
1638  return isiscube.findGroup(group);
1639  }
1640 
1641 
1649  bool Cube::hasGroup(const QString &group) const {
1650  const PvlObject &isiscube = label()->findObject("IsisCube");
1651  if (isiscube.hasGroup(group)) return true;
1652  return false;
1653  }
1654 
1655 
1663  bool Cube::hasTable(const QString &name) {
1664  for(int o = 0; o < label()->objects(); o++) {
1665  PvlObject &obj = label()->object(o);
1666  if (obj.isNamed("Table")) {
1667  if (obj.hasKeyword("Name")) {
1668  QString temp = (QString) obj["Name"];
1669  temp = temp.toUpper();
1670  QString temp2 = name;
1671  temp2 = temp2.toUpper();
1672  if (temp == temp2) return true;
1673  }
1674  }
1675  }
1676  return false;
1677  }
1678 
1679 
1688  void Cube::putGroup(const PvlGroup &group) {
1689  if (isReadOnly()) {
1690  QString msg = "Cannot add a group to the label of cube [" + (QString)QFileInfo(fileName()).fileName() +
1691  "] because it is opened read-only";
1692  throw IException(IException::Programmer, msg, _FILEINFO_);
1693  return;
1694  }
1695 
1696  PvlObject &isiscube = label()->findObject("IsisCube");
1697  if (isiscube.hasGroup(group.name())) {
1698  isiscube.findGroup(group.name()) = group;
1699  }
1700  else {
1701  isiscube.addGroup(group);
1702  }
1703  }
1704 
1705 
1710  void Cube::applyVirtualBandsToLabel() {
1711  PvlObject &core = m_label->findObject("IsisCube").findObject("Core");
1712 
1713  // Prune the band bin group if it exists
1714  if (m_label->findObject("IsisCube").hasGroup("BandBin")) {
1715  PvlGroup &bandBin = m_label->findObject("IsisCube").findGroup("BandBin");
1716  for (int k = 0;k < bandBin.keywords();k++) {
1717  if (bandBin[k].size() == m_bands && m_virtualBandList) {
1718  PvlKeyword temp = bandBin[k];
1719  bandBin[k].clear();
1720  for (int i = 0;i < m_virtualBandList->size();i++) {
1721  int physicalBand = m_virtualBandList->at(i) - 1;
1722  bandBin[k].addValue(temp[physicalBand], temp.unit(physicalBand));
1723  }
1724  }
1725  }
1726  }
1727 
1728  // Change the number of bands in the labels of the cube
1729  if (m_virtualBandList && core.hasGroup("Dimensions")) core.findGroup("Dimensions")["Bands"] = toString(m_virtualBandList->size());
1730  }
1731 
1732 
1738  void Cube::cleanUp(bool removeIt) {
1739  if (m_ioHandler) {
1740  delete m_ioHandler;
1741  m_ioHandler = NULL;
1742  }
1743 
1744  // Always remove a temporary file
1745  if (m_tempCube) {
1746  QFile::remove(m_tempCube->expanded());
1747  removeIt = false; // dont remove originals
1748 
1749  delete m_tempCube;
1750  m_tempCube = NULL;
1751  }
1752 
1753  if (removeIt) {
1754  QFile::remove(m_labelFileName->expanded());
1755 
1756  if (*m_labelFileName != *m_dataFileName)
1757  QFile::remove(m_dataFileName->expanded());
1758  }
1759 
1760  delete m_labelFile;
1761  m_labelFile = NULL;
1762 
1763  delete m_dataFile;
1764  m_dataFile = NULL;
1765 
1766  delete m_labelFileName;
1767  m_labelFileName = NULL;
1768 
1769  delete m_dataFileName;
1770  m_dataFileName = NULL;
1771 
1772  delete m_label;
1773  m_label = NULL;
1774 
1775  delete m_virtualBandList;
1776  m_virtualBandList = NULL;
1777 
1778  initialize();
1779  }
1780 
1781 
1786  void Cube::construct() {
1787  m_labelFile = NULL;
1788  m_dataFile = NULL;
1789  m_ioHandler = NULL;
1790  m_mutex = NULL;
1791 
1792  m_camera = NULL;
1793  m_projection = NULL;
1794 
1795  m_labelFileName = NULL;
1796  m_dataFileName = NULL;
1797  m_tempCube = NULL;
1798  m_formatTemplateFile = NULL;
1799  m_label = NULL;
1800 
1801  m_virtualBandList = NULL;
1802 
1803  m_mutex = new QMutex();
1804  m_formatTemplateFile =
1805  new FileName("$base/templates/labels/CubeFormatTemplate.pft");
1806 
1807  initialize();
1808  }
1809 
1810 
1817  QFile *Cube::dataFile() const {
1818  if (m_dataFile)
1819  return m_dataFile;
1820  else
1821  return m_labelFile;
1822  }
1823 
1824 
1832  FileName Cube::realDataFileName() const {
1833  FileName result;
1834 
1835  // Attached, stores DN data - normal cube
1836  if (m_attached && m_storesDnData) {
1837  ASSERT(m_labelFileName);
1838  result = *m_labelFileName;
1839  }
1840  // Detached, stores DN data - standard detached cube
1841  else if (!m_attached && m_storesDnData) {
1842  ASSERT(m_dataFileName);
1843  result = *m_dataFileName;
1844  }
1845  // External cube - go look at our external file
1846  else if (!m_storesDnData) {
1847  ASSERT(m_dataFileName);
1848  FileName guess = *m_dataFileName;
1849  QDir dir(guess.toString());
1850 
1851  // If path is relative and there is a labelFileName, start in directory of the ecub, then
1852  // cd to the directory containing the DnFile, since it is relative to the location of the ecub.
1853  // We need to turn the relative path into an absolute path.
1854  if (dir.isRelative() && m_labelFileName) {
1855  QDir dir2(m_labelFileName->originalPath());
1856  dir2.cd(guess.path());
1857  guess = dir2.absolutePath() + "/" + guess.name();
1858  }
1859  do {
1860  Pvl guessLabel(guess.expanded());
1861 
1862  PvlObject &core = guessLabel.findObject("IsisCube").findObject("Core");
1863 
1864  if (core.hasKeyword("^DnFile")) {
1865  FileName currentGuess = guess;
1866  guess = core["^DnFile"][0];
1867 
1868  if (!guess.path().startsWith("/")) {
1869  guess = currentGuess.path() + "/" + guess.original();
1870  }
1871  }
1872  else if (core.hasKeyword("^Core")) {
1873  result = core["^Core"][0];
1874  }
1875  else {
1876  result = guess;
1877  }
1878  }
1879  while (result.name() == "");
1880  }
1881 
1882  return result;
1883  }
1884 
1885 
1897  void Cube::initialize() {
1898  m_byteOrder = Lsb;
1899  if (IsBigEndian())
1900  m_byteOrder = Msb;
1901  m_format = Tile;
1902  m_pixelType = Real;
1903 
1904  m_attached = true;
1905  m_storesDnData = true;
1906  m_labelBytes = 65536;
1907 
1908  m_samples = 0;
1909  m_lines = 0;
1910  m_bands = 0;
1911 
1912  m_base = 0.0;
1913  m_multiplier = 1.0;
1914  }
1915 
1916 
1922  void Cube::initCoreFromLabel(const Pvl &label) {
1923  const PvlObject &core = label.findObject("IsisCube").findObject("Core");
1924 
1925  if (!core.hasKeyword("^DnFile")) {
1926  // Dimensions
1927  const PvlGroup &dims = core.findGroup("Dimensions");
1928  m_samples = dims["Samples"];
1929  m_lines = dims["Lines"];
1930  m_bands = dims["Bands"];
1931 
1932  // Stored pixel information
1933  const PvlGroup &pixelsGroup = core.findGroup("Pixels");
1934  m_byteOrder = ByteOrderEnumeration(pixelsGroup["ByteOrder"]);
1935  m_base = pixelsGroup["Base"];
1936  m_multiplier = pixelsGroup["Multiplier"];
1937  m_pixelType = PixelTypeEnumeration(pixelsGroup["Type"]);
1938 
1939  // Now examine the format to see which type of handler to create
1940  if ((QString) core["Format"] == "BandSequential") {
1941  m_format = Bsq;
1942  }
1943  else {
1944  m_format = Tile;
1945  }
1946  }
1947  else {
1948  FileName temp(core["^DnFile"][0]);
1949  if (!temp.expanded().startsWith("/")) {
1950  temp = FileName(m_labelFileName->path() + "/" + temp.original());
1951  }
1952 
1953  initCoreFromLabel(Pvl(temp.toString()));
1954  }
1955  }
1956 
1957 
1966  void Cube::initLabelFromFile(FileName labelFileName, bool readWrite) {
1967  ASSERT(!m_labelFileName);
1968 
1969  try {
1970  if (labelFileName.fileExists()) {
1971  m_label = new Pvl(labelFileName.expanded());
1972  if (!m_label->objects()) {
1973  throw IException();
1974  }
1975  }
1976  }
1977  catch(IException &) {
1978  if (m_label) {
1979  delete m_label;
1980  m_label = NULL;
1981  }
1982  }
1983 
1984  try {
1985  if (!m_label) {
1986  FileName tmp(labelFileName);
1987  tmp = tmp.addExtension("cub");
1988  if (tmp.fileExists()) {
1989  m_label = new Pvl(tmp.expanded());
1990  if (!m_label->objects()) {
1991  throw IException();
1992  }
1993  labelFileName = tmp;
1994  }
1995  }
1996  }
1997  catch(IException &e) {
1998  if (m_label) {
1999  delete m_label;
2000  m_label = NULL;
2001  }
2002  }
2003 
2004  try {
2005  if (!m_label) {
2006  FileName tmp(labelFileName);
2007  tmp = tmp.setExtension("lbl");
2008  if (tmp.fileExists()) {
2009  m_label = new Pvl(tmp.expanded());
2010  if (!m_label->objects()) {
2011  throw IException();
2012  }
2013  labelFileName = tmp;
2014  }
2015  }
2016  }
2017  catch(IException &e) {
2018  if (m_label) {
2019  delete m_label;
2020  m_label = NULL;
2021  }
2022  }
2023 
2024  try {
2025  if (!m_label) {
2026  FileName tmp(labelFileName);
2027  tmp = tmp.addExtension("ecub");
2028  if (tmp.fileExists()) {
2029  m_label = new Pvl(tmp.expanded());
2030  if (!m_label->objects()) {
2031  throw IException();
2032  }
2033  labelFileName = tmp;
2034  }
2035  }
2036  }
2037  catch(IException &e) {
2038  if (m_label) {
2039  delete m_label;
2040  m_label = NULL;
2041  }
2042  }
2043 
2044  if (!m_label) {
2045  QString msg = Message::FileOpen(labelFileName.original());
2046  throw IException(IException::Io, msg, _FILEINFO_);
2047  }
2048 
2049  m_labelFileName = new FileName(labelFileName);
2050 
2051  // See if this is an old Isis cube format. If so then we will
2052  // need to internalize a new label
2053  if (m_label->hasKeyword("CCSD3ZF0000100000001NJPL3IF0PDS200000001")) {
2054  if (!readWrite) {
2055  reformatOldIsisLabel(m_labelFileName->expanded());
2056  }
2057  else {
2058  QString msg = "Can not open [" + m_labelFileName->original() + "]"
2059  " because it is an ISIS2 cube.";
2060  cleanUp(false);
2061  throw IException(IException::Io, msg, _FILEINFO_);
2062  }
2063  }
2064  else {
2065  m_labelFile = new QFile(m_labelFileName->expanded());
2066  }
2067  }
2068 
2069 
2073  void Cube::openCheck() {
2074  if (isOpen()) {
2075  string msg = "Sorry you can't do a SetMethod after the cube is opened";
2076  throw IException(IException::Programmer, msg, _FILEINFO_);
2077  }
2078  }
2079 
2080 
2086  Pvl Cube::realDataFileLabel() const {
2087  Pvl label = *m_label;
2088  PvlObject *core = NULL;
2089 
2090  do {
2091  core = &label.findObject("IsisCube").findObject("Core");
2092 
2093  if (core->hasKeyword("^DnFile")) {
2094 
2095  FileName temp((*core)["^DnFile"][0]);
2096  if (!temp.expanded().startsWith("/")) {
2097  temp = realDataFileName();
2098  }
2099 
2100  label = Pvl(temp.toString());
2101  core = NULL;
2102  }
2103  }
2104  while (!core);
2105 
2106  return label;
2107  }
2108 
2109 
2116  void Cube::reformatOldIsisLabel(const QString &oldCube) {
2117  QString parameters = "from=" + oldCube;
2118  FileName oldName(oldCube);
2119  FileName tempCube = FileName::createTempFile("Temporary_" + oldName.name() + ".cub");
2120  parameters += " to=" + tempCube.expanded();
2121 
2122  if (iApp == NULL) {
2123  QString command = "$ISISROOT/bin/pds2isis " + parameters;
2124  ProgramLauncher::RunSystemCommand(command);
2125  }
2126  else {
2127  QString prog = "pds2isis";
2128  ProgramLauncher::RunIsisProgram(prog, parameters);
2129  }
2130 
2131  m_tempCube = new FileName(tempCube);
2132  *m_label = Pvl(m_tempCube->toString());
2133  m_labelFile = new QFile(m_tempCube->expanded());
2134  }
2135 
2136 
2146  void Cube::latLonRange(double &minLatitude, double &maxLatitude, double &minLongitude, double &
2147  maxLongitude) {
2148  Camera *cam;
2149  TProjection *proj;
2150 
2151  bool isGood = false;
2152  bool useProj = true;
2153 
2154  if (hasGroup("Instrument")) {
2155  useProj = false;
2156  }
2157 
2158  // setup camera or projection
2159  if (useProj) {
2160  try {
2161  proj = (TProjection *) projection();
2162  }
2163  catch(IException &e) {
2164  QString msg = "Cannot calculate lat/lon range without a camera or projection";
2165  throw IException(e, IException::User, msg, _FILEINFO_);
2166  }
2167  }
2168  else {
2169  try {
2170  cam = camera();
2171  }
2172  catch(IException &e) {
2173  QString msg = "Unable to create camera when calculating a lat/lon range.";
2174  throw IException(e, IException::User, msg, _FILEINFO_);
2175  }
2176  }
2177 
2178  // Iterate over all samp/line combos in cube
2179  minLatitude = 99999;
2180  minLongitude = 99999;
2181  maxLatitude = -99999;
2182  maxLongitude = -99999;
2183 
2184  for (double sample = 0.5; sample < sampleCount() + 0.5; sample++) {
2185  // Checks to see if the point is in outer space
2186  for (double line = 0.5; line < lineCount() + 0.5; line++) {
2187  if (useProj) {
2188  isGood = proj->SetWorld(sample, line);
2189  }
2190  else {
2191  isGood = cam->SetImage(sample, line);
2192  }
2193 
2194  double lat, lon;
2195  if (isGood) {
2196  if (useProj) {
2197  lat = proj->UniversalLatitude();
2198  lon = proj->UniversalLongitude();
2199  }
2200  else {
2201  lat = cam->UniversalLatitude();
2202  lon = cam->UniversalLongitude();
2203  }
2204 
2205  // update mix/max lat/lons
2206  if (lat < minLatitude) {
2207  minLatitude = lat;
2208  }
2209  else if (lat > maxLatitude) {
2210  maxLatitude = lat;
2211  }
2212 
2213  if (lon < minLongitude) {
2214  minLongitude = lon;
2215  }
2216  else if (lon > maxLongitude) {
2217  maxLongitude = lon;
2218  }
2219  }
2220  }
2221  }
2222  if ( (minLatitude == 99999) || (minLongitude == 99999) || (maxLatitude == -99999) ||
2223  (maxLongitude == -99999) ) {
2224  QString msg = "Unable to calculate a minimum or maximum latitutde or longitude.";
2225  throw IException(IException::Unknown, msg, _FILEINFO_);
2226  }
2227  }
2228 
2233  void Cube::writeLabels() {
2234  if (!isOpen()) {
2235  string msg = "Cube must be opened first before writing labels";
2236  throw IException(IException::Programmer, msg, _FILEINFO_);
2237  }
2238 
2239  // Set the pvl's format template
2240  m_label->setFormatTemplate(m_formatTemplateFile->original());
2241 
2242  // Write them with attached data
2243  if (m_attached) {
2244  QMutexLocker locker(m_mutex);
2245  QMutexLocker locker2(m_ioHandler->dataFileMutex());
2246 
2247  ostringstream temp;
2248  temp << *m_label << endl;
2249  string tempstr = temp.str();
2250  if ((int) tempstr.length() < m_labelBytes) {
2251  QByteArray labelArea(m_labelBytes, '\0');
2252  QByteArray labelUnpaddedContents(tempstr.c_str(), tempstr.length());
2253  labelArea.replace(0, labelUnpaddedContents.size(), labelUnpaddedContents);
2254  // Rewrite the label area
2255  m_labelFile->seek(0);
2256  m_labelFile->write(labelArea);
2257  }
2258  else {
2259  locker2.unlock();
2260  QString msg = "Label space is full in [" +
2261  (QString)FileName(*m_labelFileName).name() +
2262  "] unable to write labels";
2263  cleanUp(false);
2264  throw IException(IException::Io, msg, _FILEINFO_);
2265  }
2266  }
2267 
2268  // or detached label
2269  else {
2270  m_label->write(m_labelFileName->expanded());
2271  }
2272  }
2273 }
PvlObject & object(const int index)
Return the object at the specified index.
Definition: PvlObject.cpp:460
bool SetLine(const int line, const int band=1)
Positions the buffer at the requested line and returns a status indicator if the set was succesful or...
Definition: LineManager.cpp:60
Buffer for reading and writing cube data.
Definition: Buffer.h:69
long long int BigInt
Big int.
Definition: Constants.h:65
void AddData(const double *data, const unsigned int count)
Add an array of doubles to the histogram counters.
Definition: Histogram.cpp:453
int keywords() const
Returns the number of keywords contained in the PvlContainer.
Definition: PvlContainer.h:100
QString path() const
Returns the path of the file name.
Definition: FileName.cpp:119
double * DoubleBuffer() const
Returns the value of the shape buffer.
Definition: Buffer.h:154
The label is pointing to an external DN file - the label is also external to the data.
Definition: CubeAttribute.h:56
QString unit(const int index=0) const
Returns the units of measurement of the element of the array of values for the object at the specifie...
Definition: PvlKeyword.cpp:373
PixelType pixelType() const
Return the pixel type as an Isis::PixelType.
void SetMaximumSteps(const int steps)
This sets the maximum number of steps in the process.
Definition: Progress.cpp:101
PvlGroupIterator findGroup(const QString &name, PvlGroupIterator beg, PvlGroupIterator end)
Find a group with the specified name, within these indexes.
Definition: PvlObject.h:141
ByteOrder byteOrder() const
Return the byte order as an Isis::ByteOrder.
const double ValidMinimum
The minimum valid double value for Isis pixels.
Definition: SpecialPixel.h:102
File name manipulation and expansion.
Definition: FileName.h:116
IO Handler for Isis Cubes using the BSQ format.
double UniversalLatitude() const
Returns the planetocentric latitude, in degrees, at the surface intersection point in the body fixed ...
Definition: Sensor.cpp:225
void Read(const QString &file)
This method reads Pvl values from a specified file.
Definition: Blob.cpp:243
Base class for Map TProjections.
Definition: TProjection.h:182
PvlObjectIterator findObject(const QString &name, PvlObjectIterator beg, PvlObjectIterator end)
Find the index of object with a specified name, between two indexes.
Definition: PvlObject.h:286
int SizeOf(Isis::PixelType pixelType)
Returns the number of bytes of the specified PixelType.
Definition: PixelType.h:62
void addGroup(const Isis::PvlGroup &group)
Add a group to the object.
Definition: PvlObject.h:198
FileName addExtension(const QString &extension) const
Adds a new extension to the file name.
Definition: FileName.cpp:241
void Write(const QString &file)
Write the blob data out to a file.
Definition: Blob.cpp:369
int toInt(const QString &string)
Global function to convert from a string to an integer.
Definition: IString.cpp:108
QString PixelTypeName(Isis::PixelType pixelType)
Returns string name of PixelType enumeration entered as input parameter.
Definition: PixelType.h:82
void setFormat(Format format)
Used prior to the Create method, this will specify the format of the cube, either band...
Definition: Cube.cpp:981
Namespace for the standard library.
ByteOrder
Tests the current architecture for byte order.
Definition: Endian.h:59
bool propagatePixelType() const
Return true if the pixel type is to be propagated from an input cube.
QString name() const
Returns the name of the file excluding the path and the attributes in the file name.
Definition: FileName.cpp:178
double UniversalLongitude()
This returns a universal longitude (positive east in 0 to 360 domain).
void setLabelsAttached(bool attached)
Use prior to calling create, this sets whether or not to use separate label and data files...
Definition: Cube.cpp:993
bool propagateMinimumMaximum() const
Return true if the min/max are to be propagated from an input cube.
bool hasGroup(const QString &name) const
Returns a boolean value based on whether the object has the specified group or not.
Definition: PvlObject.h:222
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition: IString.cpp:226
QString originalPath() const
Returns the path of the original file name.
Definition: FileName.cpp:100
void deleteGroup(const QString &name)
Remove a group from the current PvlObject.
Definition: PvlObject.cpp:379
void CheckStatus()
Checks and updates the status.
Definition: Progress.cpp:121
void setDimensions(int ns, int nl, int nb)
Used prior to the Create method to specify the size of the cube.
Definition: Cube.cpp:932
bool hasKeyword(const QString &kname, FindOptions opts) const
See if a keyword is in the current PvlObject, or deeper inside other PvlObjects and Pvlgroups within ...
Definition: PvlObject.cpp:207
int size() const
Returns the total number of pixels in the shape buffer.
Definition: Buffer.h:113
PixelType
Enumerations for Isis Pixel Types.
Definition: PixelType.h:43
bool begin()
Moves the shape buffer to the first position.
void addObject(const PvlObject &object)
Add a PvlObject.
Definition: PvlObject.h:319
Buffer manager, for moving through a cube in lines.
Definition: LineManager.h:55
QString name() const
Returns the container name.
Definition: PvlContainer.h:77
bool SetImage(const double sample, const double line)
Sets the sample/line values of the image to get the lat/lon values.
Definition: Camera.cpp:170
This class is used to accumulate statistics on double arrays.
Definition: Statistics.h:107
void SetValidRange(const double minimum=Isis::ValidMinimum, const double maximum=Isis::ValidMaximum)
Changes the range of the bins.
Definition: Histogram.cpp:413
The input label is in a separate data file from the image.
Definition: CubeAttribute.h:49
Isis::PixelType PixelTypeEnumeration(const QString &type)
Returns PixelType enumeration given a string.
Definition: PixelType.h:105
Base class for Map Projections.
Definition: Projection.h:171
Program progress reporter.
Definition: Progress.h:58
void setPixelType(PixelType pixelType)
Used prior to the Create method, this will specify the output pixel type.
Definition: Cube.cpp:1019
Container of a cube histogram.
Definition: Histogram.h:86
void SetText(const QString &text)
Changes the value of the text string reported just before 0% processed.
Definition: Progress.cpp:77
Manages a Buffer over a cube.
Definition: BufferManager.h:68
bool IsBigEndian()
Definition: Endian.h:122
PvlKeyword & findKeyword(const QString &kname, FindOptions opts)
Finds a keyword in the current PvlObject, or deeper inside other PvlObjects and Pvlgroups within this...
Definition: PvlObject.cpp:148
Contains multiple PvlContainers.
Definition: PvlGroup.h:57
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:40
bool next()
Moves the shape buffer to the next position.
Manipulate and parse attributes of output cube filenames.
void setBaseMultiplier(double base, double mult)
Used prior to the Create method, this will specify the base and multiplier for converting 8-bit/16-bi...
Definition: Cube.cpp:866
A single keyword-value pair.
Definition: PvlKeyword.h:98
double maximum() const
Return the output cube attribute maximum.
QString expanded() const
Returns a QString of the full file name including the file path, excluding the attributes.
Definition: FileName.cpp:212
QString original() const
Returns the full file name including the file path.
Definition: FileName.cpp:228
The input label is embedded in the image file.
Definition: CubeAttribute.h:48
Cube::Format fileFormat() const
Return the file format an Cube::Format.
IO Handler for Isis Cubes using the tile format.
bool end() const
Returns true if the shape buffer has accessed the end of the cube.
Container for cube-like labels.
Definition: Pvl.h:135
double UniversalLongitude() const
Returns the positive east, 0-360 domain longitude, in degrees, at the surface intersection point in t...
Definition: Sensor.cpp:248
PixelType pixelType() const
Definition: Cube.cpp:1403
void deleteObject(const QString &name)
Remove an object from the current PvlObject.
Definition: PvlObject.cpp:337
void setByteOrder(ByteOrder byteOrder)
Used prior to the Create method, this will specify the byte order of pixels, either least or most sig...
Definition: Cube.cpp:917
double UniversalLatitude()
This returns a universal latitude (planetocentric).
bool SetWorld(const double x, const double y)
This method is used to set a world coordinate.
Definition: Projection.cpp:512
bool isNamed(const QString &match) const
Returns whether the given string is equal to the container name or not.
Definition: PvlContainer.h:86
QString Name() const
Accessor method that returns a string containing the Blob name.
Definition: Blob.cpp:149
PvlGroup & group(const int index)
Return the group at the specified index.
Definition: PvlObject.cpp:423
QString toString() const
Returns a QString of the full file name including the file path, excluding the attributes with any Is...
Definition: FileName.cpp:531
void setMinMax(double min, double max)
Used prior to the Create method, this will compute a good base and multiplier value given the minimum...
Definition: Cube.cpp:883
Pvl * label() const
Returns a pointer to the IsisLabel object associated with the cube.
Definition: Cube.cpp:1346
const double ValidMaximum
The maximum valid double value for Isis pixels.
Definition: SpecialPixel.h:137
void write(Blob &blob)
This method will write a blob of data (e.g.
Definition: Cube.cpp:763
Isis exception class.
Definition: IException.h:107
FileName setExtension(const QString &extension) const
Sets all current file extensions to a new extension in the file name.
Definition: FileName.cpp:281
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
void setExternalDnData(FileName cubeFileWithDnData)
Used to set external dn data to cube.
Definition: Cube.cpp:949
QString FileOpen(const QString &filename)
This error should be used when a file could not be opened.
Definition: FileOpen.cpp:28
int groups() const
Returns the number of groups contained.
Definition: PvlObject.h:87
double minimum() const
Return the output cube attribute minimum.
void AddData(const double *data, const unsigned int count)
Add an array of doubles to the accumulators and counters.
Definition: Statistics.cpp:154
Contains Pvl Groups and Pvl Objects.
Definition: PvlObject.h:74
void create(const QString &cfile)
This method will create an isis cube for writing.
Definition: Cube.cpp:331
Format
These are the possible storage formats of Isis3 cubes.
Definition: Cube.h:180
QString Type() const
Accessor method that returns a string containing the Blob type.
Definition: Blob.cpp:140
This is the parent of the caching algorithms
void clear()
Clears PvlKeywords.
Definition: PvlContainer.h:105
bool fileExists() const
Returns true if the file exists; false otherwise.
Definition: FileName.cpp:465
void setLabelSize(int labelBytes)
Used prior to the Create method, this will allocate a specific number of bytes in the label area for ...
Definition: Cube.cpp:1006
FileName removeExtension() const
Removes all extensions in the file name.
Definition: FileName.cpp:262
IO Handler for Isis Cubes.
Definition: Cube.h:170