source: palm/trunk/SCRIPTS/palm_csd @ 3651

Last change on this file since 3651 was 3629, checked in by maronga, 6 years ago

palm_csd improvements

  • Property svn:executable set to *
  • Property svn:keywords set to Id
File size: 51.4 KB
Line 
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3#--------------------------------------------------------------------------------#
4# This file is part of the PALM model system.
5#
6# PALM is free software: you can redistribute it and/or modify it under the terms
7# of the GNU General Public License as published by the Free Software Foundation,
8# either version 3 of the License, or (at your option) any later version.
9#
10# PALM is distributed in the hope that it will be useful, but WITHOUT ANY
11# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License along with
15# PALM. If not, see <http://www.gnu.org/licenses/>.
16#
17# Copyright 1997-2018  Leibniz Universitaet Hannover
18#--------------------------------------------------------------------------------#
19#
20# Current revisions:
21# -----------------
22#
23#
24# Former revisions:
25# -----------------
26# $Id: palm_csd 3629 2018-12-13 12:18:54Z suehring $
27# Added canopy generator calls. Some improvements
28#
29# 3567 2018-11-27 13:59:21Z maronga
30# Initial revisions
31#
32# Description:
33# ------------
34# Processing tool for creating PIDS conform static drivers from rastered NetCDF
35# input
36#
37# @Author Bjoern Maronga (maronga@muk.uni-hannover.de)
38#
39# @todo Make input files optional
40# @todo Allow for ASCII input of terrain height and building height
41# @todo Modularize reading config file
42#------------------------------------------------------------------------------#
43
44from palm_csd_files.palm_csd_netcdf_interface import *
45from palm_csd_files.palm_csd_tools import *
46from palm_csd_files.palm_csd_canopy_generator import *
47import numpy as np
48
49   
50def read_config_file():
51   
52   import configparser
53   from math import floor
54   import numpy as np
55   import os
56   import subprocess as sub
57   import sys
58
59#  Check if configuration files exists and quit otherwise
60   input_config = ".csd.config"
61   for i in range(1,len(sys.argv)): 
62      input_config = str(sys.argv[i])
63       
64   config = configparser.RawConfigParser(allow_no_value=True)
65
66   if ( os.path.isfile(input_config) == False ):
67      print ("Error. No configuration file " + input_config + " found.")
68      raise SystemExit   
69
70   config.read(input_config)
71
72
73#  Definition of settings
74   global settings_filename_out
75   global settings_bridge_width
76   global settings_lai_roof_intensive
77   global settings_lai_roof_extensive
78   global settings_season
79   global settings_lai_low_default
80   global settings_lai_high_default
81   global settings_patch_height_default
82   global settings_lai_alpha
83   global settings_lai_beta
84   global ndomains
85
86#  Definition of global configuration parameters
87   global global_acronym
88   global global_angle
89   global global_author
90   global global_campaign
91   global global_comment
92   global global_contact
93   global global_data_content 
94   global global_dependencies
95   global global_institution
96   global global_keywords
97   global global_location
98   global global_palm_version
99   global global_references
100   global global_site
101   global global_source
102   global global_version
103
104
105#  Definition of domain parameters
106   global domain_names
107   global domain_px
108   global domain_x0
109   global domain_y0
110   global domain_x1
111   global domain_y1
112   global domain_nx
113   global domain_ny
114   global domain_dz
115   global domain_3d
116   global domain_high_vegetation
117   global domain_ip
118   global domain_za
119   global domain_parent
120   global domain_green_roofs
121   global domain_street_trees
122   global domain_canopy_patches
123
124#  Definition of input data parameters
125   global input_names
126   global input_px
127 
128       
129   global input_file_x
130   global input_file_y
131   global input_file_x_UTM
132   global input_file_y_UTM   
133   global input_file_lat
134   global input_file_lon 
135   global input_file_zt
136   global input_file_buildings_2d
137   global input_file_bridges_2d
138   global input_file_building_id
139   global input_file_bridges_id   
140   global input_file_building_type
141   global input_file_building_type
142   global input_file_lai 
143   global input_file_vegetation_type
144   global input_file_vegetation_height
145   global input_file_pavement_type
146   global input_file_water_type
147   global input_file_street_type
148   global input_file_street_crossings
149   global input_file_soil_type
150   global input_file_vegetation_on_roofs
151   global input_file_tree_crown_diameter
152   global input_file_tree_height
153   global input_file_tree_trunk_diameter
154   global input_file_tree_type
155   global input_file_patch_height
156
157   global zt_all
158   global zt_min
159
160   settings_filename_out = "default"
161   settings_bridge_width = 3.0
162   settings_lai_roof_intensive = 0.5
163   settings_lai_roof_extensive = 1.0
164   settings_season = "summer"
165   settings_lai_high_default = 6.0
166   settings_lai_low_default = 1.0
167   settings_patch_height_default = 10.0
168   settings_lai_alpha = 5.0
169   settings_lai_beta = 3.0
170   ndomains = 0
171
172   global_acronym = ""
173   global_angle = ""
174   global_author = ""
175   global_campaign = ""
176   global_comment = ""
177   global_contact = ""
178   global_data_content = ""
179   global_dependencies = ""
180   global_institution = ""
181   global_keywords = ""
182   global_location = ""
183   global_palm_version = 6.0
184   global_references = ""
185   global_site = ""
186   global_source = ""
187   global_version = 1
188
189   domain_names = []
190   domain_px = []
191   domain_x0 = []
192   domain_y0 = []
193   domain_x1 = []
194   domain_y1 = []
195   domain_nx = []
196   domain_ny = []
197   domain_dz = []
198   domain_3d = []
199   domain_high_vegetation = []
200   domain_ip = []
201   domain_za = []
202   domain_parent = []
203   domain_green_roofs = []
204   domain_street_trees = []
205   domain_canopy_patches = []
206
207   zt_min = 0.0
208   zt_all = []
209
210   input_names = []
211   input_px = []
212
213   input_file_x = []
214   input_file_y = [] 
215   input_file_x_UTM = []
216   input_file_y_UTM = [] 
217   input_file_lat = []
218   input_file_lon = [] 
219   
220   input_file_zt = []
221   input_file_buildings_2d = []
222   input_file_bridges_2d = []
223   input_file_building_id = []
224   input_file_bridges_id = []   
225   input_file_building_type = []
226   input_file_lai = []
227   input_file_vegetation_type = []
228   input_file_vegetation_height = []   
229   input_file_pavement_type = []
230   input_file_water_type = []
231   input_file_street_type = [] 
232   input_file_street_crossings = []     
233   input_file_soil_type = []
234   input_file_vegetation_on_roofs = []
235   input_file_tree_crown_diameter = []
236   input_file_tree_height = []
237   input_file_tree_trunk_diameter = []
238   input_file_tree_type = []
239   input_file_patch_height = []
240   
241# Load all user parameters from config file
242   for i in range(0,len(config.sections())):
243
244      read_tmp = config.sections()[i]
245     
246      if ( read_tmp == 'global' ):
247         global_acronym = config.get(read_tmp, 'acronym')
248         global_angle = float(config.get(read_tmp, 'rotation_angle'))
249         global_author = config.get(read_tmp, 'author')
250         global_campaign = config.get(read_tmp, 'campaign')
251         global_comment = config.get(read_tmp, 'comment')
252         global_contact = config.get(read_tmp, 'contact_person')
253         global_data_content = config.get(read_tmp, 'data_content')   
254         global_dependencies = config.get(read_tmp, 'dependencies')
255         global_institution = config.get(read_tmp, 'institution')
256         global_keywords = config.get(read_tmp, 'keywords')
257         global_location = config.get(read_tmp, 'location')
258         global_palm_version = float(config.get(read_tmp, 'palm_version'))
259         global_references = config.get(read_tmp, 'references')
260         global_site = config.get(read_tmp, 'site')
261         global_source = config.get(read_tmp, 'source')
262         global_version = float(config.get(read_tmp, 'version'))
263
264      if ( read_tmp == 'settings' ):
265         settings_filename_out = config.get(read_tmp, 'filename_out')
266         settings_lai_roof_intensive = config.get(read_tmp, 'lai_roof_intensive')
267         settings_lai_roof_extensive = config.get(read_tmp, 'lai_roof_extensive') 
268         settings_bridge_width = float(config.get(read_tmp, 'bridge_width'))   
269         settings_season = config.get(read_tmp, 'season')   
270         settings_lai_high_default = float(config.get(read_tmp, 'lai_high_vegetation_default'))
271         settings_lai_low_default = float(config.get(read_tmp, 'lai_low_vegetation_default'))         
272         settings_patch_height_default = float(config.get(read_tmp, 'patch_height_default')) 
273         settings_lai_alpha = float(config.get(read_tmp, 'lai_alpha')) 
274         settings_lai_beta = float(config.get(read_tmp, 'lai_beta')) 
275
276      if ( read_tmp.split("_")[0] == 'domain' ):
277         ndomains = ndomains + 1
278         domain_names.append(read_tmp.split("_")[1])
279         domain_px.append(float(config.get(read_tmp, 'pixel_size')))
280         domain_nx.append(int(config.get(read_tmp, 'nx')))
281         domain_ny.append(int(config.get(read_tmp, 'ny')))
282         domain_dz.append(float(config.get(read_tmp, 'dz')))       
283         domain_3d.append(config.getboolean(read_tmp, 'buildings_3d'))
284         domain_high_vegetation.append(config.getboolean(read_tmp, 'allow_high_vegetation'))
285         domain_canopy_patches.append(config.getboolean(read_tmp, 'generate_vegetation_patches'))       
286         domain_ip.append(config.getboolean(read_tmp, 'interpolate_terrain'))
287         domain_za.append(config.getboolean(read_tmp, 'use_palm_z_axis')) 
288         if domain_ip[ndomains-1] and not domain_za[ndomains-1]:
289            domain_za[ndomains-1] = True
290            print("+++ Overwrite user setting for use_palm_z_axis")
291         
292         domain_parent.append(config.get(read_tmp, 'domain_parent'))
293
294         domain_x0.append(int(floor(float(config.get(read_tmp, 'origin_x'))/float(config.get(read_tmp, 'pixel_size')))))
295         domain_y0.append(int(floor(float(config.get(read_tmp, 'origin_y'))/float(config.get(read_tmp, 'pixel_size')))))       
296         domain_x1.append(int(floor(float(config.get(read_tmp, 'origin_x'))/float(config.get(read_tmp, 'pixel_size'))) + int(config.get(read_tmp, 'nx'))))
297         domain_y1.append(int(floor(float(config.get(read_tmp, 'origin_y'))/float(config.get(read_tmp, 'pixel_size'))) + int(config.get(read_tmp, 'ny'))))
298         domain_green_roofs.append(config.getboolean(read_tmp, 'vegetation_on_roofs')) 
299         domain_street_trees.append(config.getboolean(read_tmp, 'street_trees')) 
300         
301      if ( read_tmp.split("_")[0] == 'input' ):
302         input_names.append(read_tmp.split("_")[1])
303         input_px.append(float(config.get(read_tmp, 'pixel_size')))
304         input_file_x.append(config.get(read_tmp, 'path') + "/" + config.get(read_tmp, 'file_x'))
305         input_file_y.append(config.get(read_tmp, 'path') + "/" + config.get(read_tmp, 'file_y')) 
306         input_file_lat.append(config.get(read_tmp, 'path') + "/" + config.get(read_tmp, 'file_lat'))
307         input_file_lon.append(config.get(read_tmp, 'path') + "/" + config.get(read_tmp, 'file_lon'))   
308         input_file_x_UTM.append(config.get(read_tmp, 'path') + "/" + config.get(read_tmp, 'file_x_UTM'))
309         input_file_y_UTM.append(config.get(read_tmp, 'path') + "/" + config.get(read_tmp, 'file_y_UTM')) 
310         input_file_zt.append(config.get(read_tmp, 'path') + "/" + config.get(read_tmp, 'file_zt'))
311         input_file_buildings_2d.append(config.get(read_tmp, 'path') + "/" + config.get(read_tmp, 'file_buildings_2d'))
312         input_file_bridges_2d.append(config.get(read_tmp, 'path') + "/" + config.get(read_tmp, 'file_bridges_2d'))
313         input_file_building_id.append(config.get(read_tmp, 'path') + "/" + config.get(read_tmp, 'file_building_id')) 
314         input_file_bridges_id.append(config.get(read_tmp, 'path') + "/" + config.get(read_tmp, 'file_bridges_id')) 
315         input_file_building_type.append(config.get(read_tmp, 'path') + "/" + config.get(read_tmp, 'file_building_type'))
316         input_file_lai.append(config.get(read_tmp, 'path') + "/" + config.get(read_tmp, 'file_lai'))         
317         input_file_vegetation_type.append(config.get(read_tmp, 'path') + "/" + config.get(read_tmp, 'file_vegetation_type')) 
318         input_file_vegetation_height.append(config.get(read_tmp, 'path') + "/" + config.get(read_tmp, 'file_vegetation_height'))         
319         input_file_pavement_type.append(config.get(read_tmp, 'path') + "/" + config.get(read_tmp, 'file_pavement_type'))   
320         input_file_water_type.append(config.get(read_tmp, 'path') + "/" + config.get(read_tmp, 'file_water_type'))
321         input_file_street_type.append(config.get(read_tmp, 'path') + "/" + config.get(read_tmp, 'file_street_type'))   
322         input_file_street_crossings.append(config.get(read_tmp, 'path') + "/" + config.get(read_tmp, 'file_street_crossings')) 
323         input_file_patch_height.append(config.get(read_tmp, 'path') + "/" + config.get(read_tmp, 'file_patch_height')) 
324         input_file_tree_crown_diameter.append(config.get(read_tmp, 'path') + "/" + config.get(read_tmp, 'file_tree_crown_diameter')) 
325         input_file_tree_height.append(config.get(read_tmp, 'path') + "/" + config.get(read_tmp, 'file_tree_height')) 
326         input_file_tree_trunk_diameter.append(config.get(read_tmp, 'path') + "/" + config.get(read_tmp, 'file_tree_trunk_diameter')) 
327         input_file_tree_type.append(config.get(read_tmp, 'path') + "/" + config.get(read_tmp, 'file_tree_type')) 
328         input_file_vegetation_on_roofs.append(config.get(read_tmp, 'path') + "/" + config.get(read_tmp, 'file_vegetation_on_roofs'))           
329         #input_file_soil_type.append(config.get(read_tmp, 'path') + "/" + config.get(read_tmp, 'file_soil_type'))   
330   return 0
331
332
333############################################################
334
335# Start of main program
336datatypes = {
337   "x": "f4", 
338   "y": "f4", 
339   "z": "f4", 
340   "lat": "f4", 
341   "lon": "f4",   
342   "E_UTM": "f4", 
343   "N_UTM": "f4", 
344   "zt": "f4",
345   "buildings_2d": "f4",
346   "buildings_3d": "b",
347   "bridges_2d": "f4",
348   "building_id": "i",
349   "bridges_id": "i",
350   "building_type": "b",
351   "nsurface_fraction": "i",
352   "vegetation_type": "b",
353   "vegetation_height": "f4",
354   "pavement_type": "b", 
355   "water_type": "b", 
356   "street_type": "b", 
357   "street_crossings": "b",     
358   "soil_type": "b",
359   "surface_fraction": "f4",
360   "building_pars": "f4",
361   "vegetation_pars": "f4",
362   "tree_data": "f4",
363   "tree_type": "b",
364   "nbuilding_pars": "i",
365   "nvegetation_pars": "i",
366   "zlad": "f4"
367   }
368
369fillvalues = {
370   "lat": float(-9999.0),
371   "lon": float(-9999.0),
372   "E_UTM": float(-9999.0),
373   "N_UTM": float(-9999.0),   
374   "zt": float(-9999.0),
375   "buildings_2d": float(-9999.0),
376   "buildings_3d": np.byte(-127),
377   "bridges_2d": float(-9999.0),
378   "building_id": int(-9999),
379   "bridges_id": int(-9999),
380   "building_type": np.byte(-127),
381   "nsurface_fraction": int(-9999),
382   "vegetation_type": np.byte(-127),
383   "vegetation_height": float(-9999.0),
384   "pavement_type": np.byte(-127),
385   "water_type": np.byte(-127),
386   "street_type": np.byte(-127), 
387   "street_crossings": np.byte(-127),   
388   "soil_type": np.byte(-127),
389   "surface_fraction": float(-9999.0),
390   "building_pars": float(-9999.0),
391   "vegetation_pars": float(-9999.0),
392   "tree_data": float(-9999.0),
393   "tree_type": np.byte(-127)
394   }
395
396defaultvalues = {
397   "lat": float(-9999.0),
398   "lon": float(-9999.0),
399   "E_UTM": float(-9999.0),
400   "N_UTM": float(-9999.0), 
401   "zt": float(0.0),
402   "buildings_2d": float(0.0),
403   "buildings_3d": 0,   
404   "bridges_2d": float(0.0),
405   "building_id": int(0),
406   "bridges_id": int(0),
407   "building_type": 1,
408   "nsurface_fraction": int(-9999),
409   "vegetation_type": 3,
410   "vegetation_height": float(-9999.0),
411   "pavement_type": 1, 
412   "water_type": 1, 
413   "street_type": 1, 
414   "street_crossings": 0,   
415   "soil_type": 1,
416   "surface_fraction": float(0.0),
417   "buildings_pars": float(-9999.0),
418   "tree_data": float(-9999.0),
419   "tree_type": 0,
420   "vegetation_pars": float(-9999.0)   
421   }
422 
423# Read configuration file and set parameters accordingly
424read_config_file()
425
426
427filename = []
428ii = []
429ii_parent = []
430# Define indices and filenames for all domains and create netCDF files
431for i in range(0,ndomains):
432
433#  Calculate indices and input files
434   ii.append(input_px.index(domain_px[i]))
435   filename.append(settings_filename_out + "_" + domain_names[i])
436   if domain_parent[i] is not None:
437      ii_parent.append(domain_names.index(domain_parent[i]))
438   else:
439      ii_parent.append(None)
440
441
442   x_UTM = nc_read_from_file_2d(input_file_x[ii[i]], "Band1", domain_x0[i], domain_x0[i], domain_y0[i], domain_y0[i])
443   y_UTM = nc_read_from_file_2d(input_file_y[ii[i]], "Band1", domain_x0[i], domain_x0[i], domain_y0[i], domain_y0[i])
444   lat = nc_read_from_file_2d(input_file_lat[ii[i]], "Band1", domain_x0[i], domain_x0[i], domain_y0[i], domain_y0[i])
445   lon = nc_read_from_file_2d(input_file_lon[ii[i]], "Band1", domain_x0[i], domain_x0[i], domain_y0[i], domain_y0[i]) 
446   
447#  Create NetCDF output file and set global attributes
448   nc_create_file(filename[i])
449   nc_write_global_attributes(filename[i],float(x_UTM[0,0]),float(y_UTM[0,0]),float(lat[0,0]),float(lon[0,0]),"",global_acronym,global_angle,global_author,global_campaign,global_comment,global_contact,global_data_content,global_dependencies,global_institution,global_keywords,global_location,global_palm_version,global_references,global_site,global_source,global_version)
450
451   
452# Process terrain height
453for i in range(0,ndomains):
454
455#  Read and write terrain height (zt)
456   zt = nc_read_from_file_2d(input_file_zt[ii[i]], 'Band1', domain_x0[i], domain_x1[i], domain_y0[i], domain_y1[i])
457
458#  Final step: add zt array to the global array   
459   zt_all.append(zt)
460   del zt
461 
462#  Calculate the global (all domains) minimum of the terrain height. This value will be substracted for all
463#  data sets
464zt_min = min(zt_all[0].flatten()) 
465for i in range(0,ndomains):
466   zt_min = min(zt_min,min(zt_all[i].flatten()))
467   
468del zt_all[:]
469
470for i in range(0,ndomains):
471
472#  Read and write terrain height (zt)
473   zt = nc_read_from_file_2d(input_file_zt[ii[i]], 'Band1', domain_x0[i], domain_x1[i], domain_y0[i], domain_y1[i])
474   x = nc_read_from_file_1d(input_file_x[ii[i]], "x", domain_x0[i], domain_x1[i])
475   y = nc_read_from_file_1d(input_file_y[ii[i]], "y", domain_y0[i], domain_y1[i])
476
477   print( "Shift terrain height by -" + str(zt_min))
478   zt = zt - zt_min
479
480#  If necessary, interpolate parent domain terrain height on child domain grid and blend the two
481   if domain_ip[i]:
482      tmp_x0 = int( domain_x0[i] * domain_px[i] / domain_px[ii_parent[i]] ) - 1
483      tmp_y0 = int( domain_y0[i] * domain_px[i] / domain_px[ii_parent[i]] ) - 1
484      tmp_x1 = int( domain_x1[i] * domain_px[i] / domain_px[ii_parent[i]] ) + 1
485      tmp_y1 = int( domain_y1[i] * domain_px[i] / domain_px[ii_parent[i]] ) + 1
486               
487      tmp_x = nc_read_from_file_1d(input_file_x[ii_parent[i]], "x", tmp_x0, tmp_x1)
488      tmp_y = nc_read_from_file_1d(input_file_y[ii_parent[i]], "y", tmp_y0, tmp_y1)
489
490      zt_parent = nc_read_from_file_2d(input_file_zt[ii_parent[i]], 'Band1', tmp_x0, tmp_x1, tmp_y0, tmp_y1)
491
492      print( "Shift terrain height by -" + str(zt_min))
493      zt_parent = zt_parent - zt_min
494
495#     Interpolate array and bring to PALM grid of child domain
496      zt_ip = interpolate_2d(zt_parent,tmp_x,tmp_y,x,y)
497      zt_ip = bring_to_palm_grid(zt_ip,x,y,domain_dz[ii_parent[i]])
498
499#     Shift the child terrain height according to the parent mean terrain height       
500      zt = zt - np.mean(zt)  + np.mean(zt_ip)
501 
502 
503#     Blend over the parent and child terrain height within a radius of 50 px 
504      zt = blend_array_2d(zt,zt_ip,50)
505   
506#  Final step: add zt array to the global array   
507   zt_all.append(zt)
508   del zt
509 
510
511# Read and shift x and y coordinates, shift terrain height according to its minimum value and write all data
512# to file 
513for i in range(0,ndomains):   
514#  Read horizontal grid variables from zt file and write them to output file
515   x = nc_read_from_file_1d(input_file_x[ii[i]], "x", domain_x0[i], domain_x1[i])
516   y = nc_read_from_file_1d(input_file_y[ii[i]], "y", domain_y0[i], domain_y1[i]) 
517   x = x - min(x.flatten()) + domain_px[i]/2.0
518   y = y - min(y.flatten()) + domain_px[i]/2.0 
519   nc_write_dimension(filename[i], 'x', x, datatypes["x"])
520   nc_write_dimension(filename[i], 'y', y, datatypes["y"]) 
521   nc_write_attribute(filename[i], 'x', 'long_name', 'x')
522   nc_write_attribute(filename[i], 'x', 'standard_name','projection_x_coordinate')   
523   nc_write_attribute(filename[i], 'x', 'units', 'm')
524   nc_write_attribute(filename[i], 'y', 'long_name', 'x')
525   nc_write_attribute(filename[i], 'y', 'standard_name', 'projection_y_coordinate')   
526   nc_write_attribute(filename[i], 'y', 'units', 'm')
527
528   lat = nc_read_from_file_2d(input_file_lat[ii[i]], "Band1", domain_x0[i], domain_x1[i], domain_y0[i], domain_y1[i])
529   lon = nc_read_from_file_2d(input_file_lon[ii[i]], "Band1", domain_x0[i], domain_x1[i], domain_y0[i], domain_y1[i]) 
530
531   nc_write_to_file_2d(filename[i], 'lat', lat, datatypes["lat"],'y','x',fillvalues["lat"])
532   nc_write_to_file_2d(filename[i], 'lon', lon, datatypes["lon"],'y','x',fillvalues["lon"]) 
533   
534   nc_write_attribute(filename[i], 'lat', 'long_name', 'latitude')
535   nc_write_attribute(filename[i], 'lat', 'standard_name','latitude')   
536   nc_write_attribute(filename[i], 'lat', 'units', 'degrees_north')
537 
538   nc_write_attribute(filename[i], 'lon', 'long_name', 'longitude')
539   nc_write_attribute(filename[i], 'lon', 'standard_name','longitude')   
540   nc_write_attribute(filename[i], 'lon', 'units', 'degrees_east') 
541   
542   x_UTM = nc_read_from_file_2d(input_file_x_UTM[ii[i]], "Band1", domain_x0[i], domain_x1[i], domain_y0[i], domain_y1[i])
543   y_UTM = nc_read_from_file_2d(input_file_y_UTM[ii[i]], "Band1", domain_x0[i], domain_x1[i], domain_y0[i], domain_y1[i]) 
544   
545   nc_write_to_file_2d(filename[i], 'E_UTM', x_UTM, datatypes["E_UTM"],'y','x',fillvalues["E_UTM"])
546   nc_write_to_file_2d(filename[i], 'N_UTM', y_UTM, datatypes["N_UTM"],'y','x',fillvalues["N_UTM"]) 
547   
548   nc_write_attribute(filename[i], 'E_UTM', 'long_name', 'easting')
549   nc_write_attribute(filename[i], 'E_UTM', 'standard_name','projection_x_coorindate')   
550   nc_write_attribute(filename[i], 'E_UTM', 'units', 'm')
551 
552   nc_write_attribute(filename[i], 'N_UTM', 'long_name', 'northing')
553   nc_write_attribute(filename[i], 'N_UTM', 'standard_name','projection_y_coorindate')   
554   nc_write_attribute(filename[i], 'N_UTM', 'units', 'm') 
555 
556   nc_write_crs(filename[i])
557   
558 
559 
560#  If necessary, bring terrain height to PALM's vertical grid. This is either forced by the user or implicitly
561#  by using interpolation for a child domain       
562   if domain_za[i]:
563      zt_all[i] = bring_to_palm_grid(zt_all[i],x,y,domain_dz[i])
564
565   nc_write_to_file_2d(filename[i], 'zt', zt_all[i], datatypes["zt"],'y','x',fillvalues["zt"])
566   nc_write_attribute(filename[i], 'zt', 'long_name', 'orography')
567   nc_write_attribute(filename[i], 'zt', 'units', 'm')
568   nc_write_attribute(filename[i], 'zt', 'res_orig', domain_px[i]) 
569   nc_write_attribute(filename[i], 'zt', 'coordinates', 'E_UTM N_UTM lon lat') 
570   nc_write_attribute(filename[i], 'zt', 'grid_mapping', 'E_UTM N_UTM lon lat')   
571
572del zt_all
573
574
575#  Process building height, id, and type
576for i in range(0,ndomains): 
577   buildings_2d = nc_read_from_file_2d(input_file_buildings_2d[ii[i]], 'Band1', domain_x0[i], domain_x1[i], domain_y0[i], domain_y1[i])
578   
579   building_id = nc_read_from_file_2d(input_file_building_id[ii[i]], 'Band1', domain_x0[i], domain_x1[i], domain_y0[i], domain_y1[i]) 
580 
581   building_type = nc_read_from_file_2d(input_file_building_type[ii[i]], 'Band1', domain_x0[i], domain_x1[i], domain_y0[i], domain_y1[i]) 
582   building_type[building_type == 255] = fillvalues["building_type"]
583   building_type = np.where(building_type < 1,defaultvalues["building_type"],building_type)
584 
585   check = check_arrays_2(buildings_2d,building_id,fillvalues["buildings_2d"],fillvalues["building_id"])
586   if not check:
587      buildings_2d = np.where(building_id != fillvalues["building_id"],buildings_2d,fillvalues["buildings_2d"])
588      building_id = np.where(buildings_2d == fillvalues["buildings_2d"],fillvalues["building_id"],building_id)
589      print("Data check #1 " + str(check_arrays_2(buildings_2d,building_id,fillvalues["buildings_2d"],fillvalues["building_id"])))
590
591   check = check_arrays_2(buildings_2d,building_type,fillvalues["buildings_2d"],fillvalues["building_type"])
592   if not check:
593      building_type = np.where(buildings_2d == fillvalues["buildings_2d"],fillvalues["building_type"],building_type)
594      building_type = np.where((building_type == fillvalues["building_type"]) & (buildings_2d != fillvalues["buildings_2d"]),defaultvalues["building_type"],building_type)
595      print("Data check #2 " + str(check_arrays_2(buildings_2d,building_type,fillvalues["buildings_2d"],fillvalues["building_type"])))
596 
597   nc_write_to_file_2d(filename[i], 'buildings_2d', buildings_2d, datatypes["buildings_2d"],'y','x',fillvalues["buildings_2d"])
598   nc_write_attribute(filename[i], 'buildings_2d', 'long_name', 'buildings')
599   nc_write_attribute(filename[i], 'buildings_2d', 'units', 'm')
600   nc_write_attribute(filename[i], 'buildings_2d', 'res_orig', domain_px[i]) 
601   nc_write_attribute(filename[i], 'buildings_2d', 'lod', 1) 
602   nc_write_attribute(filename[i], 'buildings_2d', 'coordinates', 'E_UTM N_UTM lon lat') 
603   nc_write_attribute(filename[i], 'buildings_2d', 'grid_mapping', 'E_UTM N_UTM lon lat')   
604   
605   nc_write_to_file_2d(filename[i], 'building_id', building_id, datatypes["building_id"],'y','x',fillvalues["building_id"])
606   nc_write_attribute(filename[i], 'building_id', 'long_name', 'building id')
607   nc_write_attribute(filename[i], 'building_id', 'units', '')
608   nc_write_attribute(filename[i], 'building_id', 'res_orig', domain_px[i]) 
609   nc_write_attribute(filename[i], 'building_id', 'coordinates', 'E_UTM N_UTM lon lat') 
610   nc_write_attribute(filename[i], 'building_id', 'grid_mapping', 'E_UTM N_UTM lon lat')   
611   
612   nc_write_to_file_2d(filename[i], 'building_type', building_type, datatypes["building_type"],'y','x',fillvalues["building_type"])
613   nc_write_attribute(filename[i], 'building_type', 'long_name', 'building type')
614   nc_write_attribute(filename[i], 'building_type', 'units', '')
615   nc_write_attribute(filename[i], 'building_type', 'res_orig', domain_px[i]) 
616   nc_write_attribute(filename[i], 'building_type', 'coordinates', 'E_UTM N_UTM lon lat') 
617   nc_write_attribute(filename[i], 'building_type', 'grid_mapping', 'E_UTM N_UTM lon lat')   
618 
619del buildings_2d
620del building_id
621del building_type
622
623# Create 3d buildings if necessary. In that course, read bridge objects and add them to building layer
624for i in range(0,ndomains): 
625   
626   if domain_3d[i]:
627      x = nc_read_from_file_2d_all(filename[i], 'x')
628      y = nc_read_from_file_2d_all(filename[i], 'y') 
629      buildings_2d = nc_read_from_file_2d_all(filename[i], 'buildings_2d') 
630      building_id = nc_read_from_file_2d_all(filename[i], 'building_id') 
631     
632      bridges_2d = nc_read_from_file_2d(input_file_bridges_2d[ii[i]], 'Band1', domain_x0[i], domain_x1[i], domain_y0[i], domain_y1[i])
633      bridges_id = nc_read_from_file_2d(input_file_bridges_id[ii[i]], 'Band1', domain_x0[i], domain_x1[i], domain_y0[i], domain_y1[i])
634     
635      bridges_2d = np.where(bridges_2d == 0.0,fillvalues["bridges_2d"],bridges_2d)
636      building_id = np.where(bridges_2d == fillvalues["bridges_2d"],building_id,bridges_id)
637     
638     
639      if np.any(buildings_2d != fillvalues["buildings_2d"]):
640         buildings_3d, z = make_3d_from_2d(buildings_2d,x,y,domain_dz[i])
641         if np.any(bridges_2d != fillvalues["bridges_2d"]):
642            buildings_3d = make_3d_from_bridges_2d(buildings_3d,bridges_2d,x,y,domain_dz[i],settings_bridge_width,fillvalues["bridges_2d"])
643         else:
644            print("Skipping creation of 3D bridges (no bridges in domain)")
645           
646           
647         nc_write_dimension(filename[i], 'z', z, datatypes["z"]) 
648         nc_write_attribute(filename[i], 'z', 'long_name', 'z') 
649         nc_write_attribute(filename[i], 'z', 'units', 'm')
650 
651         nc_write_to_file_3d(filename[i], 'buildings_3d', buildings_3d, datatypes["buildings_3d"],'z','y','x',fillvalues["buildings_3d"])   
652         nc_write_attribute(filename[i], 'buildings_3d', 'long_name', 'buildings 3d')
653         nc_write_attribute(filename[i], 'buildings_3d', 'units', '')
654         nc_write_attribute(filename[i], 'buildings_3d', 'res_orig', domain_px[i]) 
655         nc_write_attribute(filename[i], 'buildings_3d', 'lod', 2) 
656         
657         del buildings_3d
658         
659      else:
660         print("Skipping creation of 3D buildings (no buildings in domain)")
661
662
663      del bridges_2d, bridges_id, building_id, buildings_2d
664
665
666
667# Read vegetation type, water_type, pavement_type, soil_type and make fields consistent
668for i in range(0,ndomains): 
669
670   building_type = nc_read_from_file_2d_all(filename[i], 'building_type') 
671     
672   vegetation_type = nc_read_from_file_2d(input_file_vegetation_type[ii[i]], 'Band1', domain_x0[i], domain_x1[i], domain_y0[i], domain_y1[i])   
673   vegetation_type[vegetation_type == 255] = fillvalues["vegetation_type"]
674   vegetation_type = np.where((vegetation_type < 1) & (vegetation_type != fillvalues["vegetation_type"]),defaultvalues["vegetation_type"],vegetation_type)
675   
676   pavement_type = nc_read_from_file_2d(input_file_pavement_type[ii[i]], 'Band1', domain_x0[i], domain_x1[i], domain_y0[i], domain_y1[i])   
677   pavement_type[pavement_type == 255] = fillvalues["pavement_type"]
678   pavement_type = np.where((pavement_type < 1) & (pavement_type != fillvalues["pavement_type"]),defaultvalues["pavement_type"],pavement_type)
679
680   water_type = nc_read_from_file_2d(input_file_water_type[ii[i]], 'Band1', domain_x0[i], domain_x1[i], domain_y0[i], domain_y1[i])   
681   water_type[water_type == 255] = fillvalues["water_type"]
682   water_type = np.where((water_type < 1) & (water_type != fillvalues["water_type"]),defaultvalues["water_type"],water_type)
683 
684#  to do: replace by real soil input data
685   soil_type = nc_read_from_file_2d(input_file_vegetation_type[ii[i]], 'Band1', domain_x0[i], domain_x1[i], domain_y0[i], domain_y1[i]) 
686   soil_type[soil_type == 255] = fillvalues["soil_type"]
687   soil_type = np.where((soil_type < 1) & (soil_type != fillvalues["soil_type"]),defaultvalues["soil_type"],soil_type)
688
689#  Make arrays consistent
690#  #1 Set vegetation type to missing for pixel where a pavement type is set
691   vegetation_type = np.where((vegetation_type != fillvalues["vegetation_type"]) & (pavement_type != fillvalues["pavement_type"]),fillvalues["vegetation_type"],vegetation_type)
692
693#  #2 Set vegetation type to missing for pixel where a building type is set
694   vegetation_type = np.where((vegetation_type != fillvalues["vegetation_type"]) & (building_type != fillvalues["building_type"]) ,fillvalues["vegetation_type"],vegetation_type)
695
696#  #3 Set vegetation type to missing for pixel where a building type is set
697   vegetation_type = np.where((vegetation_type != fillvalues["vegetation_type"]) & (water_type != fillvalues["water_type"]),fillvalues["vegetation_type"],vegetation_type)   
698
699#  #4 Remove pavement for pixels with buildings
700   pavement_type = np.where((pavement_type != fillvalues["pavement_type"]) & (building_type != fillvalues["building_type"]),fillvalues["pavement_type"],pavement_type) 
701
702#  #5 Remove pavement for pixels with water
703   pavement_type = np.where((pavement_type != fillvalues["pavement_type"]) & (water_type != fillvalues["water_type"]),fillvalues["pavement_type"],pavement_type)   
704
705#  #6 Remove water for pixels with buildings
706   water_type = np.where((water_type != fillvalues["water_type"]) & (building_type != fillvalues["building_type"]),fillvalues["water_type"],water_type) 
707   
708
709#  #7 to be removed: set default soil type everywhere
710   soil_type = np.where((vegetation_type != fillvalues["vegetation_type"]) | (pavement_type != fillvalues["pavement_type"]),defaultvalues["soil_type"],fillvalues["soil_type"]) 
711 
712 
713#  Check for consistency and fill empty fields with default vegetation type
714   consistency_array, test = check_consistency_4(vegetation_type,building_type,pavement_type,water_type,fillvalues["vegetation_type"],fillvalues["building_type"],fillvalues["pavement_type"],fillvalues["water_type"])
715   
716   if test:
717      vegetation_type = np.where(consistency_array == 0,defaultvalues["vegetation_type"],vegetation_type)
718      consistency_array, test = check_consistency_4(vegetation_type,building_type,pavement_type,water_type,fillvalues["vegetation_type"],fillvalues["building_type"],fillvalues["pavement_type"],fillvalues["water_type"])
719   
720#  Create surface_fraction array
721   x = nc_read_from_file_2d_all(filename[i], 'x')
722   y = nc_read_from_file_2d_all(filename[i], 'y') 
723   nsurface_fraction = np.arange(0,3)
724   surface_fraction = np.ones((len(nsurface_fraction),len(y),len(x)))
725   
726   surface_fraction[0,:,:] = np.where(vegetation_type != fillvalues["vegetation_type"], 1.0, 0.0)
727   surface_fraction[1,:,:] = np.where(pavement_type != fillvalues["pavement_type"], 1.0, 0.0)
728   surface_fraction[2,:,:] = np.where(water_type != fillvalues["water_type"], 1.0, 0.0)
729   
730   nc_write_dimension(filename[i], 'nsurface_fraction', nsurface_fraction, datatypes["nsurface_fraction"]) 
731   nc_write_to_file_3d(filename[i], 'surface_fraction', surface_fraction, datatypes["surface_fraction"],'nsurface_fraction','y','x',fillvalues["surface_fraction"])     
732   nc_write_attribute(filename[i], 'surface_fraction', 'long_name', 'surface fraction')
733   nc_write_attribute(filename[i], 'surface_fraction', 'units', '')
734   nc_write_attribute(filename[i], 'surface_fraction', 'res_orig', domain_px[i])     
735   del surface_fraction   
736   
737 
738#  Correct vegetation_type when a vegetation height is available and is indicative of low vegeetation
739   vegetation_height = nc_read_from_file_2d(input_file_vegetation_height[ii[i]], 'Band1', domain_x0[i], domain_x1[i], domain_y0[i], domain_y1[i])   
740         
741   vegetation_type = np.where((vegetation_height != fillvalues["vegetation_height"]) & (vegetation_height == 0.0) & ((vegetation_type == 4) | (vegetation_type == 5) | (vegetation_type == 6) |(vegetation_type == 7) | (vegetation_type == 17) | (vegetation_type == 18)), 3, vegetation_type)
742   vegetation_height = np.where((vegetation_height != fillvalues["vegetation_height"]) & (vegetation_height == 0.0) & ((vegetation_type == 4) | (vegetation_type == 5) | (vegetation_type == 6) |(vegetation_type == 7) | (vegetation_type == 17) | (vegetation_type == 18)), fillvalues["vegetation_height"],vegetation_height)
743
744
745   nc_write_to_file_2d(filename[i], 'vegetation_type', vegetation_type, datatypes["vegetation_type"],'y','x',fillvalues["vegetation_type"])     
746   nc_write_attribute(filename[i], 'vegetation_type', 'long_name', 'vegetation type')
747   nc_write_attribute(filename[i], 'vegetation_type', 'units', '')
748   nc_write_attribute(filename[i], 'vegetation_type', 'res_orig', domain_px[i]) 
749   nc_write_attribute(filename[i], 'vegetation_type', 'coordinates', 'E_UTM N_UTM lon lat') 
750   nc_write_attribute(filename[i], 'vegetation_type', 'grid_mapping', 'E_UTM N_UTM lon lat')   
751   del vegetation_type
752
753   nc_write_to_file_2d(filename[i], 'pavement_type', pavement_type, datatypes["pavement_type"],'y','x',fillvalues["pavement_type"])   
754   nc_write_attribute(filename[i], 'pavement_type', 'long_name', 'pavement type')
755   nc_write_attribute(filename[i], 'pavement_type', 'units', '')
756   nc_write_attribute(filename[i], 'pavement_type', 'res_orig', domain_px[i]) 
757   nc_write_attribute(filename[i], 'pavement_type', 'coordinates', 'E_UTM N_UTM lon lat') 
758   nc_write_attribute(filename[i], 'pavement_type', 'grid_mapping', 'E_UTM N_UTM lon lat')   
759   del pavement_type
760
761   nc_write_to_file_2d(filename[i], 'water_type', water_type, datatypes["water_type"],'y','x',fillvalues["water_type"]) 
762   nc_write_attribute(filename[i], 'water_type', 'long_name', 'water type')
763   nc_write_attribute(filename[i], 'water_type', 'units', '')
764   nc_write_attribute(filename[i], 'water_type', 'res_orig', domain_px[i]) 
765   nc_write_attribute(filename[i], 'water_type', 'coordinates', 'E_UTM N_UTM lon lat') 
766   nc_write_attribute(filename[i], 'water_type', 'grid_mapping', 'E_UTM N_UTM lon lat')   
767   del water_type
768
769   nc_write_to_file_2d(filename[i], 'soil_type', soil_type, datatypes["soil_type"],'y','x',fillvalues["soil_type"]) 
770   nc_write_attribute(filename[i], 'soil_type', 'long_name', 'soil type')
771   nc_write_attribute(filename[i], 'soil_type', 'units', '')
772   nc_write_attribute(filename[i], 'soil_type', 'res_orig', domain_px[i])   
773   nc_write_attribute(filename[i], 'soil_type', 'coordinates', 'E_UTM N_UTM lon lat') 
774   nc_write_attribute(filename[i], 'soil_type', 'grid_mapping', 'E_UTM N_UTM lon lat')   
775   del soil_type
776
777   del x
778   del y
779
780#  pixels with bridges get building_type = 7 = bridge. This does not change the _type setting for the under-bridge
781#  area
782   if domain_3d[i]:
783      if np.any(building_type != fillvalues["building_type"]):
784 
785         bridges_2d = nc_read_from_file_2d(input_file_bridges_2d[ii[i]], 'Band1', domain_x0[i], domain_x1[i], domain_y0[i], domain_y1[i])         
786         bridges_2d = np.where(bridges_2d == 0.0,fillvalues["bridges_2d"],bridges_2d)
787         building_type = np.where(bridges_2d != fillvalues["bridges_2d"],7,building_type)
788         nc_overwrite_to_file_2d(filename[i], 'building_type', building_type) 
789 
790         del building_type 
791         del bridges_2d
792
793# Read/write street type and street crossings
794for i in range(0,ndomains): 
795
796   street_type = nc_read_from_file_2d(input_file_street_type[ii[i]], 'Band1', domain_x0[i], domain_x1[i], domain_y0[i], domain_y1[i])   
797   street_type[street_type == 255] = fillvalues["street_type"]
798   street_type = np.where((street_type < 1) & (street_type != fillvalues["street_type"]),defaultvalues["street_type"],street_type)
799   
800   nc_write_to_file_2d(filename[i], 'street_type', street_type, datatypes["street_type"],'y','x',fillvalues["street_type"]) 
801   nc_write_attribute(filename[i], 'street_type', 'long_name', 'street type')
802   nc_write_attribute(filename[i], 'street_type', 'units', '')
803   nc_write_attribute(filename[i], 'street_type', 'res_orig', domain_px[i]) 
804   nc_write_attribute(filename[i], 'street_type', 'coordinates', 'E_UTM N_UTM lon lat') 
805   nc_write_attribute(filename[i], 'street_type', 'grid_mapping', 'E_UTM N_UTM lon lat')   
806   del street_type
807   
808   street_crossings = nc_read_from_file_2d(input_file_street_crossings[ii[i]], 'Band1', domain_x0[i], domain_x1[i], domain_y0[i], domain_y1[i])   
809   street_crossings[street_crossings == 255] = fillvalues["street_crossings"]
810   street_crossings = np.where((street_crossings < 1) & (street_crossings != fillvalues["street_crossings"]),defaultvalues["street_crossings"],street_crossings)
811   
812   nc_write_to_file_2d(filename[i], 'street_crossings', street_crossings, datatypes["street_crossings"],'y','x',fillvalues["street_crossings"]) 
813   nc_write_attribute(filename[i], 'street_crossings', 'long_name', 'street crossings')
814   nc_write_attribute(filename[i], 'street_crossings', 'units', '')
815   nc_write_attribute(filename[i], 'street_crossings', 'res_orig', domain_px[i]) 
816   nc_write_attribute(filename[i], 'street_crossings', 'coordinates', 'E_UTM N_UTM lon lat') 
817   nc_write_attribute(filename[i], 'street_crossings', 'grid_mapping', 'E_UTM N_UTM lon lat')   
818   del street_crossings
819
820
821# Read/write vegetation on roofs
822for i in range(0,ndomains): 
823   if domain_green_roofs[i]: 
824      green_roofs = nc_read_from_file_2d(input_file_vegetation_on_roofs[ii[i]], 'Band1', domain_x0[i], domain_x1[i], domain_y0[i], domain_y1[i])   
825      buildings_2d = nc_read_from_file_2d_all(filename[i], 'buildings_2d') 
826
827
828      x = nc_read_from_file_2d_all(filename[i], 'x')
829      y = nc_read_from_file_2d_all(filename[i], 'y') 
830      nbuilding_pars = np.arange(0,46)
831      building_pars = np.ones((len(nbuilding_pars),len(y),len(x)))
832      building_pars[:,:,:] = fillvalues["building_pars"]
833
834#     assign green fraction on roofs
835      building_pars[3,:,:] = np.where( (buildings_2d != fillvalues["buildings_2d"] ) & ( green_roofs != fillvalues["building_pars"] ),1.0,fillvalues["building_pars"])
836
837#     assign leaf area index for vegetation on roofs
838      building_pars[4,:,:] = np.where( ( buildings_2d != fillvalues["buildings_2d"] ) & ( green_roofs == 1.0 ),settings_lai_roof_intensive,fillvalues["building_pars"])
839      building_pars[4,:,:] = np.where( ( buildings_2d != fillvalues["buildings_2d"] ) & ( green_roofs == 2.0 ),settings_lai_roof_extensive,building_pars[4,:,:])
840   
841   
842      nc_write_dimension(filename[i], 'nbuilding_pars', nbuilding_pars, datatypes["nbuilding_pars"]) 
843      nc_write_to_file_3d(filename[i], 'building_pars', building_pars, datatypes["building_pars"],'nbuilding_pars','y','x',fillvalues["building_pars"]) 
844      nc_write_attribute(filename[i], 'building_pars', 'long_name', 'building_pars')
845      nc_write_attribute(filename[i], 'building_pars', 'units', '')
846      nc_write_attribute(filename[i], 'building_pars', 'res_orig', domain_px[i]) 
847      nc_write_attribute(filename[i], 'building_pars', 'coordinates', 'E_UTM N_UTM lon lat') 
848      nc_write_attribute(filename[i], 'building_pars', 'grid_mapping', 'E_UTM N_UTM lon lat')   
849         
850      del building_pars, buildings_2d, x, y
851
852
853# Read tree data and create LAD and BAD arrays using the canopy generator
854for i in range(0,ndomains): 
855   if domain_street_trees[i]: 
856      lai = nc_read_from_file_2d(input_file_lai[ii[i]], 'Band1', domain_x0[i], domain_x1[i], domain_y0[i], domain_y1[i])   
857     
858     
859#     Save lai data as default for low and high vegetation
860      lai_low = lai
861      lai_high = lai
862     
863      x = nc_read_from_file_2d_all(filename[i], 'x')
864      y = nc_read_from_file_2d_all(filename[i], 'y') 
865      nvegetation_pars = np.arange(0,11)
866      vegetation_pars = np.ones((len(nvegetation_pars),len(y),len(x)))
867      vegetation_pars[:,:,:] = fillvalues["vegetation_pars"] 
868     
869      vegetation_pars[1,:,:] = lai
870     
871
872#     Write out first version of LAI. Will later be overwritten.
873      nc_write_dimension(filename[i], 'nvegetation_pars', nvegetation_pars, datatypes["nvegetation_pars"]) 
874      nc_write_to_file_3d(filename[i], 'vegetation_pars', vegetation_pars, datatypes["vegetation_pars"],'nvegetation_pars','y','x',fillvalues["vegetation_pars"]) 
875      nc_write_attribute(filename[i], 'vegetation_pars', 'long_name', 'vegetation_pars')
876      nc_write_attribute(filename[i], 'vegetation_pars', 'units', '')
877      nc_write_attribute(filename[i], 'vegetation_pars', 'res_orig', domain_px[i]) 
878      nc_write_attribute(filename[i], 'vegetation_pars', 'coordinates', 'E_UTM N_UTM lon lat') 
879      nc_write_attribute(filename[i], 'vegetation_pars', 'grid_mapping', 'E_UTM N_UTM lon lat')   
880
881
882#     Read all tree parameters from file
883      tree_height = nc_read_from_file_2d(input_file_tree_height[ii[i]], 'Band1', domain_x0[i], domain_x1[i], domain_y0[i], domain_y1[i])   
884      tree_crown_diameter = nc_read_from_file_2d(input_file_tree_crown_diameter[ii[i]], 'Band1', domain_x0[i], domain_x1[i], domain_y0[i], domain_y1[i])   
885      tree_trunk_diameter = nc_read_from_file_2d(input_file_tree_trunk_diameter[ii[i]], 'Band1', domain_x0[i], domain_x1[i], domain_y0[i], domain_y1[i])         
886      tree_type = nc_read_from_file_2d(input_file_tree_type[ii[i]], 'Band1', domain_x0[i], domain_x1[i], domain_y0[i], domain_y1[i]) 
887      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]) 
888     
889#     Remove missing values from the data. Reasonable values will be set by the tree generator   
890      tree_height = np.where( (tree_height == 0.0) | (tree_height == -1.0) ,fillvalues["tree_data"],tree_height)
891      tree_crown_diameter = np.where( (tree_crown_diameter == 0.0) | (tree_crown_diameter == -1.0) ,fillvalues["tree_data"],tree_crown_diameter)
892      tree_trunk_diameter = np.where( (tree_trunk_diameter == 0.0) | (tree_trunk_diameter == -1.0) ,fillvalues["tree_data"],tree_trunk_diameter)
893      tree_type = np.where( (tree_type == 0.0) | (tree_type == -1.0) ,fillvalues["tree_data"],tree_type)
894      patch_height = np.where( patch_height == -1.0 ,fillvalues["tree_data"],patch_height)     
895
896#     Convert trunk diameter from cm to m
897      tree_trunk_diameter = np.where(tree_trunk_diameter != fillvalues["tree_data"], tree_trunk_diameter * 0.01,tree_trunk_diameter)
898
899
900#     Temporarily change missing value for tree_type
901      tree_type = np.where( (tree_type == fillvalues["tree_type"]),fillvalues["tree_data"],tree_type)   
902
903#     Compare patch height array with vegetation type and correct accordingly
904      vegetation_type = nc_read_from_file_2d_all(filename[i], 'vegetation_type') 
905
906
907#     For zero-height patches, set vegetation_type to short grass and remove these pixels from the patch height array
908      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)
909      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)     
910      nc_overwrite_to_file_2d(filename[i], 'vegetation_type', vegetation_type) 
911
912      max_tree_height = max(tree_height.flatten())
913      max_patch_height = max(patch_height.flatten())
914     
915      if ( (max_tree_height != fillvalues["tree_data"]) | (max_patch_height == fillvalues["tree_data"]) ):
916           
917         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"])
918 
919 
920#        Remove LAD volumes that are inside buildings
921         buildings_2d = nc_read_from_file_2d_all(filename[i], 'buildings_2d') 
922         for k in range(0,len(zlad)-1):
923 
924            lad[k,:,:] = np.where(buildings_2d == fillvalues["buildings_2d"],lad[k,:,:],fillvalues["tree_data"])
925            bad[k,:,:] = np.where(buildings_2d == fillvalues["buildings_2d"],bad[k,:,:],fillvalues["tree_data"])
926            tree_ids[k,:,:] = np.where(buildings_2d == fillvalues["buildings_2d"],tree_ids[k,:,:],fillvalues["tree_data"])     
927 
928 
929         nc_write_dimension(filename[i], 'zlad', zlad, datatypes["tree_data"]) 
930         nc_write_to_file_3d(filename[i], 'lad', lad, datatypes["tree_data"],'zlad','y','x',fillvalues["tree_data"]) 
931         nc_write_attribute(filename[i], 'lad', 'long_name', 'leaf area density')
932         nc_write_attribute(filename[i], 'lad', 'units', '')
933         nc_write_attribute(filename[i], 'lad', 'res_orig', domain_px[i]) 
934         nc_write_attribute(filename[i], 'lad', 'coordinates', 'E_UTM N_UTM lon lat') 
935         nc_write_attribute(filename[i], 'lad', 'grid_mapping', 'E_UTM N_UTM lon lat') 
936 
937         nc_write_to_file_3d(filename[i], 'bad', bad, datatypes["tree_data"],'zlad','y','x',fillvalues["tree_data"]) 
938         nc_write_attribute(filename[i], 'bad', 'long_name', 'basal area density')
939         nc_write_attribute(filename[i], 'bad', 'units', '')
940         nc_write_attribute(filename[i], 'bad', 'res_orig', domain_px[i]) 
941         nc_write_attribute(filename[i], 'bad', 'coordinates', 'E_UTM N_UTM lon lat') 
942         nc_write_attribute(filename[i], 'bad', 'grid_mapping', 'E_UTM N_UTM lon lat')
943           
944         nc_write_to_file_3d(filename[i], 'tree_id', tree_ids, datatypes["tree_data"],'zlad','y','x',fillvalues["tree_data"]) 
945         nc_write_attribute(filename[i], 'tree_id', 'long_name', 'tree id')
946         nc_write_attribute(filename[i], 'tree_id', 'units', '')
947         nc_write_attribute(filename[i], 'tree_id', 'res_orig', domain_px[i]) 
948         nc_write_attribute(filename[i], 'tree_id', 'coordinates', 'E_UTM N_UTM lon lat') 
949         nc_write_attribute(filename[i], 'tree_id', 'grid_mapping', 'E_UTM N_UTM lon lat')           
950           
951         del buildings_2d, lai, lad, bad, tree_ids, zlad
952
953      del vegetation_pars, tree_height, tree_crown_diameter, tree_trunk_diameter, tree_type, patch_height, vegetation_type, x, y
954
955
956# Create vegetation patches for locations with high vegetation type
957for i in range(0,ndomains): 
958   if domain_canopy_patches[i]: 
959
960#     Load vegetation_type and lad array (at level z = 0) for re-processing
961      vegetation_type = nc_read_from_file_2d_all(filename[i], 'vegetation_type') 
962      lad = nc_read_from_file_3d_all(filename[i], 'lad') 
963      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]) 
964      vegetation_pars = nc_read_from_file_3d_all(filename[i], 'vegetation_pars') 
965      lai = vegetation_pars[1,:,:]
966
967#     For all pixels where the LAD array does not contains a street tree and for which a high vegetation was set and for which a patch height is either missing of larger than one grid spacing
968#     the lai_high is reset to a low vegetation value
969      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])) ),settings_lai_low_default,fillvalues["tree_data"])
970
971#     For all pixels where lai_high is set but no lai is available, set the default high vegetation lai TODO: check if this makes sense bacauce lai_high = lai anway?!
972      lai_high = np.where( (lai_high != fillvalues["tree_data"]) & (lai == fillvalues["tree_data"]), settings_lai_high_default, lai_high)
973
974#     Define a patch height whereever it is missing, but where a high vegetation LAI was set
975      patch_height = np.where ( (lai_high != fillvalues["tree_data"]) & (patch_height == fillvalues["tree_data"]), settings_patch_height_default, patch_height)
976
977#     Remove pixels where street trees were already set
978      patch_height = np.where ( (lad[0,:,:] != fillvalues["tree_data"]), fillvalues["tree_data"], patch_height)
979
980#     For missing LAI values, set either the high vegetation default or the low vegetation default   
981      lai_high = np.where( (patch_height > 2.0) & (lai_high == fillvalues["tree_data"]),settings_lai_high_default,lai_high)
982      lai_high = np.where( (patch_height <= 2.0) & (lai_high == fillvalues["tree_data"]),settings_lai_low_default,lai_high)
983   
984   
985      if ( max(patch_height.flatten()) >= (2.0 * domain_dz[i]) ):
986         print("    start calculating LAD (this might take some time)") 
987         lad_patch, patch_nz, status = process_patch(domain_dz[i],patch_height,lai_high,settings_lai_alpha,settings_lai_beta)
988
989         lad[0:patch_nz+1,:,:] = np.where( (lad[0:patch_nz+1,:,:] == fillvalues["tree_data"]),lad_patch[0:patch_nz+1,:,:], lad[0:patch_nz+1,:,:] )
990
991#     Remove high vegetation wherever it is replaced by a leaf area density. This should effectively remove all high vegetation pixels
992      vegetation_type = np.where((lad[0,:,:] != fillvalues["tree_data"]) & (vegetation_type != fillvalues["vegetation_type"]),3,vegetation_type)
993 
994 
995#     If desired, remove all high vegetation. TODO: check if this is still necessary
996      if domain_high_vegetation[i]:
997         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)   
998
999 
1000#     Remove LAI from pixels where a LAD was set
1001      lai_low = np.where( (lad[0,:,:] == fillvalues["tree_data"]), lai,fillvalues["tree_data"])
1002   
1003#     Fill low vegetation pixels without LAI set with default value
1004      lai_low = np.where( (lai == fillvalues["tree_data"]) & (vegetation_type != fillvalues["vegetation_type"] ), settings_lai_low_default, lai)
1005
1006   
1007#     Overwrite lai in vegetation_parameters 
1008
1009      vegetation_pars[1,:,:] = lai_low
1010      nc_overwrite_to_file_3d(filename[i], 'vegetation_pars', vegetation_pars) 
1011
1012#     Overwrite lad array
1013      nc_overwrite_to_file_3d(filename[i], 'lad', lad) 
1014     
1015#     Overwrite vegetation_type
1016      nc_overwrite_to_file_2d(filename[i], 'vegetation_type', vegetation_type)   
1017     
1018     
1019      del vegetation_type, lad, lai, patch_height, vegetation_pars
Note: See TracBrowser for help on using the repository browser.