Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to display crosshatches on the wiggle line/xyplot renderer #1742

Merged
merged 3 commits into from
Feb 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,12 @@ interface SNPCoverageRendererProps {
regions: Region[]
bpPerPx: number
height: number
width: number
highResolutionScaling: number
blockKey: string
dataAdapter: BaseFeatureDataAdapter
notReady: boolean
scaleOpts: ScaleOpts
sessionId: string
signal: AbortSignal
displayModel: unknown
theme: ThemeOptions
}

Expand Down
14 changes: 14 additions & 0 deletions plugins/wiggle/src/LinePlotRenderer/LinePlotRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,12 @@ export default class extends WiggleBaseRenderer {
bpPerPx,
scaleOpts,
height: unadjustedHeight,
ticks: { values },
displayCrossHatches,
config,
} = props
const [region] = regions
const width = (region.end - region.start) / bpPerPx
const offset = YSCALEBAR_LABEL_OFFSET

// the adjusted height takes into account YSCALEBAR_LABEL_OFFSET from the
Expand Down Expand Up @@ -74,5 +77,16 @@ export default class extends WiggleBaseRenderer {
ctx.fillRect(leftPx, 0, w, height)
}
}

if (displayCrossHatches) {
ctx.lineWidth = 1
ctx.strokeStyle = 'rgba(200,200,200,0.8)'
values.forEach(tick => {
ctx.beginPath()
ctx.moveTo(0, Math.round(toY(tick)))
ctx.lineTo(width, Math.round(toY(tick)))
ctx.stroke()
})
}
}
}
Original file line number Diff line number Diff line change
@@ -1,61 +1,49 @@
import { getConf } from '@jbrowse/core/configuration'
import { BaseLinearDisplayComponent } from '@jbrowse/plugin-linear-genome-view'
import { observer } from 'mobx-react'
import React from 'react'
import { Axis, axisPropsFromTickScale, RIGHT } from 'react-d3-axis'
import { getScale } from '../../util'
import { WiggleDisplayModel, YSCALEBAR_LABEL_OFFSET } from '../models/model'
import { Axis, LEFT, RIGHT } from 'react-d3-axis'
import { WiggleDisplayModel } from '../models/model'

export const YScaleBar = observer(
({ model }: { model: WiggleDisplayModel }) => {
const { domain, height, scaleType } = model
const scale = getScale({
scaleType,
domain,
range: [height - YSCALEBAR_LABEL_OFFSET, YSCALEBAR_LABEL_OFFSET],
inverted: getConf(model, 'inverted'),
})
const ticks = height < 50 ? 2 : 4
const axisProps = axisPropsFromTickScale(scale, ticks)
const { values } = axisProps
({
model,
orientation,
}: {
model: WiggleDisplayModel
orientation?: string
}) => {
const { ticks } = model

return (
<svg
style={{
position: 'absolute',
top: 0,
left: 300,
pointerEvents: 'none',
height,
width: 50,
}}
>
<g transform="translate(0,5)" />
<Axis
{...axisProps}
values={values}
format={(n: number) => n}
style={{ orient: RIGHT }}
/>
</svg>
<Axis
{...ticks}
format={(n: number) => n}
style={{ orient: orientation === 'left' ? LEFT : RIGHT }}
/>
)
},
)

export default observer((props: { model: WiggleDisplayModel }) => {
const { model } = props
const { ready, stats, needsScalebar } = model
const { ready, stats, height, needsScalebar } = model
return (
<div>
<BaseLinearDisplayComponent {...props} />
<div
style={{
paddingTop: needsScalebar ? YSCALEBAR_LABEL_OFFSET : undefined,
paddingBottom: needsScalebar ? YSCALEBAR_LABEL_OFFSET : undefined,
}}
>
{ready && stats && needsScalebar ? <YScaleBar model={model} /> : null}
</div>
{ready && stats && needsScalebar ? (
<svg
style={{
position: 'absolute',
top: 0,
left: 300,
pointerEvents: 'none',
height,
width: 50,
}}
>
<YScaleBar model={model} />
</svg>
) : null}
</div>
)
})
56 changes: 54 additions & 2 deletions plugins/wiggle/src/LinearWiggleDisplay/models/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ import React from 'react'
import { AnyConfigurationSchemaType } from '@jbrowse/core/configuration/configurationSchema'
import { FeatureStats } from '@jbrowse/core/util/stats'
import { Feature } from '@jbrowse/core/util/simpleFeature'
import { getNiceDomain } from '../../util'
import { axisPropsFromTickScale } from 'react-d3-axis'
import { getNiceDomain, getScale } from '../../util'

import Tooltip from '../components/Tooltip'
import SetMinMaxDlg from '../components/SetMinMaxDialog'
Expand Down Expand Up @@ -65,8 +66,10 @@ const stateModelFactory = (
selectedRendering: types.optional(types.string, ''),
resolution: types.optional(types.number, 1),
fill: types.maybe(types.boolean),
rendererTypeNameState: types.maybe(types.string),
scale: types.maybe(types.string),
autoscale: types.maybe(types.string),
displayCrossHatches: types.maybe(types.boolean),
constraints: types.optional(
types.model({
max: types.maybe(types.number),
Expand Down Expand Up @@ -130,9 +133,17 @@ const stateModelFactory = (
self.constraints.max = val
},

setRendererType(val: string) {
self.rendererTypeNameState = val
},

setMinScore(val?: number) {
self.constraints.min = val
},

toggleCrossHatches() {
self.displayCrossHatches = !self.displayCrossHatches
},
}))
.views(self => ({
get TooltipComponent(): React.FC {
Expand All @@ -144,7 +155,8 @@ const stateModelFactory = (
},

get rendererTypeName() {
const viewName = getConf(self, 'defaultRendering')
const viewName =
self.rendererTypeNameState || getConf(self, 'defaultRendering')
const rendererType = rendererTypes.get(viewName)
if (!rendererType) {
throw new Error(`unknown alignments view name ${viewName}`)
Expand Down Expand Up @@ -184,6 +196,7 @@ const stateModelFactory = (
...configBlob,
filled: self.fill,
scaleType: this.scaleType,
displayCrossHatches: self.displayCrossHatches,
})
},
}))
Expand Down Expand Up @@ -245,11 +258,33 @@ const stateModelFactory = (
get autoscaleType() {
return self.autoscale || getConf(self, 'autoscale')
},

get displayCrossHatchesSetting() {
return (
self.displayCrossHatches ||
readConfObject(self.rendererConfig, 'displayCrossHatches')
)
},
}
})
.views(self => {
const { trackMenuItems } = self
return {
get ticks() {
const { scaleType, domain, height } = self
const range = [
height - YSCALEBAR_LABEL_OFFSET,
YSCALEBAR_LABEL_OFFSET,
]
const scale = getScale({
scaleType,
domain,
range,
inverted: getConf(self, 'inverted'),
})
const ticks = height < 50 ? 2 : 4
return axisPropsFromTickScale(scale, ticks)
},
get renderProps() {
return {
...self.composedRenderProps,
Expand All @@ -260,6 +295,8 @@ const stateModelFactory = (
scaleOpts: self.scaleOpts,
resolution: self.resolution,
height: self.height,
ticks: this.ticks,
displayCrossHatches: self.displayCrossHatches,
}
},

Expand Down Expand Up @@ -321,6 +358,21 @@ const stateModelFactory = (
self.toggleLogScale()
},
},
{
type: 'checkbox',
label: 'Draw cross hatches',
checked: self.displayCrossHatchesSetting,
onClick: () => {
self.toggleCrossHatches()
},
},
{
label: 'Renderer type',
subMenu: [...rendererTypes.keys()].map(key => ({
label: key,
onClick: () => self.setRendererType(key),
})),
},
{
label: 'Autoscale type',
subMenu: [
Expand Down
7 changes: 4 additions & 3 deletions plugins/wiggle/src/WiggleBaseRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { BaseFeatureDataAdapter } from '@jbrowse/core/data_adapters/BaseAdapter'
import ServerSideRendererType from '@jbrowse/core/pluggableElementTypes/renderers/ServerSideRendererType'
import React from 'react'
import { AnyConfigurationModel } from '@jbrowse/core/configuration/configurationSchema'
import { ThemeOptions } from '@material-ui/core'
import { ScaleOpts } from './util'

export interface WiggleBaseRendererProps {
Expand All @@ -16,15 +17,15 @@ export interface WiggleBaseRendererProps {
regions: Region[]
bpPerPx: number
height: number
width: number
highResolutionScaling: number
blockKey: string
dataAdapter: BaseFeatureDataAdapter
notReady: boolean
scaleOpts: ScaleOpts
sessionId: string
signal: AbortSignal
displayModel: unknown
displayCrossHatches: boolean
ticks: { values: number[] }
theme: ThemeOptions
}

export default abstract class extends ServerSideRendererType {
Expand Down
1 change: 1 addition & 0 deletions plugins/wiggle/src/XYPlotRenderer/XYPlotRenderer.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ test('several features', async () => {
bpPerPx: 3,
highResolutionScaling: 1,
height: 100,
ticks: { values: [0, 100] },
})

expect(result).toMatchSnapshot({
Expand Down
14 changes: 14 additions & 0 deletions plugins/wiggle/src/XYPlotRenderer/XYPlotRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@ export default class XYPlotRenderer extends WiggleBaseRenderer {
scaleOpts,
height: unadjustedHeight,
config,
ticks: { values },
displayCrossHatches,
} = props
const [region] = regions
const width = (region.end - region.start) / bpPerPx

// the adjusted height takes into account YSCALEBAR_LABEL_OFFSET from the
// wiggle display, and makes the height of the actual drawn area add
Expand Down Expand Up @@ -121,5 +124,16 @@ export default class XYPlotRenderer extends WiggleBaseRenderer {
ctx.fillRect(leftPx, 0, w, height)
}
}

if (displayCrossHatches) {
ctx.lineWidth = 1
ctx.strokeStyle = 'rgba(200,200,200,0.8)'
values.forEach(tick => {
ctx.beginPath()
ctx.moveTo(0, Math.round(toY(tick)))
ctx.lineTo(width, Math.round(toY(tick)))
ctx.stroke()
})
}
}
}
5 changes: 5 additions & 0 deletions plugins/wiggle/src/configSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ export default ConfigurationSchema(
'choose whether to use max/min/average or whiskers which combines all three into the same rendering',
defaultValue: 'whiskers',
},
displayCrossHatches: {
type: 'boolean',
description: 'choose to draw cross hatches (sideways lines)',
defaultValue: false,
},
},
{ explicitlyTyped: true },
)