AngularJS/ChartJS: Get the current series - javascript

I am currently using Angular Chart (http://jtblin.github.io/angular-chart.js/)
I need to find the current dataset/series Index.
In my angular controller:
$scope.mainChart.series = ['Past year', 'Current year'];
$scope.mainChart.data = [
[10, 20, 30, 40], // 2015 - Index 0
[50, 60, 70, 80] // 2016 - Index 1
];
In the points array exists the property _datasetIndex. My onClick function is:
$scope.mainChart.onClick = function (points, event) {
$log.log( points[0]._datasetIndex ); // 0
$log.log( points[1]._datasetIndex ); // 1
};
How can I get the current series index that are clicked?
My canvas element is:
<canvas id="line" class="chart chart-line" chart-data="mainChart.data" chart-labels="mainChart.labels" chart-click="mainChart.onClick" chart-series="mainChart.series" chart-options="mainChart.options" chart-y-axes="mainChart.multiAxis" chart-legend="true" height="270"></canvas>

Lenin Meza: Your answer helped me.
Herewith I have posted shortcut/alternate way of fetching label and series.
$scope.mainChart.onClick = function (points, event) {
// Get current chart
var chart = points[0]._chart.controller;
var activePoint = chart.getElementAtEvent(event);
if (activePoint.length > 0) {
// Get current Dataset
var model = activePoint[0]._model;
// Get current serie by dataset index
var series = model.datasetLabel;
//get the internal index of slice in pie chart
var clickedElementindex = activePoints[0]["_index"];
//get specific label by index
var label = model.label;
//get value by index
var value = chart.data.datasets[dataset].data[clickedElementindex];
}
};

Angular-Chart is wrapped around AngularJS+Chart.js. According to Chart.js you have this http://www.chartjs.org/docs/#advanced-usage-prototype-methods ..getElementsAtEvent(e) if you could find the Chart instance.
Otherwise, if you are running out of time you can do the following.
First you need to distinguish all the points, so there are no points that have the same (label & series index & data set index).
function induceIndex(point){
//FIND the INDEX of the SET
var dataSetIndex= $scope.mainChart.series.findIndex(sElem=>sElem === point.dataSetLabel);
//GET the SET itself
var dataSet = $scope.mainChart.data[seriesIndex];
//FIND the POINT in the DATASET asserting that it is at the same INDEX of its LABEL
var pointIndex = dataset.findIndex((dElem,index)=>dElem=== point.value && $scope.mainChart.labels[index] === point.label);
//do what you want
return pointIndex;
}

I have multiple Charts in my Dashboard and i resolve this with this code:
$scope.mainChart.onClick = function (points, event) {
// Get current chart
var chart = points[0]._chart.controller;
var activePoint = chart.getElementAtEvent(event);
if (activePoint.length > 0) {
// Get current Dataset
var dataset = activePoint[0]._datasetIndex;
// Get current serie by dataset index
var serie = $scope.mainChart.series[dataset];
//get the internal index of slice in pie chart
var clickedElementindex = activePoints[0]["_index"];
//get specific label by index
var label = chart.data.labels[clickedElementindex];
//get value by index
var value = chart.data.datasets[dataset].data[clickedElementindex];
}
};

Related

Google App Script Concating Arrays change the values for the whole array

I have a list of 290 items with 4 columns, which I need to duplicate. I have in a Spreadsheet Row some departements and under it a lot of systems. for each system I need to duplicated the 290 values and add one index column at the front, the department in column 6 and the system in column 7.
I am using the following code:
const ssOrg = SS.getSheetByName("OrgStructure");
function myFunction() {
var afinal = [];
var aDevs = ssDeliverables.getDataRange().getValues();
aDevs.shift();
var lastRow = ssOrg.getLastRow();
var lastColum = ssOrg.getLastColumn();
var count = 1
for (var spalte = 1; spalte <lastColum; spalte++){
var squad = ssOrg.getRange(3,spalte).getValue();
for (var reihe=5; reihe <lastRow; reihe++) {
var system = ssOrg.getRange(reihe,spalte).getValue();
if (system !== ""){
aDevs.map(function(row){
row[0] = count;
row[5] = squad;
row[6] = system;
count ++
return row
})
Logger.log(system);
afinal = afinal.concat(aDevs);
}
}
}
var lastDataRow = ssAssessmentLogic.getLastRow();
ssAssessmentLogic.getRange(2,1,lastDataRow-1,10).clearContent();
var rngResult = ssAssessmentLogic.getRange(2,1,afinal.length,7);
rngResult.setValues(afinal);
}
The problem is that the array at the end (16000 rows) has the same value for each row in column 6 and 7. It is allways the last system & department combination that appears in all 16000 rows.
Where am I wrong?
The question was a little confusing for me but I followed your specifics in the comments section where you explain what exactly info to copy and how and where to paste it.
This gets the job done:
const ss = SpreadsheetApp.getActive();
// this gets the "deliverables" and the "departments", this last ones in a list
// and for each department runs the function to add the complete new modified array to the spreadsheet
function fillsNewSheet(){
var newSheet = ss.getSheetByName('List_DeliverablesALL');
// hardcoded the titles
newSheet.getRange(1, 1, 1, 6).setValues([['taskHasDeliverableNumber', 'Deliverable Description', 'SDP Task', 'SDP Milestone', 'Group', 'Department']])
var deliverables = getDeliverables();
var departments = getDepartments();
for(i=0;i<departments.length;i++){
var departmentsGroup = departments[i];
for(j=0;j<departmentsGroup.length;j++){
addsNewSection(deliverables, departmentsGroup[j])
}
}
}
// this just gets de array of values we are gonna paste for each department in the structure sheet.
function getDeliverables(){
var deliSheet =ss.getSheetByName('Deliverables1');
var deliValues = deliSheet.getRange(2, 2, deliSheet.getLastRow()-1, 4).getValues();
return deliValues;
}
// As the departments are in different columns with different row counts,
// I go over the whole columns and rows and create a single list with all "department" and "group" pairs
function getDepartments(){
var structureSheet = ss.getSheetByName('OrgStructure');
var cols = structureSheet.getLastColumn();
var groups = structureSheet.getRange(3, 1, 1, cols).getValues()[0]
var departments = [];
for(i=1;i<=cols;i++){
var group = groups[i-1];
var groupDeps = structureSheet.getRange(5, i, structureSheet.getLastRow(), 1).getValues();
var subDeps = []
for(j=0;j<groupDeps.length;j++){
subDeps.push([group, groupDeps[j][0]])
}
var filtered = subDeps.filter( function (data) { return data[1] != "" });
departments.push(filtered);
}
return departments;
}
// finally this gets the complete list of "deliverables" from the first sheet, and one specific department.
function addsNewSection(deliverables, department){
var newSheet = ss.getSheetByName('List_DeliverablesALL');
// and in every row of the deliverables list we add the corresponding department/group pair to get the new modified array.
var newSection = []
for(k=0;k<deliverables.length;k++){
var newRow = deliverables[k].concat(department)
newSection.push(newRow)
}
// when this is complete I paste the whole new array in the third sheet.
newSheet.getRange(newSheet.getLastRow()+1, 1, newSection.length, 6).setValues(newSection)
}

How to remove images with specific WRS_PATH and WRS_ROW from a landsat 8 surface reflectance collection?

There are four tiles (path:41,row:35/path:41,row:36/path:42,row:35/path:42,row:36) of LANDSAT 8 surface reflectance that cover my study area. I want to remove only images(tile) with path 42 and row 36 from this collection. How can I do that?
Here is my code:
Map.centerObject(table);
Map.addLayer(table);
var sd = '2015-01-01';//Start Date
var ed = '2016-01-01';//End Date
var suro = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR')
.filterBounds(table)
.filterDate(sd,ed)
//.filter(ee.Filter.and(ee.Filter.notEquals('WRS_PATH',42),ee.Filter.notEquals('WRS_ROW',36)))
.filter(ee.Filter.lt('CLOUD_COVER', 45));
var sur = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR')
.filterBounds(table)
.filterDate(sd,ed)
//.filter(ee.Filter.and(ee.Filter.notEquals('WRS_PATH',42),ee.Filter.notEquals('WRS_ROW',36)))
.filter(ee.Filter.lt('CLOUD_COVER', 45))
//Map a function to mask clouds and negative values
.map(function(img){
var idd = img.id();
// Bits 3 and 5 are cloud shadow and cloud, respectively.
var cloudShadowBitMask = 1 << 3;
var cloudsBitMask = 1 << 5;
// Get the pixel QA band.
var qa = img.select('pixel_qa');
// Both flags should be set to zero, indicating clear conditions.
var mask = qa.bitwiseAnd(cloudShadowBitMask).eq(0)
.and(qa.bitwiseAnd(cloudsBitMask).eq(0));
// Return the masked image, scaled to reflectance, without the QA bands.
var img2 = img.updateMask(mask).multiply(0.0001).select("B1").rename(idd);
//Mask negative values from images
var mask2 = img2.gt(0);
return img2.multiply(mask2);
})
.toBands()
.clip(table);
Map.addLayer(sur);
var imColl_sur = sur.getInfo().bands;
print(imColl_sur);
print(imColl_sur.length);
for (var i = 0; i < imColl_sur.length; i++) {
//Image Load
var im = sur.select(imColl_sur[i]["id"]);
//var id = imColl_sur[i]["id"];
//var im = ee.Image.load(id);
//Image Properties from original collection
var idl = suro.getInfo().features[i]["properties"]["LANDSAT_ID"];
var st = suro.getInfo().features[i]["properties"]["SENSING_TIME"];
var sza = (suro.getInfo().features[i]["properties"]["SOLAR_ZENITH_ANGLE"])
.toString();
//Download
Export.image.toDrive({
image: im,
description: 'L8_surReflectance_B1_'+idl.slice(10,26)
+st.slice(11,13)+st.slice(14,16)+'_'
+sza.slice(0,2)+sza.slice(3,8),
scale: 30,
region: table,
maxPixels: 1e9
});
}
Edit:
Combining filters probably works somehow, and would be more elegant.
But you can use a second approach: create a new metadata variable combining ROW and PATH, and filter based on it:
var geometry = ee.Geometry({"type":"Polygon","coordinates":[[[-98.01249999999999,41.430123208731864],[-98.01249999999999,38.809492348693325],[-92.03593749999999,38.809492348693325],[-92.03593749999999,41.430123208731864]]],"geodesic":false,"evenOdd":true})
var sd = '2015-01-01';//Start Date
var ed = '2016-01-01';//End Date
var suro = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR')
.filterBounds(geometry)
.filterDate(sd,ed)
.map(function(image){
return image.set({'WRS_PATHROW':{'path':image.get('WRS_PATH'),
'row':image.get('WRS_ROW')}
})})
.filter(ee.Filter.neq('WRS_PATHROW', {'path':25, 'row':32}))
You can combine two filters with an ee.Filter.and to remove any images that have WRS_PATH=21 and WRS_ROW=32:
var filters = ee.Filter.and(
ee.Filter.neq('WRS_PATH',21),
ee.Filter.neq('WRS_ROW',32)
);
var suro = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR')
.filterBounds(geometry)
.filterDate(sd,ed)
.filter(filters);

Offset displayed data 4 hours forward on HighCharts x axis

I have existing charts that displays data for a full day 12:00am - 12:00am.
Now required to change one chart forward to display 4:00am - 4:00am.
I have managed to shift the x axis labels (.add(4, 'hours')) but the chart data is still in the same position.
How do I shift the charted data forward 4 hours?
Limited scope to change global variables as this will impact other charts.
var getChartSeries = function(response, chart_series_data) {
var lines = response.graph_data.lines;
for (var i=0; i<lines.length; i++) {
var series = lines[i];
var dateFormat = graphDateFormat;
if (chartIntraday) dateFormat = 'HH:mm:ss';
var currSeriesData = [];
for (var j=0; j<series.data.length; j++) {
var row = series.data[j];
var yValue = parseFloat(row[1]);
var point = {
x: moment(row[0], dateFormat).add(4, 'hours').valueOf(),
y: yValue,
displayValue: row[3]
};
currSeriesData.push(point);
}
// Set the series name, legend label, and the line identifier
var name = formatLegendLabel(series.display_name, response);
var label = response.label;
if (response.display_name != undefined && response.display_name != '') label = series.display_name + ' : ' + label;
By default chart adjusts extremes to the provided data. To display these few hours before the first point use xAxis.min property.
Live demo: http://jsfiddle.net/kkulig/xqdqooh9/
API reference: https://api.highcharts.com/highcharts/xAxis.min

(amCharts) I have a chart which data has two different prefixes. Any way to tell the function which data has which prefix?

I have an amChart chart which data is taken from two tables below it (code is modified from this SO answer). Every row the category in each tables begins with different prefix: first table begins with (Sales) and second table begins with (Market).
Here is my code for better illustration: http://jsfiddle.net/uoxbm2d3/2/
Since there are two tables and it's a column/bar chart, I need the columns/bars to be stacked based on from which table or what prefix they have. So (Sales) will only be stacked with (Sales) or, in other words, data from Table 1 will only be stacked with Table 1. Same goes with (Market)/Table 2 that will only be stacked with its siblings. Something like this:
The green/yellow/orange color is from Table 1 (Sales); the blue/purple color is from Table 2 (Market).
Is there any way to tell the function which graph comes from which table? Or at least to tell the function which data has which prefix?
Here is a piece of the script
function generateGraphsFromData(chart, chartData) {
//get the chart graph value fields as lookup table with a seen property set to false by default
//this will be used to determine what graphs need to be removed when looking at the data
var graphValueFields = chart.graphs.reduce(function(valueFields, graph) {
valueFields[graph.valueField] = 0;
return valueFields;
}, {});
var removeValueFields = [];
//create an array of new graph value fields by filtering out the categoryField
//and the currently known valueFields.
var newGraphValueFields = [];
Object.keys(chartData[0]).filter(function(key) {
return key != chart.categoryField;
}).forEach(function(valueField) {
//if this is a new graph, add it to the list
if (graphValueFields[valueField] === undefined) {
newGraphValueFields.push(valueField);
} else {
//otherwise, set the seen flag to 1
graphValueFields[valueField] = 1;
}
});
//for each new value field left over, create a graph object and add to the chart.
newGraphValueFields.forEach(function(valueField) {
var graph = new AmCharts.AmGraph();
graph.title = valueField;
graph.valueField = valueField;
graph.balloonText = "<strong>[[title]]</strong><br /> Rp[[value]]";
graph.id = valueField; //use the valueField as the ID for ease of removal
graph.type = 'column';
graph.lineAlpha = 0;
graph.fillAlphas = 0.5;
graph.bullet = "none";
graph.stackable = true; // disable stacking
chart.addGraph(graph);
});
//loop through the graphValueFields lookup table and remove all graphs that were not seen when
//rescanning the data
Object.keys(graphValueFields).forEach(function(removeGraphValueField) {
if (graphValueFields[removeGraphValueField] === 0) {
chart.removeGraph(chart.getGraphById(removeGraphValueField));
}
})
}
Once you add your new graphs and remove any old ones, you can sort by title then loop through them again to find the first non-matching prefix and set the graph's newStack property to true while setting it to false in the rest of the graphs. For example:
chart.graphs.sort(function(lhs, rhs) {
//sort by title, ensures that the sales (first table) data comes first
var lhsSalesIdx = lhs.title.indexOf('(Sales)');
var rhsSalesIdx = rhs.title.indexOf('(Sales)');
if (lhsSalesIdx !== -1 && rhsSalesIdx === -1) {
return -1;
}
else if (lhsSalesIdx === -1 && rhsSalesIdx !== -1) {
return 1;
}
else {
return lhs.title.localeCompare(rhs.title);
}
});
var stackSet = false;
//find the first instance of the market row graph and set its newStack property to true
//while clearing out the others
for (var i = 0; i < chart.graphs.length; ++i) {
if (!stackSet && chart.graphs[i].title.indexOf('(Sales)') === -1) {
chart.graphs[i].newStack = true;
stackSet = true;
}
else {
chart.graphs[i].newStack = false;
}
}
Updated fiddle - note that I set stackable back to true in your new graph loop for this to work as well.

Get the minimum value in the chart rendered for flot.js

Is it possible to get the lowest value in the chart itself assuming that the data is dynamic?Take a look at this example Fiddle.
$(function () {
var d1 = [];
for (var i = 0; i < 14; i += 0.5)
d1.push([i, Math.sin(i)]);
$.plot($("#placeholder"), [ d1]);
});
How can I get the lowest value in this line chart?
Update: It seems my earlier example didn't quite make sense please take a look at this link: https://abtw.alliancebernstein.com.tw/APAC/TW/Funds/American-Income.htm?ShareClassId=60006908 make sure to turn off Flash plugin so that Flotchart will render. Now looking at the area chart I want to get the lowest value base on the chart rendered. Is this possible?
If you save your plot object like so
var plot = $.plot($("#placeholder"), [ d1]);
you can get the minimum value from it with
var minimum = plot.getData()[0].yaxis.datamin;
The same is possible for maximum value (datamax), for the xaxis and for other data series (the index behind getData()).
http://jsfiddle.net/fenderistic/Sf5Yr/
Simply keep a lowest variable, and check throughout the for-loop to see if the value lower, if so, replace the current lowest value with it.
$(function () {
var d1 = [];
//Assuming you're always starting at zero
var lowest = Math.sin(0);
for (var i = 0; i < 14; i += 0.5) {
d1.push([i, Math.sin(i)]);
if (Math.sin(i) < lowest) {
lowest = Math.sin(i);
}
}
alert(lowest)
$.plot($("#placeholder"), [d1]);
});

Categories