PRO ncdf_read,filename,info,dinfo,vinfo,gatts,vatts,data ; -------- ---- ----- ----- ----- ----- ---- ; | | | | | | ; general info --' | | | | `-- data ; dimension info --------' | | `-------- variable attributes ; variable info --------------' `-------------- global attributes ; ; ================== ; read a NetCDF file ; ================== ; ; NB The data is read into a rather nasty combination of structures, arrays, ; and pointers, which is, unfortunately, necessary in order to cope with ; the full generality of the data format. Here is the sort of syntax you ; might use to get at elements of the returned data -- cumbersome because ; IDL doesn't support C-type "a->b" shorthand for "(*a).b". ; ; "INFO.NDIMS" ; "INFO.NVARS" ; "INFO.NGATTS" ; "INFO.RECDIM" ; ; "DINFO[idim].NAME" ; "DINFO[idim].SIZE" ; ; "VINFO[ivar].NAME" ; "VINFO[ivar].NAME" ; "VINFO[ivar].DATATYPE" ; "VINFO[ivar].NDIMS" ; "VINFO[ivar].NATTS" ; "VINFO[ivar].DIM[ivdim]" ; ; "GATTS.NAME" ; "GATTS.DATATYPE" ; "GATTS.LENGTH" ; "*GATTS.VALUES" or maybe "STRING(*GATTS.VALUES)" ; ; "(*VATTS[ivar])[iatt].NAME" ; "(*VATTS[ivar])[iatt].DATATYPE" ; "(*VATTS[ivar])[iatt].LENGTH" ; "*(*VATTS[ivar])[iatt].VALUES" or maybe ; "STRING(*(*VATTS[ivar])[iatt].VALUES)" ; ; "*DATA[ivar]" or maybe "(*DATA[ivar])[idim1,idim2,idim3,...]" ; ;---------------------------------------------------------------------- ; compile_opt idl2, strictarrsubs ; ;; open file id=ncdf_open(filename) ;; info info=ncdf_inquire(id) ;; dimension info dinfo=replicate({name:"",size:0L},info.ndims) for idim=0,info.ndims-1 do begin $ ncdf_diminq,id,idim,name,size dinfo[idim].name=name dinfo[idim].size=size endfor ;; variable info vinfo=replicate({ name:"", $ datatype:"", $ ndims:0l, natts:0l, $ dim:lonarr(info.ndims) $ },info.nvars) for ivar=0,info.nvars-1 do begin var=ncdf_varinq(id,ivar) vinfo[ivar].name=var.name vinfo[ivar].datatype=var.datatype vinfo[ivar].ndims=var.ndims vinfo[ivar].natts=var.natts vinfo[ivar].dim=var.dim endfor ;; global attributes if info.ngatts gt 0 then begin gatts=replicate({name:'', $ datatype:'', $ length:0L, $ values:ptr_new()}, $ info.ngatts) for iatt=0,info.ngatts-1 do begin name=ncdf_attname(id,iatt,/global) gatts[iatt].name=name att=ncdf_attinq(id,name,/global) gatts[iatt].length=att.length gatts[iatt].datatype=att.datatype ncdf_attget,id,name,vals,/global gatts[iatt].values=ptr_new(vals) endfor endif else begin ;; arbitary scalar value ;; an empty list would be sensible but IDL doesn't support it gatts=-1 endelse ;; variable attributes vatts=replicate(ptr_new(),info.nvars) for ivar=0,info.nvars-1 do begin if vinfo[ivar].natts gt 0 then begin vatts[ivar]=ptr_new(replicate({name:'', $ datatype:'', $ length:0L, $ values:ptr_new()}, $ vinfo[ivar].natts)) for iatt=0,vinfo[ivar].natts-1 do begin name=ncdf_attname(id,ivar,iatt) (*vatts[ivar])[iatt].name=name att=ncdf_attinq(id,ivar,name) (*vatts[ivar])[iatt].length=att.length (*vatts[ivar])[iatt].datatype=att.datatype ncdf_attget,id,ivar,name,vals (*vatts[ivar])[iatt].values=ptr_new(vals) endfor endif else begin vatts[ivar]=ptr_new(-1) ;; Pointer to arbitrary scalar -- analogous to case of lack of ;; global attributes above. We could put a here ;; instead, but try to be friendlier to code that might try ;; to dereference it. endelse endfor ;; data data=replicate(ptr_new(),info.nvars) for ivar=0,info.nvars-1 do begin ncdf_varget,id,ivar,val data[ivar]=ptr_new(val) endfor end