Skip to content
Snippets Groups Projects
Commit 5ad6c8e9 authored by Toumji Abdallah's avatar Toumji Abdallah
Browse files

Implemented the creation of the README file

parent f510011d
No related branches found
No related tags found
No related merge requests found
import json
import os
import shutil
import tkinter as tk
from tkinter import ttk
from pathlib import Path
from tkinter import ttk
import BIDSHandler.MainApplication as MainApplication
import BIDSHandler.Tools as Tools
from BIDSHandler.CreationTool.FormHandler import FormHandler
import shutil
from BIDSHandler.CreationTool.EntryManager import Entry
from BIDSHandler.CreationTool.FormHandler import FormHandler
class Application(tk.Frame):
......@@ -45,10 +45,12 @@ class Application(tk.Frame):
''' This method is used to create the widgets of the main window of the application.
'''
start_bids_project_button = tk.Button(self.main_frame, text='Start BIDS Project', command=self.start_bids_project)
start_bids_project_button = tk.Button(self.main_frame, text='Start BIDS Project',
command=self.start_bids_project)
start_bids_project_button.grid(row=0, column=0)
complete_bids_project_button = tk.Button(self.main_frame, text='Complete BIDS Project', command=self.complete_bids_project)
complete_bids_project_button = tk.Button(self.main_frame, text='Complete BIDS Project',
command=self.complete_bids_project)
complete_bids_project_button.grid(row=0, column=1)
tool_selection_button = tk.Button(self.main_frame, text='Back to Tool Selection', command=self.tool_selection)
......@@ -69,7 +71,8 @@ class Application(tk.Frame):
self.name_entry = tk.Entry(self.center_frame)
self.name_entry.grid(row=0, column=1)
path_button = tk.Button(self.center_frame, text='Select project directory', command=self.select_project_directory)
path_button = tk.Button(self.center_frame, text='Select project directory',
command=self.select_project_directory)
path_button.grid(row=2, column=0, columnspan=2)
self.confirm_button = tk.Button(self.main_frame, text='Confirm', command=self.form_creation,
......@@ -112,7 +115,8 @@ class Application(tk.Frame):
self.selected_forms = []
for i, var in enumerate(self.checkbox_vars):
if var.get() == 1:
if var.get() != 0:
print(list(self.possible_forms.keys())[i])
self.selected_forms.append(list(self.possible_forms.keys())[i])
self.project_name = self.name_entry.get()
......@@ -127,7 +131,9 @@ class Application(tk.Frame):
self.form_handler.show_forms(0)
self.confirm_button.config(text='Create', command=self.form_finish, state='disabled')
self.center_frame.winfo_toplevel().bind('<<EntryStateChanged>>', lambda *_: self.check_mandatory(self.form_handler.form_frame_list[0], self.confirm_button))
self.center_frame.winfo_toplevel().bind('<<EntryStateChanged>>',
lambda *_: self.check_mandatory(self.form_handler.form_frame_list[0],
self.confirm_button))
def form_finish(self):
''' This method is used to finish the creation of the dataset description of the new BIDS project.
......@@ -141,7 +147,11 @@ class Application(tk.Frame):
self.form_handler.show_forms(0)
self.confirm_button.config(text='Confirm', command=self.next_step, state='disabled')
self.form_handler.frame.winfo_toplevel().bind('<<EntryStateChanged>>', lambda *_: self.check_mandatory(self.form_handler.form_frame_list[0], self.confirm_button))
if '.md' in self.form_handler.form_frame_list[0].form[0]:
self.confirm_button.config(state='normal')
self.form_handler.frame.winfo_toplevel().bind('<<EntryStateChanged>>', lambda *_: self.check_mandatory(
self.form_handler.form_frame_list[0], self.confirm_button))
def next_step(self):
''' This method is used to go to the next step of the creation of the new BIDS project.
......@@ -182,7 +192,8 @@ class Application(tk.Frame):
If the directory already exists, the user is prompted to overwrite it.
'''
if os.path.exists(self.project_directory):
overwrite = tk.messagebox.askyesno('Overwrite', 'The directory already exists, do you want to overwrite it?')
overwrite = tk.messagebox.askyesno('Overwrite',
'The directory already exists, do you want to overwrite it?')
if overwrite:
# Remove the directory even if it is not empty.
import shutil
......@@ -233,7 +244,8 @@ class Application(tk.Frame):
self.session_entry = tk.Entry(self.architecture_frame)
self.session_entry.grid(row=1, column=1)
self.architecture_confirm_button = tk.Button(self.architecture_frame, text='Confirm', command=self.architecture_finish)
self.architecture_confirm_button = tk.Button(self.architecture_frame, text='Confirm',
command=self.architecture_finish)
self.architecture_confirm_button.grid(row=2, column=0, columnspan=2)
def architecture_finish(self):
......@@ -266,7 +278,8 @@ class Application(tk.Frame):
os.mkdir(os.path.join(path, 'ses-' + str(j)))
self.architecture_label.config(text='Architecture of the project created')
self.architecture_show_project = tk.Button(self.architecture_frame, text='Show project state', command=self.actual_project_state)
self.architecture_show_project = tk.Button(self.architecture_frame, text='Show project state',
command=self.actual_project_state)
self.architecture_show_project.pack()
self.architecture_confirm_button = tk.Button(self.architecture_frame, text='Continue', command=self.next_step)
......@@ -301,13 +314,16 @@ class Application(tk.Frame):
self.integrate_data_frame = tk.Frame(self.main_frame)
self.integrate_data_frame.pack()
self.integrate_data_button = tk.Button(self.integrate_data_frame, text='Integrate data', command=self.integrate_data_file)
self.integrate_data_button = tk.Button(self.integrate_data_frame, text='Integrate data',
command=self.integrate_data_file)
self.integrate_data_button.pack()
self.show_project_button = tk.Button(self.integrate_data_frame, text='Show project state', command=self.actual_project_state)
self.show_project_button = tk.Button(self.integrate_data_frame, text='Show project state',
command=self.actual_project_state)
self.show_project_button.pack()
self.integrate_data_confirm_button = tk.Button(self.integrate_data_frame, text='Continue', command=self.next_step)
self.integrate_data_confirm_button = tk.Button(self.integrate_data_frame, text='Continue',
command=self.next_step)
self.integrate_data_confirm_button.pack()
def integrate_data_file(self):
......@@ -321,7 +337,8 @@ class Application(tk.Frame):
self.integrate_data_label = tk.Label(self.integrate_data_window, text='Integrate data')
self.integrate_data_label.grid(row=0, column=0)
self.integrate_data_button = tk.Button(self.integrate_data_window, text='Select file', command=self.select_experiment_file)
self.integrate_data_button = tk.Button(self.integrate_data_window, text='Select file',
command=self.select_experiment_file)
self.integrate_data_button.grid(row=1, column=0)
def select_experiment_file(self):
......@@ -346,22 +363,27 @@ class Application(tk.Frame):
self.directory = tk.filedialog.askdirectory(initialdir=self.project_directory)
self.integrate_data_window.lift()
self.integrate_data_label.config(text='File selected: ' + self.experiment_file + '\nDirectory selected: ' + self.directory)
self.integrate_data_label.config(
text='File selected: ' + self.experiment_file + '\nDirectory selected: ' + self.directory)
self.integrate_data_button.grid_forget()
self.task_label = tk.Label(self.integrate_data_window, text='Task:')
self.task_label.grid(row=1, column=0)
self.task_entry = Entry(self.integrate_data_window, label=self.task_label, row=1, column=1, columnspan=1, valid_condition='len(value) > 0')
self.task_entry = Entry(self.integrate_data_window, label=self.task_label, row=1, column=1, columnspan=1,
valid_condition='len(value) > 0')
self.acquisition_label = tk.Label(self.integrate_data_window, text='Acquisition:')
self.acquisition_label.grid(row=2, column=0)
self.acquisition_entry = Entry(self.integrate_data_window, label=self.acquisition_label, row=2, column=1, columnspan=1, valid_condition='len(value) > 0')
self.acquisition_entry = Entry(self.integrate_data_window, label=self.acquisition_label, row=2, column=1,
columnspan=1, valid_condition='len(value) > 0')
self.run_label = tk.Label(self.integrate_data_window, text='Run:')
self.run_label.grid(row=3, column=0)
self.run_entry = Entry(self.integrate_data_window, label=self.run_label, row=3, column=1, columnspan=1, valid_condition='len(value) > 0')
self.run_entry = Entry(self.integrate_data_window, label=self.run_label, row=3, column=1, columnspan=1,
valid_condition='len(value) > 0')
self.integrate_data_button = tk.Button(self.integrate_data_window, text='Integrate', command=self.integrate_data_finish, state='disabled')
self.integrate_data_button = tk.Button(self.integrate_data_window, text='Integrate',
command=self.integrate_data_finish, state='disabled')
self.integrate_data_button.grid(row=4, column=0, columnspan=2)
self.integrate_data_window.bind('<<EntryStateChanged>>', lambda *_: self.check_mandatory_integrate_data())
......@@ -425,13 +447,16 @@ class Application(tk.Frame):
self.integrate_sidecar_frame = tk.Frame(self.main_frame)
self.integrate_sidecar_frame.pack()
self.integrate_sidecar_button = tk.Button(self.integrate_sidecar_frame, text='Integrate sidecar', command=self.integrate_sidecar_file)
self.integrate_sidecar_button = tk.Button(self.integrate_sidecar_frame, text='Integrate sidecar',
command=self.integrate_sidecar_file)
self.integrate_sidecar_button.pack()
self.create_sidecar_button = tk.Button(self.integrate_sidecar_frame, text='Create sidecar', command=self.create_sidecar)
self.create_sidecar_button = tk.Button(self.integrate_sidecar_frame, text='Create sidecar',
command=self.create_sidecar)
self.create_sidecar_button.pack()
self.show_project_button = tk.Button(self.integrate_sidecar_frame, text='Show project state', command=self.actual_project_state)
self.show_project_button = tk.Button(self.integrate_sidecar_frame, text='Show project state',
command=self.actual_project_state)
self.show_project_button.pack()
def integrate_sidecar_file(self):
......@@ -446,7 +471,8 @@ class Application(tk.Frame):
self.integrate_sidecar_label = tk.Label(self.integrate_sidecar_window, text='Integrate sidecar')
self.integrate_sidecar_label.grid(row=0, column=0)
self.integrate_sidecar_button = tk.Button(self.integrate_sidecar_window, text='Select file', command=self.select_sidecar_file)
self.integrate_sidecar_button = tk.Button(self.integrate_sidecar_window, text='Select file',
command=self.select_sidecar_file)
self.integrate_sidecar_button.grid(row=1, column=0)
def create_sidecar(self):
......@@ -461,7 +487,8 @@ class Application(tk.Frame):
self.integrate_sidecar_label = tk.Label(self.integrate_sidecar_window, text='Create sidecar')
self.integrate_sidecar_label.grid(row=0, column=0)
self.sidecar_type_label = tk.Label(self.integrate_sidecar_window, text='Select the type of experiment the sidecar will be applied to:')
self.sidecar_type_label = tk.Label(self.integrate_sidecar_window,
text='Select the type of experiment the sidecar will be applied to:')
self.sidecar_type_label.grid(row=1, column=0)
self.experiment_type = tk.StringVar()
......@@ -471,7 +498,8 @@ class Application(tk.Frame):
self.experiment_type_dropdown.grid(row=1, column=1)
self.experiment_type_dropdown.config(state='readonly')
self.integrate_sidecar_button = tk.Button(self.integrate_sidecar_window, text='Continue', command=self.create_sidecar_second)
self.integrate_sidecar_button = tk.Button(self.integrate_sidecar_window, text='Continue',
command=self.create_sidecar_second)
self.integrate_sidecar_button.grid(row=2, column=0)
def create_sidecar_second(self):
......@@ -497,7 +525,6 @@ class Application(tk.Frame):
self.integrate_sidecar_button.config(text='Continue', command=self.create_sidecar_third)
def select_sidecar_type(self):
''' This method is used to select the type of the sidecar to create.
......@@ -506,7 +533,8 @@ class Application(tk.Frame):
self.integrate_sidecar_window.lift()
self.integrate_sidecar_label.config(text='Create sidecar\nType selected: ' + self.sidecar_type.get())
self.change_sidecar_button = tk.Button(self.integrate_sidecar_window, text='Change type', command=self.create_sidecar)
self.change_sidecar_button = tk.Button(self.integrate_sidecar_window, text='Change type',
command=self.create_sidecar)
self.integrate_sidecar_button.config(text='Create', command=self.create_sidecar_second, state='normal')
......@@ -528,10 +556,12 @@ class Application(tk.Frame):
self.form_handler = FormHandler(self.integrate_sidecar_window, [self.sidecar_type.get()], 'res/Sidecars.json')
self.form_handler.show_forms(0)
self.integrate_sidecar_button = tk.Button(self.integrate_sidecar_window, text='Confirm', command=self.create_sidecar_finish, state='disabled')
self.integrate_sidecar_button = tk.Button(self.integrate_sidecar_window, text='Confirm',
command=self.create_sidecar_finish, state='disabled')
self.integrate_sidecar_button.grid(row=2, column=0)
self.form_handler.frame.winfo_toplevel().bind('<<EntryStateChanged>>', lambda *_: self.check_mandatory(self.form_handler.form_frame_list[0], self.integrate_sidecar_button))
self.form_handler.frame.winfo_toplevel().bind('<<EntryStateChanged>>', lambda *_: self.check_mandatory(
self.form_handler.form_frame_list[0], self.integrate_sidecar_button))
def create_sidecar_finish(self):
''' This method is used to finish the creation of the sidecar of the new BIDS project.
......@@ -548,7 +578,8 @@ class Application(tk.Frame):
self.experiments_files = []
self.integrate_sidecar_label.config(text='Sidecar created')
self.integrate_sidecar_button.config(text='Select experiments', command=lambda: self.select_experiments(True), state='normal')
self.integrate_sidecar_button.config(text='Select experiments', command=lambda: self.select_experiments(True),
state='normal')
def select_sidecar_file(self):
''' This method is used to select the file to integrate to the new BIDS project.
......@@ -561,13 +592,15 @@ class Application(tk.Frame):
self.integrate_sidecar_window.lift()
self.integrate_sidecar_label.config(text='File selected: ' + self.sidecar_file)
self.dropdown_label = tk.Label(self.integrate_sidecar_window, text='Select the type of the experiment files the sidecar will be applied to:')
self.dropdown_label = tk.Label(self.integrate_sidecar_window,
text='Select the type of the experiment files the sidecar will be applied to:')
self.dropdown_label.grid(row=2, column=0)
self.experiment_type = tk.StringVar()
self.experiment_type.set('eeg')
self.sidecar_type_dropdown = ttk.Combobox(self.integrate_sidecar_window, textvariable=self.experiment_type)
self.sidecar_type_dropdown['values'] = json.load(open(os.path.join(os.path.dirname(__file__), 'res/ModalityFiles.json'))).keys()
self.sidecar_type_dropdown['values'] = json.load(
open(os.path.join(os.path.dirname(__file__), 'res/ModalityFiles.json'))).keys()
self.sidecar_type_dropdown.grid(row=2, column=1)
self.sidecar_type_dropdown.config(state='readonly')
......@@ -580,7 +613,8 @@ class Application(tk.Frame):
The user is guided through the process of finishing the selection of the file to integrate to the new BIDS project.
The user is also prompted to select the experiments to apply the sidecar to.
'''
self.integrate_sidecar_label.config(text='File selected: ' + self.sidecar_file + '\nType: ' + self.experiment_type.get())
self.integrate_sidecar_label.config(
text='File selected: ' + self.sidecar_file + '\nType: ' + self.experiment_type.get())
self.dropdown_label.config(text='Select the type of the sidecar:')
......@@ -595,7 +629,6 @@ class Application(tk.Frame):
self.integrate_sidecar_button.grid(row=3, column=0)
self.experiments_files = []
def select_experiments(self, create=False):
''' This method is used to select the experiments to apply the sidecar to.
......@@ -607,14 +640,18 @@ class Application(tk.Frame):
self.dropdown_label.destroy()
self.experiments_files.append(tk.filedialog.askopenfilename(initialdir=self.project_directory))
self.integrate_sidecar_window.lift()
self.integrate_sidecar_label.config(text='File selected: ' + self.sidecar_file + '\nType: ' + self.sidecar_type.get() + '\nExperiments selected: ' + str(self.experiments_files))
self.integrate_sidecar_label.config(
text='File selected: ' + self.sidecar_file + '\nType: ' + self.sidecar_type.get() + '\nExperiments selected: ' + str(
self.experiments_files))
# To Do : add buttons to select all the experiments of a subject or a session etc.
self.add_experiment_button = tk.Button(self.integrate_sidecar_window, text='Add experiment', command=lambda: self.select_experiments(create))
self.add_experiment_button = tk.Button(self.integrate_sidecar_window, text='Add experiment',
command=lambda: self.select_experiments(create))
self.add_experiment_button.grid(row=2, column=0)
if not create:
self.integrate_sidecar_button.config(text='Integrate', command=self.integrate_sidecar_finish, state='normal')
self.integrate_sidecar_button.config(text='Integrate', command=self.integrate_sidecar_finish,
state='normal')
self.integrate_sidecar_button.grid(row=3, column=0)
else:
self.integrate_sidecar_button.config(text='Integrate', command=self.place_created_sidecar, state='normal')
......@@ -635,7 +672,8 @@ class Application(tk.Frame):
self.integrate_sidecar_label = tk.Label(self.integrate_sidecar_window, text='Integrating sidecar...')
self.integrate_sidecar_label.pack()
self.integrate_sidecar_button = tk.Button(self.integrate_sidecar_window, text='Leave', command=self.integrate_sidecar_window.destroy)
self.integrate_sidecar_button = tk.Button(self.integrate_sidecar_window, text='Leave',
command=self.integrate_sidecar_window.destroy)
self.integrate_sidecar_button.pack()
path = self.get_optimal_files(self.experiments_files, self.sidecar_type.get())
......@@ -655,7 +693,8 @@ class Application(tk.Frame):
path_list = []
no_shared = False
if emplacement.keys().__len__() == self.number_of_subjects or (emplacement.keys().__len__() >= self.number_of_subjects/2 and self.number_of_subjects > 2):
if emplacement.keys().__len__() == self.number_of_subjects or (
emplacement.keys().__len__() >= self.number_of_subjects / 2 and self.number_of_subjects > 2):
concerned_files = []
for sub in emplacement.keys():
for ses in emplacement[sub].keys():
......@@ -666,7 +705,8 @@ class Application(tk.Frame):
no_shared = True
else:
Path(path).touch()
if Tools.verify_inheritance(path, self.project_directory, self.project_directory, experiments_files, self.experiment_type.get()):
if Tools.verify_inheritance(path, self.project_directory, self.project_directory, experiments_files,
self.experiment_type.get()):
path_list.append(path)
else:
no_shared = True
......@@ -675,7 +715,8 @@ class Application(tk.Frame):
no_shared = False
for sub in emplacement.keys():
first_if = False
if emplacement[sub].keys().__len__() == self.number_of_sessions or (emplacement[sub].keys().__len__() >= self.number_of_sessions/2 and self.number_of_sessions > 2):
if emplacement[sub].keys().__len__() == self.number_of_sessions or (emplacement[
sub].keys().__len__() >= self.number_of_sessions / 2 and self.number_of_sessions > 2):
first_if = True
concerned_files = []
for ses in emplacement[sub].keys():
......@@ -686,7 +727,8 @@ class Application(tk.Frame):
no_shared = True
else:
Path(path).touch()
if Tools.verify_inheritance(path, self.project_directory, self.project_directory + '/' + sub, experiments_files, self.experiment_type.get()):
if Tools.verify_inheritance(path, self.project_directory, self.project_directory + '/' + sub,
experiments_files, self.experiment_type.get()):
path_list.append(path)
else:
no_shared = True
......@@ -697,7 +739,8 @@ class Application(tk.Frame):
concerned_files.extend(emplacement[sub][ses])
path = Tools.find_shared_entities(concerned_files)
# To Do automate the selection of the data type folder
path_list.append(self.project_directory + '/' + sub + '/' + ses + Tools.get_type_from_extension(concerned_files[0].split('.')[-1]) + path + sidecar_type)
path_list.append(self.project_directory + '/' + sub + '/' + ses + Tools.get_type_from_extension(
concerned_files[0].split('.')[-1]) + path + sidecar_type)
return path_list
def get_entities(self, experiments_files):
......@@ -746,7 +789,8 @@ class Application(tk.Frame):
self.integrate_sidecar_label = tk.Label(self.integrate_sidecar_window, text='Placing sidecar...')
self.integrate_sidecar_label.grid(row=0, column=0)
self.integrate_sidecar_button = tk.Button(self.integrate_sidecar_window, text='Leave', command=self.integrate_sidecar_window.destroy)
self.integrate_sidecar_button = tk.Button(self.integrate_sidecar_window, text='Leave',
command=self.integrate_sidecar_window.destroy)
self.integrate_sidecar_button.grid(row=1, column=0)
path = self.get_optimal_files(self.experiments_files, self.sidecar_type.get())
......
import tkinter as tk
# Necessary for the text_to_condition function
import re
from BIDSHandler.CreationTool.ToolTipHandler import CreateToolTip
......
......@@ -31,15 +31,30 @@ class Form:
self.create_form_json()
elif '.tsv' in self.form[0]:
self.create_form_tsv()
elif '.md' in self.form[0]:
self.create_form_md()
def create_form_json(self):
self.entries = EntryManager.create_entry_from_json(self.form, self.frame, self.help_icon)
def create_form_md(self):
text_entry = tk.Text(self.frame, height=10, width=50)
text_entry.grid(row=self.current_row, column=0, columnspan=5, rowspan=10)
self.current_row += 10
help_label = tk.Label(self.frame, image=self.help_icon)
help_label.grid(row=self.current_row, column=3)
CreateToolTip(help_label, 'This field is a markdown field.\n'
'You can write your text in markdown format.\n'
'To learn more about markdown, visit this link: https://www.markdownguide.org/basic-syntax/')
self.entries.append(text_entry)
def is_valid_mandatory(self):
if '.json' in self.form[0]:
if '.md' in self.form[0]:
return True
elif '.json' in self.form[0]:
for entry in self.entries:
if entry.state == 'invalid' and self.form[1][entry.label.cget('text')][
'requirement level'] == 'required':
if entry.state == 'invalid' and self.form[1][entry.label.cget('text')]['requirement level'] == 'required':
return False
return True
elif '.tsv' in self.form[0]:
......@@ -76,7 +91,6 @@ class Form:
self.validation_label.config(image=self.invalid_icon)
return False
self.validation_label.config(image=self.valid_icon)
return True
def save_form(self, path):
......@@ -84,6 +98,8 @@ class Form:
self.save_form_json(path)
elif '.tsv' in self.form[0]:
self.save_form_tsv(path)
elif '.md' in self.form[0]:
self.save_form_md(path)
def save_form_json(self, path):
data = {}
......@@ -93,6 +109,10 @@ class Form:
with open(os.path.join(path, self.form[0]), 'w') as file:
json.dump(data, file)
def save_form_md(self, path):
with open(os.path.join(path, self.form[0]), 'w') as file:
file.write(self.entries[0].get('1.0', tk.END))
def create_form_tsv(self):
table_frame = tk.Frame(self.frame)
table_frame.grid(row=self.current_row, column=0, columnspan=5)
......
......@@ -2,7 +2,7 @@
"dataset_description.json": "required",
"participants.tsv": "required",
"participants.json": "recommended",
"README": "recommended",
"README.md": "recommended",
"CHANGES": "recommended",
"LICENSE": "recommended",
"CITATION.cff": "optional"
......
......@@ -141,5 +141,13 @@
},
"participants.json" : {
"linked_file": "participants.tsv"
},
"README.md" : {
"Description" : {
"requirement level" : "recommended",
"multiple" : false,
"description" : "Description of the dataset",
"valid condition": "len(value) > 0"
}
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment