





import argparse
import json
from pathlib import Path

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

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


logging.set_verbosity_info()
__lowercase       :int       =  logging.get_logger(__name__)







def       UpperCAmelCase							(     _lowerCamelCase      :  Optional[Any]			,   _lowerCamelCase      :  List[str]=False     ):





						'''simple docstring'''


						SCREAMING_SNAKE_CASE__     :				Dict   =					[]
						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"),
												    ]     )

												# if just the base model, we should remove "vit" from all keys that start with "vit"
												SCREAMING_SNAKE_CASE__     :				Union[str, 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       UpperCAmelCase							(     _lowerCamelCase      :  Optional[int]			,   _lowerCamelCase      :  str			,   _lowerCamelCase      :  List[Any]=False     ):





						'''simple docstring'''


						for i in range(config.num_hidden_layers     ):
												if base_model:
																		SCREAMING_SNAKE_CASE__     :				Dict   =					""
												else:
																		SCREAMING_SNAKE_CASE__     :				Union[str, Any]   =					"vit."
												# read in weights + bias of input projection layer (in timm, this is a single matrix + bias)
												SCREAMING_SNAKE_CASE__     :				List[str]   =					state_dict.pop(f"""blocks.{i}.attn.qkv.weight"""     )
												SCREAMING_SNAKE_CASE__     :				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__     :				int   =					in_proj_weight[
												    : config.hidden_size, :
												]
												SCREAMING_SNAKE_CASE__     :				List[Any]   =					in_proj_bias[: config.hidden_size]
												SCREAMING_SNAKE_CASE__     :				Any   =					in_proj_weight[
												    config.hidden_size : config.hidden_size * 2, :
												]
												SCREAMING_SNAKE_CASE__     :				Union[str, Any]   =					in_proj_bias[
												    config.hidden_size : config.hidden_size * 2
												]
												SCREAMING_SNAKE_CASE__     :				Union[str, Any]   =					in_proj_weight[
												    -config.hidden_size :, :
												]
												SCREAMING_SNAKE_CASE__     :				List[str]   =					in_proj_bias[-config.hidden_size :]







def       UpperCAmelCase							(     _lowerCamelCase      :  Tuple     ):





						'''simple docstring'''


						SCREAMING_SNAKE_CASE__     :				Dict   =					["head.weight", "head.bias"]
						for k in ignore_keys:
												state_dict.pop(_lowerCamelCase			,   _lowerCamelCase     )







def       UpperCAmelCase							(     _lowerCamelCase      :  Dict			,   _lowerCamelCase      :  int			,   _lowerCamelCase      :  List[str]     ):





						'''simple docstring'''


						SCREAMING_SNAKE_CASE__     :				List[Any]   =					dct.pop(_lowerCamelCase     )
						SCREAMING_SNAKE_CASE__     :				Tuple   =					val







def       UpperCAmelCase							(     ):





						'''simple docstring'''


						SCREAMING_SNAKE_CASE__     :				List[str]   =					"http://images.cocodataset.org/val2017/000000039769.jpg"
						SCREAMING_SNAKE_CASE__     :				List[Any]   =					Image.open(requests.get(_lowerCamelCase			,   stream=_lowerCamelCase     ).raw     )
						return im







@torch.no_grad()
def       UpperCAmelCase							(     _lowerCamelCase      :  int			,   _lowerCamelCase      :  str			,   _lowerCamelCase      :  int=True     ):





						'''simple docstring'''


						SCREAMING_SNAKE_CASE__     :				str   =					ViTConfig()
						# patch_size
						if model_name[-1] == "8":
												SCREAMING_SNAKE_CASE__     :				Optional[int]   =					8
						# set labels if required
						if not base_model:
												SCREAMING_SNAKE_CASE__     :				Any   =					1_000
												SCREAMING_SNAKE_CASE__     :				int   =					"huggingface/label-files"
												SCREAMING_SNAKE_CASE__     :				int   =					"imagenet-1k-id2label.json"
												SCREAMING_SNAKE_CASE__     :				Union[str, Any]   =					json.load(open(hf_hub_download(_lowerCamelCase			,   _lowerCamelCase			,   repo_type="dataset"     )			,   "r"     )     )
												SCREAMING_SNAKE_CASE__     :				List[str]   =					{int(_lowerCamelCase     ): v for k, v in idalabel.items()}
												SCREAMING_SNAKE_CASE__     :				Union[str, Any]   =					idalabel
												SCREAMING_SNAKE_CASE__     :				int   =					{v: k for k, v in idalabel.items()}
						# size of the architecture
						if model_name in ["dino_vits8", "dino_vits16"]:
												SCREAMING_SNAKE_CASE__     :				Optional[Any]   =					384
												SCREAMING_SNAKE_CASE__     :				int   =					1_536
												SCREAMING_SNAKE_CASE__     :				str   =					12
												SCREAMING_SNAKE_CASE__     :				Union[str, Any]   =					6

						# load original model from torch hub
						SCREAMING_SNAKE_CASE__     :				Optional[Any]   =					torch.hub.load("facebookresearch/dino:main"			,   _lowerCamelCase     )
						original_model.eval()

						# load state_dict of original model, remove and rename some keys
						SCREAMING_SNAKE_CASE__     :				List[Any]   =					original_model.state_dict()
						if base_model:
												remove_classification_head_(_lowerCamelCase     )
						SCREAMING_SNAKE_CASE__     :				Union[str, Any]   =					create_rename_keys(_lowerCamelCase			,   base_model=_lowerCamelCase     )
						for src, dest in rename_keys:
												rename_key(_lowerCamelCase			,   _lowerCamelCase			,   _lowerCamelCase     )
						read_in_q_k_v(_lowerCamelCase			,   _lowerCamelCase			,   _lowerCamelCase     )

						# load HuggingFace model
						if base_model:
												SCREAMING_SNAKE_CASE__     :				Optional[Any]   =					ViTModel(_lowerCamelCase			,   add_pooling_layer=_lowerCamelCase     ).eval()
						else:
												SCREAMING_SNAKE_CASE__     :				int   =					ViTForImageClassification(_lowerCamelCase     ).eval()
						model.load_state_dict(_lowerCamelCase     )

						# Check outputs on an image, prepared by ViTImageProcessor
						SCREAMING_SNAKE_CASE__     :				Optional[int]   =					ViTImageProcessor()
						SCREAMING_SNAKE_CASE__     :				Union[str, Any]   =					image_processor(images=prepare_img()			,   return_tensors="pt"     )
						SCREAMING_SNAKE_CASE__     :				str   =					encoding["pixel_values"]
						SCREAMING_SNAKE_CASE__     :				Tuple   =					model(_lowerCamelCase     )

						if base_model:
												SCREAMING_SNAKE_CASE__     :				Any   =					original_model(_lowerCamelCase     )
												assert torch.allclose(_lowerCamelCase			,   outputs.last_hidden_state[:, 0, :]			,   atol=1E-1     )
						else:
												SCREAMING_SNAKE_CASE__     :				Dict   =					original_model(_lowerCamelCase     )
												assert logits.shape == outputs.logits.shape
												assert torch.allclose(_lowerCamelCase			,   outputs.logits			,   atol=1E-3     )

						Path(_lowerCamelCase     ).mkdir(exist_ok=_lowerCamelCase     )
						print(f"""Saving model {model_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__":
				__lowercase       :Tuple       =  argparse.ArgumentParser()
				# Required parameters
				parser.add_argument(
				    "--model_name",
				    default="dino_vitb16",
				    type=str,
				    help="Name of the model trained with DINO you'd like to convert.",
				)
				parser.add_argument(
				    "--pytorch_dump_folder_path", default=None, type=str, help="Path to the output PyTorch model directory."
				)
				parser.add_argument(
				    "--base_model",
				    action="store_true",
				    help="Whether to only convert the base model (no projection head weights).",
				)

				parser.set_defaults(base_model=True)
				__lowercase       :List[str]       =  parser.parse_args()
				convert_vit_checkpoint(args.model_name, args.pytorch_dump_folder_path, args.base_model)






from __future__ import annotations







def       UpperCAmelCase							(     _lowerCamelCase      :  list[int | float]			,   _lowerCamelCase      :  int			,   _lowerCamelCase      :  int     ):





						'''simple docstring'''


						if len(_lowerCamelCase     ) == 0:
												raise ValueError("find_max() arg is an empty sequence"     )
						if (
						    left >= len(_lowerCamelCase     )
						    or left < -len(_lowerCamelCase     )
						    or right >= len(_lowerCamelCase     )
						    or right < -len(_lowerCamelCase     )
						):
												raise IndexError("list index out of range"     )
						if left == right:
												return nums[left]
						SCREAMING_SNAKE_CASE__     :				Optional[int]   =					(left + right) >> 1  # the middle
						SCREAMING_SNAKE_CASE__     :				List[Any]   =					find_max(_lowerCamelCase			,   _lowerCamelCase			,   _lowerCamelCase     )  # find max in range[left, mid]
						SCREAMING_SNAKE_CASE__     :				Optional[int]   =					find_max(_lowerCamelCase			,   mid + 1			,   _lowerCamelCase     )  # find max in range[mid + 1, right]

						return left_max if left_max >= right_max else right_max


if __name__ == "__main__":
				import doctest

				doctest.testmod(verbose=True)