Giter VIP home page Giter VIP logo

react-msa-viewer's Introduction

<MSAViewer />

Travis NPM codecov

react-msa-viewer is a performant, extendable, highly-customizable, production-ready React Component that renders a Multiple Sequence Alignment (MSA).

WARNING: Work in progress - use with caution

MSAViewer example

Getting started

import MSAViewer from '@plotly/react-msa-viewer';

function MSA() {
  const options = {
    sequences: [
      {
        name: "seq.1",
        sequence: "MEEPQSDPSIEP-PLSQETFSDLWKLLPENNVLSPLPS-QA-VDDLMLSPDDLAQWLTED"
      },
      {
        name: "seq.2",
        sequence: "MEEPQSDLSIEL-PLSQETFSDLWKLLPPNNVLSTLPS-SDSIEE-LFLSENVAGWLEDP"
      },
      {
        name: "seq.3",
        sequence: "MEEPQSDLSIEL-PLSQETFSDLWKLLPPNNVLSTLPS-SDSIEE-LFLSENVAGWLEDP"
      },
    ],
    colorScheme: "zappo",
  };
  return (
    <MSAViewer {...options} />
  );
}

Open on CodePen

Installation

For npm users, run:

npm i --save @plotly/react-msa-viewer

For yarn users, run:

yarn add @plotly/react-msa-viewer

Use your own layout

<MSAViewer> acts a Context Provider for all MSA subcomponents. Hence, it will automatically take care of synchronization between all MSA components in its tree:

import {
  Labels,
  MSAViewer,
  OverviewBar,
  PositionBar,
  SequenceOverview,
  SequenceViewer,
} from '@plotly/react-msa-viewer';

function MSA() {
  const options = {
    sequences: [
      {
        name: "seq.1",
        sequence: "MEEPQSDPSIEP-PLSQETFSDLWKLLPENNVLSPLPS-QA-VDDLMLSPDDLAQWLTED"
      },
      {
        name: "seq.2",
        sequence: "MEEPQSDLSIEL-PLSQETFSDLWKLLPPNNVLSTLPS-SDSIEE-LFLSENVAGWLEDP"
      },
      {
        name: "seq.3",
        sequence: "MEEPQSDLSIEL-PLSQETFSDLWKLLPPNNVLSTLPS-SDSIEE-LFLSENVAGWLEDP"
      },
    ],
  };
  return (
    <MSAViewer {...options}>
      <SequenceOverview method="information-content"/>
      <div style={{display: "flex"}} >
        <div>
          <SequenceViewer/>
          <br/>
          <OverviewBar/>
          <PositionBar/>
        </div>
        <Labels/>
      </div>
    </MSAViewer>
  );
}

Open on CodePen

Usage in Vanilla JS

Using the react-msa-viewer with React is highly recommended. However, it can be used in Vanilla JS:

<html>
<meta charset="utf-8" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/15.4.2/react-dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prop-types/15.5.2/prop-types.js"></script>
<script src="https://unpkg.com/@plotly/react-msa-viewer/dist/index.umd.min.js"></script>
<body>
  <div id="my-msa" />
  <script>
  var options = {
    sequences: [
      {
        name: "seq.1",
        sequence: "MEEPQSDPSIEP-PLSQETFSDLWKLLPENNVLSPLPS-QA-VDDLMLSPDDLAQWLTED"
      },
      {
        name: "seq.2",
        sequence: "MEEPQSDLSIEL-PLSQETFSDLWKLLPPNNVLSTLPS-SDSIEE-LFLSENVAGWLEDP"
      },
      {
        name: "seq.3",
        sequence: "MEEPQSDLSIEL-PLSQETFSDLWKLLPPNNVLSTLPS-SDSIEE-LFLSENVAGWLEDP"
      },
    ],
    colorScheme: "zappo",
   };
  ReactDOM.render(
    React.createElement(ReactMSAViewer.MSAViewer, options),
    document.getElementById('my-msa')
  );
  </script>
</body>
</html>

See an example on CodePen.

Props

Warning: these properties are still susceptible to a change at any moment.

MSAViewer (component)

A general-purpose layout for the MSA components

When children are passed it acts as a Context Provider for the msaStore, otherwise it provides a default layout and forwards it props the respective components.

Props

barAttributes

Attributes to apply to each bar.

type: object

barFillColor

Fill color of the OverviewBar, e.g. #999999

type: string

barMethod

Method to use for the OverviewBar:

  • information-content: Information entropy after Shannon of a column (scaled)
  • conservation: Conservation of a column (scaled)

type: enum('information-content'|'conservation')

barStyle

Inline styles to apply to each bar.

type: object

colorScheme

Colorscheme to use. Currently the follow colorschemes are supported: buried_index, clustal, clustal2, cinema, helix_propensity, hydro, lesk, mae, nucleotide, purine_pyrimidine, strand_propensity, taylor, turn_propensity, and zappo.

See msa-colorschemes for details.

type: custom

height

Height of the sequence viewer (in pixels), e.g. 500.

type: number

labelAttributes

Attributes to apply to each label.

type: object

labelComponent

Component to create labels from.

type: union(object|func)

labelStyle

Inline styles to apply to each label.

type: object

layout

Predefined layout scheme to use (only used when no child elements are provided). Available layouts: basic, inverse, full, compact, funky

type: enum('basic'|'default'|'inverse'|'full'|'compact'|'funky')

markerAttributes

Attributes to apply to each marker.

type: object

markerComponent

Component to create markers from.

type: union(object|func)

markerStartIndex

At which number the PositionBar marker should start counting. Typical values are: 1 (1-based indexing) and 0 (0-based indexing).

type: number

markerSteps

At which steps the position labels should appear, e.g. 2 for (1, 3, 5)

type: number

markerStyle

Inline styles to apply to each marker.

type: object

msaStore

A custom msaStore (created with createMSAStore). Useful for custom interaction with other components

type: object

onResidueClick

Callback fired when the mouse pointer clicked a residue.

type: func

onResidueDoubleClick

Callback fired when the mouse pointer clicked a residue.

type: func

onResidueMouseEnter

Callback fired when the mouse pointer is entering a residue.

type: func

onResidueMouseLeave

Callback fired when the mouse pointer is leaving a residue.

type: func

position

Current x and y position of the viewpoint in the main sequence viewer (in pixels). This specifies the position of the top-left corner of the viewpoint within the entire alignment, e.g. {xPos: 20, yPos: 5}.

type: custom

sequenceBorder

Whether to draw a border.

type: bool

sequenceBorderColor

Color of the border. Name, hex or RGB value.

type: string

sequenceBorderWidth

Width of the border.

type: number

sequenceOverflow

What should happen if content overflows.

type: enum("hidden"|"auto"|"scroll")

sequenceOverflowX

What should happen if x-axis content overflows (overwrites "overflow")

type: enum("hidden"|"auto"|"scroll"|"initial")

sequenceOverflowY

What should happen if y-axis content overflows (overwrites "overflow")

type: enum("hidden"|"auto"|"scroll"|"initial")

sequenceScrollBarPositionX

X Position of the scroll bar ("top or "bottom")

type: enum("top"|"bottom")

sequenceScrollBarPositionY

Y Position of the scroll bar ("left" or "right")

type: enum("left"|"right")

sequenceTextColor

Color of the text residue letters (name, hex or RGB value)

type: string

sequenceTextFont

Font to use when drawing the individual residues.

type: string

sequences (required)

Sequence data. sequences expects an array of individual sequences.

sequence: Raw sequence, e.g. MEEPQSDPSIEP (required) name: name of the sequence, e.g. Sequence X

Example:

const sequences = [
  {
    name: "seq.1",
    sequence: "MEEPQSDPSIEP-PLSQETFSDLWKLLPENNVLSPLPS-QA-VDDLMLSPDDLAQWLTED",
  },
  {
    name: "seq.2",
    sequence: "MEEPQSDLSIEL-PLSQETFSDLWKLLPPNNVLSTLPS-SDSIEE-LFLSENVAGWLEDP",
  },
];

type: arrayOf[SequencePropType]

tileHeight

Height of the main tiles (in pixels), e.g. 20

type: number

tileWidth

Width of the main tiles (in pixels), e.g. 20

type: number

width

Width of the sequence viewer (in pixels), e.g. 500.

type: number

Labels (component)

Displays the sequence names.

Props

cacheElements

defaultValue: 10

font

Font of the sequence labels, e.g. 20px Arial

type: string

labelAttributes

Attributes to apply to each label.

type: object

labelComponent

Component to create labels from.

type: union(object|func)

labelStyle

Inline styles to apply to each label.

type: object defaultValue: {}

style

Inline styles to apply to the Label component

type: object

OverviewBar (component)

Creates a small overview box of the sequences for a general overview.

Props

engine

Rendering engine: canvas or webgl (experimental).

type: enum('canvas'|'webgl') defaultValue: "canvas"

fillColor

Fill color of the OverviewBar, e.g. #999999

type: string defaultValue: "#999999"

height (required)

Width of the component (in pixels), e.g. 100

type: number defaultValue: 50

method

Method to use for the OverviewBar:

  • information-content: Information entropy after Shannon of a column (scaled)
  • conservation: Conservation of a column (scaled)

type: enum('information-content'|'conservation') defaultValue: "conservation"

style

Custom style configuration.

type: object

width (required)

Width of the component (in pixels), e.g. 100

type: number

PositionBar (component)

Displays the sequence names with an arbitrary Marker component

Props

cacheElements

defaultValue: 10

font

Font of the sequence labels, e.g. 20px Arial

type: string

height

Height of the PositionBar (in pixels), e.g. 100

type: number defaultValue: 15

markerAttributes

Attributes to apply to each marker.

type: object

markerComponent

Component to create markers from.

type: union(object|func)

markerSteps

At which steps the position labels should appear, e.g. 2 for (1, 3, 5)

type: number defaultValue: 2

markerStyle

Inline styles to apply to each marker.

type: object defaultValue: {}

startIndex

At which number the PositionBar marker should start counting. Typical values are: 1 (1-based indexing) and 0 (0-based indexing).

type: number defaultValue: 1

style

Inline styles to apply to the PositionBar component

type: object defaultValue: { font: "12px Arial", }

SequenceOverview (component)

Props

engine

Rendering engine: canvas or webgl (experimental).

type: enum('canvas'|'webgl') defaultValue: "canvas"

height (required)

Width of the component (in pixels), e.g. 100

type: number defaultValue: 50

style

Custom style configuration.

type: object

tileHeight

Height of a tile in the OverviewBar, e.g. 5

type: number defaultValue: 5

tileWidth

Width of a tile in the OverviewBar, e.g. 5

type: number defaultValue: 5

width (required)

Width of the component (in pixels), e.g. 100

type: number

SequenceViewer (component)

Component to draw the main sequence alignment.

Props

border

Whether to draw a border.

type: bool defaultValue: false

borderColor

Color of the border. Name, hex or RGB value.

type: string defaultValue: "black"

borderWidth

Width of the border.

type: number defaultValue: 1

cacheElements

Number of residues to prerender outside of the visible viewbox.

type: number defaultValue: 20

onResidueClick

Callback fired when the mouse pointer clicked a residue.

type: func

onResidueDoubleClick

Callback fired when the mouse pointer clicked a residue.

type: func

onResidueMouseEnter

Callback fired when the mouse pointer is entering a residue.

type: func

onResidueMouseLeave

Callback fired when the mouse pointer is leaving a residue.

type: func

overflow

What should happen if content overflows.

type: enum("hidden"|"auto"|"scroll") defaultValue: "hidden"

overflowX

What should happen if x-axis content overflows (overwrites "overflow")

type: enum("hidden"|"auto"|"scroll"|"initial") defaultValue: "auto"

overflowY

What should happen if y-axis content overflows (overwrites "overflow")

type: enum("hidden"|"auto"|"scroll"|"initial") defaultValue: "auto"

scrollBarPositionX

X Position of the scroll bar ("top or "bottom")

type: enum("top"|"bottom") defaultValue: "bottom"

scrollBarPositionY

Y Position of the scroll bar ("left" or "right")

type: enum("left"|"right") defaultValue: "right"

showModBar

Show the custom ModBar

type: bool defaultValue: false

textColor

Color of the text residue letters (name, hex or RGB value)

type: string defaultValue: "black"

textFont

Font to use when drawing the individual residues.

type: string defaultValue: "18px Arial"

xGridSize

Number of residues to cluster in one tile (x-axis) (default: 10)

type: number defaultValue: 10

yGridSize

Number of residues to cluster in one tile (y-axis) (default: 10)

type: number defaultValue: 10

Creating your own MSA components

The React MSA Viewer uses an Redux store internally. You can connect your components with it too.

import React, {Component} from 'react';
import {
  msaConnect,
  MSAViewer,
  SequenceViewer,
} from '@plotly/react-msa-viewer';

class MyFirstMSAPluginComponent extends React.Component {
  render() {
    const residue = "E";
    const style = {
      width: this.props.tileWidth,
      height: this.props.tileHeight,
      backgroundColor: this.props.colorScheme.getColor(residue),
    }
    return (
      <div style={style}>
        {residue}
      </div>
    );
  }
}

const mapStateToProps = state => {
  return {
    tileHeight: state.props.tileHeight,
    tileWidth: state.props.tileWidth,
    colorScheme: state.props.colorScheme,
  }
}

const MyFirstMSAPlugin = msaConnect(
  mapStateToProps,
)(MyFirstMSAPluginComponent);

function MyMSA() {
  return (
    <MSAViewer sequences={sequences}>
      <SequenceViewer />
      <br />
      <MyFirstMSAPlugin />
    </MSAViewer>
  );
}

Open on CodePen

However, for performance reasons you need to use a special mixin to listen for position events.

import {
  withPositionStore,
  MSAViewer,
  SequenceViewer,
} from '@plotly/react-msa-viewer';


class MyFirstMSAPlugin extends React.Component {
  shouldRerender(newPosition) {
     return true;
  }
  render() {
    return (
      <div>
        x: {this.position.xPos}, y: {this.position.yPos}
      </div>
    );
  }
}

// inject the MSAPositionStore as this.position
withPositionStore(MyFirstMSAPlugin);

function MyMSA() {
  return (
    <MSAViewer sequences={sequences}>
      <SequenceViewer />
      <MyFirstMSAPlugin />
    </MSAViewer>
  );
}

ReactDOM.render(<MyMSA />, document.getElementById("my-msa"));

Open on CodePen

Alternatively, you can also listen to events.

Listen to events

The MSAViewer components (and its subcomponents) provide a variety of callbacks like onResidueClick that can be used to plug with your code:

import {
  MSAViewer,
} from 'react-msa-viewer';

function MyMSA() {
  return <MSAViewer sequences={sequences} onResidueClick={console.log} />
}

Open on CodePen

Some events also trigger custom DOM events which might simply subscription outside of React:

<html>
<meta charset="utf-8" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/15.4.2/react-dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prop-types/15.5.2/prop-types.js"></script>
<script src="https://unpkg.com/@plotly/react-msa-viewer/dist/index.umd.min.js"></script>
<body>
  <div id="my-msa" />
  <script>
    var options = {
      sequences: [
        {
          name: "seq.1",
          sequence: "MEEPQSDPSIEP-PLSQETFSDLWKLLPENNVLSPLPS-QA-VDDLMLSPDDLAQWLTED"
        },
        {
          name: "seq.2",
          sequence: "MEEPQSDLSIEL-PLSQETFSDLWKLLPPNNVLSTLPS-SDSIEE-LFLSENVAGWLEDP"
        },
        {
          name: "seq.3",
          sequence: "MEEPQSDLSIEL-PLSQETFSDLWKLLPPNNVLSTLPS-SDSIEE-LFLSENVAGWLEDP"
        }
      ],
      colorScheme: "zappo"
    };
    var el = document.getElementById("my-msa");
    ReactDOM.render(React.createElement(ReactMSAViewer.MSAViewer, options), el);
    el.addEventListener('residueClick', (e) => console.log(e.detail));
  </script>
</body>
</html>

Open on CodePen.

The custom DOM events bubble up the tree and contain their payload in.detail.

Sending actions

While the most common way to update the MSA is to update its properties, you can also send a variety of actions to the MSAViewer.

import {
  MSAViewer,
} from 'react-msa-viewer';

class MyMSA extends React.Component {
  moveLeft = () => {
    this.msa.movePosition({yMovement: -10})
  }
  moveRight = () => {
    this.msa.movePosition({yMovement: 10})
  }
  jumpOrigin = () => {
    debugger;
    this.msa.movePosition({yPos: 0})
  }
  render() {
    return (
      <div>
        <MSAViewer sequences={sequences} ref={(ref) => this.msa = ref} />
        <button onClick={this.moveLeft}>Move left</button>
        <button onClick={this.moveRight}>Move right</button>
        <button onClick={this.jumpOrigin}>Jump to the origin</button>
      </div>
    );
  }
}

Open on CodePen

It's also possible to use actions to create a payload and dispatch it later:

import {
  MSAViewer,
} from 'react-msa-viewer';

class MyMSA extends React.Component {
  moveLeft = () => {
    const payload = actions.movePosition({yMovement: -10});
    this.msa.dispatch(payload);
  }
  moveRight = () => {
    const payload = actions.movePosition({yMovement: 10});
    this.msa.dispatch(payload);
  }
  jumpOrigin = () => {
    const payload = actions.updatePosition({yPos: 0});
    this.msa.dispatch(payload);
  }
  render() {
    return (
      <div>
        <MSAViewer sequences={sequences} ref={(ref) => this.msa = ref} />
        <button onClick={this.moveLeft}>Move left</button>
        <button onClick={this.moveRight}>Move right</button>
        <button onClick={this.jumpOrigin}>Jump to the origin</button>
      </div>
    );
  }
}

Development

Getting started

Get the code:

git clone https://github.com/plotly/react-msa-viewer

Install the project dev dependencies:

npm install

Contributing

Please, see the CONTRIBUTING file.

Contributor Code of Conduct

Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms. See CODE_OF_CONDUCT file.

License

react-msa-viewer is released under the MIT License. See the bundled LICENSE file for details.

react-msa-viewer's People

Contributors

alexcjohnson avatar wilzbach avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-msa-viewer's Issues

msa.js doesn't work with Firefox Nightly 85

On Firefox 85+, msa.js is broken on msa.biojs.net as well as on your demo site.

Note that Firefox 85 will be relased soon! (2021-01-26)

On msa.biojs.net:

Uncaught TypeError: t.on is not a function
    resetSeqs index.js:58
    e index.js:56
    resetSeqs index.js:59
    t index.js:14
    _loadSeqs msa.js:121
    initialize msa.js:79
    Backbone 3
    <anonymous> norowuvoqo.js:18
index.js:58:9
    resetSeqs index.js:58
    e index.js:56
    resetSeqs index.js:59
    t index.js:14
    _loadSeqs msa.js:121
    initialize msa.js:79
    Backbone 3
    <anonymous> norowuvoqo.js:18

on your site:

TypeError: e.on is not a function
    resetSeqs shallowEqual.js:4
    _ shallowEqual.js:4
    _ shallowEqual.js:4
    columnHeights shallowEqual.js:4
    c index.js:9
    o index.js:9
    s index.js:9
    o index.js:9
    s index.js:9
    o index.js:9
    value shallowEqual.js:4
    React 24
    706 shallowEqual.js:4
    706 shallowEqual.js:4
    Webpack 6
react-dom.production.min.js:13
    React 25
    706 shallowEqual.js:4
    706 shallowEqual.js:4
    Webpack 6

I already reported the issue here: wilzbach/msa#257

The developer said that he hasn't touched the code in years and is very busy on his new job. I hope that you can fix the issue!

Support collapsing columns

e.g. when columns have a low information content (typically gaps) a viewer might not want to look at them.
Also authors might want to hide uninteresting columns by default.

Experiment with extremely large alignments

  • sequence overview panel component needs to be able to sample multiple columns into one pixel
  • the sequence viewer component shouldn't display text if the tile size drops over a threshold (i.e. the letter couldn't be shown fully anymore)

Increase cache size for the HTML scrolling

Instead of just keeping the previous and next element extra in cache, the scrolling/dragging performance might be better if the last 5 + next 5 elements are kept in cache and thus rerendering needs to happen a lot less often.

Explain how to synchronize a SequenceViewer component with other components

A very common request from users is to be able to create their own custom MSA layout easily. Of course a few default layouts should be provided, but in my experience these will never be enough.
Thus, the documentation should explain how the current scrolling position can be synchronized between multiple components.

Improve the modbar

Status quo:

image

TODO:

  • make the zoom buttons functional
  • add possibly more buttons?
  • experiment with different layout positions

Demo code for Vanilla JS fails with "e.on is not a function"

I copied and pasted the VanillaJS code to a test.html.
Opened on chrome but the site stays blank, and returns the following error:

statSeqs.js:66 Uncaught TypeError: e.on is not a function
    at Us.resetSeqs (statSeqs.js:66:10)
    at new e (statSeqs.js:22:8)
    at e (statSeqs.js:14:12)
    at OverviewBar.js:78:21
    at index.js:70:25
    at index.js:30:25
    at index.js:84:33
    at t.<anonymous> (index.js:30:25)
    at index.js:80:37
    at t.bar (index.js:30:25)

Looks like some buggy line on the node module reselect/es/index.js
Any ideas?

Thanks in advance!
Pedro

Remove react-scripts

A custom bundling step (and thus webpack configuration) is already required anyway.

onResidue events

A user should be able to listen to these events:

  • onResidueClick
  • onResidueEnter
  • onResidueLeave
  • onResidueClick
  • onResidueDoubleClick

The following examples should be provided:

  • showing a tooltip on hover
  • showing extra information when clicking on a residue

Other tasks:

  • add documentation

Install warning.

When installing the npm package there is a warning:
warning react-msa-viewer > [email protected]: ๐Ÿ™Œ Thanks for using Babel: we recommend using babel-preset-env now: please read babeljs.io/env to update!

Overview Tile

  • Show the currently viewed area
  • Allow to move the currently viewed area
  • Subpixel problem: merge by majority
  • Use shading or transparency for not so bright colors as in the MSAViewer

image

Add more tests

  • test viewport scrolling in the FakeScrollBar
  • test viewport scrolling in the PositionBar

Support custom annotations and features

It might be interesting for users to plugin in their own annotations and domains directly into the MSA, e.g.

Examples on how this could look like:

image

image

(from the old MSA viewer)

image

(from the NCBI viewer)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.