visdesignlab / upset2

UpSet - Visualizing Intersecting Sets
https://upset.multinet.app/
BSD 3-Clause "New" or "Revised" License
41 stars 7 forks source link

UpSet 2.0 – Visualizing Intersecting Sets

UpSet 2 is deployed at https://upset.multinet.app/.

Deployment Status: Netlify Status

About

UpSet is an interactive, web based visualization technique designed to analyze set-based data. UpSet visualizes both, set intersections and their properties, and the items (elements) in the dataset.

Please see the https://upset.app for more info about UpSet.

This version is a re-implementation using modern web technologies of the original UpSet.

UpSet 2 is described in this short poster:

Kiran Gadhave, Hendrik Strobelt, Nils Gehlenborg, Alexander Lex
UpSet 2: From Prototype to Tool
Proceedings of the IEEE Information Visualization Conference – Posters (InfoVis ’19), 2019.

UpSet 2 is based on the original UpSet, which was first described in this paper:

Alexander Lex, Nils Gehlenborg, Hendrik Strobelt, Romain Vuillemot, Hanspeter Pfister
UpSet: Visualization of Intersecting Sets
IEEE Transactions on Visualization and Computer Graphics (InfoVis), 20(12): 1983--1992, doi:10.1109/TVCG.2014.2346248, 2014.

UpSet 2.0 as a React Component

UpSet 2.0 can be imported as a React component using:

npm install @visdesignlab/upset2-react

Note that UpSet 2.0 requires a react version of 16.0 or higher.

Import the component using import { Upset } from @visdesignlab/upset2-react in your react component.

UpSet 2.0 Data

Data structure

The raw data structure for UpSet should be a list of set membership objects.

Raw Data

The data object should be an array of objects. Each object should contain all the set membership boolean values as well as any attributes.

This data example shows only two characters from the Simpsons.

const rawData = [
   {
    "Name": "Homer",
    "School": false,
    "Blue Hair": false,
    "Duff Fan": true,
    "Evil": false,
    "Male": true,
    "Power Plant": true,
    "Age": 40
  },
  {
    "Name": "Marge",
    "School": false,
    "Blue Hair": true,
    "Duff Fan": false,
    "Evil": false,
    "Male": false,
    "Power Plant": false,
    "Age": 36
  },
]

The data and/or attributes objects can be JSON strings or traditional JS objects.

Loading Data into the UpSet 2.0 component

Loading Raw Data

Data uploaded to UpSet must follow the UpSet 2.0 Data Structure. Simply pass the data object to the Upset component in the data field.

The example below is a simple usecase for loading raw data into UpSet 2.0.

const main = () => {
  const rawData = [
    {
      "Name": "Homer",
      "School": false,
      "Blue Hair": false,
      "Duff Fan": true,
      "Evil": false,
      "Male": true,
      "Power Plant": true,
      "Age": 40
    },
    {
      "Name": "Marge",
      "School": false,
      "Blue Hair": true,
      "Duff Fan": false,
      "Evil": false,
      "Male": false,
      "Power Plant": false,
      "Age": 36
    },
  ];

  return <Upset data={rawData} />;
}
Pre-Processing Data

If you want to pre-process your data to gain access to the data objects generated and use by UpSet, or are having issues with the raw data loading, you must use the process function from UpSet 2.0 Core. First, import process from @visdesignlab/upset2-react. Then, before loading rendering the UpSet 2.0 component, call the process function, which takes the data and annotations objects as arguments.

The data object should be the same as raw data defined in Data Structure.

The annotations object should be an object with a nested object field columns. This field is a mapping of the column name to the column's data type. The columns field should contain an entry for each possible column in the data, as well as the type for each column.

The entry corresponding to the column which is the name of the item should be of type label. This will be used to generate ids and name the subsets. Note: There should only be one label column. Any entry for a set membership column should be a boolean type. Finally, any entry for an attribute column should be a number type.

In the example below, the item name is Name, noted by the label type. The sets are School, Blue Hair, Duff Fan, Evil, Male, and Power Plant. The only attribute in this dataset is Age, which is a number. This is clear in the annotations object, which denotes this.

const annotations = {
  "columns": {
    "Name": "label",
    "School": "boolean",
    "Blue Hair": "boolean",
    "Duff Fan": "boolean",
    "Evil": "boolean",
    "Male": "boolean",
    "Power Plant": "boolean",
    "Age": "number"
  }
}

The example below details a simple usecase of the process function.

import { Upset, process } from '@visdesignlab/upset2-react';

const main = () => {
  const rawData = [
    {
      "Name": "Homer",
      "School": false,
      "Blue Hair": false,
      "Duff Fan": true,
      "Evil": false,
      "Male": true,
      "Power Plant": true,
      "Age": 40
    },
    {
      "Name": "Marge",
      "School": false,
      "Blue Hair": true,
      "Duff Fan": false,
      "Evil": false,
      "Male": false,
      "Power Plant": false,
      "Age": 36
    },
  ];

  const annotations = {
    columns: {
      "Name": "label",
      "School": "boolean",
      "Blue Hair": "boolean",
      "Duff Fan": "boolean",
      "Evil": "boolean",
      "Male": "boolean",
      "Power Plant": "boolean",
      "Age": "number"
    }
  };

  const processedData = process(rawData, annotations);

  return <Upset data={processedData} />;
}

UpSet 2.0 component options

All options

Configuration (Grammar) options

The configuration (grammar) is used both as internal tracking for UpSet 2.0, and to generate the alt-text via Multinet's API. Other implementations which are attempting to generate text descriptions using the same API must generate a grammar containing the values below. Reference upset-alt-txt-gen for more information about generating text descriptions.

If no configuration options are provided, the default will be:

The configuration options are documented below:

To export the grammar of an UpSet 2.0 plot programmatically, use the exportState function. This function has the following parameters:

Example of full configuration (grammar) JSON produced for default Simpsons dataset:

{
  "plotInformation": {
    "description": "",
    "sets": "",
    "items": ""
  },
  "horizontal": false,
  "firstAggregateBy": "None",
  "firstOverlapDegree": 2,
  "secondAggregateBy": "None",
  "secondOverlapDegree": 2,
  "sortVisibleBy": "Alphabetical",
  "sortBy": "Size",
  "sortByOrder": "Descending",
  "filters": {
    "maxVisible": 6,
    "minVisible": 0,
    "hideEmpty": true,
    "hideNoSet": false
  },
  "visibleSets": [
    "Set_School",
    "Set_Blue Hair",
    "Set_Duff Fan",
    "Set_Evil",
    "Set_Male",
    "Set_Power Plant"
  ],
  "visibleAttributes": [
    "Age"
  ],
  "bookmarkedIntersections": [],
  "collapsed": [],
  "plots": {
    "scatterplots": [],
    "histograms": []
  },
  "allSets": [
    {
      "name": "Set_School",
      "size": 6
    },
    {
      "name": "Set_Blue Hair",
      "size": 3
    },
    {
      "name": "Set_Duff Fan",
      "size": 6
    },
    {
      "name": "Set_Evil",
      "size": 6
    },
    {
      "name": "Set_Male",
      "size": 18
    },
    {
      "name": "Set_Power Plant",
      "size": 5
    }
  ],
  "selected": null
}
Sidebar options

SidebarProps type:

interface SidebarProps {
  /**
   * Indicates whether the sidebar is open or closed.
   */
  open: boolean;

  /**
   * Callback function to close the sidebar.
   */
  close: () => void;
}
Alt Text Generation

Alt Text generation requires the use of a custom or imported Alt-Text generation function. In upset.multinet.app, we are using the Multinet API, which exposes an api call to the upset-alttxt python package.

Default Configuration

The default configuration for UpSet 2.0 shows the Aggregation/Filtering settings sidebar, sort the plot by Size (Descending), and shows up to the first 3 attributes in the data.

Example using Simpsons dataset:

<Upset data={simpsonsCharacterData} />

Default UpSet 2.0 plot configuration

Developer Docs

Developer documentation can be found at https://vdl.sci.utah.edu/upset2/.

For more information on documentation see the Developer Documentation Guidelines.

Local Installation

To deploy UpSet 2.0 locally it is necessary to install the Multinet infrastructure.

Multinet Installation

  1. Clone Multinet API, Multinet Client, and Multinet JS into individual folders.
  2. Follow the installation instructions for Multinet API and Multinet Client.

Upset Installation

  1. Clone the repository using git clone or download and extract the zip file.
  2. Open terminal in the cloned folder and run yarn install
  3. Run yarn build in the terminal to compile.
  4. Navigate to the upset2 folder.
  5. In packages/app copy .env.default and rename the copied file to .env
  6. In the OAUTH application created during the OAUTH API setup of Multinet API, add http://localhost:3000/ to the redirect uris field.
  7. Copy the Client id field in the application but do not modify the value
  8. Navigate to the .env file created in step 5.
  9. Paste the Client id to the field VITE_OAUTH_CLIENT_ID

Running the application

To run UpSet 2.0 locally, first, complete the Local Installation steps. Then, use yarn dev to run UpSet 2.0 on port 3000. A browser window for localhost:3000 will open during the launch process.

End To End (e2e) Testing

To run the playwright end to end tests, use the command: yarn test

To open the test in a UI view to track steps, append --ui.

This will launch a local server if there is not one already running on port 3000.

To add a test, add a .spec.ts file to e2e-tests. For information on how to use playwright, please see the playwright documentation.

Storybook development

Storybook can be used to test development of UpSet 2.0 as a react component. To run storybook, run cd packages/upset from the project root directory. Then, run yarn storybook. This will run Upset.stories.tsx, which opens a browser tab for the storybook. This will render the react component of UpSet with the simpsons dataset and stripped of any attribute or settings rendering.

A new story can be added by adding a {name}.stories.tsx file to packages/upset/stories/. New data can be added to the data subfolder in the same directory.

Developer Documentation Guidelines

When adding a new feature, ensure that your additions are well documented following JSDoc style annotations. Also, please add testing via Playwright, outlined in #end-to-end-e2e-testing.

To build the documentation locally, use the command: yarn doc. The default file output is at /docs.