Skip to content

Commit

Permalink
Merge pull request #113 from earthrise-media/colorblind-palette
Browse files Browse the repository at this point in the history
Add colorblind palette
  • Loading branch information
Martin Bernard authored Dec 12, 2023
2 parents eac3c87 + c68819d commit 49e50b2
Show file tree
Hide file tree
Showing 107 changed files with 257 additions and 71 deletions.
34 changes: 24 additions & 10 deletions vacs-map-app/scripts/generate-minimaps.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,24 @@ const grid_filename = 'public/data/grid.csv';
const output_folder = 'src/assets/img/minimaps/';

const divergingScheme = {
name: 'default',
min: "#FFA31A",
center: "#424242",
max: "#13F364",
}

const colorblindDivergingScheme = {
name: 'colorblindFriendly',
min: '#E7EB2A',
center: '#424242',
max: '#D156F0'
}

// running for both schemes at once is too much for JS, so uncomment the line below that you want
// const colorSchemes = [divergingScheme, colorblindDivergingScheme]
// const colorSchemes = [divergingScheme]
const colorSchemes = [colorblindDivergingScheme]

const getGeoData = () => {
return JSON.parse(fs.readFileSync(geo_filename));
}
Expand Down Expand Up @@ -94,7 +107,7 @@ const getModels = (data) => {
)).filter(m => m.startsWith('future')).sort();
}

const getColorGenerator = (data, crop) => {
const getColorGenerator = (data, crop, scheme) => {
const columnNames = getModels(data).map(m => `yieldratio_${crop}_${m}`);
const extents = columnNames.map(d => getExtent(data, d));
const extent = [
Expand All @@ -104,7 +117,7 @@ const getColorGenerator = (data, crop) => {

return d3.scaleLinear()
.domain([extent[0], 0, extent[1]])
.range([divergingScheme.min, divergingScheme.center, divergingScheme.max]);
.range([scheme.min, scheme.center, scheme.max]);
};

const generateMapSvg = (crop, model, data, world, Africa, AfricanCountries, Africa0, color) => {
Expand Down Expand Up @@ -226,16 +239,17 @@ const generateMaps = () => {

const Africa = topojsonClient.merge(Africa0, Africa0.objects.countries.geometries);

crops.forEach(crop => {
models.forEach(model => {
const color = getColorGenerator(data, crop);

const svg = generateMapSvg(crop, model, data, world, Africa, AfricanCountries, Africa0, color);

fs.writeFileSync(`${output_folder}${crop}_${model}.svg`, svg.html());
colorSchemes.forEach(scheme => {
crops.forEach(crop => {
models.forEach(model => {
const color = getColorGenerator(data, crop, scheme);

const svg = generateMapSvg(crop, model, data, world, Africa, AfricanCountries, Africa0, color);

fs.writeFileSync(`${output_folder}${scheme.name}/${crop}_${model}.svg`, svg.html());
})
})
})

}

generateMaps();
Expand Down
14 changes: 8 additions & 6 deletions vacs-map-app/src/LandingPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,14 @@
<br />
<p>
The program has brought together experts in various fields, including climate adaptation,
plant breeding, nutrition, and food composition. <a href="https://agmip.org/" target="_blank"> AgMIP</a> was chosen to lead the initial phase of crop-climate modeling work, the results of which are visualized on this website. The selection process for crops was
informed by scientific data and expert opinions, ensuring a balance of priorities across
different scientific disciplines and stakeholder interests. This collaborative approach is
critical for developing an inclusive and effective strategy to address the nutritional
needs and environmental challenges in Africa.
plant breeding, nutrition, and food composition.
<a href="https://agmip.org/" target="_blank"> AgMIP</a> was chosen to lead the initial
phase of crop-climate modeling work, the results of which are visualized on this website.
The selection process for crops was informed by scientific data and expert opinions,
ensuring a balance of priorities across different scientific disciplines and stakeholder
interests. This collaborative approach is critical for developing an inclusive and
effective strategy to address the nutritional needs and environmental challenges in
Africa.
</p>
<br />
<p>
Expand Down Expand Up @@ -338,7 +341,6 @@ a {
</style>

<style>
.overlay .disclaimer-wrapper {
justify-content: center;
}
Expand Down
3 changes: 3 additions & 0 deletions vacs-map-app/src/assets/img/colorblind-active.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions vacs-map-app/src/assets/img/colorblind.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

10 changes: 7 additions & 3 deletions vacs-map-app/src/components/CardWrapper.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@

<script setup>
import { toRefs, computed } from 'vue'
import { stopLightScheme } from '@/utils/colors'
import { storeToRefs } from 'pinia'
import { useColorStore } from '@/stores/colors'
defineEmits(['showInfo'])
const props = defineProps({
Expand Down Expand Up @@ -63,6 +64,9 @@ const props = defineProps({
})
const { title, description, handleClick, indicator } = toRefs(props)
const colorStore = useColorStore()
const { stopLight: stopLightScheme } = storeToRefs(colorStore)
const indicatorLevel = computed(() => {
if (indicator?.value.val === null) return 'no data'
if (indicator.value.val < 3) return 'low'
Expand All @@ -71,8 +75,8 @@ const indicatorLevel = computed(() => {
})
const indicatorColor = computed(() => {
if (indicatorLevel.value === 'no data') return stopLightScheme.default
return stopLightScheme[indicatorLevel.value]
if (indicatorLevel.value === 'no data') return stopLightScheme.value.default
return stopLightScheme.value[indicatorLevel.value]
})
</script>
Expand Down
9 changes: 8 additions & 1 deletion vacs-map-app/src/components/CropCards.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { storeToRefs } from 'pinia'
import * as d3 from 'd3'
import { useFiltersStore } from '@/stores/filters'
import { useCropInformationStore } from '../stores/cropInformation'
import { useColorStore } from '@/stores/colors'
import CardWrapper from './CardWrapper.vue'
import DataDisclaimer from './DataDisclaimer.vue'
Expand All @@ -38,6 +39,9 @@ const { selectedCrop, selectedModel, selectedCropGroup, cropSortBy, cropSortOrde
storeToRefs(filtersStore)
const { data: cropInformation } = storeToRefs(cropInformationStore)
const colorStore = useColorStore()
const { colorblindFriendly } = storeToRefs(colorStore)
const filteredCrops = computed(() => {
if (!selectedCropGroup.value) return cropInformation.value
return cropInformation.value.filter((d) => d.crop_group === selectedCropGroup.value)
Expand All @@ -59,7 +63,10 @@ const navigate = (crop) => {
}
const getUrl = (crop) => {
return new URL(`../assets/img/minimaps/${crop}_${selectedModel.value}.svg`, import.meta.url).href
const schemeFolder = colorblindFriendly.value ? 'colorblindFriendly/' : 'default/'
const url = `../assets/img/minimaps/${schemeFolder}${crop}_${selectedModel.value}.svg`
return new URL(url, import.meta.url).href
}
</script>
Expand Down
42 changes: 21 additions & 21 deletions vacs-map-app/src/components/CropFingerprint.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<template>
<div class="fingerprint-wrapper">
<div class="legend">
<span class="benchmark-message">
*As compared to benchmark crop {{ benchmarkCropObject?.label }}</span
<span class="reference-message">
*As compared to reference crop {{ referenceCropObject?.label }}</span
>

<div class="responsive-legend">
Expand All @@ -14,8 +14,8 @@
>
{{ selectedCropObject?.label }}
</span>
<span v-if="showBenchmark" class="category-label benchmark-label">
{{ benchmarkCropObject?.label }}
<span v-if="showReference" class="category-label reference-label">
{{ referenceCropObject?.label }}
</span>
</div>
<div v-else class="hovered-label">
Expand All @@ -30,12 +30,12 @@
{{ cat }}
</span>
<span
v-if="showBenchmark"
class="category-label benchmark-label"
@mouseenter="hoveredCategory = 'benchmark'"
v-if="showReference"
class="category-label reference-label"
@mouseenter="hoveredCategory = 'reference'"
@mouseleave="hoveredCategory = null"
>
Benchmark
Reference
</span>
</div>
</div>
Expand Down Expand Up @@ -66,9 +66,9 @@
<circle v-for="d in d3.range(11)" :key="d" :r="y(d)" />
</g>

<g v-if="showBenchmark">
<g v-if="showReference">
<path
v-for="indicator in benchmarkIndicators"
v-for="indicator in referenceIndicators"
:key="indicator.key"
fill="#ffffff01"
stroke="#DAB967"
Expand All @@ -78,12 +78,12 @@
highlighted:
hovered?.key === indicator.key ||
hoveredCategory === indicator.category ||
hoveredCategory === 'benchmark',
hoveredCategory === 'reference',
unhighlighted:
(hovered && hovered.key !== indicator.key && hoveredCategory !== 'benchmark') ||
(hovered && hovered.key !== indicator.key && hoveredCategory !== 'reference') ||
(hoveredCategory &&
hoveredCategory !== indicator.category &&
hoveredCategory !== 'benchmark')
hoveredCategory !== 'reference')
}"
/>
</g>
Expand Down Expand Up @@ -154,22 +154,22 @@ const hoverIndicators = computed(() => {
})
})
const benchmarkCropObject = computed(() => {
const referenceCropObject = computed(() => {
if (!cropInformation.value) return null
return cropInformation.value.find(
(d) => d.crop_group === selectedCropObject.value.crop_group && d.benchmark
)
})
const benchmarkIndicators = computed(() => {
return getIndicators(benchmarkCropObject.value).filter(
const referenceIndicators = computed(() => {
return getIndicators(referenceCropObject.value).filter(
(d, i) => selectedIndicators.value[i].value
)
})
const showBenchmark = computed(() => {
if (!benchmarkCropObject.value) return false
return benchmarkCropObject.value !== selectedCropObject.value
const showReference = computed(() => {
if (!referenceCropObject.value) return false
return referenceCropObject.value !== selectedCropObject.value
})
const getIndicators = (crop) => {
Expand Down Expand Up @@ -262,7 +262,7 @@ svg {
color: var(--white);
}
.benchmark-message {
.reference-message {
color: var(--gray);
font-size: 0.8125rem;
font-style: italic;
Expand Down Expand Up @@ -300,7 +300,7 @@ svg {
text-transform: uppercase;
}
.benchmark-label {
.reference-label {
color: #dab967;
border: 1px solid #dab967;
}
Expand Down
11 changes: 9 additions & 2 deletions vacs-map-app/src/components/DistributionPlot.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import { computed, toRefs, ref, onMounted, watch } from 'vue'
import { useFiltersStore } from '@/stores/filters'
import { useCropYieldsStore } from '@/stores/cropYields'
import { useMapExploreStore } from '../stores/mapExplore'
import { useColorStore } from '@/stores/colors'
import { storeToRefs } from 'pinia'
import { divergingScheme } from '@/utils/colors'
const props = defineProps({
scenario: {
Expand All @@ -29,6 +29,9 @@ const { selectedMetric, selectedCrop, availableModels, availableCrops } = storeT
const { data: cropYieldsData } = storeToRefs(cropYieldsStore)
const { hoveredId } = storeToRefs(mapExploreStore)
const colorStore = useColorStore()
const { diverging: divergingScheme } = storeToRefs(colorStore)
const canvasRef = ref(null)
const context = ref(null)
const wrapperRef = ref(null)
Expand Down Expand Up @@ -89,7 +92,7 @@ const getCellColor = (value) => {
const scale = d3
.scaleLinear()
.domain([cropExtent.value[0], 0, cropExtent.value[1]])
.range([divergingScheme.min, divergingScheme.center, divergingScheme.max])
.range([divergingScheme.value.min, divergingScheme.value.center, divergingScheme.value.max])
.clamp(true)
return scale(value)
Expand Down Expand Up @@ -192,6 +195,10 @@ watch(selectedCrop, () => {
watch(hoveredId, () => {
draw()
})
watch(divergingScheme, () => {
draw()
})
</script>
<style scoped>
Expand Down
15 changes: 11 additions & 4 deletions vacs-map-app/src/components/GridOverlay.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
<script setup>
import * as d3 from 'd3'
import { computed, toRefs, watch } from 'vue'
import { divergingScheme } from '@/utils/colors'
import { storeToRefs } from 'pinia'
import { useMapExploreStore } from '../stores/mapExplore'
import { useColorStore } from '@/stores/colors'
const props = defineProps({
id: {
Expand Down Expand Up @@ -87,6 +87,9 @@ const {
const mapExploreStore = useMapExploreStore()
const { hoveredId } = storeToRefs(mapExploreStore)
const colorStore = useColorStore()
const { diverging: divergingScheme } = storeToRefs(colorStore)
const addLayer = () => {
if (!map.value || !mapReady.value || map.value.getLayer(id.value)) return
map.value.addLayer(
Expand Down Expand Up @@ -247,8 +250,8 @@ const getCircleColorDiverging = (extent, center) => {
// const interpolator = d3.interpolateBrBG;
// const interpolator = d3.interpolatePiYG;
const interpolator = d3.interpolateHsl(divergingScheme.min, divergingScheme.max)
const interpolator = d3.interpolateHsl(divergingScheme.value.min, divergingScheme.value.max)
console.log(divergingScheme.value)
return interpolator(value)
}
Expand All @@ -267,7 +270,7 @@ const getCircleColorDiverging = (extent, center) => {
min,
getColor(0),
center,
divergingScheme.center,
divergingScheme.value.center,
max,
getColor(1)
]
Expand Down Expand Up @@ -316,6 +319,10 @@ watch(colorColumn, () => {
updateLayer()
})
watch(divergingScheme, () => {
updateLayer()
})
watch(hoveredId, (current, prev) => {
updateHoveredFeatureState(prev, false)
updateHoveredFeatureState(current, true)
Expand Down
Loading

0 comments on commit 49e50b2

Please sign in to comment.