Skip to content

Commit abc7c13

Browse files
committed
Scaling of colorscale. Setting colorscale to apply to selected view. Toggle views on and off.
1 parent b41d7d7 commit abc7c13

File tree

2 files changed

+124
-39
lines changed

2 files changed

+124
-39
lines changed

python/rdesigneur/moogul.py

Lines changed: 75 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class MooView:
3939
rgb = []
4040
viewList = []
4141
consolidatedTitle = ""
42+
colorbarViewIdx = 0 # Which View does the colorbar serve?
4243

4344
def __init__( self, swx = 10, swy = 10, hideAxis = True, title = "view", colormap = 'jet'
4445
):
@@ -58,6 +59,7 @@ def __init__( self, swx = 10, swy = 10, hideAxis = True, title = "view", colorma
5859
self.valMmax = 1.0
5960
self.simTime = 0.0
6061
self.plotFlag_ = True
62+
self.cbox = []
6163

6264
@staticmethod
6365
def replayLoop():
@@ -121,60 +123,71 @@ def updateAxis( self ):
121123
self.axisLength.text = "{:.2f} <i>u</i>m".format( dx * 1e6*self.scene.range * self.colorbar.width / self.scene.width )
122124

123125
def raiseMax( self, isDouble = False ):
124-
valRange = self.valMax - self.valMin
126+
moov = MooView.viewList[MooView.colorbarViewIdx]
127+
valRange = moov.valMax - moov.valMin
125128
if isDouble:
126-
self.valMax = self.valMin + 2 * valRange
129+
moov.valMax = moov.valMin + 2 * valRange
127130
else:
128-
self.valMax = self.valMin + valRange * 1.1111111111111111111111
131+
moov.valMax = moov.valMin + valRange * 1.1111111111111111111111
132+
return moov.valMax
129133

130134
def lowerMax( self, isDouble = False ):
131-
valRange = self.valMax - self.valMin
135+
moov = MooView.viewList[MooView.colorbarViewIdx]
136+
valRange = moov.valMax - moov.valMin
132137
if isDouble:
133-
self.valMax = self.valMin + 0.5 * valRange
138+
moov.valMax = moov.valMin + 0.5 * valRange
134139
else:
135-
self.valMax = self.valMin + valRange * 0.9
140+
moov.valMax = moov.valMin + 0.9 * valRange
141+
return moov.valMax
136142

137143
def raiseMin( self, isDouble = False ):
138-
valRange = self.valMax - self.valMin
144+
moov = MooView.viewList[MooView.colorbarViewIdx]
145+
valRange = moov.valMax - moov.valMin
139146
if isDouble:
140-
self.valMin = self.valMmax - 0.5 * valRange
147+
moov.valMin = moov.valMmax - 0.5 * valRange
141148
else:
142-
self.valMin = self.valMax - valRange * 0.9
149+
moov.valMin = moov.valMax - valRange * 0.9
150+
return moov.valMin
143151

144152
def lowerMin( self, isDouble = False ):
145-
valRange = self.valMax - self.valMin
153+
moov = MooView.viewList[MooView.colorbarViewIdx]
154+
valRange = moov.valMax - moov.valMin
146155
if isDouble:
147-
self.valMin = self.valMax - 2 * valRange
156+
moov.valMin = moov.valMax - 2 * valRange
148157
else:
149-
self.valMin = self.valMax - valRange * 1.1111111111111111111111
150-
151-
158+
moov.valMin = moov.valMax - valRange * 1.1111111111111111111111
159+
return moov.valMin
152160

153161
def scaleColorbar( self, event ):
154162
loc = event.pos
155-
#print( loc.y )
163+
if loc.y > 6:
164+
idx = MooView.colorbarViewIdx + 1
165+
if idx >= len( MooView.viewList ):
166+
idx = 0
167+
self.selectCbar( idx )
168+
return
156169
if loc.y > 4 and loc.y < 4.7:
157-
self.lowerMax( self.scene.mouse.shift )
158-
self.barMax.text = "{:.3f}".format(self.valMax)
170+
ret = self.lowerMax( self.scene.mouse.shift )
171+
self.barMax.text = "{:.3e}".format(ret)
159172
elif loc.y > 4.85 and loc.y < 5.5:
160-
self.raiseMax( self.scene.mouse.shift )
161-
self.barMax.text = "{:.3f}".format(self.valMax)
173+
ret = self.raiseMax( self.scene.mouse.shift )
174+
self.barMax.text = "{:.3e}".format(ret)
162175
elif loc.y > -3.25 and loc.y < -2.6:
163-
self.raiseMin( self.scene.mouse.shift )
164-
self.barMin.text = "{:.3f}".format(self.valMin)
176+
ret = self.raiseMin( self.scene.mouse.shift )
177+
self.barMin.text = "{:.3e}".format(ret)
165178
elif loc.y > -3.95 and loc.y < -3.45:
166-
self.lowerMin( self.scene.mouse.shift )
167-
self.barMin.text = "{:.3f}".format(self.valMin)
168-
self.drawables_[0].updateLimits( self.valMin, self.valMax )
179+
ret = self.lowerMin( self.scene.mouse.shift )
180+
self.barMin.text = "{:.3e}".format(ret)
181+
for moov in MooView.viewList:
182+
moov.drawables_[0].updateLimits( moov.valMin, moov.valMax )
169183

170184
def innerColorbar( self, title, bg ):
171185
barWidth = SCALE_SCENE * 1.5
172186
if ( bgLookup(bg).mag < 1 ):
173187
barTextColor = vp.color.white
174188
else:
175189
barTextColor = vp.color.black
176-
self.colorbar = vp.canvas( title = title, width = barWidth, height = self.swy * SCALE_SCENE, background = bgLookup(bg), align = 'left', range = 1, autoscale = False )
177-
#self.colorbar = vp.canvas( title = title, width = barWidth, height = self.swy * SCALE_SCENE, background = vp.color.cyan, align = 'left', range = 1, autoscale = False )
190+
self.colorbar = vp.canvas( title = "Datasets = ", width = barWidth, height = self.swy * SCALE_SCENE, background = bgLookup(bg), align = 'left', range = 1, autoscale = False )
178191
self.colorbar.userzoom = False
179192
self.colorbar.userspin = False
180193
self.colorbar.userpan = False
@@ -185,10 +198,11 @@ def innerColorbar( self, title, bg ):
185198
axOrigin = vp.vector( 0, -5.5, 0 )
186199
for idx, rgb in enumerate( self.rgb ):
187200
cbox = vp.box( canvas = self.colorbar, pos = vp.vector( 0, height * (idx - 26), 0), width = width, height = height, color = rgb )
188-
barName = self.title.replace( ' ', '\n' )
201+
barName = self.title.replace( '.', '\n' )
202+
barName = barName.replace( '/', '\n', 1 )
189203
self.barName = vp.label( canvas = self.colorbar, align = 'left', pixel_pos = True, pos = vp.vector( 2, (self.swy - 0.32) * SCALE_SCENE, 0), text = barName, height = 15, color = barTextColor, box = False, opacity = 0 )
190-
self.barMin = vp.label( canvas = self.colorbar, align = 'center', pixel_pos = True, pos = vp.vector( barWidth/2, self.swy * SCALE_SCENE * 0.22, 0), text = "{:.3f}".format(self.valMin), height = 12, color = barTextColor, box = False, opacity = 0 )
191-
self.barMax = vp.label( canvas = self.colorbar, align = 'center', pixel_pos = True, pos = vp.vector( barWidth/2, (self.swy - 1.2) * SCALE_SCENE, 0), text = "{:.3f}".format(self.valMax), height = 12, color = barTextColor, box = False, opacity = 0 )
204+
self.barMin = vp.label( canvas = self.colorbar, align = 'center', pixel_pos = True, pos = vp.vector( barWidth/2, self.swy * SCALE_SCENE * 0.22, 0), text = "{:.3e}".format(self.valMin), height = 12, color = barTextColor, box = False, opacity = 0 )
205+
self.barMax = vp.label( canvas = self.colorbar, align = 'center', pixel_pos = True, pos = vp.vector( barWidth/2, (self.swy - 1.2) * SCALE_SCENE, 0), text = "{:.3e}".format(self.valMax), height = 12, color = barTextColor, box = False, opacity = 0 )
192206
self.xAx = vp.cylinder( canvas = self.colorbar, pos = axOrigin, axis = vp.vector( 0.8, 0, 0 ), radius = 0.04, color = vp.color.red )
193207
self.yAx = vp.cylinder( canvas = self.colorbar, pos = axOrigin, axis = vp.vector( 0, 0.8, 0 ), radius = 0.04, color = vp.color.green )
194208
self.zAx = vp.cylinder( canvas = self.colorbar, pos = axOrigin, axis = vp.vector( 0, 0, 0 ), radius = 0.04, color = vp.color.blue )
@@ -200,12 +214,32 @@ def makeColorbar( self, doOrnaments = True, colorscale = 'jet', bg = 'default' )
200214
title = MooView.consolidatedTitle + "\n"
201215
self.innerColorbar( title, bg )
202216
if doOrnaments:
217+
for idx, mv in enumerate( MooView.viewList ):
218+
chk = vp.checkbox( bind = mv.toggleView, checked = True, text = mv.title + " ", pos = self.colorbar.title_anchor )
219+
chk.idx = idx
220+
self.cbox.append( chk )
221+
self.colorbar.append_to_title("\n")
203222
self.timeLabel = vp.wtext( text = "Time = 0.000 sec", pos = self.colorbar.title_anchor )
204223
self.sleepLabel = vp.wtext( text = " Frame dt = 0.005 sec", pos = self.colorbar.title_anchor )
205224
self.sleepSlider = vp.slider( pos = self.colorbar.title_anchor, length = 200, bind = self.setSleepTime, min = 0, max = len( sleepTimes ) -1, value = min( len( sleepTimes ), 2 ) )
206225
self.replayButton = vp.button( text = "Start Replay", pos = self.colorbar.title_anchor, bind=self.toggleReplay, disabled = True )
207226
self.colorbar.append_to_title("\n")
208227

228+
def selectCbar( self, idx ):
229+
MooView.colorbarViewIdx = idx
230+
moov = MooView.viewList[idx]
231+
view0 = MooView.viewList[0]
232+
view0.barName.text = view0.cbox[idx].text.replace( '.', '\n' )
233+
view0.barName.text = view0.barName.text.replace( '/', '\n', 1 )
234+
view0.barMin.text = "{:.3e}".format(moov.valMin)
235+
view0.barMax.text = "{:.3e}".format(moov.valMax)
236+
237+
def toggleView( self, cbox ):
238+
for d in self.drawables_:
239+
d.setVisible( cbox.checked )
240+
if cbox.checked: # The colorbar is assigned to selected view:
241+
self.selectCbar( cbox.idx )
242+
209243
def pickObj( self ):
210244
obj = self.scene.mouse.pick
211245
if obj == None:
@@ -285,7 +319,6 @@ def firstDraw( self, mergeDisplays, rotation=0.0, elev=0.0, azim=0.0, center = [
285319
else:
286320
self.doAutoscale()
287321
self.updateAxis()
288-
print( "Self.viewIDX = ", self.viewIdx, ", MOOView.viewIdx = ", MooView.viewIdx )
289322
if self.viewIdx == (MooView.viewIdx-1):
290323
MooView.viewList[0].graph = vp.graph( title = "Graph", xtitle = "Time (s)", ytitle = " Units here", width = 700, fast=False, align = "left" )
291324
MooView.viewList[0].graphPlot1 = vp.gcurve( color = vp.color.blue, interval=-1)
@@ -480,6 +513,7 @@ def __init__( self,
480513
self.valMax = valMax
481514
self.segments = []
482515
self.snapshot = []
516+
self.visible = True
483517
#cmap = plt.get_cmap( self.colormap, lut = NUM_CMAP )
484518
#self.rgb = [ list2vec(cmap(i)[0:3]) for i in range( NUM_CMAP ) ]
485519

@@ -500,7 +534,7 @@ def updateValues( self, simTime ):
500534
indices = np.maximum( np.minimum( scaleVal, NUM_CMAP-0.5), 0.0).astype(int)
501535

502536
# Have to figure how this will work with multiple update rates.
503-
self.snapshot.append( [simTime, indices] )
537+
self.snapshot.append( [simTime, self.val] )
504538

505539
self.displayValues( indices )
506540

@@ -512,7 +546,6 @@ def updateLimits( self, vmin, vmax ):
512546
valMin = self.valMin = vmin
513547
valMax = self.valMax = vmax
514548
scaleVal = NUM_CMAP * (self.val - valMin) / (valMax - valMin)
515-
#indices = scaleVal.ndarray.astype( int )
516549
indices = np.maximum( np.minimum( scaleVal, NUM_CMAP-0.5), 0.0).astype(int)
517550
self.displayValues( indices )
518551

@@ -525,7 +558,9 @@ def displayValues( self, indices ):
525558
def replaySnapshot( self, idx ):
526559
if idx >= len( self.snapshot ):
527560
return 0.0
528-
self.displayValues( self.snapshot[idx][1] )
561+
scaleVal = NUM_CMAP * (self.snapshot[idx][1] - self.valMin) / (self.valMax - self.valMin)
562+
indices = np.maximum( np.minimum( scaleVal, NUM_CMAP-0.5), 0.0).astype(int)
563+
self.displayValues( indices )
529564
return self.snapshot[idx][0] # return frame time
530565

531566
def updateDiameter( self ):
@@ -559,6 +594,13 @@ def plotHistory( self, path, field, graph, plot ):
559594
dat = [[x,y] for x, y in zip( t, v ) ]
560595
plot.data = dat
561596

597+
def setVisible( self, state ):
598+
if self.visible == state:
599+
return
600+
self.visible = state
601+
for s in self.segments:
602+
s.visible = state
603+
562604

563605
#####################################################################
564606

python/rdesigneur/nsdfview.py

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
import moogul
1212
mooViews = []
1313

14+
defaultFieldRange = { 'conc': [0.0, 1.0], 'n': [0, 10], 'Vm': [-0.7, 0.02], 'Ik':[-1e-9, 1e-9], 'Ca':[0.0, 1.0] }
15+
1416
class ObjHandle:
1517
def __init__( self, path ):
1618
self.path = str( path, "utf-8" )
@@ -151,7 +153,7 @@ def getHistory( self, path, field ):
151153
return t, val
152154

153155
#####################################################################
154-
def listElecDatasets( nsdf ):
156+
def printElecDatasetInfo( nsdf ):
155157
elec = nsdf["/data/uniform/%elec"]
156158
for ee in elec:
157159
path = ""
@@ -169,11 +171,11 @@ def listElecDatasets( nsdf ):
169171
shape = dataset.shape
170172
print( "Elec: {:<36} shape=({}), dt={}".format( path, shape, dt ) )
171173

172-
def listDatasets( nsdf ):
174+
def printDatasetInfo( nsdf ):
173175
uniform = nsdf["/data/uniform"]
174176
for uu in uniform:
175177
if uu == "%elec":
176-
listElecDatasets( nsdf )
178+
printElecDatasetInfo( nsdf )
177179
else:
178180
group = uniform[uu]
179181
path = uu[1:]
@@ -186,6 +188,33 @@ def listDatasets( nsdf ):
186188
shape = dataset.shape
187189
print( "Chem: {:<36} shape=({}), dt={}".format( path + '.' + datasetName, shape, dt ) )
188190

191+
def listDatasets( nsdf ):
192+
## Returns list of datasets in path.field format.
193+
ret = []
194+
uniform = nsdf["/data/uniform"]
195+
for uu in uniform:
196+
if uu == "%elec":
197+
elec = nsdf["/data/uniform/%elec"]
198+
for ee in elec:
199+
path = ""
200+
spl = ee.split( '%', 1 )
201+
if spl[0] == "##[ISA=CompartmentBase]":
202+
path += "#"
203+
else:
204+
path = spl[0]
205+
if len( spl ) > 1:
206+
path += '/' + spl[1].replace( '%', '/' )
207+
for field in elec[ee]:
208+
ret.append( path + '.' + field )
209+
else:
210+
group = uniform[uu]
211+
for ch in group:
212+
path = uu[1:] + '/' + ch.replace( '%', '/' )
213+
if path[-2:] == '[]':
214+
path = path[:-2]
215+
for field in group[ch]:
216+
ret.append( path + '.' + field )
217+
return ret
189218

190219
#####################################################################
191220
def main():
@@ -199,23 +228,37 @@ def main():
199228
parser.add_argument( '-l', '--list_datasets', action="store_true", help="List possible datasets available to view." )
200229
args = parser.parse_args()
201230

231+
'''
202232
if (not args.list_datasets) and len( args.viewspec ) == 0:
203233
print( "warning: No viewpsec defined in command line" )
204234
quit()
235+
'''
205236

206237
nsdf = h5py.File( args.NSDF_filename, 'r' )
207238
if args.list_datasets:
208-
listDatasets( nsdf )
239+
printDatasetInfo( nsdf )
209240
quit()
210241

242+
if len( args.viewspec ) == 0:
243+
viewspec = []
244+
datasets = listDatasets( nsdf )
245+
for ds in datasets:
246+
spl = ds.split( '.' )
247+
dispMin, dispMax = defaultFieldRange[ spl[1] ]
248+
viewspec.append( [spl[0], spl[1], dispMin, dispMax ] )
249+
merge_displays = True
250+
else:
251+
viewspec = args.viewspec
252+
merge_displays = args.merge_displays
253+
211254
viewer = []
212-
for vs in args.viewspec:
255+
for vs in viewspec:
213256
viewer.append( makeMoogli( nsdf, vs ) )
214257
dt = viewer[0].drawables_[0].dataWrapper_.dt_
215258
shape = viewer[0].drawables_[0].dataWrapper_.getShape()
216259
numSteps = shape[1]
217260
for v in viewer:
218-
v.firstDraw( args.merge_displays, rotation = args.rotation, colormap = args.colormap, bg = args.background )
261+
v.firstDraw( merge_displays, rotation = args.rotation, colormap = args.colormap, bg = args.background )
219262

220263
simTime = 0.0
221264
for step in range( numSteps ):

0 commit comments

Comments
 (0)