def stringToComp(self, original): sideChains = [] nameArr = original.split('-') for i in range (len(nameArr)):#sec-butyl to secbutyl or similar and get rid of the di/tri/etc. stuff nameArr[i] = self.cropNumPrefix(nameArr[i])[1] if nameArr[i] in self.hyphenatedPrefixes: nameArr[i] = "(" + nameArr[i] + ")" + nameArr[i+1] del nameArr[i+1] if nameArr[-1] in self.suffixes: #the @@@@-5-ol case name = nameArr.pop() location = nameArr.pop() sideChains.append([self.getShape(name), location]) splitMain = self.cropSuffix(nameArr.pop()) secondSplit = self.cropPrefix(splitMain[0]) if secondSplit[0] != '' and nameArr[-1][0].isdigit(): #the 5-methyl@@@@ case location = nameArr.pop() secondSplit[0] = self.cropYL(secondSplit[0]) sideChains.append([ self.getShape(secondSplit[0]), location]) splitMain[0] = secondSplit[1] if splitMain[1] != 'ane' and splitMain[1] != 'an': sideChains.append([ self.getShape(splitMain[1]), 0]) elif splitMain[1] != 'ane' and len(nameArr) > 0 and nameArr[-1][0].isdigit(): #the 5-@@@@-ol case if len(nameArr[-1]) > 1: #meaning mutliple sidechains --> need to also remove the di/tri/etc. prefix/suffix thing splitMain[0] = self.cropNumPrefix(splitMain[0])[1] location = nameArr.pop() sideChains.append( self.getShape([splitMain[1], location])) if (splitMain[0][-1] == 'a'): #hexa --> hex splitMain[0]= splitMain[0][:-1] cycloBool = False if len(splitMain[0]) >5 and splitMain[0][:5] == 'cyclo': #if cyclo, gets rid of the cyclo bit and sets cyclo to be true cycloBool = True splitMain[0] = splitMain[0][5:] mainCompound = None if splitMain[0] in self.alkaneRoots: mainCompound = Compound( self.alkaneRoots[splitMain[0]], cycloBool)##here is the main compound else: if splitMain[0] in self.sideChainRoots: mainCompound = Compound(self.sideChainRoots[splitMain[0]], cycloBool) else: raise Exception('I do not recognize ", splitMain[0]') for i in range(0, len(nameArr), 2): sideChains.append( [self.getShape(nameArr[1]), nameArr[0]]) del nameArr[0] #deletes the chain and its location, which was just added to the sideChains del nameArr[0] for i in range(len(sideChains)): #parse the location into an int array j = 0 locs = [] while j<len(sideChains[i][1]): if sideChains[i][1][j] == ',': locs.append(int(sideChains[i][1][:j] )) sideChains[i][1] = sideChains[i][1][j+1:] j = 0 j += 1 locs.append(int(sideChains[i][1])) sideChains[i][1] = locs mainCompound.addSideChains(sideChains) return mainCompound
def getCompound(self): cp1 = Compound() tok1 = self.lex.getLookAheadToken() while (tok1.getTokType() == TokenType.ID or tok1.getTokType() == TokenType.IF or tok1.getTokType() is TokenType.PRINT # should have == instead of is or tok1.getTokType() == TokenType.FROM): state1 = self.getStatement() cp1.addStatement(state1) tok1 = self.lex.getLookAheadToken() return cp1
def getCompound(self): comp= Compound() s = self.getStatement() comp.add(s) tok = self.lex.getLookaheadToken() while self.isValidStartOfStatement(tok): s= self.getStatement() comp.add(s) tok= self.lex.getLookaheadToken() return comp
def molecularFormula(self): empiricalFormula = self.empiricalFormula() compound = Compound(empiricalFormula) if self.availableMass == 0: return "No Mass Inputted" multiplier = self.availableMass / compound.molarMass() molecularFormula = { symbol: round(quantity * multiplier) for symbol, quantity in empiricalFormula.items() } return molecularFormula
def bond(e1, e2): if not isinstance(e1, Element): raise TypeError("First item is not an element") elif not isinstance(e2, Element): raise TypeError("First item is not an element") if (e1.dictionary['type'] == 'Non Metal' and e2.dictionary['type'] == 'Non Metal') \ and (abs(e1.dictionary['electronegativity'] - e2.dictionary['electronegativity']) < 2): return Compound({e1: abs(charge(e2)), e2: abs(charge(e1))}, 'covalent') elif (e1.dictionary['type'] == 'Metal' and e2.dictionary['type'] == 'Non Metal') \ or (e1.dictionary['type'] == 'Non Metal' and e2.dictionary['type'] == 'Metal'): return Compound({e1: abs(charge(e2)), e2: abs(charge(e1))}, 'ionic') elif e1.dictionary['type'] == 'Metal' and e2.dictionary['type'] == 'Metal': return Compound({e1: abs(charge(e2)), e2: abs(charge(e1))}, 'metallic') else: return Compound({e1: abs(charge(e2)), e2: abs(charge(e1))}, None)
async def molarMass(inputs, author, channel): malformedCompounds = [] validCompounds = [] for item in inputs: if Compound.isMalformed(item): malformedCompounds.append(item) continue compound = Compound(item) # class used to calculate molar mass validCompounds.append(compound) # if there are malformed compounds if malformedCompounds: await channel.send( f"{author} Error: Invalid Compound(s): " f"{', '.join(malformedCompounds)}. Please try again.") else: await channel.send(f"{author} ```Molar Mass(es)\n" f"{showMolarMass(validCompounds)}```")
def p_compound(self, p): '''Compound : Id checkIdIsCompoundOrElem | Id checkIdIsElem Integer | FormFunc Bond FormFunc | Id checkIdIsElem Bond FormFunc | FormFunc Bond Id checkIdIsElem | Id checkIdIsElem Bond Id checkIdIsElem | FormFunc''' # print(p[2]) if self.trace: print("--Compound: ") if len(p) > 5: if p[2] and p[5]: p[0] = utils.manageTermOperation(self.variables.get(p[1]), p[3],self.variables.get(p[4])) else: raise TypeError("Invalid Ids passed as compound") elif len(p) > 4: if p[2] == '&': if p[4]: p[0] = utils.manageTermOperation(p[1], p[2],self.variables.get(p[3])) else: raise TypeError("Invalid Id passed as Element") else: if p[4]: p[0] = utils.manageTermOperation(self.variables.get(p[1]), p[3],p[4]) else: raise TypeError("Invalid Id passed as Element") elif len(p) > 3: if p[2] == '&': p[0] = utils.manageTermOperation(p[1], p[2], p[3]) else: p[0] = Compound({self.variables.get(p[1]):p[3]}, "covalent") elif len(p) > 2: if p[2]: if isinstance(self.variables.get(p[1]), Element): p[0] = Compound({self.variables.get(p[1]):1}, "covalent") else: p[0] = self.variables.get(p[1]) else: raise TypeError("Invalid Id passed as compound") else: p[0] = Compound({p[1]:1}, "covalent")
def availableElements(self, reactants, products): availableElements = [] compounds = reactants + products for compound in compounds: compound = Compound(compound) for part in compound: if part not in availableElements: availableElements.append(part) return availableElements
def _findBalancedEquation(self, unBalancedEquation): balancedEquation = "" rawEquation = [[ compound.strip() for compound in re.split(r"\+", side.strip()) ] for side in re.split("->|=", unBalancedEquation)] realSolution = True reactants = rawEquation[0] products = rawEquation[1] print(f"{reactants=}, {products=}") availableElements = self.availableElements( reactants, products) # unique elements within the chem eq print(f"{availableElements=}") matrixA = [] vectorB = [] # Initialize the matrix and vector for availableElement in availableElements: matrixEntry = [] vectorEntry = [] for index in range(len(reactants)): exists = False compound = Compound(reactants[index]) for constituentPart in compound: if availableElement == constituentPart: exists = True coefficient = compound[constituentPart] matrixEntry.append(coefficient) if not exists: matrixEntry.append(0) for index in range(len(products)): exists = False compound = Compound(products[index]) constituentParts = compound.keys() # last entry if len(products) - 1 == index: for constituentPart in constituentParts: if availableElement == constituentPart: exists = True coefficient = compound[constituentPart] vectorEntry.append(coefficient) if not exists: vectorEntry.append(0) else: for constituentPart in constituentParts: if availableElement == constituentPart: exists = True coefficient = compound[constituentPart] matrixEntry.append(-coefficient) # matrixEntry.append(-coefficient) if not exists: matrixEntry.append(0) matrixA.append(matrixEntry) vectorB.append(vectorEntry) print(f"{matrixA=}, {vectorB=}") matrixA = np.array(matrixA) vectorB = np.array(vectorB) linearRegression = np.linalg.lstsq(matrixA, vectorB, rcond=None) solution = linearRegression[0] residual = linearRegression[ 1] # this shows whether there are real solutions or not # print(f"{solution=}, {residual=}") # if there are residuals if residual.size > 0: # this equation most likely does not exist in real life and probably has no real solution realSolution = False if realSolution: determinantOfA = np.linalg.det(matrixA) solution *= determinantOfA gcd = np.gcd.reduce(np.round(solution).astype(int)) solution /= gcd solution = np.round(solution).astype(int) print(f"1. {solution=}") for index, reactant in enumerate(reactants): coefficient = abs(solution[index])[0] if index == len(reactants) - 1: if coefficient == 1: balancedEquation += f"{reactant} ->" else: balancedEquation += f"{coefficient}{reactant} ->" else: if coefficient == 1: balancedEquation += f"{reactant} + " else: balancedEquation += f"{coefficient}{reactant} + " for index, product in enumerate(products): index += len(reactants) if index >= len(product) - 1: coefficient = abs(int(determinantOfA / gcd)) if coefficient == 1: balancedEquation += f" {product}" else: balancedEquation += f" {coefficient}{product}" else: coefficient = abs(solution[index]) if coefficient == 1: balancedEquation += f" {product} + " else: balancedEquation += f" {coefficient}{product} + " else: balancedEquation = f"No Real Solution for {self.__unBalancedEquation}" return balancedEquation
scale = 1 # My Mac desktop seems to have a different dot-pitch than what TK is expecting ppmm = scale * root.winfo_fpixels('1m') * (100 / 70) cp = CAMParameters() render_params = RenderParameters(ppmm, cp) depth = -0.20 c = tk.Canvas(root, bg="#b87333", width=cp.board_w * ppmm, height=cp.board_h * ppmm) # ----------------------------------------------------------------- # A hard-coded board design for testing. This will come from # an external file once we are finished. e = Compound() """ # ---- IQ Modulator Project --------------------------------------- # Top grid e.add((30, 0), Grid(6, 1)) e.add((15, 10), Dip8(True)) e.add((55, 10), Dip8(True)) e.add((10, 25), Grid(6, 2)) e.add((50, 25), Grid(6, 2)) e.add((35, 45), Dip14(True)) e.add((18, 70), Grid(10, 2)) """ """
newList = [] keys = list(lists.keys()) keys.sort(key=get_value) for i in range(9): for j in keys: newList.append(lists[j][i]) self.comps = newList ###################################### ###################################### ###################################### path = "Tuttle/VaspRuns/ABC4/" xml = "vasprun.xml" comp = [] for x, q, u in os.walk(path): if x.find("runnable") > 0: c = Vasprun(x + '/' + xml) comp.append(Compound(c)) mplot = MultiPlot(comp) mplot.sort() mplot.plot(color='r') mplot.change_limits(xlim=(-15, 10), ylim=(0, 20)) mplot.fig.savefig("a3bc6.png")
async def formula(inputs, author, channel): print(f"{inputs=}") inputs = re.split(r"(?<=[A-Za-z0-9])\s*?:\s*?(?=[0-9.])", inputs) print(f"{inputs=}") rawInputs = [] for input in inputs: rawInputs += [ entry.strip() for entry in re.split(r",\s*?|;\s*?", input) ] print(f"{rawInputs=}") percentDict = {} totalPercent = 0 epsilon = 0.011 mass = 0 for index in range(len(rawInputs)): if index % 2 == 0: element = rawInputs[index] if "mass" in element: # this entry contains the mass element = element.split("=") mass = float(element[1]) continue percent = rawInputs[index + 1] if "%" in percent: percent = int(percent.replace("%", "")) / 100 totalPercent += percent elif "." in percent: percent = float(percent) totalPercent += percent else: await channel.send( f"{author} The inputs for the command are inputted wrong.") return if element not in periodic_table: await channel.send( f"{author} One or more of the inputted elements is not inputted correctly." ) percentDict[rawInputs[index]] = percent # if the total percent is within an acceptable range if 1 - epsilon <= totalPercent <= 1 + epsilon: print(f"{percentDict=}") # if the user inputted a mass value if mass > 0: # give the molecular formula compoundFormula = Formula(**percentDict, mass=mass) compound = Compound(compoundFormula.molecularFormula()) await channel.send(f"{author} The molecular formula is: {compound}" ) else: # give the empirical formula compoundFormula = Formula(**percentDict) compound = Compound(compoundFormula.empiricalFormula()) await channel.send(f"{author} The empirical formula is: {compound}" ) else: await channel.send(f"{author} The percentages do not add up to 100%.") return