def _call(self, start1, stop1, start2, stop2, data): if self._memory_map is not None: if data.ndim == 2: self._memory_map[start1:stop1, start2:stop2] = data[:, :, numpy.newaxis] else: self._memory_map[start1:stop1, start2:stop2] = data return # we have to fall-back to manually write element_size = int_func(self._raw_dtype.itemsize) if len(self._shape) == 3: element_size *= int_func(self._shape[2]) stride = element_size*int_func(self._shape[0]) # go to the appropriate spot in the file for first entry self._fid.seek(self._data_offset + stride*start1 + element_size*start2) if start1 == 0 and stop1 == self._shape[0]: # we can write the block all at once data.astype(self._raw_dtype).tofile(self._fid) else: # have to write one row at a time bytes_to_skip_per_row = element_size*(self._shape[0]-(stop1-start1)) for i, row in enumerate(data): # we the row, and then skip to where the next row starts row.astype(self._raw_dtype).tofile(self._fid) if i < len(data) - 1: # don't seek on last entry (avoid segfault, or whatever) self._fid.seek(bytes_to_skip_per_row, os.SEEK_CUR)
def validate_lims(lims, typ): # type: (Union[None, tuple, list, numpy.ndarray], str) -> Tuple[Tuple[int, int], ...] def validate_entry(st, ed, shap, i_fr): if not ((0 <= st < shap[ind]) and (st < ed <= shap[ind])): raise ValueError('{}_limits is {}, and frame {} has shape {}'.format(typ, lims, i_fr, shap)) ind = 0 if typ == 'row' else 1 if lims is None: return tuple((0, shp[ind]) for shp in sizes) else: o_lims = numpy.array(lims, dtype=numpy.int64) t_lims = [] if len(o_lims.shape) == 1: if o_lims.shape[0] != 2: raise ValueError( 'row{}_limits must be of the form (<start>, <end>), got {}'.format(typ, lims)) t_start = int_func(o_lims[0]) t_end = int_func(o_lims[1]) for i_frame, shp in zip(frames, sizes): validate_entry(t_start, t_end, shp, i_frame) t_lims.append((t_start, t_end)) else: if o_lims.shape[0] != len(frames): raise ValueError( '{0:s}_limits must either be of the form (<start>, <end>) applied to all frames, ' 'or a collection of such of the same length as frames. ' 'Got len({0:s}_limits) = {1:d} and len(frames) = {2:d}'.format(typ, o_lims.shape[0], len(frames))) for entry, i_frame, shp in zip(o_lims, frames, sizes): t_start = int_func(entry[0]) t_end = int_func(entry[1]) validate_entry(t_start, t_end, shp, i_frame) t_lims.append((t_start, t_end)) return tuple(t_lims)
def _read_raw_fun(self, range1, range2): range1, range2 = self._reorder_arguments(range1, range2) rows_size = int_func((range1[1]-range1[0])/range1[2]) cols_size = int_func((range2[1]-range2[0])/range2[2]) if self._output_bands == 1: out = numpy.empty((rows_size, cols_size), dtype=self._dtype) else: out = numpy.empty((rows_size, cols_size, self._output_bands), dtype=self._dtype) for entry, child_chipper in zip(self._bounds, self._child_chippers): row_start, row_end, col_start, col_end = entry # find row overlap for chipper - it's rectangular crange1, cinds1 = self._subset(range1, row_start, row_end) if crange1 is None: continue # there is no row overlap for this chipper # find column overlap for chipper - it's rectangular crange2, cinds2 = self._subset(range2, col_start, col_end) if crange2 is None: continue # there is no column overlap for this chipper if self._output_bands == 1: out[cinds1[0]:cinds1[1], cinds2[0]:cinds2[1]] = \ child_chipper[crange1[0]:crange1[1]:crange1[2], crange2[0]:crange2[1]:crange2[2]] else: out[cinds1[0]:cinds1[1], cinds2[0]:cinds2[1], :] = \ child_chipper[crange1[0]:crange1[1]:crange1[2], crange2[0]:crange2[1]:crange2[2]] return out
def _read_file(self, range1, range2): def get_row_location(rr, cc): return self._data_offset + \ rr*stride + \ cc*element_size # we have to manually map out the stride and all that for the array ourselves element_size = int_func(numpy.dtype(self._raw_dtype).itemsize*self._raw_bands) stride = element_size*int_func(self._shape[0]) # how much to skip a whole (real) row? entries_per_row = abs(range1[1] - range1[0]) # not including the stride, if not +/-1 # let's determine the specific row/column arrays that we are going to read dim1array = numpy.arange(range1) dim2array = numpy.arange(range2) # allocate our output array out = numpy.empty((len(dim1array), len(dim2array), self._raw_bands), dtype=self._raw_dtype) # determine the first column reading location (may be reading cols backwards) col_begin = dim2array[0] if range2[2] > 0 else dim2array[-1] for i, row in enumerate(dim1array): # go to the appropriate point in the file for (row/col) self._fid.seek(get_row_location(row, col_begin)) # interpret this of line as numpy.ndarray - inherently flat array line = numpy.fromfile(self._fid, self._raw_dtype, entries_per_row*self._raw_bands) # note that we purposely read without considering skipping elements, which # is factored in (along with any potential order reversal) below out[i, :, :] = line[::range2[2]] return out
def _parse_int(val, length, default, name, instance): """ Parse and/or validate the integer input. Parameters ---------- val : None|int|bytes length : int default : None|int Returns ------- int """ if val is None: return default else: val = int_func(val) if -int_func(10)**(length-1) < val < int_func(10)**length: return val raise ValueError( 'Integer {} cannot be rendered as a string of {} characters for ' 'attribute {} of class {}'.format(val, length, name, instance.__class__.__name__))
def from_bytes(cls, value, start, subhead_len=0, item_len=0): """ Parameters ---------- value : bytes|str start : int subhead_len : int item_len : int Returns ------- _ItemArrayHeaders """ subhead_len, item_len = int_func(cls._subhead_len), int_func(cls._item_len) if len(value) < start + 3: raise ValueError('value must have length at least {}. Got {}'.format(start+3, len(value))) loc = start count = int_func(value[loc:loc+3]) length = 3 + count*(subhead_len + item_len) if len(value) < start + length: raise ValueError('value must have length at least {}. Got {}'.format(start+length, len(value))) loc += 3 subhead_sizes = numpy.zeros((count, ), dtype=numpy.int64) item_sizes = numpy.zeros((count, ), dtype=numpy.int64) for i in range(count): subhead_sizes[i] = int_func(value[loc: loc+subhead_len]) loc += subhead_len item_sizes[i] = int_func(value[loc: loc+item_len]) loc += item_len return cls(subhead_sizes, item_sizes)
def _prepare_output(self, row_range, col_range): row_count = int_func( (row_range[1] - row_range[0]) / float(row_range[2])) col_count = int_func( (col_range[1] - col_range[0]) / float(col_range[2])) out_size = (row_count, col_count, 3) return numpy.zeros(out_size, dtype=numpy.float64)
def write_support_array(self, identifier, data, start_indices=(0, 0)): """ Write support array data to the file. Parameters ---------- identifier : str data : numpy.ndarray start_indices : Tuple[int, int] """ def validate_bytes_per_pixel(): observed_bytes_per_pixel = int_func(data.nbytes / pixel_count) if observed_bytes_per_pixel != entry.BytesPerElement: raise ValueError( 'Observed bytes per pixel {} for support {}, expected ' 'bytes per pixel {}'.format(observed_bytes_per_pixel, entry.Identifier, entry.BytesPerElement)) if data.ndim < 2: raise ValueError( 'Provided support data is required to be at least two dimensional' ) pixel_count = data.shape[0] * data.shape[1] int_index = self._validate_support_index(identifier) identifier = self._validate_support_key(identifier) entry = self.crsd_meta.Data.SupportArrays[int_index] validate_bytes_per_pixel() start_indices = (int_func(start_indices[0]), int_func(start_indices[1])) rows = (start_indices[0], start_indices[0] + data.shape[0]) columns = (start_indices[1], start_indices[1] + data.shape[1]) if start_indices[0] < 0 or start_indices[1] < 0: raise IndexError( 'start_indices given as {}, but must have non-negative entries.' .format(start_indices)) if rows[1] > entry.NumRows or columns[1] > entry.NumCols: raise IndexError( 'start_indices given as {}, and given data has shape {}. This is ' 'incompatible with signal block of shape {}.' ''.format(start_indices, data.shape, (entry.NumRows, entry.NumCols))) total_pixels = entry.NumRows * entry.NumCols # write the data self._support_memmaps[identifier][rows[0]:rows[1], columns[0]:columns[1]] = data # update the count of written data self._writing_state['support'][identifier] += pixel_count # check if the written pixels is seemingly ridiculous or redundant if self._writing_state['support'][identifier] > total_pixels: logger.warning( 'Appear to have written {} total pixels to support array {},\n\t' 'which only has {} pixels.\n\t' 'This may be indicative of an error.'.format( self._writing_state['support'][identifier], identifier, total_pixels))
def get_image_data(): # type: () -> ImageDataType samp_prec = _stringify(hf['sample_precision'][()]) if samp_prec.upper() == 'INT16': pixel_type = 'RE16I_IM16I' elif samp_prec.upper() == 'FLOAT32': pixel_type = 'RE32F_IM32F' else: raise ValueError( 'Got unhandled sample precision {}'.format(samp_prec)) num_rows = int_func(number_of_range_samples) num_cols = int_func(number_of_azimuth_samples) scp_row = int_func(coord_center[0]) - 1 scp_col = int_func(coord_center[1]) - 1 if 0 < scp_col < num_rows - 1: if look_side == 'left': scp_col = num_cols - scp_col - 1 else: # early ICEYE processing bug led to nonsensical SCP scp_col = int_func(num_cols / 2.0) return ImageDataType(PixelType=pixel_type, NumRows=num_rows, NumCols=num_cols, FirstRow=0, FirstCol=0, FullImage=(num_rows, num_cols), SCPPixel=(scp_row, scp_col))
def validate_range(arg, siz): # type: (Union[None, int, Tuple[int, int], Tuple[int, int, int]], int) -> tuple """ Validate the range definition. Parameters ---------- arg : None|int|Tuple[int, int]|Tuple[int, int, int] siz : int Returns ------- tuple Of the form `(start, stop, step)`. """ start, stop, step = None, None, None if arg is None: pass elif isinstance(arg, integer_types): start = arg stop = arg + 1 step = 1 else: # NB: following this pattern to avoid confused pycharm inspection if len(arg) == 1: start = int(arg[0]) stop = start + 1 elif len(arg) == 2: start, stop = arg elif len(arg) == 3: start, stop, step = arg start = 0 if start is None else int_func(start) stop = siz if stop is None else int_func(stop) step = 1 if step is None else int_func(step) # basic validity check if not (-siz < start < siz): raise ValueError( 'Range argument {} has extracted start {}, which is required ' 'to be in the range [0, {})'.format(arg, start, siz)) if not (-siz < stop <= siz): raise ValueError( 'Range argument {} has extracted "stop" {}, which is required ' 'to be in the range [0, {}]'.format(arg, stop, siz)) if not (0 < abs(step) <= siz): raise ValueError( 'Range argument {} has extracted step {}, for an axis of length ' '{}'.format(arg, step, siz)) if ((step < 0) and (stop > start)) or ((step > 0) and (start > stop)): raise ValueError( 'Range argument {} has extracted start {}, stop {}, step {}, ' 'which is not valid.'.format(arg, start, stop, step)) # reform negative values for start/stop appropriately if start < 0: start += siz if stop < 0: stop += siz return start, stop, step
def __init__(self, tiff_details, symmetry=(False, False, True)): """ Parameters ---------- tiff_details : TiffDetails symmetry : Tuple[bool] """ if isinstance(tiff_details, str): tiff_details = TiffDetails(tiff_details) if not isinstance(tiff_details, TiffDetails): raise TypeError('NativeTiffChipper input argument must be a filename ' 'or TiffDetails object.') tiff_details.check_compression() tiff_details.check_tiled() self._tiff_details = tiff_details if isinstance(tiff_details.tags['SampleFormat'], numpy.ndarray): samp_form = tiff_details.tags['SampleFormat'][0] else: samp_form = tiff_details.tags['SampleFormat'] if samp_form not in self._SAMPLE_FORMATS: raise ValueError('Invalid sample format {}'.format(samp_form)) if isinstance(tiff_details.tags['BitsPerSample'], numpy.ndarray): bits_per_sample = tiff_details.tags['BitsPerSample'][0] else: bits_per_sample = tiff_details.tags['BitsPerSample'] raw_bands = int(tiff_details.tags['SamplesPerPixel']) if samp_form in [5, 6]: transform_data = 'COMPLEX' output_bands = int(raw_bands) raw_bands *= 2 bits_per_sample /= 2 output_dtype = 'complex64' elif raw_bands == 2: # NB: this is heavily skewed towards SAR and obviously not general transform_data = 'COMPLEX' output_dtype = 'complex64' output_bands = 1 else: transform_data = None output_bands = raw_bands output_dtype = None data_size = (int_func(tiff_details.tags['ImageLength']), int_func(tiff_details.tags['ImageWidth'])) raw_dtype = numpy.dtype('{0:s}{1:s}{2:d}'.format( self._tiff_details.endian, self._SAMPLE_FORMATS[samp_form], int(bits_per_sample/8))) if output_dtype is None: output_dtype = raw_dtype data_offset = int_func(tiff_details.tags['StripOffsets'][0]) super(NativeTiffChipper, self).__init__( tiff_details.file_name, raw_dtype, data_size, raw_bands, output_bands, output_dtype, symmetry=symmetry, transform_data=transform_data, data_offset=data_offset)
def _reorder_arguments(self, range1, range2): """ Reinterpret the range arguments into actual "physical" arguments of memory, in light of the symmetry attribute. Parameters ---------- range1 : None|int|tuple * if `None`, then the range is not limited in first axis * if `int` = step size * if (`int`, `int`) = `end`, `step size` * if (`int`, `int`, `int`) = `start`, `stop`, `step size` range2 : None|int|tuple same as `range1`, except for the second axis. Returns ------- None|int|tuple actual range 1 - in light of `range1`, `range2` and symmetry None|int|tuple actual range 2 - in light of `range1`, `range2` and symmetry """ if isinstance(range1, (numpy.ndarray, list)): range1 = tuple(int_func(el) for el in range1) if isinstance(range2, (numpy.ndarray, list)): range2 = tuple(int_func(el) for el in range2) if not (range1 is None or isinstance(range1, integer_types) or isinstance(range1, tuple)): raise TypeError('range1 is of type {}, but must be an instance of None, ' 'int or tuple.'.format(range1)) if isinstance(range1, tuple) and len(range1) > 3: raise TypeError('range1 must have no more than 3 entries, received {}.'.format(range1)) if not (range2 is None or isinstance(range2, integer_types) or isinstance(range2, tuple)): raise TypeError('range2 is of type {}, but must be an instance of None, ' 'int or tuple.'.format(range2)) if isinstance(range2, tuple) and len(range2) > 3: raise TypeError('range2 must have no more than 3 entries, received {}.'.format(range2)) # switch the axes symmetry dictates if self._symmetry[2]: range1, range2 = range2, range1 lim1, lim2 = self._data_size[1], self._data_size[0] else: lim1, lim2 = self._data_size[0], self._data_size[1] # validate the first range if self._symmetry[0]: real_arg1 = reverse_range(range1, lim1) else: real_arg1 = validate_range(range1, lim1) # validate the second range if self._symmetry[1]: real_arg2 = reverse_range(range2, lim2) else: real_arg2 = validate_range(range2, lim2) return real_arg1, real_arg2
def _parse_count(cls, value, start): loc = start count = int_func(value[loc:loc + cls._count_size]) loc += cls._count_size if count == 0: # (only) if there are more than 9, a longer field is used count = int_func(value[loc:loc + 5]) loc += 5 return count, loc
def _prepare_output(self, row_range, col_range, frames=None): row_count = int_func( (row_range[1] - row_range[0]) / float(row_range[2])) col_count = int_func( (col_range[1] - col_range[0]) / float(col_range[2])) if frames is None or len(frames) == 1: out_size = (row_count, col_count) else: out_size = (row_count, col_count, len(frames)) return numpy.zeros(out_size, dtype=numpy.complex64)
def _get_rows_per_block(self, max_block_size): pixel_type = self._writer.sicd_meta.ImageData.PixelType cols = int_func(self._writer.sicd_meta.ImageData.NumCols) bytes_per_row = 8*cols if pixel_type == 'RE32F_IM32F': bytes_per_row = 8*cols elif pixel_type == 'RE16I_IM16I': bytes_per_row = 4*cols elif pixel_type == 'AMP8I_PHS8I': bytes_per_row = 2*cols return max(1, int_func(round(max_block_size/bytes_per_row)))
def from_node(cls, node, xml_ns, ns_key=None, kwargs=None): dim1 = int_func(node.attrib['size']) dim2 = int_func(node.attrib['numLuts']) arr = numpy.zeros((dim1, dim2), dtype=numpy.uint16) lut_key = cls._child_xml_ns_key.get('LUTValues', ns_key) lut_nodes = find_children(node, 'LUTValues', xml_ns, lut_key) for i, lut_node in enumerate(lut_nodes): arr[:, i] = [str(el) for el in get_node_value(lut_node)] if numpy.max(arr) < 256: arr = numpy.cast[numpy.uint8](arr) return cls(LUTValues=arr)
def from_node(cls, node, xml_ns, ns_key=None, kwargs=None): num_phasings = int_func(node.attrib['numPhasings']) num_points = int_func(node.attrib['numPoints']) coefs = numpy.zeros((num_phasings+1, num_points+1), dtype=numpy.float64) ckey = cls._child_xml_ns_key.get('Coefs', ns_key) coef_nodes = find_children(node, 'Coef', xml_ns, ckey) for cnode in coef_nodes: ind1 = int_func(cnode.attrib['phasing']) ind2 = int_func(cnode.attrib['point']) val = float(get_node_value(cnode)) coefs[ind1, ind2] = val return cls(Coefs=coefs)
def _parse_attribute(cls, fields, attribute, value, start): if attribute == 'data': length = int_func(value[start:start + cls._size_len]) start += cls._size_len if length > 0: ofl = int_func(value[start:start+cls._ofl_len]) fields['OFL'] = ofl fields['data'] = value[start+cls._ofl_len:start + length] else: fields['OFL'] = 0 fields['data'] = None return start + length return super(UserHeaderType, cls)._parse_attribute(fields, attribute, value, start)
def other_axis_deskew(t_full_data, fft_sgn): # We cannot generally deskew in both directions at once, but we # can recenter the nonskewed dimension with a uniform shift if numpy.any(self._delta_kcoa_poly_off_axis != 0): # get deltakcoa at midpoint, and treat as a constant polynomial row_mid = row_array[int_func(round(0.5 * row_array.size)) - 1] col_mid = col_array[int_func(round(0.5 * col_array.size)) - 1] delta_kcoa_new_const = numpy.zeros((1, 1), dtype='float64') delta_kcoa_new_const[0, 0] = polynomial.polyval2d( row_mid, col_mid, self._delta_kcoa_poly_off_axis) # apply this uniform shift t_full_data = _deskew_array( t_full_data, delta_kcoa_new_const, row_array, col_array, fft_sgn, 1-self.dimension) return t_full_data
def __init__(self, data_size, symmetry=(False, False, False), complex_type=False): """ Parameters ---------- data_size : tuple The full size of the data *after* any required transformation. See `data_size` property. symmetry : tuple Describes any required data transformation. See the `symmetry` property. complex_type : callable|bool For complex type handling. If callable, then this is expected to transform the raw data to the complex data. If this evaluates to `True`, then the assumption is that real/imaginary components are stored in adjacent bands, which will be combined into a single band upon extraction. """ if not (isinstance(complex_type, bool) or callable(complex_type)): raise ValueError('complex-type must be a boolean or a callable') self._complex_type = complex_type if not isinstance(symmetry, tuple): symmetry = tuple(symmetry) if len(symmetry) != 3: raise ValueError( 'The symmetry parameter must have length 3, and got {}.'. format(symmetry)) self._symmetry = tuple([bool(entry) for entry in symmetry]) if not isinstance(data_size, tuple): data_size = tuple(data_size) if len(data_size) != 2: raise ValueError( 'The data_size parameter must have length 2, and got {}.'. format(data_size)) data_size = (int_func(data_size[0]), int_func(data_size[1])) if data_size[0] < 0 or data_size[1] < 0: raise ValueError( 'All entries of data_size {} must be non-negative.'.format( data_size)) if self._symmetry[2]: self._data_size = (data_size[1], data_size[0]) else: self._data_size = data_size
def pixel_count(self, value): if value is None: self._pixel_count = None return if not isinstance(value, integer_types): value = int_func(value) self._pixel_count = value
def _get_sicd_time_args(sicd, subdivisions=24): # type: (SICDType, Union[int, None]) -> (dict, Union[None, numpy.ndarray]) """ Fetch the SICD time arguments and array. Parameters ---------- sicd : SICDType subdivisions : int|None Returns ------- (dict, None|numpy.ndarray) """ if sicd.Timeline is None or sicd.Timeline.CollectStart is None: return {}, None beg_time = sicd.Timeline.CollectStart.astype('datetime64[us]') if sicd.Timeline.CollectDuration is None: return { 'when': str(beg_time) + 'Z', }, None end_time = beg_time + int_func(sicd.Timeline.CollectDuration * 1e6) if not isinstance(subdivisions, integer_types) or subdivisions < 2: time_array = None else: time_array = numpy.linspace(0, sicd.Timeline.CollectDuration, subdivisions) return { 'beginTime': str(beg_time) + 'Z', 'endTime': str(end_time) + 'Z' }, time_array
def get_dimension_details(the_range): full_count = abs(int_func(the_range[1] - the_range[0])) the_snip = -1 if the_range[2] < 0 else 1 t_filter_map = filter_map_construction(full_count/self.fill) t_block_size = self.get_fetch_block_size(the_range[0], the_range[1]) t_full_range = (the_range[0], the_range[1], the_snip) return t_filter_map, t_block_size, t_full_range
def dimension(self, value): value = int_func(value) if value not in [0, 1]: raise ValueError('dimension must be 0 or 1, got {}'.format(value)) self._dimension = value if self._sicd is not None: self._set_sicd(self._sicd)
def is_normalized(sicd, dimension=1): """ Check if the sicd structure is normalized along the provided dimension. Parameters ---------- sicd : SICDType The SICD structure. dimension : int The dimension to test. Returns ------- bool normalization state in the given dimension """ def _is_fft_sgn_negative(): if dimension == 0: if sicd.Grid is None or sicd.Grid.Row is None or sicd.Grid.Row.Sgn is None: return True return sicd.Grid.Row.Sgn == -1 else: if sicd.Grid is None or sicd.Grid.Col is None or sicd.Grid.Col.Sgn is None: return True return sicd.Grid.Col.Sgn == -1 dimension = int_func(dimension) if dimension not in [0, 1]: raise ValueError( 'dimension must be either 0 or 1, got {}'.format(dimension)) return is_not_skewed(sicd, dimension) and is_uniform_weight(sicd, dimension) and \ _is_fft_sgn_negative()
def read_pvp_vector(self, variable, index, the_range=None): frm = 'd' # all fields in CPHD 0.3 are of double type # fetch the header object header = self.cphd_header # fetch the appropriate details from the cphd structure cphd_meta = self.cphd_meta data = cphd_meta.Data if not isinstance(index, integer_types): index = int_func(index) if not (0 <= index < data.NumCPHDChannels): raise ValueError('index must be in the range [0, {})'.format( data.NumCPHDChannels)) row_count = data.ArraySize[index].NumVectors # get overall offset pvp_block_offset = header.VB_BYTE_OFFSET # get offset for this vector block pvp_offset = data.NumBytesVBP * index vector_size = data.NumBytesVBP # see if this variable/field is sensible result = cphd_meta.VectorParameters.get_position_offset_and_size( variable) if result is None: return None field_offset, fld_siz = result return self._read_pvp_vector(pvp_block_offset, pvp_offset, vector_size, field_offset, frm, fld_siz, row_count, the_range)
def _validate_index(self, index): """ Get corresponding integer index for CPHD channel. Parameters ---------- index : int|str Returns ------- None|int """ cphd_meta = self.cphd_details.cphd_meta if isinstance(index, string_types): for i, channel in enumerate(cphd_meta.Data.Channels): if channel.Identifier == index: return i raise KeyError( 'Cannot find CPHD channel for identifier {}'.format(index)) else: int_index = int_func(index) if not (0 <= int_index < cphd_meta.Data.NumCPHDChannels): raise ValueError('index must be in the range [0, {})'.format( cphd_meta.Data.NumCPHDChannels)) return int_index
def _validate_support_key(self, index): """ Gets the corresponding identifier for the support array. Parameters ---------- index : int|str Returns ------- str """ if isinstance(index, string_types): if index in self._support_map: return index else: raise KeyError( 'Cannot find support array for identifier {}'.format( index)) else: int_index = int_func(index) if not (0 <= int_index < len(self.crsd_meta.Data.SupportArrays)): raise ValueError('index must be in the range [0, {})'.format( len(self.crsd_meta.Data.SupportArrays))) return self.crsd_meta.Data.SupportArrays[int_index].Identifier
def _parse_attribute(cls, fields, attribute, value, start): if attribute == 'data': length = int_func(value[start:start + cls._size_len]) start += cls._size_len fields['data'] = value[start:start + length] return start + length return super(Unstructured, cls)._parse_attribute(fields, attribute, value, start)
def from_bytes(cls, value, start): tag_value = value[start:start + 6].decode('utf-8').strip() lng = int_func(value[start + 6:start + 11]) if tag_value != cls._tag_value: raise ValueError('tag value must be {}. Got {}'.format( cls._tag_value, tag_value)) return cls(value[start + 11:start + 11 + lng])