

import argparse
import json
import pickle
from pathlib import Path

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

from transformers import MaskFormerConfig, MaskFormerForInstanceSegmentation, MaskFormerImageProcessor, SwinConfig
from transformers.utils import logging


logging.set_verbosity_info()
lowerCAmelCase__								=		logging.get_logger(__name__)






def 					lowerCamelCase_     (							UpperCAmelCase_							:     str	)						->				Optional[Any]:




	'''simple docstring'''




	_UpperCamelCase   :		Optional[Any]			=						SwinConfig.from_pretrained(
	    'microsoft/swin-tiny-patch4-window7-224'							,       out_features=['stage1', 'stage2', 'stage3', 'stage4']	)
	_UpperCamelCase   :		int			=						MaskFormerConfig(backbone_config=UpperCAmelCase_	)

	_UpperCamelCase   :		Optional[Any]			=						'huggingface/label-files'
	if "ade20k-full" in model_name:
		# this should be ok
		_UpperCamelCase   :		Tuple			=						8_4_7
		_UpperCamelCase   :		int			=						'maskformer-ade20k-full-id2label.json'
	elif "ade" in model_name:
		# this should be ok
		_UpperCamelCase   :		int			=						1_5_0
		_UpperCamelCase   :		str			=						'ade20k-id2label.json'
	elif "coco-stuff" in model_name:
		# this should be ok
		_UpperCamelCase   :		List[Any]			=						1_7_1
		_UpperCamelCase   :		List[str]			=						'maskformer-coco-stuff-id2label.json'
	elif "coco" in model_name:
		# TODO
		_UpperCamelCase   :		str			=						1_3_3
		_UpperCamelCase   :		Union[str, Any]			=						'coco-panoptic-id2label.json'
	elif "cityscapes" in model_name:
		# this should be ok
		_UpperCamelCase   :		Dict			=						1_9
		_UpperCamelCase   :		Optional[Any]			=						'cityscapes-id2label.json'
	elif "vistas" in model_name:
		# this should be ok
		_UpperCamelCase   :		int			=						6_5
		_UpperCamelCase   :		Optional[int]			=						'mapillary-vistas-id2label.json'

	_UpperCamelCase   :		Union[str, Any]			=						json.load(open(hf_hub_download(UpperCAmelCase_							,       UpperCAmelCase_							,       repo_type='dataset'	)							,       'r'	)	)
	_UpperCamelCase   :		List[str]			=						{int(UpperCAmelCase_	): v for k, v in idalabel.items()}

	return config






def 					lowerCamelCase_     (							UpperCAmelCase_							:     str	)						->				Dict:




	'''simple docstring'''




	_UpperCamelCase   :		Optional[int]			=						[]
	# stem
	# fmt: off
	rename_keys.append(('backbone.patch_embed.proj.weight', 'model.pixel_level_module.encoder.model.embeddings.patch_embeddings.projection.weight')	)
	rename_keys.append(('backbone.patch_embed.proj.bias', 'model.pixel_level_module.encoder.model.embeddings.patch_embeddings.projection.bias')	)
	rename_keys.append(('backbone.patch_embed.norm.weight', 'model.pixel_level_module.encoder.model.embeddings.norm.weight')	)
	rename_keys.append(('backbone.patch_embed.norm.bias', 'model.pixel_level_module.encoder.model.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.layers.{i}.blocks.{j}.norm1.weight''', F'''model.pixel_level_module.encoder.model.encoder.layers.{i}.blocks.{j}.layernorm_before.weight''')	)
			rename_keys.append((F'''backbone.layers.{i}.blocks.{j}.norm1.bias''', F'''model.pixel_level_module.encoder.model.encoder.layers.{i}.blocks.{j}.layernorm_before.bias''')	)
			rename_keys.append((F'''backbone.layers.{i}.blocks.{j}.attn.relative_position_bias_table''', F'''model.pixel_level_module.encoder.model.encoder.layers.{i}.blocks.{j}.attention.self.relative_position_bias_table''')	)
			rename_keys.append((F'''backbone.layers.{i}.blocks.{j}.attn.relative_position_index''', F'''model.pixel_level_module.encoder.model.encoder.layers.{i}.blocks.{j}.attention.self.relative_position_index''')	)
			rename_keys.append((F'''backbone.layers.{i}.blocks.{j}.attn.proj.weight''', F'''model.pixel_level_module.encoder.model.encoder.layers.{i}.blocks.{j}.attention.output.dense.weight''')	)
			rename_keys.append((F'''backbone.layers.{i}.blocks.{j}.attn.proj.bias''', F'''model.pixel_level_module.encoder.model.encoder.layers.{i}.blocks.{j}.attention.output.dense.bias''')	)
			rename_keys.append((F'''backbone.layers.{i}.blocks.{j}.norm2.weight''', F'''model.pixel_level_module.encoder.model.encoder.layers.{i}.blocks.{j}.layernorm_after.weight''')	)
			rename_keys.append((F'''backbone.layers.{i}.blocks.{j}.norm2.bias''', F'''model.pixel_level_module.encoder.model.encoder.layers.{i}.blocks.{j}.layernorm_after.bias''')	)
			rename_keys.append((F'''backbone.layers.{i}.blocks.{j}.mlp.fc1.weight''', F'''model.pixel_level_module.encoder.model.encoder.layers.{i}.blocks.{j}.intermediate.dense.weight''')	)
			rename_keys.append((F'''backbone.layers.{i}.blocks.{j}.mlp.fc1.bias''', F'''model.pixel_level_module.encoder.model.encoder.layers.{i}.blocks.{j}.intermediate.dense.bias''')	)
			rename_keys.append((F'''backbone.layers.{i}.blocks.{j}.mlp.fc2.weight''', F'''model.pixel_level_module.encoder.model.encoder.layers.{i}.blocks.{j}.output.dense.weight''')	)
			rename_keys.append((F'''backbone.layers.{i}.blocks.{j}.mlp.fc2.bias''', F'''model.pixel_level_module.encoder.model.encoder.layers.{i}.blocks.{j}.output.dense.bias''')	)

		if i < 3:
			rename_keys.append((F'''backbone.layers.{i}.downsample.reduction.weight''', F'''model.pixel_level_module.encoder.model.encoder.layers.{i}.downsample.reduction.weight''')	)
			rename_keys.append((F'''backbone.layers.{i}.downsample.norm.weight''', F'''model.pixel_level_module.encoder.model.encoder.layers.{i}.downsample.norm.weight''')	)
			rename_keys.append((F'''backbone.layers.{i}.downsample.norm.bias''', F'''model.pixel_level_module.encoder.model.encoder.layers.{i}.downsample.norm.bias''')	)
		rename_keys.append((F'''backbone.norm{i}.weight''', F'''model.pixel_level_module.encoder.hidden_states_norms.{i}.weight''')	)
		rename_keys.append((F'''backbone.norm{i}.bias''', F'''model.pixel_level_module.encoder.hidden_states_norms.{i}.bias''')	)

	# FPN
	rename_keys.append(('sem_seg_head.layer_4.weight', 'model.pixel_level_module.decoder.fpn.stem.0.weight')	)
	rename_keys.append(('sem_seg_head.layer_4.norm.weight', 'model.pixel_level_module.decoder.fpn.stem.1.weight')	)
	rename_keys.append(('sem_seg_head.layer_4.norm.bias', 'model.pixel_level_module.decoder.fpn.stem.1.bias')	)
	for source_index, target_index in zip(range(3							,       0							,       -1	)							,       range(0							,       3	)	):
		rename_keys.append((F'''sem_seg_head.adapter_{source_index}.weight''', F'''model.pixel_level_module.decoder.fpn.layers.{target_index}.proj.0.weight''')	)
		rename_keys.append((F'''sem_seg_head.adapter_{source_index}.norm.weight''', F'''model.pixel_level_module.decoder.fpn.layers.{target_index}.proj.1.weight''')	)
		rename_keys.append((F'''sem_seg_head.adapter_{source_index}.norm.bias''', F'''model.pixel_level_module.decoder.fpn.layers.{target_index}.proj.1.bias''')	)
		rename_keys.append((F'''sem_seg_head.layer_{source_index}.weight''', F'''model.pixel_level_module.decoder.fpn.layers.{target_index}.block.0.weight''')	)
		rename_keys.append((F'''sem_seg_head.layer_{source_index}.norm.weight''', F'''model.pixel_level_module.decoder.fpn.layers.{target_index}.block.1.weight''')	)
		rename_keys.append((F'''sem_seg_head.layer_{source_index}.norm.bias''', F'''model.pixel_level_module.decoder.fpn.layers.{target_index}.block.1.bias''')	)
	rename_keys.append(('sem_seg_head.mask_features.weight', 'model.pixel_level_module.decoder.mask_projection.weight')	)
	rename_keys.append(('sem_seg_head.mask_features.bias', 'model.pixel_level_module.decoder.mask_projection.bias')	)

	# Transformer decoder
	for idx in range(config.decoder_config.decoder_layers	):
		# self-attention out projection
		rename_keys.append((F'''sem_seg_head.predictor.transformer.decoder.layers.{idx}.self_attn.out_proj.weight''', F'''model.transformer_module.decoder.layers.{idx}.self_attn.out_proj.weight''')	)
		rename_keys.append((F'''sem_seg_head.predictor.transformer.decoder.layers.{idx}.self_attn.out_proj.bias''', F'''model.transformer_module.decoder.layers.{idx}.self_attn.out_proj.bias''')	)
		# cross-attention out projection
		rename_keys.append((F'''sem_seg_head.predictor.transformer.decoder.layers.{idx}.multihead_attn.out_proj.weight''', F'''model.transformer_module.decoder.layers.{idx}.encoder_attn.out_proj.weight''')	)
		rename_keys.append((F'''sem_seg_head.predictor.transformer.decoder.layers.{idx}.multihead_attn.out_proj.bias''', F'''model.transformer_module.decoder.layers.{idx}.encoder_attn.out_proj.bias''')	)
		# MLP 1
		rename_keys.append((F'''sem_seg_head.predictor.transformer.decoder.layers.{idx}.linear1.weight''', F'''model.transformer_module.decoder.layers.{idx}.fc1.weight''')	)
		rename_keys.append((F'''sem_seg_head.predictor.transformer.decoder.layers.{idx}.linear1.bias''', F'''model.transformer_module.decoder.layers.{idx}.fc1.bias''')	)
		# MLP 2
		rename_keys.append((F'''sem_seg_head.predictor.transformer.decoder.layers.{idx}.linear2.weight''', F'''model.transformer_module.decoder.layers.{idx}.fc2.weight''')	)
		rename_keys.append((F'''sem_seg_head.predictor.transformer.decoder.layers.{idx}.linear2.bias''', F'''model.transformer_module.decoder.layers.{idx}.fc2.bias''')	)
		# layernorm 1 (self-attention layernorm)
		rename_keys.append((F'''sem_seg_head.predictor.transformer.decoder.layers.{idx}.norm1.weight''', F'''model.transformer_module.decoder.layers.{idx}.self_attn_layer_norm.weight''')	)
		rename_keys.append((F'''sem_seg_head.predictor.transformer.decoder.layers.{idx}.norm1.bias''', F'''model.transformer_module.decoder.layers.{idx}.self_attn_layer_norm.bias''')	)
		# layernorm 2 (cross-attention layernorm)
		rename_keys.append((F'''sem_seg_head.predictor.transformer.decoder.layers.{idx}.norm2.weight''', F'''model.transformer_module.decoder.layers.{idx}.encoder_attn_layer_norm.weight''')	)
		rename_keys.append((F'''sem_seg_head.predictor.transformer.decoder.layers.{idx}.norm2.bias''', F'''model.transformer_module.decoder.layers.{idx}.encoder_attn_layer_norm.bias''')	)
		# layernorm 3 (final layernorm)
		rename_keys.append((F'''sem_seg_head.predictor.transformer.decoder.layers.{idx}.norm3.weight''', F'''model.transformer_module.decoder.layers.{idx}.final_layer_norm.weight''')	)
		rename_keys.append((F'''sem_seg_head.predictor.transformer.decoder.layers.{idx}.norm3.bias''', F'''model.transformer_module.decoder.layers.{idx}.final_layer_norm.bias''')	)

	rename_keys.append(('sem_seg_head.predictor.transformer.decoder.norm.weight', 'model.transformer_module.decoder.layernorm.weight')	)
	rename_keys.append(('sem_seg_head.predictor.transformer.decoder.norm.bias', 'model.transformer_module.decoder.layernorm.bias')	)

	# heads on top
	rename_keys.append(('sem_seg_head.predictor.query_embed.weight', 'model.transformer_module.queries_embedder.weight')	)

	rename_keys.append(('sem_seg_head.predictor.input_proj.weight', 'model.transformer_module.input_projection.weight')	)
	rename_keys.append(('sem_seg_head.predictor.input_proj.bias', 'model.transformer_module.input_projection.bias')	)

	rename_keys.append(('sem_seg_head.predictor.class_embed.weight', 'class_predictor.weight')	)
	rename_keys.append(('sem_seg_head.predictor.class_embed.bias', 'class_predictor.bias')	)

	for i in range(3	):
		rename_keys.append((F'''sem_seg_head.predictor.mask_embed.layers.{i}.weight''', F'''mask_embedder.{i}.0.weight''')	)
		rename_keys.append((F'''sem_seg_head.predictor.mask_embed.layers.{i}.bias''', F'''mask_embedder.{i}.0.bias''')	)
	# fmt: on

	return rename_keys






def 					lowerCamelCase_     (							UpperCAmelCase_							:     Any							,       UpperCAmelCase_							:     Union[str, Any]							,       UpperCAmelCase_							:     Tuple	)						->				Union[str, Any]:




	'''simple docstring'''




	_UpperCamelCase   :		Optional[int]			=						dct.pop(UpperCAmelCase_	)
	_UpperCamelCase   :		Optional[Any]			=						val






def 					lowerCamelCase_     (							UpperCAmelCase_							:     Optional[Any]							,       UpperCAmelCase_							:     Dict	)						->				Dict:




	'''simple docstring'''




	_UpperCamelCase   :		Union[str, Any]			=						[int(backbone_config.embed_dim * 2**i	) for i in range(len(backbone_config.depths	)	)]
	for i in range(len(backbone_config.depths	)	):
		_UpperCamelCase   :		Optional[int]			=						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)
			_UpperCamelCase   :		Optional[int]			=						state_dict.pop(F'''backbone.layers.{i}.blocks.{j}.attn.qkv.weight'''	)
			_UpperCamelCase   :		Union[str, Any]			=						state_dict.pop(F'''backbone.layers.{i}.blocks.{j}.attn.qkv.bias'''	)
			# next, add query, keys and values (in that order) to the state dict
			_UpperCamelCase   :		int			=						in_proj_weight[:dim, :]
			_UpperCamelCase   :		Union[str, Any]			=						in_proj_bias[: dim]
			_UpperCamelCase   :		Dict			=						in_proj_weight[
			    dim : dim * 2, :
			]
			_UpperCamelCase   :		Union[str, Any]			=						in_proj_bias[
			    dim : dim * 2
			]
			_UpperCamelCase   :		Tuple			=						in_proj_weight[
			    -dim :, :
			]
			_UpperCamelCase   :		Dict			=						in_proj_bias[-dim :]
			# fmt: on






def 					lowerCamelCase_     (							UpperCAmelCase_							:     str							,       UpperCAmelCase_							:     Optional[int]	)						->				Optional[Any]:




	'''simple docstring'''




	_UpperCamelCase   :		str			=						config.decoder_config.hidden_size
	for idx in range(config.decoder_config.decoder_layers	):
		# read in weights + bias of self-attention input projection layer (in the original implementation, this is a single matrix + bias)
		_UpperCamelCase   :		Tuple			=						state_dict.pop(F'''sem_seg_head.predictor.transformer.decoder.layers.{idx}.self_attn.in_proj_weight'''	)
		_UpperCamelCase   :		Any			=						state_dict.pop(F'''sem_seg_head.predictor.transformer.decoder.layers.{idx}.self_attn.in_proj_bias'''	)
		# next, add query, keys and values (in that order) to the state dict
		_UpperCamelCase   :		Tuple			=						in_proj_weight[: hidden_size, :]
		_UpperCamelCase   :		Union[str, Any]			=						in_proj_bias[:config.hidden_size]
		_UpperCamelCase   :		List[Any]			=						in_proj_weight[hidden_size : hidden_size * 2, :]
		_UpperCamelCase   :		int			=						in_proj_bias[hidden_size : hidden_size * 2]
		_UpperCamelCase   :		Any			=						in_proj_weight[-hidden_size :, :]
		_UpperCamelCase   :		int			=						in_proj_bias[-hidden_size :]
		# read in weights + bias of cross-attention input projection layer (in the original implementation, this is a single matrix + bias)
		_UpperCamelCase   :		Optional[Any]			=						state_dict.pop(F'''sem_seg_head.predictor.transformer.decoder.layers.{idx}.multihead_attn.in_proj_weight'''	)
		_UpperCamelCase   :		Dict			=						state_dict.pop(F'''sem_seg_head.predictor.transformer.decoder.layers.{idx}.multihead_attn.in_proj_bias'''	)
		# next, add query, keys and values (in that order) to the state dict
		_UpperCamelCase   :		int			=						in_proj_weight[: hidden_size, :]
		_UpperCamelCase   :		int			=						in_proj_bias[:config.hidden_size]
		_UpperCamelCase   :		str			=						in_proj_weight[hidden_size : hidden_size * 2, :]
		_UpperCamelCase   :		Optional[int]			=						in_proj_bias[hidden_size : hidden_size * 2]
		_UpperCamelCase   :		Dict			=						in_proj_weight[-hidden_size :, :]
		_UpperCamelCase   :		Optional[Any]			=						in_proj_bias[-hidden_size :]
	# fmt: on






def 					lowerCamelCase_     (							)						->				torch.Tensor:




	'''simple docstring'''




	_UpperCamelCase   :		Optional[Any]			=						'http://images.cocodataset.org/val2017/000000039769.jpg'
	_UpperCamelCase   :		Tuple			=						Image.open(requests.get(UpperCAmelCase_							,       stream=UpperCAmelCase_	).raw	)
	return im






@torch.no_grad()
def 					lowerCamelCase_     (							UpperCAmelCase_							:     str							,       UpperCAmelCase_							:     str							,       UpperCAmelCase_							:     str							,       UpperCAmelCase_							:     bool = False	)						->				Optional[Any]:




	'''simple docstring'''




	_UpperCamelCase   :		Optional[int]			=						get_maskformer_config(UpperCAmelCase_	)

	# load original state_dict
	with open(UpperCAmelCase_							,       'rb'	) as f:
		_UpperCamelCase   :		Dict			=						pickle.load(UpperCAmelCase_	)
	_UpperCamelCase   :		Union[str, Any]			=						data['model']

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

	# rename keys
	_UpperCamelCase   :		Dict			=						create_rename_keys(UpperCAmelCase_	)
	for src, dest in rename_keys:
		rename_key(UpperCAmelCase_							,       UpperCAmelCase_							,       UpperCAmelCase_	)
	read_in_swin_q_k_v(UpperCAmelCase_							,       config.backbone_config	)
	read_in_decoder_q_k_v(UpperCAmelCase_							,       UpperCAmelCase_	)

	# update to torch tensors
	for key, value in state_dict.items():
		_UpperCamelCase   :		List[Any]			=						torch.from_numpy(UpperCAmelCase_	)

	# load 🤗 model
	_UpperCamelCase   :		str			=						MaskFormerForInstanceSegmentation(UpperCAmelCase_	)
	model.eval()

	for name, param in model.named_parameters():
		print(UpperCAmelCase_							,       param.shape	)

	_UpperCamelCase	,		_UpperCamelCase   :		List[Any]			=						model.load_state_dict(UpperCAmelCase_							,       strict=UpperCAmelCase_	)
	assert missing_keys == [
	    "model.pixel_level_module.encoder.model.layernorm.weight",
	    "model.pixel_level_module.encoder.model.layernorm.bias",
	]
	assert len(UpperCAmelCase_	) == 0, F'''Unexpected keys: {unexpected_keys}'''

	# verify results
	_UpperCamelCase   :		Optional[int]			=						prepare_img()
	if "vistas" in model_name:
		_UpperCamelCase   :		Union[str, Any]			=						6_5
	elif "cityscapes" in model_name:
		_UpperCamelCase   :		Union[str, Any]			=						6_5_5_3_5
	else:
		_UpperCamelCase   :		List[Any]			=						2_5_5
	_UpperCamelCase   :		Optional[Any]			=						True if 'ade' in model_name else False
	_UpperCamelCase   :		Any			=						MaskFormerImageProcessor(ignore_index=UpperCAmelCase_							,       reduce_labels=UpperCAmelCase_	)

	_UpperCamelCase   :		Optional[Any]			=						image_processor(UpperCAmelCase_							,       return_tensors='pt'	)

	_UpperCamelCase   :		Optional[int]			=						model(**UpperCAmelCase_	)

	print('Logits:'							,       outputs.class_queries_logits[0, :3, :3]	)

	if model_name == "maskformer-swin-tiny-ade":
		_UpperCamelCase   :		Tuple			=						torch.tensor(
		    [[3.6_3_5_3, -4.4_7_7_0, -2.6_0_6_5], [0.5_0_8_1, -4.2_3_9_4, -3.5_3_4_3], [2.1_9_0_9, -5.0_3_5_3, -1.9_3_2_3]]	)
	assert torch.allclose(outputs.class_queries_logits[0, :3, :3]							,       UpperCAmelCase_							,       atol=1e-4	)
	print('Looks ok!'	)

	if pytorch_dump_folder_path is not None:
		print(F'''Saving model and image processor to {pytorch_dump_folder_path}'''	)
		Path(UpperCAmelCase_	).mkdir(exist_ok=UpperCAmelCase_	)
		model.save_pretrained(UpperCAmelCase_	)
		image_processor.save_pretrained(UpperCAmelCase_	)

	if push_to_hub:
		print('Pushing model and image processor to the hub...'	)
		model.push_to_hub(F'''nielsr/{model_name}'''	)
		image_processor.push_to_hub(F'''nielsr/{model_name}'''	)


if __name__ == "__main__":
							lowerCAmelCase__								=		argparse.ArgumentParser()
							# Required parameters
							parser.add_argument(
							    """--model_name""",
							    default="""maskformer-swin-tiny-ade""",
							    type=str,
							    help=("""Name of the MaskFormer model you'd like to convert""",),
							)
							parser.add_argument(
							    """--checkpoint_path""",
							    default="""/Users/nielsrogge/Documents/MaskFormer_checkpoints/MaskFormer-Swin-tiny-ADE20k/model.pkl""",
							    type=str,
							    help="""Path to the original state dict (.pth file).""",
							)
							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."""
							)

							lowerCAmelCase__								=		parser.parse_args()
							convert_maskformer_checkpoint(
							    args.model_name, args.checkpoint_path, args.pytorch_dump_folder_path, args.push_to_hub
							)







from __future__ import annotations

import matplotlib.pyplot as plt  # type: ignore
import numpy

# initial triangle of Koch snowflake
lowerCAmelCase__								=		numpy.array([0, 0])
lowerCAmelCase__								=		numpy.array([0.5, 0.8_66_02_54])
lowerCAmelCase__								=		numpy.array([1, 0])
lowerCAmelCase__								=		[VECTOR_1, VECTOR_2, VECTOR_3, VECTOR_1]






def 					lowerCamelCase_     (							UpperCAmelCase_							:     list[numpy.ndarray]							,       UpperCAmelCase_							:     int	)						->				list[numpy.ndarray]:




	'''simple docstring'''




	_UpperCamelCase   :		Tuple			=						initial_vectors
	for _ in range(UpperCAmelCase_	):
		_UpperCamelCase   :		str			=						iteration_step(UpperCAmelCase_	)
	return vectors






def 					lowerCamelCase_     (							UpperCAmelCase_							:     list[numpy.ndarray]	)						->				list[numpy.ndarray]:




	'''simple docstring'''




	_UpperCamelCase   :		int			=						[]
	for i, start_vector in enumerate(vectors[:-1]	):
		_UpperCamelCase   :		Union[str, Any]			=						vectors[i + 1]
		new_vectors.append(UpperCAmelCase_	)
		_UpperCamelCase   :		Tuple			=						end_vector - start_vector
		new_vectors.append(start_vector + difference_vector / 3	)
		new_vectors.append(
		    start_vector + difference_vector / 3 + rotate(difference_vector / 3							,       6_0	)	)
		new_vectors.append(start_vector + difference_vector * 2 / 3	)
	new_vectors.append(vectors[-1]	)
	return new_vectors






def 					lowerCamelCase_     (							UpperCAmelCase_							:     numpy.ndarray							,       UpperCAmelCase_							:     float	)						->				numpy.ndarray:




	'''simple docstring'''




	_UpperCamelCase   :		str			=						numpy.radians(UpperCAmelCase_	)
	_UpperCamelCase	,		_UpperCamelCase   :		Optional[Any]			=						numpy.cos(UpperCAmelCase_	), numpy.sin(UpperCAmelCase_	)
	_UpperCamelCase   :		Any			=						numpy.array(((c, -s), (s, c))	)
	return numpy.dot(UpperCAmelCase_							,       UpperCAmelCase_	)






def 					lowerCamelCase_     (							UpperCAmelCase_							:     list[numpy.ndarray]	)						->				None:




	'''simple docstring'''




	_UpperCamelCase   :		str			=						plt.gca()
	axes.set_aspect('equal'	)

	# matplotlib.pyplot.plot takes a list of all x-coordinates and a list of all
	# y-coordinates as inputs, which are constructed from the vector-list using
	# zip()
	_UpperCamelCase	,		_UpperCamelCase   :		Dict			=						zip(*UpperCAmelCase_	)
	plt.plot(UpperCAmelCase_							,       UpperCAmelCase_	)
	plt.show()


if __name__ == "__main__":
							import doctest

							doctest.testmod()

							lowerCAmelCase__								=		iterate(INITIAL_VECTORS, 5)
							plot(processed_vectors)




