Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Secondary y-axis title/tick-labels are shifted if layout: xaxis is added #243

Open
FSund opened this issue Feb 7, 2023 · 13 comments
Open
Labels
bug Something isn't working

Comments

@FSund
Copy link

FSund commented Feb 7, 2023

Describe the bug
If I add for example

layout:
  xaxis:
    tickformat: '%H:%M'

the title for the secondary y-axis ends up on top of the tick labels.

Without layout: xaxis

image

With layout: xaxis

image

The same issue appears if I for example add a yaxis config (from the "now line" example)

layout:
  yaxis9:
    visible: false
    fixedrange: true

Screenshots
If applicable, add screenshots to help explain your problem.

yaml

type: custom:plotly-graph
hours_to_show: current_day
refresh_interval: 10
defaults:
  entity:
    line:
      width: 2
config:
  staticPlot: true

entities:
  - entity: sensor.kaifa_active_power_import
    name: Forbruk
    marker:
      color: '#FF4560'
    statistic: mean
    type: bar
    unit_of_measurement: kW
    filters:
      - map_y_numbers: y/1000.0
  - entity: sensor.nordpool_kwh_krsand_nok_3_10_025
    attribute: raw_today
    name: Pris
    line:
      color: '#008FFB'
    filters:
      - fn: |-
          ({states}) => {
            const ys = [];
            const xs = [];
            let state = states.slice(-1)[0]
            let raw = state.attributes.raw_today
            for (let i = 0; i < raw.length; i++){
              let start = new Date(raw[i].start)
              xs.push(start);
              let end = new Date(raw[i].end)
              xs.push(end);
              ys.push(raw[i].value);
              ys.push(raw[i].value);
            }
            return { xs, ys };
          }
  - entity: sensor.nordpool_kwh_krsand_nok_3_10_025
    attribute: raw_tomorrow
    name: Pris i morgen
    line:
      color: '#00E396'
    filters:
      - fn: |-
          ({states}) => {
            const ys = [];
            const xs = [];
            let state = states.slice(-1)[0]
            let raw = state.attributes.raw_tomorrow
            for (let i = 0; i < raw.length; i++){
              let start = new Date(raw[i].start)
              start.setDate(start.getDate() - 1); // subtract one day
              xs.push(start);
              end = new Date(raw[i].end)
              end.setDate(end.getDate() - 1); // subtract one day
              xs.push(end);
              ys.push(raw[i].value);
              ys.push(raw[i].value);
            }
            return { xs, ys };
          }

Additional context
Add any other context about the problem here.

@FSund FSund added the bug Something isn't working label Feb 7, 2023
@FSund FSund changed the title Secondary y-axis is shifted when I add layout: xaxis Secondary y-axis title/tick-labels are shifted when I add layout: xaxis Feb 7, 2023
@FSund FSund changed the title Secondary y-axis title/tick-labels are shifted when I add layout: xaxis Secondary y-axis title/tick-labels are shifted if layout: xaxis is added Feb 7, 2023
@FSund
Copy link
Author

FSund commented Feb 7, 2023

I'm kind of able to fix it with the following config, with the downside that I have to manually set the y-axis label.

layout:
  xaxis:
    tickformat: '%H:%M'
  yaxis2:
    title:
      text: "NOK/kWh"
      standoff: 10
    autoshift: true
    anchor: 'free'

image

@FSund
Copy link
Author

FSund commented Feb 7, 2023

I was able to fix it in a more flexible way, by adding yaxis: y and yaxis: y2 to the respective entities (and keeping yaxis: y9 for the "now" line). Perhaps this is useful for fixing the underlying issue?

Here's the result:
image

Full card config:

type: custom:plotly-graph
hours_to_show: current_day
refresh_interval: 10
defaults:
  entity:
    line:
      width: 2
config:
  staticPlot: true
layout:
  xaxis:
    tickformat: '%H:%M'
  yaxis9:
    visible: false
    fixedrange: true
    range: [0,1]
entities:
  - entity: sensor.kaifa_active_power_import
    name: Forbruk
    yaxis: y
    marker:
      color: '#FF4560'
    statistic: mean
    type: bar
    unit_of_measurement: kW
    filters:
      - map_y_numbers: y/1000.0
  - entity: sensor.nordpool_kwh_krsand_nok_3_10_025
    attribute: raw_today
    name: Pris
    yaxis: y2
    line:
      color: '#008FFB'
    filters:
      - fn: |-
          ({states}) => {
            const ys = [];
            const xs = [];
            let state = states.slice(-1)[0]
            let raw = state.attributes.raw_today
            for (let i = 0; i < raw.length; i++){
              let start = new Date(raw[i].start)
              xs.push(start);
              let end = new Date(raw[i].end)
              xs.push(end);
              ys.push(raw[i].value);
              ys.push(raw[i].value);
            }
            return { xs, ys };
          }
  - entity: sensor.nordpool_kwh_krsand_nok_3_10_025
    attribute: raw_tomorrow
    name: Pris i morgen
    yaxis: y2
    line:
      color: '#00E396'
    filters:
      - fn: |-
          ({states}) => {
            const ys = [];
            const xs = [];
            let state = states.slice(-1)[0]
            let raw = state.attributes.raw_tomorrow
            for (let i = 0; i < raw.length; i++){
              let start = new Date(raw[i].start)
              start.setDate(start.getDate() - 1); // subtract one day
              xs.push(start);
              end = new Date(raw[i].end)
              end.setDate(end.getDate() - 1); // subtract one day
              xs.push(end);
              ys.push(raw[i].value);
              ys.push(raw[i].value);
            }
            return { xs, ys };
          }
  - entity: ""
    name: Now
    yaxis: y9
    showlegend: false
    line:
      width: 1
      dash: dot
      color: deepskyblue
    x: $ex [Date.now(), Date.now()]
    y: [0, 1]

@dbuezas
Copy link
Owner

dbuezas commented Feb 7, 2023

This looks like a bug in plotlyjs, but I'll take a look to make sure it's not me (this card).
You could also try setting the right margin manually, which is set automatically by the card depending on if any entity uses the y2 axis, but you can override it like this:

layout:
  margin:
    r: 60

Congratulations on posting the issue number 100 by the way 😁

@dbuezas
Copy link
Owner

dbuezas commented Feb 7, 2023

Interesting, I can't reproduce this. I removed the filters and plugged some thermometers and I get this:
image
Note I added the now line and the right margin still looks intact.
Which version of the card are you using? Are you sure it is the latest one?

here's my adapted yaml (same as yours but w/o attributes and filters, which should have zero effect on the plot itself)

type: custom:plotly-graph
hours_to_show: current_day
refresh_interval: 10
defaults:
  entity:
    line:
      width: 2
config:
  staticPlot: true

entities:
  - entity: sensor.openweathermap_temperature
    name: Forbruk
    marker:
      color: '#FF4560'
    statistic: mean
    type: bar
    unit_of_measurement: kW
    filters:
      - map_y_numbers: y/1000.0
  - entity: sensor.garden_temperature
    name: Pris
    line:
      color: '#008FFB'
  - entity: sensor.wintergarten_thermometer_temperature
    name: Pris i morgen
    line:
      color: '#00E396'
  - entity: ""
    name: Now
    yaxis: y9
    showlegend: false
    line:
      width: 1
      dash: dot
      color: deepskyblue
    x: $ex [Date.now(), Date.now()]
    y: [0, 1]
layout:
  yaxis9:
    visible: false
    fixedrange: true

@dbuezas
Copy link
Owner

dbuezas commented Feb 7, 2023

On a side note, nice job transforming the data from the attribute, power user 💪!
Just watch out on the missing "let" for the end variable, and missing semicolons at the end. On certain cases the missing semicolon results in very unexpected behaviour (two statements in two lines end up being interpreted as a single one in ways one doesn't expect)

@FSund
Copy link
Author

FSund commented Feb 8, 2023

I'm on v3.3.1 via HACS. I'll try to make a simpler example and see if something different happens.

Thanks for the JS pointers! It's pretty hard to debug JavaScript inside YAML :D

@FSund
Copy link
Author

FSund commented Feb 8, 2023

I managed to reproduce it with a minimal example

image

type: custom:plotly-graph
hours_to_show: current_day
layout:
  xaxis:
    tickformat: '%H:%M'
entities:
  - entity: sensor.waveplus_temperature
  - entity: sensor.waveplus_humidity

If I remove the layout-section it looks as expected

image

I've cleared my cache and done hard refreshes, but the bug still appears.

@dbuezas
Copy link
Owner

dbuezas commented Feb 8, 2023

Ok, I'll give it a try this evening. To debug the js, take a look at the debug section in the readme. You can make the browser stop and go step by step in a $fn by using the debugger statement

@dbuezas
Copy link
Owner

dbuezas commented Feb 8, 2023

Ok, this I can reproduce

@dbuezas
Copy link
Owner

dbuezas commented Feb 8, 2023

image

@dbuezas
Copy link
Owner

dbuezas commented Feb 8, 2023

Oh, I know what this is. The default right margin depends on the entities: if there is one that uses yaxis2, then the right margin is increased from 30 to 60.

Here:
image

The problem is that the yaxis an entity will use depends on its unit_of_measurement, and that is only known after processing (fetching, etc) the entity. Since you define the layout before the entities, the defaults for the layout also land before the entities, but that means their yaxes are not yet known.

This is an oversight on my side, and in the current implementation, the only thing I can do is to make the margin function throw an error if it's evaluated before the entities.
I'll have to think about this but, but in the meanwhile, you have 2 options:

  • move the layout to after the entities
  • or set the right margin manually

@FSund
Copy link
Author

FSund commented Feb 8, 2023

Nice detective work :) It's not an issue for me anymore with my current config, but nice to know the workaround of putting the layout after the entities. Never knew the order could have that effect.

@dbuezas
Copy link
Owner

dbuezas commented Feb 8, 2023

Well, the order shouldn't actually have an effect, that is my mistake.
In the other places where there are dependencies between the sections of the yaml, having the wrong order throws an error and the UI clearly indicates that the order needs to change.

This is a bit odd when caused by a default, because the error talks about flags the user didn't set themselves. I did it this way because I'm internally reusing the universal-functions' mechanisms, which tremendously simplify the handling of user-config-dependant-defaults. They were a bit of an ugly nightmare in v2.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants