Skip to content

Commit

Permalink
Multi-level synteny
Browse files Browse the repository at this point in the history
Fixes

Incremental

Misc

No consolelogs

Updates to svg export

SVG export

Misc

Bump deps

Unused JsonEditor re-export

Refname renaming on mcscan anchors adapter

Assembly name on each row

Update deps
  • Loading branch information
cmdcolin committed Aug 12, 2024
1 parent 615b1e3 commit de50757
Show file tree
Hide file tree
Showing 34 changed files with 1,301 additions and 2,715 deletions.
30 changes: 9 additions & 21 deletions packages/core/assemblyManager/assemblyManager.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import {
addDisposer,
cast,
getParent,
types,
Instance,
IAnyType,
} from 'mobx-state-tree'
import { when } from '../util'
import { reaction } from 'mobx'

// locals
import { when } from '../util'
import { readConfObject, AnyConfigurationModel } from '../configuration'
import assemblyFactory, { Assembly } from './assembly'
import PluginManager from '../PluginManager'
Expand Down Expand Up @@ -164,20 +165,17 @@ function assemblyManagerFactory(conf: IAnyType, pm: PluginManager) {
reaction(
() => self.assemblyList,
assemblyConfs => {
self.assemblies.forEach(asm => {
for (const asm of self.assemblies) {
if (!asm.configuration) {
this.removeAssembly(asm)
}
})
assemblyConfs.forEach(conf => {
if (
!self.assemblies.some(
a => a.name === readConfObject(conf, 'name'),
)
) {
}
for (const conf of assemblyConfs) {
const name = readConfObject(conf, 'name')
if (!self.assemblies.some(a => a.name === name)) {
this.addAssembly(conf)
}
})
}
},
{ fireImmediately: true, name: 'assemblyManagerAfterAttach' },
),
Expand Down Expand Up @@ -207,16 +205,6 @@ function assemblyManagerFactory(conf: IAnyType, pm: PluginManager) {
addAssembly(configuration: Conf) {
self.assemblies.push({ configuration })
},

/**
* #action
* private: you would generally want to add to manipulate
* jbrowse.assemblies, session.sessionAssemblies, or
* session.temporaryAssemblies instead of using this directly
*/
replaceAssembly(idx: number, configuration: Conf) {
self.assemblies[idx] = cast({ configuration })
},
}))
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,15 +87,16 @@ export async function renderToSvg(model: BSV, opts: ExportSvgOptions) {

<SVGRuler model={displayResults[0]!.view} fontSize={fontSize} />
</g>
<SVGTracks
textHeight={textHeight}
trackLabels={trackLabels}
fontSize={fontSize}
model={displayResults[0]!.view}
displayResults={displayResults[0]!.data}
offset={offset}
trackLabelOffset={trackLabelOffset}
/>
<g transform={`translate(0 ${offset})`}>
<SVGTracks
textHeight={textHeight}
trackLabels={trackLabels}
fontSize={fontSize}
model={displayResults[0]!.view}
displayResults={displayResults[0]!.data}
trackLabelOffset={trackLabelOffset}
/>
</g>
</g>

<g transform={`translate(${shift} ${fontSize + heights[0]!})`}>
Expand All @@ -105,15 +106,16 @@ export async function renderToSvg(model: BSV, opts: ExportSvgOptions) {
</text>
<SVGRuler model={displayResults[1]!.view} fontSize={fontSize} />
</g>
<SVGTracks
textHeight={textHeight}
trackLabels={trackLabels}
fontSize={fontSize}
model={displayResults[1]!.view}
displayResults={displayResults[1]!.data}
offset={offset}
trackLabelOffset={trackLabelOffset}
/>
<g transform={`translate(0 ${offset})`}>
<SVGTracks
textHeight={textHeight}
trackLabels={trackLabels}
fontSize={fontSize}
model={displayResults[1]!.view}
displayResults={displayResults[1]!.data}
trackLabelOffset={trackLabelOffset}
/>
</g>
</g>

<defs>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,31 @@ export default class MCScanAnchorsAdapter extends BaseFeatureDataAdapter {
}

async hasDataForRefName() {
// determining this properly is basically a call to getFeatures
// so is not really that important, and has to be true or else
// getFeatures is never called (BaseFeatureDataAdapter filters it out)
// determining this properly is basically a call to getFeatures so is not
// really that important, and has to be true or else getFeatures is never
// called (BaseFeatureDataAdapter filters it out)
return true
}

async getRefNames() {
// we cannot determine this accurately
getAssemblyNames() {
const assemblyNames = this.getConf('assemblyNames') as string[]
return assemblyNames
}

async getRefNames(opts: BaseOptions = {}) {
// @ts-expect-error
const r1 = opts.regions?.[0].assemblyName
const { feats } = await this.setup(opts)

const idx = this.getAssemblyNames().indexOf(r1)
if (idx !== -1) {
const set = new Set<string>()
for (const feat of feats) {
set.add(idx === 0 ? feat[0].refName : feat[1].refName)
}
return [...set]
}
console.warn('Unable to do ref renaming on adapter')
return []
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,31 @@ export default class MCScanAnchorsAdapter extends BaseFeatureDataAdapter {
return true
}

async getRefNames() {
// we cannot determine this accurately
getAssemblyNames() {
const assemblyNames = this.getConf('assemblyNames') as string[]
return assemblyNames
}

async getRefNames(opts: BaseOptions = {}) {
// @ts-expect-error
const r1 = opts.regions?.[0].assemblyName
const { feats } = await this.setup(opts)

const idx = this.getAssemblyNames().indexOf(r1)
if (idx !== -1) {
const set = new Set<string>()
for (const feat of feats) {
if (idx === 0) {
set.add(feat[0].refName)
set.add(feat[1].refName)
} else {
set.add(feat[2].refName)
set.add(feat[3].refName)
}
}
return [...set]
}
console.warn('Unable to do ref renaming on adapter')
return []
}

Expand Down
2 changes: 0 additions & 2 deletions plugins/config/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,4 @@ export default class ConfigurationPlugin extends Plugin {
}
}

export { default as JsonEditor } from './ConfigurationEditorWidget/components/JsonEditor'

export { LazyConfigurationEditorComponent as ConfigurationEditor }
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
ConfigurationReference,
AnyConfigurationSchemaType,
} from '@jbrowse/core/configuration'
import { types, getSnapshot, Instance } from 'mobx-state-tree'
import { types, getSnapshot, Instance, getParent } from 'mobx-state-tree'
import {
dedupe,
Feature,
Expand Down Expand Up @@ -34,10 +34,6 @@ function stateModelFactory(configSchema: AnyConfigurationSchemaType) {
* #property
*/
configuration: ConfigurationReference(configSchema),
/**
* #property
*/
height: 100,
}),
)
.volatile((/* self */) => ({
Expand Down Expand Up @@ -165,20 +161,22 @@ function renderBlockData(self: LinearComparativeDisplay) {
const { rpcManager } = getSession(self)
const display = self

// Alternative to readConfObject(config) is below used because renderProps is
// something under our control. Compare to serverSideRenderedBlock
// Alternative to readConfObject(config) is below used because
// renderProps is something under our control. Compare to
// serverSideRenderedBlock
readConfObject(self.configuration)

const { adapterConfig } = self
const parent = getContainingView(self) as LinearComparativeViewModel
const sessionId = getRpcSessionId(self)
getSnapshot(parent)

return parent.initialized
? {
rpcManager,
renderProps: {
...display.renderProps(),
// @ts-expect-error
level: getParent(self, 4).level as number,
view: parent,
adapterConfig,
sessionId,
Expand All @@ -195,11 +193,10 @@ async function renderBlockEffect(props: ReturnType<typeof renderBlockData>) {
}

const { rpcManager, renderProps } = props
const { adapterConfig } = renderProps
const view0 = renderProps.view.views[0]

const { adapterConfig, level } = renderProps
const view = renderProps.view.views[level]
const features = (await rpcManager.call('getFeats', 'CoreGetFeatures', {
regions: view0.staticBlocks.contentBlocks,
regions: view.staticBlocks.contentBlocks,
sessionId: 'getFeats',
adapterConfig,
})) as Feature[]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
import React, { useState } from 'react'
import { IconButton, Typography } from '@mui/material'
import { Typography } from '@mui/material'
import { makeStyles } from 'tss-react/mui'
import { SearchBox } from '@jbrowse/plugin-linear-genome-view'
import { observer } from 'mobx-react'
import { Menu } from '@jbrowse/core/ui'
import CascadingMenuButton from '@jbrowse/core/ui/CascadingMenuButton'

// icons
import MoreVertIcon from '@mui/icons-material/MoreVert'

// locals
import { LinearComparativeViewModel } from '../model'
import { TrackSelector as TrackSelectorIcon } from '@jbrowse/core/ui/Icons'
import CascadingMenuButton from '@jbrowse/core/ui/CascadingMenuButton'

type LCV = LinearComparativeViewModel

const useStyles = makeStyles()(() => ({
headerBar: {
Expand All @@ -39,7 +36,11 @@ const useStyles = makeStyles()(() => ({
},
}))

const TrackSelector = observer(({ model }: { model: LCV }) => {
const TrackSelector = observer(function ({
model,
}: {
model: LinearComparativeViewModel
}) {
return (
<CascadingMenuButton
menuItems={[
Expand All @@ -58,57 +59,55 @@ const TrackSelector = observer(({ model }: { model: LCV }) => {
)
})

const Header = observer(function ({ model }: { model: LCV }) {
const Header = observer(function ({
model,
}: {
model: LinearComparativeViewModel
}) {
const { classes } = useStyles()
const [menuAnchorEl, setMenuAnchorEl] = useState<HTMLElement>()
const anyShowHeaders = model.views.some(view => !view.hideHeader)
const { views } = model
const [showSearchBoxes, setShowSearchBoxes] = useState(false)
return (
<div className={classes.headerBar}>
<TrackSelector model={model} />

<IconButton
onClick={event => {
setMenuAnchorEl(event.currentTarget)
}}
<CascadingMenuButton
className={classes.iconButton}
menuItems={[
...model.headerMenuItems(),
{
label: 'Show search boxes?',
checked: showSearchBoxes,
onClick: () => {
setShowSearchBoxes(!showSearchBoxes)
},
type: 'checkbox',
},
]}
>
<MoreVertIcon />
</IconButton>
{!anyShowHeaders
? model.views.map(view => (
</CascadingMenuButton>

{showSearchBoxes ? (
<div>
{views.map(view => (
<div key={view.id} className={classes.searchBox}>
<div className={classes.searchContainer}>
<SearchBox model={view} showHelp={false} />
</div>
<div className={classes.bp}>
<Typography
variant="body2"
color="textSecondary"
className={classes.bp}
>
{Math.round(view.coarseTotalBp).toLocaleString('en-US')} bp
</Typography>
</div>
<Typography
variant="body2"
color="textSecondary"
className={classes.bp}
>
{view.assemblyNames.join(',')}{' '}
{Math.round(view.coarseTotalBp).toLocaleString('en-US')} bp
</Typography>
</div>
))
: null}
))}
</div>
) : null}

<div className={classes.spacer} />

{menuAnchorEl ? (
<Menu
anchorEl={menuAnchorEl}
open
onMenuItemClick={(_event, callback) => {
callback()
setMenuAnchorEl(undefined)
}}
menuItems={model.headerMenuItems()}
onClose={() => {
setMenuAnchorEl(undefined)
}}
/>
) : null}
</div>
)
})
Expand Down
Loading

0 comments on commit de50757

Please sign in to comment.