from .description import Description from .workspaceObject import WorkspaceObject from . import formulas class Group(WorkspaceObject): # pylint: disable=too-many-instance-attributes def __init__(self, string, groupCategory, directionCategory, facet, objectList, bondList): # pylint: disable=too-many-arguments WorkspaceObject.__init__(self, string) slipnet = self.ctx.slipnet self.groupCategory = groupCategory self.directionCategory = directionCategory self.facet = facet self.objectList = objectList self.bondList = bondList self.bondCategory = self.groupCategory.getRelatedNode( slipnet.bondCategory) leftObject = objectList[0] rightObject = objectList[-1] self.leftIndex = leftObject.leftIndex self.leftmost = self.leftIndex == 1 self.rightIndex = rightObject.rightIndex self.rightmost = self.rightIndex == len(self.string) self.descriptions = [] self.bondDescriptions = [] self.name = '' if self.bondList and len(self.bondList): firstFacet = self.bondList[0].facet self.addBondDescription( Description(self, slipnet.bondFacet, firstFacet)) self.addBondDescription( Description(self, slipnet.bondCategory, self.bondCategory)) self.addDescription(slipnet.objectCategory, slipnet.group) self.addDescription(slipnet.groupCategory, self.groupCategory) if not self.directionCategory: # sameness group - find letterCategory letter = self.objectList[0].getDescriptor(self.facet) self.addDescription(self.facet, letter) if self.directionCategory: self.addDescription(slipnet.directionCategory, self.directionCategory) if self.spansString(): self.addDescription(slipnet.stringPositionCategory, slipnet.whole) elif self.leftmost: self.addDescription(slipnet.stringPositionCategory, slipnet.leftmost) elif self.rightmost: self.addDescription(slipnet.stringPositionCategory, slipnet.rightmost) elif self.middleObject(): self.addDescription(slipnet.stringPositionCategory, slipnet.middle) self.add_length_description_category() def add_length_description_category(self): # check whether or not to add length description category random = self.ctx.random slipnet = self.ctx.slipnet probability = self.lengthDescriptionProbability() if random.coinFlip(probability): length = len(self.objectList) if length < 6: self.addDescription(slipnet.length, slipnet.numbers[length - 1]) def __str__(self): s = self.string.__str__() l = self.leftIndex - 1 r = self.rightIndex return 'group[%d:%d] == %s' % (l, r - 1, s[l:r]) def getIncompatibleGroups(self): result = [] for objekt in self.objectList: while objekt.group: result += [objekt.group] objekt = objekt.group return result def addBondDescription(self, description): self.bondDescriptions += [description] def singleLetterGroupProbability(self): slipnet = self.ctx.slipnet temperature = self.ctx.temperature numberOfSupporters = self.numberOfLocalSupportingGroups() if not numberOfSupporters: return 0.0 if numberOfSupporters == 1: exp = 4.0 elif numberOfSupporters == 2: exp = 2.0 else: exp = 1.0 support = self.localSupport() / 100.0 activation = slipnet.length.activation / 100.0 supportedActivation = (support * activation) ** exp #TODO: use entropy return temperature.getAdjustedProbability(supportedActivation) def flippedVersion(self): slipnet = self.ctx.slipnet flippedBonds = [b.flippedversion() for b in self.bondList] flippedGroup = self.groupCategory.getRelatedNode(slipnet.flipped) flippedDirection = self.directionCategory.getRelatedNode( slipnet.flipped) return Group(self.string, flippedGroup, flippedDirection, self.facet, self.objectList, flippedBonds) def buildGroup(self): workspace = self.ctx.workspace workspace.objects += [self] workspace.structures += [self] self.string.objects += [self] for objekt in self.objectList: objekt.group = self workspace.buildDescriptions(self) self.activateDescriptions() def activateDescriptions(self): for description in self.descriptions: description.descriptor.buffer = 100.0 def lengthDescriptionProbability(self): slipnet = self.ctx.slipnet temperature = self.ctx.temperature length = len(self.objectList) if length > 5: return 0.0 cubedlength = length ** 3 fred = cubedlength * (100.0 - slipnet.length.activation) / 100.0 probability = 0.5 ** fred #TODO: use entropy value = temperature.getAdjustedProbability(probability) if value < 0.06: value = 0.0 return value def break_the_structure(self): self.breakGroup() def breakGroup(self): workspace = self.ctx.workspace if self.correspondence: self.correspondence.breakCorrespondence() if self.group: self.group.breakGroup() if self.leftBond: self.leftBond.breakBond() if self.rightBond: self.rightBond.breakBond() while len(self.descriptions): description = self.descriptions[-1] description.breakDescription() for o in self.objectList: o.group = None if self in workspace.structures: workspace.structures.remove(self) if self in workspace.objects: workspace.objects.remove(self) if self in self.string.objects: self.string.objects.remove(self) def updateInternalStrength(self): slipnet = self.ctx.slipnet relatedBondAssociation = self.groupCategory.getRelatedNode( slipnet.bondCategory).degreeOfAssociation() bondWeight = relatedBondAssociation ** 0.98 length = len(self.objectList) if length == 1: lengthFactor = 5.0 elif length == 2: lengthFactor = 20.0 elif length == 3: lengthFactor = 60.0 else: lengthFactor = 90.0 lengthWeight = 100.0 - bondWeight weightList = ((relatedBondAssociation, bondWeight), (lengthFactor, lengthWeight)) self.internalStrength = formulas.weightedAverage(weightList) def updateExternalStrength(self): if self.spansString(): self.externalStrength = 100.0 else: self.externalStrength = self.localSupport() def localSupport(self): numberOfSupporters = self.numberOfLocalSupportingGroups() if numberOfSupporters == 0: return 0.0 supportFactor = min(1.0, 0.6 ** (1 / (numberOfSupporters ** 3))) densityFactor = 100.0 * ((self.localDensity() / 100.0) ** 0.5) return densityFactor * supportFactor def numberOfLocalSupportingGroups(self): count = 0 for objekt in self.string.objects: if isinstance(objekt, Group) and self.isOutsideOf(objekt): if (objekt.groupCategory == self.groupCategory and objekt.directionCategory == self.directionCategory): count += 1 return count def localDensity(self): numberOfSupporters = self.numberOfLocalSupportingGroups() halfLength = len(self.string) / 2.0 return 100.0 * numberOfSupporters / halfLength def sameGroup(self, other): if self.leftIndex != other.leftIndex: return False if self.rightIndex != other.rightIndex: return False if self.groupCategory != other.groupCategory: return False if self.directionCategory != other.directionCategory: return False if self.facet != other.facet: return False return True def distinguishingDescriptor(self, descriptor): """Whether no other object of the same type has the same descriptor""" if not WorkspaceObject.distinguishingDescriptor(self, descriptor): return False for objekt in self.string.objects: # check to see if they are of the same type if isinstance(objekt, Group) and objekt != self: # check all descriptions for the descriptor for description in objekt.descriptions: if description.descriptor == descriptor: return False return True