def saveToCSV(self, fileName = None): if not fileName: fileName = util.getSaveFileName(self, 'csv') if not fileName: return # make sure the top-level parameters are up-to-date self.designMomentumEV = util.convertUnitsStringToNumber(self.ui.designMomentum.text(), 'eV') self.totalCharge = util.convertUnitsStringToNumber(self.ui.totalCharge.text(), 'C') # create a header to identify this as a RadTrack file h1 = 'RadTrack,Copyright 2012-2014 by RadiaBeam Technologies LLC - All rights reserved (C)\n ' # names of the top-level parameters h2 = 'p0 [eV],Q [C],mass [eV]\n ' # values of the top-level parameters h3 = str(self.designMomentumEV)+','+str(self.totalCharge)+','+str(self.eMassEV)+'\n ' # label the columns h4 = 'x,xp,y,yp,s,dp\n ' # specify the units h5 = '[m],[rad],[m],[rad],[m],[rad]' # assemble the full header myHeader = h1 + h2 + h3 + h4 + h5 # write particle data into the file # create local pointer to particle array userNumberOfParticles = int(self.ui.numPtcls.text()) tmp6 = randomSampleOfBunch(self.myBunch.getDistribution6D().getPhaseSpace6D().getArray6D(), userNumberOfParticles) np.savetxt(fileName, tmp6.transpose(), fmt=str('%1.12e'), delimiter=',', comments='', header=myHeader)
def getValue(self, textBox): try: self.valueFromTextBox[textBox] = util.convertUnitsStringToNumber(textBox.text(), textBox.unit) return self.valueFromTextBox[textBox] except ValueError: if textBox in self.valueFromTextBox: del self.valueFromTextBox[textBox]
def _num(d, w): # need type checking if w is None: return None v = w.text() if d.units: v = RbUtility.convertUnitsStringToNumber(v, d.units) return d.py_type(v)
def goalSeek(self): # Newton's method variableTextBox = self.textBox[self.ui.vary.currentText()] resultTextBox = self.textBox[self.ui.target.currentText()] self.ui.solverResult.setText('Searching...') maximumIterations = 1000 success = False dxFactor = 1e-9 try: x0 = self.valueFromTextBox[variableTextBox] except KeyError: x0 = dxFactor bestX = x0 try: goal = util.convertUnitsStringToNumber(self.ui.lineEdit.text(), resultTextBox.unit) y0 = self.calculateValue(variableTextBox, x0, resultTextBox) bestError = abs((y0-goal)/goal) for i in range(maximumIterations): try: y0 = self.calculateValue(variableTextBox, x0, resultTextBox) error = abs((y0-goal)/goal) if error < 1e-6: success = True break else: if error < bestError: bestX = x0 bestError = error dx = abs(dxFactor*x0) slope = self.calculateSlope(variableTextBox, x0, dx, resultTextBox) x0 = x0 - (y0-goal)/slope if x0 < 0: x0 = dx except (ZeroDivisionError, KeyError, OverflowError): dxFactor = 2*dxFactor x0 = x0+dx except ValueError: # "goal" is blank -> find extrema by Newton's method on slope dx = abs(dxFactor*x0) bestSlope = abs(self.calculateSlope(variableTextBox, x0, dx, resultTextBox)) for i in range(maximumIterations): try: dx = abs(dxFactor*x0) slope = self.calculateSlope(variableTextBox, x0, dx, resultTextBox) if abs(slope) < 1e-6: success = True break else: if slope < bestSlope: bestX = x0 bestSlope = slope secondDerivitive = self.calculateSecondDerivitive(variableTextBox, x0, dx, resultTextBox) x0 = x0 - (slope)/secondDerivitive if x0 < 0: x0 = dx except (ZeroDivisionError, KeyError, OverflowError): dxFactor = 2*dxFactor x0 = x0+dx if success: value = x0 self.ui.solverResult.setText('Success.') else: value = bestX self.ui.solverResult.setText('Failed. Could not find a solution.') variableTextBox.setText(util.displayWithUnitsNumber(util.roundSigFig(value, 5), variableTextBox.unit)) variableTextBox.setCursorPosition(0) self.calculateAll()
def plot(self): try: xTextBox = self.textBox[self.ui.x.currentText()] xOrginalValue = xTextBox.text() yTextBox = self.textBox[self.ui.y.currentText()] yOrginalValue = yTextBox.text() zTextBox = self.textBox[self.ui.z.currentText()] except KeyError: return # Combo box choice was left blank try: xmin = util.convertUnitsStringToNumber(self.ui.xmin.text(), xTextBox.unit) xmax = util.convertUnitsStringToNumber(self.ui.xmax.text(), xTextBox.unit) if xmin > xmax: xmin, xmax = xmax, xmin ymin = util.convertUnitsStringToNumber(self.ui.ymin.text(), yTextBox.unit) ymax = util.convertUnitsStringToNumber(self.ui.ymax.text(), yTextBox.unit) if ymin > ymax: ymin, ymax = ymax, ymin except ValueError: # text box left blank return numPoints = 32 # per variable, 32*32 = 1,024 points total xRange = numpy.linspace(xmin, xmax, numPoints) _, xAxisLabel, xRangeUnits = rangeUnits(xTextBox, xRange) yRange = numpy.linspace(ymin, ymax, numPoints) _, yAxisLabel, yRangeUnits = rangeUnits(yTextBox, yRange) Z = numpy.zeros((numPoints, numPoints)) plotProgress = QtGui.QProgressDialog("Plotting ...", None, 0, (numPoints**2)-1) plotProgress.setMinimumDuration(0) try: for j, x in enumerate(xRange): for i, y in enumerate(yRange): plotProgress.setValue(plotProgress.value()+1) xTextBox.setText(str(x)) yTextBox.setText(str(y)) results = calculate(self.userInputDict()) try: Z[i,j] = results[zTextBox.dictName] except KeyError: Z[i,j] = float('nan') zUnit, zAxisLabel, _ = rangeUnits(zTextBox, Z.flat) for z in numpy.nditer(Z, op_flags=['readwrite']): z[...] = util.convertUnitsNumber(z, zTextBox.unit, zUnit) # Plotting self.ui.plotWidget.canvas.fig.clear() self.ui.plotWidget.canvas.ax = self.ui.plotWidget.canvas.fig.add_subplot(111) c = self.ui.plotWidget.canvas.ax.imshow(numpy.flipud(Z), cmap = 'hot', extent = [min(xRangeUnits), max(xRangeUnits), min(yRangeUnits), max(yRangeUnits)], aspect = 'auto') self.ui.plotWidget.canvas.ax.set_xlabel(xAxisLabel) self.ui.plotWidget.canvas.ax.set_ylabel(yAxisLabel) cb = self.ui.plotWidget.canvas.fig.colorbar(c) cb.set_label(zAxisLabel) self.ui.plotWidget.canvas.ax.set_xlim(min(xRangeUnits), max(xRangeUnits)) self.ui.plotWidget.canvas.ax.set_ylim(min(yRangeUnits), max(yRangeUnits)) self.ui.plotWidget.canvas.fig.tight_layout() self.ui.plotWidget.canvas.draw() finally: # Restore text boxes to original state xTextBox.setText(xOrginalValue) xTextBox.setCursorPosition(0) yTextBox.setText(yOrginalValue) yTextBox.setCursorPosition(0) self.calculateAll()
def generateBunch(self, particleLimit = None): if self.userInputEnabled(): errorMessage = [] self.parent.ui.statusbar.showMessage('Generating bunch ...') # Get input from text boxes. try: numParticles = int(self.ui.numPtcls.text()) except ValueError: numParticles = 0 if numParticles <= 0: errorMessage.append(self.ui.numPtclsLabel.text().strip() + ' must be a postive number.') if particleLimit: numParticles = min(numParticles, particleLimit) try: self.designMomentumEV = util.convertUnitsStringToNumber(self.ui.designMomentum.text(), 'eV') except ValueError: self.designMomentumEV = 0 if self.designMomentumEV <= 0: errorMessage.append(self.ui.designMomentumLabel.text().strip() + ' must be a positive value.') try: self.totalCharge = util.convertUnitsStringToNumber(self.ui.totalCharge.text().strip(), 'C') except ValueError: self.totalCharge = 0 if self.totalCharge <= 0: errorMessage.append(self.ui.charge.text() + ' must be a positive value.') if errorMessage: QtGui.QMessageBox(QtGui.QMessageBox.Warning, 'Input Error' + ('s' if len(errorMessage) > 1 else ''), '\n'.join(errorMessage), QtGui.QMessageBox.Ok, self).exec_() self.parent.ui.statusbar.clearMessage() self.myBunch = None return beta0gamma0 = self.designMomentumEV / self.eMassEV gamma0 = math.sqrt(beta0gamma0**2 + 1.) beta0 = beta0gamma0 / gamma0 # get input from the table of Twiss parameters self.twissAlphaX = util.convertUnitsStringToNumber(self.ui.twissTable.item(0,0).text(), '') self.twissAlphaY = util.convertUnitsStringToNumber(self.ui.twissTable.item(1,0).text(), '') self.twissBetaX = util.convertUnitsStringToNumber(self.ui.twissTable.item(0,1).text(), 'm/rad') self.twissBetaY = util.convertUnitsStringToNumber(self.ui.twissTable.item(1,1).text(), 'm/rad') self.twissEmitNX = util.convertUnitsStringToNumber(self.ui.twissTable.item(0,2).text(), 'm*rad') self.twissEmitNY = util.convertUnitsStringToNumber(self.ui.twissTable.item(1,2).text(), 'm*rad') if self.longTwissFlag == "alpha-bct-dp": self.twissAlphaZ = util.convertUnitsStringToNumber(self.ui.twissTableZ.item(0,0).text(), '') self.bctRms = util.convertUnitsStringToNumber(self.ui.twissTableZ.item(0,1).text(), 'm') self.dPopRms = float(self.ui.twissTableZ.item(0,2).text()) self.twissEmitNZ = (self.bctRms/beta0) * self.dPopRms / math.sqrt(1.+self.twissAlphaZ**2) self.twissBetaZ = (self.bctRms/beta0) / self.dPopRms * math.sqrt(1.+self.twissAlphaZ**2) # elif self.longTwissFlag == "coupling-bct-dp": # msgBox = QtGui.QMessageBox() # message = 'Error --\n\n' # message += ' longTwissFlag has been specified as "'+self.longTwissFlag+'".\n' # message += ' This value is not yet supported, but is coming soon!\n\n' # message += 'Please go to the "Specification Type" button and choose "alpha-bct-dp".\n\n' # msgBox.setText(message) # msgBox.exec_() # elif self.longTwissFlag == "alpha-beta-emit": # msgBox = QtGui.QMessageBox() # message = 'Error --\n\n' # message += ' longTwissFlag has been specified as "'+self.longTwissFlag+'".\n' # message += ' This value is not yet supported, but is coming soon!\n\n' # message += 'Please go to the "Specification Type" button and choose "alpha-bct-dp".\n\n' # msgBox.setText(message) # msgBox.exec_() # else: # msgBox = QtGui.QMessageBox() # message = 'Error --\n\n' # message += ' longTwissFlag has been specified as "'+self.longTwissFlag+'".\n' # message += ' This choice is invalid!\n\n' # message += 'Please use the "Specification Type" button to choose a valid option.\n\n' # msgBox.setText(message) # msgBox.exec_() # Get input from the table of phase space offsets self.offsetX = util.convertUnitsStringToNumber(self.ui.offsetTable.item(0,0).text(), 'm') self.offsetY = util.convertUnitsStringToNumber(self.ui.offsetTable.item(1,0).text(), 'm') self.offsetT = util.convertUnitsStringToNumber(self.ui.offsetTable.item(2,0).text(), 'm') self.offsetXP = util.convertUnitsStringToNumber(self.ui.offsetTable.item(0,1).text(), 'rad') self.offsetYP = util.convertUnitsStringToNumber(self.ui.offsetTable.item(1,1).text(), 'rad') self.offsetPT = util.convertUnitsStringToNumber(self.ui.offsetTable.item(2,1).text(), 'rad') # instantiate the particle bunch self.myBunch = beam.RbParticleBeam6D(numParticles) self.myBunch.setDesignMomentumEV(self.designMomentumEV) self.myBunch.setTotalCharge(self.totalCharge) self.myBunch.setMassEV(self.eMassEV) # assume electrons # specify the distribution flag and extent self.myDist = self.myBunch.getDistribution6D() self.myDist.setDistributionType(self.distributionFlag) self.myDist.setMaxRmsFactor(3.) # specify the Twiss parameters self.myBunch.setTwissParamsByName2D(self.twissAlphaX,self.twissBetaX, self.twissEmitNX/beta0gamma0,'twissX') self.myBunch.setTwissParamsByName2D(self.twissAlphaY,self.twissBetaY, self.twissEmitNY/beta0gamma0,'twissY') self.myBunch.setTwissParamsByName2D(self.twissAlphaZ,self.twissBetaZ, self.twissEmitNZ,'twissZ') # create the distribution self.myBunch.makeParticlePhaseSpace6D() # offset the distribution if (self.offsetX != 0.): self.myDist.offsetDistribComp(self.offsetX, 0) if (self.offsetXP != 0.): self.myDist.offsetDistribComp(self.offsetXP, 1) if (self.offsetY != 0.): self.myDist.offsetDistribComp(self.offsetY, 2) if (self.offsetYP != 0.): self.myDist.offsetDistribComp(self.offsetYP, 3) if (self.offsetT != 0.): self.myDist.offsetDistribComp(self.offsetT, 4) if (self.offsetPT != 0.): self.myDist.offsetDistribComp(self.offsetPT, 5) # generate the plots self.refreshPlots() self.parent.ui.statusbar.clearMessage()