1 # Copyright (C) 2013-2016 Martin Vejmelka, UC Denver
3 # Permission is hereby granted, free of charge, to any person obtaining a copy
4 # of this software and associated documentation files (the "Software"), to deal
5 # in the Software without restriction, including without limitation the rights
6 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7 # of the Software, and to permit persons to whom the Software is furnished to do
8 # so, subject to the following conditions:
10 # The above copyright notice and this permission notice shall be included in all
11 # copies or substantial portions of the Software.
13 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
14 # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR
15 # A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
16 # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
18 # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 from datetime
import datetime
26 from lxml
import etree
30 A dictionary that allows member access to its keys.
33 def __init__(self
, d
):
35 Updates itself with d.
39 def __getattr__(self
, item
):
42 def __setattr__(self
, item
, value
):
48 Load information on job profiles available to users.
50 :return: a dict keyed by profile id containing Dicts with profile info
52 profs
= json
.load(open('etc/profiles.json'))
53 return {name
:Dict(p
) for name
,p
in profs
.items()}
57 Convert a UTC datetime into a ESMF string.
59 :param ts: the datetime object
60 :return: the date time in ESMF format
62 return '%04d-%02d-%02d_%02d:%02d:%02d' % (ts
.year
, ts
.month
, ts
.day
, ts
.hour
, ts
.minute
, ts
.second
)
67 Parse and convert an ESMF datetime into a datetime in UTC.
69 :param esmf: the ESMF string YYYY-MM-DD_hh:mm:ss
70 :return: a datetime in the UTC timezone
72 year
, mon
, day
= int(esmf
[0:4]), int(esmf
[5:7]), int(esmf
[8:10])
73 hour
, min, sec
= int(esmf
[11:13]), int(esmf
[14:16]), int(esmf
[17:19])
74 return datetime(year
, mon
, day
, hour
, min, sec
, tzinfo
=pytz
.utc
)
80 :param path: list of file paths
81 :return: 'OK', otherwise error
84 logging
.debug('Deleting %s' % f
)
87 logging
.info('Deleted %s' % f
)
88 except OSError as err
:
89 logging
.error('Cannot delete %s: %s' % (f
,err
.strerror
))
93 # load the system configuration
96 sys_cfg
= Dict(json
.load(open('etc/conf.json')))
98 logging
.critical('Cannot find system configuration, have you created etc/conf.json?')
101 sys
= sys_cfg
.sys_install_path
= sys_cfg
.get('sys_install_path',os
.getcwd())
102 sys_cfg
.jobs_path
= sys_cfg
.get('jobs_path',osp
.join(sys
,'jobs'))
103 sys_cfg
.logs_path
= sys_cfg
.get('logs_path',osp
.join(sys
,'logs'))
104 sys_cfg
.sims_path
= sys_cfg
.get('sims_path',osp
.join(sys
,'simulations'))
108 def parse_kml(kml_data
, kml_object
):
110 parser
= etree
.XMLParser(recover
=True, remove_blank_text
=True)
111 # parse the file as a tree element
112 root
= etree
.fromstring(kml_data
, parser
=parser
)
113 # get namespace map that each tag is going to contain
114 nsmap
= root
.nsmap
.get('kml', root
.nsmap
.get(None))
115 # create xpath lambda function to generate paths to elements with the namespace map
116 xpath
= lambda tag
: './/{{{}}}{}'.format(nsmap
, tag
) if nsmap
else './/{}'.format(tag
)
117 # get all the Placemarks
119 # loop all the placemarks
120 for pm
in root
.iterfind(xpath('Placemark')):
121 # loop all the polygons
122 for pp
in pm
.iterfind(xpath(kml_object
)):
123 # TODO: add multiple outer boundaries (JS only allows one boundary for now)
124 # get the outer boundary coordinates
126 out_elem
= pp
.find(xpath('outerBoundaryIs')).find(xpath('coordinates'))
128 out_elem
= pp
.find(xpath('coordinates'))
129 # append outer boundaries to general array cleaning blank spaces
132 'lat': float(coord
.strip().split(',')[1].strip()),
133 'lon': float(coord
.strip().split(',')[0].strip()),
136 for coord
in out_elem
.text
.strip().split(' ') if coord
.strip() != ''
138 # TODO: add inner boundaries (JS only allows one boundary for now)