From 8a6e1220f9acf7600f7b401edd4a9f243920faa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Pleva=C4=8D?= Date: Mon, 20 Nov 2023 13:14:38 +0100 Subject: [PATCH] Some basic documentation --- src/SIMDDNA/__init__.py | 3 +- src/SIMDDNA/ascii.py | 24 +++++++ src/SIMDDNA/assembly.py | 9 +++ src/SIMDDNA/molecule.py | 145 +++++++++++++++++++++++++++++++++++++++- src/SIMDDNA/register.py | 133 ++++++++++++++++++------------------ src/main.py | 48 +++++++++++++ 6 files changed, 290 insertions(+), 72 deletions(-) create mode 100644 src/main.py diff --git a/src/SIMDDNA/__init__.py b/src/SIMDDNA/__init__.py index 0040413..afff55f 100644 --- a/src/SIMDDNA/__init__.py +++ b/src/SIMDDNA/__init__.py @@ -1,2 +1,3 @@ import ascii as ascii -import molecule as molecule \ No newline at end of file +import molecule as molecule +import register as register \ No newline at end of file diff --git a/src/SIMDDNA/ascii.py b/src/SIMDDNA/ascii.py index e0379b5..fbd22a1 100644 --- a/src/SIMDDNA/ascii.py +++ b/src/SIMDDNA/ascii.py @@ -1,6 +1,18 @@ +## +# @file ascii.py +# @autor Lukáš Plevač +# @brief defines function from print structions in ASCII reprezentation + from molecule import isComplementary from molecule import nothing +## +# Return number of bases to bind with main chain 0 +# @param chainID id of chain in molecule +# @param curPOS current position in molecule +# @param molecule molecule with chain +# @return int +# def toBindingLen(chainID, curPOS, molecule): toBLen = 0 @@ -28,6 +40,18 @@ def toBindingLen(chainID, curPOS, molecule): return None +## +# Show molecule in ASCII reprezentation +# [AB].{D} +# +# / +# -/ +# ---- +# ABCD +# +# @param molecule molecule to print +# @param spacing chars between ascii chars +# def showMolecule(molecule, spacing = ""): Invlines = [ "", # register strand diff --git a/src/SIMDDNA/assembly.py b/src/SIMDDNA/assembly.py index e69de29..7170ad9 100644 --- a/src/SIMDDNA/assembly.py +++ b/src/SIMDDNA/assembly.py @@ -0,0 +1,9 @@ +class Assembly: + def __init__(self, asm): + # remove whitespaces + asm = asm.strip() + # load macros from file + self.macros = self.parseMacros(asm) + + def parseMacros(self, asm): + \ No newline at end of file diff --git a/src/SIMDDNA/molecule.py b/src/SIMDDNA/molecule.py index 9ed54ce..dc949f6 100644 --- a/src/SIMDDNA/molecule.py +++ b/src/SIMDDNA/molecule.py @@ -1,10 +1,15 @@ +## +# @file molecule.py +# @autor Lukáš Plevač +# @brief defines class molecule and functions to work with it + # # [aa] - double strand of aa (domain a and domain a) # {aa} - single strand of aa (domain a and domain a) [upper] # - single strand of aa (domain a and domain a) [downer] # # example: -# [ABC]*{abc}{ba}*[CC]*{CA} +# [ABC].{abc}{ba}.[CC].{CA} # # c # b b A @@ -14,21 +19,48 @@ # a b c A B C C C C # +## +# @brief Char representing space in chain +# nothing = "-" +## +# Check if two bases is complementary +# @param baseA one of base to check +# @param baseB second of base to check +# @return baseA is complementary to baseB +# def isComplementary(baseA, baseB): return (f"{baseA}*" == baseB) or (baseA == f"{baseB}*") +## +# Class representing moleculte +# class Molecule: + + ## + # Init empty molecule + # def __init__(self): self.chains = [] + ## + # Get length of longest chain in molecule + # @return int + # def __len__(self): return self.maxChainSize() - + + ## + # Return number of count of chains in molecule + # @return int + # def chainsCount(self): return len(self.chains) + ## + # Pad all chains to same length using insert spaces + # def endPad(self): targetSize = self.maxChainSize() @@ -36,15 +68,34 @@ class Molecule: while (targetSize > len(self.chains[id])): self.chains[id].append(nothing) + ## + # Add base to end of chain + # @param base base to add + # @param chainId id of chain to add base + # def addToChain(self, base, chainId): self.chains[chainId].append(base) + ## + # Get chain as array + # @param chain id of chain + # @return array of chain + # def getChain(self, chain): return self.chains[chain] + ## + # Remove chain form molecule + # @param chainId id of chain + # @post all chains ids is reindex + # def removeChain(self, chainId): del self.chains[chainId] + ## + # Get length of longest chain in molecule + # @return int + # def maxChainSize(self): maxLen = 0 for chain in self.chains: @@ -52,38 +103,82 @@ class Molecule: return maxLen + ## + # Add chain to end of chain in molecule + # @param chainID id of chain in molecule to add other chain on end + # @param chain array reprezentation of chain + # def chain2chain(self, chainID, chain): for base in chain: self.chains[chainID].append(base) + ## + # Add spaces to start of chain in molecule + # @param chainID id of chain in molecule + # @param count count of spaces + # def padChain(self, chainID, count): for _ in range(count): self.chains[chainID].insert(0, nothing) + ## + # Add spaces to start of chain in molecule by length of other chain in molecule + # @param chainID id of chain in molecule to pad + # @param targetID if of chain of len count of spaces + # def padChainToLen(self, chainID, targetID): targetSize = len(self.chains[targetID]) curSize = len(self.chains[chainID]) self.padChain(chainID, targetSize - curSize) + ## + # Add spaces to start of all chains in molecule + # @param chainID id of chain in molecule to pad + # @param count count of spaces + # def padAllChains(self, length): for id in range(len(self.chains)): self.padChain(id, length) + ## + # Add base to end of chain same as addToChain() + # @param base base to add + # @param chainId id of chain to add base + # def addBase(self, chainID, base): self.chains[chainID].append(base) + ## + # Add chain to molecule + # @return id of new chain + # def addChain(self): chainId = len(self.chains) self.chains.append([]) return chainId + ## + # Update base in chain + # @param base base to set + # @param chainId id of chain to add base + # @param baseID id of base in chain + # def updateBase(self, chainID, baseID, base): self.chains[chainID][baseID] = base + ## + # Get base from chain + # @param chainId id of chain to add base + # @param baseID id of base in chain + # def getBase(self, chainID, baseID): return self.chains[chainID][baseID] + ## + # Get Number of possible binding on position on molecule + # @param baseID id of base in chain (position in molecule) + # def bindedCountAt(self, baseID): binding = 0 for chain in self.chains: @@ -92,6 +187,17 @@ class Molecule: return binding + ## + # Add base to end of chain by char represetion + # A representing base A + # A* representing complement of base A + # A** representing base A (complement of complement) + # @param char char represetation of base to add + # @param chainId id of chain to add base + # @param isBackward is adding from back to front + # -A (+B) + # AB + # def charAddBase(self, chainID, char, isBackward = False): if isBackward: if len(self.chains[chainID]) == 0 or self.getBase(chainID, 0) != nothing: @@ -107,7 +213,19 @@ class Molecule: self.updateBase(chainID, -1, f"{curBase}*") else: self.addBase(chainID, char) - + + ## + # Print raw reprezentation of molecule + # aligmented chains as string + # D + # B* C* + # A B C A B C + # + # Print as: + # + # A B C A B C + # - B* C* D* - - + # def rawPrint(self): for chan in self.chains: raw = "" @@ -116,6 +234,27 @@ class Molecule: print(raw) +## +# Convert string notation of molecule to molecule class object +# @param notationStr string notation of molecule +# @return Molecule object +# +# String notation: +# - <> for lower chain +# - [] for double chain +# - {} for upper chain +# - * for complement +# - . for concatenate upper strand with double strand +# +# String notation example: +# [ABC].{abc}{ba}.[CC].{CA} +# +# c +# b b A +# a C +# A* B* C* C* C* +# | | | | | +# a b c A B C C C C def parse(notationStr): newMolecule = Molecule() state = "init" diff --git a/src/SIMDDNA/register.py b/src/SIMDDNA/register.py index 5ca094f..d7d5949 100644 --- a/src/SIMDDNA/register.py +++ b/src/SIMDDNA/register.py @@ -1,20 +1,61 @@ +## +# @file register.py +# @autor Lukáš Plevač +# @brief implments REGISTER from SIMD|DNA + import molecule import ascii class Register: + ## + # Init register + # @param mol molecule reprezenting register + # def __init__(self, mol = molecule.Molecule()): self.set(mol) + ## + # set register molecule + # @param mol molecule reprezenting register + # def set(self, mol): self.mol = mol - def inscription(self, IMols): + ## + # Perform instruction on register + # @param mol molecule reprezenting register + # + def instruction(self, IMols): for mol in IMols: + # try bind mol to all possible bindings self.doAllBinding(mol) + + # remove unbinded chains from register (because new imol have bind on older chain with more bases that register) + # --- + # ||| + # --- + # + # ---- R self.removeUnbinded() + + # remove unbinded chains from register (because new imol have bind on more posisin on register that older) + # -- + # + # --- + # ||| + # ---- R self.removeReplaced() + + # remove all unstable binded chains binded on 1 base or lower self.removeUnstable() + ## + # remove unbinded chains from register (because new imol have bind on more posisin on register that older) + # -- + # + # --- + # ||| + # ---- R def removeReplaced(self): while True: done = True @@ -38,6 +79,13 @@ class Register: if done: break + ## + # remove unbinded chains from register (because new imol have bind on older chain with more bases that register) + # --- + # ||| + # --- + # + # ---- R def removeUnbinded(self): while True: done = True @@ -63,6 +111,8 @@ class Register: if done: break + ## + # remove all unstable binded chains binded on 1 base or lower def removeUnstable(self): while True: done = True @@ -71,11 +121,15 @@ class Register: for chainI in range(self.mol.chainsCount() - 1, 0, -1): # for all bases in molecule bindScore = 0 + finalBindScore = 0 for pos in range(len(self.mol)): if molecule.isComplementary(self.mol.getBase(chainI, pos), self.mol.getBase(0, pos)) and self.mol.bindedCountAt(pos) == 1: # binde minimaly once bindScore += 1 + else: + bindScore = 0 + finalBindScore = max(finalBindScore, bindScore) - if bindScore < 2: + if finalBindScore < 2: self.mol.removeChain(chainI) done = False break @@ -84,6 +138,10 @@ class Register: if done: break + ## + # try bind mol to all possible bindings + # Added all imol bindings as new chains + # do not chech if other chain is ocupation this postion def doAllBinding(self, imol): # for all chains in register for chainI in range(self.mol.chainsCount()): @@ -108,73 +166,12 @@ class Register: self.mol.chain2chain(chain, imol.getChain(0)) self.mol.endPad() + ## + # Show register with raw print molecule def show(self): return self.mol.rawPrint() + ## + # Show register with ascii reprezentation of molecule def asciiShow(self, spaceing = ""): - return ascii.showMolecule(self.mol, spaceing) - - -print("---------------------------------") -print("Before") -print("---------------------------------\n") - -# create register -num1 = "{A}[BCDE]" -num0 = "[ABC][DE]" - -myreg = Register(molecule.parse( - num1 + num0 + num0 + num1 + num1 + num1 + num1 + num0 + num1 + num0 -)) - -myreg.asciiShow() - -print("\n---------------------------------") -print("After") -print("---------------------------------\n") - -# do inscription -# mark -# myreg.inscription([ -# molecule.parse("") -# ]) - -# do instruction -# remove - -myreg.inscription([ - molecule.parse("{D*E*A*F*}") -]) - -myreg.asciiShow(" ") - -myreg.inscription([ - molecule.parse("{D*E*A*B*C*G*}") -]) - -myreg.asciiShow(" ") - -myreg.inscription([ - molecule.parse("{DEABCG}") -]) - -myreg.asciiShow(" ") - -myreg.inscription([ - molecule.parse("{A*B*C*}"), - molecule.parse("{D*E*}") -]) - -myreg.asciiShow(" ") - -myreg.inscription([ - molecule.parse("{DEAF}") -]) - -myreg.asciiShow(" ") - -myreg.inscription([ - molecule.parse("{B*C*D*E*}") -]) - -myreg.asciiShow(" ") \ No newline at end of file + return ascii.showMolecule(self.mol, spaceing) \ No newline at end of file diff --git a/src/main.py b/src/main.py new file mode 100644 index 0000000..2a4b4fd --- /dev/null +++ b/src/main.py @@ -0,0 +1,48 @@ + +from SIMDDNA.register import Register +from SIMDDNA import molecule +from SIMDDNA.assembly import Assembly + +asm = Assembly( +""" +define: + 0 [ABC][DE] + 1 {A}[BCDE] + +data: + 1001111010 + +instructions: + {D*E*A*F*} # mark 01 + {D*E*A*B*C*G*} # mark 11 + {DEABCG} # remove mark 11 + {A*B*C*} {D*E*} # write 0 + {DEAF} # remove mark 01 + {B*C*D*E*} # write 1 +""" +) + +print("=================================") +print("| Inital state |") +print("=================================") +print("\n") + +regs = [] + +for data in asm.getData(): + regs.append(Register(molecule.parse(data))) + regs[-1].asciiShow(spaceing = " ") + + +iId = 0 +for ins in asm.getInstructions(): + print("=================================") + print(f"| Instruction {iId} |") + print("=================================") + print("\n") + + for reg in regs: + reg.instruction(ins) + reg.asciiShow(spaceing = " ") + + iId += 1 \ No newline at end of file