نویسنده (ها): Microbioscopicdata (توسط الکساندروس Athanasopoulos)
در ابتدا منتشر شده در به سمت هوش مصنوعیبشر
به آموزش دوم در سری ما ، “تشخیص هسته و اندازه گیری فلورسانس در پایتون” خوش آمدید. در این آموزش ، ما بر اندازه گیری شدت فلورسانس از کانال GFP ، استخراج داده های مربوطه و انجام یک تجزیه و تحلیل دقیق برای به دست آوردن بینش های بیولوژیکی معنی دار متمرکز خواهیم شد.
برای بهره مندی کامل از این آموزش ، داشتن درک اساسی از برنامه نویسی پایتون و همچنین آشنایی با میکروسکوپ فلورسانس ، از جمله اصول استفاده از پروتئین های فلورسنت مانند GFP (پروتئین فلورسنت سبز) مفید است.
در آموزش قبلی ، ما از تصاویر سلولهای فیبروبلاست استفاده کردیم که هسته ها با DAPI ، یک رنگ فلورسنت (کانال آبی) که به DNA متصل می شود ، و پروتئین مورد علاقه ای که در سیتوپلاسم و هسته وجود دارد ، در کانال سبز تشخیص داده می شود. ما با پردازش تصاویر برای افزایش کیفیت داده ها شروع کردیم. ما برای کاهش سر و صدا از هموار سازی گاوسی با مقادیر مختلف سیگما استفاده کردیم و از روشهای آستانه برای تمایز مؤثر هسته ها از پس زمینه استفاده کردیم. علاوه بر این ، ما در مورد تکنیک های پس از پردازش ، مانند از بین بردن مصنوعات کوچک ، برای اصلاح بیشتر نتایج تقسیم بندی بحث کردیم.
کد زیر (از اولین آموزش ما) به طور موثری بخش ها و تجسم هسته ها در تصاویر میکروسکوپ فلورسانس را نشان می دهد و بینش روشنی در مورد توزیع و شدت ویژگی های شناسایی شده ارائه می دهد. مرحله بعدی در اندازه گیری فلورسانس ، برچسب زدن هسته های تقسیم شده است.
from skimage import io, filters, morphology, measure, segmentation, color
from skimage.measure import regionprops
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
# Set option to display all columns and rows in Pandas DataFrames
pd.set_option('display.max_columns', None)
pd.set_option('display.max_rows', None)# Load the multi-channel TIFF image
image = io.imread('fibro_nuclei.tif')
# Separate the GFP channel (assuming channel 0 is GFP)
channel1 = image[:, 0, :, :] # GFP channel
# Perform Maximum Intensity Projection (MIP) on GFP channel
channel1_max_projection = np.max(channel1, axis=0)
# Separate the DAPI channel (assuming channel 1 is DAPI)
channel2 = image[:, 1, :, :] # DAPI channel
# Perform Maximum Intensity Projection (MIP) on DAPI channel
channel2_max_projection = np.max(channel2, axis=0)
# Apply Gaussian smoothing to the DAPI MIP
smoothed_image = filters.gaussian(channel2_max_projection, sigma=5)
# Apply Otsu's method to find the optimal threshold and create a binary mask
threshold_value = filters.threshold_otsu(smoothed_image)
binary_mask = smoothed_image > threshold_value
# Create subplots with shared x-axis and y-axis
fig, (ax1, ax2) = plt.subplots(1, 2, sharex=True, sharey=True, figsize=(10, 10))
# Visualize the Maximum Intensity Projection (MIP) for the DAPI channel
ax1.imshow(channel2_max_projection, cmap='gray')
ax1.set_title('Maximum Intensity Projection (DAPI Channel)')
# Visualize the binary mask obtained after thresholding the smoothed DAPI MIP
ax2.imshow(binary_mask, cmap='gray')
ax2.set_title('Binary Mask (After Thresholding)')
# Adjust layout to prevent overlap
plt.tight_layout()
# Display the plots
plt.show()
برچسب زدن هسته های تقسیم شده
برچسب زدن ماسک باینری یک گام مهم در تجزیه و تحلیل تصویر است. هنگامی که ما آستانه را روی یک تصویر انجام می دهیم ، نتیجه یک ماسک باینری است (همچنین به آموزش قبلی ما نیز مراجعه کنید) که پیکسل ها به عنوان پیش زمینه/درست (به عنوان مثال ، هسته) یا پس زمینه/کاذب طبقه بندی می شوند. با این حال ، این ماسک باینری به تنهایی بین هسته های مختلف فردی تمایز قائل نمی شود – به سادگی نشان می دهد که پیکسل ها متعلق به پیش زمینه و پس زمینه هستند.
برچسب زدن فرآیند اختصاص یک شناسه منحصر به فرد (برچسب) به هر هسته در ماسک باینری است. در زمینه اجزای متصل ، برچسب زدن شامل می شود شناسایی و مارک گروه های پیکسل متصل (مؤلفه ها) که نمایانگر اشیاء فردی ، مانند هسته ها ، در تصویر است. پس از ایجاد ماسک باینری ، الگوریتم مؤلفه های متصل اعمال می شود. این الگوریتم ماسک باینری را به اسکن می کند گروه های پیکسل متصل با استفاده از معیارهای 4-اتصال یا 8-اتصال (در زیر تصویر را ببینید) و یک برچسب منحصر به فرد را به هر مؤلفه متصل اختصاص می دهد. هر برچسب با یک هسته مشخص در تصویر مطابقت دارد [1]بشر
انواع مختلفی از اتصال ، در درجه اول اتصال 4 و 8-اتصال وجود دارد:
4-اتصال:
- تعریف: در 4-اتصال ، یک پیکسل (علاقه) در صورت اشتراک گذاری لبه به پیکسل دیگری در نظر گرفته می شود. در یک شبکه 2D ، هر پیکسل چهار همسایه ممکن دارد: چپ ، راست ، بالاتر و پایین.
- برنامه: 4 اتصال اغلب در الگوریتم ها استفاده می شود جایی که اتصالات مورب در نظر گرفته نشده است، بدین ترتیب یک شکل محدودتر از اتصال فراهم می کند.
8-اتصال:
- تعریف: در 8-اتصال ، یک پیکسل (از علاقه) به همه همسایگان خود ، از جمله آنهایی که یک راس مشترک دارند ، متصل است. این بدان معنی است که ، علاوه بر همسایگان چهار لبه (مانند 4 اتصال) ، پیکسل نیز به چهار همسایه مورب وصل می شود.
- برنامه: 8-اتصال در برنامه هایی که اتصالات مورب قابل توجه است استفاده می شود و یک شکل فراگیر تر از اتصال را فراهم می کند.
چرا برچسب زدن مهم است
- شناسایی: برچسب زدن به ما امکان می دهد بین هسته های فردی درون ماسک باینری شناسایی و تمایز قائل شویم. هر هسته دارای یک برچسب منحصر به فرد است ، که باعث می شود هر هسته به طور جداگانه درمان و تجزیه و تحلیل شود.
- تجزیه: پس از برچسب زدن هسته ها ، می توانیم خصوصیات مختلفی از هر هسته را به صورت جداگانه اندازه گیری کنیم ، مانند مساحت ، محیط و شدت فلورسانس … این برای تجزیه و تحلیل کمی در تحقیقات بیولوژیکی ضروری است.
- تجسم: برچسب زدن همچنین تجسم هسته های تقسیم شده را تسهیل می کند. با اختصاص رنگ ها یا شدت های مختلف به هر برچسب ، به راحتی می توانیم هسته های تقسیم شده را در یک تصویر دارای برچسب مشاهده و تشخیص دهیم.
از کد زیر برای برچسب زدن مناطق متصل (مؤلفه ها) در تصویر باینری ما استفاده می شود. تابع skimage.measure.label
ماسک باینری را اسکن می کند و یک برچسب عدد صحیح منحصر به فرد را به هر مؤلفه متصل اختصاص می دهد. خروجی یک تصویر دارای برچسب (آرایه 2D Numpy) است که در آن به هر جزء متصل به یک برچسب عدد صحیح منحصر به فرد (به عنوان مثال ، 1 ، 2 ، 3 و غیره) اختصاص داده می شود. پیکسل هایی که متعلق به همان مؤلفه هستند (به عنوان مثال ، یک هسته واحد) دارای همان برچسب هستند. به طور پیش فرض ، این تابع از 8 اتصال استفاده می کند.
تابع color.label2rgb(labeled_nuclei, bg_label=0)
از ماژول Skimage.Color یک تصویر برچسب زده شده را به یک تصویر RGB (رنگ) تبدیل می کند.
labeled_nuclei
: این تصویر برچسب زده شده استbg_label=0
: این مشخص می کند که برچسب پس زمینه 0 است ، بنابراین پس زمینه رنگی نخواهد شد و فقط مناطق دارای برچسب (هسته) در تصویر RGB خروجی متفاوت رنگ می شوند.
در segmentation.clear_border()
عملکرد در کنار هم برای حذف هر هسته ای که لبه های تصویر را لمس می کند ، استفاده می شود و از آن اطمینان حاصل می کند فقط هسته های کاملاً حاوی در نظر گرفته می شوندبشر سپس تصویر برای بازتاب حذف این هسته های مرزی ، به نمایش گذاشته می شود و تعداد به روز شده چاپ می شود. سرانجام ، هسته های دارای برچسب به صورت رنگی تجسم می شوند و هر هسته با استفاده از شماره برچسب مربوطه ، در سانتروئید خود حاشیه نویسی می شود.
# Label the nuclei and return the number of labeled components
labeled_nuclei, num_nuclei = measure.label(binary_mask, return_num=True)print(f"Initial number of labeled nuclei: {num_nuclei}")
# Remove nuclei that touch the borders
cleared_labels = segmentation.clear_border(labeled_nuclei)# Recalculate the number of labeled nuclei after clearing the borders
# Note: We need to exclude the background (label 0)
final_labels, final_num_nuclei = measure.label(cleared_labels > 0, return_num=True)print(f"Number of labeled nuclei after clearing borders: {final_num_nuclei}")
# Visualize the labeled nuclei
plt.figure(figsize=(10, 10))
plt.imshow(color.label2rgb(final_labels, bg_label=0), cmap='nipy_spectral')
plt.title('Labeled Nuclei')
plt.axis('off')# Annotate each nucleus with its label
for region in measure.regionprops(final_labels):
# Take the centroid of the region and use it for placing the label
y, x = region.centroid
plt.text(x, y+30, f"Nucleus: {region.label}", color='white', fontsize=12, ha='center', va='center')plt.show()
Initial number of labeled nuclei: 19
Number of labeled nuclei after clearing borders: 15
اندازه گیری فلورسانس
برای اندازه گیری فلورسانس در کانال سبز (GFP) از تصویر چند کانال Z-Stack ما ، ما به جای اینکه فقط به حداکثر پیش بینی شدت داشته باشیم ، مقادیر پیکسل کانال GFP را در مناطق تعریف شده توسط ماسک باینری ما جمع می کنیم.
این روش (جمع مقادیر پیکسل) بازنمایی بهتری از سیگنال فلورسانس کل در هر منطقه دارای برچسب (هسته) را ارائه می دهد زیرا کل توزیع شدت را به جای فقط درخشان ترین پیکسل ها به خود اختصاص می دهد.بشر
کد زیر با جمع آوری شدت پیکسل در کانال GFP ، فلورسانس GFP را برای هر هسته دارای برچسب در تصویر محاسبه می کند. مقادیر حاصل در لیستی برای تجزیه و تحلیل بیشتر ، مانند مقایسه فلورسانس در هسته های مختلف یا ارزیابی توزیع GFP در نمونه ذخیره می شوند. عمل channel1.sum(axis=0)
خلاصه شدت پیکسل در تمام موقعیت های z برای هر موقعیت (x ، y) در تصویر. این منجر به یک تصویر 2D می شود که در آن هر مقدار پیکسل نشان دهنده شدت فلورسانس در آن (x ، y) در کل عمق نمونه است.
# Sum fluorescence in GFP channel within each labeled nucleus
gfp_fluorescence = []for region in measure.regionprops(final_labels, intensity_image=channel1.sum(axis=0)): # channel1.sum(axis=0) has a data type of 64-bit unsigned integer
gfp_sum = region.intensity_image.sum()
gfp_fluorescence.append(gfp_sum)# Print the total fluorescence for each nucleus
Nucleus 1: Total GFP Fluorescence = 80250
for i, fluorescence in enumerate(gfp_fluorescence, start=1):
print(f"Nucleus {i}: Total GFP Fluorescence = {fluorescence}")
Nucleus 2: Total GFP Fluorescence = 164085
Nucleus 3: Total GFP Fluorescence = 490688
Nucleus 4: Total GFP Fluorescence = 241095
Nucleus 5: Total GFP Fluorescence = 174400
Nucleus 6: Total GFP Fluorescence = 373265
Nucleus 7: Total GFP Fluorescence = 384270
Nucleus 8: Total GFP Fluorescence = 657477
Nucleus 9: Total GFP Fluorescence = 484203
Nucleus 10: Total GFP Fluorescence = 390793
Nucleus 11: Total GFP Fluorescence = 430493
Nucleus 12: Total GFP Fluorescence = 438093
Nucleus 13: Total GFP Fluorescence = 402420
Nucleus 14: Total GFP Fluorescence = 387462
Nucleus 15: Total GFP Fluorescence = 513172
تجزیه و تحلیل
کد فوق به طور عملی چگالی یکپارچه را محاسبه می کند که اندازه گیری در تجزیه و تحلیل تصویر برای تعیین کمیت میزان سیگنال (به عنوان مثال فلورسانس) در یک منطقه مورد علاقه (مانند هسته) است.
در میکروسکوپ فلورسانس ، از چگالی یکپارچه می توان برای برآورد میزان کل فلورسانس در یک هسته معین یا محفظه سلولی استفاده کرد. این می تواند برای مقایسه سطح بیان پروتئین دارای برچسب فلورسانس بین سلولهای مختلف یا شرایط آزمایشی مفید باشد.
کد زیر تبدیل می کند gfp_fluorescence list
به فریم داده های پاندا برای تجزیه و تحلیل آماری بیشتر ، مانند مقایسه فلورسانس در هسته ها یا شرایط مختلف ، محاسبه میانگین و انحراف استاندارد ، یا انجام تجزیه و تحلیل های پیشرفته تر مانند خوشه بندی یا همبستگی مطالعات
# Convert the fluorescence data into a DataFrame
df = pd.DataFrame({'Nucleus': range(1, len(gfp_fluorescence) + 1), 'GFP_Fluorescence': gfp_fluorescence})# Display the DataFrame
df
با تجزیه و تحلیل توزیع شدت فلورسانس در سراسر هسته ها ، به طور بالقوه می توانیم وجود جمعیت یا زیر گروه های مختلف را در نمونه نشان دهیم. این تجزیه و تحلیل می تواند بینش های ارزشمندی مانند شناسایی الگوهای بیان متمایز یا پاسخ به درمان ارائه دهد. تکنیک هایی مانند خوشه بندی می توانند در طبقه بندی هسته ها بر اساس پروفایل های فلورسانس آنها کمک کنند و تفسیرهای بیولوژیکی عمیق تر را امکان پذیر می کنند.
# Plot histogram
plt.figure(figsize=(10, 6))
sns.histplot(df['GFP_Fluorescence'], bins=20, kde=True)
plt.title('Histogram of GFP Fluorescence Intensity')
plt.xlabel('GFP Fluorescence Intensity')
plt.ylabel('Frequency')
plt.show()
تجزیه و تحلیل خوشه بندی:
ما می توانیم خوشه های K-Means را برای گروه بندی هسته ها بر اساس شدت فلورسانس آنها اعمال کنیم. این می تواند به شناسایی جمعیت متمایز که در سطح بیان آنها متفاوت است کمک کند. در طرح پراکندگی زیر هر نقطه یک هسته را نشان می دهد ، با محور x نشانگر شاخص هسته و محور y نشان دهنده شدت فلورسانس GFP برای آن هسته است. نقاط بر اساس خوشه ای که متعلق به آنها هستند ، کدگذاری شده اند. دو خوشه نشان داده شده است: خوشه 0 (به رنگ سبز) و خوشه 1 (در نارنجی). خوشه بندی با استفاده از K-Means با دو خوشه انجام شد. این طرح نشان می دهد که چگونه هسته ها را می توان بر اساس شدت فلورسانس GFP آنها به خوشه های مجزا گروه بندی کرد.
from sklearn.cluster import KMeans# Reshape data for clustering
fluorescence_data = df['GFP_Fluorescence'].values.reshape(-1, 1)
# Apply K-means clustering (let's assume 2 clusters for simplicity)
kmeans = KMeans(n_clusters=2, random_state=0).fit(fluorescence_data)
df['Cluster'] = kmeans.labels_
# Visualize clusters
plt.figure(figsize=(10, 6))
sns.scatterplot(x=df.index, y=df['GFP_Fluorescence'], hue=df['Cluster'], palette='Set2')
plt.title('K-means Clustering of GFP Fluorescence Intensity')
plt.xlabel('Nucleus')
plt.ylabel('GFP Fluorescence Intensity')
plt.show()
با هم ، این توطئه ها (هیستوگرام و طرح پراکندگی) نشانگر وجود حداقل دو زیر گروه هسته بر اساس فلورسانس GFP آنها ، به طور بالقوه منعکس کننده تنوع بیولوژیکی یا شرایط مختلف مؤثر بر بیان فلورسانس است.
پایان
در این آموزش ، ما تکنیک های پیشرفته پردازش تصویر را برای تقسیم هسته ها و تعیین کمیت سیگنال های فلورسنت با استفاده از پایتون بررسی کردیم. با استفاده از روش هایی مانند صاف کردن گاوسی ، آستانه و برچسب زدن به مؤلفه های متصل ، ما توانستیم هسته های فردی را به طور دقیق شناسایی و جدا کنیم. ما همچنین نحوه اندازه گیری شدت فلورسانس در کانال GFP را با جمع بندی مقادیر پیکسل در سلامت های Z برای ضبط توزیع کامل فلورسانس در هر هسته نشان دادیم. از طریق تجزیه و تحلیل داده ها ، ما توانستیم سیگنال های فلورسانس را کمیت و تفسیر کنیم و بینش های عمیق تری را در مورد تغییرات بیولوژیکی فراهم کنیم.
منابع:
[1] P. Bankhead ، “مقدمه ای برای تجزیه و تحلیل BioImage – مقدمه ای برای تجزیه و تحلیل BioImage.” https://bioimagebook.github.io/index.html (دسترسی به 29 ژوئن 2023).
منتشر شده از طریق به سمت هوش مصنوعی