├── quadrant.m ├── quadrantwieghted.m └── QuadScanalphawieghtedFull.m /quadrant.m: -------------------------------------------------------------------------------- 1 | function qq=quadrant(rr) 2 | 3 | %This function is to calculate the density quadrant scan curve from a recurrence matrix rr 4 | 5 | [dx,dy]=size(rr); 6 | 7 | if dx~=dy, 8 | disp('matrix not square'); 9 | end; 10 | 11 | hand=waitbar(0,'quadrant'); 12 | 13 | for i=1:dx 14 | pp=rr(1:i,1:i); %points at the first quadrant 15 | ff=rr((i+1):dx,(i+1):dx); %points at the third quadrant 16 | pf=rr(1:i,(i+1):dx); %points at the second quadrant 17 | fp=rr((i+1):dx,1:i); % points at the fourth quadrant 18 | qs=(sum(pp(:))+sum(ff(:))) /(i^2+(dx-i)^2); 19 | qs=qs / (qs + (sum(pf(:))+sum(fp(:)))/(i*(dx-i)*2)); 20 | qq(i)=qs; 21 | waitbar(i/dx,hand); 22 | 23 | end; 24 | close(hand); 25 | -------------------------------------------------------------------------------- /quadrantwieghted.m: -------------------------------------------------------------------------------- 1 | function qq=quadrantwieghted(rr) 2 | 3 | %This function is to calculate the weighted quadrand scan from a recurrence matrix rr 4 | 5 | [dx,dy]=size(rr); 6 | 7 | if dx~=dy, 8 | disp('matrix not square'); 9 | end; 10 | 11 | hand=waitbar(0,'quadrant'); 12 | qq(1)=0.5; 13 | qq(dx)=0.5; 14 | for i=2:dx-1 15 | wieghtp=0.5*(1-tanh(((1:i-1)-200)/50)); %the 200 and 50 are parameters and should be changed according to your application 16 | wieghtp=wieghtp(end:-1:1); 17 | wieghtf=0.5*(1-tanh(((1:dx-i)-200)/50)); %the 200 and 50 are parameters and should be changed according to your application 18 | wieghtpp=wieghtp'*wieghtp; 19 | wieghtpp=wieghtpp./wieghtpp(end,end); 20 | wieghtff=wieghtf'*wieghtf; 21 | wieghtff=wieghtff./wieghtff(1,1); 22 | wieghtpf=wieghtp'*wieghtf; 23 | wieghtpf=wieghtpf./wieghtpf(end,1); 24 | wieghtfp=wieghtf'*wieghtp; 25 | wieghtfp=wieghtfp./wieghtfp(1,end); 26 | pp=rr(1:(i-1),1:(i-1)).*wieghtpp; 27 | ff=rr((i+1):dx,(i+1):dx).*wieghtff; 28 | pf=rr(1:(i-1),(i+1):dx).*wieghtpf; 29 | fp=rr((i+1):dx,1:(i-1)).*wieghtfp; 30 | qs=sum(pp(:))+sum(ff(:)); 31 | qs=qs / (qs + (sum(pf(:))+sum(fp(:)))); 32 | qq(i)=qs; 33 | waitbar(i/dx,hand); 34 | 35 | end; 36 | close(hand); 37 | -------------------------------------------------------------------------------- /QuadScanalphawieghtedFull.m: -------------------------------------------------------------------------------- 1 | function [Dist,RM,QS]=QuadScanalphawieghtedFull(X,alpha) 2 | 3 | %This function is to apply Recurrence plot and Quardant Scan analysis for 4 | %transitions or boundaries detection. 5 | %X is the input data, X could be multivariate input where columns 6 | %are the variables 7 | %alpha is the threshold, it is for the recurrence analysis 8 | %Dist is the distance (norm) matrix, RM is the recurrence matrix, QS is the quadrant scan curve 9 | %If you use this code please read and cite our paper "Fast Automatic Detection of Geological Boundaries from Multivariate Log Data Using Recurrence 10 | %Journal: Computers and Geosciences" 11 | 12 | X=bsxfun(@rdivide,X,sum(X)); %normalisation (importnat when we have multi-variable input) 13 | 14 | N = size(X,1); 15 | 16 | Dist=zeros(N); 17 | 18 | %%%% Norm Matrix %%%% 19 | for i=1:N 20 | 21 | x0=i; 22 | for j=i:N 23 | y0=j; 24 | % Calculate the euclidean distance 25 | distance = norm(X(i,:)-X(j,:)); 26 | % Store the minimum distance between the two points 27 | Dist(x0,y0) = distance; 28 | Dist(y0,x0) = distance; 29 | end 30 | end 31 | 32 | 33 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Ploting the Distance (Norm) Matrix)%%%%% 34 | 35 | figure('Position',[100 100 550 400]); 36 | imagesc(Dist); 37 | colorbar; 38 | axis image; 39 | xlabel('Depth Index','FontSize',10,'FontWeight','bold'); 40 | ylabel('Depth Index','FontSize',10,'FontWeight','bold'); 41 | title('Norm Matrix','FontSize',10,'FontWeight','bold'); 42 | get(gcf,'CurrentAxes'); 43 | set(gca,'YDir','normal') 44 | set(gca,'LineWidth',2,'FontSize',10,'FontWeight','bold'); 45 | 46 | 47 | %%%%% Define threshold %%%% 48 | threshold=alpha*(mean(Dist(:))+3*std(Dist(:))); 49 | 50 | %%%%% Recurrence plot matrix %%%% 51 | RM=zeros(size(Dist,1),size(Dist,2)); 52 | for i=1:size(Dist,1) 53 | for j=i+1:size(Dist,1) 54 | if Dist(i,j) <= threshold 55 | RM(i,j)=1; 56 | RM(j,i)=1; 57 | end 58 | end 59 | end 60 | RM = RM +eye(size(Dist,1)); 61 | 62 | %%%% Ploting the recurrence plot %%% 63 | figure('Position',[100 100 550 400]); 64 | imagesc(RM); 65 | axis image; 66 | xlabel('Depth','FontSize',10,'FontWeight','bold'); 67 | ylabel('Depth','FontSize',10,'FontWeight','bold'); 68 | title('Recurrence Plot','FontSize',10,'FontWeight','bold'); 69 | get(gcf,'CurrentAxes'); 70 | set(gca,'YDir','normal') 71 | set(gca,'LineWidth',2,'FontSize',10,'FontWeight','bold'); 72 | 73 | %%%% Quadrant Scan: Two options: %%%% 74 | % (1) Density QS 75 | QS=quadrant(RM); % Density Quadrant Scan: import Function "quadrant" 76 | 77 | % (2) Weighted QS 78 | % QS=quadrantwieghted(RM); %Weighted Quadrant Scan: import Function "quadrantwieghted" 79 | 80 | %%%% Ploting the quadrant scan %%%% 81 | figure('Position',[100 100 550 400]); 82 | plot(QS) 83 | --------------------------------------------------------------------------------