jiayuasu commented on code in PR #1124:
URL: https://github.com/apache/sedona/pull/1124#discussion_r1401408332
##########
common/src/main/java/org/apache/sedona/common/raster/RasterBandAccessors.java:
##########
@@ -81,6 +88,190 @@ public static long getCount(GridCoverage2D raster, int
band) {
// return getCount(raster, 1, excludeNoDataValue);
// }
+ /**
+ * @param raster Raster to use for computing stats
+ * @param roi Geometry to define the region of interest
+ * @param band Band to be used for computation
+ * @param excludeNoData Specifies whether to exclude no-data value or not
+ * @return An array with all the stats for the region
+ * @throws FactoryException
+ */
+ public static double[] getZonalStatsAll(GridCoverage2D raster, Geometry
roi, int band, boolean excludeNoData) throws FactoryException {
+ List<Object> objects = getStatObjects(raster, roi, band,
excludeNoData);
+ DescriptiveStatistics stats = (DescriptiveStatistics) objects.get(0);
+ double[] pixelData = (double[]) objects.get(1);
+
+ // order of stats
+ // count, sum, mean, median, mode, stddev, variance, min, max
+ double[] result = new double[9];
+ result[0] = stats.getN();
+ result[1] = stats.getSum();
+ result[2] = stats.getMean();
+ result[3] = stats.getPercentile(50);
+ result[4] = zonalMode(pixelData);
+ result[5] = stats.getStandardDeviation();
+ result[6] = stats.getVariance();
+ result[7] = stats.getMin();
+ result[8] = stats.getMax();
+
+ return result;
+ }
+
+ /**
+ * @param raster Raster to use for computing stats
+ * @param roi Geometry to define the region of interest
+ * @param band Band to be used for computation
+ * @return An array with all the stats for the region, excludeNoData is
set to true
+ * @throws FactoryException
+ */
+ public static double[] getZonalStatsAll(GridCoverage2D raster, Geometry
roi, int band) throws FactoryException {
+ return getZonalStatsAll(raster, roi, band, true);
+ }
+
+ /**
+ * @param raster Raster to use for computing stats
+ * @param roi Geometry to define the region of interest
+ * @return An array with all the stats for the region, excludeNoData is
set to true and band is set to 1
+ * @throws FactoryException
+ */
+ public static double[] getZonalStatsAll(GridCoverage2D raster, Geometry
roi) throws FactoryException {
+ return getZonalStatsAll(raster, roi, 1, true);
+ }
+
+ /**
+ * @param raster Raster to use for computing stats
+ * @param roi Geometry to define the region of interest
+ * @param band Band to be used for computation
+ * @param statType Define the statistic to be computed
+ * @param excludeNoData Specifies whether to exclude no-data value or not
+ * @return A double precision floating point number representing the
requested statistic calculated over the specified region.
+ * @throws FactoryException
+ */
+ public static double getZonalStats(GridCoverage2D raster, Geometry roi,
int band, String statType, boolean excludeNoData) throws FactoryException {
+
+ List<Object> objects = getStatObjects(raster, roi, band,
excludeNoData);
+ DescriptiveStatistics stats = (DescriptiveStatistics) objects.get(0);
+ double[] pixelData = (double[]) objects.get(1);
+
+ switch (statType.toLowerCase()) {
+ case "sum":
+ return stats.getSum();
+ case "average":
+ case "avg":
+ case "mean":
+ return stats.getMean();
+ case "count":
+ return stats.getN();
+ case "max":
+ return stats.getMax();
+ case "min":
+ return stats.getMin();
+ case "stddev":
+ case "sd":
+ return stats.getStandardDeviation();
+ case "median":
+ return stats.getPercentile(50);
+ case "mode":
+ return zonalMode(pixelData);
+ case "variance":
+ return stats.getVariance();
+ default:
+ throw new IllegalArgumentException("Please select from the
accepted options. Some of the valid options are sum, mean, stddev, etc.");
+ }
+ }
+
+ /**
+ * @param raster Raster to use for computing stats
+ * @param roi Geometry to define the region of interest
+ * @param band Band to be used for computation
+ * @param statType Define the statistic to be computed
+ * @return A double precision floating point number representing the
requested statistic calculated over the specified region. The excludeNoData is
set to true.
+ * @throws FactoryException
+ */
+ public static double getZonalStats(GridCoverage2D raster, Geometry roi,
int band, String statType) throws FactoryException {
+ return getZonalStats(raster, roi, band, statType, true);
+ }
+
+ /**
+ * @param raster Raster to use for computing stats
+ * @param roi Geometry to define the region of interest
+ * @param statType Define the statistic to be computed
+ * @return A double precision floating point number representing the
requested statistic calculated over the specified region. The excludeNoData is
set to true and band is set to 1.
+ * @throws FactoryException
+ */
+ public static double getZonalStats(GridCoverage2D raster, Geometry roi,
String statType) throws FactoryException {
+ return getZonalStats(raster, roi, 1, statType, true);
+ }
+
+ /**
+ * @param pixelData An array of double with pixel values
+ * @return Mode of the pixel values. If there is multiple with same
occurrence, then the largest value will be returned.
+ */
+ private static double zonalMode(double[] pixelData) {
+ double[] modes = StatUtils.mode(pixelData);
+ return modes[modes.length - 1];
+ }
+
+ /**
+ * An intermediate function to compute zonal statistics
+ * @param raster Raster to use for computing stats
+ * @param roi Geometry to define the region of interest
+ * @param band Band to be used for computation
+ * @param excludeNoData Specifies whether to exclude no-data value or not
+ * @return an object of DescriptiveStatistics and an array of double with
pixel data.
+ * @throws FactoryException
+ */
+ private static List<Object> getStatObjects(GridCoverage2D raster, Geometry
roi, int band, boolean excludeNoData) throws FactoryException {
+ RasterUtils.ensureBand(raster, band);
+
+ if(RasterAccessors.srid(raster) != roi.getSRID()) {
+ // implicitly converting roi geometry CRS to raster CRS
+ roi = RasterUtils.convertCRSIfNeeded(roi,
raster.getCoordinateReferenceSystem());
+ // have to set the SRID as RasterUtils.convertCRSIfNeeded doesn't
set it even though the geometry is in raster's CRS
+ roi = Functions.setSRID(roi, RasterAccessors.srid(raster));
+ }
+
+ // checking if the raster contains the geometry
+ if (!RasterPredicates.rsIntersects(raster, roi)) {
+ throw new IllegalArgumentException("The provided geometry is not
intersecting the raster. Please provide a geometry that is in the raster's
extent.");
+ }
+
+ Raster rasterData = RasterUtils.getRaster(raster.getRenderedImage());
+ String datatype = RasterBandAccessors.getBandType(raster, band);
+ Double noDataValue = RasterBandAccessors.getBandNoDataValue(raster,
band);
+ // Adding an arbitrary value '150' for the pixels that are under the
geometry.
+ GridCoverage2D rasterizedGeom =
RasterConstructors.asRasterWithRasterExtent(roi, raster, datatype, 150, null);
Review Comment:
@furqaankhan Will it collide with existing values in a raster? If not, we
are good.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]