1+ import { NC_CONSTANTS , DATA_TYPE_SIZE , CONSTANT_DTYPE_MAP } from './constants.js' ;
2+ import type { NetCDF4Module } from './types.js' ;
3+
4+ export function getVariables (
5+ module : NetCDF4Module ,
6+ ncid : number
7+ ) : Record < string , any > {
8+ const variables : Record < string , any > = { } ;
9+ const varCount = getVarCount ( module , ncid ) ;
10+ const dimIds = getDimIDs ( module , ncid )
11+ for ( let varid = 0 ; varid < varCount ; varid ++ ) {
12+ if ( dimIds . includes ( varid ) ) continue ; //Don't include spatial Vars
13+
14+ const result = module . nc_inq_varname ( ncid , varid ) ;
15+ if ( result . result !== NC_CONSTANTS . NC_NOERR || ! result . name ) {
16+ console . warn ( `Failed to get variable name for varid ${ varid } (error: ${ result . result } )` ) ;
17+ continue ;
18+ }
19+ variables [ result . name ] = {
20+ id : varid
21+ }
22+ }
23+ return variables ;
24+ }
25+
26+ export function getVarCount (
27+ module : NetCDF4Module ,
28+ ncid : number
29+ ) : number {
30+ const result = module . nc_inq_nvars ( ncid ) ;
31+ if ( result . result !== NC_CONSTANTS . NC_NOERR ) {
32+ throw new Error ( `Failed to get number of variables (error: ${ result . result } )` ) ;
33+ }
34+ return result . nvars || 0 ;
35+ }
36+
37+ export function getDimCount (
38+ module : NetCDF4Module ,
39+ ncid : number
40+ ) : number {
41+ const result = module . nc_inq_ndims ( ncid ) ;
42+ if ( result . result !== NC_CONSTANTS . NC_NOERR ) {
43+ throw new Error ( `Failed to get number of dimensions (error: ${ result . result } )` ) ;
44+ }
45+ return result . ndims || 0 ;
46+ }
47+
48+ export function getDims (
49+ module : NetCDF4Module ,
50+ ncid : number
51+ ) : Record < string , any > {
52+ const dimIDs = getDimIDs ( module , ncid ) ;
53+ const dims : Record < string , any > = { } ;
54+ for ( const dimid of dimIDs ) {
55+ const dim = getDim ( module , ncid , dimid )
56+ dims [ dim . name ] = {
57+ size : dim . len ,
58+ units :dim . units ,
59+ id :dim . id
60+ }
61+ }
62+ return dims
63+ }
64+
65+ export function getDimIDs (
66+ module : NetCDF4Module ,
67+ ncid : number
68+ ) : number [ ] | Int32Array {
69+ const result = module . nc_inq_dimids ( ncid , 0 ) ;
70+ if ( result . result !== NC_CONSTANTS . NC_NOERR ) {
71+ throw new Error ( `Failed to get dimension IDs (error: ${ result . result } )` ) ;
72+ }
73+ return result . dimids || [ 0 ] ;
74+ }
75+
76+ export function getDim (
77+ module : NetCDF4Module ,
78+ ncid : number ,
79+ dimid : number
80+ ) : Record < string , any > {
81+ const result = module . nc_inq_dim ( ncid , dimid ) ;
82+ if ( result . result !== NC_CONSTANTS . NC_NOERR ) {
83+ throw new Error ( `Failed to get dim (error: ${ result . result } )` ) ;
84+ }
85+ const varResult = module . nc_inq_varid ( ncid , result . name as string )
86+ const varID = varResult . varid as number
87+ const { result :output , ...dim } = result
88+ const unitResult = getAttributeValues ( module , ncid , varID , "units" )
89+ return { ...dim , units :unitResult , id :varID } ;
90+ }
91+
92+ export function getAttributeValues (
93+ module : NetCDF4Module ,
94+ ncid : number ,
95+ varid : number ,
96+ attname : string
97+ ) : any {
98+ const attInfo = module . nc_inq_att ( ncid , varid , attname ) ;
99+ if ( attInfo . result !== NC_CONSTANTS . NC_NOERR ) {
100+ console . warn ( `Failed to get attribute info for ${ attname } (error: ${ attInfo . result } )` ) ;
101+ return ;
102+ }
103+ const attType = attInfo . type ;
104+ if ( ! attType ) throw new Error ( "Failed to allocate memory for attribute type." ) ;
105+ let attValue ;
106+ if ( attType === 2 ) attValue = module . nc_get_att_text ( ncid , varid , attname , attInfo . len as number ) ;
107+ else if ( attType === 3 ) attValue = module . nc_get_att_short ( ncid , varid , attname , attInfo . len as number ) ;
108+ else if ( attType === 4 ) attValue = module . nc_get_att_int ( ncid , varid , attname , attInfo . len as number ) ;
109+ else if ( attType === 5 ) attValue = module . nc_get_att_float ( ncid , varid , attname , attInfo . len as number ) ;
110+ else if ( attType === 6 ) attValue = module . nc_get_att_double ( ncid , varid , attname , attInfo . len as number ) ;
111+ else if ( attType === 10 ) attValue = module . nc_get_att_longlong ( ncid , varid , attname , attInfo . len as number ) ;
112+ else attValue = module . nc_get_att_double ( ncid , varid , attname , attInfo . len as number ) ;
113+
114+ return attValue . data
115+ }
116+
117+ export function getGlobalAttributes (
118+ module : NetCDF4Module ,
119+ ncid : number ,
120+ ) : Record < string , any > {
121+ const attributes : Record < string , any > = { } ;
122+ const nattsResult = module . nc_inq_natts ( ncid ) ;
123+ if ( nattsResult . result !== NC_CONSTANTS . NC_NOERR ) {
124+ throw new Error ( `Failed to get number of global attributes (error: ${ nattsResult . result } )` ) ;
125+ }
126+ const nAtts = nattsResult . natts as number
127+ const attNames = [ ]
128+ for ( let i = 0 ; i < nAtts ; i ++ ) {
129+ const name = getAttributeName ( module , ncid , NC_CONSTANTS . NC_GLOBAL , i )
130+ attNames . push ( name )
131+ }
132+ if ( attNames . length === 0 ) return attributes
133+ for ( const attname of attNames ) {
134+ if ( ! attname ) continue ;
135+ attributes [ attname ] = getAttributeValues ( module , ncid , NC_CONSTANTS . NC_GLOBAL , attname )
136+ }
137+ return attributes
138+ }
139+
140+ export function getAttributeName (
141+ module : NetCDF4Module ,
142+ ncid : number ,
143+ varid :number ,
144+ attId : number
145+ ) : string | undefined {
146+ const result = module . nc_inq_attname ( ncid , varid , attId ) ;
147+ if ( result . result !== NC_CONSTANTS . NC_NOERR ) {
148+ throw new Error ( `Failed to get attribute (error: ${ result . result } )` ) ;
149+ }
150+ return result . name
151+ }
152+
153+ export function getFullMetadata (
154+ module : NetCDF4Module ,
155+ ncid : number ,
156+ ) : Record < string , any > [ ] {
157+ const varIds = getVarIDs ( module , ncid )
158+ const metas = [ ]
159+ for ( const varid of varIds ) {
160+ const varMeta = getVariableInfo ( module , ncid , varid )
161+ const { attributes, ...varDeets } = varMeta
162+ metas . push ( { ...varDeets , ...attributes } )
163+ }
164+ return metas
165+ }
166+
167+ export function getVarIDs (
168+ module : NetCDF4Module ,
169+ ncid : number
170+ ) : number [ ] | Int32Array {
171+ const result = module . nc_inq_varids ( ncid ) ;
172+ if ( result . result !== NC_CONSTANTS . NC_NOERR ) {
173+ throw new Error ( `Failed to get variable IDs (error: ${ result . result } )` ) ;
174+ }
175+ return result . varids || [ 0 ] ;
176+ }
177+
178+ export function getVariableInfo (
179+ module : NetCDF4Module ,
180+ ncid : number ,
181+ variable : number | string ) : Record < string , any > {
182+ const info : Record < string , any > = { }
183+
184+ const isId = typeof variable === "number"
185+ let varid = variable
186+ if ( ! isId ) {
187+ const result = module . nc_inq_varid ( ncid , variable )
188+ varid = result . varid as number
189+ }
190+ const result = module . nc_inq_var ( ncid , varid as number ) ;
191+ if ( result . result !== NC_CONSTANTS . NC_NOERR ) {
192+ throw new Error ( `Failed to get variable info (error: ${ result . result } )` ) ;
193+ }
194+ const typeMultiplier = DATA_TYPE_SIZE [ result . type as number ]
195+
196+ //Dim Info
197+ const dimids = result . dimids
198+ const dims = [ ]
199+ const shape = [ ]
200+ let size = 1
201+ if ( dimids ) {
202+ for ( const dimid of dimids ) {
203+ const dim = getDim ( module , ncid , dimid )
204+ size *= dim . len
205+ dims . push ( dim )
206+ shape . push ( dim . len )
207+ }
208+ }
209+
210+ //Attribute Info
211+ const attNames = [ ]
212+ if ( result . natts ) {
213+ for ( let i = 0 ; i < result . natts ; i ++ ) {
214+ const attname = getAttributeName ( module , ncid , varid as number , i )
215+ attNames . push ( attname )
216+ }
217+ }
218+ const atts : Record < string , any > = { }
219+ if ( attNames . length > 0 ) {
220+ for ( const attname of attNames ) {
221+ if ( ! attname ) continue ;
222+ atts [ attname ] = getAttributeValues ( module , ncid , varid as number , attname )
223+ }
224+ }
225+
226+ //Chunking Info
227+ let chunks : number [ ] ;
228+ const chunkResult = module . nc_inq_var_chunking ( ncid , varid as number ) ;
229+ const isChunked = chunkResult . chunking === NC_CONSTANTS . NC_CHUNKED
230+ if ( isChunked ) {
231+ chunks = chunkResult . chunkSizes as number [ ]
232+ } else {
233+ chunks = shape
234+ }
235+ const chunkElements = chunks . reduce ( ( a : number , b : number ) => a * b , 1 )
236+
237+ //Output
238+ info [ "name" ] = result . name
239+ info [ "dtype" ] = CONSTANT_DTYPE_MAP [ result . type as number ]
240+ info [ 'nctype' ] = result . type
241+ info [ "shape" ] = shape
242+ info [ 'dims' ] = dims
243+ info [ "size" ] = size
244+ info [ "totalSize" ] = size * typeMultiplier
245+ info [ "attributes" ] = atts
246+ info [ "chunked" ] = isChunked
247+ info [ "chunks" ] = chunks
248+ info [ "chunkSize" ] = chunkElements * typeMultiplier
249+
250+ return info ;
251+ }
252+
253+ export function getVariableArray (
254+ module : NetCDF4Module ,
255+ ncid : number ,
256+ variable : number | string
257+ ) : Float32Array | Float64Array | Int16Array | Int32Array | BigInt64Array | BigInt [ ] | string [ ] {
258+ const isId = typeof variable === "number"
259+ let varid = isId ? variable as number : 0
260+ if ( ! isId ) {
261+ const result = module . nc_inq_varid ( ncid , variable )
262+ varid = result . varid as number
263+ }
264+ const info = getVariableInfo ( module , ncid , varid )
265+ const arraySize = info . size
266+ const arrayType = info . nctype
267+ if ( ! arrayType || ! arraySize ) throw new Error ( "Failed to allocate memory for array" )
268+ let arrayData ;
269+ if ( arrayType === 2 ) arrayData = module . nc_get_var_text ( ncid , varid , arraySize ) ;
270+ else if ( arrayType === 3 ) arrayData = module . nc_get_var_short ( ncid , varid , arraySize ) ;
271+ else if ( arrayType === 4 ) arrayData = module . nc_get_var_int ( ncid , varid , arraySize ) ;
272+ else if ( arrayType === 10 ) arrayData = module . nc_get_var_longlong ( ncid , varid , arraySize ) ;
273+ else if ( arrayType === 5 ) arrayData = module . nc_get_var_float ( ncid , varid , arraySize ) ;
274+ else if ( arrayType === 6 ) arrayData = module . nc_get_var_double ( ncid , varid , arraySize ) ;
275+ else arrayData = module . nc_get_var_double ( ncid , varid , arraySize ) ;
276+ if ( ! arrayData . data ) throw new Error ( "Failed to read array data" )
277+ return arrayData . data
278+ }
279+
280+ export function getSlicedVariableArray (
281+ module : NetCDF4Module ,
282+ ncid : number ,
283+ variable : number | string ,
284+ start : number [ ] ,
285+ count : number [ ]
286+ ) : Float32Array | Float64Array | Int16Array | Int32Array | BigInt64Array | BigInt [ ] | string [ ] {
287+ const isId = typeof variable === "number"
288+ let varid = isId ? variable as number : 0
289+ if ( ! isId ) {
290+ const result = module . nc_inq_varid ( ncid , variable )
291+ varid = result . varid as number
292+ }
293+ const info = getVariableInfo ( module , ncid , varid )
294+ const arrayType = info . nctype
295+ if ( ! arrayType ) throw new Error ( "Failed to allocate memory for array" )
296+ let arrayData ;
297+ if ( arrayType === 3 ) arrayData = module . nc_get_vara_short ( ncid , varid , start , count ) ;
298+ else if ( arrayType === 4 ) arrayData = module . nc_get_vara_int ( ncid , varid , start , count ) ;
299+ else if ( arrayType === 5 ) arrayData = module . nc_get_vara_float ( ncid , varid , start , count ) ;
300+ else if ( arrayType === 6 ) arrayData = module . nc_get_vara_double ( ncid , varid , start , count ) ;
301+ else arrayData = module . nc_get_vara_double ( ncid , varid , start , count ) ;
302+ if ( ! arrayData . data ) {
303+ console . log ( arrayData )
304+ throw new Error ( "Failed to read array data" ) }
305+ return arrayData . data
306+ }
307+
308+ // if (!module) throw new Error("Failed to load module. Ensure module is initialized before calling methods")
0 commit comments