source: orange-bioinformatics/widgets/prototypes/OWDataFiles.py @ 1072:b9c859aad5a0

Revision 1072:b9c859aad5a0, 10.3 KB checked in by markotoplak, 4 years ago (diff)

OWDataFiles: now it also works on unix systems.

Line 
1"""
2<name>Data Files</name>
3<description>Reads data from designated directory.</description>
4<icon>icons/ChipDataFiles.png</icon>
5<priority>1050</priority>
6<contact>Peter Juvan (peter.juvan@fri.uni-lj.si)</contact>
7"""
8
9from OWWidget import *
10import OWGUI
11import os, os.path, orange
12
13import warnings
14warnings.filterwarnings("ignore", "'strain'", orange.AttributeWarning)
15
16class DataFiles(orange.Orange):
17    """Structure for communicating multiple ExampleTables:
18    [(name1,[exampleTable1a,exampleTable1b,...]), (name2,[exampleTable2a,...]), ...]
19    """
20    pass
21
22
23class ExampleSelection(orange.Orange):
24    """Structure for selection of examples: (selectorName, [0,1,...])
25    """
26    pass
27
28
29class OWDataFiles(OWWidget):
30    settingsList  = ["recentDirs", "selectedDirName", "applyOnChange"]
31
32    def __init__(self, parent=None, signalManager = None, loaddata=1):
33        OWWidget.__init__(self, parent, signalManager, 'Data Files', wantMainArea = 0, resizingEnabled = 1)
34
35        self.callbackDeposit = []
36
37        self.inputs = []
38        self.outputs = [("Examples", ExampleTable), ("Structured Data", DataFiles)]
39
40        self.dataStructure = []
41        self.datasets = None
42        self.lastSentIds = []
43
44        # Settings
45        self.recentDirs=[] 
46        self.selectedDirName = "None"
47        self.applyOnChange = 0
48        self.loadSettings()
49
50        # CONTROLS
51        box = OWGUI.widgetBox(self.controlArea, "Directory", addSpace = True, orientation=0)
52        self.dircombo=QComboBox(box)
53        box.layout().addWidget(self.dircombo)
54        button = OWGUI.button(box, self, '...', callback = self.browseDirectory, disabled=0)
55        button.setMaximumWidth(25)
56        # connecting GUI to code
57        self.connect(self.dircombo,SIGNAL('activated(int)'),self.selectDir)
58
59        # info
60        box = OWGUI.widgetBox(self.controlArea, "Info", addSpace = True)
61        self.infoa = OWGUI.widgetLabel(box, 'No data loaded.')
62        self.infob = OWGUI.widgetLabel(box, '')
63        self.infoc = OWGUI.widgetLabel(box, '')
64           
65        # LIST VIEW
66        frmListView = OWGUI.widgetBox(self.controlArea, None, addSpace = True)
67        self.tree = QTreeWidget(frmListView)
68        self.tree.setSelectionMode(QAbstractItemView.MultiSelection)
69        self.tree.setHeaderLabel("Directory/Data File")
70        frmListView.layout().addWidget(self.tree)
71        self.connect(self.tree,SIGNAL('itemSelectionChanged()'),self.selectionChanged)
72
73        # Output
74        box = OWGUI.widgetBox(self.controlArea, "Output", addSpace = True)
75        OWGUI.checkBox(box, self, 'applyOnChange', 'Commit data on selection change')
76        self.commitBtn = OWGUI.button(box, self, "Commit", callback=self.sendData, disabled=1)
77        self.resize(300,600)
78
79        # initial settings           
80        self.recentDirs=filter(os.path.exists,self.recentDirs)
81        self.setDirlist()
82        self.dircombo.setCurrentIndex(0)
83        if self.recentDirs!=[] and loaddata:
84            self.loadData(self.recentDirs[0])
85           
86    def setFileTree(self):
87        self.disconnect(self.tree,SIGNAL('itemSelectionChanged()'),self.selectionChanged)
88        self.tree.clear()
89        self.listitems = []
90        for d in self.dataStructure:
91            (dirname, files) = d
92            diritem = QTreeWidgetItem(self.tree, [dirname], QTreeWidgetItem.UserType)
93            diritem.setSelected(1)
94            self.listitems.append(diritem)
95            diritem.setExpanded(1)
96            diritem.name = dirname
97            for f in files:
98                item = QTreeWidgetItem(diritem, [f.name], QTreeWidgetItem.UserType)
99                item.setSelected(1)
100                self.listitems.append(item)
101                item.data = f
102        self.connect(self.tree,SIGNAL('itemSelectionChanged()'),self.selectionChanged)
103               
104    def selectionChanged(self):
105        if self.applyOnChange:
106            self.sendData()
107
108    # checks which data has been selected, builds a data structure, and sends it out
109    def sendData(self):
110        data = []
111        # clear what has been previously sent
112        for id in self.lastSentIds:
113            self.send("Examples", None, id)
114        self.lastSentIds = []
115        # send new data
116        id = 0
117        for tIdx in range(self.tree.topLevelItemCount()):
118            dir = self.tree.topLevelItem(tIdx)
119            if dir in self.tree.selectedItems():
120                files = []
121                for cIdx in range(dir.childCount()):
122                    f = dir.child(cIdx)
123                    if f in self.tree.selectedItems():
124                        files.append(f.data)
125                        self.send("Examples", f.data, id)
126                        self.lastSentIds.append(id)
127                        id += 1
128                data.append((dir.name, files))
129        #print "DATAS", data
130        self.send("Structured Data", data)
131
132    # Loads the data from a root directory, sends the data to the output channels
133    def loadData(self, root):
134        dataStructure = [] # structured [(dirname0, [d00, d01, ...]), ...]
135        datasets = []  # flat list containing all the data sets
136        dirs = os.listdir(root)
137        lenDirs = len(dirs)
138        if lenDirs:
139            self.progressBarInit()
140            pbStep = 100./lenDirs
141        for d in dirs:
142            dirname = os.path.join(root, d)
143            if os.path.isdir(dirname):
144                dirdata = []   
145                files  = os.listdir(dirname)
146                for f in files:
147                    name, ext = os.path.splitext(f)
148                    if ext in ['.tab', '.txt', '.data']:
149                        try:
150                            data = None
151                            data = orange.ExampleTable(os.path.join(dirname,f))
152                            data.name = name
153                            data.strain = os.path.basename(dirname)
154                            dirdata.append(data)
155                        except orange.KernelException:
156                            print 'Warning: file %s\\%s not in appropriate format' %(dirname, f)
157                if len(dirdata):
158                    dataStructure.append((os.path.split(dirname)[1], dirdata))
159                    datasets = datasets + dirdata
160            self.progressBarAdvance(pbStep)
161        if lenDirs:
162            self.progressBarFinished()
163
164        # enable commit, set file tree
165        self.commitBtn.setEnabled(len(dataStructure))
166        self.dataStructure = dataStructure
167        self.datasets = datasets
168        self.setFileTree()
169
170        # set infos (sumarize the data)
171        if len(dataStructure):
172            numSets = len(self.dataStructure)
173            numFiles = len(self.datasets)
174            self.infoa.setText("%d set%s, total of %d data file%s." % (numSets, ["", "s"][numSets!=1], numFiles, ["","s"][numFiles!=1]))
175            # construct lists that sumarize the data
176            numExamplesList = []
177            numAttrList = []
178            hasClass = []
179            attrNameList = []
180            for et in datasets:
181                numExamplesList.append(len(et))
182                numAttrList.append(len(et.domain.attributes))
183                hasClass.append(et.domain.classVar != None)
184                for attr in et.domain.attributes:
185                    if attr.name not in attrNameList:
186                        attrNameList.append(attr.name)
187            # report the number of attributes/class
188            if len(numAttrList):
189                minNumAttr = min(numAttrList)
190                maxNumAttr = max(numAttrList)
191                if minNumAttr != maxNumAttr:
192                    infob = "From %d to %d attribute%s (%d in total)" % (minNumAttr, maxNumAttr, ["","s"][maxNumAttr!=1], len(attrNameList))
193                else:
194                    infob = "%d attribute%s" % (maxNumAttr, ["","s"][maxNumAttr!=1])
195            else:
196                infob = "No attributes"
197            if sum(hasClass) == len(hasClass):
198                infob += ", all files contain class variable."
199            elif sum(hasClass) == 0:
200                infob += ", no class variable."
201            else:
202                infob += ", some files contain class variable."
203            self.infob.setText(infob)
204            # report the number of examples
205            if len(numExamplesList):
206                infoc = "Files contain "
207                minNumE = min(numExamplesList)
208                maxNumE = max(numExamplesList)
209                if minNumE == maxNumE:
210                    infoc += "%d example%s, " % (maxNumE, ["","s"][maxNumE!=1])
211                else:
212                    infoc += "from %d to %d example%s, " % (minNumE, maxNumE, ["","s"][maxNumE!=1])
213                infoc += "%d in total." % sum(numExamplesList)
214            else:
215                infoc = "Files contain no examples."
216            self.infoc.setText(infoc)
217
218            # Add a directory to the start of the file list.
219            # If it exists, move it to the start of the list
220            if root in self.recentDirs:
221                self.recentDirs.remove(root)
222            self.recentDirs.insert(0, root)
223            self.setDirlist()
224            self.selectedDirName = root
225               
226        else:
227            self.infoa.setText('No data on input.')
228            self.infob.setText('')
229            self.infoc.setText('')
230
231        # read data
232        if self.applyOnChange:
233            self.sendData()
234
235    # displays a file dialog and selects a directory
236    def browseDirectory(self):
237        if len(self.recentDirs):
238            startdir=self.recentDirs[0]
239        else:
240            startdir ="."
241        dirname=str(QFileDialog.getExistingDirectory(self, 'Data Directory', startdir, QFileDialog.ShowDirsOnly))
242        if len(dirname):
243            self.loadData(str(dirname))
244
245    def setDirlist(self):
246        self.dircombo.clear()
247        if len(self.recentDirs):
248            for dir in self.recentDirs:
249                (upperdir,dirname)=os.path.split(dir)
250                # leave out the path
251                self.dircombo.insertItem(self.dircombo.count(), dirname)
252        else:
253            self.dircombo.insertItem(0,"(none)")
254
255    # called when user makes a selection from the drop-down menu
256    def selectDir(self, n):
257        if self.recentDirs:
258            self.loadData(self.recentDirs[n])
259        else:
260            self.loadData("(none)")
261
262
263
264if __name__=="__main__":
265    a=QApplication(sys.argv)
266    ow=OWDataFiles()
267    ow.show()
268    ow.loadData("/home/marko/anova/smallchipdata")
269    a.exec_()
270    ow.saveSettings()
Note: See TracBrowser for help on using the repository browser.