def average_of_conformations(self): # make a new configuration to hold the average values avr_conformation = propka.conformation_container.Conformation_container(name='average', parameters=self.conformations[self.conformation_names[0]].parameters, molecular_container=self) container = self.conformations[self.conformation_names[0]] for group in container.get_groups_for_calculations(): # new group to hold average values avr_group = group.clone() # sum up all groups ... for name in self.conformation_names: group_to_add = self.conformations[name].find_group(group) if group_to_add: avr_group += group_to_add else: warning('Group %s could not be found in conformation %s.' % (group.atom.residue_label, name)) # ... and store the average value avr_group = avr_group / len(self.conformation_names) avr_conformation.groups.append(avr_group) # store information on coupling in the average container if len(list(filter(lambda c: c.non_covalently_coupled_groups, self.conformations.values()))): avr_conformation.non_covalently_coupled_groups = True # store chain info avr_conformation.chains = self.conformations[self.conformation_names[0]].chains self.conformations['AVR'] = avr_conformation return
def setup_atoms(self): # Find the atoms in the histidine ring ring_atoms = propka.ligand.is_ring_member(self.atom) if len(ring_atoms) != 5: warning('His group does not seem to contain a ring', self) # protonate ring for r in ring_atoms: my_protonator.protonate_atom(r) # set the center using the ring atoms if ring_atoms: self.set_center(ring_atoms) else: # Missing side-chain atoms self.set_center([self.atom]) # FIXME perhaps it would be better to ignore this group completely? # find the hydrogens on the ring-nitrogens hydrogens = [] nitrogens = [ra for ra in ring_atoms if ra.element == 'N'] for nitrogen in nitrogens: hydrogens.extend(nitrogen.get_bonded_elements('H')) self.set_interaction_atoms(hydrogens+nitrogens, nitrogens) return
def protein_precheck(conformations, names): for name in names: atoms = conformations[name].atoms # Group the atoms by their residue: atoms_by_residue = {} for a in atoms: if a.element != 'H': res_id = resid_from_atom(a) try: atoms_by_residue[res_id].append(a) except KeyError: atoms_by_residue[res_id] = [a] for res_id, res_atoms in atoms_by_residue.items(): resname = res_atoms[0].resName residue_label = '%3s%5s'%(resname, res_id) # ignore ligand residues if resname not in expected_atom_numbers: continue # check for c-terminal if 'C-' in [a.terminal for a in res_atoms]: if len(res_atoms) != expected_atom_numbers[resname]+1: warning('Unexpected number (%d) of atoms in residue %s in conformation %s' % (len(res_atoms), residue_label, name)) continue # check number of atoms in residue if len(res_atoms) != expected_atom_numbers[resname]: warning('Unexpected number (%d) of atoms in residue %s in conformation %s' % (len(res_atoms), residue_label, name)) return
def setup_atoms(self): # Find the atoms in the histidine ring ring_atoms = propka.ligand.is_ring_member(self.atom) if len(ring_atoms) != 5: warning('His group does not seem to contain a ring', self) # protonate ring for r in ring_atoms: my_protonator.protonate_atom(r) # set the center using the ring atoms if ring_atoms: self.set_center(ring_atoms) else: # Missing side-chain atoms self.set_center([self.atom]) # FIXME perhaps it would be better to ignore this group completely? # find the hydrogens on the ring-nitrogens hydrogens = [] nitrogens = [ra for ra in ring_atoms if ra.element == 'N'] for nitrogen in nitrogens: hydrogens.extend(nitrogen.get_bonded_elements('H')) self.set_interaction_atoms(hydrogens + nitrogens, nitrogens) return
def average_of_conformations(self): """Generate an average of conformations.""" parameters = self.conformations[self.conformation_names[0]].parameters # make a new configuration to hold the average values avr_conformation = ConformationContainer(name='average', parameters=parameters, molecular_container=self) container = self.conformations[self.conformation_names[0]] for group in container.get_groups_for_calculations(): # new group to hold average values avr_group = group.clone() # sum up all groups ... for name in self.conformation_names: group_to_add = self.conformations[name].find_group(group) if group_to_add: avr_group += group_to_add else: str_ = ('Group {0:s} could not be found in ' 'conformation {1:s}.'.format( group.atom.residue_label, name)) warning(str_) # ... and store the average value avr_group = avr_group / len(self.conformation_names) avr_conformation.groups.append(avr_group) # store information on coupling in the average container if len( list( filter(lambda c: c.non_covalently_coupled_groups, self.conformations.values()))): avr_conformation.non_covalently_coupled_groups = True # store chain info avr_conformation.chains = self.conformations[ self.conformation_names[0]].chains self.conformations['AVR'] = avr_conformation
def add_protons(self, atom): # decide which method to use debug('PROTONATING',atom) if atom.steric_number in list(self.protonation_methods.keys()): self.protonation_methods[atom.steric_number](atom) else: warning('Do not have a method for protonating', atom, '(steric number: %d)' % atom.steric_number) return
def add_protons(self, atom): # decide which method to use debug('PROTONATING', atom) if atom.steric_number in list(self.protonation_methods.keys()): self.protonation_methods[atom.steric_number](atom) else: warning('Do not have a method for protonating', atom, '(steric number: %d)' % atom.steric_number) return
def set_bond_distance(self, a, element): d = 1.0 if element in list(self.bond_lengths.keys()): d = self.bond_lengths[element] else: warning('Bond length for %s not found, using the standard value of %f' % (element, d)) a = a.rescale(d) return a
def get_marvin_pkas_for_molecule(self, atoms, filename='__tmp_ligand.mol2', reuse=False, no_pkas=10, min_pH=-10, max_pH=20): # print out structure unless we are using user-modified structure if not reuse: propka.pdb.write_mol2_for_atoms(atoms, filename) # check that we actually have a file to work with if not os.path.isfile(filename): warning( 'Didn\'t find a user-modified file \'%s\' - generating one' % filename) propka.pdb.write_mol2_for_atoms(atoms, filename) # Marvin # calculate pKa values options = 'pka -a %d -b %d --min %f --max %f -d large' % ( no_pkas, no_pkas, min_pH, max_pH) (output, errors) = subprocess.Popen([self.cxcalc, filename] + options.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() if len(errors) > 0: info( '********************************************************************************************************' ) info( '* Warning: Marvin execution failed: *' ) info('* %-100s *' % errors) info( '* *' ) info( '* Please edit the ligand mol2 file and re-run PropKa with the -l option: %29s *' % filename) info( '********************************************************************************************************' ) sys.exit(-1) # extract calculated pkas indices, pkas, types = self.extract_pkas(output) # store calculated pka values for i in range(len(indices)): atoms[indices[i]].marvin_pka = pkas[i] atoms[indices[i]].charge = {'a': -1, 'b': +1}[types[i]] info('%s model pKa: %.2f' % (atoms[indices[i]], pkas[i])) return
def get_marvin_pkas_for_molecule(self, atoms, filename='__tmp_ligand.mol2', reuse=False, num_pkas=10, min_ph=-10, max_ph=20): """Use Marvin executables to calculate pKas for a molecule. Args: molecule: the molecule name: filename reuse: flag to reuse the structure files num_pkas: number of pKas to calculate min_ph: minimum pH value max_ph: maximum pH value """ # print out structure unless we are using user-modified structure if not reuse: write_mol2_for_atoms(atoms, filename) # check that we actually have a file to work with if not os.path.isfile(filename): errstr = ( "Didn't find a user-modified file '{0:s}' " "- generating one".format( filename)) warning(errstr) write_mol2_for_atoms(atoms, filename) # Marvin calculate pKa values fmt = ( 'pka -a {num1} -b {num2} --min {min_ph} ' '--max {max_ph} -d large') options = ( fmt.format( num1=num_pkas, num2=num_pkas, min_ph=min_ph, max_ph=max_ph)) (output, errors) = subprocess.Popen( [self.cxcalc, filename]+options.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() if len(errors) > 0: info('***********************************************************' '*********************************************') info('* Warning: Marvin execution failed: ' ' *') info('* {0:<100s} *'.format(errors)) info('* ' ' *') info('* Please edit the ligand mol2 file and re-run PropKa with ' 'the -l option: {0:>29s} *'.format(filename)) info('***********************************************************' '*********************************************') sys.exit(-1) # extract calculated pkas indices, pkas, types = self.extract_pkas(output) # store calculated pka values for i, index in enumerate(indices): atoms[index].marvin_pka = pkas[i] atoms[index].charge = {'a': -1, 'b': 1}[types[i]] info('{0:s} model pKa: {1:<.2f}'.format(atoms[index], pkas[i]))
def set_bond_distance(self, a, element): d = 1.0 if element in list(self.bond_lengths.keys()): d = self.bond_lengths[element] else: warning( 'Bond length for %s not found, using the standard value of %f' % (element, d)) a = a.rescale(d) return a
def insert(self, k1, k2, v): if k1 in self.dictionary.keys() and k2 in self.dictionary[k1].keys(): if k1 != k2: warning("Parameter value for %s, %s defined more than once" % (k1, k2)) if not k1 in self.dictionary: self.dictionary[k1] = {} self.dictionary[k1][k2] = v return
def add_protons(self, atom): """Add protons to atom. Args: atom: atom for calculation """ # decide which method to use debug('PROTONATING', atom) if atom.steric_number in list(self.protonation_methods.keys()): self.protonation_methods[atom.steric_number](atom) else: warning('Do not have a method for protonating', atom, '(steric number: {0:d})'.format(atom.steric_number))
def insert(self, k1, k2, v): if k1 in self.dictionary.keys() and k2 in self.dictionary[k1].keys(): if k1 != k2: warning('Parameter value for %s, %s defined more than once' % (k1, k2)) if not k1 in self.dictionary: self.dictionary[k1] = {} self.dictionary[k1][k2] = v return
def insert(self, key1, key2, value): """Insert value into matrix. Args: key1: first matrix key (row) key2: second matrix key (column) value: value to insert """ if key1 in self.dictionary and key2 in self.dictionary[key1]: if key1 != key2: str_ = ('Parameter value for {0:s}, {1:s} defined more ' 'than once'.format(key1, key2)) warning(str_) if not key1 in self.dictionary: self.dictionary[key1] = {} self.dictionary[key1][key2] = value
def set_bond_distance(self, bvec, element): """Set bond distance between atom and element. Args: bvec: bond vector element: bonded element Returns: scaled bond vector """ dist = 1.0 if element in list(self.bond_lengths.keys()): dist = self.bond_lengths[element] else: str_ = ( 'Bond length for {0:s} not found, using the standard value ' 'of {1:f}'.format(element, dist)) warning(str_) bvec = bvec.rescale(dist) return bvec
def protein_precheck(conformations, names): for name in names: atoms = conformations[name].atoms # Group the atoms by their residue: atoms_by_residue = {} for a in atoms: if a.element != 'H': res_id = resid_from_atom(a) try: atoms_by_residue[res_id].append(a) except KeyError: atoms_by_residue[res_id] = [a] for res_id, res_atoms in atoms_by_residue.items(): resname = res_atoms[0].resName residue_label = '%3s%5s' % (resname, res_id) # ignore ligand residues if resname not in expected_atom_numbers: continue # check for c-terminal if 'C-' in [a.terminal for a in res_atoms]: if len(res_atoms) != expected_atom_numbers[resname] + 1: warning( 'Unexpected number (%d) of atoms in residue %s in conformation %s' % (len(res_atoms), residue_label, name)) continue # check number of atoms in residue if len(res_atoms) != expected_atom_numbers[resname]: warning( 'Unexpected number (%d) of atoms in residue %s in conformation %s' % (len(res_atoms), residue_label, name)) return
def get_marvin_pkas_for_molecule(self, atoms, filename='__tmp_ligand.mol2', reuse=False, no_pkas=10, min_pH =-10, max_pH=20): # print out structure unless we are using user-modified structure if not reuse: propka.pdb.write_mol2_for_atoms(atoms, filename) # check that we actually have a file to work with if not os.path.isfile(filename): warning('Didn\'t find a user-modified file \'%s\' - generating one' % filename) propka.pdb.write_mol2_for_atoms(atoms, filename) # Marvin # calculate pKa values options = 'pka -a %d -b %d --min %f --max %f -d large'%(no_pkas, no_pkas, min_pH, max_pH) (output,errors) = subprocess.Popen([self.cxcalc, filename]+options.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() if len(errors)>0: info('********************************************************************************************************') info('* Warning: Marvin execution failed: *') info('* %-100s *' % errors) info('* *') info('* Please edit the ligand mol2 file and re-run PropKa with the -l option: %29s *' % filename) info('********************************************************************************************************') sys.exit(-1) # extract calculated pkas indices,pkas,types = self.extract_pkas(output) # store calculated pka values for i in range(len(indices)): atoms[indices[i]].marvin_pka = pkas[i] atoms[indices[i]].charge = {'a':-1,'b':+1}[types[i]] info('%s model pKa: %.2f' % (atoms[indices[i]], pkas[i])) return
def set_interaction_atoms(self, interaction_atoms_for_acids, interaction_atoms_for_bases): [a.set_group_type(self.type) for a in interaction_atoms_for_acids+interaction_atoms_for_bases] self.interaction_atoms_for_acids = interaction_atoms_for_acids self.interaction_atoms_for_bases = interaction_atoms_for_bases # check if all atoms have been identified ok = True for [expect, found, t] in [[expected_atoms_acid_interactions, self.interaction_atoms_for_acids, 'acid'], [expected_atoms_base_interactions, self.interaction_atoms_for_bases, 'base']]: if self.type in expect.keys(): for e in expect[self.type].keys(): if len([a for a in found if a.element==e]) != expect[self.type][e]: ok = False if not ok: warning('Missing atoms or failed protonation for %s (%s) -- please check the structure' % (self.label, self.type)) warning('%s' % self) Na = sum([expected_atoms_acid_interactions[self.type][e] for e in expected_atoms_acid_interactions[self.type].keys()]) Nb = sum([expected_atoms_base_interactions[self.type][e] for e in expected_atoms_base_interactions[self.type].keys()]) warning('Expected %d interaction atoms for acids, found:' % Na) for i in range(len(self.interaction_atoms_for_acids)): warning(' %s' % self.interaction_atoms_for_acids[i]) warning('Expected %d interaction atoms for bases, found:' % Nb) for i in range(len(self.interaction_atoms_for_bases)): warning(' %s' % self.interaction_atoms_for_bases[i]) #return return
def hydrogen_bond_interaction(group1, group2, version): # find the smallest distance between interacting atoms atoms1 = group1.get_interaction_atoms(group2) atoms2 = group2.get_interaction_atoms(group1) [closest_atom1, distance, closest_atom2 ] = propka.calculations.get_smallest_distance(atoms1, atoms2) if None in [closest_atom1, closest_atom2]: warning('Side chain interaction failed for %s and %s' % (group1.label, group2.label)) return None # get the parameters [dpka_max, cutoff] = version.get_hydrogen_bond_parameters(closest_atom1, closest_atom2) if dpka_max == None or None in cutoff: return None # check that the closest atoms are close enough if distance >= cutoff[1]: return None # check that bond distance criteria is met bond_distance_too_short = group1.atom.is_atom_within_bond_distance( group2.atom, version.parameters.min_bond_distance_for_hydrogen_bonds, 1) if bond_distance_too_short: return None # set the angle factor # # ---closest_atom1/2 # . # . # the_hydrogen---closest_atom2/1--- f_angle = 1.0 if group2.type in version.parameters.angular_dependent_sidechain_interactions: if closest_atom2.element == 'H': heavy_atom = closest_atom2.bonded_atoms[0] hydrogen = closest_atom2 distance, f_angle, nada = propka.calculations.AngleFactorX( closest_atom1, hydrogen, heavy_atom) else: # Either the structure is corrupt (no hydrogen), or the heavy atom is closer to # the titratable atom than the hydrogen. In either case we set the angle factor # to 0 f_angle = 0.0 elif group1.type in version.parameters.angular_dependent_sidechain_interactions: if closest_atom1.element == 'H': heavy_atom = closest_atom1.bonded_atoms[0] hydrogen = closest_atom1 distance, f_angle, nada = propka.calculations.AngleFactorX( closest_atom2, hydrogen, heavy_atom) else: # Either the structure is corrupt (no hydrogen), or the heavy atom is closer to # the titratable atom than the hydrogen. In either case we set the angle factor # to 0 f_angle = 0.0 weight = version.calculatePairWeight(group1.Nmass, group2.Nmass) exception, value = version.checkExceptions(group1, group2) #exception = False # circumventing exception if exception == True: """ do nothing, value should have been assigned """ #info(" exception for %s %s %6.2lf" % (group1.label, group2.label, value)) else: value = version.calculateSideChainEnergy(distance, dpka_max, cutoff, weight, f_angle) # info('distance',distance) # info('dpka_max',dpka_max) # info('cutoff',cutoff) # info('f_angle',f_angle) # info('weight',weight) # info('value',value) # info('===============================================') return value
def set_interaction_atoms(self, interaction_atoms_for_acids, interaction_atoms_for_bases): [ a.set_group_type(self.type) for a in interaction_atoms_for_acids + interaction_atoms_for_bases ] self.interaction_atoms_for_acids = interaction_atoms_for_acids self.interaction_atoms_for_bases = interaction_atoms_for_bases # check if all atoms have been identified ok = True for [expect, found, t] in [[ expected_atoms_acid_interactions, self.interaction_atoms_for_acids, 'acid' ], [ expected_atoms_base_interactions, self.interaction_atoms_for_bases, 'base' ]]: if self.type in expect.keys(): for e in expect[self.type].keys(): if len([a for a in found if a.element == e ]) != expect[self.type][e]: ok = False if not ok: warning( 'Missing atoms or failed protonation for %s (%s) -- please check the structure' % (self.label, self.type)) warning('%s' % self) Na = sum([ expected_atoms_acid_interactions[self.type][e] for e in expected_atoms_acid_interactions[self.type].keys() ]) Nb = sum([ expected_atoms_base_interactions[self.type][e] for e in expected_atoms_base_interactions[self.type].keys() ]) warning('Expected %d interaction atoms for acids, found:' % Na) for i in range(len(self.interaction_atoms_for_acids)): warning(' %s' % self.interaction_atoms_for_acids[i]) warning('Expected %d interaction atoms for bases, found:' % Nb) for i in range(len(self.interaction_atoms_for_bases)): warning(' %s' % self.interaction_atoms_for_bases[i]) #return return
def set_interaction_atoms(self, interaction_atoms_for_acids, interaction_atoms_for_bases): """Set interacting atoms and group types. Args: interaction_atoms_for_acids: list of atoms for acid interactions interaction_atoms_for_base: list of atoms for base interactions """ for atom in interaction_atoms_for_acids + interaction_atoms_for_bases: atom.set_group_type(self.type) self.interaction_atoms_for_acids = interaction_atoms_for_acids self.interaction_atoms_for_bases = interaction_atoms_for_bases # check if all atoms have been identified ok = True for [expect, found, _] in [[ EXPECTED_ATOMS_ACID_INTERACTIONS, self.interaction_atoms_for_acids, 'acid' ], [ EXPECTED_ATOMS_BASE_INTERACTIONS, self.interaction_atoms_for_bases, 'base' ]]: if self.type in expect.keys(): for elem in expect[self.type].keys(): if (len([a for a in found if a.element == elem]) != expect[self.type][elem]): ok = False if not ok: str_ = 'Missing atoms or failed protonation for ' str_ += '{0:s} ({1:s}) -- please check the structure'.format( self.label, self.type) warning(str_) warning('{0:s}'.format(str(self))) num_acid = sum([ EXPECTED_ATOMS_ACID_INTERACTIONS[self.type][e] for e in EXPECTED_ATOMS_ACID_INTERACTIONS[self.type].keys() ]) num_base = sum([ EXPECTED_ATOMS_BASE_INTERACTIONS[self.type][e] for e in EXPECTED_ATOMS_BASE_INTERACTIONS[self.type].keys() ]) warning( 'Expected {0:d} interaction atoms for acids, found:'.format( num_acid)) for i in range(len(self.interaction_atoms_for_acids)): warning(' {0:s}'.format( str(self.interaction_atoms_for_acids[i]))) warning( 'Expected {0:d} interaction atoms for bases, found:'.format( num_base)) for i in range(len(self.interaction_atoms_for_bases)): warning(' {0:s}'.format( str(self.interaction_atoms_for_bases[i])))
def hydrogen_bond_interaction(group1, group2, version): """Calculate energy for hydrogen bond interactions between two groups. Args: group1: first interacting group group2: second interacting group version: an object that contains version-specific parameters Returns: hydrogen bond interaction energy """ # find the smallest distance between interacting atoms atoms1 = group1.get_interaction_atoms(group2) atoms2 = group2.get_interaction_atoms(group1) [closest_atom1, dist, closest_atom2] = get_smallest_distance(atoms1, atoms2) if None in [closest_atom1, closest_atom2]: warning('Side chain interaction failed for {0:s} and {1:s}'.format( group1.label, group2.label)) return None # get the parameters [dpka_max, cutoff] = version.get_hydrogen_bond_parameters(closest_atom1, closest_atom2) if (dpka_max is None) or (None in cutoff): return None # check that the closest atoms are close enough if dist >= cutoff[1]: return None # check that bond distance criteria is met min_hbond_dist = version.parameters.min_bond_distance_for_hydrogen_bonds if group1.atom.is_atom_within_bond_distance(group2.atom, min_hbond_dist, 1): return None # set angle factor f_angle = 1.0 if group2.type in version.parameters.angular_dependent_sidechain_interactions: if closest_atom2.element == 'H': heavy_atom = closest_atom2.bonded_atoms[0] hydrogen = closest_atom2 dist, f_angle, _ = angle_distance_factors(closest_atom1, hydrogen, heavy_atom) else: # Either the structure is corrupt (no hydrogen), or the heavy atom # is closer to the titratable atom than the hydrogen. In either # case, we set the angle factor to 0 f_angle = 0.0 elif group1.type in version.parameters.angular_dependent_sidechain_interactions: if closest_atom1.element == 'H': heavy_atom = closest_atom1.bonded_atoms[0] hydrogen = closest_atom1 dist, f_angle, _ = angle_distance_factors(closest_atom2, hydrogen, heavy_atom) else: # Either the structure is corrupt (no hydrogen), or the heavy atom # is closer to the titratable atom than the hydrogen. In either # case, we set the angle factor to 0 f_angle = 0.0 weight = version.calculate_pair_weight(group1.num_volume, group2.num_volume) exception, value = version.check_exceptions(group1, group2) if exception: # Do nothing, value should have been assigned. pass else: value = version.calculate_side_chain_energy(dist, dpka_max, cutoff, weight, f_angle) return value
def hydrogen_bond_interaction(group1, group2, version): # find the smallest distance between interacting atoms atoms1 = group1.get_interaction_atoms(group2) atoms2 = group2.get_interaction_atoms(group1) [closest_atom1, distance, closest_atom2] = propka.calculations.get_smallest_distance(atoms1, atoms2) if None in [closest_atom1, closest_atom2]: warning('Side chain interaction failed for %s and %s' % (group1.label, group2.label)) return None # get the parameters [dpka_max, cutoff] = version.get_hydrogen_bond_parameters(closest_atom1,closest_atom2) if dpka_max==None or None in cutoff: return None # check that the closest atoms are close enough if distance >= cutoff[1]: return None # check that bond distance criteria is met bond_distance_too_short = group1.atom.is_atom_within_bond_distance(group2.atom, version.parameters.min_bond_distance_for_hydrogen_bonds,1) if bond_distance_too_short: return None # set the angle factor # # ---closest_atom1/2 # . # . # the_hydrogen---closest_atom2/1--- f_angle = 1.0 if group2.type in version.parameters.angular_dependent_sidechain_interactions: if closest_atom2.element == 'H': heavy_atom = closest_atom2.bonded_atoms[0] hydrogen = closest_atom2 distance, f_angle, nada = propka.calculations.AngleFactorX(closest_atom1, hydrogen, heavy_atom) else: # Either the structure is corrupt (no hydrogen), or the heavy atom is closer to # the titratable atom than the hydrogen. In either case we set the angle factor # to 0 f_angle = 0.0 elif group1.type in version.parameters.angular_dependent_sidechain_interactions: if closest_atom1.element == 'H': heavy_atom = closest_atom1.bonded_atoms[0] hydrogen = closest_atom1 distance, f_angle, nada = propka.calculations.AngleFactorX(closest_atom2, hydrogen, heavy_atom) else: # Either the structure is corrupt (no hydrogen), or the heavy atom is closer to # the titratable atom than the hydrogen. In either case we set the angle factor # to 0 f_angle = 0.0 weight = version.calculatePairWeight(group1.Nmass, group2.Nmass) exception, value = version.checkExceptions(group1, group2) #exception = False # circumventing exception if exception == True: """ do nothing, value should have been assigned """ #info(" exception for %s %s %6.2lf" % (group1.label, group2.label, value)) else: value = version.calculateSideChainEnergy(distance, dpka_max, cutoff, weight, f_angle) # info('distance',distance) # info('dpka_max',dpka_max) # info('cutoff',cutoff) # info('f_angle',f_angle) # info('weight',weight) # info('value',value) # info('===============================================') return value