DEMOD Subroutine

public subroutine DEMOD(X, N, F)

NAME

demod(3f) - [M_datapac:STATISTICS] perform a complex demodulation

SYNOPSIS

   SUBROUTINE DEMOD(X,N,F)

DESCRIPTION

demod(3f) performs a complex demodulation on the data in the input
vector x at the input demodulation frequency = f.

the complex demodulation consists of the following--

 1. an amplitude versus time plot;
 2. a phase versus time plot;
 3. an updated demodulation frequency estimate
    to assist the analyst in determining a
    more appropriate frequency at which
    to demodulate in case the specified
    input demodulation frequency f
    does not flatten sufficiently the
    phase plot.

the allowable range of the input demodulation frequency f is 0.0 to
0.5 (exclusively).

the input demodulation frequency f is measured of in units of
cycles per 'data point' or, more precisely, in cycles per unit time
where 'unit time' is defined as the elapsed time between adjacent
observations.

OPTIONS

 X   description of parameter
 Y   description of parameter

EXAMPLES

Sample program:

program demo_demod
use M_datapac, only : demod
implicit none
! call demod(x,y)
end program demo_demod

Results:

AUTHOR

The original DATAPAC library was written by James Filliben of the Statistical
Engineering Division, National Institute of Standards and Technology.

MAINTAINER

John Urban, 2022.05.31

LICENSE

CC0-1.0

REFERENCES

  • granger and hatanaka, pages 170 to 189, especially pages 173, 177, and 182.

Arguments

Type IntentOptional Attributes Name
real(kind=wp), dimension(:) :: X
integer :: N
real(kind=wp) :: F

Common Blocks

CAUPLT (subroutine)
CHSCDF (subroutine)
CODE (subroutine)
DECOMP (subroutine)
DEXPLT (subroutine)
EV1PLT (subroutine)
EV2PLT (subroutine)
EXPPLT (subroutine)
EXTREM (subroutine)
EXTREM (subroutine)
FREQ (subroutine)
GAMPLT (subroutine)
GEOPLT (subroutine)
HFNPLT (subroutine)
INVXWX (subroutine)
LAMPLT (subroutine)
LGNPLT (subroutine)
LOGPLT (subroutine)
MEDIAN (subroutine)
norout (subroutine)
NORPLT (subroutine)
PARPLT (subroutine)
PLOTU (subroutine)
POIPLT (subroutine)
RUNS (subroutine)
SAMPP (subroutine)
SPCORR (subroutine)
TAIL (subroutine)
TPLT (subroutine)
TRIM (subroutine)
UNIPLT (subroutine)
WEIB (subroutine)
WEIPLT (subroutine)
WIND (subroutine)
"> common /BLOCK2_real32/

Type Attributes Name Initial
real :: WS(15000)

Source Code

SUBROUTINE DEMOD(X,N,F)
REAL(kind=wp) :: ai, aiflag, aimax2, alen1, alen2, an, del, F, fest, fmin, hold, pi, range, slopeh, sloper, sum, WS, X, Y1, Y2
REAL(kind=wp) :: Z, zmax, zmin, znew
INTEGER :: i, iend, iendp1, iflag, ilower, imax1, imax2, imax2m, ip1, istart, iupper, j, lenma1, lenma2, N
!
!     INPUT ARGUMENTS--X      = THE  VECTOR OF
!                               (UNSORTED) OBSERVATIONS.
!                      N      = THE INTEGER NUMBER OF OBSERVATIONS
!                               IN THE VECTOR X.
!                      F      = THE
!                               DEMODULATION FREQUENCY.
!                               F IS IN UNITS OF CYCLES PER DATA POINT.
!                               F IS BETWEEN 0.0 AND 0.5 (EXCLUSIVELY).
!     OUTPUT--2 pages OF AUTOMATIC PRINTOUT--
!             1) AN AMPLITUDE PLOT;
!             2) A PHASE PLOT; AND
!             3) AN UPDATED DEMODULATION FREQUENCY ESTIMATE.
!     PRINTING--YES.
!     RESTRICTIONS--THE MAXIMUM ALLOWABLE VALUE OF N
!                   FOR THIS SUBROUTINE IS 5000.
!                 --THE SAMPLE SIZE N MUST BE GREATER
!                   THAN OR EQUAL TO 3.
!                 --THE INPUT FREQUENCY F MUST BE
!                   GREATER THAN OR EQUAL TO 2/(N-2).
!                 --THE INPUT FREQUENCY F MUST BE
!                   SMALLER THAN 0.5.
!     OTHER DATAPAC   SUBROUTINES NEEDED--PLOTX.
!     FORTRAN LIBRARY SUBROUTINES NEEDED--SQRT, SIN, COS, ATAN.
!     MODE OF INTERNAL OPERATIONS--.
!     COMMENT--IN ORDER THAT THE RESULTS OF THE COMPLEX DEMODULATION
!              BE VALID AND PROPERLY INTERPRETED, THE INPUT DATA
!              IN X SHOULD BE EQUI-SPACED IN TIME
!              (OR WHATEVER VARIABLE CORRESPONDS TO TIME).
!            --IF THE INPUT OBSERVATIONS IN X ARE CONSIDERED
!              TO HAVE BEEN COLLECTED 1 SECOND APART IN TIME,
!              THEN THE DEMODULATION FREQUENCY F
!              WOULD BE IN UNITS OF HERTZ
!              (= CYCLES PER SECOND).
!            --A FREQUENCY OF 0.0 CORRESPONDS TO A CYCLE
!              IN THE DATA OF INFINITE (= 1/(0.0))
!              LENGTH OR PERIOD.
!              A FREQUENCY OF 0.5 CORRESPONDS TO A CYCLE
!              IN THE DATA OF LENGTH = 1/(0.5) = 2 DATA POINTS.
!            --IN EXAMINING THE AMPLITUDE AND PHASE PLOTS,
!              ATTENTION SHOULD BE PAID NOT ONLY TO THE
!              STRUCTURE OF THE PHASE PLOT
!              (NEAR-ZERO SLOPE VERSUS NON-ZERO SLOPE)
!              BUT ALSO TO THE RANGE
!              OF VALUES ON THE VERTICAL AXIS.
!              A PLOT WITH MUCH STRUCTURE BUT
!              WITH A SMALL RANGE ON THE VERTICAL AXIS
!              IS USUALLY MORE INDICATIVE OF A
!              DEFINITE CYCLIC COMPONENT AT THE
!              SPECIFIED INPUT DEMODULATION FREQUENCY,
!              THAN IS A PLOT WITH LESS STRUCTURE BUT
!              A WIDER RANGE ON THE VERTICAL AXIS.
!            --INTERNAL TO THIS SUBROUTINE, 2 MOVING
!              AVERAGES ARE APPLIED, EACH OF LENGTH 1/F.
!              HENCE THE AMPLITUDE AND PHASE PLOTS
!              HAVE N - 2/F VALUES
!              (RATHER THAN N VALUES) ALONG THE
!              HORIZONTAL (TIME) AXIS.
!              IN ORDER THAT THE AMPLITUDE AND PHASE
!              PLOTS BE NON-EMPTY, AN INPUT
!              REQUIREMENT ON F FOR THIS SUBROUTINE
!              IS THAT THE SAMPLE SIZE N
!              AND THE DEMODULATION FREQUENCY F
!              MUST BE SUCH THAT
!              N - 2/F BE GREATER THAN ZERO.
!              FURTHER, SINCE A PLOT WITH BUT
!              1 POINT IS MEANINGLESS
!              AND OUGHT ALSO BE EXCLUDED,
!              THE REQUIREMENT IS EXTENDED
!              SO THAT N - 2/F MUST BE GREATER THAN 1.
!     ORIGINAL VERSION--NOVEMBER  1972.
!     UPDATED         --NOVEMBER  1975.
!     UPDATED         --FEBRUARY  1976.
!
!---------------------------------------------------------------------
!
      DIMENSION X(:)
      DIMENSION Y1(5000) , Y2(5000) , Z(5000)
      COMMON /BLOCK2_real32/ WS(15000)
      EQUIVALENCE (Y1(1),WS(1))
      EQUIVALENCE (Y2(1),WS(5001))
      EQUIVALENCE (Z(1),WS(10001))
      DATA pi/3.141592653_wp/
!
      ilower = 3
      iupper = 5000
      an = N
      fmin = 2.0_wp/(an-2.0_wp)
!
!     CHECK THE INPUT ARGUMENTS FOR ERRORS
!
      IF ( N<ilower .OR. N>iupper ) THEN
         WRITE (G_IO,99001) ilower , iupper
99001    FORMAT (' ',                                                   &
     &'***** FATAL ERROR--THE SECOND INPUT ARGUMENT TO THE DEMOD  SUBROU&
     &TINE IS OUTSIDE THE ALLOWABLE (',I0,',',I0,') INTERVAL *****')
         WRITE (G_IO,99002) N
99002    FORMAT (' ','***** THE VALUE OF THE ARGUMENT IS ',I0,' *****')
         RETURN
      ELSE
         IF ( F<=fmin .OR. F>=0.5_wp ) THEN
            WRITE (G_IO,99003) fmin
99003       FORMAT (' ',                                                &
     &'***** FATAL ERROR--THE THIRD INPUT ARGUMENT TO THE  DEMOD  SUBROU&
     &TINE IS OUTSIDE THE ALLOWABLE (',F10.8,',0.5) ','INTERVAL *****')
            WRITE (G_IO,99004) F
99004       FORMAT (' ','***** THE VALUE OF THE ARGUMENT IS ',E15.8,    &
     &              ' *****')
            WRITE (G_IO,99005) fmin , N
99005       FORMAT (' ','                   THE ABOVE LOWER LIMIT (',   &
     &              F10.8,                                              &
     &              ') = 2/(N-2) WHERE N = THE INPUT SAMPLE SIZE = ',I0)
            RETURN
         ELSE
            hold = X(1)
            DO i = 2 , N
               IF ( X(i)/=hold ) GOTO 50
            ENDDO
            WRITE (G_IO,99006) hold
99006       FORMAT (' ',                                                &
     &'***** NON-FATAL DIAGNOSTIC--THE FIRST  INPUT ARGUMENT (A VECTOR) &
     &TO THE DEMOD  SUBROUTINE HAS ALL ELEMENTS = ',E15.8,' *****')
            RETURN
         ENDIF
!
!-----START POINT-----------------------------------------------------
!
!     FORM THE COSINE AND SINE SERIES
!
 50      DO i = 1 , N
            ai = i
            Y1(i) = X(i)*COS(6.2831853_wp*F*ai)
            Y2(i) = X(i)*SIN(6.2831853_wp*F*ai)
         ENDDO
!
!     DEFINE THE LENGTH OF THE 2 MOVING AVERAGES
!
         lenma1 = 1.0_wp/F
         lenma2 = 1.0_wp/F
         alen1 = lenma1
         alen2 = lenma2
         imax1 = N - lenma1
         imax2 = imax1 - lenma2
!
!     FORM THE FIRST MOVING AVERAGE FOR THE COSINE SERIES
!
         DO i = 1 , imax1
            istart = i + 1
            iend = i + lenma1 - 1
            iendp1 = i + lenma1
            sum = 0.0_wp
            DO j = istart , iend
               sum = sum + Y1(j)
            ENDDO
            sum = sum + Y1(i)/2.0_wp + Y1(iendp1)/2.0_wp
            Z(i) = sum/alen1
         ENDDO
!
!     FORM THE SECOND MOVING AVERAGE FOR THE COSINE SERIES
!
         DO i = 1 , imax2
            istart = i + 1
            iend = i + lenma2 - 1
            iendp1 = i + lenma2
            sum = 0.0_wp
            DO j = istart , iend
               sum = sum + Z(j)
            ENDDO
            sum = sum + Z(i)/2.0_wp + Z(iendp1)/2.0_wp
            Y1(i) = sum/alen2
         ENDDO
!
!     FORM THE FIRST MOVING AVERAGE FOR THE SINE SERIES
!
         DO i = 1 , imax1
            istart = i + 1
            iend = i + lenma1 - 1
            iendp1 = i + lenma1
            sum = 0.0_wp
            DO j = istart , iend
               sum = sum + Y2(j)
            ENDDO
            sum = sum + Y2(i)/2.0_wp + Y2(iendp1)/2.0_wp
            Z(i) = sum/alen1
         ENDDO
!
!     FORM THE SECOND MOVING AVERAGE FOR THE SINE SERIES
!
         DO i = 1 , imax2
            istart = i + 1
            iend = i + lenma1 - 1
            iendp1 = i + lenma1
            sum = 0.0_wp
            DO j = istart , iend
               sum = sum + Z(j)
            ENDDO
            sum = sum + Z(i)/2.0_wp + Z(iendp1)/2.0_wp
            Y2(i) = sum/alen2
         ENDDO
!
!
!     FORM THE AMPLITUDES AND PLOT THEM
!
         DO i = 1 , imax2
            Z(i) = 2.0_wp*SQRT(Y1(i)*Y1(i)+Y2(i)*Y2(i))
         ENDDO
         CALL PLOTX(Z,imax2)
         WRITE (G_IO,99007) F
!
99007    FORMAT (' ',30X,                                               &
     &           'AMPLITUDE PLOT FOR THE DEMODULATION FREQUENCY = ',    &
     &           F8.6,' CYCLES PER UNIT TIME')
!
!     COMPUTE THE DIFFERENCE BETWEEN THE MAX AND MIN AMPLITUDES AND WRITE IT OUT
!
         zmin = Z(1)
         zmax = Z(1)
         DO i = 1 , imax2
            IF ( Z(i)<zmin ) zmin = Z(i)
            IF ( Z(i)>zmax ) zmax = Z(i)
         ENDDO
         range = zmax - zmin
         WRITE (G_IO,99008) zmin , zmax , range
99008    FORMAT (' ',9X,'MINIMUM AMPLITUDE = ',E15.8,5X,                &
     &           'MAXIMUM AMPLITUDE = ',E15.8,5X,                       &
     &           'RANGE OF AMPLITUDES = ',E15.8)
!
!     FORM THE PHASES AND PLOT THEM
!
         DO i = 1 , imax2
            Z(i) = ATAN(Y1(i)/Y2(i))
         ENDDO
         CALL PLOTX(Z,imax2)
         WRITE (G_IO,99009) F
99009    FORMAT (' ',32X,'PHASE PLOT FOR THE DEMODULATION FREQUENCY = ',&
     &           F8.6,' CYCLES PER UNIT TIME')
!
!     COMPUTE A NEW ESTIMATE FOR THE DEMODULATION FREQUENCY AND WRITE IT OUT
!
         aimax2 = imax2
         imax2m = imax2 - 1
         iflag = 0
         zmin = Z(1)
         zmax = Z(1)
         DO i = 1 , imax2m
            ip1 = i + 1
            del = Z(ip1) - Z(i)
            IF ( del>2.5_wp ) iflag = iflag - 1
            IF ( del<-2.5_wp ) iflag = iflag + 1
            aiflag = iflag
            znew = Z(ip1) + aiflag*pi
            IF ( znew<zmin ) zmin = znew
            IF ( znew>zmax ) zmax = znew
         ENDDO
         range = zmax - zmin
         sloper = range/aimax2
         slopeh = sloper/(2.0_wp*pi)
         fest = F + slopeh
         WRITE (G_IO,99010) zmin , zmax , range
99010    FORMAT (' ',3X,'MINIMUM PHASE = ',E15.8,' RADIANS   ',         &
     &           'MAXIMUM PHASE = ',E15.8,' RADIANS   ',                &
     &           'RANGE OF PHASES = ',E15.8,' RADIANS')
         WRITE (G_IO,99011) sloper , slopeh , fest
99011    FORMAT (' ','SLOPE = ',E14.8,' RADIANS = ',E14.6,              &
     &           ' CYCLES PER UNIT TIME    EST. OF NEW DEMOD. FREQ. = ',&
     &           E15.8,' CYC./UNIT TIME')
      ENDIF
!
END SUBROUTINE DEMOD