Changeset 4793


Ignore:
Timestamp:
Nov 24, 2020 9:48:21 AM (3 years ago)
Author:
maronga
Message:

allow for overhanging vegetation in palm_csd

Location:
palm/trunk/SCRIPTS
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • palm/trunk/SCRIPTS/.csd.config.default

    r4641 r4793  
    212212vegetation_on_roofs = False
    213213street_trees = True
     214overhanging_trees = False
    214215
    215216[domain_N02]
     
    228229vegetation_on_roofs = False
    229230street_trees = True
     231overhanging_trees = False
  • palm/trunk/SCRIPTS/palm_csd

    r4749 r4793  
    2525# -----------------
    2626# $Id$
     27# Added output of tree_type (species or classification). Added tree_id for
     28# vegetation patches. Allow for overlapping vegetation with buildings
     29#
     30# 4749 2020-10-16 11:21:27Z maronga
    2731# Bugfix: processing of patch height faulty for multiple domains
    2832#
     
    164168   global domain_street_trees
    165169   global domain_canopy_patches
     170   global domain_overhanging_trees
    166171
    167172#  Definition of input data parameters
     
    250255   domain_street_trees = []
    251256   domain_canopy_patches = []
     257   domain_overhanging_trees = []
    252258
    253259   zt_min = 0.0
     
    349355         domain_green_roofs.append(config.getboolean(read_tmp, 'vegetation_on_roofs'))
    350356         domain_street_trees.append(config.getboolean(read_tmp, 'street_trees'))
    351          
     357         domain_overhanging_trees.append(config.getboolean(read_tmp, 'overhanging_trees'))
     358                 
    352359      if ( read_tmp.split("_")[0] == 'input' ):
    353360         input_names.append(read_tmp.split("_")[1])
     
    417424   "vegetation_pars": "f4",
    418425   "tree_data": "f4",
    419    "tree_type": "b",
     426   "tree_id": "i",
     427   "tree_type": "f4",
     428   "tree_types": "b", 
    420429   "nbuilding_pars": "i",
    421430   "nvegetation_pars": "i",
     
    447456   "vegetation_pars": float(-9999.0),
    448457   "tree_data": float(-9999.0),
    449    "tree_type": np.byte(-127)
     458   "tree_id": int(-9999),
     459   "tree_type": float(-9999.0),
     460   "tree_types": np.byte(-127)
    450461   }
    451462
     
    473484   "buildings_pars": float(-9999.0),
    474485   "tree_data": float(-9999.0),
    475    "tree_type": 0,
     486   "tree_type": np.byte(-127),
    476487   "vegetation_pars": float(-9999.0)   
    477488   }
     
    963974      vegetation_pars =  nc_read_from_file_2d_all(filename[i], 'vegetation_pars')
    964975
    965       lai = np.copy(vegetation_pars[1,:,:])
     976      lai = nc_read_from_file_2d(input_file_lai[ii[i]], 'Band1', domain_x0[i], domain_x1[i], domain_y0[i], domain_y1[i])   
    966977
    967978      x = nc_read_from_file_2d_all(filename[i], 'x')
     
    9911002      tree_trunk_diameter = np.where( (tree_trunk_diameter == 0.0) | (tree_trunk_diameter == -1.0) ,fillvalues["tree_data"],tree_trunk_diameter)
    9921003      tree_type = np.where( (tree_type == 0.0) | (tree_type == -1.0) ,fillvalues["tree_data"],tree_type)
    993       patch_height = np.where( patch_height == -1.0 ,fillvalues["tree_data"],patch_height)     
     1004     
     1005#     For vegetation pixel with missing height information (-1), set default patch height   
     1006      patch_height = np.where( patch_height == -1.0 ,settings_patch_height_default,patch_height)     
    9941007
    9951008#     Convert trunk diameter from cm to m
     
    10051018
    10061019#     For zero-height patches, set vegetation_type to short grass and remove these pixels from the patch height array
    1007       vegetation_type = np.where( (patch_height == 0.0) & ( (vegetation_type == 4) | (vegetation_type == 5) | (vegetation_type == 6) |(vegetation_type == 7) | (vegetation_type == 17) | (vegetation_type == 18) ),3,vegetation_type)
    1008       patch_type = np.where( (patch_height == 0.0) & ( (vegetation_type == 4) | (vegetation_type == 5) | (vegetation_type == 6) |(vegetation_type == 7) | (vegetation_type == 17) | (vegetation_type == 18) ),fillvalues["tree_data"],patch_height)   
    1009      
     1020      vegetation_type = np.where( (patch_height == 0.0) & ( (vegetation_type == 4) | (vegetation_type == 5) | (vegetation_type == 6) |(vegetation_type == 7) | (vegetation_type == 17) | (vegetation_type == 18) ),3,vegetation_type)
     1021      patch_height = np.where( (patch_height == 0.0) & ( (vegetation_type == 4) | (vegetation_type == 5) | (vegetation_type == 6) |(vegetation_type == 7) | (vegetation_type == 17) | (vegetation_type == 18) ),fillvalues["tree_data"],patch_height)       
    10101022
    10111023      max_tree_height = max(tree_height.flatten())
     
    10171029      if ( (max_tree_height != fillvalues["tree_data"]) | (max_patch_height != fillvalues["tree_data"]) ):
    10181030
    1019          lad, bad, tree_ids, zlad = generate_single_tree_lad(x,y,domain_dz[i],max_tree_height,max_patch_height,tree_type,tree_height,tree_crown_diameter,tree_trunk_diameter,lai,settings_season,fillvalues["tree_data"])
    1020  
     1031         lad, bad, tree_ids, tree_types, zlad = generate_single_tree_lad(x,y,domain_dz[i],max_tree_height,max_patch_height,tree_type,tree_height,tree_crown_diameter,tree_trunk_diameter,lai,settings_season,fillvalues["tree_data"])
    10211032 
    10221033#        Remove LAD volumes that are inside buildings
    1023          buildings_2d = nc_read_from_file_2d_all(filename[i], 'buildings_2d')
    1024          for k in range(0,len(zlad)-1):
     1034         if not domain_overhanging_trees[i]:
     1035            buildings_2d = nc_read_from_file_2d_all(filename[i], 'buildings_2d')
     1036            for k in range(0,len(zlad)-1):
    10251037 
    1026             lad[k,:,:] = np.where(buildings_2d == fillvalues["buildings_2d"],lad[k,:,:],fillvalues["tree_data"])
    1027             bad[k,:,:] = np.where(buildings_2d == fillvalues["buildings_2d"],bad[k,:,:],fillvalues["tree_data"])
    1028             tree_ids[k,:,:] = np.where(buildings_2d == fillvalues["buildings_2d"],tree_ids[k,:,:],fillvalues["tree_data"])     
    1029 
    1030          del buildings_2d
     1038               lad[k,:,:] = np.where(buildings_2d == fillvalues["buildings_2d"],lad[k,:,:],fillvalues["tree_data"])
     1039               bad[k,:,:] = np.where(buildings_2d == fillvalues["buildings_2d"],bad[k,:,:],fillvalues["tree_data"])
     1040               tree_ids[k,:,:] = np.where(buildings_2d == fillvalues["buildings_2d"],tree_ids[k,:,:],fillvalues["tree_id"])     
     1041
     1042            del buildings_2d
    10311043 
     1044 
    10321045         nc_write_dimension(filename[i], 'zlad', zlad, datatypes["tree_data"])
     1046
    10331047         nc_write_to_file_3d(filename[i], 'lad', lad, datatypes["tree_data"],'zlad','y','x',fillvalues["tree_data"])
    10341048         nc_write_attribute(filename[i], 'lad', 'long_name', 'leaf area density')
     
    10371051         nc_write_attribute(filename[i], 'lad', 'coordinates', 'E_UTM N_UTM lon lat')
    10381052         nc_write_attribute(filename[i], 'lad', 'grid_mapping', 'E_UTM N_UTM lon lat')
    1039   
     1053 
    10401054         nc_write_to_file_3d(filename[i], 'bad', bad, datatypes["tree_data"],'zlad','y','x',fillvalues["tree_data"])
    10411055         nc_write_attribute(filename[i], 'bad', 'long_name', 'basal area density')
     
    10451059         nc_write_attribute(filename[i], 'bad', 'grid_mapping', 'E_UTM N_UTM lon lat')
    10461060           
    1047          nc_write_to_file_3d(filename[i], 'tree_id', tree_ids, datatypes["tree_data"],'zlad','y','x',fillvalues["tree_data"])
     1061         nc_write_to_file_3d(filename[i], 'tree_id', tree_ids, datatypes["tree_id"],'zlad','y','x',fillvalues["tree_id"])
    10481062         nc_write_attribute(filename[i], 'tree_id', 'long_name', 'tree id')
    10491063         nc_write_attribute(filename[i], 'tree_id', 'units', '')
     
    10511065         nc_write_attribute(filename[i], 'tree_id', 'coordinates', 'E_UTM N_UTM lon lat')
    10521066         nc_write_attribute(filename[i], 'tree_id', 'grid_mapping', 'E_UTM N_UTM lon lat')           
     1067
     1068         nc_write_to_file_3d(filename[i], 'tree_type', tree_types, datatypes["tree_types"],'zlad','y','x',fillvalues["tree_types"])
     1069         nc_write_attribute(filename[i], 'tree_type', 'long_name', 'tree type')
     1070         nc_write_attribute(filename[i], 'tree_type', 'units', '')
     1071         nc_write_attribute(filename[i], 'tree_type', 'res_orig', domain_px[i]) 
     1072         nc_write_attribute(filename[i], 'tree_type', 'coordinates', 'E_UTM N_UTM lon lat')
     1073         nc_write_attribute(filename[i], 'tree_type', 'grid_mapping', 'E_UTM N_UTM lon lat')   
    10531074           
    1054          del lai, lad, bad, tree_ids, zlad
    1055 
     1075         del lai, lad, bad, tree_ids, tree_types, zlad
     1076
     1077      else:
     1078         print('No street trees generated in domain ' + str(i))
     1079         
    10561080      del vegetation_pars, tree_height, tree_crown_diameter, tree_trunk_diameter, tree_type, patch_height, x, y
    10571081
     
    10611085   if domain_canopy_patches[i]:
    10621086
    1063 #     Load vegetation_type and lad array (at level z = 0) for re-processing
    1064       vegetation_type = nc_read_from_file_2d_all(filename[i], 'vegetation_type')
    1065       lad = nc_read_from_file_3d_all(filename[i], 'lad')
    1066       zlad = nc_read_from_file_1d_all(filename[i], 'zlad')
    10671087      patch_height = nc_read_from_file_2d(input_file_patch_height[ii[i]], 'Band1', domain_x0[i], domain_x1[i], domain_y0[i], domain_y1[i])
    1068       vegetation_pars = nc_read_from_file_3d_all(filename[i], 'vegetation_pars')
    1069       lai = vegetation_pars[1,:,:]
    1070      
    1071 
    1072 #     Determine all pixels that do not already have an LAD but which are high vegetation to a dummy value of 1.0 and remove all other pixels
    1073       lai_high = np.where( (lad[0,:,:] == fillvalues["tree_data"]) & ( ( (vegetation_type == 4) | (vegetation_type == 5) | (vegetation_type == 6) |(vegetation_type == 7) | (vegetation_type == 17) | (vegetation_type == 18) ) & ( (patch_height == fillvalues["tree_data"]) | (patch_height >= domain_dz[i])) ),1.0,fillvalues["tree_data"])
    1074 
    1075 
    1076 #     Treat all pixels where short grass is defined, but where a patch_height >= dz is found, as high vegetation (often the case in backyards)
    1077       lai_high = np.where( (lai_high == fillvalues["tree_data"]) & (patch_height >= domain_dz[i]) & (vegetation_type == 3), 1.0, lai_high)
     1088
     1089#     For vegetation pixel with missing height information (-1), set default patch height     
     1090      patch_height = np.where( patch_height == -1.0 ,settings_patch_height_default,patch_height)
     1091     
     1092      max_patch_height = max(patch_height.flatten())
     1093      if ( max_patch_height != fillvalues["tree_data"] ):
     1094#        Call canopy generator for single trees only if there is any tree height available in the domain.
     1095#        This does not guarantee that there are street trees that can be processed. This is checked in the
     1096#        canopy generator.
     1097
     1098#        Load vegetation_type and lad array (at level z = 0) for re-processing
     1099         vegetation_type = nc_read_from_file_2d_all(filename[i], 'vegetation_type')
     1100         lad = nc_read_from_file_3d_all(filename[i], 'lad')
     1101         tree_id = nc_read_from_file_3d_all(filename[i], 'tree_id')
     1102         tree_types = nc_read_from_file_3d_all(filename[i], 'tree_type')
     1103         zlad = nc_read_from_file_1d_all(filename[i], 'zlad')
     1104         vegetation_pars = nc_read_from_file_3d_all(filename[i], 'vegetation_pars')
     1105         lai = nc_read_from_file_2d(input_file_lai[ii[i]], 'Band1', domain_x0[i], domain_x1[i], domain_y0[i], domain_y1[i])   
     1106   
     1107         nc_write_to_file_2d(filename[i], 'patch_height', patch_height, datatypes["tree_data"],'y','x',fillvalues["tree_data"])
     1108         nc_write_attribute(filename[i], 'patch_height', 'long_name', 'tree type')
     1109         nc_write_attribute(filename[i], 'patch_height', 'units', '')
     1110         nc_write_attribute(filename[i], 'patch_height', 'res_orig', domain_px[i]) 
     1111         nc_write_attribute(filename[i], 'patch_height', 'coordinates', 'E_UTM N_UTM lon lat')
     1112         nc_write_attribute(filename[i], 'patch_height', 'grid_mapping', 'E_UTM N_UTM lon lat')     
     1113
     1114#        Determine all pixels that do not already have an LAD but which are high vegetation to a dummy value of 1.0 and remove all other pixels
     1115         lai_high = np.where( (lad[0,:,:] == fillvalues["tree_data"]) & ( ( (vegetation_type == 4) | (vegetation_type == 5) | (vegetation_type == 6) |(vegetation_type == 7) | (vegetation_type == 17) | (vegetation_type == 18) ) & ( (patch_height == fillvalues["tree_data"]) | (patch_height >= domain_dz[i])) ),1.0,fillvalues["tree_data"])
     1116
     1117
     1118#        Treat all pixels where short grass is defined, but where a patch_height >= dz is found, as high vegetation (often the case in backyards)
     1119         lai_high = np.where( (lai_high == fillvalues["tree_data"]) & (patch_height >= domain_dz[i]) & (vegetation_type == 3), 1.0, lai_high)
    10781120                         
    1079 #     Now, assign either the default LAI for high vegetation or keep 1.0 from the lai_high array.
    1080       lai_high = np.where( (lai_high != fillvalues["tree_data"]) & (lai == fillvalues["tree_data"]), settings_lai_high_default, lai_high)
    1081 
    1082 #     If LAI values are available in the LAI array, write them on the lai_high array
    1083       lai_high = np.where( (lai_high != fillvalues["tree_data"]) & (lai != fillvalues["tree_data"]), lai, lai_high)
    1084 
    1085 
    1086 #     Define a patch height wherever it is missing, but where a high vegetation LAI was set
    1087       patch_height = np.where ( (lai_high != fillvalues["tree_data"]) & (patch_height == fillvalues["tree_data"]), settings_patch_height_default, patch_height)
    1088 
    1089 
    1090 #     Remove pixels where street trees were already set
    1091       patch_height = np.where ( (lad[0,:,:] != fillvalues["tree_data"]), fillvalues["tree_data"], patch_height)
    1092 
    1093 #     Remove patch heights that have no lai_high value
    1094       patch_height = np.where ( (lai_high == fillvalues["tree_data"]), fillvalues["tree_data"], patch_height)
    1095 
    1096 #     For missing LAI values, set either the high vegetation default or the low vegetation default   
    1097       lai_high = np.where( (patch_height > 2.0) & (patch_height != fillvalues["tree_data"]) & (lai_high == fillvalues["tree_data"]),settings_lai_high_default,lai_high)
    1098       lai_high = np.where( (patch_height <= 2.0) & (patch_height != fillvalues["tree_data"]) & (lai_high == fillvalues["tree_data"]),settings_lai_low_default,lai_high)
     1121#        If overhanging trees are allowed, assign pixels with patch_height > dz that are not included in vegetation_type to high
     1122         if domain_overhanging_trees[i]:
     1123            lai_high = np.where( (lai_high == fillvalues["tree_data"]) & (patch_height >= domain_dz[i]), 1.0, lai_high)
     1124
     1125#        Now, assign either the default LAI for high vegetation or keep 1.0 from the lai_high array.
     1126         lai_high = np.where( (lai_high != fillvalues["tree_data"]) & (lai == fillvalues["tree_data"]), settings_lai_high_default, lai_high)
     1127
     1128#        If LAI values are available in the LAI array, write them on the lai_high array
     1129         lai_high = np.where( (lai_high != fillvalues["tree_data"]) & (lai != fillvalues["tree_data"]), lai, lai_high)
     1130
     1131
     1132#        Define a patch height wherever it is missing, but where a high vegetation LAI was set
     1133         patch_height = np.where ( (lai_high != fillvalues["tree_data"]) & (patch_height == fillvalues["tree_data"]), settings_patch_height_default, patch_height)
     1134
     1135
     1136#        Remove pixels where street trees were already se
     1137         patch_height = np.where ( (lad[0,:,:] != fillvalues["tree_data"]), fillvalues["tree_data"], patch_height)
     1138
     1139#        Remove patch heights that have no lai_high value
     1140         patch_height = np.where ( (lai_high == fillvalues["tree_data"]), fillvalues["tree_data"], patch_height)
     1141
     1142
     1143
     1144
     1145#        For missing LAI values, set either the high vegetation default or the low vegetation default   
     1146         lai_high = np.where( (patch_height > 2.0) & (patch_height != fillvalues["tree_data"]) & (lai_high == fillvalues["tree_data"]),settings_lai_high_default,lai_high)
     1147         lai_high = np.where( (patch_height <= 2.0) & (patch_height != fillvalues["tree_data"]) & (lai_high == fillvalues["tree_data"]),settings_lai_low_default,lai_high)
    10991148         
    1100       if ( max(patch_height.flatten()) >= (2.0 * domain_dz[i]) ):
    1101          print("    start calculating LAD (this might take some time)")       
     1149         if ( max(patch_height.flatten()) >= (2.0 * domain_dz[i]) ):
     1150            print("    start calculating LAD (this might take some time)")       
    11021151
    11031152         
    1104          lad_patch, patch_nz, status = process_patch(domain_dz[i],patch_height,max(zlad),lai_high,settings_lai_alpha,settings_lai_beta)
    1105 
    1106 #        2D loop in order to avoid memory problems with large arrays
    1107          for iii in range(0,domain_nx[i]):
    1108             for jj in range(0,domain_ny[i]):           
    1109 
    1110                lad[0:patch_nz+1,jj,iii] = np.where( (lad[0:patch_nz+1,jj,iii] == fillvalues["tree_data"]),lad_patch[0:patch_nz+1,jj,iii], lad[0:patch_nz+1,jj,iii] )
    1111 
    1112 #     Remove high vegetation wherever it is replaced by a leaf area density. This should effectively remove all high vegetation pixels
    1113       vegetation_type = np.where((lad[0,:,:] != fillvalues["tree_data"]) & (vegetation_type != fillvalues["vegetation_type"]),settings_veg_type_below_trees,vegetation_type)
     1153            lad_patch, patch_id, patch_types, patch_nz, status = process_patch(domain_dz[i],patch_height,vegetation_type,max(zlad),lai_high,settings_lai_alpha,settings_lai_beta)
     1154
     1155#           Increase the patch ids by the maximum id for street trees to avoid double ids
     1156            max_id = max(tree_id.flatten())
     1157            patch_id = np.where( patch_id != fillvalues["tree_id"], patch_id+max_id, patch_id)
     1158
     1159#           2D loop in order to avoid memory problems with large arrays
     1160            for iii in range(0,domain_nx[i]):
     1161               for jj in range(0,domain_ny[i]):           
     1162
     1163                  tree_id[0:patch_nz+1,jj,iii] = np.where( (lad[0:patch_nz+1,jj,iii] == fillvalues["tree_data"]),patch_id[0:patch_nz+1,jj,iii], tree_id[0:patch_nz+1,jj,iii] )
     1164                  tree_types[0:patch_nz+1,jj,iii] = np.where( (lad[0:patch_nz+1,jj,iii] == fillvalues["tree_data"]),patch_types[0:patch_nz+1,jj,iii], tree_types[0:patch_nz+1,jj,iii] )                 
     1165                  lad[0:patch_nz+1,jj,iii]     = np.where( (lad[0:patch_nz+1,jj,iii] == fillvalues["tree_data"]),lad_patch[0:patch_nz+1,jj,iii], lad[0:patch_nz+1,jj,iii] )
     1166
     1167#        Remove high vegetation wherever it is replaced by a leaf area density. This should effectively remove all high vegetation pixels
     1168         vegetation_type = np.where((lad[0,:,:] != fillvalues["tree_data"]) & (vegetation_type != fillvalues["vegetation_type"]),settings_veg_type_below_trees,vegetation_type)
    11141169             
    1115 #     If desired, remove all high vegetation. TODO: check if this is still necessary
    1116       if not domain_high_vegetation[i]:
    1117          vegetation_type = np.where((vegetation_type != fillvalues["vegetation_type"]) & ( (vegetation_type == 4) | (vegetation_type == 5) | (vegetation_type == 6) |(vegetation_type == 7) | (vegetation_type == 17) | (vegetation_type == 18) ),3,vegetation_type)   
     1170#        If desired, remove all high vegetation. TODO: check if this is still necessary
     1171         if not domain_high_vegetation[i]:
     1172            vegetation_type = np.where((vegetation_type != fillvalues["vegetation_type"]) & ( (vegetation_type == 4) | (vegetation_type == 5) | (vegetation_type == 6) |(vegetation_type == 7) | (vegetation_type == 17) | (vegetation_type == 18) ),3,vegetation_type)   
    11181173
    11191174 
    1120 #     Set default low LAI for pixels with an LAD (short grass below trees)
    1121       lai_low = np.where( (lad[0,:,:] == fillvalues["tree_data"]), lai, settings_lai_low_default)
     1175#        Set default low LAI for pixels with an LAD (short grass below trees)
     1176         lai_low = np.where( (lad[0,:,:] == fillvalues["tree_data"]), lai, settings_lai_low_default)
    11221177   
    1123 #     Fill low vegetation pixels without LAI set or with LAI = 0 with default value
    1124       lai_low = np.where( ( (lai_low == fillvalues["tree_data"]) | (lai_low == 0.0) ) & (vegetation_type != fillvalues["vegetation_type"] ), settings_lai_low_default, lai_low)
    1125 
    1126 #     Remove lai for pixels that have no vegetation_type
    1127       lai_low = np.where( ( (vegetation_type != fillvalues["vegetation_type"]) & (vegetation_type != 1) ), lai_low, fillvalues["tree_data"])
     1178#        Fill low vegetation pixels without LAI set or with LAI = 0 with default value
     1179         lai_low = np.where( ( (lai_low == fillvalues["tree_data"]) | (lai_low == 0.0) ) & (vegetation_type != fillvalues["vegetation_type"] ), settings_lai_low_default, lai_low)
     1180
     1181#        Remove lai for pixels that have no vegetation_type
     1182         lai_low = np.where( ( (vegetation_type != fillvalues["vegetation_type"]) & (vegetation_type != 1) ), lai_low, fillvalues["tree_data"])
    11281183       
    1129 #     Overwrite lai in vegetation_parameters 
    1130       vegetation_pars[1,:,:] = np.copy(lai_low)
    1131       nc_overwrite_to_file_3d(filename[i], 'vegetation_pars', vegetation_pars)
    1132 
    1133 #     Overwrite lad array
    1134       nc_overwrite_to_file_3d(filename[i], 'lad', lad)
    1135            
    1136       nc_overwrite_to_file_2d(filename[i], 'vegetation_type', vegetation_type) 
    1137 
    1138      
    1139       del vegetation_type, lad, lai, patch_height, vegetation_pars, zlad
    1140 
     1184#        Overwrite lai in vegetation_parameters 
     1185         vegetation_pars[1,:,:] = np.copy(lai_low)
     1186         nc_overwrite_to_file_3d(filename[i], 'vegetation_pars', vegetation_pars)
     1187
     1188#        Overwrite lad and id arrays
     1189         nc_overwrite_to_file_3d(filename[i], 'lad', lad)
     1190         nc_overwrite_to_file_3d(filename[i], 'tree_id', tree_id)
     1191         nc_overwrite_to_file_3d(filename[i], 'tree_type', tree_types)
     1192
     1193         nc_overwrite_to_file_2d(filename[i], 'vegetation_type', vegetation_type) 
     1194
     1195
     1196         del vegetation_type, lad, lai, patch_height, vegetation_pars, zlad
     1197      else:
     1198         print('No tree patches found in domain ' + str(i))
    11411199
    11421200# Final adjustment of vegetation parameters: remove LAI where a bare soil was set
  • palm/trunk/SCRIPTS/palm_csd_files/palm_csd_canopy_generator.py

    r4481 r4793  
    2020# Current revisions:
    2121# -----------------
    22 # 
    23 # 
     22#
     23#
    2424# Former revisions:
    2525# -----------------
    2626# $Id: palm_csd_canopy_generator.py 3773 2019-03-01 08:56:57Z maronga $
     27# Bugfix: do not allow BAD < 0, revised treatment of tree trunks
     28#
     29# 3773 2019-03-01 08:56:57Z maronga
    2730# Added support for tree shape
    2831#
     
    4649import math
    4750import scipy.integrate as integrate
     51import scipy.ndimage as nd
    4852
    4953def generate_single_tree_lad(x,y,dz,max_tree_height,max_patch_height,tree_type,tree_height,tree_dia,trunk_dia,tree_lai,season,fill):
     
    6468   ids = np.ones((len(zlad),len(y),len(x)))
    6569   ids[:,:,:] = fill
    66    
     70 
     71   types = np.ones((len(zlad),len(y),len(x)))
     72   types[:,:,:] = np.byte(-127) 
    6773
    6874#  Calculating the number of trees in the arrays and a boolean array storing the location of trees which is used for convenience in the following loop environment   
     
    107113                  bad[0:lad_loc_nz,ind_l_y:ind_r_y+1,ind_l_x:ind_r_x+1] = np.where(bad_loc[0:lad_loc_nz,out_l_y:out_r_y+1,out_l_x:out_r_x+1] != fill,bad_loc[0:lad_loc_nz,out_l_y:out_r_y+1,out_l_x:out_r_x+1],bad[0:lad_loc_nz,ind_l_y:ind_r_y+1,ind_l_x:ind_r_x+1])
    108114                  ids[0:lad_loc_nz,ind_l_y:ind_r_y+1,ind_l_x:ind_r_x+1] = np.where(lad_loc[0:lad_loc_nz,out_l_y:out_r_y+1,out_l_x:out_r_x+1] != fill,tree_id_counter,ids[0:lad_loc_nz,ind_l_y:ind_r_y+1,ind_l_x:ind_r_x+1])
     115                  types[0:lad_loc_nz,ind_l_y:ind_r_y+1,ind_l_x:ind_r_x+1] = np.where(lad_loc[0:lad_loc_nz,out_l_y:out_r_y+1,out_l_x:out_r_x+1] != fill,np.byte(tree_type[j,i]),types[0:lad_loc_nz,ind_l_y:ind_r_y+1,ind_l_x:ind_r_x+1])                   
    109116
    110117
     
    116123
    117124               del lad_loc, x_loc, y_loc, z_loc, status
    118    return lad, bad, ids, zlad
     125   return lad, bad, ids, types, zlad
    119126
    120127
     
    230237   fillvalues = {
    231238   "tree_data": float(-9999.0),
     239   "tree_type": np.byte(-127)
    232240   }
    233241   
    234242   
    235243#  Check for missing data in the input and set default values if needed
    236    if ( tree_type == fillvalues["tree_data"] ):
     244   if ( tree_type == fillvalues["tree_type"] ):
    237245      tree_type = int(0)
    238246   else:
     
    295303   nx = int(tree_dia / dx) + 2
    296304   nz = int(tree_height / dz) + 2
    297    
     305   
     306
     307 
    298308#  Add one grid point if diameter is an odd value   
    299309   if ( (tree_dia % 2.0) != 0.0 ):
    300310      nx = nx + 1
    301 
    302311
    303312#  Create local domain of the tree's LAD
     
    459468
    460469#  Create BAD array and populate. TODO: revise as low LAD inside the foliage does not result in low BAD values.
    461    bad_loc = np.where(lad_loc != fillvalues["tree_data"],(1.0 - lad_loc)*0.1,lad_loc)
     470   bad_loc = np.where(lad_loc != fillvalues["tree_data"],(1.0 - (lad_loc/(max(lad_loc.flatten())+0.01)))*0.1,lad_loc)
    462471   
    463472
     
    469478            if ( z[k] <= crown_center ):
    470479               r_test = np.sqrt( (x[i] - tree_location_x)**(2) + (y[j] - tree_location_y)**(2)  )
    471                if ( r_test <= radius ):
    472                   bad_loc[k,j,i] = 1.0
    473                if ( (r_test == 0.0) & (trunk_dia <= dx) ):
    474                    bad_loc[k,j,i] = radius**(2) * 3.14159265359
     480               if ( r_test == 0.0 ):
     481                  if ( trunk_dia <= dx ):
     482                     bad_loc[k,j,i] = radius**2 * 3.14159265359
     483                  else:
     484                     # WORKAROUND: divide remaining circle area over the 8 surrounding valid_pixels
     485                     bad_loc[k,j-1:j+2,i-1:i+2] = radius**2 * 3.14159265359 / 8.0
     486                     # for the central pixel fill the pixel
     487                     bad_loc[k,j,i] = dx**2
     488               #elif ( r_test <= radius ):
     489                  # TODO: calculate circle segment of grid points cut by the grid
     490 
    475491
    476492   return lad_loc, bad_loc, x, y, z, 0
    477493
    478494
    479 def process_patch(dz,patch_height,max_height_lad,patch_lai,alpha,beta):
     495def process_patch(dz,patch_height,vegetation_type,max_height_lad,patch_lai,alpha,beta):
    480496   
    481497#  Define fill values
    482498   fillvalues = {
    483499   "tree_data": float(-9999.0),
    484    "pch_index": int(-9999),
     500   "tree_id":   int(-9999),   
     501   "tree_type": np.byte(-127), 
     502   "pch_index": int(-9999)
    485503   }
    486504
     505   
    487506   phdz = patch_height[:,:] / dz
    488507   pch_index = np.where( (patch_height[:,:] != fillvalues["tree_data"]),phdz.astype(int)+1,int(-1))   
     
    520539                lad_loc[k,j,i] = 0.5 * ( pre_lad[k-1] + pre_lad[k] )
    521540
    522    return lad_loc, nz, 0
     541
     542   patch_id_2d = np.where(lad_loc[0,:,:] != fillvalues["tree_data"], 1, 0)
     543   patch_id = np.where(lad_loc != fillvalues["tree_data"], 1, 0)
     544   patch_type = np.where(lad_loc != fillvalues["tree_data"], np.byte(1), np.byte(-127))
     545
     546   num_ids = nd.label(patch_id_2d, output=patch_id_2d)
     547 
     548   for k in range(0,nz):
     549   
     550      vegetation_type_int = vegetation_type.astype(int)
     551      patch_id[k,:,:]   = np.where((patch_id_2d != 0) & (lad_loc[k,:,:] != fillvalues["tree_data"]), patch_id_2d, fillvalues["tree_id"])
     552      patch_type[k,:,:] = np.where((patch_id_2d != 0) & (lad_loc[k,:,:] != fillvalues["tree_data"]), np.byte(100+vegetation_type), fillvalues["tree_type"])
     553
     554   return lad_loc, patch_id, patch_type, nz, 0
    523555
    524556
     
    559591       self.bad_scale = bad_scale
    560592       self.dbh = dbh   
     593   
Note: See TracChangeset for help on using the changeset viewer.