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.
- {syncoder-0.0.3a1 → syncoder-0.0.4a2}/PKG-INFO +1 -1
- {syncoder-0.0.3a1 → syncoder-0.0.4a2}/src/syncoder/__init__.py +1 -1
- {syncoder-0.0.3a1 → syncoder-0.0.4a2}/src/syncoder/codec.py +68 -3
- syncoder-0.0.4a2/src/syncoder/reedsoloMulti.py +1152 -0
- {syncoder-0.0.3a1 → syncoder-0.0.4a2}/tests/test_codec_pytest.py +15 -1
- {syncoder-0.0.3a1 → syncoder-0.0.4a2}/.gitignore +0 -0
- {syncoder-0.0.3a1 → syncoder-0.0.4a2}/.vscode/.gitignore +0 -0
- {syncoder-0.0.3a1 → syncoder-0.0.4a2}/LICENSE +0 -0
- {syncoder-0.0.3a1 → syncoder-0.0.4a2}/README.md +0 -0
- {syncoder-0.0.3a1 → syncoder-0.0.4a2}/environments/conda_environment.yml +0 -0
- {syncoder-0.0.3a1 → syncoder-0.0.4a2}/environments/conda_environment_dev.yml +0 -0
- {syncoder-0.0.3a1 → syncoder-0.0.4a2}/environments/conda_environment_test.yml +0 -0
- {syncoder-0.0.3a1 → syncoder-0.0.4a2}/pyproject.toml +0 -0
|
@@ -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.
|
|
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
|
-
|
|
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
|
|
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.
|