def OnTimer(self, event): self.adata = LAD.Afni1D('motion.1D', verb=self.verb) #print '-- TR: %d' % self.adata.mat[0][0] if self.adata.mat[0][0] != self.TRNumber: self.eucMotion = self.adata.mat[0][1] self.set_TR(self.adata.mat[0][0]) self.motiondetectionacc = self.motiondetectionacc + self.eucMotion self.MotionConfig.set_text('Accumulated motion: %2.2f' % float(self.motiondetectionacc)) print '-- Euclidean Motion: %f' % self.adata.mat[0][1] self.plot_data(self.eucMotion) if self.TRNumber == 37 and self.motiondetectionacc < (self.TRESHOLDRT*17): self.NMotionsConfig.set_text('Head motion trend: PASS') elif self.TRNumber == 37 and self.motiondetectionacc > (self.TRESHOLDRT*17): self.NMotionsConfig.set_text('Head motion trend: FAIL') elif self.TRNumber < 37: self.NMotionsConfig.set_text('Head motion trend: Analyzing...') if self.TRNumber <= 2: self.textExcessive.set_visible(False) self.ACCmotionstatus = 0 self.rectangleACC.set_y(self.ACCmotionstatus/20.0) self.MotionDetected = 0 self.NMotionText.set_text("%3d" % self.ACCmotionstatus) self.motiondetectionacc = 0 self.MotionConfig.set_text('Accumulated motion: 0.00') self.NMotionsConfig.set_text('Head motion trend: Waiting...') if self.MotionDetected == 1: #self.counter += 1 #if self.counter < 10: self.textExcessive.set_visible(True)
def set_censor_arr(self): self.censor_width = self.all_x[1] - self.all_x[0] # add to this in different forms, where True values mean # censoring is flagged to have occured cen_arr = [False] * self.npts # combine all strings of censor lists: # ... from user-entered strings if self.censor_in_trs: maxind = self.npts - 1 for ttt in self.censor_in_trs: ll = au.decode_1D_ints(ttt, imax=maxind) for ii in ll: cen_arr[ii] = True # ... from user-entered files if self.censor_in_files: for fff in self.censor_in_files: x = LAD.Afni1D(fff) if x.nt != self.npts : sys.exit("** ERROR: len of censor file {} ({}) does not " "match Npts={}".format(fff, x.nt, self.npts)) for i in range(self.npts): val = x.mat[0][i] if not(val): cen_arr[i] = True # And finally store the list of xvals to censor self.ncensor = cen_arr.count(True) if self.ncensor : for i in range(self.npts): if cen_arr[i]: self.censor_arr.append(self.all_x[i])
def gershgoriny_dist_from_I_aff12_file(fname): '''Input a file of an aff12 matrix (either MATRIX or ONELINE format). Must have exactly 12 numbers. See help of 'gershgoriny_dist_from_I_aff12()' for what happens next. Output is one scalar number. ''' # read in, and get into proper shape with a transposition x = LAD.Afni1D(fname) x.transpose() if len(x.mat) == 3 and len(x.mat[0]) == 4: # then we have a MATRIX-format aff12.1D param already, and we # are all set to go out = gershgoriny_dist_from_I_aff12(x.mat) elif len(x.mat) == 1 and len(x.mat[0]) == 12: # then we have a ONELINE-format aff12.1D param, and we have to # reshape it M = [[0.0] * 4 for row in range(3)] for i in range(3): M[i][:] = x.mat[0][4 * i:4 * (i + 1)] dist_gershgorin = gershgoriny_dist_from_I_aff12(M) else: print("** ERROR: Input matrix in {} has some problems! Doesn't look\n" " like an aff12.1D format (ONELINE, 1x12; MATRIX, 3x4)\n" "".format(fname)) sys.exit(3) return dist_gershgorin
def __init__(self): self.valid_opts = None self.user_opts = None self.data_choice = 'motion' self.TR_data = [] # store computed TR data self.verb = 1 self.serial_port = None # serial port (filename) # lib_realtime.py class instances self.RTI = None # real-time interface RTInterface self.SER = None # serial port interface Serial # data choice parameters self.dc_params = [] # demo attributes self.show_demo_data = 0 self.demo_frame = None # for demo plot self.wx_app = None # wx App for demo plot self.adata = LAD.Afni1D('motion.1D', verb=self.verb) self.valid_opts = self.init_options() self.Currentmotion = numpy.zeros(6) self.Previousmotion = numpy.zeros(6)
def process_matlab_file(self, fname, index=0): """process matlab files """ try: import scipy.io import numpy except: print '** missing library: scipy.io' print ' (please install scipy)' return 1 if not os.path.isfile(fname): print "** missing file '%s'" % fname return 1 mfile = scipy.io.loadmat(fname) if mfile == None: return 1 # prepare output prefix prefix = self.prefix if prefix != '' and len(self.infiles) > 1: prefix = '%s.%02d' % (self.prefix, index + 1) klist = [key for key in mfile.keys() if key[0:2] != '__'] maxlen = max([len(key) for key in klist]) if self.verb: if self.verb > 1: print print '-- file %s has %d key(s)' % (fname, len(klist)) for key in klist: obj = mfile[key] if self.verb > 1: print(' %-*s %s' % (maxlen, key, type(obj))), if type(obj) is numpy.ndarray: print ' shape %s' % str(obj.shape) else: print # maybe write any numpy data if prefix != '' and type(obj) is numpy.ndarray: # convert object to Afni1D and transpose olist = obj.tolist() adata = LD.Afni1D(from_mat=1, matrix=olist, verb=self.verb) adata.transpose() # if model, break apart, else just write if key == 'model' and adata.nvec >= 2: self.write_model_files(adata, prefix) else: ofile = '%s.%s.1D' % (prefix, key) print '++ writing ndarry to %s' % ofile adata.write(ofile, overwrite=self.overwrite) return 0
def write_model_files(self, adata, prefix): """break model matrix into many 1D files """ if adata.nvec < 1: return 0 for ind in range(adata.nvec): avec = LD.Afni1D(from_mat=1, matrix=[adata.mat[ind]], verb=self.verb) ofile = '%s.model.%02d.1D' % (prefix, ind + 1) print '++ writing model file %s' % ofile avec.write(ofile, overwrite=self.overwrite) return 0
def create_all_x(self): '''Populate abscissa/x-values depending on what the user entered, either a filename containing values or a stop/start/step rule. Input ----- iopts : object containing all the info Return ------ *nothing returned* : the 'iopts.xvals' array is populated ''' if self.xfile : dat = LAD.Afni1D(fff) x = dat.mat[0] if x.nvec > 1 : sys.exit("** ERROR reading in xvalue file: too many columns.\n" " Specify just one!") elif self.xvals: i = 0 A = self.xvals[0] x = [A] while A < self.xvals[1] and i < MAXLEN: A+= self.xvals[2] x.append(A) i+=1 else: print("*+ No input x-axis; making values based on length of data: " "[0..{}]".format(self.npts - 1)) x = [] for i in range(self.npts): x.append(i) self.all_x = x
def create_all_y(self): '''Populate ordinate/y-values from one or more filenames of y-values entered. ''' ys = [] for fff in self.infiles: x = LAD.Afni1D(fff) print("++ FOR: {}: {} arrays with {} pts".format(fff, x.nvec, x.nt)) # this is done a bit clunkily here at the mo b/c; used to # read in as AfniData, which was relatively backwards; can # simplify later... for i in range(x.nvec): p = [] for j in range(x.nt): p.append(x.mat[i][j]) ys.append(p) self.all_y = ys self.set_npts() self.set_ndsets() self.set_y_minmax()
def __init__(self, title='', verb=1): #Make a figure and axes with dimensions as desired------------------------------------ wx.Frame.__init__(self, None, -1, title, size=(400,300),style=wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER) #400x300 window self.verb = verb self.figure = Figure(figsize=(5,5)) self.AxisRT = self.figure.add_axes([0.1, 0.05, 0.2, 0.6]) self.canvas = FigureCanvas(self, -1, self.figure) self.sizer = wx.BoxSizer(wx.VERTICAL) self.sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW) self.SetSizer(self.sizer) self.Fit() self.ax = None pic = wx.Icon("brain.ico", wx.BITMAP_TYPE_ICO) self.SetIcon(pic) #Maximum euclidean norm of derivate of motion self.TRESHOLDRT = 0.9 #Number of motions that is acceptable self.NMotion = 15 #Number of TR's self.TRNumber = 4 #Number of motions in the exam self.ACCmotionstatus = 0 #Euclidean motion of derivative of motion values self.eucMotion = 0 #open file that contain data to display self.adata = LAD.Afni1D('motion.1D', verb=self.verb) #write none values to file self.adata.mat[0][0] = 0 self.adata.mat[0][1] = 0 self.adata.write('motion.1D',overwrite=1) #Variable that indicate when excessive motion is detected self.MotionDetected = 0 #counter to blink Excessive motion text self.counter = 0 #Color Map self.colobarRT = 0 #Maximum and Minimun Values self.normRT = 0 #Boundaries self.bounds = 0 #Real Time Bargraph self.bargraphRT = 0 #rectangle to fill real time bar self.rectangleRT = 0 #Color map to accumulative head motion self.colobarACC = 0 #Maximun and minimun values of acc head motion self.normACC = 0 #Boudn of acc bar self.boundsACC = 0 #Accumulative bar self.bargraphACC = 0 #Accumulated motion self.motiondetectionacc = 0 #CREATE SOME TEXTS-------------------------------------------------------------------- self.AxisRT.text(-0.4, 1.48, 'fMRI Motion Viewer', fontdict=fonttitle) self.MotionConfig = self.AxisRT.text(-0.4, 1.4, 'Accumulated motion: 0.00', fontdict=fontmediun) self.NMotionsConfig = self.AxisRT.text(-0.4, 1.32,'Head motion trend: Waiting...', fontdict=fontmediun) self.AxisRT.text(-0.1, 1.15, 'RT Head Motion', fontdict=fontmediun) self.MotionLimitText = self.AxisRT.text(0.12, 1, "- - -", fontdict=fontTRNumber) self.AxisRT.text(2.8, 1.31, 'TR', fontdict=fontmediun) self.TRNumberText = self.AxisRT.text(3.3, 1.3, self.TRNumber, fontdict=fontTR) # #REAL TIME HEAD MOTION BAR------------------------------------------------------------ #self.colobarRT = mpl.colors.ListedColormap(['c', 'y', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r']) #self.normRT = mpl.colors.Normalize(vmin=0, vmax=5.0) #self.bounds = [0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4.0, 4.5, 5] #self.normRT = mpl.colors.BoundaryNorm(self.bounds, self.colobarRT.N) #self.bargraphRT = mpl.colorbar.ColorbarBase(self.AxisRT, self.colobarRT, # self.normRT, # orientation='vertical') #self.bargraphRT.set_label('Real Time Head Motion') #Rectangle to fill the bar------------------------------------------------------------ self.rectangleRT = Rectangle((0.0, 0), 1, 1, facecolor='white') currentAxis = self.figure.gca() currentAxis.add_patch(self.rectangleRT) #ACCUMULATIVE HEAD MOTION BAR--------------------------------------------------------- self.AxisACC = self.figure.add_axes([0.6, 0.05, 0.2, 0.6]) #self.colobarACC = mpl.colors.ListedColormap(['c', 'y', 'r']) #self.normACC = mpl.colors.Normalize(vmin=0, vmax=25) #self.boundsACC = [0, 5, 10, 15, 20, 25] #self.normACC = mpl.colors.BoundaryNorm(self.boundsACC, self.colobarACC.N) #self.bargraphACC = mpl.colorbar.ColorbarBase(self.AxisACC, cmap=self.colobarACC, # norm=self.normACC, # orientation='vertical') #self.bargraphACC.set_label('Number of motions detected') self.AxisACC.text(-0.1, 1.15, 'TR with motion', fontdict=fontmediun) self.NMotionText = self.AxisACC.text(0.18, 1, "- - -", fontdict=fontTRNumber) #Rectangle to fill the bar------------------------------------------------------------ self.rectangleACC = Rectangle((0.0, 0), 1, 1, facecolor='white') currentAxis = self.figure.gca() currentAxis.add_patch(self.rectangleACC) #Excessive motion text---------------------------------------------------------------- self.textExcessive = self.figure.text(0.1, 0.5, 'Excessive motion. Stop the Scan!', color='white', bbox=dict(facecolor='red', edgecolor='red')) self.textExcessive.set_size('x-large') self.textExcessive.set_visible(False) TIMER_ID = 100 # pick a number self.timer = wx.Timer(self, TIMER_ID) self.Bind(wx.EVT_TIMER, self.OnTimer) # Add a panel so it looks correct on all platforms self.panel = wx.Panel(self, size=(400,400),pos=(0,0)) self.labelInitText = wx.StaticText(self.panel, wx.ID_ANY, 'Please insert the exam info:', (85, 50), (160, -1), wx.ALIGN_CENTER) font2 = wx.Font(12, wx.DECORATIVE, wx.NORMAL, wx.NORMAL) self.labelInitText.SetFont(font2) self.labelInitText.SetForegroundColour((47,79,79)) # set text color self.TitlePanel = wx.StaticText(self.panel,-1,'fMRI Motion Viewer', (110, 10), (400, -1), wx.ALIGN_CENTER) font = wx.Font(14, wx.DECORATIVE, wx.NORMAL, wx.NORMAL) self.TitlePanel.SetFont(font) self.TitlePanel.SetForegroundColour((0,191,255)) # set text color self.labelInputOne = wx.StaticText(self.panel, wx.ID_ANY, 'Head Motion Limit [0 - 2.0]', (85, 80), (160, -1), wx.ALIGN_CENTER) font2 = wx.Font(12, wx.DECORATIVE, wx.NORMAL, wx.NORMAL) self.labelInputOne.SetFont(font2) self.labelInputOne.SetForegroundColour((47,79,79)) # set text color self.inputTxtOne = wx.TextCtrl(self.panel,wx.ID_ANY,'',pos=(85,100)) self.inputTxtOne.WriteText('0.9') self.labelInputTwo = wx.StaticText(self.panel, wx.ID_ANY, 'Acceptable Head Motions [0 - 20]', (85, 140), (160, -1), wx.ALIGN_CENTER) self.labelInputTwo.SetFont(font2) self.labelInputTwo.SetForegroundColour((47,79,79)) # set text color self.inputTxtTwo = wx.TextCtrl(self.panel, wx.ID_ANY, '',pos=(85,160)) self.inputTxtTwo.WriteText('15') self.labelHelp = wx.TextCtrl(parent = self.panel, id = -1, pos = (20, 210), size = (360, 100), style = wx.TE_MULTILINE|wx.TE_READONLY|wx.TE_AUTO_URL) self.labelHelp.AppendText("Note: This system was developed to detect excessive head motion in fMRI exams. For this it calculates the Euclidean norm of derivative of six degrees of freedom of the head.\n") self.okBtn = wx.Button(self.panel, wx.ID_ANY, 'Start ',(85, 340), (60, -1), wx.ALIGN_CENTER) self.cancelBtn = wx.Button(self.panel, wx.ID_ANY, 'Quit ',(255, 340), (60, -1), wx.ALIGN_CENTER) #self.HelpBtn = wx.Button(self.panel, wx.ID_ANY, 'Help ',(255, 320), (60, -1), wx.ALIGN_CENTER) self.Bind(wx.EVT_BUTTON, self.onOK, self.okBtn) self.Bind(wx.EVT_BUTTON, self.onCancel, self.cancelBtn) self.Show(True)
print help_str sys.exit(0) an = 1 niter = 0 if sys.argv[an] == '-niter': if an + 2 >= narg: print usage_str sys.exit(1) niter = int(sys.argv[an + 1]) print '-- using niter = %d' % niter an += 2 infile = sys.argv[an] mdata = LAD.Afni1D(infile, verb=0) if not mdata.ready: print '** failed to read maxdata file %s' % infile sys.exit(1) try: mdata = [int(round(m)) for m in mdata.mat[0]] except: print '** failed to process integers from maxdata file %s' % infile sys.exit(1) mdata.sort() cmax = mdata[-1] mlen = len(mdata) if niter > 0 and niter > mlen: print '** have input niter (%d) > mlen(%d)' % (niter, mlen)