How to plot scattered point of NDVI and draw the trend in google earth engine - google-earth-engine

I am using 'USGS Landsat 8 Level 2, Collection 2, Tier 1' Landsat to calculate mean NDVI and plot the trend from the scattered plot.
I have used the following code:
For importing file:
var imageCollection 'USGS Landsat 8 Level 2, Collection 2, Tier 1'
var Table 'the shapefile'
// Define a function that will add an NDVI band to a Landsat 8 image.
var addNDVI = function(image) {
var ndvi = image.normalizedDifference(['SR_B5', 'SR_B4']).rename('NDVI');
return image.addBands(ndvi);
};
function add_NDVI_collection(image_IC){
var NDVI_IC = table.map(addNDVI);
return NDVI_IC;
}
// Filter and map the function over the collection.
var withNDVI = imageCollection.filterDate('2015-01', '2015-12')
.map(addNDVI); // <-- map() the function over the collection.
// Filter and map the function over the collection.
// Make a chart.
var chart = ui.Chart.image.series({
imageCollection: withNDVI.select('NDVI'),
region: table, //again, here the ROI is a single point
reducer: ee.Reducer.mean()})
// Define custom options for the chart. See:
// https://developers.google.com/chart/interactive/docs/reference
var options = {
title: 'NDVI over time',
hAxis: { title: 'time' ,format: 'YYYY-MMM',gridlines:{count:12}},
vAxis: { title: 'NDVI' },
series: {
0: { color: 'blue' }
}
};
// Set the options of the chart and print it.
chart = chart.setOptions(options);
print(chart); // Put it in the console
I got the following plot:
How can I plot the scattered point instead of the connecting line for the NDVI and draw the trend by removing outlier?

You can use this tutorial to have full control over your chart.
For smoothing your curve:
.setOptions({
curveType: 'function'
})
For showing the points
{
pointSize: 10
}

Related

ArcGIS JS - how to detect polygon points connect

I'm using ArcGIS JS 4.16 to allow users to draw a polygon on the map. The idea is that there will only be one polygon at any given time and when you connect two dots, it makes sense that it would complete the polygon. Double clicking or pressing "C" seems a bit more complex for the average use case.
const drawLayer = new GraphicsLayer();
const map = new Map({
basemap: 'streets-vector',
layers: [drawLayer],
});
const view = new MapView({
container: mapRef.current,
map: map,
center: [-73.93, 40.73],
zoom: 10,
});
const draw = new Draw({ view: view });
document
.getElementById('enableCreatePolygon')
.addEventListener('click', () => {
enableCreatePolygon(draw, view);
});
const enableCreatePolygon = (draw, view) => {
const action = draw.create('polygon');
action.on('vertex-add', (evt) => {
createPolygonGraphic(evt.vertices);
});
action.on('vertex-remove', (evt) => {
createPolygonGraphic(evt.vertices);
});
action.on('cursor-update', (evt) => {
createPolygonGraphic(evt.vertices);
});
action.on('draw-complete', (evt) => {
createPolygonGraphic(evt.vertices);
});
};
const createPolygonGraphic = (vertices) => {
view.graphics.removeAll();
const polygon = {
type: 'polygon',
rings: vertices,
spatialReference: view.spatialReference,
};
const graphic = new Graphic({
geometry: polygon,
symbol: {
type: 'simple-fill',
color: [51, 51, 204, 0.15],
style: 'solid',
outline: {
color: [51, 51, 204, 0.8],
width: 2,
},
},
});
I see two options, implement the "logic" or use SketchViewModel where is it already implemented. Btw, with the "logic" I mean complete polygon when the last vertex is equal (with a tolerance) to the first vertex.
Take a look at this links,
ArcGIS JS API Docs - SketchViewModel
You can implement your own UI to interact with the model or use the SketchWidget.
ArcGIS JS API Examples - Using custom UI or interaction
ArcGIS JS API Examples - Using SketchWidget

ngx-charts line chart, how to show the line chart with dot for the data point all the time

for ngx-charts line chart, it show the line chart, but there is no dot for the data point.
If you hover the data point, it show a dot for the data pint and also with a label tooltip.
I like to have the line chart to show all the data point with a dot all the time like this.
I need your help on how to show a dot at the data point in ngx-charts line chart
Here is the sample for ngx-chart https://github.com/kedmenecr/cinnamon-angular5-with-ngx-charts
Here is the source code for ngx-chart libary . https://github.com/swimlane/ngx-charts
thanks.
if anyone still needs this feature I workaround this feature with a non-super clean solution but it works with no side effect so far :
custom service to draw the points over liner chart:
import { Injectable } from '#angular/core';
#Injectable()
export class CustomLinerChartService {
/**
* custom: override SVG to have the dots display all the time over the liner chart
* since it's not supported anymore from ngx chart
*/
showDots(chart) {
let index = 0;
const paths = chart.chartElement.nativeElement.getElementsByClassName(
'line-series'
);
const color = chart.chartElement.nativeElement.getElementsByClassName(
'line-highlight'
);
for (let path of paths) {
const chrtColor = color[index].getAttribute('ng-reflect-fill');
const pathElement = path.getElementsByTagName('path')[0];
const pathAttributes = {
'marker-start': `url(#dot${index})`,
'marker-mid': `url(#dot${index})`,
'marker-end': `url(#dot${index})`
};
this.createMarker(chart, chrtColor, index);
this.setAttributes(pathElement, pathAttributes);
index += 1;
}
}
/**
* create marker
*
*/
createMarker(chart, color, index) {
const svg = chart.chartElement.nativeElement.getElementsByTagName('svg');
var marker = document.createElementNS(
'http://www.w3.org/2000/svg',
'marker'
);
var circle = document.createElementNS(
'http://www.w3.org/2000/svg',
'circle'
);
svg[0].getElementsByTagName('defs')[0].append(marker);
marker.append(circle);
const m = svg[0].getElementsByTagName('marker')[0];
const c = svg[0].getElementsByTagName('circle')[0];
const markerAttributes = {
id: `dot${index}`,
viewBox: '0 0 10 10',
refX: 5,
refY: 5,
markerWidth: 5,
markerHeight: 5
};
const circleAttributes = {
cx: 5,
cy: 5,
r: 5,
fill: color
};
m.append(circle);
this.setAttributes(m, markerAttributes);
this.setAttributes(c, circleAttributes);
}
/**
* set multiple attributes
*/
setAttributes(element, attributes) {
for (const key in attributes) {
element.setAttribute(key, attributes[key]);
}
}
}
and after your view init and the data is set to the chart call :
#ViewChild('chart') chart: any;
ngAfterViewInit() {
this.customLinerChartService.showDots(this.chart);
}
make sure to have the reference on your chart :
<ngx-charts-line-chart #chart>
UPDATE
you can't rely on ng-reflect-fill class since it just added in development mood so insted provide your colors as array and chose it based on index for example
This simpler approach first posted here also works well:
https://github.com/swimlane/ngx-charts/issues/462#issuecomment-783237600
I suggest first getting a reference to the chart, and looping through the series:
#ViewChild("numberChart", {read: ElementRef, static: false})
numberChartRef: ElementRef;
...
chartRef.nativeElement.querySelectorAll("g.line-series path").forEach((el) => {
el.setAttribute("stroke-width", "10");
el.setAttribute("stroke-linecap", "round");
});
I test the length of the series, and only apply these changes if the length is 1. Also make sure to return the attributes to the defaults though if you don't want extra thick lines for all your charts-
I have a way simpler solution to this, just adding a single field will do the trick for you:
In your component class, set the "dot" property of the series to true:
this.data = [
{
name: 'Series 1',
series: [
{
name: 'Point 1',
value: 9,
},
{
name: 'Point 2',
value: 7,
},
{
name: 'Point 3',
value: 5,
}
],
dot: true
},
{
name: 'Series 2',
series: [
{
name: 'Point 1',
value: 8,
},
{
name: 'Point 2',
value: 6,
},
{
name: 'Point 3',
value: 4,
}
],
dot: true
}
];
This will show dots on the line chart on the respective data points as shown below:
Data points
Highlight Single Point

Load Graph using Chart.js with Dynamic Data ASP.net MVC-Core

I am new to ASP.net MVC using Bootstrap to load a graph with dynamic data coming from the database. I use this link as guide and tutorial in starting. https://canvasjs.com/docs/charts/integration/asp-net-mvc-charts/
I was able to load the graph with static data, right now, I want to fill the graph with data dynamically that comes from the database.
Here's the codes started
patientService.cs - this will give a result set of patient's vital sign (height, weight and date recorded). One patient may have a multiple recorded vital sign per date. This will be the label and the data of the graph (height and date)
public IEnumerable<VisitVitalSignVM> GetVisitVitalSignHeight(int patientId)
{
var patientList = _patient.GetAllPatient().Where(a => a.patientId.Equals(patientId));
var registrationList = _registration.Get().Where(a => a.patientId.Equals(patientId));
var visitVitalSignList = _visitVitaSign.Get();
var dataCreatedDate = (from a in visitVitalSignList
join b in registrationList on a.registrationId equals b.registrationId
where a.registrationId == b.registrationId
//select a).ToList();
select new VisitVitalSignVM()
{
height = a.height,
weight = a.weight,
lastUpdatedDate = a.lastUpdatedDate
}
).DefaultIfEmpty();
return dataCreatedDate;
}
Note that lastUpdatedDate represents the data for the x-axis and height represents the data for the y axis.
patient.cs - the will pull data from the service layer and forward result in viewModel through partial view.
[HttpGet]
public IActionResult GetVisitVitalSignDetails(int patientId, string type, string graph)
{
var visitSign = _patient.GetVisitVitalSignHeight(patientId);
return PartialView("_ViewVisitVitalSignGraphDetails", visitSign);
}
_partialViewPatient.cshtml - this will then receive the data needed to plot the graph. Currently, the code in the javascript are the static one. I am now lost, on how to plot the data from the VisitVitalSignVM Model to the datasets.
**#using UMP.ClinicalSystem.Models.Models;
#using UMP.ClinicalSystem.Models.Dto;
#model IEnumerable<VisitVitalSignVM>
#{
Layout = null;
}
<div id="chartContainer"> </div>
<script src="https://canvasjs.com/assets/script/canvasjs.min.js"></script>
<script type="text/javascript">
var chart = new CanvasJS.Chart("chartContainer", {
theme: "theme2",
animationEnabled: true,
title: {
text: "Simple Column Chart in ASP.NET MVC"
},
subtitles: [
{ text: "Try Resizing the Browser" }
],
data: [
{
type: "line", //change type to bar, line, area, pie, etc
dataPoints: [
{ x: 10, y: 71 },
{ x: 20, y: 55 },
{ x: 30, y: 50 },
{ x: 40, y: 65 },
{ x: 50, y: 95 },
{ x: 60, y: 68 },
{ x: 70, y: 28 },
{ x: 80, y: 34 },
{ x: 90, y: 14 }
]
}
]
});
chart.render();
</script>**
Your plugin requires that the data be an array of objects containing properties x and y
You need to first convert your view model collection to a javascript array, then build a new array of objects to pass to the dataPoints option.
In the view include #inject IJsonHelper Json; so you can serialize the model and then in the script
// convert your model to a javascript array
var model = #Html.Raw(Json.Serialize(Model));
// initialise a new array
var datapoints = [];
// build an array of objects
$.each(model, function(index, item) {
datapoints.push({ x: new Date(item.lastUpdatedDate), y: item.height });
});
and then modify the plug code to use the array
var chart = new CanvasJS.Chart("chartContainer", {
theme: "theme2",
....
data: [{
type: "line",
dataPoints: datapoints // modify this
}]
});
chart.render();

AmCharts map - insert html

I'm trying to create a pulse effect on a point on a AmCharts Map. In order to do this I need to insert HTML at a latitude and longitude point but can't work out how to do it through the api (http://docs.amcharts.com/3/javascriptmaps/)
Here is the effect I'm trying to achieve - http://kevinurrutia.tumblr.com/post/16411271583/creating-a-css3-pulsating-circle
Here is a jsfiddle of the map with the HTML and CSS http://jsfiddle.net/9cBXh/2/
// request #3275
var dataPoints = [{
latitude: '51.000000000000',
longitude: '9.000000000000',
type: 'bubble',
color: '#cc0000',
fixedSize: false,
alpha: 0.9,
height: 30,
width: 30,
centered: true,
id: 'test'
}];
AmCharts.ready(function() {
// create AmMap object
var map = new AmCharts.AmMap();
// set path to images
map.pathToImages = "http://www.ammap.com/lib/images/";
var dataProvider = {
mapVar: AmCharts.maps.worldLow,
getAreasFromMap:false,
images: dataPoints
};
// pass data provider to the map object
map.dataProvider = dataProvider;
map.areasSettings = {
autoZoom: true,
selectedColor: "#CC0000"
};
// write the map to container div
map.write("mapdiv");
});
The red dot is the bubble generated through the api. The blue dot and circle is the html I need to insert at the lat and long co-ordinates...somehow!
Any help would be appreciated.
Here's a complete working example of the AmCharts map with several pulsating HTML elements as map markers:
http://www.amcharts.com/demos/custom-html-elements-map-markers/
(You can view the source by clicking on the EDIT button)
The idea is very simple:
Trap "positionChanged" event. Go throiugh all of the "images" in the map's dataProvider, create HTML elements for each of those, then position them directly over the map by using API functions that resolve longitude/latitude coordinates to screen top/left coordinates:
// add events to recalculate map position when the map is moved or zoomed
map.addListener("positionChanged", updateCustomMarkers);
// this function will take current images on the map and create HTML elements for them
function updateCustomMarkers (event) {
// get map object
var map = event.chart;
// go through all of the images
for( var x in map.dataProvider.images) {
// get MapImage object
var image = map.dataProvider.images[x];
// check if it has corresponding HTML element
if ('undefined' == typeof image.externalElement)
image.externalElement = createCustomMarker(image);
// reposition the element accoridng to coordinates
image.externalElement.style.top = map.latitudeToY(image.latitude) + 'px';
image.externalElement.style.left = map.longitudeToX(image.longitude) + 'px';
}
}
// this function creates and returns a new marker element
function createCustomMarker(image) {
// create holder
var holder = document.createElement('div');
holder.className = 'map-marker';
holder.title = image.title;
holder.style.position = 'absolute';
// create dot
var dot = document.createElement('div');
dot.className = 'dot';
holder.appendChild(dot);
// create pulse
var pulse = document.createElement('div');
pulse.className = 'pulse';
holder.appendChild(pulse);
// append the marker to the map container
image.chart.chartDiv.appendChild(holder);
return holder;
}

Extend polyline and handle mouse event

I write JS app where I draw a lot of polylines using array of points, but in avery point I have some additional properties in this point (GPS data, speed etc).
I want to show these additional props onmouseover or onmouseclick event.
I have two ways:
use the standard polylines and event handler. But in this case I can't to determine additional properties for start point of this polyline cause I can't to save these props in polyline properties. There is one solution - save in array additional properties and try to find them by LatLng of first point of the polyline, but it's too slow I guess..
extend polyline and save additional properties in new Object, but I can't to extend mouse events :(
To extend polyline I use this code:
function myPolyline(prop, opts){
this.prop = prop;
this.Polyline = new google.maps.Polyline(opts);
}
myPolyline.prototype.setMap = function(map) {
return this.Polyline.setMap(map);
}
myPolyline.prototype.getPath = function() {
return this.Polyline.getPath();
}
myPolyline.prototype.addListener= function(prop) {
return this.Polyline.addListener();
}
myPolyline.prototype.getProp= function() {
return this.prop;
}
myPolyline.prototype.setProp= function(prop) {
return this.prop = prop;
}
and create new object in for loop (i - index of current point in array of points) like that:
var polyline_opts = {
path: line_points,
strokeColor: color,
geodesic: true,
strokeOpacity: 0.5,
strokeWeight: 4,
icons: [
{
icon: lineSymbol,
offset: '25px',
repeat: '50px'
}
],
map: map
};
var add_prop = {
id: i,
device_id: device_id
};
...
devices_properties[device_id].tracks[(i-1)] = new myPolyline(add_prop, polyline_opts);
Where:
line_points - array of points (just two points),
i - current point index
devices_properties[device_id].tracks - array of extended polylines (with add properties) by my device_id index
After that I set event handler like that:
var tmp = devices_properties[device_id].tracks[(i-1)];
google.maps.event.addListener(tmp.Polyline, 'click', function(e) {
...
console.log(tmp.prop.id);
...
}
But in this case I always get the same id in console..
When I use
google.maps.event.addListener(devices_properties[device_id].tracks[(i-1)].Polyline, 'click', function(e) {
...
console.log(???); // How to get parent of polyline fired the event?
...
}
I don't know how to get parent of polyline fired the event?
I answer my own question - It's done, I've just have some troubles with using "for" instead "$.each" :)
Before I use:
for ( i = 1; i < devices_properties[device_id].history_points.length; i++ ) {
...
create myPolyline
...
}
and it's doesn't work - created one event handle.
After:
$.each(devices_properties[device_id].history_points, function(i, tmp){
...
create myPolyline ()
...
}
and it works - create a lot of event handlers.
To handle event I use this:
google.maps.event.addListener(c_polyline.Polyline, 'mouseover', function(e) {
var prop = c_polyline.getProp();
...
console.log(prop.id, prop.device_id);
}

Resources