Search code examples
matlabidlnetcdfidl-programming-language

IDL and MatLab getting strange values from NetCDF file


I have a NetCDF file, which contains data representing total precipitation across the globe over several months (so it's stored in a three dimensional array). I first ensured that the data was sensible, and the way it was formed, both in XConv and ncdump. All looks sensible - values vary from very small (~10^-10 - this makes sense, as this is model data, and effectively represents zero) to about 5x10^-3.

The problems start when I try to handle this data in IDL or MatLab. The arrays generated in these programs are full of huge negative numbers such as -4x10^4, with occasional huge positive numbers, such as 5000. Strangely, looking at a plot of the data in MatLab with respect to latitude and longitude (at a specific time), the pattern of rainfall looks sensible, but the values are just completely wrong.

In IDL, I'm reading the file in to write it to a text file so it can be handled by some software that takes very basic text files. Here's the code I'm using:

PRO nao_heaps

address = '/Users/levyadmin/Downloads/'
file_base = 'output'
ncid = ncdf_open(address + file_base + '.nc')

MONTHS=['january','february','march','april','may','june','july','august','september','october','november','december']

varid_field = ncdf_varid(ncid, "tp")
varid_lon = ncdf_varid(ncid, "longitude")
varid_lat = ncdf_varid(ncid, "latitude")
varid_time = ncdf_varid(ncid, "time")

ncdf_varget,ncid, varid_field, total_precip
ncdf_varget,ncid, varid_lat, lats
ncdf_varget,ncid, varid_lon, lons
ncdf_varget,ncid, varid_time, time

ncdf_close,ncid

lats = reform(lats)
lons = reform(lons)
time = reform(time)
total_precip = reform(total_precip)
total_precip = total_precip*1000. ;put in mm

noLats=(size(lats))(1)
noLons=(size(lons))(1)
noMonths=(size(time))(1)

; the data may not be an integer number of years (otherwise we could make this next loop cleaner)
av_precip=fltarr(noLons,noLats,12)
for month=0, 11 do begin
  year = 0
  while ( (year*12) + month lt noMonths ) do begin
    av_precip(*,*,month) = av_precip(*,*,month) + total_precip(*,*, (year*12)+month )
    year++
  endwhile
  av_precip(*,*,month) = av_precip(*,*,month)/year
endfor

fname = address + file_base + '.dat'
OPENW,1,fname
PRINTF,1,'longitude'
PRINTF,1,lons

PRINTF,1,'latitude'
PRINTF,1,lats

for month=0,11 do begin
  PRINTF,1,MONTHS(month)
  PRINTF,1,av_precip(*,*,month)
endfor


CLOSE,1

END

Anyone have any ideas why I'm getting such strange values in MatLab and IDL?!


Solution

  • AH! Found the answer. NetCDF files use an offset, and a scale factor for the data to keep the size of the file to a minimum. To get the correct values, I simply need to:

    total_precip = offset + (scale_factor * total_precip) ;put into correct range
    

    At present I'm getting the scale factor and offset from ncdump, and hard coding them into my IDL program, but does anyone know how I can get them dynamically in my IDL code..?