Example #1
0
 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
Example #2
0
def flash_size_stats_for_intervals(t_start,
                                   t_end,
                                   dt,
                                   lat_bounds=None,
                                   lon_bounds=None,
                                   outdir=None):
    """ Create a pipeline to process an arbitrary number of flashes which are 
        accumulated in dt-length intervals between t_start and t_end.
        
        t_start, t_end: datetime.datetime instances
        dt: datetime.timedelta
        
        Returns:
        printer_of_stats: 
        all_frame_targets: a list of targets that receive (events, flashes) from the flash file reader

        all_frame_targets can be passed as other_analysis_targets to lmatools.flash_stats.plot_spectra_for_files.
        
        When all data have been read (i.e., plot_spectra_for_files has returned), the accumulated statistics are
        retrieved by closing the targets returned by this function, i.e.
            for target in timeframe_targets:
                target.close()
            printer_of_stats.close()
        
        plot_spectra_for_files itself could be refactored to make use of these same time windows natively, but
        that's a project for later. The dependency here on stormdrain is another issue; it may make sense to have
        lmatools depend on stormdrain.
    """
    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

    results = StatResults(basedate=t_ref, outdir=outdir)
    printer_of_stats = results.stats_printer()

    all_frame_targets = []
    for n in range(n_frames):
        # New BoundsFilter object for filtering flashes and flash_stats.stats_for_parameter that sits behind the bounds filter
        t0, t1 = t_edges_seconds[n:n + 2]
        b = Bounds()

        if lat_bounds is not None:
            b.ctr_lat = lat_bounds
        if lon_bounds is not None:
            b.ctr_lon = lon_bounds

        b.start = t0, t1
        statframer = results.stats_for_frame(t_edges[n],
                                             t_edges[n + 1],
                                             target=printer_of_stats)
        momentizer = raw_moments_for_parameter('area',
                                               preprocess=np.sqrt,
                                               output_target=statframer)
        bound_filt = BoundsFilter(bounds=b, target=momentizer)
        ev_fl_rcvr = events_flashes_receiver(target=bound_filt.filter())
        all_frame_targets.append(ev_fl_rcvr)
    return printer_of_stats, all_frame_targets
Example #3
0
 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
Example #4
0
def flash_size_stats_for_intervals(t_start, t_end, dt, lat_bounds=None, lon_bounds=None, outdir=None):
    """ Create a pipeline to process an arbitrary number of flashes which are 
        accumulated in dt-length intervals between t_start and t_end.
        
        t_start, t_end: datetime.datetime instances
        dt: datetime.timedelta
        
        Returns:
        printer_of_stats: 
        all_frame_targets: a list of targets that receive (events, flashes) from the flash file reader

        all_frame_targets can be passed as other_analysis_targets to lmatools.flash_stats.plot_spectra_for_files.
        
        When all data have been read (i.e., plot_spectra_for_files has returned), the accumulated statistics are
        retrieved by closing the targets returned by this function, i.e.
            for target in timeframe_targets:
                target.close()
            printer_of_stats.close()
        
        plot_spectra_for_files itself could be refactored to make use of these same time windows natively, but
        that's a project for later. The dependency here on stormdrain is another issue; it may make sense to have
        lmatools depend on stormdrain.
    """
    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
    
    results = StatResults(basedate=t_ref, outdir=outdir)
    printer_of_stats = results.stats_printer()
    
    all_frame_targets = []
    for n in range(n_frames):
        # New BoundsFilter object for filtering flashes and flash_stats.stats_for_parameter that sits behind the bounds filter
        t0, t1 = t_edges_seconds[n:n+2]
        b = Bounds()
        
        if lat_bounds is not None:
            b.ctr_lat = lat_bounds
        if lon_bounds is not None:
            b.ctr_lon = lon_bounds

        b.start = t0, t1 
        statframer = results.stats_for_frame(t_edges[n], t_edges[n+1], target=printer_of_stats)
        momentizer = raw_moments_for_parameter('area', preprocess=np.sqrt, output_target=statframer)
        bound_filt = BoundsFilter(bounds=b, target=momentizer)
        ev_fl_rcvr = events_flashes_receiver(target=bound_filt.filter())
        all_frame_targets.append(ev_fl_rcvr)
    return printer_of_stats, all_frame_targets
Example #5
0
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
Example #6
0
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
Example #7
0
 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
Example #8
0
 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
Example #9
0
    # 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.

    panel2_fig = plt.figure()
    panels2 = Panels4D(figure=panel2_fig, names_4D=('x', 'y', 'z', 'time'))
Example #10
0
                       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.