Facets Dive is a data visualization for interactively exploring large numbers of records at once—many thousands at a time. Each record should be an object with key/value pairs representing the features of that record, and the values should be strings or numbers.
In this section, you'll learn how to use Dive embedded in your on page or app. The two things you need are your own data, and the Dive Polymer element.
The <facets-dive>
element has many attributes you can set to customize its behavior, but the only one you absolutely must set is data
.
This should be an array of JavaScript objects, where each object represents a single record.
For example, say your data is a list of food items. Each food has a unique name, belongs to a category, and provides calories. As JSON, your data would look something like this:
[{
"name": "apple",
"category": "fruit",
"calories": 95
},{
"name": "broccoli",
"category": "vegetable",
"calories": 50
},{
...Many more foods...
}]
The objects don't all need to have exactly the same set of keys. If an object is missing keys that are present in another object, that record will still be shown in Dive.
At this time, Dive only handles numeric and string values. If the values on your objects are complex (like arrays, or nested objects), these will be cast as strings prior to being visualized.
By default, Dive will render text onto a circle to represent each data point. However, you can supply a sprite atlas that it can use instead.
A sprite atlas is one big image containing many tiny images at predictable coordinates. Starting from the top-left hand corner of the image, sprites proceed across and down, from left-to-right and from top-to-bottom.
For example, consider a data set with 10,000 data points. Indexed from zero, they'd be arranged in a sprite atlas like so:
+---------+---------+---------+- - - - -+---------+
| | | | | |
| 0 | 1 | 2 | ... | 99 |
| | | | | |
+---------+---------+---------+- - - - -+---------+
| | | | | |
| 100 | 101 | 102 | ... | 199 |
| | | | | |
+---------+---------+---------+- - - - -+---------+
| | | | | |
| 200 | 201 | 202 | ... | 299 |
| | | | | |
+---------+---------+---------+- - - - -+---------+
| | | | | |
. . . . .
| . | . | . | . | . |
. . . . .
| | | | | |
+---------+---------+---------+- - - - -+---------+
| | | | | |
| 9900 | 9901 | 9902 | ... | 9999 |
| | | | | |
+---------+---------+---------+- - - - -+---------+
To specify the URL to an atlas to use, set the atlasUrl
property of the Dive Polymer Element in JavaScript (or the atlas-url
attribute in HTML).
If the atlas image is served from a different domain than the visualization, it will have to use CORS headers to be useful.
In that case, you'll also have to set the crossOrigin
property (or cross-origin
HTML attribute) to be either anonymous
or use-credentials
just like you would for an <img>
or <video>
tag as described on Mozilla's CORS settings attributes page.
To correctly slice up the sprite atlas, Dive needs to know the width and height in pixels of each sprite.
You can set these with the spriteImageWidth
and spriteImageHeight
properties (sprite-image-width
and sprite-image-height
when setting them in HTML), respectively.
The project is built with Bazel.
Make sure you have installed Bazel and run the Bazel BUILD files prior to proceeding.
Provided you've loaded the <facets-dive>
Polymer element, you can insert an instance into your page like so.
<facets-dive></facets-dive>
To set the data, you'll need to add a little JavaScript.
In your code, first get a reference to this DOM element, then assign your array of objects to the data
attribute.
const vis = document.querySelector('facets-dive');
vis.data = [ ... your data ... ];
The test.html
and test.ts
files under components/facets_dive
include a simple example.
Dive is divided into three panels. From left-to-right they are the control panel, the main visualization, and the info panel.
Once data has been loaded into the visualization, users drive exploration by manipulating the controls in the control panel. There are four sections, each of which expand when clicked. They are Faceting, Positioning, Color, and Display.
Dive's main function is to lay records out in a grid formation. This is called faceting, and there are two directions that can be independently controlled: the vertical (row-based) and horizontal (column-based) directions.
When you select a feature to facet by in either direction, Dive will bucket the items by that feature. For numeric values, Dive divides up the range of values into equally sized numeric segments. For string values, Dive puts items together which share the same string value, and if there are too many, puts those in a bucket labeled other.
In addition, string values that contain spaces can be treated as an undifferentiated bag of words. When the user checks the Bag of Words box, Dive arranges the items by putting them together in terms of their most common word. This feature will likely be drastically changed or removed in the future.
By default, Dive will arrange items within each cell of the grid by stacking them.
Alternatively, the items can be placed in a scatter plot.
This is most useful when Faceting is set to <NONE>
.
Features with numeric values can be used for scatter plot positioning. Any items whose value is not a number will still be shown, but the value will be coerced to zero.
The Color Controls let you specify a field to use to color the individual items.
If a sprite atlas has not been specified, Dive will pick a feature to color by. The picking algorithim prioritizes features which have a small number of unique values, such as categorical features.
The Display Controls let you specify what Dive will render onto each point. If a sprite atlas has been specified, then Dive will default to showing the sprite for each point. If not, then Dive will select the feature whose values are most unique, then render those strings as text on top of a circle background.
Whether you're using a sprite atlas or not, you can interactively control which feature is rendered to the points using the Display dropdown.
To play around with Dive locally, you can run the demos with Bazel. These act as functional tests we use to perform manual tests.
Thanks to a collaboration with Quick Draw, one great way to try out Dive is to explore Quick Draw data.
To run the Quick Draw demo, open a terminal to your facets project directory, and run the following bazel command:
$ bazel run //facets_dive/demo
Once the server starts up, you can see the demo here: http://localhost:6006/facets-dive/demo/quickdraw.html
To test Dive using a simple, synthetic dataset, open a terminal to the facets project, then run the following command:
$ bazel run //facets_dive/components/facets_dive:devserver
Once this starts up, navigate to http://localhost:6006/facets-dive/components/facets-dive/runner.html.
Dive's lib
directory contains libraries that do most of the visualization grunt work.
To run the unit test suite for these libraries, open a terminal to the facets project, then run this command:
$ bazel run //facets_dive/lib/test:devserver
Once the server starts up, open a browser and navigate to http://localhost:6006/facets-dive/lib/test/runner.html. Then, open your browser's web developer console. You should see a report of all of the tests that were run, including a summary of how they did.
The Dive Polymer element is composed of several constituent sub-components.
Each of them (<facets-dive-info-card>
, <facets-dive-controls>
, and <facets-dive-vis>
) have integration tests of the same form, which we use to confirm that code additions build and load correctly.
Dive's properties can be accessed both as attributes on the <facets-dive>
element in HTML, and as properties on the FacetsDive
Polymer element in JavaScript.
IMPORTANT: When setting any of these properties on the <facets-dive>
element in HTML, use dashed-names-like-this, not camelCaseNamesLikeThis.
These properties relate to the data that Dive visualizes.
data
-Array<{}>
- An array of data objects to visualize.filteredDataIndices
-number[]
- An array of indices into the data objects array (optional). If this is non-null then only the entries in the data array with these indices are to be visualized.
Properties that influence how the sprites in the visualization are rendered.
spriteImageWidth
-number
- Width of sprite backing images in pixels. If not provided, a reasonable default will be set. (Usesprite-image-width
in HTML).spriteImageHeight
-number
- Height of sprite backing images in pixels. If not provided, a reasonable default will be set. (Usesprite-image-height
in HTML).atlasUrl
-string
- URL of an atlas image to use for backing sprites. Each sprite is mapped by its index within thedata
array to a rectangle of the atlas image. (Useatlas-url
in HTML).spriteUrl
-string
- URL of a single, default sprite image to use for backing sprites. Each sprite has this same image. If not provided, a generic looking dot will be used. (Usesprite-url
in HTML).crossOrigin
-string
- OptionalcrossOrigin
property to use onImage
elements. Described on MDN's CORS settings attributes page. If set, this should either beanonymous
, oruse-credentials
. This is necessary for using atlas or sprite images from any domain other than the one hosting the page. (Usecross-origin
in HTML).
These optional properties control various stylistic aspects of Dive.
height
-number
- Height of the element in pixels. If left unspecified, the element will grow to fill its parent element.gridFacetingVerticalLabelColor
-string
- Label color for grid faceting in the vertical direction. If not provided, a reasonable default will be set. (Usegrid-faceting-vertical-label-color
in HTML).gridFacetingHorizontalLabelColor
-string
- Label color for grid faceting in the horizontal direction. If not provided, a reasonable default will be set. (Usegrid-faceting-horizontal-label-color
in HTML).itemPositioningVerticalLabelColor
-string
- Label color for item positioning in the vertical direction. If not provided, a reasonable default will be set. (Useitem-positioning-vertical-label-color
in HTML).itemPositioningHorizontalLabelColor
-string
- Label color for item positioning in the horizontal direction. If not provided, a reasonable default will be set. (Useitem-positioning-horizontal-label-color
in HTML).
Properties that drive the interactivity of Dive. These are typically controlled by the user, but can also be set programatically after data has loaded.
verticalFacet
-string
- Name of the field (feature) of the data to facet by vertically (row-based).verticalBuckets
-number
- Number of buckets to use when faceting vertically (row-based).verticalBagOfWords
-boolean
- For string-based, multi-word fields, the visualization can treat the values as a bag-of-words, rather than as full strings. For example, say a field had values like "toy store" and "pet store". The bag-of-words capability would bucket all the "store" values together, or split them into "toy store" and "pet store" depending on the number of buckets. This property determines whether the vertical facet should be treated as a bag-of-words.horizontalFacet
-string
- Name of the field of the data to facet by horizontally.horizontalBuckets
-number
- Number of buckets to use when faceting horizontally.horizontalBagOfWords
-boolean
- Whether to treat the horizontal facet field as a bag of words.positionMode
-string
- Mode used for positioning items within grid cells. Choices arestacked
(the default) andscatter
.verticalPosition
-string
- Field used to position items along the vertical axis when in scatter mode.horizontalPosition
-string
- Field used to position items along the horizontal axis.colorBy
-string
- Field used to color items.imageFieldName
-string
- In the event that a per-sprite image is not available (no atlas), this holds the name of the field used to draw text onto the backing canvas behind the sprites. Say your data was a collection of books, each with a "title" attribute. IfimageFieldName
was set to"title"
, then the title of each book would be drawn onto a circle to represent that data point.paletteChoice
-string
- Which source color palette should be used for generating a data-specific color palette. The four recognized values arestandard
,warm
,cool
, andassist
. Each palette uses colors from the Material Design style guide.selectedData
-Array<{}>
- READ ONLY. The currently selected data objects. They will all be elements of the data array. Changed through user interaction (clicking sprites).
infoRenderer?
-(dataObject: {}, containerElem: Element) => void
- Callback function to use to render the content of a data object for the info pane. If not specified, theFacetsDiveInfoCard.defaultInfoRenderer
will be used.