diff --git a/organization-people/README.md b/organization-people/README.md new file mode 100644 index 0000000..cb05695 --- /dev/null +++ b/organization-people/README.md @@ -0,0 +1,8 @@ +## organization-people + +A collection of Jupyter notebooks showing examples of using a persistent identifier for an organization (here ROR ID) as input for different APIs of PID providers or PID Graphs and retrieving all people (identified by an ORCID iD) connected to it. + +Currently available PID Graphs: +* [FREYA PID Graph](https://blog.datacite.org/powering-the-pid-graph/) [![Google Colab](https://badgen.net/badge/Launch/on%20Google%20Colab/blue?icon=terminal)](https://colab.research.google.com/github/Project-TAPIR/pidgraph-notebooks/blob/main/organization-people/freya_get_people_by_organization.ipynb) +* [OpenAlex](https://openalex.org/about)[![Google Colab](https://badgen.net/badge/Launch/on%20Google%20Colab/blue?icon=terminal)](https://colab.research.google.com/github/Project-TAPIR/pidgraph-notebooks/blob/main/organization-people/openalex_get_people_by_organization.ipynb) +* [ORCID](https://orcid.org/)[![Google Colab](https://badgen.net/badge/Launch/on%20Google%20Colab/blue?icon=terminal)](https://colab.research.google.com/github/Project-TAPIR/pidgraph-notebooks/blob/main/organization-people/orcid_get_people_by_organization.ipynb) diff --git a/organization-people/freya_get_people_by_organization.ipynb b/organization-people/freya_get_people_by_organization.ipynb new file mode 100644 index 0000000..09a9f02 --- /dev/null +++ b/organization-people/freya_get_people_by_organization.ipynb @@ -0,0 +1 @@ +{"nbformat":4,"nbformat_minor":0,"metadata":{"colab":{"name":"Kopie von Kopie von freya_get_people_by_organization.ipynb","provenance":[{"file_id":"https://github.com/Project-TAPIR/pidgraph-notebooks/blob/organization-people/organization-people/freya_get_people_by_organization.ipynb","timestamp":1643208926409}],"authorship_tag":"ABX9TyOPyixqZithrfY0TncA4o1K"},"kernelspec":{"name":"python3","display_name":"Python 3"},"language_info":{"name":"python"}},"cells":[{"cell_type":"markdown","source":["### Query the FREYA PID Graph for all people affiliated with an organization\n","\n","This notebook queries the [FREYA PID Graph](https://blog.datacite.org/powering-the-pid-graph/) via [Datacite's GraphQL API](https://api.datacite.org/graphql) to retrieve all people affiliated with an organization. It takes a ROR URL as input which is used to retrieve the according Grid and Ringgold ID of the organization and query the ORCID API with it [for affiliated people](https://info.orcid.org/faq/how-do-i-find-orcid-record-holders-at-my-institution/). From the resulting list of people we output the ORCID iDs."],"metadata":{"id":"etxiXTW668ZD"}},{"cell_type":"code","source":["# needed dependency to make HTTP calls\n","import requests\n","# dependencies for dealing with json\n","!pip install python-benedict\n","from benedict import benedict"],"metadata":{"id":"8Mk7-aYc7x3A"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":["The input for the query is a ROR URL."],"metadata":{"id":"J31_ejB6bWqd"}},{"cell_type":"code","source":["# input parameter for all further computations\n","example_ror=\"https://ror.org/021k10z87\""],"metadata":{"id":"UwYUsbnMbZnI","executionInfo":{"status":"ok","timestamp":1643208788232,"user_tz":-60,"elapsed":15,"user":{"displayName":"","photoUrl":"","userId":""}}},"execution_count":2,"outputs":[]},{"cell_type":"markdown","source":["We use it to query Datacite's GraphQL API for the organization's metadata and all people connected to it. Since the API uses pagination, we need to loop through all pages to get the complete result set.\n"],"metadata":{"id":"ba_A3Anpbl4P"}},{"cell_type":"code","source":["# Datacite's GraphQL endpoint for the FREYA PID Graph\n","DATACITE_GRAPHQL_API = \"https://api.datacite.org/graphql\"\n","\n","# Query to retrieve an organization and all its affiliated people\n","QUERY_ORGA2PEOPLE = \"\"\"query organization($ror :ID!, $after:String){\n","organization(id: $ror) {\n"," people(first: 1000, after: $after) {\n"," totalCount\n"," pageInfo {\n"," endCursor\n"," hasNextPage\n"," }\n","\n"," nodes {\n"," id\n"," name\n"," givenName\n"," }\n"," }\n"," }\n","}\"\"\"\n","\n","# query all people that are connected to given ROR\n","def download_data(ror):\n"," continue_paginating = True\n"," cursor=\"\"\n"," while continue_paginating:\n"," vars = {'ror': ror, 'after': cursor}\n"," response = requests.post(url=DATACITE_GRAPHQL_API,\n"," json={'query': QUERY_ORGA2PEOPLE, 'variables': vars},\n"," headers={'Content-Type': 'application/json'})\n"," result=response.json()\n","\n"," # check if next page exists and set cursor to next page\n"," continue_paginating = has_next_page(result)\n"," cursor = next_cursor(result)\n"," yield result\n","\n","# check if there is another page with results to query\n","def has_next_page(response_data):\n"," resp_dict = benedict.from_json(response_data)\n"," has_next_page = resp_dict.get(\"data.organization.people.pageInfo.hasNextPage\")\n"," return has_next_page\n","\n","# set cursor to next value\n","def next_cursor(response_data):\n"," resp_dict = benedict.from_json(response_data)\n"," cursor = resp_dict.get(\"data.organization.people.pageInfo.endCursor\")\n"," return cursor\n","\n","\n","#--- example execution\n","list_of_pages=download_data(example_ror)"],"metadata":{"id":"7FAu2l388OeD","executionInfo":{"status":"ok","timestamp":1643208819281,"user_tz":-60,"elapsed":226,"user":{"displayName":"","photoUrl":"","userId":""}}},"execution_count":4,"outputs":[]},{"cell_type":"markdown","source":["From the returned pages we extract the list of people."],"metadata":{"id":"2lR-J8vUcI5-"}},{"cell_type":"code","source":["# from the result pages we get from the GraphQL API, extract the data about the people\n","def extract_people_from_pages(list_of_pages):\n"," for page in list_of_pages:\n"," page_dict=benedict.from_json(page)\n"," for person in page_dict.get('data.organization.people.nodes'):\n"," yield person\n","\n","#--- example execution\n","people=extract_people_from_pages(list_of_pages)"],"metadata":{"id":"lQqnqydz2hUh","executionInfo":{"status":"ok","timestamp":1643208827139,"user_tz":-60,"elapsed":261,"user":{"displayName":"","photoUrl":"","userId":""}}},"execution_count":5,"outputs":[]},{"cell_type":"markdown","source":["From each person's metadata we extract and print out their name and ORCID iD."],"metadata":{"id":"FwJxfB_12wtY"}},{"cell_type":"code","source":["# extract ORCID from person\n","def extract_orcid(person):\n"," person_dict = benedict.from_json(person)\n"," orcid = person_dict.get('id').replace(\"https://orcid.org/\", \"\")\n"," name = person_dict.get('name')\n"," return orcid, name\n","\n","#--- example execution\n","for person in people:\n"," orcid, name = extract_orcid(person)\n"," print(f\"{orcid}, {name}\")"],"metadata":{"id":"aCYx1t4P3Bpu","executionInfo":{"status":"ok","timestamp":1643208836439,"user_tz":-60,"elapsed":2988,"user":{"displayName":"","photoUrl":"","userId":""}},"outputId":"1c350aa6-6659-4ff9-990d-e0309706941b","colab":{"base_uri":"https://localhost:8080/"}},"execution_count":6,"outputs":[{"output_type":"stream","name":"stdout","text":["0000-0002-3783-6130, Irene Weipert-Fenner\n","0000-0002-5452-0488, Hans-Joachim Spanger\n","0000-0001-6746-1248, Anton Peez\n","0000-0001-6731-5304, Julia Eckert\n","0000-0003-1575-9688, Hendrik Simon\n","0000-0002-1712-2624, Julian Junk\n","0000-0003-0035-5840, Raphael Oidtmann\n","0000-0002-8739-2486, Elvira Rosert\n","0000-0002-5925-043X, Ariadne Natal\n","0000-0002-7012-6739, Peter Kreuzer\n","0000-0001-7843-4480, Dirk Peters\n","0000-0003-0039-9827, Eldad Ben Aharon\n","0000-0001-6823-6819, Janna Lisa Chalmovsky\n","0000-0003-1940-8877, Mikhail Polianskii\n","0000-0002-4259-6071, Felix S. Bethke\n","0000-0001-7286-3575, Paul Chambers\n"]}]}]} \ No newline at end of file diff --git a/organization-people/openalex_get_people_by_organization.ipynb b/organization-people/openalex_get_people_by_organization.ipynb new file mode 100644 index 0000000..3c2dd8b --- /dev/null +++ b/organization-people/openalex_get_people_by_organization.ipynb @@ -0,0 +1 @@ +{"metadata":{"language_info":{"name":"python","version":"3.7.8","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kernelspec":{"name":"python3","display_name":"Python 3","language":"python"},"colab":{"name":"Kopie von Kopie von openalex_get_people_by_organization.ipynb","provenance":[{"file_id":"https://github.com/Project-TAPIR/pidgraph-notebooks/blob/organization-people/organization-people/openalex_get_people_by_organization.ipynb","timestamp":1643210429142}],"collapsed_sections":[]}},"nbformat_minor":5,"nbformat":4,"cells":[{"cell_type":"markdown","source":["### Query OpenAlex for all people affiliated with an organization\n","This script queries the [OpenAlex API](https://docs.openalex.org/api) via its '`/authors`' endpoint for all authors affiliated with an organization.\n","It takes a ROR URL as input which is used to retrieve all authors that specified the ROR ID in their metadata field '`last_known_institution.ror`'. From the resulting list of people we output their respective ORCID iDs."],"metadata":{"id":"ac7bedaf-05fb-4eb0-9bf5-e4d1d68a08c3"},"id":"ac7bedaf-05fb-4eb0-9bf5-e4d1d68a08c3"},{"cell_type":"code","source":["# needed dependency to make HTTP calls\n","import requests"],"metadata":{"id":"IUqshUWKwSk2","executionInfo":{"status":"ok","timestamp":1643210415322,"user_tz":-60,"elapsed":8,"user":{"displayName":"","photoUrl":"","userId":""}}},"id":"IUqshUWKwSk2","execution_count":1,"outputs":[]},{"cell_type":"markdown","source":["The input for the query is a ROR URL."],"metadata":{"id":"nSJjdkxGdWll"},"id":"nSJjdkxGdWll"},{"cell_type":"code","source":["# input parameter\n","example_ror=\"https://ror.org/021k10z87\""],"metadata":{"id":"7EryzPledIp6","executionInfo":{"status":"ok","timestamp":1643210415322,"user_tz":-60,"elapsed":6,"user":{"displayName":"","photoUrl":"","userId":""}}},"id":"7EryzPledIp6","execution_count":2,"outputs":[]},{"cell_type":"markdown","source":["We use it to query the OpenAlex API for authors that specified the organization's ROR ID in the field '`last_known_institution.ror`'. Since the OpenAlex API uses [pagination](https://docs.openalex.org/api/get-lists-of-entities#pagination), we need to loop through all pages to get the complete result set."],"metadata":{"id":"MiXVDKXid9tq"},"id":"MiXVDKXid9tq"},{"cell_type":"code","source":["# OpenAlex endpoint to query for authors\n","OPENALEX_API_AUTHORS = \"https://api.openalex.org/authors\"\n","\n","# query all people that are connected to given ROR\n","def download_data(ror):\n"," page = 1\n"," max_page = 1\n"," while page <= max_page:\n"," params = {'filter': 'last_known_institution.ror:'+ror, 'page': page}\n","\n"," response = requests.get(url=OPENALEX_API_AUTHORS,\n"," params=params,\n"," headers= {'Content-Type': 'application/json'})\n"," result=response.json()\n","\n"," # calculate max page number in first loop\n"," if max_page == 1:\n"," max_page = determine_max_page(result)\n"," page = page + 1\n"," yield result\n","\n","# calculate max number of result pages\n","def determine_max_page(response_data):\n"," item_count = response_data['meta']['count']\n"," items_per_page = response_data['meta']['per_page']\n"," max_page_ceil = item_count // items_per_page + bool(item_count % items_per_page)\n"," return max_page_ceil\n","\n","\n","#-- example execution\n","list_of_pages=download_data(example_ror)"],"metadata":{"trusted":true,"id":"8b608640-96a8-47d1-9de7-b7d3f6fd5a47","executionInfo":{"status":"ok","timestamp":1643210415323,"user_tz":-60,"elapsed":5,"user":{"displayName":"","photoUrl":"","userId":""}}},"execution_count":3,"outputs":[],"id":"8b608640-96a8-47d1-9de7-b7d3f6fd5a47"},{"cell_type":"markdown","source":["From the resulting list of people we extract and print out each ORCID and name."],"metadata":{"id":"CwRzvAQweuoW"},"id":"CwRzvAQweuoW"},{"cell_type":"code","source":["# extract all ORCIDs from the result\n","def extract_orcids(data):\n"," for author in data['results']:\n"," try:\n"," orcid=author['ids']['orcid'].replace(\"https://orcid.org/\", \"\")\n"," name=author['display_name']\n"," yield orcid, name\n"," except (KeyError,AttributeError) as e:\n"," pass\n","\n","#-- example execution\n","for page in list_of_pages:\n"," for orcid,name in extract_orcids(page):\n"," print(f\"{orcid}, {name}\")"],"metadata":{"trusted":true,"colab":{"base_uri":"https://localhost:8080/"},"id":"1c36737c-4dcf-42d5-80e2-802f0a7a8326","outputId":"5efd986b-0b92-4b0d-e5cc-a65aeae2785e","executionInfo":{"status":"ok","timestamp":1643210418504,"user_tz":-60,"elapsed":3186,"user":{"displayName":"","photoUrl":"","userId":""}}},"execution_count":4,"outputs":[{"output_type":"stream","name":"stdout","text":["0000-0002-3824-5375, Nicole Deitelhoff\n","0000-0002-7348-7206, Jonas Wolff\n","0000-0002-6891-770X, Francis O’Connor\n","0000-0002-3536-8898, Felix Anderl\n","0000-0002-4259-6071, Felix S. Bethke\n","0000-0002-3136-0901, Thorsten Gromes\n","0000-0001-9698-2616, Annika Elena Poppe\n","0000-0002-3783-6130, Irene Weipert-Fenner\n","0000-0002-4793-9010, Arvid Bell\n","0000-0002-7012-6739, Peter Kreuzer\n","0000-0002-0143-5183, Christina Kohler\n"]}],"id":"1c36737c-4dcf-42d5-80e2-802f0a7a8326"}]} \ No newline at end of file diff --git a/organization-people/orcid_get_people_by_organization.ipynb b/organization-people/orcid_get_people_by_organization.ipynb new file mode 100644 index 0000000..63d82c0 --- /dev/null +++ b/organization-people/orcid_get_people_by_organization.ipynb @@ -0,0 +1 @@ +{"nbformat":4,"nbformat_minor":0,"metadata":{"colab":{"name":"Kopie von orcid_get_people_by_organization.ipynb","provenance":[{"file_id":"https://github.com/Project-TAPIR/pidgraph-notebooks/blob/organization-people/organization-people/orcid_get_people_by_organization.ipynb","timestamp":1643211404649}],"collapsed_sections":[],"authorship_tag":"ABX9TyPDEh7qk1Vs70HvumKRqfGY"},"kernelspec":{"name":"python3","display_name":"Python 3"},"language_info":{"name":"python"}},"cells":[{"cell_type":"markdown","source":["### Query ORCID for all people affiliated with an organization and filter for current employees only\n","\n","This notebook queries the [ORCID API](https://api.orcid.org/v3.0/) for all [people affiliated with an organization](https://info.orcid.org/faq/how-do-i-find-orcid-record-holders-at-my-institution/). Additionally the affiliation is narrowed down to people **currently employed** by the organization."],"metadata":{"id":"u4HQPvDxKyjs"}},{"cell_type":"code","execution_count":null,"metadata":{"id":"5s5h9I5OKefn"},"outputs":[],"source":["# needed dependency to make HTTP calls\n","import requests\n","# dependencies for dealing with json\n","import pprint\n","!pip install python-benedict\n","from benedict import benedict"]},{"cell_type":"markdown","source":["### Organization metadata\n","The input value for all following queries is a ROR id or ROR URL."],"metadata":{"id":"JqXxTHg026Tk"}},{"cell_type":"code","source":["example_ror=\"https://ror.org/04aj4c181\""],"metadata":{"id":"tAoAtVZP25JT","executionInfo":{"status":"ok","timestamp":1643211341240,"user_tz":-60,"elapsed":8,"user":{"displayName":"","photoUrl":"","userId":""}}},"execution_count":2,"outputs":[]},{"cell_type":"markdown","source":["The first step is to call the [ROR API](https://ror.readme.io/) for the organization's metadata."],"metadata":{"id":"mmV5ar17CiSO"}},{"cell_type":"code","source":["# URL for ROR API\n","ROR_API_ENDPOINT = \"https://api.ror.org/organizations\"\n","\n","# query ROR API for organization's metadata\n","def query_ror_api(ror):\n"," response = requests.get(url=requests.utils.requote_uri(ROR_API_ENDPOINT + \"/\" + ror),\n"," headers={'Content-Type': 'application/json'})\n"," result=response.json()\n","\n"," return result\n","\n","#-- example execution\n","ror_data=query_ror_api(example_ror)\n","# if you want to see the retrieved metadata, uncomment next line\n","# pprint.pprint(ror_data)"],"metadata":{"id":"FKpMNpLLLYaZ","executionInfo":{"status":"ok","timestamp":1643211342054,"user_tz":-60,"elapsed":820,"user":{"displayName":"","photoUrl":"","userId":""}}},"execution_count":3,"outputs":[]},{"cell_type":"markdown","source":["In particular we are interested in the organization's grid ID and Wikidata ID."],"metadata":{"id":"mxOGfasxMAaA"}},{"cell_type":"code","source":["def extract_grid_from_ror_data(ror_data):\n"," orga_dict = benedict.from_json(ror_data)\n"," path_to_grid_id = \"external_ids.GRID.all\"\n"," grid_id = orga_dict.get(path_to_grid_id)\n"," return grid_id\n","\n","def extract_wikidata_from_ror_data(ror_data):\n"," orga_dict = benedict.from_json(ror_data)\n"," path_to_wikidata_id = \"external_ids.Wikidata.all[0]\"\n"," wikidata_id = orga_dict.get(path_to_wikidata_id)\n"," return wikidata_id\n","\n","\n","# example execution\n","organization_grid_id=extract_grid_from_ror_data(ror_data)\n","print(\"grid ID: \" + organization_grid_id)\n","organization_wikidata_id=extract_wikidata_from_ror_data(ror_data)\n","print(\"Wikidata ID: \" + organization_wikidata_id)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"wSwVZgSELik3","outputId":"510ec8f8-e8bf-4ead-db9e-8ed4a8c36d1e","executionInfo":{"status":"ok","timestamp":1643211342055,"user_tz":-60,"elapsed":11,"user":{"displayName":"","photoUrl":"","userId":""}}},"execution_count":4,"outputs":[{"output_type":"stream","name":"stdout","text":["grid ID: grid.461819.3\n","Wikidata ID: Q2399120\n"]}]},{"cell_type":"markdown","source":["We use the Wikidata ID of the organization to query Wikidata for the Ringgold ID of the organization."],"metadata":{"id":"oLZD9V1lzyQ4"}},{"cell_type":"code","source":["WIKIDATA_API = \"https://www.wikidata.org/w/api.php\"\n","\n","# query Wikidata with an organization's Wikidata ID\n","def query_wikidata_api(wikidata_id):\n","\n"," response = requests.get(url=WIKIDATA_API,\n"," params={'action': 'wbgetentities', 'ids': wikidata_id, 'props':'claims', 'format':'json'},\n"," headers={'Content-Type': 'application/json'})\n"," result=response.json()\n"," return result\n","\n","def extract_ringgold_from_wikidata_data(wikidata, wikidata_id):\n"," wikidata_dict = benedict.from_json(wikidata)\n"," path_to_ringgold_id = f\"entities.{wikidata_id}.claims.P3500[0].mainsnak.datavalue.value\"\n"," ringgold_id = wikidata_dict.get(path_to_ringgold_id)\n"," return ringgold_id\n","\n","\n","#-- example execution\n","wikidata_data = query_wikidata_api(organization_wikidata_id)\n","# if you want to see all metadata retrieved from Wikidata, uncomment next line\n","#pprint.pprint(wikidata_data)\n","organization_ringgold_id = extract_ringgold_from_wikidata_data(wikidata_data, organization_wikidata_id)\n","print(\"Ringgold ID: \" + str(organization_ringgold_id or ''))"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"v8S4dwfM0A-1","outputId":"44ece1df-3a30-4aa8-8bd6-0199353f0585","executionInfo":{"status":"ok","timestamp":1643211342356,"user_tz":-60,"elapsed":307,"user":{"displayName":"","photoUrl":"","userId":""}}},"execution_count":5,"outputs":[{"output_type":"stream","name":"stdout","text":["Ringgold ID: 28359\n"]}]},{"cell_type":"markdown","source":["To sum up the process up until now:\n","1. We used an organization's ROR ID to query the ROR API for an organization's grid ID and Wikidata ID. \n","2. We use Wikidata as intermediary to retrieve the Ringgold ID of the organization.\n","\n","![organization_data.png](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUAAAAFPCAYAAAA8xhd/AAAFgHRFWHRteGZpbGUAJTNDbXhmaWxlJTIwaG9zdCUzRCUyMmFwcC5kaWFncmFtcy5uZXQlMjIlMjBtb2RpZmllZCUzRCUyMjIwMjItMDEtMThUMTYlM0ExOCUzQTM2LjY3MVolMjIlMjBhZ2VudCUzRCUyMjUuMCUyMChXaW5kb3dzKSUyMiUyMGV0YWclM0QlMjJHY28zOVNEUXdyWHA3ZDhpR19KXyUyMiUyMHZlcnNpb24lM0QlMjIxNS41LjglMjIlMjB0eXBlJTNEJTIyZGV2aWNlJTIyJTNFJTNDZGlhZ3JhbSUyMGlkJTNEJTIyal9KdkxEUWlyNFU3V1Z3bXRFbGolMjIlMjBuYW1lJTNEJTIyUGFnZS0xJTIyJTNFNVZoZGM2SXdGUDAxUEc0SGlDZyUyQlZtMjdmZGpaVG4zbzdtTktVc2dZaVJOaWhmNzZUU1I4SktCdEhUOTJ4aGZIZXdJWGN1NDVOeUVPbUM3ekJ3NVh5UyUyQkdNSFY4RiUyQlVPbURtJTJCUHdwOSUyQmF1QW9nVEFXQU14SjZpRXZBYVlrdyUyQnNRVmVqYTRKd1psd29HS09DckV3d1ltbUtJMkZna0hPMk1TOTdZOVI4NmdyR3VBUE1JMGk3NkF0Qkl0SG8wSFdiZ1olMkJZeElsJTJCOUxnYVdNTHFZZzFrQ1VSczA0TEFuUU9tbkRGUiUyRmx2bVUwd1ZkeFV2NVgzM08wYnJGJTJCTTRGViUyQjVBYjB0Rm1oMUR4JTJGeVlQR1l2YzZMeVYzeFEyZDVoM1N0SiUyRno4JTJCMWtDdDAlMkJQJTJCcTFGVVZIQjJUcEZXR1h6SEREWkpFVGclMkJRcEdhblFqYXklMkJ4UkN5cEh0WjVNUmM0MyUyRm5DWGsyRGxBOW1TeXg0SVMlMkZSTjRDQlprNUxwOWJFcGxXSWl0MmtWWU1LZzdyMmNaMjZvVWYlMkIwUXg5Z3kyJTJGdzFhSEpKeWlXeVU3R1VVVVpobUpURjRhRWwwWlNTWjQ4VWNGTjBFViUyRm0yUHpYSWpLblNVQ2NoRjlaeVVwVmhka1JQUlNpVWpsY203Y2F1d3lhV0NvaFU4WVU0a1E1aHJySndWUmgxcldLV1RNMmRySHVFOWxBSHRXY2hqTEQ0VFlsY0tyVklIUFpXdU1JNHBGT1RkZk4yJTJCOHVzblBERWlKMUlyYmVDYVN2TUdsb0xLYWVxNzJoNnpFJTJGbFdvdEJLVlBMUVNiUlZZejN0d3dVS2R0ajVjZFlScXZTbE1LVUpLWWxUcFZ0WlpDV0ZpWEl2a2Ezd1ZnOHNDVUxxOWduSEdmbUFyOXRVU2k4ck5aJTJGdERJT0pFOHhVcnJWZ1dkbk12YTFlT1Z2Z0thT01ONEo5STVSYTBERzZ4c2dxd2JEYk5ZYm5iQnJCMFp0R2JmU1I0ZlM5TmolMkJpcFM5cVZidThjc0U5MEtyQVNuUm1xdzVQSnd2JTJGJTJCbVF4c1BjS2gzWndXMThnT0s4c1JoMVp2SkFGUVZEQTYycmpBejh3Q3hwMDIzaDR6alllN2l2TWY3RmRIdTlvYUpkaWJOeGg3RUY5ODEyVmpJRzFJUVE5M3pCOWJmRmtSYW1lZjRwMTV5TExUbmpSM1VoNHBHWEgzbzJjZTlueGVnNENTQnJINnJqa3FneHJyenQ5aGoxckYlMkZXJTJCZCUyQmlnbWRqcDFxODY3MktPJTJCc3dJWDNaVWVHRkhkYiUyRkY5MndSM00lMkIzQ0NkYW9PeWpqNTU5Vm4zd1pnaiUyQkFNWExzRG52TElsdURvM0IzVDglM0QlM0MlMkZkaWFncmFtJTNFJTNDJTJGbXhmaWxlJTNFtSbOjQAAHjBJREFUeJzt3V3IHFcdgPGTj6aNRWGskN4ULwYUP0ChI94IgqBDVUoRm2lpRRE/GCiCUpSuVUpA7ERBr+wGRUUoU6xKSF01tkHTCW3S0rgqqLTZmGIjwY4RFbxIQ/9etGcyO3tmd/Z9d8/smXl+cNDuu7Mz72b32TMfmygBgJ5SIiLHjx+X++67j8FgMHoxjh8/fiWABw4cEKUUg8Fg9GIcOHBgNoAvvfSSvPzyywwGg9HJ8dJLL80PIAB0FQEE0FsEEEBvEUAAvUUAAfQWAQTQWwQQQG8RQAC9RQAB9BYBBNBbBBBAbxFAAL1FAAH0FgEE0FsEEEBvEUAAvUUAAfQWAQTQWwQQQG8RQAC9RQAB9BYB7KkkSeb+M4FRFMl4PK5dPssyiaJIPM+bWmY0Gq18XeV1KqUkSZLitrrHDIJAkiSRPM+39gShFwhgT+koDYdDybJsagyH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)"],"metadata":{"id":"Tx8YWNLZ7_fx"}},{"cell_type":"markdown","source":["### Connection organization -> people\n","The second part of the process is to query for the people affiliated with the organization. For this we use the ORCID API and search for people affiliated with an organization like it is explained in the ORCID tutorial [\"How do I find ORCID record holders at my institution?\"](https://info.orcid.org/faq/how-do-i-find-orcid-record-holders-at-my-institution/). As parameters for the query we use the Grid ID and Ringgold ID for the organization.\n"],"metadata":{"id":"tQ0ZhMZk_Wcz"}},{"cell_type":"code","source":["ORCID_SEARCH_API = \"https://pub.orcid.org/v3.0/search/\"\n","\n","# query ORCID with an organization's Grid ID and Ringgold\n","def query_orcid_for_affiliations(grid_id, ringgold_id):\n"," query = f\"grid-org-id:{grid_id}\" if grid_id else \"\"\n"," query += \" OR \" if grid_id and ringgold_id else \"\"\n"," query += f\"ringgold-org-id:{ringgold_id}\" if ringgold_id else \"\"\n","\n"," response = requests.get(url=ORCID_SEARCH_API,\n"," params={'q': query},\n"," headers={'Content-Type': 'application/json', 'Accept': 'application/json'})\n"," result=response.json()\n"," return result\n","\n","def extract_orcids_from_affiliated_people(affiliated_people):\n"," people_dict = benedict.from_json(affiliated_people)\n"," for person in people_dict.get('result'):\n"," orcid=benedict(person).get('orcid-identifier.path')\n"," yield orcid\n","\n","#-- example execution\n","affiliated_people = query_orcid_for_affiliations(organization_grid_id, organization_ringgold_id)\n","#pprint.pprint(affiliated_people)\n","print(f\"Number of affiliated people: {affiliated_people.get('num-found','')}\")\n","affiliated_orcids= extract_orcids_from_affiliated_people(affiliated_people)\n","for orcid in affiliated_orcids:\n"," print(orcid)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"LwhzE2Nc_J-x","outputId":"9a77ca26-0568-42fd-d28b-068469735274","executionInfo":{"status":"ok","timestamp":1643211343190,"user_tz":-60,"elapsed":840,"user":{"displayName":"","photoUrl":"","userId":""}}},"execution_count":6,"outputs":[{"output_type":"stream","name":"stdout","text":["Number of affiliated people: 89\n","0000-0003-3922-8638\n","0000-0002-5610-9908\n","0000-0003-2749-7988\n","0000-0001-9758-904X\n","0000-0003-2718-0913\n","0000-0002-2614-1253\n","0000-0002-1266-4029\n","0000-0003-0929-7528\n","0000-0002-4311-5620\n","0000-0002-1595-3213\n","0000-0001-5135-5758\n","0000-0002-3680-2086\n","0000-0001-7408-0611\n","0000-0002-6347-5666\n","0000-0002-2874-4832\n","0000-0001-5375-3063\n","0000-0003-1574-4865\n","0000-0001-5322-0478\n","0000-0002-1407-7362\n","0000-0001-5492-3212\n","0000-0003-1668-3304\n","0000-0002-6802-1241\n","0000-0001-9248-5444\n","0000-0003-2257-0517\n","0000-0001-5693-4708\n","0000-0002-0938-0340\n","0000-0002-0698-2864\n","0000-0003-2510-0529\n","0000-0002-2342-0636\n","0000-0002-9362-4968\n","0000-0003-3320-5187\n","0000-0002-0021-9729\n","0000-0003-0524-1834\n","0000-0001-8824-8390\n","0000-0002-7760-5708\n","0000-0002-0719-5440\n","0000-0003-1537-2862\n","0000-0001-6260-7578\n","0000-0002-5320-0220\n","0000-0003-1132-7220\n","0000-0002-0474-2410\n","0000-0002-3278-0422\n","0000-0002-3447-0575\n","0000-0002-1851-0442\n","0000-0002-7917-3101\n","0000-0002-1442-335X\n","0000-0002-1019-3606\n","0000-0002-9649-7829\n","0000-0003-1702-8707\n","0000-0002-5124-0165\n","0000-0001-9133-4978\n","0000-0001-8080-5308\n","0000-0001-7086-6211\n","0000-0002-1452-9509\n","0000-0002-8579-9717\n","0000-0002-1019-9151\n","0000-0002-9767-3257\n","0000-0003-4040-9073\n","0000-0003-0226-3608\n","0000-0001-8920-7515\n","0000-0002-2593-8754\n","0000-0001-5712-1565\n","0000-0001-6836-1193\n","0000-0003-0232-7085\n","0000-0002-3557-9345\n","0000-0002-7325-5114\n","0000-0002-3075-7640\n","0000-0002-7992-5668\n","0000-0003-2499-7741\n","0000-0001-5839-0177\n","0000-0002-0310-5831\n","0000-0002-7839-3698\n","0000-0002-4450-349X\n","0000-0003-1800-0351\n","0000-0003-1043-4964\n","0000-0002-3060-7052\n","0000-0003-3709-5608\n","0000-0003-3184-5930\n","0000-0001-7460-7794\n","0000-0001-5336-6899\n","0000-0001-8258-2603\n","0000-0001-9924-9153\n","0000-0003-2237-7725\n","0000-0002-8913-9011\n","0000-0002-2013-6920\n","0000-0001-5232-9236\n","0000-0003-3975-5374\n","0000-0002-0687-5460\n","0000-0001-8777-2780\n"]}]},{"cell_type":"markdown","source":["The connection between organization and people via their affiliation as defined by the ORCID API is quite abroad: \n","\n","* It contains each person that used the organization identifier in one of the sections [employment, education & qualifications, membership & service, invited positions & distinctions](https://info.orcid.org/documentation/integration-guide/working-with-organization-identifiers/) in their ORCID record.\n","* Furthermore the connection is not limited to the current affiliation but also contains people that were affiliated with the organization years ago.\n","\n","--> \n","\n","That's why we decided to use the ORCIDs we retrieve via the search API and query the ORCID API for each of their detailed record to narrow the result set down to only people who \n","* use one of the organization's IDs in the employment section\n","* and that are currently employed (end-date of employment is empty)"],"metadata":{"id":"DUMnQM62MXns"}},{"cell_type":"code","source":["ORCID_RECORD_API = \"https://pub.orcid.org/v3.0/\"\n","\n","# query ORCID for an ORCID record\n","def query_orcid_for_record(orcid_id):\n","\n"," response = requests.get(url=requests.utils.requote_uri(ORCID_RECORD_API + orcid_id),\n"," headers={'Content-Type': 'application/json', 'Accept': 'application/json'})\n"," result=response.json()\n"," return result\n","\n","# check if affiliated person is a current employee\n","def is_current_employee(orcid_id, grid_id, ringgold_id):\n"," # get orcid record\n"," orcid_record = query_orcid_for_record(orcid_id)\n","\n"," #filter for current employees only\n"," record_dict = benedict.from_json(orcid_record)\n"," path_to_employments = \"activities-summary.employments.affiliation-group\"\n"," for employment in record_dict.get(path_to_employments):\n"," employment_dict = benedict(employment)\n"," path_to_orga_id = \"summaries[0].employment-summary.organization.disambiguated-organization.disambiguated-organization-identifier\"\n"," path_to_end_date = \"summaries[0].employment-summary.end-date\"\n","\n"," orga_id = employment_dict.get(path_to_orga_id)\n"," end_date = employment_dict.get(path_to_end_date)\n","\n"," return not end_date and (orga_id == grid_id or orga_id == ringgold_id)\n","\n","\n","#-- example execution\n","affiliated_orcids = extract_orcids_from_affiliated_people(affiliated_people)\n","employee_orcids = [orcid_id for orcid_id in affiliated_orcids if is_current_employee(orcid_id, organization_grid_id, organization_ringgold_id)]\n","print(f\"Number of current employees: {len(employee_orcids)}\")\n","for orcid_id in employee_orcids:\n"," print(orcid_id)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"6Ac2mk4vOz1A","outputId":"711330f3-415d-4404-acb9-a8645bb86fc7","executionInfo":{"status":"ok","timestamp":1643211372146,"user_tz":-60,"elapsed":28960,"user":{"displayName":"","photoUrl":"","userId":""}}},"execution_count":7,"outputs":[{"output_type":"stream","name":"stdout","text":["Number of current employees: 59\n","0000-0003-3922-8638\n","0000-0002-5610-9908\n","0000-0003-2749-7988\n","0000-0001-9758-904X\n","0000-0003-2718-0913\n","0000-0002-2614-1253\n","0000-0003-0929-7528\n","0000-0002-1595-3213\n","0000-0001-5135-5758\n","0000-0002-3680-2086\n","0000-0002-6347-5666\n","0000-0002-2874-4832\n","0000-0001-5375-3063\n","0000-0003-1574-4865\n","0000-0001-5322-0478\n","0000-0002-1407-7362\n","0000-0001-5492-3212\n","0000-0002-6802-1241\n","0000-0001-9248-5444\n","0000-0002-0938-0340\n","0000-0002-0698-2864\n","0000-0003-2510-0529\n","0000-0002-2342-0636\n","0000-0002-9362-4968\n","0000-0001-8824-8390\n","0000-0002-0719-5440\n","0000-0001-6260-7578\n","0000-0003-1132-7220\n","0000-0002-0474-2410\n","0000-0002-3278-0422\n","0000-0002-3447-0575\n","0000-0002-1851-0442\n","0000-0002-7917-3101\n","0000-0002-1442-335X\n","0000-0003-1702-8707\n","0000-0002-5124-0165\n","0000-0001-8080-5308\n","0000-0002-1452-9509\n","0000-0002-8579-9717\n","0000-0002-1019-9151\n","0000-0003-4040-9073\n","0000-0003-0226-3608\n","0000-0001-8920-7515\n","0000-0002-2593-8754\n","0000-0001-6836-1193\n","0000-0003-0232-7085\n","0000-0002-7325-5114\n","0000-0002-7992-5668\n","0000-0003-2499-7741\n","0000-0001-5839-0177\n","0000-0002-0310-5831\n","0000-0003-1043-4964\n","0000-0002-3060-7052\n","0000-0003-3709-5608\n","0000-0003-3184-5930\n","0000-0001-5336-6899\n","0000-0002-8913-9011\n","0000-0002-2013-6920\n","0000-0003-3975-5374\n"]}]},{"cell_type":"markdown","source":["--> For this example we were able to narrow down the result from 89 affiliated people to 59 currently employed people."],"metadata":{"id":"3oj7LKIlZBgT"}}]} \ No newline at end of file