# DSP.jl how to use ZeroPoleGain with specifications in Hz?

**URL:** <https://discourse.julialang.org/t/dsp-jl-how-to-use-zeropolegain-with-specifications-in-hz/90772>\
**Category:** General Usage\
**Tags:** dsp\
**Created:** [November 24, 2022, 7:43pm UTC](https://discourse.julialang.org/t/dsp-jl-how-to-use-zeropolegain-with-specifications-in-hz/90772 "2022-11-24T19:43:56Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![dutille](https://avatars.discourse-cdn.com/v4/letter/d/7ba0ec/32.png) [@dutille](https://discourse.julialang.org/u/dutille)\
**Post date:** [November 24, 2022, 7:43pm UTC](https://discourse.julialang.org/t/dsp-jl-how-to-use-zeropolegain-with-specifications-in-hz/90772/1 "2022-11-24T19:43:56Z")

</div>

Let’s say I want to implement a digital filter that is defined by its zeros and poles to filter signals sampled at `fs` Hz. It seems logical to use `DSP.Filters.ZeroPoleGain(z,p,k)`. But there is little information about the units for `z` and `p`. If the zeros and poles are in Hz+imHz, how do I obtain suitable values for `z` and `p`? If `zHz` is a pole in Hz+imHz, do I have to divide it by `fs` to obtain `z`? Should I multiply by `2*pi`?. Map from the s-plane to the z-plane? Sorry for the stupid question.

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [November 25, 2022, 8:46am UTC](https://discourse.julialang.org/t/dsp-jl-how-to-use-zeropolegain-with-specifications-in-hz/90772/2 "2022-11-25T08:46:57Z")

</div>

You may need to convert the frequencies in Hz to rad/sample.  
Pi rad/sample equals to the Nyquist frequency ( = sampling frequency / 2 = `fs/2` in Hz).  
Then the frequency vector `frs` in rad/sample which we need to feed into `freqresp(filter, frs)` is given by `frs = pi * fhz / (fs/2)`, where `fhz` are the frequencies in Hertz.

---

<div class="post-metadata">

**Author:** ![dutille](https://avatars.discourse-cdn.com/v4/letter/d/7ba0ec/32.png) [@dutille](https://discourse.julialang.org/u/dutille)\
**Post date:** [November 25, 2022, 8:39pm UTC](https://discourse.julialang.org/t/dsp-jl-how-to-use-zeropolegain-with-specifications-in-hz/90772/3 "2022-11-25T20:39:22Z")

</div>

Thanks, but it does not work as expected. Here is my code:

```julia
using DSP, Plots
#4 zeros in Hz
zhz=[0.,0.,0.,0.]
#8 poles in Hz (2 of magnitude 1Hz and 6 of magnitude 20 Hz)
phz=[-0.707(1-im), -0.707(1+im), -19.27-5.16im, -19.27+5.16im, -14.11(1-im), -14.11(1+im), -5.16-19.27im, -5.16+19.27im]
fs=44100. #sampling frequency
f=ZeroPoleGain(2π/fs*zhz,2π/fs*phz,1)
fhz=0.01:0.01:400.
frs=2π/fs*fhz
A=20log10.(abs.(freqresp(f,frs)))
plot(fhz,A)

```

This filter should feature a minimum attenuation at 10 Hz and increasingly attenuate as the distance to 10 Hz increases. Here the attenuation I get is more or less constant.

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [November 25, 2022, 9:13pm UTC](https://discourse.julialang.org/t/dsp-jl-how-to-use-zeropolegain-with-specifications-in-hz/90772/4 "2022-11-25T21:13:44Z")

</div>

Sorry, I don’t understand what you mean by the “20 Hz magnitude” poles. Some of the poles are outside the unit circle and the filter will not be stable, having exponentially increasing components.

I recommend that you try to reproduce using `DSP.jl` a well documented example, [like this one](https://staff.fnwi.uva.nl/r.vandenboomgaard/SP20162017/ComplexDomain/ZDomain/poles_zeros.html).

---

<div class="post-metadata">

**Author:** ![dutille](https://avatars.discourse-cdn.com/v4/letter/d/7ba0ec/32.png) [@dutille](https://discourse.julialang.org/u/dutille)\
**Post date:** [November 25, 2022, 9:24pm UTC](https://discourse.julialang.org/t/dsp-jl-how-to-use-zeropolegain-with-specifications-in-hz/90772/5 "2022-11-25T21:24:23Z")

</div>

After multiplication by `\pi/(fs/2)` my poles and zeros originally specified in Hz will be inside the unit circle.

The example you suggested works.

```julia
using DSP, Plots
z=[0.95+0.31im, 0.95-0.31im]
p=[0.9-0.3im, 0.9+0.3im]
f=ZeroPoleGain(z,p,1)
frs=0:0.001:π
A=20log10.(abs.(freqresp(f,frs)))
plot(frs,A)

```

But that does not tell me what to do with my poles and zeros in Hz.

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [November 25, 2022, 9:30pm UTC](https://discourse.julialang.org/t/dsp-jl-how-to-use-zeropolegain-with-specifications-in-hz/90772/6 "2022-11-25T21:30:45Z")

</div>

I don’t think it is valid to apply frequency conversions directly to the poles and zeros. They should be applied only to the frequency vector input to the `freqresp()` function, that is expected in rad/sample for a digital filter.

**NB:**  
and then plot the filter frequency response in a Hertz scale with `plot(fhz, A)`

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [November 25, 2022, 11:40pm UTC](https://discourse.julialang.org/t/dsp-jl-how-to-use-zeropolegain-with-specifications-in-hz/90772/8 "2022-11-25T23:40:36Z")

</div>

> [@dutille](#):
>
> The example you suggested works.  
> …  
> But that does not tell me what to do with my poles and zeros in Hz.

In that example, where there is one pole at: `p1 = 0.9 + 0.3*im`, the “corresponding frequency” (in the transfer function) in Hertz can be computed using:

```julia
angle(p1)/π * fs/2

```

---

<div class="post-metadata">

**Author:** ![dutille](https://avatars.discourse-cdn.com/v4/letter/d/7ba0ec/32.png) [@dutille](https://discourse.julialang.org/u/dutille)\
**Post date:** [November 26, 2022, 8:08pm UTC](https://discourse.julialang.org/t/dsp-jl-how-to-use-zeropolegain-with-specifications-in-hz/90772/9 "2022-11-26T20:08:38Z")

</div>

Thanks. Then `DSP.Filters.ZeroPoleGain()` takes arguments in the z-plane. And I have to map my zeros and poles in the s-plane onto the z-plane. A possible approach is to use the bilinear transform. Do you know of any Julia equivalent to the bilinear() Matlab function that is used here:

````julia
p=[ -0.707+j* 0.707
    -0.707-j* 0.707
   -19.27+j* 5.16
   -19.27-j* 5.16
   -14.11+j*14.11
   -14.11-j*14.11
    -5.16+j*19.27
    -5.16-j*19.27];
%zeros
z=[0 0 0 0]';
%scalar gain
k=10^(116/20);
%get analog filter coefficients
[bG,aG] = zp2tf(z,p,k);
%get filter response
[hG,fG] = freqs(bG,aG,[0 logspace(log10(0.2),log10(200),1000)]);

%%Try to get digital coefficients from bilinear transform
[bz,az]=bilinear(bG,aG,fs);
%get digital filter response
[Hz, fz]= freqz(bz,az,100*fs,fs);
```

From https://se.mathworks.com/matlabcentral/answers/6373-s-plane-to-z-plane-transformation.
````

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [November 27, 2022, 7:14am UTC](https://discourse.julialang.org/t/dsp-jl-how-to-use-zeropolegain-with-specifications-in-hz/90772/11 "2022-11-27T07:14:06Z")

</div>

> [@dutille](#):
>
> Do you know of any Julia equivalent to the bilinear()

There is a `DSP.Filters.bilinear()` function that is not documented. See this [other post](https://discourse.julialang.org/t/not-sure-how-to-apply-a-filter/50265/7) and the [github source](https://github.com/JuliaDSP/DSP.jl/blob/master/src/Filters/design.jl) code.
