andymchugh / andrewbmchugh-flow-panel

Apache License 2.0
23 stars 2 forks source link

feature request: measurement-based dynamics #67

Open bijwaard opened 1 month ago

bijwaard commented 1 month ago

Hi Andy,

The flow panel gets more complete every time I update, great work!

It would be nice to be able to add dynamics to the flow from measurements similar to what the marcuscalidus-svg-panel does. To integrate this functionality, I can imagine the following updates to flow panel, hopefully keeping effort on the flow panel side minimal while adding much animation freedom for the users:

Kind regards, Dennis

bijwaard commented 2 weeks ago

Some further remarks:

The dynamic SVG that I was thinking of are:

allomorphy commented 2 weeks ago

Amazing @andymchugh if this could be feasible for you and thanks to @bijwaard for that suggestion.

Our first use case involves a version of a gauge like the standard Grafane gauge but it needs to embed on a seelected graphical background. Would love to do that with the amazing flow-panel.

All for this brave new world of dynamic widgets in flow-panel 👏

E

andymchugh commented 2 weeks ago

Can you give a few concrete examples of what you want to drive? i.e. in your phasor do each of the colored lines have unique ids? do you want to change their full 'path' attribute based on a single data reference, what is your algorithm for going from data to cell attributes, etc. With concrete examples of your data input, your svg and how you would change your cell attriutes I can have a think what would work with the general panel concepts. It's much harder to take an abstract ask because by the time it's translated into something functional it might no longer do the thing you really needed.

bijwaard commented 2 weeks ago

Hi Andy,

Sorry for the abstract description, but I was unsure if my specific use case could be generalized from a YAML description alone, that is why I thought of Javascript functions for panel-user, inspired by my usage of the SVG plugin.

Concretely, in my use-case I want to drive the end-point of a line (phasor) from 2 measurements. The input consists of two values, say x and y, that would drive the end-point of the arrow. My SVG for the first phasor line L1 looks as follows:

<marker id="markerArrowRed" markerWidth="3" markerHeight="3" refX="1.5" refY="1.5" orient="auto">
          <path d="M1,0 L1,3 L2,1.5 L1,0" style="fill: red" />
</marker>
<line id="L1" x1="100" y1="100" x2="100" y2="45" style="stroke-width: 3px; stroke: red; marker-end: url(#markerArrowRed);"

<!-- some other phasor lines for L2, L3 and Neutral  with different color -->

<circle id="circle100" style="stroke: black; fill: lightgrey; fill-opacity:0.5" cx="100" cy="100" r="100"/>
<text id="label100" x="100" y="200" fill="black" text-anchor="middle" style="text-anchor: middle; dominant-baseline: middle;">5</text>

<!-- some other smaller circles and corresponding labels that show the magnitude at that level -->

Essentially, I would like to drive the x2 and y2 of the L1 line endpoint from the measurements x and y. Since the measurement values can have a wide range, the magnitude sqrt(x^2+y^2) may need to be scaled down to a certain zoom-level to be within range of the circles in the diagram. The same goes for other phasors like L2, L3 (and Neutral for current). The phasors can be either for current, voltage or power.

In my original SVG panel I used javascript to change the zoom-level using the middle-mouse actions up/down while hoovering above the diagram and adjust the numbers on the circles, and a click on the area to fix the zoom-level to the maximum for all phasors in the same plot. Auto-scaling the magnitude could also be an option in most cases, but they may give false interpretation when comparing phasor plots of the same type (e.g. power of transformer station and a single house).

The other use-case from @allomorphy with a gauge, would just drive the end-point of the line on the rim of a circle/ellipse, this would also change x2 and y2 in a more proportional way from one measurement to stay on the circle/ellipse boundary.

Kind regards, Dennis

andymchugh commented 2 weeks ago

great, thanks for info. will have a think...

andymchugh commented 1 week ago

Just a heads up, work on this is in progress in the form of a general purpose attribute drive where your javascript (defined in the yaml) receives data+grafanaVariables+svgElementCopy and you get to return attributes to be added to the svgElement.

If you need to drive more than just svg-element-attributes do say. I think this meets the usecase described above...

bijwaard commented 1 week ago

Hi Andy, Thanks for the heads up and support! A callback function definition in the yaml file sounds great.

At the moment only svg-element attributes (x2 and y2 of the phasor lines) and text labels (the magnitude label such as 5 below the circles) would be driven by measurements.

<line id="L1" x1="100" y1="100" x2="100" y2="45" style="stroke-width: 3px; stroke: red; marker-end: url(#markerArrowRed);"
<text id="label100" x="100" y="200" fill="black" text-anchor="middle" style="text-anchor: middle; dominant-baseline: middle;">5</text>

Some questions:

Btw. We may be able to calculate the maximum magnitude in the current grafana refresh and only use it in the next grafana refresh to update the circle labels and scale the phasor lines accordingly. In that case sequence of callbacks probably does not matter much.

Kind regards, Dennis

andymchugh commented 1 week ago

yaml multi-line: yes

multiple dataRefs: yes

multiple elements: no. Don't yet understand why you'd need that. If there's some shared scalar i'd have thought that's one line of javascript you'd have in the function. Say if its more complex than that?

remembered values: yes within the function. There'll be a state object that can be built up. Not planned across functions but open if there's a compelling argument.

label text: not planned as part of this as text tends not to be in attributes. Can you explain a bit more why you need a bespoke text drive?

predefined sequence: kindof in that the svg is traversed depth first but I wouldn't expect you to rely on it as it sounds very brittle. It has some meaning for things like double arrowed connectors where the three path elements are ordered body-leftArrow-rightArrow.

additional args: I guess you are thinking about a shared javascript function and those args being like 'template specialisation'. That could be added. Is this the usecase you are thinking of?

andymchugh commented 1 week ago

I've looked again at your circle legends and I think understand your need for bespoke label text too. Will think on how to incorporate it

bijwaard commented 6 days ago

multiple elements: Driving multiple elements from one function is not crucial, when we can easily re-use the same function on multiple SVG elements, e.g. with a given argument.

Remembered values: when we cannot remember state across functions, we may will probably create one function that drives functionality for different things based on a given argument.

Label text:

The text fields would be used for showing magnitude scale of the phasor lines, e.g. when the phasor denotes power and you often don't know beforehand what the range of amount will be, can be 100W, 1kW, 10kW or even a few 100kW on a substation. With autoscaling you could automatically apply a scaling factor depending on the current value range and more easily see the line differences:

An alternative to autoscaling by remembering magnitude could be to set a maximum magnitude from a grafana template variable and display that value on the outer circle of the phasor plot and add it as a callback function argument. That would mean driving the label value from a template variable. This template variable would then also be an additional argument for the callback functions.

predetermined sequence: agree that relying on this sequence is asking for trouble later

additional args: depending on the options above 1 or two additional arguments for the callback functions would be help:

andymchugh commented 6 days ago

Great. That makes sense. Thanks for info.