py2ls 0.1.4.8__py3-none-any.whl → 0.1.4.9__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.
Files changed (33) hide show
  1. py2ls/.git/COMMIT_EDITMSG +1 -1
  2. py2ls/.git/FETCH_HEAD +1 -1
  3. py2ls/.git/index +0 -0
  4. py2ls/.git/logs/HEAD +3 -0
  5. py2ls/.git/logs/refs/heads/main +3 -0
  6. py2ls/.git/logs/refs/remotes/origin/HEAD +5 -0
  7. py2ls/.git/logs/refs/remotes/origin/main +3 -0
  8. py2ls/.git/objects/01/d5bd8065e6860c0bd23ff9fa57161806a099e1 +0 -0
  9. py2ls/.git/objects/09/08da26de58c114225ad81f484b80bf5d351b34 +0 -0
  10. py2ls/.git/objects/1c/3f92adda34344bcbbbf9d409c79855ae2aaea8 +2 -0
  11. py2ls/.git/objects/32/fd627b62fad7cf3b2f9e34ab9777126a0987ad +0 -0
  12. py2ls/.git/objects/39/7ead045fbbcfb17c62019eb18fe21ed05dbee5 +0 -0
  13. py2ls/.git/objects/4f/7afb40dff2153d857fc85748c2eecb85125042 +0 -0
  14. py2ls/.git/objects/62/4488173ed2c8936fa5cea3cf5dd3f26a30b86e +0 -0
  15. py2ls/.git/objects/6d/ee29dbdcc84edeeacede105110446f3ccac963 +0 -0
  16. py2ls/.git/objects/b7/2c9e75ab7d0afe594664650aa8f6c772f5ac64 +0 -0
  17. py2ls/.git/objects/bb/81ccc0513f18fc160b54a82861e9a80d23f4f6 +0 -0
  18. py2ls/.git/objects/cd/822b3574a88ebdd1ed82fd6983f37e626d52b4 +0 -0
  19. py2ls/.git/objects/d8/4688b54c0040a30976b3a6540bc47adf7ce680 +0 -0
  20. py2ls/.git/objects/f1/e50757fddc28b445545dc7e2759b54cdd0f42e +0 -0
  21. py2ls/.git/refs/heads/main +1 -1
  22. py2ls/.git/refs/remotes/origin/main +1 -1
  23. py2ls/__init__.py +1 -1
  24. py2ls/data/.DS_Store +0 -0
  25. py2ls/data/db2ls_sql_chtsht.json +39 -0
  26. py2ls/data/lang_code_iso639.json +97 -0
  27. py2ls/db2ls.py +356 -0
  28. py2ls/ips.py +168 -240
  29. py2ls/translator.py +6 -99
  30. {py2ls-0.1.4.8.dist-info → py2ls-0.1.4.9.dist-info}/METADATA +1 -1
  31. {py2ls-0.1.4.8.dist-info → py2ls-0.1.4.9.dist-info}/RECORD +32 -16
  32. py2ls/dbhandler.py +0 -97
  33. {py2ls-0.1.4.8.dist-info → py2ls-0.1.4.9.dist-info}/WHEEL +0 -0
py2ls/ips.py CHANGED
@@ -1,51 +1,52 @@
1
1
  from scipy.ndimage import convolve1d
2
+ from scipy.signal import savgol_filter
3
+ import pingouin as pg
4
+ from scipy import stats
5
+
2
6
  import numpy as np
3
7
  import pandas as pd
8
+
4
9
  import json
5
- import matplotlib.pyplot as plt
6
- import seaborn as sns
7
- # import scienceplots
8
10
  import matplotlib
9
- import sys
10
- import os
11
- from scipy.signal import savgol_filter
12
- import pingouin as pg
13
- from scipy import stats
11
+ import matplotlib.pyplot as plt
14
12
  import matplotlib.ticker as tck
13
+ from mpl_toolkits.mplot3d import Axes3D
14
+ import seaborn as sns
15
+
16
+ import sys, os,shutil,re, yaml,json
15
17
  from cycler import cycler
16
- import re
18
+ import time
19
+ from dateutil import parser
20
+ from datetime import datetime
21
+
17
22
  from PIL import Image,ImageEnhance, ImageOps,ImageFilter
18
23
  from rembg import remove,new_session
19
- from mpl_toolkits.mplot3d import Axes3D
24
+
20
25
  import docx
21
- import pandas as pd
22
26
  from fpdf import FPDF
23
- import yaml
24
27
  from lxml import etree
25
28
  from docx import Document
26
29
  from PyPDF2 import PdfReader
27
30
  from pdf2image import convert_from_path, pdfinfo_from_path
28
- from nltk.tokenize import sent_tokenize,word_tokenize
31
+ from nltk.tokenize import sent_tokenize, word_tokenize
29
32
  import nltk # nltk.download("punkt")
30
33
  from docx2pdf import convert
31
34
  import img2pdf as image2pdf
32
- import pprint
35
+ import nbformat
36
+ from nbconvert import MarkdownExporter
37
+
33
38
  from itertools import pairwise
34
- import time
35
39
  from box import Box, BoxList
36
40
  from numerizer import numerize
37
41
  from tqdm import tqdm
38
42
  import mimetypes
39
43
  from pprint import pp
40
- from dateutil import parser
41
- from datetime import datetime
42
44
  from collections import Counter
43
45
  from fuzzywuzzy import fuzz,process
44
- from py2ls import netfinder
45
46
  from langdetect import detect
46
- import shutil
47
47
  from duckduckgo_search import DDGS
48
48
 
49
+ from py2ls import netfinder
49
50
 
50
51
  dir_save='/Users/macjianfeng/Dropbox/Downloads/'
51
52
 
@@ -58,6 +59,45 @@ def rm_folder(folder_path, verbose=True):
58
59
  if verbose:
59
60
  print(f'Failed to delete {folder_path}. Reason: {e}')
60
61
 
62
+ def fremove(path, verbose=True):
63
+ """
64
+ Remove a folder and all its contents or a single file.
65
+ Parameters:
66
+ path (str): The path to the folder or file to remove.
67
+ verbose (bool): If True, print success or failure messages. Default is True.
68
+ """
69
+ try:
70
+ if os.path.isdir(path):
71
+ shutil.rmtree(path)
72
+ if verbose:
73
+ print(f'Successfully deleted folder {path}')
74
+ elif os.path.isfile(path):
75
+ os.remove(path)
76
+ if verbose:
77
+ print(f'Successfully deleted file {path}')
78
+ else:
79
+ if verbose:
80
+ print(f'Path {path} does not exist')
81
+ except Exception as e:
82
+ if verbose:
83
+ print(f'Failed to delete {path}. Reason: {e}')
84
+
85
+
86
+ def get_cwd(verbose:bool = True):
87
+ """
88
+ get_cwd: to get the current working directory
89
+ Args:
90
+ verbose (bool, optional): to show which function is use. Defaults to True.
91
+ """
92
+ try:
93
+ script_dir = os.path.dirname(os.path.abspath(__file__))
94
+ if verbose:
95
+ print("os.path.dirname(os.path.abspath(__file__)):", script_dir)
96
+ except NameError:
97
+ # This works in an interactive environment (like a Jupyter notebook)
98
+ script_dir = os.getcwd()
99
+ if verbose:
100
+ print("os.getcwd():", script_dir)
61
101
 
62
102
  def search(query, limit=5, kind='text', output='df',verbose=False,download=True, dir_save=dir_save):
63
103
  from duckduckgo_search import DDGS
@@ -157,102 +197,10 @@ def ai(*args, **kwargs):
157
197
  return echo(**kwargs)
158
198
 
159
199
  def detect_lang(text, output='lang',verbose=True):
160
- lang_code_iso639={'Abkhazian': 'ab',
161
- 'Afar': 'aa',
162
- 'Afrikaans': 'af',
163
- 'Akan': 'ak',
164
- 'Albanian': 'sq',
165
- 'Amharic': 'am',
166
- 'Arabic': 'ar',
167
- 'Armenian': 'hy',
168
- 'Assamese': 'as',
169
- # 'Avaric': 'av',
170
- 'Aymara': 'ay',
171
- 'Azerbaijani': 'az',
172
- 'Bashkir': 'ba',
173
- 'Basque': 'eu',
174
- 'Belarusian': 'be',
175
- 'Bislama': 'bi',
176
- 'Breton': 'br',
177
- 'Burmese': 'my',
178
- 'Catalan, Valencian': 'ca',
179
- 'Chamorro': 'ch',
180
- 'Chichewa, Chewa, Nyanja': 'ny',
181
- 'Chinese': 'zh',
182
- 'Corsican': 'co',
183
- 'Cree': 'cr',
184
- 'Croatian': 'hr',
185
- 'Danish': 'da',
186
- 'Dutch, Flemish': 'nl',
187
- 'Dzongkha': 'dz',
188
- 'English': 'en',
189
- 'Finnish': 'fi',
190
- 'French': 'fr',
191
- 'Galician': 'gl',
192
- 'Georgian': 'ka',
193
- 'German': 'de',
194
- 'Greek, Modern (1453–)': 'el',
195
- 'Gujarati': 'gu',
196
- 'Hausa': 'ha',
197
- 'Hebrew': 'he',
198
- 'Hindi': 'hi',
199
- 'Hungarian': 'hu',
200
- 'Icelandic': 'is',
201
- 'Italian': 'it',
202
- 'Kikuyu, Gikuyu': 'ki',
203
- 'Korean': 'ko',
204
- 'Kurdish': 'ku',
205
- 'Latin': 'la',
206
- 'Limburgan, Limburger, Limburgish': 'li',
207
- 'Luba-Katanga': 'lu',
208
- 'Macedonian': 'mk',
209
- 'Malay': 'ms',
210
- 'Nauru': 'na',
211
- 'North Ndebele': 'nd',
212
- 'Nepali': 'ne',
213
- 'Norwegian': 'no',
214
- 'Norwegian Nynorsk': 'nn',
215
- 'Sichuan Yi, Nuosu': 'ii',
216
- 'Occitan': 'oc',
217
- 'Ojibwa': 'oj',
218
- 'Oriya': 'or',
219
- 'Ossetian, Ossetic': 'os',
220
- 'Persian': 'fa',
221
- 'Punjabi, Panjabi': 'pa',
222
- 'Quechua': 'qu',
223
- 'Romanian, Moldavian, Moldovan': 'ro',
224
- 'Russian': 'ru',
225
- 'Samoan': 'sm',
226
- 'Sanskrit': 'sa',
227
- 'Serbian': 'sr',
228
- 'Shona': 'sn',
229
- 'Sinhala, Sinhalese': 'si',
230
- 'Slovenian': 'sl',
231
- 'Somali': 'so',
232
- 'Sundanese': 'su',
233
- 'Swahili': 'sw',
234
- 'Swati': 'ss',
235
- 'Tajik': 'tg',
236
- 'Tamil': 'ta',
237
- 'Telugu': 'te',
238
- 'Thai': 'th',
239
- 'Tibetan': 'bo',
240
- 'Tigrinya': 'ti',
241
- 'Tonga (Tonga Islands)': 'to',
242
- 'Tsonga': 'ts',
243
- 'Twi': 'tw',
244
- 'Ukrainian': 'uk',
245
- 'Urdu': 'ur',
246
- 'Uzbek': 'uz',
247
- 'Venda': 've',
248
- 'Vietnamese': 'vi',
249
- 'Volapük': 'vo',
250
- 'Welsh': 'cy',
251
- 'Wolof': 'wo',
252
- 'Xhosa': 'xh',
253
- 'Yiddish': 'yi',
254
- 'Yoruba': 'yo',
255
- 'Zulu': 'zu'}
200
+ dir_curr_script=os.path.dirname(os.path.abspath(__file__))
201
+ dir_lang_code=dir_curr_script+"/data/lang_code_iso639.json"
202
+ print(dir_curr_script,os.getcwd(),dir_lang_code)
203
+ lang_code_iso639=fload(dir_lang_code)
256
204
  l_lang,l_code = [],[]
257
205
  [[l_lang.append(v),l_code.append(k)] for v,k in lang_code_iso639.items()]
258
206
  try:
@@ -340,21 +288,7 @@ def counter(list_, verbose=True):
340
288
  # print(f"Return a list of the n most common elements:\n{c.most_common()}")
341
289
  # print(f"Compute the sum of the counts:\n{c.total()}")
342
290
 
343
- def is_num(s):
344
- """
345
- Check if a string can be converted to a number (int or float).
346
- Parameters:
347
- - s (str): The string to check.
348
- Returns:
349
- - bool: True if the string can be converted to a number, False otherwise.
350
- """
351
- try:
352
- float(s) # Try converting the string to a float
353
- return True
354
- except ValueError:
355
- return False
356
- def isnum(s):
357
- return is_num(s)
291
+
358
292
 
359
293
  def str2time(time_str, fmt='24'):
360
294
  """
@@ -600,6 +534,7 @@ def paper_size(paper_type_str='a4'):
600
534
  if not paper_type:
601
535
  paper_type='a4' # default
602
536
  return df[paper_type].tolist()
537
+
603
538
  def docx2pdf(dir_docx, dir_pdf=None):
604
539
  if dir_pdf:
605
540
  convert(dir_docx,dir_pdf)
@@ -815,7 +750,7 @@ def pdf2img(dir_pdf, dir_save=None, page=None, kind="png",verbose=True, **kws):
815
750
  df_dir_img_single_page = pd.DataFrame()
816
751
  dir_single_page = []
817
752
  if verbose:
818
- pprint.pp(pdfinfo_from_path(dir_pdf))
753
+ pp(pdfinfo_from_path(dir_pdf))
819
754
  if isinstance(page, tuple) and page:
820
755
  page = list(page)
821
756
  if isinstance(page,int):
@@ -888,7 +823,14 @@ def fload(fpath, kind=None, **kwargs):
888
823
  def load_xlsx(fpath, **kwargs):
889
824
  df = pd.read_excel(fpath, **kwargs)
890
825
  return df
891
-
826
+ def load_ipynb(fpath,**kwargs):
827
+ as_version=kwargs.get("as_version",4)
828
+ with open(fpath, "r") as file:
829
+ nb = nbformat.read(file, as_version=as_version)
830
+ md_exporter = MarkdownExporter()
831
+ md_body, _ = md_exporter.from_notebook_node(nb)
832
+ return md_body
833
+
892
834
  def load_pdf(fpath, page='all', verbose=False, **kwargs):
893
835
  """
894
836
  Parameters:
@@ -950,7 +892,7 @@ def fload(fpath, kind=None, **kwargs):
950
892
 
951
893
  kind = kind.lstrip('.').lower()
952
894
  img_types=[ 'bmp','eps', 'gif', 'icns', 'ico', 'im', 'jpg','jpeg', 'jpeg2000','msp', 'pcx', 'png', 'ppm', 'sgi', 'spider', 'tga','tiff','webp',"json"]
953
- doc_types = ["docx", "txt", "md", "html", "json", "yaml", "xml", "csv", "xlsx", "pdf"]
895
+ doc_types = ["docx", "txt", "md", "html", "json", "yaml", "xml", "csv", "xlsx", "pdf","ipynb"]
954
896
  supported_types = [*doc_types, *img_types]
955
897
  if kind not in supported_types:
956
898
  raise ValueError(f"Error:\n{kind} is not in the supported list {supported_types}")
@@ -970,6 +912,8 @@ def fload(fpath, kind=None, **kwargs):
970
912
  return load_csv(fpath, **kwargs)
971
913
  elif kind == "xlsx":
972
914
  return load_xlsx(fpath, **kwargs)
915
+ elif kind == "ipynb":
916
+ return load_ipynb(fpath, **kwargs)
973
917
  elif kind == "pdf":
974
918
  print('usage:load_pdf(fpath, page="all", verbose=False)')
975
919
  return load_pdf(fpath, **kwargs)
@@ -1093,7 +1037,25 @@ def fsave(
1093
1037
  df = pd.DataFrame(data)
1094
1038
  df.to_excel(fpath, **kwargs)
1095
1039
 
1040
+ def save_ipynb(fpath,data,**kwargs):
1041
+ # Split the content by code fences to distinguish between code and markdown
1042
+ parts = data.split('```')
1043
+ cells = []
1096
1044
 
1045
+ for i, part in enumerate(parts):
1046
+ if i % 2 == 0:
1047
+ # Even index: markdown content
1048
+ cells.append(nbf.v4.new_markdown_cell(part.strip()))
1049
+ else:
1050
+ # Odd index: code content
1051
+ cells.append(nbf.v4.new_code_cell(part.strip()))
1052
+ # Create a new notebook
1053
+ nb = nbformat.v4.new_notebook()
1054
+ nb['cells'] = cells
1055
+ # Write the notebook to a file
1056
+ with open(fpath, 'w', encoding='utf-8') as ipynb_file:
1057
+ nbf.write(fpath, ipynb_file)
1058
+
1097
1059
  # def save_json(fpath, data, **kwargs):
1098
1060
  # with open(fpath, "w") as file:
1099
1061
  # json.dump(data, file, **kwargs)
@@ -1152,6 +1114,7 @@ def fsave(
1152
1114
  "json",
1153
1115
  "xml",
1154
1116
  "yaml",
1117
+ "ipynb"
1155
1118
  ]:
1156
1119
  print(
1157
1120
  f"Warning:\n{kind} is not in the supported list ['docx', 'txt', 'md', 'html', 'pdf', 'csv', 'xlsx', 'json', 'xml', 'yaml']"
@@ -1168,19 +1131,17 @@ def fsave(
1168
1131
  elif kind == "pdf":
1169
1132
  save_pdf(fpath, content, font_name, font_size)
1170
1133
  elif kind == "csv":
1171
- save_csv(
1172
- fpath, content, **kwargs
1173
- ) # Assuming content is in tabular form (list of dicts or DataFrame)
1134
+ save_csv(fpath, content, **kwargs)
1174
1135
  elif kind == "xlsx":
1175
- save_xlsx(
1176
- fpath, content, **kwargs
1177
- ) # Assuming content is in tabular form (list of dicts or DataFrame)
1136
+ save_xlsx(fpath, content, **kwargs)
1178
1137
  elif kind == "json":
1179
- save_json(fpath, content) # Assuming content is a serializable object
1138
+ save_json(fpath, content)
1180
1139
  elif kind == "xml":
1181
- save_xml(fpath, content) # Assuming content is a dictionary
1140
+ save_xml(fpath, content)
1182
1141
  elif kind == "yaml":
1183
- save_yaml(fpath, content, **kwargs) # Assuming content is a serializable object
1142
+ save_yaml(fpath, content, **kwargs)
1143
+ elif kind == "ipynb":
1144
+ save_ipynb(fpath, content, **kwargs)
1184
1145
  else:
1185
1146
  try:
1186
1147
  netfinder.downloader(url=content, dir_save=dirname(fpath), kind=kind)
@@ -1285,42 +1246,19 @@ def isa(*args,**kwargs):
1285
1246
  elif 'zip' in contains.lower():
1286
1247
  return is_zip(fpath)
1287
1248
  elif 'dir' in contains.lower() or ('f' in contains.lower() and 'd' in contains.lower()):
1288
- return bool(('/' in fpath) or ('\\' in fpath))
1249
+ return os.path.isdir(fpath)
1289
1250
  elif 'fi' in contains.lower():#file
1290
1251
  return os.path.isfile(fpath)
1252
+ elif 'num' in contains.lower():#file
1253
+ return os.path.isfile(fpath)
1254
+ elif 'text' in contains.lower() or 'txt' in contains.lower():#file
1255
+ return is_text(fpath)
1256
+ elif 'color' in contains.lower():#file
1257
+ return is_str_color(fpath)
1291
1258
  else:
1292
1259
  print(f"{contains} was not set up correctly")
1293
1260
  return False
1294
1261
 
1295
- def is_image(fpath):
1296
- mime_type, _ = mimetypes.guess_type(fpath)
1297
- if mime_type and mime_type.startswith('image'):
1298
- return True
1299
- else:
1300
- return False
1301
-
1302
- def is_document(fpath):
1303
- mime_type, _ = mimetypes.guess_type(fpath)
1304
- if mime_type and (
1305
- mime_type.startswith('text/') or
1306
- mime_type == 'application/pdf' or
1307
- mime_type == 'application/msword' or
1308
- mime_type == 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' or
1309
- mime_type == 'application/vnd.ms-excel' or
1310
- mime_type == 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' or
1311
- mime_type == 'application/vnd.ms-powerpoint' or
1312
- mime_type == 'application/vnd.openxmlformats-officedocument.presentationml.presentation'
1313
- ):
1314
- return True
1315
- else:
1316
- return False
1317
-
1318
- def is_zip(fpath):
1319
- mime_type, _ = mimetypes.guess_type(fpath)
1320
- if mime_type == 'application/zip':
1321
- return True
1322
- else:
1323
- return False
1324
1262
  def listdir(
1325
1263
  rootdir,
1326
1264
  kind="folder",
@@ -1428,21 +1366,15 @@ def list_func(lib_name, opt="call"):
1428
1366
  funcs = dir(lib_name)
1429
1367
  return funcs
1430
1368
  def func_list(lib_name, opt="call"):
1431
- if opt == "call":
1432
- funcs = [func for func in dir(lib_name) if callable(getattr(lib_name, func))]
1433
- else:
1434
- funcs = dir(lib_name)
1435
- return funcs
1369
+ return list_func(lib_name, opt=opt)
1436
1370
 
1437
1371
  def newfolder(*args, **kwargs):
1438
1372
  """
1439
1373
  newfolder(pardir, chdir)
1440
-
1441
1374
  Args:
1442
1375
  pardir (dir): parent dir
1443
1376
  chdir (str): children dir
1444
1377
  overwrite (bool): overwrite?
1445
-
1446
1378
  Returns:
1447
1379
  mkdir, giving a option if exists_ok or not
1448
1380
  """
@@ -1501,33 +1433,29 @@ def newfolder(*args, **kwargs):
1501
1433
  return rootdir
1502
1434
 
1503
1435
  def figsave(*args,dpi=300):
1504
- DirSave = None
1436
+ dir_save = None
1505
1437
  fname = None
1506
-
1507
1438
  for arg in args:
1508
1439
  if isinstance(arg, str):
1509
1440
  if '/' in arg or '\\' in arg:
1510
- DirSave = arg
1441
+ dir_save = arg
1511
1442
  elif '/' not in arg and '\\' not in arg:
1512
1443
  fname = arg
1513
-
1514
1444
  # Backup original values
1515
- if '/' in DirSave:
1516
- if DirSave[-1] != '/':
1517
- DirSave = DirSave + '/'
1518
- elif '\\' in DirSave:
1519
- if DirSave[-1] != '\\':
1520
- DirSave = DirSave + '\\'
1445
+ if '/' in dir_save:
1446
+ if dir_save[-1] != '/':
1447
+ dir_save = dir_save + '/'
1448
+ elif '\\' in dir_save:
1449
+ if dir_save[-1] != '\\':
1450
+ dir_save = dir_save + '\\'
1521
1451
  else:
1522
- raise ValueError('Check the Path of DirSave Directory')
1523
-
1452
+ raise ValueError('Check the Path of dir_save Directory')
1524
1453
  ftype = fname.split('.')[-1]
1525
1454
  if len(fname.split('.')) == 1:
1526
1455
  ftype = 'nofmt'
1527
- fname = DirSave + fname + '.' + ftype
1456
+ fname = dir_save + fname + '.' + ftype
1528
1457
  else:
1529
- fname = DirSave + fname
1530
-
1458
+ fname = dir_save + fname
1531
1459
  # Save figure based on file type
1532
1460
  if ftype.lower() == 'eps':
1533
1461
  plt.savefig(fname, format='eps', bbox_inches='tight')
@@ -1552,7 +1480,6 @@ def figsave(*args,dpi=300):
1552
1480
  plt.savefig(fname, format='emf', dpi=dpi, bbox_inches='tight')
1553
1481
  elif ftype.lower() == 'fig':
1554
1482
  plt.savefig(fname, format='pdf', bbox_inches='tight',dpi=dpi)
1555
-
1556
1483
  print(f'\nSaved @: dpi={dpi}\n{fname}')
1557
1484
 
1558
1485
 
@@ -1586,8 +1513,6 @@ def FuncStars(ax,
1586
1513
  report=None,
1587
1514
  report_scale=-0.1,
1588
1515
  report_loc=None):
1589
-
1590
-
1591
1516
  if ax is None:
1592
1517
  ax = plt.gca()
1593
1518
  if Ylim is None:
@@ -1598,11 +1523,9 @@ def FuncStars(ax,
1598
1523
  report_loc = np.min(Ylim) + report_scale*np.abs(np.diff(Ylim))
1599
1524
  if report_scale > 0:
1600
1525
  report_scale = -np.abs(report_scale)
1601
-
1602
1526
  yscale = np.float64(yscale)
1603
1527
  y_loc = np.min(Ylim) + yscale*(np.max(Ylim)-np.min(Ylim))
1604
1528
  xcenter = np.mean([x1, x2])
1605
-
1606
1529
  # ns / *
1607
1530
  if alpha < pval:
1608
1531
  if nsshow == 'on':
@@ -1626,7 +1549,6 @@ def FuncStars(ax,
1626
1549
  plt.text(xcenter, y_loc, symbol * 3,
1627
1550
  ha='center', va='center_baseline',
1628
1551
  fontsize=fontsize, fontname=fontname, color=symbolcolor)
1629
-
1630
1552
  # lines indicators
1631
1553
  if linego: # and 0 < pval <= 0.05:
1632
1554
  print(pval)
@@ -1666,12 +1588,10 @@ def FuncStars(ax,
1666
1588
  [np.min(Ylim) + 0.95*(np.max(Ylim)-np.min(Ylim)) - np.abs(np.diff(Ylim)) * tailindicator[1],
1667
1589
  np.min(Ylim) + 0.95*(np.max(Ylim)-np.min(Ylim)) - np.abs(np.diff(Ylim)) * 0.002],
1668
1590
  linestyle=linestyle, color=linecolor, linewidth=linewidth)
1669
-
1670
1591
  if values_below is not None:
1671
1592
  plt.text(xcenter, y_loc * (-0.1), values_below,
1672
1593
  ha='center', va='bottom', # 'center_baseline', rotation=rotation,
1673
1594
  fontsize=fontsize_note, fontname=fontname, color='k')
1674
-
1675
1595
  # report / comments
1676
1596
  if report is not None:
1677
1597
  plt.text(xcenter, report_loc, report,
@@ -1681,7 +1601,49 @@ def is_str_color(s):
1681
1601
  # Regular expression pattern for hexadecimal color codes
1682
1602
  color_code_pattern = r"^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{8})$"
1683
1603
  return re.match(color_code_pattern, s) is not None
1684
-
1604
+ def is_num(s):
1605
+ """
1606
+ Check if a string can be converted to a number (int or float).
1607
+ Parameters:
1608
+ - s (str): The string to check.
1609
+ Returns:
1610
+ - bool: True if the string can be converted to a number, False otherwise.
1611
+ """
1612
+ try:
1613
+ float(s) # Try converting the string to a float
1614
+ return True
1615
+ except ValueError:
1616
+ return False
1617
+ def isnum(s):
1618
+ return is_num(s)
1619
+ def is_image(fpath):
1620
+ mime_type, _ = mimetypes.guess_type(fpath)
1621
+ if mime_type and mime_type.startswith('image'):
1622
+ return True
1623
+ else:
1624
+ return False
1625
+ def is_document(fpath):
1626
+ mime_type, _ = mimetypes.guess_type(fpath)
1627
+ if mime_type and (
1628
+ mime_type.startswith('text/') or
1629
+ mime_type == 'application/pdf' or
1630
+ mime_type == 'application/msword' or
1631
+ mime_type == 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' or
1632
+ mime_type == 'application/vnd.ms-excel' or
1633
+ mime_type == 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' or
1634
+ mime_type == 'application/vnd.ms-powerpoint' or
1635
+ mime_type == 'application/vnd.openxmlformats-officedocument.presentationml.presentation'
1636
+ ):
1637
+ return True
1638
+ else:
1639
+ return False
1640
+ def is_zip(fpath):
1641
+ mime_type, _ = mimetypes.guess_type(fpath)
1642
+ if mime_type == 'application/zip':
1643
+ return True
1644
+ else:
1645
+ return False
1646
+
1685
1647
  def stdshade(ax=None,*args, **kwargs):
1686
1648
  if (
1687
1649
  isinstance(ax, np.ndarray)
@@ -1703,7 +1665,6 @@ def stdshade(ax=None,*args, **kwargs):
1703
1665
  l_style2 = ["--", "-."]
1704
1666
  l_style1 = ["-", ":"]
1705
1667
  l_mark = ["o", "+", "*", ".", "x", "_", "|", "s", "d", "^", "v", ">", "<", "p", "h"]
1706
-
1707
1668
  # Check each argument
1708
1669
  for iarg in range(len(args)):
1709
1670
  if (
@@ -1816,8 +1777,6 @@ def stdshade(ax=None,*args, **kwargs):
1816
1777
  else:
1817
1778
  line = ax.plot(x, yMean, color=acolor, ls=plotStyle, marker=plotMarker, **line_kws)
1818
1779
  return line[0], fill
1819
-
1820
-
1821
1780
  # =============================================================================
1822
1781
  # # for plot figures {Qiu et al.2023}
1823
1782
  # =============================================================================
@@ -1998,7 +1957,6 @@ def FuncCmpt(X1, X2, pmc='auto', pair='unpaired'):
1998
1957
  X1, X2, cfg_pmc=cfg_pmc, pair=cfg_pair)
1999
1958
  return p, output
2000
1959
 
2001
-
2002
1960
  # ======compare 2 group test===================================================
2003
1961
  # # Example
2004
1962
  # X1 = [19, 22, 16, 29, 24]
@@ -2320,7 +2278,6 @@ def FuncMultiCmpt(pmc='pmc', pair='unpair', data=None, dv=None, factor=None,
2320
2278
  'both' in cfg_pair) else None
2321
2279
  go_mix_within = factor if ('pa' in cfg_pair) or (
2322
2280
  'np' not in cfg_pair) else None
2323
-
2324
2281
  if res_tab['p-unc'][0] <= .05:
2325
2282
  # Pairwise Comparisons
2326
2283
  method_post_hoc = [
@@ -2334,7 +2291,6 @@ def FuncMultiCmpt(pmc='pmc', pair='unpair', data=None, dv=None, factor=None,
2334
2291
  for met in method_post_hoc:
2335
2292
  post_curr = pg.pairwise_tests(data=data, dv=dv, between=go_mix_between, within=go_mix_within, subject=go_subject, parametric=go_pmc, marginal=True, alpha=0.05, alternative='two-sided',
2336
2293
  padjust=met)
2337
-
2338
2294
  res_posthoc = pd.concat([res_posthoc, post_curr],
2339
2295
  ignore_index=True)
2340
2296
  else:
@@ -2354,7 +2310,6 @@ def FuncMultiCmpt(pmc='pmc', pair='unpair', data=None, dv=None, factor=None,
2354
2310
  output['res_tab']['APA'] = output['APA'] # note APA in the table
2355
2311
  # print(output['stat'])
2356
2312
  # print(output['res_tab'])
2357
-
2358
2313
  return output
2359
2314
 
2360
2315
 
@@ -2580,18 +2535,14 @@ def str2list(str_):
2580
2535
  def load_img(fpath):
2581
2536
  """
2582
2537
  Load an image from the specified file path.
2583
-
2584
2538
  Args:
2585
2539
  fpath (str): The file path to the image.
2586
-
2587
2540
  Returns:
2588
2541
  PIL.Image: The loaded image.
2589
-
2590
2542
  Raises:
2591
2543
  FileNotFoundError: If the specified file is not found.
2592
2544
  OSError: If the specified file cannot be opened or is not a valid image file.
2593
2545
  """
2594
-
2595
2546
  try:
2596
2547
  img = Image.open(fpath)
2597
2548
  return img
@@ -2604,12 +2555,10 @@ def apply_filter(img, *args):
2604
2555
  # def apply_filter(img, filter_name, filter_value=None):
2605
2556
  """
2606
2557
  Apply the specified filter to the image.
2607
-
2608
2558
  Args:
2609
2559
  img (PIL.Image): The input image.
2610
2560
  filter_name (str): The name of the filter to apply.
2611
2561
  **kwargs: Additional parameters specific to the filter.
2612
-
2613
2562
  Returns:
2614
2563
  PIL.Image: The filtered image.
2615
2564
  """
@@ -2813,10 +2762,8 @@ def imgsets(
2813
2762
  def auto_enhance(img):
2814
2763
  """
2815
2764
  Automatically enhances the image based on its characteristics.
2816
-
2817
2765
  Args:
2818
2766
  img (PIL.Image): The input image.
2819
-
2820
2767
  Returns:
2821
2768
  dict: A dictionary containing the optimal enhancement values.
2822
2769
  """
@@ -2832,47 +2779,33 @@ def imgsets(
2832
2779
  bit_depth = 16
2833
2780
  else:
2834
2781
  raise ValueError("Unsupported image mode")
2835
-
2836
2782
  # Calculate the brightness and contrast for each channel
2837
2783
  num_channels = len(img.getbands())
2838
2784
  brightness_factors = []
2839
2785
  contrast_factors = []
2840
2786
  for channel in range(num_channels):
2841
2787
  channel_histogram = img.split()[channel].histogram()
2842
- brightness = sum(i * w for i, w in enumerate(channel_histogram)) / sum(
2843
- channel_histogram
2844
- )
2788
+ brightness = sum(i * w for i, w in enumerate(channel_histogram))/sum(channel_histogram)
2845
2789
  channel_min, channel_max = img.split()[channel].getextrema()
2846
2790
  contrast = channel_max - channel_min
2847
-
2848
2791
  # Adjust calculations based on bit depth
2849
2792
  normalization_factor = 2**bit_depth - 1 # Max value for the given bit depth
2850
- brightness_factor = (
2851
- 1.0 + (brightness - normalization_factor / 2) / normalization_factor
2852
- )
2853
- contrast_factor = (
2854
- 1.0 + (contrast - normalization_factor / 2) / normalization_factor
2855
- )
2856
-
2793
+ brightness_factor = (1.0 + (brightness - normalization_factor / 2) / normalization_factor)
2794
+ contrast_factor = (1.0 + (contrast - normalization_factor / 2) / normalization_factor)
2857
2795
  brightness_factors.append(brightness_factor)
2858
2796
  contrast_factors.append(contrast_factor)
2859
-
2860
2797
  # Calculate the average brightness and contrast factors across channels
2861
2798
  avg_brightness_factor = sum(brightness_factors) / num_channels
2862
2799
  avg_contrast_factor = sum(contrast_factors) / num_channels
2863
-
2864
2800
  return {"brightness": avg_brightness_factor, "contrast": avg_contrast_factor}
2865
-
2866
2801
  # Load image if input is a file path
2867
2802
  if isinstance(img, str):
2868
2803
  img = load_img(img)
2869
-
2870
2804
  img_update = img.copy()
2871
2805
  # Auto-enhance image if requested
2872
2806
  if auto:
2873
2807
  auto_params = auto_enhance(img_update)
2874
2808
  sets.update(auto_params)
2875
-
2876
2809
  if sets is None:
2877
2810
  sets = {}
2878
2811
  for k, value in sets.items():
@@ -2947,12 +2880,9 @@ def imgsets(
2947
2880
  if len(value)==3:
2948
2881
  value+=(255,)
2949
2882
  img_update = remove(img_update, bgcolor=value)
2950
-
2951
2883
  if filter_kws:
2952
2884
  for filter_name, filter_value in filter_kws.items():
2953
2885
  img_update = apply_filter(img_update, filter_name, filter_value)
2954
-
2955
-
2956
2886
  # Display the image if requested
2957
2887
  if show:
2958
2888
  if figsize is None:
@@ -2961,7 +2891,6 @@ def imgsets(
2961
2891
  plt.figure(figsize=figsize, dpi=dpi)
2962
2892
  plt.imshow(img_update)
2963
2893
  plt.axis("on") if show_axis else plt.axis("off")
2964
-
2965
2894
  return img_update
2966
2895
  # # usage:
2967
2896
  # img = imgsets(
@@ -2982,7 +2911,6 @@ def figsets(*args):
2982
2911
  "scatter","ieee","no-latex","std-colors","high-vis","bright","dark_background","science",
2983
2912
  "high-vis","vibrant","muted","retro","grid","high-contrast","light","cjk-tc-font","cjk-kr-font",
2984
2913
  ]
2985
-
2986
2914
  def sets_priority(ax,key, value):
2987
2915
  if ("fo" in key) and (("size" in key) or ("sz" in key)):
2988
2916
  fontsize=value