From b4054761e8e3d15853ec153aea4ba2309e339a0e Mon Sep 17 00:00:00 2001 From: Martin Landa Date: Mon, 19 Nov 2018 16:40:10 +0100 Subject: [PATCH] arcgis provider major clean-up (work in progress), see #23 #24 --- smoderp2d/providers/arcgis/arcgis_dmtfce.py | 24 +- .../providers/arcgis/data_preparation.py | 357 ++++++++---------- smoderp2d/providers/base/data_preparation.py | 80 ++-- smoderp2d/providers/base/exception.py | 8 + smoderp2d/providers/grass/data_preparation.py | 4 +- 5 files changed, 245 insertions(+), 228 deletions(-) create mode 100644 smoderp2d/providers/base/exception.py diff --git a/smoderp2d/providers/arcgis/arcgis_dmtfce.py b/smoderp2d/providers/arcgis/arcgis_dmtfce.py index 74405a1..e9442eb 100644 --- a/smoderp2d/providers/arcgis/arcgis_dmtfce.py +++ b/smoderp2d/providers/arcgis/arcgis_dmtfce.py @@ -1,29 +1,32 @@ import arcpy -import arcgisscripting -gp = arcgisscripting.create() import sys import os +def dmtfce(dmt, save_dir, fl_dir=None): + """ -def dmtfce(dmt, save_dir, fl_dir): + :param str dmt: DMT raster name + :param str save_dir: directory where to save output + :param str fl_dir: flow direction raster name or None + """ # loading file soil_type_values # filling the sink areas in raster try: dmt_fill = arcpy.sa.Fill(dmt) except: + # TODO: use our own exceptions... arcpy.AddMessage( "Unexpected error during raster fill calculation:", sys.exc_info()[0]) raise # flow direction calculation - try: # tady by pak meslo jit pridavat pripraven fl dir - if fl_dir == "NONE": + try: + if not fl_dir: flow_direction = arcpy.sa.FlowDirection(dmt_fill) - flow_direction.save(save_dir + os.sep + "fl_dir") + flow_direction.save(os.path.join(save_dir, "fl_dir") else: flow_direction = fl_dir - except: arcpy.AddMessage( "Unexpected error during flow direction calculation:", @@ -33,8 +36,7 @@ def dmtfce(dmt, save_dir, fl_dir): # flow accumulation calculation try: flow_accumulation = arcpy.sa.FlowAccumulation(flow_direction) - flow_accumulation.save(save_dir + os.sep + "facc") - # mat_fa = arcpy.RasterToNumPyArray(flow_accumulation) + flow_accumulation.save(os.path.join(save_dir, "facc")) except: arcpy.AddMessage( "Unexpected error during flow accumulation calculation:", @@ -44,11 +46,11 @@ def dmtfce(dmt, save_dir, fl_dir): # slope calculation try: slope = arcpy.sa.Slope(dmt, "PERCENT_RISE", 1) - # ExtractByMask (slope, raster_dmt) - slope.save(save_dir + "\\slope") + slope.save(os.path.join(save_dir, "slope")) except: arcpy.AddMessage( "Unexpected error during slope calculation:", sys.exc_info()[0]) raise + return dmt_fill, flow_direction, flow_accumulation, slope diff --git a/smoderp2d/providers/arcgis/data_preparation.py b/smoderp2d/providers/arcgis/data_preparation.py index bfc35ad..f5654c5 100644 --- a/smoderp2d/providers/arcgis/data_preparation.py +++ b/smoderp2d/providers/arcgis/data_preparation.py @@ -10,6 +10,7 @@ from smoderp2d.providers.base import Logger from smoderp2d.providers.base.data_preparation import PrepareDataBase +from smoderp2d.providers.base.exception import DataPreparationInvalidInput # arcpy imports from arcpy.sa import * @@ -32,6 +33,40 @@ def __init__(self): arcpy.CheckOutExtension("Spatial") self.gp.overwriteoutput = 1 + def _get_input_params(self): + """Get input parameters from ArcGIS toolbox. + """ + self._input_params['dmt'] = self.gp.GetParameterAsText( + constants.PARAMETER_DMT) + self._input_params['soil_indata'] = self.gp.GetParameterAsText( + constants.PARAMETER_SOIL) + self._input_params['stype'] = self.gp.GetParameterAsText( + constants.PARAMETER_SOIL_TYPE) + self._input_params['veg_indata'] = self.gp.GetParameterAsText( + constants.PARAMETER_VEGETATION) + self._input_params['vtype'] = self.gp.GetParameterAsText( + constants.PARAMETER_VEGETATION_TYPE) + self._input_params['rainfall_file_path'] = self.gp.GetParameterAsText( + constants.PARAMETER_PATH_TO_RAINFALL_FILE) + self._input_params['maxdt'] = float(self.gp.GetParameterAsText( + constants.PARAMETER_MAX_DELTA_T)) + self._input_params['end_time'] = float(self.gp.GetParameterAsText( + constants.PARAMETER_END_TIME)) * 60.0 # prevod na s + self._input_params['points'] = self.gp.GetParameterAsText( + constants.PARAMETER_POINTS) + self._input_params['output'] = self.gp.GetParameterAsText( + constants.PARAMETER_PATH_TO_OUTPUT_DIRECTORY) + self._input_params['tab_puda_veg'] = self.gp.GetParameterAsText( + constants.PARAMETER_SOILVEGTABLE) + self._input_params['tab_puda_veg_code'] = self.gp.GetParameterAsText( + constants.PARAMETER_SOILVEGTABLE_CODE) + self._input_params['stream'] = self.gp.GetParameterAsText( + constants.PARAMETER_STREAM) + self._input_params['tab_stream_tvar'] = self.gp.GetParameterAsText( + constants.PARAMETER_STREAMTABLE) + self._input_params['tab_stream_tvar_code'] = self.gp.GetParameterAsText( + constants.PARAMETER_STREAMTABLE_CODE) + def run(self): """Main function of data_preparation class. Returns computed parameters from input data using ArcGIS in a form of a @@ -39,62 +74,8 @@ def run(self): :return data: dictionary with model parameters. """ - self._add_message("DATA PREPARATION") - self._add_message("----------------") - - self._create_dict() - - # get input parameters from ArcGIS toolbox - dmt = self.gp.GetParameterAsText(constants.PARAMETER_DMT) - soil_indata = self.gp.GetParameterAsText(constants.PARAMETER_SOIL) - ptyp = self.gp.GetParameterAsText(constants.PARAMETER_SOIL_TYPE) - veg_indata = self.gp.GetParameterAsText(constants.PARAMETER_VEGETATION) - vtyp = self.gp.GetParameterAsText(constants.PARAMETER_VEGETATION_TYPE) - rainfall_file_path = self.gp.GetParameterAsText(constants.PARAMETER_PATH_TO_RAINFALL_FILE) - maxdt = float(self.gp.GetParameterAsText(constants.PARAMETER_MAX_DELTA_T)) - end_time = float(self.gp.GetParameterAsText(constants.PARAMETER_END_TIME)) * 60.0 # prevod na s - points = self.gp.GetParameterAsText(constants.PARAMETER_POINTS) - output = self.gp.GetParameterAsText(constants.PARAMETER_PATH_TO_OUTPUT_DIRECTORY) - tab_puda_veg = self.gp.GetParameterAsText(constants.PARAMETER_SOILVEGTABLE) - tab_puda_veg_code = self.gp.GetParameterAsText(constants.PARAMETER_SOILVEGTABLE_CODE) - stream = self.gp.GetParameterAsText(constants.PARAMETER_STREAM) - tab_stream_tvar = self.gp.GetParameterAsText(constants.PARAMETER_STREAMTABLE) - tab_stream_tvar_code = self.gp.GetParameterAsText(constants.PARAMETER_STREAMTABLE_CODE) - - # set dict parameters from input data (fixed) - self.data['maxdt'] = maxdt - self.data['end_time'] = end_time - self.data['outdir'] = output - self.data['points'] = points - - # create output folder, where temporary data are stored - self._add_message("Creating output...") - self._set_output() - - # copy of dmt for ?? TODO - # TODO: move to _create_mask - dmt_copy = os.path.join(self.data['temp'], "tempGDB.gdb", "dmt_copy") - arcpy.CopyRaster_management(dmt, dmt_copy) - - arcpy.env.snapRaster = dmt + super(PrepareData, self).run() - self._add_message( - "Computing fill, flow direction, flow accumulation, slope..." - ) - dmt_fill, flow_direction, flow_accumulation, slope_orig = \ - dmtfce(dmt_copy, self.data['temp'], "NONE") - - # intersect - self._add_message("Computing intersect of input data...") - intersect, null_shp, sfield = self._get_intersect( - dmt_copy, veg_indata, soil_indata, vtyp, ptyp, - tab_puda_veg, tab_puda_veg_code - ) - - # clip - self._add_message("Clip of the source data by intersect...") - flow_direction_clip, slope_clip, dmt_clip = self._clip_data( - dmt_copy, intersect, slope_orig, flow_direction) self._add_message("Computing parameters of DMT...") # raster to numpy array conversion @@ -154,125 +135,131 @@ def _add_message(self, message): def _set_output(self): - """ - Creates and clears directories, to which created files are saved. - Creates temporary geodatabase. - """ - - # deleting output directory - shutil.rmtree(self.data['outdir']) - - if not os.path.exists(self.data['outdir']): - os.makedirs(self.data['outdir']) - self._add_message("Creating of the output directory: " + self.data['outdir']) - - self.data['temp'] = self.data['outdir'] + os.sep + "temp" - - if not os.path.exists(self.data['temp']): - os.makedirs(self.data['temp']) - - self._add_message("Creating of the temp: " + self.data['temp']) - - # deleting content of output directory - dirList = os.listdir(self.data['outdir']) # arcgis bug - locking shapefiles - ab = 0 - for fname in dirList: - if "sr.lock" in fname: - ab = 1 - - if ab == 0: - contents = [os.path.join(self.data['outdir'], i) for i in os.listdir(self.data['outdir'])] - - [shutil.rmtree(i) if os.path.isdir(i) else os.unlink(i) - for i in contents] - - if not os.path.exists(self.data['temp']): - os.makedirs(self.data['temp']) - - temp_gdb = arcpy.CreateFileGDB_management(self.data['temp'], "tempGDB.gdb") - - def _get_intersect(self, dmt_copy, veg_indata, soil_indata, vtyp, ptyp, tab_puda_veg, tab_puda_veg_code): - """ - :param dmt_copy: - :param veg_indata: - :param soil_indata: - :param vtyp: - :param ptyp: - :param tab_puda_veg: - :param tab_puda_veg_code: + """Creates empty output and temporary directories to which created + files are saved. Creates temporary ArcGIS File Geodatabase. - :return intersect: - :return null_shp: - :return sfield: """ + super(PrepareData, self)._set_output() - # adding attribute for soil and vegetation into attribute table (type short int) - # preparation for clip - null = self.data['temp'] + os.sep + "hrance_rst" - null_shp = self.data['temp'] + os.sep + "null.shp" - self.gp.Reclassify_sa(dmt_copy, "VALUE", "-100000 100000 1", null, "DATA") # reklasifikuje se vsechno na 1 - arcpy.RasterToPolygon_conversion(null, null_shp, "NO_SIMPLIFY") + # create temporary ArcGIS File Geodatabase + arcpy.CreateFileGDB_management( + self.data['temp'], "tempGDB.gdb" + ) - soil_boundary = self.data['temp'] + os.sep + "s_b.shp" - veg_boundary = self.data['temp'] + os.sep + "v_b.shp" + def _set_mask(self): + """TODO""" + dmt_copy = os.path.join( + self.data['temp'], "tempGDB.gdb", "dmt_copy") + arcpy.CopyRaster_management(dmt, dmt_copy) - arcpy.Dissolve_management(veg_indata, veg_boundary, vtyp) - arcpy.Dissolve_management(soil_indata, soil_boundary, ptyp) + # align computation region to DMT grid + arcpy.env.snapRaster = dmt - group = [soil_boundary, veg_boundary, null_shp] - intersect = self.data['outdir'] + os.sep + "interSoilLU.shp" + dmt_mask = os.path.join(self.data['temp'], "dmt_mask") + self.gp.Reclassify_sa( + dmt_copy, "VALUE", "-100000 100000 1", dmt_mask, "DATA" + ) # reklasifikuje se vsechno na 1 + + return dmt_copy, dmt_mask + + def _dmtfce(self, dmt): + return dmtfce(dmt, self.data['temp']) + + def _get_intersect(self, dmt, mask, + veg_indata, soil_indata, vtype, stype, + tab_puda_veg, tab_puda_veg_code): + """ + :param str dmt: DMT raster name + :param str mask: raster mask name + :param str veg_indata: vegetation input vector name + :param soil_indata: soil input vector name + :param vtype: attribute vegetation column for dissolve + :param stype: attribute soil column for dissolve + :param tab_puda_veg: soil table to join + :param tab_puda_veg_code: key soil attribute + + :return intersect: intersect vector name + :return mask_shp: vector mask name + :return sfield: list of selected attributes + """ + # convert mask into polygon feature class + mask_shp = os.path.join(self.data['temp'], "mask.shp") + arcpy.RasterToPolygon_conversion( + mask, mask_shp, "NO_SIMPLIFY") + + # dissolve soil and vegetation polygons + soil_boundary = os.path.join( + self.data['temp'], "s_b.shp") + veg_boundary = os.path.join( + self.data['temp'], "v_b.shp") + arcpy.Dissolve_management(veg_indata, veg_boundary, vtype) + arcpy.Dissolve_management(soil_indata, soil_boundary, stype) + + # do intersection + group = [soil_boundary, veg_boundary, mask_shp] + intersect = os.path.join( + self.data['outdir'], "interSoilLU.shp") arcpy.Intersect_analysis(group, intersect, "ALL", "", "INPUT") + # remove "puda_veg" if exists and create a new one if self.gp.ListFields(intersect, "puda_veg").Next(): arcpy.DeleteField_management(intersect, "puda_veg") - arcpy.AddField_management(intersect, "puda_veg", "TEXT", "", "", "15", "", "NULLABLE", "NON_REQUIRED","") - - if ptyp == vtyp: - vtyp1 = vtyp + "_1" - else: - vtyp1 = vtyp + arcpy.AddField_management( + intersect, "puda_veg", "TEXT", "", "", "15", "", + "NULLABLE", "NON_REQUIRED","") - fields = [ptyp, vtyp1, "puda_veg"] + # compute "puda_veg" values (stype + vtype) + vtype1 = vtype + "_1" if stype == vtype else vtype + fields = [stype, vtype1, "puda_veg"] with arcpy.da.UpdateCursor(intersect, fields) as cursor: for row in cursor: row[2] = row[0] + row[1] cursor.updateRow(row) - del cursor - - puda_veg_dbf = self.data['temp'] + os.sep + "puda_veg_tab_current.dbf" + # copy attribute table to DBF file for modifications + puda_veg_dbf = os.path.join( + self.data['temp'], "puda_veg_tab_current.dbf") arcpy.CopyRows_management(tab_puda_veg, puda_veg_dbf) - sfield = ["k", "s", "n", "pi", "ppl", "ret", "b", "x", "y", "tau", "v"] - self._join_table(intersect, "puda_veg", puda_veg_dbf,tab_puda_veg_code,"k;s;n;pi;ppl;ret;b;x;y;tau;v") + + # join table copy to intersect feature class + sfield = ["k", "s", "n", "pi", "ppl", + "ret", "b", "x", "y", "tau", "v"] + self._join_table( + intersect, "puda_veg", puda_veg_dbf, tab_puda_veg_code, + ";".join(sfield) + ) with arcpy.da.SearchCursor(intersect, sfield) as cursor: for row in cursor: for i in range(len(row)): - if row[i] == " ": - self._add_message( - "Values in soilveg tab are not correct - STOP, check shp file Prunik in output") - sys.exit() + if row[i] == " ": # TODO: empty string or NULL value? + raise DataPreparationInvalidInput( + "Values in soilveg tab are not correct" + ) - return intersect, null_shp, sfield + return intersect, mask_shp, sfield - def _clip_data(self, dmt_copy, intersect, slope_orig, flow_direction): + def _clip_data(self, dmt, intersect, slope, flow_direction): """ + Clip input data based on AOI. - :param dmt_copy: - :param intersect: - :param slope_orig: - :param flow_direction: - - :return flow_direction_clip: - :return slope_clip: - :return dmt_clip: - """ + :param str dmt: raster DMT name + :param str intersect: vector intersect feature call name + :param str slope: raster slope name + :param str flow_direction: raster flow direction name - # mask and clip data + :return str dmt_clip: output clipped DMT name + :return str slope_clip: output clipped slope name + :return str flow_direction_clip: ouput clipped flow direction name - if self.data['points'] and (self.data['points'] != "#") and (self.data['points'] != ""): + """ + # TODO: check only None value + # clip input vectors based on AOI + if self.data['points'] and \ + (self.data['points'] != "#") and (self.data['points'] != ""): self.data['points'] = self._clip_points(intersect) + # set extent from intersect vector map arcpy.env.extent = intersect # raster description @@ -281,56 +268,42 @@ def _clip_data(self, dmt_copy, intersect, slope_orig, flow_direction): # output raster coordinate system arcpy.env.outputCoordinateSystem = dmt_desc.SpatialReference - maska = self.data['temp'] + os.sep + "maska" - arcpy.PolygonToRaster_conversion(intersect, "FID", maska, "MAXIMUM_AREA", cellsize = dmt_desc.MeanCellHeight) + # create raster mask based on interesect feature calll + mask = os.path.join(self.data['temp'], "mask") + arcpy.PolygonToRaster_conversion( + intersect, "FID", mask, "MAXIMUM_AREA", + cellsize = dmt_desc.MeanCellHeight) # cropping rasters - dmt_clip = ExtractByMask(dmt_copy, maska) - dmt_clip.save(self.data['outdir'] + os.sep + "DMT") - slope_clip = ExtractByMask(slope_orig, maska) - slope_clip.save(self.data['temp'] + os.sep + "slope_clip") + dmt_clip = ExtractByMask(dmt_copy, mask) + dmt_clip.save(os.path.join(self.data['outdir'], "dmt_clip")) + slope_clip = ExtractByMask(slope_orig, mask) + slope_clip.save(os.path.join(self.data['temp'], "slope_clip")) + flow_direction_clip = ExtractByMask(flow_direction, mask) + flow_direction_clip.save(os.path.join(self.data['outdir'], "flow_clip")) - flow_direction_clip = ExtractByMask(flow_direction, maska) - flow_direction_clip.save(self.data['outdir'] + os.sep + "flowDir") - - return flow_direction_clip, slope_clip, dmt_clip + return dmt_clip, slope_clip, flow_direction_clip def _clip_points(self, intersect): """ - - :param intersect: + :param intersect: vector intersect feature class """ - tmpPoints = [] - desc = arcpy.Describe(self.data['points']) - shapefieldname = desc.ShapeFieldName - rows_p = arcpy.SearchCursor(self.data['points']) - for row in rows_p: - feat = row.getValue(shapefieldname) - pnt = feat.getPart() - tmpPoints.append([pnt.X, pnt.Y]) - del rows_p - - pointsClipCheck = self.data['outdir'] + os.sep + "pointsCheck.shp" - arcpy.Clip_analysis(self.data['points'], intersect, pointsClipCheck) - - tmpPointsCheck = [] - descCheck = arcpy.Describe(pointsClipCheck) - shapefieldnameCheck = descCheck.ShapeFieldName - rows_pch = arcpy.SearchCursor(pointsClipCheck) - for row2 in rows_pch: - featCheck = row2.getValue(shapefieldnameCheck) - pntChech = featCheck.getPart() - tmpPointsCheck.append([pntChech.X, pntChech.Y]) - del rows_pch - - diffpts = [c for c in tmpPoints if c not in tmpPointsCheck] - if len(diffpts) == 0: - pass - else: - self._add_message("!!! Points at coordinates [x,y]:") - for item in diffpts: - self._add_message(item) - self._add_message("are outside the computation domain and will be ignored !!!") + # clip vector points based on intersect + pointsClipCheck = os.path.join( + self.data['outdir'], "pointsCheck.shp") + arcpy.Clip_analysis( + self.data['points'], intersect, pointsClipCheck + ) + + # count number of features (rows) + npoints = arcpy.GetCount_management(self._input_params['points']) + npoints_clipped = arcpy.GetCount_management(pointsClipCheck) + + diffpts = npoints - npoints_clipped + if len(diffpts) > 0: + Logger.warning( + "{} points outside of computation domain will be ignored".format(len(diffpts)) + ) self.data['points'] = pointsClipCheck @@ -700,7 +673,7 @@ def _add_field(self, input, newfield, datatype, default_value): # EDL arcpy.CalculateField_management(input, newfield, default_value, "PYTHON") return input - def _join_table(self, in_data, in_field, join_table, join_field, fields = None): + def _join_table(self, in_data, in_field, join_table, join_field, fields=None): """ :param in_data: @@ -711,9 +684,11 @@ def _join_table(self, in_data, in_field, join_table, join_field, fields = None): :return: """ if fields == None: - arcpy.JoinField_management(in_data, in_field, join_table, join_field) + arcpy.JoinField_management( + in_data, in_field, join_table, join_field) else: - arcpy.JoinField_management(in_data, in_field, join_table, join_field, fields) + arcpy.JoinField_management( + in_data, in_field, join_table, join_field, fields) def _save_raster(self, name, array_export, folder): """ diff --git a/smoderp2d/providers/base/data_preparation.py b/smoderp2d/providers/base/data_preparation.py index aff39ba..1753d1f 100644 --- a/smoderp2d/providers/base/data_preparation.py +++ b/smoderp2d/providers/base/data_preparation.py @@ -1,44 +1,41 @@ class PrepareDataBase(object): + def __init__(self): + self._input_params = {} + def run(self): Logger.info("DATA PREPARATION") Logger.info("----------------") - self._create_dict() - - # get input parameters from GRASS UI - # TODO: TBD + # get input parameters + self._get_input_params() - # set dict parameters from input data (fixed) - # TODO: code duplication - self.data['maxdt'] = maxdt - self.data['end_time'] = end_time - self.data['outdir'] = output - self.data['points'] = points + # set output data directory + self._set_output_data() # create output folder, where temporary data are stored - # TODO: code duplication - self._add_message("Creating output...") self._set_output() - self._set_mask() # TODO + dmt_copy, dmt_mask = self._set_mask() + # DMT computation Logger.info( "Computing fill, flow direction, flow accumulation, slope..." ) - dmt_fill, flow_direction, flow_accumulation, slope_orig = \ - dmtfce(dmt_copy, self.data['temp'], "NONE") # TODO + dmt_fill, flow_direction, flow_accumulation, slope = \ + self._dmtfce(dmt_copy) # intersect Logger.info("Computing intersect of input data...") intersect, null_shp, sfield = self._get_intersect( - gp, dmt_copy, veg_indata, soil_indata, vtyp, ptyp, - tab_puda_veg, tab_puda_veg_code + dmt_copy, + self._input_params['veg_indata'], self._input_params['soil_indata'], + self._input_params['vtype'], self._input_params['ptype'], + self._input_params['tab_puda_veg'], self._input_params['tab_puda_veg_code'] ) # clip Logger.info("Clip of the source data by intersect...") - flow_direction_clip, slope_clip, dmt_clip = self._clip_data( - dmt_copy, intersect, slope_orig, flow_direction - ) + dmt_clip, slope_clip, flow_direction_clip = self._clip_data( + dmt_copy, intersect, slope, flow_direction) Logger.info("Computing parameters of DMT...") # raster to numpy array conversion @@ -88,7 +85,7 @@ def run(self): return self.data - def _create_dict(self): + def _set_output_data(self): """ Creates dictionary to which model parameters are computed. """ @@ -107,7 +104,7 @@ def _create_dict(self): 'c': None, 'r': None, 'combinatIndex': None, - 'maxdt': None, + 'maxdt': self._input_params['maxdt'], 'mat_pi': None, 'mat_ppl': None, 'surface_retention': None, @@ -123,11 +120,11 @@ def _create_dict(self): 'mat_nan': None, 'mat_a': None, 'mat_n': None, - 'outdir': None, + 'outdir': self._input_params['output'], 'pixel_area': None, - 'points': None, + 'points': self._input_params['points'], # TODO: used outside? 'poradi': None, - 'end_time': None, + 'end_time': self._input_params['end_time'], 'spix': None, 'state_cell': None, 'temp': None, @@ -142,4 +139,37 @@ def _create_dict(self): 'STREAM_RATIO': None, 'toky_loc': None } + + def _set_output(self): + """Creates empty output and temporary directories to which created + files are saved. + """ + # delete output directory if exists and create new one + Logger.info( + "Creating output directory {}".format(self.data['outdir']) + ) + if os.path.exists(self.data['outdir']): + shutil.rmtree(self.data['outdir']) + os.makedirs(self.data['outdir']) + + # create temporary ArcGIS File Geodatabase + Logger.debug( + "Creating temp directory {}".format(self.data['temp']) + ) + self.data['temp'] = os.path.join( + self.data['outdir'], "temp" + ) + os.makedirs(self.data['temp']) + + def set_mask(self): + raise NotImplemented("Not implemented for base provider") + def _dmtfce(self, dmt): + raise NotImplemented("Not implemented for base provider") + + def _get_intersect(self, dmt_copy, veg_indata, soil_indata, + stype, stype, tab_puda_veg, tab_puda_veg_code): + raise NotImplemented("Not implemented for base provider") + + def _get_input_params(self): + raise NotImplemented("Not implemented for base provider") diff --git a/smoderp2d/providers/base/exception.py b/smoderp2d/providers/base/exception.py new file mode 100644 index 0000000..ab77618 --- /dev/null +++ b/smoderp2d/providers/base/exception.py @@ -0,0 +1,8 @@ +class DataPreparationError(Exception): + pass + +class DataPreparationInvalidInput(DataPreparationError): + def __init__(self, msg): + Logger.fatal( + "Invalid input for data preparation: {}".format(msg) + ) diff --git a/smoderp2d/providers/grass/data_preparation.py b/smoderp2d/providers/grass/data_preparation.py index 71da58e..580ba8f 100644 --- a/smoderp2d/providers/grass/data_preparation.py +++ b/smoderp2d/providers/grass/data_preparation.py @@ -12,4 +12,6 @@ def run(self): :return data: dictionary with model parameters. """ - pass + # get input parameters from GRASS UI + # TODO: TBD +