wxDC Problem

Plattformunabhängige GUIs mit wxWidgets.
Antworten
ete
User
Beiträge: 218
Registriert: Montag 19. Februar 2007, 13:19
Kontaktdaten:

Hi!

ich habe ein Problem bei Zeichnen einer Grafik und finde den Fehler einfach nicht...

Ich möchte Pfeile under einem Stringabschnitt zeichnen. Überlappen mehrere Pfeile, so soll der nächste um 50 Positionen nach unten verschoben werden. Dies finde ich über die Farbe des Pixel der Start und Endpunkte der Pfeile heraus.

Leider funktioniert das ganze nur bedingt. Die Farbe werden korrekt gescheckt aber wenn der zweite Pfeil mit dem Ende in einen schon vorhandenen Pfeil gerät, wird die Position nicht verschoben...
Hier mal der Code (einfachhalber in das ScrolledWindow Example vom wxPython gepackt) und die nötigen Text Files:

Code: Alles auswählen

import  wx
from itertools import izip 

BUFFERED = 1    

class MyCanvas(wx.ScrolledWindow):
    def __init__(self, parent, id = -1, size = wx.DefaultSize):
        wx.ScrolledWindow.__init__(self, parent, id, (0, 0), size=size, 

style=wx.SUNKEN_BORDER)

        self.lines = []
        self.maxWidth  = 50000
        self.maxHeight = 1000
        self.x = self.y = 0
        self.curLine = []
        self.drawing = False

        self.SetBackgroundColour("WHITE") 
       
        self.SetVirtualSize((self.maxWidth, self.maxHeight))
        self.SetScrollRate(20,20)

        if BUFFERED:
            self.buffer = wx.EmptyBitmap(self.maxWidth, self.maxHeight)
            dc = wx.BufferedDC(None, self.buffer)
            dc.SetBackground(wx.Brush(self.GetBackgroundColour()))
            dc.Clear()
            self.DoDrawing(dc)
       
        self.Bind(wx.EVT_PAINT, self.OnPaint)

    def getWidth(self):
        return self.maxWidth

    def getHeight(self):
        return self.maxHeight

    def OnPaint(self, event):
        if BUFFERED:
            dc = wx.BufferedPaintDC(self, self.buffer, wx.BUFFER_VIRTUAL_AREA)
        else:
            dc = wx.PaintDC(self)
            self.PrepareDC(dc)
            self.DoDrawing(dc)
            
    def dict_laden(self, pfad):
        d ={}  
        datei = file(pfad) 
        liste = datei.readlines() 
        for eintrag in liste:
            l_eintrag = eintrag.split() 
            d[l_eintrag[0]] = l_eintrag[1]
        datei.close() 
        return d
        
    def rev_compl(self, primer):
        nucl = {'A': 'T', 'C': 'G', 'T': 'A', 'G': 'C'}
        liste = primer.split()
        letters = list(primer)
        letters.reverse() 
        letters = [nucl[base] for base in letters] 
        i = ''.join(letters) 
        return i
            
    def DoDrawing(self, dc, printing=False):
        dc.BeginDrawing()
        dc.SetBackground(wx.Brush(self.GetBackgroundColour()))
        dc.Clear()
        dc.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL, wx.NORMAL, 0, "Courier New"))
        
        # Get data and arrows 
        d = self.dict_laden('arrow.txt')
        seq = open('query_seq.txt', 'r')
        seq = seq.readlines()
        seq = str(seq)
        seq = seq.replace('[', '')
        seq = seq.replace(']', '')
        seq = seq.replace("'", '')
        seq = seq.upper()
        # draw sequence
        dc.DrawText(str(seq), 10, 10)
        # get size of character  
        text = '-'
        tw, th, space, z = dc.GetFullTextExtent(text)
        # set starting positions
        hight = 50
        arrow = 30
        zahl = 0
        # for arrows in dict
        for i in d.keys():
            zahl = zahl + 1
            # find arrow on sequence
            pos = seq.find(i)
            # if not found reverse complement the arrow
            if pos == -1:
                i = self.rev_compl(i)
                pos = seq.find(i)
            print len(i)  
            # calc length of the arrow
            length = (len(i) * tw) - space
            # calc start position of the arrow
            pos_rec = (pos * tw) + tw
            # calc end position of the arrow
            end_pos = pos_rec + length
            # Get colour before draw an arrow 
            # start position
            pixel = dc.GetPixel(pos_rec, (hight+1))
            # end position
            pixel2 = dc.GetPixel(end_pos, (hight+10))
            
            # if colour is red...
            if pixel == (255, 0, 0, 255):
                # ...increase hight >>> decrease arrow position
                hight = hight + 50
                # for the tip of the arrow
                arrow = arrow + 50
                # same for the end pixel
                if pixel2 == (255, 0, 0, 255):
                    hight = hight + 50
                    arrow = arrow + 50
       
            else:
                #...keep hight if colour is white
                hight = 50
                arrow = 30
          
            dc.SetBrush(wx.RED_BRUSH)
            dc.SetPen(wx.RED_PEN)
            # rectangle
            dc.DrawRectangle(pos_rec, hight, (length-40), 20)
            poly = [(10,10), (10,50), (10,50), (50,30), (50,30), (10,10)]
            # arrow tip
            dc.DrawPolygon(poly, (end_pos-50), arrow)
            #dc.DrawText(str(zahl), (end_pos-((length/2)+30)), (arrow+20))
            dc.DrawText(str(zahl), pos_rec, (hight+1))
            dc.EndDrawing()
            
def runTest(frame, nb, log):
    win = MyCanvas(nb)
    return win

if __name__ == '__main__':
    import sys,os
    import run
    run.main(['', os.path.basename(sys.argv[0])] + sys.argv[1:])
Und die txt Files zum testen:

query_seq.txt
ggcccctccaccccaccccacccagtcgctgcggatacttgattctgctactcggccagcgatcgatctcgcctccgccatgagcgccaccagg
ccctccttcttcccctccaacaacaacaggaacaagcccgccacccggaaccccttcgactccgactcggacgacgacggcggcatggcccggc
gcggcccggcgcgggcctcgtccgtcccgacccccgccgcggggccggccagggcctcctcggccccgatccccgccgacgaggcggaccagcg
gggcgccctgttcggcgcgggccccgcgccgtccggcttcgcgtcctcctcctccgcggccgccaggggccggtacaggaacgacttccgcgac
tcgggcggcgtggaggcgcagtccgtgcaggagctcgagggctacgcggcctacaaggccgaggagaccacgcgccgggtcgacggctgcctcc
gggtcgccgaggagatgcgggacaccgcgtcaaagaccctgctccaggtgcaccagcagggccagcagatcaggcgcacccacgccatggccgt
cgacatcgaccaggatctctccaggggggaaaagctactaggtgatcttggtggtttgttttccaagaagtggaagccaaagaagaacggcgca
atcaggggccctatgctgaccagagacgattccttcatacgcaagggcagccatatggagcagaggcataaactggggctgtcagatcgtccgc
atcgatccaatgcacgccagttcctatctgaacccacatcaggccttgagaaagtcgaggtggagaaggcaaagcaggatgatggcctgtctga
ccttagcgacatactgacagagttgaaaggaatggccattgacatgggaactgagattgaggggcaaacaaaggatcttggtcatgcggagaag
gactttgacgaacttaactacagggtcaagggggcaaacgctcgaacacgtcgcctgcttggcagataggcaagaagcatatgttgttcaccag
aggattctgtgacactccttatcttctgcatttgctttcgtgggctgttaattcagatcattttgtgcataaaactctggttaggaaggtctgt
tggggagttgtatcagggtttattgtgtatatacgctagacgggcggttcgttttctatgttgcagttgtactacatttgctatggacagtaga
tacgtttgtattcggttttcttgttttgcaatcgctatgctgcaggaaagcac

arrow.txt
GGATACTTGATTCTGCTACTCGGCCAG SNAP34-WF33
CAACTCTGTCAGTATGTCGCTAAGGTC SNAP34-PW-1R
TGAACAACATATGCTTCTTGCCTATC SNAP32-OE-R2
GTCGCTGCGGATACTTGATTCTGC SNAP34-WF25
AATGGCCATTCCTTTCAACTCTG SNAP34-PW-2R
CCACCCAGTCGCTGCGGATAC SNAP34-WF18
ATGAGCGCCACCAGGCCCTC SNAP34-WF80
CCAGCGATCGATCTCGCCTC SNAP34-WF56
CACGAAAGCAAATGCAGAAG SNAP34-OE-R
AGTCGCTGCGGATACTTGAT SNAP34-OE-F
TTGCCCCTCAATCTCAGTTC SNAP34-DET-R
GGAGCAGAGGCATAAACTGG SNAP34-DET-F
GCAGCATAGCGATTGCAAAA HO12F09_3UTR-R
TATACGCTAGACGGGCGGTT HO12F09_3UTR-F
CAAGATCCTTTGTTTGCCCC HW07G11
TAACAGCCCACGAAAGCAAA HO12F09
CCACCCCACCCCACCCAG SNAP34-WF8
CTCCGCCATGAGCGCCAC SNAP34-WF73
GGCCCCTCCACCCCACC SNAP34-WF1
GCCATGAGCGCCACCAG SNAP34-OE-F2

Wäre nett, wenn mal jemand draufschauen könnte...
Wahrscheinlich hab ich wieder Tomaten auf den Augen :shock:
http://www.snowflake-sl.info/index.html
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Hoi Stefanie,

so hast Du das also gelöst. Ich bin sicher, dass sieht sehr gut aus, nur leider bekomme ich einen Fehler meines X Window Systems, wenn ich das ausprobiere. (Vielleicht, wenn Du das ganze Programm bzw. den relevaten Teil zum Download bereitstellst? So auf den ersten Blick finde ich den Fehler nicht. Sonst wer?)

Einen Tipp allerdings würde ich allgemein schon anbringen: Das wird von Monitor zu Monitor wahrscheinlich unterschiedlich aussehen. Wäre es nicht besser die Positionierung relativ zu bewerkstelligen?

Gruß,
Christian
ete
User
Beiträge: 218
Registriert: Montag 19. Februar 2007, 13:19
Kontaktdaten:

Hi!

Ja, ich fand es die einfachste Lösung. Es werden 2 Fenster erscheinen: das untere mit einer (ungenauen) Übersicht, in dem man in ein oberes Fenster (Code unten) mit Mouse Over Event fokussieren kann.
Was bekommst du denn für ne Message? Auf meinen XP läufts.

GetPixel hat (leider, wie ich jetzt mitbekommen habe) ausserdem Platform limitations.

Kennt jemande einen anderen Weg, um rauszufinden ob auf einer Position schon "gedrawed" wurde bzw. welcher Farcode vorhanden ist?
Meinst du mit relativ z.B. die Zeichenbereiche in ne Liste und zu vergleichen?

Lg
Stefanie
http://www.snowflake-sl.info/index.html
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

ete hat geschrieben:GetPixel hat (leider, wie ich jetzt mitbekommen habe) ausserdem Platform limitations.
Das könnte der Grund sein, warum es bei mir (unter Linux) nicht klappt. Gerold?

Bzgl. Fehlermeldung: Ich bekomme halt die Fehlermeldung, dass das X Window System gerade abgestürzt ist - nicht sehr aussagekräftig. Ich vermute der Grund hierfür liegt eher daran, wie die wx-Bibliothek auf irgendetwas reagiert und nicht auf einem Fehler im Pythoncode.

Gruß,
Christian
fhoech
User
Beiträge: 143
Registriert: Montag 9. April 2007, 18:26

Ich musste den Code ins wxPython "demo"-Unterverzeichnis kopieren (hab das ursprüngliche ScrolledWindow-Demo einfach umbenannt), damit es überhaupt funktioniert (Windows XP).
Hab mal ein bisschen dran rumgebastelt. Evtl. macht der folgende Code, was du möchtest. Habe die GetPixel-Abfrage durch eine kombinierte Dictionary/List-Abfrage ersetzt (das Dictionary erhält als keys jeweils die vertikale Position der Pfeile, als Werte die von Pfeilen überlagerten Pixel in horizontaler Richtung. Dann wird einfach gegengecheckt und bei Bedarf nach unten verschoben).

Code: Alles auswählen

	def DoDrawing(self, dc, printing=False):
		dc.BeginDrawing()
		dc.SetBackground(wx.Brush(self.GetBackgroundColour()))
		dc.Clear()
		dc.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL, wx.NORMAL, 0, "Courier New"))
	   
		# Get data and arrows
		d = self.dict_laden('arrow.txt')
		seq = open('query_seq.txt', 'r')
		seq = seq.readlines()
		seq = str(seq)
		seq = seq.replace('[', '')
		seq = seq.replace(']', '')
		seq = seq.replace("'", '')
		seq = seq.upper()
		# draw sequence
		dc.DrawText(str(seq), 10, 10)
		# get size of character 
		text = '-'
		tw, th, space, z = dc.GetFullTextExtent(text)
		zahl = 0
		# stored positions
		stored_pos = {}
		# for arrows in dict
		for i in d.keys():
			zahl = zahl + 1
			# find arrow on sequence
			pos = seq.find(i)
			# if not found reverse complement the arrow
			if pos == -1:
				i = self.rev_compl(i)
				pos = seq.find(i)
			print len(i) 
			# calc length of the arrow
			length = (len(i) * tw) - space
			# calc start position of the arrow
			pos_rec = (pos * tw) + tw
			# calc end position of the arrow
			end_pos = pos_rec + length
			
			# get range covered by arrow
			arrow_range = range(pos_rec, end_pos)
			# set starting positions
			hight = 50
			arrow = 30
			# check if any of the range values are in stored_pos at the given height, if so, move down 50 px each time until free pos is found
			if stored_pos.has_key(hight):
				for j in arrow_range:
					while j in stored_pos[hight]:
						hight += 50
						arrow += 50
						if not stored_pos.has_key(hight):
							stored_pos[hight] = []
			else:
				stored_pos[hight] = []
			for j in arrow_range:
				if not j in stored_pos[hight]:
					# add positions covered by arrow to stored_pos
					stored_pos[hight] += [j]
		 
			dc.SetBrush(wx.RED_BRUSH)
			dc.SetPen(wx.RED_PEN)
			# rectangle
			dc.DrawRectangle(pos_rec, hight, (length-40), 20)
			poly = [(10,10), (10,50), (10,50), (50,30), (50,30), (10,10)]
			# arrow tip
			dc.DrawPolygon(poly, (end_pos-50), arrow)
			#dc.DrawText(str(zahl), (end_pos-((length/2)+30)), (arrow+20))
			dc.DrawText(str(zahl), pos_rec, (hight+1))
			dc.EndDrawing()
ete
User
Beiträge: 218
Registriert: Montag 19. Februar 2007, 13:19
Kontaktdaten:

Jep, an sowas hab ich auch gedacht.

Danke nochmal!
http://www.snowflake-sl.info/index.html
Antworten