




import gc
import random
import unittest

import numpy as np
import torch

from diffusers import (
    DDIMScheduler,
    KandinskyVaaControlnetPipeline,
    KandinskyVaaPriorPipeline,
    UNetaDConditionModel,
    VQModel,
)
from diffusers.utils import floats_tensor, load_image, load_numpy, slow, torch_device
from diffusers.utils.testing_utils import enable_full_determinism, require_torch_gpu

from ..test_pipelines_common import PipelineTesterMixin, assert_mean_pixel_difference


enable_full_determinism()




class 						__lowercase		(__UpperCamelCase     ,		unittest.TestCase							):




      """simple docstring"""





      _snake_case							     =						KandinskyVaaControlnetPipeline
      _snake_case							     =						["""image_embeds""", """negative_image_embeds""", """hint"""]
      _snake_case							     =						["""image_embeds""", """negative_image_embeds""", """hint"""]
      _snake_case							     =						[
          """generator""",
          """height""",
          """width""",
          """latents""",
          """guidance_scale""",
          """num_inference_steps""",
          """return_dict""",
          """guidance_scale""",
          """num_images_per_prompt""",
          """output_type""",
          """return_dict""",
      ]
      _snake_case							     =						False

      @property
      def 	UpperCAmelCase      (      self	)		->				List[Any]:
         return 3_2

      @property
      def 	UpperCAmelCase      (      self	)		->				str:
         return 3_2

      @property
      def 	UpperCAmelCase      (      self	)		->				Tuple:
         return self.time_input_dim

      @property
      def 	UpperCAmelCase      (      self	)		->				Any:
         return self.time_input_dim * 4

      @property
      def 	UpperCAmelCase      (      self	)		->				int:
         return 1_0_0

      @property
      def 	UpperCAmelCase      (      self	)		->				Union[str, Any]:
         torch.manual_seed(0	)

         snake_case      :				List[str]				=       {
             'in_channels': 8,
             # Out channels is double in channels because predicts mean and variance
             'out_channels': 8,
             'addition_embed_type': 'image_hint',
             'down_block_types': ('ResnetDownsampleBlock2D', 'SimpleCrossAttnDownBlock2D'),
             'up_block_types': ('SimpleCrossAttnUpBlock2D', 'ResnetUpsampleBlock2D'),
             'mid_block_type': 'UNetMidBlock2DSimpleCrossAttn',
             'block_out_channels': (self.block_out_channels_a, self.block_out_channels_a * 2),
             'layers_per_block': 1,
             'encoder_hid_dim': self.text_embedder_hidden_size,
             'encoder_hid_dim_type': 'image_proj',
             'cross_attention_dim': self.cross_attention_dim,
             'attention_head_dim': 4,
             'resnet_time_scale_shift': 'scale_shift',
             'class_embed_type': None,
         }

         snake_case      :				Dict				=       UNetaDConditionModel(**A	)
         return model

      @property
      def 	UpperCAmelCase      (      self	)		->				Optional[int]:
         return {
             "block_out_channels": [3_2, 3_2, 6_4, 6_4],
             "down_block_types": [
                 "DownEncoderBlock2D",
                 "DownEncoderBlock2D",
                 "DownEncoderBlock2D",
                 "AttnDownEncoderBlock2D",
             ],
             "in_channels": 3,
             "latent_channels": 4,
             "layers_per_block": 1,
             "norm_num_groups": 8,
             "norm_type": "spatial",
             "num_vq_embeddings": 1_2,
             "out_channels": 3,
             "up_block_types": ["AttnUpDecoderBlock2D", "UpDecoderBlock2D", "UpDecoderBlock2D", "UpDecoderBlock2D"],
             "vq_embed_dim": 4,
         }

      @property
      def 	UpperCAmelCase      (      self	)		->				List[str]:
         torch.manual_seed(0	)
         snake_case      :				Optional[Any]				=       VQModel(**self.dummy_movq_kwargs	)
         return model

      def 	UpperCAmelCase      (      self	)		->				Dict:
         snake_case      :				Optional[Any]				=       self.dummy_unet
         snake_case      :				str				=       self.dummy_movq

         snake_case      :				Optional[Any]				=       DDIMScheduler(
             num_train_timesteps=1_0_0_0				,      beta_schedule="""linear"""				,      beta_start=0.0_00_85				,      beta_end=0.0_12				,      clip_sample=A				,      set_alpha_to_one=A				,      steps_offset=1				,      prediction_type="""epsilon"""				,      thresholding=A				,      )

         snake_case      :				Optional[Any]				=       {
             'unet': unet,
             'scheduler': scheduler,
             'movq': movq,
         }
         return components

      def 	UpperCAmelCase      (      self				,      A				,      A=0	)		->				List[Any]:
         snake_case      :				Any				=       floats_tensor((1, self.text_embedder_hidden_size)				,      rng=random.Random(A	)	).to(A	)
         snake_case      :				Dict				=       floats_tensor((1, self.text_embedder_hidden_size)				,      rng=random.Random(seed + 1	)	).to(
             A	)

         # create hint
         snake_case      :				Any				=       floats_tensor((1, 3, 6_4, 6_4)				,      rng=random.Random(A	)	).to(A	)

         if str(A	).startswith("""mps"""	):
            snake_case      :				Dict				=       torch.manual_seed(A	)
         else:
            snake_case      :				List[str]				=       torch.Generator(device=A	).manual_seed(A	)
         snake_case      :				Optional[Any]				=       {
             'image_embeds': image_embeds,
             'negative_image_embeds': negative_image_embeds,
             'hint': hint,
             'generator': generator,
             'height': 6_4,
             'width': 6_4,
             'guidance_scale': 4.0,
             'num_inference_steps': 2,
             'output_type': 'np',
         }
         return inputs

      def 	UpperCAmelCase      (      self	)		->				Any:
         snake_case      :				int				=       'cpu'

         snake_case      :				List[str]				=       self.get_dummy_components()

         snake_case      :				List[str]				=       self.pipeline_class(**A	)
         snake_case      :				Union[str, Any]				=       pipe.to(A	)

         pipe.set_progress_bar_config(disable=A	)

         snake_case      :				Dict				=       pipe(**self.get_dummy_inputs(A	)	)
         snake_case      :				Optional[int]				=       output.images

         snake_case      :				Union[str, Any]				=       pipe(
             **self.get_dummy_inputs(A	)				,      return_dict=A				,      )[0]

         snake_case      :				List[Any]				=       image[0, -3:, -3:, -1]
         snake_case      :				Dict				=       image_from_tuple[0, -3:, -3:, -1]

         assert image.shape == (1, 6_4, 6_4, 3)

         snake_case      :				Dict				=       np.array(
             [0.6_95_98_26, 0.86_82_79, 0.7_55_80_92, 0.68_76_94_67, 0.85_80_58_04, 0.65_97_74_96, 0.44_88_53_02, 0.5_95_91_11, 0.4_25_15_95]	)

         assert (
             np.abs(image_slice.flatten() - expected_slice	).max() < 1e-2
         ), f""" expected_slice {expected_slice}, but got {image_slice.flatten()}"""

         assert (
             np.abs(image_from_tuple_slice.flatten() - expected_slice	).max() < 1e-2
         ), f""" expected_slice {expected_slice}, but got {image_from_tuple_slice.flatten()}"""




@slow
@require_torch_gpu
class 						__lowercase		(unittest.TestCase							):




      """simple docstring"""





      def 	UpperCAmelCase      (      self	)		->				Optional[int]:
         # clean up the VRAM after each test
         super().tearDown()
         gc.collect()
         torch.cuda.empty_cache()

      def 	UpperCAmelCase      (      self	)		->				Optional[Any]:
         snake_case      :				int				=       load_numpy(
             """https://huggingface.co/datasets/hf-internal-testing/diffusers-images/resolve/main"""
             """/kandinskyv22/kandinskyv22_controlnet_robotcat_fp16.npy"""	)

         snake_case      :				Tuple				=       load_image(
             """https://huggingface.co/datasets/hf-internal-testing/diffusers-images/resolve/main"""
             """/kandinskyv22/hint_image_cat.png"""	)
         snake_case      :				str				=       torch.from_numpy(np.array(A	)	).float() / 2_5_5.0
         snake_case      :				Optional[Any]				=       hint.permute(2				,      0				,      1	).unsqueeze(0	)

         snake_case      :				Optional[Any]				=       KandinskyVaaPriorPipeline.from_pretrained(
             """kandinsky-community/kandinsky-2-2-prior"""				,      torch_dtype=torch.floataa	)
         pipe_prior.to(A	)

         snake_case      :				Union[str, Any]				=       KandinskyVaaControlnetPipeline.from_pretrained(
             """kandinsky-community/kandinsky-2-2-controlnet-depth"""				,      torch_dtype=torch.floataa	)
         snake_case      :				str				=       pipeline.to(A	)
         pipeline.set_progress_bar_config(disable=A	)

         snake_case      :				Union[str, Any]				=       'A robot, 4k photo'

         snake_case      :				int				=       torch.Generator(device="""cuda"""	).manual_seed(0	)
         snake_case      :				Tuple				=       pipe_prior(
             A				,      generator=A				,      num_inference_steps=5				,      negative_prompt=""""""				,      ).to_tuple()

         snake_case      :				Union[str, Any]				=       torch.Generator(device="""cuda"""	).manual_seed(0	)
         snake_case      :				List[Any]				=       pipeline(
             image_embeds=A				,      negative_image_embeds=A				,      hint=A				,      generator=A				,      num_inference_steps=1_0_0				,      output_type="""np"""				,      )

         snake_case      :				List[str]				=       output.images[0]

         assert image.shape == (5_1_2, 5_1_2, 3)

         assert_mean_pixel_difference(A				,      A	)












import argparse
import json
from collections import OrderedDict

import torch
from huggingface_hub import cached_download, hf_hub_url

from transformers import AutoImageProcessor, CvtConfig, CvtForImageClassification


def        SCREAMING_SNAKE_CASE      (       _UpperCAmelCase )			->     int:
    lowerCamelCase__    :      Optional[int]					 =		[]
    embed.append(
        (
            F"""cvt.encoder.stages.{idx}.embedding.convolution_embeddings.projection.weight""",
            F"""stage{idx}.patch_embed.proj.weight""",
        ) )
    embed.append(
        (
            F"""cvt.encoder.stages.{idx}.embedding.convolution_embeddings.projection.bias""",
            F"""stage{idx}.patch_embed.proj.bias""",
        ) )
    embed.append(
        (
            F"""cvt.encoder.stages.{idx}.embedding.convolution_embeddings.normalization.weight""",
            F"""stage{idx}.patch_embed.norm.weight""",
        ) )
    embed.append(
        (
            F"""cvt.encoder.stages.{idx}.embedding.convolution_embeddings.normalization.bias""",
            F"""stage{idx}.patch_embed.norm.bias""",
        ) )
    return embed


def        SCREAMING_SNAKE_CASE      (       _UpperCAmelCase						,	_UpperCAmelCase )			->     Tuple:
    lowerCamelCase__    :      Tuple					 =		[]
    attention_weights.append(
        (
            F"""cvt.encoder.stages.{idx}.layers.{cnt}.attention.attention.convolution_projection_query.convolution_projection.convolution.weight""",
            F"""stage{idx}.blocks.{cnt}.attn.conv_proj_q.conv.weight""",
        ) )
    attention_weights.append(
        (
            F"""cvt.encoder.stages.{idx}.layers.{cnt}.attention.attention.convolution_projection_query.convolution_projection.normalization.weight""",
            F"""stage{idx}.blocks.{cnt}.attn.conv_proj_q.bn.weight""",
        ) )
    attention_weights.append(
        (
            F"""cvt.encoder.stages.{idx}.layers.{cnt}.attention.attention.convolution_projection_query.convolution_projection.normalization.bias""",
            F"""stage{idx}.blocks.{cnt}.attn.conv_proj_q.bn.bias""",
        ) )
    attention_weights.append(
        (
            F"""cvt.encoder.stages.{idx}.layers.{cnt}.attention.attention.convolution_projection_query.convolution_projection.normalization.running_mean""",
            F"""stage{idx}.blocks.{cnt}.attn.conv_proj_q.bn.running_mean""",
        ) )
    attention_weights.append(
        (
            F"""cvt.encoder.stages.{idx}.layers.{cnt}.attention.attention.convolution_projection_query.convolution_projection.normalization.running_var""",
            F"""stage{idx}.blocks.{cnt}.attn.conv_proj_q.bn.running_var""",
        ) )
    attention_weights.append(
        (
            F"""cvt.encoder.stages.{idx}.layers.{cnt}.attention.attention.convolution_projection_query.convolution_projection.normalization.num_batches_tracked""",
            F"""stage{idx}.blocks.{cnt}.attn.conv_proj_q.bn.num_batches_tracked""",
        ) )
    attention_weights.append(
        (
            F"""cvt.encoder.stages.{idx}.layers.{cnt}.attention.attention.convolution_projection_key.convolution_projection.convolution.weight""",
            F"""stage{idx}.blocks.{cnt}.attn.conv_proj_k.conv.weight""",
        ) )
    attention_weights.append(
        (
            F"""cvt.encoder.stages.{idx}.layers.{cnt}.attention.attention.convolution_projection_key.convolution_projection.normalization.weight""",
            F"""stage{idx}.blocks.{cnt}.attn.conv_proj_k.bn.weight""",
        ) )
    attention_weights.append(
        (
            F"""cvt.encoder.stages.{idx}.layers.{cnt}.attention.attention.convolution_projection_key.convolution_projection.normalization.bias""",
            F"""stage{idx}.blocks.{cnt}.attn.conv_proj_k.bn.bias""",
        ) )
    attention_weights.append(
        (
            F"""cvt.encoder.stages.{idx}.layers.{cnt}.attention.attention.convolution_projection_key.convolution_projection.normalization.running_mean""",
            F"""stage{idx}.blocks.{cnt}.attn.conv_proj_k.bn.running_mean""",
        ) )
    attention_weights.append(
        (
            F"""cvt.encoder.stages.{idx}.layers.{cnt}.attention.attention.convolution_projection_key.convolution_projection.normalization.running_var""",
            F"""stage{idx}.blocks.{cnt}.attn.conv_proj_k.bn.running_var""",
        ) )
    attention_weights.append(
        (
            F"""cvt.encoder.stages.{idx}.layers.{cnt}.attention.attention.convolution_projection_key.convolution_projection.normalization.num_batches_tracked""",
            F"""stage{idx}.blocks.{cnt}.attn.conv_proj_k.bn.num_batches_tracked""",
        ) )
    attention_weights.append(
        (
            F"""cvt.encoder.stages.{idx}.layers.{cnt}.attention.attention.convolution_projection_value.convolution_projection.convolution.weight""",
            F"""stage{idx}.blocks.{cnt}.attn.conv_proj_v.conv.weight""",
        ) )
    attention_weights.append(
        (
            F"""cvt.encoder.stages.{idx}.layers.{cnt}.attention.attention.convolution_projection_value.convolution_projection.normalization.weight""",
            F"""stage{idx}.blocks.{cnt}.attn.conv_proj_v.bn.weight""",
        ) )
    attention_weights.append(
        (
            F"""cvt.encoder.stages.{idx}.layers.{cnt}.attention.attention.convolution_projection_value.convolution_projection.normalization.bias""",
            F"""stage{idx}.blocks.{cnt}.attn.conv_proj_v.bn.bias""",
        ) )
    attention_weights.append(
        (
            F"""cvt.encoder.stages.{idx}.layers.{cnt}.attention.attention.convolution_projection_value.convolution_projection.normalization.running_mean""",
            F"""stage{idx}.blocks.{cnt}.attn.conv_proj_v.bn.running_mean""",
        ) )
    attention_weights.append(
        (
            F"""cvt.encoder.stages.{idx}.layers.{cnt}.attention.attention.convolution_projection_value.convolution_projection.normalization.running_var""",
            F"""stage{idx}.blocks.{cnt}.attn.conv_proj_v.bn.running_var""",
        ) )
    attention_weights.append(
        (
            F"""cvt.encoder.stages.{idx}.layers.{cnt}.attention.attention.convolution_projection_value.convolution_projection.normalization.num_batches_tracked""",
            F"""stage{idx}.blocks.{cnt}.attn.conv_proj_v.bn.num_batches_tracked""",
        ) )
    attention_weights.append(
        (
            F"""cvt.encoder.stages.{idx}.layers.{cnt}.attention.attention.projection_query.weight""",
            F"""stage{idx}.blocks.{cnt}.attn.proj_q.weight""",
        ) )
    attention_weights.append(
        (
            F"""cvt.encoder.stages.{idx}.layers.{cnt}.attention.attention.projection_query.bias""",
            F"""stage{idx}.blocks.{cnt}.attn.proj_q.bias""",
        ) )
    attention_weights.append(
        (
            F"""cvt.encoder.stages.{idx}.layers.{cnt}.attention.attention.projection_key.weight""",
            F"""stage{idx}.blocks.{cnt}.attn.proj_k.weight""",
        ) )
    attention_weights.append(
        (
            F"""cvt.encoder.stages.{idx}.layers.{cnt}.attention.attention.projection_key.bias""",
            F"""stage{idx}.blocks.{cnt}.attn.proj_k.bias""",
        ) )
    attention_weights.append(
        (
            F"""cvt.encoder.stages.{idx}.layers.{cnt}.attention.attention.projection_value.weight""",
            F"""stage{idx}.blocks.{cnt}.attn.proj_v.weight""",
        ) )
    attention_weights.append(
        (
            F"""cvt.encoder.stages.{idx}.layers.{cnt}.attention.attention.projection_value.bias""",
            F"""stage{idx}.blocks.{cnt}.attn.proj_v.bias""",
        ) )
    attention_weights.append(
        (
            F"""cvt.encoder.stages.{idx}.layers.{cnt}.attention.output.dense.weight""",
            F"""stage{idx}.blocks.{cnt}.attn.proj.weight""",
        ) )
    attention_weights.append(
        (
            F"""cvt.encoder.stages.{idx}.layers.{cnt}.attention.output.dense.bias""",
            F"""stage{idx}.blocks.{cnt}.attn.proj.bias""",
        ) )
    attention_weights.append(
        (F"""cvt.encoder.stages.{idx}.layers.{cnt}.intermediate.dense.weight""", F"""stage{idx}.blocks.{cnt}.mlp.fc1.weight""") )
    attention_weights.append(
        (F"""cvt.encoder.stages.{idx}.layers.{cnt}.intermediate.dense.bias""", F"""stage{idx}.blocks.{cnt}.mlp.fc1.bias""") )
    attention_weights.append(
        (F"""cvt.encoder.stages.{idx}.layers.{cnt}.output.dense.weight""", F"""stage{idx}.blocks.{cnt}.mlp.fc2.weight""") )
    attention_weights.append(
        (F"""cvt.encoder.stages.{idx}.layers.{cnt}.output.dense.bias""", F"""stage{idx}.blocks.{cnt}.mlp.fc2.bias""") )
    attention_weights.append(
        (F"""cvt.encoder.stages.{idx}.layers.{cnt}.layernorm_before.weight""", F"""stage{idx}.blocks.{cnt}.norm1.weight""") )
    attention_weights.append(
        (F"""cvt.encoder.stages.{idx}.layers.{cnt}.layernorm_before.bias""", F"""stage{idx}.blocks.{cnt}.norm1.bias""") )
    attention_weights.append(
        (F"""cvt.encoder.stages.{idx}.layers.{cnt}.layernorm_after.weight""", F"""stage{idx}.blocks.{cnt}.norm2.weight""") )
    attention_weights.append(
        (F"""cvt.encoder.stages.{idx}.layers.{cnt}.layernorm_after.bias""", F"""stage{idx}.blocks.{cnt}.norm2.bias""") )
    return attention_weights


def        SCREAMING_SNAKE_CASE      (       _UpperCAmelCase )			->     Tuple:
    lowerCamelCase__    :      Union[str, Any]					 =		[]
    token.append((F"""cvt.encoder.stages.{idx}.cls_token""", 'stage2.cls_token') )
    return token


def        SCREAMING_SNAKE_CASE      (       )			->     str:
    lowerCamelCase__    :      str					 =		[]
    head.append(('layernorm.weight', 'norm.weight') )
    head.append(('layernorm.bias', 'norm.bias') )
    head.append(('classifier.weight', 'head.weight') )
    head.append(('classifier.bias', 'head.bias') )
    return head


def        SCREAMING_SNAKE_CASE      (       _UpperCAmelCase						,	_UpperCAmelCase						,	_UpperCAmelCase						,	_UpperCAmelCase )			->     Optional[int]:
    lowerCamelCase__    :      Tuple					 =		'imagenet-1k-id2label.json'
    lowerCamelCase__    :      Union[str, Any]					 =		1000

    lowerCamelCase__    :      Optional[Any]					 =		'huggingface/label-files'
    lowerCamelCase__    :      Any					 =		num_labels
    lowerCamelCase__    :      Dict					 =		json.load(open(cached_download(hf_hub_url(_UpperCAmelCase						,	_UpperCAmelCase						,	repo_type='dataset' ) )						,	'r' ) )
    lowerCamelCase__    :      int					 =		{int(_UpperCAmelCase ): v for k, v in idalabel.items()}

    lowerCamelCase__    :      Tuple					 =		idalabel
    lowerCamelCase__    :      List[Any]					 =		{v: k for k, v in idalabel.items()}

    lowerCamelCase__    :      List[str]					 =		CvtConfig(num_labels=_UpperCAmelCase						,	idalabel=_UpperCAmelCase						,	labelaid=_UpperCAmelCase )

    # For depth size 13 (13 = 1+2+10)
    if cvt_model.rsplit('/'						,	1 )[-1][4:6] == "13":
        lowerCamelCase__    :      List[Any]					 =		[1, 2, 10]

    # For depth size 21 (21 = 1+4+16)
    elif cvt_model.rsplit('/'						,	1 )[-1][4:6] == "21":
        lowerCamelCase__    :      Dict					 =		[1, 4, 16]

    # For wide cvt (similar to wide-resnet) depth size 24 (w24 = 2 + 2 20)
    else:
        lowerCamelCase__    :      Optional[Any]					 =		[2, 2, 20]
        lowerCamelCase__    :      Optional[int]					 =		[3, 12, 16]
        lowerCamelCase__    :      str					 =		[192, 768, 1024]

    lowerCamelCase__    :      Any					 =		CvtForImageClassification(_UpperCAmelCase )
    lowerCamelCase__    :      Optional[Any]					 =		AutoImageProcessor.from_pretrained('facebook/convnext-base-224-22k-1k' )
    lowerCamelCase__    :      Tuple					 =		image_size
    lowerCamelCase__    :      List[str]					 =		torch.load(_UpperCAmelCase						,	map_location=torch.device('cpu' ) )

    lowerCamelCase__    :      Optional[int]					 =		OrderedDict()
    lowerCamelCase__    :      Tuple					 =		[]

    for idx in range(len(config.depth ) ):
        if config.cls_token[idx]:
            lowerCamelCase__    :      Optional[Any]					 =		list_of_state_dict + cls_token(_UpperCAmelCase )
        lowerCamelCase__    :      str					 =		list_of_state_dict + embeddings(_UpperCAmelCase )
        for cnt in range(config.depth[idx] ):
            lowerCamelCase__    :      str					 =		list_of_state_dict + attention(_UpperCAmelCase						,	_UpperCAmelCase )

    lowerCamelCase__    :      int					 =		list_of_state_dict + final()
    for gg in list_of_state_dict:
        print(_UpperCAmelCase )
    for i in range(len(_UpperCAmelCase ) ):
        lowerCamelCase__    :      str					 =		original_weights[list_of_state_dict[i][1]]

    model.load_state_dict(_UpperCAmelCase )
    model.save_pretrained(_UpperCAmelCase )
    image_processor.save_pretrained(_UpperCAmelCase )


# Download the weights from zoo: https://1drv.ms/u/s!AhIXJn_J-blW9RzF3rMW7SsLHa8h?e=blQ0Al

if __name__ == "__main__":
    _UpperCAmelCase				:       List[str]	   =				argparse.ArgumentParser()
    parser.add_argument(
        """--cvt_model""",
        default="""cvt-w24""",
        type=str,
        help="""Name of the cvt model you'd like to convert.""",
    )
    parser.add_argument(
        """--image_size""",
        default=3_84,
        type=int,
        help="""Input Image Size""",
    )
    parser.add_argument(
        """--cvt_file_name""",
        default=R"""cvtmodels\CvT-w24-384x384-IN-22k.pth""",
        type=str,
        help="""Input Image Size""",
    )
    parser.add_argument(
        """--pytorch_dump_folder_path""", default=None, type=str, help="""Path to the output PyTorch model directory."""
    )

    _UpperCAmelCase				:       List[str]	   =				parser.parse_args()
    convert_cvt_checkpoint(args.cvt_model, args.image_size, args.cvt_file_name, args.pytorch_dump_folder_path)





