diff --git a/my_experiments/ibd_literature/test.txt b/my_experiments/ibd_literature/test.txt new file mode 100644 index 000000000..1f2ad8bdf --- /dev/null +++ b/my_experiments/ibd_literature/test.txt @@ -0,0 +1,5 @@ +Subject Predicate Object +inflammatory bowel disease pro-inflammatory cytokine production +ulcerative colitis to arachidonic acid metabolic process +ulcerative colitis relieving inflammatory response +ulcerative colitis and inflammatory response diff --git a/output_parser_yaml.py b/output_parser_yaml.py new file mode 100644 index 000000000..b0dc6913d --- /dev/null +++ b/output_parser_yaml.py @@ -0,0 +1,40 @@ +import yaml +from yaml import CLoader as Loader +from oaklib import get_adapter + +NULL_VALS = ['', 'Not mentioned', 'none mentioned', 'Not mentioned in the text', + 'Not mentioned in the provided text.', 'No exposures mentioned in the text.', + 'None', 'N/A', 'No exposures mentioned in the text.', 'None mentioned in the text', + 'Not mentioned in the text.', 'None relevant', 'None mentioned in the text.', + 'No gene to molecular activity relationships mentioned in the text.', + 'No genes mentioned', 'No genes mentioned in the text.', 'NA', '-', + 'None mentioned'] +output_file = "experiments/ibd_literature/output_2000_1122.yaml" + +def filter_dictionary(input_dict, filter_keys): + filtered_dict = {key: value for key, value in input_dict.items() if key in filter_keys} + return filtered_dict + +with open(output_file, 'r') as file: + filtered_data = [] + for doc in yaml.safe_load_all(file): + try: + for dict in doc["extracted_object"]["disease_cellular_process_relationships"]: + filtered_data.append(filter_dictionary(dict, ["subject", "predicate", "object"])) + except: + continue + +for entry in filtered_data: + if (len(entry) == 3 and + entry["subject"] not in NULL_VALS and + entry["predicate"] not in NULL_VALS and + entry["object"] not in NULL_VALS): + if (entry["subject"].startswith("MONDO:") and + entry["object"].startswith("GO:")): + entry["subject"] = get_adapter("sqlite:obo:MONDO").label(entry["subject"]) + # if entry["predicate"].startswith("RO:"): + # entry["predicate"] = get_adapter("sqlite:obo:RO").label(entry["predicate"]) + entry["object"] = get_adapter("sqlite:obo:GO").label(entry["object"]) + if entry["predicate"].startswith("RO:"): + entry["predicate"] = get_adapter("sqlite:obo:RO").label(entry["predicate"]) + print(entry) \ No newline at end of file diff --git a/src/ontogpt/cli.py b/src/ontogpt/cli.py index b9e8cfe91..3867df7f6 100644 --- a/src/ontogpt/cli.py +++ b/src/ontogpt/cli.py @@ -46,6 +46,7 @@ from ontogpt.io.csv_wrapper import output_parser, write_obj_as_csv from ontogpt.io.html_exporter import HTMLExporter from ontogpt.io.markdown_exporter import MarkdownExporter +from ontogpt.io.template_loader import get_template_details from ontogpt.utils.gene_set_utils import ( GeneSet, _is_human, @@ -63,6 +64,10 @@ from ontogpt.io.yaml_wrapper import dump_minimal_yaml from ontogpt.templates.core import ExtractionResult +from ontogpt.converters.output_filtered_triples import output_filtered_triples +# from ontogpt.converters.output_filtered_triples import edit_yaml +from ontogpt.converters.output_filtered_triples import read_template + @dataclass class Settings: @@ -312,12 +317,21 @@ def extract( elif inputfile and not Path(inputfile).exists(): raise FileNotFoundError(f"Cannot find input file {inputfile}") - if model_source == "OpenAI": - ke = SPIRESEngine(template=template, model=model_name, **kwargs) - if settings.cache_db: - ke.client.cache_db_path = settings.cache_db - if settings.skip_annotators: - ke.client.skip_annotators = settings.skip_annotators + if template: + template_details = get_template_details(template=template) + else: + raise ValueError("No template specified. Use -t/--template option.") + + ke = SPIRESEngine( + template_details=template_details, + model=selectmodel["alternative_names"][0], + model_source=selectmodel["provider"].lower(), + **kwargs, + ) + if settings.cache_db: + ke.client.cache_db_path = settings.cache_db + if settings.skip_annotators: + ke.client.skip_annotators = settings.skip_annotators elif model_source == "GPT4All": ke = GPT4AllEngine(template=template, model=model_name, **kwargs) @@ -357,14 +371,22 @@ def generate_extract(model, entity, template, output, output_format, show_prompt if not model: model = DEFAULT_MODEL selectmodel = get_model_by_name(model) - model_source = selectmodel["provider"] - if model_source == "OpenAI": - ke = SPIRESEngine(template, **kwargs) - if settings.cache_db: - ke.client.cache_db_path = settings.cache_db - if settings.skip_annotators: - ke.skip_annotators = settings.skip_annotators + if template: + template_details = get_template_details(template=template) + else: + raise ValueError("No template specified. Use -t/--template option.") + + ke = SPIRESEngine( + template_details=template_details, + model=selectmodel["alternative_names"][0], + model_source=selectmodel["provider"].lower(), + **kwargs, + ) + if settings.cache_db: + ke.client.cache_db_path = settings.cache_db + if settings.skip_annotators: + ke.skip_annotators = settings.skip_annotators elif model_source == "GPT4All": model_name = selectmodel["alternative_names"][0] @@ -413,14 +435,22 @@ def iteratively_generate_extract( if not model: model = DEFAULT_MODEL selectmodel = get_model_by_name(model) - model_source = selectmodel["provider"] - if model_source == "OpenAI": - ke = SPIRESEngine(template, **kwargs) - if settings.cache_db: - ke.client.cache_db_path = settings.cache_db - if settings.skip_annotators: - ke.skip_annotators = settings.skip_annotators + if template: + template_details = get_template_details(template=template) + else: + raise ValueError("No template specified. Use -t/--template option.") + + ke = SPIRESEngine( + template_details=template_details, + model=selectmodel["alternative_names"][0], + model_source=selectmodel["provider"].lower(), + **kwargs, + ) + if settings.cache_db: + ke.client.cache_db_path = settings.cache_db + if settings.skip_annotators: + ke.skip_annotators = settings.skip_annotators elif model_source == "GPT4All": model_name = selectmodel["alternative_names"][0] @@ -461,14 +491,22 @@ def pubmed_extract(model, pmid, template, output, output_format, get_pmc, show_p if not model: model = DEFAULT_MODEL selectmodel = get_model_by_name(model) - model_source = selectmodel["provider"] - if model_source == "OpenAI": - ke = SPIRESEngine(template, **kwargs) - if settings.cache_db: - ke.client.cache_db_path = settings.cache_db - if settings.skip_annotators: - ke.skip_annotators = settings.skip_annotators + if template: + template_details = get_template_details(template=template) + else: + raise ValueError("No template specified. Use -t/--template option.") + + ke = SPIRESEngine( + template_details=template_details, + model=selectmodel["alternative_names"][0], + model_source=selectmodel["provider"].lower(), + **kwargs, + ) + if settings.cache_db: + ke.client.cache_db_path = settings.cache_db + if settings.skip_annotators: + ke.skip_annotators = settings.skip_annotators elif model_source == "GPT4All": model_name = selectmodel["alternative_names"][0] @@ -518,14 +556,22 @@ def pubmed_annotate( if not model: model = DEFAULT_MODEL selectmodel = get_model_by_name(model) - model_source = selectmodel["provider"] - if model_source == "OpenAI": - ke = SPIRESEngine(template, **kwargs) - if settings.cache_db: - ke.client.cache_db_path = settings.cache_db - if settings.skip_annotators: - ke.skip_annotators = settings.skip_annotators + if template: + template_details = get_template_details(template=template) + else: + raise ValueError("No template specified. Use -t/--template option.") + + ke = SPIRESEngine( + template_details=template_details, + model=selectmodel["alternative_names"][0], + model_source=selectmodel["provider"].lower(), + **kwargs, + ) + if settings.cache_db: + ke.client.cache_db_path = settings.cache_db + if settings.skip_annotators: + ke.skip_annotators = settings.skip_annotators elif model_source == "GPT4All": model_name = selectmodel["alternative_names"][0] @@ -559,14 +605,22 @@ def wikipedia_extract(model, article, template, output, output_format, show_prom if not model: model = DEFAULT_MODEL selectmodel = get_model_by_name(model) - model_source = selectmodel["provider"] - if model_source == "OpenAI": - ke = SPIRESEngine(template=template, model=model, **kwargs) - if settings.cache_db: - ke.client.cache_db_path = settings.cache_db - if settings.skip_annotators: - ke.skip_annotators = settings.skip_annotators + if template: + template_details = get_template_details(template=template) + else: + raise ValueError("No template specified. Use -t/--template option.") + + ke = SPIRESEngine( + template_details=template_details, + model=selectmodel["alternative_names"][0], + model_source=selectmodel["provider"].lower(), + **kwargs, + ) + if settings.cache_db: + ke.client.cache_db_path = settings.cache_db + if settings.skip_annotators: + ke.skip_annotators = settings.skip_annotators elif model_source == "GPT4All": model_name = selectmodel["alternative_names"][0] @@ -600,14 +654,18 @@ def wikipedia_search(model, topic, keyword, template, output, output_format, sho if not model: model = DEFAULT_MODEL selectmodel = get_model_by_name(model) - model_source = selectmodel["provider"] - if model_source == "OpenAI": - ke = SPIRESEngine(template=template, model=model, **kwargs) + if template: + template_details = get_template_details(template=template) + else: + raise ValueError("No template specified. Use -t/--template option.") - elif model_source == "GPT4All": - model_name = selectmodel["alternative_names"][0] - ke = GPT4AllEngine(template=template, model=model_name, **kwargs) + ke = SPIRESEngine( + template_details=template_details, + model=selectmodel["alternative_names"][0], + model_source=selectmodel["provider"].lower(), + **kwargs, + ) logging.info(f"Creating for {template} => {topic}") client = WikipediaClient() @@ -652,14 +710,18 @@ def search_and_extract( if not model: model = DEFAULT_MODEL selectmodel = get_model_by_name(model) - model_source = selectmodel["provider"] - if model_source == "OpenAI": - ke = SPIRESEngine(template, **kwargs) + if template: + template_details = get_template_details(template=template) + else: + raise ValueError("No template specified. Use -t/--template option.") - elif model_source == "GPT4All": - model_name = selectmodel["alternative_names"][0] - ke = GPT4AllEngine(template=template, model=model_name, **kwargs) + ke = SPIRESEngine( + template_details=template_details, + model=selectmodel["alternative_names"][0], + model_source=selectmodel["provider"].lower(), + **kwargs, + ) term = " ".join(term_tokens) logging.info(f"Creating for {template}; search={term} kw={keyword}") @@ -698,14 +760,22 @@ def web_extract(model, template, url, output, output_format, show_prompt, **kwar if not model: model = DEFAULT_MODEL selectmodel = get_model_by_name(model) - model_source = selectmodel["provider"] - if model_source == "OpenAI": - ke = SPIRESEngine(template=template, model=model, **kwargs) - if settings.cache_db: - ke.client.cache_db_path = settings.cache_db - if settings.skip_annotators: - ke.skip_annotators = settings.skip_annotators + if template: + template_details = get_template_details(template=template) + else: + raise ValueError("No template specified. Use -t/--template option.") + + ke = SPIRESEngine( + template_details=template_details, + model=selectmodel["alternative_names"][0], + model_source=selectmodel["provider"].lower(), + **kwargs, + ) + if settings.cache_db: + ke.client.cache_db_path = settings.cache_db + if settings.skip_annotators: + ke.skip_annotators = settings.skip_annotators elif model_source == "GPT4All": model_name = selectmodel["alternative_names"][0] @@ -748,14 +818,22 @@ def recipe_extract( if not model: model = DEFAULT_MODEL selectmodel = get_model_by_name(model) - model_source = selectmodel["provider"] - if model_source == "OpenAI": - ke = SPIRESEngine(template, **kwargs) - if settings.cache_db: - ke.client.cache_db_path = settings.cache_db - if settings.skip_annotators: - ke.skip_annotators = settings.skip_annotators + if template: + template_details = get_template_details(template=template) + else: + raise ValueError("No template specified. Use -t/--template option.") + + ke = SPIRESEngine( + template_details=template_details, + model=selectmodel["alternative_names"][0], + model_source=selectmodel["provider"].lower(), + **kwargs, + ) + if settings.cache_db: + ke.client.cache_db_path = settings.cache_db + if settings.skip_annotators: + ke.skip_annotators = settings.skip_annotators elif model_source == "GPT4All": model_name = selectmodel["alternative_names"][0] @@ -800,14 +878,18 @@ def convert(model, template, input, output, output_format, **kwargs): if not model: model = DEFAULT_MODEL selectmodel = get_model_by_name(model) - model_source = selectmodel["provider"] - if model_source == "OpenAI": - ke = SPIRESEngine(template, **kwargs) + if template: + template_details = get_template_details(template=template) + else: + raise ValueError("No template specified. Use -t/--template option.") - elif model_source == "GPT4All": - model_name = selectmodel["alternative_names"][0] - ke = GPT4AllEngine(template=template, model=model_name, **kwargs) + ke = SPIRESEngine( + template_details=template_details, + model=selectmodel["alternative_names"][0], + model_source=selectmodel["provider"].lower(), + **kwargs, + ) cls = ke.template_pyclass with open(input, "r") as f: @@ -1464,7 +1546,7 @@ def eval_enrichment(genes, input_file, number_to_drop, annotations_path, model, default=False, show_default=True, help="If set, chunk input text, then prepare a separate prompt for each chunk." - " Otherwise the full input text is passed.", + " Otherwise the full input text is passed.", ) @click.argument("evaluator") def eval(evaluator, num_tests, output, chunking, model, **kwargs): @@ -1477,10 +1559,9 @@ def eval(evaluator, num_tests, output, chunking, model, **kwargs): else: modelname = DEFAULT_MODEL - evaluator = create_evaluator(name=evaluator, - num_tests=num_tests, - chunking=chunking, - model=modelname) + evaluator = create_evaluator( + name=evaluator, num_tests=num_tests, chunking=chunking, model=modelname + ) eos = evaluator.eval() output.write(dump_minimal_yaml(eos, minimize=False)) @@ -1504,13 +1585,18 @@ def fill(model, template, object: str, examples, output, output_format, show_pro if not model: model = DEFAULT_MODEL selectmodel = get_model_by_name(model) - model_source = selectmodel["provider"] - if model_source == "OpenAI": - ke = SPIRESEngine(template=template, **kwargs) + if template: + template_details = get_template_details(template=template) else: - model_name = selectmodel["alternative_names"][0] - ke = GPT4AllEngine(template=template, model=model_name, **kwargs) + raise ValueError("No template specified. Use -t/--template option.") + + ke = SPIRESEngine( + template_details=template_details, + model=selectmodel["alternative_names"][0], + model_source=selectmodel["provider"].lower(), + **kwargs, + ) object = yaml.safe_load(object) logging.info(f"Object to fill = {object}") @@ -1562,8 +1648,13 @@ def complete(model, input, output, output_format, show_prompt, **kwargs): @click.option("--input", "-i", type=click.File("r"), default=sys.stdin, help="Input file") def parse(template, input): """Parse OpenAI results.""" - logging.info(f"Creating for {template}") - ke = SPIRESEngine(template) + + if template: + template_details = get_template_details(template=template) + else: + raise ValueError("No template specified. Use -t/--template option.") + + ke = SPIRESEngine(template_details=template_details) text = input.read() logging.debug(f"Input text: {text}") # ke.annotator = BioPortalImplementation() @@ -1697,6 +1788,103 @@ def clinical_notes( output.write(results) +@main.command() +@click.option("-i", "--input", help="Input file.") +@click.option("-o", "--output", help="Output file.") +@click.option("--subject-prefix", default = "MONDO", help="Prefix for subject.") +@click.option("--object-prefix", default = "GO", help="Prefix for object.") +@click.option("--pred-prefix", default = "RO", help="Prefix for predicate.") +def get_triples(input, output, subject_prefix, object_prefix, pred_prefix): + """Filter YAML format extraction output to s, p, o triples. + + Example: + + ontogpt get-triples -i extracted.yaml -o extracted.tsv --subject-prefix MONDO --object-prefix GO --pred-prefix RO + + """ + triples = output_filtered_triples(input, subject_prefix, object_prefix, pred_prefix) + + with open(output, "w") as file: + file.write("Subject\tPredicate\tObject\n") + for triple in triples: + file.write("\t".join(triple.values())) + file.write("\n") + +@main.command() +@template_option +@prompt_template_option +@model_option +@recurse_option +@output_option_wb +@output_format_options +@show_prompt_option +@click.option( + "--limit", + default=20, + help="Total number of citation records to return.", +) +@click.option( + "--get-pmc/--no-get-pmc", + default=False, + help="Attempt to parse PubMed Central full text(s) instead of abstract(s) alone.", +) +# @click.option("--subject-prefix", default = "MONDO", help="Prefix for subject.") +# @click.option("--object-prefix", default = "GO", help="Prefix for object.") +# @click.option("--pred-prefix", default = "RO", help="Prefix for predicate.") +@click.option("--subject-prefix", default = None, help = "Prefix for subject.") +@click.option("--object-prefix", default = None, help = "Prefix for object.") +@click.option("--pred-prefix", default = None, help = "Prefix for predicate.") +@click.argument("search") +def pubmed_annotate_template_alter( + model, search, template, prompt_template, output, output_format, limit, get_pmc, show_prompt, subject_prefix, object_prefix, pred_prefix, **kwargs +): + """Retrieve a collection of PubMed IDs for a search term; annotate them using a template. + + Example: + ontogpt pubmed-annotate-template-alter -t ibd_literature + --prompt-template src/ontogpt/templates/ibd_literature.yaml "inflammatory bowel disease" + --limit 2000 -o output.yaml -O yaml --subject-prefix CHEBI --object-prefix GO --pred-prefix RO + + """ + + contents = read_template(prompt_template, subject_prefix, object_prefix, pred_prefix) + + pubmed_annotate(model, search, contents, output, output_format, limit, get_pmc, show_prompt) + + """logging.info(f"Creating for {template}") + + edit_yaml(template, subject_prefix, object_prefix, pred_prefix) + + if not model: + model = DEFAULT_MODEL + selectmodel = get_model_by_name(model) + model_source = selectmodel["provider"] + + if model_source == "OpenAI": + ke = SPIRESEngine(template, **kwargs) + if settings.cache_db: + ke.client.cache_db_path = settings.cache_db + if settings.skip_annotators: + ke.skip_annotators = settings.skip_annotators + + elif model_source == "GPT4All": + model_name = selectmodel["alternative_names"][0] + ke = GPT4AllEngine(template=template, model=model_name, **kwargs) + + pubmed_annotate_limit = limit + pmc = PubmedClient() + pmids = pmc.get_pmids(search) + if get_pmc: + logging.info("Will try to retrieve PubMed Central texts.") + textlist = pmc.text(pmids[: pubmed_annotate_limit + 1], pubmedcental=True) + else: + textlist = pmc.text(pmids[: pubmed_annotate_limit + 1]) + for text in textlist: + logging.debug(f"Input text: {text}") + results = ke.extract_from_text(text=text, show_prompt=show_prompt) + write_extraction(results, output, output_format, ke)""" + + @main.command() def list_templates(): """List the templates.""" diff --git a/src/ontogpt/converters/output_filtered_triples.py b/src/ontogpt/converters/output_filtered_triples.py new file mode 100644 index 000000000..62e786da5 --- /dev/null +++ b/src/ontogpt/converters/output_filtered_triples.py @@ -0,0 +1,86 @@ +import yaml +from yaml import CLoader as Loader +from oaklib import get_adapter + +NULL_VALS = [ + "", + "Not mentioned", + "none mentioned", + "Not mentioned in the text", + "Not mentioned in the provided text.", + "No exposures mentioned in the text.", + "None", + "N/A", + "No exposures mentioned in the text.", + "None mentioned in the text", + "Not mentioned in the text.", + "None relevant", + "None mentioned in the text.", + "No gene to molecular activity relationships mentioned in the text.", + "No genes mentioned", + "No genes mentioned in the text.", + "NA", + "-", + "None mentioned", +] + +def edit_yaml(template, subject_prefix, object_prefix, pred_prefix): + def object_based_add(prefix, isAnnotator): + if isAnnotator: + if isinstance(prefix, str): + return "sqlite:obo:" + prefix.lower() + elif isinstance(prefix, list): + prefix_full = ["sqlite:obo:" + pf.lower() for pf in prefix] + return ", ".join(prefix_full) + else: + if isinstance(prefix, str): + return [prefix] + elif isinstance(prefix, list): + return prefix + + with open(template, "r") as file: + contents = yaml.safe_load(file) + contents["classes"]["Disease"]["id_prefixes"] = object_based_add(subject_prefix, False) + contents["classes"]["Disease"]["annotations"]["annotators"] = object_based_add(subject_prefix, True) + contents["classes"]["CellularProcess"]["id_prefixes"] = object_based_add(object_prefix, False) + contents["classes"]["CellularProcess"]["annotations"]["annotators"] = object_based_add(object_prefix, True) + contents["classes"]["DiseaseToCellularProcessPredicate"]["id_prefixes"] = object_based_add(pred_prefix, False) + contents["classes"]["DiseaseToCellularProcessPredicate"]["annotations"]["annotators"] = object_based_add(pred_prefix, True) + + with open(template, "w") as file: + yaml.dump(contents, file, sort_keys = False) + +def output_filtered_triples(input_file, subject_prefix, object_prefix, pred_prefix): + filtered_data = [] + + def filter_dictionary(input_dict, filter_keys): + filtered_dict = {key: value for key, value in input_dict.items() if key in filter_keys} + return filtered_dict + + # TODO: + # 0. Don't need to call get_adapter every time - just once is fine for each annotator + # 1. This does not handle situations where the subject or object or predicate is a list of values + # 2. This does not handle situations where any of the above are None (as in, not specified) + # 3. This does not handle situations where the input triples may be missing s, p, or o + # 4. This does not allow us to not label s, p, or o + # 5. This makes the assumption that the adapter is the same as the prefix + with open(input_file, "r") as file: + for doc in yaml.safe_load_all(file): + try: + for dict in doc["extracted_object"]["disease_cellular_process_relationships"]: + entry = filter_dictionary(dict, ["subject", "predicate", "object"]) + if (len(entry) == 3 + and entry["subject"] not in NULL_VALS + and entry["predicate"] not in NULL_VALS + and entry["object"] not in NULL_VALS + ): + if entry["subject"].startswith(f"{subject_prefix}:") and entry["object"].startswith(f"{object_prefix}:"): + entry["subject"] = get_adapter(f"sqlite:obo:{subject_prefix}").label(entry["subject"]) + entry["object"] = get_adapter(f"sqlite:obo:{object_prefix}").label(entry["object"]) + if entry["predicate"].startswith(f"{pred_prefix}:"): + entry["predicate"] = get_adapter(f"sqlite:obo:{pred_prefix}").label(entry["predicate"]) + filtered_data.append(entry) + except: + continue + + return filtered_data diff --git a/src/ontogpt/engines/knowledge_engine.py b/src/ontogpt/engines/knowledge_engine.py index cb6da8e74..47dd41036 100644 --- a/src/ontogpt/engines/knowledge_engine.py +++ b/src/ontogpt/engines/knowledge_engine.py @@ -81,9 +81,9 @@ class KnowledgeEngine(ABC): knowledge sources plus LLMs """ - template: TEMPLATE_NAME = "" - """LinkML Template to use for this engine. - Must be of the form .""" + template_details: tuple + """Tuple containing loaded template details, including: + (LinkML class, module, python class, SchemaView object)""" template_class: ClassDefinition = None """LinkML Class for the template. @@ -152,8 +152,13 @@ class KnowledgeEngine(ABC): encoding = None def __post_init__(self): - if self.template: - self.template_class = self._get_template_class(self.template) + if self.template_details: + ( + self.template_class, + self.template_module, + self.template_pyclass, + self.schemaview, + ) = self.template_details if self.template_class: logging.info(f"Using template {self.template_class.name}") if not self.model: diff --git a/src/ontogpt/templates/ibd_literature_test.yaml b/src/ontogpt/templates/ibd_literature_test.yaml new file mode 100644 index 000000000..5020680ef --- /dev/null +++ b/src/ontogpt/templates/ibd_literature_test.yaml @@ -0,0 +1,76 @@ +id: http://w3id.org/ontogpt/ibd_literature +name: ibd-literature-template +title: IBD Literature Template +description: A template for extracting information from IBD literature +license: https://creativecommons.org/publicdomain/zero/1.0/ +prefixes: + CHEBI: http://purl.obolibrary.org/obo/CHEBI_ + ECTO: http://purl.obolibrary.org/obo/ECTO_ + ExO: http://purl.obolibrary.org/obo/ExO_ + HGNC: http://identifiers.org/hgnc/ + NCIT: http://purl.obolibrary.org/obo/NCIT_ + MONDO: http://purl.obolibrary.org/obo/MONDO_ + GO: http://purl.obolibrary.org/obo/GO_ + core: http://w3id.org/ontogpt/core/ + ibdlit: http://w3id.org/ontogpt/ibd_literature/ + linkml: https://w3id.org/linkml/ +default_prefix: ibdlit +default_range: string +imports: +- linkml:types +- core +classes: + IBDAnnotations: + tree_root: true + attributes: + diseases: + description: semicolon-separated list of diseases + multivalued: true + range: Disease + cellular_process: + description: semicolon-separated list of cellular processes + multivalued: true + range: CellularProcess + disease_cellular_process_relationships: + description: semicolon-separated list of disease to cellular process relationships + multivalued: true + range: DiseaseCellularProcessRelationship + Disease: + is_a: NamedEntity + id_prefixes: + - MONDO + annotations: + annotators: sqlite:obo:mondo + prompt: the name of the disease + CellularProcess: + is_a: NamedEntity + id_prefixes: + - GO + annotations: + annotators: sqlite:obo:go + prompt: the name of the cellular process + DiseaseToCellularProcessPredicate: + is_a: NamedEntity + id_prefixes: + - RO + annotations: + annotators: sqlite:obo:ro + prompt: the name of the type of relationship between a disease and a cellular + process. + DiseaseCellularProcessRelationship: + is_a: CompoundExpression + attributes: + subject: + range: Disease + description: The name of the disease. + predicate: + range: DiseaseToCellularProcessPredicate + description: The name of the type of relationship between a disease and a + cellular process. + object: + range: CellularProcess + description: The name of the cellular process. + subject_qualifier: + range: NamedEntity + object_qualifier: + range: NamedEntity