DiaModality 0.2.6__tar.gz

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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 konung-yaropolk
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,2 @@
1
+ include LICENSE
2
+ include README.md
@@ -0,0 +1,169 @@
1
+ Metadata-Version: 2.2
2
+ Name: DiaModality
3
+ Version: 0.2.6
4
+ Summary: Tool to plot modality vector diagrams
5
+ Author-email: konung-yaropolk <yaropolk1995@gmail.com>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2024 konung-yaropolk
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+ Project-URL: Homepage, https://github.com/konung-yaropolk/DiaModality
28
+ Project-URL: Repository, https://github.com/konung-yaropolk/DiaModality.git
29
+ Project-URL: Issues, https://github.com/konung-yaropolk/DiaModality/issues
30
+ Keywords: Visualization,Science,Plotting,Matplotlib
31
+ Classifier: Programming Language :: Python
32
+ Classifier: Programming Language :: Python :: 3
33
+ Classifier: Programming Language :: Python :: 3.12
34
+ Classifier: License :: OSI Approved :: MIT License
35
+ Classifier: Operating System :: OS Independent
36
+ Classifier: Development Status :: 4 - Beta
37
+ Classifier: Intended Audience :: Science/Research
38
+ Classifier: Natural Language :: English
39
+ Classifier: Topic :: Scientific/Engineering :: Visualization
40
+ Requires-Python: >=3.10
41
+ Description-Content-Type: text/markdown
42
+ License-File: LICENSE
43
+ Requires-Dist: numpy
44
+ Requires-Dist: matplotlib
45
+ Requires-Dist: scsv>=0.1.4
46
+
47
+ # DiaModality - The Modality Diagram
48
+
49
+ Simple tool to plot vector modality diagram
50
+
51
+ [![pypi_version](https://img.shields.io/pypi/v/diamodality?label=PyPI&color=green)](https://pypi.org/project/diamodality)
52
+ [![GitHub Release](https://img.shields.io/github/v/release/konung-yaropolk/DiaModality?label=GitHub&color=green&link=https%3A%2F%2Fgithub.com%2Fkonung-yaropolk%2FDiaModality)](https://github.com/konung-yaropolk/DiaModality)
53
+ [![PyPI - License](https://img.shields.io/pypi/l/diamodality)](https://pypi.org/project/diamodality)
54
+ [![Python](https://img.shields.io/badge/Python-v3.10%5E-green?logo=python)](https://pypi.org/project/diamodality)
55
+ [![PyPI - Downloads](https://img.shields.io/pypi/dm/DiaModality?label=PyPI%20stats&color=blue)](https://pypi.org/project/diamodality)
56
+
57
+
58
+
59
+ ### To install package run the command:
60
+ ```bash
61
+ pip install diamodality
62
+ ```
63
+
64
+
65
+ ### Example use case:
66
+ See the /demo directory on Git repo or
67
+ create and run the following two files:
68
+ *(file names don't matter)*
69
+
70
+ ---
71
+ ``generate_sample_data.py``:
72
+ ```python
73
+ import csv
74
+ import random
75
+ import os
76
+
77
+ num_rows = 1500
78
+ output_file = 'modality_data.csv'
79
+
80
+ # locate working directory
81
+ script_dir = os.path.dirname(os.path.realpath(__file__))
82
+ file_path = os.path.join(script_dir, output_file)
83
+
84
+ # Open a new CSV file to write the data
85
+ with open(file_path, mode='w', newline='') as file:
86
+ writer = csv.writer(file)
87
+
88
+ # Generate the data
89
+ signal_treshold = 1.5
90
+ for _ in range(num_rows):
91
+
92
+ # generate data columns:
93
+ col1 = random.uniform(0, 2.7)
94
+ col2 = random.uniform(0, 3.3)
95
+ col3 = random.uniform(0, 7.3)
96
+
97
+ # generate binarization columns:
98
+ col4 = 1 if col1 > signal_treshold else ''
99
+ col5 = 1 if col2 > signal_treshold else ''
100
+ col6 = 1 if col3 > signal_treshold else ''
101
+
102
+ writer.writerow([col1, col2, col3, col4, col5, col6])
103
+
104
+ ```
105
+
106
+
107
+ ---
108
+ ``plot_sample_data.py``:
109
+ ```python
110
+ import DiaModality.ModalityPlot as plt
111
+ import scsv as csv
112
+ import os
113
+
114
+ # input files:
115
+ files = ['modality_data.csv']
116
+
117
+ # Get full path
118
+ script_dir = os.path.dirname(os.path.realpath(__file__))
119
+
120
+ for file in files:
121
+
122
+ # Get full path of input files
123
+ file_path = os.path.join(script_dir, file)
124
+
125
+ # Parse data from csv file
126
+ new_csv = csv.OpenFile(file_path)
127
+ data, binarization = new_csv.GetRows(3, 3)
128
+
129
+ # Make figure:
130
+ plot = plt.ModalityPlot(
131
+ data,
132
+ binarization,
133
+ modalities=['Set 1', 'Set 2', 'Set 3'],
134
+ angles=[210, 90, 330],
135
+ labels=False,
136
+ scalecircle=0.5, # Scale circle radius
137
+ scalecircle_linestyle=':',
138
+ scalecircle_linewidth=0.75,
139
+ marker='', # vector endpoints marker
140
+ linestyle='-',
141
+ linewidth=0.5,
142
+ alpha=0.5,
143
+ same_scale=False, # Draw all the subplots in the same scale
144
+ full_center=True, # Draw all vectors in the central subplot,
145
+ # else draw trimodal vectors only
146
+ whole_sum=True, # Calculate all three modality vectors despite binarization
147
+ figsize=(10, 10),
148
+ dpi=100,
149
+ title='Modality Diagram Example',
150
+ colors=(
151
+ 'tab:green', # Set 1 color
152
+ 'navy', # Set 2 color
153
+ 'tab:red', # Set 3 color
154
+ '#1E88E5', # Sets 1 & 2 intersection color
155
+ '#FF9933', # Sets 1 & 3 intersection color
156
+ '#9900FF', # Sets 2 & 3 intersection color
157
+ 'black', # All sets intersection color
158
+ ),
159
+ )
160
+
161
+ plot.save(file_path, type='png', transparent=False)
162
+ plot.show()
163
+ ```
164
+
165
+ Source page:
166
+ https://github.com/konung-yaropolk/DiaModality
167
+
168
+
169
+ ![modality_data csv](https://github.com/user-attachments/assets/eb77b4d7-281f-45b0-a5ce-4c2442fc9a75)
@@ -0,0 +1,123 @@
1
+ # DiaModality - The Modality Diagram
2
+
3
+ Simple tool to plot vector modality diagram
4
+
5
+ [![pypi_version](https://img.shields.io/pypi/v/diamodality?label=PyPI&color=green)](https://pypi.org/project/diamodality)
6
+ [![GitHub Release](https://img.shields.io/github/v/release/konung-yaropolk/DiaModality?label=GitHub&color=green&link=https%3A%2F%2Fgithub.com%2Fkonung-yaropolk%2FDiaModality)](https://github.com/konung-yaropolk/DiaModality)
7
+ [![PyPI - License](https://img.shields.io/pypi/l/diamodality)](https://pypi.org/project/diamodality)
8
+ [![Python](https://img.shields.io/badge/Python-v3.10%5E-green?logo=python)](https://pypi.org/project/diamodality)
9
+ [![PyPI - Downloads](https://img.shields.io/pypi/dm/DiaModality?label=PyPI%20stats&color=blue)](https://pypi.org/project/diamodality)
10
+
11
+
12
+
13
+ ### To install package run the command:
14
+ ```bash
15
+ pip install diamodality
16
+ ```
17
+
18
+
19
+ ### Example use case:
20
+ See the /demo directory on Git repo or
21
+ create and run the following two files:
22
+ *(file names don't matter)*
23
+
24
+ ---
25
+ ``generate_sample_data.py``:
26
+ ```python
27
+ import csv
28
+ import random
29
+ import os
30
+
31
+ num_rows = 1500
32
+ output_file = 'modality_data.csv'
33
+
34
+ # locate working directory
35
+ script_dir = os.path.dirname(os.path.realpath(__file__))
36
+ file_path = os.path.join(script_dir, output_file)
37
+
38
+ # Open a new CSV file to write the data
39
+ with open(file_path, mode='w', newline='') as file:
40
+ writer = csv.writer(file)
41
+
42
+ # Generate the data
43
+ signal_treshold = 1.5
44
+ for _ in range(num_rows):
45
+
46
+ # generate data columns:
47
+ col1 = random.uniform(0, 2.7)
48
+ col2 = random.uniform(0, 3.3)
49
+ col3 = random.uniform(0, 7.3)
50
+
51
+ # generate binarization columns:
52
+ col4 = 1 if col1 > signal_treshold else ''
53
+ col5 = 1 if col2 > signal_treshold else ''
54
+ col6 = 1 if col3 > signal_treshold else ''
55
+
56
+ writer.writerow([col1, col2, col3, col4, col5, col6])
57
+
58
+ ```
59
+
60
+
61
+ ---
62
+ ``plot_sample_data.py``:
63
+ ```python
64
+ import DiaModality.ModalityPlot as plt
65
+ import scsv as csv
66
+ import os
67
+
68
+ # input files:
69
+ files = ['modality_data.csv']
70
+
71
+ # Get full path
72
+ script_dir = os.path.dirname(os.path.realpath(__file__))
73
+
74
+ for file in files:
75
+
76
+ # Get full path of input files
77
+ file_path = os.path.join(script_dir, file)
78
+
79
+ # Parse data from csv file
80
+ new_csv = csv.OpenFile(file_path)
81
+ data, binarization = new_csv.GetRows(3, 3)
82
+
83
+ # Make figure:
84
+ plot = plt.ModalityPlot(
85
+ data,
86
+ binarization,
87
+ modalities=['Set 1', 'Set 2', 'Set 3'],
88
+ angles=[210, 90, 330],
89
+ labels=False,
90
+ scalecircle=0.5, # Scale circle radius
91
+ scalecircle_linestyle=':',
92
+ scalecircle_linewidth=0.75,
93
+ marker='', # vector endpoints marker
94
+ linestyle='-',
95
+ linewidth=0.5,
96
+ alpha=0.5,
97
+ same_scale=False, # Draw all the subplots in the same scale
98
+ full_center=True, # Draw all vectors in the central subplot,
99
+ # else draw trimodal vectors only
100
+ whole_sum=True, # Calculate all three modality vectors despite binarization
101
+ figsize=(10, 10),
102
+ dpi=100,
103
+ title='Modality Diagram Example',
104
+ colors=(
105
+ 'tab:green', # Set 1 color
106
+ 'navy', # Set 2 color
107
+ 'tab:red', # Set 3 color
108
+ '#1E88E5', # Sets 1 & 2 intersection color
109
+ '#FF9933', # Sets 1 & 3 intersection color
110
+ '#9900FF', # Sets 2 & 3 intersection color
111
+ 'black', # All sets intersection color
112
+ ),
113
+ )
114
+
115
+ plot.save(file_path, type='png', transparent=False)
116
+ plot.show()
117
+ ```
118
+
119
+ Source page:
120
+ https://github.com/konung-yaropolk/DiaModality
121
+
122
+
123
+ ![modality_data csv](https://github.com/user-attachments/assets/eb77b4d7-281f-45b0-a5ce-4c2442fc9a75)
@@ -0,0 +1,35 @@
1
+ [build-system]
2
+ requires = ["setuptools>=62.6"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "DiaModality"
7
+ dynamic = ["version", "dependencies"]
8
+ license = {file = "LICENSE"}
9
+ authors = [
10
+ { name="konung-yaropolk", email="yaropolk1995@gmail.com" },
11
+ ]
12
+ description = "Tool to plot modality vector diagrams"
13
+ keywords = ["Visualization", "Science", "Plotting", "Matplotlib"]
14
+ readme = {file = "README.md", content-type = "text/markdown"}
15
+ requires-python = ">=3.10"
16
+ classifiers = [
17
+ "Programming Language :: Python",
18
+ "Programming Language :: Python :: 3",
19
+ "Programming Language :: Python :: 3.12",
20
+ "License :: OSI Approved :: MIT License",
21
+ "Operating System :: OS Independent",
22
+ "Development Status :: 4 - Beta",
23
+ "Intended Audience :: Science/Research",
24
+ "Natural Language :: English",
25
+ "Topic :: Scientific/Engineering :: Visualization",
26
+ ]
27
+
28
+ [project.urls]
29
+ Homepage = "https://github.com/konung-yaropolk/DiaModality"
30
+ Repository = "https://github.com/konung-yaropolk/DiaModality.git"
31
+ Issues = "https://github.com/konung-yaropolk/DiaModality/issues"
32
+
33
+ [tool.setuptools.dynamic]
34
+ version = {attr = "DiaModality.__version__"}
35
+ dependencies = {file = ["requirements.txt"]}
@@ -0,0 +1,3 @@
1
+ numpy
2
+ matplotlib
3
+ scsv>=0.1.4
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,348 @@
1
+ #!/usr/bin/env python
2
+ import matplotlib.pyplot as plt
3
+ # import matplotlib.colors as mcolors
4
+ import matplotlib.gridspec as gridspec
5
+ import numpy as np
6
+
7
+ # Only use for plot layout adjustment
8
+ DEBUG = False
9
+
10
+
11
+ class __Figure():
12
+ '''
13
+ Super class of all future plots
14
+ '''
15
+
16
+ def __init__(
17
+ self,
18
+ marker='',
19
+ linestyle='-',
20
+ linewidth=0.5,
21
+ alpha=0.8,
22
+ figsize=(10, 10),
23
+ dpi=100,
24
+ title='',
25
+ ) -> None:
26
+
27
+ self.marker = marker
28
+ self.linestyle = linestyle
29
+ self.linewidth = linewidth
30
+ self.alpha = alpha
31
+ self.figsize = figsize
32
+ self.dpi = dpi
33
+ self.title = title
34
+ self.debug_flag = DEBUG
35
+
36
+ # Prepare figure:
37
+ self.fig = plt.figure(figsize=self.figsize, dpi=self.dpi)
38
+ self._make_layout()
39
+
40
+ def _make_layout(self) -> None:
41
+ # Create figure
42
+ plt.subplots_adjust(wspace=0.0, hspace=0.0)
43
+ plt.tight_layout()
44
+ plt.suptitle(self.title)
45
+
46
+
47
+ class __Output():
48
+ '''
49
+ Output options mixin
50
+ '''
51
+
52
+ def show(self):
53
+ plt.show()
54
+
55
+ def save(self,
56
+ filename,
57
+ type='png',
58
+ transparent=False):
59
+ plt.savefig('{}.{}'.format(filename, type), transparent=transparent)
60
+
61
+
62
+ class ModalityPlot(__Figure, __Output):
63
+ '''
64
+ Input fotmat:
65
+
66
+ data: list of points, each point should be represented as a
67
+ list or touple containing three floats, one per modality.
68
+
69
+ '''
70
+
71
+ def __init__(
72
+ self,
73
+ data: list,
74
+ binarization: list,
75
+ modalities=('Set A', 'Set B', 'Set C'),
76
+ angles=[90, 210, 330],
77
+ labels=True,
78
+ scalecircle=1, # Scale circle radius
79
+ scalecircle_linestyle=':',
80
+ scalecircle_linewidth=1,
81
+ marker='', # vector endpoints marker
82
+ linestyle='-',
83
+ linewidth=0.5,
84
+ alpha=0.8,
85
+ same_scale=False, # Draw all the subplots in the same scale
86
+ # Draw all vectors in the central subplot, else draw trimodal vectors only
87
+ full_center=True,
88
+ whole_sum=True, # Calculate all three modality vectors despite binarization
89
+ figsize=(10, 10),
90
+ dpi=300,
91
+ title='',
92
+ colors=(
93
+ 'tab:green', # Set 1 color
94
+ 'navy', # Set 2 color
95
+ 'tab:red', # Set 3 color
96
+ '#1E88E5', # Sets 1 & 2 intersection color
97
+ '#FF9933', # Sets 1 & 3 intersection color
98
+ '#9900FF', # Sets 2 & 3 intersection color
99
+ 'black', # All sets intersection color
100
+ ),
101
+ normalization_func='sigmoid',
102
+ ) -> None:
103
+
104
+ self.data, self.binarization = self.__format_input(data, binarization)
105
+ self.modalities = modalities
106
+ self.angles = np.deg2rad(angles)
107
+ self.labels = labels
108
+ self.scalecircle = scalecircle
109
+ self.scalecircle_linestyle = scalecircle_linestyle
110
+ self.scalecircle_linewidth = scalecircle_linewidth
111
+ self.same_scale = same_scale
112
+ self.full_center = full_center
113
+ self.whole_sum = whole_sum
114
+ self.colors = colors
115
+ self.normalization_func = normalization_func
116
+ self.modality_patterns = (
117
+ (True, False, False),
118
+ (False, True, False),
119
+ (False, False, True),
120
+ (True, True, False),
121
+ (True, False, True),
122
+ (False, True, True),
123
+ (True, True, True),
124
+ )
125
+ self.modalities_array = (
126
+ (self.modalities[0], None, None),
127
+ (None, self.modalities[1], None),
128
+ (None, None, self.modalities[2]),
129
+ (self.modalities[0], self.modalities[1], None),
130
+ (self.modalities[0], None, self.modalities[2]),
131
+ (None, self.modalities[1], self.modalities[2]),
132
+ (None, None, None),
133
+ )
134
+
135
+ super().__init__(
136
+ marker,
137
+ linestyle,
138
+ linewidth,
139
+ alpha,
140
+ figsize,
141
+ dpi,
142
+ title,
143
+ )
144
+
145
+ # check input:
146
+ assert self.data.any(), 'data array must not be empty'
147
+ assert self.binarization.any(), 'binarization array must not be empty'
148
+ assert len(self.data) == len(
149
+ self.binarization), 'data and binarization arrays must have exact length'
150
+ assert len(self.data[0]) == len(self.binarization[0]
151
+ ) == 3, 'data and binarization arrays must have three columns each'
152
+
153
+ def __format_input(self, input_data, input_bin) -> list:
154
+ '''
155
+ Data formatting:
156
+ Each column represents one modality. Empty cells are counted as 0.
157
+ Each row containing at least one value that will be represented as a point.
158
+ '''
159
+
160
+ output_data = np.array(input_data, dtype=object)
161
+ # Replace empty cells with zeros
162
+ output_data[output_data is None] = 0
163
+ output_data = output_data.astype(np.float32)
164
+
165
+ # Replace zeros with False and other numbers with True
166
+ output_bin = np.array(input_bin, dtype=np.bool_)
167
+
168
+ return output_data, output_bin
169
+
170
+ def __normalization(self, input) -> list:
171
+ '''
172
+ Define function to normalize coordinates
173
+ to values in range of 0 to 1 for HSV color model.
174
+ input: np.array
175
+ '''
176
+
177
+ match self.normalization_func:
178
+
179
+ case 'linear':
180
+ def func(x): return (x - np.min(input)) / \
181
+ (np.max(input) - np.min(input))
182
+
183
+ case 'sigmoid':
184
+ def func(x): return 1 / (1 + np.exp(-x))
185
+
186
+ # case 'log':
187
+ # log_input = np.log1p(input)
188
+ # func = lambda x: (x - np.min(log_input)) / (np.max(log_input) - np.min(log_input))
189
+
190
+ return [func(x) for x in input]
191
+
192
+ def __vector_addition(self, data, binarization) -> list:
193
+
194
+ resultants = np.array((), dtype=np.float32)
195
+
196
+ for points, bins in zip(data, binarization):
197
+
198
+ # ignore empty lines
199
+ if not all(x == 0 for x in points):
200
+
201
+ # Calculate resultant vector
202
+ resultants = np.append(
203
+ resultants,
204
+ np.sum(
205
+ [points[i] * np.exp(1j * self.angles[i])
206
+ if bins[i] or self.whole_sum
207
+ else 0
208
+ for i in range(len(points))
209
+ ]
210
+ )
211
+ )
212
+ else:
213
+ resultants = np.append(resultants, (0))
214
+
215
+ return resultants
216
+
217
+ def __find_match_modality(self, sample, list) -> int:
218
+ for i, item in enumerate(list):
219
+ if np.array_equal(item, sample):
220
+ return i
221
+ return 0
222
+
223
+ def __draw_scalecircle(self, ax) -> None:
224
+
225
+ # Plot the single-unit circle
226
+ r = self.scalecircle
227
+ theta = np.linspace(0, 2*np.pi, 100)
228
+ ax.plot(theta, [r]*len(theta), color='black',
229
+ linestyle=self.scalecircle_linestyle, linewidth=self.scalecircle_linewidth, zorder=10)
230
+
231
+ def __initiate_subplot(self, ax) -> None:
232
+
233
+ # Set custom design
234
+ ax.set_yticklabels([])
235
+ ax.set_xticks(self.angles if self.labels else [])
236
+ ax.grid(False)
237
+ ax.spines['polar'].set_visible(
238
+ False) if not self.debug_flag else ax.spines['polar'].set_visible(True)
239
+ ax.patch.set_facecolor('none')
240
+
241
+ # Draw coordinate grid on the top of figure
242
+ # to make easier subplots alignment on devtime
243
+
244
+ def __debug_grid(self, fig, y, x) -> None:
245
+
246
+ for i in range(1, y*x+1):
247
+
248
+ ax = fig.add_subplot(y, x, i)
249
+
250
+ # Set the facecolor of the axes
251
+ ax.patch.set_facecolor('none')
252
+ ax.set_xticks([])
253
+ ax.set_yticks([])
254
+
255
+ for spine in ax.spines.values():
256
+ spine.set_edgecolor('black')
257
+
258
+ def __draw_subplot(self, ax, resultants, modality_pattern, modalities) -> None:
259
+
260
+ # for future sets calculation
261
+ sets_counter = [0] * 8
262
+
263
+ # Color measurement in HSV format (temporarry abandoned future)
264
+ # hue_array = self.__normalization(np.angle(resultants))
265
+ # sat_array = np.ones_like(hue_array)
266
+ # val_array = self.__normalization(np.abs(resultants))
267
+ # color = mcolors.hsv_to_rgb((hue, sat, val))
268
+
269
+ for resultant, data_row, bin_row in zip(resultants, self.data, self.binarization):
270
+
271
+ if (resultant
272
+ and np.array_equal(bin_row, modality_pattern)
273
+ or (self.full_center
274
+ and modality_pattern == (True, True, True)
275
+ and (tuple(bin_row) not in self.modality_patterns[:3]
276
+ or self.whole_sum
277
+ )
278
+ )
279
+ ):
280
+
281
+ # defining the modality of responce to apply color and z-order
282
+ modality_pattern_number = self.__find_match_modality(
283
+ bin_row, self.modality_patterns)
284
+ sets_counter[modality_pattern_number] += 1
285
+ color = self.colors[modality_pattern_number]
286
+ zorder = modality_pattern_number
287
+
288
+ ax.plot(
289
+ [0, np.angle(resultant)],
290
+ [0, np.abs(resultant)],
291
+ zorder=zorder,
292
+ marker=self.marker,
293
+ linestyle=self.linestyle,
294
+ linewidth=self.linewidth,
295
+ color=color,
296
+ alpha=self.alpha
297
+ )
298
+ if self.labels:
299
+ ax.set_xticklabels(modalities)
300
+
301
+ if self.scalecircle:
302
+ self.__draw_scalecircle(ax)
303
+
304
+ if not self.whole_sum and sum(modality_pattern) == 1:
305
+ ax.set_visible(False)
306
+
307
+ def _make_layout(self) -> None:
308
+ '''
309
+ Make figure layout,
310
+ starting point of plotting
311
+ '''
312
+
313
+ # Defining layout
314
+ gs = gridspec.GridSpec(20, 20, figure=self.fig)
315
+ ax1 = self.fig.add_subplot(gs[7:17, 1:11], polar=True)
316
+ ax2 = self.fig.add_subplot(gs[1:11, 5:15], polar=True)
317
+ ax3 = self.fig.add_subplot(gs[7:17, 9:19], polar=True)
318
+ ax12 = self.fig.add_subplot(gs[4:14, 3:13], polar=True)
319
+ ax13 = self.fig.add_subplot(gs[7:17, 5:15], polar=True)
320
+ ax23 = self.fig.add_subplot(gs[4:14, 7:17], polar=True)
321
+ ax0 = self.fig.add_subplot(gs[5:15, 5:15], polar=True)
322
+ subplots = (ax1, ax2, ax3, ax12, ax13, ax23, ax0)
323
+
324
+ # calculate resultants
325
+ resultants = self.__vector_addition(self.data, self.binarization)
326
+
327
+ # plot each subplot
328
+ for ax, modality_pattern, modalities in zip(subplots, self.modality_patterns, self.modalities_array):
329
+ self.__initiate_subplot(ax)
330
+ self.__draw_subplot(ax, resultants, modality_pattern, modalities)
331
+
332
+ if self.same_scale:
333
+ rlim = ax0.get_xlim()
334
+ for ax in subplots:
335
+ ax.set_rlim(rlim)
336
+
337
+ # Draw coordinate grid on the top of figure
338
+ # to make easier subplots alignment on devtime
339
+ if self.debug_flag:
340
+ self.__debug_grid(self.fig, 20, 20)
341
+
342
+ plt.subplots_adjust(wspace=0.0, hspace=0.0)
343
+ plt.tight_layout()
344
+ plt.suptitle(self.title)
345
+
346
+
347
+ if __name__ == '__main__':
348
+ print('This package works as an imported module only.\nUse "import diamodality" statement')
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env python
2
+ from ._version import __version__
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env python
2
+
3
+ if __name__ == '__main__':
4
+ print('This package works as an imported module only.\nUse "import diamodality" statement')
@@ -0,0 +1 @@
1
+ __version__ = "0.2.6"
@@ -0,0 +1,169 @@
1
+ Metadata-Version: 2.2
2
+ Name: DiaModality
3
+ Version: 0.2.6
4
+ Summary: Tool to plot modality vector diagrams
5
+ Author-email: konung-yaropolk <yaropolk1995@gmail.com>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2024 konung-yaropolk
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+ Project-URL: Homepage, https://github.com/konung-yaropolk/DiaModality
28
+ Project-URL: Repository, https://github.com/konung-yaropolk/DiaModality.git
29
+ Project-URL: Issues, https://github.com/konung-yaropolk/DiaModality/issues
30
+ Keywords: Visualization,Science,Plotting,Matplotlib
31
+ Classifier: Programming Language :: Python
32
+ Classifier: Programming Language :: Python :: 3
33
+ Classifier: Programming Language :: Python :: 3.12
34
+ Classifier: License :: OSI Approved :: MIT License
35
+ Classifier: Operating System :: OS Independent
36
+ Classifier: Development Status :: 4 - Beta
37
+ Classifier: Intended Audience :: Science/Research
38
+ Classifier: Natural Language :: English
39
+ Classifier: Topic :: Scientific/Engineering :: Visualization
40
+ Requires-Python: >=3.10
41
+ Description-Content-Type: text/markdown
42
+ License-File: LICENSE
43
+ Requires-Dist: numpy
44
+ Requires-Dist: matplotlib
45
+ Requires-Dist: scsv>=0.1.4
46
+
47
+ # DiaModality - The Modality Diagram
48
+
49
+ Simple tool to plot vector modality diagram
50
+
51
+ [![pypi_version](https://img.shields.io/pypi/v/diamodality?label=PyPI&color=green)](https://pypi.org/project/diamodality)
52
+ [![GitHub Release](https://img.shields.io/github/v/release/konung-yaropolk/DiaModality?label=GitHub&color=green&link=https%3A%2F%2Fgithub.com%2Fkonung-yaropolk%2FDiaModality)](https://github.com/konung-yaropolk/DiaModality)
53
+ [![PyPI - License](https://img.shields.io/pypi/l/diamodality)](https://pypi.org/project/diamodality)
54
+ [![Python](https://img.shields.io/badge/Python-v3.10%5E-green?logo=python)](https://pypi.org/project/diamodality)
55
+ [![PyPI - Downloads](https://img.shields.io/pypi/dm/DiaModality?label=PyPI%20stats&color=blue)](https://pypi.org/project/diamodality)
56
+
57
+
58
+
59
+ ### To install package run the command:
60
+ ```bash
61
+ pip install diamodality
62
+ ```
63
+
64
+
65
+ ### Example use case:
66
+ See the /demo directory on Git repo or
67
+ create and run the following two files:
68
+ *(file names don't matter)*
69
+
70
+ ---
71
+ ``generate_sample_data.py``:
72
+ ```python
73
+ import csv
74
+ import random
75
+ import os
76
+
77
+ num_rows = 1500
78
+ output_file = 'modality_data.csv'
79
+
80
+ # locate working directory
81
+ script_dir = os.path.dirname(os.path.realpath(__file__))
82
+ file_path = os.path.join(script_dir, output_file)
83
+
84
+ # Open a new CSV file to write the data
85
+ with open(file_path, mode='w', newline='') as file:
86
+ writer = csv.writer(file)
87
+
88
+ # Generate the data
89
+ signal_treshold = 1.5
90
+ for _ in range(num_rows):
91
+
92
+ # generate data columns:
93
+ col1 = random.uniform(0, 2.7)
94
+ col2 = random.uniform(0, 3.3)
95
+ col3 = random.uniform(0, 7.3)
96
+
97
+ # generate binarization columns:
98
+ col4 = 1 if col1 > signal_treshold else ''
99
+ col5 = 1 if col2 > signal_treshold else ''
100
+ col6 = 1 if col3 > signal_treshold else ''
101
+
102
+ writer.writerow([col1, col2, col3, col4, col5, col6])
103
+
104
+ ```
105
+
106
+
107
+ ---
108
+ ``plot_sample_data.py``:
109
+ ```python
110
+ import DiaModality.ModalityPlot as plt
111
+ import scsv as csv
112
+ import os
113
+
114
+ # input files:
115
+ files = ['modality_data.csv']
116
+
117
+ # Get full path
118
+ script_dir = os.path.dirname(os.path.realpath(__file__))
119
+
120
+ for file in files:
121
+
122
+ # Get full path of input files
123
+ file_path = os.path.join(script_dir, file)
124
+
125
+ # Parse data from csv file
126
+ new_csv = csv.OpenFile(file_path)
127
+ data, binarization = new_csv.GetRows(3, 3)
128
+
129
+ # Make figure:
130
+ plot = plt.ModalityPlot(
131
+ data,
132
+ binarization,
133
+ modalities=['Set 1', 'Set 2', 'Set 3'],
134
+ angles=[210, 90, 330],
135
+ labels=False,
136
+ scalecircle=0.5, # Scale circle radius
137
+ scalecircle_linestyle=':',
138
+ scalecircle_linewidth=0.75,
139
+ marker='', # vector endpoints marker
140
+ linestyle='-',
141
+ linewidth=0.5,
142
+ alpha=0.5,
143
+ same_scale=False, # Draw all the subplots in the same scale
144
+ full_center=True, # Draw all vectors in the central subplot,
145
+ # else draw trimodal vectors only
146
+ whole_sum=True, # Calculate all three modality vectors despite binarization
147
+ figsize=(10, 10),
148
+ dpi=100,
149
+ title='Modality Diagram Example',
150
+ colors=(
151
+ 'tab:green', # Set 1 color
152
+ 'navy', # Set 2 color
153
+ 'tab:red', # Set 3 color
154
+ '#1E88E5', # Sets 1 & 2 intersection color
155
+ '#FF9933', # Sets 1 & 3 intersection color
156
+ '#9900FF', # Sets 2 & 3 intersection color
157
+ 'black', # All sets intersection color
158
+ ),
159
+ )
160
+
161
+ plot.save(file_path, type='png', transparent=False)
162
+ plot.show()
163
+ ```
164
+
165
+ Source page:
166
+ https://github.com/konung-yaropolk/DiaModality
167
+
168
+
169
+ ![modality_data csv](https://github.com/user-attachments/assets/eb77b4d7-281f-45b0-a5ce-4c2442fc9a75)
@@ -0,0 +1,14 @@
1
+ LICENSE
2
+ MANIFEST.in
3
+ README.md
4
+ pyproject.toml
5
+ requirements.txt
6
+ src/DiaModality/ModalityPlot.py
7
+ src/DiaModality/__init__.py
8
+ src/DiaModality/__main__.py
9
+ src/DiaModality/_version.py
10
+ src/DiaModality.egg-info/PKG-INFO
11
+ src/DiaModality.egg-info/SOURCES.txt
12
+ src/DiaModality.egg-info/dependency_links.txt
13
+ src/DiaModality.egg-info/requires.txt
14
+ src/DiaModality.egg-info/top_level.txt
@@ -0,0 +1,3 @@
1
+ numpy
2
+ matplotlib
3
+ scsv>=0.1.4
@@ -0,0 +1 @@
1
+ DiaModality