#!/usr/bin/env /Library/Frameworks/Python.framework/Versions/Current/bin/python import os import sys, gc from string import * import time as t import numpy as np import scipy import math from PyQt4 import QtGui as qg from PyQt4 import QtCore as qc from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas from matplotlib.backends.backend_qt4agg import NavigationToolbar2QTAgg as NavigationToolbar #from guppy import hpy; hp=hpy() import h5file import hrplot #import py_compile ###################################################################################################################################### # This is a Plotting program designed to read h5 files generated by ppn, the NuGrid's # postprossessing software # # It consists of 3 files, this one, h5file.py and hrplot.py. This file acts as the core to the gui program # and makes calls as needed to the other files. # # h5file.py contains programm classes for wrapping the h5 files. they automatically gather data from the h5files # and allow queries to access data from the files. # # hrplot.py contains the necessary programming to perform the plots. This centralizes all the mpl function calls ######################################################################################################################################## ##Global Variables## openFile = [] # The list of files currently open in memory x_paramater = '' # A plotting parameter-What the x-axis should be y_paramater = '' # See above x_vals = [] # The actual data of interest y_vals = [] # plot_cattr = [] # An array to hold the cattr plot_data = [] write = 0 # This class Manages the GUI frontend. It starts by building the main GUI and calls several functions # to assist in construction and manage the plot classes. class h5Plotter(qg.QMainWindow, qc.QThread): # Class variables (there are many more, but these are the major ones path = '' # The current directory path h5s = [] # An h5FileHolder that contains the h5Files of interest-see h5file.py isos_to_plot = [] # A list of isotopes to be plotted indexes = [] # A list of the indexes of the isotpes to be plotted cycle_of_interest = [] # A list of cycles that will be plotted in the abundance plot isotopes = [] # A list of isotopes in the h5 file for abundance plot isotope_index = [] variable_limit_input = [] # For use in special kippenhahn plot variable = [] # Also for special kippenhahn plot_index = 1 # For writing to file. Need to number HP = [] AP = [] SP = [] AB = [] sp_kh = [] KH = [] GP = [] IA = [] elements_names = ['Neutron','H','He','Li','Be','B','C','N','O','F','Ne','Na','Mg','Al', 'Si','P','S','Cl','Ar','K','Ca','Sc','Ti','V','Cr','Mn','Fe','Co','Ni', 'Cu','Zn','Ga','Ge','As','Se','Br','Kr','Rb','Sr','Y','Zr','Nb','Mo','Tc', 'Ru','Rh','Pd','Ag','Cd','In','Sn','Sb','Te', 'I','Xe','Cs','Ba','La','Ce', 'Pr','Nd','Pm','Sm','Eu','Gd','Tb','Dy','Ho','Er','Tm','Yb','Lu','Hf','Ta', 'W','Re','Os','Ir','Pt','Au','Hg','Tl','Pb','Bi','Po','At'] stable_el = [['Neutron','999'],['H',1, 2],['He', 3, 4],['Li', 6, 7],['Be', 9],['B', 10, 11],['C', 12, 13],['N', 14, 15],['O', 16, 17, 18],['F', 19],['Ne', 20, 21, 22],['Na', 23],['Mg', 24, 25, 26],['Al', 27],['Si', 28, 29, 30],['P', 31],['S', 32, 33, 34, 36],['Cl', 35, 37],['Ar', 36, 38, 40],['K', 39, 40, 41],['Ca', 40, 42, 43, 44, 46, 48],['Sc', 45],['Ti', 46, 47, 48, 49, 50],['V', 50, 51],['Cr', 50, 52, 53, 54],['Mn', 55],['Fe', 54, 56, 57, 58],['Co', 59],['Ni', 58, 60, 61, 62, 64],['Cu', 63, 65],['Zn', 64, 66, 67, 68, 70],['Ga', 69, 71],['Ge', 70, 72, 73, 74, 76],['As', 75],['Se', 74, 76, 77, 78, 80, 82],['Br', 79, 81],['Kr', 78, 80, 82, 83, 84, 86],['Rb', 85, 87],['Sr', 84, 86, 87, 88],['Y', 89],['Zr', 90, 91, 92, 94, 96],['Nb', 93],['Mo', 92, 94, 95, 96, 97, 98, 100],['Tc',999],['Ru', 96, 98, 99, 100, 101, 102, 104],['Rh', 103],['Pd', 102, 104, 105, 106, 108, 110],['Ag', 107, 109],['Cd', 106, 108, 110, 111, 112, 113, 114, 116],['In', 113, 115],['Sn', 112, 114, 115, 116, 117, 118, 119, 120, 122, 124],['Sb', 121, 123],['Te', 120, 122, 123, 124, 125, 126, 128, 130],['I', 127],['Xe', 124, 126, 128, 129, 130, 131, 132, 134, 136],['Cs', 133],['Ba', 130, 132, 134, 135, 136, 137, 138],['La', 138, 139],['Ce', 136, 138, 140, 142],['Pr', 141],['Nd', 142, 143, 144, 145, 146, 148, 150],['Pm',999],['Sm', 144, 147, 148, 149, 150, 152, 154],['Eu', 151, 153],['Gd', 152, 154, 155, 156, 157, 158, 160],['Tb', 159],['Dy', 156, 158, 160, 161, 162, 163, 164],['Ho', 165],['Er', 162, 164, 166, 167, 168, 170],['Tm', 169],['Yb', 168, 170, 171, 172, 173, 174, 176],['Lu', 175, 176],['Hf', 174, 176, 177, 178, 179, 180],['Ta', 180, 181],['W', 180, 182, 183, 184, 186],['Re', 185, 187],['Os', 184, 186, 187, 188, 189, 190, 192],['Ir', 191, 193],['Pt', 190, 192, 194, 195, 196, 198],['Au', 197],['Hg', 196, 198, 199, 200, 201, 202, 204],['Tl', 203, 205],['Pb', 204, 206, 207, 208],['Bi', 209],['Th', 232],['U',235,238]] ######################################################################################### # # HR Plot Manager # ######################################################################################### # Manages the hrplot class and plot def begin_HR_Plot(self): qc.QThread.__init__(self,None) ideal_factor = int(float(len(self.h5s.cycles)/1000)) self.dialog = qg.QDialog() self.dialog.setModal(True) mainbox = qg.QVBoxLayout() self.dialog.setLayout(mainbox) box1 = qg.QVBoxLayout() box2 = qg.QHBoxLayout() mainbox.addLayout(box1) mainbox.addLayout(box2) label = qg.QLabel('Sparsity Factor') self.sparse = qg.QLineEdit(str(ideal_factor)) self.write = qg.QCheckBox('Write to file', None) box1.addWidget(label) box1.addWidget(self.sparse) box1.addWidget(self.write) accept = qg.QPushButton('Plot') deny = qg.QPushButton('Cancel') box2.addWidget(accept) box2.addWidget(deny) self.connect(accept, qc.SIGNAL('clicked()'), self.continue_HR_Plot) self.connect(deny, qc.SIGNAL('clicked()'), self.dialog.close) self.dialog.show() def continue_HR_Plot(self): t0 = t.time() self.dialog.close() try: sparsity_factor = int(self.sparse.text()) except AttributeError: sparsity_factor = int(float(len(self.h5s.cycles)/1000)) if sparsity_factor < 1: sparsity_factor = 1 print "Sparse: "+str(sparsity_factor) t1=t.time() data = self.h5s.fetch_datas('logTeff','logL',None, sparsity_factor) teff = data[0] logL = data[1] ''' #Inefficient takes too long teff = self.h5s.get1('logTeff') #data[0] logL = self.h5s.get1('logL') #data[1] a=[] for i in range(len(teff)): if i%sparsity_factor==0: a.append(teff[i]) teff=a a=[] for i in range(len(logL)): if i%sparsity_factor==0: a.append(logL[i]) logL=a ''' #del data t2=t.time() print t2-t1 t.sleep(3) self.HP.append(hrplot.hrplot(teff,logL, self.sub_plot_controller, sparsity_factor, self)) self.HP[-1].run() self.tabs.addSubWindow(self.HP[-1].canvas,qc.Qt.SubWindow).show() mpl_toolbar = NavigationToolbar(self.HP[-1].canvas, self.tabs.activeSubWindow()) mpl_toolbar.move(10,25) mpl_toolbar.resize(500,50) mpl_toolbar.show() #del teff, logL, mpl_toolbar, self.sparse self.connect(self.tabs.currentSubWindow(), qc.SIGNAL('destroyed()'),self.close_HR_thread) self.textEdit.append('Plot 1 Complete') #except IndexError: # self.textEdit.append('You have no data loaded. Load some data') t1 = t.time() #self.h5s.check_open_files() def close_HR_thread(self): #self.terminate() gc.collect() ######################################################################################### # # Isotope Subplot Manager # ######################################################################################### # This class controlls dialog box # and subplot controll of the abundance_plot class def isotope_subplot(self,isotopes): print "isotope_subplot" # Set vars and build dialog box self.isotopes = isotopes self.textEdit.append('Beginning plot dialog') self.dialog = qg.QDialog() self.dialog.setModal(True) # Build a layout box to stack widgets mainbox = qg.QVBoxLayout() box1 = qg.QVBoxLayout() box2 = qg.QHBoxLayout() # Define the box layouts position and role self.dialog.setLayout(mainbox) mainbox.addLayout(box1) mainbox.addLayout(box2) # Build the lists containing the data that can be plotted self.dmodel1 = qg.QStandardItemModel() self.dlist1 = qg.QListView() self.dlist1.setSelectionMode(qg.QAbstractItemView.ExtendedSelection) self.dlist1.setModel(self.dmodel1) # Build user interaction mode- a line containing a label of selected isotops self.iso_input = qg.QLineEdit(None) self.iso_input.setText('Enter Isotopes Here. Defaults to All') self.iso_input.setReadOnly(False) sparse_label = qg.QLabel('Sparsity Factor') self.sparsity = qg.QLineEdit(str(len(self.h5s.cycles)/1000)) # Add the widgets to first box box1.addWidget(sparse_label) box1.addWidget(self.sparsity) box1.addWidget(self.iso_input) box1.addWidget(self.dlist1) # Build the control buttons sp_button = qg.QPushButton('Do Abundance Plot',None) # Connect accept button to the fnction do_sp self.connect(sp_button,qc.SIGNAL('clicked()'),self.do_sp) box1.addWidget(sp_button) # Cycle through list of isotopes available to be plotted and # add them to the list #print isotopes for isos in isotopes: temp3 = qg.QStandardItem(str(isos[0])+str(isos[1])) temp3.setText(str(isos[0])+'-'+str(isos[1])) temp3.setEditable(False) self.dmodel1.appendRow(temp3) self.dialog.show() # Connect the list to the isotope selection function #self.connect(self.dlist1,qc.SIGNAL('doubleClicked(const QModelIndex &)'),self.select_isotope) # This function, called from isotope_subplot controls the data aquizition and plotting to do # The isotope subplot def do_sp(self): # Close the dialog box generated in isotope_subplot self.dialog.close() self.isos_to_plot = [] print self.dlist1, self.dmodel1 indexes = self.dlist1.selectedIndexes() for index in indexes: self.isos_to_plot.append(str(self.dmodel1.itemFromIndex(index).text())) print 'isos_to_plot', self.isos_to_plot try: sparsity = int(self.sparsity.text()) except AttributeError: sparsity = float(len(self.h5s.cycles))/float(1000) if sparsity == 0 : sparsity = 1 self.textEdit.append('Beginning plot with sparsity of '+str(sparsity)) # Check if there is and isotopes selected. If not --> go back to isotope_subplot if self.isos_to_plot == []: self.isotope_subplot(self.h5s.isotopes) # Otherwise get the data else: all_vals = [] # FIXME - it should be possible to combine the next batch of for loops into just a few!! # Cycle through the selected cycles and get all the data (calls h5FileHolder function) for cycs in self.cycle_of_interest: all_vals.append(self.h5s.get(cycs,'iso_massf', sparsity)) for isos in self.isos_to_plot: self.textEdit.append('Abundance Plot '+ str(isos) + ' for cycles ' + str(self.cycles_of_interest)) yvals = [] # Cycle through the data and extract the information of interest for cyc in xrange(len(self.cycle_of_interest)): temp1 = [] for ind in xrange(len(self.indexes)): temp2 = [] for coords in xrange(len(all_vals[cyc])): temp2.append(all_vals[cyc][coords][ind]) temp1.append(temp2) yvals.append(temp1) del temp1, temp2 # Call abundance_plot class and do the plot self.AP.append(hrplot.abundance_plot(yvals, self.cycle_of_interest,self.isos_to_plot)) self.AP[-1].run()# # Attach the abundance_plot canvas and mpl_toolbar to our subwindow self.tabs.addSubWindow(self.AP[-1].canvas,qc.Qt.SubWindow).show() mpl_toolbar = NavigationToolbar(self.AP[-1].canvas, self.tabs.activeSubWindow()) mpl_toolbar.move(10,25) mpl_toolbar.resize(500,50) mpl_toolbar.show() self.connect(self.tabs.currentSubWindow(), qc.SIGNAL('destroyed()'),self.close_sp_thread) del yvals#, temp1, temp2 gc.collect() def close_sp_thread(self): gc.collect() # Accepts the users isotope subplot varaible selection def select_isotope(self, QModelIndex): selected = str(self.dmodel1.itemFromIndex(QModelIndex).text()) self.textEdit.append('Selected isotope: ' + str(selected)) if self.isos_to_plot.count(selected) == 0: self.isos_to_plot.append(selected) self.iso_input.setText(str(self.isos_to_plot)) self.indexes.append(QModelIndex.row()) #########################################################################################3 # # Abundance or Sub_plot class controll # ########################################################################################### # This function controlls the subplot class or abundance_plot, # depending on user selection, and it's variables def do_hr_subplot(self): # The following builds the dialog box for user interaction # This includes 2 lists for the user to select which variables # are of interest self.textEdit.append('Beginning plot dialog') self.dialog = qg.QDialog() self.dialog.setModal(True) #self.gp = qg.QGroupBox('Plot Dialog',None) #self.swindow.setWidget(self.gp) mainbox = qg.QVBoxLayout() box0 = qg.QVBoxLayout() box1 = qg.QHBoxLayout() box1a = qg.QHBoxLayout() box2 = qg.QHBoxLayout() self.dialog.setLayout(mainbox) mainbox.addLayout(box0) mainbox.addLayout(box1) mainbox.addLayout(box1a) mainbox.addLayout(box2) self.write = qg.QCheckBox('Write To File', None) box0.addWidget(self.write) self.dlist1 = qg.QListView() # self.dlist1.setSelectionMode(qg.QAbstractItemView.ExtendedSelection) self.dmodel1 = qg.QStandardItemModel() self.dlist1.setModel(self.dmodel1) self.dlist2 = qg.QListView() self.dlist2.setSelectionMode(qg.QAbstractItemView.ExtendedSelection) self.dmodel2 = qg.QStandardItemModel() self.dlist2.setModel(self.dmodel2) box1.addWidget(self.dlist1) box1.addWidget(self.dlist2) for dcol in self.h5s.dcols: temp3 = qg.QStandardItem(dcol) temp3.setText(dcol) temp3.setEditable(False) temp4 = qg.QStandardItem(dcol) temp4.setText(dcol) temp4.setEditable(False) self.dmodel1.appendRow(temp3) self.dmodel2.appendRow(temp4) del temp3, temp4 gc.collect() # Add the option to have a log plot for the x and y axis self.log_x = qg.QCheckBox('Use log scale for x-axis') self.log_y = qg.QCheckBox('Use log scale for y-axis') box1a.addWidget(self.log_x) box1a.addWidget(self.log_y) # Add two buttons to accept the selected plot variables of the given cycle(s) # or close the dialog box and continue navigating the HR plot window accept = qg.QPushButton('Plot',None) deny = qg.QPushButton('Cancel',None) box2.addWidget(accept) box2.addWidget(deny) self.connect(deny,qc.SIGNAL('clicked()'),self.dialog.close) self.connect(accept,qc.SIGNAL('clicked()'),self.do_subplot) self.dialog.show() #################################################################################################### # # Subplot class # ##################################################################################################### # Controls the subplot class def do_subplot(self): global write write = self.write.checkState() self.logx = False self.logy = False if self.log_x.checkState() == 2: self.logx = True if self.log_y.checkState() == 2: self.logy = True self.cycle_of_interest = [] self.dialog.close() self.textEdit.append('Beginning subplot. Accessing selections......') # Use the sub_plot_controller as a data mediator between classes index = self.sub_plot_controller.text() #index = index[1:len(index)-1] # Take the data from the sub_plot_controller and add it to the cycles_of_interest list index = index.split(',') try: index = int(index[0]) except IndexError, ValueError: index = int(index) try: self.cycle_of_interest.append(self.h5s.cycles[index[0]]) except TypeError: try: self.cycle_of_interest.append(self.h5s.cycles[index]) except IndexError: print 'skipping == cheating' self.textEdit.append('Doing plot for cycle: ' + str(self.cycle_of_interest)) # Grabs the data from the users dialog (do_hr_subplot function) self.x_data = str(self.dmodel1.itemFromIndex(self.dlist1.selectedIndexes()[0]).text()) self.y_data = str(self.dmodel2.itemFromIndex(self.dlist2.selectedIndexes()[0]).text()) self.textEdit.append('For xaxis: ' + str(self.x_data)) self.textEdit.append('For yaxis: ' + str(self.y_data)) try: isotopes = self.h5s.fetch_isotopes() except IndexError: None #try: xval = [] yval = [] if self.x_data.count('iso_massf') or self.y_data.count('iso_massf') or self.x_data.count('yps') or self.y_data.count('yps'): self.get_isotope_input() else: self.do_sp() def get_isotope_input(self): self.isos_to_plot = [] ideal_factor = len(self.h5s.cycles)/1000 self.dialog = qg.QDialog() self.dialog.setModal(True) mainbox = qg.QVBoxLayout() self.dialog.setLayout(mainbox) self.textEdit.append('Beginning plot dialog') self.dialog = qg.QDialog() self.dialog.setModal(True) # Build a layout box to stack widgets mainbox = qg.QVBoxLayout() box1 = qg.QVBoxLayout() box2 = qg.QHBoxLayout() # Define the box layouts position and role self.dialog.setLayout(mainbox) mainbox.addLayout(box1) mainbox.addLayout(box2) # Build the lists containing the data that can be plotted self.dmodel1 = qg.QStandardItemModel() self.dlist1 = qg.QListView() self.dlist1.setSelectionMode(qg.QAbstractItemView.ExtendedSelection) self.dlist1.setModel(self.dmodel1) # Build user interaction mode- a line containing a label of selected isotops self.iso_input = qg.QLineEdit(None) self.iso_input.setText('Enter Isotopes Here. Defaults to All') self.iso_input.setReadOnly(False) sparse_label = qg.QLabel('Sparsity Factor') self.sparsity = qg.QLineEdit(str(len(self.h5s.cycles)/1000)) # Add the widgets to first box box1.addWidget(sparse_label) box1.addWidget(self.sparsity) box1.addWidget(self.iso_input) box1.addWidget(self.dlist1) # Build the control buttons sp_button = qg.QPushButton('Do Abundance Plot',None) # Connect accept button to the fnction do_sp self.connect(sp_button,qc.SIGNAL('clicked()'),self.do_sp) box1.addWidget(sp_button) # Cycle through list of isotopes available to be plotted and # add them to the list for isos in self.h5s.isotopes: temp3 = qg.QStandardItem(str(isos[0])+str(isos[1])) temp3.setText(str(isos[0])+'-'+str(isos[1])) temp3.setEditable(False) self.dmodel1.appendRow(temp3) self.dialog.show() # Connect the list to the isotope selection function #self.connect(self.dlist1,qc.SIGNAL('doubleClicked(const QModelIndex &)'),self.select_isotope) # Accepts the users isotope subplot varaible selection # def select_isotope(self, QModelIndex): # selected = str(self.dmodel1.itemFromIndex(QModelIndex).text()) # if self.isos_to_plot.count(selected) == 0: # self.isos_to_plot.append(selected) # self.iso_input.setText(str(self.isos_to_plot)) # self.indexes.append(QModelIndex.row()) def do_sp(self): global write if self.y_data.count('iso_massf') or self.y_data.count('yps'): self.indexes = self.dlist1.selectedIndexes() for i in xrange(len(self.indexes)): self.isos_to_plot.append(str(self.dmodel1.itemFromIndex(self.indexes[i]).text())) self.indexes[i] = int(self.indexes[i].row()) self.dialog.close() self.write = qg.QCheckBox('Write To File', None) self.write.setCheckState(write) # Get the data the user selected (see h5file.py) #for cycs in self.cycle_of_interest: #data = self.h5s.fetch_datas(self.x_data,self.y_data,cycs, 1) xval = self.h5s.get(self.cycle_of_interest,self.x_data,1) yval = self.h5s.get(self.cycle_of_interest,self.y_data,1) try: if len(yval) < 2 and (self.y_data == 'iso_massf' or self.y_data == 'yps'): yval = yval[0] # Call subplot except AttributeError: print 'atribute error' self.SP.append(hrplot.subplot(self)) self.SP[-1].run(self.x_data,self.y_data,xval,yval,self.cycle_of_interest, self.indexes, self.h5s.isotopes, self.logx, self.logy) # Add the retruned plot to the self.tabs.addSubWindow(self.SP[-1].canvas,qc.Qt.SubWindow).show() mpl_toolbar = NavigationToolbar(self.SP[-1].canvas, self.tabs.activeSubWindow()) mpl_toolbar.move(10,25) mpl_toolbar.resize(500,50) mpl_toolbar.show() self.textEdit.append('Plot 1 Complete') #except AttributeError: self.connect(self.tabs.currentSubWindow(), qc.SIGNAL('destroyed()'),self.close_SP_thread) #del index#, xval, yval # free up some memory self.isos_to_plot = [] self.indexes = [] gc.collect() def close_SP_thread(self): print 'closing subplot' gc.collect() ########################################################################################### # # Abundance Plot over Time # ########################################################################################### def ab_dialog(self): self.dialog = qg.QDialog() self.dialog.setModal(True) # controllers for sparsity and block_plot mainbox = qg.QVBoxLayout() box1 = qg.QVBoxLayout() box2 = qg.QHBoxLayout() box3 = qg.QHBoxLayout() self.dialog.setLayout(mainbox) mainbox.addLayout(box1) mainbox.addLayout(box2) mainbox.addLayout(box3) sparse_label = qg.QLabel('Sparsity Factor') self.sparsity = qg.QLineEdit(None) self.sparsity.setReadOnly(False) self.sparsity.setText('10') self.write = qg.QCheckBox('Write To File', None) self.isos = qg.QLineEdit(None) self.isos.setText('Your Isotope Selections Will Appear Here') self.isos.setReadOnly(False) self.limit_scale = qg.QLineEdit(None) self.limit_scale.setReadOnly(False) self.limit_scale.setText('Select The Limit Scaling Factor. Defaults to 5') # self.box_plot = qg.QCheckBox('Do a true Kippenham Plot') # Add the widgets to first box box1.addWidget(sparse_label) box1.addWidget(self.sparsity) box1.addWidget(self.isos) box1.addWidget(self.write) # Add the widgets to first box box1.addWidget(sparse_label) box1.addWidget(self.sparsity) box1.addWidget(self.isos) # self.box1.addWidget(self.box_plot) self.dlist1 = qg.QListView() self.dlist1.setSelectionMode(qg.QAbstractItemView.ExtendedSelection) self.dmodel1 = qg.QStandardItemModel() self.dlist1.setModel(self.dmodel1) box2.addWidget(self.dlist1) #self.box1.addWidget(self.dlist2) for dcol in self.h5s.isotopes: temp3 = qg.QStandardItem(str(dcol[0])+str(dcol[1])) temp3.setText(str(dcol[0])+'-'+str(dcol[1])) temp3.setEditable(False) self.dmodel1.appendRow(temp3) # Add two buttons to accept the selected plot variables of the given cycle(s) # or close the dialog box and continue navigating the HR plot window accept = qg.QPushButton('Plot',None) deny = qg.QPushButton('Cancel',None) box3.addWidget(accept) box3.addWidget(deny) self.connect(deny,qc.SIGNAL('clicked()'),self.dialog.close) self.connect(accept,qc.SIGNAL('clicked()'),self.begin_AB_plot) #self.connect(self.dlist1,qc.SIGNAL('doubleClicked(const QModelIndex &)'),self.append_isotope) self.dialog.show() def begin_AB_plot(self): global write write = self.write.checkState() self.isotope_index = self.dlist1.selectedIndexes() for i in xrange(len(self.isotope_index)): self.isotope_index[i] = int(self.isotope_index[i].row()) print 'abundance plot index:',self.isotope_index self.dialog.close() all_age = [] Z = [] t0 = t.time() self.textEdit.append('Beginning Abundance Plot') # This grabs the user dcol from the KH_plot dialog try: scale = int(self.sparsity.text()) except ValueError: scale = 10 # Start fetching data all_age = self.h5s.get('age',scale) max_age = max(all_age) for x in xrange(len(all_age)): all_age[x] = np.log10((max_age - all_age[x])/3.15576e7 +1.e-8) max_strata = 0 if len(self.isotope_index) > 1: self.isotope_index = self.isotope_index[0] # this grabs the appropriate dcolrmation from the h5 files data = self.h5s.fetch_sparse_yps(False, scale,self.isotope_index,self.textEdit) all_mass = data[0] Z = data[1] del data self.isotope_index = [] t1 = t.time() self.textEdit.append( 'Data Aquisition time: ' + str(t1-t0)) # loop through the data and find the longest set of mass-coordinate data index_max_strata = 0 for x in xrange(len(Z)): #Z.append(self.h5s.get('iso_massf',self.h5s.cycles[x])) strata_len = len(Z[x]) if strata_len > max_strata: max_strata = strata_len index_max_strata = x ny = max_strata longest_line = all_mass[index_max_strata] t2 = t.time() self.textEdit.append( 'Strata Time: ' + str(t2-t1)) dy=1 dx=1 # This handles the pleasing abundance plots that happened to get lumped into this plot section z=np.zeros([len(self.h5s.cycles)/scale,len(longest_line)],float) for x in xrange(len(self.h5s.cycles)/scale): try: y = len(all_mass[x])-1 except IndexError: break index = y while y >=1 and index >= 0 : bot = all_mass[x][y-1] top = all_mass[x][y] if longest_line[index] < top and y < len(all_mass[x])-2: y -= 1 # we are too far to the right elif longest_line[index] > bot: y-=1 elif longest_line[index] >= top and longest_line[index] <= bot: dx = bot-top dxprime = longest_line[index]-all_mass[x][y] dy = Z[x][y-1]-Z[x][y] z[x][index] = Z[x][y]+dxprime*(dy/dx) index-=1 else: y-=1 #print 'percent: ' + str(float(x)/float(len(self.h5s.cycles))*100) t3 = t.time() self.write = qg.QCheckBox('Write To File', None) self.write.setCheckState(write) self.AB.append(hrplot.AB_Plot(all_age,all_mass,longest_line,z, self)) self.AB[-1].run() # Adds the the plot to the gui subwindow and adds a toolbar to the subwindow self.tabs.addSubWindow(self.AB[-1].canvas,qc.Qt.SubWindow).show() mpl_toolbar = NavigationToolbar(self.AB[-1].canvas, self.tabs.activeSubWindow()) mpl_toolbar.move(10,25) mpl_toolbar.resize(500,50) mpl_toolbar.show() self.connect(self.tabs.currentSubWindow(), qc.SIGNAL('destroyed()'),self.close_AB_plot) self.connect(self.AB[-1], qc.SIGNAL('finished()'),self.print_done) # cleanup the memory a little? #AB.__del__() del z, Z, longest_line, all_mass, all_age, mpl_toolbar #gc.collect() def close_AB_plot(self): gc.collect() def print_done(self): print 'Thread AB is done' # Adds an isotope to the list of isotopes to be plotted. # def append_isotope(self,QModelIndex): # if self.isotope_index.count(self.dlist1.selectedIndexes()[0].row()): # self.isotope_index.pop(self.isotope_index.index(self.dlist1.selectedIndexes()[0].row())) # else: # self.isotope_index.append(self.dlist1.selectedIndexes()[0].row()) # temp = '' # for x in xrange(len(self.isotope_index)): # temp+=str(self.h5s.isotopes[self.isotope_index[x]][0])+'-'+str(self.h5s.isotopes[self.isotope_index[x]][1])+str(',') # self.isos.setText(temp) #################################################################################### # # Special Kippenhahn Plot control # # Similar to the normal kippenhahn plot, but instead of using the convection # indicator to generate plot data, the elemental abundances compared # against a series of user inputted abundance limits # #################################################################################### def sp_kh_dialog(self): self.dialog2 = qg.QDialog() self.dialog2.setModal(True) mainbox = qg.QVBoxLayout() box0 = qg.QHBoxLayout() box1 = qg.QHBoxLayout() box2 = qg.QHBoxLayout() self.dialog2.setLayout(mainbox) self.variable_list = qg.QListView() self.variable_list.setSelectionMode(qg.QAbstractItemView.ExtendedSelection) self.variable_model = qg.QStandardItemModel() self.variable_list.setModel(self.variable_model) # self.connect(self.variable_list, qc.SIGNAL('activated(const QModelIndex &)'), self.add_element) accept_button = qg.QPushButton('Input Limits') deny_button = qg.QPushButton('Cancel') self.connect(accept_button,qc.SIGNAL('clicked()'), self.process_sp_input) self.connect(deny_button, qc.SIGNAL('clicked()'), self.dialog2.close) # label = qg.QLabel('Select an element by double clicking on it') # mainbox.addWidget(label) mainbox.addWidget(self.variable_list) # mainbox.addWidget(accept_button) # mainbox.addWidget(deny_button) for dcol in self.h5s.dcols: temp= qg.QStandardItem(str(dcol)) temp.setText(str(dcol)) temp.setEditable(False) self.variable_model.appendRow(temp) mainbox.addLayout(box0) mainbox.addLayout(box1) mainbox.addLayout(box2) min_cycle_label = qg.QLabel('Minimum Cycle') max_cycle_label = qg.QLabel('Maximumum Cycle') self.min_cycle_entry = qg.QLineEdit() self.max_cycle_entry = qg.QLineEdit() self.min_cycle_entry.setText(str(self.h5s.cycles[0])) self.max_cycle_entry.setText(str(self.h5s.cycles[-1])) #self.min_cycle_entry.text()), int(self.max_cycle_entry.text()) box0.addWidget(min_cycle_label) box0.addWidget(max_cycle_label) box1.addWidget(self.min_cycle_entry) box1.addWidget(self.max_cycle_entry) box2.addWidget(accept_button) box2.addWidget(deny_button) self.dialog2.show() def process_sp_input(self): self.dialog2.close() self.variable = [] indexes = self.variable_list.selectedIndexes() for i in xrange(len(indexes)): self.variable.append(str(self.variable_model.itemFromIndex(indexes[i]).text())) indexes[i] = int(indexes[i].row()) #print self.variable if self.variable.count('iso_massf'): self.select_isotopes_sp_kh() else: self.add_element() def select_isotopes_sp_kh(self): self.dialog = qg.QDialog() self.dialog.setModal(True) # controllers for sparsity and block_plot mainbox = qg.QVBoxLayout() box1 = qg.QVBoxLayout() box2 = qg.QHBoxLayout() box3 = qg.QHBoxLayout() self.dialog.setLayout(mainbox) mainbox.addLayout(box1) mainbox.addLayout(box2) mainbox.addLayout(box3) # sparse_label = qg.QLabel('Sparsity Factor') # self.sparsity = qg.QLineEdit(None) # self.sparsity.setReadOnly(False) # self.sparsity.setText('10') # self.write = qg.QCheckBox('Write To File', None) # self.isos = qg.QLineEdit(None) # self.isos.setText('Your Isotope Selections Will Appear Here') # self.isos.setReadOnly(False) # self.limit_scale = qg.QLineEdit(None) # self.limit_scale.setReadOnly(False) # self.limit_scale.setText('Select The Limit Scaling Factor. Defaults to 5') # self.box_plot = qg.QCheckBox('Do a true Kippenham Plot') # Add the widgets to first box # box1.addWidget(sparse_label) # box1.addWidget(self.sparsity) # box1.addWidget(self.isos) box1.addWidget(self.write) self.box1.addWidget(self.box_plot) self.dlist1 = qg.QListView() self.dlist1.setSelectionMode(qg.QAbstractItemView.ExtendedSelection) self.dmodel1 = qg.QStandardItemModel() self.dlist1.setModel(self.dmodel1) box2.addWidget(self.dlist1) #self.box1.addWidget(self.dlist2) for dcol in self.h5s.isotopes: temp3 = qg.QStandardItem(str(dcol[0])+str(dcol[1])) temp3.setText(str(dcol[0])+'-'+str(dcol[1])) temp3.setEditable(False) self.dmodel1.appendRow(temp3) # Add two buttons to accept the selected plot variables of the given cycle(s) # or close the dialog box and continue navigating the HR plot window accept = qg.QPushButton('Plot',None) deny = qg.QPushButton('Cancel',None) box3.addWidget(accept) box3.addWidget(deny) self.connect(accept, qc.SIGNAL('clicked()'),self.add_element) self.connect(deny,qc.SIGNAL('clicked()'), self.dialog.close) self.dialog.show() # Please excuse the poor naming of the function and related variables # It was originally written to handle isotopes def add_element(self): try: self.dialog2.close() self.dialog.close() except: None if self.variable.count('iso_massf'): self.variable.pop(self.variable.index('iso_massf')) self.variable.append('iso_massf') indexes = self.dlist1.selectedIndexes() for i in xrange(len(indexes)): self.variable.append(str(self.dmodel1.itemFromIndex(indexes[i]).text())) indexes[i] = int(indexes[i].row()) self.dialog = qg.QDialog() self.dialog.setModal(True) self.mainbox = qg.QVBoxLayout() box0 = qg.QVBoxLayout() #box0a = qg.QVBoxLayout() #box0b = qg.QHBoxLayout() box1 = qg.QHBoxLayout() self.element_limit_input = [] self.dialog.setLayout(self.mainbox) self.mainbox.addLayout(box0) self.write = qg.QCheckBox('Write To File', None) box0.addWidget(self.write) self.element_list = [] self.element_box = [] self.element_label = [] for i in xrange(len(self.variable)): if self.variable[i].count('iso_massf') == 0: #print 'adding variables', self.variable[i] self.element_list.append(qg.QLineEdit()) self.element_box.append(qg.QHBoxLayout()) #print 'adding element', self.variable[i] self.element_label.append(qg.QLabel(self.variable[i])) #self.element_label[-1].setText(self.element_list[i]) self.element_box[-1].addWidget(self.element_label[-1]) self.element_box[-1].addWidget(self.element_list[-1]) self.mainbox.addLayout(self.element_box[-1]) accept = qg.QPushButton('Accept') deny = qg.QPushButton('Deny') self.connect(accept,qc.SIGNAL('clicked()'), self.complete_sp_kh) self.connect(deny, qc.SIGNAL('clicked()'), self.dialog.close) self.mainbox.addLayout(box1) box1.addWidget(accept) box1.addWidget(deny) self.dialog.show() # Opens the dialog with the freshly generated limit boxes def complete_sp_kh(self): self.dialog.close() # Get the limits the user has selected cycle_list = [] age = [] # Get the range of cycles of interest, and the scale. # self.element_list --> self.variable_limit_input self.variable_limit_input = [] for i in xrange(len(self.element_list)): self.variable_limit_input.append(str(self.element_list[i].text())) try: ranger = [int(self.min_cycle_entry.text()), int(self.max_cycle_entry.text())] self.textEdit.append('Range: '+ str(ranger)) except: ranger = [int(self.h5s.cycles[0]), int(self.h5s.cycles[len(self.h5s.cycles)-1])] self.textEdit.append('Range: '+ str(ranger)) #Define the scale - TODO - set as user defined. self.scale = float(len(self.h5s.cycles[ranger[0]:ranger[1]]))/float(1000) if self.scale == 0: self.scale = 1 self.textEdit.append('Scale :'+ str(self.scale)) # Build the cycle list using the range and scale factor for x in xrange(int(round(len(self.h5s.cycles[ranger[0]:ranger[1]])/self.scale))): #print int(round(self.scale*x))+ranger[0] try: cycle_list.append(self.h5s.cycles[int(round(self.scale*x))+ranger[0]]) age.append(self.h5s.ages[int(round(self.scale*x))+ranger[0]]) except IndexError: None limits = [] # Get the plot limits and error check- throw away and limits that are not numbers for limit in self.variable_limit_input: lims = limit lim = lims.split(',') list_lims = [] for li in lim: try: list_lims.append(float(li)) except AttributeError: print 'Bad limit input: ', li limits.append(list_lims) # Decide how big a matrix me need to build total_len = 0 for lim in limits: total_len+=len(lim) # Fetch the necessary data mass = self.h5s.get(cycle_list,'mass', self.scale) variable_data = [] isodat = [] for var in self.variable: if self.h5s.dcols.count(var): self.textEdit.append('Fetching: ' +str(var)) variable_data.append(self.h5s.get(cycle_list,str(var),self.scale)) else: #We are fetching isotope data. IT requires a little more processing if isodat == []: isodat = self.h5s.get(cycle_list,'iso_massf',self.scale) while len(isodat) == 1: isodat = isodat[0] iso = var.split('-') for x in xrange(len(self.h5s.isotopes)): if iso[0] == self.h5s.isotopes[x][0] and iso[1] == str(self.h5s.isotopes[x][1]): iso_index = x break iso_dat = [] for dat in isodat: temp = [] for da in dat: temp.append(da[iso_index]) iso_dat.append(temp) variable_data.append(iso_dat) # All the data is now fetched and organized # Now build the matrix that holds the data Z = np.zeros([2*total_len,len(cycle_list)], float) # holds the data # Z = np.zeros([total_len,len(cycle_list)], float) curr_index = 0 first = True # Helps controll the 2 seperate lines we define for each limit for x in xrange(len(cycle_list)): # Step through the time steps for y in xrange(len(mass[x])-1): # Step through the mass coordinates #curr_index = 0 for z in xrange(len(limits)): #Step through the limits as provided by user limits[z].sort() for a in xrange(len(limits[z])): try: if (variable_data[z][x][y] >= limits[z][a] and variable_data[z][x][y+1] <= limits[z][a]) or (variable_data[z][x][y] <= limits[z][a] and variable_data[z][x][y+1] >= limits[z][a]): Z[curr_index][x] = max([mass[x][y],mass[x][y+1]]) except IndexError: None #print 'indexError' #curr_index+=1 curr_index+=2 if first: curr_index = 1 first = False else: curr_index = 0 first = True for x in xrange(len(Z)): for y in xrange(len(Z[x]-5)): catch =0 ind = 0 for z in xrange(3): try: if Z[x][y] == 0 and Z[x][y+z] > 0: catch+=1 ind = z except IndexError: None if catch > 2: Z[x][y] = Z[x][y+z] self.dialog = self.dialog self.sp_kh.append(hrplot.SP_KH_Plot(self.variable, limits, cycle_list, age,Z ,self)) self.sp_kh[-1].run() # Adds the the plot to the gui subwindow and adds a toolbar to the subwindow self.tabs.addSubWindow(self.sp_kh[-1].canvas,qc.Qt.SubWindow).show() mpl_toolbar = NavigationToolbar(self.sp_kh[-1].canvas, self.tabs.activeSubWindow()) mpl_toolbar.move(10,25) mpl_toolbar.resize(500,50) mpl_toolbar.show() # del elem_list, limits, cycle_list, ranger, age #self.connect(self.tabs.currentSubWindow(), qc.SIGNAL('destroyed()'),self.close_KH_thread) #self.connect(self.KH, qc.SIGNAL('finished()'), self.print_KH_done) def add_isotope_sp_kh(self): self.isos_to_plot = [] self.dialog1 = qg.QDialog() self.dialog1.setModal(True) mainbox = qg.QVBoxLayout() self.dialog1.setLayout(mainbox) self.textEdit.append('Beginning plot dialog') self.dialog1 = qg.QDialog() self.dialog1.setModal(True) # Build a layout box to stack widgets mainbox = qg.QVBoxLayout() box1 = qg.QVBoxLayout() box2 = qg.QHBoxLayout() # Define the box layouts position and role self.dialog1.setLayout(mainbox) mainbox.addLayout(box1) mainbox.addLayout(box2) # Build the lists containing the data that can be plotted self.dmodel1 = qg.QStandardItemModel() self.dlist1 = qg.QListView() self.dlist1.setSelectionMode(qg.QAbstractItemView.ExtendedSelection) self.dlist1.setModel(self.dmodel1) # Build user interaction mode- a line containing a label of selected isotops self.iso_input = qg.QLineEdit(None) self.iso_input.setText('Enter Isotopes Here. Defaults to All') self.iso_input.setReadOnly(False) # Add the widgets to first box box1.addWidget(self.iso_input) box1.addWidget(self.dlist1) # Build the control buttons # Cycle through list of isotopes available to be plotted and # add them to the list for isos in self.h5s.isotopes: #print isos temp3 = qg.QStandardItem(str(isos[0])+str(isos[1])) temp3.setText(str(isos[0])+'-'+str(isos[1])) temp3.setEditable(False) self.dmodel1.appendRow(temp3) self.dialog1.show() # Connect the list to the isotope selection function self.connect(self.dlist1,qc.SIGNAL('doubleClicked(const QModelIndex &)'),self.pick_element) def pick_element(self, QModelIndex): self.dialog1.close() self.variable.pop() self.variable.append(self.dmodel1.itemFromIndex(QModelIndex).text()) self.complete_add_element() ########################################################################################### # # Kippenhan Diagram Controll # ########################################################################################### # This controlls the plot dialog managing the KH diagram def kh_dialog(self): self.dialog = qg.QDialog() self.dialog.setModal(True) # controllers for sparsity and block_plot mainbox = qg.QVBoxLayout() box0 = qg.QVBoxLayout() box1 = qg.QHBoxLayout() box2 = qg.QHBoxLayout() box2a = qg.QHBoxLayout() box3 = qg.QHBoxLayout() self.dialog.setLayout(mainbox) mainbox.addLayout(box0) mainbox.addLayout(box1) mainbox.addLayout(box2) mainbox.addLayout(box2a) mainbox.addLayout(box3) title = qg.QLabel('Kippenhahn Plot') self.write = qg.QCheckBox('Write To File', None) box0.addWidget(title) box0.addWidget(self.write) min_age = qg.QLabel('minimum cycle, age') if self.h5s.ages == []: self.h5s.ages = self.h5s.get(self.h5s.cycles, 'age', 1) self.min_age_entry = qg.QLineEdit(str(self.h5s.ages[0])) self.min_age_entry.setReadOnly(True) self.min_cycle_entry = qg.QLineEdit(str(self.h5s.cycles[0])) self.min_cycle_entry.setReadOnly(False) box1.addWidget(min_age) box1.addWidget(self.min_cycle_entry) box1.addWidget(self.min_age_entry) #self.connect(self.min_age_entry, qc.SIGNAL('editingFinished()'), self.update_min_age) self.connect(self.min_cycle_entry, qc.SIGNAL('editingFinished()'), self.update_min_cycle) max_age = qg.QLabel('maximum cycle, age') self.max_age_entry = qg.QLineEdit(str(self.h5s.ages[len(self.h5s.ages)-1])) self.max_age_entry.setReadOnly(True) self.max_cycle_entry = qg.QLineEdit(str(self.h5s.cycles[len(self.h5s.cycles)-1])) self.max_cycle_entry.setReadOnly(False) box2.addWidget(max_age) box2.addWidget(self.max_cycle_entry) box2.addWidget(self.max_age_entry) #self.connect(self.max_age_entry, qc.SIGNAL('editingFinished()'), self.update_max_age) self.connect(self.max_cycle_entry, qc.SIGNAL('editingFinished()'), self.update_max_cycle) # Add an option to select either cycles or age for the x-axes self.cyc_or_age = qg.QCheckBox('Use cycles instead of age') box2a.addWidget(self.cyc_or_age) # Add two buttons to accept the selected plot variables of the given cycle(s) # or close the dialog box and continue navigating the HR plot window accept = qg.QPushButton('Plot',None) deny = qg.QPushButton('Cancel',None) box3.addWidget(accept) box3.addWidget(deny) self.connect(deny,qc.SIGNAL('clicked()'),self.dialog.close) self.connect(accept,qc.SIGNAL('clicked()'),self.begin_KH_plot) # self.connect(self.dlist1,qc.SIGNAL('doubleClicked(const QModelIndex &)'),self.append_isotope) self.dialog.show() def update_min_cycle(self): users_in = self.min_cycle_entry.text() if str(users_in).isdigit(): index = int(users_in) #index = self.h5s.cycles.index(int(users_in)) self.min_cycle_entry.setText(str(self.h5s.cycles[index])) self.min_age_entry.setText(str(self.h5s.ages[index])) if index < 0: self.min_cycle_entry.setText(str(self.h5s.cycles[0])) self.min_age_entry.setText(str(self.h5s.ages[0])) else: self.min_cycle_entry.setText(str(self.h5s.cycles[0])) self.min_age_entry.setText(str(self.h5s.ages[0])) def update_max_cycle(self): users_in = self.max_cycle_entry.text() if str(users_in).isdigit(): try: index = int(users_in) #index = self.h5s.cycles.index(int(users_in)) self.max_cycle_entry.setText(str(self.h5s.cycles[index])) self.max_age_entry.setText(str(self.h5s.ages[index])) except ValueError: self.max_cycle_entry.setText(str(self.h5s.cycles[len(self.h5s.cycles)-1])) self.max_age_entry.setText(str(self.h5s.ages[len(self.h5s.ages)-1])) else: self.max_cycle_entry.setText(str(self.h5s.cycles[len(self.h5s.cycles)-1])) self.max_age_entry.setText(str(self.h5s.ages[len(self.h5s.ages)-1])) # Gets the necessary information and performs the plot. def begin_KH_plot(self): checkstate = 0 #print self.h5s.cycles try: self.dialog.close() ranger = [self.h5s.cycles.index(self.min_cycle_entry.text()), self.h5s.cycles.index(self.max_cycle_entry.text())] print 'first ranger', ranger self.scale = float(len(self.h5s.cycles[ranger[0]:ranger[1]]))/float(1000) cyc_or_age = self.cyc_or_age.checkState() print self.scale except IndexError: ranger = [int(self.h5s.cycles[0]), int(self.h5s.cycles[len(self.h5s.cycles)-1])] cyc_or_age = self.cyc_or_age.checkState() if self.h5s.ages == [] or self.h5s.ages[0] == []: self.textEdit.append('Using Cycles instead of Ages') cyc_or_age = 2 all_age = [] Z = [] t0 = t.time() self.textEdit.append('Beginning Kippenhahn Plot') max_strata = 0 cycle_list = [] if self.scale == 0.0: print 'fixing scale' self.scale = 1.0 print self.scale for x in xrange(int(round(len(self.h5s.cycles[ranger[0]:ranger[1]])/self.scale))): # print self.cycles[int(round(scale*x))+ranger[0]] #str(int(round(self.cycles[ranger[0]:ranger[1]])/scale)+ ranger[0]) try: cycle_list.append(self.h5s.cycles[int(round(self.scale*x))+ranger[0]]) except IndexError: try: cycle_list.append(self.h5s.cycles[int(round(self.scale*(x-1)))+ranger[0]]) except IndexError: cycle_list.append(self.h5s.cycles[int(round(self.scale*(x-2)))+ranger[0]]) #age.append(self.ages[int(round(scale*x))+ranger[0]]) conv = self.h5s.fetch_KH_data(self.scale, ranger, cycle_list) all_age = [] if cyc_or_age == 0: all_age = self.h5s.get(cycle_list,'age',1) else: all_age = cycle_list for x in xrange(len(all_age)): all_age[x] = int(all_age[x]) #all_age, conv = self.h5s.fetch_KH_data(self.scale, ranger) # Do the plots self.KH.append(hrplot.KH_Plot(all_age,conv,self.scale, checkstate ,self)) self.KH[-1].run() # Adds the the plot to the gui subwindow and adds a toolbar to the subwindow self.tabs.addSubWindow(self.KH[-1].canvas,qc.Qt.SubWindow).show() mpl_toolbar = NavigationToolbar(self.KH[-1].canvas, self.tabs.activeSubWindow()) mpl_toolbar.move(10,25) mpl_toolbar.resize(500,50) mpl_toolbar.show() self.connect(self.tabs.currentSubWindow(), qc.SIGNAL('destroyed()'),self.close_KH_thread) self.connect(self.KH[-1], qc.SIGNAL('finished()'), self.print_KH_done) # cleanup the memory a little? del all_age, conv gc.collect() t1 = t.time() def print_KH_done(self): print 'KH Thread is done' def close_KH_thread(self): gc.collect() ############################################################################# # # Generic Plot Controller - will plot pretty much anything that you # have data on. # ############################################################################# # The first dialog the user encounters decides which datasets the user is interested in def g_dialog(self): # hp.setrelheap() self.dialog = qg.QDialog() mainbox = qg.QVBoxLayout() box0 = qg.QVBoxLayout() box0a = qg.QVBoxLayout() box1 = qg.QHBoxLayout() self.dialog.setLayout(mainbox) mainbox.addLayout(box0) mainbox.addLayout(box0a) mainbox.addLayout(box1) self.write = qg.QCheckBox('Write To File', None) label1 = qg.QLabel('Select the style of plot you wish to perform') self.plot_select = qg.QComboBox() self.plot_select.addItem('cattr Plot') self.plot_select.addItem('Data Plot') box0.addWidget(self.write) box0.addWidget(label1) box0.addWidget(self.plot_select) # The sparsity here is really important. Each cycle takes 64 kB memory and with >100 cycles to write # you will fast run out of memory. scale = qc.QString(str(int(len(self.h5s.cycles)/100))) if int(scale) <= 1: scale = '1' label2 = qg.QLabel('Select the sparsity-default gives 100 cycles.\nThis is important for memory conservation!') self.sparsity_line = qg.QLineEdit() self.sparsity_line.setText(scale) box0a.addWidget(label2) box0a.addWidget(self.sparsity_line) accept = qg.QPushButton('Next') deny = qg.QPushButton('Cancel') box1.addWidget(accept) box1.addWidget(deny) self.connect(accept, qc.SIGNAL('clicked()'), self.g_dialog_2) self.connect(deny, qc.SIGNAL('clicked()'), self.dialog.close) self.textEdit.append('Beginning Generic Plot') self.dialog.show() # The second dialog the user encounters allows the user to select the # Cycle(s) of interest and the datas category of interest def g_dialog_2(self): global write self.dialog.close() self.plot_type = self.plot_select.currentIndex() try: self.scale = int(self.sparsity_line.text()) except ValueError: self.scale = int(len(self.h5s.cycles)/100) write = self.write.checkState() self.dialog = qg.QDialog() mainbox = qg.QVBoxLayout() box0 = qg.QHBoxLayout() box1 = qg.QHBoxLayout() box2 = qg.QHBoxLayout() box3 = qg.QHBoxLayout() box3a = qg.QHBoxLayout() box4 = qg.QHBoxLayout() #box5 = qg.QHBoxLayout() self.dialog.setLayout(mainbox) mainbox.addLayout(box0) mainbox.addLayout(box1) mainbox.addLayout(box2) mainbox.addLayout(box3) mainbox.addLayout(box3a) mainbox.addLayout(box4) #mainbox.addLayout(box5) self.y_parm = [] self.cycle_to_plot = [] x_label = qg.QLabel('X axis') y_label = qg.QLabel('Y axis') box2.addWidget(x_label) box2.addWidget(y_label) # if we are plotting cattr build a list of cycles and cattrs to show if self.plot_type == 0: self.cycle_to_plot = [] # hp.setrelheap() self.data_list1 = qg.QListView() self.data_list1.setSelectionMode(qg.QAbstractItemView.ExtendedSelection) self.data_model1 = qg.QStandardItemModel() self.data_list1.setModel(self.data_model1) #self.connect(self.meta_list1, qc.SIGNAL('activated(const QModelIndex &)'), self.select_x_parm) self.data_list2 = qg.QListView() self.data_list2.setSelectionMode(qg.QAbstractItemView.ExtendedSelection) self.data_model2 = qg.QStandardItemModel() self.data_list2.setModel(self.data_model2) #self.connect(self.meta_list2, qc.SIGNAL('activated(const QModelIndex &)'), self.select_y_parm) temp1 = qg.QStandardItem('Cycle') temp2 = qg.QStandardItem('Cycle') self.data_model1.appendRow(temp1) self.data_model2.appendRow(temp2) for mets in self.h5s.cattrs: temp1 = qg.QStandardItem(mets) temp1.setText(mets) temp1.setEditable(False) self.data_model1.appendRow(temp1) temp2 = qg.QStandardItem(mets) temp2.setText(mets) temp2.setEditable(False) self.data_model2.appendRow(temp2) self.cyc_list = qg.QListView() self.cyc_list.setSelectionMode(qg.QAbstractItemView.ExtendedSelection) self.cyc_model = qg.QStandardItemModel() self.cyc_list.setModel(self.cyc_model) # self.connect(self.cyc_list,qc.SIGNAL('activated(const QModelIndex &)'),self.select_cyc) temp = qg.QStandardItem('All') temp.setText('All') temp.setEditable(False) self.cyc_model.appendRow(temp) # hp.setrelheap() # This is where you will have memory problems if the sparsity is set to low. for x in xrange(len(self.h5s.cycles)/self.scale): temp = qg.QStandardItem('cycle-'+str(self.h5s.cycles[self.scale*x])) temp.setEditable(False) self.cyc_model.appendRow(temp) box1.addWidget(self.cyc_list) box3.addWidget(self.data_list1) box3.addWidget(self.data_list2) # if we are doing a data plot build a list of data categories and cycles. elif self.plot_type == 1: self.data_list1 = qg.QListView() self.data_list1.setSelectionMode(qg.QAbstractItemView.ExtendedSelection) self.data_model1 = qg.QStandardItemModel() self.data_list1.setModel(self.data_model1) #self.connect(self.data_list1, qc.SIGNAL('activated(const QModelIndex &)'), self.select_x_parm) self.data_list2 = qg.QListView() self.data_list2.setSelectionMode(qg.QAbstractItemView.ExtendedSelection) self.data_model2 = qg.QStandardItemModel() self.data_list2.setModel(self.data_model2) #self.connect(self.data_list2, qc.SIGNAL('activated(const QModelIndex &)'), self.select_y_parm) for dcol in self.h5s.dcols: temp1 = qg.QStandardItem(dcol) temp1.setText(dcol) temp1.setEditable(False) self.data_model1.appendRow(temp1) temp2 = qg.QStandardItem(dcol) temp2.setText(dcol) temp2.setEditable(False) self.data_model2.appendRow(temp2) self.cyc_list = qg.QListView() self.cyc_list.setSelectionMode(qg.QAbstractItemView.ExtendedSelection) self.cyc_model = qg.QStandardItemModel() self.cyc_list.setModel(self.cyc_model) # self.connect(self.cyc_list,qc.SIGNAL('activated(const QModelIndex &)'),self.select_cyc) temp = qg.QStandardItem('All') temp.setText('All') temp.setEditable(False) self.cyc_model.appendRow(temp) for x in xrange(len(self.h5s.cycles)/self.scale): temp = qg.QStandardItem('cycle-'+str(self.h5s.cycles[self.scale*x])) #temp.setText('cycle-'+str(self.h5s.cycles[self.scale*x])) temp.setEditable(False) self.cyc_model.appendRow(temp) box1.addWidget(self.cyc_list) box3.addWidget(self.data_list1) box3.addWidget(self.data_list2) self.log_x = qg.QCheckBox('Log Scale x-axis', None) self.log_y = qg.QCheckBox('Log Scale y-axis', None) box3a.addWidget(self.log_x) box3a.addWidget(self.log_y) accept = qg.QPushButton('Plot') back = qg.QPushButton('Back') deny = qg.QPushButton('Cancel') self.write = qg.QCheckBox('Write To File', None) self.write.setCheckState(write) self.connect(accept, qc.SIGNAL('clicked()'), self.g_plot) self.connect(back, qc.SIGNAL('clicked()'), self.g_dialog) self.connect(deny, qc.SIGNAL('clicked()'), self.dialog.close) box4.addWidget(accept) box4.addWidget(back) box4.addWidget(deny) self.dialog.show() # When a cycle in the cyc_list is double clicked it is appended to the cycle_to_plot list, or removed if # already present # def select_cyc(self, QModelIndex): #if self.plot_type == 0: # if self.cycle_to_plot.count(str(self.cyc_model.itemFromIndex(QModelIndex).text())) == 0: # self.cycle_to_plot.append(str(self.cyc_model.itemFromIndex(QModelIndex).text())) # else: # self.cycle_to_plot.pop(self.cycle_to_plot.index(str(self.cyc_model.itemFromIndex(QModelIndex).text()))) # self.textEdit.append('Added new cycle: ' + str(self.cycle_to_plot)) # When an x-parameter is double clicked it becomes the x paramater to plot # def select_x_parm(self, QModelIndex): # if self.plot_type == 0: # self.x_parm = (str(self.meta_model1.itemFromIndex(QModelIndex).text())) # elif self.plot_type == 1: # self.x_parm = (str(self.data_model1.itemFromIndex(QModelIndex).text())) # self.textEdit.append('Selected x-axis: ' + str(self.x_parm)) # When a y parameter in either the meta_list or data_list, it is appended to the y_pparm list, or # removed if present # def select_y_parm(self, QModelIndex): # if self.plot_type == 0: # if self.y_parm.count(str(self.meta_model2.itemFromIndex(QModelIndex).text())) == 0: # self.y_parm.append(str(self.meta_model2.itemFromIndex(QModelIndex).text())) # else: # self.y_parm.pop(self.y_parm.index(str(self.meta_model2.itemFromIndex(QModelIndex).text()))) # elif self.plot_type == 1: # if self.y_parm.count(str(self.data_model2.itemFromIndex(QModelIndex).text())) == 0: # self.y_parm.append(str(self.data_model2.itemFromIndex(QModelIndex).text())) # else: # self.y_parm.pop(self.y_parm.index(str(self.data_model2.itemFromIndex(QModelIndex).text()))) # self.textEdit.append('Selected Y-axis: ' + str(self.y_parm)) def g_plot(self): cyc_indexes = self.cyc_list.selectedIndexes() x_indexes = self.data_list1.selectedIndexes() y_indexes = self.data_list2.selectedIndexes() self.cycle_to_plot = [] for index in cyc_indexes: self.cycle_to_plot.append(str(self.cyc_model.itemFromIndex(index).text())) self.x_parm = str(self.data_model1.itemFromIndex(x_indexes[0]).text()) self.y_parm = [] for index in y_indexes: self.y_parm.append(str(self.data_model2.itemFromIndex(index).text())) #FIXME -- fetching isotopes doesn't work!!! self.write = qg.QCheckBox('Write To File', None) self.write.setCheckState(write) # This is stupid, but the object is deleted otherwise. self.textEdit.append('Beginning plot') self.dialog.close() #scale = 1 self.x_data = [] self.y_data = [] self.x_log = self.log_x.checkState() self.y_log = self.log_y.checkState() try: for x in xrange(len(self.cycle_to_plot)): try: self.cycle_to_plot[x] = self.cycle_to_plot[x].split('-')[1] except IndexError: None self.cycle_to_plot.sort() except TypeError: print 'typeerror' except AttributeError: print 'attribute error' if self.y_parm.count('iso_massf') or self.y_parm.count('yps') and self.plot_type == 1: self.gp_iso_selection() else: self.g_plot2() def gp_iso_selection(self): self.isos_to_plot = [] ideal_factor = 1000/len(self.h5s.cycles) self.dialog = qg.QDialog() self.dialog.setModal(True) mainbox = qg.QVBoxLayout() self.dialog.setLayout(mainbox) self.textEdit.append('Beginning plot dialog') self.dialog = qg.QDialog() self.dialog.setModal(True) # Build a layout box to stack widgets mainbox = qg.QVBoxLayout() box1 = qg.QVBoxLayout() box2 = qg.QHBoxLayout() # Define the box layouts position and role self.dialog.setLayout(mainbox) mainbox.addLayout(box1) mainbox.addLayout(box2) # Build the lists containing the data that can be plotted self.dmodel1 = qg.QStandardItemModel() self.dlist1 = qg.QListView() self.dlist1.setSelectionMode(qg.QAbstractItemView.ExtendedSelection) self.dlist1.setModel(self.dmodel1) # Build user interaction mode- a line containing a label of selected isotops self.iso_input = qg.QLineEdit(None) self.iso_input.setText('Enter Isotopes Here. Defaults to All') self.iso_input.setReadOnly(False) #sparse_label = qg.QLabel('Sparsity Factor') #self.sparsity = qg.QLineEdit(str(1000/len(self.h5s.cycles))) # Add the widgets to first box #box1.addWidget(sparse_label) #box1.addWidget(self.sparsity) box1.addWidget(self.iso_input) box1.addWidget(self.dlist1) # Build the control buttons sp_button = qg.QPushButton('Do Plot',None) # Connect accept button to the fnction do_sp self.connect(sp_button,qc.SIGNAL('clicked()'),self.g_plot2) box1.addWidget(sp_button) # Cycle through list of isotopes available to be plotted and # add them to the list for isos in self.h5s.isotopes: temp3 = qg.QStandardItem(str(isos[0])+str(isos[1])) temp3.setText(str(isos[0])+'-'+str(isos[1])) temp3.setEditable(False) self.dmodel1.appendRow(temp3) self.dialog.show() # Connect the list to the isotope selection function # self.connect(self.dlist1,qc.SIGNAL('doubleClicked(const QModelIndex &)'),self.gp_select_isotope) def g_plot2(self): global write self.dialog.close() self.y_data = [] self.x_data = [] # if we are doing a cattr plot we fetch the appropriate data if self.plot_type == 0: # if the the user has selected more than one cycle if len(self.cycle_to_plot) > 1 or self.cycle_to_plot.count('All') == 1 or len(self.cycle_to_plot) == 0: if self.cycle_to_plot.count('All') or len(self.cycle_to_plot) == 0: self.cycle_to_plot = self.h5s.cycles print len(self.cycle_to_plot) if self.x_parm == 'Cycle': self.x_data.append(self.cycle_to_plot) else: self.x_data.append(self.h5s.get1(self.x_parm)) for yparm in self.y_parm: if yparm == 'Cycle': self.y_data.append(self.cycle_to_plot) else: self.y_data.append(self.h5s.get1(yparm)) else: for x in xrange(len(self.cycle_to_plot)): self.cycle_to_plot[x] = int(self.cycle_to_plot[x]) #self.cycle_to_plot = [self.cycle_to_plot] if self.x_parm == 'Cycle': self.x_data = [self.cycle_to_plot] else: self.x_data.append(self.h5s.get1(self.cycle_to_plot, self.x_parm)) temp = [] for yparm in self.y_parm: if yparm == 'Cycle': self.y_data.append(self.cycle_to_plot) else: self.y_data.append(self.h5s.get1(self.cycle_to_plot, yparm)) # if we are doing a data plot we fetch the appropriate data elif self.plot_type == 1: # if len(self.cycle_to_plot) == 0 or self.cycle_to_plot.count('All'): # self.x_data = self.h5s.get(self.x_parm,1) # for i in xrange(len(self.y_parm)): # x = [] # y = [] # yval = self.h5s.get(self.y_parm[i],1) # self.y_data.append(yval) if self.y_parm.count('iso_massf') or self.y_parm.count('yps'): try: self.y_parm.pop(self.y_parm.index('iso_massf')) except ValueError: self.y_parm.pop(self.y_parm.index('yps')) print 'iso_massf selected::::, ', self.y_parm selected = self.dlist1.selectedIndexes() isos = [] for selec in selected: isos.append(str(self.dmodel1.itemFromIndex(selec).text())) print 'isos', isos self.y_parm = isos print self.y_parm self.dialog.close() for k in xrange(len(self.cycle_to_plot)): for iso in isos: tempy = self.h5s.get1([self.cycle_to_plot[k]], 'iso_massf',iso) print 'iso', iso, tempy # while len(tempy) == 1: # print 'trimming in fetch' # tempy = tempy[0] # print len(tempy) self.y_data.append(tempy) tempx = self.h5s.get1([self.cycle_to_plot[k]], self.x_parm) # while len(tempx) == 1: # tempx = tempx[0] # print len(tempx) self.x_data.append(tempx) #self.y_data.append(self.h5s.get(self.cycle_to_plot, 'iso_massf', iso,1)) #print len(self.y_data[-1]) print 'Len iso', len(self.y_data), len(self.x_data) #try: # while len(self.y_data) == 1: # self.y_data = self.y_data[0] #except TypeError: # None else: #elif len(self.cycle_to_plot) > 0 : self.y_data = [] for cycle in self.cycle_to_plot: temp = [] for yparm in self.y_parm: temp.append(self.h5s.get1([cycle], yparm)) self.y_data.append(temp) self.x_data.append(self.h5s.get1([cycle], self.x_parm)) #print len(self.y_data), len(self.y_data[0])#, len(self.y_data[0][0]) self.complete_g_plot() def complete_g_plot(self): #self.y_parm = [] #for ind in self.indexes: # self.y_parm.append('Abundance: '+ str(self.h5s.isotopes[ind][0]) + '-' + str(self.h5s.isotopes[ind][1])) # print self.y_parm print len(self.x_data), len(self.y_data), len(self.cycle_to_plot) # All the data has been fetched. It is time to start plotting self.GP.append(hrplot.generic_plot(self.x_parm, self.y_parm, self.x_data, self.y_data, self.x_log, self.y_log, self.plot_type, self)) self.GP[-1].run() del self.x_data, self.y_data # Adds the the plot to the gui subwindow and adds a toolbar to the subwindow self.tabs.addSubWindow(self.GP[-1].canvas,qc.Qt.SubWindow).show() mpl_toolbar = NavigationToolbar(self.GP[-1].canvas, self.tabs.activeSubWindow()) mpl_toolbar.move(10,25) mpl_toolbar.resize(500,50) mpl_toolbar.show() self.connect(self.tabs.currentSubWindow(), qc.SIGNAL('destroyed()'),self.close_GP_thread) self.connect(self.GP[-1], qc.SIGNAL('finished()'), self.print_GP_done) def print_GP_done(self): print 'GP Thread is done' def close_GP_thread(self): print 'here' gc.collect() print self.GP print 'done destruction' ############################################################################################################### # # # Show Data Dialog # # # # This brings up a simple dialog box containing all the different categories that are # # within the loaded data # # # ################################################################################################################ def show_data(self): self.dialog = qg.QDialog() mainbox = qg.QVBoxLayout() box1 = qg.QHBoxLayout() box2 = qg.QHBoxLayout() box3 = qg.QHBoxLayout() self.dialog.setLayout(mainbox) mainbox.addLayout(box1) mainbox.addLayout(box2) mainbox.addLayout(box3) cycle_title = qg.QLabel('Cycles') meta_title = qg.QLabel('cattr') data_title = qg.QLabel('Data') box1.addWidget(cycle_title) box1.addWidget(meta_title) box1.addWidget(data_title) self.cyc_list = qg.QListView() self.cyc_list.setSelectionMode(qg.QAbstractItemView.ExtendedSelection) self.cyc_model = qg.QStandardItemModel() self.cyc_list.setModel(self.cyc_model) for x in xrange(len(self.h5s.cycles)): temp = qg.QStandardItem(self.h5s.cycles[x]) temp.setText('cycle-'+str(self.h5s.cycles[x])) temp.setEditable(False) self.cyc_model.appendRow(temp) self.meta_list1 = qg.QListView() self.meta_list1.setSelectionMode(qg.QAbstractItemView.ExtendedSelection) self.meta_model1 = qg.QStandardItemModel() self.meta_list1.setModel(self.meta_model1) for mets in self.h5s.cattrs: temp1 = qg.QStandardItem(mets) temp1.setText(mets) temp1.setEditable(False) self.meta_model1.appendRow(temp1) self.data_list1 = qg.QListView() self.data_list1.setSelectionMode(qg.QAbstractItemView.ExtendedSelection) self.data_model1 = qg.QStandardItemModel() self.data_list1.setModel(self.data_model1) for dcol in self.h5s.dcols: temp1 = qg.QStandardItem(dcol) temp1.setText(dcol) temp1.setEditable(False) self.data_model1.appendRow(temp1) box2.addWidget(self.cyc_list) box2.addWidget(self.meta_list1) box2.addWidget(self.data_list1) close_but = qg.QPushButton('Close') close_but.setFixedSize(80,40) self.connect(close_but, qc.SIGNAL('clicked()'), self.dialog.close) box3.addWidget(close_but) self.dialog.show() ######################################################################################### # # # Write Data to File Option. This is made avaiable for anyone who wishes # # to write data to file. The file name is automatic and column headers are # # written if available. Ignored if not # # # ######################################################################################### def write_to_file(self, xdata, ydata, xlabel, ylabel, plot_type): file_name = 'mppnp_plot_data_'+plot_type+str(self.plot_index) self.plot_index+=1 f = open(file_name,'w') if xlabel != None and ylabel != None and plot_type != None: f.write(plot_type+'\n') f.write(xlabel + '\t' + ylabel + '\n') try: size = int(np.ndim(ydata)) if size == 1: for x in xrange(ydata.shape[0]): f.write(str(xdata[x]) + '\t' + str(ydata[x]) + '\n') elif size == 2: #print 'who not here' try: for x in xrange(ydata.shape[0]): try: f.write(str(xdata[x])) except IndexError: print 'skipped xrow ', x for y in xrange(ydata.shape[1]): f.write('\t'+str(ydata[x][y])) f.write('\n') except AttributeError: for x in xrange(len(xdata)): f.write(str(xdata[x][0]) + '\t' + str(ydata[x][0]) + '\n') except TypeError: for x in xrange(len(ydata)): for y in xrange(len(ydata[x])): f.write(str(ydata[x][y])+'\t') f.write('\n') else: print size print 'Still not right' except IndexError: print 'not numpy' f.close() ######################################################################################### # # # isotopic abundance plot. plots the abundance of isotopes for # # a "reasonable" number of cycles # # # # reasonable - so the plot does not look like crap # # # ######################################################################################### def isotopic_abund(self): a_mass = self.h5s.get([self.h5s.cycles[0]],'mass', 1) if len(a_mass) == 1: ranges = [min(a_mass[0]), max(a_mass[0])] else: try: ranges = [min(a_mass), max(a_mass)] except IndexError: print 'index error: ',ranges self.dialog = qg.QDialog() mainbox = qg.QVBoxLayout() box1 = qg.QHBoxLayout() box2 = qg.QHBoxLayout() box2a = qg.QHBoxLayout() box3 = qg.QHBoxLayout() self.dialog.setLayout(mainbox) mainbox.addLayout(box1) mainbox.addLayout(box2) mainbox.addLayout(box2a) mainbox.addLayout(box3) self.ref_index = '' self.cyc_list = qg.QListView() self.cyc_list.setSelectionMode(qg.QAbstractItemView.ExtendedSelection) self.cyc_model = qg.QStandardItemModel() self.cyc_list.setModel(self.cyc_model) self.connect(self.cyc_list,qc.SIGNAL('doubleClicked(const QModelIndex &)'),self.append_cycle) box1.addWidget(self.cyc_list) self.scale = 1 # self.scale = float(1000)/len(self.h5s.cycles) # if len(self.h5s.cycles)/self.scale < 1 or self.scale < 1: # self.scale = 1 for x in xrange(int(len(self.h5s.cycles)/self.scale)): temp = qg.QStandardItem('cycle-'+str(self.h5s.cycles[int(self.scale*x)])) #temp.setText('cycle-'+str(self.h5s.cycles[self.scale*x])) temp.setEditable(False) self.cyc_model.appendRow(temp) self.element_list = qg.QListView() self.element_list.setSelectionMode(qg.QAbstractItemView.ExtendedSelection) self.element_model = qg.QStandardItemModel() self.element_list.setModel(self.element_model) # self.connect(self.element_list, qc.SIGNAL('activated(const QModelIndex &)'), self.append_element) box1.addWidget(self.element_list) self.cycle_to_plot = [] self.isotope_to_plot = [] #label = qg.QLabel('Select an element by double clicking on it') temp = qg.QStandardItem('ALL') temp.setText('ALL') temp.setEditable(False) self.element_model.appendRow(temp) new = True self.elem_list = ['' for x in xrange(len(self.elements_names)) ] # Build a list of elements self.elem_index = [[-1] for x in xrange(len(self.elements_names))] # #print 'len elem_index: ', len(self.elem_index) temp_index = [] # Holds a 1D list of isotopes for a single element temp_name = self.h5s.isotopes[0][0] # PLace holder for elem in self.elem_index: elem.remove(-1) for x in xrange(len(self.h5s.isotopes)): if self.elements_names.count(self.h5s.isotopes[x][0]): self.elem_index[self.elements_names.index(self.h5s.isotopes[x][0])].append(x) if self.elem_list.count(self.h5s.isotopes[x][0]) == 0: self.elem_list[self.elements_names.index(self.h5s.isotopes[x][0])] += self.h5s.isotopes[x][0] # Sort the indices so that the atomic masses come out in order-needed for nice plotting for x in xrange(len(self.elem_index)): numbers = [] for y in xrange(len(self.elem_index[x])): numbers.append(self.h5s.isotopes[self.elem_index[x][y]][1]) #list3 = zip(numbers, self.elem_index[x]) list3 = zip(self.elem_index[x], numbers) #print list3 list3.sort() #print list3 list3.sort() for y in xrange(len(list3)): self.elem_index[x][y] = list3[y][0] for dcol in self.elem_list: temp= qg.QStandardItem(dcol) temp.setText(dcol) temp.setEditable(False) self.element_model.appendRow(temp) range_label = qg.QLabel('Select Range for mass coord (min/max)') self.min_range = qg.QLineEdit(str(ranges[0])) self.max_range = qg.QLineEdit(str(ranges[1])) box2.addWidget(range_label) box2.addWidget(self.min_range) box2.addWidget(self.max_range) self.rel_abun_plot = qg.QCheckBox('Do Relative Plot') self.plot_only_stable = qg.QCheckBox('Plot only the stable isotopes') box2a.addWidget(self.rel_abun_plot) box2a.addWidget(self.plot_only_stable) accept =qg.QPushButton('Plot') deny = qg.QPushButton('Cancel') self.connect(accept, qc.SIGNAL('clicked()'), self.do_iso_abund) self.connect(deny, qc.SIGNAL('clicked()'), self.dialog.close) box3.addWidget(accept) box3.addWidget(deny) print 'finnished dialog' self.dialog.show() def append_cycle(self, QModelIndex): # if self.cycle_to_plot.count(str(self.cyc_model.itemFromIndex(QModelIndex).text())) == 0: # self.cycle_to_plot.append(str(self.cyc_model.itemFromIndex(QModelIndex).text())) # else: # self.cycle_to_plot.pop(self.cycle_to_plot.index(str(self.cyc_model.itemFromIndex(QModelIndex).text()))) self.ref_index = str(self.cyc_model.itemFromIndex(QModelIndex).text()) self.textEdit.append('Added new cycle: ' + str(self.ref_index)) #def append_element(self, QModelIndex): # self.ref_index = str(self.element_model.itemFromIndex(QModelIndex).text()) # self.textEdit.append('Reference Cycle:'+str(self.ref_index)) #if self.isotope_to_plot.count(str(self.element_model.itemFromIndex(QModelIndex).text())) == 0: # self.isotope_to_plot.append(str(self.element_model.itemFromIndex(QModelIndex).text())) #else: # self.isotope_to_plot.pop(self.isotope_to_plot.index(str(self.element_model.itemFromIndex(QModelImdex).text()))) #self.textEdit.append('Added new isotope: ' + str(self.isotope_to_plot)) def do_iso_abund(self): self.dialog.close() elms = self.element_list.selectedIndexes() cycs= self.cyc_list.selectedIndexes() for i in xrange(len(elms)): self.isotope_to_plot.append(str(self.element_model.itemFromIndex(elms[i]).text())) for i in xrange(len(cycs)): self.cycle_to_plot.append(str(self.cyc_model.itemFromIndex(cycs[i]).text())) rel_abunPlot = self.rel_abun_plot.checkState() plot_only_stable = self.plot_only_stable.checkState() if rel_abunPlot == 2 and self.ref_index == '': self.textEdit.append('Please double click on a reference cycle') self.isotopic_abund() print 'doing abundance plot', self.isotope_to_plot, rel_abunPlot # if self.cycle_to_plot == [] or (rel_abunPlot == 2 and len(self.cycle_to_plot) < 2): # self.isotopic_abund() # else: try: ranges = [] ranges.append(float(self.min_range.text())) ranges.append(float(self.max_range.text())) ranges.sort() # So the user can screw up the input without serious problems except TypeError: print 'problem with ranges' self.isotopic_abund() # abunds = [] # Holds the abundances index = [] # Holds the indices of interest # a_masses = [] # holds a list of the mass_coordinates cycs = [] # Fetch the abundance information we are in interested in for cycle in self.cycle_to_plot: cycs.append(cycle.split('-')[1]) # abunds = self.h5s.get(cycs,'iso_massf',1) a_masses = self.h5s.get(cycs,'mass',1) #print len(abunds), len(a_masses), len(abunds[0]), len(a_masses[0]) try: # self.ref_index print 'ref index::::', self.ref_index try: ref_mass = self.h5s.get([self.ref_index.split('-')[1]],'iso_massf',1) except: ref_mass = self.h5s.get([self.ref_index.split('-')[1]],'yps',1) ref_coords = self.h5s.get([self.ref_index.split('-')[1]],'mass',1) if len(ref_mass) == 1: ref_mass = ref_mass[0] # ref_coords = ref_coords[0] print len(ref_mass) except IndexError: print 'Performing normal plot' ref_mass = [] # Determine which isotopes we need to plot if self.isotope_to_plot.count('ALL') or self.isotope_to_plot == []: self.isotope_to_plot = self.elem_list for x in xrange(len(self.elem_list)): index.append(x) #print 'adding index', x # elif len(self.isotope_to_plot) == 2: # holder = self.isotope_to_plot.pop() # start = self.elem_list.index(self.isotope_to_plot[0]) # index.append(start) # start+=1 # while self.elem_list[start] != holder: # self.isotope_to_plot.append(self.elem_list[start]) # index.append(start) # start+=1 # self.isotope_to_plot.append(self.elem_list[start]) # index.append(start) else: print 'here' for x in xrange(len(self.isotope_to_plot)): index.append(self.elem_list.index(self.isotope_to_plot[x])) #print self.isotope_to_plot # If the user is interested in only the stable isotopes, we need to filter # with respect to that if plot_only_stable: # loop through the index list for t in xrange(15): removed = False for ind in index: # and the indice of isotope try: for iso in self.elem_index[ind]: for elem in self.stable_el: # Loop through the list of stable isotopes if self.h5s.isotopes[iso][0] == elem[0]: # Is it the same element? print self.h5s.isotopes[iso] matched = elem.count(int(self.h5s.isotopes[iso][1])) # Does the stable el list contain he isotope if matched == 0: try: #print 'removing', self.elem_index[ind], iso self.elem_index[ind].remove(iso) print 'removed', iso removed = True except: print 'failed to remove: ', self.isotope[iso] except IndexError: removed = True if removed == False: print 'done popping' break #print len(abunds), len(abunds[0]), len(abunds[0][0]) # We now have all the info we need. Just compile it into a useful form. In this case a 3D matix # cycles, elements, isotopes. this way the isotopes of a given element can be linked in the plot abund_plot = [] self.mass_num = [] try: abunds = self.h5s.get1(cycs, 'iso_massf') except : abunds = self.h5s.get1(cycs,'yps') if len(cycs) == 1: abunds = [abunds] #for i in xrange(len(self.cycle_to_plot)): # here = self.h5s.get([int(self.cycle_to_plot[i].split('-')[1])], 'iso_massf',1) # if len(here) == 1: # here = here[0] # abunds.append(here) # try: # abunds = abunds[0] # except IndexError: # print 'no trimming', len(abunds) # Loop through cycles to be plotted for i in xrange(len(self.cycle_to_plot)): time_step = [] # Loop through the mass coordinate to find the nearest indices for ranges # Loop through the indices of the element list we wish to plot for j in xrange(len(index)): # Loop through the elements temp = [] try: x = a_masses[i][0] del x except IndexError: a_masses = [a_masses] for k in xrange(len(self.elem_index[index[j]])): # Loop through the isotopes abundance = 0 #print 'elemIndexKs', self.elem_index[index[j]][k] try: for l in xrange(len(abunds[i])): try: if ranges[0] <= a_masses[i][l] and ranges[1] >= a_masses[i][l] : # Only collect data in etween ranges. #print abunds[i][l][self.elem_index[index[j]][k]] #if abunds[i][l][self.elem_index[index[j]][k]] < 1e-20: # abundance += 1e-20 try: abundance += (abunds[i][l][self.elem_index[index[j]][k]])*abs(a_masses[i][l+1]-a_masses[i][l]) except IndexError: # The last step requires us to interpolate to the next highest step abundance += (abunds[i][l][self.elem_index[index[j]][k]])*abs(round(a_masses[i][l])-a_masses[i][l]) except IndexError: None#print 'end of the line' #print abundance/abs(ranges[1]-ranges[0]) if abundance < 1e-20: abundance = 1e-20 temp.append(abundance/abs(ranges[1]-ranges[0])) except AttributeError: print i time_step.append(temp) #print time_step abund_plot.append(time_step) temp3 = [] for j in xrange(len(index)): temp = [] temp2 = [] for k in xrange(len(self.elem_index[index[j]])): temp.append(float(self.h5s.isotopes[self.elem_index[index[j]][k]][1])) abundance = 0 #print len(self.elem_index[index[j]]) for l in xrange(len(ref_mass)): if ranges[0] <= ref_coords[l] and ranges[1] >= ref_coords[l] : try: abundance += ref_mass[l][self.elem_index[index[j]][k]]*abs(ref_coords[l+1]-ref_coords[l]) except IndexError: abundance += ref_mass[l][self.elem_index[index[j]][k]]*abs(round(ref_coords[l])-ref_coords[l]) if abundance < 1e-20: abundance = 1e-20 #print abundance temp2.append(abundance/abs(ranges[1]-ranges[0])) #print temp3 self.mass_num.append(temp) temp3.append(temp2) ref_mass = temp3 del temp2 #print ref_mass # for ref in ref_mass: # print 'ref', ref #if len(abund_plot) == 1: # abund_plot = abund_plot[0] print 'doing plot' , len(ref_mass) self.IA.append(hrplot.IA_Plot(self,abund_plot, self.isotope_to_plot, index, rel_abunPlot, ranges, ref_mass)) self.IA[-1].run() del abund_plot, abunds # Adds the the plot to the gui subwindow and adds a toolbar to the subwindow self.tabs.addSubWindow(self.IA[-1].canvas,qc.Qt.SubWindow).show() mpl_toolbar = NavigationToolbar(self.IA[-1].canvas, self.tabs.activeSubWindow()) mpl_toolbar.move(10,25) mpl_toolbar.resize(500,50) mpl_toolbar.show() # self.connect(self.tabs.currentSubWindow(), qc.SIGNAL('destroyed()'),self.close_GP_thread) # self.connect(self.GP, qc.SIGNAL('finished()'), self.print_GP_done) ######################################################################################## # # Plotter GUI frontend controll # ######################################################################################## ############################################################################# # # File Navigator Components # ############################################################################# # The select all button. def select_all(self): global openFile # Gets the current path and all the files in it self.path = os.getcwd() self.files = os.listdir(self.path) files_of_interest = [] # Builds a list of h5 files and builds the complete filepath of these files for fil in self.h5files: if os.path.isfile(self.path + os.sep + fil): files_of_interest.append(self.path + os.sep + fil) #if fil.count('.h5'): # h5files.append(fil) # self.textEdit.append('added file: ' + str(fil)) #file_head = [h5files.split('.')[:len(h5files.split('.'))-3] , h5files.split('.')[:len(h5files.split('.'))-3] ] # Appends this list to the global variable openFile openFile = files_of_interest self.search_h5() # Used to build file navigator def check_folder(self): folder = os.getcwd() self.files = os.listdir(folder) self.textEdit.append('Current Location: ' + str(folder)) folders = [] self.h5files = [] useless_files = [] #print self.files # Loops through all the files in the current dir. # Sort directories, h5 files and all other files. for fil in self.files: if os.path.isdir(folder + os.sep + fil) and fil[0] != '.': folders.append(fil) elif os.path.isfile(folder + os.sep + fil): if fil.count('.h5'): self.h5files.append(fil) else: useless_files.append(fil) # Awesome sorting algorithm for these filenames self.h5files = sorted(self.h5files, cmp) # Build the navigator self.dcol = qg.QStandardItem() self.tree = qg.QStandardItemModel() self.dcol = qg.QStandardItem('..') # Provide the up-on-level option self.dcol.setText('..') self.dcol.setEditable(False) self.tree.appendRow(self.dcol) folder_col = qg.QColor(112266) dat_col = qg.QColor(110011) folders.sort() # Add folders to the list for fold in folders: self.dcol = qg.QStandardItem(fold) self.dcol.setText(fold) self.dcol.setEditable(False) self.dcol.setBackground(qg.QBrush(folder_col)) self.tree.appendRow(self.dcol) # Add h5files to the list try: for h5fil in self.h5files: self.dcol = qg.QStandardItem(h5fil) self.dcol.setText(h5fil) self.dcol.setEditable(False) self.dcol.setBackground(qg.QBrush(dat_col)) self.tree.appendRow(self.dcol) except UnboundLocalError: print 'No h5 files in dir' # Add the rest for us in useless_files: self.dcol = qg.QStandardItem(us) self.dcol.setText(us) self.dcol.setEditable(False) self.tree.appendRow(self.dcol) for x in xrange(len(self.files)): self.dcol = qg.QStandardItem(self.files[x]) self.dcol.setText(self.files[x]) self.dcol.setEditable(False) self.treeView.setModel(self.tree) # Handles the file selection for the buildTree function def open_file(self,QModelIndex): # Get the filepath selected ipath = str(os.getcwd()+os.path.sep+self.tree.itemFromIndex(QModelIndex).text()) ip = ipath.split('.') # if the selected is .., step up directory tree if self.tree.itemFromIndex(QModelIndex).text() == '..': os.chdir(ipath.rpartition(os.path.sep)[0].rpartition(os.path.sep)[0]) self.check_folder() else: if os.path.isdir(ipath): os.chdir(ipath) self.check_folder() #elif os.path.isfile(ipath) and ip[len(ip)-1].count('h5'): # self.textEdit.append('Selected file: ' + ipath) # openFile.append(ipath) else: self.textEdit.append('This is a file, not a folder') # This builds the file navigation window on the left side of the window def buildTree(self,path): self.treeView = qg.QListView() self.treeView.setSelectionMode(qg.QAbstractItemView.ExtendedSelection) self.check_folder() self.viewTool = qg.QDockWidget('File Navigator',None, qc.Qt.SubWindow) self.viewTool.setAllowedAreas(qc.Qt.LeftDockWidgetArea) self.viewTool.setFeatures(qg.QDockWidget.NoDockWidgetFeatures) # Set the initial path and add widget to the window self.addDockWidget(qc.Qt.LeftDockWidgetArea,self.viewTool) self.viewTool.setWidget(self.treeView) # Connect the clicked signal to the open_file function self.connect(self.treeView,qc.SIGNAL('doubleClicked(const QModelIndex &)'),self.open_file) # This function calls the h5FileHolder class using the user's selected files def search_h5(self): global openFile t1 = t.time() self.path = os.getcwd() #self.textEdit.append('Opening the selected files. This may take ~1 second per file.') indexes = self.treeView.selectedIndexes() for index in indexes: openFile.append(str(self.tree.itemFromIndex(index).text())) print 'openFile', openFile if len(openFile) == 2: #print 'opening ', openFile, self.h5files indexh5 = int(self.h5files.index(openFile[0].split('/')[int(len(openFile[0].split('/')))-1]))+1 indexf = 1 while self.h5files[indexh5] != openFile[indexf].split('/')[int(len(openFile[indexf].split('/')))-1]: openFile.insert(int(indexf),self.h5files[indexh5]) indexh5+=1 indexf +=1 #print 'opening ', openFile, self.h5files self.h5s = h5file.h5FileHolder(openFile,self.path, self.textEdit) if len(openFile) >1: self.make_wait() else: self.signal_done() def make_wait(self): print 'Making wait' #self.connect(self.h5s[-1], qc.SIGNAL('finished()'), self.signal_done) self.dialog = qg.QDialog() self.dialog.setModal(True) mainbox = qg.QHBoxLayout() self.dialog.setLayout(mainbox) wait_label = qg.QLabel('Loading Files, Please Wait.......') mainbox.addWidget(wait_label) self.dialog.show() print 'dialog shown' self.connect(self.textEdit, qc.SIGNAL('textChanged()'), self.signal_done) def signal_done(self): try: self.dialog.close() except AttributeError: None self.disconnect(self.textEdit, qc.SIGNAL('textChanged()'), self.signal_done) self.textEdit.append('Files read. You can begin plotting') def clear_mem(self): global openFile self.h5s.cycles = [] self.h5s.ages = [] self.h5s.cattrs = [] self.h5s.Tables = [] self.h5s.dcols = [] self.h5s.filepaths = [] openFile = [] # The list of files currently open in memory x_paramater = '' # A plotting parameter-What the x-axis should be y_paramater = '' # See above x_vals = [] # The actual data of interest y_vals = [] # plot_cattr = [] # An array to hold the cattr plot_data = [] for h5 in self.h5s.h5s: h5.cycle = [] h5.cattr = [] h5.dcol = [] h5.age = [] h5.data = [] h5.skipped_nodes = 0 h5.ver = '' h5.classname = '' h5.Table = [] h5.isomeric_state = [] h5.new = True h5.filename = None #del h5 del self.dcol self.h5files = [] self.h5s = [] self.path = '' # The current directory path self.isos_to_plot = [] # A list of isotopes to be plotted self.indexes = [] # A list of the indexes of the isotpes to be plotted self.cycle_of_interest = [] # A list of cycles that will be plotted in the abundance plot # self.isotopes = [] # A list of isotopes in the h5 file for abundance plot self.isotope_index = [] self.variable_limit_input = [] # For use in special kippenhahn plot self.variable = [] # Also for special kippenhahn self.plot_index = 1 # For writing to file. Need to number self.HP = [] self.AP = [] self.SP = [] self.AB = [] self.sp_kh = [] self.KH = [] self.GP = [] self.IA = [] self.textEdit.append('Memory Cleared') # Start the GUI! def __init__(self, parent = None): # Define the main window properties t0 = t.time() qg.QMainWindow.__init__(self, parent) qc.QThread.__init__(self,None) # hp.setrelheap() #py_compile.compile("h5file.py") #py_compile.compile("hrplot.py") #gc.DEBUG_LEAK self.setWindowTitle("Plotter") self.setGeometry(10,10,1200,900) self.textEdit = qg.QTextEdit() # Set the current path and build the file navigator self.path = os.getcwd() self.buildTree(self.path) # Build the plot window area self.tabs = qg.QMdiArea(None) self.setCentralWidget(self.tabs) # Build the text output box - provides basic instructions self.welcome = qg.QTextEdit() self.welcome.setReadOnly(True) self.welcome.append('Welcome to the h5 File plotter') self.welcome.append('This System is intended to simplify simply plotting by providing a GUI interface.') self.welcome.append('The controlbar to the left allows you to select files and perform plotting actions on their contents') self.welcome.setTextColor(qg.QColor(110011)) self.welcome.append('Useable files appear this color') self.welcome.setTextColor(qg.QColor(112266)) self.welcome.append('Folders appear this color') self.welcome.setTextColor(qg.QColor(000000)) self.welcome.append('The two dots allow you to back up') self.welcome.append('Once you have selected files, press the get data button and an HR plot will be generated.') self.welcome.append('Your plots should appear in the central window') self.tabs.addSubWindow(self.welcome,qc.Qt.SubWindow).showMaximized() # Build the text output box self.dialogTool = qg.QDockWidget('Dialog',None,qc.Qt.SubWindow) self.dialogTool.setFeatures(qg.QDockWidget.NoDockWidgetFeatures) #self.addToolBar(self.dialogTool) self.addDockWidget(qc.Qt.BottomDockWidgetArea,self.dialogTool) self.viewTool.setWidget(self.treeView) self.sub_plot_controller = qg.QLineEdit() self.connect(self.sub_plot_controller,qc.SIGNAL('textChanged (const QString&)'),self.do_hr_subplot) self.dialogTool.setWidget(self.textEdit) #self.dialogTool.setAllowedAreas(qg.BottomToolBarArea) self.textEdit.setText('Welcome to the h5 file plotter for ppn outputs') self.textEdit.append('Please select h5 files using the file navigator on the left') self.textEdit.append('and set any plotting options you may be interested in in the control window.') self.textEdit.setReadOnly(True) # Build the toolbar on the top of the GUI self.controllers_buttons = qg.QToolBar('Buttons',None) self.controllers_buttons.setAllowedAreas(qc.Qt.TopToolBarArea) self.controllers_buttons.setOrientation(qc.Qt.Vertical) # Attach the toolbar buttons self.controllers_buttons.addAction('Check Files',self.search_h5) # self.controllers_buttons.addAction('Select All Files In Dir.',self.select_all) # self.controllers_buttons.addAction('Clear Mem', self.clear_mem) # FIXME self.controllers_buttons.addAction('Do HR Plot',self.begin_HR_Plot) self.controllers_buttons.addAction('Kippenhahn Plot',self.kh_dialog) self.controllers_buttons.addAction('Special Kippenhahn', self.sp_kh_dialog) # self.controllers_buttons.addAction('Abundance Plot',self.ab_dialog) self.controllers_buttons.addAction('Generic Plot', self.g_dialog) self.controllers_buttons.addAction('Show Data', self.show_data) self.controllers_buttons.addAction('Iso Abund', self.isotopic_abund) self.addToolBar(self.controllers_buttons) def __del__(self): try: print 'Deleting GUI' #self.h5s.check_open_files() if self.h5s.h5Files != []: self.h5s.__del__() except AttributeError: print 'Nothing to destory:(' def __main__(): app = qg.QApplication(sys.argv) main_window = h5Plotter() main_window.show() #app.exec_() sys.exit(app.exec_()) app = qg.QApplication(sys.argv) main_window = h5Plotter() main_window.show() app.exec_()