본문 바로가기

🧠 Note. Brain science

Seoul | OBELAB 세미나 2 - fNIRS 실험 셋팅

fMRI와 fNIRS

fMRI 에서 측정하는 뇌 혈류량과, fNIRS의 헤모글로빈 수치가 비슷한 목적으로 측정하고 있고, 실제 fmri 와 비슷한 패턴으로 측정된다는 입증 자료이다.

HbO 수치와 BOLD ( Blood Oxygen Level Dependent : fmri 대표 지표) 가 비슷한 패턴을 보임을 A 그래프에서 알 수 있다.

 

실험 설계 시 유의점과 분석 시 유의점

HbO, HbR, HbT가 뉴런 활성도 때문인지, 아니면 다른 심박박동수 등 때문인지 모름.

 

특히, 초반 block에서는 활성화가 크게 있는 경우가 있음. -> fnirs 기기에 대한 불안감, 뛰어왔을 때 영향, 준비가 제대로 안되어있을 경우.

 

실험 설계를 통한 해결

  • resting state 가 필요함.
  • 중간중간 휴식을 꾸준히 줌.
  • baseline 측정 전 휴식시간

 

이미 측정 완료했다면, 전처리 혹은 분석 법으로 해결

  • General Linear Model (가장 흔함) 
    • Y = X*beta + error (Y 실제 측정값, X는 예상 HbO 값 으로 하여 beta 의 크기에 따라, 얼마나 이론적 활성도랑 비슷하게 따라가는지를 확인 가능함)
  • frequency 분석
  • short seperation channel

 

뇌 반응이 실제 stimulus에 의한 것인지 다른 자극에 의한 것인지 모르기 때문에 변인 통제가 중요함.

따라서 아래와 같은 고려 사항이 필요

  • baseline 과 비교하여 측정해야 함
  • 참가자 간 변산이 크기 때문에 paired test 혹은 matched group design으로 비교함
    >> matched group design 시에는 체중, 정신적 특성, 나이, 등 혈류량에 미치는 영향 변인을 모두 통제해야 함.
  • 연습 효과에 의해, sequence를 통제해야 함. (block design이 필수)

 

실험 설계 할 때 마커를 동일하게 하기 위한 방법 - PsychoPy3

뇌파에서와 비슷하게, psychopy를 활용하여 마커를 프로그램에 넣을 수 있다고 한다.

fnirs 도 psychopy에서 마커를 전송해서 줄 수 있는 것 같음.

마커 넘기는 방법은 faq에서 확인 가능하지만 여기 붙여넣었다. 로그인해야함 ㅠㅠ

 

 

3. Defining the “send_marker” function

  • Define a function sending each marker if the socket connection is confirmed and the object “MyPort” is created. Insert and use the function whenever needed.
  • You can simply copy and paste the function script that we provide.
  • Basically, the marker array is defined as ‘abc’ + Marker number in “byte” format + ‘xyz’
  • FYI, if using Pavlovia, change “msg = bytes(b'abc') + marker.to_bytes(4, byteorder="little") + bytes(b'xyz’)” to “msg = bytes('abc') + marker.to_bytes(4, byteorder="little") + bytes('xyz’)” to solve the JS syntax error.
  • This is handled within the function. Input of the function is simply the numbers or the variable that the number is assigned to.
  •  
# Define "send_marker" function

def send_marker(marker):
    # check whether marker is int
    if not isinstance(marker, int):
        try:
            marker = int(marker)
        except: 
            print('Error!! Markers must be numbers.')
    # send marker 
    msg = bytes(b'abc') + marker.to_bytes(4, byteorder="little") + bytes(b'xyz')
    MyPort.send(msg)
    print("Sending marker No:" f'{marker}')

 

4.Sending markers before and after a loop using the “send_marker” function

  • To send block markers indicating the beginning and end of a block, add a code component before and after the block loop.
  • You can mark the beginning of a loop by inserting the marker-sending snippet into the “End Routin” tab of a routine preceding the loop. Likewise, the end of a loop can be marked by inserting the snippet into the “Begin Routine.” of a routine following the loop. This way, you can mark the onset/offset of a certain block (where the trial structure is repeated within the loop).
  • This is one example of placing onset/offset markers, and you can place the markers on any place (Begin Routine or End Routine tab) of each routine, depending on your study design. Change the variable name or marker number inside the send function and place the snippet anywhere appropriate.
  • A short time gap (about 200ms) is necessary between the two markers for both markers can be properly sent, which is a limitation of the socket communication. If you want to insert a Staret marker of the second block right after the End marker of the first block, create some temporal margin between them by, for example, using “time.sleep(0.3)”, so that neither one of them gets lost.   
  • After sending the last marker of the entire program, close the socket connection using .close() methods of the socket object, in this example, MyPort.close() and clear the object by del(MyPort).
  •  

5.Sending markers before and after a routine using the “send_marker” function

  • In the case of a routine that is not repeated, such as a rest period, you can send the onset/offset marker of the routine called “Rest/Baseline” by entering the marker code in the ‘Begin Routine’ and ‘End Routine’ tabs in one of the 'Code' components within the routine.
  •  

6. Example code

## markers are integers such as 1111, 2222, 1, 4, etc.
## Assign the markers to a variable or use them as they are.
e.g., MyMarker = 1111

### Insert this to "begin experiment" tab of a routine. ###

# Port Setup

import socket, time
import numpy as np

if (expInfo['with_socket'] == '1'):
    serverIp = '127.0.0.1'
    tcpPort = 60000
    MyPort = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    MyPort.connect((serverIp, tcpPort))
    addr = (serverIp, tcpPort)
    print ('Connected by', addr)

# Define "send_marker" function
def send_marker(marker):
    # check whether marker is int
    if not isinstance(marker, int):
        try:
            marker = int(marker)
        except: 
            print('Error!! Markers must be numbers.')
    # send marker 
    msg = bytes(b'abc') + marker.to_bytes(4, byteorder="little") + bytes(b'xyz')
    MyPort.send(msg)
    print("Sending marker No:" f'{marker}')

#### Send markers whenever required  #####
block_start_marker = 1001
if (expInfo['with_socket'] == '1'):
    send_marker(block_start_marker)  # if any number (e.g., 1001) is assigned to the variable "block_start_marker".

##### When Task application is closed
test_end = 9999
if (expInfo['with_socket'] == '1'):
    send_marker(test_end) # if any number (e.g., 9999) is assigned to the variable "test_end". 
    time.sleep(0.3)
    MyPort.close()
    del(MyPort)

#### If variable assginment is not necessary  #####
if (expInfo['with_socket'] == '1'):
    send_marker(1111)

 

 

Block design 과 Even-related Design

아래 출처에서 재구성함 : https://www.fmri4newbies.com/lecture

 

 

뇌영상(fMRI, fNIRS) 연구에서는 자극을 제시하는 방식에 따라 Block Design, Event-Related Design, Mixed Design 등 다양한 실험 설계를 사용한다.

 

Block Design은 활성화를 쉽게 검출할 수 있지만 개별 시행의 인지 과정을 구분하기 어렵고,

Event-Related Design은 시행별 반응을 분석할 수 있지만 더 많은 데이터와 정교한 모델링이 필요하다.

Mixed Design은 두 방법의 장점을 결합하여 지속적인 상태 변화와 순간적인 반응을 동시에 분석할 수 있다.

 

그래서 대부분 뇌과학 관련 task는 mixed design을 주로 사용한다고 한다.

 

특히 fNIRS에서는 혈역학 반응(HRF)이 수 초에 걸쳐 나타나기 때문에, Rapid Event-Related Design을 사용할 경우 HRF 중첩(overlap)을 고려한 GLM 분석이 중요하다.