NodeJS

Core functionality

  • RAMANI API NodeJS Library
  • Access online map data through various RAMANI Services
  • Support for Leaflet Maps Services
  • Georeference information from the COPERNICUS and Sentinel data services
  • Store and Get geometry data in Ramani Cloud

Supported Platforms

With Ramani's NodeJS-API you can build your own backend to consume our datasets.


Library Dependencies


Sample Project

To get All the samples source code, you can clone or download on this Project Maps-API NodeJS Example


Getting started

These instructions will help you how to development with our Maps-API in your project. See descriptions below for our Maps-API.

Install And Import RamaniAPI Library

npm install ramani

//import to your code
var ramani = require('ramani');

API-Key

You must provide the API-Key that you get from our client-area webpage before accessing our services. Below is the step-by-step guide to create new API Key:

  • Sign in. Or Register first, if you don't have an account yet
  • Login to your dashboard.
  • Select tab Configuration and your API Key is there.

api-key


Add API Key on Your Javascript Code

var ramani = require('ramani');
var rc = ramani.init({
    user:'YOUR_USERNAME',
    apikey:'YOUR_API_KEY',
    schema:'public'
});
rc.catch(function (error) {
    console.log(error);
});

Note:

  • public is the default Schema name.

Sample Codes

Get Ramani Public Layer ID

public-layerid

  1. Goto Ramani Public Maps
  2. Click on layer button.
  3. Select the datasets you want to use.
  4. Login if you are not loggin yet.
  5. Draw something on the map.
  6. Click get code button.
  7. You will see the Layer ID and also some code snippet.
  8. For sample public.username_SWTRR.

Get Private Layer ID

private-layerid-0 private-layerid-1

  1. Login to your Ramani Cloud Account
  2. Click Editor button from your dashboard.
  3. Select the Database tab.
  4. The Layer ID is combination of Schema and Table ID, here you schema name.
  5. This is your layer ID.
  6. For sample public.SWTRR.

Get Location Info (getPoint)

To get more features information at a single point. Retrieves data, including geometry and attribute values.

//Get Point 
rc.then(function(auth){
  ramani.getPoint([2.3443,48.8537], {
    layer: 'YOUR_LAYER_ID',
  }).then(function(response){
      console.log(response);
  });
});

Note:

  • The getPoint operation is designed to provide clients with more information about a single location on a map. The return text can be provided on either JSON ('text/json') or GeoJSON ('text/geojson') format.

Get Point Profile (getPointProfile)

To get more features information at a single point. Retrieves data, including geometry and attribute values.

rc.then(function(auth){
  var layerobj = [];
  layerobj.push({
      point : [52.338, 6.332],
      layers : ["YOUR_LAYER_ID_A", "YOUR_LAYER_ID_B"]
  });
  ramani.getPointProfile(layerobj).then(function(res) {
      res.forEach(function(val){
          console.log(val);
      })
  }).catch(function (error) {
      console.log(error);
    });
});

Get Vertical Profile

To get more features information at a single point(Get Point), along a vertical dimension.

//Get Vertical Profile as JSON
rc.then(function(auth){
  ramani.getVerticleProfile([52.338, 6.332], {
        layer: 'YOUR_LAYER_ID'
  }).then(function(response){
      console.log(response);
  }).catch(function (error) {
      console.log(error);
  });
});

Note:

  • Only works on layers that have a temporal dimension (explore the maps we have offer in our DDL), for example nitrates in the depth of the ocean
  • Only support for JSON, PNG.
  • Replace imageID with the ID of image element to show the image, and don't forget to change info_format to image/png to receive a PNG image as return.

Example: For example, nitrates variability along ocean depth.


Get Time-series Profile

To get more features information at a single point(Get Point), along with variation in time (along a temporal dimension).

// Get Timeseries JSON Format
rc.then(function(auth){
  ramani.getTimeseriesProfile([52.338, 6.332], {
  layer: 'YOUR_LAYER_ID',
  time : '2013-12-04T00:00:00.000Z/2013-12-28T00:00:00.000Z'
  }).then(function(res){
      console.log(res);
  });
});

Note:

  • Only works on layers that have a temporal dimension (explore the maps we have offer in our DDL), for example Leaf Area Index (LAI) over the seasons of the year
  • Only support for format JSON,and PNG.
  • If you want show the result as image replace imageID with the ID of image element to show the image, and don't forget to change info_format to image/png to receive a PNG image as return.

Get Horizontal Profile (GetTransect)

To get more features information at multiple point, along a horizontal dimension. For example, atmospheric ozone along a line (single or multiple segments) crossing a city.

//Get Transect JSON Format
rc.then(function(auth){
  ramani.getTransect([
        [49.14758022506841, 1.9720458984374998],
        [49.337651296668845, 3.5870361328124996]
  ],{
  layer: 'YOUR_LAYER_ID',
  }).then(function(response){
      console.log(response);
  }).catch(function (error) {
      console.log(error);
  });
});

Note:


Get Area Profile

To get more features information at multiple point, along a horizontal dimension. But for an area defined by PolygonOptions.

//GetArea JSON Format
rc.then(function(auth){
  ramani.getArea([
        [52.382305628707854, 6.25396728515625],
        [52.424196211696774, 6.372899355829467],
        [52.30345857599569, 6.257838787287611],
        [52.309025707071214, 6.638463891157568]
  ], {
  layer: 'YOUR_LAYER_ID',
  'return' :'aggregate'
  }).then(function(response){
      console.log(response);
  }).catch(function (error) {
      console.log(error);
    });
});

Note:

  • Only support for JSON,and PNG.
  • Only support for return type : ALL, HISTOGRAM, and AGGREGATE.
  • Explore the maps we have offer in our DDL.
  • To get layer capabilities (attribute) or if you want to set custom parameter.

Return as Aggregate Example :

 {
  "type": "GetAreaResponse",
  "area": {
    "crs": "EPSG:4326",
    "linestring": "0.549412 44.47218,0.559412 44.48218,0.539412 44.46218,",
    "dataset": "Copernicus Type: Leaf-Area Index (Global, Historical)",
    "variable": "leaf_area_index",
    "units": "",
    "aggregate": {
      "mean": 1.3295866718292235,
      "stdv": 0.09477143603275541,
      "skew": 0.3785473045287679,
      "kurt": -1.3290498057043592,
      "min": 1.233320951461792,
      "max": 1.4999849796295166,
      "perc": 1.2999869585037231,
      "median": 1.2999869585037231
    }
  }
}

Return as Histogram Example :

 {
  "type": "GetAreaResponse",
  "area": {
    "crs": "EPSG:4326",
    "linestring": "0.549412 44.47218,0.559412 44.48218,0.539412 44.46218,",
    "dataset": "Copernicus Type: Leaf-Area Index (Global, Historical)",
    "variable": "leaf_area_index",
    "units": "",
    "histogram": [
      "{frequency=92.0, value=1.2999869585037231}",
      "{frequency=52.0, value=1.3999860286712646}",
      "{frequency=46.0, value=1.533318042755127}",
      "{frequency=52.0, value=1.3999860286712646}",
      "{frequency=96.0, value=1.2999869585037231}",
      "{frequency=52.0, value=1.2666540145874023}",
      "{frequency=97.0, value=1.3666529655456543}",
      "{frequency=13.0, value=1.1999880075454712}"
    ]
  }
}

Get Point Cube

The extended version of Get Feature Info (Get Point). Where you’re able to not just get the information on a single point, but also the information of the neighboor GeoPoint, in a 3x3, 5x5, etc bounding box. It would be usefull for a comparison (e.g temperature between all neighboring pixels in a 3x3).

In order to create a grid(rectangular), a bounding box is needed. And every bounding box has a radius, which is the distance from your center point to the outer edge of bounding box. And the diameter, which is the distance between outer edge, or always twice the radius.

The radius value in our API is the latlong distance(e.g. distance from GeoPoint(10.00, 10.00) to GeoPoint(10.00, 10.50) will has 0.5 distance in lon (± 50Km)). And if you set your radius at 0.5, your diameter(grid width) will be 1. This also means, the distance between bounding box center point in your grid, is 1 (diameter).

rc.then(function(auth){
  var layerobj = [];
  layerobj.push({
          point : [52.338, 6.332],
          params : {
              layer : 'YOUR_LAYER_ID'
          }
      });
  var grid = 3;
  var radius = 0.005;
  ramani.getPointCube(layerobj, grid, radius).then(function(res) {
      res.forEach(function(val){
          console.log(val.features[0]);
      })
  }).catch(function (error) {
      console.log(error);
  });
});

The code above will give you 9 data points, since you're requesting for 3x3 grid size. The value itself once again, depend on your GeoPoint and Radius.

result 0 : 
{
  "type": "FeatureInfoResponse",
  "features": [
    {
      "geometry": "6.332 52.328",
      "properties": {
        "iIndex": 49068,
        "jIndex": 21898,
        "gridCentreLon": 6.3320830289319545,
        "gridCentreLat": 52.327948366775345
      },
      "featureInfo": [
        {
          "time": "2006-01-01T00:00:00.000Z",
          "value": 18
        }
      ]
    }
  ]
}
result 1 : 
{
  "type": "FeatureInfoResponse",
  "features": [
    {
      "geometry": "6.342 52.328",
      "properties": {
        "iIndex": 49076,
        "jIndex": 21898,
        "gridCentreLon": 6.342327845860233,
        "gridCentreLat": 52.327948366775345
      },
      "featureInfo": [
        {
          "time": "2006-01-01T00:00:00.000Z",
          "value": 18
        }
      ]
    }
  ]
}
...

With the order from the Bottom Left (the lowest coordinate) to Top Right (the higher coordinate). Below is the visualization of the 3x3 grid indices, where the (0,0) is your original GeoPoint:

Point Cube

Note:

  • Only support for grid size with odd value and >= 3
  • Explore the maps we have offer in our DDL

Set Layer Attributes (setParams)

Set Parameter is used to add or replace existing parameters, to make your requested data richer and more dynamic. Make sure to call setParams(params) before executing your request, or the API will use your default parameter.

 rc.setParams({ time : '2010-02-04T00:00:00.000Z/2010-04-15T00:00:00.000Z' });

Note: Use this method to set Layer attributes. For more information about which parameters you can set follow this link.

Example: Use the param ( TIME) to set the temporal range of a time-series.


Get Layer Attributes(GetMetadata)

To requests metadata (e.g. date-range, layer details, units, etc.) from layer dataset. For example, to obtain the temporal range of a time-series required by getTimeseriesProfile use (TIME), or to get the extremes of a layer (Min), and (Max) to set the scaleRange parameter.

//get Metadata
rc.then(function(auth){
  ramani.getMetadata('YOUR_LAYER_ID')
  .then(function(response){
        console.log(response);
  });
});

Note: Use this method to get Layer attributes aka metadata. For more information about which parameters you can get follow this link.

Example: To obtain the temporal range of a time-series required by getTimeseriesProfile use ( TIME), or to get the extremes of a layer ( Min) and ( Max) to set the scaleRange parameter.


Get dates for timeseries and return as RSS

Using Get Layer Attributes method, below is the example to get (TIME) for Get Time-series Profile:

 //Get Dates for timeseries return as RSS
rc.then(function(auth){
  ramani.getMetadata('YOUR_LAYER_ID', { item:'dates',  format : 'rss' })
  .then(function(response){
        console.log(response);
  });
});


Example: click to see the example.

Here is the result response with ISO8601 as JSON :

<rss version="2.0">
  <channel>
    <title>Land cover type</title>
    <link>http://ramani.ujuizi.com/ddl/wms?token=ofa2hee728jaurgraqim78fes5&package=com.ujuizi.ramaniapi.js&item=dates&layerName=simS3seriesCoverGlobal/coverclass&request=GetMetadata</link>
    <description>GetMetadata (Date) RSS Service.</description>
    <copyright>(c)Ujuizi Laboratories</copyright>
    <pubDate>Fri, 23 Aug 2019 07:07:37 GMT</pubDate>
    <dc:date>2019-08-23T07:07:37Z</dc:date>
    <dc:rights>(c)Ujuizi Laboratories</dc:rights>
    <item>
      <title>2004-01-01T00:00:00.000Z</title>
      <link>http://ramani.ujuizi.com/ddl/wms?token=ofa2hee728jaurgraqim78fes5&package=com.ujuizi.ramaniapi.js&item=timesteps&layerName=simS3seriesCoverGlobal/coverclass&request=GetMetadata&day=2004-01-01T00:00:00.000Z</link>
      <pubDate>Fri, 23 Aug 2019 07:07:37 GMT</pubDate>
      <guid>http://ramani.ujuizi.com/ddl/wms?token=ofa2hee728jaurgraqim78fes5&package=com.ujuizi.ramaniapi.js&item=timesteps&layerName=simS3seriesCoverGlobal/coverclass&request=GetMetadata&day=2004-01-01T00:00:00.000Z

Get dates for timeseries and return ISO8601 format

Using Get Layer Attributes method, below is the example to get (TIME) for Get Time-series Profile:

rc.then(function(auth){
  ramani.getMetadata('YOUR_LAYER_ID', { item:'dates' }).then(function(response){
        console.log(response);
  });
});

Here is the result response with ISO8601 as JSON :

{
  "units": "",
  "bbox": [
    "-180.0",
    "-64.99722222234622",
    "179.99722222611302",
    "89.99999999999999"
  ],
  "scaleRange": [
    "-126.0",
    "120.0"
  ],
  "numColorBands": 250,
  "supportedStyles": [
    "boxfill"
  ],
  "datesWithData": [
    "2004-01-01T00:00:00.000Z",
    "2009-01-01T00:00:00.000Z"
  ],
  "nearestTimeIso": "2009-01-01T00:00:00.000Z",
  "timeAxisUnits": "ISO8601"
}

<!--

Get an animated Map ( getAnimation)

With the Ramani API Framework for JavaScript, you can create animated map layers (provided the dataset of interest has a temporal dimension). The code below demonstrates how to receive an image (imgobj) for each time step available.

  var transect = rc.getAnimation(point, { layer: '**layerID**', info_format : 'image/png', imgobj : 'imgobj' });

Note: You can set the TIME param to choose the time range to be covered (as described in Set Layer Attributes).


-->

Store Geometry Data

Store Point (storePoint)

Store a new or modified point feature on Ramani Cloud (currently only support for private layers):

rc.then(function(auth){
  var fields = { id : '99', time : '12313123', accelx: '1.2' }; 
  ramani.storePoint('YOUR_LAYER_ID', fields, overlay.getLatLng())
  .then(function(res){
      console.log(res);
  });
});

Note: Allows the user to define series of points of interest and store these for repeated usage on different requests.


Store Polygon (storePolygon)

Store a (multi)polygon feature on Ramani Cloud (currently only support for private layers):



rc.then(function(auth){
var fields = { id : '1', name : 'pointA' }; 
 ramani.storePolygon('YOUR_LAYER_ID', fields, points)
  .then(function(res){
      console.log(res);
  });
});

Note: Note: This function can be used to retrieve a pre-defined area for future usage.


Store Line (storeLine)

Store your (multi)line feature on Ramani Cloud (currently only support for private layers):

var fields = { id : '1', name : 'pointA' }; 

rc.then(function(auth){
  var fields = { id : '99', time : '12313123', accelx: '1.2' }; 
  ramani.storeLine('YOUR_LAYER_ID', fields, points)
  .then(function(res){
      console.log(res);
  });
});

Note: Useful to keep a line stored for future usage, e.g. for obtaining a Horizontal Profile (with getTransect) for the same region over different days.

Testing The Library

Explore our Sample Maps-API. And fell free to give us some feedback, such as :

  • The app is confusing, because ____
  • Can you add more information on ____
  • Can you change this part to ____
  • What do you mean by ____

etc. Because your experiences when using the app is very important to us.

  • TMake sure you have already included the library dependencies to the project (see Library Dependencies)
  • Use the latest version from Releases
  • Test and explore all the method (for examples, see Getting Started)
  • Provide us with your Feedback (see Contributing)

Contributing

  • Explore our sample app.
  • Evaluating our source code.
  • Build your own product or use-case with our library.
  • Give us some feedback about your experiences feedback

Feedback


License

Copyright (c) 2017 RAMANI B.V.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.