Exemple #1
0
    def __init__(self,**kwargs):
        """ Constructor
        
        Parameters
        ----------    

        fs : sampling frequency
        fc : center frequency
        beta : scale factor :math:`$\beta$`
        Tns  : time integration in nanoseconds
        BGHz : Bandwidth in GHz
        pfa  : false alarm probability
        wt   : filter B ripple
        R    : Resistance for Tension/Power conversion 
        NF   : Noise factor in dB (default 0dB)
        gpass: gain in the pass band
        gstop : gain in the stop band

        Notes
        -----

        An energy detector is determined by 2 filter a bandpass elliptic filter 
        :math:`H_B(f)` and a lowpass filter which corresponds to the time 
        integration over duration :math:`T` :math:`H_T(f)`

        """

        defaults = {'fsGHz':50,
                    'fcGHz':4,
                    'BGHz':3,
                    'Tns':10,
                    'pfa':0.01,
                    'beta':1,
                    'wt':0.01,
                    'gpass':0.5,
                    'gstop':30,
                    'NF':0,
                    'R':50}

        for k in defaults:
            if k not in kwargs:
                kwargs[k]=defaults[k]

        self.fsGHz = kwargs['fsGHz']
        self.fcGHz = kwargs['fcGHz']
        self.R = kwargs['R']
        BGHz = kwargs['BGHz']
        Tns = kwargs['Tns']
        wt  = kwargs['wt']
        #
        # Filter B : Input Band Pass Filter
        #
        ts  = 1./self.fsGHz
        fN  = self.fsGHz/2.
        w1  = (self.fcGHz-BGHz/2.)/fN
        w2  = (self.fcGHz+BGHz/2.)/fN
        wp  = [w1,w2]
        ws  = [w1-wt,w2+wt]

        self.filterB  = DF()
        self.filterB.ellip_bp(wp,ws,kwargs['gpass'],kwargs['gstop'])
        #self.filterB.butter(order=6,w=wp,typ='bandpass')

        #
        # Filter T : Time Averaging Filter (Integrator)  (Tns => N samples)
        #

        N  = np.ceil(Tns/ts)
        b  = (Tns*1e-9/N)*ones(N)
        self.NfilterT = len(b)
        a  = array([1])
        self.filterT = DF(b,a)

        #
        #
        #
        self.BGHz  = BGHz
        self.Tns   = Tns
        self.beta  = kwargs['beta']
        self.pfa   = kwargs['pfa']
        self.NF    = kwargs['NF']

        #
        # calculates ED moments, order and scale
        #

        # self.moment(typ='struc')
        # kB = 1,3806488 × 10-23 
        kB = 1.3806488e-23
        # TB : Noise temperature
        TB  = 290*10**(self.NF/10.)
        N0  = kB*TB
        self.order = 2*self.BGHz*self.Tns
        self.muy   = self.order*N0
        self.vary  = 4*self.BGHz*self.Tns*N0**2
        self.scale = np.sqrt(self.vary/(2*self.order))
Exemple #2
0



IP = ip.psd(Tpns=500)
IP.plotdB(mask=True)




IP = ip.psd




flt=DF()
fc = 4 
fs = fsGHz
fN = 50 
B = 0.5
w1 = (fc-B/2)/fN
w2 = (fc+B/2)/fN
flt.butter(w=[w1,w2],typ='bandpass')
flt.freqz()


### Creating a simple channel



#fig = plt.figure(figsize=(10,3))
Exemple #3
0
class ED(PyLayers):
    """
    Energy Detector Class

    This class implements an energy detector receiver


    """
    def __init__(self,**kwargs):
        """ Constructor
        
        Parameters
        ----------    

        fs : sampling frequency
        fc : center frequency
        beta : scale factor :math:`$\beta$`
        Tns  : time integration in nanoseconds
        BGHz : Bandwidth in GHz
        pfa  : false alarm probability
        wt   : filter B ripple
        R    : Resistance for Tension/Power conversion 
        NF   : Noise factor in dB (default 0dB)
        gpass: gain in the pass band
        gstop : gain in the stop band

        Notes
        -----

        An energy detector is determined by 2 filter a bandpass elliptic filter 
        :math:`H_B(f)` and a lowpass filter which corresponds to the time 
        integration over duration :math:`T` :math:`H_T(f)`

        """

        defaults = {'fsGHz':50,
                    'fcGHz':4,
                    'BGHz':3,
                    'Tns':10,
                    'pfa':0.01,
                    'beta':1,
                    'wt':0.01,
                    'gpass':0.5,
                    'gstop':30,
                    'NF':0,
                    'R':50}

        for k in defaults:
            if k not in kwargs:
                kwargs[k]=defaults[k]

        self.fsGHz = kwargs['fsGHz']
        self.fcGHz = kwargs['fcGHz']
        self.R = kwargs['R']
        BGHz = kwargs['BGHz']
        Tns = kwargs['Tns']
        wt  = kwargs['wt']
        #
        # Filter B : Input Band Pass Filter
        #
        ts  = 1./self.fsGHz
        fN  = self.fsGHz/2.
        w1  = (self.fcGHz-BGHz/2.)/fN
        w2  = (self.fcGHz+BGHz/2.)/fN
        wp  = [w1,w2]
        ws  = [w1-wt,w2+wt]

        self.filterB  = DF()
        self.filterB.ellip_bp(wp,ws,kwargs['gpass'],kwargs['gstop'])
        #self.filterB.butter(order=6,w=wp,typ='bandpass')

        #
        # Filter T : Time Averaging Filter (Integrator)  (Tns => N samples)
        #

        N  = np.ceil(Tns/ts)
        b  = (Tns*1e-9/N)*ones(N)
        self.NfilterT = len(b)
        a  = array([1])
        self.filterT = DF(b,a)

        #
        #
        #
        self.BGHz  = BGHz
        self.Tns   = Tns
        self.beta  = kwargs['beta']
        self.pfa   = kwargs['pfa']
        self.NF    = kwargs['NF']

        #
        # calculates ED moments, order and scale
        #

        # self.moment(typ='struc')
        # kB = 1,3806488 × 10-23 
        kB = 1.3806488e-23
        # TB : Noise temperature
        TB  = 290*10**(self.NF/10.)
        N0  = kB*TB
        self.order = 2*self.BGHz*self.Tns
        self.muy   = self.order*N0
        self.vary  = 4*self.BGHz*self.Tns*N0**2
        self.scale = np.sqrt(self.vary/(2*self.order))

    def __repr__(self):
        st = 'Energy Detector'+'\n'
        st = st+'---------------'+'\n\n'
        st = st+'Center frequency : '+str(self.fcGHz)+' GHz\n'
        st = st+'Bandwidth : '+str(self.BGHz)+' GHz \n'
        st = st+'Integration Time : '+str(self.Tns)+' ns \n'
        st = st+'Resistance : '+str(self.R)+' Ohms\n'
        st = st+'Mean (y) : '+str(self.muy/1e-9)+' nJ \n'
        st = st+'Std(y) : '+str(np.sqrt(self.vary)/1e-9)+' nJ \n'
        st = st+'Order (df) : '+str(self.order)+'  \n'
        st = st+'Scale : '+str(self.scale)+'  \n'
        st = st+'2BT : '+str(2*self.BGHz*self.Tns)+' \n'

        return(st)

    def apply(self,x,typ='ideal'):
        r"""

        Parameters
        ----------

        x : input signal

        Returns
        -------

        y : :math:`F_2\{\beta^2 F_1\{x\}^2\}`

            :math:`F{x}` means a filtering of x with filter :math:`F`

        """
        if typ=='real':
            # B filtering 
            self.xf1 = self.filterB.filter(x.y)
            # quadrator and scaling 
            self.xq  = ((self.beta)**2)*(self.xf1*self.xf1)/self.R
            # T filtering
            self.y        = bs.TUsignal(x.x,self.filterT.filter(self.xq))
        
        if typ=='ideal':
            # B filtering  --> FH signal
            X   = x.fft()
            self.gate = np.zeros(len(x.x))
            u1 = np.where((x.x>(self.fcGHz-self.BGHz/2.)) & (x.x<(self.fcGHz+self.BGHz/2)))[0]
            u2 = np.where((x.x>(self.fsGHz-self.fcGHz-self.BGHz/2.)) & (x.x<(self.fsGHz-self.fcGHz+self.BGHz/2)))[0]
            self.gate[u1] = 1
            self.gate[u2] = 1
            X.y = X.y*self.gate
            self.y = X.ifft()

            #self.xq  = ((self.beta)**2)*(self.xf1*self.xf1)/self.R
            #self.y        = bs.TUsignal(x.x,self.filterT.filter(self.xq))
        return(self.y)

    def moment(self,typ='struc'):
        r""" evaluate mean and variance of output signal y

        Parameters
        ----------

        typ : string
          'struc' structural evaluation of moments
          'emp' empirical evaluation of moments

        Notes
        -----

        :math:`R_y(\tau)=2R_x^2(\tau)+R_x^2(0)`

        This function updates the order and scale or the Energy Detector

        """
        # filterB bandpass filter
        self.filterB.freqz(display=False)
        # filterT time integration (=low pass filter)
        self.filterT.freqz(display=False)
        w = bs.Noise(fsGHz=self.fsGHz)

        if typ=='struc':
            # ACF of filter B
            self.RB = self.filterB.wnxcorr(var=w.var)
            # F.de Coulom T&T signal eq 8.148
            # ACF of xq
            self.Rx = self.RB*self.RB*2
            # Power of xq
            RB0= self.RB.y[0]
            # 
            self.Rx.y = self.Rx.y+RB0**2

            Phix = np.real(fft.fft(self.Rx.y))
            HH   = self.filterT.H.symH(0)
            HH.y = HH.y/(self.Tns*1e-9)
            Phiy = Phix * np.real(HH.y * np.conj(HH.y))
            self.muy = self.RB.max()[0]*self.beta*self.beta
            self.vary = mean(Phiy)

        if typ=='emp':
            self.muy  = self.y.y[self.NfilterT:].mean()
            self.vary = self.y.y[self.NfilterT:].var()

        self.order = (2*(self.muy)**2)/self.vary
        self.scale = np.sqrt(self.vary/(2*self.order))

    def pdf(self,E,Ei=0):
        """ calculates decision problem densities under H0 and H1

        Parameters
        ----------

        E  : float
            Legitimate Signal Energy
        Ei : float
            Interferer Signal Energy

        See Also
        --------

        scipy.stats.chi2
        scipy.stats.ncx2

        """

        self.E = E
        self.Ei = Ei

        # H0 : Noise only (no interferer)
        # central chi square
        if Ei==0:
            self.pH0 = st.chi2(self.order,
                               scale=self.scale)
        else:
        # H0 : Noise + interference
        # non central chi square
            self.pH0 = st.ncx2(self.order,
                               scale=self.scale,
                               nc=Ei/(self.scale))

        # H1 : Signal + interference + Noise
        # non central chi square
        self.pH1 = st.ncx2(self.order,
                           scale=self.scale,
                           nc=(E+Ei)/(self.scale))

    def errprob(self,E,Ei=0,thresh=0,typ='thresh'):
        """ calculates error probability

        Parameters
        ----------

        E  : float
            Legitimate Signal Energy
        Ei : float
            Interferer Signal Energy
        thresh : float
        typ : string
            'thresh'
            'scale': for IEEE.802.11.6 standard
            'both' : both kind of decision

        Returns
        -------

        errp : error probability

        Notes
        -----

        See Also
        --------

        scipy.stats.ncf
        ED.pdf

        """

        self.pdf(E,Ei=Ei)

        if typ=='thresh':
            self.p10 = self.pH0.sf(thresh)
            self.p01 = 1-self.pH1.sf(thresh)
            errp = 0.5*(self.p10+self.p01)

        if typ=='scale':
            ncf = st.ncf(dfn = self.order,
                         dfd = self.order,
                         scale = 1,
                         nc = self.E/self.scale)
            errp = 1 - ncf.sf(1)

        if typ=='both':
            self.p10 = self.pH0.sf(thresh)
            self.p01 = 1-self.pH1.sf(thresh)
            pe1 = 0.5*(self.p10+self.p01)
            ncf = st.ncf(dfn=self.order,
                         dfd=self.order,
                         scale=1,
                         nc=self.E/self.scale)
            pe2= 1 - ncf.sf(1)
            errp =(pe1,pe2)

        return(errp)

    def plot(self,E):
        """ plot decision problem densities

        Parameters
        ----------

        E : float
            value of energy

        """

        self.pdf(E)
        e  = np.linspace(0,max(self.muy*5,2*self.E),200)
        p0 = self.pH0.pdf(e)
        p1 = self.pH1.pdf(e)
        #plt.plot(10*np.log10(E),p0,'b',linewidth=4)
        #plt.plot(10*np.log10(E),p1,'r',linewidth=4)
        plt.plot(e,p0,'b',linewidth=4)
        plt.plot(e,p1,'r',linewidth=4)

    def roc(self,E,typ='thresh'):
        """ determine receiver operating curve

        Parameters
        ----------

        E   : float
            Energy
        typ : string
            'thresh' | 'both' | 'scale'


        Returns
        -------

        terr : error probability
        tpfa : false alarm probability
        tpd  : detection probability


        Notes
        -----

        Iterate on energy from 0 to 10*E

        """

        thresh = np.linspace(10*E,0,300)
        terr = []
        tpfa = []
        tpd =[]

        for t in thresh:
            perr = self.errprob(E,thresh=t,typ=typ)
            terr.append(perr)
            tpfa.append(self.p10)
            tpd.append(1-self.p01)

        terr = np.array(terr)
        tpfa = np.array(tpfa)
        tpd = np.array(tpd)

        return(terr,tpfa,tpd)
Exemple #4
0
    t  = linspace(0,1,Npoints)
    wn = sqrt(Var_w)*randn(Npoints)

    #
    # Filter 1 : Input Band Pass Filter
    #
    w1       = 0.05
    w2       = 0.1
    wt       = 0.01
    wp       = [w1,w2]
    ws       = [w1-wt,w2+wt]
    gpass    = 0.5
    gstop    = 30
    type     = 'ellip'

    filter1  = DF()
    filter1.ellip_bp(wp,ws,gpass,gstop)

    #
    # Filter 2 : averaging filter
    #
    N       = 40
    b       = (1./N)*ones(N)
    a       = array([1])
    filter2 = DF(b,a)

    #
    #
    #
    beta     = 1
    pfa      = 0.001