cratonml 0.1.1.0__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,45 @@
1
+ Metadata-Version: 2.1
2
+ Name: cratonml
3
+ Version: 0.1.1.0
4
+ Summary: Python application for W-Seis
5
+ Author: KamashevAM
6
+ Author-email: kamashev41@gmail.com
7
+ Requires-Python: >=3.11,<3.13
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.11
10
+ Classifier: Programming Language :: Python :: 3.12
11
+ Requires-Dist: cratonapi (>=0.1.0.9,<0.2.0.0)
12
+ Requires-Dist: imbalanced-learn (>=0.12.4,<0.13.0)
13
+ Requires-Dist: nose2 (>=0.15.1,<0.16.0)
14
+ Requires-Dist: numpy (>=1.26.4,<2.0.0)
15
+ Requires-Dist: pandas (>=2.2.3,<3.0.0)
16
+ Requires-Dist: pywin32 (>=306,<307)
17
+ Requires-Dist: pywin32-ctypes (>=0.2.2,<0.3.0)
18
+ Requires-Dist: scikit-learn (>=1.5.0,<2.0.0)
19
+ Requires-Dist: scipy (>=1.14.0,<2.0.0)
20
+ Requires-Dist: seaborn (>=0.13.2,<0.14.0)
21
+ Description-Content-Type: text/markdown
22
+
23
+ # MLToolBox
24
+
25
+ # Использование:
26
+
27
+
28
+ + Установка зависимостей
29
+ ```
30
+ $ pip install mltoolbox
31
+ ```
32
+ + Запустите Desmana, GisWell и подгрузите сейсмический проект
33
+ ```
34
+ # Логика версионирования CHANGELOG:
35
+
36
+ M.N.K.L
37
+
38
+ M - за глобальный релиз отвечает (выход в прод, закрытие этапа)
39
+ N - при добавлении нового модуля, либо изменения старых, но без поддержки расчета прошлых версий
40
+ K - при добавлении новых функциональностей в существующих модулях (функции, класс и тд)
41
+ L - при изменении текущего функционала
42
+
43
+ При изменении номера, все что правее по индексу меняется на ноль.
44
+ Подразумевается что тесты не входят в пулл changelog, но если отдельно заливаются то менять L
45
+ Новые записи вносить вверх файла CHANGELOG
@@ -0,0 +1,23 @@
1
+ # MLToolBox
2
+
3
+ # Использование:
4
+
5
+
6
+ + Установка зависимостей
7
+ ```
8
+ $ pip install mltoolbox
9
+ ```
10
+ + Запустите Desmana, GisWell и подгрузите сейсмический проект
11
+ ```
12
+ # Логика версионирования CHANGELOG:
13
+
14
+ M.N.K.L
15
+
16
+ M - за глобальный релиз отвечает (выход в прод, закрытие этапа)
17
+ N - при добавлении нового модуля, либо изменения старых, но без поддержки расчета прошлых версий
18
+ K - при добавлении новых функциональностей в существующих модулях (функции, класс и тд)
19
+ L - при изменении текущего функционала
20
+
21
+ При изменении номера, все что правее по индексу меняется на ноль.
22
+ Подразумевается что тесты не входят в пулл changelog, но если отдельно заливаются то менять L
23
+ Новые записи вносить вверх файла CHANGELOG
@@ -0,0 +1,2 @@
1
+ import cratonml.calculate
2
+ import cratonml.data
@@ -0,0 +1,221 @@
1
+ import numpy as np
2
+ from sklearn.ensemble import RandomForestClassifier as RandomForest
3
+ from sklearn.naive_bayes import GaussianNB
4
+ from sklearn.tree import DecisionTreeClassifier as DecisionTree
5
+ from sklearn.linear_model import LogisticRegression
6
+
7
+
8
+ class GaussianNaiveBayesClassifier:
9
+ """Класс для классификации алгоритмом Gaussian Naive Bayes."""
10
+
11
+ @staticmethod
12
+ def get_model(x_train: np.ndarray, y_train: np.ndarray):
13
+ """
14
+ Возвращает модель обученную на тренировочных данных.
15
+
16
+ Parameters
17
+ ----------
18
+ x_train: np.ndarray
19
+ Массив значений размера (N, M). Где N - количество точек, M - количество атрибутов.
20
+ y_train: np.ndarray
21
+ Массив значений размера N.
22
+
23
+ Returns
24
+ -------
25
+ GaussianNB
26
+ Обученная модель.
27
+ """
28
+
29
+ assert x_train.ndim == 2, "x_train: Ожидался 2D массив"
30
+ assert y_train.ndim == 1, "y_train: Ожидался 1D массив"
31
+ assert x_train.shape[0] == y_train.shape[0], "Массив y_train имеет несоответствующую длину"
32
+
33
+ model = GaussianNB()
34
+ model.fit(x_train, y_train)
35
+ return model
36
+
37
+ @staticmethod
38
+ def predict(model: GaussianNB, x_test: np.ndarray):
39
+ """
40
+ Прогнозирует метки для тестового набора данных.
41
+
42
+ Parameters
43
+ ----------
44
+ model: GaussianNB
45
+ Обученная модель.
46
+ x_test: np.ndarray
47
+ Массив значений размера (N, M). Где N - количество точек, M - количество атрибутов.
48
+
49
+ Returns
50
+ -------
51
+ np.ndarray
52
+ Массив меток размера N.
53
+ """
54
+
55
+ assert x_test.ndim == 2, "x_test: Ожидался 2D массив"
56
+
57
+ prediction = model.predict(x_test)
58
+ return prediction
59
+
60
+
61
+ class LogisticRegressionClassifier:
62
+ """Класс для классификации алгоритмом Logistic Regression."""
63
+ @staticmethod
64
+ def get_model(x_train: np.ndarray, y_train: np.ndarray):
65
+ """
66
+ Возвращает модель обученную на тренировочных данных.
67
+
68
+ Parameters
69
+ ----------
70
+ x_train: np.ndarray
71
+ Массив значений размера (N, M). Где N - количество точек, M - количество атрибутов.
72
+ y_train: np.ndarray
73
+ Массив значений размера N.
74
+
75
+ Returns
76
+ -------
77
+ LogisticRegression
78
+ Обученная модель.
79
+ """
80
+
81
+ assert x_train.ndim == 2, "x_train: Ожидался 2D массив"
82
+ assert y_train.ndim == 1, "y_train: Ожидался 1D массив"
83
+ assert x_train.shape[0] == y_train.shape[0], "Массив y_train имеет несоответствующую длину"
84
+
85
+ model = LogisticRegression()
86
+ model.fit(x_train, y_train)
87
+ return model
88
+
89
+ @staticmethod
90
+ def predict(model: LogisticRegression, x_test: np.ndarray):
91
+ """
92
+ Прогнозирует метки для тестового набора данных.
93
+
94
+ Parameters
95
+ ----------
96
+ model: LogisticRegression
97
+ Обученная модель.
98
+ x_test: np.ndarray
99
+ Массив значений размера (N, M). Где N - количество точек, M - количество атрибутов.
100
+
101
+ Returns
102
+ -------
103
+ np.ndarray
104
+ Массив меток размера N.
105
+ """
106
+
107
+ assert x_test.ndim == 2, "x_test: Ожидался 2D массив"
108
+
109
+ prediction = model.predict(x_test)
110
+ return prediction
111
+
112
+
113
+ class DecisionTreeClassifier:
114
+ """Класс для классификации Decision Tree."""
115
+ @staticmethod
116
+ def get_model(x_train: np.ndarray, y_train: np.ndarray, min_samples_split: int or float = 2, max_depth: int = None):
117
+ """
118
+ Возвращает модель обученную на тренировочных данных.
119
+
120
+ Parameters
121
+ ----------
122
+ x_train: np.ndarray
123
+ Массив значений размера (N, M). Где N - количество точек, M - количество атрибутов.
124
+ y_train: np.ndarray
125
+ Массив значений размера N.
126
+ min_samples_split: int or float = 2
127
+ Минимальное количество выборок, необходимое для разделения внутреннего узла.(параметр DecisionTree).
128
+ max_depth: int = None
129
+ Максимальная глубина дерева(параметр DecisionTree).
130
+
131
+ Returns
132
+ -------
133
+ DecisionTree
134
+ Обученная модель.
135
+ """
136
+
137
+ assert x_train.ndim == 2, "x_train: Ожидался 2D массив"
138
+ assert y_train.ndim == 1, "y_train: Ожидался 1D массив"
139
+ assert x_train.shape[0] == y_train.shape[0], "Массив y_train имеет несоответствующую длину"
140
+
141
+ model = DecisionTree(min_samples_split=min_samples_split, max_depth=max_depth)
142
+ model.fit(x_train, y_train)
143
+ return model
144
+
145
+ @staticmethod
146
+ def predict(model: DecisionTree, x_test: np.ndarray):
147
+ """
148
+ Прогнозирует метки для тестового набора данных.
149
+
150
+ Parameters
151
+ ----------
152
+ model: DecisionTree
153
+ Обученная модель.
154
+ x_test: np.ndarray
155
+ Массив значений размера (N, M). Где N - количество точек, M - количество атрибутов.
156
+
157
+ Returns
158
+ -------
159
+ np.ndarray
160
+ Массив меток размера N.
161
+ """
162
+
163
+ assert x_test.ndim == 2, "x_test: Ожидался 2D массив"
164
+
165
+ prediction = model.predict(x_test)
166
+ return prediction
167
+
168
+
169
+ class RandomForestClassifier:
170
+ """Класс для классификации Random Forest."""
171
+ @staticmethod
172
+ def get_model(x_train: np.ndarray, y_train: np.ndarray, n_estimators: int = 100, max_depth: int = None):
173
+ """
174
+ Возвращает модель обученную на тренировочных данных.
175
+
176
+ Parameters
177
+ ----------
178
+ x_train: np.ndarray
179
+ Массив значений размера (N, M). Где N - количество точек, M - количество атрибутов.
180
+ y_train: np.ndarray
181
+ Массив значений размера N.
182
+ n_estimators: int = 100
183
+ Количество деревьев в лесу.(параметр RandomForest).
184
+ max_depth: int = None
185
+ Максимальная глубина дерева(параметр RandomForest).
186
+ Returns
187
+ -------
188
+ RandomForest
189
+ Обученная модель.
190
+ """
191
+
192
+ assert x_train.ndim == 2, "x_train: Ожидался 2D массив"
193
+ assert y_train.ndim == 1, "y_train: Ожидался 1D массив"
194
+ assert x_train.shape[0] == y_train.shape[0], "Массив y_train имеет несоответствующую длину"
195
+
196
+ model = RandomForest(n_estimators=n_estimators, max_depth=max_depth)
197
+ model.fit(x_train,y_train)
198
+ return model
199
+
200
+ @staticmethod
201
+ def predict(model: RandomForest, x_test: np.ndarray):
202
+ """
203
+ Прогнозирует метки для тестового набора данных.
204
+
205
+ Parameters
206
+ ----------
207
+ model: RandomForest
208
+ Обученная модель.
209
+ x_test: np.ndarray
210
+ Массив значений размера (N, M). Где N - количество точек, M - количество атрибутов.
211
+
212
+ Returns
213
+ -------
214
+ np.ndarray
215
+ Массив меток размера N.
216
+ """
217
+
218
+ assert x_test.ndim == 2, "x_test: Ожидался 2D массив"
219
+
220
+ prediction = model.predict(x_test)
221
+ return prediction
@@ -0,0 +1,252 @@
1
+ from sklearn.cluster import KMeans, HDBSCAN
2
+ import numpy as np
3
+ from scipy import stats
4
+ from sklearn.mixture import GaussianMixture
5
+
6
+ RANDOM_STATE = 42
7
+ ALPHA_K = 0.02
8
+
9
+
10
+ class KMeansClassifier:
11
+ """Класс для KMeans кластеризации."""
12
+
13
+ @staticmethod
14
+ def __get_scaled_inertia(data, cluster):
15
+ inertia_o = np.square((data - data.mean(axis=0))).sum()
16
+ scaled_inertia = cluster.inertia_ / inertia_o + ALPHA_K * cluster.n_clusters
17
+ return scaled_inertia
18
+
19
+ @staticmethod
20
+ def __get_cluster(data, n_clusters):
21
+ cluster = KMeans(n_clusters=n_clusters,
22
+ random_state=RANDOM_STATE, algorithm='elkan')
23
+ cluster.fit(data)
24
+ return cluster
25
+
26
+ @staticmethod
27
+ def __get_cluster_centers(kmeans):
28
+ kmeans_centers = np.unique(np.sum(kmeans.cluster_centers_, axis=1))
29
+ return kmeans_centers
30
+
31
+ @staticmethod
32
+ def __get_labels(data, n_clusters):
33
+ kmeans = KMeansClassifier.__get_cluster(data, n_clusters)
34
+ kmeans_labels_before_sorting = kmeans.labels_
35
+ kmeans_centers = KMeansClassifier.__get_cluster_centers(kmeans)
36
+ kmeans_uniq_labels = np.unique(kmeans_labels_before_sorting)
37
+ sorted_kmeans_uniq_labels = kmeans_uniq_labels[np.argsort(kmeans_centers)]
38
+
39
+ kmeans_labels = np.zeros_like(kmeans_labels_before_sorting)
40
+ for i, label in enumerate(sorted_kmeans_uniq_labels):
41
+ kmeans_labels[kmeans_labels_before_sorting == label] = i
42
+
43
+ return kmeans_labels
44
+
45
+ @staticmethod
46
+ def find_the_best_number_of_clusters(data: np.ndarray) -> int:
47
+ """
48
+ Подбирает оптимальное количество кластеров на основании взвешенной инерции.
49
+
50
+ Parameters
51
+ ----------
52
+ data: np.ndarray
53
+ 2D массив значений.
54
+
55
+ Returns
56
+ -------
57
+ int
58
+ Оптимальное количество кластеров.
59
+ """
60
+
61
+ assert data.ndim == 2, "data: Ожидался 2D массив"
62
+
63
+ scaled_inertia_list = []
64
+ number_of_clusters_list = range(2, min(15, data.shape[0]))
65
+ for number_of_clusters in number_of_clusters_list:
66
+ cluster = KMeansClassifier.__get_cluster(data, number_of_clusters)
67
+ scaled_inertia = KMeansClassifier.__get_scaled_inertia(data, cluster)
68
+ scaled_inertia_list.append(scaled_inertia)
69
+ scaled_inertia_list = np.asarray(scaled_inertia_list)
70
+ best_number_of_clusters = number_of_clusters_list[np.argmin(scaled_inertia_list)]
71
+ return best_number_of_clusters
72
+
73
+ @staticmethod
74
+ def calculate(data: np.ndarray, n_clusters: int) -> np.ndarray:
75
+ """
76
+ Распределяет объекты по n_clusters кластерам по сходству. Для вычисления этого сходства используется евклидово расстояние в качестве меры.
77
+
78
+ Parameters
79
+ ----------
80
+ data: np.ndarray
81
+ Массив значений (N, M). Где N-количество точек, M - количество атрибутов.
82
+ n_clusters: int
83
+ Количество кластеров.
84
+
85
+ Returns
86
+ -------
87
+ np.ndarray
88
+ Массив меток размера N.
89
+ """
90
+
91
+ assert data.ndim == 2, "data: Ожидался 2D массив"
92
+ assert n_clusters > 0, "Параметр n_clusters должен принимать положительное значение"
93
+
94
+ labels = KMeansClassifier.__get_labels(data=data, n_clusters=n_clusters)
95
+ return labels
96
+
97
+
98
+ class GaussianMixtureClassifier:
99
+ """Класс для Gaussian Mixture кластеризации."""
100
+
101
+ @staticmethod
102
+ def __get_cluster(data, number_of_clusters):
103
+ cluster = GaussianMixture(n_components=number_of_clusters,
104
+ random_state=RANDOM_STATE)
105
+ cluster.fit(data)
106
+ return cluster
107
+
108
+ @staticmethod
109
+ def __get_cluster_centers(gm, data):
110
+ centers = np.empty(shape=(gm.n_components, data.shape[1]))
111
+ for i in range(gm.n_components):
112
+ density = stats.multivariate_normal(cov=gm.covariances_[i], mean=gm.means_[i]).logpdf(data)
113
+ centers[i, :] = data[np.argmax(density)]
114
+ centers = np.sum(centers, axis=1)
115
+ return centers
116
+
117
+ @staticmethod
118
+ def __get_labels(data, n_clusters):
119
+ gm = GaussianMixtureClassifier.__get_cluster(data, n_clusters)
120
+ gm_labels_before_sorting = gm.predict(data)
121
+ gm_centers = GaussianMixtureClassifier.__get_cluster_centers(gm, data)
122
+ gm_uniq_labels = np.unique(gm_labels_before_sorting)
123
+ sorted_gm_uniq_labels = gm_uniq_labels[np.argsort(gm_centers)]
124
+
125
+ gm_labels = np.zeros_like(gm_labels_before_sorting)
126
+ for i, label in enumerate(sorted_gm_uniq_labels):
127
+ gm_labels[gm_labels_before_sorting == label] = i
128
+
129
+ return gm_labels
130
+
131
+ @staticmethod
132
+ def find_the_best_number_of_clusters(data: np.ndarray) -> int:
133
+ """
134
+ Подбирает оптимальное количество кластеров на основе Байесовского критерия.
135
+
136
+ Parameters
137
+ ----------
138
+ data: np.ndarray
139
+ 2D массив значений.
140
+
141
+ Returns
142
+ -------
143
+ int
144
+ Оптимальное количество кластеров.
145
+ """
146
+
147
+ assert data.ndim == 2, "data: Ожидался 2D массив"
148
+
149
+ bic_list = []
150
+ number_of_clusters_list = range(2, min(15, data.shape[0] + 1))
151
+ for number_of_clusters in number_of_clusters_list:
152
+ gm = GaussianMixtureClassifier.__get_cluster(data, number_of_clusters)
153
+ bic = -gm.bic(data)
154
+ if bic < 0:
155
+ bic = np.nan
156
+ bic_list.append(bic)
157
+ bic_list = np.asarray(bic_list)
158
+ # bic_list_log = np.log(bic_list)
159
+ # best_number_of_clusters = number_of_clusters_list[np.nanargmin(bic_list_log)]
160
+ best_number_of_clusters = number_of_clusters_list[np.nanargmin(bic_list)]
161
+ return best_number_of_clusters
162
+
163
+ @staticmethod
164
+ def calculate(data: np.ndarray, n_clusters: int) -> np.ndarray:
165
+ """
166
+ Распределяет объекты по n_clusters кластерам, предполагая, что данные состоят из смеси гауссовых распределений.
167
+
168
+ Parameters
169
+ ----------
170
+ data: np.ndarray
171
+ Массив значений (N, M). Где N - количество точек, M - количество атрибутов.
172
+ n_clusters: int
173
+ Количество кластеров.
174
+
175
+ Returns
176
+ -------
177
+ np.ndarray
178
+ Массив меток размера N.
179
+ """
180
+
181
+ assert data.ndim == 2, "data: Ожидался 2D массив"
182
+ assert n_clusters > 0, "Параметр n_clusters должен принимать положительное значение"
183
+
184
+ labels = GaussianMixtureClassifier.__get_labels(data=data, n_clusters=n_clusters)
185
+ return labels
186
+
187
+
188
+ class HDBSCANClassifier:
189
+ """Класс для HDBSCAN кластеризации."""
190
+
191
+ @staticmethod
192
+ def __get_cluster(data, min_cluster_size, min_samples, cluster_selection_epsilon):
193
+ cluster = HDBSCAN(min_cluster_size=min_cluster_size, min_samples=min_samples,
194
+ cluster_selection_epsilon=cluster_selection_epsilon)
195
+ cluster.fit(data)
196
+ return cluster
197
+
198
+ @staticmethod
199
+ def __get_labels(data, min_cluster_size, min_samples, cluster_selection_epsilon):
200
+ hdbscan = HDBSCANClassifier.__get_cluster(data, min_cluster_size, min_samples, cluster_selection_epsilon)
201
+ hdbscan_labels = hdbscan.labels_
202
+ return hdbscan_labels
203
+
204
+ @staticmethod
205
+ def get_number_of_clusters(labels: np.ndarray) -> int:
206
+ """
207
+ Возвращает количество кластеров.
208
+
209
+ Parameters
210
+ ----------
211
+ labels: np.ndarray
212
+ 1D массив меток.
213
+
214
+ Returns
215
+ -------
216
+ int
217
+ Количество кластеров.
218
+ """
219
+
220
+ assert labels.ndim == 1, "labels: Ожидался 1D массив"
221
+
222
+ return np.unique(labels).shape[0]
223
+
224
+ @staticmethod
225
+ def calculate(data: np.ndarray,
226
+ min_cluster_size: int = 5,
227
+ min_samples: int = None,
228
+ cluster_selection_epsilon: float = 0.0) -> np.ndarray:
229
+ """
230
+ Выявляет кластеры в наборе данных на основе распределения плотности точек данных.
231
+
232
+ Parameters
233
+ ----------
234
+ data: np.ndarray
235
+ Массив значений (N, M). Где N-количество точек, M - количество атрибутов.
236
+ min_cluster_size: int, default=5
237
+ Минимальное количество выборок, чтобы эта группа считалась кластером(параметр HDBSCAN).
238
+ min_samples: int, default=None
239
+ Минимальное количество выборок в окрестности, чтобы точка считалась центральной(параметр HDBSCAN).
240
+ cluster_selection_epsilon: float, default=0.0
241
+ Максимальное расстояние, допустимое между точками, чтобы они считались связанными в процессе кластеризации на основе плотности(параметр HDBSCAN).
242
+
243
+ Returns
244
+ -------
245
+ np.ndarray
246
+ Массив меток размера N.
247
+ """
248
+
249
+ assert data.ndim == 2, "data: Ожидался 2D массив"
250
+
251
+ labels = HDBSCANClassifier.__get_labels(data, min_cluster_size, min_samples, cluster_selection_epsilon)
252
+ return labels
@@ -0,0 +1,52 @@
1
+ import numpy as np
2
+ from sklearn.decomposition import PCA
3
+
4
+
5
+ RANDOM_STATE = 42
6
+
7
+
8
+ def get_pca_statistics(data: np.ndarray) -> np.ndarray:
9
+ """
10
+ Считает долю дисперсии для каждого компонента.
11
+
12
+ Parameters
13
+ ----------
14
+ data: np.ndarray
15
+ Массив значений, размера (N, M).
16
+
17
+ Returns
18
+ -------
19
+ np.ndarray
20
+ Массив доль дисперсии, размера N.
21
+ """
22
+
23
+ assert data.ndim == 2, "data: Ожидался 2D массив"
24
+
25
+ pca = PCA(n_components=data.shape[1],
26
+ random_state=RANDOM_STATE)
27
+ pca.fit(data)
28
+ return pca.explained_variance_ratio_
29
+
30
+
31
+ def pca_transform(data: np.ndarray, n_components: int) -> np.ndarray:
32
+ """
33
+ Понижение размерности с помощью PCA путём проецирования данных на главные (собственные) вектора.
34
+
35
+ Parameters
36
+ ----------
37
+ data: np.ndarray
38
+ Массив значений, размера (N, M).
39
+ n_components: int
40
+ Количество сохраняемых компонентов.
41
+
42
+ Returns
43
+ -------
44
+ np.ndarray
45
+ Преобразованный массив, размера (N, n_components).
46
+ """
47
+
48
+ assert data.ndim == 2, "data: Ожидался 2D массив"
49
+ assert n_components > 0, "Параметр n_components должен принимать положительное значение"
50
+
51
+ return PCA(n_components=n_components,
52
+ random_state=RANDOM_STATE).fit_transform(data)
@@ -0,0 +1,68 @@
1
+ import numpy as np
2
+ from .curve_utils import get_peaks, remove_single_width_peaks, remove_given_width_peaks
3
+
4
+
5
+ def fill_with_value_by_mask(data: np.ndarray, mask: np.ndarray, blank_code: float) -> np.ndarray:
6
+ """
7
+ Востанавливает массив, заполняя кодом бланковки по маске.
8
+
9
+ Parameters
10
+ ----------
11
+ data: np.ndarray
12
+ Массив значений, размером N.
13
+ mask: np.ndarray
14
+ Маска(True - в строке был nan, False - в строке не было nan), размером M >= N.
15
+ blank_code: float
16
+ Код бланковки.
17
+
18
+ Returns
19
+ -------
20
+ np.ndarray
21
+ Востановленный массив, размером M.
22
+ """
23
+
24
+ assert data.ndim == 1, "data: Ожидался 1D массив"
25
+ assert mask.ndim == 1, "mask: Ожидался 1D массив"
26
+ assert mask.shape[0] >= data.shape[0], "Длина массива mask должна быть не меньше длины data"
27
+
28
+ data_with_blank_code = np.zeros(mask.shape[0])
29
+ data_with_blank_code[mask] = blank_code
30
+ data_with_blank_code[~mask] = data
31
+ return data_with_blank_code
32
+
33
+
34
+ def curve_peaks_processing(curve: np.ndarray, depth: np.ndarray, minimal_width_in_meter: float) -> np.ndarray:
35
+ """
36
+ Обработка пиков кривой. Удаление пиков, которые меньше заданной ширины (minimal_width_in_meter).
37
+
38
+ Parameters
39
+ ----------
40
+ curve: np.ndarray
41
+ Массив значений кривой, размером N.
42
+ depth: np.ndarray
43
+ Массив глубин кривой, размером N.
44
+ minimal_width_in_meter: float
45
+ Минимальная ширина пиков в метрах.
46
+
47
+ Returns
48
+ -------
49
+ np.ndarray
50
+ Обработанная кривая, размером N.
51
+ """
52
+
53
+ assert curve.ndim == 1, "curve: Ожидался 1D массив"
54
+ assert depth.ndim == 1, "depth: Ожидался 1D массив"
55
+ assert minimal_width_in_meter > 0, "Параметр minimal_width_in_meter должен принимать положительное значение"
56
+
57
+ dz = np.diff(depth)[0]
58
+ minimal_width_in_sample = int(minimal_width_in_meter / dz)
59
+
60
+ single_peaks = get_peaks(curve, 1)
61
+ single_filled_curve = remove_single_width_peaks(curve, single_peaks)
62
+
63
+ given_width_peaks = get_peaks(single_filled_curve, minimal_width_in_sample)
64
+ filled_curve = remove_given_width_peaks(single_filled_curve,
65
+ given_width_peaks,
66
+ minimal_width_in_sample)
67
+ filled_curve = abs(filled_curve - 1)
68
+ return filled_curve