Welcome!
This is the community forum for my apps Pythonista and Editorial.
For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.
Interactive visualization
-
Hello everyone, I am working with python quite a while now and am now faced with the task to program an interactive map visualization over time. I am working at an NGO which supports children in Uganda and we want to visualize all supported children and projects over time on a map of the area (animated). Furthermore some information about the projects (since when, how it helped) and children (age, supported since, etc.) should be shown when hovering or kicking the according dot on ths map. Which libraries and other things do you recommend for this project? Data is stored and edited as a CSV file including coordinates and other important information. Thank you for your help!
-
@RichardSmith see an example here
-
Easier way to begin
-
@RichardSmith, I know this might sound odd in our forum, but if this is something you need to work on PCs and maybe send to others etc., I would suggest the map features of Excel.
-
@mikael said:
if this is something you need to work on PCs
In this case, I agree but if he already knows Python and asks it for Pythonista...
-
@RichardSmith Shortest script
import console from objc_util import * import ctypes import ui class CLLocationCoordinate2D (Structure): _fields_ = [('latitude', c_double), ('longitude', c_double)] class MKCoordinateSpan (Structure): _fields_ = [('d_lat', c_double), ('d_lon', c_double)] class MKCoordinateRegion (Structure): _fields_ = [('center', CLLocationCoordinate2D), ('span', MKCoordinateSpan)] MKPointAnnotation = ObjCClass('MKPointAnnotation') MKPinAnnotationView = ObjCClass('MKPinAnnotationView') MKAnnotationView = ObjCClass('MKAnnotationView') UIColor = ObjCClass('UIColor') # used to set pin color def mapView_viewForAnnotation_(self,cmd,mk_mapview,mk_annotation): try: # not specially called in the same sequence as pins created # should have one MK(Pin)AnnotationView by type (ex: pin color) annotation = ObjCInstance(mk_annotation) mapView = ObjCInstance(mk_mapview) if annotation.isKindOfClass_(MKPointAnnotation): tit = str(annotation.title()) subtit = str(annotation.subtitle()) pin_color = annotation.pin_color id = tit pinView = mapView.dequeueReusableAnnotationViewWithIdentifier_(id) if not pinView: pinView = MKPinAnnotationView.alloc().initWithAnnotation_reuseIdentifier_(annotation,id) pinView.canShowCallout = True # tap-> show title pinView.animatesDrop = False # not Animated pin falls like a drop pinView.pinColor = pin_color # 0=red 1=green 2=purple else: pinView.annotation = annotation return pinView.ptr return None except Exception as e: print('Error on line {}'.format(sys.exc_info()[-1].tb_lineno), type(e).__name__, e) # Build method of MKMapView Delegate methods = [mapView_viewForAnnotation_] protocols = ['MKMapViewDelegate'] try: MyMapViewDelegate = ObjCClass('MyMapViewDelegate') except Exception as e: MyMapViewDelegate = create_objc_class('MyMapViewDelegate', methods=methods, protocols=protocols) #MyMapViewDelegate = create_objc_class('MyMapViewDelegate', NSObject, methods=methods, protocols=protocols) class MapView(ui.View): @on_main_thread def __init__(self, *args, **kwargs): ui.View.__init__(self, *args, **kwargs) MKMapView = ObjCClass('MKMapView') frame = CGRect(CGPoint(0, 0), CGSize(self.width, self.height)) self.mk_map_view = MKMapView.alloc().initWithFrame_(frame) flex_width, flex_height = (1<<1), (1<<4) self.mk_map_view.setAutoresizingMask_(flex_width|flex_height) self_objc = ObjCInstance(self) self_objc.addSubview_(self.mk_map_view) self.mk_map_view.release() # Set Delegate of mk_map_view map_delegate = MyMapViewDelegate.alloc().init()#.autorelease() self.mk_map_view.setDelegate_(map_delegate) @on_main_thread def add_pin(self, lat, lon, color, title, subtitle): global all_points '''Add a pin annotation to the map''' MKPointAnnotation = ObjCClass('MKPointAnnotation') coord = CLLocationCoordinate2D(lat, lon) all_points.append(coord) # store all pin's for MKPolyline annotation = MKPointAnnotation.alloc().init().autorelease() annotation.setTitle_(title) annotation.setSubtitle_(str(subtitle)) annotation.setCoordinate_(coord, restype=None, argtypes=[CLLocationCoordinate2D]) annotation.pin_color = color self.mk_map_view.addAnnotation_(annotation) @on_main_thread def set_region(self, lat, lon, d_lat, d_lon, animated=False): '''Set latitude/longitude of the view's center and the zoom level (specified implicitly as a latitude/longitude delta)''' region = MKCoordinateRegion(CLLocationCoordinate2D(lat, lon), MKCoordinateSpan(d_lat, d_lon)) self.mk_map_view.setRegion_animated_(region, animated, restype=None, argtypes=[MKCoordinateRegion, c_bool]) def main(): global all_points #----- Main process ----- console.clear() # Hide script back = MapView() back.background_color='white' back.name = 'Test for @RichardSmith' back.present('fullscreen', hide_title_bar=False) map_points = [] # assume infos come from a CSV file map_points.append((0.5830414, 32.5316170, 0, 'Yoweri Museveni', '12 years, supported since 01/02/2019')) map_points.append((0.2986261, 32.6033583, 1, "The Uganda National N.G.O Forum", 'since 1997, Providing a Sharing and Reflection Platform for NGOs in Uganda')) # min and max of latitude and longitude min_lat = min(map_points,key = lambda x:x[0])[0] max_lat = max(map_points,key = lambda x:x[0])[0] min_lon = min(map_points,key = lambda x:x[1])[1] max_lon = max(map_points,key = lambda x:x[1])[1] # Display map, center and zoom so all points are visible back.set_region((min_lat+max_lat)/2,(min_lon+max_lon)/2, 4*(max_lat-min_lat), 4*(max_lon-min_lon), animated=True) # Display pin's all_points = [] for point in map_points: back.add_pin(point[0],point[1],point[2],point[3],point[4]) # Protect against import if __name__ == '__main__': main()
-
Add these lines if you want multiple lines in the subtitle
. . . pinView.pinColor = pin_color # 0=red 1=green 2=purple # add these lines if you want several lines in subtitle: begin l_title = ui.Label() l_title.font = ('Menlo',12) # police echappement fixe lo = ObjCInstance(l_title) l_title.text = subtit.replace(',','\n') lo.setNumberOfLines_(0) pinView.setDetailCalloutAccessoryView_(lo) # add these lines if you want several lines in subtitle: end
-
This post is deleted!