Skip to content

Commit

Permalink
Merge pull request #90 from ccnmtl/STAT-51-legend
Browse files Browse the repository at this point in the history
Generate a legend for 2 genre graphs
  • Loading branch information
ndittren authored Aug 1, 2023
2 parents c450cf7 + 955b6cf commit 1c1e9b6
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 29 deletions.
5 changes: 3 additions & 2 deletions src/common.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,10 @@ export const graphBins = {
popularity: popularity
};

export const primary = 'rgba(82, 208, 80, 1.0)';
export const secondary = 'rgba(255, 100, 100, 0.7)';
export const PRIMARY = 'rgba(82, 208, 80, 1.0)';
export const SECONDARY = 'rgba(255, 100, 100, 0.7)';
export const HIGHLIGHT_1 = 'yellow';
export const HIGHLIGHT_2 = 'rgba(255, 100, 255, 0.7)';
export const GRAPH_BG = 'rgba(64, 64, 64, 1.0)';
export const FONT_SIZE = 14;
export const MARGIN = 30;
12 changes: 6 additions & 6 deletions src/graphForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import genres from '../data/trackDataByGenre.json';
import { CumulativeSampleMean } from './graphs/sampleMeanLine';
import { Histogram } from './graphs/histogram';
import {
Genre, toTitleCase, InstructionData, primary, secondary
Genre, toTitleCase, InstructionData, PRIMARY, SECONDARY
} from './common';
import seedrandom from 'seedrandom'; // https://github.com/davidbau/seedrandom
import { EstimatedDistribution } from './graphs/estimatedSampleDistribution';
Expand Down Expand Up @@ -200,7 +200,7 @@ export const GraphForm: React.FC<GraphFormProps> = (
<div className='row' id='capture'>
{graphTypes.includes(SAMPLEDATAHISTOGRAM1) && (
<Histogram
color={primary}
color={PRIMARY}
data1={data1}
data2={null}
genre1={genre1}
Expand All @@ -210,7 +210,7 @@ export const GraphForm: React.FC<GraphFormProps> = (
)}
{graphTypes.includes(SAMPLEDATAHISTOGRAM2) && (
<Histogram
color={secondary}
color={SECONDARY}
data1={data2}
data2={null}
genre1={genre2}
Expand All @@ -220,7 +220,7 @@ export const GraphForm: React.FC<GraphFormProps> = (
)}
{graphTypes.includes(SAMPLEDATAHISTOGRAMBOTH) && (
<Histogram
color={primary}
color={PRIMARY}
data1={data1}
data2={data2}
genre1={genre1}
Expand All @@ -245,7 +245,7 @@ export const GraphForm: React.FC<GraphFormProps> = (
)}
{graphTypes.includes(DISTRIBUTIONHISTOGRAM) && (
<Histogram
color={primary}
color={PRIMARY}
data1={meanData1}
data2={meanData2}
genre1={genre1}
Expand Down Expand Up @@ -372,7 +372,7 @@ export const GraphForm: React.FC<GraphFormProps> = (
<input
type='submit'
id='submit-btn'
className='btn btn-primary'
className='btn btn-PRIMARY'
value='Submit'
/>
</form>
Expand Down
6 changes: 3 additions & 3 deletions src/graphs/estimatedSampleDistribution.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useRef, useEffect, useState } from 'react';
import { BinData, graphBins, toTitleCase, primary, secondary } from '../common';
import { BinData, graphBins, toTitleCase, PRIMARY, SECONDARY } from '../common';
import { scaleLinear } from 'd3-scale';
import { select, Selection } from 'd3-selection';
import {
Expand Down Expand Up @@ -187,9 +187,9 @@ export const EstimatedDistribution: React.FC<EstimatedDistributionProps> = (
selection.selectAll('g').remove();

generateCurve(selection, 'curve1', projection, data1, curve, fill,
primary, se1, mean1, x, y);
PRIMARY, se1, mean1, x, y);
generateCurve(selection, 'curve2', projection, data2, curve, fill,
secondary, se2, mean2, x, y);
SECONDARY, se2, mean2, x, y);

// Construct the Y-axis
selection.append('g')
Expand Down
81 changes: 66 additions & 15 deletions src/graphs/histogram.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
import React, { useRef, useEffect, useState } from 'react';
import {
BinData, graphBins, toTitleCase, primary, secondary, HIGHLIGHT_1,
BinData, graphBins, toTitleCase, SECONDARY, GRAPH_BG, HIGHLIGHT_1,
HIGHLIGHT_2
} from '../common';
import { axisBottom, axisLeft } from 'd3';
import { bin, Bin } from 'd3-array';
import { scaleLinear, ScaleLinear } from 'd3-scale';
import { select, Selection } from 'd3-selection';
/**
* import { visibility } from
* 'html2canvas/dist/types/css/property-descriptors/visibility';
*/


const BUCKET_PADDING = 4;
const FONT_SIZE = 14;
const MARGIN = 30;
const Y_LABEL = 20;
const Y_CAP = 20;
const Y_SCALE = 20;
const LEGEND_R = 10;
const LEGEND_GAP = 20;
const LEGEND_TEXT_DROP = 5;
const LEGEND_CIRCLE_STROKE = 1.5;


interface HistogramProps {
Expand Down Expand Up @@ -97,6 +98,15 @@ export const Histogram: React.FC<HistogramProps> = (
.thresholds(
(binData.max - binData.min) / binData.ticks)(
data1); // First data goes here
const bins2 = data2 ?
bin()
.domain([binData.min, binData.max])
.thresholds((binData.max - binData.min) / binData.ticks)(
data2) :
null;
const over20 = [...bins1.map(d => d.length),
...bins1.map(d => d.length)].find(x => x > Y_SCALE);
const yCap = over20 ? 20 * Math.ceil(over20 / Y_SCALE) : Y_SCALE;

const gWidth = Number.parseInt(selection.style('width')) - MARGIN;
const height =
Expand All @@ -106,11 +116,20 @@ export const Histogram: React.FC<HistogramProps> = (
.domain([binData.min, binData.max]).nice()
.range([MARGIN + Y_LABEL, gWidth]);
const y = scaleLinear()
.domain([0, Y_CAP])
.domain([0, yCap])
.range([height, MARGIN]);

const id1 = 'detail-1';

// Generate graph body
selection.append('rect')
.attr('fill', GRAPH_BG)
.attr('height', height-MARGIN)
.attr('id', 'graph-background')
.attr('width', gWidth-MARGIN-Y_LABEL)
.attr('x', MARGIN + Y_LABEL)
.attr('y', MARGIN);

// Construct graph bars
selection.append('g')
.attr('id', 'genre1')
Expand All @@ -128,21 +147,16 @@ export const Histogram: React.FC<HistogramProps> = (
select(this).attr('fill', HIGHLIGHT_1);
})
.on('mouseout', function(){
select(this).attr('fill', primary);
select(this).attr('fill', color);
document.getElementById(id1).remove();
});

// Construct 2nd set of graph bars
if (data2) {
const id2 = 'detail-2';
const bins2 = bin()
.domain([binData.min, binData.max])
.thresholds(
(binData.max - binData.min) / binData.ticks)(
data2); //Second data set goes here
selection.append('g')
.attr('id', 'genre2')
.attr('fill', secondary)
.attr('fill', SECONDARY)
.selectAll()
.data(bins2)
.join('rect')
Expand All @@ -156,7 +170,7 @@ export const Histogram: React.FC<HistogramProps> = (
select(this).attr('fill', HIGHLIGHT_2);
})
.on('mouseout', function(){
select(this).attr('fill', secondary);
select(this).attr('fill', SECONDARY);
document.getElementById(id2).remove();
});

Expand Down Expand Up @@ -223,6 +237,43 @@ export const Histogram: React.FC<HistogramProps> = (
.attr('y', 12)
.text(`Count: ${data1.length}`))
.attr('font-size', FONT_SIZE);

// Generate Legend
if (genre1 && genre2) {
selection.append('g')
.attr('id', 'legend')
.attr('transform',
`translate(${gWidth}, ${3 * MARGIN / 2})`)
.call((g) => g.append('g')
.attr('transform',
`translate(${-LEGEND_GAP}, 0)`)
.call((g) => g.append('circle')
.attr('stroke', 'black')
.attr('stroke-width', LEGEND_CIRCLE_STROKE)
.attr('fill', color)
.attr('r', LEGEND_R))
.call((g) => g.append('text')
.attr('fill', 'white')
.attr('text-anchor', 'end')
.attr('x', -LEGEND_GAP)
.attr('y', LEGEND_TEXT_DROP)
.text(`${toTitleCase(genre1)}`)))
.call((g) => g.append('g')
.attr('transform',
`translate(${-LEGEND_GAP}, ${30})`)
.call((g) => g.append('circle')
.attr('stroke', 'black')
.attr('stroke-width', LEGEND_CIRCLE_STROKE)
.attr('fill', SECONDARY)
.attr('r', LEGEND_R))
.call((g) => g.append('text')
.attr('fill', 'white')
.attr('text-anchor', 'end')
.attr('x', -LEGEND_GAP)
.attr('y', LEGEND_TEXT_DROP)
.text(`${toTitleCase(genre2)}`)))
.attr('font-size', FONT_SIZE);
}
}
}, [selection, data1, genre1, genre2, audioFeature]);

Expand Down
6 changes: 3 additions & 3 deletions src/graphs/sampleMeanLine.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useRef, useEffect } from 'react';
import { BinData, graphBins, toTitleCase, primary, secondary,
import { BinData, graphBins, toTitleCase, PRIMARY, SECONDARY,
FONT_SIZE, MARGIN } from '../common';
import { cumulativeMeanFunc } from './utils';
import { line, axisBottom, axisLeft } from 'd3';
Expand Down Expand Up @@ -96,7 +96,7 @@ export const CumulativeSampleMean: React.FC<CumulativeSampleMeanProps> = (
.datum(cm)
.attr('d', lnMkr(cm))
.attr('fill', 'none')
.attr('stroke', primary)
.attr('stroke', PRIMARY)
.attr('stroke-width', 2);

if(data2) {
Expand All @@ -121,7 +121,7 @@ export const CumulativeSampleMean: React.FC<CumulativeSampleMeanProps> = (
.datum(cm2)
.attr('d', lnMkr2(cm2))
.attr('fill', 'none')
.attr('stroke', secondary)
.attr('stroke', SECONDARY)
.attr('stroke-width', 2);
}

Expand Down

0 comments on commit 1c1e9b6

Please sign in to comment.