Render a Plotly figure. Args: fig: A Plotly figure object.
(fig, size: float = 1.0, component_id: str | None = None, **kwargs)
| 520 | |
| 521 | @with_render_tracking("plotly") |
| 522 | def plotly(fig, size: float = 1.0, component_id: str | None = None, **kwargs) -> ComponentReturn: # noqa: C901 |
| 523 | """ |
| 524 | Render a Plotly figure. |
| 525 | |
| 526 | Args: |
| 527 | fig: A Plotly figure object. |
| 528 | """ |
| 529 | |
| 530 | try: |
| 531 | import time |
| 532 | |
| 533 | start_time = time.time() |
| 534 | logger.debug("[PLOTLY] Starting plotly render") |
| 535 | logger.debug(f"[PLOTLY] Created plot component with id {component_id}") |
| 536 | |
| 537 | # Optimize the figure for web rendering |
| 538 | optimize_start = time.time() |
| 539 | |
| 540 | # Reduce precision of numeric values |
| 541 | for trace in fig.data: |
| 542 | for attr in ["x", "y", "z", "lat", "lon"]: |
| 543 | if hasattr(trace, attr): |
| 544 | values = getattr(trace, attr) |
| 545 | if isinstance(values, list | np.ndarray): |
| 546 | if np.issubdtype(np.array(values).dtype, np.floating): |
| 547 | setattr(trace, attr, np.round(values, decimals=4)) |
| 548 | |
| 549 | # Optimize marker sizes |
| 550 | if hasattr(trace, "marker") and hasattr(trace.marker, "size"): |
| 551 | if isinstance(trace.marker.size, list | np.ndarray): |
| 552 | # Scale marker sizes to a reasonable range |
| 553 | sizes = np.array(trace.marker.size) |
| 554 | if len(sizes) > 0: |
| 555 | _min_size, max_size = ( |
| 556 | 5, |
| 557 | 20, |
| 558 | ) # Reasonable size range for web rendering |
| 559 | with np.errstate(divide="ignore", invalid="ignore"): |
| 560 | scaled_sizes = (sizes / max_size) * max_size |
| 561 | scaled_sizes = np.nan_to_num( |
| 562 | scaled_sizes, nan=0.0, posinf=0.0, neginf=0.0 |
| 563 | ) |
| 564 | |
| 565 | # Ensure there's a minimum size if needed |
| 566 | scaled_sizes = np.clip(scaled_sizes, 1, max_size) |
| 567 | |
| 568 | trace.marker.size = scaled_sizes.tolist() |
| 569 | |
| 570 | # Optimize layout |
| 571 | if hasattr(fig, "layout"): |
| 572 | # Set reasonable margins |
| 573 | fig.update_layout( |
| 574 | margin={"l": 50, "r": 50, "t": 50, "b": 50}, autosize=True |
| 575 | ) |
| 576 | |
| 577 | # Optimize font sizes |
| 578 | fig.update_layout(font={"size": 12}, title={"font": {"size": 14}}) |
| 579 |