Skip to content

Commit

Permalink
Refactoring the alignments tracks
Browse files Browse the repository at this point in the history
  • Loading branch information
cmdcolin committed Nov 10, 2024
1 parent 14e990c commit 071d8cb
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 98 deletions.
27 changes: 11 additions & 16 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 { getMismatches, parseCigar } from '../MismatchParser'
import { getMismatches } from '../MismatchParser'
import BamAdapter from './BamAdapter'

export default class BamSlightlyLazyFeature implements Feature {
Expand All @@ -20,17 +20,18 @@ export default class BamSlightlyLazyFeature implements Feature {
id() {
return `${this.adapter.id}-${this.record.id}`
}
get mismatches() {
return getMismatches(
this.record.CIGAR,
this.record.tags.MD as string | undefined,
this.record.seq,
this.ref,
this.record.qualRaw,
)
}

get(field: string): any {
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]
return field === 'mismatches' ? this.mismatches : this.fields[field]
}

parent() {
Expand All @@ -41,16 +42,11 @@ export default class BamSlightlyLazyFeature implements Feature {
return undefined
}

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

get fields(): SimpleFeatureSerialized {
const r = this.record
const a = this.adapter
const p = r.isPaired()
return {
id: this.id(),
start: r.start,
name: r.name,
end: r.end,
Expand Down Expand Up @@ -99,4 +95,3 @@ function cacheGetter<T>(ctor: { prototype: T }, prop: keyof T): void {
}

cacheGetter(BamSlightlyLazyFeature, 'fields')
cacheGetter(BamSlightlyLazyFeature, 'parsedCigar')
155 changes: 73 additions & 82 deletions plugins/alignments/src/CramAdapter/CramSlightlyLazyFeature.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,97 +16,87 @@ export default class CramSlightlyLazyFeature implements Feature {
private _store: CramAdapter,
) {}

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

_get_start() {
get start() {
return this.record.alignmentStart - 1
}

_get_end() {
return this.record.alignmentStart + (this.record.lengthOnRef ?? 1) - 1
get end() {
return this.start + (this.record.lengthOnRef ?? 1)
}

_get_cram_read_features() {
return this.record.readFeatures
}

_get_type() {
get type() {

Check failure on line 31 in plugins/alignments/src/CramAdapter/CramSlightlyLazyFeature.ts

View workflow job for this annotation

GitHub Actions / Lint, typecheck, test

Literals should be exposed using readonly fields
return 'match'
}

_get_score() {
get score() {
return this.record.mappingQuality
}

_get_flags() {
get flags() {
return this.record.flags
}

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

_read_group_id() {
return this._store.samHeader.readGroups?.[this.record.readGroupId]
}

_get_qual() {
get qual() {
return (this.record.qualityScores || []).join(' ')
}

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

_get_refName() {
return this._store.refIdToName(this.record.sequenceId)
}

_get_is_paired() {
return !!this.record.mate
get refName() {
return this._store.refIdToName(this.record.sequenceId)!
}

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

_get_template_length() {
get template_length() {
return this.record.templateLength || this.record.templateSize
}

_get_next_ref() {
get next_ref() {
return this.record.mate
? this._store.refIdToName(this.record.mate.sequenceId)
: undefined
}

_get_next_segment_position() {
get next_segment_position() {
return this.record.mate
? `${this._store.refIdToName(this.record.mate.sequenceId)}:${
this.record.mate.alignmentStart
}`
: undefined
}

_get_next_pos() {
get is_paired() {
return !!this.record.mate
}

get next_pos() {
return this.record.mate?.alignmentStart
}

_get_tags() {
const RG = this._read_group_id()
const { tags } = this.record
// avoids a tag copy if no RG, but just copy if there is one
return RG !== undefined ? { ...tags, RG } : tags
get tags() {
const RG = this._store.samHeader.readGroups?.[this.record.readGroupId]
return RG !== undefined ? { ...this.record.tags, RG } : this.record.tags
}

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

// generate a CIGAR, based on code from jkbonfield
_get_CIGAR() {
get CIGAR() {
return readFeaturesToCIGAR(
this.record.readFeatures,
this.record.alignmentStart,
Expand All @@ -115,29 +105,12 @@ export default class CramSlightlyLazyFeature implements Feature {
)
}

tags() {
return Object.getOwnPropertyNames(CramSlightlyLazyFeature.prototype)
.filter(
prop =>
prop.startsWith('_get_') &&
prop !== '_get_mismatches' &&
prop !== '_get_cram_read_features',
)
.map(methodName => methodName.replace('_get_', ''))
}

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

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

parent() {
Expand All @@ -148,40 +121,58 @@ export default class CramSlightlyLazyFeature implements Feature {
return undefined
}

set() {}

pairedFeature() {
return false
get mismatches() {
return readFeaturesToMismatches(
this.record.readFeatures,
this.start,
this.qualRaw,
)
}

_get_clipPos() {
const mismatches = this.get('mismatches')
if (mismatches.length) {
const record =
this.get('strand') === -1 ? mismatches.at(-1) : mismatches[0]
const { type, cliplen } = record
if (type === 'softclip' || type === 'hardclip') {
return cliplen
}
get fields(): SimpleFeatureSerialized {
return {
start: this.start,
name: this.name,
end: this.end,
score: this.score,
qual: this.qual,
strand: this.strand,
template_length: this.template_length,
flags: this.flags,
tags: this.tags,
refName: this.refName,
CIGAR: this.CIGAR,
seq: this.seq,
type: 'match',
pair_orientation: this.pair_orientation,
next_ref: this.next_ref,
next_pos: this.next_pos,
next_segment_position: this.next_segment_position,
uniqueId: this.id(),
}
return 0
}

toJSON(): SimpleFeatureSerialized {
return {
...Object.fromEntries(
this.tags()
.map(t => [t, this.get(t)])
.filter(elt => elt[1] !== undefined),
),
uniqueId: this.id(),
}
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_mismatches() {
const readFeatures = this.record.readFeatures
const qual = this.qualRaw()
const start = this.get('start')
return readFeaturesToMismatches(readFeatures, start, qual)
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(CramSlightlyLazyFeature, 'fields')

0 comments on commit 071d8cb

Please sign in to comment.