Skip to content

Commit

Permalink
Merge pull request #1721 from GMOD/adjust_feature_height
Browse files Browse the repository at this point in the history
Manually adjust feature height and spacing on alignments track
  • Loading branch information
rbuels authored Feb 23, 2021
2 parents fceb39a + 8ee6560 commit 720894f
Show file tree
Hide file tree
Showing 8 changed files with 230 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export class LayoutSession implements LayoutSessionProps {
maxHeight: readConfObject(this.config, 'maxHeight'),
displayMode: readConfObject(this.config, 'displayMode'),
pitchX: this.bpPerPx,
pitchY: 3,
pitchY: readConfObject(this.config, 'noSpacing') ? 1 : 3,
})
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,8 @@ export default observer(
<Typography>
Filter by tag name and value. Use * in the value field to get
all reads containing any value for that tag. Example: filter tag
name SA with value * to get all split/supplementary reads
name SA with value * to get all split/supplementary reads. Other
examples include HP for haplotype, or RG for read group
</Typography>
<TextField
className={classes.field}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import React, { useState } from 'react'
import { makeStyles } from '@material-ui/core/styles'
import {
Button,
TextField,
Typography,
IconButton,
Dialog,
DialogContent,
DialogTitle,
Checkbox,
FormControlLabel,
} from '@material-ui/core'
import CloseIcon from '@material-ui/icons/Close'

const useStyles = makeStyles(theme => ({
root: {
margin: theme.spacing(4),
},
closeButton: {
position: 'absolute',
right: theme.spacing(1),
top: theme.spacing(1),
color: theme.palette.grey[500],
},
}))

export default function SetMinMaxDlg(props: {
display: {
minScore: number
maxScore: number
setMinScore: Function
setMaxScore: Function
setFeatureHeight: Function
setNoSpacing: Function
featureHeightSetting: number
noSpacing: boolean
}
handleClose: () => void
}) {
const classes = useStyles()
const { display, handleClose } = props
const { featureHeightSetting, noSpacing: noSpacingSetting } = display

const [height, setHeight] = useState(`${featureHeightSetting}`)
const [noSpacing, setNoSpacing] = useState(noSpacingSetting)

const ok = height !== '' && !Number.isNaN(+height)

return (
<Dialog
open
onClose={handleClose}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<DialogTitle id="alert-dialog-title">
Set feature height
<IconButton
aria-label="close"
className={classes.closeButton}
onClick={handleClose}
>
<CloseIcon />
</IconButton>
</DialogTitle>
<DialogContent style={{ overflowX: 'hidden' }}>
<Typography>
Adjust the feature height and whether there is any spacing between
features. Setting feature height to 1 and removing spacing makes the
display very compact
</Typography>
<div className={classes.root}>
<Typography>Enter feature height: </Typography>
<TextField
value={height}
onChange={event => {
setHeight(event.target.value)
}}
/>
<FormControlLabel
control={
<Checkbox
checked={!!noSpacing}
onChange={() => setNoSpacing(val => !val)}
/>
}
label="Remove spacing between features in y-direction?"
/>

<Button
variant="contained"
color="primary"
type="submit"
style={{ marginLeft: 20 }}
disabled={!ok}
onClick={() => {
display.setFeatureHeight(
height !== '' && !Number.isNaN(+height) ? +height : undefined,
)
display.setNoSpacing(noSpacing)

handleClose()
}}
>
Submit
</Button>
</div>
</DialogContent>
</Dialog>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const useStyles = makeStyles(theme => ({
},
}))

export default function ColorByTagDlg(props: {
export default function SortByTagDlg(props: {
display: { setSortedBy: Function }
handleClose: () => void
}) {
Expand Down Expand Up @@ -50,6 +50,9 @@ export default function ColorByTagDlg(props: {
<DialogContent>
<div>
<Typography>Set the tag to sort by</Typography>
<Typography color="textSecondary">
Examples: HP for haplotype, RG for read group, etc.
</Typography>
<TextField
value={tag}
onChange={event => {
Expand Down
52 changes: 45 additions & 7 deletions plugins/alignments/src/LinearPileupDisplay/model.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { ConfigurationReference, getConf } from '@jbrowse/core/configuration'
import {
ConfigurationReference,
readConfObject,
getConf,
} from '@jbrowse/core/configuration'
import {
getParentRenderProps,
getRpcSessionId,
Expand Down Expand Up @@ -33,6 +37,7 @@ import LinearPileupDisplayBlurb from './components/LinearPileupDisplayBlurb'
import ColorByTagDlg from './components/ColorByTag'
import FilterByTagDlg from './components/FilterByTag'
import SortByTagDlg from './components/SortByTag'
import SetFeatureHeightDlg from './components/SetFeatureHeight'

// using a map because it preserves order
const rendererTypes = new Map([
Expand All @@ -54,6 +59,8 @@ const stateModelFactory = (
type: types.literal('LinearPileupDisplay'),
configuration: ConfigurationReference(configSchema),
showSoftClipping: false,
featureHeight: types.maybe(types.number),
noSpacing: types.maybe(types.boolean),
sortedBy: types.maybe(
types.model({
type: types.string,
Expand Down Expand Up @@ -94,6 +101,12 @@ const stateModelFactory = (
setCurrBpPerPx(n: number) {
self.currBpPerPx = n
},
setFeatureHeight(n: number) {
self.featureHeight = n
},
setNoSpacing(flag: boolean) {
self.noSpacing = flag
},

setColorScheme(colorScheme: { type: string; tag?: string }) {
self.colorTagMap = observable.map({}) // clear existing mapping
Expand Down Expand Up @@ -160,7 +173,8 @@ const stateModelFactory = (
const { sortedBy, colorBy, renderProps } = self
const view = getContainingView(self) as LGV

// continually generate the vc pairing, set and rerender if any new values seen
// continually generate the vc pairing, set and rerender if any
// new values seen
if (colorBy?.tag) {
const uniqueTagSet = await self.getUniqueTagValues(
colorBy,
Expand Down Expand Up @@ -280,6 +294,21 @@ const stateModelFactory = (
},
}
})

.views(self => ({
get rendererConfig() {
const configBlob =
getConf(self, ['renderers', self.rendererTypeName]) || {}
return self.rendererType.configSchema.create({
...configBlob,
height: self.featureHeight,
noSpacing: self.noSpacing,
})
},
get featureHeightSetting() {
return self.featureHeight
},
}))
.views(self => {
const { trackMenuItems } = self
return {
Expand Down Expand Up @@ -359,10 +388,10 @@ const stateModelFactory = (
return filters
},

get rendererConfig() {
const configBlob =
getConf(self, ['renderers', self.rendererTypeName]) || {}
return self.rendererType.configSchema.create(configBlob)
get featureHeightSetting() {
return (
self.featureHeight || readConfObject(self.rendererConfig, 'height')
)
},

get renderProps() {
Expand All @@ -379,7 +408,7 @@ const stateModelFactory = (
colorTagMap: JSON.parse(JSON.stringify(self.colorTagMap)),
filters: this.filters,
showSoftClip: self.showSoftClipping,
config: this.rendererConfig,
config: self.rendererConfig,
}
},

Expand Down Expand Up @@ -489,6 +518,15 @@ const stateModelFactory = (
},
],
},
{
label: 'Set feature height',
onClick: () => {
getContainingTrack(self).setDialogComponent(
SetFeatureHeightDlg,
self,
)
},
},
{
label: 'Filter by',
icon: FilterListIcon,
Expand Down
6 changes: 4 additions & 2 deletions plugins/alignments/src/PileupRenderer/PileupRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -526,8 +526,10 @@ export default class PileupRenderer extends BoxRendererType {
rect.width + 2 * padding,
heightPx,
)
ctx.fillStyle = 'white'
ctx.fillText(txt, mismatchLeftPx - rect.width / 2, topPx + heightPx)
if (heightPx > charHeight) {
ctx.fillStyle = 'white'
ctx.fillText(txt, mismatchLeftPx - rect.width / 2, topPx + heightPx)
}
}
}
}
Expand Down
5 changes: 5 additions & 0 deletions plugins/alignments/src/PileupRenderer/configSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ export default ConfigurationSchema(
defaultValue: 7,
functionSignature: ['feature'],
},
noSpacing: {
type: 'boolean',
description: 'remove spacing between features',
defaultValue: false,
},
},
{ explicitlyTyped: true },
)
Original file line number Diff line number Diff line change
Expand Up @@ -1415,6 +1415,63 @@ exports[`ConfigurationEditor widget renders with defaults of the PileupTrack sch
</button>
</div>
</div>
<div
class="MuiPaper-root makeStyles-paper MuiPaper-elevation1 MuiPaper-rounded"
>
<div
class="makeStyles-paperContent"
>
<div
class="MuiFormControl-root"
>
<label
class="MuiFormControlLabel-root"
>
<span
aria-disabled="false"
class="MuiButtonBase-root MuiIconButton-root PrivateSwitchBase-root MuiCheckbox-root MuiCheckbox-colorSecondary MuiIconButton-colorSecondary"
>
<span
class="MuiIconButton-label"
>
<input
class="PrivateSwitchBase-input"
data-indeterminate="false"
type="checkbox"
value=""
/>
<svg
aria-hidden="true"
class="MuiSvgIcon-root"
focusable="false"
viewBox="0 0 24 24"
>
<path
d="M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"
/>
</svg>
</span>
<span
class="MuiTouchRipple-root"
/>
</span>
<span
class="MuiTypography-root MuiFormControlLabel-label MuiTypography-body1"
>
noSpacing
</span>
</label>
<p
class="MuiFormHelperText-root"
>
remove spacing between features
</p>
</div>
</div>
<div
class="makeStyles-slotModeSwitch"
/>
</div>
</div>
</div>
</div>
Expand Down

0 comments on commit 720894f

Please sign in to comment.