Export time dimension NetCDF to raster format using ArcPy

4626
24
Jump to solution
06-11-2018 05:06 AM
ShouvikJha
Occasional Contributor III

I have single NetCDF file which is time dimension NetCDF file, the netCDF file contains the monthly weather data for 20 years. I want to convert the NetCDF to raster tiff format and output of the raster as same the month and year name. below is code but it's producing the error in line number 29. Time format of the data is YY-MM-DD 2013-01-01 12:00, 2013-02-01 12:00, so on. How to loop all the time dimension.  

updated download link for input files: 2013.nc - Google Drive 

I tried to extract the layer manually using ArcGIS tool, it's successfully extracted. I have copied the code from ArcGIS 

arcpy.MakeNetCDFRasterLayer_md(in_netCDF_file="E:/Weather/2002.nc",
variable="slhf",
x_dimension="longitude",
y_dimension="latitude",
out_raster_layer="sshf_Layer",
band_dimension="",
dimension_values="time '01-01-2013 12:00:00'",
value_selection_method="BY_VALUE")‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
# Import system modules
import arcpy
from arcpy import env
from arcpy.sa import *

#Workspace
outLoc = r"E:\Weather/"
inNetCDF = r"E:\Weather\2002.nc"
#Veriable
variable = "slhf"
x_dimension = "lon"
y_dimension = "lat"
band_dimension = ""
dimension = "time"
valueSelectionMethod = "BY_VALUE"

nc_FP = arcpy.NetCDFFileProperties(inNetCDF)
nc_Dim = nc_FP.getDimensions()

for dimension in nc_Dim:
        if dimension == "time":
            top = nc_FP.getDimensionSize(dimension)
            for i in range(0, top):

                dimension_values = nc_FP.getDimensionValue(dimension, i)
                nowFile = str(dimension_values)
                nowFile = nowFile.translate(None, '/')
                # I needed after 2013
                if int(nowFile.split()[0].split('-')[-1])==2013:

                    dv1 = ["time", dimension_values]
                    dimension_values = [dv1]

                    arcpy.MakeNetCDFRasterLayer_md(inNetCDF, variable, x_dimension, y_dimension, nowFile, band_dimension, dimension_values, valueSelectionMethod)
                    print "success"
                    outname = outLoc + nowFile

                    arcpy.CopyRaster_management(nowFile, outname,"", "", "", "NONE", "NONE", "")


                else: print "DATA OUT OF RANGE"‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Error message

ExecuteError: Failed to execute. Parameters are not valid.
ERROR 000237: One or more dimensions are invalid
ERROR 000237: One or more dimensions are invalid
Failed to execute (MakeNetCDFRasterLayer).‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos
24 Replies
ShouvikJha
Occasional Contributor III

Xander Bakker‌, i just checked the time given in code in line number 38 and changed according to the name of the first layer, it extracted the first layer successfully but from second layer its show DATA OUT OF RANGE . We can not keep the ==112013 statement constant as different month layer has a different number, e.g for Januray 112013, February 212013, March 312013 so on , but what you displayed it shows the constant number for each layer as 4021900. 

 Please corporate to work out the issue  

if int(nowFile.split()[0].split('-')[-1])==112013:  # 2013‍‍

While extracting the data, can we keep the layer name same as time spam of data , for instance, for first layer 112013, second 212013, 

0 Kudos
XanderBakker
Esri Esteemed Contributor

Could you try the code below (changing the paths to the input NC file and output products)?

def main():
    # Import system modules
    import arcpy
    import os
    arcpy.env.overwriteOutput = True

    #Workspace
    outLoc = r"C:\GeoNet\NetCDF"
    inNetCDF = r"C:\GeoNet\NetCDF\2013.nc"
    #Veriable
    variable = "slhf"
    x_dimension = "longitude"
    y_dimension = "latitude"
    band_dimension = ""
    dimension = "time"
    valueSelectionMethod = "BY_VALUE"

    nc_FP = arcpy.NetCDFFileProperties(inNetCDF)
    print "nc_FP:", nc_FP
    nc_Dim = nc_FP.getDimensions()
    print "nc_Dim:", nc_Dim

    for dimension in nc_Dim:
        print "dimension:", dimension
        if dimension == "time":
            top = nc_FP.getDimensionSize(dimension)
            print "top:", top
            for i in range(0, top):
                print "i", i
                dimension_values = nc_FP.getDimensionValue(dimension, i)
                year = GetYear(dimension_values)
                print "year:", year
                name = GetNameOutputFile(dimension_values)
                print "name:", name

                if year == '2013':
                    dv1 = "time '{}'".format(dimension_values)
                    # dv1 = ["time", dimension_values]
                    # dimension_values = [dv1]
                    out_ras_lay = "sshf_{}".format(name)

                    arcpy.MakeNetCDFRasterLayer_md(inNetCDF, variable, x_dimension, y_dimension, out_ras_lay, band_dimension, dv1, valueSelectionMethod)
                    print "success"
                    out_name =  "{}.tif".format(out_ras_lay)
                    out_ras = os.path.join(outLoc, out_name)
                    print "out_name:", out_name
                    print "out_ras:", out_ras

                    arcpy.CopyRaster_management(out_ras_lay, out_ras,"", "", "", "NONE", "NONE", "")
                    print "CopyRaster OK..."

                else:
                    print "DATA OUT OF RANGE"



def GetNameOutputFile(dimension_value):
    dct_ampm = {'P.':'PM', 'A.':'AM', 'PM': 'PM', 'AM': 'AM'}
    lst1 = dimension_value.split(' ')
    if '/' in dimension_value:
        lst2a = lst1[0].split('/')
        lst2b = lst1[1].split(':')
        lst2a = CorrectList(lst2a)
        lst2b = CorrectList(lst2b)
        if len(lst1) >= 3:
            ampm = lst1[2].upper()
            if ampm in dct_ampm:
                ampm = dct_ampm[ampm]
            else:
                ampm = 'XX'
            name = 'd{}{}{}_t{}{}{}'.format(lst2a[2], lst2a[1], lst2a[0], lst2b[0], lst2b[1], ampm)
        else:
            name = 'd{}{}{}_t{}{}'.format(lst2a[2], lst2a[1], lst2a[0], lst2b[0], lst2b[1])

    elif '-' in dimension_value:
        lst2a = lst1[0].split('-')
        lst2b = lst1[1].split(':')
        name = 'd{}{}{}_t{}{}'.format(lst2a[2], lst2a[1], lst2a[0], lst2b[0], lst2b[1])
    else:
        name = 'd18990101_t0000'
    return name


def GetYear(dimension_value):
    lst1 = dimension_value.split(' ')
    if '/' in dimension_value:
        year = lst1[0].split('/')[2]
    elif '-' in dimension_value:
        year = lst1[0].split('-')[2]
    else:
        year = '1899'
    return year


def CorrectList(lst2a):
    lst = []
    for a in lst2a:
        if len(a) == 1:
            lst.append('0{}'.format(a))
        else:
            lst.append(a)
    return lst


if __name__ == '__main__':
    main()
0 Kudos
ShouvikJha
Occasional Contributor III

Xander Bakker‌ Thank you. This script perfectly running 

XanderBakker
Esri Esteemed Contributor

I'm glad it worked!

0 Kudos
ShouvikJha
Occasional Contributor III

Xander Bakker‌, please can you look at the code, why its generating error message, 

0 Kudos