def testDocument(self): # Create a new document packet doc_packet1 = czml.CZMLPacket(id='document', version='1.0') self.assertEqual(doc_packet1.data(), { 'id': 'document', 'version': '1.0' }) # Modify an existing document packet doc_packet1.version = '1.1' self.assertEqual(doc_packet1.data(), { 'id': 'document', 'version': '1.1' }) # Create a new document packet from an existing document packet doc_packet2 = czml.CZMLPacket() doc_packet2.loads(doc_packet1.dumps()) self.assertEqual(doc_packet1.data(), doc_packet2.data()) # Test that version can only be added to the document packet (id='document') with self.assertRaises(Exception): doc_packet1 = czml.CZMLPacket(id='foo', version='1.0') doc_packet1 = czml.CZMLPacket(id='foo') self.assertRaises(Exception, setattr, doc_packet1, 'version', '1.0') # Test the writing of CZML using the write() method and the reading of that CZML using the loads() method doc = czml.CZML() doc.packets.append(doc_packet2) label_packet = czml.CZMLPacket(id='label') label = czml.Label() label.text = 'test label' label.show = True label_packet.label = label doc.packets.append(label_packet) test_filename = 'test.czml' doc.write(test_filename) with open(test_filename, 'r') as test_file: doc2 = czml.CZML() doc2.loads(test_file.read()) self.assertEqual(doc.dumps(), doc2.dumps()) os.remove(test_filename)
def __init__(self, verbose=False): """Construct a CZMLWriter. Args: verbose (bool): Extra messaging from methods. """ self.doc = czml.CZML() self.doc.packets.append(czml.CZMLPacket(id="document", version="1.0")) self.timestep_count = 0 self.sim_end_date = None self.sim_start_date = None self._verbose = verbose
def czml(self): doc = czml.CZML(); iso = self.date.isoformat() # Generate time-specific lists for various objects central_polyline_degrees = [] north_polyline_degrees = [] south_polyline_degrees = [] ellipse_position = [] ellipse_semiMajorAxis = [] ellipse_semiMinorAxis = [] ellipse_rotation = [] for t in range(len(self.time)): time = iso + "T" + self.time[t] + ":00Z" # Define polyline waypoints only where data exist if self.position['north'][t] != None: north_polyline_degrees += [self.position['north'][t][0], self.position['north'][t][1], 0.0] if self.position['central'][t] != None: central_polyline_degrees += [self.position['central'][t][0], self.position['central'][t][1], 0.0] if self.position['south'][t] != None: south_polyline_degrees += [self.position['south'][t][0], self.position['south'][t][1], 0.0] # Define ellipse positions and attributes for every time in the interval, using limits where necessary use_limit = min(int(math.floor(t/(len(self.time)/2))),1) if self.position['north'][t] == None: north = self.limits['north'][use_limit] else: north = self.position['north'][t] if self.position['central'][t] == None: central = self.limits['central'][use_limit] else: central = self.position['central'][t] if self.position['south'][t] == None: south = self.limits['south'][use_limit] else: south = self.position['south'][t] # Approximate ellipse semiMajorAxis from vincenty distance between limit polylines north2 = (north[1], north[0]) south2 = (south[1], south[0]) semi_major_axis = vincenty(north2, south2).meters / 2 # Approximate elipse semiMinorAxis from sun altitude (probably way wrong!) ellipse_axis_ratio = self.sun_altitude[t] / 90 semi_minor_axis = semi_major_axis * ellipse_axis_ratio # Approximate ellipse rotation using basic spheroid (TODO: replace with WGS-84) # Calculate bearing in both directions and average them nlat = north[1]/180 * math.pi; nlon = north[0]/180 * math.pi; clat = central[1]/180 * math.pi; clon = central[0]/180 * math.pi; slat = south[1]/180 * math.pi; slon = south[0]/180 * math.pi; y = math.sin(slon-nlon) * math.cos(slat); x = math.cos(nlat) * math.sin(slat) - math.sin(nlat) * math.cos(slat) * math.cos(slon-nlon); initial_bearing = math.atan2(y, x) if (initial_bearing < 0): initial_bearing += math.pi * 2 y = math.sin(nlon-slon) * math.cos(nlat); x = math.cos(slat) * math.sin(nlat) - math.sin(slat) * math.cos(nlat) * math.cos(nlon-slon); final_bearing = math.atan2(y, x) - math.pi if (final_bearing < 0): final_bearing += math.pi * 2 rotation = -1 * ((initial_bearing + final_bearing) / 2 - (math.pi / 2)) ellipse_position += [time, central[0], central[1], 0.0] ellipse_semiMajorAxis += [time, round(semi_major_axis, 3)] ellipse_semiMinorAxis += [time, round(semi_minor_axis, 3)] ellipse_rotation += [time, round(rotation, 3)] # Generate document packet with clock start_time = iso + "T" + self.time[0] + ":00Z" end_time = iso + "T" + self.time[-1] + ":00Z" packet = czml.CZMLPacket(id='document',version='1.0') c = czml.Clock() c.multiplier = 300 c.range = "LOOP_STOP" c.step = "SYSTEM_CLOCK_MULTIPLIER" c.currentTime = start_time c.interval = start_time + "/" + end_time packet.clock = c doc.packets.append(packet) # Generate a polyline packet for the north and south polylines, connected and filled limit_polyline_degrees = list(north_polyline_degrees) point = len(south_polyline_degrees)/3 while (point > 0): offset = (point-1) * 3 limit_polyline_degrees += [ south_polyline_degrees[offset], south_polyline_degrees[offset+1], south_polyline_degrees[offset+2] ] point -= 1 packet_id = iso + '_bounds_polygon' packet = czml.CZMLPacket(id=packet_id) boc = czml.Color(rgba=(232, 72, 68, 255)) bsc = czml.SolidColor(color=czml.Color(rgba=(0, 0, 0, 66))) bmat = czml.Material(solidColor=bsc) bdeg = limit_polyline_degrees bpos = czml.Positions(cartographicDegrees=bdeg) bpg = czml.Polygon(show=True, height=0, outline=True, outlineColor=boc, outlineWidth=2, material=bmat, positions=bpos) packet.polygon = bpg doc.packets.append(packet) # Generate central polyline packet packet_id = iso + '_central_polyline' packet = czml.CZMLPacket(id=packet_id) csc = czml.SolidColor(color=czml.Color(rgba=(241, 226, 57, 255))) cmat = czml.Material(solidColor=csc) cpos = czml.Positions(cartographicDegrees=central_polyline_degrees) cpl = czml.Polyline(show=True, width=4, followSurface=True, material=cmat, positions=cpos) packet.polyline = cpl doc.packets.append(packet) # Generate ellipse shadow packet packet_id = iso + '_shadow_ellipse' packet = czml.CZMLPacket(id=packet_id) esc = czml.SolidColor(color=czml.Color(rgba=(0, 0, 0, 160))) emat = czml.Material(solidColor=esc) xmaj = czml.Number(ellipse_semiMajorAxis) xmin = czml.Number(ellipse_semiMinorAxis) rot = czml.Number(ellipse_rotation) ell = czml.Ellipse(show=True, fill=True, granularity=0.002, material=emat, semiMajorAxis=xmaj, semiMinorAxis=xmin, rotation=rot) packet.ellipse = ell packet.position = czml.Position(cartographicDegrees=ellipse_position) doc.packets.append(packet) return list(doc.data())
def geojsonToCzmlTotal(file, total=True): doc = czml.CZML() clock={ 'interval': '2019-12-31T00:00:00Z/2020-08-16T23:59:59Z', 'currentTime': '2019-12-31T00:00:00Z', 'multiplier': 320000, 'range': 'LOOP_STOP', 'step': 'SYSTEM_CLOCK_MULTIPLIER' } packet1 = czml.CZMLPacket( id='document', version='1.0', clock=clock ) doc.packets.append(packet1) with open(file) as f: ids = {} data = json.load(f) for feature in data['features']: total_values = 0 if total: total_values = feature['properties']['total_cases'] if feature['properties']['total_cases'] != None else 0 else: total_values = feature['properties']['total_deaths'] if feature['properties']['total_deaths'] != None else 0 description = 'Total deaths on ' + feature['properties']['date'] + ' is ' + str(total_values) description= '\ <h2>General Details:</h2> \ <p>\ Date: {date} <br /> \ Total cases: {total_cases} <br /> \ Total cases/million: {total_cases_pm} <br /> \ Total deaths: {total_deaths} <br /> \ Total deaths/million: {total_deaths_pm} <br /> \ New cases: {new_cases} <br /> \ New deaths: {new_deaths} <br /> \ </p>\ <h2>Demographic Details:</h2> \ <p> \ Population: {population} <br /> \ Median age: {median_age} <br /> \ Hospital beds/thoudsand: {hospital_beds_per_thousand} \ </p> \ '.format( date=feature['properties']['date'], total_cases=feature['properties']['total_cases'], total_cases_pm=feature['properties']['total_cases_per_million'], total_deaths=feature['properties']['total_deaths'], total_deaths_pm=feature['properties']['total_deaths_per_million'], new_cases=feature['properties']['new_cases'], new_deaths=feature['properties']['new_deaths'], population=feature['properties']['population'], median_age=feature['properties']['median_age'], hospital_beds_per_thousand=feature['properties']['hospital_beds_per_thousand'], ) id = 0 if feature['properties']['Address'] in ids: ids[feature['properties']['Address']] += 1 id = ids[feature['properties']['Address']] else: ids[feature['properties']['Address']] = 0 packet = czml.CZMLPacket( id=feature['properties']['Address']+str(id), name=feature['properties']['Address'], description=description, availability=feature['properties']['date'] + 'T00:00:00.000Z'+ '/' + feature['properties']['date'] + 'T23:59:59.999Z' ) # pixel_size=0 # if total_values > 5: # pixel_size = math.log(total_values) point = czml.Point( show=True, pixelSize=clamp(total_values, 0, 100) ) # Coloring based on number of cases color = [255, 0, 0, 65] if total_values < 50: color = [52, 235, 61, 65] elif total_values >= 50 and total_values < 200: color = [235, 222, 52, 65] elif total_values >= 200 and total_values < 2000: color = [235, 155, 52, 65] else: color = [235, 76, 52, 65] point.color = {'rgba': color} packet.point = point packet.position = { 'cartographicDegrees': [ feature['geometry']['coordinates'][0], feature['geometry']['coordinates'][1], 0.0 ] } doc.packets.append(packet) # Write the czml document to a file if total: filename = "./data_total.czml" doc.write(filename) else: filename = "./data_deaths.czml" doc.write(filename)