syncoder 0.0.3a1__tar.gz → 0.0.4a2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: syncoder
3
- Version: 0.0.3a1
3
+ Version: 0.0.4a2
4
4
  Summary: A codec for DNA data storage
5
5
  Project-URL: Homepage, https://example.com/TBD
6
6
  Project-URL: Issues, https://example.com/TBD/issues
@@ -3,4 +3,4 @@ from .codec import _default_b32_alphabet, _default_b32_alphabet_alt
3
3
  default_b32_alphabet = _default_b32_alphabet
4
4
  default_b32_alphabet_alt = _default_b32_alphabet_alt
5
5
 
6
- __version__ = "0.0.3a1"
6
+ __version__ = "0.0.4a2"
@@ -3,14 +3,22 @@ import struct
3
3
  import itertools
4
4
  import logging
5
5
  import typing
6
- from typing import Optional,Union, Callable, Tuple #requires python 3.5 or later
6
+ from typing import Optional,Union, Callable, Tuple, Literal, cast #requires python 3.8 or later
7
7
 
8
8
 
9
9
  import numpy as np
10
10
  from numpy.typing import ArrayLike
11
11
 
12
12
  import galois
13
- import reedsolo
13
+
14
+ #import a version of reedsolo that supports multi instance
15
+ import importlib.metadata
16
+ import packaging.version
17
+ rsvers = importlib.metadata.version('reedsolo')
18
+ if packaging.version.Version(rsvers) <= packaging.version.Version("2.1.3b1"):
19
+ from . import reedsoloMulti as reedsolo
20
+ else:
21
+ import reedsolo
14
22
 
15
23
  #### ROADMAP ####
16
24
  # - integrate the baseN to DNA function here. (generalize from b32fn)
@@ -160,7 +168,7 @@ class BaseNBlockCodec:
160
168
  # sizes in bytes:
161
169
  # |<---- self.data_chunk_size ----->|<- . ->|
162
170
  # ^ = self.index_bits <-- in bits not bytes.
163
- # note: actual k remains alphabet_size-1, but the code is shorted (0 padded) to inner_n symbols.
171
+ # note: actual k remains alphabet_size-1, but the code is shortened (0 padded) to inner_n symbols.
164
172
  k = inner_n - (inner_d - 1)
165
173
  self.inner_k = k
166
174
  q = self.inner_coder.field.order
@@ -356,6 +364,63 @@ class BaseNBlockCodec:
356
364
  logging.warning("Outer code errors found on strand {}, byte {}.".format(*e))
357
365
 
358
366
  return data_decoded, erasures, errors, chunk_errors
367
+
368
+ def extract_index_dna(self, dna: str|bytes, words:list[str], alternate_words:list[str], error_check: bool = False, padding: Literal["left","right"]="right") -> int:
369
+ """
370
+ Extracts the index from the given DNA strand.
371
+
372
+ Args:
373
+ dna (str|bytes): The input DNA strand from which to extract the index.
374
+ error_check (bool, optional): If True, the inner_codec will be used to
375
+ attempt to check for errors. Defaults to False.
376
+ padding Literal["left","right"], optional): Assume any missing bases are left or right of index. Defaults to "right".
377
+ Note padded sequences are unlikely to error correct properly.
378
+ words (list[str]): The primary set of base words used, in order, for encoding.
379
+ alternate_words (list[str]): The alternate (aka synonymous) set of words used, in order, for encoding.
380
+
381
+ Returns:
382
+ int: The index. or -1 if error_check==True and unrecoverable error found.
383
+ """
384
+ word_len:int = len(words[0])
385
+ if isinstance(dna,bytes):
386
+ dna= dna.decode()
387
+ dna_s:str = cast(str,dna)
388
+
389
+ if padding == "right":
390
+ _p = self.inner_k*word_len - len(dna_s)
391
+ if _p>0: #if i have less than a full codeword of bases
392
+ dna_s = dna_s + "A"*_p
393
+ elif padding == "left":
394
+ _p = self.inner_k*word_len - len(dna_s)
395
+ if _p>0: #if i have less than a full codeword of bases
396
+ dna_s = "A"*_p + dna_s
397
+
398
+ data = dna_to_bN([dna_s],words,alternate_words)[0]
399
+
400
+ return self.extract_index(data,error_check)
401
+
402
+ def extract_index(self, data: list[int], error_check: bool = False) -> int:
403
+ """
404
+ Extracts the index from the given DNA strand.
405
+
406
+ Args:
407
+ data list[int]: The input data from which to extract the index.
408
+ If a list[int] is given, it is assumed be be inner code symbols.
409
+ error_check (bool, optional): If True, the inner_codec will be used to
410
+ attempt to check for errors. Defaults to False.
411
+
412
+ Returns:
413
+ int: The index. or -1 if error_check==True and unrecoverable error found.
414
+ """
415
+ if error_check == False:
416
+ data = data[0:self.inner_k] #extract message
417
+ else:
418
+ data, n_corrected = self.inner_coder.decode(data,errors=True)[0].tolist()
419
+ if n_corrected < 0:
420
+ return -1
421
+ chunk_int = _baseN_to_int(data, self.inner_coder.field.order)
422
+ chunk_index = (chunk_int >> (self.data_chunk_size * 8))
423
+ return chunk_index
359
424
 
360
425
 
361
426
  #convert base N into DNA.