




'''simple docstring'''

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


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






@dataclasses.dataclass(frozen=_lowerCamelCase     )
class 						a				:
				snake_case_      =		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'.
				snake_case_      =		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.
				snake_case_      =		42  # [num_res, num_atom_type]

				# Residue index as used in PDB. It is not necessarily continuous or 0-indexed.
				snake_case_      =		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.
				snake_case_      =		42  # [num_res, num_atom_type]

				# Chain indices for multi-chain predictions
				snake_case_      =		None

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

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

				# Chain corresponding to each parent
				snake_case_      =		None







def 		__magic_name__    (	__UpperCAmelCase	)		->					Protein:

					'''simple docstring'''

					snake_case_									=				r'''(\[[A-Z]+\]\n)'''
					snake_case_									=				[tag.strip() for tag in re.split(__UpperCAmelCase,      __UpperCAmelCase	) if len(__UpperCAmelCase	) > 0]
					snake_case_									=				zip(tags[0::2],      [l.split('''\n'''	) for l in tags[1::2]]	)

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

					assert aatype is not None

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


def 		__magic_name__    (	__UpperCAmelCase,      __UpperCAmelCase = 0	)		->					List[str]:

					'''simple docstring'''

					snake_case_									=				[]

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

					snake_case_									=				prot.parents
					snake_case_									=				prot.parents_chain_index
					if parents is not None and parents_chain_index is not None:
										snake_case_									=				[p for i, p in zip(__UpperCAmelCase,      __UpperCAmelCase	) if i == chain_id]

					if parents is None or len(__UpperCAmelCase	) == 0:
										snake_case_									=				['''N/A''']

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

					return pdb_headers


def 		__magic_name__    (	__UpperCAmelCase,      __UpperCAmelCase	)		->					str:

					'''simple docstring'''

					snake_case_									=				[]
					snake_case_									=				pdb_str.split('''\n'''	)

					snake_case_									=				prot.remark
					if remark is not None:
										out_pdb_lines.append(F"REMARK {remark}"	)

					snake_case_									=				42
					if prot.parents is not None and len(prot.parents	) > 0:
										snake_case_									=				[]
										if prot.parents_chain_index is not None:
															snake_case_									=				{}
															for p, i in zip(prot.parents,      prot.parents_chain_index	):
																				parent_dict.setdefault(str(__UpperCAmelCase	),      []	)
																				parent_dict[str(__UpperCAmelCase	)].append(__UpperCAmelCase	)

															snake_case_									=				max([int(__UpperCAmelCase	) for chain_idx in parent_dict]	)
															for i in range(max_idx + 1	):
																				snake_case_									=				parent_dict.get(str(__UpperCAmelCase	),      ['''N/A''']	)
																				parents_per_chain.append(__UpperCAmelCase	)
										else:
															parents_per_chain.append(list(prot.parents	)	)
					else:
										snake_case_									=				[['''N/A''']]

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

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

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

															out_pdb_lines.append(make_parent_line(__UpperCAmelCase	)	)

					return "\n".join(__UpperCAmelCase	)


def 		__magic_name__    (	__UpperCAmelCase	)		->					str:

					'''simple docstring'''

					snake_case_									=				residue_constants.restypes + ['''X''']

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

					snake_case_									=				residue_constants.atom_types

					snake_case_									=				[]

					snake_case_									=				prot.atom_mask
					snake_case_									=				prot.aatype
					snake_case_									=				prot.atom_positions
					snake_case_									=				prot.residue_index.astype(np.intaa	)
					snake_case_									=				prot.b_factors
					snake_case_									=				prot.chain_index

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

					snake_case_									=				get_pdb_headers(__UpperCAmelCase	)
					if len(__UpperCAmelCase	) > 0:
										pdb_lines.extend(__UpperCAmelCase	)

					snake_case_									=				aatype.shape[0]
					snake_case_									=				1
					snake_case_									=				0
					snake_case_									=				string.ascii_uppercase
					snake_case_									=				None
					# Add all atom sites.
					for i in range(__UpperCAmelCase	):
										snake_case_									=				res_atoa(aatype[i]	)
										for atom_name, pos, mask, b_factor in zip(__UpperCAmelCase,      atom_positions[i],      atom_mask[i],      b_factors[i]	):
															if mask < 0.5:
																				continue

															snake_case_									=				'''ATOM'''
															snake_case_									=				atom_name if len(__UpperCAmelCase	) == 4 else F" {atom_name}"
															snake_case_									=				''''''
															snake_case_									=				''''''
															snake_case_									=				1.0_0
															snake_case_									=				atom_name[0]  # Protein supports only C, N, O, S, this works.
															snake_case_									=				''''''

															snake_case_									=				'''A'''
															if chain_index is not None:
																				snake_case_									=				chain_tags[chain_index[i]]

															# PDB is a columnar format, every space matters here!
															snake_case_									=				(
															    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(__UpperCAmelCase	)
															atom_index += 1

										snake_case_									=				i == n - 1
										if chain_index is not None:
															if i != n - 1 and chain_index[i + 1] != prev_chain_index:
																				snake_case_									=				True
																				snake_case_									=				chain_index[i + 1]

										if should_terminate:
															# Close the chain.
															snake_case_									=				'''TER'''
															snake_case_									=				(
															    F"{chain_end:<6}{atom_index:>5}      {res_atoa(aatype[i]	):>3} {chain_tag:>1}{residue_index[i]:>4}"
															)
															pdb_lines.append(__UpperCAmelCase	)
															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(__UpperCAmelCase,      __UpperCAmelCase	)	)

					pdb_lines.append('''END'''	)
					pdb_lines.append(''''''	)
					return "\n".join(__UpperCAmelCase	)


def 		__magic_name__    (	__UpperCAmelCase	)		->					np.ndarray:

					'''simple docstring'''

					return residue_constants.STANDARD_ATOM_MASK[prot.aatype]


def 		__magic_name__    (	__UpperCAmelCase,      __UpperCAmelCase,      __UpperCAmelCase = None,      __UpperCAmelCase = None,      __UpperCAmelCase = None,      __UpperCAmelCase = None,      __UpperCAmelCase = None,      )		->					Protein:

					'''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=__UpperCAmelCase,      remark=__UpperCAmelCase,      parents=__UpperCAmelCase,      parents_chain_index=__UpperCAmelCase,      )


"""simple docstring"""







import argparse
import struct
import unittest







class        UpperCamelCase		:
   def __init__(			self     ,__UpperCamelCase			)	->      None:


        '''simple docstring'''


        lowercase_	:				str													=	data

        # Initialize hash values
        lowercase_	:				Optional[int]													=	[
            0X6_A_0_9_E_6_6_7,
            0XB_B_6_7_A_E_8_5,
            0X3_C_6_E_F_3_7_2,
            0XA_5_4_F_F_5_3_A,
            0X5_1_0_E_5_2_7_F,
            0X9_B_0_5_6_8_8_C,
            0X1_F_8_3_D_9_A_B,
            0X5_B_E_0_C_D_1_9,
        ]

        # Initialize round constants
        lowercase_	:				Tuple													=	[
            0X4_2_8_A_2_F_9_8,
            0X7_1_3_7_4_4_9_1,
            0XB_5_C_0_F_B_C_F,
            0XE_9_B_5_D_B_A_5,
            0X3_9_5_6_C_2_5_B,
            0X5_9_F_1_1_1_F_1,
            0X9_2_3_F_8_2_A_4,
            0XA_B_1_C_5_E_D_5,
            0XD_8_0_7_A_A_9_8,
            0X1_2_8_3_5_B_0_1,
            0X2_4_3_1_8_5_B_E,
            0X5_5_0_C_7_D_C_3,
            0X7_2_B_E_5_D_7_4,
            0X8_0_D_E_B_1_F_E,
            0X9_B_D_C_0_6_A_7,
            0XC_1_9_B_F_1_7_4,
            0XE_4_9_B_6_9_C_1,
            0XE_F_B_E_4_7_8_6,
            0X0_F_C_1_9_D_C_6,
            0X2_4_0_C_A_1_C_C,
            0X2_D_E_9_2_C_6_F,
            0X4_A_7_4_8_4_A_A,
            0X5_C_B_0_A_9_D_C,
            0X7_6_F_9_8_8_D_A,
            0X9_8_3_E_5_1_5_2,
            0XA_8_3_1_C_6_6_D,
            0XB_0_0_3_2_7_C_8,
            0XB_F_5_9_7_F_C_7,
            0XC_6_E_0_0_B_F_3,
            0XD_5_A_7_9_1_4_7,
            0X0_6_C_A_6_3_5_1,
            0X1_4_2_9_2_9_6_7,
            0X2_7_B_7_0_A_8_5,
            0X2_E_1_B_2_1_3_8,
            0X4_D_2_C_6_D_F_C,
            0X5_3_3_8_0_D_1_3,
            0X6_5_0_A_7_3_5_4,
            0X7_6_6_A_0_A_B_B,
            0X8_1_C_2_C_9_2_E,
            0X9_2_7_2_2_C_8_5,
            0XA_2_B_F_E_8_A_1,
            0XA_8_1_A_6_6_4_B,
            0XC_2_4_B_8_B_7_0,
            0XC_7_6_C_5_1_A_3,
            0XD_1_9_2_E_8_1_9,
            0XD_6_9_9_0_6_2_4,
            0XF_4_0_E_3_5_8_5,
            0X1_0_6_A_A_0_7_0,
            0X1_9_A_4_C_1_1_6,
            0X1_E_3_7_6_C_0_8,
            0X2_7_4_8_7_7_4_C,
            0X3_4_B_0_B_C_B_5,
            0X3_9_1_C_0_C_B_3,
            0X4_E_D_8_A_A_4_A,
            0X5_B_9_C_C_A_4_F,
            0X6_8_2_E_6_F_F_3,
            0X7_4_8_F_8_2_E_E,
            0X7_8_A_5_6_3_6_F,
            0X8_4_C_8_7_8_1_4,
            0X8_C_C_7_0_2_0_8,
            0X9_0_B_E_F_F_F_A,
            0XA_4_5_0_6_C_E_B,
            0XB_E_F_9_A_3_F_7,
            0XC_6_7_1_7_8_F_2,
        ]

        lowercase_	:				Tuple													=	self.preprocessing(self.data			)
        self.final_hash()
   @staticmethod
   def 			_UpperCAmelCase   (			__UpperCamelCase			)	->      bytes:


        '''simple docstring'''


        lowercase_	:				str													=	B'\x80' + (B'\x00' * (63 - (len(__UpperCamelCase			) + 8) % 64))
        lowercase_	:				str													=	struct.pack('>Q'     ,(len(__UpperCamelCase			) * 8)			)
        return data + padding + big_endian_integer
   def 			_UpperCAmelCase   (			self			)	->      None:


        '''simple docstring'''


        lowercase_	:				Optional[Any]													=	[
            self.preprocessed_data[x : x + 64]
            for x in range(0     ,len(self.preprocessed_data			)     ,64			)
        ]

        for block in self.blocks:
             # Convert the given block into a list of 4 byte integers
             lowercase_	:				Any													=	list(struct.unpack('>16L'     ,__UpperCamelCase			)			)
             # add 48 0-ed integers
             words += [0] * 48

             lowercase_							,  lowercase_							,  lowercase_							,  lowercase_							,  lowercase_							,  lowercase_							,  lowercase_							,  lowercase_	:				Optional[int]													=	self.hashes

             for index in range(0     ,64			):
                  if index > 15:
                       # modify the zero-ed indexes at the end of the array
                       lowercase_	:				str													=	(
                           self.ror(words[index - 15]     ,7			)
                           ^ self.ror(words[index - 15]     ,18			)
                           ^ (words[index - 15] >> 3)
                       )
                       lowercase_	:				int													=	(
                           self.ror(words[index - 2]     ,17			)
                           ^ self.ror(words[index - 2]     ,19			)
                           ^ (words[index - 2] >> 10)
                       )

                       lowercase_	:				Optional[Any]													=	(
                           words[index - 16] + sa + words[index - 7] + sa
                       ) % 0X1_0_0_0_0_0_0_0_0

                  # Compression
                  lowercase_	:				Tuple													=	self.ror(__UpperCamelCase     ,6			) ^ self.ror(__UpperCamelCase     ,11			) ^ self.ror(__UpperCamelCase     ,25			)
                  lowercase_	:				Union[str, Any]													=	(e & f) ^ ((~e & 0XF_F_F_F_F_F_F_F) & g)
                  lowercase_	:				str													=	(
                      h + sa + ch + self.round_constants[index] + words[index]
                  ) % 0X1_0_0_0_0_0_0_0_0
                  lowercase_	:				Optional[int]													=	self.ror(__UpperCamelCase     ,2			) ^ self.ror(__UpperCamelCase     ,13			) ^ self.ror(__UpperCamelCase     ,22			)
                  lowercase_	:				Optional[Any]													=	(a & b) ^ (a & c) ^ (b & c)
                  lowercase_	:				Any													=	(sa + maj) % 0X1_0_0_0_0_0_0_0_0

                  lowercase_							,  lowercase_							,  lowercase_							,  lowercase_							,  lowercase_							,  lowercase_							,  lowercase_							,  lowercase_	:				Tuple													=	(
                      g,
                      f,
                      e,
                      ((d + tempa) % 0X1_0_0_0_0_0_0_0_0),
                      c,
                      b,
                      a,
                      ((tempa + tempa) % 0X1_0_0_0_0_0_0_0_0),
                  )

             lowercase_	:				str													=	[a, b, c, d, e, f, g, h]

             # Modify final values
             lowercase_	:				Dict													=	[
                 ((element + mutated_hash_values[index]) % 0X1_0_0_0_0_0_0_0_0)
                 for index, element in enumerate(self.hashes			)
             ]

        lowercase_	:				Any													=	''.join([hex(__UpperCamelCase			)[2:].zfill(8			) for value in self.hashes]			)







   def 			_UpperCAmelCase   (			self     ,__UpperCamelCase     ,__UpperCamelCase			)	->      int:


        '''simple docstring'''


        return 0XF_F_F_F_F_F_F_F & (value << (32 - rotations)) | (value >> rotations)







class        UpperCamelCase		(			unittest.TestCase  ):
   def 			_UpperCAmelCase   (			self			)	->      None:


        '''simple docstring'''


        import hashlib

        lowercase_	:				Union[str, Any]													=	bytes('Test String'     ,'utf-8'			)
        self.assertEqual(SHAaaa(__UpperCamelCase			).hash     ,hashlib.shaaaa(__UpperCamelCase			).hexdigest()			)






def 			lowercase__(       ):
     import doctest

     doctest.testmod()

     lowercase_	:				Tuple													=	argparse.ArgumentParser()
     parser.add_argument(
         '-s'     ,			'--string'     ,			dest='input_string'     ,			default='Hello World!! Welcome to Cryptography'     ,			help='Hash the string'     ,			)
     parser.add_argument(
         '-f'     ,			'--file'     ,			dest='input_file'     ,			help='Hash contents of a file'      )

     lowercase_	:				Any													=	parser.parse_args()

     lowercase_	:				int													=	args.input_string

     # hash input should be a bytestring
     if args.input_file:
          with open(args.input_file     ,			'rb'      ) as f:
               lowercase_	:				str													=	f.read()
     else:
          lowercase_	:				Optional[int]													=	bytes(__SCREAMING_SNAKE_CASE     ,			'utf-8'      )

     print(SHAaaa(__SCREAMING_SNAKE_CASE      ).hash      )


if __name__ == "__main__":
       main()

