-2

How to calculate the longest consecutive pattern of C/T anywhere in sequence and longest consecutive pattern of C/T from centre

CCCCTGTTGCCAAACAATGC

TTTTCCCGCCTTTGGCCTAC

TACACGGAACCTCTTTTTTA

The desired output is to calculate the longest consecutive pattern of C/T anywhere in sequence and longest consecutive pattern of C/T from centre

CCCCTGTTGCCAAACAATGC 5 2

TTTTCCCGCCTTTGGCCTAC 7 5

TACACGGAACCTCTTTTTTA 10 10

The first line has 5 consecutive pattern of C/T in the sequence, while the longest C/T pattern from center is 2.

PS. A solution to similar question is here Count the longest stretch of consecutive patterns

  • What do you mean by "from centre"? Du you mean only in the second half of the sequence? The first sequence does not contain a run two C or T in the second half. – Kusalananda Oct 15 '18 at 9:56
2

I assume you mean by "from center" is "the sequence that includes the middle character of the string. I've added a line to the testing data such that the middle character of the string is neither a C or a T:

$ cat file
CCCCTGTTGCCAAACAATGC
TTTTCCCGCCTTTGGCCTAC
TACACGGAACCTCTTTTTTA
CATAAAAAAAAAAAAACTCT

The solution relies on awk's RSTART and RLENGTH variables that are set as a by-product of the match() function matching the pattern, and some arithmetic to keep track of where we are in the string:

awk '{
    line = $0
    max = max_ctr = 0
    mid = int(length($0)/2)
    idx = 1
    while (match( substr(line,idx), /[CT]+/ )) {
        if (RLENGTH > max) max = RLENGTH
        if (idx <= mid && mid <= idx+RLENGTH) max_ctr = RLENGTH
        idx += RSTART + RLENGTH - 1
    }
    print $0, max, max_ctr
}' file

outputs

CCCCTGTTGCCAAACAATGC 5 2
TTTTCCCGCCTTTGGCCTAC 7 5
TACACGGAACCTCTTTTTTA 10 10
CATAAAAAAAAAAAAACTCT 4 0
0

In case "from centre" means "longest string closest to centre but not necessarily crossing it", you could try

awk '
        {MID = int(length()/2);
         MX = PTR = 0 
         T0 = $0
         while (match ($0, /[CcTt]+/))  {if (RLENGTH > MX) MX = RLENGTH

                                         SSTR = PTR  + RSTART
                                         SEND = SSTR + RLENGTH - 1
                                         TMPS = SSTR - MID
                                         TMPE = MID  - SEND
                                         if  (SEND < MID)                                       {P = TMPE; RES = RLENGTH}
                                         else   {if (SSTR <= MID)                               {P = 0;    RES = RLENGTH}
                                                 else if ((P > TMPS) ||
                                                          (P == TMPS) && (RLENGTH >  RES))      {P = TMPS; RES = RLENGTH}
                                                }
                                         PTR  = SEND
                                         $0 = substr ($0, RSTART + RLENGTH)
                                        }
         print T0, MX, RES
        }
' file

It loops through the line from regex to regex match, keeping a pointer to hold the position in original line. Hereby it counts character distance from string end to centre, or from centre to start of string, and assigns the smallest distance's string length to the result variable. For equal distance, it retains the longest length.

For patterns crossing the centre, the result is equivalent to the samples given before.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.