def testPoint(self): point = czml.Point() point.color = {'rgba': [0, 255, 127, 55]} self.assertEqual(point.data(), {'color': {'rgba': [0, 255, 127, 55]}, 'show': False}) point.outlineColor = {'rgbaf': [0.0, 0.255, 0.127, 0.55]} self.assertEqual(point.data(), {'color': {'rgba': [0, 255, 127, 55]}, 'outlineColor': {'rgbaf': [0.0, 0.255, 0.127, 0.55]}, 'show': False}) point.pixelSize = 10 point.outlineWidth = 2 point.show = True self.assertEqual(point.data(), {'color': {'rgba': [0, 255, 127, 55]}, 'pixelSize': 10, 'outlineColor': {'rgbaf': [0.0, 0.255, 0.127, 0.55]}, 'outlineWidth': 2, 'show': True}) p2 = czml.Point() p2.loads(point.dumps()) self.assertEqual(point.data(), p2.data())
def _filter_users_criteria(filters): try: users = db.session.query(Users.userid, Users.userpos, func.length(Users.userpos), func.twAvg(func.speed(Users.userpos))).filter( *filters, ).all() except: traceback.print_exc() return jsonify({"errors": [DATA_UNINITIALIZED_ERROR]}), 400 # Import the library from czml import czml # Initialize a document doc = czml.CZML() # Create and append the document packet packet1 = czml.CZMLPacket(id='document', version='1.0') doc.packets.append(packet1) # Create and append a POINT packet packet3 = czml.CZMLPacket() for user_id, user, distance, speed in users: packet3.id = user_id pp = czml.Point() pp.color = {'rgba': [0, 255, 127, 55]} pp.outlineColor = {'rgba': [255, 0, 0, 128]} #varPos = czml.Position(cartographicDegrees=[2020-06-04T16:00:00Z,-56.189652081027,-34.8888227843656,0,2020-06-04T16:05:00Z,-56.189652081027,-34.8888227843656,0]) pos = czml.Position() #coords = ['2020-06-04T16:00:00Z','-56.189652081027','-34.8888227843656','0','2020-06-04T16:05:00Z','-56.189652081027','-34.8888227843656','0'] coords = serialize_trajectory(user) pos.epoch = coords['epoch'] pos.cartographicDegrees = coords['cartographicDegrees'] #varPos.cartographicDegrees = [2020-06-04T16:00:00Z,-56.189652081027,-34.8888227843656,0,2020-06-04T16:05:00Z,-56.189652081027,-34.8888227843656,0] #trayectoria = Path(pos,pp) packet3.position = pos packet3.point = pp #Path(pos, pp) #packet3.path = trayectoria #pp.Position = Position(varPos) doc.packets.append(packet3) # Write the CZML document to a file filename = "example.czml" doc.write(filename) return jsonify({ "users": [{ "id": user_id, "trajectory": serialize_trajectory(user), "distance": distance, "speed": speed, } for user_id, user, distance, speed in users] })
def testPoint(self): # Create a new point point = czml.Point() point.color = {'rgba': [0, 255, 127, 55]} self.assertEqual(point.data(), { 'color': { 'rgba': [0, 255, 127, 55] }, 'show': False }) point.outlineColor = {'rgbaf': [0.0, 0.255, 0.127, 0.55]} self.assertEqual( point.data(), { 'color': { 'rgba': [0, 255, 127, 55] }, 'outlineColor': { 'rgbaf': [0.0, 0.255, 0.127, 0.55] }, 'show': False }) # Modify an existing point point.pixelSize = 10 point.outlineWidth = 2 point.show = True self.assertEqual( point.data(), { 'color': { 'rgba': [0, 255, 127, 55] }, 'pixelSize': 10, 'outlineColor': { 'rgbaf': [0.0, 0.255, 0.127, 0.55] }, 'outlineWidth': 2, 'show': True }) # Create a new point from an existing point p2 = czml.Point() p2.loads(point.dumps()) self.assertEqual(point.data(), p2.data()) # Add a point to a CZML packet packet = czml.CZMLPacket(id='abc') packet.point = p2 self.assertEqual( packet.data(), { 'id': 'abc', 'point': { 'color': { 'rgba': [0, 255, 127, 55] }, 'pixelSize': 10, 'outlineColor': { 'rgbaf': [0.0, 0.255, 0.127, 0.55] }, 'outlineWidth': 2, 'show': True }, })
def add_vector_migrations(self, vector_migrations, demographics, migration_duration_timesteps, dot_color, dot_size_pixels, path_color, path_thickness_pixels, path_trail_time_factor): """Adds vector cohort migration animations to a CZML output. This function, given vector migrations in a particular format and a demographics file, adds "comet" animations for migration events. This function expects the following fields in vector_migrations: * Time (int): the timestep of the beginning of the migration event * FromNodeID (int): the node ID from which the migration emanates * ToNodeID (int): the node ID to which the migration completes Returns: Number of vector cohort migrations in animation layer Args: vector_migrations (CSVReport): The ReportVectorMigrations.csv report. demographics (Demographics): The Demographics object describing the nodes. migration_duration_timesteps (int): The duration of the migration animations in timesteps. dot_color (string): A CSS #rrggbb color for the comet dot. dot_size_pixels (int): Size in pixels of comet dot. path_color (string): A CSS #rrggbb color for the comet tail. path_thickness_pixels (float): Thickness in pixels of comet tail. path_trail_time_factor (float): Length of trail as a multiple of the migration_duration. E.g. if this is 1.0, the trail length will be the full distance from source node to the destination node. If 0.5, the trail length will be half the distance between the nodes. """ count = 0 for row in vector_migrations: timestep = int(row["Time"]) from_node_id = row["FromNodeID"] to_node_id = row["ToNodeID"] if not (from_node_id in demographics and to_node_id in demographics): continue from_node = demographics[from_node_id] to_node = demographics[to_node_id] dur_seconds = migration_duration_timesteps * 60 * 60 * 24 trail_seconds = dur_seconds * path_trail_time_factor availability = self._timestep_to_iso(timestep) + "/" +\ self._timestep_to_iso(timestep + migration_duration_timesteps) id_txt = "%s-%s@%d_%d" % (from_node_id, to_node_id, timestep, count) # The thing to remember about paths is that their initial duration # is going to be availability, but then they are going to be around # for an *additional* trailTime seconds. So the color fade in the # path needs to run for dur_seconds + trailTime. mig_path = czml.CZMLPacket( id=id_txt, availability=availability, position={ "epoch": self._timestep_to_iso(timestep), "cartographicDegrees": [ 0, # in seconds from_node["NodeAttributes"]["Longitude"], from_node["NodeAttributes"]["Latitude"], 0, # altitude dur_seconds, to_node["NodeAttributes"]["Longitude"], to_node["NodeAttributes"]["Latitude"], 0 # altitude ] }) dc = Color.from_html_hash(dot_color) pc = Color.from_html_hash(path_color) pt = czml.Point(pixelSize=dot_size_pixels, show=True, color={ "epoch": self._timestep_to_iso(timestep), "rgba": [ 0, dc.r, dc.g, dc.b, 255, dur_seconds, dc.r, dc.g, dc.b, 0 ] }) path = czml.Path(leadTime=0, trailTime=trail_seconds, resolution=CZMLWriter.k_default_clock_multiplier, material={ "solidColor": { "color": { "epoch": self._timestep_to_iso(timestep), "rgba": [ 0, pc.r, pc.g, pc.b, 255, dur_seconds + trail_seconds, pc.r, pc.g, pc.b, 0 ] } } }, width=path_thickness_pixels) mig_path.point = pt mig_path.path = path self.doc.packets.append(mig_path) count += 1 if self._verbose: print("CZMLWriter.add_vector_migrations: %d migrations added." %\ count) return count
def add_migrations(self, migrations, demographics, with_altitude=False): """Adds migration animations to a CZML output. This function, given migrations in a particular format and demographics, adds "comet" animations for migration events. Returns: Number of infected human migrations in animation layer Args: migrations (obj): An object that describes migrations (see below) demographics (Demographics): A Demographics object describing nodes with_altitude: True to respect the altitude in the node coordinates migrations is a dictionary where the keys are <timestep> and the values are objects with keys <from_node_id>-<to_node_id> and the values are the number of migrations at that timestep from from_node_id to to_node_id. See MigrationHelpers.py for more details. Todo: * Color customization (comet heads, comet tails) * Duration customization (comet tails) """ count = 0 for timestep in list(migrations.keys()): timestep_rec = migrations[timestep] for migration_key in list(timestep_rec.keys()): from_node_id, to_node_id = migration_key.split("-") if not (from_node_id in demographics and to_node_id in demographics): continue from_node = demographics[from_node_id] to_node = demographics[to_node_id] availability = self._timestep_to_iso(timestep) + "/" +\ self._timestep_to_iso(int(timestep) + CZMLWriter.k_default_migration_duration_days) id_txt = "%s_%d" % (migration_key, count) # The thing to remember about paths is that their initial # duration is going to be availability, but then they are going # to be around for an *additional* trailTime seconds. So the # color fade in the path needs to run for dur_seconds + # trailTime. mig_path = czml.CZMLPacket( id=id_txt, availability=availability, position={ "epoch": self._timestep_to_iso(timestep), "cartographicDegrees": [ 0, # seconds from_node["NodeAttributes"]["Longitude"], from_node["NodeAttributes"]["Latitude"], from_node["NodeAttributes"]["Altitude"] if with_altitude else 0, CZMLWriter.k_default_migration_duration_seconds, to_node["NodeAttributes"]["Longitude"], to_node["NodeAttributes"]["Latitude"], to_node["NodeAttributes"]["Altitude"] if with_altitude else 0 ] }) pt = czml.Point( pixelSize=10, show=True, color={ "epoch": self._timestep_to_iso(timestep), "rgba": [ 0, 186, 127, 183, 255, CZMLWriter.k_default_migration_duration_seconds, 186, 127, 183, 0 ] }) path = czml.Path( leadTime=0, trailTime=60 * 60 * 12, # half-day resolution=CZMLWriter.k_default_clock_multiplier, material={ "solidColor": { "color": { "epoch": self._timestep_to_iso(timestep), "rgba": [ 0, 255, 255, 255, 255, CZMLWriter. k_default_migration_duration_seconds + 60 * 60 * 12, 255, 255, 255, 0 ] } } }, width=2.5) mig_path.point = pt mig_path.path = path self.doc.packets.append(mig_path) count += 1 if self._verbose: print("CZMLWriter.add_migrations: %d migrations added." % count) return count
def add_nodes(self, demographics, population_as_size=True, with_altitude=False, processor=None, namer=None): """Add demographics node data to the CZMLWriter object. DEPRECATED. This (DEPRECATED) method allows you to add node representations to a CZML output file, where the node point size is relative to the node's InitialPopulation. Since the Vis-Tools client does this in a much more flexible way, this method is deprecated, but may be educational for those looking to extend the CZMLWriter class. Returns: None Args: demographics (Demographics) A Demographics object with node data. population_as_size (bool): True to scale point size by InitialPopulation, fixed size otherwise with_altitude: True to emit node coordinates including their altitude, false to just emit them with default altitude processor: None or a function that processes the node and and the czml wrapper into a new CZML packet. namer: None or a function that converts a node into a name string """ pop_adjusted_max = demographics.calc_adjusted_pop_max() pop_range = pop_adjusted_max - demographics.population_min size_px_min = 6 size_px_max = 32 size_range = size_px_max - size_px_min for node in demographics.Nodes: name = repr(node["NodeID"]) if namer is not None: name = namer(node, name) attrs = node["NodeAttributes"] lon = attrs["Longitude"] lat = attrs["Latitude"] alt = attrs["Altitude"] if with_altitude else 0 if processor is None: packet = czml.CZMLPacket( id=name, name=name, position={"cartographicDegrees": [lon, lat, alt]}) size = CZMLWriter.k_default_node_point_size if population_as_size: pop = attrs["InitialPopulation"] if pop > pop_adjusted_max: pop = pop_adjusted_max norm_pop = (pop - demographics.population_min) / pop_range size = size_px_min + norm_pop * size_range # show=True is required below packet.point = czml.Point(pixelSize=size, show=True) else: packet = processor(self, czml, node) self.doc.packets.append(packet) if self._verbose: print("CZMLWriter.add_nodes: Added %s node%s" %\ (len(demographics.Nodes), "" if len(demographics.Nodes) == 1 else "s"))
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)