diff --git a/python/obitools3/dms/taxo/__init__.py b/python/obitools3/dms/taxo/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/python/obitools3/dms/taxo/taxo.pxd b/python/obitools3/dms/taxo/taxo.pxd index 45ae0ed..edbb06a 100644 --- a/python/obitools3/dms/taxo/taxo.pxd +++ b/python/obitools3/dms/taxo/taxo.pxd @@ -4,12 +4,16 @@ from ..capi.obitaxonomy cimport ecotx_t, OBIDMS_taxonomy_p from ..dms cimport DMS +from ..object cimport OBIWrapper -cdef class OBI_Taxonomy : - cdef str _name - cdef OBIDMS_taxonomy_p _pointer - cdef OBIDMS _dms + +cdef class OBI_Taxonomy(OBIWrapper) : + cdef str _name # TODO keep as bytes? + cdef DMS _dms + cdef inline OBIDMS_taxonomy_p pointer(self) + + cpdef get_taxon_by_idx(self, int idx) cpdef write(self, str prefix) cpdef int add_taxon(self, str name, str rank_name, int parent_taxid, int min_taxid=*) cpdef close(self) diff --git a/python/obitools3/dms/taxo/taxo.pyx b/python/obitools3/dms/taxo/taxo.pyx index d11711b..bb8a93c 100644 --- a/python/obitools3/dms/taxo/taxo.pyx +++ b/python/obitools3/dms/taxo/taxo.pyx @@ -14,18 +14,38 @@ from ..capi.obitaxonomy cimport obi_read_taxonomy, \ from cpython.pycapsule cimport PyCapsule_New, PyCapsule_GetPointer -cdef class OBI_Taxonomy : +cdef class OBI_Taxonomy(OBIWrapper) : # TODO function to import taxonomy? - def __init__(self, OBIDMS dms, str name, bint taxdump=False) : + + cdef inline OBIDMS_taxonomy_p pointer(self) : + return (self._pointer) + + + @staticmethod + def open(DMS dms, str name, bint taxdump=False) : + + cdef void* pointer + cdef OBI_Taxonomy taxo - self._dms = dms - self._name = name if taxdump : - self._pointer = obi_read_taxdump(tobytes(name)) + pointer = obi_read_taxdump(tobytes(name)) else : - self._pointer = obi_read_taxonomy(dms._pointer, tobytes(name), True) # TODO discuss + pointer = obi_read_taxonomy(dms.pointer(), tobytes(name), True) # TODO discuss # TODO if not found in DMS, try to import? + if pointer == NULL : + raise RuntimeError("Error : Cannot read taxonomy %s" + % name) + + taxo = OBIWrapper.new(OBI_Taxonomy, pointer) + + dms.register(taxo) + + taxo._dms = dms + taxo._name = name + + return taxo + def __getitem__(self, object ref): @@ -33,15 +53,31 @@ cdef class OBI_Taxonomy : cdef object taxon_capsule if type(ref) == int : - taxon_p = obi_taxo_get_taxon_with_taxid(self._pointer, ref) + 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") - - + + + cpdef get_taxon_by_idx(self, int idx): + + cdef ecotx_t* taxa + cdef ecotx_t* taxon_p + cdef object taxon_capsule + + taxa = self.pointer().taxa.taxon + taxon_p = (taxa+idx) + taxon_capsule = PyCapsule_New(taxon_p, NULL, NULL) + return OBI_Taxon(taxon_capsule, self) + + + def __len__(self): + return self.pointer().taxa.count + + def __iter__(self): cdef ecotx_t* taxa @@ -49,33 +85,46 @@ cdef class OBI_Taxonomy : cdef object taxon_capsule cdef int t - taxa = self._pointer.taxa.taxon + taxa = self.pointer().taxa.taxon # Yield each taxid - for t in range(self._pointer.taxa.count): + 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 : + 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) + 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 OBIDMS_taxonomy_p pointer = self.pointer() + + if self.active() : + self._dms.unregister(self) + OBIWrapper.close(self) + if (obi_close_taxonomy(self.pointer()) < 0) : + raise Exception("Problem closing the taxonomy %s" % + self._name) + + + # name property getter + @property + def name(self): + return self._name + cdef class OBI_Taxon : # TODO dict subclass? @@ -86,48 +135,59 @@ cdef class OBI_Taxon : # TODO dict subclass? self._tax = tax + # To test equality + def __richcmp__(self, OBI_Taxon taxon2, int op): + return (self.name == taxon2.name) and \ + (self.taxid == taxon2.taxid) and \ + (self.rank == taxon2.rank) and \ + (self.farest == taxon2.farest) and \ + (self.parent.taxid == taxon2.parent.taxid) and \ + (self.preferred_name == taxon2.preferred_name) + + # 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) : + 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['rank'] = self.rank d['preferred name'] = self.preferred_name d['parent'] = self.parent.taxid d['farest'] = self.farest