This is a test version of Biostars. For the public version, visit https://www.biostars.org.
Find 4 Values In Window Size 6 That Fit Criteria -> Add To List Until 3 Do Not Fit Criteria And Do Not Include Last 3 -> Repeat Where It Left Off . Chou Fasman . Python

if you have a list of values:

values=['130','90','150','123','133','120','160','45','67','55','34','130','120','180','130','10']

and wanted to scan through with a window size of 6 and if 4 out of the 6 were >= 100 then keep scanning until there were 3 in a row that were < 100 and then not include those in the list

so for example with an empty list called results:

results=[]

i would like to append those values that satisfied the criteria into the empty list to get

results=[('130','90','150','123','133','120','160'),('55','34','130','120','180','130','10')]

i know i have convert all the strings into integers with int() but that's not the part that i'm having trouble with. i'm having trouble finding the 4 out of the window size 6 that are >= 100, adding that to a list, AND THEN going from where i left off in the window

In the Chou Fasman Algorithm each window size is 6 and if 4 are greater than 100 then all 6 are included and its extended until 4 consecutive values (i'm going to do 3 instead) are less than 100 (those 4 (or 3) are not included) and then the window starts again from that spot making a new list.

so first window would be:

['130','90','150','123','133,'120'] #and more than 4 are greater than 100 so that starting point is stored and the next window is checked
['90','150','123','133','120','160'] #again there are 4 greater than 100 so the next window is checked
['150','123','133','120','160','45'] #again
['123','133','120','160','45','67'] #again
['133','120','160','45','67','55'] #stop and assign values '130' to '160' into a list and then start the new window from where it left off

Results=[('130','90','150','123','133','120','160')]

['120','160','45','67','55','34'] # skips
['160','45','67','55','34','130'] # skips
['45','67','55','34','130','120'] # skips
['67','55','34','130','120','180'] # skips
['55','34','130','120','180','130'] # new list in Results starts with '55'
['34','130','120','180','130','10'] # sequence ends and this window still fits criteria so include these into the list so the results would now be

Results=[('130','90','150','123','133','120','160'),('55','34','130','120','180','130','10')]

I'd really like stay clear of yields and generators if possible

python windows function

For questions related to programming you should consider them posting at stackoverflow.

Can you give the question some biological relevance? I suspect there is some application, but you can see that without mentioning it our edification suffers, and the moderators get pissed off (and close your question).

Albeit not very prominently, the question does mention the Chou-Fasman method, so I don't see it as being particularly off topic.

@xenophiliuslovegood: In that case we should open a new forum to discuss programming issues related to bioinformatics. ;)

4 answers

This will do the work

start=False
results=[]
allresults=[]
for x in range(len(values)-6):
    if start or sum(int(x)>=100 for x in values[x:x+6])>4: # begin appending if window condition satified
        start=True
    if start:
        results.append(values[x])
        if sum(int(x)<100 for x in values[x+1:x+5])>=4: # break loop if next 4 are less than 100
            allresults.append(results)
            results=[]
            start=False

if start:
    allresults.append(values[x:])

print (str(allresults))

ahh almost i change value to values=['130','90','150','123','133','120','160','180','45','67','55','34','130','120','180','130','10','30'] and it should spit out results=[('130','90','150','123','133','120','160','180'),('55','34','130','120','180','130','10','30')]

because in the Chou Fasman Algorithm each window size is 6 and if 4 are greater than 100 then all 6 are included and its extended until 4 consecutive values are less than 100 and then the window starts again making a new list. thanks tho this definitely set me in the right direction i'm going to work with this . been over 6hrs

i changed the question to make it easier and more specific

Instead of the break, append the results to another list and clear the results list. This should get you all the results instead of just the first one.

Changed the program to incorporate that.

Changed the program to incorporate some of that. You could modify some of the values to get the specific results you want.

So basically you just want to remove any series of numbers that are all less than 100 and appear more than 4 times in a row?

Something like this should work:

values=['130','90','150','123','133','120','160','180','45','67','55','34','130','120']

less = []
result = []
for i in values:
    if int(i) < 100:
        less.append(i)
    else:
        if len(less) < 4:
            for j in less:
                result.append(j)
            less = []
        else:
            less = []
        result.append(i)

print result

almost . i want it to end and create a list out of the values that it found . so if it had the values values=['130','90','150','123','133','120','160','180','45','67','55','34','130','120','180','130','10','30'] it should make the results=[('130','90','150','123','133','120','160','180'),('55','34','130','120','180','130','10','30')] because in the Chou Fasman Algorithm each window size is 6 and if 4 are greater than 100 then all 6 are included and its extended until 4 consecutive values are less than 100 and then the window starts again making a new list. thanks tho this definitely set m

i changed the question to make it easier and more specific

It's not clear to my why your second tuple in all-results include that final '10' as that seems to go against your description. I have implemented a solution using generators ('cause that's the easiest way), but the interface returns a list. The parameters are adjustable, so you can change the various cutoffs.

def _chou_fasman(values, window_size, cutoff, n_above, n_below):
    i = -1
    while i < len(values) - window_size:
        i += 1
        current = values[i: i + window_size]
        if sum(1 for c in current if c > cutoff) < n_above: continue
        j = i + window_size + n_below
        while sum(1 for v in values[i + window_size: j] if v < cutoff) < n_below and j < len(values):
            j += 1
        last_index = j - n_below # you may need to change this, it's not clear from you example.
        yield values[i:min(len(values), last_index)]
        i = last_index

def chou_fasman(values, window_size=6, cutoff=100, n_above=4, n_below=3):
    return list(_chou_fasman(values, window_size, cutoff, n_above, n_below))

if __name__ == "__main__":
    values = map(int, ['130','90','150','123','133','120','160','45','67',
                       '55','34','130','120','180','130','10'])
    print "\n".join(map(str, chou_fasman(values)))

where you'll call chou_fasman so as not to have to deal with generators.

there is a typo in his example solution. It should not be ('55','34','120','180','130','10') rather [55, 34, 130, 120, 180, 130, 10] (a 130 is missing from his list).

why is there a 10 on the end?

@ xenophiliuslovegood : i fixed the typo you were right @brentp : the 10 is on the end b/c the last window of size 6 includes the 10 and that window still has at least 4 values greater than 100 so the last window is accepted in the algorithm

As far as I understand this does what you want, produces the correct answers when fed with all the examples you provided (except I think there's a typo in one of your example solutions), certainly does not use generators.

def build_choufasman_regions(l):
    le=len(l)
    tmp=[];res=[]
    pos=0
    while (pos<= (le-6) ):
        c=0;
        for i in range(pos,pos+6):
            if (l[i]>=100): c=c+1
        if c>=4:
            if ([]==tmp):
                tmp.extend(l[pos:pos+6])
            else:
                tmp.extend([l[pos+5]])
        else:
            if ([]==tmp): pass
            else:
                if (tmp[-1]<100 and tmp[-2]<100):
                    tmp.pop(-1);tmp.pop(-1);pos=pos+3
                res.append(tmp)
                tmp=[]
        #print pos,tmp
        pos=pos+1
    if ([]!=tmp):res.append(tmp) 
    return res

l=[130,90,150,123,133,120,160,45,67,55,34,130,120,180,130,10]   
print build_choufasman_regions(l)
l=[130,90,150,123,133,120,160,180,45,67,55,34,130,120,180,130,10,30]
print build_choufasman_regions(l)
l=[1,1,1,200,200,200,100,100,50,100]
print build_choufasman_regions(l)

I fixed the formatting of the code, indentation had come out wrong while copy/pasting.

Log in to answer this question.