julianna-langston / chart2music Goto Github PK
View Code? Open in Web Editor NEWTurns charts into music so the blind can hear data
License: MIT License
Turns charts into music so the blind can hear data
License: MIT License
Currently, when alt
attribute and its corresponding value exist within an image element, c2m does not add any sonification instruction message. What if you append the sonification instruction to the original alt value by its default behavior, and make its behavior configurable for the users (e.g., options for append, override, none)?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/chart2music"></script>
</head>
<body>
<img src="mychart.png" id="MyChart" alt="Original alt text by content author." />
<script>
c2mChart({
type: "bar",
element: document.getElementById("MyChart"),
data: [1, 2, 3]
});
</script>
</body>
</html>
I was wondering if you had any plans for supporting the following chart types:
Boxplot.
Scatter plot.
Heat map.
Histogram.
Geospatial map.
Segmented (stacked) bar plot within each level.
Dodged (side-by-side) bar plot within each level.
I know, we cannot cover everything at once, but it would be great if we could prioritize some chart types. FYI, our team has been working on SVG-based accessible charts for bar plot, boxplot, heat map, and scatter plot. Will share our progress as well going forward. We are also trying to keep the same json metadata format in our own module to be compatible with C2M in the long run.
Provide a gallery of different chart types and features on a page. The charts should be directly embedded, but should include links to a codepen, so that developers can see how it was put together.
Chart type examples:
Features:
Support his new top-level property:
{
info: {
notes: [
"Data from BLS, World Bank, FiveThirtyEight"
]
}
}
Add a new keyboard shortcut, "i", to open an info dialog. In this dialog, all of the notes should be listed in an unordered list. Only plain text is supported.
Hi! Are we amenable to adding support for commonjs
? It's relatively simple:
The AudioEngine should provide a gettable variable, version
, which should have the value "1".
Let's say you want to create a simple bar chart that shows how many moon Mercury, Venus, Earth, and Mars have. You could do that in a couple of ways:
Option 1: Using formats
const planets = ["Mercury", "Venus", "Earth", "Mars"];
c2mChart({
type: "bar",
data: [0,0,1,2],
axes: {
x: {
format: (index) => planets[index]
}
}
});
Option 2: Using valueLabels
const planets = ["Mercury", "Venus", "Earth", "Mars"];
c2mChart({
type: "bar",
data: [0,0,1,2],
axes: {
x: {
valueLabels: planets
}
}
});
However, this is separating out the data with the labels. If we kept the 2 together, we could instead do something like this:
c2mChart({
type: "bar",
data: [
{x: "Mercury", y: 0},
{x: "Venus", y: 0},
{x: "Earth", y: 1},
{x: "Mars", y: 2}
]
});
Note that this isn't simply a matter of finding a new way to do the same thing. The data
value supports data points that are either numbers or objects; if the data points are object, then x
is required and must be a number. If you need to use an object (eg, the chart is a box plot, or you want to leverage the custom
property for a callback), then you need to use a numeric x
value, even when it doesn't make sense.
Here is the data for a chart showing the first 4 planets, showing how close and how far they get from the sun. Note how each data point has an x
value that simply duplicates its own index:
const planets = ["Mercury", "Venus", "Earth", "Mars"];
c2mChart({
type: "bar",
data: [
{
x: 0,
high: .466, // Measured in Astronomical Units
low: .307
},
{
x: 1,
high: .728,
low: .718
},
{
x: 2,
high: 1.016,
low: .983
},
{
x: 3,
high: 1.666
low: 1.381
},
],
axes: {
x: {
valueLabels: planets
}
}
});
In this case, it makes more sense to be able to just put down:
{x: "Mercury", high: .466, low: .307}
instead of duplicating index values and juggling where the data was placed.
Sonified image elements by c2m require screen readers' focus mode/forms mode. Do you have any special reasons that you did not implement "application" role for the users not having to manually switch between modes? I have also noticed that SAS Graphic Accelerator used "application" role.
The following example automatically switches to screen readers' focus/forms mode when it gets focused via tab key.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/chart2music"></script>
</head>
<body>
<img src="mychart.png" id="MyChart" role="application"/>
<script>
c2mChart({
type: "bar",
element: document.getElementById("MyChart"),
data: [1, 2, 3]
});
</script>
</body>
</html>
Add id
as a supported property for all data points
Whenever data is changed, keep track of the ID of the data point that's in focus. If the data changes, but a data point with the focus ID is currently specified, and no focus point is provided, keep the data point with the current focus ID.
This means that the order of precedence to determine which data point has focus when data changes is:
setData
functionPage up/down keys move between groups; however, I have not been able to find a way to go to the first group and the last group quickly, such as Ctrl+PG-Up/Down
. It would be great if these shortcuts could be added.
Great package, easy to work with 🥇
Noticed your recent post on the ECharts board and got intrigued. ECharts currently does not support keyboard commands.
But chart2music does! So I played with two of your examples and got it rocking - chart2music on ECharts.
Custom hotkeys is a nice feature. I added '+' and '-' for zoom in & out. It could help with EChart issues like this one.
Hope many more people will benefit from your work. Thank you.
If I'm focused on a chart and I press "h" WITHOUT caps lock on, the help dialog opens. If I turn caps lock on and then press "H", the dialog does not open.
When C2M generates a summary, if the X-values are dates, the summary formats them as numbers
https://codepen.io/chart2music/pen/XWBqLPx
Additionally, if you try to include a format function that relies on the X-values to be dates, it will throw a js error.
Support sound effects in the audio engine.
The AudioEngine interface should include the functions:
getAvailableSoundEffects(): string[]
playSoundEffect(effect_name: string, panning: number, duration: number): {err: null | string}
The sound effects that the AudioEngine should support are:
ping
- a short, high-pitched sound that rises rapidly and falls rapidlychime
- a medium-length, high-pitched sound that rises rapidly and falls slowlyWhen calling getAvailableSoundEffects
, it should return the names of sound effects available. In this case, it should return [ping
, chime
]. The order of the returned effects is not meaningful.
When playSoundEffect
is called, it should play the requested sound. If there is no error, it should return {err: null}
. If the requested doesn't exist, it should return an error message:
{
err: "Requested sound 'bad' is not available. The available sounds are: 'ping', 'chime'"
}
The requested sound effect should be played at the provided panning.
The provided duration relates to the duration of individual data points. The sound doesn't need to take as long as the duration, but should try to be shorter than the duration when possible.
Provide instructions for how end-users would interact with Chart2Music.
Instructions should include all of the current keyboard and mobile interactions.
I was wondering if C2M sonification could be also access via mobile devices, such as iOS and Android. My quick test with iPhone does not seem to work, but please correct me if I am wrong.
The following example does not work. Simply speaking, sonification is not generated with a directly embedded svg object.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/chart2music"></script>
</head>
<body>
<svg id='MyChart' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' class='svglite'
width='504.00pt' height='360.00pt' viewBox='0 0 504.00 360.00'>
<defs>
<style type='text/css'>
<![CDATA[
.svglite line,
.svglite polyline,
.svglite polygon,
.svglite path,
.svglite rect,
.svglite circle {
fill: none;
stroke: #000000;
stroke-linecap: round;
stroke-linejoin: round;
stroke-miterlimit: 10.00;
}
.svglite text {
white-space: pre;
}
]]>
</style>
</defs>
<rect width='100%' height='100%' style='stroke: none; fill: #FFFFFF;' />
<defs>
<clipPath id='cpMC4wMHw1MDQuMDB8MC4wMHwzNjAuMDA='>
<rect x='0.00' y='0.00' width='504.00' height='360.00' />
</clipPath>
</defs>
<g clip-path='url(#cpMC4wMHw1MDQuMDB8MC4wMHwzNjAuMDA=)'>
<rect x='0.00' y='0.00' width='504.00' height='360.00'
style='stroke-width: 1.07; stroke: #FFFFFF; fill: #FFFFFF;' />
</g>
<defs>
<clipPath id='cpMzMuMjR8NDk4LjUyfDUuNDh8MzI4LjI3'>
<rect x='33.24' y='5.48' width='465.28' height='322.79' />
</clipPath>
</defs>
<g clip-path='url(#cpMzMuMjR8NDk4LjUyfDUuNDh8MzI4LjI3)'>
<rect x='33.24' y='5.48' width='465.28' height='322.79'
style='stroke-width: 1.07; stroke: none; fill: #EBEBEB;' />
<polyline points='33.24,266.27 498.52,266.27 '
style='stroke-width: 0.53; stroke: #FFFFFF; stroke-linecap: butt;' />
<polyline points='33.24,171.61 498.52,171.61 '
style='stroke-width: 0.53; stroke: #FFFFFF; stroke-linecap: butt;' />
<polyline points='33.24,76.95 498.52,76.95 '
style='stroke-width: 0.53; stroke: #FFFFFF; stroke-linecap: butt;' />
<polyline points='33.24,313.60 498.52,313.60 '
style='stroke-width: 1.07; stroke: #FFFFFF; stroke-linecap: butt;' />
<polyline points='33.24,218.94 498.52,218.94 '
style='stroke-width: 1.07; stroke: #FFFFFF; stroke-linecap: butt;' />
<polyline points='33.24,124.28 498.52,124.28 '
style='stroke-width: 1.07; stroke: #FFFFFF; stroke-linecap: butt;' />
<polyline points='33.24,29.62 498.52,29.62 '
style='stroke-width: 1.07; stroke: #FFFFFF; stroke-linecap: butt;' />
<polyline points='72.01,328.27 72.01,5.48 '
style='stroke-width: 1.07; stroke: #FFFFFF; stroke-linecap: butt;' />
<polyline points='136.64,328.27 136.64,5.48 '
style='stroke-width: 1.07; stroke: #FFFFFF; stroke-linecap: butt;' />
<polyline points='201.26,328.27 201.26,5.48 '
style='stroke-width: 1.07; stroke: #FFFFFF; stroke-linecap: butt;' />
<polyline points='265.88,328.27 265.88,5.48 '
style='stroke-width: 1.07; stroke: #FFFFFF; stroke-linecap: butt;' />
<polyline points='330.50,328.27 330.50,5.48 '
style='stroke-width: 1.07; stroke: #FFFFFF; stroke-linecap: butt;' />
<polyline points='395.12,328.27 395.12,5.48 '
style='stroke-width: 1.07; stroke: #FFFFFF; stroke-linecap: butt;' />
<polyline points='459.75,328.27 459.75,5.48 '
style='stroke-width: 1.07; stroke: #FFFFFF; stroke-linecap: butt;' />
<rect x='42.93' y='289.93' width='58.16' height='23.67'
style='stroke-width: 1.07; stroke: none; stroke-linecap: square; stroke-linejoin: miter; fill: #595959;' />
<rect x='107.56' y='91.15' width='58.16' height='222.45'
style='stroke-width: 1.07; stroke: none; stroke-linecap: square; stroke-linejoin: miter; fill: #595959;' />
<rect x='172.18' y='119.55' width='58.16' height='194.05'
style='stroke-width: 1.07; stroke: none; stroke-linecap: square; stroke-linejoin: miter; fill: #595959;' />
<rect x='236.80' y='261.54' width='58.16' height='52.06'
style='stroke-width: 1.07; stroke: none; stroke-linecap: square; stroke-linejoin: miter; fill: #595959;' />
<rect x='301.42' y='157.41' width='58.16' height='156.19'
style='stroke-width: 1.07; stroke: none; stroke-linecap: square; stroke-linejoin: miter; fill: #595959;' />
<rect x='366.04' y='147.94' width='58.16' height='165.66'
style='stroke-width: 1.07; stroke: none; stroke-linecap: square; stroke-linejoin: miter; fill: #595959;' />
<rect x='430.67' y='20.15' width='58.16' height='293.45'
style='stroke-width: 1.07; stroke: none; stroke-linecap: square; stroke-linejoin: miter; fill: #595959;' />
</g>
<g clip-path='url(#cpMC4wMHw1MDQuMDB8MC4wMHwzNjAuMDA=)'>
<text x='28.31' y='316.75' text-anchor='end' style='font-size: 8.80px;fill: #4D4D4D; font-family: "Arial";'
textLength='4.90px' lengthAdjust='spacingAndGlyphs'>0</text>
<text x='28.31' y='222.09' text-anchor='end' style='font-size: 8.80px;fill: #4D4D4D; font-family: "Arial";'
textLength='9.79px' lengthAdjust='spacingAndGlyphs'>20</text>
<text x='28.31' y='127.43' text-anchor='end' style='font-size: 8.80px;fill: #4D4D4D; font-family: "Arial";'
textLength='9.79px' lengthAdjust='spacingAndGlyphs'>40</text>
<text x='28.31' y='32.77' text-anchor='end' style='font-size: 8.80px;fill: #4D4D4D; font-family: "Arial";'
textLength='9.79px' lengthAdjust='spacingAndGlyphs'>60</text>
<polyline points='30.50,313.60 33.24,313.60 '
style='stroke-width: 1.07; stroke: #333333; stroke-linecap: butt;' />
<polyline points='30.50,218.94 33.24,218.94 '
style='stroke-width: 1.07; stroke: #333333; stroke-linecap: butt;' />
<polyline points='30.50,124.28 33.24,124.28 '
style='stroke-width: 1.07; stroke: #333333; stroke-linecap: butt;' />
<polyline points='30.50,29.62 33.24,29.62 '
style='stroke-width: 1.07; stroke: #333333; stroke-linecap: butt;' />
<polyline points='72.01,331.01 72.01,328.27 '
style='stroke-width: 1.07; stroke: #333333; stroke-linecap: butt;' />
<polyline points='136.64,331.01 136.64,328.27 '
style='stroke-width: 1.07; stroke: #333333; stroke-linecap: butt;' />
<polyline points='201.26,331.01 201.26,328.27 '
style='stroke-width: 1.07; stroke: #333333; stroke-linecap: butt;' />
<polyline points='265.88,331.01 265.88,328.27 '
style='stroke-width: 1.07; stroke: #333333; stroke-linecap: butt;' />
<polyline points='330.50,331.01 330.50,328.27 '
style='stroke-width: 1.07; stroke: #333333; stroke-linecap: butt;' />
<polyline points='395.12,331.01 395.12,328.27 '
style='stroke-width: 1.07; stroke: #333333; stroke-linecap: butt;' />
<polyline points='459.75,331.01 459.75,328.27 '
style='stroke-width: 1.07; stroke: #333333; stroke-linecap: butt;' />
<text x='72.01' y='339.50' text-anchor='middle'
style='font-size: 8.80px;fill: #4D4D4D; font-family: "Arial";' textLength='29.36px'
lengthAdjust='spacingAndGlyphs'>2seater</text>
<text x='136.64' y='339.50' text-anchor='middle'
style='font-size: 8.80px;fill: #4D4D4D; font-family: "Arial";' textLength='33.26px'
lengthAdjust='spacingAndGlyphs'>compact</text>
<text x='201.26' y='339.50' text-anchor='middle'
style='font-size: 8.80px;fill: #4D4D4D; font-family: "Arial";' textLength='29.82px'
lengthAdjust='spacingAndGlyphs'>midsize</text>
<text x='265.88' y='339.50' text-anchor='middle'
style='font-size: 8.80px;fill: #4D4D4D; font-family: "Arial";' textLength='30.32px'
lengthAdjust='spacingAndGlyphs'>minivan</text>
<text x='330.50' y='339.50' text-anchor='middle'
style='font-size: 8.80px;fill: #4D4D4D; font-family: "Arial";' textLength='25.44px'
lengthAdjust='spacingAndGlyphs'>pickup</text>
<text x='395.12' y='339.50' text-anchor='middle'
style='font-size: 8.80px;fill: #4D4D4D; font-family: "Arial";' textLength='47.46px'
lengthAdjust='spacingAndGlyphs'>subcompact</text>
<text x='459.75' y='339.50' text-anchor='middle'
style='font-size: 8.80px;fill: #4D4D4D; font-family: "Arial";' textLength='13.69px'
lengthAdjust='spacingAndGlyphs'>suv</text>
<text x='265.88' y='352.10' text-anchor='middle' style='font-size: 11.00px; font-family: "Arial";'
textLength='25.06px' lengthAdjust='spacingAndGlyphs'>class</text>
<text transform='translate(13.36,166.88) rotate(-90)' text-anchor='middle'
style='font-size: 11.00px; font-family: "Arial";' textLength='26.92px'
lengthAdjust='spacingAndGlyphs'>count</text>
</g>
</svg>
<script>
c2mChart({
type: "bar",
element: document.getElementById("MyChart"),
data: [1, 2, 3]
});
</script>
</body>
</html>
Example situation
A visual chart shows a scatter plot and a violin plot. While chart2music supports scatter plots, it doesn't support violin plots. I want to make the scatter plot accessible to users, but I don't want to hide the fact that there's a violin plot also present in the visuals.
Request
There should be a way to communicate inaccessible layers. Maybe the user is told that there are 2 layers. They go to the first one, a scatter plot, and can navigate as normal. They navigate to the second layer, like "Chart contains unsupported chart type: violin plot.", perhaps optionally with some kind of alt text.
Thanks for working on and releasing such a great open-source project!
I was attempting to reproduce a minimal example using the instruction provided in readme. However, the following code does not produce any sonification layers. Could you please help me better understand what's wrong with my code below?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/chart2music"></script>
</head>
<body>
<img src="mychart.png" id="MyChart" />
<script>
c2mChart({
type: "bar",
element: document.getElementById("MyChart"),
data: [1, 2, 3]
});
</script>
</body>
</html>
Steps:
setCategoryVisibility("A", false)
There are console errors.
Follow the bug reproduction steps in this codepen:
https://codepen.io/chart2music/pen/jOpxjoZ
Caption box is currently in english.
If it's amenable to you, I would be willing to add international support and could provide translations in german and spanish!
Would want approval before I start the work, it would be done over the course of months.
Please correct me if I am wrong, but there does not seem to be a candlestick chart example. It would be great if a sample chart could be added.
I appreciate the new support for heatmaps and correlation matrices. I would like to open a discussion for the following items:
Horizontal autoplay is possible with ctrl+shift+left/right arrows; there is no way to autoswipe cells in a vertical direction.
I understand that you borrowed the same concepts using pg-up/down keys from multi-line charts and grouped box plot. Given that heatmaps and matrices are grid form and well-mapped with standard arrow key layout, wouldn't it be more cognitively accessible and easier to press? In heatmap consisting of two categorical variables, both horizontal and vertical navigations are changing groups anyway. I think there is no strong reason to keep using pg up/down keys only for vertical nav given this characteristic.
DataVizCatalogue lists the following chart types as representing hierarchies through proportions:
Note that DataVizCatalogue also lists tree diagrams as a way of representing hierachies. However, since a tree diagram doesn't necessarily convey quantifiable data, it is excluded from this feature request
Data points for treemaps would contain:
toGroup
if one isn't specifiedInteractions:
Here's how this chart.js example treemap would be represented
{
type: "treemap",
axes: {
y: {
label: "Area",
format: (value) => value.toLocaleString() + " km2"
}
},
data: {
Region: [
{label: "West", y: 4851705},
{label: "South", y: 2383947},
{label: "Midwest", y: 2128257},
{label: "Northeast", y: 469615},
],
West: [
{label: "Pacific", y: 2615082},
{label: "Mountain", y: 2236623},
],
South: [
{label: "West South Central", y: 1150090},
{label: "South Atlantic", y: 758843},
{label: "East South Central", y: 475014}
],
Midwest: [
{label: "West North Central", y: 1347716},
{label: "East North Central", y: 780541}
],
Northeast: [
{label: "Middle Atlantic", y: 283168},
{label: "New England", y: 186447},
],
Pacific: [
{label: "Alaska", y: 1723337},
{label: "California", y: 423972},
{label: "Oregon", y: 254799},
{label: "Washington", y: 184661},
{label: "Hawaii", y: 28313}
],
Mountain: [
{label: "Montana", y: 380831},
{label: "New Mexico", y: 314917},
{label: "Arizona", y: 295234},
{label: "Nevada", y: 286380},
{label: "Colorado", y: 269601},
{label: "Utah", y: 219882},
{label: "Wyoming", y: 253335},
{label: "Idaho", y: 216443}
],
"West South Central": [
{label: "Texas", y: 695662},
{label: "Oklahoma", y: 181037},
{label: "Arkansas", y: 137732},
{label: "Louisiana", y: 135659}
],
"South Atlantic": [
{label: "Florida", y: 170312},
{label: "Georgia", y: 153910},
{label: "North Carolina", y: 139391},
{label: "Virginia", y: 110787},
{label: "South Carolina", y: 82933},
{label: "West Virginia", y: 62756},
{label: "Maryland", y: 32131},
{label: "Delaware", y: 6446}
],
"East South Central": [
{label: "Alabama", y: 135767},
{label: "Mississippi", y: 125438},
{label: "Tennessee", y: 109153},
{label: "Kentucky", y: 104656}
],
"West North Central": [
{label: "Minnesota", y: 225163},
{label: "Kansas", y: 213100},
{label: "Nebraska", y: 200330},
{label: "South Dakota", y: 199729},
{label: "North Dakota", y: 183108},
{label: "Missouri", y: 180540},
{label: "Iowa", y: 145746}
],
"East North Central": [
{label: "Michigan", y: 250487},
{label: "Wisconsin", y: 169635},
{label: "Illinois", y: 149995},
{label: "Ohio", y: 116098},
{label: "Indiana", y: 94326}
],
"Middle Atlantic": [
{label: "New York", y: 141297},
{label: "Pennsylvania", y: 119280}
{label: "New Jersey", y: 22591}
],
"New England": [
{label: "Maine", y: 91633},
{label: "Massachusetts", y: 27336},
{label: "Vermont", y: 24906},
{label: "New Hampshire", y: 24214},
{label: "Connecticut", y: 14357},
{label: "Rhode Island", y: 4001}
]
}
}
The first group, "Region", will be the first-shown label. When you drill down on the label "South", you'll move to the group "South".
Expand the playDataPoint
function to include a resonance value. resonance
will be a number between 0 and 1, indicating a percent of the maximum amount of resonance that can be played. By default, the value is 0.
When this is included, the data point should have resonance/reverb/echo-y version of the data point being played. This will be used in bubble plots and area bar charts to represent the volume of the data point.
We expect users to get rough, estimated vibes from this sonification. We want users to be able to tell if something is "a lot", "a little", or "a medium amount". The user does not need to be able to distinguish small differences between data points.
When SVG file contains manipulable DOM tree, is it possible to embed C2M's keyboard and visual highlight events into SVG elements?
For example, the following SVG barplot has 7 bars denoted with <rect>
tag and some id patterns. I can retrieve them via svg.querySelectorAll("g[id^='geom_rect.'] rect");
.
I want to dynamically and visually highlight each bar element that moves along with C2M sonification from left to right. I have done this by using our team's own js module, but I am currently looking for an integrated solution.
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="730.19px" height="730.19px" viewBox="0 0 730.19 730.19" version="1.1">
<metadata xmlns:gridsvg="http://www.stat.auckland.ac.nz/~paul/R/gridSVG/">
<gridsvg:generator name="gridSVG" version="1.7-4" time="2022-08-07 21:32:46" />
<gridsvg:argument name="name" value="barplot.svg" />
<gridsvg:argument name="exportCoords" value="none" />
<gridsvg:argument name="exportMappings" value="none" />
<gridsvg:argument name="exportJS" value="none" />
<gridsvg:argument name="res" value="72" />
<gridsvg:argument name="prefix" value="" />
<gridsvg:argument name="addClasses" value="FALSE" />
<gridsvg:argument name="indent" value="TRUE" />
<gridsvg:argument name="htmlWrapper" value="FALSE" />
<gridsvg:argument name="usePaths" value="vpPaths" />
<gridsvg:argument name="uniqueNames" value="TRUE" />
<gridsvg:separator name="id.sep" value="." />
<gridsvg:separator name="gPath.sep" value="::" />
<gridsvg:separator name="vpPath.sep" value="::" />
</metadata>
<g transform="translate(0, 730.19) scale(1, -1)">
<g id="gridSVG" fill="rgb(255,255,255)" stroke="rgb(0,0,0)" stroke-dasharray="none" stroke-width="0.75" font-size="12" font-family="Helvetica, Arial, FreeSans, Liberation Sans, Nimbus Sans L, sans-serif" opacity="1" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-opacity="1" fill-opacity="1" font-weight="normal" font-style="normal">
<g id="layout.1">
<g id="layout.2">
<defs>
<clipPath id="layout::background.1-9-12-1.1.clipPath">
<rect x="0" y="0" width="730.19" height="730.19" fill="none" stroke="none" />
</clipPath>
</defs>
<g id="layout::background.1-9-12-1.1" clip-path="url(#layout::background.1-9-12-1.1.clipPath)">
<g id="background.1-9-12-1.1">
<rect id="background.1-9-12-1.1.1" x="0" y="0" width="730.19" height="730.19" transform="" stroke-width="1.07" stroke="rgb(255,255,255)" fill="rgb(255,255,255)" stroke-dasharray="none" stroke-opacity="1" fill-opacity="1" />
</g>
</g>
<defs>
<clipPath id="layout::panel.7-5-7-5.1.clipPath">
<rect x="33.48" y="31.91" width="691.24" height="692.8" fill="none" stroke="none" />
</clipPath>
</defs>
<g id="layout::panel.7-5-7-5.1" clip-path="url(#layout::panel.7-5-7-5.1.clipPath)">
<g id="panel.7-5-7-5.1">
<g id="grill.gTree.67.1">
<g id="panel.background..rect.60.1">
<rect id="panel.background..rect.60.1.1" x="33.48" y="31.91" width="691.24" height="692.8" transform="" stroke-width="1.07" stroke="none" fill="rgb(235,235,235)" stroke-dasharray="none" stroke-opacity="0" fill-opacity="1" />
</g>
<g id="panel.grid.minor.y..polyline.62.1">
<polyline id="panel.grid.minor.y..polyline.62.1.1" points="33.48,164.99 724.72,164.99" stroke="rgb(255,255,255)" fill="none" stroke-width="0.53" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
<polyline id="panel.grid.minor.y..polyline.62.1.2" points="33.48,368.15 724.72,368.15" stroke="rgb(255,255,255)" fill="none" stroke-width="0.53" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
<polyline id="panel.grid.minor.y..polyline.62.1.3" points="33.48,571.32 724.72,571.32" stroke="rgb(255,255,255)" fill="none" stroke-width="0.53" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
</g>
<g id="panel.grid.major.y..polyline.64.1">
<polyline id="panel.grid.major.y..polyline.64.1.1" points="33.48,63.4 724.72,63.4" stroke="rgb(255,255,255)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
<polyline id="panel.grid.major.y..polyline.64.1.2" points="33.48,266.57 724.72,266.57" stroke="rgb(255,255,255)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
<polyline id="panel.grid.major.y..polyline.64.1.3" points="33.48,469.74 724.72,469.74" stroke="rgb(255,255,255)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
<polyline id="panel.grid.major.y..polyline.64.1.4" points="33.48,672.91 724.72,672.91" stroke="rgb(255,255,255)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
</g>
<g id="panel.grid.major.x..polyline.66.1">
<polyline id="panel.grid.major.x..polyline.66.1.1" points="91.08,31.91 91.08,724.72" stroke="rgb(255,255,255)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
<polyline id="panel.grid.major.x..polyline.66.1.2" points="187.09,31.91 187.09,724.72" stroke="rgb(255,255,255)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
<polyline id="panel.grid.major.x..polyline.66.1.3" points="283.09,31.91 283.09,724.72" stroke="rgb(255,255,255)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
<polyline id="panel.grid.major.x..polyline.66.1.4" points="379.1,31.91 379.1,724.72" stroke="rgb(255,255,255)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
<polyline id="panel.grid.major.x..polyline.66.1.5" points="475.1,31.91 475.1,724.72" stroke="rgb(255,255,255)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
<polyline id="panel.grid.major.x..polyline.66.1.6" points="571.11,31.91 571.11,724.72" stroke="rgb(255,255,255)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
<polyline id="panel.grid.major.x..polyline.66.1.7" points="667.11,31.91 667.11,724.72" stroke="rgb(255,255,255)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
</g>
</g>
<g id="geom_rect.rect.56.1">
<rect id="geom_rect.rect.56.1.1" x="47.88" y="63.4" width="86.4" height="50.79" transform="" stroke="none" fill="rgb(89,89,89)" stroke-width="1.07" stroke-dasharray="none" stroke-linejoin="miter" stroke-linecap="square" stroke-opacity="0" fill-opacity="1" />
<rect id="geom_rect.rect.56.1.2" x="143.88" y="63.4" width="86.4" height="477.45" transform="" stroke="none" fill="rgb(89,89,89)" stroke-width="1.07" stroke-dasharray="none" stroke-linejoin="miter" stroke-linecap="square" stroke-opacity="0" fill-opacity="1" />
<rect id="geom_rect.rect.56.1.3" x="239.89" y="63.4" width="86.4" height="416.5" transform="" stroke="none" fill="rgb(89,89,89)" stroke-width="1.07" stroke-dasharray="none" stroke-linejoin="miter" stroke-linecap="square" stroke-opacity="0" fill-opacity="1" />
<rect id="geom_rect.rect.56.1.4" x="335.89" y="63.4" width="86.4" height="111.74" transform="" stroke="none" fill="rgb(89,89,89)" stroke-width="1.07" stroke-dasharray="none" stroke-linejoin="miter" stroke-linecap="square" stroke-opacity="0" fill-opacity="1" />
<rect id="geom_rect.rect.56.1.5" x="431.9" y="63.4" width="86.4" height="335.23" transform="" stroke="none" fill="rgb(89,89,89)" stroke-width="1.07" stroke-dasharray="none" stroke-linejoin="miter" stroke-linecap="square" stroke-opacity="0" fill-opacity="1" />
<rect id="geom_rect.rect.56.1.6" x="527.9" y="63.4" width="86.4" height="355.54" transform="" stroke="none" fill="rgb(89,89,89)" stroke-width="1.07" stroke-dasharray="none" stroke-linejoin="miter" stroke-linecap="square" stroke-opacity="0" fill-opacity="1" />
<rect id="geom_rect.rect.56.1.7" x="623.91" y="63.4" width="86.4" height="629.82" transform="" stroke="none" fill="rgb(89,89,89)" stroke-width="1.07" stroke-dasharray="none" stroke-linejoin="miter" stroke-linecap="square" stroke-opacity="0" fill-opacity="1" />
</g>
</g>
</g>
<g id="layout::spacer.8-6-8-6.1" />
<g id="layout::spacer.8-4-8-4.1" />
<g id="layout::spacer.6-6-6-6.1" />
<g id="layout::spacer.6-4-6-4.1" />
<g id="layout::axis-t.6-5-6-5.1" />
<g id="layout::axis-l.7-4-7-4.1">
<g id="layout::axis-l.7-4-7-4::GRID.VP.16.1">
<g id="axis-l.7-4-7-4.1">
<g id="layout::axis-l.7-4-7-4::GRID.VP.16::axis.1">
<g id="axis.1">
<g id="layout::axis-l.7-4-7-4::GRID.VP.16::axis::axis.1-1-1-1.1">
<g id="layout::axis-l.7-4-7-4::GRID.VP.16::axis::axis.1-1-1-1::GRID.VP.14.1" font-size="8.8" stroke="rgb(77,77,77)" font-family="Helvetica, Arial, FreeSans, Liberation Sans, Nimbus Sans L, sans-serif" stroke-opacity="1" font-weight="normal" font-style="normal">
<g id="layout::axis-l.7-4-7-4::GRID.VP.16::axis::axis.1-1-1-1::GRID.VP.14::GRID.VP.15.1">
<g id="axis.1-1-1-1.1">
<g id="GRID.text.74.1">
<g id="GRID.text.74.1.1" transform="translate(28.55, 63.4)" stroke-width="0.1">
<g id="GRID.text.74.1.1.scale" transform="scale(1, -1)">
<text x="0" y="0" id="GRID.text.74.1.1.text" text-anchor="end" font-size="8.8" stroke="rgb(77,77,77)" font-family="Helvetica, Arial, FreeSans, Liberation Sans, Nimbus Sans L, sans-serif" fill="rgb(77,77,77)" stroke-opacity="1" fill-opacity="1" font-weight="normal" font-style="normal">
<tspan id="GRID.text.74.1.1.tspan.1" dy="3.23" x="0">0</tspan>
</text>
</g>
</g>
<g id="GRID.text.74.1.2" transform="translate(28.55, 266.57)" stroke-width="0.1">
<g id="GRID.text.74.1.2.scale" transform="scale(1, -1)">
<text x="0" y="0" id="GRID.text.74.1.2.text" text-anchor="end" font-size="8.8" stroke="rgb(77,77,77)" font-family="Helvetica, Arial, FreeSans, Liberation Sans, Nimbus Sans L, sans-serif" fill="rgb(77,77,77)" stroke-opacity="1" fill-opacity="1" font-weight="normal" font-style="normal">
<tspan id="GRID.text.74.1.2.tspan.1" dy="3.23" x="0">20</tspan>
</text>
</g>
</g>
<g id="GRID.text.74.1.3" transform="translate(28.55, 469.74)" stroke-width="0.1">
<g id="GRID.text.74.1.3.scale" transform="scale(1, -1)">
<text x="0" y="0" id="GRID.text.74.1.3.text" text-anchor="end" font-size="8.8" stroke="rgb(77,77,77)" font-family="Helvetica, Arial, FreeSans, Liberation Sans, Nimbus Sans L, sans-serif" fill="rgb(77,77,77)" stroke-opacity="1" fill-opacity="1" font-weight="normal" font-style="normal">
<tspan id="GRID.text.74.1.3.tspan.1" dy="3.23" x="0">40</tspan>
</text>
</g>
</g>
<g id="GRID.text.74.1.4" transform="translate(28.55, 672.91)" stroke-width="0.1">
<g id="GRID.text.74.1.4.scale" transform="scale(1, -1)">
<text x="0" y="0" id="GRID.text.74.1.4.text" text-anchor="end" font-size="8.8" stroke="rgb(77,77,77)" font-family="Helvetica, Arial, FreeSans, Liberation Sans, Nimbus Sans L, sans-serif" fill="rgb(77,77,77)" stroke-opacity="1" fill-opacity="1" font-weight="normal" font-style="normal">
<tspan id="GRID.text.74.1.4.tspan.1" dy="3.23" x="0">60</tspan>
</text>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
<g id="layout::axis-l.7-4-7-4::GRID.VP.16::axis::axis.1-2-1-2.1">
<g id="axis.1-2-1-2.1">
<polyline id="axis.1-2-1-2.1.1" points="30.74,63.4 33.48,63.4" stroke="rgb(51,51,51)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
<polyline id="axis.1-2-1-2.1.2" points="30.74,266.57 33.48,266.57" stroke="rgb(51,51,51)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
<polyline id="axis.1-2-1-2.1.3" points="30.74,469.74 33.48,469.74" stroke="rgb(51,51,51)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
<polyline id="axis.1-2-1-2.1.4" points="30.74,672.91 33.48,672.91" stroke="rgb(51,51,51)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
</g>
</g>
</g>
</g>
</g>
</g>
</g>
<g id="layout::axis-r.7-6-7-6.1" />
<g id="layout::axis-b.8-5-8-5.1">
<g id="layout::axis-b.8-5-8-5::GRID.VP.13.1">
<g id="axis-b.8-5-8-5.1">
<g id="layout::axis-b.8-5-8-5::GRID.VP.13::axis.1">
<g id="axis.2">
<g id="layout::axis-b.8-5-8-5::GRID.VP.13::axis::axis.1-1-1-1.1">
<g id="axis.1-1-1-1.2">
<polyline id="axis.1-1-1-1.2.1" points="91.08,29.17 91.08,31.91" stroke="rgb(51,51,51)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
<polyline id="axis.1-1-1-1.2.2" points="187.09,29.17 187.09,31.91" stroke="rgb(51,51,51)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
<polyline id="axis.1-1-1-1.2.3" points="283.09,29.17 283.09,31.91" stroke="rgb(51,51,51)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
<polyline id="axis.1-1-1-1.2.4" points="379.1,29.17 379.1,31.91" stroke="rgb(51,51,51)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
<polyline id="axis.1-1-1-1.2.5" points="475.1,29.17 475.1,31.91" stroke="rgb(51,51,51)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
<polyline id="axis.1-1-1-1.2.6" points="571.11,29.17 571.11,31.91" stroke="rgb(51,51,51)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
<polyline id="axis.1-1-1-1.2.7" points="667.11,29.17 667.11,31.91" stroke="rgb(51,51,51)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
</g>
</g>
<g id="layout::axis-b.8-5-8-5::GRID.VP.13::axis::axis.2-1-2-1.1">
<g id="layout::axis-b.8-5-8-5::GRID.VP.13::axis::axis.2-1-2-1::GRID.VP.11.1" font-size="8.8" stroke="rgb(77,77,77)" font-family="Helvetica, Arial, FreeSans, Liberation Sans, Nimbus Sans L, sans-serif" stroke-opacity="1" font-weight="normal" font-style="normal">
<g id="layout::axis-b.8-5-8-5::GRID.VP.13::axis::axis.2-1-2-1::GRID.VP.11::GRID.VP.12.1">
<g id="axis.2-1-2-1.1">
<g id="GRID.text.70.1">
<g id="GRID.text.70.1.1" transform="translate(91.08, 26.98)" stroke-width="0.1">
<g id="GRID.text.70.1.1.scale" transform="scale(1, -1)">
<text x="0" y="0" id="GRID.text.70.1.1.text" text-anchor="middle" font-size="8.8" stroke="rgb(77,77,77)" font-family="Helvetica, Arial, FreeSans, Liberation Sans, Nimbus Sans L, sans-serif" fill="rgb(77,77,77)" stroke-opacity="1" fill-opacity="1" font-weight="normal" font-style="normal">
<tspan id="GRID.text.70.1.1.tspan.1" dy="6.46" x="0">2seater</tspan>
</text>
</g>
</g>
<g id="GRID.text.70.1.2" transform="translate(187.09, 26.98)" stroke-width="0.1">
<g id="GRID.text.70.1.2.scale" transform="scale(1, -1)">
<text x="0" y="0" id="GRID.text.70.1.2.text" text-anchor="middle" font-size="8.8" stroke="rgb(77,77,77)" font-family="Helvetica, Arial, FreeSans, Liberation Sans, Nimbus Sans L, sans-serif" fill="rgb(77,77,77)" stroke-opacity="1" fill-opacity="1" font-weight="normal" font-style="normal">
<tspan id="GRID.text.70.1.2.tspan.1" dy="6.46" x="0">compact</tspan>
</text>
</g>
</g>
<g id="GRID.text.70.1.3" transform="translate(283.09, 26.98)" stroke-width="0.1">
<g id="GRID.text.70.1.3.scale" transform="scale(1, -1)">
<text x="0" y="0" id="GRID.text.70.1.3.text" text-anchor="middle" font-size="8.8" stroke="rgb(77,77,77)" font-family="Helvetica, Arial, FreeSans, Liberation Sans, Nimbus Sans L, sans-serif" fill="rgb(77,77,77)" stroke-opacity="1" fill-opacity="1" font-weight="normal" font-style="normal">
<tspan id="GRID.text.70.1.3.tspan.1" dy="6.46" x="0">midsize</tspan>
</text>
</g>
</g>
<g id="GRID.text.70.1.4" transform="translate(379.1, 26.98)" stroke-width="0.1">
<g id="GRID.text.70.1.4.scale" transform="scale(1, -1)">
<text x="0" y="0" id="GRID.text.70.1.4.text" text-anchor="middle" font-size="8.8" stroke="rgb(77,77,77)" font-family="Helvetica, Arial, FreeSans, Liberation Sans, Nimbus Sans L, sans-serif" fill="rgb(77,77,77)" stroke-opacity="1" fill-opacity="1" font-weight="normal" font-style="normal">
<tspan id="GRID.text.70.1.4.tspan.1" dy="6.46" x="0">minivan</tspan>
</text>
</g>
</g>
<g id="GRID.text.70.1.5" transform="translate(475.1, 26.98)" stroke-width="0.1">
<g id="GRID.text.70.1.5.scale" transform="scale(1, -1)">
<text x="0" y="0" id="GRID.text.70.1.5.text" text-anchor="middle" font-size="8.8" stroke="rgb(77,77,77)" font-family="Helvetica, Arial, FreeSans, Liberation Sans, Nimbus Sans L, sans-serif" fill="rgb(77,77,77)" stroke-opacity="1" fill-opacity="1" font-weight="normal" font-style="normal">
<tspan id="GRID.text.70.1.5.tspan.1" dy="6.46" x="0">pickup</tspan>
</text>
</g>
</g>
<g id="GRID.text.70.1.6" transform="translate(571.11, 26.98)" stroke-width="0.1">
<g id="GRID.text.70.1.6.scale" transform="scale(1, -1)">
<text x="0" y="0" id="GRID.text.70.1.6.text" text-anchor="middle" font-size="8.8" stroke="rgb(77,77,77)" font-family="Helvetica, Arial, FreeSans, Liberation Sans, Nimbus Sans L, sans-serif" fill="rgb(77,77,77)" stroke-opacity="1" fill-opacity="1" font-weight="normal" font-style="normal">
<tspan id="GRID.text.70.1.6.tspan.1" dy="6.46" x="0">subcompact</tspan>
</text>
</g>
</g>
<g id="GRID.text.70.1.7" transform="translate(667.11, 26.98)" stroke-width="0.1">
<g id="GRID.text.70.1.7.scale" transform="scale(1, -1)">
<text x="0" y="0" id="GRID.text.70.1.7.text" text-anchor="middle" font-size="8.8" stroke="rgb(77,77,77)" font-family="Helvetica, Arial, FreeSans, Liberation Sans, Nimbus Sans L, sans-serif" fill="rgb(77,77,77)" stroke-opacity="1" fill-opacity="1" font-weight="normal" font-style="normal">
<tspan id="GRID.text.70.1.7.tspan.1" dy="6.46" x="0">suv</tspan>
</text>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
<g id="layout::xlab-t.5-5-5-5.1" />
<g id="layout::xlab-b.9-5-9-5.1">
<g id="layout::xlab-b.9-5-9-5::GRID.VP.17.1" font-size="11" stroke="rgb(0,0,0)" font-family="Helvetica, Arial, FreeSans, Liberation Sans, Nimbus Sans L, sans-serif" stroke-opacity="1" font-weight="normal" font-style="normal">
<g id="layout::xlab-b.9-5-9-5::GRID.VP.17::GRID.VP.18.1">
<g id="xlab-b.9-5-9-5.1">
<g id="GRID.text.78.1">
<g id="GRID.text.78.1.1" transform="translate(379.1, 15.8)" stroke-width="0.1">
<g id="GRID.text.78.1.1.scale" transform="scale(1, -1)">
<text x="0" y="0" id="GRID.text.78.1.1.text" text-anchor="middle" font-size="11" stroke="rgb(0,0,0)" font-family="Helvetica, Arial, FreeSans, Liberation Sans, Nimbus Sans L, sans-serif" fill="rgb(0,0,0)" stroke-opacity="1" fill-opacity="1" font-weight="normal" font-style="normal">
<tspan id="GRID.text.78.1.1.tspan.1" dy="7.9" x="0">class</tspan>
</text>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
<g id="layout::ylab-l.7-3-7-3.1">
<g id="layout::ylab-l.7-3-7-3::GRID.VP.19.1" font-size="11" stroke="rgb(0,0,0)" font-family="Helvetica, Arial, FreeSans, Liberation Sans, Nimbus Sans L, sans-serif" stroke-opacity="1" font-weight="normal" font-style="normal">
<g id="layout::ylab-l.7-3-7-3::GRID.VP.19::GRID.VP.20.1">
<g id="ylab-l.7-3-7-3.1">
<g id="GRID.text.81.1">
<g id="GRID.text.81.1.1" transform="translate(5.48, 378.31)" stroke-width="0.1">
<g id="GRID.text.81.1.1.scale" transform="scale(1, -1)">
<text x="0" y="0" id="GRID.text.81.1.1.text" transform="rotate(-90)" text-anchor="middle" font-size="11" stroke="rgb(0,0,0)" font-family="Helvetica, Arial, FreeSans, Liberation Sans, Nimbus Sans L, sans-serif" fill="rgb(0,0,0)" stroke-opacity="1" fill-opacity="1" font-weight="normal" font-style="normal">
<tspan id="GRID.text.81.1.1.tspan.1" dy="7.9" x="0">count</tspan>
</text>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
<g id="layout::ylab-r.7-7-7-7.1" />
<g id="layout::subtitle.4-5-4-5.1" />
<g id="layout::title.3-5-3-5.1" />
<g id="layout::caption.10-5-10-5.1" />
<g id="layout::tag.2-2-2-2.1" />
</g>
</g>
</g>
</g>
</svg>
For band, candlestick, and boxplot, we can either hear one stat separately or all stats altogether. However, I would like to customize the range chord. For example, I would like to hear open and close for candlestick chart vs. high and low. It would be great if users could customize the stat range combination following their needs.
this technique has been already demonstrated in other solutions, such as accessible graphs as well as brailleChart.
Line chart, candle plot, bar plot and histogram can use line-type braille pattern like ⣀⡠⠤⠔⠒⠊⠉
Boxplot: We may be able to represent boxplot pattern in braille unicode like this. I created this randomly, but this can show you my ideas (this has three outliers): ⠒⠒⠒⠿⠇⠿⠿⠒⠒⠒⠒ ⠠⠈⠠
Heat map braille pattern: we could display different dot patterns to represent different colors row by row just like below:⠿⠿⠿⠿⠿⠿⠿⠀⠇⠇⠇⠇⠇⠇⠇⠀⠣⠣⠣⠣⠣⠣⠣⠀⠭⠭⠭⠭⠭⠭⠭
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.