def validate(cls, asn):
        super(AsnMixin_CrossCandidate, cls).validate(asn)

        if isinstance(asn, AsnMixin_CrossCandidate):
            try:
                candidates = set(member['asn_candidate_id']
                                 for product in asn.data['products']
                                 for member in product['members'])
            except (AttributeError, KeyError) as err:
                raise AssociationNotValidError('Validation failed')
            if not len(candidates) > 1:
                raise AssociationNotValidError(
                    'Validation failed: No candidates found.')
        return True
Beispiel #2
0
    def validate(cls, asn):
        super(DMSBaseMixin, cls).validate(asn)

        if isinstance(asn, DMSBaseMixin):
            result = False
            try:
                result = all(test['validated']
                             for test in asn.validity.values())
            except (AttributeError, KeyError):
                raise AssociationNotValidError('Validation failed')
            if not result:
                raise AssociationNotValidError(
                    'Validation failed validity tests.')

        return True
Beispiel #3
0
    def _add_items(self,
                   items,
                   product_name=None,
                   with_exptype=False,
                   **kwargs):
        """ Force adding items to the association

        Parameters
        ----------
        items : [object[, ...]]
            A list of items to make members of the association.

        product_name : str or None
            The name of the product to add the items to.
            If the product does not already exist, it will be created.
            If None, the default DMS Level3 naming
            conventions will be attempted.

        with_exptype : bool
            If True, each item is expected to be a 2-tuple with
            the first element being the item to add as `expname`
            and the second items is the `exptype`

        kwargs : dict
            Allows other keyword arguments used by other subclasses.

        Notes
        -----
        This is a low-level shortcut into adding members, such as file names,
        to an association. All defined shortcuts and other initializations are
        by-passed, resulting in a potentially unusable association.
        """
        if product_name is None:
            raise AssociationNotValidError(
                'Product name needs to be specified'
            )

        self.new_product(product_name)
        members = self.current_product['members']
        for item in items:
            exptype = 'science'
            if with_exptype:
                item, exptype = item
            member = Member(
                {
                    'expname': item,
                    'exptype': exptype
                },
                item=item
            )
            self.update_validity(member)
            members.append(member)
        self.sequence = next(self._sequence)
Beispiel #4
0
    def add_catalog_members(self):
        """Add catalog and direct image member based on direct image members"""
        directs = self.members_by_type('direct_image')
        if not directs:
            raise AssociationNotValidError(
                '{} has no required direct image exposures'.format(
                    self.__class__.__name__
                )
            )

        sciences = self.members_by_type('science')
        if not sciences:
            raise AssociationNotValidError(
                '{} has no required science exposure'.format(
                    self.__class__.__name__
                )
            )
        science = sciences[0]

        # Get the exposure sequence for the science. Then, find
        # the direct image greater than but closest to this value.
        closest = directs[0]  # If the search fails, just use the first.
        try:
            expspcin = int(getattr_from_list(science.item, ['expspcin'], _EMPTY)[1])
        except KeyError:
            # If exposure sequence cannot be determined, just fall through.
            logger.debug('Science exposure %s has no EXPSPCIN defined.', science)
        else:
            min_diff = 9999         # Initialize to an invalid value.
            for direct in directs:
                # For NIRCam, only consider direct images from the same channel
                # as the grism image
                if direct.item['exp_type'] == 'nrc_image':
                    science_channel = getattr_from_list(science.item, ['channel'], _EMPTY)[1]
                    direct_channel = getattr_from_list(direct.item, ['channel'], _EMPTY)[1]
                    if direct_channel != science_channel:
                        continue
                # For NIRISS, only consider direct images with the same PUPIL value
                if direct.item['exp_type'] == 'nis_image':
                    science_pupil = getattr_from_list(science.item, ['pupil'], _EMPTY)[1]
                    direct_pupil = getattr_from_list(direct.item, ['pupil'], _EMPTY)[1]
                    if direct_pupil != science_pupil:
                        continue
                try:
                    direct_expspcin = int(getattr_from_list(
                        direct.item, ['expspcin'], _EMPTY
                    )[1])
                except KeyError:
                    # Try the next one.
                    logger.debug('Direct image %s has no EXPSPCIN defined.', direct)
                    continue
                diff = direct_expspcin - expspcin
                if diff < min_diff and diff > 0:
                    min_diff = diff
                    closest = direct

        # Note the selected direct image. Used in `Asn_Lv2WFSS._get_opt_element`
        self.direct_image = closest

        # Remove all direct images from the association.
        members = self.current_product['members']
        direct_idxs = [
            idx
            for idx, member in enumerate(members)
            if member['exptype'] == 'direct_image'
        ]
        deque((
            list.pop(members, idx)
            for idx in sorted(direct_idxs, reverse=True)
        ))

        # Add the Level3 catalog, direct image, and segmentation map members
        lv3_direct_image_root = DMS_Level3_Base._dms_product_name(self)
        members.append(
            Member({
                'expname': lv3_direct_image_root + '_i2d.fits',
                'exptype': 'direct_image'
            })
        )
        members.append(
            Member({
                'expname': lv3_direct_image_root + '_cat.ecsv',
                'exptype': 'sourcecat'
            })
        )
        members.append(
            Member({
                'expname': lv3_direct_image_root + '_segm.fits',
                'exptype': 'segmap'
            })
        )