rapidtide 3.0a9__py3-none-any.whl → 3.0a10__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -30,7 +30,6 @@ import pandas as pd
30
30
  import pyqtgraph as pg
31
31
  from nibabel.affines import apply_affine
32
32
  from pyqtgraph.Qt import QtCore, QtGui, QtWidgets
33
- from statsmodels.robust.scale import mad
34
33
 
35
34
  import rapidtide.util as tide_util
36
35
  from rapidtide.Colortables import *
@@ -130,7 +129,86 @@ def _get_parser():
130
129
  return parser
131
130
 
132
131
 
133
- def selectFile():
132
+ def addDataset(
133
+ thisdatafileroot,
134
+ anatname=None,
135
+ geommaskname=None,
136
+ userise=False,
137
+ usecorrout=True,
138
+ useatlas=False,
139
+ forcetr=False,
140
+ forceoffset=False,
141
+ offsettime=0.0,
142
+ ignoredimmatch=False,
143
+ ):
144
+ global currentdataset, thesubjects, whichsubject, datafileroots
145
+ global verbosity
146
+
147
+ print("Loading", thisdatafileroot)
148
+ thissubject = RapidtideDataset(
149
+ "main",
150
+ thisdatafileroot,
151
+ anatname=anatname,
152
+ geommaskname=geommaskname,
153
+ userise=userise,
154
+ usecorrout=usecorrout,
155
+ useatlas=useatlas,
156
+ forcetr=forcetr,
157
+ forceoffset=forceoffset,
158
+ offsettime=offsettime,
159
+ verbose=verbosity,
160
+ )
161
+ if len(thesubjects) > 0:
162
+ # check to see that the dimensions match
163
+ dimmatch, sizematch, spacematch, affinematch = check_rt_spatialmatch(
164
+ thissubject, thesubjects[0]
165
+ )
166
+ if dimmatch or ignoredimmatch:
167
+ thesubjects.append(thissubject)
168
+ else:
169
+ print(f"dataset {thisdatafileroot} does not match loaded data - skipping")
170
+ else:
171
+ thesubjects.append(thissubject)
172
+
173
+ # list the datasets
174
+ for idx, subject in enumerate(thesubjects):
175
+ print(f"subject {idx}: {subject.fileroot}")
176
+
177
+
178
+ def updateFileMenu():
179
+ global thesubjects, whichsubject
180
+ global fileMenu, sel_open
181
+ global sel_files
182
+
183
+ if pyqtversion == 5:
184
+ qactionfunc = QtWidgets.QAction
185
+ else:
186
+ qactionfunc = QtGui.QAction
187
+
188
+ # scrub file menu
189
+ if sel_files is not None:
190
+ for sel_file in sel_files:
191
+ fileMenu.removeAction(sel_file)
192
+ del sel_file
193
+
194
+ # now build it back
195
+ if len(thesubjects) > 0:
196
+ sel_files = []
197
+ for idx, subject in enumerate(thesubjects):
198
+ if idx == whichsubject:
199
+ indicator = "\u2714 "
200
+ else:
201
+ indicator = " "
202
+ sel_files.append(qactionfunc(indicator + subject.fileroot, win))
203
+ sel_files[-1].triggered.connect(partial(selectDataset, idx))
204
+ fileMenu.addAction(sel_files[-1])
205
+
206
+
207
+ def datasetPicker():
208
+ global currentdataset, thesubjects, whichsubject, datafileroots
209
+ global ui, win, defaultdict, overlagGraphicsViews
210
+ global verbosity
211
+
134
212
  mydialog = QtWidgets.QFileDialog()
135
213
  if pyqtversion == 5:
136
214
  options = mydialog.Options()
@@ -146,7 +224,36 @@ def selectFile():
146
224
  datafileroot = str(lagfilename[:bidsstartloc])
147
225
  else:
148
226
  datafileroot = str(lagfilename[: lagfilename.find("lagtimes.nii.gz")])
149
- return datafileroot
227
+ datafileroots.append(datafileroot)
228
+ addDataset(datafileroots[-1])
229
+ whichsubject = len(thesubjects) - 1
230
+ selectDataset(whichsubject)
231
+
232
+ # update the file menu
233
+ updateFileMenu()
234
+
235
+
236
+ def selectDataset(thesubject):
237
+ global currentdataset, thesubjects, whichsubject, datafileroots
238
+ global ui, win, defaultdict, overlagGraphicsViews
239
+ global verbosity, uiinitialized
240
+
241
+ whichsubject = thesubject
242
+ if uiinitialized:
243
+ thesubjects[whichsubject].setfocusregressor(currentdataset.focusregressor)
244
+ thesubjects[whichsubject].setfocusmap(currentdataset.focusmap)
245
+ currentdataset = thesubjects[whichsubject]
246
+ activateDataset(
247
+ currentdataset,
248
+ ui,
249
+ win,
250
+ defaultdict,
251
+ overlayGraphicsViews,
252
+ verbosity=verbosity,
253
+ )
254
+
255
+ # update the file menu
256
+ updateFileMenu()
150
257
 
151
258
 
152
259
  class xyztlocation(QtWidgets.QWidget):
@@ -314,10 +421,17 @@ class xyztlocation(QtWidgets.QWidget):
314
421
  # print('resetting T spinbox values')
315
422
  if self.TPosSpinBox is not None:
316
423
  self.TPosSpinBox.setValue(self.tpos)
424
+ self.TPosSpinBox.setRange(0, self.tdim - 1)
317
425
  if self.TCoordSpinBox is not None:
318
426
  self.TCoordSpinBox.setValue(self.tcoord)
427
+ tllcoord = self.tr2real(0)
428
+ tulcoord = self.tr2real(self.tdim - 1)
429
+ tmin = np.min([tllcoord, tulcoord])
430
+ tmax = np.max([tllcoord, tulcoord])
431
+ self.TCoordSpinBox.setRange(tmin, tmax)
319
432
  if self.TimeSlider is not None:
320
433
  self.TimeSlider.setValue((self.tpos))
434
+ self.TimeSlider.setRange(0, self.tdim - 1)
321
435
  # print('done resetting T spinbox values')
322
436
  self.updatedT.emit()
323
437
 
@@ -349,6 +463,8 @@ class xyztlocation(QtWidgets.QWidget):
349
463
  self.updateXYZValues(emitsignal=emitsignal)
350
464
 
351
465
  def setTpos(self, tpos):
466
+ if tpos > self.tdim:
467
+ tpos = self.tdim
352
468
  if self.tpos != tpos:
353
469
  self.tpos = tpos
354
470
  self.tcoord = self.tr2real(self.tpos)
@@ -469,77 +585,7 @@ class xyztlocation(QtWidgets.QWidget):
469
585
  self.movieTimer.start(int(self.frametime))
470
586
 
471
587
 
472
- """class KeyPressWindow(QtWidgets.QMainWindow):
473
- sigKeyPress = QtCore.pyqtSignal(object)
474
-
475
- def __init__(self, *args, **kwargs):
476
- super().__init__(*args, **kwargs)
477
-
478
- def keyPressEvent(self, ev):
479
- self.sigKeyPress.emit(ev)"""
480
-
481
-
482
- def nextFileButtonPressed():
483
- global currentdataset, thesubjects, whichsubject
484
- global defaultdict, overlayGraphicsViews
485
- numsubjects = len(thesubjects)
486
- whichsubject = (whichsubject + 1) % numsubjects
487
- print(f"subject number set to {whichsubject}")
488
- thesubjects[whichsubject].setfocusregressor(currentdataset.focusregressor)
489
- thesubjects[whichsubject].setfocusmap(currentdataset.focusmap)
490
- currentdataset = thesubjects[whichsubject]
491
- activatedataset(
492
- currentdataset,
493
- ui,
494
- win,
495
- defaultdict,
496
- overlayGraphicsViews,
497
- verbosity=verbosity,
498
- doinit=False,
499
- )
500
- updateRegressor()
501
- updateRegressorSpectrum()
502
- updateUI(
503
- callingfunc="nextFileButtonPressed",
504
- orthoimages=True,
505
- histogram=True,
506
- focusvals=True,
507
- )
508
-
509
-
510
- """def keyPressed(evt):
511
- global currentsubject, thesubjects, whichsubject
512
- global defaultdict, overlayGraphicsViews
513
- numsubjects = len(thesubjects)
514
- if evt.key() == QtCore.Qt.Key.Key_F:
515
- whichsubject = (whichsubject + 1) % numsubjects
516
- print("Key_Up")
517
- elif evt.key() == QtCore.Qt.Key.Key_B:
518
- whichsubject = (whichsubject - 1) % numsubjects
519
- print("Key_Down")
520
- elif evt.key() == QtCore.Qt.Key.Key_Left:
521
- whichsubject = (whichsubject - 1) % numsubjects
522
- print("Key_Left")
523
- elif evt.key() == QtCore.Qt.Key.Key_Right:
524
- whichsubject = (whichsubject + 1) % numsubjects
525
- print("Key_Right")
526
- else:
527
- print(evt.key())
528
- print(f"subject number set to {whichsubject}")
529
- currentdataset = thesubjects[whichsubject]
530
- activatedataset(
531
- currentdataset,
532
- ui,
533
- win,
534
- defaultdict,
535
- overlayGraphicsViews,
536
- verbosity=verbosity,
537
- doinit=False,
538
- )
539
- updateOrthoImages()"""
540
-
541
-
542
- def logstatus(thetextbox, thetext):
588
+ def logStatus(thetextbox, thetext):
543
589
  if pyqtversion == 5:
544
590
  thetextbox.moveCursor(QtGui.QTextCursor.End)
545
591
  thetextbox.insertPlainText(thetext + "\n")
@@ -871,7 +917,7 @@ def updateAveragingMode():
871
917
  print("in updateAveragingMode")
872
918
  if ("atlas" in overlays) and (not atlasaveragingdone):
873
919
  calcAtlasStats()
874
- set_atlasmask()
920
+ setAtlasMask()
875
921
  if ("atlas" in overlays) and False:
876
922
  updateAtlasStats()
877
923
  if averagingmode is not None:
@@ -938,7 +984,7 @@ def MAD_radioButton_clicked(enabled):
938
984
  updateAveragingMode()
939
985
 
940
986
 
941
- def transparency_checkbox_clicked():
987
+ def transparencyCheckboxClicked():
942
988
  global LUT_alpha, LUT_endalpha, ui, overlays, currentdataset
943
989
  global verbosity
944
990
 
@@ -1034,7 +1080,7 @@ def rainbow_radioButton_clicked(enabled):
1034
1080
  updateLUT()
1035
1081
 
1036
1082
 
1037
- def set_mask(maskname):
1083
+ def setMask(maskname):
1038
1084
  global overlays, loadedfuncmaps, ui, atlasaveragingdone, currentdataset
1039
1085
  maskinfodicts = {}
1040
1086
  maskinfodicts["nomask"] = {
@@ -1049,6 +1095,10 @@ def set_mask(maskname):
1049
1095
  "msg": "Using valid fit points as functional mask",
1050
1096
  "label": "Valid mask",
1051
1097
  }
1098
+ maskinfodicts["brainmask"] = {
1099
+ "msg": "Externally provided brain mask",
1100
+ "label": "Brain mask",
1101
+ }
1052
1102
  maskinfodicts["refinemask"] = {
1053
1103
  "msg": "Voxel refinement mask",
1054
1104
  "label": "Refine mask",
@@ -1071,16 +1121,16 @@ def set_mask(maskname):
1071
1121
  overlays[themap].setFuncMask(overlays[maskname].data)
1072
1122
  atlasaveragingdone = False
1073
1123
  updateAveragingMode()
1074
- updateUI(callingfunc=f"set_mask({maskname})", orthoimages=True, histogram=True)
1124
+ updateUI(callingfunc=f"setMask({maskname})", orthoimages=True, histogram=True)
1075
1125
 
1076
1126
 
1077
- def set_atlasmask():
1127
+ def setAtlasMask():
1078
1128
  global overlays, loadedfuncmaps, ui, currentdataset
1079
1129
  print("Using all defined atlas regions as functional mask")
1080
1130
  ui.setMask_Button.setText("Valid mask")
1081
1131
  for themap in currentdataset.loadedfuncmaps:
1082
1132
  overlays[themap].setFuncMask(overlays["atlasmask"].data)
1083
- updateUI(callingfunc="set_atlasmask", orthoimages=True, histogram=True)
1133
+ updateUI(callingfunc="setAtlasMask", orthoimages=True, histogram=True)
1084
1134
 
1085
1135
 
1086
1136
  def overlay_radioButton_clicked(which, enabled):
@@ -1096,6 +1146,8 @@ def overlay_radioButton_clicked(which, enabled):
1096
1146
  currentdataset.setfocusmap(panetomap[which] + "_atlasstat")
1097
1147
  else:
1098
1148
  currentdataset.setfocusmap(panetomap[which])
1149
+ thedispmin = overlays[currentdataset.focusmap].dispmin
1150
+ thedispmax = overlays[currentdataset.focusmap].dispmax
1099
1151
  if verbosity > 1:
1100
1152
  print("currentdataset.focusmap set to ", currentdataset.focusmap)
1101
1153
  if overlays[currentdataset.focusmap].lut_state == gen_gray_state():
@@ -1122,7 +1174,9 @@ def overlay_radioButton_clicked(which, enabled):
1122
1174
  overlays[currentdataset.focusmap].tr,
1123
1175
  overlays[currentdataset.focusmap].toffset,
1124
1176
  )
1125
-
1177
+ overlays[currentdataset.focusmap].dispmin = thedispmin
1178
+ overlays[currentdataset.focusmap].dispmax = thedispmax
1179
+ updateDispLimits()
1126
1180
  updateUI(
1127
1181
  callingfunc="overlay_radioButton_clicked",
1128
1182
  histogram=True,
@@ -1275,7 +1329,7 @@ def printfocusvals():
1275
1329
  global ui, overlays, currentdataset
1276
1330
  global currentloc
1277
1331
  global simfuncFitter
1278
- logstatus(
1332
+ logStatus(
1279
1333
  ui.logOutput,
1280
1334
  "\n\nValues at location "
1281
1335
  + "{0},{1},{2}".format(currentloc.xpos, currentloc.ypos, currentloc.zpos),
@@ -1297,7 +1351,7 @@ def printfocusvals():
1297
1351
  + str(":")
1298
1352
  + "{:.3f}".format(round(focusval, 3))
1299
1353
  )
1300
- logstatus(ui.logOutput, outstring)
1354
+ logStatus(ui.logOutput, outstring)
1301
1355
  else:
1302
1356
  if focusval > 0.0:
1303
1357
  if simfuncFitter is not None:
@@ -1308,7 +1362,7 @@ def printfocusvals():
1308
1362
  + str(":\n\t ")
1309
1363
  + failstring.replace(", ", "\n\t ")
1310
1364
  )
1311
- logstatus(ui.logOutput, outstring)
1365
+ logStatus(ui.logOutput, outstring)
1312
1366
  else:
1313
1367
  outstring = (
1314
1368
  indentstring
@@ -1316,7 +1370,7 @@ def printfocusvals():
1316
1370
  + str(":")
1317
1371
  + str(currentdataset.atlaslabels[int(focusval) - 1])
1318
1372
  )
1319
- logstatus(ui.logOutput, outstring)
1373
+ logStatus(ui.logOutput, outstring)
1320
1374
 
1321
1375
 
1322
1376
  def regressor_radioButton_clicked(theregressor, enabled):
@@ -1326,15 +1380,22 @@ def regressor_radioButton_clicked(theregressor, enabled):
1326
1380
  updateRegressorSpectrum()
1327
1381
 
1328
1382
 
1329
- def activatedataset(
1330
- currentdataset, ui, win, defaultdict, overlayGraphicsViews, verbosity=0, doinit=False
1331
- ):
1383
+ def activateDataset(currentdataset, ui, win, defaultdict, overlayGraphicsViews, verbosity=0):
1332
1384
  global regressors, overlays
1333
1385
  global mainwin
1334
1386
  global xdim, ydim, zdim, tdim, xpos, ypos, zpos, tpos
1335
1387
  global timeaxis
1336
1388
  global usecorrout
1337
1389
  global orthoimagedict
1390
+ global panesinitialized, uiinitialized
1391
+ global currentloc
1392
+
1393
+ if uiinitialized:
1394
+ currentloc.xdim = currentdataset.xdim
1395
+ currentloc.ydim = currentdataset.ydim
1396
+ currentloc.xdim = currentdataset.zdim
1397
+ currentloc.tdim = currentdataset.tdim
1398
+ currentloc.setTpos(currentloc.tpos)
1338
1399
 
1339
1400
  if verbosity > 1:
1340
1401
  print("getting regressors")
@@ -1508,7 +1569,7 @@ def activatedataset(
1508
1569
 
1509
1570
  if verbosity > 1:
1510
1571
  print("focusmap is:", currentdataset.focusmap, "bgmap is:", bgmap)
1511
- if doinit:
1572
+ if not panesinitialized:
1512
1573
  if bgmap is None:
1513
1574
  mainwin = OrthoImageItem(
1514
1575
  overlays[currentdataset.focusmap],
@@ -1533,12 +1594,12 @@ def activatedataset(
1533
1594
  else:
1534
1595
  mainwin.setMap(overlays[currentdataset.focusmap])
1535
1596
 
1536
- if verbosity > 1:
1537
- print("loading panes")
1538
1597
  availablepanes = len(overlayGraphicsViews)
1598
+ if verbosity > 0:
1599
+ print(f"loading {availablepanes} available panes")
1539
1600
  numnotloaded = 0
1540
1601
  numloaded = 0
1541
- if doinit:
1602
+ if not panesinitialized:
1542
1603
  orthoimagedict = {}
1543
1604
  for idx, themap in enumerate(currentdataset.dispmaps):
1544
1605
  if overlays[themap].display_state:
@@ -1546,11 +1607,15 @@ def activatedataset(
1546
1607
  (numloaded > availablepanes - 2) and (themap != "corrout")
1547
1608
  ):
1548
1609
  if verbosity > 1:
1549
- print("skipping map ", themap, "(", idx, "): out of display panes")
1610
+ print(
1611
+ f"skipping map {themap}({idx}): out of display panes ({numloaded=}, {availablepanes=})"
1612
+ )
1550
1613
  numnotloaded += 1
1551
1614
  else:
1552
1615
  if verbosity > 1:
1553
- print("loading map ", themap, "(", idx, ") into pane ", numloaded)
1616
+ print(
1617
+ f"loading map {themap}=({idx}) into pane {numloaded} of {availablepanes}"
1618
+ )
1554
1619
  if bgmap is None:
1555
1620
  loadpane(
1556
1621
  overlays[themap],
@@ -1572,7 +1637,7 @@ def activatedataset(
1572
1637
  bgmap=overlays[bgmap],
1573
1638
  sm_imgsize=sm_imgsize,
1574
1639
  )
1575
- numloaded += 1
1640
+ numloaded += 1
1576
1641
  else:
1577
1642
  if verbosity > 1:
1578
1643
  print("not loading map ", themap, "(", idx, "): display_state is False")
@@ -1588,6 +1653,21 @@ def activatedataset(
1588
1653
  if numnotloaded > 0:
1589
1654
  print("WARNING:", numnotloaded, "maps could not be loaded - not enough panes")
1590
1655
 
1656
+ # record that we've been through once
1657
+ panesinitialized = True
1658
+
1659
+ if uiinitialized:
1660
+ # update the windows
1661
+ updateUI(
1662
+ callingfunc="activateDataset",
1663
+ orthoimages=True,
1664
+ histogram=True,
1665
+ )
1666
+
1667
+ # update the regressor
1668
+ updateRegressor()
1669
+ updateRegressorSpectrum()
1670
+
1591
1671
 
1592
1672
  def loadpane(
1593
1673
  themap,
@@ -1627,6 +1707,7 @@ def loadpane(
1627
1707
  def tidepool(args):
1628
1708
  global vLine
1629
1709
  global ui, win
1710
+ global fileMenu, sel_open, sel_files
1630
1711
  global movierunning
1631
1712
  global focusmap, bgmap, focusregressor
1632
1713
  global maps
@@ -1643,9 +1724,10 @@ def tidepool(args):
1643
1724
  global imageadj
1644
1725
  global harvestcolormaps
1645
1726
  global atlasaveragingdone
1646
- global currentdataset, thesubjects, whichsubject
1727
+ global currentdataset, thesubjects, whichsubject, datafileroots
1647
1728
  global defaultdict, overlayGraphicsViews
1648
1729
  global verbosity
1730
+ global panesinitialized, uiinitialized
1649
1731
  global simfuncFitter
1650
1732
  global simfunc_ax, simfuncCurve, simfuncfitCurve, simfuncTLine, simfuncPeakMarker, simfuncCurvePoint, simfuncCaption
1651
1733
 
@@ -1671,6 +1753,10 @@ def tidepool(args):
1671
1753
  tpos = 0
1672
1754
  verbosity = 0
1673
1755
  simfuncFitter = None
1756
+ datafileroots = []
1757
+ panesinitialized = False
1758
+ uiinitialized = False
1759
+ sel_files = None
1674
1760
 
1675
1761
  if pyqtversion == 5:
1676
1762
  if args.uistyle == "normal":
@@ -1702,7 +1788,6 @@ def tidepool(args):
1702
1788
  else:
1703
1789
  geommaskname = None
1704
1790
 
1705
- datafileroots = []
1706
1791
  if args.datafileroot is not None:
1707
1792
  print("using ", args.datafileroot, " as the root file name list")
1708
1793
  datafileroots = args.datafileroot
@@ -1729,34 +1814,25 @@ def tidepool(args):
1729
1814
  # make the main window
1730
1815
  app = QtWidgets.QApplication([])
1731
1816
  print("setting up output window")
1732
- # win = KeyPressWindow()
1733
- # win.sigKeyPress.connect(keyPressed)
1734
1817
  win = QtWidgets.QMainWindow()
1735
1818
  ui = uiTemplate.Ui_MainWindow()
1736
1819
  ui.setupUi(win)
1737
1820
  win.show()
1738
1821
  win.setWindowTitle("TiDePool")
1739
1822
 
1740
- """"# create the menu bar
1823
+ # create the menu bar
1741
1824
  print("creating menu bar")
1742
1825
  menuBar = win.menuBar()
1743
- fileMenu = QtWidgets.QMenu(win)
1826
+ fileMenu = menuBar.addMenu("File")
1744
1827
  if pyqtversion == 5:
1745
1828
  qactionfunc = QtWidgets.QAction
1746
1829
  else:
1747
1830
  qactionfunc = QtGui.QAction
1748
- sel_open = qactionfunc("Open", win)
1749
- sel_open.triggered.connect(selectFile())
1831
+ sel_open = qactionfunc("Add dataset...", win)
1832
+ sel_open.triggered.connect(datasetPicker)
1750
1833
  fileMenu.addAction(sel_open)
1751
- win.setMenuBar(menuBar)
1752
- print("done creating menu bar")"""
1753
-
1754
- # get inputfile root name if necessary
1755
- if len(datafileroots) == 0:
1756
- datafileroots.append(selectFile())
1757
- if len(datafileroots) == 0:
1758
- print("No input file specified - exiting.")
1759
- sys.exit()
1834
+ fileMenu.addSeparator()
1835
+ print("done creating menu bar")
1760
1836
 
1761
1837
  # wire up the ortho image windows for mouse interaction
1762
1838
  vb_colorbar = pg.ViewBox(enableMouse=False)
@@ -1784,6 +1860,10 @@ def tidepool(args):
1784
1860
  if harvestcolormaps:
1785
1861
  ui.largeimage_horizontalLayout.addWidget(imageadj)
1786
1862
 
1863
+ if args.uistyle == "big":
1864
+ extramaps = True
1865
+ else:
1866
+ extramaps = False
1787
1867
  defaultdict = {
1788
1868
  "lagmask": {
1789
1869
  "colormap": gen_gray_state(),
@@ -1815,6 +1895,12 @@ def tidepool(args):
1815
1895
  "display": False,
1816
1896
  "funcmask": None,
1817
1897
  },
1898
+ "brainmask": {
1899
+ "colormap": gen_gray_state(),
1900
+ "label": "Brain mask",
1901
+ "display": False,
1902
+ "funcmask": None,
1903
+ },
1818
1904
  "p_lt_0p050_mask": {
1819
1905
  "colormap": gen_gray_state(),
1820
1906
  "label": "p<0.05",
@@ -1890,12 +1976,42 @@ def tidepool(args):
1890
1976
  "MTT": {
1891
1977
  "colormap": gen_spectrum_state(),
1892
1978
  "label": "MTT",
1893
- "display": True,
1979
+ "display": extramaps,
1894
1980
  "funcmask": "p_lt_0p050_mask",
1895
1981
  },
1896
1982
  "R2": {
1897
1983
  "colormap": gen_thermal_state(),
1898
- "label": "Fit R2",
1984
+ "label": "GLM Fit R2",
1985
+ "display": extramaps,
1986
+ "funcmask": "p_lt_0p050_mask",
1987
+ },
1988
+ "CoV": {
1989
+ "colormap": gen_thermal_state(),
1990
+ "label": "Coefficient of variation",
1991
+ "display": True,
1992
+ "funcmask": "p_lt_0p050_mask",
1993
+ },
1994
+ "confoundR2": {
1995
+ "colormap": gen_thermal_state(),
1996
+ "label": "Confound Fit R2",
1997
+ "display": extramaps,
1998
+ "funcmask": "p_lt_0p050_mask",
1999
+ },
2000
+ "varBefore": {
2001
+ "colormap": gen_thermal_state(),
2002
+ "label": "LFO variance before GLM",
2003
+ "display": extramaps,
2004
+ "funcmask": "p_lt_0p050_mask",
2005
+ },
2006
+ "varAfter": {
2007
+ "colormap": gen_thermal_state(),
2008
+ "label": "LFO variance after GLM",
2009
+ "display": extramaps,
2010
+ "funcmask": "p_lt_0p050_mask",
2011
+ },
2012
+ "varChange": {
2013
+ "colormap": gen_thermal_state(),
2014
+ "label": "LFO variance decrease %",
1899
2015
  "display": True,
1900
2016
  "funcmask": "p_lt_0p050_mask",
1901
2017
  },
@@ -1908,7 +2024,7 @@ def tidepool(args):
1908
2024
  "fitNorm": {
1909
2025
  "colormap": gen_thermal_state(),
1910
2026
  "label": "fitNorm",
1911
- "display": True,
2027
+ "display": False,
1912
2028
  "funcmask": "p_lt_0p050_mask",
1913
2029
  },
1914
2030
  "gaussout": {
@@ -1920,7 +2036,7 @@ def tidepool(args):
1920
2036
  "failimage": {
1921
2037
  "colormap": gen_spectrum_state(),
1922
2038
  "label": "Fit failure reason",
1923
- "display": False,
2039
+ "display": extramaps,
1924
2040
  "funcmask": None,
1925
2041
  },
1926
2042
  "anatomic": {
@@ -1944,7 +2060,7 @@ def tidepool(args):
1944
2060
  "neglog10p": {
1945
2061
  "colormap": gen_thermal_state(),
1946
2062
  "label": "Correlation fit -log10p",
1947
- "display": False,
2063
+ "display": extramaps,
1948
2064
  "funcmask": "None",
1949
2065
  },
1950
2066
  "delayoffset": {
@@ -1999,7 +2115,7 @@ def tidepool(args):
1999
2115
  ui.rainbow_radioButton.clicked.connect(rainbow_radioButton_clicked)
2000
2116
 
2001
2117
  # wire up the transparency checkbox
2002
- ui.transparency_checkBox.stateChanged.connect(transparency_checkbox_clicked)
2118
+ ui.transparency_checkBox.stateChanged.connect(transparencyCheckboxClicked)
2003
2119
 
2004
2120
  overlaybuttons = [
2005
2121
  ui.overlay_radioButton_01,
@@ -2058,13 +2174,14 @@ def tidepool(args):
2058
2174
  theview.hide()
2059
2175
 
2060
2176
  # define things for the popup mask menu
2061
- popMenu = QtWidgets.QMenu(win)
2177
+ popMaskMenu = QtWidgets.QMenu(win)
2062
2178
  if pyqtversion == 5:
2063
2179
  qactionfunc = QtWidgets.QAction
2064
2180
  else:
2065
2181
  qactionfunc = QtGui.QAction
2066
2182
  sel_nomask = qactionfunc("No mask", win)
2067
2183
  sel_lagmask = qactionfunc("Valid fit", win)
2184
+ sel_brainmask = qactionfunc("Externally provided brain mask", win)
2068
2185
  sel_refinemask = qactionfunc("Voxels used in refine", win)
2069
2186
  sel_meanmask = qactionfunc("Voxels used in mean regressor calculation", win)
2070
2187
  sel_preselectmask = qactionfunc(
@@ -2075,24 +2192,38 @@ def tidepool(args):
2075
2192
  sel_0p005 = qactionfunc("p<0.005", win)
2076
2193
  sel_0p001 = qactionfunc("p<0.001", win)
2077
2194
 
2078
- sel_nomask.triggered.connect(partial(set_mask, "nomask"))
2079
- sel_lagmask.triggered.connect(partial(set_mask, "lagmask"))
2080
- sel_refinemask.triggered.connect(partial(set_mask, "refinemask"))
2081
- sel_meanmask.triggered.connect(partial(set_mask, "meanmask"))
2082
- sel_preselectmask.triggered.connect(partial(set_mask, "preselectmask"))
2083
- sel_0p05.triggered.connect(partial(set_mask, "p_lt_0p050_mask"))
2084
- sel_0p01.triggered.connect(partial(set_mask, "p_lt_0p010_mask"))
2085
- sel_0p005.triggered.connect(partial(set_mask, "p_lt_0p005_mask"))
2086
- sel_0p001.triggered.connect(partial(set_mask, "p_lt_0p001_mask"))
2087
- popMenu.addAction(sel_nomask)
2195
+ sel_nomask.triggered.connect(partial(setMask, "nomask"))
2196
+ sel_lagmask.triggered.connect(partial(setMask, "lagmask"))
2197
+ sel_brainmask.triggered.connect(partial(setMask, "brainmask"))
2198
+ sel_refinemask.triggered.connect(partial(setMask, "refinemask"))
2199
+ sel_meanmask.triggered.connect(partial(setMask, "meanmask"))
2200
+ sel_preselectmask.triggered.connect(partial(setMask, "preselectmask"))
2201
+ sel_0p05.triggered.connect(partial(setMask, "p_lt_0p050_mask"))
2202
+ sel_0p01.triggered.connect(partial(setMask, "p_lt_0p010_mask"))
2203
+ sel_0p005.triggered.connect(partial(setMask, "p_lt_0p005_mask"))
2204
+ sel_0p001.triggered.connect(partial(setMask, "p_lt_0p001_mask"))
2205
+ popMaskMenu.addAction(sel_nomask)
2088
2206
  numspecial = 0
2089
2207
 
2090
- def on_context_menu(point):
2208
+ # configure the mask selection popup menu
2209
+ def on_mask_context_menu(point):
2091
2210
  # show context menu
2092
- popMenu.exec(ui.setMask_Button.mapToGlobal(point))
2211
+ popMaskMenu.exec(ui.setMask_Button.mapToGlobal(point))
2093
2212
 
2094
2213
  ui.setMask_Button.setContextMenuPolicy(QtCore.Qt.ContextMenuPolicy.CustomContextMenu)
2095
- ui.setMask_Button.customContextMenuRequested.connect(on_context_menu)
2214
+ ui.setMask_Button.customContextMenuRequested.connect(on_mask_context_menu)
2215
+
2216
+ # configure the file selection popup menu
2217
+ def on_file_context_menu(point):
2218
+ # show context menu
2219
+ popMaskMenu.exec(ui.setFile_Button.mapToGlobal(point))
2220
+
2221
+ try:
2222
+ ui.setFile_Button.setContextMenuPolicy(QtCore.Qt.ContextMenuPolicy.CustomContextMenu)
2223
+ ui.setFile_Button.customContextMenuRequested.connect(on_file_context_menu)
2224
+ setfilebuttonexists = True
2225
+ except AttributeError:
2226
+ setfilebuttonexists = False
2096
2227
 
2097
2228
  # wire up the regressor selection radio buttons
2098
2229
  regressorbuttons = [
@@ -2116,52 +2247,41 @@ def tidepool(args):
2116
2247
 
2117
2248
  # read in all the datasets
2118
2249
  thesubjects = []
2119
-
2120
- print("loading datasets...")
2121
- for thisdatafileroot in datafileroots:
2122
- print("Loading", thisdatafileroot)
2123
- thissubject = RapidtideDataset(
2124
- "main",
2125
- thisdatafileroot,
2126
- anatname=anatname,
2127
- geommaskname=geommaskname,
2128
- userise=userise,
2129
- usecorrout=usecorrout,
2130
- useatlas=useatlas,
2131
- forcetr=forcetr,
2132
- forceoffset=forceoffset,
2133
- offsettime=offsettime,
2134
- verbose=verbosity,
2135
- )
2136
- if len(thesubjects) > 0:
2137
- # check to see that the dimensions match
2138
- dimmatch, sizematch, spacematch, affinematch = check_rt_spatialmatch(
2139
- thissubject, thesubjects[0]
2140
- )
2141
- if dimmatch or args.ignoredimmatch:
2142
- thesubjects.append(thissubject)
2143
- else:
2144
- print(f"dataset {thisdatafileroot} does not match loaded data - skipping")
2145
- else:
2146
- thesubjects.append(thissubject)
2147
2250
  whichsubject = 0
2148
- currentdataset = thesubjects[whichsubject]
2149
- activatedataset(
2150
- currentdataset,
2151
- ui,
2152
- win,
2153
- defaultdict,
2154
- overlayGraphicsViews,
2155
- verbosity=verbosity,
2156
- doinit=True,
2157
- )
2251
+ if len(datafileroots) > 0:
2252
+ print("loading prespecified datasets...")
2253
+ for thisdatafileroot in datafileroots:
2254
+ addDataset(
2255
+ thisdatafileroot,
2256
+ anatname=anatname,
2257
+ geommaskname=geommaskname,
2258
+ userise=userise,
2259
+ usecorrout=usecorrout,
2260
+ useatlas=useatlas,
2261
+ forcetr=forcetr,
2262
+ forceoffset=forceoffset,
2263
+ offsettime=offsettime,
2264
+ ignoredimmatch=args.ignoredimmatch,
2265
+ )
2266
+ currentdataset = thesubjects[whichsubject]
2267
+ activateDataset(
2268
+ currentdataset,
2269
+ ui,
2270
+ win,
2271
+ defaultdict,
2272
+ overlayGraphicsViews,
2273
+ verbosity=verbosity,
2274
+ )
2275
+ # update the file menu
2276
+ updateFileMenu()
2277
+ else:
2278
+ # get inputfile root name if necessary
2279
+ datasetPicker()
2158
2280
 
2159
- for thebutton in [ui.nextFile_Button]:
2160
- if len(thesubjects) == 1:
2161
- thebutton.setDisabled(True)
2162
- thebutton.hide()
2163
- else:
2164
- thebutton.clicked.connect(nextFileButtonPressed)
2281
+ # check to see that something is loaded
2282
+ if len(thesubjects) == 0:
2283
+ print("No input datasets specified - exiting.")
2284
+ sys.exit()
2165
2285
 
2166
2286
  # wire up the display range controls
2167
2287
  ui.resetDispLimits_Button.clicked.connect(resetDispLimits)
@@ -2263,29 +2383,32 @@ def tidepool(args):
2263
2383
  if verbosity > 1:
2264
2384
  print("loadedfuncmasks", currentdataset.loadedfuncmasks)
2265
2385
  if len(currentdataset.loadedfuncmasks) > 0:
2266
- popMenu.addSeparator()
2386
+ popMaskMenu.addSeparator()
2267
2387
  if "lagmask" in currentdataset.loadedfuncmasks:
2268
- popMenu.addAction(sel_lagmask)
2388
+ popMaskMenu.addAction(sel_lagmask)
2389
+ numspecial += 1
2390
+ if "brainmask" in currentdataset.loadedfuncmasks:
2391
+ popMaskMenu.addAction(sel_brainmask)
2269
2392
  numspecial += 1
2270
2393
  if "refinemask" in currentdataset.loadedfuncmasks:
2271
- popMenu.addAction(sel_refinemask)
2394
+ popMaskMenu.addAction(sel_refinemask)
2272
2395
  numspecial += 1
2273
2396
  if "meanmask" in currentdataset.loadedfuncmasks:
2274
- popMenu.addAction(sel_meanmask)
2397
+ popMaskMenu.addAction(sel_meanmask)
2275
2398
  numspecial += 1
2276
2399
  if "preselectmask" in currentdataset.loadedfuncmasks:
2277
- popMenu.addAction(sel_preselectmask)
2400
+ popMaskMenu.addAction(sel_preselectmask)
2278
2401
  numspecial += 1
2279
2402
  if numspecial > 0:
2280
- popMenu.addSeparator()
2403
+ popMaskMenu.addSeparator()
2281
2404
  if "p_lt_0p050_mask" in currentdataset.loadedfuncmasks:
2282
- popMenu.addAction(sel_0p05)
2405
+ popMaskMenu.addAction(sel_0p05)
2283
2406
  if "p_lt_0p010_mask" in currentdataset.loadedfuncmasks:
2284
- popMenu.addAction(sel_0p01)
2407
+ popMaskMenu.addAction(sel_0p01)
2285
2408
  if "p_lt_0p005_mask" in currentdataset.loadedfuncmasks:
2286
- popMenu.addAction(sel_0p005)
2409
+ popMaskMenu.addAction(sel_0p005)
2287
2410
  if "p_lt_0p001_mask" in currentdataset.loadedfuncmasks:
2288
- popMenu.addAction(sel_0p001)
2411
+ popMaskMenu.addAction(sel_0p001)
2289
2412
 
2290
2413
  # initialize the location picker
2291
2414
  global currentloc
@@ -2331,5 +2454,7 @@ def tidepool(args):
2331
2454
 
2332
2455
  updateUI(callingfunc="main thread", orthoimages=True, focusvals=True)
2333
2456
  updateRegressor()
2457
+ updateRegressorSpectrum()
2458
+ uiinitialized = True
2334
2459
 
2335
2460
  QtWidgets.QApplication.instance().exec()