

'''simple docstring'''




import enum
import inspect
from typing import Iterable, List, Optional, Tuple, Union



class        lowercase_	(		enum.Enum ):

  '''simple docstring'''





  __lowerCAmelCase					: Dict      =   "timm"
  __lowerCAmelCase					: Any      =   "transformers"




def       lowerCamelCase__		(						SCREAMING_SNAKE_CASE      :   Optional[Iterable[str]]       ,   SCREAMING_SNAKE_CASE      :   Optional[Iterable[int]]       ,   SCREAMING_SNAKE_CASE      :   Optional[Iterable[str]]						):
  if stage_names is None:
    raise ValueError('Stage_names must be set for transformers backbones'						)

  if out_features is not None:
    if not isinstance(SCREAMING_SNAKE_CASE       ,   (list,)						):
      raise ValueError(f'''out_features must be a list {type(SCREAMING_SNAKE_CASE						)}'''						)
    if any(feat not in stage_names for feat in out_features						):
      raise ValueError(f'''out_features must be a subset of stage_names: {stage_names} got {out_features}'''						)

  if out_indices is not None:
    if not isinstance(SCREAMING_SNAKE_CASE       ,   (list, tuple)						):
      raise ValueError(f'''out_indices must be a list or tuple, got {type(SCREAMING_SNAKE_CASE						)}'''						)
    if any(idx >= len(SCREAMING_SNAKE_CASE						) for idx in out_indices						):
      raise ValueError('out_indices must be valid indices for stage_names {stage_names}, got {out_indices}'						)

  if out_features is not None and out_indices is not None:
    if len(SCREAMING_SNAKE_CASE						) != len(SCREAMING_SNAKE_CASE						):
      raise ValueError('out_features and out_indices should have the same length if both are set'						)
    if out_features != [stage_names[idx] for idx in out_indices]:
      raise ValueError('out_features and out_indices should correspond to the same stages if both are set'						)


def       lowerCamelCase__		(						SCREAMING_SNAKE_CASE      :   Optional[List[str]]       ,   SCREAMING_SNAKE_CASE      :   Optional[Union[List[int], Tuple[int]]]       ,   SCREAMING_SNAKE_CASE      :   List[str]       ,   ):
  if out_indices is None and out_features is None:
    UpperCAmelCase													=	[len(SCREAMING_SNAKE_CASE						) - 1]
    UpperCAmelCase													=	[stage_names[-1]]
  elif out_indices is None and out_features is not None:
    UpperCAmelCase													=	[stage_names.index(SCREAMING_SNAKE_CASE						) for layer in out_features]
  elif out_features is None and out_indices is not None:
    UpperCAmelCase													=	[stage_names[idx] for idx in out_indices]
  return out_features, out_indices


def       lowerCamelCase__		(						SCREAMING_SNAKE_CASE      :   Optional[List[str]]       ,   SCREAMING_SNAKE_CASE      :   Optional[Union[List[int], Tuple[int]]]       ,   SCREAMING_SNAKE_CASE      :   List[str]       ,   ):
  verify_out_features_out_indices(out_features=SCREAMING_SNAKE_CASE       ,   out_indices=SCREAMING_SNAKE_CASE       ,   stage_names=SCREAMING_SNAKE_CASE						)
  UpperCAmelCase							,      UpperCAmelCase													=	_align_output_features_output_indices(
      out_features=SCREAMING_SNAKE_CASE       ,   out_indices=SCREAMING_SNAKE_CASE       ,   stage_names=SCREAMING_SNAKE_CASE						)
  # Verify that the aligned out_features and out_indices are valid
  verify_out_features_out_indices(out_features=SCREAMING_SNAKE_CASE       ,   out_indices=SCREAMING_SNAKE_CASE       ,   stage_names=SCREAMING_SNAKE_CASE						)
  return output_features, output_indices



class        lowercase_	:

  '''simple docstring'''





  __lowerCAmelCase					: Optional[BackboneType]      =   None
  def 						snake_case_			(     self   , a_     )							->				None:


    """simple docstring"""
    if getattr(self   , '_backbone'   , a_     ) is None:
      raise ValueError('self._backbone must be set before calling _init_timm_backbone'     )

    # These will diagree with the defaults for the transformers models e.g. for resnet50
    # the transformer model has out_features = ['stem', 'stage1', 'stage2', 'stage3', 'stage4']
    # the timm model has out_features = ['act', 'layer1', 'layer2', 'layer3', 'layer4']
    UpperCAmelCase													=	[stage['module'] for stage in self._backbone.feature_info.info]
    UpperCAmelCase													=	[stage['num_chs'] for stage in self._backbone.feature_info.info]
    UpperCAmelCase													=	self._backbone.feature_info.out_indices
    UpperCAmelCase													=	self._backbone.feature_info.module_name()

    # We verify the out indices and out features are valid
    verify_out_features_out_indices(
        out_features=a_   , out_indices=a_   , stage_names=self.stage_names     )
    UpperCAmelCase							,      UpperCAmelCase													=	out_features, out_indices
  def 						snake_case_			(     self   , a_     )							->				None:


    """simple docstring"""
    UpperCAmelCase													=	getattr(a_   , 'stage_names'     )
    UpperCAmelCase													=	getattr(a_   , 'out_features'   , a_     )
    UpperCAmelCase													=	getattr(a_   , 'out_indices'   , a_     )

    UpperCAmelCase													=	stage_names
    UpperCAmelCase							,      UpperCAmelCase													=	get_aligned_output_features_output_indices(
        out_features=a_   , out_indices=a_   , stage_names=a_     )
    # Number of channels for each stage. This is set in the transformer backbone model init
    UpperCAmelCase													=	None
  def 						snake_case_			(     self   , a_     )							->				None:


    """simple docstring"""
    UpperCAmelCase													=	config

    UpperCAmelCase													=	getattr(a_   , 'use_timm_backbone'   , a_     )
    UpperCAmelCase													=	BackboneType.TIMM if self.use_timm_backbone else BackboneType.TRANSFORMERS

    if self.backbone_type == BackboneType.TIMM:
      self._init_timm_backbone(a_     )
    elif self.backbone_type == BackboneType.TRANSFORMERS:
      self._init_transformers_backbone(a_     )
    else:
      raise ValueError(F'''backbone_type {self.backbone_type} not supported.'''     )
  @property
  def 						snake_case_			(     self     )							->				str:


    """simple docstring"""
    return self._out_features
  @out_features.setter
  def 						snake_case_			(     self   , a_     )							->				Tuple:


    """simple docstring"""
    UpperCAmelCase							,      UpperCAmelCase													=	get_aligned_output_features_output_indices(
        out_features=a_   , out_indices=a_   , stage_names=self.stage_names     )
  @property
  def 						snake_case_			(     self     )							->				List[Any]:


    """simple docstring"""
    return self._out_indices
  @out_indices.setter
  def 						snake_case_			(     self   , a_     )							->				Any:


    """simple docstring"""
    UpperCAmelCase							,      UpperCAmelCase													=	get_aligned_output_features_output_indices(
        out_features=a_   , out_indices=a_   , stage_names=self.stage_names     )
  @property
  def 						snake_case_			(     self     )							->				Dict:


    """simple docstring"""
    # the current backbones will output the number of channels for each stage
    # even if that stage is not in the out_features list.
    return {stage: self.num_features[i] for i, stage in enumerate(self.stage_names     )}
  @property
  def 						snake_case_			(     self     )							->				List[Any]:


    """simple docstring"""
    return [self.out_feature_channels[name] for name in self.out_features]
  def 						snake_case_			(     self   , *a_   , **a_     )							->				Tuple:


    """simple docstring"""
    UpperCAmelCase													=	dict(inspect.signature(self.forward     ).parameters     )
    UpperCAmelCase													=	{k: v for k, v in kwargs.items() if k in signature}
    return self(*a_   , **a_     )
  def 						snake_case_			(     self   , a_   , a_ = None   , a_ = None   , a_ = None   , )							->				Optional[Any]:


    """simple docstring"""
    raise NotImplementedError('This method should be implemented by the derived class.'     )





  def 						snake_case_			(     self     )							->				int:


    """simple docstring"""
    UpperCAmelCase													=	super().to_dict()
    UpperCAmelCase													=	output.pop('_out_features'     )
    UpperCAmelCase													=	output.pop('_out_indices'     )
    return output




class        lowercase_	:

  '''simple docstring'''





  @property
  def 						snake_case_			(     self     )							->				Optional[int]:


    """simple docstring"""
    return self._out_features
  @out_features.setter
  def 						snake_case_			(     self   , a_     )							->				str:


    """simple docstring"""
    UpperCAmelCase							,      UpperCAmelCase													=	get_aligned_output_features_output_indices(
        out_features=a_   , out_indices=a_   , stage_names=self.stage_names     )
  @property
  def 						snake_case_			(     self     )							->				Tuple:


    """simple docstring"""
    return self._out_indices
  @out_indices.setter
  def 						snake_case_			(     self   , a_     )							->				Optional[Any]:


    """simple docstring"""
    UpperCAmelCase							,      UpperCAmelCase													=	get_aligned_output_features_output_indices(
        out_features=a_   , out_indices=a_   , stage_names=self.stage_names     )





  def 						snake_case_			(     self     )							->				Optional[int]:


    """simple docstring"""
    UpperCAmelCase													=	super().to_dict()
    UpperCAmelCase													=	output.pop('_out_features'     )
    UpperCAmelCase													=	output.pop('_out_indices'     )
    return output





'''simple docstring'''




from typing import List, Optional, Tuple, Union

from . import logging
from .import_utils import is_torch_available, is_torch_version


if is_torch_available():
  import torch

_a				: List[Any] 							=						logging.get_logger(__name__)  # pylint: disable=invalid-name

try:
  from torch._dynamo import allow_in_graph as maybe_allow_in_graph
except (ImportError, ModuleNotFoundError):


  def       lowerCamelCase__		(						cls      :   Dict						):
    return cls


def       lowerCamelCase__		(						SCREAMING_SNAKE_CASE      :   Union[Tuple, List]       ,   SCREAMING_SNAKE_CASE      :   Optional[Union[List["torch.Generator"], "torch.Generator"]] = None       ,   SCREAMING_SNAKE_CASE      :   Optional["torch.device"] = None       ,   SCREAMING_SNAKE_CASE      :   Optional["torch.dtype"] = None       ,   SCREAMING_SNAKE_CASE      :   Optional["torch.layout"] = None       ,   ):
  UpperCAmelCase													=	device
  UpperCAmelCase													=	shape[0]

  UpperCAmelCase													=	layout or torch.strided
  UpperCAmelCase													=	device or torch.device('cpu'						)

  if generator is not None:
    UpperCAmelCase													=	generator.device.type if not isinstance(SCREAMING_SNAKE_CASE       ,   SCREAMING_SNAKE_CASE						) else generator[0].device.type
    if gen_device_type != device.type and gen_device_type == "cpu":
      UpperCAmelCase													=	'cpu'
      if device != "mps":
        logger.info(
            f'''The passed generator was created on \'cpu\' even though a tensor on {device} was expected.'''
            f''' Tensors will be created on \'cpu\' and then moved to {device}. Note that one can probably'''
            f''' slighly speed up this function by passing a generator that was created on the {device} device.'''						)
    elif gen_device_type != device.type and gen_device_type == "cuda":
      raise ValueError(f'''Cannot generate a {device} tensor from a generator of type {gen_device_type}.'''						)

  if isinstance(SCREAMING_SNAKE_CASE       ,   SCREAMING_SNAKE_CASE						):
    UpperCAmelCase													=	(1,) + shape[1:]
    UpperCAmelCase													=	[
        torch.randn(SCREAMING_SNAKE_CASE       ,   generator=generator[i]       ,   device=SCREAMING_SNAKE_CASE       ,   dtype=SCREAMING_SNAKE_CASE       ,   layout=SCREAMING_SNAKE_CASE						)
        for i in range(SCREAMING_SNAKE_CASE						)
    ]
    UpperCAmelCase													=	torch.cat(SCREAMING_SNAKE_CASE       ,   dim=0						).to(SCREAMING_SNAKE_CASE						)
  else:
    UpperCAmelCase													=	torch.randn(SCREAMING_SNAKE_CASE       ,   generator=SCREAMING_SNAKE_CASE       ,   device=SCREAMING_SNAKE_CASE       ,   dtype=SCREAMING_SNAKE_CASE       ,   layout=SCREAMING_SNAKE_CASE						).to(SCREAMING_SNAKE_CASE						)

  return latents



def       lowerCamelCase__		(						SCREAMING_SNAKE_CASE      :   Tuple						):
  if is_torch_version('<'       ,   '2.0.0'						) or not hasattr(SCREAMING_SNAKE_CASE       ,   '_dynamo'						):
    return False
  return isinstance(SCREAMING_SNAKE_CASE       ,   torch._dynamo.eval_frame.OptimizedModule						)


