diff --git a/__main__.py b/__main__.py index b6d98de9a639f47eec5912b79ce420b62e2aec42..66ccadf76742dc0c49302a9e9acdd5d54485cbc7 100755 --- a/__main__.py +++ b/__main__.py @@ -22,10 +22,10 @@ subparsers = parser.add_subparsers(help='sub-command help', dest="subparser_name parser_asic = subparsers.add_parser('asic', help='ASIC design') parser_asic.add_argument('label', help='LABEL to identify ASIC design') -parser_draw = subparsers.add_parser('current', help='calculate drift current') -parser_draw.add_argument('label', help='LABEL to identify root files') +parser_cce = subparsers.add_parser('cce', help='Charge Collection Efficiency') +parser_cce.add_argument('label', help='LABEL to identify CCE experiment') -parser_draw = subparsers.add_parser('draw', help='draw figures') +parser_draw = subparsers.add_parser('current', help='calculate drift current') parser_draw.add_argument('label', help='LABEL to identify root files') parser_gsignal = subparsers.add_parser('elec', help='electronic readout') @@ -43,23 +43,26 @@ parser_fpga.add_argument('label', help='LABEL to identify FPGA design') parser_gen_signal = subparsers.add_parser('gen_signal', help='generate signal') parser_gen_signal.add_argument('det_name', help='name of the detector') +parser_gen_signal.add_argument('-l','--label', help='LABEL to identify signal generation method', default='signal') parser_gen_signal.add_argument('-vol', '--voltage', type=str, help='bias voltage') parser_gen_signal.add_argument('-abs', '--absorber', type=str, help='model of particle energy absorber') parser_gen_signal.add_argument('-amp', '--amplifier', type=str, help='amplifier') parser_gen_signal.add_argument('-s', '--scan', type=int, help='instance number for scan mode') -parser_gsignal = subparsers.add_parser('particle', help='calculate particle') -parser_gsignal.add_argument('label', help='LABEL to identify spaceres files') - -parser_root = subparsers.add_parser('root', help='root files conversion') -parser_root.add_argument('label', help='LABEL to identify root files') - parser_spaceres = subparsers.add_parser('spaceres', help='space resolution calculation') parser_spaceres.add_argument('label', help='LABEL to identify spaceres files') parser_spaceres = subparsers.add_parser('timeres', help='time resolution calculation') parser_spaceres.add_argument('det_name', help='name of the detector') +parser_tct = subparsers.add_parser('tct', help='TCT simulation') +parser_tct.add_argument('label', help='LABEL to identify TCT options') +parser_tct.add_argument('det_name', help='name of the detector') +parser_tct.add_argument('laser', help='name of the laser') +parser_tct.add_argument('-vol', '--voltage', type=str, help='bias voltage') +parser_tct.add_argument('-amp', '--amplifier', type=str, help='amplifier') +parser_tct.add_argument('-s', '--scan', type=int, help='instance number for scan mode') + args = parser.parse_args() if len(sys.argv) == 1: @@ -68,7 +71,7 @@ if len(sys.argv) == 1: kwargs = vars(args) -submodules = ['asic', 'current', 'draw', 'elec', 'field', 'fpga', 'gen_signal', 'particle', 'root', 'spaceres', 'timeres'] +submodules = ['asic', 'cce', 'current', 'draw', 'elec', 'field', 'fpga', 'gen_signal', 'particle', 'spaceres', 'tct', 'timeres'] submodule = kwargs['subparser_name'] if submodule not in submodules: @@ -84,7 +87,7 @@ if kwargs['batch'] == True: elif kwargs['shell'] == False: # not in shell try: - for package in ['ROOT', 'geant4_pybind', 'devsim']: + for package in ['ROOT', 'geant4_pybind', 'devsim', 'numpy', 'scipy']: # package dependency check import package submodule = importlib.import_module(submodule) diff --git a/asic/regincr.py b/asic/regincr.py index e9886bb606feab4bd2b3a0dcaa4b58756ff8a55d..06d2f8d3dfd1172ff5837c241ae63a4bd28484dc 100644 --- a/asic/regincr.py +++ b/asic/regincr.py @@ -3,6 +3,7 @@ #========================================================================= import pymtl3 as mtl +from util.output import create_path class RegIncr( mtl.Component ): def construct( s ): @@ -27,12 +28,6 @@ class RegIncr( mtl.Component ): def line_trace( s ): return f"{s.in_} ({s.reg_out}) {s.out}" -def create_path(path): - import os - """ If the path does not exit, create the path""" - if not os.access(path, os.F_OK): - os.makedirs(path, exist_ok=True) - def main(): input_values = [ 0x01, 0x13, 0x25, 0x37, 0xff ] # Add three zero values to end of list of input values diff --git a/asic/regincr2stage.py b/asic/regincr2stage.py index 57b6c80949a651fc7b9730f883be60795c40b819..63af2fd35ac3f68120c8495c3ad24994f5640123 100644 --- a/asic/regincr2stage.py +++ b/asic/regincr2stage.py @@ -7,6 +7,7 @@ import pymtl3 as mtl from .regincr import RegIncr +from util.output import create_path class RegIncr2stage( mtl.Component ): # Constructor @@ -29,12 +30,6 @@ class RegIncr2stage( mtl.Component ): s.reg_incr_1.line_trace(), s.out ) - -def create_path(path): - import os - """ If the path does not exit, create the path""" - if not os.access(path, os.F_OK): - os.makedirs(path, exist_ok=True) def main(): input_values = [ 0x01, 0x13, 0x25, 0x37, 0xff ] diff --git a/cce/__init__.py b/cce/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..da8e43679a20be8d1cceae96f3e8d2d07cfd885c --- /dev/null +++ b/cce/__init__.py @@ -0,0 +1,5 @@ +def main(kwargs): + label = kwargs['label'] + if label == 'HPK-Si-LGAD-CCE': + from cce import cce_alpha + cce_alpha.main() \ No newline at end of file diff --git a/elec/cce_alpha.py b/cce/cce_alpha.py similarity index 100% rename from elec/cce_alpha.py rename to cce/cce_alpha.py diff --git a/control/kei_2026_bias_control.py b/control/kei_2026_bias_control.py deleted file mode 100644 index e829f045bbc82fec3fc7ea8d060c4d0f5b2f292b..0000000000000000000000000000000000000000 --- a/control/kei_2026_bias_control.py +++ /dev/null @@ -1,97 +0,0 @@ -import visa -import time -import warnings - -class keithley2026: - def __init__(self): - instlist=visa.ResourceManager() - print(instlist.list_resources()) - self.kei026=instlist.open_resource("GPIB1::4::INSTR") - self.timedelay=1 - - def testIO(self): - message=self.kei026.ask('*IDN?') - print(message) - - def set_voltage(self,vol): - if vol > 5.0: - warnings.warn("Warning High Voltage!!!!") - self.kei026.write("smua.source.limiti=5E-7") - self.kei026.write("smua.source.func=smua.OUTPUT_DCVOLTS") - vols=self.show_voltage() - self.sweep(vols,vol,0.1) - vols=self.show_voltage() - return vols - - def show_voltage(self): - self.kei026.write("voltagea=smua.measure.v()") - voltage=self.kei026.ask("printnumber(voltagea)") - print("voltage [V]: " + str(voltage)) - return float(str(voltage)) - - def sweep(self, vols, vole, step): - if vols < vole: - self.sweep_forward(vols,vole,step) - else: - self.sweep_backward(vols,vole,step) - - def sweep_forward(self, vols, vole, step): - # Conveter from V to mV - mvols=vols*1000 - mvole=vole*1000 - mstep=step*1000 - - for mvol in range(int(mvols),int(mvole),int(mstep)): - vol=mvol/1000 # mV -> V - self.kei026.write("smua.source.levelv="+str(vol)) - self.kei026.write("smua.source.limiti=5E-7") - self.show_voltage() - time.sleep(self.timedelay) - self.kei026.write("smua.source.levelv="+str(vole)) - self.show_voltage() - - def sweep_backward(self, vols, vole, step): - # Conveter from V to mV - mvols=vols*1000 - mvole=vole*1000 - mstep=step*1000 - - for mvol in range(int(mvols),int(mvole), -int(mstep)): - vol=mvol/1000 # mV -> V - self.kei026.write("smua.source.levelv="+str(vol)) - self.kei026.write("smua.source.limiti=5E-7") - self.show_voltage() - time.sleep(self.timedelay) - self.kei026.write("smua.source.levelv="+str(vole)) - self.show_voltage() - - def display_current(self): - self.kei026.write("display.smua.measure.func=display.MEASURE_DCAMPS") - self.kei026.write("smua.measure.rangei=1E-6") - self.kei026.write("smua.measure.rel.enablei=1") - self.kei026.write("currenta=smua.measure.i()") - current=self.kei026.ask("printnumber(currenta)") - print("current [A]: " + str(current)) - - time.sleep(self.timedelay) - self.kei026.write("currenta=smua.measure.i()") - current=self.kei026.ask("printnumber(currenta)") - return float(str(current)) - - def output_on(self): - self.kei026.write("smua.source.output=smua.OUTPUT_ON") - print("On") - - def output_off(self): - self.kei026.write("smua.source.output=smua.OUTPUT_OFF") - print("Off") - - -if __name__=="__main__": - kei026=keithley2026() - kei026.output_on() - kei026.set_voltage(0.1) - current=kei026.display_current() - print(current) - #kei026.output_off() - diff --git a/control/kei_2400b_control.py b/control/kei_2400b_control.py deleted file mode 100644 index 2391685f775ae7a15a295a14e53df70147ecf589..0000000000000000000000000000000000000000 --- a/control/kei_2400b_control.py +++ /dev/null @@ -1,104 +0,0 @@ -import visa -import time -import warnings - -class keithley2400B: - def __init__(self): - instlist=visa.ResourceManager() - print(instlist.list_resources()) - self.kei2400b=instlist.open_resource("GPIB0::24::INSTR") - self.timedelay=5 - - def testIO(self): - message=self.kei2400b.ask('*IDN?') - print(message) - - def set_voltage(self,vol): - if vol > 105: - warnings.warn("Warning High Voltage!!!!") - - self.kei2400b.write(":sense:current:protection 1.05E-4") - self.kei2400b.write(":source:function voltage") - self.kei2400b.write(":source:voltage:mode fixed") - vols=self.show_voltage() - self.sweep(vols,vol,1) - vols=self.show_voltage() - return vols - - def show_voltage(self): - self.kei2400b.write(":source:voltage:mode fixed") - self.kei2400b.write(":form:elem voltage") - voltage=self.kei2400b.ask(":read?") - print("voltage [V]: " + str(voltage)) - return float(str(voltage)) - - def sweep(self, vols, vole, step): - if vols < vole: - self.sweep_forward(vols,vole,step) - else: - self.sweep_backward(vols,vole,step) - - def sweep_forward(self, vols, vole, step): - # Conveter from V to mV - mvols=vols*1000 - mvole=vole*1000 - mstep=step*1000 - - for mvol in range(int(mvols),int(mvole),int(mstep)): - vol=mvol/1000 # mV -> V - self.kei2400b.write(":source:voltage:level "+str(vol)) - self.kei2400b.write(":sense:current:protection 1.05E-4") - self.show_voltage() - time.sleep(self.timedelay) - - self.kei2400b.write(":source:voltage:level "+str(vole)) - self.show_voltage() - - def sweep_backward(self, vols, vole, step): - # Conveter from V to mV - mvols=vols*1000 - mvole=vole*1000 - mstep=step*1000 - - for mvol in range(int(mvols),int(mvole), -int(mstep)): - vol=mvol/1000 # mV -> V - self.kei2400b.write(":source:voltage:level "+str(vol)) - self.kei2400b.write(":sense:current:protection 1.05E-4") - self.show_voltage() - time.sleep(self.timedelay) - - self.kei2400b.write(":source:voltage:level "+str(vole)) - self.show_voltage() - - def display_current(self): - self.kei2400b.write(":sense:function 'current'") - self.kei2400b.write(":sense:current:range 1.05E-4") - self.kei2400b.write(":display:enable on") - self.kei2400b.write(":display:digits 7") - self.kei2400b.write(":form:elem current") - current=self.kei2400b.ask(":read?") - print("instant current [A]: " + str(current)) - - time.sleep(self.timedelay) - self.kei2400b.write(":form:elem current") - current=self.kei2400b.ask(":read?") - print("long current [A]: " + str(current)) - return float(str(current)) - - def output_on(self): - self.kei2400b.write(":output on") - print("On") - - def output_off(self): - self.kei2400b.write(":output off") - print("Off") - - -if __name__=="__main__": - kei2400b=keithley2400b() - kei2400b.output_on() - kei2400b.set_voltage(1) - current=kei2400b.display_current() - print(current) - kei2400b.output_off() - diff --git a/control/kei_2400c_control.py b/control/kei_2400c_control.py deleted file mode 100644 index 80d4b134bba39fbe733a2e0029e8664c3208f201..0000000000000000000000000000000000000000 --- a/control/kei_2400c_control.py +++ /dev/null @@ -1,103 +0,0 @@ -import visa -import time -import warnings - -class keithley2400c: - def __init__(self): - instlist=visa.ResourceManager() - print(instlist.list_resources()) - self.kei2400c=instlist.open_resource("GPIB0::24::INSTR") - self.timedelay=1 - - def testIO(self): - message=self.kei2400c.ask('*IDN?') - print(message) - - def set_voltage(self,vol): - if vol > 2.0: - warnings.warn("Warning High Voltage!!!!") - - self.kei2400c.write(":sense:current:protection 1E-6") - self.kei2400c.write(":source:function voltage") - self.kei2400c.write(":source:voltage:mode fixed") - vols=self.show_voltage() - self.sweep(vols,vol,0.1) - vols=self.show_voltage() - return vols - - def show_voltage(self): - self.kei2400c.write(":source:voltage:mode fixed") - self.kei2400c.write(":form:elem voltage") - voltage=self.kei2400c.ask(":read?") - print("voltage [V]: " + str(voltage)) - return float(str(voltage)) - - def sweep(self, vols, vole, step): - if vols < vole: - self.sweep_forward(vols,vole,step) - else: - self.sweep_backward(vols,vole,step) - - def sweep_forward(self, vols, vole, step): - # Conveter from V to mV - mvols=vols*1000 - mvole=vole*1000 - mstep=step*1000 - - for mvol in range(int(mvols),int(mvole),int(mstep)): - vol=mvol/1000 # mV -> V - self.kei2400c.write(":source:voltage:level "+str(vol)) - self.kei2400c.write(":sense:current:protection 1E-6") - self.show_voltage() - time.sleep(self.timedelay) - - self.kei2400c.write(":source:voltage:level "+str(vole)) - self.show_voltage() - - def sweep_backward(self, vols, vole, step): - # Conveter from V to mV - mvols=vols*1000 - mvole=vole*1000 - mstep=step*1000 - - for mvol in range(int(mvols),int(mvole), -int(mstep)): - vol=mvol/1000 # mV -> V - self.kei2400c.write(":source:voltage:level "+str(vol)) - self.kei2400c.write(":sense:current:protection 1E-6") - self.show_voltage() - time.sleep(self.timedelay) - - self.kei2400c.write(":source:voltage:level "+str(vole)) - self.show_voltage() - - def display_current(self): - self.kei2400c.write(":sense:function 'current'") - self.kei2400c.write(":sense:current:range 1E-6") - self.kei2400c.write(":display:enable on") - self.kei2400c.write(":display:digits 7") - self.kei2400c.write(":form:elem current") - current=self.kei2400c.ask(":read?") - print("current [A]: " + str(current)) - - time.sleep(self.timedelay) - self.kei2400c.write(":form:elem current") - current=self.kei2400c.ask(":read?") - return float(str(current)) - - def output_on(self): - self.kei2400c.write(":output on") - print("On") - - def output_off(self): - self.kei2400c.write(":output off") - print("Off") - - -if __name__=="__main__": - kei2400c=keithley2400c() - kei2400c.output_on() - kei2400c.set_voltage(1) - current=kei2400c.display_current() - print(current) - kei2400c.output_off() - diff --git a/control/keithley2470ccontrol_hyj.py b/control/keithley2470ccontrol_hyj.py deleted file mode 100644 index 05dff6b61f559144a0d12efe80836be3bfdd31ff..0000000000000000000000000000000000000000 --- a/control/keithley2470ccontrol_hyj.py +++ /dev/null @@ -1,128 +0,0 @@ -import pyvisa as visa -import time -import warnings - -class Keithley2470: - def __init__(self, resource_name): - instlist = visa.ResourceManager() - print(instlist.list_resources()) - self.kei2470 = instlist.open_resource(resource_name) - self.kei2470.timeout = 25000 - self.cmpl = '105E-6' - def testIO(self): - message = self.kei2470.query('*IDN?') - print(message) - - def set_current_protection(self, current): - self.cmpl = str(current) - self.kei2470.write(":SENSe:CURRent:RANGe " + str(current)) - - - def set_voltage_protection(self, vol): - self.kei2470.write(":SOURce:VOLTage:RANGe " + str(vol)) - - - def set_voltage(self, vol, speed=0.2): - self.kei2470.write(":SENSe:CURRent:RANGe " + self.cmpl) - self.kei2470.write(":SOURce:FUNCtion VOLTage") - - if(abs(vol)>=1): - if(vol>0):vols = vol - 1 - else: vols = vol + 1 - else: vols = self.show_voltage() - print("vols="+str(vols)) - self.sweep(vols, vol, 0.25, speed) - - vols = vol - return vols - - def show_voltage(self): - - - self.kei2470.write(":SOURce:FUNCtion VOLTage") - self.kei2470.write(":DISPlay:READing:FORMat PREFix") - voltage = self.kei2470.query(":READ?") - - print("voltage [V]: " + str(voltage)) - return float(str(voltage)) - - def sweep(self, vols, vole, step, speed): - if vols < vole: - self.sweep_forward(vols,vole,step,speed) - else: - self.sweep_backward(vols,vole,step,speed) - - def sweep_forward(self, vols, vole, step,speed): - - mvols=vols*1000 - mvole=vole*1000+1 - mstep=step*1000 - for mvol in range(int(mvols),int(mvole),int(mstep)): - vol=mvol/1000 - self.kei2470.write(":SOURce:VOLTage:LEVel "+str(vol)) - time.sleep(0.1/speed) - - def sweep_backward(self, vols, vole, step,speed): - - mvols=vols*1000 - mvole=vole*1000-1 - mstep=step*1000 - - for mvol in range(int(mvols),int(mvole), -int(mstep)): - vol=mvol/1000 - self.kei2470.write(":SOURce:VOLTage:LEVel "+str(vol)) - time.sleep(0.1/speed) - - def display_current(self): - self.kei2470.write(":SENSe:FUNCtion 'CURRent'") - - - self.kei2470.write(":SENS:CURR:RANG:AUTO ON") - - self.kei2470.write(":DISPlay:READing:FORMat PREFix") - - current=self.kei2470.query(":READ?") - - print("current [A]: " + str(current)) - return float(str(current)) - - def hit_compliance(self): - tripped=int(str(self.kei2470.query("SOUR:CURR:VLIM:TRIP?"))) - - if tripped: - print("Hit the compliance "+self.cmpl+"A.") - return tripped - - def output_on(self): - self.kei2470.write(":OUTPut:STATe ON") - - print("On") - - def output_off(self): - self.kei2470.write(":OUTPut:STATe OFF") - print("Off") - - def beep(self, freq=1046.50, duration=0.3): - self.kei2470.write(":SYSTem:BEEPer "+str(freq)+", "+str(duration)) - - time.sleep(duration) - - def filter_on(self, count=20, mode="REPeat"): - - self.kei2470.write(":SENSe:CURRent:AVERage:COUNt "+str(count)) - - self.kei2470.write(":SENSe:CURRent:AVERage:TCONtrol "+mode) - - self.kei2470.write(":SENSe:CURRent:AVERage:STATe ON") - - def filter_off(self): - - self.kei2400c.write("[:SENSe[1]]:CURRent[:DC]:AVERage:STATe OFF") - - def __del__(self): - self.kei2470.close() - - -if __name__ == "__main__": - kei2470 = Keithley2470("USB0::0x05E6::0x2470::04554700::INSTR") - kei2470.testIO() diff --git a/control/keye4980acontrol.py b/control/keye4980acontrol.py deleted file mode 100644 index ac040eab10b9522f026d6eed5fe3959d791b0c12..0000000000000000000000000000000000000000 --- a/control/keye4980acontrol.py +++ /dev/null @@ -1,41 +0,0 @@ -import pyvisa as visa -import time -import warnings - -class keysighte4980a: - def __init__(self,resource_name): - instlist=visa.ResourceManager() - print(instlist.list_resources()) - self.lcr=instlist.open_resource(resource_name) - self.lcr.write(":function:impedance:type CPRP") - self.lcr.write(":format:ascii:long on") - self.lcr.write(":aperture medium") - - def testIO(self): - message=self.lcr.query('*IDN?') - print(message) - - def set_voltage_level(self, vol): - self.lcr.write(":voltage:level "+str(vol)) - - def set_frequency(self, freq): - self.lcr.write(":frequency "+freq) - - def set_trigger_remote(self): - self.lcr.write("trigger:source bus") - - def set_trigger_internal(self): - self.lcr.write("trigger:source internal") - - def get_capacitance(self): - res=self.lcr.write("trigger:immediate") - res=self.lcr.query("fetch?") - reslist=res.split(",") - cap=reslist[0] - print("capacitance [F]: " + cap) - return float(cap) - -if __name__=="__main__": - lcr=keysighte4980a("USB0::0x2A8D::0x2F01::MY46516486::INSTR") - lcr.testIO() - lcr.set_trigger_internal() diff --git a/control/mdo_3034_control.py b/control/mdo_3034_control.py deleted file mode 100644 index 0152585299c4540de52b070791cb870c24a4bd3a..0000000000000000000000000000000000000000 --- a/control/mdo_3034_control.py +++ /dev/null @@ -1,110 +0,0 @@ -import numpy as np -import pandas as pd -import pylab -import re -import time - -try: - import visa -except ImportError as err: - print(err) - exit() - -class MDO3034C: - def __init__(self, resource_name): - instlist=visa.ResourceManager() - #print(instlist.list_resources()) - self.my_resource=instlist.open_resource(resource_name) - - def write_command(self,command): - self.my_resource.write(command) - time.sleep(0.5) - def testIO(self): - #self.my_resource.write('*RST') - self.my_resource.write('*CLS') - #self.my_resource.query_delay = 10.0 - message=self.my_resource.query('*IDN?') - time.sleep(1) - print("ocsilloscope information:" + message) - - def readSet(self,ch,point_number): - self.my_resource.write(":DATA:SOU "+ ch) - self.my_resource.write(':DATA:START 1') - self.my_resource.write(':DATA:STOP ' + point_number) - self.my_resource.write(':WFMOutpre:ENCdg BINARY') - self.my_resource.write(":WFMOutpre:BYT_Nr 1") - self.my_resource.write(":HEADer 0") - self.my_resource.write(":WFMOutpre?") - - def readOffset(self): - self.write_command('WFMPRE:YMULT?') - ymult = float(self.my_resource.read_raw()) - print("ymult = " + repr(ymult) + '\n') - self.write_command('WFMPRE:YZERO?') - yzero = float(self.my_resource.read_raw()) - print("yzero = " + repr(yzero) + '\n') - self.write_command('WFMPRE:YOFF?') - yoff = float(self.my_resource.read_raw()) - print("yoff = " + repr(yoff) + '\n') - self.write_command('WFMPRE:XINCR?') - xincr = float(self.my_resource.read_raw()) - print("xincr = " + repr(xincr) + '\n') - self.write_command('WFMPRE:XZERO?') - xzero = float(self.my_resource.read_raw()) - print("xzero = " + repr(xzero) + '\n') - return ymult,yzero,yoff,xincr,xzero - - def readWave(self): - ymult,yzero,yoff,xincr,xzero=self.readOffset() - self.my_resource.write('*CLS') - self.my_resource.write("CURVE?") - file = open('test.txt','w+') - - ########################################## - # receive data format: - # #510000<data>\n receive 10000 data - # #41000<data>\n receive 1000 data - ######################################### - data = np.frombuffer(self.my_resource.read_raw(),dtype=np.int8,count=int(POINT_NUMBER),offset=len(POINT_NUMBER) + 2) - np.savetxt('test.txt',data,fmt='%d',delimiter=',') - - print(data.size) - Volts = (data - 0) * ymult + yzero - Time = np.arange(0, data.size, 1) - Time = Time * xincr + xzero - - return Time, Volts - - def save_wave_data(self,time,voltage): - datadic = {'Time[ms]':time,'Voltage[mv]':voltage} - dataform = pd.DataFrame(datadic,columns=['Time[ms]','Voltage[mv]']) - dataform.to_csv('dataform.csv') - - - def plotWave(self, Time, Volts): - pylab.plot(Time, Volts) - pylab.show() - - -if __name__=="__main__": - POINT_NUMBER = '10000' - CHANNEL = 'CH1' - rm = visa.ResourceManager() - print(rm.list_resources()) - list_sources = rm.list_resources() - for resource_name in list_sources: - match_result = re.match(r'TCPIP',resource_name) - if match_result: - tcpip_resource = resource_name - print("the TCPIP resource is:" + repr(tcpip_resource)) - break - else: - print("no TCPIP resource,please check it!") - exit() - scope=MDO3034C(tcpip_resource) - scope.testIO() - scope.readSet(CHANNEL,POINT_NUMBER) - - Time,Volts = scope.readWave() - scope.plotWave(Time, Volts) - print(max(Volts)-min(Volts)) diff --git a/control/scan_amp.py b/control/scan_amp.py deleted file mode 100644 index e8428c9107dd9c95917906096aff506c88ebc0bd..0000000000000000000000000000000000000000 --- a/control/scan_amp.py +++ /dev/null @@ -1,52 +0,0 @@ -import raser.control.kei_2026_bias_control as kei2026 -import raser.control.tek_tds5054b_control as tds5054b -import visa -import time -import pylab -import csv -import numpy as np - -def csv_writer(data,path): - with open(path,"w") as csv_file: - writer=csv.writer(csv_file,lineterminator='\n') - writer.writerow(['Bias Voltage[V]','Measure Voltage [V]','Meaure Current [A]','Max Amp [mV]']) - for val in data: - writer.writerows([val]) - - -biasSupply=kei2026.keithley2026() -scope=tds5054b.TDS5054B() - -scope.testIO() -scope.readSet(3) - -vols=[] -mvols=[] -maxAmp=[] -current=[] - -iStart=int(0*1e3) -iEnd=int(1*1e3) -iStep=int(0.1*1e3) -for iBias in range(iStart,iEnd,iStep): - biasSupply.output_on() - biasvol=iBias/1000 - if biasvol>5: - break - vols.append(biasvol) - mvols.append(biasSupply.set_voltage(biasvol)) - current.append(biasSupply.display_current()) - - Time,Volts = scope.readWave() - maxAmp.append(max(Volts)-min(Volts)) - -print("Bias Vols: "+str(vols)) -print("Measure vols: "+str(mvols)) -print("Current: "+str(current)) -print("MaxAmp: "+str(maxAmp)) - -data=[vols,mvols,current,maxAmp] -dataarray=np.array(data) - -filename="test.csv" -csv_writer(dataarray.T,filename) diff --git a/control/scan_cv_2470.py b/control/scan_cv_2470.py deleted file mode 100644 index 26f29a6e5e39dbd8c4afdbb7282af857002028a4..0000000000000000000000000000000000000000 --- a/control/scan_cv_2470.py +++ /dev/null @@ -1,107 +0,0 @@ -import keye4980acontrol -import keithley2470ccontrol_hyj as kei2470 -import csv -import numpy as np -import platform -import sys -import warnings -import time - - -def csv_writer(data,path): - with open(path,"w") as csv_file: - writer=csv.writer(csv_file,lineterminator='\n') - writer.writerow(['Bias Voltage[V]','Measured Voltage[V]','Measured Capacitance[pF]','Capacitance^{-2}[pF]^{-2}','Monitoring Current[A]']) - for val in data: - writer.writerows([val]) - -# prevent from running with python2 -if platform.python_version().startswith('2'): - print('You are running with',platform.python_version(),'.') - print('Please run with python3.') - print('Exit.') - sys.exit() - - -lcr=keye4980acontrol.keysighte4980a("USB0::0x2A8D::0x2F01::MY46516486::INSTR") - -lcr.set_frequency("1kHz") -lcr.set_voltage_level(0.1) -timedelay=3.0 - - - -biasSupply=kei2470.Keithley2470("USB0::0x05E6::0x2470::04554700::INSTR") -biasSupply.set_current_protection(100E-6) -biasSupply.set_voltage_protection(400) -positiveHV=True -HVrange=150.0*1e3 - - -time_start=time.time() -vols=[] -mvols=[] -pcap=[] - -invpcap2=[] -current=[] - -if positiveHV: - sign=1 -else: - sign=-1 - -iStart=int(0*1e3) -iEnd=int(sign*HVrange+sign*1) -iStep=int(sign*1.0*1e3) -lcr.set_trigger_remote() -biasSupply.output_on() -for iBias in range(iStart,iEnd,iStep): - biasvol=iBias/1000 - if biasvol>400: - warnings.warn("Warning! Exceed the maximum voltage of the bias adapter!") - break - vols.append(biasvol) - mvols.append(biasSupply.set_voltage(biasvol)) - time.sleep(timedelay) - current.append(biasSupply.display_current()) - - tmp_ipcap = 0. - for i in range(5): - print("display_capacitance",i,":",lcr.get_capacitance()/1e-12) - tmp_ipcap += lcr.get_capacitance()/1e-12 - time.sleep(0.2) - ipcap = tmp_ipcap/5.0 - - pcap.append(ipcap) - - invpcap2.append(1.0/(ipcap*ipcap)) - if biasSupply.hit_compliance(): - break - -print("Bias Vols: "+str(vols)) -print("Measured vols: "+str(mvols)) -print("Capacitance: "+str(pcap)) - -print("Current: "+str(current)) - -data=[vols,mvols,pcap,invpcap2,current] - -dataarray=np.array(data) - -filename="test_CV.csv" -csv_writer(dataarray.T,filename) -time_top=time.time() -print("Ramping up takes %3.0f s." % (time_top-time_start)) - -print("Now ramping down...") -lcr.set_trigger_internal() - -biasSupply.sweep(HVrange*sign*1e-3,0,1,5) -biasSupply.output_off() -biasSupply.beep() -time_end=time.time() - -print("Ramping up time:\t%3.0f s" % (time_top-time_start)) -print("Ramping down time:\t%3.0f s" % (time_end-time_top)) -print("Total time:\t\t%3.0f m %2.0f s" % ((time_end-time_start)//60, (time_end-time_start)%60)) diff --git a/control/scan_iv.py b/control/scan_iv.py deleted file mode 100644 index 36e15f5702bf21c1b6c20c92ffcac13d15d4ea5c..0000000000000000000000000000000000000000 --- a/control/scan_iv.py +++ /dev/null @@ -1,44 +0,0 @@ -import raser.control.Kei2400c_control as kei2400 -import visa -import time -import pylab -import csv -import numpy as np - -def csv_writer(data,path): - with open(path,"w") as csv_file: - writer=csv.writer(csv_file,lineterminator='\n') - writer.writerow(['Bias Voltage[V]','Measure Voltage [V]','Meaure Current [A]']) - for val in data: - writer.writerows([val]) - - -biasSupply=kei2400.keithley2400c() - -vols=[] -mvols=[] -current=[] - -iStart=int(0*1e3) -iEnd=int(5.0*1e3) -iStep=int(0.5*1e3) -for iBias in range(iStart,iEnd,iStep): - biasSupply.output_on() - biasvol=iBias/1000 - if biasvol>2: - break - vols.append(biasvol) - mvols.append(biasSupply.set_voltage(biasvol)) - current.append(biasSupply.display_current()) - -biasSupply.set_voltage(0*1e3) - -print("Bias Vols: "+str(vols)) -print("Measure vols: "+str(mvols)) -print("Current: "+str(current)) - -data=[vols,mvols,current] -dataarray=np.array(data) - -filename="test.csv" -csv_writer(dataarray.T,filename) diff --git a/control/scan_strip_iv.py b/control/scan_strip_iv.py deleted file mode 100644 index 7aec31aadb074ac391a60e0df397413b8937a4c4..0000000000000000000000000000000000000000 --- a/control/scan_strip_iv.py +++ /dev/null @@ -1,45 +0,0 @@ -import raser.control.kei_2400b_control as kei2400 -import visa -import time -import pylab -import csv -import numpy as np - -def csv_writer(data,path): - with open(path,"w") as csv_file: - writer=csv.writer(csv_file,lineterminator='\n') - writer.writerow(['Bias Voltage[V]','Measure Voltage [V]','Meaure Current [A]']) - for val in data: - writer.writerows([val]) - - -biasSupply=kei2400.keithley2400B() - -vols=[] -mvols=[] -current=[] - -iStart=int(0*1e3) -iEnd=int(105.0*1e3) -iStep=int(2.5*1e3) -for iBias in range(iStart,iEnd,iStep): - biasSupply.output_on() - biasvol=iBias/1000 - if biasvol>105: - print("Much high") - break - vols.append(biasvol) - mvols.append(biasSupply.set_voltage(biasvol)) - current.append(biasSupply.display_current()) - -biasSupply.set_voltage(0*1e3) - -print("Bias Vols: "+str(vols)) -print("Measure vols: "+str(mvols)) -print("Current: "+str(current)) - -data=[vols,mvols,current] -dataarray=np.array(data) - -filename="striptest.csv" -csv_writer(dataarray.T,filename) diff --git a/control/scaniv.py b/control/scaniv.py deleted file mode 100644 index 56412f9969f37d676049bcab47b9102aff91fab8..0000000000000000000000000000000000000000 --- a/control/scaniv.py +++ /dev/null @@ -1,85 +0,0 @@ -#import Kei2400CControl as kei2400 -import keithley2470ccontrol_hyj as kei2470 -# import visa -import pyvisa as visa -import time -import pylab -import csv -import numpy as np -import platform -import sys - -def csv_writer(data,path): - with open(path,"w") as csv_file: - writer=csv.writer(csv_file,lineterminator='\n') - writer.writerow(['Bias Voltage[V]','Measured Voltage[V]','Measured Current[A]']) - for val in data: - writer.writerows([val]) - - -if platform.python_version().startswith('2'): - print('You are running with',platform.python_version(),'.') - print('Please run with python3.') - print('Exit.') - sys.exit() -biasSupply=kei2470.Keithley2470("USB0::0x05E6::0x2470::04554700::INSTR") - - -biasSupply.set_current_protection(105E-6) -biasSupply.set_voltage_protection(800) -positiveHV=True -HVrange=700*1e3 -biasSupply.filter_on() - -time_start=time.time() -vols=[] -mvols=[] -current=[] - -if positiveHV: - sign=1 -else: - sign=-1 -iStart=int(0*1e3) -iEnd=int(sign*HVrange+sign*1) -iStep=int(sign*10.0*1e3) -for iBias in range(iStart,iEnd,iStep): - biasSupply.output_on() - biasvol=iBias/1000 - vols.append(biasvol) - mvols.append(biasSupply.set_voltage(biasvol)) - time.sleep(5.0) - - tmp_current = 0. - for i in range(2): - print("display_current",i,":",biasSupply.display_current()) - tmp_current += biasSupply.display_current() - time.sleep(0.2) - - my_current = tmp_current/3.0 - current.append(my_current) - if biasSupply.hit_compliance(): - break - -print("Bias Vols: "+str(vols)) -print("Measured vols: "+str(mvols)) -print("Current: "+str(current)) - -data=[vols,mvols,current] -dataarray=np.array(data) - -filename="test_IV.csv" -csv_writer(dataarray.T,filename) -time_top=time.time() -print("Ramping up takes %3.0f s." % (time_top-time_start)) - -print("Now ramping down...") - -biasSupply.sweep(HVrange*sign*1e-3,0,1 ,5) -biasSupply.output_off() -biasSupply.beep() -time_end=time.time() - -print("Ramping up time:\t%3.0f s" % (time_top-time_start)) -print("Ramping down time:\t%3.0f s" % (time_end-time_top)) -print("Total time:\t\t%3.0f m %2.0f s" % ((time_end-time_start)//60, (time_end-time_start)%60)) diff --git a/control/tek_tds5054b_control.py b/control/tek_tds5054b_control.py deleted file mode 100644 index a5eba0f718439c2974e325a8cf4eb6a73a0dd6f4..0000000000000000000000000000000000000000 --- a/control/tek_tds5054b_control.py +++ /dev/null @@ -1,56 +0,0 @@ -import visa -import numpy as np -from struct import unpack -import pylab - -class TDS5054B: - def __init__(self): - instlist=visa.ResourceManager() - print(instlist.list_resources()) - self.scope=instlist.open_resource("GPIB0::1::INSTR") - - def testIO(self): - message=self.scope.ask('*IDN?') - print(message) - - def readSet(self,ch): - self.scope.write("DATA:SOU "+str(ch)) - self.scope.write('DATA:WIDTH 1') - self.scope.write('DATA:ENC RPB') - - def readOffset(self): - ymult = float(self.scope.ask('WFMPRE:YMULT?')) - yzero = float(self.scope.ask('WFMPRE:YZERO?')) - yoff = float(self.scope.ask('WFMPRE:YOFF?')) - xincr = float(self.scope.ask('WFMPRE:XINCR?')) - return ymult,yzero,yoff,xincr - - def readWave(self): - ymult,yzero,yoff,xincr=self.readOffset() - - self.scope.write("CURVE?") - data=self.scope.read_raw() - headerlen=2+int(data[1]) - header=data[:headerlen] - ADC_wave=data[headerlen:-1] - ADC_wave = np.array(unpack('%sB' % len(ADC_wave),ADC_wave)) - Volts = (ADC_wave - yoff) * ymult + yzero - Time = np.arange(0, xincr * len(Volts), xincr) - Time=Time*1e9 #ns - Volts=Volts*1e3 #mV - - return Time, Volts - - def plotWave(self, Time, Volts): - pylab.plot(Time, Volts) - pylab.show() - - -if __name__=="__main__": - scope=TDS5054B() - scope.testIO() - scope.readSet(3) - - Time,Volts = scope.readWave() - scope.plotWave(Time, Volts) - print(max(Volts)-min(Volts)) diff --git a/current/__init__.py b/current/__init__.py index 4083f50b4fff786f3ccd0331d799292fbc935ceb..cbb8fa04cdc8f5d6efc9bd31715b16719350510b 100644 --- a/current/__init__.py +++ b/current/__init__.py @@ -1,4 +1,4 @@ -from . import * + def main(kwargs): label = kwargs['label'] diff --git a/current/cal_current.py b/current/cal_current.py index 5f5865dfe0531686a17d6789424b9d6ec8d0a46d..b9b6c88cd5ff0be24612bdc5a43084e375817d92 100644 --- a/current/cal_current.py +++ b/current/cal_current.py @@ -1,22 +1,28 @@ # -*- encoding: utf-8 -*- + ''' -Description: Simulate e-h pairs drifting and calculate induced current +Description: + Simulate e-h pairs drifting and calculate induced current @Date : 2021/09/02 14:01:46 @Author : Yuhang Tan, Chenxi Fu @version : 2.0 ''' + import random -import numpy as np import math +import os + +import numpy as np import ROOT + from .model import Material -from .model import Vector +from util.math import Vector, signal_convolution +from util.output import create_path t_bin = 50e-12 t_end = 10e-9 t_start = 0 delta_t = 10e-12 -pixel = 25 #um min_intensity = 1 # V/cm class Carrier: @@ -48,13 +54,9 @@ class Carrier: self.z = z_init self.t = t_init self.t_end = t_end - self.pixel = pixel self.path = [[x_init, y_init, z_init, t_init]] self.signal = [[] for j in range(int(read_ele_num))] self.end_condition = 0 - self.diffuse_end_condition = 0 - self.row=0 - self.column=0 self.cal_mobility = Material(material).cal_mobility self.charge = charge @@ -72,9 +74,7 @@ class Carrier: e_field = my_f.get_e_field(self.x,self.y,self.z) intensity = Vector(e_field[0],e_field[1],e_field[2]).get_length() mobility = Material(my_d.material) - #mu = mobility.cal_mobility(my_d.temperature, my_d.doping_function(self.z+delta_z), self.charge, average_intensity) - mu = mobility.cal_mobility(my_d.temperature, 1e12, self.charge, intensity) - # TODO: rebuild the doping function or admit this as an approximation + mu = mobility.cal_mobility(my_d.temperature, my_f.get_doping(self.x, self.y, self.z), self.charge, intensity) velocity_vector = [e_field[0]*mu, e_field[1]*mu, e_field[2]*mu] # cm/s if(intensity > min_intensity): @@ -156,80 +156,6 @@ class Carrier: elif (self.t > t_end): self.end_condition = "time out" return self.end_condition - - def diffuse_single_step(self,my_d,my_f): - delta_t=t_bin - #e_field = my_f.get_e_field(self.x,self.y,self.z) - intensity = 0 - - kboltz=8.617385e-5 #eV/K - mobility = Material(my_d.material) - mu = mobility.cal_mobility(my_d.temperature, my_d.doping_function(self.z), self.charge, intensity) - diffusion = (2.0*kboltz*mu*my_d.temperature*delta_t)**0.5 - #diffusion = 0.0 - dif_x=random.gauss(0.0,diffusion)*1e4 - dif_y=random.gauss(0.0,diffusion)*1e4 - dif_z=0 - - if((self.x+dif_x)>=my_d.l_x): - self.x = my_d.l_x - elif((self.x+dif_x)<0): - self.x = 0 - else: - self.x = self.x+dif_x - # y axis - if((self.y+dif_y)>=my_d.l_y): - self.y = my_d.l_y - elif((self.y+dif_y)<0): - self.y = 0 - else: - self.y = self.y+dif_y - # z axis - if((self.z+dif_z)>=my_d.l_z): - self.z = my_d.l_z - elif((self.z+dif_z)<0): - self.z = 0 - else: - self.z = self.z+dif_z - #time - self.t = self.t+delta_t - #record - self.path.append([self.x,self.y,self.z,self.t]) - - def diffuse_end(self,my_f): - if (self.z<=0): - # self.end_condition = "out of bound" - self.diffuse_end_condition = "collect" - return self.diffuse_end_condition - - def diffuse_not_in_sensor(self,my_d): - if (self.x<=0) or (self.x>=my_d.l_x)\ - or (self.y<=0) or (self.y>=my_d.l_y)\ - or (self.z>=my_d.l_z): - self.diffuse_end_condition = "out of bound" - mod_x = self.x % self.pixel - mod_y = self.y % self.pixel - if ((mod_x> 7.5) & (mod_x<17.5)) & ((mod_y> 7.5) & (mod_y<17.5)) \ - & (self.t <= self.t_end): - self.diffuse_end_condition = "collect" - return self.diffuse_end_condition - - ''' - if (self.z<= 0) or (self.t >= self.t_end): - self.diffuse_end_condition = "collect" - #print("diffuse end") - return self.diffuse_end_condition - ''' - - def pixel_position(self,my_f,my_d): - if self.diffuse_end_condition == "collect": - self.row = self.x // self.pixel - self.column = self.y // self.pixel - else: - self.row = -1 - self.column = -1 - return self.row,self.column,abs(self.charge) - class CalCurrent: @@ -250,8 +176,11 @@ class CalCurrent: 2022/10/28 """ def __init__(self, my_d, my_f, ionized_pairs, track_position): + + self.read_ele_num = my_f.read_ele_num self.electrons = [] self.holes = [] + for i in range(len(track_position)): electron = Carrier(track_position[i][0],\ track_position[i][1],\ @@ -259,14 +188,14 @@ class CalCurrent: track_position[i][3],\ -1*ionized_pairs[i],\ my_d.material,\ - my_f.read_ele_num) + self.read_ele_num) hole = Carrier(track_position[i][0],\ track_position[i][1],\ track_position[i][2], track_position[i][3],\ ionized_pairs[i],\ my_d.material,\ - my_f.read_ele_num) + self.read_ele_num) if not electron.not_in_sensor(my_d): self.electrons.append(electron) self.holes.append(hole) @@ -278,18 +207,18 @@ class CalCurrent: self.t_start = t_start self.n_bin = int((self.t_end-self.t_start)/self.t_bin) - self.current_define(my_f.read_ele_num) - for i in range(my_f.read_ele_num): + self.current_define(self.read_ele_num) + for i in range(self.read_ele_num): self.sum_cu[i].Reset() self.positive_cu[i].Reset() self.negative_cu[i].Reset() - self.get_current(my_d,my_f.read_ele_num) + self.get_current(my_d,self.read_ele_num) if "lgad3D" in my_d.det_model: self.gain_current = CalCurrentGain(my_d, my_f, self) - for i in range(my_f.read_ele_num): + for i in range(self.read_ele_num): self.gain_positive_cu[i].Reset() self.gain_negative_cu[i].Reset() - self.get_current_gain(my_f.read_ele_num) + self.get_current_gain(self.read_ele_num) def drifting_loop(self, my_d, my_f): for electron in self.electrons: @@ -386,6 +315,7 @@ class CalCurrent: class CalCurrentGain(CalCurrent): '''Calculation of gain carriers and gain current, simplified version''' def __init__(self, my_d, my_f, my_current): + self.read_ele_num = my_current.read_ele_num self.electrons = [] # gain carriers self.holes = [] cal_coefficient = Material(my_d.material).cal_coefficient @@ -400,7 +330,7 @@ class CalCurrentGain(CalCurrent): hole.path[-1][3],\ -1*hole.charge*gain_rate,\ my_d.material,\ - my_f.read_ele_num)) + self.read_ele_num)) self.holes.append(Carrier(hole.path[-1][0],\ hole.path[-1][1],\ @@ -408,7 +338,7 @@ class CalCurrentGain(CalCurrent): hole.path[-1][3],\ hole.charge*gain_rate,\ my_d.material,\ - my_f.read_ele_num)) + self.read_ele_num)) else : # n layer at d=0, electrons multiplicated into holes for electron in my_current.electrons: @@ -418,7 +348,7 @@ class CalCurrentGain(CalCurrent): electron.path[-1][3],\ -1*electron.charge*gain_rate,\ my_d.material,\ - my_f.read_ele_num)) + self.read_ele_num)) self.electrons.append(Carrier(electron.path[-1][0],\ electron.path[-1][1],\ @@ -426,7 +356,7 @@ class CalCurrentGain(CalCurrent): electron.path[-1][3],\ electron.charge*gain_rate,\ my_d.material,\ - my_f.read_ele_num)) + self.read_ele_num)) self.drifting_loop(my_d, my_f) @@ -435,11 +365,11 @@ class CalCurrentGain(CalCurrent): self.t_start = t_start self.n_bin = int((self.t_end-self.t_start)/self.t_bin) - self.current_define(my_f.read_ele_num) - for i in range(my_f.read_ele_num): + self.current_define(self.read_ele_num) + for i in range(self.read_ele_num): self.positive_cu[i].Reset() self.negative_cu[i].Reset() - self.get_current(my_d,my_f.read_ele_num) + self.get_current(my_d,self.read_ele_num) def gain_rate(self, my_d, my_f, cal_coefficient): @@ -546,114 +476,22 @@ class CalCurrentGain(CalCurrent): self.negative_cu[j].Add(test_n) test_n.Reset() + class CalCurrentG4P(CalCurrent): def __init__(self, my_d, my_f, my_g4p, batch): G4P_carrier_list = CarrierListFromG4P(my_d.material, my_g4p, batch) - self.read_ele_num = my_f.read_ele_num super().__init__(my_d, my_f, G4P_carrier_list.ionized_pairs, G4P_carrier_list.track_position) + class CalCurrentStrip(CalCurrent): def __init__(self, my_d, my_f, my_g4p, batch): G4P_carrier_list = StripCarrierListFromG4P(my_d.material, my_g4p, batch) - self.read_ele_num = my_f.read_ele_num super().__init__(my_d, my_f, G4P_carrier_list.ionized_pairs, G4P_carrier_list.track_position) -class CalCurrentPixel: - """Calculation of diffusion electrons in pixel detector""" - def __init__(self, my_d, my_f, my_g4p): - batch = len(my_g4p.localposition) - layer = len(my_d.lt_z) - G4P_carrier_list = PixelCarrierListFromG4P(my_d, my_g4p) - self.collected_charge=[] #temp paras don't save as self. - self.sum_signal = [] - self.event = [] - for k in range(batch): - l_dict = {} - signal_charge = [] - for j in range(layer): - self.electrons = [] - self.charge,self.collected_charge = [],[]#same like before - self.row,self.column=[],[] - Hit = {'index':[],'charge':[]} - #print(len(G4P_carrier_list.ionized_pairs[k][j])) - print("%f pairs of carriers are generated from G4 in event_ %d layer %d" %(sum(G4P_carrier_list.ionized_pairs[k][j]),k,j)) - #print(G4P_carrier_list.track_position[k][j]) - for i in range(len(G4P_carrier_list.track_position[k][j])): - electron = Carrier(G4P_carrier_list.track_position[k][j][i][0],\ - G4P_carrier_list.track_position[k][j][i][1],\ - G4P_carrier_list.track_position[k][j][i][2],\ - 0,\ - -1*G4P_carrier_list.ionized_pairs[k][j][i],\ - my_d.material,\ - 1) - if not electron.not_in_sensor(my_d): - self.electrons.append(electron) - self.diffuse_loop(my_d,my_f) - - Xbins=int(my_d.l_x // electron.pixel) - Ybins=int(my_d.l_y // electron.pixel) - Xup=my_d.l_x // electron.pixel - Yup=my_d.l_y // electron.pixel - test_charge = ROOT.TH2F("charge", "charge",Xbins, 0, Xup, Ybins, 0, Yup) - for i in range(len(self.row)): - #test_charge.SetBinContent(int(self.row[i]),int(self.column[i]),self.charge[i]) - test_charge.Fill(self.row[i],self.column[i],self.charge[i]) - - sum_fired = ROOT.TH2F("charge", "Pixel Detector charge",Xbins, 0, Xup, Ybins, 0, Yup) - sum_fired.Add(test_charge) - - self.sum_charge = ROOT.TH2F("charge", "Pixel Detector charge",Xbins, 0, Xup, Ybins, 0, Yup) - self.sum_charge.Add(test_charge) - - test_charge.Reset - collected_charge=self.pixel_charge(my_d,Xbins,Ybins) - signal_charge.append(collected_charge) - - Hit["index"],Hit["charge"] = self.pixel_fired(sum_fired,Xbins,Ybins) - l_dict[j] = Hit - print("%f electrons are collected in event_ %d,layer %d" %(sum(self.charge),k,j)) - self.sum_signal.append(signal_charge) - self.event.append(l_dict) - #print(signal_charge) - del signal_charge - #print(self.sum_signal) - #print(self.event) - - def diffuse_loop(self, my_d, my_f): - for electron in self.electrons: - while not electron.diffuse_not_in_sensor(my_d): - electron.diffuse_single_step(my_d, my_f) - electron.diffuse_end(my_f) - x,y,charge_quantity = electron.pixel_position(my_f,my_d) - if (x != -1)&(y != -1): - self.row.append(x) - self.column.append(y) - self.charge.append(charge_quantity) - - def pixel_charge(self,my_d,Xbins,Ybins): - for x in range(Xbins): - for y in range(Ybins): - charge =self.sum_charge.GetBinContent(x,y) - if (charge>0.2): - self.collected_charge.append([x,y,charge]) - return self.collected_charge - - def pixel_fired(self,tot,Xbins,Ybins): - Hit = {'index':[],'charge':[]} - for x in range(Xbins): - for y in range(Ybins): - charge =tot.GetBinContent(x,y) - if (charge>0.2): - Hit["index"].append([x,y]) - Hit["charge"].append(charge) - return Hit["index"],Hit["charge"] - - class CalCurrentLaser(CalCurrent): def __init__(self, my_d, my_f, my_l): super().__init__(my_d, my_f, my_l.ionized_pairs, my_l.track_position) - self.read_ele_num = my_f.read_ele_num for i in range(self.read_ele_num): @@ -675,11 +513,11 @@ class CalCurrentLaser(CalCurrent): convolved_gain_negative_cu.Reset() convolved_sum_cu.Reset() - self.signalConvolution(self.positive_cu[i],my_l.timePulse,convolved_positive_cu) - self.signalConvolution(self.negative_cu[i],my_l.timePulse,convolved_negative_cu) - self.signalConvolution(self.gain_positive_cu[i],my_l.timePulse,convolved_gain_positive_cu) - self.signalConvolution(self.gain_negative_cu[i],my_l.timePulse,convolved_gain_negative_cu) - self.signalConvolution(self.sum_cu[i],my_l.timePulse,convolved_sum_cu) + signal_convolution(self.positive_cu[i],convolved_positive_cu,[my_l.timePulse]) + signal_convolution(self.negative_cu[i],convolved_negative_cu,[my_l.timePulse]) + signal_convolution(self.gain_positive_cu[i],convolved_gain_positive_cu,[my_l.timePulse]) + signal_convolution(self.gain_negative_cu[i],convolved_gain_negative_cu,[my_l.timePulse]) + signal_convolution(self.sum_cu[i],convolved_sum_cu,[my_l.timePulse]) self.positive_cu[i] = convolved_positive_cu self.negative_cu[i] = convolved_negative_cu @@ -687,13 +525,6 @@ class CalCurrentLaser(CalCurrent): self.gain_negative_cu[i] = convolved_gain_negative_cu self.sum_cu[i] = convolved_sum_cu - def signalConvolution(self,cu,timePulse,convolved_cu): - for i in range(self.n_bin): - pulse_responce = cu.GetBinContent(i) - for j in range(-i,self.n_bin-i): - time_pulse = timePulse(j*self.t_bin) - convolved_cu.Fill((i+j)*self.t_bin - 1e-14, pulse_responce*time_pulse*self.t_bin) - #resolve float error class CarrierListFromG4P: def __init__(self, material, my_g4p, batch): @@ -742,65 +573,6 @@ class CarrierListFromG4P: self.tracks_t_energy_deposition = my_g4p.edep_devices[j] #为什么ä¸ä½¿ç”¨ï¼Ÿ self.ionized_pairs = [step*1e6/self.energy_loss for step in self.tracks_step] -class PixelCarrierListFromG4P: - def __init__(self, my_d,my_g4p): - """ - Description: - Events position and energy depositon - Parameters: - material : string - deciding the energy loss of MIP - my_g4p : Particles - batch : int - batch = 0: Single event, select particle with long enough track - batch != 0: Multi event, assign particle with batch number - Modify: - 2022/10/25 - """ - batch = len(my_g4p.localposition) - layer = len(my_d.lt_z) - material = my_d.material - self.pixelsize_x = my_d.p_x - self.pixelsize_y = my_d.p_y - self.pixelsize_z = my_d.p_z - - if (material == "SiC"): - self.energy_loss = 8.4 #ev - elif (material == "Si"): - self.energy_loss = 3.6 #ev - - self.track_position, self.ionized_pairs= [],[] - self.layer= layer - for j in range(batch): - self.single_event(my_g4p,j) - - def single_event(self,my_g4p,j): - s_track_position,s_energy= [],[] - for i in range(self.layer): - position = [] - energy = [] - name = "Layer_"+str(i) - #print(name) - for k in range(len(my_g4p.devicenames[j])): - px,py,pz = self.split_name(my_g4p.devicenames[j][k]) - if name in my_g4p.devicenames[j][k]: - tp = [0 for i in range(3)] - tp[0] = my_g4p.localposition[j][k][0]+(px-0.5)*self.pixelsize_x - tp[1] = my_g4p.localposition[j][k][1]+(py-0.5)*self.pixelsize_y - tp[2] = my_g4p.localposition[j][k][2]+self.pixelsize_z/2 - position.append(tp) - energy.append(my_g4p.energy_steps[j][k]) - s_track_position.append(position) - pairs = [step*1e6/self.energy_loss for step in energy] - s_energy.append(pairs) - del position,energy - self.track_position.append(s_track_position) - self.ionized_pairs.append(s_energy) - - def split_name(self,volume_name): - parts = volume_name.split('_') - return int(parts[1]),int(parts[2]),int(parts[4]) - class StripCarrierListFromG4P: def __init__(self, material, my_g4p, batch): @@ -839,26 +611,3 @@ class StripCarrierListFromG4P: self.tracks_step = my_g4p.energy_steps[j] self.tracks_t_energy_deposition = my_g4p.edep_devices[j] #为什么ä¸ä½¿ç”¨ï¼Ÿ self.ionized_pairs = [step*1e6/self.energy_loss for step in self.tracks_step] - -# TODO: change this to a method of CalCurrent -def save_current(my_d,my_l,my_current,my_f,key): - if "planar3D" in my_d.det_model or "planarRing" in my_d.det_model: - path = os.path.join('output', 'pintct', my_d.det_name, ) - elif "lgad3D" in my_d.det_model: - path = os.path.join('output', 'lgadtct', my_d.det_name, ) - create_path(path) - L = eval("my_l.{}".format(key)) - #L is defined by different keys - time = array('d', [999.]) - current = array('d', [999.]) - fout = ROOT.TFile(os.path.join(path, "sim-TCT-current") + str(L) + ".root", "RECREATE") - t_out = ROOT.TTree("tree", "signal") - t_out.Branch("time", time, "time/D") - for i in range(my_f.read_ele_num): - t_out.Branch("current"+str(i), current, "current"+str(i)+"/D") - for j in range(my_current.n_bin): - current[0]=my_current.sum_cu[i].GetBinContent(j) - time[0]=j*my_current.t_bin - t_out.Fill() - t_out.Write() - fout.Close() \ No newline at end of file diff --git a/current/cal_current_diffuse.py b/current/cal_current_diffuse.py new file mode 100644 index 0000000000000000000000000000000000000000..4a6368c2ca31d97c6c422fc888d29f08669821c5 --- /dev/null +++ b/current/cal_current_diffuse.py @@ -0,0 +1,289 @@ +# -*- encoding: utf-8 -*- + +''' +Description: + Simulate e-h pairs diffusing and calculate induced current in MAPS +@Date : 2021/09/02 14:01:46 +@Author : Yuhang Tan, Haobo Wang +@version : 2.0 +''' + +import random +import math +import os + +import numpy as np +import ROOT + +from .model import Material +from util.math import Vector + +t_bin = 50e-12 +t_end = 10e-9 +t_start = 0 +delta_t = 10e-12 +pixel = 25 #um +min_intensity = 1 # V/cm + +class Carrier: + """ + Description: + Definition of carriers and the record of their movement + Parameters: + x_init, y_init, z_init, t_init : float + initial space and time coordinates in um and s + charge : float + a set of drifting carriers, absolute value for number, sign for charge + Attributes: + x, y, z, t : float + space and time coordinates in um and s + path : float[] + recording the carrier path in [x, y, z, t] + charge : float + a set of drifting carriers, absolute value for number, sign for charge + signal : float[] + the generated signal current on the reading electrode + end_condition : 0/string + tag of how the carrier ended drifting + Modify: + 2022/10/28 + """ + def __init__(self, x_init, y_init, z_init, t_init, charge, read_ele_num): + self.x = x_init + self.y = y_init + self.z = z_init + self.t = t_init + self.t_end = t_end + self.pixel = pixel + self.path = [[x_init, y_init, z_init, t_init]] + self.signal = [[] for j in range(int(read_ele_num))] + self.diffuse_end_condition = 0 + self.row=0 + self.column=0 + + self.charge = charge + + def diffuse_single_step(self,my_d,my_f): + delta_t=t_bin + #e_field = my_f.get_e_field(self.x,self.y,self.z) + intensity = 0 + + kboltz=8.617385e-5 #eV/K + mobility = Material(my_d.material) + mu = mobility.cal_mobility(my_d.temperature, my_f.get_doping(self.x, self.y, self.z), self.charge, intensity) + diffusion = (2.0*kboltz*mu*my_d.temperature*delta_t)**0.5 + #diffusion = 0.0 + dif_x=random.gauss(0.0,diffusion)*1e4 + dif_y=random.gauss(0.0,diffusion)*1e4 + dif_z=0 + + if((self.x+dif_x)>=my_d.l_x): + self.x = my_d.l_x + elif((self.x+dif_x)<0): + self.x = 0 + else: + self.x = self.x+dif_x + # y axis + if((self.y+dif_y)>=my_d.l_y): + self.y = my_d.l_y + elif((self.y+dif_y)<0): + self.y = 0 + else: + self.y = self.y+dif_y + # z axis + if((self.z+dif_z)>=my_d.l_z): + self.z = my_d.l_z + elif((self.z+dif_z)<0): + self.z = 0 + else: + self.z = self.z+dif_z + #time + self.t = self.t+delta_t + #record + self.path.append([self.x,self.y,self.z,self.t]) + + def diffuse_end(self,my_f): + if (self.z<=0): + # self.end_condition = "out of bound" + self.diffuse_end_condition = "collect" + return self.diffuse_end_condition + + def diffuse_not_in_sensor(self,my_d): + if (self.x<=0) or (self.x>=my_d.l_x)\ + or (self.y<=0) or (self.y>=my_d.l_y)\ + or (self.z>=my_d.l_z): + self.diffuse_end_condition = "out of bound" + mod_x = self.x % self.pixel + mod_y = self.y % self.pixel + if ((mod_x> 7.5) & (mod_x<17.5)) & ((mod_y> 7.5) & (mod_y<17.5)) \ + & (self.t <= self.t_end): + self.diffuse_end_condition = "collect" + return self.diffuse_end_condition + + ''' + if (self.z<= 0) or (self.t >= self.t_end): + self.diffuse_end_condition = "collect" + #print("diffuse end") + return self.diffuse_end_condition + ''' + + def pixel_position(self,my_f,my_d): + if self.diffuse_end_condition == "collect": + self.row = self.x // self.pixel + self.column = self.y // self.pixel + else: + self.row = -1 + self.column = -1 + return self.row,self.column,abs(self.charge) + + + +class CalCurrentPixel: + """Calculation of diffusion electrons in pixel detector""" + def __init__(self, my_d, my_f, my_g4p): + batch = len(my_g4p.localposition) + layer = len(my_d.lt_z) + G4P_carrier_list = PixelCarrierListFromG4P(my_d, my_g4p) + self.collected_charge=[] #temp paras don't save as self. + self.sum_signal = [] + self.event = [] + for k in range(batch): + l_dict = {} + signal_charge = [] + for j in range(layer): + self.electrons = [] + self.charge,self.collected_charge = [],[]#same like before + self.row,self.column=[],[] + Hit = {'index':[],'charge':[]} + #print(len(G4P_carrier_list.ionized_pairs[k][j])) + print("%f pairs of carriers are generated from G4 in event_ %d layer %d" %(sum(G4P_carrier_list.ionized_pairs[k][j]),k,j)) + #print(G4P_carrier_list.track_position[k][j]) + for i in range(len(G4P_carrier_list.track_position[k][j])): + electron = Carrier(G4P_carrier_list.track_position[k][j][i][0],\ + G4P_carrier_list.track_position[k][j][i][1],\ + G4P_carrier_list.track_position[k][j][i][2],\ + 0,\ + -1*G4P_carrier_list.ionized_pairs[k][j][i],\ + 1) + if not electron.diffuse_not_in_sensor(my_d): + self.electrons.append(electron) + self.diffuse_loop(my_d,my_f) + + Xbins=int(my_d.l_x // electron.pixel) + Ybins=int(my_d.l_y // electron.pixel) + Xup=my_d.l_x // electron.pixel + Yup=my_d.l_y // electron.pixel + test_charge = ROOT.TH2F("charge", "charge",Xbins, 0, Xup, Ybins, 0, Yup) + for i in range(len(self.row)): + #test_charge.SetBinContent(int(self.row[i]),int(self.column[i]),self.charge[i]) + test_charge.Fill(self.row[i],self.column[i],self.charge[i]) + + sum_fired = ROOT.TH2F("charge", "Pixel Detector charge",Xbins, 0, Xup, Ybins, 0, Yup) + sum_fired.Add(test_charge) + + self.sum_charge = ROOT.TH2F("charge", "Pixel Detector charge",Xbins, 0, Xup, Ybins, 0, Yup) + self.sum_charge.Add(test_charge) + + test_charge.Reset + collected_charge=self.pixel_charge(my_d,Xbins,Ybins) + signal_charge.append(collected_charge) + + Hit["index"],Hit["charge"] = self.pixel_fired(sum_fired,Xbins,Ybins) + l_dict[j] = Hit + print("%f electrons are collected in event_ %d,layer %d" %(sum(self.charge),k,j)) + self.sum_signal.append(signal_charge) + self.event.append(l_dict) + #print(signal_charge) + del signal_charge + #print(self.sum_signal) + #print(self.event) + + def diffuse_loop(self, my_d, my_f): + for electron in self.electrons: + while not electron.diffuse_not_in_sensor(my_d): + electron.diffuse_single_step(my_d, my_f) + electron.diffuse_end(my_f) + x,y,charge_quantity = electron.pixel_position(my_f,my_d) + if (x != -1)&(y != -1): + self.row.append(x) + self.column.append(y) + self.charge.append(charge_quantity) + + def pixel_charge(self,my_d,Xbins,Ybins): + for x in range(Xbins): + for y in range(Ybins): + charge =self.sum_charge.GetBinContent(x,y) + if (charge>0.2): + self.collected_charge.append([x,y,charge]) + return self.collected_charge + + def pixel_fired(self,tot,Xbins,Ybins): + Hit = {'index':[],'charge':[]} + for x in range(Xbins): + for y in range(Ybins): + charge =tot.GetBinContent(x,y) + if (charge>0.2): + Hit["index"].append([x,y]) + Hit["charge"].append(charge) + return Hit["index"],Hit["charge"] + + +class PixelCarrierListFromG4P: + def __init__(self, my_d,my_g4p): + """ + Description: + Events position and energy depositon + Parameters: + material : string + deciding the energy loss of MIP + my_g4p : Particles + batch : int + batch = 0: Single event, select particle with long enough track + batch != 0: Multi event, assign particle with batch number + Modify: + 2022/10/25 + """ + batch = len(my_g4p.localposition) + layer = len(my_d.lt_z) + material = my_d.material + self.pixelsize_x = my_d.p_x + self.pixelsize_y = my_d.p_y + self.pixelsize_z = my_d.p_z + + if (material == "SiC"): + self.energy_loss = 8.4 #ev + elif (material == "Si"): + self.energy_loss = 3.6 #ev + + self.track_position, self.ionized_pairs= [],[] + self.layer= layer + for j in range(batch): + self.single_event(my_g4p,j) + + def single_event(self,my_g4p,j): + s_track_position,s_energy= [],[] + for i in range(self.layer): + position = [] + energy = [] + name = "Layer_"+str(i) + #print(name) + for k in range(len(my_g4p.devicenames[j])): + px,py,pz = self.split_name(my_g4p.devicenames[j][k]) + if name in my_g4p.devicenames[j][k]: + tp = [0 for i in range(3)] + tp[0] = my_g4p.localposition[j][k][0]+(px-0.5)*self.pixelsize_x + tp[1] = my_g4p.localposition[j][k][1]+(py-0.5)*self.pixelsize_y + tp[2] = my_g4p.localposition[j][k][2]+self.pixelsize_z/2 + position.append(tp) + energy.append(my_g4p.energy_steps[j][k]) + s_track_position.append(position) + pairs = [step*1e6/self.energy_loss for step in energy] + s_energy.append(pairs) + del position,energy + self.track_position.append(s_track_position) + self.ionized_pairs.append(s_energy) + + def split_name(self,volume_name): + parts = volume_name.split('_') + return int(parts[1]),int(parts[2]),int(parts[4]) + diff --git a/current/model.py b/current/model.py index d14752479af598f3ba22813012a9da0dcf5412cc..4e484b1d28032bef95afb0a54ba7fc17bfb994cb 100644 --- a/current/model.py +++ b/current/model.py @@ -205,7 +205,7 @@ class Material: plt.title("Mobility Model") plt.grid(True,ls = '--',which="both") fig.show() - fig.savefig("./output/model/"+self.mat_name+"Mobility"+self.mobility_model+".png") + fig.savefig("./output/current/model/"+self.mat_name+"Mobility"+self.mobility_model+".png") def cal_coefficient(self, electric_field, charges, temperature): """ Define Avalanche Model """ @@ -330,38 +330,6 @@ class Material: return coefficient -class Vector: - def __init__(self,a1,a2,a3): - self.components = [a1,a2,a3] - - def cross(self,Vector_b): - """ Get vector cross product of self and another Vector""" - o1 = self.components[1]*Vector_b.components[2]-self.components[2]*Vector_b.components[1] - o2 = self.components[2]*Vector_b.components[0]-self.components[0]*Vector_b.components[2] - o3 = self.components[0]*Vector_b.components[1]-self.components[1]*Vector_b.components[0] - return Vector(o1,o2,o3) - - def get_length(self): - " Return length of self" - return math.sqrt(self.components[0]*self.components[0]+self.components[1]*self.components[1]+self.components[2]*self.components[2]) - - def add(self,Vector_b): - " Return the sum of two Vectors. eg: [1,2,3]+[1,2,3] = [2,4,6]" - o1 = self.components[0]+Vector_b.components[0] - o2 = self.components[1]+Vector_b.components[1] - o3 = self.components[2]+Vector_b.components[2] - return Vector(o1,o2,o3) - - def sub(self,Vector_b): - " Return the subtraction of two Vectors. eg: [1,2,3]-[1,2,3] = [0,0,0]" - o1 = self.components[0]-Vector_b.components[0] - o2 = self.components[1]-Vector_b.components[1] - o3 = self.components[2]-Vector_b.components[2] - return Vector(o1,o2,o3) - - def mul(self,k): - " Return Vector multiplied by number. eg: 2 * [1,2,3] = [2,4,6]" - return Vector(self.components[0]*k,self.components[1]*k,self.components[2]*k) def main(): if not (os.path.exists("./output/model")): diff --git a/draw/__init__.py b/draw/__init__.py deleted file mode 100644 index 56d912c04af8f1cd7e0be6f7dfd6ecfaeaef12c4..0000000000000000000000000000000000000000 --- a/draw/__init__.py +++ /dev/null @@ -1,208 +0,0 @@ -import os -import ROOT -from . import iv -from . import cv -from . import compare_iv -from . import compare_cv -from . import draw_iv_cv_paper9 -from . import alpha_ana_SICAR -from . import data_convolution -def main(kwargs): - label = kwargs['label'] - - if label == 'sicar1.1.8': - input_dir = '/publicfs/atlas/atlasnew/silicondet/itk/raser/wangkeqi/sicar1.1.8' - output_dir = '/afs/ihep.ac.cn/users/w/wangkeqi/raser/output/fig' - draw_figure(input_dir, output_dir, label) - elif label == 'compare_sicar1.1.8_iv': - iv.main(label) - elif label == 'compare_sicar1.1.8_cv': - cv.main(label) - elif label == 'sicar1.1.8-1': - input_dir = '/publicfs/atlas/atlasnew/silicondet/itk/raser/wangkeqi/sicar1.1.8' - output_dir = '/afs/ihep.ac.cn/users/w/wangkeqi/raser/output/fig' - draw_figure(input_dir, output_dir, label) - elif label == 'sicar1.1.8-2': - input_dir = '/publicfs/atlas/atlasnew/silicondet/itk/raser/wangkeqi/sicar1.1.8' - output_dir = '/afs/ihep.ac.cn/users/w/wangkeqi/raser/output/fig' - draw_figure(input_dir, output_dir, label) - elif label == 'itk_md8_data_v1': - input_dir = '/publicfs/atlas/atlasnew/silicondet/itk/raser/lizhan/itkmd8/itkmd8data' - output_dir = '/afs/ihep.ac.cn/users/l/lizhan/disk/scrathfs/raser/output/fig' - draw_figure(input_dir, output_dir, label,xtitle_iv="Reverse Bias Voltage [V]",ytitle_iv="Current [nA]", - xtitle_cv="Reverse Bias Voltage [V]",ytitle_cv="Capacitance [pF]", - xlowerlimit_iv=0,xupperlimit_iv=700,ylowerlimit_iv=1e-11,yupperlimit_iv=1e-5,ylogscale_iv=0, - xlowerlimit_cv=0,xupperlimit_cv=400,ylowerlimit_cv=0,yupperlimit_cv=1e2,ylogscale_cv=0) - elif label == 'itk_md8_sim_v1': - input_dir = '/publicfs/atlas/atlasnew/silicondet/itk/raser/lizhan/itkmd8/itkmd8sim' - output_dir = '/afs/ihep.ac.cn/users/l/lizhan/disk/scrathfs/raser/output/fig' - draw_figure(input_dir, output_dir, label,xtitle_iv="Reverse Bias Voltage [V]",ytitle_iv="Current [nA]", - xtitle_cv="Reverse Bias Voltage [V]",ytitle_cv="Capacitance [pF]", - xlowerlimit_iv=0,xupperlimit_iv=700,ylowerlimit_iv=1e-11,yupperlimit_iv=1e-5,ylogscale_iv=0, - xlowerlimit_cv=0,xupperlimit_cv=400,ylowerlimit_cv=0,yupperlimit_cv=1e2,ylogscale_cv=0) - elif label == 'itk_md8_compare_dataandsim_v1': - input_dir = '/publicfs/atlas/atlasnew/silicondet/itk/raser/lizhan/itkmd8/comparison' - output_dir = '/afs/ihep.ac.cn/users/l/lizhan/disk/scrathfs/raser/output/fig' - cv.main(label) - iv.main(label) - elif label == 'itk_atlas18_sim_v1': - input_dir = '/publicfs/atlas/atlasnew/silicondet/itk/raser/lizhan/atlas18/sim' - output_dir = '/afs/ihep.ac.cn/users/l/lizhan/disk/scrathfs/raser/output/fig' - draw_figure(input_dir, output_dir, label,xtitle_iv="Reverse Bias Voltage [V]",ytitle_iv="Current [A]", - xtitle_cv="Reverse Bias Voltage [V]",ytitle_cv="Capacitance [pF]", - xlowerlimit_iv=0,xupperlimit_iv=700,ylowerlimit_iv=1e-11,yupperlimit_iv=1e-5,ylogscale_iv=0, - xlowerlimit_cv=0,xupperlimit_cv=400,ylowerlimit_cv=0,yupperlimit_cv=1e2,ylogscale_cv=0) - elif label == 'itk_atlas18_data_v1': - input_dir = '/publicfs/atlas/atlasnew/silicondet/itk/raser/lizhan/atlas18/data' - output_dir = '/afs/ihep.ac.cn/users/l/lizhan/disk/scrathfs/raser/output/fig' - draw_figure(input_dir, output_dir, label,xtitle_iv="Reverse Bias Voltage [V]",ytitle_iv="Current [nA]", - xtitle_cv="Reverse Bias Voltage [V]",ytitle_cv="Capacitance [pF]", - xlowerlimit_iv=0,xupperlimit_iv=700,ylowerlimit_iv=1e-11,yupperlimit_iv=1e-5,ylogscale_iv=0, - xlowerlimit_cv=0,xupperlimit_cv=400,ylowerlimit_cv=0,yupperlimit_cv=1e2,ylogscale_cv=0) - elif label == 'sicar1.1.8-1,sicar1.1.8-2_iv': - iv.main(label) - elif label == 'sicar1.1.8-1,sicar1.1.8-2_cv': - cv.main(label) - elif label == "compare_nju_iv": - path1="/publicfs/atlas/atlasnew/silicondet/itk/raser/zhaosen/njupin_iv/nju_pin_iv.root" - path2="./output/2Dresult/simNJUPIN/simIV800.0to800.0.root" - compare_iv.main(label,path1,path2) - elif label == "compare_nju_cv": - path1="/publicfs/atlas/atlasnew/silicondet/itk/raser/zhaosen/njupin_cv/4H-SiC-PIN-cv.root" - path2="./output/2Dresult/simNJUPIN/simCV500.0to500.0.root" - compare_cv.main(label,path1,path2) - elif label == "compare_sim_sicar1.1.8_cv": - path1="/publicfs/atlas/atlasnew/silicondet/itk/raser/wangkeqi/sicar1.1.8/sicar1.1.8-11_cv.root" - path2="./output/2Dresult/simsicar1.1.6/simCV500.0to500.0.root" - compare_cv.main(label,path1,path2) - elif label == "compare_sicar_cv_1d": - path1="/publicfs/atlas/atlasnew/silicondet/itk/raser/wangkeqi/sicar1.1.8/iv_cv/sicar1.1.8-8_cv.root" - path2="./output/field/SICAR-1.1.8/simCV-500.0to0.0.root" - compare_cv.main(label,path1,path2) - elif label == "compare_sim_sicar1.1.8_iv": - path1="/publicfs/atlas/atlasnew/silicondet/itk/raser/wangkeqi/sicar1.1.8/sicar1.1.8-11_iv.root" - path2="./output/2Dresult/simsicar1.1.6/simIV650.0to650.0.root" - compare_iv.main(label,path1,path2) - elif label =="p9": - csv_folder="/publicfs/atlas/atlasnew/silicondet/itk/raser/zhaosen/samples" - for file in os.listdir(csv_folder): - if file.endswith(".csv"): - csv_filename = os.path.join(csv_folder, file) - root_filename = file.replace(".csv", ".root") - root_fullpath = os.path.join(csv_folder, root_filename) - draw_iv_cv_paper9.create_root_file(csv_filename, root_fullpath) - draw_iv_cv_paper9.main() - alpha_ana_SICAR.main() - data_convolution.landau_mirror() - data_convolution.energy_sim() - else: - raise NameError(label) - -def draw_figure(input_dir, output_dir, label,xtitle_iv="Reverse Bias Voltage [V]",ytitle_iv="Current [A]", - xtitle_cv="Reverse Bias Voltage [V]",ytitle_cv="Capacitance [pF]", - xlowerlimit_iv=0,xupperlimit_iv=510,ylowerlimit_iv=1e-11,yupperlimit_iv=1e-5,ylogscale_iv=0, - xlowerlimit_cv=0,xupperlimit_cv=399.99,ylowerlimit_cv=0,yupperlimit_cv=1e2,ylogscale_cv=0): - - com_name = [] - for file in os.listdir(input_dir): - if file.endswith('.root'): - com_name.append(file) - for name in com_name: - if label == 'sicar1.1.8' and not name.startswith('sicar1.1.8'): - continue - elif label == 'sicar1.1.8-1' and not name.startswith('sicar1.1.8-1_'): - continue - elif label == 'sicar1.1.8-2' and not name.startswith('sicar1.1.8-2_'): - continue - name = name.split('.root')[0] - - input_file = os.path.join(input_dir, name + '.root') - output_file = os.path.join(output_dir, name + '.root') - pdf_file = os.path.join(output_dir, name + '.pdf') - png_file = os.path.join(output_dir, name + '.png') - - if name.endswith('iv'): - file = ROOT.TFile(input_file, "READ") - tree = file.Get("myTree") - graph = ROOT.TGraph() - - for i, event in enumerate(tree): - if label in ['itk_md8_data','itk_atlas18_data']: - x = event.Voltage_V - x = abs(x) - y = event.Current_nA - y = abs(y)*1e-9 - elif label == 'itk_atlas18_sim': - x = event.Voltage - x = abs(x) - y = event.Current - y = abs(y)*1e-9 - else: - x = event.Value - x = abs(x) - y = event.Reading - y = abs(y) - graph.SetPoint(i, x, y) - - draw_with_options(graph,name,output_file,pdf_file,png_file,xtitle_iv,ytitle_iv, - xlowerlimit_iv,xupperlimit_iv,ylowerlimit_iv,yupperlimit_iv,ylogscale_iv) - #problem: unable to change y limits - - if name.endswith('cv'): - file = ROOT.TFile(input_file, "READ") - tree = file.Get("myTree") - graph = ROOT.TGraph() - for i, event in enumerate(tree): - x = event.Voltage - x = abs(x) - y = event.Capacitance - y = abs(y) - graph.SetPoint(i, x, y) - - draw_with_options(graph,name,output_file,pdf_file,png_file,xtitle_cv,ytitle_cv, - xlowerlimit_cv,xupperlimit_cv,ylowerlimit_cv,yupperlimit_cv,ylogscale_cv) - - -def draw_with_options(graph,name,output_file,pdf_file,png_file,xtitle,ytitle, - xlowerlimit,xupperlimit,ylowerlimit,yupperlimit,ylogscale): - graph.SetNameTitle("") - graph.SetLineWidth(1) - graph.SetMarkerColor(ROOT.kBlack) - graph.SetMarkerStyle(24) - graph.SetMarkerSize(1) - - graph.GetXaxis().SetTitle(xtitle) - graph.GetXaxis().SetLimits(xlowerlimit,xupperlimit) - graph.GetXaxis().CenterTitle() - graph.GetXaxis().SetTitleOffset(1.4) - graph.GetXaxis().SetTitleSize(0.05) - graph.GetXaxis().SetLabelSize(0.05) - graph.GetXaxis().SetNdivisions(505) - - graph.GetYaxis().SetLimits(ylowerlimit,yupperlimit) - graph.GetYaxis().SetTitle(ytitle) - graph.GetYaxis().CenterTitle() - graph.GetYaxis().SetTitleOffset(1.8) - graph.GetYaxis().SetTitleSize(0.05) - graph.GetYaxis().SetLabelSize(0.05) - graph.Draw("AP") - - c = ROOT.TCanvas("c","c",500,500) - c.SetLeftMargin(0.22) - c.SetBottomMargin(0.16) - legend = ROOT.TLegend(0.27,0.67,0.62,0.80) - c.SetGrid() - c.SetFrameLineWidth(5) - - legend.SetTextSize(0.04) - legend.AddEntry(graph,name.split('_')[0]) - - c.cd() - c.SetLogy(ylogscale) - graph.Draw() - legend.Draw() - - c.SaveAs(output_file) - c.SaveAs(pdf_file) - c.SaveAs(png_file) - del c \ No newline at end of file diff --git a/draw/alpha_ana_SICAR.py b/draw/alpha_ana_SICAR.py deleted file mode 100644 index a37f5d0a31584219ccef8aa7b967d4793496c836..0000000000000000000000000000000000000000 --- a/draw/alpha_ana_SICAR.py +++ /dev/null @@ -1,167 +0,0 @@ -import ROOT -import os -import numpy -import sys -import math - -def read_file(file_path,wave_name): - - with open(file_path + '/' + wave_name, 'r') as f: - - lines = f.readlines() - points = lines[1:] - time, volt = [],[] - - for point in points: - try: - time.append(float(point.strip('\n').strip().split(',')[3])*1e9) - volt.append(float(point.strip('\n').strip().split(',')[4])*1e3) - except Exception as e: - pass - - return time,volt - -def get_max(time_list,volt_list): - - volt_max = 0. - time_max = 0. - index_max = 0 - for i in range(len(volt_list)): - if(volt_list[i]>volt_max): - time_max = time_list[i] - volt_max = volt_list[i] - index_max = i - return time_max,volt_max,index_max - -def get_baseline(time_list,volt_list,time_win): - - time_start = time_list[0] - time_end = time_start + time_win - count = 0. - total = 0. - for i in range(len(time_list)): - if(time_list[i] < time_end): - total += volt_list[i] - count += 1. - baseline = total/count - return baseline - -def get_charge(time_list,volt_list,baseline): - - volt_cut_baseline_list = [] - for i in range(len(volt_list)): - volt_cut_baseline_list.append(volt_list[i]-baseline) - - time_max,volt_max,index_max = get_max(time_list,volt_cut_baseline_list) - - time_bin = time_list[1]-time_list[0] - tmp_integrate = 0. - - tmp_index = index_max - while True: - if(volt_cut_baseline_list[tmp_index]<0.): break - tmp_integrate += volt_cut_baseline_list[tmp_index]*time_bin - tmp_index -= 1 - - tmp_index = index_max+1 - while True: - if(volt_cut_baseline_list[tmp_index]<0.): break - tmp_integrate += volt_cut_baseline_list[tmp_index]*time_bin - tmp_index += 1 - - charge = tmp_integrate*(1e-12)/50/100*(1e15) - - return charge - -def main(): - path = '/publicfs/atlas/atlasnew/silicondet/itk/raser/zhaosen/CCE_1.1.8-8-2/' - for file in ["100V","150V","200V","250V","300V","350V"]: - input_name = file - path = '/publicfs/atlas/atlasnew/silicondet/itk/raser/zhaosen/CCE_1.1.8-8-2/' + input_name #文件路径 - waves = os.listdir(path) - time,volt = [],[] - window = 1 - - c = ROOT.TCanvas('c','c',600,500) - c.SetLeftMargin(0.16) - c.SetBottomMargin(0.14) - # c = ROOT.TCanvas('c','c',1500,600) - # c.Divide(2,1) - charge_graph = ROOT.TH1F('charge','charge',50,150,350) #bin,最å°å€¼ï¼Œæœ€å¤§å€¼ - # volt_graph = ROOT.TH1F('volt',"volt",50,800,1800) - charge_graph.SetStats(0) # å…³é—统计框架 - # volt_graph.SetStats(0) # å…³é—统计框架 - - - for wave in waves: - - print(wave) - time,volt = read_file(path,wave) - time_max,volt_max,index_max = get_max(time,volt) - baseline = get_baseline(time,volt,window) - try: - charge = get_charge(time,volt,baseline) - except: - print('error') - if charge > 30 and charge < 330: - charge_graph.Fill(charge) - # volt_graph.Fill(volt_max) - - charge_graph.SetTitle(' ') - charge_graph.GetXaxis().SetTitle("Charge (fC)") - charge_graph.GetXaxis().CenterTitle() - charge_graph.GetXaxis().SetTitleOffset(1.2) - charge_graph.GetXaxis().SetTitleSize(0.05) - charge_graph.GetXaxis().SetLabelSize(0.05) - # charge_graph.GetXaxis().SetNdivisions(505) - charge_graph.GetYaxis().CenterTitle() - charge_graph.GetYaxis().SetTitleOffset(1.6) - charge_graph.GetYaxis().SetTitleSize(0.05) - charge_graph.GetYaxis().SetLabelSize(0.05) - # ROOT.TGaxis.SetMaxDigits(3) - # charge_graph.GetYaxis().SetMaxDigits(3) - # charge_graph.GetYaxis().SetRangeUser(79, 104.99) - - # volt_graph.GetXaxis().SetTitle('Voltage [mV]') - - # c.cd(1) - c.cd() - charge_graph.Draw() - - gaussian = ROOT.TF1("gaussian", "gaus", 150, 350) - - - charge_graph.Fit(gaussian, "R") - #gaussian.Draw("same") - - mean = gaussian.GetParameter(1) - sigma = gaussian.GetParameter(2) - # æ·»åŠ æœ—é“分布 - - landau = ROOT.TF1("landau", "landau", 150, 350) # 创建朗é“分布函数 - charge_graph.Fit(landau,"R") - #landau.Draw("same") - - - landau_mean = landau.GetParameter(0) - landau_sigma = landau.GetParameter(1) - - convolution = ROOT.TF1("convolution", "landau*gaus", 150, 350) # 创建å·ç§¯å‡½æ•° - convolution.SetParameters(landau_mean, landau_sigma, mean, sigma) # 设置åˆå§‹å‚æ•° - charge_graph.Fit(convolution, "R") # 进行å·ç§¯æ‹Ÿåˆ - x_max = convolution.GetMaximumX() - #convolution.GetParameter() - convolution.Draw("same") - latex = ROOT.TLatex() - latex.SetTextSize(0.04) - latex.SetTextAlign(13) - latex.DrawLatexNDC(0.2, 0.8, "x_max = %.2f" % x_max ) - # latex.DrawLatexNDC(0.2, 0.75, "Sigma = %.2f" % sigma) - - # c.cd(2) - # volt_graph.Draw() - - c.SaveAs('/publicfs/atlas/atlasnew/silicondet/itk/raser/zhaosen/CCE_1.1.8-8-2/fig_sen/'+ input_name + '_distribution_cut.png') - c.SaveAs('/publicfs/atlas/atlasnew/silicondet/itk/raser/zhaosen/CCE_1.1.8-8-2/fig_sen/'+ input_name + '_distribution_cut.pdf') -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/draw/compare_cv.py b/draw/compare_cv.py deleted file mode 100755 index 70ad438b678792165ff2cc237adaa1f2d2aa8e0b..0000000000000000000000000000000000000000 --- a/draw/compare_cv.py +++ /dev/null @@ -1,66 +0,0 @@ - -import ROOT -import os -def compare_cv(label,path1,path2): - folder_path="./output/draw" - if not os.path.exists(folder_path): - os.makedirs(folder_path) - - file1 = ROOT.TFile(path1) - tree1 = file1.Get("myTree") - - # 创建第一个图形 - canvas = ROOT.TCanvas("canvas", "Canvas", 1600, 1200) - - # 创建一个TGraph对象æ¥å˜å‚¨ç¬¬ä¸€ä¸ªROOT文件ä¸çš„æ•°æ® - graph1 = ROOT.TGraph(tree1.GetEntries()) - - # ä»Žæ ‘ä¸èŽ·å–å˜é‡æ•°æ®å¹¶æ·»åŠ 到TGraphå¯¹è±¡ä¸ - for i, event in enumerate(tree1): - graph1.SetPoint(i, event.Voltage, event.Capacitance) - - # 设置第一个数æ®ç‚¹çš„æ ‡è®°æ ·å¼å’Œé¢œè‰² - graph1.SetMarkerStyle(20) - graph1.SetMarkerColor(ROOT.kBlue) - graph1.SetMarkerSize(0.5) - graph1.GetXaxis().SetTitle("Voltage/v") - graph1.GetYaxis().SetTitle("CAP/pF") - # 打开第二个ROOT文件 - file2 = ROOT.TFile(path2) - tree2 = file2.Get("SicarTestCV") - - # 创建一个TGraph对象æ¥å˜å‚¨ç¬¬äºŒä¸ªROOT文件ä¸çš„æ•°æ® - graph2 = ROOT.TGraph(tree2.GetEntries()) - - # ä»Žæ ‘ä¸èŽ·å–å˜é‡æ•°æ®å¹¶æ·»åŠ 到TGraphå¯¹è±¡ä¸ - for i, event in enumerate(tree2): - graph2.SetPoint(i, event.voltage, event.CAP) - - # 设置第二个数æ®ç‚¹çš„æ ‡è®°æ ·å¼å’Œé¢œè‰² - graph2.SetMarkerStyle(21) - graph2.SetMarkerColor(ROOT.kRed) - graph2.SetMarkerSize(0.5) - - graph2.GetXaxis().SetTitle("Voltage/v") - graph2.GetYaxis().SetTitle("CAP/pF") - - canvas = ROOT.TCanvas("canvas", "Canvas", 1600, 1200) - graph1.SetTitle("{}_SimulateVSexperiment".format(label)) - graph1.Draw("AP") - graph2.Draw("P") - - # 创建图例 - legend = ROOT.TLegend(0.7, 0.7, 0.9, 0.9) - legend.AddEntry(graph1, "experiment", "p") - legend.AddEntry(graph2, "simulate", "p") - legend.Draw() - - # 显示图形 - - canvas.Update() - canvas.SaveAs("./output/draw/compare_{}_ex.root".format(label)) -def main(label,path1,path2): - compare_cv(label,path1,path2) - -if __name__ == "__main__": - main(label,path1,path2) \ No newline at end of file diff --git a/draw/compare_iv.py b/draw/compare_iv.py deleted file mode 100755 index 8b75d2c52121c5434398514a24c2aa5321a689f7..0000000000000000000000000000000000000000 --- a/draw/compare_iv.py +++ /dev/null @@ -1,62 +0,0 @@ -import ROOT -import os -def compare_iv(label,path1,path2): - folder_path="./output/draw" - if not os.path.exists(folder_path): - os.makedirs(folder_path) - - file1 = ROOT.TFile(path1) - tree1 = file1.Get("myTree") - - # 创建一个TGraph对象æ¥å˜å‚¨ç¬¬ä¸€ä¸ªROOT文件ä¸çš„æ•°æ® - graph1 = ROOT.TGraph(tree1.GetEntries()) - - # ä»Žæ ‘ä¸èŽ·å–å˜é‡æ•°æ®å¹¶æ·»åŠ 到TGraphå¯¹è±¡ä¸ - for i, event in enumerate(tree1): - graph1.SetPoint(i, abs(event.Value), abs(event.Reading)) - - # 设置第一个数æ®ç‚¹çš„æ ‡è®°æ ·å¼å’Œé¢œè‰² - graph1.SetMarkerStyle(20) - graph1.SetMarkerColor(ROOT.kBlue) - graph1.SetMarkerSize(0.5) - graph1.GetXaxis().SetTitle("Voltage/v") - graph1.GetYaxis().SetTitle("Current/A") - # 打开第二个ROOT文件 - file2 = ROOT.TFile(path2) - tree2 = file2.Get("SicarTestIV") - - # 创建一个TGraph对象æ¥å˜å‚¨ç¬¬äºŒä¸ªROOT文件ä¸çš„æ•°æ® - graph2 = ROOT.TGraph(tree2.GetEntries()) - - # ä»Žæ ‘ä¸èŽ·å–å˜é‡æ•°æ®å¹¶æ·»åŠ 到TGraphå¯¹è±¡ä¸ - for i, event in enumerate(tree2): - graph2.SetPoint(i, event.voltage, event.Current) - - # 设置第二个数æ®ç‚¹çš„æ ‡è®°æ ·å¼å’Œé¢œè‰² - graph2.SetMarkerStyle(21) - graph2.SetMarkerColor(ROOT.kRed) - graph2.SetMarkerSize(0.5) - - graph2.GetXaxis().SetTitle("Voltage/v") - graph2.GetYaxis().SetTitle("Current/A") - - canvas = ROOT.TCanvas("canvas", "Canvas", 800, 600) - graph1.SetTitle("{}_SimulateVSexperiment".format(label)) - graph1.Draw("AP") - graph2.Draw("P") - - # 创建图例 - legend = ROOT.TLegend(0.7, 0.7, 0.9, 0.9) - legend.AddEntry(graph1, "experiment", "p") - legend.AddEntry(graph2, "simulate", "p") - legend.Draw() - - # 显示图形 - - canvas.Update() - canvas.SaveAs("./output/draw/compare_{}_ex.root".format(label)) -def main(label,path1,path2): - compare_iv(label,path1,path2) - -if __name__ == "__main__": - main(label,path1,path2) \ No newline at end of file diff --git a/draw/cv.py b/draw/cv.py deleted file mode 100644 index 39e891aaae89d928a3832fde76d0c6604382d37c..0000000000000000000000000000000000000000 --- a/draw/cv.py +++ /dev/null @@ -1,94 +0,0 @@ -import os -import ROOT - -def draw_cv(input_dir, output_dir, label): - com_name = [] - legend_name = [] - - for file in os.listdir(input_dir): - if file.endswith('.root'): - com_name.append(file) - - c_c = ROOT.TCanvas("c_c", "c_c", 800, 800) - c_c.SetLeftMargin(0.22) - c_c.SetBottomMargin(0.16) - c_c.SetGrid() - c_c.SetFrameLineWidth(5) - c_c.SetLogy() - multigraphs_c = ROOT.TMultiGraph() - - for i in range(len(com_name)): - name = com_name[i] - if label == 'sicar1.1.8_cv' and not name.startswith('sicar1.1.8'): - continue - elif label == 'sicar1.1.8-1,sicar1.1.8-2_cv' and not (name.startswith('sicar1.1.8-1_')) and not (name.startswith('sicar1.1.8-2_')): - continue - - name = name.split('.root')[0] - - input_file = os.path.join(input_dir, name + '.root') - - if name.endswith('cv'): - file = ROOT.TFile(input_file, "READ") - tree = file.Get("myTree") - graph = ROOT.TGraph() - legend_name.append(name.split('_')[0]) - - for i, event in enumerate(tree): - x = event.Voltage - x = abs(x) - y = event.Capacitance - y = abs(y) - graph.SetPoint(i, x, y) - - graph.SetNameTitle("") - graph.SetMarkerColor(0+i) - graph.SetMarkerStyle(24) - graph.SetMarkerSize(1) - multigraphs_c.Add(graph) - - multigraphs_c.GetXaxis().SetLimits(0,399.99) - multigraphs_c.GetXaxis().SetTitle("Reverse Bias Voltage [V]") - multigraphs_c.GetXaxis().CenterTitle() - multigraphs_c.GetXaxis().SetTitleOffset(1.4) - multigraphs_c.GetXaxis().SetTitleSize(0.05) - multigraphs_c.GetXaxis().SetLabelSize(0.05) - multigraphs_c.GetXaxis().SetNdivisions(505) - multigraphs_c.GetYaxis().SetLimits(4,5e2) - multigraphs_c.GetYaxis().SetRangeUser(4, 5e2) - multigraphs_c.GetYaxis().SetTitle("Capacitance [pF]") - multigraphs_c.GetYaxis().CenterTitle() - multigraphs_c.GetYaxis().SetTitleOffset(1.8) - multigraphs_c.GetYaxis().SetTitleSize(0.05) - multigraphs_c.GetYaxis().SetLabelSize(0.05) - multigraphs_c.Draw("AP") - - max_i = len(legend_name) - 1 - legend_c = ROOT.TLegend(0.52,0.82-0.05*float(max_i),0.87,0.85) - legend_c.SetTextSize(0.04) - - for i, graph in enumerate(multigraphs_c): - legend_c.AddEntry(graph, legend_name[i]) - - legend_c.Draw() - - file_name_c = label + ".root" - c_c.SaveAs(os.path.join(output_dir, file_name_c)) - file_name_c = label + ".pdf" - c_c.SaveAs(os.path.join(output_dir, file_name_c)) - file_name_c = label + ".png" - c_c.SaveAs(os.path.join(output_dir, file_name_c)) - - -def main(label): - if label=='itk_md8_compare_dataandsim': - input_dir = '/publicfs/atlas/atlasnew/silicondet/itk/raser/lizhan/itkmd8/comparison' - output_dir = '/afs/ihep.ac.cn/users/l/lizhan/disk/scrathfs/raser/output/fig' - else: - input_dir = '/publicfs/atlas/atlasnew/silicondet/itk/raser/wangkeqi/sicar1.1.8' - output_dir = '/afs/ihep.ac.cn/users/w/wangkeqi/raser/output/fig' - - draw_cv(input_dir, output_dir, label) - -if __name__ == "__main__": - main() diff --git a/draw/data_convolution.py b/draw/data_convolution.py deleted file mode 100644 index be207ece6f4a4f05bcfcc315d624368c8bd91d16..0000000000000000000000000000000000000000 --- a/draw/data_convolution.py +++ /dev/null @@ -1,324 +0,0 @@ -#!/usr/bin/env python3 -# -*- encoding: utf-8 -*- - -import ROOT -import os -import math -import array -import time as tm -import pandas -def read_file(file_path,wave_name): - - with open(file_path + '/' + wave_name, 'r') as f: - - lines = f.readlines() - points = lines[1:] - time, volt = [],[] - - for point in points: - try: - time.append(float(point.strip('\n').strip().split(',')[3])*1e9) - volt.append(float(point.strip('\n').strip().split(',')[4])*1e3) - except Exception as e: - pass - - return time,volt - -def get_max(time_list,volt_list): - - volt_max = 0. - time_max = 0. - index_max = 0 - for i in range(len(volt_list)): - if(volt_list[i]>volt_max): - time_max = time_list[i] - volt_max = volt_list[i] - index_max = i - return time_max,volt_max,index_max - -def get_baseline(time_list,volt_list,time_win): - - time_start = time_list[0] - time_end = time_start + time_win - count = 0. - total = 0. - for i in range(len(time_list)): - if(time_list[i] < time_end): - total += volt_list[i] - count += 1. - baseline = total/count - return baseline - -def get_charge(time_list,volt_list,baseline): - - volt_cut_baseline_list = [] - for i in range(len(volt_list)): - volt_cut_baseline_list.append(volt_list[i]-baseline) - - time_max,volt_max,index_max = get_max(time_list,volt_cut_baseline_list) - - time_bin = time_list[1]-time_list[0] - tmp_integrate = 0. - - tmp_index = index_max - while True: - if(volt_cut_baseline_list[tmp_index]<0.): break - tmp_integrate += volt_cut_baseline_list[tmp_index]*time_bin - tmp_index -= 1 - - tmp_index = index_max+1 - while True: - if(volt_cut_baseline_list[tmp_index]<0.): break - tmp_integrate += volt_cut_baseline_list[tmp_index]*time_bin - tmp_index += 1 - - charge = tmp_integrate*(1e-12)/50/100*(1e15) - - return charge - - - -def energy_sim(): - c=ROOT.TCanvas("c","c",700,500) - charge_graph_file=ROOT.TFile.Open("./output/SiC_LGAD/energy_deposition_final.root") - charge_graph=charge_graph_file.Get("Edetector") - - # 定义新的直方图 - new_hist = ROOT.TH1F("new_histogram", "New Histogram", 200, 4.1, 4.6) - new_hist.SetStats(0) - # é‡æ–°å¡«å……æ•°æ®åˆ°æ–°çš„直方图 - for i in range(charge_graph.GetNbinsX()): - bin_content = charge_graph.GetBinContent(i) - bin_center = charge_graph.GetBinCenter(i) - new_hist.Fill(bin_center, bin_content) - - # 将新的直方图ä¿å˜åˆ°æ–‡ä»¶ - new_file = ROOT.TFile("new_output.root", "RECREATE") - new_hist.Write() - new_file.Close() - npars=3 - f2 = ROOT.TF1("f2", "[2]*TMath::Landau(2*[0]-x, [0], [1])", 4.1, 4.6,npars) - #f2 = ROOT.TF1("f2", "[2]*TMath::Gaus(x, [0], [1])", 0, 2.5,npars) - f2.SetParLimits(0,4.,5) - f2.SetParLimits(1,0,1) - f2.SetParLimits(2,70.,1000) - f2.SetParameters(4.4,0.1,70) - #h=ROOT.TH1F("h","data",75,150,350) - weight_factor = 1 # å‡è®¾å¢žåŠ 2å€çš„æƒé‡ - data_file = open("data_points.txt", "w") - for i in range(new_hist.GetNbinsX()): - bin_content = new_hist.GetBinContent(i) - bin_error = new_hist.GetBinError(i) - #if bin_content < 80: # 举例:å‡è®¾é«˜äºŽæŸä¸ªé˜ˆå€¼çš„æ•°æ®ç‚¹å¢žåŠ æƒé‡ - new_hist.SetBinContent(i, bin_content) - data_file.write(f"{new_hist.GetXaxis().GetBinCenter(i)} {bin_content}\n") - new_hist.SetBinError(i,0) - data_file.close() - # è¿›è¡Œæ‹Ÿåˆ - new_hist.Fit(f2,"W") - - f2.SetLineColor(ROOT.kBlue) - num_points = 1000 # 设置需è¦è®¡ç®—çš„ç‚¹çš„æ•°é‡ - fit_points = [] - for i in range(num_points): - x = 4 + i * (5 - 4) / num_points # 在x范围内å‡åŒ€é€‰å–点 - y = f2.Eval(x) # 计算拟åˆæ›²çº¿ä¸Šçš„点 - fit_points.append((x, y)) - - # 将拟åˆæ›²çº¿ä¸Šçš„点写入txt文件 - output_file = open("fit_curve.txt", "w") - for point in fit_points: - output_file.write(f"{point[0]} {point[1]}\n") - - output_file.close() - - new_hist.SetLineColor(ROOT.kBlack) - new_hist.SetMarkerStyle(20) # è®¾ç½®ç‚¹çš„æ ·å¼ä¸ºå®žå¿ƒåœ† - new_hist.SetMarkerColor(ROOT.kBlack) # 设置点的颜色为黑色 - new_hist.SetMinimum(0) # 设置y轴最å°å€¼ - new_hist.SetMaximum(90) - new_hist.SetLabelFont(43, "XYZ") - new_hist.SetTitleFont(43, "XYZ") - new_hist.SetLabelSize(20, "XYZ") - new_hist.SetTitleSize(20, "XYZ") - new_hist.SetLabelSize(0.04, "X") # 设置Xè½´æ ‡ç¾çš„长度为2.6 - new_hist.SetLabelSize(0.04, "Y") # 设置Yè½´æ ‡ç¾çš„长度为2.6 - - new_hist.Draw("P") - #f2.Draw("same") - latex = ROOT.TLatex() - latex.SetTextSize(0.04) - latex.SetTextAlign(13) - latex.DrawLatexNDC(0.2, 0.8, "MPV= %.2f" % (f2.GetParameter(0))) - #latex.DrawLatexNDC(0.2, 0.6, "sigma= %.2f" % (f2.GetParameter(1))) - c.SaveAs("./output/SiC_LGAD/fit_alpha.svg") - c.SaveAs("./output/SiC_LGAD/fit_alpha.root") - - -def landau_mirror(): - - charge_con=[] - charge_err=[] - path = '/publicfs/atlas/atlasnew/silicondet/itk/raser/zhaosen/CCE_1.1.8-8-2/' - c = ROOT.TCanvas('c','c',1500,1200) - c.SetLeftMargin(0.16) - c.SetBottomMargin(0.14) - - #c.Divide(3, 2) - for i, file in enumerate(["100v","150v","200v","250v","300v","350v"]): - - input_name = file - path = '/publicfs/atlas/atlasnew/silicondet/itk/raser/zhaosen/alpha/' + input_name #文件路径 - waves = os.listdir(path) - time,volt = [],[] - window = 1 - - c.cd(i+1) - charge = ROOT.RooRealVar("charge", "charge", 30, 200) - - charge_graph = ROOT.TH1F('charge','charge',120,30.,200) #bin,最å°å€¼ï¼Œæœ€å¤§å€¼ - # volt_graph = ROOT.TH1F('volt',"volt",50,800,1800) - xaxis = charge_graph.GetXaxis() - yaxis = charge_graph.GetYaxis() - - # è®¾ç½®æ¨ªè½´å’Œçºµè½´æ ‡ç¾ - xaxis.SetTitle("Charge (fC)") - xaxis.CenterTitle() # å°†æ ‡ç¾å±…ä¸ - xaxis.SetTitleSize(0.04) # è®¾ç½®æ ‡ç¾çš„å¤§å° - - - yaxis.SetTitle("Counts (a.u.)") - yaxis.CenterTitle() # å°†æ ‡ç¾å±…ä¸ - yaxis.SetTitleSize(0.04) # è®¾ç½®æ ‡ç¾çš„å¤§å° - charge_graph.SetStats(0) # å…³é—统计框架S - - - output_file_2 = open("charge_histogram.{}txt".format(input_name), "w") - for wave in waves: - #print(wave) - time,volt = read_file(path,wave) - time_max,volt_max,index_max = get_max(time,volt) - baseline = get_baseline(time,volt,window) - try: - charge = get_charge(time,volt,baseline) - except: - print('error') - if charge > 30 and charge < 330: - charge_graph.Fill(charge) - - output_file_2.write(f"{charge}\n") - - - charge_var = ROOT.RooRealVar("charge_var", "charge_var", charge) - data = ROOT.RooDataHist("charge_graph", "charge_graph", ROOT.RooArgList( charge_var), ROOT.RooFit.Import(charge_graph)) - output_file_2.close() - output_file_2 = open("charge_histogram.{}txt".format(input_name), "w") - - npars=6 - #f2=ROOT.TF1("f2","0.5*[0]*[1]/TMath::Pi() /TMath::Max( 1.e-10,(x-[2])*(x-[2])+ .25*[1]*[1]") - f2 = ROOT.TF1("f2", "[2]*TMath::Landau(2*[0]-x, [0], [1])+[5]*TMath::Gaus(x,[3],[4])", 30, 200,npars) - f2.SetParLimits(0,150.,155) - f2.SetParLimits(1,0.,10) - f2.SetParLimits(2,0.,1000) - f2.SetParLimits(3,150.,155) - f2.SetParLimits(4,0.,10) - f2.SetParLimits(5,0.,1000) - f2.SetParameters(150,2,0,150,2,0) - - charge_graph.Fit(f2,"w") - # 计算拟åˆæ›²çº¿ä¸Šçš„点 - num_points = 1000 # 设置需è¦è®¡ç®—çš„ç‚¹çš„æ•°é‡ - fit_points = [] - for i in range(num_points): - x = 30 + i * (200 - 30) / num_points # 在x范围内å‡åŒ€é€‰å–点 - y = f2.Eval(x) # 计算拟åˆæ›²çº¿ä¸Šçš„点 - fit_points.append((x, y)) - - # 将拟åˆæ›²çº¿ä¸Šçš„点写入txt文件 - output_file = open("fit_curve_points{}.txt".format(input_name), "w") - for point in fit_points: - output_file.write(f"{point[0]} {point[1]}\n") - - output_file.close() - f2.SetLineColor(ROOT.kBlue) - - - charge_graph.SetLineColor(ROOT.kBlack) - charge_graph.SetMarkerStyle(20) # è®¾ç½®ç‚¹çš„æ ·å¼ä¸ºå®žå¿ƒåœ† - charge_graph.SetMarkerColor(ROOT.kBlack) # 设置点的颜色为黑色 - charge_graph.SetMinimum(0) # 设置y轴最å°å€¼ - charge_graph.SetMaximum(70) - graph = ROOT.TGraph() - graph.GetXaxis().SetLabelFont(42) # 设置xè½´æ ‡é¢˜çš„å—体 - graph.GetXaxis().SetLabelSize(0.04) # 设置xè½´æ ‡é¢˜çš„å—å· - graph.GetYaxis().SetLabelFont(42) # 设置yè½´æ ‡é¢˜çš„å—体 - graph.GetYaxis().SetLabelSize(0.04) - graph.GetXaxis().SetNdivisions(1010) # 设置x轴主刻度和次刻度的分割数 - graph.GetYaxis().SetNdivisions(1001) # 设置y轴主刻度和次刻度的分割数 # 设置yè½´æ ‡é¢˜çš„å—å· - graph.GetXaxis().SetTitle( 'Charge (fC)' ) - graph.GetYaxis().SetTitle( 'Counts (a.u.)' ) - graph.GetXaxis().SetTickLength(0.04) # 设置x轴刻度长度 - graph.GetYaxis().SetTickLength(0.04) # 设置y轴刻度长度 - graph.GetXaxis().CenterTitle() # å°†xè½´æ ‡é¢˜å±…ä¸ - graph.GetYaxis().CenterTitle() # å°†yè½´æ ‡é¢˜å±…ä¸ - charge_graph.Draw("E") - #f2.Draw("same") - latex = ROOT.TLatex() - latex.SetTextSize(0.04) - latex.SetTextAlign(13) - latex.DrawLatexNDC(0.2, 0.8, "MPV= %.2f" % (f2.GetParameter(0))) - latex.DrawLatexNDC(0.2, 0.7, "SL= %.2f" % (f2.GetParameter(1))) - #latex.DrawLatexNDC(0.2,0.4,"Charge=%.4f"%(integral_value)) - - - charge_con.append(f2.GetParameter(0)) - charge_err.append(f2.GetParameter(1)) - - c.Update() - - c.SaveAs("fit_alpha" + input_name + ".png") - canvas=ROOT.TCanvas("canvas","canvas",1500,1200) - print(charge_con) - - graph=ROOT.TGraphErrors() - for i,n in enumerate([100,150,200,250,300,350]): - graph.SetPointError(i,0,charge_err[i]) - graph.SetPoint(i,n,charge_con[i]) - mg=ROOT.TMultiGraph("mg","") - graph.SetMarkerStyle(20) # è®¾ç½®ç‚¹çš„æ ·å¼ä¸ºå®žå¿ƒåœ† - graph.SetMarkerColor(ROOT.kBlack) # 设置点的颜色为黑色 - graph.GetXaxis().SetLabelFont(42) # 设置xè½´æ ‡é¢˜çš„å—体 - graph.GetXaxis().SetLabelSize(0.04) # 设置xè½´æ ‡é¢˜çš„å—å· - graph.GetYaxis().SetLabelFont(42) # 设置yè½´æ ‡é¢˜çš„å—体 - graph.GetYaxis().SetLabelSize(0.04) # 设置yè½´æ ‡é¢˜çš„å—å· - graph.GetYaxis().SetTitle( 'Charge (fC)' ) - graph.GetXaxis().SetTitle( 'Reverse Bias Voltage (V)' ) - graph.GetXaxis().CenterTitle() # å°†xè½´æ ‡é¢˜å±…ä¸ - graph.GetYaxis().CenterTitle() # å°†yè½´æ ‡é¢˜å±…ä¸ - - graph.Draw("AP") - data=pandas.read_csv("./raser/draw/fit.csv") - x = abs(data['X'].values) - y = abs(data['Y'].values) - fit_graph=ROOT.TGraph() - for i ,n in enumerate(x): - fit_graph.SetPoint(i,n,y[i]) - #fit_graph.SetLineStyle(2) - fit_graph.SetMarkerStyle(20) # è®¾ç½®ç‚¹çš„æ ·å¼ä¸ºå®žå¿ƒåœ† - fit_graph.SetMarkerColor(ROOT.kRed) # 设置点的颜色为黑色 - fit_graph.GetXaxis().SetLabelFont(42) # 设置xè½´æ ‡é¢˜çš„å—体 - fit_graph.GetXaxis().SetLabelSize(0.04) # 设置xè½´æ ‡é¢˜çš„å—å· - fit_graph.GetYaxis().SetLabelFont(42) # 设置yè½´æ ‡é¢˜çš„å—体 - fit_graph.GetYaxis().SetLabelSize(0.04) # 设置yè½´æ ‡é¢˜çš„å—å· - fit_graph.GetYaxis().SetTitle( 'Charge (fC)' ) - fit_graph.GetXaxis().SetTitle( 'Reverse Bias Voltage (V)' ) - fit_graph.GetXaxis().CenterTitle() # å°†xè½´æ ‡é¢˜å±…ä¸ - fit_graph.GetYaxis().CenterTitle() - fit_graph.Draw("AP") - - mg.Add(graph) - mg.Add(fit_graph) - mg.Draw("AP") - canvas.SaveAs("charge_alpha.root") - canvas.SaveAs("charge_alpha.png") - diff --git a/draw/draw_iv_cv_paper4.py b/draw/draw_iv_cv_paper4.py deleted file mode 100644 index d1754d4a9250d1fb3e7ab27dc09c5d6b724121aa..0000000000000000000000000000000000000000 --- a/draw/draw_iv_cv_paper4.py +++ /dev/null @@ -1,124 +0,0 @@ -#!/usr/bin/env python -import numpy as np -import ROOT - -def draw_double_iv(path1, path2, start): - data1=np.loadtxt(path1, skiprows=start-1, comments="END") - v1=-data1.T[0] - i1=-data1.T[1] - data2=np.loadtxt(path2, skiprows=start-1, comments="END") - v2=-data2.T[0] - i2=-data2.T[1] - - c = ROOT.TCanvas('c', '', 800, 600) - c.SetFillColor(0) - c.SetFrameFillColor(0) - ROOT.gStyle.SetPadColor(0) - ROOT.gStyle.SetCanvasColor(0) - ROOT.gStyle.SetOptStat(0) - c.SetLeftMargin(0.15) - c.SetBottomMargin(0.15) - - c.SetLogy() - - mg=ROOT.TMultiGraph("mg","") - n1=len(v1) - graph1 = ROOT.TGraph(n1,v1,i1) - n2=len(v2) - graph2 = ROOT.TGraph(n2,v2,i2) - - graph1.SetLineColor(4) - graph2.SetLineColor(6) - graph1.SetMarkerColor(4) - graph2.SetMarkerColor(6) - graph1.SetMarkerStyle(20) - graph2.SetMarkerStyle(22) - - mg.Add(graph1) - mg.Add(graph2) - mg.Draw('apl') - mg.SetMinimum(7e-10) - mg.SetMaximum(1.5e-4) - - mg.GetYaxis().SetTitle('Current [A]') - mg.GetXaxis().SetTitle('Reverse Bias Voltage [V]') - mg.GetYaxis().SetLabelSize(0.05) - mg.GetYaxis().SetTitleSize(0.05) - mg.GetXaxis().SetLabelSize(0.05) - mg.GetXaxis().SetTitleSize(0.05) - - legend = ROOT.TLegend(0.2, 0.6, 0.4, 0.75) - legend.AddEntry(graph1, "p-i-n", "pl") - legend.AddEntry(graph2, "LGAD", "pl") - legend.SetTextSize(27) - legend.SetTextFont(43) - - legend.SetBorderSize(0) - legend.SetFillColor(0) - legend.Draw() - - c.SaveAs("output/iv_comparison.pdf") - - -def draw_double_cv(path1, path2, start): - data1=np.loadtxt(path1, skiprows=start-1, comments="END") - v1=-data1.T[0] - c1=data1.T[1] - data2=np.loadtxt(path2, skiprows=start-1, comments="END") - v2=-data2.T[0] - c2=data2.T[1] - - c = ROOT.TCanvas('c', '', 800, 600) - c.SetFillColor(0) - c.SetFrameFillColor(0) - ROOT.gStyle.SetPadColor(0) - ROOT.gStyle.SetCanvasColor(0) - ROOT.gStyle.SetOptStat(0) - c.SetLeftMargin(0.15) - c.SetBottomMargin(0.15) - - - mg=ROOT.TMultiGraph("mg","") - n1=len(v1) - graph1 = ROOT.TGraph(n1,v1,c1**(-2)) - n2=len(v2) - graph2 = ROOT.TGraph(n2,v2,c2**(-2)) - - graph1.SetLineColor(4) - graph2.SetLineColor(6) - graph1.SetMarkerColor(4) - graph2.SetMarkerColor(6) - graph1.SetMarkerStyle(20) - graph2.SetMarkerStyle(22) - - mg.Add(graph1) - mg.Add(graph2) - mg.Draw('apl') - - mg.GetYaxis().SetTitle('Capacitance^{-2} [F^{-2}]') - mg.GetXaxis().SetTitle('Reverse Bias Voltage [V]') - mg.GetYaxis().SetLabelSize(0.05) - mg.GetYaxis().SetTitleSize(0.05) - mg.GetXaxis().SetLabelSize(0.05) - mg.GetXaxis().SetTitleSize(0.05) - - legend = ROOT.TLegend(0.6, 0.2, 0.8, 0.35) - legend.AddEntry(graph1, "p-i-n", "pl") - legend.AddEntry(graph2, "LGAD", "pl") - legend.SetTextSize(27) - legend.SetTextFont(43) - - legend.SetBorderSize(0) - legend.SetFillColor(0) - legend.Draw() - - c.SaveAs("output/cv_comparison.pdf") - -pin_iv = '/afs/ihep.ac.cn/users/f/fuchenxi/disk/1/hpk_ivcv/HPK-EPI-W2-200-DS-SE5PINNM-01/HPK-EPI-W2-200-DS-SE5PINNM-01_2019-09-03_1.iv' -pin_cv = '/afs/ihep.ac.cn/users/f/fuchenxi/disk/1/hpk_ivcv/HPK-EPI-W2-200-DS-SE5PINNM-01/HPK-EPI-W2-200-DS-SE5PINNM-01_2019-09-03_1.cv' -lgad_iv = '/afs/ihep.ac.cn/users/f/fuchenxi/disk/1/hpk_ivcv/HPK-EPI-W2-200-DS-SE5-01/HPK-EPI-W2-200-DS-SE5-01_2019-08-26_1.iv' -lgad_cv = '/afs/ihep.ac.cn/users/f/fuchenxi/disk/1/hpk_ivcv/HPK-EPI-W2-200-DS-SE5-01/HPK-EPI-W2-200-DS-SE5-01_2019-08-28_1.cv' -iv_start = 66 -cv_start = 71 -draw_double_iv(pin_iv, lgad_iv, iv_start) -draw_double_cv(pin_cv, lgad_cv, cv_start) \ No newline at end of file diff --git a/draw/draw_iv_cv_paper9.py b/draw/draw_iv_cv_paper9.py deleted file mode 100644 index 29b3865f302e0959b60fcdb6777b254df93fab53..0000000000000000000000000000000000000000 --- a/draw/draw_iv_cv_paper9.py +++ /dev/null @@ -1,234 +0,0 @@ -#!/usr/bin/env python -import ROOT -import csv -import os -from array import array -import numpy as np -from scipy.optimize import curve_fit -# 读å–CSV文件 -def read_csv(csv_filename): - data = [] - with open(csv_filename, 'r') as csvfile: - csvreader = csv.reader(csvfile) - next(csvreader) # 跳过表头 - for row in csvreader: - if csv_filename.endswith("cv.csv"): - if row: # 检查是å¦å˜åœ¨æ•°æ® - x_value = float(row[0]) if row[0] else 0.0 - y_value = float(row[2]) if row[2] else 0.0 - data.append((x_value, y_value)) - elif csv_filename.endswith("iv.csv"): - if row: # 检查是å¦å˜åœ¨æ•°æ® - x_value = float(row[0]) if row[0] else 0.0 - y_value = float(row[1]) if row[1] else 0.0 - data.append((x_value, y_value)) - elif csv_filename.endswith("other.csv"): - if row: # 检查是å¦å˜åœ¨æ•°æ® - x_value = float(row[0]) if row[0] else 0.0 - y_value = float(row[1]) if row[1] else 0.0 - data.append((x_value, y_value)) - - return data - -# 创建ROOT文件并å˜å‚¨æ•°æ® -def create_root_file(csv_filename, root_filename): - data = read_csv(csv_filename) - - # 创建ROOT文件 - root_file = ROOT.TFile(root_filename, "RECREATE") - - # 创建TTree对象 - tree = ROOT.TTree("data_tree", "Data from CSV") - x = ROOT.std.vector('double')() - y = ROOT.std.vector('double')() - tree.Branch("x", x) - tree.Branch("y", y) - - for i, (x_val, y_val) in enumerate(data): - x.push_back(x_val) - y.push_back(y_val) - tree.Fill() - - # å°†TTree对象写入ROOT文件 - tree.Write() - root_file.Close() - - -def draw_iv_p9(): - # 创建一个Canvas - c = ROOT.TCanvas('c', '', 800, 600) - c.SetFillColor(0) - c.SetFrameFillColor(0) - ROOT.gStyle.SetPadColor(0) - ROOT.gStyle.SetCanvasColor(0) - ROOT.gStyle.SetOptStat(0) - c.SetLeftMargin(0.15) - c.SetBottomMargin(0.15) - c.SetLogy() - # é历文件夹 - folder_path = "/publicfs/atlas/atlasnew/silicondet/itk/raser/zhaosen/samples/" # 文件夹路径 - colors = [ROOT.kGreen, ROOT.kRed, ROOT.kTeal, ROOT.kYellow, ROOT.kMagenta] # 定义ä¸åŒçš„颜色 - mg=ROOT.TMultiGraph("mg","") - legend = ROOT.TLegend(0.6, 0.2, 0.8, 0.4) - legend.SetBorderSize(0) # 设置图例的边框大å°ä¸º0,å³æ²¡æœ‰è¾¹æ¡† - for i,file_name in enumerate(os.listdir(folder_path)): - if file_name.endswith("iv.root"): # 如果文件å以"iv.root"结尾 - file_number = int(''.join(filter(str.isdigit, file_name))) - color_index = file_number - 1 - root_file = ROOT.TFile(os.path.join(folder_path, file_name)) - tree = root_file.Get("data_tree") # 获å–Treeå称 - n_entries = tree.GetEntries() - x_data = array('d', [0]*n_entries) # 创建一个数组æ¥å˜å‚¨x值 - y_data = array('d', [0]*n_entries) - - ex_data = array('d',[0]*n_entries) # 创建一个数组æ¥å˜å‚¨x误差 - ey_data = array('d',[0]*n_entries) # 创建一个数组æ¥å˜å‚¨y误差 # 创建一个数组æ¥å˜å‚¨y值 - for n in range(n_entries): - tree.GetEntry(n) - for i, x in enumerate(tree.x): - if 0 <= abs(x) <= 400: # ä»…æ·»åŠ 0 到 400 之间的 x 值åŠå¯¹åº”çš„ y 值 - x_data.append(abs(x)) - ex_data.append(0) - y_data.append(abs(tree.y[i]/(3.14*0.05*0.05))) - ey_data.append(0) - #print(x_data,y_data) - #graph = ROOT.TGraphErrors(len(x_data), array('d', x_data), array('d', y_data),ex_data,ey_data) # 创建TGraph对象 - graph = ROOT.TGraph(len(x_data), array('d', x_data), array('d', y_data)) # 创建TGraph对象 - graph.SetMarkerStyle(20) # è®¾ç½®æ ‡è®°å½¢çŠ¶ - graph.SetMarkerSize(0.5) - - graph.SetMarkerColor(colors[color_index]) - mg.Add(graph) # æ·»åŠ åˆ°TMultiGraphä¸ - legend.AddEntry(graph, file_name.split("_iv")[0], "p") - - - mg.GetYaxis().SetTitle('Current Density [A/cm^2]') - mg.GetXaxis().SetTitle('Reverse Bias Voltage [V]') - mg.GetYaxis().SetLabelSize(0.05) - mg.GetYaxis().SetTitleSize(0.05) - mg.GetYaxis().CenterTitle(True) - mg.GetXaxis().SetLabelSize(0.05) - mg.GetXaxis().SetTitleSize(0.05) - mg.GetXaxis().CenterTitle(True) - mg.SetMinimum(1e-11) - mg.SetMaximum(1e-2) - mg.Draw('AP') - legend.Draw() - #c.Update() - - c.SaveAs("/publicfs/atlas/atlasnew/silicondet/itk/raser/zhaosen/samples/output/iv_comparison.root") - c.SaveAs("/publicfs/atlas/atlasnew/silicondet/itk/raser/zhaosen/samples/output/iv_comparison.pdf") - #c.SaveAs("./iv_comparison.root") - #c.SaveAs("./iv_comparison.pdf") - - -def draw_cv_p9(): - # 创建一个Canvas - c = ROOT.TCanvas('c', '', 1200, 600) # 调整画布大å°ä»¥å®¹çº³ä¸¤ä¸ªå图 - #c.Divide(2, 1) # 将画布分割æˆä¸¤åˆ— - c.SetFillColor(0) - c.SetFrameFillColor(0) - ROOT.gStyle.SetPadColor(0) - ROOT.gStyle.SetCanvasColor(0) - ROOT.gStyle.SetOptStat(0) - c.SetLeftMargin(0.15) - c.SetBottomMargin(0.15) - c.SetLogy() - #c.cd(1) - # é历文件夹 - folder_path = "/publicfs/atlas/atlasnew/silicondet/itk/raser/zhaosen/samples" # 文件夹路径 - mg = ROOT.TMultiGraph("mg", "") - legend = ROOT.TLegend(0.6, 0.6, 0.8, 0.8) - legend.SetBorderSize(0) # 设置图例的边框大å°ä¸º0,å³æ²¡æœ‰è¾¹æ¡† - colors = [ROOT.kGreen, ROOT.kRed, ROOT.kPink, ROOT.kCyan, ROOT.kOrange] # 定义ä¸åŒçš„颜色 - for i, file_name in enumerate(os.listdir(folder_path)): - if file_name.endswith("cv.root"): # 如果文件å以"cv.root"结尾 - file_number = int(''.join(filter(str.isdigit, file_name))) - color_index = file_number - 1 - root_file = ROOT.TFile(os.path.join(folder_path, file_name)) - tree = root_file.Get("data_tree") # 获å–Treeå称 - n_entries = tree.GetEntries() - x_data = array('d', [0] * n_entries) # 创建一个数组æ¥å˜å‚¨x值 - y_data = array('d', [0] * n_entries) - ex_data = array('d', [0] * n_entries) # 创建一个数组æ¥å˜å‚¨x误差 - ey_data = array('d', [0] * n_entries) # 创建一个数组æ¥å˜å‚¨y误差 # 创建一个数组æ¥å˜å‚¨y值 - for n in range(n_entries): - tree.GetEntry(n) - for i, x in enumerate(tree.x): - if 0 <= abs(x) <= 400: # ä»…æ·»åŠ 0 到 400 之间的 x 值åŠå¯¹åº”çš„ y 值 - x_data.append(abs(x)) - ex_data.append(0) - y_data.append(abs(tree.y[i])) - ey_data.append(0) - graph = ROOT.TGraph(len(x_data), array('d', x_data), array('d', y_data)) # 创建TGraphErrors对象 - graph.SetMarkerStyle(20) - graph.SetMarkerColor(colors[color_index]) # è®¾ç½®æ ‡è®°é¢œè‰²ï¼Œä½¿ç”¨å–ä½™è¿ç®—é‡å¤ä½¿ç”¨é¢œè‰² - #graph.SetLineColor(colors[i % len(colors)]) - graph.SetMarkerSize(0.5) - mg.Add(graph) # æ·»åŠ åˆ°TMultiGraphä¸ - - legend.AddEntry(graph, file_name.split("_cv")[0], "p") - - - mg.GetYaxis().SetTitle('Capacitance [pF]') - mg.GetXaxis().SetTitle('Reverse Bias Voltage [V]') - mg.GetYaxis().SetLabelSize(0.05) - mg.GetYaxis().SetTitleSize(0.05) - mg.GetYaxis().CenterTitle(True) - mg.GetXaxis().SetLabelSize(0.05) - mg.GetXaxis().SetTitleSize(0.05) - mg.GetXaxis().CenterTitle(True) - mg.SetMinimum(1e0) - mg.SetMaximum(1e3) - mg.Draw('P') - legend.Draw("same") - - """ - c.cd(2) - fig2_files="/publicfs/atlas/atlasnew/silicondet/itk/raser/zhaosen/simulation_cv" - mg=ROOT.TMultiGraph("mg","") - legend=ROOT.TLegend(0.6,0.6,0.8,0.8) - legend.SetBorderSize(0) - for file_name in os.listdir(fig2_files): - if file_name.endswith("cv_other.root"): - root_file = ROOT.TFile(os.path.join(folder_path, file_name)) - tree=root_file.Get("data_tree") - n_entries=tree.GetEntries() - x_data = array('d', [0] * n_entries) # 创建一个数组æ¥å˜å‚¨x值 - y_data = array('d', [0] * n_entries) - for n in range(n_entries): - tree.GetEntry(n) - for i,x in enumerate(tree.x): - if 0<x<=400: - x_data.append(abs(x)) - y_data.append(abs(tree.y[i])) - print(x_data) - graph=ROOT.TGraph(len(x_data),array("d",x_data),array("d",y_data)) - graph.SetMarkerStyle(20) - graph.SetMarkerSize(0.5) - mg.Add(graph) # æ·»åŠ åˆ°TMultiGraphä¸ - legend.AddEntry(graph, file_name.split("_cv_other")[0], "p") - - mg.GetYaxis().SetTitle('Capacitance [pF]') - mg.GetXaxis().SetTitle('Reverse Bias Voltage [V]') - mg.GetYaxis().SetLabelSize(0.05) - mg.GetYaxis().SetTitleSize(0.05) - mg.GetYaxis().CenterTitle(True) - mg.GetXaxis().SetLabelSize(0.05) - mg.GetXaxis().SetTitleSize(0.05) - mg.GetXaxis().CenterTitle(True) - mg.SetMinimum(1e0) - mg.SetMaximum(1e3) - mg.Draw('P') - legend.Draw("same") - c.Update()""" - - c.SaveAs("/publicfs/atlas/atlasnew/silicondet/itk/raser/zhaosen/samples/output/cv_comparison.root") - c.SaveAs("/publicfs/atlas/atlasnew/silicondet/itk/raser/zhaosen/samples/output/cv_comparison.pdf") - - -def main(): - draw_cv_p9() - draw_iv_p9() - #test() - #print("fix cv") \ No newline at end of file diff --git a/draw/field_comparison.py b/draw/field_comparison.py deleted file mode 100644 index bd7ca63459a939aade1da083fbab4683c6d501b9..0000000000000000000000000000000000000000 --- a/draw/field_comparison.py +++ /dev/null @@ -1,152 +0,0 @@ -#!/usr/bin/env python3 -# -*- encoding: utf-8 -*- -''' -@Description: compare the difference of the electric field of p-i-n and LGAD -@Date : 2023/02/14 17:00:00 -@Author : Chenxi Fu -@version : 1.0 - -Usage : -source ./run raser -raser 'python/paper4/field_comparison.py' -''' - -# TODO: Need to be rewritten or deleted! - -import sys -import os -sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) -import raser -import time -import ROOT -import math - -def draw_fields(my_pin_field,my_lgad_field,path): - - c1 = ROOT.TCanvas("c", "canvas",1200, 1000) - ROOT.gStyle.SetOptStat(ROOT.kFALSE) - ROOT.gStyle.SetOptFit() - c1.SetLeftMargin(0.18) - c1.SetBottomMargin(0.14) - - n = 2000 - lgad_field_histo = ROOT.TH1F("","",n,0,50) - lgad_field_histo.GetXaxis().SetTitle("z[\mu m]") - lgad_field_histo.GetYaxis().SetTitle("E[V/\mu m]") - pin_field_histo = ROOT.TH1F("","",n,0,50) - pin_field_histo.GetXaxis().SetTitle("z[\mu m]") - pin_field_histo.GetYaxis().SetTitle("E[V/\mu m]") - - for i in range(n): - z = (i+1)*50/n - le = my_lgad_field.get_e_field(650,650,z-0.01)[2] - lgad_field_histo.SetBinContent(i+1,le) - pe = my_pin_field.get_e_field(650,650,z-0.01)[2] - pin_field_histo.SetBinContent(i+1,pe) - - lgad_field_histo.SetTitle("") - lgad_field_histo.SetLineColor(6) - lgad_field_histo.SetMarkerColor(6) - lgad_field_histo.SetMarkerStyle(20) - lgad_field_histo.Draw("HIST") - lgad_field_histo.Draw("SAME P") - pin_field_histo.SetLineColor(4) - pin_field_histo.SetMarkerColor(4) - pin_field_histo.SetMarkerStyle(22) - pin_field_histo.Draw("SAME HIST") - pin_field_histo.Draw("SAME P") - - lgad_field_histo.GetXaxis().SetTitleSize(0.05) - lgad_field_histo.GetXaxis().SetLabelSize(0.05) - lgad_field_histo.GetYaxis().SetTitleSize(0.05) - lgad_field_histo.GetYaxis().SetLabelSize(0.05) - - legend = ROOT.TLegend(0.5, 0.6, 0.8, 0.8) - legend.AddEntry(pin_field_histo, "p-i-n", "pl") - legend.AddEntry(lgad_field_histo, "LGAD", "pl") - legend.SetTextSize(0.05) - legend.SetBorderSize(0) - legend.Draw("same") - - c1.SaveAs(path+"field_comparison"+".pdf") - c1.SaveAs(path+"field_comparison"+".root") - -def draw_sigma(field,path): - n = 100 - E = ROOT.TH1F("","",n,0,50) - E.GetXaxis().SetTitle("z[\mu m]") - E.GetYaxis().SetTitle("E[V/\mu m]") - - S = ROOT.TH1F("","",n,0,50) - S.GetXaxis().SetTitle("z[\mu m]") - S.GetYaxis().SetTitle("\sigma^{-2}[\mu m^{-2}]") - - e_2 = field.get_e_field(650,650,2)[2] - for i in range(n): - z = (i+1)*50/n - e = field.get_e_field(650,650,z-0.01)[2] - if z<2: - s=0 - else: - s = 1/(450 + 49 + 2.8*(1+2*math.log(e_2/e))**2) # temporal_FWHM^2 v^2 + sigma_0^2 + (k_{B}Tε/q^2N_{eff})(1+2ln(E_2/E)^2) - E.SetBinContent(i+1,e) - S.SetBinContent(i+1,s) - - c1 = ROOT.TCanvas("c", "canvas",1000, 1000) - ROOT.gStyle.SetOptStat(ROOT.kFALSE) - ROOT.gStyle.SetOptFit() - c1.SetLeftMargin(0.18) - c1.SetRightMargin(0.2) - c1.SetBottomMargin(0.14) - c1.SetRightMargin(0.12) - - E.Draw("COLZ") - E.GetXaxis().SetTitleSize(0.05) - E.GetXaxis().SetLabelSize(0.05) - E.GetYaxis().SetTitleSize(0.05) - E.GetYaxis().SetLabelSize(0.05) - E.SetLineWidth(2) - E.SetTitle("") - c1.SaveAs(path+"Field.pdf") - c1.SaveAs(path+"Field.root") - del c1 - - c2 = ROOT.TCanvas("c", "canvas",1000, 1000) - ROOT.gStyle.SetOptStat(ROOT.kFALSE) - ROOT.gStyle.SetOptFit() - c2.SetLeftMargin(0.18) - c2.SetRightMargin(0.2) - c2.SetBottomMargin(0.14) - c2.SetRightMargin(0.12) - - S.Draw("COLZ") - S.GetXaxis().SetTitleSize(0.05) - S.GetXaxis().SetLabelSize(0.05) - S.GetYaxis().SetTitleSize(0.05) - S.GetYaxis().SetLabelSize(0.05) - S.SetLineWidth(2) - S.SetTitle("") - c2.SaveAs(path+"Sigma.pdf") - c2.SaveAs(path+"Sigma.root") - del c2 - -def main(): - path = "output/lgadtct/HPK-Si-LGAD/" - if not os.access(path, os.F_OK): - os.makedirs(path, exist_ok=True) - - pin_paras = ["det_name=HPK-Si-PIN","parfile=paras/setting.json"] - pin_set = raser.Setting(pin_paras) - my_pin = raser.R3dDetector(pin_set) - my_pin_field = raser.FenicsCal(my_pin,pin_set.fenics) - - lgad_paras = ["det_name=HPK-Si-LGAD","parfile=paras/setting.json"] - lgad_set = raser.Setting(lgad_paras) - my_lgad = raser.R3dDetector(lgad_set) - my_lgad_field = raser.FenicsCal(my_lgad,lgad_set.fenics) - - draw_fields(my_pin_field,my_lgad_field,path) - draw_sigma(my_lgad_field,path) - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/draw/iv.py b/draw/iv.py deleted file mode 100644 index fb5783884afd319be7f41498d05bf806f15b9d68..0000000000000000000000000000000000000000 --- a/draw/iv.py +++ /dev/null @@ -1,90 +0,0 @@ -import os -import ROOT - -def draw_iv(input_dir, output_dir, label): - com_name = [] - legend_name = [] - - for file in os.listdir(input_dir): - if file.endswith('.root'): - com_name.append(file) - - c_i = ROOT.TCanvas("c_i", "c_i", 800, 800) - c_i.SetLeftMargin(0.22) - c_i.SetBottomMargin(0.16) - c_i.SetGrid() - c_i.SetFrameLineWidth(5) - multigraphs_i = ROOT.TMultiGraph() - - for i in range(len(com_name)): - name = com_name[i] - if label == 'sicar1.1.8' and not name.startswith('sicar1.1.8'): - continue - elif label == 'sicar1.1.8-1,sicar1.1.8-2_iv' and not (name.startswith('sicar1.1.8-1_')) and not (name.startswith('sicar1.1.8-2_')): - continue - - name = name.split('.root')[0] - - input_file = os.path.join(input_dir, name + '.root') - - if name.endswith('iv'): - file = ROOT.TFile(input_file, "READ") - tree = file.Get("myTree") - graph1 = ROOT.TGraph() - legend_name.append(name.split('_')[0]) - for i, event in enumerate(tree): - x = event.Value - x = abs(x) - y = event.Reading - y = abs(y) - graph1.SetPoint(i, x, y) - - graph1.SetNameTitle("") - graph1.SetMarkerColor(0+i) - graph1.SetMarkerStyle(24) - graph1.SetMarkerSize(1) - multigraphs_i.Add(graph1) - - multigraphs_i.GetXaxis().SetTitle("Reverse Bias Voltage [V]") - multigraphs_i.GetXaxis().SetLimits(0,510) - multigraphs_i.GetXaxis().CenterTitle() - multigraphs_i.GetXaxis().SetTitleOffset(1.4) - multigraphs_i.GetXaxis().SetTitleSize(0.05) - multigraphs_i.GetXaxis().SetLabelSize(0.05) - multigraphs_i.GetXaxis().SetNdivisions(505) - multigraphs_i.GetYaxis().SetLimits(1e-11,1e-5) - multigraphs_i.GetYaxis().SetTitle("Current [A]") - multigraphs_i.GetYaxis().CenterTitle() - multigraphs_i.GetYaxis().SetTitleOffset(1.8) - multigraphs_i.GetYaxis().SetTitleSize(0.05) - multigraphs_i.GetYaxis().SetLabelSize(0.05) - multigraphs_i.Draw("AP") - - max_i = len(legend_name) - 1 - legend_i = ROOT.TLegend(0.52,0.82-0.05*float(max_i),0.87,0.85) - legend_i.SetTextSize(0.04) - - for i, graph1 in enumerate(multigraphs_i): - legend_i.AddEntry(graph1, legend_name[i]) - - legend_i.Draw() - - file_name_i = label + "_iv.root" - c_i.SaveAs(os.path.join(output_dir, file_name_i)) - file_name_i = label + "_iv.pdf" - c_i.SaveAs(os.path.join(output_dir, file_name_i)) - file_name_i = label + "_iv.png" - c_i.SaveAs(os.path.join(output_dir, file_name_i)) - -def main(label): - if label=='itk_md8_compare_dataandsim': - input_dir = '/publicfs/atlas/atlasnew/silicondet/itk/raser/lizhan/itkmd8/comparison' - output_dir = '/afs/ihep.ac.cn/users/l/lizhan/disk/scrathfs/raser/output/fig' - else: - input_dir = '/publicfs/atlas/atlasnew/silicondet/itk/raser/wangkeqi/sicar1.1.8' - output_dir = '/afs/ihep.ac.cn/users/w/wangkeqi/raser/output/fig' - - draw_iv(input_dir, output_dir, label) - -if __name__ == "__main__": - main() diff --git a/elec/ABCStar_fe_get_fig.py b/elec/ABCStar_fe_get_fig.py new file mode 100755 index 0000000000000000000000000000000000000000..dc634321bbdc4b3991e23cdf5f7872fffbad0a88 --- /dev/null +++ b/elec/ABCStar_fe_get_fig.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python3 +# TODO: Need to be TOTALLY rewritten +import ROOT +import numpy + +def read_file(file_path,file_name): + with open(file_path + file_name) as f: + lines = f.readlines() + time,volt = [],[] + + for line in lines: + time.append(float(line.split()[0])*1e9) + volt.append(float(line.split()[1])) + + time = numpy.array(time,dtype='float64') + volt = numpy.array(volt,dtype='float64') + + return time,volt + +def main(): + file_path = 'output/elec/' + #file_name = 'drs4_analog.raw' + file_name = 'ABCStar_fe.raw' + com_name=file_name.split('.')[0] + fig_name=file_path + com_name + '.pdf' + time,volt = [],[] + + time,volt = read_file(file_path,file_name) + length = len(time) + + ROOT.gROOT.SetBatch() + c = ROOT.TCanvas('c','c',700,600) + f1 = ROOT.TGraph(length,time,volt) + f1.SetTitle(' ') + + f1.SetLineColor(2) + f1.SetLineWidth(2) + + f1.GetXaxis().SetTitle('Time [ns]') + # f1.GetXaxis().SetLimits(0,5) + f1.GetXaxis().SetLimits(0,30) + f1.GetXaxis().CenterTitle() + f1.GetXaxis().SetTitleSize(0.05) + f1.GetXaxis().SetTitleOffset(0.8) + + f1.GetYaxis().SetTitle('Voltage [V]') + f1.GetYaxis().SetLimits(0,-1) + f1.GetYaxis().CenterTitle() + f1.GetYaxis().SetTitleSize(0.05) + f1.GetYaxis().SetTitleOffset(0.93) + + c.cd() + f1.Draw('AL') + c.SaveAs(fig_name) + print("figure has been saved in " , fig_name) + +if __name__ == '__main__': + main() + diff --git a/elec/__init__.py b/elec/__init__.py index d739f8f0f1e7023f5f18d988e16eb4003da1ad22..3d9a1d6550ec630d49e63fd2fffe7f561c9af2f1 100644 --- a/elec/__init__.py +++ b/elec/__init__.py @@ -1,20 +1,22 @@ -from . import * + def main(kwargs): label = kwargs['label'] - if label == 'foo': - foo.main() if label == 'ngspice_t1': import subprocess - subprocess.run(['ngspice -b -r t1.raw output/T1_tmp.cir'], shell=True) - if label == 'drs4_get_analog': + subprocess.run(['ngspice -b output/elec/T1_tmp.cir'], shell=True) + elif label == 'ngspice_ABCStar_fe': + import subprocess + subprocess.run(['ngspice -b param_file/circuit/ABCStar_fe.cir'], shell=True) + elif label == 'drs4_get_analog': import subprocess - subprocess.run(['ngspice -b -r drs4_analog.raw paras/circuitdrs4_analog.cir'], shell=True) - if label == 'drs4_get_fig': + subprocess.run(['ngspice -b param_file/circuit/drs4_analog.cir'], shell=True) + elif label == 'drs4_get_fig': from . import drs4_get_fig drs4_get_fig.main() - if label == 'HPK-Si-LGAD-CCE': - from . import cce_alpha - cce_alpha.main() + elif label == 'ABCStar_fe_get_fig': + from . import ABCStar_fe_get_fig + ABCStar_fe_get_fig.main() else: - raise NameError(label) \ No newline at end of file + from . import readout + readout.main(label) diff --git a/elec/draw_t1.py b/elec/draw_t1.py index aee027e00140f549bd155840d3305c2c7c42ab0c..f8fc36421a0e9ff28f60453014e1bc291cbd93d0 100644 --- a/elec/draw_t1.py +++ b/elec/draw_t1.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -*- encoding: utf-8 -*- - +# TODO: Need to be TOTALLY rewritten import time import os from array import array @@ -87,9 +87,9 @@ def T1(): legend.Draw("") now = time.strftime("%Y_%m%d_%H%M%S") - path = os.path.join("output/fig", str(now)) + path = os.path.join("output/elec/t1", str(now)) os.makedirs(path) - c.SaveAs(os.path.join('output/fig', str(now), 't1.pdf')) + c.SaveAs(os.path.join('output/elec/t1', str(now), 't1.pdf')) if __name__ == '__main__': T1() \ No newline at end of file diff --git a/elec/drs4_get_fig.py b/elec/drs4_get_fig.py index 3597377d618e4f64f02cbce4b5e8a7baea7307da..a27c8917101fd1de35daaeaf8308a2a1d08b5765 100755 --- a/elec/drs4_get_fig.py +++ b/elec/drs4_get_fig.py @@ -1,10 +1,10 @@ #!/usr/bin/env python3 - +# TODO: Need to be TOTALLY rewritten import ROOT import numpy def read_file(file_path,file_name): - with open(file_path + '/' + file_name) as f: + with open(file_path + file_name) as f: lines = f.readlines() time,volt = [],[] @@ -18,7 +18,7 @@ def read_file(file_path,file_name): return time,volt def main(): - file_path = 'fig/' + file_path = 'output/elec/' file_name = 'drs4_analog.raw' com_name=file_name.split('.')[0] fig_name=file_path + com_name + '.pdf' diff --git a/elec/ele_readout.py b/elec/ele_readout.py deleted file mode 100644 index b43712752bd3103939cd6a44b301a04e79fb9f8f..0000000000000000000000000000000000000000 --- a/elec/ele_readout.py +++ /dev/null @@ -1,264 +0,0 @@ -# -*- encoding: utf-8 -*- -''' -Description: - Simulate induced current through BB or CSA amplifier -@Date : 2021/09/02 14:11:57 -@Author : tanyuhang -@version : 1.0 -''' - -import math -import ROOT - -import json - -# TODO: Need to be TOTALLY rewritten - -# CSA and BB amplifier simulation -class Amplifier: - def __init__(self,my_current,amplifier,mintstep="50e-12"): - """ - Description: - Get current after CSA and BB amplifier - Parameters: - --------- - CSA_par : dic - All input paramters of CSA in CSA_par - BB_par : dic - All input paramters of BB in CSA_par - mintstep : float - The readout time step (bin width) - @Modify: - --------- - 2021/09/09 - """ - self.ele = [] - - ele_json = "./setting/electronics/" + amplifier + ".json" - with open(ele_json) as f: - ampl_par = json.load(f) - - self.ele_name = ampl_par['ele_name'] - self.read_ele_num = my_current.read_ele_num - self.ampli_define(ampl_par) - self.sampling_charge(my_current,mintstep) - self.ampl_sim() - - def ampli_define(self,ampl_par): - """ - Description: - The parameters of CSA and BB amplifier. - Details introduction can be got in setting module. - @Modify: - --------- - 2021/09/09 - """ - if ampl_par['ele_name'] == 'CSA': - self.t_rise = ampl_par['t_rise'] - self.t_fall = ampl_par['t_fall'] - self.trans_imp = ampl_par['trans_imp'] - self.CDet = ampl_par['CDet'] - self.BBW = ampl_par['BBW'] - self.BBGain = ampl_par['BBGain'] - self.BB_imp = ampl_par['BB_imp'] - self.OscBW = ampl_par['OscBW'] - - tau_BB_RC = 1.0e-12*self.BB_imp*self.CDet #BB RC - tau_BB_BW = 0.35/(1.0e9*self.BBW)/2.2 #BB Tau - - self.tau_BBA = math.sqrt(pow(tau_BB_RC,2)+pow(tau_BB_BW,2)) - - elif ampl_par['ele_name'] == 'BB': - self.t_rise = ampl_par['t_rise'] - self.t_fall = ampl_par['t_fall'] - self.CDet = ampl_par['CDet'] - self.BBW = ampl_par['BBW'] - self.BBGain = ampl_par['BBGain'] - self.BB_imp = ampl_par['BB_imp'] - self.OscBW = ampl_par['OscBW'] - ##BB simualtion parameter - tau_C50 = 1.0e-12*50.*self.CDet #Oscil. RC - tau_BW = 0.35/(1.0e9*self.OscBW)/2.2 #Oscil. RC - tau_BB_RC = 1.0e-12*self.BB_imp*self.CDet #BB RC - tau_BB_BW = 0.35/(1.0e9*self.BBW)/2.2 #BB Tau - self.tau_scope = math.sqrt(pow(tau_C50,2)+pow(tau_BW,2)) - self.tau_BBA = math.sqrt(pow(tau_BB_RC,2)+pow(tau_BB_BW,2)) - - def sampling_charge(self,my_current,mintstep): - """ Transform current to charge - with changing bin width to oscilloscope bin width - """ - self.max_num=[] - self.itot=[] - for i in range(self.read_ele_num): - self.max_num.append(my_current.sum_cu[i].GetNbinsX()) - self.itot.append([0.0]*self.max_num[i]) - - self.max_hist_num = my_current.n_bin - self.undersampling = int(float(mintstep)/my_current.t_bin) - self.time_unit = my_current.t_bin*self.undersampling - self.CDet_j = 0 # CSA readout mode - - self.qtot = [0.0]*self.read_ele_num - # self.qtot = [0.0] - # get total charge - for k in range(self.read_ele_num): - i=0 - for j in range(0,self.max_hist_num,self.undersampling): - self.itot[k][i] = my_current.sum_cu[k].GetBinContent(j) - self.qtot[k] = self.qtot[k] + self.itot[k][i]*self.time_unit - i+=1 - max_hist_num = int(self.max_hist_num/self.undersampling) - IintTime = max(2.0*(self.t_rise+self.t_fall)*1e-9/self.time_unit, - 3.0*self.tau_BBA/self.time_unit) - self.IMaxSh = int(max_hist_num + IintTime) - - def ampl_sim(self): - """ - Description: - CSA and BB amplifier Simulation - Parameters: - --------- - arg1 : int - - @Modify: - --------- - 2021/09/09 - """ - IMaxSh = self.IMaxSh - preamp_Q = [] - for i in range(self.read_ele_num): - preamp_Q.append([0.0]*IMaxSh) - step=1 - - for k in range(self.read_ele_num): - for i in range(IMaxSh-step): - if(i>0 and i <self.max_hist_num-step): - preamp_Q[k][i] = 0.0 - for il in range(i,i+step): - preamp_Q[k][i] += self.itot[k][il]*self.time_unit - elif (i != 0): - preamp_Q[k][i]=0.0 - - if self.ele_name == 'CSA': - for k in range(self.read_ele_num): - self.CSA_p_init() - for i in range(IMaxSh-step): - if i >= step: - dif_shaper_Q = preamp_Q[k][i] - else: - dif_shaper_Q = 0 - for j in range(IMaxSh-i): - self.fill_CSA_out(i,j,dif_shaper_Q) - self.max_CSA(i) - self.fill_CSA_th1f(k) - - elif self.ele_name == 'BB': - for k in range(self.read_ele_num): - self.BB_p_init() - for i in range(IMaxSh-step): - if i >= step: - dif_shaper_Q = preamp_Q[k][i] - else: - dif_shaper_Q = 0 - for j in range(IMaxSh-i): - self.fill_BB_out(i,j,dif_shaper_Q) - self.fill_BB_th1f(k) - - def CSA_p_init(self): - """ CSA parameter initialization""" - t_rise = self.t_rise - t_fall = self.t_fall - self.tau_rise = t_rise/2.2*1e-9 - self.tau_fall = t_fall/2.2*1e-9 - if (self.tau_rise == self.tau_fall): - self.tau_rise *= 0.9 - self.sh_max = 0.0 - self.shaper_out_Q = [0.0]*self.IMaxSh - self.shaper_out_V = [0.0]*self.IMaxSh - - def BB_p_init(self): - """ BB parameter initialization""" - self.Vout_scope = [0.0]*self.IMaxSh - self.Iout_BB_RC = [0.0]*self.IMaxSh - self.Iout_C50 = [0.0]*self.IMaxSh - self.BBGraph = [0.0]*self.IMaxSh - - def fill_CSA_out(self,i,j,dif_shaper_Q): - """ Fill CSA out variable""" - self.shaper_out_Q[i+j] += self.tau_fall/(self.tau_fall+self.tau_rise) \ - * dif_shaper_Q*(math.exp(-j*self.time_unit - / self.tau_fall)-math.exp( - - j*self.time_unit/self.tau_rise)) - - def fill_BB_out(self,i,j,dif_shaper_Q): - """ Fill BB out variable""" - self.Iout_C50[i+j] += (dif_shaper_Q)/self.tau_scope \ - * math.exp(-j*self.time_unit/self.tau_scope) - self.Iout_BB_RC[i+j] += (dif_shaper_Q)/self.tau_BBA \ - * math.exp(-j*self.time_unit/self.tau_BBA) - self.BBGraph[i+j] = 1e3 * self.BBGain * self.Iout_BB_RC[i+j] - R_in = 50 # the input impedance of the amplifier - self.Vout_scope[i+j] = R_in * self.Iout_C50[i+j] -# if (abs(self.BBGraph[i+j]) > 800): -# self.BBGraph[i+j] = 800*self.BBGraph[i+j]/abs(self.BBGraph[i+j]) - - def max_CSA(self,i): - """ Get max out value of CSA""" - if (abs(self.shaper_out_Q[i]) > abs(self.sh_max)): - self.sh_max = self.shaper_out_Q[i] - - def fill_CSA_th1f(self,k): - """ Change charge to amplitude [mV] - and save in the th1f - """ - Ci = 3.5e-11 #fF - Qfrac = 1.0/(1.0+self.CDet*1e-12/Ci) - - self.ele.append(ROOT.TH1F("electronics"+str(k+1), "electronics", - self.IMaxSh, 0, self.IMaxSh*self.time_unit)) - for i in range(self.IMaxSh): - if self.sh_max == 0.0: - self.shaper_out_V[i] = 0.0 - elif self.CDet_j == 0: - - self.shaper_out_V[i] = self.shaper_out_Q[i]*self.trans_imp\ - * 1e15*self.qtot[k]*Qfrac/self.sh_max - # self.shaper_out_V[i] = self.shaper_out_Q[i]*self.trans_imp/(self.CDet*1e-12) #C_D=3.7pF - - elif self.CDet_j ==1: - self.shaper_out_V[i] = self.shaper_out_Q[i]*self.trans_imp\ - * 1e15*self.qtot[k]/self.sh_max - self.ele[k].SetBinContent(i,self.shaper_out_V[i]) - #Print the max current time of CSA - min_CSA_height, max_CSA_height = min(self.shaper_out_V), max(self.shaper_out_V) - if abs(min_CSA_height) < abs(max_CSA_height): - time_t = self.shaper_out_V.index(max_CSA_height) - else: - time_t = self.shaper_out_V.index(min_CSA_height) - print("CSA peak time={:.2e}".format(time_t*self.time_unit)) - - def fill_BB_th1f(self,k): - """ Change charge to amplitude [V] - and save in the th1f - """ - - self.ele.append(ROOT.TH1F("electronics BB"+str(k+1),"electronics BB", - self.IMaxSh,0,self.IMaxSh*self.time_unit)) - for i in range(len(self.Vout_scope)+1): - if i == 0: - self.ele[k].SetBinContent(i,0) - else: - self.ele[k].SetBinContent(i,self.Vout_scope[i-1]) - # Print the max current time of BB - min_BB_height, max_BB_height = min(self.Vout_scope), max(self.Vout_scope) - if abs(min_BB_height) < abs(max_BB_height): - time_t = self.Vout_scope.index(max_BB_height) - self.max_BB_height = abs(max_BB_height) - else: - time_t = self.Vout_scope.index(min_BB_height) - self.max_BB_height = abs(min_BB_height) - print("BB peak time={:.2e}".format(time_t*self.time_unit)) - - def __del__(self): - pass diff --git a/elec/ngspice.py b/elec/ngspice.py index cf323767f061060bfb2587208d49fc193c46f4bb..815c18451e3891a830708eaabfb713548a536c2a 100644 --- a/elec/ngspice.py +++ b/elec/ngspice.py @@ -1,10 +1,11 @@ def ngspice(input_c, input_p): - with open('./paras/circuitT1.cir', 'r') as f: + with open('./param_file/circuit/T1.cir', 'r') as f: lines = f.readlines() lines[113] = 'I1 2 0 PWL('+str(input_c)+') \n' lines[140] = 'tran 0.1p ' + str((input_p[len(input_p) - 2])) + '\n' lines[141] = 'wrdata output/t1.raw v(out)\n' f.close() - with open('./output/T1_tmp.cir', 'w') as f: + with open('./output/elec/T1_tmp.cir', 'w') as f: f.writelines(lines) f.close() +# TODO: Need to be TOTALLY rewritten \ No newline at end of file diff --git a/elec/ngspice_get_fig.py b/elec/ngspice_get_fig.py index 86fbd535e4cf5ff5e9fab5b70a4ab440f036510d..9026dbc327b6e7c9337ffa88931d90c224dde08c 100644 --- a/elec/ngspice_get_fig.py +++ b/elec/ngspice_get_fig.py @@ -3,7 +3,7 @@ import ROOT import sys import numpy - +# TODO: Need to be TOTALLY rewritten def read_file(file_path,file_name): with open(file_path + '/' + file_name) as f: lines = f.readlines() @@ -19,7 +19,7 @@ def read_file(file_path,file_name): return time,volt def main(): - file_path = 'output/fig/' + file_path = 'output/elec/ngspice_fig' file_name = sys.argv[1] com_name=file_name.split('.')[0] fig_name=file_path + com_name + '.pdf' diff --git a/elec/ngspice_set_input.py b/elec/ngspice_set_input.py index 4524df24cf519162f35cf1dadb4ec85fcd52bbf6..15ffceb868059ee67d10f401935fc107c59a13bc 100644 --- a/elec/ngspice_set_input.py +++ b/elec/ngspice_set_input.py @@ -1,7 +1,7 @@ import os import ROOT from array import array - +# TODO: Need to be TOTALLY rewritten def set_input(my_current,my_l,my_d,key): if "planar3D" in my_d.det_model or "planarRing" in my_d.det_model: path = os.path.join('output', 'pintct', my_d.det_name, ) diff --git a/elec/noise_histogram.py b/elec/noise_histogram.py deleted file mode 100644 index 6f400e6e06dcc094b9338312a53dc125805a6db8..0000000000000000000000000000000000000000 --- a/elec/noise_histogram.py +++ /dev/null @@ -1,57 +0,0 @@ -#!/usr/bin/env python3 -# -*- encoding: utf-8 -*- - -import os -import matplotlib.pyplot as plt -import numpy as np - -csv_files = [] - -def read_csv_file(folder_path): - for csv_file in os.listdir(folder_path): - if csv_file.endswith('.csv'): - csv_files.append(os.path.join(folder_path, csv_file)) - return csv_files - -folder_path = 'C:\\Users\\86188\\Desktop\\20230808\\noise_diya_ucsc' -csv_files = read_csv_file(folder_path) - -def read_csv(csv_file): - time, voltage = [], [] - with open(csv_file, 'r') as file: - lines = file.readlines() - for line in lines[6:]: - time.append(float(line.split(',')[3]) * 1e9) - voltage.append(float(line.split(',')[4]) * 1e3) - return time, voltage - -voltage_list = [] - -for csv_file in csv_files: - time, voltage = read_csv(csv_file) - voltage_list.extend(voltage) # å°†æ¯ä¸ªcsvæ–‡ä»¶çš„ç”µåŽ‹å€¼æ·»åŠ åˆ°åˆ—è¡¨ä¸ - -# 计算直方图 -hist, bins = np.histogram(voltage_list, bins=70) - -# 计算å‡å€¼å’Œæ ‡å‡†å·® -mean = np.mean(voltage_list) -stddev = np.std(voltage_list) - -# 绘制直方图 -plt.figure(figsize=(10, 6)) -plt.hist(voltage_list, bins=50, alpha=1, density=True, label='Voltage Distribution') - -# 显示å‡å€¼å’Œæ ‡å‡†å·® -plt.text(0.7, 0.9, f'Mean: {mean:.2f} mV', transform=plt.gca().transAxes) -plt.text(0.7, 0.85, f'Standard Deviation: {stddev:.2f} mV', transform=plt.gca().transAxes) - -plt.xlabel('Voltage/mV') -plt.ylabel('Frequency') -plt.title(' noise voltage distribution') - -save_dir = 'C:\\Users\\86188\\Desktop\\20230808\\noise_diya_ucsc' -file_name = 'noise.pdf' -save_file = os.path.join(save_dir,file_name) -plt.savefig(save_file) -plt.show() diff --git a/elec/readout.py b/elec/readout.py new file mode 100644 index 0000000000000000000000000000000000000000..a87d1dc8c15cc3edb65e06ecaabdc4165f0c34bf --- /dev/null +++ b/elec/readout.py @@ -0,0 +1,231 @@ +#!/usr/bin/env python3 +# -*- encoding: utf-8 -*- + +''' +Description: + Simulate induced current through BB or CSA amplifier +@Date : 2024/09/22 15:24:33 +@Author : tanyuhang, Chenxi Fu +@version : 2.0 +''' + +import math +import json + +import ROOT + +from util.math import signal_convolution +from util.output import output + +class Amplifier: + """Get current after amplifier with convolution, for each reading electrode + + Parameters + --------- + currents : list[ROOT.TH1F] + The ROOT.TH1F objects of induced current with time information + + amplifier_name : str + The name of the amplifier + + CDet : None | float + The capacitance of the detector + + Attributes + --------- + amplified_current : list[ROOT.TH1F] + The list of induced current after amplifier + + Methods + --------- + amplifier_define + Define parameters and the responce function of amplifier + + fill_amplifier_output + Get the induced current after amplifier + + set_scope_output + Get the scope output after amplifier + + Last Modified + --------- + 2024/09/14 + """ + def __init__(self, currents: list[ROOT.TH1F], amplifier_name: str, CDet = None): + self.amplified_current = [] + + ele_json = "./setting/electronics/" + amplifier_name + ".json" + with open(ele_json) as f: + self.amplifier_parameters = json.load(f) + + self.amplified_current_name = self.amplifier_parameters['ele_name'] + self.read_ele_num = len(currents) + + self.amplifier_define(CDet) + self.fill_amplifier_output(currents) + self.set_scope_output(currents) + + def amplifier_define(self, CDet): + """ + Description: + The parameters, pulse responce function and scope scaling of the amplifier. + Details introduction can be got in setting module. + @Modify: + --------- + 2021/09/09 + """ + if CDet is None: + CDet = self.amplifier_parameters['CDet'] + + if self.amplifier_parameters['ele_name'] == 'CSA': + """ CSA parameter initialization""" + + mode = 0 + + def pulse_responce_CSA(t): + if t < 0: # step function + return 0 + + t_rise = self.amplifier_parameters['t_rise'] + t_fall = self.amplifier_parameters['t_fall'] + + tau_rise = t_rise/2.2*1e-9 + tau_fall = t_fall/2.2*1e-9 + if (tau_rise == tau_fall): + tau_rise *= 0.9 + + return tau_fall/(tau_fall+tau_rise) * (math.exp(-t/tau_fall)-math.exp(-t/tau_rise)) + + def scale_CSA(output_Q_max, input_Q_tot): + """ CSA scale function""" + trans_imp = self.amplifier_parameters['trans_imp'] + Ci = 3.5e-11 #fF + Qfrac = 1.0/(1.0+self.CDet*1e-12/Ci) + + if output_Q_max == 0.0: + return 0.0 + + if mode == 0: + scale = trans_imp * 1e15 * input_Q_tot * Qfrac / output_Q_max + # scale = trans_imp/(self.CDet*1e-12) #C_D=3.7pF + elif mode == 1: + scale = trans_imp * 1e15 * input_Q_tot / output_Q_max + + return scale + + self.pulse_responce_list = [pulse_responce_CSA] + self.scale = scale_CSA + + elif self.amplifier_parameters['ele_name'] == 'BB': + """ BB parameter initialization""" + + mode = "scope" + + def pulse_responce_BB(t): + if t < 0: # step function + return 0 + + BB_bandwidth = self.amplifier_parameters['BB_bandwidth'] + BB_imp = self.amplifier_parameters['BB_imp'] + OscBW = self.amplifier_parameters['OscBW'] + + if mode == "scope": + tau_C50 = 1.0e-12 * 50. * CDet #Oscil. RC + tau_BW = 0.35 / (1.0e9*OscBW) / 2.2 #Oscil. RC + tau_scope = math.sqrt(pow(tau_C50,2)+pow(tau_BW,2)) + + return 1/tau_scope * math.exp(-t/tau_scope) + + elif mode == "RC": + tau_BB_RC = 1.0e-12 * BB_imp * CDet #BB RC + tau_BB_BW = 0.35 / (1.0e9*BB_bandwidth) / 2.2 #BB Tau, Rf*Cf? + tau_BBA = math.sqrt(pow(tau_BB_RC,2)+pow(tau_BB_BW,2)) + + return 1/tau_BBA * math.exp(-t/tau_BBA) + + else: + raise NameError(mode,"mode is not defined") + + def scale_BB(output_Q_max, input_Q_tot): + """ BB scale function""" + + if mode == "scope": + R_in = 50 + return R_in + + elif mode == "RC": + BB_Gain = self.amplifier_parameters['BB_Gain'] # kOhm ? + return BB_Gain * 1e3 + + self.pulse_responce_list = [pulse_responce_BB] + self.scale = scale_BB + + elif self.amplifier_parameters['ele_name'] == 'ABCStar_fe': + """ ABCStar_fe parameter initialization""" + + def pulse_responce_ABCStar_fe_input(t): + if t < 0: + return 0 + input_res = self.amplifier_parameters['input_res'] + return 1/(1e-12*CDet) * math.exp(-t/(1e-12*CDet*input_res)) + + def pulse_responce_ABCStar_fe_RCfeedback(t): + if t < 0: + return 0 + input_res = self.amplifier_parameters['input_res'] + Cf = self.amplifier_parameters['Cf'] + Rf = self.amplifier_parameters['Rf'] + tau_amp = 1e-12 * Cf * input_res + tau_f = 1e-12 * Cf * Rf + return 1/tau_amp * math.exp(-t/tau_f) + + def scale_ABCStar_fe(output_Q_max, input_Q_tot): + """ ABCStar_fe scale function""" + return 1000.0 # V to mV + + self.pulse_responce_list = [pulse_responce_ABCStar_fe_input, pulse_responce_ABCStar_fe_RCfeedback] + self.scale = scale_ABCStar_fe + + + def fill_amplifier_output(self, currents: list[ROOT.TH1F]): + for i in range(self.read_ele_num): + cu = currents[i] + self.amplified_current.append(ROOT.TH1F("electronics %s"%(self.amplified_current_name)+str(i+1), "electronics %s"%(self.amplified_current_name), + cu.GetNbinsX(),cu.GetXaxis().GetXmin(),cu.GetXaxis().GetXmax())) + self.amplified_current[i].Reset() + signal_convolution(cu, self.amplified_current[i], self.pulse_responce_list) + + def set_scope_output(self, currents: list[ROOT.TH1F]): + for i in range(self.read_ele_num): + cu = currents[i] + input_Q_tot = cu.Integral() + output_Q_max = self.amplified_current[i].GetMaximum() + self.amplified_current[i].Scale(self.scale(output_Q_max, input_Q_tot)) + +def main(label): + '''main function for readout.py to test the output of the given amplifier''' + + my_th1f = ROOT.TH1F("my_th1f", "my_th1f", 600, 0, 30e-9) + # input signal: square pulse + for i in range(21, 41): + my_th1f.SetBinContent(i, 2e-6) # A + + ele = Amplifier([my_th1f], label) + + c=ROOT.TCanvas("c","canvas1",1000,1000) + my_th1f.Draw("HIST") + + origin_max = my_th1f.GetMaximum() + amp_max = ele.amplified_current[0].GetMaximum() + print("amp_max =",amp_max,'mV') + + ratio = origin_max/amp_max + ele.amplified_current[0].Scale(ratio) + ele.amplified_current[0].Draw("SAME HIST") + + path = output(__file__, label) + c.SaveAs(path+'/'+label+'_test.pdf') + +if __name__ == '__main__': + import sys + main(sys.argv[1]) \ No newline at end of file diff --git a/elec/t1_create.py b/elec/t1_create.py index 70df9e24cbd56f7fadb3adaf7d58419232083b9c..69410b8c83b4f2f3eab91ca2a8f08b961dceb167 100644 --- a/elec/t1_create.py +++ b/elec/t1_create.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -*- encoding: utf-8 -*- - +# TODO: Need to be TOTALLY rewritten import ROOT import os import numpy as np @@ -70,17 +70,17 @@ if number>=1: input_c.append(str(0)) input_p=','.join(input_c) - with open('/scratchfs/atlas/xingchenli/raser/paras/circuitT1.cir', 'r') as f: + with open('/scratchfs/atlas/xingchenli/raser/param_file/circuit/T1.cir', 'r') as f: lines = f.readlines() lines[113] = 'I1 2 0 PWL('+str(input_p)+') \n' lines[140] = 'tran 0.1p ' + str((input_c[len(input_c) - 2])) + '\n' lines[141] = 'wrdata output/'+str(L)+'t1.txt v(out)\n' f.close() - with open('/scratchfs/atlas/xingchenli/raser/output/T1_tmp.cir', 'w') as f: + with open('/scratchfs/atlas/xingchenli/raser/output/elec/T1_tmp.cir', 'w') as f: f.writelines(lines) f.close() - os.system("ngspice -b -r t1.txt output/T1_tmp.cir") + os.system("ngspice -b -r t1.txt output/elec/T1_tmp.cir") t1=np.loadtxt('/scratchfs/atlas/xingchenli/raser/output/'+str(L)+'t1.txt',dtype=float) volt=[] @@ -142,17 +142,17 @@ else: input_c.append(str(0)) input_p=','.join(input_c) - with open('/scratchfs/atlas/xingchenli/raser/paras/circuitT1.cir', 'r') as f: + with open('/scratchfs/atlas/xingchenli/raser/param_file/circuit/T1.cir', 'r') as f: lines = f.readlines() lines[113] = 'I1 2 0 PWL('+str(input_p)+') \n' lines[140] = 'tran 0.1p ' + str((input_c[len(input_c) - 2])) + '\n' lines[141] = 'wrdata output/'+str(L)+'t1.txt v(out)\n' f.close() - with open('/scratchfs/atlas/xingchenli/raser/output/T1_tmp.cir', 'w') as f: + with open('/scratchfs/atlas/xingchenli/raser/output/elec/T1_tmp.cir', 'w') as f: f.writelines(lines) f.close() - os.system("ngspice -b -r t1.txt output/T1_tmp.cir") + os.system("ngspice -b -r t1.txt output/elec/T1_tmp.cir") t1=np.loadtxt('/scratchfs/atlas/xingchenli/raser/output/'+str(L)+'t1.txt',dtype=float) volt=[] diff --git a/field/__init__.py b/field/__init__.py index 469b36e2248e12632dca06ff374e3bdfceb6c1b2..2e68a4572ccbd3546bbb6b2bf1216151b44bdaa4 100755 --- a/field/__init__.py +++ b/field/__init__.py @@ -1,8 +1,5 @@ import logging -import devsim -from . import gen_devsim_db -from . import devsim_solve -from . import test4hsic + def main(kwargs): label = kwargs['label'] verbose = kwargs['verbose'] @@ -16,10 +13,14 @@ def main(kwargs): logging.debug('This is DEBUG messaage') if label == 'gen_devsim_db': + from . import gen_devsim_db gen_devsim_db.main() elif label == "3d_plugin_field": + from . import test4hsic test4hsic.main("2dfield_4HSiC") elif label == "3d_ringcontact_Elefield": + from . import test4hsic test4hsic.main("3d_ringcontact") else: + from . import devsim_solve devsim_solve.main(kwargs) diff --git a/field/build_device.py b/field/build_device.py index 82526b5b14fd7f0b5e685e61a4673696f252a32e..9bb4dffa6194b95626aea4caeae47aacf4582de5 100644 --- a/field/build_device.py +++ b/field/build_device.py @@ -1,14 +1,16 @@ #!/usr/bin/env python3 # -*- encoding: utf-8 -*- -import devsim -from . import model_create - -from util.output import output import json import os +import devsim import matplotlib.pyplot +import numpy as np + +from . import model_create +from util.output import output +from util.math import * class Detector: """ @@ -65,8 +67,10 @@ class Detector: if "strip" in self.det_name or "Strip" in self.det_name: # TODO: change this into model self.read_ele_num = self.device_dict['read_ele_num'] + else: + self.read_ele_num = 1 - if "pixeldetector" in self.det_model: + if "pixel" in self.det_model: self.p_x = self.device_dict['px'] self.p_y = self.device_dict['py'] self.p_z = self.device_dict['pz'] @@ -124,7 +128,7 @@ class Detector: devsim.add_2d_interface(mesh=mesh_name, **interface) devsim.finalize_mesh(mesh=mesh_name) devsim.create_device(mesh=mesh_name, device=mesh_name) - devsim.write_devices(file="test", type="tecplot") + devsim.write_devices(file="output/field/test", type="tecplot") def createGmshMesh(self): mesh_name = self.device @@ -148,13 +152,13 @@ class Detector: elif self.control_dict["ac-weightfield"] == False: pass if 'Acceptors_ir' in self.device_dict['doping']: - model_create.CreateNodeModel(self.device, self.region, "Acceptors", self.device_dict['doping']['Acceptors']+"+"+self.device_dict['doping']['Acceptors_ir']) + model_create.CreateNodeModel(self.device, self.region, "Acceptors", self.device_dict['doping']['Acceptors']+"+"+self.device_dict['doping']['Acceptors_ir']) else: - model_create.CreateNodeModel(self.device, self.region, "Acceptors", self.device_dict['doping']['Acceptors']) + model_create.CreateNodeModel(self.device, self.region, "Acceptors", self.device_dict['doping']['Acceptors']) if 'Donors_ir' in self.device_dict['doping']: - model_create.CreateNodeModel(self.device, self.region, "Donors", self.device_dict['doping']['Donors']+"+"+self.device_dict['doping']['Donors_ir']) + model_create.CreateNodeModel(self.device, self.region, "Donors", self.device_dict['doping']['Donors']+"+"+self.device_dict['doping']['Donors_ir']) else: - model_create.CreateNodeModel(self.device, self.region, "Donors", self.device_dict['doping']['Donors']) + model_create.CreateNodeModel(self.device, self.region, "Donors", self.device_dict['doping']['Donors']) model_create.CreateNodeModel(self.device, self.region, "NetDoping", "Donors-Acceptors") devsim.edge_from_node_model(device=self.device, region=self.region, node_model="Acceptors") devsim.edge_from_node_model(device=self.device, region=self.region, node_model="NetDoping") diff --git a/field/devsim_field.py b/field/devsim_field.py index 80daf40f36709ec7950dc6a6b7f7f5612cc1e189..679b6f12a813e236009dc670bbbeea1e0d4e0b9c 100644 --- a/field/devsim_field.py +++ b/field/devsim_field.py @@ -10,16 +10,10 @@ import pickle import ROOT import numpy as np -from scipy.interpolate import interp1d as p1d -from scipy.interpolate import interp2d as p2d -from scipy.interpolate import griddata -from scipy.interpolate import LinearNDInterpolator as LNDI -diff_res = 1e-5 # difference resolution in cm +from util.math import * -x_bin = 1000 -y_bin = 1000 -z_bin = 1000 +diff_res = 1e-5 # difference resolution in cm class DevsimField: def __init__(self, device_name, dimension, voltage, read_ele_num, l_z): @@ -29,15 +23,39 @@ class DevsimField: self.read_ele_num = int(read_ele_num) self.l_z = l_z # used for planar weighting field TODO: auto weighting field + DopingFile = "./output/field/{}/NetDoping_0.0V.pkl".format(self.name) PotentialFile = "./output/field/{}/Potential_{}V.pkl".format(self.name, self.voltage) TrappingRate_pFile = "./output/field/{}/TrappingRate_p_{}V.pkl".format(self.name, self.voltage) TrappingRate_nFile = "./output/field/{}/TrappingRate_n_{}V.pkl".format(self.name, self.voltage) - self.set_potential(PotentialFile) #self.potential, self.x_efield, self.y_efield, self.z_efield + self.set_doping(DopingFile) #self.Doping + self.set_potential(PotentialFile) #self.Potential, self.x_efield, self.y_efield, self.z_efield self.set_trap_p(TrappingRate_pFile) # self.TrappingRate_p self.set_trap_n(TrappingRate_nFile) # self.TrappingRate_n self.set_w_p() #self.weighting_potential[] + def set_doping(self, DopingFile): + try: + with open(DopingFile,'rb') as file: + DopingNotUniform=pickle.load(file) + print("Doping file loaded for {}".format(self.name)) + if DopingNotUniform['metadata']['dimension'] < self.dimension: + print("Doping dimension not match") + return + except FileNotFoundError: + print("Doping file not found, please run field simulation first") + print("or manually set the doping file") + return + + if DopingNotUniform['metadata']['dimension'] == 1: + DopingUniform = get_common_interpolate_1d(DopingNotUniform) + elif DopingNotUniform['metadata']['dimension'] == 2: + DopingUniform = get_common_interpolate_2d(DopingNotUniform) + elif DopingNotUniform['metadata']['dimension'] == 3: + DopingUniform = get_common_interpolate_3d(DopingNotUniform) + + self.Doping = DopingUniform + def set_potential(self, PotentialFile): try: with open(PotentialFile,'rb') as file: @@ -54,9 +72,9 @@ class DevsimField: if PotentialNotUniform['metadata']['dimension'] == 1: PotentialUniform = get_common_interpolate_1d(PotentialNotUniform) elif PotentialNotUniform['metadata']['dimension'] == 2: - PotentialUniform =get_common_interpolate_2d(PotentialNotUniform) + PotentialUniform = get_common_interpolate_2d(PotentialNotUniform) elif PotentialNotUniform['metadata']['dimension'] == 3: - PotentialUniform =get_common_interpolate_3d(PotentialNotUniform) + PotentialUniform = get_common_interpolate_3d(PotentialNotUniform) self.Potential = PotentialUniform @@ -88,9 +106,9 @@ class DevsimField: if TrappingRate_pNotUniform['metadata']['dimension'] == 1: TrappingRate_pUniform = get_common_interpolate_1d(TrappingRate_pNotUniform) elif TrappingRate_pNotUniform['metadata']['dimension'] == 2: - TrappingRate_pUniform =get_common_interpolate_2d(TrappingRate_pNotUniform) + TrappingRate_pUniform = get_common_interpolate_2d(TrappingRate_pNotUniform) elif TrappingRate_pNotUniform['metadata']['dimension'] == 3: - TrappingRate_pUniform =get_common_interpolate_3d(TrappingRate_pNotUniform) + TrappingRate_pUniform = get_common_interpolate_3d(TrappingRate_pNotUniform) self.TrappingRate_p = TrappingRate_pUniform @@ -110,14 +128,27 @@ class DevsimField: if TrappingRate_nNotUniform['metadata']['dimension'] == 1: TrappingRate_nUniform = get_common_interpolate_1d(TrappingRate_nNotUniform) elif TrappingRate_nNotUniform['metadata']['dimension'] == 2: - TrappingRate_nUniform =get_common_interpolate_2d(TrappingRate_nNotUniform) + TrappingRate_nUniform = get_common_interpolate_2d(TrappingRate_nNotUniform) elif TrappingRate_nNotUniform['metadata']['dimension'] == 3: - TrappingRate_nUniform =get_common_interpolate_3d(TrappingRate_nNotUniform) + TrappingRate_nUniform = get_common_interpolate_3d(TrappingRate_nNotUniform) self.TrappingRate_n = TrappingRate_nUniform # DEVSIM dimension order: x, y, z # RASER dimension order: z, x, y + + def get_doping(self, x, y, z): + ''' + input: position in um + output: doping in cm^-3 + ''' + x, y, z = x/1e4, y/1e4, z/1e4 # um to cm + if self.dimension == 1: + return self.Doping(z) + elif self.dimension == 2: + return self.Doping(z, x) + elif self.dimension == 3: + return self.Doping(z, x, y) def get_potential(self, x, y, z): ''' @@ -243,45 +274,6 @@ class DevsimField: elif self.dimension == 3: return self.TrappingRate_p(z, x, y) -def get_common_interpolate_1d(data): - values = data['values'] - points = data['points'] - f = p1d(points, values) - return f - -def get_common_interpolate_2d(data): - values = data['values'] - points_x = [] - points_y = [] - for point in data['points']: - points_x.append(point[0]) - points_y.append(point[1]) - new_x = np.linspace(min(points_x), max(points_x), x_bin) - new_y = np.linspace(min(points_y), max(points_y), y_bin) - new_points = np.array(np.meshgrid(new_x, new_y)).T.reshape(-1, 2) - new_values = griddata((points_x, points_y), values, new_points, method='linear') - f = p2d(new_x, new_y, new_values) - return f - -def get_common_interpolate_3d(data): - values = data['values'] - points_x = [] - points_y = [] - points_z = [] - for point in data['points']: - points_x.append(point[0]) - points_y.append(point[1]) - points_z.append(point[2]) - new_x = np.linspace(min(points_x), max(points_x), x_bin) - new_y = np.linspace(min(points_y), max(points_y), y_bin) - new_z = np.linspace(min(points_z), max(points_z), z_bin) - new_points = np.array(np.meshgrid(new_x, new_y, new_z)).T.reshape(-1, 3) - new_values = griddata((points_x, points_y, points_z), values, new_points, method='linear') - lndi = LNDI(new_points, new_values) - def f(x, y, z): - point = [x, y, z] - return lndi(point) - return f def linear_w_p(z, l_z): if z >= l_z: diff --git a/field/devsim_solve.py b/field/devsim_solve.py index 2bad8bd7350cca615a2b4de38e236b89466294be..bc648a6b23fbb576623b58d3aa05333a1ba52773 100644 --- a/field/devsim_solve.py +++ b/field/devsim_solve.py @@ -213,7 +213,9 @@ def main(kwargs): hole_current = devsim.get_contact_current(device=device, contact=circuit_contacts, equation="HoleContinuityEquation") total_current = electron_current + hole_current - if(abs(total_current/area_factor)>105e-6): break + if(abs(total_current/area_factor)>105e-6): + print("current is too large !") + # break current.append(abs(total_current/area_factor)) writer_iv.writerow([v,abs(total_current/area_factor)]) @@ -291,7 +293,11 @@ def milestone_save_1D(device, region, v, path): metadata['voltage'] = v metadata['dimension'] = 1 - for name in ['Potential', 'TrappingRate_p', 'TrappingRate_n']: # scalar field on mesh point (instead of on edge) + names = ['Potential', 'TrappingRate_p', 'TrappingRate_n'] + if v == 0: + names.append('NetDoping') + + for name in names: # scalar field on mesh point (instead of on edge) with open(os.path.join(path, "{}_{}V.pkl".format(name,v)),'wb') as file: data = {} data['values'] = eval(name) # refer to the object with given name @@ -325,7 +331,11 @@ def milestone_save_2D(device, region, v, path): metadata['voltage'] = v metadata['dimension'] = 2 - for name in ['Potential', 'TrappingRate_p', 'TrappingRate_n']: # scalar field on mesh point (instead of on edge) + names = ['Potential', 'TrappingRate_p', 'TrappingRate_n'] + if v == 0: + names.append('NetDoping') + + for name in names: # scalar field on mesh point (instead of on edge) with open(os.path.join(path, "{}_{}V.pkl".format(name,v)),'wb') as file: data = {} data['values'] = eval(name) # refer to the object with given name @@ -336,7 +346,6 @@ def milestone_save_2D(device, region, v, path): pickle.dump(data, file) - def milestone_save_wf_2D(device, region, v, path,contact): x = np.array(devsim.get_node_model_values(device=device, region=region, name="x")) # get x-node values y = np.array(devsim.get_node_model_values(device=device, region=region, name="y")) # get y-node values @@ -352,7 +361,6 @@ def milestone_save_wf_2D(device, region, v, path,contact): draw2D(x,y,Potential,"Potential",v, path) draw2D(x_mid,y_mid,ElectricField,"ElectricField",v, path) - dd = os.path.join(path, str(v),str(contact)+'V.dd') devsim.write_devices(file=dd, type="tecplot") @@ -380,7 +388,11 @@ def milestone_save_3D(device, region, v, path): metadata['voltage'] = v metadata['dimension'] = 3 - for name in ['Potential']: # scalar field on mesh point (instead of on edge) + names = ['Potential', 'TrappingRate_p', 'TrappingRate_n'] + if v == 0: + names.append('NetDoping') + + for name in names: # scalar field on mesh point (instead of on edge) with open(os.path.join(path, "{}_{}V.pkl".format(name,v)),'wb') as file: data = {} data['values'] = eval(name) # refer to the object with given name diff --git a/field/test4hsic.py b/field/test4hsic.py index 334f453b58b6546c5f87672ab18c5d043d7f8f15..0f3399c0fb027de5d5afa64c40d7b6e52fe4bb08 100755 --- a/field/test4hsic.py +++ b/field/test4hsic.py @@ -11,13 +11,13 @@ from mpl_toolkits.mplot3d import Axes3D def main(simname): if '3d' in simname: - with open('./output/{}/x_500.0.pkl'.format(simname), 'rb') as file: + with open('./output/field/{}/x_500.0.pkl'.format(simname), 'rb') as file: x = pickle.load(file) - with open('./output/{}/y_500.0.pkl'.format(simname), 'rb') as file: + with open('./output/field/{}/y_500.0.pkl'.format(simname), 'rb') as file: y = pickle.load(file) - with open('./output/{}/z_500.0.pkl'.format(simname), 'rb') as file: + with open('./output/field/{}/z_500.0.pkl'.format(simname), 'rb') as file: z = pickle.load(file) - with open('./output/{}/potential_500.0.pkl'.format(simname), 'rb') as file: + with open('./output/field/{}/potential_500.0.pkl'.format(simname), 'rb') as file: potential = pickle.load(file) # 定义æ’å€¼ç½‘æ ¼ @@ -45,7 +45,7 @@ def main(simname): ax_potential_xz.set_xlabel('x') ax_potential_xz.set_ylabel('z') ax_potential_xz.set_title('Potential XZ Plane') - plt.savefig('./output/{}/Potential_XZ_Plane.png'.format(simname)) + plt.savefig('./output/field/{}/Potential_XZ_Plane.png'.format(simname)) # 绘制电势的yzå¹³é¢æˆªé¢å›¾ fig_potential_yz = plt.figure() @@ -54,7 +54,7 @@ def main(simname): ax_potential_yz.set_xlabel('y') ax_potential_yz.set_ylabel('z') ax_potential_yz.set_title('Potential YZ Plane') - plt.savefig('./output/{}/Potential_YZ_Plane.png'.format(simname)) + plt.savefig('./output/field/{}/Potential_YZ_Plane.png'.format(simname)) # 绘制电势的xyå¹³é¢æˆªé¢å›¾ fig_xy_planes = plt.figure(figsize=(10, 10)) for i in range(0, nPoints, 5): @@ -72,7 +72,7 @@ def main(simname): ax_total_field_xy.set_xlabel('x') ax_total_field_xy.set_ylabel('y') ax_total_field_xy.set_title('Total Field XY Plane') - plt.savefig('./output/{}/Total_Field_XY_Plane.png'.format(simname)) + plt.savefig('./output/field/{}/Total_Field_XY_Plane.png'.format(simname)) #Plot total field YZ plane fig_total_field_yz = plt.figure() @@ -81,7 +81,7 @@ def main(simname): ax_total_field_yz.set_xlabel('y') ax_total_field_yz.set_ylabel('z') ax_total_field_yz.set_title('Total Field YZ Plane') - plt.savefig('./output/{}/Total_Field_YZ_Plane.png'.format(simname)) + plt.savefig('./output/field/{}/Total_Field_YZ_Plane.png'.format(simname)) #Plot 20 dianchang XY planes fig_xy = plt.figure(figsize=(15, 15)) @@ -94,17 +94,17 @@ def main(simname): ax_xy.set_ylabel('y') ax_xy.set_title('XY Plane {}'.format(i+1)) plt.tight_layout() - plt.savefig('./output/{}/Total_Field_XY_Planes.png'.format(simname)) + plt.savefig('./output/field/{}/Total_Field_XY_Planes.png'.format(simname)) else: # 从pickle文件ä¸åŠ è½½xã€yå’Œç”µåŠ¿æ•°æ® - with open('./output/{}/x_500.0.pkl'.format(simname), 'rb') as file: + with open('./output/field/{}/x_500.0.pkl'.format(simname), 'rb') as file: x = pickle.load(file) - with open('./output/{}/y_500.0.pkl'.format(simname), 'rb') as file: + with open('./output/field/{}/y_500.0.pkl'.format(simname), 'rb') as file: y = pickle.load(file) - with open('./output/{}/potential_500.0.pkl'.format(simname), 'rb') as file: + with open('./output/field/{}/potential_500.0.pkl'.format(simname), 'rb') as file: potential = pickle.load(file) # 定义æ’å€¼ç½‘æ ¼ @@ -150,9 +150,9 @@ def main(simname): hTotalField.SetBinContent(i+1, j+1, total_field[i, j]) # ä¿å˜æ€»åœºå¼ºä¸ºROOT对象 - output_file = ROOT.TFile('./output/{}/Total_Field_2D.root'.format(simname), 'recreate') + output_file = ROOT.TFile('./output/field/{}/Total_Field_2D.root'.format(simname), 'recreate') hTotalField.Write() output_file.Close() if __name__ == "__main__": - main(simname) \ No newline at end of file + main("2dfield_4HSiC") \ No newline at end of file diff --git a/gen_signal/__init__.py b/gen_signal/__init__.py index 3ba98384db5d63b6b9bb2619818de61456c63785..af5d0aaf5ee383f6caf43689c730d8d7bd415560 100644 --- a/gen_signal/__init__.py +++ b/gen_signal/__init__.py @@ -1,205 +1,8 @@ -#!/usr/bin/env python3 -# -*- encoding: utf-8 -*- -''' -@Description: The main program of Raser induced current simulation -@Date : 2024/02/20 18:12:26 -@Author : tanyuhang, Chenxi Fu -@version : 2.0 -''' -import sys -import os -import array -import time -import subprocess -import ROOT - -from field import build_device as bdv -from particle import g4simulation as g4s -from field import devsim_field as devfield -from current import cal_current as ccrt -from elec import ele_readout as rdout -from elec import ngspice_set_input as ngsip -from elec import ngspice as ng - -from . import draw_save -from util.output import output - -import json - -import random - def main(kwargs): - """ - Description: - The main program of Raser induced current simulation - Parameters: - --------- - dset : class - Parameters of simulation - Function or class: - Detector -- Define the basic parameters and mesh structure of the detector - DevsimCal -- Get the electric field and weighting potential - Particles -- Electron and hole paris distibution - CalCurrent -- Drift of e-h pais and induced current - Amplifier -- Readout electronics simulation - draw_plots -- Draw electric field, drift path and energy deposition - Modify: - --------- - 2021/09/02 - """ - start = time.time() - - det_name = kwargs['det_name'] - my_d = bdv.Detector(det_name) - - if kwargs['voltage'] != None: - voltage = float(kwargs['voltage']) - else: - voltage = float(my_d.voltage) - - if kwargs['absorber'] != None: - absorber = kwargs['absorber'] - else: - absorber = my_d.absorber - - if kwargs['amplifier'] != None: - amplifier = kwargs['amplifier'] - else: - amplifier = my_d.amplifier - - if "strip" in det_name: - my_f = devfield.DevsimField(my_d.device, my_d.dimension, voltage, my_d.read_ele_num, my_d.l_z) - else: - my_f = devfield.DevsimField(my_d.device, my_d.dimension, voltage, 1, my_d.l_z) - - if kwargs['scan'] != None: - geant4_json = "./setting/absorber/" + absorber + ".json" - with open(geant4_json) as f: - g4_dic = json.load(f) - - total_events = int(g4_dic['total_events']) - for i in range(kwargs['scan']): - # TODO: change this into multithread - instance_number = i - g4_seed = instance_number * total_events - my_g4p = g4s.Particles(my_d, absorber, g4_seed) - batch_loop(my_d, my_f, my_g4p, amplifier, g4_seed, total_events, instance_number) - del my_g4p - return - - else: - g4_seed = random.randint(0,1e7) - my_g4p = g4s.Particles(my_d, absorber, g4_seed) - - if "strip" in det_name: - my_current = ccrt.CalCurrentStrip(my_d, my_f, my_g4p, 0) - else: - my_current = ccrt.CalCurrentG4P(my_d, my_f, my_g4p, 0) - - if 'ngspice' in amplifier: - save_current(my_d, my_current,my_f = devfield.DevsimField(my_d.device, my_d.dimension, voltage, 1, my_d.l_z), key=None) - input_p=ngsip.set_input(my_current, my_d, key=None) - input_c=','.join(input_p) - ng.ngspice_t0(input_c, input_p) - subprocess.run(['ngspice -b -r t0.raw output/T0_tmp.cir'], shell=True) - ng.plot_waveform() - else: - ele_current = rdout.Amplifier(my_current, amplifier) - draw_save.draw_plots(my_d,ele_current,my_f,my_g4p,my_current) - - del my_f - end = time.time() - print("total_time:%s"%(end-start)) - + label = kwargs['label'] - -def batch_loop(my_d, my_f, my_g4p, amplifier, g4_seed, total_events, instance_number): - """ - Description: - Batch run some events to get time resolution - Parameters: - --------- - start_n : int - Start number of the event - end_n : int - end number of the event - detection_efficiency: float - The ration of hit particles/total_particles - @Returns: - --------- - None - @Modify: - --------- - 2021/09/07 - """ - path = output(__file__, my_d.det_name, 'batch') - if "plugin" in my_d.det_model: - draw_save.draw_ele_field(my_d,my_f,"xy",my_d.det_model,my_d.l_z*0.5,path) + if label == 'signal': + from . import gen_signal_main + gen_signal_main.main(kwargs) else: - draw_save.draw_ele_field_1D(my_d,my_f,path) - draw_save.draw_ele_field(my_d,my_f,"xz",my_d.det_model,my_d.l_y*0.5,path) - - start_n = instance_number * total_events - end_n = (instance_number + 1) * total_events - - effective_number = 0 - for event in range(start_n,end_n): - print("run events number:%s"%(event)) - if len(my_g4p.p_steps[event-start_n]) > 5: - effective_number += 1 - my_current = ccrt.CalCurrentG4P(my_d, my_f, my_g4p, event-start_n) - ele_current = rdout.Amplifier(my_current, amplifier) - draw_save.save_signal_time_resolution(my_d,event,ele_current,my_g4p,start_n,my_f) - del ele_current - detection_efficiency = effective_number/(end_n-start_n) - print("detection_efficiency=%s"%detection_efficiency) - - - -def save_current(my_d,my_current,my_f,key): - if key!=None: - if "planar3D" in my_d.det_model or "planarRing" in my_d.det_model: - path = os.path.join('output', 'pintct', my_d.det_name, ) - elif "lgad3D" in my_d.det_model: - path = os.path.join('output', 'lgadtct', my_d.det_name, ) - if os.path.exists(path): - os.mkdir(path) - L = eval("my_l.{}".format(key)) - #L is defined by different keys - elif key==None: - if "planar3D" in my_d.det_model or "planarRing" in my_d.det_model: - path = os.path.join('output', 'PIN', my_d.det_name, ) - elif "lgad3D" in my_d.det_model: - path = os.path.join('output', 'LGAD', my_d.det_name, ) - if not os.path.exists(path): - os.makedirs(path) - - #L is defined by different keys - time = array.array('d', [999.]) - current = array.array('d', [999.]) - fout = ROOT.TFile(os.path.join(path, "sim-current") + ".root", "RECREATE") - t_out = ROOT.TTree("tree", "signal") - t_out.Branch("time", time, "time/D") - for i in range(my_f.read_ele_num): - t_out.Branch("current"+str(i), current, "current"+str(i)+"/D") - for j in range(my_current.n_bin): - current[0]=my_current.sum_cu[i].GetBinContent(j) - time[0]=j*my_current.t_bin - t_out.Fill() - t_out.Write() - fout.Close() - - - - - - - -if __name__ == '__main__': - args = sys.argv[1:] - kwargs = {} - for arg in args: - key, value = arg.split('=') - kwargs[key] = value - main(kwargs) - \ No newline at end of file + raise NameError diff --git a/gen_signal/draw_save.py b/gen_signal/draw_save.py index 66ef9f50f9ec5c41c2eee3df53f1d019d8194158..ad2132000cb30db544a287a35eddd489b062d949 100644 --- a/gen_signal/draw_save.py +++ b/gen_signal/draw_save.py @@ -15,7 +15,7 @@ import time from util.output import output -def draw_plots(my_d,ele_current,my_f,my_g4p,my_current,my_l=None): +def draw_plots(my_d,ele_current,my_f,my_g4p,my_current,my_l=None,laser_path=None): """ @description: Draw electric field ,drift path and energy deposition @@ -27,15 +27,18 @@ def draw_plots(my_d,ele_current,my_f,my_g4p,my_current,my_l=None): 2021/08/31 """ now = time.strftime("%Y_%m%d_%H%M%S") - path = output(__file__, my_d.det_name, now) + if laser_path != None: + path = laser_path + else: + path = output(__file__, my_d.det_name, now) if "plugin" in my_d.det_model: draw_ele_field(my_d,my_f,"xy",my_d.det_model,my_d.l_z*0.5,path) else: draw_ele_field_1D(my_d,my_f,path) draw_ele_field(my_d,my_f,"xz",my_d.det_model,my_d.l_y*0.5,path) - for i in range(my_f.read_ele_num): - draw_current(my_d, my_current,ele_current.ele,i,ele_current.ele_name,path) # Draw current + for i in range(my_current.read_ele_num): + draw_current(my_d, my_current,ele_current.amplified_current,i,ele_current.amplified_current_name,path) # Draw current #energy_deposition(my_g4p) # Draw Geant4 depostion distribution if my_l != None: my_l.draw_nocarrier3D(path) @@ -70,9 +73,9 @@ def save_signal_csv(ele_current,my_g4p,number,start_n,k,output_path="none"): output_file = output_path + "/t_" +str(number)+charge+e_dep+"events.csv" f1 = open(output_file,"w") f1.write("time[ns], Amplitude [mV] \n") - for i in range(ele_current.ele[k].GetNbinsX()): + for i in range(ele_current.amplified_current[k].GetNbinsX()): f1.write("%s,%s \n"%(i*ele_current.time_unit, - ele_current.ele[k][i])) + ele_current.amplified_current[k][i])) f1.close() print("output_file:%s"%output_file) @@ -545,8 +548,8 @@ def energy_deposition(my_g4v): print("MPV:%s"%g1.GetParameter(1)) h1.Draw() now = time.strftime("%Y_%m%d_%H%M") - c1.SaveAs("output/fig/dep_SiC"+"_"+now+"_energy.pdf") - c1.SaveAs("output/fig/dep_SiC"+"_"+now+"_energy.root") + c1.SaveAs("output/particle/dep_SiC"+"_"+now+"_energy.pdf") + c1.SaveAs("output/particle/dep_SiC"+"_"+now+"_energy.root") def create_path(path): """ If the path does not exit, create the path""" @@ -676,7 +679,7 @@ def get1_beam_number(my_g4p): def cce(my_d,my_f,my_current, path): charge=array('d') x=array('d') - for i in range(my_f.read_ele_num): + for i in range(my_current.read_ele_num): x.append(i+1) sum_charge=0 for j in range(my_current.n_bin): diff --git a/gen_signal/gen_signal_main.py b/gen_signal/gen_signal_main.py new file mode 100644 index 0000000000000000000000000000000000000000..12a19313cc15e1d89b4b3e5e8400afb48e82c650 --- /dev/null +++ b/gen_signal/gen_signal_main.py @@ -0,0 +1,201 @@ +#!/usr/bin/env python3 +# -*- encoding: utf-8 -*- +''' +@Description: The main program of Raser induced current simulation +@Date : 2024/02/20 18:12:26 +@Author : tanyuhang, Chenxi Fu +@version : 2.0 +''' +import sys +import os +import array +import time +import subprocess +import ROOT + +from field import build_device as bdv +from particle import g4simulation as g4s +from field import devsim_field as devfield +from current import cal_current as ccrt +from elec import readout as rdo +from elec import ngspice_set_input as ngsip +from elec import ngspice as ng + +from . import draw_save +from util.output import output + +import json + +import random + +def main(kwargs): + """ + Description: + The main program of Raser induced current simulation + Parameters: + --------- + dset : class + Parameters of simulation + Function or class: + Detector -- Define the basic parameters and mesh structure of the detector + DevsimCal -- Get the electric field and weighting potential + Particles -- Electron and hole paris distibution + CalCurrent -- Drift of e-h pais and induced current + Amplifier -- Readout electronics simulation + draw_plots -- Draw electric field, drift path and energy deposition + Modify: + --------- + 2021/09/02 + """ + start = time.time() + + det_name = kwargs['det_name'] + my_d = bdv.Detector(det_name) + + if kwargs['voltage'] != None: + voltage = float(kwargs['voltage']) + else: + voltage = float(my_d.voltage) + + if kwargs['absorber'] != None: + absorber = kwargs['absorber'] + else: + absorber = my_d.absorber + + if kwargs['amplifier'] != None: + amplifier = kwargs['amplifier'] + else: + amplifier = my_d.amplifier + + my_f = devfield.DevsimField(my_d.device, my_d.dimension, voltage, my_d.read_ele_num, my_d.l_z) + + if kwargs['scan'] != None: + geant4_json = "./setting/absorber/" + absorber + ".json" + with open(geant4_json) as f: + g4_dic = json.load(f) + + total_events = int(g4_dic['total_events']) + for i in range(kwargs['scan']): + # TODO: change this into multithread + instance_number = i + g4_seed = instance_number * total_events + my_g4p = g4s.Particles(my_d, absorber, g4_seed) + batch_loop(my_d, my_f, my_g4p, amplifier, g4_seed, total_events, instance_number) + del my_g4p + return + + else: + g4_seed = random.randint(0,1e7) + my_g4p = g4s.Particles(my_d, absorber, g4_seed) + + if "strip" in det_name: + my_current = ccrt.CalCurrentStrip(my_d, my_f, my_g4p, 0) + else: + my_current = ccrt.CalCurrentG4P(my_d, my_f, my_g4p, 0) + + if 'ngspice' in amplifier: + save_current(my_d, my_current, my_f = devfield.DevsimField(my_d.device, my_d.dimension, voltage, 1, my_d.l_z), key=None) + input_p=ngsip.set_input(my_current, my_d, key=None) + input_c=','.join(input_p) + ng.ngspice_t0(input_c, input_p) + subprocess.run(['ngspice -b -r t0.raw output/T0_tmp.cir'], shell=True) + ng.plot_waveform() + else: + ele_current = rdo.Amplifier(my_current.sum_cu, amplifier) + draw_save.draw_plots(my_d,ele_current,my_f,my_g4p,my_current) + + del my_f + end = time.time() + print("total_time:%s"%(end-start)) + + + +def batch_loop(my_d, my_f, my_g4p, amplifier, g4_seed, total_events, instance_number): + """ + Description: + Batch run some events to get time resolution + Parameters: + --------- + start_n : int + Start number of the event + end_n : int + end number of the event + detection_efficiency: float + The ration of hit particles/total_particles + @Returns: + --------- + None + @Modify: + --------- + 2021/09/07 + """ + path = output(__file__, my_d.det_name, 'batch') + if "plugin" in my_d.det_model: + draw_save.draw_ele_field(my_d,my_f,"xy",my_d.det_model,my_d.l_z*0.5,path) + else: + draw_save.draw_ele_field_1D(my_d,my_f,path) + draw_save.draw_ele_field(my_d,my_f,"xz",my_d.det_model,my_d.l_y*0.5,path) + + start_n = instance_number * total_events + end_n = (instance_number + 1) * total_events + + effective_number = 0 + for event in range(start_n,end_n): + print("run events number:%s"%(event)) + if len(my_g4p.p_steps[event-start_n]) > 5: + effective_number += 1 + my_current = ccrt.CalCurrentG4P(my_d, my_f, my_g4p, event-start_n) + ele_current = rdo.Amplifier(my_current.sum_cu, amplifier) + draw_save.save_signal_time_resolution(my_d,event,ele_current,my_g4p,start_n,my_f) + del ele_current + detection_efficiency = effective_number/(end_n-start_n) + print("detection_efficiency=%s"%detection_efficiency) + +# TODO: change this to a method of CalCurrent +def save_current(my_d,my_current,my_f,key): + if key!=None: + if "planar3D" in my_d.det_model or "planarRing" in my_d.det_model: + path = os.path.join('output', 'pintct', my_d.det_name, ) + elif "lgad3D" in my_d.det_model: + path = os.path.join('output', 'lgadtct', my_d.det_name, ) + if os.path.exists(path): + os.mkdir(path) + L = eval("my_l.{}".format(key)) + #L is defined by different keys + elif key==None: + if "planar3D" in my_d.det_model or "planarRing" in my_d.det_model: + path = os.path.join('output', 'PIN', my_d.det_name, ) + elif "lgad3D" in my_d.det_model: + path = os.path.join('output', 'LGAD', my_d.det_name, ) + if not os.path.exists(path): + os.makedirs(path) + + #L is defined by different keys + time = array.array('d', [999.]) + current = array.array('d', [999.]) + fout = ROOT.TFile(os.path.join(path, "sim-current") + ".root", "RECREATE") + t_out = ROOT.TTree("tree", "signal") + t_out.Branch("time", time, "time/D") + for i in range(my_current.read_ele_num): + t_out.Branch("current"+str(i), current, "current"+str(i)+"/D") + for j in range(my_current.n_bin): + current[0]=my_current.sum_cu[i].GetBinContent(j) + time[0]=j*my_current.t_bin + t_out.Fill() + t_out.Write() + fout.Close() + + + + + + + +if __name__ == '__main__': + args = sys.argv[1:] + kwargs = {} + for arg in args: + key, value = arg.split('=') + kwargs[key] = value + main(kwargs) + \ No newline at end of file diff --git a/motor/GUI/Limits.ui b/motor/GUI/Limits.ui deleted file mode 100644 index dad80ce20d1f92e99d2727acf77d49666eb8b384..0000000000000000000000000000000000000000 --- a/motor/GUI/Limits.ui +++ /dev/null @@ -1,95 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>Limits</class> - <widget class="QDialog" name="Limits"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>229</width> - <height>112</height> - </rect> - </property> - <property name="windowTitle"> - <string>Limits</string> - </property> - <layout class="QGridLayout" name="gridLayout"> - <item row="0" column="1"> - <widget class="QLabel" name="LabelUpper"> - <property name="text"> - <string>Upper Limit</string> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QDoubleSpinBox" name="LowerLimit"> - <property name="decimals"> - <number>0</number> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QDoubleSpinBox" name="UpperLimit"> - <property name="decimals"> - <number>0</number> - </property> - </widget> - </item> - <item row="0" column="0"> - <widget class="QLabel" name="LabelLower"> - <property name="text"> - <string>Lower Limit</string> - </property> - </widget> - </item> - <item row="4" column="0" colspan="2"> - <widget class="QDialogButtonBox" name="ButtonBox"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="standardButtons"> - <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> - </property> - <property name="centerButtons"> - <bool>false</bool> - </property> - </widget> - </item> - </layout> - </widget> - <resources/> - <connections> - <connection> - <sender>ButtonBox</sender> - <signal>accepted()</signal> - <receiver>Limits</receiver> - <slot>accept()</slot> - <hints> - <hint type="sourcelabel"> - <x>248</x> - <y>254</y> - </hint> - <hint type="destinationlabel"> - <x>157</x> - <y>274</y> - </hint> - </hints> - </connection> - <connection> - <sender>ButtonBox</sender> - <signal>rejected()</signal> - <receiver>Limits</receiver> - <slot>reject()</slot> - <hints> - <hint type="sourcelabel"> - <x>316</x> - <y>260</y> - </hint> - <hint type="destinationlabel"> - <x>286</x> - <y>274</y> - </hint> - </hints> - </connection> - </connections> -</ui> diff --git a/motor/GUI/XWidget.ui b/motor/GUI/XWidget.ui deleted file mode 100644 index d6d3214dc69e9d41528fcc8032a8252c1b97c180..0000000000000000000000000000000000000000 --- a/motor/GUI/XWidget.ui +++ /dev/null @@ -1,218 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>Form</class> - <widget class="QWidget" name="Form"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>298</width> - <height>296</height> - </rect> - </property> - <property name="windowTitle"> - <string>Form</string> - </property> - <layout class="QGridLayout" name="gridLayout"> - <item row="2" column="3"> - <widget class="QLabel" name="CurPos"> - <property name="text"> - <string>Current Position:</string> - </property> - </widget> - </item> - <item row="4" column="2"> - <widget class="QGroupBox" name="RelativeMove"> - <property name="title"> - <string>Relative Move</string> - </property> - <layout class="QGridLayout" name="gridLayout_2"> - <item row="1" column="0"> - <widget class="QDoubleSpinBox" name="RelativePos"> - <property name="minimumSize"> - <size> - <width>50</width> - <height>0</height> - </size> - </property> - <property name="decimals"> - <number>0</number> - </property> - <property name="minimum"> - <double>-1015.000000000000000</double> - </property> - <property name="maximum"> - <double>1015.000000000000000</double> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QLabel" name="mm"> - <property name="text"> - <string>um</string> - </property> - </widget> - </item> - <item row="3" column="0" colspan="2"> - <widget class="QPushButton" name="MoveRE"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>30</height> - </size> - </property> - <property name="text"> - <string>Move</string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item row="6" column="3"> - <widget class="QPushButton" name="Limits"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>40</height> - </size> - </property> - <property name="text"> - <string>Limits</string> - </property> - </widget> - </item> - <item row="3" column="2"> - <widget class="QPushButton" name="Home"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>30</height> - </size> - </property> - <property name="text"> - <string>Home</string> - </property> - </widget> - </item> - <item row="2" column="2"> - <widget class="QLabel" name="StatusLabel"> - <property name="text"> - <string/> - </property> - </widget> - </item> - <item row="4" column="3"> - <widget class="QGroupBox" name="AbsoluteMove"> - <property name="title"> - <string>Absolut Move</string> - </property> - <layout class="QGridLayout" name="gridLayout_3"> - <item row="3" column="0"> - <widget class="QDoubleSpinBox" name="DesirePos"> - <property name="minimumSize"> - <size> - <width>50</width> - <height>0</height> - </size> - </property> - <property name="sizeIncrement"> - <size> - <width>0</width> - <height>0</height> - </size> - </property> - <property name="decimals"> - <number>0</number> - </property> - <property name="maximum"> - <double>1015.000000000000000</double> - </property> - </widget> - </item> - <item row="3" column="1"> - <widget class="QLabel" name="mm_2"> - <property name="text"> - <string>um</string> - </property> - </widget> - </item> - <item row="4" column="0" colspan="2"> - <widget class="QPushButton" name="MoveAB"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>30</height> - </size> - </property> - <property name="text"> - <string>Move</string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item row="3" column="3"> - <widget class="QLCDNumber" name="CurrentPos"/> - </item> - <item row="2" column="1" rowspan="7"> - <widget class="QScrollBar" name="Scroll"> - <property name="maximum"> - <number>1015</number> - </property> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="invertedAppearance"> - <bool>false</bool> - </property> - <property name="invertedControls"> - <bool>false</bool> - </property> - </widget> - </item> - <item row="7" column="2"> - <widget class="QPushButton" name="JogPlus"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>40</height> - </size> - </property> - <property name="text"> - <string>X+ Jog</string> - </property> - </widget> - </item> - <item row="6" column="2"> - <widget class="QPushButton" name="JogMinus"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>40</height> - </size> - </property> - <property name="text"> - <string>X- Jog</string> - </property> - </widget> - </item> - <item row="7" column="3"> - <widget class="QPushButton" name="Stop"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>40</height> - </size> - </property> - <property name="text"> - <string>Stop</string> - </property> - </widget> - </item> - </layout> - </widget> - <resources/> - <connections/> -</ui> diff --git a/motor/GUI/XYZWidget.ui b/motor/GUI/XYZWidget.ui deleted file mode 100644 index d0790ede4506f0dcefdc36245fb3397fcf998aac..0000000000000000000000000000000000000000 --- a/motor/GUI/XYZWidget.ui +++ /dev/null @@ -1,1850 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>MainWindow</class> - <widget class="QMainWindow" name="MainWindow"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>655</width> - <height>450</height> - </rect> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>655</width> - <height>450</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>655</width> - <height>450</height> - </size> - </property> - <property name="windowTitle"> - <string>MainWindow</string> - </property> - <widget class="QWidget" name="centralwidget"> - <widget class="QTabWidget" name="tabWidget"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>631</width> - <height>411</height> - </rect> - </property> - <property name="currentIndex"> - <number>0</number> - </property> - <widget class="QWidget" name="tab"> - <attribute name="title"> - <string>Stage Control</string> - </attribute> - <widget class="QLabel" name="label_4"> - <property name="geometry"> - <rect> - <x>510</x> - <y>0</y> - <width>60</width> - <height>24</height> - </rect> - </property> - <property name="text"> - <string><html><head/><body><p align="center"><span style=" font-size:16pt; font-weight:600;">Reset</span></p></body></html></string> - </property> - </widget> - <widget class="QGroupBox" name="groupBox_2"> - <property name="geometry"> - <rect> - <x>480</x> - <y>30</y> - <width>131</width> - <height>331</height> - </rect> - </property> - <property name="title"> - <string/> - </property> - <widget class="QPushButton" name="ResetPosX"> - <property name="geometry"> - <rect> - <x>10</x> - <y>40</y> - <width>51</width> - <height>41</height> - </rect> - </property> - <property name="text"> - <string>Home X</string> - </property> - </widget> - <widget class="QPushButton" name="ResetPosY"> - <property name="geometry"> - <rect> - <x>10</x> - <y>130</y> - <width>51</width> - <height>41</height> - </rect> - </property> - <property name="text"> - <string>Home Y</string> - </property> - </widget> - <widget class="QPushButton" name="ResetPosZ"> - <property name="geometry"> - <rect> - <x>10</x> - <y>200</y> - <width>51</width> - <height>41</height> - </rect> - </property> - <property name="text"> - <string>Home Z</string> - </property> - </widget> - <widget class="QPushButton" name="SetMotor"> - <property name="geometry"> - <rect> - <x>10</x> - <y>280</y> - <width>101</width> - <height>41</height> - </rect> - </property> - <property name="text"> - <string>Set Motor</string> - </property> - </widget> - <widget class="QPushButton" name="zeroX"> - <property name="geometry"> - <rect> - <x>70</x> - <y>40</y> - <width>51</width> - <height>41</height> - </rect> - </property> - <property name="text"> - <string>Zero X</string> - </property> - </widget> - <widget class="QPushButton" name="zeroY"> - <property name="geometry"> - <rect> - <x>70</x> - <y>130</y> - <width>51</width> - <height>41</height> - </rect> - </property> - <property name="text"> - <string>Zero Y</string> - </property> - </widget> - <widget class="QPushButton" name="zeroZ"> - <property name="geometry"> - <rect> - <x>70</x> - <y>200</y> - <width>51</width> - <height>41</height> - </rect> - </property> - <property name="text"> - <string>Zero Z</string> - </property> - </widget> - </widget> - <widget class="QLabel" name="label_8"> - <property name="geometry"> - <rect> - <x>320</x> - <y>0</y> - <width>144</width> - <height>18</height> - </rect> - </property> - <property name="text"> - <string><html><head/><body><p align="center"><span style=" font-size:12pt; font-weight:600;">Current Position</span></p></body></html></string> - </property> - </widget> - <widget class="QGroupBox" name="groupBox_3"> - <property name="geometry"> - <rect> - <x>320</x> - <y>30</y> - <width>151</width> - <height>271</height> - </rect> - </property> - <property name="title"> - <string/> - </property> - <widget class="QLCDNumber" name="CurrentPosX"> - <property name="geometry"> - <rect> - <x>30</x> - <y>40</y> - <width>91</width> - <height>41</height> - </rect> - </property> - </widget> - <widget class="QLCDNumber" name="CurrentPosY"> - <property name="geometry"> - <rect> - <x>30</x> - <y>130</y> - <width>91</width> - <height>41</height> - </rect> - </property> - </widget> - <widget class="QLCDNumber" name="CurrentPosZ"> - <property name="geometry"> - <rect> - <x>30</x> - <y>220</y> - <width>91</width> - <height>41</height> - </rect> - </property> - </widget> - <widget class="QLabel" name="label_9"> - <property name="geometry"> - <rect> - <x>20</x> - <y>20</y> - <width>81</width> - <height>21</height> - </rect> - </property> - <property name="text"> - <string>Current Pos.X</string> - </property> - </widget> - <widget class="QLabel" name="label_10"> - <property name="geometry"> - <rect> - <x>20</x> - <y>100</y> - <width>91</width> - <height>21</height> - </rect> - </property> - <property name="text"> - <string>Current Pos.Y</string> - </property> - </widget> - <widget class="QLabel" name="label_11"> - <property name="geometry"> - <rect> - <x>20</x> - <y>190</y> - <width>91</width> - <height>31</height> - </rect> - </property> - <property name="text"> - <string>Current Pos.Z</string> - </property> - </widget> - </widget> - <widget class="QLabel" name="PosContr"> - <property name="geometry"> - <rect> - <x>70</x> - <y>0</y> - <width>192</width> - <height>24</height> - </rect> - </property> - <property name="text"> - <string><html><head/><body><p align="center"><span style=" font-size:16pt; font-weight:600;">Position Control</span></p></body></html></string> - </property> - </widget> - <widget class="QGroupBox" name="groupBox"> - <property name="geometry"> - <rect> - <x>0</x> - <y>30</y> - <width>311</width> - <height>331</height> - </rect> - </property> - <property name="title"> - <string/> - </property> - <property name="flat"> - <bool>false</bool> - </property> - <property name="checkable"> - <bool>false</bool> - </property> - <widget class="QLabel" name="label_5"> - <property name="geometry"> - <rect> - <x>210</x> - <y>50</y> - <width>72</width> - <height>18</height> - </rect> - </property> - <property name="text"> - <string><html><head/><body><p><span style=" font-size:12pt;">Set pos.X</span></p></body></html></string> - </property> - </widget> - <widget class="QLabel" name="label_6"> - <property name="geometry"> - <rect> - <x>210</x> - <y>130</y> - <width>72</width> - <height>18</height> - </rect> - </property> - <property name="text"> - <string><html><head/><body><p><span style=" font-size:12pt;">Set pos.Y</span></p></body></html></string> - </property> - </widget> - <widget class="QLabel" name="label_7"> - <property name="geometry"> - <rect> - <x>210</x> - <y>220</y> - <width>72</width> - <height>18</height> - </rect> - </property> - <property name="text"> - <string><html><head/><body><p><span style=" font-size:12pt;">Set pos.Z</span></p></body></html></string> - </property> - </widget> - <widget class="QSpinBox" name="StepMoveX"> - <property name="geometry"> - <rect> - <x>110</x> - <y>130</y> - <width>71</width> - <height>31</height> - </rect> - </property> - <property name="buttonSymbols"> - <enum>QAbstractSpinBox::UpDownArrows</enum> - </property> - <property name="maximum"> - <number>500</number> - </property> - </widget> - <widget class="QSpinBox" name="StepMoveY"> - <property name="geometry"> - <rect> - <x>110</x> - <y>210</y> - <width>71</width> - <height>31</height> - </rect> - </property> - <property name="maximum"> - <number>500</number> - </property> - </widget> - <widget class="QSpinBox" name="StepMoveZ"> - <property name="geometry"> - <rect> - <x>110</x> - <y>300</y> - <width>71</width> - <height>31</height> - </rect> - </property> - <property name="maximum"> - <number>500</number> - </property> - </widget> - <widget class="QLabel" name="label"> - <property name="geometry"> - <rect> - <x>20</x> - <y>130</y> - <width>71</width> - <height>31</height> - </rect> - </property> - <property name="text"> - <string>Step move X</string> - </property> - </widget> - <widget class="QLabel" name="label_2"> - <property name="geometry"> - <rect> - <x>20</x> - <y>210</y> - <width>71</width> - <height>31</height> - </rect> - </property> - <property name="text"> - <string>Step move Y</string> - </property> - </widget> - <widget class="QLabel" name="label_3"> - <property name="geometry"> - <rect> - <x>20</x> - <y>300</y> - <width>71</width> - <height>31</height> - </rect> - </property> - <property name="text"> - <string>Step move Z</string> - </property> - </widget> - <widget class="QPushButton" name="XMinus"> - <property name="geometry"> - <rect> - <x>60</x> - <y>70</y> - <width>61</width> - <height>31</height> - </rect> - </property> - <property name="text"> - <string><</string> - </property> - </widget> - <widget class="QPushButton" name="XPlus"> - <property name="geometry"> - <rect> - <x>120</x> - <y>70</y> - <width>61</width> - <height>31</height> - </rect> - </property> - <property name="text"> - <string>></string> - </property> - </widget> - <widget class="QPushButton" name="YMinus"> - <property name="geometry"> - <rect> - <x>60</x> - <y>170</y> - <width>61</width> - <height>31</height> - </rect> - </property> - <property name="text"> - <string><</string> - </property> - </widget> - <widget class="QPushButton" name="YPlus"> - <property name="geometry"> - <rect> - <x>120</x> - <y>170</y> - <width>61</width> - <height>31</height> - </rect> - </property> - <property name="text"> - <string>></string> - </property> - </widget> - <widget class="QPushButton" name="ZMinus"> - <property name="geometry"> - <rect> - <x>60</x> - <y>250</y> - <width>61</width> - <height>31</height> - </rect> - </property> - <property name="text"> - <string><</string> - </property> - </widget> - <widget class="QPushButton" name="ZPlus"> - <property name="geometry"> - <rect> - <x>120</x> - <y>250</y> - <width>61</width> - <height>31</height> - </rect> - </property> - <property name="text"> - <string>></string> - </property> - </widget> - <widget class="QPushButton" name="MoveButton"> - <property name="geometry"> - <rect> - <x>200</x> - <y>290</y> - <width>91</width> - <height>41</height> - </rect> - </property> - <property name="text"> - <string>move</string> - </property> - </widget> - <widget class="QLineEdit" name="SetPosX"> - <property name="geometry"> - <rect> - <x>200</x> - <y>80</y> - <width>91</width> - <height>20</height> - </rect> - </property> - <property name="text"> - <string>0</string> - </property> - </widget> - <widget class="QLineEdit" name="SetPosY"> - <property name="geometry"> - <rect> - <x>200</x> - <y>170</y> - <width>91</width> - <height>20</height> - </rect> - </property> - <property name="text"> - <string>0</string> - </property> - </widget> - <widget class="QLineEdit" name="SetPosZ"> - <property name="geometry"> - <rect> - <x>202</x> - <y>260</y> - <width>91</width> - <height>20</height> - </rect> - </property> - <property name="text"> - <string>0</string> - </property> - </widget> - <widget class="QLabel" name="label_29"> - <property name="geometry"> - <rect> - <x>40</x> - <y>2</y> - <width>54</width> - <height>20</height> - </rect> - </property> - <property name="text"> - <string><html><head/><body><p align="center"><span style=" font-size:12pt; font-weight:600;">motor</span></p></body></html></string> - </property> - </widget> - <widget class="QLabel" name="label_30"> - <property name="geometry"> - <rect> - <x>140</x> - <y>2</y> - <width>54</width> - <height>20</height> - </rect> - </property> - <property name="text"> - <string><html><head/><body><p align="center"><span style=" font-size:12pt; font-weight:600;">motor</span></p></body></html></string> - </property> - </widget> - <widget class="QLabel" name="label_31"> - <property name="geometry"> - <rect> - <x>250</x> - <y>2</y> - <width>54</width> - <height>20</height> - </rect> - </property> - <property name="text"> - <string><html><head/><body><p align="center"><span style=" font-size:12pt; font-weight:600;">motor</span></p></body></html></string> - </property> - </widget> - <widget class="QWidget" name="layoutWidget"> - <property name="geometry"> - <rect> - <x>0</x> - <y>20</y> - <width>311</width> - <height>32</height> - </rect> - </property> - <layout class="QHBoxLayout" name="horizontalLayout_4"> - <item> - <widget class="QLabel" name="label_26"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>37</width> - <height>16777215</height> - </size> - </property> - <property name="text"> - <string><html><head/><body><p align="center"><span style=" font-size:12pt; font-weight:600;">X:</span></p></body></html></string> - </property> - </widget> - </item> - <item> - <widget class="QSpinBox" name="X_Motor_Num"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>28</height> - </size> - </property> - <property name="minimum"> - <number>1</number> - </property> - <property name="maximum"> - <number>3</number> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="label_27"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>37</width> - <height>16777215</height> - </size> - </property> - <property name="text"> - <string><html><head/><body><p align="center"><span style=" font-size:12pt; font-weight:600;">Y:</span></p></body></html></string> - </property> - </widget> - </item> - <item> - <widget class="QSpinBox" name="Y_Motor_Num"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>28</height> - </size> - </property> - <property name="minimum"> - <number>1</number> - </property> - <property name="maximum"> - <number>3</number> - </property> - <property name="value"> - <number>2</number> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="label_28"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>37</width> - <height>16777215</height> - </size> - </property> - <property name="text"> - <string><html><head/><body><p align="center"><span style=" font-size:12pt; font-weight:600;">Z:</span></p></body></html></string> - </property> - </widget> - </item> - <item> - <widget class="QSpinBox" name="Z_Motor_Num"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>28</height> - </size> - </property> - <property name="minimum"> - <number>1</number> - </property> - <property name="maximum"> - <number>3</number> - </property> - <property name="value"> - <number>3</number> - </property> - </widget> - </item> - </layout> - </widget> - </widget> - <widget class="QPushButton" name="StopBut"> - <property name="geometry"> - <rect> - <x>350</x> - <y>320</y> - <width>91</width> - <height>41</height> - </rect> - </property> - <property name="text"> - <string>Stop</string> - </property> - </widget> - </widget> - <widget class="QWidget" name="tab_2"> - <attribute name="title"> - <string>Movement Parameters</string> - </attribute> - <widget class="QLabel" name="label_12"> - <property name="geometry"> - <rect> - <x>10</x> - <y>20</y> - <width>111</width> - <height>21</height> - </rect> - </property> - <property name="text"> - <string><html><head/><body><p><span style=" font-weight:600;">Step definitions</span></p></body></html></string> - </property> - </widget> - <widget class="QGroupBox" name="groupBox_4"> - <property name="geometry"> - <rect> - <x>0</x> - <y>50</y> - <width>311</width> - <height>301</height> - </rect> - </property> - <property name="title"> - <string/> - </property> - <widget class="QSpinBox" name="x0"> - <property name="geometry"> - <rect> - <x>20</x> - <y>40</y> - <width>91</width> - <height>31</height> - </rect> - </property> - <property name="minimum"> - <number>-100000</number> - </property> - <property name="maximum"> - <number>100000</number> - </property> - </widget> - <widget class="QSpinBox" name="dx"> - <property name="geometry"> - <rect> - <x>115</x> - <y>40</y> - <width>91</width> - <height>31</height> - </rect> - </property> - <property name="minimum"> - <number>1</number> - </property> - <property name="maximum"> - <number>1000</number> - </property> - </widget> - <widget class="QSpinBox" name="Nx"> - <property name="geometry"> - <rect> - <x>210</x> - <y>40</y> - <width>101</width> - <height>31</height> - </rect> - </property> - <property name="maximum"> - <number>1000</number> - </property> - </widget> - <widget class="QSpinBox" name="y0"> - <property name="geometry"> - <rect> - <x>20</x> - <y>110</y> - <width>91</width> - <height>31</height> - </rect> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>0</height> - </size> - </property> - <property name="sizeIncrement"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - <property name="minimum"> - <number>-100000</number> - </property> - <property name="maximum"> - <number>100000</number> - </property> - </widget> - <widget class="QSpinBox" name="Ny"> - <property name="geometry"> - <rect> - <x>210</x> - <y>110</y> - <width>101</width> - <height>31</height> - </rect> - </property> - <property name="maximum"> - <number>1000</number> - </property> - </widget> - <widget class="QSpinBox" name="dy"> - <property name="geometry"> - <rect> - <x>115</x> - <y>110</y> - <width>91</width> - <height>31</height> - </rect> - </property> - <property name="minimum"> - <number>1</number> - </property> - <property name="maximum"> - <number>1000</number> - </property> - </widget> - <widget class="QSpinBox" name="z0"> - <property name="geometry"> - <rect> - <x>20</x> - <y>180</y> - <width>91</width> - <height>31</height> - </rect> - </property> - <property name="minimum"> - <number>-100000</number> - </property> - <property name="maximum"> - <number>100000</number> - </property> - </widget> - <widget class="QSpinBox" name="Nz"> - <property name="geometry"> - <rect> - <x>210</x> - <y>180</y> - <width>101</width> - <height>31</height> - </rect> - </property> - <property name="maximum"> - <number>1000</number> - </property> - </widget> - <widget class="QSpinBox" name="dz"> - <property name="geometry"> - <rect> - <x>115</x> - <y>180</y> - <width>91</width> - <height>31</height> - </rect> - </property> - <property name="minimum"> - <number>1</number> - </property> - <property name="maximum"> - <number>1000</number> - </property> - </widget> - <widget class="QLabel" name="label_19"> - <property name="geometry"> - <rect> - <x>20</x> - <y>150</y> - <width>86</width> - <height>29</height> - </rect> - </property> - <property name="text"> - <string><html><head/><body><p><span style=" font-size:12pt; font-weight:600;">z0</span></p></body></html></string> - </property> - </widget> - <widget class="QLabel" name="label_20"> - <property name="geometry"> - <rect> - <x>112</x> - <y>150</y> - <width>85</width> - <height>29</height> - </rect> - </property> - <property name="text"> - <string><html><head/><body><p><span style=" font-size:12pt; font-weight:600;">dz</span></p></body></html></string> - </property> - </widget> - <widget class="QLabel" name="label_21"> - <property name="geometry"> - <rect> - <x>203</x> - <y>150</y> - <width>86</width> - <height>29</height> - </rect> - </property> - <property name="text"> - <string><html><head/><body><p><span style=" font-size:12pt; font-weight:600;">Nz</span></p></body></html></string> - </property> - </widget> - <widget class="QPushButton" name="ScanBut"> - <property name="geometry"> - <rect> - <x>20</x> - <y>230</y> - <width>91</width> - <height>41</height> - </rect> - </property> - <property name="text"> - <string>Scan</string> - </property> - </widget> - <widget class="QWidget" name="layoutWidget"> - <property name="geometry"> - <rect> - <x>20</x> - <y>10</y> - <width>271</width> - <height>31</height> - </rect> - </property> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <widget class="QLabel" name="label_13"> - <property name="text"> - <string><html><head/><body><p><span style=" font-size:12pt; font-weight:600;">x0</span></p></body></html></string> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="label_14"> - <property name="text"> - <string><html><head/><body><p><span style=" font-size:12pt; font-weight:600;">dx</span></p></body></html></string> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="label_15"> - <property name="text"> - <string><html><head/><body><p><span style=" font-size:12pt; font-weight:600;">Nx</span></p></body></html></string> - </property> - </widget> - </item> - </layout> - </widget> - <widget class="QWidget" name="layoutWidget"> - <property name="geometry"> - <rect> - <x>20</x> - <y>80</y> - <width>271</width> - <height>31</height> - </rect> - </property> - <layout class="QHBoxLayout" name="horizontalLayout_2"> - <item> - <widget class="QLabel" name="label_16"> - <property name="text"> - <string><html><head/><body><p><span style=" font-size:12pt; font-weight:600;">y0</span></p></body></html></string> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="label_17"> - <property name="text"> - <string><html><head/><body><p><span style=" font-size:12pt; font-weight:600;">dy</span></p></body></html></string> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="label_18"> - <property name="text"> - <string><html><head/><body><p><span style=" font-size:12pt; font-weight:600;">Ny</span></p></body></html></string> - </property> - </widget> - </item> - </layout> - </widget> - <widget class="QWidget" name="layoutWidget"> - <property name="geometry"> - <rect> - <x>20</x> - <y>150</y> - <width>271</width> - <height>31</height> - </rect> - </property> - <layout class="QHBoxLayout" name="horizontalLayout_3"/> - </widget> - <widget class="QPushButton" name="ScanStop"> - <property name="geometry"> - <rect> - <x>200</x> - <y>230</y> - <width>91</width> - <height>41</height> - </rect> - </property> - <property name="text"> - <string>Scanning Stop</string> - </property> - </widget> - <widget class="QPushButton" name="Set_Speed"> - <property name="geometry"> - <rect> - <x>110</x> - <y>230</y> - <width>91</width> - <height>41</height> - </rect> - </property> - <property name="text"> - <string>Set Speed</string> - </property> - </widget> - </widget> - <widget class="QGroupBox" name="groupBox_5"> - <property name="geometry"> - <rect> - <x>470</x> - <y>50</y> - <width>151</width> - <height>301</height> - </rect> - </property> - <property name="title"> - <string/> - </property> - <widget class="QLCDNumber" name="CurrentPosX_2"> - <property name="geometry"> - <rect> - <x>30</x> - <y>40</y> - <width>91</width> - <height>41</height> - </rect> - </property> - </widget> - <widget class="QLCDNumber" name="CurrentPosY_2"> - <property name="geometry"> - <rect> - <x>30</x> - <y>130</y> - <width>91</width> - <height>41</height> - </rect> - </property> - </widget> - <widget class="QLCDNumber" name="CurrentPosZ_2"> - <property name="geometry"> - <rect> - <x>30</x> - <y>220</y> - <width>91</width> - <height>41</height> - </rect> - </property> - </widget> - <widget class="QLabel" name="label_22"> - <property name="geometry"> - <rect> - <x>20</x> - <y>20</y> - <width>81</width> - <height>21</height> - </rect> - </property> - <property name="text"> - <string>Current Pos.X</string> - </property> - </widget> - <widget class="QLabel" name="label_23"> - <property name="geometry"> - <rect> - <x>20</x> - <y>100</y> - <width>91</width> - <height>21</height> - </rect> - </property> - <property name="text"> - <string>Current Pos.Y</string> - </property> - </widget> - <widget class="QLabel" name="label_24"> - <property name="geometry"> - <rect> - <x>20</x> - <y>190</y> - <width>91</width> - <height>31</height> - </rect> - </property> - <property name="text"> - <string>Current Pos.Z</string> - </property> - </widget> - </widget> - <widget class="QLabel" name="label_25"> - <property name="geometry"> - <rect> - <x>470</x> - <y>20</y> - <width>144</width> - <height>18</height> - </rect> - </property> - <property name="text"> - <string><html><head/><body><p align="center"><span style=" font-size:12pt; font-weight:600;">Current Position</span></p></body></html></string> - </property> - </widget> - <widget class="QLabel" name="label_32"> - <property name="geometry"> - <rect> - <x>300</x> - <y>20</y> - <width>171</width> - <height>20</height> - </rect> - </property> - <property name="text"> - <string><html><head/><body><p><span style=" font-weight:600;">Speed Paremeters</span></p></body></html></string> - </property> - </widget> - <widget class="QGroupBox" name="groupBox_6"> - <property name="geometry"> - <rect> - <x>310</x> - <y>50</y> - <width>161</width> - <height>301</height> - </rect> - </property> - <property name="title"> - <string/> - </property> - <widget class="QLabel" name="label_33"> - <property name="geometry"> - <rect> - <x>10</x> - <y>20</y> - <width>54</width> - <height>12</height> - </rect> - </property> - <property name="text"> - <string><html><head/><body><p><span style=" font-weight:600;">Step X</span></p></body></html></string> - </property> - </widget> - <widget class="QLabel" name="label_34"> - <property name="geometry"> - <rect> - <x>90</x> - <y>20</y> - <width>54</width> - <height>12</height> - </rect> - </property> - <property name="text"> - <string><html><head/><body><p><span style=" font-weight:600;">Speed X</span></p></body></html></string> - </property> - </widget> - <widget class="QLabel" name="label_35"> - <property name="geometry"> - <rect> - <x>90</x> - <y>90</y> - <width>54</width> - <height>12</height> - </rect> - </property> - <property name="text"> - <string><html><head/><body><p><span style=" font-weight:600;">Speed Y</span></p></body></html></string> - </property> - </widget> - <widget class="QLabel" name="label_36"> - <property name="geometry"> - <rect> - <x>10</x> - <y>90</y> - <width>54</width> - <height>12</height> - </rect> - </property> - <property name="text"> - <string><html><head/><body><p><span style=" font-weight:600;">Step Y</span></p></body></html></string> - </property> - </widget> - <widget class="QLabel" name="label_37"> - <property name="geometry"> - <rect> - <x>90</x> - <y>160</y> - <width>54</width> - <height>12</height> - </rect> - </property> - <property name="text"> - <string><html><head/><body><p><span style=" font-weight:600;">Speed Z</span></p></body></html></string> - </property> - </widget> - <widget class="QLabel" name="label_38"> - <property name="geometry"> - <rect> - <x>10</x> - <y>160</y> - <width>54</width> - <height>12</height> - </rect> - </property> - <property name="text"> - <string><html><head/><body><p><span style=" font-weight:600;">Step Z</span></p></body></html></string> - </property> - </widget> - <widget class="QWidget" name="layoutWidget"> - <property name="geometry"> - <rect> - <x>0</x> - <y>40</y> - <width>158</width> - <height>27</height> - </rect> - </property> - <layout class="QHBoxLayout" name="horizontalLayout_5"> - <item> - <widget class="QSpinBox" name="Step_X"> - <property name="minimumSize"> - <size> - <width>75</width> - <height>25</height> - </size> - </property> - <property name="minimum"> - <number>0</number> - </property> - <property name="maximum"> - <number>256</number> - </property> - <property name="value"> - <number>0</number> - </property> - <property name="displayIntegerBase"> - <number>10</number> - </property> - </widget> - </item> - <item> - <widget class="QSpinBox" name="Speed_X"> - <property name="minimumSize"> - <size> - <width>75</width> - <height>25</height> - </size> - </property> - <property name="maximum"> - <number>100000</number> - </property> - <property name="value"> - <number>1000</number> - </property> - </widget> - </item> - </layout> - </widget> - <widget class="QWidget" name="layoutWidget"> - <property name="geometry"> - <rect> - <x>0</x> - <y>110</y> - <width>158</width> - <height>27</height> - </rect> - </property> - <layout class="QHBoxLayout" name="horizontalLayout_6"> - <item> - <widget class="QSpinBox" name="Step_Y"> - <property name="minimumSize"> - <size> - <width>75</width> - <height>25</height> - </size> - </property> - <property name="minimum"> - <number>0</number> - </property> - <property name="maximum"> - <number>256</number> - </property> - <property name="value"> - <number>0</number> - </property> - </widget> - </item> - <item> - <widget class="QSpinBox" name="Speed_Y"> - <property name="minimumSize"> - <size> - <width>75</width> - <height>25</height> - </size> - </property> - <property name="maximum"> - <number>100000</number> - </property> - <property name="value"> - <number>1000</number> - </property> - </widget> - </item> - </layout> - </widget> - <widget class="QWidget" name="layoutWidget"> - <property name="geometry"> - <rect> - <x>0</x> - <y>180</y> - <width>158</width> - <height>27</height> - </rect> - </property> - <layout class="QHBoxLayout" name="horizontalLayout_7"> - <item> - <widget class="QSpinBox" name="Step_Z"> - <property name="minimumSize"> - <size> - <width>75</width> - <height>25</height> - </size> - </property> - <property name="minimum"> - <number>0</number> - </property> - <property name="maximum"> - <number>256</number> - </property> - <property name="value"> - <number>0</number> - </property> - </widget> - </item> - <item> - <widget class="QSpinBox" name="Speed_Z"> - <property name="minimumSize"> - <size> - <width>75</width> - <height>25</height> - </size> - </property> - <property name="maximum"> - <number>100000</number> - </property> - <property name="value"> - <number>1000</number> - </property> - </widget> - </item> - </layout> - </widget> - <widget class="QRadioButton" name="default_speed"> - <property name="geometry"> - <rect> - <x>20</x> - <y>220</y> - <width>111</width> - <height>16</height> - </rect> - </property> - <property name="text"> - <string>Default Speed</string> - </property> - <property name="checked"> - <bool>true</bool> - </property> - </widget> - <widget class="QRadioButton" name="setting_speed"> - <property name="geometry"> - <rect> - <x>20</x> - <y>260</y> - <width>101</width> - <height>16</height> - </rect> - </property> - <property name="text"> - <string>Setting Speed</string> - </property> - </widget> - </widget> - </widget> - <widget class="QWidget" name="tab_3"> - <attribute name="title"> - <string>Data Capture</string> - </attribute> - <widget class="QCommandLinkButton" name="FolderSet"> - <property name="geometry"> - <rect> - <x>580</x> - <y>170</y> - <width>41</width> - <height>41</height> - </rect> - </property> - <property name="text"> - <string/> - </property> - </widget> - <widget class="QPushButton" name="CaptureBut"> - <property name="geometry"> - <rect> - <x>490</x> - <y>230</y> - <width>101</width> - <height>41</height> - </rect> - </property> - <property name="text"> - <string>Capture</string> - </property> - </widget> - <widget class="QLabel" name="label_39"> - <property name="geometry"> - <rect> - <x>320</x> - <y>180</y> - <width>51</width> - <height>31</height> - </rect> - </property> - <property name="text"> - <string>Folder:</string> - </property> - </widget> - <widget class="QLineEdit" name="FolderText"> - <property name="geometry"> - <rect> - <x>370</x> - <y>180</y> - <width>201</width> - <height>31</height> - </rect> - </property> - </widget> - <widget class="QLabel" name="label_40"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>141</width> - <height>21</height> - </rect> - </property> - <property name="text"> - <string><html><head/><body><p><span style=" font-weight:600;">Devices and Interface:</span></p></body></html></string> - </property> - </widget> - <widget class="QComboBox" name="Interface"> - <property name="geometry"> - <rect> - <x>0</x> - <y>20</y> - <width>301</width> - <height>31</height> - </rect> - </property> - <property name="currentText"> - <string/> - </property> - </widget> - <widget class="QPushButton" name="ReadyBut"> - <property name="geometry"> - <rect> - <x>370</x> - <y>230</y> - <width>91</width> - <height>41</height> - </rect> - </property> - <property name="text"> - <string>Ready</string> - </property> - </widget> - <widget class="QTextEdit" name="InfoText"> - <property name="geometry"> - <rect> - <x>0</x> - <y>100</y> - <width>301</width> - <height>271</height> - </rect> - </property> - </widget> - <widget class="QLabel" name="label_43"> - <property name="geometry"> - <rect> - <x>330</x> - <y>60</y> - <width>161</width> - <height>21</height> - </rect> - </property> - <property name="text"> - <string><html><head/><body><p align="center"><span style=" font-weight:600;">Capture Frequency(HZ):</span></p></body></html></string> - </property> - </widget> - <widget class="QSpinBox" name="Frequency"> - <property name="geometry"> - <rect> - <x>500</x> - <y>60</y> - <width>71</width> - <height>21</height> - </rect> - </property> - <property name="minimum"> - <number>1</number> - </property> - <property name="maximum"> - <number>1000</number> - </property> - </widget> - <widget class="QPushButton" name="CapturePause"> - <property name="geometry"> - <rect> - <x>490</x> - <y>290</y> - <width>101</width> - <height>41</height> - </rect> - </property> - <property name="text"> - <string>Pause</string> - </property> - </widget> - <widget class="QWidget" name="layoutWidget"> - <property name="geometry"> - <rect> - <x>0</x> - <y>70</y> - <width>301</width> - <height>32</height> - </rect> - </property> - <layout class="QHBoxLayout" name="horizontalLayout_8"> - <item> - <widget class="QLabel" name="label_41"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>25</height> - </size> - </property> - <property name="text"> - <string><html><head/><body><p><span style=" font-weight:600;">Channel:</span></p></body></html></string> - </property> - </widget> - </item> - <item> - <widget class="QSpinBox" name="Channel"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>25</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>50</width> - <height>16777215</height> - </size> - </property> - <property name="minimum"> - <number>1</number> - </property> - <property name="maximum"> - <number>4</number> - </property> - <property name="value"> - <number>1</number> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="label_42"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>25</height> - </size> - </property> - <property name="text"> - <string><html><head/><body><p><span style=" font-weight:600;">Data Point:</span></p></body></html></string> - </property> - </widget> - </item> - <item> - <widget class="QSpinBox" name="Points"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>25</height> - </size> - </property> - <property name="minimum"> - <number>1</number> - </property> - <property name="maximum"> - <number>99999</number> - </property> - <property name="value"> - <number>1000</number> - </property> - </widget> - </item> - </layout> - </widget> - <widget class="QLabel" name="label_44"> - <property name="geometry"> - <rect> - <x>330</x> - <y>90</y> - <width>41</width> - <height>16</height> - </rect> - </property> - <property name="text"> - <string><html><head/><body><p><span style=" font-weight:600;">ymult:</span></p></body></html></string> - </property> - </widget> - <widget class="QLabel" name="ymult"> - <property name="geometry"> - <rect> - <x>380</x> - <y>90</y> - <width>54</width> - <height>12</height> - </rect> - </property> - <property name="text"> - <string/> - </property> - </widget> - <widget class="QLabel" name="label_46"> - <property name="geometry"> - <rect> - <x>460</x> - <y>90</y> - <width>51</width> - <height>16</height> - </rect> - </property> - <property name="text"> - <string><html><head/><body><p><span style=" font-weight:600;">yoff:</span></p></body></html></string> - </property> - </widget> - <widget class="QLabel" name="yoff"> - <property name="geometry"> - <rect> - <x>510</x> - <y>90</y> - <width>54</width> - <height>12</height> - </rect> - </property> - <property name="text"> - <string/> - </property> - </widget> - <widget class="QLabel" name="label_47"> - <property name="geometry"> - <rect> - <x>330</x> - <y>120</y> - <width>41</width> - <height>16</height> - </rect> - </property> - <property name="text"> - <string><html><head/><body><p><span style=" font-weight:600;">yzero:</span></p></body></html></string> - </property> - </widget> - <widget class="QLabel" name="yzero"> - <property name="geometry"> - <rect> - <x>380</x> - <y>120</y> - <width>54</width> - <height>12</height> - </rect> - </property> - <property name="text"> - <string/> - </property> - </widget> - <widget class="QLabel" name="label_45"> - <property name="geometry"> - <rect> - <x>460</x> - <y>120</y> - <width>51</width> - <height>16</height> - </rect> - </property> - <property name="text"> - <string><html><head/><body><p><span style=" font-weight:600;">xincr:</span></p></body></html></string> - </property> - </widget> - <widget class="QLabel" name="xincr"> - <property name="geometry"> - <rect> - <x>510</x> - <y>120</y> - <width>54</width> - <height>12</height> - </rect> - </property> - <property name="text"> - <string/> - </property> - </widget> - <widget class="QLabel" name="label_48"> - <property name="geometry"> - <rect> - <x>330</x> - <y>150</y> - <width>41</width> - <height>16</height> - </rect> - </property> - <property name="text"> - <string><html><head/><body><p><span style=" font-weight:600;">xzero:</span></p></body></html></string> - </property> - </widget> - <widget class="QLabel" name="xzero"> - <property name="geometry"> - <rect> - <x>380</x> - <y>150</y> - <width>54</width> - <height>12</height> - </rect> - </property> - <property name="text"> - <string/> - </property> - </widget> - <widget class="QRadioButton" name="Frequency_mode"> - <property name="geometry"> - <rect> - <x>330</x> - <y>30</y> - <width>91</width> - <height>21</height> - </rect> - </property> - <property name="text"> - <string>Frequency</string> - </property> - </widget> - <widget class="QRadioButton" name="step_mode"> - <property name="geometry"> - <rect> - <x>480</x> - <y>30</y> - <width>89</width> - <height>21</height> - </rect> - </property> - <property name="text"> - <string>step</string> - </property> - <property name="checked"> - <bool>true</bool> - </property> - </widget> - <widget class="QLabel" name="label_49"> - <property name="geometry"> - <rect> - <x>330</x> - <y>10</y> - <width>91</width> - <height>16</height> - </rect> - </property> - <property name="text"> - <string><html><head/><body><p align="center"><span style=" font-weight:600;">Capture Mode:</span></p></body></html></string> - </property> - </widget> - </widget> - </widget> - </widget> - <widget class="QMenuBar" name="menubar"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>655</width> - <height>23</height> - </rect> - </property> - </widget> - <widget class="QStatusBar" name="statusbar"/> - </widget> - <resources/> - <connections/> -</ui> diff --git a/motor/GUI/YWidget.ui b/motor/GUI/YWidget.ui deleted file mode 100644 index 44111526a92e9ab17218f4c99ab89952de41f547..0000000000000000000000000000000000000000 --- a/motor/GUI/YWidget.ui +++ /dev/null @@ -1,215 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>Form</class> - <widget class="QWidget" name="Form"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>266</width> - <height>296</height> - </rect> - </property> - <property name="windowTitle"> - <string>Form</string> - </property> - <layout class="QGridLayout" name="gridLayout"> - <item row="7" column="2"> - <widget class="QPushButton" name="Stop"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>40</height> - </size> - </property> - <property name="text"> - <string>Stop</string> - </property> - </widget> - </item> - <item row="10" column="1" colspan="2"> - <widget class="QScrollBar" name="Scroll"> - <property name="maximum"> - <number>299</number> - </property> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="invertedAppearance"> - <bool>true</bool> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="QLabel" name="StatusLabel"> - <property name="text"> - <string/> - </property> - </widget> - </item> - <item row="3" column="1"> - <widget class="QPushButton" name="Home"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>30</height> - </size> - </property> - <property name="text"> - <string>Home</string> - </property> - </widget> - </item> - <item row="2" column="2"> - <widget class="QLabel" name="CurPos"> - <property name="text"> - <string>Current Position:</string> - </property> - </widget> - </item> - <item row="3" column="2"> - <widget class="QLCDNumber" name="CurrentPos"/> - </item> - <item row="7" column="1"> - <widget class="QPushButton" name="Limits"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>40</height> - </size> - </property> - <property name="text"> - <string>Limits</string> - </property> - </widget> - </item> - <item row="4" column="1"> - <widget class="QGroupBox" name="RelativeMove"> - <property name="title"> - <string>Relative Move</string> - </property> - <layout class="QGridLayout" name="gridLayout_2"> - <item row="1" column="0"> - <widget class="QDoubleSpinBox" name="RelativePos"> - <property name="minimumSize"> - <size> - <width>50</width> - <height>0</height> - </size> - </property> - <property name="decimals"> - <number>0</number> - </property> - <property name="minimum"> - <double>-299.000000000000000</double> - </property> - <property name="maximum"> - <double>299.000000000000000</double> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QLabel" name="mm"> - <property name="text"> - <string>um</string> - </property> - </widget> - </item> - <item row="3" column="0" colspan="2"> - <widget class="QPushButton" name="MoveRE"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>30</height> - </size> - </property> - <property name="text"> - <string>Move</string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item row="4" column="2"> - <widget class="QGroupBox" name="AbsoluteMove"> - <property name="title"> - <string>Absolut Move</string> - </property> - <layout class="QGridLayout" name="gridLayout_3"> - <item row="3" column="0"> - <widget class="QDoubleSpinBox" name="DesirePos"> - <property name="minimumSize"> - <size> - <width>50</width> - <height>0</height> - </size> - </property> - <property name="sizeIncrement"> - <size> - <width>0</width> - <height>0</height> - </size> - </property> - <property name="decimals"> - <number>0</number> - </property> - <property name="maximum"> - <double>299.000000000000000</double> - </property> - </widget> - </item> - <item row="3" column="1"> - <widget class="QLabel" name="mm_2"> - <property name="text"> - <string>um</string> - </property> - </widget> - </item> - <item row="4" column="0" colspan="2"> - <widget class="QPushButton" name="MoveAB"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>30</height> - </size> - </property> - <property name="text"> - <string>Move</string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item row="8" column="2"> - <widget class="QPushButton" name="JogMinus"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>40</height> - </size> - </property> - <property name="text"> - <string>Y- Jog</string> - </property> - </widget> - </item> - <item row="8" column="1"> - <widget class="QPushButton" name="JogPlus"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>40</height> - </size> - </property> - <property name="text"> - <string>Y+ Jog</string> - </property> - </widget> - </item> - </layout> - </widget> - <resources/> - <connections/> -</ui> diff --git a/motor/GUI/ZWidget.ui b/motor/GUI/ZWidget.ui deleted file mode 100644 index 6fd59da4691502f9c4246904e65e1c3cafe3cf70..0000000000000000000000000000000000000000 --- a/motor/GUI/ZWidget.ui +++ /dev/null @@ -1,218 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>Form</class> - <widget class="QWidget" name="Form"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>298</width> - <height>266</height> - </rect> - </property> - <property name="windowTitle"> - <string>Form</string> - </property> - <layout class="QGridLayout" name="gridLayout"> - <item row="3" column="2"> - <widget class="QPushButton" name="Home"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>30</height> - </size> - </property> - <property name="text"> - <string>Home</string> - </property> - </widget> - </item> - <item row="2" column="1" rowspan="5"> - <widget class="QScrollBar" name="Scroll"> - <property name="maximum"> - <number>300</number> - </property> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="invertedAppearance"> - <bool>true</bool> - </property> - <property name="invertedControls"> - <bool>true</bool> - </property> - </widget> - </item> - <item row="5" column="3"> - <widget class="QPushButton" name="Limits"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>40</height> - </size> - </property> - <property name="text"> - <string>Limits</string> - </property> - </widget> - </item> - <item row="2" column="3"> - <widget class="QLabel" name="CurPos"> - <property name="text"> - <string>Current Position:</string> - </property> - </widget> - </item> - <item row="2" column="2"> - <widget class="QLabel" name="StatusLabel"> - <property name="text"> - <string/> - </property> - </widget> - </item> - <item row="6" column="2"> - <widget class="QPushButton" name="JogMinus"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>40</height> - </size> - </property> - <property name="text"> - <string>Z- Jog</string> - </property> - </widget> - </item> - <item row="6" column="3"> - <widget class="QPushButton" name="Stop"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>40</height> - </size> - </property> - <property name="text"> - <string>Stop</string> - </property> - </widget> - </item> - <item row="5" column="2"> - <widget class="QPushButton" name="JogPlus"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>40</height> - </size> - </property> - <property name="text"> - <string>Z+ Jog</string> - </property> - </widget> - </item> - <item row="3" column="3"> - <widget class="QLCDNumber" name="CurrentPos"/> - </item> - <item row="4" column="2"> - <widget class="QGroupBox" name="RelativeMove"> - <property name="title"> - <string>Relative Move</string> - </property> - <layout class="QGridLayout" name="gridLayout_2"> - <item row="1" column="0"> - <widget class="QDoubleSpinBox" name="RelativePos"> - <property name="minimumSize"> - <size> - <width>50</width> - <height>0</height> - </size> - </property> - <property name="decimals"> - <number>0</number> - </property> - <property name="minimum"> - <double>-300.000000000000000</double> - </property> - <property name="maximum"> - <double>300.000000000000000</double> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QLabel" name="mm"> - <property name="text"> - <string>um</string> - </property> - </widget> - </item> - <item row="3" column="0" colspan="2"> - <widget class="QPushButton" name="MoveRE"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>30</height> - </size> - </property> - <property name="text"> - <string>Move</string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item row="4" column="3"> - <widget class="QGroupBox" name="AbsoluteMove"> - <property name="title"> - <string>Absolut Move</string> - </property> - <layout class="QGridLayout" name="gridLayout_3"> - <item row="3" column="0"> - <widget class="QDoubleSpinBox" name="DesirePos"> - <property name="minimumSize"> - <size> - <width>50</width> - <height>0</height> - </size> - </property> - <property name="sizeIncrement"> - <size> - <width>0</width> - <height>0</height> - </size> - </property> - <property name="decimals"> - <number>0</number> - </property> - <property name="maximum"> - <double>300.000000000000000</double> - </property> - </widget> - </item> - <item row="3" column="1"> - <widget class="QLabel" name="mm_2"> - <property name="text"> - <string>um</string> - </property> - </widget> - </item> - <item row="4" column="0" colspan="2"> - <widget class="QPushButton" name="MoveAB"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>30</height> - </size> - </property> - <property name="text"> - <string>Move</string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - </layout> - </widget> - <resources/> - <connections/> -</ui> diff --git a/motor/det_lab_stage.py b/motor/det_lab_stage.py deleted file mode 100644 index 46f05772be7320c2dad886d2d2fac9d79567af37..0000000000000000000000000000000000000000 --- a/motor/det_lab_stage.py +++ /dev/null @@ -1,236 +0,0 @@ -#! /usr/bin/env python - -# Reference: -# Luis Ardila leardilap@unal.edu.co 22/03/15 -import sys -from PyQt5 import QtGui, QtCore, uic, QtWidgets - -tctEnable = True -if tctEnable: - import pymotor - -testPass = False - -class Axis(QtWidgets.QWidget): - def __init__(self, parent, Title, Device, uiFile): - super(Axis, self).__init__(parent) - - self.ui = uic.loadUi(uiFile) - - #Declaring Device - if tctEnable: - self.axis = pymotor.Motor(Device) - - #Jogging Plus - self.ui.JogPlus.pressed.connect(self.JogPlus) - self.ui.JogPlus.released.connect(self.Stop) - - #Jogging Minus - self.ui.JogMinus.pressed.connect(self.JogMinus) - self.ui.JogMinus.released.connect(self.Stop) - - #Home - self.ui.Home.clicked.connect(self.Home) - - #Move - self.ui.MoveAB.clicked.connect(self.MoveAB) - self.ui.MoveRE.clicked.connect(self.MoveRE) - - ##Stop - self.ui.Stop.clicked.connect(self.Stop) - - ##Limits - self.ui.Limits.clicked.connect(self.Limits) - - #Scroll - self.ui.Scroll.valueChanged[int].connect(self.UpdateDesiredPosScroll) - - #Updating State - Position - self.timer = QtCore.QTimer() - self.timer.start(100) - self.timer.timeout.connect(self.UpdateState) - self.timer.timeout.connect(self.CurrentPosition) - - ##################### - # Initializing Widget - self.UpdateDesiredPos() - self.ui.setWindowTitle(Title) - - # Var - self.currentPos = 0 - self.Title = Title - self.lenght = self.ui.DesirePos.maximum() - - def JogPlus(self): - if tctEnable: - self.axis.moveforward() - else: - self.ui.StatusLabel.setText("JogPlus") - - def JogMinus(self): - if tctEnable: - self.axis.movebackward() - else: - self.ui.StatusLabel.setText("JogMinus") - - def Home(self): - ret = QtWidgets.QMessageBox.warning(self, "Homming", - "Please Check the setup!\n\nAre you sure you really want\nto Home the motor?", - QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.Cancel | QtWidgets.QMessageBox.Escape) - if ret == QtWidgets.QMessageBox.Yes: - if tctEnable: - self.axis.home() - else: - self.ui.StatusLabel.setText("Home") - - def Stop(self): - if tctEnable: - self.axis.stop() - else: - self.ui.StatusLabel.setText("") - - self.UpdateDesiredPos() - - def Limits(self): - self.Limits = Limits(self) - - def MoveAB(self): - pos = self.ui.DesirePos.value() - if tctEnable: - self.axis.move(pos) - self.ui.CurrentPos.display(self.currentPos) - else: - self.ui.StatusLabel.setText(str(pos)) - self.currentPos = self.ui.DesirePos.value() - self.ui.CurrentPos.display(self.currentPos) - - self.ui.Scroll.setValue(pos) - - def MoveRE(self): - movement = self.ui.RelativePos.value() - UpperLimit = self.ui.DesirePos.maximum() - LowerLimit = self.ui.DesirePos.minimum() - - if self.currentPos + movement > UpperLimit: - movement = UpperLimit - self.currentPos - elif self.currentPos + movement < LowerLimit: - movement = LowerLimit - self.currentPos - - if tctEnable: - self.axis.forward(movement) - else: - self.ui.StatusLabel.setText(str(movement)) - self.currentPos = self.currentPos + movement - self.ui.CurrentPos.display(self.currentPos) - - self.UpdateDesiredPos() - - def UpdateDesiredPosScroll(self): - pos = self.ui.Scroll.value() - self.ui.DesirePos.setValue(pos) - - def UpdateDesiredPos(self): - if tctEnable: - pos = self.axis.get_status_position() - self.ui.DesirePos.setValue(pos) - self.ui.Scroll.setValue(pos) - - def CurrentPosition(self): - if tctEnable: - self.currentPos = self.axis.get_status_position() - self.ui.CurrentPos.display(self.currentPos) - - def UpdateState(self): - if tctEnable and testPass: - state = self.axis.state() - self.ui.StatusLabel.setText(str(state)) - - def run(self): - self.ui.show() - -class Limits(QtWidgets.QDialog): - def __init__(self, parent): - QtWidgets.QDialog.__init__(self, parent) - - # Declaring GUI - self.ui = uic.loadUi('GUI/Limits.ui') - self.ui.show() - self.ui.ButtonBox.accepted.connect(lambda: self.Accepted) - self.ui.UpperLimit.valueChanged.connect(lambda: self.UpdateUpperLimit) - self.ui.LowerLimit.valueChanged.connect(lambda: self.UpdateLowerLimit) - self.ui.setWindowTitle(str(parent.Title + " Limits")) - self.ui.UpperLimit.setMaximum(parent.lenght*2) - self.ui.LowerLimit.setMaximum(parent.lenght*2) - self.ui.UpperLimit.setMinimum(-parent.lenght*2) - self.ui.LowerLimit.setMinimum(-parent.lenght*2) - self.ui.UpperLimit.setValue(parent.ui.DesirePos.maximum()) - self.ui.LowerLimit.setValue(parent.ui.DesirePos.minimum()) - - def UpdateUpperLimit(self, parent): - self.UpperLimit = self.ui.UpperLimit.value() - self.LowerLimit = self.ui.LowerLimit.value() - if self.UpperLimit - self.LowerLimit > parent.lenght: - self.ui.LowerLimit.setValue(self.UpperLimit - parent.lenght) - elif self.UpperLimit <= self.LowerLimit: - self.ui.LowerLimit.setValue(self.UpperLimit - 1) - - def UpdateLowerLimit(self, parent): - self.UpperLimit = self.ui.UpperLimit.value() - self.LowerLimit = self.ui.LowerLimit.value() - if self.LowerLimit + parent.lenght < self.UpperLimit: - self.ui.UpperLimit.setValue(self.LowerLimit + parent.lenght) - elif self.LowerLimit >= self.UpperLimit: - self.ui.UpperLimit.setValue(self.LowerLimit + 1) - - def Accepted(self, parent): - parent.ui.DesirePos.setMaximum(self.ui.UpperLimit.value()) - parent.ui.DesirePos.setMinimum(self.ui.LowerLimit.value()) - parent.ui.Scroll.setMaximum(self.ui.UpperLimit.value()) - parent.ui.Scroll.setMinimum(self.ui.LowerLimit.value()) - -class MainWidget(QtWidgets.QWidget): - def __init__(self, parent=None): - super(MainWidget, self).__init__(parent) - - self.stack = QtWidgets.QStackedWidget() - layout = QtWidgets.QVBoxLayout(self) - layout.addWidget(self.stack) - - ############################################################## - # DETECTOR - # X Detector - XD_Title = "X Detector" - XD_Device = "testxdet" - #XD_Device = "xi-com:///dev/tty.usbmodem00000D81" - XD_uiFile = "GUI/XWidget.ui" - self.XDetector = Axis(self, XD_Title, XD_Device, XD_uiFile) - - ## Y Detector - #YD_Title = "Y Detector" - #YD_Device = "testydet" - #YD_uiFile = "GUI/YWidget.ui" - #self.YDetector = Axis(self, YD_Title, YD_Device, YD_uiFile) - - ## Z Detector - #ZD_Title = "Z Detector" - #ZD_Device = "testzdet" - #ZD_uiFile = "GUI/ZWidget.ui" - #self.ZDetector = Axis(self, ZD_Title, ZD_Device, ZD_uiFile) - - ################################################################ - # MAIN WINDOW - self.stack.addWidget(self.XDetector) - #self.stack.addWidget(self.YDetector) - #self.stack.addWidget(self.ZDetector) - - self.XDetector.run() - #self.YDetector.run() - #self.ZDetector.run() - - -if __name__ == "__main__": - app = QtWidgets.QApplication(sys.argv) - - win = MainWidget() - - sys.exit(app.exec_()) diff --git a/motor/mdo_3034_control.py b/motor/mdo_3034_control.py deleted file mode 100644 index 4edb4aaa36c32223e5e69b54ce20310ab922d30a..0000000000000000000000000000000000000000 --- a/motor/mdo_3034_control.py +++ /dev/null @@ -1,94 +0,0 @@ -import numpy as np -import pandas as pd -import pylab -import re -import time - -try: - import visa -except ImportError as err: - print(err) - exit() - -class MDO3034C: - def __init__(self, resource_name): - instlist=visa.ResourceManager() - #print(instlist.list_resources()) - self.my_resource=instlist.open_resource(resource_name) - - def write_command(self,command): - self.my_resource.write(command) - time.sleep(0.5) - def testIO(self): - #self.my_resource.write('*RST') - self.my_resource.write('*CLS') - #self.my_resource.query_delay = 10.0 - message=self.my_resource.query('*IDN?') - time.sleep(1) - #print("ocsilloscope information:" + message) - return message - - def readSet(self,ch,point_number): - self.my_resource.write(":DATA:SOU "+ ch) - self.my_resource.write(':DATA:START 1') - self.my_resource.write(':DATA:STOP ' + point_number) - self.my_resource.write(':WFMOutpre:ENCdg BINARY') - self.my_resource.write(":WFMOutpre:BYT_Nr 1") - self.my_resource.write(":HEADer 0") - self.my_resource.write(":WFMOutpre?") - - def readOffset(self): - self.write_command('WFMPRE:YMULT?') - ymult = float(self.my_resource.read_raw()) - print("ymult = " + repr(ymult) + '\n') - self.write_command('WFMPRE:YZERO?') - yzero = float(self.my_resource.read_raw()) - print("yzero = " + repr(yzero) + '\n') - self.write_command('WFMPRE:YOFF?') - yoff = float(self.my_resource.read_raw()) - print("yoff = " + repr(yoff) + '\n') - self.write_command('WFMPRE:XINCR?') - xincr = float(self.my_resource.read_raw()) - print("xincr = " + repr(xincr) + '\n') - self.write_command('WFMPRE:XZERO?') - xzero = float(self.my_resource.read_raw()) - print("xzero = " + repr(xzero) + '\n') - return ymult,yzero,yoff,xincr,xzero - - def readWave(self,ymult,yzero,yoff,xincr,xzero,point_num): - #ymult,yzero,yoff,xincr,xzero=self.readOffset() - self.my_resource.write('*CLS') - self.my_resource.write("CURVE?") - #file = open('test.txt','w+') - - ########################################## - # receive data format: - # #510000<data>\n receive 10000 data - # #41000<data>\n receive 1000 data - ######################################### - data = np.frombuffer(self.my_resource.read_raw(),dtype=np.int8,count=int(point_num),offset=len(str(point_num)) + 2) - #np.savetxt('test.txt',data,fmt='%d',delimiter=',') - - print(data.size) - Volts = (data - yoff) * ymult + yzero - Time = np.arange(0, data.size, 1) - Time = Time * xincr + xzero - - return Time, Volts - - def save_wave_data(self,time,voltage,filenames='./data.csv'): - datadic = {'Time[ms]':time,'Voltage[mv]':voltage} - dataform = pd.DataFrame(datadic,columns=['Time[ms]','Voltage[mv]']) - dataform.to_csv(filenames,mode='a+',index=False) - - - def plotWave(self, Time, Volts): - pylab.plot(Time, Volts) - pylab.show() - -def ReadInterface(): - rm = visa.ResourceManager() - print(rm.list_resources()) - list_sources = rm.list_resources() - return list_sources - diff --git a/motor/pymotor.py b/motor/pymotor.py deleted file mode 100644 index bb4fc5c4a9771341a74bc5d091bc0b01a96234b3..0000000000000000000000000000000000000000 --- a/motor/pymotor.py +++ /dev/null @@ -1,211 +0,0 @@ -import ctypes -from ctypes import * -import time -import os -import sys -import re -import platform -#from VitualDevice import * -import tempfile - -cur_dir = os.path.abspath(os.path.dirname(__file__)) -ximc_dir = os.path.join(cur_dir, "..", "ximc") -ximc_package_dir = os.path.join(ximc_dir, "crossplatform", "wrappers", "python") -sys.path.append(ximc_package_dir) # add ximc.py wrapper to python path - -print(ximc_package_dir) - -if platform.system() == "Windows": - print("windows#################") - if platform.architecture() == ('64bit', 'WindowsPE') : - libdir = os.path.join(ximc_dir, "win64") - #print(platform.architecture()) - else: - libdir = os.path.join(ximc_dir,"win32") - #print(platform.architecture()) - - - #print(libdir) -os.environ["Path"] = libdir + ";" + os.environ["Path"] # add dll - -if sys.version_info >= (3,0): - - try: - from pyximc import * - except ImportError as err: - print ("Can't import pyximc module.\ - The most probable reason is that \ - you haven't copied pyximc.py to the working directory.\ - See developers' documentation for details.") - exit() - except OSError as err: - print ("Can't load libximc library.\ - Please add all shared libraries to the appropriate places \ - (next to pyximc.py on Windows). \ - It is decribed in detailes in developers' documentation.") - exit() - -# variable 'lib' points to a loaded library -# note that ximc uses stdcall on win -print("Library loaded") -sbuf = create_string_buffer(64) -lib.ximc_version(sbuf) -print("Library version: " + sbuf.raw.decode()) - -DEBUG = False -def log(s): - if DEBUG: - print(s) - -def enum_device(): - devenum = lib.enumerate_devices(EnumerateFlags.ENUMERATE_PROBE, None) - print("Device enum handle: " + repr(devenum)) - print("Device enum handle type: " + repr(type(devenum))) - - dev_count = lib.get_device_count(devenum) - print("Device count: " + repr(dev_count)) - - controller_name = controller_name_t() - enum_name = ['','',''] - friend_name = ['', '', ''] - for dev_ind in range(0, dev_count): - enum_name[dev_ind] = lib.get_device_name(devenum, dev_ind) - result = lib.get_enumerate_device_controller_name(devenum, dev_ind, - byref(controller_name)) - if result == Result.Ok: - friend_name[dev_ind] = controller_name.ControllerName - print("Enumerated device #{} name (port name): ".format(dev_ind) \ - + repr(enum_name[dev_ind]) \ - + ". Friendly name: " \ - + repr(controller_name.ControllerName) \ - + ".") - - return enum_name, dev_count, friend_name - -class Motor(): - def __init__(self, device_name = None): - self.lib = lib - self.device_id = self.open_device(device_name) - - - def set_speed(self,step,speed): - log("\nset speed\n") - speed_settings = move_settings_t() - speed_settings.Speed = speed - speed_settings.uSpeed = step - speed_settings.Accel = 1000 - speed_settings.Decel = 2000 - speed_settings.AntiplaySpeed = 50 - speed_settings.uAntiplaySpeed = 0 - result = self.lib.set_move_settings(self.device_id,byref(speed_settings)) - print("move settings Result:" + repr(result)) - move_settings = move_settings_t() - result = self.lib.get_move_settings(self.device_id,byref(move_settings)) - if result == 0: - print("move settings:",move_settings.Speed,move_settings.uSpeed,move_settings.Accel,move_settings.Decel) - - - def home(self): - log("\nMoving home") - result = self.lib.command_homezero(self.device_id) - log("Result: " + repr(result)) - - def zero(self): - log("\nzero the position") - result = self.lib.command_zero(self.device_id) - log("Result: " + repr(result)) - - def forward(self, distance): # move forward Deltaposition - log("\nShifting") - log(distance) - dis = ctypes.c_int() - dis.value = int(distance) - move_settings = move_settings_t() - result = self.lib.get_move_settings(self.device_id,byref(move_settings)) - if result == 0: - print("move settings:",move_settings.Speed,move_settings.uSpeed,move_settings.Accel,move_settings.Decel,move_settings.AntiplaySpeed,move_settings.uAntiplaySpeed) - result = self.lib.command_movr(self.device_id, dis, 0) - log("Result: " + repr(result)) - - def backward(self, distance): # move backward Deltaposition - log("\nShifting") - shift = ctypes.c_int() - shift.value = 0 - int(distance) # in oppsite direction - result = self.lib.command_movr(self.device_id, shift, 0) - log("Result: " + repr(result)) - - def moveforward(self): - log("\nMoving forward") - result = self.lib.command_right(self.device_id) - log("Result: " + repr(result)) - - def movebackward(self): - log("\nMoving backward") - result = self.lib.command_left(self.device_id) - log("Result: " + repr(result)) - - def move(self, position): # move to the Setposition - log("\nMoving position") - pos = ctypes.c_int() - pos.value = int(position) - result = self.lib.command_move(self.device_id, pos, 0) - print("Result: " + repr(result)) - - def stop(self): - log("\nStopping") - result = self.lib.command_stop(self.device_id) - log("Result: " + repr(result)) - - def get_position(self): - print("\nRead position") - pos = get_position_t() - result = self.lib.get_position(self.device_id, byref(pos)) - print("Result: " + repr(result)) - if result == Result.Ok: - print("Position: " + repr(pos.Position)) - return pos.Position - - def set_position(self, position): - print("\nSet position") - pos = set_position_t() - pos.Position = position - result = self.lib.set_position(self.device_id, byref(pos)) - print("Result: " + repr(result)) - if result == Result.Ok: - print("Setting Position Done") - - def get_status_position(self): - log("\nGet status") - status = status_t() - result = self.lib.get_status(self.device_id, byref(status)) - log("Result: " + repr(result)) - if result == Result.Ok: - log("Status.CurPosition: " + repr(status.CurPosition)) - return status.CurPosition - - def get_status(self): - log("\nGet status") - status = status_t() - result = self.lib.get_status(self.device_id, byref(status)) - log("Result: " + repr(result)) - if result == Result.Ok: - log("Status.CurPosition: " + repr(status.CurPosition)) - - def get_name(self,devenum,dev_index): - return self.lib.get_device_name(devenum,dev_index) - - - def open_device(self, open_name): - device_id = ctypes.c_int() - print("\nOpen device " + repr(open_name)) - device_id = self.lib.open_device(open_name) - - print("\ndevice id:" + repr(device_id)) - return device_id - - def close_device(self): - result = self.lib.close_device(byref(cast(self.device_id, POINTER(c_int)))) - if result == Result.Ok: - print("Close device " + repr(self.device_id)) - - diff --git a/motor/stage.py b/motor/stage.py deleted file mode 100644 index 0b6c59b9119f14d611f45db6176f71d1f8432eaf..0000000000000000000000000000000000000000 --- a/motor/stage.py +++ /dev/null @@ -1,123 +0,0 @@ -import time -import pymotor - -tctEnable = True - -class Stage(): - def __init__(self,device): - self.Xaxis = device[0] - self.Yaxis = device[1] - self.Zaxis = device[2] - self.flag = 1 - - def SetSpeed(self,step,speed): - self.Xaxis.set_speed(step[0],speed[0]) - self.Yaxis.set_speed(step[1],speed[1]) - self.Zaxis.set_speed(step[2],speed[2]) - - - def Home(self,motor): - if tctEnable: - motor.home() - - def Zero(self,motor): - if tctEnable: - motor.zero() - - def Stop(self): - if tctEnable: - self.Xaxis.stop() - self.Yaxis.stop() - self.Zaxis.stop() - - ''' - def Limits(self): - self.Limits = Limits(self) - ''' - def MoveAB(self,pos_X,pos_Y,pos_Z): - if tctEnable: - self.Xaxis.move(pos_X) - self.Yaxis.move(pos_Y) - self.Zaxis.move(pos_Z) - #waiting for motor moving to (pos_X,pos_Y,pos_Z) - while True: - position_flag = (self.Xaxis.get_status_position() == pos_X) and (self.Yaxis.get_status_position() == pos_Y) and (self.Zaxis.get_status_position() == pos_Z) - if position_flag: - break - - def MoveRE(self,motor,movement): - UpperLimit = 100000 - LowerLimit = -100000 - currentPos = motor.get_status_position() - movePos = currentPos + movement - if currentPos + movement > UpperLimit: - movement = UpperLimit - currentPos - elif currentPos + movement < LowerLimit: - movement = LowerLimit - currentPos - - if tctEnable: - motor.forward(movement) - #wait for accomplishing move - while True: - move_flag = movePos == motor.get_status_position() - if move_flag: - break - - - - def Scan(self,pos_o,dp,Np): - self.x0 = pos_o[0] - self.y0 = pos_o[1] - self.z0 = pos_o[2] - self.dx = dp[0] - self.dy = dp[1] - self.dz = dp[2] - self.Nx = Np[0] - self.Ny = Np[1] - self.Nz = Np[2] - self.scan_signal = False - - #preprocess the situation when Nx = 0 or Ny = 0 or Nz = 0 - if self.Nx == 0: - self.dx = 0 - self.Nx = 1 - if self.Ny == 0: - self.dy = 0 - self.Ny = 1 - if self.Nz == 0: - self.dz = 0 - self.Nz = 1 - - if self.flag == 1: - self.MoveAB(self.x0,self.y0,self.z0) - - # scan step by step - self.flag1 = self.flag2 = -1 - for self.i in range(0, self.Nz): - if self.flag == 0: - break - self.MoveRE(self.Zaxis, self.dz) - if self.dz != 0: - self.scan_signal = True - self.flag1 = self.flag1 * (-1) - for self.j in range(0, self.Nx): - if self.flag == 0: - break - self.MoveRE(self.Xaxis, self.flag1 * self.dx) - if self.dx != 0: - self.scan_signal = True - print(self.Xaxis.get_status_position(),self.Yaxis.get_status_position(),self.Zaxis.get_status_position()) - - self.flag2 = self.flag2 * (-1) - for self.k in range(0, self.Ny): - if self.flag == 0: - break - self.MoveRE(self.Yaxis, self.flag2 * self.dy) - if self.dy != 0: - self.scan_signal = True - #time.sleep(1) - print(self.Xaxis.get_status_position(),self.Yaxis.get_status_position(),self.Zaxis.get_status_position()) - #print(self.ui.CurrentPosX_2.value(),self.ui.CurrentPosY_2.value(),self.ui.CurrentPosZ_2.value()) - #self.timer.timeout.connect(self.UpdateDesiredPos) - #self.timer.start(100) - #self.UpdateDesiredPos() \ No newline at end of file diff --git a/motor/tct_control.py b/motor/tct_control.py deleted file mode 100644 index a1593240bc4781dba519e6eee16e57572d926038..0000000000000000000000000000000000000000 --- a/motor/tct_control.py +++ /dev/null @@ -1,348 +0,0 @@ -#! /usr/bin/env python - -#reference: -#Luis Ardila leardilap@unal.edu.co 22/03/15 - -#Liejian Chen - -import sys,time -import numpy -from PyQt5 import QtGui, QtCore, uic, QtWidgets - -tctEnable = True -if tctEnable: - import pymotor - import thread - import raser.motor.mdo_3034_control as mdo_3034_control - import raser.motor.vitual_device as vitual_dev - -testpass = False -""" -扫æ时默认æ¯ä¸€ä¸ªæ‰«æç‚¹é‡‡é›†ä¸€æ¬¡æ•°æ® -如需在æ¯ä¸ªç‚¹é‡‡é›†å¤šæ¬¡æ•°æ®ï¼Œè¯·åœ¨è¿è¡Œç¨‹åºæ—¶åŠ ä¸ŠåŠ ä¸Šæ¯ä¸ªé‡‡é›†ç‚¹éœ€è¦é‡‡é›†æ•°æ®çš„次数 -例: -æ¯ä¸ªé‡‡é›†ç‚¹åªéœ€è¦é‡‡é›†1次数æ®ï¼špython TCTControl.py -æ¯ä¸ªé‡‡é›†ç‚¹éœ€è¦é‡‡é›†50次数æ®ï¼špython TCTControl.py 50 -""" -if len(sys.argv)==2: - count_2=int(sys.argv[1]) -else: - count_2=1 - - -class MainWidget(QtWidgets.QWidget): - SignalCapture = QtCore.pyqtSignal() - SignalScanContinue = QtCore.pyqtSignal() - def __init__(self, parent=None): - super(MainWidget, self).__init__(parent) - - - ################################################ - #initialize the device information,search usable device - self.EmumDevice() - - self.uiFile = "GUI/XYZWidget.ui" - self.ui = uic.loadUi(self.uiFile) - self.Title = "TCT Control" - ############################################################## - self.timer = QtCore.QTimer() - self.timer.start(500) - self.SetMotor() - self.SpeedMode() - self.ui.Interface.addItems(mdo_3034_control.ReadInterface()) - - - #Move - self.ui.MoveButton.clicked.connect(lambda:self.ClickMove(int(self.ui.SetPosX.text()), int(self.ui.SetPosY.text()), int(self.ui.SetPosZ.text()))) - - #Step move X - self.ui.XPlus.clicked.connect(lambda:self.MoveStep("X",1,self.ui.StepMoveX.value())) - self.ui.XMinus.clicked.connect(lambda:self.MoveStep("X",-1,self.ui.StepMoveX.value())) - - #Step move Y - self.ui.YPlus.clicked.connect(lambda:self.MoveStep("Y",1,self.ui.StepMoveY.value())) - self.ui.YMinus.clicked.connect(lambda:self.MoveStep("Y",-1,self.ui.StepMoveY.value())) - - #Step move Z - self.ui.ZPlus.clicked.connect(lambda:self.MoveStep("Z",1,self.ui.StepMoveZ.value())) - self.ui.ZMinus.clicked.connect(lambda:self.MoveStep("Z",-1,self.ui.StepMoveZ.value())) - - #Home - self.ui.ResetPosX.clicked.connect(lambda:self.Home("X")) - self.ui.ResetPosY.clicked.connect(lambda:self.Home("Y")) - self.ui.ResetPosZ.clicked.connect(lambda:self.Home("Z")) - - #Zero - self.ui.zeroX.clicked.connect(lambda:self.Zero("X")) - self.ui.zeroY.clicked.connect(lambda:self.Zero("Y")) - self.ui.zeroZ.clicked.connect(lambda:self.Zero("Z")) - - #scan - self.ui.ScanBut.clicked.connect(self.Scan) - self.SignalScanContinue.connect(self.ScanContinue) - - #Stop - self.ui.StopBut.clicked.connect(self.Stop) - self.ui.ScanStop.clicked.connect(self.ScanStop) - - #set motor - self.ui.SetMotor.clicked.connect(self.SetMotor) - - #set speed - self.ui.default_speed.toggled.connect(self.SpeedMode) - self.ui.setting_speed.toggled.connect(self.SpeedMode) - self.ui.Set_Speed.clicked.connect(lambda:self.SetSpeed(False)) - - #set folder - self.ui.FolderSet.clicked.connect(self.SetFolder) - - #capture data - self.ui.CaptureBut.clicked.connect(self.SaveData) - self.SignalCapture.connect(lambda:self.CaptureMode(True)) - - #capture pause - self.ui.CapturePause.clicked.connect(self.CapturePause) - - #Capture ready - self.ui.ReadyBut.clicked.connect(self.Ready) - - # Var - self.currentPosX = 0 - self.currentPosY = 0 - self.currentPosZ = 0 - - ##################### - # Initializing Widget - self.UpdateDesiredPos() - self.ui.setWindowTitle(self.Title) - self.timer.timeout.connect(self.UpdateDesiredPos) - - - self.ui.show() - - def ClickMove(self,px,py,pz): - self.new_thread = thread.ControlThread(self.setdevice) - self.new_thread.operation_num = 3 - self.new_thread.px = px - self.new_thread.py = py - self.new_thread.pz = pz - self.new_thread.start() - - def MoveStep(self,motor,direction,steps): - self.new_thread = thread.ControlThread(self.setdevice) - self.new_thread.operation_num = 4 - self.new_thread.mv = direction*steps - if motor == "X": - self.new_thread.motor = self.new_thread.laser_stage.Xaxis - elif motor == "Y": - self.new_thread.motor = self.new_thread.laser_stage.Yaxis - elif motor == "Z": - self.new_thread.motor = self.new_thread.laser_stage.Zaxis - else: - print("\n\n\nError!!!!!!!\n\n\n") - self.new_thread.start() - - def Home(self,motor): - self.new_thread = thread.ControlThread(self.setdevice) - self.new_thread.operation_num = 1 - if motor == "X": - self.new_thread.motor = self.new_thread.laser_stage.Xaxis - elif motor == "Y": - self.new_thread.motor = self.new_thread.laser_stage.Yaxis - elif motor == "Z": - self.new_thread.motor = self.new_thread.laser_stage.Zaxis - else: - print("\n\n\nError!!!!!!!\n\n\n") - self.new_thread.start() - - def Zero(self,motor): - self.new_thread = thread.ControlThread(self.setdevice) - self.new_thread.operation_num = 5 - if motor == "X": - self.new_thread.motor = self.new_thread.laser_stage.Xaxis - elif motor == "Y": - self.new_thread.motor = self.new_thread.laser_stage.Yaxis - elif motor == "Z": - self.new_thread.motor = self.new_thread.laser_stage.Zaxis - else: - print("\n\n\nError!!!!!!!\n\n\n") - self.new_thread.start() - - - def Scan(self): - self.scan_thread = thread.ScanThread(self.setdevice) - self.scan_thread.flag = True - self.scan_thread.pos_o = [self.ui.x0.value(),self.ui.y0.value(),self.ui.z0.value()] - self.scan_thread.dp = [self.ui.dx.value(),self.ui.dy.value(),self.ui.dz.value()] - self.scan_thread.Np = [self.ui.Nx.value(),self.ui.Ny.value(),self.ui.Nz.value()] - self.scan_thread.start() - print(111) - - def ScanContinue(self): - self.scan_thread.continue_flag = True - - def SetMotor(self): - self.setdevice = numpy.empty(3,dtype=object) - self.setdevice[0] = self.device[self.ui.X_Motor_Num.value()-1] - self.setdevice[1] = self.device[self.ui.Y_Motor_Num.value()-1] - self.setdevice[2] = self.device[self.ui.Z_Motor_Num.value()-1] - print(self.setdevice) - - def SetSpeed(self,default): - self.steps = numpy.empty(3,dtype=int) - self.speed = numpy.empty(3,dtype=int) - if default: - self.steps = [0,0,0] - self.speed = [1000,1000,1000] - else: - self.steps[0] = self.ui.Step_X.value() - self.steps[1] = self.ui.Step_Y.value() - self.steps[2] = self.ui.Step_Z.value() - self.speed[0] = self.ui.Speed_X.value() - self.speed[1] = self.ui.Speed_Y.value() - self.speed[2] = self.ui.Speed_Z.value() - self.new_thread = thread.ControlThread(self.setdevice) - self.new_thread.operation_num = 6 - self.new_thread.step = self.steps - self.new_thread.speed = self.speed - self.new_thread.start() - self.new_thread.wait() - - def SpeedMode(self): - if self.ui.setting_speed.isChecked(): - self.ui.Set_Speed.setEnabled(True) - if self.ui.default_speed.isChecked(): - self.ui.Set_Speed.setEnabled(False) - self.SetSpeed(True) - - - def Stop(self): - self.new_thread = thread.ControlThread(self.setdevice) - self.new_thread.operation_num = 2 - self.new_thread.start() - - def ScanStop(self): - self.scan_thread.flag = False - - - - def EmumDevice(self): - pymotor.enum_device() - print('\nemum complete!\n') - self.device_name ,self.dev_count, self.friend_name = pymotor.enum_device() - self.device = numpy.empty(5,dtype=object) - if self.dev_count == 0: - print("\nNo finding of device.") - print("\nUse the vitual device:\n") - self.device_name = ["testxmotor","testymotor","testzmotor"] - self.i = 0 - for self.str_device in self.device_name: - print('str_device:'+self.str_device) - self.device[self.i] = vitual_dev.VitualDevice(self.device_name[self.i]) - print('device[]' + str(self.device[self.i])) - #self.testmotor = pymotor.Motor(vitual_dev.VitualDevice(self.str_device).open_name) - #self.testmotor.move(10) - self.i = self.i + 1 - else: - for self.dev_ind in range(0,self.dev_count): - if 'Axis 1' in repr(self.friend_name[self.dev_ind]): self.device[0] =pymotor.Motor(self.device_name[self.dev_ind]) - if 'Axis 2' in repr(self.friend_name[self.dev_ind]): self.device[1] =pymotor.Motor(self.device_name[self.dev_ind]) - if 'Axis 3' in repr(self.friend_name[self.dev_ind]): self.device[2] =pymotor.Motor(self.device_name[self.dev_ind]) - print(self.device) - - - - def CurrentPosition(self): - if tctEnable: - self.currentPosX = self.setdevice[0].get_status_position() - self.currentPosY = self.setdevice[1].get_status_position() - self.currentPosZ = self.setdevice[2].get_status_position() - - def UpdateDesiredPos(self): - if tctEnable: - self.CurrentPosition() - self.ui.CurrentPosX.display(self.currentPosX) - self.ui.CurrentPosX_2.display(self.currentPosX) - self.ui.CurrentPosY.display(self.currentPosY) - self.ui.CurrentPosY_2.display(self.currentPosY) - self.ui.CurrentPosZ.display(self.currentPosZ) - self.ui.CurrentPosZ_2.display(self.currentPosZ) - #self.timer.start(500) - def SetFolder(self): - dlg = QtWidgets.QFileDialog() - dlg.setFileMode(QtWidgets.QFileDialog.Directory) - dlg.setFilter(QtCore.QDir.Files) - if dlg.exec_(): - filenames = dlg.selectedFiles() - print(repr(filenames)) - self.ui.FolderText.setText(filenames[0]) - - def SaveData(self): - if self.ui.Frequency_mode.isChecked() == True: - self.CaptureMode(False) - if self.ui.step_mode.isChecked() == True: - self.Scan() - self.scan_thread.CaptureSignal.connect(self.StepCapture) - - def StepCapture(self): - print("capture\n") - self.scan_thread.continue_flag = False #let scan thread wait - self.SignalCapture.emit() - - def CaptureMode(self,mode): - for i in range(0,count_2): - self.capture_thread = thread.DataCapture() - self.capture_thread.flag = True - self.capture_thread.stepmode_flag = mode - self.capture_thread.resource = self.ui.Interface.currentText() - self.capture_thread.folder = self.ui.FolderText.text() - self.capture_thread.device = self.setdevice - self.capture_thread.frequency = self.ui.Frequency.value() - self.capture_thread.point_num = self.ui.Points.value() - self.capture_thread.ymult = float(self.ui.ymult.text()) - self.capture_thread.yzero = float(self.ui.yzero.text()) - self.capture_thread.yoff = float(self.ui.yoff.text()) - self.capture_thread.xincr = float(self.ui.xincr.text()) - self.capture_thread.xzero = float(self.ui.xzero.text()) - self.capture_thread.scope = self.scope - self.capture_thread.info = self.oscilloscope_info - self.capture_thread.start() - self.capture_thread.scan_signal.connect(self.SignalScanContinue.emit) - print(i) - time.sleep(0.2) - #self.capture_thread.wait() - - def CapturePause(self): - self.capture_thread.flag = False - self.ScanStop() - #self.scope.close_resource() - - - - def Ready(self): - self.readythread = thread.ReadyThread() - self.readythread.resource_name = self.ui.Interface.currentText() - self.readythread.channel = self.ui.Channel.value() - self.readythread.point_number = self.ui.Points.value() - self.readythread.start() - self.readythread.sinOut.connect(self.DisplayReadyInfo) - - def DisplayReadyInfo(self,dis_message): - if dis_message == "offset": - self.ui.InfoText.append(self.readythread.message) - self.ui.ymult.setText(str(self.readythread.ymult)) - self.ui.yzero.setText(str(self.readythread.yzero)) - self.ui.yoff.setText(str(self.readythread.yoff)) - self.ui.xincr.setText(str(self.readythread.xincr)) - self.ui.xzero.setText(str(self.readythread.xzero)) - elif dis_message == "open": - self.scope = self.readythread.scope - self.oscilloscope_info = self.readythread.message - self.ui.InfoText.append(self.readythread.message) - else: - self.ui.InfoText.append(self.readythread.message) - -if __name__ == "__main__": - app = QtWidgets.QApplication(sys.argv) - win = MainWidget() - sys.exit(app.exec_()) diff --git a/motor/test_combine.py b/motor/test_combine.py deleted file mode 100644 index 03745a28c73b43327365d6aca0942fcf28377864..0000000000000000000000000000000000000000 --- a/motor/test_combine.py +++ /dev/null @@ -1,184 +0,0 @@ -#! /usr/bin/env python - -#reference: -#Luis Ardila leardilap@unal.edu.co 22/03/15 - -#Liejian Chen - -import sys,time -import numpy -from PyQt5 import QtGui, QtCore, uic, QtWidgets - -tctEnable = True -if tctEnable: - import pymotor - import raser.motor.vitual_device as vitual_dev - -testpass = False - - -class MainWidget(QtWidgets.QWidget): - def __init__(self, parent=None): - super(MainWidget, self).__init__(parent) - - ################################################ - #initialize the device information,search usable device - self.InitEmum() - - self.uiFile = "GUI/XYZWidget.ui" - self.ui = uic.loadUi(self.uiFile) - self.Title = "XYZ Motor" - ############################################################## - self.timer = QtCore.QTimer() - - #Declaring Device - self.SetMotor() - - #Move - self.ui.MoveButton.clicked.connect(lambda:self.MoveAB(int(self.ui.SetPosX.text()), int(self.ui.SetPosY.text()), int(self.ui.SetPosZ.text()))) - - #Step move X - self.ui.XPlus.clicked.connect(lambda:self.MoveRE(self.Xaxis,self.ui.StepMoveX.value())) - self.ui.XMinus.clicked.connect(lambda:self.MoveRE(self.Xaxis,-self.ui.StepMoveX.value())) - - #Step move Y - self.ui.YPlus.clicked.connect(lambda:self.MoveRE(self.Yaxis,self.ui.StepMoveY.value())) - self.ui.YMinus.clicked.connect(lambda:self.MoveRE(self.Yaxis,-self.ui.StepMoveY.value())) - - #Step move Z - self.ui.ZPlus.clicked.connect(lambda:self.MoveRE(self.Zaxis,self.ui.StepMoveZ.value())) - self.ui.ZMinus.clicked.connect(lambda:self.MoveRE(self.Zaxis,-self.ui.StepMoveZ.value())) - - #Home - self.ui.ResetPosX.clicked.connect(lambda:self.Home(self.Xaxis)) - self.ui.ResetPosY.clicked.connect(lambda:self.Home(self.Yaxis)) - self.ui.ResetPosZ.clicked.connect(lambda:self.Home(self.Zaxis)) - - #scan - self.ui.ScanBut.clicked.connect(lambda:self.Scan(self.Xaxis,self.Yaxis,self.Zaxis)) - - #set motor - self.ui.SetMotor.clicked.connect(self.SetMotor) - - # Var - self.currentPosX = 0 - self.currentPosY = 0 - self.currentPosZ = 0 - - ##################### - # Initializing Widget - self.UpdateDesiredPos() - self.ui.setWindowTitle(self.Title) - self.ui.show() - - def InitEmum(self): - pymotor.enum_device() - print('\nemum complete!\n') - self.devenum ,self.dev_count = pymotor.enum_device() - self.device = numpy.empty(5,dtype=object) - if self.dev_count == 0: - print("\nNo finding of device.") - print("\nUse the vitual device:\n") - self.device_name = ["testxmotor","testymotor","testzmotor"] - self.i = 0 - for self.str_device in self.device_name: - print('str_device:'+self.str_device) - self.device[self.i] = vitual_dev.VitualDevice(self.device_name[self.i]) - print('device[]' + str(self.device[self.i])) - self.i = self.i + 1 - else: - for self.dev_ind in range(0,self.dev_count): - self.device[self.dev_count] =pymotor.Motor(pymotor.Motor.get_name(self,self.devenum,self.dev_ind)) - - def Home(self,motor): - ret = QtWidgets.QMessageBox.warning(self, "Homming", - "Please Check the setup!\n\nAre you sure you really want\nto Home the motor?", - QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.Cancel | QtWidgets.QMessageBox.Escape) - if ret == QtWidgets.QMessageBox.Yes: - if tctEnable: - motor.home() - else: - self.ui.StatusLabel.setText("Home") - self.UpdateDesiredPos() - - def Stop(self): - if tctEnable: - self.Xaxis.stop() - else: - self.ui.StatusLabel.setText("") - - self.UpdateDesiredPos() - ''' - def Limits(self): - self.Limits = Limits(self) - ''' - def MoveAB(self,pos_X,pos_Y,pos_Z): - if tctEnable: - self.Xaxis.move(pos_X) - self.Yaxis.move(pos_Y) - self.Zaxis.move(pos_Z) - self.UpdateDesiredPos() - - def MoveRE(self,motor,movement): - UpperLimit = 100 - LowerLimit = -100 - currentPos = motor.get_status_position() - if currentPos + movement > UpperLimit: - movement = UpperLimit - currentPos - elif currentPos + movement < LowerLimit: - movement = LowerLimit - currentPos - - if tctEnable: - motor.forward(movement) - time.sleep(0.1) - self.UpdateDesiredPos() - - def Scan(self,motor1,motor2,motor3): - self.x0 = self.ui.x0.value() - self.y0 = self.ui.y0.value() - self.z0 = self.ui.z0.value() - self.dx = self.ui.dx.value() - self.dy = self.ui.dy.value() - self.dz = self.ui.dz.value() - self.Nx = self.ui.Nx.value() - self.Ny = self.ui.Ny.value() - self.Nz = self.ui.Nz.value() - - self.MoveAB(self.x0,self.y0,self.z0) - #delay 1 second for motor moving to (x0,y0.z0) - time.sleep(2) - - for self.PZ in range(self.z0, self.z0 + ((self.Nz + 1) * self.dz) , self.dz): - for self.PX in range(self.x0, self.x0 + ((self.Nx + 1) * self.dx) , self.dx): - for self.PY in range(self.y0, self.y0 + ((self.Ny + 1) * self.dy) , self.dy): - self.MoveAB(self.PX, self.PY, self.PZ) - print(self.Xaxis.get_status_position(),self.Yaxis.get_status_position(),self.Zaxis.get_status_position()) - self.timer.timeout.connect(self.UpdateDesiredPos) - self.timer.start(100) - #time.sleep(0.1) - - def SetMotor(self): - self.Xaxis = self.device[self.ui.X_Motor_Num.value()-1] - self.Yaxis = self.device[self.ui.Y_Motor_Num.value()-1] - self.Zaxis = self.device[self.ui.Z_Motor_Num.value()-1] - - def CurrentPosition(self): - if tctEnable: - self.currentPosX = self.Xaxis.get_status_position() - self.currentPosY = self.Yaxis.get_status_position() - self.currentPosZ = self.Zaxis.get_status_position() - def UpdateDesiredPos(self): - if tctEnable: - self.CurrentPosition() - self.ui.CurrentPosX.display(self.currentPosX) - self.ui.CurrentPosX_2.display(self.currentPosX) - self.ui.CurrentPosY.display(self.currentPosY) - self.ui.CurrentPosY_2.display(self.currentPosY) - self.ui.CurrentPosZ.display(self.currentPosZ) - self.ui.CurrentPosZ_2.display(self.currentPosZ) - self.timer.start(100) - -if __name__ == "__main__": - app = QtWidgets.QApplication(sys.argv) - win = MainWidget() - sys.exit(app.exec_()) diff --git a/motor/thread.py b/motor/thread.py deleted file mode 100644 index 043a15fb93719cd04680fa125a4b5453588e8750..0000000000000000000000000000000000000000 --- a/motor/thread.py +++ /dev/null @@ -1,205 +0,0 @@ -import pymotor,stage,raser.motor.vitual_device as vitual_device -import raser.motor.mdo_3034_control as MD -import time -from datetime import datetime -import numpy as np -from PyQt5 import QtCore - -class ControlThread(QtCore.QThread): - def __init__(self,device): - super(ControlThread,self).__init__() - self.laser_stage = stage.Stage(device) - #control message initial - self.operation_num = 0 - self.motor = self.laser_stage.Xaxis - self.px = 0 - self.py = 0 - self.pz = 0 - self.mv = 0 - self.po = [0,0,0] - self.dp = [1,1,1] - self.Np = [0,0,0] - self.step = [8,8,8] - self.speed = [0,0,0] - - ############################# - # 1.home - # 2.stop - # 3.move set position - # 4.move step - # 5.zero - # 6.set speed - ############################ - def run(self): - if self.operation_num == 1: - self.laser_stage.Home(self.motor) - elif self.operation_num == 2: - self.laser_stage.Stop() - elif self.operation_num == 3: - self.laser_stage.MoveAB(self.px,self.py,self.pz) - elif self.operation_num == 4: - self.laser_stage.MoveRE(self.motor,self.mv) - elif self.operation_num == 5: - self.laser_stage.Zero(self.motor) - elif self.operation_num == 6: - self.laser_stage.SetSpeed(self.step,self.speed) - else: - time.sleep(1) - -class DataCapture(QtCore.QThread): - stop_signal = QtCore.pyqtSignal(str) - scan_signal = QtCore.pyqtSignal() - def __init__(self): - super(DataCapture,self).__init__() - self.resource = 'ASRL1::INSTR' - self.folder = './' - self.device = [] - self.frequency = 10 - self.point_num = 10000 - self.ymult = 0 - self.yoff = 0 - self.yzero = 0 - self.xincr = 0 - self.xzero = 0 - self.stepmode_flag = True - self.flag = True - self.scope = None - self.info = '' - - def capture(self): - filename = self.folder + '/TCT' + datetime.now().isoformat().replace(':','') + '.csv' - self.pos = [self.device[0].get_status_position(),self.device[1].get_status_position(),self.device[2].get_status_position()] - time,voltage = self.scope.readWave(self.ymult,self.yzero,self.yoff,self.xincr,self.xzero,self.point_num) - myfile = open(filename,'w+') - myfile.write('oscilloscope,' + self.info + '\n') - myfile.write(',' + 'x' + ',' + str(self.pos[0]) + '\n') - myfile.write(',' + 'y' + ',' + str(self.pos[1]) + '\n') - myfile.write(',' + 'z' + ',' + str(self.pos[2]) + '\n') - self.scope.save_wave_data(time,voltage,myfile) - print("capture done!") - myfile.close() - - if self.flag == False: - self.stop_signal.emit('stop') - #print("pause##########") - #self.timer.stop() - #self.finished() - self.scan_signal.emit() #emit scan continue signal - - def run(self): - self.timer = QtCore.QTimer() - if self.stepmode_flag: - time.sleep(0.1) - self.capture() - else: - self.timer.start(int(1000/self.frequency)) - self.info = self.scope.testIO() - self.timer.timeout.connect(self.capture) - self.stop_signal.connect(self.timer.stop) - self.exec() - - -class ReadyThread(QtCore.QThread): - sinOut = QtCore.pyqtSignal(str) - def __init__(self): - super(ReadyThread,self).__init__() - self.resource_name = '' - self.channel = 1 - self.point_number = 10000 - self.message = 'Nothing has done!' - - def run(self): - self.scope = MD.MDO3034C(self.resource_name) - msg = self.scope.testIO() - self.message = "ocsilloscope information:" + msg - self.sinOut.emit('open') - self.scope.readSet('ch' + str(self.channel),str(self.point_number)) - self.message = "read set complete!" - self.sinOut.emit('readset') - self.ymult,self.yzero,self.yoff,self.xincr,self.xzero = self.scope.readOffset() - self.message = "read offset complete!" - self.sinOut.emit('offset') - -class ScanThread(QtCore.QThread): - CaptureSignal = QtCore.pyqtSignal(str) - def __init__(self,device): - super(ScanThread,self).__init__() - self.laser_stage = stage.Stage(device) - self.pos_o = [0,0,0] - self.dp = [1,1,1] - self.Np = [0,0,0] - self.flag = False #stop flag - self.continue_flag = True - - def scan(self): - self.x0 = self.pos_o[0] - self.y0 = self.pos_o[1] - self.z0 = self.pos_o[2] - self.dx = self.dp[0] - self.dy = self.dp[1] - self.dz = self.dp[2] - self.Nx = self.Np[0] - self.Ny = self.Np[1] - self.Nz = self.Np[2] - #preprocess the situation when Nx = 0 or Ny = 0 or Nz = 0 - if self.Nx == 0: - self.dx = 0 - self.Nx = 1 - if self.Ny == 0: - self.dy = 0 - self.Ny = 1 - if self.Nz == 0: - self.dz = 0 - self.Nz = 1 - - if self.flag: - self.laser_stage.MoveAB(self.x0,self.y0,self.z0) - print("move ab\n") - - # scan step by step - self.flag1 = self.flag2 = -1 - for self.i in range(0, self.Nz): - if self.flag == False: - print("break\n") - break - if self.dy == 0: self.laser_stage.MoveAB(self.x0, self.laser_stage.Yaxis.get_status_position(), self.laser_stage.Zaxis.get_status_position()) - if self.dx == 0: self.laser_stage.MoveAB(self.laser_stage.Xaxis.get_status_position(), self.y0, self.laser_stage.Zaxis.get_status_position()) - self.laser_stage.MoveRE(self.laser_stage.Zaxis, self.dz) - if self.dz != 0: - self.CaptureSignal.emit('capture') #one step move complete,emit capture signal - time.sleep(0.1) - while True: - if self.continue_flag: - break - - self.flag1 = self.flag1 * (-1) - for self.j in range(0, self.Nx): - if self.flag == False: - print("break\n") - break - if self.dz == 0: self.laser_stage.MoveAB(self.laser_stage.Xaxis.get_status_position(), self.y0, self.laser_stage.Zaxis.get_status_position()) # x-y scan - self.laser_stage.MoveRE(self.laser_stage.Xaxis, self.dx) - if self.dx != 0: - self.CaptureSignal.emit('capture') - time.sleep(0.1) - while True: - if self.continue_flag: - break - print(self.laser_stage.Xaxis.get_status_position(),self.laser_stage.Yaxis.get_status_position(),self.laser_stage.Zaxis.get_status_position()) - - self.flag2 = self.flag2 * (-1) - for self.k in range(0, self.Ny): - if self.flag == False: - print("break\n") - break - self.laser_stage.MoveRE(self.laser_stage.Yaxis, self.dy) - if self.dy != 0: - self.CaptureSignal.emit('capture') - time.sleep(0.1) - while True: - if self.continue_flag: - break - print(self.laser_stage.Xaxis.get_status_position(),self.laser_stage.Yaxis.get_status_position(),self.laser_stage.Zaxis.get_status_position()) - - def run(self): - self.scan() diff --git a/motor/vitual_device.py b/motor/vitual_device.py deleted file mode 100644 index d72422fd97b2378c9eacc6de1639ff11f56d3bc0..0000000000000000000000000000000000000000 --- a/motor/vitual_device.py +++ /dev/null @@ -1,29 +0,0 @@ -#this file is used to make a vitual device - -import pymotor -import sys -import os -import re -import tempfile -import urllib.parse - -class VitualDevice(pymotor.Motor): - def __init__(self,device_name): - if sys.version_info < (3,0): - print("Using virtual device needs python3!") - exit(1) - - # use URI for virtual device when there is new urllib python3 API - tempdir = tempfile.gettempdir() + "/" + str(device_name)+ ".bin" - print("\ntempdir: " + tempdir) - # "\" <-> "/" - if os.altsep: - tempdir = tempdir.replace(os.sep, os.altsep) - - uri = urllib.parse.urlunparse(urllib.parse.ParseResult \ - (scheme="file",netloc=None, path=tempdir,\ - params=None, query=None, fragment=None)) - # converter address to b - self.open_name = re.sub(r'^file', 'xi-emu', uri).encode() - super(VitualDevice,self).__init__(self.open_name) - diff --git a/particle/__init__.py b/particle/__init__.py index 6dfde866ecc0968ecbbc9fce0b9aba666228863a..49f24a520178ca201f7c2fc9bac62fbb706fbbed 100644 --- a/particle/__init__.py +++ b/particle/__init__.py @@ -1,4 +1,4 @@ -from . import * + def main(kwargs): label = kwargs['label'] if label == 'temperature': @@ -10,7 +10,7 @@ def main(kwargs): cflm.main() elif label == "test": from . import g4_sic_energy_deposition - command="./paras/g4macro/gui.mac" + command="./param_file/g4macro/gui.mac" g4_sic_energy_deposition.main() else: raise NameError(label) \ No newline at end of file diff --git a/particle/cflm.py b/particle/cflm.py index 5fa9f2d6588cb67eae8ef882d2b4420062d6dff5..4640a0c2ebca58cf3e59937f984dbe5143a05ea2 100755 --- a/particle/cflm.py +++ b/particle/cflm.py @@ -299,7 +299,7 @@ def main(): UImanager = g4b.G4UImanager.GetUIpointer() - UImanager.ApplyCommand("/control/execute paras/g4macro/init_vis.mac") + UImanager.ApplyCommand("/control/execute param_file/g4macro/init_vis.mac") UImanager.ApplyCommand('/run/initialize') UImanager.ApplyCommand('/tracking/verbose 2') diff --git a/particle/g4_sic_energy_deposition.py b/particle/g4_sic_energy_deposition.py index 9d790de73ffe37cd027bd08de256ddd96b78470b..64f660d5d36ba3fdacbe746bdd7d8fcf114d7887 100755 --- a/particle/g4_sic_energy_deposition.py +++ b/particle/g4_sic_energy_deposition.py @@ -317,7 +317,7 @@ def main(): UImanager = g4b.G4UImanager.GetUIpointer() - UImanager.ApplyCommand("/control/execute paras/g4macro/init_vis.mac")#åˆå§‹åŒ–å¯è§†åŒ–é…ç½® + UImanager.ApplyCommand("/control/execute param_file/g4macro/init_vis.mac")#åˆå§‹åŒ–å¯è§†åŒ–é…ç½® UImanager.ApplyCommand('/run/initialize')#åˆå§‹åŒ–è¿è¡Œï¼Œå‡†å¤‡å¼€å§‹æ¨¡æ‹Ÿ UImanager.ApplyCommand("/gun/particle ion") diff --git a/particle/g4si_itk.py b/particle/g4si_itk.py index 350c6b6837977c2a194ff60bfec73ca2cb2ac2ae..c68e5207bfb25b7e021980aacb830d6ffd01c272 100644 --- a/particle/g4si_itk.py +++ b/particle/g4si_itk.py @@ -41,7 +41,7 @@ class SiITk: visManager = g4b.G4VisExecutive() visManager.Initialize() UImanager = g4b.G4UImanager.GetUIpointer() - UImanager.ApplyCommand('/control/execute paras/g4macro/init_vis.mac') + UImanager.ApplyCommand('/control/execute param_file/g4macro/init_vis.mac') else: UImanager = g4b.G4UImanager.GetUIpointer() UImanager.ApplyCommand('/run/initialize') diff --git a/particle/g4simulation.py b/particle/g4simulation.py index 71e303d0a8b12c7a3f53f0a0dd9fa0ad668e2077..42396202909a4bd35b622b86d26c9f9e9a03e725 100644 --- a/particle/g4simulation.py +++ b/particle/g4simulation.py @@ -19,6 +19,8 @@ import random import json +verbose = 0 + # Geant4 main process class Particles: #model name for other class to use @@ -27,7 +29,7 @@ class Particles: #use in pixel_detector _randx = None _randy = None - def __init__(self, my_d, absorber, g4_seed): + def __init__(self, my_d, absorber, g4_seed = random.randint(0, 1e7)): """ Description: Geant4 main process @@ -70,7 +72,6 @@ class Particles: g4RunManager.SetUserInitialization(my_g4d) # set physics list physics_list = g4b.FTFP_BERT() - physics_list.SetVerboseLevel(1) physics_list.RegisterPhysics(g4b.G4StepLimiterPhysics()) g4RunManager.SetUserInitialization(physics_list) # define global parameter @@ -88,9 +89,12 @@ class Particles: visManager = g4b.G4VisExecutive() visManager.Initialize() UImanager = g4b.G4UImanager.GetUIpointer() - UImanager.ApplyCommand('/control/execute paras/g4macro/init_vis.mac') + UImanager.ApplyCommand('/control/execute param_file/g4macro/init_vis.mac') else: UImanager = g4b.G4UImanager.GetUIpointer() + # reduce verbose from physics list + UImanager.ApplyCommand('/process/em/verbose %d'%(verbose)) + UImanager.ApplyCommand('/process/had/verbose %d'%(verbose)) UImanager.ApplyCommand('/run/initialize') g4RunManager.BeamOn(int(g4_dic['total_events'])) diff --git a/root/__init__.py b/root/__init__.py deleted file mode 100644 index 804037ae655831d228d6eaee957658bb5ea34668..0000000000000000000000000000000000000000 --- a/root/__init__.py +++ /dev/null @@ -1,97 +0,0 @@ -import sys -import os -import ROOT -import csv - -def convert_csv_to_root(input_dir, output_dir, label): - com_name = [] - for file in os.listdir(input_dir): - if file.endswith('.csv'): - com_name.append(file) - for name in com_name: - if label == 'sicar1.1.8' and not name.startswith('sicar1.1.8'): - continue - elif label == 'sicar1.1.8-1' and not name.startswith('sicar1.1.8-1_'): - continue - elif label == 'sicar1.1.8-2' and not name.startswith('sicar1.1.8-2_'): - continue - - name = name.split('.csv')[0] - input_file = os.path.join(input_dir, name + '.csv') - output_file = os.path.join(output_dir, name + '.root') - - if name.endswith('iv'): - if label=="itk_atlas18_data_v1": - df = ROOT.RDF.MakeCsvDataFrame(input_file, True, '\t') - elif label =="njupin_iv_v1": - df = ROOT.RDF.MakeCsvDataFrame(input_file, True, ',') - else: - df = ROOT.RDF.MakeCsvDataFrame(input_file, True, ',') - if label in ["itk_md8_data_v1","itk_atlas18_data_v1"]: - df.Snapshot("myTree", output_file, {"Voltage_V", "Current_nA"}) - elif label in ['itk_atlas18_sim_v1','itk_md8_sim_v1']: - df.Snapshot("myTree", output_file, {"Voltage", "Current"}) - elif label =="njupin_iv_v1": - df.Snapshot("myTree", output_file, {"Current","Voltage"}) - - else: - df.Snapshot("myTree", output_file, {"Value","Reading"}) - - if name.endswith('cv'): - df = ROOT.RDF.MakeCsvDataFrame(input_file, True, ',') - if label=="itk_md8_sim_v1": - df.Snapshot("myTree", output_file, {"Voltage", "Capacitance"}) - elif label =="njupin_cv_v1": - df.Snapshot("myTree", output_file, {"Voltage", "Capacitance"}) - else: - df.Snapshot("myTree", output_file, {"Voltage", "Capacitance", "Capacitance^-2"}) - - if name.endswith('Wfm'): - df = ROOT.RDF.MakeCsvDataFrame(input_file, True, ',') - df.Snapshot("myTree", output_file, {"Time", "Volt"}) - - - sys.stdout.write('Saved as {}\n'.format(output_file)) - - -def main(kwargs): - label = kwargs['label'] - - if label == 'sicar1.1.8': - input_dir = '/scratchfs/bes/wangkeqi/wangkeqi/data/SICAR1.1.8' - output_dir = '/publicfs/atlas/atlasnew/silicondet/itk/raser/wangkeqi/sicar1.1.8/iv_cv' - elif label == 'sicar1.1.8-1': - input_dir = '/scratchfs/bes/wangkeqi/wangkeqi/data/SICAR1.1.8' - output_dir = '/publicfs/atlas/atlasnew/silicondet/itk/raser/wangkeqi/sicar1.1.8/iv_cv' - elif label == 'sicar1.1.8-2': - input_dir = '/scratchfs/bes/wangkeqi/wangkeqi/data/SICAR1.1.8' - output_dir = '/publicfs/atlas/atlasnew/silicondet/itk/raser/wangkeqi/sicar1.1.8/iv_cv' - elif label == 'itk_md8_data_v1': - input_dir = '/afs/ihep.ac.cn/users/l/lizhan/disk/scrathfs/sensorsimanddata/itkmd8/itkmd8data' - output_dir = '/publicfs/atlas/atlasnew/silicondet/itk/raser/lizhan/itkmd8/itkmd8data' - elif label == 'itk_md8_sim_v1': - input_dir = '/afs/ihep.ac.cn/users/l/lizhan/disk/scrathfs/sensorsimanddata/itkmd8/itkmd8sim' - output_dir = '/publicfs/atlas/atlasnew/silicondet/itk/raser/lizhan/itkmd8/itkmd8sim' - elif label == 'itk_atlas18_sim_v1': - input_dir = '/afs/ihep.ac.cn/users/l/lizhan/disk/scrathfs/sensorsimanddata/itkatlas18/sim' - output_dir = '/publicfs/atlas/atlasnew/silicondet/itk/raser/lizhan/atlas18/sim' - elif label == 'itk_atlas18_data_v1': - input_dir = '/afs/ihep.ac.cn/users/l/lizhan/disk/scrathfs/sensorsimanddata/itkatlas18/data' - output_dir = '/publicfs/atlas/atlasnew/silicondet/itk/raser/lizhan/atlas18/data' - elif label == 'njupin_iv_v1': - input_dir = "/afs/ihep.ac.cn/users/s/senzhao/njupin" - output_dir = '/publicfs/atlas/atlasnew/silicondet/itk/raser/zhaosen/njupin_iv' - elif label == 'njupin_cv_v1': - input_dir = "/afs/ihep.ac.cn/users/s/senzhao/njupin/cv" - output_dir = '/publicfs/atlas/atlasnew/silicondet/itk/raser/zhaosen/njupin_cv' - elif label == 'sicar1.1.8_alpha_v1': - input_dir = '/scratchfs/bes/wangkeqi/wangkeqi/data/SICAR1.1.8/CCE_1.1.8-8-1/400v' - output_dir = '/publicfs/atlas/atlasnew/silicondet/itk/raser/wangkeqi/sicar1.1.8/alpha/1/400V' - elif label == 'sicar1.1.8_beta': - input_dir = '/scratchfs/bes/wangkeqi/wangkeqi/data/SICAR1.1.8/time_1.1.8-8/20231116/si/beta_' - output_dir = '/publicfs/atlas/atlasnew/silicondet/itk/raser/wangkeqi/sicar1.1.8/beta' - else: - raise NameError(label) - - convert_csv_to_root(input_dir, output_dir, label) - diff --git a/spaceres/__init__.py b/spaceres/__init__.py index f58754258c1fe3c32a8ccf15852ebc2d2899afd7..59b4b6e8a785215dbe8be42b51469446f7772dfa 100644 --- a/spaceres/__init__.py +++ b/spaceres/__init__.py @@ -1,16 +1,9 @@ import sys import os -#sys.path.insert(0, sys.path[0]+"/../") - -import ROOT import time import subprocess -from . import telescope as tlcp -#from . import test -from particle.g4simulation import Particles -from particle.geometry import R3dDetector -from current.cal_current import CalCurrentPixel +import ROOT def main(kwargs): label = kwargs['label'] @@ -18,103 +11,17 @@ def main(kwargs): print("taichu_v1: ","first version of telescope simulation") print("taichu_v2: ","second version of telescope simulation") elif label.startswith("taichu_v1"): - #paths = ['det_name=Taichu3', 'parfile=readjson/detector.json', 'geant4_model=pixel_detector', 'geant4_parfile=readjson/absorber.json', 'pixel_detector'] - dset = Setting() #read label.json instead of inputting path - my_d = R3dDetector(dset) #remain the same - my_f = 0 - my_g4p = Particles(my_d, dset) #remove my_f - my_charge = CalCurrentPixel(my_d,my_f,my_g4p) - if label.endswith("draw_charge"): - draw_charge(my_charge) - my_telescope = tlcp.telescope(my_d,my_charge) - #tlcp.main(my_d) + from . import telescope_signal as tlcp + tlcp.main() elif label.startswith("taichu_v2"): - #virtual object - class MyObject: - pass - #output - res = [] - psize = [] - N = 25 - MaxSize = 25. - for i in range(N): - t_my_d = MyObject() - t_my_d.seedcharge = 100 - t_my_d.p_x = MaxSize*(i+1)/N - t_my_d.p_y = MaxSize*(i+1)/N - t_my_d.p_z = 200. - t_my_d.lt_z = [20000.,60000.,100000.,140000.,180000.,220000.] - psize.append(t_my_d.p_x) - res.append(tlcp.main(t_my_d)) - - graph = ROOT.TGraph() - for i in range(len(psize)): - graph.SetPoint(i,psize[i],res[i]) - - canvas = ROOT.TCanvas("canvas", "TGraph", 800, 600) - graph.SetMarkerStyle(ROOT.kFullCircle) - graph.GetYaxis().SetTitle("Resolution [um]") - graph.GetYaxis().CenterTitle() - graph.GetXaxis().SetTitle("Pixel Size [um]") - graph.GetXaxis().CenterTitle() - - legend = ROOT.TLegend(0.27,0.67,0.62,0.80) - legend.SetTextSize(0.04) - legend.AddEntry(graph,label) - - canvas.SetGrid() - - graph.Draw("APL") - legend.Draw() - - canvas.Draw() - Name = "Res vs size" - now = time.strftime("%Y_%m%d_%H%M") - path = os.path.join("output/fig", str(now),'' ) - """ If the path does not exit, create the path""" - if not os.access(path, os.F_OK): - os.makedirs(path) - canvas.SaveAs(path+Name+".png") + from . import telescope_signal as tlcp + tlcp.taichu_v2(label) elif label.startswith("acts_v1"): - python_script = "raser/spaceres/telescope_simulation.py" - - result = subprocess.run(["python3", python_script], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) - - if result.returncode == 0: - print(f"Script '{python_script}' executed successfully.") - else: - print(f"Script '{python_script}' failed with return code:", result.returncode) - - stdout_output = result.stdout - stderr_output = result.stderr - - print("Standard Output:") - print(stdout_output) - - print("Standard Error:") - print(stderr_output) + from . import telescope_acts as tlcp_acts + tlcp_acts.main() + elif label.startswith("g4"): + from . import telescope_g4 + telescope_g4.main() else: raise NameError(label) -def draw_charge(my_charge): - path = os.path.join("output", "pixel",) - create_path(path) - c=ROOT.TCanvas("c","canvas1",1000,1000) - c.cd() - c.Update() - c.SetLeftMargin(0.12) - # c.SetTopMargin(0.12) - c.SetRightMargin(0.12) - c.SetBottomMargin(0.14) - ROOT.gStyle.SetOptStat(ROOT.kFALSE) - ROOT.gStyle.SetOptStat(0) - - my_charge.sum_charge.GetXaxis().SetNdivisions(510) - my_charge.sum_charge.GetYaxis().SetNdivisions(505) - my_charge.sum_charge.GetXaxis().SetTitle("X") - my_charge.sum_charge.GetYaxis().SetTitle("Y") - - my_charge.sum_charge.Draw("lego") - c.Update() - c.SaveAs(path+"/Pixel_charge.pdf") - c.SaveAs(path+"/Pixel_charge.root") diff --git a/spaceres/telescope_simulation.py b/spaceres/telescope_acts.py old mode 100644 new mode 100755 similarity index 93% rename from spaceres/telescope_simulation.py rename to spaceres/telescope_acts.py index 80a2e6805dd4045e3a36d10da78fe575f81602bc..a007c578c63154f703cdfc079c9fd795ff4c9b32 --- a/spaceres/telescope_simulation.py +++ b/spaceres/telescope_acts.py @@ -4,6 +4,9 @@ from pathlib import Path import acts import acts.examples + +from util.io_decorator import io_decorator as iod + from acts.examples.simulation import ( addParticleGun, addDigitization, @@ -30,9 +33,11 @@ from acts.examples.reconstruction import ( TrackSelectorConfig, ) -u = acts.UnitConstants +# get run result +@iod +def main(): + u = acts.UnitConstants -if "__main__" == __name__: detector, trackingGeometry, decorators = acts.examples.TelescopeDetector.create( positions=[20, 60, 100 ,140, 180, 220], stereos = [0, 0, 0, 0, 0, 0], @@ -42,10 +47,10 @@ if "__main__" == __name__: field = acts.ConstantBField(acts.Vector3(0, 0, 1 * u.T)) - outputDir = Path.cwd() / "output/telescope_simulation" + outputDir = Path.cwd() / "output/spaceres/telescope_acts" if not outputDir.exists(): outputDir.mkdir() - inputDir = Path.cwd() / "setting" + inputDir = Path.cwd() / "setting/acts" rnd = acts.examples.RandomNumbers(seed=42) @@ -148,4 +153,7 @@ if "__main__" == __name__: outputDirRoot=outputDir / postfix, ) ''' - s.run() \ No newline at end of file + s.run() + +if "__main__" == __name__: + main() \ No newline at end of file diff --git a/spaceres/telescope_jiaqi.py b/spaceres/telescope_g4.py similarity index 93% rename from spaceres/telescope_jiaqi.py rename to spaceres/telescope_g4.py index 918cfdd30fe70b0a9e47889782b66d9240e2f58b..8d464f11b1dbfcdc29457cc24e2de55a0b769f84 100755 --- a/spaceres/telescope_jiaqi.py +++ b/spaceres/telescope_g4.py @@ -584,45 +584,50 @@ class B2ActionInitialization(G4VUserActionInitialization): self.SetUserAction(B2EventAction()) self.SetUserAction(B2SteppingAction()) -# Detect interactive mode (if no arguments) and define UI session -ui = None -if len(sys.argv) == 1: - ui = G4UIExecutive(len(sys.argv), sys.argv) - -# Optionally: choose a different Random engine... -# G4Random.setTheEngine(MTwistEngine()) - -# Construct the default run manager -runManager = G4RunManagerFactory.CreateRunManager(G4RunManagerType.Serial) - -# Set mandatory initialization classes -runManager.SetUserInitialization(B2aDetectorConstruction()) - -physicsList = FTFP_BERT() -physicsList.RegisterPhysics(G4StepLimiterPhysics()) -runManager.SetUserInitialization(physicsList) - -# Set user action classes -runManager.SetUserInitialization(B2ActionInitialization()) - -# Initialize visualization -visManager = G4VisExecutive() -# G4VisExecutive can take a verbosity argument - see /vis/verbose guidance. -# visManager = G4VisExecutive("Quiet"); -visManager.Initialize() - -# Get the pointer to the User Interface manager -UImanager = G4UImanager.GetUIpointer() - -# Process macro or start UI session -if ui == None: - # batch mode - command = "/control/execute ./cfg/ " - fileName = sys.argv[1] - UImanager.ApplyCommand(command+fileName) -else: - # interactive mode - UImanager.ApplyCommand("/control/execute ./paras/g4macro/init_vistelescope.mac") - if ui.IsGUI(): - UImanager.ApplyCommand("/control/execute ./paras/g4macro/gui.mac") - ui.SessionStart() + +def main(batchMac = None): + # Detect interactive mode (if no arguments) and define UI session + ui = None + if batchMac == None: + ui = G4UIExecutive(1, [__file__]) + + # Optionally: choose a different Random engine... + # G4Random.setTheEngine(MTwistEngine()) + + # Construct the default run manager + runManager = G4RunManagerFactory.CreateRunManager(G4RunManagerType.Serial) + + # Set mandatory initialization classes + runManager.SetUserInitialization(B2aDetectorConstruction()) + + physicsList = FTFP_BERT() + physicsList.RegisterPhysics(G4StepLimiterPhysics()) + runManager.SetUserInitialization(physicsList) + + # Set user action classes + runManager.SetUserInitialization(B2ActionInitialization()) + + # Initialize visualization + visManager = G4VisExecutive() + # G4VisExecutive can take a verbosity argument - see /vis/verbose guidance. + # visManager = G4VisExecutive("Quiet"); + visManager.Initialize() + + # Get the pointer to the User Interface manager + UImanager = G4UImanager.GetUIpointer() + + # Process macro or start UI session + if ui == None: + # batch mode + command = "/control/execute ./param_file/g4macro/" + fileName = batchMac + UImanager.ApplyCommand(command+fileName) + else: + # interactive mode + UImanager.ApplyCommand("/control/execute ./param_file/g4macro/init_vistelescope.mac") + if ui.IsGUI(): + UImanager.ApplyCommand("/control/execute ./param_file/g4macro/gui.mac") + ui.SessionStart() + +if __name__ == "__main__": + main(sys.argv[1]) \ No newline at end of file diff --git a/spaceres/telescope.py b/spaceres/telescope_signal.py similarity index 84% rename from spaceres/telescope.py rename to spaceres/telescope_signal.py index fbcc272202f7a5df50d83c252ad0c25219d08c89..2d2514377aa5187f8d098e7234dc08b53ac7c8ca 100644 --- a/spaceres/telescope.py +++ b/spaceres/telescope_signal.py @@ -6,13 +6,20 @@ Description: @Author : yiminghu @version : 1.0 ''' -import ROOT + import time import os + +import ROOT import acts import numpy as np -class telescope: +from particle.g4simulation import Particles +from field.build_device import Detector +from current.cal_current_diffuse import CalCurrentPixel +from util.output import create_path + +class Telescope: def __init__(self,my_d,my_c): """ Description: @@ -128,7 +135,7 @@ class telescope: Name = "fit"+str(DUT) now = time.strftime("%Y_%m%d_%H%M") - path = os.path.join("fig", str(now),'' ) + path = os.path.join("output/spaceres/taichu_v1", str(now),'' ) #print(path) """ If the path does not exit, create the path""" @@ -220,7 +227,7 @@ class telescope: label.Draw() now = time.strftime("%Y_%m%d_%H%M") - path = os.path.join("fig", str(now),'' ) + path = os.path.join("output/spaceres/taichu_v1", str(now),'' ) #print(path) """ If the path does not exit, create the path""" @@ -376,7 +383,7 @@ class island: #interface to generate simple examples for debugging -class Test: +class PixelHitTest: def __init__(self,my_d): self.event = [] @@ -444,11 +451,89 @@ class Test: #print(t_list) return t_list -def main(my_d): - my_c = Test(my_d) - tel = telescope(my_d,my_c) - return tel.Resolution_Tol[2][0] - +def draw_charge(my_charge): + path = os.path.join("output", "pixel",) + create_path(path) + c=ROOT.TCanvas("c","canvas1",1000,1000) + c.cd() + c.Update() + c.SetLeftMargin(0.12) + # c.SetTopMargin(0.12) + c.SetRightMargin(0.12) + c.SetBottomMargin(0.14) + ROOT.gStyle.SetOptStat(ROOT.kFALSE) + ROOT.gStyle.SetOptStat(0) + + my_charge.sum_charge.GetXaxis().SetNdivisions(510) + my_charge.sum_charge.GetYaxis().SetNdivisions(505) + my_charge.sum_charge.GetXaxis().SetTitle("X") + my_charge.sum_charge.GetYaxis().SetTitle("Y") + + my_charge.sum_charge.Draw("lego") + c.Update() + c.SaveAs(path+"/Pixel_charge.pdf") + c.SaveAs(path+"/Pixel_charge.root") + +def main(): + my_d = Detector("TAICHU3") #remain the same + my_f = 0 + my_g4p = Particles(my_d, my_d.absorber) #remove my_f + my_hit_charge = CalCurrentPixel(my_d,my_f,my_g4p) + draw_charge(my_hit_charge) + my_telescope_charge = Telescope(my_d,my_hit_charge) + my_hit_test = PixelHitTest(my_d) + my_telescope_test = Telescope(my_d,my_hit_test) + +def taichu_v2(label=""): + #virtual object + class MyObject: + pass + #output + res = [] + psize = [] + N = 25 + MaxSize = 25. + for i in range(N): + t_my_d = MyObject() + t_my_d.seedcharge = 100 + t_my_d.p_x = MaxSize*(i+1)/N + t_my_d.p_y = MaxSize*(i+1)/N + t_my_d.p_z = 200. + t_my_d.lt_z = [20000.,60000.,100000.,140000.,180000.,220000.] + psize.append(t_my_d.p_x) + my_hit_test = PixelHitTest(t_my_d) + my_telescope_test = Telescope(t_my_d,my_hit_test) + res.append(my_telescope_test.Resolution_Tol[2][0]) + + graph = ROOT.TGraph() + for i in range(len(psize)): + graph.SetPoint(i,psize[i],res[i]) + + canvas = ROOT.TCanvas("canvas", "TGraph", 800, 600) + graph.SetMarkerStyle(ROOT.kFullCircle) + graph.GetYaxis().SetTitle("Resolution [um]") + graph.GetYaxis().CenterTitle() + graph.GetXaxis().SetTitle("Pixel Size [um]") + graph.GetXaxis().CenterTitle() + + legend = ROOT.TLegend(0.27,0.67,0.62,0.80) + legend.SetTextSize(0.04) + legend.AddEntry(graph,label) + + canvas.SetGrid() + + graph.Draw("APL") + legend.Draw() + + canvas.Draw() + Name = "Res vs size" + now = time.strftime("%Y_%m%d_%H%M") + path = os.path.join("output/spaceres/taichu_v2", str(now),'' ) + """ If the path does not exit, create the path""" + if not os.access(path, os.F_OK): + os.makedirs(path) + canvas.SaveAs(path+Name+".png") + if __name__ == '__main__': start = time.time() main() diff --git a/tct/__init__.py b/tct/__init__.py index ee92e9a50ad43cff91a237a8b9c968e213079d17..acadfc43471714874894ba86a63098b4a78985b7 100644 --- a/tct/__init__.py +++ b/tct/__init__.py @@ -1,8 +1,8 @@ -from . import foo def main(kwargs): label = kwargs['label'] - if label == 'foo': - foo.main() + if label == 'signal': + from . import tct_signal + tct_signal.main(kwargs) else: - raise NameError(label) \ No newline at end of file + raise NameError diff --git a/tct/extract_waveform.py b/tct/extract_waveform.py deleted file mode 100644 index ba7787fb1532da6e4852a73994b7b9a058283286..0000000000000000000000000000000000000000 --- a/tct/extract_waveform.py +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env python3 -import sys -import os -import math -import ROOT -from array import array - -def save_experiment_data(Vbias, z_init, z_0, t_init, myt, out): - - n = myt.Draw("-(volt-aBlineMean):(time-{})".format(t_init), - "Vbias=={}\ - &&(z-{}-{}>-0.0001)\ - &&(z-{}-{}<0.0001)\ - &&((time-{})>0)\ - &&((time-{})<10)".format(Vbias,z_init,z_0,z_init,z_0,t_init,t_init), - "goff") - graph1 = ROOT.TGraph(n,myt.GetV2(),myt.GetV1()) - v1 = array('d') - t1 = array('d') - for i in range(n): - v1.append(graph1.GetPointY(i)) - t1.append(graph1.GetPointX(i)) - - volt = array('d',[999.]) - time = array('d',[999.]) - fout = ROOT.TFile(out+".root", "RECREATE") - t_out = ROOT.TTree("tree", "signal") - t_out.Reset() - t_out.Branch("volt", volt, "volt/D") - t_out.Branch("time", time, "time/D") - for i in range(len(t1)): - time[0]=t1[i] - volt[0]=v1[i] - t_out.Fill() - t_out.Write() - fout.Close() - del t_out - print(out+".root Saved") - -if not os.access('output/pintct/HPK-Si-PIN/data/', os.F_OK): - os.makedirs('output/pintct/HPK-Si-PIN/data/', exist_ok=True) -if not os.access('output/lgadtct/HPK-Si-LGAD/data/', os.F_OK): - os.makedirs('output/lgadtct/HPK-Si-LGAD/data/', exist_ok=True) - -myPinFile = ROOT.TFile("/afs/ihep.ac.cn/users/f/fuchenxi/disk/1/edge_voltage_2019_10_24_15_12_57_HPK-EPI-W2-200-DS-SE5PINNM-01.txt.root") -myPinTree = myPinFile.Get("edge") -myLgadFile = ROOT.TFile("/afs/ihep.ac.cn/users/f/fuchenxi/disk/1/edge_voltage_2019_10_09_12_26_57_HPK-EPI-W2-200-DS-SE5-04.txt.root") -myLgadTree = myLgadFile.Get("edge") -# myPinTree.Show(17) # checkout the members - -z_init_pin = "11.986" -z_init_lgad = "11.954" -t_init_pin = "10.853" -t_init_lgad = "10.803" - -for j in range(-10, 60+1): - rel_z = 0.02*j - z_0 = str(1e-3*j) # in milimeter - save_experiment_data(-200, z_init_pin, z_0, t_init_pin, myPinTree,"output/pintct/HPK-Si-PIN/data/exp-TCT"+str(round(rel_z,2))+"fz_rel") - save_experiment_data(-200, z_init_lgad, z_0, t_init_lgad, myLgadTree,"output/lgadtct/HPK-Si-LGAD/data/exp-TCT"+str(round(rel_z,2))+"fz_rel") - -for V in range(-200, -40, 20): - z_0 = str(1e-3*25) - save_experiment_data(V, z_init_pin, z_0, t_init_pin, myPinTree,"output/pintct/HPK-Si-PIN/data/exp-TCT"+str(round(V,0))+"voltage") - save_experiment_data(V, z_init_lgad, z_0, t_init_lgad, myLgadTree,"output/lgadtct/HPK-Si-LGAD/data/exp-TCT"+str(round(V,0))+"voltage") \ No newline at end of file diff --git a/tct/save_TTree.py b/tct/save_TTree.py index fd29690812237f1a208d276f187e3a56ac0bb85b..eb23d91f8bc74aec5675785af633692dafcd8f8b 100644 --- a/tct/save_TTree.py +++ b/tct/save_TTree.py @@ -1,18 +1,18 @@ import os -from util.output import output +from util.output import create_path from array import array import ROOT -def save_signal_TTree(dset,my_d,key,ele_current,my_f): +def save_signal_TTree(my_d,key,ele_current,my_f): if "planar3D" in my_d.det_model or "planarRing" in my_d.det_model: - path = os.path.join("output", "pintct", dset.det_name, "data",) + path = os.path.join("output", "pintct", my_d.det_name, "data",) elif "lgad3D" in my_d.det_model: - path = os.path.join("output", "lgadtct", dset.det_name, "data",) + path = os.path.join("output", "lgadtct", my_d.det_name, "data",) create_path(path) - for j in range(my_f.read_ele_num): + for j in range(ele_current.read_ele_num): volt = array('d', [999.]) time = array('d', [999.]) - if my_f.read_ele_num==1: + if ele_current.read_ele_num==1: fout = ROOT.TFile(os.path.join(path, "sim-TCT") + str(key) + ".root", "RECREATE") else: fout = ROOT.TFile(os.path.join(path, "sim-TCT") + str(key)+"No_"+str(j)+".root", "RECREATE") diff --git a/tct/source.py b/tct/source.py index cd631a4fc72109c0b4b64e5e7371e94349c08f0d..cf8a2627d5a1f30cdd5b1c1cbc7e315ab06a2f7a 100644 --- a/tct/source.py +++ b/tct/source.py @@ -1,7 +1,7 @@ import math import ROOT import numpy as np -from particle.geometry import R3dDetector +from field.build_device import Detector class TCTTracks(): """ @@ -23,6 +23,7 @@ class TCTTracks(): """ def __init__(self, my_d, laser): #technique used + self.model = laser["laser_model"] self.tech = laser["tech"] self.direction = laser["direction"] #material parameters to certain wavelength of the beam @@ -190,54 +191,53 @@ class TCTTracks(): # to reduce run time, convolute the time pulse function with the signal after the signal is calculated return np.exp(-4 * np.log(2) * t ** 2 / self.temporal_FWHM ** 2) / ((2*np.pi)**(1/2) * self.temporal_FWHM / (2 * (2*np.log(2))**(1/2))) - -def draw_nocarrier3D(self,path): - ROOT.gStyle.SetOptStat(0) - c1 = ROOT.TCanvas("c1","canvas2",200,10,1000,1000) - h = ROOT.TH3D("h","",\ - int((self.x_right_most - self.x_left_most) / self.x_step), self.x_left_most, self.x_right_most,\ - int((self.y_right_most - self.y_left_most) / self.y_step), self.y_left_most, self.y_right_most,\ - int((self.z_right_most - self.z_left_most) / self.z_step), self.z_left_most, self.z_right_most) - for i in range(len(self.track_position)): - h.Fill(self.track_position[i][0], self.track_position[i][1], self.track_position[i][2], self.ionized_pairs[i]) - h.Draw() - h.GetXaxis().SetTitle("Depth [\mu m]")#[μm] - h.GetXaxis().SetTitleSize(0.05) - h.GetXaxis().SetLabelSize(0.05) - h.GetYaxis().SetTitle("Width [\mu m]") - h.GetYaxis().SetTitleSize(0.05) - h.GetYaxis().SetLabelSize(0.05) - h.GetZaxis().SetTitle("Thick [\mu m]") - h.GetZaxis().SetTitleSize(0.05) - h.GetZaxis().SetLabelSize(0.05) - h.GetXaxis().SetTitleOffset(1.8) - h.GetYaxis().SetTitleOffset(2.2) - h.GetZaxis().SetTitleOffset(1.4) - c1.SetLeftMargin(0.15) - c1.SaveAs(path+"nocarrier_"\ - +str(round(self.fx_rel,5))+"_"\ - +str(round(self.fy_rel,5))+"_"\ - +str(round(self.fz_rel,5))+".pdf") - -def draw_nocarrier2D(self, path): - ROOT.gStyle.SetOptStat(0) - c1 = ROOT.TCanvas("c1","canvas2",200,10,1000,1000) - h = ROOT.TH2D("h","",\ - int((self.x_right_most - self.x_left_most) / self.x_step), self.x_left_most, self.x_right_most,\ - int((self.z_right_most - self.z_left_most) / self.z_step), self.z_left_most, self.z_right_most) - for i in range(len(self.track_position)): - h.Fill(self.track_position[i][0], self.track_position[i][2], self.ionized_pairs[i]) - h.Draw("COLZ") - h.GetXaxis().SetTitle("Depth [\mu m]")#[μm] - h.GetXaxis().SetTitleSize(0.05) - h.GetXaxis().SetLabelSize(0.05) - h.GetYaxis().SetTitle("Thick [\mu m]") - h.GetYaxis().SetTitleSize(0.05) - h.GetYaxis().SetLabelSize(0.05) - h.GetZaxis().SetLabelSize(0.05) - c1.SetRightMargin(0.15) - c1.SetLeftMargin(0.12) - c1.SaveAs(path+"nocarrier2D_"\ - +str(round(self.fx_rel,5))+"_"\ - +str(round(self.fy_rel,5))+"_"\ - +str(round(self.fz_rel,5))+".pdf") + def draw_nocarrier3D(self,path): + ROOT.gStyle.SetOptStat(0) + c1 = ROOT.TCanvas("c1","canvas2",200,10,1000,1000) + h = ROOT.TH3D("h","",\ + int((self.x_right_most - self.x_left_most) / self.x_step), self.x_left_most, self.x_right_most,\ + int((self.y_right_most - self.y_left_most) / self.y_step), self.y_left_most, self.y_right_most,\ + int((self.z_right_most - self.z_left_most) / self.z_step), self.z_left_most, self.z_right_most) + for i in range(len(self.track_position)): + h.Fill(self.track_position[i][0], self.track_position[i][1], self.track_position[i][2], self.ionized_pairs[i]) + h.Draw() + h.GetXaxis().SetTitle("Depth [\mu m]")#[μm] + h.GetXaxis().SetTitleSize(0.05) + h.GetXaxis().SetLabelSize(0.05) + h.GetYaxis().SetTitle("Width [\mu m]") + h.GetYaxis().SetTitleSize(0.05) + h.GetYaxis().SetLabelSize(0.05) + h.GetZaxis().SetTitle("Thick [\mu m]") + h.GetZaxis().SetTitleSize(0.05) + h.GetZaxis().SetLabelSize(0.05) + h.GetXaxis().SetTitleOffset(1.8) + h.GetYaxis().SetTitleOffset(2.2) + h.GetZaxis().SetTitleOffset(1.4) + c1.SetLeftMargin(0.15) + c1.SaveAs(path+"/nocarrier_"\ + +str(round(self.fx_rel,5))+"_"\ + +str(round(self.fy_rel,5))+"_"\ + +str(round(self.fz_rel,5))+".pdf") + + def draw_nocarrier2D(self, path): + ROOT.gStyle.SetOptStat(0) + c1 = ROOT.TCanvas("c1","canvas2",200,10,1000,1000) + h = ROOT.TH2D("h","",\ + int((self.x_right_most - self.x_left_most) / self.x_step), self.x_left_most, self.x_right_most,\ + int((self.z_right_most - self.z_left_most) / self.z_step), self.z_left_most, self.z_right_most) + for i in range(len(self.track_position)): + h.Fill(self.track_position[i][0], self.track_position[i][2], self.ionized_pairs[i]) + h.Draw("COLZ") + h.GetXaxis().SetTitle("Depth [\mu m]")#[μm] + h.GetXaxis().SetTitleSize(0.05) + h.GetXaxis().SetLabelSize(0.05) + h.GetYaxis().SetTitle("Thick [\mu m]") + h.GetYaxis().SetTitleSize(0.05) + h.GetYaxis().SetLabelSize(0.05) + h.GetZaxis().SetLabelSize(0.05) + c1.SetRightMargin(0.15) + c1.SetLeftMargin(0.12) + c1.SaveAs(path+"/nocarrier2D_"\ + +str(round(self.fx_rel,5))+"_"\ + +str(round(self.fy_rel,5))+"_"\ + +str(round(self.fz_rel,5))+".pdf") diff --git a/tct/tct_analysis.py b/tct/tct_analysis.py deleted file mode 100644 index fbdf3b8c566f9c68b1c9706598c8acd360ad9942..0000000000000000000000000000000000000000 --- a/tct/tct_analysis.py +++ /dev/null @@ -1,538 +0,0 @@ -#!/usr/bin/env python3 -# -*- encoding: utf-8 -*- -""" -author: wanghaobo -time: 2022.12.25 -Use: 1.Read the data of Raser eTCT induced current - 2.Add experimental noise on induced current - 3.Get the risertime,charge collection and velocity profile -""" - -from array import array -import contextlib -import os -import sys -import ROOT -import math -import numpy as np - -sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) -import raser - -def collect_data(path, model, volt_scale, time_scale, keys, key_name): - amplitude = array("d") - risetime = array("d") - charge = array("d") - velprof = array("d") - difprof = array("d") - volts = [] - times = [] - - for key in keys: - volt=array("d",[0.]) - time=array("d",[0.]) - rootfile=path+model+str(key)+key_name+".root" - volt,time=read_rootfile(rootfile, volt_scale, time_scale) - volts.append(volt) - times.append(time) - J=len(volt) - - amplitude.append(get_amplitude(volt,J)) - charge.append(get_charge(volt,J)) - velprof.append(get_velprof(volt,time,J)) - risetime.append(get_risetime(volt,time,J)) - difprof.append(get_difprof(volt,time,J)) - - return amplitude, charge, risetime, velprof, difprof, volts, times - -def read_rootfile(rootfile,volt_scale,time_scale): - J=0 - v1=array("d") - t1=array("d") - myFile = ROOT.TFile(str(rootfile)) - myt = myFile.tree - for entry in myt: - v1.append(volt_scale*entry.volt) - t1.append(time_scale*entry.time) - J=J+1 - return v1,t1 - -def add_noise(rootfile,J,v1,t1): - v2=array("d",[0.]) - t2=array("d",[0.]) - noise=np.array([0]) - fout = ROOT.TFile("noise_"+str(rootfile), "RECREATE") - t_out = ROOT.TTree("tree", "signal") - t_out.Branch("volt", v2, "volt/D") - t_out.Branch("time", t2, "time/D") - for i in range(J): - t2[0]=t1[i] - v2[0]=v1[i]+noise[i] - t_out.Fill() - t_out.Write() - fout.Close() - -def get_amplitude(volt,J): - Vmax = max(volt) - for Max in range(J): - if volt[Max] - Vmax > -1e-5*Vmax: - break - for min in range(Max,0,-1): - if volt[min-1] > volt[min]: - #Vmin = volt[min] - Vmin = 0 - break - else: - #Vmin = volt[0] - Vmin = 0 - return(Vmax-Vmin) - -def get_charge(volt,J): - sum_volt=0 - for j in range(J): - sum_volt+=volt[j] - return sum_volt*50e-12/(100*0.65e-9/2.2/(3.7e-12))*1e15 - # t_bin = 50e-12 A = 100 Ï„_RC_D = 0.65e-9/2.2 C_D = 3.7e-12 result in fC - -def get_velprof(volt,time,J): - t = 1.1 #ns - for j in range(J): - if time[j] >= t: - break - return volt[j] - -def get_difprof(volt,time,J): - max_diff = 0 - for i in range(J-1): - if volt[i+1]-volt[i] > max_diff: - max_diff = volt[i+1]-volt[i] - return max_diff/(100*0.65e-9/2.2/(3.7e-12))/50e-12/2.24e-4/16992*1e-6 - # A = 100 Ï„_RC_D = 0.65e-9/2.2 C_D = 3.7e-12 t_bin = 50e-12 k_2hν = 2.24e-4 E_p/hν = 19992 result in μm - -def get_risetime(volt,time,J): - x=array("d") - y=array("d") - Vmax=max(volt) - for Max in range(J): - if volt[Max] - Vmax > -1e-5*Vmax: - break - for min in range(Max,0,-1): - if volt[min-1] > volt[min]and volt[min]<0.1*Vmax: - Vmin = volt[min] - break - else: - Vmin = volt[0] - for k in range(J): - if (volt[k] - Vmin)<0.1*(Vmax - Vmin)<(volt[k+1] - Vmin): - break - for l in range(J): - if (volt[l-1] - Vmin)<0.9*(Vmax - Vmin)<(volt[l] - Vmin): - break - n=l-k - for j in range(k,l+1): - x.append(time[j]) - y.append(volt[j]) - - graph1 = ROOT.TGraph(n,x,y) - f=ROOT.TF1("f","[0]+[1]*x",0,10) - graph1.Fit(f,"Q") - b=f.GetParameter(1) - c=f.GetParameter(0) - e1=np.true_divide((0.2*(Vmax-Vmin)-c),b) - e2=np.true_divide((0.8*(Vmax-Vmin)-c),b) - risetime=np.true_divide((e2-e1),0.6) - return risetime - -def draw_graphs(array1,keys,key_name,name,path): - n=len(array1) - g = ROOT.TCanvas('g', '', 800, 600) - g.SetFillColor(0) - g.SetFrameFillColor(0) - ROOT.gStyle.SetPadColor(0) - ROOT.gStyle.SetCanvasColor(0) - ROOT.gStyle.SetOptStat(0) - g.SetLeftMargin(0.15) - g.SetRightMargin(0.15) - g.SetTopMargin(0.1) - g.SetBottomMargin(0.15) - - graph=ROOT.TGraph(n,keys,array1) - graph.SetMarkerStyle(3) - graph.Draw('ap') - - legend = ROOT.TLegend(0.6,0.7, 0.83, 0.89) - legend.AddEntry(graph,"RASER Simulation", "p") - legend.SetTextSize(18) - legend.SetTextFont(43) - legend.SetBorderSize(0) - legend.SetFillColor(0) - legend.Draw() - - g.SaveAs(path+name+".pdf") - - return - -def draw_double_graphs(array1,array2,keys1,keys2,key_name,name,path): - c = ROOT.TCanvas('c', '', 800, 600) - c.SetFillColor(0) - c.SetFrameFillColor(0) - ROOT.gStyle.SetPadColor(0) - ROOT.gStyle.SetCanvasColor(0) - ROOT.gStyle.SetOptStat(0) - c.SetLeftMargin(0.15) - c.SetBottomMargin(0.15) - - mg=ROOT.TMultiGraph("mg","") - n1=len(array1) - graph1 = ROOT.TGraph(n1,keys1,array1) - n2=len(array2) - graph2 = ROOT.TGraph(n2,keys2,array2) - - graph1.SetLineColor(2) - graph2.SetLineColor(1) - graph1.SetMarkerColor(2) - graph2.SetMarkerColor(1) - graph1.SetMarkerStyle(26) - graph2.SetMarkerStyle(4) - - mg.Add(graph1) - mg.Add(graph2) - mg.Draw('ap') - - if name == 'Amplitude': - Y_title = 'Amplitude [V]' - if 'LGAD' in path: - mg.GetYaxis().SetRangeUser(0,1.13) - else: - mg.GetYaxis().SetRangeUser(0,0.04) - - if name == 'Charge': - Y_title = 'Charge [fC]' - if 'LGAD' in path: - mg.GetYaxis().SetRangeUser(0,200) - else: - mg.GetYaxis().SetRangeUser(0,6) - - if name == 'VelProf': - Y_title = 'Ve+Vh [a.u.]' - if 'LGAD' in path: - mg.GetYaxis().SetRangeUser(0,0.1) - else: - mg.GetYaxis().SetRangeUser(0,0.015) - - if name == 'RiseTime': - Y_title = 'RiseTime [ns]' - if 'LGAD' in path: - mg.GetYaxis().SetRangeUser(0,1.5) - else: - mg.GetYaxis().SetRangeUser(0,1.5) - - if name == 'DifProf': - Y_title = '1/\sigma [\mu m^{-1}]' - if 'LGAD' in path: - mg.GetYaxis().SetRangeUser(0,0.1) - else: - mg.GetYaxis().SetRangeUser(0,0.003) - - mg.GetYaxis().SetTitle(Y_title) - if key_name == "z": - mg.GetXaxis().SetTitle('z [\mu m]') - elif key_name == "voltage": - mg.GetXaxis().SetTitle('Reverse bias voltage [V]') - mg.GetYaxis().SetLabelSize(0.05) - mg.GetYaxis().SetTitleSize(0.05) - mg.GetXaxis().SetLabelSize(0.05) - mg.GetXaxis().SetTitleSize(0.05) - - legend = ROOT.TLegend(0.45,0.65, 0.81, 0.86) - legend.AddEntry(graph1, "RASER simulation", "p") - legend.AddEntry(graph2, "TCT measurement", "p") - legend.SetTextSize(27) - legend.SetTextFont(43) - - legend.SetBorderSize(0) - legend.SetFillColor(0) - legend.Draw() - - c.SaveAs(path+name+"_"+key_name+"_comparison.pdf") - -def draw_triple_graphs(array1,array2,array3,keys1,keys2,keys3,key_name,name,path): - c = ROOT.TCanvas('c', '', 800, 600) - c.SetFillColor(0) - c.SetFrameFillColor(0) - ROOT.gStyle.SetPadColor(0) - ROOT.gStyle.SetCanvasColor(0) - ROOT.gStyle.SetOptStat(0) - c.SetLeftMargin(0.15) - c.SetBottomMargin(0.15) - - mg=ROOT.TMultiGraph("mg","") - n1=len(array1) - graph1 = ROOT.TGraph(n1,keys1,array1) - n2=len(array2) - graph2 = ROOT.TGraph(n2,keys2,array2) - n3=len(array3) - graph3 = ROOT.TGraph(n3,keys3,array3) - - graph1.SetLineColor(2) - graph2.SetLineColor(1) - graph3.SetLineColor(35) - graph1.SetMarkerColor(2) - graph2.SetMarkerColor(1) - graph3.SetMarkerColor(35) - graph1.SetMarkerStyle(26) - graph2.SetMarkerStyle(4) - graph3.SetMarkerStyle(32) - - graph3.SetLineWidth(4) - - # fill the background - # gain layer - x1 = array("d",[0,2,2,0,0]) - y1 = array("d",[0,0,0.1,0.1,0]) - excl1 = ROOT.TGraph(5,x1,y1) - excl1.SetLineColor(ROOT.kPink+1) - excl1.SetFillColor(ROOT.kPink+1) - # bulk - x2 = array("d",[2,50,50,2,2]) - y2 = array("d",[0,0,0.1,0.1,0]) - excl2 = ROOT.TGraph(5,x2,y2) - excl2.SetLineColor(ROOT.kCyan-10) - excl2.SetFillColor(ROOT.kCyan-10) - - mg.Add(excl1,"f") - mg.Add(excl2,"f") - - mg.Add(graph1,"p") - mg.Add(graph2,"p") - mg.Add(graph3,"l") - mg.Draw("a*") - - ROOT.gPad.RedrawAxis() - ROOT.gPad.RedrawAxis("G") - - if name == 'Amplitude': - Y_title = 'Amplitude [V]' - if 'LGAD' in path: - mg.GetYaxis().SetRangeUser(0,1.13) - else: - mg.GetYaxis().SetRangeUser(0,0.04) - - if name == 'Charge': - Y_title = 'Charge [fC]' - if 'LGAD' in path: - mg.GetYaxis().SetRangeUser(0,200) - else: - mg.GetYaxis().SetRangeUser(0,6) - - if name == 'VelProf': - Y_title = 'Ve+Vh [a.u.]' - if 'LGAD' in path: - mg.GetYaxis().SetRangeUser(0,0.1) - else: - mg.GetYaxis().SetRangeUser(0,0.015) - - if name == 'RiseTime': - Y_title = 'RiseTime [ns]' - if 'LGAD' in path: - mg.GetYaxis().SetRangeUser(0,1.5) - else: - mg.GetYaxis().SetRangeUser(0,1.5) - - if name == 'DifProf': - Y_title = '1/\sigma [\mu m^{-1}]' - if 'LGAD' in path: - mg.GetYaxis().SetRangeUser(0,0.1) - else: - mg.GetYaxis().SetRangeUser(0,0.003) - - Box=ROOT.TBox(8,0.03,42,0.05) - Box.SetLineColor(ROOT.kRed) - Box.SetFillStyle(0) - Box.SetLineStyle(2) - Box.Draw() - - l=ROOT.TLatex() - l.SetTextSize(20) - l.SetTextFont(43) - l.DrawLatex(11,0.022,"Full Gaussian shape region") - - mg.GetYaxis().SetTitle(Y_title) - if key_name == "z": - mg.GetXaxis().SetTitle('z [\mu m]') - elif key_name == "voltage": - mg.GetXaxis().SetTitle('Reverse bias voltage [V]') - mg.GetYaxis().SetLabelSize(0.05) - mg.GetYaxis().SetTitleSize(0.05) - mg.GetXaxis().SetLabelSize(0.05) - mg.GetXaxis().SetTitleSize(0.05) - - legend = ROOT.TLegend(0.4,0.65, 0.76, 0.85) - legend.AddEntry(graph1, "RASER simulation", "p") - legend.AddEntry(graph2, "TCT measurement", "p") - legend.AddEntry(graph3, "Expected value", "l") - legend.SetTextSize(27) - legend.SetTextFont(43) - - legend.SetBorderSize(0) - legend.SetFillColor(0) - legend.Draw() - - c.SaveAs(path+name+"_"+key_name+"_theory_comparison.pdf") - -def draw_double_signals(time_1,time_2,signal_1,signal_2,key,key_name,path): - c = ROOT.TCanvas('c', '', 800, 600) - c.SetFillColor(0) - c.SetFrameFillColor(0) - ROOT.gStyle.SetPadColor(0) - ROOT.gStyle.SetCanvasColor(0) - ROOT.gStyle.SetOptStat(0) - c.SetLeftMargin(0.15) - c.SetBottomMargin(0.15) - - mg=ROOT.TMultiGraph("mg","") - n1=len(time_1) - graph1 = ROOT.TGraph(n1,time_1,signal_1) - n2=len(time_2) - graph2 = ROOT.TGraph(n2,time_2,signal_2) - - graph1.SetLineColor(2) - graph2.SetLineColor(1) - graph1.SetMarkerColor(2) - graph2.SetMarkerColor(1) - graph1.SetMarkerStyle(26) - graph2.SetMarkerStyle(4) - - mg.Add(graph1) - mg.Add(graph2) - mg.Draw('apl') - - mg.GetYaxis().SetTitle('Signal [V]') - mg.GetXaxis().SetTitle('Time [ns]') - mg.GetYaxis().SetLabelSize(0.05) - mg.GetYaxis().SetTitleSize(0.05) - mg.GetXaxis().SetLabelSize(0.05) - mg.GetXaxis().SetTitleSize(0.05) - - mg.GetXaxis().SetLimits(0,10) - - legend = ROOT.TLegend(0.45,0.65, 0.81, 0.86) - legend.AddEntry(graph1, "RASER simulation", "pl") - legend.AddEntry(graph2, "TCT measurement", "pl") - legend.SetTextSize(27) - legend.SetTextFont(43) - - legend.SetBorderSize(0) - legend.SetFillColor(0) - legend.Draw() - - c.SaveAs(path+str(key)+key_name+"_comparison.pdf") - -def analysis_depth(path,output_path,pulse_energy_scale): - Z = array("d") - rel_z = array("d") - for L in range(-8,59): - Z.append(L) - rel_z.append(round(0.02*L,2)) - - if "experiment" in sys.argv: - amplitude, charge, risetime, velprof, difprof, volts, times = collect_data(path, "sim-TCT", pulse_energy_scale, 1e9, rel_z, 'fz_rel') - amplitude_exp, charge_exp, risetime_exp, velprof_exp, difprof_exp, volts_exp, times_exp = collect_data(path, "exp-TCT", 1, 1, rel_z, 'fz_rel') - draw_double_graphs(amplitude,amplitude_exp,Z,Z,"z","Amplitude",output_path) - draw_double_graphs(charge,charge_exp,Z,Z,"z","Charge",output_path) - draw_double_graphs(risetime,risetime_exp,Z,Z,"z","RiseTime",output_path) - draw_double_graphs(velprof,velprof_exp,Z,Z,"z","VelProf",output_path) - draw_double_graphs(difprof,difprof_exp,Z,Z,"z","DifProf",output_path) - - velprof_theory, difprof_theory = dif_cal() - Z_vel = array("d") - Z_dif = array("d") - for L in range(0,51): - Z_vel.append(L) - for L in range(2,51): - Z_dif.append(L) - draw_triple_graphs(velprof,velprof_exp,velprof_theory,Z,Z,Z_vel,"z","VelProf",output_path) - draw_triple_graphs(difprof,difprof_exp,difprof_theory,Z,Z,Z_dif,"z","DifProf",output_path) - - for volt,time,volt_exp,time_exp,z in zip(volts, times, volts_exp, times_exp, list(Z)): - draw_double_signals(time,time_exp,volt,volt_exp,z,"z",output_path) - - else: - amplitude, charge, risetime, velprof, difprof, volts, times= collect_data(path, "sim-TCT", pulse_energy_scale, 1e9, rel_z, 'fz_rel') - draw_graphs(amplitude,Z,"z","Amplitude",output_path) - draw_graphs(charge,Z,"z","Charge",output_path) - draw_graphs(risetime,Z,"z","RiseTime",output_path) - draw_graphs(velprof,Z,"z","VelProf",output_path) - draw_graphs(difprof,Z,"z","DifProf",output_path) - -def analysis_voltage(path,output_path,pulse_energy_scale): - V = array("d") - VN = array("i") - for L in range(60,220,20): - V.append(L) - VN.append(-L) - - if "experiment" in sys.argv: - amplitude, charge, risetime, velprof, difprof, volts, times = collect_data(path, "sim-TCT", pulse_energy_scale, 1e9, V, 'voltage') - amplitude_exp, charge_exp, risetime_exp, velprof_exp, difprof_exp, volts_exp, times_exp = collect_data(path, "exp-TCT", 1, 1, VN, 'voltage') - draw_double_graphs(charge,charge_exp,V,V,"voltage","Charge",output_path) - - for volt,time,volt_exp,time_exp,v in zip(volts, times, volts_exp, times_exp, list(V)): - draw_double_signals(time,time_exp,volt,volt_exp,v,"voltage",output_path) - - else: - amplitude, charge, risetime, velprof, difprof, volts, times= collect_data(path, "sim-TCT", pulse_energy_scale, 1e9, V, 'voltage') - draw_graphs(charge,V,"voltage","Charge",output_path) - -def dif_cal(): - lgad_paras = ["det_name=HPK-Si-LGAD","parfile=paras/setting.json"] - lgad_set = raser.Setting(lgad_paras) - my_lgad = raser.R3dDetector(lgad_set) - my_lgad_field = raser.FenicsCal(my_lgad,lgad_set.fenics) - - field = array("d") # in [0,50] - dif = array("d") # in [2,50] - E_2 = my_lgad_field.get_e_field(650,650,2)[2] - for i in range(0,51): - E = my_lgad_field.get_e_field(650,650,i)[2] - field.append(0.002*E) - if i not in range(2,51): - continue - fE = (E_2/E)**2 - C = (350e-12*1e5*1e6/2)**2/2/np.log(2) # Ï„^2v^2 - z1C0 = (6.8/2)**2 # w_0^2/4 - z1C2 = 1.064**2/4/np.pi**2/(6.8/2)**2/11.9**2 - z2 = 2.8 - alpha = 9.87e-4 - def f(x): - return np.exp(-alpha*x)*alpha/(C + (z1C2 * x**2 + z1C0) * fE + z2/2 * (fE-1))**0.5 - - n = 1301 - x_list = np.linspace(0, 1300, n) # in cm - f_list = np.zeros(n) - for j in range(n): - f_list[j] = f(x_list[j]) - - int_f = 0 - for j in range(n-1): - int_f += (f_list[j] + f_list[j+1]) * (x_list[j+1] - x_list[j]) /2 - - dif.append(int_f) - - return field,dif - -def main(): - path=sys.argv[1] - output_path=sys.argv[2] - if not os.access(output_path, os.F_OK): - os.makedirs(output_path, exist_ok=True) - if 'LGAD' in path: - pulse_energy_scale = 1.58 - else: - pulse_energy_scale = 1 - # the pulse energy difference in experiment - analysis_depth(path,output_path,pulse_energy_scale) - analysis_voltage(path,output_path,pulse_energy_scale) - -if __name__ == "__main__": - main() diff --git a/tct/tct_signal.py b/tct/tct_signal.py index e08a73adab33d52250b5edbd202e07435a546739..2af29b6ec5feeba376aed023a0e8568a49ebe881 100644 --- a/tct/tct_signal.py +++ b/tct/tct_signal.py @@ -1,73 +1,133 @@ #!/usr/bin/env python3 # -*- encoding: utf-8 -*- -import os import sys -sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) -import raser -from .save_TTree import save_signal_TTree +import os +import array +import time +import subprocess +import json +import time -# TODO: Need to be rewritten! +import ROOT -import time -from util.output import output +from field import build_device as bdv +from field import devsim_field as devfield +from current import cal_current as ccrt +from elec import readout as rdo +from elec import ngspice_set_input as ngsip +from elec import ngspice as ng +from .source import TCTTracks +from .save_TTree import save_signal_TTree +from util.output import output, create_path from gen_signal.draw_save import draw_plots -args = sys.argv[1:] -start = time.time() -dset = raser.Setting(args) -if "parameter_alter=True" in args: - # need to put the changed value at the end of the parameter list - key,_,value=args[-1].rpartition('=') - value=float(value) - if key in dset.laser_paras: - dset.laser_paras.update({key:value}) - key_string = str(dset.laser_paras[key])+key - elif key in dset.paras: - dset.paras.update({key:value}) - key_string = str(dset.paras[key])+key -else: - key_string = "" -my_d = raser.R3dDetector(dset) +def main(kwargs): + """ + Description: + The main program of Raser induced current simulation + Parameters: + --------- + dset : class + Parameters of simulation + Function or class: + Detector -- Define the basic parameters and mesh structure of the detector + DevsimCal -- Get the electric field and weighting potential + Particles -- Electron and hole paris distibution + CalCurrent -- Drift of e-h pais and induced current + Amplifier -- Readout electronics simulation + draw_plots -- Draw electric field, drift path and energy deposition + Modify: + --------- + 2021/09/02 + """ + start = time.time() -if('devsim' in args): - print("using devsim to build the field") - my_f = raser.DevsimCal(my_d, dset.det_name, dset.detector, dset.fenics) -else: - print("using fenics to build the field") - my_f = raser.FenicsCal(my_d,dset.fenics) + det_name = kwargs['det_name'] + my_d = bdv.Detector(det_name) + + if kwargs['voltage'] != None: + voltage = float(kwargs['voltage']) + else: + voltage = float(my_d.voltage) -my_l = raser.TCTTracks(my_d, dset.laser) -my_current = raser.CalCurrentLaser(my_d, my_f, my_l) -ele_current = raser.Amplifier(my_current, dset.amplifier) -if "ngspice" in args: - my_current.save_current(dset,my_d,my_l,my_f,"fx_rel") - input_p=ngsip.set_input(dset,my_current,my_l,my_d,"fx_rel") - input_c=','.join(input_p) - with open('paras/circuitT1.cir', 'r') as f: - lines = f.readlines() - lines[113] = 'I1 2 0 PWL('+str(input_c)+') \n' - lines[140] = 'tran 0.1p ' + str((input_p[len(input_p) - 2])) + '\n' - lines[141] = 'wrdata output/t1.raw v(out)\n' - f.close() - with open('output/T1_tmp.cir', 'w') as f: - f.writelines(lines) - f.close() -if "scan=True" in args: #assume parameter alter - save_signal_TTree(dset,my_d,key_string,ele_current,my_f) - if "planar3D" in my_d.det_model or "planarRing" in my_d.det_model: - path = "output/" + "pintct/" + dset.det_name + "/" - elif "lgad3D" in my_d.det_model: - path = "output/" + "lgadtct/" + dset.det_name + "/" + if kwargs['laser'] != None: + laser = kwargs['laser'] + laser_json = "./setting/laser/" + laser + ".json" + with open(laser_json) as f: + laser_dic = json.load(f) else: + # TCT must be with laser raise NameError -else: - draw_plots(my_d,ele_current,my_f,None,my_current,my_l) -if "draw_carrier" in label: - now = time.strftime("%Y_%m%d_%H%M") - path = output(__path__, now) - my_l.draw_nocarrier3D(path,my_l) - my_l.draw_nocarrier2D(path,my_l) + if kwargs['amplifier'] != None: + amplifier = kwargs['amplifier'] + else: + amplifier = my_d.amplifier + + if "strip" in det_name: + my_f = devfield.DevsimField(my_d.device, my_d.dimension, voltage, my_d.read_ele_num, my_d.l_z) + else: + my_f = devfield.DevsimField(my_d.device, my_d.dimension, voltage, 1, my_d.l_z) + + my_l = TCTTracks(my_d, laser_dic) + + if "strip" in det_name: + pass + else: + my_current = ccrt.CalCurrentLaser(my_d, my_f, my_l) + + if 'ngspice' in amplifier: + save_current(my_d, my_current,my_f = devfield.DevsimField(my_d.device, my_d.dimension, voltage, 1, my_d.l_z), key=None) + input_p=ngsip.set_input(my_current, my_d, key=None) + input_c=','.join(input_p) + ng.ngspice_t0(input_c, input_p) + subprocess.run(['ngspice -b -r t0.raw output/T0_tmp.cir'], shell=True) + ng.plot_waveform() + else: + ele_current = rdo.Amplifier(my_current.sum_cu, amplifier) + + if kwargs['scan'] != None: #assume parameter alter + key = my_l.fz_rel + save_signal_TTree(my_d,key,ele_current,my_f) + if "planar3D" in my_d.det_model or "planarRing" in my_d.det_model: + path = "output/" + "pintct/" + my_d.det_name + "/" + elif "lgad3D" in my_d.det_model: + path = "output/" + "lgadtct/" + my_d.det_name + "/" + else: + raise NameError + else: + path = output(__file__, my_d.det_name, my_l.model) + draw_plots(my_d,ele_current,my_f,None,my_current,my_l,path) + print("total time used:%s"%(time.time()-start)) + +#TODO: move this to calcurrent +def save_current(my_d,my_current,my_f,key): + if "planar3D" in my_d.det_model or "planarRing" in my_d.det_model: + path = os.path.join('output', 'pintct', my_d.det_name, ) + elif "lgad3D" in my_d.det_model: + path = os.path.join('output', 'lgadtct', my_d.det_name, ) + create_path(path) + L = eval("my_l.{}".format(key)) + #L is defined by different keys + time = array('d', [999.]) + current = array('d', [999.]) + fout = ROOT.TFile(os.path.join(path, "sim-TCT-current") + str(L) + ".root", "RECREATE") + t_out = ROOT.TTree("tree", "signal") + t_out.Branch("time", time, "time/D") + for i in range(my_current.read_ele_num): + t_out.Branch("current"+str(i), current, "current"+str(i)+"/D") + for j in range(my_current.n_bin): + current[0]=my_current.sum_cu[i].GetBinContent(j) + time[0]=j*my_current.t_bin + t_out.Fill() + t_out.Write() + fout.Close() -print("total time used:%s"%(time.time()-start)) +if __name__ == '__main__': + args = sys.argv[1:] + kwargs = {} + for arg in args: + key, value = arg.split('=') + kwargs[key] = value + main(kwargs) \ No newline at end of file diff --git a/tct/tct_t1.py b/tct/tct_t1.py index 5701fd72fdb1311889549c60b6b98b650b062c3c..7cc4d52d43cdd3b591794cd592f79e600663f996 100644 --- a/tct/tct_t1.py +++ b/tct/tct_t1.py @@ -26,7 +26,7 @@ my_f = raser.FenicsCal(my_d, dset.fenics) my_l = raser.TCTTracks(my_d, dset.laser) my_current = raser.CalCurrentLaser(my_d, my_f, my_l) -ele_current = raser.Amplifier(my_current, dset.amplifier) +ele_current = raser.Amplifier(my_current.sum_cu, dset.amplifier) save_TTree.save_signal_TTree(dset,my_d,my_l.fx_rel,ele_current,my_f) my_current.save_current(dset,my_d,my_l,my_f,"fx_rel") @@ -64,13 +64,13 @@ t_start = t1 t_rise = t2 - t1 t_fall = t3 - t2 -with open('paras/circuitT1.cir', 'r') as f: +with open('param_file/circuit/T1.cir', 'r') as f: lines = f.readlines() lines[113] = 'I1 2 0 pulse(0 ' + str(c_max) + 'u ' + str(t_start) + 'n ' + str(t_rise) + 'n ' + str(t_fall) + 'n 0.00000001n ' + str((T_ele[len(T_ele) - 1])) + 'n 0)\n' lines[140] = 'tran 0.1p ' + str((T_ele[len(T_ele) - 1])) + 'n\n' lines[142] = 'wrdata output/t1.raw v(out)\n' f.close() -with open('output/T1_tmp.cir', 'w') as f: +with open('output/elec/T1_tmp.cir', 'w') as f: f.writelines(lines) f.close() diff --git a/util/batchjob.py b/util/batchjob.py index 600ab2b306a0ddb2c9448d49f3c8ed6f7307539a..36ac65e99eacc36c108dcf4665740a19df1db263 100644 --- a/util/batchjob.py +++ b/util/batchjob.py @@ -13,6 +13,8 @@ import subprocess import grp import pwd +from util.output import create_path + def main(destination_subfolder, command, args): test = vars(args)['test'] stat_info = os.stat("./") @@ -40,11 +42,6 @@ def submit_job(jobfile_name,destination_subfolder,group, test=False): destination_subfolder,destination_subfolder,jobfile_name,group) run_cmd(command, test) -def create_path(path): - """ If the path does not exit, create the path""" - if not os.access(path, os.F_OK): - os.makedirs(path, exist_ok=True) - def run_cmd(command, test=False): if test: sys.stdout.write(command+'\n') diff --git a/util/io_decorator.py b/util/io_decorator.py new file mode 100644 index 0000000000000000000000000000000000000000..3dcc74dd612e5d4960a949d57c1f35529af0cce8 --- /dev/null +++ b/util/io_decorator.py @@ -0,0 +1,31 @@ +import sys +import io +from contextlib import redirect_stdout, redirect_stderr +import importlib.util +import inspect + +def io_decorator(func): + def wrapper(*args, **kwargs): + try: + # Capture the standard output and error + stdout_buffer = io.StringIO() + stderr_buffer = io.StringIO() + + with redirect_stdout(stdout_buffer), redirect_stderr(stderr_buffer): + func(*args, **kwargs) + # Get the output + stdout_output = stdout_buffer.getvalue() + stderr_output = stderr_buffer.getvalue() + + print(f"Function '{func.__name__}' executed successfully.") + print("Standard Output:") + print(stdout_output) + + if stderr_output: + print("Standard Error:") + print(stderr_output) + + except Exception as e: + print(f"Function '{func.__name__}' failed with an exception:", e) + + return wrapper diff --git a/util/math.py b/util/math.py new file mode 100644 index 0000000000000000000000000000000000000000..1d8c72aefeea4ec435fd98b9b98bd4ed7b60af6e --- /dev/null +++ b/util/math.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python3 +# -*- encoding: utf-8 -*- + +''' +Description: + Math Objects +@Date : 2024/09/19 20:57:33 +@Author : Chenxi Fu +@version : 1.0 +''' + +import math +from typing import Callable + +import numpy as np +from scipy.interpolate import interp1d as p1d +from scipy.interpolate import interp2d as p2d +from scipy.interpolate import griddata +from scipy.interpolate import LinearNDInterpolator as LNDI +import ROOT + +x_bin = 1000 +y_bin = 1000 +z_bin = 1000 + +class Vector: + def __init__(self,a1,a2,a3): + self.components = [a1,a2,a3] + + def cross(self,Vector_b): + """ Get vector cross product of self and another Vector""" + o1 = self.components[1]*Vector_b.components[2]-self.components[2]*Vector_b.components[1] + o2 = self.components[2]*Vector_b.components[0]-self.components[0]*Vector_b.components[2] + o3 = self.components[0]*Vector_b.components[1]-self.components[1]*Vector_b.components[0] + return Vector(o1,o2,o3) + + def get_length(self): + " Return length of self" + return math.sqrt(self.components[0]*self.components[0]+self.components[1]*self.components[1]+self.components[2]*self.components[2]) + + def add(self,Vector_b): + " Return the sum of two Vectors. eg: [1,2,3]+[1,2,3] = [2,4,6]" + o1 = self.components[0]+Vector_b.components[0] + o2 = self.components[1]+Vector_b.components[1] + o3 = self.components[2]+Vector_b.components[2] + return Vector(o1,o2,o3) + + def sub(self,Vector_b): + " Return the subtraction of two Vectors. eg: [1,2,3]-[1,2,3] = [0,0,0]" + o1 = self.components[0]-Vector_b.components[0] + o2 = self.components[1]-Vector_b.components[1] + o3 = self.components[2]-Vector_b.components[2] + return Vector(o1,o2,o3) + + def mul(self,k): + " Return Vector multiplied by number. eg: 2 * [1,2,3] = [2,4,6]" + return Vector(self.components[0]*k,self.components[1]*k,self.components[2]*k) + + +def get_common_interpolate_1d(data): + values = data['values'] + points = data['points'] + f = p1d(points, values) + return f + +def get_common_interpolate_2d(data): + values = data['values'] + points_x = [] + points_y = [] + for point in data['points']: + points_x.append(point[0]) + points_y.append(point[1]) + new_x = np.linspace(min(points_x), max(points_x), x_bin) + new_y = np.linspace(min(points_y), max(points_y), y_bin) + new_points = np.array(np.meshgrid(new_x, new_y)).T.reshape(-1, 2) + new_values = griddata((points_x, points_y), values, new_points, method='linear') + f = p2d(new_x, new_y, new_values) + return f + +def get_common_interpolate_3d(data): + values = data['values'] + points_x = [] + points_y = [] + points_z = [] + for point in data['points']: + points_x.append(point[0]) + points_y.append(point[1]) + points_z.append(point[2]) + + new_x = np.linspace(min(points_x), max(points_x), x_bin) + new_y = np.linspace(min(points_y), max(points_y), y_bin) + new_z = np.linspace(min(points_z), max(points_z), z_bin) + new_points = np.array(np.meshgrid(new_x, new_y, new_z)).T.reshape(-1, 3) + new_values = griddata((points_x, points_y, points_z), values, new_points, method='linear') + lndi = LNDI(new_points, new_values) + def f(x, y, z): + point = [x, y, z] + return lndi(point) + return f + +def signal_convolution(signal_original: ROOT.TH1F, signal_convolved: ROOT.TH1F, pulse_responce_function_list: list[Callable[[float],float]]): + so = signal_original + sc = signal_convolved + st = ROOT.TH1F("signal_temp","signal_temp",so.GetNbinsX(),so.GetXaxis().GetXmin(),so.GetXaxis().GetXmax()) + st.Reset() + st.Add(so) + + t_bin = so.GetBinWidth(0) # for uniform bin + n_bin = so.GetNbinsX() + for pr in pulse_responce_function_list: + for i in range(n_bin): + st_i = st.GetBinContent(i) + for j in range(-i,n_bin-i): + pr_j = pr(j*t_bin) + sc.Fill((i+j)*t_bin + 1e-14, st_i*pr_j*t_bin) # 1e-14 resolves float error + st.Reset() + st.Add(sc) + sc.Reset() + + sc.Add(st) +