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

Bubble markers map type #257

Merged
merged 58 commits into from
Aug 9, 2023
Merged

Bubble markers map type #257

merged 58 commits into from
Aug 9, 2023

Conversation

moontrip
Copy link
Contributor

@moontrip moontrip commented May 25, 2023

(Connor is new lead on this PR)
Resolves #263
Resolves #95
Resolves #249

@moontrip moontrip linked an issue May 31, 2023 that may be closed by this pull request
@chowington chowington self-assigned this Jun 14, 2023
@chowington chowington changed the title preliminary bubble marker component Bubble markers map type Jun 20, 2023
@chowington
Copy link
Member

chowington commented Jun 20, 2023

Numbers in the bubbles are just for sanity checking---not meant to be in the final product!

image

@moontrip
Copy link
Contributor Author

The screenshot looks great, @chowington 👍 Seems like center label helps to alleviate overlapped bubbles like bottom left bubbles in your screenshot.

@d-callan
Copy link
Member

we do need a way for people to read the values, and its possible labels on the bubbles will prove the best way to do that. my only concern was about maintaining enough contrast to be readable against all hues in our gradient colormap. we can maybe try it though and see what it looks like.

const valueToSizeMapper = (value: number) => {
// Area scales directly with value
const constant = 100;
const area = value * constant;
Copy link
Member

Choose a reason for hiding this comment

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

so i can live w area based scaling if we include a note in the legend that thats how weve done it.


const valueToSizeMapper = (value: number) => {
// Area scales directly with value
const constant = 100;
Copy link
Member

Choose a reason for hiding this comment

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

can you explain to me? is this to do w very small values or something?

Copy link
Member

Choose a reason for hiding this comment

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

if so, we should shift the range maybe instead? add as opposed to multiply?

Copy link
Member

Choose a reason for hiding this comment

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

No, this is just the scaling factor/"slope" to convert a value to a size in pixels

Copy link
Member

Choose a reason for hiding this comment

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

i still dont understand..

Copy link
Member

Choose a reason for hiding this comment

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

It doesn't make sense to make the circle size exactly equal to the value, like a value of 500 -> 500px circle, so the constant is what you multiple the value by to get the circle size

Copy link
Member

Choose a reason for hiding this comment

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

I've changed it to scalingFactor locally, with I think is more clear

@@ -102,6 +111,7 @@ enum MapSideNavItemLabels {
enum MarkerTypeLabels {
pie = 'Donuts',
barplot = 'Bar plots',
bubble = 'Bubbles',
Copy link
Member

Choose a reason for hiding this comment

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

this reminds me we need to discuss whether we can put bubble map before the donuts and have that be default in a ux meeting..

export interface BubbleMarkerConfiguration
extends MarkerConfiguration<'bubble'> {
selectedVariable: VariableDescriptor;
selectedValues: string[] | undefined;
Copy link
Member

Choose a reason for hiding this comment

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

if i understand this right i think this works for cat vars. cont need to choose an aggregation method.

{
type: 'bubble',
selectedVariable: defaultVariable,
selectedValues: undefined,
Copy link
Member

Choose a reason for hiding this comment

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

so this is maybe interesting.. if the first featured var is categorical and we have no default values selected does the user see anything in bubble mode without having to configure something?

Copy link
Member

Choose a reason for hiding this comment

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

I don't think we've got as far as handling the selected values yet.

: 0;

const bubbleValueToSizeMapper = (value: number) => {
const largestCircleArea = 9000;
Copy link
Member

Choose a reason for hiding this comment

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

how did we decide this?

Copy link
Member

Choose a reason for hiding this comment

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

I eyeballed it 😉

@@ -316,30 +368,50 @@ export function useStandaloneMapMarkers(
},
];

// here's what Bob pointed out
const count =
vocabulary != null // if there's an overlay (all expected use cases)
? overlayValues.reduce((sum, { count }) => (sum = sum + count), 0)
Copy link
Member

Choose a reason for hiding this comment

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

just curious, why not just use entityCount always?

Copy link
Member

Choose a reason for hiding this comment

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

Dunno, I just left this as it was!

label: reorderedData[0].label,
value: count,
color:
'color' in reorderedData[0] ? reorderedData[0].color : undefined,
Copy link
Member

Choose a reason for hiding this comment

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

is this a temp thing until i have the backend put together? not sure i understand..

Copy link
Member

Choose a reason for hiding this comment

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

Not sure what in particular you're talking about here, but yeah most likely a temporary thing, lol

@asizemore
Copy link
Member

#311 for the bubble icon

For the overlapping bubbles, it's common in bubble charts to have the stroke be whatever color and then the fill be the same color but maybe 0.7 opacity like in the following

Screen Shot 2023-06-22 at 5 35 56 AM

And sorry to leave the discussion early at the dev meeting yesterday! Did y'all come to a conclusion about the bubble sizing wrt different zoom levels and the legend?

Copy link
Member

@bobular bobular left a comment

Choose a reason for hiding this comment

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

I just want to put these comments in before I get distracted by other work. Will return for a proper review!

@@ -110,6 +115,11 @@ export function useAppState(uiStateKey: string, analysisState: AnalysisState) {
selectedVariable: defaultVariable,
selectedValues: undefined,
},
{
Copy link
Member

Choose a reason for hiding this comment

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

The problem with old analyses not being backwards compatible will require some extra work here.

The problem was that appState.markerConfigurations was missing an entry for type: 'bubble' because the default configuration is currently only made when there is absolutely no configuration.

A solution (not sure if solves all future compatibility issues, but will solve this one for now) could be as follows:

Modify this particular useEffect to initialise appState.markerConfigurations to an empty array. Move the default markerConfigurations array outside here as defaultMarkerConfigurations.

Add a new useEffect directly after this one to check that appState.markerConfigurations contains the same number of elements as defaultMarkerConfigurations, and those elements have the same type values. If any are missing, add the appropriate element from defaultMarkerConfigurations. If there are any extra (future deprecated?) elements - probably remove them??

{
type: 'bubble',
selectedVariable: defaultVariable,
selectedValues: undefined,
Copy link
Member

Choose a reason for hiding this comment

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

I don't think we've got as far as handling the selected values yet.

@bobular
Copy link
Member

bobular commented Jun 22, 2023

@chowington are you planning to use dependentAxisRange in the bubble markers?
Probably not needed if there's a valueToSizeMapper function passed around?

If not, could you remove it please.

Also a switch statement here would be lovely please:

  const markers = useMemo(
    () =>
      markersData?.map((markerProps) =>
        markerType === 'pie' ? (
          <DonutMarkerComponent {...markerProps} />
        ) : markerType === 'bubble' ? (
          <BubbleMarkerComponent {...(markerProps as BubbleMarkerProps)} />
        ) : (
          <ChartMarkerComponent {...markerProps} />
        )
      ) || [],
    [markersData, markerType]
  );

@bobular
Copy link
Member

bobular commented Jun 22, 2023

Thinking more about accommodating the new back end.

In useStandaloneMapMarkers (should be renamed maybe to useStandaloneMapMarkerData?):

I think renaming this type StandaloneMapMarkersResponse into DonutMarkersResponse | ChartMarkersResponse with those two types actually being identical/aliases (until we tackle the tech debt mentioned above) - this will help with readability (I much prefer it to DonutAndChartMarkersResponse). And something similar with the request types.

Then we can move ahead with DonutMarkersResponse | ChartMarkersResponse | BubbleMarkersResponse.

The reduce in the same hook that returns { valueMax, valueMinPos, countSum } will likely break for the bubble response, but we only need to do it for the chart markers (hence my question above) - so we can start being a bit more selective about what we do for the different marker types.

@chowington
Copy link
Member

chowington commented Aug 2, 2023

Looks like I can't remove people as reviewers if they've already given a review--I'm assigning @bobular to be the primary reviewer if that's alright with you, Bob!

@chowington chowington marked this pull request as ready for review August 2, 2023 20:37
@chowington
Copy link
Member

So honestly there's not much I can think of that requires specific attention/decision. Maybe some minor points:

  • I removed the numbers inside the bubbles since adding the popup, as they were not part of the mockup, and it would be a headache to make them fit inside the smaller bubbles well.
  • The default gradient is the brownish color; I don't particularly like that for the map, as it can be hard to distinguish the brown from the map background. That is the default we use for the scatter plot though. I may look into changing it unless others think it's fine.
  • There is still the issue with binary variables failing at the backend.

@chowington
Copy link
Member

Actually, I'll tag @asizemore for the gradient topic, as she put a lot of thought into choosing these gradients!

@chowington chowington requested review from dmfalke and removed request for bobular August 3, 2023 19:14

const markers = useMemo(
() =>
markersData?.map((markerProps) =>
markerType === 'pie' ? (
<DonutMarkerComponent {...markerProps} />
Copy link
Member

Choose a reason for hiding this comment

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

Remove type assertions, replace by prop filtering

Comment on lines +721 to +723
overlayConfiguration={
activeOverlayConfig.value as OverlayConfig
}
Copy link
Member

Choose a reason for hiding this comment

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

Look into this assertion too

@asizemore
Copy link
Member

So exciting to see this all come together!!! I'd be happy to tackle the gradient issue. I'll make it a new issue and assign myself

Copy link
Member

@dmfalke dmfalke left a comment

Choose a reason for hiding this comment

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

Connor and I did a synchronous review on Friday. The following issues will be addressed before merging:

  • Gradient legend issue: if min = max, then the gradient is empty (or white)
  • Fix y-axis config labels (proportion and aggregation are flipped)
  • Change tooltip label that is currently Color.

Copy link
Member

@dmfalke dmfalke left a comment

Choose a reason for hiding this comment

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

@chowington is looks like you've addressed the major things we discussed. I'm ready to approve this! Is there anything else you're working on, in this PR?

@chowington
Copy link
Member

chowington commented Aug 8, 2023

@dmfalke I'm just merging in main and testing, but I'm done otherwise 👍

Edit: Done

@chowington chowington requested a review from dmfalke August 8, 2023 20:41
Copy link
Member

@dmfalke dmfalke left a comment

Choose a reason for hiding this comment

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

🚀

@chowington chowington merged commit fcf36a4 into main Aug 9, 2023
1 check passed
@chowington chowington deleted the 95-bubble-marker-component branch August 9, 2023 13:08
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.

Map: Add Bubble marker map type Map: Bubble size legend component Bubble marker react component
7 participants