Skip to content

feat - Add tight_layout support to reduce margins and improve layout spacing(new)#1182

Merged
Saksham-Sirohi merged 4 commits into
fossasia:devfrom
Manik-Khajuria-5:Tight-Layout-for_visdom
Jun 11, 2026
Merged

feat - Add tight_layout support to reduce margins and improve layout spacing(new)#1182
Saksham-Sirohi merged 4 commits into
fossasia:devfrom
Manik-Khajuria-5:Tight-Layout-for_visdom

Conversation

@Manik-Khajuria-5

@Manik-Khajuria-5 Manik-Khajuria-5 commented Apr 12, 2026

Copy link
Copy Markdown
Member

Description

This PR adds a tight_layout option to Visdom plots, leveraging Plotly's built-in automargin instead of hardcoding margins.

Changes:

  • _opts2layout updates:

    • Supports tight_layout=True in opts
    • Sets margins to minimal values (keeps 30px top margin for title/modebar)
    • Existing explicit margin options (marginleft, etc.) still override defaults
  • _axisformat updates:

    • Enables Plotly automargin on 2D axes when tight_layout=True
    • Plotly dynamically calculates exact margin needed per-axis to avoid label clipping

Motivation and Context

Visdom plots often have excessive default margins (60px on all sides), reducing usable space.
As noted in #724, both matplotlib (tight_layout()) and Plotly (automargin) handle this natively.
This feature enables Plotly's built-in layout intelligence via a simple opt-in flag no hardcoded zero margins or extra API methods needed.

Fixes: #724


How Has This Been Tested?

  • Ran test_tight_layout.py with side-by-side comparison of tight vs normal plots
  • Verified margins reduce correctly with tight_layout=True
  • Verified long axis labels are not clipped (automargin expands as needed)
  • Verified explicit margin overrides still work alongside tight_layout=True
  • Verified 3D plots are unaffected

Screenshots (if appropriate):

screenshot-2026-06-01_21-35-15 screenshot-2026-06-01_21-35-20

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Code refactor or cleanup (changes to existing code for improved readability or performance)

Checklist:

  • I adapted the version number under py/visdom/VERSION according to Semantic Versioning
  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.

Summary by Sourcery

Add a tight_layout option to Visdom plots to reduce default margins and leverage Plotly’s automatic margin handling.

New Features:

  • Introduce a tight_layout option in Visdom plotting options to enable more compact plot layouts using Plotly’s automargin.

Enhancements:

  • Adjust default plot margins when tight_layout is enabled while preserving existing explicit margin overrides.
  • Enable Plotly axis automargin on 2D axes when tight_layout is requested to prevent label clipping without manual margin tuning.

@sourcery-ai

sourcery-ai Bot commented Apr 12, 2026

Copy link
Copy Markdown
Contributor
Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Adds an optional tight_layout flag to Visdom Plotly layouts that reduces default margins and enables Plotly’s automargin behavior on 2D axes while preserving existing explicit margin overrides and 3D layout behavior.

Flow diagram for tight_layout handling in _opts2layout

flowchart TD
    A[opts input] --> B[Read tight_layout from opts]
    B --> C{is3d?}

    C -- Yes --> D[Use 3D defaults:
margin.l = opts.marginleft or 0
margin.b = opts.marginbottom or 0
margin.t = opts.margintop or 20
margin.r = opts.marginright or 60]

    C -- No --> E{tight_layout?}

    E -- No --> F[Use 2D defaults:
margin.l = opts.marginleft or 60
margin.b = opts.marginbottom or 60
margin.t = opts.margintop or 60
margin.r = opts.marginright or 60]

    E -- Yes --> G[Use tight 2D defaults:
margin.l = opts.marginleft or 0
margin.b = opts.marginbottom or 0
margin.t = opts.margintop or 30
margin.r = opts.marginright or 0]

    D --> H[Build layout dict]
    F --> H
    G --> H

    H --> I[axis automargin = opts.tight_layout or None in _axisformat]
    I --> J[Return final layout and axes]
Loading

File-Level Changes

Change Details Files
Add tight_layout-aware margin defaults to the Visdom Plotly layout.
  • Introduce a tight boolean derived from opts['tight_layout'] in layout generation.
  • Adjust default left, right, top, and bottom margins to smaller values when tight_layout is enabled, while keeping existing explicit margin options as overrides.
  • Preserve the existing 3D-specific margin defaults and ensure tight_layout only affects 2D plots by checking is3d.
py/visdom/__init__.py
Enable Plotly automargin for axes when tight_layout is requested.
  • Pass a new automargin field in axis configuration, driven by opts['tight_layout'].
  • Ensure automargin is only enabled when tight_layout is True and left unset otherwise so Plotly uses its defaults.
py/visdom/__init__.py

Assessment against linked issues

Issue Objective Addressed Explanation
#724 Add a Visdom option equivalent to matplotlib's tight_layout() that, when enabled, automatically reduces blank margins/padding in windows without requiring manual opts.margin* settings for each window.

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@Manik-Khajuria-5

Copy link
Copy Markdown
Member Author

@marcoag I have written clean code but as discussed pylinter check breaks as mentioned in #1173

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 2 issues, and left some high level feedback:

  • In tight_layout, the env parameter defaults to None and is passed through directly to get_window_data/_update_window_tight_layout; consider normalizing env to env or self.env for consistency with the rest of the API.
  • _update_window_tight_layout currently overwrites all margins with zeros regardless of any existing explicit margin configuration or tight_layout-related logic in _opts2layout; consider reusing _opts2layout or conditionally preserving user-specified margins to avoid surprising layout changes.
  • When calling self._send in _update_window_tight_layout, you set opts to {"tight_layout": True} which discards any existing opts associated with the window; consider merging this flag into the existing opts instead of replacing them.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `tight_layout`, the `env` parameter defaults to `None` and is passed through directly to `get_window_data`/`_update_window_tight_layout`; consider normalizing `env` to `env or self.env` for consistency with the rest of the API.
- `_update_window_tight_layout` currently overwrites all margins with zeros regardless of any existing explicit margin configuration or `tight_layout`-related logic in `_opts2layout`; consider reusing `_opts2layout` or conditionally preserving user-specified margins to avoid surprising layout changes.
- When calling `self._send` in `_update_window_tight_layout`, you set `opts` to `{"tight_layout": True}` which discards any existing `opts` associated with the window; consider merging this flag into the existing opts instead of replacing them.

## Individual Comments

### Comment 1
<location path="py/visdom/__init__.py" line_range="267-272" />
<code_context>
+            layout["xaxis"] = {}
+        if not layout.get("yaxis"):
+            layout["yaxis"] = {}
+        layout["xaxis"]["automargin"] = True
+
     if opts.get("stacked"):
</code_context>
<issue_to_address>
**suggestion:** Consider enabling `automargin` on both x and y axes for tight 2D layouts.

In the `tight and not is3d` branch, only `xaxis.automargin` is set while `yaxis` is left unchanged. For tight layouts this can cause asymmetric behavior and potential clipping on the vertical side. Please apply the same `automargin` logic to `yaxis` (including initializing the dict if needed) so both axes behave consistently.

```suggestion
    if tight and not is3d:
        if not layout.get("xaxis"):
            layout["xaxis"] = {}
        if not layout.get("yaxis"):
            layout["yaxis"] = {}
        layout["xaxis"]["automargin"] = True
        layout["yaxis"]["automargin"] = True
```
</issue_to_address>

### Comment 2
<location path="py/visdom/__init__.py" line_range="1646-1650" />
<code_context>
+        if raw is None:
+            return
+        try:
+            win_map = json.loads(raw) if isinstance(raw, str) else raw
+        except (ValueError, TypeError):
+            return
+        results = {}
+        for win_id, win_info in win_map.items():
+            if not isinstance(win_info, dict) or win_info.get("type") != "plot":
+                continue
</code_context>
<issue_to_address>
**issue (bug_risk):** Guard against non-dict `win_map` before iterating with `.items()` in `tight_layout`.

After decoding `raw`, this code assumes `win_map` is a mapping and calls `.items()` unconditionally. If the backend returns something else (e.g., a list or `None`), this will raise an `AttributeError`. Please add a type check (e.g., `isinstance(win_map, dict)`) and return early if it fails to ensure robustness against unexpected responses.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread py/visdom/__init__.py Outdated
Comment thread py/visdom/__init__.py Outdated
@Manik-Khajuria-5 Manik-Khajuria-5 marked this pull request as draft April 12, 2026 13:34
@Manik-Khajuria-5 Manik-Khajuria-5 marked this pull request as ready for review April 12, 2026 13:43

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've left some high level feedback:

  • The runtime tight_layout update sets all margins to 0 (including top) whereas _opts2layout keeps a 30px top margin when a title exists, which may lead to inconsistent behavior and potential title clipping between newly created plots and retrofitted ones.
  • In _update_window_tight_layout, you send "opts": {"tight_layout": True} on update, which will discard any existing opts for that window; consider merging with existing options instead of overwriting them to avoid losing configuration.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The runtime `tight_layout` update sets all margins to 0 (including top) whereas `_opts2layout` keeps a 30px top margin when a title exists, which may lead to inconsistent behavior and potential title clipping between newly created plots and retrofitted ones.
- In `_update_window_tight_layout`, you send `"opts": {"tight_layout": True}` on update, which will discard any existing `opts` for that window; consider merging with existing options instead of overwriting them to avoid losing configuration.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@Manik-Khajuria-5

Copy link
Copy Markdown
Member Author

@marcoag Can u Please review this PR ?

@vedansh-5 vedansh-5 requested a review from Copilot April 23, 2026 19:51
@vedansh-5

Copy link
Copy Markdown
Member

Hi @Manik-Khajuria-5, I triggered a copilot review - please address its concerns.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a tight_layout feature to Visdom plot layouts to reduce default Plotly margins and enable axis automargin, plus a client API (viz.tight_layout) to apply the behavior to existing windows.

Changes:

  • Extend _opts2layout to support opts["tight_layout"]=True with reduced default margins and axis automargin (2D).
  • Add _update_window_tight_layout(...) to update an existing window’s Plotly layout in-place.
  • Add public tight_layout(win=None, env=None) to apply tight layout to one window or all plot windows in an env.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread py/visdom/__init__.py Outdated
Comment thread py/visdom/__init__.py Outdated
Comment thread py/visdom/__init__.py Outdated
@Manik-Khajuria-5 Manik-Khajuria-5 changed the base branch from master to dev May 6, 2026 12:07

@Jayantparashar10 Jayantparashar10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The _opts2layout change handles tight_layout=True correctly t: 30 when a title exists, t: 0 otherwise. Good.

But viz.tight_layout(win=...) goes through a completely different path _update_window_tight_layout fetches the current window layout and manually overwrites the margin:

margin.update({"l": 0, "r": 0, "b": 0, "t": 0})

This always sets t: 0 regardless of whether the window has a title.

Tested locally — calling viz.tight_layout(win=w) on a titled plot clips the title entirely.

The fix is straightforward since you already fetched the layout:

  has_title = bool(layout.get("title"))
  margin.update({"l": 0, "r": 0, "b": 0, "t": 30 if has_title else 0})

@Manik-Khajuria-5

Copy link
Copy Markdown
Member Author

@Jayantparashar10 Done Thanks for review!

@Jayantparashar10 Jayantparashar10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tight_layout() is missing @pytorch_wrap without it the method won't be recorded in offline mode, unlike every other public Visdom method. Add @pytorch_wrap decorator above the method definition to match the convention.

@Manik-Khajuria-5

Copy link
Copy Markdown
Member Author

@Jayantparashar10 Thanks for review I checked in codebase methods like scatter , line , image need it but tight_layout is closer to utility methods like save, close, delete_env, and more So it is not needed

@Jayantparashar10 Jayantparashar10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The _opts2layout changes are clean and the fallback to existing marginleft /right /top /bottom opts still works. LGTM

Image

@rajnisht7 rajnisht7 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

as seen the modbar is colliding with the title

Image

and the graph as well when no title is passed

@Manik-Khajuria-5

Copy link
Copy Markdown
Member Author

@rajnisht7 Thanks for review . I have fixed it kindly review it again
screenshot-2026-05-25_19-08-55
screenshot-2026-05-25_19-08-49

@rajnisht7 rajnisht7 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Manik-Khajuria-5 when resizing the pane to minimum width, visdom is crashing

also still the title is overlapping with the mod bar

Screencast_20260530_102303.online-video-cutter.com.mp4

@Manik-Khajuria-5

Manik-Khajuria-5 commented May 30, 2026

Copy link
Copy Markdown
Member Author

@rajnisht7 Thanks for reveiw I have fixed recommended suggestion
image
here is the result

@Manik-Khajuria-5 Manik-Khajuria-5 marked this pull request as draft May 30, 2026 12:57
@Manik-Khajuria-5 Manik-Khajuria-5 force-pushed the Tight-Layout-for_visdom branch from e6d3ae8 to 441b217 Compare June 1, 2026 16:18
@Manik-Khajuria-5 Manik-Khajuria-5 marked this pull request as ready for review June 1, 2026 16:18
@Manik-Khajuria-5

Copy link
Copy Markdown
Member Author

Hey @rajnisht7, you were right Plotly already has built-in tight layout support via automargin on axes. Thanks for pointing this out in the last meeting! I've
simplified the implementation to just leverage that instead of hardcoding margins. Much cleaner now.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've left some high level feedback:

  • Consider validating or normalizing opts['tight_layout'] to a strict boolean before using it (rather than relying on general truthiness), so unexpected types (e.g., strings from JSON) don’t silently trigger tight layout and automargin.
  • The tightened margin defaults are now embedded directly in _opts2layout; if other plot types or future layout options need similar behavior, it might be worth centralizing these margin presets (normal vs tight vs 3D) into named constants or a small helper for easier tuning.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Consider validating or normalizing `opts['tight_layout']` to a strict boolean before using it (rather than relying on general truthiness), so unexpected types (e.g., strings from JSON) don’t silently trigger tight layout and `automargin`.
- The tightened margin defaults are now embedded directly in `_opts2layout`; if other plot types or future layout options need similar behavior, it might be worth centralizing these margin presets (normal vs tight vs 3D) into named constants or a small helper for easier tuning.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@Manik-Khajuria-5

Copy link
Copy Markdown
Member Author

@rajnisht7 Can u please review this PR too

@tonypzy tonypzy left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@Saksham-Sirohi Saksham-Sirohi merged commit 1d8d749 into fossasia:dev Jun 11, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

"Tight layout" for visdom?

7 participants