@@ -57,6 +57,9 @@ export default class BigMafAdapter extends BaseFeatureDataAdapter {
5757
5858 getFeatures ( query : Region , opts ?: BaseOptions ) {
5959 const { statusCallback = ( ) => { } } = opts || { }
60+ // Pre-compile regex for better performance
61+ const WHITESPACE_REGEX = / + /
62+
6063 return ObservableCreate < Feature > ( async observer => {
6164 const { adapter } = await this . setup ( )
6265 const features = await updateStatus (
@@ -68,48 +71,66 @@ export default class BigMafAdapter extends BaseFeatureDataAdapter {
6871 for ( const feature of features ) {
6972 const maf = feature . get ( 'mafBlock' ) as string
7073 const blocks = maf . split ( ';' )
71- let aln : string | undefined
72- const alns = [ ] as string [ ]
73- const alignments = { } as Record < string , OrganismRecord >
74- const blocks2 = [ ] as string [ ]
74+
75+ // Count sequence blocks first to pre-size arrays
76+ let sequenceBlockCount = 0
7577 for ( const block of blocks ) {
7678 if ( block . startsWith ( 's' ) ) {
77- if ( aln ) {
78- alns . push ( block . split ( / + / ) [ 6 ] ! )
79- blocks2 . push ( block )
80- } else {
81- aln = block . split ( / + / ) [ 6 ]
82- alns . push ( aln ! )
83- blocks2 . push ( block )
84- }
79+ sequenceBlockCount ++
8580 }
8681 }
8782
88- for ( let i = 0 ; i < blocks2 . length ; i ++ ) {
89- const elt = blocks2 [ i ] !
90- const ad = elt . split ( / + / )
91- const y = ad [ 1 ] ! . split ( '.' )
92- const org = y [ 0 ] !
93- const chr = y [ 1 ] !
94-
95- alignments [ org ] = {
96- chr : chr ,
97- start : + ad [ 1 ] ! ,
98- srcSize : + ad [ 2 ] ! ,
99- strand : ad [ 3 ] === '+' ? 1 : - 1 ,
100- unknown : + ad [ 4 ] ! ,
101- seq : alns [ i ] ! ,
83+ // Pre-size arrays based on actual sequence block count
84+ const alns = new Array < string > ( sequenceBlockCount )
85+ const alignments = { } as Record < string , OrganismRecord >
86+
87+ let sequenceIndex = 0
88+ let referenceSeq : string | undefined
89+
90+ // Single-pass processing: combine both loops
91+ for ( const block of blocks ) {
92+ if ( block . startsWith ( 's' ) ) {
93+ // Split once and cache the result
94+ const parts = block . split ( WHITESPACE_REGEX )
95+ const sequence = parts [ 6 ] !
96+ const organismChr = parts [ 1 ] !
97+
98+ // Store sequence in pre-sized array
99+ alns [ sequenceIndex ] = sequence
100+
101+ // Set reference sequence from first block
102+ if ( referenceSeq === undefined ) {
103+ referenceSeq = sequence
104+ }
105+
106+ // Parse organism and chromosome once
107+ const dotIndex = organismChr . indexOf ( '.' )
108+ const org = organismChr . slice ( 0 , Math . max ( 0 , dotIndex ) )
109+ const chr = organismChr . slice ( Math . max ( 0 , dotIndex + 1 ) )
110+
111+ // Create alignment record directly
112+ alignments [ org ] = {
113+ chr,
114+ start : + parts [ 2 ] ! ,
115+ srcSize : + parts [ 3 ] ! ,
116+ strand : parts [ 4 ] === '+' ? 1 : - 1 ,
117+ unknown : + parts [ 5 ] ! ,
118+ seq : sequence ,
119+ }
120+
121+ sequenceIndex ++
102122 }
103123 }
124+
104125 observer . next (
105126 new SimpleFeature ( {
106127 id : feature . id ( ) ,
107128 data : {
108129 start : feature . get ( 'start' ) ,
109130 end : feature . get ( 'end' ) ,
110131 refName : feature . get ( 'refName' ) ,
111- seq : alns [ 0 ] ,
112- alignments : alignments ,
132+ seq : referenceSeq ,
133+ alignments,
113134 } ,
114135 } ) ,
115136 )
0 commit comments