upgini 1.1.223__py3-none-any.whl → 1.1.224__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.

Potentially problematic release.


This version of upgini might be problematic. Click here for more details.

upgini/dataset.py CHANGED
@@ -349,7 +349,11 @@ class Dataset: # (pd.DataFrame):
349
349
  self.columns_renaming[ipv4] = original_ip
350
350
 
351
351
  ipv6 = ip + "_v6"
352
- self.data[ipv6] = self.data[ip].apply(self._to_ipv6).apply(self.__ip_to_int).astype(str)
352
+ self.data[ipv6] = (
353
+ self.data[ip].apply(self._to_ipv6)
354
+ .apply(self.__ip_to_int)
355
+ .astype("string").str.replace(".0", "", regex=False)
356
+ )
353
357
  self.data = self.data.drop(columns=ip)
354
358
  self.meaning_types[ipv6] = FileColumnMeaningType.IPV6_ADDRESS
355
359
  self.etalon_def[FileColumnMeaningType.IPV6_ADDRESS.value] = ipv6
@@ -1,4 +1,3 @@
1
- from functools import reduce
2
1
  import gc
3
2
  import hashlib
4
3
  import itertools
@@ -11,6 +10,8 @@ import sys
11
10
  import tempfile
12
11
  import time
13
12
  import uuid
13
+ from collections import namedtuple
14
+ from functools import reduce
14
15
  from threading import Thread
15
16
  from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union
16
17
 
@@ -294,6 +295,18 @@ class FeaturesEnricher(TransformerMixin):
294
295
 
295
296
  api_key = property(_get_api_key, _set_api_key)
296
297
 
298
+ @staticmethod
299
+ def _check_eval_set(eval_set, X):
300
+ checked_eval_set = []
301
+ if eval_set is not None and not isinstance(eval_set, list):
302
+ raise ValidationError(bundle.get("unsupported_type_eval_set").format(type(eval_set)))
303
+ for eval_pair in eval_set or []:
304
+ if not isinstance(eval_pair, tuple) or len(eval_pair) != 2:
305
+ raise ValidationError(bundle.get("eval_set_invalid_tuple_size").format(len(eval_pair)))
306
+ if not is_frames_equal(X, eval_pair[0]):
307
+ checked_eval_set.append(eval_pair)
308
+ return checked_eval_set
309
+
297
310
  def fit(
298
311
  self,
299
312
  X: Union[pd.DataFrame, pd.Series, np.ndarray],
@@ -370,19 +383,13 @@ class FeaturesEnricher(TransformerMixin):
370
383
  try:
371
384
  self.X = X
372
385
  self.y = y
373
- checked_eval_set = []
374
- for eval_pair in eval_set or []:
375
- if len(eval_pair) != 2:
376
- raise ValidationError(bundle.get("eval_set_invalid_tuple_size").format(len(eval_pair)))
377
- if not is_frames_equal(X, eval_pair[0]):
378
- checked_eval_set.append(eval_pair)
379
- self.eval_set = checked_eval_set
386
+ self.eval_set = self._check_eval_set(eval_set, X)
380
387
  self.dump_input(trace_id, X, y, eval_set)
381
388
  self.__inner_fit(
382
389
  trace_id,
383
390
  X,
384
391
  y,
385
- checked_eval_set,
392
+ self.eval_set,
386
393
  progress_bar,
387
394
  start_time=start_time,
388
395
  exclude_features_sources=exclude_features_sources,
@@ -512,13 +519,7 @@ class FeaturesEnricher(TransformerMixin):
512
519
  try:
513
520
  self.X = X
514
521
  self.y = y
515
- checked_eval_set = []
516
- for eval_pair in eval_set or []:
517
- if len(eval_pair) != 2:
518
- raise ValidationError(bundle.get("eval_set_invalid_tuple_size").format(len(eval_pair)))
519
- if not is_frames_equal(X, eval_pair[0]):
520
- checked_eval_set.append(eval_pair)
521
- self.eval_set = checked_eval_set
522
+ self.eval_set = self._check_eval_set(eval_set, X)
522
523
  self.dump_input(trace_id, X, y, eval_set)
523
524
 
524
525
  if _num_samples(drop_duplicates(X)) > Dataset.MAX_ROWS:
@@ -528,7 +529,7 @@ class FeaturesEnricher(TransformerMixin):
528
529
  trace_id,
529
530
  X,
530
531
  y,
531
- checked_eval_set,
532
+ self.eval_set,
532
533
  progress_bar,
533
534
  start_time=start_time,
534
535
  exclude_features_sources=exclude_features_sources,
@@ -1189,12 +1190,7 @@ class FeaturesEnricher(TransformerMixin):
1189
1190
  if X is None:
1190
1191
  return True, self.X, self.y, self.eval_set
1191
1192
 
1192
- checked_eval_set = []
1193
- for eval_pair in eval_set or []:
1194
- if len(eval_pair) != 2:
1195
- raise ValidationError(bundle.get("eval_set_invalid_tuple_size").format(len(eval_pair)))
1196
- if not is_frames_equal(X, eval_pair[0]):
1197
- checked_eval_set.append(eval_pair)
1193
+ checked_eval_set = self._check_eval_set(eval_set, X)
1198
1194
 
1199
1195
  if (
1200
1196
  X is self.X
@@ -1231,181 +1227,28 @@ class FeaturesEnricher(TransformerMixin):
1231
1227
  progress_bar: Optional[ProgressBar] = None,
1232
1228
  progress_callback: Optional[Callable[[SearchProgress], Any]] = None,
1233
1229
  ):
1234
- is_demo_dataset = hash_input(X, y, eval_set) in DEMO_DATASET_HASHES
1235
1230
  is_input_same_as_fit, X, y, eval_set = self._is_input_same_as_fit(X, y, eval_set)
1231
+ is_demo_dataset = hash_input(X, y, eval_set) in DEMO_DATASET_HASHES
1236
1232
  validated_X = self._validate_X(X)
1237
1233
  validated_y = self._validate_y(validated_X, y)
1234
+ validated_eval_set = (
1235
+ [self._validate_eval_set_pair(validated_X, eval_set_pair) for eval_set_pair in eval_set]
1236
+ if eval_set
1237
+ else None
1238
+ )
1238
1239
 
1239
- eval_set_sampled_dict = dict()
1240
-
1241
- if self.__cached_sampled_datasets is not None and is_input_same_as_fit and remove_outliers_calc_metrics is None:
1242
- self.logger.info("Cached enriched dataset found - use it")
1243
- X_sampled, y_sampled, enriched_X, eval_set_sampled_dict, search_keys = self.__cached_sampled_datasets
1244
- if exclude_features_sources:
1245
- enriched_X = drop_existing_columns(enriched_X, exclude_features_sources)
1246
- elif len(self.feature_importances_) == 0:
1247
- self.logger.info("No external features selected. So use only input datasets for metrics calculation")
1248
- X_sampled, search_keys = self._extend_x(validated_X, is_demo_dataset)
1249
- y_sampled = validated_y
1250
- enriched_X = X_sampled
1251
- if eval_set is not None:
1252
- for idx in range(len(eval_set)):
1253
- eval_X_sampled, _ = self._extend_x(eval_set[idx][0], is_demo_dataset)
1254
- eval_y_sampled = eval_set[idx][1]
1255
- enriched_eval_X = eval_X_sampled
1256
- eval_set_sampled_dict[idx] = (eval_X_sampled, enriched_eval_X, eval_y_sampled)
1257
- self.__cached_sampled_datasets = (X_sampled, y_sampled, enriched_X, eval_set_sampled_dict, search_keys)
1258
- elif not self.imbalanced and not exclude_features_sources and is_input_same_as_fit:
1259
- self.logger.info("Dataset is not imbalanced, so use enriched_X from fit")
1260
- search_keys = self.fit_search_keys
1261
-
1262
- rows_to_drop = None
1263
- task_type = self.model_task_type or define_task(validated_y, self.logger, silent=True)
1264
- if task_type == ModelTaskType.REGRESSION:
1265
- target_outliers_df = self._search_task.get_target_outliers(trace_id)
1266
- if target_outliers_df is not None and len(target_outliers_df) > 0:
1267
- outliers = pd.merge(
1268
- self.df_with_original_index,
1269
- target_outliers_df,
1270
- left_on=SYSTEM_RECORD_ID,
1271
- right_on=SYSTEM_RECORD_ID,
1272
- how="inner",
1273
- )
1274
- top_outliers = outliers.sort_values(by=TARGET, ascending=False)[TARGET].head(3)
1275
- if remove_outliers_calc_metrics is None or remove_outliers_calc_metrics is True:
1276
- rows_to_drop = outliers
1277
- not_msg = ""
1278
- else:
1279
- not_msg = "not "
1280
- msg = bundle.get("target_outliers_warning").format(len(target_outliers_df), top_outliers, not_msg)
1281
- print(msg)
1282
- self.logger.warning(msg)
1283
-
1284
- enriched_Xy, enriched_eval_sets = self.__enrich(
1285
- self.df_with_original_index,
1286
- self._search_task.get_all_initial_raw_features(trace_id, metrics_calculation=True),
1287
- rows_to_drop=rows_to_drop,
1288
- )
1289
-
1290
- enriched_X = drop_existing_columns(enriched_Xy, TARGET)
1291
- x_columns = [
1292
- c for c in validated_X.columns.to_list() + self.fit_generated_features if c in enriched_X.columns
1293
- ]
1294
- X_sampled = enriched_Xy[x_columns].copy()
1295
- y_sampled = enriched_Xy[TARGET].copy()
1296
-
1297
- self.logger.info(f"Shape of enriched_X: {enriched_X.shape}")
1298
- self.logger.info(f"Shape of X after sampling: {X_sampled.shape}")
1299
- self.logger.info(f"Shape of y after sampling: {len(y_sampled)}")
1300
-
1301
- if eval_set is not None:
1302
- if len(enriched_eval_sets) != len(eval_set):
1303
- raise ValidationError(
1304
- bundle.get("metrics_eval_set_count_diff").format(len(enriched_eval_sets), len(eval_set))
1305
- )
1306
-
1307
- for idx in range(len(eval_set)):
1308
- enriched_eval_X = drop_existing_columns(enriched_eval_sets[idx + 1], TARGET)
1309
- eval_X_sampled = enriched_eval_sets[idx + 1][x_columns].copy()
1310
- eval_y_sampled = enriched_eval_sets[idx + 1][TARGET].copy()
1311
- eval_set_sampled_dict[idx] = (eval_X_sampled, enriched_eval_X, eval_y_sampled)
1312
-
1313
- self.__cached_sampled_datasets = (X_sampled, y_sampled, enriched_X, eval_set_sampled_dict, search_keys)
1314
- else:
1315
- self.logger.info("Dataset is imbalanced or exclude_features_sources or X was passed. Run transform")
1316
- print(bundle.get("prepare_data_for_metrics"))
1317
- if eval_set is not None:
1318
- self.logger.info("Transform with eval_set")
1319
- # concatenate X and eval_set with eval_set_index
1320
- df_with_eval_set_index = validated_X.copy()
1321
- df_with_eval_set_index[TARGET] = validated_y
1322
- df_with_eval_set_index[EVAL_SET_INDEX] = 0
1323
- for idx, eval_pair in enumerate(eval_set):
1324
- eval_x, eval_y = self._validate_eval_set_pair(validated_X, eval_pair)
1325
- eval_df_with_index = eval_x.copy()
1326
- eval_df_with_index[TARGET] = eval_y
1327
- eval_df_with_index[EVAL_SET_INDEX] = idx + 1
1328
- df_with_eval_set_index = pd.concat([df_with_eval_set_index, eval_df_with_index])
1329
-
1330
- # downsample if need to eval_set threshold
1331
- num_samples = _num_samples(df_with_eval_set_index)
1332
- if num_samples > Dataset.FIT_SAMPLE_WITH_EVAL_SET_THRESHOLD:
1333
- self.logger.info(f"Downsampling from {num_samples} to {Dataset.FIT_SAMPLE_WITH_EVAL_SET_ROWS}")
1334
- df_with_eval_set_index = df_with_eval_set_index.sample(
1335
- n=Dataset.FIT_SAMPLE_WITH_EVAL_SET_ROWS, random_state=self.random_state
1336
- )
1337
-
1338
- X_sampled = (
1339
- df_with_eval_set_index[df_with_eval_set_index[EVAL_SET_INDEX] == 0]
1340
- .copy()
1341
- .drop(columns=[EVAL_SET_INDEX, TARGET])
1342
- )
1343
- X_sampled, search_keys = self._extend_x(X_sampled, is_demo_dataset)
1344
- y_sampled = df_with_eval_set_index[df_with_eval_set_index[EVAL_SET_INDEX] == 0].copy()[TARGET]
1345
- eval_set_sampled_dict = dict()
1346
- for idx in range(len(eval_set)):
1347
- eval_x_sampled = (
1348
- df_with_eval_set_index[df_with_eval_set_index[EVAL_SET_INDEX] == (idx + 1)]
1349
- .copy()
1350
- .drop(columns=[EVAL_SET_INDEX, TARGET])
1351
- )
1352
- eval_x_sampled, _ = self._extend_x(eval_x_sampled, is_demo_dataset)
1353
- eval_y_sampled = df_with_eval_set_index[df_with_eval_set_index[EVAL_SET_INDEX] == (idx + 1)].copy()[
1354
- TARGET
1355
- ]
1356
- eval_set_sampled_dict[idx] = (eval_x_sampled, eval_y_sampled)
1357
-
1358
- df_with_eval_set_index.drop(columns=TARGET, inplace=True)
1359
-
1360
- enriched = self.transform(
1361
- df_with_eval_set_index,
1362
- exclude_features_sources=exclude_features_sources,
1363
- silent_mode=True,
1364
- trace_id=trace_id,
1365
- metrics_calculation=True,
1366
- progress_bar=progress_bar,
1367
- progress_callback=progress_callback,
1368
- )
1369
- if enriched is None:
1370
- return None
1371
-
1372
- enriched_X = enriched[enriched[EVAL_SET_INDEX] == 0].copy()
1373
- enriched_X.drop(columns=EVAL_SET_INDEX, inplace=True)
1374
-
1375
- for idx in range(len(eval_set)):
1376
- enriched_eval_x = enriched[enriched[EVAL_SET_INDEX] == (idx + 1)].copy()
1377
- enriched_eval_x.drop(columns=EVAL_SET_INDEX, inplace=True)
1378
- eval_x_sampled, eval_y_sampled = eval_set_sampled_dict[idx]
1379
- eval_set_sampled_dict[idx] = (eval_x_sampled, enriched_eval_x, eval_y_sampled)
1380
- else:
1381
- self.logger.info("Transform without eval_set")
1382
- df = self.X.copy()
1383
-
1384
- df[TARGET] = validated_y
1385
- num_samples = _num_samples(df)
1386
- if num_samples > Dataset.FIT_SAMPLE_THRESHOLD:
1387
- self.logger.info(f"Downsampling from {num_samples} to {Dataset.FIT_SAMPLE_ROWS}")
1388
- df = df.sample(n=Dataset.FIT_SAMPLE_ROWS, random_state=self.random_state)
1389
-
1390
- X_sampled = df.copy().drop(columns=TARGET)
1391
- X_sampled, search_keys = self._extend_x(X_sampled, is_demo_dataset)
1392
- y_sampled = df.copy()[TARGET]
1393
-
1394
- df.drop(columns=TARGET, inplace=True)
1395
-
1396
- enriched_X = self.transform(
1397
- df,
1398
- exclude_features_sources=exclude_features_sources,
1399
- silent_mode=True,
1400
- trace_id=trace_id,
1401
- metrics_calculation=True,
1402
- progress_bar=progress_bar,
1403
- progress_callback=progress_callback,
1404
- )
1405
- if enriched_X is None:
1406
- return None
1407
-
1408
- self.__cached_sampled_datasets = (X_sampled, y_sampled, enriched_X, eval_set_sampled_dict, search_keys)
1240
+ X_sampled, y_sampled, enriched_X, eval_set_sampled_dict, search_keys = self._sample_data_for_metrics(
1241
+ trace_id,
1242
+ validated_X,
1243
+ validated_y,
1244
+ validated_eval_set,
1245
+ exclude_features_sources,
1246
+ is_input_same_as_fit,
1247
+ is_demo_dataset,
1248
+ remove_outliers_calc_metrics,
1249
+ progress_bar,
1250
+ progress_callback,
1251
+ )
1409
1252
 
1410
1253
  excluding_search_keys = list(search_keys.keys())
1411
1254
  if search_keys_for_metrics is not None and len(search_keys_for_metrics) > 0:
@@ -1425,12 +1268,12 @@ class FeaturesEnricher(TransformerMixin):
1425
1268
  X_sorted, y_sorted = self._sort_by_keys(X_sampled, y_sampled, search_keys, self.cv)
1426
1269
  enriched_X_sorted, enriched_y_sorted = self._sort_by_keys(enriched_X, y_sampled, search_keys, self.cv)
1427
1270
 
1428
- group_columns = self._get_group_columns(search_keys)
1271
+ group_columns = sorted(self._get_group_columns(search_keys))
1429
1272
  groups = (
1430
1273
  None
1431
- if not group_columns
1274
+ if not group_columns or self.cv != CVType.group_k_fold
1432
1275
  else reduce(
1433
- lambda left, right: left + "_" + right, [X_sorted[c].astype(str) for c in group_columns]
1276
+ lambda left, right: left + "_" + right, [enriched_X_sorted[c].astype(str) for c in group_columns]
1434
1277
  ).factorize()[0]
1435
1278
  )
1436
1279
 
@@ -1478,6 +1321,258 @@ class FeaturesEnricher(TransformerMixin):
1478
1321
  groups,
1479
1322
  )
1480
1323
 
1324
+ _SampledDataForMetrics = namedtuple(
1325
+ "_SampledDataForMetrics", "X_sampled y_sampled enriched_X eval_set_sampled_dict search_keys"
1326
+ )
1327
+
1328
+ def _sample_data_for_metrics(
1329
+ self,
1330
+ trace_id: str,
1331
+ validated_X: Union[pd.DataFrame, pd.Series, np.ndarray, None],
1332
+ validated_y: Union[pd.DataFrame, pd.Series, np.ndarray, List, None],
1333
+ eval_set: Optional[List[tuple]],
1334
+ exclude_features_sources: Optional[List[str]],
1335
+ is_input_same_as_fit: bool,
1336
+ is_demo_dataset: bool,
1337
+ remove_outliers_calc_metrics: Optional[bool],
1338
+ progress_bar: Optional[ProgressBar],
1339
+ progress_callback: Optional[Callable[[SearchProgress], Any]],
1340
+ ) -> _SampledDataForMetrics:
1341
+ if self.__cached_sampled_datasets is not None and is_input_same_as_fit and remove_outliers_calc_metrics is None:
1342
+ self.logger.info("Cached enriched dataset found - use it")
1343
+ return self.__get_sampled_cached_enriched(exclude_features_sources)
1344
+ elif len(self.feature_importances_) == 0:
1345
+ self.logger.info("No external features selected. So use only input datasets for metrics calculation")
1346
+ return self.__sample_only_input(validated_X, validated_y, eval_set, is_demo_dataset)
1347
+ elif not self.imbalanced and not exclude_features_sources and is_input_same_as_fit:
1348
+ self.logger.info("Dataset is not imbalanced, so use enriched_X from fit")
1349
+ return self.__sample_balanced(
1350
+ validated_X, validated_y, eval_set, trace_id, remove_outliers_calc_metrics, is_demo_dataset
1351
+ )
1352
+ else:
1353
+ self.logger.info("Dataset is imbalanced or exclude_features_sources or X was passed. Run transform")
1354
+ print(bundle.get("prepare_data_for_metrics"))
1355
+ return self.__sample_imbalanced(
1356
+ validated_X,
1357
+ validated_y,
1358
+ eval_set,
1359
+ is_demo_dataset,
1360
+ exclude_features_sources,
1361
+ trace_id,
1362
+ progress_bar,
1363
+ progress_callback,
1364
+ )
1365
+
1366
+ def __get_sampled_cached_enriched(self, exclude_features_sources: Optional[List[str]]) -> _SampledDataForMetrics:
1367
+ X_sampled, y_sampled, enriched_X, eval_set_sampled_dict, search_keys = self.__cached_sampled_datasets
1368
+ if exclude_features_sources:
1369
+ enriched_X = drop_existing_columns(enriched_X, exclude_features_sources)
1370
+
1371
+ return self.__mk_sampled_data_tuple(X_sampled, y_sampled, enriched_X, eval_set_sampled_dict, search_keys)
1372
+
1373
+ def __sample_only_input(
1374
+ self, validated_X: pd.DataFrame, validated_y: pd.Series, eval_set: Optional[List[tuple]], is_demo_dataset: bool
1375
+ ) -> _SampledDataForMetrics:
1376
+ eval_set_sampled_dict = dict()
1377
+ X_sampled, search_keys = self._extend_x(validated_X, is_demo_dataset)
1378
+ y_sampled = validated_y
1379
+ enriched_X = X_sampled
1380
+ if eval_set is not None:
1381
+ for idx in range(len(eval_set)):
1382
+ eval_X_sampled, _ = self._extend_x(eval_set[idx][0], is_demo_dataset)
1383
+ eval_y_sampled = eval_set[idx][1]
1384
+ enriched_eval_X = eval_X_sampled
1385
+ eval_set_sampled_dict[idx] = (eval_X_sampled, enriched_eval_X, eval_y_sampled)
1386
+ self.__cached_sampled_datasets = (X_sampled, y_sampled, enriched_X, eval_set_sampled_dict, search_keys)
1387
+
1388
+ return self.__mk_sampled_data_tuple(X_sampled, y_sampled, enriched_X, eval_set_sampled_dict, search_keys)
1389
+
1390
+ def __sample_balanced(
1391
+ self,
1392
+ validated_X: pd.DataFrame,
1393
+ validated_y: pd.Series,
1394
+ eval_set: Optional[List[tuple]],
1395
+ trace_id: str,
1396
+ remove_outliers_calc_metrics: Optional[bool],
1397
+ is_demo_dataset: bool,
1398
+ ) -> _SampledDataForMetrics:
1399
+ eval_set_sampled_dict = dict()
1400
+ search_keys = self.fit_search_keys
1401
+
1402
+ rows_to_drop = None
1403
+ task_type = self.model_task_type or define_task(validated_y, self.logger, silent=True)
1404
+ if task_type == ModelTaskType.REGRESSION:
1405
+ target_outliers_df = self._search_task.get_target_outliers(trace_id)
1406
+ if target_outliers_df is not None and len(target_outliers_df) > 0:
1407
+ outliers = pd.merge(
1408
+ self.df_with_original_index,
1409
+ target_outliers_df,
1410
+ left_on=SYSTEM_RECORD_ID,
1411
+ right_on=SYSTEM_RECORD_ID,
1412
+ how="inner",
1413
+ )
1414
+ top_outliers = outliers.sort_values(by=TARGET, ascending=False)[TARGET].head(3)
1415
+ if remove_outliers_calc_metrics is None or remove_outliers_calc_metrics is True:
1416
+ rows_to_drop = outliers
1417
+ not_msg = ""
1418
+ else:
1419
+ not_msg = "not "
1420
+ msg = bundle.get("target_outliers_warning").format(len(target_outliers_df), top_outliers, not_msg)
1421
+ print(msg)
1422
+ self.logger.warning(msg)
1423
+
1424
+ # index in each dataset (X, eval set) may be reordered and non unique, but index in validated datasets
1425
+ # can differs from it
1426
+ enriched_Xy, enriched_eval_sets = self.__enrich(
1427
+ self.df_with_original_index,
1428
+ self._search_task.get_all_initial_raw_features(trace_id, metrics_calculation=True),
1429
+ rows_to_drop=rows_to_drop,
1430
+ )
1431
+
1432
+ enriched_X = drop_existing_columns(enriched_Xy, TARGET)
1433
+ X_sampled, search_keys = self._extend_x(validated_X, is_demo_dataset)
1434
+ y_sampled = enriched_Xy[TARGET].copy()
1435
+
1436
+ self.logger.info(f"Shape of enriched_X: {enriched_X.shape}")
1437
+ self.logger.info(f"Shape of X after sampling: {X_sampled.shape}")
1438
+ self.logger.info(f"Shape of y after sampling: {len(y_sampled)}")
1439
+
1440
+ if eval_set is not None:
1441
+ if len(enriched_eval_sets) != len(eval_set):
1442
+ raise ValidationError(
1443
+ bundle.get("metrics_eval_set_count_diff").format(len(enriched_eval_sets), len(eval_set))
1444
+ )
1445
+
1446
+ for idx in range(len(eval_set)):
1447
+ enriched_eval_X = drop_existing_columns(enriched_eval_sets[idx + 1], TARGET)
1448
+ eval_X_sampled, _ = self._extend_x(eval_set[idx][0], is_demo_dataset)
1449
+ eval_y_sampled = eval_set[idx][1].copy()
1450
+ eval_set_sampled_dict[idx] = (eval_X_sampled, enriched_eval_X, eval_y_sampled)
1451
+
1452
+ self.__cached_sampled_datasets = (X_sampled, y_sampled, enriched_X, eval_set_sampled_dict, search_keys)
1453
+
1454
+ return self.__mk_sampled_data_tuple(X_sampled, y_sampled, enriched_X, eval_set_sampled_dict, search_keys)
1455
+
1456
+ def __sample_imbalanced(
1457
+ self,
1458
+ validated_X: pd.DataFrame,
1459
+ validated_y: pd.Series,
1460
+ eval_set: Optional[List[tuple]],
1461
+ is_demo_dataset: bool,
1462
+ exclude_features_sources: Optional[List[str]],
1463
+ trace_id: str,
1464
+ progress_bar: Optional[ProgressBar],
1465
+ progress_callback: Optional[Callable[[SearchProgress], Any]],
1466
+ ) -> _SampledDataForMetrics:
1467
+ eval_set_sampled_dict = dict()
1468
+ if eval_set is not None:
1469
+ self.logger.info("Transform with eval_set")
1470
+ # concatenate X and eval_set with eval_set_index
1471
+ df_with_eval_set_index = validated_X.copy()
1472
+ df_with_eval_set_index[TARGET] = validated_y
1473
+ df_with_eval_set_index[EVAL_SET_INDEX] = 0
1474
+ for idx, eval_pair in enumerate(eval_set):
1475
+ eval_x, eval_y = self._validate_eval_set_pair(validated_X, eval_pair)
1476
+ eval_df_with_index = eval_x.copy()
1477
+ eval_df_with_index[TARGET] = eval_y
1478
+ eval_df_with_index[EVAL_SET_INDEX] = idx + 1
1479
+ df_with_eval_set_index = pd.concat([df_with_eval_set_index, eval_df_with_index])
1480
+
1481
+ # downsample if need to eval_set threshold
1482
+ num_samples = _num_samples(df_with_eval_set_index)
1483
+ if num_samples > Dataset.FIT_SAMPLE_WITH_EVAL_SET_THRESHOLD:
1484
+ self.logger.info(f"Downsampling from {num_samples} to {Dataset.FIT_SAMPLE_WITH_EVAL_SET_ROWS}")
1485
+ df_with_eval_set_index = df_with_eval_set_index.sample(
1486
+ n=Dataset.FIT_SAMPLE_WITH_EVAL_SET_ROWS, random_state=self.random_state
1487
+ )
1488
+
1489
+ X_sampled = (
1490
+ df_with_eval_set_index[df_with_eval_set_index[EVAL_SET_INDEX] == 0]
1491
+ .copy()
1492
+ .drop(columns=[EVAL_SET_INDEX, TARGET])
1493
+ )
1494
+ X_sampled, search_keys = self._extend_x(X_sampled, is_demo_dataset)
1495
+ y_sampled = df_with_eval_set_index[df_with_eval_set_index[EVAL_SET_INDEX] == 0].copy()[TARGET]
1496
+ eval_set_sampled_dict = dict()
1497
+ for idx in range(len(eval_set)):
1498
+ eval_x_sampled = (
1499
+ df_with_eval_set_index[df_with_eval_set_index[EVAL_SET_INDEX] == (idx + 1)]
1500
+ .copy()
1501
+ .drop(columns=[EVAL_SET_INDEX, TARGET])
1502
+ )
1503
+ eval_x_sampled, _ = self._extend_x(eval_x_sampled, is_demo_dataset)
1504
+ eval_y_sampled = df_with_eval_set_index[df_with_eval_set_index[EVAL_SET_INDEX] == (idx + 1)].copy()[
1505
+ TARGET
1506
+ ]
1507
+ eval_set_sampled_dict[idx] = (eval_x_sampled, eval_y_sampled)
1508
+
1509
+ df_with_eval_set_index.drop(columns=TARGET, inplace=True)
1510
+
1511
+ enriched = self.transform(
1512
+ df_with_eval_set_index,
1513
+ exclude_features_sources=exclude_features_sources,
1514
+ silent_mode=True,
1515
+ trace_id=trace_id,
1516
+ metrics_calculation=True,
1517
+ progress_bar=progress_bar,
1518
+ progress_callback=progress_callback,
1519
+ )
1520
+ if enriched is None:
1521
+ return None
1522
+
1523
+ enriched_X = enriched[enriched[EVAL_SET_INDEX] == 0].copy()
1524
+ enriched_X.drop(columns=EVAL_SET_INDEX, inplace=True)
1525
+
1526
+ for idx in range(len(eval_set)):
1527
+ enriched_eval_x = enriched[enriched[EVAL_SET_INDEX] == (idx + 1)].copy()
1528
+ enriched_eval_x.drop(columns=EVAL_SET_INDEX, inplace=True)
1529
+ eval_x_sampled, eval_y_sampled = eval_set_sampled_dict[idx]
1530
+ eval_set_sampled_dict[idx] = (eval_x_sampled, enriched_eval_x, eval_y_sampled)
1531
+ else:
1532
+ self.logger.info("Transform without eval_set")
1533
+ df = self.X.copy()
1534
+
1535
+ df[TARGET] = validated_y
1536
+ num_samples = _num_samples(df)
1537
+ if num_samples > Dataset.FIT_SAMPLE_THRESHOLD:
1538
+ self.logger.info(f"Downsampling from {num_samples} to {Dataset.FIT_SAMPLE_ROWS}")
1539
+ df = df.sample(n=Dataset.FIT_SAMPLE_ROWS, random_state=self.random_state)
1540
+
1541
+ X_sampled = df.copy().drop(columns=TARGET)
1542
+ X_sampled, search_keys = self._extend_x(X_sampled, is_demo_dataset)
1543
+ y_sampled = df.copy()[TARGET]
1544
+
1545
+ df.drop(columns=TARGET, inplace=True)
1546
+
1547
+ enriched_X = self.transform(
1548
+ df,
1549
+ exclude_features_sources=exclude_features_sources,
1550
+ silent_mode=True,
1551
+ trace_id=trace_id,
1552
+ metrics_calculation=True,
1553
+ progress_bar=progress_bar,
1554
+ progress_callback=progress_callback,
1555
+ )
1556
+ if enriched_X is None:
1557
+ return None
1558
+
1559
+ self.__cached_sampled_datasets = (X_sampled, y_sampled, enriched_X, eval_set_sampled_dict, search_keys)
1560
+
1561
+ return self.__mk_sampled_data_tuple(X_sampled, y_sampled, enriched_X, eval_set_sampled_dict, search_keys)
1562
+
1563
+ def __mk_sampled_data_tuple(
1564
+ self,
1565
+ X_sampled: pd.DataFrame,
1566
+ y_sampled: pd.Series,
1567
+ enriched_X: pd.DataFrame,
1568
+ eval_set_sampled_dict: Dict,
1569
+ search_keys: Dict,
1570
+ ):
1571
+ search_keys = {k: v for k, v in search_keys.items() if k in X_sampled.columns.to_list()}
1572
+ return FeaturesEnricher._SampledDataForMetrics(
1573
+ X_sampled, y_sampled, enriched_X, eval_set_sampled_dict, search_keys
1574
+ )
1575
+
1481
1576
  def get_search_id(self) -> Optional[str]:
1482
1577
  """Returns search_id of the fitted enricher. Not available before a successful fit."""
1483
1578
  return self._search_task.search_task_id if self._search_task else None
@@ -2065,9 +2160,6 @@ class FeaturesEnricher(TransformerMixin):
2065
2160
  if autofe_description is not None:
2066
2161
  display_html_dataframe(autofe_description, autofe_description, "*Description of AutoFE feature names")
2067
2162
 
2068
- if not self.warning_counter.has_warnings():
2069
- self.__display_support_link(bundle.get("all_ok_community_invite"))
2070
-
2071
2163
  if self._has_paid_features(exclude_features_sources):
2072
2164
  if calculate_metrics is not None and calculate_metrics:
2073
2165
  msg = bundle.get("metrics_with_paid_features")
@@ -2108,6 +2200,9 @@ class FeaturesEnricher(TransformerMixin):
2108
2200
 
2109
2201
  self.__show_report_button()
2110
2202
 
2203
+ if not self.warning_counter.has_warnings():
2204
+ self.__display_support_link(bundle.get("all_ok_community_invite"))
2205
+
2111
2206
  def __adjust_cv(self, df: pd.DataFrame, date_column: pd.Series, model_task_type: ModelTaskType):
2112
2207
  # Check Multivariate time series
2113
2208
  if (
@@ -2118,17 +2213,18 @@ class FeaturesEnricher(TransformerMixin):
2118
2213
  and is_blocked_time_series(df, date_column, list(self.fit_search_keys.keys()) + [TARGET])
2119
2214
  ):
2120
2215
  msg = bundle.get("multivariate_timeseries_detected")
2121
- self.__override_cv(CVType.blocked_time_series, msg)
2216
+ self.__override_cv(CVType.blocked_time_series, msg, print_warning=False)
2122
2217
  elif (
2123
- self.cv is None
2218
+ (self.cv is None or self.cv == CVType.k_fold)
2124
2219
  and model_task_type != ModelTaskType.REGRESSION
2125
2220
  and self._get_group_columns(self.fit_search_keys)
2126
2221
  ):
2127
2222
  msg = bundle.get("group_k_fold_in_classification")
2128
- self.__override_cv(CVType.group_k_fold, msg)
2223
+ self.__override_cv(CVType.group_k_fold, msg, print_warning=self.cv is not None)
2129
2224
 
2130
- def __override_cv(self, cv: CVType, msg: str):
2131
- print(msg)
2225
+ def __override_cv(self, cv: CVType, msg: str, print_warning: bool = True):
2226
+ if print_warning:
2227
+ print(msg)
2132
2228
  self.logger.warning(msg)
2133
2229
  self.cv = cv
2134
2230
  self.runtime_parameters.properties["cv_type"] = self.cv.name
@@ -2448,8 +2544,10 @@ class FeaturesEnricher(TransformerMixin):
2448
2544
  self, df: pd.DataFrame, meaning_types: Dict[str, FileColumnMeaningType], search_keys: Dict[str, SearchKey]
2449
2545
  ) -> pd.DataFrame:
2450
2546
  # save original order or rows
2451
- df = df.reset_index(drop=True).reset_index()
2452
- df = df.rename(columns={DEFAULT_INDEX: ORIGINAL_INDEX})
2547
+ original_index_name = df.index.name
2548
+ index_name = df.index.name or DEFAULT_INDEX
2549
+ df = df.reset_index().reset_index(drop=True)
2550
+ df = df.rename(columns={index_name: ORIGINAL_INDEX})
2453
2551
 
2454
2552
  # order by date and idempotent order by other keys
2455
2553
  if self.cv not in [CVType.time_series, CVType.blocked_time_series]:
@@ -2480,7 +2578,8 @@ class FeaturesEnricher(TransformerMixin):
2480
2578
 
2481
2579
  # return original order
2482
2580
  df = df.set_index(ORIGINAL_INDEX)
2483
- df = df.sort_index()
2581
+ df.index.name = original_index_name
2582
+ # df = df.sort_index()
2484
2583
 
2485
2584
  meaning_types[SYSTEM_RECORD_ID] = FileColumnMeaningType.SYSTEM_RECORD_ID
2486
2585
  return df
@@ -2541,6 +2640,9 @@ class FeaturesEnricher(TransformerMixin):
2541
2640
  self.logger.warning(f"X contain columns with same name as returned from backend: {dup_features}")
2542
2641
  raise ValidationError(bundle.get("returned_features_same_as_passed").format(dup_features))
2543
2642
 
2643
+ # index overrites from result_features
2644
+ original_index_name = df_with_original_index.index.name
2645
+ df_with_original_index = df_with_original_index.reset_index()
2544
2646
  result_features = pd.merge(
2545
2647
  df_with_original_index,
2546
2648
  result_features,
@@ -2548,6 +2650,8 @@ class FeaturesEnricher(TransformerMixin):
2548
2650
  right_on=SYSTEM_RECORD_ID,
2549
2651
  how="left" if is_transform else "inner",
2550
2652
  )
2653
+ result_features = result_features.set_index(original_index_name or DEFAULT_INDEX)
2654
+ result_features.index.name = original_index_name
2551
2655
 
2552
2656
  if rows_to_drop is not None:
2553
2657
  print(f"Before dropping target outliers size: {len(result_features)}")
@@ -2986,6 +3090,7 @@ class FeaturesEnricher(TransformerMixin):
2986
3090
  autofe_descriptions_df=self.get_autofe_features_description(),
2987
3091
  search_id=self._search_task.search_task_id,
2988
3092
  email=get_rest_client(self.endpoint, self.api_key).get_current_email(),
3093
+ search_keys=[str(sk) for sk in self.search_keys.values()],
2989
3094
  )
2990
3095
  except Exception:
2991
3096
  pass
@@ -3109,19 +3214,15 @@ class FeaturesEnricher(TransformerMixin):
3109
3214
  def __display_support_link(self, link_text: Optional[str] = None):
3110
3215
  support_link = bundle.get("support_link")
3111
3216
  link_text = link_text or bundle.get("support_text")
3112
- # badge = bundle.get("slack_community_bage")
3113
- # alt = bundle.get("slack_community_alt")
3114
3217
  try:
3115
3218
  from IPython.display import HTML, display
3116
3219
 
3117
3220
  _ = get_ipython() # type: ignore
3118
3221
  self.logger.warning(link_text)
3119
- print(link_text)
3120
3222
  display(
3121
3223
  HTML(
3122
- f"""<a href='{support_link}' target='_blank' rel='noopener noreferrer'>
3123
- Support</a>"""
3124
- # <img alt='{alt}' src='{badge}'></a>
3224
+ f"""{link_text} <a href='{support_link}' target='_blank' rel='noopener noreferrer'>
3225
+ here</a>"""
3125
3226
  )
3126
3227
  )
3127
3228
  except (ImportError, NameError):
@@ -17,7 +17,7 @@ transform_usage_warning=You are trying to launch enrichment for {} rows, which w
17
17
  support_link=https://upgini.com/support
18
18
  # slack_community_link=https://4mlg.short.gy/join-upgini-community
19
19
  # slack_community_text=\nWARNING: Looks like you've run into an error. For help request write us in the Upgini community
20
- support_text=\nWARNING: Looks like you've run into an error. For help request write us in support page:
20
+ support_text=\nWARNING: Looks like you've run into an error. For help request write us in support
21
21
  slack_community_bage=https://img.shields.io/badge/slack-@upgini-orange.svg?logo=slack
22
22
  slack_community_alt=Upgini Slack community
23
23
  version_warning=\nWARNING: Unsupported library version detected {},\nplease update with “%pip install -U upgini” to the latest {} and restart Jupyter kernel
@@ -110,6 +110,7 @@ y_is_empty=y is empty
110
110
  x_contains_reserved_column_name=Column name {} is reserved. Please rename column and try again
111
111
  missing_generate_feature=\nWARNING: Feature {} specified in `generate_features` is not present in input columns: {}
112
112
  # eval set validation
113
+ unsupported_type_eval_set=Unsupported type of eval_set: {}. It should be tuple of two elements: X and y
113
114
  eval_set_invalid_tuple_size=eval_set contains a tuple of size {}. It should contain only pairs of X and y
114
115
  unsupported_x_type_eval_set=Unsupported type of X in eval_set: {}. Use pandas.DataFrame, pandas.Series or numpy.ndarray or list.
115
116
  eval_x_and_x_diff_shape=The column set in eval_set are differ from the column set in X
@@ -193,7 +194,7 @@ phone_detected=Phone numbers detected in column `{}`. It can be used only with a
193
194
  phone_detected_not_registered=\nWARNING: Phone numbers detected in column `{}`. It can be used only with api_key from profile.upgini.com\nSee docs to turn off the automatic detection: https://github.com/upgini/upgini/blob/main/README.md#turn-off-autodetection-for-search-key-columns
194
195
  target_type_detected=Detected task type: {}\n
195
196
  # all_ok_community_invite=Chat with us in Slack community:
196
- all_ok_community_invite=Contact Upgini support:
197
+ all_ok_community_invite=Support request
197
198
  too_small_for_metrics=Your train dataset contains less than 500 rows. For such dataset Upgini will not calculate accuracy metrics. Please increase the number of rows in the training dataset to calculate accuracy metrics
198
199
  imbalance_multiclass=Class {0} is on 25% quantile of classes distribution ({1} records in train dataset). \nDownsample classes with records more than {1}.
199
200
  loss_selection_info=Using loss `{}` for feature selection
@@ -5,7 +5,7 @@ import urllib.parse
5
5
  import uuid
6
6
  from datetime import datetime, timezone
7
7
  from io import BytesIO
8
- from typing import Callable, Optional
8
+ from typing import Callable, List, Optional
9
9
 
10
10
  import pandas as pd
11
11
  from xhtml2pdf import pisa
@@ -133,6 +133,7 @@ def make_html_report(
133
133
  autofe_descriptions_df: Optional[pd.DataFrame],
134
134
  search_id: str,
135
135
  email: Optional[str] = None,
136
+ search_keys: Optional[List[str]] = None,
136
137
  ):
137
138
  # relevant_features_df = relevant_features_df.copy()
138
139
  # relevant_features_df["Feature name"] = relevant_features_df["Feature name"].apply(
@@ -236,6 +237,11 @@ def make_html_report(
236
237
  <p>This report was generated automatically by Upgini.</p>
237
238
  <p>The report shows a listing of relevant features for your
238
239
  ML task and accuracy metrics after enrichment.</p>
240
+ {
241
+ f"The following primary keys was used for data search: {search_keys}"
242
+ if search_keys is not None
243
+ else ""
244
+ }
239
245
  {"<h3>All relevant features. Accuracy after enrichment</h3>" + make_table(metrics_df)
240
246
  if metrics_df is not None
241
247
  else ""
@@ -244,7 +250,7 @@ def make_html_report(
244
250
  {make_table(relevant_datasources_df)}
245
251
  <h3>All relevant features. Listing</h3>
246
252
  {make_table(relevant_features_df, wrap_long_string=25)}
247
- {"<h3>Description of AutoFE feature names</h3>" + make_table(autofe_descriptions_df)
253
+ {"<h3>Description of AutoFE feature names</h3>" + make_table(autofe_descriptions_df, wrap_long_string=25)
248
254
  if autofe_descriptions_df is not None
249
255
  else ""
250
256
  }
@@ -261,12 +267,13 @@ def prepare_and_show_report(
261
267
  autofe_descriptions_df: Optional[pd.DataFrame],
262
268
  search_id: str,
263
269
  email: Optional[str],
270
+ search_keys: Optional[List[str]] = None,
264
271
  ):
265
272
  if not ipython_available():
266
273
  return
267
274
 
268
275
  report = make_html_report(
269
- relevant_features_df, relevant_datasources_df, metrics_df, autofe_descriptions_df, search_id, email
276
+ relevant_features_df, relevant_datasources_df, metrics_df, autofe_descriptions_df, search_id, email, search_keys
270
277
  )
271
278
 
272
279
  if len(relevant_features_df) > 0:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: upgini
3
- Version: 1.1.223
3
+ Version: 1.1.224
4
4
  Summary: Intelligent data search & enrichment for Machine Learning
5
5
  Home-page: https://upgini.com/
6
6
  Author: Upgini Developers
@@ -9,6 +9,7 @@ License: BSD 3-Clause License
9
9
  Project-URL: Bug Reports, https://github.com/upgini/upgini/issues
10
10
  Project-URL: Source, https://github.com/upgini/upgini
11
11
  Keywords: data science,machine learning,data mining,automl,data search
12
+ Platform: UNKNOWN
12
13
  Classifier: Development Status :: 5 - Production/Stable
13
14
  Classifier: Intended Audience :: Customer Service
14
15
  Classifier: Intended Audience :: Developers
@@ -26,20 +27,19 @@ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
26
27
  Classifier: Topic :: Scientific/Engineering :: Information Analysis
27
28
  Requires-Python: >=3.7,<3.11
28
29
  Description-Content-Type: text/markdown
29
- License-File: LICENSE
30
- Requires-Dist: python-dateutil (>=2.8.0)
31
- Requires-Dist: requests (>=2.8.0)
32
- Requires-Dist: pandas (<2.0.0,>=1.1.0)
33
- Requires-Dist: numpy (>=1.19.0)
34
- Requires-Dist: scikit-learn (>=1.0.1)
35
- Requires-Dist: pydantic (<2.0.0,>=1.8.2)
36
- Requires-Dist: fastparquet (>=0.8.1)
37
- Requires-Dist: python-json-logger (>=2.0.2)
38
- Requires-Dist: catboost (>=1.0.3)
39
- Requires-Dist: lightgbm (>=3.3.2)
40
- Requires-Dist: pyjwt (>=2.8.0)
41
- Requires-Dist: xhtml2pdf (==0.2.11)
42
- Requires-Dist: ipywidgets (>=8.1.0)
30
+ Requires-Dist: python-dateutil >=2.8.0
31
+ Requires-Dist: requests >=2.8.0
32
+ Requires-Dist: pandas <2.0.0,>=1.1.0
33
+ Requires-Dist: numpy >=1.19.0
34
+ Requires-Dist: scikit-learn >=1.0.1
35
+ Requires-Dist: pydantic <2.0.0,>=1.8.2
36
+ Requires-Dist: fastparquet >=0.8.1
37
+ Requires-Dist: python-json-logger >=2.0.2
38
+ Requires-Dist: catboost >=1.0.3
39
+ Requires-Dist: lightgbm >=3.3.2
40
+ Requires-Dist: pyjwt >=2.8.0
41
+ Requires-Dist: xhtml2pdf ==0.2.11
42
+ Requires-Dist: ipywidgets >=8.1.0
43
43
 
44
44
 
45
45
  <!-- <h2 align="center"> <a href="https://upgini.com/">Upgini</a> : low-code feature search and enrichment library for machine learning </h2> -->
@@ -151,7 +151,7 @@ Requires-Dist: ipywidgets (>=8.1.0)
151
151
  * The goal is to predict salary for data science job postning based on information about employer and job description.
152
152
  * Following this guide, you'll learn how to **search & auto generate new relevant features with Upgini library**
153
153
  * The evaluation metric is [Mean Absolute Error (MAE)](https://en.wikipedia.org/wiki/Mean_absolute_error).
154
-
154
+
155
155
  Run [Feature search & generation notebook](https://github.com/upgini/upgini/blob/main/notebooks/Upgini_Features_search%26generation.ipynb) inside your browser:
156
156
 
157
157
  [![Open example in Google Colab](https://img.shields.io/badge/run_example_in-colab-blue?style=for-the-badge&logo=googlecolab)](https://colab.research.google.com/github/upgini/upgini/blob/main/notebooks/Upgini_Features_search%26generation.ipynb)
@@ -842,3 +842,5 @@ Some convenient ways to start contributing are:
842
842
 
843
843
  <sup>😔 Found mistype or a bug in code snippet? Our bad! <a href="https://github.com/upgini/upgini/issues/new?assignees=&title=readme%2Fbug">
844
844
  Please report it here.</a></sup>
845
+
846
+
@@ -1,9 +1,8 @@
1
1
  upgini/__init__.py,sha256=asENHgEVHQBIkV-e_0IhE_ZWqkCG6398U3ZLrNzAH6k,407
2
2
  upgini/ads.py,sha256=mre6xn44wcC_fg63iLT_kTh4mViZqR9AKRJZAtpQz8Y,2592
3
- upgini/dataset.py,sha256=n6WZ9GkUsf0Q-PJ4Dq2ORZGnKrqY2ONNOuufflZ9hSk,49650
3
+ upgini/dataset.py,sha256=7z9zbVvd1_MiufmoZlCwEHwQ25Q2DX_0g9PFcSMlqMY,49764
4
4
  upgini/errors.py,sha256=BqpvfhW2jJW5fa5KXj0alhXatGl-WK4xTl309-QNLp8,959
5
- upgini/features_enricher.py,sha256=xOS85qypqCjEHvkXMYihQFX1uEYzwOHDum-3It_TMOg,152273
6
- upgini/fingerprint.js,sha256=VygVIQlN1v4NGZfjHqtRogOw8zjTnnMNJg_f7M5iGQU,33442
5
+ upgini/features_enricher.py,sha256=a78eCA6uS1kPtSLQQB3wQFBIiAPn4b0i3AjvlUyBm38,155965
7
6
  upgini/http.py,sha256=KIAwmBwo9dQxTVEEHKE-BOGcOcJ6o5Q5f6R2kvX-aAc,40808
8
7
  upgini/metadata.py,sha256=LUvOc3SGkvXwBPpGkCnacywpR6lAmZ2mGJqcD7LAsXI,7235
9
8
  upgini/metrics.py,sha256=YeYHJtEIs8OG-EzidG-nbSYB919pjZ4MMbdcZ_jfV2s,23639
@@ -20,7 +19,7 @@ upgini/normalizer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU
20
19
  upgini/normalizer/phone_normalizer.py,sha256=VIgLXuDuzzjPEXiy_LyDVLZKGaS7-le6Fh6T4D-TQDU,9930
21
20
  upgini/resource_bundle/__init__.py,sha256=M7GtS7KPQw9pinz8P2aQWXpSkD2YFwUPVGk1w92Pn84,7888
22
21
  upgini/resource_bundle/exceptions.py,sha256=KT-OnqA2J4OTfLjhbEl3KFZM2ci7EOPjqJuY_rXp3vs,622
23
- upgini/resource_bundle/strings.properties,sha256=IJfD_iAUYzV6hxjEb_O-p6Ww27QfUv0O6OYmos4LRlw,24264
22
+ upgini/resource_bundle/strings.properties,sha256=NPEfvUleQm09klmPo8sQMF_B_brs3nY2mt8GENsLICw,24355
24
23
  upgini/sampler/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
25
24
  upgini/sampler/base.py,sha256=X2PVsfZ3Rl7twpFDh5UWyxqY2K_jcMGxZ2NcHLwFRj4,6489
26
25
  upgini/sampler/random_under_sampler.py,sha256=whX_f_TtalHH8Seyn_7n3sX_TSiDHeYfALmme9saqDg,4082
@@ -32,7 +31,7 @@ upgini/utils/country_utils.py,sha256=9BXSXoGm3nVoOZE_bRENY-KMkwMUFvAF3Au0zxUNA1o
32
31
  upgini/utils/custom_loss_utils.py,sha256=DBslpjWGPt7xTeypt78baR59012SYphbPsO_YLKdilo,3972
33
32
  upgini/utils/cv_utils.py,sha256=NTVd7itVWiyrEiM2LPXHGXIzMCncdGR4SRxrOu57Euc,2492
34
33
  upgini/utils/datetime_utils.py,sha256=P56e7gcgAogJYfs2Blzk1uypxb9yrFzNaeJpMCRm6Zc,7716
35
- upgini/utils/display_utils.py,sha256=M9bt74MAEQCv11KPMAdUzyKT-9GAVDAhURPsTFn5YQ0,10365
34
+ upgini/utils/display_utils.py,sha256=mGqs2XzD_4bmeRgmrGXWjxt_ZQigc2leaXBcRge9DkY,10676
36
35
  upgini/utils/email_utils.py,sha256=MhCLUAWqbp81xRyKizauNhVx6t_MFeJQRQ8pFM7EpFo,3480
37
36
  upgini/utils/fallback_progress_bar.py,sha256=f-VzVbiO6oU9WoKzEgoegYotixdiKanGlvdQCOGC-NY,1128
38
37
  upgini/utils/features_validator.py,sha256=iP8muF3PUf_aP9m7O3i3LPMuJPTNbw8rCAWqgvDt_h8,2369
@@ -45,8 +44,8 @@ upgini/utils/sklearn_ext.py,sha256=IMx2La70AXAggApVpT7sMEjWqVWon5AMZt4MARDsIMQ,4
45
44
  upgini/utils/target_utils.py,sha256=cu52icjhDIPpEStHYMXrD2hIl9gzvfnxZr0Ra5osV0k,1616
46
45
  upgini/utils/track_info.py,sha256=DVNVZmXUb4f25DSPEuUNEFx49hNEBfmuY9iSW5jkMnI,5708
47
46
  upgini/utils/warning_counter.py,sha256=vnmdFo5-7GBkU2bK9h_uC0K0Y_wtfcYstxOdeRfacO0,228
48
- upgini-1.1.223.dist-info/LICENSE,sha256=5RRzgvdJUu3BUDfv4bzVU6FqKgwHlIay63pPCSmSgzw,1514
49
- upgini-1.1.223.dist-info/METADATA,sha256=srZeu4yr3Cr_y3OMbaOp17PEOA2YnZV9R3Dbd9GW1ak,48306
50
- upgini-1.1.223.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
51
- upgini-1.1.223.dist-info/top_level.txt,sha256=OFhTGiDIWKl5gFI49qvWq1R9IKflPaE2PekcbDXDtx4,7
52
- upgini-1.1.223.dist-info/RECORD,,
47
+ upgini-1.1.224.dist-info/LICENSE,sha256=5RRzgvdJUu3BUDfv4bzVU6FqKgwHlIay63pPCSmSgzw,1514
48
+ upgini-1.1.224.dist-info/METADATA,sha256=FB0guMPa2N-aDRYBvSTaXjpFii-1n_z6he1jNX6AeYE,48277
49
+ upgini-1.1.224.dist-info/WHEEL,sha256=Xo9-1PvkuimrydujYJAjF7pCkriuXBpUPEjma1nZyJ0,92
50
+ upgini-1.1.224.dist-info/top_level.txt,sha256=OFhTGiDIWKl5gFI49qvWq1R9IKflPaE2PekcbDXDtx4,7
51
+ upgini-1.1.224.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.37.1)
2
+ Generator: bdist_wheel (0.41.3)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
upgini/fingerprint.js DELETED
@@ -1,8 +0,0 @@
1
- /**
2
- * FingerprintJS v3.4.2 - Copyright (c) FingerprintJS, Inc, 2023 (https://fingerprint.com)
3
- * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.
4
- *
5
- * This software contains code from open-source projects:
6
- * MurmurHash3 by Karan Lyons (https://github.com/karanlyons/murmurHash3.js)
7
- */
8
- var e=function(){return e=Object.assign||function(e){for(var n,t=1,r=arguments.length;t<r;t++)for(var o in n=arguments[t])Object.prototype.hasOwnProperty.call(n,o)&&(e[o]=n[o]);return e},e.apply(this,arguments)};function n(e,n,t,r){return new(t||(t=Promise))((function(o,a){function i(e){try{u(r.next(e))}catch(n){a(n)}}function c(e){try{u(r.throw(e))}catch(n){a(n)}}function u(e){var n;e.done?o(e.value):(n=e.value,n instanceof t?n:new t((function(e){e(n)}))).then(i,c)}u((r=r.apply(e,n||[])).next())}))}function t(e,n){var t,r,o,a,i={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return a={next:c(0),throw:c(1),return:c(2)},"function"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function c(c){return function(u){return function(c){if(t)throw new TypeError("Generator is already executing.");for(;a&&(a=0,c[0]&&(i=0)),i;)try{if(t=1,r&&(o=2&c[0]?r.return:c[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,c[1])).done)return o;switch(r=0,o&&(c=[2&c[0],o.value]),c[0]){case 0:case 1:o=c;break;case 4:return i.label++,{value:c[1],done:!1};case 5:i.label++,r=c[1],c=[0];continue;case 7:c=i.ops.pop(),i.trys.pop();continue;default:if(!(o=i.trys,(o=o.length>0&&o[o.length-1])||6!==c[0]&&2!==c[0])){i=0;continue}if(3===c[0]&&(!o||c[1]>o[0]&&c[1]<o[3])){i.label=c[1];break}if(6===c[0]&&i.label<o[1]){i.label=o[1],o=c;break}if(o&&i.label<o[2]){i.label=o[2],i.ops.push(c);break}o[2]&&i.ops.pop(),i.trys.pop();continue}c=n.call(e,i)}catch(u){c=[6,u],r=0}finally{t=o=0}if(5&c[0])throw c[1];return{value:c[0]?c[1]:void 0,done:!0}}([c,u])}}}function r(e,n,t){if(t||2===arguments.length)for(var r,o=0,a=n.length;o<a;o++)!r&&o in n||(r||(r=Array.prototype.slice.call(n,0,o)),r[o]=n[o]);return e.concat(r||Array.prototype.slice.call(n))}function o(e,n){return new Promise((function(t){return setTimeout(t,e,n)}))}function a(e){return!!e&&"function"==typeof e.then}function i(e,n){try{var t=e();a(t)?t.then((function(e){return n(!0,e)}),(function(e){return n(!1,e)})):n(!0,t)}catch(r){n(!1,r)}}function c(e,r,a){return void 0===a&&(a=16),n(this,void 0,void 0,(function(){var n,i,c,u;return t(this,(function(t){switch(t.label){case 0:n=Array(e.length),i=Date.now(),c=0,t.label=1;case 1:return c<e.length?(n[c]=r(e[c],c),(u=Date.now())>=i+a?(i=u,[4,o(0)]):[3,3]):[3,4];case 2:t.sent(),t.label=3;case 3:return++c,[3,1];case 4:return[2,n]}}))}))}function u(e){e.then(void 0,(function(){}))}function l(e,n){e=[e[0]>>>16,65535&e[0],e[1]>>>16,65535&e[1]],n=[n[0]>>>16,65535&n[0],n[1]>>>16,65535&n[1]];var t=[0,0,0,0];return t[3]+=e[3]+n[3],t[2]+=t[3]>>>16,t[3]&=65535,t[2]+=e[2]+n[2],t[1]+=t[2]>>>16,t[2]&=65535,t[1]+=e[1]+n[1],t[0]+=t[1]>>>16,t[1]&=65535,t[0]+=e[0]+n[0],t[0]&=65535,[t[0]<<16|t[1],t[2]<<16|t[3]]}function s(e,n){e=[e[0]>>>16,65535&e[0],e[1]>>>16,65535&e[1]],n=[n[0]>>>16,65535&n[0],n[1]>>>16,65535&n[1]];var t=[0,0,0,0];return t[3]+=e[3]*n[3],t[2]+=t[3]>>>16,t[3]&=65535,t[2]+=e[2]*n[3],t[1]+=t[2]>>>16,t[2]&=65535,t[2]+=e[3]*n[2],t[1]+=t[2]>>>16,t[2]&=65535,t[1]+=e[1]*n[3],t[0]+=t[1]>>>16,t[1]&=65535,t[1]+=e[2]*n[2],t[0]+=t[1]>>>16,t[1]&=65535,t[1]+=e[3]*n[1],t[0]+=t[1]>>>16,t[1]&=65535,t[0]+=e[0]*n[3]+e[1]*n[2]+e[2]*n[1]+e[3]*n[0],t[0]&=65535,[t[0]<<16|t[1],t[2]<<16|t[3]]}function d(e,n){return 32===(n%=64)?[e[1],e[0]]:n<32?[e[0]<<n|e[1]>>>32-n,e[1]<<n|e[0]>>>32-n]:(n-=32,[e[1]<<n|e[0]>>>32-n,e[0]<<n|e[1]>>>32-n])}function m(e,n){return 0===(n%=64)?e:n<32?[e[0]<<n|e[1]>>>32-n,e[1]<<n]:[e[1]<<n-32,0]}function f(e,n){return[e[0]^n[0],e[1]^n[1]]}function v(e){return e=f(e,[0,e[0]>>>1]),e=f(e=s(e,[4283543511,3981806797]),[0,e[0]>>>1]),e=f(e=s(e,[3301882366,444984403]),[0,e[0]>>>1])}function h(e,n){n=n||0;var t,r=(e=e||"").length%16,o=e.length-r,a=[0,n],i=[0,n],c=[0,0],u=[0,0],h=[2277735313,289559509],p=[1291169091,658871167];for(t=0;t<o;t+=16)c=[255&e.charCodeAt(t+4)|(255&e.charCodeAt(t+5))<<8|(255&e.charCodeAt(t+6))<<16|(255&e.charCodeAt(t+7))<<24,255&e.charCodeAt(t)|(255&e.charCodeAt(t+1))<<8|(255&e.charCodeAt(t+2))<<16|(255&e.charCodeAt(t+3))<<24],u=[255&e.charCodeAt(t+12)|(255&e.charCodeAt(t+13))<<8|(255&e.charCodeAt(t+14))<<16|(255&e.charCodeAt(t+15))<<24,255&e.charCodeAt(t+8)|(255&e.charCodeAt(t+9))<<8|(255&e.charCodeAt(t+10))<<16|(255&e.charCodeAt(t+11))<<24],c=d(c=s(c,h),31),a=l(a=d(a=f(a,c=s(c,p)),27),i),a=l(s(a,[0,5]),[0,1390208809]),u=d(u=s(u,p),33),i=l(i=d(i=f(i,u=s(u,h)),31),a),i=l(s(i,[0,5]),[0,944331445]);switch(c=[0,0],u=[0,0],r){case 15:u=f(u,m([0,e.charCodeAt(t+14)],48));case 14:u=f(u,m([0,e.charCodeAt(t+13)],40));case 13:u=f(u,m([0,e.charCodeAt(t+12)],32));case 12:u=f(u,m([0,e.charCodeAt(t+11)],24));case 11:u=f(u,m([0,e.charCodeAt(t+10)],16));case 10:u=f(u,m([0,e.charCodeAt(t+9)],8));case 9:u=s(u=f(u,[0,e.charCodeAt(t+8)]),p),i=f(i,u=s(u=d(u,33),h));case 8:c=f(c,m([0,e.charCodeAt(t+7)],56));case 7:c=f(c,m([0,e.charCodeAt(t+6)],48));case 6:c=f(c,m([0,e.charCodeAt(t+5)],40));case 5:c=f(c,m([0,e.charCodeAt(t+4)],32));case 4:c=f(c,m([0,e.charCodeAt(t+3)],24));case 3:c=f(c,m([0,e.charCodeAt(t+2)],16));case 2:c=f(c,m([0,e.charCodeAt(t+1)],8));case 1:c=s(c=f(c,[0,e.charCodeAt(t)]),h),a=f(a,c=s(c=d(c,31),p))}return a=l(a=f(a,[0,e.length]),i=f(i,[0,e.length])),i=l(i,a),a=l(a=v(a),i=v(i)),i=l(i,a),("00000000"+(a[0]>>>0).toString(16)).slice(-8)+("00000000"+(a[1]>>>0).toString(16)).slice(-8)+("00000000"+(i[0]>>>0).toString(16)).slice(-8)+("00000000"+(i[1]>>>0).toString(16)).slice(-8)}function p(e){return parseInt(e)}function b(e){return parseFloat(e)}function y(e,n){return"number"==typeof e&&isNaN(e)?n:e}function g(e){return e.reduce((function(e,n){return e+(n?1:0)}),0)}function w(e,n){if(void 0===n&&(n=1),Math.abs(n)>=1)return Math.round(e/n)*n;var t=1/n;return Math.round(e*t)/t}function L(e){return e&&"object"==typeof e&&"message"in e?e:{message:e}}function k(e){return"function"!=typeof e}function V(e,r,o){var a=Object.keys(e).filter((function(e){return!function(e,n){for(var t=0,r=e.length;t<r;++t)if(e[t]===n)return!0;return!1}(o,e)})),l=c(a,(function(n){return function(e,n){var t=new Promise((function(t){var r=Date.now();i(e.bind(null,n),(function(){for(var e=[],n=0;n<arguments.length;n++)e[n]=arguments[n];var o=Date.now()-r;if(!e[0])return t((function(){return{error:L(e[1]),duration:o}}));var a=e[1];if(k(a))return t((function(){return{value:a,duration:o}}));t((function(){return new Promise((function(e){var n=Date.now();i(a,(function(){for(var t=[],r=0;r<arguments.length;r++)t[r]=arguments[r];var a=o+Date.now()-n;if(!t[0])return e({error:L(t[1]),duration:a});e({value:t[1],duration:a})}))}))}))}))}));return u(t),function(){return t.then((function(e){return e()}))}}(e[n],r)}));return u(l),function(){return n(this,void 0,void 0,(function(){var e,n,r,o;return t(this,(function(t){switch(t.label){case 0:return[4,l];case 1:return[4,c(t.sent(),(function(e){var n=e();return u(n),n}))];case 2:return e=t.sent(),[4,Promise.all(e)];case 3:for(n=t.sent(),r={},o=0;o<a.length;++o)r[a[o]]=n[o];return[2,r]}}))}))}}function Z(e,n){var t=function(e){return k(e)?n(e):function(){var t=e();return a(t)?t.then(n):n(t)}};return function(n){var r=e(n);return a(r)?r.then(t):t(r)}}function W(){var e=window,n=navigator;return g(["MSCSSMatrix"in e,"msSetImmediate"in e,"msIndexedDB"in e,"msMaxTouchPoints"in n,"msPointerEnabled"in n])>=4}function C(){var e=window,n=navigator;return g(["msWriteProfilerMark"in e,"MSStream"in e,"msLaunchUri"in n,"msSaveBlob"in n])>=3&&!W()}function S(){var e=window,n=navigator;return g(["webkitPersistentStorage"in n,"webkitTemporaryStorage"in n,0===n.vendor.indexOf("Google"),"webkitResolveLocalFileSystemURL"in e,"BatteryManager"in e,"webkitMediaStream"in e,"webkitSpeechGrammar"in e])>=5}function x(){var e=window,n=navigator;return g(["ApplePayError"in e,"CSSPrimitiveValue"in e,"Counter"in e,0===n.vendor.indexOf("Apple"),"getStorageUpdates"in n,"WebKitMediaKeys"in e])>=4}function F(){var e=window;return g(["safari"in e,!("DeviceMotionEvent"in e),!("ongestureend"in e),!("standalone"in navigator)])>=3}function Y(){var e,n,t=window;return g(["buildID"in navigator,"MozAppearance"in(null!==(n=null===(e=document.documentElement)||void 0===e?void 0:e.style)&&void 0!==n?n:{}),"onmozfullscreenchange"in t,"mozInnerScreenX"in t,"CSSMozDocumentRule"in t,"CanvasCaptureMediaStream"in t])>=4}function M(){var e=document;return e.fullscreenElement||e.msFullscreenElement||e.mozFullScreenElement||e.webkitFullscreenElement||null}function G(){var e=S(),n=Y();if(!e&&!n)return!1;var t=window;return g(["onorientationchange"in t,"orientation"in t,e&&!("SharedWorker"in t),n&&/android/i.test(navigator.appVersion)])>=2}function R(e){var n=new Error(e);return n.name=e,n}function X(e,r,a){var i,c,u;return void 0===a&&(a=50),n(this,void 0,void 0,(function(){var n,l;return t(this,(function(t){switch(t.label){case 0:n=document,t.label=1;case 1:return n.body?[3,3]:[4,o(a)];case 2:return t.sent(),[3,1];case 3:l=n.createElement("iframe"),t.label=4;case 4:return t.trys.push([4,,10,11]),[4,new Promise((function(e,t){var o=!1,a=function(){o=!0,e()};l.onload=a,l.onerror=function(e){o=!0,t(e)};var i=l.style;i.setProperty("display","block","important"),i.position="absolute",i.top="0",i.left="0",i.visibility="hidden",r&&"srcdoc"in l?l.srcdoc=r:l.src="about:blank",n.body.appendChild(l);var c=function(){var e,n;o||("complete"===(null===(n=null===(e=l.contentWindow)||void 0===e?void 0:e.document)||void 0===n?void 0:n.readyState)?a():setTimeout(c,10))};c()}))];case 5:t.sent(),t.label=6;case 6:return(null===(c=null===(i=l.contentWindow)||void 0===i?void 0:i.document)||void 0===c?void 0:c.body)?[3,8]:[4,o(a)];case 7:return t.sent(),[3,6];case 8:return[4,e(l,l.contentWindow)];case 9:return[2,t.sent()];case 10:return null===(u=l.parentNode)||void 0===u||u.removeChild(l),[7];case 11:return[2]}}))}))}function A(e){for(var n=function(e){for(var n,t,r="Unexpected syntax '".concat(e,"'"),o=/^\s*([a-z-]*)(.*)$/i.exec(e),a=o[1]||void 0,i={},c=/([.:#][\w-]+|\[.+?\])/gi,u=function(e,n){i[e]=i[e]||[],i[e].push(n)};;){var l=c.exec(o[2]);if(!l)break;var s=l[0];switch(s[0]){case".":u("class",s.slice(1));break;case"#":u("id",s.slice(1));break;case"[":var d=/^\[([\w-]+)([~|^$*]?=("(.*?)"|([\w-]+)))?(\s+[is])?\]$/.exec(s);if(!d)throw new Error(r);u(d[1],null!==(t=null!==(n=d[4])&&void 0!==n?n:d[5])&&void 0!==t?t:"");break;default:throw new Error(r)}}return[a,i]}(e),t=n[0],r=n[1],o=document.createElement(null!=t?t:"div"),a=0,i=Object.keys(r);a<i.length;a++){var c=i[a],u=r[c].join(" ");"style"===c?j(o.style,u):o.setAttribute(c,u)}return o}function j(e,n){for(var t=0,r=n.split(";");t<r.length;t++){var o=r[t],a=/^\s*([\w-]+)\s*:\s*(.+?)(\s*!([\w-]+))?\s*$/.exec(o);if(a){var i=a[1],c=a[2],u=a[4];e.setProperty(i,c,u||"")}}}var I=["monospace","sans-serif","serif"],J=["sans-serif-thin","ARNO PRO","Agency FB","Arabic Typesetting","Arial Unicode MS","AvantGarde Bk BT","BankGothic Md BT","Batang","Bitstream Vera Sans Mono","Calibri","Century","Century Gothic","Clarendon","EUROSTILE","Franklin Gothic","Futura Bk BT","Futura Md BT","GOTHAM","Gill Sans","HELV","Haettenschweiler","Helvetica Neue","Humanst521 BT","Leelawadee","Letter Gothic","Levenim MT","Lucida Bright","Lucida Sans","Menlo","MS Mincho","MS Outlook","MS Reference Specialty","MS UI Gothic","MT Extra","MYRIAD PRO","Marlett","Meiryo UI","Microsoft Uighur","Minion Pro","Monotype Corsiva","PMingLiU","Pristina","SCRIPTINA","Segoe UI Light","Serifa","SimHei","Small Fonts","Staccato222 BT","TRAJAN PRO","Univers CE 55 Medium","Vrinda","ZWAdobeF"];function H(e){return e.toDataURL()}var P,N;function z(){var e=this;return function(){if(void 0===N){var e=function(){var n=D();E(n)?N=setTimeout(e,2500):(P=n,N=void 0)};e()}}(),function(){return n(e,void 0,void 0,(function(){var e;return t(this,(function(n){switch(n.label){case 0:return E(e=D())?P?[2,r([],P,!0)]:M()?[4,(t=document,(t.exitFullscreen||t.msExitFullscreen||t.mozCancelFullScreen||t.webkitExitFullscreen).call(t))]:[3,2]:[3,2];case 1:n.sent(),e=D(),n.label=2;case 2:return E(e)||(P=e),[2,e]}var t}))}))}}function D(){var e=screen;return[y(b(e.availTop),null),y(b(e.width)-b(e.availWidth)-y(b(e.availLeft),0),null),y(b(e.height)-b(e.availHeight)-y(b(e.availTop),0),null),y(b(e.availLeft),null)]}function E(e){for(var n=0;n<4;++n)if(e[n])return!1;return!0}function T(e){var r;return n(this,void 0,void 0,(function(){var n,a,i,c,u,l,s;return t(this,(function(t){switch(t.label){case 0:for(n=document,a=n.createElement("div"),i=new Array(e.length),c={},B(a),s=0;s<e.length;++s)"DIALOG"===(u=A(e[s])).tagName&&u.show(),B(l=n.createElement("div")),l.appendChild(u),a.appendChild(l),i[s]=u;t.label=1;case 1:return n.body?[3,3]:[4,o(50)];case 2:return t.sent(),[3,1];case 3:n.body.appendChild(a);try{for(s=0;s<e.length;++s)i[s].offsetParent||(c[e[s]]=!0)}finally{null===(r=a.parentNode)||void 0===r||r.removeChild(a)}return[2,c]}}))}))}function B(e){e.style.setProperty("display","block","important")}function _(e){return matchMedia("(inverted-colors: ".concat(e,")")).matches}function O(e){return matchMedia("(forced-colors: ".concat(e,")")).matches}function U(e){return matchMedia("(prefers-contrast: ".concat(e,")")).matches}function Q(e){return matchMedia("(prefers-reduced-motion: ".concat(e,")")).matches}function K(e){return matchMedia("(dynamic-range: ".concat(e,")")).matches}var q=Math,$=function(){return 0};var ee={default:[],apple:[{font:"-apple-system-body"}],serif:[{fontFamily:"serif"}],sans:[{fontFamily:"sans-serif"}],mono:[{fontFamily:"monospace"}],min:[{fontSize:"1px"}],system:[{fontFamily:"system-ui"}]};var ne={fonts:function(){return X((function(e,n){var t=n.document,r=t.body;r.style.fontSize="48px";var o=t.createElement("div"),a={},i={},c=function(e){var n=t.createElement("span"),r=n.style;return r.position="absolute",r.top="0",r.left="0",r.fontFamily=e,n.textContent="mmMwWLliI0O&1",o.appendChild(n),n},u=I.map(c),l=function(){for(var e={},n=function(n){e[n]=I.map((function(e){return function(e,n){return c("'".concat(e,"',").concat(n))}(n,e)}))},t=0,r=J;t<r.length;t++){n(r[t])}return e}();r.appendChild(o);for(var s=0;s<I.length;s++)a[I[s]]=u[s].offsetWidth,i[I[s]]=u[s].offsetHeight;return J.filter((function(e){return n=l[e],I.some((function(e,t){return n[t].offsetWidth!==a[e]||n[t].offsetHeight!==i[e]}));var n}))}))},domBlockers:function(e){var r=(void 0===e?{}:e).debug;return n(this,void 0,void 0,(function(){var e,n,o,a,i;return t(this,(function(t){switch(t.label){case 0:return x()||G()?(c=atob,e={abpIndo:["#Iklan-Melayang","#Kolom-Iklan-728","#SidebarIklan-wrapper",'[title="ALIENBOLA" i]',c("I0JveC1CYW5uZXItYWRz")],abpvn:[".quangcao","#mobileCatfish",c("LmNsb3NlLWFkcw=="),'[id^="bn_bottom_fixed_"]',"#pmadv"],adBlockFinland:[".mainostila",c("LnNwb25zb3JpdA=="),".ylamainos",c("YVtocmVmKj0iL2NsaWNrdGhyZ2guYXNwPyJd"),c("YVtocmVmXj0iaHR0cHM6Ly9hcHAucmVhZHBlYWsuY29tL2FkcyJd")],adBlockPersian:["#navbar_notice_50",".kadr",'TABLE[width="140px"]',"#divAgahi",c("YVtocmVmXj0iaHR0cDovL2cxLnYuZndtcm0ubmV0L2FkLyJd")],adBlockWarningRemoval:["#adblock-honeypot",".adblocker-root",".wp_adblock_detect",c("LmhlYWRlci1ibG9ja2VkLWFk"),c("I2FkX2Jsb2NrZXI=")],adGuardAnnoyances:[".hs-sosyal","#cookieconsentdiv",'div[class^="app_gdpr"]',".as-oil",'[data-cypress="soft-push-notification-modal"]'],adGuardBase:[".BetterJsPopOverlay",c("I2FkXzMwMFgyNTA="),c("I2Jhbm5lcmZsb2F0MjI="),c("I2NhbXBhaWduLWJhbm5lcg=="),c("I0FkLUNvbnRlbnQ=")],adGuardChinese:[c("LlppX2FkX2FfSA=="),c("YVtocmVmKj0iLmh0aGJldDM0LmNvbSJd"),"#widget-quan",c("YVtocmVmKj0iLzg0OTkyMDIwLnh5eiJd"),c("YVtocmVmKj0iLjE5NTZobC5jb20vIl0=")],adGuardFrench:["#pavePub",c("LmFkLWRlc2t0b3AtcmVjdGFuZ2xl"),".mobile_adhesion",".widgetadv",c("LmFkc19iYW4=")],adGuardGerman:['aside[data-portal-id="leaderboard"]'],adGuardJapanese:["#kauli_yad_1",c("YVtocmVmXj0iaHR0cDovL2FkMi50cmFmZmljZ2F0ZS5uZXQvIl0="),c("Ll9wb3BJbl9pbmZpbml0ZV9hZA=="),c("LmFkZ29vZ2xl"),c("Ll9faXNib29zdFJldHVybkFk")],adGuardMobile:[c("YW1wLWF1dG8tYWRz"),c("LmFtcF9hZA=="),'amp-embed[type="24smi"]',"#mgid_iframe1",c("I2FkX2ludmlld19hcmVh")],adGuardRussian:[c("YVtocmVmXj0iaHR0cHM6Ly9hZC5sZXRtZWFkcy5jb20vIl0="),c("LnJlY2xhbWE="),'div[id^="smi2adblock"]',c("ZGl2W2lkXj0iQWRGb3hfYmFubmVyXyJd"),"#psyduckpockeball"],adGuardSocial:[c("YVtocmVmXj0iLy93d3cuc3R1bWJsZXVwb24uY29tL3N1Ym1pdD91cmw9Il0="),c("YVtocmVmXj0iLy90ZWxlZ3JhbS5tZS9zaGFyZS91cmw/Il0="),".etsy-tweet","#inlineShare",".popup-social"],adGuardSpanishPortuguese:["#barraPublicidade","#Publicidade","#publiEspecial","#queTooltip",".cnt-publi"],adGuardTrackingProtection:["#qoo-counter",c("YVtocmVmXj0iaHR0cDovL2NsaWNrLmhvdGxvZy5ydS8iXQ=="),c("YVtocmVmXj0iaHR0cDovL2hpdGNvdW50ZXIucnUvdG9wL3N0YXQucGhwIl0="),c("YVtocmVmXj0iaHR0cDovL3RvcC5tYWlsLnJ1L2p1bXAiXQ=="),"#top100counter"],adGuardTurkish:["#backkapat",c("I3Jla2xhbWk="),c("YVtocmVmXj0iaHR0cDovL2Fkc2Vydi5vbnRlay5jb20udHIvIl0="),c("YVtocmVmXj0iaHR0cDovL2l6bGVuemkuY29tL2NhbXBhaWduLyJd"),c("YVtocmVmXj0iaHR0cDovL3d3dy5pbnN0YWxsYWRzLm5ldC8iXQ==")],bulgarian:[c("dGQjZnJlZW5ldF90YWJsZV9hZHM="),"#ea_intext_div",".lapni-pop-over","#xenium_hot_offers"],easyList:[".yb-floorad",c("LndpZGdldF9wb19hZHNfd2lkZ2V0"),c("LnRyYWZmaWNqdW5reS1hZA=="),".textad_headline",c("LnNwb25zb3JlZC10ZXh0LWxpbmtz")],easyListChina:[c("LmFwcGd1aWRlLXdyYXBbb25jbGljayo9ImJjZWJvcy5jb20iXQ=="),c("LmZyb250cGFnZUFkdk0="),"#taotaole","#aafoot.top_box",".cfa_popup"],easyListCookie:[".ezmob-footer",".cc-CookieWarning","[data-cookie-number]",c("LmF3LWNvb2tpZS1iYW5uZXI="),".sygnal24-gdpr-modal-wrap"],easyListCzechSlovak:["#onlajny-stickers",c("I3Jla2xhbW5pLWJveA=="),c("LnJla2xhbWEtbWVnYWJvYXJk"),".sklik",c("W2lkXj0ic2tsaWtSZWtsYW1hIl0=")],easyListDutch:[c("I2FkdmVydGVudGll"),c("I3ZpcEFkbWFya3RCYW5uZXJCbG9jaw=="),".adstekst",c("YVtocmVmXj0iaHR0cHM6Ly94bHR1YmUubmwvY2xpY2svIl0="),"#semilo-lrectangle"],easyListGermany:["#SSpotIMPopSlider",c("LnNwb25zb3JsaW5rZ3J1ZW4="),c("I3dlcmJ1bmdza3k="),c("I3Jla2xhbWUtcmVjaHRzLW1pdHRl"),c("YVtocmVmXj0iaHR0cHM6Ly9iZDc0Mi5jb20vIl0=")],easyListItaly:[c("LmJveF9hZHZfYW5udW5jaQ=="),".sb-box-pubbliredazionale",c("YVtocmVmXj0iaHR0cDovL2FmZmlsaWF6aW9uaWFkcy5zbmFpLml0LyJd"),c("YVtocmVmXj0iaHR0cHM6Ly9hZHNlcnZlci5odG1sLml0LyJd"),c("YVtocmVmXj0iaHR0cHM6Ly9hZmZpbGlhemlvbmlhZHMuc25haS5pdC8iXQ==")],easyListLithuania:[c("LnJla2xhbW9zX3RhcnBhcw=="),c("LnJla2xhbW9zX251b3JvZG9z"),c("aW1nW2FsdD0iUmVrbGFtaW5pcyBza3lkZWxpcyJd"),c("aW1nW2FsdD0iRGVkaWt1b3RpLmx0IHNlcnZlcmlhaSJd"),c("aW1nW2FsdD0iSG9zdGluZ2FzIFNlcnZlcmlhaS5sdCJd")],estonian:[c("QVtocmVmKj0iaHR0cDovL3BheTRyZXN1bHRzMjQuZXUiXQ==")],fanboyAnnoyances:["#ac-lre-player",".navigate-to-top","#subscribe_popup",".newsletter_holder","#back-top"],fanboyAntiFacebook:[".util-bar-module-firefly-visible"],fanboyEnhancedTrackers:[".open.pushModal","#issuem-leaky-paywall-articles-zero-remaining-nag","#sovrn_container",'div[class$="-hide"][zoompage-fontsize][style="display: block;"]',".BlockNag__Card"],fanboySocial:["#FollowUs","#meteored_share","#social_follow",".article-sharer",".community__social-desc"],frellwitSwedish:[c("YVtocmVmKj0iY2FzaW5vcHJvLnNlIl1bdGFyZ2V0PSJfYmxhbmsiXQ=="),c("YVtocmVmKj0iZG9rdG9yLXNlLm9uZWxpbmsubWUiXQ=="),"article.category-samarbete",c("ZGl2LmhvbGlkQWRz"),"ul.adsmodern"],greekAdBlock:[c("QVtocmVmKj0iYWRtYW4ub3RlbmV0LmdyL2NsaWNrPyJd"),c("QVtocmVmKj0iaHR0cDovL2F4aWFiYW5uZXJzLmV4b2R1cy5nci8iXQ=="),c("QVtocmVmKj0iaHR0cDovL2ludGVyYWN0aXZlLmZvcnRobmV0LmdyL2NsaWNrPyJd"),"DIV.agores300","TABLE.advright"],hungarian:["#cemp_doboz",".optimonk-iframe-container",c("LmFkX19tYWlu"),c("W2NsYXNzKj0iR29vZ2xlQWRzIl0="),"#hirdetesek_box"],iDontCareAboutCookies:['.alert-info[data-block-track*="CookieNotice"]',".ModuleTemplateCookieIndicator",".o--cookies--container","#cookies-policy-sticky","#stickyCookieBar"],icelandicAbp:[c("QVtocmVmXj0iL2ZyYW1ld29yay9yZXNvdXJjZXMvZm9ybXMvYWRzLmFzcHgiXQ==")],latvian:[c("YVtocmVmPSJodHRwOi8vd3d3LnNhbGlkemluaS5sdi8iXVtzdHlsZT0iZGlzcGxheTogYmxvY2s7IHdpZHRoOiAxMjBweDsgaGVpZ2h0OiA0MHB4OyBvdmVyZmxvdzogaGlkZGVuOyBwb3NpdGlvbjogcmVsYXRpdmU7Il0="),c("YVtocmVmPSJodHRwOi8vd3d3LnNhbGlkemluaS5sdi8iXVtzdHlsZT0iZGlzcGxheTogYmxvY2s7IHdpZHRoOiA4OHB4OyBoZWlnaHQ6IDMxcHg7IG92ZXJmbG93OiBoaWRkZW47IHBvc2l0aW9uOiByZWxhdGl2ZTsiXQ==")],listKr:[c("YVtocmVmKj0iLy9hZC5wbGFuYnBsdXMuY28ua3IvIl0="),c("I2xpdmVyZUFkV3JhcHBlcg=="),c("YVtocmVmKj0iLy9hZHYuaW1hZHJlcC5jby5rci8iXQ=="),c("aW5zLmZhc3R2aWV3LWFk"),".revenue_unit_item.dable"],listeAr:[c("LmdlbWluaUxCMUFk"),".right-and-left-sponsers",c("YVtocmVmKj0iLmFmbGFtLmluZm8iXQ=="),c("YVtocmVmKj0iYm9vcmFxLm9yZyJd"),c("YVtocmVmKj0iZHViaXp6bGUuY29tL2FyLz91dG1fc291cmNlPSJd")],listeFr:[c("YVtocmVmXj0iaHR0cDovL3Byb21vLnZhZG9yLmNvbS8iXQ=="),c("I2FkY29udGFpbmVyX3JlY2hlcmNoZQ=="),c("YVtocmVmKj0id2Vib3JhbWEuZnIvZmNnaS1iaW4vIl0="),".site-pub-interstitiel",'div[id^="crt-"][data-criteo-id]'],officialPolish:["#ceneo-placeholder-ceneo-12",c("W2hyZWZePSJodHRwczovL2FmZi5zZW5kaHViLnBsLyJd"),c("YVtocmVmXj0iaHR0cDovL2Fkdm1hbmFnZXIudGVjaGZ1bi5wbC9yZWRpcmVjdC8iXQ=="),c("YVtocmVmXj0iaHR0cDovL3d3dy50cml6ZXIucGwvP3V0bV9zb3VyY2UiXQ=="),c("ZGl2I3NrYXBpZWNfYWQ=")],ro:[c("YVtocmVmXj0iLy9hZmZ0cmsuYWx0ZXgucm8vQ291bnRlci9DbGljayJd"),c("YVtocmVmXj0iaHR0cHM6Ly9ibGFja2ZyaWRheXNhbGVzLnJvL3Ryay9zaG9wLyJd"),c("YVtocmVmXj0iaHR0cHM6Ly9ldmVudC4ycGVyZm9ybWFudC5jb20vZXZlbnRzL2NsaWNrIl0="),c("YVtocmVmXj0iaHR0cHM6Ly9sLnByb2ZpdHNoYXJlLnJvLyJd"),'a[href^="/url/"]'],ruAd:[c("YVtocmVmKj0iLy9mZWJyYXJlLnJ1LyJd"),c("YVtocmVmKj0iLy91dGltZy5ydS8iXQ=="),c("YVtocmVmKj0iOi8vY2hpa2lkaWtpLnJ1Il0="),"#pgeldiz",".yandex-rtb-block"],thaiAds:["a[href*=macau-uta-popup]",c("I2Fkcy1nb29nbGUtbWlkZGxlX3JlY3RhbmdsZS1ncm91cA=="),c("LmFkczMwMHM="),".bumq",".img-kosana"],webAnnoyancesUltralist:["#mod-social-share-2","#social-tools",c("LmN0cGwtZnVsbGJhbm5lcg=="),".zergnet-recommend",".yt.btn-link.btn-md.btn"]},n=Object.keys(e),[4,T((i=[]).concat.apply(i,n.map((function(n){return e[n]}))))]):[2,void 0];case 1:return o=t.sent(),r&&function(e,n){for(var t="DOM blockers debug:\n```",r=0,o=Object.keys(e);r<o.length;r++){var a=o[r];t+="\n".concat(a,":");for(var i=0,c=e[a];i<c.length;i++){var u=c[i];t+="\n ".concat(n[u]?"🚫":"➡️"," ").concat(u)}}console.log("".concat(t,"\n```"))}(e,o),(a=n.filter((function(n){var t=e[n];return g(t.map((function(e){return o[e]})))>.6*t.length}))).sort(),[2,a]}var c}))}))},fontPreferences:function(){return function(e,n){void 0===n&&(n=4e3);return X((function(t,o){var a=o.document,i=a.body,c=i.style;c.width="".concat(n,"px"),c.webkitTextSizeAdjust=c.textSizeAdjust="none",S()?i.style.zoom="".concat(1/o.devicePixelRatio):x()&&(i.style.zoom="reset");var u=a.createElement("div");return u.textContent=r([],Array(n/20<<0),!0).map((function(){return"word"})).join(" "),i.appendChild(u),e(a,i)}),'<!doctype html><html><head><meta name="viewport" content="width=device-width, initial-scale=1">')}((function(e,n){for(var t={},r={},o=0,a=Object.keys(ee);o<a.length;o++){var i=a[o],c=ee[i],u=c[0],l=void 0===u?{}:u,s=c[1],d=void 0===s?"mmMwWLliI0fiflO&1":s,m=e.createElement("span");m.textContent=d,m.style.whiteSpace="nowrap";for(var f=0,v=Object.keys(l);f<v.length;f++){var h=v[f],p=l[h];void 0!==p&&(m.style[h]=p)}t[i]=m,n.appendChild(e.createElement("br")),n.appendChild(m)}for(var b=0,y=Object.keys(ee);b<y.length;b++){r[i=y[b]]=t[i].getBoundingClientRect().width}return r}))},audio:function(){var e=window,n=e.OfflineAudioContext||e.webkitOfflineAudioContext;if(!n)return-2;if(x()&&!F()&&!function(){var e=window;return g(["DOMRectList"in e,"RTCPeerConnectionIceEvent"in e,"SVGGeometryElement"in e,"ontransitioncancel"in e])>=3}())return-1;var t=new n(1,5e3,44100),r=t.createOscillator();r.type="triangle",r.frequency.value=1e4;var o=t.createDynamicsCompressor();o.threshold.value=-50,o.knee.value=40,o.ratio.value=12,o.attack.value=0,o.release.value=.25,r.connect(o),o.connect(t.destination),r.start(0);var i=function(e){var n=3,t=500,r=500,o=5e3,i=function(){};return[new Promise((function(c,l){var s=!1,d=0,m=0;e.oncomplete=function(e){return c(e.renderedBuffer)};var f=function(){setTimeout((function(){return l(R("timeout"))}),Math.min(r,m+o-Date.now()))},v=function(){try{var r=e.startRendering();switch(a(r)&&u(r),e.state){case"running":m=Date.now(),s&&f();break;case"suspended":document.hidden||d++,s&&d>=n?l(R("suspended")):setTimeout(v,t)}}catch(o){l(o)}};v(),i=function(){s||(s=!0,m>0&&f())}})),i]}(t),c=i[0],l=i[1],s=c.then((function(e){return function(e){for(var n=0,t=0;t<e.length;++t)n+=Math.abs(e[t]);return n}(e.getChannelData(0).subarray(4500))}),(function(e){if("timeout"===e.name||"suspended"===e.name)return-3;throw e}));return u(s),function(){return l(),s}},screenFrame:function(){var e=this,r=z();return function(){return n(e,void 0,void 0,(function(){var e,n;return t(this,(function(t){switch(t.label){case 0:return[4,r()];case 1:return e=t.sent(),[2,[(n=function(e){return null===e?null:w(e,10)})(e[0]),n(e[1]),n(e[2]),n(e[3])]]}}))}))}},osCpu:function(){return navigator.oscpu},languages:function(){var e,n=navigator,t=[],r=n.language||n.userLanguage||n.browserLanguage||n.systemLanguage;if(void 0!==r&&t.push([r]),Array.isArray(n.languages))S()&&g([!("MediaSettingsRange"in(e=window)),"RTCEncodedAudioFrame"in e,""+e.Intl=="[object Intl]",""+e.Reflect=="[object Reflect]"])>=3||t.push(n.languages);else if("string"==typeof n.languages){var o=n.languages;o&&t.push(o.split(","))}return t},colorDepth:function(){return window.screen.colorDepth},deviceMemory:function(){return y(b(navigator.deviceMemory),void 0)},screenResolution:function(){var e=screen,n=function(e){return y(p(e),null)},t=[n(e.width),n(e.height)];return t.sort().reverse(),t},hardwareConcurrency:function(){return y(p(navigator.hardwareConcurrency),void 0)},timezone:function(){var e,n=null===(e=window.Intl)||void 0===e?void 0:e.DateTimeFormat;if(n){var t=(new n).resolvedOptions().timeZone;if(t)return t}var r,o=(r=(new Date).getFullYear(),-Math.max(b(new Date(r,0,1).getTimezoneOffset()),b(new Date(r,6,1).getTimezoneOffset())));return"UTC".concat(o>=0?"+":"").concat(Math.abs(o))},sessionStorage:function(){try{return!!window.sessionStorage}catch(e){return!0}},localStorage:function(){try{return!!window.localStorage}catch(e){return!0}},indexedDB:function(){if(!W()&&!C())try{return!!window.indexedDB}catch(e){return!0}},openDatabase:function(){return!!window.openDatabase},cpuClass:function(){return navigator.cpuClass},platform:function(){var e=navigator.platform;return"MacIntel"===e&&x()&&!F()?function(){if("iPad"===navigator.platform)return!0;var e=screen,n=e.width/e.height;return g(["MediaSource"in window,!!Element.prototype.webkitRequestFullscreen,n>.65&&n<1.53])>=2}()?"iPad":"iPhone":e},plugins:function(){var e=navigator.plugins;if(e){for(var n=[],t=0;t<e.length;++t){var r=e[t];if(r){for(var o=[],a=0;a<r.length;++a){var i=r[a];o.push({type:i.type,suffixes:i.suffixes})}n.push({name:r.name,description:r.description,mimeTypes:o})}}return n}},canvas:function(){var e,n,t=!1,r=function(){var e=document.createElement("canvas");return e.width=1,e.height=1,[e,e.getContext("2d")]}(),o=r[0],a=r[1];if(function(e,n){return!(!n||!e.toDataURL)}(o,a)){t=function(e){return e.rect(0,0,10,10),e.rect(2,2,6,6),!e.isPointInPath(5,5,"evenodd")}(a),function(e,n){e.width=240,e.height=60,n.textBaseline="alphabetic",n.fillStyle="#f60",n.fillRect(100,1,62,20),n.fillStyle="#069",n.font='11pt "Times New Roman"';var t="Cwm fjordbank gly ".concat(String.fromCharCode(55357,56835));n.fillText(t,2,15),n.fillStyle="rgba(102, 204, 0, 0.2)",n.font="18pt Arial",n.fillText(t,4,45)}(o,a);var i=H(o);i!==H(o)?e=n="unstable":(n=i,function(e,n){e.width=122,e.height=110,n.globalCompositeOperation="multiply";for(var t=0,r=[["#f2f",40,40],["#2ff",80,40],["#ff2",60,80]];t<r.length;t++){var o=r[t],a=o[0],i=o[1],c=o[2];n.fillStyle=a,n.beginPath(),n.arc(i,c,40,0,2*Math.PI,!0),n.closePath(),n.fill()}n.fillStyle="#f9c",n.arc(60,60,60,0,2*Math.PI,!0),n.arc(60,60,20,0,2*Math.PI,!0),n.fill("evenodd")}(o,a),e=H(o))}else e=n="";return{winding:t,geometry:e,text:n}},touchSupport:function(){var e,n=navigator,t=0;void 0!==n.maxTouchPoints?t=p(n.maxTouchPoints):void 0!==n.msMaxTouchPoints&&(t=n.msMaxTouchPoints);try{document.createEvent("TouchEvent"),e=!0}catch(r){e=!1}return{maxTouchPoints:t,touchEvent:e,touchStart:"ontouchstart"in window}},vendor:function(){return navigator.vendor||""},vendorFlavors:function(){for(var e=[],n=0,t=["chrome","safari","__crWeb","__gCrWeb","yandex","__yb","__ybro","__firefox__","__edgeTrackingPreventionStatistics","webkit","oprt","samsungAr","ucweb","UCShellJava","puffinDevice"];n<t.length;n++){var r=t[n],o=window[r];o&&"object"==typeof o&&e.push(r)}return e.sort()},cookiesEnabled:function(){var e=document;try{e.cookie="cookietest=1; SameSite=Strict;";var n=-1!==e.cookie.indexOf("cookietest=");return e.cookie="cookietest=1; SameSite=Strict; expires=Thu, 01-Jan-1970 00:00:01 GMT",n}catch(t){return!1}},colorGamut:function(){for(var e=0,n=["rec2020","p3","srgb"];e<n.length;e++){var t=n[e];if(matchMedia("(color-gamut: ".concat(t,")")).matches)return t}},invertedColors:function(){return!!_("inverted")||!_("none")&&void 0},forcedColors:function(){return!!O("active")||!O("none")&&void 0},monochrome:function(){if(matchMedia("(min-monochrome: 0)").matches){for(var e=0;e<=100;++e)if(matchMedia("(max-monochrome: ".concat(e,")")).matches)return e;throw new Error("Too high value")}},contrast:function(){return U("no-preference")?0:U("high")||U("more")?1:U("low")||U("less")?-1:U("forced")?10:void 0},reducedMotion:function(){return!!Q("reduce")||!Q("no-preference")&&void 0},hdr:function(){return!!K("high")||!K("standard")&&void 0},math:function(){var e,n=q.acos||$,t=q.acosh||$,r=q.asin||$,o=q.asinh||$,a=q.atanh||$,i=q.atan||$,c=q.sin||$,u=q.sinh||$,l=q.cos||$,s=q.cosh||$,d=q.tan||$,m=q.tanh||$,f=q.exp||$,v=q.expm1||$,h=q.log1p||$;return{acos:n(.12312423423423424),acosh:t(1e308),acoshPf:(e=1e154,q.log(e+q.sqrt(e*e-1))),asin:r(.12312423423423424),asinh:o(1),asinhPf:function(e){return q.log(e+q.sqrt(e*e+1))}(1),atanh:a(.5),atanhPf:function(e){return q.log((1+e)/(1-e))/2}(.5),atan:i(.5),sin:c(-1e300),sinh:u(1),sinhPf:function(e){return q.exp(e)-1/q.exp(e)/2}(1),cos:l(10.000000000123),cosh:s(1),coshPf:function(e){return(q.exp(e)+1/q.exp(e))/2}(1),tan:d(-1e300),tanh:m(1),tanhPf:function(e){return(q.exp(2*e)-1)/(q.exp(2*e)+1)}(1),exp:f(1),expm1:v(1),expm1Pf:function(e){return q.exp(e)-1}(1),log1p:h(10),log1pPf:function(e){return q.log(1+e)}(10),powPI:function(e){return q.pow(q.PI,e)}(-100)}},videoCard:function(){var e,n=document.createElement("canvas"),t=null!==(e=n.getContext("webgl"))&&void 0!==e?e:n.getContext("experimental-webgl");if(t&&"getExtension"in t){var r=t.getExtension("WEBGL_debug_renderer_info");if(r)return{vendor:(t.getParameter(r.UNMASKED_VENDOR_WEBGL)||"").toString(),renderer:(t.getParameter(r.UNMASKED_RENDERER_WEBGL)||"").toString()}}},pdfViewerEnabled:function(){return navigator.pdfViewerEnabled},architecture:function(){var e=new Float32Array(1),n=new Uint8Array(e.buffer);return e[0]=1/0,e[0]=e[0]-e[0],n[3]}};function te(e){var n=function(e){if(G())return.4;if(x())return F()?.5:.3;var n=e.platform.value||"";if(/^Win/.test(n))return.6;if(/^Mac/.test(n))return.5;return.7}(e),t=function(e){return w(.99+.01*e,1e-4)}(n);return{score:n,comment:"$ if upgrade to Pro: https://fpjs.dev/pro".replace(/\$/g,"".concat(t))}}function re(n){return JSON.stringify(n,(function(n,t){return t instanceof Error?e({name:(r=t).name,message:r.message,stack:null===(o=r.stack)||void 0===o?void 0:o.split("\n")},r):t;var r,o}),2)}function oe(e){return h(function(e){for(var n="",t=0,r=Object.keys(e).sort();t<r.length;t++){var o=r[t],a=e[o],i=a.error?"error":JSON.stringify(a.value);n+="".concat(n?"|":"").concat(o.replace(/([:|\\])/g,"\\$1"),":").concat(i)}return n}(e))}function ae(e){return void 0===e&&(e=50),function(e,n){void 0===n&&(n=1/0);var t=window.requestIdleCallback;return t?new Promise((function(e){return t.call(window,(function(){return e()}),{timeout:n})})):o(Math.min(e,n))}(e,2*e)}function ie(e,r){var o=Date.now();return{get:function(a){return n(this,void 0,void 0,(function(){var n,i,c;return t(this,(function(t){switch(t.label){case 0:return n=Date.now(),[4,e()];case 1:return i=t.sent(),c=function(e){var n;return{get visitorId(){return void 0===n&&(n=oe(this.components)),n},set visitorId(e){n=e},confidence:te(e),components:e,version:"3.4.2"}}(i),(r||(null==a?void 0:a.debug))&&console.log("Copy the text below to get the debug data:\n\n```\nversion: ".concat(c.version,"\nuserAgent: ").concat(navigator.userAgent,"\ntimeBetweenLoadAndGet: ").concat(n-o,"\nvisitorId: ").concat(c.visitorId,"\ncomponents: ").concat(re(i),"\n```")),[2,c]}}))}))}}}function ce(e){var r=void 0===e?{}:e,o=r.delayFallback,a=r.debug;return r.monitoring,n(this,void 0,void 0,(function(){return t(this,(function(e){switch(e.label){case 0:return[4,ae(o)];case 1:return e.sent(),[2,ie(V(ne,{debug:a},[]),a)]}}))}))}var ue={load:ce,hashComponents:oe,componentsToDebugString:re},le=h;export{re as componentsToDebugString,ue as default,M as getFullscreenElement,z as getScreenFrame,oe as hashComponents,G as isAndroid,S as isChromium,F as isDesktopSafari,C as isEdgeHTML,Y as isGecko,W as isTrident,x as isWebKit,ce as load,V as loadSources,le as murmurX64Hash128,ae as prepareForSources,ne as sources,Z as transformSource,X as withIframe};