410 std::vector<helper::RasterBandMetaData>& bands,
423 std::vector<std::vector<T>> probabilities(count);
426 for (
int i = 0; i < count; i++) {
427 probabilities[i].resize(nSamp - 1);
430 for (
int j = 0; j < nSamp - 1; j++) {
431 probabilities[i][j] =
static_cast<T
>(j + 1) /
static_cast<T
>(nSamp);
435 int xBlockSize = bands[0].xBlockSize;
436 int yBlockSize = bands[0].yBlockSize;
438 int xBlocks = (width + xBlockSize - 1) / xBlockSize;
439 int yBlocks = (height + yBlockSize - 1) / yBlockSize;
444 std::vector<T> corrBuffer(count * xBlockSize * yBlockSize);
445 std::vector<std::vector<T>> quantileBuffers(count);
446 for (
int i = 0; i < count; i++) {
447 quantileBuffers[i].resize(xBlockSize * yBlockSize);
451 access.band.p_buffer = VSIMalloc3(xBlockSize, yBlockSize,
access.band.size);
455 const auto cor_desc = oneapi::dal::covariance::descriptor{}.set_result_options(oneapi::dal::covariance::result_options::cor_matrix);
456 oneapi::dal::covariance::partial_compute_result<> partial_result;
459 std::vector<VSLSSTaskPtr> quantileTasks(count);
461 MKL_INT quant_order_n =
quantiles[0].size();
463 MKL_INT n = xBlockSize * yBlockSize;
464 MKL_INT nparams = VSL_SS_SQUANTS_ZW_PARAMS_N;
465 MKL_INT xstorage = VSL_SS_MATRIX_STORAGE_ROWS;
468 if (type == GDT_Float64) {
469 for (
int i = 0; i < count; i++) {
471 status = vsldSSNewTask(
476 reinterpret_cast<double *
>(quantileBuffers[i].data()),
483 for (
int i = 0; i < count; i++) {
485 status = vslsSSNewTask(
490 reinterpret_cast<float *
>(quantileBuffers[i].data()),
497 int8_t *p_access =
reinterpret_cast<int8_t *
>(
access.band.p_buffer);
499 bool calledEditStreamQuantiles =
false;
500 void *p_data =
reinterpret_cast<void *
>(corrBuffer.data());
502 for (
int yBlock = 0; yBlock < yBlocks; yBlock++) {
503 for (
int xBlock = 0; xBlock < xBlocks; xBlock++) {
506 bands[0].p_band->GetActualBlockSize(xBlock, yBlock, &xValid, &yValid);
509 for (
int i = 0; i < count ; i++) {
510 CPLErr err = bands[i].p_band->RasterIO(
516 (
void *)((
size_t)p_data + i * size),
520 size *
static_cast<size_t>(count),
521 size *
static_cast<size_t>(count) *
static_cast<size_t>(xBlockSize)
525 throw std::runtime_error(
"Error reading data from raster band.");
534 rasterBandIO(
access.band,
access.band.p_buffer, xBlockSize, yBlockSize, xBlock, yBlock, xValid, yValid,
true,
false);
539 for (
int y = 0; y < yValid; y++) {
540 int index = y * xBlockSize;
541 for (
int x = 0; x < xValid; x++) {
543 T *p_buff = corrBuffer.data() + (index * count);
544 for (
int b = 0; b < count; b++) {
546 isNan = std::isnan(val) || val == bands[b].nan;
552 quantileBuffers[b][n] = val;
553 corrBuffer[n * count + b] = val;
559 bool accessible = !
access.used || p_access[index] != 1;
561 if (
existing.used &&
existing.containsIndex(x + xBlock * xBlockSize, y + yBlock * yBlockSize)) {
562 clhs.addExistingPoint(
564 xBlock * xBlockSize + x,
565 yBlock * yBlockSize + y
568 else if (accessible && rand.
next()) {
571 xBlock * xBlockSize + x,
572 yBlock * yBlockSize + y
585 if (type == GDT_Float64) {
586 if (!calledEditStreamQuantiles) {
587 for (
int i = 0; i < count; i++) {
589 status = vsldSSEditStreamQuantiles(
592 reinterpret_cast<double *
>(probabilities[i].data()),
593 reinterpret_cast<double *
>(
quantiles[i].data()),
598 calledEditStreamQuantiles =
true;
600 for (
int i = 0; i < count; i++) {
601 status = vsldSSCompute(
603 VSL_SS_STREAM_QUANTS,
604 VSL_SS_METHOD_SQUANTS_ZW_FAST
609 if (!calledEditStreamQuantiles) {
610 for (
int i = 0; i < count; i++) {
612 status = vslsSSEditStreamQuantiles(
615 reinterpret_cast<float *
>(probabilities[i].data()),
616 reinterpret_cast<float *
>(
quantiles[i].data()),
621 calledEditStreamQuantiles =
true;
623 for (
int i = 0; i < count; i++) {
624 status = vslsSSCompute(
626 VSL_SS_STREAM_QUANTS,
627 VSL_SS_METHOD_SQUANTS_ZW_FAST
634 DALHomogenTable table = DALHomogenTable(corrBuffer.data(), n, count, [](
const T *){}, oneapi::dal::data_layout::row_major);
635 partial_result = oneapi::dal::partial_compute(cor_desc, partial_result, table);
640 VSIFree(
access.band.p_buffer);
644 auto result = oneapi::dal::finalize_compute(cor_desc, partial_result);
645 auto correlation = result.get_cor_matrix();
647 oneapi::dal::row_accessor<const T> acc {correlation};
650 std::vector<std::vector<T>> corr(count);
651 for (
int i = 0; i < count; i++) {
652 corr[i].resize(count);
653 auto row = acc.pull({i, i + 1});
655 for (
int j = 0; j < count; j++) {
659 status = (type == GDT_Float64) ?
660 vsldSSCompute(quantileTasks[i], VSL_SS_STREAM_QUANTS, VSL_SS_METHOD_SQUANTS_ZW) :
661 vslsSSCompute(quantileTasks[i], VSL_SS_STREAM_QUANTS, VSL_SS_METHOD_SQUANTS_ZW);
662 status = vslSSDeleteTask(&quantileTasks[i]);
707 xso::xoshiro_4x64_plus& rng,
716 std::vector<double>& xCoords,
717 std::vector<double>& yCoords)
719 std::vector<T> features;
723 std::vector<int> sampleCountPerQuantile(nFeat * nSamp, 0);
724 std::vector<int> quantilesOfEachSample(nSamp * nFeat, 0);
728 clhs.getExistingFeatures(features, x, y);
734 size_t neSamples = x.size();
735 if (neSamples > 0 && replace != 0) {
736 for (
size_t si = 0; si < neSamples; si++) {
737 for (
size_t fi = 0; fi < nFeat; fi++) {
738 T val = features[(si * nFeat) + fi];
740 sampleCountPerQuantile[(fi * nSamp) + q]++;
741 quantilesOfEachSample[(si * nFeat) + fi] = q;
745 while (replace > 0 && neSamples > 0) {
746 size_t worstRedundancy = 0;
747 size_t worstRedundancyIndex = 0;
751 for (
size_t si = 0; si < neSamples; si++) {
752 size_t curSampleRedundancy = 0;
753 for (
size_t fi = 0; fi < nFeat; fi++) {
754 size_t q = quantilesOfEachSample[(si * nFeat) + fi];
755 curSampleRedundancy += sampleCountPerQuantile[(fi * nSamp) + q];
757 if (curSampleRedundancy > worstRedundancy) {
758 worstRedundancy = curSampleRedundancy;
759 worstRedundancyIndex = si;
766 if (worstRedundancy == nFeat) {
772 size_t si = worstRedundancyIndex;
773 for (
size_t fi = 0; fi < nFeat; fi++) {
774 size_t q = quantilesOfEachSample[(si * nFeat) + fi];
775 sampleCountPerQuantile[(fi * nSamp) + q]--;
778 x[si] = x[neSamples - 1];
779 y[si] = y[neSamples - 1];
780 std::memcpy(features.data() + (si * nFeat),
781 features.data() + ((neSamples - 1) * nFeat),
783 std::memcpy(quantilesOfEachSample.data() + (si * nFeat),
784 quantilesOfEachSample.data() + ((neSamples - 1) * nFeat),
785 sizeof(
int) * nFeat);
796 size_t starti = neSamples;
797 boost::unordered::unordered_flat_set<uint64_t> points;
801 for (
size_t si = 0; si < neSamples; si++) {
802 OGRPoint point =
existing.getPoint(x[si], y[si]);
806 xCoords.push_back(point.getX());
807 yCoords.push_back(point.getY());
810 points.insert((((uint64_t) x[si]) << 32) | ((uint64_t) y[si]));
814 if (starti >= nSamp) {
818 std::uniform_real_distribution<T>
dist(0.0, 1.0);
819 std::uniform_int_distribution<size_t> indexDist(starti, nSamp - 1);
821 std::vector<std::vector<T>> corr(nFeat);
822 for (
int i = 0; i < nFeat; i++) {
823 corr[i].resize(nFeat);
826 features.resize(nSamp * nFeat);
834 clhs.getRandomPoint(p);
836 if (points.contains((((uint64_t) p.
x) << 32) | ((uint64_t) p.
y))) {
843 for (
int f = 0; f < nFeat; f++) {
845 features[(i * nFeat) + f] = val;
848 sampleCountPerQuantile[(f * nSamp) + q]++;
849 quantilesOfEachSample[(i * nFeat) + f] = q;
852 points.insert((((uint64_t) p.
x) << 32) | ((uint64_t) p.
y));
857 DALHomogenTable table = DALHomogenTable(features.data(), nSamp, nFeat, [](
const T *){}, oneapi::dal::data_layout::row_major);
858 const auto cor_desc = oneapi::dal::covariance::descriptor{}.set_result_options(oneapi::dal::covariance::result_options::cor_matrix);
859 const auto result = oneapi::dal::compute(cor_desc, table);
860 oneapi::dal::row_accessor<const T> acc {result.get_cor_matrix()};
861 for (
int i = 0; i < nFeat; i++) {
862 auto row = acc.pull({i, i + 1});
864 for (
int j = 0; j < nFeat; j++) {
870 double d = temp /
static_cast<double>(iterations);
873 T objQ =
clhs.quantileObjectiveFunc(sampleCountPerQuantile);
874 T objC =
clhs.correlationObjectiveFunc(corr);
879 std::vector<T> oldf(nFeat);
882 while (temp > 0 && objQ != 0) {
884 if (
dist(rng) < 0.5) {
893 size_t worstRedundancyIndex = 0;
894 size_t worstRedundancy = 0;
895 for (
size_t si = starti; si < nSamp; si++) {
896 size_t curSampleRedundancy = 0;
897 for (
size_t fi = 0; fi < nFeat; fi++) {
898 size_t q = quantilesOfEachSample[(si * nFeat) + fi];
899 curSampleRedundancy += sampleCountPerQuantile[(fi * nSamp) + q];
901 if (curSampleRedundancy > worstRedundancy) {
902 worstRedundancy = curSampleRedundancy;
903 worstRedundancyIndex = si;
906 i = worstRedundancyIndex;
911 std::memcpy(oldf.data(), features.data() + (i * nFeat), nFeat *
sizeof(T));
915 clhs.getRandomPoint(p);
916 while (points.contains((((uint64_t) p.
x) << 32) | ((uint64_t) p.
y))) {
917 clhs.getRandomPoint(p);
921 std::memcpy(features.data() + (i * nFeat), p.
p_features, nFeat *
sizeof(T));
924 std::vector<int> oldq(nFeat);
925 std::vector<int> newq(nFeat);
926 for (
int f = 0; f < nFeat; f++) {
930 sampleCountPerQuantile[(f * nSamp) + q]--;
935 sampleCountPerQuantile[(f * nSamp) + q]++;
939 T newObjQ =
clhs.quantileObjectiveFunc(sampleCountPerQuantile);
942 const auto result = oneapi::dal::compute(cor_desc, table);
943 oneapi::dal::row_accessor<const T> acc {result.get_cor_matrix()};
944 for (
int j = 0; j < nFeat; j++) {
945 auto row = acc.pull({j, j + 1});
947 for (
int k = 0; k < nFeat; k++) {
953 T newObjC =
clhs.correlationObjectiveFunc(corr);
955 T newObj = newObjQ + newObjC;
956 T delta = newObj - obj;
958 bool keep =
dist(rng) < std::exp(-1 * delta / temp);
962 points.erase((((uint64_t) x[i]) << 32) | ((uint64_t) y[i]));
963 points.insert((((uint64_t) p.
x) << 32) | ((uint64_t) p.
y));
968 std::memcpy(quantilesOfEachSample.data() + (i * nFeat), newq.data(),
sizeof(
int) * nFeat);
976 for (
int f = 0; f < nFeat; f++) {
977 sampleCountPerQuantile[(f * nSamp) + newq[f]]--;
978 sampleCountPerQuantile[(f * nSamp) + oldq[f]]++;
982 reinterpret_cast<void *
>(features.data() + (i * nFeat)),
983 reinterpret_cast<void *
>(oldf.data()),
994 for (
int i = starti ; i < nSamp; i++) {
996 OGRPoint point = OGRPoint(xCoord, yCoord);
1002 xCoords.push_back(xCoord);
1003 yCoords.push_back(yCoord);
1043 std::string layerName,
1049 std::string tempFolder,
1050 std::string filename)
1059 std::vector<double> xCoords, yCoords;
1061 std::vector<helper::RasterBandMetaData> bands(p_raster->
getBandCount());
1062 for (
int i = 0; i < nFeat; i++) {
1066 bands[i].nan = bands[i].p_band->GetNoDataValue();
1067 bands[i].p_band->GetBlockSize(&bands[i].xBlockSize, &bands[i].yBlockSize);
1071 GDALDriver *p_driver = GetGDALDriverManager()->GetDriverByName(
"MEM");
1073 throw std::runtime_error(
"unable to create output sample dataset driver.");
1075 GDALDataset *p_samples = p_driver->Create(
"", 0, 0, 0, GDT_Unknown,
nullptr);
1077 throw std::runtime_error(
"unable to create output dataset with driver.");
1081 OGRLayer *p_layer = p_samples->CreateLayer(
"samples", p_wrapper->
getSRS(), wkbPoint,
nullptr);
1083 throw std::runtime_error(
"unable to create output dataset layer.");
1094 bands[0].xBlockSize,
1112 xso::xoshiro_4x64_plus rng;
1126 GDALDataType type = GDT_Float32;
1128 if (band.type == GDT_Float64) {
1134 if (type == GDT_Float64) {
1135 std::vector<std::vector<double>>
quantiles;
1141 readRaster<double>(bands,
clhs,
access,
existing, rand, type,
quantiles,
sizeof(
double), width, height, nFeat, nSamp);
1144 selectSamples<double>(
quantiles,
clhs, rng,
existing, replace, iterations, nSamp, nFeat, p_layer, GT, plot, xCoords, yCoords);
1147 std::vector<std::vector<float>>
quantiles;
1153 readRaster<float>(bands,
clhs,
access,
existing, rand, type,
quantiles,
sizeof(
float), width, height, nFeat, nSamp);
1156 selectSamples<float>(
quantiles,
clhs, rng,
existing, replace, iterations, nSamp, nFeat, p_layer, GT, plot, xCoords, yCoords);
1159 if (filename !=
"") {
1161 p_wrapper->
write(filename);
1163 catch (
const std::exception& e) {
1164 std::cout <<
"Exception thrown trying to write file: " << e.what() << std::endl;
1168 return {{xCoords, yCoords}, p_wrapper};