wxDC Problem

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

wxDC Problem

Beitragvon ete » Montag 1. September 2008, 15:45

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:
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Beitragvon CM » Dienstag 2. September 2008, 18:18

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:

Beitragvon ete » Mittwoch 3. September 2008, 11:12

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
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Beitragvon CM » Mittwoch 3. September 2008, 12:28

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

Beitragvon fhoech » Mittwoch 3. September 2008, 15:21

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:

Beitragvon ete » Donnerstag 4. September 2008, 10:03

Jep, an sowas hab ich auch gedacht.

Danke nochmal!

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder