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

Update tooltip #1

Merged
merged 9 commits into from
May 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 36 additions & 36 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,28 @@
repos:
- repo: local
hooks:
- id: ruff
name: ruff
description: "Run 'ruff' for extremely fast Python linting"
entry: ruff check --force-exclude
language: python
types_or: [python, pyi]
args: []
require_serial: true
additional_dependencies: []
minimum_pre_commit_version: "2.9.2"

- id: ruff-format
name: ruff-format
description: "Run 'ruff format' for extremely fast Python formatting"
entry: ruff format --force-exclude
language: python
types_or: [python, pyi]
args: []
require_serial: true
additional_dependencies: []
minimum_pre_commit_version: "2.9.2"

- id: black-fix
name: black (auto format)
entry: ./env/Scripts/black.exe
Expand All @@ -13,20 +35,6 @@ repos:
language: system
types: [python]

- id: pytest-selenium
name: pytest (selenium tests)
entry: ./env/Scripts/pytest.exe
args: ['tests/', '-k', 'selenium', '--webdriver', 'Firefox']
language: system
pass_filenames: false

- id: pytest-non-selenium
name: pytest (non-selenium tests)
entry: ./env/Scripts/pytest.exe
args: ['tests/', '-k', 'not selenium']
language: system
pass_filenames: false

- id: black
name: black
entry: ./env/Scripts/black.exe
Expand All @@ -39,30 +47,22 @@ repos:
language: system
types: [python]

- id: ruff
name: ruff
description: "Run 'ruff' for extremely fast Python linting"
entry: ruff check --force-exclude
language: python
types_or: [python, pyi]
args: []
require_serial: true
additional_dependencies: []
minimum_pre_commit_version: "2.9.2"

- id: ruff-format
name: ruff-format
description: "Run 'ruff format' for extremely fast Python formatting"
entry: ruff format --force-exclude
language: python
types_or: [python, pyi]
args: []
require_serial: true
additional_dependencies: []
minimum_pre_commit_version: "2.9.2"

- id: mypy
name: mypy
entry: ./env/Scripts/mypy.exe
language: system
types: [python]

- id: pytest-selenium
name: pytest (selenium tests)
entry: ./env/Scripts/pytest.exe
args: ['tests/', '-k', 'selenium', '--webdriver', 'Firefox', '--testmon']
language: system
pass_filenames: false

- id: pytest-non-selenium
name: pytest (non-selenium tests)
entry: ./env/Scripts/pytest.exe
args: ['tests/', '-k', 'not selenium', '--testmon']
language: system
pass_filenames: false
2 changes: 1 addition & 1 deletion .python-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.12.0
3.12.3
111 changes: 111 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,117 @@ tooltip(app10, style=custom_style, graph_ids=["graph-id"], template=template, de
For more examples, refer to the provided `dash_tooltip_demo.py` and check out [Plotly’s Text and Annotations documentation](https://plotly.com/python/text-and-annotations/#styling-and-coloring-annotations), which provides a wealth of information on customizing the appearance of annotations.
Refer to the [Plotly Annotation Reference](https://plotly.com/python/reference/layout/annotations/) for a comprehensive guide on available styling attributes and how to apply them.

## Template updating

Tooltip content can be updated to match with selected data in a dynamic Dash app:
```python
GRAPH_ID = "scatter-plot16a"

# Sample DataFrame with DatetimeIndex
date_range = pd.date_range(start="2025-01-01", periods=5)
df = pd.DataFrame(
{
"x": [1, 2, 3, 4, 5],
"y": [2, 4, 6, 8, 10],
"z": [3, 6, 9, 12, 15],
"a": [4, 8, 12, 16, 20],
"b": [5, 10, 15, 20, 25],
},
index=date_range,
)

# Initialize the Dash app
app16 = dash.Dash(__name__)

# Define the layout
app16.layout = html.Div(
[
html.Label("Select X and Y columns:"),
dcc.Dropdown(
id="x-column",
options=[{"label": col, "value": col} for col in df.columns],
placeholder="Select X axis data",
),
dcc.Dropdown(
id="y-column",
options=[{"label": col, "value": col} for col in df.columns],
placeholder="Select Y axis data",
),
dcc.Graph(
id=GRAPH_ID,
style={"width": "600px", "height": "600px"},
config={
"editable": True,
"edits": {"shapePosition": True, "annotationPosition": True},
},
),
]
)

# Create a tooltip instance
tooltip_instance16 = tooltip(app16, graph_ids=[GRAPH_ID])

# Define callback to update the scatter plot
@app16.callback(
Output(GRAPH_ID, "figure", allow_duplicate=True),
[Input("x-column", "value"), Input("y-column", "value")],
prevent_initial_call=True,
)
def update_scatter_plot(x_column, y_column):
if not x_column or not y_column:
raise PreventUpdate # Prevent update if either dropdown is not selected

non_selected_columns = [
col for col in df.columns if col not in [x_column, y_column]
]
customdata = df[non_selected_columns].apply(
lambda row: "<br>".join(
f"{col}: {val}" for col, val in zip(non_selected_columns, row)
),
axis=1,
)
# gives (depending on selected entries):
# 2022-01-01 x: 1<br>z: 3<br>b: 5
# 2022-01-02 x: 2<br>z: 6<br>b: 10
# ...

# New template, to match selected data entries
template = (
"<b>Date</b>: %{customdata}<br>"
+ f"<b>{x_column}: %{{x}}<br>"
+ f"{y_column}: %{{y}}</b><br>"
)
# gives (depending on selected entries):
# <b>Date</b>: %{customdata}<br><b>x: %{x}<br><b>a</b>: %{y}<br>

# Update template for new tooltips
tooltip_instance16.update_template(graph_id=GRAPH_ID, template=template)

trace = go.Scatter(
x=df[x_column],
y=df[y_column],
mode="markers",
marker=dict(color="blue"),
customdata=df.index.strftime("%Y-%m-%d %H:%M:%S") + "<br>" + customdata,
# Include date and time with other data
hovertemplate=template,
)
layout = go.Layout(
title="Scatter Plot",
xaxis=dict(title=x_column),
yaxis=dict(title=y_column),
hovermode="closest",
height=800,
width=800,
)
return {"data": [trace], "layout": layout}


# Run the app
if __name__ == "__main__":
app16.run_server(debug=False, port=8196)
```

## Handling Log Axes

Due to a long-standing bug in Plotly (see [Plotly Issue #2580](https://github.com/plotly/plotly.py/issues/2580)), annotations (`fig.add_annotation`) may not be placed correctly on log-scaled axes. The `dash_tooltip` module provides an option to automatically correct the tooltip placement on log-scaled axes via the `apply_log_fix` argument in the `tooltip` function. By default, `apply_log_fix` is set to `True` to enable the fix.
Expand Down
16 changes: 10 additions & 6 deletions dash_qt_demo2.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import http.client
import threading
import os
import sys
import threading
import time

import dash
import numpy as np
import plotly.graph_objects as go
from dash import dcc, html
from PyQt6.QtCore import QUrl
from PyQt6.QtWebEngineWidgets import QWebEngineView
from PyQt6.QtWidgets import QApplication, QFileDialog, QMainWindow
import plotly.graph_objects as go

from dash_tooltip import tooltip

dash_port = 8050
Expand Down Expand Up @@ -89,8 +90,8 @@ def create_dash_app():
layout_margin = {"l": 25, "r": 25, "t": 25, "b": 25}

# Creating a grid of x and y values
x = np.linspace(0, 10, 100)
y = np.linspace(0, 10, 100)
x = np.linspace(0, 10, 400)
y = np.linspace(0, 10, 400)
X, Y = np.meshgrid(x, y)

# Calculate Z as a function of X and Y
Expand All @@ -102,7 +103,7 @@ def create_dash_app():
z=Z,
x=x,
y=y,
colorscale="Viridis"
colorscale="Viridis",
# You can change the colorscale as needed
),
layout=go.Layout(margin=layout_margin),
Expand Down Expand Up @@ -151,7 +152,10 @@ def create_dash_app():
template1 = "x: %{x:.2f},<br>y: %{y:.2f}"
tooltip(app, template=template1, graph_ids=["example-graph1"])
template2 = "x: %{x:.2f},<br>y: %{y:.2f},<br>z: %{z:.3f}"
tooltip(app, template=template2, graph_ids=["example-graph2"])
tooltip_style = {
"bgcolor": "rgba(255, 255, 255, 0.2)",
}
tooltip(app, style=tooltip_style, template=template2, graph_ids=["example-graph2"])
return app


Expand Down
Loading
Loading