Skip to content

Commit

Permalink
Remove duplicate features with note
Browse files Browse the repository at this point in the history
  • Loading branch information
cmdcolin committed Mar 4, 2021
1 parent e5f293c commit 495adab
Showing 1 changed file with 59 additions and 47 deletions.
106 changes: 59 additions & 47 deletions packages/core/BaseFeatureWidget/BaseFeatureDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
AccordionSummary,
Typography,
Divider,
Paper,
Tooltip,
Select,
MenuItem,
Expand All @@ -28,6 +27,8 @@ import {
import { Feature } from '../util/simpleFeature'
import SanitizedHTML from '../ui/SanitizedHTML'

type Feat = { start: number; end: number }

const globalOmit = [
'name',
'start',
Expand Down Expand Up @@ -168,6 +169,7 @@ const BasicValue = ({ value }: { value: string | React.ReactNode }) => {
}
const SimpleValue = ({
name,

value,
description,
prefix,
Expand Down Expand Up @@ -292,11 +294,24 @@ function SequenceFeatureDetails(props: BaseProps) {
const utrColor = 'rgba(0,150,150,0.3)'
const proteinColor = 'rgba(150,0,150,0.3)'

let cds = children.filter(sub => sub.type === 'CDS')
let exons = children.filter(sub => sub.type === 'exon')
// filter duplicate entries in cds and exon lists duplicate entries may be
// rare but was seen in Gencode v36 track NCList, likely a bug on GFF3 or
// probably worth ignoring here (produces broken protein translations if
// included)
// position 1:224,800,006..225,203,064 gene ENSG00000185842.15 first
// transcript ENST00000445597.6
// http://localhost:3000/?config=test_data%2Fconfig.json&session=share-FUl7G1isvF&password=HXh5Y
const fid = (feat: Feat) => `${feat.start}-${feat.end}`

let cds = children
.filter(sub => sub.type === 'CDS')
.filter((item, pos, ary) => !pos || fid(item) !== fid(ary[pos - 1]))

let exons = children
.filter(sub => sub.type === 'exon')
.filter((item, pos, ary) => !pos || fid(item) !== fid(ary[pos - 1]))
const revstrand = feature.strand === -1
const sequence = revstrand ? revcom(preseq) : preseq

const seqlen = sequence.length
if (revstrand) {
cds = cds
Expand Down Expand Up @@ -456,7 +471,7 @@ function CoreDetails(props: BaseProps) {
const displayRef = refName ? `${refName}:` : ''
const displayedDetails: Record<string, any> = {
...feature,
length: end - start,
length: (end - start).toLocaleString('en-US'),
position: `${displayRef}${displayStart}..${displayEnd} ${strandStr}`,
}

Expand Down Expand Up @@ -640,66 +655,63 @@ export interface BaseInputProps extends BaseCardProps {
formatter?: (val: unknown, key: string) => JSX.Element
}

function Subfeature(props: BaseProps) {
const { feature, model } = props
const { type, name, id, subfeatures } = feature
const displayName = name || id
const session = getSession(model)
const defSeqTypes = ['mRNA', 'transcript']
const sequenceTypes =
getConf(session, ['featureDetails', 'sequenceTypes']) || defSeqTypes

return (
<BaseCard title={displayName ? `${displayName} - ${type}` : type}>
<CoreDetails {...props} />
<Divider />
<Attributes attributes={feature} {...props} />
{sequenceTypes.includes(feature.type) ? (
<SequenceFeatureDetails {...props} />
) : null}
{feature.subfeatures && feature.subfeatures.length ? (
<BaseCard title="Subfeatures" defaultExpanded={false}>
{subfeatures.map((sub: any) => (
<Subfeature key={JSON.stringify(sub)} feature={sub} model={model} />
))}
</BaseCard>
) : null}
</BaseCard>
)
}

function isEmpty(obj: Record<string, unknown>) {
return Object.keys(obj).length === 0
}

export const BaseFeatureDetails = observer((props: BaseInputProps) => {
const classes = useStyles()
const { model } = props
const { featureData } = model

if (!model.featureData) {
if (!featureData) {
return null
}
const feature = JSON.parse(JSON.stringify(model.featureData))
const feature = JSON.parse(JSON.stringify(featureData))

if (isEmpty(feature)) {
return null
}
return <FeatureDetails model={model} feature={feature} />
})

const FeatureDetails = (props: {
model: any
feature: any
depth?: number
}) => {
const { model, feature, depth = 0 } = props
const { name, id, type, subfeatures } = feature
const displayName = name || id
const session = getSession(model)
const defSeqTypes = ['mRNA', 'transcript']
const sequenceTypes =
getConf(session, ['featureDetails', 'sequenceTypes']) || defSeqTypes

return (
<Paper className={classes.paperRoot}>
<BaseCoreDetails feature={feature} {...props} />
<BaseCard title={displayName ? `${displayName} - ${type}` : type}>
<div>Core details</div>
<CoreDetails {...props} />
<Divider />
<BaseAttributes feature={feature} {...props} />
{feature.subfeatures && feature.subfeatures.length ? (
<BaseCard title="Subfeatures">
{feature.subfeatures.map((subfeature: any) => (
<Subfeature
key={JSON.stringify(subfeature)}
feature={subfeature}
<div>Attributes</div>
<Attributes attributes={feature} {...props} />
{sequenceTypes.includes(feature.type) ? (
<SequenceFeatureDetails {...props} />
) : null}
{subfeatures && subfeatures.length ? (
<BaseCard
title="Subfeatures"
defaultExpanded={!sequenceTypes.includes(feature.type)}
>
{subfeatures.map((sub: any) => (
<FeatureDetails
key={JSON.stringify(sub)}
feature={sub}
model={model}
depth={depth + 1}
/>
))}
</BaseCard>
) : null}
</Paper>
</BaseCard>
)
})
}

0 comments on commit 495adab

Please sign in to comment.