Skip to content

References

Analytics

The analytics module provides a facade class for analyzing calendar events and generating charts. The module uses a CalendarDataCollector to retrieve events from the Google Calendar API and a DataTransformer to transform the data into the format required by the plotting functions. The plotting is done by creating instances of PlotFactory.

The AnalyzerFacade class provides three methods for analyzing events: analyze_one, analyze_many, and analyze_one_with_periods. The analyze_one method analyzes a single event, the analyze_many method analyzes multiple events, and the analyze_one_with_periods method analyzes a single event over a period of time.

The AnalyzerBuilder class is a builder class that allows for creating instances of the AnalyzerFacade class with different options.

AnalyzerFacade

Facade class for analyzing calendar events and generating charts.

The class provides three methods for analyzing events: analyze_one, 'analyze_many', and 'analyze_one_with_periods'. It uses a CalendarDataCollector to retrieve events from Google Calendar API and a DataTransformer to transform the data into the format required by the plotting functions. The plotting is done by creating instances of PlotFactory.

Parameters:

Name Type Description Default
creds Credentials

Google credentials class instance.

required

Attributes:

Name Type Description
creds Credentials

An instance of the Credentials class.

plot_type str

The type of chart to be generated.

max_events int

The maximum number of events to be analyzed.

ascending bool

If True, sort the events in ascending order of duration.

data_collector AsyncCalendarDataCollector

An instance of the CalendarDataCollector class.

Examples:

# Initialize AnalyzerFacade and analyze a single event
analyzer = AnalyzerBuilder().with_credentials(creds).build()
start_time = datetime(2023, 3, 1, tzinfo=pytz.UTC)
end_time = datetime(2023, 3, 18, tzinfo=pytz.UTC)
event_name = "Meeting"
plot = await analyzer.analyze_one(start_time, end_time, event_name)

# Initialize AnalyzerFacade and analyze multiple events
analyzer = AnalyzerBuilder().with_credentials(creds).build()
start_time = datetime(2023, 3, 1, 0, 0, 0)
end_time = datetime(2023, 3, 31, 23, 59, 59)
fig = await analyzer.analyze_many(start_time=start_time, end_time=end_time)
fig.show()

# Initialize AnalyzerFacade and analyze a single event over a period of time
analyzer = AnalyzerBuilder().with_credentials(creds).build()
start_time = datetime(2023, 3, 1, tzinfo=pytz.UTC)
end_time = datetime(2023, 3, 31, tzinfo=pytz.UTC)
event_name = "Meeting"
period_days = 7
num_periods = 2
plot = await analyzer.analyze_one_with_periods(
start_time=start_time,
end_time=end_time,
event_name=event_name,
period_days=period_days,
num_periods=num_periods,
)
Source code in google_calendar_analytics/analytics.py
class AnalyzerFacade:
    """
    Facade class for analyzing calendar events and generating charts.

    The class provides three methods for analyzing events:
    `analyze_one`, 'analyze_many', and 'analyze_one_with_periods'.
    It uses a CalendarDataCollector to retrieve events from Google Calendar API and a DataTransformer
    to transform the data into the format required by the plotting functions. The plotting is done by
    creating instances of PlotFactory.

    Args:
        creds (Credentials): Google credentials class instance.

    Attributes:
        creds (Credentials): An instance of the Credentials class.
        plot_type (str): The type of chart to be generated.
        max_events (int): The maximum number of events to be analyzed.
        ascending (bool): If True, sort the events in ascending order of duration.
        data_collector (AsyncCalendarDataCollector): An instance of the CalendarDataCollector class.

    Examples:
        ```python
        # Initialize AnalyzerFacade and analyze a single event
        analyzer = AnalyzerBuilder().with_credentials(creds).build()
        start_time = datetime(2023, 3, 1, tzinfo=pytz.UTC)
        end_time = datetime(2023, 3, 18, tzinfo=pytz.UTC)
        event_name = "Meeting"
        plot = await analyzer.analyze_one(start_time, end_time, event_name)

        # Initialize AnalyzerFacade and analyze multiple events
        analyzer = AnalyzerBuilder().with_credentials(creds).build()
        start_time = datetime(2023, 3, 1, 0, 0, 0)
        end_time = datetime(2023, 3, 31, 23, 59, 59)
        fig = await analyzer.analyze_many(start_time=start_time, end_time=end_time)
        fig.show()

        # Initialize AnalyzerFacade and analyze a single event over a period of time
        analyzer = AnalyzerBuilder().with_credentials(creds).build()
        start_time = datetime(2023, 3, 1, tzinfo=pytz.UTC)
        end_time = datetime(2023, 3, 31, tzinfo=pytz.UTC)
        event_name = "Meeting"
        period_days = 7
        num_periods = 2
        plot = await analyzer.analyze_one_with_periods(
        start_time=start_time,
        end_time=end_time,
        event_name=event_name,
        period_days=period_days,
        num_periods=num_periods,
        )
        ```
    """

    def __init__(self, creds: Credentials):
        self.style_class = None
        self.creds = creds
        self.plot_type = "Line"
        self.max_events = 5
        self.ascending = False

        self.session = None
        self.data_collector = None

    async def __aenter__(self):
        ssl_context = ssl.create_default_context(cafile=certifi.where())
        self.session = aiohttp.ClientSession(
            connector=aiohttp.TCPConnector(ssl=ssl_context)
        )
        self.data_collector = AsyncCalendarDataCollector(self.creds, self.session)
        return self

    async def __aexit__(self, exc_type, exc, tb):
        if self.session:
            await self.session.close()

        self.session = None
        self.data_collector = None

    async def analyze_one(
        self,
        start_time: datetime,
        end_time: datetime,
        event_name: str,
        plot_type: str,
        style_class: VisualDesign = base_plot_design,
        **kwargs
    ) -> go.Figure:
        """
        Analyze a single event and generate a plot.

        This method analyzes a single event from the specified start time to end time and generates a plot using the OneEventDurationStrategy. The method uses a CalendarDataCollector to retrieve events from the Google Calendar API, a DataTransformer to transform the data into the required format, and a PlotFactory to generate the plot.

        Args:
            start_time (datetime): The start time for the analysis.
            end_time (datetime): The end time for the analysis.
            event_name (str): The name of the event to analyze.
            plot_type (str): The type of plot to generate.
            style_class (Type[VisualDesign]): The class that defines the style of the plot.
            **kwargs: Additional keyword arguments for the plot creation.

        Returns:
            go.Figure: The plot generated by the PlotFactory.

        Raises:
            None

        Examples:
            To analyze a single event from March 1, 2023 to March 18, 2023 with the name "Meeting" and generate a plot, use:

            ```
            analyzer = AnalyzerBuilder().with_credentials(creds).build()
            start_time = datetime(2023, 3, 1, tzinfo=pytz.UTC)
            end_time = datetime(2023, 3, 18, tzinfo=pytz.UTC)
            event_name = "Meeting"
            plot = await analyzer.analyze_one(start_time, end_time, event_name)
            ```
        """
        if plot_type not in ("Line",):
            raise exceptions.InvalidPlotTypeError(self.plot_type, method="analyze_one")

        self.style_class = style_class
        self.plot_type = plot_type

        return await self._analyze(
            start_time=start_time,
            end_time=end_time,
            event_name=event_name,
            method="one",
            transformer_strategy=OneEventDurationStrategy(),
        )

    async def analyze_many(
        self,
        start_time: datetime,
        end_time: datetime,
        plot_type: str,
        max_events: int = 5,
        ascending=False,
        style_class: VisualDesign = base_plot_design,
        **kwargs
    ) -> go.Figure:
        """
        Analyze multiple calendar events and generate a plot of their durations.

        Args:
            start_time (datetime): The start time for the analysis.
            end_time (datetime): The end time for the analysis.
            plot_type (str): The type of plot to generate.
            max_events (int): The maximum number of events to analyze.
            ascending (bool): If True, sort the events in ascending order of duration.
            style_class (Type[VisualDesign]): The class that defines the style of the plot.
            **kwargs: Additional keyword arguments for the plot creation.

        Returns:
            go.Figure: The plot generated by the PlotFactory.

        Raises:
            None

        Examples:
            ```
            analyzer = AnalyzerBuilder().with_credentials(creds).build()
            start_time = datetime(2023, 3, 1, 0, 0, 0)
            end_time = datetime(2023, 3, 31, 23, 59, 59)
            fig = await analyzer.analyze_many(start_time=start_time, end_time=end_time)
            fig.show()
            ```
        """

        if plot_type not in ("Bar", "Pie"):
            raise exceptions.InvalidPlotTypeError(self.plot_type, method="analyze_many")

        self.style_class = style_class
        self.plot_type = plot_type
        self.max_events = max_events
        self.ascending = ascending

        return await self._analyze(
            start_time=start_time,
            end_time=end_time,
            method="many",
            transformer_strategy=ManyEventsDurationStrategy(),
        )

    async def analyze_one_with_periods(
        self,
        start_time: datetime,
        end_time: datetime,
        event_name: str,
        plot_type: str,
        period_days: int = 7,
        num_periods: int = 2,
        style_class: VisualDesign = base_plot_design,
        **kwargs
    ) -> go.Figure:
        """
        Analyze a single event over multiple periods of time and generate a plot.

        This method analyzes a single event from the specified start time to end time over multiple periods of time using the EventDurationPeriodsStrategy. The method uses a CalendarDataCollector to retrieve events from the Google Calendar API, a DataTransformer to transform the data into the required format, and a PlotFactory to generate the plot.

        Args:
            start_time (datetime): The start time for the analysis.
            end_time (datetime): The end time for the analysis.
            event_name (str): The name of the event to analyze.
            period_days (int, optional): The number of days in each period. Defaults to 7.
            num_periods (int, optional): The number of periods to analyze. Defaults to 2.
            plot_type (str): The type of plot to generate.
            style_class (Type[VisualDesign]): The class that defines the style of the plot.
            **kwargs: Additional keyword arguments for the plot creation.

        Returns:
            go.Figure: The plot generated by the PlotFactory.

        Raises:
            None

        Examples:
            To analyze a single event named "Meeting" from March 1, 2023 to March 31, 2023 over two periods of 7 days and generate a plot, use:

            ```
            analyzer = AnalyzerBuilder().with_credentials(creds).build()
            start_time = datetime(2023, 3, 1, tzinfo=pytz.UTC)
            end_time = datetime(2023, 3, 31, tzinfo=pytz.UTC)
            event_name = "Meeting"
            period_days = 7
            num_periods = 2
            plot = await analyzer.analyze_one_with_periods(start_time, end_time, event_name, period_days, num_periods)
            ```
        """
        if plot_type not in ("MultyLine",):
            raise exceptions.InvalidPlotTypeError(
                self.plot_type, method="analyze_one_with_periods"
            )

        self.style_class = style_class
        self.plot_type = plot_type

        return await self._analyze(
            start_time=start_time,
            end_time=end_time,
            event_name=event_name,
            method="one_with_periods",
            period_days=period_days,
            num_periods=num_periods,
            transformer_strategy=EventDurationPeriodsStrategy(),
        )

    async def _analyze(
        self,
        start_time: datetime,
        end_time: datetime,
        transformer_strategy: EventDurationStrategy,
        event_name: str = None,  # type: ignore
        method: str = "one",
        period_days: int = 7,
        num_periods: int = 2,
        **kwargs
    ) -> go.Figure:
        """
        Analyzes calendar events data and creates a plot using the specified method.

        Args:
            start_time (datetime): The start time for the analysis.
            end_time (datetime): The end time for the analysis.
            event_name (str, optional): The name of the event to analyze. Required for the 'one' and 'one_with_periods' methods. Defaults to None.
            transformer_strategy (DataTransformerStrategy): The strategy to use for data transformation.
            method (str, optional): The method to use for analysis. Must be one of 'one', 'many', or 'one_with_periods'. Defaults to 'one'.
            period_days (int, optional): The number of days in each period. Required for the 'one_with_periods' method. Defaults to 7.
            num_periods (int, optional): The number of periods to analyze. Required for the 'one_with_periods' method. Defaults to 2.
            **kwargs: Additional keyword arguments for the plot creation.

        Returns:
            go.Figure: The plot generated by the PlotFactory.

        Raises:
            ValueError: If an invalid method is specified.
        """
        plot_creator = await PlotFactory(
            plot_type=self.plot_type,
            style_class=self.style_class,
        )

        calendar_events = await self.data_collector.collect_data(
            start_time=start_time,
            end_time=end_time,
        )

        if method == "one":
            event_durations = await transformer_strategy.calculate_duration(
                events=calendar_events, event_name=event_name
            )
            return await plot_creator.plot(
                events=event_durations, event_name=event_name
            )
        elif method == "many":
            event_durations = await transformer_strategy.calculate_duration(
                events=calendar_events,
                max_events=self.max_events,
                ascending=self.ascending,
            )
            return await plot_creator.plot(events=event_durations)
        elif method == "one_with_periods":
            event_durations = await transformer_strategy.calculate_duration(
                events=calendar_events,
                event_name=event_name,
                period_days=period_days,
                num_periods=num_periods,
            )

            return await plot_creator.plot(
                events=event_durations, event_name=event_name
            )
        else:
            raise ValueError("Invalid method specified")

analyze_many(start_time, end_time, plot_type, max_events=5, ascending=False, style_class=base_plot_design, **kwargs) async

Analyze multiple calendar events and generate a plot of their durations.

Parameters:

Name Type Description Default
start_time datetime

The start time for the analysis.

required
end_time datetime

The end time for the analysis.

required
plot_type str

The type of plot to generate.

required
max_events int

The maximum number of events to analyze.

5
ascending bool

If True, sort the events in ascending order of duration.

False
style_class Type[VisualDesign]

The class that defines the style of the plot.

base_plot_design
**kwargs

Additional keyword arguments for the plot creation.

{}

Returns:

Type Description
go.Figure

go.Figure: The plot generated by the PlotFactory.

Examples:

analyzer = AnalyzerBuilder().with_credentials(creds).build()
start_time = datetime(2023, 3, 1, 0, 0, 0)
end_time = datetime(2023, 3, 31, 23, 59, 59)
fig = await analyzer.analyze_many(start_time=start_time, end_time=end_time)
fig.show()
Source code in google_calendar_analytics/analytics.py
async def analyze_many(
    self,
    start_time: datetime,
    end_time: datetime,
    plot_type: str,
    max_events: int = 5,
    ascending=False,
    style_class: VisualDesign = base_plot_design,
    **kwargs
) -> go.Figure:
    """
    Analyze multiple calendar events and generate a plot of their durations.

    Args:
        start_time (datetime): The start time for the analysis.
        end_time (datetime): The end time for the analysis.
        plot_type (str): The type of plot to generate.
        max_events (int): The maximum number of events to analyze.
        ascending (bool): If True, sort the events in ascending order of duration.
        style_class (Type[VisualDesign]): The class that defines the style of the plot.
        **kwargs: Additional keyword arguments for the plot creation.

    Returns:
        go.Figure: The plot generated by the PlotFactory.

    Raises:
        None

    Examples:
        ```
        analyzer = AnalyzerBuilder().with_credentials(creds).build()
        start_time = datetime(2023, 3, 1, 0, 0, 0)
        end_time = datetime(2023, 3, 31, 23, 59, 59)
        fig = await analyzer.analyze_many(start_time=start_time, end_time=end_time)
        fig.show()
        ```
    """

    if plot_type not in ("Bar", "Pie"):
        raise exceptions.InvalidPlotTypeError(self.plot_type, method="analyze_many")

    self.style_class = style_class
    self.plot_type = plot_type
    self.max_events = max_events
    self.ascending = ascending

    return await self._analyze(
        start_time=start_time,
        end_time=end_time,
        method="many",
        transformer_strategy=ManyEventsDurationStrategy(),
    )

analyze_one(start_time, end_time, event_name, plot_type, style_class=base_plot_design, **kwargs) async

Analyze a single event and generate a plot.

This method analyzes a single event from the specified start time to end time and generates a plot using the OneEventDurationStrategy. The method uses a CalendarDataCollector to retrieve events from the Google Calendar API, a DataTransformer to transform the data into the required format, and a PlotFactory to generate the plot.

Parameters:

Name Type Description Default
start_time datetime

The start time for the analysis.

required
end_time datetime

The end time for the analysis.

required
event_name str

The name of the event to analyze.

required
plot_type str

The type of plot to generate.

required
style_class Type[VisualDesign]

The class that defines the style of the plot.

base_plot_design
**kwargs

Additional keyword arguments for the plot creation.

{}

Returns:

Type Description
go.Figure

go.Figure: The plot generated by the PlotFactory.

Examples:

To analyze a single event from March 1, 2023 to March 18, 2023 with the name "Meeting" and generate a plot, use:

analyzer = AnalyzerBuilder().with_credentials(creds).build()
start_time = datetime(2023, 3, 1, tzinfo=pytz.UTC)
end_time = datetime(2023, 3, 18, tzinfo=pytz.UTC)
event_name = "Meeting"
plot = await analyzer.analyze_one(start_time, end_time, event_name)
Source code in google_calendar_analytics/analytics.py
async def analyze_one(
    self,
    start_time: datetime,
    end_time: datetime,
    event_name: str,
    plot_type: str,
    style_class: VisualDesign = base_plot_design,
    **kwargs
) -> go.Figure:
    """
    Analyze a single event and generate a plot.

    This method analyzes a single event from the specified start time to end time and generates a plot using the OneEventDurationStrategy. The method uses a CalendarDataCollector to retrieve events from the Google Calendar API, a DataTransformer to transform the data into the required format, and a PlotFactory to generate the plot.

    Args:
        start_time (datetime): The start time for the analysis.
        end_time (datetime): The end time for the analysis.
        event_name (str): The name of the event to analyze.
        plot_type (str): The type of plot to generate.
        style_class (Type[VisualDesign]): The class that defines the style of the plot.
        **kwargs: Additional keyword arguments for the plot creation.

    Returns:
        go.Figure: The plot generated by the PlotFactory.

    Raises:
        None

    Examples:
        To analyze a single event from March 1, 2023 to March 18, 2023 with the name "Meeting" and generate a plot, use:

        ```
        analyzer = AnalyzerBuilder().with_credentials(creds).build()
        start_time = datetime(2023, 3, 1, tzinfo=pytz.UTC)
        end_time = datetime(2023, 3, 18, tzinfo=pytz.UTC)
        event_name = "Meeting"
        plot = await analyzer.analyze_one(start_time, end_time, event_name)
        ```
    """
    if plot_type not in ("Line",):
        raise exceptions.InvalidPlotTypeError(self.plot_type, method="analyze_one")

    self.style_class = style_class
    self.plot_type = plot_type

    return await self._analyze(
        start_time=start_time,
        end_time=end_time,
        event_name=event_name,
        method="one",
        transformer_strategy=OneEventDurationStrategy(),
    )

analyze_one_with_periods(start_time, end_time, event_name, plot_type, period_days=7, num_periods=2, style_class=base_plot_design, **kwargs) async

Analyze a single event over multiple periods of time and generate a plot.

This method analyzes a single event from the specified start time to end time over multiple periods of time using the EventDurationPeriodsStrategy. The method uses a CalendarDataCollector to retrieve events from the Google Calendar API, a DataTransformer to transform the data into the required format, and a PlotFactory to generate the plot.

Parameters:

Name Type Description Default
start_time datetime

The start time for the analysis.

required
end_time datetime

The end time for the analysis.

required
event_name str

The name of the event to analyze.

required
period_days int

The number of days in each period. Defaults to 7.

7
num_periods int

The number of periods to analyze. Defaults to 2.

2
plot_type str

The type of plot to generate.

required
style_class Type[VisualDesign]

The class that defines the style of the plot.

base_plot_design
**kwargs

Additional keyword arguments for the plot creation.

{}

Returns:

Type Description
go.Figure

go.Figure: The plot generated by the PlotFactory.

Examples:

To analyze a single event named "Meeting" from March 1, 2023 to March 31, 2023 over two periods of 7 days and generate a plot, use:

analyzer = AnalyzerBuilder().with_credentials(creds).build()
start_time = datetime(2023, 3, 1, tzinfo=pytz.UTC)
end_time = datetime(2023, 3, 31, tzinfo=pytz.UTC)
event_name = "Meeting"
period_days = 7
num_periods = 2
plot = await analyzer.analyze_one_with_periods(start_time, end_time, event_name, period_days, num_periods)
Source code in google_calendar_analytics/analytics.py
async def analyze_one_with_periods(
    self,
    start_time: datetime,
    end_time: datetime,
    event_name: str,
    plot_type: str,
    period_days: int = 7,
    num_periods: int = 2,
    style_class: VisualDesign = base_plot_design,
    **kwargs
) -> go.Figure:
    """
    Analyze a single event over multiple periods of time and generate a plot.

    This method analyzes a single event from the specified start time to end time over multiple periods of time using the EventDurationPeriodsStrategy. The method uses a CalendarDataCollector to retrieve events from the Google Calendar API, a DataTransformer to transform the data into the required format, and a PlotFactory to generate the plot.

    Args:
        start_time (datetime): The start time for the analysis.
        end_time (datetime): The end time for the analysis.
        event_name (str): The name of the event to analyze.
        period_days (int, optional): The number of days in each period. Defaults to 7.
        num_periods (int, optional): The number of periods to analyze. Defaults to 2.
        plot_type (str): The type of plot to generate.
        style_class (Type[VisualDesign]): The class that defines the style of the plot.
        **kwargs: Additional keyword arguments for the plot creation.

    Returns:
        go.Figure: The plot generated by the PlotFactory.

    Raises:
        None

    Examples:
        To analyze a single event named "Meeting" from March 1, 2023 to March 31, 2023 over two periods of 7 days and generate a plot, use:

        ```
        analyzer = AnalyzerBuilder().with_credentials(creds).build()
        start_time = datetime(2023, 3, 1, tzinfo=pytz.UTC)
        end_time = datetime(2023, 3, 31, tzinfo=pytz.UTC)
        event_name = "Meeting"
        period_days = 7
        num_periods = 2
        plot = await analyzer.analyze_one_with_periods(start_time, end_time, event_name, period_days, num_periods)
        ```
    """
    if plot_type not in ("MultyLine",):
        raise exceptions.InvalidPlotTypeError(
            self.plot_type, method="analyze_one_with_periods"
        )

    self.style_class = style_class
    self.plot_type = plot_type

    return await self._analyze(
        start_time=start_time,
        end_time=end_time,
        event_name=event_name,
        method="one_with_periods",
        period_days=period_days,
        num_periods=num_periods,
        transformer_strategy=EventDurationPeriodsStrategy(),
    )

VisualizerFactory

This module provides classes for generating visualizations of event data using Pandas and Plotly libraries. It includes classes for bar charts, pie charts, and line charts of event durations, as well as multiple line charts for events over multiple periods. The Plot class defines some common properties for all visualization classes, while the ManyEventPlot and OneEventPlot classes define required abstract methods. The factory method PlotFactory returns an object of the specified visualization class based on input parameters.

BarPlot

Bases: ManyEventPlot

Source code in google_calendar_analytics/visualization/visualizer_factory.py
class BarPlot(ManyEventPlot):
    async def plot(
        self,
        events: pd.DataFrame,
        title: str = "Top events with the Longest Duration",
        **kwargs,
    ) -> go.Figure:
        """
        Plot a bar chart of the event durations.

        Args:
            events (pd.DataFrame): A DataFrame containing the event names as the index and the event durations as values.
            title (str): The title of the chart.
        """

        fig = go.Figure(
            go.Bar(
                x=events.Event,
                y=events.Duration,
                name="Duration",
                marker=dict(color=self.style_class.rgb_colors, colorscale="Blues"),
            )
        )
        if self.style_class.show_xaxis_title:
            fig.update_xaxes(title_text="Event")

        if self.style_class.show_yaxis_title:
            fig.update_yaxes(title_text="Duration (Hours)")

        if self.style_class.show_title:
            fig.update_layout(
                title=title,
                title_font=dict(size=18, color=self.font_color),
            )

        fig.update_layout(
            width=self.style_class.width,
            height=self.style_class.height,
            plot_bgcolor=self.plot_bgcolor,
            paper_bgcolor=self.paper_bgcolor,
            font=dict(color=self.font_color),
        )
        fig.update_traces(
            hovertemplate="<b>Event:</b> %{x} <br><b>Duration:</b> %{y:.2f} hours",
        )

        return fig

plot(events, title='Top events with the Longest Duration', **kwargs) async

Plot a bar chart of the event durations.

Parameters:

Name Type Description Default
events pd.DataFrame

A DataFrame containing the event names as the index and the event durations as values.

required
title str

The title of the chart.

'Top events with the Longest Duration'
Source code in google_calendar_analytics/visualization/visualizer_factory.py
async def plot(
    self,
    events: pd.DataFrame,
    title: str = "Top events with the Longest Duration",
    **kwargs,
) -> go.Figure:
    """
    Plot a bar chart of the event durations.

    Args:
        events (pd.DataFrame): A DataFrame containing the event names as the index and the event durations as values.
        title (str): The title of the chart.
    """

    fig = go.Figure(
        go.Bar(
            x=events.Event,
            y=events.Duration,
            name="Duration",
            marker=dict(color=self.style_class.rgb_colors, colorscale="Blues"),
        )
    )
    if self.style_class.show_xaxis_title:
        fig.update_xaxes(title_text="Event")

    if self.style_class.show_yaxis_title:
        fig.update_yaxes(title_text="Duration (Hours)")

    if self.style_class.show_title:
        fig.update_layout(
            title=title,
            title_font=dict(size=18, color=self.font_color),
        )

    fig.update_layout(
        width=self.style_class.width,
        height=self.style_class.height,
        plot_bgcolor=self.plot_bgcolor,
        paper_bgcolor=self.paper_bgcolor,
        font=dict(color=self.font_color),
    )
    fig.update_traces(
        hovertemplate="<b>Event:</b> %{x} <br><b>Duration:</b> %{y:.2f} hours",
    )

    return fig

LinePlot

Bases: OneEventPlot

Source code in google_calendar_analytics/visualization/visualizer_factory.py
class LinePlot(OneEventPlot):
    async def plot(
        self,
        events: pd.DataFrame,
        event_name: str,
        **kwargs,
    ) -> go.Figure:
        """
        Plot a line chart of the event durations.

        Args:
            events (pd.DataFrame): A DataFrame containing the event dates as the index and the event durations as the values.
            event_name (str): The name of the event.
        """
        fig = go.Figure()
        fig.add_trace(
            go.Scatter(
                x=events.Date,
                y=events.Duration,
                mode="lines+markers",
                line=dict(
                    color=self.style_class.rgb_line_color,
                    width=self.style_class.line_width,
                    shape=self.style_class.line_shape,
                ),
                marker=dict(size=6, color=self.style_class.rgb_line_color),
                name="Duration",
            )
        )

        if self.style_class.show_title:
            fig.update_layout(
                title=dict(
                    text=f"Time spent on {event_name}",
                    font=dict(size=16, color=self.font_color),
                )
            )

        if self.style_class.show_xaxis_title:
            fig.update_xaxes(title_text="Date")

        if self.style_class.show_yaxis_title:
            fig.update_yaxes(title_text="Duration (hours)")

        fig.update_layout(
            xaxis=dict(
                showgrid=self.style_class.show_grid,
                nticks=10,
                dtick="D5",
                gridcolor=self.grid_color,
                gridwidth=self.style_class.grid_width,
                titlefont=dict(size=14, color=self.font_color),
                tickfont=dict(size=12, color=self.font_color),
                tickcolor=self.font_color,
            ),
            yaxis=dict(
                showgrid=self.style_class.show_grid,
                gridwidth=self.style_class.grid_width,
                gridcolor=self.grid_color,
                titlefont=dict(size=14, color=self.font_color),
                tickfont=dict(size=12, color=self.font_color),
                tickcolor=self.font_color,
            ),
            margin=dict(l=50, r=50, t=80, b=50),
            width=self.style_class.width,
            height=self.style_class.height,
            plot_bgcolor=self.plot_bgcolor,
            paper_bgcolor=self.paper_bgcolor,
        )

        fig.update_traces(
            hovertemplate="<b>Date:</b> %{x} <br><b>Duration:</b> %{y:.2f} hours"
        )

        return fig

plot(events, event_name, **kwargs) async

Plot a line chart of the event durations.

Parameters:

Name Type Description Default
events pd.DataFrame

A DataFrame containing the event dates as the index and the event durations as the values.

required
event_name str

The name of the event.

required
Source code in google_calendar_analytics/visualization/visualizer_factory.py
async def plot(
    self,
    events: pd.DataFrame,
    event_name: str,
    **kwargs,
) -> go.Figure:
    """
    Plot a line chart of the event durations.

    Args:
        events (pd.DataFrame): A DataFrame containing the event dates as the index and the event durations as the values.
        event_name (str): The name of the event.
    """
    fig = go.Figure()
    fig.add_trace(
        go.Scatter(
            x=events.Date,
            y=events.Duration,
            mode="lines+markers",
            line=dict(
                color=self.style_class.rgb_line_color,
                width=self.style_class.line_width,
                shape=self.style_class.line_shape,
            ),
            marker=dict(size=6, color=self.style_class.rgb_line_color),
            name="Duration",
        )
    )

    if self.style_class.show_title:
        fig.update_layout(
            title=dict(
                text=f"Time spent on {event_name}",
                font=dict(size=16, color=self.font_color),
            )
        )

    if self.style_class.show_xaxis_title:
        fig.update_xaxes(title_text="Date")

    if self.style_class.show_yaxis_title:
        fig.update_yaxes(title_text="Duration (hours)")

    fig.update_layout(
        xaxis=dict(
            showgrid=self.style_class.show_grid,
            nticks=10,
            dtick="D5",
            gridcolor=self.grid_color,
            gridwidth=self.style_class.grid_width,
            titlefont=dict(size=14, color=self.font_color),
            tickfont=dict(size=12, color=self.font_color),
            tickcolor=self.font_color,
        ),
        yaxis=dict(
            showgrid=self.style_class.show_grid,
            gridwidth=self.style_class.grid_width,
            gridcolor=self.grid_color,
            titlefont=dict(size=14, color=self.font_color),
            tickfont=dict(size=12, color=self.font_color),
            tickcolor=self.font_color,
        ),
        margin=dict(l=50, r=50, t=80, b=50),
        width=self.style_class.width,
        height=self.style_class.height,
        plot_bgcolor=self.plot_bgcolor,
        paper_bgcolor=self.paper_bgcolor,
    )

    fig.update_traces(
        hovertemplate="<b>Date:</b> %{x} <br><b>Duration:</b> %{y:.2f} hours"
    )

    return fig

ManyEventPlot

Bases: Plot

Source code in google_calendar_analytics/visualization/visualizer_factory.py
class ManyEventPlot(Plot):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

    @abstractmethod
    async def plot(
        self,
        events: pd.DataFrame,
        title: str = "Title",
    ):
        """
        Analyze one event for a certain period of time.
        """

plot(events, title='Title') abstractmethod async

Analyze one event for a certain period of time.

Source code in google_calendar_analytics/visualization/visualizer_factory.py
@abstractmethod
async def plot(
    self,
    events: pd.DataFrame,
    title: str = "Title",
):
    """
    Analyze one event for a certain period of time.
    """

MultyLinePlot

Bases: OneEventPlot

Source code in google_calendar_analytics/visualization/visualizer_factory.py
class MultyLinePlot(OneEventPlot):
    async def plot(self, events: pd.DataFrame, event_name: str, **kwargs) -> go.Figure:
        """
        Plot a line chart of the event durations.

        Args:
            events (pd.DataFrame): A DataFrame containing the event dates as the index and the event durations as the values.
            event_name (str): The name of the event.
        """
        fig = go.Figure()

        # Create a separate line for each period
        for period in events.Period.unique():
            period_events = events[events.Period == period]
            period_start = period_events.Date.min().strftime("%m-%d")
            period_end = period_events.Date.max().strftime("%m-%d")
            period_label = f"{period_start} to {period_end}"
            fig.add_trace(
                go.Scatter(
                    x=period_events.Day,
                    y=period_events.Duration,
                    mode="lines+markers",
                    line=dict(width=2),
                    marker=dict(size=6),
                    name=period_label,
                    text=period_events.Date,
                    hovertemplate="<b>Date:</b> %{text} <br><b>Duration:</b> %{y:.2f} hours",
                    showlegend=self.style_class.show_legend,
                )
            )
            fig.update_layout(hovermode="x")

        if self.style_class.show_title:
            fig.update_layout(
                title=dict(
                    text=f"Time spent on {event_name}",
                    font=dict(size=16, color=self.font_color),
                )
            )

        if self.style_class.show_xaxis_title:
            fig.update_xaxes(title_text="Day")

        if self.style_class.show_yaxis_title:
            fig.update_yaxes(title_text="Duration (hours)")
        # Update the color scheme and set the title of the figure
        fig.update_layout(
            xaxis=dict(
                showgrid=self.style_class.show_grid,
                gridwidth=self.style_class.grid_width,
                dtick="D5",
                gridcolor=self.grid_color,
                titlefont=dict(size=14, color=self.font_color),
                tickfont=dict(size=12, color=self.font_color),
                tickcolor=self.font_color,
            ),
            yaxis=dict(
                showgrid=self.style_class.show_grid,
                gridwidth=self.style_class.grid_width,
                gridcolor=self.grid_color,
                titlefont=dict(size=14, color=self.font_color),
                tickfont=dict(size=12, color=self.font_color),
            ),
            margin=dict(l=50, r=50, t=80, b=50),
            width=self.style_class.width,
            height=self.style_class.height,
            plot_bgcolor=self.plot_bgcolor,
            paper_bgcolor=self.paper_bgcolor,
        )
        return fig

plot(events, event_name, **kwargs) async

Plot a line chart of the event durations.

Parameters:

Name Type Description Default
events pd.DataFrame

A DataFrame containing the event dates as the index and the event durations as the values.

required
event_name str

The name of the event.

required
Source code in google_calendar_analytics/visualization/visualizer_factory.py
async def plot(self, events: pd.DataFrame, event_name: str, **kwargs) -> go.Figure:
    """
    Plot a line chart of the event durations.

    Args:
        events (pd.DataFrame): A DataFrame containing the event dates as the index and the event durations as the values.
        event_name (str): The name of the event.
    """
    fig = go.Figure()

    # Create a separate line for each period
    for period in events.Period.unique():
        period_events = events[events.Period == period]
        period_start = period_events.Date.min().strftime("%m-%d")
        period_end = period_events.Date.max().strftime("%m-%d")
        period_label = f"{period_start} to {period_end}"
        fig.add_trace(
            go.Scatter(
                x=period_events.Day,
                y=period_events.Duration,
                mode="lines+markers",
                line=dict(width=2),
                marker=dict(size=6),
                name=period_label,
                text=period_events.Date,
                hovertemplate="<b>Date:</b> %{text} <br><b>Duration:</b> %{y:.2f} hours",
                showlegend=self.style_class.show_legend,
            )
        )
        fig.update_layout(hovermode="x")

    if self.style_class.show_title:
        fig.update_layout(
            title=dict(
                text=f"Time spent on {event_name}",
                font=dict(size=16, color=self.font_color),
            )
        )

    if self.style_class.show_xaxis_title:
        fig.update_xaxes(title_text="Day")

    if self.style_class.show_yaxis_title:
        fig.update_yaxes(title_text="Duration (hours)")
    # Update the color scheme and set the title of the figure
    fig.update_layout(
        xaxis=dict(
            showgrid=self.style_class.show_grid,
            gridwidth=self.style_class.grid_width,
            dtick="D5",
            gridcolor=self.grid_color,
            titlefont=dict(size=14, color=self.font_color),
            tickfont=dict(size=12, color=self.font_color),
            tickcolor=self.font_color,
        ),
        yaxis=dict(
            showgrid=self.style_class.show_grid,
            gridwidth=self.style_class.grid_width,
            gridcolor=self.grid_color,
            titlefont=dict(size=14, color=self.font_color),
            tickfont=dict(size=12, color=self.font_color),
        ),
        margin=dict(l=50, r=50, t=80, b=50),
        width=self.style_class.width,
        height=self.style_class.height,
        plot_bgcolor=self.plot_bgcolor,
        paper_bgcolor=self.paper_bgcolor,
    )
    return fig

OneEventPlot

Bases: Plot

Source code in google_calendar_analytics/visualization/visualizer_factory.py
class OneEventPlot(Plot):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

    @abstractmethod
    async def plot(
        self,
        events: pd.DataFrame,
        event_name: str,
    ):
        """
        Analyze one event for a certain period of time.
        """

plot(events, event_name) abstractmethod async

Analyze one event for a certain period of time.

Source code in google_calendar_analytics/visualization/visualizer_factory.py
@abstractmethod
async def plot(
    self,
    events: pd.DataFrame,
    event_name: str,
):
    """
    Analyze one event for a certain period of time.
    """

PiePlot

Bases: ManyEventPlot

Source code in google_calendar_analytics/visualization/visualizer_factory.py
class PiePlot(ManyEventPlot):
    async def plot(
        self,
        events: pd.DataFrame,
        title: str = "Top events with the Longest Duration",
        **kwargs,
    ) -> go.Figure:
        """
        Plot a pie chart of the event durations.

        Args:
            events (pd.DataFrame): A DataFrame containing the event names as the index and the event durations as the values.
            title (str): The title of the chart.
        """
        fig = go.Figure(
            go.Pie(
                labels=events.Event,
                values=events.Duration,
                textposition="auto",
                name="Duration",
                marker=dict(colors=self.style_class.rgb_colors),
                textinfo="label+percent",
                showlegend=self.style_class.show_legend,
            )
        )

        if self.style_class.show_title:
            fig.update_layout(
                title=title,
                title_font=dict(size=18, color=self.font_color),
            )

        fig.update_layout(
            width=self.style_class.width,
            height=self.style_class.height,
            plot_bgcolor=self.plot_bgcolor,
            paper_bgcolor=self.paper_bgcolor,
            font=dict(color=self.font_color),
        )
        fig.update_traces(
            hovertemplate="<b>Event:</b> %{label} <br><b>Duration:</b> \
                           %{value:.2f} hours<br><b>Percentage:</b> %{percent}",
        )
        return fig

plot(events, title='Top events with the Longest Duration', **kwargs) async

Plot a pie chart of the event durations.

Parameters:

Name Type Description Default
events pd.DataFrame

A DataFrame containing the event names as the index and the event durations as the values.

required
title str

The title of the chart.

'Top events with the Longest Duration'
Source code in google_calendar_analytics/visualization/visualizer_factory.py
async def plot(
    self,
    events: pd.DataFrame,
    title: str = "Top events with the Longest Duration",
    **kwargs,
) -> go.Figure:
    """
    Plot a pie chart of the event durations.

    Args:
        events (pd.DataFrame): A DataFrame containing the event names as the index and the event durations as the values.
        title (str): The title of the chart.
    """
    fig = go.Figure(
        go.Pie(
            labels=events.Event,
            values=events.Duration,
            textposition="auto",
            name="Duration",
            marker=dict(colors=self.style_class.rgb_colors),
            textinfo="label+percent",
            showlegend=self.style_class.show_legend,
        )
    )

    if self.style_class.show_title:
        fig.update_layout(
            title=title,
            title_font=dict(size=18, color=self.font_color),
        )

    fig.update_layout(
        width=self.style_class.width,
        height=self.style_class.height,
        plot_bgcolor=self.plot_bgcolor,
        paper_bgcolor=self.paper_bgcolor,
        font=dict(color=self.font_color),
    )
    fig.update_traces(
        hovertemplate="<b>Event:</b> %{label} <br><b>Duration:</b> \
                       %{value:.2f} hours<br><b>Percentage:</b> %{percent}",
    )
    return fig

PlotFactory(style_class, plot_type='Pie', event_name='Event') async

Factory method to create a plot object.

Parameters:

Name Type Description Default
plot_type str

The type of plot to create.

'Pie'
event_name str

The name of the event.

'Event'
style_class Type[base_plot_design]

The style class to use for the plot.

required
Source code in google_calendar_analytics/visualization/visualizer_factory.py
async def PlotFactory(
    style_class: Type[base_plot_design], plot_type="Pie", event_name="Event"
) -> Plot:
    """
    Factory method to create a plot object.

    Args:
        plot_type (str): The type of plot to create.
        event_name (str): The name of the event.
        style_class (Type[base_plot_design]): The style class to use for the plot.
    """

    plots = {
        "Pie": PiePlot,
        "Bar": BarPlot,
        "Line": LinePlot,
        "MultyLine": MultyLinePlot,
    }

    if plot_type not in plots:
        raise ValueError(
            f"Invalid plot type: '{plot_type}'.\n"
            f"Available options are: {', '.join(plots.keys())}."
        )

    return plots[plot_type](style_class=style_class, event_name=event_name)