# cwtLayer

## Description

A CWT layer computes the CWT of the input. Use of this layer requires Deep Learning Toolbox™.

## Creation

### Description

creates a CWT layer for a
signal of length 1024 samples. The layer uses 10 wavelet filters per octave and periodic
boundary conditions. By default, the layer uses the analytic Morse (3,60) wavelet.`layer`

= cwtLayer

The input to `cwtLayer`

must be a `dlarray`

(Deep Learning Toolbox) object in
`"CBT"`

format. The size along the time dimension of the tensor input
is padded to equal the value of SignalLength. By default, `cwtLayer`

formats the output as
`"SCBT"`

. For more information, see Layer Output Format.

**Note**

`cwtLayer`

initializes the weights internally to be the wavelet
filters used in the CWT. It is not recommended to initialize the weights
directly.

creates a CWT layer with properties
specified by one or more name-value arguments. For example, `layer`

= cwtLayer(`Name=Value`

)```
layer =
cwtLayer(Wavelet="amor")
```

creates a layer that uses the analytic Morlet wavelet
in the CWT. You can specify multiple name-value arguments.

## Properties

### CWT

`SignalLength`

— Signal length in samples

`1024`

(default) | positive integer

Signal length in samples, specified as a positive integer greater than or equal
to 4. All sequence inputs to `cwtLayer`

are padded to have size
`SignalLength`

along the time dimension.

**Data Types: **`single`

| `double`

`Wavelet`

— Analysis wavelet

`"Morse"`

(default) | `"amor"`

| `"bump"`

Analysis wavelet used in the CWT, specified as `"Morse"`

,
`"amor"`

, or `"bump"`

, representing the analytic
Morse, Morlet (Gabor), and bump wavelet, respectively. The default wavelet is the
analytic Morse (3,60) wavelet.

`Threshold`

— Weight threshold

`1e–8`

(default) | positive real scalar

Weight threshold, specified as a positive real scalar. `cwtLayer`

uses the threshold value to determine the significant values for each of the CWT
filters in the wavelet filter bank prior to any weight modification through learning.
It sets values below the specified threshold to zero and excludes them from learning.
The CWT filters are normalized so that the peak value is 2 for each filter.

Smaller values of

`Threshold`

result in more values being retained from the CWT filters and therefore less weight reduction.Larger values of

`Threshold`

result in more weight reduction and more divergence between the deep learning CWT and transforms computed with the full filter bank.A threshold less than

`realmin`

, the smallest positive normalized floating-point number in double precision, is clipped to`realmin`

for computing significant filter values.

Setting `Threshold`

to a value which results in no
values being retained for any individual filter results in an error.

**Data Types: **`single`

| `double`

`IncludeLowpass`

— Include lowpass filter

`false`

or `0`

(default) | `true`

or `1`

Include lowpass filter, specified as a numeric or logical `1`

(`true`

) or `0`

(`false`

).
Specify `true`

to include the lowpass (scaling) filter in the
CWT.

**Data Types: **`logical`

`VoicesPerOctave`

— Number of voices per octave

`10`

(default) | integer between 1 and 48

Number of voices per octave in the CWT, specified as an integer between 1 and 48. The CWT scales are discretized using the specified number of voices per octave. The energy spread of the wavelet in frequency and time automatically determines the minimum and maximum scales.

You can use `cwtfreqbounds`

to determine the frequency limits of the wavelet filter
bank. The frequency limits depend on parameters such as the energy spread of the
wavelet, number of voices per octave, and signal length.

**Data Types: **`single`

| `double`

`FrequencyLimits`

— Frequency limits

two-element scalar vector

Frequency limits for the CWT, specified as a two-element vector with positive strictly increasing entries. The frequency limits are interpreted as normalized frequencies, cycles/sample.

The first element specifies the lowest peak passband frequency and must be greater than or equal to the product of the wavelet peak frequency in normalized frequency and two time standard deviations divided by SignalLength.

The second element specifies the highest peak passband frequency and must be less than or equal to the Nyquist frequency.

The base-2 logarithm of the ratio of the upper frequency limit
`freqMax`

to the lower frequency limit `freqMin`

must be greater than or equal to 1/VoicesPerOctave:

`log`

._{2}(freqMax/freqMin) ≥
1/VoicesPerOctave

For more information, see CWT Frequency Limits.

To obtain normalized frequencies, divide your desired frequency limits in hertz by the sample rate in hertz. For example, if the sample rate is 1000 Hz and your desired frequency limits are [100,400] Hz, divide each element by 1000 to obtain the normalized frequencies: [100/1000,400/1000].

Frequency limits apply only to wavelet filters. If you additionally specify
`IncludeLowpass`

as `true`

,
`cwtLayer`

also includes the lowpass (scaling) filter.

**Note**

If you use **Deep Network
Designer (Deep Learning Toolbox)** to create or edit a deep learning network, and change the
`Wavelet`

property of a **cwtLayer**, the app does not change the frequency limits of the layer.
If you want the app to provide the default frequency limits appropriate for the new
wavelet, you must take additional steps. For more information, see Reset Frequency Limits to Default Values in Deep Network Designer.

**Data Types: **`single`

| `double`

`TimeBandwidth`

— Time-bandwidth product for Morse wavelet

`60`

(default) | positive scalar

Time-bandwidth product for the Morse wavelet, specified as a positive scalar
greater than or equal to 3 and less than or equal to 120. The symmetry (gamma) of the
Morse wavelet is fixed at 3. This property is only valid when
`Wavelet`

is `"Morse"`

. The time-bandwidth
product is ignored for the `"amor"`

and `"bump"`

wavelets. For Morse wavelets, the larger the time-bandwidth product, the more spread
out the wavelet is in time and narrower the wavelet is in frequency.

In the notation of Morse Wavelets,
`TimeBandwidth`

is
*P*^{2}.

**Data Types: **`single`

| `double`

`TransformMode`

— Layer transform mode

`"mag"`

(default) | `"squaremag"`

| `"realimag"`

Layer transform mode, specified as one of these:

`"mag"`

— CWT magnitude`"squaremag"`

— CWT squared magnitude`"realimag"`

— CWT real and imaginary parts concatenated along the channel dimension

### Layer

`WeightLearnRateFactor`

— Multiplier for weight learning rate

`0`

(default) | nonnegative scalar

Multiplier for weight learning rate, specified as a nonnegative scalar. The
weights are the reduced CWT filter values represented as a
1-by-1-by-*Nr* tensor. See `cwtfilters2array`

for details. By default, the weights do not update with
training.

**Data Types: **`single`

| `double`

`Name`

— Layer name

`''`

(default) | character vector | string scalar

Layer name, specified as a character vector or a string scalar.
For `Layer`

array input, the `trainNetwork`

(Deep Learning Toolbox), `assembleNetwork`

(Deep Learning Toolbox), `layerGraph`

(Deep Learning Toolbox), and
`dlnetwork`

(Deep Learning Toolbox) functions automatically assign
names to layers with the name `''`

.

**Data Types: **`char`

| `string`

`NumInputs`

— Number of inputs

`1`

(default)

This property is read-only.

Number of inputs of the layer. This layer accepts a single input only.

**Data Types: **`double`

`InputNames`

— Input names

`{"in"}`

(default)

This property is read-only.

Input names of the layer. This layer accepts a single input only.

**Data Types: **`cell`

`NumOutputs`

— Number of outputs

`1`

(default)

This property is read-only.

Number of outputs of the layer. This layer has a single output only.

**Data Types: **`double`

`OutputNames`

— Output names

`{'out'}`

(default)

This property is read-only.

Output names of the layer. This layer has a single output only.

**Data Types: **`cell`

## Object Functions

`filterbank` | Full-weight CWT filter bank for deep learning |

## Examples

### Use `cwtLayer`

in Deep Learning Network

Create a CWT layer for a signal of length 2000 samples. Set the learning rate factor to 1.

cLayer = cwtLayer(SignalLength=2000,WeightLearnRateFactor=1);

Create a three-layer `dlnetwork`

containing a sequence input layer, the CWT layer you just made, and a 2-D max pooling layer.

```
sqLayer = sequenceInputLayer(1,Name="input",MinLength=2000);
mpLayer = maxPooling2dLayer([2 25],Stride=[2 12]);
layers = [sqLayer
cLayer
mpLayer];
dlnet = dlnetwork(layers);
```

Run a batch of 10 random single-channel signals through the `dlnetwork`

.

dataout = forward(dlnet, ... dlarray(randn(1,10,2000,"single"),"CBT")); size(dataout)

`ans = `*1×4*
40 1 10 165

dims(dataout)

ans = 'SCBT'

### Compare CWT With `cwtLayer`

and Filter Bank

Load the Espiga3 EEG dataset. The data consists of 23 channels of EEG sampled at 200 Hz. There are 995 samples in each channel. Save the multisignal as a `dlarray`

, specifying the dimensions in order. `dlarray`

permutes the array dimensions to the `"CBT"`

shape expected by a deep learning network.

load Espiga3 [N,nch] = size(Espiga3); x = dlarray(Espiga3,"TCB"); whos Espiga3 x

Name Size Bytes Class Attributes Espiga3 995x23 183080 double x 23x1x995 183110 dlarray

Create a CWT filter bank that is appropriate for the channels in the dataset. Use the default analytic Morse (3,60) wavelet. Specify periodic boundary conditions. Use the filter bank to obtain the CWT of one of the channels. The CWT is a 2-D matrix. The row dimension corresponds to scale, or frequency, and the column dimension corresponds to time.

```
fb = cwtfilterbank(SignalLength=N,Boundary="periodic");
colInd = 11;
cfs = wt(fb,Espiga3(:,colInd));
```

**Layer Transform Mode — "mag"**

Create a CWT layer that can be used with the EEG data. By default, the layer outputs the absolute value of the CWT, or scalogram, of each channel.

clayer = cwtLayer(SignalLength=N);

Create a two-layer `dlnetwork`

object containing a sequence input layer and the CWT layer you just created. Treat each channel as a feature. Specify the signal length as the minimum sequence length for the input layer.

slayer = sequenceInputLayer(nch,MinLength=N); layers = [slayer clayer]; dlnet = dlnetwork(layers);

Run the EEG data through the `forward`

method of the network.

dataout = forward(dlnet,x);

By default, the output of `cwtLayer`

is a `dlarray`

object in `"SCBT"`

format. The spatial dimension corresponds to frequency. Convert the network output to a numeric array. Permute the dimensions of the network output to correspond with `"STCB"`

format. The result is a 3-D numeric array because there is only one batch.

q = extractdata(dataout); q = permute(q,[1 4 2 3]); whos q cfs

Name Size Bytes Class Attributes cfs 71x995 1130320 double complex q 71x995x23 6499340 single

Extract from the output the result that corresponds to the channel you chose. Compare with the absolute value of the CWT you obtained previously.

r = q(:,:,colInd); d = max(abs(r(:)-abs(cfs(:)))); str = sprintf("Difference: %g",d); fprintf("%s\n",str)

Difference: 8.86966e-06

subplot(2,1,1) imagesc(r) title("Layer Output") subplot(2,1,2) imagesc(abs(cfs)) title("Filter Bank Output")

**Layer Transform Mode — "realimag"**

Create a CWT layer that can be used with the data. Specify the layer outputs to be the real and imaginary parts of the CWT. Create a two-layer `dlnetwork`

object containing a sequence input layer and the CWT layer. Run the EEG data through the `forward`

method of the network.

```
clayer2 = cwtLayer(SignalLength=N,TransformMode="realimag");
layers2 = [slayer
clayer2];
dlnet2 = dlnetwork(layers2);
dataout2 = forward(dlnet2,x);
```

Convert the network output to a numeric array. Permute the dimensions of the network output to correspond with `"STCB"`

format. Because the output are the real and imaginary parts of the CWT, the size of the channel dimension is twice the number of input channels.

```
q2 = extractdata(dataout2);
q2 = permute(q2,[1 4 2 3]);
whos q2
```

Name Size Bytes Class Attributes q2 71x995x46 12998680 single

Choose a channel. Use the CWT filter bank to obtain the CWT of that channel. Compare the real and imaginary parts of the CWT with the corresponding results from the network output.

colInd = 23; cfs = wt(fb,Espiga3(:,colInd)); r = q2(:,:,[colInd nch+colInd]); a1 = real(cfs); a2 = r(:,:,1); str1 = sprintf("Difference (real part): %g",max(abs(a1(:)-a2(:)))); a1 = imag(cfs); a2 = r(:,:,2); str2 = sprintf("Difference (imag part): %g",max(abs(a1(:)-a2(:)))); fprintf("%s\n%s\n",str1,str2)

Difference (real part): 7.102e-05 Difference (imag part): 6.94453e-05

figure subplot(2,2,1) imagesc(real(cfs)) title("Filter Bank — Real") subplot(2,2,2) imagesc(r(:,:,1)) title("Layer — Real") subplot(2,2,3) imagesc(imag(cfs)) title("Filter Bank — Imag") subplot(2,2,4) imagesc(r(:,:,2)) title("Layer — Imag")

### CWT Frequency Limits

Create a CWT layer using default values. By default, the CWT layer is for a signal length of 1024 samples. The layer uses the analytic Morse (3,60) wavelet in the CWT with 10 voices per octave and periodic boundary conditions. Inspect the default frequency limits of the layer. The frequency limits, which are in units of cycles/sample, are based on the energy spread of the wavelet, the signal length, and the voices per octave.

clayer = cwtLayer; clayer.FrequencyLimits

`ans = `*1×2*
0.0032 0.4341

Use the `filterbank`

method of the layer to obtain the full-weight CWT filter bank for the layer. Each row contains the values of a filter. The filters are ordered from high center frequency to low.

```
psif = filterbank(clayer);
whos psif
```

Name Size Bytes Class Attributes psif 71x1024 290816 single

You can determine the center frequencies by creating a `cwtfilterbank`

object, specifying the same wavelet parameters as used in the CWT layer, and then use the `centerFrequencies`

object function.

Create a `cwtfilterbank`

. The default wavelet parameters are identical to those in the CWT layer. Obtain the center frequencies. The frequencies are ordered from high to low. Plot the center frequencies.

fb = cwtfilterbank; cf = centerFrequencies(fb); subplot(2,1,1) plot(cf) ylabel("Cycles/Sample") title("Wavelet Center Frequencies") grid on subplot(2,1,2) semilogy(cf) grid on ylabel("Cycles/Sample") title("Semi-Log Scale")

The plots show that the wavelet center frequencies are not linearly spaced as is commonly the case with other filter banks. Specifically, the center frequencies are exponentially decreasing. In continuous wavelet analysis, the center frequencies of the wavelet filters are logarithmically spaced. The most common spacing is the base 2^(1/*NV*), where *NV* is the number of voices per octave, raised to integer powers. In other words, in a CWT filter bank, it is not possible for consecutive center frequencies $${f}_{1}$$ and $${f}_{2}$$, where $${f}_{1}<{f}_{2}$$, to satisfy $${\mathrm{log}}_{2}({f}_{2}/{f}_{1})<1/NV$$. Frequency limits you specify in the CWT layer must satisfy $${\mathrm{log}}_{2}({f}_{2}/{f}_{1})\ge 1/NV$$.

The CWT layer uses 10 voices per octave. Compute the base-2 logarithm of the ratios of consecutive pairs of center frequencies. Confirm the minimum and maximum values of the result are both equal to 1/10.

cfRatio = log2(cf(1:end-1)./cf(2:end)); [min(cfRatio) max(cfRatio)]

`ans = `*1×2*
0.1000 0.1000

Plot the full-weight CWT filter bank and the center frequencies. The center frequencies correspond to the peaks of the frequency response of each wavelet in the filter bank.

slen = clayer.SignalLength; f = 0:1/slen:1-1/slen; figure plot(f,psif') xlim([0 1/2]) xlabel("Cycles/Sample") ylabel("Magnitude") title(["Full-Weight Filter Bank", "With Center Frequencies"]) hold on plot(cf,2*ones(size(psif,1),1),'bx') hold off

If the CWT layer you created does not support your frequency limits, try increasing the number of voices per octave in the layer. For more information, see Practical Introduction to Time-Frequency Analysis Using the Continuous Wavelet Transform and Continuous and Discrete Wavelet Transforms.

### Reset Frequency Limits to Default Values in Deep Network Designer

This example shows how to reset the frequency limits to default values after changing the wavelet of a **cwtLayer** in **Deep Network Designer**.

Suppose you are editing a deep learning network using **Deep Network Designer**. The network has a **cwtLayer** that uses the Morse wavelet and has frequency limits set at `[0.1,0.3]`

.

Use the drop-down list to change the **Wavelet** to `amor`

. The frequency limits do not change, but the number of weights does change.

To change the frequency limits to default values appropriate for the `amor`

wavelet, first do one of the following:

Delete the

**FrequencyLimits**`0.1,0.3`

.Set the

**FrequencyLimits**to`[]`

.

Then click the mouse outside the **FrequencyLimits** edit field to move the focus. The app automatically populates **FrequencyLimits** with default values for the `amor`

wavelet. The number of weights also changes to reflect the new limits.

**Tip**: If you change the frequency limits, and later want to restore the default values, follow the same steps.

## More About

### Layer Output Format

`cwtLayer`

formats the output as
`"SCBT"`

, a sequence of 1-D images where the image height corresponds to
scale, or frequency. The second dimension corresponds to the channel, the third dimension
corresponds to the batch, and the fourth dimension corresponds to time.

You can feed the output of

`cwtLayer`

unchanged to a 1-D convolutional layer when you want to convolve along the frequency (`"S"`

) dimension. For more information, see`convolution1dLayer`

(Deep Learning Toolbox).To feed the output of

`cwtLayer`

to a 1-D convolutional layer when you want to convolve along the time (`"T"`

) dimension, you must place a flatten layer after the`cwtLayer`

. For more information, see`flattenLayer`

(Deep Learning Toolbox).You can feed the output of

`cwtLayer`

unchanged to a 2-D convolutional layer when you want to convolve along the frequency (`"S"`

) and time (`"T"`

) dimensions jointly. For more information, see`convolution2dLayer`

(Deep Learning Toolbox).To use

`cwtLayer`

as part of a recurrent neural network, you must place a flatten layer after the`cwtLayer`

. For more information, see`lstmLayer`

(Deep Learning Toolbox) and`gruLayer`

(Deep Learning Toolbox).To use the output of

`cwtLayer`

with a fully connected layer as part of a classification workflow, you must reduce the time (`"T"`

) dimension of the output so that it has size 1. To reduce the time dimension of the output, place a global pooling layer before the fully connected layer. For more information, see`globalAveragePooling2dLayer`

(Deep Learning Toolbox) and`fullyConnectedLayer`

(Deep Learning Toolbox).

## Version History

**Introduced in R2022b**

## See Also

### Apps

- Deep Network Designer (Deep Learning Toolbox)

### Functions

`dlcwt`

|`cwtfilters2array`

|`cwt`

|`cwtfreqbounds`

|`dlmodwt`

### Objects

`cwtfilterbank`

|`modwtLayer`

|`stftLayer`

(Signal Processing Toolbox) |`dlarray`

(Deep Learning Toolbox) |`dlnetwork`

(Deep Learning Toolbox)

### Topics

- Practical Introduction to Time-Frequency Analysis Using the Continuous Wavelet Transform
- Time-Frequency Convolutional Network for EEG Data Classification
- Time-Frequency Feature Embedding with Deep Metric Learning
- Deep Learning in MATLAB (Deep Learning Toolbox)
- List of Deep Learning Layers (Deep Learning Toolbox)

## Open Example

You have a modified version of this example. Do you want to open this example with your edits?

## MATLAB Command

You clicked a link that corresponds to this MATLAB command:

Run the command by entering it in the MATLAB Command Window. Web browsers do not support MATLAB commands.

Select a Web Site

Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .

You can also select a web site from the following list:

## How to Get Best Site Performance

Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.

### Americas

- América Latina (Español)
- Canada (English)
- United States (English)

### Europe

- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)

- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)