react-msa-viewer
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
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} />
);
}
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>
);
}
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>
);
}
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"));
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} />
}
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>
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>
);
}
}
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