83 std::vector<helper::RasterBandMetaData>& bands,
90 int bandCount =
static_cast<int>(bands.size());
91 T *p_data =
reinterpret_cast<T *
>(VSIMalloc3(width * height, bandCount, size));
93 std::vector<helper::Variance> bandVariances(bandCount);
94 std::vector<T> noDataVals(bandCount);
95 for (
size_t i = 0; i < bands.size(); i++) {
96 noDataVals[i] =
static_cast<T
>(bands[i].nan);
100 for (
size_t i = 0; i < bands.size(); i++) {
101 bands[i].p_band->RasterIO(
107 (
void *)((
size_t)p_data + i * size),
112 size * bands.size() * width
118 for (
int i = 0; i < height * width; i++) {
120 for (
int b = 0; b < bandCount; b++) {
121 T val = p_data[i * bandCount + b];
122 isNan = val == noDataVals[b] || std::isnan(val);
126 p_data[nFeatures * bandCount + b] = val;
132 for (
int i = 0; i < nFeatures; i++) {
133 for (
int b = 0; b < bandCount; b++) {
134 T val = p_data[i * bandCount + b];
135 bandVariances[b].update(
static_cast<double>(val));
140 DALHomogenTable table = DALHomogenTable::wrap<T>(p_data, nFeatures, bandCount, oneapi::dal::data_layout::row_major);
141 const auto desc = oneapi::dal::pca::descriptor<T, oneapi::dal::pca::method::cov>().set_component_count(nComp).set_deterministic(
true);
142 const auto result = oneapi::dal::train(desc, table);
147 auto eigenvectors = result.get_eigenvectors();
148 auto eigenvalues = result.get_eigenvalues();
149 int64_t eigRows = eigenvectors.get_row_count();
150 int64_t eigCols = eigenvectors.get_column_count();
152 oneapi::dal::row_accessor<const float> eigVecAcc {eigenvectors};
153 auto eigVecBlock = eigVecAcc.pull({0, eigRows});
155 oneapi::dal::row_accessor<const float> eigValAcc {eigenvalues};
156 auto eigValBlock = eigValAcc.pull({0, 1});
160 for (int64_t i = 0; i < eigRows; i++) {
161 retval.
eigenvalues[i] =
static_cast<double>(eigValBlock[i]);
164 for (int64_t j = 0; j < eigCols; j++) {
165 retval.
eigenvectors[i][j] =
static_cast<double>(eigVecBlock[i * eigCols + j]);
169 for (
int b = 0; b < bandCount; b++) {
170 retval.
means.push_back(bandVariances[b].getMean());
171 retval.
stdevs.push_back(bandVariances[b].getStdev());
220 std::vector<helper::RasterBandMetaData>& bands,
229 int bandCount =
static_cast<int>(bands.size());
230 T *p_data =
reinterpret_cast<T *
>(VSIMalloc3(xBlockSize * yBlockSize, bandCount, size));
232 std::vector<helper::Variance> bandVariances(bandCount);
233 std::vector<T> noDataVals(bandCount);
234 for (
size_t i = 0; i < bands.size(); i++) {
235 noDataVals[i] =
static_cast<T
>(bands[i].nan);
238 const auto desc = oneapi::dal::pca::descriptor<T, oneapi::dal::pca::method::cov>().set_component_count(nComp).set_deterministic(
true);
239 oneapi::dal::pca::partial_train_result<> partial_result;
241 for (
int yBlock = 0; yBlock < yBlocks; yBlock++) {
242 for (
int xBlock = 0; xBlock < xBlocks; xBlock++) {
244 bands[0].p_band->GetActualBlockSize(xBlock, yBlock, &xValid, &yValid);
247 for (
int i = 0; i < bandCount; i++) {
248 bands[i].p_band->RasterIO(
254 (
void *)((
size_t)p_data + i * size),
259 size * bands.size() *
static_cast<size_t>(xBlockSize)
265 for (
int x = 0; x < xValid; x++) {
266 for (
int y = 0; y < yValid; y++) {
268 for (
int b = 0; b < bandCount; b++) {
269 T val = p_data[((y * xBlockSize) + x) * bandCount + b];
270 isNan = std::isnan(val) || val == noDataVals[b];
274 p_data[nFeatures * bandCount + b] = val;
281 for (
int i = 0; i < nFeatures; i++) {
282 for (
int b = 0; b < bandCount; b++) {
283 T val = p_data[i * bandCount + b];
284 bandVariances[b].update(
static_cast<double>(val));
290 partial_result = oneapi::dal::partial_train(desc, partial_result, table);
294 auto result = oneapi::dal::finalize_train(desc, partial_result);
299 auto eigenvectors = result.get_eigenvectors();
300 auto eigenvalues = result.get_eigenvalues();
301 int64_t eigRows = eigenvectors.get_row_count();
302 int64_t eigCols = eigenvectors.get_column_count();
304 oneapi::dal::row_accessor<const T> eigVecAcc {eigenvectors};
305 auto eigVecBlock = eigVecAcc.pull({0, eigRows});
307 oneapi::dal::row_accessor<const T> eigValAcc {eigenvalues};
308 auto eigValBlock = eigValAcc.pull({0, 1});
312 for (int64_t i = 0; i < eigRows; i++) {
313 retval.
eigenvalues[i] =
static_cast<T
>(eigValBlock[i]);
316 for (int64_t j = 0; j < eigCols; j++) {
317 retval.
eigenvectors[i][j] =
static_cast<T
>(eigValBlock[i * eigCols + j]);
321 for (
int b = 0; b < bandCount; b++) {
322 retval.
means.push_back(bandVariances[b].getMean());
323 retval.
stdevs.push_back(bandVariances[b].getStdev());
366 std::vector<helper::RasterBandMetaData>& bands,
367 std::vector<helper::RasterBandMetaData>& PCABands,
374 int bandCount =
static_cast<int>(bands.size());
375 int nComp =
static_cast<int>(PCABands.size());
376 std::vector<T> noDataVals(bandCount);
377 T resultNan = std::nan(
"");
380 T *p_data =
reinterpret_cast<T *
>(VSIMalloc3(bandCount, height * width, size));
381 for (
int b = 0; b < bandCount; b++) {
382 noDataVals[b] =
static_cast<T
>(bands[b].nan);
384 bands[b].p_band->RasterIO(
390 (
void *)((
size_t)p_data + b * size),
395 size * bandCount * width
400 for (
int i = 0; i < height * width; i++) {
401 int bi = i * bandCount;
403 for (
int b = 0; b < bandCount; b++) {
404 T val = p_data[bi + b];
405 p_data[bi + b] = (val == noDataVals[b]) ?
412 T *p_comp =
reinterpret_cast<T *
>(VSIMalloc3(nComp, bandCount, size));
413 for (
int c = 0; c < nComp; c++) {
414 int ci = c * bandCount;
415 for (
int b = 0; b < bandCount; b++) {
429 const auto dataTable =
DALHomogenTable(p_data, height * width, bandCount, [](
const T*){}, oneapi::dal::data_layout::row_major);
430 const auto compTable =
DALHomogenTable(p_comp, nComp, bandCount, [](
const T*){}, oneapi::dal::data_layout::row_major);
433 const auto kernel_desc = oneapi::dal::linear_kernel::descriptor{}.set_scale(1.0).set_shift(0.0);
434 const auto compute_result = oneapi::dal::compute(kernel_desc, dataTable, compTable);
437 const auto values = compute_result.get_values();
438 oneapi::dal::row_accessor<const T> valAcc {values};
439 const T *p_result = valAcc.pull({0, height * width}).get_data();
442 for (
int c = 0; c < nComp; c++) {
443 PCABands[c].p_band->RasterIO(
449 (
void *)((
size_t)p_result + c * size),
502 std::vector<helper::RasterBandMetaData>& bands,
503 std::vector<helper::RasterBandMetaData>& PCABands,
512 int bandCount =
static_cast<int>(bands.size());
513 int nComp =
static_cast<int>(PCABands.size());
514 std::vector<T> noDataVals(bandCount);
515 T resultNan = std::nan(
"");
516 for (
int i = 0; i < bandCount; i++) {
517 noDataVals[i] =
static_cast<T
>(bands[i].nan);
520 T *p_data =
reinterpret_cast<T *
>(VSIMalloc3(xBlockSize * yBlockSize, size, bandCount));
521 T *p_comp =
reinterpret_cast<T *
>(VSIMalloc3(nComp, bandCount, size));
524 const auto dataTable =
DALHomogenTable(p_data, xBlockSize * yBlockSize, bandCount, [](
const T*){}, oneapi::dal::data_layout::row_major);
525 const auto compTable =
DALHomogenTable(p_comp, nComp, bandCount, [](
const T*){}, oneapi::dal::data_layout::row_major);
527 for (
int yBlock = 0; yBlock < yBlocks; yBlock++) {
528 for (
int xBlock = 0; xBlock < xBlocks; xBlock++) {
530 bands[0].p_band->GetActualBlockSize(xBlock, yBlock, &xValid, &yValid);
533 for (
int b = 0; b < bandCount; b++) {
534 bands[b].p_band->RasterIO(
540 (
void *)((
size_t)p_data + b * size),
545 size * bands.size() *
static_cast<size_t>(xBlockSize)
550 for (
int i = 0; i < xBlockSize * yBlockSize; i++) {
551 int bi = i * bandCount;
553 for (
int b = 0; b < bandCount; b++) {
554 T val = p_data[bi + b];
555 p_data[bi + b] = (val == noDataVals[b]) ?
570 const auto kernel_desc = oneapi::dal::linear_kernel::descriptor{}.set_scale(1.0).set_shift(0.0);
571 const auto compute_result = oneapi::dal::compute(kernel_desc, dataTable, compTable);
574 const auto values = compute_result.get_values();
575 oneapi::dal::row_accessor<const T> valAcc {values};
576 const T *p_result = valAcc.pull({0, xBlockSize * yBlockSize}).get_data();
579 for (
int c = 0; c < nComp; c++) {
580 PCABands[c].p_band->RasterIO(
586 (
void *)((
size_t)p_comp + c * size),
591 size * nComp * xBlockSize
652 std::string tempFolder,
653 std::string filename,
654 std::map<std::string, std::string> driverOptions)
662 std::string projection = std::string(p_raster->
getDataset()->GetProjectionRef());
664 bool isMEMDataset = !largeRaster && filename ==
"";
665 bool isVRTDataset = largeRaster && filename ==
"";
666 GDALDataset *p_dataset =
nullptr;
668 std::vector<helper::RasterBandMetaData> bands(bandCount);
669 std::vector<helper::RasterBandMetaData> pcaBands(nComp);
670 std::vector<helper::VRTBandDatasetInfo> VRTBandInfo;
672 int xBlockSize, yBlockSize;
673 p_raster->
getRasterBand(0)->GetBlockSize(&xBlockSize, &yBlockSize);
675 GDALDataType type = GDT_Float32;
676 size_t size =
sizeof(float);
677 for (
int i = 0; i < bandCount; i++) {
679 bands[i].nan = bands[i].p_band->GetNoDataValue();
683 size =
sizeof(double);
690 for (
int i = 0; i < nComp; i++) {
691 pcaBands[i].type = type == GDT_Float64 ? GDT_Float64 : GDT_Float32;
692 pcaBands[i].size = type == GDT_Float64 ?
sizeof(double) :
sizeof(float);
693 pcaBands[i].name =
"comp_" + std::to_string(i + 1);
694 pcaBands[i].nan = std::nan(
"");
698 else if (isVRTDataset){
701 for (
int i = 0; i < nComp; i++) {
702 pcaBands[i].type = type == GDT_Float64 ? GDT_Float64 : GDT_Float32;
703 pcaBands[i].size = type == GDT_Float64 ?
sizeof(double) :
sizeof(float);
704 pcaBands[i].name =
"comp_" + std::to_string(i + 1);
705 pcaBands[i].nan = std::nan(
"");
710 std::filesystem::path filepath = filename;
711 std::string extension = filepath.extension().string();
714 if (extension ==
".tif") {
718 throw std::runtime_error(
"sgs only supports .tif files right now.");
721 bool useTiles = xBlockSize != width &&
722 yBlockSize != height;
724 for (
int i = 0; i < nComp; i++) {
725 pcaBands[i].type = type == GDT_Float64 ? GDT_Float64 : GDT_Float32;
726 pcaBands[i].size = type == GDT_Float64 ?
sizeof(double) :
sizeof(float);
727 pcaBands[i].name =
"comp_" + std::to_string(i + 1);
728 pcaBands[i].nan = std::nan(
"");
731 pcaBands[i].xBlockSize = xBlockSize;
732 pcaBands[i].yBlockSize = yBlockSize;
751 int xBlocks = (width + xBlockSize - 1) / xBlockSize;
752 int yBlocks = (height + yBlockSize - 1) / yBlockSize;
755 std::vector<std::vector<double>> eigenvectors;
756 std::vector<double> eigenvalues;
757 std::vector<double> means;
758 std::vector<double> stdevs;
765 result =
calculatePCA<float>(bands, type, size, xBlockSize, yBlockSize, xBlocks, yBlocks, nComp);
766 writePCA<float>(bands, pcaBands, result, type, size, xBlockSize, yBlockSize, xBlocks, yBlocks);
774 for (
size_t i = 0; i < result.
eigenvectors.size(); i++) {
776 for (
size_t j = 0; j < result.
eigenvectors[i].size(); j++) {
777 eigenvectors[i][j] =
static_cast<double>(result.
eigenvectors[i][j]);
782 for (
size_t i = 0; i < result.
eigenvalues.size(); i++) {
783 eigenvalues[i] =
static_cast<double>(result.
eigenvalues[i]);
786 means = result.
means;
794 result =
calculatePCA<double>(bands, type, size, xBlockSize, yBlockSize, xBlocks, yBlocks, nComp);
795 writePCA<double>(bands, pcaBands, result, type, size, xBlockSize, yBlockSize, xBlocks, yBlocks);
804 means = result.
means;
810 throw std::runtime_error(
"should not be here! GDALDataType should be one of Float32/Float64!");
814 for (
int c = 0; c < nComp; c++) {
815 GDALClose(VRTBandInfo[c].p_dataset);
820 std::vector<void *> buffers(nComp);
822 for (
int c = 0; c < nComp; c++) {
823 buffers[c] = pcaBands[c].p_buffer;
831 return {p_outrast, eigenvectors, eigenvalues, means, stdevs};