Re: reading all variables from a netCDF file - solved

From: Saji N. Hameed <saji_at_nyahnyahspammersnyahnyah>
Date: Mon, 2 Mar 2009 10:58:10 +0900

Hi Jonathan,

Congratulations for solving the problem and much thanks for sharing
your new code with us...

Best wishes,

saji

--
* Jonathan Vigh <vigh_at_atmos.colostate.edu> [2009-02-26 22:04:03 +0000]:
> Hi all,
>   After thinking some more, I realized a way to incorporate Saji's  
> suggestion as a module that runs at the beginning of the program. This  
> module opens the file and queries it to obtain the list of variables.  
> Using that variable list, it dynamically generates another module which  
> contains the lines to read them from the file. This module should be  
> loaded immediately after the first one. Both modules are called from the  
> main calling program outside of the main statement block, so all the  
> variables read in from the file will be global and available to all  
> functions and procedures throughout the program.
>
> Since all that is required is to load the two modules at the top of your  
> program, I think this is a pretty unobtrusive way to read in the  
> contents of a netCDF file with many or unknown variables.
>
> I've attached the module_read_netcdf.ncl code, the module that was  
> generated dynamically (which will be overwritten at run-time), an  
> example 'main.ncl', and a simple netCDF file for those who are curious  
> to try this out.
>
> Thanks for the helpful suggestion!
>
> Jonathan
>
>
>
>
> Jonathan Vigh wrote:
>> Hi Saji,
>>     Thanks for the suggestion - that is an innovative idea. I was 
>> hoping to modify this idea a bit and write code to generate just the 
>> lines of code I would need to read in each variable, write these out as 
>> a module, and then load that module within my program in the spot I 
>> need it - but unfortunately "load" only works if the module is loaded 
>> outside of the block that is planning to use it, so I get an error when 
>> I try to load it:
>> "input in flex scanner failed"
>>
>> So for now, I'm just going to use NCL to generate the 100+ lines to  
>> reach each variable and cut and paste it into my program (and repeat  
>> this if the variables in my netCDF files change).
>>
>> Hopefully new versions of NCL can include some of these nifty features, 
>> like an "eval" function, a way to create variables without assignment,  
>> and a way to reference a variable without knowing it's name before 
>> runtime.
>>
>> Jonathan
>>
>>
>>
>>
>>
>> Saji N. Hameed wrote:
>>   
>>> Hi Jonathan,
>>>
>>> As a follow up of my previous mail related to "eval", why don't you
>>> run ncl on your code twice? The first pass will create NCL code that
>>> will be run in the second pass.
>>>
>>> Here is my crude semi-pseudo-code 
>>>
>>> Start of NCL file ----------
>>>
>>> _NCLCode=""  ; declared at the outset. global variable??
>>>
>>> function cr()
>>> begin
>>>   return(inttochar(10))
>>> end
>>>
>>> procedure add_msg(msg)
>>> begin
>>>   _NCLCode=_NCLCode+cr+msg
>>> end
>>>
>>>
>>> begin
>>>   do ivar = 0,nvar-1
>>>     msg =varnames(ivar)+" = fin->$"+varnames(ivar)+"$"     
>>> add_msg(msg)
>>>   end do
>>>
>>>   asciiwrite("runit.ncl",_NCLCode)   system("ncl runit.ncl")
>>> end
>>>
>>>
>>>
>>> * Jonathan Vigh <vigh_at_atmos.colostate.edu> [2009-02-24 21:05:59 +0000]:
>>>
>>>       
>>>> Hi David,
>>>>    I'll likely be doing some conditional processing, where some  
>>>> variables affect others, so I'd like to have them all in memory at 
>>>> once. For this specific application, all the variables are quite 
>>>> small - the entire netCDF file is <50 KB - so it won't be a problem 
>>>> to hold them all in memory. I'm planning to read in about 200 of 
>>>> these files and aggregate some of the 177 variables into several 
>>>> multidimensional arrays for further data analysis. The variables 
>>>> are a hodgepodge of arrays of strings, logicals, integers, floats, 
>>>> etc. It's a mess. I've never had to work with such a disparate 
>>>> collection of data before. The netCDF files I'm reading are 
>>>> actually an intermediate (but necessary) step - the data were 
>>>> originally read from several very nonstandard ascii file formats  
>>>> and I wrote them to the netCDF files. I wrote out the 177 variables 
>>>> using a general method, so that's why I was hoping to read in the 
>>>> 177 variables in a general way. The trouble with creating the 
>>>> variable without knowing it's name seems to be the main hitch at 
>>>> the moment. Accessing it without knowing it's name is the other 
>>>> hitch.
>>>>
>>>> So basically, I think need a "create_new_var" procedure (not 
>>>> function) which would act like:
>>>>    create_new_var( varname, vartype, vardimsize )
>>>>
>>>> One the variable is created in memory, I'd need a way to reference 
>>>> it in order to assign data to it from the file.
>>>>
>>>> So my code to read in everything would be something like:
>>>>   varnames = getfilevarnames(fin)        ; Returns an array of file 
>>>> variable names in the file
>>>>   vartypes = getfilevartypes(fin,varnames)       ; Returns the type 
>>>> of each variable name listed. A missing value is returned for any 
>>>> variable name that doesn't exist in the file.
>>>>
>>>>   nvars = dimsizes(varnames)
>>>>    do ivar = 0, nvars-1
>>>>       create_new_var( varnames(ivar), vartypes(ivar),  
>>>> getfilevardimsizes(fin,varnames(ivar)) )
>>>>       #varnames(ivar)# = fin->$varnames(ivar)$      ; where # # is 
>>>> used to indicate the way to reference the variable in memory using 
>>>> the string value from my array varnames that was queried from the 
>>>> file
>>>>    end do
>>>>
>>>> If there was a way to reference the variable from memory, one could 
>>>> do all the processing on an arbitrary variable without ever knowing 
>>>> it's name. This would be a nice feature to have.
>>>>
>>>> Jonathan
>>>>
>>>>
>>>>
>>>> Dave Allured wrote:
>>>>           
>>>>> Jonathan,
>>>>>
>>>>> Do you need to have all the variables in memory at the same time, 
>>>>> or can you just process them one at a time from the input file to 
>>>>> the output file(s)?  The second has a much easier answer than the 
>>>>> first.   A little more information about the nature of your 
>>>>> application is needed.
>>>>>
>>>>> Dave Allured
>>>>> CU/CIRES Climate Diagnostics Center (CDC)
>>>>> http://cires.colorado.edu/science/centers/cdc/
>>>>> NOAA/ESRL/PSD, Climate Analysis Branch (CAB)
>>>>> http://www.cdc.noaa.gov/psd1/
>>>>>
>>>>> Jonathan Vigh wrote:
>>>>>                 
>>>>>> Greetings NCL'ers,
>>>>>>     I'd like to read in all the variables from a netCDF file in 
>>>>>> a general way because there are 177 of them. I understand how 
>>>>>> to query the file and get a list of variable names, and I even 
>>>>>> understand how to reference the variable using:
>>>>>> fin->$varnames$
>>>>>>
>>>>>> What I am confused about is what to assign this to. I'd like to 
>>>>>> avoid having to type out 177 lines to read in each variable if 
>>>>>> possible. But if I didn't even know the variable names in 
>>>>>> advance, I'd still like to know how to do this.
>>>>>>
>>>>>> Maybe I've missed something really basic, but I couldn't seem 
>>>>>> to find anything from the documentation. If anyone has an idea, 
>>>>>> I'd be most grateful. It would be nice if NCL could simply make 
>>>>>> all the variables in a netCDF file available without having to 
>>>>>> go through this step, so maybe this could be the prototype for 
>>>>>> a new function that does this.
>>>>>>
>>>>>> Thanks,
>>>>>>    Jonathan
>>>>>>
>>>>>>
>>>>>> begin
>>>>>>   processed_filename = systemfunc("cd " + 
>>>>>> processed_data_directory + "; ls " + stormid + "*.nc")     fin 
>>>>>> = addfile(processed_data_directory + processed_filename,"r")   
>>>>>> ; open output netCDF file
>>>>>>
>>>>>> ; query the file to see what variables it contains and what the 
>>>>>> sizes of the file dimensions are
>>>>>>   varnames = getfilevarnames(fin)        ; Returns an array of 
>>>>>> file variable names in the file
>>>>>>   filedimsizes = getfiledimsizes(fin)        ; Returns a list 
>>>>>> of the sizes of all the dimensions in the file.
>>>>>>
>>>>>> ; query all the named variables in the file
>>>>>>   vartypes = getfilevartypes(fin,varnames)       ; Returns the 
>>>>>> type of each variable name listed. A missing value is returned 
>>>>>> for any variable name that doesn't exist in the file.
>>>>>>
>>>>>>
>>>>>> ; loop through all the variables, query them, and read them in  
>>>>>>    nvars = dimsizes(varnames)
>>>>>>    do ivar = 0, nvars-1
>>>>>>       print("Reading variable ivar = "+ivar+"  
>>>>>> "+vartypes(ivar)+"      "+varnames(ivar))
>>>>>>       ???? = fin->$varnames(ivar)$             ; I understand 
>>>>>> how to read in a variable from a file if I don't know the 
>>>>>> variable name in advance, but how can I assign it to a variable 
>>>>>> without typing the variable's name?
>>>>>>    end do
>>>>>>
>>>>>> end
>>>>>> _______________________________________________
>>>>>> ncl-talk mailing list
>>>>>> List instructions, subscriber options, unsubscribe:
>>>>>> http://mailman.ucar.edu/mailman/listinfo/ncl-talk
>>>>>>                       
>>>>> _______________________________________________
>>>>> ncl-talk mailing list
>>>>> List instructions, subscriber options, unsubscribe:
>>>>> http://mailman.ucar.edu/mailman/listinfo/ncl-talk
>>>>>                 
>>>> _______________________________________________
>>>> ncl-talk mailing list
>>>> List instructions, subscriber options, unsubscribe:
>>>> http://mailman.ucar.edu/mailman/listinfo/ncl-talk
>>>>
>>>>           
>>>       
>>
>> _______________________________________________
>> ncl-talk mailing list
>> List instructions, subscriber options, unsubscribe:
>> http://mailman.ucar.edu/mailman/listinfo/ncl-talk
>>
>>   
>
> ;********************************************************
> ; main.ncl
> ;
> ; This program demonstrates a general method to read in the contents
> ; of a netCDF file without knowing the variable names in advance. 
> ;
> ;********************************************************
> ;load "$NCARG_ROOT/lib/ncarg/nclscripts/csm/gsn_code.ncl"
> ;load "$NCARG_ROOT/lib/ncarg/nclscripts/csm/gsn_csm.ncl"
> ;load "$NCARG_ROOT/lib/ncarg/nclscripts/csm/shea_util.ncl"
> ;load "$NCARG_ROOT/lib/ncarg/nclscripts/csm/contributed.ncl"
> load "./module_read_netcdf.ncl"
> load "./module_dynamically_generated_part.ncl"
> ; load your next "global" module
> ; then load any modules containing procedures or functions
> ;********************************************************
> begin
> 
>   print(" Now in the main calling program.")
> 
>   print("")
>   print("The file's variables are:")
>   print("")
> 
>   print("    "+varnames)
> 
> ; now do fun stuff with your data . . .
> 
> 
> 
> end
> 
> ;********************************************************
> ; module_dynamically_generated_part.ncl
> ; This module was generated dynamically by NCL to
> ; read in all the variables from a file since we may
> ; not know the variable names before run-time.
> ;********************************************************
> var3 = fin->var3
> var2 = fin->var2
> var1 = fin->var1
> ;********************************************************
> ; module_read_netCDF.ncl
> ;********************************************************
> ; This module contains a function to read all the variables 
> ; from a netCDF file without knowing the file contents in
> ; advance. It opens the file, queries it to determine
> ; which variables are present, and then reads them in..
> ;
> ; In order to make them available, all of this is done 
> ; before any other part of the subsequent program runs.
> ; i.e. the variables will be global and therefore 
> ; accessible to all functions and procedures in the
> ; main program which loads this module.
> ;
> ; Author: Jonathan Vigh, Colorado State University, 02/26/2009
> ; (with a helpful contribution by Saji N. Hameed, University of Hawaii)
> ;
> ;********************************************************
> ;
> ; Note that we do not put the contents of this module within 'begin' and 'end' statements. 
> ; This means that this everything in this module will be global (accessible to all other 
> ; functions and procedures in subsequent modules and the main program which loads this 
> ; module. 
> 
> ; the filename can either be given here or as a command-line argument
>   ncdf_filename            = "foo.nc"
> 
> 
> ;===================================================================
> ; Read the processed data file which contains the best track and VDM data for this storm 
> ;===================================================================
>   print("")
>   print("Now opening the netCDF data file: "+ncdf_filename)
>   fin = addfile(ncdf_filename,"r")   ; open output netCDF file
> 
> ; retrieve the global attributes from the file
>   fatt_names = getvaratts(fin)   
>   if(.not.all(ismissing(fatt_names))) then
>      print("")
>      print("The file's global attributes are: ")
>      print("")
>      
>      do i = 0,dimsizes(fatt_names)-1
>         print(fatt_names(i)+" = "+fin@$fatt_names(i)$)
>      end do
>   
>   end if
> 
> ; query the file to see what variables it contains and what the sizes of the file dimensions are
>   varnames = getfilevarnames(fin)		; Returns an array of file variable names in the file
>   filedimsizes = getfiledimsizes(fin)		; Returns a list of the sizes of all the dimensions in the file. 
> 
> ; query all the named variables in the file
>   vartypes = getfilevartypes(fin,varnames)   	; Returns the type of each variable name listed. A missing value is returned for any variable name that doesn't exist in the file.
> 
>   nvars = dimsizes(varnames)
> 
> ; Now use NCL to generate some code that we will then load and use to read in all the variables
> ; we will generate the lines of the module sequentially and attach them as strings to a boolean variable
> ; then we'll write all the strings out using asciiwrite.
> 
>   cr = inttochar(10)
> 
>   module_filename = "module_dynamically_generated_part.ncl" 
> 
>   module_contents = ";********************************************************" + cr \
>                   + "; " + module_filename + cr \
> 		  + "; This module was generated dynamically by NCL to" + cr \
> 		  + "; read in all the variables from a file since we may" + cr \
> 		  + "; not know the variable names before run-time." + cr \
> 		  + ";********************************************************" 
> 
>   do ivar = 0, nvars - 1
>      module_contents = module_contents + cr + varnames(ivar)+" = fin->"+varnames(ivar)
>   end do
> 
>   if(isfilepresent(module_filename))
>     system("/bin/rm -f " + module_filename)     ; remove a pre-existing file
>   end if
>  
>   asciiwrite(module_filename,module_contents)
>   
> ; The dynamically-generated module will then be loaded immediately after this module has been loaded in the calling program.
> ; Both modules must be loaded before the 'main' program begins (i.e. before the 'begin' statement).   
>  
> 
> _______________________________________________
> ncl-talk mailing list
> List instructions, subscriber options, unsubscribe:
> http://mailman.ucar.edu/mailman/listinfo/ncl-talk
-- 
Saji N. Hameed
APEC Climate Center          				+82 51 668 7470
National Pension Corporation Busan Building 12F         
Yeonsan 2-dong, Yeonje-gu, BUSAN 611705			saji_at_apcc21.net
KOREA
_______________________________________________
ncl-talk mailing list
List instructions, subscriber options, unsubscribe:
http://mailman.ucar.edu/mailman/listinfo/ncl-talk
Received on Sun Mar 01 2009 - 18:58:10 MST

This archive was generated by hypermail 2.2.0 : Mon Mar 02 2009 - 16:45:42 MST