Skip to content

Commit

Permalink
Add (optional) jitter to dot plot. Seeded based on row size and dot i…
Browse files Browse the repository at this point in the history
…ndex
  • Loading branch information
JakeWags committed Jul 10, 2024
1 parent 160142c commit 94a7205
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export const AttributeBar: FC<Props> = ({ attribute, summary, row }) => {
case 'Strip Plot':
return <StripPlot scale={scale} values={values} attribute={attribute} summary={summary as SixNumberSummary} isAggregate={isRowAggregate(row)} row={row} />;
default:
return <DotPlot scale={scale} values={values} attribute={attribute} summary={summary as SixNumberSummary} isAggregate={isRowAggregate(row)} row={row} />;
return <DotPlot scale={scale} values={values} attribute={attribute} summary={summary as SixNumberSummary} isAggregate={isRowAggregate(row)} row={row} jitter />;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@ type Props = {
summary: SixNumberSummary;
isAggregate: boolean;
row: Subset | Aggregate;
jitter?: boolean;
};

// Dot plot component for the attributes plots
export const DotPlot: FC<Props> = ({
scale, values, attribute, summary, isAggregate, row,
scale, values, attribute, summary, isAggregate, row, jitter = false,
}) => {
const dimensions = useRecoilValue(dimensionsSelector);
const attributes = useRecoilValue(visibleAttributesSelector);
Expand All @@ -25,6 +26,29 @@ export const DotPlot: FC<Props> = ({
return null;
}

/**
* Generates a y offset for the provided index.
* Seeded based on row size so that jitter is consistent between renders, and also varies between rows.
* Rows of the same size will have the same jitter.
* @param index The index of the dot being rendered
* @returns y offset for the dot based on the index and row size
*/
function getJitterForIndex(index: number) {
const seed = row.size + index;

/**
* Generates a random number between 0 and 1 using a seed value.
* Poor randomness approximation, but good enough for jittering.
* @returns A random number between 0 and 1.
*/
function random() {
const x = Math.sin(seed) * 10000;
return x - Math.floor(x);
}

return (dimensions.attribute.plotHeight / 4) * (1 - random() * 2);
}

return (
<g>
<rect
Expand All @@ -37,7 +61,7 @@ export const DotPlot: FC<Props> = ({
/>
{values.map((value, idx) => (
// eslint-disable-next-line react/no-array-index-key
<circle key={`${row.id} + ${idx}`} cx={scale(value)} cy={0} r={dimensions.attribute.dotSize} fill="black" opacity="0.4" />
<circle key={`${row.id} + ${idx}`} cx={scale(value)} cy={jitter ? getJitterForIndex(idx) : 0} r={dimensions.attribute.dotSize} fill="black" opacity="0.2" />
))}
</g>
);
Expand Down

0 comments on commit 94a7205

Please sign in to comment.