mirror of
				https://github.com/KevinMidboe/linguist.git
				synced 2025-10-29 17:50:22 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			110 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			110 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
undef("PrnOscPat_driver")
 | 
						|
function PrnOscPat_driver(eof[*][*][*]:numeric, eof_ts[*][*]:numeric, kPOP[1]:integer)
 | 
						|
; =================================================================
 | 
						|
; compute Principal Oscillation Patterns (POPs)
 | 
						|
; =================================================================
 | 
						|
local dim_ts, dim_eof, neof, ntim, nlat, mlon, dnam_ts, dnam_eof, neof, j \
 | 
						|
    , cov0, cov1, cov0_inverse, A, z, Z, pr, pi, zr, zi, mean, stdev      \
 | 
						|
    , evlr, eigi, eigr   
 | 
						|
begin
 | 
						|
 | 
						|
  dim_ts  = dimsizes(eof_ts)        ; (neof,ntim)
 | 
						|
  dim_eof = dimsizes(eof)           ; (neof,nlat,mlon)
 | 
						|
 | 
						|
  ntim    = dim_ts(1)
 | 
						|
  neof    = dim_eof(0)
 | 
						|
  nlat    = dim_eof(1)
 | 
						|
  mlon    = dim_eof(2)
 | 
						|
 | 
						|
  dnam_ts = getvardims(eof_ts)      ; dimension names
 | 
						|
  dnam_eof= getvardims(eof)         ; used at end for meta data
 | 
						|
 | 
						|
; =================================================================
 | 
						|
; lag-0 and lag-1  matrices 
 | 
						|
; =================================================================
 | 
						|
 | 
						|
  if (get_ncl_version().eq."6.1.2") then                ; bug in 6.1.2
 | 
						|
      cov0    = covcorm(eof_ts,(/1,0/))			; lag-0 covariance matrix
 | 
						|
  else
 | 
						|
      cov0    = covcorm(eof_ts,(/0,1/))			; lag-0 covariance matrix (n x n)
 | 
						|
  end if
 | 
						|
                                                        ; either
 | 
						|
  cov1    = covcorm_xy(eof_ts, eof_ts, (/0,1,0/))       ; lag-1 
 | 
						|
 ;cov1    = covcorm_xy(eof_ts(:,0:ntim-2) \             ; alternative, brute force
 | 
						|
 ;                    ,eof_ts(:,1:ntim-1), (/0,0,0/)) 
 | 
						|
 ;printVarSummary(cov1)
 | 
						|
 | 
						|
; =================================================================
 | 
						|
; matrix A contains information for evolution of the POP system. 
 | 
						|
; POPs are eigenvectors of A.  
 | 
						|
; =================================================================
 | 
						|
 | 
						|
  cov0_inverse = inverse_matrix(cov0)
 | 
						|
  A = cov1#inverse_matrix(cov0)                         ; [*][*] => neof x neof
 | 
						|
 | 
						|
; =================================================================
 | 
						|
; NCL 6.1.1 of dgeevx:  evlr(2,2,N,N) ; (left(0)/right(1), real(0)/imag(1),:,:)
 | 
						|
; Eigenvalues are returned as attributes: eigi  = evlr@eigi  ; eigr  = evlr@eigr
 | 
						|
; =================================================================
 | 
						|
 | 
						|
  evlr  = dgeevx_lapack(A, "B", "V", "V", "B", False)  
 | 
						|
 | 
						|
; =================================================================
 | 
						|
; POP time series from eigenvalues and right eigenvectors 
 | 
						|
; ================================================================= 
 | 
						|
 ;PR   = (/ evlr(1,0,:,:) /)         ; right ev (1), real part (0)
 | 
						|
 ;PI   = (/ evlr(1,1,:,:) /)         ; right ev (1), imag part (1)
 | 
						|
                                     ; kPOP is what we want; use righteigenvector
 | 
						|
  pr   = (/ evlr(1,0,kPOP-1,:) /)    ; right ev (1), real part (0), row 'kPOP-1' 
 | 
						|
  pi   = (/ evlr(1,1,kPOP-1,:) /)    ; right ev (1), imag part (1), row 'kPOP-1'
 | 
						|
   
 | 
						|
  z    = inverse_matrix( (/ (/sum(pr*pr), sum(pr*pi)/) \
 | 
						|
                          , (/sum(pr*pi), sum(pi*pi)/) /))#(/pr,pi/)#eof_ts
 | 
						|
   
 | 
						|
                                                        ; complex conjugate
 | 
						|
  z    = (/z(0,:), -z(1,:)/)       		    	; real & imag series
 | 
						|
  z    = dim_rmvmean_n(z,1)
 | 
						|
  mean = dim_avg_n(z,1)                                 ; calculate mean
 | 
						|
  stdev= dim_stddev_n(z,1)                              ; calculate stdev
 | 
						|
  z    = dim_standardize_n(z,1,1)			; standardize time series
 | 
						|
 | 
						|
  z!0     = "nPOP"				        ; add meta data
 | 
						|
  z!1     = dnam_ts(1)		
 | 
						|
  z&nPOP  = (/0,1/)
 | 
						|
  z&$dnam_ts(1)$ = eof_ts&$dnam_ts(1)$            
 | 
						|
  z@stdev = stdev				
 | 
						|
  z@mean  = mean			
 | 
						|
  z@long_name = "POP timeseries"			
 | 
						|
 ;printVarSummary(z)
 | 
						|
 | 
						|
; =================================================================
 | 
						|
; POP spatial patterns
 | 
						|
; =================================================================
 | 
						|
 | 
						|
  zr = pr(0)*eof(0,:,:)			; construct POP spatial domain
 | 
						|
  zi = pi(0)*eof(0,:,:)
 | 
						|
  do j=1,neof-1
 | 
						|
     zr = zr + pr(j)*eof(j,:,:)
 | 
						|
     zi = zi + pi(j)*eof(j,:,:)
 | 
						|
  end do
 | 
						|
 | 
						|
  Z   = (/zr*stdev(0), -zi*stdev(1)/)	; scale patterns by time series stdev
 | 
						|
 | 
						|
  Z!0 = "nPOP"				; add meta data
 | 
						|
  Z!1 = dnam_eof(1)
 | 
						|
  Z!2 = dnam_eof(2)
 | 
						|
 | 
						|
  Z&nPOP          = (/0,1/)                             
 | 
						|
  Z&$dnam_eof(1)$ = eof&$dnam_eof(1)$    
 | 
						|
  Z&$dnam_eof(2)$ = eof&$dnam_eof(2)$    
 | 
						|
  Z@long_name     = "POP pattern"
 | 
						|
 ;printVarSummary(Z)
 | 
						|
 | 
						|
; =================================================================
 | 
						|
; return POP time series and POP spatial patterns as a 
 | 
						|
; variable of type 'list' which contains 2 variables
 | 
						|
; =================================================================
 | 
						|
 | 
						|
  return( [/z, Z/] )    ; this is type "list"      
 | 
						|
end
 |