Trying to use for loop to create an array of bandpass filters, but gets error "conversion to double from dfilt.df2sos is not possible"

8 views (last 30 days)
I have been trying to use a for loop to generate an array of bandpass filters using the dfilt.df2sos command in order to minimise numerical errors, and then using fvtool to analyze the filters. However, when running the command I keep running into the error "Unable to perform assignment because value of type 'dfilt.df2sos' is not convertible to 'double'." on line bppf(i) = dfilt.df2sos(s,g);. I suspect this is probably due to how I initialised the array bppf, but I can't seem to find a workaround for this. I am also trying to use the web browser to run this code, but I'm not sure if that's really the cause of the problem. Any help would be much appreciated thank you.
Edit: I realised I accidentally missed out on variables ap and as when copying and pasting my code
fs = 48000; % sample frequency
wss1 = [5680 2840 1420 710 355 177 88 44]*2*pi/fs;
wss2 = [11360 5680 2840 1420 710 355 177 88 44]*2*pi/fs;
wpp1 = 0.9*[8000 4000 2000 1000 500 250 125 63]*2*pi/fs;
wpp2 = zeros(8);
dp = 0.05;
ds = 0.05;
% peak passband ripple and minimum stopband attenuation in dB
ap = -20*log10(1-dp); as = -20*log10(ds);
% append wpp2
for i = 1:length(wpp2)
wpp2(i) = wss1(i)*wss2(i)/wpp1(i);
end
% design of prototype butteworth bandpass filter
bppf = zeros(8);
for i = 1:8
% bandedge frequencies for analog filter (T=1)
omp1 = 2*tan(wpp1(i)/2);
omp2 = 2*tan(wpp2(i)/2);
oms1 = 2*tan(wss1(i)/2);
oms2 = 2*tan(wss2(i)/2);
% filter design
[N Wn] = buttord([omp1/pi omp2/pi],[oms1/pi oms2/pi],ap,as);
[z,p,k] = butter(N,Wn,'bandpass');
[s,g] = zp2sos(z,p,k);
bppf(i) = dfilt.df2sos(s,g);
end
fvtool(bppf(1),bppf(2),bppf(3),bppf(4),bppf(5),bppf(6),bppf(7),bppf(8))
  1 Comment
Umar
Umar on 28 Sep 2024

Hi @ Hanlin Wang,

You mentioned, “ However, when running the command I keep running into the error "Unable to perform assignment because value of type 'dfilt.df2sos' is not convertible to 'double'." on line bppf(i) = dfilt.df2sos(s,g);”

You did not provide full code by not defining parameters for variables ap and as in the code provided by you.

    % filter design
    [N Wn] = buttord([omp1/pi omp2/pi],[oms1/pi oms2/pi],ap,as);

These variables typically represent the maximum allowable passband ripple and the minimum stopband attenuation, respectively. However, I defined them by using synthetic numbers and was able to execute the code with no problems, please see attached.

After analyzing error you encountered while trying to create an array of bandpass filters using the dfilt.df2sos command in MATLAB, it indicates a type mismatch when attempting to assign a filter object to a numeric array. This issue raised from the initialization of the bppf array. So, in MATLAB, when you initialize bppf as a numeric array using zeros(8), it can only hold numeric values, not objects like dfilt.df2sos. To resolve this, you should initialize bppf as a cell array, which can store different types of data, including objects. Here’s how you can modify your code:

bppf = cell(1, 8); % Initialize bppf as a cell array
for i = 1:8
  % bandedge frequencies for analog filter (T=1)
  omp1 = 2*tan(wpp1(i)/2);
  omp2 = 2*tan(wpp2(i)/2);
  oms1 = 2*tan(wss1(i)/2);
  oms2 = 2*tan(wss2(i)/2);
    % filter design
    [N, Wn] = buttord([omp1/pi omp2/pi], [oms1/pi oms2/pi], ap, as);
    [z, p, k] = butter(N, Wn, 'bandpass');
    [s, g] = zp2sos(z, p, k);
    bppf{i} = dfilt.df2sos(s, g); % Store the filter object in the cell 
    array
  end
  fvtool(bppf{1}, bppf{2}, bppf{3}, bppf{4}, bppf{5}, bppf{6}, bppf{7}, 
  bppf{8});

By using a cell array, you can successfully store the filter objects and analyze them with fvtool. Additionally, make sure that your MATLAB environment is properly set up, as running code in a web browser may introduce other limitations.

Please let me know if this helped resolved your problem.

Sign in to comment.

Accepted Answer

Voss
Voss on 28 Sep 2024
Edited: Voss on 28 Sep 2024

Make bppf a cell array:

bppf = cell(1,8);

Then index bppf using curly braces instead of parentheses:

bppf{i} = dfilt.df2sos(s,g);

And you can call fvtool with all bppf using a comma-separated list:

fvtool(bppf{:})

More Answers (1)

Paul
Paul on 28 Sep 2024
Hi Hanlin Wang,
fs = 48000; % sample frequency
wss1 = [5680 2840 1420 710 355 177 88 44]*2*pi/fs;
wss2 = [11360 5680 2840 1420 710 355 177 88 44]*2*pi/fs;
wpp1 = 0.9*[8000 4000 2000 1000 500 250 125 63]*2*pi/fs;
wpp2 = zeros(8);
% append wpp2
for i = 1:length(wpp2)
wpp2(i) = wss1(i)*wss2(i)/wpp1(i);
end
% design of prototype butteworth bandpass filter
This line creates bppf as a 8 x 8 double
bppf = zeros(8);
whos bppf
Name Size Bytes Class Attributes bppf 8x8 512 double
You probably wanted to create bppf as a 1 x 8 or 8 x 1. But the problem is that it's a double array, and the offending line is attempting to assign a dfilt.df2sos into an element of a double array, which can't be done.
If you really want to preallocate bppf as a dfilt.df2sos, then we can do
bppf = createArray(1,8,Like=dfilt.df2sos);
whos bppf
Name Size Bytes Class Attributes bppf 1x8 64 dfilt.df2sos
Then proceed as before.
ap = 3; as = 60; % need to define these to run the code
for i = 1:8
% bandedge frequencies for analog filter (T=1)
omp1 = 2*tan(wpp1(i)/2);
omp2 = 2*tan(wpp2(i)/2);
oms1 = 2*tan(wss1(i)/2);
oms2 = 2*tan(wss2(i)/2);
% filter design
[N Wn] = buttord([omp1/pi omp2/pi],[oms1/pi oms2/pi],ap,as);
[z,p,k] = butter(N,Wn,'bandpass');
[s,g] = zp2sos(z,p,k);
bppf(i) = dfilt.df2sos(s,g);
end
Or you may want to make bppf as a cell array with each element storing an individual dfilt.df2sos.
  1 Comment
Hanlin Wang
Hanlin Wang on 28 Sep 2024
Hi Paul, thank you for your insight! I did try using
bppf = createArray();
initially but I missed out on the parameter Like=dfilt.df2sos, which resulted in another error, so I went with the cell array method as described by you and Voss above which did work.

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!