react-msa-viewer

    1.0.1 • Public • Published

    <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

    Live demo

    MSAViewer example

    Checkout the storybook at https://msa.bio.sh

    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.

    Install

    npm i react-msa-viewer

    DownloadsWeekly Downloads

    69

    Version

    1.0.1

    License

    MIT

    Unpacked Size

    3.26 MB

    Total Files

    116

    Last publish

    Collaborators

    • jmmease
    • chriddyp
    • bpostlethwaite
    • alexcjohnson
    • nicolaskruchten
    • antrg
    • archmoj
    • xhlu
    • hammadtheone
    • plotlysteve
    • wilzbach