




'''simple docstring'''





from typing import Dict, Iterable, Optional, Union

import numpy as np

from ...image_processing_utils import BaseImageProcessor, BatchFeature, get_size_dict
from ...image_transforms import normalize, rescale, resize, to_channel_dimension_format, to_pil_image
from ...image_utils import (
    IMAGENET_STANDARD_MEAN,
    IMAGENET_STANDARD_STD,
    ChannelDimension,
    ImageInput,
    PILImageResampling,
    make_list_of_images,
    to_numpy_array,
    valid_images,
)
from ...utils import TensorType, is_pytesseract_available, is_vision_available, logging, requires_backends


if is_vision_available():
  import PIL

# soft dependency
if is_pytesseract_available():
  import pytesseract

_SCREAMING_SNAKE_CASE							:       Tuple						=			logging.get_logger(__name__)


def 					UpperCamelCase_(     snake_case							:	List[str]							,    snake_case							:	Any							,    snake_case							:	List[str]					):

       '''simple docstring'''






       return [
           int(1_0_0_0 * (box[0] / width)					),
           int(1_0_0_0 * (box[1] / height)					),
           int(1_0_0_0 * (box[2] / width)					),
           int(1_0_0_0 * (box[3] / height)					),
       ]


def 					UpperCamelCase_(     snake_case							:	np.ndarray							,    snake_case							:	Optional[str]							,    snake_case							:	Optional[str]					):

       '''simple docstring'''






       snake_case_      =				to_pil_image(snake_case					)
       snake_case_ ,				snake_case_      =				pil_image.size
       snake_case_      =				pytesseract.image_to_data(snake_case							,    lang=snake_case							,    output_type="dict"							,    config=snake_case					)
       snake_case_ ,				snake_case_ ,				snake_case_ ,				snake_case_ ,				snake_case_      =				data["text"], data["left"], data["top"], data["width"], data["height"]

       # filter empty words and corresponding coordinates
       snake_case_      =				[idx for idx, word in enumerate(snake_case					) if not word.strip()]
       snake_case_      =				[word for idx, word in enumerate(snake_case					) if idx not in irrelevant_indices]
       snake_case_      =				[coord for idx, coord in enumerate(snake_case					) if idx not in irrelevant_indices]
       snake_case_      =				[coord for idx, coord in enumerate(snake_case					) if idx not in irrelevant_indices]
       snake_case_      =				[coord for idx, coord in enumerate(snake_case					) if idx not in irrelevant_indices]
       snake_case_      =				[coord for idx, coord in enumerate(snake_case					) if idx not in irrelevant_indices]

       # turn coordinates into (left, top, left+width, top+height) format
       snake_case_      =				[]
       for x, y, w, h in zip(snake_case							,    snake_case							,    snake_case							,    snake_case					):
              snake_case_      =				[x, y, x + w, y + h]
              actual_boxes.append(snake_case					)

       # finally, normalize the bounding boxes
       snake_case_      =				[]
       for box in actual_boxes:
              normalized_boxes.append(normalize_box(snake_case							,    snake_case							,    snake_case					)					)

       assert len(snake_case					) == len(snake_case					), "Not as many words as there are bounding boxes"

       return words, normalized_boxes




class 			_snake_case		(     lowercase_							):
   lowerCAmelCase_					:				Tuple							=   ["pixel_values"]




   def __init__( self    ,							a__ = True    ,							a__ = None    ,							a__ = PILImageResampling.BILINEAR    ,							a__ = True    ,							a__ = 1 / 255    ,							a__ = True    ,							a__ = None    ,							a__ = None    ,							a__ = True    ,							a__ = None    ,							a__ = ""    ,							**a__    ,							)    ->    None:

          '''simple docstring'''




          super().__init__(**a__							)
          snake_case_      =				size if size is not None else {"height": 224, "width": 224}
          snake_case_      =				get_size_dict(a__							)

          snake_case_      =				do_resize
          snake_case_      =				size
          snake_case_      =				resample
          snake_case_      =				do_rescale
          snake_case_      =				rescale_value
          snake_case_      =				do_normalize
          snake_case_      =				image_mean if image_mean is not None else IMAGENET_STANDARD_MEAN
          snake_case_      =				image_std if image_std is not None else IMAGENET_STANDARD_STD
          snake_case_      =				apply_ocr
          snake_case_      =				ocr_lang
          snake_case_      =				tesseract_config




   def        lowerCAmelCase__    ( self    ,							a__    ,							a__    ,							a__ = PILImageResampling.BILINEAR    ,							a__ = None    ,							**a__    ,							)    ->    np.ndarray:

          '''simple docstring'''




          snake_case_      =				get_size_dict(a__							)
          if "height" not in size or "width" not in size:
                 raise ValueError(F'The size dictionary must contain the keys \'height\' and \'width\'. Got {size.keys()}'							)
          snake_case_      =				(size["height"], size["width"])
          return resize(a__    ,							size=a__    ,							resample=a__    ,							data_format=a__    ,							**a__							)




   def        lowerCAmelCase__    ( self    ,							a__    ,							a__    ,							a__ = None    ,							**a__    ,							)    ->    np.ndarray:

          '''simple docstring'''




          return rescale(a__    ,							scale=a__    ,							data_format=a__    ,							**a__							)




   def        lowerCAmelCase__    ( self    ,							a__    ,							a__    ,							a__    ,							a__ = None    ,							**a__    ,							)    ->    np.ndarray:

          '''simple docstring'''




          return normalize(a__    ,							mean=a__    ,							std=a__    ,							data_format=a__    ,							**a__							)




   def        lowerCAmelCase__    ( self    ,							a__    ,							a__ = None    ,							a__ = None    ,							a__=None    ,							a__ = None    ,							a__ = None    ,							a__ = None    ,							a__ = None    ,							a__ = None    ,							a__ = None    ,							a__ = None    ,							a__ = None    ,							a__ = None    ,							a__ = ChannelDimension.FIRST    ,							**a__    ,							)    ->    PIL.Image.Image:

          '''simple docstring'''




          snake_case_      =				do_resize if do_resize is not None else self.do_resize
          snake_case_      =				size if size is not None else self.size
          snake_case_      =				get_size_dict(a__							)
          snake_case_      =				resample if resample is not None else self.resample
          snake_case_      =				do_rescale if do_rescale is not None else self.do_rescale
          snake_case_      =				rescale_factor if rescale_factor is not None else self.rescale_factor
          snake_case_      =				do_normalize if do_normalize is not None else self.do_normalize
          snake_case_      =				image_mean if image_mean is not None else self.image_mean
          snake_case_      =				image_std if image_std is not None else self.image_std
          snake_case_      =				apply_ocr if apply_ocr is not None else self.apply_ocr
          snake_case_      =				ocr_lang if ocr_lang is not None else self.ocr_lang
          snake_case_      =				tesseract_config if tesseract_config is not None else self.tesseract_config

          snake_case_      =				make_list_of_images(a__							)

          if not valid_images(a__							):
                 raise ValueError(
                     "Invalid image type. Must be of type PIL.Image.Image, numpy.ndarray, "
                     "torch.Tensor, tf.Tensor or jax.ndarray."							)

          if do_resize and size is None:
                 raise ValueError("Size must be specified if do_resize is True."							)

          if do_rescale and rescale_factor is None:
                 raise ValueError("Rescale factor must be specified if do_rescale is True."							)

          if do_normalize and (image_mean is None or image_std is None):
                 raise ValueError("If do_normalize is True, image_mean and image_std must be specified."							)

          # All transformations expect numpy arrays.
          snake_case_      =				[to_numpy_array(a__							) for image in images]

          # Tesseract OCR to get words + normalized bounding boxes
          if apply_ocr:
                 requires_backends(self    ,							"pytesseract"							)
                 snake_case_      =				[]
                 snake_case_      =				[]
                 for image in images:
                        snake_case_ ,				snake_case_      =				apply_tesseract(a__    ,							a__    ,							a__							)
                        words_batch.append(a__							)
                        boxes_batch.append(a__							)

          if do_resize:
                 snake_case_      =				[self.resize(image=a__    ,							size=a__    ,							resample=a__							) for image in images]

          if do_rescale:
                 snake_case_      =				[self.rescale(image=a__    ,							scale=a__							) for image in images]

          if do_normalize:
                 snake_case_      =				[self.normalize(image=a__    ,							mean=a__    ,							std=a__							) for image in images]

          snake_case_      =				[to_channel_dimension_format(a__    ,							a__							) for image in images]

          snake_case_      =				BatchFeature(data={"pixel_values": images}    ,							tensor_type=a__							)

          if apply_ocr:
                 snake_case_      =				words_batch
                 snake_case_      =				boxes_batch
          return data










'''simple docstring'''





import os

import torch

from ..logging import get_logger
from .constants import FSDP_PYTORCH_VERSION, MODEL_NAME, OPTIMIZER_NAME
from .versions import is_torch_version


if is_torch_version(">=", FSDP_PYTORCH_VERSION):
		import torch.distributed.checkpoint as dist_cp
		from torch.distributed.checkpoint.default_planner import DefaultLoadPlanner, DefaultSavePlanner
		from torch.distributed.checkpoint.optimizer import load_sharded_optimizer_state_dict
		from torch.distributed.fsdp.fully_sharded_data_parallel import FullyShardedDataParallel as FSDP
		from torch.distributed.fsdp.fully_sharded_data_parallel import StateDictType


_SCREAMING_SNAKE_CASE							:       Tuple						=			get_logger(__name__)


def 					UpperCamelCase_(     snake_case							:	Optional[Any]							,    snake_case							:	Optional[Any]							,    snake_case							:	Optional[Any]							,    snake_case							:	int							,    snake_case							:	List[Any]=0					):

							'''simple docstring'''






							os.makedirs(snake_case							,    exist_ok=snake_case					)
							with FSDP.state_dict_type(
							    snake_case							,    fsdp_plugin.state_dict_type							,    fsdp_plugin.state_dict_config							,    fsdp_plugin.optim_state_dict_config					):
														snake_case_      =				model.state_dict()
														if fsdp_plugin.state_dict_type == StateDictType.FULL_STATE_DICT:
																					snake_case_      =				f'{MODEL_NAME}.bin' if model_index == 0 else f'{MODEL_NAME}_{model_index}.bin'
																					snake_case_      =				os.path.join(snake_case							,    snake_case					)
																					if accelerator.process_index == 0:
																												logger.info(f'Saving model to {output_model_file}'					)
																												torch.save(snake_case							,    snake_case					)
																												logger.info(f'Model saved to {output_model_file}'					)
														elif fsdp_plugin.state_dict_type == StateDictType.LOCAL_STATE_DICT:
																					snake_case_      =				(
																					    f'{MODEL_NAME}_rank{accelerator.process_index}.bin'
																					    if model_index == 0
																					    else f'{MODEL_NAME}_{model_index}_rank{accelerator.process_index}.bin'
																					)
																					snake_case_      =				os.path.join(snake_case							,    snake_case					)
																					logger.info(f'Saving model to {output_model_file}'					)
																					torch.save(snake_case							,    snake_case					)
																					logger.info(f'Model saved to {output_model_file}'					)
														elif fsdp_plugin.state_dict_type == StateDictType.SHARDED_STATE_DICT:
																					snake_case_      =				os.path.join(snake_case							,    f'{MODEL_NAME}_{model_index}'					)
																					os.makedirs(snake_case							,    exist_ok=snake_case					)
																					logger.info(f'Saving model to {ckpt_dir}'					)
																					snake_case_      =				{"model": state_dict}

																					dist_cp.save_state_dict(
																					    state_dict=snake_case							,    storage_writer=dist_cp.FileSystemWriter(snake_case					)							,    planner=DefaultSavePlanner()							,    )
																					logger.info(f'Model saved to {ckpt_dir}'					)


def 					UpperCamelCase_(     snake_case							:	Optional[int]							,    snake_case							:	Optional[Any]							,    snake_case							:	int							,    snake_case							:	Union[str, Any]							,    snake_case							:	Any=0					):

							'''simple docstring'''






							accelerator.wait_for_everyone()
							with FSDP.state_dict_type(
							    snake_case							,    fsdp_plugin.state_dict_type							,    fsdp_plugin.state_dict_config							,    fsdp_plugin.optim_state_dict_config					):
														if fsdp_plugin.state_dict_type == StateDictType.FULL_STATE_DICT:
																					if type(snake_case					) != FSDP and accelerator.process_index != 0:
																												if not fsdp_plugin.sync_module_states:
																																			raise ValueError(
																																			    "Set the `sync_module_states` flag to `True` so that model states are synced across processes when "
																																			    "initializing FSDP object"					)
																												return
																					snake_case_      =				f'{MODEL_NAME}.bin' if model_index == 0 else f'{MODEL_NAME}_{model_index}.bin'
																					snake_case_      =				os.path.join(snake_case							,    snake_case					)
																					logger.info(f'Loading model from {input_model_file}'					)
																					snake_case_      =				torch.load(snake_case					)
																					logger.info(f'Model loaded from {input_model_file}'					)
														elif fsdp_plugin.state_dict_type == StateDictType.LOCAL_STATE_DICT:
																					snake_case_      =				(
																					    f'{MODEL_NAME}_rank{accelerator.process_index}.bin'
																					    if model_index == 0
																					    else f'{MODEL_NAME}_{model_index}_rank{accelerator.process_index}.bin'
																					)
																					snake_case_      =				os.path.join(snake_case							,    snake_case					)
																					logger.info(f'Loading model from {input_model_file}'					)
																					snake_case_      =				torch.load(snake_case					)
																					logger.info(f'Model loaded from {input_model_file}'					)
														elif fsdp_plugin.state_dict_type == StateDictType.SHARDED_STATE_DICT:
																					snake_case_      =				(
																					    os.path.join(snake_case							,    f'{MODEL_NAME}_{model_index}'					)
																					    if f'{MODEL_NAME}' not in input_dir
																					    else input_dir
																					)
																					logger.info(f'Loading model from {ckpt_dir}'					)
																					snake_case_      =				{"model": model.state_dict()}
																					dist_cp.load_state_dict(
																					    state_dict=snake_case							,    storage_reader=dist_cp.FileSystemReader(snake_case					)							,    planner=DefaultLoadPlanner()							,    )
																					snake_case_      =				state_dict["model"]
																					logger.info(f'Model loaded from {ckpt_dir}'					)
														model.load_state_dict(snake_case					)


def 					UpperCamelCase_(     snake_case							:	str							,    snake_case							:	List[str]							,    snake_case							:	Any							,    snake_case							:	Tuple							,    snake_case							:	Optional[Any]							,    snake_case							:	Tuple=0					):

							'''simple docstring'''






							os.makedirs(snake_case							,    exist_ok=snake_case					)
							with FSDP.state_dict_type(
							    snake_case							,    fsdp_plugin.state_dict_type							,    fsdp_plugin.state_dict_config							,    fsdp_plugin.optim_state_dict_config					):
														snake_case_      =				FSDP.optim_state_dict(snake_case							,    snake_case					)
														if fsdp_plugin.state_dict_type == StateDictType.FULL_STATE_DICT:
																					if accelerator.process_index == 0:
																												snake_case_      =				(
																												    f'{OPTIMIZER_NAME}.bin' if optimizer_index == 0 else f'{OPTIMIZER_NAME}_{optimizer_index}.bin'
																												)
																												snake_case_      =				os.path.join(snake_case							,    snake_case					)
																												logger.info(f'Saving Optimizer state to {output_optimizer_file}'					)
																												torch.save(snake_case							,    snake_case					)
																												logger.info(f'Optimizer state saved in {output_optimizer_file}'					)
														else:
																					snake_case_      =				os.path.join(snake_case							,    f'{OPTIMIZER_NAME}_{optimizer_index}'					)
																					os.makedirs(snake_case							,    exist_ok=snake_case					)
																					logger.info(f'Saving Optimizer state to {ckpt_dir}'					)
																					dist_cp.save_state_dict(
																					    state_dict={"optimizer": optim_state}							,    storage_writer=dist_cp.FileSystemWriter(snake_case					)							,    planner=DefaultSavePlanner()							,    )
																					logger.info(f'Optimizer state saved in {ckpt_dir}'					)




def 					UpperCamelCase_(     snake_case							:	Optional[Any]							,    snake_case							:	List[str]							,    snake_case							:	Union[str, Any]							,    snake_case							:	int							,    snake_case							:	Optional[int]							,    snake_case							:	Union[str, Any]=0					):

							'''simple docstring'''






							accelerator.wait_for_everyone()
							with FSDP.state_dict_type(
							    snake_case							,    fsdp_plugin.state_dict_type							,    fsdp_plugin.state_dict_config							,    fsdp_plugin.optim_state_dict_config					):
														if fsdp_plugin.state_dict_type == StateDictType.FULL_STATE_DICT:
																					snake_case_      =				None
																					# below check should work but currently it isn't working (mostly opytorch issue),
																					# in the meantime disabling it at the cost of excess memory usage
																					# if accelerator.process_index == 0 or not fsdp_plugin.optim_state_dict_config.rank0_only:
																					snake_case_      =				(
																					    f'{OPTIMIZER_NAME}.bin' if optimizer_index == 0 else f'{OPTIMIZER_NAME}_{optimizer_index}.bin'
																					)
																					snake_case_      =				os.path.join(snake_case							,    snake_case					)
																					logger.info(f'Loading Optimizer state from {input_optimizer_file}'					)
																					snake_case_      =				torch.load(snake_case					)
																					logger.info(f'Optimizer state loaded from {input_optimizer_file}'					)
														else:
																					snake_case_      =				(
																					    os.path.join(snake_case							,    f'{OPTIMIZER_NAME}_{optimizer_index}'					)
																					    if f'{OPTIMIZER_NAME}' not in input_dir
																					    else input_dir
																					)
																					logger.info(f'Loading Optimizer from {ckpt_dir}'					)
																					snake_case_      =				load_sharded_optimizer_state_dict(
																					    model_state_dict=model.state_dict()							,    optimizer_key="optimizer"							,    storage_reader=dist_cp.FileSystemReader(snake_case					)							,    )
																					snake_case_      =				optim_state["optimizer"]
																					logger.info(f'Optimizer loaded from {ckpt_dir}'					)
														snake_case_      =				FSDP.optim_state_dict_to_load(snake_case							,    snake_case							,    snake_case					)
														optimizer.load_state_dict(snake_case					)




