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

feat: added wip gradio UI #10

Merged
merged 4 commits into from
Jun 17, 2024
Merged

feat: added wip gradio UI #10

merged 4 commits into from
Jun 17, 2024

Conversation

ErikBjare
Copy link
Owner

@ErikBjare ErikBjare commented Jun 17, 2024

Summary by Sourcery

This pull request adds a new Gradio-based user interface for the QuantifiedMe project, enabling users to explore various types of quantified self data through multiple interactive tabs.

  • New Features:
    • Introduced a new Gradio-based UI for the QuantifiedMe project, providing multiple tabs for data exploration including Summary, Explore, Time, Sleep, Drugs, Correlations, and Data Sources.

@ErikBjare ErikBjare marked this pull request as ready for review June 17, 2024 16:56
Copy link

sourcery-ai bot commented Jun 17, 2024

Reviewer's Guide by Sourcery

This pull request introduces a new Gradio-based UI for the QuantifiedMe project. The implementation includes multiple views for exploring different types of data, such as summary, raw data, correlations, drugs, sleep, time, and data sources. The main.py file contains the core logic for loading data, creating plots, and setting up the Gradio UI, while the main.py file serves as the entry point for running the application.

File-Level Changes

Files Changes
src/quantifiedme/ui/main.py
src/quantifiedme/ui/__main__.py
Introduced a new Gradio-based UI for the QuantifiedMe project, including multiple views for exploring different types of data (summary, raw data, correlations, drugs, sleep, time, and data sources).

Tips
  • Trigger a new Sourcery review by commenting @sourcery-ai review on the pull request.
  • You can change your review settings at any time by accessing your dashboard:
    • Enable or disable the Sourcery-generated pull request summary or reviewer's guide;
    • Change the review language;
  • You can always contact us if you have any questions or feedback.

@ErikBjare ErikBjare merged commit 84eedcd into master Jun 17, 2024
3 of 5 checks passed
@ErikBjare ErikBjare deleted the dev/gradio branch June 17, 2024 16:57
Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey @ErikBjare - I've reviewed your changes and they look great!

Here's what I looked at during the review
  • 🟡 General issues: 8 issues found
  • 🟢 Security: all looks good
  • 🟢 Testing: all looks good
  • 🟢 Complexity: all looks good
  • 🟢 Documentation: all looks good

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 to tell me if it was helpful.

from quantifiedme.load.qslang import load_df as load_qslang_df


@cache
Copy link

Choose a reason for hiding this comment

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

suggestion: Consider using lru_cache instead of cache

The cache decorator is a simple alias for lru_cache(maxsize=None). If you anticipate the need to limit the cache size in the future, it might be more flexible to use lru_cache directly.

Suggested change
@cache
from functools import lru_cache
@lru_cache(maxsize=None)

fast = False
df = load_all(fast=fast)
print("Slicing timeperiods")
df = pd.concat([df[(df.index >= start) & (df.index <= end)] for start, end in tps])
Copy link

Choose a reason for hiding this comment

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

issue (performance): Potential performance issue with large dataframes

Using list comprehensions to filter and concatenate dataframes can be inefficient for large datasets. Consider using pd.concat with a generator expression or another method to handle large dataframes more efficiently.

return df


def load_timeperiod(period: str) -> pd.DataFrame:
Copy link

Choose a reason for hiding this comment

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

suggestion: Function name might be misleading

The function load_timeperiod suggests it loads a single time period, but it actually calls load_timeperiods which handles multiple periods. Consider renaming it to something like load_single_timeperiod for clarity.

Suggested change
def load_timeperiod(period: str) -> pd.DataFrame:
def load_single_timeperiod(period: str) -> pd.DataFrame:


def period_to_timeperiod(period: str) -> tuple[datetime, datetime]:
now = datetime.now()
match period.lower():
Copy link

Choose a reason for hiding this comment

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

suggestion: Consider adding a default case for match statement

While the current implementation raises a ValueError for unknown periods, it might be more robust to include a default case in the match statement to handle unexpected inputs gracefully.

Suggested change
match period.lower():
match period.lower():
case "day":
return (now.replace(hour=0, minute=0, second=0), now)
case _:
raise ValueError(f"Unknown period: {period}")

raise ValueError(f"Unknown period: {period}")


def dropdown_dfcols(df) -> gr.Dropdown:
Copy link

Choose a reason for hiding this comment

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

suggestion: Type hint for df parameter is missing

Consider adding a type hint for the df parameter to improve code readability and type checking. For example, def dropdown_dfcols(df: pd.DataFrame) -> gr.Dropdown:.

Suggested change
def dropdown_dfcols(df) -> gr.Dropdown:
import pandas as pd
def dropdown_dfcols(df: pd.DataFrame) -> gr.Dropdown:


# when loaded
# update the top categories plot
dataframe_el.change(
Copy link

Choose a reason for hiding this comment

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

issue (bug_risk): Potential issue with gradio change event

The change event in Gradio might not trigger as expected for DataFrame elements. Ensure that this behavior is tested thoroughly to avoid unexpected issues.


def view_time():
"""View to explore time data"""
pass
Copy link

Choose a reason for hiding this comment

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

issue: Unimplemented view functions

The view_time and view_sources functions are currently unimplemented. If these are placeholders, consider adding a TODO comment or raising a NotImplementedError to make it clear that these need to be completed.

Comment on lines +21 to +31
fast = True
now = datetime.now()
oldest_start = min((start for start, _ in tps))
if oldest_start < now - timedelta(days=30):
fast = False
df = load_all(fast=fast)
print("Slicing timeperiods")
df = pd.concat([df[(df.index >= start) & (df.index <= end)] for start, end in tps])
print("DONE! Sliced", len(df), "rows")
print(df)
return df
Copy link

Choose a reason for hiding this comment

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

issue (code-quality): We've found these issues:

print(f"Col changed to {col}")
df = df.reset_index().rename(columns={"index": "date"})
df = df[["date", col]]
y_max = max([v for v in df[col] if isinstance(v, (int, float))], default=0)
Copy link

Choose a reason for hiding this comment

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

suggestion (code-quality): Replace unneeded comprehension with generator (comprehension-to-generator)

Suggested change
y_max = max([v for v in df[col] if isinstance(v, (int, float))], default=0)
y_max = max((v for v in df[col] if isinstance(v, (int, float))), default=0)

Comment on lines +184 to +186
range = gr.Dropdown(
label="Range", choices=["Day", "Week", "Month", "Year"], value="Month"
)
Copy link

Choose a reason for hiding this comment

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

issue (code-quality): Don't assign to builtin variable range (avoid-builtin-shadow)


ExplanationPython has a number of builtin variables: functions and constants that
form a part of the language, such as list, getattr, and type
(See https://docs.python.org/3/library/functions.html).
It is valid, in the language, to re-bind such variables:

list = [1, 2, 3]

However, this is considered poor practice.

  • It will confuse other developers.
  • It will confuse syntax highlighters and linters.
  • It means you can no longer use that builtin for its original purpose.

How can you solve this?

Rename the variable something more specific, such as integers.
In a pinch, my_list and similar names are colloquially-recognized
placeholders.

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.

1 participant