コード例 #1
0
class Read_Cheat_Sheet(QWidget):
    def __init__(self, font, size_policy, base_directory):
        super().__init__()
        self.setWindowIcon(QIcon('BEI_Logo.png'))
        self.setWindowTitle('Cheat Sheet Reading')
        self.font = font
        self.size_policy = size_policy
        self.base_directory = base_directory
        self.setup()

    def setup(self):
        '''Setup the cheat sheet viewing
        '''
        self.display = QTextEdit(self)
        self.display.setFont(self.font)
        self.display.setSizePolicy(self.size_policy, self.size_policy)
        self.display.setReadOnly(True)

        self.options = QListView(self)
        self.options.setFont(self.font)
        self.options.setSizePolicy(self.size_policy, self.size_policy)
        #        self.options.setReadOnly(True)
        self.options.setEditTriggers(QAbstractItemView.NoEditTriggers)

        layout = QHBoxLayout(self)
        layout.addWidget(self.options)
        layout.addWidget(self.display)
        self.setLayout(layout)

        #get the different topics from cheat_sheet_topics.txt
        c = open(
            os.path.join(os.path.join(self.base_directory, 'Cheat_Sheets'),
                         'Topics.txt'), 'r')
        c_data = c.readlines()
        c.close()
        if len(c_data) == 0:
            replay = QMessageBox.information(
                self, 'No Cheat Sheets', 'There are currently no cheat sheets',
                QMessageBox.Ok)
            if replay == QMessageBox.Ok:
                self.close()
        else:
            self.topics = []
            for i in c_data:
                self.topics.append(i.replace('\n', ''))

            self.entry = QStandardItemModel()
            self.options.setModel(self.entry)

            self.options.doubleClicked[QModelIndex].connect(self.openFile)
            for tex in self.topics:
                self.entry.appendRow(QStandardItem(tex))
            self.show()

    def openFile(self, index):
        item = self.entry.itemFromIndex(index)
        text = str(item.text()).replace(' ', '_')
        #open the text file associated with the clicked item
        u = open(
            os.path.join(os.path.join(self.base_directory, 'Cheat_Sheets'),
                         '{}.txt'.format(text)), 'r')
        data = u.readlines()
        u.close()
        combi = ''
        for i in data:
            combi += i
        self.display.setText(combi)
コード例 #2
0
class Viewer(QMainWindow):
    loaded_spectrum = {}
    count_rates = {}
    plotted_spectrum = []
    e_plot = []
    e_calibration = []
    mini = 0
    maxi = 14
    plotted_tracking = []
    not_plotted_tracking = []

    def __init__(self):
        super().__init__()
        self.size_policy = QSizePolicy.Expanding
        self.font = QFont()
        self.font.setPointSize(12)
        self.setWindowTitle('Calibrated Spectrum Viewer')
        self.menu()
        self.geometry()
        self.showMaximized()
        self.show()

    def menu(self):
        self.menuFile = self.menuBar().addMenu('&File')
        self.load_new = QAction('&Load New Spectrum')
        self.load_new.triggered.connect(self.new_spectrum)
        self.load_new.setShortcut('Ctrl+O')
        self.load_new.setToolTip('Load a new calibrated spectrum')

        self.save_figure = QAction('&Save Spectrum Image')
        self.save_figure.triggered.connect(self.save_fig)
        self.save_figure.setShortcut('Ctrl+Shift+S')
        self.save_spec = QAction('&Save Spe File')
        self.save_spec.triggered.connect(self.spe)
        self.save_spec.setShortcut('Ctrl+S')
        self.menuFile.addActions(
            [self.load_new, self.save_figure, self.save_spec])

        self.menuEdit = self.menuBar().addMenu('&Edit')
        self.calibrate_spectrum = QAction('&Calibrate Spectrum')
        self.calibrate_spectrum.triggered.connect(self.spectrum_calibrate)
        self.calibrate_spectrum.setShortcut('Ctrl+G')
        self.calibrate_spectrum.setToolTip('Calibrate a raw spectrum')
        self.menuEdit.addActions([self.calibrate_spectrum])

        self.change_zoom = QAction('&Change Zoom Location')
        self.change_zoom.triggered.connect(self.zoom_change)
        self.change_zoom.setShortcut('Ctrl+Z')
        self.change_zoom.setToolTip('Change the initial zoom on the spectrum')

        self.menuView = self.menuBar().addMenu('&View Spectrum Data')
        self.view_energies = QAction('&View Energies')
        self.view_energies.setToolTip('Add Vertical Energy Lines')
        self.view_energies.triggered.connect(self.vert_lines)
        self.view_calibration_energies = QAction('&Calibration Energies')
        self.view_calibration_energies.triggered.connect(self.calib_lines)
        self.view_countrate = QAction('&Count Rates')
        self.view_countrate.triggered.connect(self.rate_tracking)
        self.roi_uncertainty = QAction('&ROI Uncertainties')
        self.roi_uncertainty.triggered.connect(self.roi_count_rate_uncertainty)
        self.res_action = QAction('&Energy Resolution')
        self.res_action.triggered.connect(self.find_peaks)

        self.menuView.addActions([
            self.view_energies, self.change_zoom,
            self.view_calibration_energies, self.view_countrate,
            self.roi_uncertainty, self.res_action
        ])

        self.menuList = self.menuBar().addMenu('&List Mode Data Analysis')
        self.timing_window = QAction('&View Time Decay')
        self.timing_window.triggered.connect(self.time_display)
        self.list_mode = QAction('&Analyze List Mode Data')
        self.list_mode.triggered.connect(self.list_moder)
        self.detection_probability = QAction('&Detection Probability')
        self.detection_probability.triggered.connect(self.detec_prob)
        self.dieaway = QAction('&Analyze Die Away')
        self.dieaway.triggered.connect(self.bck_die_away)
        self.video = QAction('&Save Probability Videos')
        self.video.triggered.connect(self.save_detec_videos)
        self.view_probs = QAction('&View Detection Probability')
        self.view_probs.triggered.connect(self.view_probabilities)

        self.menuList.addActions([
            self.timing_window, self.list_mode, self.detection_probability,
            self.dieaway, self.video, self.view_probs
        ])

    def geometry(self):
        self.open_ = QDockWidget('Loaded Spectrums')
        #initialize the widget to be used for loading the spectrum
        self.open_spectrum = QListView(self)
        self.open_spectrum.setFont(self.font)
        self.open_spectrum.setSizePolicy(self.size_policy, self.size_policy)
        self.open_spectrum.setEditTriggers(QAbstractItemView.NoEditTriggers)

        self.loader = QStandardItemModel()
        self.open_spectrum.setModel(self.loader)
        self.open_spectrum.doubleClicked[QModelIndex].connect(self.update_add)

        self.open_.setWidget(self.open_spectrum)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.open_)
        #initialize the widget to remove a spectrum from the plotter
        self.close_ = QDockWidget('Plotted Spectrum')
        self.close_spectrum = QListView(self)
        self.close_spectrum.setFont(self.font)
        self.close_spectrum.setSizePolicy(self.size_policy, self.size_policy)
        self.close_spectrum.setEditTriggers(QAbstractItemView.NoEditTriggers)

        self.unloader = QStandardItemModel()
        self.close_spectrum.setModel(self.unloader)
        self.close_spectrum.doubleClicked[QModelIndex].connect(
            self.update_close)

        self.close_.setWidget(self.close_spectrum)
        self.addDockWidget(Qt.RightDockWidgetArea, self.close_)

        #add the plot window
        self.plot_window = QWidget()
        layout = QVBoxLayout()
        self.figure = Figure()
        self._canvas = FigureCanvas(self.figure)
        self.toolbar = NavigationToolbar(self._canvas, self)
        layout.addWidget(self.toolbar)
        layout.addWidget(self._canvas)
        self.plot_window.setLayout(layout)
        self.setCentralWidget(self.plot_window)
        self.static_ax = self._canvas.figure.subplots()
        self.static_ax.set_yscale('log')
        self.static_ax.set_xlim(0, 14)
        self.static_ax.set_xlabel('Energy [MeV]')
        self.static_ax.set_ylabel('Count Rate [cps]')
        self.figure.tight_layout()

    def new_spectrum(self):
        self.vals = New()
        self.vals.add.clicked.connect(self.new_getter)

    def new_getter(self):
        self.vals.add_spectrum()
        counts = self.vals.counts
        calibr = self.vals.calibration
        legend = self.vals.legend.text()
        accum_time = self.vals.accum_time
        self.count_rates[legend] = self.vals.count_rate
        self.loaded_spectrum[legend] = [calibr, counts, accum_time]
        self.loader.appendRow(QStandardItem(legend))
        self.not_plotted_tracking.append(legend)

    def vert_lines(self):
        self.widget = QWidget()
        self.widget.setWindowTitle('Add Energies')
        current_lines = ''
        for i in range(len(self.e_plot)):
            if i != 0:
                current_lines += ',{}'.format(self.e_plot[i])
            else:
                current_lines += '{}'.format(self.e_plot[i])
        self.line = QLineEdit(self)
        self.line.setFont(self.font)
        self.line.setSizePolicy(self.size_policy, self.size_policy)
        self.line.setToolTip('Enter energies in MeV, seperated by commas')
        self.line.setText(current_lines)

        self.line_label = QLabel('Energies:', self)
        self.line_label.setFont(self.font)
        self.line_label.setSizePolicy(self.size_policy, self.size_policy)

        self.add = QPushButton('Update')
        self.add.setFont(self.font)
        self.add.setSizePolicy(self.size_policy, self.size_policy)
        self.add.clicked.connect(self.add_lines)
        layout = QGridLayout()
        layout.addWidget(self.line_label, 0, 0)
        layout.addWidget(self.line, 0, 1)
        layout.addWidget(self.add, 1, 0, 1, 2)
        self.widget.setLayout(layout)
        self.widget.show()

    def calib_lines(self):
        self.widget1 = QWidget()
        self.widget1.setWindowTitle('Add Energies')
        current_lines = ''
        for i in range(len(self.e_calibration)):
            if i != 0:
                current_lines += ',{}'.format(self.e_calibration[i])
            else:
                current_lines += '{}'.format(self.e_calibration[i])
        self.line1 = QLineEdit(self)
        self.line1.setFont(self.font)
        self.line1.setSizePolicy(self.size_policy, self.size_policy)
        self.line1.setToolTip(
            'Enter energies in MeV used for calibration, seperated by commas')
        self.line1.setText(current_lines)

        self.line_label1 = QLabel('Energies:', self)
        self.line_label1.setFont(self.font)
        self.line_label1.setSizePolicy(self.size_policy, self.size_policy)

        self.add1 = QPushButton('Update')
        self.add1.setFont(self.font)
        self.add1.setSizePolicy(self.size_policy, self.size_policy)
        self.add1.clicked.connect(self.add_cal_lines)
        layout = QGridLayout()
        layout.addWidget(self.line_label1, 0, 0)
        layout.addWidget(self.line1, 0, 1)
        layout.addWidget(self.add1, 1, 0, 1, 2)
        self.widget1.setLayout(layout)
        self.widget1.show()

    def add_lines(self):
        text = self.line.text().split(sep=',')
        try:
            self.e_plot = [float(i) for i in text]
        except:
            self.e_plot = []
        self.widget.close()
        self.replot()

    def add_cal_lines(self):
        text = self.line1.text().split(sep=',')
        try:
            self.e_calibration = [float(i) for i in text]
        except:
            self.e_calibration = []
        self.widget1.close()
        self.replot()

    def zoom_change(self):
        self.change_zoomed = QWidget()

        min_label = QLabel('Min:[MeV]', self)
        min_label.setFont(self.font)
        min_label.setSizePolicy(self.size_policy, self.size_policy)
        max_label = QLabel('Max:[MeV]', self)
        max_label.setFont(self.font)
        max_label.setSizePolicy(self.size_policy, self.size_policy)

        self.min_ = QLineEdit(self)
        self.min_.setFont(self.font)
        self.min_.setSizePolicy(self.size_policy, self.size_policy)
        self.min_.setText(str(self.mini))

        self.max_ = QLineEdit(self)
        self.max_.setFont(self.font)
        self.max_.setSizePolicy(self.size_policy, self.size_policy)
        self.max_.setText(str(self.maxi))

        self.add_ = QPushButton('Update')
        self.add_.setFont(self.font)
        self.add_.setSizePolicy(self.size_policy, self.size_policy)
        self.add_.clicked.connect(self.zoomed_update)

        layout = QGridLayout()
        layout.addWidget(min_label, 0, 0)
        layout.addWidget(self.min_, 0, 1)
        layout.addWidget(max_label, 1, 0)
        layout.addWidget(self.max_, 1, 1)
        layout.addWidget(self.add_, 2, 0, 1, 2)
        self.change_zoomed.setLayout(layout)
        self.change_zoomed.show()

    def zoomed_update(self):
        self.mini = float(self.min_.text())
        self.maxi = float(self.max_.text())
        self.change_zoomed.close()
        self.replot()

    def update_add(self, index):
        item = self.loader.itemFromIndex(index)
        val = item.text()
        self.plotted_spectrum.append(val)
        #add the item selected to the plotted side
        self.plotted_tracking.append(val)
        self.unloader.appendRow(QStandardItem(val))
        #remove all the values from the add plot
        self.loader.removeRows(0, self.loader.rowCount())
        #remove the values clicked from the not plotted list
        self.not_plotted_tracking.remove(val)
        #add the remaining items back to the options
        for i in self.not_plotted_tracking:
            self.loader.appendRow(QStandardItem(i))
        self.replot()

    def update_close(self, index):
        item = self.unloader.itemFromIndex(index)
        val = item.text()
        self.plotted_spectrum.remove(val)
        #add the value to the not plotted side
        self.not_plotted_tracking.append(val)
        self.loader.appendRow(QStandardItem(val))
        #remove all the values from the unloading side
        self.unloader.removeRows(0, self.unloader.rowCount())
        #remove the value from the tracking list
        self.plotted_tracking.remove(val)
        #put the items back into the unloader
        for i in self.plotted_tracking:
            self.unloader.appendRow(QStandardItem(i))
        self.replot()

    def replot(self):
        self.static_ax.clear()
        self.mouse_tracking()
        self.static_ax.set_yscale('log')
        self.static_ax.set_xlim(self.mini, self.maxi)
        self.static_ax.set_xlabel('Energy [MeV]')
        self.static_ax.set_ylabel('Count Rate [cps]')
        current = list(self.static_ax.get_xticks())

        for i in self.e_plot:
            current.append(i)
            self.static_ax.axvline(i, color='r', linestyle='--', linewidth=0.8)
        for i in self.e_calibration:
            current.append(i)
            self.static_ax.axvline(i, color='k', linestyle='-', linewidth=1)

        for i in self.plotted_spectrum:
            spec = self.loaded_spectrum[i]
            self.static_ax.plot(spec[0],
                                spec[1],
                                label='{}, Accum Time: {}s'.format(i, spec[2]))

        current = [round(float(k), 2) for k in current]
        self.static_ax.set_xticks(current)
        self.static_ax.set_xticklabels(current, rotation=90)
        self.static_ax.legend(prop={'size': 18})
        #        self.static_ax.tick_params(labelsize=18)
        self._canvas.draw()
        self.figure.tight_layout()

    def save_fig(self):
        options = 'Portable Network Graphics (*.png);;'
        options_ = 'Joint Photographic Experts Group(*.jpg)'
        options = options + options_
        file_name, ok = QFileDialog.getSaveFileName(self,
                                                    'Spectrum Image Save', "",
                                                    options)

        if file_name and ok:
            self.figure.savefig(file_name, dpi=600, figsize=(10, 10))

    def spectrum_calibrate(self):
        '''Launch a calibration window
        '''
        self.calibrator = Window()

    def rate_tracking(self):
        '''Show the count rate for all the loaded spectrum
        '''
        self.rater = QWidget()
        self.rater.setWindowTitle('Count Rates')
        editor = QTextEdit()
        editor.setFont(self.font)
        editor.setReadOnly(True)
        editor.setSizePolicy(self.size_policy, self.size_policy)

        for i in list(self.count_rates.keys()):
            editor.append('{}: {:,.2f}cps'.format(i, self.count_rates[i]))
        layout = QVBoxLayout()
        layout.addWidget(editor)
        self.rater.setLayout(layout)
        self.rater.show()

    def mouse_tracking(self):
        self.txt = self.static_ax.text(0.85,
                                       0.6,
                                       "",
                                       transform=self.static_ax.transAxes)
        self.figure.canvas.mpl_connect('motion_notify_event', self.mouse_move)

    def mouse_move(self, event):
        if not event.inaxes:
            return
        self.txt.set_text('Energy: {:,.3f} MeV'.format(event.xdata))
        self._canvas.draw()

    def roi_display(self):
        '''Determine the number of counts 
        in a specified ROI and display them
        '''
        self.change_roi = QWidget()

        min_label = QLabel('Min:[MeV]', self)
        min_label.setFont(self.font)
        min_label.setSizePolicy(self.size_policy, self.size_policy)
        max_label = QLabel('Max:[MeV]', self)
        max_label.setFont(self.font)
        max_label.setSizePolicy(self.size_policy, self.size_policy)

        self.min_roi = QLineEdit(self)
        self.min_roi.setFont(self.font)
        self.min_roi.setSizePolicy(self.size_policy, self.size_policy)

        self.max_roi = QLineEdit(self)
        self.max_roi.setFont(self.font)
        self.max_roi.setSizePolicy(self.size_policy, self.size_policy)

        self.add_roi = QPushButton('Update')
        self.add_roi.setFont(self.font)
        self.add_roi.setSizePolicy(self.size_policy, self.size_policy)
        self.add_roi.clicked.connect(self.roi_update)

        layout = QGridLayout()
        layout.addWidget(min_label, 0, 0)
        layout.addWidget(self.min_roi, 0, 1)
        layout.addWidget(max_label, 1, 0)
        layout.addWidget(self.max_roi, 1, 1)
        layout.addWidget(self.add_roi, 2, 0, 1, 2)
        self.change_roi.setLayout(layout)
        self.change_roi.show()

    def roi_update(self):
        self.change_roi.close()
        roi_counts = {}
        for i in self.plotted_spectrum:
            calibration = self.loaded_spectrum[i]
            ma = 0
            mi = len(calibration[0])
            for j in range(len(calibration[0])):
                if calibration[0][j] <= float(self.max_roi.text()):
                    ma = j
                if calibration[0][j] <= float(self.min_roi.text()):
                    #                    print(calibration[0][j])
                    mi = j
#            print(mi,ma)
            roi_counts[i] = self.loaded_spectrum[i][1][mi:ma]


#        scale the rois by the accumulation time and determine the sum of the
#        area using np
        roi = {}
        for i in list(roi_counts.keys()):
            timer = float(self.loaded_spectrum[i][2])
            scale = 0
            for j in range(len(roi_counts[i])):
                scale += roi_counts[i][j]  #*timer
            roi[i] = scale
        self.roi_counts = roi
        if self.display == False:
            self.uncertain()
        if self.display:
            self.display_roi = QWidget()
            self.display_roi.setWindowTitle('ROI counts')
            rois = QTextEdit()
            rois.setFont(self.font)
            rois.setSizePolicy(self.size_policy, self.size_policy)
            for i in list(roi.keys()):
                rois.append('{}: {:.4f} cps'.format(i, roi[i]))
            layout = QVBoxLayout()
            layout.addWidget(rois)
            self.display_roi.setLayout(layout)
            self.display_roi.show()
        self.display = True

    def spe(self):
        '''Save the selected file out to an spe file format, even though the
        calibration will likely not be correct
        '''
        items = self.loaded_spectrum.keys()
        text, ok = QInputDialog.getItem(self, 'Save Spectrum', 'Saving:',
                                        items, 0, False)
        if ok and text:
            name = QFileDialog.getSaveFileName(self, 'Spe File Name', '',
                                               'IAEA (*.spe)')
            if name != " ":
                try:
                    Save_Spe(self.loaded_spectrum[text], text, name)
                except:
                    pass

    def time_display(self):
        self.di = Time_Window()

    def list_moder(self):
        self.lm = List_Mode_Viewer()

    def roi_count_rate_uncertainty(self):
        '''Calculate the std of the ROI count rates-- will 
        eventaully have the ability to indicate which loaded spectrum 
        are desired'''
        self.display = False
        self.roi_display()
        # self.display=True
    def uncertain(self):
        # now to select the foreground and background spectrum:
        foreground, ok = QInputDialog.getItem(self, 'Foreground',
                                              'Select Foreground',
                                              self.roi_counts.keys(), 0, False)
        background, ok2 = QInputDialog.getItem(self, 'Background',
                                               'Select Background',
                                               self.roi_counts.keys(), 0,
                                               False)
        if ok and ok2:
            #get the count rates from both of them
            uncer = net_std(self.roi_counts[foreground],
                            self.roi_counts[background])
            u = uncer.calculate_uncertainties()
            net_cr = self.roi_counts[foreground] - self.roi_counts[background]
            self.uncertainty_display(u, net_cr, foreground, background)

    def uncertainty_display(self, net_uncer, net_count_rate, foreground,
                            background):
        self.rateu = QWidget()
        self.rateu.setWindowTitle('Count Rates')
        editor = QTextEdit()
        editor.setFont(self.font)
        editor.setReadOnly(True)
        editor.setSizePolicy(self.size_policy, self.size_policy)
        fore_cps = self.roi_counts[foreground]
        back_cps = self.roi_counts[background]
        editorappd = [
            'Foreground: {}: {:.3f} +\- {:.3f} cps'.format(
                foreground, fore_cps,
                fore_cps**0.5), 'Background: {}: {:.3f} +\- {:.3f} cps'.format(
                    background, back_cps, back_cps**0.5),
            'Net: {:.3f} +\- {:.3f} cps'.format(net_count_rate, net_uncer)
        ]
        for i in editorappd:
            editor.append(i)

        layout = QVBoxLayout()
        layout.addWidget(editor)
        self.rateu.setLayout(layout)
        self.rateu.show()

    def bck_die_away(self):
        #get the file
        file_name, ok = QFileDialog.getOpenFileName(
            self, 'Background Die Away List Mode File', "",
            'Comma Seperated File (*.csv);;Text File (*.txt)')

        num_bins, ok2 = QInputDialog.getInt(self, 'Enter number of bins',
                                            'Bins:', 300, 0, 10000)
        if file_name != '' and ok and ok2:
            cts, time = bkg(file_name, num_bins).process_data()
            io = max(cts[1::])
            index = (np.abs(cts - io / 2)).argmin()
            t_12 = time[index]
            lambd = np.log(2) / t_12
            fit = [io * np.exp(-lambd * i) for i in time]
            plt.plot(time[1::], cts[1::], '*')
            # plt.plot(time[1::],fit[1::])
            plt.ylabel('Count Rate (cps)')
            plt.xlabel('Time (s)')
            plt.show()
            f = open('Back_Die_Away.csv', 'w')
            f.write('Time,Counts\n')
            for i in range(len(cts)):
                f.write('{:.5f},{:.5f}\n'.format(cts[i], time[i]))
            f.close()

    def detec_prob(self):
        #get the foreground and background file names and info
        #get the file
        file_nameb, ok = QFileDialog.getOpenFileName(
            self, 'Background List Mode File', "",
            'Comma Seperated File (*.csv);;Text File (*.txt)')
        file_namef, ok2 = QFileDialog.getOpenFileName(
            self, 'Foreground List Mode File', "",
            'Comma Seperated File (*.csv);;Text File (*.txt)')
        if ok and ok2:
            num, ok3 = QInputDialog.getInt(self, 'Detection Probability',
                                           'Percentage:', 99, 0, 100)
            if ok3:
                evals = np.linspace(0, 1800, 181)
                detection_probability = DT(file_namef, file_nameb, evals)
                probs = detection_probability.probs
                probs = [i * 100 for i in probs]
                #need to parse through the probabilities and find the first
                #real data point that doesn't represent a statistical anamoly
                #set a lower threshold to start counting at
                threshold = 90  #if the probability drops below this
                s_index = 0
                for i in range(len(probs)):
                    if probs[i] <= threshold:
                        s_index = i
                        break
                probs = probs[s_index::]
                evals = evals[s_index::]
                time_detect = np.interp(num, probs, evals)
                plt.figure(1)
                plt.plot(evals, probs, '*')
                plt.axvline(
                    time_detect,
                    label='Time to {}% detection probability: {:.2f}s'.format(
                        num, time_detect))
                plt.xlabel('Time(s)')
                plt.ylabel('Probability (%)')
                plt.legend()
                # print(probs)
                plt.show()

                #save the raw data out
                fore_sums = detection_probability.f_sums[s_index::]
                back_sums = detection_probability.b_sums[s_index::]
                analysis_times = detection_probability.a_times[s_index::]
                raw_name, ok3 = QFileDialog.getSaveFileName(
                    self, 'Raw Data Save File Name', "",
                    'Comma Seperated File (*.csv);;Text File (*.txt)')
                if ok3:
                    f = open(raw_name, 'w')
                    for i in range(len(fore_sums)):
                        f.write('{},{},{:.4f},{:.4f}\n'.format(
                            fore_sums[i], back_sums[i], analysis_times[i],
                            probs[i]))
                    f.close()

    def save_detec_videos(self):
        file_nameb, ok = QFileDialog.getOpenFileName(
            self, 'Raw Data File', "",
            'Comma Seperated File (*.csv);;Text File (*.txt)')
        file_nameg, ok1 = QFileDialog.getSaveFileName(self, 'Curve Save File',
                                                      "", 'Multimeda (*.mp4)')
        file_namep, ok2 = QFileDialog.getSaveFileName(self,
                                                      'Probability Save File',
                                                      "", 'Multimeda (*.mp4)')

        if ok and ok1 and ok2:
            Movie = movie(file_nameb, file_nameg, file_namep)
            Movie.save_gaussian()
            Movie.save_probability()

    def find_peaks(self):
        #first get all the plotted spectrum names
        loaded_spectrum = self.plotted_spectrum
        selection, ok = QInputDialog.getItem(self, 'Energy Resolution',
                                             'Selection', loaded_spectrum, 0,
                                             False)
        if ok:
            x = self.loaded_spectrum[selection][1]
            y = self.loaded_spectrum[selection][0]
            #then let the user select which one to pick

            #then get the counts to analyze

            peaks, properties = signal.find_peaks(x, width=3, distance=2)
            e_res = []
            widths = properties['widths']  #the fwhm of the peak
            left = properties['left_ips']  #left point of the fwhm
            right = properties['right_ips']  #right point of the fwhm
            sigma = [i / (2 * np.sqrt(2 * np.log(2)))
                     for i in widths]  #standard deviation
            left_sig = []
            right_sig = []
            #recalculate the peak location based on the average fo the left and right fwhm
            for i in range(len(peaks)):
                avg = (left[i] + right[i]) / 2
                peaks[i] = avg
                left_sig.append(avg - 4 * sigma[i])
                right_sig.append(avg + 4 * sigma[i])
                e_res.append(widths[i] / avg * 100)

            plt.plot(y, x)
            plt.yscale('log')
            _, y_max = plt.gca().get_ylim()
            y_max = y_max - .5 * y_max
            for i in range(len(peaks)):
                plt.axvline(y[int(peaks[i])],
                            linestyle='--',
                            color='m',
                            linewidth=1)
                v = y[int(peaks[i])] + 0.005 * y[int(peaks[i])]
                plt.annotate('{:.2f}%'.format(e_res[i]),
                             xy=(v, y_max),
                             rotation='vertical',
                             color='m')
            # plt.axvspan(y[int(left_sig[2])],y[int(right_sig[2])],facecolor='g',alpha=0.5)
            plt.show()
            return peaks, e_res

    def view_probabilities(self):
        self.view = Plotter()
コード例 #3
0
class Calibration_Window(QMainWindow):
    '''Open a calibration window that allows the user to select the calibration
    style. Allows the user to click on location in graph to select the 
    channels to calibrate and gets the required energy at that point
    '''
    counts = []
    channels = []
    calibration_lines = []
    energies = {}

    def __init__(self):
        super().__init__()
        self.font = QFont()
        self.font.setPointSize(12)
        self.size_policy = QSizePolicy.Expanding
        self.setWindowTitle('Energy Calibration')
        self.menu()
        self.geometry()
        self.mouse_tracking()
        self.showMaximized()
        self.show()

    def menu(self):
        self.menuFile = self.menuBar().addMenu('&File')
        self.load_new = QAction('&Load New Spectrum')
        self.load_new.triggered.connect(self.new_spectrum)
        self.load_new.setShortcut('Ctrl+O')
        self.load_new.setToolTip('Load a raw spectrum')

        self.rebin_action = QAction('&Rebin Data')
        self.rebin_action.triggered.connect(self.rebin)
        self.rebin_action.setEnabled(False)
        self.rebin_action.setShortcut('Ctrl+B')

        self.rebin_action_save = QAction('&Save Rebin Count')
        self.rebin_action_save.triggered.connect(self.save_rebinned)
        self.rebin_action_save.setEnabled(False)
        self.rebin_action_save.setShortcut('Ctrl+Shift+S')

        self.calibrateAction = QAction('&Calibrate')
        self.calibrateAction.triggered.connect(self.calibration)
        self.calibrateAction.setShortcut('Ctrl+C')
        self.calibrateAction.setDisabled(True)

        self.save = QAction('&Save Calibration')
        self.save.triggered.connect(self.save_)
        self.save.setShortcut('Ctrl+S')
        self.save.setDisabled(True)
        self.menuFile.addActions([
            self.load_new, self.rebin_action, self.calibrateAction, self.save,
            self.rebin_action_save
        ])

    def geometry(self):
        '''Setup the geometry
        '''
        self.added_values = QListView(self)
        self.added_values.setFont(self.font)
        self.added_values.setSizePolicy(self.size_policy, self.size_policy)
        self.added_values.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.added_ = QDockWidget('Calibration Values')
        self.added_.setWidget(self.added_values)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.added_)

        self.loaded = QStandardItemModel()
        self.added_values.setModel(self.loaded)
        self.added_values.doubleClicked[QModelIndex].connect(self.update)

        self.calibrate = QPushButton('Calibrate')
        self.calibrate.setFont(self.font)
        self.calibrate.setSizePolicy(self.size_policy, self.size_policy)
        self.calibrate.clicked.connect(self.calibration)

        self.plot = QWidget()
        layout = QVBoxLayout()
        self.figure = Figure()
        self.canvas = FigureCanvas(self.figure)
        self.toolbar = NavigationToolbar(self.canvas, self)
        layout.addWidget(self.toolbar)
        layout.addWidget(self.canvas)
        self.plot.setLayout(layout)
        self.ax = self.canvas.figure.subplots()
        self.ax.set_yscale('log')
        self.ax.set_xlabel('Channel')
        self.ax.set_ylabel('Counts')
        self.figure.tight_layout()

        self.calibrated_plot = QWidget()
        layout1 = QVBoxLayout()
        self.figure1 = Figure()
        self.canvas1 = FigureCanvas(self.figure1)
        self.toolbar1 = NavigationToolbar(self.canvas1, self)
        layout1.addWidget(self.toolbar1)
        layout1.addWidget(self.canvas1)
        self.calibrated_plot.setLayout(layout1)
        self.ax1 = self.canvas1.figure.subplots()
        self.ax1.set_yscale('log')
        self.ax1.set_xlabel('Energy (MeV)')
        self.ax1.set_ylabel('Counts')
        self.ax1.set_title('Current Linear Calibration')
        self.figure1.tight_layout()

        main = QWidget()
        main_lay = QVBoxLayout()
        main_lay.addWidget(self.plot)
        main_lay.addWidget(self.calibrated_plot)
        main.setLayout(main_lay)
        self.setCentralWidget(main)

    def mouse_tracking(self):
        self.lx = self.ax.axvline(color='k', linestyle='--')
        self.txt = self.ax.text(0.8, 0.9, "", transform=self.ax.transAxes)
        self.figure.canvas.mpl_connect('motion_notify_event', self.mouse_move)

    def mouse_move(self, event):
        if not event.inaxes:
            return
        x = event.xdata
        self.lx.set_xdata(x)
        self.txt.set_text('Channel: {:.2f}'.format(x))
        self.canvas.draw()

    def mouse_click(self, event):
        if not event.inaxes:
            return
        if event.dblclick:
            if event.button == 3:
                e, ok = QInputDialog.getDouble(self, 'Energy', 'Energy:(MeV)',
                                               10, 0, 15, 10)
                if ok:
                    self.calibration_lines.append(round(event.xdata, 2))
                    self.energies['{:.2f}'.format(
                        event.xdata)] = '{:.4f}'.format(e)
                    self.loaded.appendRow(
                        QStandardItem('Ch: {:.2f}->Energy: {:.4f} MeV'.format(
                            event.xdata, e)))
                    if len(self.calibration_lines) >= 2:
                        self.calibrateAction.setEnabled(True)
                self.replot()

    def new_spectrum(self):
        #load the file from a text or csv file
        fileName, ok = QFileDialog.getOpenFileName(
            self, 'Raw Spectrum', '',
            'Text File (*.txt);;Comma Seperate File (*.csv);;IAEA(*.spe)')
        if ok and fileName != '':
            #clear the list view to start calibrating again
            self.loaded.removeRows(0, self.loaded.rowCount())
            self.energies = {}
            self.calibration_lines = []
            self.counts = []
            self.channels = []
            if '.spe' not in fileName.lower():
                f = open(fileName, 'r')
                f_data = f.readlines()
                f.close()

                headers = f_data[0].split(sep=',')
                h_space = f_data[0].split(sep=' ')
                mult = False
                if len(headers) > 1 or len(h_space) > 1:
                    headers[-1] = headers[-1].split(sep='\n')[0]
                    item, ok = QInputDialog.getItem(self, 'Select Data Header',
                                                    'Header:', headers, 0,
                                                    False)
                    if ok:
                        column = headers.index(item)
                else:
                    mult = True
                    column = 0
                if ok or mult:
                    for i in range(len(f_data)):
                        try:
                            self.counts.append(
                                float(f_data[i].split(sep=',')[column]))
                            self.channels.append(i)
                        except:
                            True
            else:
                self.counts, self.channels = self.load_spe(fileName)
            self.rebin_action.setEnabled(True)
            self.rebin_action_save.setEnabled(True)
            self.replot(left_lim=0,
                        right_lim=len(self.channels) +
                        0.01 * len(self.channels))

    def find_peaks(self, x, width, distance):
        peaks, properties = signal.find_peaks(x,
                                              width=width,
                                              distance=distance)
        e_res = []
        widths = properties['widths']  #the fwhm of the peak
        left = properties['left_ips']  #left point of the fwhm
        right = properties['right_ips']  #right point of the fwhm
        sigma = [i / (2 * np.sqrt(2 * np.log(2)))
                 for i in widths]  #standard deviation
        left_sig = []
        right_sig = []
        #recalculate the peak location based on the average fo the left and right fwhm
        for i in range(len(peaks)):
            avg = (left[i] + right[i]) / 2
            peaks[i] = avg
            left_sig.append(avg - 4 * sigma[i])
            right_sig.append(avg + 4 * sigma[i])
            e_res.append(widths[i] / avg * 100)

        return peaks, e_res, left_sig, right_sig

    def replot(self, left_lim=None, right_lim=None):
        '''Redraw the uncalibrated spectrum'''
        l, r = self.ax.get_xlim()
        self.ax.clear()
        self.mouse_tracking()
        self.figure.canvas.mpl_connect('button_press_event', self.mouse_click)
        self.ax.set_yscale('log')
        self.ax.set_xlabel('Channel')
        self.ax.set_ylabel('Counts')

        self.ax.plot(self.channels, self.counts)
        if left_lim != None and right_lim != None:
            self.ax.set_xlim(left_lim, right_lim)
        else:
            self.ax.set_xlim(l, r)
        #let an algorithm find the peaks
        peaks = self.find_peaks(self.counts, 3, 2)[0]
        for i in peaks:
            self.ax.axvline(x=i, color='r', linestyle='--', linewidth=0.5)
        for i in self.calibration_lines:
            self.ax.axvline(x=i, color='k', linestyle='--')

        self.canvas.draw()
        self.figure.tight_layout()
        self.replot_calibration()

    def replot_calibration(self, left_lim=None, right_lim=None):
        '''Replot the calibrated spectrum:
            If 0 data points are entered, set intercept to 0 and
            set maximum energy to be 3MeV
            If 1 data point is enetered, set intercep to 0 and 
            find slope to be E/C (energy entered divided by bin num)
            If 2 or more data points are entered, call the linear calibration
            functions
        '''
        #calibration channel numbers: self.calibration_lines-> list
        #calibration energies: self.energies-> dictionary with string of cali as key
        self.ax1.clear()
        if len(self.calibration_lines) == 0:
            #take the channels and scale them from 0-3MeV
            slope = 3 / len(self.channels)
            calibrated = [i * slope for i in self.channels]
        elif len(self.calibration_lines) == 1:
            #get the energy and channel number
            ch = self.calibration_lines[0]
            en = float(self.energies[str(ch)])
            #the slope if those divided
            slope = en / ch
            calibrated = [i * slope for i in self.channels]

        else:
            channels = self.calibration_lines
            energies = self.energies.values()
            energies = [float(i) for i in energies]
            calibrated, m, b = cali(self.channels).linear_least_squares_fit(
                channels, energies, live_plotter=True)
            x = max(calibrated) - 0.12 * max(calibrated)
            y = max(self.counts) / 5
            self.ax1.annotate(
                'Slope: {:.3f} keV/ch\nIntercept: {:.3f}keV'.format(
                    m * 1000, b * 1000),
                xy=(x, y))
        self.ax1.set_xlim(0, max(calibrated))
        self.ax1.set_yscale('log')
        self.ax1.set_xlabel('Energy (MeV)')
        self.ax1.set_ylabel('Counts')
        self.ax1.set_title('Current Linear Calibration')
        self.ax1.plot(calibrated, self.counts)
        enr = list(self.energies.values())
        enr = [float(i) for i in enr]
        for i in enr:
            self.ax1.axvline(x=i, color='k', linestyle='--')
        self.canvas1.draw()
        self.figure1.tight_layout()

    def calibration(self):
        channels = list(self.energies.keys())
        energies = list(self.energies.values())
        channels = [float(i) for i in channels]
        energies = [float(j) for j in energies]

        #get the calibration method desired
        items = ('Linear', 'Deviation Pairs', 'External Calibration',
                 'Segemented Linear')
        item, ok = QInputDialog.getItem(self, 'Calibration Type',
                                        'Calibration:', items, 0, False)
        if ok and item:
            if item == items[0]:
                self.cal_values = cali(self.channels).linear_least_squares_fit(
                    channels, energies)
            elif item == items[1]:
                self.cal_values = cali(self.channels).deviation_pairs(
                    channels, energies)
            elif item == items[2]:
                text, ok = QInputDialog.getText(
                    self, 'Slope and Intercept',
                    'Slope [MeV/Ch],Intercept[MeV]:', QLineEdit.Normal, "")
                if ok and len(text.split(sep=',')) == 2:
                    vals = text.split(sep=',')
                    self.cal_values = cali(self.channels).external_calibration(
                        float(vals[0]), float(vals[1]))
            elif item == items[3]:
                self.cal_values = cali(
                    self.channels).segmented_linear_least_squares(
                        channels, energies)

            plt.figure(1, figsize=(5, 5))
            plt.plot(self.channels, self.cal_values)
            plt.figure(2, figsize=(5, 5))
            plt.plot(self.cal_values, self.counts)
            plt.xlabel('Energy [MeV]')
            plt.ylabel('Counts')
            plt.title('Energy Calibrated Spectrum')
            plt.yscale('log')
            plt.xlim(0, 14)
            plt.show()
            self.save.setEnabled(True)

    def save_(self):
        name, ok = QFileDialog.getSaveFileName(
            self, 'Calibration Data', '',
            'Text File (*.txt);; Comma Seperated File (*.csv)')
        if ok:
            f = open(name, 'w')
            for i in self.cal_values:
                f.write('{:.8f}\n'.format(i))

    def save_rebinned(self):
        name, ok = QFileDialog.getSaveFileName(
            self, 'Calibration Data', '',
            'Text File (*.txt);; Comma Seperated File (*.csv)')
        if ok:
            f = open(name, 'w')
            for i in self.counts:
                f.write('{:.8f}\n'.format(i))

    def update(self, index):
        item = self.loaded.itemFromIndex(index)
        val = item.text()
        ch = val.split(sep='->')[0].split(sep=': ')[1]
        self.energies.pop(ch)
        self.calibration_lines.remove(float(ch))
        self.loaded.removeRows(0, self.loaded.rowCount())
        for i in self.calibration_lines:
            self.loaded.appendRow(
                QStandardItem('Ch: {:.2f}->Energy: {} MeV'.format(
                    i, self.energies[str(i)])))
        self.replot()

    def load_spe(self, file_path):
        '''Load a spectrum file type using the SPE file format'''
        f = open(file_path, 'r')
        data = f.readlines()
        f.close()

        counts = []
        channels = []
        # num_counts=int(data[7].split()[1])
        #first find the index for $DATA so
        s_index = 0
        e_index = 0
        for i in range(len(data)):
            if '$DATA:' in data[i]:
                s_index = i + 2
        for i in range(s_index, len(data)):
            if '$' in data[i]:
                e_index = i - 1
                break

        for i in range(s_index, e_index):
            counts.append(float(data[i]))
            channels.append(i - s_index)
        return counts, channels

    def rebin(self):
        '''rebing the data and the replot it'''
        values = ['2', '4']
        selected, ok = QInputDialog.getItem(self, 'Select Rebin',
                                            'Bins to combine', values, 0,
                                            False)
        if ok:
            s = int(selected)
            self.counts = Rebins(self.counts, s).rebinner()
            self.channels = [i for i in range(len(self.counts))]
            #need to redo the calibration lines
            for i in range(len(self.calibration_lines)):
                self.calibration_lines[i] = round(
                    self.calibration_lines[i] / 2, 2)
            #next take care of the values shown on the right
            self.loaded.removeRows(0, self.loaded.rowCount())
            channels = self.calibration_lines
            energies = list(self.energies.values())
            channels = [float(i) for i in channels]
            energies = [float(j) for j in energies]
            self.energies = {}
            for i in range(len(energies)):
                self.energies['{:.2f}'.format(channels[i])] = '{:.4f}'.format(
                    energies[i])
            for i in self.calibration_lines:
                self.loaded.appendRow(
                    QStandardItem('Ch: {:.2f}->Energy: {} MeV'.format(
                        i, self.energies[str(i)])))

            self.replot(left_lim=0,right_lim=len(self.channels)+\
                        0.01*len(self.channels))
コード例 #4
0
class ColorMapsDialog(object):
    
    def __init__(self,  title, message, items_selected, imageName):
        self.title = title
        self.message = message
        self.items_selected = items_selected #[s for s in items_selected.split(',')]
        self.imageName = imageName
        self.cmObj = ColorMaps()
        self.CM = self.cmObj.colorMaps
        
        form = QFormLayout()
        form.addRow(QLabel(message))
        self.listView = QListView()
        form.addRow(self.listView)
        font = QFont()
        font.setBold(True)
        font.setPointSize(8)
        self.listView.setFont(font)
        model = QStandardItemModel(self.listView)
        size = QSize(60,30)
        for item in self.CM:
            # create an item with a caption
            standardItem = QStandardItem(item)
            standardItem.setCheckable(True)
            if item in self.items_selected: standardItem.setCheckState(True)
            standardItem.setSizeHint(size)
            model.appendRow(standardItem)
        self.listView.setModel(model)
        
    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")
        Dialog.resize(530, 447)
        Dialog.setWindowTitle(self.title)
        self.buttonBox = QDialogButtonBox(Dialog)
        self.buttonBox.setGeometry(QRect(10, 390, 511, 32))
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel|QDialogButtonBox.Ok)
        self.buttonBox.setObjectName("buttonBox")
        self.horizontalLayoutWidget = QWidget(Dialog)
        self.horizontalLayoutWidget.setGeometry(QRect(9, 10, 511, 363))
        self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget")
        self.horizontalLayout = QHBoxLayout(self.horizontalLayoutWidget)
        self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.horizontalLayout.addWidget(self.listView)
        self.label = QLabel(self.horizontalLayoutWidget)
        self.label.setText("")
        self.label.setPixmap(QPixmap(self.imageName))
        self.label.setAlignment(Qt.AlignCenter)
        self.label.setObjectName("label")
        self.horizontalLayout.addWidget(self.label)

        self.retranslateUi(Dialog)
        self.buttonBox.accepted.connect(Dialog.accept)
        self.buttonBox.rejected.connect(Dialog.reject)
        QMetaObject.connectSlotsByName(Dialog)

    def retranslateUi(self, Dialog):
        _translate = QCoreApplication.translate
        Dialog.setWindowTitle(_translate("Dialog", self.title))
        
    def itemsSelected(self):
        selected = []
        model = self.listView.model()
        i = 0
        while model.item(i):
            if model.item(i).checkState():
                selected.append(model.item(i).text())
            i += 1
        return selected
コード例 #5
0
class Edit_Customer_Information(QWidget):
    def __init__(self, font, size_policy, base_directory):
        super().__init__()
        self.setWindowIcon(QIcon('BEI_Logo.png'))
        self.setWindowTitle('Update Customer Information')
        self.font = font
        self.size_policy = size_policy
        self.base_directory = base_directory
        self.setup()

    def setup(self):
        '''Setup the cheat sheet viewing
        '''
        self.display = QTextEdit(self)
        self.display.setFont(self.font)
        self.display.setSizePolicy(self.size_policy, self.size_policy)
        #        self.display.setReadOnly(True)

        self.options = QListView(self)
        self.options.setFont(self.font)
        self.options.setSizePolicy(self.size_policy, self.size_policy)
        self.options.setEditTriggers(QAbstractItemView.NoEditTriggers)

        self.save = QPushButton('Update', self)
        self.save.setFont(self.font)
        self.save.setSizePolicy(self.size_policy, self.size_policy)
        self.save.clicked.connect(self.save_info)
        self.save.setEnabled(False)

        layout = QGridLayout(self)
        layout.addWidget(self.options, 0, 0)
        layout.addWidget(self.display, 0, 1)
        layout.addWidget(self.save, 1, 0)
        self.setLayout(layout)

        #get the different topics from cheat_sheet_topics.txt
        c = open(
            os.path.join(
                os.path.join(self.base_directory, 'Customer_Information'),
                'Customers.txt'), 'r')
        c_data = c.readlines()
        c.close()
        if len(c_data) == 0:
            replay = QMessageBox.information(
                self, 'No Customers', 'There are currently no customers',
                QMessageBox.Ok)
            if replay == QMessageBox.Ok:
                self.close()
        else:
            self.topics = []
            for i in c_data:
                self.topics.append(i.replace('\n', ''))

            self.entry = QStandardItemModel()
            self.options.setModel(self.entry)

            self.options.doubleClicked[QModelIndex].connect(self.openFile)
            for tex in self.topics:
                self.entry.appendRow(QStandardItem(tex))
            self.show()

    def openFile(self, index):
        self.save.setEnabled(True)
        item = self.entry.itemFromIndex(index)
        text = str(item.text()).replace(' ', '_')
        self.customer = text
        #open the text file associated with the clicked item
        cust = os.path.join(self.base_directory, 'Customer_Information')
        u = open(
            os.path.join(os.path.join(cust, 'Addresses'),
                         '{}.txt'.format(text)), 'r')
        data = u.readlines()
        u.close()
        combi = ''
        for i in data:
            combi += i
        self.display.setText(combi)

    def save_info(self):
        cust = os.path.join(self.base_directory, 'Customer_Information')
        u = open(
            os.path.join(os.path.join(cust, 'Addresses'),
                         '{}.txt'.format(self.customer)), 'w')
        u.write(self.display.toPlainText())
        u.close()
        QMessageBox.information(self, 'Saved',
                                '{} information updated'.format(self.customer),
                                QMessageBox.Ok)
コード例 #6
0
ファイル: BEI_Invoice.py プロジェクト: alangburl/BEI_Invoice
class Invoice(QMainWindow):
    '''Runs the main window of the invoice development
    Calls the table to be used for parts and labor from
    table_widget.py
    '''
    invoice_count = 0
    total_parts_ = 0
    labor_supplies_ = 0
    recent_open = False
    start_flag = False
    current_job = str
    labor_ = 0
    parts_ = 0
    supplies = 0
    freight_ = 0
    subtotal = 0
    taxed = 0
    totals = 0
    tax = 0
    partial = 0
    finance = 0
    new_total = 0
    open_list = []
    printed_list = {}

    def __init__(self):
        '''Initialize the window and get pertinent information read in:
            Set the window size
            Set the picture to be a BEI logo
            Read in the standard labor rates
            '''
        super().__init__()
        self.size_policy = QSizePolicy.Expanding
        self.font = QFont()
        self.font.setPointSize(12)
        self.showMaximized()
        self.setWindowIcon(QIcon('BEI_Logo.png'))
        #        backimage=QImage('BEI_Logo.png')
        self.setWindowTitle('Burl Equipment Inc. Invoices Beta')
        self.tray = QSystemTrayIcon(self)
        self.tray.setIcon(QIcon('BEI_Logo.png'))
        self.show()
        self.menu_bar()
        self.statusbar = QStatusBar()
        self.setStatusBar(self.statusbar)
        #this is the first time start up section, should only run the very
        #first time
        self.base_directory = str(
            Path(os.path.join(os.environ['USERPROFILE'], 'BEI_Invoices')))
        base_entries = os.listdir(os.environ['USERPROFILE'])
        if 'BEI_Invoices' not in base_entries:
            initi.First_Run(self.base_directory)

    def menu_bar(self):
        '''Create the menu bar for the main window will include
                Name:       Shortcut:         Function called:
            File:
                New         CTRL+N            new_invoice_begin
                Open        CTRL+O            existing_invoice_open
                Save        CTRL+S              print_invoice
                Quit        ALT       save_invoice
                Print       CTRL+P   +F4            exit_system
            Edit:
                Change Labor Rates            labor_rates
            View:
                View Totals                   view_totals
                View Labor Breakdown          labor_breakdown
            Help:
                View Current Cheat Sheet      cheat_sheet
                Add New Task to Cheat Sheet   add_cheat_task
        '''
        self.menuFile = self.menuBar().addMenu("&File")
        self.actionNew = QAction('&New', self)
        self.actionNew.setShortcut('Ctrl+N')
        self.actionNew.triggered.connect(self.new_invoice_begin)
        self.actionOpen = QAction("&Open", self)
        self.actionOpen.setShortcut('Ctrl+O')
        self.actionOpen.triggered.connect(self.existing_invoice_open)
        self.actionSave = QAction('&Save', self)
        self.actionSave.setShortcut('Ctrl+S')
        self.actionSave.setDisabled(True)
        self.actionSave.triggered.connect(self.save_invoice)
        #        self.actionImport=QAction('&Import Old Job',self)
        #        self.actionImport.triggered.connect(self.old_job)
        #        self.actionImport.setShortcut('Ctrl+I')
        self.actionPrint = QAction('&Print', self)
        self.actionPrint.setShortcut('Ctrl+P')
        self.actionPrint.setDisabled(True)
        self.actionPrint.triggered.connect(self.print_invoice)

        self.printMenu = QMenu('Print Envelopes', self)
        self.actionEnvelope = QAction('&Print All Billed Customer Envelopes',
                                      self)
        self.actionEnvelope.triggered.connect(self.envelop_write)
        self.actionEnvelope.setShortcut('Ctrl+E')
        self.actionEnvelope.setDisabled(True)

        self.actionEnvelope1 = QAction(
            '&Print Single Billed Customer Envelope', self)
        self.actionEnvelope1.triggered.connect(self.envelop_write1)
        self.actionEnvelope1.setShortcut('Ctrl+R')

        self.actionBilledEnvelopes = QAction('&Print Check Envelope', self)
        self.actionBilledEnvelopes.triggered.connect(self.billing_envelopes)
        self.actionBilledEnvelopes.setShortcut('Ctrl+C')

        self.printMenu.addActions([
            self.actionEnvelope, self.actionEnvelope1,
            self.actionBilledEnvelopes
        ])

        self.actionQuit = QAction('&Exit', self)
        self.actionQuit.triggered.connect(self.closing)
        self.actionQuit.setShortcut('Alt+F4')
        self.menuFile.addActions([
            self.actionNew, self.actionOpen, self.actionSave, self.actionPrint
        ])
        self.menuFile.addMenu(self.printMenu)
        self.menuFile.addAction(self.actionQuit)

        self.menuEdit = self.menuBar().addMenu('&Edit')
        self.menuEdit_Change_In = QMenu('Change Basic Invoice Information',
                                        self)
        self.menuEdit_Change_Sy = QMenu('Change Operating Data', self)

        self.actionLaborRates = QAction('&Change Standard Labor Rates', self)
        self.actionLaborRates.triggered.connect(self.labor_rates)
        self.actionAddTechnician = QAction('&Add Technician', self)
        self.actionAddTechnician.triggered.connect(self.add_tech)
        self.actionChangeDate = QAction('&Change Invoice Date', self)
        self.actionChangeDate.triggered.connect(self.date_change)
        self.actionChangeCustomerAddress = QAction('&Change Customer Address',
                                                   self)
        self.actionChangeCustomerAddress.triggered.connect(self.change_address)
        self.actionBasicInfo = QAction('&Change Basic Information', self)
        self.actionBasicInfo.triggered.connect(self.change_basic_info)
        self.actionBasicInfo.setDisabled(True)
        self.menuEdit_Change_In.addActions([self.actionBasicInfo])
        self.menuEdit_Change_Sy.addActions([
            self.actionLaborRates, self.actionAddTechnician,
            self.actionChangeDate, self.actionChangeCustomerAddress
        ])
        self.menuEdit.addMenu(self.menuEdit_Change_In)
        self.menuEdit.addMenu(self.menuEdit_Change_Sy)

        self.menuView = self.menuBar().addMenu('&View')
        self.actionViewLaborBreakdown = QAction('&View Labor Breakdown', self)
        self.actionViewLaborBreakdown.setDisabled(True)
        self.actionViewLaborBreakdown.triggered.connect(self.breakdown)
        self.actionViewAllWindows = QAction('&View All Windows', self)
        self.actionViewAllWindows.setDisabled(True)
        self.actionViewAllWindows.triggered.connect(self.view_windows)
        self.actionViewCutomer = QAction('&View Customer Invoice', self)
        self.actionViewCutomer.triggered.connect(self.view_customer)
        self.actionViewCutomer = QAction('&View Customer Invoice', self)
        self.actionViewCutomer.triggered.connect(self.view_customer)
        self.actionViewCutomer.setEnabled(False)
        self.actionViewCompany = QAction('&View Company Invoice', self)
        self.actionViewCompany.triggered.connect(self.view_company)
        self.actionViewCompany.setEnabled(False)
        self.menuView.addActions([
            self.actionViewLaborBreakdown, self.actionViewAllWindows,
            self.actionViewCutomer, self.actionViewCompany
        ])

        self.actionJobNumbers = QAction('&More Job Numbers', self)
        self.actionJobNumbers.triggered.connect(self.new_job_nums)
        self.menuJobNumbers = self.menuBar().addMenu('Job Numbers')
        self.menuJobNumbers.addAction(self.actionJobNumbers)

        self.menuPayment = self.menuBar().addMenu('&Finance/Payments')
        self.actionPartialPayment = QAction('&Partial Payment', self)
        self.actionPartialPayment.triggered.connect(self.partial_payment)
        self.actionPartialPayment.setDisabled(True)
        self.actionFinanceCharges = QAction('&Add Finance Charges', self)
        self.actionFinanceCharges.triggered.connect(self.finance_charges)
        self.actionFinanceCharges.setDisabled(True)
        self.menuPayment.addActions(
            [self.actionPartialPayment, self.actionFinanceCharges])

        self.menuHelp = self.menuBar().addMenu('&Help')
        self.actionViewCheatSheet = QAction('&View Cheat Sheet', self)
        self.actionViewCheatSheet.triggered.connect(self.cheat_sheet)
        self.actionNewCheat = QAction('&Add New Item to Cheat Sheet', self)
        self.actionNewCheat.triggered.connect(self.add_cheat_task)
        self.actionUpdate = QAction('&Update Application')
        self.actionUpdate.triggered.connect(self.updater)
        self.menuHelp.addActions([
            self.actionViewCheatSheet, self.actionNewCheat, self.actionUpdate
        ])

    def new_invoice_begin(self):
        '''Entering basic information:
            Job Number:
            Machine:
            Customer Name:
        '''
        try:
            self.docked.close()
            self.docked2.close()
            self.totals_table.close()
            self.save_invoice()
            self.new_window = New_Invoice(12, self.base_directory)
            #            self.new_window.basic_information()
            self.new_window.start.clicked.connect(self.job_num_insertion)
            self.new_window.customer_address_line_2.returnPressed.connect(
                self.new_window.information_)
            self.new_window.customer_address_line_2.returnPressed.connect(
                self.job_num_insertion)
        except:
            self.new_window = New_Invoice(12, self.base_directory)
            #            self.new_window.basic_information()
            self.new_window.start.clicked.connect(self.job_num_insertion)
            self.new_window.customer_address_line_2.returnPressed.connect(
                self.new_window.information_)
            self.new_window.customer_address_line_2.returnPressed.connect(
                self.job_num_insertion)

    def job_num_insertion(self):
        '''Call the table with the job number given in the new invoice
        '''
        self.reset_data()
        if not self.recent_open:
            self.recent_invoices()
        self.tax = self.new_window.tax
        self.customer = self.new_window.customer.replace('#', '')
        self.machine_text = self.new_window.machine_
        self.current_job = self.new_window.job_num
        if self.current_job not in self.open_list:
            self.open_list.append(self.current_job)
            self.recently_opened_invoice.appendRow(
                QStandardItem(str(self.current_job)))
        self.invoice_count += 1
        #make the folder for this invoice to be saved in
        self.job_dire = os.path.join(
            os.path.join(self.base_directory, 'Saved_Invoices'),
            self.current_job)
        try:
            os.mkdir(self.job_dire)
            #save the basic information
            location = os.path.join(
                os.path.join(self.base_directory, 'Saved_Invoices'),
                self.current_job)
            self.table(self.new_window.job_num)
            basic = os.path.join(location, 'Basic_Info.csv')
            f = open(basic, 'w')
            f.write(str(self.current_job) + '\n')

            f.write(self.new_window.customer + '\n')
            f.write(self.new_window.machine_ + '\n')
            f.write('{},{}\n'.format(str(self.new_window.tax),
                                     self.new_window.tax_code))
            f.write(self.new_window.line1 + '\n')
            f.write(self.new_window.line2 + '\n')
            f.close()
        except:
            buttonReply = QMessageBox.question(
                self, 'Confirm New Machine',
                'Job Number {} already exist.\nDo you want to overwrite it?'.
                format(self.new_window.job_num),
                QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
            if buttonReply == QMessageBox.Yes:
                self.table(self.new_window.job_num)
                location = os.path.join(
                    os.path.join(self.base_directory, 'Saved_Invoices'),
                    self.current_job)
                basic = os.path.join(location, 'Basic_Info.csv')
                f = open(basic, 'w')
                f.write(str(self.current_job) + '\n')

                f.write(self.new_window.customer + '\n')
                f.write(self.new_window.machine_ + '\n')
                f.write('{},{}\n'.format(str(self.new_window.tax),
                                         self.new_window.tax_code))
                f.write(self.new_window.line1 + '\n')
                f.write(self.new_window.line2 + '\n')
                f.close()
            elif buttonReply == QMessageBox.No:
                self.current_job = str(self.current_job)
                self.read_in_data()

    def existing_invoice_open(self):
        '''Open an existing invoice
        '''
        try:
            self.docked.close()
            self.docked2.close()
            self.save_invoice()
        except:
            True
        if not self.recent_open:
            self.recent_invoices()
        #get the saved invoices
        loc = os.path.join(self.base_directory, 'Saved_Invoices')
        saved_jobs = os.listdir(loc)
        self.existing = QWidget()
        self.existing.setWindowIcon(QIcon('BEI_Logo.png'))
        self.existing.setWindowTitle('Open Existing Invoice')
        self.open = QPushButton('Open', self)
        self.open.setFont(self.font)
        self.open.setSizePolicy(self.size_policy, self.size_policy)
        self.open.clicked.connect(self.reader)

        self.job_to_open = QLineEdit(self)
        self.job_to_open.setFont(self.font)
        self.job_to_open.setSizePolicy(self.size_policy, self.size_policy)
        self.job_to_open.setCompleter(QCompleter(saved_jobs))
        #        self.job_to_open.returnPressed.connect(self.reader)

        layout = QVBoxLayout()
        layout.addWidget(self.job_to_open)
        layout.addWidget(self.open)
        self.existing.setLayout(layout)
        self.existing.setGeometry(400, 400, 300, 100)
        self.existing.show()

    def reader(self):
        self.current_job = self.job_to_open.text()
        self.read_in_data()
        self.existing.close()

    def table(self, num):
        '''Setup the table for use with a new invoice
        '''
        self.start_flag = True
        self.actionPrint.setEnabled(True)

        self.actionSave.setEnabled(True)
        self.actionViewLaborBreakdown.setEnabled(True)
        self.actionBasicInfo.setEnabled(True)
        self.actionViewAllWindows.setEnabled(True)
        self.actionViewCutomer.setEnabled(True)
        self.actionViewCompany.setEnabled(True)
        self.docked = QMdiSubWindow()
        self.docked.setWindowTitle('Invoice {}'.format(num))
        self.num = num
        self.tabs = QTabWidget(self)
        self.parts = Parts_Tabs(num)
        self.tabs.addTab(self.parts, 'Parts')
        self.labor = Labor_Tabs(num)
        self.tabs.addTab(self.labor, 'Labor')
        self.docked.setWidget(self.tabs)

        self.parts.total.connect(self.calculate_totals)
        self.labor.labor_total.connect(self.calculate_totals)

        cust_display = QWidget(self)
        self.cust_label = QLabel('Customer: {}'.format(self.customer), self)
        self.cust_label.setFont(self.font)
        self.machine_label = QLabel('Machine: {}'.format(self.machine_text),
                                    self)
        self.machine_label.setFont(self.font)
        lay = QHBoxLayout()
        lay.addWidget(self.cust_label)
        lay.addWidget(self.machine_label)
        cust_display.setLayout(lay)

        #design and insert the totals table
        self.totals_table = Table(7, 2)
        self.totals_table.tableWidget.setItem(0, 0, QTableWidgetItem('Parts:'))
        self.totals_table.tableWidget.setItem(1, 0, QTableWidgetItem('Labor:'))
        self.totals_table.tableWidget.setItem(2, 0,
                                              QTableWidgetItem('Supplies:'))
        self.totals_table.tableWidget.setItem(3, 0,
                                              QTableWidgetItem('Freight:'))
        self.totals_table.tableWidget.setItem(4, 0,
                                              QTableWidgetItem('Subtotal:'))
        self.totals_table.tableWidget.setItem(
            5, 0, QTableWidgetItem('Tax: {:.2f}%'.format(self.tax * 100)))
        self.totals_table.tableWidget.setItem(6, 0, QTableWidgetItem('Total:'))
        #set up the comments section
        self.comments = QTextEdit(self)
        self.comments.setFont(self.font)
        self.comments.setSizePolicy(self.size_policy, self.size_policy)
        self.comments.setText('Comments:\n')

        self.additional_docking = QWidget(self)
        layout = QVBoxLayout(self)
        layout.addWidget(cust_display)
        layout.addWidget(self.totals_table)
        layout.addWidget(self.comments)
        self.additional_docking.setLayout(layout)

        self.docked2 = QMdiSubWindow()
        self.docked2.setWidget(self.additional_docking)
        self.docked2.setWindowTitle('Information')

        self.mdi = QMdiArea()
        self.mdi.addSubWindow(self.docked2)
        self.mdi.addSubWindow(self.docked)

        self.mdi.tileSubWindows()
        self.setCentralWidget(self.mdi)
#        self.window_saved=self.saveState(1)

    def recent_invoices(self):
        '''Show a list of recently opened invoices
        '''
        self.recent_open = True
        self.recent = QDockWidget('Recently opened invoices', self)

        self.recently_opened_invoice = QStandardItemModel()
        self.invoices_open = QListView(self)
        self.invoices_open.setFont(self.font)
        self.invoices_open.setSizePolicy(self.size_policy, self.size_policy)
        self.invoices_open.setModel(self.recently_opened_invoice)
        self.invoices_open.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.invoices_open.doubleClicked[QModelIndex].connect(self.recall)

        self.notes = QTextEdit(self)
        self.notes.setFont(self.font)
        self.notes.setSizePolicy(self.size_policy, self.size_policy)
        self.notes.setText('Notes:\n')

        self.running_info = QWidget(self)
        layout = QVBoxLayout(self)
        layout.addWidget(self.invoices_open)
        layout.addWidget(self.notes)
        self.running_info.setLayout(layout)
        self.recent.setWidget(self.running_info)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.recent)

    def recall(self, index):
        item = self.recently_opened_invoice.itemFromIndex(index)
        job_number = item.text()
        self.docked.close()
        self.docked2.close()
        self.save_invoice()
        self.current_job = job_number
        self.read_in_data()

    def save_invoice(self, printing=False):
        '''Save both the parts and labor tables
        '''
        if self.current_job == str:
            pass
        else:
            location = os.path.join(
                os.path.join(self.base_directory, 'Saved_Invoices'),
                self.current_job)
            parts_file = os.path.join(location, 'Parts.csv')
            #first read and write the parts information
            f = open(parts_file, 'w')
            row = []
            for i in range(100):
                try:
                    for j in range(8):
                        if j == 0:
                            if self.parts.parts_table.tableWidget.item(
                                    i, j).text() != '*':
                                val = float(
                                    self.parts.parts_table.tableWidget.item(
                                        i, j).text())
                            elif self.parts.parts_table.tableWidget.item(
                                    i, j).text() == '*':
                                val = self.parts.parts_table.tableWidget.item(
                                    i, j).text()
                            row.append(val)
                        else:
                            try:
                                val = self.parts.parts_table.tableWidget.item(
                                    i, j).text()
                                row.append(val)
                            except:
                                row.append('')
                    if '\n' in row[-1]:
                        row[-1] = row[-1].split(sep='\n')[0]
                    row[2] = row[2].replace(',', '.')
                    f.write('{},{},{},{},{},{},{},{}\n'.format(*row))
                    row = []
                except:
                    break
            f.close()
            #save the total table
            total_location = os.path.join(location, 'Totals.csv')
            h = open(total_location, 'w')
            t_row = [
                self.parts_, self.labor_, self.supplies, self.freight_,
                self.subtotal, self.taxed, self.totals
            ]
            for i in t_row:
                try:
                    float(i)
                    h.write('{:.2f}\n'.format(i))
                except:
                    h.write('0')
            h.close()
            #save the comments
            comments_location = os.path.join(location, 'Comments.csv')
            v = open(comments_location, 'w')
            v.write(self.comments.toPlainText())
            v.close()
            #finally save the labor information
            #get the number of techs showing
            count = self.labor.counts

            for l in range(count):
                labor_location = os.path.join(location, 'tech{}.csv'.format(l))
                o = open(labor_location, 'w')
                #get the data from the labor class
                tech_labor = self.labor.read_data_out(l)
                for k in range(len(tech_labor)):
                    if '\n' in list(tech_labor[k][-1]):
                        tech_labor[k][-1] = float(tech_labor[k][-1])
                    o.write('{},{},{},{},{},{},{},{}\n'.format(*tech_labor[k]))
                o.close()

        self.statusbar.showMessage('Invoice {} saved'.format(self.current_job),
                                   5000)
        envelop_writer = EWriter(self.base_directory, self.current_job)
        envelop_writer.generate_latex()

        acrobat = 'Acrobat.exe' in (p.name() for p in psutil.process_iter())
        reader = 'AcroRd32.exe' in (p.name() for p in psutil.process_iter())
        if acrobat:
            lis = ['taskkill', '/F', '/IM', 'Acrobat.exe', '/T']
            subprocess.call(lis)
        if reader:
            os.system('taskkill /F /IM "AcroRd32.exe" /T')

        if printing == False:
            comp_cust = Saver(self, self.base_directory, self.current_job)
            comp_cust.out.connect(self.failure)
            comp_cust.start()

    def failure(self, value):
        if value == 1:
            QMessageBox.information(self, 'Save Failure',
                                    'Closing PDF and trying again',
                                    QMessageBox.Ok)


#            self.save_invoice()

    def add_tech(self):
        '''Adding a technician to the company:
            Changes to make:
                Add to the tabs 
                Add standard labor rates
                Change stuff in the base invoice, 
                not sure how this is going to work yet
        '''
        text, okPressed = QInputDialog.getText(self, "Tech Name", "Tech name:",
                                               QLineEdit.Normal, "")
        if okPressed and text != '':
            regular, okPressed1 = QInputDialog.getDouble(
                self, "Regular Rate", "Regular Hourly Rate: $", 80, 0, 150, 2)
            if okPressed1:
                overtime, okPressed2 = QInputDialog.getDouble(
                    self, "Overtime Rate", "Overtime Hourly Rate: $", 80, 0,
                    150, 2)
                if okPressed2:
                    directory = str(
                        Path(
                            os.path.join(
                                os.path.join(os.environ['USERPROFILE'],
                                             'BEI_Invoices')),
                            'Basic_Information_Totals'))
                    tech_data = open(
                        str(Path(os.path.join(directory, 'Labor_Rates.csv'))),
                        'a')
                    tech_data.write('{},{},{}\n'.format(
                        text, regular, overtime))
                    tech_data.close()
                    QMessageBox.information(
                        self, 'Updated',
                        'Application must be restarted to apply these changes',
                        QMessageBox.Ok)

    def read_in_data(self):
        self.actionPartialPayment.setEnabled(True)
        self.actionFinanceCharges.setEnabled(True)
        self.invoice_count += 1

        if self.current_job not in self.open_list:
            self.open_list.append(self.current_job)
            self.recently_opened_invoice.appendRow(
                QStandardItem(self.current_job))
        #open the basic information and read the tax percentage
        location = os.path.join(
            os.path.join(self.base_directory, 'Saved_Invoices'),
            '{}'.format(self.current_job))
        e = open(os.path.join(location, 'Basic_Info.csv'), 'r')
        basic = e.readlines()
        e.close()
        self.customer, self.machine_text = basic[1].replace(
            '\n', ''), basic[2].replace('\n', '')

        self.tax = float(basic[3].split(sep=',')[0])
        self.table(self.current_job)
        self.machine_label.setText('Machine: {}'.format(self.machine_text))
        self.cust_label.setText('Customer: {}'.format(self.customer))
        #read in the parts data from the file and hand it off the the parts_tab
        #class to be placed in the table
        location = os.path.join(
            os.path.join(self.base_directory, 'Saved_Invoices'),
            '{}'.format(self.current_job))
        parts_location = os.path.join(location, 'Parts.csv')
        p_d = open(parts_location, 'r')
        p_data = p_d.readlines()
        p_d.close()
        parts_data = [p_data[i].split(sep=',') for i in range(len(p_data))]
        self.parts.read_in_data(parts_data)

        #read in the totals information
        totals_information = os.path.join(location, 'Totals.csv')
        t_d = open(totals_information, 'r')
        t_data = t_d.readlines()
        t_d.close()
        totals = [float(i) for i in t_data]
        #reset all the s
        self.reset_data()
        #try to read in payments and finance cahrges if they exist
        try:
            par_d = open(os.path.join(location, 'Payments.csv'), 'r')
            self.partial = float(par_d.readlines()[0])
            par_d.close()
        except:
            self.partial = 0
        try:
            fin_d = open(os.path.join(location, 'Finance.csv'), 'r')
            self.finance = float(fin_d.readlines()[0])
            fin_d.close()
        except:
            self.finance = 0

        self.parts_, self.labor_, self.supplies, self.freight_, self.subtotal, self.taxed, self.totals = totals
        #set the values into the totals table
        #        self.totals=self.totals+self.finance-self.partial
        for i in range(len(totals)):
            self.totals_table.tableWidget.setItem(
                i, 1, QTableWidgetItem('${:,.2f}'.format(totals[i])))

        #read and put the comments in place
        comments_location = os.path.join(location, 'Comments.csv')
        c_data = open(comments_location, 'r')
        com_data = c_data.readlines()
        c_data.close()
        combi = ''
        for i in com_data:
            combi += str(i)
        self.comments.setText(combi)

        #read in the labor data
        #determine the number of tech there are
        tech_num = 0
        dir_ = os.listdir(location)
        for i in range(len(dir_)):
            if 'tech' in dir_[i]:
                tech_num += 1

        for l in range(tech_num):
            loca = os.path.join(location, 'tech{}.csv'.format(l))
            l_data = open(loca, 'r')
            lab_data = l_data.readlines()
            l_data.close()
            labor_data = [o.split(sep=',') for o in lab_data]
            self.labor.read_in_data(l, labor_data)

    def reset_data(self):
        self.parts_, self.labor_, self.supplies, self.freight_, self.subtotal, self.taxed, self.totals = [
            0, 0, 0, 0, 0, 0, 0
        ]
        self.partial, self.finance = 0, 0

    def labor_rates(self):
        '''Change the labor rates
        '''
        self.changes = Labor_Rates(self.base_directory, self.font,
                                   self.size_policy)
        self.changes.show()

    def update_parts_total(self):
        self.parts_calculator()
        #        self.parts_=round(self.parts.parts_total,2)
        #        self.freight_=round(self.parts.freight_total,2)
        self.totals_table.tableWidget.setItem(
            0, 1, QTableWidgetItem('${:,.2f}'.format(self.parts_)))
        self.totals_table.tableWidget.setItem(
            3, 1, QTableWidgetItem('${:,.2f}'.format(self.freight_)))
        self.total_parts_ = self.parts_ + self.freight_

    def parts_calculator(self):
        self.parts_ = 0
        self.freight_ = 0
        #        self.parts.parts_sumation()
        #        self.parts_=self.parts.parts_total
        #        self.freight_=self.parts.freight_total+1

        for i in range(100):
            try:
                self.parts_ += float(
                    self.parts.parts_table.tableWidget.item(i, 5).text())
                try:
                    self.freight_ += float(
                        self.parts.parts_table.tableWidget.item(i, 6).text())
                except:
                    self.freight_ += 0
            except:
                True

    def update_labor(self):
        total_labor = 0
        for i in range(self.labor.counts):
            total_labor += self.labor.find_tech_total(i)
        self.totals_table.tableWidget.setItem(
            1, 1, QTableWidgetItem('${:,.2f}'.format(round(total_labor, 2))))
        self.totals_table.tableWidget.setItem(
            2, 1,
            QTableWidgetItem('${:,.2f}'.format(round(total_labor * 0.05, 2))))
        self.supplies = round(total_labor * 0.05, 2)
        self.labor_ = total_labor
        self.labor_supplies_ = round(self.labor_, 2) + self.supplies

    def calculate_totals(self):
        '''Calculate the totals for the totals table and display it
        '''
        self.update_labor()
        #        self.parts.parts_sumation()
        self.update_parts_total()
        self.subtotal = self.labor_supplies_ + self.total_parts_
        self.totals_table.tableWidget.setItem(
            4, 1, QTableWidgetItem('${:,.2f}'.format(self.subtotal)))
        self.taxed = self.tax * self.subtotal
        self.totals_table.tableWidget.setItem(
            5, 1, QTableWidgetItem('${:,.2f}'.format(self.taxed)))
        self.totals = self.subtotal + self.taxed + self.finance - self.partial
        self.totals_table.tableWidget.setItem(
            6, 1, QTableWidgetItem('${:,.2f}'.format(self.totals)))

    def print_invoice(self):
        '''
        Print the customer and company invoices
        '''
        #make sure the invoice is saved
        self.save_invoice(printing=True)
        self.printed_list[self.current_job] = [
            self.customer, self.machine_text
        ]
        try:
            pdf2.PDF_Builder(self.current_job, self.base_directory,
                             'Company').print_tex()
            pdf2.PDF_Builder(self.current_job, self.base_directory,
                             'Customer').print_tex()
        except:
            QMessageBox.information(self, 'Print Failure',
                                    'Close file and try again', QMessageBox.Ok)

        #first check and see if the Envelopes directory has this
        #months print list
        envelope_date = EP(self.base_directory, self.customer,
                           self.current_job)
        self.envelope_date = envelope_date.dater()
        self.actionEnvelope.setEnabled(True)
        self.actionEnvelope1.setEnabled(True)

    def closing(self):
        #        self.save_invoice()
        self.close()

    def breakdown(self):
        '''view the labor break down
        '''
        #open the labor rates to get the names
        loc = os.path.join(self.base_directory, 'Basic_Information_Totals')
        file_loc = os.path.join(loc, 'Labor_Rates.csv')
        f = open(file_loc, 'r')
        f_data = f.readlines()
        f.close()
        names = []
        for i in range(len(f_data)):
            names.append(f_data[i].split(sep=',')[0])
        #get the totals from the labor page
        individauls = self.labor.find_tech_individual()
        #combine the two lists into a single string
        combined = ''
        for i in range(len(individauls)):
            combined += '{}: ${:,.2f}\n'.format(names[i], individauls[i])
        QMessageBox.information(self, 'Labor Breakdown', combined,
                                QMessageBox.Ok)

    def date_change(self):
        '''change the data on the invoices for the month
        '''
        self.date_changed = QWidget()
        self.date_changed.setWindowTitle('Change Invoice Date')
        self.date_changed.setWindowIcon(QIcon('BEI_Logo.png'))
        self.line = QLineEdit()
        self.line.setFont(self.font)
        self.line.setSizePolicy(self.size_policy, self.size_policy)
        self.save_date = QPushButton('Save Date')
        self.save_date.setFont(self.font)
        self.save_date.setSizePolicy(self.size_policy, self.size_policy)
        self.save_date.clicked.connect(self.saved_date)
        layout = QVBoxLayout()
        layout.addWidget(self.line)
        layout.addWidget(self.save_date)
        self.date_changed.setLayout(layout)

        d_location = os.path.join(self.base_directory,
                                  'Basic_Information_Totals')
        self.date_location = os.path.join(d_location, 'Invoice_Date.txt')

        y = open(self.date_location, 'r')
        date = y.readlines()
        y.close()
        self.line.setText(date[0])
        self.date_changed.show()

    def saved_date(self):
        '''
        Save the new date
        '''
        y = open(self.date_location, 'w')
        y.write(self.line.text())
        y.close()
        self.date_changed.close()

    def new_job_nums(self):
        '''Run the class to create more job numbers 
        '''
        self.n_jobs = Job_Numbers()

    def cheat_sheet(self):
        '''Open the cheat sheet for viewing
        '''
        self.chea = Read_Cheat_Sheet(self.font, self.size_policy,
                                     self.base_directory)

    def add_cheat_task(self):
        self.cheat = Write_Cheat_Sheet(self.font, self.size_policy,
                                       self.base_directory)

    def partial_payment(self):
        self.a = Partial_Payments(self.font, self.size_policy)
        self.a.add.clicked.connect(self.proce)

    def proce(self):
        try:
            self.a.process()
            self.this_payment = self.a.amount
            try:
                location = os.path.join(
                    os.path.join(self.base_directory, 'Saved_Invoices'),
                    '{}'.format(self.current_job))
                payments = os.path.join(location, 'Payments.csv')
                f = open(payments, 'r')
                value = float(f.readlines()[0])
                f.close()
                self.this_payment += value
            except:
                self.this_payment = self.this_payment
            self.comments.append(
                '''Partial payment of ${:,.2f} on {}, leaves a remaining balance of ${:,.2f}'''
                .format(self.a.amount, self.a.date,
                        self.totals - self.a.amount))
            f = open(payments, 'w')
            f.write(str(self.this_payment))
            self.partial = self.this_payment
            self.calculate_totals()
            f.close()
        except:
            pass

    def finance_charges(self):
        self.charg = Finance_Charges(self.font, self.size_policy)
        self.charg.add.clicked.connect(self.fin_process)

    def fin_process(self):
        self.charg.process()
        self.finance += self.charg.amount

        self.comments.append(
            'Finance Charge of ${:,.2f} applied on {}, kindly remit payment immediately.'
            .format(self.charg.amount, self.charg.date))
        location = os.path.join(
            os.path.join(self.base_directory, 'Saved_Invoices'),
            '{}'.format(self.current_job))
        fin_loc = os.path.join(location, 'Finance.csv')
        f = open(fin_loc, 'w')
        f.write(str(self.finance))
        f.close()
        self.calculate_totals()

    def change_basic_info(self):
        #first read in the current status of the basic info
        location = os.path.join(
            os.path.join(self.base_directory, 'Saved_Invoices'),
            '{}'.format(self.current_job))
        e = open(os.path.join(location, 'Basic_Info.csv'), 'r')
        basic = e.readlines()
        e.close()

        self.update_info = QWidget()
        self.update_info.setWindowTitle('Update Basic Information')
        self.update_info.setWindowIcon(QIcon('BEI_Logo.png'))
        mach = QLabel('Machine', self)
        mach.setFont(self.font)
        mach.setSizePolicy(self.size_policy, self.size_policy)

        tax = QLabel('Tax [%]', self)
        tax.setFont(self.font)
        tax.setSizePolicy(self.size_policy, self.size_policy)

        self.machine = QLineEdit(self)
        self.machine.setFont(self.font)
        self.machine.setSizePolicy(self.size_policy, self.size_policy)
        self.machine.setText(basic[2])

        self.tax_value = QLineEdit(self)
        self.tax_value.setFont(self.font)
        self.tax_value.setSizePolicy(self.size_policy, self.size_policy)
        self.tax_value.setText(
            str(round(float(basic[3].split(sep=',')[0]) * 100, 2)))

        update = QPushButton('Update', self)
        update.setFont(self.font)
        update.setSizePolicy(self.size_policy, self.size_policy)
        update.clicked.connect(self.update_basic_values)

        layout = QGridLayout()
        layout.addWidget(mach, 0, 0)
        layout.addWidget(self.machine, 0, 1)
        layout.addWidget(tax, 1, 0)
        layout.addWidget(self.tax_value, 1, 1)
        layout.addWidget(update, 2, 0)
        self.update_info.setLayout(layout)
        self.update_info.show()

    def update_basic_values(self):
        self.update_info.close()
        location = os.path.join(
            os.path.join(self.base_directory, 'Saved_Invoices'),
            '{}'.format(self.current_job))
        e = open(os.path.join(location, 'Basic_Info.csv'), 'r')
        basic = e.readlines()
        e.close()
        flag = False
        #change the information in basic[2] and basic[3] to match the new values
        if basic[2].split(sep='\n')[0] != self.machine.text():
            old = basic[2].split(sep='\n')[0].replace(' ', '_')
            cust = basic[1].split(sep='\n')[0].replace(' ', '_')
            file_name = basic[0].split(sep='\n')[0] + '.pdf'
            flag = True
            basic[2] = self.machine.text()
            self.machine_text = basic[2]
            self.machine_label.setText('Machine: {}'.format(self.machine_text))
        if float(basic[3].split(
                sep=',')[0]) != float(self.tax_value.text()) / 100:
            try:
                tax_code, ok = QInputDialog.getText(
                    self, 'Update Tax Code', 'Tax Code: ', QLineEdit.Normal,
                    basic[3].split(sep=',')[1].split(sep='\n')[0])
            except:
                tax_code, ok = QInputDialog.getText(self, 'Update Tax Code',
                                                    'Tax Code: ',
                                                    QLineEdit.Normal, "")
            basic[3] = '{},{}'.format(
                float(self.tax_value.text()) / 100, tax_code)

        self.tax = float(self.tax_value.text()) / 100

        f = open(os.path.join(location, 'Basic_Info.csv'), 'w')
        for i in range(len(basic)):
            if '\n' not in basic[i]:
                f.write('{}\n'.format(basic[i]))
            else:
                f.write('{}'.format(basic[i]))
        f.close()

        #change the percent shown in the total value
        self.totals_table.tableWidget.setItem(
            5, 0, QTableWidgetItem('Tax: {:.2f}%'.format(self.tax * 100)))
        #next update the totals
        self.calculate_totals()
        self.save_invoice()
        time.sleep(3)
        if flag:
            #depending on if the machine has been updated, get rid of the previous
            #version of the file and start change it to the new location
            location = os.path.join(os.path.expanduser('~/Desktop'),
                                    'BEI_Invoices')
            old_location_cust_ = os.path.join(
                os.path.join(location, 'Customer'), cust)
            old_location_cust = os.path.join(old_location_cust_, old)
            old_final_cust = os.path.join(old_location_cust, file_name)

            old_location_comp_ = os.path.join(
                os.path.join(location, 'Company'), cust)
            old_location_comp = os.path.join(old_location_comp_, old)
            len_old = len(os.listdir(old_location_comp))
            old_final_comp = os.path.join(old_location_comp, file_name)

            if len_old == 1:
                shutil.rmtree(old_location_comp)
                shutil.rmtree(old_location_cust)
            else:
                os.unlink(old_final_comp)
                os.unlink(old_final_cust)

    def view_windows(self):
        '''Used to re-initialize the totals and main window'''
        self.save_invoice()
        self.read_in_data()

    def closeEvent(self, event):
        if self.start_flag:
            self.save_invoice(printing=True)
            flag = self.save_no_threading()
            if flag == 0:
                reply = QMessageBox.question(
                    self, 'Close Window',
                    'Do you want to close the application?',
                    QMessageBox.Yes | QMessageBox.No, QMessageBox.No)

                if reply == QMessageBox.Yes:
                    event.accept()
                else:
                    event.ignore()
            else:
                event.ignore()
        else:
            event.accept()

    def updater(self):
        QMessageBox.information(self, 'Restart Required',
                                'Run BEI_Updater and Restart program',
                                QMessageBox.Ok)
        self.close()

    def change_address(self):
        self.edi = EDI(self.font, self.size_policy, self.base_directory)

    def view_customer(self):
        flag = self.save_no_threading()
        if flag == 0:
            location = os.path.join(os.path.expanduser('~/Desktop'),
                                    'BEI_Invoices')
            location = os.path.join(location, 'Customer')
            cust_location = os.path.join(location,
                                         self.customer.replace(' ', '_'))
            machine_location = os.path.join(
                cust_location, self.machine_text.replace(' ', '_'))
            job_location = os.path.join(machine_location, '{}.pdf'.format(
                self.current_job)).replace('&', '^&')
            print(job_location)
            subprocess.Popen(job_location, shell=True)
        else:
            pass

    def view_company(self):
        flag = self.save_no_threading()
        if flag == 0:
            location = os.path.join(os.path.expanduser('~/Desktop'),
                                    'BEI_Invoices')
            location = os.path.join(location, 'Company')
            cust_location = os.path.join(location,
                                         self.customer.replace(' ', '_'))
            machine_location = os.path.join(
                cust_location, self.machine_text.replace(' ', '_'))
            job_location = os.path.join(machine_location, '{}.pdf'.format(
                self.current_job)).replace('&', '^&')
            subprocess.Popen(job_location, shell=True)
        else:
            pass

    def save_no_threading(self):
        self.save_invoice(printing=True)
        try:
            pdf2.PDF_Builder(self.current_job, self.base_directory, 'Company')
            pdf2.PDF_Builder(self.current_job, self.base_directory, 'Customer')
            return 0
        except:
            QMessageBox.information(self, 'Opening Failure',
                                    'Close file and try again', QMessageBox.Ok)
            time.sleep(1)
            return 1

    def envelop_write(self):
        #navigate to the envelope folder
        loc = os.path.join(
            os.path.join(self.base_directory, 'Customer_Envelopes'),
            self.envelope_date + '.txt')
        f = open(loc, 'r')
        data = f.readlines()
        f.close()
        job_numbers = []
        for i in data:
            job_numbers.append(i.split()[1])
        QMessageBox.information(
            self, 'Envelope Printing',
            'Load {} invoices into printer before clicking OK'.format(
                len(job_numbers)), QMessageBox.Ok)
        base = os.path.join(self.base_directory, 'Saved_Invoices')
        for i in range(len(job_numbers)):
            enve_loc = os.path.join(os.path.join(base, job_numbers[i]),
                                    'envelope.pdf')
            os.startfile(enve_loc, 'print')

    def envelop_write1(self):
        #get the job number to print
        num, ok = QInputDialog.getText(self, 'Single Customer Envelope',
                                       'Job Number to print:',
                                       QLineEdit.Normal, '')
        if num != '' and ok:
            writer = EWriter(self.base_directory, num)
            writer.generate_latex()
            QMessageBox.information(
                self, 'Envelope Printing',
                'Load 1 invoices into printer before clicking OK',
                QMessageBox.Ok)
            writer.print_pdf()

    def billing_envelopes(self):
        self.billing_ = CE(self.base_directory)