Skip to content

feat: add visualization layer with altair#5

Merged
ravishan16 merged 7 commits intomainfrom
feature/visualization-layer-3
Oct 4, 2025
Merged

feat: add visualization layer with altair#5
ravishan16 merged 7 commits intomainfrom
feature/visualization-layer-3

Conversation

@ravishan16
Copy link
Owner

This PR resolves #3 by adding a visualization layer to the Streamlit app using Altair.

- Add altair for chart generation
- Recommend chart based on dataframe schema
- Allow user to customize chart
- Add tests for visualization module
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @ravishan16, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a significant enhancement to the Streamlit application by adding a robust data visualization layer. Leveraging Altair, users can now interactively generate various charts directly from their dataframes, with intelligent recommendations for chart types and axes. This greatly improves the app's capability to present and analyze data visually.

Highlights

  • Visualization Layer Added: A new visualization layer has been integrated into the Streamlit application, allowing for dynamic data charting.
  • Altair Integration: The Altair library is now used to generate various types of charts, including bar, line, scatter, histogram, and heatmap.
  • Dynamic Chart Recommendations: The application can now recommend suitable chart types and axes based on the structure of the displayed DataFrame.
  • New Module and Dependencies: A new module src/visualization.py has been added to handle visualization logic, and altair has been included in requirements.txt.
  • Unit Tests for Visualization: Comprehensive unit tests have been added for the make_chart and get_chart_recommendation functions to ensure their correctness.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@codecov-commenter
Copy link

codecov-commenter commented Oct 2, 2025

Codecov Report

❌ Patch coverage is 20.07913% with 808 lines in your changes missing coverage. Please review.
✅ Project coverage is 22.87%. Comparing base (06d94e8) to head (58fba80).

Files with missing lines Patch % Lines
src/ui/tabs.py 0.00% 225 Missing ⚠️
src/core.py 0.00% 165 Missing ⚠️
src/ui/components.py 0.00% 122 Missing ⚠️
src/visualization.py 61.88% 78 Missing and 23 partials ⚠️
src/ui/sidebar.py 0.00% 100 Missing ⚠️
src/ai_service.py 20.40% 39 Missing ⚠️
src/app_logic.py 0.00% 27 Missing ⚠️
src/ai_engines/base.py 51.72% 11 Missing and 3 partials ⚠️
src/ui/login_style.py 0.00% 3 Missing ⚠️
src/ui/style.py 0.00% 3 Missing ⚠️
... and 4 more
Additional details and impacted files
@@            Coverage Diff             @@
##             main       #5      +/-   ##
==========================================
+ Coverage   22.07%   22.87%   +0.80%     
==========================================
  Files          14       24      +10     
  Lines         956     1893     +937     
  Branches      149      330     +181     
==========================================
+ Hits          211      433     +222     
- Misses        729     1415     +686     
- Partials       16       45      +29     
Flag Coverage Δ
unittests 22.87% <20.07%> (+0.80%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a visualization layer using Altair, which is a great addition for data exploration within the app. The implementation is well-structured, with a new module for visualization logic and corresponding unit tests. I've identified a high-severity bug that could cause the application to crash under certain conditions, along with a couple of medium-severity suggestions to improve user experience and code maintainability. Overall, this is a solid feature addition.

selected_x_axis = st.selectbox("X-axis", x_axis_options, index=x_axis_options.get_loc(x_axis) if x_axis else 0)

y_axis_options = cols
selected_y_axis = st.selectbox("Y-axis", y_axis_options, index=y_axis_options.get_loc(y_axis) if y_axis else 1)
Copy link
Contributor

Choose a reason for hiding this comment

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

high

This line can cause the application to crash. If y_axis is None (when no recommendation is available) and the result DataFrame has only one column, y_axis_options will have a length of 1. The code then attempts to use index=1, which is out of bounds and raises an exception. The default index should be handled safely to prevent this.

    selected_y_axis = st.selectbox("Y-axis", y_axis_options, index=y_axis_options.get_loc(y_axis) if y_axis else min(1, len(y_axis_options) - 1))

Comment on lines 10 to 37
if chart_type == "Bar":
chart = alt.Chart(df).mark_bar().encode(
x=x,
y=y,
)
elif chart_type == "Line":
chart = alt.Chart(df).mark_line().encode(
x=x,
y=y,
)
elif chart_type == "Scatter":
chart = alt.Chart(df).mark_circle().encode(
x=x,
y=y,
)
elif chart_type == "Histogram":
chart = alt.Chart(df).mark_bar().encode(
x=alt.X(x, bin=True),
y='count()',
)
elif chart_type == "Heatmap":
chart = alt.Chart(df).mark_rect().encode(
x=x,
y=y,
)
else:
st.error("Invalid chart type")
return None
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

This if/elif/else chain for creating charts works, but it can be refactored into a more maintainable and extensible structure using a dictionary. Mapping chart types to their configurations would make the code cleaner and simplify adding new chart types in the future.

    chart_configs = {
        "Bar": {"mark": "bar", "encode": {"x": x, "y": y}},
        "Line": {"mark": "line", "encode": {"x": x, "y": y}},
        "Scatter": {"mark": "circle", "encode": {"x": x, "y": y}},
        "Histogram": {"mark": "bar", "encode": {"x": alt.X(x, bin=True), "y": 'count()'}},
        "Heatmap": {"mark": "rect", "encode": {"x": x, "y": y}},
    }

    if chart_type in chart_configs:
        config = chart_configs[chart_type]
        chart = alt.Chart(df).mark(**config["mark"]).encode(**config["encode"])
    else:
        st.error("Invalid chart type")
        return None

Comment on lines 80 to 86
selected_chart_type = st.selectbox("Chart type", chart_type_options, index=chart_type_options.index(chart_type) if chart_type else 0)

x_axis_options = cols
selected_x_axis = st.selectbox("X-axis", x_axis_options, index=x_axis_options.get_loc(x_axis) if x_axis else 0)

y_axis_options = cols
selected_y_axis = st.selectbox("Y-axis", y_axis_options, index=y_axis_options.get_loc(y_axis) if y_axis else 1)
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

When a user selects "Histogram" as the chart type, the UI still prompts for a "Y-axis". This can be confusing, as the make_chart function correctly ignores this selection and uses a count for the y-axis.

To improve the user experience, I recommend conditionally hiding the Y-axis selector when the chart type is 'Histogram'. This would make the interface more intuitive.

@ravishan16 ravishan16 merged commit b011662 into main Oct 4, 2025
6 checks passed
@ravishan16 ravishan16 deleted the feature/visualization-layer-3 branch October 4, 2025 19:57
@ravishan16 ravishan16 self-assigned this Oct 4, 2025
@ravishan16 ravishan16 added the enhancement New feature or request label Oct 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature: Add Visualization Layer with Altair

2 participants

Comments