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
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
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)
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' }) )