{"id":19881457,"url":"https://github.com/giscience/measures-rest","last_synced_at":"2025-10-10T13:38:56.073Z","repository":{"id":149844465,"uuid":"123655229","full_name":"GIScience/measures-rest","owner":"GIScience","description":"A REST server to provide measures for geospatial datasets","archived":false,"fork":false,"pushed_at":"2022-08-16T08:07:05.000Z","size":74,"stargazers_count":10,"open_issues_count":2,"forks_count":0,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-05-02T14:36:03.724Z","etag":null,"topics":["data","dggs","geospatial","measure","rest"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/GIScience.png","metadata":{"files":{"readme":"README.md","changelog":null,"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}},"created_at":"2018-03-03T03:23:47.000Z","updated_at":"2024-01-03T16:37:41.000Z","dependencies_parsed_at":"2023-09-25T01:52:05.136Z","dependency_job_id":null,"html_url":"https://github.com/GIScience/measures-rest","commit_stats":{"total_commits":66,"total_committers":3,"mean_commits":22.0,"dds":"0.045454545454545414","last_synced_commit":"a75d007c9842d3ebfc3a71b5065836eae297f09b"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/GIScience/measures-rest","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GIScience%2Fmeasures-rest","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GIScience%2Fmeasures-rest/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GIScience%2Fmeasures-rest/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GIScience%2Fmeasures-rest/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/GIScience","download_url":"https://codeload.github.com/GIScience/measures-rest/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GIScience%2Fmeasures-rest/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279004065,"owners_count":26083667,"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-10-10T02:00:06.843Z","response_time":62,"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":["data","dggs","geospatial","measure","rest"],"created_at":"2024-11-12T17:14:19.710Z","updated_at":"2025-10-10T13:38:56.038Z","avatar_url":"https://github.com/GIScience.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![status: archive](https://github.com/GIScience/badges/raw/master/status/archive.svg)](https://github.com/GIScience/badges#archive)\n\n# Measures REST\n\nThe framework `Measures REST` provides a REST server for measures.  In the context of this software, a measure is regarded as being a distribution of values on Earth, aggregated by some Discrete Global Grid System (DGGS).  Measures refer to properties of the data, or to how a dataset has been created.  Typical examples of measures are data quality measures or measures of the fitness for purpose.\n\n## Overview\n\nThe framework provided by this repository is a framework only: if measures are provided, the resulting data can be cached and then be accessed by a REST interface.  The measures themselves rely on external data sources, which are independent of this framework.  Measures have, accordingly, to be written on an individual basis, referring to external data sources.  Whenever someone requests a measure via the REST interface, the REST server evaluates the corresponding measure and caches the data.\n\n![Overview](https://github.com/giscience/measures-rest/blob/master/docs/images/overview.svg)\n\n## Scientific Publications\n\nThe following publication is related to this framework and the used DGGS:\n\n* F-B Mocnik: **Linked Open Data Vocabularies for Semantically Annotated Repositories of Data Quality Measures** Proceedings of the 10th International Conference on Geographic Information Science (GIScience), 2018\n\n* F-B Mocnik, A Mobasheri, L Griesbaum, M Eckle, C Jacobs, and C Klonner: [**A grounding-based ontology of data quality measures**](http://josis.org/index.php/josis/article/viewFile/360/197) Journal of Spatial Information Science, 16, 2018\n\n* F-B Mocnik: [**A Novel Identifier Scheme for the ISEA Aperture 3 Hexagon Discrete Global Grid System.**](http://doi.org/10.1080/15230406.2018.1455157) Cartography and Geographic Information Science 46(3), 2019, 227–291\n\n## Related Software\n\nSeveral extensions will be published, which allow to implement measures for specific data sources.  They will be announced soon.\n\nThere exist different extensions that aid in implementing a measure for specific data sources:\n\n* [**Measure Rest OSHDB.**](https://github.com/giscience/measures-rest-oshdb) This extension aids in implementing measures that consume data from the [OpenStreetMap History Database (OSHDB)](https://github.com/giscience/oshdb).\n\nIn addition, the REST interface is compatible with the JavaScript library [**geogrid.js**](https://github.com/mocnik-science/geogrid.js), which visualizes measures as a layer to [Leaflet](http://leafletjs.com).  This framework makes extensive use of the library [**geogrid**](https://github.com/mocnik-science/geogrid) that computes and handles Discrete Global Grid Systems (DGGS).\n\n## Implementing a Measure\n\nMeasures always extend the class `Measure\u003cR\u003e`, where `R` is a generic parameter that refers to the result of the measure.  As an example, a measure returning a `Double` value always extends `Measure\u003cDouble\u003e`.  A typical implementation of a measure looks like follows:\n\n```java\npublic class MeasureExample extends Measure\u003cR\u003e {\n    @Override\n    protected SortedMap\u003cGridCell, R\u003e compute(BoundingBox bbox, ZonedDateTime date, ZonedDateTime dateFrom, Integer intervalInDays, RequestParameter p) throws Exception {\n        // implement the measure here\n    }\n}\n```\n\nObserve that the class name of the measure (`MeasureExample`) will automatically be used to identify the measure.  Among others, the name is used to identify the particular measure in the REST interface.  The name is automatically reformatted to `example` in our case.  (The prefix `Measure` is removed and following words are converted from camel-case to [kebab-case notation](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles).)  The above code needs usually just to be copied and can, apart from an adaption of the class name and the method `compute`, stay unmodified.\n\nThe method `compute` needs to be overwritten by an implementation of the actual measure.  The bounding box for which data should be aggregated is provided as parameter `bbox`; the date to compute the measure for, as parameter `date`; and, in case that the measure refers to a time span, the start of the timespan, as parameter `dateFrom`.  Furthermore, the computation can refer to additional parameters.  The parameter `\"key\"` can be accessed by `p.get(\"key\").toString()` in case of a string parameter, `p.get(\"key\").toInteger()` in case of an integer parameter, and `p.get(\"key\").toDouble()` in case of a double parameter.  The default value of a parameter can be overwritten by `p.setDefault(\"key\", \"default value\")`.\n\nThe result is a `SortedMap` with `GridCell` as keys and `R` as values.  Here, `GridCell` refers to the corresponding class of the library [geogrid](https://github.com/mocnik-science/geogrid), which represents a grid cell.  The aggregation has to be implemented manually though it can use the functions provided by geogrid.  In particular, the `GridCell` for a tuple of coordinates can be computed as\n```java\nthis._grid.cellForLocation(lat, lon);\n```\n\n## Running the REST Server\n\n### Initializing and running the server\n\nThe REST server can easily be instantiated as\n\n```java\nRestServer restServer = new RestServer();\n```\n\nIn this case, the server provides a REST interface on port 8080 for the URL `http://localhost`.  In case another port or another URL should be used, corresponding parameters can be provided:\n\n```java\nRestServer restServer = new RestServer(8080);\nRestServer restServer = new RestServer(\"http://localhost:8080\");\n```\n\nIn addition, the cache strategy (see also below), can be provided, for example:\n\n```java\nRestServer restServer = new RestServer(\"http://localhost:8080\", new CacheMemory());\n```\n\nAfter having instantiated the server, the measures can be registered – this step needs to be repeated for every measure:\n\n```java\nrestServer.register(new MeasureExample());\n```\n\nFinally, the server can be started:\n\n```java\nrestServer.run();\n```\n\n### Additional Settings\n\nIn case that a certain type of cell IDs shall be used, e.g., `NON_ADAPTIVE` IDs, the server can be informed to do so before it is run:\n\n```java\nrestServer.setGridCellIDType(GridCellIDType.ADAPTIVE_UNIQUE);\nrestServer.run();\n```\n\nThe default value is `ADAPTIVE_1_PERCENT`. For further information refer to [**geogrid**](https://github.com/mocnik-science/geogrid).\n\n## Accessing a Measure Via the REST Interface\n\nWhen having started the server, the registered measures can be accessed via the REST interface, which runs on `http://localhost:8080` by default.  A measure named `measure-example` can accordingly be evaluated by referring to `http://localhost:8080/api/measure-example`.  As parameters, the resolution of the grid and the bounding box need to be provided.  The complete URL is, for example, as follows:\n\n[`http://localhost:8080/api/measure-example/grid?resolution=14\u0026bbox=7.86,48.16,9.53,50.63`](http://localhost:8080/api/measure-example/grid?resolution=14\u0026bbox=7.86,48.16,9.53,50.63)\n\nHere, the bounding box is provided as minimum and maximum of the longitude and the latitude respectively (more information below in the description of the parameters).  As a result, a JSON response is returned which consists of the identifiers (IDs) of the grid cells (see [geogrid](https://github.com/mocnik-science/geogrid)), as well as of the corresponding value of the measure:\n\n```json\n{\n    \"type\":\"grid\",\n    \"resolution\":14,\n    \"date\":\"2017-09-01T00:00Z\",\n    \"data\":[\n        {\"value\":0.345, \"id\":\"1309502766029885663\"},\n        {\"value\":0.784, \"id\":\"1309502815023667023\"},\n        {\"value\":0.352, \"id\":\"1309502838018652306\"},\n        {\"value\":null, \"id\":\"1309502851015240491\"},\n        {\"value\":null, \"id\":\"1309502862032073320\"},\n        {\"value\":0.546, \"id\":\"1309502875029138747\"},\n        {\"value\":null, \"id\":\"1309502880017193079\"},\n        ...\n    ]\n}\n```\n\n## Parameters\n\n### Overview\n\nThe following parameters are available:\n\n| Option | Type | Default | Description |\n| ------ | ---- | ------- | ----------- |\n| `resolution` | Integer | mandatory | Resolution of the grid, which is to be used for aggregating the data resulting from the evaluation of the measure. |\n| `bbox` | Number, Number, Number, Number | mandatory | Bounding box, provided as `minLon`, `minLat`, `maxLon`, and `maxLat` (in this order). |\n| `latLng` | Boolean | `false` | Result contains the coordinates (latitude and longitude) explicitly if `latLng` is `true`. |\n| `date` | Date | mandatory | Date, or end of the time span, to evaluate the measure for. |\n| `dateFrom` | Date | `null` | Start of the time span to evaluate the measure for. |\n| `daysBefore` | Integer | 3 * 365 | Length of the time span (which ends at `date`) to evaluate the measure for. |\n| `intervalInDays` | Integer | 30 | Interval (in days) in which the time span shall be examined. |\n| `p` | * | | Encodes all other parameters. |\n\n### Parameters `days`, `dateFrom`, and `daysBefore`\n\nA measure can either refer to a certain point in time, represented by the parameter `date`, or to a time span represented by the parameters `dateFrom`/`daysBefore` and `date`.  Whether a measure refers to a time span is determined by the function `refersToTimeSpan`.  By default, a measure refers to only one point in time:\n\n```java\npublic Boolean refersToTimeSpan() {\n    return false;\n}\n```\n\nIf the measure shall rather refer to a time span, it needs to be overridden:\n\n```java\n@Override\npublic Boolean refersToTimeSpan() {\n    return true;\n}\n```\n\nThe measure contains default values. If a parameter is missing in the URL, the default value is used instead. By default, the default parameters are set as follows:\n\n```java\npublic ZonedDateTime defaultDate() {\n    return ZonedDateTime.now(UTC).with(TemporalAdjusters.firstDayOfMonth()).truncatedTo(DAYS);\n}\npublic ZonedDateTime defaultDateFrom() {\n    return null;\n}\npublic Integer defaultDaysBefore() {\n    return 3 * 12 * 30;\n}\npublic Integer defaultIntervalInDays() {\n    return 30;\n}\n```\n\nAccordingly, if the parameter `date` is omitted in the URL, it is defaulted to the start of the current month.  If the measure refers to a time span but no parameter `dateFrom` or `daysBefore` is provided in the URL, the default values for `dateFrom` and `daysBefore` are evaluated (in this order).  If `defaultDateFrom` returns `null`, the method `defaultDaysBefore` is evaluated.  The default methods can be overriden in the implemention of a measure.\n\nBoth parameters `dateFrom` and `date` need to be provided as `yyyy-MM-dd`, as in the following examples:\n\n[`http://localhost:8080/api/measure-example/grid?resolution=14\u0026bbox=7.86,48.16,9.53,50.63\u0026date=2017-09-01`](http://localhost:8080/api/measure-example/grid?resolution=14\u0026bbox=7.86,48.16,9.53,50.63\u0026date=2017-09-01)\n\n[`http://localhost:8080/api/measure-example/grid?resolution=14\u0026bbox=7.86,48.16,9.53,50.63\u0026date=2017-09-01\u0026dateFrom=2015-09-01`](http://localhost:8080/api/measure-example/grid?resolution=14\u0026bbox=7.86,48.16,9.53,50.63\u0026date=2017-09-01\u0026dateFrom=2015-09-01)\n\n### Parameter `latLng`\n\nIf the file should in addition contain the coordinates, the parameter `latLng` needs to be set to `true`:\n\n[`http://localhost:8080/api/measure-example/grid?resolution=14\u0026bbox=7.86,48.16,9.53,50.63\u0026latLng=true`](http://localhost:8080/api/measure-example/grid?resolution=14\u0026bbox=7.86,48.16,9.53,50.63\u0026latLng=true)\n\nAccordingly, the result contains the corresponding coordinates of the centroid of the corresponding cell:\n\n```json\n{{\n    \"type\":\"grid\",\n    \"resolution\":14,\n    \"date\":\"2017-09-01T00:00Z\",\n    \"data\":[\n        {\"value\":0.345, \"id\":\"1309502766029885663\", \"lat\":9.502766309434305, \"lon\":29.8856629972524},\n        {\"value\":0.784, \"id\":\"1309502815023667023\", \"lat\":9.502814964223331, \"lon\":23.667023156128714},\n        {\"value\":0.352, \"id\":\"1309502838018652306\", \"lat\":9.502838251618373, \"lon\":18.652305606256853},\n        {\"value\":null, \"id\":\"1309502851015240491\", \"lat\":9.502851238108507, \"lon\":15.240490824377252},\n        {\"value\":null, \"id\":\"1309502862032073320\", \"lat\":9.502862302688978, \"lon\":32.073320392682334},\n        {\"value\":0.546, \"id\":\"1309502875029138747\", \"lat\":9.502874619605427, \"lon\":29.138747369884587},\n        {\"value\":null, \"id\":\"1309502880017193079\", \"lat\":9.502879767399307, \"lon\":17.19307948719968},\n        ...\n    ]\n}\n```\n\n## Cache\n\nThe computation of a measure for a given bounding box at a given resolution can be very time consuming.  When results are needed within a fraction of a second, it might make sense to cache the results.  There exist different strategies to cache the data, each of which has individual advantages and disadvantages:\n\n* **`CacheMemory`.**  This approach caches the data in the memory.\n* more caching strategies are to be implemented\n\nAs a default, `CacheMemory` is being used.  A particular instance of a caching strategy can be used as follows during the instantiation of the REST server:\n\n```java\nRestServer restServer = new RestServer(new CacheMemory());\nRestServer restServer = new RestServer(8080, new CacheMemory());\nRestServer restServer = new RestServer(\"http://localhost:8080\", new CacheMemory());\n```\n\n## Visualization\n\nThe REST interface of this framework is compatible with the JavaScript library [geogrid.js](https://github.com/mocnik-science/geogrid.js), which visualizes measures as a layer to [Leaflet](http://leafletjs.com):\n\n![Overview](https://github.com/mocnik-science/geogrid.js/blob/master/docs/images/screenshot.jpg)\n\n## Author\n\nThis software is archived at HeiGIT gGmbH and not further meintained.\n\nIn 2017–2019, this software has been developed and maintained by Franz-Benjamin Mocnik, \u003cmocnik@uni-heidelberg.de\u003e, GIScience Research Group, Institute of Geography, Heidelberg University. The development has been supported by the DFG project *A framework for measuring the fitness for purpose of OpenStreetMap data based on intrinsic quality indicators* (FA 1189/3-1).\n\n(c) by Heidelberg University, 2017–2019.\n\n## License\n\nThe code is licensed under the [MIT license](https://github.com/giscience/measures-rest/blob/master/LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgiscience%2Fmeasures-rest","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgiscience%2Fmeasures-rest","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgiscience%2Fmeasures-rest/lists"}