{"id":19568880,"url":"https://github.com/geotrellis/geotrellis-server","last_synced_at":"2025-10-11T12:35:31.622Z","repository":{"id":27639517,"uuid":"111709646","full_name":"geotrellis/geotrellis-server","owner":"geotrellis","description":"Tools for building raster processing and display services","archived":false,"fork":false,"pushed_at":"2024-05-14T12:39:46.000Z","size":2638,"stargazers_count":74,"open_issues_count":28,"forks_count":24,"subscribers_count":9,"default_branch":"main","last_synced_at":"2025-05-14T11:51:01.757Z","etag":null,"topics":["geotrellis","geotrellis-server","maml","map-algebra","ogc","tms","wcs","wms","wmts"],"latest_commit_sha":null,"homepage":"","language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/geotrellis.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2017-11-22T16:47:51.000Z","updated_at":"2024-12-13T02:36:53.000Z","dependencies_parsed_at":"2024-01-11T20:43:01.255Z","dependency_job_id":"e86cb888-ae4c-4e9b-98af-edb85605d9da","html_url":"https://github.com/geotrellis/geotrellis-server","commit_stats":null,"previous_names":[],"tags_count":42,"template":false,"template_full_name":null,"purl":"pkg:github/geotrellis/geotrellis-server","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geotrellis%2Fgeotrellis-server","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geotrellis%2Fgeotrellis-server/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geotrellis%2Fgeotrellis-server/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geotrellis%2Fgeotrellis-server/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/geotrellis","download_url":"https://codeload.github.com/geotrellis/geotrellis-server/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geotrellis%2Fgeotrellis-server/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":269669229,"owners_count":24456624,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-10T02:00:08.965Z","response_time":71,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["geotrellis","geotrellis-server","maml","map-algebra","ogc","tms","wcs","wms","wmts"],"created_at":"2024-11-11T06:06:44.605Z","updated_at":"2025-10-11T12:35:26.572Z","avatar_url":"https://github.com/geotrellis.png","language":"Scala","funding_links":[],"categories":["Web Map Server"],"sub_categories":[],"readme":"# GeoTrellis Server \n\n[![CI](https://github.com/geotrellis/geotrellis-server/actions/workflows/ci.yml/badge.svg)](https://github.com/geotrellis/geotrellis-server/actions/workflows/ci.yml) [![Maven Central](https://img.shields.io/maven-central/v/com.azavea.geotrellis/geotrellis-server-core_2.12)](http://search.maven.org/#search%7Cga%7C1%7com.azavea.geotrellis) [![Snapshots](https://img.shields.io/nexus/s/https/oss.sonatype.org/com.azavea.geotrellis/geotrellis-server-core_2.12.svg)](https://oss.sonatype.org/content/repositories/snapshots/com/azavea/geotrellis/geotrellis-server-core_2.12/)\n\n\nGeoTrellis Server is a set of components designed to simplify\nviewing, processing, and serving raster data from arbitrary sources\nwith an emphasis on doing so in a functional style. It aims to ease\nthe pains related to constructing complex raster processing workflows\nwhich result in TMS-based (z, x, y) and extent-based products.\n\nIn addition to providing a story about how sources of imagery can be displayed\nor returned, this project aims to simplify the creation of dynamic,\nresponsive layers whose transformations can be described in MAML\n([Map Algebra Modeling Language](https://github.com/geotrellis/maml/)).\n\n### Getting Started with GeoTrellis Server\n\nGeoTrellis Server is currently available for Scala 2.13 and 2.12.\n\nTo get started with SBT, simply add the following to your build.sbt file:\n\n```scala\nlibraryDependencies += \"com.azavea.geotrellis\" %% \"geotrellis-server-core\" % \"\u003clatest version\u003e\"\n```\n\n### High level concepts\n\nImagine you've got a simple case class which is sufficient to identify\nlayers of imagery for an application you're working on. \n\n```scala\nimport java.net.URI\n\ncase class ImageryLayer(location: URI)\n```\n\nImagine further that you'd like to enable your application to compose these\nlayers together via map algebra to produce derived layers and that the\ncombinations can't be known at compile-time (users will be deciding\nwhich - if any - map algebra to run). This is a job that GeoTrellis\nserver can radically simplify. Because we're dealing with behavior\nspecified at runtime, we need to evaluate program descriptions rather\nthan simple, first-order parameters - the task for which\n[MAML](https://github.com/geotrellis/maml/) was written.\n\n```scala\n// This node describes a `LocalAdd` on the values eventually\n// bound to `RasterVar(\"test1\")` and `RasterVar(\"test2\")\nval simpleAdd = Addition(List(RasterVar(\"test1\"), RasterVar(\"test2\")))\n\n// This describes incrementing every value in the eventually bound raster by 1\nval plusOne = Addition(List(RasterVar(\"additionRaster1\"), IntLit(1)))\n```\n\nBecause MAML encodes map alagebra transformations in data, actually\nexecuting a MAML program for practical purposes can be difficult and\nunintuitive. GeoTrellis server bridges this gap by providing a\ntypeclass-based means of extending source types in client applications\nwith the behaviors necessary to actually evaluate a MAML AST.\n\nThe following example demonstrates what is required to generate\nfunctions which produce extents provided MAML program descriptions. For\na more complete example, check out\n[CogNode](example/src/main/scala/geotrellis/server/example/cog/CogNode.scala).\n```scala\nimport io.circe._\nimport io.circe.syntax._\nimport io.circe.generic.semiauto._\nimport cats._\nimport cats.effect._\nimport com.azavea.maml.ast._\nimport com.azavea.maml.eval.BufferingInterpreter\nimport geotrellis.server._\n\n// This class points to a COG and specifies a band of interest\ncase class RasterRef(uri: URI, band: Int)\n\n// We need to provide some implicit evidence. Most applications can do this within companion objects\nobject RasterRef {\n  // reification means 'thingification', and that's what we're proving we can do here\n  implicit val rasterRefExtentReification: ExtentReification[RasterRef] = new ExtentReification[RasterRef] {\n    def extentReification(self: CogNode, buffer: Int)(implicit contextShift: ContextShift[IO]): (Extent, CellSize) =\u003e IO[Literal] = ???\n  }\n  // We can lean on circe's automatic derivation to provide an encoder\n  implicit val rasterRefEncoding: Encoder[RasterRef] = deriveEncoder[RasterRef]\n}\n\n// A source from which MAML evaluation will be able to derive necessary artifacts\nval reference = RasterRef(\"http://some.url.com\", 1)\n\n// We need to key provided references based on the ID of the Var they'll replace\nval parameters = Map(\"additionRaster1\" -\u003e reference)\n\n// This is an interpeter GT Server will use to roll up the tree + params to some result\nval interpreter = BufferingInterpreter.DEFAULT\n\n// Not yet a result: we can use the result here to produce artifacts for different extent inputs\nval tileEval = LayerExtent.apply(IO.pure(plusOne), IO.pure(parameters), interpreter)\n\nval targetExtent: Extent = ??? // Where should the tile come from?\nval targetCellSize: CellSize = ??? // What resolution should the tile be?\n\n// Branch on Valid/Invalid and print some info about which branch we're on\ntileEval(targetExtent, targetCellSize) map {\n  case Valid(tile) =\u003e\n    println(\"we did it, a tile: (rows: ${tile.rows}, cols: ${tile.cols})\")\n  case Invalid(err) =\u003e\n    println(\"Ran into an error (${err.asJson}) during MAML evaluation of AST (${plusOne.asJson}) with params (${params.asJson})\")\n}\n```\n\n`LayerExtent` is joined by two other objects which organize evaluation\nstrategies for different products:\n\n- `LayerExtent`: Constructs functions that produce a `cats.data.Validated` instance\ncontaining a `Tile` (given an extent) or else `MamlError`s. Requires\n`ExtentReification` and `Encoder` evidence\n\n- `LayerTms`: Constructs functions that produce a `cats.data.Validated` instance\ncontaining a `Tile` (given the tms Z, X, Y coordinates) or else\n`MamlError`s. Requires `TmsReification` and `Encoder` evidence\n\n- `LayerHistogram`: Constructs functions that produce a `cats.data.Validated` instance\ncontaining a `Histogram` or else `MamlError`s. Requires\n`ExtentReification`, `Encoder`, and `HasRasterExtents` evidence\n\nEach of these objects is a response to distinct needs encountered when\nwriting raster-based applications. Included in each object are methods\nwhich encode several strategies for evaluating their products. The strategies\ncurrently available are:\n- `apply`: Takes parameters, a MAML AST, and a MAML `Interpreter` and evaluates accordingly\n\n- `generateExpression`: parameters, a function which will generate an AST based on the\nparameters, and a MAML `Interpreter`\n\n- `curried`: Takes an AST and a MAML `Interpreter` (this method produces an\nintermediate, curried, function which expects a parameter map to\nevaluate)\n\n- `identity`: Evaluates a proven source without any MAML evaluation (useful for\nquickly defining a static layer viewer or debugging implicit evidence behavior\n\n\n### Running an example\n\nThree example servers are available which can be run through the provided\nmakefile. These examples have been implemented via [http4s](https://http4s.org/),\nwhich has a pleasant, clean API and plays nicely with the\n[cats](https://typelevel.org/cats/) and [cats-effect](https://typelevel.org/cats-effect/)\nlibraries.\n\n1. A server and simple UI that evaluates weighted overlays between\narbitrary COGs. This demo includes a simple UI, available at http://localhost:9000/ for a\n```bash\n./scripts/server --overlay\n```\n\n2. Integrates GTServer components with application-specific persistence needs.\n```bash\n./scripts/server --persistence\n```\n\n3. Illustrates GTServer evaluating a remote-sensing classic, the NDVI.\n```bash\n./scripts/server --ndvi\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeotrellis%2Fgeotrellis-server","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgeotrellis%2Fgeotrellis-server","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeotrellis%2Fgeotrellis-server/lists"}