


import argparse
import json
from pathlib import Path

import requests
import timm
import torch
from huggingface_hub import hf_hub_download
from PIL import Image

from transformers import DeiTImageProcessor, ViTConfig, ViTForImageClassification, ViTImageProcessor, ViTModel
from transformers.utils import logging


logging.set_verbosity_info()
SCREAMING_SNAKE_CASE						:List[str]			=  logging.get_logger(__name__)



def       _lowerCAmelCase    (				lowerCAmelCase_				:Tuple		,    lowerCAmelCase_				:Any=False				)->str:
   '''simple docstring'''






   snake_case_            =       []
   for i in range(config.num_hidden_layers				):
      # encoder layers: output projection, 2 feedforward neural networks and 2 layernorms
      rename_keys.append((F'''blocks.{i}.norm1.weight''', F'''vit.encoder.layer.{i}.layernorm_before.weight''')				)
      rename_keys.append((F'''blocks.{i}.norm1.bias''', F'''vit.encoder.layer.{i}.layernorm_before.bias''')				)
      rename_keys.append((F'''blocks.{i}.attn.proj.weight''', F'''vit.encoder.layer.{i}.attention.output.dense.weight''')				)
      rename_keys.append((F'''blocks.{i}.attn.proj.bias''', F'''vit.encoder.layer.{i}.attention.output.dense.bias''')				)
      rename_keys.append((F'''blocks.{i}.norm2.weight''', F'''vit.encoder.layer.{i}.layernorm_after.weight''')				)
      rename_keys.append((F'''blocks.{i}.norm2.bias''', F'''vit.encoder.layer.{i}.layernorm_after.bias''')				)
      rename_keys.append((F'''blocks.{i}.mlp.fc1.weight''', F'''vit.encoder.layer.{i}.intermediate.dense.weight''')				)
      rename_keys.append((F'''blocks.{i}.mlp.fc1.bias''', F'''vit.encoder.layer.{i}.intermediate.dense.bias''')				)
      rename_keys.append((F'''blocks.{i}.mlp.fc2.weight''', F'''vit.encoder.layer.{i}.output.dense.weight''')				)
      rename_keys.append((F'''blocks.{i}.mlp.fc2.bias''', F'''vit.encoder.layer.{i}.output.dense.bias''')				)

   # projection layer + position embeddings
   rename_keys.extend(
       [
           ("cls_token", "vit.embeddings.cls_token"),
           ("patch_embed.proj.weight", "vit.embeddings.patch_embeddings.projection.weight"),
           ("patch_embed.proj.bias", "vit.embeddings.patch_embeddings.projection.bias"),
           ("pos_embed", "vit.embeddings.position_embeddings"),
       ]				)

   if base_model:
      # layernorm + pooler
      rename_keys.extend(
          [
              ("norm.weight", "layernorm.weight"),
              ("norm.bias", "layernorm.bias"),
              ("pre_logits.fc.weight", "pooler.dense.weight"),
              ("pre_logits.fc.bias", "pooler.dense.bias"),
          ]				)

      # if just the base model, we should remove "vit" from all keys that start with "vit"
      snake_case_            =       [(pair[0], pair[1][4:]) if pair[1].startswith("vit"				) else pair for pair in rename_keys]
   else:
      # layernorm + classification head
      rename_keys.extend(
          [
              ("norm.weight", "vit.layernorm.weight"),
              ("norm.bias", "vit.layernorm.bias"),
              ("head.weight", "classifier.weight"),
              ("head.bias", "classifier.bias"),
          ]				)

   return rename_keys



def       _lowerCAmelCase    (				lowerCAmelCase_				:List[Any]		,    lowerCAmelCase_				:str		,    lowerCAmelCase_				:str=False				)->Tuple:
   '''simple docstring'''






   for i in range(config.num_hidden_layers				):
      if base_model:
         snake_case_            =       ""
      else:
         snake_case_            =       "vit."
      # read in weights + bias of input projection layer (in timm, this is a single matrix + bias)
      snake_case_            =       state_dict.pop(F'''blocks.{i}.attn.qkv.weight'''				)
      snake_case_            =       state_dict.pop(F'''blocks.{i}.attn.qkv.bias'''				)
      # next, add query, keys and values (in that order) to the state dict
      snake_case_            =       in_proj_weight[
          : config.hidden_size, :
      ]
      snake_case_            =       in_proj_bias[: config.hidden_size]
      snake_case_            =       in_proj_weight[
          config.hidden_size : config.hidden_size * 2, :
      ]
      snake_case_            =       in_proj_bias[
          config.hidden_size : config.hidden_size * 2
      ]
      snake_case_            =       in_proj_weight[
          -config.hidden_size :, :
      ]
      snake_case_            =       in_proj_bias[-config.hidden_size :]



def       _lowerCAmelCase    (				lowerCAmelCase_				:List[str]				)->Optional[Any]:
   '''simple docstring'''






   snake_case_            =       ["head.weight", "head.bias"]
   for k in ignore_keys:
      state_dict.pop(lowerCAmelCase_		,    lowerCAmelCase_				)



def       _lowerCAmelCase    (				lowerCAmelCase_				:List[Any]		,    lowerCAmelCase_				:str		,    lowerCAmelCase_				:Union[str, Any]				)->Tuple:
   '''simple docstring'''






   snake_case_            =       dct.pop(lowerCAmelCase_				)
   snake_case_            =       val



def       _lowerCAmelCase    (				)->Union[str, Any]:
   '''simple docstring'''






   snake_case_            =       "http://images.cocodataset.org/val2017/000000039769.jpg"
   snake_case_            =       Image.open(requests.get(lowerCAmelCase_		,    stream=lowerCAmelCase_				).raw				)
   return im



@torch.no_grad()
def       _lowerCAmelCase    (				lowerCAmelCase_				:Tuple		,    lowerCAmelCase_				:List[str]				)->Union[str, Any]:
   '''simple docstring'''






   snake_case_            =       ViTConfig()
   snake_case_            =       False
   # dataset (ImageNet-21k only or also fine-tuned on ImageNet 2012), patch_size and image_size
   if vit_name[-5:] == "in21k":
      snake_case_            =       True
      snake_case_            =       int(vit_name[-12:-10]				)
      snake_case_            =       int(vit_name[-9:-6]				)
   else:
      snake_case_            =       1_000
      snake_case_            =       "huggingface/label-files"
      snake_case_            =       "imagenet-1k-id2label.json"
      snake_case_            =       json.load(open(hf_hub_download(lowerCAmelCase_		,    lowerCAmelCase_		,    repo_type="dataset"				)		,    "r"				)				)
      snake_case_            =       {int(lowerCAmelCase_				): v for k, v in idalabel.items()}
      snake_case_            =       idalabel
      snake_case_            =       {v: k for k, v in idalabel.items()}
      snake_case_            =       int(vit_name[-6:-4]				)
      snake_case_            =       int(vit_name[-3:]				)
   # size of the architecture
   if "deit" in vit_name:
      if vit_name[9:].startswith("tiny"				):
         snake_case_            =       192
         snake_case_            =       768
         snake_case_            =       12
         snake_case_            =       3
      elif vit_name[9:].startswith("small"				):
         snake_case_            =       384
         snake_case_            =       1_536
         snake_case_            =       12
         snake_case_            =       6
      else:
         pass
   else:
      if vit_name[4:].startswith("small"				):
         snake_case_            =       768
         snake_case_            =       2_304
         snake_case_            =       8
         snake_case_            =       8
      elif vit_name[4:].startswith("base"				):
         pass
      elif vit_name[4:].startswith("large"				):
         snake_case_            =       1_024
         snake_case_            =       4_096
         snake_case_            =       24
         snake_case_            =       16
      elif vit_name[4:].startswith("huge"				):
         snake_case_            =       1_280
         snake_case_            =       5_120
         snake_case_            =       32
         snake_case_            =       16

    # load original model from timm
   snake_case_            =       timm.create_model(lowerCAmelCase_		,    pretrained=lowerCAmelCase_				)
   timm_model.eval()

   # load state_dict of original model, remove and rename some keys
   snake_case_            =       timm_model.state_dict()
   if base_model:
      remove_classification_head_(lowerCAmelCase_				)
   snake_case_            =       create_rename_keys(lowerCAmelCase_		,    lowerCAmelCase_				)
   for src, dest in rename_keys:
      rename_key(lowerCAmelCase_		,    lowerCAmelCase_		,    lowerCAmelCase_				)
   read_in_q_k_v(lowerCAmelCase_		,    lowerCAmelCase_		,    lowerCAmelCase_				)

   # load HuggingFace model
   if vit_name[-5:] == "in21k":
      snake_case_            =       ViTModel(lowerCAmelCase_				).eval()
   else:
      snake_case_            =       ViTForImageClassification(lowerCAmelCase_				).eval()
   model.load_state_dict(lowerCAmelCase_				)

   # Check outputs on an image, prepared by ViTImageProcessor/DeiTImageProcessor
   if "deit" in vit_name:
      snake_case_            =       DeiTImageProcessor(size=config.image_size				)
   else:
      snake_case_            =       ViTImageProcessor(size=config.image_size				)
   snake_case_            =       image_processor(images=prepare_img()		,    return_tensors="pt"				)
   snake_case_            =       encoding["pixel_values"]
   snake_case_            =       model(lowerCAmelCase_				)

   if base_model:
      snake_case_            =       timm_model.forward_features(lowerCAmelCase_				)
      assert timm_pooled_output.shape == outputs.pooler_output.shape
      assert torch.allclose(lowerCAmelCase_		,    outputs.pooler_output		,    atol=1e-3				)
   else:
      snake_case_            =       timm_model(lowerCAmelCase_				)
      assert timm_logits.shape == outputs.logits.shape
      assert torch.allclose(lowerCAmelCase_		,    outputs.logits		,    atol=1e-3				)

   Path(lowerCAmelCase_				).mkdir(exist_ok=lowerCAmelCase_				)
   print(F'''Saving model {vit_name} to {pytorch_dump_folder_path}'''				)
   model.save_pretrained(lowerCAmelCase_				)
   print(F'''Saving image processor to {pytorch_dump_folder_path}'''				)
   image_processor.save_pretrained(lowerCAmelCase_				)


if __name__ == "__main__":
   SCREAMING_SNAKE_CASE						:Any			=  argparse.ArgumentParser()
   # Required parameters
   parser.add_argument(
       '''--vit_name''',
       default='''vit_base_patch16_224''',
       type=str,
       help='''Name of the ViT timm model you\'d like to convert.''',
   )
   parser.add_argument(
       '''--pytorch_dump_folder_path''', default=None, type=str, help='''Path to the output PyTorch model directory.'''
   )

   SCREAMING_SNAKE_CASE						:Dict			=  parser.parse_args()
   convert_vit_checkpoint(args.vit_name, args.pytorch_dump_folder_path)








from math import factorial



def       _lowerCAmelCase    (				lowerCAmelCase_				:int = 20				)->int:
   '''simple docstring'''






   snake_case_            =       2 * n  # middle entry of odd rows starting at row 3 is the solution for n = 1,
   # 2, 3,...
   snake_case_            =       n // 2

   return int(factorial(lowerCAmelCase_				) / (factorial(lowerCAmelCase_				) * factorial(n - k				))				)


if __name__ == "__main__":
   import sys

   if len(sys.argv) == 1:
      print(solution(20))
   else:
      try:
         SCREAMING_SNAKE_CASE						:Any			=  int(sys.argv[1])
         print(solution(n))
      except ValueError:
         print('''Invalid entry - please enter a number.''')




