forked from SainsburyWellcomeCentre/lasagna
-
Notifications
You must be signed in to change notification settings - Fork 0
/
lasagna_helperFunctions.py
262 lines (201 loc) · 9.81 KB
/
lasagna_helperFunctions.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
"""
Helper functions for lasagna. Functions in this file are involved in the following tasks:
1. Finding plot widgets by name within an object.
2. Finding paths to preferences files, etc.
3. Defining default preferences and loading and saving preferences.
"""
import os
import string
import yaml #Preferences are stored in a YAML file
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
def findPyQtGraphObjectNameInPlotWidget(PlotWidget,itemName,regex=False,verbose=False):
"""
Searches a PyQtGraph PlotWidget for an plot object (i.e. something added with .addItem)
with name "itemName"
Inputs:
PlotWidget - an instance of a PyQtGraph plot widget
itemName - a string defining the .objectName to search for in PlotWidget.
regex - if True the itemName is treated as a regular expression. [False by default]
Outputs:
Returns the instance of the object bearing the chosen name. Returns None if no
object was found.
Notes:
The user must assign a sensible name to every created plot item. Added objects will
by default have a blank object name. This function does not do a recursive search,
so you can't feed it the GUI root object and expect an answer. It returns *ONLY* the
first found item.
"""
if verbose:
print("findPyQtGraphObjectNameInPlotWidget - looking for object %s in PlotWidget %s" % (itemName,str(PlotWidget)))
if regex==True:
import re
if not hasattr(PlotWidget, 'getPlotItem'):
print("findPyQtGraphObjectNameInPlotWidget finds no attribute getPlotItem")
return False
pltItem = PlotWidget.getPlotItem()
if not hasattr(pltItem,'items'):
print("findPyQtGraphObjectNameInPlotWidget finds no attribute 'items'")
return False
if len(pltItem.items)==0:
print("findPyQtGraphObjectNameInPlotWidget finds no items in list")
return False
if regex == True:
for thisItem in pltItem.items:
if re.search(itemName,thisItem.objectName):
return thisItem
else:
for thisItem in pltItem.items:
if thisItem.objectName == itemName:
return thisItem
if verbose:
print("Failed to find %s in PlotWidget" % itemName)
return False
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Functions that find and define paths for handling plugins and preferences
def getHomeDir():
"""
Return the user's home directory as a string. Should work on both Windows and Linux
See: http://stackoverflow.com/questions/10644183/how-to-store-variables-preferences-in-python-for-later-use
"""
if os.name != "posix":
homedir = os.path.expanduser("~")+"\\"
else:
homedir = "{}/".format(os.path.expanduser("~"))
return homedir
def stripTrailingFileFromPath(thisPath):
"""
Given a path (e.g. '/home/user/myImage.tiff') strip the file name and return the rest of the path
"""
thisPath = os.path.split(thisPath)
thisPath = str(thisPath[0])
thisPath += os.path.sep
if thisPath[-1] != os.path.sep:
thisPath = thisPath + os.path.sep
return thisPath
def absPathToLasagna():
"""
Returns the absolute path to this module, which in turn is the absolute path to lasagna.
This function is used for thing such as identifying the correct path for loading plugins
packaged with lasagna.
"""
return stripTrailingFileFromPath(os.path.abspath(__file__))
def getLasagna_prefDir():
"""
Returns the path to lasagna preferences directory.
If it does not exist it creates it and then returns the path
"""
prefDir = getHomeDir() +'.lasagna'
if not os.path.exists(prefDir):
os.makedirs(prefDir)
assert os.path.exists(prefDir)
if os.name != "posix":
prefDir = prefDir + '\\'
else:
prefDir = prefDir + '/'
return prefDir
def getLasagnaPrefFile():
"""
Returns the location of the main lasagna preferences file.
It does not matter if the file does not exist, since it will be
created on demand by other functions.
"""
return getLasagna_prefDir() + 'lasagna_prefs.yml'
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Functions that handle preferences
def defaultPreferences():
"""
** These are the default preferences **
Return a dictionary containing the default lasagna preferences. This is necessary
in case a particular preference is missing or the preferences file is missing.
"""
return {
'lastLoadDir' : getHomeDir(), #The directory from which we last loaded data
'numRecentFiles' : 5, #The number of recently loaded file names to store
'recentlyLoadedFiles' : [], #A list containing the last "numRecentFiles" file names
'IO_modulePaths' : [absPathToLasagna()+'IO'], #must be asbolute paths
'pluginPaths' : [absPathToLasagna()+'tutorialPlugins',
absPathToLasagna()+'registrationPlugins',
absPathToLasagna()+'ARA'], #must be asbolute paths
'defaultAxisRatios' : [1,2,0.5], #The default axis ratios
'defaultPointZSpread' : [5,5,3], #The range of layers over which points or lines are visible
'showCrossHairs' : True, #Whether or not to show the cross hairs
'colorOrder' : ['red','green','blue','magenta','cyan','yellow','gray'], #The order in which colors appear by default (see imagestack class)
'symbolOrder' : ['o','s','t','d','+'],
'defaultLineWidth' : 2,
'defaultSymbolOpacity' : 200,
'defaultSymbolSize' : 8,
'hideZoomResetButtonOnImageAxes' : True,
'hideAxes' : True,
}
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Functions that handle preferences
"""
The following plugin functions by default expect the name and path of the preferences file to be the
main lasagna preferences file. However, this can be over-ridden so that indiviual plugins can have
their own preferences files and still use these functions.
"""
def loadAllPreferences(prefFName=getLasagnaPrefFile(),defaultPref=defaultPreferences()):
"""
Load the preferences YAML file. If the file is missing, we create it using the default
preferences defined above. Preferences are returned as a dictionary.
"""
#print "loading from pref file %s" % prefFName
#Generate a default preferences file if no preferences file exists
if os.path.exists(prefFName) == False:
print("PREF FILE")
print(prefFName)
writeAllPreferences(defaultPref,prefFName=prefFName)
print("Created default preferences file in " + prefFName)
#Load preferences YAML file as a dictionary
with open(prefFName, 'r') as stream:
return yaml.load(stream)
def readPreference(preferenceName,prefFName=getLasagnaPrefFile(), preferences=getLasagnaPrefFile()):
"""
Read preferences with key "preferenceName" from YAML file prefFName on disk.
If the key is abstent, call defaultPreferences and search for the key. If it
is present, add to preferences file and return the value. If absent, raise a
warning and return None. The caller function needs to decide what to do with
the None.
"""
#TODO: need some sort of check as to whether the preference value is valid
#Check on disk
preferences = loadAllPreferences(prefFName)
if preferenceName in preferences:
return preferences[preferenceName]
else:
print("Did not find preference %s on disk. Looking in defaultPreferencesa" % preferenceName)
#Check in default preferences and to file and return if so
preferences = defaultPreferences()
if preferenceName in preferences:
value = preferences[preferenceName]
preferenceWriter(preferenceName,value,prefFName)
return value
else:
print("Did not find preference %s in default preferences" % preferenceName)
def writeAllPreferences(preferences,prefFName=getLasagnaPrefFile()):
"""
Save the dictionary "preferences" as a YAML file in the .lasagna directory located in the
user's home directory.
"""
assert isinstance(preferences,dict)
#TODO: check ability to write to the file before proceeding
with open(prefFName, 'w') as stream:
yaml.dump(preferences, stream)
def preferenceWriter(preferenceName,newValue,prefFName=getLasagnaPrefFile()):
"""
Overwrite a single key "preferenceName" in self.preferences with the value "newValue"
Saves updates dictionary to the preferences file
"""
print("Writing preference data for: %s\n" % preferenceName)
preferences = loadAllPreferences(prefFName)
if preferenceName in preferences:
preferences[preferenceName] = newValue
else:
print("Adding missing preference %s to preferences file" % preferenceName)
preferences[preferenceName] = newValue
writeAllPreferences(preferences,prefFName)