المحطة 7 · الدرس 4

تجهيز رسومات للنشر

مهم12 دقيقةقبل هذا الدرس: خرائط الرأس topoplot، رسم ERP للقنوات (قريباً)اطبع البطاقة
تبدأ من: eeglab_data.set (D1) · ما طُبّق عليه قبل هذا الدرس: فلترة high-pass و low-pass، إزالة ضوضاء الكهرباء (50 أو 60 هرتز)، القنوات السيئة، الاستيفاء (interpolation)، إعادة المرجع (re-referencing)، تشغيل ICA، فلتر 1 هرتز قبل ICA ونسخ الأوزان، ICLabel وحذف المكوّنات، استخراج epochs، تصحيح baseline، رفض epochs السيئةتنزيل البيانات (يفتح في نافذة جديدة)
سكربت الوصول لهذه الحالة
MATLAB
% Shortcut: if you saved D1_epochs_clean.set in the epoch rejection lesson, keep
% the first line and the last two lines (pop_newset, eeglab redraw), and replace
% every line between them with:
% EEG = pop_loadset('D1_epochs_clean.set', pwd);
[ALLEEG, EEG, CURRENTSET, ALLCOM] = eeglab;
eeglabRoot = fileparts(which('eeglab'));
EEG = pop_loadset('eeglab_data.set', fullfile(eeglabRoot, 'sample_data'));
fullLocs = EEG.chanlocs;

% Main dataset: high-pass at 0.1 Hz, then 60 Hz line-noise removal
EEG = pop_eegfiltnew(EEG, 'locutoff', 0.1);
EEG = pop_eegfiltnew(EEG, 'locutoff', 58, 'hicutoff', 62, 'revfilt', 1);

% Bad channels you removed earlier, e.g. {'T7'}; leave empty if none
badChans = {};
if ~isempty(badChans)
    EEG = pop_select(EEG, 'rmchannel', badChans);
    EEG = pop_interp(EEG, fullLocs, 'spherical');
end

% Average reference, EOG channels excluded
eogIdx = find(ismember({EEG.chanlocs.labels}, {'EOG1', 'EOG2'}));
EEG = pop_reref(EEG, [], 'exclude', eogIdx);

% ICA on a 1-Hz copy, then copy the weights back
EEG_ica = pop_eegfiltnew(EEG, 'locutoff', 1);
EEG_ica = pop_runica(EEG_ica, 'icatype', 'runica', 'extended', 1);
EEG.icaweights  = EEG_ica.icaweights;
EEG.icasphere   = EEG_ica.icasphere;
EEG.icachansind = EEG_ica.icachansind;
EEG.icawinv     = [];
EEG.icaact      = [];
EEG = eeg_checkset(EEG);

% Remove eye and muscle components, then low-pass at 30 Hz
EEG = pop_iclabel(EEG, 'default');
EEG = pop_icflag(EEG, [NaN NaN; 0.9 1; 0.9 1; NaN NaN; NaN NaN; NaN NaN; NaN NaN]);
artifactComps = find(EEG.reject.gcompreject);
if ~isempty(artifactComps)
    EEG = pop_subcomp(EEG, artifactComps, 0);
end
EEG = pop_eegfiltnew(EEG, 'hicutoff', 30);

% Epochs around 'square', baseline, and +/-100 uV rejection
EEG = pop_epoch(EEG, {'square'}, [-1 2], 'newname', 'D1 epochs', 'epochinfo', 'yes');
EEG = pop_rmbase(EEG, [-200 0]);
EEG = pop_eegthresh(EEG, 1, 1:EEG.nbchan, -100, 100, EEG.xmin, EEG.xmax, 0, 0);
badEpochs = find(EEG.reject.rejthresh);
if ~isempty(badEpochs)
    EEG = pop_rejepoch(EEG, EEG.reject.rejthresh, 0);
end
EEG.setname = 'D1 epochs clean';
EEG = eeg_checkset(EEG);
EEG = pop_saveset(EEG, 'filename', 'D1_epochs_clean.set', 'filepath', pwd);
EEG.filename = ''; EEG.filepath = ''; EEG.datfile = ''; EEG.saved = 'no';
[ALLEEG, EEG, CURRENTSET] = pop_newset(ALLEEG, EEG, 0, 'setname', 'D1 epochs clean', 'gui', 'off');
eeglab redraw;

الفكرة باختصار

الرسمة التي تفهمها على شاشتك ليست رسمة جاهزة للورقة. المجلة تصغّرها إلى عرض عمود واحد تقريباً، فيصير الخط الصغير غير مقروء، والصورة الملتقطة من الشاشة مشوّشة عند التكبير.

والأخطر من الشكل هو الصدق. خريطتان لشرطين بمقياسي ألوان مختلفين توحيان بفرق غير موجود، أو تخفيان فرقاً موجوداً. والمراجع ينتبه لهذا.

قبل وبعد

اعرض
رسم Pz لشرطين ملتقط من الشاشة ومصغّر: النص صغير لا يُقرأ، والخطوط رفيعة، والحواف مسننة، والمحور الرأسي بلا وحدة.
قبل: لقطة شاشة مصغّرةالبيانات: عيّنة EEGLAB الرسمية (eeglab_data.set)
الرسم نفسه بعد التصدير بـ exportgraphics: خلفية بيضاء، وخطان بلونين ونمطين (متصل ومتقطع)، والمحور الرأسي Potential (µV)، وعدد المحاولات في المفتاح.
بعد: ملف متجهي، معروض هنا صورةًالبيانات: عيّنة EEGLAB الرسمية (eeglab_data.set)

أسئلتك بعد هذا، كل جواب في قسمه:

لماذا أحتاج هذه الخطوة؟

السبب بالتفصيل، والمصطلحات التي تحتاجها

هذا الدرس يأخذ رسمتين من الدرسين السابقين، ويجهّزهما للنشر: صيغة متّجهة، ومقاس محدد، وخط مقروء، ومقياس ألوان واحد، وملف أرقام يثبت ما في الرسمة.

كيف أطبّقها في EEGLAB؟

10 خطوة من القوائم

ابدأ داتاستdatasetملف بيانات EEG واحد محمّل في EEGLAB مع معلوماته. D1 epochs clean مفتوحة، كما في “نقطة البداية”. للخرائط استخدم D1 epochs clean scalp، النسخة ذات الـ 30 قناةchannelالإشارة المسجّلة من قطب واحد، وهي ما يعرضه EEGLAB. بدون EOG1 و EOG2. إذا لم تكن مفتوحة، اصنعها كما في أول خطوة من درس خرائط الرأس (Edit ثم Select data). الواجهةGUIالنوافذ والقوائم التي نستخدمها بالفأرة بدل كتابة الأوامر. تكفي لخرائط داتاست واحدة. مقارنة شرطين في رسمة واحدة تحتاج سكربتscriptملف أوامر MATLAB ينفّذ خطوات المعالجة بالترتيب.، كما في درس رسم ERPمتوسط استجابة الدماغ لحدث معيّن عبر محاولات كثيرة. للقنوات.

أولاً: اعرف حدود المقياس

  1. والداتاست D1 epochs clean scalp هي المختارة، افتح Plot ثم ERP map series ثم In 2-D.
  2. اكتب 100 200 300 400 في Plotting ERP scalp maps at these latencies، و [1 4] في Plot geometry (rows,col.); [] -> near square. اضغط Ok.
  3. اقرأ أعلى رقم على شريط الألوان، وقرّبه لأعلى إلى عدد صحيح. هذا حدّك.

ثانياً: ثبّت المقياس وصدّر

  1. افتح نفس النافذة مرة ثانية. في خانةfield (in a dialog)مكان في نافذة نكتب فيه قيمة أو نختارها. الخيارات الإضافية اكتب 'electrodes', 'on', 'maplimits', [-5 5]، وضع حدّك مكان 5. استخدم نفس حدthresholdقيمة إذا تجاوزتها الإشارة اعتُبرت مشكلة. لكل خريطة ستقارنها بهذه، حتى من داتاست أخرى.
  2. في نافذة الرسمة افتح File ثم Save As، واختر نوع الملف PDF أو SVG. هذه قائمةmenuمجموعة أوامر تظهر عند الضغط على اسمها في أعلى النافذة. MATLAB نفسها، لا قائمة EEGLAB.
  3. افتح الملف وكبّره: الخطوط والحروف حادة، ونص العناوين يمكن تحديده. هذا معنى “متّجهة”.

ثالثاً: صدّر الأرقام التي وراء الرسمة

  1. افتح File ثم Export ثم Data and ICA activity to text file.
  2. في Output file name اكتب erp_all.txt.
  3. فعّل Export ERP average instead of trials:، واترك Transpose matrix (elec -> cols): و Export channel labels/component numbers: و Export time values: مفعّلة كما هي. اضغط Ok.
  4. يظهر ملف نصي: الصف الأول أسماء القنوات، والعمود الأول الزمن بالميلي ثانية، وكل صف بعده نقطة زمنية. هذا ما تضعه في المواد الإضافية للورقة، أو ترسم منه في برنامج آخر.

كيف أكتبها بالكود؟

نفس الخطوات في 46 أسطر MATLAB
MATLAB
EEG = pop_loadset('D1_epochs_clean.set', pwd);
pos = eeg_getepochevent(EEG, 'type', {'square'}, 'timewin', [-5 5], 'fieldname', 'position');
EEG_pos1 = pop_select(EEG, 'trial', find(pos == 1));
EEG_pos2 = pop_select(EEG, 'trial', find(pos == 2));
EEG_pos1.setname = 'D1 epochs clean pos1';
EEG_pos2.setname = 'D1 epochs clean pos2';
chan = find(strcmp({EEG.chanlocs.labels}, 'Pz'));
scalp = find(~ismember({EEG.chanlocs.labels}, {'EOG1', 'EOG2'}));   % EOG is not on the average reference
erp1 = mean(EEG_pos1.data, 3);
erp2 = mean(EEG_pos2.data, 3);

% Figure 1: Pz waveforms at single-column size, 9-pt font, white background
fig1 = figure('Color', 'w', 'Units', 'centimeters', 'Position', [2 2 9 7]);
hold on;
plot(EEG.times, erp1(chan, :), 'Color', [0 0.45 0.74], 'LineWidth', 1.2);
plot(EEG.times, erp2(chan, :), 'Color', [0.85 0.33 0.10], 'LineWidth', 1.2, 'LineStyle', '--');
xline(0, 'k:'); yline(0, 'k-');
xlim([-200 800]);
set(gca, 'YDir', 'normal', 'FontName', 'Arial', 'FontSize', 9, 'TickDir', 'out', 'Box', 'off');
xlabel('Time (ms)'); ylabel('Potential (\muV)');
legend({sprintf('Position 1 (n = %d)', EEG_pos1.trials), ...
        sprintf('Position 2 (n = %d)', EEG_pos2.trials)}, 'Location', 'northeast', 'Box', 'off');
title('Pz', 'FontWeight', 'normal');
exportgraphics(fig1, 'fig_pz_erp.pdf', 'ContentType', 'vector', 'BackgroundColor', 'white');

% Figure 2: 300 to 500 ms maps for both conditions on one shared symmetric scale
win = EEG.times >= 300 & EEG.times <= 500;
map1 = mean(erp1(scalp, win), 2);
map2 = mean(erp2(scalp, win), 2);
lim = ceil(max(abs([map1; map2])));
fprintf('Shared color scale: -%d to %d uV\n', lim, lim);
fig2 = figure('Color', 'w', 'Units', 'centimeters', 'Position', [2 2 12 6]);
subplot(1, 2, 1);
topoplot(map1, EEG.chanlocs(scalp), 'maplimits', [-lim lim], 'electrodes', 'on');
title('Position 1', 'FontName', 'Arial', 'FontSize', 9, 'FontWeight', 'normal');
ax = subplot(1, 2, 2);
topoplot(map2, EEG.chanlocs(scalp), 'maplimits', [-lim lim], 'electrodes', 'on');
title('Position 2', 'FontName', 'Arial', 'FontSize', 9, 'FontWeight', 'normal');
axPos = ax.Position;
cb = colorbar('FontName', 'Arial', 'FontSize', 9);
ax.Position = axPos;   % keep both maps the same size
cb.Position = [0.92 0.25 0.02 0.5];
ylabel(cb, '\muV');
exportgraphics(fig2, 'fig_maps_300_500.pdf', 'ContentType', 'vector', 'BackgroundColor', 'white');
exportgraphics(fig2, 'fig_maps_300_500.png', 'Resolution', 600, 'BackgroundColor', 'white');

% The numbers behind the figures: one row per time point, one column per channel
pop_export(EEG_pos1, 'erp_pos1.txt', 'erp', 'on', 'transpose', 'on', 'elec', 'on', 'time', 'on', 'precision', 4);
pop_export(EEG_pos2, 'erp_pos2.txt', 'erp', 'on', 'transpose', 'on', 'elec', 'on', 'time', 'on', 'precision', 4);

أي قيمة أختار؟

القيم المناسبة حسب هدف تحليلك
الإعدادالقيمةلماذا
الصيغةPDF أو SVG أو EPS (متّجهة) للموجات، و PNG بدقة 600 dpi للخرائط إذا كان الملف المتّجه ثقيلاًالمتّجهة تبقى حادة عند أي تكبير، والمجلة تقبلها غالباً. خريطة الرأسscalp mapرسم يبيّن توزيع قيمة على الرأس من الأعلى. فيها آلاف المضلّعات الملونة، فقد يكبر ملفها المتّجه. لا تستخدم JPEG أبداً، لأنه يضيف تشويشاً حول الخطوط.
العرضحوالي 9 cm لعمود واحد، وحوالي 18 cm لعمودينارسم بالمقاس النهائي من البداية، بدل التصغير بعد ذلك. تحقق من دليل المجلة، فالمقاسات تختلف قليلاً.
حجم الخط8 إلى 10 نقاط بالمقاس النهائيأصغر من 7 نقاط لا يُقرأ مطبوعاً. ولأنك ترسم بالمقاس النهائي، ما تختاره هنا هو ما يراه القارئ.
الخطوط1 إلى 1.5 نقطة، ونمطان مختلفان للشرطينالنمط (متصل ومتقطع) يميّز الشرطين حتى في الطباعة بالأبيض والأسود، ولمن يصعب عليه تمييز الألوان.
مقياس الألوانواحد متماثل لكل الخرائط التي تُقارن، مع شريط ألوان بوحدتههذا أهم بند في الصدق. قرّب الحد لعدد صحيح واذكره في الوصف.
الاتجاهالموجب للأعلى، واذكرهبعض المختبرات ترسم السالب للأعلى. أيّاً كان اختيارك، القارئ يحتاج أن يعرفه من المحور أو الوصف.
exportgraphicsيحتاج MATLAB R2020a أو أحدثفي إصدار أقدم استخدم print(fig1, 'fig_pz_erp', '-dpdf', '-painters').

كيف أتأكد أنها نجحت؟

4 فحوص سريعة
  • كبّر ملف PDF إلى 400%: الموجات والحروف حادة، ويمكنك تحديد نص المحاور بالمؤشر.
  • مقاس الصفحة في ملف fig_pz_erp.pdf حوالي 9 × 7 cm في خصائص الملف.
  • الخريطتان في fig_maps_300_500.pdf في كل منهما 30 نقطة قطبelectrodeالقطعة المعدنية التي توضع على الرأس لالتقاط الإشارة. ولا شيء تحت العينين، وبنفس الحجم، وتشتركان في شريط ألوان واحد حدّاه هما الرقم الذي طبعه سطر Shared color scale.
  • ملف erp_pos1.txt فيه صف عناوين ثم 384 صفاً (نقطة لكل 7.8 ms من -1000 إلى 1992 ms)، و 33 عموداً: الزمن ثم 32 قناة.

ما الأخطاء التي يقع فيها كثيرون؟

6 أخطاء، وكيف تتجنّبها
  • لقطة الشاشة. دقتها دقة شاشتك، وتتشوّه عند الطباعة. صدّر الرسمة من MATLAB دائماً.
  • رسم كبير ثم تصغير. خط بحجم 10 على رسمة عرضها 25 cm يصير 3.6 نقاط بعد تصغيرها إلى 9 cm. حدّد المقاس قبل الرسم.
  • مقياس ألوان لكل خريطة. إذا رسمت كل شرطconditionحالة تجريبية نقارن بينها وبين غيرها، مثل "مألوف" و"غير مألوف". في نافذة مستقلة، يختار EEGLAB لكل نافذة حدودها من بياناتها. ثبّت maplimits بنفس القيمة في كل النوافذ.
  • خلفية EEGLAB الزرقاء الفاتحة. نوافذ رسومات EEGLAB لونها الافتراضي أزرق فاتح جداً. اجعل الخلفية بيضاء عند التصدير، كما في السكربت.
  • وصف ناقص. تحت كل رسمة ERP اذكر: القناة، المرجعreferenceالنقطة التي يُقاس جهد كل قناة بالنسبة لها.، والمرشّحات، وعدد المحاولات لكل شرط، والاتجاه. بدونها لا يمكن تفسير الرسمة.
  • تجميل البيانات. لا تزد التنعيم ولا تقصّ المحور لتكبّر فرقاً. ما تصدّره يجب أن يطابق ملف الأرقام.

كيف أكتبها في ورقتي؟

قالب Methods: عدّل البيانات والإعدادات والإصدارات لتطابق ما نفّذته

قالب: عدّل البيانات والإعدادات والإصدارات لتطابق ما نفّذته.

Figures were exported as vector PDF files with MATLAB exportgraphics; scalp maps of both conditions (30 average-referenced scalp channels) share one symmetric color scale of ±[X] µV (topoplot, EEGLAB 2026.1).

أين أقرأ أكثر؟

2 مراجع: التوثيق الرسمي أولاً
  • EEGLAB Tutorialتوثيق11. Write scripts > d. Advanced plots
  • EEGLAB TutorialتوثيقReference Topics > Exporting Data: Exporting data to an ASCII text file

مكتوب لـ EEGLAB 2026.1 · 2026-10-28

تحتاج مساعدة؟

اسأل، أو شاركنا رأيك، أو بلّغ عن خطأ