1 from __future__
import absolute_import
2 from __future__
import print_function
3 import simplekml
as kml
8 from utils
import update_nested_dict
, load_sys_cfg
9 from six
.moves
.urllib
.parse
import urljoin
10 import posixpath
as pxp
12 from six
.moves
import map
13 from six
.moves
import zip
15 sys_cfg
= load_sys_cfg()
16 sys_cfg
.sims_path
= 'fdds/simulations'
17 sys_cfg
.sims_url_path
= 'simulations'
19 def make_kmz(job_id
, steps
, mode
, only_vars
):
21 Create KMZ file from visualization stored in wrfxweb.
22 :param job_id: string, the name of job directory
23 :param steps: string '1,1,1,3' takes every 3rd frame in domain 4, etc. Default: all 1
24 :param mode: string, 'inc', ' to include image files (default), 'ref' to use links only
25 :param only_var: list of strings variables to include or None to include all
28 logging
.info('make_kmz: job_id=%s' % job_id
)
29 job_path
= osp
.join(osp
.abspath(sys_cfg
.sims_path
),job_id
)
30 url_prefix
= pxp
.join(sys_cfg
.url_root
,sys_cfg
.sims_url_path
,job_id
)
31 logging
.debug('make_kmz: job_path %s' % job_path
)
32 logging
.debug('make_kmz: url_prefix %s' % url_prefix
)
35 if mode
== '' or mode
== "inc":
36 kmz_filename
= job_id
+ '_inc.kmz'
37 href_prefix
= osp
.abspath(job_path
)
39 logging
.debug('make_kmz: kmz file will include images from %s' % href_prefix
)
40 logging
.info('make_kmz: kmz file will include images')
42 kmz_filename
= job_id
+ '_ref.kmz'
43 href_prefix
= url_prefix
45 logging
.debug('make_kmz: kmz file will link to images from %s' % href_prefix
)
46 logging
.info('make_kmz: kmz file will link to images')
48 logging
.error('make_kmz: arg 2 must be "inc" or "ref" or omitted')
51 # read the catalog and the manifest
52 cat_path
= osp
.join(job_path
,'catalog.json')
53 cat
= json
.load(open(cat_path
))
55 logging
.error('job id %s not in the catalog' % job_id
)
57 cat_entry
= cat
[job_id
]
58 mf
= json
.load(open(osp
.join(sys_cfg
.sims_path
,cat_entry
['manifest_path'])))
60 mdomain
= max(list(map(int, list(mf
.keys()))))
64 step
=list(map(int, steps
.split(',')))
67 elif len(step
) != mdomain
:
68 logging
.error('make_kmz: steps needed for all up to max domain number = %s' % mdomain
)
71 description
= cat_entry
['description']
72 logging
.info('make_kmz: job description: %s' % description
)
74 # transpose var and time in manifest, output to frame
77 for ts_esmf
in mf
[domain
]:
78 for var
in mf
[domain
][ts_esmf
]:
79 if only_vars
is None or var
in only_vars
:
80 update_nested_dict(frame
,{domain
:{var
:{ts_esmf
:mf
[domain
][ts_esmf
][var
]}}})
82 doc
= kml
.Kml(name
=description
)
84 for domain
in sorted(frame
):
85 domain_folder
= doc
.newfolder(name
= domain
)
86 istep
= step
[int(domain
)-1]
87 logging
.info('make_kmz: processing domain %s step %s' % (domain
, istep
))
88 for var
in frame
[domain
]:
89 var_folder
= domain_folder
.newfolder(name
= var
)
90 ts_esmf
= sorted(frame
[domain
][var
].keys())
91 ts_esmf
= ts_esmf
[1::istep
]
92 ts_esmf1
= ts_esmf
[1:]
94 for ts_esmf
,ts_esmf1
in zip(ts_esmf
,ts_esmf1
):
95 ts_folder
= var_folder
.newfolder(name
= ts_esmf
)
96 ts_folder
.timespan
.begin
= ts_esmf
.replace('_','T')+'Z'
97 if ts_esmf1
is not None:
98 ts_folder
.timespan
.end
= ts_esmf1
.replace('_','T')+'Z'
99 frame_data
= frame
[domain
][var
][ts_esmf
]
100 raster_path
= frame_data
['raster']
101 coords
= frame_data
['coords']
102 if 'colorbar' in frame_data
:
103 # add colorbar to KMZ
104 cb_path
= frame_data
['colorbar']
105 cbo
= ts_folder
.newscreenoverlay(name
='colorbar')
106 cbo
.overlayxy
= kml
.OverlayXY(x
=0,y
=1,xunits
=kml
.Units
.fraction
,yunits
=kml
.Units
.fraction
)
107 cbo
.screenxy
= kml
.ScreenXY(x
=0.02,y
=0.95,xunits
=kml
.Units
.fraction
,yunits
=kml
.Units
.fraction
)
108 cbo
.size
= kml
.Size(x
=150,y
=300,xunits
=kml
.Units
.pixel
,yunits
=kml
.Units
.pixel
)
109 cbo
.color
= kml
.Color
.rgb(255,255,255,a
=150)
111 cbo
.icon
.href
= href_join(href_prefix
,cb_path
)
114 ground
= ts_folder
.newgroundoverlay(name
=var
,color
='80ffffff')
115 ground
.gxlatlonquad
.coords
= coords
116 ground
.visibility
= 0
117 ground
.icon
.href
= href_join(href_prefix
,raster_path
)
120 kmz_path
= osp
.join(job_path
,kmz_filename
)
121 logging
.info('make_kmz: creating file %s' % kmz_path
)
122 doc
.savekmz(kmz_path
)
123 url
= pxp
.join(url_prefix
,kmz_filename
)
124 logging
.info('make_kmz: file created at %s' % url
)
126 r
= requests
.get(url
, stream
=True)
127 content_size
= int(r
.headers
['Content-Length'])
128 logging
.info('make_kmz: file size is %s' % content_size
)
129 cat
[job_id
]['kml_url']=url
130 cat
[job_id
]['kml_size']=content_size
131 json
.dump(cat
, open(cat_path
,'w'), indent
=4, separators
=(',', ': '))
132 except Exception as e
:
133 logging
.warning('make_kmz: accessing the file over the web failed with exception %s' % e
)
140 if __name__
== '__main__':
144 if len(sys
.argv
) < 2:
145 print('usage: make_kmz.sh job_id steps mode only_vars variable1 variable2 ...')
146 print('job_id: the name of job directory in ' + sys_cfg
.sims_path
)
147 print("steps: '1,1,1,3' takes every 3rd frame in domain 4, etc. Default: all 1")
148 print("mode: inc to include image files (default), ref to use links only")
149 print('variable (optional): variables to include; if absent all will be included')
152 logging
.basicConfig(level
=logging
.INFO
, format
='%(asctime)s - %(levelname)s - %(message)s')
156 if len(sys
.argv
) >= 3:
161 if len(sys
.argv
) >= 4:
166 if len(sys
.argv
) >= 5:
167 only_vars
= sys
.argv
[4:]
171 make_kmz(job_id
, steps
, mode
, only_vars
)