class Controller: def __init__(self,configDict=None,debug=False): """ construct an instance of the controller class to use invoke the method initialize """ ## basic application wide variables self.appName = "cytostream" self.debug = debug if self.debug == True: self.verbose = True self.defaultDir = os.path.join(self.baseDir,'projects') else: self.verbose = False self.defaultDir = os.getenv("HOME") ## application variables self.configDict = configDict self.reset_workspace() # get base directory if hasattr(sys,'frozen'): self.baseDir = os.path.dirname(sys.executable) self.baseDir = re.sub("MacOS","Resources",self.baseDir) else: self.baseDir = os.path.dirname(__file__) if os.path.split(self.baseDir)[-1] != "cytostream": self.baseDir = os.path.join(self.baseDir,"cytostream") if os.path.isdir(os.path.join(self.baseDir,'cytostream')) == True: self.baseDir = os.path.join(self.baseDir,"cytostream") def reset_workspace(self): self.projectID = None self.homeDir = None self.model = Model(verbose=self.verbose) self.log = None self.subsampleIndices = None self.fileChannelPath = None self.baseDir = self.model.baseDir self.currentPlotView = None self.compensationFilePath= None self.eventsList = [] self.fileNameList = None self.channelDict = None self.subsampleDict = {} self.uniqueLabels = {} self.labelsList = {} self.labelsLogList = {} self.pythonPath = self.model.pythonPath def save(self): self.log.write() def initialize_project(self,homeDir,loadExisting=False): ## clean #if clean == True: self.homeDir = os.path.realpath(homeDir) if loadExisting == False: print '...cleaning home directory' self.remove_project(self.homeDir) os.mkdir(self.homeDir) self.projectID = os.path.split(homeDir)[-1] self.homeDir = homeDir self.log = Logger(self.homeDir,configDict=self.configDict) self.model.initialize(self.homeDir) self.fileNameList = get_fcs_file_names(self.homeDir) ## this needs to be tested or modified for very large projects self.eventsList = [self.model.get_events_from_file(fn) for fn in self.fileNameList] if len(self.fileNameList) > 0: self.fileChannels = self.model.get_file_channel_list(self.fileNameList[0]) else: self.fileChannels = None if self.channelDict == None: self.channelDict = self.model.load_channel_dict() def _labels_load(self,labelsID): ''' load the labels from a given labelsID Often the model run id is the labelsID ''' if labelsID == None: return if self.labelsList.has_key(labelsID) == True: return None _labelsList = [] _logsList = [] for fileName in self.fileNameList: _labels = self.model.load_saved_labels(fileName,labelsID) modelLog = self.model.load_saved_labels_log(fileName,labelsID) _labelsList.append(_labels) _logsList.append(modelLog) self.labelsList[labelsID] = _labelsList self.labelsLogList[labelsID] = _logsList def get_events(self,selectedFileName,subsample='original',filterName=None): ''' input: selectedFileName - string representing the file without the full path and without a file extension subsample - any numeric string, int or float that specifies an already processed subsample subsample - may also be a filterID such as 'filter1' ''' ## error checking if selectedFileName not in self.fileNameList: print "ERROR: Controller.get_events - Invalid selectedFile specified", selectedFileName return None ## check to see if orig events are in memory otherwise load them from pickle if len(self.eventsList) > 0: origEvents = self.eventsList[self.fileNameList.index(selectedFileName)] else: origEvents = self.model.get_events_from_file(selectedFileName) if subsample == 'original': return origEvents elif filterName != None: if self.subsampleDict.has_key(filterName) == False: print "WARNING: Controller.get_events -- invalid filterName" return origEvents[self.subsampleDict[key],:] else: self.handle_subsampling(subsample) key = str(int(float(subsample))) return origEvents[self.subsampleDict[key],:] def get_labels(self,fileName,labelsID,subsample='original',getLog=False): """ returns labels for a given file name and run id labels are preloaded into a dictionary for speed """ if fileName not in self.fileNameList: print "ERROR: Controller.get_labels - Invalid selectedFile specified", fileName return None ## ensure labels are present self._labels_load(labelsID) labels = self.labelsList[labelsID][self.fileNameList.index(fileName)] labelsLog = self.labelsLogList[labelsID][self.fileNameList.index(fileName)] if getLog == True: return labels,labelsLog else: return labels def save_labels(self,fileName,fileLabels,labelsID): """ convenience function to save labels """ ## error checking if fileName not in self.fileNameList: print "ERROR: Controller.save_labels -- fileName is not in fileList - skipping..." return None fileEvents = self.get_events(fileName) if len(fileLabels) != int(fileEvents.shape[0]): print "ERROR: Controller.save_labels -- input fileLabels must be the same size as events",len(fileLabels),fileEvents.shape[0] return None self.model.save_labels(fileName,fileLabels,labelsID) def save_labels_log(self,fileName,logDict,labelsID): """ convenience funtion to save label log """ ## error checking if fileName not in self.fileNameList: print "ERROR: Controller.save_labels_log -- fileName is not in fileList - skipping..." return None if type(logDict) != type({}): print "ERROR: Controller.save_labels_log -- logDict must be of type dictionary - skipping..." return None self.model.save_labels_log(fileName,logDict,labelsID) def process_images(self,mode,modelRunID=None,progressBar=None,view=None,verbose=False): ## error check if mode not in ['qa','analysis']: print "ERROR: invalid mode specified" return None if mode == 'analysis' and modelRunID == None: print "ERROR: controller.process_images - modelRun must be specified" return None ## declare variables numImagesToCreate = 0 ## ensure alternate_labels have been selected if len(self.log.log['alternate_channel_labels']) == 0: self.log.log['alternate_channel_labels'] = self.model.get_master_channel_list() self.save() ## determine mode specific variables if mode == 'qa': subsample = self.log.log['subsample_qa'] excludedChannels = self.log.log['excluded_channels_qa'] excludedFiles = self.log.log['excluded_files_qa'] elif mode == 'analysis': subsample = self.log.log['subsample_analysis'] excludedChannels = self.log.log['excluded_channels_analysis'] excludedFiles = self.log.log['excluded_files_analysis'] if subsample == 'original': maxViewSubsample = self.log.log['setting_max_scatter_display'] self.handle_subsampling(maxViewSubsample) ## use the variable 'default_thumb_channels' to set thumbnails to view if self.channelDict == None or len(self.channelDict) == 0: self.channelDict = self.model.load_channel_dict() channelThumbs = [] channelIndices = [] channelMap = [] defaultThumbChannels = self.log.log['default_thumb_channels'] for channel in defaultThumbChannels: if channel == 'FSC': for channel in ['FSCA','FSCH','FSCW','FSC']: if self.channelDict.has_key(channel): channelIndices.append(self.channelDict[channel]) channelThumbs.append(channel) break elif channel == 'SSC': for channel in ['SSCA','SSCH','SSCW','SSC']: if self.channelDict.has_key(channel): channelIndices.append(self.channelDict[channel]) channelThumbs.append(channel) break else: if self.channelDict.has_key(channel): channelIndices.append(self.channelDict[channel]) channelThumbs.append(channel) maxNumComparisons = 5 if len(channelIndices) < 3: channelIndices = range(len(self.fileChannels))[:maxNumComparisons] channelThumbs = [get_official_name_match(i) for i in self.fileChannels[:maxNumComparisons]] self.log.log['default_thumb_channels'] = channelThumbs self.save() comparisons = [] for _j,chanj in enumerate(channelThumbs): j = self.channelDict[chanj] for _i,chani in enumerate(channelThumbs): if _j == _i: continue i = self.channelDict[chani] comparisons.append((i,j)) self.log.log['thumbnails_to_view'] = comparisons ## get channels to be viewed channelInds = set([]) for comp in comparisons: channelInds.update(comp) ## save the thumb channel map self.log.log['default_thumb_channels'] = channelThumbs self.save() ## get num images to create for fileName in self.fileNameList: numImagesToCreate += len(comparisons) percentDone = 0 imageCount = 0 ## get img dir if mode == 'analysis': imgDir = os.path.join(self.homeDir,'figs',modelRunID) subsample=self.log.log['subsample_analysis'] elif mode == 'qa': imgDir = os.path.join(self.homeDir,"figs",'qa') subsample=self.log.log['subsample_qa'] if os.path.isdir(imgDir) == False: if self.verbose == True: print 'INFO: making img dir', imgDir os.mkdir(imgDir) for fileInd in range(len(self.fileNameList)): fileName = self.fileNameList[fileInd] ## check to see that file is not in excluded files if fileName in excludedFiles: continue ## progress point information imageProgress = range(int(numImagesToCreate)+(len(channelThumbs)*len(self.fileNameList))) ## specify model type to show as thumbnails modelType = self.log.log['thumbnail_results_default'] plotsToViewChannels = [(0,1) for i in range(16)] plotsToViewFiles = [fileInd for i in range(16)] plotsToViewHighlights = [None for i in range(16)] plotsToViewRuns = [modelRunID for i in range(16)] self.log.log["plots_to_view_files"] = plotsToViewFiles self.log.log["plots_to_view_highlights"] = plotsToViewHighlights self.log.log["plots_to_view_runs"] = plotsToViewRuns for comp in comparisons: plotsToViewChannels[0] = comp self.log.log["plots_to_view_channels"] = plotsToViewChannels self.save() figName = os.path.join(imgDir,"%s_%s_%s.%s"%(fileName,comp[0],comp[1],self.log.log['plot_type'])) script = os.path.join(self.baseDir,"RunMakeScatterPlot.py") if os.path.isfile(script) == False: print 'ERROR: cannot find RunMakeScatterPlot.py' return False else: pltCmd = "'%s' '%s' -h '%s' -f '%s' -m '%s' -s '%s'"%(self.pythonPath,script,self.homeDir,figName,mode,subsample) proc = subprocess.Popen(pltCmd,shell=True,stdout=subprocess.PIPE,stdin=subprocess.PIPE) while True: try: next_line = proc.stdout.readline() proc.wait() if next_line == '' and proc.poll() != None: break else: print next_line except: proc.wait() break imageCount += 1 progress = 1.0 / float(len(imageProgress)) *100.0 percentDone+=progress if progressBar != None: progressBar.move_bar(int(round(percentDone))) if verbose == True: print percentDone for chan in channelThumbs: chanInd = self.channelDict[chan] figName = os.path.join(imgDir,"%s_%s.%s"%(fileName,chan,self.log.log['plot_type'])) script = os.path.join(self.baseDir,"RunMakeHistogramPlot.py") if os.path.isfile(script) == False: print 'ERROR: cannot find RunMakeHistogramPlot.py' return False else: pltCmd = "'%s' '%s' -h '%s' -f '%s' -c '%s' -s '%s'"%(self.pythonPath,script,self.homeDir,figName,chanInd,subsample) proc = subprocess.Popen(pltCmd,shell=True,stdout=subprocess.PIPE,stdin=subprocess.PIPE) while True: try: next_line = proc.stdout.readline() proc.wait() if next_line == '' and proc.poll() != None: break else: print next_line except: proc.wait() break imageCount += 1 progress = 1.0 / float(len(imageProgress)) *100.0 percentDone+=progress if verbose == True: print percentDone if progressBar != None: progressBar.move_bar(int(round(percentDone))) thumbDir = os.path.join(imgDir,fileName+"_thumbs") self.create_thumbs(imgDir,thumbDir,fileName) def create_thumbs(self,imgDir,thumbDir,fileName,thumbsClean=True): # test to see if thumbs dir needs to be made if os.path.isdir(thumbDir) == False: os.mkdir(thumbDir) #if specified clean out the thumbs dir if thumbsClean == True: for img in os.listdir(thumbDir): os.remove(os.path.join(thumbDir,img)) # make thumbs anew for img in os.listdir(imgDir): if os.path.isfile(os.path.join(imgDir,img)) == True: imgFile = os.path.join(imgDir,img) self.make_thumb(imgFile,thumbDir,fileName) os.remove(imgFile) def make_thumb(self,imgFile,thumbDir,fileName): comparisons = self.log.log['thumbnails_to_view'] channels = self.fileChannels if os.path.isfile(imgFile) == True: if len(comparisons) <= 4: thumbSize = 250 elif len(comparisons) <= 8: thumbSize = 200 elif len(comparisons) <= 12: thumbSize = 180 elif len(comparisons) <= 16: thumbSize = 160 elif len(comparisons) <= 20: thumbSize = 140 elif len(comparisons) <= 24: thumbSize = 120 elif len(comparisons) <= 28: thumbSize = 100 else: thumbSize = 50 thumbFile = os.path.split(imgFile[:-4]+"_thumb.png")[-1] thumbFile = os.path.join(thumbDir,thumbFile) ## use PIL to create thumb size = thumbSize,thumbSize im = Image.open(imgFile) im.thumbnail(size, Image.ANTIALIAS) im.save(thumbFile) else: print "ERROR: bad file name specified",fileName def get_subsample_indices(self,subsample): """ returns a np.array of indices """ if subsample == 'original': return self.handle_subsampling(subsample) key = str(int(float(subsample))) return self.subsampleDict[key] def handle_subsampling(self,subsample): ''' handels subsampling by fetching saved indices if subsampling is specified at the qa or analysis stage and the number is the same this function enables the use of only a single subsampling ''' if subsample == 'original': return True else: subsample = int(float(subsample)) key = str(subsample) if self.subsampleDict.has_key(key) == False: subsampleIndices = self.model.get_subsample_indices(subsample) if type(subsampleIndices) == type(np.array([])): pass else: print "WARNING: No subsample indices were returned to controller" return False self.subsampleDict[key] = subsampleIndices return True def create_new_project(self,homeDir,channelDict={},record=True): """ create a new project """ ## initialize project self.initialize_project(homeDir) ## remove previous if os.path.exists(self.homeDir) == True: if self.verbose == True: print 'INFO: overwriting project of same name...', self.homeDir self.remove_project(self.homeDir) if self.homeDir != None: os.mkdir(self.homeDir) os.mkdir(os.path.join(self.homeDir,"data")) os.mkdir(os.path.join(self.homeDir,"figs")) os.mkdir(os.path.join(self.homeDir,"models")) os.mkdir(os.path.join(self.homeDir,"results")) os.mkdir(os.path.join(self.homeDir,"documents")) ## class wide variables self.model.save_channel_dict(channelDict) self.fileNameList = get_fcs_file_names(self.homeDir) self.channelDict = self.model.load_channel_dict() ## record project creation in log if record == True: add_project_to_log(self.baseDir,self.homeDir,'created') ## save progress self.save() return True def remove_project(self,homeDir): """ deletes a project and all associated data """ if os.path.isdir(self.homeDir): shutil.rmtree(self.homeDir) def rm_fcs_file(self,fcsFile): """ remove a fcs file from a project """ dataDir = os.path.join(self.homeDir,'data') modelsDir = os.path.join(self.homeDir,'models') figsDir = os.path.join(self.homeDir,'figs') searchKey1 = fcsFile + "\_data" searchKey2 = fcsFile + "\_channels" searchKey3 = fcsFile + "\_run" searchKey4 = fcsFile + "\_" ## remove files from data directory for dirFile in os.listdir(dataDir): if re.search(searchKey1 + "|" + searchKey2, dirFile): os.remove(os.path.join(dataDir,dirFile)) ## remove files from models directory for dirFile in os.listdir(modelsDir): if re.search(searchKey3, dirFile): os.remove(os.path.join(modelsDir,dirFile)) ## get a list of figures dirs and remove files from each figsDirList = [] for itemName in os.listdir(figsDir): if os.path.isdir(os.path.join(figsDir,itemName)): figsDirList.append(itemName) ## remove all figures for dirName in figsDirList: for dirFile in os.listdir(os.path.join(figsDir,dirName,fcsFile+"_thumbs")): os.remove(os.path.join(figsDir,dirName,fcsFile+"_thumbs",dirFile)) os.removedirs(os.path.join(figsDir,dirName,fcsFile+"_thumbs")) for dirFile in os.listdir(os.path.join(figsDir,dirName)): if re.search(searchKey4,dirFile): os.remove(os.path.join(figsDir,dirName,dirFile)) def load_files_handler(self,fileList,progressBar=None,view=None,inputChannels=None): if type(fileList) != type([]): print "INPUT ERROR: load_files_handler: takes as input a list of file paths" dataType = self.log.log['input_data_type'] if dataType not in ['fcs','comma','tab','array']: print "INPUT ERROR: load_files_handler: dataType must be of type 'fsc' 'comma','tab','array'" if dataType in ['array'] and inputChannels == None: print "ERROR: Controller -- inputChannels must be specified if dType is array" return None else: self.fileChannelPath = inputChannels if dataType in ['comma','tab']: if self.fileChannelPath == None: defaultDir = os.path.join(self.homeDir,os.path.pardir) allFiles = QtGui.QFileDialog.getOpenFileNames(view,'Load the channels file',directory=defaultDir) self.fileChannelPath = str(allFiles[0]) ## used the selected transform transform = self.log.log['load_transform'] autoComp = self.log.log['auto_compensation'] logicleScaleMax = self.log.log['logicle_scale_max'] self.model.load_files(fileList,progressBar=progressBar,dataType=dataType,fileChannelPath=self.fileChannelPath, compensationFilePath=self.compensationFilePath,transform=transform,autoComp=autoComp, logicleScaleMax=logicleScaleMax) ## reload the log file and save it self.log = Logger(self.homeDir) self.save() ## initialize class wide variables self.fileNameList = get_fcs_file_names(self.homeDir) if len(self.fileNameList) < 50: self.eventsList = [self.model.get_events_from_file(fn) for fn in self.fileNameList] else: self.eventsList = [] if len(self.fileNameList) > 0: self.fileChannels = self.model.get_file_channel_list(self.fileNameList[0]) self.channelDict = self.model.load_channel_dict() def handle_filtering_by_clusters(self,filterID,fileName,parentModelRun,clusterIDs): """ Filtering saves a np.array using the original array shape where row indices that have been filtered become 0 or 1. Filter results can be fetched like a subsample. """ modelsRunList = get_models_run_list(self.log.log) ## error checkings if fileName not in self.fileNameList: msg = "fileName is not in fileList - skipping filtering" print "ERROR: Controller.handle_filtering_by_clusters -- %s"%msg return None if parentModelRun not in modelsRunList: msg = "parentModelRun is not in modelsRunList - skipping filtering" print "ERROR: Controller.handle_filtering_by_clusters -- %s"%msg return None ## create a log logDict = {"timestamp": time.asctime(), "parent model": parentModelRun} ## get the filter labels fileEvents = self.get_events(fileName) fileLabels = a = np.zeros((fileEvents.shape[0]),dtype=int) filterIndices = self.model.get_filter_indices_by_clusters(fileName,parentModelRun,clusterIDs) fileLabels[filterIndices] = 1 ## save the filter indices self.model.save_labels(fileName,fileLabels,filterID) self.model.save_labels_log(fileName,logDict,filterID) def handle_filtering_by_indices(self,filterID,fileName,filterIndices,parentModelRun=None): """ Filtering saves a np.array using the original array shape where row indices that have been filtered become 0 or 1. Filter results can be fetched like a subsample. """ modelsRunList = get_models_run_list(self.log.log) ## create a log logDict = {"timestamp": time.asctime(), "parent model": parentModelRun} ## error checking if fileName not in self.fileNameList: print "ERROR: Controller.handle_filtering_by_clusters -- fileName is not in fileList - skipping filtering" return None ## get the filter labels fileEvents = self.get_events(fileName) fileLabels = a = np.zeros((fileEvents.shape[0]),dtype=int) fileLabels[filterIndices] = 1 ## save the filter indices self.model.save_labels(fileName,fileLabels,filterID) self.model.save_labels_log(fileName,logDict,filterID) def validate_channel_dict(self,fileChannels,channelDict): """ ensure a valid channel dict """ if fileChannels == None or len(fileChannels) == 0: print "WARNING: Controller.validate_channel_dict invalid file channels specified" print '...', fileChannels return False mismatchFound = False for key,chanInd in channelDict.iteritems(): key = key.lower() keyParts = key.split("+") for k in keyParts: if k == 'ifng': k = 'ifng|ifn' if k == 'dump': k = "dump|cd14|cd19|vamine" if chanInd >= len(fileChannels): print "WARNING: Controller.validate_channel_dict -- chan indx is invalid %s is larger than %s"%(chanInd,len(fileChannels)) return False strippedChannelName = re.sub("\s|\-|\_","",fileChannels[chanInd]) if not re.search(k,strippedChannelName,flags=re.IGNORECASE): print "WARNING: Controller.validate_channel_dict file channel to channel dict mismatch?", k, key, fileChannels[chanInd] mismatchFound = True if mismatchFound == True: return False else: return True def sanitize_check(self,script): """ standard function to sanitize file name inputs """ if re.search(">|<|\*|\||^\$|;|#|\@|\&",script): return False else: return True def run_selected_model(self,progressBar=None,view=None): def report_progress(percentComplete,percentagesReported,progressBar=None): if progressBar != None: progressBar.move_bar(int(round(percentComplete))) else: if int(round(percentComplete)) in percentagesReported: return percentagesReported.append(int(round(percentComplete))) if int(round(percentComplete)) != 100: print "\r",int(round(percentComplete)),"percent complete", else: print "\r",int(round(percentComplete)),"percent complete" ## ensure filelist variable is up to date if len(self.fileNameList) == 0: self.fileNameList = get_fcs_file_names(self.homeDir) ## variables selectedModel = self.log.log['model_to_run'] percentComplete = 0 percentagesReported = [] fileList = self.fileNameList ## iterate the model run ID self.log.log['models_run_count'] = str(int(self.log.log['models_run_count']) + 1) modelRunID = 'run'+self.log.log['models_run_count'] self.log.log['selected_model'] = modelRunID self.save() if selectedModel not in self.model.modelsInfo.keys(): print "ERROR: Controller.run_selected_model_cpu -- Invalid model",selectedModel return print 'running... %s via %s'%(selectedModel,self.model.modelsInfo[selectedModel][1]) cmd = self.pythonPath script = os.path.join(self.baseDir,self.model.modelsInfo[selectedModel][1]) if view == None: fileCount = 0 for fileName in fileList: fileCount += 1 if os.path.isfile(script) == False: print "ERROR: Invalid model run file path ", script argsStr = "'%s' -h '%s' -f '%s'"%(script,self.homeDir,fileName) proc = subprocess.Popen(cmd + ' ' + argsStr, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE) while True: try: next_line = proc.stdout.readline() proc.wait() if next_line == '' and proc.poll() != None: break else: print next_line except: proc.wait() break else: view.mc.init_model_process(cmd,script,fileList) def save_gate(self,gateName,verts,channel1,channel2,channel1Name,channel2Name,parent,fileName, modelRunID='run1',saveLabels=True): ''' saves a given gate channels are the channel index iFilter - is a filter created using indices within a gate cFilter - is a filter created using indices derived from clusters within a gate This function and all functions that interact with proprietary software output are experimental and functionality is not guaranteed. ''' isCytokine = False cytokineChan = None parent = re.sub("\s+","_",parent) gateName = re.sub("\s+","_",gateName) parent = re.sub("\.gate","",parent) gateName = re.sub("\.gate","",gateName) gateFilePath = os.path.join(os.path.join(self.homeDir,"data"),gateName) #gateName = re.sub(fileName,"",gateName) #parent = re.sub(fileName,"",parent) #gateName = re.sub("_gate_$","",gateName) #parent = re.sub("_gate_$","",parent) ## check to see if we have a cytokine if re.search(cytokinePattern,gateName): isCytokine = True if re.search(cytokinePattern,channel1Name): cytokineChan = 0 if re.search(cytokinePattern,channel2Name): cytokineChan = 1 gateToSave = {'verts':verts, 'channel1':channel1, 'channel2':channel2, 'parent':parent, 'name':gateName, 'cytokine':isCytokine} if not re.search("\.gate",gateFilePath): gateFilePath = gateFilePath+".gate" tmp1 = open(gateFilePath,'w') cPickle.dump(gateToSave,tmp1) tmp1.close() if saveLabels == False: return ## save the labels associated with each gate fileEvents = self.get_events(fileName) fileLabels = self.get_labels(fileName,modelRunID) _gateIndices = get_indices_from_gate(fileEvents[:,[channel1,channel2]],verts) if parent != 'root': parentGate = self.load_gate(parent) filterLabels = self.get_labels(fileName,parent,getLog=False) parentIndices = np.where(filterLabels==1)[0] gateIndices = list(set(parentIndices).intersection(set(_gateIndices))) else: gateIndices = _gateIndices ## save events by index #labels = np.zeros((fileEvents.shape[0]),dtype=int) #if gateIndices != None: # labels[posIndices] = 1 #nga.save_labels(fileName,labels,gn) self.handle_filtering_by_indices(gateName,fileName,gateIndices) def load_gate(self,gateID): ''' loads the gate from a pickle file ''' gateList = get_saved_gate_names(self.homeDir) if gateID not in gateList: print "ERROR: Controller.load_gate -- invalid gate specified",gateID print gateList return gateFilePath = os.path.join(self.homeDir,'data','%s.gate'%gateID) tmp = open(gateFilePath,'r') gate = cPickle.load(tmp) tmp.close() return gate def save_subplots(self,figName,numSubplots,figMode='analysis',figTitle=None,useScale=False,drawState='heat', subplotTitles=None,gatesToShow=None,positiveToShow=None,drawLabels=True,textToShow=None, fontSize=10): ''' function used from within cytostream when SaveSubplots cannot be imported ''' ss = SaveSubplots(self,figName,numSubplots,figMode=figMode,figTitle=figTitle,useScale=useScale, drawLabels=drawLabels,drawState=drawState,subplotTitles=subplotTitles, gatesToShow=gatesToShow,positiveToShow=positiveToShow,textToShow=textToShow, fontSize=fontSize)