vc2-static-filter-analysis

This command statically analyses a VC-2 filter configuration to determine mathematical expressions for worst-case signal ranges and generate test patterns.

Example usage

A simple 2-level LeGall (5, 3) transform:

$ vc2-static-filter-analysis \
    --wavelet-index le_gall_5_3 \
    --dwt-depth 2 \
    --output static_analysis.json

A more complex asymmetric transform:

$ vc2-static-filter-analysis \
    --wavelet-index haar_with_shift \
    --wavelet-index-ho le_gall_5_3 \
    --dwt-depth 1 \
    --dwt-depth-ho 2 \
    --output static_analysis.json

Arguments

The complete set of arguments can be listed using --help

usage: vc2-static-filter-analysis [-h] --wavelet-index WAVELET_INDEX
                                  [--wavelet-index-ho WAVELET_INDEX_HO]
                                  [--dwt-depth DWT_DEPTH]
                                  [--dwt-depth-ho DWT_DEPTH_HO]
                                  [--num-batches NUM_BATCHES]
                                  [--batch-num BATCH_NUM] [--output OUTPUT]
                                  [--verbose]

This command statically analyses a VC-2 filter configuration to determine
mathematical expressions for worst-case signal ranges and generate test
patterns. Writes the output to a JSON file.

optional arguments:
  -h, --help            show this help message and exit
  --wavelet-index WAVELET_INDEX, -w WAVELET_INDEX
                        The VC-2 wavelet index for the wavelet transform. One
                        of: 0 or deslauriers_dubuc_9_7, 1 or le_gall_5_3, 2 or
                        deslauriers_dubuc_13_7, 3 or haar_no_shift, 4 or
                        haar_with_shift, 5 or fidelity, 6 or daubechies_9_7.
  --wavelet-index-ho WAVELET_INDEX_HO, -W WAVELET_INDEX_HO
                        The VC-2 wavelet index for the horizontal parts of the
                        wavelet transform. If not specified, assumed to be the
                        same as --wavelet-index/-w.
  --dwt-depth DWT_DEPTH, -d DWT_DEPTH
                        The VC-2 transform depth. Defaults to 0 if not
                        specified.
  --dwt-depth-ho DWT_DEPTH_HO, -D DWT_DEPTH_HO
                        The VC-2 horizontal-only transform depth. Defaults to
                        0 if not specified.
  --num-batches NUM_BATCHES, -B NUM_BATCHES
                        If the analysis is to be performed in a series of
                        smaller batches, the number of batches to split it
                        into.
  --batch-num BATCH_NUM, -b BATCH_NUM
                        When --num-batches is used, the specific the batch to
                        run.
  --output OUTPUT, -o OUTPUT
                        The name of the file to write the computed JSON output
                        to. Defaults to stdout.
  --verbose, -v         Show more detailed status information during
                        execution.

JSON file format

The output of vc2-static-filter-analysis is a JSON file which has the following structure:

{
    "wavelet_index": <int>,
    "wavelet_index_ho": <int>,
    "dwt_depth": <int>,
    "dwt_depth_ho": <int>,
    "analysis_signal_bounds": [<signal-bounds>, ...],
    "synthesis_signal_bounds": [<signal-bounds>, ...],
    "analysis_test_patterns": [<test-pattern-specification>, ...],
    "synthesis_test_patterns": [<test-pattern-specification>, ...],
}

Signal bounds

The "analysis_signal_bounds" and "synthesis_signal_bounds" lists define algebraic expressions for the upper- and lower-bounds for each analysis and synthesis filter phase (see Terminology) as follows:

<signal-bounds> = {
    "level": <int>,
    "array_name": <string>,
    "phase": [<int>, <int>],
    "lower_bound": <algebraic-expression>,
    "upper_bound": <algebraic-expression>,
}

<algebraic-expression> = [
    {
        "symbol": <string-or-null>,
        "numer": <string>,
        "denom": <string>,
    },
    ...
]

Note

The deserialise_signal_bounds() Python utility function is provided for unpacking this structure.

Each <algebraic-expression> defines an algebraic linear expression. As an example, the following expression:

\[\frac{2}{3}a + 5b - 2\]

Would be represented in JSON form as:

[
    {"symbol": "a", "numer": "2", "denom": "3"},
    {"symbol": "b", "numer": "5", "denom": "1"},
    {"symbol": null, "numer": "-2", "denom": "1"},
]

In the expressions defining the analysis filter signal levels, the following symbols are used:

  • signal_min – The minimum picture signal value (e.g. -512 for 10 bit signals).

  • signal_max – The minimum picture signal value (e.g. 511 for 10 bit signals).

In the expressions defining the synthesis filter signal levels, symbols with the form coeff_<level>_<orient>_min and coeff_<level>_<orient>_min are used. For example coeff_1_LL_min would mean the minimum value a level-1 ‘LL’ subband value could have.

Test patterns

The "analysis_test_patterns and "synthesis_test_patterns lists define test patterns for each analysis and synthesis filter phase like so:

<test-pattern-specification> = {
    "level": <int>,
    "array_name": <string>,
    "phase": [<int>, <int>],
    "target": [<int>, <int>],
    "target_transition_multiple": [<int>, <int>],
    "pattern": <test-pattern>,
    "pattern_transition_multiple": [<int>, <int>],
}

<test-pattern> = {
    "dx": <int>,
    "dy": <int>,
    "width": <int>,
    "height": <int>,
    "positive": <string>,
    "mask": <string>,
}

Note

The deserialise_test_pattern_specifications() Python utility function is provided for unpacking this structure.

Test patterns are defined in terms of a collection of pixel polarity values which indicate which pixels should be set to their maximum level and which should be set to their minimum. All other pixel values may be set arbitrarily. For the encoding used by the <test-pattern> object to encode the pixel polarities themselves, see serialise_test_pattern.

Test patterns must be carefully aligned within a test picture when used. See TestPatternSpecification for the meaning of the relevant fields of <test-pattern-specification>. .

Missing values

Only intermediate arrays are included which contain novel values. Arrays which are just renamings, interleavings and subsamplings of other arrays are omitted.

Runtime and memory consumption

For typical ‘real world’ filter configurations, this command should complete within a few seconds and use a trivial amount of memory.

For larger wavelets (e.g. the fidelity filter) and deeper transforms (e.g. three or more levels), the runtime and memory requirements can grow significantly. For example, a 4-level LeGall (5, 3) transform will take on the order of an hour to analyse. As an especially extreme case, a 4-level Fidelity wavelet will require around 16 GB of RAM and several weeks to complete.

The --verbose option provides useful progress information as the static analysis process proceeds. As a guide, the vast majority of the runtime will be spent on the synthesis filters due to their far greater number. RAM usage grows rapidly during the processing of the analysis filters and then only grow very slightly during synthesis filter analysis.

Batched/parallel execution

When analysing extremely large filters, it might be useful to split the analysis process into multiple batches to be executed simultaneously on several cores or computers.

To run the analysis process in batched mode, the --num-batches argument must be given specifying the total number of batches the execution will be split into. Each batch must also be given a --batch-num argument specifying which batch is to be executed. For example, the following commands might be run on four machines to parallelise the analysis of a 3-level Fidelity filter.

$ vc2-static-filter-analysis \
    --wavelet-index fidelity \
    --depth 3 \
    --num-batches 4 \
    --batch-num 0 \
    --output static_analysis_batch_0.json

$ vc2-static-filter-analysis \
    --wavelet-index fidelity \
    --depth 3 \
    --num-batches 4 \
    --batch-num 1 \
    --output static_analysis_batch_1.json

$ vc2-static-filter-analysis \
    --wavelet-index fidelity \
    --depth 3 \
    --num-batches 4 \
    --batch-num 2 \
    --output static_analysis_batch_2.json

$ vc2-static-filter-analysis \
    --wavelet-index fidelity \
    --depth 3 \
    --num-batches 4 \
    --batch-num 3 \
    --output static_analysis_batch_3.json

Once all four analyses have finished, the results are then combined together using the vc2-static-filter-analysis-combine utility:

$ vc2-static-filter-analysis-combine \
    static_analysis_batch_0.json \
    static_analysis_batch_1.json \
    static_analysis_batch_2.json \
    static_analysis_batch_3.json \
    --output static_analysis.json

Warning

Each batch may still require the same amount of RAM as a complete analysis.

Warning

The batching process requires some duplicated processing in each batch. Consequently more total CPU time may be required than non-batched execution.

Warning

Though batches are intended to take similar amounts of time to execute, this is not guaranteed.