{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Light Sensitivity Experiment: \n", "\n", "## Reporting a repeated treatment design with `ISA create mode`\n", "\n", "This example creates `ISA study descriptor` for study with sequential treatments organized in an arm. This shows how to use objects from the `isatools.create` component in a granular fashion. It creates each `Element` of the Study `Arm` at a time.\n", "Finally, the `study design plan` is shown by serializing the `ISA Study Design Model` content as an `ISA_design` JSON document, which can be rendered in various ways (tables, figures)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Study metadata" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "# If executing the notebooks on `Google Colab`,uncomment the following command \n", "# and run it to install the required python libraries. Also, make the test datasets available.\n", "\n", "# !pip install -r requirements.txt" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": false }, "outputs": [], "source": [ "import os\n", "import datetime\n", "import json\n", "from collections import OrderedDict\n", "from isatools.model import (\n", " Investigation,\n", " Study,\n", " Sample,\n", " OntologyAnnotation,\n", " StudyFactor,\n", " FactorValue,\n", " Characteristic,\n", " Source,\n", " Protocol,\n", " Process\n", ")\n", "from isatools.create.model import (\n", " Treatment,\n", " NonTreatment,\n", " StudyDesign,\n", " StudyCell,\n", " StudyArm,\n", " ProductNode,\n", " SampleAndAssayPlan,\n", " AssayGraph\n", ")\n", "from isatools.create.constants import (\n", " BASE_FACTORS,\n", " SCREEN,\n", " RUN_IN,\n", " WASHOUT,\n", " FOLLOW_UP,\n", " SAMPLE,\n", " EXTRACT,\n", " LABELED_EXTRACT,\n", " DATA_FILE\n", ")\n", "from isatools.isatab import dumps\n", "from isatools.isajson import ISAJSONEncoder\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": false }, "outputs": [], "source": [ "investigation = Investigation()\n", "investigation1 = Investigation() # to be used with the study create function\n", "study = Study(filename=\"s_study_xover.txt\")\n", "study.identifier = \"elifesprint2019-1\"\n", "study.title = \"elifesprint2019-1: light sensitivity\"\n", "study.description = \"a study about light sensitivity difference between a control population (n=10) and a genotype A population (n=10).\"\n", "study.submission_date = str(datetime.datetime.today())\n", "study.public_release_date = str(datetime.datetime.today())\n", "study.sources = [Source(name=\"source1\")]\n", "study.samples = [Sample(name=\"sample1\")]\n", "study.protocols = [Protocol(name=\"sample collection\")]\n", "study.process_sequence = [Process(executes_protocol=study.protocols[-1], inputs=[study.sources[-1]], outputs=[study.samples[-1]])]\n", "investigation.studies = [study]\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "# Let's see the object :\n", "investigation" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": false }, "outputs": [], "source": [ "# print(dumps(investigation))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": false }, "outputs": [], "source": [ "# print(json.dumps(investigation, cls=ISAJSONEncoder, sort_keys=True, indent=4, separators=(',', ': ')))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1. Creation of the first `ISA Study Design Element` and setting *both* `element_type` AND `duration_unit` attributes" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": false }, "outputs": [], "source": [ "# IMPORTANT: note how duration_unit value is supplied as an OntologyAnnotation object\n", "nte1 = NonTreatment(element_type='screen', duration_unit=OntologyAnnotation(term=\"days\"))\n", "print(nte1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 2. Creation of another `ISA Study Design Element`, of type `Treatment`" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": false }, "outputs": [], "source": [ "te1 = Treatment()\n", "te1.type='radiological intervention'\n", "print(te1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 2.1 defining the first treatment as a vector of ISA factor values:\n", "\n", "Under \"ISA Study Design Create mode\", a `Study Design Element` of type `Treatment` needs to be defined by a vector of `Factors` and their respective associated `Factor Values`. This is done as follows:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": false }, "outputs": [], "source": [ "\n", "f1 = StudyFactor(name='light', factor_type=OntologyAnnotation(term=\"electromagnetic energy\"))\n", "f1v = FactorValue(factor_name=f1, value=\"visible light at 3000K produced by LED array\")\n", "f2 = StudyFactor(name='dose', factor_type=OntologyAnnotation(term=\"quantity\"))\n", "\n", "# IMPORTANT: note how *FactorValue value* is supplied as an *numeral*\n", "f2v = FactorValue(factor_name=f2, value=250, unit=OntologyAnnotation(term='lux'))\n", "f3 = StudyFactor(name='duration', factor_type=OntologyAnnotation(term=\"time\"))\n", "f3v = FactorValue(factor_name=f3, value=1, unit=OntologyAnnotation(term='hr'))\n", "\n", "print(f1v,f2v)\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": false }, "outputs": [], "source": [ "#assigning the factor values declared above to the ISA treatment element\n", "te1.factor_values = [f1v,f2v,f3v]\n", "print(te1)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 3. Creation of a second `ISA Study Design Element`, of type `Treatment`, following the same pattern." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": false }, "outputs": [], "source": [ "te3 = Treatment()\n", "te3.type = 'radiological intervention'\n", "rays = StudyFactor(name='light', factor_type=OntologyAnnotation(term=\"electromagnetic energy\"))\n", "\n", "raysv = FactorValue(factor_name=rays, value='visible light at 3000K produced by LED array')\n", "rays_intensity = StudyFactor(name='dose', factor_type=OntologyAnnotation(term=\"quantity\"))\n", "rays_intensityv= FactorValue(factor_name=rays_intensity, value = 250, unit=OntologyAnnotation(term='lux'))\n", "rays_duration = StudyFactor(name = 'duration', factor_type=OntologyAnnotation(term=\"time\"))\n", "rays_durationv = FactorValue(factor_name=rays_duration, value=1, unit=OntologyAnnotation(term='hour'))\n", "\n", "te3.factor_values = [raysv,rays_intensityv,rays_durationv]\n", "print(te3)\n", " " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 4. Creation of 'wash out' period as an `ISA Study Design Element`." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": false }, "outputs": [], "source": [ "# Creation of another ISA element, which is not a Treatment element, which is of type `screen` by default\n", "# nte2 = NonTreatment()\n", "# nte2.type = 'washout'\n", "# net2.duration_unit=OntologyAnnotation(term=\"days\")\n", "\n", "nte2 = NonTreatment(element_type='washout', duration_unit=OntologyAnnotation(term=\"days\"))\n", "print(nte2)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": false }, "outputs": [], "source": [ "# setting the factor values associated with 'default' DURATION Factor associated with such elements\n", "nte2.duration.value=2\n", "nte2.duration.unit=OntologyAnnotation(term=\"weeks\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 5. Creation of 'follow-up' period as an `ISA Study Design Element`." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": false }, "outputs": [], "source": [ "nte3 = NonTreatment(element_type='follow-up', duration_value=1, duration_unit=OntologyAnnotation(term=\"month\"))\n", "#print(nte3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 6. Creation of the associated container, known as an ISA `Cell` for each ISA `Element`.\n", "In this example, a single `Element` is hosted by a `Cell`, which must be named. In more complex designs (e.g. study designs with assymetric arms), a `Cell` may contain more than one `Element`, hence the list attribute." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": false }, "outputs": [], "source": [ "st_cl1= StudyCell(name=\"st_cl1\", elements=[nte1])\n", "st_cl2= StudyCell(name=\"st_cl2\", elements=[te1])\n", "st_cl3= StudyCell(name=\"st_cl3\", elements=[nte2])\n", "st_cl4= StudyCell(name=\"st_cl4\", elements=[te3])\n", "st_cl5= StudyCell(name=\"st_cl5\", elements=[nte3])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 7. Creation of an ISA `Study Arm` and setting the number of subjects associated to that unique sequence of ISA `Cell`s." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": false }, "outputs": [], "source": [ "genotype_cat = OntologyAnnotation(term=\"genotype\")\n", "genotype_value1 = OntologyAnnotation(term=\"control - normal\")\n", "genotype_value2 = OntologyAnnotation(term=\"mutant\")\n", "\n", "arm1 = StudyArm(\n", " name='Arm 1', \n", " group_size=2\n", ")\n", "\n", "arm1.source_type=Characteristic(\n", " category=genotype_cat,\n", " value=genotype_value1\n", ")\n", "\n", "print(arm1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 8. Declaring an ISA `Sample Assay Plan`, defining which `Sample` are to be collected and which `Assay`s to be used" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "whole_patient=ProductNode(\n", " id_=\"MAT1\",\n", " name=\"subject\",\n", " node_type=SAMPLE,\n", " size=1,\n", " characteristics=[\n", " Characteristic(\n", " category=OntologyAnnotation(term='organism part'), \n", " value=OntologyAnnotation(term='whole organism')\n", " )\n", " ]\n", ")\n", "\n", "saliva=ProductNode(\n", " id_=\"MAT2\",\n", " name=\"saliva\",\n", " node_type=SAMPLE,\n", " size=1,\n", " characteristics=[\n", " Characteristic(\n", " category=OntologyAnnotation(term='organism part'),\n", " value=OntologyAnnotation(term='saliva')\n", " )\n", " ]\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here we load an isa assay definition in the form of an ordered dictionary. It corresponds to an ISA configuration assay table but expressed in JSON." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We now show how to create an new AssayGraph structure from scratch, as if we were defining a completely new assay type." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "light_sensitivity_phenotyping_1 = OrderedDict([\n", " ('measurement_type', OntologyAnnotation(term='melatonine concentration')),\n", " ('technology_type', OntologyAnnotation(term='radioimmunoprecipitation assay')),\n", " ('extraction', {}),\n", " ('extract', [\n", " {\n", " 'node_type': EXTRACT,\n", " 'characteristics_category': OntologyAnnotation(term='extract type'),\n", " 'characteristics_value': OntologyAnnotation(term='extract'),\n", " 'size': 1,\n", " 'technical_replicates': None,\n", " 'is_input_to_next_protocols': True\n", " }]),\n", " \n", " ('radioimmunoprecipitation', {\n", " OntologyAnnotation(term='instrument'): [OntologyAnnotation(term='Beckon Dickison XYZ')],\n", " OntologyAnnotation(term='antibody'): [OntologyAnnotation(term='AbCam antiMelatonine ')],\n", " OntologyAnnotation(term='time point'): [OntologyAnnotation(term='1 hr'),\n", " OntologyAnnotation(term='2 hr')]\n", " }),\n", " ('raw_data_file', [\n", " {\n", " 'node_type': DATA_FILE,\n", " 'size': 1,\n", " 'technical_replicates': 1,\n", " 'is_input_to_next_protocols': False\n", " }\n", " ])\n", "])\n", "\n", "\n", "light_sensitivity_phenotyping_2 = OrderedDict([\n", " ('measurement_type', OntologyAnnotation(term='light sensitivity')),\n", " ('technology_type', OntologyAnnotation(term='electroencephalography')),\n", " ('data_collection', {\n", " OntologyAnnotation(term='instrument'): [OntologyAnnotation(term='Somnotouch')],\n", " OntologyAnnotation(term='sampling_rate'): [OntologyAnnotation(term='200 Hz')],\n", " OntologyAnnotation(term='time point'): [OntologyAnnotation(term='1 hr'),\n", " OntologyAnnotation(term='2 hr')]\n", " }),\n", " ('raw_data_file', [\n", " {\n", " 'node_type': DATA_FILE,\n", " 'size': 1,\n", " 'technical_replicates': 1,\n", " 'is_input_to_next_protocols': False\n", " }\n", " ])\n", "])\n", "\n", "light_sensitivity_phenotyping_3 = OrderedDict([\n", " ('measurement_type', OntologyAnnotation(term='light sensitivity phenotyping')),\n", " ('technology_type', OntologyAnnotation(term='direct measurement')),\n", " ('data_collection', {\n", " OntologyAnnotation(term='variables'): [OntologyAnnotation(term='sleepiness'),\n", " OntologyAnnotation(term='heart rate'),\n", " OntologyAnnotation(term='pupilla size')],\n", " OntologyAnnotation(term='time point'): [OntologyAnnotation(term='1 hr'),\n", " OntologyAnnotation(term='2 hr')]\n", " }),\n", " ('raw_data_file', [\n", " {\n", " 'node_type': DATA_FILE,\n", " 'size': 1,\n", " 'technical_replicates': 1,\n", " 'is_input_to_next_protocols': False\n", " }\n", " ])\n", "])\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": false }, "outputs": [], "source": [ "alterness_assay_graph = AssayGraph.generate_assay_plan_from_dict(light_sensitivity_phenotyping_1)\n", "melatonine_assay_graph = AssayGraph.generate_assay_plan_from_dict(light_sensitivity_phenotyping_2)\n", "general_phenotyping_assay_graph = AssayGraph.generate_assay_plan_from_dict(light_sensitivity_phenotyping_3)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "\n", "sap1 = SampleAndAssayPlan(name='sap1', sample_plan=[whole_patient,saliva],assay_plan=[alterness_assay_graph,melatonine_assay_graph,general_phenotyping_assay_graph])\n", "\n", "sap1.add_element_to_map(sample_node=saliva, assay_graph=melatonine_assay_graph)\n", "sap1.add_element_to_map(sample_node=whole_patient, assay_graph=alterness_assay_graph)\n", "sap1.add_element_to_map(sample_node=whole_patient,assay_graph=general_phenotyping_assay_graph)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 9. Declaration of an ISA assay and linking specimen type and data acquisition plan for this assay" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "sap1.sample_to_assay_map" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 10. Build an ISA `Study Design Arm` by adding the first set of ISA `Cells` and setting the `Sample Assay Plan`" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": false }, "outputs": [], "source": [ "arm1.add_item_to_arm_map(st_cl1, sap1)\n", "# print(arm1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 11 Now expanding the `Arm` by adding a new `Cell`, which uses the same `Sample Assay Plan` as the one used in Cell #1.\n", "Of course, the `Sample Assay Plan` for this new `Cell` could be different. It would have to be to built as shown before." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": false }, "outputs": [], "source": [ "arm1.add_item_to_arm_map(st_cl2, sap1)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": false }, "outputs": [], "source": [ "# Adding the last section of the Arm, with a cell which also uses the same sample assay plan.\n", "arm1.add_item_to_arm_map(st_cl3, sap1)\n", "arm1.add_item_to_arm_map(st_cl4, sap1)\n", "arm1.add_item_to_arm_map(st_cl5, sap1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 12. Creation of additional ISA Study Arms and setting the number of subjects associated to that unique sequence of ISA Cells." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": false }, "outputs": [], "source": [ "arm2 = StudyArm(name='Arm 2')\n", "arm2.group_size=2\n", "arm2.source_type=Characteristic(category=genotype_cat,\n", " value=genotype_value2)\n", "\n", "# st_cl6= StudyCell(name=\"st_cl6\", elements=[nte1])\n", "# st_cl7= StudyCell(name=\"st_cl7\", elements=[te1])\n", "# st_cl8= StudyCell(name=\"st_cl8\", elements=[nte2])\n", "# st_cl9= StudyCell(name=\"st_cl9\", elements=[te3])\n", "# st_cl10= StudyCell(name=\"st_cl10\", elements=[nte3])\n", "\n", "\n", "\n", "arm2.source_type.category\n", "arm2.add_item_to_arm_map(st_cl1,sap1)\n", "arm2.add_item_to_arm_map(st_cl4,sap1)\n", "arm2.add_item_to_arm_map(st_cl3,sap1)\n", "arm2.add_item_to_arm_map(st_cl2,sap1)\n", "arm2.add_item_to_arm_map(st_cl5,sap1)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "arm3 = StudyArm(name='Arm 3')\n", "arm3.group_size=2\n", "arm3.source_type=Characteristic(category=genotype_cat,\n", " value=genotype_value1\n", " )\n", "arm3.add_item_to_arm_map(st_cl1,sap1)\n", "arm3.add_item_to_arm_map(st_cl2,sap1)\n", "arm3.add_item_to_arm_map(st_cl3,sap1)\n", "arm3.add_item_to_arm_map(st_cl4,sap1)\n", "arm3.add_item_to_arm_map(st_cl5,sap1)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": false }, "outputs": [], "source": [ "arm4 = StudyArm(name='Arm 4')\n", "arm4.group_size=2\n", "arm4.source_type=Characteristic(category=genotype_cat,\n", " value=genotype_value2)\n", "\n", "arm4.add_item_to_arm_map(st_cl1,sap1)\n", "arm4.add_item_to_arm_map(st_cl4,None)\n", "arm4.add_item_to_arm_map(st_cl3,sap1)\n", "arm4.add_item_to_arm_map(st_cl2,None)\n", "arm4.add_item_to_arm_map(st_cl5,sap1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 14. We can now create the ISA `Study Design` object, which will receive the `Arms` defined by the user." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": false }, "outputs": [], "source": [ "study_design_final= StudyDesign(name='trial design #1')\n", "# print(sd)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": false }, "outputs": [], "source": [ "# Adding a study arm to the study design object.\n", "study_design_final.add_study_arm(arm1)\n", "study_design_final.add_study_arm(arm2)\n", "study_design_final.add_study_arm(arm3)\n", "study_design_final.add_study_arm(arm4)\n", "\n", "study_finale = study_design_final.generate_isa_study()\n", "investigation1.studies.append(study_finale)\n", "# print(investigation1.studies[0].name)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": false }, "outputs": [], "source": [ "# Let's now serialize the ISA study design to JSON\n", "from isatools.create.model import StudyDesignEncoder\n", "\n", "f=json.dumps(study_design_final, cls=StudyDesignEncoder, sort_keys=True, indent=4, separators=(',', ': '))\n", "\n", "final_dir = os.path.abspath(os.path.join('notebook-output', 'isa-study-custom-assay-light-sensitivity'))\n", "\n", "with open(os.path.join(final_dir,'./light-sensitivity-study_design_final.json'), 'w') as isa_sdf_jf:\n", " json.dump(json.loads(f), isa_sdf_jf)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "# print(json.dumps(investigation, cls=ISAJSONEncoder, sort_keys=True, indent=4, separators=(',', ': ')))\n", "from isatools import isatab\n", "isatab.dump(investigation1, final_dir)\n", "\n", "from isatools.isatab import dump_tables_to_dataframes as dumpdf\n", "dataframes = dumpdf(investigation)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## About this notebook\n", "\n", "- authors: philippe.rocca-serra@oerc.ox.ac.uk, massimiliano.izzo@oerc.ox.ac.uk\n", "- license: CC-BY 4.0\n", "- support: isatools@googlegroups.com\n", "- issue tracker: https://github.com/ISA-tools/isa-api/issues" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.1" } }, "nbformat": 4, "nbformat_minor": 1 }