



import dataclasses
import re
import string
from typing import Any, Dict, Iterator, List, Mapping, Optional, Sequence, Tuple

import numpy as np

from . import residue_constants


_snake_case		=  Mapping[str, np.ndarray]
_snake_case		=  Mapping[str, Any]  # Is a nested dict.
_snake_case		=  0.01



@dataclasses.dataclass(frozen=a)
class   UpperCAmelCase_    :
							lowerCamelCase__   			=		42  # [num_res, num_atom_type, 3]

							# Amino-acid type for each residue represented as an integer between 0 and
							# 20, where 20 is 'X'.
							lowerCamelCase__   			=		42  # [num_res]

							# Binary float mask to indicate presence of a particular atom. 1.0 if an atom
							# is present and 0.0 if not. This should be used for loss masking.
							lowerCamelCase__   			=		42  # [num_res, num_atom_type]

							# Residue index as used in PDB. It is not necessarily continuous or 0-indexed.
							lowerCamelCase__   			=		42  # [num_res]

							# B-factors, or temperature factors, of each residue (in sq. angstroms units),
							# representing the displacement of the residue from its ground truth mean
							# value.
							lowerCamelCase__   			=		42  # [num_res, num_atom_type]

							# Chain indices for multi-chain predictions
							lowerCamelCase__   			=		None

							# Optional remark about the protein. Included as a comment in output PDB
							# files
							lowerCamelCase__   			=		None

							# Templates used to generate this protein (prediction-only)
							lowerCamelCase__   			=		None

							# Chain corresponding to each parent
							lowerCamelCase__   			=		None






def 				A				(					_lowerCamelCase  ):





							'''simple docstring'''




							_lowerCAmelCase     :							Dict    =    r"(\[[A-Z]+\]\n)"
							_lowerCAmelCase     :							List[str]    =    [tag.strip() for tag in re.split(_lowerCamelCase				, _lowerCamelCase  ) if len(_lowerCamelCase  ) > 0]
							_lowerCAmelCase     :							Iterator[Tuple[str, List[str]]]    =    zip(tags[0::2]				, [l.split("\n"  ) for l in tags[1::2]]  )

							_lowerCAmelCase     :							List[str]    =    ["N", "CA", "C"]
							_lowerCAmelCase     :							str    =    None
							_lowerCAmelCase     :							Dict    =    None
							_lowerCAmelCase     :							Any    =    None
							for g in groups:
														if "[PRIMARY]" == g[0]:
																					_lowerCAmelCase     :							Optional[int]    =    g[1][0].strip()
																					for i in range(len(_lowerCamelCase  )  ):
																												if seq[i] not in residue_constants.restypes:
																																			_lowerCAmelCase     :							List[str]    =    "X"  # FIXME: strings are immutable
																					_lowerCAmelCase     :							Any    =    np.array(
																					    [residue_constants.restype_order.get(_lowerCamelCase				, residue_constants.restype_num  ) for res_symbol in seq]  )
														elif "[TERTIARY]" == g[0]:
																					_lowerCAmelCase     :							List[List[float]]    =    []
																					for axis in range(3  ):
																												tertiary.append(list(map(_lowerCamelCase				, g[1][axis].split()  )  )  )
																					_lowerCAmelCase     :							Optional[int]    =    np.array(_lowerCamelCase  )
																					_lowerCAmelCase     :							str    =    np.zeros((len(tertiary[0]  ) // 3, residue_constants.atom_type_num, 3)  ).astype(np.floataa  )
																					for i, atom in enumerate(_lowerCamelCase  ):
																												_lowerCAmelCase     :							Dict    =    np.transpose(tertiary_np[:, i::3]  )
																					atom_positions *= PICO_TO_ANGSTROM
														elif "[MASK]" == g[0]:
																					_lowerCAmelCase     :							Optional[int]    =    np.array(list(map({"-": 0, "+": 1}.get				, g[1][0].strip()  )  )  )
																					_lowerCAmelCase     :							List[Any]    =    np.zeros(
																					    (
																					        len(_lowerCamelCase  ),
																					        residue_constants.atom_type_num,
																					    )  ).astype(np.floataa  )
																					for i, atom in enumerate(_lowerCamelCase  ):
																												_lowerCAmelCase     :							int    =    1
																					atom_mask *= mask[..., None]

							assert aatype is not None

							return Protein(
							    atom_positions=_lowerCamelCase				, atom_mask=_lowerCamelCase				, aatype=_lowerCamelCase				, residue_index=np.arange(len(_lowerCamelCase  )  )				, b_factors=_lowerCamelCase				, )






def 				A				(					_lowerCamelCase				, _lowerCamelCase = 0  ):





							'''simple docstring'''




							_lowerCAmelCase     :							List[str]    =    []

							_lowerCAmelCase     :							Dict    =    prot.remark
							if remark is not None:
														pdb_headers.append(F"REMARK {remark}"  )

							_lowerCAmelCase     :							List[str]    =    prot.parents
							_lowerCAmelCase     :							str    =    prot.parents_chain_index
							if parents is not None and parents_chain_index is not None:
														_lowerCAmelCase     :							Optional[int]    =    [p for i, p in zip(_lowerCamelCase				, _lowerCamelCase  ) if i == chain_id]

							if parents is None or len(_lowerCamelCase  ) == 0:
														_lowerCAmelCase     :							str    =    ["N/A"]

							pdb_headers.append(F"PARENT {' '.join(_lowerCamelCase  )}"  )

							return pdb_headers






def 				A				(					_lowerCamelCase				, _lowerCamelCase  ):





							'''simple docstring'''




							_lowerCAmelCase     :							List[str]    =    []
							_lowerCAmelCase     :							Union[str, Any]    =    pdb_str.split("\n"  )

							_lowerCAmelCase     :							Optional[Any]    =    prot.remark
							if remark is not None:
														out_pdb_lines.append(F"REMARK {remark}"  )

							_lowerCAmelCase     :							List[List[str]]
							if prot.parents is not None and len(prot.parents  ) > 0:
														_lowerCAmelCase     :							Any    =    []
														if prot.parents_chain_index is not None:
																					_lowerCAmelCase     :							Dict[str, List[str]]    =    {}
																					for p, i in zip(prot.parents				, prot.parents_chain_index  ):
																												parent_dict.setdefault(str(_lowerCamelCase  )				, []  )
																												parent_dict[str(_lowerCamelCase  )].append(_lowerCamelCase  )

																					_lowerCAmelCase     :							Optional[int]    =    max([int(_lowerCamelCase  ) for chain_idx in parent_dict]  )
																					for i in range(max_idx + 1  ):
																												_lowerCAmelCase     :							List[Any]    =    parent_dict.get(str(_lowerCamelCase  )				, ["N/A"]  )
																												parents_per_chain.append(_lowerCamelCase  )
														else:
																					parents_per_chain.append(list(prot.parents  )  )
							else:
														_lowerCAmelCase     :							Union[str, Any]    =    [["N/A"]]

							def make_parent_line(_lowerCamelCase  ) -> str:
														return F"PARENT {' '.join(_lowerCamelCase  )}"

							out_pdb_lines.append(make_parent_line(parents_per_chain[0]  )  )

							_lowerCAmelCase     :							List[str]    =    0
							for i, l in enumerate(_lowerCamelCase  ):
														if "PARENT" not in l and "REMARK" not in l:
																					out_pdb_lines.append(_lowerCamelCase  )
														if "TER" in l and "END" not in lines[i + 1]:
																					chain_counter += 1
																					if not chain_counter >= len(_lowerCamelCase  ):
																												_lowerCAmelCase     :							List[Any]    =    parents_per_chain[chain_counter]
																					else:
																												_lowerCAmelCase     :							str    =    ["N/A"]

																					out_pdb_lines.append(make_parent_line(_lowerCamelCase  )  )

							return "\n".join(_lowerCamelCase  )






def 				A				(					_lowerCamelCase  ):





							'''simple docstring'''




							_lowerCAmelCase     :							Dict    =    residue_constants.restypes + ["X"]

							def res_atoa(_lowerCamelCase  ) -> str:
														return residue_constants.restype_atoa.get(restypes[r]				, "UNK"  )

							_lowerCAmelCase     :							Optional[int]    =    residue_constants.atom_types

							_lowerCAmelCase     :							List[str]    =    []

							_lowerCAmelCase     :							List[str]    =    prot.atom_mask
							_lowerCAmelCase     :							Optional[Any]    =    prot.aatype
							_lowerCAmelCase     :							Tuple    =    prot.atom_positions
							_lowerCAmelCase     :							Optional[int]    =    prot.residue_index.astype(np.intaa  )
							_lowerCAmelCase     :							Dict    =    prot.b_factors
							_lowerCAmelCase     :							Dict    =    prot.chain_index

							if np.any(aatype > residue_constants.restype_num  ):
														raise ValueError("Invalid aatypes."  )

							_lowerCAmelCase     :							List[Any]    =    get_pdb_headers(_lowerCamelCase  )
							if len(_lowerCamelCase  ) > 0:
														pdb_lines.extend(_lowerCamelCase  )

							_lowerCAmelCase     :							str    =    aatype.shape[0]
							_lowerCAmelCase     :							Dict    =    1
							_lowerCAmelCase     :							List[str]    =    0
							_lowerCAmelCase     :							int    =    string.ascii_uppercase
							_lowerCAmelCase     :							Tuple    =    None
							# Add all atom sites.
							for i in range(_lowerCamelCase  ):
														_lowerCAmelCase     :							List[Any]    =    res_atoa(aatype[i]  )
														for atom_name, pos, mask, b_factor in zip(_lowerCamelCase				, atom_positions[i]				, atom_mask[i]				, b_factors[i]  ):
																					if mask < 0.5:
																												continue

																					_lowerCAmelCase     :							Optional[Any]    =    "ATOM"
																					_lowerCAmelCase     :							str    =    atom_name if len(_lowerCamelCase  ) == 4 else F" {atom_name}"
																					_lowerCAmelCase     :							List[Any]    =    ""
																					_lowerCAmelCase     :							Optional[int]    =    ""
																					_lowerCAmelCase     :							Any    =    1.00
																					_lowerCAmelCase     :							Any    =    atom_name[0]  # Protein supports only C, N, O, S, this works.
																					_lowerCAmelCase     :							Optional[int]    =    ""

																					_lowerCAmelCase     :							Any    =    "A"
																					if chain_index is not None:
																												_lowerCAmelCase     :							Tuple    =    chain_tags[chain_index[i]]

																					# PDB is a columnar format, every space matters here!
																					_lowerCAmelCase     :							List[Any]    =    (
																					    F"{record_type:<6}{atom_index:>5} {name:<4}{alt_loc:>1}"
																					    F"{res_name_a:>3} {chain_tag:>1}"
																					    F"{residue_index[i]:>4}{insertion_code:>1}   "
																					    F"{pos[0]:>8.3f}{pos[1]:>8.3f}{pos[2]:>8.3f}"
																					    F"{occupancy:>6.2f}{b_factor:>6.2f}          "
																					    F"{element:>2}{charge:>2}"
																					)
																					pdb_lines.append(_lowerCamelCase  )
																					atom_index += 1

														_lowerCAmelCase     :							List[Any]    =    i == n - 1
														if chain_index is not None:
																					if i != n - 1 and chain_index[i + 1] != prev_chain_index:
																												_lowerCAmelCase     :							Union[str, Any]    =    True
																												_lowerCAmelCase     :							Union[str, Any]    =    chain_index[i + 1]

														if should_terminate:
																					# Close the chain.
																					_lowerCAmelCase     :							Optional[Any]    =    "TER"
																					_lowerCAmelCase     :							List[Any]    =    (
																					    F"{chain_end:<6}{atom_index:>5}      {res_atoa(aatype[i]  ):>3} {chain_tag:>1}{residue_index[i]:>4}"
																					)
																					pdb_lines.append(_lowerCamelCase  )
																					atom_index += 1

																					if i != n - 1:
																												# "prev" is a misnomer here. This happens at the beginning of
																												# each new chain.
																												pdb_lines.extend(get_pdb_headers(_lowerCamelCase				, _lowerCamelCase  )  )

							pdb_lines.append("END"  )
							pdb_lines.append(""  )
							return "\n".join(_lowerCamelCase  )






def 				A				(					_lowerCamelCase  ):





							'''simple docstring'''




							return residue_constants.STANDARD_ATOM_MASK[prot.aatype]






def 				A				(					_lowerCamelCase				, _lowerCamelCase				, _lowerCamelCase = None				, _lowerCamelCase = None				, _lowerCamelCase = None				, _lowerCamelCase = None				, _lowerCamelCase = None				, ):





							'''simple docstring'''




							return Protein(
							    aatype=features["aatype"]				, atom_positions=result["final_atom_positions"]				, atom_mask=result["final_atom_mask"]				, residue_index=features["residue_index"] + 1				, b_factors=b_factors if b_factors is not None else np.zeros_like(result["final_atom_mask"]  )				, chain_index=_lowerCamelCase				, remark=_lowerCamelCase				, parents=_lowerCamelCase				, parents_chain_index=_lowerCamelCase				, )


from typing import List, Optional, Union

import numpy as np
import PIL.Image

from ...image_processing_utils import BaseImageProcessor, BatchFeature
from ...image_transforms import rescale, resize, to_channel_dimension_format
from ...image_utils import (
    ChannelDimension,
    PILImageResampling,
    get_image_size,
    make_list_of_images,
    to_numpy_array,
    valid_images,
)
from ...utils import TensorType, logging


__snake_case								=  logging.get_logger(__name__)




class 						lowercase__  (						_UpperCAmelCase  ):
	A__    :   List[str]				       =["""pixel_values"""]
	def __init__(			self							:   Dict       ,   UpperCAmelCase_							:   bool = True       ,   UpperCAmelCase_							:   int = 32       ,   UpperCAmelCase_							:   int=PILImageResampling.BILINEAR       ,   UpperCAmelCase_							:   bool = True       ,   **UpperCAmelCase_							:   Any       ,   ):
						SCREAMING_SNAKE_CASE__													= do_resize
						SCREAMING_SNAKE_CASE__													= do_rescale
						SCREAMING_SNAKE_CASE__													= size_divisor
						SCREAMING_SNAKE_CASE__													= resample
						super().__init__(**UpperCAmelCase_							)
	def      A_				(			self							:   Optional[int]       ,   UpperCAmelCase_							:   np.ndarray       ,   UpperCAmelCase_							:   int       ,   UpperCAmelCase_							:   Dict       ,   UpperCAmelCase_							:   Optional[ChannelDimension] = None       ,   **UpperCAmelCase_							:   Dict							):
						SCREAMING_SNAKE_CASE__						, SCREAMING_SNAKE_CASE__													= get_image_size(UpperCAmelCase_							)
						# Rounds the height and width down to the closest multiple of size_divisor
						SCREAMING_SNAKE_CASE__													= height // size_divisor * size_divisor
						SCREAMING_SNAKE_CASE__													= width // size_divisor * size_divisor
						SCREAMING_SNAKE_CASE__													= resize(UpperCAmelCase_       ,   (new_h, new_w)       ,   resample=UpperCAmelCase_       ,   data_format=UpperCAmelCase_       ,   **UpperCAmelCase_							)
						return image
	def      A_				(			self							:   Any       ,   UpperCAmelCase_							:   np.ndarray       ,   UpperCAmelCase_							:   float       ,   UpperCAmelCase_							:   Optional[ChannelDimension] = None       ,   **UpperCAmelCase_							:   List[str]							):
						return rescale(image=UpperCAmelCase_       ,   scale=UpperCAmelCase_       ,   data_format=UpperCAmelCase_       ,   **UpperCAmelCase_							)





	def      A_				(			self							:   Dict       ,   UpperCAmelCase_							:   Union["PIL.Image.Image", TensorType, List["PIL.Image.Image"], List[TensorType]]       ,   UpperCAmelCase_							:   Optional[bool] = None       ,   UpperCAmelCase_							:   Optional[int] = None       ,   UpperCAmelCase_							:   List[str]=None       ,   UpperCAmelCase_							:   Optional[bool] = None       ,   UpperCAmelCase_							:   Optional[Union[TensorType, str]] = None       ,   UpperCAmelCase_							:   ChannelDimension = ChannelDimension.FIRST       ,   **UpperCAmelCase_							:   List[Any]       ,   ):
						SCREAMING_SNAKE_CASE__													= do_resize if do_resize is not None else self.do_resize
						SCREAMING_SNAKE_CASE__													= do_rescale if do_rescale is not None else self.do_rescale
						SCREAMING_SNAKE_CASE__													= size_divisor if size_divisor is not None else self.size_divisor
						SCREAMING_SNAKE_CASE__													= resample if resample is not None else self.resample

						if do_resize and size_divisor is None:
											raise ValueError('size_divisor is required for resizing'							)

						SCREAMING_SNAKE_CASE__													= make_list_of_images(UpperCAmelCase_							)

						if not valid_images(UpperCAmelCase_							):
											raise ValueError('Invalid image(s)'							)

						# All transformations expect numpy arrays.
						SCREAMING_SNAKE_CASE__													= [to_numpy_array(UpperCAmelCase_							) for img in images]

						if do_resize:
											SCREAMING_SNAKE_CASE__													= [self.resize(UpperCAmelCase_       ,   size_divisor=UpperCAmelCase_       ,   resample=UpperCAmelCase_							) for image in images]

						if do_rescale:
											SCREAMING_SNAKE_CASE__													= [self.rescale(UpperCAmelCase_       ,   scale=1 / 255							) for image in images]

						SCREAMING_SNAKE_CASE__													= [to_channel_dimension_format(UpperCAmelCase_       ,   UpperCAmelCase_							) for image in images]

						SCREAMING_SNAKE_CASE__													= {'pixel_values': images}
						return BatchFeature(data=UpperCAmelCase_       ,   tensor_type=UpperCAmelCase_							)





