def test_relative_step_size_to(self): a = SymbolArray(3) s1 = SubsampledArray(a, (1, 2, 3), (4, 5, 6)) assert s1.relative_step_size_to(a) == (1, 2, 3) assert s1.relative_step_size_to(s1) == (1, 1, 1) assert s1.relative_step_size_to(SymbolArray(3, "nope")) is None s2 = SubsampledArray(s1, (11, 22, 33), (4, 5, 6)) assert s2.relative_step_size_to(a) == (11 * 1, 22 * 2, 33 * 3) assert s2.relative_step_size_to(s1) == (11, 22, 33) assert s2.relative_step_size_to(s2) == (1, 1, 1)
def test_period_one_complex(self): # A A A B B B # a = A A A b = B B B # A A A B B B a = SymbolArray(2, "A") b = SymbolArray(2, "B") # A B A # ab = A B A # A B A ab = InterleavedArray(a, b, 0) # A*2 B*2 A*2 # ab2 = A*2 B*2 A*2 # A*2 B*2 A*2 ab2 = LeftShiftedArray(ab, 1) # B*2 B*2 B*2 # b2 = B*2 B*2 B*2 # B*2 B*2 B*2 b2 = SubsampledArray(ab2, (2, 1), (1, 0)) spca = SymbolicPeriodicCachingArray(b2, a, b) model_answers = {(x, y): b2[x, y] for x in range(3) for y in range(3)} ab2._cache.clear() # Should produce equivalent results to wrapped array for (x, y), exp_answer in model_answers.items(): assert spca[x, y] == exp_answer # Shouldn't have requested anything but the 0th phase of the wrapped # array assert list(ab2._cache) == [(1, 0)]
def test_relative_step_size_to(self): a = SymbolArray(2) s = SubsampledArray(a, (2, 3), (0, 0)) spca = SymbolicPeriodicCachingArray(s, a) assert spca.relative_step_size_to(a) == (2, 3) assert spca.relative_step_size_to(spca) == (1, 1) assert spca.relative_step_size_to(SymbolArray(2, "nope")) is None
def test_relative_step_size_to(self): a = SymbolArray(2) s = SubsampledArray(a, (2, 3), (0, 0)) l = LeftShiftedArray(s, 123) assert l.relative_step_size_to(a) == (2, 3) assert l.relative_step_size_to(l) == (1, 1) assert l.relative_step_size_to(SymbolArray(2, "nope")) is None
def test_subsampling(self): a = SymbolArray(3, "v") s = SubsampledArray(a, (1, 2, 3), (0, 10, 20)) assert s[0, 0, 0] == LinExp(("v", 0, 10, 20)) assert s[1, 0, 0] == LinExp(("v", 1, 10, 20)) assert s[0, 1, 0] == LinExp(("v", 0, 12, 20)) assert s[0, 0, 1] == LinExp(("v", 0, 10, 23)) assert s[2, 2, 2] == LinExp(("v", 2, 14, 26))
def test_period(self, input_period, steps, exp_period): a = RepeatingSymbolArray(input_period) s = SubsampledArray(a, steps, (0, ) * len(steps)) assert s.period == exp_period assert period_empirically_correct(s)
def test_nop(self): a = SymbolArray(3, "v") s = SubsampledArray(a, (1, 2, 3), (0, 10, 20)) assert s.nop is True
def test_bad_arguments(self, steps, offsets): a = SymbolArray(3, "v") with pytest.raises(TypeError): SubsampledArray(a, steps, offsets)
def analysis_transform(h_filter_params, v_filter_params, dwt_depth, dwt_depth_ho, array): """ Perform a multi-level VC-2 analysis Discrete Wavelet Transform (DWT) on a :py:class:`InfiniteArray` in a manner which is the complement of the 'idwt' pseudocode function described in (15.4.1) in the VC-2 standard. Parameters ========== h_filter_params, v_filter_params : :py:class:`vc2_data_tables.LiftingFilterParameters` Horizontal and vertical filter parameters for the corresponding *synthesis* trhansform (e.g. from :py:data:`vc2_data_tables.LIFTING_FILTERS`). These filter parameters will be transformed into analysis lifting stages internally. dwt_depth, dwt_depth_ho: int Transform depths for 2D and horizontal-only transforms. array : :py:class:`InfiniteArray` The array representing the picture to be analysed. Returns ======= coeff_arrays : {level: {orientation: :py:class:`InfiniteArray`, ...}, ...} The output transform coefficient values. These nested dictionaries are indexed the same way as 'coeff_data' in the idwt pseudocode function in (15.4.1) in the VC-2 specification. intermediate_arrays : {(level, array_name): :py:class:`InfiniteArray`, ...} All intermediate (and output) value arrays, named according to the convention described in :ref:`terminology`. This value is returned as an :py:class:`~collections.OrderedDict` giving the arrays in their order of creation; a sensible order for display purposes. """ intermediate_arrays = OrderedDict() h_filter_params = convert_between_synthesis_and_analysis(h_filter_params) v_filter_params = convert_between_synthesis_and_analysis(v_filter_params) input = array for level in reversed(range(1, dwt_depth_ho + dwt_depth + 1)): intermediate_arrays[(level, "Input")] = input # Bit shift dc = intermediate_arrays[(level, "DC")] = LeftShiftedArray( input, h_filter_params.filter_bit_shift, ) # Horizontal lifting stages for num, stage in enumerate(h_filter_params.stages): name = "DC{}".format("'" * (num + 1)) dc = intermediate_arrays[(level, name)] = LiftedArray(dc, stage, 0) # Horizontal subsample l = intermediate_arrays[(level, "L")] = SubsampledArray(dc, (2, 1), (0, 0)) h = intermediate_arrays[(level, "H")] = SubsampledArray(dc, (2, 1), (1, 0)) if level > dwt_depth_ho: # Vertical lifting stages for num, stage in enumerate(v_filter_params.stages): name = "L{}".format("'" * (num + 1)) l = intermediate_arrays[(level, name)] = LiftedArray(l, stage, 1) name = "H{}".format("'" * (num + 1)) h = intermediate_arrays[(level, name)] = LiftedArray(h, stage, 1) # Vertical subsample ll = intermediate_arrays[(level, "LL")] = SubsampledArray( l, (1, 2), (0, 0)) lh = intermediate_arrays[(level, "LH")] = SubsampledArray( l, (1, 2), (0, 1)) hl = intermediate_arrays[(level, "HL")] = SubsampledArray( h, (1, 2), (0, 0)) hh = intermediate_arrays[(level, "HH")] = SubsampledArray( h, (1, 2), (0, 1)) input = ll else: input = l # Separately enumerate just the final output arrays coeff_arrays = {} for level in range(1, dwt_depth_ho + dwt_depth + 1): coeff_arrays[level] = {} if level > dwt_depth_ho: for orient in ["LH", "HL", "HH"]: coeff_arrays[level][orient] = intermediate_arrays[(level, orient)] else: coeff_arrays[level]["H"] = intermediate_arrays[(level, "H")] if dwt_depth_ho > 0: coeff_arrays[0] = {"L": input} else: coeff_arrays[0] = {"LL": input} return coeff_arrays, intermediate_arrays