Пример #1
0
    def run_sensor_cal(self, sensor):

        if (self.cur_row < 0):
            msg = 'No Q330 has been seleceted'
            logging.info(msg)
            res = QtWidgets.QMessageBox().warning(self.app_win, 'PyCal', msg,
                                                  QtWidgets.QMessageBox().Close,
                                                  QtWidgets.QMessageBox().Close)
        else:
            wcfg = self.cfg[self.cur_row]

            if sensor not in ['A', 'B']:
                msg = 'Invalid sensor can not be calibrated:' + sensor
                logging.error(msg)
                raise Exception(msg)

            if sensor == 'A':
                seis_model = wcfg.data[WrapperCfg.WRAPPER_KEY_SENS_COMPNAME_A]
                sensor_descr = wcfg.data[WrapperCfg.WRAPPER_KEY_SENS_DESCR_A]
                chancodes = wcfg.data[WrapperCfg.WRAPPER_KEY_CHANNELS_A]
                loc = wcfg.data[WrapperCfg.WRAPPER_KEY_LOCATION_A]
            elif sensor == 'B':
                seis_model = wcfg.data[WrapperCfg.WRAPPER_KEY_SENS_COMPNAME_B]
                sensor_descr = wcfg.data[WrapperCfg.WRAPPER_KEY_SENS_DESCR_B]
                chancodes = wcfg.data[WrapperCfg.WRAPPER_KEY_CHANNELS_B]
                loc = wcfg.data[WrapperCfg.WRAPPER_KEY_LOCATION_B]

            # replace 'no LOC' underscores with spaces.
            loc = loc.replace('_', ' ')
            # lets just make sure sensor in CTBTO supported list
            # should never get here is cfg files deployed correctly
            if seis_model not in CTBTO_SEIS_MODELS:
                msg = 'PyCal UNSUPPORTED SENSOR MODEL: ' + seis_model
                logging.error(msg)
                QtWidgets.QMessageBox().critical(self.app_win, 'PyCal ERROR', msg,
                                             QtWidgets.QMessageBox().Close,
                                             QtWidgets.QMessageBox().Close)
                return

            lf_calib = self.cfg.find_calib(seis_model + '|' + CALTYPE_RBLF)
            hf_calib = self.cfg.find_calib(seis_model + '|' + CALTYPE_RBHF)

            if (not lf_calib) or (not hf_calib):
                msg = 'Calib Record missing for sensor [{}].'.format(seis_model)
                logging.error(msg)
                QtWidgets.QMessageBox().critical(self.app_win, 'PyCal ERROR', msg,
                                                 QtWidgets.QMessageBox().Close,
                                                 QtWidgets.QMessageBox().Close)
                return

            sta = wcfg.data[WrapperCfg.WRAPPER_KEY_STA]
            ip = wcfg.data[WrapperCfg.WRAPPER_KEY_IP]

            output_dir = os.path.join(pcgl.get_results_root(), '-'.join([sta, ip.replace('.', '_'), sensor, seis_model]))
            makedirs(output_dir, mode=0o744, exist_ok=True)

            cal_descr = '{:>11} : {:<6} at {}'.format('Q330 Tag#', wcfg.data[WrapperCfg.WRAPPER_KEY_TAGNO], ip)
            cal_descr += '\n{:>11} : {} (Sensor {})'.format('Sensor', sensor_descr, sensor)
            cal_descr += '\n{:>11} : {}'.format('Station', wcfg.data[WrapperCfg.WRAPPER_KEY_STA])
            cal_descr += '\n{:>11} : {}'.format('Loc', loc)
            cal_descr += '\n{:>11} : {}'.format('Chan Codes', chancodes)

            tot_cal_time = lf_calib.cal_time_min() + hf_calib.cal_time_min()

            cal_info = {
                'sta' : sta,
                'loc' : loc,
                'chancodes' : chancodes,
                'ip' : ip,
                'seis_model' : seis_model,
                'cal_descr': cal_descr,
                'cal_tot_time_mins': tot_cal_time,
                'cal_time' : {
                    CALTYPE_RBLF : lf_calib.cal_time_min(),
                    CALTYPE_RBHF : hf_calib.cal_time_min(),
                },
                'cmd_line' : {
                    CALTYPE_RBHF : wcfg.gen_qcal_cmdline(sensor, CALTYPE_RBHF) + ' root=' + self.cfg.root_dir,
                    CALTYPE_RBLF : wcfg.gen_qcal_cmdline(sensor, CALTYPE_RBLF) + ' root=' + self.cfg.root_dir
                },
                'output_dir': output_dir
            }

            logging.debug('cal_info:' + str(cal_info))

            success, lf_msfn = self.run_sensor_cal_type(sensor, CALTYPE_RBLF, cal_info)
            if success:
                lf_logfn = os.path.splitext(lf_msfn)[0] + '.log'
                logging.info('QCal RBLF Miniseed file saved: ' + os.path.join(output_dir, lf_msfn))
                logging.info('QCal RBLF Log file saved: ' + os.path.join(output_dir, lf_logfn))

                # need 5.5 minute "cooling off period" before starting HF run
                if not self.cool_off_q330(window_title='PyCal - Preparing for HF Stage',
                                          info_text='Preparing for HF calibration stage...',
                                          cooling_period_seconds=330):
                    return

                success, hf_msfn = self.run_sensor_cal_type(sensor, CALTYPE_RBHF, cal_info)
                if success:
                    chancodeslst = chancodes.split(',')
                    channel_codes = ComponentsTpl(vertical=chancodeslst[0], north=chancodeslst[1], east=chancodeslst[2])

                    hf_logfn = os.path.splitext(hf_msfn)[0] + '.log'
                    logging.info('QCal RBHF Miniseed file saved: ' + os.path.join(output_dir, hf_msfn))
                    logging.info('QCal RBHF Log file saved: ' + os.path.join(output_dir, hf_logfn))

                    # msg_box = QtWidgets.QMessageBox(self.app_win)
                    # msg_box.setIcon(QtWidgets.QMessageBox.Information)
                    # msg_box.setText('PyCal Analysis Phase Starting')
                    # msg_box.setInformativeText(
                    #     'Calibration data acquired successfully.\n\n' +
                    #     'The data will now be analyzed.\n' +
                    #     'This will take several minutes.')
                    # btn = msg_box.addButton('Continue...', QtWidgets.QMessageBox.RejectRole)
                    # msg_box.setDefaultButton(btn)
                    # msg_box.exec()
                    #
                    if seis_model in SEISMOMETER_RESPONSES:
                        if getattr(sys, 'frozen', False):
                            bundle_dir = sys._MEIPASS
                            full_paz_fn = os.path.abspath(os.path.join(bundle_dir,
                                                                       'IDA',
                                                                       'data',
                                                                       SEISMOMETER_RESPONSES[seis_model]['full_resp_file']))
                        else:
                            full_paz_fn = os.path.abspath(os.path.join('.',
                                                                       'data',
                                                                       SEISMOMETER_RESPONSES[seis_model]['full_resp_file']))
                    else:
                        msg1 = 'PyCal does not have response information for SENSOR MODEL: ' + seis_model
                        msg2 = 'Analysis can not be performed.'
                        logging.error(msg1)
                        logging.error(msg2)
                        QtWidgets.QMessageBox().critical(self.app_win, 'PyCal ERROR', msg1 + '\n' + msg2,
                                                         QtWidgets.QMessageBox().Close,
                                                         QtWidgets.QMessageBox().Close)
                        return

                    logging.info('Analysis starting...')
                    logging.debug('Using FULL response at: ' + full_paz_fn)

                    retcode, \
                    ims_calres_txt_fn, \
                    cal_amp_plot_fn, \
                    cal_pha_plot_fn = self.run_analysis(process_qcal_data,
                                                        sta,
                                                        channel_codes,
                                                        loc,
                                                        output_dir,
                                                        (lf_msfn, lf_logfn),
                                                        (hf_msfn, hf_logfn),
                                                        seis_model,
                                                        full_paz_fn)

                    if retcode == 0:
                        logging.info('Analysis phase completed with return code: {}'.format(retcode))
                        logging.info('The following files have been saved in directory: ' + output_dir)
                        logging.info('  {} {}'.format('CALIBRATE_RESULT Msg: ', os.path.basename(ims_calres_txt_fn)))
                        logging.info('  {} {}'.format('Amplitude Response Plots: ', os.path.basename(cal_amp_plot_fn)))
                        logging.info('  {} {}'.format('Phase Response Plots: ', os.path.basename(cal_pha_plot_fn)))

                        msg_list = ['Result files saved in directory:\n\n{}\n\n'.format(output_dir),
                                    '{}\n{}\n\n'.format('IMS 2.0 MESSAGE TEMPLATE:', os.path.basename(ims_calres_txt_fn)),
                                    '{}\n{}\n\n'.format('AMP PLOTS:', os.path.basename(cal_amp_plot_fn)),
                                    '{}\n{}'.format('PHASE PLOTS:', os.path.basename(cal_pha_plot_fn))]

                        res = QtWidgets.QMessageBox().information(self.app_win, 'PyCal',
                                                                  'Calibration completed successfully!\n\n' + ''.join(msg_list),
                                                                  QtWidgets.QMessageBox().Close,
                                                                  QtWidgets.QMessageBox().Close)

                        call(['open', output_dir])
                        call(['open', '-a', 'TextEdit', ims_calres_txt_fn])
                        call(['open', cal_amp_plot_fn])
                        call(['open', cal_pha_plot_fn])
                    else:
                        logging.warning('Analysis phase completed with return code: {}'.format(retcode))
                else:
                    self.update_details(self.cur_row) # triggers comms check...

            else:
                self.update_details(self.cur_row) # triggers comms check...
                logging.error("Unable to complete calibration")
Пример #2
0
    def run_test_analysis(self):

        QtWidgets.QMessageBox().information(self.app_win, 'PyCal Analysis',
                                                  'Calibration data acquired successfully.\n\n'
                                                  'The data will now be analyzed.\n'
                                                  'This could take several minutes.',
                                                  QtWidgets.QMessageBox().Close,
                                                  QtWidgets.QMessageBox().Close)

        channel_codes = ComponentsTpl(north='BHN', east='BHE', vertical='BHZ')

        sensor = 'A'
        seis_model = SEISTYPE_STS25

        # sta = 'AS108'
        # loc = '10'
        # ip = '198.202.124.228'
        # hf_msfn  = 'CAL-198.202.124.228-sts2.5-rbhf-2016-0511-1213.ms'
        # hf_logfn = 'CAL-198.202.124.228-sts2.5-rbhf-2016-0511-1213.log'
        # lf_msfn  = 'CAL-198.202.124.228-sts2.5-rblf-2016-0511-1249.ms'
        # lf_logfn = 'CAL-198.202.124.228-sts2.5-rblf-2016-0511-1249.log'
        #
        # # XPFO "Fast" test
        # seis_model = 'sts2.5-F'
        # sta='XPFO'
        # ip = '172.23.34.108'
        # hf_msfn = 'CAL-172.23.34.108-sts2.5-F-rbhf-2016-0511-0838.ms'
        # hf_logfn = 'CAL-172.23.34.108-sts2.5-F-rbhf-2016-0511-0838.log'
        # lf_msfn = 'CAL-172.23.34.108-sts2.5-F-rblf-2016-0511-0836.ms'
        # lf_logfn = 'CAL-172.23.34.108-sts2.5-F-rblf-2016-0511-0836.log'
        #
        seis_model = self.test_set['seis_model']
        sta = self.test_set['sta']
        ip = self.test_set['ip']
        loc = self.test_set['loc']
        hf_msfn = self.test_set['hf_msfn']
        hf_logfn = self.test_set['hf_logfn']
        lf_msfn = self.test_set['lf_msfn']
        lf_logfn = self.test_set['lf_logfn']

        output_dir = os.path.join(pcgl.get_results_root(), '-'.join([sta, ip.replace('.','_'), sensor, seis_model]))

        if seis_model in SEISMOMETER_RESPONSES:
            if getattr(sys, 'frozen', False):
                bundle_dir = sys._MEIPASS
                full_paz_fn = os.path.abspath(os.path.join(bundle_dir, 'IDA', 'data', SEISMOMETER_RESPONSES[seis_model]['full_resp_file']))
            else:
                full_paz_fn = os.path.abspath(os.path.join('.', 'data', SEISMOMETER_RESPONSES[seis_model]['full_resp_file']))
        else:
            msg1 = 'PyCal does not have response information for SENSOR MODEL: ' + seis_model
            msg2 = 'Analysis can not be performed.'
            logging.error(msg1)
            logging.error(msg2)
            QtWidgets.QMessageBox().critical(self.app_win, 'PyCal ERROR', msg1 + '\n' + msg2,
                                             QtWidgets.QMessageBox().Close,
                                             QtWidgets.QMessageBox().Close)
            return

        logging.info('Analysis starting...')
        logging.debug('Using FULL response at: ' + full_paz_fn)

        retcode, \
        ims_calres_txt_fn, \
        cal_amp_plot_fn, \
        cal_pha_plot_fn = self.run_analysis(process_qcal_data,
                                            sta,
                                            channel_codes,
                                            loc,
                                            output_dir,
                                            (lf_msfn, lf_logfn),
                                            (hf_msfn, hf_logfn),
                                            seis_model,
                                            full_paz_fn)

        if retcode == 0:
            call(['open', output_dir])
            call(['open', '-a', 'TextEdit', ims_calres_txt_fn])
            call(['open', cal_amp_plot_fn])
            call(['open', cal_pha_plot_fn])

            msg_list = ['Results can be found in directory:\n\n{}\n\n'.format(output_dir),
                        '{}\n{}\n\n'.format('IMS 2.0 MESSAGE TEMPLATE:', os.path.basename(ims_calres_txt_fn)),
                        '{}\n{}\n\n'.format('AMP PLOTS:', os.path.basename(cal_amp_plot_fn)),
                        '{}\n{}'.format('PHASE PLOTS:', os.path.basename(cal_pha_plot_fn))]

            logging.info('The following files have been saved in directory: ' + output_dir)
            logging.info('   IMS 2.0 MESSAGE TEMPLATE: ' + os.path.basename(ims_calres_txt_fn))
            logging.info('   Amplitude Response Plots: ' + os.path.basename(cal_amp_plot_fn))
            logging.info('   Phase Response Plots: ' + os.path.basename(cal_pha_plot_fn))

            res = QtWidgets.QMessageBox().information(self.app_win, 'PyCal',
                                                      'Calibration completed successfully!\n\n' + ''.join(msg_list),
                                                      QtWidgets.QMessageBox().Close,
                                                      QtWidgets.QMessageBox().Close)