7#include "CubeIoHandler.h"
16#include <QListIterator>
17#include <QMapIterator>
21#include <QElapsedTimer>
25#include "CubeCachingAlgorithm.h"
26#include "Displacement.h"
29#include "EndianSwapper.h"
30#include "IException.h"
33#include "Preference.h"
37#include "RawCubeChunk.h"
38#include "RegionalCachingAlgorithm.h"
39#include "SpecialPixel.h"
40#include "Statistics.h"
62 const QList<int> *virtualBandList,
const Pvl &label,
bool alreadyOnDisk) :
63 ImageIoHandler(virtualBandList) {
75 IString msg =
"Cannot create a CubeIoHandler with a NULL data file";
76 throw IException(IException::Programmer, msg, _FILEINFO_);
81 PvlGroup &performancePrefs =
82 Preference::Preferences().findGroup(
"Performance");
83 IString cubeWritePerfOpt = performancePrefs[
"CubeWriteThread"][0];
86 cubeWritePerfOpt.DownCase() ==
"always") {
104 const PvlObject &core = label.findObject(
"IsisCube").findObject(
"Core");
105 const PvlGroup &pixelGroup = core.findGroup(
"Pixels");
107 QString byteOrderStr = pixelGroup.findKeyword(
"ByteOrder")[0];
109 byteOrderStr.toUpper());
110 m_base = pixelGroup.findKeyword(
"Base");
112 m_pixelType = PixelTypeEnumeration(pixelGroup.findKeyword(
"Type"));
122 const PvlGroup &dimensions = core.findGroup(
"Dimensions");
127 m_startByte = (int)core.findKeyword(
"StartByte") - 1;
137 catch(IException &e) {
138 IString msg =
"Constructing CubeIoHandler failed";
139 throw IException(e, IException::Programmer, msg, _FILEINFO_);
142 IString msg =
"Constructing CubeIoHandler failed";
143 throw IException(IException::Programmer, msg, _FILEINFO_);
165 while (it.hasNext()) {
173 QMapIterator<int, RawCubeChunk *> it(*
m_rawData);
174 while (it.hasNext()) {
250 int bufferStartSample = bufferToFill.
Sample();
251 int bufferStartLine = bufferToFill.
Line();
252 int bufferStartBand = bufferToFill.
Band();
254 int bufferEndSample = bufferStartSample + bufferSampleCount - 1;
255 int bufferEndLine = bufferStartLine + bufferLineCount - 1;
256 int bufferEndBand = bufferStartBand + bufferBandCount - 1;
259 int startBand = bufferStartBand - 1;
263 int expectedChunkIndex =
271 int chunkStartSample, chunkStartLine, chunkStartBand,
272 chunkEndSample, chunkEndLine, chunkEndBand;
275 chunkStartSample, chunkStartLine, chunkStartBand,
276 chunkEndSample, chunkEndLine, chunkEndBand);
278 if (chunkStartSample == bufferStartSample &&
279 chunkStartLine == bufferStartLine &&
280 chunkStartBand == bufferStartBand &&
281 chunkEndSample == bufferEndSample &&
282 chunkEndLine == bufferEndLine &&
283 chunkEndBand == bufferEndBand) {
284 cubeChunks.append(
getChunk(expectedChunkIndex,
true));
285 chunkBands.append(cubeChunks.last()->getStartBand());
289 if (cubeChunks.empty()) {
292 for(
int i = 0; i < bufferToFill.
size(); i++) {
293 bufferToFill[i] = Null;
296 QPair< QList<RawCubeChunk *>,
QList<int> > chunkInfo;
298 bufferToFill.
Sample(), bufferSampleCount,
299 bufferToFill.
Line(), bufferLineCount,
300 bufferToFill.
Band(), bufferBandCount);
301 cubeChunks = chunkInfo.first;
302 chunkBands = chunkInfo.second;
305 for (
int i = 0; i < cubeChunks.size(); i++) {
310 if (lastChunkCount !=
m_rawData->size()) {
371 if (blockForWriteCache) {
385 QMapIterator<int, RawCubeChunk *> it(*
m_rawData);
386 while (it.hasNext()) {
390 if(it.value()->isDirty()) {
497 return indexOffsetToBand + indexInBand;
575 int numSamples,
int numLines,
int numBands) {
576 bool success =
false;
580 IString msg =
"You cannot change the chunk sizes once set";
582 else if(numSamples < 1) {
583 msg =
"Negative and zero chunk sizes are not supported, samples per chunk"
584 " cannot be [" + IString(numSamples) +
"]";
586 else if(numLines < 1) {
587 msg =
"Negative and zero chunk sizes are not supported, lines per chunk "
588 "cannot be [" + IString(numLines) +
"]";
590 else if(numBands < 1) {
591 msg =
"Negative and zero chunk sizes are not supported, lines per chunk "
592 "cannot be [" + IString(numBands) +
"]";
608 msg =
"File size [" + IString((BigInt)
m_dataFile->size()) +
609 " bytes] not big enough to hold data [" +
616 throw IException(IException::Programmer, msg, _FILEINFO_);
642 bool lessThan =
false;
663 lessThan = lhs->
Band() < rhs->
Band();
665 else if (lhs->
Line() != rhs->
Line()) {
666 lessThan = lhs->
Line() < rhs->
Line();
691 int numSamples,
int startLine,
int numLines,
int startBand,
692 int numBands)
const {
696 int lastBand = startBand + numBands - 1;
702 QPoint(max(startSample, 1),
704 QPoint(min(startSample + numSamples - 1,
706 min(startLine + numLines - 1,
712 for(
int band = startBand; band <= lastBand; band ++) {
714 QRect areaLeftInBand(areaInBand);
716 int actualBand = band;
726 while(!areaLeftInBand.isEmpty()) {
774 int areaStartLine = areaLeftInBand.top();
775 int areaStartSample = areaLeftInBand.left();
790 while(chunkRect.intersects(areaLeftInBand) &&
791 (initialChunkBand >= 1 && initialChunkBand <=
bandCount())) {
794 int chunkZPos = initialChunkZPos;
797 int chunkIndex = chunkXPos +
804 results.append(newChunk);
805 resultBands.append(band);
807 chunkRect.moveLeft(chunkRect.right() + 1);
810 areaLeftInBand.setTop(chunkRect.bottom() + 1);
814 return QPair< QList<RawCubeChunk *>,
QList<int> >(results, resultBands);
837 int &startX,
int &startY,
int &startZ,
838 int &endX,
int &endY,
int &endZ)
const {
845 int startVBand = cube2.
Band();
848 int startPhysicalBand = 0;
849 int endPhysicalBand = 0;
851 bool startVBandFound =
false;
852 for(
int virtualBand = startVBand; virtualBand <= endVBand; virtualBand ++) {
853 int physicalBand = virtualBand;
855 bool bandExists =
true;
865 if(!startVBandFound) {
866 startPhysicalBand = physicalBand;
867 endPhysicalBand = physicalBand;
868 startVBandFound =
true;
871 if(physicalBand < startPhysicalBand)
872 startPhysicalBand = physicalBand;
874 if(physicalBand > endPhysicalBand)
875 endPhysicalBand = physicalBand;
904 bool cacheOverflowing =
906 bool shouldAndCanFlush =
false;
907 bool forceStart = force;
911 if (shouldAndCanFlush) {
916 if (cacheOverflowing && !shouldAndCanFlush) {
927 shouldAndCanFlush =
true;
930 else if (!cacheOverflowing && shouldAndCanFlush) {
947 delete bufferToWrite;
1006 bool allocateIfNecessary)
const {
1013 if(allocateIfNecessary && !chunk) {
1016 (*m_dataIsOnDiskMap)[chunkIndex] =
true;
1026 endSample, endLine, endBand);
1027 chunk =
new RawCubeChunk(startSample, startLine, startBand,
1028 endSample, endLine, endBand,
1035 (*m_rawData)[chunkIndex] = chunk;
1065 int &startSample,
int &startLine,
int &startBand,
1066 int &endSample,
int &endLine,
int &endBand)
const {
1075 int chunkBandIndex = chunkIndex;
1099 int startSample = 0;
1108 endSample, endLine, endBand);
1123 for(
int i = 0; i < nullBuffer.
size(); i++) {
1124 nullBuffer[i] = Null;
1149 const Buffer &justRequested)
const {
1154 bool algorithmAccepted =
false;
1156 int algorithmIndex = 0;
1157 while(!algorithmAccepted &&
1158 algorithmIndex < m_cachingAlgorithms->size()) {
1167 if(algorithmAccepted) {
1171 foreach(chunkToFree, chunksToFree) {
1180 if(!algorithmAccepted &&
m_rawData->size() > 100) {
1209 if(bufferToWrite.
Sample() == 1 &&
1211 bufferLineCount == 1 &&
1212 bufferBandCount == 1) {
1215 int bufferLine = bufferToWrite.
Line();
1216 int chunkStartLine =
1217 (*m_lastProcessByLineChunks)[0]->getStartLine();
1219 (*m_lastProcessByLineChunks)[0]->lineCount();
1220 int bufferBand = bufferToWrite.
Band();
1221 int chunkStartBand =
1222 (*m_lastProcessByLineChunks)[0]->getStartBand();
1224 (*m_lastProcessByLineChunks)[0]->bandCount();
1226 if(bufferLine >= chunkStartLine &&
1227 bufferLine <= chunkStartLine + chunkLines - 1 &&
1228 bufferBand >= chunkStartBand &&
1229 bufferBand <= chunkStartBand + chunkBands - 1) {
1231 for (
int i = 0; i < cubeChunks.size(); i++) {
1232 cubeChunkBands.append( cubeChunks[i]->getStartBand() );
1241 int bufferStartSample = bufferToWrite.
Sample();
1242 int bufferStartLine = bufferToWrite.
Line();
1243 int bufferStartBand = bufferToWrite.
Band();
1245 int bufferEndSample = bufferStartSample + bufferSampleCount - 1;
1246 int bufferEndLine = bufferStartLine + bufferLineCount - 1;
1247 int bufferEndBand = bufferStartBand + bufferBandCount - 1;
1249 int expectedChunkIndex =
1257 int chunkStartSample, chunkStartLine, chunkStartBand,
1258 chunkEndSample, chunkEndLine, chunkEndBand;
1261 chunkStartSample, chunkStartLine, chunkStartBand,
1262 chunkEndSample, chunkEndLine, chunkEndBand);
1264 if (chunkStartSample == bufferStartSample &&
1265 chunkStartLine == bufferStartLine &&
1266 chunkStartBand == bufferStartBand &&
1267 chunkEndSample == bufferEndSample &&
1268 chunkEndLine == bufferEndLine &&
1269 chunkEndBand == bufferEndBand) {
1270 cubeChunks.append(
getChunk(expectedChunkIndex,
true));
1271 cubeChunkBands.append(cubeChunks.last()->getStartBand());
1275 QPair< QList<RawCubeChunk *>,
QList<int> > chunkInfo;
1276 if(cubeChunks.empty()) {
1278 bufferToWrite.
Sample(), bufferSampleCount,
1279 bufferToWrite.
Line(), bufferLineCount,
1280 bufferToWrite.
Band(), bufferBandCount);
1281 cubeChunks = chunkInfo.first;
1282 cubeChunkBands = chunkInfo.second;
1286 if(bufferToWrite.
Sample() == 1 &&
1288 bufferLineCount == 1 &&
1289 bufferBandCount == 1) {
1297 for(
int i = 0; i < cubeChunks.size(); i++) {
1298 writeIntoRaw(bufferToWrite, *cubeChunks[i], cubeChunkBands[i]);
1313 Buffer &output,
int index)
const {
1330 int bufferBand = output.
Band();
1336 int chunkBandSize = chunkLineSize * chunk.
lineCount();
1339 const char *chunkBuf = chunk.
getRawData().data();
1340 char *buffersRawBuf = (
char *)output.
RawBuffer();
1342 for(
int z = startZ; z <= endZ; z++) {
1343 const int &bandIntoChunk = z - chunkStartBand;
1344 int virtualBand = z;
1346 virtualBand = index;
1348 if(virtualBand != 0 && virtualBand >= bufferBand &&
1349 virtualBand <= bufferBand + bufferBands - 1) {
1351 for(
int y = startY; y <= endY; y++) {
1352 const int &lineIntoChunk = y - chunkStartLine;
1353 int bufferIndex = output.
Index(startX, y, virtualBand);
1355 for(
int x = startX; x <= endX; x++) {
1356 const int &sampleIntoChunk = x - chunkStartSample;
1358 const int &chunkIndex = sampleIntoChunk +
1359 (chunkLineSize * lineIntoChunk) +
1360 (chunkBandSize * bandIntoChunk);
1362 double &bufferVal = buffersDoubleBuf[bufferIndex];
1365 float raw = ((
float *)chunkBuf)[chunkIndex];
1369 if(raw >= VALID_MIN4) {
1370 bufferVal = (double) raw;
1375 else if(raw == LOW_INSTR_SAT4)
1376 bufferVal = LOW_INSTR_SAT8;
1377 else if(raw == LOW_REPR_SAT4)
1378 bufferVal = LOW_REPR_SAT8;
1379 else if(raw == HIGH_INSTR_SAT4)
1380 bufferVal = HIGH_INSTR_SAT8;
1381 else if(raw == HIGH_REPR_SAT4)
1382 bufferVal = HIGH_REPR_SAT8;
1384 bufferVal = LOW_REPR_SAT8;
1387 ((
float *)buffersRawBuf)[bufferIndex] = raw;
1391 short raw = ((
short *)chunkBuf)[chunkIndex];
1395 if(raw >= VALID_MIN2) {
1401 else if(raw == LOW_INSTR_SAT2)
1402 bufferVal = LOW_INSTR_SAT8;
1403 else if(raw == LOW_REPR_SAT2)
1404 bufferVal = LOW_REPR_SAT8;
1405 else if(raw == HIGH_INSTR_SAT2)
1406 bufferVal = HIGH_INSTR_SAT8;
1407 else if(raw == HIGH_REPR_SAT2)
1408 bufferVal = HIGH_REPR_SAT8;
1410 bufferVal = LOW_REPR_SAT8;
1413 ((
short *)buffersRawBuf)[bufferIndex] = raw;
1418 unsigned short raw = ((
unsigned short *)chunkBuf)[chunkIndex];
1422 if(raw >= VALID_MINU2) {
1425 else if (raw > VALID_MAXU2) {
1426 if(raw == HIGH_INSTR_SATU2)
1427 bufferVal = HIGH_INSTR_SAT8;
1428 else if(raw == HIGH_REPR_SATU2)
1429 bufferVal = HIGH_REPR_SAT8;
1431 bufferVal = LOW_REPR_SAT8;
1436 else if(raw == LOW_INSTR_SATU2)
1437 bufferVal = LOW_INSTR_SAT8;
1438 else if(raw == LOW_REPR_SATU2)
1439 bufferVal = LOW_REPR_SAT8;
1441 bufferVal = LOW_REPR_SAT8;
1444 ((
unsigned short *)buffersRawBuf)[bufferIndex] = raw;
1449 unsigned int raw = ((
unsigned int *)chunkBuf)[chunkIndex];
1453 if(raw >= VALID_MINUI4) {
1456 else if (raw > VALID_MAXUI4) {
1457 if(raw == HIGH_INSTR_SATUI4)
1458 bufferVal = HIGH_INSTR_SAT8;
1459 else if(raw == HIGH_REPR_SATUI4)
1460 bufferVal = HIGH_REPR_SAT8;
1462 bufferVal = LOW_REPR_SAT8;
1467 else if(raw == LOW_INSTR_SATUI4)
1468 bufferVal = LOW_INSTR_SAT8;
1469 else if(raw == LOW_REPR_SATUI4)
1470 bufferVal = LOW_REPR_SAT8;
1472 bufferVal = LOW_REPR_SAT8;
1475 ((
unsigned int *)buffersRawBuf)[bufferIndex] = raw;
1482 unsigned char raw = ((
unsigned char *)chunkBuf)[chunkIndex];
1487 else if(raw == HIGH_REPR_SAT1) {
1488 bufferVal = HIGH_REPR_SAT8;
1494 ((
unsigned char *)buffersRawBuf)[bufferIndex] = raw;
1529 findIntersection(output, buffer, startX, startY, startZ, endX, endY, endZ);
1531 int bufferBand = buffer.
Band();
1537 int bandSize = lineSize * output.
lineCount();
1541 for(
int z = startZ; z <= endZ; z++) {
1542 const int &bandIntoChunk = z - outputStartBand;
1543 int virtualBand = index;
1550 if(virtualBand != 0 && virtualBand >= bufferBand &&
1551 virtualBand <= bufferBand + bufferBands - 1) {
1553 for(
int y = startY; y <= endY; y++) {
1554 const int &lineIntoChunk = y - outputStartLine;
1555 int bufferIndex = buffer.
Index(startX, y, virtualBand);
1557 for(
int x = startX; x <= endX; x++) {
1558 const int &sampleIntoChunk = x - outputStartSample;
1560 const int &chunkIndex = sampleIntoChunk +
1561 (lineSize * lineIntoChunk) + (bandSize * bandIntoChunk);
1563 double bufferVal = buffersDoubleBuf[bufferIndex];
1568 if(bufferVal >= VALID_MIN8) {
1569 double filePixelValueDbl = (bufferVal -
m_base) /
1572 if(filePixelValueDbl < (
double) VALID_MIN4) {
1573 raw = LOW_REPR_SAT4;
1575 else if(filePixelValueDbl > (
double) VALID_MAX4) {
1576 raw = HIGH_REPR_SAT4;
1579 raw = (float) filePixelValueDbl;
1583 if(bufferVal == NULL8)
1585 else if(bufferVal == LOW_INSTR_SAT8)
1586 raw = LOW_INSTR_SAT4;
1587 else if(bufferVal == LOW_REPR_SAT8)
1588 raw = LOW_REPR_SAT4;
1589 else if(bufferVal == HIGH_INSTR_SAT8)
1590 raw = HIGH_INSTR_SAT4;
1591 else if(bufferVal == HIGH_REPR_SAT8)
1592 raw = HIGH_REPR_SAT4;
1594 raw = LOW_REPR_SAT4;
1596 ((
float *)chunkBuf)[chunkIndex] =
1603 if(bufferVal >= VALID_MIN8) {
1604 double filePixelValueDbl = (bufferVal -
m_base) /
1606 if(filePixelValueDbl < VALID_MIN2 - 0.5) {
1607 raw = LOW_REPR_SAT2;
1609 if(filePixelValueDbl > VALID_MAX2 + 0.5) {
1610 raw = HIGH_REPR_SAT2;
1613 int filePixelValue = (int)round(filePixelValueDbl);
1615 if(filePixelValue < VALID_MIN2) {
1616 raw = LOW_REPR_SAT2;
1618 else if(filePixelValue > VALID_MAX2) {
1619 raw = HIGH_REPR_SAT2;
1622 raw = filePixelValue;
1627 if(bufferVal == NULL8)
1629 else if(bufferVal == LOW_INSTR_SAT8)
1630 raw = LOW_INSTR_SAT2;
1631 else if(bufferVal == LOW_REPR_SAT8)
1632 raw = LOW_REPR_SAT2;
1633 else if(bufferVal == HIGH_INSTR_SAT8)
1634 raw = HIGH_INSTR_SAT2;
1635 else if(bufferVal == HIGH_REPR_SAT8)
1636 raw = HIGH_REPR_SAT2;
1638 raw = LOW_REPR_SAT2;
1641 ((
short *)chunkBuf)[chunkIndex] =
1649 if(bufferVal >= VALID_MINUI4) {
1650 double filePixelValueDbl = (bufferVal -
m_base) /
1652 if(filePixelValueDbl < VALID_MINUI4 - 0.5) {
1653 raw = LOW_REPR_SATUI4;
1655 if(filePixelValueDbl > VALID_MAXUI4) {
1656 raw = HIGH_REPR_SATUI4;
1659 unsigned int filePixelValue = (
unsigned int)round(filePixelValueDbl);
1661 if(filePixelValue < VALID_MINUI4) {
1662 raw = LOW_REPR_SATUI4;
1664 else if(filePixelValue > VALID_MAXUI4) {
1665 raw = HIGH_REPR_SATUI4;
1668 raw = filePixelValue;
1673 if(bufferVal == NULL8)
1675 else if(bufferVal == LOW_INSTR_SAT8)
1676 raw = LOW_INSTR_SATUI4;
1677 else if(bufferVal == LOW_REPR_SAT8)
1678 raw = LOW_REPR_SATUI4;
1679 else if(bufferVal == HIGH_INSTR_SAT8)
1680 raw = HIGH_INSTR_SATUI4;
1681 else if(bufferVal == HIGH_REPR_SAT8)
1682 raw = HIGH_REPR_SATUI4;
1684 raw = LOW_REPR_SATUI4;
1687 ((
unsigned int *)chunkBuf)[chunkIndex] =
1696 if(bufferVal >= VALID_MIN8) {
1697 double filePixelValueDbl = (bufferVal -
m_base) /
1699 if(filePixelValueDbl < VALID_MINU2 - 0.5) {
1700 raw = LOW_REPR_SATU2;
1702 if(filePixelValueDbl > VALID_MAXU2 + 0.5) {
1703 raw = HIGH_REPR_SATU2;
1706 int filePixelValue = (int)round(filePixelValueDbl);
1708 if(filePixelValue < VALID_MINU2) {
1709 raw = LOW_REPR_SATU2;
1711 else if(filePixelValue > VALID_MAXU2) {
1712 raw = HIGH_REPR_SATU2;
1715 raw = filePixelValue;
1720 if(bufferVal == NULL8)
1722 else if(bufferVal == LOW_INSTR_SAT8)
1723 raw = LOW_INSTR_SATU2;
1724 else if(bufferVal == LOW_REPR_SAT8)
1725 raw = LOW_REPR_SATU2;
1726 else if(bufferVal == HIGH_INSTR_SAT8)
1727 raw = HIGH_INSTR_SATU2;
1728 else if(bufferVal == HIGH_REPR_SAT8)
1729 raw = HIGH_REPR_SATU2;
1731 raw = LOW_REPR_SATU2;
1734 ((
unsigned short *)chunkBuf)[chunkIndex] =
1740 if(bufferVal >= VALID_MIN8) {
1741 double filePixelValueDbl = (bufferVal -
m_base) /
1743 if(filePixelValueDbl < VALID_MIN1 - 0.5) {
1744 raw = LOW_REPR_SAT1;
1746 else if(filePixelValueDbl > VALID_MAX1 + 0.5) {
1747 raw = HIGH_REPR_SAT1;
1750 int filePixelValue = (int)(filePixelValueDbl + 0.5);
1751 if(filePixelValue < VALID_MIN1) {
1752 raw = LOW_REPR_SAT1;
1754 else if(filePixelValue > VALID_MAX1) {
1755 raw = HIGH_REPR_SAT1;
1758 raw = (
unsigned char)(filePixelValue);
1763 if(bufferVal == NULL8)
1765 else if(bufferVal == LOW_INSTR_SAT8)
1766 raw = LOW_INSTR_SAT1;
1767 else if(bufferVal == LOW_REPR_SAT8)
1768 raw = LOW_REPR_SAT1;
1769 else if(bufferVal == HIGH_INSTR_SAT8)
1770 raw = HIGH_INSTR_SAT1;
1771 else if(bufferVal == HIGH_REPR_SAT8)
1772 raw = HIGH_REPR_SAT1;
1774 raw = LOW_REPR_SAT1;
1777 ((
unsigned char *)chunkBuf)[chunkIndex] = raw;
1793 IString msg =
"Cannot call CubeIoHandler::writeNullDataToDisk unless "
1794 "data is not already on disk (Cube::Create was called)";
1795 throw IException(IException::Programmer, msg, _FILEINFO_);
1799 for(
int i = 0; i < numChunks; i++) {
1803 (*m_dataIsOnDiskMap)[i] =
true;
1847 int elapsedMs =
m_timer->elapsed();
1848 int idealFlushElapsedTime = 100;
1854 int msOffIdeal = elapsedMs - idealFlushElapsedTime;
1855 double percentOffIdeal = msOffIdeal / (double)idealFlushElapsedTime;
1858 int currentCacheSize =
m_ioHandler->m_idealFlushSize;
1859 int desiredAdjustment = -1 * currentCacheSize * percentOffIdeal;
1860 int desiredCacheSize = (int)(currentCacheSize + desiredAdjustment);
1862 qMax(32, desiredCacheSize)));
1902 delete bufferToWrite;
Represents a 3D area (a 3D "cube")
bool isValid() const
Returns true if all of the positions of the 3D area are valid (i.e.
Area3D intersect(const Area3D &otherArea) const
Returns the intersection of this 3D area with another 3D area.
Buffer for containing a three dimensional section of an image.
void SetBasePosition(const int start_sample, const int start_line, const int start_band)
This method is used to set the base position of the shape buffer.
Buffer for reading and writing cube data.
int size() const
Returns the total number of pixels in the shape buffer.
int Line(const int index=0) const
Returns the line position associated with a shape buffer index.
double * DoubleBuffer() const
Returns the value of the shape buffer.
void * RawBuffer() const
Returns a void pointer to the raw buffer.
int LineDimension() const
Returns the number of lines in the shape buffer.
int Band(const int index=0) const
Returns the band position associated with a shape buffer index.
int BandDimension() const
Returns the number of bands in the shape buffer.
int SampleDimension() const
Returns the number of samples in the shape buffer.
int Index(const int i_samp, const int i_line, const int i_band) const
Given a sample, line, and band position, this returns the appropriate index in the shape buffer.
int Sample(const int index=0) const
Returns the sample position associated with a shape buffer index.
This stores the results of the caching algorithm.
QList< RawCubeChunk * > getChunksToFree() const
bool algorithmUnderstoodData() const
If this is true, then the results (be them empty or not) should be considered valid.
This is the parent of the caching algorithms.
virtual CacheResult recommendChunksToFree(QList< RawCubeChunk * > allocated, QList< RawCubeChunk * > justUsed, const Buffer &justRequested)=0
Call this to determine which chunks should be freed from memory.
This class is designed to handle write() asynchronously.
QElapsedTimer * m_timer
Used to calculate the lifetime of an instance of this class.
BufferToChunkWriter(CubeIoHandler *ioHandler, QList< Buffer * > buffersToWrite)
Create a BufferToChunkWriter which is designed to asynchronously move the given buffers into the cube...
~BufferToChunkWriter()
We're done writing our buffers into the cube, clean up.
QList< Buffer * > * m_buffersToWrite
The buffers that need pushed into the IO handler; we own these.
void run()
This is the asynchronous computation.
CubeIoHandler * m_ioHandler
The IO Handler instance to put the buffers into.
bool m_useOptimizedCubeWrite
This is true if the Isis preference for the cube write thread is optimized.
QList< CubeCachingAlgorithm * > * m_cachingAlgorithms
The caching algorithms to use, in order of priority.
int m_consecutiveOverflowCount
How many times the write cache has overflown in a row.
int m_numBands
The number of physical bands in the cube.
int m_bandsInChunk
The number of physical bands in a cube chunk.
virtual void clearCache(bool blockForWriteCache=true) const
Free all cube chunks (cached cube data) from memory and write them to disk.
int m_samplesInChunk
The number of samples in a cube chunk.
QMap< int, bool > * m_dataIsOnDiskMap
The map from chunk index to on-disk status, all true if not allocated.
void freeChunk(RawCubeChunk *chunkToFree) const
If the chunk is dirty, then we write it to disk.
int m_linesInChunk
The number of lines in a cube chunk.
virtual ~CubeIoHandler()
Cleans up all allocated memory.
virtual void addCachingAlgorithm(CubeCachingAlgorithm *algorithm)
This will add the given caching algorithm to the list of attempted caching algorithms.
int m_numSamples
The number of samples in the cube.
void blockUntilThreadPoolEmpty() const
This blocks (doesn't return) until the number of active runnables in the thread pool goes to 0.
QPair< QList< RawCubeChunk * >, QList< int > > findCubeChunks(int startSample, int numSamples, int startLine, int numLines, int startBand, int numBands) const
Get the cube chunks that correspond to the given cube area.
PixelType pixelType() const
void writeNullDataToDisk() const
Write all NULL cube chunks that have not yet been accessed to disk.
volatile int m_idealFlushSize
Ideal write cache flush size.
int getChunkCountInLineDimension() const
QList< RawCubeChunk * > * m_lastProcessByLineChunks
This is an optimization for process by line.
bool m_lastOperationWasWrite
If the last operation was a write then we need to flush the cache when reading.
void setChunkSizes(int numSamples, int numLines, int numBands)
This should be called once from the child constructor.
PixelType m_pixelType
The format of each DN in the cube.
QByteArray * m_nullChunkData
A raw cube chunk's data when it was all NULL's. Used for speed.
int getLineCountInChunk() const
int getChunkCount() const
double m_multiplier
The multiplicative factor of the data on disk.
int m_numLines
The number of lines in the cube.
int getChunkCountInSampleDimension() const
void minimizeCache(const QList< RawCubeChunk * > &justUsed, const Buffer &justRequested) const
Apply the caching algorithms and get rid of excess cube data in memory.
virtual void readRaw(RawCubeChunk &chunkToFill)=0
This needs to populate the chunkToFill with unswapped raw bytes from the disk.
QFile * m_dataFile
The file containing cube data.
int getChunkCountInBandDimension() const
QPair< QMutex *, QList< Buffer * > > * m_writeCache
These are the buffers we need to write to raw cube chunks.
double m_base
The additive offset of the data on disk.
CubeIoHandler(QFile *dataFile, const QList< int > *virtualBandList, const Pvl &label, bool alreadyOnDisk)
Creates a new CubeIoHandler using a RegionalCachingAlgorithm.
BigInt getBytesPerChunk() const
QMap< int, RawCubeChunk * > * m_rawData
The map from chunk index to chunk for cached data.
QThreadPool * m_ioThreadPool
This contains threads for doing cube writes (and later maybe cube reads).
BigInt getDataStartByte() const
void findIntersection(const RawCubeChunk &cube1, const Buffer &cube2, int &startX, int &startY, int &startZ, int &endX, int &endY, int &endZ) const
Find the intersection between the buffer area and the cube chunk.
void flushWriteCache(bool force=false) const
This attempts to write the so-far-unwritten buffers from m_writeCache into the cube's RawCubeChunk ca...
virtual void writeRaw(const RawCubeChunk &chunkToWrite)=0
This needs to write the chunkToWrite directly to disk with no modifications to the data itself.
void getChunkPlacement(int chunkIndex, int &startSample, int &startLine, int &startBand, int &endSample, int &endLine, int &endBand) const
Get the X/Y/Z (Sample,Line,Band) range of the chunk at the given index.
virtual void read(Buffer &bufferToFill) const
Read cube data from disk into the buffer.
RawCubeChunk * getNullChunk(int chunkIndex) const
This creates a chunk filled with NULLs whose placement is at chunkIndex's position.
virtual void write(const Buffer &bufferToWrite)
Write buffer data into the cube data on disk.
BigInt m_startByte
The start byte of the cube data.
RawCubeChunk * getChunk(int chunkIndex, bool allocateIfNecessary) const
Retrieve the cached chunk at the given chunk index, if there is one.
static bool bufferLessThan(Buffer *const &lhs, Buffer *const &rhs)
This is used for sorting buffers into the most efficient write order.
int getSampleCountInChunk() const
virtual BigInt getDataSize() const
int getBandCountInChunk() const
void writeIntoRaw(const Buffer &buffer, RawCubeChunk &output, int index) const
Write the intersecting area of the buffer into the chunk.
void synchronousWrite(const Buffer &bufferToWrite)
This method takes the given buffer and synchronously puts it into the Cube's cache.
EndianSwapper * m_byteSwapper
A helper that swaps byte order to and from file order.
void writeIntoDouble(const RawCubeChunk &chunk, Buffer &output, int startIndex) const
Write the intersecting area of the chunk into the buffer.
int getChunkIndex(const RawCubeChunk &) const
Given a chunk, what's its index in the file.
Displacement is a signed length, usually in meters.
@ Pixels
The distance is being specified in pixels.
Distance measurement, usually in meters.
@ Pixels
The distance is being specified in pixels.
QList< int > * m_virtualBands
Converts from virtual band to physical band.
QMutex * m_writeThreadMutex
This enables us to block while the write thread is working.
A section of raw data on the disk.
QByteArray & getRawData() const
int getStartSample() const
void setDirty(bool dirty)
Sets the chunk's dirty flag, indicating whether or not the chunk's data matches the data that is on d...
void setRawData(QByteArray rawData)
Sets the chunk's raw data.
This algorithm recommends chunks to be freed that are not within the last IO.
This is free and unencumbered software released into the public domain.
This is free and unencumbered software released into the public domain.
This is free and unencumbered software released into the public domain.
Namespace for the standard library.