CalcGM_Noise_LMU.py 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603
  1. # -*- coding: utf-8 -*-
  2. """
  3. Created on Fri Oct 05 15:49:46 2018
  4. @author: aemdlabs
  5. """
  6. #!/usr/bin/env python2
  7. # -*- coding: utf-8 -*-
  8. """
  9. Created on Wed Sep 5 12:05:21 2018
  10. @author: aguimera
  11. """
  12. from PhyREC.NeoInterface import NeoSegment, NeoSignal#, ReadMCSFile
  13. import PhyREC.SignalAnalysis as Ran
  14. import PhyREC.PlotWaves as Rplt
  15. import PhyREC.SignalAnalysis as Ran
  16. import quantities as pq
  17. import matplotlib.pyplot as plt
  18. import numpy as np
  19. import neo
  20. import PhyREC.SignalProcess as RPro
  21. import deepdish as dd
  22. import csv
  23. from datetime import datetime
  24. import os
  25. from scipy import integrate
  26. from scipy.interpolate import interp1d
  27. import PyGFET.AnalyzeData as FETana
  28. import PyGFET.PlotDataClass as FETplt
  29. def ReadMCSFile(McsFile, OutSeg=None, SigNamePrefix=''):
  30. import McsPy.McsData as McsData
  31. Dat = McsData.RawData(McsFile)
  32. Rec = Dat.recordings[0]
  33. NSamps = Rec.duration
  34. if OutSeg is None:
  35. OutSeg = NeoSegment()
  36. for AnaStrn, AnaStr in Rec.analog_streams.iteritems():
  37. if len(AnaStr.channel_infos) == 1:
  38. continue
  39. for Chn, Chinfo in AnaStr.channel_infos.iteritems():
  40. print 'Analog Stream ', Chinfo.label, Chinfo.sampling_frequency
  41. ChName = str(SigNamePrefix + Chinfo.label)
  42. print ChName
  43. Fs = Chinfo.sampling_frequency
  44. Var, Unit = AnaStr.get_channel_in_range(Chn, 0, NSamps)
  45. sig = neo.AnalogSignal(pq.Quantity(Var, Chinfo.info['Unit']),
  46. t_start=0*pq.s,
  47. sampling_rate=Fs.magnitude*pq.Hz,
  48. name=ChName)
  49. OutSeg.AddSignal(sig)
  50. return OutSeg
  51. def ReadLogFile(File):
  52. Fin = open(File)
  53. reader = csv.reader(Fin, delimiter='\t')
  54. LogVals = {}
  55. ValsPos = {}
  56. for il, e in enumerate(reader):
  57. if il == 0:
  58. for ih, v in enumerate(e):
  59. ValsPos[ih] = v
  60. LogVals[v] = []
  61. else:
  62. for ih, v in enumerate(e):
  63. par = ValsPos[ih]
  64. if (par=='Vgs') or (par=='Vds') or (par=='Vref'):
  65. LogVals[par].append(float(v.replace(',','.')))
  66. elif par == 'Date/Time':
  67. LogVals[par].append(datetime.strptime(v, '%d/%m/%Y %H:%M:%S'))
  68. else:
  69. LogVals[par].append(v)
  70. deltas = np.array(LogVals['Date/Time'])[:]-LogVals['Date/Time'][0]
  71. LogVals['Time'] = []
  72. for d in deltas:
  73. LogVals['Time'].append(d.total_seconds())
  74. Fin.close()
  75. return LogVals
  76. def GetSwitchTimes(Sig, Thres=-1e-4, Plot=True):
  77. s = Sig.GetSignal(None)
  78. ds = np.abs(np.diff(np.array(s), axis=0))
  79. if Plot:
  80. plt.figure()
  81. plt.plot(s.times, s)
  82. plt.plot(s.times[1:], ds)
  83. ds = Sig.duplicate_with_new_array(signal=ds)
  84. Times = Ran.threshold_detection(ds,
  85. threshold=Thres,
  86. RelaxTime=5*pq.s)
  87. return Times
  88. def MeanStd(Data, var):
  89. Arr = np.zeros([len(Data.keys()),len(Data[Data.keys()[0]][var])])
  90. for iT,TrtName in enumerate(Data.keys()):
  91. Arr[iT,:] = Data[TrtName][var][:,0]
  92. return np.mean(Arr,0), np.std(Arr,0)
  93. def MeanStdGM(Data):
  94. Arr = np.zeros([len(Data.keys()),len(Data[Data.keys()[0]])])
  95. for iT,TrtName in enumerate(Data.keys()):
  96. Arr[iT,:] = Data[TrtName]
  97. return np.mean(Arr,0), np.std(Arr,0)
  98. def Integrate(PSD, Freqs, Fmin, Fmax):
  99. indices = np.where((Freqs >= Fmin) & (Freqs<=Fmax))
  100. print( Freqs[indices])
  101. Irms = np.sqrt(integrate.trapz(PSD[indices], Freqs[indices]))
  102. return Irms
  103. MCSMapI={'SE1':'Ch03',
  104. 'SE2':'Ch05',
  105. 'SE3':'Ch01',
  106. 'SE4':'Ch02',
  107. 'SE5':'Ch22',
  108. 'SE6':'Ch06',
  109. 'SE7':'Ch16',
  110. 'SE8':'Ch37',
  111. 'SE9':'Ch20',
  112. 'SE10':'Ch10',
  113. 'SE11':'Ch24',
  114. 'SE12':'Ch08',
  115. 'SE13':'Ch14',
  116. 'SE14':'Ch04',
  117. 'SE15':'Ch18',
  118. 'SE16':'Ch33',
  119. 'SE17':'Ch34',
  120. 'SE18':'Ch60',
  121. 'SE19':'Ch38',
  122. 'SE20':'Ch64',
  123. 'SE21':'Ch40',
  124. 'SE22':'Ch56',
  125. 'SE23':'Ch42',
  126. 'SE24':'Ch70',
  127. 'SE25':'Ch66',
  128. 'SE26':'Ch65',
  129. 'SE27':'Ch68',
  130. 'SE28':'Ch67',
  131. 'SE29':'Ch55',
  132. 'SE30':'Ch62',
  133. 'SE31':'Ch58',
  134. 'SE32':'Ch69',
  135. 'ME1':'Ch57',
  136. 'ME2':'Ch61',
  137. 'ME3':'Ch53',
  138. 'ME4':'Ch63',
  139. 'ME5':'Ch52',
  140. 'ME6':'Ch41',
  141. 'ME7':'Ch49',
  142. 'ME8':'Ch51',
  143. 'ME9':'Ch46',
  144. 'ME10':'Ch45',
  145. 'ME11':'Ch44',
  146. 'ME12':'Ch39',
  147. 'ME13':'Ch54',
  148. 'ME14':'Ch43',
  149. 'ME15':'Ch50',
  150. 'ME16':'Ch47',
  151. 'ME17':'Ch32',
  152. 'ME18':'Ch27',
  153. 'ME19':'Ch30',
  154. 'ME20':'Ch29',
  155. 'ME21':'Ch28',
  156. 'ME22':'Ch25',
  157. 'ME23':'Ch26',
  158. 'ME24':'Ch07',
  159. 'ME25':'Ch21',
  160. 'ME26':'Ch11',
  161. 'ME27':'Ch17',
  162. 'ME28':'Ch15',
  163. 'ME29':'Ch13',
  164. 'ME30':'Ch31',
  165. 'ME31':'Ch19',
  166. 'ME32':'Ch09'}
  167. #Col, Row
  168. MCSMapFacingDown={'Ch58':(0,1),
  169. 'Ch57':(0,2),
  170. 'Ch56':(0,3),
  171. 'Ch55':(0,4),
  172. 'Ch54':(0,5),
  173. 'Ch53':(0,6),
  174. 'Ch52':(0,7),
  175. 'Ch51':(0,8),
  176. 'Ch50':(0,9),
  177. 'Ch49':(0,10),
  178. 'Ch60':(1,0),
  179. 'Ch61':(1,1),
  180. 'Ch62':(1,2),
  181. 'Ch63':(1,3),
  182. 'Ch64':(1,4),
  183. 'Ch65':(1,5),
  184. 'Ch43':(1,6),
  185. 'Ch44':(1,7),
  186. 'Ch45':(1,8),
  187. 'Ch46':(1,9),
  188. 'Ch47':(1,10),
  189. 'Ch70':(2,0),
  190. 'Ch69':(2,1),
  191. 'Ch68':(2,2),
  192. 'Ch67':(2,3),
  193. 'Ch66':(2,4),
  194. 'Ch42':(2,5),
  195. 'Ch41':(2,6),
  196. 'Ch40':(2,7),
  197. 'Ch39':(2,8),
  198. 'Ch38':(2,9),
  199. 'Ch37':(2,10),
  200. 'Ch01':(3,0),
  201. 'Ch02':(3,1),
  202. 'Ch03':(3,2),
  203. 'Ch04':(3,3),
  204. 'Ch05':(3,4),
  205. 'Ch06':(3,5),
  206. 'Ch30':(3,6),
  207. 'Ch31':(3,7),
  208. 'Ch32':(3,8),
  209. 'Ch33':(3,9),
  210. 'Ch34':(3,10),
  211. 'Ch11':(4,0),
  212. 'Ch10':(4,1),
  213. 'Ch09':(4,2),
  214. 'Ch08':(4,3),
  215. 'Ch07':(4,4),
  216. 'Ch29':(4,5),
  217. 'Ch28':(4,6),
  218. 'Ch27':(4,7),
  219. 'Ch26':(4,8),
  220. 'Ch25':(4,9),
  221. 'Ch24':(4,10),
  222. 'Ch12':None,
  223. 'Ch59':None,
  224. 'Ch13':(5,1),
  225. 'Ch14':(5,2),
  226. 'Ch15':(5,3),
  227. 'Ch16':(5,4),
  228. 'Ch17':(5,5),
  229. 'Ch18':(5,6),
  230. 'Ch19':(5,7),
  231. 'Ch20':(5,8),
  232. 'Ch21':(5,9),
  233. 'Ch22':(5,10)}
  234. if __name__ == '__main__':
  235. # Path = '../Characterization/28062019/B12142O37-T2/'
  236. # InFileM = Path + '2019-06-29T18-00-36B12142O37-T2-1mVVgsSweep-ICN2-PostEthx2-Pt.h5' ############
  237. # InFileS = Path + '2019-06-29T18-00-36B12142O37-T2-1mVVgsSweep-ICN2-PostEthx2-Pt_2.h5' ##########
  238. # LogFile = Path + 'B12142O37-T2-ACDC-PostEthx2-Pt.txt'
  239. # IVFigFile = 'Figs/InVivo-B12142O37-T2-2.png'
  240. # GMFigFile = 'Figs/InVivo-B12142O37-T2-2.png'
  241. # FoutDCvals = 'InVivo-B12142O37-T2-2.h5'
  242. #
  243. # Path = '../Characterization/28062019/B12142O30-T4/'
  244. # InFileM = Path + '2019-06-29T17-31-17B12142O30-T4-1mVVgsSweep-ICN2-Pt-2.h5' ############
  245. # InFileS = Path + '2019-06-29T17-31-17B12142O30-T4-1mVVgsSweep-ICN2-Pt-2_2.h5' ##########
  246. # LogFile = Path + 'B12142O30-T4-PreEth-ACDC-1mV-Pt-2.txt'
  247. # Path = '../Characterization/03072019/B12142O37-T4/'
  248. # InFileM = Path + '2019-07-03T09-23-45B12142O37-T4-ACDC-1mVsine-Pt-PostEthx2.h5' ############
  249. # InFileS = Path + '2019-07-03T09-23-45B12142O37-T4-ACDC-1mVsine-Pt-PostEthx2_2.h5' ##########
  250. # LogFile = Path + 'B12142O37-T4-ACDC-Pt-PostEthx2.txt'
  251. #
  252. # Path = '../Characterization/03072019/B12142O30-T9/'
  253. # InFileM = Path + '2019-07-03T10-43-12B12142O30-T9-ACDC-1mVsine-Pt-PostEth.h5' ############
  254. # InFileS = Path + '2019-07-03T10-43-12B12142O30-T9-ACDC-1mVsine-Pt-PostEth_2.h5' ##########
  255. # LogFile = Path + 'B12142o30-T9-ACDC-Pt-PostEth.txt'
  256. Path = ''
  257. InFileM = Path + '2019-07-23T16-18-20B12784O18-T2-ACDC-PostEth-1mV_2.h5' ############
  258. InFileS = Path + '2019-07-23T16-18-20B12784O18-T2-ACDC-PostEth-1mV_2_2.h5' ##########
  259. LogFile = Path + 'B12784O18-T2-ACDC-PostEth_Cy2.txt'
  260. StartCycle = -1
  261. LogVals = ReadLogFile(LogFile)
  262. delta = np.mean([t-LogVals['Time'][it] for it, t in enumerate(LogVals['Time'][1:])])*pq.s
  263. Delay = delta * StartCycle
  264. DCch = ('ME5', 'ME7', 'ME29', 'ME31', 'SE5', 'SE7', 'SE29', 'SE31')
  265. TrigChannel = 'SE31'
  266. TrigThres = 5e-5
  267. Vgs = np.array(LogVals['Vgs'])
  268. Vds = LogVals['Vds'][0]
  269. ivgain1 = 12e3*pq.V
  270. ivgain2 = 101
  271. ACgain = 10*1
  272. DCgain = 1*pq.V
  273. Fsig = 10
  274. StabTime = 10*pq.s
  275. GuardTime = 1*pq.s
  276. BW = 100
  277. ivgainDC = 118.8*pq.V #the gain (1e6) is already applied to the saved signal ## Check this gain
  278. ivgainAC = 1188*pq.V
  279. #
  280. # SigProAC = [{'function': RPro.Gain, 'args': {'Gain': pq.A/ACgain}},
  281. # {'function': RPro.Filter, 'args': {'Type':'highpass',
  282. # 'Order':2,
  283. # 'Freqs':(1)}},
  284. # ]
  285. #
  286. # SigProDC = [{'function': RPro.Gain, 'args': {'Gain': pq.A/DCgain}},
  287. # {'function': RPro.Filter, 'args': {'Type':'highpass',
  288. # 'Order':2,
  289. # 'Freqs':(1)}},
  290. # ]
  291. Rec = ReadMCSFile(InFileM,
  292. OutSeg=None,
  293. SigNamePrefix='M')
  294. Rec = ReadMCSFile(InFileS,
  295. OutSeg=Rec,
  296. SigNamePrefix='S')
  297. # %%
  298. plt.close('all')
  299. plt.ion()
  300. SwTimes = GetSwitchTimes(Sig=Rec.GetSignal(TrigChannel),
  301. Thres=TrigThres,
  302. Plot=True)
  303. SlotsDC = []
  304. SlotsAC = []
  305. for sig in Rec.Signals():
  306. if sig.name not in DCch:
  307. continue
  308. if sig.name.startswith('M'):
  309. col = 'r'
  310. else:
  311. col = 'g'
  312. SlotsDC.append(Rplt.WaveSlot(sig,
  313. Position=0,
  314. Color=col,
  315. Alpha=0.5))
  316. Splots = Rplt.PlotSlots(SlotsDC)
  317. Splots.PlotChannels(Time=None,
  318. Units='mV')
  319. Splots.PlotEvents(SwTimes,
  320. color='k')
  321. Splots.PlotEvents(LogVals['Time']*pq.s+SwTimes[0]+Delay,
  322. color='r')
  323. SwTimes = LogVals['Time']*pq.s+SwTimes[0]+Delay
  324. #%% calc IV DC
  325. DevDCVals = {}
  326. fig, Axt = plt.subplots()
  327. Ids = {}
  328. for sl in SlotsDC:
  329. Ids[sl.name] = []
  330. for isw, (t, vg) in enumerate(zip(SwTimes, Vgs)):
  331. ts = SwTimes[isw]+delta
  332. TWind = (t+StabTime, ts-GuardTime)
  333. s = sl.GetSignal(TWind, Units='V')
  334. Axt.plot(s)
  335. vio = np.mean(s).magnitude
  336. ids = (vio*101-(-vg+Vds))/12e3
  337. Ids[sl.name].append(ids)
  338. DCVals = {'Ids': np.array((Ids[sl.name],)).transpose(),
  339. 'Vds': np.array((Vds,)),
  340. 'Vgs': np.array(Vgs),
  341. 'ChName': sl.name,
  342. 'Name': sl.name,
  343. 'DateTime': LogVals['Date/Time'][0]}
  344. DevDCVals[sl.name] = DCVals
  345. FETana.CheckIsOK(DevDCVals, RdsRange=[400, 40e3])
  346. FETana.CalcGM(DevDCVals)
  347. pltDC = FETplt.PyFETPlot()
  348. pltDC.AddAxes(('Ids', 'Gm', 'Rds'))
  349. pltDC.PlotDataCh(DevDCVals, PltIsOK=True)
  350. pltDC.AddLegend()
  351. # if os.path.exists(IVFigFile[0:-7]) == False:
  352. # os.mkdir((IVFigFile[0:-7]))
  353. # pltDC.Fig.savefig(IVFigFile[0:-7]+'/'+IVFigFile[5:])
  354. #%% Calc GM
  355. GM = {}
  356. Irms = {}
  357. Urms = {}
  358. UrmsDrift = {}
  359. SNR = {}
  360. Irms2 = {}
  361. figgm, axgm = plt.subplots()
  362. fig, (AxPsd, Axt) = plt.subplots(2,1)
  363. fig2, (AxPs, Axt) = plt.subplots(2,1)
  364. for sig in Rec.Signals():
  365. if sig.name[0:3] == 'SEn':
  366. continue
  367. # if sig.name in DCch:
  368. # sig.SignalProcess = SigProDC
  369. # else:
  370. # sig.SignalProcess = SigProAC
  371. #
  372. GM[sig.name] = []
  373. Irms[sig.name] = []
  374. Irms2[sig.name] = []
  375. Urms[sig.name] = []
  376. SNR[sig.name] = []
  377. UrmsDrift[sig.name] = []
  378. for isw, (t, vg) in enumerate(zip(SwTimes, Vgs)):
  379. if isw == len(SwTimes)-1:
  380. ts = sl.Signal.t_stop
  381. else:
  382. ts = SwTimes[isw+1]
  383. TWind = (t+StabTime, ts-GuardTime)
  384. s = sig.GetSignal(TWind, Units ='V')
  385. if s.name in DCch:
  386. s = (s*ivgain2-(-vg+Vds)*pq.V)/ivgain1
  387. else:
  388. s = s/(ivgain1*ACgain/ivgain2)
  389. Axt.plot(s.times, s, label=vg, alpha=0.5)
  390. PS = Ran.PlotPSD((s,),
  391. Time = TWind,
  392. Ax=AxPs,
  393. FMin=1,
  394. Label=str(vg),
  395. scaling='spectrum')
  396. ps = PS[sig.name]['psd']
  397. Fps = PS[sig.name]['ff']
  398. indicesPeak = np.where( ((Fps >= Fsig-4) & (Fps<=Fsig+4)))
  399. IDSpeak = np.sqrt(ps[np.argmax(ps[indicesPeak])+indicesPeak[0][0]]+
  400. ps[np.argmax(ps[indicesPeak])+indicesPeak[0][0]+1]+
  401. ps[np.argmax(ps[indicesPeak])+indicesPeak[0][0]-1])
  402. #
  403. gm = IDSpeak*1000/0.707
  404. GM[sig.name] = np.append(GM[sig.name],gm)
  405. PSD = Ran.PlotPSD((s,),
  406. Time = TWind,
  407. Ax=AxPsd,
  408. FMin=1,
  409. Label=str(vg),
  410. scaling='density')
  411. psd = PSD[sig.name]['psd'][:,0]
  412. Fpsd = PSD[sig.name]['ff']
  413. irms = Integrate(psd, Fpsd, 1.9, 1.9*3.2)
  414. Irms[sig.name] = np.append(Irms[sig.name],irms*2)
  415. Irms[sig.name] = Irms[sig.name]
  416. irms2 = np.sqrt(psd[2]*Fpsd[2]*np.log(100))
  417. Irms2[sig.name] = np.append(Irms2[sig.name],irms2)
  418. Irms2[sig.name] = Irms2[sig.name]
  419. SNR[sig.name] = 20*np.log10(GM[sig.name]*(0.707/1000)/Irms[sig.name])
  420. # if float(SNR[sig.name][0]) <=15:
  421. # continue
  422. Urms[sig.name] = Irms[sig.name]/GM[sig.name]
  423. Polate = interp1d(Vgs-0.34,Urms[sig.name])
  424. VgsInt=np.linspace(-0.2,-0.01,10)
  425. UrmsDrift[sig.name] = Polate(VgsInt)
  426. plt.figure(8)
  427. plt.plot(Vgs-0.34, Urms[sig.name],'k',alpha=0.1)
  428. # axgm.plot(Vgs, GM[sig.name], label=sig.name)
  429. plt.figure(9)
  430. plt.plot(Vgs, SNR[sig.name])
  431. axgm.plot(Vgs, GM[sig.name], label=sig.name)
  432. # plt.figure(8)
  433. # plt.plot(Vgs-0.7, Urms[sig.name])
  434. plt.figure(5)
  435. plt.xlabel('Ugs(V)')
  436. plt.ylabel('Gm(S)')
  437. # fig.savefig(IVFigFile[0:-7]+'/'+sig.name+'psd'+'.png')
  438. # plt.close(fig)
  439. # plt.close()
  440. plt.figure(6)
  441. GMmean, GMstd = MeanStdGM(GM)
  442. plt.plot(Vgs, GMmean*1000/0.1,'k',label = '1 metal layer')
  443. plt.fill_between(Vgs-0.70, GMmean*1000/0.1-GMstd*1000/0.1, GMmean*1000/0.1+GMstd*1000/0.1,color = 'k',alpha =0.3)
  444. plt.xlabel('V$_{gs}$ - V$_{CNP}$ (V)')
  445. plt.ylabel('G$_m$ (mS/V)')
  446. plt.legend()
  447. plt.figure(7)
  448. IrmsMean, IrmsStd = MeanStdGM(Irms)
  449. plt.semilogy(Vgs, IrmsMean,'k',label = 'rms')
  450. plt.fill_between(Vgs, IrmsMean-IrmsStd, IrmsMean+IrmsStd ,color = 'k',alpha =0.3)
  451. IrmsMean2, IrmsStd2 = MeanStdGM(Irms2)
  452. plt.semilogy(Vgs, IrmsMean2,'b',label = 'a param')
  453. plt.fill_between(Vgs, IrmsMean2-IrmsStd2, IrmsMean2+IrmsStd2 ,color = 'b',alpha =0.3)
  454. plt.xlabel('V$_{gs}$ - V$_{CNP}$ (V)')
  455. plt.ylabel('I$_{rms}$ (A)')
  456. plt.legend()
  457. plt.figure(8)
  458. UrmsMean, UrmsStd = MeanStdGM(Urms)
  459. plt.semilogy(Vgs-0.34, UrmsMean,'k')
  460. plt.fill_between(Vgs-0.34, UrmsMean-UrmsStd, UrmsMean+UrmsStd ,color = 'k',alpha =0.3)
  461. plt.xlabel('V$_{gs}$ - V$_{CNP}$ (V)')
  462. plt.ylabel('V$_{gs-rms}$ ($\mu$V)')
  463. plt.legend()
  464. plt.figure(9)
  465. SNRMean, SNRStd = MeanStdGM(SNR)
  466. plt.plot(Vgs-0.70, SNRMean,'k',label = '1 metal layer')
  467. plt.fill_between(Vgs-0.70, SNRMean-SNRStd, SNRMean+SNRStd ,color = 'k',alpha =0.3)
  468. plt.xlabel('V$_{gs}$ - V$_{CNP}$ (V)')
  469. plt.ylabel('SNR (dB)')
  470. plt.legend()
  471. fig, ax = plt.subplots()
  472. UrmsDriftArray = np.zeros((len(UrmsDrift.keys()),len(UrmsDrift[UrmsDrift.keys()[0]])))
  473. for ikeyTrt,keyTrt in enumerate(UrmsDrift.keys()):
  474. for ikeyVgs in np.arange(len(UrmsDrift[UrmsDrift.keys()[0]])):
  475. UrmsDriftArray[ikeyTrt, ikeyVgs] = UrmsDrift[keyTrt][ikeyVgs]*1e6
  476. # ax.plot(np.random.normal(VgsInt[ikeyVgs], 0.003)-0.0015, UrmsDrift[keyTrt][ikeyVgs]*1e6,'*k')
  477. bpr = ax.boxplot(UrmsDriftArray, positions=VgsInt, widths=0.006)
  478. # axgm.legend()
  479. # figgm.savefig(IVFigFile[0:-7]+'/'+'Gm'+'.png')
  480. # dd.io.save(FoutDCvals, (DevDCVals,GM ), ('zlib', 1))
  481. dd.io.save(Path+'GM-B12784O18-T2', GM)
  482. #%% plot map SNR
  483. plt.figure()
  484. A=np.log10(np.ones((11,6))*5e-17)
  485. for Trt in SNR.keys():
  486. ch = MCSMapI[Trt]
  487. # if Trt in DCch:
  488. # continue
  489. A[MCSMapFacingDown[ch][1],MCSMapFacingDown[ch][0]] = SNR[Trt][7]
  490. plt.imshow(A, interpolation='nearest', vmin=10, vmax=38)
  491. plt.grid(True)
  492. cbar=plt.colorbar()
  493. plt.xlabel('column')
  494. plt.ylabel('row')
  495. cbar.set_label('SNR [dB]', rotation=270, labelpad=15)
  496. #%% plot map Urms
  497. plt.figure()
  498. A=np.log10(np.ones((11,6))*5e-17)
  499. import matplotlib.colors as colors
  500. for Trt in SNR.keys():
  501. ch = MCSMapI[Trt]
  502. # if Trt in DCch:
  503. # continue
  504. A[MCSMapFacingDown[ch][1],MCSMapFacingDown[ch][0]] = (Urms[Trt][9])*1e6
  505. plt.imshow(A, interpolation='nearest', vmin=3, vmax=30, norm=colors.LogNorm(vmin=3, vmax=30))
  506. plt.grid(True)
  507. cbar=plt.colorbar()
  508. plt.xlabel('column',fontsize=12)
  509. plt.ylabel('row',fontsize=12)
  510. cbar.set_label('U$_{gs-rms}$ ($\mu$V)', rotation=270, labelpad=15,fontsize=13)