def build(z: List[List[float]],
          scale: Union[str, List[List[Union[float, str]]]], path: str):
    """
    Тут будується графік, після чого зображення зберігається у файл.
    """
    figure = Figure()
    figure.add_trace(
        Heatmap(z=z, zmin=0, zmax=1, colorscale=scale, showscale=False))
    figure.update_layout(showlegend=False,
                         plot_bgcolor='white',
                         margin={
                             't': 0,
                             'r': 0,
                             'b': 0,
                             'l': 0
                         })
    figure.update_xaxes(showticklabels=False,
                        showgrid=False,
                        showline=False,
                        zeroline=False)
    figure.update_yaxes(scaleanchor='x',
                        scaleratio=1,
                        showticklabels=False,
                        showgrid=False,
                        showline=False,
                        zeroline=False)
    figure.write_image(path, width=1600, height=800)
Example #2
0
def customize_figure(fig: Figure) -> Figure:
    """Update the layout and style of plotly figures.

    Parameters
    ----------
    fig : plotly.graph_objs._figure.Figure
        The figure to modify

    Returns
    -------
    plotly.graph_objs._figure.Figure
        A customized figure.
    """
    fig.update_xaxes(fixedrange=True, title="Values", title_font_size=12)
    fig.update_yaxes(fixedrange=True, title_font_size=12)
    fig.update_layout(
        font_family="Courier New",
        paper_bgcolor="#205050",
        plot_bgcolor="#205050",
        margin={
            "l": 60,
            "t": 40,
            "r": 10,
            "b": 10
        },
        title_font_size=13,
        template="plotly_dark",
    )
    return fig
Example #3
0
def build_mse_dependency(
        distribution_name: str, thetas: List[float], n_moments: int, n_samples: int, n_runs: int
) -> Figure:
    figure = Figure()
    figure.update_layout(title=f"Dependency between moment and MSE for {distribution_name} distribution")
    figure.update_xaxes(title="k")
    figure.update_yaxes(title="MSE")
    for theta in thetas:
        experiment = Experiment(distribution_name, theta)
        mse = experiment.run(n_moments, n_samples, n_runs)
        figure.add_trace(create_mse_scatter(mse, distribution_name, theta))
    return figure
Example #4
0
def customize_figure(fig: go.Figure) -> go.Figure:
    """Update the font style, plot background, axes labels, and more.

    Args:
        fig (plotly.graph_objs._figure.Figure): Figure to edit.

    Returns:
        plotly.graph_objs._figure.Figure: Customized figure.
    """
    fig.update_layout(
        font_family="serif",
        plot_bgcolor="#fff",
        titlefont=dict(size=18, color="#444"),
        title_x=0.1,
    )
    fig.update_xaxes(fixedrange=True, title_font_size=16)
    fig.update_yaxes(fixedrange=True, title_font_size=16)
    return fig
def formatted_fig_json(fig: go.Figure) -> dict:
    """Formats figure with styling and returns as JSON.

    :param fig: Plotly figure.
    :type fig: go.Figure
    :return: Formatted plotly figure as a JSON dict.
    :rtype: dict
    """
    fig.update_xaxes(title_font=dict(size=16, color="black"),
                     tickfont={"size": 14})
    fig.update_yaxes(title_font=dict(size=16, color="black"),
                     tickfont={"size": 14})
    fig.update_layout(
        hoverlabel_align="right",
        font_family="Roboto",
        title_font_size=20,
        plot_bgcolor="white",
        paper_bgcolor="white",
    )
    return json.loads(fig.to_json())
 def __update_axes(self, fig: pgo.Figure):
     if self.properties.x_axis_name is not None:
         fig.update_xaxes(
             patch={
                 'visible': True,
                 'title': {
                     'text': self.properties.x_axis_name,
                 }
             },
             overwrite=True,
         )
     if self.properties.y_axis_name is not None:
         fig.update_yaxes(
             patch={
                 'visible': True,
                 'title': {
                     'text': self.properties.y_axis_name,
                 }
             },
             overwrite=True,
         )
Example #7
0
def timeseries_comparison_plot(
    series_1: pd.Series,
    series_2: pd.Series,
    traces_opts: dict = {},
    layout_opts: dict = {
        "xaxis_title": "Time",
        "yaxis_title": "Values",
        "autosize": True,
        "height": 200,
    },
    line_opts: dict = {},
) -> Figure:
    """Create a single time series line plot Plotly figure
    
    Returns the plotly figure object.
    """

    fig = Figure()
    # Only thing I figured is - I could do this

    s1 = series_1.sort_index()

    fig.add_scatter(
        x=s1.index, y=s1, mode="lines", name=s1.name if s1.name else "series_1"
    )  # Not what is desired - need a line

    s2 = series_2.sort_index()

    fig.add_scatter(
        x=s2.index, y=s2, mode="lines", name=s2.name if s2.name else "series_2"
    )  # Not what is desired - need a line

    fig.update_layout(**layout_opts)  # see https://plotly.com/python/figure-labels/
    fig.update_traces(traces_opts)  # set line color?

    fig.update_layout(margin=dict(l=0, r=0, b=0, t=5, pad=0))

    fig.update_yaxes(automargin=True)
    fig.update_xaxes(automargin=True)
    return fig
def multi_plotly_timeseries_plot(
    dataframe: pd.DataFrame,
    traces_opts: dict = {},
    layout_opts: dict = {
        "xaxis_title": "Time",
        "yaxis_title": "Values",
        "autosize": True,
        "height": 200,
    },
    line_opts: dict = {},
) -> Figure:
    """Create a single time series line plot Plotly figure
    
    Returns the plotly figure object.
    """

    fig = Figure()
    columns = list(dataframe.keys())

    to_plot_df = dataframe.sort_index()

    # Only thing I figured is - I could do this
    for key in columns:
        fig.add_scatter(x=to_plot_df.index,
                        y=to_plot_df[key],
                        mode="lines",
                        name=key)  # Not what is desired - need a line

    fig.update_layout(
        **layout_opts)  # see https://plotly.com/python/figure-labels/
    fig.update_traces(traces_opts)  # set line color?

    fig.update_layout(margin=dict(l=0, r=0, b=0, t=5, pad=0))

    fig.update_yaxes(automargin=True)
    fig.update_xaxes(automargin=True)
    return fig
Example #9
0
def update_xaxes(figure: go.Figure, plot_type: str,
                 **kwargs: Any) -> go.Figure:
    data_frame = kwargs["data_frame"]
    facet_col = kwargs.get("facet_col")
    return figure.update_xaxes(
        gridwidth=1,
        gridcolor="lightgrey",
        showline=True,
        linewidth=2,
        linecolor="black",
        mirror=True,
        title=None if facet_col is not None else kwargs.get("x"),
        showticklabels=(data_frame[facet_col].nunique() <= 100)
        if facet_col is not None else None,
        tickangle=0,
        tickfont_size=max((20 - (0.4 * data_frame[facet_col].nunique())), 10)
        if facet_col is not None else None,
        fixedrange=plot_type == "distribution",
    ).update_xaxes(**kwargs.get("xaxis", {}))
Example #10
0
def budget_heatmap(df,
                   datetime_column=DATETIME_COLUMN,
                   category_column=CATEGORY_COLUMN,
                   amount_column=AMOUNT_COLUMN,
                   budget=None,
                   moving_average_window=None,
                   start_date=None,
                   end_date=None,
                   fig: go.Figure = None,
                   annotations=True,
                   annotation_text_size=8,
                   delta_column=DELTA_COLUMN):
    """
    TODO:
        - Docstring
        - Visually show if there's no data before X date (right now it just looks like spending-budget is great!)

    Args:
        df:
        datetime_column:
        category_column:
        amount_column:
        budget:  (or really budget collection?)
        moving_average_window:
        start_date:
        end_date:
        fig:
        annotations (bool): If True, write the (amount-budget) value in each cell of the heatmap

    Returns:

    """
    if fig is None:
        fig = go.Figure()

    start_date, end_date, date_range = _parse_dates(datetime_column, df,
                                                    end_date, start_date,
                                                    moving_average_window)

    # If we have no data here, we haven't selected any categories to plot.  Escape
    if len(df) == 0:
        # no data!
        return fig

    # Construct plot
    zmid = 0
    zmin, zmax = get_rounded_z_range_including_mid(df[delta_column],
                                                   zmid,
                                                   round_to=10)
    colorscale = make_centered_rg_colorscale(zmin, zmax, zmid)

    # For plotting, reverse the order of the rows.  Rows picked on the sidebar are populated top to bottom, but y-values
    # on a heatmap show from bottom to top (increasing y direction)
    df_sums = _reverse_index_level_order(df, BUDGET_NAME_COLUMN)

    df_sums.sort_index()
    fig.add_trace(
        go.Heatmap(
            x=df_sums.index.get_level_values(datetime_column),
            y=df_sums.index.get_level_values(BUDGET_NAME_COLUMN),
            z=df_sums[DELTA_COLUMN],
            text=df_sums[DELTA_COLUMN],
            colorscale=colorscale,
            zmin=zmin,
            zmax=zmax,
            xgap=1,
            ygap=3,
        ))

    if annotations:
        annotations = _make_annotations(df_sums, annotation_text_size,
                                        delta_column)
        fig.update_layout(annotations=annotations, )

    fig.update_layout(**FIGURE_BACKGROUND)
    fig.update_yaxes(dtick=1)

    # Ensure axes show full range of data, and pad by same amount as other figures
    fig.update_xaxes(range=[start_date - X_AXIS_PAD, end_date], dtick="M1")

    return fig
Example #11
0
File: main.py Project: jckdm/thesis
def main():
    # get path to directory
    filepath = input('Path to directory (blank if PWD): ')

    # check if valid path
    if filepath != '':
        if not path.isdir(filepath):
            exit('Invalid path')

    data, lats, lons, flag, good, bad = [], [None, None], [None,
                                                           None], False, 0, 0

    # ask if user wants too show images' metadata (added for my zine)
    meta = input('\nShow metadata? (y/n): ')

    if meta.lower() in ('yes', 'y'):
        metaflag = True
    elif meta.lower() in ('no', 'n'):
        metaflag = False
    else:
        exit('Invalid response')

    # read all files in dir
    for file in glob(filepath + '*'):
        file = file.lower()
        # skip non-image files
        if not file.endswith('.jpg') and not file.endswith(
                '.jpeg') and not file.endswith('.png'):
            continue

        # extract Exif data from image
        exif = {
            TAGS[key]: val
            for key, val in Image.open(file).getexif().items() if key in TAGS
        }

        # extract GPS + datetime
        try:
            loc = exif['GPSInfo']
            dt = exif['DateTimeOriginal']
            good += 1
        # skip if either missing
        except KeyError:
            bad += 1
            continue

        # extract latitude and longitude
        lat = {
            'dir': loc[1],
            'deg': loc[2][0],
            'min': loc[2][1],
            'sec': loc[2][2]
        }
        lon = {
            'dir': loc[3],
            'deg': loc[4][0],
            'min': loc[4][1],
            'sec': loc[4][2]
        }

        # clean and print metadata
        if metaflag:
            cleanLat = str(lat['deg']) + '° ' + str(lat['min']) + '\' ' + str(
                lat['sec']) + '\" ' + str(lat['dir'])
            cleanLon = str(lon['deg']) + '° ' + str(lon['min']) + '\' ' + str(
                lon['sec']) + '\" ' + str(lon['dir'])

            print(
                f'File: {file}   Latitude: {cleanLat}   Longitude: {cleanLon}   Time: {dt}'
            )

        # calculate full coordinate with degree, minute, second
        truLat = float(lat['deg'] + (lat['min'] / 60.0) +
                       (lat['sec'] / 3600.0))
        truLon = float(lon['deg'] + (lon['min'] / 60.0) +
                       (lon['sec'] / 3600.0))

        # calculate mins and maxes
        if flag:
            lons[0], lons[1] = min(lons[0], truLon), max(lons[1], truLon)
            lats[0], lats[1] = min(lats[0], truLat), max(lats[1], truLat)
        # first time just assign values and flip flag
        else:
            lons[0], lons[1] = truLon, truLon
            lats[0], lats[1] = truLat, truLat
            flag = True

        data.append({
            'img': file,
            'lat': lat,
            'lon': lon,
            'datetime': dt,
            'truLat': truLat,
            'truLon': truLon
        })

    # not enough valid images
    if good <= 1:
        exit('Didn\'t find enough valid image files for a visualization.')

    print(
        f'\nExtracted metadata from {good} files. Unable to extract from {bad}.\n'
    )

    # prompt for viz choice
    q = input(
        'Please enter the number corresponding to your visualization of choice:\n1: Unsorted path\n2: Sorted path\n3: Both paths overlaid\n\n#: '
    )

    # validate user input
    while q not in ('1', '2', '3'):
        q = input('#: ')
    q = int(q)

    coords, sortedCoords, unSortedData = 'M ', 'M ', None

    # copy data, add first point
    if q == 1 or q == 3:
        unSortedData = data.copy()
        coords += str(unSortedData[0]['truLat']) + ',' + str(
            unSortedData[0]['truLon']) + ' '
    # sort data, add first point
    if q == 2 or q == 3:
        data.sort(key=lambda x: x['datetime'])
        sortedCoords += str(data[0]['truLat']) + ',' + str(
            data[0]['truLon']) + ' '

    # append rest of points
    for i in range(1, good):
        if q == 1 or q == 3:
            coords += ('L' + str(unSortedData[i]['truLat']) + ',' +
                       str(unSortedData[i]['truLon']) + ' ')
        if q == 2 or q == 3:
            sortedCoords += ('L' + str(data[i]['truLat']) + ',' +
                             str(data[i]['truLon']) + ' ')

    paths = []

    # if using unsorted, append path
    if coords != 'M ':
        paths.append({'type': 'path', 'path': coords, 'line_color': '#3CB371'})
    # if using sorted, append path
    if sortedCoords != 'M ':
        paths.append({
            'type': 'path',
            'path': sortedCoords,
            'line_color': '#6666FF'
        })

    fig = Figure(layout=Layout(plot_bgcolor='RGBA(1,1,1,0)'))
    # draw axes from min to max
    fig.update_xaxes(range=[lats[0], lats[1]], color='#FFFFFF')
    fig.update_yaxes(range=[lons[0], lons[1]], color='#FFFFFF')

    fig.update_layout(shapes=paths)
    fig.show()
Example #12
0
def substituted_data_plot(
    raw_values: pd.Series,
    substitutions: pd.Series,
    message_series: pd.Series = None,
    traces_opts: dict = {},
    layout_opts: dict = {
        "xaxis_title": "Time",
        "yaxis_title": "Values",
        "autosize": True,
        "height": 200,
    },
    line_opts: dict = {},
) -> Figure:
    """Create a single time series line plot Plotly figure
    
    Returns the plotly figure object.
    """

    fig = Figure()

    s1 = raw_values.sort_index()
    s1 = s1.loc[~s1.index.duplicated(keep="first")]

    s2 = substitutions.sort_index()
    s2 = s2.loc[~s2.index.duplicated(keep="first")]

    completely_handled_series, replaced_originals, replacements, new_values, deleted = handle_substitutions(
        s1, s2)

    fig.add_scatter(
        x=completely_handled_series.index,
        y=completely_handled_series,
        mode="markers+lines",
        name=raw_values.name +
        "_substituted" if raw_values.name else "raw_values_substituted",
        line_color="blue",
        opacity=0.6,
    )  # Not what is desired - need a line

    fig.add_scatter(
        x=replaced_originals.index,
        y=replaced_originals,
        mode="markers",
        name="replaced raw values",
        line_color="orange",
        marker=dict(size=10, opacity=0.6),
    )  # Not what is desired - need a line

    fig.add_scatter(
        x=deleted.index,
        y=deleted,
        mode="markers",
        name="ignored raw values",
        line_color="red",
        marker=dict(symbol="x", size=10, opacity=0.6),
    )  # Not what is desired - need a line

    fig.add_scatter(
        x=new_values.index,
        y=new_values,
        mode="markers",
        name="added values",
        line_color="green",
        marker=dict(symbol="cross", size=10, opacity=0.6),
    )  # Not what is desired - need a line

    fig.update_layout(
        **layout_opts)  # see https://plotly.com/python/figure-labels/
    fig.update_traces(traces_opts)  # set line color?

    fig.update_layout(margin=dict(l=0, r=0, b=0, t=5, pad=0))

    fig.update_yaxes(automargin=True)
    fig.update_xaxes(automargin=True)
    return fig
Example #13
0
def timeseries_comparison_plot(
    series_1: pd.Series,
    series_2: pd.Series,
    limit_violation_timestamp: str,
    limit: float,
    traces_opts: dict = {},
    layout_opts: dict = {
        "xaxis_title": "Time",
        "yaxis_title": "Values",
        "autosize": True,
        "height": 200,
    },
    line_opts: dict = {},
) -> Figure:
    """Create a single time series line plot Plotly figure
    
    Returns the plotly figure object.
    """

    fig = Figure()
    # Only thing I figured is - I could do this

    s1 = series_1.sort_index()

    fig.add_scatter(
        x=s1.index, y=s1, mode="lines", name=s1.name if s1.name else "series_1"
    )  # Not what is desired - need a line

    s2 = series_2.sort_index()

    fig.add_scatter(
        x=s2.index, y=s2, mode="lines", name=s2.name if s2.name else "series_2"
    )  # Not what is desired - need a line

    fig.update_layout(**layout_opts)  # see https://plotly.com/python/figure-labels/
    fig.update_traces(traces_opts)  # set line color?

    vline_y_min = np.min([series_1.min(), series_2.min(), limit])
    vline_y_max = np.max([series_1.max(), series_2.max(), limit])

    hline_x_min = np.min([series_1.index.min(), series_2.index.min()])
    hline_x_max = np.max([series_1.index.max(), series_2.index.max()])

    fig.update_layout(
        shapes=(
            [
                dict(
                    type="line",
                    yref="y",
                    y0=vline_y_min,
                    y1=vline_y_max,
                    xref="x",
                    x0=limit_violation_timestamp,
                    x1=limit_violation_timestamp,
                )
            ]
            if limit_violation_timestamp is not None
            else []
        )
        + [
            dict(
                type="line",
                yref="y",
                y0=limit,
                y1=limit,
                xref="x",
                x0=hline_x_min,
                x1=hline_x_max,
                line={"color": "red", "width": 1},
            )
        ]
    )

    fig.update_layout(margin=dict(l=0, r=0, b=0, t=5, pad=0))

    fig.update_yaxes(automargin=True)
    fig.update_xaxes(automargin=True)
    return fig
def timeseries_comparison_plot(
    series_1: pd.Series,
    series_2: pd.Series,
    freq,
    freq_factor,
    max_shifts_past,
    max_shifts_future,
    traces_opts: dict = {},
    layout_opts: dict = {
        "xaxis_title": "Time",
        "yaxis_title": "Values",
        "autosize": True,
        "height": 480,
    },
    line_opts: dict = {},
) -> Figure:
    """Create a single time series line plot Plotly figure
    
    Returns the plotly figure object.
    """
    if max_shifts_past < 0 or max_shifts_future < 0:
        raise ValueError("Shift maxima values must be greater equal zero.")

    fig = Figure()

    s1 = series_1.sort_index()

    fig.add_scatter(
        x=s1.index,
        y=s1,
        mode="lines",
        name=s1.name if (s1.name and s1.name != "measurement") else "series",
    )

    s2 = series_2.sort_index()

    for step in np.arange(-max_shifts_past, max_shifts_future, 1):
        shifted = s2.copy()
        shifted.index = shifted.index.shift(periods=step * freq_factor,
                                            freq=freq)
        fig.add_scatter(
            x=shifted.index,
            y=shifted,
            mode="lines",
            name=shifted.name if
            (shifted.name
             and shifted.name != "measurement") else "series_shiftable",
            visible=False,
        )

    fig.data[max_shifts_past + 1].visible = True  # start somewhere

    steps = []
    for i in range(len(fig.data)):
        step = dict(
            method="update",
            args=[
                {
                    "visible": [False] * (len(fig.data))
                },
                {
                    "title":
                    f"Shifted by x times frequency {freq_factor}{freq}: " +
                    str(i - max_shifts_past - 1)
                },
            ],  # layout attribute
        )
        step["args"][0]["visible"][i] = True  # Toggle i'th trace to "visible"
        step["args"][0]["visible"][0] = True
        step["label"] = str(i - max_shifts_past - 1)
        steps.append(step)

    sliders = [
        dict(
            active=max_shifts_past,
            currentvalue={
                "prefix": f"Shifted by x times frequency {freq_factor}{freq}: "
            },
            pad={
                "t": 80,
                "b": 10
            },
            steps=steps[1:],
        )
    ]

    fig.update_layout(
        **layout_opts)  # see https://plotly.com/python/figure-labels/
    fig.update_traces(traces_opts)  # set line color?

    fig.update_layout(margin=dict(l=0, r=0, b=40, t=30, pad=10))

    fig.update_yaxes(automargin=True)
    fig.update_xaxes(automargin=True)

    fig.update_layout(sliders=sliders)

    return fig
Example #15
0
    def plot_dimensions_graph(
            fig: go.Figure, y: List[float], y_labels: Optional[List[str]] = None, y_err: Optional[List[float]] = None,
            practical_maximum: Optional[float] = None, label: Optional[str] = None):
        color = QUALITATIVE_COLORS[0]
        rgb_ints = [str(int(x.strip(" "))) for x in color[4:][:-1].split(",")]
        new_color = f"rgba({','.join(rgb_ints + ['0.2'])})"

        # Error range
        x = list(range(1, len(y) + 1))
        if y_err:
            y_upper = [m + e for m, e in zip(y, y_err)]
            y_lower = [m - e for m, e in zip(y, y_err)]
            fig.add_trace(go.Scatter(
                x=x + x[::-1],
                y=y_upper + y_lower[::-1],
                fill='toself',
                fillcolor=new_color,
                line_color='rgba(255,255,255,0)',
                showlegend=False,
                name=label,
                hoverinfo='skip',
                legendgroup=label,
            ))

        custom_data: Optional[List[Any]] = None
        hover_template = None
        if y_labels:
            if y_err:
                custom_data = list(zip(y_labels, y_err))
                hover_template = '<b>%{y:.3f} +- %{customdata[1]:.3f}</b><br>%{customdata[0]}'
            else:
                custom_data = y_labels
                hover_template = '<b>%{y:.3f}</b><br>%{customdata}'

        # Mean line
        fig.add_trace(go.Scatter(
            x=x, y=y,
            customdata=custom_data,
            hovertemplate=hover_template,
            line_color=color,
            showlegend=True,
            name=label,
            legendgroup=label,
        ))
        fig.update_traces(mode='lines')

        # Max MI
        if practical_maximum:
            fig.add_shape(
                # Line Horizontal
                type="line",
                x0=min(x),
                y0=practical_maximum,
                x1=max(x),
                y1=practical_maximum,
                line=dict(
                    color="LightSeaGreen",
                    dash="dash",
                ),
            )

        fig.update_layout(margin=dict(l=20, r=20, t=20, b=20))  # noqa
        fig.update_xaxes(title_text="Dimensions Selected", tickvals=x)

        # Make serif
        fig.update_layout(font=dict(
            family="serif",
        ))

        return fig