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

geotrellis.engine.RasterSource.scala Maven / Gradle / Ivy

Go to download

GeoTrellis is an open source geographic data processing engine for high performance applications.

There is a newer version: 0.10.3
Show newest version
/*
 * Copyright (c) 2014 Azavea.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package geotrellis.engine

import geotrellis.engine.op._
import geotrellis.engine.io._
import geotrellis.raster._
import geotrellis.raster.resample._
import geotrellis.raster.summary._

import geotrellis.vector.Extent

import akka.actor.ActorRef

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

@deprecated("geotrellis-engine has been deprecated", "Geotrellis Version 0.10")
class RasterSource(val rasterDef: Op[RasterDefinition], val tileOps: Op[Seq[Op[Tile]]])
    extends DataSource[Tile, Tile] {
  type Self = RasterSource

  def elements = tileOps
  val rasterDefinition = rasterDef

  def tiles = elements
  def rasters: Op[Seq[Op[Raster[Tile]]]] =
    (rasterDefinition, tiles).map { (rd, seq) =>
      val tileExtents = rd.tileExtents
      seq.zipWithIndex.map { case (tileOp, tileIndex) =>
        tileOp map { tile => Raster(tile, tileExtents(tileIndex)) }
      }
    }

  def withElements(newElements: Op[Seq[Op[Tile]]]): DataSource[Tile, Tile] =
    RasterSource(rasterDefinition, newElements)

  def convergeOp(): Op[Tile] =
    tiles.flatMap { ts =>
      if(ts.size == 1) { ts(0) }
      else {
        (rasterDefinition, logic.Collect(ts)).map { (rd, tileSeq) =>
          CompositeTile(tileSeq, rd.tileLayout).toArrayTile
        }
      }
    }

  def global[That](f: Tile=>Tile): RasterSource = {
    val tileOps: Op[Seq[Op[Tile]]] =
      (rasterDefinition, logic.Collect(tiles)).map { (rd, tileSeq) =>
        if(rd.isTiled) {
          val r = f(CompositeTile(tileSeq.toSeq, rd.tileLayout))
          r.split(rd.tileLayout).map(Literal(_))
        } else {
          Seq(f(tileSeq(0)))
        }
      }
    RasterSource(rasterDefinition, tileOps)
  }

  def globalOp[T, That](f: Tile=>Op[Tile]): RasterSource = {
    val tileOps: Op[Seq[Op[Tile]]] =
      (rasterDefinition, logic.Collect(tiles)).flatMap { (rd, tileSeq) =>
        if(rd.isTiled) {
          f(CompositeTile(tileSeq.toSeq, rd.tileLayout)).map { r =>
            r.split(rd.tileLayout).map(Literal(_))
          }
        } else {
          Seq(f(tileSeq(0)))
        }
      }
    RasterSource(rasterDefinition, tileOps)
  }

  /** apply a function to elements, and return the appropriate datasource **/
  def mapTile(f: Tile => Tile): RasterSource =
    mapTileOp(Op(f(_)))

  /** apply a function to elements, and return the appropriate datasource **/
  def mapTile(f: Tile => Tile, name: String): RasterSource =
    mapTileOp(Op(f(_)), name)

  /** apply a function to element operations, and return the appropriate datasource **/
  def mapTileOp(f: Op[Tile] => Op[Tile]): RasterSource =
    mapTileOp(f, s"${getClass.getSimpleName} map")

  /** apply a function to element operations, and return the appropriate datasource **/
  def mapTileOp(f: Op[Tile] => Op[Tile], name: String): RasterSource = {
    val newOp = elements.map(_.map(f)).withName(name)
    RasterSource(rasterDefinition, newOp)
  }

  /** apply a function to elements, and return the appropriate datasource **/
  def mapRaster(f: Raster[Tile] => Tile): RasterSource =
    mapRasterOp { op => op.map(f(_)) }

  /** apply a function to elements, and return the appropriate datasource **/
  def mapRaster(f: Raster[Tile] => Tile, name: String): RasterSource =
    mapRasterOp({ op => op.map(f(_)) }, name)

  /** apply a function to element operations, and return the appropriate datasource **/
  def mapRasterOp(f: Op[Raster[Tile]] => Op[Tile]): RasterSource =
    mapRasterOp(f, s"${getClass.getSimpleName} map")

  /** apply a function to element operations, and return the appropriate datasource **/
  def mapRasterOp(f: Op[Raster[Tile]] => Op[Tile], name: String): RasterSource = {
    val newOp = rasters.map(_.map(f)).withName(name)
    RasterSource(rasterDefinition, newOp)
  }

  /** apply a function to elements, and return the appropriate datasource **/
  def mapWithExtent[T](f: (Tile, Extent) => T)(implicit d: DummyImplicit): SeqSource[T] =
    mapWithExtentOp { op => op.map { case (t, e) => f(t, e) } }

  /** apply a function to elements, and return the appropriate datasource **/
  def mapWithExtent[T](f: (Tile, Extent) => T, name: String)(implicit d: DummyImplicit): SeqSource[T] =
    mapWithExtentOp({ op => op.map { case (t, e) => f(t, e) } }, name)

  /** apply a function to element operations, and return the appropriate datasource **/
  def mapWithExtentOp[T](f: Op[(Tile, Extent)] => Op[T])(implicit d: DummyImplicit): SeqSource[T] =
    mapWithExtentOp(f, s"${getClass.getSimpleName} map")

  /** apply a function to element operations, and return the appropriate datasource **/
  def mapWithExtentOp[T](f: Op[(Tile, Extent)] => Op[T], name: String)(implicit d: DummyImplicit): SeqSource[T] = {
    val newOp = rasters.map(_.map { r => r.flatMap { case Raster(t, e) => f(t, e) } }).withName(name)
    SeqSource(newOp)
  }

  def combineTile(rs: RasterSource)(f: (Tile, Tile)=> Tile) =
    combineTileOp(rs)( { (a, b) => (a, b).map(f(_, _)) })

  def combineTile(rs: RasterSource, name: String)(f: (Tile, Tile)=> Tile) =
    combineTileOp(rs, name)( { (a, b) => (a, b).map(f(_, _)) })

  def combineTile(rss: Seq[RasterSource])(f: Seq[Tile] => Tile): RasterSource =
     combineTileOp(rss)(_.mapOps(f(_)))

  def combineTile(rss: Seq[RasterSource], name: String)(f: Seq[Tile] => Tile): RasterSource =
     combineTileOp(rss, name)(_.mapOps(f(_)))

  def combineTileOp(rs: RasterSource)(f: (Op[Tile], Op[Tile])=>Op[Tile]): RasterSource =
    combineTileOp(rs, s"${getClass.getSimpleName} combine")(f)

  def combineTileOp(rs: RasterSource, name: String)(f: (Op[Tile], Op[Tile])=>Op[Tile]): RasterSource = {
    val newElements: Op[Seq[Op[Tile]]] =
      ((elements, rs.elements).map { (e1, e2) =>
        e1.zip(e2).map { case (a, b) =>
          f(a, b)
        }
      }).withName(name)
    RasterSource(rasterDefinition, newElements)
  }

  def combineTileOp(rss: Seq[RasterSource])(f: Seq[Op[Tile]]=>Op[Tile]): RasterSource =
    combineTileOp(rss, s"${getClass.getSimpleName} combine")(f)

  def combineTileOp(rss: Seq[RasterSource], name: String)(f: Seq[Op[Tile]]=>Op[Tile]): RasterSource = {
    val newElements: Op[Seq[Op[Tile]]] =
      (elements +: rss.map(_.elements)).mapOps { seq =>
        seq.transpose.map(f)
      }.withName(name)

    RasterSource(rasterDefinition, newElements)
  }

  def convert(newType: CellType) = {
    val newDef = rasterDefinition.map(_.withType(newType))
    val ops = tiles.map { seq => seq.map { tile => tile.map { r => r.convert(newType) } } }

    RasterSource(newDef, ops)
  }

  def min(): ValueSource[Int] =
    map(_.findMinMax._1)
      .reduce { (m1, m2) =>
        if(isNoData(m1)) m2
        else if(isNoData(m2)) m1
        else math.min(m1, m2)
       }

  def max(): ValueSource[Int] =
    map(_.findMinMax._2)
      .reduce { (m1, m2) =>
        if(isNoData(m1)) m2
        else if(isNoData(m2)) m1
        else math.max(m1, m2)
       }

  def minMax(): ValueSource[(Int, Int)] =
    map(_.findMinMax)
      .reduce { (mm1, mm2) =>
        val (min1, max1) = mm1
        val (min2, max2) = mm2
        (if(isNoData(min1)) min2
         else if(isNoData(min2)) min1
         else math.min(min1, min2),
         if(isNoData(max1)) max2
         else if(isNoData(max2)) max1
         else math.max(max1, max2)
        )
       }

  def info: ValueSource[RasterLayerInfo] =
    ValueSource(
      rasterDefinition
        .flatMap { rd =>
          if(rd.catalogued) {
            LoadRasterLayerInfo(rd.layerId)
          } else {
            RasterLayerInfo.fromDefinition(rd)
          }
        }
    )

  def rasterExtent: ValueSource[RasterExtent] =
    ValueSource(rasterDefinition.map(_.rasterExtent))

  private def resample(targetOp: Op[RasterExtent]): RasterSource = {

    val newDef: Op[RasterDefinition] =
      (rasterDefinition, targetOp).map { (rd, target) =>
        RasterDefinition(
          rd.layerId,
          target,
          TileLayout.singleTile(target.cols, target.rows),
          rd.cellType
        )
      }

    val newOp: Op[Seq[Op[Tile]]] =
      (rasterDefinition, tiles, targetOp).flatMap { (rd, seq, target) =>
        if (rd.isTiled) {
          val re = rd.rasterExtent
          val tileLayout = rd.tileLayout

          val targetExtent = target.extent
          val tileExtents = TileExtents(re.extent, tileLayout)

          val resampled = mutable.ListBuffer[Op[Raster[Tile]]]()
          val tCols = tileLayout.layoutCols
          val tRows = tileLayout.layoutRows
          cfor(0)(_ < tRows, _ + 1) { tRow =>
            cfor(0)(_ < tCols, _ + 1) { tCol =>
              val sourceExtent = tileExtents(tCol, tRow)
              sourceExtent.intersection(targetExtent) match {
                case Some(ext) =>
                  val cols = math.ceil((ext.xmax - ext.xmin) / re.cellwidth).toInt
                  val rows = math.ceil((ext.ymax - ext.ymin) / re.cellheight).toInt
                  val tileRe = RasterExtent(ext, re.cellwidth, re.cellheight, cols, rows)

                  // Read section of the tile
                  resampled += seq(tCols * tRow + tCol).map { r => (r.resample(sourceExtent, tileRe), ext) }
                case None => // pass
              }
            }
          }

          if (resampled.size == 0) {
            Seq(Literal(ArrayTile.empty(rd.cellType, target.cols, target.rows)))
          } else if (resampled.size == 1) {
            Seq(resampled.head.map(_.tile))
          } else {

            // Create destination raster data
            logic.Collect(resampled) map { resampled =>
              val tile = ArrayTile.empty(rd.cellType, target.cols, target.rows)

              for(Raster(rasterPart, extent) <- resampled) {
                // Copy over the values to the correct place in the raster data
                val cols = rasterPart.cols
                val rows = rasterPart.rows
                val tileRe = RasterExtent(extent, cols, rows)

                if (rd.cellType.isFloatingPoint) {
                  cfor(0)(_ < rows, _ + 1) { partRow =>
                    cfor(0)(_ < cols, _ + 1) { partCol =>
                      val tileCol = re.mapXToGrid(tileRe.gridColToMap(partCol))
                      val tileRow = re.mapYToGrid(tileRe.gridRowToMap(partRow))

                      if (!(tileCol < 0 ||
                            tileCol >= re.cols ||
                            tileRow < 0 || tileRow >= re.rows)
                         ) {
                        tile.setDouble(tileCol, tileRow, rasterPart.getDouble(partCol, partRow))
                      }
                    }
                  }
                } else {
                  cfor(0)(_ < rows, _ + 1) { partRow =>
                    cfor(0)(_ < cols, _ + 1) { partCol =>
                      val tileCol = re.mapXToGrid(tileRe.gridColToMap(partCol))
                      val tileRow = re.mapYToGrid(tileRe.gridRowToMap(partRow))
                      if (!(tileCol < 0 ||
                            tileCol >= re.cols ||
                            tileRow < 0 ||
                            tileRow >= re.rows)
                         ) {
                        tile.set(tileCol, tileRow, rasterPart.get(partCol, partRow))
                      }
                    }
                  }
                }
              }
              Seq(Literal(tile))
            }
          }
        } else {
          Seq(seq(0).map(_.resample(rd.rasterExtent.extent, target)))
        }
      }

    RasterSource(newDef, newOp)
  }

  def resample(target: RasterExtent): RasterSource =
    resample(Literal(target))

  def resample(target: Extent): RasterSource =
    resample(rasterDefinition.map(_.rasterExtent.createAlignedRasterExtent(target)))

  def resample(targetCols: Int, targetRows: Int): RasterSource =
    resample(rasterDefinition.map(_.rasterExtent.withDimensions(targetCols, targetRows)))

  def distribute(cluster: Option[ActorRef]) = RasterSource(rasterDefinition, distributeOps(cluster))
  def cached(implicit engine: Engine) = RasterSource(rasterDefinition, cachedOps(engine))

}

@deprecated("geotrellis-engine has been deprecated", "Geotrellis Version 0.10")
object RasterSource {
  def fromPath(path: String): RasterSource =
    fromPath(path, None)

  def fromPath(path: String, rasterExtent: RasterExtent): RasterSource =
    fromPath(path, Some(rasterExtent))

  def fromPath(path: String, targetExtent: Option[RasterExtent]): RasterSource =
    apply(LoadRasterLayerFromPath(path), targetExtent)

  def fromUrl(jsonUrl: String): RasterSource =
    fromUrl(jsonUrl, None)

  def fromUrl(jsonUrl: String, targetExtent: RasterExtent): RasterSource =
    fromUrl(jsonUrl, Some(targetExtent))

  def fromUrl(jsonUrl: String, targetExtent: Option[RasterExtent]): RasterSource =
    apply(LoadRasterLayerFromUrl(jsonUrl), targetExtent)

  def apply(rasterLayer: Op[RasterLayer], targetExtent: Option[RasterExtent])
           (implicit d: DI): RasterSource = {
    val rasterDef =
      rasterLayer map { layer =>
        RasterDefinition(layer.info.id,
                         layer.info.rasterExtent,
                         layer.info.tileLayout,
                         layer.info.cellType)
      }

    val tileOps =
      targetExtent match {
        case re @ Some(_) =>
          rasterLayer.map { layer =>
            Seq(Literal(layer.getRaster(re)))
          }
        case None =>
          rasterLayer.map { layer =>
            (for(tileRow <- 0 until layer.info.tileLayout.layoutRows;
              tileCol <- 0 until layer.info.tileLayout.layoutCols) yield {
              Literal(layer.getTile(tileCol, tileRow))
            })
          }
      }

    RasterSource(rasterDef, tileOps)
  }

  def apply(name: String): RasterSource =
    RasterSource(LoadRasterDefinition(LayerId(name)), None)

  def apply(name: String, rasterExtent: RasterExtent): RasterSource =
    RasterSource(LoadRasterDefinition(LayerId(name)), Some(rasterExtent))

  def apply(store: String, name: String): RasterSource =
    RasterSource(LoadRasterDefinition(LayerId(store, name)), None)

  def apply(store: String, name: String, rasterExtent: RasterExtent): RasterSource =
    RasterSource(LoadRasterDefinition(LayerId(store, name)), Some(rasterExtent))

  def apply(layerId: LayerId): RasterSource =
    RasterSource(LoadRasterDefinition(layerId), None)

  def apply(layerId: LayerId, rasterExtent: RasterExtent): RasterSource =
    RasterSource(LoadRasterDefinition(layerId), Some(rasterExtent))

  def apply(rasterDef: Op[RasterDefinition]): RasterSource =
    apply(rasterDef, None)

  def apply(rasterDef: Op[RasterDefinition], targetExtent: RasterExtent): RasterSource =
    apply(rasterDef, Some(targetExtent))

  def apply(rasterDef: Op[RasterDefinition], targetExtent: Option[RasterExtent]): RasterSource = {
    val (rd, tileOps) =
      targetExtent match {
        case reOp @ Some(re) =>
          ( rasterDef.map(_.withRasterExtent(re)),
            rasterDef.map { rd =>
              Seq(LoadRaster(rd.layerId, reOp))
            }
          )
        case None =>
          ( rasterDef,
            rasterDef.map { rd =>
              (for(tileRow <- 0 until rd.tileLayout.layoutRows;
                tileCol <- 0 until rd.tileLayout.layoutCols) yield {
                LoadTile(rd.layerId, tileCol, tileRow)
              })
            }
          )
      }

    new RasterSource(rd, tileOps)
  }

  def apply(rasterDef: Op[RasterDefinition], tileOps: Op[Seq[Op[Tile]]]) =
    new RasterSource(rasterDef, tileOps)

  /** Create a RasterSource who's tile ops are the tiles of a CompositeTile. */
  def apply(compositeTile: CompositeTile, extent: Extent): RasterSource = {
    val rasterDef =
      RasterDefinition(
        LayerId("LiteralCompositeTile"),
        RasterExtent(extent, compositeTile.cols, compositeTile.rows),
        compositeTile.tileLayout,
        compositeTile.cellType
      )

    val tileOps = compositeTile.tiles.map(Literal(_))

    new RasterSource(rasterDef, tileOps)
  }

  def apply(compositeTile: Op[CompositeTile], extent: Op[Extent])(implicit d: DI): RasterSource = {
    val rasterDef = (compositeTile, extent).map { (tr, ext) =>
      RasterDefinition(
        LayerId("LiteralCompositeTile"),
        RasterExtent(ext, tr.cols, tr.rows),
        tr.tileLayout,
        tr.cellType
      )
    }
    val tileOps = compositeTile.map(_.tiles.map(Literal(_)))
    new RasterSource(rasterDef, tileOps)
  }

  def apply(raster: Op[Tile], extent: Op[Extent])(implicit d: DI, d2: DI): RasterSource = {
    val rasterDef =
      (raster, extent).map { (r, ext) =>
        RasterDefinition(LayerId("LiteralRaster"),
          RasterExtent(ext, r.cols, r.rows),
          TileLayout.singleTile(r.cols, r.rows),
          r.cellType
        )
      }

    val tileOps = Literal(Seq(raster))
    new RasterSource(rasterDef, tileOps)
  }

  def apply(r: Tile, extent: Extent): RasterSource = {
    val rasterDef =
      Literal {
        RasterDefinition(LayerId("LiteralRaster"),
          RasterExtent(extent, r.cols, r.rows),
          TileLayout.singleTile(r.cols, r.rows),
          r.cellType
        )
      }

    val tileOps = Literal(Seq(Literal(r)))
    new RasterSource(rasterDef, tileOps)
  }

  def layerExists(layerId: LayerId): Boolean = engine.layerExists(layerId)
  def layerExists(layerName: String): Boolean = engine.layerExists(layerName)
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy