Mixuan
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    Ulty Multy - EEG Data Analysis and Visualization ================================================ Welcome to the tutorial of Ulty Multy! This project utilizes the open data from OpenNeuro to analyze and visualize EEG data. For detailed information, please visit the [Github Repo](https://github.com/mixuanpan/Ulty_Multy). Foreword -------- Electroencephalogram (EEG) data analysis plays a crucial role in understanding brain activity, enabling advancements in neuroscience, biomedical engineering, and brain-computer interfaces. This user manual serves as a comprehensive guide to Ulty Multy, a MATLAB and EEGLAB-based system designed to streamline EEG data processing, feature extraction, and visualization. Developed to improve the efficiency and accuracy of EEG analysis, this tool integrates automated preprocessing workflows, advanced signal processing techniques, and intuitive graphical displays. Whether you are a researcher, student, or practitioner working with EEG data, this manual provides detailed instructions on system functionalities, from data loading to final interpretation. By following this guide, users will gain a clear understanding of how to leverage the tool for extracting meaningful insights from EEG recordings. We hope this manual enhances your experience and facilitates a deeper exploration of brainwave patterns and cognitive analysis. Main Script ----------- This is the file to run to start the program ``` % asks for user consent to perform data analysis consent = ip_welcome(); % When Consent is given if consent % load subject data par = readtable("data/participants.tsv", "FileType","text", "Delimiter", "\t"); % display user info subject_num = ip_subject_info(par); % filter data [data, low, upper, noise_num] = ip_data_filter(subject_num); % perform time frequency analysis and visualize the user-selected % channel(s) [power, freqs1] = ip_time_frequency_analysis(data); % view the relative location of each channel in a 3D interactive graph ip_brain_plot(data, subject_num); % compare the data of the target subject to the entire subject pool in % each channel ip_final_display(subject_num, low, upper, noise_num, freqs1, power); fprintf("\nAnalysis Successful.\n\n"); % When consent is not given else fprintf("\nPermission Denied!\n"); fprintf("\nAnalysis Unsuccessful.\n\n"); end ``` Welcome Function ---------------- This function begins with a welcome message explaining the data collection process, providing users with background information to help interpret the analysis results. The program then asks for consent to analyze the user’s local data. If consent is denied, the program ends without performing any analysis. While the open data used for this project is stored locally, requesting consent is essential when handling real user data in future applications. ``` function consent = ip_welcome() % INITIALIZATION fileName = "README"; % the name of the file to be displayed dir = "data"; % file directory filePath = fullfile(pwd, dir, fileName); % path to the file % check if the file exists if isfile(filePath) content = fileread(filePath); % read the file as a char array else content = ''; fprintf("\nFile not found!\n"); end % Printed Output fprintf("Welcome to the EEG Data Analysis Tool.\n") fprintf("This tool is designed to perform different analysis on the given data as follows: \n\n") disp(content); % Data Collection Process % Ask for user's consent consent = input("Do you allow this tool to perform data analysis (y/n)? ", "s"); if strcmp(lower(consent), 'y') fprintf("\nThank you for your permission!\n") fprintf("A series of analysis will be performed shortly.\n"); consent = true; else consent = false; end end ``` ### Welcome Message Displayed: Welcome to the EEG Data Analysis Tool. This tool is designed to perform different analysis on the given data as follows: Data collection took place at the NeuroCognition Laboratory (NCL) in San Diego, California under the supervision of Dr. Phillip Holcomb. This project followed the San Diego State University’s IRB guidelines. Participants sat in a comfortable chair in a darkened sound attenuated room throughout the experiment. They were given a gamepad for button pressing. They were instructed to watch the LCD video monitor that was at a viewing distance of 150cm. Participants were presented with 300 prime-target pairs. All targets were four-letter English words. Of the 300 critical trials, 100 had English word primes, 100 had ASL sign primes, and 100 had fingerspelled word primes. Half of the primes in each condition were related to the targets. Related English word primes were identity primes to the English word, related fingerspelled word primes were also identity primes, and related ASL primes were ASL translations of the English word targets. The other half of the primes were unrelated to the targets. Participants were instructed to focus on the purple fixation cross that appeared on the screen for 800ms. This fixation cross then turned white for 500ms. Then, one of three prime conditions was presented: an English word, an ASL sign, or a fingerspelled word. English prime words were presented for 300ms. Signed (M = 565ms) and fingerspelled (M = 1173ms) video primes had variable durations. All target stimuli were 4-letter English words presented for 500ms. Related primes were either identity or translations. Press any of the 4 buttons on the right of the gamepad whenever you see an animal. It doesn’t matter if the animal is presented as a sign, a word, or fingerspelled. Press for ANY animal. You can blink whenever you see purple. A purple + means you have time for a quick blink. A purple (--) means you can blink as much as you want. Subject Number & Info Function ------------------------------ This function prompts the user to select a target subject (between 1 and 27) for analysis. If the input is invalid or out of range, the program will continue asking until a valid input is provided. The function then reads a .tsv file to display the selected subject’s demographics and data collection settings. This helps the user identify potential influencing factors when comparing data across subjects. ``` function subject_num = ip_subject_info(par) % INITIALIZATION invalid_num = [14 15 25]; % no subjects found len = length(invalid_num); % number of invalid numbers checker = true; % while loop control variable bool = true; % loop control variable % subject_num error check while checker % ask for subject number from user input subject_num = input("Which subject are you looking for? Enter a number between 1 and 27 (inclusive) --> "); % When the subject number is in the given range if (subject_num >= 1 && subject_num <= 27) for i = 1:len % length of invalid_num if subject_num == invalid_num(i) fprintf("\nSubject not found!\n\n"); bool = false; end end if bool checker = false; % stop the while loop end bool = true; % When the subject number is out of range else fprintf("\nError! Enter a number between 1 to 27 (inclusive)!\n\n"); end end % target subject ID id = "sub-" + int2str(subject_num); % print out subject info fprintf("\n<strong>Subject Info:</strong>\n"); % match: similar to the "find" function but comparing in tables disp(par(matches(par.participant_id, id), :)); % print out subject settings fprintf("\n<strong>Subject Settings:</strong>\n"); fileName = fullfile("data", sprintf("sub-%d", subject_num), "eeg", sprintf("sub-%d_task-SemanticCategorization_eeg.json", subject_num)); jsonData = jsondecode(fileread(fileName)); disp(jsonData); end ``` ### Subject Info Displayed ![02_Subject_Info_02_Display](https://hackmd.io/_uploads/r18l2y63yg.png) Data Filtering Function ----------------------- This function includes bandpass filtering and notch filtering, both of which help reduce noise and improve signal clarity in the EEG data. Bandpass filtering isolates signals within a specific frequency range, removing frequencies outside of this range to focus on meaningful brain activity. The user is prompted to input lower and upper bounds between 0.1 Hz and 40 Hz — the typical range for EEG analysis, as it captures key brainwave patterns such as delta, theta, alpha, beta, and gamma waves. If the user inputs values outside this range or sets the upper bound lower than the lower bound, the program triggers an error and asks for valid inputs. Once the program receives valid values, it uses the pop\_eegfiltnew() function to apply the bandpass filter, preserving only the signals within the chosen frequency band. For instance, setting the range to 1–30 Hz would eliminate low-frequency drifts and high-frequency noise, making brainwave patterns more discernible. Notch filtering, on the other hand, targets narrow-band interference, such as powerline noise, which typically occurs at 50 Hz (in most countries) or 60 Hz (in North America). The user can select either 50 Hz or 60 Hz for the notch filter, and the program will apply it to remove the constant-frequency interference that often appears as spikes in EEG data. Removing powerline noise helps uncover subtle patterns in brain activity that might otherwise be masked by electrical interference. By applying both bandpass and notch filtering, the program ensures that the processed EEG data is cleaner and more suitable for accurate time- frequency analysis. ``` function [data, low, upper, noise_num] = ip_data_filter(subject_num) fprintf("\n<strong>EEG Data Filtering Begins</strong>\n"); currentPath = "/Users/mixuan/Desktop/Ulty_Multy"; % current directory % the file for reading EEG data fileName = "sub-" + int2str(subject_num) + "_task-SemanticCategorization_eeg.set"; % the path for the EEG data file filePath = fullfile(currentPath, "data", "sub-" + int2str(subject_num), "eeg"); cd(filePath); % change to file directory % load eeg data list from the data of user-chosen subject % use char() to avoid '.set' being truncated EEG = pop_loadset(char(fileName)); cd(currentPath); % change to working directory checker = true; % while loop control variable checker2 = true; % another loop control variable low = 0; % initialize the lower bound upper = 0; % initialize the upper bound noise_num = 0; % initialize the powerline to be removed % bandpass filter bounds from user input while checker indicator = input("Do you want to bandpass filter (y/n)? ", 's'); % When the user wants a bandpass filter if strcmp(lower(indicator), "y") % ask for lower bound input while checker2 low = input("Enter the lower bound in Hz: "); if low < 0.1 fprintf("Entered lower bound is too small!\n") fprintf("Please enter a positive number greater or equal to 0.1 Hz!\n") else checker2 = false; end end % ask for upper bound input checker2 = true; while checker2 upper = input("Enter the upper bound in Hz: "); if upper > 40 fprintf("Entered upper bound is too high!\n") fprintf("Please enter a positive number smaller than 40 Hz!\n") elseif upper < low fprintf("Entered upper bound is too low!\n") fprintf("Upper bound must be higher than lower bound!\n") else checker2 = false; end end % Bandpass filter in the desired Hz range EEG = pop_eegfiltnew(EEG, low, upper); checker = false; % When the user doesn't want a bandpass filter elseif strcmp(lower(indicator), "n") checker = false; end end % noise removal checker = true; while checker indicator = input("Do you want to remove a specific powerline (y/n)? ", 's'); % When the user wants a noise removal if strcmp(lower(indicator), 'y') noise_num = menu("Enter the notch filter to be filtered out", "50 Hz (common in Europe and most countries)", "60 Hz (common in North America)"); % convert 1, 2 (index) to 50, 60 (notch filter) noise_num = 40 + 10 * noise_num; % notch filtering EEG = pop_eegfiltnew(EEG, noise_num - 1, noise_num + 1, [], 1); checker = false; % When the user doesn't want a noise removal elseif strcmp(lower(indicator), 'n') checker = false; % When the user falsely indicates if they want a noise removal or % not, the program skips the noise removal processing else fprintf("Please enter either 'y' or 'n'\n"); end end % function output data = EEG; fprintf("\nEEG Data Filtering Successful\n"); end ``` ### Notch Filtering Options ![03_Data_Filtering_02_Notch_Filter_Choice](https://hackmd.io/_uploads/HyStRL03Jl.png) ### Data Filtering Full Display ![03_Data_Filtering_03_Full_Display](https://hackmd.io/_uploads/H1IsCIR2Je.png) Time Frequency Analysis Function -------------------------------- After filtering, the program automatically conducts a time-frequency analysis using FFT with Hanning window tapering. It adjusts the frequency range to match FFT output (1 Hz to 60 Hz) and generates 200 time points. This process is repeated 32 times — once for each channel — producing 30,934 estimated frequencies. The function generates a heat map to visualize how the power of different frequency components changes over time for each EEG channel. The user can select any of the 32 channels for display, and the program will create a heat map using the imagesc() function. In the heat map, the x-axis represents time, the y-axis represents frequency, and the color intensity indicates the magnitude of power at each time-frequency point. Warmer colors, such as red and yellow, reflect higher power, while cooler colors, like blue and green, indicate lower power. In this example, the user chooses channel 21, 7, 1, and 32 to visualize. ``` function [power, freqs] = ip_time_frequency_analysis(input_data) % inform the user of the analysis type fprintf("\n<strong>Time Frequency Analysis</strong>\n"); EEG = input_data; channels_num = size(EEG.data, 1); % number of channels % cell arrays contain elements with different types power = cell(1, channels_num); % a cell array to store power freqs = []; % frequency initialization checker = true; % loop control variable % Wavelet Decomposition for each (typically 32) channel for ch = 1:channels_num [power{ch}, freqs] = timefreq(EEG.data(ch, :), EEG.srate, 'freqs', [1, 60]); end % Power Spectrum for individual channels while checker checker2 = true; % loop control variable while checker2 channel = input("\n\nWhich channel would you like to visualize? "); if ~isnumeric(channel) fprintf("\nPlease enter a numeric value!\n"); elseif isnumeric(channel) & (channel < 1 | channel > channels_num) fprintf("\nPlease enter a number between 1 and %i!\n", channels_num); else checker2 = false; end end % Plotting figure; imagesc([], freqs, abs(power{channel})); % plot power magnitude xlabel("Time (ms)"); ylabel("Frequency (Hz)"); title(["Time-Frequency Representation: Channel ", num2str(channel)]); colorbar; % wait until the figure is closed by the user waitfor(gcf); % Plot another channel checker2 = input("Do you want to visualize another channel (y/n)? ", "s"); if strcmp(lower(checker2), "n") checker = false; elseif ~strcmp(lower(checker2), "y") fprintf("\nInput Error!!\n\n"); checker = false; end end fprintf("\nTime Frequency Analysis and Visualization Successful.\n"); end ``` ### Analysis for Each of 32 Channels ![04_Time_Frequency_Analysis_01_Begin](https://hackmd.io/_uploads/BkPgkvC21e.png) ### User's Choices of Channel Visualization ![04_Time_Frequency_Analysis_03_Visualization_00_Input](https://hackmd.io/_uploads/HkCmkDAh1l.png) ### Time Frequency Analysis Visualization Examples ![04_Time_Frequency_Analysis_03_Visualization_02_07](https://hackmd.io/_uploads/SkrPyDC3yl.png) ![04_Time_Frequency_Analysis_03_Visualization_03_01](https://hackmd.io/_uploads/SJrwkwChkg.png) ![04_Time_Frequency_Analysis_03_Visualization_01_21](https://hackmd.io/_uploads/rkBwkv0nJe.png) ![04_Time_Frequency_Analysis_03_Visualization_04_32](https://hackmd.io/_uploads/r14Dkv0hkg.png) 3D Brain Plot Function ---------------------- This function creates a 3D interactive brain plot where the user can rotate, zoom, and explore the brain's surface. Highlighted channels are shown in red, making it easy to track their position. The interactive nature allows the user to inspect different angles and better understand the spatial relationship between channels. This feature enhances data interpretation by providing a clear, dynamic view of brain activity distribution. ``` function ip_brain_plot(data, subject_num) % INITIALIZATION EEG = data; % EEG data from user input chanlocs = EEG.chanlocs; % extract channel locations checker = true; % loop control variable % extract the channels for the given subject number from the file channels = readtable(sprintf("data/sub-%d/eeg/sub-%d_task-SemanticCategorization_channels.tsv", subject_num, subject_num), "FileType", "text", ... "Delimiter", "\t"); % extract the name column of the channels to show in the final 3D graph labels = channels.name; fprintf("\n<strong>Brain Plotting Begins</strong>\n"); % ask the user if they want to highlight a specific channel while checker indicator = input("Do you want to highlight a specific channel (y/n)? ", "s"); if strcmp(lower(indicator), "n") checker = false; elseif strcmp(lower(indicator), "y") checker = false; highlight = menu("Choose the channel name that you want it to be highlighted.", labels); else fprintf("Please enter 'y' or 'n'!\n"); end end figure; hold on; % iterate through each EEG channel as a point for i = 1:length(chanlocs) if ~isempty(labels{i}) % Check if the label exists % locates each channel to the correct coordination plot3(chanlocs(i).X, chanlocs(i).Y, chanlocs(i).Z); % determine highlight if exist("highlight", "var") & i == highlight % variable "highlight" doesn't exist if the user didn't % specify it color = "red"; else % the color of the highlighted channel on the 3D brain map, % default black color = "black"; end % add each label name to the data points text(chanlocs(i).X, chanlocs(i).Y, chanlocs(i).Z, ... labels{i}, 'FontSize', 10, 'FontWeight', 'bold', 'HorizontalAlignment', 'left', 'Color', color); end end % professional naming of the plot xlabel("X"); ylabel("Y"); zlabel("Z"); title("3D Representation of EEG Channels"); % adjust view angle view(3); % since brain is not a sphere, we need the relative scale of X, Y, & Z % axis equal; -> This makes the 3 axes equal grid on; % wait until the graph is closed to proceed to the final display waitfor(gcf); end ``` ### Channel Highlight Options ![05_Brain_Plot_02_Channel_Highlight 2](https://hackmd.io/_uploads/By91gP0h1x.png) ### Final Brain Map Display (Interactive) [Video Demonstration](https://github.com/mixuanpan/Ulty_Multy/blob/main/Media/01/05_Brain_Plot_03_3D_Map_Display_Video.mov) ![05_Brain_Plot_03_3D_Map_Display](https://hackmd.io/_uploads/rJHcgPRnJx.png) Final Display Function ---------------------- This function compares the selected subject’s data with other subjects’ data. The selected subject’s data is displayed in transparent red, while the compared subject’s data appears in gray. Overlapping areas are shown in darker red, highlighting similarities between the two datasets. This comparison is performed channel by channel, helping to identify consistent patterns and variations across individuals. To improve efficiency and avoid excessive loading time, the program saves the comparison plots directly to a folder instead of displaying them. ``` function ip_final_display(subject_num, low, upper, noise_num, freqs, power_spec) % compare the target to all of the subjects % Data Packaging % Initialization fprintf("\n<strong>Final Analysis Results:</strong>\n\n"); % There are a total of 27 subjects with 3 missing data subject_count = 27; invalid_num = [14 15 25]; % no subjects found current_subject = 1; % subjects to iterate through, starting from 1 currentPath = "/Users/mixuan/Desktop/Ulty_Multy"; % data directory % results directory resultsPath = "/Users/mixuan/Desktop/Ulty_Multy/Results"; channels_num = 32; % number of channels in the given data % ip_brain_plot.m channels = readtable(sprintf("data/sub-%d/eeg/sub-%d_task-SemanticCategorization_channels.tsv", subject_num, subject_num), "FileType", "text", ... "Delimiter", "\t"); labels = channels.name; % names of the 32 channels % iterate through each subject to analyze and get the data while current_subject <= subject_count % ip_subject_info.m % check if the current subject is the target subject current_subject = current_subject + (current_subject == subject_num) * (current_subject < subject_count); % check if the subject number is invalid if current_subject >= invalid_num(1) && current_subject <= invalid_num(end) for i = 1:length(invalid_num) current_subject = current_subject + (current_subject == invalid_num(i)); end end % ip_data_filter % filter each subject data with the bandwith given to the target % subject % the file for reading EEG data fileName = "sub-" + int2str(current_subject) + "_task-SemanticCategorization_eeg.set"; % the path for the EEG data file filePath = fullfile(currentPath, "data", "sub-" + int2str(current_subject), "eeg"); cd(filePath); % change to file directory % load eeg data list from the current subject EEG = pop_loadset(char(fileName)); cd(currentPath) % back to script directory % bandpass filter if low ~= 0 && upper ~= 0 % both "low ~= 0" and "upper ~= 0" are numeric scales -> % use && instead of & for performance EEG = pop_eegfiltnew(EEG, low, upper); % Bandpass filter in the desired Hz range end % noise removal if noise_num ~= 0 EEG = pop_eegfiltnew(EEG, noise_num - 1, noise_num + 1, [], 1); % notch filter end % ip_time_frequency_analysis.m fig = figure("Visible", "off"); % Set the figure to be invisible % % 4 rows, 8 columns for 32 subplots layout = tiledlayout(4, 8, 'Padding', 'compact', 'TileSpacing', 'compact'); for ch = 1:channels_num % Wavelet Decomposition for each channel % power data for this specific channel % only need the power data, neglecting the frequency power_data = timefreq(EEG.data(ch, :), EEG.srate, 'freqs', [1, 60]); nexttile; % Compared subject data in gray plot(freqs, abs(power_data), 'Color', [0.7, 0.7, 0.7, 0.03]); hold on; % stay on the same figure % Target subject data in red plot(freqs, abs(power_spec{ch}), 'Color', [1, 0, 0, 0.006], "LineWidth", 1.5); % Channel name for each subplot title(sprintf("%s", labels{ch}), "FontWeight", "bold", 'Units', 'normalized', 'Position', [1, 1, 1]); end % Graph formatting for all subplots xlabel(layout, "Frequency (Hz)", "FontWeight", "bold"); % y label ylabel(layout, "Power (VA)", "FontWeight", "bold"); % x label % title title(layout, sprintf("Subject %i - Gray vs. Target Subject - Red (%i)", current_subject, subject_num)); % save the graph file saveas(fig, fullfile(resultsPath, sprintf("output_%i.png", current_subject))); close(fig); % close the current figure fprintf("\n<strong>Final display progress: subject %i</strong>\n\n", current_subject); current_subject = current_subject + 1; % change to the next subject end end ``` ### Plot Type Determination To determine the best way to plot power (complex data) vs. frequency, I tested two approaches: plotting the magnitude of power on a real plane (left) and the original complex data on a complex plane (right). The left graph clearly shows variations in power magnitude over a frequency range, while the right graph is obscure and not useful for analysis. Therefore, I chose to plot the magnitude of power (amplitude) in the final display. ![Subject_27](https://hackmd.io/_uploads/SJ0dLvA3Jg.png) ### Example Display Graphs For Subject 27 Subject 1 vs. Subject 27 ![output_1](https://hackmd.io/_uploads/H1QINv03yl.png) Subject 3 vs. Subject 27 ![output_3](https://hackmd.io/_uploads/BkmLNvR2Jl.png) Subject 22 vs. Subject 27 ![output_22](https://hackmd.io/_uploads/SJXLVPR2ye.png) Subject 24 vs. Subject 27 ![output_24](https://hackmd.io/_uploads/S1Q8NvC2kg.png) ---------------------- [Published with MATLAB® R2024b](https://www.mathworks.com/products/matlab/)

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully