py2ls 0.1.9.9__py3-none-any.whl → 0.1.10.0__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.
py2ls/batman.py
ADDED
@@ -0,0 +1,183 @@
|
|
1
|
+
import smtplib
|
2
|
+
from email.mime.text import MIMEText
|
3
|
+
from email.mime.multipart import MIMEMultipart
|
4
|
+
from email.mime.base import MIMEBase
|
5
|
+
from email import encoders
|
6
|
+
import schedule
|
7
|
+
import time
|
8
|
+
from datetime import datetime
|
9
|
+
import os
|
10
|
+
|
11
|
+
|
12
|
+
signature_styles = [
|
13
|
+
"", # none
|
14
|
+
(
|
15
|
+
"------------------------------------------------------------------------------------------------\n"
|
16
|
+
"Jianfeng Liu, PhD\n"
|
17
|
+
"Institute of Medical Psychology and Behavioural Neurobiology\n"
|
18
|
+
"University of Tübingen\n"
|
19
|
+
"Otfried-Müller-Str. 25\n"
|
20
|
+
"72076 Tübingen\n\n"
|
21
|
+
),
|
22
|
+
f"Pappelweg 8\n72076 Tübingen\n\n",
|
23
|
+
]
|
24
|
+
|
25
|
+
|
26
|
+
def email_to(**kwargs):
|
27
|
+
"""
|
28
|
+
usage:
|
29
|
+
email_to(who="example@gmail.com",
|
30
|
+
subject="test",
|
31
|
+
what="this is the body",
|
32
|
+
attachments="/Users/test.pdf")
|
33
|
+
Send an email with optional attachments.
|
34
|
+
|
35
|
+
:param who: Recipient email address
|
36
|
+
:param subject: Email subject
|
37
|
+
:param what: Email what
|
38
|
+
:param attachments: List of file paths to attach
|
39
|
+
"""
|
40
|
+
who, what, subject = None, None, None
|
41
|
+
attachments = False
|
42
|
+
pause_sec = False # default 10 seconds pause
|
43
|
+
signature = signature_styles[0]
|
44
|
+
|
45
|
+
# params config
|
46
|
+
for k, v in kwargs.items():
|
47
|
+
if any(
|
48
|
+
[
|
49
|
+
"who" in k.lower(),
|
50
|
+
"whe" in k.lower(),
|
51
|
+
all(["@" in k.lower(), "." in k.lower()]),
|
52
|
+
]
|
53
|
+
): # 'who' or "where"
|
54
|
+
who = v
|
55
|
+
if any(["sub" in k.lower(), "hea" in k.lower()]): # 'subject', 'header'
|
56
|
+
subject = v
|
57
|
+
if any(
|
58
|
+
["wha" in k.lower(), "con" in k.lower(), "bod" in k.lower()]
|
59
|
+
): # 'what','content','body'
|
60
|
+
what = v
|
61
|
+
if any(["att" in k.lower(), "fil" in k.lower()]): # 'attachments', 'file'
|
62
|
+
attachments = v # optional
|
63
|
+
if any(
|
64
|
+
["paus" in k.lower(), "tim" in k.lower(), "delay" in k.lower()]
|
65
|
+
): # 'attachments', 'file'
|
66
|
+
pause_sec = v # optional
|
67
|
+
if any(["sig" in k.lower()]): # 'attachments', 'file'
|
68
|
+
signature = v # optional
|
69
|
+
if not isinstance(v, str):
|
70
|
+
signature = signature_styles[v]
|
71
|
+
|
72
|
+
# config sender
|
73
|
+
email_address = "andyandhope@gmail.com"
|
74
|
+
email_password = "myff ltls sfym wehe" # this is fake info
|
75
|
+
|
76
|
+
# Create email message
|
77
|
+
message = MIMEMultipart()
|
78
|
+
message["From"] = email_address
|
79
|
+
message["To"] = who
|
80
|
+
message["Subject"] = subject
|
81
|
+
|
82
|
+
# add signature
|
83
|
+
if signature:
|
84
|
+
what += f"\n\n{signature}\n"
|
85
|
+
|
86
|
+
# the eamil's body
|
87
|
+
message.attach(MIMEText(what, "plain"))
|
88
|
+
|
89
|
+
# attach files
|
90
|
+
if attachments:
|
91
|
+
if isinstance(attachments, str):
|
92
|
+
attachments = [attachments]
|
93
|
+
for file in attachments:
|
94
|
+
part = MIMEBase("application", "octet-stream")
|
95
|
+
try:
|
96
|
+
with open(file, "rb") as attachment:
|
97
|
+
part.set_payload(attachment.read())
|
98
|
+
encoders.encode_base64(part)
|
99
|
+
|
100
|
+
fname = os.path.basename(file)
|
101
|
+
print(fname)
|
102
|
+
part.add_header(
|
103
|
+
"Content-Disposition", f'attachment; filename= "{fname}"'
|
104
|
+
)
|
105
|
+
message.attach(part)
|
106
|
+
except FileNotFoundError:
|
107
|
+
print(f"File not found: {file}")
|
108
|
+
except Exception as e:
|
109
|
+
print(f"Error attaching file {file}: {e}")
|
110
|
+
if pause_sec:
|
111
|
+
time.sleep(pause_sec)
|
112
|
+
# Send the email
|
113
|
+
try:
|
114
|
+
with smtplib.SMTP("smtp.gmail.com", 587) as server:
|
115
|
+
server.starttls()
|
116
|
+
server.login(email_address, email_password)
|
117
|
+
server.sendmail(email_address, who, message.as_string())
|
118
|
+
print(f"Email successfully sent to {who}")
|
119
|
+
except Exception as e:
|
120
|
+
print(f"Failed to send email: {e}")
|
121
|
+
|
122
|
+
|
123
|
+
def email_to_every(who, subject, what, when, attachments=None):
|
124
|
+
"""
|
125
|
+
Check the time and send an email when the time matches the when.
|
126
|
+
|
127
|
+
:param who: Recipient email address
|
128
|
+
:param subject: Email subject
|
129
|
+
:param what: Email what
|
130
|
+
:param when: Time to send the email in HH:MM format
|
131
|
+
:param attachments: List of file paths to attach
|
132
|
+
"""
|
133
|
+
current_time = datetime.now().strftime("%H:%M")
|
134
|
+
if current_time == when:
|
135
|
+
email_to(
|
136
|
+
who=who,
|
137
|
+
subject=subject,
|
138
|
+
what=what,
|
139
|
+
attachments=attachments,
|
140
|
+
)
|
141
|
+
|
142
|
+
|
143
|
+
# Example usage
|
144
|
+
def example_job():
|
145
|
+
# Example email details
|
146
|
+
reminder_subject = "Reminder: Important Meeting Tomorrow"
|
147
|
+
reminder_what = (
|
148
|
+
"Don't forget about the meeting tomorrow at 10 AM in the conference room."
|
149
|
+
)
|
150
|
+
who = "Jianfeng.Liu0413@gmail.com"
|
151
|
+
when = "14:30" # Send time in 24-hour format
|
152
|
+
|
153
|
+
# Optional attachments
|
154
|
+
attachments = ["path/to/attachment1.pdf", "path/to/attachment2.jpg"]
|
155
|
+
|
156
|
+
# Schedule the email
|
157
|
+
email_to_every(who, reminder_subject, reminder_what, when, attachments)
|
158
|
+
|
159
|
+
|
160
|
+
if __name__ == "__main__":
|
161
|
+
# Schedule the job to run every minute
|
162
|
+
schedule.every(1).minutes.do(example_job)
|
163
|
+
|
164
|
+
while True:
|
165
|
+
schedule.run_pending()
|
166
|
+
time.sleep(1)
|
167
|
+
|
168
|
+
# example2:
|
169
|
+
email_to(
|
170
|
+
who="Jianfeng.Liu@medizin.uni-tuebingen.de",
|
171
|
+
subj="test",
|
172
|
+
wha="this is the body",
|
173
|
+
signat="\n\n Best, Jianfeng\n",
|
174
|
+
att="/Users/macjianfeng/Dropbox/Downloads/_*_doc-xlsx/20240822-preprints_full_20190101_20201031-2.xlsx",
|
175
|
+
)
|
176
|
+
# example3:
|
177
|
+
email_to(
|
178
|
+
who="Jianfeng.Liu@medizin.uni-tuebingen.de",
|
179
|
+
subj="test",
|
180
|
+
wha="this is the test",
|
181
|
+
signat=2,
|
182
|
+
att="/Users/macjianfeng/Dropbox/Downloads/_*_doc-xlsx/20240822-preprints_full_20190101_20201031-2.xlsx",
|
183
|
+
)
|
py2ls/ich2ls.py
CHANGED
@@ -1,103 +1,212 @@
|
|
1
1
|
import numpy as np
|
2
|
+
import pandas as pd
|
2
3
|
import matplotlib.pyplot as plt
|
3
4
|
from scipy.stats import pearsonr
|
4
5
|
from PIL import Image
|
5
6
|
from skimage import filters, morphology, measure, color
|
6
7
|
|
8
|
+
# 用来处理ich图像的初级工具包
|
7
9
|
|
8
|
-
def img_preprocess(dir_img, subtract_background=True, size_obj=50, size_hole=50):
|
9
|
-
"""
|
10
|
-
Processes an image by performing thresholding, morphological operations,
|
11
|
-
and region labeling.
|
12
10
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
- size_hole: Maximum size of holes to fill (default: 50).
|
11
|
+
def open_img(dir_img, convert="gray", plot=False):
|
12
|
+
# Step 1: Load the image
|
13
|
+
image = Image.open(dir_img)
|
17
14
|
|
18
|
-
|
19
|
-
- output: Dictionary containing the overlay image, threshold value, and regions.
|
20
|
-
"""
|
21
|
-
props_list = [
|
22
|
-
"area", # Number of pixels in the region. Useful for determining the size of regions.
|
23
|
-
"area_bbox",
|
24
|
-
"area_convex",
|
25
|
-
"area_filled",
|
26
|
-
"axis_major_length", # Lengths of the major and minor axes of the ellipse that fits the region. Useful for understanding the shape's elongation and orientation.
|
27
|
-
"axis_minor_length",
|
28
|
-
"bbox", # Bounding box coordinates (min_row, min_col, max_row, max_col). Useful for spatial localization of regions.
|
29
|
-
"centroid", # Center of mass coordinates (centroid-0, centroid-1). Helps locate the center of each region.
|
30
|
-
"centroid_local",
|
31
|
-
"centroid_weighted",
|
32
|
-
"centroid_weighted_local",
|
33
|
-
"coords",
|
34
|
-
"eccentricity", # Measure of how elongated the region is. Values range from 0 (circular) to 1 (line). Useful for assessing the shape of regions.
|
35
|
-
"equivalent_diameter_area", # Diameter of a circle with the same area as the region. Provides a simple measure of size.
|
36
|
-
"euler_number",
|
37
|
-
"extent", # Ratio of the region's area to the area of its bounding box. Indicates how much of the bounding box is filled by the region.
|
38
|
-
"feret_diameter_max", # Maximum diameter of the region, providing another measure of size.
|
39
|
-
"image",
|
40
|
-
"image_convex",
|
41
|
-
"image_filled",
|
42
|
-
"image_intensity",
|
43
|
-
"inertia_tensor", # ensor describing the distribution of mass in the region, useful for more advanced shape analysis.
|
44
|
-
"inertia_tensor_eigvals",
|
45
|
-
"intensity_max", # Maximum intensity value within the region. Helps identify regions with high-intensity features.
|
46
|
-
"intensity_mean", # Average intensity value within the region. Useful for distinguishing between regions based on their brightness.
|
47
|
-
"intensity_min", # Minimum intensity value within the region. Useful for regions with varying intensity.
|
48
|
-
"intensity_std",
|
49
|
-
"label", # Unique identifier for each region.
|
50
|
-
"moments",
|
51
|
-
"moments_central",
|
52
|
-
"moments_hu", # Hu moments are a set of seven invariant features that describe the shape of the region. Useful for shape recognition and classification.
|
53
|
-
"moments_normalized",
|
54
|
-
"moments_weighted",
|
55
|
-
"moments_weighted_central",
|
56
|
-
"moments_weighted_hu",
|
57
|
-
"moments_weighted_normalized",
|
58
|
-
"orientation", # ngle of the major axis of the ellipse that fits the region. Useful for determining the orientation of elongated regions.
|
59
|
-
"perimeter", # Length of the boundary of the region. Useful for shape analysis.
|
60
|
-
"perimeter_crofton",
|
61
|
-
"slice",
|
62
|
-
"solidity", # Ratio of the area of the region to the area of its convex hull. Indicates how solid or compact a region is.
|
63
|
-
]
|
64
|
-
if isinstance(dir_img, str):
|
65
|
-
# Step 1: Load the image
|
66
|
-
image = Image.open(dir_img)
|
67
|
-
|
68
|
-
# Step 2: Convert the image to grayscale and normalize
|
15
|
+
if convert == "gray" or convert == "grey":
|
69
16
|
gray_image = image.convert("L")
|
70
17
|
image_array = np.array(gray_image)
|
18
|
+
else:
|
19
|
+
image_array = np.array(image)
|
20
|
+
if plot:
|
21
|
+
_, axs = plt.subplots(1, 2)
|
22
|
+
axs[0].imshow(image)
|
23
|
+
axs[1].imshow(image_array)
|
24
|
+
axs[0].set_title("img_raw")
|
25
|
+
axs[1].set_title(f"img_{convert}")
|
26
|
+
return image, image_array
|
27
|
+
|
28
|
+
|
29
|
+
from skimage import filters, morphology
|
30
|
+
|
31
|
+
|
32
|
+
def clean_img(
|
33
|
+
img,
|
34
|
+
method=["threshold_otsu", "objects", "holes"],
|
35
|
+
obj_min=50,
|
36
|
+
hole_min=50,
|
37
|
+
filter=None,
|
38
|
+
plot=False,
|
39
|
+
cmap="grey",
|
40
|
+
):
|
41
|
+
if isinstance(method, str):
|
42
|
+
if method == "all":
|
43
|
+
method = ["threshold_otsu", "objects", "holes"]
|
44
|
+
else:
|
45
|
+
method = [method]
|
46
|
+
if any("thr" in met or "ot" in met for met in method) and filter is None:
|
47
|
+
thr_otsu = filters.threshold_otsu(img)
|
48
|
+
img_update = img > thr_otsu
|
49
|
+
if any("obj" in met for met in method):
|
50
|
+
img_update = morphology.remove_small_objects(img_update, min_size=obj_min)
|
51
|
+
if any("hol" in met for met in method):
|
52
|
+
img_update = morphology.remove_small_holes(img_update, area_threshold=hole_min)
|
53
|
+
if ("thr" in met for met in method) and filter: # threshold
|
54
|
+
mask = (img >= filter[0]) & (img <= filter[1])
|
55
|
+
img_update = np.where(mask, img, 0)
|
56
|
+
|
57
|
+
if plot:
|
58
|
+
plt.imshow(img_update, cmap=cmap)
|
59
|
+
return img_update
|
60
|
+
|
61
|
+
|
62
|
+
from skimage import filters, segmentation
|
63
|
+
|
64
|
+
|
65
|
+
def segment_img(
|
66
|
+
img,
|
67
|
+
filter=[30, 150],
|
68
|
+
plot=False,
|
69
|
+
mode="reflect", # 'reflect' or 'constant'
|
70
|
+
method="region", # 'region' or 'edge', 'threshold'
|
71
|
+
area_min=50,
|
72
|
+
cmap="jet",
|
73
|
+
connectivity=1,
|
74
|
+
output="segmentation",
|
75
|
+
):
|
76
|
+
if "reg" in method: # region method
|
77
|
+
# 1. find an elevation map using the Sobel gradient of the image
|
78
|
+
elevation_map = filters.sobel(img, mode=mode)
|
79
|
+
# 2. find markers of the background and the coins based on the extreme parts of the histogram of gray values.
|
80
|
+
markers = np.zeros_like(img)
|
81
|
+
# Apply filtering based on provided filter values
|
82
|
+
if filter is not None:
|
83
|
+
markers[img < filter[0]] = 1
|
84
|
+
markers[img > filter[1]] = 2
|
85
|
+
else:
|
86
|
+
# If no filter is provided, set markers across the whole range of the image
|
87
|
+
markers[img == img.min()] = 1
|
88
|
+
markers[img == img.max()] = 2
|
89
|
+
# 3. watershed transform to fill regions of the elevation map starting from the markers
|
90
|
+
img_segmentation = segmentation.watershed(
|
91
|
+
elevation_map, markers=markers, connectivity=connectivity
|
92
|
+
)
|
93
|
+
if plot:
|
94
|
+
_, axs = plt.subplots(2, 2)
|
95
|
+
for i, ax in enumerate(axs.flatten().tolist()):
|
96
|
+
if i == 0:
|
97
|
+
ax.imshow(img)
|
98
|
+
ax.set_title("image")
|
99
|
+
elif i == 1:
|
100
|
+
ax.imshow(elevation_map, cmap=cmap)
|
101
|
+
ax.set_title("elevation map")
|
102
|
+
elif i == 2:
|
103
|
+
ax.imshow(markers, cmap=cmap)
|
104
|
+
ax.set_title("markers")
|
105
|
+
elif i == 3:
|
106
|
+
ax.imshow(img_segmentation, cmap=cmap)
|
107
|
+
ax.set_title("segmentation")
|
108
|
+
ax.set_axis_off()
|
109
|
+
if "el" in output:
|
110
|
+
return elevation_map
|
111
|
+
elif "mar" in output:
|
112
|
+
return markers
|
113
|
+
elif "seg" in output:
|
114
|
+
return img_segmentation
|
115
|
+
else:
|
116
|
+
return img_segmentation
|
117
|
+
elif "ed" in method: # edge
|
118
|
+
edges = cal_edges(img)
|
119
|
+
fills = fill_holes(edges)
|
120
|
+
img_segmentation = remove_holes(fills, area_min)
|
121
|
+
if plot:
|
122
|
+
_, axs = plt.subplots(2, 2)
|
123
|
+
for i, ax in enumerate(axs.flatten().tolist()):
|
124
|
+
if i == 0:
|
125
|
+
ax.imshow(img)
|
126
|
+
ax.set_title("image")
|
127
|
+
elif i == 1:
|
128
|
+
ax.imshow(edges, cmap=cmap)
|
129
|
+
ax.set_title("edges map")
|
130
|
+
elif i == 2:
|
131
|
+
ax.imshow(fills, cmap=cmap)
|
132
|
+
ax.set_title("fills")
|
133
|
+
elif i == 3:
|
134
|
+
ax.imshow(img_segmentation, cmap=cmap)
|
135
|
+
ax.set_title("segmentation")
|
136
|
+
ax.set_axis_off()
|
137
|
+
if "seg" in output:
|
138
|
+
return img_segmentation
|
139
|
+
elif "ed" in output:
|
140
|
+
return edges
|
141
|
+
elif "fill" in output:
|
142
|
+
return fills
|
143
|
+
else:
|
144
|
+
return img_segmentation
|
145
|
+
elif "thr" in method: # threshold
|
146
|
+
if filter:
|
147
|
+
mask = (img >= filter[0]) & (img <= filter[1])
|
148
|
+
img_threshold = np.where(mask, img, 0)
|
149
|
+
if plot:
|
150
|
+
plt.imshow(img_threshold, cmap=cmap)
|
151
|
+
return img_threshold
|
152
|
+
else:
|
153
|
+
return None
|
154
|
+
|
155
|
+
|
156
|
+
from skimage import measure
|
157
|
+
|
158
|
+
|
159
|
+
def label_img(img, plot=False):
|
160
|
+
img_label = measure.label(img)
|
161
|
+
if plot:
|
162
|
+
plt.imshow(img_label)
|
163
|
+
return img_label
|
164
|
+
|
165
|
+
|
166
|
+
def img_process(img, **kwargs):
|
167
|
+
convert = "gray"
|
168
|
+
method_clean_img = ["threshold_otsu", "objects", "holes"]
|
169
|
+
obj_min_clean_img = 50
|
170
|
+
hole_min_clean_img = 50
|
171
|
+
plot = True
|
172
|
+
for k, v in kwargs.items():
|
173
|
+
if "convert" in k.lower():
|
174
|
+
convert = v
|
175
|
+
if "met" in k.lower() and any(
|
176
|
+
["clean" in k.lower(), "rem" in k.lower(), "rm" in k.lower()]
|
177
|
+
):
|
178
|
+
method_clean_img = v
|
179
|
+
if "obj" in k.lower() and any(
|
180
|
+
["clean" in k.lower(), "rem" in k.lower(), "rm" in k.lower()]
|
181
|
+
):
|
182
|
+
obj_min_clean_img = v
|
183
|
+
if "hol" in k.lower() and any(
|
184
|
+
["clean" in k.lower(), "rem" in k.lower(), "rm" in k.lower()]
|
185
|
+
):
|
186
|
+
hole_min_clean_img = v
|
187
|
+
if "plot" in k.lower():
|
188
|
+
plot = v
|
189
|
+
|
190
|
+
if isinstance(img, str):
|
191
|
+
image, image_array = open_img(img, convert=convert)
|
71
192
|
normalized_image = image_array / 255.0
|
72
193
|
else:
|
73
|
-
cleaned_image =
|
194
|
+
cleaned_image = img
|
74
195
|
image_array = cleaned_image
|
75
196
|
normalized_image = cleaned_image
|
76
197
|
image = cleaned_image
|
77
|
-
binary_image = cleaned_image
|
78
|
-
thr_val = None
|
79
|
-
if subtract_background:
|
80
|
-
# Step 3: Apply thresholding to segment the image
|
81
|
-
thr_val = filters.threshold_otsu(image_array)
|
82
|
-
print(f"Threshold value is: {thr_val}")
|
83
|
-
|
84
|
-
# Apply thresholds and generate binary images
|
85
|
-
binary_image = image_array > thr_val
|
86
|
-
|
87
|
-
# Step 4: Perform morphological operations to clean the image
|
88
|
-
# Remove small objects and fill small holes
|
89
|
-
cleaned_image_rm_min_obj = morphology.remove_small_objects(
|
90
|
-
binary_image, min_size=size_obj
|
91
|
-
)
|
92
|
-
cleaned_image = morphology.remove_small_holes(
|
93
|
-
cleaned_image_rm_min_obj, area_threshold=size_hole
|
94
|
-
)
|
95
198
|
|
199
|
+
# Remove small objects and fill small holes
|
200
|
+
cleaned_image = clean_img(
|
201
|
+
img=image_array,
|
202
|
+
method=method_clean_img,
|
203
|
+
obj_min=obj_min_clean_img,
|
204
|
+
hole_min=hole_min_clean_img,
|
205
|
+
plot=False,
|
206
|
+
)
|
96
207
|
# Label the regions
|
97
|
-
label_image =
|
98
|
-
|
99
|
-
# Optional: Overlay labels on the original image
|
100
|
-
overlay_image = color.label2rgb(label_image, image_array)
|
208
|
+
label_image = label_img(cleaned_image)
|
209
|
+
overlay_image = overlay_imgs(label_image, image=image_array)
|
101
210
|
regions = measure.regionprops(label_image, intensity_image=image_array)
|
102
211
|
region_props = measure.regionprops_table(
|
103
212
|
label_image, intensity_image=image_array, properties=props_list
|
@@ -108,18 +217,137 @@ def img_preprocess(dir_img, subtract_background=True, size_obj=50, size_hole=50)
|
|
108
217
|
"img": image,
|
109
218
|
"img_array": image_array,
|
110
219
|
"img_scale": normalized_image,
|
111
|
-
"img_binary": binary_image,
|
112
220
|
"img_clean": cleaned_image,
|
113
221
|
"img_label": label_image,
|
114
222
|
"img_overlay": overlay_image,
|
115
|
-
"thr_val": thr_val,
|
116
223
|
"regions": regions,
|
117
224
|
"df_regions": df_regions,
|
118
225
|
}
|
119
|
-
|
226
|
+
if plot:
|
227
|
+
imgs = []
|
228
|
+
[imgs.append(i) for i in list(output.keys()) if "img" in i]
|
229
|
+
for img_ in imgs:
|
230
|
+
plt.figure()
|
231
|
+
plt.imshow(output[img_])
|
232
|
+
plt.title(img_)
|
120
233
|
return output
|
121
234
|
|
122
235
|
|
236
|
+
# def img_preprocess(dir_img, subtract_background=True, size_obj=50, size_hole=50,**kwargs):
|
237
|
+
# """
|
238
|
+
# Processes an image by performing thresholding, morphological operations,
|
239
|
+
# and region labeling.
|
240
|
+
|
241
|
+
# Parameters:
|
242
|
+
# - dir_img: Path to the image file.
|
243
|
+
# - size_obj: Minimum size of objects to keep (default: 50).
|
244
|
+
# - size_hole: Maximum size of holes to fill (default: 50).
|
245
|
+
|
246
|
+
# Returns:
|
247
|
+
# - output: Dictionary containing the overlay image, threshold value, and regions.
|
248
|
+
# """
|
249
|
+
# props_list = [
|
250
|
+
# "area", # Number of pixels in the region. Useful for determining the size of regions.
|
251
|
+
# "area_bbox",
|
252
|
+
# "area_convex",
|
253
|
+
# "area_filled",
|
254
|
+
# "axis_major_length", # Lengths of the major and minor axes of the ellipse that fits the region. Useful for understanding the shape's elongation and orientation.
|
255
|
+
# "axis_minor_length",
|
256
|
+
# "bbox", # Bounding box coordinates (min_row, min_col, max_row, max_col). Useful for spatial localization of regions.
|
257
|
+
# "centroid", # Center of mass coordinates (centroid-0, centroid-1). Helps locate the center of each region.
|
258
|
+
# "centroid_local",
|
259
|
+
# "centroid_weighted",
|
260
|
+
# "centroid_weighted_local",
|
261
|
+
# "coords",
|
262
|
+
# "eccentricity", # Measure of how elongated the region is. Values range from 0 (circular) to 1 (line). Useful for assessing the shape of regions.
|
263
|
+
# "equivalent_diameter_area", # Diameter of a circle with the same area as the region. Provides a simple measure of size.
|
264
|
+
# "euler_number",
|
265
|
+
# "extent", # Ratio of the region's area to the area of its bounding box. Indicates how much of the bounding box is filled by the region.
|
266
|
+
# "feret_diameter_max", # Maximum diameter of the region, providing another measure of size.
|
267
|
+
# "image",
|
268
|
+
# "image_convex",
|
269
|
+
# "image_filled",
|
270
|
+
# "image_intensity",
|
271
|
+
# "inertia_tensor", # ensor describing the distribution of mass in the region, useful for more advanced shape analysis.
|
272
|
+
# "inertia_tensor_eigvals",
|
273
|
+
# "intensity_max", # Maximum intensity value within the region. Helps identify regions with high-intensity features.
|
274
|
+
# "intensity_mean", # Average intensity value within the region. Useful for distinguishing between regions based on their brightness.
|
275
|
+
# "intensity_min", # Minimum intensity value within the region. Useful for regions with varying intensity.
|
276
|
+
# "intensity_std",
|
277
|
+
# "label", # Unique identifier for each region.
|
278
|
+
# "moments",
|
279
|
+
# "moments_central",
|
280
|
+
# "moments_hu", # Hu moments are a set of seven invariant features that describe the shape of the region. Useful for shape recognition and classification.
|
281
|
+
# "moments_normalized",
|
282
|
+
# "moments_weighted",
|
283
|
+
# "moments_weighted_central",
|
284
|
+
# "moments_weighted_hu",
|
285
|
+
# "moments_weighted_normalized",
|
286
|
+
# "orientation", # ngle of the major axis of the ellipse that fits the region. Useful for determining the orientation of elongated regions.
|
287
|
+
# "perimeter", # Length of the boundary of the region. Useful for shape analysis.
|
288
|
+
# "perimeter_crofton",
|
289
|
+
# "slice",
|
290
|
+
# "solidity", # Ratio of the area of the region to the area of its convex hull. Indicates how solid or compact a region is.
|
291
|
+
# ]
|
292
|
+
# if isinstance(dir_img, str):
|
293
|
+
# # Step 1: Load the image
|
294
|
+
# image = Image.open(dir_img)
|
295
|
+
|
296
|
+
# # Step 2: Convert the image to grayscale and normalize
|
297
|
+
# gray_image = image.convert("L")
|
298
|
+
# image_array = np.array(gray_image)
|
299
|
+
# normalized_image = image_array / 255.0
|
300
|
+
# else:
|
301
|
+
# cleaned_image = dir_img
|
302
|
+
# image_array = cleaned_image
|
303
|
+
# normalized_image = cleaned_image
|
304
|
+
# image = cleaned_image
|
305
|
+
# binary_image = cleaned_image
|
306
|
+
# thr_val = None
|
307
|
+
# if subtract_background:
|
308
|
+
# # Step 3: Apply thresholding to segment the image
|
309
|
+
# thr_val = filters.threshold_otsu(image_array)
|
310
|
+
# print(f"Threshold value is: {thr_val}")
|
311
|
+
|
312
|
+
# # Apply thresholds and generate binary images
|
313
|
+
# binary_image = image_array > thr_val
|
314
|
+
|
315
|
+
# # Step 4: Perform morphological operations to clean the image
|
316
|
+
# # Remove small objects and fill small holes
|
317
|
+
# cleaned_image_rm_min_obj = morphology.remove_small_objects(
|
318
|
+
# binary_image, min_size=size_obj
|
319
|
+
# )
|
320
|
+
# cleaned_image = morphology.remove_small_holes(
|
321
|
+
# cleaned_image_rm_min_obj, area_threshold=size_hole
|
322
|
+
# )
|
323
|
+
|
324
|
+
# # Label the regions
|
325
|
+
# label_image = label_img(cleaned_image)
|
326
|
+
|
327
|
+
# # Optional: Overlay labels on the original image
|
328
|
+
# overlay_image = color.label2rgb(label_image, image_array)
|
329
|
+
# regions = measure.regionprops(label_image, intensity_image=image_array)
|
330
|
+
# region_props = measure.regionprops_table(
|
331
|
+
# label_image, intensity_image=image_array, properties=props_list
|
332
|
+
# )
|
333
|
+
# df_regions = pd.DataFrame(region_props)
|
334
|
+
# # Pack the results into a single output variable (dictionary)
|
335
|
+
# output = {
|
336
|
+
# "img": image,
|
337
|
+
# "img_array": image_array,
|
338
|
+
# "img_scale": normalized_image,
|
339
|
+
# "img_binary": binary_image,
|
340
|
+
# "img_clean": cleaned_image,
|
341
|
+
# "img_label": label_image,
|
342
|
+
# "img_overlay": overlay_image,
|
343
|
+
# "thr_val": thr_val,
|
344
|
+
# "regions": regions,
|
345
|
+
# "df_regions": df_regions,
|
346
|
+
# }
|
347
|
+
|
348
|
+
# return output
|
349
|
+
|
350
|
+
|
123
351
|
def cal_pearson(img1, img2):
|
124
352
|
"""Compute Pearson correlation coefficient between two images."""
|
125
353
|
img1_flat = img1.flatten()
|
@@ -134,3 +362,229 @@ def cal_manders(img1, img2):
|
|
134
362
|
img2_binary = img2 > filters.threshold_otsu(img2)
|
135
363
|
overlap_coef = np.sum(img1_binary & img2_binary) / np.sum(img1_binary)
|
136
364
|
return overlap_coef
|
365
|
+
|
366
|
+
|
367
|
+
def overlay_imgs(
|
368
|
+
*imgs,
|
369
|
+
image=None,
|
370
|
+
colors=None,
|
371
|
+
alpha=0.3,
|
372
|
+
bg_label=0,
|
373
|
+
bg_color=(0, 0, 0),
|
374
|
+
image_alpha=1,
|
375
|
+
kind="overlay",
|
376
|
+
saturation=0,
|
377
|
+
channel_axis=-1,
|
378
|
+
):
|
379
|
+
# Ensure all input images have the same shape
|
380
|
+
print(
|
381
|
+
f'\nusage:\nich2ls.overlay_imgs(res_b["img_binary"], res_r["img_binary"], bg_label=0)'
|
382
|
+
)
|
383
|
+
shapes = [img.shape for img in imgs]
|
384
|
+
if not all(shape == shapes[0] for shape in shapes):
|
385
|
+
raise ValueError("All input images must have the same shape")
|
386
|
+
|
387
|
+
# If no image is provided, use the first input image as the base
|
388
|
+
if image is None:
|
389
|
+
image = imgs[0]
|
390
|
+
|
391
|
+
# Combine the images into a label, with unique multipliers for each image
|
392
|
+
label = sum((img.astype(np.uint) * (i + 1) for i, img in enumerate(imgs)))
|
393
|
+
|
394
|
+
# Create the overlay image
|
395
|
+
overlay_image = color.label2rgb(
|
396
|
+
label,
|
397
|
+
image=image,
|
398
|
+
bg_label=bg_label,
|
399
|
+
colors=colors,
|
400
|
+
alpha=alpha,
|
401
|
+
bg_color=bg_color,
|
402
|
+
image_alpha=image_alpha,
|
403
|
+
saturation=saturation,
|
404
|
+
kind=kind,
|
405
|
+
channel_axis=channel_axis, # Corrected from saturation to channel_axis
|
406
|
+
)
|
407
|
+
|
408
|
+
return overlay_image
|
409
|
+
|
410
|
+
|
411
|
+
from skimage import exposure
|
412
|
+
|
413
|
+
|
414
|
+
# Comparing edge-based and region-based segmentation
|
415
|
+
def draw_hist(img, ax=None, **kwargs):
|
416
|
+
"""
|
417
|
+
_, axs = plt.subplots(1, 2)
|
418
|
+
draw_hist(image, c="r", ax=axs[1], lw=2, ls=":")
|
419
|
+
"""
|
420
|
+
print(f"img type: {type(img)}")
|
421
|
+
if not isinstance(img, np.ndarray):
|
422
|
+
img = np.array(img)
|
423
|
+
hist, hist_centers = exposure.histogram(img)
|
424
|
+
if ax is None:
|
425
|
+
ax = plt.gca()
|
426
|
+
ax.plot(hist_centers, hist, **kwargs)
|
427
|
+
|
428
|
+
|
429
|
+
from skimage import feature
|
430
|
+
|
431
|
+
|
432
|
+
# delineate the contours of the coins using edge-based segmentation
|
433
|
+
def cal_edges(img, plot=False, cmap=plt.cm.gray):
|
434
|
+
edges = feature.canny(img)
|
435
|
+
if plot:
|
436
|
+
plt.imshow(edges, cmap=cmap)
|
437
|
+
return edges
|
438
|
+
|
439
|
+
|
440
|
+
from scipy import ndimage as ndi
|
441
|
+
|
442
|
+
|
443
|
+
# These contours are then filled using mathematical morphology.
|
444
|
+
def fill_holes(img, plot=False):
|
445
|
+
img_fill_holes = ndi.binary_fill_holes(img)
|
446
|
+
if plot:
|
447
|
+
plt.imshow(img_fill_holes, cmap=plt.cm.gray)
|
448
|
+
return img_fill_holes
|
449
|
+
|
450
|
+
|
451
|
+
from skimage import morphology
|
452
|
+
|
453
|
+
|
454
|
+
def remove_holes(img, size=50, plot=False):
|
455
|
+
img_rm_holes = morphology.remove_small_objects(img, size)
|
456
|
+
if plot:
|
457
|
+
plt.imshow(img_rm_holes, cmap=plt.cm.gray)
|
458
|
+
return img_rm_holes
|
459
|
+
|
460
|
+
|
461
|
+
import matplotlib.patches as mpatches
|
462
|
+
from skimage import measure, color
|
463
|
+
|
464
|
+
|
465
|
+
def draw_bbox(
|
466
|
+
img,
|
467
|
+
df=None,
|
468
|
+
img_label=None,
|
469
|
+
img_label2rgb=None,
|
470
|
+
show=True, # plot the image
|
471
|
+
bg_alpha=1, # the alpha of the bg image
|
472
|
+
area_min=1,
|
473
|
+
area_max=None,
|
474
|
+
fill=False,
|
475
|
+
edgecolor="red",
|
476
|
+
linewidth=2,
|
477
|
+
ax=None,
|
478
|
+
**kwargs,
|
479
|
+
):
|
480
|
+
"""
|
481
|
+
ich2ls.draw_bbox(
|
482
|
+
res["img_label"], fill=False, color="r", lw=1, edgecolor="w", alpha=0.4)
|
483
|
+
"""
|
484
|
+
if ax is None:
|
485
|
+
ax = plt.gca()
|
486
|
+
if img_label is None:
|
487
|
+
img_label = measure.label(img)
|
488
|
+
if isinstance(show, bool):
|
489
|
+
if show:
|
490
|
+
if img_label2rgb is None:
|
491
|
+
img_label2rgb = color.label2rgb(img_label, image=img, bg_label=0)
|
492
|
+
ax.imshow(img_label2rgb, alpha=bg_alpha)
|
493
|
+
elif isinstance(show, str):
|
494
|
+
if "raw" in show:
|
495
|
+
ax.imshow(img, alpha=bg_alpha)
|
496
|
+
elif "label" in show:
|
497
|
+
ax.imshow(img_label, alpha=bg_alpha)
|
498
|
+
elif "rgb" in show:
|
499
|
+
if img_label2rgb is None:
|
500
|
+
img_label2rgb = color.label2rgb(img_label, image=img, bg_label=0)
|
501
|
+
ax.imshow(img_label2rgb, alpha=bg_alpha)
|
502
|
+
elif "no" in show.lower():
|
503
|
+
pass
|
504
|
+
num = 0
|
505
|
+
if df is None:
|
506
|
+
for region in measure.regionprops(img_label):
|
507
|
+
# take regions with large enough areas
|
508
|
+
if area_max is None:
|
509
|
+
area_max = np.inf
|
510
|
+
if area_min <= region.area <= area_max:
|
511
|
+
minr, minc, maxr, maxc = region.bbox
|
512
|
+
rect = mpatches.Rectangle(
|
513
|
+
(minc, minr),
|
514
|
+
maxc - minc,
|
515
|
+
maxr - minr,
|
516
|
+
fill=fill,
|
517
|
+
edgecolor=edgecolor,
|
518
|
+
linewidth=linewidth,
|
519
|
+
**kwargs,
|
520
|
+
)
|
521
|
+
ax.add_patch(rect)
|
522
|
+
num += 1
|
523
|
+
else:
|
524
|
+
# Iterate over each row in the DataFrame and draw the bounding boxes
|
525
|
+
for _, row in df.iterrows():
|
526
|
+
minr = row["bbox-0"]
|
527
|
+
minc = row["bbox-1"]
|
528
|
+
maxr = row["bbox-2"]
|
529
|
+
maxc = row["bbox-3"]
|
530
|
+
|
531
|
+
# Optionally filter by area if needed
|
532
|
+
area = (maxr - minr) * (maxc - minc)
|
533
|
+
if area >= area_min:
|
534
|
+
rect = mpatches.Rectangle(
|
535
|
+
(minc, minr),
|
536
|
+
maxc - minc,
|
537
|
+
maxr - minr,
|
538
|
+
fill=fill,
|
539
|
+
edgecolor=edgecolor,
|
540
|
+
linewidth=linewidth,
|
541
|
+
**kwargs,
|
542
|
+
)
|
543
|
+
ax.add_patch(rect)
|
544
|
+
num += 1
|
545
|
+
return num
|
546
|
+
|
547
|
+
|
548
|
+
props_list = [
|
549
|
+
"area", # Number of pixels in the region. Useful for determining the size of regions.
|
550
|
+
"area_bbox",
|
551
|
+
"area_convex",
|
552
|
+
"area_filled",
|
553
|
+
"axis_major_length", # Lengths of the major and minor axes of the ellipse that fits the region. Useful for understanding the shape's elongation and orientation.
|
554
|
+
"axis_minor_length",
|
555
|
+
"bbox", # Bounding box coordinates (min_row, min_col, max_row, max_col). Useful for spatial localization of regions.
|
556
|
+
"centroid", # Center of mass coordinates (centroid-0, centroid-1). Helps locate the center of each region.
|
557
|
+
"centroid_local",
|
558
|
+
"centroid_weighted",
|
559
|
+
"centroid_weighted_local",
|
560
|
+
"coords",
|
561
|
+
"eccentricity", # Measure of how elongated the region is. Values range from 0 (circular) to 1 (line). Useful for assessing the shape of regions.
|
562
|
+
"equivalent_diameter_area", # Diameter of a circle with the same area as the region. Provides a simple measure of size.
|
563
|
+
"euler_number",
|
564
|
+
"extent", # Ratio of the region's area to the area of its bounding box. Indicates how much of the bounding box is filled by the region.
|
565
|
+
"feret_diameter_max", # Maximum diameter of the region, providing another measure of size.
|
566
|
+
"image",
|
567
|
+
"image_convex",
|
568
|
+
"image_filled",
|
569
|
+
"image_intensity",
|
570
|
+
"inertia_tensor", # ensor describing the distribution of mass in the region, useful for more advanced shape analysis.
|
571
|
+
"inertia_tensor_eigvals",
|
572
|
+
"intensity_max", # Maximum intensity value within the region. Helps identify regions with high-intensity features.
|
573
|
+
"intensity_mean", # Average intensity value within the region. Useful for distinguishing between regions based on their brightness.
|
574
|
+
"intensity_min", # Minimum intensity value within the region. Useful for regions with varying intensity.
|
575
|
+
"intensity_std",
|
576
|
+
"label", # Unique identifier for each region.
|
577
|
+
"moments",
|
578
|
+
"moments_central",
|
579
|
+
"moments_hu", # Hu moments are a set of seven invariant features that describe the shape of the region. Useful for shape recognition and classification.
|
580
|
+
"moments_normalized",
|
581
|
+
"moments_weighted",
|
582
|
+
"moments_weighted_central",
|
583
|
+
"moments_weighted_hu",
|
584
|
+
"moments_weighted_normalized",
|
585
|
+
"orientation", # ngle of the major axis of the ellipse that fits the region. Useful for determining the orientation of elongated regions.
|
586
|
+
"perimeter", # Length of the boundary of the region. Useful for shape analysis.
|
587
|
+
"perimeter_crofton",
|
588
|
+
"slice",
|
589
|
+
"solidity", # Ratio of the area of the region to the area of its convex hull. Indicates how solid or compact a region is.
|
590
|
+
]
|
py2ls/netfinder.py
CHANGED
@@ -671,8 +671,8 @@ def downloader(
|
|
671
671
|
if dir_save:
|
672
672
|
if rm_folder:
|
673
673
|
ips.rm_folder(dir_save)
|
674
|
-
if verbose:
|
675
|
-
|
674
|
+
# if verbose:
|
675
|
+
# print(f"\n... attempting to download to local\n")
|
676
676
|
fnames = [file_link.split("/")[-1] for file_link in file_links_all]
|
677
677
|
|
678
678
|
for idx, file_link in enumerate(file_links_all):
|
@@ -688,6 +688,9 @@ def downloader(
|
|
688
688
|
ext = next(
|
689
689
|
(ftype for ftype in kind if ftype in file_link), None
|
690
690
|
)
|
691
|
+
if ext is None:
|
692
|
+
ext = kind_
|
693
|
+
print("ehereerere", ext)
|
691
694
|
if ext:
|
692
695
|
corrected_fname = fname_corrector(fnames[idx], ext)
|
693
696
|
corrected_fname = check_and_modify_filename(
|
py2ls/plot.py
CHANGED
@@ -1823,15 +1823,43 @@ def get_color(
|
|
1823
1823
|
cmap = "grey"
|
1824
1824
|
# Determine color list based on cmap parameter
|
1825
1825
|
if "aut" in cmap:
|
1826
|
-
|
1827
|
-
"#
|
1828
|
-
|
1829
|
-
"#
|
1830
|
-
|
1831
|
-
"#
|
1832
|
-
|
1833
|
-
"#
|
1834
|
-
|
1826
|
+
if n == 1:
|
1827
|
+
colorlist = ["#3A4453"]
|
1828
|
+
elif n == 2:
|
1829
|
+
colorlist = ["#3A4453", "#DF5932"]
|
1830
|
+
elif n == 3:
|
1831
|
+
colorlist = ["#3A4453", "#DF5932", "#299D8F"]
|
1832
|
+
elif n == 4:
|
1833
|
+
# colorlist = ["#3A4453", "#DF5932", "#EBAA00", "#0B4083"]
|
1834
|
+
colorlist = ["#81C6BD", "#FBAF63", "#F2675B", "#72A1C9"]
|
1835
|
+
elif n == 5:
|
1836
|
+
colorlist = [
|
1837
|
+
"#3A4453",
|
1838
|
+
"#427AB2",
|
1839
|
+
"#F09148",
|
1840
|
+
"#DBDB8D",
|
1841
|
+
"#C59D94",
|
1842
|
+
"#AFC7E8",
|
1843
|
+
]
|
1844
|
+
elif n == 6:
|
1845
|
+
colorlist = [
|
1846
|
+
"#3A4453",
|
1847
|
+
"#427AB2",
|
1848
|
+
"#F09148",
|
1849
|
+
"#DBDB8D",
|
1850
|
+
"#C59D94",
|
1851
|
+
"#E53528",
|
1852
|
+
]
|
1853
|
+
else:
|
1854
|
+
colorlist = [
|
1855
|
+
"#474747",
|
1856
|
+
"#FF2C00",
|
1857
|
+
"#0C5DA5",
|
1858
|
+
"#845B97",
|
1859
|
+
"#58BBCC",
|
1860
|
+
"#FF9500",
|
1861
|
+
"#D57DBE",
|
1862
|
+
]
|
1835
1863
|
by = "start"
|
1836
1864
|
elif any(["cub" in cmap.lower(), "sns" in cmap.lower()]):
|
1837
1865
|
if kwargs:
|
@@ -1909,6 +1937,10 @@ import matplotlib.pyplot as plt
|
|
1909
1937
|
|
1910
1938
|
|
1911
1939
|
def stdshade(ax=None, *args, **kwargs):
|
1940
|
+
"""
|
1941
|
+
usage:
|
1942
|
+
plot.stdshade(data_array, c=clist[1], lw=2, ls="-.", alpha=0.2)
|
1943
|
+
"""
|
1912
1944
|
# Separate kws_line and kws_fill if necessary
|
1913
1945
|
kws_line = kwargs.pop("kws_line", {})
|
1914
1946
|
kws_fill = kwargs.pop("kws_fill", {})
|
@@ -1946,8 +1978,9 @@ def stdshade(ax=None, *args, **kwargs):
|
|
1946
1978
|
ax = plt.gca()
|
1947
1979
|
if ax is None:
|
1948
1980
|
ax = plt.gca()
|
1949
|
-
alpha = 0.
|
1950
|
-
acolor = "k"
|
1981
|
+
alpha = kwargs.get("alpha", 0.2)
|
1982
|
+
acolor = kwargs.get("color", "k")
|
1983
|
+
acolor = kwargs.get("c", "k")
|
1951
1984
|
paraStdSem = "sem"
|
1952
1985
|
plotStyle = "-"
|
1953
1986
|
plotMarker = "none"
|
@@ -144,6 +144,7 @@ py2ls/.gitignore,sha256=y7GvbD_zZkjPVVIue8AyiuFkDMuUbvMaV65Lgu89To8,2763
|
|
144
144
|
py2ls/LICENSE,sha256=UOZ1F5fFDe3XXvG4oNnkL1-Ecun7zpHzRxjp-XsMeAo,11324
|
145
145
|
py2ls/README.md,sha256=CwvJWAnSXnCnrVHlnEbrxxi6MbjbE_MT6DH2D53S818,11572
|
146
146
|
py2ls/__init__.py,sha256=Nn8jTIvySX7t7DMJ8VNRVctTStgXGjHldOIdZ35PdW8,165
|
147
|
+
py2ls/batman.py,sha256=CSM3PxXE4Qpt_yVfaAgMUAGZuJCG_PGkENjG_Mjev4k,5717
|
147
148
|
py2ls/brain_atlas.py,sha256=w1o5EelRjq89zuFJUNSz4Da8HnTCwAwDAZ4NU4a-bAY,5486
|
148
149
|
py2ls/chat.py,sha256=Yr22GoIvoWhpV3m4fdwV_I0Mn77La346_ymSinR-ORA,3793
|
149
150
|
py2ls/correlators.py,sha256=RbOaJIPLCHJtUm5SFi_4dCJ7VFUPWR0PErfK3K26ad4,18243
|
@@ -176,15 +177,15 @@ py2ls/db2ls.py,sha256=MMfFX47aIPIyu7fU9aPvX9lbPRPYOpJ_VXwlnWk-8qo,13615
|
|
176
177
|
py2ls/doc.py,sha256=xN3g1OWfoaGUhikbJ0NqbN5eKy1VZVvWwRlhHMgyVEc,4243
|
177
178
|
py2ls/export_requirements.py,sha256=x2WgUF0jYKz9GfA1MVKN-MdsM-oQ8yUeC6Ua8oCymio,2325
|
178
179
|
py2ls/freqanalysis.py,sha256=F4218VSPbgL5tnngh6xNCYuNnfR-F_QjECUUxrPYZss,32594
|
179
|
-
py2ls/ich2ls.py,sha256=
|
180
|
+
py2ls/ich2ls.py,sha256=3E9R8oVpyYZXH5PiIQgT3CN5NxLe4Dwtm2LwaeacE6I,21381
|
180
181
|
py2ls/ips.py,sha256=HbktFzKIszBHtB3DtyUCCM6xj9NJZAz38ZCcIomjBFs,105439
|
181
|
-
py2ls/netfinder.py,sha256=
|
182
|
-
py2ls/plot.py,sha256=
|
182
|
+
py2ls/netfinder.py,sha256=xma9YoBxY4GcgoyG4YXEOU8oKPYByIt0uWqPyshHt8s,50812
|
183
|
+
py2ls/plot.py,sha256=9z0VPvMTFsuYKakuHjTGKK6UtiQylM3-WCxbNEKxTos,95283
|
183
184
|
py2ls/setuptools-70.1.0-py3-none-any.whl,sha256=2bi3cUVal8ip86s0SOvgspteEF8SKLukECi-EWmFomc,882588
|
184
185
|
py2ls/sleep_events_detectors.py,sha256=bQA3HJqv5qnYKJJEIhCyhlDtkXQfIzqksnD0YRXso68,52145
|
185
186
|
py2ls/stats.py,sha256=fJmXQ9Lq460StOn-kfEljE97cySq7876HUPTnpB5hLs,38123
|
186
187
|
py2ls/translator.py,sha256=bc5FB-wqC4TtQz9gyCP1mE38HqNRJ_pmuRIgKnAlMzM,30581
|
187
188
|
py2ls/wb_detector.py,sha256=7y6TmBUj9exCZeIgBAJ_9hwuhkDh1x_-yg4dvNY1_GQ,6284
|
188
|
-
py2ls-0.1.
|
189
|
-
py2ls-0.1.
|
190
|
-
py2ls-0.1.
|
189
|
+
py2ls-0.1.10.0.dist-info/METADATA,sha256=76w1Clumy3D_fhABBpVwMaJV_49n-MJnOVRHW3wiaJY,20018
|
190
|
+
py2ls-0.1.10.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
191
|
+
py2ls-0.1.10.0.dist-info/RECORD,,
|
File without changes
|