class SCL_One_Cavity_Tracker_Model:
	def __init__(self,scl_long_tuneup_controller):
		self.scl_long_tuneup_controller = scl_long_tuneup_controller
		self.scl_accSeq = self.scl_long_tuneup_controller.scl_accSeq
		self.part_tracker = AlgorithmFactory.createParticleTracker(self.scl_accSeq)
		self.part_tracker.setRfGapPhaseCalculation(true)
		self.part_probe_init = ProbeFactory.createParticleProbe(self.scl_accSeq,self.part_tracker)
		self.scenario = Scenario.newScenarioFor(self.scl_accSeq)
		self.scenario.setSynchronizationMode(Scenario.SYNC_MODE_DESIGN)
		self.scenario.resync()
		# in the dictionary we will have 
		# cav_wrappers_param_dict[cav_wrapper] = [cavAmp,phase,[[gapLattElem,E0,ETL],...]]
		# E0 and ETL are parameters for all RF gaps
		self.cav_wrappers_param_dict = {}
		cav_wrappers = self.scl_long_tuneup_controller.cav_wrappers
		self.cav_amp_phase_dict = {}
		for cav_wrapper in cav_wrappers:
			amp = cav_wrapper.cav.getDfltCavAmp()
			phase = cav_wrapper.cav.getDfltCavPhase()
			self.cav_amp_phase_dict[cav_wrapper] = (amp,phase)
		#------ Make rf gap arrays for each cavity. 
		#------ The elements are IdealRfGap instances not AcceleratorNode. 
		#------ self.cavToGapsDict has {cav_name:[irfGaps]}
		rfGaps = self.scl_accSeq.getAllNodesWithQualifier(AndTypeQualifier().and((OrTypeQualifier()).or(RfGap.s_strType)))	
		self.cavToGapsDict = {}		
		for cav_wrapper in cav_wrappers:
			self.cavToGapsDict[cav_wrapper] = []
			for rfGap in rfGaps:
				if(rfGap.getId().find(cav_wrapper.cav.getId()) >= 0):
					irfGaps = self.scenario.elementsMappedTo(rfGap)
					self.cavToGapsDict[cav_wrapper].append(irfGaps[0])				
		#self.scenario.setModelInput(self.gap_first,RfGapPropertyAccessor.PROPERTY_PHASE,phase)
		#self.scenario.setModelInput(self.gap_first,RfGapPropertyAccessor.PROPERTY_ETL,val)
		#self.scenario.setModelInput(self.gap_first,RfGapPropertyAccessor.PROPERTY_E0,val)
		#self.scenario.setModelInput(quad,ElectromagnetPropertyAccessor,PROPERTY_FIELD,val)		
		#----------------------------------------------------------------
		self.scan_gd = BasicGraphData()
		self.harmonicsAnalyzer = HarmonicsAnalyzer(2)
		self.eKin_in = 185.6
		self.cav_amp = 14.0
		self.cav_phase_shift = 0.
		#------------------------
		self.active_cav_wrapper = null
		self.solver = null
		
	def restoreInitAmpPhases(self):
		cav_wrappers = self.scl_long_tuneup_controller.cav_wrappers
		for cav_wrapper in cav_wrappers:
			(amp,phase) = self.cav_amp_phase_dict[cav_wrapper]
			self.active_cav_wrapper.cav.updateDesignAmp(amp)
			self.active_cav_wrapper.cav.updateDesignPhase(phase)
		self.setActiveCavity(null)
		
	def getEkinAmpPhaseShift(self):
		return (self.eKin_in,self.cav_amp,self.cav_phase_shift)
		
	def setModelAmpPhaseToActiveCav(self,amp,phase,phase_shift):
		if(self.active_cav_wrapper != null):
			self.active_cav_wrapper.cav.updateDesignAmp(amp)
			self.active_cav_wrapper.cav.updateDesignPhase(phase-phase_shift)
			
	def getAvgGapPhase(self):
		#------------- calculate avg. RF gap phase -----------
		if(self.active_cav_wrapper == null): return 0.
		rf_gap_arr = self.cavToGapsDict[self.active_cav_wrapper]
		phase_rf_gaps_avg = 0.
		for irfGap in rf_gap_arr:
			phase_rf_gaps_avg += makePhaseNear(irfGap.getPhase(),0.)
		phase_rf_gaps_avg /= len(rf_gap_arr)
		phase_rf_gaps_avg = makePhaseNear((phase_rf_gaps_avg*180./math.pi)%360.,0.)
		return phase_rf_gaps_avg
			
	def getModelEnergyOut(self,eKin_in,amp,phase,phase_shift):
		if(self.active_cav_wrapper == null): return 0.
		self.setModelAmpPhaseToActiveCav(amp,phase,phase_shift)
		part_probe = ParticleProbe(self.part_probe_init)
		part_probe.setKineticEnergy(eKin_in*1.0e+6)
		self.scenario.setProbe(part_probe)	
		self.scenario.resync()
		self.scenario.run()
		return self.scenario.getTrajectory().finalState().getKineticEnergy()/1.0e+6
			
	def fillOutEneregyVsPhase(self,eKin_in,amp,phase_shift,phase_arr):
		self.scan_gd.removeAllPoints()
		if(self.active_cav_wrapper == null): return
		self.active_cav_wrapper.cav.updateDesignAmp(amp)
		self.scenario.resync()
		irfGap = self.cavToGapsDict[self.active_cav_wrapper][0]	
		for phase in phase_arr:
			part_probe = ParticleProbe(self.part_probe_init)
			part_probe.setKineticEnergy(eKin_in*1.0e+6)
			self.scenario.setProbe(part_probe)		
			#self.active_cav_wrapper.cav.updateDesignPhase(phase-phase_shift)
			#self.scenario.resync()
			irfGap.setPhase((phase-phase_shift)*math.pi/180.)
			self.scenario.run()
			eKin_out = self.scenario.getTrajectory().finalState().getKineticEnergy()/1.0e+6
			self.scan_gd.addPoint(phase,eKin_out)
		return self.scan_gd
			
	def getDiff2(self,eKin_in,amp,phase_shift):
		if(self.active_cav_wrapper == null): return 0.
		scan_gdExp = self.active_cav_wrapper.eKinOutPlot
		n_points = scan_gdExp.getNumbOfPoints()
		if(n_points <= 0): return 0.
		phase_arr = []
		for ip in range(n_points):
			phase_arr.append(scan_gdExp.getX(ip))
		scan_gd = self.fillOutEneregyVsPhase(eKin_in,amp,phase_shift,phase_arr)
		diff2 = 0.
		for ip in range(n_points):
			diff2 += (scan_gd.getY(ip) - scan_gdExp.getY(ip))**2
		diff2 /= n_points
		return diff2
			
	def setActiveCavity(self,cav_wrapper):
		self.active_cav_wrapper = cav_wrapper
		if(cav_wrapper != null):
			self.gap_list = cav_wrapper.cav.getGapsAsList()
			self.gap_first = self.gap_list.get(0)
			self.gap_last = self.gap_list.get(self.gap_list.size()-1)
			self.scenario.setStartNode(self.gap_first.getId())
			self.scenario.setStopNode(self.gap_last.getId())
		else:
			self.scenario.unsetStartNode()
			self.scenario.unsetStopNode()
			self.gap_first = null
			self.gap_last = null	
			self.gap_list = null
			
	def harmonicsAnalysisStep(self):
		if(self.active_cav_wrapper == null): return
		self.eKin_in = self.active_cav_wrapper.eKin_in
		self.cav_amp = 14.0
		self.cav_phase_shift = 0.
		#--------- first iteration
		self.getDiff2(self.eKin_in,self.cav_amp,self.cav_phase_shift)
		err = self.harmonicsAnalyzer.analyzeData(self.scan_gd)	
		harm_function = self.harmonicsAnalyzer.getHrmonicsFunction()
		energy_amp_test = harm_function.getParamArr()[1]
		energy_amp_exp = self.active_cav_wrapper.energy_guess_harm_funcion.getParamArr()[1]
		self.cav_amp = self.cav_amp*energy_amp_exp/energy_amp_test
		#--------- second iteration	
		self.getDiff2(self.eKin_in,self.cav_amp,self.cav_phase_shift)
		err = self.harmonicsAnalyzer.analyzeData(self.scan_gd)	
		harm_function = self.harmonicsAnalyzer.getHrmonicsFunction()
		energy_amp_test = harm_function.getParamArr()[1]
		energy_amp_exp = self.active_cav_wrapper.energy_guess_harm_funcion.getParamArr()[1]
		self.cav_amp = self.cav_amp*energy_amp_exp/energy_amp_test
		max_model_energy_phase = self.harmonicsAnalyzer.getPositionOfMax()
		max_exp_energy_phase = self.active_cav_wrapper.energy_guess_harm_funcion.findMax()
		self.cav_phase_shift = makePhaseNear(-(max_model_energy_phase - max_exp_energy_phase),0.)
		#print "debug model max=",max_model_energy_phase," exp=",max_exp_energy_phase," shift=",self.cav_phase_shift," amp=",self.cav_amp
		
	def fit(self):
		if(self.active_cav_wrapper == null): return
		variables = ArrayList()
		delta_hint = InitialDelta()
		#----- variable eKin_in
		var = Variable("eKin_in",self.eKin_in, - Double.MAX_VALUE, Double.MAX_VALUE)
		variables.add(var)
		delta_hint.addInitialDelta(var,0.3)
		#----- variable cavity amplitude
		var = Variable("cav_amp",self.cav_amp, - Double.MAX_VALUE, Double.MAX_VALUE)
		variables.add(var)
		delta_hint.addInitialDelta(var,self.cav_amp*0.01)
		#----- variable cavity phase offset
		var = Variable("phase_offset",self.cav_phase_shift, - Double.MAX_VALUE, Double.MAX_VALUE)
		variables.add(var)
		delta_hint.addInitialDelta(var,1.0)
		#-------- solve the fitting problem
		scorer = CavAmpPhaseScorer(self,variables)
		maxSolutionStopper = SolveStopperFactory.maxEvaluationsStopper(120) 
		self.solver = Solver(SimplexSearchAlgorithm(),maxSolutionStopper)
		problem = ProblemFactory.getInverseSquareMinimizerProblem(variables,scorer,0.0001)
		problem.addHint(delta_hint)
		self.solver.solve(problem)
		#------- get results
		trial = self.solver.getScoreBoard().getBestSolution()
		err2 = scorer.score(trial,variables)	
		[self.eKin_in,self.cav_amp,self.cav_phase_shift] = scorer	.getTrialParams(trial)	
		self.active_cav_wrapper.eKin_in = self.eKin_in
		self.active_cav_wrapper.designPhase = makePhaseNear(self.active_cav_wrapper.livePhase - self.cav_phase_shift,0.)
		self.active_cav_wrapper.eKin_err = math.sqrt(err2)
		cav_phase = self.active_cav_wrapper.livePhase
		self.active_cav_wrapper.eKin_out = self.getModelEnergyOut(self.eKin_in,self.cav_amp,cav_phase,self.cav_phase_shift)
		#print "debug cav=",self.active_cav_wrapper.alias," shift=",self.cav_phase_shift," amp=",self.cav_amp," err2=",	math.sqrt(err2)," ekinOut=",	self.active_cav_wrapper.eKin_out		
		#----- this defenition of the avg. gap phase will be replaced by another with self.model_eKin_in
		self.active_cav_wrapper.avg_gap_phase = self.getAvgGapPhase()
		self.active_cav_wrapper.designAmp = self.cav_amp
		self.solver = null
		#----make theory graph plot
		x_arr = []
		y_arr = []
		for i in range(self.scan_gd.getNumbOfPoints()):
			phase = self.scan_gd.getX(i)
			y = self.scan_gd.getY(i)
			x_arr.append(phase)
			y_arr.append(y)
		self.active_cav_wrapper.eKinOutPlotTh.addPoint(x_arr,y_arr)			
		
	def stopFitting(self):
		if(self.solver != null):
			self.solver.stopSolving()
def calculateEneregyVsPhase(cav_wrapper,scl_long_tuneup_controller,bpm_wrappers_good_arr):
	# This function will calculate output energy vs. cav. phase by using known BPM offsets
	# It will return false if the cavity cannot be analysed 
	eKin_in = cav_wrapper.eKin_in	
	# make cav_wrapper.energy_guess_harm_funcion harmonic function
	res = makeEnergyGuessHarmFunc(eKin_in,cav_wrapper,scl_long_tuneup_controller)
	if(not res): return false
	mass = scl_long_tuneup_controller.mass/1.0e+6			
	c_light = scl_long_tuneup_controller.c_light	
	bpm_freq = scl_long_tuneup_controller.bpm_freq
	coeff_init = 360.0*bpm_freq/c_light
	phaseDiffPlot = cav_wrapper.phaseDiffPlot
	cav_wrapper.eKinOutPlot.removeAllPoints()
	cav_wrapper.eKinOutPlotTh.removeAllPoints()
	for ip in range(phaseDiffPlot.getNumbOfPoints()):
		cav_phase = phaseDiffPlot.getX(ip)
		ekin_guess =  cav_wrapper.energy_guess_harm_funcion.getValue(cav_phase)
		beta_guess = math.sqrt(ekin_guess*(ekin_guess+2*mass))/(ekin_guess+mass)
		coeff = coeff_init/beta_guess
		# let's make bpm_phase(z) points for good BPMs
		gd = BasicGraphData()
		base_bpm_wrapper = bpm_wrappers_good_arr[0]
		(graphDataAmp,graphDataPhase) = cav_wrapper.bpm_amp_phase_dict[base_bpm_wrapper]
		base_bpm_offset = base_bpm_wrapper.final_phase_offset.phaseOffset_avg	
		base_bpm_phase = makePhaseNear180(graphDataPhase.getY(ip) - base_bpm_offset,0.)
		gd.addPoint(base_bpm_wrapper.pos,base_bpm_phase)
		#print "debug ==== ip=",ip," cav_phase=",cav_phase," eKin_guess=",ekin_guess	
		for bpm_ind in range(1,len(bpm_wrappers_good_arr)):
			bpm_wrapper = bpm_wrappers_good_arr[bpm_ind]
			(graphDataAmp,graphDataPhase) = cav_wrapper.bpm_amp_phase_dict[bpm_wrapper]
			bpm_phase = graphDataPhase.getY(ip) - bpm_wrapper.final_phase_offset.phaseOffset_avg
			delta_pos = bpm_wrapper.pos - gd.getX(bpm_ind-1)
			bpm_phase_guess = gd.getY(bpm_ind-1) + coeff*delta_pos
			bpm_phase = makePhaseNear180(bpm_phase,bpm_phase_guess)
			gd.addPoint(bpm_wrapper.pos,bpm_phase)
			#print "debug bpm=",bpm_wrapper.alias," pos=",bpm_pos," phase=",bpm_phase
		res_arr = GraphDataOperations.polynomialFit(gd,-1.e+36,+1.e+36,1)		
		if(res_arr == null): return false
		slope = res_arr[0][1]
		init_phase = res_arr[0][0]
		bad_point_ind = 1
		bad_points_count = 0
		while(bad_point_ind >= 0):
			bad_point_ind = -1
			avg_err2 = 0.
			for index in range(gd.getNumbOfPoints()):
				avg_err2 += (gd.getY(index) - (init_phase + slope*gd.getX(index)))**2
			if(gd.getNumbOfPoints() > 1): avg_err2 /= gd.getNumbOfPoints()
			avg_err = math.sqrt(avg_err2)
			for index in range(gd.getNumbOfPoints()):
				diff = gd.getY(index) - (init_phase + slope*gd.getX(index))
				if(math.fabs(diff) > 3.0*avg_err):
					bad_point_ind = index
					break
			if(bad_point_ind >= 0):
				bad_points_count += 1
				gd.removePoint(bad_point_ind)
				res_arr = GraphDataOperations.polynomialFit(gd,-1.e+36,+1.e+36,1)		
				if(res_arr == null): return false	
				slope = res_arr[0][1]
				init_phase = res_arr[0][0]	
			if(bad_points_count > 4):
				return false
		slope_err = res_arr[1][1]	
		init_phase_err = res_arr[1][0]			
		beta = coeff_init/slope
		gamma = 1./math.sqrt(1.0-beta*beta)
		eKin = mass*(gamma-1.0)
		delta_eKin = mass*gamma**3*beta**3*slope_err/coeff_init
		cav_wrapper.eKinOutPlot.addPoint(cav_phase,eKin,delta_eKin)
		"""
		print "debug ==================== cav_phase=",cav_phase," eKin_out=",eKin," dE=",delta_eKin," ekin_guess=",ekin_guess
		for ip0 in range(gd.getNumbOfPoints()):
			print "debug bpm_ind=",ip0," pos=",gd.getX(ip0)," Y=",gd.getY(ip0)," delta=",(gd.getY(ip0)-(res_arr[0][1]*gd.getX(ip0)+init_phase))
		"""
	return true
Ejemplo n.º 3
0
class WS_Scan_Record:
	"""
	This class keeps the results of the scan in one directions for one LW or WS
	"""
	def __init__(self, ws_node, ws_direction = WS_DIRECTION_NULL):
		self.ws_node = ws_node
		self.gauss_sigma = 0.
		self.gd_wf = BasicGraphData()
		self.gd_log_wf = BasicGraphData()
		self.gd_wf.setDrawLinesOn(false)
		self.gd_log_wf.setDrawLinesOn(false)
		self.gd_wf.setGraphPointSize(5)
		self.gd_log_wf.setGraphPointSize(5)
		self.gd_wf.setGraphColor(Color.BLUE)
		self.gd_log_wf.setGraphColor(Color.BLUE)
		self.setDirection(ws_direction)
		self.left_limit = 0.
		self.right_limit = 0.
		
	def setWF(self,wf_x_arr,wf_y_arr):
		#set waive form
		self.gd_wf.removeAllPoints()
		self.gd_log_wf.removeAllPoints()
		if(len(wf_x_arr) == len(wf_y_arr) and len(wf_y_arr) > 0):
			self.left_limit = wf_x_arr[0]
			self.right_limit = wf_x_arr[len(wf_x_arr)-1]
			y_max = 0.
			for y in wf_y_arr:
				if(math.fabs(y_max) < math.fabs(y)):
					y_max = y
			if(y_max < 0):
				for i in range(len(wf_y_arr)):
					wf_y_arr[i] = - wf_y_arr[i]
				y_max = - y_max
			self.gd_wf.addPoint(wf_x_arr,wf_y_arr)
			for i in range(len(wf_y_arr)):
				if(wf_y_arr[i] > 0.):
					self.gd_log_wf.addPoint(wf_x_arr[i],math.log(wf_y_arr[i]))
					
	def setDirection(	self,ws_direction):
		self.ws_direction = ws_direction
		legendKey = GRAPH_LEGEND_KEY
		legendName = self.ws_node.getId() 
		if(self.ws_direction == WS_DIRECTION_HOR): legendName += " Hor. "
		if(self.ws_direction == WS_DIRECTION_VER): legendName += " Ver. "
		self.gd_wf.setGraphProperty(legendKey,legendName+" Data")
		self.gd_log_wf.setGraphProperty(legendKey,"Log "+legendName+" Data ")	
						
	def getName(self):
		return self.ws_node.getId()
		
	def getAccNode(self):
		return self.ws_node
		
	def getCopy(self):
		""" 
		This method will return the partial copy of the record
		"""
		cp_record = WS_Scan_Record(self.ws_node,self.ws_direction)
		cp_record.left_limit  = self.left_limit
		cp_record.right_limit = self.right_limit
		cp_record.gauss_sigma = self.gauss_sigma
		#copy Graph data
		for i in range(self.gd_wf.getNumbOfPoints()):
			cp_record.gd_wf.addPoint(self.gd_wf.getX(i),self.gd_wf.getY(i))
			cp_record.gd_log_wf.addPoint(self.gd_log_wf.getX(i),self.gd_log_wf.getY(i))
		return cp_record
class WS_Scan_Record:
	"""
	This class keeps the results of the scan in one directions for one LW or WS
	"""
	def __init__(self, ws_node, ws_direction = WS_DIRECTION_NULL):
		self.ws_node = ws_node
		self.gauss_sigma = 0.
		self.gd_wf = BasicGraphData()
		self.gd_log_wf = BasicGraphData()
		self.gd_wf.setDrawLinesOn(false)
		self.gd_log_wf.setDrawLinesOn(false)
		self.gd_wf.setGraphPointSize(5)
		self.gd_log_wf.setGraphPointSize(5)
		self.gd_wf.setGraphColor(Color.BLUE)
		self.gd_log_wf.setGraphColor(Color.BLUE)
		self.setDirection(ws_direction)
		self.left_limit = 0.
		self.right_limit = 0.
		
	def setWF(self,wf_x_arr,wf_y_arr):
		#set waive form
		self.gd_wf.removeAllPoints()
		self.gd_log_wf.removeAllPoints()
		if(len(wf_x_arr) == len(wf_y_arr) and len(wf_y_arr) > 0):
			self.left_limit = wf_x_arr[0]
			self.right_limit = wf_x_arr[len(wf_x_arr)-1]
			y_max = 0.
			for y in wf_y_arr:
				if(math.fabs(y_max) < math.fabs(y)):
					y_max = y
			if(y_max < 0):
				for i in range(len(wf_y_arr)):
					wf_y_arr[i] = - wf_y_arr[i]
				y_max = - y_max
			self.gd_wf.addPoint(wf_x_arr,wf_y_arr)
			for i in range(len(wf_y_arr)):
				if(wf_y_arr[i] > 0.):
					self.gd_log_wf.addPoint(wf_x_arr[i],math.log(wf_y_arr[i]))
					
	def setDirection(	self,ws_direction):
		self.ws_direction = ws_direction
		legendKey = GRAPH_LEGEND_KEY
		legendName = self.ws_node.getId() 
		if(self.ws_direction == WS_DIRECTION_HOR): legendName += " Hor. "
		if(self.ws_direction == WS_DIRECTION_VER): legendName += " Ver. "
		self.gd_wf.setGraphProperty(legendKey,legendName+" Data")
		self.gd_log_wf.setGraphProperty(legendKey,"Log "+legendName+" Data ")	
						
	def getName(self):
		return self.ws_node.getId()
		
	def getAccNode(self):
		return self.ws_node
		
	def getCopy(self):
		""" 
		This method will return the partial copy of the record
		"""
		cp_record = WS_Scan_Record(self.ws_node,self.ws_direction)
		cp_record.left_limit  = self.left_limit
		cp_record.right_limit = self.right_limit
		cp_record.gauss_sigma = self.gauss_sigma
		#copy Graph data
		for i in range(self.gd_wf.getNumbOfPoints()):
			cp_record.gd_wf.addPoint(self.gd_wf.getX(i),self.gd_wf.getY(i))
			cp_record.gd_log_wf.addPoint(self.gd_log_wf.getX(i),self.gd_log_wf.getY(i))
		return cp_record
Ejemplo n.º 5
0
class BPM_Scan_Data:
	def __init__(self,main_loop_controller,cav_controller,bpm_wrapper):
		self.main_loop_controller = main_loop_controller
		self.cav_controller = cav_controller
		self.bpm_wrapper = bpm_wrapper
		self.cav_amp = 0.
		self.derivative = 0.
		self.zero_accel_phase = 0.
		self.max_accel_phase = 0.
		self.min_accel_phase = 0.
		#------ for MEBT measurements for Iteration process only
		self.cav_off_bpm_phase = 0.
		self.cav_off_bpm_phase_err = 0.
		self.cav_on_bpm_phase = 0.
		self.cav_on_bpm_phase_err = 0.
		self.cav_off_bpm_amp = 0.
		self.cav_off_bpm_amp_err = 0.
		self.cav_on_bpm_amp = 0.
		self.cav_on_bpm_amp_err = 0.
		#-----------------------------------------------------		
		self.harmonicsAnalyzer = HarmonicsAnalyzer(2)		
		self.phase_gd = BasicGraphData()
		self.phase_gd.setLineThick(3)
		self.phase_gd.setGraphPointSize(7)
		self.phase_gd.setGraphColor(Color.BLUE)
		self.phase_gd.setGraphProperty(GRAPH_LEGEND_KEY,self.bpm_wrapper.alias)
		self.phase_gd.setDrawLinesOn(true)
		self.phase_gd.setDrawPointsOn(true)
		#------------------------------
		self.amp_gd = BasicGraphData()
		self.amp_gd.setLineThick(3)
		self.amp_gd.setGraphPointSize(7)
		self.amp_gd.setGraphColor(Color.BLUE)
		self.amp_gd.setGraphProperty(GRAPH_LEGEND_KEY,self.bpm_wrapper.alias)
		self.amp_gd.setDrawLinesOn(true)
		self.amp_gd.setDrawPointsOn(true)		
		#------------------------------------
		self.phase_fit_gd = BasicGraphData()
		self.phase_fit_gd.setLineThick(3)
		self.phase_fit_gd.setGraphPointSize(3)
		self.phase_fit_gd.setGraphColor(Color.RED)
		self.phase_fit_gd.setGraphProperty(GRAPH_LEGEND_KEY,"Fit "+self.bpm_wrapper.alias)
		self.phase_fit_gd.setDrawLinesOn(true)
		self.phase_fit_gd.setDrawPointsOn(false)		
		
	def clean(self):
		self.phase_gd.removeAllPoints()	
		self.amp_gd.removeAllPoints()	
		self.phase_fit_gd.removeAllPoints()
		self.derivative = 0.
		self.zero_accel_phase = 0.
		self.max_accel_phase = 0.
		self.min_accel_phase = 0.		
		#------ for MEBT measurements for Iteration process only
		self.cav_off_bpm_phase = 0.
		self.cav_off_bpm_phase_err = 0.
		self.cav_on_bpm_phase = 0.
		self.cav_on_bpm_phase_err = 0.
		self.cav_off_bpm_amp = 0.
		self.cav_off_bpm_amp_err = 0.
		self.cav_on_bpm_amp = 0.
		self.cav_on_bpm_amp_err = 0.		

	def addPoint(self,cav_phase):
		if(not self.bpm_wrapper.isOn): return
		bpm_amp = self.bpm_wrapper.bpm.getAmpAvg()		
		bpm_phase = self.bpm_wrapper.bpm.getPhaseAvg()
		self.addExternalPoint(cav_phase,bpm_amp,bpm_phase)
		
	def getAmpAndPhase(self):
		if(not self.bpm_wrapper.isOn): return (0.,0.)
		bpm_amp = self.bpm_wrapper.bpm.getAmpAvg()		
		bpm_phase = self.bpm_wrapper.bpm.getPhaseAvg()
		return (bpm_amp,bpm_phase)		

	def addExternalPoint(self,cav_phase,bpm_amp,bpm_phase):
		if(self.phase_gd.getNumbOfPoints() != 0):
			cav_phase_old = self.phase_gd.getX(self.phase_gd.getNumbOfPoints()-1)
			bpm_phase_old = self.phase_gd.getY(self.phase_gd.getNumbOfPoints()-1)
			cav_phase = makePhaseNear(cav_phase,cav_phase_old)
			bpm_phase = makePhaseNear(bpm_phase,bpm_phase_old)
		self.phase_gd.addPoint(cav_phase,bpm_phase)
		self.amp_gd.addPoint(cav_phase,bpm_amp)		
		
	def shiftToPhase(self,gd,bpm_phase_init):
		nP = gd.getNumbOfPoints()
		if(nP == 0): return
		x_arr = []
		y_arr = []
		err_arr = []
		for ip in range(nP):
			x_arr.append(gd.getX(ip))	
			y_arr.append(gd.getY(ip))	
			err_arr.append(gd.getErr(ip))
		gd.removeAllPoints()
		y_arr[0] = makePhaseNear(y_arr[0],bpm_phase_init)
		for ip in range(1,nP):
			y_arr[ip] = makePhaseNear(y_arr[ip],y_arr[ip-1])	
		gd.addPoint(x_arr,y_arr,err_arr)			
			
	def makeLinearFit(self):
		self.phase_fit_gd.removeAllPoints()	
		self.derivative = 0.
		if(self.phase_gd.getNumbOfPoints() > 1):
			GraphDataOperations.polynomialFit(self.phase_gd,self.phase_fit_gd,1)
			self.phase_fit_gd.setGraphColor(Color.RED)
			nP = self.phase_fit_gd.getNumbOfPoints()
			self.derivative = 0.
			if(nP > 1):
				X0 = self.phase_fit_gd.getX(0)
				X1 = self.phase_fit_gd.getX(nP-1)
				self.derivative = self.phase_fit_gd.getValueDerivativeY((X0+X1)/2.0)
			return true
		return false
				
	def makeHarmonicFit(self):
		self.phase_fit_gd.removeAllPoints()	
		if(self.phase_gd.getNumbOfPoints() < 8): return false
		err = self.harmonicsAnalyzer.analyzeData(self.phase_gd)	
		harm_function = self.harmonicsAnalyzer.getHrmonicsFunction()		
		#-----remove bad points
		gd = self.phase_gd
		max_bad_points_count = 3
		bad_points_count = 0
		bad_index = 1
		while(bad_index >= 0):
			bad_index = -1
			for i in range(gd.getNumbOfPoints()):
				phase = gd.getX(i)
				y_appr = harm_function.getValue(phase)
				y = gd.getY(i)
				if(math.fabs(y-y_appr) > 3.0*err):
					bad_index = i
					bad_points_count += 1
					break
			if(bad_index >= 0):
				gd.removePoint(bad_index)
				self.amp_gd.removePoint(bad_index)
			# we should stop if we have too many bad points
			if(bad_points_count > max_bad_points_count):
				return false
		if(bad_points_count > 0):
			err = self.harmonicsAnalyzer.analyzeData(gd)
			harm_function = self.harmonicsAnalyzer.getHrmonicsFunction()
		#----find a new cavity phase		
		min_phase = makePhaseNear(self.harmonicsAnalyzer.getPositionOfMin(),0.)
		max_phase = makePhaseNear(self.harmonicsAnalyzer.getPositionOfMax(),0.)
		# guess phase is -90 deg if max acceleratiom phase is 0.
		self.zero_accel_phase = makePhaseNear(min_phase - 90.,0.)
		self.max_accel_phase = min_phase
		self.min_accel_phase = max_phase 
		#print "debug min_phase=",min_phase
		#print "debug max_phase=",max_phase
		#print "debug zero_accel_phase =",self.zero_accel_phase
		#----make theory graph plot
		harm_function = self.harmonicsAnalyzer.getHrmonicsFunction()
		x_arr = []
		y_arr = []
		for i in range(73):
		 phase = -180.0 + 5.0*i
		 y = harm_function.getValue(phase)
		 x_arr.append(phase)
		 y_arr.append(y)
		self.phase_fit_gd.addPoint(x_arr,y_arr)
		#--------------------		
		return true
				
	def setCavAmplitudeParam(self,cav_amp):
		self.cav_amp = cav_amp
		self.phase_fit_gd.setGraphProperty(GRAPH_LEGEND_KEY,"Fit "+self.bpm_wrapper.alias+" CavAmp= %6.4f "%self.cav_amp)
		self.phase_gd.setGraphProperty(GRAPH_LEGEND_KEY,self.bpm_wrapper.alias+" CavAmp= %6.4f "%self.cav_amp)
		self.amp_gd.setGraphProperty(GRAPH_LEGEND_KEY,self.bpm_wrapper.alias+" CavAmp= %6.4f "%self.cav_amp)
		
	def checkLastDataPoint(self,min_bpm_amp):
		if(not self.bpm_wrapper.isOn): return false
		res = true
		nP = self.phase_gd.getNumbOfPoints()
		if(nP > 1):
			if(math.fabs(self.phase_gd.getY(nP-2) - self.phase_gd.getY(nP-1)) < 0.000000001):
				return false
		if(nP > 0):
			if(self.amp_gd.getY(nP-1) < min_bpm_amp):
				return false
		return res
				
	def removeLastPoint(self):
		if(not self.bpm_wrapper.isOn): return
		nP = self.phase_gd.getNumbOfPoints()
		if(nP < 1): return
		self.phase_gd.removePoint(nP-1)
		self.amp_gd.removePoint(nP-1)
		
	def getAvgPhaseAndErr(self):
		nP = self.phase_gd.getNumbOfPoints()
		if(nP < 1): return (0.,0.)
		phase_arr = []
		for ind in range(nP):
			phase_arr.append(self.phase_gd.getY(ind))
		(avg_phase,avg_phase_err) = calculateAvgErr(phase_arr)
		return (avg_phase,avg_phase_err)
	
	def writeDataToXML(self,root_da):
		bpm_scan_data_da = root_da.createChild("bpm_scan_data")
		bpm_scan_data_da.setValue("cav",self.cav_controller.cav_wrapper.alias)	
		bpm_scan_data_da.setValue("bpm",self.bpm_wrapper.alias)	
		bpm_scan_data_da.setValue("cav_amp",self.cav_amp)
		bpm_scan_data_da.setValue("derivative","%7.5f"%self.derivative)
		bpm_scan_data_da.setValue("zero_accel_phase","%7.3f"%self.zero_accel_phase)
		bpm_scan_data_da.setValue("max_accel_phase", "%7.3f"%self.max_accel_phase)
		if(self.cav_controller.cav_wrapper.alias.find("MEBT") >= 0):
			mebt_cav_off_on_da = bpm_scan_data_da.createChild("cav_off_on_data")
			mebt_cav_off_on_da.setValue("cav_off_bpm_phase",self.cav_off_bpm_phase)
			mebt_cav_off_on_da.setValue("cav_off_bpm_phase_err",self.cav_off_bpm_phase_err)
			mebt_cav_off_on_da.setValue("cav_on_bpm_phase",self.cav_on_bpm_phase)
			mebt_cav_off_on_da.setValue("cav_on_bpm_phase_err",self.cav_on_bpm_phase_err)
			mebt_cav_off_on_da.setValue("cav_off_bpm_amp",self.cav_off_bpm_amp)
			mebt_cav_off_on_da.setValue("cav_off_bpm_amp_err",self.cav_off_bpm_amp_err)
			mebt_cav_off_on_da.setValue("cav_on_bpm_amp",self.cav_on_bpm_amp)
			mebt_cav_off_on_da.setValue("cav_on_bpm_amp_err",self.cav_on_bpm_amp_err)
		dumpGraphDataToDA(self.phase_gd,bpm_scan_data_da,"phase_scan_gd")
		dumpGraphDataToDA(self.amp_gd,bpm_scan_data_da,"amp_scan_gd")
		dumpGraphDataToDA(self.phase_fit_gd,bpm_scan_data_da,"phase_scan_fit_gd")
		
	def readDataFromXML(self,bpm_scan_data_da):
		self.cav_amp = bpm_scan_data_da.doubleValue("cav_amp")
		self.derivative = bpm_scan_data_da.doubleValue("derivative")
		self.zero_accel_phase = bpm_scan_data_da.doubleValue("zero_accel_phase")
		self.max_accel_phase = bpm_scan_data_da.doubleValue("max_accel_phase")
		mebt_cav_off_on_da = bpm_scan_data_da.childAdaptor("cav_off_on_data")
		if(mebt_cav_off_on_da != null):
			self.cav_off_bpm_phase	= mebt_cav_off_on_da.doubleValue("cav_off_bpm_phase")
			self.cav_off_bpm_phase_err	= mebt_cav_off_on_da.doubleValue("cav_off_bpm_phase_err")
			self.cav_on_bpm_phase	= mebt_cav_off_on_da.doubleValue("cav_on_bpm_phase")
			self.cav_on_bpm_phase_err	= mebt_cav_off_on_da.doubleValue("cav_on_bpm_phase_err")
			self.cav_off_bpm_amp	= mebt_cav_off_on_da.doubleValue("cav_off_bpm_amp")
			self.cav_off_bpm_amp_err	= mebt_cav_off_on_da.doubleValue("cav_off_bpm_amp_err")
			self.cav_on_bpm_amp	= mebt_cav_off_on_da.doubleValue("cav_on_bpm_amp")
			self.cav_on_bpm_amp_err	= mebt_cav_off_on_da.doubleValue("cav_on_bpm_amp_err")
		readGraphDataFromDA(self.phase_gd,bpm_scan_data_da,"phase_scan_gd")
		readGraphDataFromDA(self.amp_gd,bpm_scan_data_da,"amp_scan_gd")
		readGraphDataFromDA(self.phase_fit_gd,bpm_scan_data_da,"phase_scan_fit_gd")
class FaradayCup_Scan_Data:
    def __init__(self, dtl_acceptance_scans_controller,
                 dtl_acc_scan_cavity_controller):
        self.dtl_acceptance_scans_controller = dtl_acceptance_scans_controller
        self.main_loop_controller = self.dtl_acceptance_scans_controller.main_loop_controller
        self.dtl_acc_scan_cavity_controller = dtl_acc_scan_cavity_controller
        self.cav_wrapper = self.dtl_acc_scan_cavity_controller.cav_wrapper
        self.cav_amp = 0.
        self.cav_init_phase = 0.
        self.cav_phase_shift = 0.
        #-----------------------------------------------------
        self.fc_scan_gd = BasicGraphData()
        self.fc_scan_gd.setLineThick(3)
        self.fc_scan_gd.setGraphPointSize(7)
        self.fc_scan_gd.setGraphColor(Color.BLUE)
        self.fc_scan_gd.setGraphProperty(GRAPH_LEGEND_KEY,
                                         self.cav_wrapper.alias)
        self.fc_scan_gd.setDrawLinesOn(true)
        self.fc_scan_gd.setDrawPointsOn(true)

    def clean(self):
        self.fc_scan_gd.removeAllPoints()
        #------ for MEBT measurements for Iteration process only
        self.cav_amp = 0.
        self.cav_init_phase = 0.
        self.cav_phase_shift = 0.

    def addPoint(self):
        cav_phase = self.dtl_acc_scan_cavity_controller.getCavPhase()
        fc_charge = self.dtl_acc_scan_cavity_controller.getFC_Charge()
        self.addExternalPoint(cav_phase, fc_charge)

    def addExternalPoint(self, cav_phase, fc_charge):
        if (self.fc_scan_gd.getNumbOfPoints() != 0):
            cav_phase_old = self.fc_scan_gd.getX(
                self.fc_scan_gd.getNumbOfPoints() - 1)
            cav_phase = makePhaseNear(cav_phase, cav_phase_old)
        self.fc_scan_gd.addPoint(cav_phase, fc_charge)

    def shiftCavPhase(self, gd, phase_shift):
        self.cav_phase_shift += phase_shift
        self.cav_init_phase += phase_shift
        self.cav_phase_shift = makePhaseNear(self.cav_phase_shift, 0.)
        self.cav_init_phase = makePhaseNear(self.cav_init_phase, 0.)
        nP = gd.getNumbOfPoints()
        if (nP == 0): return
        x_arr = []
        y_arr = []
        err_arr = []
        for ip in range(nP):
            x_arr.append(gd.getX(ip) + phase_shift)
            y_arr.append(gd.getY(ip))
            err_arr.append(gd.getErr(ip))
        gd.removeAllPoints()
        for ip in range(nP):
            x_arr[ip] = makePhaseNear(x_arr[ip], 0.)
        gd.addPoint(x_arr, y_arr, err_arr)

    def setCavAmplitudeParam(self, cav_amp):
        self.cav_amp = cav_amp
        self.fc_scan_gd.setGraphProperty(
            GRAPH_LEGEND_KEY,
            self.cav_wrapper.alias + " CavAmp= %6.4f " % self.cav_amp)

    def checkLastDataPoint(self, min_charge):
        res = true
        nP = self.fc_scan_gd.getNumbOfPoints()
        if (nP > 1):
            if (math.fabs(self.amp_gd.getY(nP - 1)) > min_charge):
                if (math.fabs(
                        self.fc_scan_gd.getY(nP - 2) -
                        self.fc_scan_gd.getY(nP - 1)) < 0.000000001):
                    return false
        return res

    def removeLastPoint(self):
        nP = self.fc_scan_gd.getNumbOfPoints()
        if (nP < 1): return
        self.fc_scan_gd.removePoint(nP - 1)

    def writeDataToXML(self, root_da):
        fc_scan_data_da = root_da.createChild("fc_scan_data")
        fc_scan_data_da.setValue("cav_amp", self.cav_amp)
        fc_scan_data_da.setValue("cav_phase", self.cav_init_phase)
        fc_scan_data_da.setValue("phase_shift", self.cav_phase_shift)
        dumpGraphDataToDA(self.fc_scan_gd, fc_scan_data_da,
                          "fc_acceptance_scan_gd")

    def readDataFromXML(self, fc_scan_data_da):
        self.cav_amp = fc_scan_data_da.doubleValue("cav_amp")
        self.cav_init_phase = fc_scan_data_da.doubleValue("cav_phase")
        self.cav_phase_shift = fc_scan_data_da.doubleValue("phase_shift")
        readGraphDataFromDA(self.fc_scan_gd, fc_scan_data_da,
                            "fc_acceptance_scan_gd")