diff --git a/python/obitools3/dms/capi/obiview.pxd b/python/obitools3/dms/capi/obiview.pxd index 792441b..ea56620 100644 --- a/python/obitools3/dms/capi/obiview.pxd +++ b/python/obitools3/dms/capi/obiview.pxd @@ -66,8 +66,12 @@ cdef extern from "obiview.h" nogil: Obiview_p obi_new_view_cloned_from_name(OBIDMS_p dms, const_char_p view_name, const_char_p view_to_clone_name, index_t* line_selection, const_char_p comments) - Obiview_p obi_new_view_nuc_seqs_cloned_from_name(OBIDMS_p dms, const_char_p view_name, const_char_p view_to_clone_name, index_t* line_selection, const_char_p comments, bint quality_column) - + Obiview_p obi_new_view_nuc_seqs_cloned_from_name(OBIDMS_p dms, const_char_p view_name, const_char_p view_to_clone_name, index_t* line_selection, const_char_p comments) + + Obiview_p obi_clone_view(OBIDMS_p dms, Obiview_p view_to_clone, const char* view_name, index_t* line_selection, const char* comments) + + Obiview_p obi_clone_view_from_name(OBIDMS_p dms, const char* view_to_clone_name, const char* view_name, index_t* line_selection, const char* comments) + Obiview_infos_p obi_view_map_file(OBIDMS_p dms, const char* view_name, bint finished) int obi_view_unmap_file(OBIDMS_p dms, Obiview_infos_p view_infos) diff --git a/python/obitools3/dms/obiseq.pxd b/python/obitools3/dms/obiseq.pxd new file mode 100644 index 0000000..b397d0c --- /dev/null +++ b/python/obitools3/dms/obiseq.pxd @@ -0,0 +1,22 @@ +#cython: language_level=3 + +from .view.view cimport Line + + +cdef class Seq(dict) : + + cdef str _id + cdef object _seq + cdef str _definition + + +cdef class Nuc_Seq(Seq) : + + cdef object _quality + #cpdef object reverse_complement(self) + + +cdef class Nuc_Seq_Stored(Line) : + + cpdef object get_str_quality(self) + #cpdef object reverse_complement(self) \ No newline at end of file diff --git a/python/obitools3/dms/obiseq.pyx b/python/obitools3/dms/obiseq.pyx new file mode 100644 index 0000000..3b8aa74 --- /dev/null +++ b/python/obitools3/dms/obiseq.pyx @@ -0,0 +1,126 @@ +#cython: language_level=3 + +from obitools3.utils cimport bytes2str, str2bytes + +from .capi.obiview cimport NUC_SEQUENCE_COLUMN, \ + ID_COLUMN, \ + DEFINITION_COLUMN, \ + QUALITY_COLUMN + + +cdef class Seq(dict) : + def __init__(self, str id, object seq, object definition=None) : + self.id = id + self.seq = seq + if definition is not None : + self.definition = definition + + # sequence id property getter and setter + @property + def id(self): # @ReservedAssignment + return self._id + + @id.setter + def id(self, str new_id): # @ReservedAssignment @DuplicatedSignature + self._id = new_id + self[bytes2str(ID_COLUMN)] = new_id + + # sequence property getter and setter + @property + def seq(self): + return self._seq + + @seq.setter + def seq(self, object new_seq): # @DuplicatedSignature + self._seq = new_seq + self["SEQ"] = new_seq # TODO discuss + + # sequence definition property getter and setter + @property + def definition(self): + return self._definition + + @definition.setter + def definition(self, object new_definition): # @DuplicatedSignature + self._definition = new_definition + self[bytes2str(DEFINITION_COLUMN)] = new_definition + + +cdef class Nuc_Seq(Seq) : + + # nuc sequence property getter and setter + @property + def seq(self): + return self._seq + + @seq.setter + def seq(self, object new_seq): # @DuplicatedSignature + self._seq = new_seq + self[bytes2str(NUC_SEQUENCE_COLUMN)] = new_seq + + # sequence quality property getter and setter + @property + def quality(self): + return self._quality + + @quality.setter + def quality(self, object new_quality): # @DuplicatedSignature + self._quality = new_quality + self[bytes2str(QUALITY_COLUMN)] = new_quality + +# cpdef str reverse_complement(self) : TODO in C ? +# pass + + +cdef class Nuc_Seq_Stored(Line) : + + # TODO store the str version of column name macros? + + # sequence id property getter and setter + @property + def id(self): # @ReservedAssignment @DuplicatedSignature + return self[bytes2str(ID_COLUMN)] + + @id.setter + def id(self, str new_id): # @ReservedAssignment @DuplicatedSignature + self[bytes2str(ID_COLUMN)] = new_id + + # sequence definition property getter and setter + @property + def definition(self): + return self[bytes2str(DEFINITION_COLUMN)] + + @definition.setter + def definition(self, str new_def): # @DuplicatedSignature + self[bytes2str(DEFINITION_COLUMN)] = new_def + + # nuc_seq property getter and setter + @property + def nuc_seq(self): + return self[bytes2str(NUC_SEQUENCE_COLUMN)] + + @nuc_seq.setter + def nuc_seq(self, object new_seq): # @DuplicatedSignature + self[bytes2str(NUC_SEQUENCE_COLUMN)] = new_seq + + # quality property getter and setter + @property + def quality(self): + return self[bytes2str(QUALITY_COLUMN)] + + @quality.setter + def quality(self, object new_qual): # @DuplicatedSignature + if (type(new_qual) == list) or (new_qual is None) : # TODO check that quality column exists + self[bytes2str(QUALITY_COLUMN)] = new_qual + else : # Quality is in str form + (((self._view).columns)[bytes2str(QUALITY_COLUMN)]).set_str_line(self._index, new_qual) + + cpdef object get_str_quality(self) : # TODO not ideal. Make quality_int and quality_str properties + return ((self._view).columns)[bytes2str(QUALITY_COLUMN)].get_str_line(self._index) + +# cpdef str reverse_complement(self) : TODO in C ? +# pass + + # TODO static method to import OBI_Nuc_Seq to OBI_Nuc_Seq_Stored ? + + \ No newline at end of file diff --git a/python/obitools3/dms/view/view.pxd b/python/obitools3/dms/view/view.pxd index d4c8560..fc3d057 100644 --- a/python/obitools3/dms/view/view.pxd +++ b/python/obitools3/dms/view/view.pxd @@ -30,11 +30,7 @@ cdef class View(OBIWrapper): list lines=*) @staticmethod - cdef type get_view_class(bytes viewtype) - - @staticmethod - cdef register_view_class(bytes viewtype, - type classe) + cdef type get_view_class(bytes view_type) cdef class Line_selection(list): @@ -55,3 +51,7 @@ cdef class Line : cdef View _view +cdef register_view_class(bytes view_type_name, + type view_class) + +cdef register_all_view_classes() diff --git a/python/obitools3/dms/view/view.pyx b/python/obitools3/dms/view/view.pyx index 7a896d1..58b5b7d 100644 --- a/python/obitools3/dms/view/view.pyx +++ b/python/obitools3/dms/view/view.pyx @@ -9,6 +9,7 @@ from libc.stdlib cimport malloc from ..capi.obiview cimport Alias_column_pair_p, \ obi_new_view, \ obi_open_view, \ + obi_clone_view, \ obi_save_and_close_view, \ obi_view_get_pointer_on_column_in_view, \ obi_view_delete_column, \ @@ -26,6 +27,8 @@ from ..object cimport OBIObjectClosedInstance from ..column.column cimport Column +from obitools3.dms.view import typed_view + from ..capi.obitypes cimport only_ATGC, \ OBI_BOOL, \ OBI_CHAR, \ @@ -34,27 +37,16 @@ from ..capi.obitypes cimport only_ATGC, \ OBI_QUAL, \ OBI_SEQ, \ OBI_STR - + +import importlib +import inspect +import pkgutil + cdef class View(OBIWrapper) : cdef inline Obiview_p pointer(self) : - return (self._pointer) - - - @staticmethod - cdef register_view_class(bytes view_type_name, - type view_class): - ''' - Each sub class of `dms.View` needs to be registered after its declaration - to declare its relationship with an `OBIType_t` - ''' - global __VIEW_CLASS__ - - assert issubclass(view_class, View) - - __VIEW_CLASS__[view_type_name] = view_class - + return (self._pointer) @staticmethod cdef type get_view_class(bytes view_type): @@ -65,8 +57,7 @@ cdef class View(OBIWrapper) : @staticmethod def new(DMS dms, object view_name, - object comments=None, - type view_class=View): + object comments=None): cdef bytes view_name_b = tobytes(view_name) cdef bytes comments_b @@ -74,7 +65,7 @@ cdef class View(OBIWrapper) : cdef void* pointer cdef View view # @DuplicatedSignature - + if comments is not None: comments_b = tobytes(comments) else: @@ -90,7 +81,7 @@ cdef class View(OBIWrapper) : message = "Error : Cannot create view %s" % bytes2str(view_name_b) raise RuntimeError(message) - view = OBIWrapper.new(view_class, pointer) + view = OBIWrapper.new(View, pointer) view._dms = dms dms.register(view) @@ -115,11 +106,11 @@ cdef class View(OBIWrapper) : else: comments_b = b'' - pointer = obi_new_view(self._dms.pointer(), - view_name_b, - self.pointer(), - NULL, - comments_b) + pointer = obi_clone_view(self._dms.pointer(), + self.pointer(), + view_name_b, + NULL, + comments_b) if pointer == NULL : raise RuntimeError("Error : Cannot clone view %s into view %s" @@ -485,13 +476,13 @@ cdef class Line_selection(list): comments_b = tobytes(comments) else: comments_b = b'' - - pointer = obi_new_view(self._view._dms.pointer(), - view_name_b, - self._view.pointer(), - self.__build_binary_list__(), - comments_b) - + + pointer = obi_clone_view(self._view._dms.pointer(), + self._view.pointer(), + view_name_b, + self.__build_binary_list__(), + comments_b) + if pointer == NULL : raise RuntimeError("Error : Cannot clone view %s into view %s with new line selection" % (str(self._view.name), @@ -504,3 +495,28 @@ cdef class Line_selection(list): return view + +############################################################# + + +cdef register_view_class(bytes view_type_name, + type view_class): + ''' + Each subclass of `dms.view` needs to be registered after its declaration + ''' + global __VIEW_CLASS__ + + assert issubclass(view_class, View) + + __VIEW_CLASS__[view_type_name] = view_class + + +cdef register_all_view_classes() : + + x = list(pkgutil.walk_packages(typed_view.__path__, prefix="obitools3.dms.view.typed_view.")) + all_modules = [importlib.import_module(a[1]) for a in x] + for mod in all_modules : + getattr(mod, 'register_class')() + + +register_all_view_classes()