Skip to content

Commit

Permalink
Add option to 'Hide small indels (<10bp)' (#4733)
Browse files Browse the repository at this point in the history
  • Loading branch information
cmdcolin authored Dec 19, 2024
1 parent 057168d commit 1d793a1
Show file tree
Hide file tree
Showing 24 changed files with 198 additions and 80 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ export function SharedLinearPileupDisplayMixin(
* #property
*/
jexlFilters: types.optional(types.array(types.string), []),
/**
* #property
*/
hideSmallIndelsSetting: types.maybe(types.boolean),
}),
)
.volatile(() => ({
Expand Down Expand Up @@ -130,10 +134,20 @@ export function SharedLinearPileupDisplayMixin(
},
}))
.views(self => ({
/**
* #getter
*/
get autorunReady() {
const view = getContainingView(self) as LGV
return view.initialized && self.statsReadyAndRegionNotTooLarge
},

/**
* #getter
*/
get hideSmallIndels() {
return self.hideSmallIndelsSetting
},
}))
.actions(self => ({
/**
Expand Down Expand Up @@ -265,24 +279,35 @@ export function SharedLinearPileupDisplayMixin(
setJexlFilters(filters: string[]) {
self.jexlFilters = cast(filters)
},

/**
* #action
*/
setHideSmallIndels(arg: boolean) {
self.hideSmallIndelsSetting = arg
},
}))

.views(self => ({
/**
* #getter
*/
get rendererConfig() {
const { featureHeight, noSpacing, trackMaxHeight, rendererTypeName } =
self
const {
featureHeight: height,
noSpacing,
hideSmallIndels,
trackMaxHeight: maxHeight,
rendererTypeName,
} = self
const configBlob = getConf(self, ['renderers', rendererTypeName]) || {}
return self.rendererType.configSchema.create(
{
...configBlob,
...(featureHeight !== undefined ? { height: featureHeight } : {}),
...(hideSmallIndels !== undefined ? { hideSmallIndels } : {}),
...(height !== undefined ? { height } : {}),
...(noSpacing !== undefined ? { noSpacing } : {}),
...(trackMaxHeight !== undefined
? { maxHeight: trackMaxHeight }
: {}),
...(maxHeight !== undefined ? { maxHeight } : {}),
},
getEnv(self),
)
Expand Down Expand Up @@ -561,6 +586,15 @@ export function SharedLinearPileupDisplayMixin(
},
],
},
{
label: 'Hide small indels (<10bp)',
priority: -1,
type: 'checkbox',
checked: self.hideSmallIndels,
onClick: () => {
self.setHideSmallIndels(!self.hideSmallIndels)
},
},
{
label: 'Set max height...',
priority: -1,
Expand Down
2 changes: 2 additions & 0 deletions plugins/alignments/src/LinearPileupDisplay/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,12 +208,14 @@ function stateModelFactory(configSchema: AnyConfigurationSchemaType) {
trackMaxHeight,
mismatchAlpha,
rendererTypeName,
hideSmallIndels,
} = self
const configBlob = getConf(self, ['renderers', rendererTypeName]) || {}
return self.rendererType.configSchema.create(
{
...configBlob,
...(featureHeight !== undefined ? { height: featureHeight } : {}),
...(hideSmallIndels !== undefined ? { hideSmallIndels } : {}),
...(noSpacing !== undefined ? { noSpacing } : {}),
...(mismatchAlpha !== undefined ? { mismatchAlpha } : {}),
...(trackMaxHeight !== undefined
Expand Down
9 changes: 9 additions & 0 deletions plugins/alignments/src/PileupRenderer/configSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,15 @@ const PileupRenderer = ConfigurationSchema(
'the minimum width in px for a pileup mismatch feature. use for increasing/decreasing mismatch marker widths when zoomed out, e.g. 0 or 1',
defaultValue: 1,
},
/**
* #slot
*/
hideSmallIndels: {
type: 'boolean',
description:
'Hides small indels, sometimes occurring in long read sequencing',
defaultValue: false,
},
/**
* #slot
*/
Expand Down
2 changes: 2 additions & 0 deletions plugins/alignments/src/PileupRenderer/makeImageData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export function makeImageData({
config,
'largeInsertionIndicatorScale',
)
const hideSmallIndels = readConfObject(config, 'hideSmallIndels') as boolean
const defaultColor = readConfObject(config, 'color') === '#f0f'
const theme = createJBrowseTheme(configTheme)
const colorForBase = getColorBaseMap(theme)
Expand Down Expand Up @@ -76,6 +77,7 @@ export function makeImageData({
ctx,
feat,
renderArgs,
hideSmallIndels,
mismatchAlpha,
drawSNPsMuted,
drawIndels,
Expand Down
51 changes: 31 additions & 20 deletions plugins/alignments/src/PileupRenderer/renderMismatches.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export function renderMismatches({
charHeight,
colorForBase,
contrastForBase,
hideSmallIndels,
canvasWidth,
drawSNPsMuted,
drawIndels = true,
Expand All @@ -32,6 +33,7 @@ export function renderMismatches({
drawSNPsMuted?: boolean
minSubfeatureWidth: number
largeInsertionIndicatorScale: number
hideSmallIndels: boolean
charWidth: number
charHeight: number
canvasWidth: number
Expand Down Expand Up @@ -100,32 +102,41 @@ export function renderMismatches({
)
}
} else if (mismatch.type === 'deletion' && drawIndels) {
fillRect(
ctx,
leftPx,
topPx,
Math.abs(leftPx - rightPx),
heightPx,
canvasWidth,
colorForBase.deletion,
)
const txt = `${mismatch.length}`
const rwidth = measureText(txt, 10)
if (widthPx >= rwidth && heightPx >= heightLim) {
ctx.fillStyle = contrastForBase.deletion!
ctx.fillText(txt, (leftPx + rightPx) / 2 - rwidth / 2, topPx + heightPx)
const len = mismatch.length
if (!hideSmallIndels || len >= 10) {
fillRect(
ctx,
leftPx,
topPx,
Math.abs(leftPx - rightPx),
heightPx,
canvasWidth,
colorForBase.deletion,
)
const txt = `${mismatch.length}`
const rwidth = measureText(txt, 10)
if (widthPx >= rwidth && heightPx >= heightLim) {
ctx.fillStyle = contrastForBase.deletion!
ctx.fillText(
txt,
(leftPx + rightPx) / 2 - rwidth / 2,
topPx + heightPx,
)
}
}
} else if (mismatch.type === 'insertion' && drawIndels) {
const pos = leftPx + extraHorizontallyFlippedOffset
const len = +mismatch.base || mismatch.length
const insW = Math.max(minSubfeatureWidth, Math.min(1.2, 1 / bpPerPx))
if (len < 10) {
fillRect(ctx, pos, topPx, insW, heightPx, canvasWidth, 'purple')
if (1 / bpPerPx >= charWidth && heightPx >= heightLim) {
const l = Math.round(pos - insW)
fillRect(ctx, l, topPx, insW * 3, 1, canvasWidth)
fillRect(ctx, l, topPx + heightPx - 1, insW * 3, 1, canvasWidth)
ctx.fillText(`(${mismatch.base})`, pos + 3, topPx + heightPx)
if (!hideSmallIndels) {
fillRect(ctx, pos, topPx, insW, heightPx, canvasWidth, 'purple')
if (1 / bpPerPx >= charWidth && heightPx >= heightLim) {
const l = Math.round(pos - insW)
fillRect(ctx, l, topPx, insW * 3, 1, canvasWidth)
fillRect(ctx, l, topPx + heightPx - 1, insW * 3, 1, canvasWidth)
ctx.fillText(`(${mismatch.base})`, pos + 3, topPx + heightPx)
}
}
}
} else if (mismatch.type === 'hardclip' || mismatch.type === 'softclip') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1422,6 +1422,56 @@ exports[`renders with defaults of the PileupTrack schema 1`] = `
class="css-lulcq7-slotModeSwitch"
/>
</div>
<div
class="MuiPaper-root MuiPaper-elevation MuiPaper-rounded MuiPaper-elevation1 css-12upmnv-MuiPaper-root-paper"
style="--Paper-shadow: 0px 2px 1px -1px rgba(0,0,0,0.2),0px 1px 1px 0px rgba(0,0,0,0.14),0px 1px 3px 0px rgba(0,0,0,0.12);"
>
<div
class="css-1962tgi-paperContent"
>
<div
class="MuiFormControl-root MuiFormControl-marginDense css-ylkp5u-MuiFormControl-root"
>
<label
class="MuiFormControlLabel-root MuiFormControlLabel-labelPlacementEnd css-19opgx6-MuiFormControlLabel-root"
>
<span
class="MuiButtonBase-root MuiCheckbox-root MuiCheckbox-colorPrimary MuiCheckbox-sizeMedium PrivateSwitchBase-root MuiCheckbox-root MuiCheckbox-colorPrimary MuiCheckbox-sizeMedium MuiCheckbox-root MuiCheckbox-colorPrimary MuiCheckbox-sizeMedium css-cr4rkl-MuiButtonBase-root-MuiCheckbox-root"
>
<input
class="PrivateSwitchBase-input css-j8yymo"
data-indeterminate="false"
type="checkbox"
/>
<svg
aria-hidden="true"
class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium css-14500qs-MuiSvgIcon-root"
data-testid="CheckBoxOutlineBlankIcon"
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="MuiTypography-root MuiTypography-body1 MuiFormControlLabel-label css-1xfjy4j-MuiTypography-root"
>
hideSmallIndels
</span>
</label>
<p
class="MuiFormHelperText-root MuiFormHelperText-sizeSmall MuiFormHelperText-contained css-shvv2y-MuiFormHelperText-root"
>
Hides small indels, sometimes occurring in long read sequencing
</p>
</div>
</div>
<div
class="css-lulcq7-slotModeSwitch"
/>
</div>
<div
class="MuiPaper-root MuiPaper-elevation MuiPaper-rounded MuiPaper-elevation1 css-12upmnv-MuiPaper-root-paper"
style="--Paper-shadow: 0px 2px 1px -1px rgba(0,0,0,0.2),0px 1px 1px 0px rgba(0,0,0,0.14),0px 1px 3px 0px rgba(0,0,0,0.12);"
Expand Down
10 changes: 5 additions & 5 deletions website/docs/models/AssemblyManager.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ session.assemblies, session.sessionAssemblies, and session.temporaryAssemblies

```js
// type signature
IArrayType<IModelType<{ configuration: IMaybe<IReferenceType<IAnyType>>; }, { error: unknown; loadingP: Promise<void> | undefined; volatileRegions: BasicRegion[] | undefined; refNameAliases: RefNameAliases | undefined; lowerCaseRefNameAliases: RefNameAliases | undefined; cytobands: Feature[] | undefined; } & ... 5 m...
IArrayType<IModelType<{ configuration: IMaybe<IReferenceType<IAnyType>>; }, { error: unknown; loadingP: Promise<void>; volatileRegions: BasicRegion[]; refNameAliases: RefNameAliases; lowerCaseRefNameAliases: RefNameAliases; cytobands: Feature[]; } & ... 5 more ... & { ...; }, _NotCustomized, _NotCustomized>>
// code
assemblies: types.array(assemblyFactory(conf, pm))
```
Expand All @@ -40,7 +40,7 @@ assemblies: types.array(assemblyFactory(conf, pm))

```js
// type
Record<string, { configuration: any; } & NonEmptyObject & { error: unknown; loadingP: Promise<void> | undefined; volatileRegions: BasicRegion[] | undefined; refNameAliases: RefNameAliases | undefined; lowerCaseRefNameAliases: RefNameAliases | undefined; cytobands: Feature[] | undefined; } & ... 6 more ... & IStateTr...
Record<string, { configuration: any; } & NonEmptyObject & { error: unknown; loadingP: Promise<void>; volatileRegions: BasicRegion[]; refNameAliases: RefNameAliases; lowerCaseRefNameAliases: RefNameAliases; cytobands: Feature[]; } & ... 6 more ... & IStateTreeNode<...>>
```

#### getter: assemblyNamesList
Expand All @@ -66,7 +66,7 @@ session.temporaryAssemblies

```js
// type signature
get: (asmName: string) => { configuration: any; } & NonEmptyObject & { error: unknown; loadingP: Promise<void> | undefined; volatileRegions: BasicRegion[] | undefined; refNameAliases: RefNameAliases | undefined; lowerCaseRefNameAliases: RefNameAliases | undefined; cytobands: Feature[] | undefined; } & ... 6 more ... & IS...
get: (asmName: string) => { configuration: any; } & NonEmptyObject & { error: unknown; loadingP: Promise<void>; volatileRegions: BasicRegion[]; refNameAliases: RefNameAliases; lowerCaseRefNameAliases: RefNameAliases; cytobands: Feature[]; } & ... 6 more ... & IStateTreeNode<...>
```

#### method: waitForAssembly
Expand All @@ -76,7 +76,7 @@ with regions loaded

```js
// type signature
waitForAssembly: (assemblyName: string) => Promise<{ configuration: any; } & NonEmptyObject & { error: unknown; loadingP: Promise<void> | undefined; volatileRegions: BasicRegion[] | undefined; refNameAliases: RefNameAliases | undefined; lowerCaseRefNameAliases: RefNameAliases | undefined; cytobands: Feature[] | undefined; } & ... 6 ...
waitForAssembly: (assemblyName: string) => Promise<{ configuration: any; } & NonEmptyObject & { error: unknown; loadingP: Promise<void>; volatileRegions: BasicRegion[]; refNameAliases: RefNameAliases; lowerCaseRefNameAliases: RefNameAliases; cytobands: Feature[]; } & ... 6 more ... & IStateTreeNode<...>>
```

#### method: getRefNameMapForAdapter
Expand Down Expand Up @@ -110,7 +110,7 @@ directly

```js
// type signature
removeAssembly: (asm: { configuration: any; } & NonEmptyObject & { error: unknown; loadingP: Promise<void> | undefined; volatileRegions: BasicRegion[] | undefined; refNameAliases: RefNameAliases | undefined; lowerCaseRefNameAliases: RefNameAliases | undefined; cytobands: Feature[] | undefined; } & ... 6 more ... & IStateTreeNode<.....
removeAssembly: (asm: { configuration: any; } & NonEmptyObject & { error: unknown; loadingP: Promise<void>; volatileRegions: BasicRegion[]; refNameAliases: RefNameAliases; lowerCaseRefNameAliases: RefNameAliases; cytobands: Feature[]; } & ... 6 more ... & IStateTreeNode<...>) => void
```

#### action: addAssembly
Expand Down
2 changes: 1 addition & 1 deletion website/docs/models/BaseChordDisplay.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ renderStarted: () => void

```js
// type signature
renderSuccess: ({ message, data, reactElement, html, renderingComponent, }: { message?: string; data?: any; html?: string; reactElement?: React.ReactElement; renderingComponent?: React.ComponentType<any>; }) => void
renderSuccess: ({ message, data, reactElement, html, renderingComponent, }: { message?: string; data?: any; html?: string; reactElement?: ReactElement<unknown, string | JSXElementConstructor<any>>; renderingComponent?: React.ComponentType<any>; }) => void
```

#### action: renderError
Expand Down
2 changes: 1 addition & 1 deletion website/docs/models/BaseDisplay.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ rpcDriverName: types.maybe(types.string)

```js
// type
React.FC<{ model: { id: string; type: string; rpcDriverName: string; } & NonEmptyObject & { rendererTypeName: string; error: unknown; message: string | undefined; } & IStateTreeNode<IModelType<{ id: IOptionalIType<...>; type: ISimpleType<...>; rpcDriverName: IMaybe<...>; }, { ...; }, _NotCustomized, _NotCustomized>>...
React.FC<{ model: { id: string; type: string; rpcDriverName: string; } & NonEmptyObject & { rendererTypeName: string; error: unknown; message: string; } & IStateTreeNode<IModelType<{ id: IOptionalIType<ISimpleType<string>, [...]>; type: ISimpleType<...>; rpcDriverName: IMaybe<...>; }, { ...; }, _NotCustomized, _NotC...
```
#### getter: DisplayBlurb
Expand Down
2 changes: 1 addition & 1 deletion website/docs/models/BaseFeatureWidget.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ maxDepth: types.maybe(types.number)

```js
// type signature
IOptionalIType<IModelType<{}, { showCoordinatesSetting: string; intronBp: number; upDownBp: number; upperCaseCDS: boolean; charactersPerRow: number; feature: SimpleFeatureSerialized | undefined; mode: string; } & { ...; } & { ...; } & { ...; }, _NotCustomized, _NotCustomized>, [...]>
IOptionalIType<IModelType<{}, { showCoordinatesSetting: string; intronBp: number; upDownBp: number; upperCaseCDS: boolean; charactersPerRow: number; feature: SimpleFeatureSerialized; mode: string; } & { ...; } & { ...; } & { ...; }, _NotCustomized, _NotCustomized>, [...]>
// code
sequenceFeatureDetails: types.optional(SequenceFeatureDetailsF(), {})
```
Expand Down
2 changes: 1 addition & 1 deletion website/docs/models/BaseRootModel.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ sessionPath: types.optional(types.string, '')

```js
// type signature
IOptionalIType<IModelType<{ assemblies: IArrayType<IModelType<{ configuration: IMaybe<IReferenceType<IAnyType>>; }, { error: unknown; loadingP: Promise<void> | undefined; volatileRegions: BasicRegion[] | undefined; refNameAliases: RefNameAliases | undefined; lowerCaseRefNameAliases: RefNameAliases | undefined; cytob...
IOptionalIType<IModelType<{ assemblies: IArrayType<IModelType<{ configuration: IMaybe<IReferenceType<IAnyType>>; }, { error: unknown; loadingP: Promise<void>; volatileRegions: BasicRegion[]; refNameAliases: RefNameAliases; lowerCaseRefNameAliases: RefNameAliases; cytobands: Feature[]; } & ... 5 more ... & { ...; }, ...
// code
assemblyManager: types.optional(
assemblyManagerFactory(assemblyConfigSchema, pluginManager),
Expand Down
2 changes: 1 addition & 1 deletion website/docs/models/BaseWebSession.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ TextSearchManager
```js
// type
{ assemblies: IMSTArray<IModelType<{ configuration: IMaybe<IReferenceType<IAnyType>>; }, { error: unknown; loadingP: Promise<void> | undefined; volatileRegions: BasicRegion[] | undefined; refNameAliases: RefNameAliases | undefined; lowerCaseRefNameAliases: RefNameAliases | undefined; cytobands: Feature[] | undefined...
{ assemblies: IMSTArray<IModelType<{ configuration: IMaybe<IReferenceType<IAnyType>>; }, { error: unknown; loadingP: Promise<void>; volatileRegions: BasicRegion[]; refNameAliases: RefNameAliases; lowerCaseRefNameAliases: RefNameAliases; cytobands: Feature[]; } & ... 5 more ... & { ...; }, _NotCustomized, _NotCustomi...
```
#### getter: savedSessionMetadata
Expand Down
2 changes: 1 addition & 1 deletion website/docs/models/DotplotDisplay.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ setMessage: (messageText: string) => void

```js
// type signature
setRendered: (args?: { data: any; reactElement: React.ReactElement; renderingComponent: React.Component; }) => void
setRendered: (args?: { data: any; reactElement: ReactElement<unknown, string | JSXElementConstructor<any>>; renderingComponent: Component<{}, {}, any>; }) => void
```

#### action: setError
Expand Down
Loading

0 comments on commit 1d793a1

Please sign in to comment.