

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()
a_						     =    logging.get_logger(__name__)

def  lowerCamelCase__ (					_a							,			_a=False):
	SCREAMING_SNAKE_CASE   :      Tuple				     =       []
	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"
		SCREAMING_SNAKE_CASE   :      Any				     =       [(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__ (					_a							,			_a							,			_a=False):
	for i in range(config.num_hidden_layers):
		if base_model:
			SCREAMING_SNAKE_CASE   :      Dict				     =       ""
		else:
			SCREAMING_SNAKE_CASE   :      str				     =       "vit."
		# read in weights + bias of input projection layer (in timm, this is a single matrix + bias)
		SCREAMING_SNAKE_CASE   :      Optional[int]				     =       state_dict.pop(f"blocks.{i}.attn.qkv.weight")
		SCREAMING_SNAKE_CASE   :      Optional[Any]				     =       state_dict.pop(f"blocks.{i}.attn.qkv.bias")
		# next, add query, keys and values (in that order) to the state dict
		SCREAMING_SNAKE_CASE   :      Optional[Any]				     =       in_proj_weight[
		    : config.hidden_size, :
		]
		SCREAMING_SNAKE_CASE   :      Union[str, Any]				     =       in_proj_bias[: config.hidden_size]
		SCREAMING_SNAKE_CASE   :      List[str]				     =       in_proj_weight[
		    config.hidden_size : config.hidden_size * 2, :
		]
		SCREAMING_SNAKE_CASE   :      List[str]				     =       in_proj_bias[
		    config.hidden_size : config.hidden_size * 2
		]
		SCREAMING_SNAKE_CASE   :      str				     =       in_proj_weight[
		    -config.hidden_size :, :
		]
		SCREAMING_SNAKE_CASE   :      Optional[Any]				     =       in_proj_bias[-config.hidden_size :]

def  lowerCamelCase__ (					_a):
	SCREAMING_SNAKE_CASE   :      Optional[int]				     =       ["head.weight", "head.bias"]
	for k in ignore_keys:
		state_dict.pop(_a							,			_a)

def  lowerCamelCase__ (					_a							,			_a							,			_a):
	SCREAMING_SNAKE_CASE   :      str				     =       dct.pop(_a)
	SCREAMING_SNAKE_CASE   :      Any				     =       val

def  lowerCamelCase__ (					):
	SCREAMING_SNAKE_CASE   :      Optional[int]				     =       "http://images.cocodataset.org/val2017/000000039769.jpg"
	SCREAMING_SNAKE_CASE   :      Optional[int]				     =       Image.open(requests.get(_a							,			stream=_a).raw)
	return im

@torch.no_grad()
def  lowerCamelCase__ (					_a							,			_a):
	SCREAMING_SNAKE_CASE   :      List[str]				     =       ViTConfig()
	SCREAMING_SNAKE_CASE   :      Optional[int]				     =       False
	# dataset (ImageNet-21k only or also fine-tuned on ImageNet 2012), patch_size and image_size
	if vit_name[-5:] == "in21k":
		SCREAMING_SNAKE_CASE   :      Any				     =       True
		SCREAMING_SNAKE_CASE   :      Optional[int]				     =       int(vit_name[-12:-10])
		SCREAMING_SNAKE_CASE   :      List[Any]				     =       int(vit_name[-9:-6])
	else:
		SCREAMING_SNAKE_CASE   :      int				     =       1000
		SCREAMING_SNAKE_CASE   :      Tuple				     =       "huggingface/label-files"
		SCREAMING_SNAKE_CASE   :      List[str]				     =       "imagenet-1k-id2label.json"
		SCREAMING_SNAKE_CASE   :      List[Any]				     =       json.load(open(hf_hub_download(_a							,			_a							,			repo_type="dataset")							,			"r"))
		SCREAMING_SNAKE_CASE   :      Any				     =       {int(_a): v for k, v in idalabel.items()}
		SCREAMING_SNAKE_CASE   :      List[Any]				     =       idalabel
		SCREAMING_SNAKE_CASE   :      str				     =       {v: k for k, v in idalabel.items()}
		SCREAMING_SNAKE_CASE   :      List[Any]				     =       int(vit_name[-6:-4])
		SCREAMING_SNAKE_CASE   :      Union[str, Any]				     =       int(vit_name[-3:])
	# size of the architecture
	if "deit" in vit_name:
		if vit_name[9:].startswith("tiny"):
			SCREAMING_SNAKE_CASE   :      List[str]				     =       192
			SCREAMING_SNAKE_CASE   :      str				     =       768
			SCREAMING_SNAKE_CASE   :      Optional[Any]				     =       12
			SCREAMING_SNAKE_CASE   :      List[Any]				     =       3
		elif vit_name[9:].startswith("small"):
			SCREAMING_SNAKE_CASE   :      int				     =       384
			SCREAMING_SNAKE_CASE   :      Optional[int]				     =       1536
			SCREAMING_SNAKE_CASE   :      Optional[int]				     =       12
			SCREAMING_SNAKE_CASE   :      Any				     =       6
		else:
			pass
	else:
		if vit_name[4:].startswith("small"):
			SCREAMING_SNAKE_CASE   :      str				     =       768
			SCREAMING_SNAKE_CASE   :      List[str]				     =       2304
			SCREAMING_SNAKE_CASE   :      Tuple				     =       8
			SCREAMING_SNAKE_CASE   :      str				     =       8
		elif vit_name[4:].startswith("base"):
			pass
		elif vit_name[4:].startswith("large"):
			SCREAMING_SNAKE_CASE   :      Dict				     =       1024
			SCREAMING_SNAKE_CASE   :      Any				     =       4096
			SCREAMING_SNAKE_CASE   :      Tuple				     =       24
			SCREAMING_SNAKE_CASE   :      Optional[int]				     =       16
		elif vit_name[4:].startswith("huge"):
			SCREAMING_SNAKE_CASE   :      Union[str, Any]				     =       1280
			SCREAMING_SNAKE_CASE   :      Dict				     =       5120
			SCREAMING_SNAKE_CASE   :      Any				     =       32
			SCREAMING_SNAKE_CASE   :      str				     =       16

    # load original model from timm
	SCREAMING_SNAKE_CASE   :      Optional[int]				     =       timm.create_model(_a							,			pretrained=_a)
	timm_model.eval()

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

	# load HuggingFace model
	if vit_name[-5:] == "in21k":
		SCREAMING_SNAKE_CASE   :      Union[str, Any]				     =       ViTModel(_a).eval()
	else:
		SCREAMING_SNAKE_CASE   :      List[Any]				     =       ViTForImageClassification(_a).eval()
	model.load_state_dict(_a)

	# Check outputs on an image, prepared by ViTImageProcessor/DeiTImageProcessor
	if "deit" in vit_name:
		SCREAMING_SNAKE_CASE   :      Optional[int]				     =       DeiTImageProcessor(size=config.image_size)
	else:
		SCREAMING_SNAKE_CASE   :      str				     =       ViTImageProcessor(size=config.image_size)
	SCREAMING_SNAKE_CASE   :      List[Any]				     =       image_processor(images=prepare_img()							,			return_tensors="pt")
	SCREAMING_SNAKE_CASE   :      Tuple				     =       encoding["pixel_values"]
	SCREAMING_SNAKE_CASE   :      Optional[int]				     =       model(_a)

	if base_model:
		SCREAMING_SNAKE_CASE   :      str				     =       timm_model.forward_features(_a)
		assert timm_pooled_output.shape == outputs.pooler_output.shape
		assert torch.allclose(_a							,			outputs.pooler_output							,			atol=1E-3)
	else:
		SCREAMING_SNAKE_CASE   :      List[str]				     =       timm_model(_a)
		assert timm_logits.shape == outputs.logits.shape
		assert torch.allclose(_a							,			outputs.logits							,			atol=1E-3)

	Path(_a).mkdir(exist_ok=_a)
	print(f"Saving model {vit_name} to {pytorch_dump_folder_path}")
	model.save_pretrained(_a)
	print(f"Saving image processor to {pytorch_dump_folder_path}")
	image_processor.save_pretrained(_a)


if __name__ == "__main__":
			a_						     =    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.'
			)

			a_						     =    parser.parse_args()
			convert_vit_checkpoint(args.vit_name, args.pytorch_dump_folder_path)


def  lowerCamelCase__ (					_a = 50):
	SCREAMING_SNAKE_CASE   :      int				     =       [1] * (length + 1)

	for row_length in range(length + 1):
		for tile_length in range(2							,			5):
			for tile_start in range(row_length - tile_length + 1):
				ways_number[row_length] += ways_number[
				    row_length - tile_start - tile_length
				]

	return ways_number[length]


if __name__ == "__main__":
			print(F'''{solution() = }''')