def plot_demo_dataset(d, panels): # Create a scatterplot representation of the dataset, and add the necessary transforms # to get the data to the plot. In this case, it's a simple filter on the plot bounds, and # distribution to all the scatter artists. Might also add map projection here if the plot # were not directly showing lat, lon, alt. # Set up dataset -> time-height bound filter -> brancher branch = Branchpoint([]) brancher = branch.broadcast() # strictly speaking, z in the map projection and MSL alt aren't the same - z is somewhat distorted by the projection. # therefore, add some padding. filtered again later after projection. transform_mapping = {'z':('alt', (lambda v: (v[0]*1.0e3 - 1.0e3, v[1]*1.0e3 + 1.0e3)) ) } bound_filter = BoundsFilter(target=brancher, bounds=panels.bounds, restrict_to=('time'), transform_mapping=transform_mapping) filterer = bound_filter.filter() d.target = filterer # Set up brancher -> coordinate transform -> final_filter -> mutli-axis scatter updater scatter_ctrl = PanelsScatterController(panels=panels, color_field='time') scatter_outlet_broadcaster = scatter_ctrl.branchpoint scatter_updater = scatter_outlet_broadcaster.broadcast() final_bound_filter = BoundsFilter(target=scatter_updater, bounds=panels.bounds) final_filterer = final_bound_filter.filter() cs_transformer = panels.cs.project_points(target=final_filterer, x_coord='x', y_coord='y', z_coord='z', lat_coord='lat', lon_coord='lon', alt_coord='alt', distance_scale_factor=1.0e-3) branch.targets.add(cs_transformer) # return each broadcaster so that other things can tap into results of transformation of this dataset return branch, scatter_outlet_broadcaster
def length_stats_for_intervals(t_start, t_end, dt, D, b_s, chi2=5.0, stations=5): """ """ t_edges, duration = time_edges(t_start, t_end, dt.total_seconds()) t_ref, t_edges_seconds = seconds_since_start_of_day(t_start, t_edges) n_frames = len(t_edges) - 1 max_alt, d_alt = 20.0, 0.5 alt_bins = np.arange(0.0, max_alt + d_alt, d_alt) results_aggregator = StatResults(alt_bins, basedate=t_ref) all_frame_targets = [] for n in range(n_frames): t0, t1 = t_edges_seconds[n:n + 2] statframer = results_aggregator.timeframe_results_rcvr() this_frame = in_time_range(t0, t1, statframer) all_frame_targets.append(this_frame) brancher = Branchpoint(all_frame_targets) ev_fl_rcvr = length_for_these_flashes(D, b_s, alt_bins, chi2=chi2, stations=stations, target=brancher.broadcast()) return ev_fl_rcvr, all_frame_targets, results_aggregator
def pipeline_for_dataset(self, d, panels): # Set up dataset -> time-height bound filter -> brancher branch = Branchpoint([]) brancher = branch.broadcast() # strictly speaking, z in the map projection and MSL alt aren't the same - z is somewhat distorted by the projection. # therefore, add some padding. filtered again later after projection. quality_filter = BoundsFilter(target=brancher, bounds=self.bounds).filter() transform_mapping = {'z':('alt', (lambda v: (v[0]*1.0e3 - 1.0e3, v[1]*1.0e3 + 1.0e3)) ) } bound_filter = BoundsFilter(target=quality_filter, bounds=panels.bounds, restrict_to=('time'), transform_mapping=transform_mapping) filterer = bound_filter.filter() d.target = filterer # Set up brancher -> coordinate transform -> final_filter -> mutli-axis scatter updater scatter_ctrl = PanelsScatterController( panels=panels, color_field='time', default_color_bounds=self.default_color_bounds) scatter_outlet_broadcaster = scatter_ctrl.branchpoint scatter_updater = scatter_outlet_broadcaster.broadcast() final_bound_filter = BoundsFilter(target=scatter_updater, bounds=panels.bounds) final_filterer = final_bound_filter.filter() cs_transformer = panels.cs.project_points( target=final_filterer, x_coord='x', y_coord='y', z_coord='z', lat_coord='lat', lon_coord='lon', alt_coord='alt', distance_scale_factor=1.0e-3) branch.targets.add(cs_transformer) # return each broadcaster so that other things can tap into results of transformation of this dataset return branch, scatter_ctrl
def flash_stats_for_dataset(self, d, selection_broadcaster): flash_stat_branchpoint = Branchpoint([self.flash_stat_printer()]) flash_stat_brancher = flash_stat_branchpoint.broadcast() @coroutine def flash_data_for_selection(target, flash_id_key = 'flash_id'): """ Accepts an array of event data from the pipeline, and sends event and flash data. """ while True: ev = (yield) # array of event data try: fl_dat = d.flash_data flash_ids = set(ev[flash_id_key]) flashes = np.fromiter( (fl for fl in fl_dat if fl[flash_id_key] in flash_ids), dtype=fl_dat.dtype) except AttributeError: # There are no flash data in the dataset flashes = None target.send((ev, flashes)) selection_broadcaster.targets.add(flash_data_for_selection(flash_stat_brancher)) return flash_stat_branchpoint
def pipeline_for_dataset(self, d, panels, names4d=('lon', 'lat', 'alt', 'time'), transform_mapping=None, scatter_kwargs = {} ): """ Set 4d_names to the spatial coordinate names in d that provide longitude, latitude, altitude, and time. Default of lon, lat, alt, and time which are assumed to be in deg, deg, meters, seconds entries in the scatter_kwargs dictionary are passed as kwargs to the matplotlib scatter call. """ # Set up dataset -> time-height bound filter -> brancher branch = Branchpoint([]) brancher = branch.broadcast() # strictly speaking, z in the map projection and MSL alt aren't the same - z is somewhat distorted by the projection. # therefore, add some padding. filtered again later after projection. quality_filter = BoundsFilter(target=brancher, bounds=self.bounds).filter() if transform_mapping is None: transform_mapping = self.z_alt_mapping # Use 'time', which is the name in panels.bounds, and not names4d[3], which should # is linked to 'time' by transform_mapping if necessary bound_filter = BoundsFilter(target=quality_filter, bounds=panels.bounds, restrict_to=('time'), transform_mapping=transform_mapping) filterer = bound_filter.filter() d.target = filterer # Set up brancher -> coordinate transform -> final_filter -> mutli-axis scatter updater scatter_ctrl = PanelsScatterController( panels=panels, color_field=names4d[3], default_color_bounds=self.default_color_bounds, **scatter_kwargs) scatter_outlet_broadcaster = scatter_ctrl.branchpoint scatter_updater = scatter_outlet_broadcaster.broadcast() final_bound_filter = BoundsFilter(target=scatter_updater, bounds=panels.bounds) final_filterer = final_bound_filter.filter() cs_transformer = panels.cs.project_points( target=final_filterer, x_coord='x', y_coord='y', z_coord='z', lat_coord=names4d[1], lon_coord=names4d[0], alt_coord=names4d[2], distance_scale_factor=1.0e-3) branch.targets.add(cs_transformer) # return each broadcaster so that other things can tap into results of transformation of this dataset return branch, scatter_ctrl
def scatter_dataset_on_panels(panels, color_field=None): bounds_updated_xchg = get_exchange('SD_bounds_updated') all_outlets = [] empty = [ 0, ] for ax in panels.ax_specs: # create a new scatter artist art = ax.scatter(empty, empty, c=empty, s=4, marker='s', edgecolors='none') # Need to update the color mapping using the specified color field. It needs to know that the # bounds have been updated in order to adjust the color limits. up = MappableRangeUpdater(art, color_field=color_field) bounds_updated_xchg.attach(up) # Need to update the actual scatter coordinate data on each scatter artist outlet = ScatterArtistOutlet(art, coord_names=panels.ax_specs[ax], color_field=color_field) all_outlets.append(outlet.update()) brancher = Branchpoint(all_outlets) return brancher
def pipeline_for_dataset(self, d, panels, marker='s'): # Set up dataset -> time-height bound filter -> brancher branch = Branchpoint([]) brancher = branch.broadcast() # strictly speaking, z in the map projection and MSL alt aren't the same - z is somewhat distorted by the projection. # therefore, add some padding. filtered again later after projection. # quality_filter = BoundsFilter(target=brancher, bounds=self.bounds).filter() transform_mapping = {'z':('alt', (lambda v: (v[0]*1.0e3 - 1.0e3, v[1]*1.0e3 + 1.0e3)) ) } # make the target in the line below quality_filter to add additional data-dependent # filtering. bound_filter = BoundsFilter(target=brancher, bounds=panels.bounds, restrict_to=('time'), transform_mapping=transform_mapping) filterer = bound_filter.filter() # Adjust the height in response to bounds changes, so that the markers stay near # the bottom axis in a time-height view height_control = GroundMarkerHeightController(target=filterer, alt_name='alt') height_adjuster = height_control.adjust_height() d.target = height_adjuster # Set up brancher -> coordinate transform -> final_filter -> mutli-axis scatter updater scatter_ctrl = PanelsScatterController( panels=panels, s=64, color_field='time', marker=marker) #default_color_bounds=self.default_color_bounds) scatter_outlet_broadcaster = scatter_ctrl.branchpoint scatter_updater = scatter_outlet_broadcaster.broadcast() final_bound_filter = BoundsFilter(target=scatter_updater, bounds=panels.bounds) final_filterer = final_bound_filter.filter() cs_transformer = panels.cs.project_points( target=final_filterer, x_coord='x', y_coord='y', z_coord='z', lat_coord='lat', lon_coord='lon', alt_coord='alt', distance_scale_factor=1.0e-3) branch.targets.add(cs_transformer) # return each broadcaster so that other things can tap into results of transformation of this dataset return branch, scatter_ctrl
def plot_demo_dataset(d, panels): # Create a scatterplot representation of the dataset, and add the necessary transforms # to get the data to the plot. In this case, it's a simple filter on the plot bounds, and # distribution to all the scatter artists. Might also add map projection here if the plot # were not directly showing lat, lon, alt. # Set up dataset -> time-height bound filter -> brancher branch = Branchpoint([]) brancher = branch.broadcast() # strictly speaking, z in the map projection and MSL alt aren't the same - z is somewhat distorted by the projection. # therefore, add some padding. filtered again later after projection. transform_mapping = {"z": ("alt", (lambda v: (v[0] * 1.0e3 - 1.0e3, v[1] * 1.0e3 + 1.0e3)))} bound_filter = BoundsFilter( target=brancher, bounds=panels.bounds, restrict_to=("time"), transform_mapping=transform_mapping ) filterer = bound_filter.filter() d.target = filterer # Set up brancher -> coordinate transform -> final_filter -> mutli-axis scatter updater scatter_ctrl = PanelsScatterController(panels=panels, color_field="time") scatter_outlet_broadcaster = scatter_ctrl.branchpoint scatter_updater = scatter_outlet_broadcaster.broadcast() final_bound_filter = BoundsFilter(target=scatter_updater, bounds=panels.bounds) final_filterer = final_bound_filter.filter() cs_transformer = panels.cs.project_points( target=final_filterer, x_coord="x", y_coord="y", z_coord="z", lat_coord="lat", lon_coord="lon", alt_coord="alt", distance_scale_factor=1.0e-3, ) branch.targets.add(cs_transformer) # return each broadcaster so that other things can tap into results of transformation of this dataset return branch, scatter_outlet_broadcaster
def flash_stats_for_dataset(self, d, selection_broadcaster): flash_stat_branchpoint = Branchpoint([self.flash_stat_printer()]) flash_stat_brancher = flash_stat_branchpoint.broadcast() @coroutine def flash_data_for_selection(target, flash_id_key = 'flash_id'): """ Accepts an array of event data from the pipeline, and sends event and flash data. """ while True: ev = (yield) # array of event data fl_dat = d.flash_data flash_ids = set(ev[flash_id_key]) flashes = np.fromiter( (fl for fl in fl_dat if fl[flash_id_key] in flash_ids), dtype=fl_dat.dtype) target.send((ev, flashes)) selection_broadcaster.targets.add(flash_data_for_selection(flash_stat_brancher)) return flash_stat_branchpoint
def __init__(self, panels, color_field='time', default_color_bounds=None, s=4, antialiased=False, **kwargs): """ *panels* is a LinkedPanels instance. extra kwargs are passed to the call to scatter""" if default_color_bounds is None: default_color_bounds = Bounds() self.default_color_bounds = default_color_bounds self.mappable_updaters = set() self.color_field = color_field self.panels = panels self.artist_outlet_controllers = set() bounds_updated_xchg = get_exchange('SD_bounds_updated') artist_outlets = [] empty = [ 0, ] for ax in panels.ax_specs: # create a new scatter artist art = ax.scatter(empty, empty, c=empty, s=s, edgecolors='none', antialiased=antialiased, **kwargs) # Need to update the color mapping using the specified color field. It needs to know that the # bounds have been updated in order to adjust the color limits. up = MappableRangeUpdater(art, color_field=color_field, default_bounds=default_color_bounds) bounds_updated_xchg.attach(up) self.mappable_updaters.add(up) # Need to update the actual scatter coordinate data on each scatter artist outlet = ScatterArtistOutlet(art, coord_names=panels.ax_specs[ax], color_field=color_field) self.artist_outlet_controllers.add(outlet) self.mappable_updaters.add(outlet) artist_outlets.append(outlet.update()) self.artist_outlets = artist_outlets self.branchpoint = Branchpoint(artist_outlets)
def length_stats_for_intervals(t_start, t_end, dt, D, b_s, chi2=5.0, stations=5): """ """ t_edges, duration = time_edges(t_start, t_end, dt.total_seconds()) t_ref, t_edges_seconds = seconds_since_start_of_day(t_start, t_edges) n_frames = len(t_edges)-1 max_alt, d_alt = 20.0, 0.5 alt_bins = np.arange(0.0,max_alt+d_alt, d_alt) results_aggregator = StatResults(alt_bins, basedate=t_ref) all_frame_targets = [] for n in range(n_frames): t0, t1 = t_edges_seconds[n:n+2] statframer = results_aggregator.timeframe_results_rcvr() this_frame = in_time_range(t0, t1, statframer) all_frame_targets.append(this_frame) brancher = Branchpoint(all_frame_targets) ev_fl_rcvr = length_for_these_flashes(D, b_s, alt_bins, chi2=chi2, stations=stations, target=brancher.broadcast()) return ev_fl_rcvr, all_frame_targets, results_aggregator
], dtype=[('name', '|S32'), ('lat', '>f4'), ('lon', '>f4'), ('alt', '>f4'), ('time', '>f4')]) # Create a dataset that stores numpy named array data, and automatically receives updates # when the bounds of a plot changes. d = NamedArrayDataset(data) # Create a scatterplot representation of the dataset, and add the necessary transforms # to get the data to the plot. In this case, it's a simple filter on the plot bounds, and # distribution to all the scatter artists. Might also add map projection here if the plot # were not directly showing lat, lon, alt. scatter_ctrl = PanelsScatterController(panels=panels, color_field='time') scatter_outlet_broadcaster = scatter_ctrl.branchpoint scatter_updater = scatter_outlet_broadcaster.broadcast() branch = Branchpoint([ scatter_updater, ]) brancher = branch.broadcast() bound_filter = BoundsFilter(target=brancher, bounds=panels.bounds) filterer = bound_filter.filter() d.target = filterer # Set an initial view. panels.panels['xy'].axis((-110, -90, 30, 40)) panels.panels['tz'].axis((0, 10, 0, 5e3)) # Shouldn't need these, since the previous two cover all coordinates # panels.panels['zy'].axis((0, 5e3, 30, 40,)) # panels.panels['xz'].axis((-110, -90, 0, 5e3)) # Now let's set up a second figure that has projected data. The unprojected axes act # as the master data controller, and control what data get re-flowed to the other plot.
('Very Large Array', 34.079, -107.618, 2126., 4.23 ), ], dtype = [ ('name', '|S32'), ('lat', '>f4'), ('lon', '>f4'), ('alt', '>f4'), ('time', '>f4') ] ) # Create a dataset that stores numpy named array data, and automatically receives updates # when the bounds of a plot changes. d = NamedArrayDataset(data) # Create a scatterplot representation of the dataset, and add the necessary transforms # to get the data to the plot. In this case, it's a simple filter on the plot bounds, and # distribution to all the scatter artists. Might also add map projection here if the plot # were not directly showing lat, lon, alt. scatter_ctrl = PanelsScatterController(panels=panels, color_field='time') scatter_outlet_broadcaster = scatter_ctrl.branchpoint scatter_updater = scatter_outlet_broadcaster.broadcast() branch = Branchpoint([scatter_updater,]) brancher = branch.broadcast() bound_filter = BoundsFilter(target=brancher, bounds=panels.bounds) filterer = bound_filter.filter() d.target = filterer # Set an initial view. panels.panels['xy'].axis((-110, -90, 30, 40)) panels.panels['tz'].axis((0, 10, 0, 5e3)) # Shouldn't need these, since the previous two cover all coordinates # panels.panels['zy'].axis((0, 5e3, 30, 40,)) # panels.panels['xz'].axis((-110, -90, 0, 5e3)) # Now let's set up a second figure that has projected data. The unprojected axes act