ae3e / ae3e-plotly-panel

Plotly panel for Grafana

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

windrose example

DOSprojects opened this issue · comments

Hi

Is it possible to publish the windrose example from the graph?

I am not an expert and trying to figure it out without success.
Already figured out a way to decode the timestamps (not needed in this example), but I included it for demo.
An I already succeeded in creating a simple line graph with influxdb data, but no windrose.
Also, with some trouble - I am no expert, found out to create a windrose with random data.
using latest Grafana version and latest Plugin version (as proposed in another issue)

I am using this Influxdb2.0 query, but the data does only returns 2 series (time and winddirection), not the third series (windspeed)

from(bucket: "bucket01")
|> range(start: v.timeRangeStart, stop: v.timeRangeStop)
|> filter(fn: (r) => r["_measurement"] == "pws")
|> filter(fn: (r) => r["_field"] == "winddirection" or r["_field"] == "windspeed")

And this script

console.log(data)
//***** original data
var d_time = data.series[0].fields[0].values._chunks[0].data.values;
console.log(d_time);
var d_dir = data.series[0].fields[1].values._chunks[0].data.values;
console.log(d_dir);
var nd_dir = d_dir.length;
console.log(nd_dir);
//var d_spd = data.series[0].fields[2].values._chunks[0].data.values;
var d_dir = Array.from(Array(nd_dir)).map(x=>Math.random()359);
var d_spd = Array.from(Array(nd_dir)).map(x=>Math.random()105);
console.log(d_spd);
var nd_spd = d_spd.length;
console.log(nd_spd);
//
*** def result arrays
// recalc timestamps
/*
var r_time = [];
var nd_time = t1.length/2;
for (var i=0; i<nd_time; i++) {
r_time.push((d_time[i2]+d_time[i2+1]6553665536)/1000000);
}
/
let cthetanames = '["N","NO","O","ZO","Z","ZW","W","NW"]';
var ncthetas = 8;
//let ccolors = ['"#49ff00"', '"#54ff10"', '"#8dff20"', '"#b9ff2d"', '"#feff41"', '"#fedb37"', '"#feb32b"', '"#fe9322"', '"#fe6116"', '"#ff2609"', '"#ff0000"'];
//var nccolors = ccolors.length;
let cnames = ['"100<"', '"90<"', '"80<"', '"70<"', '"60<"', '"50<"', '"40<"', '"30<"', '"20<"', '"10<"', '"0<"'];
var cspds = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 500];
var ncspds = cspds.length;
var cdirs = [22.5, 67.5, 112.5, 157.5, 202.5, 247.5, 292.5, 337.5, 361];
var ncdirs = cdirs.length;
// create bins from data
var bins = []; // array [speed][dir]
for (var i=0; i<ncspds; i++){
bins.push([]);
for (var j=0; j<ncdirs; j++){
bins[i].push(0);
}
}
//
**** Loop through data and add correct bin
for (var i=0; i<nd_dir; i++){
var dir = d_dir[i];
var spd = d_spd[i];
loops:
for (var j=0; j<ncspds; j++){
if (spd<cspds[j]){
for (var k=0; k<ncdirs; k++){
if (dir<cdirs[k]){
bins[j][k]++;
break loops;
}
}
}
}
}
for (var i=0; i<cspds; i++){ // merge first and last dir (0-22.5° and 337.5-0°)
bins[i][0] = bins[i][0] + bins[i][ncdirs-1];
bins[i].pop();
}
console.log(bins);
var series = "[";
for (i=0; i<ncspds; i++) {
series = series + '{"r" : [' + bins[i] + '], "theta" : ' + cthetanames + ', "name" : ' + cnames[i] + ', "type": "barpolar"},';
// series = series + '{"r" : [' + bins[i] + '], "theta" : ' + cthetanames + ', "name" : ' + cnames[i] + ', "marker" : {"color" : ' + ccolors[i] + '}, "type": "barpolar"},';
}
series = series.slice(0, -1)
series = series + "]";
console.log(series);
var seriesjson = JSON.parse(series);
console.log(seriesjson);
return {data : seriesjson};

Thanks
Lieven Dossche

commented

Unfortunatly I'm not familiar with Influx but:

  1. Are you able to chart your timeseries (wind direction and wind speed) on a regular Grafana chart with the influx query written above
  2. Should Influx return one serie with 3 fields (data.series[0].fields[0] to data.series[0].fields[3]) or 2 series (data.series[1] and data.series[2]) with 2 fields (timestamp+value)? What does the console.log(data) at the top of your script return ?
  3. The script to process data looks good to me

Hope it helps...

Hi

Thx for the response.

the console.log(data) gives me the opportunity to check the contents of the data variable in the browser developpers console window.

For what I see is that a query should return 1 series.
This series contains 1 field with timestamps and then for every field in a query one extra field.
But if I define in my query 1, 2 or more fields, in data in only find 2 fields: 1 with the timestamps and one with the first field in the query.
Also strange is that the time field contains double the number of elements as the data field.
In fact I need to recreate the timestamps array myself combining 2 elements i and i+1 to 1 value with the formula ([ix]+[ix+1]*6553665536)/1000000.
It seems an Influxdb v2 issue, but it is strange that the built-in panels do the timestamps correctly and also can display more then one series?!?

Nevertheless, I am experimenting, as with the script above, with more interesting plotly graph types and very enthusiastic.
Very useful plugin and a huge extension of the standard panels.

tried to include some samples:
plotly0
plotly1
plotly2

Kind Regards
Lieven

THIS ISSUE WAS PURE GOLD for me!
I would never have figured out why my InfluxDB2 would not plot whatsoever.

@ae3e : It would be great if you could put the following Code / Information in your Readme concerning InfluxDB 2 query results.

They are provided in the "wrong" array format and have to be converted. Thanks to @LDossche for providing the correct path to the data!


var x_data_64 = data.series[0].fields[1].values._chunks[0].data.values;
//console.log(x_data);
var y_data_64 = data.series[1].fields[1].values._chunks[0].data.values;
//console.log(y_data);
var x_data = Array.from(x_data_64);
var y_data = Array.from(y_data_64);
var trace = {x: x_data, y: y_data }; 

@LDossche
I discovered a bug in Grafana, which maybe causes your problem. Grafana seems to ignore all other columns it receives from an influx query IF there is a column present wich is named "_value".
Try adding a simple rename to your query end and see if this helps - it did for me:
|> rename(columns: {_value: "_value_new"})

@cgfoed
Thanks for sharing.
The rename trick works for me, partially.
For a timeframe <=12h, series looks like this:
series: Array(2)

  • 0:
    -- fields: Array(6)
    --- 0: {name: "_start", type: "time", values: t, config: {…}, labels: undefined, …}
    --- 1: {name: "_stop", type: "time", values: t, config: {…}, labels: undefined, …}
    --- 2: {name: "_time", type: "time", values: t, config: {…}, labels: undefined, …}
    --- 3: {name: "_value_new", type: "number", values: t, config: {…}, labels: undefined, …}
    --- 4: {name: "_field", type: "string", values: t, config: {…}, labels: undefined, …}
    --- 5: {name: "_measurement", type: "string", values: t, config: {…}, labels: undefined, …}
    --- ...
  • 1:
    -- fields: Array(6)
    --- 0: {name: "_start", type: "time", values: t, config: {…}, labels: undefined, …}
    --- 1: {name: "_stop", type: "time", values: t, config: {…}, labels: undefined, …}
    --- 2: {name: "_time", type: "time", values: t, config: {…}, labels: undefined, …}
    --- 3: {name: "_value_new", type: "number", values: t, config: {…}, labels: undefined, …}
    --- 4: {name: "_field", type: "string", values: t, config: {…}, labels: undefined, …}
    --- 5: {name: "_measurement", type: "string", values: t, config: {…}, labels: undefined, …}
    --- ...
  • _proto
  • ...
    And I get the correct series:
    var winddirections = data.series[0].fields[3].values._chunks[0].data.values;
    var windspeeds = data.series[1].fields[3].values._chunks[0].data.values;
    Can be optimized with |> drop(columns: ["_measurement", "_start", "_stop"]), which returns fewer fields.

But with a timeframe of eg 7 days, series looks like this:
series: Array(1)

  • 0:
    -- fields: Array(6)
    --- 0: {name: "_start", type: "time", values: t, config: {…}, labels: undefined, …}
    --- 1: {name: "_stop", type: "time", values: t, config: {…}, labels: undefined, …}
    --- 2: {name: "_time", type: "time", values: t, config: {…}, labels: undefined, …}
    --- 3: {name: "_value_new", type: "number", values: t, config: {…}, labels: undefined, …}
    --- 4: {name: "_field", type: "string", values: t, config: {…}, labels: undefined, …}
    --- 5: {name: "_measurement", type: "string", values: t, config: {…}, labels: undefined, …}
    --- ...
  • _proto
  • ...

So the second series isn't returned anymore.
Perhaps some time out or too much data?
I am absolutely not a javascript or grafana or whatever specialist :)
So I am sure I don't use the tools as a pro does to investigate those issues.

But just taking one step back:
A standard line graph panel with the same flux query gives me perfectly 2 line graphs (one winddirection, one windspeed)
The Flux query should return for each panel the same data, not?
So, here, why do we have to do all those tricks here? e.g. the timestamp calculation, field renaming, ...
I tried to look at the code of the standard panels what is different or how it is done there, but that's way beyond my limits

I assume it has to do with the max. data points. Try increasing it drastically:
image

IF this helps this would be my explanation:
Max data points checks AFTER parsing the data.
Parsing the data from an influx query is done by grafana and means a major reduction in data points as it removes everything from your query, that's considered garbage like "_start", "_stop", "_measurement" etc.

If you rename "_value" the grafana importer can't find a column to parse und passes ALL the data to your panel. Now every row in every column represents a data point, reaching the "max data points" limit much sooner.

for performance reasons I would recommend dropping all unneeded data yourself by:
|> drop(columns: ["_stop", "_start"])

If you are interested, here is my issue:
grafana/grafana#30085

Indeed increasing the max datapoints solves the issue
Thx
Lieven

Hi

Thx for the response.

the console.log(data) gives me the opportunity to check the contents of the data variable in the browser developpers console window.

For what I see is that a query should return 1 series.
This series contains 1 field with timestamps and then for every field in a query one extra field.
But if I define in my query 1, 2 or more fields, in data in only find 2 fields: 1 with the timestamps and one with the first field in the query.
Also strange is that the time field contains double the number of elements as the data field.
In fact I need to recreate the timestamps array myself combining 2 elements i and i+1 to 1 value with the formula ([ix]+[ix+1]*6553665536)/1000000.
It seems an Influxdb v2 issue, but it is strange that the built-in panels do the timestamps correctly and also can display more then one series?!?

Nevertheless, I am experimenting, as with the script above, with more interesting plotly graph types and very enthusiastic.
Very useful plugin and a huge extension of the standard panels.

tried to include some samples:
plotly0
plotly1
plotly2

Kind Regards
Lieven

Hi,

How to generate the percentage and how to adjust the true north position(rotation)?
Thank you so much!!!

@cgfoed
Thanks for sharing.
The rename trick works for me, partially.
For a timeframe <=12h, series looks like this:
series: Array(2)

* 0:
  -- fields: Array(6)
  --- 0: {name: "_start", type: "time", values: t, config: {…}, labels: undefined, …}
  --- 1: {name: "_stop", type: "time", values: t, config: {…}, labels: undefined, …}
  --- 2: {name: "_time", type: "time", values: t, config: {…}, labels: undefined, …}
  --- 3: {name: "_value_new", type: "number", values: t, config: {…}, labels: undefined, …}
  --- 4: {name: "_field", type: "string", values: t, config: {…}, labels: undefined, …}
  --- 5: {name: "_measurement", type: "string", values: t, config: {…}, labels: undefined, …}
  --- ...

* 1:
  -- fields: Array(6)
  --- 0: {name: "_start", type: "time", values: t, config: {…}, labels: undefined, …}
  --- 1: {name: "_stop", type: "time", values: t, config: {…}, labels: undefined, …}
  --- 2: {name: "_time", type: "time", values: t, config: {…}, labels: undefined, …}
  --- 3: {name: "_value_new", type: "number", values: t, config: {…}, labels: undefined, …}
  --- 4: {name: "_field", type: "string", values: t, config: {…}, labels: undefined, …}
  --- 5: {name: "_measurement", type: "string", values: t, config: {…}, labels: undefined, …}
  --- ...

* _**proto**

* ...
  And I get the correct series:
  var winddirections = data.series[0].fields[3].values._chunks[0].data.values;
  var windspeeds = data.series[1].fields[3].values._chunks[0].data.values;
  Can be optimized with   |> drop(columns: ["_measurement", "_start", "_stop"]), which returns fewer fields.

But with a timeframe of eg 7 days, series looks like this:
series: Array(1)

* 0:
  -- fields: Array(6)
  --- 0: {name: "_start", type: "time", values: t, config: {…}, labels: undefined, …}
  --- 1: {name: "_stop", type: "time", values: t, config: {…}, labels: undefined, …}
  --- 2: {name: "_time", type: "time", values: t, config: {…}, labels: undefined, …}
  --- 3: {name: "_value_new", type: "number", values: t, config: {…}, labels: undefined, …}
  --- 4: {name: "_field", type: "string", values: t, config: {…}, labels: undefined, …}
  --- 5: {name: "_measurement", type: "string", values: t, config: {…}, labels: undefined, …}
  --- ...

* _**proto**

* ...

So the second series isn't returned anymore.
Perhaps some time out or too much data?
I am absolutely not a javascript or grafana or whatever specialist :)
So I am sure I don't use the tools as a pro does to investigate those issues.

But just taking one step back:
A standard line graph panel with the same flux query gives me perfectly 2 line graphs (one winddirection, one windspeed)
The Flux query should return for each panel the same data, not?
So, here, why do we have to do all those tricks here? e.g. the timestamp calculation, field renaming, ...
I tried to look at the code of the standard panels what is different or how it is done there, but that's way beyond my limits

Hi, I am having a similar issue and found a workaround.
Depending on Grafana's time range data in the console is:

  • short ranges: data.series[0].fields[1].values.col._chunks[0].data.values
  • long ranges: data.series[0].fields[1].values._chunks[0].data.values

Depending on time range, the field "col" might be missing.

My workaround to this issue is the following (done directly in Plotly script):

if (typeof data.series[0].fields[1].values.col === 'undefined'){
var myVar = data.series[0].fields[1].values._chunks[0].data.values;
}
else{
var myVar = data.series[0].fields[1].values.col._chunks[0].data.values;
};

It's probably a bit rough but thought it might help

Thank you all for sharing your code! It was very very helpful for getting into the plotly panel since I could not find another documentation where the panel is used together with influx 2.0.

However, I could not figure out how to use the code to convert the data to the correct array format (data.series[0].fields[1].values._chunks[0].data.values etc). It alway braught me "TypeError: data.series[0].fields[1].values._chunks is undefined".

So I checked the console in Firefox and found that for example the "_time" field had the following path: data.series[0].fields[2].values.source.buffer, see screenshot. Applying this to all fields, the panel worked perfectly, no adjustment of the array structure or whatsoever was needed.

grafik

Furthermore I found out that the path only contains ".source" when you apply grafana transformations to the query. When there are no transformations, the path is data.series[0].fields[2].values.buffer.

Don't know if this is helpful for someone, but I wanted to share.

Hi @Ldossche,
Im also trying to plot wind direction & wind speed in a grafana panel based on ae3e-plotly-panel.

At the moment I am unsure how to configure the panels 'data' 'layout' and 'configuration' fields. Would you mind sharing how yours looks from the dashboard editor?

@DOSprojects I am a little bit lost with your description of the queries:
My queries against InfluxDB look like this:
SELECT mean("wind.wind_speed.value") FROM "zsvwetter" WHERE $timeFilter GROUP BY time($__interval) fill(null)
and
SELECT mean("wind.wind_direction.value") FROM "zsvwetter" WHERE $timeFilter GROUP BY time($__interval) fill(null)

Both are aliased with speed and direction. But this gives no data to the script as quoted by you. At which point do I need to enter your query?

Hi Stevie

My data comes from an infuxdb. Yours seems SQL to me.

So the start of the script sends some data to the log of your browser (open the developpers aids)

// get data
console.log(data);

At least this should give you some data

Ah, now I understand: you are using flux, while I am using InfluxQL... ok, then I have to understand how to use flux...

I think you can use whatever source you want, as long as it returns you some data. I just have no idea if the format of the returned data is different. But indeed, if you want to copy my example, you need to use flux.

Yeah, I got it working, thanks! Now I have a strange issue: I played around by zooming in the graph, but I do not find any way to zoom out again - it only shows me the one wind colour a time - or something like that... Is there a way to reset this and: how to stop making the windrose zoomable at all?

ah....
config: {
"displayModeBar": false,
"staticPlot": true
}