You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Display total daily mileage/time/tss/elevation as a dashed circle, with individual activity circles drawn with appropriate radiuses, and the overall dashed circle's radius corresponding to the total volume on that day.
When hovering, show 2+ distinct circles that can be selected
First, need to modify the saved activities in the dummy database to have 2 runs in the same day. I'll be running application/cli/cli/rundummy, so start there.
Well lookee here, there is a --saved_activity_count option; let's add a --saved_activity_daily_count.
The saved activities need different distances to see how this stacking issue works. I edited application.cli.rundummy to draw distances from a np random distribution. Stopping for now.
Detour: Alternative idea:
The page in question (pages.training_log) creates a graph for each week using create_week_cal from df_week, which is just a subset of the dataframe created by Activity.load_summary_df(). Thinking I could just create a simple view with a spoofed dataframe to test out this behavior
Now looking to change the circle behavior. Starting in pages.training_log.create_week_cal().
Looks like the circles are added on #L251-#L298. Not sure what the units of the x-axis are - could be based on weekday. Woof!
Aside: part of me is thinking weekly calendars might work better as individual dash components rather than a single plotly figure. But dash components might have limitations.
Looks like I need to define the x-values of the trace in a more sophisticated way.
If the activity is the only one on its day, it remains the same as current.
But if the activity is one of multiple on its day:
If it is largest: offset to the left and plot first.
If it is 2nd-largest: offset to the right and plot second.
If it is 3rd-largest or smaller: ???
Not sure of the exact specifics, but the offsets need to be such that diameter_total = (radius_left + offset_left) + (radius_right + offset_right)
It's hard to tell how to derive distances - the circles are actually a trace with sizeref options specified. sizemode is area, and sizeref scales the markers: for example, with distance, marker_size = 100 for a marathon.
The bubble sizes for the other quantities are defined in update_week_cal().
Weird - it seems like the data for each week is stored as customdata on the week's trace. update_week_cal seems like it should be a callback attached to the week rows, which should be AIO components! This is making me itchy to refactor, but first I must decide whether I will stick with the weeks-as-figures approach, or dash has created components that will do what I need.
SVG requires dash-svg, an extension that is pretty new.
Thinking it's fine to go ahead and convert this bad boy into reusable components. It shouldn't take too long (lol we'll see), and will facilitate future development. I purposefully had waited to refactor this area until it was touched!
So I changed create_week_cal into TrainingWeekFigure, a subclass of go.Figure. But it looks like the AIO component that wants to be made (if any) is the entire calendar, not just weeks. That includes the dropdown that selects TSS/elevation/etc. But that AIO component is only used here, so keep it all in-file if possible.
But there's still the matter of update_week_cal. It expects the figure produced by TrainingWeekFigure, so why isn't it a method?
I am stuck trying to make TrainingWeekFigure behave like a regular plotly Figure thru init(), while having the option to create via TrainingWeekFigure.from_dataframe().
Never mind, got it to go. Optional bubble_type argument in init.
Now for the presumably difficult part: determining how far to offset the circles. The units are:
1 standard volume unit (a marathon, 3.5 hours, etc) -> marker_size = 100
Circles have a 1-day center-to-center spacing.
So how does marker_size translate to datetime-space??
To start, let's calculate everything in terms of marker_size, then figure out how to convert.
marker_size scales by area, not diameter, so the ratio of marker sizes of two volume measurements is (val_1 / val_2)^0.5
The offset of each circle needs to create a larger circle such that A_1 + A_2 = A_tot.
Ugh...after going down this rabbit hole, I'm convinced it doesn't make a ton of sense to use markers for this.
Individual shapes seems like the better option, because there really aren't a ton of activities per week. And the sizes for the shapes are specified in the coordinate system of the plot, removing the need to translate marker_size (which seemed doomed to fail anyway).
Welp. The shape of the circle is controlled by its min and max values on each axis. Generally this defines an ellipse, and that is the shape that typically comes out, unless I have a very specific screen width. Could I add a couple of unused axes as a workaround? I doubt it, because how would the hidden axis resize itself?
I am going to take a step back and figure out if there is a better presentation style available. It's pretty clear that I wouldn't be able to achieve the StravaTrainingLog-esque behavior of the markers, so how should I handle this? Maybe just a calendar view. TBD.
Back at it after some time off, and my desire to have cool hover behavior has returned.
I think the best way to accomplish this is with hover events in plotly.js. Main idea is that the marker(s) would (potentially) change position when hovered, so that the user could see each one distinctly.
Considering it could even switch from a single circle summarizing daily load, into multiple circles, one per activity.
aaron-schroeder
changed the title
>1 activity on a single day creates overlapping bubbles on small screen
>1 activity on a single day creates overlapping bubbles
Feb 1, 2023
First, need to modify the saved activities in the dummy database to have 2 runs in the same day. I'll be running application/cli/cli/rundummy, so start there.
Well lookee here, there is a --saved_activity_count option; let's add a --saved_activity_daily_count.
The saved activities need different distances to see how this stacking issue works. I edited application.cli.rundummy to draw distances from a np random distribution. Stopping for now.
Detour: Alternative idea:
create_week_cal
fromdf_week
, which is just a subset of the dataframe created byActivity.load_summary_df()
. Thinking I could just create a simple view with a spoofed dataframe to test out this behaviorNow looking to change the circle behavior. Starting in
pages.training_log.create_week_cal()
.Looks like the circles are added on #L251-#L298. Not sure what the units of the x-axis are - could be based on weekday. Woof!
Looks like I need to define the x-values of the trace in a more sophisticated way.
Not sure of the exact specifics, but the offsets need to be such that
diameter_total = (radius_left + offset_left) + (radius_right + offset_right)
It's hard to tell how to derive distances - the circles are actually a trace with sizeref options specified.
sizemode
is area, andsizeref
scales the markers: for example, with distance,marker_size
= 100 for a marathon.The bubble sizes for the other quantities are defined in
update_week_cal()
.Weird - it seems like the data for each week is stored as
customdata
on the week's trace.update_week_cal
seems like it should be a callback attached to the week rows, which should be AIO components! This is making me itchy to refactor, but first I must decide whether I will stick with the weeks-as-figures approach, or dash has created components that will do what I need.Potential Dash components:
Thinking it's fine to go ahead and convert this bad boy into reusable components. It shouldn't take too long (lol we'll see), and will facilitate future development. I purposefully had waited to refactor this area until it was touched!
So I changed
create_week_cal
into TrainingWeekFigure, a subclass of go.Figure. But it looks like the AIO component that wants to be made (if any) is the entire calendar, not just weeks. That includes the dropdown that selects TSS/elevation/etc. But that AIO component is only used here, so keep it all in-file if possible.But there's still the matter of update_week_cal. It expects the figure produced by TrainingWeekFigure, so why isn't it a method?
I am stuck trying to make TrainingWeekFigure behave like a regular plotly Figure thru init(), while having the option to create via TrainingWeekFigure.from_dataframe().
Never mind, got it to go. Optional
bubble_type
argument in init.Now for the presumably difficult part: determining how far to offset the circles. The units are:
To start, let's calculate everything in terms of marker_size, then figure out how to convert.
Ugh...after going down this rabbit hole, I'm convinced it doesn't make a ton of sense to use markers for this.
Individual shapes seems like the better option, because there really aren't a ton of activities per week. And the sizes for the shapes are specified in the coordinate system of the plot, removing the need to translate
marker_size
(which seemed doomed to fail anyway).Welp. The shape of the circle is controlled by its min and max values on each axis. Generally this defines an ellipse, and that is the shape that typically comes out, unless I have a very specific screen width. Could I add a couple of unused axes as a workaround? I doubt it, because how would the hidden axis resize itself?
One last thought I don't want to lose: manually specifying SVG paths with plotly. (Seems unlikely, as the svg is drawn in the plot's coord system).
I am going to take a step back and figure out if there is a better presentation style available. It's pretty clear that I wouldn't be able to achieve the StravaTrainingLog-esque behavior of the markers, so how should I handle this? Maybe just a calendar view. TBD.
Back at it after some time off, and my desire to have cool hover behavior has returned.
I think the best way to accomplish this is with hover events in plotly.js. Main idea is that the marker(s) would (potentially) change position when hovered, so that the user could see each one distinctly.
The text was updated successfully, but these errors were encountered: