Source code for lascar.container.multiple_container

# This file is part of lascar
#
# lascar is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program.  If not, see <https://www.gnu.org/licenses/>.
#
#
# Copyright 2018 Manuel San Pedro, Victor Servant, Charles Guillemet, Ledger SAS - manuel.sanpedro@ledger.fr, victor.servant@ledger.fr, charles@ledger.fr

"""
multiple_container.py

    MultipleContainer concatenate containers already instanciated.

"""
import numpy as np

from .container import AbstractArray, Container, TraceBatchContainer


[docs]class MultipleContainer(Container): def __init__(self, *args, **kwargs): """ Constructor. :param args: a *list of containers to be concatenated into the MultipleContainer """ self._containers = args self.number_of_traces = sum([len(container) for container in args]) self.leakages = AbstractArray( (self.number_of_traces,) + self._containers[0].leakages.shape[1:], self._containers[0].leakages.dtype, ) self.values = AbstractArray( (self.number_of_traces,) + self._containers[0].values.shape[1:], self._containers[0].values.dtype, ) Container.__init__(self, **kwargs) self.logger.debug( "Creating MultipleContainer using %d Container." % len(self._containers) ) # improvement (todo) current = 0 self._t = np.zeros((self.number_of_traces + 1, 2), int) for i, container in enumerate(args): self._t[current : current + container.number_of_traces, 0] = i self._t[current : current + container.number_of_traces, 1] = range( container.number_of_traces ) current += container.number_of_traces self._t[current] = i, container.number_of_traces def __getitem__(self, item): self.logger.debug("__getitem__ with key %s %s" % (str(item), type(item))) if isinstance(item, int): container_idx, suboffset = self._t[item] return self._containers[container_idx][int(suboffset)] elif isinstance(item, slice): # check contiguity: if item.step is not None and item.step > 1: raise ValueError( "MultipleContainer __getitem__ slice elements must be contiguous" ) offset_begin = item.start if item.start else 0 offset_end = item.stop if item.stop else self.number_of_traces elif isinstance(item, list): # check contiguity: if np.any(np.diff(np.array(item)) != 1): raise ValueError( "MultipleContainer __getitem__ list elements must be contiguous" ) offset_begin = item[0] offset_end = item[-1] else: raise ValueError( "MultipleContainer __getitem__ only accepts int, list and slices (contiguous)" ) container_offset_begin, suboffset_offset_begin = self._t[offset_begin] container_offset_end, suboffset_offset_end = self._t[offset_end] # if container_offset_begin == container_offset_end: # return self._containers[container_offset_end][suboffset_offset_begin:suboffset_offset_end] # # else: # leakages = np.empty((offset_end - offset_begin,) + self._leakage_abstract.shape, self._leakage_abstract.dtype) # values = np.empty((offset_end - offset_begin,) + self._value_abstract.shape, self._value_abstract.dtype) # #first container: # leakages[:len(container_offset_begin)-suboffset_offset_begin] = suboffsets = [] if container_offset_begin == container_offset_end: suboffsets.append( [container_offset_begin, suboffset_offset_begin, suboffset_offset_end] ) else: suboffsets.append( [ container_offset_begin, suboffset_offset_begin, self._containers[container_offset_begin].number_of_traces, ] ) for i in range(container_offset_begin + 1, container_offset_end): suboffsets.append([i, 0, self._containers[i].number_of_traces]) suboffsets.append([container_offset_end, 0, suboffset_offset_end]) # TODO: Find a better solution... leakages = np.concatenate( [ self._containers[suboffset[0]][suboffset[1] : suboffset[2]].leakages for suboffset in suboffsets ] ) values = np.concatenate( [ self._containers[suboffset[0]][suboffset[1] : suboffset[2]].values for suboffset in suboffsets ] ) # leakages = np.zeros((offset_end - offset_begin,) + self._leakage_abstract.shape, self._leakage_abstract.dtype) # values = np.zeros((offset_end - offset_begin,) + self._value_abstract.shape, self._value_abstract.dtype) # # # print("leakages,values", leakages.shape, values.shape) # print() # print([str(i) for i in self._containers]) # print("offsets", offset_begin, offset_end) # print("suboffsets", suboffsets) # print("leakages", leakages.shape) # print("values", values.shape) # # i = 0 # # print("loop") # for suboffset in suboffsets: # print("suboffset", suboffset) # batch = self._containers[suboffset[0]][suboffset[1]:suboffset[2]] # print('batch',batch) # print('i:i+len', i, i+len(batch)) # print('leakages[i:i + len(batch)]',leakages[i:i + len(batch)].shape) # leakages[i:i + len(batch)] = batch.leakages # values[i:i + len(batch)] = batch.values # i += len(batch) return TraceBatchContainer(leakages, values) @property def leakage_section(self): return self._leakage_section @leakage_section.setter def leakage_section(self, section): for c in self._containers: c.leakage_section = section self._leakage_section = section self._leakage_section_abstract = c._leakage_section_abstract self._leakage_abstract = c._leakage_abstract @property def leakage_processing(self): return self._leakage_processing @leakage_processing.setter def leakage_processing(self, processing): for c in self._containers: c.leakage_processing = processing self._leakage_processing = processing self._leakage_section_abstract = c._leakage_section_abstract self._leakage_abstract = c._leakage_abstract @property def value_section(self): return self._value_section @value_section.setter def value_section(self, section): for c in self._containers: c.value_section = section self._value_section = section self._value_section_abstract = c._value_section_abstract self._value_abstract = c._value_abstract @property def value_processing(self): return self._value_processing @value_processing.setter def value_processing(self, processing): for c in self._containers: c.value_processing = processing self._value_processing = processing self._value_section_abstract = c._value_section_abstract self._value_abstract = c._value_abstract
[docs] def get_leakage_mean_var(self): """ Compute mean/var of the leakage. :return: mean/var of the container leakages """ sum_x = np.zeros((self._leakage_abstract.shape)) sum_x2 = np.zeros((self._leakage_abstract.shape)) for c in self._containers: m, v = c.get_leakage_mean_var() sum_x += m * len(c) sum_x2 += (v + m ** 2) * len(c) return sum_x / len(self), (sum_x2 / len(self)) - (sum_x / len(self)) ** 2