I'm having a tough time visualizing a netCDF file with poor metadata in ArcMap, which is probably not a surprise. I know the file to contain ozone concentrations over the United States. If I try to bring the layer into ArcMap using "Make NetCDF Raster Layer" I get the following:
Clearly something isn't right, but it's kind of close. The US states layer is in straight WGS84. If it's helpful, the bottom left corner of the netCDF layer is at (0, 0) decimal degrees. If I open it up in Panoply, it works fine without modification, which suggests to me that the file contains some kind of helpful information, somewhere:
I've surmised that gdalwarp should be able to help, but I'm not sure how. If I run gdalinfo on the netCDF file, I get the following:
>> gdalinfo MAX8hr_4th.2050_T2_year
Warning 1: No UNIDATA NC_GLOBAL:Conventions attribute
Driver: netCDF/Network Common Data Format
Files: MAX8hr_4th.2050_T2_year
Size is 512, 512
Coordinate System is `'
Metadata:
NC_GLOBAL#CDATE=2013282
NC_GLOBAL#CTIME=144932
NC_GLOBAL#EXEC_ID=????????????????
NC_GLOBAL#FILEDESC=Concentration file output Averaged over the synchronization time steps
Timestamp represents beginning computed date/time
Layer mapping (CGRID to AGRID): Layer 1 to 1
NC_GLOBAL#FTYPE=1
NC_GLOBAL#GDNAM=clim36
NC_GLOBAL#GDTYP=2
NC_GLOBAL#HISTORY=
NC_GLOBAL#IOAPI_VERSION=$Id: @(#) ioapi library version 3.0 $
NC_GLOBAL#NCOLS=148
NC_GLOBAL#NLAYS=4
NC_GLOBAL#NROWS=122
NC_GLOBAL#NTHIK=1
NC_GLOBAL#NVARS=1
NC_GLOBAL#P_ALP=33
NC_GLOBAL#P_BET=45
NC_GLOBAL#P_GAM=-97
NC_GLOBAL#SDATE=2050001
NC_GLOBAL#STIME=80000
NC_GLOBAL#TSTEP=240000
NC_GLOBAL#UPNAM=MAX8HRCELL
NC_GLOBAL#VAR-LIST=O3
NC_GLOBAL#VGLVLS={1,0,0,0,0}
NC_GLOBAL#VGTOP=5000
NC_GLOBAL#VGTYP=7
NC_GLOBAL#WDATE=2013282
NC_GLOBAL#WTIME=144932
NC_GLOBAL#XCELL=36000
NC_GLOBAL#XCENT=-97
NC_GLOBAL#XORIG=-2736000
NC_GLOBAL#YCELL=36000
NC_GLOBAL#YCENT=40
NC_GLOBAL#YORIG=-2448000
Subdatasets:
SUBDATASET_1_NAME=NETCDF:"MAX8hr_4th.2050_T2_year":TFLAG
SUBDATASET_1_DESC=[1x1x2] TFLAG (32-bit integer)
SUBDATASET_2_NAME=NETCDF:"MAX8hr_4th.2050_T2_year":O3
SUBDATASET_2_DESC=[1x4x122x148] O3 (32-bit floating-point)
Corner Coordinates:
Upper Left ( 0.0, 0.0)
Lower Left ( 0.0, 512.0)
Upper Right ( 512.0, 0.0)
Lower Right ( 512.0, 512.0)
Center ( 256.0, 256.0)
which appears to contain some spatial information (NC_GLOBAL#XCENT, NC_GLOBAL#XORIG, etc.), but I'm unsure how to employ it.
Here's the output from a call to ncdump -h ozone.nc
(filename shortened for brevity).
dimensions:
TSTEP = UNLIMITED ; // (1 currently)
DATE-TIME = 2 ;
LAY = 4 ;
VAR = 1 ;
ROW = 122 ;
COL = 148 ;
variables:
int TFLAG(TSTEP, VAR, DATE-TIME) ;
TFLAG:units = "<YYYYDDD,HHMMSS>" ;
TFLAG:long_name = "TFLAG " ;
TFLAG:var_desc = "Timestep-valid flags: (1) YYYYDDD or (2) HHMMSS " ;
float O3(TSTEP, LAY, ROW, COL) ;
O3:long_name = "O3 " ;
O3:units = "ppbV " ;
O3:var_desc = "Linear combination of \"O3\" " ;
// global attributes:
:IOAPI_VERSION = "$Id: @(#) ioapi library version 3.0 $ " ;
:EXEC_ID = "???????????????? " ;
:FTYPE = 1 ;
:CDATE = 2013282 ;
:CTIME = 144749 ;
:WDATE = 2013282 ;
:WTIME = 144749 ;
:SDATE = 2010001 ;
:STIME = 80000 ;
:TSTEP = 240000 ;
:NTHIK = 1 ;
:NCOLS = 148 ;
:NROWS = 122 ;
:NLAYS = 4 ;
:NVARS = 1 ;
:GDTYP = 2 ;
:P_ALP = 33. ;
:P_BET = 45. ;
:P_GAM = -97. ;
:XCENT = -97. ;
:YCENT = 40. ;
:XORIG = -2736000. ;
:YORIG = -2448000. ;
:XCELL = 36000. ;
:YCELL = 36000. ;
:VGTYP = 7 ;
:VGTOP = 5000.f ;
:VGLVLS = 1.f, 0.f, 0.f, 0.f, 0.f ;
:GDNAM = "clim36 " ;
:UPNAM = "MAX8HRCELL " ;
:VAR-LIST = "O3 " ;
:FILEDESC = "Concentration file output Averaged over the synchronization time steps Timestamp represents beginning computed date/time Layer mapping (CGRID to AGRID): Layer 1 to 1 " ;
:HISTORY = "" ;
}
EDIT: Based on some additional information synthesized from the data's source and the metadata, I gathered that the data are already in a Lambert Conformal projection but that ArcMap isn't able to extract that info from the metadata. My approach has been to use gdal_translate
to properly embed the projection information in the netCDF file. The following call gets very close, but is not quite there:
gdal_translate -of netCDF -a_ullr -2736000 2448000 2736000 -2448000 -a_srs "+proj=lcc +lat_1=33 +lat_2=45 +lat_0=40 +lon_0=-97 +x_0=0 +y_0=0 +ellps=sphere +datum=NAD83 +units=m +no_defs" NETCDF:"MAX8hr_4th.2050_T2_year":O3 out.nc
This gives me the following in Arc:
It seems like the data need to be shifted west and south slightly, but I'm not sure how to do that precisely given that I've used the best information I can get from the metadata already. One idea is that the assumed radius of the Earth needs to be changed (I believe the data are based on a spherical assumption from investigation within Panoply), but changing the proj4 definition to +ellps=sphere
doesn't change the assumed spheroid, as shown in the call to gdalinfo
which now returns:
Warning 1: dimension #1 (LAY) is not a Time dimension.
Warning 1: dimension #0 (TSTEP) is not a Time dimension.
Driver: netCDF/Network Common Data Format
Files: ozone6.nc
Size is 148, 122
Coordinate System is:
PROJCS["unnamed",
GEOGCS["NAD83",
DATUM["North_American_Datum_1983",
SPHEROID["GRS 1980",6378137,298.257222101,
AUTHORITY["EPSG","7019"]],
TOWGS84[0,0,0,0,0,0,0],
AUTHORITY["EPSG","6269"]],
PRIMEM["Greenwich",0,
AUTHORITY["EPSG","8901"]],
UNIT["degree",0.0174532925199433,
AUTHORITY["EPSG","9108"]],
AUTHORITY["EPSG","4269"]],
PROJECTION["Lambert_Conformal_Conic_2SP"],
PARAMETER["standard_parallel_1",33],
PARAMETER["standard_parallel_2",45],
PARAMETER["latitude_of_origin",40],
PARAMETER["central_meridian",-97],
PARAMETER["false_easting",0],
PARAMETER["false_northing",0],
UNIT["Meter",1]]
Origin = (-2736000.000000000000000,2447999.999999999500000)
Pixel Size = (36972.972972972981000,-40131.147540983598000)
Metadata:
lambert_conformal_conic#false_easting=0
lambert_conformal_conic#false_northing=0
lambert_conformal_conic#GeoTransform=-2736000 36972.97297297297 0 2448000 0 -40131.14754098361
lambert_conformal_conic#grid_mapping_name=lambert_conformal_conic
lambert_conformal_conic#inverse_flattening=298.257222101
lambert_conformal_conic#latitude_of_projection_origin=40
lambert_conformal_conic#longitude_of_central_meridian=-97
lambert_conformal_conic#longitude_of_prime_meridian=0
lambert_conformal_conic#semi_major_axis=6378137
lambert_conformal_conic#spatial_ref=PROJCS["unnamed",GEOGCS["NAD83",DATUM["North_American_Datum_1983",SPHEROID["GRS 1980",6378137,298.257222101,AUTHORITY["EPSG","7019"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY["EPSG","6269"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9108"]],AUTHORITY["EPSG","4269"]],PROJECTION["Lambert_Conformal_Conic_2SP"],PARAMETER["standard_parallel_1",33],PARAMETER["standard_parallel_2",45],PARAMETER["latitude_of_origin",40],PARAMETER["central_meridian",-97],PARAMETER["false_easting",0],PARAMETER["false_northing",0],UNIT["Meter",1]]
lambert_conformal_conic#standard_parallel={33,45}
NC_GLOBAL#CDATE=2013282
NC_GLOBAL#Conventions=CF-1.5
NC_GLOBAL#CTIME=144749
NC_GLOBAL#EXEC_ID=????????????????
NC_GLOBAL#FILEDESC=Concentration file output Averaged over the synchronization time steps Timestamp represents beginning computed date/time Layer mapping (CGRID to AGRID): Layer 1 to 1
NC_GLOBAL#FTYPE=1
NC_GLOBAL#GDAL=GDAL 1.11.3, released 2015/09/16
NC_GLOBAL#GDNAM=clim36
NC_GLOBAL#GDTYP=2
NC_GLOBAL#history=Tue May 03 12:44:02 2016: GDAL CreateCopy( ozone6.nc, ... )
NC_GLOBAL#IOAPI_VERSION=$Id: @(#) ioapi library version 3.0 $
NC_GLOBAL#NCOLS=148
NC_GLOBAL#NLAYS=4
NC_GLOBAL#NROWS=122
NC_GLOBAL#NTHIK=1
NC_GLOBAL#NVARS=1
NC_GLOBAL#P_ALP=33
NC_GLOBAL#P_BET=45
NC_GLOBAL#P_GAM=-97
NC_GLOBAL#SDATE=2010001
NC_GLOBAL#STIME=80000
NC_GLOBAL#TSTEP=240000
NC_GLOBAL#UPNAM=MAX8HRCELL
NC_GLOBAL#VAR-LIST=O3
NC_GLOBAL#VGLVLS={1,0,0,0,0}
NC_GLOBAL#VGTOP=5000
NC_GLOBAL#VGTYP=7
NC_GLOBAL#WDATE=2013282
NC_GLOBAL#WTIME=144749
NC_GLOBAL#XCELL=36000
NC_GLOBAL#XCENT=-97
NC_GLOBAL#XORIG=-2736000
NC_GLOBAL#YCELL=36000
NC_GLOBAL#YCENT=40
NC_GLOBAL#YORIG=-2448000
NETCDF_DIM_EXTRA={TSTEP,LAY}
NETCDF_DIM_LAY_DEF={4,5}
NETCDF_DIM_LAY_VALUES={9.96921e+036,9.96921e+036,9.96921e+036,9.96921e+036}
NETCDF_DIM_TSTEP_DEF={1,5}
NETCDF_DIM_TSTEP_VALUES=9.96921e+036
O3#_FillValue=9.96921e+036
O3#grid_mapping=lambert_conformal_conic
O3#long_name=O3
O3#units=ppbV
O3#var_desc=Linear combination of O3
x#long_name=x coordinate of projection
x#standard_name=projection_x_coordinate
x#units=m
y#long_name=y coordinate of projection
y#standard_name=projection_y_coordinate
y#units=m
Corner Coordinates:
Upper Left (-2736000.000, 2448000.000) (140d30'40.39"W, 55d50'15.32"N)
Lower Left (-2736000.000,-2448000.000) (120d53'22.23"W, 15d10'27.73"N)
Upper Right ( 2736000.000, 2448000.000) ( 53d29'19.61"W, 55d50'15.32"N)
Lower Right ( 2736000.000,-2448000.000) ( 73d 6'37.77"W, 15d10'27.73"N)
Center ( 0.0000000, 0.0000000) ( 97d 0' 0.00"W, 40d 0' 0.00"N)
Band 1 Block=148x1 Type=Float32, ColorInterp=Undefined
NoData Value=9.969209968386869e+036
Metadata:
_FillValue=9.96921e+036
grid_mapping=lambert_conformal_conic
long_name=O3
NETCDF_DIM_LAY=9.96921e+036
NETCDF_DIM_TSTEP=9.96921e+036
NETCDF_VARNAME=O3
units=ppbV
var_desc=Linear combination of O3
Band 2 Block=148x1 Type=Float32, ColorInterp=Undefined
NoData Value=9.969209968386869e+036
Metadata:
_FillValue=9.96921e+036
grid_mapping=lambert_conformal_conic
long_name=O3
NETCDF_DIM_LAY=9.96921e+036
NETCDF_DIM_TSTEP=9.96921e+036
NETCDF_VARNAME=O3
units=ppbV
var_desc=Linear combination of O3
Band 3 Block=148x1 Type=Float32, ColorInterp=Undefined
NoData Value=9.969209968386869e+036
Metadata:
_FillValue=9.96921e+036
grid_mapping=lambert_conformal_conic
long_name=O3
NETCDF_DIM_LAY=9.96921e+036
NETCDF_DIM_TSTEP=9.96921e+036
NETCDF_VARNAME=O3
units=ppbV
var_desc=Linear combination of O3
Band 4 Block=148x1 Type=Float32, ColorInterp=Undefined
NoData Value=9.969209968386869e+036
Metadata:
_FillValue=9.96921e+036
grid_mapping=lambert_conformal_conic
long_name=O3
NETCDF_DIM_LAY=9.96921e+036
NETCDF_DIM_TSTEP=9.96921e+036
NETCDF_VARNAME=O3
units=ppbV
var_desc=Linear combination of O3
ncdump -h dataset.nc
? Or post a link to the data?+datum=NAD83
together with+ellps=sphere
, NAD83 will override the sphere definition. Instead, use+R=6370000
.