kitikiplot 0.1.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
kitikiplot/__init__.py ADDED
@@ -0,0 +1 @@
1
+ from .kitikiplot import KitikiPlot
@@ -0,0 +1,167 @@
1
+ """
2
+ File Name: kitiki_cell.py
3
+ Description: This file defines the 'KitikiCell' class for each rectangular cell in kitiki plot
4
+ Author: Boddu Sri Pavan
5
+ Date Created: 21-10-2024
6
+ Last Modified: 07-12-2024
7
+ """
8
+
9
+ from typing import List, Dict, Union
10
+ import pandas as pd
11
+ import matplotlib.patches as mpatches
12
+ from matplotlib.patches import Rectangle
13
+ from .kitiki_color_config import ColorConfig
14
+
15
+ class KitikiCell(ColorConfig):
16
+ """
17
+ Represents a cell in the KitikiPlot visualization.
18
+
19
+ This class extends the ColorConfig class to add functionality for creating
20
+ individual cells in a grid-based visualization.
21
+
22
+ Parameters
23
+ ----------
24
+ data : pd.DataFrame or list
25
+ - The input data which can be either a 'pd.DataFrame' or a 'list'.
26
+ - If a list is provided, it will be converted into a DataFrame using specified stride and window length.
27
+ stride : int (optional)
28
+ - The number of elements to move the window after each iteration when converting a list to a DataFrame.
29
+ - Default is 1.
30
+ window_length : int (optional)
31
+ - The length of each window when converting a list to a DataFrame.
32
+ - Default is 10.
33
+
34
+ Attributes
35
+ ----------
36
+ stride : int
37
+ - The number of elements to move the window after each iteration when converting a list to a DataFrame.
38
+ - Default is 1.
39
+ """
40
+
41
+ def __init__(self, data: Union[pd.DataFrame, list], stride: int = 1, window_length: int = 10) -> None:
42
+ """
43
+ Initialize the KitikiCell object by inheriting from ColorConfig.
44
+
45
+ Parameters
46
+ ----------
47
+ data : pd.DataFrame or list
48
+ - The input data to be processed.
49
+ stride : int (optional)
50
+ - The number of elements to move the window after each iteration when converting a list to a DataFrame.
51
+ - Default is 1.
52
+ window_length : int (optional)
53
+ - The length of each window when converting a list to a DataFrame.
54
+ - Default is 10.
55
+
56
+ Attributes
57
+ ----------
58
+ stride : int
59
+ - The number of elements to move the window after each iteration when converting a list to a DataFrame.
60
+ - Default is 1.
61
+ """
62
+
63
+ super().__init__(data=data, stride= stride, window_length= window_length)
64
+
65
+
66
+ def create( self,
67
+ x: int,
68
+ y: int,
69
+ each_sample: List,
70
+ cell_width: float,
71
+ cell_height: float,
72
+ window_gap: float,
73
+ align: bool,
74
+ cmap: Union[str, Dict],
75
+ edge_color: str,
76
+ fallback_color: str,
77
+ hmap: Dict,
78
+ fallback_hatch: str,
79
+ display_hatch: bool,
80
+ transpose: bool,
81
+ **kitiki_cell_kwargs: dict) -> mpatches.Rectangle:
82
+
83
+ """
84
+ Create a rectangular cell for the KitikiPlot visualization.
85
+
86
+ Parameters
87
+ ----------
88
+ x : int
89
+ - The x-coordinate of the cell in the grid.
90
+ y : int
91
+ - The y-coordinate of the cell in the grid.
92
+ each_sample : list
93
+ - A list containing each data record used for determining color and hatch patterns to plot KitikiPlot.
94
+ cell_width : float
95
+ - The width of each cell in the grid.
96
+ - Default is 0.5.
97
+ cell_height : float
98
+ - The height of each cell in the grid.
99
+ - Default is 2.0.
100
+ window_gap : float
101
+ - The gap between cells in the grid.
102
+ - Default is 1.0.
103
+ align : bool
104
+ - A flag indicating whether to shift consecutive bars vertically (if transpose= False), and
105
+ horizontally(if transpose= True) by stride value.
106
+ - Default is True.
107
+ cmap : str or dict
108
+ - If a string, it should be a colormap name to generate colors.
109
+ - If a dictionary, it should map unique values to specific colors.
110
+ - Default is 'rainbow'.
111
+ edge_color : str
112
+ - The color to use for the edges of the rectangle.
113
+ - Default is '#000000'.
114
+ fallback_color : str
115
+ - The color to use as fallback if no specific color is assigned.
116
+ - Default is '#FAFAFA'.
117
+ hmap : dict
118
+ - A dictionary mapping unique values to their corresponding hatch patterns.
119
+ - Default is '{}'.
120
+ fallback_hatch : str
121
+ - The hatch pattern to use as fallback if no specific hatch is assigned.
122
+ - Default is '" "' (string with single space).
123
+ display_hatch : bool
124
+ - A flag indicating whether to display hatch patterns on cells.
125
+ - Default is False.
126
+ transpose : bool
127
+ - A flag indicating whether to transpose the dimensions of the cells.
128
+ - Default is False.
129
+ kitiki_cell_kwargs : keyword arguments
130
+ - Additional keyword arguments passed to customize the Rectangle object.
131
+ - Default is {}.
132
+
133
+ Returns
134
+ -------
135
+ matplotlib.patches.Rectangle: A Rectangle object representing the configured cell for KitikiPlot visualization.
136
+ """
137
+
138
+ # Adjust dimensions if 'transpose' is set to 'False'
139
+ if not transpose:
140
+
141
+ # Calculate alignment factor based on whether alignment is enabled
142
+ align_factor= (self.rows-x)*self.stride*cell_height if align else 0
143
+
144
+ # Calculate dimensions for the rectangle based on grid position and size parameters
145
+ rect_dim= (window_gap*(x+1)+ cell_width*(x+1) , cell_height*(self.cols-y-1)+align_factor)
146
+
147
+ # Adjust dimensions if 'transpose' is set to 'True'
148
+ else:
149
+
150
+ # Set cell width to 2.0 for transposed cells to enhance visualization
151
+ # cell_width= 2.0
152
+
153
+ # Calculate alignment factor for transposed configuration based on whether alignment is enabled
154
+ align_factor= x*self.stride*cell_height if align else 0
155
+
156
+ # Calculate dimensions for the rectangle based on grid position and size parameters for transposed layout
157
+ rect_dim= (cell_height*(y+1)+ align_factor, window_gap*(self.rows- x+1)+ cell_width*(self.rows- x+1))
158
+
159
+ # Return a Rectangle object with specified dimensions and styles based on input parameters
160
+ return Rectangle( rect_dim,
161
+ width= cell_width,
162
+ height= cell_height,
163
+ facecolor= cmap[0][ each_sample[y] ],
164
+ edgecolor= cmap[1],
165
+ hatch= hmap[each_sample[y]],
166
+ **kitiki_cell_kwargs
167
+ )
@@ -0,0 +1,266 @@
1
+ """
2
+ File Name: kitiki_color_config.py
3
+ Description: This file defines the 'ColorConfig' class for managing input data(list, dataframe) and configuring color, hatch of kitiki plot
4
+ Author: Boddu Sri Pavan
5
+ Date Created: 21-10-2024
6
+ Last Modified: 23-11-2024
7
+ """
8
+ from typing import Tuple, Union, Dict
9
+ import random
10
+ import math
11
+ import numpy as np
12
+ import pandas as pd
13
+ import matplotlib
14
+ import matplotlib.pyplot as plt
15
+
16
+ class ColorConfig:
17
+ """
18
+ Configure data, color, and hatch settings for KitikiPlot visualization.
19
+
20
+ Parameters
21
+ ----------
22
+ data : pd.DataFrame or list
23
+ - The input data which can be either a pandas DataFrame or a list.
24
+ - If a list is provided, it will be converted into a DataFrame using specified stride and window length.
25
+ stride : int (optional)
26
+ - The number of elements to move the window after each iteration when converting a list to a DataFrame.
27
+ - Default is 1.
28
+ window_length : int (optional)
29
+ - The length of each window when converting a list to a DataFrame.
30
+ - Default is 10.
31
+
32
+ Attributes
33
+ ----------
34
+ data : pd.DataFrame
35
+ - The DataFrame containing the input data.
36
+ stride : int
37
+ - The number of elements to move the window after each iteration when converting a list to a DataFrame.
38
+ - Default is 1.
39
+ rows : int
40
+ - The number of rows in the DataFrame.
41
+ cols : int
42
+ - The number of columns in the DataFrame.
43
+
44
+ Methods
45
+ -------
46
+ Instance Methods
47
+ - color_config: Configure colors for unique values in the DataFrame.
48
+ - hatch_config: Configure hatch patterns for unique values in the DataFrame.
49
+ - unique_config: Find unique values and their count from the input DataFrame.
50
+
51
+ Static Methods
52
+ - _convert_list_to_dataframe: Convert a list into a pandas DataFrame using sliding window.
53
+ """
54
+
55
+ def __init__(self, data: Union[pd.DataFrame, list], stride: int = 1, window_length: int = 10) -> None:
56
+ """
57
+ Initialize the ColorConfig object with data and optional parameters.
58
+ Also checks the type of input data and initializes the corresponding attributes.
59
+
60
+ Parameters
61
+ ----------
62
+ data : pd.DataFrame or list
63
+ - The input data to be processed.
64
+ stride : int (optional)
65
+ - The number of elements to move the window after each iteration when converting a list to a DataFrame.
66
+ - Default is 1.
67
+ window_length : int (optional)
68
+ - The length of each window when converting a list to a DataFrame.
69
+ - Default is 10.
70
+
71
+ Attributes
72
+ ----------
73
+ stride : int
74
+ - The number of elements to move the window after each iteration when converting a list to a DataFrame.
75
+ - Default is 1.
76
+ """
77
+
78
+ # Check if 'data' is of type 'pd.DataFrame' and initialize 'data' attribute.
79
+ if isinstance( data, pd.DataFrame):
80
+ self.data= data
81
+
82
+ # Check if 'data' is of type 'list'.
83
+ elif isinstance( data, list):
84
+
85
+ # Convert 'list' to 'pd.DataFrame' using stride and window_length, and initialize 'data' attribute.
86
+ self.data= self._convert_list_to_dataframe( data, stride, window_length)
87
+
88
+ # Store the stride value
89
+ self.stride= stride
90
+
91
+ # Set 'rows' to number of rows in the DataFrame.
92
+ self.rows= self.data.shape[0]
93
+
94
+ # Set 'cols' to number of columns in the DataFrame.
95
+ self.cols= self.data.shape[1]
96
+
97
+ @staticmethod
98
+ def _convert_list_to_dataframe( data: Union[pd.DataFrame, list], stride: int = 1, window_length: int = 10) -> pd.DataFrame:
99
+ """
100
+ Convert list into a 'pd.DataFrame' by creating sliding window of specified window length.
101
+
102
+ Parameters
103
+ ----------
104
+ data : pd.DataFrame or list
105
+ - The input data to be processed.
106
+ stride : int (optional)
107
+ - The number of elements to move the window after each iteration when converting a list to a DataFrame.
108
+ - Default is 1.
109
+ window_length : int (optional)
110
+ - The length of each window when converting a list to a DataFrame.
111
+ - Default is 10.
112
+
113
+ Returns
114
+ -------
115
+ pd.DataFrame: A DataFrame containing the sliding window of data.
116
+ """
117
+
118
+ # Calculate the number of rows needed in the DataFrame
119
+ n_rows= math.ceil(max(len(data)-window_length, 0)/ stride +1)
120
+
121
+ # Initialize an empty list to hold the rows of data
122
+ l= []
123
+
124
+ # Generate each row based on the sliding window approach
125
+ for i in range( n_rows ):
126
+
127
+ # Extract a slice from the data based on current stride and window length
128
+ row_data= data[i*stride: i*stride+window_length]
129
+
130
+ # If the extracted row is shorter than the window length, pad it with "No_Data"
131
+ if len(row_data)< window_length:
132
+ row_data+= ["No_Data"]* (window_length- len(row_data))
133
+
134
+ # Append the row to the list
135
+ l.append( row_data )
136
+
137
+ # Convert the list of rows into a 'pd.DataFrame' and return it
138
+ return pd.DataFrame( l )
139
+
140
+ def unique_config(self) -> Tuple[np.ndarray, int]:
141
+ """
142
+ Find unique values and no.of unique values from input DataFrame.
143
+
144
+ Returns
145
+ -------
146
+ tuple: (unique_values, n_unique)
147
+ unique_values : numpy.ndarray
148
+ - Array of unique values present in the input DataFrame.
149
+ n_unique : int
150
+ - Number of unique values present in the input DataFrame.
151
+ """
152
+
153
+ # Extract unique values from the input DataFrame by flattening it
154
+ unique_values= pd.unique( self.data.values.ravel())
155
+
156
+ # Calculate the number of unique values found in the DataFrame
157
+ n_unique= unique_values.shape[0]
158
+
159
+ # Return both the array of unique values and their count
160
+ return unique_values, n_unique
161
+
162
+ def color_config(self, cmap: Union[str, Dict], edge_color: str, fallback_color: str) -> Tuple[Dict, str]:
163
+ """
164
+ Configure colors for unique values in the DataFrame.
165
+
166
+ Parameters
167
+ ----------
168
+ cmap : str or dict
169
+ - If a string, it should be a colormap name to generate colors.
170
+ - If a dictionary, it should map unique values to specific colors.
171
+ - Default is 'rainbow'.
172
+ edge_color : str
173
+ - The color to use for the edges of the rectangle.
174
+ - Default is '#000000'.
175
+ fallback_color : str
176
+ - The color to use as fallback if no specific color is assigned.
177
+ - Default is '#FAFAFA'.
178
+
179
+ Returns
180
+ -------
181
+ tuple: (color_map, edge_color)
182
+ color_map : dict
183
+ - A dictionary mapping unique values to their corresponding colors.
184
+ edge_color : str
185
+ - The specified edge color.
186
+ """
187
+
188
+ # Find unique values and their count from the input DataFrame
189
+ unique_values, n_unique= self.unique_config()
190
+
191
+ # Check if cmap is a string representing a colormap name
192
+ if type(cmap)== str:
193
+
194
+ # Get the colormap and create a custom palette based on the number of unique values
195
+ cmap = plt.get_cmap( cmap, n_unique)
196
+ custom_palette = [matplotlib.colors.rgb2hex(cmap(i)) for i in range(cmap.N)]
197
+
198
+ # Create a mapping of unique values to their corresponding colors
199
+ color_map= dict(zip(unique_values, custom_palette))
200
+
201
+ # Check if cmap is a dictionary
202
+ elif type(cmap)==dict:
203
+
204
+ color_map= cmap
205
+
206
+ # Ensure all unique values are represented in the color_map
207
+ if len(cmap)!= n_unique:
208
+ for each_unique in unique_values:
209
+ if each_unique not in color_map:
210
+
211
+ # Assign fallback color for any missing unique value
212
+ color_map.update( {each_unique: fallback_color} )
213
+
214
+ # Return the final color mapping and the specified edge color
215
+ return color_map, edge_color
216
+
217
+ def hatch_config(self, h_map: Dict, fallback_hatch: str, display_hatch: bool) -> dict:
218
+ """
219
+ Configure hatch patterns for unique values in the DataFrame.
220
+
221
+ Parameters
222
+ ----------
223
+ hmap : dict
224
+ - A dictionary mapping unique values to their corresponding hatch patterns.
225
+ - Default is '{}'.
226
+ fallback_hatch : str
227
+ - The hatch pattern to use as fallback if no specific hatch is assigned.
228
+ - Default is '" "' (string with single space).
229
+ display_hatch : bool
230
+ - A flag indicating whether to display hatch patterns on cells.
231
+ - Default is False.
232
+
233
+ Returns
234
+ -------
235
+ dict: A dictionary mapping each unique value to its corresponding hatch pattern.
236
+ """
237
+
238
+ # Define a list of available hatch patterns
239
+ HATCH_PATTERN= ['o', '/', '*', '\\','..', '+o', 'x*', 'o-', '|', '-', '+', 'x', 'O', '.', '//', '\\\\', '||', '--', '++', 'xx', 'oo', 'OO', '**', '/o', '\\|', '|*', '-\\', 'O|', 'O.', '*-']
240
+
241
+ # Retrieve unique values and their count from the DataFrame
242
+ unique_values, n_unique= self.unique_config()
243
+
244
+ # If 'display_hatch' is False, set all hatch patterns to a space
245
+ if display_hatch== False:
246
+ h_map= dict(zip(unique_values, [" "]*n_unique))
247
+
248
+ # If 'display_hatch' is True and the length of 'h_map' matches the number of unique values
249
+ elif display_hatch== True and len(h_map)== n_unique:
250
+ h_map= dict(zip(unique_values, h_map))
251
+
252
+ # If 'display_hatch' is True and 'h_map' has fewer entries than unique values
253
+ elif display_hatch== True and 0<len(h_map)< n_unique:
254
+ h_map= h_map
255
+ for each_unique_value in unique_values:
256
+ if each_unique_value not in h_map:
257
+
258
+ # Assign fallback hatch pattern for any missing unique value
259
+ h_map.update( {each_unique_value: fallback_hatch} )
260
+
261
+ # If 'display_hatch' is True and 'h_map' is empty, assign default hatch patterns
262
+ elif display_hatch== True and len(h_map)==0:
263
+ h_map= dict(zip(unique_values, HATCH_PATTERN[:n_unique]))
264
+
265
+ # Return the configured 'h_map'
266
+ return h_map
@@ -0,0 +1,446 @@
1
+ """
2
+ File Name: Kiti.py
3
+ Description: This file defines the 'KitikiPlot' class for generating kitki plot for categorical sequential& time-series data
4
+ Author: Boddu Sri Pavan
5
+ Date Created: 21-10-2024
6
+ Last Modified: 23-11-2024
7
+ """
8
+
9
+ from typing import List, Union
10
+ import pandas as pd
11
+ import matplotlib
12
+ import matplotlib.pyplot as plt
13
+ import matplotlib.patches as mpatches
14
+ from .kitiki_cell import KitikiCell
15
+
16
+ class KitikiPlot(KitikiCell):
17
+ """
18
+ A class to create a Kitikiplot visualization based on sliding window data.
19
+
20
+ This class extends the KitikiCell class to provide functionality for plotting
21
+ KitikiPlot, where each cell can be customized with colors, hatches,
22
+ and other visual properties.
23
+
24
+ Parameters
25
+ ----------
26
+ data : pd.DataFrame or list
27
+ - The input data to be processed.
28
+ stride : int (optional)
29
+ - The number of elements to move the window after each iteration when converting a list to a DataFrame.
30
+ - Default is 1.
31
+ window_length : int (optional)
32
+ - The length of each window when converting a list to a DataFrame.
33
+ - Default is 10.
34
+
35
+ Attributes
36
+ ----------
37
+ stride : int
38
+ - The number of elements to move the window after each iteration when converting a list to a DataFrame.
39
+ - Default is 1.
40
+ """
41
+
42
+ def __init__(self, data: Union[pd.DataFrame, List], stride: int = 1, window_length: int = 10) -> None:
43
+ """
44
+ Initialize the KitikiPlot object by inheriting from KitikiCell.
45
+
46
+ Parameters
47
+ ----------
48
+ data : pd.DataFrame or list
49
+ - The input data to be processed.
50
+ stride : int (optional)
51
+ - The number of elements to move the window after each iteration when converting a list to a DataFrame.
52
+ - Default is 1.
53
+ window_length : int (optional)
54
+ - The length of each window when converting a list to a DataFrame.
55
+ - Default is 10.
56
+
57
+ Attributes
58
+ ----------
59
+ stride : int
60
+ - The number of elements to move the window after each iteration when converting a list to a DataFrame.
61
+ - Default is 1.
62
+ """
63
+ super().__init__(data=data, stride= stride, window_length= window_length)
64
+
65
+ def plot( self,
66
+ figsize: tuple = (25, 5),
67
+ cell_width: float = 0.5,
68
+ cell_height: float = 2.0,
69
+ window_gap: float = 1.0,
70
+ window_range: str | tuple = "all",
71
+ align: bool = True,
72
+ cmap: str | dict = "rainbow",
73
+ edge_color: str = "#000000",
74
+ fallback_color: str = "#FAFAFA",
75
+ hmap: dict = {},
76
+ fallback_hatch: str = " ",
77
+ display_hatch: bool = False,
78
+ transpose: bool = False,
79
+ xlabel: str = "Sliding Windows",
80
+ ylabel: str = "Frames",
81
+ display_xticks: bool = True,
82
+ display_yticks: bool = True,
83
+ xtick_prefix: str = "Window",
84
+ ytick_prefix: str = "Frame",
85
+ xticks_values: list = [],
86
+ yticks_values: list = [],
87
+ xticks_rotation: int = 0,
88
+ yticks_rotation: int = 0,
89
+ title: str = "KitikiPlot: Intuitive Visualization for Sliding Window",
90
+ display_grid: bool = False,
91
+ display_legend: bool = False,
92
+ legend_hatch: bool = False,
93
+ legend_kwargs: dict = {},
94
+ kitiki_cell_kwargs: dict = {}
95
+ ) -> None:
96
+ """
97
+ Create and display the Kitikiplot visualization.
98
+
99
+ This method generates a plot based on the provided parameters and data. It configures
100
+ colors, hatches, and dimensions for each cell in the grid.
101
+
102
+ Parameters
103
+ ----------
104
+ figsize : tuple (optional)
105
+ - The size of the figure (width, height).
106
+ - Default is (25, 5).
107
+ cell_width : float
108
+ - The width of each cell in the grid.
109
+ - Default is 0.5.
110
+ cell_height : float
111
+ - The height of each cell in the grid.
112
+ - Default is 2.0.
113
+ window_gap : float
114
+ - The gap between cells in the grid.
115
+ - Default is 1.0.
116
+ window_range : str or tuple (optional)
117
+ - The range of windows to display.
118
+ - Use "all" to show all windows or specify a tuple (start_index, end_index).
119
+ - Default is "all".
120
+ align : bool
121
+ - A flag indicating whether to shift consecutive bars vertically (if transpose= False), and
122
+ horizontally(if transpose= True) by stride value.
123
+ - Default is True.
124
+ cmap : str or dict
125
+ - If a string, it should be a colormap name to generate colors.
126
+ - If a dictionary, it should map unique values to specific colors.
127
+ - Default is 'rainbow'.
128
+ edge_color : str
129
+ - The color to use for the edges of the rectangle.
130
+ - Default is '#000000'.
131
+ fallback_color : str
132
+ - The color to use as fallback if no specific color is assigned.
133
+ - Default is '#FAFAFA'.
134
+ hmap : dict
135
+ - A dictionary mapping unique values to their corresponding hatch patterns.
136
+ - Default is '{}'.
137
+ fallback_hatch : str
138
+ - The hatch pattern to use as fallback if no specific hatch is assigned.
139
+ - Default is '" "' (string with single space).
140
+ display_hatch : bool
141
+ - A flag indicating whether to display hatch patterns on cells.
142
+ - Default is False.
143
+ transpose : bool (optional)
144
+ - A flag indicating whether to transpose the KitikiPlot.
145
+ - Default is False.
146
+ xlabel : str (optional)
147
+ - Label for the x-axis.
148
+ - Default is "Sliding Windows".
149
+ ylabel : str (optional)
150
+ - Label for the y-axis.
151
+ - Default is "Frames".
152
+ display_xticks : bool (optional)
153
+ - A flag indicating whether to display xticks
154
+ - Default is True
155
+ display_yticks : bool (optional)
156
+ - A flag indicating whether to display yticks
157
+ - Default is True
158
+ xtick_prefix : str (optional)
159
+ - Prefix for x-axis tick labels.
160
+ - Default is "Window".
161
+ ytick_prefix : str (optional)
162
+ - Prefix for y-axis tick labels.
163
+ - Default is "Frame".
164
+ xticks_values : list (optional)
165
+ - List containing the values for xticks
166
+ - Default is []
167
+ yticks_values : list (optional)
168
+ - List containing the values for yticks
169
+ - Default is []
170
+ xticks_rotation : int (optional)
171
+ - Rotation angle for x-axis tick labels.
172
+ - Default is 0.
173
+ yticks_rotation : int (optional)
174
+ - Rotation angle for y-axis tick labels.
175
+ - Default is 0.
176
+ title : str (optional)
177
+ - The title of the plot.
178
+ - Default is "KitikiPlot: Intuitive Visualization for Sliding Window".
179
+ display_grid : bool (optional)
180
+ - A flag indicating whether to display grid on the plot.
181
+ - Default is False.
182
+ display_legend : bool (optional)
183
+ - A flag indicating whether to display a legend on the plot.
184
+ - Default is False.
185
+ legend_hatch : bool (optional)
186
+ - A flag indicating whether to include hatch patterns in the legend.
187
+ - Default is False.
188
+ legend_kwargs : dict (optional)
189
+ - Additional keyword arguments passed to customize the legend.
190
+ - Default is {}.
191
+ kitiki_cell_kwargs : dict (optional)
192
+ - Additional keyword arguments passed to customize individual cells.
193
+ - Default is {}.
194
+
195
+ Returns
196
+ -------
197
+ None: Displays the plot directly.
198
+ """
199
+
200
+ # Configure color mapping based on user input
201
+ self.color_map= self.color_config( cmap= cmap, edge_color= edge_color, fallback_color= fallback_color )
202
+
203
+ # Determine if hatching should be displayed based on 'hmap' presence
204
+ if len(hmap)> 0:
205
+ display_hatch= True
206
+
207
+ # If 'display_hatch' is False and 'hmap' not given; default hatch settings are applied
208
+ if not display_hatch:
209
+ hmap= " "
210
+ fallback_hatch= " "
211
+
212
+ # Configure hatch mapping based on user input and conditions
213
+ self.hatch_map= self.hatch_config( h_map= hmap, fallback_hatch= fallback_hatch, display_hatch= display_hatch)
214
+
215
+ # Create figure and axis for plotting
216
+ fig, ax = plt.subplots( figsize= figsize)
217
+
218
+ # List to hold cell patches
219
+ patches= []
220
+
221
+ # Prepare data for plotting
222
+ data= self.data.values
223
+
224
+ # Check if the specified window range is set to "all"
225
+ if window_range== "all":
226
+
227
+ # If "all" is specified, set window_range to cover all rows in the data
228
+ window_range= range(self.rows)
229
+
230
+ else:
231
+
232
+ # If a specific range is provided, create a range object from the start to end index
233
+ # This allows for plotting only a subset of the data based on the user-defined range
234
+ window_range= range( window_range[0], window_range[1])
235
+
236
+ # Generate cells for each sample in the specified window range and time frame columns
237
+ for index in window_range:
238
+
239
+ each_sample= data[ index ]
240
+
241
+ for time_frame in range(self.cols):
242
+
243
+ # Create each cell using specified parameters and add it to patches list
244
+ cell_gen= self.create( x= index,
245
+ y= time_frame,
246
+ each_sample= each_sample,
247
+ cell_width= cell_width,
248
+ cell_height= cell_height,
249
+ window_gap= window_gap,
250
+ align= align,
251
+ edge_color= edge_color,
252
+ cmap= self.color_map,
253
+ fallback_color= fallback_color,
254
+ hmap= self.hatch_map,
255
+ fallback_hatch= fallback_hatch,
256
+ display_hatch= display_hatch,
257
+ transpose= transpose,
258
+ **kitiki_cell_kwargs
259
+ )
260
+ patches.append( cell_gen )
261
+
262
+ # Set plot titles
263
+ plt.title(title)
264
+
265
+ # Configure ticks based on transposition setting
266
+ if not transpose:
267
+
268
+ # Calculate x and y positions for ticks when not transposed
269
+ x_positions= [(i+1)*window_gap+(i+1)*cell_width+cell_width/2 for i in range(self.rows)]
270
+
271
+ y_positions= [(self.rows+ self.cols- self.stride- i)*cell_height+cell_height/2 for i in range(self.stride*self.rows+self.cols)]
272
+
273
+ # Display xticks if 'display_xticks' is True
274
+ if display_xticks:
275
+
276
+ # Configure xticks based on input 'xticks_values'
277
+ if xticks_values:
278
+
279
+ # Find no.of 'xticks_values'
280
+ n_xticks_values= len(xticks_values)
281
+
282
+ # Set x-ticks with the input 'xticks_values'
283
+ plt.xticks( x_positions[:n_xticks_values], xticks_values, rotation= xticks_rotation)
284
+
285
+ # Configure default xticks
286
+ else:
287
+
288
+ # Set x-ticks with appropriate labels (with default prefixes) and rotation
289
+ plt.xticks( x_positions, [xtick_prefix+'_'+str(i+1) for i in range(self.rows)], rotation= xticks_rotation)
290
+
291
+ # Else turn off the xticks
292
+ else:
293
+ plt.xticks([], [])
294
+
295
+ # Display yticks if 'display_yticks' is True
296
+ if display_yticks:
297
+
298
+ # Configure yticks based on input 'yticks_values
299
+ if yticks_values:
300
+
301
+ # Find no.of 'yticks_values'
302
+ n_yticks_values= len(yticks_values)
303
+
304
+ # Set y-ticks with the input 'yticks_values'
305
+ plt.yticks( y_positions[:n_yticks_values], yticks_values, rotation= yticks_rotation)
306
+
307
+ # Configure default yticks
308
+ else:
309
+
310
+ # Set y-ticks with appropriate labels and rotation
311
+ plt.yticks( y_positions, [ytick_prefix+"_"+str(i) for i in range(self.stride*self.rows+self.cols)], rotation= yticks_rotation)
312
+
313
+ # Else turn off the yticks
314
+ else:
315
+ plt.yticks([], [])
316
+
317
+ # Draw grid lines if display_grid is True
318
+ if display_grid:
319
+ hline_positions= [(self.rows+ self.cols- self.stride- i)*cell_height for i in range(self.stride*self.rows+self.cols+1)]
320
+ ax.hlines(y= hline_positions+[max(hline_positions)+cell_height], xmin=0, xmax=max(x_positions) + cell_width, colors='gray', linestyles='--', linewidth=0.5)
321
+
322
+ else:
323
+
324
+ # Calculate x and y positions for ticks when transposed
325
+ x_positions= [(i+1)*cell_height+cell_height/2 for i in range(self.stride*(self.rows-1)+ self.cols)]
326
+ y_positions= [(self.rows-i+1)*window_gap+(self.rows-i+1)*cell_width+cell_width/2 for i in range(self.rows)]
327
+ # Display xticks if 'display_xticks' is True
328
+ if display_xticks:
329
+
330
+ # Configure xticks based on input 'xticks_values'
331
+ if xticks_values:
332
+
333
+ # Find no.of 'xticks_values'
334
+ n_xticks_values= len( xticks_values )
335
+
336
+ # Set x-ticks with the input 'xticks_values'
337
+ plt.xticks( x_positions[:n_xticks_values], xticks_values, rotation= xticks_rotation)
338
+
339
+ # Configure default xticks
340
+ else:
341
+
342
+ # Set x-ticks with appropriate labels and rotation (note the switch of prefixes)
343
+ plt.xticks( x_positions, [xtick_prefix+"_"+str(i+1) for i in range(self.stride*(self.rows-1)+ self.cols)], rotation= xticks_rotation)
344
+
345
+ # Else turn off the xticks
346
+ else:
347
+ plt.xticks([], [])
348
+
349
+
350
+ # Display yticks if 'display_yticks' is True
351
+ if display_yticks:
352
+
353
+ # Configure yticks based on input 'yticks_values'
354
+ if yticks_values:
355
+
356
+ # Find no.of 'yticks_values'
357
+ n_yticks_values= len( yticks_values )
358
+
359
+ # Set y-ticks with the input 'yticks_values'
360
+ plt.yticks( y_positions[:n_yticks_values], yticks_values, rotation= yticks_rotation)
361
+
362
+ # Configure default yticks
363
+ else:
364
+
365
+ # Set y-ticks with appropriate labels and rotation (note the switch of prefixes)
366
+ plt.yticks( y_positions, [ytick_prefix+'_'+str(i+1) for i in range(self.rows)], rotation= yticks_rotation)
367
+
368
+ # Else turn off the yticks
369
+ else:
370
+ plt.yticks([], [])
371
+
372
+
373
+ # Draw vertical grid lines if display_grid is True
374
+ if display_grid:
375
+ vline_positions= [(i+1)*cell_height for i in range(self.stride*(self.rows-1)+ self.cols+1)]
376
+ ax.vlines(x= vline_positions, ymin=0, ymax=max(y_positions) + cell_width, colors='gray', linestyles='--', linewidth=0.5)
377
+
378
+ # Set label for 'x'-axis
379
+ plt.xlabel(xlabel)
380
+
381
+ # Set label for 'y'-axis
382
+ plt.ylabel(ylabel)
383
+
384
+ # Add all created patches (cells) to axes for rendering
385
+ for each_patch in patches:
386
+ ax.add_patch( each_patch )
387
+
388
+ # Update the limits of the axes based on the current data
389
+ ax.relim()
390
+
391
+ # Automatically adjust the view limits to fit the data within the axes
392
+ ax.autoscale_view()
393
+
394
+ # Check if a legend should be displayed based on user input
395
+ if display_legend:
396
+
397
+ # Call the legend method to create and display the legend on the specified axes
398
+ # Pass in the color map, hatch map, and any additional keyword arguments for customization
399
+ self.legend( ax= ax, color_map= self.color_map,hatch_map= self.hatch_map, legend_hatch= legend_hatch, **legend_kwargs )
400
+
401
+ # Show the plot with all configurations applied
402
+ plt.show()
403
+
404
+ def legend(self, ax: matplotlib.axes.Axes, color_map: dict, hatch_map: dict, legend_hatch: bool, **legend_kwargs: dict ) -> matplotlib.legend.Legend:
405
+ """
406
+ Create and display legend for the KitikiPlot visualization.
407
+
408
+ Parameters
409
+ ----------
410
+ ax : matplotlib.axes.Axes
411
+ - The axes object where the legend will be placed.
412
+ color_map : dict
413
+ - A dictionary mapping unique values to their corresponding colors.
414
+ hatch_map : dict
415
+ - A dictionary mapping unique values to their corresponding hatch patterns.
416
+ legend_hatch : bool (optional)
417
+ - A flag indicating whether to include hatch patterns in the legend.
418
+ - Default is False.
419
+ legend_kwargs: dict (optional)
420
+ - Additional keyword arguments passed to customize the legend.
421
+ - Default is {}.
422
+
423
+ Returns
424
+ -------
425
+ matplotlib.legend.Legend: The created legend object.
426
+ """
427
+
428
+ # Check if hatch patterns should be included in the legend
429
+ if not legend_hatch:
430
+
431
+ # Create legend patches without hatching
432
+ # Each patch corresponds to a color in the color map and is labeled with its key
433
+ legend_patches = [mpatches.Patch(facecolor=color, label=label) for label, color in color_map[0].items()]
434
+
435
+
436
+ else:
437
+ # Create legend patches that include hatching
438
+ # Each patch corresponds to a color in the color map and is labeled with its key
439
+ # The hatch pattern is specified based on the 'hatch_map', multiplied by 2 for visibility
440
+ legend_patches= [mpatches.Patch(facecolor= color_map[0][key], label= key, hatch= r"{}".format(hatch_map[key]*2)) for key in color_map[0]]
441
+
442
+ kwargs= legend_kwargs
443
+
444
+ # Return the created legend object, attaching the generated patches and any additional kwargs
445
+ return ax.legend(handles=legend_patches, **legend_kwargs)
446
+
@@ -0,0 +1,23 @@
1
+ Copyright (C) 2024 Boddu Sri Pavan
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the “Software”), to deal in the Software without restriction,
6
+ including without limitation the rights to use, copy, modify, merge,
7
+ publish, distribute, sublicense, and/or sell copies of the Software,
8
+ and to permit persons to whom the Software is furnished to do
9
+ so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY
15
+ OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
16
+ LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
20
+ OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
+ DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,106 @@
1
+ Metadata-Version: 2.1
2
+ Name: kitikiplot
3
+ Version: 0.1.3
4
+ Summary: A Python library to visualize categorical sliding window data.
5
+ Home-page: https://github.com/BodduSriPavan-111/kitikiplot
6
+ Author: Boddu Sri Pavan
7
+ Author-email: boddusripavan111@gmail.com
8
+ License: LICENSE
9
+ Project-URL: Bug Tracker, https://github.com/BodduSriPavan-111/kitikiplot/issues
10
+ Project-URL: Documentation, https://github.com/BodduSriPavan-111/kitikiplot/wiki
11
+ Project-URL: Source Code, https://github.com/BodduSriPavan-111/kitikiplot
12
+ Keywords: sliding window,sequential,time-series,genome,categorical data
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Topic :: Scientific/Engineering :: Visualization
17
+ Description-Content-Type: text/markdown
18
+ License-File: LICENSE
19
+
20
+ ![plot](https://drive.google.com/uc?id=1kzO8VZC38-ktIezrnFvH1b7K84zGBrsL)
21
+
22
+ <div align="center">
23
+
24
+ ![PyPI](https://img.shields.io/pypi/v/kitikiplot?color=blueviolet)
25
+ ![PyPI - Downloads](https://img.shields.io/pypi/dm/kitikiplot?color=gold)
26
+ [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.14632005.svg)](https://doi.org/10.5281/zenodo.14632005)
27
+ ![License](https://img.shields.io/github/license/BodduSriPavan-111/kitikiplot?color=green)
28
+
29
+ </div>
30
+
31
+ # KitikiPlot
32
+ KitikiPlot is a Python library for visualizing sequential and time-series categorical "Sliding Window" data. <br>
33
+ (The term 'kitiki' means 'window' in Telugu)
34
+
35
+ Our preprint is published in **TechRxiv**. Find it <a href="https://www.techrxiv.org/users/877016/articles/1256589-kitikiplot-a-python-library-to-visualize-categorical-sliding-window-data"> here <a/>
36
+
37
+ Research paper is published in **GIS Science Journal** Volume 12 Issue 1, 186-193, 2025 (Scopus indexed with Impact factor **6.1**). </br>
38
+ Read it here: <a href="https://zenodo.org/records/14632005">https://zenodo.org/records/14632005</a>
39
+ <!--
40
+ ## Table of Contents</h2>
41
+ - [Why Kitkiplot?](#What-and-why)
42
+ - [Getting Started](#getting-started)
43
+ - [Contribute](#contribute)
44
+ - [Maintainer(s)](#maintainer(s))
45
+ - [Citation](#citation)
46
+
47
+ ## Why Kitikiplot?
48
+ -->
49
+
50
+ ### Examples
51
+ Genome Visualization can be found in [Genome.ipynb](https://github.com/BodduSriPavan-111/kitikiplot/blob/add-comments/examples/Genome.ipynb)
52
+ ![plot](https://drive.google.com/uc?id=1vpRcqUsalg64ILluCgcXfoaUfcqQfHVN)
53
+ <br><br>
54
+ Weather Pattern in [Weather Pattern.ipynb](https://github.com/BodduSriPavan-111/kitikiplot/blob/add-comments/examples/Weather_Pattern.ipynb)
55
+ ![plot](https://drive.google.com/uc?id=1tl5XefYfBqQTap1X0iDNoY3upk0FHFni)
56
+ <br><br>
57
+ CO Trend in Air in [Air_Quality.ipynb](https://github.com/BodduSriPavan-111/kitikiplot/blob/add-comments/examples/Air_Quality.ipynb)
58
+ ![plot](https://drive.google.com/uc?id=1LTFgNDX-OlTwkSQjsWA3x6xHRLyu_a6O)
59
+ <br>
60
+
61
+ ### Getting Started
62
+ Install the package via pip:
63
+ ```
64
+ pip install kitikiplot
65
+ ```
66
+ #### Usage
67
+ ```py
68
+ from kitikiplot import KitikiPlot
69
+
70
+ data = [] # DataFrame or list of sliding window data
71
+
72
+ ktk= KitikiPlot( data= data )
73
+
74
+ ktk.plot( display_legend= True ) # Display the legend
75
+ ```
76
+ Check out the complete <b>guide of customization</b> [here](https://github.com/BodduSriPavan-111/kitikiplot/blob/main/examples/Usage_Guide.ipynb).
77
+
78
+ Please refer <a href="https://github.com/BodduSriPavan-111/kitikiplot/blob/main/CONTRIBUTING.md">CONTRIBUTING.md</a> for <b>contributions</b> to kitikiplot.
79
+
80
+ ### Author
81
+ <a href="https://www.linkedin.com/in/boddusripavan/"> Boddu Sri Pavan </a> &
82
+ <a href="https://www.linkedin.com/in/boddu-swathi-sree-2a2a58332/"> Boddu Swathi Sree </a>
83
+
84
+ ## Citation
85
+ APA <br>
86
+ > Boddu Sri Pavan, Chandrasheker Thummanagoti, & Boddu Swathi Sree. (2025). KitikiPlot A Python library to visualize categorical sliding window data. https://doi.org/10.5281/zenodo.14632005.
87
+
88
+ IEEE <br>
89
+ > Boddu Sri Pavan, Chandrasheker Thummanagotiand Boddu Swathi Sree, “KitikiPlot A Python library to visualize categorical sliding window data”, 2025, doi: 10.5281/zenodo.14632005.
90
+
91
+ BibTeX <br>
92
+ > @misc{boddu_sri_pavan_2025_14632005, <br>
93
+ > author = {Boddu Sri Pavan and <br>
94
+ > Chandrasheker Thummanagoti and <br>
95
+ > Boddu Swathi Sree}, <br>
96
+ > title = {KitikiPlot A Python library to visualize <br>
97
+ > categorical sliding window data <br>
98
+ > }, <br>
99
+ > month = jan, <br>
100
+ > year = 2025, <br>
101
+ > publisher = {Zenodo}, <br>
102
+ > doi = {10.5281/zenodo.14632005}, <br>
103
+ > url = {https://doi.org/10.5281/zenodo.14632005}, <br>
104
+ >}
105
+
106
+ ## Thank You !
@@ -0,0 +1,9 @@
1
+ kitikiplot/__init__.py,sha256=7LpJy1V-PZ-JlfjsnRMjMXxTKaFt0JP0mj-A0SgS-sE,34
2
+ kitikiplot/kitiki_cell.py,sha256=N356LoJACH7qjoVn0T0GpLPVmXnyr6bBmM19dhLY7J8,6796
3
+ kitikiplot/kitiki_color_config.py,sha256=_HsOr1txgj8E4-Xro6-ekLSRH0FSrSnzvpXjAD2AbMw,10718
4
+ kitikiplot/kitikiplot.py,sha256=eOxtrRjg2u7AeDw4l1qE6qwutTlmKur_xpqLAnJViSs,19203
5
+ kitikiplot-0.1.3.dist-info/LICENSE,sha256=14Bs-3ieyNjj9kCnVLv8CHRXEvQVM6P5uLe-pz7cBI0,1088
6
+ kitikiplot-0.1.3.dist-info/METADATA,sha256=u8L2vcbiRYzw6_1uuNGlo0ZcCC0-z0UK3pYwQ8WObs4,4714
7
+ kitikiplot-0.1.3.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
8
+ kitikiplot-0.1.3.dist-info/top_level.txt,sha256=nqjD8Sil5L7rfBQtnmLdJMR-u2BdVFnusZlOIU0Yd00,11
9
+ kitikiplot-0.1.3.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (72.1.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ kitikiplot