Skip to content

Commit

Permalink
various
Browse files Browse the repository at this point in the history
  • Loading branch information
holmrenser committed May 23, 2024
1 parent bd2571b commit 4924057
Show file tree
Hide file tree
Showing 14 changed files with 2,893 additions and 1,978 deletions.
8 changes: 0 additions & 8 deletions .flake8

This file was deleted.

8 changes: 4 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ jobs:
fail-fast: false
max-parallel: 2
matrix:
python-version: ["3.8", "3.9", "3.10"]
poetry-version: ["1.2.0a2"]
python-version: ["3.8", "3.9", "3.10", "3.11"]
poetry-version: ["1.8.3"]
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
Expand All @@ -25,8 +25,8 @@ jobs:
poetry-version: ${{ matrix.poetry-version }}
- name: Poetry install
run: poetry install
- name: Lint with flake8
run: poetry run flake8
- name: Lint with ruff
run: poetry run ruff check
- name: Run test and report coverage with pytest/coverage/coveralls
env:
COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
- name: Set up poetry
uses: abatilo/[email protected]
with:
poetry-version: "1.2.0a2"
poetry-version: "1.8.3"

- name: Poetry install
run: poetry install
Expand Down
1 change: 1 addition & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
Deploying to pypi:

```
poetry check
poetry version <major,minor,patch>
poetry run coverage run
poetry run coverage report
Expand Down
47 changes: 39 additions & 8 deletions docs/examples/ontology.ipynb → docs/examples/ontology.pct.ipynb
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "31d1a617-74a2-4af1-a450-4b60382d70c6",
"metadata": {},
"source": [
"This notebook shows how to work with biological ontologies such as the sequence ontology or the gene ontology."
]
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": 2,
"id": "fa531cea-9719-4b3e-81bf-3e37a610f9a1",
"metadata": {},
"outputs": [
Expand All @@ -12,12 +20,13 @@
"'0.0.23_alpha'"
]
},
"execution_count": 5,
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import requests\n",
"import sys\n",
"sys.path.insert(0, '../../')\n",
"import picea\n",
Expand All @@ -26,13 +35,28 @@
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": 4,
"id": "22fc23c9-f231-4b72-81bf-2e2b813ead84",
"metadata": {},
"outputs": [],
"outputs": [
{
"data": {
"text/plain": [
"<Response [200]>"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import requests\n",
"r = requests.get('https://raw.githubusercontent.com/The-Sequence-Ontology/SO-Ontologies/master/Ontology_Files/so.obo')"
"obo_url = (\n",
" 'https://raw.githubusercontent.com/The-Sequence-Ontology/'\n",
" 'SO-Ontologies/master/Ontology_Files/so.obo'\n",
")\n",
"r = requests.get(obo_url)\n",
"r"
]
},
{
Expand Down Expand Up @@ -1994,6 +2018,9 @@
}
],
"metadata": {
"jupytext": {
"formats": "ipynb,py:percent"
},
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
Expand All @@ -2009,8 +2036,12 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.9"
}
"version": "3.10.8"
},
"toc-autonumbering": false,
"toc-showcode": false,
"toc-showmarkdowntxt": false,
"toc-showtags": true
},
"nbformat": 4,
"nbformat_minor": 5
Expand Down
107 changes: 107 additions & 0 deletions docs/examples/ontology.pct.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# ---
# jupyter:
# jupytext:
# formats: ipynb,py:percent
# text_representation:
# extension: .py
# format_name: percent
# format_version: '1.3'
# jupytext_version: 1.14.1
# kernelspec:
# display_name: Python 3 (ipykernel)
# language: python
# name: python3
# ---

# %% [markdown]
# This notebook shows how to work with biological ontologies such as the sequence ontology or the gene ontology.

# %%
import sys

import requests

sys.path.insert(0, '../../')
import picea

picea.__version__

# %%
obo_url = (
'https://raw.githubusercontent.com/The-Sequence-Ontology/'
'SO-Ontologies/master/Ontology_Files/so.obo'
)
r = requests.get(obo_url)
r

# %% tags=[]
r.text.split('\n')[:100]

# %%
so = picea.Ontology.from_obo(string=r.text)

# %%
ids = [el.ID for el in so['SO:0000866'].parents.elements]

# %%
'SO:0000866' in {el.ID for so_id in ids for el in so[so_id].children.elements}

# %%
len(so)

# %%
url = 'http://purl.obolibrary.org/obo/go.obo'
# url = 'http://purl.obolibrary.org/obo/go/go-basic.obo'
r = requests.get(url)
go = picea.Ontology.from_obo(string=r.text)
len(go.elements)

# %%
[(term.ID, term.name, len(term.parents)) for term in go['GO:0048316'].parents]

# %%
go['GO:0048316'].children

# %%
import networkx as nx

nx.__version__

# %%
graph = nx.DiGraph()
for term in [go['GO:0048316'], *go['GO:0048316'].children]:
graph.add_node(term.ID, name=term.name)
for child_ID in term._children:
graph.add_edge(term.ID, child_ID)
layout = nx.planar_layout(graph)
nx.draw(graph, pos=layout, node_shape='s')

# %%
import sys

# !{sys.executable} -m pip install pygraphviz
nx.nx_agraph.to_agraph(graph)

# %%
[(term.ID, term.name) for term in go['GO:0048316'].children]

# %%
go['GO:0010431'].__dict__

# %%
go['GO:0048316'].__dict__

# %%
go['GO:0048316'].children._elements.keys()

# %% tags=[]
[(term.ID,term.name) for term in go if term.__dict__.get('alt_id') and term._parents]

# %%
[(term.ID,term.name) for term in go if not term.parents and term.children]

# %%
go['GO:0005554'].__dict__

# %%
go['GO:0003674'].__dict__
1 change: 0 additions & 1 deletion mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ theme:
nav:
- Overview:
- Overview: index.md
- About: README.md
- License: LICENSE.md
- Contributing: CONTRIBUTING.md
- Examples:
Expand Down
58 changes: 46 additions & 12 deletions picea/dag.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
from warnings import warn
from abc import ABCMeta
from typing import Optional, List, Iterable, Dict, DefaultDict, Callable
"""Direct Acyclic Graphs"""
from collections import defaultdict
from copy import deepcopy
from typing import Callable, DefaultDict, Dict, Hashable, Iterable, List, Optional
from warnings import warn


class DAGElement(metaclass=ABCMeta):
class DAGElement:
"""
Element in a DAG, intended to be used as BaseClass
"""
def __init__(
self,
ID: str,
Expand Down Expand Up @@ -97,14 +100,14 @@ def _traverse(


class DirectedAcyclicGraph:
""""Base DAG class"""
def __init__(self) -> None:
"""[summary]"""
self._elements: Dict[str, DAGElement] = dict()
self._elements: Dict[Hashable, DAGElement] = dict()

def __getitem__(self, ID: str) -> DAGElement:
def __getitem__(self, ID: Hashable) -> DAGElement:
return self._elements[ID]

def __setitem__(self, ID: str, element: DAGElement) -> None:
def __setitem__(self, ID: Hashable, element: DAGElement) -> None:
if ID in self._elements:
warn(f"Turning duplicate ID {ID} into unique ID")
element._original_ID = ID
Expand Down Expand Up @@ -136,17 +139,48 @@ def elements(self) -> List[DAGElement]:
def add(self, element: DAGElement) -> None:
self[element.ID] = element

def pop(self, ID: str) -> DAGElement:
def pop(self, ID: Hashable) -> DAGElement:
return self._elements.pop(ID)

def groupby(self, group_key) -> DefaultDict[str, "DirectedAcyclicGraph"]:
def groupby(
self,
group_func: Callable[[DAGElement], Hashable]
) -> DefaultDict[Hashable, "DirectedAcyclicGraph"]:
"""
Group elements in the current collection by calling 'group_func' and using \
the results as a dictionary key
Args:
group_func: Callable[[DagElement], Hashable] receives as input an element \
of the current collection and should return something that can be used \
as a dictionary key (i.e. it should be hashable)
Returns:
Dictionary with keys for groups and values individual DirectedAcyclicGraph \
subclasses
"""
grouped = defaultdict(self.__class__)
for interval in self:
grouped[interval[group_key]][interval.ID] = interval
grouped[group_func(interval)][interval.ID] = interval
interval._container = self
return grouped

def filter(self, filter_func: Callable) -> "DirectedAcyclicGraph":
def filter(
self,
filter_func: Callable[[DAGElement], bool]
) -> "DirectedAcyclicGraph":
"""
Filter elements in the current collection based on the output of filter_func
Args:
filter_func: Callable[[DagElement], bool] receives as input an element \
of the current collection and returns a boolean indicating whether the \
element should be kept (i.e. an element with a 'True' return value will\
be kept)
Returns:
DirectedAcyclicGraph subclass with unwanted elements removed
"""
result = self.__class__()
for interval in self:
if filter_func(interval):
Expand Down
9 changes: 5 additions & 4 deletions picea/ontology.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from typing import List
from itertools import groupby
from collections import defaultdict
import warnings
from .dag import DirectedAcyclicGraph, DAGElement
from collections import defaultdict
from itertools import groupby
from typing import List

from .dag import DAGElement, DirectedAcyclicGraph


class OntologyTerm(DAGElement):
Expand Down
Loading

0 comments on commit 4924057

Please sign in to comment.