tooluniverse 0.1.4__py3-none-any.whl → 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of tooluniverse might be problematic. Click here for more details.
- tooluniverse/__init__.py +340 -4
- tooluniverse/admetai_tool.py +84 -0
- tooluniverse/agentic_tool.py +563 -0
- tooluniverse/alphafold_tool.py +96 -0
- tooluniverse/base_tool.py +129 -6
- tooluniverse/boltz_tool.py +207 -0
- tooluniverse/chem_tool.py +192 -0
- tooluniverse/compose_scripts/__init__.py +1 -0
- tooluniverse/compose_scripts/biomarker_discovery.py +293 -0
- tooluniverse/compose_scripts/comprehensive_drug_discovery.py +186 -0
- tooluniverse/compose_scripts/drug_safety_analyzer.py +89 -0
- tooluniverse/compose_scripts/literature_tool.py +34 -0
- tooluniverse/compose_scripts/output_summarizer.py +279 -0
- tooluniverse/compose_scripts/tool_description_optimizer.py +681 -0
- tooluniverse/compose_scripts/tool_discover.py +705 -0
- tooluniverse/compose_scripts/tool_graph_composer.py +448 -0
- tooluniverse/compose_tool.py +371 -0
- tooluniverse/ctg_tool.py +1002 -0
- tooluniverse/custom_tool.py +81 -0
- tooluniverse/dailymed_tool.py +108 -0
- tooluniverse/data/admetai_tools.json +155 -0
- tooluniverse/data/agentic_tools.json +1156 -0
- tooluniverse/data/alphafold_tools.json +87 -0
- tooluniverse/data/boltz_tools.json +9 -0
- tooluniverse/data/chembl_tools.json +16 -0
- tooluniverse/data/clait_tools.json +108 -0
- tooluniverse/data/clinicaltrials_gov_tools.json +326 -0
- tooluniverse/data/compose_tools.json +202 -0
- tooluniverse/data/dailymed_tools.json +70 -0
- tooluniverse/data/dataset_tools.json +646 -0
- tooluniverse/data/disease_target_score_tools.json +712 -0
- tooluniverse/data/efo_tools.json +17 -0
- tooluniverse/data/embedding_tools.json +319 -0
- tooluniverse/data/enrichr_tools.json +31 -0
- tooluniverse/data/europe_pmc_tools.json +22 -0
- tooluniverse/data/expert_feedback_tools.json +10 -0
- tooluniverse/data/fda_drug_adverse_event_tools.json +491 -0
- tooluniverse/data/fda_drug_labeling_tools.json +544 -168
- tooluniverse/data/fda_drugs_with_brand_generic_names_for_tool.py +76929 -148860
- tooluniverse/data/finder_tools.json +209 -0
- tooluniverse/data/gene_ontology_tools.json +113 -0
- tooluniverse/data/gwas_tools.json +1082 -0
- tooluniverse/data/hpa_tools.json +333 -0
- tooluniverse/data/humanbase_tools.json +47 -0
- tooluniverse/data/idmap_tools.json +74 -0
- tooluniverse/data/mcp_client_tools_example.json +113 -0
- tooluniverse/data/mcpautoloadertool_defaults.json +28 -0
- tooluniverse/data/medlineplus_tools.json +141 -0
- tooluniverse/data/monarch_tools.json +1 -1
- tooluniverse/data/openalex_tools.json +36 -0
- tooluniverse/data/opentarget_tools.json +82 -58
- tooluniverse/data/output_summarization_tools.json +101 -0
- tooluniverse/data/packages/bioinformatics_core_tools.json +1756 -0
- tooluniverse/data/packages/categorized_tools.txt +206 -0
- tooluniverse/data/packages/cheminformatics_tools.json +347 -0
- tooluniverse/data/packages/earth_sciences_tools.json +74 -0
- tooluniverse/data/packages/genomics_tools.json +776 -0
- tooluniverse/data/packages/image_processing_tools.json +38 -0
- tooluniverse/data/packages/machine_learning_tools.json +789 -0
- tooluniverse/data/packages/neuroscience_tools.json +62 -0
- tooluniverse/data/packages/original_tools.txt +0 -0
- tooluniverse/data/packages/physics_astronomy_tools.json +62 -0
- tooluniverse/data/packages/scientific_computing_tools.json +560 -0
- tooluniverse/data/packages/single_cell_tools.json +453 -0
- tooluniverse/data/packages/software_tools.json +4954 -0
- tooluniverse/data/packages/structural_biology_tools.json +396 -0
- tooluniverse/data/packages/visualization_tools.json +399 -0
- tooluniverse/data/pubchem_tools.json +215 -0
- tooluniverse/data/pubtator_tools.json +68 -0
- tooluniverse/data/rcsb_pdb_tools.json +1332 -0
- tooluniverse/data/reactome_tools.json +19 -0
- tooluniverse/data/semantic_scholar_tools.json +26 -0
- tooluniverse/data/special_tools.json +2 -25
- tooluniverse/data/tool_composition_tools.json +88 -0
- tooluniverse/data/toolfinderkeyword_defaults.json +34 -0
- tooluniverse/data/txagent_client_tools.json +9 -0
- tooluniverse/data/uniprot_tools.json +211 -0
- tooluniverse/data/url_fetch_tools.json +94 -0
- tooluniverse/data/uspto_downloader_tools.json +9 -0
- tooluniverse/data/uspto_tools.json +811 -0
- tooluniverse/data/xml_tools.json +3275 -0
- tooluniverse/dataset_tool.py +296 -0
- tooluniverse/default_config.py +165 -0
- tooluniverse/efo_tool.py +42 -0
- tooluniverse/embedding_database.py +630 -0
- tooluniverse/embedding_sync.py +396 -0
- tooluniverse/enrichr_tool.py +266 -0
- tooluniverse/europe_pmc_tool.py +52 -0
- tooluniverse/execute_function.py +1775 -95
- tooluniverse/extended_hooks.py +444 -0
- tooluniverse/gene_ontology_tool.py +194 -0
- tooluniverse/graphql_tool.py +158 -36
- tooluniverse/gwas_tool.py +358 -0
- tooluniverse/hpa_tool.py +1645 -0
- tooluniverse/humanbase_tool.py +389 -0
- tooluniverse/logging_config.py +254 -0
- tooluniverse/mcp_client_tool.py +764 -0
- tooluniverse/mcp_integration.py +413 -0
- tooluniverse/mcp_tool_registry.py +925 -0
- tooluniverse/medlineplus_tool.py +337 -0
- tooluniverse/openalex_tool.py +228 -0
- tooluniverse/openfda_adv_tool.py +283 -0
- tooluniverse/openfda_tool.py +393 -160
- tooluniverse/output_hook.py +1122 -0
- tooluniverse/package_tool.py +195 -0
- tooluniverse/pubchem_tool.py +158 -0
- tooluniverse/pubtator_tool.py +168 -0
- tooluniverse/rcsb_pdb_tool.py +38 -0
- tooluniverse/reactome_tool.py +108 -0
- tooluniverse/remote/boltz/boltz_mcp_server.py +50 -0
- tooluniverse/remote/depmap_24q2/depmap_24q2_mcp_tool.py +442 -0
- tooluniverse/remote/expert_feedback/human_expert_mcp_tools.py +2013 -0
- tooluniverse/remote/expert_feedback/simple_test.py +23 -0
- tooluniverse/remote/expert_feedback/start_web_interface.py +188 -0
- tooluniverse/remote/expert_feedback/web_only_interface.py +0 -0
- tooluniverse/remote/expert_feedback_mcp/human_expert_mcp_server.py +1611 -0
- tooluniverse/remote/expert_feedback_mcp/simple_test.py +34 -0
- tooluniverse/remote/expert_feedback_mcp/start_web_interface.py +91 -0
- tooluniverse/remote/immune_compass/compass_tool.py +327 -0
- tooluniverse/remote/pinnacle/pinnacle_tool.py +328 -0
- tooluniverse/remote/transcriptformer/transcriptformer_tool.py +586 -0
- tooluniverse/remote/uspto_downloader/uspto_downloader_mcp_server.py +61 -0
- tooluniverse/remote/uspto_downloader/uspto_downloader_tool.py +120 -0
- tooluniverse/remote_tool.py +99 -0
- tooluniverse/restful_tool.py +53 -30
- tooluniverse/scripts/generate_tool_graph.py +408 -0
- tooluniverse/scripts/visualize_tool_graph.py +829 -0
- tooluniverse/semantic_scholar_tool.py +62 -0
- tooluniverse/smcp.py +2452 -0
- tooluniverse/smcp_server.py +975 -0
- tooluniverse/test/mcp_server_test.py +0 -0
- tooluniverse/test/test_admetai_tool.py +370 -0
- tooluniverse/test/test_agentic_tool.py +129 -0
- tooluniverse/test/test_alphafold_tool.py +71 -0
- tooluniverse/test/test_chem_tool.py +37 -0
- tooluniverse/test/test_compose_lieraturereview.py +63 -0
- tooluniverse/test/test_compose_tool.py +448 -0
- tooluniverse/test/test_dailymed.py +69 -0
- tooluniverse/test/test_dataset_tool.py +200 -0
- tooluniverse/test/test_disease_target_score.py +56 -0
- tooluniverse/test/test_drugbank_filter_examples.py +179 -0
- tooluniverse/test/test_efo.py +31 -0
- tooluniverse/test/test_enrichr_tool.py +21 -0
- tooluniverse/test/test_europe_pmc_tool.py +20 -0
- tooluniverse/test/test_fda_adv.py +95 -0
- tooluniverse/test/test_fda_drug_labeling.py +91 -0
- tooluniverse/test/test_gene_ontology_tools.py +66 -0
- tooluniverse/test/test_gwas_tool.py +139 -0
- tooluniverse/test/test_hpa.py +625 -0
- tooluniverse/test/test_humanbase_tool.py +20 -0
- tooluniverse/test/test_idmap_tools.py +61 -0
- tooluniverse/test/test_mcp_server.py +211 -0
- tooluniverse/test/test_mcp_tool.py +247 -0
- tooluniverse/test/test_medlineplus.py +220 -0
- tooluniverse/test/test_openalex_tool.py +32 -0
- tooluniverse/test/test_opentargets.py +28 -0
- tooluniverse/test/test_pubchem_tool.py +116 -0
- tooluniverse/test/test_pubtator_tool.py +37 -0
- tooluniverse/test/test_rcsb_pdb_tool.py +86 -0
- tooluniverse/test/test_reactome.py +54 -0
- tooluniverse/test/test_semantic_scholar_tool.py +24 -0
- tooluniverse/test/test_software_tools.py +147 -0
- tooluniverse/test/test_tool_description_optimizer.py +49 -0
- tooluniverse/test/test_tool_finder.py +26 -0
- tooluniverse/test/test_tool_finder_llm.py +252 -0
- tooluniverse/test/test_tools_find.py +195 -0
- tooluniverse/test/test_uniprot_tools.py +74 -0
- tooluniverse/test/test_uspto_tool.py +72 -0
- tooluniverse/test/test_xml_tool.py +113 -0
- tooluniverse/tool_finder_embedding.py +267 -0
- tooluniverse/tool_finder_keyword.py +693 -0
- tooluniverse/tool_finder_llm.py +699 -0
- tooluniverse/tool_graph_web_ui.py +955 -0
- tooluniverse/tool_registry.py +416 -0
- tooluniverse/uniprot_tool.py +155 -0
- tooluniverse/url_tool.py +253 -0
- tooluniverse/uspto_tool.py +240 -0
- tooluniverse/utils.py +369 -41
- tooluniverse/xml_tool.py +369 -0
- tooluniverse-1.0.0.dist-info/METADATA +377 -0
- tooluniverse-1.0.0.dist-info/RECORD +186 -0
- {tooluniverse-0.1.4.dist-info → tooluniverse-1.0.0.dist-info}/WHEEL +1 -1
- tooluniverse-1.0.0.dist-info/entry_points.txt +9 -0
- tooluniverse-0.1.4.dist-info/METADATA +0 -141
- tooluniverse-0.1.4.dist-info/RECORD +0 -18
- {tooluniverse-0.1.4.dist-info → tooluniverse-1.0.0.dist-info}/licenses/LICENSE +0 -0
- {tooluniverse-0.1.4.dist-info → tooluniverse-1.0.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import requests
|
|
2
|
+
import fitz
|
|
3
|
+
import easyocr
|
|
4
|
+
from io import BytesIO
|
|
5
|
+
from docx import Document
|
|
6
|
+
from PIL import Image
|
|
7
|
+
from .uspto_tool import USPTOOpenDataPortalTool
|
|
8
|
+
from .tool_registry import register_tool
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@register_tool("USPTOPatentDocumentDownloader")
|
|
12
|
+
class USPTOPatentDocumentDownloader(USPTOOpenDataPortalTool):
|
|
13
|
+
"""
|
|
14
|
+
Fetch and download the abstract (ABST), claims (CLM), and full application text (APP.TEXT)
|
|
15
|
+
PDFs for a given patent application number, following the one-time redirect flow.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
def __init__(self, tool_config):
|
|
19
|
+
super().__init__(tool_config=tool_config)
|
|
20
|
+
|
|
21
|
+
def run(self, arguments):
|
|
22
|
+
def ocr_pdf_bytes(pdf_bytes, dpi=300):
|
|
23
|
+
print("Running OCR on PDF bytes...")
|
|
24
|
+
doc = fitz.open(stream=pdf_bytes, filetype="pdf")
|
|
25
|
+
pages_text = []
|
|
26
|
+
|
|
27
|
+
# Initialize EasyOCR reader once
|
|
28
|
+
reader = easyocr.Reader(["en"], gpu=True)
|
|
29
|
+
|
|
30
|
+
for page in doc:
|
|
31
|
+
# render the page to a PIL image at high resolution
|
|
32
|
+
pix = page.get_pixmap(dpi=dpi)
|
|
33
|
+
img = Image.frombytes("RGB", [pix.width, pix.height], pix.samples)
|
|
34
|
+
img_bytes = BytesIO()
|
|
35
|
+
img.save(img_bytes, format="PNG")
|
|
36
|
+
img_bytes.seek(0)
|
|
37
|
+
results = reader.readtext(img_bytes.getvalue(), detail=0)
|
|
38
|
+
text = "\n".join(results)
|
|
39
|
+
pages_text.append(text.strip())
|
|
40
|
+
|
|
41
|
+
doc.close()
|
|
42
|
+
return "\n\n".join(pages_text)
|
|
43
|
+
|
|
44
|
+
metadata = super().run(arguments)
|
|
45
|
+
if isinstance(metadata, dict) and metadata.get("error"):
|
|
46
|
+
return metadata
|
|
47
|
+
|
|
48
|
+
desired = self.tool_config.get("document")
|
|
49
|
+
|
|
50
|
+
docs = metadata.get("documentBag", [])
|
|
51
|
+
if not docs:
|
|
52
|
+
return {"error": "No documents found."}
|
|
53
|
+
|
|
54
|
+
result = None
|
|
55
|
+
all_doc_codes = set()
|
|
56
|
+
for doc in docs:
|
|
57
|
+
code = doc.get("documentCode")
|
|
58
|
+
all_doc_codes.add(code)
|
|
59
|
+
if code != desired:
|
|
60
|
+
continue
|
|
61
|
+
|
|
62
|
+
plain_text = ""
|
|
63
|
+
pdf_opt = None
|
|
64
|
+
word_opt = None
|
|
65
|
+
for opt in doc.get("downloadOptionBag", []):
|
|
66
|
+
m = opt.get("mimeTypeIdentifier", "").upper()
|
|
67
|
+
if m == "PDF" and not pdf_opt:
|
|
68
|
+
pdf_opt = opt
|
|
69
|
+
elif m == "MS_WORD" and not word_opt:
|
|
70
|
+
word_opt = opt
|
|
71
|
+
|
|
72
|
+
if word_opt:
|
|
73
|
+
url = word_opt["downloadUrl"]
|
|
74
|
+
resp = requests.get(url, headers=self.headers, timeout=30)
|
|
75
|
+
resp.raise_for_status()
|
|
76
|
+
buf = BytesIO(resp.content)
|
|
77
|
+
docx = Document(buf)
|
|
78
|
+
plain_text = "\n\n".join(
|
|
79
|
+
p.text for p in docx.paragraphs if p.text.strip()
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
if not plain_text and pdf_opt:
|
|
83
|
+
url = pdf_opt["downloadUrl"]
|
|
84
|
+
resp = requests.get(url, headers=self.headers, timeout=30)
|
|
85
|
+
resp.raise_for_status()
|
|
86
|
+
pdf_bytes = resp.content
|
|
87
|
+
pdf_doc = fitz.open(stream=pdf_bytes, filetype="pdf")
|
|
88
|
+
for page in pdf_doc:
|
|
89
|
+
plain_text += page.get_text().strip()
|
|
90
|
+
pdf_doc.close()
|
|
91
|
+
|
|
92
|
+
if plain_text == "":
|
|
93
|
+
# If no text was extracted, try to extract text from images
|
|
94
|
+
plain_text = ocr_pdf_bytes(pdf_bytes)
|
|
95
|
+
|
|
96
|
+
if plain_text:
|
|
97
|
+
# if plain text is longer than current result, it is probably a better text extraction
|
|
98
|
+
if result is None or len(plain_text) > len(result):
|
|
99
|
+
result = plain_text
|
|
100
|
+
|
|
101
|
+
if result is None:
|
|
102
|
+
return {
|
|
103
|
+
"error": f"Could not parse document with code {desired}. The documents available for this patent are: {', '.join(all_doc_codes)}."
|
|
104
|
+
}
|
|
105
|
+
else:
|
|
106
|
+
# Return the plain text extracted from the PDF
|
|
107
|
+
return {"result": result}
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
# if __name__ == "__main__":
|
|
111
|
+
# # Example usage
|
|
112
|
+
# tool_config = {
|
|
113
|
+
# "name": "uspto_patent_document_downloader",
|
|
114
|
+
# "description": "Download patent documents and extract text.",
|
|
115
|
+
# "document": "ABST", # Specify the document type to download
|
|
116
|
+
# }
|
|
117
|
+
# downloader = USPTOPatentDocumentDownloader(tool_config)
|
|
118
|
+
# arguments = {"applicationNumberText": "19053071"} # Example application number
|
|
119
|
+
# result = downloader.run(arguments)
|
|
120
|
+
# print(result)
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Remote Tool Implementation
|
|
3
|
+
|
|
4
|
+
This module provides a RemoteTool class that represents external MCP/SMCP tools
|
|
5
|
+
that are available for listing but cannot be executed locally. These tools are
|
|
6
|
+
stored as configuration records only.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from .base_tool import BaseTool
|
|
10
|
+
from .tool_registry import register_tool
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@register_tool("RemoteTool")
|
|
14
|
+
class RemoteTool(BaseTool):
|
|
15
|
+
"""
|
|
16
|
+
A placeholder tool class for external MCP/SMCP tools.
|
|
17
|
+
|
|
18
|
+
RemoteTool represents tools that are hosted on external MCP/SMCP servers
|
|
19
|
+
and are only available for discovery and listing purposes. These tools
|
|
20
|
+
cannot be executed locally through ToolUniverse but their configurations
|
|
21
|
+
are preserved for reference.
|
|
22
|
+
|
|
23
|
+
Attributes:
|
|
24
|
+
tool_config (dict): The tool configuration dictionary
|
|
25
|
+
remote_info (dict): Information about the remote server and tool
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(self, tool_config=None):
|
|
29
|
+
"""
|
|
30
|
+
Initialize the RemoteTool.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
tool_config (dict, optional): Tool configuration dictionary
|
|
34
|
+
"""
|
|
35
|
+
super().__init__(tool_config)
|
|
36
|
+
self.remote_info = tool_config.get("remote_info", {}) if tool_config else {}
|
|
37
|
+
|
|
38
|
+
def run(self, arguments=None):
|
|
39
|
+
"""
|
|
40
|
+
Placeholder run method for remote tools.
|
|
41
|
+
|
|
42
|
+
Remote tools cannot be executed locally. This method always returns
|
|
43
|
+
an error message indicating that the tool is not available for local execution.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
arguments (dict, optional): Tool arguments (ignored)
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
dict: Error message indicating the tool is not available locally
|
|
50
|
+
"""
|
|
51
|
+
server_type = self.remote_info.get("server_type", "Unknown")
|
|
52
|
+
original_type = self.remote_info.get("original_type", "Unknown")
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
"error": "Remote tool not available for local execution",
|
|
56
|
+
"tool_name": (
|
|
57
|
+
self.tool_config.get("name", "Unknown")
|
|
58
|
+
if self.tool_config
|
|
59
|
+
else "Unknown"
|
|
60
|
+
),
|
|
61
|
+
"tool_type": "RemoteTool",
|
|
62
|
+
"original_type": original_type,
|
|
63
|
+
"server_type": server_type,
|
|
64
|
+
"message": "This tool is hosted on an external MCP/SMCP server and cannot be executed locally. Please use the external server directly.",
|
|
65
|
+
"remote_info": self.remote_info,
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
def get_remote_info(self):
|
|
69
|
+
"""
|
|
70
|
+
Get information about the remote server hosting this tool.
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
dict: Remote server information including server type, URL, and original tool type
|
|
74
|
+
"""
|
|
75
|
+
return self.remote_info.copy()
|
|
76
|
+
|
|
77
|
+
def is_available_locally(self):
|
|
78
|
+
"""
|
|
79
|
+
Check if this tool is available for local execution.
|
|
80
|
+
|
|
81
|
+
Returns:
|
|
82
|
+
bool: Always False for RemoteTool instances
|
|
83
|
+
"""
|
|
84
|
+
return False
|
|
85
|
+
|
|
86
|
+
def get_server_info(self):
|
|
87
|
+
"""
|
|
88
|
+
Get server connection information for this remote tool.
|
|
89
|
+
|
|
90
|
+
Returns:
|
|
91
|
+
dict: Server connection details
|
|
92
|
+
"""
|
|
93
|
+
return {
|
|
94
|
+
"server_type": self.remote_info.get("server_type"),
|
|
95
|
+
"server_url": self.remote_info.get("server_url"),
|
|
96
|
+
"transport": self.remote_info.get("transport"),
|
|
97
|
+
"mcp_tool_name": self.remote_info.get("mcp_tool_name"),
|
|
98
|
+
"source_directory": self.remote_info.get("source_directory"),
|
|
99
|
+
}
|
tooluniverse/restful_tool.py
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
from .graphql_tool import GraphQLTool
|
|
2
2
|
import requests
|
|
3
3
|
import copy
|
|
4
|
-
import
|
|
4
|
+
from .tool_registry import register_tool
|
|
5
|
+
|
|
5
6
|
|
|
6
7
|
def execute_RESTful_query(endpoint_url, variables=None):
|
|
7
|
-
response = requests.get(
|
|
8
|
-
endpoint_url, params = variables)
|
|
8
|
+
response = requests.get(endpoint_url, params=variables)
|
|
9
9
|
try:
|
|
10
10
|
result = response.json()
|
|
11
11
|
|
|
12
12
|
# Check if the response contains errors
|
|
13
|
-
if
|
|
14
|
-
print("Invalid Query: ", result[
|
|
13
|
+
if "error" in result:
|
|
14
|
+
print("Invalid Query: ", result["error"])
|
|
15
15
|
return False
|
|
16
16
|
else:
|
|
17
17
|
return result
|
|
18
|
-
except requests.exceptions.JSONDecodeError
|
|
18
|
+
except requests.exceptions.JSONDecodeError:
|
|
19
19
|
print("JSONDecodeError: Could not decode the response as JSON")
|
|
20
20
|
return False
|
|
21
21
|
except requests.exceptions.HTTPError as e:
|
|
@@ -23,19 +23,27 @@ def execute_RESTful_query(endpoint_url, variables=None):
|
|
|
23
23
|
except Exception as e:
|
|
24
24
|
print(f"An error occurred: {e}")
|
|
25
25
|
|
|
26
|
+
|
|
27
|
+
@register_tool("RESTfulTool")
|
|
26
28
|
class RESTfulTool(GraphQLTool):
|
|
27
29
|
def __init__(self, tool_config, endpoint_url):
|
|
28
30
|
super().__init__(tool_config, endpoint_url)
|
|
29
31
|
|
|
30
32
|
def run(self, arguments):
|
|
31
33
|
arguments = copy.deepcopy(arguments)
|
|
32
|
-
return execute_RESTful_query(
|
|
34
|
+
return execute_RESTful_query(
|
|
35
|
+
endpoint_url=self.endpoint_url, variables=arguments
|
|
36
|
+
)
|
|
37
|
+
|
|
33
38
|
|
|
39
|
+
@register_tool("Monarch")
|
|
34
40
|
class MonarchTool(RESTfulTool):
|
|
35
41
|
def __init__(self, tool_config):
|
|
36
|
-
endpoint_url =
|
|
42
|
+
endpoint_url = (
|
|
43
|
+
"https://api.monarchinitiative.org/v3/api" + tool_config["tool_url"]
|
|
44
|
+
)
|
|
37
45
|
super().__init__(tool_config, endpoint_url)
|
|
38
|
-
|
|
46
|
+
|
|
39
47
|
def run(self, arguments):
|
|
40
48
|
arguments = copy.deepcopy(arguments)
|
|
41
49
|
query_schema_runtime = copy.deepcopy(self.query_schema)
|
|
@@ -43,53 +51,68 @@ class MonarchTool(RESTfulTool):
|
|
|
43
51
|
if key in arguments:
|
|
44
52
|
query_schema_runtime[key] = arguments[key]
|
|
45
53
|
if "url_key" in query_schema_runtime:
|
|
46
|
-
url_key_name = query_schema_runtime[
|
|
47
|
-
formatted_endpoint_url = self.endpoint_url.format(
|
|
48
|
-
|
|
54
|
+
url_key_name = query_schema_runtime["url_key"]
|
|
55
|
+
formatted_endpoint_url = self.endpoint_url.format(
|
|
56
|
+
url_key=query_schema_runtime[url_key_name]
|
|
57
|
+
)
|
|
58
|
+
del query_schema_runtime["url_key"]
|
|
49
59
|
else:
|
|
50
60
|
formatted_endpoint_url = self.endpoint_url
|
|
51
61
|
if isinstance(query_schema_runtime, dict):
|
|
52
62
|
print(query_schema_runtime)
|
|
53
|
-
if
|
|
54
|
-
query_schema_runtime[
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
63
|
+
if "query" in query_schema_runtime:
|
|
64
|
+
query_schema_runtime["q"] = query_schema_runtime[
|
|
65
|
+
"query"
|
|
66
|
+
] # match with the api
|
|
67
|
+
response = execute_RESTful_query(
|
|
68
|
+
endpoint_url=formatted_endpoint_url, variables=query_schema_runtime
|
|
69
|
+
)
|
|
70
|
+
if "facet_fields" in response:
|
|
71
|
+
del response["facet_fields"]
|
|
72
|
+
|
|
58
73
|
def remove_empty_values(obj):
|
|
59
74
|
if isinstance(obj, dict):
|
|
60
|
-
return {
|
|
61
|
-
|
|
75
|
+
return {
|
|
76
|
+
k: remove_empty_values(v)
|
|
77
|
+
for k, v in obj.items()
|
|
78
|
+
if v not in [0, [], None]
|
|
79
|
+
}
|
|
62
80
|
elif isinstance(obj, list):
|
|
63
81
|
return [remove_empty_values(v) for v in obj if v not in [0, [], None]]
|
|
64
82
|
else:
|
|
65
83
|
return obj
|
|
84
|
+
|
|
66
85
|
response = remove_empty_values(response)
|
|
67
86
|
return response
|
|
68
87
|
|
|
88
|
+
|
|
89
|
+
@register_tool("MonarchDiseasesForMultiplePheno")
|
|
69
90
|
class MonarchDiseasesForMultiplePhenoTool(MonarchTool):
|
|
70
91
|
def __init__(self, tool_config):
|
|
71
92
|
super().__init__(tool_config)
|
|
72
|
-
|
|
93
|
+
|
|
73
94
|
def run(self, arguments):
|
|
74
95
|
arguments = copy.deepcopy(arguments)
|
|
75
96
|
query_schema_runtime = copy.deepcopy(self.query_schema)
|
|
76
97
|
for key in query_schema_runtime:
|
|
77
|
-
if (key!="HPO_ID_list") and (key in arguments):
|
|
98
|
+
if (key != "HPO_ID_list") and (key in arguments):
|
|
78
99
|
query_schema_runtime[key] = arguments[key]
|
|
79
100
|
all_diseases = []
|
|
80
|
-
for HPOID in arguments[
|
|
101
|
+
for HPOID in arguments["HPO_ID_list"]:
|
|
81
102
|
each_query_schema_runtime = copy.deepcopy(query_schema_runtime)
|
|
82
|
-
each_query_schema_runtime[
|
|
83
|
-
each_query_schema_runtime[
|
|
84
|
-
each_output = execute_RESTful_query(
|
|
85
|
-
|
|
86
|
-
|
|
103
|
+
each_query_schema_runtime["object"] = HPOID
|
|
104
|
+
each_query_schema_runtime["limit"] = 500
|
|
105
|
+
each_output = execute_RESTful_query(
|
|
106
|
+
endpoint_url=self.endpoint_url, variables=each_query_schema_runtime
|
|
107
|
+
)
|
|
108
|
+
each_output = each_output["items"]
|
|
109
|
+
each_output_names = [disease["subject_label"] for disease in each_output]
|
|
87
110
|
all_diseases.append(each_output_names)
|
|
88
|
-
|
|
111
|
+
|
|
89
112
|
intersection = set(all_diseases[0])
|
|
90
113
|
for element in all_diseases[1:]:
|
|
91
114
|
intersection &= set(element)
|
|
92
115
|
intersection = list(intersection)
|
|
93
|
-
if query_schema_runtime[
|
|
94
|
-
intersection = intersection[:query_schema_runtime[
|
|
116
|
+
if query_schema_runtime["limit"] < len(intersection):
|
|
117
|
+
intersection = intersection[: query_schema_runtime["limit"]]
|
|
95
118
|
return intersection
|