source: palm/trunk/SCRIPTS/palm_csd @ 3878

Last change on this file since 3878 was 3859, checked in by maronga, 6 years ago

comments in radiation model updated, minor bugfix in palm_csd

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