Isis 3.0 Programmer Reference
Back | Home
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 <QFile>
31 #include <QFileInfo>
32 #include <QMutex>
33 
34 #include "Application.h"
35 #include "Camera.h"
36 #include "CameraFactory.h"
37 #include "CubeAttribute.h"
38 #include "CubeBsqHandler.h"
39 #include "CubeTileHandler.h"
40 #include "Endian.h"
41 #include "FileName.h"
42 #include "Histogram.h"
43 #include "IException.h"
44 #include "LineManager.h"
45 #include "Message.h"
46 #include "Preference.h"
47 #include "ProgramLauncher.h"
48 #include "Projection.h"
49 #include "SpecialPixel.h"
50 #include "Statistics.h"
51 
52 using namespace std;
53 
54 namespace Isis {
56  Cube::Cube() {
57  construct();
58  }
59 
68  Cube::Cube(const FileName &fileName, QString access) {
69  construct();
70  open(fileName.toString(), access);
71  }
72 
73 
75  Cube::~Cube() {
76  close();
77 
78  delete m_mutex;
79  m_mutex = NULL;
80 
81  delete m_camera;
82  m_camera = NULL;
83 
84 
85  delete m_projection;
86  m_projection = NULL;
87 
88  delete m_formatTemplateFile;
89  m_formatTemplateFile = NULL;
90  }
91 
92 
98  bool Cube::isOpen() const {
99  bool open = (m_ioHandler != NULL);
100 
101  ASSERT(open == (bool)m_labelFile);
102  ASSERT(open == (bool)m_labelFileName);
103  ASSERT(open == (bool)m_label);
104 
105  return open;
106  }
107 
108 
117  bool Cube::isProjected() const {
118  return label()->findObject("IsisCube").hasGroup("Mapping");
119  }
120 
121 
128  bool Cube::isReadOnly() const {
129  bool readOnly = false;
130 
131  if (!isOpen()) {
132  QString msg = "No cube opened";
133  throw IException(IException::Programmer, msg, _FILEINFO_);
134  }
135 
136  if ((m_labelFile->openMode() & QIODevice::ReadWrite) != QIODevice::ReadWrite)
137  readOnly = true;
138 
139  return readOnly;
140  }
141 
142 
150  bool Cube::isReadWrite() const {
151  return !isReadOnly();
152  }
153 
154 
163  bool Cube::labelsAttached() const {
164  return m_attached;
165  }
166 
167 
175  void Cube::close(bool removeIt) {
176  if (isOpen() && isReadWrite())
177  writeLabels();
178 
179  cleanUp(removeIt);
180  }
181 
182 
183  Cube *Cube::copy(FileName newFile, const CubeAttributeOutput &newFileAttributes) {
184  if (!isOpen()) {
185  throw IException(IException::Unknown,
186  QObject::tr("Cube::copy requires the originating cube to be open"),
187  _FILEINFO_);
188  }
189 
190 
191  Cube *result = new Cube;
192 
193  if (newFileAttributes.labelAttachment() != ExternalLabel) {
194  result->setDimensions(sampleCount(), lineCount(), bandCount());
195  result->setByteOrder(newFileAttributes.byteOrder());
196  result->setFormat(newFileAttributes.fileFormat());
197 
198  if (newFileAttributes.labelAttachment() == DetachedLabel) {
199  result->setLabelsAttached(false);
200  }
201 
202  if (newFileAttributes.propagatePixelType()) {
203  result->setPixelType(pixelType());
204  }
205  else {
206  result->setPixelType(newFileAttributes.pixelType());
207  }
208 
209  if (newFileAttributes.propagateMinimumMaximum()) {
210  if(result->pixelType() == Isis::Real) {
211  result->setBaseMultiplier(0.0, 1.0);
212  }
213  else if(result->pixelType() >= pixelType()) {
214  result->setBaseMultiplier(base(), multiplier());
215  }
216  else {
217  QString msg =
218  QObject::tr("Cannot reduce the output PixelType for [%1] from [%2] without output "
219  "pixel range").arg(newFile.original()).arg(fileName());
220  throw IException(IException::User, msg, _FILEINFO_);
221  }
222  }
223  else {
224  // Not propagating so either the user entered or the programmer did
225  result->setMinMax(newFileAttributes.minimum(), newFileAttributes.maximum());
226  }
227 
228  result->setLabelSize(labelSize(true) + (1024 * 6));
229  }
230  else {
231  if (isReadWrite()) {
232  writeLabels();
233  m_ioHandler->clearCache(true);
234  }
235 
236  result->setExternalDnData(fileName());
237  }
238 
239  // Allocate the cube
240  result->create(newFile.expanded());
241 
242  PvlObject &isisCube = label()->findObject("IsisCube");
243  PvlObject &outIsisCube = result->label()->findObject("IsisCube");
244  for(int i = 0; i < isisCube.groups(); i++) {
245  outIsisCube.addGroup(isisCube.group(i));
246  }
247 
248  if (label()->hasObject("NaifKeywords")) {
249  result->label()->addObject(
250  label()->findObject("NaifKeywords"));
251  }
252 
253  for (int i = 0; i < m_label->objects(); i++) {
254  PvlObject &obj = m_label->object(i);
255  if (obj.isNamed("Table") || obj.isNamed("Polygon") || obj.isNamed("OriginalLabel") ||
256  obj.isNamed("History")) {
257  Isis::Blob t((QString)obj["Name"], obj.name());
258  read(t);
259  result->write(t);
260  }
261  }
262 
263  if (newFileAttributes.labelAttachment() != ExternalLabel) {
264  BufferManager input(sampleCount(), lineCount(), bandCount(),
265  sampleCount(), 1, 1,
266  pixelType());
267  BufferManager output(sampleCount(), lineCount(), bandCount(),
268  sampleCount(), 1, 1,
269  result->pixelType());
270 
271  input.begin();
272  output.begin();
273 
274  while (!input.end()) {
275  read(input);
276  output.Copy(input, false);
277 
278  result->write(output);
279 
280  input.next();
281  output.next();
282  }
283  }
284 
285 // Just in case the orig label doesn't work... here's original code:
286 // if((p_propagateOriginalLabel) && (InputCubes.size() > 0)) {
287 // Isis::Pvl &inlab = *InputCubes[0]->label();
288 // for(int i = 0; i < inlab.objects(); i++) {
289 // if(inlab.Object(i).isNamed("OriginalLabel")) {
290 // Isis::OriginalLabel ol;
291 // InputCubes[0]->read(ol);
292 // cube->write(ol);
293 // }
294 // }
295 // }
296 
297  return result;
298  }
299 
300 
321  void Cube::create(const QString &cubeFileName) {
322  // Already opened?
323  if (isOpen()) {
324  string msg = "You already have a cube opened";
325  throw IException(IException::Programmer, msg, _FILEINFO_);
326  }
327 
328  if (m_samples < 1 || m_lines < 1 || m_bands < 1) {
329  QString msg = "Number of samples [" + toString(m_samples) +
330  "], lines [" + toString(m_lines) + "], or bands [" + toString(m_bands) +
331  "] cannot be less than 1";
332  throw IException(IException::Programmer, msg, _FILEINFO_);
333  }
334 
335  if (m_pixelType == None) {
336  throw IException(IException::Unknown,
337  QString("Cannot create the cube [%1] with a pixel type set to None")
338  .arg(cubeFileName),
339  _FILEINFO_);
340  }
341 
342  if (m_storesDnData) {
343  // Make sure the cube is not going to exceed the maximum size preference
344  BigInt size = (BigInt)m_samples * m_lines *
345  (BigInt)m_bands * (BigInt)SizeOf(m_pixelType);
346 
347  size = size / 1024; // kb
348  size = size / 1024; // mb
349  size = size / 1024; // gb
350 
351  int maxSizePreference = 0;
352 
353  maxSizePreference =
354  Preference::Preferences().findGroup("CubeCustomization")["MaximumSize"];
355 
356  if (size > maxSizePreference) {
357  QString msg;
358  msg += "The cube you are attempting to create [" + cubeFileName + "] is ["
359  + toString(size) + "GB]. This is larger than the current allowed "
360  "size of [" + toString(maxSizePreference) + "GB]. The cube "
361  "dimensions were (S,L,B) [" + toString(m_samples) + ", " +
362  toString(m_lines) + ", " + toString(m_bands) + "] with [" +
363  toString(SizeOf(m_pixelType)) + "] bytes per pixel. If you still "
364  "wish to create this cube, the maximum value can be changed in the"
365  " file [~/.Isis/IsisPreferences] within the group "
366  "CubeCustomization, keyword MaximumSize.";
367  throw IException(IException::User, msg, _FILEINFO_);
368  }
369  }
370 
371  // Expand output name
372  FileName cubFile(cubeFileName);
373  PvlObject isiscube("IsisCube");
374  PvlObject core("Core");
375 
376  if (m_storesDnData) {
377  cubFile = cubFile.addExtension("cub");
378 
379  // See if we have attached or detached labels
380  if (m_attached) {
381  // StartByte is 1-based (why!!) so we need to do + 1
382  core += PvlKeyword("StartByte", toString(m_labelBytes + 1));
383  m_labelFileName = new FileName(cubFile);
384  m_dataFileName = new FileName(cubFile);
385  m_labelFile = new QFile(m_labelFileName->expanded());
386  }
387  else {
388  core += PvlKeyword("StartByte", toString(1));
389  core += PvlKeyword("^Core", cubFile.name());
390  m_dataFileName = new FileName(cubFile);
391  m_dataFile = new QFile(realDataFileName().expanded());
392 
393  FileName labelFileName(cubFile);
394  labelFileName = labelFileName.setExtension("lbl");
395  m_labelFileName = new FileName(labelFileName);
396  m_labelFile = new QFile(m_labelFileName->expanded());
397  }
398 
399  // Create the size of the core
400  PvlGroup dims("Dimensions");
401  dims += PvlKeyword("Samples", toString(m_samples));
402  dims += PvlKeyword("Lines", toString(m_lines));
403  dims += PvlKeyword("Bands", toString(m_bands));
404  core.addGroup(dims);
405 
406  // Create the pixel type
407  PvlGroup ptype("Pixels");
408  ptype += PvlKeyword("Type", PixelTypeName(m_pixelType));
409 
410  // And the byte ordering
411  ptype += PvlKeyword("ByteOrder", ByteOrderName(m_byteOrder));
412  ptype += PvlKeyword("Base", toString(m_base));
413  ptype += PvlKeyword("Multiplier", toString(m_multiplier));
414  core.addGroup(ptype);
415  }
416  else {
417  cubFile = cubFile.addExtension("ecub");
418 
419  ASSERT(m_dataFileName);
420 
421  core += PvlKeyword("^DnFile", m_dataFileName->original());
422 // m_dataFileName = new FileName(cubFile);
423  m_dataFile = new QFile(realDataFileName().expanded());
424 
425  m_labelFileName = new FileName(cubFile);
426  m_labelFile = new QFile(cubFile.expanded());
427  }
428 
429  isiscube.addObject(core);
430 
431  m_label = new Pvl;
432  m_label->addObject(isiscube);
433 
434  // Setup storage reserved for the label
435  PvlObject lbl("Label");
436  lbl += PvlKeyword("Bytes", toString(m_labelBytes));
437  m_label->addObject(lbl);
438 
439  const PvlGroup &pref =
440  Preference::Preferences().findGroup("CubeCustomization");
441  bool overwrite = pref["Overwrite"][0].toUpper() == "ALLOW";
442  if (!overwrite && m_labelFile->exists() && m_labelFile->size()) {
443  QString msg = "Cube file [" + m_labelFileName->original() + "] exists, " +
444  "user preference does not allow overwrite";
445  throw IException(IException::User, msg, _FILEINFO_);
446  }
447 
448  if (!m_labelFile->open(QIODevice::Truncate | QIODevice::ReadWrite)) {
449  QString msg = "Failed to create [" + m_labelFile->fileName() + "]";
450  cleanUp(false);
451  throw IException(IException::Io, msg, _FILEINFO_);
452  }
453 
454  if (m_dataFile) {
455  if (m_storesDnData && !m_dataFile->open(QIODevice::Truncate | QIODevice::ReadWrite)) {
456  QString msg = "Failed to create [" + m_dataFile->fileName() + "]";
457  cleanUp(false);
458  throw IException(IException::Io, msg, _FILEINFO_);
459  }
460  else if (!m_storesDnData && !m_dataFile->open(QIODevice::ReadOnly)) {
461  QString msg = "Failed to open [" + m_dataFile->fileName() + "] for reading";
462  cleanUp(false);
463  throw IException(IException::Io, msg, _FILEINFO_);
464  }
465  }
466 
467  bool dataAlreadyOnDisk = m_storesDnData ? false : true;
468 
469  if (m_format == Bsq) {
470  m_ioHandler = new CubeBsqHandler(dataFile(), m_virtualBandList, realDataFileLabel(),
471  dataAlreadyOnDisk);
472  }
473  else {
474  m_ioHandler = new CubeTileHandler(dataFile(), m_virtualBandList, realDataFileLabel(),
475  dataAlreadyOnDisk);
476  }
477 
478  if (m_storesDnData)
479  m_ioHandler->updateLabels(*m_label);
480 
481  // Write the labels
482  writeLabels();
483  }
484 
485 
486  void Cube::create(
487  const QString &cubeFileName, const CubeAttributeOutput &att) {
488 
489  setByteOrder(att.byteOrder());
490  setFormat(att.fileFormat());
491  setLabelsAttached(att.labelAttachment() == AttachedLabel);
492  if (!att.propagatePixelType())
493  setPixelType(att.pixelType());
494  setMinMax(att.minimum(), att.maximum());
495 
496  // Allocate the cube
497  create(cubeFileName);
498  }
499 
500 
509  void Cube::open(const QString &cubeFileName, QString access) {
510  // Already opened?
511 
512  if (isOpen()) {
513  string msg = "You already have a cube opened";
514  throw IException(IException::Programmer, msg, _FILEINFO_);
515  }
516 
517  initLabelFromFile(cubeFileName, (access == "rw"));
518 
519  // Figure out the name of the data file
520  try {
521  PvlObject &core = m_label->findObject("IsisCube").findObject("Core");
522  if (core.hasKeyword("^Core")) {
523  FileName temp(core["^Core"][0]);
524 
525  if (!temp.originalPath().startsWith("/")) {
526  m_dataFileName = new FileName(m_labelFileName->path() + "/" + temp.original());
527  }
528  else {
529  m_dataFileName = new FileName(temp);
530  }
531 
532  m_attached = false;
533  m_storesDnData = true;
534 
535  m_dataFile = new QFile(realDataFileName().expanded());
536  }
537  else if (core.hasKeyword("^DnFile")) {
538  FileName dataFileName(core["^DnFile"][0]);
539 
540  if (dataFileName.originalPath() == ".") {
541  m_dataFileName = new FileName(m_labelFileName->path() + "/" + dataFileName.name());
542  }
543  else {
544  m_dataFileName = new FileName(dataFileName);
545  }
546 
547  m_attached = true;
548  m_storesDnData = false;
549 
550  m_dataFile = new QFile(realDataFileName().expanded());
551  }
552  else {
553  m_dataFileName = new FileName(*m_labelFileName);
554  m_attached = true;
555  m_storesDnData = true;
556  }
557  }
558  catch (IException &e) {
559  cleanUp(false);
560  throw;
561  }
562 
563  if (access == "r") {
564  if (!m_labelFile->open(QIODevice::ReadOnly)) {
565  QString msg = "Failed to open [" + m_labelFile->fileName() + "] with "
566  "read only access";
567  cleanUp(false);
568  throw IException(IException::Io, msg, _FILEINFO_);
569  }
570 
571  if (m_dataFile) {
572  if (!m_dataFile->open(QIODevice::ReadOnly)) {
573  QString msg = "Failed to open [" + m_dataFile->fileName() + "] with "
574  "read only access";
575  cleanUp(false);
576  throw IException(IException::Io, msg, _FILEINFO_);
577  }
578  }
579  }
580 
581  else if (access == "rw") {
582  if (!m_labelFile->open(QIODevice::ReadWrite)) {
583  QString msg = "Failed to open [" + m_labelFile->fileName() + "] with "
584  "read/write access";
585  cleanUp(false);
586  throw IException(IException::Io, msg, _FILEINFO_);
587  }
588 
589  if (m_dataFile) {
590  if (m_storesDnData && !m_dataFile->open(QIODevice::ReadWrite)) {
591  QString msg = "Failed to open [" + m_dataFile->fileName() + "] with "
592  "read/write access";
593  cleanUp(false);
594  throw IException(IException::Io, msg, _FILEINFO_);
595  }
596  else if (!m_storesDnData && !m_dataFile->open(QIODevice::ReadOnly)) {
597  QString msg = "Failed to open [" + m_dataFile->fileName() + "] with "
598  "read access";
599  cleanUp(false);
600  throw IException(IException::Io, msg, _FILEINFO_);
601  }
602  }
603  }
604  else {
605  QString msg = "Unknown value for access [" + access + "]. Expected 'r' "
606  " or 'rw'";
607  cleanUp(false);
608  throw IException(IException::Programmer, msg, _FILEINFO_);
609  }
610 
611  initCoreFromLabel(*m_label);
612 
613  // Determine the number of bytes in the label
614  if (m_attached) {
615  m_labelBytes = m_label->findObject("Label")["Bytes"];
616  }
617  else {
618  m_labelBytes = labelSize(true);
619  }
620 
621  QPair<bool, Pvl *> dataLabel = qMakePair(false, m_label);
622  if (!m_storesDnData) {
623  dataLabel = qMakePair(true, new Pvl(m_dataFileName->expanded()));
624  }
625 
626  // Now examine the format to see which type of handler to create
627  if (m_format == Bsq) {
628  m_ioHandler = new CubeBsqHandler(dataFile(), m_virtualBandList,
629  realDataFileLabel(), true);
630  }
631  else {
632  m_ioHandler = new CubeTileHandler(dataFile(), m_virtualBandList,
633  realDataFileLabel(), true);
634  }
635 
636  if (dataLabel.first) {
637  delete dataLabel.second;
638  dataLabel.second = NULL;
639  }
640 
641  applyVirtualBandsToLabel();
642  }
643 
644 
653  void Cube::reopen(QString access) {
654  if (!m_labelFile) {
655  QString msg = "Cube has not been opened yet. The filename to re-open is "
656  "unknown";
657  throw IException(IException::Programmer, msg, _FILEINFO_);
658  }
659 
660  // Preserve filename and virtual bands when re-opening
661  FileName filename = *m_labelFileName;
662  QList<int> virtualBandList;
663 
664  if (m_virtualBandList)
665  virtualBandList = *m_virtualBandList;
666 
667  close();
668  open(filename.expanded(), access);
669 
670  if (virtualBandList.size()) {
671  if (m_virtualBandList)
672  *m_virtualBandList = virtualBandList;
673  else
674  m_virtualBandList = new QList<int>(virtualBandList);
675  }
676  }
677 
678 
686  void Cube::read(Blob &blob) const {
687  if (!isOpen()) {
688  string msg = "The cube is not opened so you can't read a blob from it";
689  throw IException(IException::Programmer, msg, _FILEINFO_);
690  }
691 
692  FileName cubeFile = *m_labelFileName;
693  if (m_tempCube)
694  cubeFile = *m_tempCube;
695 
696  QMutexLocker locker(m_mutex);
697  QMutexLocker locker2(m_ioHandler->dataFileMutex());
698  blob.Read(cubeFile.toString(), *label());
699  }
700 
701 
708  void Cube::read(Buffer &bufferToFill) const {
709  if (!isOpen()) {
710  string msg = "Try opening a file before you read it";
711  throw IException(IException::Programmer, msg, _FILEINFO_);
712  }
713 
714  QMutexLocker locker(m_mutex);
715  m_ioHandler->read(bufferToFill);
716  }
717 
718 
725  void Cube::write(Blob &blob) {
726  if (!isOpen()) {
727  string msg = "The cube is not opened so you can't write a blob to it";
728  throw IException(IException::Programmer, msg, _FILEINFO_);
729  }
730 
731  if (!m_labelFile->isWritable()) {
732  string msg = "The cube must be opened in read/write mode, not readOnly";
733  throw IException(IException::Programmer, msg, _FILEINFO_);
734  }
735 
736  // Write an attached blob
737  if (m_attached) {
738  QMutexLocker locker(m_mutex);
739  QMutexLocker locker2(m_ioHandler->dataFileMutex());
740 
741  // Compute the number of bytes in the cube + label bytes and if the
742  // endpos of the file // is not greater than this then seek to that position.
743  fstream stream(m_labelFileName->expanded().toLatin1().data(),
744  ios::in | ios::out | ios::binary);
745  stream.seekp(0, ios::end);
746 
747  // End byte = end byte of the file (aka eof position, file size)
748  streampos endByte = stream.tellp();
749  // maxbyte = position after the cube DN data and labels
750  streampos maxbyte = (streampos) m_labelBytes;
751 
752  if (m_storesDnData) {
753  maxbyte += (streampos) m_ioHandler->getDataSize();
754  }
755 
756  // If EOF is too early, allocate space up to where we want the blob
757  if (endByte < maxbyte) {
758  stream.seekp(maxbyte, ios::beg);
759  }
760 
761  blob.Write(*m_label, stream);
762  }
763 
764  // Write a detached blob
765  else {
766  FileName blobFileName = fileName();
767  blobFileName = blobFileName.removeExtension();
768  blobFileName = blobFileName.addExtension(blob.Type());
769  blobFileName = blobFileName.addExtension(blob.Name());
770  QString blobFile(blobFileName.expanded());
771  ios::openmode flags = ios::in | ios::binary | ios::out | ios::trunc;
772  fstream detachedStream;
773  detachedStream.open(blobFile.toLatin1().data(), flags);
774  if (!detachedStream) {
775  QString message = "Unable to open data file [" +
776  blobFileName.expanded() + "]";
777  throw IException(IException::Io, message, _FILEINFO_);
778  }
779 
780 // Changed to work with mods to FileName class
781 // blob.Write(p_cube.label,detachedStream,blobFileName.baseName()+"."+
782 // blob.Type()+"."+
783 // blobFileName.extension());
784  blob.Write(*m_label, detachedStream, blobFileName.name());
785  }
786  }
787 
788 
795  void Cube::write(Buffer &bufferToWrite) {
796  if (!isOpen()) {
797  string msg = "Tried to write to a cube before opening/creating it";
798  throw IException(IException::Programmer, msg, _FILEINFO_);
799  }
800 
801  if (isReadOnly()) {
802  QString msg = "Cannot write to the cube [" + (QString)QFileInfo(fileName()).fileName() +
803  "] because it is opened read-only";
804  throw IException(IException::Programmer, msg, _FILEINFO_);
805  }
806 
807  if (!m_storesDnData) {
808  QString msg = "The cube [" + QFileInfo(fileName()).fileName() +
809  "] does not support storing DN data because it is using an external file for DNs";
810  throw IException(IException::Unknown, msg, _FILEINFO_);
811  }
812 
813  QMutexLocker locker(m_mutex);
814  m_ioHandler->write(bufferToWrite);
815  }
816 
817 
828  void Cube::setBaseMultiplier(double base, double mult) {
829  openCheck();
830  m_base = base;
831  m_multiplier = mult;
832  }
833 
834 
845  void Cube::setMinMax(double min, double max) {
846  openCheck();
847 
848  m_base = 0.0;
849  m_multiplier = 1.0;
850 
851  double x1, x2;
852  if (m_pixelType == UnsignedByte) {
853  x1 = VALID_MIN1;
854  x2 = VALID_MAX1;
855  m_multiplier = (max - min) / (x2 - x1);
856  m_base = min - m_multiplier * x1;
857  }
858  else if (m_pixelType == SignedWord) {
859  x1 = VALID_MIN2;
860  x2 = VALID_MAX2;
861  m_multiplier = (max - min) / (x2 - x1);
862  m_base = min - m_multiplier * x1;
863  }
864  else if (m_pixelType == UnsignedWord) {
865  x1 = VALID_MINU2;
866  x2 = VALID_MAXU2;
867  m_multiplier = (max - min) / (x2 - x1);
868  m_base = min - m_multiplier * x1;
869  }
870  }
871 
872 
879  void Cube::setByteOrder(ByteOrder byteOrder) {
880  openCheck();
881  m_byteOrder = byteOrder;
882  }
883 
884 
894  void Cube::setDimensions(int ns, int nl, int nb) {
895  openCheck();
896  if ((ns < 1) || (nl < 1) || (nb < 1)) {
897  string msg = "SetDimensions: Invalid number of sample, lines or bands";
898  throw IException(IException::Programmer, msg, _FILEINFO_);
899  }
900  m_samples = ns;
901  m_lines = nl;
902  m_bands = nb;
903  }
904 
905 
906  void Cube::setExternalDnData(FileName cubeFileWithDnData) {
907  try {
908  initLabelFromFile(cubeFileWithDnData, false);
909  initCoreFromLabel(*m_label);
910 
911  delete m_label;
912  m_label = NULL;
913  }
914  catch (IException &) {
915  delete m_label;
916  m_label = NULL;
917  throw;
918  }
919 
920  m_storesDnData = false;
921  m_dataFileName = new FileName(cubeFileWithDnData);
922 
923  delete m_labelFile;
924  m_labelFile = NULL;
925 
926  delete m_labelFileName;
927  m_labelFileName = NULL;
928  }
929 
930 
938  void Cube::setFormat(Format format) {
939  openCheck();
940  m_format = format;
941  }
942 
943 
950  void Cube::setLabelsAttached(bool attach) {
951  openCheck();
952  m_attached = attach;
953  }
954 
955 
963  void Cube::setLabelSize(int labelBytes) {
964  openCheck();
965  m_labelBytes = labelBytes;
966  }
967 
968 
976  void Cube::setPixelType(PixelType pixelType) {
977  openCheck();
978  m_pixelType = pixelType;
979  }
980 
981 
993  void Cube::setVirtualBands(const QList<QString> &vbands) {
994  openCheck();
995  if (m_virtualBandList)
996  m_virtualBandList->clear();
997  else
998  m_virtualBandList = new QList<int>;
999 
1000  if (vbands.size() > 0) {
1001  QListIterator<QString> it(vbands);
1002  while (it.hasNext()) {
1003  m_virtualBandList->append(toInt(it.next()));
1004  }
1005  }
1006  else {
1007  delete m_virtualBandList;
1008  m_virtualBandList = NULL;
1009  }
1010 
1011  if (m_ioHandler) {
1012  m_ioHandler->setVirtualBands(m_virtualBandList);
1013  }
1014  }
1015 
1016 
1023  void Cube::setVirtualBands(const std::vector<QString> &vbands) {
1024  QList<QString> realVBands;
1025 
1026  for(unsigned int i = 0; i < vbands.size(); i++)
1027  realVBands << vbands[i];
1028 
1029  setVirtualBands(realVBands);
1030  }
1031 
1032 
1033  void Cube::relocateDnData(FileName dnDataFile) {
1034  if (!isOpen()) {
1035  throw IException(IException::Unknown,
1036  QString("Cannot relocate the DN data to [%1] for an external cube label "
1037  "file which is not open.")
1038  .arg(dnDataFile.original()),
1039  _FILEINFO_);
1040  }
1041 
1042 
1043  if (m_storesDnData) {
1044  throw IException(IException::Unknown,
1045  QString("The cube [%1] stores DN data. It cannot be relocated to [%2] - "
1046  "this is only supported for external cube label files.")
1047  .arg(m_labelFileName->original()).arg(dnDataFile.original()),
1048  _FILEINFO_);
1049  }
1050 
1051  m_label->findObject("IsisCube").findObject("Core").findKeyword("^DnFile")[0] =
1052  dnDataFile.original();
1053  reopen(m_labelFile->isWritable()? "rw" : "r");
1054  }
1055 
1056 
1057 // void Cube::relocateDnData(FileName externalLabelFile, FileName dnDataFile) {
1058 // try {
1059 // Pvl externalLabelData(externalLabelFile.expanded());
1060 // externalLabelData.FindObject("IsisCube").FindObject("Core").FindKeyword("^DnFile")[0] =
1061 // dnDataFile.original();
1062 // }
1063 // catch (IException &e) {
1064 // throw IException(e, IException::Io,
1065 // QString("File [%1] does not appear to be an external cube label file")
1066 // .arg(externalLabelFile.original().ToQt()),
1067 // _FILEINFO_);
1068 // }
1069 // }
1070 
1071 
1077  int Cube::bandCount() const {
1078  int numBands = m_bands;
1079  if (m_virtualBandList)
1080  numBands = m_virtualBandList->size();
1081  return numBands;
1082  }
1083 
1084 
1094  double Cube::base() const {
1095  return m_base;
1096  }
1097 
1098 
1106  ByteOrder Cube::byteOrder() const {
1107  return m_byteOrder;
1108  }
1109 
1110 
1118  Camera *Cube::camera() {
1119  if (m_camera == NULL && isOpen()) {
1120  m_camera = CameraFactory::Create(*this);
1121  }
1122  return m_camera;
1123  }
1124 
1125 
1132  FileName Cube::externalCubeFileName() const {
1133  if (!isOpen()) {
1134  throw IException(IException::Unknown,
1135  "An external cube label file must be opened in order to use "
1136  "Cube::getExternalCubeFileName",
1137  _FILEINFO_);
1138  }
1139 
1140  if (storesDnData()) {
1141  throw IException(IException::Unknown,
1142  "Cube::getExternalCubeFileName can only be called on an external cube label "
1143  "file",
1144  _FILEINFO_);
1145  }
1146 
1147 
1148  PvlObject &core = m_label->findObject("IsisCube").findObject("Core");
1149 
1150  return core["^DnFile"][0];
1151  }
1152 
1153 
1160  QString Cube::fileName() const {
1161  if (isOpen())
1162  return m_labelFileName->expanded();
1163  else
1164  return "";
1165  }
1166 
1167 
1172  Cube::Format Cube::format() const {
1173  return m_format;
1174  }
1175 
1176 
1196  Histogram *Cube::histogram(const int &band, QString msg) {
1197  return histogram(band, ValidMinimum, ValidMaximum, msg);
1198  }
1199 
1200 
1226  Histogram *Cube::histogram(const int &band, const double &validMin,
1227  const double &validMax, QString msg) {
1228  // Make sure cube is open
1229  if ( !isOpen() ) {
1230  QString msg = "Cannot create histogram object for an unopened cube";
1231  throw IException(IException::Programmer, msg, _FILEINFO_);
1232  }
1233 
1234  // Make sure band is valid
1235  if ((band < 0) || (band > bandCount())) {
1236  QString msg = "Invalid band in [CubeInfo::Histogram]";
1237  throw IException(IException::Programmer, msg, _FILEINFO_);
1238  }
1239 
1240  int bandStart = band;
1241  int bandStop = band;
1242  int maxSteps = lineCount();
1243  if (band == 0) {
1244  bandStart = 1;
1245  bandStop = bandCount();
1246  maxSteps = lineCount() * bandCount();
1247  }
1248 
1249  Progress progress;
1250  Histogram *hist = new Histogram(*this, band, &progress);
1251  LineManager line(*this);
1252 
1253  // This range is for throwing out data; the default parameters are OK always
1254  //hist->SetValidRange(validMin, validMax);
1255 
1256  // We now need to know the binning range - ValidMinimum/Maximum are no longer
1257  // acceptable, default to the bin range start/end.
1258  double binMin = validMin;
1259  double binMax = validMax;
1260  if (binMin == ValidMinimum) {
1261  binMin = hist->BinRangeStart();
1262  }
1263 
1264  if (binMax == ValidMaximum) {
1265  binMax = hist->BinRangeEnd();
1266  }
1267 
1268  //hist->SetBinRange(binMin, binMax);
1269  hist->SetValidRange(binMin,binMax);
1270 
1271  // Loop and get the histogram
1272  progress.SetText(msg);
1273  progress.SetMaximumSteps(maxSteps);
1274  progress.CheckStatus();
1275 
1276  for(int useBand = bandStart ; useBand <= bandStop ; useBand++) {
1277  for(int i = 1; i <= lineCount(); i++) {
1278  line.SetLine(i, useBand);
1279  read(line);
1280  hist->AddData(line.DoubleBuffer(), line.size());
1281  progress.CheckStatus();
1282  }
1283  }
1284 
1285  return hist;
1286  }
1287 
1288 
1298  Pvl *Cube::label() const {
1299  return m_label;
1300  }
1301 
1302 
1310  int Cube::labelSize(bool actual) const {
1311  int labelSize = m_labelBytes;
1312 
1313  if (actual && m_label) {
1314  ostringstream s;
1315  s << *m_label << endl;
1316  labelSize = s.tellp();
1317  }
1318  else if (actual) {
1319  labelSize = 0;
1320  }
1321 
1322  return labelSize;
1323  }
1324 
1325 
1331  int Cube::lineCount() const {
1332  return m_lines;
1333  }
1334 
1335 
1345  double Cube::multiplier() const {
1346  return m_multiplier;
1347  }
1348 
1349 
1355  PixelType Cube::pixelType() const {
1356  return m_pixelType;
1357  }
1358 
1359 
1370  int Cube::physicalBand(const int &virtualBand) const {
1371  int physicalBand = virtualBand;
1372 
1373  if (m_virtualBandList) {
1374  if ((virtualBand < 1) ||
1375  (virtualBand > m_virtualBandList->size())) {
1376  QString msg = "Out of array bounds [" + toString(virtualBand) + "]";
1377  throw IException(IException::Programmer, msg, _FILEINFO_);
1378  }
1379  physicalBand = m_virtualBandList->at(virtualBand - 1);
1380  }
1381 
1382  return physicalBand;
1383  }
1384 
1385 
1391  Projection *Cube::projection() {
1392  if (m_projection == NULL && isOpen()) {
1393  m_projection = ProjectionFactory::CreateFromCube(*label());
1394  }
1395  return m_projection;
1396  }
1397 
1398 
1404  int Cube::sampleCount() const {
1405  return m_samples;
1406  }
1407 
1408 
1427  Statistics *Cube::statistics(const int &band, QString msg) {
1428  return statistics(band, ValidMinimum, ValidMaximum, msg);
1429  }
1430 
1431 
1448  Statistics *Cube::statistics(const int &band, const double &validMin,
1449  const double &validMax, QString msg) {
1450  // Make sure cube is open
1451  if ( !isOpen() ) {
1452  QString msg = "Cannot create statistics object for an unopened cube";
1453  throw IException(IException::Programmer, msg, _FILEINFO_);
1454  }
1455 
1456  // Make sure band is valid
1457  if ((band < 0) || (band > bandCount())) {
1458  string msg = "Invalid band in [CubeInfo::Statistics]";
1459  throw IException(IException::Programmer, msg, _FILEINFO_);
1460  }
1461 
1462  // Construct a line buffer manager and a statistics object
1463  LineManager line(*this);
1464  Statistics *stats = new Statistics();
1465 
1466  stats->SetValidRange(validMin, validMax);
1467 
1468  int bandStart = band;
1469  int bandStop = band;
1470  int maxSteps = lineCount();
1471  if (band == 0) {
1472  bandStart = 1;
1473  bandStop = bandCount();
1474  maxSteps = lineCount() * bandCount();
1475  }
1476 
1477  Progress progress;
1478  progress.SetText(msg);
1479  progress.SetMaximumSteps(maxSteps);
1480  progress.CheckStatus();
1481 
1482  // Loop and get the statistics for a good minimum/maximum
1483  for(int useBand = bandStart ; useBand <= bandStop ; useBand++) {
1484  for(int i = 1; i <= lineCount(); i++) {
1485  line.SetLine(i, useBand);
1486  read(line);
1487  stats->AddData(line.DoubleBuffer(), line.size());
1488  progress.CheckStatus();
1489  }
1490  }
1491 
1492  return stats;
1493  }
1494 
1495 
1496  bool Cube::storesDnData() const {
1497  return m_storesDnData;
1498  }
1499 
1500 
1514  void Cube::addCachingAlgorithm(CubeCachingAlgorithm *algorithm) {
1515 
1516  if (isOpen() && m_ioHandler) {
1517  m_ioHandler->addCachingAlgorithm(algorithm);
1518  }
1519  else if (!isOpen()) {
1520  QString msg = "Cannot add a caching algorithm until the cube is open";
1521  throw IException(IException::Programmer, msg, _FILEINFO_);
1522  }
1523  }
1524 
1530  void Cube::clearIoCache() {
1531  if (m_ioHandler) {
1532  QMutexLocker locker(m_mutex);
1533  m_ioHandler->clearCache();
1534  }
1535  }
1536 
1537 
1547  bool Cube::deleteBlob(QString BlobType, QString BlobName) {
1548  for(int i = 0; i < m_label->objects(); i++) {
1549  PvlObject obj = m_label->object(i);
1550  if (obj.name().compare(BlobType) == 0) {
1551  if (obj.findKeyword("Name")[0] == BlobName) {
1552  m_label->deleteObject(i);
1553  return true;
1554  }
1555  }
1556  }
1557  return false;
1558  }
1559 
1560 
1569  void Cube::deleteGroup(const QString &group) {
1570  PvlObject &isiscube = label()->findObject("IsisCube");
1571  if (!isiscube.hasGroup(group)) return;
1572  isiscube.deleteGroup(group);
1573  }
1574 
1575 
1583  PvlGroup &Cube::group(const QString &group) const {
1584  PvlObject &isiscube = label()->findObject("IsisCube");
1585  return isiscube.findGroup(group);
1586  }
1587 
1588 
1596  bool Cube::hasGroup(const QString &group) const {
1597  const PvlObject &isiscube = label()->findObject("IsisCube");
1598  if (isiscube.hasGroup(group)) return true;
1599  return false;
1600  }
1601 
1602 
1610  bool Cube::hasTable(const QString &name) {
1611  for(int o = 0; o < label()->objects(); o++) {
1612  PvlObject &obj = label()->object(o);
1613  if (obj.isNamed("Table")) {
1614  if (obj.hasKeyword("Name")) {
1615  QString temp = (QString) obj["Name"];
1616  temp = temp.toUpper();
1617  QString temp2 = name;
1618  temp2 = temp2.toUpper();
1619  if (temp == temp2) return true;
1620  }
1621  }
1622  }
1623  return false;
1624  }
1625 
1626 
1635  void Cube::putGroup(const PvlGroup &group) {
1636  if (isReadOnly()) {
1637  QString msg = "Cannot add a group to the label of cube [" + (QString)QFileInfo(fileName()).fileName() +
1638  "] because it is opened read-only";
1639  throw IException(IException::Programmer, msg, _FILEINFO_);
1640  return;
1641  }
1642 
1643  PvlObject &isiscube = label()->findObject("IsisCube");
1644  if (isiscube.hasGroup(group.name())) {
1645  isiscube.findGroup(group.name()) = group;
1646  }
1647  else {
1648  isiscube.addGroup(group);
1649  }
1650  }
1651 
1652 
1653  void Cube::applyVirtualBandsToLabel() {
1654  PvlObject &core = m_label->findObject("IsisCube").findObject("Core");
1655 
1656  // Prune the band bin group if it exists
1657  if (m_label->findObject("IsisCube").hasGroup("BandBin")) {
1658  PvlGroup &bandBin = m_label->findObject("IsisCube").findGroup("BandBin");
1659  for (int k = 0;k < bandBin.keywords();k++) {
1660  if (bandBin[k].size() == m_bands && m_virtualBandList) {
1661  PvlKeyword temp = bandBin[k];
1662  bandBin[k].clear();
1663  for (int i = 0;i < m_virtualBandList->size();i++) {
1664  int physicalBand = m_virtualBandList->at(i) - 1;
1665  bandBin[k].addValue(temp[physicalBand], temp.unit(physicalBand));
1666  }
1667  }
1668  }
1669  }
1670 
1671  // Change the number of bands in the labels of the cube
1672  if (m_virtualBandList && core.hasGroup("Dimensions")) core.findGroup("Dimensions")["Bands"] = toString(m_virtualBandList->size());
1673  }
1674 
1675 
1681  void Cube::cleanUp(bool removeIt) {
1682  if (m_ioHandler) {
1683  delete m_ioHandler;
1684  m_ioHandler = NULL;
1685  }
1686 
1687  // Always remove a temporary file
1688  if (m_tempCube) {
1689  QFile::remove(m_tempCube->expanded());
1690  removeIt = false; // dont remove originals
1691 
1692  delete m_tempCube;
1693  m_tempCube = NULL;
1694  }
1695 
1696  if (removeIt) {
1697  QFile::remove(m_labelFileName->expanded());
1698 
1699  if (*m_labelFileName != *m_dataFileName)
1700  QFile::remove(m_dataFileName->expanded());
1701  }
1702 
1703  delete m_labelFile;
1704  m_labelFile = NULL;
1705 
1706  delete m_dataFile;
1707  m_dataFile = NULL;
1708 
1709  delete m_labelFileName;
1710  m_labelFileName = NULL;
1711 
1712  delete m_dataFileName;
1713  m_dataFileName = NULL;
1714 
1715  delete m_label;
1716  m_label = NULL;
1717 
1718  delete m_virtualBandList;
1719  m_virtualBandList = NULL;
1720 
1721  initialize();
1722  }
1723 
1724 
1729  void Cube::construct() {
1730  m_labelFile = NULL;
1731  m_dataFile = NULL;
1732  m_ioHandler = NULL;
1733  m_mutex = NULL;
1734 
1735  m_camera = NULL;
1736  m_projection = NULL;
1737 
1738  m_labelFileName = NULL;
1739  m_dataFileName = NULL;
1740  m_tempCube = NULL;
1741  m_formatTemplateFile = NULL;
1742  m_label = NULL;
1743 
1744  m_virtualBandList = NULL;
1745 
1746  m_mutex = new QMutex();
1747  m_formatTemplateFile =
1748  new FileName("$base/templates/labels/CubeFormatTemplate.pft");
1749 
1750  initialize();
1751  }
1752 
1753 
1760  QFile *Cube::dataFile() const {
1761  if (m_dataFile)
1762  return m_dataFile;
1763  else
1764  return m_labelFile;
1765  }
1766 
1767 
1773  FileName Cube::realDataFileName() const {
1774  FileName result;
1775 
1776  // Attached, stores DN data - normal cube
1777  if (m_attached && m_storesDnData) {
1778  ASSERT(m_labelFileName);
1779  result = *m_labelFileName;
1780  }
1781  // Detached, stores DN data - standard detached cube
1782  else if (!m_attached && m_storesDnData) {
1783  ASSERT(m_dataFileName);
1784  result = *m_dataFileName;
1785  }
1786  // External cube - go look at our external file
1787  else if (!m_storesDnData) {
1788  ASSERT(m_dataFileName);
1789  FileName guess = *m_dataFileName;
1790 
1791  do {
1792  Pvl guessLabel(guess.expanded());
1793 
1794  PvlObject &core = guessLabel.findObject("IsisCube").findObject("Core");
1795 
1796  if (core.hasKeyword("^DnFile")) {
1797  FileName currentGuess = guess;
1798  guess = core["^DnFile"][0];
1799 
1800  if (!guess.path().startsWith("/")) {
1801  guess = currentGuess.path() + "/" + guess.original();
1802  }
1803  }
1804  else if (core.hasKeyword("^Core")) {
1805  result = core["^Core"][0];
1806  }
1807  else {
1808  result = guess;
1809  }
1810  }
1811  while (result.name() == "");
1812  }
1813 
1814  return result;
1815  }
1816 
1817 
1829  void Cube::initialize() {
1830  m_byteOrder = Lsb;
1831  if (IsBigEndian())
1832  m_byteOrder = Msb;
1833  m_format = Tile;
1834  m_pixelType = Real;
1835 
1836  m_attached = true;
1837  m_storesDnData = true;
1838  m_labelBytes = 65536;
1839 
1840  m_samples = 0;
1841  m_lines = 0;
1842  m_bands = 0;
1843 
1844  m_base = 0.0;
1845  m_multiplier = 1.0;
1846  }
1847 
1848 
1849  void Cube::initCoreFromLabel(const Pvl &label) {
1850  const PvlObject &core = label.findObject("IsisCube").findObject("Core");
1851 
1852  if (!core.hasKeyword("^DnFile")) {
1853  // Dimensions
1854  const PvlGroup &dims = core.findGroup("Dimensions");
1855  m_samples = dims["Samples"];
1856  m_lines = dims["Lines"];
1857  m_bands = dims["Bands"];
1858 
1859  // Stored pixel information
1860  const PvlGroup &pixelsGroup = core.findGroup("Pixels");
1861  m_byteOrder = ByteOrderEnumeration(pixelsGroup["ByteOrder"]);
1862  m_base = pixelsGroup["Base"];
1863  m_multiplier = pixelsGroup["Multiplier"];
1864  m_pixelType = PixelTypeEnumeration(pixelsGroup["Type"]);
1865 
1866  // Now examine the format to see which type of handler to create
1867  if ((QString) core["Format"] == "BandSequential") {
1868  m_format = Bsq;
1869  }
1870  else {
1871  m_format = Tile;
1872  }
1873  }
1874  else {
1875  FileName temp(core["^DnFile"][0]);
1876  if (!temp.expanded().startsWith("/")) {
1877  temp = FileName(m_labelFileName->path() + "/" + temp.original());
1878  }
1879 
1880  initCoreFromLabel(Pvl(temp.toString()));
1881  }
1882  }
1883 
1884 
1885  void Cube::initLabelFromFile(FileName labelFileName, bool readWrite) {
1886  ASSERT(!m_labelFileName);
1887 
1888  try {
1889  if (labelFileName.fileExists()) {
1890  m_label = new Pvl(labelFileName.expanded());
1891  if (!m_label->objects()) {
1892  throw IException();
1893  }
1894  }
1895  }
1896  catch(IException &) {
1897  if (m_label) {
1898  delete m_label;
1899  m_label = NULL;
1900  }
1901  }
1902 
1903  try {
1904  if (!m_label) {
1905  FileName tmp(labelFileName);
1906  tmp = tmp.addExtension("cub");
1907  if (tmp.fileExists()) {
1908  m_label = new Pvl(tmp.expanded());
1909  if (!m_label->objects()) {
1910  throw IException();
1911  }
1912  labelFileName = tmp;
1913  }
1914  }
1915  }
1916  catch(IException &e) {
1917  if (m_label) {
1918  delete m_label;
1919  m_label = NULL;
1920  }
1921  }
1922 
1923  try {
1924  if (!m_label) {
1925  FileName tmp(labelFileName);
1926  tmp = tmp.setExtension("lbl");
1927  if (tmp.fileExists()) {
1928  m_label = new Pvl(tmp.expanded());
1929  if (!m_label->objects()) {
1930  throw IException();
1931  }
1932  labelFileName = tmp;
1933  }
1934  }
1935  }
1936  catch(IException &e) {
1937  if (m_label) {
1938  delete m_label;
1939  m_label = NULL;
1940  }
1941  }
1942 
1943  try {
1944  if (!m_label) {
1945  FileName tmp(labelFileName);
1946  tmp = tmp.addExtension("ecub");
1947  if (tmp.fileExists()) {
1948  m_label = new Pvl(tmp.expanded());
1949  if (!m_label->objects()) {
1950  throw IException();
1951  }
1952  labelFileName = tmp;
1953  }
1954  }
1955  }
1956  catch(IException &e) {
1957  if (m_label) {
1958  delete m_label;
1959  m_label = NULL;
1960  }
1961  }
1962 
1963  if (!m_label) {
1964  QString msg = Message::FileOpen(labelFileName.original());
1965  throw IException(IException::Io, msg, _FILEINFO_);
1966  }
1967 
1968  m_labelFileName = new FileName(labelFileName);
1969 
1970  // See if this is an old Isis cube format. If so then we will
1971  // need to internalize a new label
1972  if (m_label->hasKeyword("CCSD3ZF0000100000001NJPL3IF0PDS200000001")) {
1973  if (!readWrite) {
1974  reformatOldIsisLabel(m_labelFileName->expanded());
1975  }
1976  else {
1977  QString msg = "Can not open [" + m_labelFileName->original() + "]"
1978  " because it is an ISIS2 cube.";
1979  cleanUp(false);
1980  throw IException(IException::Io, msg, _FILEINFO_);
1981  }
1982  }
1983  else {
1984  m_labelFile = new QFile(m_labelFileName->expanded());
1985  }
1986  }
1987 
1988 
1992  void Cube::openCheck() {
1993  if (isOpen()) {
1994  string msg = "Sorry you can't do a SetMethod after the cube is opened";
1995  throw IException(IException::Programmer, msg, _FILEINFO_);
1996  }
1997  }
1998 
1999  Pvl Cube::realDataFileLabel() const {
2000  Pvl label = *m_label;
2001  PvlObject *core = NULL;
2002 
2003  do {
2004  core = &label.findObject("IsisCube").findObject("Core");
2005 
2006  if (core->hasKeyword("^DnFile")) {
2007 
2008  FileName temp((*core)["^DnFile"][0]);
2009  if (!temp.expanded().startsWith("/")) {
2010  temp = FileName(FileName(label.fileName()).path() + "/" + temp.original());
2011  }
2012 
2013  label = Pvl(temp.toString());
2014  core = NULL;
2015  }
2016  }
2017  while (!core);
2018 
2019  return label;
2020  }
2021 
2022 
2029  void Cube::reformatOldIsisLabel(const QString &oldCube) {
2030  QString parameters = "from=" + oldCube;
2031  FileName oldName(oldCube);
2032  FileName tempCube = FileName::createTempFile("Temporary_" + oldName.name() + ".cub");
2033  parameters += " to=" + tempCube.expanded();
2034 
2035  if (iApp == NULL) {
2036  QString command = "$ISISROOT/bin/pds2isis " + parameters;
2037  ProgramLauncher::RunSystemCommand(command);
2038  }
2039  else {
2040  QString prog = "pds2isis";
2041  ProgramLauncher::RunIsisProgram(prog, parameters);
2042  }
2043 
2044  m_tempCube = new FileName(tempCube);
2045  *m_label = Pvl(m_tempCube->toString());
2046  m_labelFile = new QFile(m_tempCube->expanded());
2047  }
2048 
2049 
2054  void Cube::writeLabels() {
2055  if (!isOpen()) {
2056  string msg = "Cube must be opened first before writing labels";
2057  throw IException(IException::Programmer, msg, _FILEINFO_);
2058  }
2059 
2060  // Set the pvl's format template
2061  m_label->setFormatTemplate(m_formatTemplateFile->original());
2062 
2063  // Write them with attached data
2064  if (m_attached) {
2065  QMutexLocker locker(m_mutex);
2066  QMutexLocker locker2(m_ioHandler->dataFileMutex());
2067 
2068  ostringstream temp;
2069  temp << *m_label << endl;
2070  string tempstr = temp.str();
2071  if ((int) tempstr.length() < m_labelBytes) {
2072  QByteArray labelArea(m_labelBytes, '\0');
2073  QByteArray labelUnpaddedContents(tempstr.c_str(), tempstr.length());
2074  labelArea.replace(0, labelUnpaddedContents.size(), labelUnpaddedContents);
2075  // Rewrite the label area
2076  m_labelFile->seek(0);
2077  m_labelFile->write(labelArea);
2078  }
2079  else {
2080  locker2.unlock();
2081  QString msg = "Label space is full in [" +
2082  (QString)FileName(*m_labelFileName).name() +
2083  "] unable to write labels";
2084  cleanUp(false);
2085  throw IException(IException::Io, msg, _FILEINFO_);
2086  }
2087  }
2088 
2089  // or detached label
2090  else {
2091  m_label->write(m_labelFileName->expanded());
2092  }
2093  }
2094 }
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:68
void AddData(const double *data, const unsigned int count)
Add an array of doubles to the histogram counters.
Definition: Histogram.cpp:448
The label is pointing to an external DN file - the label is also external to the data.
Definition: CubeAttribute.h:56
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
bool propagateMinimumMaximum() const
Return true if the min/max are to be propagated from an input cube.
const double ValidMinimum
The minimum valid double value for Isis pixels.
Definition: SpecialPixel.h:101
double maximum() const
Return the output cube attribute maximum.
bool propagatePixelType() const
Return true if the pixel type is to be propagated from an input cube.
File name manipulation and expansion.
Definition: FileName.h:111
IO Handler for Isis Cubes using the BSQ format.
void Read(const QString &file)
This method reads Pvl values from a specified file.
Definition: Blob.cpp:243
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 keywords() const
Returns the number of keywords contained in the PvlContainer.
Definition: PvlContainer.h:101
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
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
ByteOrder
Tests the current architecture for byte order.
Definition: Endian.h:59
double * DoubleBuffer() const
Returns the value of the shape buffer.
Definition: Buffer.h:153
QString fileName() const
Returns the filename used to initialise the Pvl object.
Definition: PvlContainer.h:247
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition: IString.cpp:226
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
PixelType
Enumerations for Isis Pixel Types.
Definition: PixelType.h:43
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
This class is used to accumulate statistics on double arrays.
Definition: Statistics.h:109
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
void SetValidRange(const double minimum=Isis::ValidMinimum, const double maximum=Isis::ValidMaximum)
Changes the range of the bins.
Definition: Histogram.cpp:408
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:169
Program progress reporter.
Definition: Progress.h:58
Container of a cube histogram.
Definition: Histogram.h:78
void SetText(const QString &text)
Changes the value of the text string reported just before 0% processed.
Definition: Progress.cpp:77
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:38
Manipulate and parse attributes of output cube filenames.
A single keyword-value pair.
Definition: PvlKeyword.h:98
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
Cube::Format fileFormat() const
Return the file format an Cube::Format.
QString Type() const
Accessor method that returns a string containing the Blob type.
Definition: Blob.cpp:140
The input label is embedded in the image file.
Definition: CubeAttribute.h:48
IO Handler for Isis Cubes using the tile format.
double minimum() const
Return the output cube attribute minimum.
Container for cube-like labels.
Definition: Pvl.h:135
void deleteObject(const QString &name)
Remove an object from the current PvlObject.
Definition: PvlObject.cpp:337
const double ValidMaximum
The maximum valid double value for Isis pixels.
Definition: SpecialPixel.h:136
int size() const
Returns the total number of pixels in the shape buffer.
Definition: Buffer.h:112
QString Name() const
Accessor method that returns a string containing the Blob name.
Definition: Blob.cpp:149
Isis exception class.
Definition: IException.h:99
QString FileOpen(const QString &filename)
This error should be used when a file could not be opened.
Definition: FileOpen.cpp:28
ByteOrder byteOrder() const
Return the byte order as an Isis::ByteOrder.
bool isNamed(const QString &match) const
Returns whether the given string is equal to the container name or not.
Definition: PvlContainer.h:87
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
void AddData(const double *data, const unsigned int count)
Add an array of doubles to the accumulators and counters.
Definition: Statistics.cpp:158
Contains Pvl Groups and Pvl Objects.
Definition: PvlObject.h:74
QString path() const
Returns the path.
Definition: FileName.cpp:88
Format
These are the possible storage formats of Isis3 cubes.
Definition: Cube.h:168
This is the parent of the caching algorithms.
void clear()
Clears PvlKeywords.
Definition: PvlContainer.h:106
QString name() const
Returns the container name.
Definition: PvlContainer.h:78
IO Handler for Isis Cubes.
Definition: Cube.h:158
PixelType pixelType() const
Return the pixel type as an Isis::PixelType.

U.S. Department of the Interior | U.S. Geological Survey
ISIS | Privacy & Disclaimers | Astrogeology Research Program
To contact us, please post comments and questions on the ISIS Support Center
File Modified: 07/12/2023 23:16:51