def test_median(self): """ test Analyzer computing mediansignal within mask """ # settings dictionary for this test settings = {'maskFile': maskFile, 'analysisChoice': 'Median', 'maskIsWeighted': False} # create instance of Analyzer class analyzer = Analyzer(settings) # loop over series and test seriesData = nib.load(seriesFile) results = [] for volIdx in range(seriesData.shape[3]): # extract the 3d array for this vol thisVol = seriesData.get_data()[:, :, :, volIdx] result = analyzer.runAnalysis(thisVol, volIdx) results.append(result['median']) # make np arrays of results and what results are expected to be results = np.array(results) expectedResults = np.array([1017.00, 1020.5, 1026.00]) # use np testing method to assert with customized precision np.testing.assert_almost_equal(results, expectedResults, decimal=2)
def test_customAnalysis(self): """ test Analyzer computing customAnalysis within mask """ # settings dictionary for this test settings = {'maskFile': maskFile, 'numTimepts': 3, 'analysisChoice': join(paths['testDataDir'], 'test_customAnalysisScript.py'), 'maskIsWeighted': False} # create instance of Analyzer class analyzer = Analyzer(settings) # loop over series and test seriesData = nib.load(seriesFile) results = [] for volIdx in range(seriesData.shape[3]): # extract the 3d array for this vol thisVol = seriesData.get_data()[:, :, :, volIdx] result = analyzer.runAnalysis(thisVol, volIdx) results.append(result['customResult']) # make np arrays of results and what results are expected to be results = np.array(results) expectedResults = np.array([1029.15, 1032.78, 1034.14]) # use np testing method to assert with customized precision np.testing.assert_almost_equal(results, expectedResults, decimal=2)
def test_median(self): """ test Analyzer computing mediansignal within mask """ # settings dictionary for this test settings = { 'maskFile': maskFile, 'analysisChoice': 'Median', 'maskIsWeighted': False } # create instance of Analyzer class analyzer = Analyzer(settings) # loop over series and test seriesData = nib.load(seriesFile) results = [] for volIdx in range(seriesData.shape[3]): # extract the 3d array for this vol thisVol = seriesData.get_data()[:, :, :, volIdx] result = analyzer.runAnalysis(thisVol, volIdx) results.append(result['median']) # make np arrays of results and what results are expected to be results = np.array(results) expectedResults = np.array([1017.00, 1020.5, 1026.00]) # use np testing method to assert with customized precision np.testing.assert_almost_equal(results, expectedResults, decimal=2)
def test_customAnalysis(self): """ test Analyzer computing customAnalysis within mask """ # settings dictionary for this test settings = { 'maskFile': maskFile, 'numTimepts': 3, 'analysisChoice': join(paths['testDataDir'], 'test_customAnalysisScript.py'), 'maskIsWeighted': False } # create instance of Analyzer class analyzer = Analyzer(settings) # loop over series and test seriesData = nib.load(seriesFile) results = [] for volIdx in range(seriesData.shape[3]): # extract the 3d array for this vol thisVol = seriesData.get_data()[:, :, :, volIdx] result = analyzer.runAnalysis(thisVol, volIdx) results.append(result['customResult']) # make np arrays of results and what results are expected to be results = np.array(results) expectedResults = np.array([1029.15, 1032.78, 1034.14]) # use np testing method to assert with customized precision np.testing.assert_almost_equal(results, expectedResults, decimal=2)
def launchPyneal(headless=False, customSettingsFile=None): """Main Pyneal Loop. This function will launch setup GUI, retrieve settings, initialize all threads, and start processing incoming scans """ ### Read Settings ------------------------------------ # Read the settings file, and launch the setup GUI to give the user # a chance to update the settings. Hitting 'submit' within the GUI # will update the setupConfig file with the new settings if customSettingsFile: print('Loading custom settings file: {}'.format(customSettingsFile)) settingsFile = customSettingsFile else: settingsFile = join(pynealDir, 'src/GUIs/pynealSetup/setupConfig.yaml') if not headless: # Launch GUI to let user update the settings file setupGUI.launchPynealSetupGUI(settingsFile) elif headless: print('Running headless...') print('Using settings in {}'.format(settingsFile)) assert os.path.exists( settingsFile ), 'Running headless, but settings file does not exist: {}'.format( settingsFile) # Read the new settings file, store as dict with open(settingsFile, 'r') as ymlFile: settings = yaml.load(ymlFile) ### Create the output directory, put in settings dict outputDir = createOutputDir(settings['outputPath']) settings['seriesOutputDir'] = outputDir ### Set Up Logging ------------------------------------ # The createLogger function will do a lot of the formatting set up # behind the scenes. You can write to this log by calling the # logger var and specifying the level, e.g.: logger.debug('msg') # Other modules can write to this same log by calling # the command: logger = logging.getLogger('PynealLog') logFname = join(outputDir, 'pynealLog.log') logger = createLogger(logFname) print('Logs written to: {}'.format(logFname)) # write all settings to log for k in settings: logger.info('Setting: {}: {}'.format(k, settings[k])) print('-' * 20) ### Launch Threads ------------------------------------- # Scan Receiver Thread, listens for incoming volume data, builds matrix scanReceiver = ScanReceiver(settings) scanReceiver.daemon = True scanReceiver.start() logger.debug('Starting Scan Receiver') # Results Server Thread, listens for requests from end-user (e.g. task # presentation), and sends back results resultsServer = ResultsServer(settings) resultsServer.daemon = True resultsServer.start() logger.debug('Starting Results Server') ### Create processing objects -------------------------- # Class to handle all preprocessing preprocessor = Preprocessor(settings) # Class to handle all analysis analyzer = Analyzer(settings) ### Launch Real-time Scan Monitor GUI if settings['launchDashboard']: ### launch the dashboard app as its own separate process. Once called, # it will set up a zmq socket to listen for inter-process messages on # the 'dashboardPort', and will host the dashboard website on the # 'dashboardClientPort' pythonExec = sys.executable # path to the local python executable p = subprocess.Popen([ pythonExec, join(pynealDir, 'src/GUIs/pynealDashboard/pynealDashboard.py'), str(settings['dashboardPort']), str(settings['dashboardClientPort']) ]) # Set up the socket to communicate with the dashboard server dashboardContext = zmq.Context.instance() dashboardSocket = dashboardContext.socket(zmq.REQ) dashboardSocket.connect('tcp://127.0.0.1:{}'.format( settings['dashboardPort'])) # make sure subprocess and dashboard ports get killed at close atexit.register(cleanup, p, dashboardContext) # Open dashboard in browser # s = '127.0.0.1:{}'.format(settings['dashboardClientPort']) # print(s) # web.open('127.0.0.1:{}'.format(settings['dashboardClientPort'])) # send configuration settings to dashboard configDict = { 'mask': os.path.split(settings['maskFile'])[1], 'analysisChoice': (settings['analysisChoice'] if settings['analysisChoice'] in ['Average', 'Median'] else 'Custom'), 'volDims': str(nib.load(settings['maskFile']).shape), 'numTimepts': settings['numTimepts'], 'outputPath': outputDir } sendToDashboard(dashboardSocket, topic='configSettings', content=configDict) ### Wait For Scan To Start ----------------------------- while not scanReceiver.scanStarted: time.sleep(.5) logger.debug('Scan started') ### Set up remaining configuration settings after first volume arrives while not scanReceiver.completedVols[0]: time.sleep(.1) preprocessor.set_affine(scanReceiver.get_affine()) ### Process scan ------------------------------------- # Loop over all expected volumes for volIdx in range(settings['numTimepts']): ### make sure this volume has arrived before continuing while not scanReceiver.completedVols[volIdx]: time.sleep(.1) ### start timer startTime = time.time() ### Retrieve the raw volume rawVol = scanReceiver.get_vol(volIdx) ### Preprocess the raw volume preprocVol = preprocessor.runPreprocessing(rawVol, volIdx) ### Analyze this volume result = analyzer.runAnalysis(preprocVol, volIdx) # send result to the resultsServer resultsServer.updateResults(volIdx, result) ### Calculate processing time for this volume elapsedTime = time.time() - startTime # update dashboard (if dashboard is launched) if settings['launchDashboard']: # completed volIdx sendToDashboard(dashboardSocket, topic='volIdx', content=volIdx) # timePerVol timingParams = { 'volIdx': volIdx, 'processingTime': np.round(elapsedTime, decimals=3) } sendToDashboard(dashboardSocket, topic='timePerVol', content=timingParams) ### Save output files resultsServer.saveResults() scanReceiver.saveResults() ### Figure out how to clean everything up nicely at the end resultsServer.killServer() scanReceiver.killServer()
def launchPyneal(headless=False, customSettingsFile=None): """Main Pyneal Loop. This function will launch setup GUI, retrieve settings, initialize all threads, and start processing incoming scans """ ### Read Settings ------------------------------------ # Read the settings file, and launch the setup GUI to give the user # a chance to update the settings. Hitting 'submit' within the GUI # will update the setupConfig file with the new settings if customSettingsFile: print('Loading custom settings file: {}'.format(customSettingsFile)) settingsFile = customSettingsFile else: settingsFile = join(pynealDir, 'src/GUIs/pynealSetup/setupConfig.yaml') if not headless: # Launch GUI to let user update the settings file setupGUI.launchPynealSetupGUI(settingsFile) elif headless: print('Running headless...') print('Using settings in {}'.format(settingsFile)) assert os.path.exists(settingsFile), 'Running headless, but settings file does not exist: {}'.format(settingsFile) # Read the new settings file, store as dict with open(settingsFile, 'r') as ymlFile: settings = yaml.load(ymlFile) ### Create the output directory, put in settings dict outputDir = createOutputDir(settings['outputPath']) settings['seriesOutputDir'] = outputDir ### Set Up Logging ------------------------------------ # The createLogger function will do a lot of the formatting set up # behind the scenes. You can write to this log by calling the # logger var and specifying the level, e.g.: logger.debug('msg') # Other modules can write to this same log by calling # the command: logger = logging.getLogger('PynealLog') logFname = join(outputDir, 'pynealLog.log') logger = createLogger(logFname) print('Logs written to: {}'.format(logFname)) # write all settings to log for k in settings: logger.info('Setting: {}: {}'.format(k, settings[k])) print('-'*20) ### Launch Threads ------------------------------------- # Scan Receiver Thread, listens for incoming volume data, builds matrix scanReceiver = ScanReceiver(settings) scanReceiver.daemon = True scanReceiver.start() logger.debug('Starting Scan Receiver') # Results Server Thread, listens for requests from end-user (e.g. task # presentation), and sends back results resultsServer = ResultsServer(settings) resultsServer.daemon = True resultsServer.start() logger.debug('Starting Results Server') ### Create processing objects -------------------------- # Class to handle all preprocessing preprocessor = Preprocessor(settings) # Class to handle all analysis analyzer = Analyzer(settings) ### Launch Real-time Scan Monitor GUI if settings['launchDashboard']: ### launch the dashboard app as its own separate process. Once called, # it will set up a zmq socket to listen for inter-process messages on # the 'dashboardPort', and will host the dashboard website on the # 'dashboardClientPort' pythonExec = sys.executable # path to the local python executable p = subprocess.Popen([ pythonExec, join(pynealDir, 'src/GUIs/pynealDashboard/pynealDashboard.py'), str(settings['dashboardPort']), str(settings['dashboardClientPort']) ]) # Set up the socket to communicate with the dashboard server dashboardContext = zmq.Context.instance() dashboardSocket = dashboardContext.socket(zmq.REQ) dashboardSocket.connect('tcp://127.0.0.1:{}'.format(settings['dashboardPort'])) # make sure subprocess and dashboard ports get killed at close atexit.register(cleanup, p, dashboardContext) # Open dashboard in browser # s = '127.0.0.1:{}'.format(settings['dashboardClientPort']) # print(s) # web.open('127.0.0.1:{}'.format(settings['dashboardClientPort'])) # send configuration settings to dashboard configDict = {'mask': os.path.split(settings['maskFile'])[1], 'analysisChoice': (settings['analysisChoice'] if settings['analysisChoice'] in ['Average', 'Median'] else 'Custom'), 'volDims': str(nib.load(settings['maskFile']).shape), 'numTimepts': settings['numTimepts'], 'outputPath': outputDir} sendToDashboard(dashboardSocket, topic='configSettings', content=configDict) ### Wait For Scan To Start ----------------------------- while not scanReceiver.scanStarted: time.sleep(.5) logger.debug('Scan started') ### Set up remaining configuration settings after first volume arrives while not scanReceiver.completedVols[0]: time.sleep(.1) preprocessor.set_affine(scanReceiver.get_affine()) ### Process scan ------------------------------------- # Loop over all expected volumes for volIdx in range(settings['numTimepts']): ### make sure this volume has arrived before continuing while not scanReceiver.completedVols[volIdx]: time.sleep(.1) ### start timer startTime = time.time() ### Retrieve the raw volume rawVol = scanReceiver.get_vol(volIdx) ### Preprocess the raw volume preprocVol = preprocessor.runPreprocessing(rawVol, volIdx) ### Analyze this volume result = analyzer.runAnalysis(preprocVol, volIdx) # send result to the resultsServer resultsServer.updateResults(volIdx, result) ### Calculate processing time for this volume elapsedTime = time.time() - startTime # update dashboard (if dashboard is launched) if settings['launchDashboard']: # completed volIdx sendToDashboard(dashboardSocket, topic='volIdx', content=volIdx) # timePerVol timingParams = {'volIdx': volIdx, 'processingTime': np.round(elapsedTime, decimals=3)} sendToDashboard(dashboardSocket, topic='timePerVol', content=timingParams) ### Save output files resultsServer.saveResults() scanReceiver.saveResults() ### Figure out how to clean everything up nicely at the end resultsServer.killServer() scanReceiver.killServer()