def readFile0BC(context): filedata = None with open(context.filepath, 'rb') as f: filedata = f.read() bd = BinData(filedata) print('file size =', bd.dataSize()) h = readHeader0BC(bd) context.header = h pprint(h) if h.maybeDataType == 1: assert(context.expectedFormat == 0x10) # assert(h.countRecords == 0) readPhysicalCollision0BC(bd, context) elif h.maybeDataType != 0: print('Yet unknown and unexpected header') assert(False) else: if context.expectedFormat == 0x12: readRecords0BC_format_12(bd, context) else: readRecords0BC(bd, context) print(bd.tell(), bd.dataSize())
def main(): parser = argparse.ArgumentParser( description= "-= Encoder/Decoder of convolutional codes.\nAuthor: Jozef Knaperek =-\n" ) group = parser.add_mutually_exclusive_group(required=True) group.add_argument('-e', '--encode', action='store_true', help='encode data with convolutional code') group.add_argument('-d', '--decode', action='store_true', help='decode data using Viterbi algorithm') def make_bindata(arg): return BinData(arg) make_bindata.__name__ = 'input data' parser.add_argument('-i', '--input', type=make_bindata, help='input data bit-stream (instead of using stdin)') def make_pols_list(arg): pols = [int(pol, 2) for pol in arg.split(',')] if min(map(ones_count, pols)) < 2: raise ValueError( 'Every valid polynomial must have at least two binary 1s') return pols make_pols_list.__name__ = 'polynomials list' parser.add_argument( 'polynomials', help= 'comma separated list of binnary polynomials (of at least two binary 1s in each)', type=make_pols_list) args = parser.parse_args() try: input_data = args.input or BinData(sys.stdin.read()) except ValueError: sys.exit('Invalid input data: ' + stdin_input) if args.encode: # encode print(Transitions(args.polynomials).encode(input_data)) else: # decode if len(input_data) % len(args.polynomials): sys.exit( 'Decoding error: The number of data bits ({}) is not multiple of the number of polynomials ({})!' .format(len(input_data), len(args.polynomials))) print(args.polynomials) print(Transitions(args.polynomials).decode(input_data))
def __init__(self,bstream,entry_type,size,offset=None): """ Parse an entry list from a bytestream entry_type should be any Entry type generated with Entry.create() """ self.data = [] self.corrupted = False self.type = entry_type #Set the entry offset if offset == None: self.offset = BinData(4) self.offset.init_data_from_int(bstream.offset) elif issubclass(offset.__class__,(types.IntType,)): self.offset = BinData(4) self.offset.init_data_from_int(offset) elif issubclass(offset.__class__,(BinData,)): self.offset = offset else: raise Exception('Invalid type for EntryList offset: %s' % offset.__class__) bstream.seek(int(self.offset)) if issubclass(size.__class__,(types.IntType,)): self.size = BinData(4) self.size.init_data_from_int(size) elif issubclass(size.__class__,(BinData,)): self.size = size else: raise Exception('Invalid type for EntryList size: %s' % size.__class__) for i in xrange(int(self.size)): self.data.append(self.type(bstream)) if bstream.exhausted: self.corrupted = True break
def decode(self, parity_sequence_bindata): """ Decodes convolutional code using the Viterbi algorithm. Public method (API). """ gen = self.extract_parity_sequence(parity_sequence_bindata) state = 0 # initial state INF = float('inf') # constant definition class Node(): def __init__(self, metric=INF, bindata=None): self.metric = metric self.bindata = bindata or BinData(0, 0) # init trellis olds = [Node(INF, BinData(0, 0)) for i in range(self.n_states)] # aktualna metrika, data bits news = [Node(None, None) for i in range(self.n_states) ] # nova metrika, data bits (with added one new bit) olds[0].metric = 0 # set metrics of first state to 0 # iterate through parities in encoded data (parity sequence) for parity in gen: # initialize news for new in news: new.metric = INF # set new PM to infinity # choose best paths for new step for i in range(self.n_states): for bit in (0, 1): t = self.states[i][bit].new_state p = self.states[i][bit].parity hd = hamming_distance(p, parity) new_PM = olds[i].metric + hd # compute candidate PM if new_PM < news[ t].metric: # if this new candidate is better than existing new candidate news[t].metric = new_PM news[t].bindata = olds[i].bindata + bit # update "column" in trellis with best paths chosen in previous step and prepare for next iteration for i in range(self.n_states): olds[i].metric = news[i].metric olds[i].bindata = news[i].bindata # Finalization # Get state with best PM best_state, best_PM = None, INF for old in olds: if old.metric < best_PM: best_PM = old.metric best_state = old # Decoded databits: return best_state.bindata
def _prepare_stream(self,bstream,offset): """ Initialize the offset and mode the stream to it. The offset should a BinData object to allow references to it As so, an update in an offset will update all its the references. """ if offset == None: offset = bstream.offset if issubclass(offset.__class__,(types.IntType,)): self.offset = BinData(4) self.offset.init_data_from_int(offset) elif issubclass(offset.__class__,(BinData,)): self.offset = offset elif (issubclass(offset.__class__,(Entry,)) and '__int__' in dir(offset)): self.offset = offset else: raise Exception('Invalid type for EntryList offset (%s) in class %s' % (offset,self)) bstream.seek(int(self.offset))
def make_bindata(arg): return BinData(arg)
def __init__(self, metric=INF, bindata=None): self.metric = metric self.bindata = bindata or BinData(0, 0)
def encode(self, bindata): """ Encodes data using convolutional code. Public method (API). """ parity_sequence = BinData(0, 0) for parity in self.generate_parities(bindata): parity_sequence += BinData(parity, self.parity_len) return parity_sequence