#!/usr/bin/env python """ goes_asr @Description: goes_asr is an N4RT BUFR product. It requires the following file: - OR-ABI-L2-ASRF-M? Responsible for interfacing with the goes_asr unit. @History: - Letitia Soulliard, July, 26 2021, Created - brian.helgans, Sep 23, 2021, Reworked - qiang.zhao, Dec 21, 2023, Updated """ # *** Update to today *** __updated__ = "2023-12-21" from datetime import datetime from pathlib import Path from autologging import logged, traced import aim import os import re import subprocess @traced # tracing enabled via `python -m your_package config.yaml -t` @logged # adds self.__log -- use: self.__log.info("message") class Interface(aim.Interface): """ Defines the interface to run goes_asr. """ # initialization of the Interface class expects "template" # for validating the incoming configuration file # *** Update with your needed configuration **** template = {'directory': {'bin': str, # Perl script and main program 'working_dir': str}, # In/Output files 'command': {'perl': str, # Perl interpreter 'cwordsh': str}, # FORTRAN blocked format converter 'file': {'asr': str} # Input OR-ABI-L2-ASRF-M? NC file } def setup(self): """ Generate a configuration for the science code. This will create the traditional NDE PCF file that the NPR.pl perl script expects. """ self.__log.debug("creating executable config file") working_dir = Path(self.config['directory.working_dir']) # Create and move to working directory working_dir.mkdir(parents=True,exist_ok=True) os.chdir(self.config['directory.working_dir']) with open("NPR.pl.PCF", "w") as pcf: pcf.write(f"PROD_TYPE=G16-ASR\n") pcf.write(f"CONVERSION=NC2BUFR\n") pcf.write(f"NPR_INPUT={self.config['file.asr']}\n") pcf.write(f"OPS_BIN={self.config['directory.bin']}/exe\n") pcf.write(f"CWORDSH={self.config['command.cwordsh']}\n") def process(self): """ Run N4RT for goes_asr """ # Creation_time is to be determined in the NPR.pl script. self.creation_time = datetime.utcnow() # Add the call to run the code or scripts here. self.output_info['status'] = "error" run_command =[f"{self.config['command.perl']}", "-w", f"{self.config['directory.bin']}" "/scripts/NPR.pl"] self.__log.debug(f'Running N4RT for GOES_ASR with command: {run_command}') resource = subprocess.run(run_command, capture_output=False, check=True) return_code = resource.returncode if return_code != 0: raise RuntimeError(f"Error running command: {run_command}\n See " f"logfile: NPR.pl.log\n") if return_code == 0: self.output_info['status'] = "good" def reformat(self): """ Append NPR.pl.PCF and npr.filenames files to NRP.pl.log to form a master log file to save for debugging purpose. """ # Find the version number, satID and timestamps for the log file with open("npr.filenames", 'r') as nf: lines = nf.readlines() for line in lines: subline = line.split('/')[-1] if subline.find('bufr') != -1: outfile = line break parts = re.split('\.|_', outfile) version = parts[1] satid = parts[2] stime = parts[3] etime = parts[4] ctime = parts[5] self.log_file = f"N4RT-GOES-ASR_{version}_{satid}_{stime}_{etime}_{ctime}.log" with open(self.log_file, "w") as alf: alf.write('===== NPR.pl.PCF =====\n') alf.write(' \n') with open("NPR.pl.PCF", "r") as pcf: alf.write(pcf.read()) alf.write(' \n') alf.write('===== npr.filenames =====\n') alf.write(' \n') with open("npr.filenames", "r") as nf: alf.write(nf.read()) alf.write(' \n') alf.write('===== NPR.pl.log =====\n') alf.write(' \n') with open("NPR.pl.log", "r") as nlf: alf.write(nlf.read()) def output(self): """ Inform OPS of any remaining files it should know about. Add any files that need to be pulled out of the container and saved into the output_info hand off object. Create a FileToken object for each file and give each file a useful label value. Converting the traditional NDE PSF file into a handoff object. """ with open("NPR.pl.PSF", "r") as psf: file_list = psf.readlines() output_list = list() for my_file in file_list: my_file = my_file.rstrip() my_file = Path(my_file) if my_file.parent is None: my_file = Path(f"{self.config['directory.working']}/{my_file}") file_info = {"path": my_file} file_info["label"] = f"{my_file.name.split('_')[0]}" file_token = aim.OpsFileToken(file_info) output_list.append(file_token) lf_filetoken = aim.OpsFileToken({"path": self.log_file, "label": "LOG"}) output_list.append(lf_filetoken) self.output_info['file'] = output_list