Beispiel #1
0
    def __init__(self, args=None, pool=None):

        if args is None:
            args = sys.argv[1:]
        if isinstance(args, str):
            args = args.split(' ')

        parser = argparse.ArgumentParser(
            description='Generate Assocation Data Products',
            usage='asn_generate pool'
        )
        if pool is None:
            parser.add_argument(
                'pool', type=str, help='Association Pool'
            )
        op_group = parser.add_mutually_exclusive_group()
        op_group.add_argument(
            '-i', '--ids', nargs='+',
            dest='asn_candidate_ids',
            help='space-separated list of association candidate IDs to operate on.'
        )
        op_group.add_argument(
            '--discover',
            action='store_true',
            help='Produce discovered associations'
        )
        op_group.add_argument(
            '--all-candidates',
            action='store_true', dest='all_candidates',
            help='Produce all association candidate-specific associations'
        )
        parser.add_argument(
            '-p', '--path', type=str,
            default='.',
            help='Folder to save the associations to. Default: "%(default)s"'
        )
        parser.add_argument(
            '--save-orphans', dest='save_orphans',
            nargs='?', const='orphaned.csv', default=False,
            help='Save orphaned items into the specified table. Default: "%(default)s"'
        )
        parser.add_argument(
            '--version-id', dest='version_id',
            nargs='?', const=True, default=None,
            help=(
                'Version tag to add into association name and products.'
                ' If not specified, no version will be used.'
                ' If specified without a value, the current time is used.'
                ' Otherwise, the specified string will be used.'
            )
        )
        parser.add_argument(
            '-r', '--rules', action='append',
            help='Association Rules file.'
        )
        parser.add_argument(
            '--ignore-default', action='store_true',
            help='Do not include default rules. -r should be used if set.'
        )
        parser.add_argument(
            '--dry-run',
            action='store_true', dest='dry_run',
            help='Execute but do not save results.'
        )
        parser.add_argument(
            '-d', '--delimiter', type=str,
            default='|',
            help='''Delimiter
            to use if pool files are comma-separated-value
            (csv) type files. Default: "%(default)s"
            '''
        )
        parser.add_argument(
            '--pool-format', type=str,
            default='ascii',
            help=(
                'Format of the pool file.'
                ' Any format allowed by the astropy'
                ' Unified File I/O interface is allowed.'
                ' Default: "%(default)s"'
            )
        )
        parser.add_argument(
            '-v', '--verbose',
            action='store_const', dest='loglevel',
            const=logging.INFO, default=logging.NOTSET,
            help='Output progress and results.'
        )
        parser.add_argument(
            '-D', '--debug',
            action='store_const', dest='loglevel',
            const=logging.DEBUG,
            help='Output detailed debugging information.'
        )
        parser.add_argument(
            '--DMS',
            action='store_true', dest='DMS_enabled',
            help='Running under DMS workflow conditions.'
        )
        parser.add_argument(
            '--format',
            default='json',
            help='Format of the association files. Default: "%(default)s"'
        )
        parser.add_argument(
            '--version', action='version',
            version='%(prog)s {}'.format(__version__),
            help='Version of the generator.'
        )
        parser.add_argument(
            '--no-merge', action='store_true',
            help='Do not merge Level2 associations into one'
        )

        parsed = parser.parse_args(args=args)

        # Configure logging
        config = None
        if parsed.DMS_enabled:
            config = DMS_config
        logger = log_config(name=__package__, config=config)
        logger.setLevel(parsed.loglevel)

        # Preamble
        logger.info('Command-line arguments: {}'.format(args))
        logger.context.set('asn_candidate_ids', parsed.asn_candidate_ids)

        if pool is None:
            logger.info('Reading pool {}'.format(parsed.pool))
            self.pool = AssociationPool.read(
                parsed.pool, delimiter=parsed.delimiter,
                format=parsed.pool_format,
            )
        else:
            self.pool = pool

        # DMS: Add further info to logging.
        try:
            logger.context.set('program', self.pool[0]['PROGRAM'])
        except KeyError:
            pass

        # Determine mode of operation. Options are
        #  1) Only specified candidates
        #  2) Only discovered assocations that do not match
        #     candidate associations
        #  3) Both discovered and all candidate associations.
        logger.info('Reading rules.')
        if not parsed.discover and\
           not parsed.all_candidates and\
           parsed.asn_candidate_ids is None:
            parsed.discover = True
            parsed.all_candidates = True
        if parsed.discover or parsed.all_candidates:
            global_constraints = constrain_on_candidates(
                None
            )
        elif parsed.asn_candidate_ids is not None:
            global_constraints = constrain_on_candidates(
                parsed.asn_candidate_ids
            )

        self.rules = AssociationRegistry(
            parsed.rules,
            include_default=not parsed.ignore_default,
            global_constraints=global_constraints,
            name=CANDIDATE_RULESET
        )

        if parsed.discover:
            self.rules.update(
                AssociationRegistry(
                    parsed.rules,
                    include_default=not parsed.ignore_default,
                    name=DISCOVER_RULESET
                )
            )

        logger.info('Generating associations.')
        self.associations = generate(
            self.pool, self.rules, version_id=parsed.version_id
        )

        if parsed.discover:
            logger.debug(
                '# asns found before discover filtering={}'.format(
                    len(self.associations)
                )
            )
            self.associations = filter_discovered_only(
                self.associations,
                DISCOVER_RULESET,
                CANDIDATE_RULESET,
                keep_candidates=parsed.all_candidates,
            )
            self.rules.Utility.resequence(self.associations)

        # Do a grand merging. This is done particularly for
        # Level2 associations.
        if not parsed.no_merge:
            try:
                self.associations = self.rules.Utility.merge_asns(self.associations)
            except AttributeError:
                pass

        logger.info(self.__str__())

        if not parsed.dry_run:
            self.save(
                path=parsed.path,
                format=parsed.format,
                save_orphans=parsed.save_orphans
            )
Beispiel #2
0
from jwst.associations import (
    __version__,
    AssociationPool,
    AssociationRegistry,
    generate,
)
from jwst.associations.lib.dms_base import DMSAttrConstraint
from jwst.associations.lib.constraint import (
    ConstraintTrue,
)
from jwst.associations.lib.log_config import (log_config, DMS_config)

__all__ = ['Main']

# Configure logging
logger = log_config(name=__package__)

# Ruleset names
DISCOVER_RULESET = 'discover'
CANDIDATE_RULESET = 'candidate'


class Main():
    """
    Generate Associations from an Association Pool

    Parameters
    ----------
    args: [str, ...], or None
        The command line arguments. Can be one of
            - `None`: `sys.argv` is then used.
Beispiel #3
0
import numpy as np

from jwst.associations import (
    __version__,
    AssociationPool,
    AssociationRegistry,
    generate,
)
from jwst.associations.lib.dms_base import DMSAttrConstraint
from jwst.associations.lib.constraint import (
    ConstraintTrue, )
from jwst.associations.lib.log_config import (log_config, DMS_config)

# Configure logging
logger = log_config(name=__package__)

# Ruleset names
DISCOVER_RULESET = 'discover'
CANDIDATE_RULESET = 'candidate'


class Main():
    """
    Generate Associations from an Association Pool

    Parameters
    ----------
    args: [str, ...], or None
        The command line arguments. Can be one of
            - `None`: `sys.argv` is then used.
Beispiel #4
0
    def __init__(self, args=None, pool=None):

        if args is None:
            args = sys.argv[1:]
        if isinstance(args, str):
            args = args.split(' ')

        parser = argparse.ArgumentParser(
            description='Generate Assocation Data Products',
            usage='asn_generate pool')
        if pool is None:
            parser.add_argument('pool', type=str, help='Association Pool')
        op_group = parser.add_mutually_exclusive_group()
        op_group.add_argument(
            '-i',
            '--ids',
            nargs='+',
            dest='asn_candidate_ids',
            help=
            'space-separated list of association candidate IDs to operate on.')
        op_group.add_argument('--discover',
                              action='store_true',
                              help='Produce discovered associations')
        op_group.add_argument(
            '--all-candidates',
            action='store_true',
            dest='all_candidates',
            help='Produce all association candidate-specific associations')
        parser.add_argument(
            '-p',
            '--path',
            type=str,
            default='.',
            help='Folder to save the associations to. Default: "%(default)s"')
        parser.add_argument(
            '--save-orphans',
            dest='save_orphans',
            nargs='?',
            const='orphaned.csv',
            default=False,
            help=
            'Save orphaned items into the specified table. Default: "%(default)s"'
        )
        parser.add_argument(
            '--version-id',
            dest='version_id',
            nargs='?',
            const=True,
            default=None,
            help=('Version tag to add into association name and products.'
                  ' If not specified, no version will be used.'
                  ' If specified without a value, the current time is used.'
                  ' Otherwise, the specified string will be used.'))
        parser.add_argument('-r',
                            '--rules',
                            action='append',
                            help='Association Rules file.')
        parser.add_argument(
            '--ignore-default',
            action='store_true',
            help='Do not include default rules. -r should be used if set.')
        parser.add_argument('--dry-run',
                            action='store_true',
                            dest='dry_run',
                            help='Execute but do not save results.')
        parser.add_argument('-d',
                            '--delimiter',
                            type=str,
                            default='|',
                            help='''Delimiter
            to use if pool files are comma-separated-value
            (csv) type files. Default: "%(default)s"
            ''')
        parser.add_argument('--pool-format',
                            type=str,
                            default='ascii',
                            help=('Format of the pool file.'
                                  ' Any format allowed by the astropy'
                                  ' Unified File I/O interface is allowed.'
                                  ' Default: "%(default)s"'))
        parser.add_argument('-v',
                            '--verbose',
                            action='store_const',
                            dest='loglevel',
                            const=logging.INFO,
                            default=logging.NOTSET,
                            help='Output progress and results.')
        parser.add_argument('-D',
                            '--debug',
                            action='store_const',
                            dest='loglevel',
                            const=logging.DEBUG,
                            help='Output detailed debugging information.')
        parser.add_argument('--DMS',
                            action='store_true',
                            dest='DMS_enabled',
                            help='Running under DMS workflow conditions.')
        parser.add_argument(
            '--format',
            default='json',
            help='Format of the association files. Default: "%(default)s"')
        parser.add_argument('--version',
                            action='version',
                            version='%(prog)s {}'.format(__version__),
                            help='Version of the generator.')
        parser.add_argument('--no-merge',
                            action='store_true',
                            help='Do not merge Level2 associations into one')

        parsed = parser.parse_args(args=args)

        # Configure logging
        config = None
        if parsed.DMS_enabled:
            config = DMS_config
        logger = log_config(name=__package__, config=config)
        logger.setLevel(parsed.loglevel)

        # Preamble
        logger.info('Command-line arguments: {}'.format(args))
        logger.context.set('asn_candidate_ids', parsed.asn_candidate_ids)

        if pool is None:
            logger.info('Reading pool {}'.format(parsed.pool))
            self.pool = AssociationPool.read(
                parsed.pool,
                delimiter=parsed.delimiter,
                format=parsed.pool_format,
            )
        else:
            self.pool = pool

        # DMS: Add further info to logging.
        try:
            logger.context.set('program', self.pool[0]['PROGRAM'])
        except KeyError:
            pass

        # Determine mode of operation. Options are
        #  1) Only specified candidates
        #  2) Only discovered assocations that do not match
        #     candidate associations
        #  3) Both discovered and all candidate associations.
        logger.info('Reading rules.')
        if not parsed.discover and\
           not parsed.all_candidates and\
           parsed.asn_candidate_ids is None:
            parsed.discover = True
            parsed.all_candidates = True
        if parsed.discover or parsed.all_candidates:
            global_constraints = constrain_on_candidates(None)
        elif parsed.asn_candidate_ids is not None:
            global_constraints = constrain_on_candidates(
                parsed.asn_candidate_ids)

        self.rules = AssociationRegistry(
            parsed.rules,
            include_default=not parsed.ignore_default,
            global_constraints=global_constraints,
            name=CANDIDATE_RULESET)

        if parsed.discover:
            self.rules.update(
                AssociationRegistry(parsed.rules,
                                    include_default=not parsed.ignore_default,
                                    name=DISCOVER_RULESET))

        logger.info('Generating associations.')
        self.associations = generate(self.pool,
                                     self.rules,
                                     version_id=parsed.version_id)

        if parsed.discover:
            logger.debug('# asns found before discover filtering={}'.format(
                len(self.associations)))
            self.associations = filter_discovered_only(
                self.associations,
                DISCOVER_RULESET,
                CANDIDATE_RULESET,
                keep_candidates=parsed.all_candidates,
            )
            self.rules.Utility.resequence(self.associations)

        # Do a grand merging. This is done particularly for
        # Level2 associations.
        if not parsed.no_merge:
            try:
                self.associations = self.rules.Utility.merge_asns(
                    self.associations)
            except AttributeError:
                pass

        logger.info(self.__str__())

        if not parsed.dry_run:
            self.save(path=parsed.path,
                      format=parsed.format,
                      save_orphans=parsed.save_orphans)
Beispiel #5
0
    def __init__(self, args=None):

        if args is None:
            args = sys.argv[1:]
        if isinstance(args, str):
            args = args.split(' ')

        parser = argparse.ArgumentParser(
            description='Generate Assocation Data Products',
            usage='asn_generate pool'
        )
        parser.add_argument(
            'pool', type=str, help='Association Pool'
        )
        parser.add_argument(
            '-r', '--rules', action='append',
            help='Association Rules file.'
        )
        parser.add_argument(
            '-i', '--ids', nargs='+',
            dest='asn_candidate_ids',
            help='space-separated list of association candidate IDs to operate on.'
        )
        parser.add_argument(
            '--ignore-default', action='store_true',
            help='Do not include default rules. -r should be used if set.'
        )
        parser.add_argument(
            '--dry_run',
            action='store_true', dest='dry_run',
            help='Execute but do not save results.'
        )
        parser.add_argument(
            '-p', '--path', type=str,
            default='.',
            help='Folder to save the associations to. Default: "%(default)s"'
        )
        parser.add_argument(
            '-d', '--delimiter', type=str,
            default='|',
            help='''Delimiter
            to use if pool files are comma-separated-value
            (csv) type files. Default: "%(default)s"
            '''
        )
        parser.add_argument(
            '-v', '--verbose',
            action='store_const', dest='loglevel',
            const=logging.INFO, default=logging.NOTSET,
            help='Output progress and results.'
        )
        parser.add_argument(
            '-D', '--debug',
            action='store_const', dest='loglevel',
            const=logging.DEBUG,
            help='Output detailed debugging information.'
        )
        parser.add_argument(
            '--DMS',
            action='store_true', dest='DMS_enabled',
            help='Running under DMS workflow conditions.'
        )
        parser.add_argument(
            '--cross-candidate-only',
            action='store_true', dest='cross_candidate_only',
            help='Only produce cross-candidate associations'
        )

        parsed = parser.parse_args(args=args)

        # Configure logging
        config = None
        if parsed.DMS_enabled:
            config = DMS_config
        logger = log_config(name=__package__, config=config)
        logger.setLevel(parsed.loglevel)

        # Preamble
        logger.info('Command-line arguments: {}'.format(args))
        logger.context.set('asn_candidate_ids', parsed.asn_candidate_ids)

        logger.info('Reading pool {}'.format(parsed.pool))
        self.pool = AssociationPool.read(
            parsed.pool, delimiter=parsed.delimiter
        )

        # DMS: Add further info to logging.
        try:
            logger.context.set('program', self.pool[0]['PROGRAM'])
        except KeyError:
            pass

        # Setup rules.

        # Check for Candidate-specific or whole program.
        # In DMS, this is the difference between Level 3
        # versus Level 3.5 processing.
        # The rules themselves do not contain this knowledge.
        self.cross_candidate_mode = parsed.asn_candidate_ids is None
        self.cross_candidate_only = parsed.cross_candidate_only
        global_constraints = {}
        if not self.cross_candidate_mode:
            global_constraints['asn_candidate_ids'] = {
                'value': parsed.asn_candidate_ids,
                'inputs': ['ASN_CANDIDATE_ID', 'OBS_NUM'],
                'force_unique': True,
            }

        logger.info('Reading rules.')
        self.rules = AssociationRegistry(
            parsed.rules,
            include_default=not parsed.ignore_default,
            global_constraints=global_constraints
        )

        logger.info('Generating associations.')
        self.associations, self.orphaned = generate(self.pool, self.rules)

        logger.debug(
            'cross_candidate_mode="{}" cross_candidate_only="{}"'.format(
                self.cross_candidate_mode,
                self.cross_candidate_only
            )
        )
        if self.cross_candidate_mode and self.cross_candidate_only:
            self.associations = self.rules.Utility.filter_cross_candidates(
                self.associations
            )

        logger.info(self.__str__())

        if not parsed.dry_run:
            self.save(path=parsed.path)