From 6f780148e2aa032ff6051fe2a00e2d9a74b8a5cd Mon Sep 17 00:00:00 2001 From: Celine Mercier Date: Fri, 14 Apr 2017 16:20:30 +0200 Subject: [PATCH] Cython API: added taxonomy API --- python/obitools3/dms/taxo/taxo.pxd | 19 ++++ python/obitools3/dms/taxo/taxo.pyx | 136 +++++++++++++++++++++++++++++ 2 files changed, 155 insertions(+) create mode 100644 python/obitools3/dms/taxo/taxo.pxd create mode 100644 python/obitools3/dms/taxo/taxo.pyx diff --git a/python/obitools3/dms/taxo/taxo.pxd b/python/obitools3/dms/taxo/taxo.pxd new file mode 100644 index 0000000..45ae0ed --- /dev/null +++ b/python/obitools3/dms/taxo/taxo.pxd @@ -0,0 +1,19 @@ +#cython: language_level=3 + +from ..capi.obitaxonomy cimport ecotx_t, OBIDMS_taxonomy_p + +from ..dms cimport DMS + + +cdef class OBI_Taxonomy : + cdef str _name + cdef OBIDMS_taxonomy_p _pointer + cdef OBIDMS _dms + + cpdef write(self, str prefix) + cpdef int add_taxon(self, str name, str rank_name, int parent_taxid, int min_taxid=*) + cpdef close(self) + +cdef class OBI_Taxon : + cdef ecotx_t* _pointer + cdef OBI_Taxonomy _tax \ No newline at end of file diff --git a/python/obitools3/dms/taxo/taxo.pyx b/python/obitools3/dms/taxo/taxo.pyx new file mode 100644 index 0000000..d11711b --- /dev/null +++ b/python/obitools3/dms/taxo/taxo.pyx @@ -0,0 +1,136 @@ +#cython: language_level=3 + +from obitools3.utils cimport str2bytes, bytes2str, tobytes + +from ..capi.obitaxonomy cimport obi_read_taxonomy, \ + obi_read_taxdump, \ + obi_write_taxonomy, \ + obi_close_taxonomy, \ + obi_taxo_get_taxon_with_taxid, \ + obi_taxo_add_local_taxon, \ + obi_taxo_add_preferred_name_with_taxon, \ + ecotx_t + +from cpython.pycapsule cimport PyCapsule_New, PyCapsule_GetPointer + + +cdef class OBI_Taxonomy : + # TODO function to import taxonomy? + def __init__(self, OBIDMS dms, str name, bint taxdump=False) : + + self._dms = dms + self._name = name + if taxdump : + self._pointer = obi_read_taxdump(tobytes(name)) + else : + self._pointer = obi_read_taxonomy(dms._pointer, tobytes(name), True) # TODO discuss + # TODO if not found in DMS, try to import? + + + def __getitem__(self, object ref): + + cdef ecotx_t* taxon_p + cdef object taxon_capsule + + if type(ref) == int : + taxon_p = obi_taxo_get_taxon_with_taxid(self._pointer, ref) + if taxon_p == NULL : + raise Exception("Taxon not found") + taxon_capsule = PyCapsule_New(taxon_p, NULL, NULL) + return OBI_Taxon(taxon_capsule, self) + else : + raise Exception("Not implemented") + + + def __iter__(self): + + cdef ecotx_t* taxa + cdef ecotx_t* taxon_p + cdef object taxon_capsule + cdef int t + + taxa = self._pointer.taxa.taxon + + # Yield each taxid + for t in range(self._pointer.taxa.count): + taxon_p = (taxa+t) + taxon_capsule = PyCapsule_New(taxon_p, NULL, NULL) + yield OBI_Taxon(taxon_capsule, self) + + + cpdef write(self, str prefix) : + if obi_write_taxonomy(self._dms._pointer, self._pointer, tobytes(prefix)) < 0 : + raise Exception("Error writing the taxonomy to binary files") + + + cpdef int add_taxon(self, str name, str rank_name, int parent_taxid, int min_taxid=10000000) : + cdef int taxid + taxid = obi_taxo_add_local_taxon(self._pointer, tobytes(name), tobytes(rank_name), parent_taxid, min_taxid) + if taxid < 0 : + raise Exception("Error adding a new taxon to the taxonomy") + else : + return taxid + + + cpdef close(self) : + if (obi_close_taxonomy(self._pointer) < 0) : + raise Exception("Error closing the taxonomy") + + +cdef class OBI_Taxon : # TODO dict subclass? + + def __init__(self, object taxon_capsule, OBI_Taxonomy tax) : + self._pointer = PyCapsule_GetPointer(taxon_capsule, NULL) + if self._pointer == NULL : + raise Exception("Error reading a taxon (NULL pointer)") + self._tax = tax + + + # name property getter + @property + def name(self): + return bytes2str(self._pointer.name) + + # taxid property getter + @property + def taxid(self): + return self._pointer.taxid + + # rank property getter + @property + def rank(self): + return self._pointer.rank + + # farest property getter + @property + def farest(self): + return self._pointer.farest + + # parent property getter + @property + def parent(self): + cdef object parent_capsule + parent_capsule = PyCapsule_New(self._pointer.parent, NULL, NULL) + return OBI_Taxon(parent_capsule, self._tax) + + # preferred name property getter and setter + @property + def preferred_name(self): + if self._pointer.preferred_name != NULL : + return bytes2str(self._pointer.preferred_name) + + @preferred_name.setter + def preferred_name(self, str new_preferred_name) : # @DuplicatedSignature + if (obi_taxo_add_preferred_name_with_taxon(self._tax._pointer, self._pointer, tobytes(new_preferred_name)) < 0) : + raise Exception("Error adding a new preferred name to a taxon") + + def __repr__(self): + d = {} + d['taxid'] = self.taxid + d['name'] = self.name + d['preferred name'] = self.preferred_name + d['parent'] = self.parent.taxid + d['farest'] = self.farest + return str(d) + + \ No newline at end of file