📄 owmds.py
字号:
"""
<name>MDS</name>
<description>Multi dimensional scaling</description>
<icon>MDS.png</icon>
<contact>Ales Erjavec (ales.erjavec(@at@)fri.uni-lj.si)</contact>
<priority>5000</priority>
"""
import orange
import orngMDS
import OWGUI
import Numeric
import RandomArray
import qt
import sys
import math
import time
import os
import OWGraphTools
import OWToolbars
from random import random
from OWWidget import *
from OWGraph import *
from sets import Set
try:
from OWDataFiles import DataFiles
except:
class DataFiles:
pass
class OWMDS(OWWidget):
settingsList=["graph.ColorAttr", "graph.SizeAttr", "graph.ShapeAttr", "graph.NameAttr", "graph.ShowStress", "graph.NumStressLines", "graph.ShowName",
"StressFunc", "toolbarSelection", "autoSendSelection", "selectionOptions", "computeStress"]
contextHandlers={"":DomainContextHandler("", [ContextField("graph.ColorAttr", DomainContextHandler.Optional),
ContextField("graph.SizeAttr", DomainContextHandler.Optional),
ContextField("graph.ShapeAttr", DomainContextHandler.Optional),
ContextField("graph.NameAttr", DomainContextHandler.Optional),
ContextField("graph.ShowName", DomainContextHandler.Optional)])}
callbackDeposit=[]
def __init__(self, parent=None, signalManager=None, name="Multi Dimensional Scaling"):
OWWidget.__init__(self, parent, signalManager, name)
self.StressFunc=3
self.minStressDelta=1e-5
self.maxIterations=50
self.maxImprovment=10
self.autoSendSelection=0
self.toolbarSelection=0
self.selectionOptions=0
self.computeStress=1
self.ReDraw=1
self.NumIter=1
self.RefreshMode=0
self.inputs=[("Distances", orange.SymMatrix, self.cmatrix)]
self.outputs=[("Example Table", ExampleTable), ("Structured Data Files", DataFiles)]
self.stressFunc=[("Kruskal stress", orngMDS.KruskalStress),
("Sammon stress", orngMDS.SammonStress),
("Signed sammon stress", orngMDS.SgnSammonStress),
("Signed reative stress", orngMDS.SgnRelStress)]
self.layout=QVBoxLayout(self.mainArea)
self.graph=MDSGraph(self.mainArea)
self.layout.addWidget(self.graph)
tabs=QTabWidget(self.controlArea)
graph=QVGroupBox(self)
OWGUI.hSlider(graph, self, "graph.PointSize", box="Point Size", minValue=1, maxValue=20, callback=self.graph.updateData)
self.colorCombo=OWGUI.comboBox(graph, self, "graph.ColorAttr", box="Color", callback=self.graph.updateData)
self.sizeCombo=OWGUI.comboBox(graph, self, "graph.SizeAttr", box="Size", callback=self.graph.updateData)
self.shapeCombo=OWGUI.comboBox(graph, self, "graph.ShapeAttr", box="Shape", callback=self.graph.updateData)
self.nameCombo=OWGUI.comboBox(graph, self, "graph.NameAttr", box="Label", callback=self.graph.updateData)
OWGUI.checkWithSpin(graph, self, checked="graph.ShowStress", value="graph.NumStressLines",label="Show", min=0, max=1000,
posttext="lines",spinCallback=self.graph.updateLines, checkCallback=self.graph.updateData)
self.zoomToolbar=OWToolbars.ZoomSelectToolbar(self, graph, self.graph, self.autoSendSelection)
self.connect(self.zoomToolbar.buttonSendSelections, SIGNAL("clicked()"), self.sendSelections)
self.graph.autoSendSelectionCallback = lambda :self.autoSendSelection and self.sendSelections()
OWGUI.checkBox(graph, self, "autoSendSelection", "Auto send selected")
OWGUI.radioButtonsInBox(graph, self, "selectionOptions", ["Don't append", "Append coord.", "Append coord. as meta"], box="Append coordinates")
mds=QVGroupBox(self)
init=OWGUI.widgetBox(mds, "Initialization")
OWGUI.button(init, self, "Randomize", self.randomize)
OWGUI.button(init, self, "Jitter", self.jitter)
OWGUI.button(init, self, "Torgerson", self.torgerson)
opt=OWGUI.widgetBox(mds, "Optimization")
self.startButton=OWGUI.button(opt, self, "Start", self.testStart)
OWGUI.button(opt, self, "LSMT", self.LSMT)
OWGUI.button(opt, self, "Step", self.smacofStep)
#OWGUI.button(opt, self, "Stop", self.stop)
#OWGUI.button(opt, self, "Redraw graph", callback=self.graph.updateData)
#OWGUI.checkBox(opt, self, "ReDraw", "Redraw graph after each step")
#OWGUI.spin(opt, self, "NumIter",box="Num. Iterations per Step",min=1, max=1000)
OWGUI.radioButtonsInBox(opt, self, "RefreshMode", ["Every step", "Every 10 steps", "Every 100 steps"], "Refresh After Optimization")
self.stopping=OWGUI.widgetBox(opt, "Stopping Conditions")
#OWGUI.checkBox(stopping, self, "computeStress", "Compute stress")
stress=OWGUI.widgetBox(self.stopping, "Min. Avg. Stress Delta")
OWGUI.comboBox(self.stopping, self, "StressFunc", box="Stress Function", items=[a[0] for a in self.stressFunc], callback=self.updateStress)
OWGUI.qwtHSlider(stress, self, "minStressDelta", minValue=1e-5, maxValue=1e-2, step=1e-5, precision=6)
OWGUI.spin(self.stopping, self, "maxIterations", box="Max. Number of Steps", min=1, max=100)
#OWGUI.spin(stopping, self, "maxImprovment", box="Max. improvment of a run", min=0, max=100, postfix="%")
tabs.addTab(mds, "MDS")
tabs.addTab(graph, "Graph")
mds.setSizePolicy(QSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum))
graph.setSizePolicy(QSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum))
self.controlArea.setMinimumWidth(250)
infoBox=OWGUI.widgetBox(self.controlArea, "Info")
self.infoA=QLabel("Avg. stress:", infoBox)
self.infoB=QLabel("Num. steps", infoBox)
OWGUI.button(self.controlArea, self, "Save", self.graph.saveToFile)
#self.info
self.resize(900,700)
self.done=True
def cmatrix(self, matrix=None):
self.closeContext()
self.origMatrix=matrix
self.data=data=None
if matrix:
self.data=data=getattr(matrix, "items")
if data and type(data)==orange.ExampleTable:
self.setExampleTable(data)
elif type(data)==list:
self.setList(data)
elif type(data)==orange.VarList:
self.setVarList(data)
self.graph.ColorAttr=0
self.graph.SizeAttr=0
self.graph.ShapeAttr=0
self.graph.NameAttr=0
if matrix:
self.mds=orngMDS.MDS(matrix)
self.mds.points=RandomArray.random([self.mds.n, self.mds.dim])
self.mds.getStress()
self.stress=self.getAvgStress(self.stressFunc[self.StressFunc][1])
if data and type(data) == orange.ExampleTable:
self.openContext("",self.data)
self.graph.setData(self.mds, self.colors, self.sizes, self.shapes, self.names)
else:
self.graph.clear()
def setExampleTable(self, data):
self.colorCombo.clear()
self.sizeCombo.clear()
self.shapeCombo.clear()
self.nameCombo.clear()
attributes=[attr for attr in data.domain.variables+data.domain.getmetas().values() or [] ]
discAttributes=filter(lambda a: a.varType==orange.VarTypes.Discrete, attributes)
contAttributes=filter(lambda a: a.varType==orange.VarTypes.Continuous, attributes)
attrName=[attr.name for attr in attributes]
for name in ["One color"]+attrName:
self.colorCombo.insertItem(name)
for name in ["One size"]+map(lambda a:a.name, contAttributes):
self.sizeCombo.insertItem(name)
for name in ["One shape"]+map(lambda a: a.name, discAttributes):
self.shapeCombo.insertItem(name)
for name in ["No name"]+attrName:
self.nameCombo.insertItem(name)
self.attributes=attributes
self.discAttributes=discAttributes
self.contAttributes=contAttributes
self.colors=[[Qt.black]*(len(attributes)+1) for i in range(len(data))]
self.shapes=[[QwtSymbol.Ellipse]*(len(discAttributes)+1) for i in range(len(data))]
self.sizes=[[5]*(len(contAttributes)+1) for i in range(len(data))]
self.names=[[""]*(len(attributes)+1) for i in range(len(data))]
contI=discI=attrI=1
for j, attr in enumerate(attributes):
if attr.varType==orange.VarTypes.Discrete:
c=OWGraphTools.ColorPaletteHSV(len(attr.values))
for i in range(len(data)):
self.colors[i][attrI]= data[i][attr].isSpecial() and Qt.black or c[int(data[i][attr])]
self.shapes[i][discI]= data[i][attr].isSpecial() and self.graph.shapeList[0] or self.graph.shapeList[int(data[i][attr])%len(self.graph.shapeList)]
self.names[i][attrI]=" "+str(data[i][attr])
#self.sizes[i][contI]=5
attrI+=1
discI+=1
elif attr.varType==orange.VarTypes.Continuous:
c=OWGraphTools.ColorPaletteHSV(-1)
val=[e[j] for e in data if not e[j].isSpecial()]
minVal=min(val)
maxVal=max(val)
for i in range(len(data)):
self.colors[i][attrI]=data[i][attr].isSpecial() and Qt.black or c.getColor((data[i][attr]-minVal)/max(maxVal-minVal, 1e-6))
#self.shapes[i][discI]=self.graph.shapeList[0]
self.names[i][attrI]=" "+str(data[i][attr])
self.sizes[i][contI]=data[i][attr].isSpecial() and 5 or int(self.data[i][attr]/maxVal*9)+1
contI+=1
attrI+=1
else:
for i in range(len(data)):
self.colors[i][attrI]=Qt.black
#self.shapes[i][j+1]=self.graph.shapeList[0]
self.names[i][attrI]=" "+str(data[i][attr])
#self.sizes[i][j+1]=5
attrI+=1
def setList(self, data):
self.colorCombo.clear()
self.sizeCombo.clear()
self.shapeCombo.clear()
self.nameCombo.clear()
for name in ["One color", "strain"]:
self.colorCombo.insertItem(name)
for name in ["No name", "name", "strain"]:
self.nameCombo.insertItem(name)
self.colors=[[Qt.black]*3 for i in range(len(data))]
self.shapes=[[QwtSymbol.Ellipse] for i in range(len(data))]
self.sizes=[[5] for i in range(len(data))]
if type(data[0]) in [str, unicode]:
self.names = [("", di, "", "") for di in data]
else:
self.names=[[""]*4 for i in range(len(data))]
try:
#print dir(data[0][1][0])
strains=list(Set([d.strain for d in data]))
c=OWGraphTools.ColorPaletteHSV(len(strains))
for i, d in enumerate(data):
self.colors[i][1]=c[strains.index(d.strain)]
self.names[i][1]=" "+d.name
self.names[i][2]=" "+d.strain
except Exception, val:
print val
def setVarList(self, data):
self.colorCombo.clear()
self.sizeCombo.clear()
self.shapeCombo.clear()
self.nameCombo.clear()
for name in ["One color", "Variable"]:
self.colorCombo.insertItem(name)
for name in ["No name", "Var name"]:
self.nameCombo.insertItem(name)
self.colors=[[Qt.black]*3 for i in range(len(data))]
self.shapes=[[QwtSymbol.Ellipse] for i in range(len(data))]
self.sizes=[[5] for i in range(len(data))]
self.names=[[""]*4 for i in range(len(data))]
try:
c=OWGraphTools.ColorPaletteHSV(len(data))
for i, d in enumerate(data):
self.colors[i][1]=c[i]
self.names[i][1]=" " +str(d.name)
except Exception, val:
print val
def smacofStep(self):
if not getattr(self, "mds", None):
return
for i in range(self.NumIter):
self.mds.SMACOFstep()
if self.computeStress:
self.mds.getStress(self.stressFunc[self.StressFunc][1])
self.stress=self.getAvgStress(self.stressFunc[self.StressFunc][1])
#st=time.clock()
if self.ReDraw:
self.graph.updateData()
#print "Update:", time.clock()-st
def LSMT(self):
if not getattr(self, "mds", None):
return
self.mds.LSMT()
if self.computeStress:
self.mds.getStress(self.stressFunc[self.StressFunc][1])
self.stress=self.getAvgStress(self.stressFunc[self.StressFunc][1])
if self.ReDraw:
self.graph.updateData()
def torgerson(self):
if not getattr(self, "mds", None):
return
self.mds.Torgerson()
if self.computeStress:
self.mds.getStress(self.stressFunc[self.StressFunc][1])
self.stress=self.getAvgStress(self.stressFunc[self.StressFunc][1])
self.graph.updateData()
def randomize(self):
if not getattr(self, "mds", None):
return
self.mds.points = RandomArray.random(shape=[self.mds.n,2])
if self.computeStress:
self.mds.getStress(self.stressFunc[self.StressFunc][1])
self.stress=self.getAvgStress(self.stressFunc[self.StressFunc][1])
self.graph.updateData()
def jitter(self):
if not getattr(self, "mds", None):
return
mi = Numeric.argmin(self.mds.points,0)
ma = Numeric.argmax(self.mds.points,0)
st = 0.01*(ma-mi)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -