Skip to content

Commit

Permalink
Fix RNA-seq stranded arc coloring, change the color of RNA-seq intron…
Browse files Browse the repository at this point in the history
…s, and improve compact rendering (#4639)
  • Loading branch information
cmdcolin authored Nov 7, 2024
1 parent 32ad1a6 commit 46ca580
Show file tree
Hide file tree
Showing 30 changed files with 1,449 additions and 1,218 deletions.
12 changes: 0 additions & 12 deletions packages/core/util/simpleFeature.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,6 @@ export interface Feature {
get(name: 'subfeatures'): Feature[] | undefined

get(name: string): any

/**
* Set an item of data.
*/

set(name: string, val: any): void

/**
* Get an array listing which data keys are present in this feature.
*/
tags(): string[]

/**
* Get the unique ID of this feature.
*/
Expand Down
2 changes: 1 addition & 1 deletion plugins/alignments/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"clean": "rimraf dist esm *.tsbuildinfo"
},
"dependencies": {
"@gmod/bam": "^2.0.0",
"@gmod/bam": "^3.0.0",
"@gmod/cram": "^3.0.3",
"@jbrowse/sv-core": "^2.16.1",
"@mui/icons-material": "^6.0.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ import Formatter from './Formatter'
const SupplementaryAlignments = lazy(() => import('./SupplementaryAlignments'))
const LinkedPairedAlignments = lazy(() => import('./LinkedPairedAlignments'))

const omit = ['clipPos', 'flags']

const AlignmentsFeatureDetails = observer(function (props: {
model: AlignmentFeatureWidgetModel
}) {
Expand All @@ -32,7 +30,6 @@ const AlignmentsFeatureDetails = observer(function (props: {
<Paper data-testid="alignment-side-drawer">
<FeatureDetails
{...props}
omit={omit}
// @ts-expect-error
descriptions={{ ...tags, tags: tags }}
feature={feat}
Expand Down
10 changes: 5 additions & 5 deletions plugins/alignments/src/BamAdapter/BamAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,11 +186,11 @@ export default class BamAdapter extends BaseFeatureDataAdapter {

for (const record of records) {
let ref: string | undefined
if (!record.get('MD')) {
if (!record.tags.MD) {
ref = await this.seqFetch(
originalRefName || refName,
record.get('start'),
record.get('end'),
record.start,
record.end,
)
}

Expand All @@ -200,7 +200,7 @@ export default class BamAdapter extends BaseFeatureDataAdapter {
}

if (tagFilter) {
const readVal = record.get(tagFilter.tag)
const readVal = record.tags[tagFilter.tag]
const filterVal = tagFilter.value
if (
filterVal === '*'
Expand All @@ -211,7 +211,7 @@ export default class BamAdapter extends BaseFeatureDataAdapter {
}
}

if (readName && record.get('name') !== readName) {
if (readName && record.name !== readName) {
continue
}

Expand Down
163 changes: 59 additions & 104 deletions plugins/alignments/src/BamAdapter/BamSlightlyLazyFeature.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
import { BamRecord } from '@gmod/bam'

// locals
import { getClip, getMismatches } from '../MismatchParser'
import { getMismatches, parseCigar } from '../MismatchParser'
import BamAdapter from './BamAdapter'

export default class BamSlightlyLazyFeature implements Feature {
Expand All @@ -17,94 +17,20 @@ export default class BamSlightlyLazyFeature implements Feature {
private ref?: string,
) {}

_get_name() {
return this.record.get('name')
}

_get_type(): string {
return 'match'
}

_get_score(): number {
return this.record.get('mq')
}

_get_flags(): string {
return this.record.flags
}

_get_strand(): number {
return this.record.isReverseComplemented() ? -1 : 1
}

_get_pair_orientation() {
return this.record.isPaired() ? this.record.getPairOrientation() : undefined
}

_get_next_ref() {
return this.record.isPaired()
? this.adapter.refIdToName(this.record._next_refid())
: undefined
}

_get_next_pos() {
return this.record.isPaired() ? this.record._next_pos() : undefined
}

_get_next_segment_position() {
return this.record.isPaired()
? `${this.adapter.refIdToName(this.record._next_refid())}:${
this.record._next_pos() + 1
}`
: undefined
}

_get_seq() {
return this.record.getReadBases()
}

qualRaw() {
return this.record.qualRaw()
}

set() {}

tags() {
const properties = Object.getOwnPropertyNames(
BamSlightlyLazyFeature.prototype,
)

return [
...new Set(
properties
.filter(
prop =>
prop.startsWith('_get_') &&
prop !== '_get_mismatches' &&
prop !== '_get_tags',
)
.map(methodName => methodName.replace('_get_', ''))
.concat(this.record._tags()),
),
]
}

id() {
return `${this.adapter.id}-${this.record.id()}`
return `${this.adapter.id}-${this.record.id}`
}

get(field: string): any {
const methodName = `_get_${field}`
// @ts-expect-error
if (this[methodName]) {
// @ts-expect-error
return this[methodName]()
}
return this.record.get(field)
}

_get_refName() {
return this.adapter.refIdToName(this.record.seq_id())
return field === 'mismatches'
? getMismatches(
this.record.CIGAR,
this.record.tags.MD as string | undefined,
this.record.seq,
this.ref,
this.record.qualRaw,
)
: this.fields[field]
}

parent() {
Expand All @@ -115,33 +41,62 @@ export default class BamSlightlyLazyFeature implements Feature {
return undefined
}

pairedFeature() {
return false
get parsedCigar() {
return parseCigar(this.record.CIGAR)
}

toJSON(): SimpleFeatureSerialized {
get fields(): SimpleFeatureSerialized {
const r = this.record
const a = this.adapter
const p = r.isPaired()
return {
...Object.fromEntries(
this.tags()
.map(t => [t, this.get(t)])
.filter(elt => elt[1] !== undefined),
),
id: this.id(),
start: r.start,
name: r.name,
end: r.end,
score: r.score,
qual: r.qual,
strand: r.strand,
template_length: r.template_length,
flags: r.flags,
tags: r.tags,
refName: a.refIdToName(r.ref_id)!,
CIGAR: r.CIGAR,
seq: r.seq,
type: 'match',
pair_orientation: r.pair_orientation,
next_ref: p ? a.refIdToName(r.next_refid) : undefined,
next_pos: p ? r.next_pos : undefined,
next_segment_position: p
? `${a.refIdToName(r.next_refid)}:${r.next_pos + 1}`
: undefined,
uniqueId: this.id(),
}
}

_get_mismatches() {
return getMismatches(
this.get('CIGAR'),
this.get('MD'),
this.get('seq'),
this.ref,
this.qualRaw(),
)
toJSON(): SimpleFeatureSerialized {
return this.fields
}
}

function cacheGetter<T>(ctor: { prototype: T }, prop: keyof T): void {
const desc = Object.getOwnPropertyDescriptor(ctor.prototype, prop)
if (!desc) {
throw new Error('t1')
}

_get_clipPos() {
const cigar = this.get('CIGAR') || ''
return getClip(cigar, this.get('strand'))
const getter = desc.get
if (!getter) {
throw new Error('t2')
}
Object.defineProperty(ctor.prototype, prop, {
get() {
const ret = getter.call(this)
Object.defineProperty(this, prop, { value: ret })
return ret
},
})
}

cacheGetter(BamSlightlyLazyFeature, 'fields')
cacheGetter(BamSlightlyLazyFeature, 'parsedCigar')
Loading

0 comments on commit 46ca580

Please sign in to comment.