Skip to content

add newer version of the codebase to create cobidas schemas #6

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions tools/cobidas/convert_csv_to_schema.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import os
from create_schema import create_schema

schema_to_create = ["neurovault", "pet", "mri", "eyetracker"]

# -----------------------------------------------------------------------------
# PARAMETERS
# -----------------------------------------------------------------------------
# modify the following lines to match your needs

# OUTPUT_DIR ----------------------------------------
# where the files will be written on your machine: the local repository
# corresponding to the remote where of the reproschema will be hosted


OUTPUT_DIR = "/home/remi/github/cobidas_chckls"
# OUTPUT_DIR = "/home/remi/github/cobidas-PET"
# OUTPUT_DIR = "/home/remi/github/cobidas"
# OUTPUT_DIR = "/home/remi/github/cobidas-eyetracker"

# REMOTE_REPO ----------------------------------------
# Placeholder to insert in all instances of the remote repo that will host the
# schema representation
# Most likely you just need to replace Remi-Gau in the following line by your
# github username

REMOTE_REPO = "https://raw.githubusercontent.com/Remi-Gau/cobidas_chckls/"
# REMOTE_REPO = "https://raw.githubusercontent.com/Remi-Gau/cobidas-PET/"
# REMOTE_REPO = "https://raw.githubusercontent.com/ohbm/cobidas/"
# REMOTE_REPO = "https://raw.githubusercontent.com/Remi-Gau/cobidas-eyetracker/"

# -----------------------------------------------------------------------------
# RUN
# -----------------------------------------------------------------------------

for schema in schema_to_create:

protocol = create_schema(schema, OUTPUT_DIR)

print(
"\n\n"
+ "---------------------------------------------------------------"
+ "\nYou can view this protocol here:\n"
+ "https://www.repronim.org/reproschema-ui/#/?url="
+ os.path.join(
REMOTE_REPO, "master", "protocols", protocol.dir, protocol.get_filename()
)
+ "\n"
+ "--------------------------------------------------------------"
+ "\n"
+ "https://www.repronim.org/reproschema-ui/#/?url=url-to-protocol-schema"
+ "\n"
+ "https://www.repronim.org/reproschema-ui/#/activities/0?url=url-to-activity-schema"
+ "\n"
+ "--------------------------------------------------------------"
+ "\n\n",
)
144 changes: 144 additions & 0 deletions tools/cobidas/create_schema.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
import os
import json


def create_schema(schema_to_create, OUTPUT_DIR):
"""
This takes the content of the a csv file and turns it into a
reproschema protocol.
This loops through the items of the csv and creates a new reproschema
activity with every new checklist "section" it encouters: this new activity
will be added to the protocol.
Every new item encountered is added to the current activity.
"""

import csv
from reproschema_protocol import ReproschemaProtocol
from item import get_item_info

# -----------------------------------------------------------------------------
# START
# -----------------------------------------------------------------------------

input_file, csv_info = return_protocol_details(schema_to_create)

protocol_name = schema_to_create
protocol = ReproschemaProtocol()
protocol.set_defaults(protocol_name)

# create output directories
if not os.path.exists(os.path.join(OUTPUT_DIR, "protocols", protocol.dir)):
os.makedirs(os.path.join(OUTPUT_DIR, "protocols", protocol.dir))

# to check if we got to a new section while looping through items
this_section = ""
activity = []

with open(input_file, "r") as csvfile:
PROTOCOL_METADATA = csv.reader(csvfile)
for row in PROTOCOL_METADATA:

item_info = get_item_info(row, csv_info)

if item_info["name"] != []:

protocol, activity, this_section = create_update_activity(
row,
csv_info,
protocol,
activity,
item_info,
this_section,
OUTPUT_DIR,
)

create_new_item(
item_info, activity, row, csv_info, OUTPUT_DIR,
)

protocol.sort()

protocol.write(os.path.join(OUTPUT_DIR, "protocols", protocol.dir))

return protocol


def return_protocol_details(schema_to_create):

source_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..")
csv_dir = os.path.join("inputs", "csv")

input_file = os.path.join(
source_dir, csv_dir, "cobidas_" + schema_to_create + ".csv"
)
data_dictionnary_file = os.path.join(
source_dir, csv_dir, "cobidas_" + schema_to_create + ".json"
)

with open(data_dictionnary_file) as f:
csv_info = json.load(f)

return input_file, csv_info


def create_update_activity(
row, csv_info, protocol, activity, item_info, this_section, OUTPUT_DIR
):

from reproschema_activity import ReproschemaActivity

# -------------------------------------------------------------------
# detect if this is a new section if so it will create a new activity
# -------------------------------------------------------------------
if row[csv_info["section"]["col"]] != this_section:

# update section name
this_section = row[csv_info["section"]["col"]]
section = this_section.replace(" ", "_")

activity = ReproschemaActivity()

activity_name = protocol.get_name() + "_" + section
activity.set_defaults(activity_name)

pref_label = row[csv_info["act_pref_label"]["col"]]
activity.set_pref_label(pref_label)

URI = "../../activities/" + activity.get_name() + "/" + activity.get_filename()
activity.set_URI(URI)

# create dir for this section
if not os.path.exists(
os.path.join(OUTPUT_DIR, "activities", activity.get_name())
):
os.makedirs(os.path.join(OUTPUT_DIR, "activities", activity.get_name()))
os.makedirs(
os.path.join(OUTPUT_DIR, "activities", activity.get_name(), "items")
)

protocol.append_activity(activity)

print(activity.get_filename())

activity.update_activity(item_info)

activity.sort()

activity.write(os.path.join(OUTPUT_DIR, "activities", activity.get_name()))

return protocol, activity, this_section


def create_new_item(item_info, activity, row, csv_info, OUTPUT_DIR):

from item import define_new_item

print(" " + item_info["name"])
print(" " + item_info["question"])
print(" " + item_info["resp_type"])

item = define_new_item(item_info)

item.sort()

item.write(os.path.join(OUTPUT_DIR, "activities", activity.get_name(), "items"))
191 changes: 191 additions & 0 deletions tools/cobidas/item.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
def get_item_info(row, csv_info):

item_name = []

item_col = csv_info["item"]["col"]
item_col_name = csv_info["item"]["name"]

# we want to skip the header and only include items with 1 in the include column (if it exists)
incl_col = csv_info["include"]["col"]
if row[item_col] == item_col_name or (incl_col != [] and row[incl_col] != "1"):

print(" skipping item")

return {"name": item_name}

item_name = row[item_col].replace("\n", "")

question_col = csv_info["question"]["col"]
question = row[question_col].replace("\n", "")

resp_type_col = csv_info["resp_type"]["col"]
response_type = row[resp_type_col]

choice_col = csv_info["choice"]["col"]
response_choices = row[choice_col].split(" | ")

preamble = csv_info["preamble"]["col"]

visibility = get_visibility(row, csv_info)

mandatory = get_mandatory(row, csv_info)

return {
"name": item_name,
"question": question,
"resp_type": response_type,
"choices": response_choices,
"visibility": visibility,
"preamble": preamble,
"mandatory": mandatory,
}


def get_visibility(row, csv_info):

visibility = True

if row[csv_info["vis"]["col"]] != "1":

visibility = row[csv_info["vis"]["col"]]

# vis_conditions = row[choice_col].split(',')
#
# for i, cdt in enumerate(vis_conditions):
#
# visibility['choices'].append({
# 'schema:name': opt,
# 'schema:value': i,
# '@type': 'schema:option'
# })

return visibility


def get_mandatory(row, csv_info):

mandatory = False

if row[csv_info["mandatory"]["col"]] == "1":

mandatory = True

return mandatory


def define_new_item(item_info):
"""
define jsonld for this item
"""

from reproschema_item import ReproschemaItem

item = ReproschemaItem()

item.set_defaults(item_info["name"])

item.set_question(item_info["question"])

item = define_response_choices(item, item_info["resp_type"], item_info["choices"])

return item


def define_response_choices(item, response_type, response_choices):

# in case we have one of the basic response type
# with no response choice involved
item.set_basic_response_type(response_type)

if response_type == "radio":
response_options = list_responses_options(response_choices)
item.set_input_type_as_radio(response_options)

# if we have a dropdown menu
# TODO: change to select item to have a REAL dropdown as soon as radio item
# offer the possibility to have an "Other" choice that opens a text box
elif response_type == "dropdown":
response_options = list_responses_options(response_choices)
item.set_input_type_as_radio(response_options)

elif response_type == "slider":
# response_options = slider_response(response_choices, min_label, max_label)
# item.set_input_type_as_slider(response_options)
item.set_input_type_as_slider()

if (
response_type == "boolean"
or response_type == "mri_software"
or response_type == "interpolation"
or response_type == "cost_function"
or response_type == "multiple_comparison"
):

value_constraint = response_type

if "_" in response_type:
"""
if response_type is "test_name" in the spreadsheet then the
corresponding response option value constraints file is
testNameValueConstraints, so we need to do some string magic
"""

response_type = response_type.split("_")

# This does not cover the cases where the string has more than
# 2 elements separated by "_"
value_constraint = (
response_type[0] + response_type[1][0].upper() + response_type[1][1:]
)

response_options = "../../../response_options/"
response_options += value_constraint
response_options += "ValueConstraints"

item.set_input_type_as_radio(response_options)

return item


def list_responses_options(response_choices):

response_options = {"choices": []}

for i, opt in enumerate(response_choices):

response_options["choices"].append({"name": opt, "value": i, "@type": "option"})

response_options["choices"].append(
{"name": "Other", "value": len(response_choices), "@type": "option"}
)

response_options["minValue"] = 0
response_options["maxValue"] = len(response_choices)

return response_options


def slider_response(response_choices, min_label, max_label):

import numpy

# min = int(response_choices[0])
# max = int(response_choices[1])
# steps = int(response_choices[2]) + 1 if len(response_choices) == 3 else 11
min = 1
max = 11
steps = 11
response_options = {
"valueType": "xsd:integer",
"minValue": min,
"maxValue": max,
"choices": [],
}

for i in numpy.linspace(min, max, steps):
response_options["choices"].append({"value": int(i), "@type": "option"})

response_options["choices"][0]["name"] = min_label
response_options["choices"][-1]["name"] = max_label

return response_options
Loading