Source code for kappa_sdk.plot

from ._private._field_api import FieldAPI
from ._private._well_dto import PlotInstanceDto, PlotInstancePaneDto
from ._private.dto_converters._plot_dto_converter import PlotDtoConverter
from .data import Data
from .vector import Vector
from typing import Union, List, Optional, Tuple
from .plot_channel import PlotChannel
from .plots_enum import PlotDataTypesEnum, PlotProperties
from datetime import datetime
from .measure_enum import MeasureEnum
from .datetime_utils import datetime_to_str
from .field_data_types_catalog import FieldDataTypesCatalog


[docs] class Plot: """ Plot object. Presents a KAPPA Automate Plot object. """ def __init__(self, field_id: str, well_id: str, plot_id: str, plot_name: str, field_api: FieldAPI, data_types_catalog: FieldDataTypesCatalog, dto_converter: PlotDtoConverter) -> None: self.__field_api: FieldAPI = field_api self.__field_id: str = field_id self.__well_id: str = well_id self.__id: str = plot_id self.__name: str = plot_name self.__data_types_catalog: FieldDataTypesCatalog = data_types_catalog self.__channels: List[PlotChannel] = list() self.__pane: List[PlotInstancePaneDto] = list() self.__dto_converter: PlotDtoConverter = dto_converter def rename(self, name: str) -> None: """ Rename the :class:`Plot` object. Parameters ---------- name: Name of the plot. """ dto = {'name': name} self.__name = self.__field_api.rename_plot(self.__field_id, self.__well_id, self.__id, dto) def add_existing_data(self, data: Data, channel_name: Optional[str] = None, pane_name: Optional[str] = None, show_symbols: Optional[bool] = None, show_lines: bool = True, use_elapsed: bool = False, is_y_log: bool = False, hide_in_legend: bool = False, is_raw: bool = False) -> PlotChannel: """ Add data to the :class:`Plot` object. Parameters ---------- data: Data to plot. channel_name: Name of the data. pane_name: Name of the pane. show_symbols: Show the point on the plot. show_lines: Show the lines on the plot. is_y_log: Show Y axis as log use_elapsed: use elapsed times instead of datetime values hide_in_legend: Whether this channel should be hidden or not on the legend is_raw: Whether to display raw data, as opposed to preview (default: false) Returns ------- :class:`PlotChannel`: A new Channel added to the :class:`Plot` object """ properties = PlotProperties(show_symbols=show_symbols, show_lines=show_lines, channel_name=channel_name, is_y_log=is_y_log, use_elapsed=use_elapsed, hide_in_legend=hide_in_legend, is_raw=is_raw) channel = PlotChannel(self.__field_id, self.__data_types_catalog, pane_name) channel.build_time_series(self.__well_id, data, properties) self.__channels.append(channel) return channel def add_embedded_data(self, data: Union[Vector, Tuple[List[float], List[float]]], channel_name: Optional[str] = None, pane_name: Optional[str] = None, show_symbols: Optional[bool] = None, show_lines: bool = True, data_type: Optional[Union[PlotDataTypesEnum, str]] = None, is_by_step: bool = False, x_measure: Optional[MeasureEnum] = None, y_measure: Optional[MeasureEnum] = None, is_y_log: bool = False, first_x: Optional[datetime] = None, use_elapsed: bool = False, hide_in_legend: bool = False) -> PlotChannel: """ Add data to the :class:`Plot` object. Parameters ---------- data: Data to plot. channel_name: Name of the data. pane_name: Name of the pane. show_symbols: Show the point on the plot. show_lines: Show the lines on the plot. data_type: Type of the data. is_by_step: True if it is step data. x_measure: Unit of the x_axis of the Channel (only for scatter plot). y_measure: Unit of the y_axis of the Channel. is_y_log: Show Y axis as log first_x: specify the first x of step data use_elapsed: use elapsed times instead of datetime values hide_in_legend: Whether this channel should be hidden or not on the legend Returns ------- :class:`PlotChannel`: A new Channel added to the :class:`Plot` object """ properties = PlotProperties(show_symbols=show_symbols, show_lines=show_lines, channel_name=channel_name, is_by_step=is_by_step, x_measure=x_measure, y_measure=y_measure, first_x=datetime_to_str(first_x), use_elapsed=use_elapsed, hide_in_legend=hide_in_legend, is_y_log=is_y_log) channel = PlotChannel(self.__field_id, self.__data_types_catalog, pane_name) channel.build_embedded(self.__well_id, data, data_type, properties) self.__channels.append(channel) return channel def add_cross_plot_data(self, x_data: Data, y_data: Data, channel_name: Optional[str] = None, pane_name: Optional[str] = None, show_symbols: Optional[bool] = None, show_lines: bool = True, data_type: Optional[Union[PlotDataTypesEnum, str]] = None, is_y_log: bool = False, hide_in_legend: bool = False) -> PlotChannel: """ Adds cross plot data to the visualization, enabling plotting of X versus Y data points with customizable display options and metadata. This function is used to define how data is represented in a cross plot channel and associated visualization components. Parameters ---------- x_data : Data The dataset representing the X-axis values for the cross plot. y_data : Data The dataset representing the Y-axis values for the cross plot. channel_name : Optional[str], optional An optional name associated with the created plot channel. Defaults to None. pane_name : Optional[str], optional An optional pane name where the cross plot is defined. Defaults to None. show_symbols : Optional[bool], optional Indicates if symbols should be displayed on the plot. Defaults to None. show_lines : bool, optional Determines whether lines should be displayed connecting the data points. Defaults to True. data_type : Optional[Union[PlotDataTypesEnum, str]], optional Indicates the data type of the plot, allowing for specific type categorization. Defaults to None. is_y_log : bool, optional Specifies whether the Y-axis of the plot should use a logarithmic scale. Defaults to False. hide_in_legend : bool, optional Determines if the plot should be hidden from the legend in the visualization. Defaults to False. Returns ------- PlotChannel The constructed and configured plot channel that represents the cross plot data and associated properties. """ properties = PlotProperties(show_symbols=show_symbols, show_lines=show_lines, channel_name=channel_name, hide_in_legend=hide_in_legend, is_y_log=is_y_log) channel = PlotChannel(self.__field_id, self.__data_types_catalog, pane_name) channel.build_cross_plot_channel(self.__well_id, x_data.vector_id, y_data.vector_id, data_type, properties) self.__channels.append(channel) return channel def update_plot(self) -> None: """ Update the plot in Kappa Automate""" plot_dto = self.__field_api.get_plot_dto(self.__field_id, self.__well_id, self.__id) updated_plot_dto = self.__dto_converter.get_plot_update_dto(plot_dto, self.__channels, self.__pane) try: self.__field_api.update_plot(self.__field_id, self.__well_id, self.__id, updated_plot_dto) self.__pane = list() self.__channels = list() except ConnectionError as error: if error.args[0].split(" ")[1] == str(400): raise ValueError("You probably have nan or None values in your data, you need to remove them") self.delete() raise error def get_plot_dto(self) -> PlotInstanceDto: """ Get the plot dto from Kappa Automate Returns ------- :class:`PlotInstanceDto`: The Plot instance dto from Kappa Automate """ return self.__field_api.get_plot_dto(self.__field_id, self.__well_id, self.__id) def delete(self) -> None: """ Delete the current plot """ self.__field_api.delete_plot(self.__field_id, self.__well_id, self.__id) @property def id(self) -> str: """ Gets the id of the :class:`Plot` object. """ return self.__id @property def name(self) -> str: """ Gets the name of the :class:`Plot` object. """ return self.__name def add_sub_plot(self, name: str, square_log_cycles: bool = False, stacked_bars: bool = False) -> None: """ Add a new subplot or pane to the :class:`Plot` object Parameters ---------- name: The name of the subplot square_log_cycles: Whether or not to use squared logarithmic cycles stacked_bars: Whether or not to use stacked bars """ pane = PlotInstancePaneDto(name=name, squareLogCycles=square_log_cycles, stackedBars=stacked_bars, channels=[]) self.__pane.append(pane)