-
Notifications
You must be signed in to change notification settings - Fork 3
/
step03_events_to_bids.py
executable file
·98 lines (86 loc) · 4.35 KB
/
step03_events_to_bids.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# =============================================================================
# Created By : Dace Apšvalka
# Created Date: 2024-01-27
# =============================================================================
# This script downloads the events.tsv files from the OpenNeuro dataset and
# saves them in the BIDS directory structure.
# The script also fixes the events.tsv files to comply with BIDS.
# =============================================================================
# Import libraries
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
import os
from concurrent.futures import ThreadPoolExecutor
import pandas as pd
import logging
# Initialize logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
# ------------------------------------------------------------------------------
# Define variables
# ------------------------------------------------------------------------------
base_url = 'https://openneuro.org/crn/datasets/ds000117/snapshots/1.0.5/files/{subject_id}:ses-mri:func:{subject_id}_ses-mri_task-facerecognition_{run_id}_events.tsv'
bids_dir = '/imaging/correia/da05/workshops/2024-CBU/data'
nsubjects = 16
nruns = 9
# ------------------------------------------------------------------------------
# Check if the BIDS directory exists
if not os.path.exists(bids_dir):
logging.error(f"BIDS directory {bids_dir} does not exist. Please create it first.")
exit()
#------------------------------------------------------------------------------
# Function to download a file fron OpenNeuro base_url
#------------------------------------------------------------------------------
def download_file(subject_id, run_id, session):
try:
url = base_url.format(subject_id=subject_id, run_id=run_id)
file_path = os.path.join(bids_dir, subject_id, 'func', f"{subject_id}_task-facerecognition_{run_id}_events.tsv")
with session.get(url, stream=True) as response:
if response.status_code == 200:
with open(file_path, 'wb') as file:
for chunk in response.iter_content(chunk_size=8192):
file.write(chunk)
logging.info(f"Downloaded {file_path}")
else:
logging.error(f"Failed to download {subject_id} {run_id}. Status code: {response.status_code}")
return None
return file_path
except Exception as e:
logging.error(f"Exception occurred while downloading file for {subject_id} {run_id}: {e}")
return None
#------------------------------------------------------------------------------
# Fix OpenNeuro event files to comply with BIDS
#------------------------------------------------------------------------------
def fix_events_file(file_path):
try:
events = pd.read_csv(file_path, sep='\t')
events.rename(columns={"stim_type": "trial_type"}, inplace=True)
events = events[events['trial_type'].notna() & (events['trial_type'] != "")]
events.to_csv(file_path, sep="\t", index=False)
logging.info(f"Fixed {file_path}")
except Exception as e:
logging.error(f"Exception occurred while fixing file {file_path}: {e}")
# ------------------------------------------------------------------------------
# Both functions combined
# ------------------------------------------------------------------------------
def download_and_fix(subject_id, run_id, session):
file_path = download_file(subject_id, run_id, session)
if file_path:
fix_events_file(file_path)
#------------------------------------------------------------------------------
# Main execution
#------------------------------------------------------------------------------
def main():
with requests.Session() as session:
adapter = HTTPAdapter(pool_connections=20, pool_maxsize=20, max_retries=Retry(total=5, backoff_factor=0.1))
session.mount('https://', adapter)
with ThreadPoolExecutor(max_workers=10) as executor:
for subject in range(1, nsubjects+1):
subject_id = f"sub-{subject:02d}"
for run in range(1, nruns+1):
run_id = f"run-{run:02d}"
executor.submit(download_and_fix, subject_id, run_id, session)
if __name__ == "__main__":
main()