Skip to content

Commit

Permalink
add tool identifier from bio.tools and intput and output ontologies
Browse files Browse the repository at this point in the history
  • Loading branch information
mirpedrol committed Jun 21, 2024
1 parent 7f8a35d commit afd2edc
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 6 deletions.
27 changes: 27 additions & 0 deletions nf_core/components/components_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from typing import List, Optional, Tuple

import questionary
import requests
import rich.prompt

import nf_core.utils
Expand Down Expand Up @@ -152,3 +153,29 @@ def get_components_to_install(subworkflow_dir: str) -> Tuple[List[str], List[str
elif link.startswith("../"):
subworkflows.append(name.lower())
return modules, subworkflows


def get_biotools_id(tool_name) -> str:
"""
Try to find a bio.tools ID for 'tool'
"""
url = f"https://bio.tools/api/t/?q={tool_name}&format=json"
try:
# Send a GET request to the API
response = requests.get(url)
response.raise_for_status() # Raise an error for bad status codes
# Parse the JSON response
data = response.json()

# Iterate through the tools in the response to find the tool name
for tool in data["list"]:
if tool["name"].lower() == tool_name:
return tool["biotoolsCURIE"]

# If the tool name was not found in the response
log.warning(f"Could not find a bio.tools ID for '{tool_name}'")
return ""

except requests.exceptions.RequestException as e:
log.warning(f"Could not find a bio.tools ID for '{tool_name}': {e}")
return ""
4 changes: 4 additions & 0 deletions nf_core/components/create.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import nf_core
import nf_core.utils
from nf_core.components.components_command import ComponentCommand
from nf_core.components.components_utils import get_biotools_id
from nf_core.lint_utils import run_prettier_on_file

log = logging.getLogger(__name__)
Expand Down Expand Up @@ -60,6 +61,7 @@ def __init__(
self.file_paths: Dict[str, Path] = {}
self.not_empty_template = not empty_template
self.migrate_pytest = migrate_pytest
self.tool_identifier = ""

def create(self):
"""
Expand Down Expand Up @@ -150,6 +152,8 @@ def create(self):
if self.component_type == "modules":
# Try to find a bioconda package for 'component'
self._get_bioconda_tool()
# Try to find a biotools entry for 'component'
self.tool_identifier = get_biotools_id(self.component)

# Prompt for GitHub username
self._get_username()
Expand Down
19 changes: 18 additions & 1 deletion nf_core/module-template/meta.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ tools:
tool_dev_url: "{{ tool_dev_url }}"
doi: ""
licence: {{ tool_licence }}
identifier: {{ tool_identifier }}

{% if not_empty_template -%}
## TODO nf-core: Add a description of all of the variables used as input
Expand All @@ -39,6 +40,14 @@ input:
type: file
description: {{ 'Sorted BAM/CRAM/SAM file' if not_empty_template else "" }}
pattern: {{ '"*.{bam,cram,sam}"' if not_empty_template else "" }}
ontologies:
{% if not_empty_template -%}
- edam: "http://edamontology.org/format_25722"
- edam: "http://edamontology.org/format_2573"
- edam: "http://edamontology.org/format_3462"
{% else %}
- edam: ""
{%- endif %}

{% if not_empty_template -%}
## TODO nf-core: Add a description of all of the variables used as output
Expand All @@ -56,14 +65,22 @@ output:
description: |
Groovy Map containing sample information
e.g. `[ id:'sample1', single_end:false ]`
{% endif %}
{%- endif %}
{% if not_empty_template -%}
## TODO nf-core: Delete / customise this example output
{%- endif %}
- {{ '"*.bam":' if not_empty_template else '"*":' }}
type: file
description: {{ 'Sorted BAM/CRAM/SAM file' if not_empty_template else "" }}
pattern: {{ '"*.{bam,cram,sam}"' if not_empty_template else "" }}
ontologies:
{% if not_empty_template -%}
- edam: "http://edamontology.org/format_25722"
- edam: "http://edamontology.org/format_2573"
- edam: "http://edamontology.org/format_3462"
{% else -%}
- edam: ""
{%- endif %}

authors:
- "{{ author }}"
Expand Down
15 changes: 13 additions & 2 deletions nf_core/modules/lint/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@

import questionary
import rich
import yaml
import ruamel.yaml

import nf_core.modules.modules_utils
import nf_core.utils
from nf_core.components.components_utils import get_biotools_id
from nf_core.components.lint import ComponentLint, LintExceptionError, LintResult
from nf_core.lint_utils import console

Expand Down Expand Up @@ -253,6 +254,8 @@ def update_meta_yml_file(self, mod):
"""
meta_yml = self.read_meta_yml(mod)
corrected_meta_yml = meta_yml.copy()
yaml = ruamel.yaml.YAML()
yaml.preserve_quotes = True

# Obtain inputs and outputs from main.nf and meta.yml
# Used to compare only the structure of channels and elements
Expand Down Expand Up @@ -332,6 +335,14 @@ def update_meta_yml_file(self, mod):
)
break

# Add bio.tools identifier
for i, tool in enumerate(corrected_meta_yml["tools"]):
tool_name = list(tool.keys())[0]
if "identifier" not in tool[tool_name]:
corrected_meta_yml["tools"][i][tool_name]["identifier"] = get_biotools_id(
mod.component_name if "/" not in mod.component_name else mod.component_name.split("/")[0]
)

with open(mod.meta_yml, "w") as fh:
log.info(f"Updating {mod.meta_yml}")
yaml.dump(corrected_meta_yml, fh, sort_keys=False, Dumper=nf_core.utils.custom_yaml_dumper())
yaml.dump(corrected_meta_yml, fh)
8 changes: 5 additions & 3 deletions nf_core/modules/lint/meta_yml.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from pathlib import Path
from typing import Union

import yaml
import ruamel.yaml
from jsonschema import exceptions, validators

from nf_core.components.lint import ComponentLint
Expand Down Expand Up @@ -173,6 +173,8 @@ def read_meta_yml(module_lint_object: ComponentLint, module: NFCoreComponent) ->
dict: The `meta.yml` file as a dictionary
"""
meta_yaml = None
yaml = ruamel.yaml.YAML()
yaml.preserve_quotes = True
# Check if we have a patch file, get original file in that case
if module.is_patched:
lines = ModulesDiffer.try_apply_patch(
Expand All @@ -183,11 +185,11 @@ def read_meta_yml(module_lint_object: ComponentLint, module: NFCoreComponent) ->
reverse=True,
).get("meta.yml")
if lines is not None:
meta_yaml = yaml.safe_load("".join(lines))
meta_yaml = yaml.load("".join(lines))
if meta_yaml is None:
try:
with open(module.meta_yml) as fh:
meta_yaml = yaml.safe_load(fh)
meta_yaml = yaml.load(fh)
except FileNotFoundError:
return None
return meta_yaml
Expand Down

0 comments on commit afd2edc

Please sign in to comment.