@@ -46,12 +46,12 @@ export function runClass(config: Config, freq = 600): ClassData {
4646 const profiles : TimeSeries1D = { } ;
4747 const plumes : TimeSeries1D = { } ;
4848
49- // Helper function to parse class output
50- // calculate profiles and fireplumes,
49+ // Helper function to parse class output
50+ // calculate profiles and fireplumes,
5151 // and export as timeseries
5252 const writeOutput = ( ) => {
5353 const output : Partial < ClassOutput > = { } ;
54-
54+
5555 // Generate timeseries
5656 for ( const key of outputKeys ) {
5757 const value = model . getValue ( key ) ;
@@ -62,32 +62,31 @@ export function runClass(config: Config, freq = 600): ClassData {
6262 }
6363
6464 // Generate profiles
65+ const keysToAlign = [ "p" , "T" , "Td" ] ;
6566 if ( config . sw_ml ) {
6667 const profile = generateProfiles ( config , output as ClassOutput ) ;
6768 const profileXY = profileToXY ( profile as unknown as Profile ) ;
69+ const simplifiedProfile = simplifyProfile ( profileXY , 0.01 , keysToAlign ) ;
6870
69- for ( const key of Object . keys ( profileXY ) ) {
71+ for ( const key of Object . keys ( simplifiedProfile ) ) {
7072 profiles [ key ] = profiles [ key ] || [ ] ; // Initialize if not exists
71- profiles [ key ] . push ( simplifyLine ( profileXY [ key ] , 0.01 ) ) ;
73+ profiles [ key ] . push ( simplifiedProfile [ key ] ) ;
7274 }
7375
7476 // Generate plumes
7577 if ( config . sw_fire ) {
7678 const plume = calculatePlume ( config , profile ) ;
7779 const plumeXY = plumeToXY ( plume ) ;
78- console . log ( "profile:" , profile ) ;
79- console . log ( "plume:" , plume ) ;
80+ const simplifiedPlume = simplifyProfile ( plumeXY , 0.01 , keysToAlign ) ;
8081
81- for ( const key of Object . keys ( plumeXY ) ) {
82+ for ( const key of Object . keys ( simplifiedPlume ) ) {
8283 plumes [ key ] = plumes [ key ] || [ ] ;
83- plumes [ key ] . push ( simplifyLine ( plumeXY [ key ] , 0.01 ) ) ;
84+ plumes [ key ] . push ( simplifiedPlume [ key ] ) ;
8485 }
85-
8686 }
8787 }
8888 } ;
8989
90-
9190 // Initial time
9291 writeOutput ( ) ;
9392
@@ -110,17 +109,19 @@ export function runClass(config: Config, freq = 600): ClassData {
110109 return { timeseries } ;
111110}
112111
113- type Profile = Record < string , number [ ] > & { z : number [ ] } ;
112+ type Profile = Record < string , number [ ] > & { z : number [ ] } ;
114113
115114/**
116- *
115+ *
117116 * Convert a profile like {z: [], theta: [], qt: [], ...}
118117 * to a profile like: {theta: {x: [], y: []}, qt: {x: [], y:[]}, ...}
119118 *
120119 * Useful to simplify profiles independently for each variable
121120 * and also to quickly obtain the data for a line plot
122121 */
123- function profileToXY ( profile : Profile ) : Record < string , { x : number ; y : number } [ ] > {
122+ function profileToXY (
123+ profile : Profile ,
124+ ) : Record < string , { x : number ; y : number } [ ] > {
124125 const result : Record < string , { x : number ; y : number } [ ] > = { } ;
125126
126127 for ( const key of Object . keys ( profile ) ) {
@@ -150,23 +151,75 @@ function plumeToXY(plume: Parcel[]) {
150151 return result ;
151152}
152153
153-
154154/**
155155 * Compress a line by discarding points that are within a certain relative tolerance.
156- * Using the simplify-js package, which implements the
156+ * Using the simplify-js package, which implements the
157157 * Ramer-Douglas-Peucker algorithm
158158 */
159- function simplifyLine ( line : { x : number ; y : number } [ ] , tolerance = 0.01 ) : { x : number ; y : number } [ ] {
159+ function simplifyLine (
160+ line : { x : number ; y : number } [ ] ,
161+ tolerance = 0.01 ,
162+ ) : { x : number ; y : number } [ ] {
160163 if ( line . length <= 2 ) return line ; // Nothing to simplify
161164
162- const xs = line . map ( p => p . x ) ;
163- const ys = line . map ( p => p . y ) ;
165+ const xs = line . map ( ( p ) => p . x ) ;
166+ const ys = line . map ( ( p ) => p . y ) ;
164167 const xRange = Math . max ( ...xs ) - Math . min ( ...xs ) ;
165168 const yRange = Math . max ( ...ys ) - Math . min ( ...ys ) ;
166169 const relTol = Math . min ( xRange , yRange ) * tolerance ;
167170
168171 const simplified = simplify ( line , relTol , true ) ;
169- console . log ( `Simplified from ${ line . length } to ${ simplified . length } points` ) ;
172+ // console.log(`Simplified from ${line.length} to ${simplified.length} points`);
170173 // console.log(`Simplified`);
174+ return simplified ;
175+ }
176+
177+ /**
178+ * Simplify and optionally align a profile.
179+ *
180+ * @param profileXY - Profile in {x: number; y: number}[] format
181+ * @param tolerance - Relative tolerance for simplification (default 0.01)
182+ * @param alignKeys - Array of variable keys to align. If `true`, align all. If `false` or empty, skip alignment.
183+ * @returns The simplified (and optionally partially aligned) profile
184+ */
185+ function simplifyProfile (
186+ profileXY : Record < string , { x : number ; y : number } [ ] > ,
187+ tolerance = 0.01 ,
188+ alignKeys : string [ ] | true | false = true ,
189+ ) : Record < string , { x : number ; y : number } [ ] > {
190+ // Simplify each variable
191+ const simplified : Record < string , { x : number ; y : number } [ ] > = { } ;
192+ for ( const key in profileXY ) {
193+ simplified [ key ] = simplifyLine ( profileXY [ key ] , tolerance ) ;
194+ }
195+
196+ // Decide which keys to align
197+ let keysToAlign : string [ ] ;
198+ if ( alignKeys === true ) {
199+ keysToAlign = Object . keys ( profileXY ) ;
200+ } else if ( Array . isArray ( alignKeys ) && alignKeys . length > 0 ) {
201+ keysToAlign = alignKeys ;
202+ } else {
203+ return simplified ; // nothing to align
204+ }
205+
206+ // // Build union Z grid from all simplified variables
207+ // const zSet = new Set<number>(
208+ // Object.values(simplified).flatMap((line) => line.map((pt) => pt.y)),
209+ // );
210+ // Step 3: Build union Z grid only for keys to align
211+ const zSet = new Set < number > (
212+ keysToAlign . flatMap ( ( key ) => simplified [ key ] ?. map ( ( pt ) => pt . y ) ?? [ ] ) ,
213+ ) ;
214+
215+ console . log ( zSet . size ) ;
216+
217+ // Align selected variables using original profileXY
218+ for ( const key of keysToAlign ) {
219+ if ( profileXY [ key ] ) {
220+ simplified [ key ] = profileXY [ key ] . filter ( ( pt ) => zSet . has ( pt . y ) ) ;
221+ }
222+ }
223+
171224 return simplified ;
172225}
0 commit comments