





import argparse
import json

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

from transformers import SegformerImageProcessor, SwinConfig, UperNetConfig, UperNetForSemanticSegmentation

def 				SCREAMING_SNAKE_CASE__							(	snake_case__	:str  )   ->    Tuple:
  _lowercase						    =			384
  _lowercase						    =			7
  if "tiny" in model_name:
    _lowercase						    =			96
    _lowercase						    =			(2, 2, 6, 2)
    _lowercase						    =			(3, 6, 12, 24)
  elif "small" in model_name:
    _lowercase						    =			96
    _lowercase						    =			(2, 2, 18, 2)
    _lowercase						    =			(3, 6, 12, 24)
  elif "base" in model_name:
    _lowercase						    =			128
    _lowercase						    =			(2, 2, 18, 2)
    _lowercase						    =			(4, 8, 16, 32)
    _lowercase						    =			12
    _lowercase						    =			512
  elif "large" in model_name:
    _lowercase						    =			192
    _lowercase						    =			(2, 2, 18, 2)
    _lowercase						    =			(6, 12, 24, 48)
    _lowercase						    =			12
    _lowercase						    =			768

  # set label information
  _lowercase						    =			150
  _lowercase						    =			'huggingface/label-files'
  _lowercase						    =			'ade20k-id2label.json'
  _lowercase						    =			json.load(open(hf_hub_download(snake_case__      ,				snake_case__      ,				repo_type='dataset'  )      ,				'r'  )  )
  _lowercase						    =			{int(snake_case__  ): v for k, v in idalabel.items()}
  _lowercase						    =			{v: k for k, v in idalabel.items()}

  _lowercase						    =			SwinConfig(
      embed_dim=snake_case__      ,				depths=snake_case__      ,				num_heads=snake_case__      ,				window_size=snake_case__      ,				out_features=['stage1', 'stage2', 'stage3', 'stage4']      ,				)
  _lowercase						    =			UperNetConfig(
      backbone_config=snake_case__      ,				auxiliary_in_channels=snake_case__      ,				num_labels=snake_case__      ,				idalabel=snake_case__      ,				labelaid=snake_case__      ,				)

  return config

def 				SCREAMING_SNAKE_CASE__							(	snake_case__	:Union[str, Any]  )   ->    List[Any]:
  _lowercase						    =			[]

  # fmt: off
  # stem
  rename_keys.append(('backbone.patch_embed.projection.weight', 'backbone.embeddings.patch_embeddings.projection.weight')  )
  rename_keys.append(('backbone.patch_embed.projection.bias', 'backbone.embeddings.patch_embeddings.projection.bias')  )
  rename_keys.append(('backbone.patch_embed.norm.weight', 'backbone.embeddings.norm.weight')  )
  rename_keys.append(('backbone.patch_embed.norm.bias', 'backbone.embeddings.norm.bias')  )
  # stages
  for i in range(len(config.backbone_config.depths  )  ):
    for j in range(config.backbone_config.depths[i]  ):
      rename_keys.append((F"""backbone.stages.{i}.blocks.{j}.norm1.weight""", F"""backbone.encoder.layers.{i}.blocks.{j}.layernorm_before.weight""")  )
      rename_keys.append((F"""backbone.stages.{i}.blocks.{j}.norm1.bias""", F"""backbone.encoder.layers.{i}.blocks.{j}.layernorm_before.bias""")  )
      rename_keys.append((F"""backbone.stages.{i}.blocks.{j}.attn.w_msa.relative_position_bias_table""", F"""backbone.encoder.layers.{i}.blocks.{j}.attention.self.relative_position_bias_table""")  )
      rename_keys.append((F"""backbone.stages.{i}.blocks.{j}.attn.w_msa.relative_position_index""", F"""backbone.encoder.layers.{i}.blocks.{j}.attention.self.relative_position_index""")  )
      rename_keys.append((F"""backbone.stages.{i}.blocks.{j}.attn.w_msa.proj.weight""", F"""backbone.encoder.layers.{i}.blocks.{j}.attention.output.dense.weight""")  )
      rename_keys.append((F"""backbone.stages.{i}.blocks.{j}.attn.w_msa.proj.bias""", F"""backbone.encoder.layers.{i}.blocks.{j}.attention.output.dense.bias""")  )
      rename_keys.append((F"""backbone.stages.{i}.blocks.{j}.norm2.weight""", F"""backbone.encoder.layers.{i}.blocks.{j}.layernorm_after.weight""")  )
      rename_keys.append((F"""backbone.stages.{i}.blocks.{j}.norm2.bias""", F"""backbone.encoder.layers.{i}.blocks.{j}.layernorm_after.bias""")  )
      rename_keys.append((F"""backbone.stages.{i}.blocks.{j}.ffn.layers.0.0.weight""", F"""backbone.encoder.layers.{i}.blocks.{j}.intermediate.dense.weight""")  )
      rename_keys.append((F"""backbone.stages.{i}.blocks.{j}.ffn.layers.0.0.bias""", F"""backbone.encoder.layers.{i}.blocks.{j}.intermediate.dense.bias""")  )
      rename_keys.append((F"""backbone.stages.{i}.blocks.{j}.ffn.layers.1.weight""", F"""backbone.encoder.layers.{i}.blocks.{j}.output.dense.weight""")  )
      rename_keys.append((F"""backbone.stages.{i}.blocks.{j}.ffn.layers.1.bias""", F"""backbone.encoder.layers.{i}.blocks.{j}.output.dense.bias""")  )

    if i < 3:
      rename_keys.append((F"""backbone.stages.{i}.downsample.reduction.weight""", F"""backbone.encoder.layers.{i}.downsample.reduction.weight""")  )
      rename_keys.append((F"""backbone.stages.{i}.downsample.norm.weight""", F"""backbone.encoder.layers.{i}.downsample.norm.weight""")  )
      rename_keys.append((F"""backbone.stages.{i}.downsample.norm.bias""", F"""backbone.encoder.layers.{i}.downsample.norm.bias""")  )
    rename_keys.append((F"""backbone.norm{i}.weight""", F"""backbone.hidden_states_norms.stage{i+1}.weight""")  )
    rename_keys.append((F"""backbone.norm{i}.bias""", F"""backbone.hidden_states_norms.stage{i+1}.bias""")  )

  # decode head
  rename_keys.extend(
      [
          ('decode_head.conv_seg.weight', 'decode_head.classifier.weight'),
          ('decode_head.conv_seg.bias', 'decode_head.classifier.bias'),
          ('auxiliary_head.conv_seg.weight', 'auxiliary_head.classifier.weight'),
          ('auxiliary_head.conv_seg.bias', 'auxiliary_head.classifier.bias'),
      ]  )
  # fmt: on

  return rename_keys

def 				SCREAMING_SNAKE_CASE__							(	snake_case__	:Any      ,				snake_case__	:List[Any]      ,				snake_case__	:List[str]  )   ->    Any:
  _lowercase						    =			dct.pop(snake_case__  )
  _lowercase						    =			val

def 				SCREAMING_SNAKE_CASE__							(	snake_case__	:str      ,				snake_case__	:Tuple  )   ->    Union[str, Any]:
  _lowercase						    =			[int(backbone_config.embed_dim * 2**i  ) for i in range(len(backbone_config.depths  )  )]
  for i in range(len(backbone_config.depths  )  ):
    _lowercase						    =			num_features[i]
    for j in range(backbone_config.depths[i]  ):
      # fmt: off
      # read in weights + bias of input projection layer (in original implementation, this is a single matrix + bias)
      _lowercase						    =			state_dict.pop(F"""backbone.stages.{i}.blocks.{j}.attn.w_msa.qkv.weight"""  )
      _lowercase						    =			state_dict.pop(F"""backbone.stages.{i}.blocks.{j}.attn.w_msa.qkv.bias"""  )
      # next, add query, keys and values (in that order) to the state dict
      _lowercase						    =			in_proj_weight[:dim, :]
      _lowercase						    =			in_proj_bias[: dim]
      _lowercase						    =			in_proj_weight[
          dim : dim * 2, :
      ]
      _lowercase						    =			in_proj_bias[
          dim : dim * 2
      ]
      _lowercase						    =			in_proj_weight[
          -dim :, :
      ]
      _lowercase						    =			in_proj_bias[-dim :]
      # fmt: on

def 				SCREAMING_SNAKE_CASE__							(	snake_case__	:str  )   ->    Optional[Any]:
  _lowercase    ,		_lowercase						    =			x.shape
  _lowercase						    =			x.reshape(snake_case__      ,				4      ,				in_channel // 4  )
  _lowercase						    =			x[:, [0, 2, 1, 3], :].transpose(1      ,				2  ).reshape(snake_case__      ,				snake_case__  )
  return x

def 				SCREAMING_SNAKE_CASE__							(	snake_case__	:int  )   ->    List[Any]:
  _lowercase    ,		_lowercase						    =			x.shape
  _lowercase						    =			x.reshape(snake_case__      ,				in_channel // 4      ,				4  )
  _lowercase						    =			x[:, :, [0, 2, 1, 3]].transpose(1      ,				2  ).reshape(snake_case__      ,				snake_case__  )

  return x

def 				SCREAMING_SNAKE_CASE__							(	snake_case__	:str  )   ->    Tuple:
  _lowercase						    =			x.shape[0]
  _lowercase						    =			x.reshape(4      ,				in_channel // 4  )
  _lowercase						    =			x[[0, 2, 1, 3], :].transpose(0      ,				1  ).reshape(snake_case__  )
  return x

def 				SCREAMING_SNAKE_CASE__							(	snake_case__	:List[Any]  )   ->    Any:
  _lowercase						    =			x.shape[0]
  _lowercase						    =			x.reshape(in_channel // 4      ,				4  )
  _lowercase						    =			x[:, [0, 2, 1, 3]].transpose(0      ,				1  ).reshape(snake_case__  )
  return x

def 				SCREAMING_SNAKE_CASE__							(	snake_case__	:Optional[int]      ,				snake_case__	:str      ,				snake_case__	:Optional[Any]  )   ->    Optional[Any]:
  _lowercase						    =			{
      'upernet-swin-tiny': 'https://download.openmmlab.com/mmsegmentation/v0.5/swin/upernet_swin_tiny_patch4_window7_512x512_160k_ade20k_pretrain_224x224_1K/upernet_swin_tiny_patch4_window7_512x512_160k_ade20k_pretrain_224x224_1K_20210531_112542-e380ad3e.pth',
      'upernet-swin-small': 'https://download.openmmlab.com/mmsegmentation/v0.5/swin/upernet_swin_small_patch4_window7_512x512_160k_ade20k_pretrain_224x224_1K/upernet_swin_small_patch4_window7_512x512_160k_ade20k_pretrain_224x224_1K_20210526_192015-ee2fff1c.pth',
      'upernet-swin-base': 'https://download.openmmlab.com/mmsegmentation/v0.5/swin/upernet_swin_base_patch4_window12_512x512_160k_ade20k_pretrain_384x384_22K/upernet_swin_base_patch4_window12_512x512_160k_ade20k_pretrain_384x384_22K_20210531_125459-429057bf.pth',
      'upernet-swin-large': 'https://download.openmmlab.com/mmsegmentation/v0.5/swin/upernet_swin_large_patch4_window12_512x512_pretrain_384x384_22K_160k_ade20k/upernet_swin_large_patch4_window12_512x512_pretrain_384x384_22K_160k_ade20k_20220318_091743-9ba68901.pth',
  }
  _lowercase						    =			model_name_to_url[model_name]
  _lowercase						    =			torch.hub.load_state_dict_from_url(snake_case__      ,				map_location='cpu'      ,				file_name=snake_case__  )[
      'state_dict'
  ]

  for name, param in state_dict.items():
    print(snake_case__      ,				param.shape  )

  _lowercase						    =			get_upernet_config(snake_case__  )
  _lowercase						    =			UperNetForSemanticSegmentation(snake_case__  )
  model.eval()

  # replace "bn" => "batch_norm"
  for key in state_dict.copy().keys():
    _lowercase						    =			state_dict.pop(snake_case__  )
    if "bn" in key:
      _lowercase						    =			key.replace('bn'      ,				'batch_norm'  )
    _lowercase						    =			val

  # rename keys
  _lowercase						    =			create_rename_keys(snake_case__  )
  for src, dest in rename_keys:
    rename_key(snake_case__      ,				snake_case__      ,				snake_case__  )
  read_in_q_k_v(snake_case__      ,				config.backbone_config  )

  # fix downsample parameters
  for key, value in state_dict.items():
    if "downsample" in key:
      if "reduction" in key:
        _lowercase						    =			reverse_correct_unfold_reduction_order(snake_case__  )
      if "norm" in key:
        _lowercase						    =			reverse_correct_unfold_norm_order(snake_case__  )

  model.load_state_dict(snake_case__  )

  # verify on image
  _lowercase						    =			'https://huggingface.co/datasets/hf-internal-testing/fixtures_ade20k/resolve/main/ADE_val_00000001.jpg'
  _lowercase						    =			Image.open(requests.get(snake_case__      ,				stream=snake_case__  ).raw  ).convert('RGB'  )

  _lowercase						    =			SegformerImageProcessor()
  _lowercase						    =			processor(snake_case__      ,				return_tensors='pt'  ).pixel_values

  with torch.no_grad():
    _lowercase						    =			model(snake_case__  )
    _lowercase						    =			outputs.logits

  print(logits.shape  )
  print('First values of logits:'      ,				logits[0, 0, :3, :3]  )
  # assert values
  if model_name == "upernet-swin-tiny":
    _lowercase						    =			torch.tensor(
        [[-7.5958, -7.5958, -7.4302], [-7.5958, -7.5958, -7.4302], [-7.4797, -7.4797, -7.3068]]  )
  elif model_name == "upernet-swin-small":
    _lowercase						    =			torch.tensor(
        [[-7.1921, -7.1921, -6.9532], [-7.1921, -7.1921, -6.9532], [-7.0908, -7.0908, -6.8534]]  )
  elif model_name == "upernet-swin-base":
    _lowercase						    =			torch.tensor(
        [[-6.5851, -6.5851, -6.4330], [-6.5851, -6.5851, -6.4330], [-6.4763, -6.4763, -6.3254]]  )
  elif model_name == "upernet-swin-large":
    _lowercase						    =			torch.tensor(
        [[-7.5297, -7.5297, -7.3802], [-7.5297, -7.5297, -7.3802], [-7.4044, -7.4044, -7.2586]]  )
  print('Logits:'      ,				outputs.logits[0, 0, :3, :3]  )
  assert torch.allclose(outputs.logits[0, 0, :3, :3]      ,				snake_case__      ,				atol=1E-4  )
  print('Looks ok!'  )

  if pytorch_dump_folder_path is not None:
    print(F"""Saving model {model_name} to {pytorch_dump_folder_path}"""  )
    model.save_pretrained(snake_case__  )
    print(F"""Saving processor to {pytorch_dump_folder_path}"""  )
    processor.save_pretrained(snake_case__  )

  if push_to_hub:
    print(F"""Pushing model and processor for {model_name} to hub"""  )
    model.push_to_hub(F"""openmmlab/{model_name}"""  )
    processor.push_to_hub(F"""openmmlab/{model_name}"""  )


if __name__ == "__main__":
      snake_case								=							argparse.ArgumentParser()
      # Required parameters
      parser.add_argument(
          """--model_name""",
          default="""upernet-swin-tiny""",
          type=str,
          choices=[F"""upernet-swin-{size}""" for size in ["""tiny""", """small""", """base""", """large"""]],
          help="""Name of the Swin + UperNet 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."""
      )
      parser.add_argument(
          """--push_to_hub""", action="""store_true""", help="""Whether or not to push the converted model to the 🤗 hub."""
      )

      snake_case								=							parser.parse_args()
      convert_upernet_checkpoint(args.model_name, args.pytorch_dump_folder_path, args.push_to_hub)


_UpperCAmelCase						:  int									=			range(2, 20 + 1)
_UpperCAmelCase						:  Dict									=			[10**k for k in range(ks[-1] + 1)]
_UpperCAmelCase						:  dict[int, dict[int, list[list[int]]]]									=			{}





def    __lowerCamelCase      (					UpperCamelCase__  ,				UpperCamelCase__  ,				UpperCamelCase__  ,				UpperCamelCase__ ):







							'''simple docstring'''






							snake_case_     							=       sum(a_i[j] for j in range(UpperCamelCase__  ,				len(UpperCamelCase__ ) ) )
							snake_case_     							=       sum(a_i[j] * base[j] for j in range(min(len(UpperCamelCase__ )  ,				UpperCamelCase__ ) ) )

							snake_case_							,       snake_case_     							=       0, 0
							snake_case_     							=       n - i

							snake_case_     							=       memo.get(UpperCamelCase__ )

							if sub_memo is not None:
														snake_case_     							=       sub_memo.get(UpperCamelCase__ )

														if jumps is not None and len(UpperCamelCase__ ) > 0:
																					# find and make the largest jump without going over
																					snake_case_     							=       -1
																					for _k in range(len(UpperCamelCase__ ) - 1  ,				-1  ,				-1 ):
																												if jumps[_k][2] <= k and jumps[_k][1] <= max_dn:
																																			snake_case_     							=       _k
																																			break

																					if max_jump >= 0:
																												snake_case_							,       snake_case_							,       snake_case_     							=       jumps[max_jump]
																												# since the difference between jumps is cached, add c
																												snake_case_     							=       diff + c
																												for j in range(min(UpperCamelCase__  ,				len(UpperCamelCase__ ) ) ):
																																			snake_case_							,       snake_case_     							=       divmod(UpperCamelCase__  ,				10 )
																												if new_c > 0:
																																			add(UpperCamelCase__  ,				UpperCamelCase__  ,				UpperCamelCase__ )

														else:
																					snake_case_     							=       []
							else:
														snake_case_     							=       {c: []}
														snake_case_     							=       sub_memo

							if dn >= max_dn or c + diff >= base[k]:
														return diff, dn

							if k > ks[0]:
														while True:
																					# keep doing smaller jumps
																					snake_case_							,       snake_case_     							=       next_term(UpperCamelCase__  ,				k - 1  ,				i + dn  ,				UpperCamelCase__ )
																					diff += _diff
																					dn += terms_jumped

																					if dn >= max_dn or c + diff >= base[k]:
																												break
							else:
														# would be too small a jump, just compute sequential terms instead
														snake_case_							,       snake_case_     							=       compute(UpperCamelCase__  ,				UpperCamelCase__  ,				i + dn  ,				UpperCamelCase__ )
														diff += _diff
														dn += terms_jumped

							snake_case_     							=       sub_memo[c]

							# keep jumps sorted by # of terms skipped
							snake_case_     							=       0
							while j < len(UpperCamelCase__ ):
														if jumps[j][1] > dn:
																					break
														j += 1

							# cache the jump for this value digitsum(b) and c
							sub_memo[c].insert(UpperCamelCase__  ,				(diff, dn, k) )
							return (diff, dn)





def    __lowerCamelCase      (					UpperCamelCase__  ,				UpperCamelCase__  ,				UpperCamelCase__  ,				UpperCamelCase__ ):







							'''simple docstring'''






							if i >= n:
														return 0, i
							if k > len(UpperCamelCase__ ):
														a_i.extend([0 for _ in range(k - len(UpperCamelCase__ ) )] )

							# note: a_i -> b * 10^k + c
							# ds_b -> digitsum(b)
							# ds_c -> digitsum(c)
							snake_case_     							=       i
							snake_case_							,       snake_case_							,       snake_case_     							=       0, 0, 0
							for j in range(len(UpperCamelCase__ ) ):
														if j >= k:
																					ds_b += a_i[j]
														else:
																					ds_c += a_i[j]

							while i < n:
														i += 1
														snake_case_     							=       ds_c + ds_b
														diff += addend
														snake_case_     							=       0
														for j in range(UpperCamelCase__ ):
																					snake_case_     							=       a_i[j] + addend
																					snake_case_							,       snake_case_     							=       divmod(UpperCamelCase__  ,				10 )

																					ds_c += a_i[j]

														if addend > 0:
																					break

							if addend > 0:
														add(UpperCamelCase__  ,				UpperCamelCase__  ,				UpperCamelCase__ )
							return diff, i - start_i





def    __lowerCamelCase      (					UpperCamelCase__  ,				UpperCamelCase__  ,				UpperCamelCase__ ):







							'''simple docstring'''






							for j in range(UpperCamelCase__  ,				len(UpperCamelCase__ ) ):
														snake_case_     							=       digits[j] + addend
														if s >= 10:
																					snake_case_							,       snake_case_     							=       divmod(UpperCamelCase__  ,				10 )
																					snake_case_     							=       addend // 10 + quotient
														else:
																					snake_case_     							=       s
																					snake_case_     							=       addend // 10

														if addend == 0:
																					break

							while addend > 0:
														snake_case_							,       snake_case_     							=       divmod(UpperCamelCase__  ,				10 )
														digits.append(UpperCamelCase__ )





def    __lowerCamelCase      (					UpperCamelCase__ = 10**15 ):







							'''simple docstring'''






							snake_case_     							=       [1]
							snake_case_     							=       1
							snake_case_     							=       0
							while True:
														snake_case_							,       snake_case_     							=       next_term(UpperCamelCase__  ,				20  ,				i + dn  ,				UpperCamelCase__ )
														dn += terms_jumped
														if dn == n - i:
																					break

							snake_case_     							=       0
							for j in range(len(UpperCamelCase__ ) ):
														a_n += digits[j] * 10**j
							return a_n


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




