Home > utilities > get_runs_test.m

get_runs_test

PURPOSE ^

Figure out a way to identify runs longer than some specified length for

SYNOPSIS ^

This is a script file.

DESCRIPTION ^

 Figure out a way to identify runs longer than some specified length for
 the purposes of calculating the volume of water which is subjected to a
 change in a parameter of some value.

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SOURCE CODE ^

0001 % Figure out a way to identify runs longer than some specified length for
0002 % the purposes of calculating the volume of water which is subjected to a
0003 % change in a parameter of some value.
0004 
0005 %% 1D
0006 
0007 % close all
0008 
0009 clear testChange negIdx dn startEndIdx gotTo inc longOnesIdx
0010 
0011 testIdx=88;
0012 
0013 dtJump=plotOPTS.change_type;
0014 lengthThreshold=12;
0015 changeThreshold=-0.5;
0016 
0017 % Model results
0018 testData=(squeeze(phChange(testIdx,1,:)));
0019 testTime=plotOPTS.Time_record(1:end-dtJump-1);
0020 % Synthetic data
0021 % testData=[10,10,9,8,7,6,4,2,0,-2,-4,-6,-8,-10,-20,-30,-40,-50,-60,-70,-80,-90,-100,-110,-109,-108,-107,-106,-105,-104,-103,-102,-101,-100,-99,-97,-95,-96,-97,-98,-99,-99,-99,-99,-99,-100,-101,-102,-103,-105,-107,-109,-111,-113,-115,-117,-119,-129,-130,-130,-129,-128,-127];
0022 % testTime=1:length(testData)-1;
0023 
0024 testChange=diff(testData);
0025 
0026 allIdx=1:length(testData); % array of index positions
0027 negIdx=testChange<0; % where the negative values are.
0028 dn=diff(negIdx); % the boundaries of those negative data
0029 
0030 % Find locations at which dn changes from zero to non-zero
0031 dnIdxStart=allIdx(dn==1)+1; % add one to move start along to correct index
0032 dnIdxEnd=allIdx(dn==-1);
0033 
0034 % Check if the start and end are identical (i.e. we have a spike).
0035 if (numel(dnIdxStart)==1 || numel(dnIdxEnd)==1)
0036     if dnIdxStart==dnIdxEnd
0037         warning('Single spike in time series, so carry on.')
0038         continue
0039     end
0040 end
0041 
0042 if sum(dnIdxStart)==0 || sum(dnIdxEnd)==0
0043     % No appropriate values here, so carry on.
0044     continue
0045 end
0046 
0047 % If arrays are different lengths, lop off the last one from the longer
0048 % array.
0049 if length(dnIdxEnd)>length(dnIdxStart)
0050     timeIndices=(dnIdxEnd(1:end-1)-dnIdxStart)>=lengthThreshold;
0051 elseif length(dnIdxEnd)<length(dnIdxStart)
0052     timeIndices=(dnIdxEnd-dnIdxStart(1:end-1))>=lengthThreshold;
0053 elseif length(dnIdxEnd)==length(dnIdxStart)
0054     if dnIdxStart(1)==1
0055         timeIndices=(dnIdxEnd(1:end-1)-dnIdxStart(2:end))>=lengthThreshold;
0056     elseif dnIdxEnd(1)==1
0057         timeIndices=(dnIdxEnd(2:end)-dnIdxStart(1:end-1))>=lengthThreshold;
0058     else
0059         timeIndices=(dnIdxEnd-dnIdxStart)>=lengthThreshold;
0060     end
0061 else
0062     return
0063 end
0064 
0065 if sum(timeIndices~=0)
0066     longOnesIdx(:,1)=dnIdxStart(timeIndices);
0067     longOnesIdx(:,2)=dnIdxEnd(timeIndices);
0068 else
0069     return
0070 end
0071 
0072 % Check the change magnitude for those time steps. Here we have to decide
0073 % if we're doing average change over the n-hour time period, or the maximum
0074 % instantaneous change, or ... For a first go, we'll do the average change
0075 % and use that for the threshold comparison.
0076 checkInc=1;
0077 totalVolume=0;
0078 for jj=1:size(longOnesIdx,2)
0079     averageChange=mean(testData(longOnesIdx(jj,1):longOnesIdx(jj,2)));
0080     if averageChange<changeThreshold
0081         totalVolume=totalVolume+cellVolume(longOnesIdx(jj,1):longOnesIdx(jj,2));
0082         checkInc=checkInc+1;
0083     end
0084 end
0085 
0086 close all
0087 
0088 figure(2)
0089 plot(testTime,testChange)
0090 hold on
0091 plot(testTime(testChange<0),testChange(testChange<0),'r.')
0092 % plot(testTime(4:end)-((testTime(2)-testTime(1))/2),dn*0.01,'gp')
0093 for i=1:size(longOnesIdx,1)
0094     plot(testTime(longOnesIdx(i,:)),zeros(1,length(longOnesIdx(i,:))),'g-x')
0095     text(mean(testTime(longOnesIdx(i,:))),0.01,num2str((testTime(longOnesIdx(i,2))-testTime(longOnesIdx(i,1)))*24))
0096 end
0097 
0098 %% 1Dv2
0099 
0100 close all
0101 
0102 clear testChange negIdx dn startEndIdx gotTo inc longOnesIdx
0103 
0104 testIdx=124;
0105 
0106 dtJump=plotOPTS.change_type;
0107 lengthThreshold=4;
0108 changeThreshold=-1.5;
0109 
0110 % Model results
0111 testData=(squeeze(phChange(testIdx,1,:)));
0112 testTime=plotOPTS.Time_record(1:end-dtJump-1);
0113 % Synthetic data
0114 % testData=[10,10,9,8,7,6,4,2,0,-2,-4,-6,-8,-10,-20,-30,-40,-50,-60,-70,-80,-90,-100,-110,-109,-108,-107,-106,-105,-104,-103,-102,-101,-100,-99,-97,-95,-96,-97,-98,-99,-99,-99,-99,-99,-100,-101,-102,-103,-105,-107,-109,-111,-113,-115,-117,-119,-129,-130,-130,-129,-128,-127];
0115 % testTime=1:length(testData)-1;
0116 
0117 testChange=diff(testData);
0118 
0119 allIdx=1:length(testData); % array of index positions
0120 negIdx=testChange<0; % where the negative values are.
0121 dn=diff(negIdx); % the boundaries of those negative data
0122 
0123 % Find locations at which dn changes from zero to non-zero
0124 dnIdxStart=allIdx(dn==1)+1; % add one to move start along to correct index
0125 dnIdxEnd=allIdx(dn==-1);
0126 
0127 % Check if the start and end are identical (i.e. we have a spike).
0128 if (numel(dnIdxStart)==1 || numel(dnIdxEnd)==1)
0129     if dnIdxStart==dnIdxEnd
0130         warning('Single spike in time series, so carry on.')
0131     end
0132 end
0133 % Check for no values
0134 if sum(dnIdxStart)==0 || sum(dnIdxEnd)==0
0135     % No appropriate values here, so carry on.
0136     warning('No appropriate values here, so carry on.')
0137 end
0138 % Check the first index in dnIdxEnd is larger than the dnIdxStart.
0139 if dnIdxEnd(1)<dnIdxStart(1)
0140     % Strip it out and adjust the dnIdxStart index accordingly.
0141     dnIdxEnd=dnIdxEnd(2:end);
0142     dnIdxStart=dnIdxStart(1:end-1);
0143 end
0144 
0145 
0146 % If arrays are different lengths, lop off the last one from the longer
0147 % array.
0148 if size(dnIdxEnd,2)>size(dnIdxStart,2)
0149     longOnesIdx(:,1)=dnIdxStart((dnIdxEnd(1:end-1)-dnIdxStart)>=lengthThreshold);
0150     longOnesIdx(:,2)=dnIdxEnd((dnIdxEnd(1:end-1)-dnIdxStart)>=lengthThreshold);
0151 elseif size(dnIdxEnd,2)<size(dnIdxStart,2)
0152     longOnesIdx(:,1)=dnIdxStart((dnIdxEnd-dnIdxStart(1:end-1))>=lengthThreshold);
0153     longOnesIdx(:,2)=dnIdxEnd((dnIdxEnd-dnIdxStart(1:end-1))>=lengthThreshold);
0154 else
0155     if dnIdxStart(1)==1
0156         longOnesIdx(:,1)=dnIdxStart((dnIdxEnd(1:end-1)-dnIdxStart(2:end))>=lengthThreshold);
0157         longOnesIdx(:,2)=dnIdxEnd((dnIdxEnd(1:end-1)-dnIdxStart(2:end))>=lengthThreshold);
0158     elseif dnIdxEnd(1)==1
0159         longOnesIdx(:,1)=dnIdxStart((dnIdxEnd(2:end)-dnIdxStart(1:end-1))>=lengthThreshold);
0160         longOnesIdx(:,2)=dnIdxEnd((dnIdxEnd(2:end)-dnIdxStart(1:end-1))>=lengthThreshold);
0161     else
0162         longOnesIdx(:,1)=dnIdxStart((dnIdxEnd-dnIdxStart)>=lengthThreshold);
0163         longOnesIdx(:,2)=dnIdxEnd((dnIdxEnd-dnIdxStart)>=lengthThreshold);
0164     end        
0165 end
0166 
0167 close all
0168 
0169 plot(testTime,testChange)
0170 hold on
0171 plot(testTime(testChange<0),testChange(testChange<0),'r.')
0172 % plot(testTime(4:end)-((testTime(2)-testTime(1))/2),dn*0.01,'gp')
0173 for i=1:size(longOnesIdx,1)
0174     plot(testTime(longOnesIdx(i,:)),zeros(1,length(longOnesIdx(i,:))),'g-x')
0175     text(mean(testTime(longOnesIdx(i,:))),0.01,num2str((testTime(longOnesIdx(i,2))-testTime(longOnesIdx(i,1)))*24))
0176 end
0177 
0178 
0179 %% 2D
0180 
0181 clear testChange negIdx dn startEndIdx gotTo inc allInc longOnesIdx
0182 
0183 dtJump=plotOPTS.change_type;
0184 lengthThreshold=7;
0185 changeThreshold=-0.1;
0186 
0187 testData=squeeze(phChange(:,1,:));
0188 testTime=plotOPTS.Time_record(1:end-dtJump-1);
0189 
0190 inc=1;
0191 
0192 % Easiest way I can think of doing this is to just loop through each
0193 % element, doing each timestep as a 1D analysis.
0194 for i=1:size(testData,1);
0195     disp(i)
0196     testChange=diff(testData(i,:),1,2);
0197     allIdx=1:length(testChange);
0198     negIdx=testChange<0; % where the negative values are.
0199     dn=diff(negIdx,1,2);
0200 
0201     % Add one to move start along to correct index. Since the diff
0202     % describes the relationship between the first and second value in
0203     % testData at the first value of dn. So, if you have a change between
0204     % the first and second testData values, then the start of the run is
0205     % necessarily at the second index in testData. For the end though, the
0206     % index in dn will describe the change from the run to a non-run part,
0207     % so we don't need to adjust that in the same way. We need also to
0208     % adjust the values of testChange when comparine them with
0209     %
0210     % allIdx:   |  1  |  2  |  3  |  4  |  5  |  6  |  7  |
0211     % testData: |  P  |     |     |     |     |  P  |     |
0212     %           |     |  N  |  N  |  N  |  N  |     |  N  |
0213     % negIdx:   |  0  |  1  |  1  |  1  |  1  |  0  |  1  |
0214     % dn:       |  1  |  0  |  0  |  0  | -1  |  1  |  ~  |
0215     %
0216     % So you can see that dn is positive before the start of the N run
0217     % whilst dn is negative at the last element of the run. So we need to
0218     % increase the idxStart value by one. The idxEnd doesn't need to be
0219     % modified this way.
0220     idxStart_dn=allIdx(dn==1)+1;
0221 %     idxStart_tc=allIdx(testChange(1:end-1)<changeThreshold);
0222 %     dnIdxStart=intersect(idxStart_dn,idxStart_tc);
0223     dnIdxStart=idxStart_dn;
0224     idxEnd_dn=allIdx(dn==-1);
0225 %     idxEnd_tc=allIdx(testChange(1:end-1)<changeThreshold);
0226 %     dnIdxEnd=intersect(idxEnd_dn,idxEnd_tc);
0227     dnIdxEnd=idxEnd_dn;
0228 
0229     % QC the picked results.
0230 
0231     % Check if the start and end are identical (i.e. we have a spike).
0232     if (numel(dnIdxStart)==1 || numel(dnIdxEnd)==1)
0233         if dnIdxStart==dnIdxEnd
0234             warning('Single spike in time series, so carry on.')
0235             continue
0236         end
0237     end
0238     % Check for no values
0239     if sum(dnIdxStart)==0 || sum(dnIdxEnd)==0
0240         % No appropriate values here, so carry on.
0241         warning('No appropriate values here, so carry on.')
0242         continue
0243     end
0244     % Check the first index in dnIdxEnd is larger than the dnIdxStart.
0245     if dnIdxEnd(1)<dnIdxStart(1)
0246         % Strip it out and adjust the dnIdxStart index accordingly.
0247         dnIdxEnd=dnIdxEnd(2:end);
0248         dnIdxStart=dnIdxStart(1:end-1);
0249     end
0250 
0251     % If arrays are different lengths, lop off the last one from the longer
0252     % array.
0253     if size(dnIdxEnd,2)>size(dnIdxStart,2)
0254         % Not ideal with the try's, but it seems to work...
0255         try
0256             timeRange(:,1)=dnIdxStart((dnIdxEnd(1:end-1)-dnIdxStart)>=lengthThreshold);
0257             timeRange(:,2)=dnIdxEnd((dnIdxEnd(1:end-1)-dnIdxStart)>=lengthThreshold);
0258         catch %#ok<CTCH>
0259             continue
0260         end
0261     elseif size(dnIdxEnd,2)<size(dnIdxStart,2)
0262         try
0263             timeRange(:,1)=dnIdxStart((dnIdxEnd-dnIdxStart(1:end-1))>=lengthThreshold);
0264             timeRange(:,2)=dnIdxEnd((dnIdxEnd-dnIdxStart(1:end-1))>=lengthThreshold);
0265         catch %#ok<CTCH>
0266             continue
0267         end
0268     else
0269         try
0270             timeRange(:,1)=dnIdxStart((dnIdxEnd-dnIdxStart)>=lengthThreshold);
0271             timeRange(:,2)=dnIdxEnd((dnIdxEnd-dnIdxStart)>=lengthThreshold);
0272         catch %#ok<CTCH>
0273             continue
0274         end
0275     end
0276     
0277     % Now do the magnitude check now.
0278     timeRange=timeRange(testChange(timeRange(:,1))<changeThreshold & testChange(timeRange(:,2))<changeThreshold,:);
0279     % If the start and end ranges are non-zero in length, add them to the
0280     % longOnesIdx cell array.
0281     if numel(timeRange)>=2
0282         longOnesIdx{inc}=timeRange;
0283         allInc(inc)=i;
0284         inc=inc+1;
0285     end
0286 end
0287 
0288 %% 2Dv2
0289 
0290 clear testChange negIdx dn startEndIdx gotTo inc allInc longOnesIdx timeRange
0291 
0292 dtJump=plotOPTS.change_type;
0293 lengthThreshold=2;
0294 changeThreshold=-1;
0295 
0296 testData=squeeze(phChange(:,1,:));
0297 testTime=plotOPTS.Time_record(1:end-dtJump-1);
0298 
0299 inc=1;
0300 
0301 % Easiest way I can think of doing this is to just loop through each
0302 % element, doing each timestep as a 1D analysis.
0303 for i=222%1:size(testData,1);
0304     disp(i)
0305     % Model results
0306     testData=squeeze(phChange(i,1,:))*10000000000;
0307     testTime=plotOPTS.Time_record(1:end-dtJump-1);
0308     % Synthetic data
0309     % testData=[10,10,9,8,7,6,4,2,0,-2,-4,-6,-8,-10,-20,-30,-40,-50,-60,-70,-80,-90,-100,-110,-109,-108,-107,-106,-105,-104,-103,-102,-101,-100,-99,-97,-95,-96,-97,-98,-99,-99,-99,-99,-99,-100,-101,-102,-103,-105,-107,-109,-111,-113,-115,-117,-119,-129,-130,-130,-129,-128,-127];
0310     % testTime=1:length(testData)-1;
0311 
0312     testChange=diff(testData);
0313 
0314     allIdx=1:length(testData); % array of index positions
0315     negIdx=testChange<0; % where the negative values are.
0316     dn=diff(negIdx); % the boundaries of those negative data
0317 
0318     % Find indices at which dn changes from zero to non-zero
0319     dnIdxStart=allIdx(dn==1)+1; % add one to move start along to correct index
0320     dnIdxEnd=allIdx(dn==-1);
0321 
0322     % Check if the start and end are identical (i.e. we have a spike).
0323     if (numel(dnIdxStart)==1 || numel(dnIdxEnd)==1)
0324         if dnIdxStart==dnIdxEnd
0325             warning('Single spike in time series, so carry on.')
0326             continue
0327         end
0328     end
0329     % Check for no values
0330     if sum(dnIdxStart)==0 || sum(dnIdxEnd)==0
0331         % No appropriate values here, so carry on.
0332         warning('No appropriate values here, so carry on.')
0333         continue
0334     end
0335     % Check the first index in dnIdxEnd is larger than the dnIdxStart.
0336     if dnIdxEnd(1)<dnIdxStart(1)
0337         % Strip it out and adjust the dnIdxStart index accordingly.
0338         dnIdxEnd=dnIdxEnd(2:end);
0339         dnIdxStart=dnIdxStart(1:end-1);
0340     end
0341 
0342     % If arrays are different lengths, lop off the last one from the longer
0343     % array.
0344     clear timeRange
0345     if size(dnIdxEnd,2)>size(dnIdxStart,2)
0346         % Not ideal with the try's, but it seems to work...
0347         try
0348             timeRange(:,1)=dnIdxStart((dnIdxEnd(1:end-1)-dnIdxStart)>=lengthThreshold);
0349             timeRange(:,2)=dnIdxEnd((dnIdxEnd(1:end-1)-dnIdxStart)>=lengthThreshold);
0350         catch %#ok<CTCH>
0351             continue
0352         end
0353     elseif size(dnIdxEnd,2)<size(dnIdxStart,2)
0354         try
0355             timeRange(:,1)=dnIdxStart((dnIdxEnd-dnIdxStart(1:end-1))>=lengthThreshold);
0356             timeRange(:,2)=dnIdxEnd((dnIdxEnd-dnIdxStart(1:end-1))>=lengthThreshold);
0357         catch %#ok<CTCH>
0358             continue
0359         end
0360     else
0361         try
0362             timeRange(:,1)=dnIdxStart((dnIdxEnd-dnIdxStart)>=lengthThreshold);
0363             timeRange(:,2)=dnIdxEnd((dnIdxEnd-dnIdxStart)>=lengthThreshold);
0364         catch %#ok<CTCH>
0365             continue
0366         end
0367     end
0368 
0369     % Now do the magnitude check now.
0370     timeRange=timeRange(testChange(timeRange(:,1))<changeThreshold & testChange(timeRange(:,2))<changeThreshold,:);
0371     
0372     % If the start and end ranges are non-zero in length, add them to the
0373     % longOnesIdx cell array.
0374     if numel(timeRange)>=2
0375         longOnesIdx{inc}=timeRange;
0376         allInc(inc)=i;
0377         inc=inc+1;
0378     end
0379 
0380 %     if size(dnIdxEnd,2)>size(dnIdxStart,2)
0381 %         try
0382 %             timeRange
0383 %             longOnesIdx{inc}(:,1)=dnIdxStart((dnIdxEnd(1:end-1)-dnIdxStart)>=lengthThreshold);
0384 %             longOnesIdx{inc}(:,2)=dnIdxEnd((dnIdxEnd(1:end-1)-dnIdxStart)>=lengthThreshold);
0385 %             allInc(inc)=i;
0386 %             inc=inc+1;
0387 %         end
0388 %     elseif size(dnIdxEnd,2)<size(dnIdxStart,2)
0389 %         try
0390 %             longOnesIdx{inc}(:,1)=dnIdxStart((dnIdxEnd-dnIdxStart(1:end-1))>=lengthThreshold);
0391 %             longOnesIdx{inc}(:,2)=dnIdxEnd((dnIdxEnd-dnIdxStart(1:end-1))>=lengthThreshold);
0392 %             allInc(inc)=i;
0393 %             inc=inc+1;
0394 %         end
0395 %     else
0396 %         try
0397 %             longOnesIdx{inc}(:,1)=dnIdxStart((dnIdxEnd-dnIdxStart)>=lengthThreshold);
0398 %             longOnesIdx{inc}(:,2)=dnIdxEnd((dnIdxEnd-dnIdxStart)>=lengthThreshold);
0399 %             allInc(inc)=i;
0400 %             inc=inc+1;
0401 %         end
0402 %     end
0403 
0404    
0405 %     close all
0406 %
0407 %     plot(testTime,testChange)
0408 %     hold on
0409 %     plot(testTime(testChange<0),testChange(testChange<0),'r.')
0410 %     % plot(testTime(4:end)-((testTime(2)-testTime(1))/2),dn*0.01,'gp')
0411 %     for j=1:size(longOnesIdx{inc-1},1)
0412 %         plot(testTime(longOnesIdx{inc}(j,:)),zeros(1,length(longOnesIdx{inc}(j,:))),'g-x')
0413 %         text(mean(testTime(longOnesIdx{inc-1}(j,:))),0.01,num2str((testTime(longOnesIdx{inc-1}(j,2))-testTime(longOnesIdx{inc-1}(j,1)))*24))
0414 %     end
0415 
0416 end
0417 %%
0418 close all
0419 
0420 [tx,ty]=meshgrid(1:size(testChange,2),1:size(testChange,1));
0421 
0422 pcolor(tx,ty,testChange); shading flat; axis tight
0423 colorbar
0424 caxis([-1 1])
0425 hold on
0426 plot(tx(allIdx(dn<0)),ty(allIdx(dn<0)),'r.')
0427 plot(tx(allIdx(dn>0)),ty(allIdx(dn>0)),'g.')
0428 for i=1:size(longOnesIdx,1)
0429     plot(tx(longOnesIdx(i,1)),ty(longOnesIdx(i,2)),'g-x')
0430 end
0431 
0432 %% 1D (old way)
0433 
0434 % % Find continuous negatives for more than changeThreshold "hours".
0435 % inc=0;
0436 % gotTo=1;
0437 % for i=1:length(dn)
0438 %     % Check whether we're in a flat big (i.e. the change is constant) and
0439 %     % whether the value of the change exceeds the threshold change
0440 %     % specified.
0441 %     if dn(i)==0 && testChange(i)<0
0442 %         fprintf('dn: %i\ttestChange: %i\tinc: %i\n',dn(i),testChange(i),inc)
0443 %         % Check what the value of inc is:
0444 %         % - If it's zero, we're at the start of a run.
0445 %         % - If it's non-zero, we're part way through a run.
0446 %         % - If it's negative, the last value was the end of a run.
0447 %         if inc==0
0448 %             % Start of a run
0449 %             startEndIdx(gotTo,1)=i;
0450 %             gotTo=gotTo+1;
0451 %             inc=1;
0452 %         elseif inc>0
0453 %             % Midway through a run
0454 %             inc=inc+1;
0455 %         else
0456 %             warning('Uhhh... this shouldn''t ever appear...')
0457 %         end
0458 %     elseif dn(i)~=0 && testChange(i)<0
0459 %         % At the end of a run when diff is non-zero and increment is
0460 %         % greater than zero.
0461 %         if inc>0
0462 %             startEndIdx(gotTo-1,2)=i;
0463 %             inc=0;
0464 %         end
0465 %     end
0466 %
0467 % end
0468 
0469

Generated on Wed 20-Feb-2019 16:06:01 by m2html © 2005