From 9406ffa40607e64f95e5fe479431c80ac67c47b6 Mon Sep 17 00:00:00 2001 From: Charlotte Hausman <chausman@nrao.edu> Date: Fri, 2 Jul 2021 20:57:04 +0000 Subject: [PATCH] imaging changes for casa_envoy and vela --- .../casa_envoy/casa_envoy/launchers.py | 114 ++++++++++++++ .../pexable/casa_envoy/casa_envoy/palaver.py | 140 ++++++++---------- .../pexable/casa_envoy/test/cmsimage-PPR.xml | 92 ++++++++++++ .../casa_envoy/test/image-metadata.json | 15 ++ .../casa_envoy/test/test_casa_envoy.py | 63 ++++---- .../pexable/casa_envoy/test/test_launchers.py | 68 +++++++++ .../pexable/vela/test/cmsimage-PPR.xml | 92 ++++++++++++ .../pexable/vela/test/image-metadata.json | 15 ++ .../pexable/vela/test/test_emulators.py | 72 +++++++++ .../pexable/vela/test/test_forger.py | 66 +++++++-- .../pexable/vela/test/test_vela.py | 70 ++++++--- .../pexable/vela/vela/emulators.py | 98 ++++++++++++ .../executables/pexable/vela/vela/forger.py | 51 ++++++- .../pexable/vela/vela/interfaces.py | 3 +- .../executables/pexable/vela/vela/quasar.py | 85 +++-------- .../workflow/services/workflow_service.py | 3 + 16 files changed, 831 insertions(+), 216 deletions(-) create mode 100644 apps/cli/executables/pexable/casa_envoy/casa_envoy/launchers.py create mode 100644 apps/cli/executables/pexable/casa_envoy/test/cmsimage-PPR.xml create mode 100644 apps/cli/executables/pexable/casa_envoy/test/image-metadata.json create mode 100644 apps/cli/executables/pexable/casa_envoy/test/test_launchers.py create mode 100644 apps/cli/executables/pexable/vela/test/cmsimage-PPR.xml create mode 100644 apps/cli/executables/pexable/vela/test/image-metadata.json create mode 100644 apps/cli/executables/pexable/vela/test/test_emulators.py create mode 100644 apps/cli/executables/pexable/vela/vela/emulators.py diff --git a/apps/cli/executables/pexable/casa_envoy/casa_envoy/launchers.py b/apps/cli/executables/pexable/casa_envoy/casa_envoy/launchers.py new file mode 100644 index 000000000..911e4b473 --- /dev/null +++ b/apps/cli/executables/pexable/casa_envoy/casa_envoy/launchers.py @@ -0,0 +1,114 @@ +import logging +import re +import glob +import sys +import os +import subprocess + +from casa_envoy.interfaces import CasaLauncherIF +from casa_envoy.schema import AbstractTextFile + + +def get_base_environment(parameters: dict): + os.environ["SCIPIPE_ROOTDIR"] = parameters["rootDirectory"] + os.environ["CASA_HOME"] = parameters["homeForReprocessing"] + os.environ["LANG"] = "en_US.UTF-8" + + +def check_processing_env(logger: logging.Logger): + logger.info("Checking processing environment:") + env1 = os.environ.get("SCIPIPE_ROOTDIR") + logger.info(f"SCIPIPE_ROOTDIR: {env1}") + env2 = os.environ.get("CASA_HOME") + logger.info(f"CASA_HOME: {env2}") + env3 = os.environ.get("PPR_FILENAME") + logger.info(f"PPR_FILENAME: {env3}") + env4 = os.environ.get("LANG") + logger.info(f"LANG: {env4}") + if "None" in [env1, env2, env3, env4]: + logger.info("Environment setup Failed!") + sys.exit(1) + else: + logger.info("Environment ready for processing") + + +class CalibrationLauncher(CasaLauncherIF): + def __init__(self, ppr: AbstractTextFile, metadata: AbstractTextFile): + self.logger = logging.getLogger("casa_envoy") + self.ppr = ppr + self.metadata = metadata + + def run(self): + self.logger.info("RUNNING CASA CALIBRATION!") + os.chdir("./working") + result = subprocess.Popen( + "PYTHONPATH='' xvfb-run -e ${PWD}/xvfb-run.err.txt -d -s \"-screen 0 800x600x16\" " + "${CASA_HOME}/bin/casa --pipeline --nogui --nologger -c " + "${CASA_HOME}/pipeline/pipeline/runvlapipeline.py ${PPR_FILENAME} || true", + shell=True, + executable="/bin/bash", + stdout=sys.stdout, + stderr=sys.stderr, + ) + return result.communicate() + + def setup_environment(self, parameters: dict): + get_base_environment(parameters) + os.environ["PPR_FILENAME"] = str(self.ppr) + + check_processing_env(self.logger) + + def check_logs(self, parent_path: str): + self.logger.info("CHECKING CASA CALIBRATION LOGS!") + # make sure we are in the correct directory to find log file + if not os.getcwd().endswith("/working"): + os.chdir(parent_path + "/working") + + casa_logs = glob.glob("casa-*.log") + + for file in casa_logs: + if re.match("^.*SEVERE\sflagmanager.*$", open(file).read()): + self.logger.error("CASA ERROR!") + else: + self.logger.info("CASA Success!") + + +class ImagingLauncher(CasaLauncherIF): + def __init__(self, ppr: AbstractTextFile, metadata: AbstractTextFile): + self.logger = logging.getLogger("casa_envoy") + self.ppr = ppr + self.metadata = metadata + + def run(self): + self.logger.info("RUNNING CASA IMAGING!") + os.chdir("./working") + result = subprocess.Popen( + "PYTHONPATH='' xvfb-run -e ${PWD}/xvfb-run.err.txt -d -s \"-screen 0 800x600x16\" " + "${CASA_HOME}/bin/casa --pipeline --nogui --nologger -c " + "${CASA_HOME}/pipeline/pipeline/runvlapipeline.py ${PPR_FILENAME} || true", + shell=True, + executable="/bin/bash", + stdout=sys.stdout, + stderr=sys.stderr, + ) + return result.communicate() + + def setup_environment(self, parameters: dict): + get_base_environment(parameters) + os.environ["PPR_FILENAME"] = str(self.ppr) + + check_processing_env(self.logger) + + def check_logs(self, parent_path: str): + self.logger.info("CHECKING CASA IMAGING LOGS!") + # make sure we are in the correct directory to find log file + if not os.getcwd().endswith("/working"): + os.chdir(parent_path + "/working") + + casa_logs = glob.glob("casa-*.log") + + for file in casa_logs: + if re.match("^.*SEVERE\sflagmanager.*$", open(file).read()): + self.logger.error("CASA ERROR!") + else: + self.logger.info("CASA Success!") diff --git a/apps/cli/executables/pexable/casa_envoy/casa_envoy/palaver.py b/apps/cli/executables/pexable/casa_envoy/casa_envoy/palaver.py index 71cfb981f..0aa55ca27 100644 --- a/apps/cli/executables/pexable/casa_envoy/casa_envoy/palaver.py +++ b/apps/cli/executables/pexable/casa_envoy/casa_envoy/palaver.py @@ -5,21 +5,15 @@ palaver definition: an unnecessarily elaborate or complex procedure import argparse import logging import pathlib -import re import subprocess - -import glob - +import sys +import os import json from typing import Dict - -from casa_envoy.auditor import AuditDirectories, AuditFiles -from casa_envoy.interfaces import CasaLauncherIF -from casa_envoy.schema import AbstractTextFile from pycapo import CapoConfig -import sys -import os +from casa_envoy.auditor import AuditDirectories, AuditFiles +from casa_envoy.launchers import CalibrationLauncher, ImagingLauncher """ Launch CASA processing jobs via Workspaces @@ -30,60 +24,11 @@ logger.setLevel(logging.INFO) logger.addHandler(logging.StreamHandler(sys.stdout)) -class CalibrationLauncher(CasaLauncherIF): - - def __init__(self, ppr: AbstractTextFile, metadata: AbstractTextFile): - self.ppr = ppr - self.metadata = metadata - - def run(self): - logger.info("RUNNING CASA!") - os.chdir("./working") - result = subprocess.Popen("PYTHONPATH='' xvfb-run -e ${PWD}/xvfb-run.err.txt -d -s \"-screen 0 800x600x16\" " - "${CASA_HOME}/bin/casa --pipeline --nogui --nologger -c " - "${CASA_HOME}/pipeline/pipeline/runvlapipeline.py ${PPR_FILENAME} || true", - shell=True, executable="/bin/bash", stdout=sys.stdout, stderr=sys.stderr) - return result.communicate() - - def setup_environment(self, parameters: dict): - os.environ['SCIPIPE_ROOTDIR'] = parameters["rootDirectory"] - os.environ['CASA_HOME'] = parameters["homeForReprocessing"] - os.environ['PPR_FILENAME'] = str(self.ppr) - os.environ['LANG'] = "en_US.UTF-8" - - logger.info("Checking processing environment:") - env1 = os.environ.get('SCIPIPE_ROOTDIR') - logger.info(f"SCIPIPE_ROOTDIR: {env1}") - env2 = os.environ.get('CASA_HOME') - logger.info(f"CASA_HOME: {env2}") - env3 = os.environ.get('PPR_FILENAME') - logger.info(f"PPR_FILENAME: {env3}") - env4 = os.environ.get('LANG') - logger.info(f"LANG: {env4}") - if 'None' in [env1, env2, env3, env4]: - logger.info("Environment setup Failed!") - sys.exit(1) - else: - logger.info("Environment ready for processing") - - def check_logs(self, parent_path: str): - logger.info("CHECKING CASA LOGS!") - # make sure we are in the correct directory to find log file - if not os.getcwd().endswith("/working"): - os.chdir(parent_path + "/working") - - casa_logs = glob.glob('casa-*.log') - - for file in casa_logs: - if re.match("^.*SEVERE\sflagmanager.*$", open(file).read()): - logger.info("CASA ERROR!") - else: - logger.info("CASA Success!") - - def _get_settings(cwd: pathlib.Path): use_casa = CapoConfig().getboolean("edu.nrao.archive.workspaces.ProcessingSettings.useCasa") - casa_home = CapoConfig().settings("edu.nrao.archive.workflow.config.CasaVersions").homeForReprocessing + casa_home = ( + CapoConfig().settings("edu.nrao.archive.workflow.config.CasaVersions").homeForReprocessing + ) root_dir = str(cwd.parent) processing_dir = str(cwd.stem) @@ -92,29 +37,36 @@ def _get_settings(cwd: pathlib.Path): "useCasa": use_casa, "homeForReprocessing": casa_home, "rootDirectory": root_dir, - "processingDirectory": processing_dir + "processingDirectory": processing_dir, } def arg_parser() -> argparse.ArgumentParser: parser = argparse.ArgumentParser( description="Workspaces CASA processing launcher", - formatter_class=argparse.RawTextHelpFormatter + formatter_class=argparse.RawTextHelpFormatter, ) parser.add_argument( "--standard-cal", nargs=2, action="store", required=False, - help="run the standard calibration CASA pipeline" + help="run the standard calibration CASA pipeline", + ) + parser.add_argument( + "--standard-img", + nargs=2, + action="store", + required=False, + help="run the standard calibration CASA pipeline", ) return parser -def check_calibratable(metadata_filename) -> bool: - with open(str(metadata_filename)) as json_meta: +def check_calibratable(metadata_filename: str) -> bool: + with open(metadata_filename) as json_meta: metadata = json.loads(json_meta.read()) - spl = metadata['productLocator'] + spl = metadata["productLocator"] if "execblock" in spl: return True else: @@ -122,6 +74,18 @@ def check_calibratable(metadata_filename) -> bool: return False +def check_imagable(metadata_filename: str) -> bool: + with open(metadata_filename) as json_meta: + metadata = json.loads(json_meta.read()) + cms_name = metadata["cmsName"] + cms_path = metadata["calibrationSourceDirectory"] + if cms_name is not None and cms_path is not None and cms_name[-3:] == ".ms": + return True + else: + logger.info("CMS ERROR: Imaging requires a valid CMS name and location!") + return False + + def run_audit(ppr: str, metadata: str, settings: Dict[str, str]): dir_audit = AuditDirectories(ppr, settings).audit() if dir_audit: @@ -140,16 +104,16 @@ def run_audit(ppr: str, metadata: str, settings: Dict[str, str]): def main(): args = arg_parser().parse_args() - metadata = args.standard_cal[0] - ppr = args.standard_cal[1] - if check_calibratable(metadata): - path = os.getcwd() - settings = _get_settings(pathlib.Path(path)) + path = os.getcwd() + settings = _get_settings(pathlib.Path(path)) - run_audit(ppr, metadata, settings) + if args.standard_cal is not None: + metadata = args.standard_cal[0] + ppr = args.standard_cal[1] - if args.standard_cal: + run_audit(ppr, metadata, settings) + if check_calibratable(metadata): if settings.get("useCasa"): launcher = CalibrationLauncher(ppr, metadata) launcher.setup_environment(settings) @@ -160,6 +124,26 @@ def main(): else: logger.info("RUNNING VELA!") subprocess.run(["./vela", "--standard-cal", metadata, ppr]) - else: - logger.info("TYPE ERROR: Provided SPL is not type execution block!") - sys.exit(1) + else: + logger.error("ERROR: Provided SPL is not type execution block!") + sys.exit(1) + + elif args.standard_img is not None: + metadata = args.standard_img[0] + ppr = args.standard_img[1] + + run_audit(ppr, metadata, settings) + if check_imagable(metadata): + if settings.get("useCasa"): + launcher = ImagingLauncher(ppr, metadata) + launcher.setup_environment(settings) + launcher.run() + launcher.check_logs(parent_path=path) + # return to parent directory after processing + os.chdir(path) + else: + logger.info("RUNNING VELA!") + subprocess.run(["./vela", "--standard-img", metadata, ppr]) + else: + logger.error("ERROR: CMS information missing or incorrect!") + sys.exit(1) diff --git a/apps/cli/executables/pexable/casa_envoy/test/cmsimage-PPR.xml b/apps/cli/executables/pexable/casa_envoy/test/cmsimage-PPR.xml new file mode 100644 index 000000000..41493f3ed --- /dev/null +++ b/apps/cli/executables/pexable/casa_envoy/test/cmsimage-PPR.xml @@ -0,0 +1,92 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<ns2:SciPipeRequest xmlns:ns2="Common/pipelinescience/SciPipeRequest"> + <ProjectSummary> + <ProposalCode>VLA/null</ProposalCode> + <Observatory>NRAO</Observatory> + <Telescope>VLA</Telescope> + <ProcessingSite>Socorro</ProcessingSite> + <Operator>vlapipe</Operator> + <Mode>SCIENCE</Mode> + <Version>NGRH-ALMA-10_8</Version> + <CreationTime>2021-07-01T21:14:00</CreationTime> + </ProjectSummary> + <ProjectStructure>TBD</ProjectStructure> + <ProcessingRequests> + <RootDirectory>/lustre/aoc/cluster/pipeline/docker/workspaces/spool</RootDirectory> + <ProcessingRequest> + <ProcessingIntents> + <Intents> + <Keyword>VLA_INTERFEROMETRY_STANDARD_OBSERVING_MODE</Keyword> + <Value>Undefined</Value> + </Intents> + </ProcessingIntents> + <ProcessingProcedure> + <ProcedureTitle>hifv_contimage</ProcedureTitle> + <ProcessingCommand> + <Command xmlns="">hifv_importdata</Command> + <ParameterSet> + </ParameterSet> + </ProcessingCommand> + <ProcessingCommand> + <Command xmlns="">hif_mstransform</Command> + <ParameterSet> + </ParameterSet> + </ProcessingCommand> + <ProcessingCommand> + <Command xmlns="">hif_checkproductsize</Command> + <ParameterSet> + <Parameter> + <Keyword xmlns="">maximsize</Keyword> + <Value xmlns="">16384</Value> + </Parameter> + </ParameterSet> + </ProcessingCommand> + <ProcessingCommand> + <Command xmlns="">hif_makeimlist</Command> + <ParameterSet> + <Parameter> + <Keyword xmlns="">specmode</Keyword> + <Value xmlns="">cont</Value> + </Parameter> + </ParameterSet> + </ProcessingCommand> + <ProcessingCommand> + <Command xmlns="">hif_makeimages</Command> + <ParameterSet> + <Parameter> + <Keyword xmlns="">hm_masking</Keyword> + <Value xmlns="">none</Value> + </Parameter> + <Parameter> + <Keyword xmlns="">hm_cyclefactor</Keyword> + <Value xmlns="">3.0</Value> + </Parameter> + </ParameterSet> + </ProcessingCommand> + <ProcessingCommand> + <Command xmlns="">hifv_exportdata</Command> + <ParameterSet> + <Parameter> + <Keyword xmlns="">imaging_products_only</Keyword> + <Value xmlns="">True</Value> + </Parameter> + </ParameterSet> + </ProcessingCommand> + </ProcessingProcedure> + <DataSet> + <RelativePath>tmpo1ca1pp_</RelativePath> + <SdmIdentifier>brain_000.58099.67095825232.ms</SdmIdentifier> + <DataType>asdm</DataType> + </DataSet> + </ProcessingRequest>0 + </ProcessingRequests> + <ResultsProcessing> + <ArchiveResults>false</ArchiveResults> + <CleanUpDisk>false</CleanUpDisk> + <UpdateProjectLifeCycle>false</UpdateProjectLifeCycle> + <NotifyOperatorWhenDone>false</NotifyOperatorWhenDone> + <SDMall>false</SDMall> + <SDMonly>false</SDMonly> + <PipelineOperatorAddress>Unknown</PipelineOperatorAddress> + </ResultsProcessing> +</ns2:SciPipeRequest> diff --git a/apps/cli/executables/pexable/casa_envoy/test/image-metadata.json b/apps/cli/executables/pexable/casa_envoy/test/image-metadata.json new file mode 100644 index 000000000..e2b19ffab --- /dev/null +++ b/apps/cli/executables/pexable/casa_envoy/test/image-metadata.json @@ -0,0 +1,15 @@ +{ + "fileSetIds": "brain_000.58099.67095825232", + "workflowName": "std_cms_imaging", + "systemId": "4", + "productLocator": "uid://evla/execblock/ec082e65-452d-4fec-ad88-f5b4af1f9e36", + "projectMetadata": { + "projectCode": "Operations", + "title": "", + "startTime": "58099.6710792824", + "observer": "VLA Operations" + }, + "destinationDirectory": "/lustre/aoc/cluster/pipeline/docker/workspaces/spool/tmpo1ca1pp_", + "calibrationSourceDirectory":"/lustre/aoc/cluster/pipeline/docker/workspaces/spool/tmpowrvygml/working", + "cmsName":"brain_000.58099.67095825232.ms" +} diff --git a/apps/cli/executables/pexable/casa_envoy/test/test_casa_envoy.py b/apps/cli/executables/pexable/casa_envoy/test/test_casa_envoy.py index 0a1eda676..4089a39f0 100644 --- a/apps/cli/executables/pexable/casa_envoy/test/test_casa_envoy.py +++ b/apps/cli/executables/pexable/casa_envoy/test/test_casa_envoy.py @@ -1,42 +1,35 @@ """ Tests for casa_envoy.palaver """ -import os -from unittest.mock import mock_open, patch - -from casa_envoy.palaver import ( - CalibrationLauncher, - check_calibratable, -) - - -class TestCalibrationLauncher: - @patch("os.chdir") - def test_run(self, mock_os): - with patch("subprocess.Popen") as sp: - CalibrationLauncher("test/PPR.xml", "test/test.json").run() - sp.call_count == 1 - - def test_setup_environment(self): - parameters = { - "useCasa": False, - "homeForReprocessing": "/home/casa/packages/pipeline/current", - "rootDirectory": "/tmp/workspaces_tmp/", - "processingDirectory": "tmpiox5trbp" - } - CalibrationLauncher("PPR.xml", "test.json").setup_environment(parameters=parameters) - assert os.environ.get("SCIPIPE_ROOTDIR") == parameters["rootDirectory"] - assert os.environ.get("CASA_HOME") == parameters["homeForReprocessing"] - assert os.environ.get("PPR_FILENAME") == "PPR.xml" - - @patch("os.chdir") - @patch("os.getcwd") - def test_check_logs(self, mock_os_cwd, mock_os_dir): - with patch("builtins.open", mock_open()) as o: - CalibrationLauncher("PPR.xml", "test.json").check_logs(parent_path=".") - o.call_count == 1 +import argparse +from unittest.mock import patch, MagicMock + +from casa_envoy.palaver import check_calibratable, check_imagable, _get_settings + +expected_settings = { + "useCasa": False, + "homeForReprocessing": "/home/casa/packages/pipeline/current", + "rootDirectory": "/lustre/aoc/cluster/pipeline/docker/workspaces/spool", + "processingDirectory": "tmpo1ca1pp_", +} +args = argparse.Namespace() def test_check_calibratable(): check = check_calibratable("test/test.json") - assert check == True + assert check is True + + +def test_check_imagable(): + check = check_imagable("test/image-metadata.json") + assert check is True + + +def test_get_settings(): + with patch( + "pathlib.Path.cwd", + MagicMock(return_value="/lustre/aoc/cluster/pipeline/docker/workspaces/spool/tmpo1ca1pp_"), + ) as cwd: + settings = _get_settings(cwd) + assert settings["useCasa"] == expected_settings["useCasa"] + assert settings["homeForReprocessing"] == expected_settings["homeForReprocessing"] diff --git a/apps/cli/executables/pexable/casa_envoy/test/test_launchers.py b/apps/cli/executables/pexable/casa_envoy/test/test_launchers.py new file mode 100644 index 000000000..dfe285a1c --- /dev/null +++ b/apps/cli/executables/pexable/casa_envoy/test/test_launchers.py @@ -0,0 +1,68 @@ +import os +from unittest.mock import mock_open, patch + +from casa_envoy.launchers import CalibrationLauncher, ImagingLauncher + + +class TestCalibrationLauncher: + @patch("subprocess.Popen") + @patch("os.chdir") + def test_run(self, mock_os, mock_subprocess): + CalibrationLauncher("test/PPR.xml", "test/test.json").run() + assert mock_subprocess.call_count == 1 + + def test_setup_environment(self): + parameters = { + "useCasa": False, + "homeForReprocessing": "/home/casa/packages/pipeline/current", + "rootDirectory": "/tmp/workspaces_tmp/", + "processingDirectory": "tmpiox5trbp", + } + CalibrationLauncher("PPR.xml", "test.json").setup_environment(parameters=parameters) + assert os.environ.get("SCIPIPE_ROOTDIR") == parameters["rootDirectory"] + assert os.environ.get("CASA_HOME") == parameters["homeForReprocessing"] + assert os.environ.get("PPR_FILENAME") == "PPR.xml" + + @patch("builtins.open") + @patch("glob.glob") + @patch("os.chdir") + @patch("os.getcwd") + def test_check_logs(self, mock_os_cwd, mock_os_dir, mock_glob, mock_open): + CalibrationLauncher("PPR.xml", "test.json").check_logs(parent_path=".") + assert mock_os_cwd.call_count == 1 + assert mock_os_dir.call_count == 0 + assert mock_glob.call_count == 1 + + +class TestImagingLauncher: + @patch("os.chdir") + def test_run(self, mock_os): + with patch("subprocess.Popen") as sp: + ImagingLauncher("test/cmsimage-PPR.xml", "test/image-metadata.json").run() + assert sp.call_count == 1 + + def test_setup_environment(self): + parameters = { + "useCasa": False, + "homeForReprocessing": "/home/casa/packages/pipeline/current", + "rootDirectory": "/tmp/workspaces_tmp/", + "processingDirectory": "tmpiox5trbp", + } + ppr = "cmsimage-PPR.xml" + metadata = "image-metadata.json" + ImagingLauncher(ppr, metadata).setup_environment(parameters=parameters) + assert os.environ.get("SCIPIPE_ROOTDIR") == parameters["rootDirectory"] + assert os.environ.get("CASA_HOME") == parameters["homeForReprocessing"] + assert os.environ.get("PPR_FILENAME") == ppr + + @patch("builtins.open") + @patch("glob.glob") + @patch("os.chdir") + @patch("os.getcwd") + def test_check_logs(self, mock_os_cwd, mock_os_dir, mock_glob, mock_open): + ppr = "cmsimage-PPR.xml" + metadata = "image-metadata.json" + ImagingLauncher(ppr, metadata).check_logs(parent_path=".") + assert mock_os_cwd.call_count == 1 + assert mock_os_dir.call_count == 0 + assert mock_glob.call_count == 1 diff --git a/apps/cli/executables/pexable/vela/test/cmsimage-PPR.xml b/apps/cli/executables/pexable/vela/test/cmsimage-PPR.xml new file mode 100644 index 000000000..41493f3ed --- /dev/null +++ b/apps/cli/executables/pexable/vela/test/cmsimage-PPR.xml @@ -0,0 +1,92 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<ns2:SciPipeRequest xmlns:ns2="Common/pipelinescience/SciPipeRequest"> + <ProjectSummary> + <ProposalCode>VLA/null</ProposalCode> + <Observatory>NRAO</Observatory> + <Telescope>VLA</Telescope> + <ProcessingSite>Socorro</ProcessingSite> + <Operator>vlapipe</Operator> + <Mode>SCIENCE</Mode> + <Version>NGRH-ALMA-10_8</Version> + <CreationTime>2021-07-01T21:14:00</CreationTime> + </ProjectSummary> + <ProjectStructure>TBD</ProjectStructure> + <ProcessingRequests> + <RootDirectory>/lustre/aoc/cluster/pipeline/docker/workspaces/spool</RootDirectory> + <ProcessingRequest> + <ProcessingIntents> + <Intents> + <Keyword>VLA_INTERFEROMETRY_STANDARD_OBSERVING_MODE</Keyword> + <Value>Undefined</Value> + </Intents> + </ProcessingIntents> + <ProcessingProcedure> + <ProcedureTitle>hifv_contimage</ProcedureTitle> + <ProcessingCommand> + <Command xmlns="">hifv_importdata</Command> + <ParameterSet> + </ParameterSet> + </ProcessingCommand> + <ProcessingCommand> + <Command xmlns="">hif_mstransform</Command> + <ParameterSet> + </ParameterSet> + </ProcessingCommand> + <ProcessingCommand> + <Command xmlns="">hif_checkproductsize</Command> + <ParameterSet> + <Parameter> + <Keyword xmlns="">maximsize</Keyword> + <Value xmlns="">16384</Value> + </Parameter> + </ParameterSet> + </ProcessingCommand> + <ProcessingCommand> + <Command xmlns="">hif_makeimlist</Command> + <ParameterSet> + <Parameter> + <Keyword xmlns="">specmode</Keyword> + <Value xmlns="">cont</Value> + </Parameter> + </ParameterSet> + </ProcessingCommand> + <ProcessingCommand> + <Command xmlns="">hif_makeimages</Command> + <ParameterSet> + <Parameter> + <Keyword xmlns="">hm_masking</Keyword> + <Value xmlns="">none</Value> + </Parameter> + <Parameter> + <Keyword xmlns="">hm_cyclefactor</Keyword> + <Value xmlns="">3.0</Value> + </Parameter> + </ParameterSet> + </ProcessingCommand> + <ProcessingCommand> + <Command xmlns="">hifv_exportdata</Command> + <ParameterSet> + <Parameter> + <Keyword xmlns="">imaging_products_only</Keyword> + <Value xmlns="">True</Value> + </Parameter> + </ParameterSet> + </ProcessingCommand> + </ProcessingProcedure> + <DataSet> + <RelativePath>tmpo1ca1pp_</RelativePath> + <SdmIdentifier>brain_000.58099.67095825232.ms</SdmIdentifier> + <DataType>asdm</DataType> + </DataSet> + </ProcessingRequest>0 + </ProcessingRequests> + <ResultsProcessing> + <ArchiveResults>false</ArchiveResults> + <CleanUpDisk>false</CleanUpDisk> + <UpdateProjectLifeCycle>false</UpdateProjectLifeCycle> + <NotifyOperatorWhenDone>false</NotifyOperatorWhenDone> + <SDMall>false</SDMall> + <SDMonly>false</SDMonly> + <PipelineOperatorAddress>Unknown</PipelineOperatorAddress> + </ResultsProcessing> +</ns2:SciPipeRequest> diff --git a/apps/cli/executables/pexable/vela/test/image-metadata.json b/apps/cli/executables/pexable/vela/test/image-metadata.json new file mode 100644 index 000000000..e2b19ffab --- /dev/null +++ b/apps/cli/executables/pexable/vela/test/image-metadata.json @@ -0,0 +1,15 @@ +{ + "fileSetIds": "brain_000.58099.67095825232", + "workflowName": "std_cms_imaging", + "systemId": "4", + "productLocator": "uid://evla/execblock/ec082e65-452d-4fec-ad88-f5b4af1f9e36", + "projectMetadata": { + "projectCode": "Operations", + "title": "", + "startTime": "58099.6710792824", + "observer": "VLA Operations" + }, + "destinationDirectory": "/lustre/aoc/cluster/pipeline/docker/workspaces/spool/tmpo1ca1pp_", + "calibrationSourceDirectory":"/lustre/aoc/cluster/pipeline/docker/workspaces/spool/tmpowrvygml/working", + "cmsName":"brain_000.58099.67095825232.ms" +} diff --git a/apps/cli/executables/pexable/vela/test/test_emulators.py b/apps/cli/executables/pexable/vela/test/test_emulators.py new file mode 100644 index 000000000..dff110af9 --- /dev/null +++ b/apps/cli/executables/pexable/vela/test/test_emulators.py @@ -0,0 +1,72 @@ +""" +Tests for vela.emulators +""" +import os +from unittest.mock import patch, mock_open + +import pytest + +from vela.emulators import CalibrationEmulator, ImagingEmulator +from vela.forger import forge + + +class TestCalibrationEmulator: + @pytest.mark.skip("Ignores forger mock.") + @patch("os.chdir") + @patch("vela.forger.VelaProduct.forge_products") + @patch("vela.forger.VelaLog.forge_logs") + def test_run(self, mock_logs, mock_products, mock_os): + with patch("vela.forger.forge") as mock_forge: + CalibrationEmulator("test/test.json", "test/PPR.xml").run() + assert mock_forge.call_count == 1 + + def test_setup_environment(self): + parameters = { + "useCasa": False, + "homeForReprocessing": "/home/casa/packages/pipeline/current", + "rootDirectory": "/tmp/workspaces_tmp/", + } + CalibrationEmulator("test.json", "PPR.xml").setup_environment(parameters=parameters) + assert os.environ.get("SCIPIPE_ROOTDIR") == parameters["rootDirectory"] + assert os.environ.get("CASA_HOME") == parameters["homeForReprocessing"] + assert os.environ.get("PPR_FILENAME") == "PPR.xml" + + @patch("glob.glob") + @patch("os.chdir") + def test_check_logs(self, mock_os, mock_glob): + with patch("builtins.open", mock_open()) as o: + CalibrationEmulator("test.json", "PPR.xml").check_logs(parent_path=mock_os) + assert o.call_count == 0 + assert mock_os.call_count == 1 + assert mock_glob.call_count == 1 + + +class TestImagingEmulator: + @pytest.mark.skip("Ignores forger mock.") + @patch("os.chdir") + @patch("vela.forger.VelaProduct.forge_products") + @patch("vela.forger.VelaLog.forge_logs") + def test_run(self, mock_logs, mock_products, mock_os): + with patch("vela.forger.forge") as mock_forge: + ImagingEmulator("test/test.json", "test/PPR.xml").run() + assert mock_forge.call_count == 1 + + def test_setup_environment(self): + parameters = { + "useCasa": False, + "homeForReprocessing": "/home/casa/packages/pipeline/current", + "rootDirectory": "/tmp/workspaces_tmp/", + } + ImagingEmulator("test.json", "PPR.xml").setup_environment(parameters=parameters) + assert os.environ.get("SCIPIPE_ROOTDIR") == parameters["rootDirectory"] + assert os.environ.get("CASA_HOME") == parameters["homeForReprocessing"] + assert os.environ.get("PPR_FILENAME") == "PPR.xml" + + @patch("glob.glob") + @patch("os.chdir") + def test_check_logs(self, mock_os, mock_glob): + with patch("builtins.open", mock_open()) as o: + ImagingEmulator("test.json", "PPR.xml").check_logs(parent_path=mock_os) + assert o.call_count == 0 + assert mock_os.call_count == 1 + assert mock_glob.call_count == 1 diff --git a/apps/cli/executables/pexable/vela/test/test_forger.py b/apps/cli/executables/pexable/vela/test/test_forger.py index 7656f4710..d9e38c6d8 100644 --- a/apps/cli/executables/pexable/vela/test/test_forger.py +++ b/apps/cli/executables/pexable/vela/test/test_forger.py @@ -6,28 +6,71 @@ from vela.forger import read_metadata, VelaProduct, VelaLog class TestVelaLog: + def test_forge_logs(self): + parameters_cal = read_metadata("test/test.json") + with patch("vela.forger.VelaLog.cal_logs") as cal_logs: + VelaLog("test.json").forge_logs(parameters=parameters_cal) + assert cal_logs.call_count == 1 + + parameters_img = read_metadata("test/image-metadata.json") + with patch("vela.forger.VelaLog.img_logs") as img_logs: + VelaLog("image-metadata.json").forge_logs(parameters=parameters_img) + assert img_logs.call_count == 1 + @patch("os.chdir") @patch("pendulum.now") - def test_forge_logs(self, mock_pendulum, mock_os): - parameters = read_metadata("test/test.json") + def test_cal_logs(self, mock_pendulum, mock_os): with patch("builtins.open", mock_open()) as o: - VelaLog("test.json").forge_logs(parameters=parameters) - o.call_count == 3 + VelaLog("test.json").cal_logs() + assert o.call_count == 3 handle = o() - handle.write.call_count == 3 + assert handle.write.call_count == 3 + + @patch("os.chdir") + @patch("pendulum.now") + def test_img_logs(self, mock_pendulum, mock_os): + with patch("builtins.open", mock_open()) as o: + VelaLog("image-metadata.json").img_logs() + assert o.call_count == 3 + handle = o() + assert handle.write.call_count == 3 class TestVelaProduct: + def test_forge_products(self): + parameters_cal = read_metadata("test/test.json") + with patch("vela.forger.VelaProduct.cal_products") as cal_products: + VelaProduct("test.json").forge_products(parameters=parameters_cal) + assert cal_products.call_count == 1 + + parameters_img = read_metadata("test/image-metadata.json") + with patch("vela.forger.VelaProduct.img_products") as img_products: + VelaProduct("image-metadata.json").forge_products(parameters=parameters_img) + assert img_products.call_count == 1 + @patch("os.chdir") @patch("vela.forger.VelaProduct.forge_weblog") - def test_forge_cal_products(self, mock_forge, mock_os): + @patch("vela.forger.VelaProduct.forge_measurement_set") + def test_cal_products(self, mock_ms, mock_forge, mock_os): parameters = read_metadata("test/test.json") with patch("builtins.open", mock_open()) as o: - VelaProduct("test.json").forge_cal_products(parameters=parameters) + VelaProduct("test.json").cal_products(parameters=parameters) o.assert_called_once_with("brain_001.58099.678886747686.ms.calapply.txt", "x") handle = o() handle.write.assert_called_once_with("I am a calibration file.") + @patch("os.mkdir") + @patch("os.chdir") + def test_forge_measurement_set(self, mock_chdir, mock_mkdir): + with patch("builtins.open", mock_open()) as o: + VelaProduct("test.json").forge_measurement_set(sdmId="brain_001.58099.678886747686") + assert o.call_count == 5 + handle = o() + assert handle.write.call_count == 5 + + assert mock_mkdir.call_count == 6 + assert mock_chdir.call_count == 2 + @patch("os.mkdir") @patch("os.chdir") @patch("pendulum.now") @@ -35,9 +78,9 @@ class TestVelaProduct: def test_forge_weblog(self, mock_tar, mock_pendulum, mock_os_chdir, mock_os_mkdir): with patch("builtins.open", mock_open()) as o: VelaProduct("test.json").forge_weblog(path="/tmp/workspaces_tmp/testing") - o.call_count == 3 + assert o.call_count == 3 handle = o() - handle.write.call_count == 3 + assert handle.write.call_count == 3 def test_read_metadata(): @@ -45,10 +88,11 @@ def test_read_metadata(): assert parameters["fileSetIds"] == "brain_001.58099.678886747686" assert parameters["workflowName"] == "std_calibration" assert parameters["systemId"] == "5" - assert parameters["productLocator"] == "uid://evla/execblock/9cb0964b-ad6b-40ed-bd87-d08c502503e2" + assert ( + parameters["productLocator"] == "uid://evla/execblock/9cb0964b-ad6b-40ed-bd87-d08c502503e2" + ) project = parameters.get("projectMetadata") assert project["projectCode"] == "Operations" assert project["title"] == "" assert project["startTime"] == "58099.6790081019" assert project["observer"] == "VLA Operations" - diff --git a/apps/cli/executables/pexable/vela/test/test_vela.py b/apps/cli/executables/pexable/vela/test/test_vela.py index 6b914d774..4324a2997 100644 --- a/apps/cli/executables/pexable/vela/test/test_vela.py +++ b/apps/cli/executables/pexable/vela/test/test_vela.py @@ -1,32 +1,56 @@ """ Tests for Vela """ -import os -from unittest.mock import patch, mock_open +import argparse +from unittest.mock import patch, MagicMock -from vela.quasar import CalibrationEmulator +import vela.quasar as quasar +expected_settings = { + "useCasa": False, + "homeForReprocessing": "/home/casa/packages/pipeline/current", + "rootDirectory": "/lustre/aoc/cluster/pipeline/docker/workspaces/spool", + "processingDirectory": "tmpabcd1234", +} +args = argparse.Namespace() + + +class TestQuasar: + def test_get_settings(self): + with patch( + "pathlib.Path.cwd", + MagicMock( + return_value="/lustre/aoc/cluster/pipeline/docker/workspaces/spool/tmpabcd1234" + ), + ) as cwd: + settings = quasar._get_settings(cwd) + assert settings["useCasa"] == expected_settings["useCasa"] + assert settings["homeForReprocessing"] == expected_settings["homeForReprocessing"] -class TestCalibrationEmulator: @patch("os.chdir") - @patch("vela.forger.VelaProduct.forge_cal_products") - @patch("vela.forger.VelaLog.forge_logs") - def test_run(self, mock_logs, mock_products, mock_os): - with patch("vela.forger.forge") as forge: - CalibrationEmulator("test/test.json", "test/PPR.xml").run() - forge.call_count == 1 - - def test_setup_environment(self): - parameters = {"useCasa": False, - "homeForReprocessing": "/home/casa/packages/pipeline/current", - "rootDirectory": "/tmp/workspaces_tmp/"} - CalibrationEmulator("test.json", "PPR.xml").setup_environment(parameters=parameters) - assert os.environ.get('SCIPIPE_ROOTDIR') == parameters["rootDirectory"] - assert os.environ.get('CASA_HOME') == parameters["homeForReprocessing"] - assert os.environ.get('PPR_FILENAME') == "PPR.xml" + @patch("pathlib.Path") + @patch("os.getcwd") + def test_main_stdcal(self, mock_cwd, mock_path, mock_chdir): + args.standard_cal = ["test/test.json", "test/PPR.xml"] + + with patch("argparse.ArgumentParser.parse_args", MagicMock(return_value=args)) as mock_args: + with patch("vela.emulators.CalibrationEmulator.run") as run: + quasar.main() + assert run.call_count == 1 + + # reset for testing + args.standard_cal = None @patch("os.chdir") - def test_check_logs(self, mock_os): - with patch("builtins.open", mock_open()) as o: - CalibrationEmulator("test.json", "PPR.xml").check_logs(parent_path=mock_os) - o.call_count == 1 + @patch("pathlib.Path") + @patch("os.getcwd") + def test_main_stdimg(self, mock_cwd, mock_path, mock_chdir): + args.standard_img = ["test/image-metadata.json", "test/cmsimage-PPR.xml"] + + with patch("argparse.ArgumentParser.parse_args", MagicMock(return_value=args)) as mock_args: + with patch("vela.emulators.ImagingEmulator.run") as run: + quasar.main() + assert run.call_count == 1 + + # reset for testing + args.standard_img = None diff --git a/apps/cli/executables/pexable/vela/vela/emulators.py b/apps/cli/executables/pexable/vela/vela/emulators.py new file mode 100644 index 000000000..faa97bd11 --- /dev/null +++ b/apps/cli/executables/pexable/vela/vela/emulators.py @@ -0,0 +1,98 @@ +import glob +import logging +import os +import re +import sys + +from vela.forger import forge +from vela.interfaces import CasaEmulatorIF + + +""" +Emulate a CASA run +""" + + +def get_base_environment(parameters: dict): + os.environ["SCIPIPE_ROOTDIR"] = parameters["rootDirectory"] + os.environ["CASA_HOME"] = parameters["homeForReprocessing"] + os.environ["LANG"] = "en_US.UTF-8" + + +def check_processing_env(logger: logging.Logger): + logger.info("Checking processing environment:") + env1 = os.environ.get("SCIPIPE_ROOTDIR") + logger.info(f"SCIPIPE_ROOTDIR: {env1}") + env2 = os.environ.get("CASA_HOME") + logger.info(f"CASA_HOME: {env2}") + env3 = os.environ.get("PPR_FILENAME") + logger.info(f"PPR_FILENAME: {env3}") + env4 = os.environ.get("LANG") + logger.info(f"LANG: {env4}") + if "None" in [env1, env2, env3, env4]: + logger.info("Environment setup Failed!") + sys.exit(1) + else: + logger.info("Environment ready for processing") + + +class CalibrationEmulator(CasaEmulatorIF): + def __init__(self, metadata: str, ppr: str): + self.logger = logging.getLogger("vela") + self.ppr = ppr + self.metadata = metadata + + def run(self): + self.logger.info("Vela waiting on the Forger....") + forge(self.metadata) + + def setup_environment(self, parameters: dict): + get_base_environment(parameters) + os.environ["PPR_FILENAME"] = str(self.ppr) + + check_processing_env(self.logger) + + def check_logs(self, parent_path: str): + self.logger.info("CHECKING VELA LOGS!") + + if not os.getcwd().endswith("/working"): + os.chdir(parent_path + "/working") + + vela_logs = glob.glob("vela-*.log") + + for file in vela_logs: + if re.match("^.*SEVERE\sflagmanager.*$", open(file).read()): + self.logger.info("VELA ERROR! Please inspect logs.") + else: + self.logger.info("VELA Success!") + + +class ImagingEmulator(CasaEmulatorIF): + def __init__(self, metadata: str, ppr: str): + self.logger = logging.getLogger("vela") + self.metadata = metadata + self.ppr = ppr + + def run(self): + self.logger.info("Vela waiting on the Forger....") + forge(self.metadata) + + def setup_environment(self, parameters: dict): + get_base_environment(parameters) + os.environ["PPR_FILENAME"] = str(self.ppr) + + check_processing_env(self.logger) + + def check_logs(self, parent_path: str): + self.logger.info("CHECKING VELA LOGS!") + + if not os.getcwd().endswith("/working"): + os.chdir(parent_path + "/working") + + vela_logs = glob.glob("vela-*.log") + + for file in vela_logs: + if re.match("^.*SEVERE\sflagmanager.*$", open(file).read()): + self.logger.info("VELA ERROR! Please inspect logs.") + else: + self.logger.info("VELA Success!") diff --git a/apps/cli/executables/pexable/vela/vela/forger.py b/apps/cli/executables/pexable/vela/vela/forger.py index 6a551f5e9..f921318b5 100644 --- a/apps/cli/executables/pexable/vela/vela/forger.py +++ b/apps/cli/executables/pexable/vela/vela/forger.py @@ -23,6 +23,14 @@ class VelaLog: # vela-pipeline.sh.err.txt # vela-<date_as_string>-<timestring>.log + workflow_name = parameters["workflowName"] + + if "calibration" in workflow_name: + self.cal_logs() + elif "imaging" in workflow_name: + self.img_logs() + + def cal_logs(self): path = Path.cwd() / "working" os.chdir(path) @@ -35,7 +43,7 @@ class VelaLog: pipe_err.write(forged_content()) pipe_err.close() - datestring = pendulum.now().format('YYYYMMDD') + datestring = pendulum.now().format("YYYYMMDD") timestring = pendulum.now().utcnow().format("hhmmss") log = open(f"vela-{datestring}-{timestring}.log", "w") @@ -45,13 +53,25 @@ class VelaLog: self.logger.info("Logs forging complete.") os.chdir("../") + def img_logs(self): + # TODO: find out if logs are different for imaging + self.cal_logs() + class VelaProduct: def __init__(self, metadata: str): self.logger = logging.getLogger("vela") self.metadata = metadata - def forge_cal_products(self, parameters: dict): + def forge_products(self, parameters: dict): + workflow_name = parameters["workflowName"] + + if "calibration" in workflow_name: + self.cal_products(parameters) + elif "imaging" in workflow_name: + self.img_products(parameters) + + def cal_products(self, parameters: dict): # forge products so there is something to test delivery with path = Path.cwd() / "products" @@ -65,16 +85,37 @@ class VelaProduct: calapply.close() os.chdir("../working") + self.forge_measurement_set(sdm_id) self.forge_weblog(os.getcwd()) self.logger.info("Forging products complete.") os.chdir("../") + def img_products(self, parameters: dict): + # TODO: find out products to forge + self.forge_measurement_set(parameters["fileSetIds"]) + + def forge_measurement_set(self, sdmId: str): + self.logger.info("Forging Measurement Set....") + cms_name = sdmId + ".ms" + os.mkdir(cms_name) + os.chdir("./" + cms_name) + + for i in range(0, 5): + dirname = f"FORGED_MS_DIR_{i}" + os.mkdir(dirname) + file = open(f"table.f{i}", "x") + file.write("I am a table.") + file.close() + + os.chdir("../") + self.logger.info("MS forging complete.") + def forge_weblog(self, path): self.logger.info("Forging weblog...") - datestring = pendulum.now().format('YYYYMMDD') - timestring = pendulum.now().utcnow().format('hhmmss') + datestring = pendulum.now().format("YYYYMMDD") + timestring = pendulum.now().utcnow().format("hhmmss") dirname = f"pipeline-{datestring}-{timestring}" os.mkdir(dirname) os.chdir(path + "/" + dirname) @@ -118,4 +159,4 @@ def forge(metadata: str): fake_logs.forge_logs(parameters) fake_products = VelaProduct(metadata) - fake_products.forge_cal_products(parameters) + fake_products.forge_products(parameters) diff --git a/apps/cli/executables/pexable/vela/vela/interfaces.py b/apps/cli/executables/pexable/vela/vela/interfaces.py index 184662fb4..c16891725 100644 --- a/apps/cli/executables/pexable/vela/vela/interfaces.py +++ b/apps/cli/executables/pexable/vela/vela/interfaces.py @@ -9,11 +9,12 @@ class CasaEmulatorIF(ABC): Generic CASA Emulator methods for Vela. Should be implemented for any type of CASA emulated processing. """ + def run(self): raise NotImplementedError def setup_environment(self, parameters: dict): raise NotImplementedError - def check_logs(self): + def check_logs(self, parent_path: str): raise NotImplementedError diff --git a/apps/cli/executables/pexable/vela/vela/quasar.py b/apps/cli/executables/pexable/vela/vela/quasar.py index 9732ef0dd..76a5316ee 100644 --- a/apps/cli/executables/pexable/vela/vela/quasar.py +++ b/apps/cli/executables/pexable/vela/vela/quasar.py @@ -8,13 +8,10 @@ import os import pathlib import sys -import glob -import re - from pycapo import CapoConfig -from .interfaces import CasaEmulatorIF -from .forger import forge +from vela.emulators import CalibrationEmulator +from vela.emulators import ImagingEmulator """ The Vela system allows for testing Workspaces workflows without submitting to CASA on the cluster. @@ -25,54 +22,11 @@ logger.setLevel(logging.INFO) logger.addHandler(logging.StreamHandler(sys.stdout)) -class CalibrationEmulator(CasaEmulatorIF): - def __init__(self, metadata: str, ppr: str): - self.ppr = ppr - self.metadata = metadata - - def run(self): - logger.info("Vela waiting on the Forger....") - forge(self.metadata) - - def setup_environment(self, parameters: dict): - os.environ['SCIPIPE_ROOTDIR'] = parameters["rootDirectory"] - os.environ['CASA_HOME'] = parameters["homeForReprocessing"] - os.environ['PPR_FILENAME'] = str(self.ppr) - os.environ['LANG'] = "en_US.UTF-8" - - logger.info("Checking processing environment:") - env1 = os.environ.get('SCIPIPE_ROOTDIR') - logger.info(f"SCIPIPE_ROOTDIR: {env1}") - env2 = os.environ.get('CASA_HOME') - logger.info(f"CASA_HOME: {env2}") - env3 = os.environ.get('PPR_FILENAME') - logger.info(f"PPR_FILENAME: {env3}") - env4 = os.environ.get('LANG') - logger.info(f"LANG: {env4}") - if 'None' in [env1, env2, env3, env4]: - logger.info("Environment setup Failed!") - sys.exit(1) - else: - logger.info("Environment ready for processing") - - def check_logs(self, parent_path: str): - logger.info("CHECKING VELA LOGS!") - - if not os.getcwd().endswith("/working"): - os.chdir(parent_path + "/working") - - vela_logs = glob.glob('vela-*.log') - - for file in vela_logs: - if re.match("^.*SEVERE\sflagmanager.*$", open(file).read()): - logger.info("VELA ERROR! Please inspect logs.") - else: - logger.info("VELA Success!") - - def _get_settings(cwd: pathlib.Path): use_casa = CapoConfig().getboolean("edu.nrao.archive.workspaces.ProcessingSettings.useCasa") - casa_home = CapoConfig().settings("edu.nrao.archive.workflow.config.CasaVersions").homeForReprocessing + casa_home = ( + CapoConfig().settings("edu.nrao.archive.workflow.config.CasaVersions").homeForReprocessing + ) root_dir = str(cwd.parent) processing_dir = str(cwd.stem) @@ -81,44 +35,49 @@ def _get_settings(cwd: pathlib.Path): "useCasa": use_casa, "homeForReprocessing": casa_home, "rootDirectory": root_dir, - "processingDirectory": processing_dir + "processingDirectory": processing_dir, } def parser() -> argparse.ArgumentParser: arg_parser = argparse.ArgumentParser( description="Workspaces VELA processing launcher", - formatter_class=argparse.RawTextHelpFormatter + formatter_class=argparse.RawTextHelpFormatter, ) arg_parser.add_argument( "--standard-cal", nargs=2, action="store", required=False, - help="run the standard calibration pipeline" + help="run the standard calibration pipeline", ) arg_parser.add_argument( - "--standard-image", + "--standard-img", nargs=2, action="store", required=False, - help="run the standard imaging pipeline" + help="run the standard imaging pipeline", ) return arg_parser def main(): args = parser().parse_args() - metadata = args.standard_cal[0] - ppr = args.standard_cal[1] path = os.getcwd() settings = _get_settings(pathlib.Path(path)) - if args.standard_cal: + if args.standard_cal is not None: + metadata = args.standard_cal[0] + ppr = args.standard_cal[1] emulator = CalibrationEmulator(metadata, ppr) - emulator.setup_environment(settings) - emulator.run() - emulator.check_logs(parent_path=path) - os.chdir(path) + elif args.standard_img is not None: + metadata = args.standard_img[0] + ppr = args.standard_img[1] + emulator = ImagingEmulator(metadata, ppr) else: logger.info("ARGUMENT ERROR: no valid argument was provided.") + + emulator.setup_environment(settings) + emulator.run() + emulator.check_logs(parent_path=path) + os.chdir(path) diff --git a/shared/workspaces/workspaces/workflow/services/workflow_service.py b/shared/workspaces/workspaces/workflow/services/workflow_service.py index 769e2fb6a..edf468b2c 100644 --- a/shared/workspaces/workspaces/workflow/services/workflow_service.py +++ b/shared/workspaces/workspaces/workflow/services/workflow_service.py @@ -173,6 +173,9 @@ class WorkflowService(WorkflowServiceIF): # render all the templates if request.argument["need_project_metadata"] is True: templated_files = self._render_with_metadata(request, temp_folder, definition) + # catch aat_wrest failure and abort workflow + if isinstance(templated_files, WorkflowRequest): + return request else: templated_files = definition.render_templates(request.argument) -- GitLab