예제 #1
0
    def _visdata(self):
        self._setcolors()

        datasets = []
        if isinstance(pytplot.data_quants[self.tvar_name].data, list):
            for oplot_name in pytplot.data_quants[self.tvar_name].data:
                datasets.append(pytplot.data_quants[oplot_name])
        else:
            datasets.append(pytplot.data_quants[self.tvar_name])

        for dataset in datasets:
            #Get Linestyle
            line_style = None
            if 'linestyle' in pytplot.data_quants[self.tvar_name].extras:
                line_style = pytplot.data_quants[
                    self.tvar_name].extras['linestyle']

            #Get a list of formatted times
            corrected_time = []
            for x in dataset.data.index:
                corrected_time.append(tplot_utilities.int_to_str(x))

            #Bokeh uses milliseconds since epoch for some reason
            x = dataset.data.index * 1000

            #Create lines from each column in the dataframe
            for column_name in dataset.data.columns:
                y = dataset.data[column_name]

                if self._getyaxistype() == 'log':
                    y.loc[y <= 0] = np.NaN

                line_source = ColumnDataSource(
                    data=dict(x=x, y=y, corrected_time=corrected_time))
                if self.auto_color:
                    line = Line(x='x',
                                y='y',
                                line_color=self.colors[self.linenum %
                                                       len(self.colors)],
                                **pytplot.data_quants[self.tvar_name].line_opt)
                else:
                    line = Line(x='x',
                                y='y',
                                **pytplot.data_quants[self.tvar_name].line_opt)
                if 'line_style' not in pytplot.data_quants[
                        self.tvar_name].line_opt:
                    if line_style is not None:
                        line.line_dash = line_style[self.linenum %
                                                    len(line_style)]
                else:
                    line.line_dash = pytplot.data_quants[
                        self.tvar_name].line_opt['line_style']
                self.lineglyphs.append(self.fig.add_glyph(line_source, line))
                self.linenum += 1
예제 #2
0
    def _visdata(self):
        self._setcolors()

        x = pytplot.data_quants[self.tvar_name].data.index.tolist()
        temp = [
            a for a in x if (a <= (pytplot.tplot_opt_glob['x_range'][1])
                             and a >= (pytplot.tplot_opt_glob['x_range'][0]))
        ]
        x = temp

        #Sometimes X will be huge, we'll need to cut down so that each x will stay about 1 pixel in size
        step_size = 1
        num_rect_displayed = len(x)
        if (self.fig.plot_width) < num_rect_displayed:
            step_size = int(
                math.floor(num_rect_displayed / (self.fig.plot_width)))
            x[:] = x[0::step_size]

        #Determine bin sizes
        if pytplot.data_quants[self.tvar_name].spec_bins is not None:
            bins = pytplot.data_quants[self.tvar_name].spec_bins
            bins_vary = pytplot.data_quants[
                self.tvar_name].spec_bins_time_varying
            bins_increasing = pytplot.data_quants[
                self.tvar_name].spec_bins_ascending
        else:
            bins = pd.DataFrame(
                np.arange(len(pytplot.data_quants[
                    self.tvar_name].data.columns))).transpose()
            bins_vary = False
            bins_increasing = True
        #Get length of arrays
        size_x = len(x)
        size_y = len(bins.columns)

        #These arrays will be populated with data for the rectangle glyphs
        color = []
        bottom = []
        top = []
        left = []
        right = []
        value = []
        corrected_time = []

        #left, right, and time do not depend on the values in spec_bins
        for j in range(size_x - 1):
            left.append(x[j] * 1000)
            right.append(x[j + 1] * 1000)
            corrected_time.append(tplot_utilities.int_to_str(x[j]))

        left = left * (size_y - 1)
        right = right * (size_y - 1)
        corrected_time = corrected_time * (size_y - 1)

        #Handle the case of time-varying bin sizes
        if bins_vary:
            temp_bins = bins.loc[x[0:size_x - 1]]
        else:
            temp_bins = bins.loc[0]

        if bins_increasing:
            bin_index_range = range(0, size_y - 1, 1)
        else:
            bin_index_range = range(size_y - 1, 0, -1)

        for i in bin_index_range:
            temp = pytplot.data_quants[self.tvar_name].data[i][x[0:size_x -
                                                                 1]].tolist()
            value.extend(temp)
            color.extend(
                tplot_utilities.get_heatmap_color(color_map=self.colors[0],
                                                  min_val=self.zmin,
                                                  max_val=self.zmax,
                                                  values=temp,
                                                  zscale=self.zscale))

            #Handle the case of time-varying bin sizes
            if bins_vary:
                bottom.extend(temp_bins[i].tolist())
                if bins_increasing:
                    top.extend(temp_bins[i + 1].tolist())
                else:
                    top.extend(temp_bins[i - 1].tolist())
            else:
                bottom.extend([temp_bins[i]] * (size_x - 1))
                if bins_increasing:
                    top.extend([temp_bins[i + 1]] * (size_x - 1))
                else:
                    top.extend([temp_bins[i - 1]] * (size_x - 1))

        #Here is where we add all of the rectangles to the plot
        cds = ColumnDataSource(data=dict(x=left,
                                         y=bottom,
                                         right=right,
                                         top=top,
                                         z=color,
                                         value=value,
                                         corrected_time=corrected_time))

        self.fig.quad(bottom='y',
                      left='x',
                      right='right',
                      top='top',
                      color='z',
                      source=cds)

        if self.interactive:
            if 'y_axis_type' in pytplot.data_quants[self.tvar_name].yaxis_opt:
                y_interactive_log = 'log'
            else:
                y_interactive_log = 'linear'
            self.interactive_plot = Figure(plot_height=self.fig.plot_height,
                                           plot_width=self.fig.plot_width,
                                           y_range=(self.zmin, self.zmax),
                                           y_axis_type=y_interactive_log)
            self.interactive_plot.min_border_left = 100
            spec_bins = bins
            flux = [0] * len(spec_bins)
            interactive_line_source = ColumnDataSource(
                data=dict(x=spec_bins, y=flux))
            interactive_line = Line(x='x', y='y')
            self.interactive_plot.add_glyph(interactive_line_source,
                                            interactive_line)
            self.callback = CustomJS(args=dict(
                cds=cds, interactive_line_source=interactive_line_source),
                                     code="""
                    var geometry = cb_data['geometry'];
                    var x_data = geometry.x; // current mouse x position in plot coordinates
                    var y_data = geometry.y; // current mouse y position in plot coordinates
                    var d2 = interactive_line_source.get('data');
                    var asdf = cds.get('data');
                    var j = 0;
                    x=d2['x']
                    y=d2['y']
                    time=asdf['x']
                    energies=asdf['y']
                    flux=asdf['value']
                    for (i = 0; i < time.length-1; i++) {
                        if(x_data >= time[i] && x_data <= time[i+1] ) {
                            x[j] = energies[i]
                            y[j] = flux[i]
                            j=j+1
                        }
                    }
                    j=0
                    interactive_line_source.trigger('change');
                """)
예제 #3
0
def static2dplot(var, time):
    """ If the static option is set in tplot, and is supplied with a time, then the spectrogram plot(s) for which
    it is set will have another window pop up, with y and z values plotted at the specified time. """

    # Grab names of data loaded in as tplot variables.
    names = list(pytplot.data_quants.keys())
    # Get data we'll actually work with here.
    valid_variables = tplot_utilities.get_data(names)

    # Don't plot anything unless we have spectrograms with which to work.
    if valid_variables:
        # Get z label
        labels = tplot_utilities.get_labels_axis_types(names)

        # Put together data in easy-to-access format for plots.
        data = {}
        for name in valid_variables:
            bins = tplot_utilities.get_bins(name)
            time_values, z_values = tplot_utilities.get_z_t_values(name)
            data[name] = [bins, z_values, time_values]

        # Set up the 2D static plot
        pytplot.static_window = pg.GraphicsWindow()
        pytplot.static_window.resize(1000, 600)
        pytplot.static_window.setWindowTitle('Static Window')
        plot = pytplot.static_window.addPlot(title='2D Static Plot',
                                             row=0,
                                             col=0)
        # Make it so that whenever this first starts up, you just have an empty plot
        plot_data = plot.plot([], [])

        if var in valid_variables:
            # Get min/max values of data's time range (in both datetime and seconds since epoch)
            t_min = np.nanmin(time_values)
            t_min_str = tplot_utilities.int_to_str(np.nanmin(time_values))
            t_min_conv_back = tplot_utilities.str_to_int(t_min_str)
            t_max = np.nanmax(time_values)
            t_max_str = tplot_utilities.int_to_str(np.nanmax(time_values))
            t_max_conv_back = tplot_utilities.str_to_int(t_max_str)
            # Convert user input to seconds since epoch
            user_time = tplot_utilities.str_to_int(time)

            # Covering situation where user entered a time not in the dataset!
            # As long as they used a time in the dataset, this will not trigger.
            if user_time not in range(t_min_conv_back, t_max_conv_back + 1):
                while True:
                    try:
                        user_time = tplot_utilities.str_to_int(
                            input(
                                'Chosen time not in range of data [{} to {}]. Input new time (%Y-%m-%d %H:%M:%S). '
                                .format(t_min_str, t_max_str)))
                    except:
                        continue
                    else:
                        if user_time not in range(int(t_min), int(t_max)):
                            continue
                        else:
                            break

            # Get time closest to the user's time choice
            time_array = np.array(data[var][2])
            array = np.asarray(time_array)
            idx = (np.abs(array - user_time)).argmin()
            # If user indicated they wanted the interactive plot's axes to be logged, log 'em.
            # But first make sure that values in x and y are loggable!
            x_axis = False
            y_axis = False
            # Checking x axis
            if np.nanmin(data[name][0][:]) < 0:
                print('Negative data is incompatible with log plotting.')
            elif np.nanmin(data[name][0][:]) >= 0 and labels[name][2] == 'log':
                x_axis = True
            # Checking y axis
            if np.nanmin(list(data[name][1][idx])) < 0:
                print('Negative data is incompatible with log plotting')
            elif np.nanmin(list(
                    data[name][1][idx])) >= 0 and labels[name][3] == 'log':
                y_axis = True

            # Set plot labels
            plot.setLabel('bottom', '{}'.format(labels[name][0]))
            plot.setLabel('left', '{}'.format(labels[name][1]))
            plot.setLogMode(x=x_axis, y=y_axis)
            # Update x and y range if user modified it
            tplot_utilities.set_x_range(name, x_axis, plot)
            tplot_utilities.set_y_range(name, y_axis, plot)
            # Plot data based on time we're hovering over
            plot_data.setData(data[name][0][:], list(data[name][1][idx]))
예제 #4
0
    def _visdata(self):
        self._setcolors()

        datasets = [pytplot.data_quants[self.tvar_name]]
        for oplot_name in pytplot.data_quants[
                self.tvar_name].attrs['plot_options']['overplots']:
            datasets.append(pytplot.data_quants[oplot_name])

        for dataset in datasets:
            # Get Linestyle
            line_style = None
            if 'linestyle' in pytplot.data_quants[
                    self.tvar_name].attrs['plot_options']['extras']:
                line_style = pytplot.data_quants[self.tvar_name].attrs[
                    'plot_options']['extras']['linestyle']

            # Get a list of formatted times
            corrected_time = []
            for x in dataset.coords['time'].values:
                corrected_time.append(tplot_utilities.int_to_str(x))

            # Bokeh uses milliseconds since epoch for some reason
            x = dataset.coords['time'].values * 1000.0

            # Add region of interest (roi) lines if applicable
            if 'roi_lines' in pytplot.tplot_opt_glob.keys():
                self._set_roi_lines(dataset)

            plot_options = dataset.attrs['plot_options']
            df = pytplot.tplot_utilities.convert_tplotxarray_to_pandas_dataframe(
                dataset.name)

            # Create lines from each column in the dataframe
            for column_name in df.columns:
                y = df[column_name]

                # Account for log plotting
                if self._getyaxistype() == 'log':
                    y.loc[y <= 0] = np.NaN

                if 'line_style' in plot_options['line_opt']:
                    if plot_options['line_opt']['line_style'] == 'scatter':
                        Glyph = X
                    else:
                        Glyph = Line
                else:
                    Glyph = Line
                # Until what size of a data gap are we removing nan values from the dataset? Set by the user
                # (default is to plot as bokeh would normally plot w/o worrying about data gap handling).
                limit = pytplot.tplot_opt_glob['data_gap']
                if limit != 0:
                    # Grabbing the times associated with nan values (nan_values), and the associated "position" of those
                    # keys in the dataset list (nan_keys)
                    nan_values = y[y.isnull().values].index.tolist()
                    nan_keys = [y.index.tolist().index(j) for j in nan_values]

                    nans = dict(zip(nan_keys, nan_values))

                    count = 0  # Keeping a count of how big of a time gap we have
                    consec_list = list(
                    )  # List of consecutive nan values (composed of indices for gaps not bigger than
                    # the user-specified data gap)
                    for val in range(len(nan_keys)):
                        # Avoiding some weird issues with going to the last data point in the nan dictionary keys
                        if val != (len(nan_keys) - 1):
                            # Difference between one index and another - if consecutive indices, the diff will be 1
                            diff = abs(nan_keys[val] - nan_keys[val + 1])
                            # calculate time accumulated from one index to the next
                            t_now = nan_values[val]
                            t_next = nan_values[val + 1]
                            time_accum = abs(t_now - t_next)
                            # If we haven't reached the allowed data gap, just keep track of how big of a gap we're at,
                            # and the indices in the gap
                            if diff == 1 and count < limit:
                                count += time_accum
                                consec_list.append(nan_keys[val])
                            # This triggers when we initially exceed the allowed data gap
                            elif diff == 1 and count >= limit:
                                pass
                            # When we find that the previous index and the current one are not consecutive, stop adding to
                            # the consec_list/overall_list (if applicable), and start over the count of time accumulated
                            # in a gap, as well as the consecutive list of time values with nans
                            elif diff != 1:
                                # Restart the count and add the current val to the list of nan values to remove
                                count = 0
                                consec_list.append(nan_keys[val])

                    times = x.tolist()
                    for elem in consec_list:
                        # Unless the data gap was big enough, we need to remove nan values from the data,
                        # otherwise bokeh will automatically NOT interpolate (the exact opposite of behavior in
                        # pyqtgraph, which ALWAYS interpolates...).
                        times.remove(nans[elem] * 1000.0)
                        del y[nans[elem]]
                        del corrected_time[corrected_time.index(
                            tplot_utilities.int_to_str(nans[elem]))]

                    # Data to be plotted
                    line_source = ColumnDataSource(
                        data=dict(x=times, y=y, corrected_time=corrected_time))
                else:
                    # Data to be plotted
                    line_source = ColumnDataSource(
                        data=dict(x=x, y=y, corrected_time=corrected_time))
                if self.auto_color:
                    line = Glyph(x='x',
                                 y='y',
                                 line_color=self.colors[self.linenum %
                                                        len(self.colors)])
                else:
                    line = Glyph(x='x', y='y')
                if Glyph == Line:
                    if 'line_style' not in plot_options['line_opt']:
                        if line_style is not None:
                            line.line_dash = line_style[self.linenum %
                                                        len(line_style)]
                    else:
                        line.line_dash = plot_options['line_style']
                self.lineglyphs.append(self.fig.add_glyph(line_source, line))
                self.linenum += 1