diff --git a/example/phis/quickstart.ipynb b/example/phis/quickstart.ipynb new file mode 100644 index 0000000..d1387e7 --- /dev/null +++ b/example/phis/quickstart.ipynb @@ -0,0 +1,2143 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "bb705f67-cb8a-4af0-a721-22270f7f872e", + "metadata": {}, + "source": [ + "# Phis Demo" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "8b735135-5275-4711-952c-7b1cf1141c24", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[33mWARNING [agroservices:Phis:116]: \u001b[0m \u001b[34mThe URL (https://phenome.inrae.fr/m3p/rest/) provided cannot be reached.\u001b[0m\n" + ] + } + ], + "source": [ + "from agroservices.phis.phis_interface import Phis_UI\n", + "phis = Phis_UI()" + ] + }, + { + "cell_type": "markdown", + "id": "ab23cc99-4a04-4b32-81bd-41452a56d0e2", + "metadata": {}, + "source": [ + "## Get Token" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "9bbad2bd-1c30-4853-9394-24ac84d39f40", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJvcGVuc2lsZXgiLCJzdWIiOiJtM3A6aWQvdXNlci9hY2NvdW50LnBoZW5vYXJjaGxlcHNlaW5yYWZyIiwiaWF0IjoxNzE5NTgyODg5LCJleHAiOjE3MTk1ODU1ODksImdpdmVuX25hbWUiOiJwaGVub2FyY2giLCJmYW1pbHlfbmFtZSI6ImxlcHNlIiwiZW1haWwiOiJwaGVub2FyY2hAbGVwc2UuaW5yYS5mciIsIm5hbWUiOiJwaGVub2FyY2hAbGVwc2UuaW5yYS5mciIsImxvY2FsZSI6ImVuIiwiaXNfYWRtaW4iOmZhbHNlLCJjcmVkZW50aWFsc19saXN0IjpbImFjY291bnQtYWNjZXNzIiwiZGF0YS1hY2Nlc3MiLCJkZXZpY2UtYWNjZXNzIiwiZG9jdW1lbnQtYWNjZXNzIiwiZXZlbnQtYWNjZXNzIiwiZXhwZXJpbWVudC1hY2Nlc3MiLCJmYWNpbGl0eS1hY2Nlc3MiLCJnZXJtcGxhc20tYWNjZXNzIiwiZ3JvdXAtYWNjZXNzIiwib3JnYW5pemF0aW9uLWFjY2VzcyIsInByb2plY3QtYWNjZXNzIiwicHJvdmVuYW5jZS1hY2Nlc3MiLCJzY2llbnRpZmljLW9iamVjdHMtYWNjZXNzIiwidmFyaWFibGUtYWNjZXNzIiwidm9jYWJ1bGFyeS1hY2Nlc3MiXX0.OlhdcSoLqAPO72PNIpD_lQMsN97Ep7e0c2SATARqiosJQ8N5-y1SgEOzn2DmElVusKxKzFFbLysxeUQlGwczKedeSEZGZ4TY81SFEJVNhF6pkr4VYJ6qV9dzV5PFhUM5CdvEFSBXQWqiOpeV2lNUnaEN4oHM3DJ1Nq8kQBpnLUqvVW0wisgzdcJbL5GzjzqSsGlnJsn71D37e1uAwmGZsBWBYYDfu0aApZfSpl8VW9x73vrw4fZlpjkS3f4HLibfwmjA805JLXojcbvK2ihbFV8SMSU_BhwG7IUoMhCTXWnjJ5-WK9CgqdYawmbnvs5NRPhWEMbO3OzoaQm74z0fjw\n" + ] + } + ], + "source": [ + "print(phis.token)" + ] + }, + { + "cell_type": "markdown", + "id": "8c1b7aaa-f001-4c7a-951e-a0d74edba0c3", + "metadata": {}, + "source": [ + "## Navigate data" + ] + }, + { + "cell_type": "markdown", + "id": "2888f417-39a6-4d4b-903c-c238775923be", + "metadata": {}, + "source": [ + "#### List available experiments" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "cbd24e93-8592-45b4-9fed-d2f58d34e04b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['G2WAS2022', 'ZA24']" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "phis.get_experiment()" + ] + }, + { + "cell_type": "markdown", + "id": "df52a98c-e9fc-4329-b29e-682a0dde8dcb", + "metadata": {}, + "source": [ + "#### Get specific experiment details" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "8c387ecf-d025-4f94-9c2b-11cb799f3b41", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'uri': 'm3p:id/experiment/g2was2022',\n", + " 'name': 'G2WAS2022',\n", + " 'start_date': '2022-05-15',\n", + " 'end_date': '2022-07-31',\n", + " 'description': '',\n", + " 'objective': 'G2WAS project',\n", + " 'species': [],\n", + " 'is_public': True,\n", + " 'facilities': ['m3p:id/organization/facility.phenoarch',\n", + " 'm3p:id/organization/facility.phenodyn']}" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "phis.get_experiment(experiment_name='G2WAS2022')" + ] + }, + { + "cell_type": "markdown", + "id": "a86ce348-2f3c-4c5d-b0ca-ee6b838674b3", + "metadata": {}, + "source": [ + "#### List available data" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "5638b123-4b9f-4635-9774-ef5648b91792", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[59.0,\n", + " 1524.0,\n", + " 392.0,\n", + " 61.1,\n", + " 63.5,\n", + " 65.6,\n", + " 62.0,\n", + " 58.4,\n", + " 60.5,\n", + " 68.4,\n", + " 63.0,\n", + " 63.1,\n", + " 703.4,\n", + " 1014.9,\n", + " 983.8,\n", + " 229.7,\n", + " 779.7,\n", + " 277.0,\n", + " 481.7,\n", + " 263.2,\n", + " 214.5,\n", + " 292.8,\n", + " 26.6,\n", + " 26.6,\n", + " 26.2,\n", + " 25.3,\n", + " 26.3,\n", + " 26.6,\n", + " 26.6,\n", + " 25.0,\n", + " 26.0,\n", + " 25.8,\n", + " 59.3,\n", + " 1536.0,\n", + " 411.0,\n", + " 61.3,\n", + " 63.9,\n", + " 65.2,\n", + " 62.4,\n", + " 58.7,\n", + " 60.3,\n", + " 68.8,\n", + " 63.0,\n", + " 62.9,\n", + " 1095.8,\n", + " 1085.8,\n", + " 1002.7,\n", + " 668.2,\n", + " 1039.1,\n", + " 887.7,\n", + " 548.1,\n", + " 758.4,\n", + " 451.2,\n", + " 730.5,\n", + " 26.5,\n", + " 26.5,\n", + " 26.0,\n", + " 25.4,\n", + " 26.5,\n", + " 26.6,\n", + " 26.7,\n", + " 24.8,\n", + " 25.9,\n", + " 25.8,\n", + " 59.8,\n", + " 1492.0,\n", + " 448.0,\n", + " 61.3,\n", + " 63.9,\n", + " 64.9,\n", + " 62.9,\n", + " 58.9,\n", + " 60.2,\n", + " 68.8,\n", + " 63.2,\n", + " 62.9,\n", + " 1015.9,\n", + " 814.3,\n", + " 903.4,\n", + " 913.0,\n", + " 717.1,\n", + " 272.1,\n", + " 1051.0,\n", + " 556.8,\n", + " 997.2,\n", + " 1085.3,\n", + " 26.4,\n", + " 26.5,\n", + " 26.0,\n", + " 25.5,\n", + " 26.3,\n", + " 26.5,\n", + " 26.7,\n", + " 24.8,\n", + " 25.9,\n", + " 25.8,\n", + " 57.9,\n", + " 1449.0,\n", + " 452.0,\n", + " 59.1]" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "phis.get_data(page_size=100)" + ] + }, + { + "cell_type": "markdown", + "id": "55819c69-cc9b-40df-a357-85dae9182360", + "metadata": {}, + "source": [ + "#### List available variables" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "5f272de0-ee56-496a-9b14-b1be6b280d89", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['air humidity_weather station_percentage',\n", + " 'air temperature_weather station_degree celsius',\n", + " 'CarbonDioxide_sensor_part per million',\n", + " 'diffuse PAR light_sensor_micromole.m-2.s-1',\n", + " 'direct PAR light_sensor_micromole.m-2.s-1',\n", + " 'Greenhouse_Lightning_Setpoint_Boolean',\n", + " 'Greenhouse_Shading_Setpoint_Boolean',\n", + " 'leaf temperature_thermocouple sensor_degree celsius',\n", + " 'lower near-surface infra-red radiation spectrum_wheater station_watt.m2',\n", + " 'lower solar radiation flux density_wheater station_watt.m2',\n", + " 'net irradiance_calculated variable_watt.m2',\n", + " 'PAR Light_weather station_micromole.m-2.s-1',\n", + " 'test_renaud_on_m3p_instance',\n", + " 'upper near-surface infra-red radiation spectrum_wheater station_watt.m2',\n", + " 'upper solar radiation flux density_wheater station_watt.m2',\n", + " 'weightAfter_unspecified_g',\n", + " 'weightAmount_unspecified_g',\n", + " 'weightBefore_unspecified_g']" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "phis.get_variable()" + ] + }, + { + "cell_type": "markdown", + "id": "8032a524-1e86-41bc-b85d-1fd3621fe3ea", + "metadata": {}, + "source": [ + "#### Get specific variable details" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "fab949ac-7544-4ede-ac5b-2696778c0aa2", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'uri': 'http://phenome.inrae.fr/m3p/id/variable/ev000036',\n", + " 'name': 'net irradiance_calculated variable_watt.m2',\n", + " 'entity': {'uri': 'm3p:id/variable/entity.solar', 'name': 'Solar'},\n", + " 'entity_of_interest': None,\n", + " 'characteristic': {'uri': 'http://www.ontology-of-units-of-measure.org/resource/om-2/Irradiance',\n", + " 'name': 'Irradiance'},\n", + " 'method': {'uri': 'm3p:id/variable/method.radiation_global',\n", + " 'name': 'Radiation_Global'},\n", + " 'unit': {'uri': 'http://purl.obolibrary.org/obo/UO_0000155',\n", + " 'name': 'watt per square meter'},\n", + " 'onLocal': False,\n", + " 'sharedResourceInstance': None,\n", + " 'alternative_name': None}" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "phis.get_variable(variable_name='net irradiance_calculated variable_watt.m2')" + ] + }, + { + "cell_type": "markdown", + "id": "9cf51b5d-6d54-409f-8cdf-0739e6260b5a", + "metadata": {}, + "source": [ + "#### List available projects" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "d24bf742-f2da-4ab6-8345-1a8dd5a5077e", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['Amaizing',\n", + " 'CAWaS',\n", + " 'CROPS',\n", + " 'DROPS',\n", + " 'EPPN',\n", + " 'EPPN2020',\n", + " 'EXPOSE',\n", + " 'Florimaize',\n", + " 'G2WAS',\n", + " 'Lines_VS_Hyb',\n", + " 'MYB',\n", + " 'PHENOME',\n", + " 'PHIS_Publi',\n", + " 'Progress_Genetique',\n", + " 'SelGen',\n", + " 'Sorghum genomics toolbox',\n", + " 'Test',\n", + " 'VITSEC',\n", + " 'XYZ',\n", + " 'ZTEST']" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "phis.get_project()" + ] + }, + { + "cell_type": "markdown", + "id": "1a3a4b8e-f681-4aa7-a733-f00d68278801", + "metadata": {}, + "source": [ + "#### Get specific project details" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "8a4505b9-3f38-48ce-aee6-fe56e6498755", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'uri': 'm3p:id/project/crops',\n", + " 'publisher': None,\n", + " 'publication_date': '2024-02-19T15:04:12.971969+01:00',\n", + " 'last_updated_date': None,\n", + " 'name': 'CROPS',\n", + " 'shortname': None,\n", + " 'start_date': '2014-07-01',\n", + " 'end_date': '2014-07-08',\n", + " 'description': None,\n", + " 'objective': None,\n", + " 'financial_funding': None,\n", + " 'website': None,\n", + " 'related_projects': [],\n", + " 'coordinators': [],\n", + " 'scientific_contacts': ['m3p:id/user/person.franois.tardieu'],\n", + " 'administrative_contacts': [],\n", + " 'experiments': []}" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "phis.get_project(project_name='CROPS')" + ] + }, + { + "cell_type": "markdown", + "id": "8e0ed766-a3a5-41a5-8773-095d335c96cc", + "metadata": {}, + "source": [ + "#### List available facilities" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "cff8e32f-a7b3-426c-9163-25261541fbb4", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['chambre E', 'phenoarch', 'PHENOPSIS-1', 'PHENOPSIS-2', 'PHENOPSIS-3']" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "phis.get_facility()" + ] + }, + { + "cell_type": "markdown", + "id": "683fe09d-ee07-4a10-b19e-76849afdf626", + "metadata": {}, + "source": [ + "#### Get specific facility details" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "12aaf697-7208-4602-8a0c-d311c9571c85", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'uri': 'm3p:id/organization/facility.phenoarch',\n", + " 'publisher': None,\n", + " 'publication_date': None,\n", + " 'last_updated_date': None,\n", + " 'rdf_type': 'vocabulary:Greenhouse',\n", + " 'rdf_type_name': 'greenhouse',\n", + " 'name': 'phenoarch',\n", + " 'organizations': [],\n", + " 'sites': [],\n", + " 'address': None,\n", + " 'variableGroups': [],\n", + " 'geometry': None,\n", + " 'relations': []}" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "phis.get_facility(facility_name='phenoarch')" + ] + }, + { + "cell_type": "markdown", + "id": "501d0584-f961-418e-98a9-d8c59157a8c4", + "metadata": {}, + "source": [ + "#### List available germplasms" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "04fe01d1-8cf8-406f-8760-ce13b9ad971d", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['apple tree',\n", + " 'banana',\n", + " 'barley',\n", + " 'bread wheat',\n", + " 'colza',\n", + " 'durum wheat',\n", + " 'grapevine',\n", + " 'maize',\n", + " 'Pearl millet',\n", + " 'poplar',\n", + " 'rice',\n", + " 'sorghum',\n", + " 'teosintes',\n", + " 'upland cotton',\n", + " '17g',\n", + " '17g_inrae',\n", + " '23298Mtp40',\n", + " '23298Mtp7',\n", + " '2369',\n", + " '2369_udel',\n", + " '7G20',\n", + " '7G31',\n", + " '7G39',\n", + " 'Affenth',\n", + " 'Alexandroouli',\n", + " 'ANTIGP1_SSD03',\n", + " 'ANTIGP1_SSD03_inrae',\n", + " 'ANTIGP2_HD201',\n", + " 'ANTIGP2_HD201_inrae',\n", + " 'ANTIGP2_SSD01',\n", + " 'ANTIGP2_SSD01_inrae',\n", + " 'APUC140_SSD01',\n", + " 'APUC140_SSD01_inrae',\n", + " 'APUC171_SSD01',\n", + " 'APUC171_SSD01_inrae',\n", + " 'Arbane',\n", + " 'ATPS425W',\n", + " 'ATPS425W_inrae',\n", + " 'B104',\n", + " 'B104_inrae',\n", + " 'B107',\n", + " 'B107_inrae',\n", + " 'B14a',\n", + " 'B14a_inrae',\n", + " 'B37',\n", + " 'B37_inrae',\n", + " 'B73',\n", + " 'B73_inrae',\n", + " 'B73_inrae',\n", + " 'BA90',\n", + " 'BA90_inrae',\n", + " 'BOLI711_SSD01',\n", + " 'BOLI711_SSD01_inrae',\n", + " 'BOLI905_SSD03',\n", + " 'BOLI905_SSD03_inrae',\n", + " 'BOZM0214_SSD01',\n", + " 'BOZM0214_SSD01_inrae',\n", + " 'BRVI104_HD128',\n", + " 'BRVI104_HD128_inrae',\n", + " 'BRVI117_SSD01',\n", + " 'BRVI117_SSD01_inrae',\n", + " 'BRVI139_SSD01',\n", + " 'BRVI139_SSD01_inrae',\n", + " 'BRVI142_HD105',\n", + " 'BRVI142_HD105_inrae',\n", + " 'CAL14113',\n", + " 'CAL14113_cim',\n", + " 'CAL14138',\n", + " 'CAL14138_cim',\n", + " 'CAL1440',\n", + " 'CAL1440_cim',\n", + " 'CAL1469',\n", + " 'CAL1469_cim',\n", + " 'CAL152',\n", + " 'CAL152_cim',\n", + " 'CamInb117',\n", + " 'CamInb117_inrae',\n", + " 'CFD11-004',\n", + " 'CFD11-004_inrae',\n", + " 'CFD11-005',\n", + " 'CFD11-005_inrae',\n", + " 'CFD11-006',\n", + " 'CFD11-006_inrae',\n", + " 'CFD11-007',\n", + " 'CFD11-007_inrae',\n", + " 'CFD11-010',\n", + " 'CFD11-010_inrae',\n", + " 'CFD11-011',\n", + " 'CFD11-011_inrae',\n", + " 'CFD11-026',\n", + " 'CFD11-026_inrae',\n", + " 'CFD11-029',\n", + " 'CFD11-029_inrae',\n", + " 'CFD11-030',\n", + " 'CFD11-030_inrae',\n", + " 'CFD11-045',\n", + " 'CFD11-045_inrae',\n", + " 'CFD11-047',\n", + " 'CFD11-047_inrae',\n", + " 'CFD11-048']" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "phis.get_germplasm(page_size=100)" + ] + }, + { + "cell_type": "markdown", + "id": "dd6fb8d0-754e-48e9-a752-2837ec6298b4", + "metadata": {}, + "source": [ + "#### List available germplasms with specific criteria" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "37c9339d-80d0-4675-930e-02599fdcc9ea", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['2369_udel',\n", + " 'CML10_udel',\n", + " 'CML254_udel',\n", + " 'CML258_udel',\n", + " 'CML277_udel',\n", + " 'CML341_udel',\n", + " 'CML373_udel',\n", + " 'Ki14_udel',\n", + " 'LH123Ht_udel',\n", + " 'NILASq4g31i04_udel',\n", + " 'NILASq4g31i06_udel',\n", + " 'NILASq4g41i07_udel',\n", + " 'NILASq4g71i03_udel',\n", + " 'Tzi8_udel',\n", + " 'Tzi9_udel']" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "phis.get_germplasm(rdf_type='http://www.opensilex.org/vocabulary/oeso#Accession', name='udel')" + ] + }, + { + "cell_type": "markdown", + "id": "47d512bf-6e4c-4a05-acde-2669f4b9921b", + "metadata": {}, + "source": [ + "#### Get specific germplasm details" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "f41c781e-6f93-427b-96bc-e273fa939d72", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'uri': 'http://phenome.inrae.fr/m3p/id/germplasm/accesion.CFD11-005_inrae',\n", + " 'rdf_type': 'http://www.opensilex.org/vocabulary/oeso#Accession',\n", + " 'rdf_type_name': 'Accession',\n", + " 'name': 'CFD11-005_inrae',\n", + " 'species': 'http://aims.fao.org/aos/agrovoc/c_8504',\n", + " 'species_name': 'maize',\n", + " 'publisher': None,\n", + " 'publication_date': None,\n", + " 'last_updated_date': None}" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "phis.get_germplasm(germplasm_name='CFD11-005_inrae')" + ] + }, + { + "cell_type": "markdown", + "id": "abe6ba29-c8ec-4f05-93c8-a043df7f4a30", + "metadata": {}, + "source": [ + "#### List available devices" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "3bc8180f-a5f0-4d91-a927-61dcfdf834d5", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['aria_co2_cE1',\n", + " 'aria_co2_cE2',\n", + " 'aria_co2_p',\n", + " 'aria_directionVent_ext',\n", + " 'aria_eclairage1_p',\n", + " 'aria_eclairage1_s1',\n", + " 'aria_eclairage2_p',\n", + " 'aria_eclairage2_s1',\n", + " 'aria_eclairage3_p',\n", + " 'aria_eclairage3_s1',\n", + " 'aria_eclairage4_s1',\n", + " 'aria_eclairage5_s1',\n", + " 'aria_eclairage6_s1',\n", + " 'aria_ecranBardage1_p',\n", + " 'aria_ecranBardage1_s1',\n", + " 'aria_ecranBardage2_p',\n", + " 'aria_ecranBardage2_s1',\n", + " 'aria_ecranPignon_p',\n", + " 'aria_ecranPignon_s1',\n", + " 'aria_ecranPlan_p',\n", + " 'aria_ecranPlan_s1',\n", + " 'aria_hr01_s1',\n", + " 'aria_hr02_s1',\n", + " 'aria_hr1_p',\n", + " 'aria_hr2_p',\n", + " 'aria_hr_cE1',\n", + " 'aria_hr_cE2',\n", + " 'aria_hr_ext',\n", + " 'aria_quantiteEauDsAir_ext',\n", + " 'aria_radiation_ext',\n", + " 'aria_tair01_p',\n", + " 'aria_tair01_s1',\n", + " 'aria_tair02_p',\n", + " 'aria_tair02_s1',\n", + " 'aria_tair_cE1',\n", + " 'aria_tair_cE2',\n", + " 'aria_tair_ext',\n", + " 'aria_tairHaute01_p',\n", + " 'aria_tairHaute02_p',\n", + " 'aria_vitesseVent_ext',\n", + " 'BF5',\n", + " 'CAMERA TEST OPENSILEX',\n", + " 'co2_01_cA',\n", + " 'Emb_1',\n", + " 'Emb_10',\n", + " 'Emb_11',\n", + " 'Emb_12',\n", + " 'Emb_13',\n", + " 'Emb_14',\n", + " 'Emb_15',\n", + " 'Emb_16',\n", + " 'Emb_17',\n", + " 'Emb_18',\n", + " 'Emb_19',\n", + " 'Emb_2',\n", + " 'Emb_20',\n", + " 'Emb_21',\n", + " 'Emb_22',\n", + " 'Emb_23',\n", + " 'Emb_24',\n", + " 'Emb_25',\n", + " 'Emb_26',\n", + " 'Emb_27',\n", + " 'Emb_28',\n", + " 'Emb_29',\n", + " 'Emb_3',\n", + " 'Emb_30',\n", + " 'Emb_31',\n", + " 'Emb_32',\n", + " 'Emb_33',\n", + " 'Emb_34',\n", + " 'Emb_35',\n", + " 'Emb_36',\n", + " 'Emb_37',\n", + " 'Emb_38',\n", + " 'Emb_39',\n", + " 'Emb_4',\n", + " 'Emb_40',\n", + " 'Emb_41',\n", + " 'Emb_42',\n", + " 'Emb_43',\n", + " 'Emb_44',\n", + " 'Emb_45',\n", + " 'Emb_46',\n", + " 'Emb_47',\n", + " 'Emb_48',\n", + " 'Emb_49',\n", + " 'Emb_5',\n", + " 'Emb_50',\n", + " 'Emb_51',\n", + " 'Emb_52',\n", + " 'Emb_53',\n", + " 'Emb_54',\n", + " 'Emb_55',\n", + " 'Emb_56',\n", + " 'Emb_57',\n", + " 'Emb_58',\n", + " 'Emb_59',\n", + " 'Emb_6',\n", + " 'Emb_60']" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "phis.get_device(page_size=100)" + ] + }, + { + "cell_type": "markdown", + "id": "77df9f4e-91c0-44c4-b932-042ea2cdbb39", + "metadata": {}, + "source": [ + "#### Get specific device details" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "e8193235-e5ac-4186-906f-b0d3f3a7808b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'uri': 'm3p:id/deviceAttribut/eo/2017/vc170057',\n", + " 'rdf_type': 'vocabulary:Vector',\n", + " 'rdf_type_name': 'Vector',\n", + " 'name': 'Emb_57',\n", + " 'brand': None,\n", + " 'constructor_model': None,\n", + " 'serial_number': None,\n", + " 'person_in_charge': None,\n", + " 'start_up': '2017-01-01',\n", + " 'removal': None,\n", + " 'relations': [],\n", + " 'description': None,\n", + " 'publisher': None,\n", + " 'publication_date': None,\n", + " 'last_updated_date': None}" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "phis.get_device(device_name='Emb_57')" + ] + }, + { + "cell_type": "markdown", + "id": "f6b0d09c-5566-4718-8832-17d837d7b74b", + "metadata": {}, + "source": [ + "#### List available annotations" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "6c4fbe53-45ef-4679-ace1-9c7d21733552", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "phis.get_annotation()" + ] + }, + { + "cell_type": "markdown", + "id": "9dcb9c9b-4c69-43e9-a656-21ac67348377", + "metadata": {}, + "source": [ + "#### List available documents" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "26b13101-bad6-4767-8cc5-2df08ec12399", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['test isa doc post deploy', 'test isa doc ', 'Test_dataset']" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "phis.get_document()" + ] + }, + { + "cell_type": "markdown", + "id": "e55cd13a-1889-431e-a9ab-42e39ba939c8", + "metadata": {}, + "source": [ + "#### Get specific document details" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "3069fe3f-cda6-4bca-a1f6-02e53abc85c5", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'uri': 'm3p:id/document/test_isa_doc',\n", + " 'publisher': None,\n", + " 'publication_date': None,\n", + " 'last_updated_date': None,\n", + " 'identifier': None,\n", + " 'rdf_type': 'vocabulary:ScientificDocument',\n", + " 'rdf_type_name': 'Scientific Document',\n", + " 'title': 'test isa doc ',\n", + " 'date': '2022-04-04',\n", + " 'description': None,\n", + " 'targets': [],\n", + " 'authors': [],\n", + " 'language': None,\n", + " 'format': 'png',\n", + " 'keywords': [],\n", + " 'deprecated': True,\n", + " 'source': None}" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "phis.get_document(document_title='test isa doc ')" + ] + }, + { + "cell_type": "markdown", + "id": "d39fcca3-480b-401a-9f6a-6f4d9670aa03", + "metadata": {}, + "source": [ + "#### List available factors" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "acf07aee-51ad-47f8-adc7-c3d023c98e32", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['Scenario']" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "phis.get_factor()" + ] + }, + { + "cell_type": "markdown", + "id": "9365cbd0-5fef-40a8-8349-47911ba4ea98", + "metadata": {}, + "source": [ + "#### List available organizations" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "cce64d6b-4330-4049-a8ba-60d1ed8d59d4", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "European organization organizations:\n", + "EMPHASIS\n", + "\n", + "Local organization organizations:\n", + "PHENOARCH\n", + "PHENODYN\n", + "M3P\n", + "PHENOPSIS\n", + "\n", + "National organization organizations:\n", + "PHENOME-EMPHASIS\n", + "\n" + ] + } + ], + "source": [ + "print(phis.get_organization())" + ] + }, + { + "cell_type": "markdown", + "id": "327938f2-8cbf-4da2-9805-439ce37782f6", + "metadata": {}, + "source": [ + "#### Get specific organization details" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "4fa69cce-3be1-4730-9f2b-077c8c8e5e18", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'uri': 'm3p:id/organization/phenoarch',\n", + " 'name': 'PHENOARCH',\n", + " 'parents': ['http://phenome.inrae.fr/id/organization/m3p'],\n", + " 'children': [],\n", + " 'rdf_type': 'vocabulary:LocalOrganization',\n", + " 'rdf_type_name': 'local organization',\n", + " 'publication_date': None,\n", + " 'last_updated_date': None}" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "phis.get_organization(organization_name='PHENOARCH')" + ] + }, + { + "cell_type": "markdown", + "id": "79249735-80cb-41f9-b1f7-5ff4d0fa343a", + "metadata": {}, + "source": [ + "#### List available sites" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "7df0c881-e1c1-4d54-9ca6-f971410d67d3", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "phis.get_site()" + ] + }, + { + "cell_type": "markdown", + "id": "b8a0434f-9ad1-4a23-a59f-b35f42d6667a", + "metadata": {}, + "source": [ + "#### List available scientific objects" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "4d7f5802-ca38-4134-a744-46d2e864ff70", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['0001/ZM4531/EPPN7_L/WD1/EPPN_Rep_1/01_01/ARCH2020-02-03',\n", + " '0002/ZM4534/EPPN10_L/WD1/EPPN_Rep_1/01_02/ARCH2020-02-03',\n", + " '0002/ZM4534/EPPN10_L/WD1/EPPN_Rep_1/01_02/ARCH2020-02-03',\n", + " '0003/ZM4532/EPPN8_L/WD1/EPPN_Rep_1/01_03/ARCH2020-02-03',\n", + " '0003/ZM4532/EPPN8_L/WD1/EPPN_Rep_1/01_03/ARCH2020-02-03',\n", + " '0004/ZM4527/EPPN3_L/WD1/EPPN_Rep_1/01_04/ARCH2020-02-03',\n", + " '0004/ZM4527/EPPN3_L/WD1/EPPN_Rep_1/01_04/ARCH2020-02-03',\n", + " '0005/ZM4525/EPPN1_L/WD1/EPPN_Rep_1/01_05/ARCH2020-02-03',\n", + " '0005/ZM4525/EPPN1_L/WD1/EPPN_Rep_1/01_05/ARCH2020-02-03',\n", + " '0006/ZM4526/EPPN2_L/WD1/EPPN_Rep_1/01_06/ARCH2020-02-03',\n", + " '0006/ZM4526/EPPN2_L/WD1/EPPN_Rep_1/01_06/ARCH2020-02-03',\n", + " '0007/ZM4533/EPPN9_L/WD1/EPPN_Rep_1/01_07/ARCH2020-02-03',\n", + " '0007/ZM4533/EPPN9_L/WD1/EPPN_Rep_1/01_07/ARCH2020-02-03',\n", + " '0008/ZM4538/EPPN14_L/WD1/EPPN_Rep_1/01_08/ARCH2020-02-03',\n", + " '0008/ZM4538/EPPN14_L/WD1/EPPN_Rep_1/01_08/ARCH2020-02-03',\n", + " '0009/ZM4528/EPPN4_L/WD1/EPPN_Rep_1/01_09/ARCH2020-02-03',\n", + " '0009/ZM4528/EPPN4_L/WD1/EPPN_Rep_1/01_09/ARCH2020-02-03',\n", + " '0010/ZM4555/EPPN20_T/WD1/EPPN_Rep_1/01_10/ARCH2020-02-03',\n", + " '0010/ZM4555/EPPN20_T/WD1/EPPN_Rep_1/01_10/ARCH2020-02-03',\n", + " '0011/ZM4537/EPPN13_L/WD1/EPPN_Rep_1/01_11/ARCH2020-02-03',\n", + " '0011/ZM4537/EPPN13_L/WD1/EPPN_Rep_1/01_11/ARCH2020-02-03',\n", + " '0012/ZM4530/EPPN6_L/WD1/EPPN_Rep_1/01_12/ARCH2020-02-03',\n", + " '0012/ZM4530/EPPN6_L/WD1/EPPN_Rep_1/01_12/ARCH2020-02-03',\n", + " '0013/ZM4535/EPPN11_L/WD1/EPPN_Rep_1/01_13/ARCH2020-02-03',\n", + " '0013/ZM4535/EPPN11_L/WD1/EPPN_Rep_1/01_13/ARCH2020-02-03',\n", + " '0014/ZM4529/EPPN5_L/WD1/EPPN_Rep_1/01_14/ARCH2020-02-03',\n", + " '0014/ZM4529/EPPN5_L/WD1/EPPN_Rep_1/01_14/ARCH2020-02-03',\n", + " '0015/ZM4536/EPPN12_L/WD1/EPPN_Rep_1/01_15/ARCH2020-02-03',\n", + " '0015/ZM4536/EPPN12_L/WD1/EPPN_Rep_1/01_15/ARCH2020-02-03',\n", + " '0016/ZM4541/EPPN2_H/WW/EPPN_Rep_2/01_16/ARCH2020-02-03',\n", + " '0016/ZM4541/EPPN2_H/WW/EPPN_Rep_2/01_16/ARCH2020-02-03',\n", + " '0017/ZM4547/EPPN8_H/WW/EPPN_Rep_2/01_17/ARCH2020-02-03',\n", + " '0017/ZM4547/EPPN8_H/WW/EPPN_Rep_2/01_17/ARCH2020-02-03',\n", + " '0018/ZM4549/EPPN10_H/WW/EPPN_Rep_2/01_18/ARCH2020-02-03',\n", + " '0018/ZM4549/EPPN10_H/WW/EPPN_Rep_2/01_18/ARCH2020-02-03',\n", + " '0019/ZM4552/EPPN13_H/WW/EPPN_Rep_2/01_19/ARCH2020-02-03',\n", + " '0019/ZM4552/EPPN13_H/WW/EPPN_Rep_2/01_19/ARCH2020-02-03',\n", + " '0020/ZM4546/EPPN7_H/WW/EPPN_Rep_2/01_20/ARCH2020-02-03',\n", + " '0020/ZM4546/EPPN7_H/WW/EPPN_Rep_2/01_20/ARCH2020-02-03',\n", + " '0021/ZM4542/EPPN3_H/WW/EPPN_Rep_2/01_21/ARCH2020-02-03',\n", + " '0021/ZM4542/EPPN3_H/WW/EPPN_Rep_2/01_21/ARCH2020-02-03',\n", + " '0022/ZM4543/EPPN4_H/WW/EPPN_Rep_2/01_22/ARCH2020-02-03',\n", + " '0022/ZM4543/EPPN4_H/WW/EPPN_Rep_2/01_22/ARCH2020-02-03',\n", + " '0023/ZM4545/EPPN6_H/WW/EPPN_Rep_2/01_23/ARCH2020-02-03',\n", + " '0023/ZM4545/EPPN6_H/WW/EPPN_Rep_2/01_23/ARCH2020-02-03',\n", + " '0024/ZM4553/EPPN14_H/WW/EPPN_Rep_2/01_24/ARCH2020-02-03',\n", + " '0024/ZM4553/EPPN14_H/WW/EPPN_Rep_2/01_24/ARCH2020-02-03',\n", + " '0025/ZM4540/EPPN1_H/WW/EPPN_Rep_2/01_25/ARCH2020-02-03',\n", + " '0025/ZM4540/EPPN1_H/WW/EPPN_Rep_2/01_25/ARCH2020-02-03',\n", + " '0026/ZM4550/EPPN11_H/WW/EPPN_Rep_2/01_26/ARCH2020-02-03',\n", + " '0026/ZM4550/EPPN11_H/WW/EPPN_Rep_2/01_26/ARCH2020-02-03',\n", + " '0027/ZM4554/EPPN15_H/WW/EPPN_Rep_2/01_27/ARCH2020-02-03',\n", + " '0027/ZM4554/EPPN15_H/WW/EPPN_Rep_2/01_27/ARCH2020-02-03',\n", + " '0028/ZM4544/EPPN5_H/WW/EPPN_Rep_2/01_28/ARCH2020-02-03',\n", + " '0028/ZM4544/EPPN5_H/WW/EPPN_Rep_2/01_28/ARCH2020-02-03',\n", + " '0029/ZM4548/EPPN9_H/WW/EPPN_Rep_2/01_29/ARCH2020-02-03',\n", + " '0029/ZM4548/EPPN9_H/WW/EPPN_Rep_2/01_29/ARCH2020-02-03',\n", + " '0030/ZM4551/EPPN12_H/WW/EPPN_Rep_2/01_30/ARCH2020-02-03',\n", + " '0030/ZM4551/EPPN12_H/WW/EPPN_Rep_2/01_30/ARCH2020-02-03',\n", + " '0031/ZM4555/EPPN20_T/WD1/EPPN_Rep_3/01_31/ARCH2020-02-03',\n", + " '0031/ZM4555/EPPN20_T/WD1/EPPN_Rep_3/01_31/ARCH2020-02-03',\n", + " '0032/ZM4538/EPPN14_L/WD1/EPPN_Rep_3/01_32/ARCH2020-02-03',\n", + " '0032/ZM4538/EPPN14_L/WD1/EPPN_Rep_3/01_32/ARCH2020-02-03',\n", + " '0033/ZM4527/EPPN3_L/WD1/EPPN_Rep_3/01_33/ARCH2020-02-03',\n", + " '0033/ZM4527/EPPN3_L/WD1/EPPN_Rep_3/01_33/ARCH2020-02-03',\n", + " '0034/ZM4533/EPPN9_L/WD1/EPPN_Rep_3/01_34/ARCH2020-02-03',\n", + " '0034/ZM4533/EPPN9_L/WD1/EPPN_Rep_3/01_34/ARCH2020-02-03',\n", + " '0035/ZM4529/EPPN5_L/WD1/EPPN_Rep_3/01_35/ARCH2020-02-03',\n", + " '0035/ZM4529/EPPN5_L/WD1/EPPN_Rep_3/01_35/ARCH2020-02-03',\n", + " '0036/ZM4537/EPPN13_L/WD1/EPPN_Rep_3/01_36/ARCH2020-02-03',\n", + " '0036/ZM4537/EPPN13_L/WD1/EPPN_Rep_3/01_36/ARCH2020-02-03',\n", + " '0037/ZM4525/EPPN1_L/WD1/EPPN_Rep_3/01_37/ARCH2020-02-03',\n", + " '0037/ZM4525/EPPN1_L/WD1/EPPN_Rep_3/01_37/ARCH2020-02-03',\n", + " '0038/ZM4531/EPPN7_L/WD1/EPPN_Rep_3/01_38/ARCH2020-02-03',\n", + " '0038/ZM4531/EPPN7_L/WD1/EPPN_Rep_3/01_38/ARCH2020-02-03',\n", + " '0039/ZM4536/EPPN12_L/WD1/EPPN_Rep_3/01_39/ARCH2020-02-03',\n", + " '0039/ZM4536/EPPN12_L/WD1/EPPN_Rep_3/01_39/ARCH2020-02-03',\n", + " '0040/ZM4535/EPPN11_L/WD1/EPPN_Rep_3/01_40/ARCH2020-02-03',\n", + " '0040/ZM4535/EPPN11_L/WD1/EPPN_Rep_3/01_40/ARCH2020-02-03',\n", + " '0041/ZM4534/EPPN10_L/WD1/EPPN_Rep_3/01_41/ARCH2020-02-03',\n", + " '0041/ZM4534/EPPN10_L/WD1/EPPN_Rep_3/01_41/ARCH2020-02-03',\n", + " '0042/ZM4526/EPPN2_L/WD1/EPPN_Rep_3/01_42/ARCH2020-02-03',\n", + " '0042/ZM4526/EPPN2_L/WD1/EPPN_Rep_3/01_42/ARCH2020-02-03',\n", + " '0043/ZM4528/EPPN4_L/WD1/EPPN_Rep_3/01_43/ARCH2020-02-03',\n", + " '0043/ZM4528/EPPN4_L/WD1/EPPN_Rep_3/01_43/ARCH2020-02-03',\n", + " '0044/ZM4532/EPPN8_L/WD1/EPPN_Rep_3/01_44/ARCH2020-02-03',\n", + " '0044/ZM4532/EPPN8_L/WD1/EPPN_Rep_3/01_44/ARCH2020-02-03',\n", + " '0045/ZM4530/EPPN6_L/WD1/EPPN_Rep_3/01_45/ARCH2020-02-03',\n", + " '0045/ZM4530/EPPN6_L/WD1/EPPN_Rep_3/01_45/ARCH2020-02-03',\n", + " '0046/ZM4554/EPPN15_H/WW/EPPN_Rep_4/01_46/ARCH2020-02-03',\n", + " '0046/ZM4554/EPPN15_H/WW/EPPN_Rep_4/01_46/ARCH2020-02-03',\n", + " '0047/ZM4545/EPPN6_H/WW/EPPN_Rep_4/01_47/ARCH2020-02-03',\n", + " '0047/ZM4545/EPPN6_H/WW/EPPN_Rep_4/01_47/ARCH2020-02-03',\n", + " '0048/ZM4547/EPPN8_H/WW/EPPN_Rep_4/01_48/ARCH2020-02-03',\n", + " '0048/ZM4547/EPPN8_H/WW/EPPN_Rep_4/01_48/ARCH2020-02-03',\n", + " '0049/ZM4551/EPPN12_H/WW/EPPN_Rep_4/01_49/ARCH2020-02-03',\n", + " '0049/ZM4551/EPPN12_H/WW/EPPN_Rep_4/01_49/ARCH2020-02-03',\n", + " '0050/ZM4546/EPPN7_H/WW/EPPN_Rep_4/01_50/ARCH2020-02-03',\n", + " '0050/ZM4546/EPPN7_H/WW/EPPN_Rep_4/01_50/ARCH2020-02-03',\n", + " '0051/ZM4540/EPPN1_H/WW/EPPN_Rep_4/01_51/ARCH2020-02-03']" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "phis.get_scientific_object(page_size=100)" + ] + }, + { + "cell_type": "markdown", + "id": "24cc536c-e817-448e-9b7a-e20db5fdb328", + "metadata": {}, + "source": [ + "#### Get specific scientific object details" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "8779f4e4-2c2f-44c9-b7dc-6a6850d7d4dd", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'uri': 'm3p:id/scientific-object/za20/so-0001zm4531eppn7_lwd1eppn_rep_101_01arch2020-02-03',\n", + " 'name': '0001/ZM4531/EPPN7_L/WD1/EPPN_Rep_1/01_01/ARCH2020-02-03',\n", + " 'geometry': None,\n", + " 'rdf_type': 'vocabulary:Plant',\n", + " 'rdf_type_name': 'plant',\n", + " 'publication_date': None,\n", + " 'last_updated_date': None,\n", + " 'creation_date': None,\n", + " 'destruction_date': None}" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "phis.get_scientific_object(scientific_object_name='0001/ZM4531/EPPN7_L/WD1/EPPN_Rep_1/01_01/ARCH2020-02-03')" + ] + }, + { + "cell_type": "markdown", + "id": "c2f3d2a6-73ba-4f3e-b028-2b4cf4cfefe0", + "metadata": {}, + "source": [ + "#### List available characteristics" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "efe065de-1b7a-4c35-9efe-73f97a2c2c5d", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['CO2',\n", + " 'fresh_weight',\n", + " 'humidity',\n", + " 'Infra-red radiation',\n", + " 'Irradiance',\n", + " 'Lightning',\n", + " 'Shading',\n", + " 'Temperature']" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "phis.get_characteristic()" + ] + }, + { + "cell_type": "markdown", + "id": "f2fd36bd-fb8d-456c-8064-bfac341e1e2d", + "metadata": {}, + "source": [ + "#### Get specific characteristic details" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "49f96e29-61c4-49c5-8105-f706de3991ab", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'uri': 'http://phenome.inrae.fr/m3p/id/variable/characteristic..co2',\n", + " 'name': 'CO2'}" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "phis.get_characteristic(characteristic_name='CO2')" + ] + }, + { + "cell_type": "markdown", + "id": "e934104c-f83c-4b59-be49-b37337be2208", + "metadata": {}, + "source": [ + "#### List available entities" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "c98396dc-3cc9-4613-a697-6e961ff80220", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['Air', 'Greenhouse', 'Leaf', 'Plant', 'Solar', 'Water']" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "phis.get_entity()" + ] + }, + { + "cell_type": "markdown", + "id": "0fffe9b5-67f4-449b-aba5-84aaa812dc64", + "metadata": {}, + "source": [ + "#### Get specific entity details" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "9a115d99-4e40-4c64-9477-220c6378e189", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'uri': 'http://phenome.inrae.fr/m3p/id/variable/entity.air', 'name': 'Air'}" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "phis.get_entity(entity_name='Air')" + ] + }, + { + "cell_type": "markdown", + "id": "1ab0921b-7acd-40cf-8210-27d7aeebba2f", + "metadata": {}, + "source": [ + "#### List available entities of interest" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "12aa6de7-c1d0-4648-b636-a7c4dc83bf77", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "phis.get_entity_of_interest()" + ] + }, + { + "cell_type": "markdown", + "id": "3793f85e-1783-463f-a486-93fd981b78cb", + "metadata": {}, + "source": [ + "#### List available methods" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "e89debc4-50a9-4e57-9532-654a463a320a", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['Computation',\n", + " 'Lower near-surface',\n", + " 'Measurement',\n", + " 'PAR',\n", + " 'PAR_Diffuse',\n", + " 'PAR_Direct',\n", + " 'Radiation_Global',\n", + " 'Setpoint',\n", + " 'Shelter_Instant_Measurement',\n", + " 'thermocouple',\n", + " 'Upper near-surface']" + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "phis.get_method()" + ] + }, + { + "cell_type": "markdown", + "id": "a8a91224-5d46-40f2-8e85-2cda9a8a4850", + "metadata": {}, + "source": [ + "#### Get specific method details" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "17c00ccd-0b06-4d53-925d-fc7716bc35ba", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'uri': 'http://phenome.inrae.fr/m3p/id/variable/method.computation',\n", + " 'name': 'Computation'}" + ] + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "phis.get_method(method_name='Computation')" + ] + }, + { + "cell_type": "markdown", + "id": "aea0532f-4964-4eb0-805e-5a9a2c149dcd", + "metadata": {}, + "source": [ + "#### List available units" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "a5a14d0f-a53d-453c-95db-fc0e6f898c66", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['Boolean',\n", + " 'degree celsius',\n", + " 'gram',\n", + " 'J-PER-M2',\n", + " 'Joule',\n", + " 'kilogram',\n", + " 'MicroMOL-PER-M2-SEC',\n", + " 'Micromole per square metre per_second',\n", + " 'millimetre ',\n", + " 'percent',\n", + " 'ppm',\n", + " 'watt per square meter']" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "phis.get_unit()" + ] + }, + { + "cell_type": "markdown", + "id": "39a54c76-3e7f-4667-a7a2-897a6dffd261", + "metadata": {}, + "source": [ + "#### Get specific unit details" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "86d4a3d3-3800-4134-a555-689461cac2d6", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'uri': 'http://phenome.inrae.fr/m3p/id/variable/unit.boolean',\n", + " 'name': 'Boolean'}" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "phis.get_unit(unit_name='Boolean')" + ] + }, + { + "cell_type": "markdown", + "id": "7ba37047-8fce-4dcf-9b92-6110b80e26f3", + "metadata": {}, + "source": [ + "#### List available provenances" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "d9bbf18f-a044-4800-998a-b8e16e8a03d0", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['standard_provenance',\n", + " 'Prov_air humidity_weather station_percentage_hr01_p',\n", + " 'Prov_air humidity_weather station_percentage_hr02_p',\n", + " 'Prov_air humidity_weather station_percentage_hr03_p',\n", + " 'Prov_air humidity_weather station_percentage_hr04_p',\n", + " 'Prov_air humidity_weather station_percentage_hr05_p',\n", + " 'Prov_air humidity_weather station_percentage_hr06_p',\n", + " 'Prov_air humidity_weather station_percentage_hr07_p',\n", + " 'Prov_air humidity_weather station_percentage_hr08_p',\n", + " 'Prov_air humidity_weather station_percentage_hr09_p',\n", + " 'Prov_air humidity_weather station_percentage_hr10_p',\n", + " 'Prov_PAR Light_weather station_micromole.m-2.s-1_par01_p',\n", + " 'Prov_PAR Light_weather station_micromole.m-2.s-1_par02_p',\n", + " 'Prov_PAR Light_weather station_micromole.m-2.s-1_par03_p',\n", + " 'Prov_PAR Light_weather station_micromole.m-2.s-1_par04_p',\n", + " 'Prov_PAR Light_weather station_micromole.m-2.s-1_par05_p',\n", + " 'Prov_PAR Light_weather station_micromole.m-2.s-1_par06_p',\n", + " 'Prov_PAR Light_weather station_micromole.m-2.s-1_par07_p',\n", + " 'Prov_PAR Light_weather station_micromole.m-2.s-1_par08_p',\n", + " 'Prov_PAR Light_weather station_micromole.m-2.s-1_par09_p',\n", + " 'Prov_PAR Light_weather station_micromole.m-2.s-1_par10_p',\n", + " 'Prov_air temperature_weather station_degree celsius_tair01_p',\n", + " 'Prov_air temperature_weather station_degree celsius_tair02_p',\n", + " 'Prov_diffuse PAR light_sensor_micromole.m-2.s-1_BF5',\n", + " 'Prov_direct PAR light_sensor_micromole.m-2.s-1_BF5',\n", + " 'Prov_air temperature_weather station_degree celsius_tair03_p',\n", + " 'Prov_air temperature_weather station_degree celsius_tair04_p',\n", + " 'Prov_air temperature_weather station_degree celsius_tair05_p',\n", + " 'Prov_air temperature_weather station_degree celsius_tair06_p',\n", + " 'Prov_air temperature_weather station_degree celsius_tair07_p',\n", + " 'Prov_air temperature_weather station_degree celsius_tair08_p',\n", + " 'Prov_air temperature_weather station_degree celsius_tair09_p',\n", + " 'Prov_air temperature_weather station_degree celsius_tair10_p',\n", + " 'Prov_watering_WateringStation02_water',\n", + " 'Prov_watering_WateringStation04_water',\n", + " 'Prov_watering_WateringStation04_watermaize',\n", + " 'Prov_watering_WateringStation02_watermaize',\n", + " 'Prov_watering_WateringStation03_waterwheat',\n", + " 'Prov_watering_WateringStation05_waterwheat',\n", + " 'Prov_watering_WateringStation01_waterwheat',\n", + " 'Prov_weighing_WateringStation05_ARCH2020-01-20',\n", + " 'Prov_weighing_WateringStation03_ARCH2020-01-20',\n", + " 'Prov_weighing_WateringStation04_ARCH2020-01-20',\n", + " 'Prov_weighing_WateringStation02_ARCH2020-01-20',\n", + " 'Prov_weighing_WateringStation01_ARCH2020-01-20',\n", + " 'Prov_weighing_OperatorStation01_ARCH2020-01-20',\n", + " 'Prov_weighing_WateringStation01_DYN2020-05-15',\n", + " 'Prov_watering_WateringStation01_water',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_02',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_03',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_04',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_05',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_06',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_07',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_08',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_09',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_10',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_11',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_12',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_13',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_14',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_15',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_16',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_17',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_18',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_19',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_20',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_21',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_22',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_23',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_24',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_25',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_26',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_28',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_29',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_30',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_31',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_32',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_33',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_34',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_35',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_36',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_37',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_38',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_39',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_40',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_41',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_42',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_43',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_44',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_45',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_46',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_47',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_48',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_50',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_51',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_52',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_53',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_54',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_55',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_56',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_57',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_58',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_59',\n", + " 'Prov_leaf temperature_thermocouple sensor_degree celsius_thc_emb_60',\n", + " 'Prov_weighing_WateringStation05_DYN2020-05-15',\n", + " 'Prov_weighing_WateringStation03_DYN2020-05-15',\n", + " 'Prov_weighing_WateringStation02_DYN2020-05-15',\n", + " 'Prov_weighing_WateringStation04_DYN2020-05-15',\n", + " 'Prov_watering_WateringStation05_water',\n", + " 'Prov_watering_WateringStation03_water',\n", + " 'Prov_CarbonDioxide_sensor_part per million_aria_co2_cE2',\n", + " 'Prov_CarbonDioxide_sensor_part per million_aria_co2_p',\n", + " 'Prov_air humidity_weather station_percentage_aria_hr1_p',\n", + " 'Prov_air humidity_weather station_percentage_aria_hr_cE2',\n", + " 'Prov_air humidity_weather station_percentage_aria_hr_ext',\n", + " 'Prov_net irradiance_calculated variable_watt.m2_aria_radiation_ext',\n", + " 'Prov_air temperature_weather station_degree celsius_aria_tair01_p',\n", + " 'Prov_air temperature_weather station_degree celsius_aria_tair02_p',\n", + " 'Prov_air temperature_weather station_degree celsius_aria_tair_ext',\n", + " 'Prov_air temperature_weather station_degree celsius_aria_tairHaute01_p',\n", + " 'Prov_air temperature_weather station_degree celsius_aria_tairHaute02_p',\n", + " 'Prov_Greenhouse_Lightning_Setpoint_Boolean_aria_eclairage1_p',\n", + " 'Prov_Greenhouse_Lightning_Setpoint_Boolean_aria_eclairage2_p',\n", + " 'Prov_Greenhouse_Lightning_Setpoint_Boolean_aria_eclairage3_p',\n", + " 'Prov_Greenhouse_Lightning_Setpoint_Boolean_aria_eclairage4_s1',\n", + " 'Prov_Greenhouse_Lightning_Setpoint_Boolean_aria_eclairage5_s1',\n", + " 'Prov_Greenhouse_Lightning_Setpoint_Boolean_aria_eclairage6_s1',\n", + " 'Prov_Greenhouse_Shading_Setpoint_Boolean_aria_ecranBardage1_p',\n", + " 'Prov_Greenhouse_Shading_Setpoint_Boolean_aria_ecranBardage2_p',\n", + " 'Prov_Greenhouse_Shading_Setpoint_Boolean_aria_ecranPignon_p',\n", + " 'Prov_Greenhouse_Shading_Setpoint_Boolean_aria_ecranPlan_p',\n", + " 'TEST_OPENSILEX_IRODS',\n", + " 'Prov_ARCHTEST_RICE2023_6650_ImagingStation03_Side',\n", + " 'Prov_ARCHTEST_RICE2023_6650_ImagingStation01_Side',\n", + " 'Prov_ARCHTEST_RICE2023_6650_ImagingStation02_Side',\n", + " 'Prov_ARCHTEST_RICE2023_6650_ImagingStation03_Top',\n", + " 'Prov_ARCHTEST_RICE2023_6650_ImagingStation01_Top',\n", + " 'Prov_ARCHTEST_RICE2023_6650_ImagingStation02_Top',\n", + " 'Prov_weighing_WateringStation03_ARCHTEST_RICE2023',\n", + " 'Prov_weighing_WateringStation05_ARCHTEST_RICE2023',\n", + " 'Prov_weighing_WateringStation02_ARCHTEST_RICE2023',\n", + " 'Prov_weighing_WateringStation04_ARCHTEST_RICE2023',\n", + " 'Prov_watering_WateringStation03_6l',\n", + " 'Prov_watering_WateringStation02_6l',\n", + " 'Prov_watering_WateringStation05_9l',\n", + " 'Prov_watering_WateringStation04_9l',\n", + " 'Prov_watering_WateringStation04_6l',\n", + " 'Prov_watering_WateringStation05_6l']" + ] + }, + "execution_count": 35, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "phis.get_provenance()" + ] + }, + { + "cell_type": "markdown", + "id": "cc1bb3ab-c43b-4712-8296-6cfa9a702450", + "metadata": {}, + "source": [ + "#### Get specific provenance details" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "id": "17dd3c58-4736-4078-8430-1ee607cb6b96", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'uri': 'http://www.phenome-fppn.fr/m3p/Prov_watering_WateringStation01_water',\n", + " 'name': 'Prov_watering_WateringStation01_water',\n", + " 'description': 'acquisition of WateringStation01 and water [2021-11-17__10-55-32]',\n", + " 'prov_activity': [{'rdf_type': 'vocabulary:MeasuresAcquisition',\n", + " 'uri': None,\n", + " 'start_date': '2020-01-01T00:00:00Z',\n", + " 'end_date': None,\n", + " 'settings': None}],\n", + " 'prov_agent': [{'uri': 'http://www.phenome-fppn.fr/m3p/2019/s19001',\n", + " 'rdf_type': 'vocabulary:WeighingScale',\n", + " 'settings': None},\n", + " {'uri': 'http://www.phenome-fppn.fr/m3p/2020/a20001',\n", + " 'rdf_type': 'vocabulary:WateringPump',\n", + " 'settings': None},\n", + " {'uri': 'http://www.phenome-fppn.fr/m3p/2019/v1907',\n", + " 'rdf_type': 'vocabulary:Station',\n", + " 'settings': None}],\n", + " 'publisher': None,\n", + " 'issued': None,\n", + " 'modified': None}" + ] + }, + "execution_count": 36, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "phis.get_provenance(provenance_name='Prov_watering_WateringStation01_water')" + ] + }, + { + "cell_type": "markdown", + "id": "9ab70428-5ed3-4427-bf39-8e46d7d74187", + "metadata": {}, + "source": [ + "#### List available datafiles" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "id": "13fd53b9-2138-4b36-b48f-21a5f91f54dc", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['7018.tar']" + ] + }, + "execution_count": 37, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "phis.get_datafile()" + ] + }, + { + "cell_type": "markdown", + "id": "f7b8ce86-be16-4cac-862d-79bba08ecff8", + "metadata": {}, + "source": [ + "#### Get specific datafile details" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "id": "149d8501-413d-4d15-bcd1-ea2c9eb182b8", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'uri': 'm3p:id/file/1597964400.af46ac07f735ced228cf181aa85ebced',\n", + " 'rdf_type': 'vocabulary:Image',\n", + " 'date': '2020-08-21T00:00:00.000+0100',\n", + " 'timezone': None,\n", + " 'target': 'm3p:id/scientific-object/za20/so-0001zm4531eppn7_lwd1eppn_rep_101_01arch2020-02-03',\n", + " 'provenance': {'uri': 'm3p:provenance/standard_provenance',\n", + " 'prov_used': None,\n", + " 'prov_was_associated_with': None,\n", + " 'settings': None,\n", + " 'experiments': None},\n", + " 'metadata': None,\n", + " 'archive': None,\n", + " 'filename': '7018.tar',\n", + " 'publisher': None,\n", + " 'issued': None}" + ] + }, + "execution_count": 38, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "phis.get_datafile(datafile_name='7018.tar')" + ] + }, + { + "cell_type": "markdown", + "id": "e2be1dbd-929f-4c29-8815-4e0cb4793e30", + "metadata": {}, + "source": [ + "#### List available events" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "id": "7725a021-8e76-4e2d-9320-bfb24df22125", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Association with a sensing device events:\n", + "uri: m3p:id/event/4a69aa52-c041-4fbb-bbc0-f86a4916e1da\n", + "target: ImagingStation02\n", + "\n", + "uri: m3p:id/event/ffcb426f-b605-4c7e-945a-c0237f14d1e5\n", + "target: ImagingStation03\n", + "\n", + "uri: m3p:id/event/fa52d4e5-a364-4244-95f9-11c754008e76\n", + "target: ImagingStation02\n", + "\n", + "uri: m3p:id/event/0829e9b7-ce77-4131-b8f0-d5158029b1df\n", + "target: ImagingStation01\n", + "\n", + "\n", + "Manual calibration events:\n", + "uri: m3p:id/event/cb8b96ea-4d0b-4bc6-804f-e3cf2b56092e\n", + "description: New settings for ZB24 experiment\n", + "target: ImagingStation02\n", + "\n", + "uri: m3p:id/event/690cf5fd-965d-49d7-a251-b290f5cc35f1\n", + "description: New settings for ZB24 experiment\n", + "target: ImagingStation01\n", + "\n", + "uri: m3p:id/event/aa5f7ea9-de27-4921-b080-570593fc7284\n", + "description: New settings for ZA24 experiment (zoom out)\n", + "target: ImagingStation01\n", + "target: ImagingStation03\n", + "target: ImagingStation02\n", + "\n", + "\n", + "Move events:\n", + "uri: m3p:set/event/01a64e71-c4b7-4d82-8334-ebd8cc1e2f69\n", + "target: aria_tair01_p\n", + "\n", + "uri: m3p:set/event/0d9bc611-7959-4a4c-944e-17ccc60b413a\n", + "target: aria_tairHaute02_p\n", + "\n", + "uri: m3p:set/event/0eaf87d7-5570-4537-b9f4-68b07949a6b7\n", + "target: aria_hr1_p\n", + "\n", + "uri: m3p:set/event/10f1634a-9058-4f43-a724-335d77cdba02\n", + "target: aria_tair_cE1\n", + "\n", + "uri: m3p:set/event/13d3b76d-d94d-43f7-9e5f-5970f81b6db1\n", + "target: aria_quantiteEauDsAir_ext\n", + "\n", + "uri: m3p:set/event/2342104b-21a3-433c-987d-578106cc9cf8\n", + "target: aria_radiation_ext\n", + "\n", + "uri: m3p:set/event/25c545d3-b602-4f3a-bf5a-a3db01ae94e3\n", + "target: aria_vitesseVent_ext\n", + "\n", + "uri: m3p:set/event/283c1acf-d784-46b5-8a44-b8900030b42f\n", + "target: aria_hr_cE1\n", + "\n", + "uri: m3p:set/event/2d3dc380-3eb2-419c-9987-d6bd68e0fc1a\n", + "target: aria_co2_cE1\n", + "\n", + "uri: m3p:set/event/3d0355f6-04c0-4f56-84cf-6843a7015579\n", + "target: aria_hr_cE2\n", + "\n", + "... (13 more events)\n", + "\n" + ] + } + ], + "source": [ + "print(phis.get_event(max_results_per_type=10))" + ] + }, + { + "cell_type": "markdown", + "id": "9288a120-c65e-449a-b184-00445e17ae32", + "metadata": {}, + "source": [ + "#### Get specific event details" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "id": "e7691135-9933-4528-9ba1-eda10db27c19", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'metadata': {'pagination': {'pageSize': 0,\n", + " 'currentPage': 0,\n", + " 'totalCount': 0,\n", + " 'totalPages': 0,\n", + " 'limitCount': 0,\n", + " 'hasNextPage': False},\n", + " 'status': [],\n", + " 'datafiles': []},\n", + " 'result': {'uri': 'm3p:id/event/cb8b96ea-4d0b-4bc6-804f-e3cf2b56092e',\n", + " 'publisher': None,\n", + " 'rdf_type': 'oeev:ManualCalibration',\n", + " 'rdf_type_name': 'Manual calibration',\n", + " 'start': None,\n", + " 'end': '2024-05-02T15:02Z',\n", + " 'is_instant': True,\n", + " 'description': 'New settings for ZB24 experiment',\n", + " 'targets': ['m3p:id/device/imagingstation02'],\n", + " 'publication_date': '2024-05-28T17:19:08.252541+02:00',\n", + " 'last_updated_date': None}}" + ] + }, + "execution_count": 40, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "phis.get_event(uri='m3p:id/event/cb8b96ea-4d0b-4bc6-804f-e3cf2b56092e')" + ] + }, + { + "cell_type": "markdown", + "id": "a4e43648-30b1-413a-950f-84060ecc94ac", + "metadata": {}, + "source": [ + "#### List available species" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "id": "7ee85624-495d-4a36-860b-1fe407ab5491", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['apple tree',\n", + " 'banana',\n", + " 'barley',\n", + " 'bread wheat',\n", + " 'colza',\n", + " 'durum wheat',\n", + " 'grapevine',\n", + " 'maize',\n", + " 'Pearl millet',\n", + " 'poplar',\n", + " 'rice',\n", + " 'sorghum',\n", + " 'teosintes',\n", + " 'upland cotton']" + ] + }, + "execution_count": 41, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "phis.get_species()" + ] + }, + { + "cell_type": "markdown", + "id": "0300a106-63cf-4edb-b11f-1a579c9b14b6", + "metadata": {}, + "source": [ + "#### Get system informations" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "id": "4876c969-c954-417c-875f-7c6fe72a7fe2", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'metadata': {'pagination': {'pageSize': 0,\n", + " 'currentPage': 0,\n", + " 'totalCount': 0,\n", + " 'totalPages': 0,\n", + " 'limitCount': 0,\n", + " 'hasNextPage': False},\n", + " 'status': [],\n", + " 'datafiles': []},\n", + " 'result': {'title': 'OpenSILEX',\n", + " 'version': '1.2.7-rdg',\n", + " 'description': 'OpenSILEX is an ontology-driven Information System designed for life science data.',\n", + " 'contact': {'name': 'OpenSILEX Team',\n", + " 'email': 'opensilex-help@groupes.renater.fr',\n", + " 'homepage': 'http://www.opensilex.org/'},\n", + " 'license': {'name': 'GNU Affero General Public License v3',\n", + " 'url': 'https://www.gnu.org/licenses/agpl-3.0.fr.html'},\n", + " 'modules_version': [{'name': 'org.opensilex.server.ServerModule',\n", + " 'version': '1.2.7-rdg'},\n", + " {'name': 'org.opensilex.fs.FileStorageModule', 'version': '1.2.7-rdg'},\n", + " {'name': 'org.opensilex.nosql.NoSQLModule', 'version': '1.2.7-rdg'},\n", + " {'name': 'org.opensilex.sparql.SPARQLModule', 'version': '1.2.7-rdg'},\n", + " {'name': 'org.opensilex.security.SecurityModule', 'version': '1.2.7-rdg'},\n", + " {'name': 'org.opensilex.core.CoreModule', 'version': '1.2.7-rdg'},\n", + " {'name': 'org.opensilex.front.FrontModule', 'version': '1.2.7-rdg'},\n", + " {'name': 'org.opensilex.phis.PhisWsModule', 'version': '1.2.7-rdg'},\n", + " {'name': 'org.opensilex.graphql.GraphQLModule', 'version': '1.2.7-rdg'},\n", + " {'name': 'org.opensilex.dataverse.DataverseModule', 'version': '1.2.7-rdg'},\n", + " {'name': 'org.opensilex.migration.MigrationModule', 'version': '1.2.7-rdg'},\n", + " {'name': 'org.opensilex.brapi.BrapiModule', 'version': '1.2.7-rdg'}],\n", + " 'external_docs': {'description': 'Opensilex dev documentation',\n", + " 'url': 'https://github.com/OpenSILEX/opensilex/blob/master/opensilex-doc/src/main/resources/index.md'},\n", + " 'api_docs': {'description': 'Opensilex API documentation',\n", + " 'url': 'http://147.100.202.17/m3p/api-docs'},\n", + " 'git_commit': {'commit_id': '595cec2c7d62dddb274ded3810dd6c9fab91f552',\n", + " 'commit_message': 'Enable dataverse'},\n", + " 'github_page': 'https://github.com/OpenSILEX/opensilex'}}" + ] + }, + "execution_count": 42, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "phis.get_system_info()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/src/agroservices/phis/phis.py b/src/agroservices/phis/phis.py index 4c9fe8d..cfb7fc0 100644 --- a/src/agroservices/phis/phis.py +++ b/src/agroservices/phis/phis.py @@ -9,7 +9,7 @@ # ============================================================================== import urllib -from urllib.parse import quote +from urllib.parse import quote, quote_plus import requests import six @@ -18,12 +18,13 @@ # ============================================================================== __all__ = ["phis"] +DEFAULT_PAGE_SIZE=100 class Phis(REST): # TODO: Complete with the up to date requests def __init__(self, name='Phis', - url="http://147.100.202.17/m3p/rest/", + url="https://phenome.inrae.fr/m3p/rest/", callback=None, *args, **kwargs): super().__init__( name=name, @@ -31,6 +32,7 @@ def __init__(self, name='Phis', *args, **kwargs) self.callback = callback # use in all methods) + self.token, _ = self.authenticate() def post_json(self, web_service, json_txt, timeout=10., overwriting=False, **kwargs): @@ -59,363 +61,1536 @@ def post_json(self, web_service, json_txt, timeout=10., overwrote = True return response, overwrote - def get(self, web_service, timeout=10., **kwargs): + # def get(self, web_service, timeout=10., **kwargs): + # """ + + # :param web_service: (str) name of web service requested + # :param timeout: (float) timeout for connexion in seconds + # :param kwargs: (str) arguments relative to web service (see http://147.100.202.17/m3p/api-docs/) + # :return: + # (dict) response of the server (standard http) + # """ + # response = requests.request(method='GET', + # url=self.url + web_service, + # params=kwargs, timeout=timeout) + + # return response + + # def get_all_data(self, web_service, timeout=10., **kwargs): + # """ + + # :param web_service: (str) name of web service requested + # :param timeout: (float) timeout for connexion in seconds + # :param kwargs: (str) arguments relative to web service (see http://147.100.202.17/m3p/api-docs/) + # :return: + # (list of dict) data relative to web service and parameters + # """ + # current_page = 0 + # total_pages = 1 + # values = list() + + # # TODO remove 'plants' specificity as soon as web service delay fixed + # if not web_service == 'plants': + # kwargs['pageSize'] = 50000 + # else: + # kwargs['pageSize'] = 10 + + # while total_pages > current_page: + # kwargs['page'] = current_page + # response = requests.request(method='GET', + # url=self.url + web_service, + # params=kwargs, timeout=timeout) + # if response.status_code == 200: + # values.extend(response.json()) + # elif response.status_code == 500: + # raise Exception("Server error") + # else: + # raise Exception( + # response.json()["result"]["message"]) + + # if response.json()["metadata"]["pagination"] is None: + # total_pages = 0 + # else: + # total_pages = response.json()["metadata"]["pagination"][ + # "totalPages"] + # current_page += 1 + + # return values + + def authenticate(self, identifier='phenoarch@lepse.inra.fr', + password='phenoarch'): + """ Authenticate a user and return an access token """ + json = f"""{{ + "identifier": "{identifier}", + "password": "{password}" + }}""" + + response, _ = self.post_json('security/authenticate', json) + status_code = response.status_code + if status_code == 200: + token = response.json()['result']['token'] + elif status_code == 403: + raise ValueError(response.json()["result"]["message"]) + else: + raise Exception(response.json()["result"]["message"]) + return token, status_code - :param web_service: (str) name of web service requested - :param timeout: (float) timeout for connexion in seconds - :param kwargs: (str) arguments relative to web service (see http://147.100.202.17/m3p/api-docs/) + + def get_experiment_api(self, uri=None, name=None, year=None, is_ended=None, species=None, factors=None, + projects=None, is_public=None, facilities=None, order_by=None, page=None, page_size=None): + """ + This function can either retrieve detailed information about a specific experiment by its URI or list + experiments based on various filtering criteria. + + :param uri: (str) Specify an experiment URI to get detailed information about that specific experiment + :param name: (str) Filter experiments by name + :param year: (int) Filter experiments by year (e.g., 2012, 2013...) + :param is_ended: (bool) Filter experiments by their ended status + :param species: (array[str]) Filter experiments by species + :param factors: (array[str]) Filter experiments by factors + :param projects: (array[str]) Filter experiments by projects + :param is_public: (bool) Filter experiments by their public status + :param facilities: (array[str]) Filter experiments by facilities + :param order_by: (array[str]) Order the experiments by a specific field + :param page: (int) Specify the page number for pagination + :param page_size: (int) Specify the page size for pagination :return: - (dict) response of the server (standard http) + (dict or str) The experiment information or an error message + :raises: + Exception: if the experiment is not found (HTTP 404) or if the result is empty """ - response = requests.request(method='GET', - url=self.url + web_service, - params=kwargs, timeout=timeout) - return response + # Get specific experiment information by uri + if uri: + result = self.http_get(self.url + 'core/experiments/' + quote_plus(uri), headers={'Authorization':self.token}) + if result == 404: + raise Exception("Experiment not found") + return result + + # Get list of experiments based on filtering criteria + url = self.url + 'core/experiments' + query = {} + + if name: + query['name'] = name + if year is not None: + query['year'] = str(year) + if is_ended is not None: + query['is_ended'] = str(is_ended).lower() + if species: + query['species'] = species + if factors: + query['factors'] = factors + if projects: + query['projects'] = projects + if is_public is not None: + query['is_public'] = str(is_public).lower() + if facilities: + query['facilities'] = facilities + if order_by: + query['order_by'] = order_by + if page is not None: + query['page'] = str(page) + if page_size is not None: + query['page_size'] = str(page_size) - def get_all_data(self, web_service, timeout=10., **kwargs): + if query: + query_string = '&'.join(f'{key}={quote_plus(value)}' for key, value in query.items()) + url += '?' + query_string + + try: + response = self.http_get(url, headers={'Authorization':self.token}) + if response == 404: + raise Exception("Empty result") + return response + except Exception as e: + return str(e) + + + def get_variable_api(self, uri=None, name=None, entity=None, entity_of_interest=None, characteristic=None, + method=None, unit=None, group_of_variables=None, not_included_in_group_of_variables=None, data_type=None, + time_interval=None, species=None, withAssociatedData=None, experiments=None, scientific_objects=None, + devices=None, order_by=None, page=None, page_size=None, sharedResourceInstance=None): """ + This function can either retrieve detailed information about a specific variable by its URI or list + variables based on various filtering criteria. - :param web_service: (str) name of web service requested - :param timeout: (float) timeout for connexion in seconds - :param kwargs: (str) arguments relative to web service (see http://147.100.202.17/m3p/api-docs/) + :param uri: (str) Specify a variable URI to get detailed information about that specific variable + :param name: (str) Filter variables by name + :param entity: (str) Filter variables by entity + :param entity_of_interest: (str) Filter variables by entity of interest + :param characteristic: (str) Filter variables by characteristic + :param method: (str) Filter variables by method + :param unit: (str) Filter variables by unit + :param group_of_variables: (str) Filter variables by group of variables + :param not_included_in_group_of_variables: (str) Exclude variables that are in a specific group + :param data_type: (str) Filter variables by data type + :param time_interval: (str) Filter variables by time interval + :param species: (array[str]) Filter variables by species + :param withAssociatedData: (bool) Filter variables that have associated data + :param experiments: (array[str]) Filter variables by experiments + :param scientific_objects: (array[str]) Filter variables by scientific objects + :param devices: (array[str]) Filter variables by devices + :param order_by: (array[str]) Order the variables by a specific field + :param page: (int) Specify the page number for pagination + :param page_size: (int) Specify the page size for pagination + :param sharedResourceInstance: (str) Filter variables by shared resource instance :return: - (list of dict) data relative to web service and parameters + (dict or str) The variable information or an error message + :raises: + Exception: if the variable is not found (HTTP 404) or if the result is empty """ - current_page = 0 - total_pages = 1 - values = list() + # Get specific variable information by uri + if uri: + result = self.http_get(self.url + 'core/variables/' + + quote_plus(uri), headers={'Authorization':self.token}) + if result == 404: + raise Exception("Variable not found") + return result + + # Get list of variables based on filtering criteria + url = self.url + 'core/variables' + query = {} - # TODO remove 'plants' specificity as soon as web service delay fixed - if not web_service == 'plants': - kwargs['pageSize'] = 50000 + if name: + query['name'] = name + if entity: + query['entity'] = entity + if entity_of_interest: + query['entity_of_interest'] = entity_of_interest + if characteristic: + query['characteristic'] = characteristic + if method: + query['method'] = method + if unit: + query['unit'] = unit + if group_of_variables: + query['group_of_variables'] = group_of_variables + if not_included_in_group_of_variables: + query['not_included_in_group_of_variables'] = not_included_in_group_of_variables + if data_type: + query['data_type'] = data_type + if time_interval: + query['time_interval'] = time_interval + if species: + query['species'] = species + if withAssociatedData is not None: + query['withAssociatedData'] = str(withAssociatedData).lower() + if experiments: + query['experiments'] = experiments + if scientific_objects: + query['scientific_objects'] = scientific_objects + if devices: + query['devices'] = devices + if order_by: + query['order_by'] = order_by + if page is not None: + query['page'] = str(page) + if page_size is not None: + query['page_size'] = str(page_size) else: - kwargs['pageSize'] = 10 + query['page_size'] = str(DEFAULT_PAGE_SIZE) + if sharedResourceInstance: + query['sharedResourceInstance'] = sharedResourceInstance - while total_pages > current_page: - kwargs['page'] = current_page - response = requests.request(method='GET', - url=self.url + web_service, - params=kwargs, timeout=timeout) - if response.status_code == 200: - values.extend(response.json()) - elif response.status_code == 500: - raise Exception("Server error") - else: - raise Exception( - response.json()["result"]["message"]) - if response.json()["metadata"]["pagination"] is None: - total_pages = 0 - else: - total_pages = response.json()["metadata"]["pagination"][ - "totalPages"] - current_page += 1 + if query: + query_string = '&'.join(f'{key}={quote_plus(value)}' for key, value in query.items()) + url += '?' + query_string - return values + try: + response = self.http_get(url, headers={'Authorization':self.token}) + if response == 404: + raise Exception("Empty result") + return response + except Exception as e: + return str(e) + - def ws_token(self, username='pheonoarch@lepse.inra.fr', - password='phenoarch'): - """ Get token for PHIS web service - See http://147.100.202.17/m3p/api-docs/ for exact documentation + def get_project_api(self, uri=None, name=None, year=None, keyword=None, financial_funding=None, order_by=None, + page=None, page_size=None): + """ + This function can either retrieve detailed information about a specific project by its URI or list + projects based on various filtering criteria. - :param username: (str) - :param password: (str) + :param uri: (str) Specify a project URI to get detailed information about that specific project + :param name: (str) Filter projects by name + :param year: (int) Filter projects by year (e.g., 2012, 2013...) + :param keyword: (str) Filter projects by keyword + :param financial_funding: (str) Filter projects by financial funding source + :param order_by: (array[str]) Order the projects by a specific field + :param page: (int) Specify the page number for pagination + :param page_size: (int) Specify the page size for pagination :return: - (str) token value - """ - response = self.get('security/authenticate', username=username, - password=password) - if response.status_code in [200, 201]: - return response.json()['result'] - elif response.status_code == 500: - raise Exception("Server error") + (dict or str) The project information or an error message + :raises: + Exception: if the project is not found (HTTP 404 or 500) or if the result is empty + """ + # Get specific project information by uri + if uri: + result = self.http_get(self.url + 'core/projects/' + + quote_plus(uri), headers={'Authorization':self.token}) + if (result == 404 or result == 500): + raise Exception("Project not found") + return result + + # Get list of projects based on filtering criteria + url = self.url + 'core/projects' + query = {} + + if name is not None: + query['name'] = name + if year is not None: + query['year'] = str(year) + if keyword is not None: + query['keyword'] = keyword + if financial_funding is not None: + query['financial_funding'] = financial_funding + if order_by is not None: + query['order_by'] = order_by + if page is not None: + query['page'] = str(page) + if page_size is not None: + query['page_size'] = str(page_size) else: - raise Exception(response.json()["result"]["message"]) + query['page_size'] = str(DEFAULT_PAGE_SIZE) + + if query: + query_string = '&'.join(f'{key}={quote_plus(value)}' for key, value in query.items()) + url += '?' + query_string + + try: + response = self.http_get(url, headers={'Authorization':self.token}) + if response == 404: + raise Exception("Empty result") + return response + except Exception as e: + return str(e) + + + def get_facility_api(self, uri=None, pattern=None, organizations=None, order_by=None, page=None, page_size=None): + """ + This function can either retrieve detailed information about a specific facility by its URI or list + facilities based on various filtering criteria. - def ws_projects(self, session_id, project_name=''): - """ Get all projects information if project_name is empty, or only information about project_name specified - See http://147.100.202.17/m3p/api-docs/ for exact documentation + :param uri: (str) Specify a facility URI to get detailed information about that specific facility + :param pattern: (str) Filter facilities by pattern + :param organizations: (array[str]) Filter facilities by organizations + :param order_by: (array[str]) Order the facilities by a specific field + :param page: (int) Specify the page number for pagination + :param page_size: (int) Specify the page size for pagination + :return: + (dict or str) The facility information or an error message + :raises: + Exception: if the facility is not found (HTTP 404) or if the result is empty + """ + # Get specific facility information by uri + if uri: + result = self.http_get(self.url + 'core/facilities/' + + quote_plus(uri), headers={'Authorization':self.token}) + if (result == 404): + raise Exception("Facility not found") + return result + + # Get list of facilities based on filtering criteria + url = self.url + 'core/facilities' + query = {} + + if pattern is not None: + query['pattern'] = pattern + if organizations is not None: + query['organizations'] = organizations + if order_by is not None: + query['order_by'] = order_by + if page is not None: + query['page'] = str(page) + if page_size is not None: + query['page_size'] = str(page_size) + else: + query['page_size'] = str(DEFAULT_PAGE_SIZE) + + if query: + query_string = '&'.join(f'{key}={quote_plus(value)}' for key, value in query.items()) + url += '?' + query_string + + try: + response = self.http_get(url, headers={'Authorization':self.token}) + if response == 404: + raise Exception("Empty result") + return response + except Exception as e: + return str(e) + - :param session_id: (str) token got from ws_token() - :param project_name: (str) specify a project name to get detailed information + def get_germplasm_api(self, uri=None, rdf_type=None, name=None, code=None, production_year=None, species=None, variety=None, + accession=None, group_of_germplasm=None, institute=None, experiment=None, parent_germplasms=None, + parent_germplasms_m=None, parent_germplasms_f=None, metadata=None, order_by=None, page=None, page_size=None): + """ + This function can either retrieve detailed information about a specific germplasm by its URI or list + germplasms based on various filtering criteria. + + :param uri: (str) Specify a germplasm URI to get detailed information about that specific germplasm + :param rdf_type: (str) Filter germplasms by RDF type + :param name: (str) Filter germplasms by name + :param code: (str) Filter germplasms by code + :param production_year: (int) Filter germplasms by production year + :param species: (str) Filter germplasms by species + :param variety: (str) Filter germplasms by variety + :param accession: (str) Filter germplasms by accession + :param group_of_germplasm: (str) Filter germplasms by group of germplasm + :param institute: (str) Filter germplasms by institute + :param experiment: (str) Filter germplasms by experiment + :param parent_germplasms: (array[str]) Filter germplasms by parent germplasms + :param parent_germplasms_m: (array[str]) Filter germplasms by male parent germplasms + :param parent_germplasms_f: (array[str]) Filter germplasms by female parent germplasms + :param metadata: (dict) Filter germplasms by metadata + :param order_by: (array[str]) Order the germplasms by a specific field + :param page: (int) Specify the page number for pagination + :param page_size: (int) Specify the page size for pagination :return: - (list of dict) projects list (one value only in list if project_name specified) + (dict or str) The germplasm information or an error message + :raises: + Exception: if the germplasm is not found (HTTP 404) or if the result is empty """ - return self.get_all_data('projects/' + project_name, - sessionId=session_id) + # Get specific germplasm information by uri + if uri: + result = self.http_get(self.url + 'core/germplasm/' + + quote_plus(uri), headers={'Authorization':self.token}) + if result == 404: + raise Exception("Germplasm not found") + return result + + # Get list of germplasms based on filtering criteria + url = self.url + 'core/germplasm' + query = {} + + if rdf_type is not None: + query['rdf_type'] = rdf_type + if name is not None: + query['name'] = name + if code is not None: + query['code'] = code + if production_year is not None: + query['production_year'] = str(production_year) + if species is not None: + query['species'] = species + if variety is not None: + query['variety'] = variety + if accession is not None: + query['accession'] = accession + if group_of_germplasm is not None: + query['group_of_germplasm'] = group_of_germplasm + if institute is not None: + query['institute'] = institute + if experiment is not None: + query['experiment'] = experiment + if parent_germplasms is not None: + query['parent_germplasms'] = parent_germplasms + if parent_germplasms_m is not None: + query['parent_germplasms_m'] = parent_germplasms_m + if parent_germplasms_f is not None: + query['parent_germplasms_f'] = parent_germplasms_f + if metadata is not None: + query['metadata'] = metadata + if order_by is not None: + query['order_by'] = order_by + if page is not None: + query['page'] = str(page) + if page_size is not None: + query['page_size'] = str(page_size) + else: + query['page_size'] = str(DEFAULT_PAGE_SIZE) + + if query: + query_string = '&'.join(f'{key}={quote_plus(value)}' for key, value in query.items()) + url += '?' + query_string + + try: + response = self.http_get(url, headers={'Authorization':self.token}) + if response == 404: + raise Exception("Empty result") + return response + except Exception as e: + return str(e) + + + def get_device_api(self, uri=None, rdf_type=None, include_subtypes=None, name=None, variable=None, year=None, existence_date=None, + facility=None, brand=None, model=None, serial_number=None, metadata=None, order_by=None, page=None, + page_size=None): + """ + This function can either retrieve detailed information about a specific device by its URI or list + devices based on various filtering criteria. + + :param uri: (str) Specify a device URI to get detailed information about that specific device + :param rdf_type: (str) Filter devices by RDF type + :param include_subtypes: (bool) Include subtypes in the filtering + :param name: (str) Filter devices by name + :param variable: (str) Filter devices by variable + :param year: (int) Filter devices by year + :param existence_date: (datetime.date) Filter devices by existence date (format: YYYY-MM-DD) + :param facility: (str) Filter devices by facility + :param brand: (str) Filter devices by brand + :param model: (str) Filter devices by model + :param serial_number: (str) Filter devices by serial number + :param metadata: (str) Filter devices by metadata + :param order_by: (array[str]) Order the devices by a specific field + :param page: (int) Specify the page number for pagination + :param page_size: (int) Specify the page size for pagination + :return: + (dict or str) The device information or an error message + :raises: + Exception: if the device is not found (HTTP 404) or if the result is empty + """ + # Get specific device information by uri + if uri: + result = self.http_get(self.url + 'core/devices/' + + quote_plus(uri), headers={'Authorization':self.token}) + if result == 404: + raise Exception("Device not found") + return result + + # Get list of devices based on filtering criteria + url = self.url + 'core/devices' + query = {} + + if rdf_type is not None: + query['rdf_type'] = rdf_type + if include_subtypes is not None: + query['include_subtypes'] = str(include_subtypes).lower() + if name is not None: + query['name'] = name + if variable is not None: + query['variable'] = variable + if year is not None: + query['year'] = str(year) + if existence_date is not None: + query['existence_date'] = existence_date.strftime('%Y-%m-%d') + if facility is not None: + query['facility'] = facility + if brand is not None: + query['brand'] = brand + if model is not None: + query['model'] = model + if serial_number is not None: + query['serial_number'] = serial_number + if metadata is not None: + query['metadata'] = metadata + if order_by is not None: + query['order_by'] = order_by + if page is not None: + query['page'] = str(page) + if page_size is not None: + query['page_size'] = str(page_size) + else: + query['page_size'] = str(DEFAULT_PAGE_SIZE) + + if query: + query_string = '&'.join(f'{key}={quote_plus(value)}' for key, value in query.items()) + url += '?' + query_string + + try: + response = self.http_get(url, headers={'Authorization':self.token}) + if response == 404: + raise Exception("Empty result") + return response + except Exception as e: + return str(e) + + + def get_annotation_api(self, uri=None, description=None, target=None, motivation=None, author=None, order_by=None, + page=None, page_size=None): + """ + This function can either retrieve detailed information about a specific annotation by its URI or list + annotations based on various filtering criteria. + + :param uri: (str) Specify an annotation URI to get detailed information about that specific annotation + :param description: (str) Filter annotations by description + :param target: (str) Filter annotations by target + :param motivation: (str) Filter annotations by motivation + :param author: (str) Filter annotations by author + :param order_by: (array[str]) Order the annotations by a specific field + :param page: (int) Specify the page number for pagination + :param page_size: (int) Specify the page size for pagination + :return: + (dict or str) The annotation information or an error message + :raises: + Exception: if the annotation is not found (HTTP 404) or if the result is empty + """ + # Get specific annotation information by uri + if uri: + result = self.http_get(self.url + 'core/annotations/' + + quote_plus(uri), headers={'Authorization':self.token}) + if result == 404: + raise Exception("Annotation not found") + return result + + # Get list of annotations based on filtering criteria + url = self.url + 'core/annotations' + query = {} + + if description is not None: + query['description'] = description + if target is not None: + query['target'] = target + if motivation is not None: + query['motivation'] = motivation + if author is not None: + query['author'] = author + if order_by is not None: + query['order_by'] = order_by + if page is not None: + query['page'] = str(page) + if page_size is not None: + query['page_size'] = str(page_size) + else: + query['page_size'] = str(DEFAULT_PAGE_SIZE) + + if query: + query_string = '&'.join(f'{key}={quote_plus(value)}' for key, value in query.items()) + url += '?' + query_string + + try: + response = self.http_get(url, headers={'Authorization':self.token}) + if response == 404: + raise Exception("Empty result") + return response + except Exception as e: + return str(e) + + + def get_document_api(self, uri=None, rdf_type=None, title=None, date=None, targets=None, authors=None, keyword=None, multiple=None, + deprecated=None, order_by=None, page=None, page_size=None): + """ + This function can either retrieve detailed information about a specific document by its URI or list + documents based on various filtering criteria. + + :param uri: (str) Specify a document URI to get detailed information about that specific document + :param rdf_type: (str) Filter documents by RDF type + :param title: (str) Filter documents by title + :param date: (str) Filter documents by date (format: YYYY-MM-DD) + :param targets: (str) Filter documents by targets + :param authors: (str) Filter documents by authors + :param keyword: (str) Filter documents by keyword + :param multiple: (str) Filter documents by their multiple status + :param deprecated: (str) Filter documents by their deprecated status + :param order_by: (array[str]) Order the documents by a specific field + :param page: (int) Specify the page number for pagination + :param page_size: (int) Specify the page size for pagination + :return: + (dict or str) The document information or an error message + :raises: + Exception: if the document is not found (HTTP 404) or if the result is empty + """ + # Get specific document information by uri + # Doesn't work + # if uri: + # result = self.http_get(self.url + 'core/documents/' + # + quote_plus(uri), headers={'Authorization':token}) + # if result == 404: + # raise Exception("Document not found") + # return result + + if uri: + result = self.http_get(self.url + 'core/documents/' + + quote_plus(uri) + '/description', headers={'Authorization':self.token}) + if result == 404: + raise Exception("Document not found") + return result + + # Get list of documents based on filtering criteria + url = self.url + 'core/documents' + query = {} + + if rdf_type is not None: + query['rdf_type'] = rdf_type + if title is not None: + query['title'] = title + if date is not None: + query['date'] = date + if targets is not None: + query['targets'] = targets + if authors is not None: + query['authors'] = authors + if keyword is not None: + query['keyword'] = keyword + if multiple is not None: + query['multiple'] = multiple + if deprecated is not None: + query['deprecated'] = deprecated + if order_by is not None: + query['order_by'] = order_by + if page is not None: + query['page'] = str(page) + if page_size is not None: + query['page_size'] = str(page_size) + else: + query['page_size'] = str(DEFAULT_PAGE_SIZE) + + if query: + query_string = '&'.join(f'{key}={quote_plus(value)}' for key, value in query.items()) + url += '?' + query_string + + try: + response = self.http_get(url, headers={'Authorization':self.token}) + if response == 404: + raise Exception("Empty result") + return response + except Exception as e: + return str(e) + + + def get_factor_api(self, uri=None, name=None, description=None, category=None, experiment=None, order_by=None, page=None, + page_size=None): + """ + This function can either retrieve detailed information about a specific factor by its URI or list + factors based on various filtering criteria. + + :param uri: (str) Specify a factor URI to get detailed information about that specific factor + :param name: (str) Filter factors by name + :param description: (str) Filter factors by description + :param category: (str) Filter factors by category + :param experiment: (str) Filter factors by experiment + :param order_by: (array[str]) Order the factors by a specific field + :param page: (int) Specify the page number for pagination + :param page_size: (int) Specify the page size for pagination + :return: + (dict or str) The factor information or an error message + :raises: + Exception: if the factor is not found (HTTP 404) or if the result is empty + """ + # Get specific factor information by uri + if uri: + result = self.http_get(self.url + 'core/experiments/factors/' + + quote_plus(uri), headers={'Authorization':self.token}) + if result == 404: + raise Exception("Factor not found") + return result + + # Get list of factors based on filtering criteria + url = self.url + 'core/experiments/factors' + query = {} + + if name is not None: + query['name'] = name + if description is not None: + query['description'] = description + if category is not None: + query['category'] = category + if experiment is not None: + query['experiment'] = experiment + if order_by is not None: + query['order_by'] = order_by + if page is not None: + query['page'] = str(page) + if page_size is not None: + query['page_size'] = str(page_size) + else: + query['page_size'] = str(DEFAULT_PAGE_SIZE) + + if query: + query_string = '&'.join(f'{key}={quote_plus(value)}' for key, value in query.items()) + url += '?' + query_string + + try: + response = self.http_get(url, headers={'Authorization':self.token}) + if response == 404: + raise Exception("Empty result") + return response + except Exception as e: + return str(e) + + + def get_organization_api(self, uri=None, pattern=None, organisation_uris=None, page=None, page_size=None): + """ + This function can either retrieve detailed information about a specific organization by its URI or list + organizations based on various filtering criteria. + + :param uri: (str) Specify an organization URI to get detailed information about that specific organization + :param pattern: (str) Filter organizations by pattern + :param organisation_uris: (array[str]) Filter organizations by URIs + :param page: (int) Specify the page number for pagination + :param page_size: (int) Specify the page size for pagination + :return: + (dict or str) The organization information or an error message + :raises: + Exception: if the organization is not found (HTTP 404) or if the result is empty + """ + # Get specific organization information by uri + if uri: + result = self.http_get(self.url + 'core/organisations/' + + quote_plus(uri), headers={'Authorization':self.token}) + if result == 404: + raise Exception("Organization not found") + return result + + # Get list of organizations based on filtering criteria + url = self.url + 'core/organisations' + query = {} + + if pattern is not None: + query['pattern'] = pattern + if organisation_uris is not None: + query['organisation_uris'] = organisation_uris + if page is not None: + query['page'] = str(page) + if page_size is not None: + query['page_size'] = str(page_size) + else: + query['page_size'] = str(DEFAULT_PAGE_SIZE) + + if query: + query_string = '&'.join(f'{key}={quote_plus(value)}' for key, value in query.items()) + url += '?' + query_string - def ws_germplasms(self, session_id, experiment_uri=None, species_uri=None, - project_name=None, germplasm_uri=None): - """ Get information about genotypes in experiments - See http://147.100.202.17/m3p/api-docs/ for exact documentation + try: + response = self.http_get(url, headers={'Authorization':self.token}) + if response == 404: + raise Exception("Empty result") + return response + except Exception as e: + return str(e) + - :param session_id: (str) token got from ws_token() - :param experiment_uri: (str or list of str) experiment URI - :param species_uri: (str) specie URI - :param project_name: (str) not available - :param germplasm_uri: (str) if specified then experiment_uri, species_uri and project_name parameters are useless + def get_site_api(self, uri=None, pattern=None, organizations=None, order_by=None, page=None, page_size=None): + """ + This function can either retrieve detailed information about a specific site by its URI or list + sites based on various filtering criteria. + + :param uri: (str) Specify a site URI to get detailed information about that specific site + :param pattern: (str) Filter sites by pattern + :param organizations: (array[str]) Filter sites by organizations + :param order_by: (array[str]) Order the sites by a specific field + :param page: (int) Specify the page number for pagination + :param page_size: (int) Specify the page size for pagination :return: - (list of dict) genotypic information of genotypes used in specific experiments, or for specific specie - """ - if experiment_uri is None and species_uri is None and germplasm_uri is None: - raise Exception( - "You must specify one of experiment_uri, species_uri or germplasms_uri") - if isinstance(germplasm_uri, six.string_types): - return self.get_all_data('germplasms/' + quote( - germplasm_uri), sessionId=session_id) + (dict or str) The site information or an error message + :raises: + Exception: if the site is not found (HTTP 404) or if the result is empty + """ + # Get specific site information by uri + if uri: + result = self.http_get(self.url + 'core/sites/' + + quote_plus(uri), headers={'Authorization':self.token}) + if result == 404: + raise Exception("Site not found") + return result + + # Get list of sites based on filtering criteria + url = self.url + 'core/sites' + query = {} + + if pattern is not None: + query['pattern'] = pattern + if organizations is not None: + query['organizations'] = organizations + if order_by is not None: + query['order_by'] = order_by + if page is not None: + query['page'] = str(page) + if page_size is not None: + query['page_size'] = str(page_size) else: - if isinstance(experiment_uri, list): - experiment_uri = ','.join(experiment_uri) - return self.get_all_data('germplasms', - sessionId=session_id, - experimentURI=experiment_uri, - speciesURI=species_uri, - projectName=project_name) - - def ws_environment(self, session_id, experiment_uri=None, - variable_category=None, - variables=None, facility=None, - start_date=None, end_date=None, plant_uri=None): - """ Get environment sensors values from PHIS web service - See http://147.100.202.17/m3p/api-docs/ for exact documentation - - :param session_id: (str) token got from ws_token() - :param experiment_uri: (str) An experiment URI - :param variable_category: (str) Categories available in environment - must one of the list : ["setpoint", "meteorological", "micrometeo", "setting"] - :param variables: (str or list of str) variables types - :param facility: (str) Environment location - :param start_date: (str) Date of the first data (superior or equal) ( Format: YYYY-MM-DD or YYYY-MM-DD HH:MM:SS or - YYYY-MM-DD HH:MM:SSZZ (ZZ = +01:00) ) - :param end_date: (str) Date of the last data (inferior or equal)( Format: YYYY-MM-DD or YYYY-MM-DD HH:MM:SS or - YYYY-MM-DD HH:MM:SSZZ (ZZ = +01:00) ) - :param plant_uri: (str) plant URI to get only values of concerned sensors + query['page_size'] = str(DEFAULT_PAGE_SIZE) + + if query: + query_string = '&'.join(f'{key}={quote_plus(value)}' for key, value in query.items()) + url += '?' + query_string + + try: + response = self.http_get(url, headers={'Authorization':self.token}) + if response == 404: + raise Exception("Empty result") + return response + except Exception as e: + return str(e) + + + def get_scientific_object_api(self, uri=None, experiment=None, rdf_types=None, name=None, parent=None, germplasms=None, + factor_levels=None, facility=None, variables=None, devices=None, existence_date=None, + creation_date=None, criteria_on_data=None, order_by=None, page=None, page_size=None): + """ + This function can either retrieve detailed information about a specific scientific object by its URI or list + scientific objects based on various filtering criteria. + + :param uri: (str) Specify a scientific object URI to get detailed information about that specific object + :param experiment: (str) Filter scientific objects by experiment + :param rdf_types: (array[str]) Filter scientific objects by RDF types + :param name: (str) Filter scientific objects by name + :param parent: (str) Filter scientific objects by parent + :param germplasms: (array[str]) Filter scientific objects by germplasms + :param factor_levels: (array[str]) Filter scientific objects by factor levels + :param facility: (str) Filter scientific objects by facility + :param variables: (array[str]) Filter scientific objects by variables + :param devices: (array[str]) Filter scientific objects by devices + :param existence_date: (datetime.date) Filter scientific objects by existence date + :param creation_date: (datetime.date) Filter scientific objects by creation date + :param criteria_on_data: (str) Filter scientific objects by criteria on data + :param order_by: (array[str]) Order the scientific objects by a specific field + :param page: (int) Specify the page number for pagination + :param page_size: (int) Specify the page size for pagination :return: - (list of dict) environmental data in respect to parameters - """ - if isinstance(variables, list): - variables = ','.join(variables) - if isinstance(plant_uri, six.string_types): - return self.get_all_data('plants/' + quote( - plant_uri) + '/environment', timeout=20., - sessionId=session_id, - experimentURI=experiment_uri, - variableCategory=variable_category, - variables=variables, facility=facility, - startDate=start_date, endDate=end_date) + (dict or str) The scientific object information or an error message + :raises: + Exception: if the scientific object is not found (HTTP 404) or if the result is empty + """ + # Get specific scientific object information by uri + if uri: + result = self.http_get(self.url + 'core/scientific_objects/' + + quote_plus(uri), headers={'Authorization':self.token}) + if result == 404: + raise Exception("Scientific object not found") + return result + + # Get list of scientific objects based on filtering criteria + url = self.url + 'core/scientific_objects' + query = {} + + if experiment is not None: + query['experiment'] = experiment + if rdf_types is not None: + query['rdf_types'] = rdf_types + if name is not None: + query['name'] = name + if parent is not None: + query['parent'] = parent + if germplasms is not None: + query['germplasms'] = germplasms + if factor_levels is not None: + query['factor_levels'] = factor_levels + if facility is not None: + query['facility'] = facility + if variables is not None: + query['variables'] = variables + if devices is not None: + query['devices'] = devices + if existence_date is not None: + query['existence_date'] = existence_date.strftime('%Y-%m-%d') + if creation_date is not None: + query['creation_date'] = creation_date.strftime('%Y-%m-%d') + if criteria_on_data is not None: + query['criteria_on_data'] = criteria_on_data + if order_by is not None: + query['order_by'] = order_by + if page is not None: + query['page'] = str(page) + if page_size is not None: + query['page_size'] = str(page_size) else: - return self.get_all_data('environment', timeout=20., - sessionId=session_id, - experimentURI=experiment_uri, - variableCategory=variable_category, - variables=variables, facility=facility, - startDate=start_date, endDate=end_date) - - def ws_variables(self, session_id, experiment_uri, category='environment', - provider='lepse'): - """ Get variables information according to category specified - See http://147.100.202.17/m3p/api-docs/ for exact documentation - - :param session_id: (str) token got from ws_token() - :param experiment_uri: (str) an experiment URI - :param category: (str) variable categories available, - must be one of ['environment', 'imagery', 'watering', 'weighing', 'phenotyping'] - :param provider: (str) provider of imagery processing (only used for 'imagery' category), - might be 'lemnatec' before 2015, and then 'elcom or 'lepse' + query['page_size'] = str(DEFAULT_PAGE_SIZE) + + if query: + query_string = '&'.join(f'{key}={quote_plus(value)}' for key, value in query.items()) + url += '?' + query_string + + try: + response = self.http_get(url, headers={'Authorization':self.token}) + if response == 404: + raise Exception("Empty result") + return response + except Exception as e: + return str(e) + + + def get_species_api(self, sharedResourceInstance=None): + """ + Retrieve a list of species based on optional filtering criteria. + + :param sharedResourceInstance: (str) Filter species by shared resource instance :return: - (list of dict) available variables for an experiment - """ - return self.get_all_data('variables/category/' + category, - sessionId=session_id, - experimentURI=experiment_uri, - imageryProvider=provider) - - def ws_experiments(self, session_id, project_name=None, season=None, - experiment_uri=None): - """ Get all experiments information from a project or/and a season, or only information about experiment_uri - specified - See http://147.100.202.17/m3p/api-docs/ for exact documentation - - :param session_id: (str) token got from ws_token() - :param project_name: (str) specify a project name to get specifics experiments information - :param season: (int or str) find experiments by season (eg. 2012, 2013...) - :param experiment_uri: (str) specify an experiment URI to get detailed information + (dict or str) The list of species or an error message + :raises: + Exception: if the result is empty (HTTP 404) or if there's an error during retrieval + """ + # Get list of species + url = self.url + 'core/species' + query = {} + + if sharedResourceInstance is not None: + query['sharedResourceInstance'] = sharedResourceInstance + + if query: + query_string = '&'.join(f'{key}={quote_plus(value)}' for key, value in query.items()) + url += '?' + query_string + + try: + response = self.http_get(url, headers={'Authorization':self.token}) + if response == 404: + raise Exception("Empty result") + return response + except Exception as e: + return str(e) + + + def get_system_info_api(self): + """ + Retrieve system information. + :return: - (list of dict) experiments information - """ - if project_name is None and season is None and experiment_uri is None: - raise Exception( - "You must specify one parameter of project_name, season or experiment_uri") - if isinstance(experiment_uri, six.string_types): - return self.get_all_data('core/experiments/' + quote( - experiment_uri) + '/details', - sessionId=session_id) + (dict or str) System information or an error message + :raises: + Exception: if the result is empty (HTTP 404) or if there's an error during retrieval + """ + # Get system informations + url = self.url + 'core/system/info' + + try: + response = self.http_get(url, headers={'Authorization':self.token}) + if response == 404: + raise Exception("Empty result") + return response + except Exception as e: + return str(e) + + + def get_characteristic_api(self, uri=None, name=None, order_by=None, page=None, page_size=None, sharedResourceInstance=None): + """ + Retrieve specific characteristic information by URI or list characteristics based on filtering criteria. + + :param uri: (str) URI of the specific characteristic to retrieve + :param name: (str) Filter characteristics by name + :param order_by: (array[str]) Order the characteristics by a specific field + :param page: (int) Page number for pagination + :param page_size: (int) Page size for pagination + :param sharedResourceInstance: (str) Filter characteristics by shared resource instance + :return: + (dict or str) Characteristic information or an error message + :raises: + Exception: if the characteristic is not found (HTTP 404) or if the result is empty + """ + # Get specific characteristic information by uri + if uri: + result = self.http_get(self.url + 'core/characteristics/' + + quote_plus(uri), headers={'Authorization':self.token}) + if result == 404: + raise Exception("Characteristic not found") + return result + + # Get list of characterstics based on filtering criteria + url = self.url + 'core/characteristics' + query = {} + + if name is not None: + query['name'] = name + if order_by is not None: + query['order_by'] = order_by + if page is not None: + query['page'] = str(page) + if page_size is not None: + query['page_size'] = str(page_size) else: - return self.get_all_data('core/experiments', - sessionId=session_id, - projectName=project_name, season=season) - - def ws_label_views(self, session_id, experiment_uri, camera_angle=None, - view_type=None, provider=None): - """ Get existing label views for a specific experiment - See http://147.100.202.17/m3p/api-docs/ for exact documentation - - :param session_id: (str) token got from ws_token() - :param experiment_uri: (str) an experiment URI - :param camera_angle: (int) angle of the camera (between 0 and 360°, usually each 30°) - :param view_type: (str) usually one of ['top', 'side'] - :param provider: (str) usually lemnatec or elcom (useful ??) + query['page_size'] = str(DEFAULT_PAGE_SIZE) + if sharedResourceInstance is not None: + query['sharedResourceInstance'] = sharedResourceInstance + + if query: + query_string = '&'.join(f'{key}={quote_plus(value)}' for key, value in query.items()) + url += '?' + query_string + + try: + response = self.http_get(url, headers={'Authorization':self.token}) + if response == 404: + raise Exception("Empty result") + return response + except Exception as e: + return str(e) + + + def get_entity_api(self, uri=None, name=None, order_by=None, page=None, page_size=None, sharedResourceInstance=None): + """ + Retrieve specific entity information by URI or list entities based on filtering criteria. + + :param uri: (str) URI of the specific entity to retrieve + :param name: (str) Filter entities by name + :param order_by: (array[str]) Order the entities by a specific field + :param page: (int) Page number for pagination + :param page_size: (int) Page size for pagination + :param sharedResourceInstance: (str) Filter entities by shared resource instance :return: - (list of dict) label views + (dict or str) Entity information or an error message + :raises: + Exception: if the entity is not found (HTTP 404) or if the result is empty """ - return self.get_all_data('experiments/' + quote( - experiment_uri) + '/labelViews', timeout=30., - sessionId=session_id, cameraAngle=camera_angle, - viewType=view_type, provider=provider) + # Get specific entity information by uri + if uri: + result = self.http_get(self.url + 'core/entities/' + + quote_plus(uri), headers={'Authorization':self.token}) + if result == 404: + raise Exception("Entity not found") + return result + + # Get list of entities based on filtering criteria + url = self.url + 'core/entities' + query = {} + + if name is not None: + query['name'] = name + if order_by is not None: + query['order_by'] = order_by + if page is not None: + query['page'] = str(page) + if page_size is not None: + query['page_size'] = str(page_size) + else: + query['page_size'] = str(DEFAULT_PAGE_SIZE) + if sharedResourceInstance is not None: + query['sharedResourceInstance'] = sharedResourceInstance - def ws_observation_variables(self, session_id, experiment_uri): - """ Get existing observation variables for a specific experiment - See http://147.100.202.17/m3p/api-docs/ for exact documentation + if query: + query_string = '&'.join(f'{key}={quote_plus(value)}' for key, value in query.items()) + url += '?' + query_string + + try: + response = self.http_get(url, headers={'Authorization':self.token}) + if response == 404: + raise Exception("Empty result") + return response + except Exception as e: + return str(e) + + + def get_entity_of_interest_api(self, uri=None, name=None, order_by=None, page=None, page_size=None, sharedResourceInstance=None): + """ + Retrieve specific entity of interest information by URI or list entities of interest based on filtering criteria. - :param session_id: (str) token got from ws_token() - :param experiment_uri: (str) an experiment URI + :param uri: (str) URI of the specific entity ofinterest to retrieve + :param name: (str) Filter entities of interest by name + :param order_by: (array[str]) Order the entities of interest by a specific field + :param page: (int) Page number for pagination + :param page_size: (int) Page size for pagination + :param sharedResourceInstance: (str) Filter entities of interest by shared resource instance :return: - (list of dict) observation variables - """ - return self.get_all_data('experiments/' + quote( - experiment_uri) + '/observationVariables', - sessionId=session_id) - - def ws_weighing(self, session_id, experiment_uri, date=None, - variables_name=None): - """ Get weighing data for a specific experiment - See http://147.100.202.17/m3p/api-docs/ for exact documentation - - :param session_id: (str) token got from ws_token() - :param experiment_uri: (str) an experiment URI - :param date: (str) Retrieve weighing data which been produced a particular day. Format :yyyy-MM-dd - :param variables_name: (str or list of str) name of one or several weighing variables - might be one of ['weightBefore', 'weightAfter', 'weight'] + (dict or str) entity of interest information or an error message + :raises: + Exception: if the entity of interest is not found (HTTP 404) or if the result is empty + """ + # Get specific entity of interest information by uri + if uri: + result = self.http_get(self.url + 'core/entities_of_interest/' + + quote_plus(uri), headers={'Authorization':self.token}) + if result == 404: + raise Exception("Entity of interest not found") + return result + + # Get list of entities of interest based on filtering criteria + url = self.url + 'core/entities_of_interest' + query = {} + + if name is not None: + query['name'] = name + if order_by is not None: + query['order_by'] = order_by + if page is not None: + query['page'] = str(page) + if page_size is not None: + query['page_size'] = str(page_size) + else: + query['page_size'] = str(DEFAULT_PAGE_SIZE) + if sharedResourceInstance is not None: + query['sharedResourceInstance'] = sharedResourceInstance + + if query: + query_string = '&'.join(f'{key}={quote_plus(value)}' for key, value in query.items()) + url += '?' + query_string + + try: + response = self.http_get(url, headers={'Authorization':self.token}) + if response == 404: + raise Exception("Empty result") + return response + except Exception as e: + return str(e) + + + def get_method_api(self, uri=None, name=None, order_by=None, page=None, page_size=None, sharedResourceInstance=None): + """ + Retrieve specific method information by URI or list methods based on filtering criteria. + + :param uri: (str) URI of the specific method to retrieve + :param name: (str) Filter methods by name + :param order_by: (array[str]) Order the methods by a specific field + :param page: (int) Page number for pagination + :param page_size: (int) Page size for pagination + :param sharedResourceInstance: (str) Filter methods by shared resource instance :return: - (list of dict) weighing data for a specific experiment - """ - if isinstance(variables_name, list): - variables_name = ','.join(variables_name) - return self.get_all_data('weighing', sessionId=session_id, - experimentURI=experiment_uri, date=date, - variablesName=variables_name) - - def ws_plants(self, session_id, experiment_uri, plant_alias=None, - germplasms_uri=None, plant_uri=None): - """ Get plants information for an experiment - See http://147.100.202.17/m3p/api-docs/ for exact documentation - - :param session_id: (str) token got from ws_token() - :param experiment_uri: (str) an experiment URI - :param plant_alias: (str) alias of plant, usually the name used in experimentation - :param germplasms_uri: (str) URI of a germplasm - :param plant_uri: (str) specify a plant URI to get detailed information + (dict or str) method information or an error message + :raises: + Exception: if the method is not found (HTTP 404) or if the result is empty + """ + # Get specific method information by uri + if uri: + result = self.http_get(self.url + 'core/methods/' + + quote_plus(uri), headers={'Authorization':self.token}) + if result == 404: + raise Exception("Method not found") + return result + + # Get list of methods based on filtering criteria + url = self.url + 'core/methods' + query = {} + + if name is not None: + query['name'] = name + if order_by is not None: + query['order_by'] = order_by + if page is not None: + query['page'] = str(page) + if page_size is not None: + query['page_size'] = str(page_size) + else: + query['page_size'] = str(DEFAULT_PAGE_SIZE) + if sharedResourceInstance is not None: + query['sharedResourceInstance'] = sharedResourceInstance + + if query: + query_string = '&'.join(f'{key}={quote_plus(value)}' for key, value in query.items()) + url += '?' + query_string + + try: + response = self.http_get(url, headers={'Authorization':self.token}) + if response == 404: + raise Exception("Empty result") + return response + except Exception as e: + return str(e) + + + def get_unit_api(self, uri=None, name=None, order_by=None, page=None, page_size=None, sharedResourceInstance=None): + # Get specific unit information by uri + if uri: + result = self.http_get(self.url + 'core/units/' + + quote_plus(uri), headers={'Authorization':self.token}) + if result == 404: + raise Exception("Unit not found") + return result + + # Get list of units based on filtering criteria + url = self.url + 'core/units' + query = {} + + if name is not None: + query['name'] = name + if order_by is not None: + query['order_by'] = order_by + if page is not None: + query['page'] = str(page) + if page_size is not None: + query['page_size'] = str(page_size) + else: + query['page_size'] = str(DEFAULT_PAGE_SIZE) + if sharedResourceInstance is not None: + query['sharedResourceInstance'] = sharedResourceInstance + + if query: + query_string = '&'.join(f'{key}={quote_plus(value)}' for key, value in query.items()) + url += '?' + query_string + + try: + response = self.http_get(url, headers={'Authorization':self.token}) + if response == 404: + raise Exception("Empty result") + return response + except Exception as e: + return str(e) + + + def get_provenance_api(self, uri=None, name=None, description=None, activity=None, activity_type=None, agent=None, + agent_type=None, order_by=None, page=None, page_size=None): + """ + Retrieve specific provenance information by URI or list provenances based on filtering criteria. + + :param uri: (str) URI of the specific provenance to retrieve + :param name: (str) Filter provenances by name + :param description: (str) Filter provenances by description + :param activity: (str) Filter provenances by activity + :param activity_type: (str) Filter provenances by activity type + :param agent: (str) Filter provenances by agent + :param agent_type: (str) Filter provenances by agent type + :param order_by: (array[str]) Order the provenances by a specific field + :param page: (int) Page number for pagination + :param page_size: (int) Page size for pagination :return: - (list of dict) plants information + (dict or str) Provenance information or an error message + :raises: + Exception: if the provenance is not found (HTTP 404) or if the result is empty """ - if isinstance(plant_uri, six.string_types): - return self.get_all_data('plants/' + quote(plant_uri), - sessionId=session_id, - experimentURI=experiment_uri) + # Get specific provenance information by uri + if uri: + result = self.http_get(self.url + 'core/provenances/' + + quote_plus(uri), headers={'Authorization':self.token}) + if result == 404: + raise Exception("Provenance not found") + return result + + # Get list of provenances based on filtering criteria + url = self.url + 'core/provenances' + query = {} + + if name is not None: + query['name'] = name + if description is not None: + query['description'] = description + if activity is not None: + query['activity'] = activity + if activity_type is not None: + query['activity_type'] = activity_type + if agent is not None: + query['agent'] = agent + if agent_type is not None: + query['agent_type'] = agent_type + if order_by is not None: + query['order_by'] = order_by + if page is not None: + query['page'] = str(page) + if page_size is not None: + query['page_size'] = str(page_size) else: - return self.get_all_data('plants', timeout=60., - sessionId=session_id, - experimentURI=experiment_uri, - plantAlias=plant_alias, - germplasmsURI=germplasms_uri) - - def ws_plant_moves(self, session_id, experiment_uri, plant_uri, - start_date=None, - end_date=None): - """ Get plant moves data during an experimentation - See http://147.100.202.17/m3p/api-docs/ for exact documentation - - :param session_id: (str) token got from ws_token() - :param experiment_uri: (str) an experiment URI - :param plant_uri: (str) plant URI to get moves data - :param start_date: (str) retrieve move(s) which begin after or equals to this date - ( Format: YYYY-MM-DD or YYYY-MM-DD HH:MM:SS or YYYY-MM-DD HH:MM:SSZZ (ZZ = +01:00) ) - :param end_date: (str) retrieve move(s) which end before to this date - ( Format: YYYY-MM-DD or YYYY-MM-DD HH:MM:SS or YYYY-MM-DD HH:MM:SSZZ (ZZ = +01:00) ) + query['page_size'] = str(DEFAULT_PAGE_SIZE) + + if query: + query_string = '&'.join(f'{key}={quote_plus(value)}' for key, value in query.items()) + url += '?' + query_string + + try: + response = self.http_get(url, headers={'Authorization':self.token}) + if response == 404: + raise Exception("Empty result") + return response + except Exception as e: + return str(e) + + + def get_datafile_api(self, uri=None, rdf_type=None, start_date=None, end_date=None, timezone=None, experiments=None, + targets=None, devices=None, provenances=None, metadata=None, order_by=None, page=None, page_size=None): + """ + Retrieve specific datafile information by URI or list datafiles based on filtering criteria. + + :param uri: (str) URI of the specific datafile to retrieve + :param rdf_type: (str) Filter datafiles by RDF type + :param start_date: (str) Filter datafiles by start date + :param end_date: (str) Filter datafiles by end date + :param timezone: (str) Filter datafiles by timezone + :param experiments: (array[str]) Filter datafiles by experiments + :param targets: (array[str]) Filter datafiles by targets + :param devices: (array[str]) Filter datafiles by devices + :param provenances: (array[str]) Filter datafiles by provenances + :param metadata: (str) Filter datafiles by metadata + :param order_by: (array[str]) Order the datafiles by a specific field + :param page: (int) Page number for pagination + :param page_size: (int) Page size for pagination :return: - (list of dict) plant moves data - """ - return self.get_all_data('plants/' + quote( - plant_uri) + '/moves', - timeout=20., - sessionId=session_id, - experimentURI=experiment_uri, - startDate=start_date, endDate=end_date) - - def ws_watering(self, session_id, experiment_uri, date=None, provider=None, - variables_name=None, plant_uri=None): - """ Get watering data for a specific experiment - See http://147.100.202.17/m3p/api-docs/ for exact documentation - - :param session_id: (str) token got from ws_token() - :param experiment_uri: (str) an experiment URI - :param date: (str) retrieve watering data which been produced a particular day. Format :yyyy-MM-dd - :param provider: (str) origin of the data (useful ??) - :param variables_name: (str or list of str) name of one or several watering variables - might be one of ['weightBefore', 'weightAfter', 'weightAmount'] - :param plant_uri: (str) plant URI to get only values specified plant + (dict or str) Datafile information or an error message + :raises: + Exception: if the datafile is not found (HTTP 404) or if the result is empty + """ + # Get specific datafile information by uri + # Doesn't work + # if uri: + # result = self.http_get(self.url + 'core/datafiles/' + # + quote_plus(uri), headers={'Authorization':self.token}) + # if result == 404: + # raise Exception("Datafile not found") + # return result + + if uri: + result = self.http_get(self.url + 'core/datafiles/' + + quote_plus(uri) + '/description', headers={'Authorization':self.token}) + if result == 404: + raise Exception("Datafile not found") + return result + + # Get list of datafiles based on filtering criteria + url = self.url + 'core/datafiles' + query = {} + + if rdf_type is not None: + query['rdf_type'] = rdf_type + if start_date is not None: + query['start_date'] = start_date + if end_date is not None: + query['end_date'] = end_date + if timezone is not None: + query['timezone'] = timezone + if experiments is not None: + query['experiments'] = experiments + if targets is not None: + query['targets'] = targets + if devices is not None: + query['devices'] = devices + if provenances is not None: + query['provenances'] = provenances + if metadata is not None: + query['metadata'] = metadata + if order_by is not None: + query['order_by'] = order_by + if page is not None: + query['page'] = str(page) + if page_size is not None: + query['page_size'] = str(page_size) + else: + query['page_size'] = str(DEFAULT_PAGE_SIZE) + + if query: + query_string = '&'.join(f'{key}={quote_plus(value)}' for key, value in query.items()) + url += '?' + query_string + + try: + response = self.http_get(url, headers={'Authorization':self.token}) + if response == 404: + raise Exception("Empty result") + return response + except Exception as e: + return str(e) + + + def get_event_api(self, uri=None, details=False, rdf_type=None, start=None, end=None, target=None, description=None, + order_by=None, page=None, page_size=None): + """ + Retrieve specific event information by URI or list events based on filtering criteria. + + :param uri: (str) URI of the specific event to retrieve + :param details: (bool) Flag indicating whether to retrieve detailed information for the event + :param rdf_type: (str) Filter events by RDF type + :param start: (str) Filter events by start date/time + :param end: (str) Filter events by end date/time + :param target: (str) Filter events by target + :param description: (str) Filter events by description + :param order_by: (str) Order the events by a specific field + :param page: (int) Page number for pagination + :param page_size: (int) Page size for pagination :return: - (list of dict) watering data for a specific experiment - """ - if isinstance(variables_name, list): - variables_name = ','.join(variables_name) - if isinstance(plant_uri, six.string_types): - return self.get_all_data('plants/' + quote( - plant_uri) + '/watering', timeout=30., - sessionId=session_id, - experimentURI=experiment_uri, date=date, - provider=provider, - variablesName=variables_name) + (dict or str) Event information or an error message + :raises: + Exception: if the event is not found (HTTP 404) or if the result is empty + """ + # Get specific event information by uri + if uri: + if details == True: + result = self.http_get(self.url + 'core/events/' + + quote_plus(uri) + '/details', headers={'Authorization':self.token}) + else: + result = self.http_get(self.url + 'core/events/' + + quote_plus(uri), headers={'Authorization':self.token}) + if result == 404: + raise Exception("Event not found") + return result + + # Get list of events based on filtering criteria + url = self.url + 'core/events' + query = {} + + if rdf_type is not None: + query['rdf_type'] = rdf_type + if start is not None: + query['start'] = start + if end is not None: + query['end'] = end + if target is not None: + query['target'] = target + if description is not None: + query['description'] = description + if order_by is not None: + query['order_by'] = order_by + if page is not None: + query['page'] = str(page) + if page_size is not None: + query['page_size'] = str(page_size) else: - return self.get_all_data('watering', sessionId=session_id, - experimentURI=experiment_uri, date=date, - provider=provider, - variablesName=variables_name) - - def ws_images_analysis(self, session_id, experiment_uri, date=None, - provider=None, - label_view=None, variables_name=None, - plant_uri=None): - """ Get images analysis data for a specific experiment - See http://147.100.202.17/m3p/api-docs/ for exact documentation - - :param session_id: (str) token got from ws_token() - :param experiment_uri: (str) an experiment URI - :param date: (str) retrieve phenotypes data from images which have been took at a specific day . Format :yyyy-MM-dd - :param provider: (str) origin of the data - :param label_view: (str) label view, something like side0, side30, ..., side330, top0 - :param variables_name: (str or list of str) name of one or several weighing variables - See ws_variables(session_id, experiment_uri, category='imagery') for exact list - :param plant_uri: (str) plant URI to get only values specified plant + query['page_size'] = str(DEFAULT_PAGE_SIZE) + + if query: + query_string = '&'.join(f'{key}={quote_plus(value)}' for key, value in query.items()) + url += '?' + query_string + + try: + response = self.http_get(url, headers={'Authorization':self.token}) + if response == 404: + raise Exception("Empty result") + return response + except Exception as e: + return str(e) + + + def get_data_api(self, uri=None, start_date=None, end_date=None, timezone=None, experiments=None, targets=None, variables=None, + devices=None, min_confidence=None, max_confidence=None, provenances=None, metadata=None, operators=None, + order_by=None, page=None, page_size=None): + """ + Retrieve specific data information by URI or list data based on filtering criteria. + + :param uri: (str) URI of the specific data to retrieve + :param start_date: (str) Filter data by start date/time (e.g., '2023-01-01T00:00:00Z') + :param end_date: (str) Filter data by end date/time (e.g., '2023-12-31T23:59:59Z') + :param timezone: (str) Filter data by timezone (e.g., 'UTC', 'Europe/Paris') + :param experiments: (array[str]) Filter data by experiments + :param targets: (array[str]) Filter data by targets + :param variables: (array[str]) Filter data by variables + :param devices: (array[str]) Filter data by devices + :param min_confidence: (float) Filter data by minimum confidence level + :param max_confidence: (float) Filter data by maximum confidence level + :param provenances: (array[str]) Filter data by provenances + :param metadata: (str) Filter data by metadata + :param operators: (array[str]) Filter data by operators + :param order_by: (array[str]) Order the data by specific fields + :param page: (int) Page number for pagination + :param page_size: (int) Page size for pagination (default is DEFAULT_PAGE_SIZE) :return: - (list of dict) images analysis data for a specific experiment - """ - if isinstance(variables_name, list): - variables_name = ','.join(variables_name) - if isinstance(plant_uri, six.string_types): - return self.get_all_data('plants/' + quote( - plant_uri) + '/phenotypes', timeout=30., - sessionId=session_id, - experimentURI=experiment_uri, date=date, - provider=provider, - labelView=label_view, - variablesName=variables_name) + (dict or str) Data information or an error message + :raises: + Exception: if the data is not found (HTTP 404) or if the result is empty + """ + # Get specific data information by uri + if uri: + result = self.http_get(self.url + 'core/data/' + + quote_plus(uri), headers={'Authorization':self.token}) + if result == 404: + raise Exception("Data not found") + return result + + # Get list of data based on filtering criteria + url = self.url + 'core/data' + query = {} + + if start_date is not None: + query['start_date'] = start_date + if end_date is not None: + query['end_date'] = end_date + if timezone is not None: + query['timezone'] = timezone + if experiments is not None: + query['experiments'] = experiments + if targets is not None: + query['targets'] = targets + if variables is not None: + query['variables'] = variables + if devices is not None: + query['devices'] = devices + if min_confidence is not None: + query['min_confidence'] = str(min_confidence) + if max_confidence is not None: + query['max_confidence'] = str(max_confidence) + if provenances is not None: + query['provenances'] = provenances + if metadata is not None: + query['metadata'] = metadata + if operators is not None: + query['operators'] = operators + if order_by is not None: + query['order_by'] = order_by + if page is not None: + query['page'] = str(page) + if page_size is not None: + query['page_size'] = str(page_size) else: - return self.get_all_data('imagesAnalysis', timeout=30., - sessionId=session_id, - experimentURI=experiment_uri, - date=date, provider=provider, - labelView=label_view, - variablesName=variables_name) + query['page_size'] = str(DEFAULT_PAGE_SIZE) + + if query: + query_string = '&'.join(f'{key}={quote_plus(value)}' for key, value in query.items()) + url += '?' + query_string + + try: + response = self.http_get(url, headers={'Authorization':self.token}) + if response == 404: + raise Exception("Empty result") + return response + except Exception as e: + return str(e) \ No newline at end of file diff --git a/src/agroservices/phis/phis_interface.py b/src/agroservices/phis/phis_interface.py new file mode 100644 index 0000000..3539351 --- /dev/null +++ b/src/agroservices/phis/phis_interface.py @@ -0,0 +1,536 @@ + + + +from agroservices.phis.phis import Phis +PAGE_SIZE_ALL = 10000 + +class Phis_UI(Phis): + def __init__(self): + super().__init__() + + + def get_device(self, device_name=None, uri=None, rdf_type=None, include_subtypes=None, name=None, variable=None, year=None, + existence_date=None, facility=None, brand=None, model=None, serial_number=None, metadata=None, order_by=None, + page=None, page_size=PAGE_SIZE_ALL): + + # Return details by URI + if uri: + result = self.get_device_api(uri=uri) + return result + + result = self.get_device_api(rdf_type=rdf_type, include_subtypes=include_subtypes, name=name, variable=variable, year=year, + existence_date=existence_date, facility=facility, brand=brand, model=model, + serial_number=serial_number, metadata=metadata, order_by=order_by, page=page, page_size=page_size) + + # If no device name set, return list of all devices name + if device_name == None and uri == None: + return [item['name'] for item in result['result']] + + # Else return details by name + for item in result['result']: + if item['name'] == device_name: + return item + return None + + + def get_scientific_object(self, scientific_object_name=None, uri=None, experiment=None, rdf_types=None, name=None, + parent=None, germplasms=None, factor_levels=None, facility=None, variables=None, devices=None, + existence_date=None, creation_date=None, criteria_on_data=None, order_by=None, page=None, + page_size=PAGE_SIZE_ALL): + + # Return details by URI + if uri: + result = self.get_scientific_object_api(uri=uri) + return result + + result = self.get_scientific_object_api(uri=uri, experiment=experiment, rdf_types=rdf_types, name=name, parent=parent, + germplasms=germplasms, factor_levels=factor_levels, facility=facility, + variables=variables, devices=devices, existence_date=existence_date, + creation_date=creation_date, criteria_on_data=criteria_on_data, order_by=order_by, + page=page, page_size=page_size) + # If no scientific object set, return list of all scientific objects name + if scientific_object_name == None: + return [item['name'] for item in result['result']] + + # Else return details of selected scientific object + for item in result['result']: + if item['name'] == scientific_object_name: + return item + return None + + + def get_experiment(self, experiment_name=None, uri=None, name=None, year=None, is_ended=None, species=None, factors=None, + projects=None, is_public=None, facilities=None, order_by=None, page=None, page_size=PAGE_SIZE_ALL): + + # Return details by URI + if uri: + result = self.get_experiment_api(uri=uri) + return result + + result = self.get_experiment_api(uri=uri, name=name, year=year, is_ended=is_ended, species=species, factors=factors, + projects=projects, is_public=is_public, facilities=facilities, order_by=order_by, page=page, + page_size=page_size) + # If no experiment name set, return list of all experiments name + if experiment_name == None: + return [item['name'] for item in result['result']] + + # Else return details of selected experiment + for item in result['result']: + if item['name'] == experiment_name: + return item + return None + + + def get_variable(self, variable_name=None, uri=None, name=None, entity=None, entity_of_interest=None, characteristic=None, + method=None, unit=None, group_of_variables=None, not_included_in_group_of_variables=None, data_type=None, + time_interval=None, species=None, withAssociatedData=None, experiments=None, scientific_objects=None, + devices=None, order_by=None, page=None, page_size=PAGE_SIZE_ALL, sharedResourceInstance=None): + + # Return details by URI + if uri: + result = self.get_variable_api(uri=uri) + return result + + result = self.get_variable_api(uri=uri, name=name, entity=entity, entity_of_interest=entity_of_interest, + characteristic=characteristic, method=method, unit=unit, group_of_variables=group_of_variables, + not_included_in_group_of_variables=not_included_in_group_of_variables, data_type=data_type, + time_interval=time_interval, species=species, withAssociatedData=withAssociatedData, + experiments=experiments, scientific_objects=scientific_objects, devices=devices, + order_by=order_by, page=page, page_size=page_size, sharedResourceInstance=sharedResourceInstance) + # If no variable name set, return list of all variables name + if variable_name == None: + return [item['name'] for item in result['result']] + + # Else return details of selected variable + for item in result['result']: + if item['name'] == variable_name: + return item + return None + + + def get_project(self, project_name=None, uri=None, name=None, year=None, keyword=None, financial_funding=None, order_by=None, + page=None, page_size=PAGE_SIZE_ALL): + + # Return details by URI + if uri: + result = self.get_project_api(uri=uri) + return result + + result = self.get_project_api(uri=uri, name=name, year=year, keyword=keyword, financial_funding=financial_funding, + order_by=order_by, page=page, page_size=page_size) + # If no project name set, return list of all projects name + if project_name == None: + return [item['name'] for item in result['result']] + + # Else return details of selected project + for item in result['result']: + if item['name'] == project_name: + return item + return None + + + def get_facility(self, facility_name=None, uri=None, pattern=None, organizations=None, order_by=None, page=None, + page_size=PAGE_SIZE_ALL): + + # Return details by URI + if uri: + result = self.get_facility_api(uri=uri) + return result + + result = self.get_facility_api(uri=uri, pattern=pattern, organizations=organizations, order_by=order_by, page=page, + page_size=page_size) + # If no facility name set, return list of all facilities name + if facility_name == None: + return [item['name'] for item in result['result']] + + # Else return details of selected facility + for item in result['result']: + if item['name'] == facility_name: + return item + return None + + + def get_germplasm(self, germplasm_name=None, uri=None, rdf_type=None, name=None, code=None, production_year=None, + species=None, variety=None, accession=None, group_of_germplasm=None, institute=None, experiment=None, + parent_germplasms=None, parent_germplasms_m=None, parent_germplasms_f=None, metadata=None, order_by=None, + page=None, page_size=PAGE_SIZE_ALL): + + # Return details by URI + if uri: + result = self.get_germplasm_api(uri=uri) + return result + + result = self.get_germplasm_api(uri=uri, rdf_type=rdf_type, name=name, code=code, production_year=production_year, + species=species, variety=variety, accession=accession, group_of_germplasm=group_of_germplasm, + institute=institute, experiment=experiment, parent_germplasms=parent_germplasms, + parent_germplasms_m=parent_germplasms_m, parent_germplasms_f=parent_germplasms_f, + metadata=metadata, order_by=order_by, page=page, page_size=page_size) + # If no germplasm name set, return list of all germplasms name + if germplasm_name == None: + return [item['name'] for item in result['result']] + + # Else return details of selected germplasm + for item in result['result']: + if item['name'] == germplasm_name: + return item + return None + + + def get_annotation(self, annotation_name=None, uri=None, description=None, target=None, motivation=None, author=None, + order_by=None, page=None, page_size=PAGE_SIZE_ALL): + + # Return details by URI + if uri: + result = self.get_annotation_api(uri=uri) + return result + + result = self.get_annotation_api(uri=uri, description=description, target=target, motivation=motivation, author=author, + order_by=order_by, page=page, page_size=page_size) + # If no annotation name set, return list of all annotations name + if annotation_name == None: + return [item['name'] for item in result['result']] + + # Else return details of selected annotation + for item in result['result']: + if item['name'] == annotation_name: + return item + return None + + + def get_document(self, document_title=None, uri=None, rdf_type=None, title=None, date=None, targets=None, authors=None, + keyword=None, multiple=None, deprecated=None, order_by=None, page=None, page_size=PAGE_SIZE_ALL): + + # Return details by URI + if uri: + result = self.get_document_api(uri=uri) + return result + + result = self.get_document_api(uri=uri, rdf_type=rdf_type, title=title, date=date, targets=targets, authors=authors, + keyword=keyword, multiple=multiple, deprecated=deprecated, order_by=order_by, page=page, + page_size=page_size) + # If no document name set, return list of all documents name + if document_title == None: + return [item['title'] for item in result['result']] + + # Else return details of selected document + for item in result['result']: + if item['title'] == document_title: + return item + return None + + + def get_factor(self, factor_name=None, uri=None, name=None, description=None, category=None, experiment=None, + order_by=None, page=None, page_size=PAGE_SIZE_ALL): + + # Return details by URI + if uri: + result = self.get_factor_api(uri=uri) + return result + + result = self.get_factor_api(uri=uri, name=name, description=description, category=category, experiment=experiment, + order_by=order_by, page=page, page_size=page_size) + # If no factor name set, return list of all factors name + if factor_name == None: + return [item['name'] for item in result['result']] + + # Else return details of selected factor + for item in result['result']: + if item['name'] == factor_name: + return item + return None + + + def get_organization(self, organization_name=None, uri=None, pattern=None, organisation_uris=None, page=None, + page_size=PAGE_SIZE_ALL): + + # Return details by URI + if uri: + result = self.get_organization_api(uri=uri) + return result + + result = self.get_organization_api(uri=uri, pattern=pattern, organisation_uris=organisation_uris, page=page, + page_size=page_size) + # If no organization name set, return list of all organizations name + if organization_name is None: + org_dict = {} + for item in result['result']: + rdf_type_name = item['rdf_type_name'] + if rdf_type_name not in org_dict: + org_dict[rdf_type_name] = [] + org_dict[rdf_type_name].append(item['name']) + + sorted_org_list = [] + for rdf_type_name in sorted(org_dict.keys()): + sorted_org_list.append(f"{rdf_type_name.capitalize()} organizations:") + sorted_org_list.extend(org_dict[rdf_type_name]) + sorted_org_list.append("") # Adds an empty line for separation + + return "\n".join(sorted_org_list) + + + # Else return details of selected organization + for item in result['result']: + if item['name'] == organization_name: + return item + return None + + + def get_site(self, site_name=None, uri=None, pattern=None, organizations=None, order_by=None, page=None, + page_size=PAGE_SIZE_ALL): + + # Return details by URI + if uri: + result = self.get_site_api(uri=uri) + return result + + result = self.get_site_api(uri=uri, pattern=pattern, organizations=organizations, order_by=order_by, page=page, + page_size=page_size) + # If no site name set, return list of all sites name + if site_name == None: + return [item['name'] for item in result['result']] + + # Else return details of selected site + for item in result['result']: + if item['name'] == site_name: + return item + return None + + + def get_species(self, species_name=None, sharedResourceInstance=None): + result = self.get_species_api(sharedResourceInstance=sharedResourceInstance) + # If no species name set, return list of all species name + if species_name == None: + return [item['name'] for item in result['result']] + + # Else return details of selected species + for item in result['result']: + if item['name'] == species_name: + return item + return None + + + def get_characteristic(self, characteristic_name=None, uri=None, name=None, order_by=None, page=None, + page_size=PAGE_SIZE_ALL, sharedResourceInstance=None): + + # Return details by URI + if uri: + result = self.get_characteristic_api(uri=uri) + return result + + result = self.get_characteristic_api(uri=uri, name=name, order_by=order_by, page=page, page_size=page_size, + sharedResourceInstance=sharedResourceInstance) + # If no characteristic name set, return list of all characteristics name + if characteristic_name == None: + return [item['name'] for item in result['result']] + + # Else return details of selected characteristic + for item in result['result']: + if item['name'] == characteristic_name: + return item + return None + + + def get_entity(self, entity_name=None, uri=None, name=None, order_by=None, page=None, page_size=PAGE_SIZE_ALL, + sharedResourceInstance=None): + + # Return details by URI + if uri: + result = self.get_entity_api(uri=uri) + return result + + result = self.get_entity_api(uri=uri, name=name, order_by=order_by, page=page, page_size=page_size, + sharedResourceInstance=sharedResourceInstance) + # If no entity name set, return list of all entities name + if entity_name == None: + return [item['name'] for item in result['result']] + + # Else return details of selected entity + for item in result['result']: + if item['name'] == entity_name: + return item + return None + + + def get_entity_of_interest(self, entity_of_interest_name=None, uri=None, name=None, order_by=None, page=None, + page_size=PAGE_SIZE_ALL, sharedResourceInstance=None): + + # Return details by URI + if uri: + result = self.get_entity_of_interest_api(uri=uri) + return result + + result = self.get_entity_of_interest_api(uri=uri, name=name, order_by=order_by, page=page, page_size=page_size, + sharedResourceInstance=sharedResourceInstance) + # If no entity of interest name set, return list of all entities of interest name + if entity_of_interest_name == None: + return [item['name'] for item in result['result']] + + # Else return details of selected entity of interest + for item in result['result']: + if item['name'] == entity_of_interest_name: + return item + return None + + + def get_method(self, method_name=None, uri=None, name=None, order_by=None, page=None, page_size=PAGE_SIZE_ALL, + sharedResourceInstance=None): + + # Return details by URI + if uri: + result = self.get_method_api(uri=uri) + return result + + result = self.get_method_api(uri=uri, name=name, order_by=order_by, page=page, page_size=page_size, + sharedResourceInstance=sharedResourceInstance) + # If no method name set, return list of all methods name + if method_name == None: + return [item['name'] for item in result['result']] + + # Else return details of selected method + for item in result['result']: + if item['name'] == method_name: + return item + return None + + + def get_unit(self, unit_name=None, uri=None, name=None, order_by=None, page=None, page_size=PAGE_SIZE_ALL, + sharedResourceInstance=None): + + # Return details by URI + if uri: + result = self.get_unit_api(uri=uri) + return result + + result = self.get_unit_api(uri=uri, name=name, order_by=order_by, page=page, page_size=page_size, + sharedResourceInstance=sharedResourceInstance) + # If no unit name set, return list of all units name + if unit_name == None: + return [item['name'] for item in result['result']] + + # Else return details of selected unit + for item in result['result']: + if item['name'] == unit_name: + return item + return None + + + def get_provenance(self, provenance_name=None, uri=None, name=None, description=None, activity=None, activity_type=None, + agent=None, agent_type=None, order_by=None, page=None, page_size=PAGE_SIZE_ALL): + + # Return details by URI + if uri: + result = self.get_provenance_api(uri=uri) + return result + + result = self.get_provenance_api(uri=uri, name=name, description=description, activity=activity, activity_type=activity_type, + agent=agent, agent_type=agent_type, order_by=order_by, page=page, page_size=page_size) + # If no provenances name set, return list of all provenances name + if provenance_name == None: + return [item['name'] for item in result['result']] + + # Else return details of selected provenance + for item in result['result']: + if item['name'] == provenance_name: + return item + return None + + + def get_datafile(self, datafile_name=None, uri=None, rdf_type=None, start_date=None, end_date=None, timezone=None, + experiments=None, targets=None, devices=None, provenances=None, metadata=None, order_by=None, page=None, + page_size=PAGE_SIZE_ALL): + + # Return details by URI + if uri: + result = self.get_datafile_api(uri=uri) + return result + + result = self.get_datafile_api(uri=uri, rdf_type=rdf_type, start_date=start_date, end_date=end_date, timezone=timezone, + experiments=experiments, targets=targets, devices=devices, provenances=provenances, + metadata=metadata, order_by=order_by, page=page, page_size=page_size) + # If no datafile name set, return list of all datafiles name + if datafile_name == None: + return [item['filename'] for item in result['result']] + + # Else return details of selected datafile + for item in result['result']: + if item['filename'] == datafile_name: + return item + return None + + + def get_event(self, event_name=None, uri=None, details=False, rdf_type=None, start=None, end=None, target=None, + description=None, order_by=None, page=None, page_size=PAGE_SIZE_ALL, max_results_per_type=None): + + # Return details by URI + if uri: + result = self.get_event_api(uri=uri) + return result + + result = self.get_event_api(uri=uri, details=details, rdf_type=rdf_type, start=start, end=end, target=target, + description=description, order_by=order_by, page=page, page_size=page_size) + # If no event name set, return list of all events name sorted by event type + if event_name is None: + event_dict = {} + for item in result['result']: + rdf_type_name = item['rdf_type_name'] + if rdf_type_name not in event_dict: + event_dict[rdf_type_name] = [] + event_dict[rdf_type_name].append(item) + + sorted_event_list = [] + for rdf_type_name in sorted(event_dict.keys()): + sorted_event_list.append(f"{rdf_type_name.capitalize()} events:") + count = 0 + remaining_events = 0 # Counter for remaining events to be displayed + for event in event_dict[rdf_type_name]: + if max_results_per_type is not None and count >= max_results_per_type: + remaining_events += 1 + continue + sorted_event_list.append(f'uri: {event["uri"]}') + if event['description'] is not None: + sorted_event_list.append(f'description: {event["description"]}') + for d in event["targets"]: + device_name = self.get_device(uri=d)['result']['name'] + sorted_event_list.append(f'target: {device_name}') + sorted_event_list.append("") + count += 1 + + if remaining_events > 0: + sorted_event_list.append(f"... ({remaining_events} more events)") + + sorted_event_list.append("") # Adds an empty line for separation + + result_str = "\n".join(sorted_event_list) + return result_str + + # Else return details of selected event + for item in result['result']: + if item['name'] == event_name: + return item + return None + + def get_data(self, data_date=None, uri=None, start_date=None, end_date=None, timezone=None, experiments=None, targets=None, + variables=None, devices=None, min_confidence=None, max_confidence=None, provenances=None, metadata=None, + operators=None, order_by=None, page=None, page_size=PAGE_SIZE_ALL): + + # Return details by URI + if uri: + result = self.get_data_api(uri=uri) + return result + + result = self.get_data_api(uri=uri, start_date=start_date, end_date=end_date, timezone=timezone, experiments=experiments, + targets=targets, variables=variables, devices=devices, min_confidence=min_confidence, + max_confidence=max_confidence, provenances=provenances, metadata=metadata, + operators=operators, order_by=order_by, page=page, page_size=page_size) + # If no data name set, return list of all datas name + if data_date == None: + return [item['value'] for item in result['result']] + + # Else return details of selected data + for item in result['result']: + if item['date'] == data_date: + return item + return None + + def get_system_info(self): + return self.get_system_info_api() diff --git a/test/test_phis.py b/test/test_phis.py index 38e314b..ef3897f 100644 --- a/test/test_phis.py +++ b/test/test_phis.py @@ -13,27 +13,398 @@ def test_url(): assert True -def test_token(): +def test_authenticate(): phis = Phis() - json = '{ \ - "identifier": "phenoarch@lepse.inra.fr",\ - "password": "phenoarch"\ - }' - response, _ = phis.post_json('security/authenticate', json) - token = response.json()['result']['token'] - assert len(token) > 1 + # Connexion test + token, status_code = phis.authenticate() + assert status_code == 200 + + # Wrong password test + try: + token, status_code = phis.authenticate(password='wrong') + except ValueError as e: + assert str(e) == "User does not exists, is disabled or password is invalid" + + # Wrong identifier test + try: + token, status_code = phis.authenticate(identifier='wrong') + except ValueError as e: + assert str(e) == "User does not exists, is disabled or password is invalid" + + +def test_get_experiment(): + phis = Phis() + + # Search test + data = phis.get_experiment() + assert data['result'] != [], "Request failed" + + # Filtered search test + data = phis.get_experiment(year=2022, is_ended=True, is_public=True) + assert data['result'] != [], "Request failed" + + # Filtered search test without results + data = phis.get_experiment(year=200) + assert data['result'] == [], "Expected no results, got data: " + data['result'] + + # Test with a valid URI + try: + data = phis.get_experiment(uri='m3p:id/experiment/g2was2022') + except Exception as err: + assert False, "Unexpected error: " + str(err) + + # Test with an invalid URI + try: + data = phis.get_experiment(uri='m3p:id/experiment/wrong') + except Exception as err: + assert True # Exception is expected + else: + assert False, "Expected an exception, but none was raised" + + +def test_get_variable(): + phis = Phis() + + # Search test + data = phis.get_variable() + if data['metadata']['pagination']['totalCount'] != 0: + assert data['result'] != [], "Request failed" + + # Test with a valid URI + try: + data = phis.get_variable(uri='http://phenome.inrae.fr/m3p/id/variable/ev000020') + except Exception as err: + assert False, "Unexpected error: " + str(err) + + # Test with an invalid URI + try: + data = phis.get_variable(uri='http://phenome.inrae.fr/m3p/id/variable/wrong') + except Exception as err: + assert True # Exception is expected + else: + assert False, "Expected an exception, but none was raised" + + +def test_get_project(): + phis = Phis() + + # Search test + data = phis.get_project() + if data['metadata']['pagination']['totalCount'] != 0: + assert data['result'] != [], "Request failed" + + # Test with a valid URI + try: + data = phis.get_project(uri='m3p:id/project/vitsec') + except Exception as err: + assert False, "Unexpected error: " + str(err) + + # Test with an invalid URI + try: + data = phis.get_project(uri='m3p:id/project/wrong') + except Exception as err: + assert True # Exception is expected + else: + assert False, "Expected an exception, but none was raised" + + +def test_get_facility(): + phis = Phis() + + # Search test + data = phis.get_facility() + if data['metadata']['pagination']['totalCount'] != 0: + assert data['result'] != [], "Request failed" + + # Test with a valid URI + try: + data = phis.get_facility(uri='m3p:id/organization/facility.phenoarch') + except Exception as err: + assert False, "Unexpected error: " + str(err) + + # Test with an invalid URI + try: + data = phis.get_facility(uri='m3p:id/organization/wrong') + except Exception as err: + assert True # Exception is expected + else: + assert False, "Expected an exception, but none was raised" + + +def test_get_germplasm(): + phis = Phis() + + # Search test + data = phis.get_germplasm() + if data['metadata']['pagination']['totalCount'] != 0: + assert data['result'] != [], "Request failed" + + # Test with a valid URI + try: + data = phis.get_germplasm(uri='http://aims.fao.org/aos/agrovoc/c_1066') + except Exception as err: + assert False, "Unexpected error: " + str(err) + + # Test with an invalid URI + try: + data = phis.get_germplasm(uri='http://aims.fao.org/aos/agrovoc/wrong') + except Exception as err: + assert True # Exception is expected + else: + assert False, "Expected an exception, but none was raised" + + +def test_get_device(): + phis = Phis() + + # Search test + data = phis.get_device() + if data['metadata']['pagination']['totalCount'] != 0: + assert data['result'] != [], "Request failed" + + # Test with a valid URI + try: + data = phis.get_device(uri='http://www.phenome-fppn.fr/m3p/ec1/2016/sa1600064') + except Exception as err: + assert False, "Unexpected error: " + str(err) + + # Test with an invalid URI + try: + data = phis.get_device(uri='http://www.phenome-fppn.fr/m3p/ec1/2016/wrong') + except Exception as err: + assert True # Exception is expected + else: + assert False, "Expected an exception, but none was raised" + + +def test_get_annotation(): + phis = Phis() + + # Search test + data = phis.get_annotation() + if data['metadata']['pagination']['totalCount'] != 0: + assert data['result'] != [], "Request failed" + + # Test with a valid URI + # No URIs + # try: + # data = phis.get_annotation(uri='') + # except Exception as err: + # assert False, "Unexpected error: " + str(err) + + +def test_get_document(): + phis = Phis() + + # Search test + data = phis.get_document() + if data['metadata']['pagination']['totalCount'] != 0: + assert data['result'] != [], "Request failed" + + # Test with a valid URI + try: + data = phis.get_document(uri='m3p:id/document/test_dataset') + except Exception as err: + assert False, "Unexpected error: " + str(err) + + +def test_get_factor(): + phis = Phis() + + # Search test + data = phis.get_factor() + if data['metadata']['pagination']['totalCount'] != 0: + assert data['result'] != [], "Request failed" + + # Test with a valid URI + # No URIs + # try: + # data = phis.get_factor(uri='') + # except Exception as err: + # assert False, "Unexpected error: " + str(err) + + +def test_get_organization(): + phis = Phis() + + # Search test + data = phis.get_organization() + if data['metadata']['pagination']['totalCount'] != 0: + assert data['result'] != [], "Request failed" + + # Test with a valid URI + try: + data = phis.get_organization(uri='m3p:id/organization/phenoarch') + except Exception as err: + assert False, "Unexpected error: " + str(err) + + +def test_get_site(): + phis = Phis() + + # Search test + data = phis.get_site() + if data['metadata']['pagination']['totalCount'] != 0: + assert data['result'] != [], "Request failed" + + # Test with a valid URI + # No URIs + # try: + # data = phis.get_site(uri='') + # except Exception as err: + # assert False, "Unexpected error: " + str(err) + + +def test_get_scientific_object(): + phis = Phis() + + # Search test + data = phis.get_scientific_object() + if data['metadata']['pagination']['totalCount'] != 0: + assert data['result'] != [], "Request failed" + + # Test with a valid URI + try: + data = phis.get_scientific_object(uri='m3p:id/scientific-object/za20/so-0001zm4531eppn7_lwd1eppn_rep_101_01arch2020-02-03') + except Exception as err: + assert False, "Unexpected error: " + str(err) + + +def test_get_species(): + phis = Phis() + + # Search test + data = phis.get_species() + if data['metadata']['pagination']['totalCount'] != 0: + assert data['result'] != [], "Request failed" + + +def test_get_system_info(): + phis = Phis() + + # Search test + data = phis.get_system_info() + if data['metadata']['pagination']['totalCount'] != 0: + assert data['result'] != [], "Request failed" -def test_ws_experiments(): +def test_get_characteristic(): phis = Phis() - json = '{ \ - "identifier": "phenoarch@lepse.inra.fr",\ - "password": "phenoarch"\ - }' - response, _ = phis.post_json('security/authenticate', json) - token = response.json()['result']['token'] - data = phis.ws_experiments(experiment_uri='m3p:id/experiment/g2was2022', - session_id=token) - print(data) \ No newline at end of file + # Search test + data = phis.get_characteristic() + if data['metadata']['pagination']['totalCount'] != 0: + assert data['result'] != [], "Request failed" + + # Test with a valid URI + try: + data = phis.get_characteristic(uri='http://phenome.inrae.fr/m3p/id/variable/characteristic.humidity') + except Exception as err: + assert False, "Unexpected error: " + str(err) + + +def test_get_entity(): + phis = Phis() + + # Search test + data = phis.get_entity() + if data['metadata']['pagination']['totalCount'] != 0: + assert data['result'] != [], "Request failed" + + # Test with a valid URI + try: + data = phis.get_entity(uri='http://phenome.inrae.fr/m3p/id/variable/entity.solar') + except Exception as err: + assert False, "Unexpected error: " + str(err) + + +def test_get_entity_of_interest(): + phis = Phis() + + # Search test + data = phis.get_entity_of_interest() + if data['metadata']['pagination']['totalCount'] != 0: + assert data['result'] != [], "Request failed" + + # Test with a valid URI + # No URIs + # try: + # data = phis.get_entity_of_interest(uri='') + # except Exception as err: + # assert False, "Unexpected error: " + err + + +def test_get_method(): + phis = Phis() + + # Search test + data = phis.get_method() + if data['metadata']['pagination']['totalCount'] != 0: + assert data['result'] != [], "Request failed" + + # Test with a valid URI + try: + data = phis.get_method(uri='http://phenome.inrae.fr/m3p/id/variable/method.measurement') + except Exception as err: + assert False, "Unexpected error: " + str(err) + + +def test_get_unit(): + phis = Phis() + + # Search test + data = phis.get_unit() + if data['metadata']['pagination']['totalCount'] != 0: + assert data['result'] != [], "Request failed" + + # Test with a valid URI + try: + data = phis.get_unit(uri='http://qudt.org/vocab/unit/J') + except Exception as err: + assert False, "Unexpected error: " + str(err) + + +def test_get_provenance(): + phis = Phis() + + # Search test + data = phis.get_provenance() + if data['metadata']['pagination']['totalCount'] != 0: + assert data['result'] != [], "Request failed" + + # Test with a valid URI + try: + data = phis.get_provenance(uri='http://www.phenome-fppn.fr/m3p/Prov_watering_WateringStation05_6l') + except Exception as err: + assert False, "Unexpected error: " + str(err) + + +def test_get_datafile(): + phis = Phis() + + # Search test + data = phis.get_datafile() + if data['metadata']['pagination']['totalCount'] != 0: + assert data['result'] != [], "Request failed" + + # Test with a valid URI + try: + data = phis.get_datafile(uri='m3p:id/file/1597964400.af46ac07f735ced228cf181aa85ebced') + except Exception as err: + assert False, "Unexpected error: " + str(err) + + +def test_get_event(): + phis = Phis() + + # Search test + data = phis.get_event() + if data['metadata']['pagination']['totalCount'] != 0: + assert data['result'] != [], "Request failed" + + # Test with a valid URI + try: + data = phis.get_event(uri='m3p:id/event/cb8b96ea-4d0b-4bc6-804f-e3cf2b56092e') + except Exception as err: + assert False, "Unexpected error: " + str(err) \ No newline at end of file