next up previous print clean
Next: References Up: MULTISCALE, SELF-SIMILAR FITTING Previous: Scale-invariance introduces more fitting

Coding the multiscale filter operator

Equation (3) shows an example where the first output signal is the ordinary one and the second output signal used a filter interlaced with zeros. We prepare subroutines that allow for more output signals, each with its own filter interlace parameter given in the table jump(ns). Each entry in the jump table corresponds to a particular scaling of a filter axis. The number of output signals is ns and the number of zeros interlaced between filter points for the j-th signal is jump(j)-1.

The multiscale helix filter is defined in module mshelix [*], analogous to the single-scale module helix [*]. A new function onescale extracts our usual helix filter of one particular scale from the multiscale filter.

 

module mshelix {                                # multiscale helix filter type
  use helix
  type msfilter {             
    real,    dimension( :),    pointer :: flt   # (nh) filter coefficients
    integer, dimension( :, :), pointer :: lag   # (nh,ns) filter (lags,scales)
    logical, dimension( :, :), pointer :: mis   # (nd,ns) boundary conditions
  }
contains
  subroutine msallocate( msaa, nh, ns) {
    type( msfilter)   :: msaa
    integer           :: nh, ns
    allocate( msaa%flt( nh), msaa%lag( nh, ns))
    msaa%flt = 0.;  nullify( msaa%mis)
    }
  subroutine msdeallocate( msaa) {
    type( msfilter) :: msaa
    deallocate( msaa%flt, msaa%lag)
    if( associated( msaa%mis)) deallocate( msaa%mis)
    }
  subroutine onescale( i, msaa, aa) {      # Extract single-scale filter.
    integer, intent (in) :: i
    type( filter)        :: aa
    type( msfilter)      :: msaa
    aa%flt => msaa%flt
    aa%lag => msaa%lag( :, i)
    if( associated( msaa%mis)) 
	aa%mis => msaa%mis( :, i)
    else
        nullify( aa%mis)
    }
}

We create a multscale helix with module createmshelixmod [*]. An expanded scale helix filter is like an ordinary helix filter except that the lags are scaled according to a jump.

 

module createmshelixmod {         # Create multiscale helix filter lags and mis
use mshelix
use createhelixmod
use bound
contains
  function createmshelix( nd, center, gap, jump, na)  result( msaa) {
    type( msfilter)                   :: msaa    # needed by mshelicon.
    integer, dimension(:), intent(in) :: nd, na  # data and filter axes
    integer, dimension(:), intent(in) :: center  # normally (na1/2,na2/2,...,1)
    integer, dimension(:), intent(in) :: gap     # normally ( 0,   0,  0,...,0)
    integer, dimension(:), intent(in) :: jump	 # jump(ns) stretch scales
    type( filter)                     :: aa
    integer                           :: is, ns, nh, n123 
    aa = createhelix( nd, center, gap, na)
    ns = size( jump);  nh = size( aa%lag);  n123 = product( nd)
    call msallocate( msaa, nh, ns)
    do is = 1, ns	
        msaa%lag(:,is) = aa%lag(:)*jump(is)	 # set lags for expanded scale
    call deallocatehelix( aa)
    allocate( msaa%mis( n123, ns))
    do is = 1, ns {				 # for all scales
     call onescale( is, msaa, aa);  nullify( aa%mis)	# extract a filter
     call boundn( nd, nd, na*jump(is), aa)		# set up its boundaries
     msaa%mis( :, is) = aa%mis;  deallocate( aa%mis)	# save them
    }
  }
}

First we examine code for estimating a prediction-error filter that is applicable at many scales. We simply invoke the usual filter operator hconest [*] for each scale.

 

module mshconest {      # multi-scale helix convolution, adjoint is the filter.
  use mshelix
  use hconest
  use helix
  integer, private                   :: nx, ns
  real,    dimension(:),     pointer :: x
  type( msfilter)                    :: msaa
#% _init( x, msaa)
   nx = size( x);   ns = size( msaa%lag, 2)
#% _lop( a(:), y(nx,ns))
    integer  :: is, stat1
    type (filter) :: aa
    do is = 1, ns {  
  	call onescale (is, msaa, aa)
       	call hconest_init( x, aa)
       	stat1 = hconest_lop( adj, .true., a, y(:,is))
    }
}

The multiscale prediction-error filter finding subroutine is nearly identical to the usual subroutine find_pef() [*]. (That routine cleverly ignores missing data while estimating a PEF.) To easily extend pef to multiscale filters we replace its call to the ordinary helix filter module hconest [*] by a call to mshconest.  

module mspef {         # Find multi-scale prediction-error filter (helix magic)
  use mshconest
  use cgstep_mod
  use solver_mod
contains
  subroutine find_pef( yy, aa, niter) {
    integer,             intent( in)              :: niter
    real, dimension( :), pointer                  :: yy
    type( msfilter)                               :: aa
    integer                                       :: is
    real, dimension( size( yy), size( aa%lag, 2)) :: dd
    do is = 1, size( dd, 2)
       dd( :,is) = -yy
    call mshconest_init( yy, aa)
    call solver( mshconest_lop, cgstep, aa%flt, pack( dd, .true.), 
                 niter, x0= aa%flt)
    call cgstep_close()
    }
}

The purpose of pack(dd,.true.) is to produce the one-dimensional array expected by solver() [*].

Similar code applies to the operator in (4) which is needed for missing data problems. This is like mshconest [*] except the adjoint is not the filter but the input.

 

module mshelicon {                                  # Multi-scale convolution
  use mshelix
  use helicon
  integer           :: nx, ns
  type( msfilter)   :: msaa
#%  _init (nx, ns, msaa)
#%  _lop ( xx( nx),  yy( nx, ns))
  integer :: is, stat1
  type (filter) :: aa
  do is = 1, ns { 
     call onescale( is, msaa, aa)
     call helicon_init( aa)
     stat1 = helicon_lop( adj, .true., xx, yy(:,is))
     }
}

The multiscale missing-data module msmis2 is just like the usual missing-data module mis2 [*] except that the filtering is done with the multiscale filter mshelicon [*].

 

module msmis2 {                      # multi-scale missing data interpolation
  use mshelicon
  use cgstep_mod
  use solver_mod
contains
  subroutine mis1( niter, nx, ns, xx, aa, known) {
    integer,                intent( in)     :: niter, nx, ns
    logical, dimension( :), intent( in)     :: known
    type( msfilter),        intent( in)     :: aa
    real,    dimension( :), intent( in out) :: xx
    real,    dimension( nx*ns)              :: dd
    dd = 0.
    call mshelicon_init( nx,ns, aa)
    call solver( mshelicon_lop, cgstep, niter= niter, x = xx, dat = dd, 
                    known = known, x0 = xx)
    call cgstep_close()
  }
}


next up previous print clean
Next: References Up: MULTISCALE, SELF-SIMILAR FITTING Previous: Scale-invariance introduces more fitting
Stanford Exploration Project
12/26/2000