[Debian-med-packaging] Bug#767145: That long-standing nasty Tcl/Tk-bug with autodocktools Re: Bitte weiterleiten (Re: [Pkg-tcltk-devel] Tcl/Tk help needed (Was: Bug#767145: autodocktools: fails to start the GUI))

Michel Sanner sanner at scripps.edu
Wed Feb 10 17:31:47 UTC 2016


Hello

On 02/09/2016 11:35 PM, Andreas Tille wrote:
> Hi Michel,
>
> thanks for the attempt to help.  To answer your question from the other
> mail: In Debian we need to build from source and build against the
> current development tools - thus the usage of higher Tcl/Tk version.
> (Just a personal remark: I think there are better GUI tools available
> for Python than Tcl/Tk - but that's just a side note and I have not
> investigated how much work droping Tcl/Tk might create).
We actually stopped all TK-based developments and have started writing
the next generation tools based on Qt. These tools will be much more 
user friendly
up to date and efficient, but unfortunately they do not yet provide the 
level
of functionality and stability needed to replace the existing AutoDockTools.
>
> Regarding your attached file:  I tried to test it but I realised that we
> are running into another issue first:
>
> $ autodocktools
> Run ADT from  /usr/lib/python2.7/dist-packages/AutoDockTools
> Traceback (most recent call last):
>    File "/usr/lib/python2.7/dist-packages/AutoDockTools/__init__.py", line 420, in runADT
>      from mglutil.splashregister.splashscreen import SplashScreen
>    File "/usr/lib/python2.7/dist-packages/mglutil/splashregister/splashscreen.py", line 7, in <module>
>      from mglutil.util.misc import ensureFontCase
>    File "/usr/lib/python2.7/dist-packages/mglutil/util/misc.py", line 19, in <module>
>      import numpy.oldnumeric as Numeric
> ImportError: No module named oldnumeric
> hit enter to continue
This is the very reason we gave up on trying to use system wide packages 
and bundle up a self-consistent
Python interpreter, python packages and libraries. Some third party 
packages we have been using sometime
require a specific version of a python package and we have no choice 
other than using this specific version.
IHMO this is bound to happen when you integrate a large number of 
software packages and you do not have control
over all of them.

For the new generation of our tools we already got rid of all Numeric 
references but this was not done for AutoDockTools
which is out-of-date and not easy to maintain. However it has a large 
user base and the Tk version still is, as of today,
the official stable version. So I will put one of my programmers on the 
project to update AutoDockTools to use numpy.

I hope this is the only instance left where we run into this kind of 
problems

-Michel
>
>
> I think the following files are affected by this issue:
>
> $ grep -Rw oldnumeric | grep -v '#.*oldnumeric'
> AutoDockTools/AutoDockBondClassifier.py:    import numpy.oldnumeric as Numeric, math
> AutoDockTools/autogpfCommands.py:import numpy.oldnumeric as Numeric
> AutoDockTools/autogpfCommands.py:import numpy.oldnumeric as Numeric
> AutoDockTools/histogram.py:import numpy.oldnumeric as Numeric; N = Numeric
> AutoDockTools/Conformation.py:import numpy.oldnumeric as Numeric
> AutoDockTools/pixelMap2D.py:import Image, numpy.oldnumeric as Numeric
> AutoDockTools/pixelMap2D.py:    import numpy.oldnumeric as Numeric
> AutoDockTools/Tests/test_PyAutoDock.py:import numpy.oldnumeric as Numeric
> AutoDockTools/Utilities24/prepare_dpf42.py:from numpy import oldnumeric as Numeric
> AutoDockTools/Utilities24/compute_interatomic_distance_per_vina_pose.py:import numpy.oldnumeric as Numeric
> AutoDockTools/Utilities24/summarize_docking_directory.py:import numpy.oldnumeric as Numeric
> AutoDockTools/Utilities24/prepare_covalent_flexres.py:    import numpy.oldnumeric as Numeric
> AutoDockTools/Utilities24/rotate_molecule.py:import numpy.oldnumeric as Numeric
> AutoDockTools/Utilities24/summarize_epdb_results4.py:from numpy import oldnumeric as Numeric
> AutoDockTools/Utilities24/summarize_wcg_docking.py:import os, glob, numpy.oldnumeric as Numeric
> AutoDockTools/Utilities24/compute_rms_between_methods.py:import numpy.oldnumeric as Numeric
> AutoDockTools/Utilities24/write_clustering_histogram_postscript.py:import os, glob, Tkinter, numpy.oldnumeric as Numeric
> AutoDockTools/Utilities24/compute_consensus_maps_from_dlgs.py:import os, glob, numpy.oldnumeric as Numeric, math
> AutoDockTools/Utilities24/score_atoms_by_component.py:from numpy import oldnumeric as Numeric
> AutoDockTools/Utilities24/compute_rms_between_conformations.py:import numpy.oldnumeric as Numeric
> AutoDockTools/Utilities24/summarize_results_vif.py:from numpy import oldnumeric as Numeric
> AutoDockTools/Utilities24/compute_interatomic_distance_per_pose.py:import numpy.oldnumeric as Numeric
> AutoDockTools/Utilities24/summarize_time.py:import os, glob, numpy.oldnumeric as Numeric
> AutoDockTools/AutoLigand.py:    from numpy.oldnumeric import zeros
> AutoDockTools/autoanalyzeCommands.py:import numpy.oldnumeric as Numeric, math
> AutoDockTools/autodpfCommands.py:import os, numpy.oldnumeric as Numeric
> AutoDockTools/DlgParser.py:import numpy.oldnumeric as Numeric
> AutoDockTools/autoflexCommands.py:import numpy.oldnumeric as Numeric
> AutoDockTools/autotorsCommands.py:import numpy.oldnumeric as Numeric
> AutoDockTools/DlgFilters.py:from numpy import oldnumeric as Numeric
> AutoDockTools/cluster.py:import numpy.oldnumeric as Numeric
> AutoDockTools/pyAutoDockCommands.py:import Tkinter, numpy.oldnumeric as Numeric, Pmw
> AutoDockTools/GridParameters.py:import numpy.oldnumeric as Numeric
> AutoDockTools/ConfPlayer.py:import numpy.oldnumeric as Numeric
> AutoDockTools/InteractionDetector.py:from numpy import oldnumeric as Numeric
> AutoDockTools/InteractionDetector.py:import numpy.oldnumeric as Numeric
> AutoDockTools/LigandMixin.py:import numpy.oldnumeric as Numeric, math, types, os
> AutoDockTools/cluster_ad.py:import numpy.oldnumeric as Numeric
> AutoDockTools/energyCalculator.py:import numpy.oldnumeric as Numeric
> AutoDockTools/MoleculePreparation.py:import numpy.oldnumeric as Numeric, math
>
>
> As far as I dived into a websearch the needed replacements are not
> really complex but I would consider it more sensible if you do it
> right on your side to be prepared for latest numpy.
>
> Kind regards
>
>        Andreas.
>
> On Tue, Feb 09, 2016 at 04:23:36PM -0800, Michel Sanner wrote:
>> Steffen
>>
>>
>> could you please check is replacing the file
>> mglutil/gui/BasicWidgets/Tk/vector3DGUI.py with the one attached solves the
>> problem ?
>>
>> Thanks
>>
>> On 12/29/2015 05:00 PM, Steffen Möller wrote:
>>> Hello Michel, hello Stefano,
>>>
>>> nice to hear from you, indeed. I happen to be a recent El Capitan user
>>> myself and thus
>>> can help testing on that front, too.
>>>
>>> I was not aware of a release of 1.5.7, which I had seen only as a RC1,
>>> using the
>>> information shown on
>>> http://mgltools.scripps.edu/downloads
>>> The problem should manifest itself on any platform with TclTk 8.6 onwards.
>>> Until a few seconds ago I had truly thought that you were working on
>>> something
>>> completely different already that would be released once it is ready and as
>>> such you did not notice/care about that "works with 8.5" problem.
>>>
>>> How shall we proceed? I propose that we get the code base and tools in sync
>>> and I prepare an update of the Debian packages. Is the CVS repository of
>>> yours
>>> still the place where to look? What version of TclTk do you work with?
>>> Just instruct me.
>>>
>>> Concerning the time line I am swamped till mid January. We have our next
>>> Debian meeting in Copenhagen on the first February weekend. Would be nice to
>>> have the bug fixed till then.
>>>
>>> Best,
>>>
>>> Steffen
>>>
>>>
>>> On 29/12/15 21:29, Andreas Tille wrote:
>>>> Hi Michel,
>>>>
>>>> As far as I know installing Tcl/Tk 8.6 you should be able to reproduce
>>>> the problem.  The best resource of information is probably
>>>>
>>>>      https://lists.alioth.debian.org/pipermail/pkg-tcltk-devel/2015-December/002938.html
>>>>
>>>> Hope this helps
>>>>
>>>>         Andreas.
>>>>
>>>> On Tue, Dec 29, 2015 at 11:20:20AM -0800, Michel Sanner wrote:
>>>>> Happy Holidays all
>>>>>
>>>>> I am not aware of this bug. Could you please let me know how to reproduce it
>>>>> ? and of course
>>>>> if you have a patch I'll be happy to incorporate it. We are working on a bug
>>>>> fix release of MGLTools 1.5.7
>>>>>
>>>>> This release has been postponed a little as we are trying to address some
>>>>> issues with the newest Mac OS
>>>>> El Capitan. This delay will hopefully gives us time to incorporate a bug fix
>>>>> for this problem as well
>>>>>
>>>>> -Michel
>>>>>
>>>>> On 12/29/15 10:22 AM, Stefano Forli wrote:
>>>>>> Hi Steffen (and Andreas),
>>>>>> I hope you're having happy Holidays yourselves. I'm currently in Italy enjoying some time with family.
>>>>>> No worries about bothering, you're all doing us a huge favor, so we're always in debt.
>>>>>>
>>>>>> I'm CC'ing Michel in the conversation, since he's in charge of the source code.
>>>>>> I got bit by these issues with Tcl with the old Raccoon version you packaged, but I wasn't aware of the problems with the main package AutoDockTools.
>>>>>> If you think it is something that can be solved with a reasonable amount of patches, I believe there's no problem in adding them to our CVS (but I'll let Michel chip in about this).
>>>>>>
>>>>>> I'll be happy to test the patched code, if you have any.
>>>>>>
>>>>>> Thanks!
>>>>>>
>>>>>> S
>>>>>>
>>>>>>
>>>>>> --
>>>>>>
>>>>>>   Stefano Forli, PhD
>>>>>>
>>>>>>   Assistant Professor of Integrative
>>>>>>   Structural and Computational Biology,
>>>>>>   Molecular Graphics Laboratory
>>>>>>
>>>>>>   Dept. of Integrative Structural
>>>>>>    and Computational Biology, MB-112F
>>>>>>   The Scripps Research Institute
>>>>>>   10550  North Torrey Pines Road
>>>>>>   La Jolla,  CA 92037-1000,  USA.
>>>>>>
>>>>>>      tel: +1 (858)784-2055
>>>>>>      fax: +1 (858)784-2860
>>>>>>      email: forli at scripps.edu
>>>>>>      http://www.scripps.edu/~forli/
>>>>>> ________________________________________
>>>>>> From: Steffen Möller [steffen_moeller at gmx.de]
>>>>>> Sent: Tuesday, December 29, 2015 12:55 AM
>>>>>> To: Andreas Tille; Stefano Forli
>>>>>> Subject: That long-standing nasty Tcl/Tk-bug with autodocktools Re: Bitte weiterleiten (Re: [Pkg-tcltk-devel] Tcl/Tk help needed (Was: Bug#767145: autodocktools: fails to start the GUI))
>>>>>>
>>>>>> Hi Stefano,
>>>>>>
>>>>>> some merry Christmas I hope you had and all the best for the New Year,
>>>>>> of course. The inter-annual time (as we say over here) is most likely
>>>>>> the most productive in the Open Source world :) Please forgive me
>>>>>> contacting you during all these festivities.
>>>>>>
>>>>>> I admit to know about this Tcl bug for some time, and I had even kind of
>>>>>> traced it down: the autodocktools do not pack their widgets right, i.e.
>>>>>> they are missing absolute and relative positions. Later versions than
>>>>>> 8.5 are apparently no longer tolerating it, and 8.6 is no longer any
>>>>>> recent version, I am afraid. Andreas is about to remove the package from
>>>>>> the distro as it is unusable as it is.
>>>>>>
>>>>>> How are your feelings about it all? Would you accept patches? Is there
>>>>>> something in your CVS that we should address, instead?
>>>>>>
>>>>>> All the best possible wishes
>>>>>>
>>>>>> Steffen
>>>>>>
>>>>>> On 29/12/15 08:40, Andreas Tille wrote:
>>>>>>> Hi Steffen,
>>>>>>>
>>>>>>> kannst Du das bitte mal an die Autoren weiterleiten (und den Bug in CC
>>>>>>> setzen).  Ansonsten lasse ich das Paket entfernen, weil es ja
>>>>>>> offensichtlich zu nichts nütze ist, wenn es nicht mal startet.
>>>>>>>
>>>>>>> Viele Grüße
>>>>>>>
>>>>>>>          Andreas.
>>>>>>>
>>>>>>> ----- Forwarded message from Sergei Golovan <sgolovan at nes.ru> -----
>>>>>>>
>>>>>>> Date: Thu, 24 Dec 2015 10:52:27 +0300
>>>>>>> From: Sergei Golovan <sgolovan at nes.ru>
>>>>>>> To: Andreas Tille <andreas at an3as.eu>
>>>>>>> Cc: Senthil Kumaran <stylesen at gmail.com>, 767145 at bugs.debian.org, Tcl/Tk Debian Packagers <pkg-tcltk-devel at lists.alioth.debian.org>
>>>>>>> Subject: Re: [Pkg-tcltk-devel] Tcl/Tk help needed (Was: Bug#767145: autodocktools: fails to start the GUI)
>>>>>>>
>>>>>>> Hi Andreas,
>>>>>>>
>>>>>>> On Wed, Dec 23, 2015 at 11:42 PM, Andreas Tille <andreas at an3as.eu> wrote:
>>>>>>>> Hi Tcl/Tk packaging team,
>>>>>>>>
>>>>>>>> unfortunately I got no help on debian-mentors and since we somehow need
>>>>>>>> to tackle bug  #767144 I wonder if you Tcl/Tk experts might be able to
>>>>>>>> provide some help.
>>>>>>> As far as I can see, you've stumbled on the change between Tcl/Tk 8.5
>>>>>>> and 8.6. In Tcl/Tk 8.5 one could mix grid and pack geometry managers
>>>>>>> in one master window. It often works but sometimes leads to
>>>>>>> unpredictable results, sometimes an application which does that just
>>>>>>> hangs. In Tcl/Tk 8.6 this mixing of grid and pack was explicitly
>>>>>>> forbidden, hence this error message.
>>>>>>>
>>>>>>> I don't think that there is an easy way to fix this. You can't just
>>>>>>> revert to using Tcl/Tk 8.5 because Tkinter in Debian is already
>>>>>>> switched to Tk 8.6 (and I guess using custom Tkinter is not an
>>>>>>> option). So, one has to carefully find all mixed up packs and grids
>>>>>>> and make sure that only one of them is used in every particular master
>>>>>>> window. In plain Tcl/Tk I'd override the [pack] and [grid] routines to
>>>>>>> print some debug information (something like
>>>>>>>
>>>>>>> rename pack pack:orig
>>>>>>> proc pack {args} {
>>>>>>>      puts stderr "pack: [info level -1] $args"
>>>>>>>      pack:orig {*}$args
>>>>>>> }
>>>>>>>
>>>>>>> and similar for grid). This would help to trace where exactly the
>>>>>>> mixed geometry master windows appear. I don't know how you can do
>>>>>>> something similar in Python, but I'm pretty sure it's possible.
>>>>>>>
>>>>>>> Cheers!
>>>>> -- 
>>>>>
>>>>> -----------------------------------------------------------------------
>>>>>     o
>>>>>    /   Michel F. Sanner Ph.D.            The Scripps Research Institute
>>>>> o     Associate Professor               Department of Molecular Biology
>>>>>    \                                     10550 North Torrey Pines Road
>>>>>     o  Tel. (858) 784-7742               La Jolla, CA 92037, TPC 26
>>>>>    /   Fax. (858) 784-2341
>>>>> o     sanner at scripps.edu                http://www.scripps.edu/~sanner
>>>>> -----------------------------------------------------------------------
>>>>>
>>>>>
>> -- 
>>
>> -----------------------------------------------------------------------
>>     o
>>    /    Michel F. Sanner Ph.D.            The Scripps Research Institute
>> o      Associate Professor               Department of Molecular Biology
>>    \                                      10550 North Torrey Pines Road
>>     o   Tel. (858) 784-7742               La Jolla, CA 92037, TPC 26
>>    /    Fax. (858) 784-2341
>> o      sanner at scripps.edu                http://www.scripps.edu/~sanner
>> -----------------------------------------------------------------------
>>
>> ## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by
>>
>> #########################################################################
>> #
>> # Date: Nov 2001 Authors: Michel Sanner, Daniel Stoffler
>> #
>> #    sanner at scripps.edu
>> #    stoffler at scripps.edu
>> #
>> # Copyright: Michel Sanner, Daniel Stoffler and TSRI
>> #
>> #########################################################################
>>
>> import Tkinter, numpy.oldnumeric as Numeric, string, math
>>      
>> from mglutil.math.rotax import rotax
>> from mglutil.gui.Misc.Tk.KeybdModMonitor import KeyboardModifierMonitor
>> from mglutil.util.callback import CallbackManager
>> from thumbwheel import ThumbWheel
>> from optionsPanel import VectorOptionsPanel
>>
>> class vectorGUI(Tkinter.Frame, KeyboardModifierMonitor):
>>
>>      """ This class implements a vector widget.
>>      The widget has a vector which can be moved within a sphere to generate
>>      a 3D vector. Values are normalized and stored in self.vector
>>      In addition, the vector can be rotated with 3 thumbwheels.
>>      Values can be entered directly by typing them into the 3 entry forms.
>>      Then, the 'normalize and set' button has to be pressed in order to
>>      normalize and set the new vector.
>>
>>      The widget has a configure() method: vector, mode, precision and
>>      continuous can be set this way.
>>      vector is a list of 3 floating values, e.g. [0., 0., 1.]
>>      mode describes the axis movement (rotation around an axis): is type
>>      string and can be either 'X', 'Y' or 'Z'. Free movement (standard
>>      value) is 'XY'.
>>      continuous can be either 0 (or None) or 1. Default is 0
>>      precision is type int and ranges from 1 - 10
>>      master, name and size can be passed only to the constructor.
>>
>>      a lock() method is used to disable the various gui components of the
>>      options panel. Usage: <instance>.lock(<component>=<value>)
>>      component is continuous, precision or mode. value is 0 or 1. 1 disables,
>>      0 enables.
>>      """
>>      def __init__(self, master=None, name='vector', size=200, continuous = 1,
>>                   vector=[0.0, 0.0, 1.0], mode='XY', precision=5,
>>                   lockContinuous=0,  lockPrecision=0, lockMode=0,
>>                   callback=None, labelSide='top'):
>>          
>> 	KeyboardModifierMonitor.__init__(self)
>>
>>          self.callback = callback # user specified callback
>>          self.name=name             # title inside canvas
>>          self.labelSide=labelSide   # where title gets packed
>> 	self.mode=mode             # axe mode: can be 'XY', 'X', 'Y' or 'Z'
>>          self.precision=precision   # floating number digits
>>          self.continuous=continuous # can be 1 or 0
>>          self.vector=vector         # initial vector value
>>          self.size=size             # size of vector widget
>>
>>          self.lockContinuous = lockContinuous  # set to 1 to lock menus in
>>                                                # option panel
>>          self.lockPrecision = lockPrecision
>>          self.lockMode = lockMode
>>
>>          self.r = self.size/2
>>          self.r2 = self.r*self.r
>>
>>          self.drawShadowX = 0
>>          self.drawShadowY = 1
>>          self.drawShadowZ = 0
>> 	self.fillShadowPlanes = 1
>>
>> 	Tkinter.Frame.__init__(self, master)
>>          Tkinter.Pack.config(self)
>>
>>          self.callbacks = CallbackManager() # object to manage callback
>>                                          # functions. They get called with the
>>                                          # current value as an argument
>>          self.zeros = Numeric.array( (0,0,0), 's')
>>          self.viewingMatInv = Numeric.array(
>>              [[  0.96770716, -0.03229283, -0.25      ,  0.        ],
>>               [  0.03229283, -0.96770716,  0.25      ,  0.        ],
>>               [  0.25      ,  0.25      ,  0.93541437,  0.        ],
>>               [  0.        ,  0.        ,  0.        ,  1.        ]],'f')
>>          self.viewingMat = Numeric.transpose(self.viewingMatInv)
>>          self.createCanvas(master, size)
>>          self.createEntries(self.frame)
>> 	Tkinter.Widget.bind(self.canvas, "<ButtonPress-1>", self.mouseDown)
>> 	Tkinter.Widget.bind(self.canvas, "<ButtonRelease-1>", self.mouseUp)
>> 	Tkinter.Widget.bind(self.canvas, "<B1-Motion>", self.mouseMove)
>>
>>          self.setEntries()
>>
>>          self.opPanel = VectorOptionsPanel(master = self,
>>                                            title="Vector GUI Options")
>>          Tkinter.Widget.bind(self.canvas, "<Button-3>", self.toggleOptPanel)
>>
>>          if self.callback:
>>              self.callbacks.AddCallback(self.callback)
>>
>>
>>      def toggleOptPanel(self, event=None):
>>          # opens and closes options panel by right clicking on widget
>>          if self.opPanel.flag:
>>             self.opPanel.Dismiss_cb()
>>          else:
>>              if not hasattr(self.opPanel, 'optionsForm'):
>>                  self.opPanel.displayPanel(create=1)
>>              else:
>>                  self.opPanel.displayPanel(create=0)
>>                  
>>
>>      def mouseUp(self, event):
>>          if not self.continuous:
>>              self.callbacks.CallCallbacks(self.vector)
>>
>> 	
>>      def mouseDown(self, event):
>> 	# remember where the mouse went down
>>          xc = event.x - self.xm
>>          yc = self.ym - event.y
>>          # compute the intersection point between
>>          z2 = self.r2-(xc*xc)-(yc*yc)
>>
>>          if z2>=0: # we picked inside the sphere. going for a XY rotation
>>              self.lastPt3D = (xc, yc, math.sqrt(z2))
>>          else: # going for a Z rotation
>>              pass
>>
>>
>>      def mouseMove(self, event):
>>          # simple trackball, only works inside cirle
>>          # creates an XY rotation defined by pts intersecting the spheres
>>          xc = event.x - self.xm
>>          yc = self.ym - event.y
>>          # compute the intersection point between
>>          xc2 = xc*xc
>>          yc2 = yc*yc
>>          z2 = self.r2-xc2-yc2
>>
>>          if z2 < 0:
>>              lInvMag = 1./math.sqrt(xc2 + yc2)
>>              xc *= lInvMag * (self.r)
>>              yc *= lInvMag * (self.r)
>>              z2 = 0
>>
>>          # compute rotation angle
>> 	a = self.lastPt3D
>> 	b = (xc, yc, math.sqrt(z2))
>>          ang = math.acos((a[0]*b[0]+a[1]*b[1]+a[2]*b[2])/self.r2)
>>          if self.mode=='XY':
>> 	    #compute rotation axis
>>              rotaxis = Numeric.array( (a[1]*b[2] - a[2]*b[1],
>> 				  a[2]*b[0] - a[0]*b[2],
>> 				  a[0]*b[1] - a[1]*b[0] ), 'f' )
>>          elif self.mode=='X': rotaxis = Numeric.array( (1.,0.,0.), 'f')
>>          elif self.mode=='Y': rotaxis = Numeric.array( (0.,1.,0.), 'f')
>>          elif self.mode=='Z': rotaxis = Numeric.array( (0.,0.,1.), 'f')
>>          mat = rotax( self.zeros, rotaxis, ang )
>>          self.lastPt3D = b
>>          self.updateVector(mat)
>>
>>
>>      def updateVector(self, mat):
>>          mat = Numeric.reshape(mat, (4,4))
>>          newPts = self.vector + [1]
>>          newPts = Numeric.dot( [newPts], mat )[0]
>>          self.vector = [newPts[0], newPts[1], newPts[2]]
>>          self.setEntries()
>>          self.drawVector()
>>          if self.continuous:
>>              self.callbacks.CallCallbacks(self.vector)
>>              
>>          
>>      def drawVector(self):
>>          coords3D = self.vector + [1]
>> 	# apply viewing transformation to vector
>>          newPtsWithView = Numeric.dot( [coords3D],
>>                                                   self.viewingMat)[0]
>> 	# compute 2D projection of vector (broken on 2 segments for
>> 	# depth cueing
>>          x1 = self.xm+int(newPtsWithView[0]*(self.xm))
>>          y1 = self.ym+int(newPtsWithView[1]*(self.ym))
>>
>> 	# change vector's segments coordinates
>>          self.canvas.coords(self.lId1, self.xm, self.ym, x1, y1)
>>
>> 	# update vector shadows
>> 	# Y=0 plane
>> 	if self.drawShadowY:
>> 	    pt = [coords3D[0], 0, coords3D[2], 1.]
>> 	    newPtsWithView = Numeric.dot( [pt], self.viewingMat)[0]
>> 	    xm = self.xm+int(newPtsWithView[0]*(self.xm))
>> 	    ym = self.ym+int(newPtsWithView[1]*(self.ym))
>> 	    if self.fillShadowPlanes:
>> 		self.canvas.coords(self.shadowPY,self.xm,self.ym,xm,ym,x1,y1)
>> 	    self.canvas.coords(self.shadowY,self.xm,self.ym,xm,ym,x1,y1)
>>
>> 	# X=0 plane
>> 	if self.drawShadowX:
>> 	    pt = [0, coords3D[1], coords3D[2], 1.]
>> 	    newPtsWithView = Numeric.dot( [pt], self.viewingMat)[0]
>> 	    xm = self.xm+int(newPtsWithView[0]*(self.xm))
>> 	    ym = self.ym+int(newPtsWithView[1]*(self.ym))
>> 	    if self.fillShadowPlanes:
>> 		self.canvas.coords(self.shadowPX,self.xm,self.ym,xm,ym,x1,y1)
>> 	    self.canvas.coords(self.shadowX, self.xm, self.ym, xm, ym, x1,y1)
>>
>> 	# Z=0 plane
>> 	if self.drawShadowZ:
>> 	    pt = [coords3D[0], coords3D[1], 0, 1.]
>> 	    newPtsWithView = Numeric.dot( [pt], self.viewingMat)[0]
>> 	    xm = self.xm+int(newPtsWithView[0]*(self.xm))
>> 	    ym = self.ym+int(newPtsWithView[1]*(self.ym))
>> 	    if self.fillShadowPlanes:
>> 		self.canvas.coords(self.shadowPZ,self.xm,self.ym,xm,ym,x1,y1)
>> 	    self.canvas.coords(self.shadowZ, self.xm, self.ym, xm, ym, x1,y1)
>>
>> 	if self.vector[0]<0.0:
>> 	    self.canvas.tag_raise('verticalCircle', 'moving')
>> 	else:
>> 	    self.canvas.tag_lower('verticalCircle', 'moving')
>>
>> 	if self.vector[1]<0.0:
>> 	    self.canvas.tag_raise('horizontalCircle', 'moving')
>> 	else:
>> 	    self.canvas.tag_lower('horizontalCircle', 'moving')
>>
>> 	if self.vector[2]<0.0 or self.vector[1]<0.0:
>> 	    self.canvas.tag_raise('axis', 'moving')
>> 	else:
>> 	    self.canvas.tag_lower('axis', 'moving')
>>
>>
>>      def thumbx_cb(self, events=None):
>>          val=self.thumbx.value
>>
>> ##          valX=self.thumbx.value
>> ##          valY=self.thumby.value
>> ##          valZ=self.thumbz.value
>>
>> ##          n = math.sqrt(valX*valX+valY*valY+valZ*valZ)
>> ##          if n == 0.0: v = [0.0, 0.0, 1.0]
>> ##          else: v = [valX/n, valY/n, valZ/n]
>> ##          val = v[0]
>>
>> 	rot = Numeric.zeros( (4,4), 'f' )
>>          rot[0][0] = 1.0
>>          rot[1][1] = math.cos(val)
>>          rot[1][2] = -math.sin(val)
>>          rot[2][1] = math.sin(val)
>>          rot[2][2] = math.cos(val)
>>          self.updateVector(rot)
>>
>>      def thumby_cb(self, events=None):
>>          val=self.thumby.value
>> 	rot = Numeric.zeros( (4,4), 'f' )
>>          rot[0][0] = math.cos(val)
>>          rot[0][2] = -math.sin(val)
>>          rot[1][1] = 1.0
>>          rot[2][0] = math.sin(val)
>>          rot[2][2] = math.cos(val)
>>          self.updateVector(rot)
>>
>>
>>      def thumbz_cb(self, events=None):
>>          val=self.thumbz.value
>> 	rot = Numeric.zeros( (4,4), 'f' )
>>          rot[0][0] = math.cos(val)
>>          rot[0][1] = -math.sin(val)
>>          rot[1][0] = math.sin(val)
>>          rot[1][1] = math.cos(val)
>>          rot[2][2] = 1.0
>>          self.updateVector(rot)
>>
>>
>>      def entryX_cb(self, event=None):
>>          val = self.entryXTk.get()
>>          if len(val) == 0: val = self.vector[0]
>>          try:
>>              val = float(val)
>>              self.entryXTk.set(self.thumbx.labelFormat%val)
>>          except ValueError:
>>              # put back original value if someone types garbage
>>              self.entryXTk.set(self.thumbx.labelFormat%self.vector[0])
>>
>>
>>      def entryY_cb(self, event=None):
>>          val = self.entryYTk.get()
>>          if len(val) == 0: val = self.vector[1]
>>          try:
>>              val = float(val)
>>              self.entryYTk.set(self.thumby.labelFormat%val)
>>          except ValueError:
>>              # put back original value if someone types garbage
>>              self.entryYTk.set(self.thumby.labelFormat%self.vector[1])
>>
>>
>>      def entryZ_cb(self, event=None):
>>          val = self.entryZTk.get()
>>          if len(val) == 0: val = self.vector[2]
>>          try:
>>              val = float(val)
>>              self.entryZTk.set(self.thumbz.labelFormat%val)
>>          except ValueError:
>>              # put back original value if someone types garbage
>>              self.entryZTk.set(self.thumbz.labelFormat%self.vector[2])
>>
>>
>>      def entryV_cb(self, event=None):
>>          v = self.entryVTk.get()
>>          try: val = string.split(v)
>>          except:
>>              self.setEntries()
>>              return
>>
>>          if val is None or len(val)!= 3:
>>              self.setEntries()
>>              return
>>
>>          try:
>>              valX = float(val[0])
>>              valY = float(val[1])
>>              valZ = float(val[2])
>>          except:
>>              self.setEntries()
>>              return
>>
>>          # compute normalized vector
>>          n = math.sqrt(valX*valX+valY*valY+valZ*valZ)
>>          if n == 0.0: v = [0.0, 0.0, 1.0]
>>          else: v = [valX/n, valY/n, valZ/n]
>>          self.vector = v
>>          self.setEntries()
>>          self.drawVector()
>>          if self.continuous:
>>              self.callbacks.CallCallbacks(self.vector)
>>
>>      def setButton_cb(self, event=None):
>>          valX = float(self.entryXTk.get())
>>          valY = float(self.entryYTk.get())
>>          valZ = float(self.entryZTk.get())
>>
>>          # compute normalized vector
>>          n = math.sqrt(valX*valX+valY*valY+valZ*valZ)
>>          if n == 0.0: v = [0.0, 0.0, 1.0]
>>          else: v = [valX/n, valY/n, valZ/n]
>>          self.vector = v
>>          self.setEntries()
>>          self.drawVector()
>>          if self.continuous:
>>              self.callbacks.CallCallbacks(self.vector)
>>          
>>
>>      def createEntries(self, master):
>>          self.f = Tkinter.Frame(master)
>> 	#self.f.grid(column=3, rowspan=3)
>>          
>>          def fX(): self.vector = [1.,0.,0.]; self.setEntries(); self.callbacks.CallCallbacks(self.vector)
>>          def fY(): self.vector = [0.,1.,0.]; self.setEntries(); self.callbacks.CallCallbacks(self.vector)
>>          def fZ(): self.vector = [0.,0.,1.]; self.setEntries(); self.callbacks.CallCallbacks(self.vector)
>>          f1 = Tkinter.Frame(master)
>>          f2 = Tkinter.Frame(master)
>>          f3 = Tkinter.Frame(master)
>>          f1.pack(side='top')
>>          f2.pack(side='top')
>>          f3.pack(side='top')
>>          lX = Tkinter.Button(master=f1, text='x', command=fX)
>>          lX.pack(side='left')
>>          lY = Tkinter.Button(master=f2, text='y', command=fY)
>>          lY.pack(side='left')
>>          lZ = Tkinter.Button(master=f3, text='z', command=fZ)
>>          lZ.pack(side='left')
>>          
>>          #lX = Tkinter.Button(master=self.f, text='x', command=fX)
>>          #lY = Tkinter.Button(master=self.f, text='y', command=fY)
>>          #lZ = Tkinter.Button(master=self.f, text='z', command=fZ)
>>          #lX.grid(row=0, column=0)
>>          #lY.grid(row=1, column=0)
>>          #lZ.grid(row=2, column=0)
>>
>>          #self.thumbx = ThumbWheel(master=self.f, width=50,
>>          self.thumbx = ThumbWheel(master=f1, width=50,
>>                                   height=20, labcfg={'text':'X:','side':'left'},
>>                                   wheelPad=2, oneTurn=.1, min=-1, max=1,
>>                                   showLabel=0, precision=5, type=float)
>>          self.thumbx.callbacks.AddCallback(self.thumbx_cb)
>>          self.thumbx.unbind("<Button-3>")
>>          self.thumbx.canvas.unbind("<Button-3>")
>>          #self.thumbx.grid(row=0, column=1)
>>          self.thumbx.pack(side='left')
>>
>>          #self.thumby = ThumbWheel(master=self.f, width=50,
>>          self.thumby = ThumbWheel(master=f2, width=50,
>>                                   height=20, labcfg={'text':'Y:','side':'left'},
>>                                   wheelPad=2, oneTurn=.1, min=-1, max=1,
>>                                   showLabel=0, precision=5, type=float)
>>          self.thumby.callbacks.AddCallback(self.thumby_cb)
>>          self.thumby.unbind("<Button-3>")
>>          self.thumby.canvas.unbind("<Button-3>")
>>          #self.thumby.grid(row=1, column=1)
>>          self.thumby.pack(side='left')
>>
>>          #self.thumbz = ThumbWheel(master=self.f, width=50,
>>          self.thumbz = ThumbWheel(master=f3, width=50,
>>                                   height=20, labcfg={'text':'Z:','side':'left'},
>>                                   wheelPad=2, oneTurn=.1, min=-1, max=1,
>>                                   showLabel=0, precision=5, type=float)
>>          self.thumbz.callbacks.AddCallback(self.thumbz_cb)
>>          self.thumbz.unbind("<Button-3>")
>>          self.thumbz.canvas.unbind("<Button-3>")
>>          #self.thumbz.grid(row=2, column=1)
>>          self.thumbz.pack(side='left')
>>
>>          self.entryXTk = Tkinter.StringVar()
>>          #self.entryX = Tkinter.Entry(master=self.f, textvariable=self.entryXTk,
>>          self.entryX = Tkinter.Entry(master=f1, textvariable=self.entryXTk,
>>                                      width=8)
>>          self.entryX.bind('<Return>', self.entryX_cb)
>>          #self.entryX.grid(row=0, column=2)
>>          self.entryX.pack(side='left')
>>
>>          self.entryYTk = Tkinter.StringVar()
>>          #self.entryY = Tkinter.Entry(master=self.f, textvariable=self.entryYTk,
>>          self.entryY = Tkinter.Entry(master=f2, textvariable=self.entryYTk,
>>                                      width=8)
>>          self.entryY.bind('<Return>', self.entryY_cb)
>>          #self.entryY.grid(row=1, column=2)
>>          self.entryY.pack(side='left')
>>
>>          self.entryZTk = Tkinter.StringVar()
>>          #self.entryZ = Tkinter.Entry(master=self.f, textvariable=self.entryZTk,
>>          self.entryZ = Tkinter.Entry(master=f3, textvariable=self.entryZTk,
>>                                      width=8)
>>          self.entryZ.bind('<Return>', self.entryZ_cb)
>>          #self.entryZ.grid(row=2, column=2)
>>          self.entryZ.pack(side='left')
>>
>>          self.entryVTk = Tkinter.StringVar()
>>          self.entryV = Tkinter.Entry(master, textvariable=self.entryVTk,
>>                                      width=18)
>>          
>>          self.entryV.bind('<Return>', self.entryV_cb)
>>          
>>          self.f.pack(side='top', expand=1)
>>
>>          self.entryV.pack()
>>          
>> 	self.setButton=Tkinter.Button(master, text='normalize and set',
>>                                        command = self.setButton_cb)
>> 	self.setButton.pack(side='bottom')
>>
>>
>>      def setEntries(self):
>>          self.entryXTk.set(self.thumbx.labelFormat%self.vector[0])
>>          self.entryYTk.set(self.thumby.labelFormat%self.vector[1])
>>          self.entryZTk.set(self.thumbz.labelFormat%self.vector[2])
>>
>>          lf = '%.3f'
>>          self.entryVTk.set(lf%self.vector[0]+' '+lf%self.vector[1]+' '\
>>                            +lf%self.vector[2])
>>          self.drawVector()
>>
>>
>>      def createCanvas(self, master, size=200):
>>
>>          self.frame = Tkinter.Frame(self, relief = 'sunken', borderwidth=5)
>>
>>          if self.name is not None:
>>              self.title = Tkinter.Label(self.frame, text=self.name)
>>              self.title.pack(side=self.labelSide)
>>
>> 	self.canvas = Tkinter.Canvas(self.frame, width=size, height=size)
>>
>>          # set the focus so that we get keyboard events, and add callbacks
>>          self.canvas.bind('<KeyPress>', self.modifierDown)
>>          self.canvas.bind("<KeyRelease>", self.modifierUp)
>>
>>          xm = self.xm = ym = self.ym = self.r
>> 	self.canvas.create_oval(0, 0, size, size)
>> 	self.canvas.create_oval(xm-(xm/4), 0, xm+(xm/4), size,
>> 				tags='verticalCircle')
>> 	self.canvas.create_oval(0, ym-(ym/4), size, ym+(ym/4),
>> 				tags='horizontalCircle')
>>
>>          # apply viewing transformation to vector
>>          XaxisWithView = Numeric.dot([(1.,0.,0.,1.)],self.viewingMat)[0]
>>          x1 = self.xm+int(XaxisWithView[0]*(self.xm))
>>          y1 = self.ym+int(XaxisWithView[1]*(self.ym))
>>          self.canvas.create_line(xm, ym, x1, y1, fill='red', tags='axis')
>>
>>          XaxisWithView = Numeric.dot([(0.,1.,0.,1.)],self.viewingMat)[0]
>>          x2 = self.xm+int(XaxisWithView[0]*(self.xm))
>>          y2 = self.ym+int(XaxisWithView[1]*(self.ym))
>>          self.canvas.create_line(xm, ym, x2, y2, fill='green', tags='axis')
>>
>>          XaxisWithView = Numeric.dot([(0.,0.,1.,1.)],self.viewingMat)[0]
>>          x3 = self.xm+int(XaxisWithView[0]*(self.xm))
>>          y3 = self.ym+int(XaxisWithView[1]*(self.ym))
>>          self.canvas.create_line(xm, ym, x3, y3, fill='blue', tags='axis')
>>
>> 	self.textId = self.canvas.create_text(0, size, anchor='sw', text="XY")
>>
>> 	# shadow line in X=0 plane
>> 	self.shadowPX = self.canvas.create_polygon(0,0,0,0,0,0, fill='red',
>> 					       tag='moving')
>> 	self.shadowPY = self.canvas.create_polygon(0,0,0,0,0,0, fill='green',
>> 					       tag='moving')
>> 	self.shadowPZ = self.canvas.create_polygon(0,0,0,0,0,0, fill='blue',
>> 					       tag='moving')
>>
>> 	self.shadowX = self.canvas.create_line(0, 0, 0, 0, fill='black',
>> 					       tag='moving')
>> 	self.shadowY = self.canvas.create_line(0, 0, 0, 0, fill='black',
>> 					       tag='moving')
>> 	self.shadowZ = self.canvas.create_line(0, 0, 0, 0, fill='black',
>> 					       tag='moving')
>>
>> 	self.lId1 = self.canvas.create_line(0, 0, 0, 0, fill='black', width=3,
>> 					    arrow='last')
>> 	self.canvas.pack(side='top')
>>          self.frame.pack(expand=1, fill='x')
>>          self.xm = self.ym = self.r
>>          self.drawVector()
>>
>>
>>      def setVector(self, value):
>>          #setVector does not call a callback!
>>          v = value
>>          # compute normalized vector
>>          n = math.sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2])
>>          if n == 0.0: v = [0.0, 0.0, 1.0]
>>          else: v = [v[0]/n, v[1]/n, v[2]/n]
>>          self.vector = v
>>          self.setEntries()
>>          self.drawVector()
>>
>>
>>   #####################################################################
>>   # the 'configure' methods:
>>   #####################################################################
>>
>>      def configure(self, **kw):
>>          for key,value in kw.items():
>>              # the 'set parameter' callbacks
>>              if key=='continuous': self.setContinuous(value)
>>              elif key=='mode': self.setMode(value)
>>              elif key=='precision': self.setPrecision(value)
>>
>>              # the 'lock entries' callbacks
>>              elif key=='lockContinuous': self.lockContinuousCB(value)
>>              elif key=='lockMode': self.lockModeCB(value)
>>              elif key=='lockPrecision': self.lockPrecisionCB(value)
>>
>>
>>      def setContinuous(self, cont):
>>          """ cont can be None, 0 or 1 """
>>          if cont != 1:
>>              cont = None
>>          self.continuous = cont
>>          if hasattr(self.opPanel, 'optionsForm'):
>>              w=self.opPanel.idf.entryByName['togCont']['widget']
>>              if cont:
>>                  w.setvalue('on')
>>              else:
>>                  w.setvalue('off')
>>
>>
>>      def setMode(self, mode):
>>          if mode!='XY' and mode!='X' and mode!='Y' and mode!='Z': mode = 'XY'
>> 	self.canvas.itemconfigure( self.textId, text=mode)
>> 	self.mode = mode
>>
>>          if hasattr(self.opPanel, 'optionsForm'):
>>              w=self.opPanel.idf.entryByName['togAxes']['widget']
>>              w.setvalue(mode)
>>            
>>
>>      def setPrecision(self, val):
>>          val = int(val)
>>          if val > 10: val = 10
>>          if val < 1:  val = 1
>>          
>>          self.thumbx.configure(precision=val)
>>          self.thumby.configure(precision=val)
>>          self.thumbz.configure(precision=val)
>>
>>          self.entryXTk.set(self.thumbx.labelFormat%self.vector[0])
>>          self.entryYTk.set(self.thumby.labelFormat%self.vector[1])
>>          self.entryZTk.set(self.thumbz.labelFormat%self.vector[2])
>>          
>>          if hasattr(self.opPanel, 'optionsForm'):
>>              w = self.opPanel.idf.entryByName['selPrec']['widget']
>>              w.setvalue(val)
>>
>>          if self.opPanel:
>>              self.opPanel.updateDisplay()
>>
>>
>>   #####################################################################
>>   # the 'lock' methods:
>>   #####################################################################
>>   
>>
>>      def lockContinuousCB(self, mode):
>>          if mode != 0: mode = 1
>>          self.lockContinuous = mode
>>          if hasattr(self.opPanel, 'optionsForm'):
>>              self.opPanel.lockUnlockDisplay()
>>
>>
>>      def lockPrecisionCB(self, mode):
>>          if mode != 0: mode = 1
>>          self.lockPrecision = mode
>>          if hasattr(self.opPanel, 'optionsForm'):
>>              self.opPanel.lockUnlockDisplay()
>>
>>
>>      def lockModeCB(self, mode):
>>          if mode != 0: mode = 1
>>          self.lockMode = mode
>>          if hasattr(self.opPanel, 'optionsForm'):
>>              self.opPanel.lockUnlockDisplay()
>>
>>   
>> if __name__ == '__main__':
>>      test = vectorGUI(size = 200)
>>      def foo(val):
>>          print val
>>      test.callbacks.AddCallback(foo)
>

-- 

-----------------------------------------------------------------------
    o
   /    Michel F. Sanner Ph.D.            The Scripps Research Institute
o      Associate Professor               Department of Molecular Biology
   \                                      10550 North Torrey Pines Road
    o   Tel. (858) 784-7742               La Jolla, CA 92037, TPC 26
   /    Fax. (858) 784-2341
o      sanner at scripps.edu                http://www.scripps.edu/~sanner
-----------------------------------------------------------------------



More information about the Debian-med-packaging mailing list