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) {
76 IString msg =
"Cannot create a CubeIoHandler with a NULL data file";
83 Preference::Preferences().findGroup(
"Performance");
84 IString cubeWritePerfOpt = performancePrefs[
"CubeWriteThread"][0];
87 cubeWritePerfOpt.DownCase() ==
"always") {
94 m_rawData =
new QMap<int, RawCubeChunk *>;
106 const PvlGroup &pixelGroup = core.findGroup(
"Pixels");
108 QString byteOrderStr = pixelGroup.
findKeyword(
"ByteOrder")[0];
110 byteOrderStr.toUpper());
111 m_base = pixelGroup.findKeyword(
"Base");
123 const PvlGroup &dimensions = core.findGroup(
"Dimensions");
128 m_startByte = (int)core.findKeyword(
"StartByte") - 1;
141 IString msg =
"Constructing CubeIoHandler failed";
145 IString msg =
"Constructing CubeIoHandler failed";
168 while (it.hasNext()) {
176 QMapIterator<int, RawCubeChunk *> it(*
m_rawData);
177 while (it.hasNext()) {
248 QList<RawCubeChunk *> cubeChunks;
249 QList<int > chunkBands;
251 int bufferSampleCount = bufferToFill.SampleDimension();
252 int bufferLineCount = bufferToFill.LineDimension();
253 int bufferBandCount = bufferToFill.BandDimension();
259 int bufferStartSample = bufferToFill.Sample();
260 int bufferStartLine = bufferToFill.Line();
261 int bufferStartBand = bufferToFill.Band();
263 int bufferEndSample = bufferStartSample + bufferSampleCount - 1;
264 int bufferEndLine = bufferStartLine + bufferLineCount - 1;
265 int bufferEndBand = bufferStartBand + bufferBandCount - 1;
268 int startBand = bufferStartBand - 1;
272 int expectedChunkIndex =
280 int chunkStartSample, chunkStartLine, chunkStartBand,
281 chunkEndSample, chunkEndLine, chunkEndBand;
284 chunkStartSample, chunkStartLine, chunkStartBand,
285 chunkEndSample, chunkEndLine, chunkEndBand);
287 if (chunkStartSample == bufferStartSample &&
288 chunkStartLine == bufferStartLine &&
289 chunkStartBand == bufferStartBand &&
290 chunkEndSample == bufferEndSample &&
291 chunkEndLine == bufferEndLine &&
292 chunkEndBand == bufferEndBand) {
293 cubeChunks.append(
getChunk(expectedChunkIndex,
true));
294 chunkBands.append(cubeChunks.last()->getStartBand());
298 if (cubeChunks.empty()) {
301 for(
int i = 0; i < bufferToFill.size(); i++) {
302 bufferToFill[i] =
Null;
305 QPair< QList<RawCubeChunk *>, QList<int> > chunkInfo;
307 bufferToFill.Sample(), bufferToFill.SampleDimension(),
308 bufferToFill.Line(), bufferToFill.LineDimension(),
309 bufferToFill.Band(), bufferToFill.BandDimension());
310 cubeChunks = chunkInfo.first;
311 chunkBands = chunkInfo.second;
314 for (
int i = 0; i < cubeChunks.size(); i++) {
319 if (lastChunkCount !=
m_rawData->size()) {
380 if (blockForWriteCache) {
394 QMapIterator<int, RawCubeChunk *> it(*
m_rawData);
395 while (it.hasNext()) {
399 if(it.value()->isDirty()) {
444 if(virtualBandList && !virtualBandList->empty())
537 return indexOffsetToBand + indexInBand;
615 int numSamples,
int numLines,
int numBands) {
616 bool success =
false;
620 IString msg =
"You cannot change the chunk sizes once set";
622 else if(numSamples < 1) {
623 msg =
"Negative and zero chunk sizes are not supported, samples per chunk"
624 " cannot be [" +
IString(numSamples) +
"]";
626 else if(numLines < 1) {
627 msg =
"Negative and zero chunk sizes are not supported, lines per chunk "
628 "cannot be [" +
IString(numLines) +
"]";
630 else if(numBands < 1) {
631 msg =
"Negative and zero chunk sizes are not supported, lines per chunk "
632 "cannot be [" +
IString(numBands) +
"]";
649 " bytes] not big enough to hold data [" +
682 bool lessThan =
false;
701 if (!lhsArea.intersect(rhsArea).isValid()) {
702 if (lhs->Band() != rhs->Band()) {
703 lessThan = lhs->Band() < rhs->Band();
705 else if (lhs->Line() != rhs->Line()) {
706 lessThan = lhs->Line() < rhs->Line();
708 else if (lhs->Sample() != rhs->Sample()) {
709 lessThan = lhs->Sample() < rhs->Sample();
731 int numSamples,
int startLine,
int numLines,
int startBand,
732 int numBands)
const {
733 QList<RawCubeChunk *> results;
734 QList<int> resultBands;
736 int lastBand = startBand + numBands - 1;
742 QPoint(max(startSample, 1),
744 QPoint(min(startSample + numSamples - 1,
746 min(startLine + numLines - 1,
752 for(
int band = startBand; band <= lastBand; band ++) {
754 QRect areaLeftInBand(areaInBand);
756 int actualBand = band;
766 while(!areaLeftInBand.isEmpty()) {
814 int areaStartLine = areaLeftInBand.top();
815 int areaStartSample = areaLeftInBand.left();
830 while(chunkRect.intersects(areaLeftInBand) &&
831 (initialChunkBand >= 1 && initialChunkBand <=
bandCount())) {
834 int chunkZPos = initialChunkZPos;
837 int chunkIndex = chunkXPos +
844 results.append(newChunk);
845 resultBands.append(band);
847 chunkRect.moveLeft(chunkRect.right() + 1);
850 areaLeftInBand.setTop(chunkRect.bottom() + 1);
854 return QPair< QList<RawCubeChunk *>, QList<int> >(results, resultBands);
877 int &startX,
int &startY,
int &startZ,
878 int &endX,
int &endY,
int &endZ)
const {
885 int startVBand = cube2.Band();
886 int endVBand = startVBand + cube2.BandDimension() - 1;
888 int startPhysicalBand = 0;
889 int endPhysicalBand = 0;
891 bool startVBandFound =
false;
892 for(
int virtualBand = startVBand; virtualBand <= endVBand; virtualBand ++) {
893 int physicalBand = virtualBand;
895 bool bandExists =
true;
905 if(!startVBandFound) {
906 startPhysicalBand = physicalBand;
907 endPhysicalBand = physicalBand;
908 startVBandFound =
true;
911 if(physicalBand < startPhysicalBand)
912 startPhysicalBand = physicalBand;
914 if(physicalBand > endPhysicalBand)
915 endPhysicalBand = physicalBand;
920 startX = max(cube1.getStartSample(), cube2.Sample());
921 startY = max(cube1.getStartLine(), cube2.Line());
922 startZ = max(cube1.getStartBand(), startPhysicalBand);
923 endX = min(cube1.getStartSample() + cube1.sampleCount() - 1,
924 cube2.Sample() + cube2.SampleDimension() - 1);
925 endY = min(cube1.getStartLine() + cube1.lineCount() - 1,
926 cube2.Line() + cube2.LineDimension() - 1);
927 endZ = min(cube1.getStartBand() + cube1.bandCount() - 1,
944 bool cacheOverflowing =
946 bool shouldAndCanFlush =
false;
947 bool forceStart = force;
951 if (shouldAndCanFlush) {
956 if (cacheOverflowing && !shouldAndCanFlush) {
967 shouldAndCanFlush =
true;
970 else if (!cacheOverflowing && shouldAndCanFlush) {
987 delete bufferToWrite;
1023 if(chunkToFree->isDirty())
1024 (
const_cast<CubeIoHandler *
>(
this))->writeRaw(*chunkToFree);
1046 bool allocateIfNecessary)
const {
1053 if(allocateIfNecessary && !chunk) {
1056 (*m_dataIsOnDiskMap)[chunkIndex] =
true;
1066 endSample, endLine, endBand);
1067 chunk =
new RawCubeChunk(startSample, startLine, startBand,
1068 endSample, endLine, endBand,
1072 chunk->setDirty(
false);
1075 (*m_rawData)[chunkIndex] = chunk;
1105 int &startSample,
int &startLine,
int &startBand,
1106 int &endSample,
int &endLine,
int &endBand)
const {
1115 int chunkBandIndex = chunkIndex;
1139 int startSample = 0;
1148 endSample, endLine, endBand);
1163 for(
int i = 0; i < nullBuffer.size(); i++) {
1164 nullBuffer[i] =
Null;
1189 const Buffer &justRequested)
const {
1194 bool algorithmAccepted =
false;
1196 int algorithmIndex = 0;
1197 while(!algorithmAccepted &&
1198 algorithmIndex < m_cachingAlgorithms->size()) {
1207 if(algorithmAccepted) {
1211 foreach(chunkToFree, chunksToFree) {
1220 if(!algorithmAccepted &&
m_rawData->size() > 100) {
1238 QList<RawCubeChunk *> cubeChunks;
1239 QList<int> cubeChunkBands;
1241 int bufferSampleCount = bufferToWrite.SampleDimension();
1242 int bufferLineCount = bufferToWrite.LineDimension();
1243 int bufferBandCount = bufferToWrite.BandDimension();
1249 if(bufferToWrite.Sample() == 1 &&
1251 bufferLineCount == 1 &&
1252 bufferBandCount == 1) {
1255 int bufferLine = bufferToWrite.Line();
1256 int chunkStartLine =
1257 (*m_lastProcessByLineChunks)[0]->getStartLine();
1259 (*m_lastProcessByLineChunks)[0]->lineCount();
1260 int bufferBand = bufferToWrite.Band();
1261 int chunkStartBand =
1262 (*m_lastProcessByLineChunks)[0]->getStartBand();
1264 (*m_lastProcessByLineChunks)[0]->bandCount();
1266 if(bufferLine >= chunkStartLine &&
1267 bufferLine <= chunkStartLine + chunkLines - 1 &&
1268 bufferBand >= chunkStartBand &&
1269 bufferBand <= chunkStartBand + chunkBands - 1) {
1271 for (
int i = 0; i < cubeChunks.size(); i++) {
1272 cubeChunkBands.append( cubeChunks[i]->getStartBand() );
1281 int bufferStartSample = bufferToWrite.Sample();
1282 int bufferStartLine = bufferToWrite.Line();
1283 int bufferStartBand = bufferToWrite.Band();
1285 int bufferEndSample = bufferStartSample + bufferSampleCount - 1;
1286 int bufferEndLine = bufferStartLine + bufferLineCount - 1;
1287 int bufferEndBand = bufferStartBand + bufferBandCount - 1;
1289 int expectedChunkIndex =
1297 int chunkStartSample, chunkStartLine, chunkStartBand,
1298 chunkEndSample, chunkEndLine, chunkEndBand;
1301 chunkStartSample, chunkStartLine, chunkStartBand,
1302 chunkEndSample, chunkEndLine, chunkEndBand);
1304 if (chunkStartSample == bufferStartSample &&
1305 chunkStartLine == bufferStartLine &&
1306 chunkStartBand == bufferStartBand &&
1307 chunkEndSample == bufferEndSample &&
1308 chunkEndLine == bufferEndLine &&
1309 chunkEndBand == bufferEndBand) {
1310 cubeChunks.append(
getChunk(expectedChunkIndex,
true));
1311 cubeChunkBands.append(cubeChunks.last()->getStartBand());
1315 QPair< QList<RawCubeChunk *>, QList<int> > chunkInfo;
1316 if(cubeChunks.empty()) {
1318 bufferToWrite.Sample(), bufferSampleCount,
1319 bufferToWrite.Line(), bufferLineCount,
1320 bufferToWrite.Band(), bufferBandCount);
1321 cubeChunks = chunkInfo.first;
1322 cubeChunkBands = chunkInfo.second;
1326 if(bufferToWrite.Sample() == 1 &&
1328 bufferLineCount == 1 &&
1329 bufferBandCount == 1) {
1332 new QList<RawCubeChunk *>(cubeChunks);
1337 for(
int i = 0; i < cubeChunks.size(); i++) {
1338 writeIntoRaw(bufferToWrite, *cubeChunks[i], cubeChunkBands[i]);
1353 Buffer &output,
int index)
const {
1370 int bufferBand = output.Band();
1371 int bufferBands = output.BandDimension();
1372 int chunkStartSample = chunk.getStartSample();
1373 int chunkStartLine = chunk.getStartLine();
1374 int chunkStartBand = chunk.getStartBand();
1375 int chunkLineSize = chunk.sampleCount();
1376 int chunkBandSize = chunkLineSize * chunk.lineCount();
1378 double *buffersDoubleBuf = output.DoubleBuffer();
1379 const char *chunkBuf = chunk.getRawData().data();
1380 char *buffersRawBuf = (
char *)output.RawBuffer();
1382 for(
int z = startZ; z <= endZ; z++) {
1383 const int &bandIntoChunk = z - chunkStartBand;
1384 int virtualBand = z;
1386 virtualBand = index;
1388 if(virtualBand != 0 && virtualBand >= bufferBand &&
1389 virtualBand <= bufferBand + bufferBands - 1) {
1391 for(
int y = startY; y <= endY; y++) {
1392 const int &lineIntoChunk = y - chunkStartLine;
1393 int bufferIndex = output.Index(startX, y, virtualBand);
1395 for(
int x = startX; x <= endX; x++) {
1396 const int &sampleIntoChunk = x - chunkStartSample;
1398 const int &chunkIndex = sampleIntoChunk +
1399 (chunkLineSize * lineIntoChunk) +
1400 (chunkBandSize * bandIntoChunk);
1402 double &bufferVal = buffersDoubleBuf[bufferIndex];
1405 float raw = ((
float *)chunkBuf)[chunkIndex];
1409 if(raw >= VALID_MIN4) {
1410 bufferVal = (double) raw;
1415 else if(raw == LOW_INSTR_SAT4)
1416 bufferVal = LOW_INSTR_SAT8;
1417 else if(raw == LOW_REPR_SAT4)
1418 bufferVal = LOW_REPR_SAT8;
1419 else if(raw == HIGH_INSTR_SAT4)
1420 bufferVal = HIGH_INSTR_SAT8;
1421 else if(raw == HIGH_REPR_SAT4)
1422 bufferVal = HIGH_REPR_SAT8;
1424 bufferVal = LOW_REPR_SAT8;
1427 ((
float *)buffersRawBuf)[bufferIndex] = raw;
1431 short raw = ((
short *)chunkBuf)[chunkIndex];
1435 if(raw >= VALID_MIN2) {
1441 else if(raw == LOW_INSTR_SAT2)
1442 bufferVal = LOW_INSTR_SAT8;
1443 else if(raw == LOW_REPR_SAT2)
1444 bufferVal = LOW_REPR_SAT8;
1445 else if(raw == HIGH_INSTR_SAT2)
1446 bufferVal = HIGH_INSTR_SAT8;
1447 else if(raw == HIGH_REPR_SAT2)
1448 bufferVal = HIGH_REPR_SAT8;
1450 bufferVal = LOW_REPR_SAT8;
1453 ((
short *)buffersRawBuf)[bufferIndex] = raw;
1458 unsigned short raw = ((
unsigned short *)chunkBuf)[chunkIndex];
1462 if(raw >= VALID_MINU2) {
1465 else if (raw > VALID_MAXU2) {
1466 if(raw == HIGH_INSTR_SATU2)
1467 bufferVal = HIGH_INSTR_SAT8;
1468 else if(raw == HIGH_REPR_SATU2)
1469 bufferVal = HIGH_REPR_SAT8;
1471 bufferVal = LOW_REPR_SAT8;
1476 else if(raw == LOW_INSTR_SATU2)
1477 bufferVal = LOW_INSTR_SAT8;
1478 else if(raw == LOW_REPR_SATU2)
1479 bufferVal = LOW_REPR_SAT8;
1481 bufferVal = LOW_REPR_SAT8;
1484 ((
unsigned short *)buffersRawBuf)[bufferIndex] = raw;
1489 unsigned int raw = ((
unsigned int *)chunkBuf)[chunkIndex];
1493 if(raw >= VALID_MINUI4) {
1496 else if (raw > VALID_MAXUI4) {
1497 if(raw == HIGH_INSTR_SATUI4)
1498 bufferVal = HIGH_INSTR_SAT8;
1499 else if(raw == HIGH_REPR_SATUI4)
1500 bufferVal = HIGH_REPR_SAT8;
1502 bufferVal = LOW_REPR_SAT8;
1507 else if(raw == LOW_INSTR_SATUI4)
1508 bufferVal = LOW_INSTR_SAT8;
1509 else if(raw == LOW_REPR_SATUI4)
1510 bufferVal = LOW_REPR_SAT8;
1512 bufferVal = LOW_REPR_SAT8;
1515 ((
unsigned int *)buffersRawBuf)[bufferIndex] = raw;
1522 unsigned char raw = ((
unsigned char *)chunkBuf)[chunkIndex];
1527 else if(raw == HIGH_REPR_SAT1) {
1528 bufferVal = HIGH_REPR_SAT8;
1534 ((
unsigned char *)buffersRawBuf)[bufferIndex] = raw;
1568 output.setDirty(
true);
1569 findIntersection(output, buffer, startX, startY, startZ, endX, endY, endZ);
1571 int bufferBand = buffer.
Band();
1573 int outputStartSample = output.getStartSample();
1574 int outputStartLine = output.getStartLine();
1575 int outputStartBand = output.getStartBand();
1576 int lineSize = output.sampleCount();
1577 int bandSize = lineSize * output.lineCount();
1579 char *chunkBuf = output.getRawData().data();
1581 for(
int z = startZ; z <= endZ; z++) {
1582 const int &bandIntoChunk = z - outputStartBand;
1583 int virtualBand = index;
1590 if(virtualBand != 0 && virtualBand >= bufferBand &&
1591 virtualBand <= bufferBand + bufferBands - 1) {
1593 for(
int y = startY; y <= endY; y++) {
1594 const int &lineIntoChunk = y - outputStartLine;
1595 int bufferIndex = buffer.
Index(startX, y, virtualBand);
1597 for(
int x = startX; x <= endX; x++) {
1598 const int &sampleIntoChunk = x - outputStartSample;
1600 const int &chunkIndex = sampleIntoChunk +
1601 (lineSize * lineIntoChunk) + (bandSize * bandIntoChunk);
1603 double bufferVal = buffersDoubleBuf[bufferIndex];
1608 if(bufferVal >= VALID_MIN8) {
1609 double filePixelValueDbl = (bufferVal -
m_base) /
1612 if(filePixelValueDbl < (
double) VALID_MIN4) {
1613 raw = LOW_REPR_SAT4;
1615 else if(filePixelValueDbl > (
double) VALID_MAX4) {
1616 raw = HIGH_REPR_SAT4;
1619 raw = (float) filePixelValueDbl;
1623 if(bufferVal == NULL8)
1625 else if(bufferVal == LOW_INSTR_SAT8)
1626 raw = LOW_INSTR_SAT4;
1627 else if(bufferVal == LOW_REPR_SAT8)
1628 raw = LOW_REPR_SAT4;
1629 else if(bufferVal == HIGH_INSTR_SAT8)
1630 raw = HIGH_INSTR_SAT4;
1631 else if(bufferVal == HIGH_REPR_SAT8)
1632 raw = HIGH_REPR_SAT4;
1634 raw = LOW_REPR_SAT4;
1636 ((
float *)chunkBuf)[chunkIndex] =
1643 if(bufferVal >= VALID_MIN8) {
1644 double filePixelValueDbl = (bufferVal -
m_base) /
1646 if(filePixelValueDbl < VALID_MIN2 - 0.5) {
1647 raw = LOW_REPR_SAT2;
1649 if(filePixelValueDbl > VALID_MAX2 + 0.5) {
1650 raw = HIGH_REPR_SAT2;
1653 int filePixelValue = (int)round(filePixelValueDbl);
1655 if(filePixelValue < VALID_MIN2) {
1656 raw = LOW_REPR_SAT2;
1658 else if(filePixelValue > VALID_MAX2) {
1659 raw = HIGH_REPR_SAT2;
1662 raw = filePixelValue;
1667 if(bufferVal == NULL8)
1669 else if(bufferVal == LOW_INSTR_SAT8)
1670 raw = LOW_INSTR_SAT2;
1671 else if(bufferVal == LOW_REPR_SAT8)
1672 raw = LOW_REPR_SAT2;
1673 else if(bufferVal == HIGH_INSTR_SAT8)
1674 raw = HIGH_INSTR_SAT2;
1675 else if(bufferVal == HIGH_REPR_SAT8)
1676 raw = HIGH_REPR_SAT2;
1678 raw = LOW_REPR_SAT2;
1681 ((
short *)chunkBuf)[chunkIndex] =
1689 if(bufferVal >= VALID_MINUI4) {
1690 double filePixelValueDbl = (bufferVal -
m_base) /
1692 if(filePixelValueDbl < VALID_MINUI4 - 0.5) {
1693 raw = LOW_REPR_SATUI4;
1695 if(filePixelValueDbl > VALID_MAXUI4) {
1696 raw = HIGH_REPR_SATUI4;
1699 unsigned int filePixelValue = (
unsigned int)round(filePixelValueDbl);
1701 if(filePixelValue < VALID_MINUI4) {
1702 raw = LOW_REPR_SATUI4;
1704 else if(filePixelValue > VALID_MAXUI4) {
1705 raw = HIGH_REPR_SATUI4;
1708 raw = filePixelValue;
1713 if(bufferVal == NULL8)
1715 else if(bufferVal == LOW_INSTR_SAT8)
1716 raw = LOW_INSTR_SATUI4;
1717 else if(bufferVal == LOW_REPR_SAT8)
1718 raw = LOW_REPR_SATUI4;
1719 else if(bufferVal == HIGH_INSTR_SAT8)
1720 raw = HIGH_INSTR_SATUI4;
1721 else if(bufferVal == HIGH_REPR_SAT8)
1722 raw = HIGH_REPR_SATUI4;
1724 raw = LOW_REPR_SATUI4;
1727 ((
unsigned int *)chunkBuf)[chunkIndex] =
1736 if(bufferVal >= VALID_MIN8) {
1737 double filePixelValueDbl = (bufferVal -
m_base) /
1739 if(filePixelValueDbl < VALID_MINU2 - 0.5) {
1740 raw = LOW_REPR_SATU2;
1742 if(filePixelValueDbl > VALID_MAXU2 + 0.5) {
1743 raw = HIGH_REPR_SATU2;
1746 int filePixelValue = (int)round(filePixelValueDbl);
1748 if(filePixelValue < VALID_MINU2) {
1749 raw = LOW_REPR_SATU2;
1751 else if(filePixelValue > VALID_MAXU2) {
1752 raw = HIGH_REPR_SATU2;
1755 raw = filePixelValue;
1760 if(bufferVal == NULL8)
1762 else if(bufferVal == LOW_INSTR_SAT8)
1763 raw = LOW_INSTR_SATU2;
1764 else if(bufferVal == LOW_REPR_SAT8)
1765 raw = LOW_REPR_SATU2;
1766 else if(bufferVal == HIGH_INSTR_SAT8)
1767 raw = HIGH_INSTR_SATU2;
1768 else if(bufferVal == HIGH_REPR_SAT8)
1769 raw = HIGH_REPR_SATU2;
1771 raw = LOW_REPR_SATU2;
1774 ((
unsigned short *)chunkBuf)[chunkIndex] =
1780 if(bufferVal >= VALID_MIN8) {
1781 double filePixelValueDbl = (bufferVal -
m_base) /
1783 if(filePixelValueDbl < VALID_MIN1 - 0.5) {
1784 raw = LOW_REPR_SAT1;
1786 else if(filePixelValueDbl > VALID_MAX1 + 0.5) {
1787 raw = HIGH_REPR_SAT1;
1790 int filePixelValue = (int)(filePixelValueDbl + 0.5);
1791 if(filePixelValue < VALID_MIN1) {
1792 raw = LOW_REPR_SAT1;
1794 else if(filePixelValue > VALID_MAX1) {
1795 raw = HIGH_REPR_SAT1;
1798 raw = (
unsigned char)(filePixelValue);
1803 if(bufferVal == NULL8)
1805 else if(bufferVal == LOW_INSTR_SAT8)
1806 raw = LOW_INSTR_SAT1;
1807 else if(bufferVal == LOW_REPR_SAT8)
1808 raw = LOW_REPR_SAT1;
1809 else if(bufferVal == HIGH_INSTR_SAT8)
1810 raw = HIGH_INSTR_SAT1;
1811 else if(bufferVal == HIGH_REPR_SAT8)
1812 raw = HIGH_REPR_SAT1;
1814 raw = LOW_REPR_SAT1;
1817 ((
unsigned char *)chunkBuf)[chunkIndex] = raw;
1833 IString msg =
"Cannot call CubeIoHandler::writeNullDataToDisk unless "
1834 "data is not already on disk (Cube::Create was called)";
1839 for(
int i = 0; i < numChunks; i++) {
1843 (*m_dataIsOnDiskMap)[i] =
true;
1866 CubeIoHandler * ioHandler, QList<Buffer *> buffersToWrite) {
1887 int elapsedMs = m_timer->elapsed();
1888 int idealFlushElapsedTime = 100;
1894 int msOffIdeal = elapsedMs - idealFlushElapsedTime;
1895 double percentOffIdeal = msOffIdeal / (double)idealFlushElapsedTime;
1898 int currentCacheSize = m_ioHandler->m_idealFlushSize;
1899 int desiredAdjustment = -1 * currentCacheSize * percentOffIdeal;
1900 int desiredCacheSize = (int)(currentCacheSize + desiredAdjustment);
1901 m_ioHandler->m_idealFlushSize = (int)(qMin(5000,
1902 qMax(32, desiredCacheSize)));
1907 m_ioHandler->m_writeThreadMutex->unlock();
1910 delete m_buffersToWrite;
1911 m_buffersToWrite = NULL;
1940 foreach (
Buffer * bufferToWrite, *m_buffersToWrite) {
1941 m_ioHandler->synchronousWrite(*bufferToWrite);
1942 delete bufferToWrite;
1945 m_buffersToWrite->clear();
1946 m_ioHandler->m_dataFile->flush();
Represents a 3D area (a 3D "cube")
Buffer for containing a three dimensional section of an image.
Buffer for reading and writing cube data.
double * DoubleBuffer() const
Returns the value of 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 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.
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.
Handles converting buffers to and from disk.
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.
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.
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.
QMutex * dataFileMutex()
Get the mutex that this IO handler is using around I/Os on the given data file.
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.
QMutex * m_writeThreadMutex
This enables us to block while the write thread is working.
QList< int > * m_virtualBands
Converts from virtual band to physical band.
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.
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...
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.
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.
void write(const Buffer &bufferToWrite)
Write buffer data into the cube data on disk.
BigInt m_startByte
The start byte of the cube data.
void setVirtualBands(const QList< int > *virtualBandList)
This changes the virtual band list.
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
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.
float Float(void *buf)
Swaps a floating point value.
short int ShortInt(void *buf)
Swaps a short integer value.
uint32_t Uint32_t(void *buf)
Swaps a 32bit unsigned integer.
unsigned short int UnsignedShortInt(void *buf)
Swaps an unsigned short integer value.
@ Programmer
This error is for when a programmer made an API call that was illegal.
Adds specific functionality to C++ strings.
PvlKeyword & findKeyword(const QString &name)
Find a keyword with a specified name.
Contains multiple PvlContainers.
Container for cube-like labels.
Contains Pvl Groups and Pvl Objects.
PvlObjectIterator findObject(const QString &name, PvlObjectIterator beg, PvlObjectIterator end)
Find the index of object with a specified name, between two indexes.
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.
int SizeOf(Isis::PixelType pixelType)
Returns the number of bytes of the specified PixelType.
Isis::PixelType PixelTypeEnumeration(const QString &type)
Returns PixelType enumeration given a string.
const double Null
Value for an Isis Null pixel.
long long int BigInt
Big int.
PixelType
Enumerations for Isis Pixel Types.
Namespace for the standard library.