All Downloads are FREE. Search and download functionalities are using the official Maven repository.

geotrellis.raster.op.local.Majority.scala Maven / Gradle / Ivy

The newest version!
package geotrellis.raster.op.local

import geotrellis._
import geotrellis.raster._
import geotrellis.source._

import spire.syntax.cfor._
import scala.collection.mutable

object Majority extends Serializable {
  def apply(rs:Op[Raster]*):Op[Raster] =
    apply(0,rs)

  def apply(rs:Seq[Op[Raster]])(implicit d:DI):Op[Raster] =
    apply(0,rs)

  def apply(level:Op[Int],rs:Op[Raster]*):Op[Raster] =
    apply(level,rs)

  def apply(level:Op[Int],rs:Seq[Op[Raster]])(implicit d:DI):Op[Raster] =
    (level,logic.Collect(rs)).map { (level,rs) =>
      if(Set(rs.map(_.rasterExtent)).size != 1) {
        val rasterExtents = rs.map(_.rasterExtent).toSeq
        throw new GeoAttrsError("Cannot combine rasters with different raster extents." +
          s"$rasterExtents are not all equal")
      }

      val layerCount = rs.length
      if(layerCount == 0) {
        sys.error(s"Can't compute majority of empty sequence")
      } else {
        val newRasterType = rs.map(_.rasterType).reduce(_.union(_))
        val re = rs(0).rasterExtent
        val cols = re.cols
        val rows = re.rows
        val data = RasterData.allocByType(newRasterType,cols,rows)

        if(newRasterType.isDouble) {
          val counts = mutable.Map[Double,Int]()

          for(col <- 0 until cols) {
            for(row <- 0 until rows) {
              counts.clear
              for(r <- rs) {
                val v = r.getDouble(col,row)
                if(isData(v)) {
                  if(!counts.contains(v)) {
                    counts(v) = 1
                  } else {
                    counts(v) += 1
                  }
                }
              }

              val sorted =
                counts.keys
                  .toSeq
                  .sortBy { k => counts(k) }
                  .toList
              val len = sorted.length - 1
              val m =
                if(len >= level) { sorted(len-level) }
                else { Double.NaN }
              data.setDouble(col,row, m)
            }
          }
        } else {
          val counts = mutable.Map[Int,Int]()

          for(col <- 0 until cols) {
            for(row <- 0 until rows) {
              counts.clear
              for(r <- rs) {
                val v = r.get(col,row)
                if(isData(v)) {
                  if(!counts.contains(v)) {
                    counts(v) = 1
                  } else {
                    counts(v) += 1
                  }
                }
              }

              val sorted =
                counts.keys
                  .toSeq
                  .sortBy { k => counts(k) }
                  .toList
              val len = sorted.length - 1
              val m =
                if(len >= level) { sorted(len-level) }
                else { NODATA }
              data.set(col,row, m)
            }
          }
        }
        ArrayRaster(data,re)
      }
    }
    .withName("Majority")
}

trait MajorityOpMethods[+Repr <: RasterSource] { self: Repr =>
  /** Assigns to each cell the value within the given rasters that is the most numerous. */
  def localMajority(rss:Seq[RasterSource]):RasterSource = 
    combineOp(rss)(Majority(_))

  /** Assigns to each cell the value within the given rasters that is the most numerous. */
  def localMajority(rss:RasterSource*)(implicit d:DI):RasterSource = 
    localMajority(rss)

  /** Assigns to each cell the value within the given rasters that is the nth most numerous. */
  def localMajority(n:Int,rss:Seq[RasterSource]):RasterSource = 
    combineOp(rss)(Majority(n,_))

  /** Assigns to each cell the value within the given rasters that is the nth most numerous. */
  def localMajority(n:Int,rss:RasterSource*)(implicit d:DI):RasterSource = 
    localMajority(n,rss)
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy