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

geotrellis.package.scala Maven / Gradle / Ivy

The newest version!
import geotrellis.source.CanBuildSourceFrom
import geotrellis.statistics.Histogram

import language.experimental.macros

package object geotrellis {
  implicit lazy val server = GeoTrellis.server

  // Keep constant values in sync with macro functions
  @inline final val byteNODATA = Byte.MinValue 
  @inline final val shortNODATA = Short.MinValue
  @inline final val NODATA = Int.MinValue

  import geotrellis.Macros._
  def isNoData(b:Byte):Boolean = macro isNoDataByte_impl
  def isNoData(s:Short):Boolean = macro isNoDataShort_impl
  def isNoData(i:Int):Boolean = macro isNoDataInt_impl
  def isNoData(f:Float):Boolean = macro isNoDataFloat_impl
  def isNoData(d:Double):Boolean = macro isNoDataDouble_impl

  def isData(b:Byte):Boolean = macro isDataByte_impl
  def isData(s:Short):Boolean = macro isDataShort_impl
  def isData(i:Int):Boolean = macro isDataInt_impl
  def isData(f:Float):Boolean = macro isDataFloat_impl
  def isData(d:Double):Boolean = macro isDataDouble_impl

  @inline final def b2i(n:Byte):Int = if (isNoData(n)) NODATA else n.toInt
  @inline final def i2b(n:Int):Byte = if (isNoData(n)) byteNODATA else n.toByte

  @inline final def s2i(n:Short):Int = if (isNoData(n)) NODATA else n.toInt
  @inline final def i2s(n:Int):Short = if (isNoData(n)) shortNODATA else n.toShort

  @inline final def i2f(n:Int):Float = if (isNoData(n)) Float.NaN else n.toFloat
  @inline final def f2i(n:Float):Int = if (isNoData(n)) NODATA else n.toInt

  @inline final def i2d(n:Int):Double = if (isNoData(n)) Double.NaN else n.toDouble
  @inline final def d2i(n:Double):Int = if (isNoData(n)) NODATA else n.toInt

  // Use this implicit class to fill arrays ... much faster than Array.fill[Int](dim)(val), etc.
  implicit class ByteArrayFiller(val arr:Array[Byte]) extends AnyVal {
    def fill(v:Byte) = { java.util.Arrays.fill(arr,v) ; arr }
  }
  implicit class ShortArrayFiller(val arr:Array[Short]) extends AnyVal {
    def fill(v:Short) = { java.util.Arrays.fill(arr,v) ; arr }
  }
  implicit class IntArrayFiller(val arr:Array[Int]) extends AnyVal {
    def fill(v:Int) = { java.util.Arrays.fill(arr,v) ; arr }
  }
  implicit class FloatArrayFiller(val arr:Array[Float]) extends AnyVal {
    def fill(v:Float) = { java.util.Arrays.fill(arr,v) ; arr }
  }
  implicit class DoubleArrayFiller(val arr:Array[Double]) extends AnyVal {
    def fill(v:Double) = { java.util.Arrays.fill(arr,v) ; arr }
  }


  type Op[+A] = Operation[A]
  type DI = DummyImplicit

  type RasterData = geotrellis.raster.RasterData

  type Png = Array[Byte]

  /**
   * Add simple syntax for creating an operation.
   *
   * Define a function after op function that returns:
   *
   * 1) A literal value, e.g.
   *   val plusOne = op { (i:Int) => i + 1 }
   *
   * 2) An operation to be executed:
   *   val localPlusOne = ( (r:Raster, i:Int) => local.Add(r,i + 1) )
   *
   * 3) Or a StepResult (which indicates success or failure)
   *   val plusOne = op { (i:Int) => Result(i + 1) }
   *
   */

  def op[T](value: => T): Operation[T] =
    new Op0(() => Result(value))

  // Op1 methods for op //

  /**
   * Create an operation from a 1-arg function that returns StepOutput.
   *
   * For example:
   *
   * val plusOne = op { (i:Int) => Result(i + 1) }
   */
  def op[A, T](f: (A) => StepOutput[T]): (Op[A]) => Op1[A, T] =
    (a: Op[A]) => new Op1(a)((a) => f(a))

  /**
   * Create an operation from a 1-arg function that returns an operation to be executed.
   *
   * For example:
   *
   * val localPlusOne = ( (r:Raster, i:Int) => local.Add(r,i + 1) )
   *
   */
  def op[A, T](f: (A) => Op[T])(implicit n: DI): (Op[A]) => Op1[A, T] =
    (a: Op[A]) => new Op1(a)((a) => StepRequiresAsync(List(f(a)), (l) => Result(l.head.asInstanceOf[T])))

  /**
   * Create an operation from a 1-arg function that returns a literal value.
   *
   * For example:
   *
   * val plusOne = op { (i:Int) => i + 1 }
   */
  def op[A, T](f: (A) => T)(implicit n: DI, o: DI): (Op[A]) => Op1[A, T] =
    (a: Op[A]) => new Op1(a)((a) => Result(f(a)))

  // Op2 methods for op() //

  /**
   * Create an operation from a 2-arg function that returns StepOutput.
   */
  def op[A, B, T](f: (A, B) => StepOutput[T]): (Op[A], Op[B]) => Op2[A, B, T] =
    (a: Op[A], b: Op[B]) => new Op2(a, b)((a, b) => f(a, b))

  /**
   * Create an operation from a 2-arg function that returns an operation.
   */
  def op[A, B, T](f: (A, B) => Op[T])(implicit n: DI): (Op[A], Op[B]) => Op2[A, B, T] =
    (a: Op[A], b: Op[B]) => new Op2(a, b)((a, b) => StepRequiresAsync(List(f(a, b)), (l) =>
      Result(l.head.asInstanceOf[T])))

  /**
   * Create an operation from a 2-arg function that returns a literal value.
   */
  def op[A, B, T](f: (A, B) => T)(implicit n: DI, o: DI): (Op[A], Op[B]) => Op2[A, B, T] =
    (a: Op[A], b: Op[B]) => new Op2(a, b)((a, b) => Result(f(a, b)))

  // Op3 methods for op() //

  /**
   * Create an operation from a 3-arg function that returns StepOutput.
   */
  def op[A, B, C, T](f: (A, B, C) => StepOutput[T]): (Op[A], Op[B], Op[C]) => Op3[A, B, C, T] =
    (a: Op[A], b: Op[B], c: Op[C]) => new Op3(a, b, c)((a, b, c) => f(a, b, c))

  /**
   * Create an operation from a 3-arg function that returns an operation.
   */
  def op[A, B, C, T](f: (A, B, C) => Op[T])(implicit  n: DI): (Op[A], Op[B], Op[C]) => Op3[A, B, C, T] =
    (a: Op[A], b: Op[B], c: Op[C]) =>
      new Op3(a, b, c)((a, b, c) => StepRequiresAsync(List(f(a, b, c)), (l) => Result(l.head.asInstanceOf[T])))

  /**
   * Create an operation from a 3-arg function that returns a literal value.
   */
  def op[A, B, C, T](f: (A, B, C) => T)(implicit n: DI, o: DI): (Op[A], Op[B], Op[C]) => Op3[A, B, C, T] =
    (a: Op[A], b: Op[B], c: Op[C]) => new Op3(a, b, c)((a, b, c) => Result(f(a, b, c)))

  // Op4 methods for op() //

  /**
   * Create an operation from a 4-arg function that returns StepOutput.
   */
  def op[A, B, C, D, T](f: (A, B, C, D) => StepOutput[T]): 
	  (Op[A], Op[B], Op[C], Op[D]) => Op4[A, B, C, D, T] =
    (a: Op[A], b: Op[B], c: Op[C], d: Op[D]) => new Op4(a, b, c, d)((a, b, c, d) => f(a, b, c, d))

  /**
   * Create an operation from a 4-arg function that returns an operation.
   */
  def op[A, B, C, D, T](f: (A, B, C, D) => Op[T])(implicit n: DI): 
	  (Op[A], Op[B], Op[C], Op[D]) => Op4[A, B, C, D, T] =
    (a: Op[A], b: Op[B], c: Op[C], d: Op[D]) => new Op4(a, b, c, d)((a, b, c, d) => 
      StepRequiresAsync(List(f(a, b, c, d)), (l) => Result(l.head.asInstanceOf[T])))
  
  /**
   * Create an operation from a 4-arg function that returns a literal value.
   */
  def op[A, B, C, D, T](f: (A, B, C, D) => T)(implicit n: DI, o: DI): 
	  (Op[A], Op[B], Op[C], Op[D]) => Op4[A, B, C, D, T] =
    (a: Op[A], b: Op[B], c: Op[C], d: Op[D]) => new Op4(a, b, c, d)((a, b, c, d) => 
      Result(f(a, b, c, d)))

  /**
   * Execute operation with temporary server instance.
   */
  def execute[T:Manifest](op:Operation[T]) = {
    val s = process.Server.empty("execute")
    val result = s.run(op)
    s.shutdown()
    result 
  }

  /**
   * Syntax for converting tuples of operations
   * into objects that you can call map and flatMap on.
   * this is similiar to a for comprehension, but the
   * operations will be executed in parallel.
   */
  implicit class OpMap2[A,B](t:(Op[A],Op[B])) {
    def map[T](f:(A,B)=>T) = op(f).apply(t._1,t._2)
    def flatMap[T](f:(A,B)=>Op[T]) = op(f).apply(t._1,t._2)
  }

  implicit class OpMap3[A,B,C](t:(Op[A],Op[B],Op[C])) {
    def map[T](f:(A,B,C)=>T) = op(f).apply(t._1,t._2,t._3)
    def flatMap[T](f:(A,B,C)=>Op[T]) = op(f).apply(t._1,t._2,t._3)
  }

  implicit class OpMap4[A,B,C,D](t:(Op[A],Op[B],Op[C],Op[D])) {
    def map[T](f:(A,B,C,D)=>T) = op(f).apply(t._1,t._2,t._3,t._4)
    def flatMap[T](f:(A,B,C,D)=>Op[T]) = op(f).apply(t._1,t._2,t._3,t._4)
  }

  /** 
   * Syntax for converting an iterable collection to 
   * have methods to work with the results of those 
   * operations executed in parallel
   */
  implicit class OpMapSeq[A](seq:Seq[Op[A]]) {
    def mapOps[T](f:(Seq[A]=>T)) = logic.Collect(Literal(seq)).map(f)
    def flaMapOps[T](f:(Seq[A]=>Op[T])) = logic.Collect(Literal(seq)).flatMap(f)
  }

  implicit class OpMapArray[A](seq:Array[Op[A]]) {
    def mapOps[T](f:(Seq[A]=>T)) = logic.Collect(Literal(seq.toSeq)).map(f)
    def flaMapOps[T](f:(Seq[A]=>Op[T])) = logic.Collect(Literal(seq.toSeq)).flatMap(f)
  }

  implicit class OpSeqToCollect[T](seq:Op[Seq[Op[T]]]) {
    def collect() = logic.Collect(seq)
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy