Skip to content

Commit 0350893

Browse files
committed
Initial code
1 parent 322b9c9 commit 0350893

13 files changed

Lines changed: 823 additions & 24 deletions

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,6 @@ dist
2020
npm-debug.log*
2121
yarn-debug.log*
2222
yarn-error.log*
23+
24+
# idea
25+
.idea

README.md

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# react-mutation-plot
22

3-
> React based a mutation distribution graphics tool.
3+
> A React based mutation lollipop plot.
44
55
[![NPM](https://img.shields.io/npm/v/react-mutation-plot.svg)](https://www.npmjs.com/package/react-mutation-plot) [![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)
66

@@ -15,12 +15,20 @@ npm install --save react-mutation-plot
1515
```jsx
1616
import React, { Component } from 'react'
1717

18-
import MyComponent from 'react-mutation-plot'
18+
import Lollipop from 'react-mutation-plot'
1919

2020
class Example extends Component {
2121
render () {
2222
return (
23-
<MyComponent />
23+
<LollipopPlot
24+
domains={domains}
25+
lollipops={lollipops}
26+
vizWidth={vizWidth}
27+
vizHeight={vizHeight}
28+
hugoGeneSymbol={hugoGeneSymbol}
29+
xMax={xMax}
30+
yMax={yMax}
31+
/>
2432
)
2533
}
2634
}

example/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"react-mutation-plot": "link:.."
1313
},
1414
"scripts": {
15-
"start": "react-scripts start",
15+
"start": "PORT=3008 react-scripts start",
1616
"build": "react-scripts build",
1717
"test": "react-scripts test --env=jsdom",
1818
"eject": "react-scripts eject"

example/src/App.js

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,30 @@
1-
import React, { Component } from 'react'
1+
import React, {Component} from 'react'
22

3-
import ExampleComponent from 'react-mutation-plot'
3+
import LollipopPlot from 'react-mutation-plot'
4+
import {lollipops} from './mock/lollipops.json'
5+
import {domains} from './mock/domains.json'
46

7+
const mockData = {
8+
vizHeight: 130, // hardcoded
9+
vizWidth: 665, // hardcoded
10+
xMax: 1210, // protein length
11+
yMax: 23, // max #mutations
12+
hugoGeneSymbol: 'EGFR',
13+
lollipops: lollipops,
14+
domains: domains
15+
}
516
export default class App extends Component {
6-
render () {
17+
render() {
718
return (
8-
<div>
9-
<ExampleComponent text='Modern React component module' />
10-
</div>
19+
<LollipopPlot
20+
domains={mockData.domains}
21+
lollipops={mockData.lollipops}
22+
vizWidth={mockData.vizWidth}
23+
vizHeight={mockData.vizHeight}
24+
hugoGeneSymbol={mockData.hugoGeneSymbol}
25+
xMax={mockData.xMax}
26+
yMax={mockData.yMax}
27+
/>
1128
)
1229
}
1330
}

example/src/mock/domains.json.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
export const domains = [
2+
{
3+
'startCodon': 57,
4+
'endCodon': 167,
5+
'label': 'Recep_L_domain',
6+
'color': '#2dcf00',
7+
'tooltip': {
8+
'header': 'Recep_L_domain',
9+
'body': 'Recep_L_domain (57 - 167)'
10+
}
11+
},
12+
{
13+
'startCodon': 185,
14+
'endCodon': 338,
15+
'label': 'Furin-like',
16+
'color': '#ff5353',
17+
'tooltip': {
18+
'header': 'Furin-like'
19+
}
20+
},
21+
{
22+
'startCodon': 361,
23+
'endCodon': 480,
24+
'label': 'Recep_L_domain',
25+
'color': '#2dcf00'
26+
},
27+
{
28+
'startCodon': 505,
29+
'endCodon': 636,
30+
'label': 'GF_recep_IV',
31+
'color': '#5b5bff',
32+
'tooltip': {
33+
'header': 'Title',
34+
'body': 'Description'
35+
}
36+
},
37+
{
38+
'startCodon': 713,
39+
'endCodon': 965,
40+
'label': 'Pkinase_Tyr',
41+
'color': '#ebd61d',
42+
'tooltip': {
43+
'header': 'Title',
44+
'body': 'Description'
45+
}
46+
}
47+
]

example/src/mock/lollipops.json.js

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
export const lollipops = [
2+
{
3+
'codon': 858,
4+
'count': 23,
5+
'tooltip': {
6+
'header': 'Title',
7+
'body': 'Description'
8+
},
9+
'color': '#008000',
10+
'label': {
11+
'text': 'L858R',
12+
'textAnchor': 'middle',
13+
'fontSize': 10,
14+
'fontFamily': 'arial'
15+
}
16+
},
17+
{
18+
'codon': 746,
19+
'count': 17,
20+
'tooltip': {
21+
'header': 'Title',
22+
'body': 'Description'
23+
},
24+
'color': '#993404'
25+
},
26+
{
27+
'codon': 861,
28+
'count': 5,
29+
'tooltip': {
30+
'header': 'Title',
31+
'body': 'Description'
32+
},
33+
'color': '#008000'
34+
},
35+
{
36+
'codon': 747,
37+
'count': 5,
38+
'tooltip': {
39+
'header': 'Title',
40+
'body': 'Description'
41+
},
42+
'color': '#993404'
43+
},
44+
{
45+
'codon': 768,
46+
'count': 3,
47+
'tooltip': {
48+
'header': 'Title',
49+
'body': 'Description'
50+
},
51+
'color': '#008000'
52+
},
53+
{
54+
'codon': 754,
55+
'count': 3,
56+
'tooltip': {
57+
'header': 'Title',
58+
'body': 'Description'
59+
},
60+
'color': '#008000'
61+
},
62+
{
63+
'codon': 719,
64+
'count': 3,
65+
'tooltip': {
66+
'header': 'Title',
67+
'body': 'Description'
68+
},
69+
'color': '#008000'
70+
},
71+
{
72+
'codon': 709,
73+
'count': 3,
74+
'tooltip': {
75+
'header': 'Title',
76+
'body': 'Description'
77+
},
78+
'color': '#993404'
79+
},
80+
{
81+
'codon': 833,
82+
'count': 2,
83+
'tooltip': {
84+
'header': 'Title',
85+
'body': 'Description'
86+
},
87+
'color': '#008000'
88+
},
89+
{
90+
'codon': 1,
91+
'count': 1,
92+
'tooltip': {
93+
'header': 'Title',
94+
'body': 'Description'
95+
},
96+
'color': '#cf58bc'
97+
}
98+
]

package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
},
1515
"scripts": {
1616
"test": "cross-env CI=1 react-scripts test --env=jsdom",
17+
"coverage": "cross-env CI=1 react-scripts test --env=jsdom --coverage",
1718
"test:watch": "react-scripts test --env=jsdom",
1819
"build": "rollup -c",
1920
"start": "rollup -c -w",
@@ -72,5 +73,9 @@
7273
},
7374
"files": [
7475
"dist"
75-
]
76+
],
77+
"dependencies": {
78+
"prop-types": "^15.6.2",
79+
"react-tooltip": "^3.9.2"
80+
}
7681
}

src/components/Domain.js

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
import * as React from 'react'
2+
import PropTypes from 'prop-types'
3+
import {getTooltipContent} from './Tooltip'
4+
5+
export const domainSpec = PropTypes.shape({
6+
startCodon: PropTypes.number,
7+
endCodon: PropTypes.number,
8+
color: PropTypes.string,
9+
label: PropTypes.string,
10+
labelColor: PropTypes.string
11+
})
12+
13+
class Domain extends React.Component {
14+
centerX = () => {
15+
return this.props.x + (this.props.width / 2)
16+
}
17+
18+
centerY = () => {
19+
return this.props.y + (this.props.height / 2)
20+
}
21+
22+
displayText = () => {
23+
const label = document.getElementById(this.props.id)
24+
let labelLength = label ? label.textLength.baseVal.value : 0
25+
let displayText = this.props.label
26+
if (labelLength) {
27+
let substringLength = labelLength
28+
// Find the number of characters that will fit inside
29+
while ((substringLength > 0) &&
30+
(label.getSubStringLength(0, substringLength) > this.props.width)) {
31+
substringLength -= 1
32+
}
33+
if (substringLength < labelLength) {
34+
// If we have to do shortening
35+
substringLength -= 2 // make room for ellipsis ..
36+
if (substringLength <= 0) {
37+
// too short to show any string
38+
displayText = ''
39+
} else {
40+
// if it's long enough to show anything at all
41+
displayText = displayText.substr(0, substringLength) + '..'
42+
}
43+
}
44+
}
45+
return displayText
46+
}
47+
48+
makeTextElement = (reference) => {
49+
let props = {
50+
x: this.centerX(),
51+
y: this.centerY(),
52+
textAnchor: 'middle',
53+
dy: '0.3em',
54+
fill: (this.props.labelColor || '#FFFFFF'),
55+
style: {
56+
fontSize: '12px',
57+
fontFamily: 'arial'
58+
}
59+
}
60+
const text = (reference ? (this.props.label || '') : this.displayText())
61+
if (reference) {
62+
props.id = this.props.id
63+
props.visibility = 'hidden'
64+
props.style = {opacity: 0}
65+
}
66+
return (<text {...props}>{text}</text>)
67+
}
68+
69+
render() {
70+
return (
71+
<g>
72+
<rect
73+
x={this.props.x}
74+
y={this.props.y}
75+
width={this.props.width}
76+
height={this.props.height}
77+
fill={this.props.color}
78+
/>
79+
{this.makeTextElement(true)}
80+
{this.makeTextElement(false)}
81+
<rect
82+
x={this.props.x}
83+
y={this.props.y}
84+
width={this.props.width}
85+
height={this.props.height}
86+
style={{opacity: 0}}
87+
data-tip={getTooltipContent(this.props.tooltip)}
88+
data-for='svgTooltip'
89+
/>
90+
</g>
91+
)
92+
}
93+
}
94+
95+
Domain.propTypes = {
96+
x: PropTypes.number,
97+
y: PropTypes.number,
98+
width: PropTypes.number,
99+
height: PropTypes.number,
100+
color: PropTypes.string,
101+
label: PropTypes.string,
102+
labelColor: PropTypes.string,
103+
spec: domainSpec,
104+
tooltip: PropTypes.any
105+
}
106+
107+
export default Domain

0 commit comments

Comments
 (0)