Advertisement
OreganoHauch

All code (as of Dec 6th, 2020)

Dec 6th, 2020
113
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 41.46 KB | None | 0 0
  1. #!/usr/bin/env python
  2. # coding: utf-8
  3.  
  4. # In[228]:
  5.  
  6.  
  7. # import external modules
  8. import h5py
  9. import time
  10. import math
  11. import cv2
  12. import os
  13. import os.path
  14. import shutil
  15.  
  16. import numpy as np
  17. import matplotlib.pyplot as plt
  18. import matplotlib.cm as cm
  19.  
  20. from IPython.core.display import display, HTML
  21. from shutil import copyfile
  22. from os import path
  23. from scipy.interpolate import griddata
  24. from mpl_toolkits.axes_grid1 import make_axes_locatable
  25. from mpl_toolkits.axes_grid1.colorbar import colorbar
  26. from matplotlib.ticker import (MultipleLocator, FormatStrFormatter, AutoMinorLocator, AutoLocator)
  27. import pylatex
  28.  
  29. get_ipython().run_line_magic('matplotlib', 'inline')
  30.  
  31.  
  32. # In[2]:
  33.  
  34.  
  35. # change width of Jupyter notebook
  36. def displaywidth(width):
  37. try:
  38. display(HTML("<style>.container { width:" + str(width) + "% !important; }</style>"))
  39. except:
  40. print("Enter an integer percentage for width.")
  41.  
  42.  
  43. # In[3]:
  44.  
  45.  
  46. def load_h5(scan, datatype, show_time=False):
  47. '''This function loads only a few selected h5 files, but the definition should suffice for all the files I might need throughout the work on my bachelor's thesis.'''
  48.  
  49. start = time.time()
  50.  
  51. try:
  52. if datatype == "positions":
  53. h5_file = h5py.File("/asap3/petra3/gpfs/p06/2018/data/11005475/processed/0016_EMPA_MSH_003c/scan_00" + str(scan) + "/positions.h5", "r")
  54. else:
  55. h5_file = h5py.File("/asap3/petra3/gpfs/p06/2018/data/11005475/processed/0016_EMPA_MSH_003c/scan_00" + str(scan) + "/data/" + datatype + ".h5", "r")
  56. return h5_file
  57. except:
  58. print("You entered '" + str(scan) + "' for the argument 'scan'. The function only takes an integer as first argument. Its value must lie between 178 and 192, except for 184, because this scan was aborted.\nThe second argument must be a string for the datatype, e.g. 'position' or 'fluo_roi'.")
  59.  
  60. end = time.time()
  61.  
  62. if show_time:
  63. print("Loading file " + datatype + ".h5 from scan 00" + str(scan) + "took " + str(end-start) + "seconds.")
  64.  
  65.  
  66. # In[4]:
  67.  
  68.  
  69. displaywidth(100)
  70.  
  71.  
  72. # In[5]:
  73.  
  74.  
  75. def counts2amps(scan, nA=True):
  76. '''This function takes the integer scan number as an argument, looks for the counter data inside of the h5 file,
  77. converts all the counts into XBIC in [nA] and returns the values as an ndarray.'''
  78.  
  79. # load counts and turn it into 2d array
  80. if scan in [179,187,188,189,190]: # XBIC measurements without the chopper, i.e. without the lock-in-amplifier
  81. loaded_counts1 = load_h5(scan, "counter")["/data/solar_cell_0-10V"]
  82. counts_as_array1 = np.array(loaded_counts1)
  83. loaded_counts2 = load_h5(scan, "counter")["/data/solar_cell_0-10V"]
  84. counts_as_array2 = np.array(loaded_counts2)
  85. counts_as_array = counts_as_array1-counts_as_array2 # subtract negative from positive signal
  86. else:
  87. loaded_counts = load_h5(scan, "counter")["/data/lock_in_R_0-10V"]
  88. counts_as_array = np.array(loaded_counts).astype(float) # this integer array must be converted to float, otherwise np.reciprocal will return only zeros
  89.  
  90. counts_as_array = np.array(load_h5(scan, "counter")["/data/lock_in_0-10V"]).astype(float)
  91.  
  92. # load photon counts
  93. loaded_photon_counts = load_h5(scan, "counter")["/data/qbpm_micro_sum"]
  94. photon_counts_as_array = np.array(loaded_photon_counts).astype(float) # this integer array must be converted to float, otherwise np.reciprocal will return only zeros
  95.  
  96. # load exposure times and turn it into 2d array
  97. loaded_exposure_times = load_h5(scan, "counter")["/data/exposure_time"]
  98. exposure_times_as_array = np.array(loaded_exposure_times)
  99.  
  100. # normalize counts and photons to one second
  101. c_rate = (counts_as_array/exposure_times_as_array)
  102. ph_rate = photon_counts_as_array/exposure_times_as_array
  103.  
  104. # normalize counts to the average photon rate and one second
  105. f_DAQ = c_rate * np.mean(ph_rate)/ph_rate # multiply each LIA count by the ratio of the average photon count to the respective photon count (e.g. twice as much photons as the average should be normalized to half of the XBIC curent)
  106.  
  107. # calculate the conversion factor
  108. if scan in [178,179,180,181,182,183,184,185,186,191,192]: # these scans have a sensitivity of 1 μA/V
  109. A_PA = 10**6 # "P_A" = 1/sensitivity: Preamplifier amplification factor in V/A, values taken from LogbuchStrahlzeitPetraIII31.10.-6.11.2018.pptx, slide 54f.
  110. if scan in [187,188,189,190]: # these scans have a sensitivity of 100 mA/V
  111. A_PA = 10
  112. A_LIA = 1 # "A_LIA" = 1/scaling = Lock-in amplifier amplification factor in V/V, values also taken from the pptx logbook
  113. V2f = 1000000
  114. Wff = math.sqrt(2) # the output signal (in this case a sine signal) of the LIA is the RMS amplitude, but we are interested in the peak-to-peak value (see jove paper, p.4)
  115. H_conv = 2*Wff/(V2f*A_LIA*A_PA)
  116.  
  117. # finally multiply the conversion factor with the normalized count of each pixel
  118. if not nA:
  119. S_XBIC = f_DAQ * H_conv
  120. S_XBIC = f_DAQ * H_conv * 10**9
  121.  
  122. # return S_XBIC_raw_nA
  123. return S_XBIC
  124.  
  125.  
  126. # In[ ]:
  127.  
  128.  
  129. plotXBIC(14)
  130.  
  131.  
  132. # In[ ]:
  133.  
  134.  
  135. for i in range(178,193):
  136. plotXBIC_singlecell(singleplots=[i])
  137.  
  138.  
  139. # In[ ]:
  140.  
  141.  
  142. print(cv2.imread(r"/asap3/petra3/gpfs/p06/2018/data/11005475/scratch_cc/Jan/savefig/plotXBIC_singlecell/01.png"))
  143.  
  144.  
  145. # In[ ]:
  146.  
  147.  
  148.  
  149.  
  150.  
  151. # In[255]:
  152.  
  153.  
  154. img1 = cv2.imread(r"savefig/plotXBIC_singlecell/01.png")
  155. img2 = cv2.imread(r"savefig/plotXBIC_singlecell/02.png")
  156. #gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
  157. vis = cv2.vconcat([img1, img2])
  158. cv2.imshow("concatenated images",img1)
  159. cv2.waitKey(0)
  160. cv2.destroyAllWindows()
  161.  
  162.  
  163. # In[ ]:
  164.  
  165.  
  166. img1 = cv2.imread(r"savefig/plotXBIC_singlecell/01.png")
  167. cv2.imshow("concatenated images",img1)
  168. cv2.waitKey(0)
  169. cv2.destroyAllWindows()
  170.  
  171.  
  172. # In[ ]:
  173.  
  174.  
  175. im = cv2.imread('IMG_FILENAME',0)
  176. h,w = im.shape[:2]
  177. print(im.shape)
  178. plt.imshow(im,cmap='gray')
  179. plt.show()
  180.  
  181.  
  182. # In[ ]:
  183.  
  184.  
  185. folder_path = "savefig/plotXBIC_singlecell/"
  186. # Open one of the files,
  187. for data_file in os.listdir(folder_path):
  188. print(data_file)
  189.  
  190.  
  191. # In[ ]:
  192.  
  193.  
  194. # move the copies of the singlecell PNGs into the copy folder
  195. os.chdir(r"/asap3/petra3/gpfs/p06/2018/data/11005475/scratch_cc/Jan/")
  196. os.chdir(r"savefig/plotXBIC_singlecell/")
  197. newPath = "copied singlecell plots/"
  198.  
  199. for file in os.listdir(os.getcwd()):
  200. if "Copy" in file:
  201. print(str(file), "was moved to", str(newPath))
  202. shutil.move(file,newPath)
  203. else:
  204. print(str(file), "does not contain \"Copy\"")
  205. os.chdir(r"/asap3/petra3/gpfs/p06/2018/data/11005475/scratch_cc/Jan/")
  206.  
  207.  
  208. # In[204]:
  209.  
  210.  
  211. # copy all PNGs from the copies folder into the upper folder and remove the Copy part of the name
  212.  
  213. os.chdir(r"/asap3/petra3/gpfs/p06/2018/data/11005475/scratch_cc/Jan/savefig/plotXBIC_singlecell/copied singlecell plots/")
  214. for file in sorted(os.listdir(os.getcwd())):
  215. file_renamed = file.replace("-Copy1", "")
  216. os.rename(file,file_renamed)
  217. copyfile(file_renamed,r"../" + file_renamed)
  218. os.chdir(r"/asap3/petra3/gpfs/p06/2018/data/11005475/scratch_cc/Jan/")
  219.  
  220.  
  221. # In[253]:
  222.  
  223.  
  224. # rename the files in order
  225. os.chdir(r"/asap3/petra3/gpfs/p06/2018/data/11005475/scratch_cc/Jan/")
  226. os.chdir(r"savefig/plotXBIC_singlecell/")
  227. index = 1
  228. for file in sorted(os.listdir(os.getcwd())):
  229. if ".png" in file:
  230. os.rename(file,"{:02d}.png".format(index))
  231. index += 1
  232. os.chdir(r"/asap3/petra3/gpfs/p06/2018/data/11005475/scratch_cc/Jan/")
  233.  
  234.  
  235. # In[9]:
  236.  
  237.  
  238. def plotXBIC_singlecell(plot_range=None, singleplots=None, compareA=None, compareB=None, figsize=(30,30)):
  239. '''
  240. This function plots the XBIC, using data from the previously defined counts2amps() function. Look at the examples to see how to use it:
  241.  
  242. plotXBIC(plot_range=14) will do the following:
  243. It will plot 14 datasets, starting with #178 and ending with #192 (and omitting 184 which is still counted).
  244.  
  245. plotXBIC(singleplots=[178,185,192]) will do the following:
  246. It will plot #178, #185 and #192.
  247.  
  248. plotXBIC(compareA=[178,178,185], compareB=[187,189,189]) will do the following:
  249. It will plot
  250. Scan 178 minus Scan 187
  251. Scan 178 minus Scan 189
  252. Scan 185 minus Scan 189.
  253. '''
  254.  
  255. # the best looking fontsize is about half of the width of the figsize
  256. fontsize = figsize[0]//2
  257.  
  258. # individualize titles for each scan if there is a bias voltage applied (information from LogbuchStrahlzeitPetraIII31.10.-6.11.2018.pptx, slide 54f., corresponding to handwritten logbook)
  259. voltage_dic = {
  260. 178: "",
  261. 179: "",
  262. 180: "",
  263. 181: "",
  264. 182: " (+ 100 mV)",
  265. 183: " (- 100 mV)",
  266. 185: " (- 200 mV)",
  267. 186: " (+ 200 mV)",
  268. 187: " (+ 500 mV)",
  269. 188: "(- 500 mV)",
  270. 189: " (- 1 V)",
  271. 190: " (+ 600 mv)",
  272. 191: "",
  273. 192: ""
  274. }
  275.  
  276. # create a figure for all plots
  277. fig = plt.figure(figsize=figsize)
  278.  
  279. loop_count = 1 # the subplot number should be independent of omitted scans (e.g. scan #184); otherwise you would see an empty space at that position
  280.  
  281. if type(plot_range) is int:
  282. if plot_range > 6:
  283. plot_range += 1 # scan #184 is omitted, but still counted by the for-loop
  284. for scan in range(178, 178 + plot_range):
  285.  
  286. if scan == 184:
  287. continue # scan 184 was aborted
  288.  
  289. plotXBIC_loop_single(scan=scan,fig=fig,fontsize=fontsize,voltage_dic=voltage_dic,loop_count=loop_count)
  290.  
  291. loop_count += 1
  292.  
  293. plt.show()
  294.  
  295. if type(singleplots) is list:
  296. for scan in singleplots:
  297.  
  298. if scan == 184:
  299. continue # scan 184 was aborted
  300.  
  301. plotXBIC_loop_single(scan=scan,fig=fig,fontsize=fontsize,voltage_dic=voltage_dic,loop_count=loop_count, savepng=True)
  302.  
  303. loop_count += 1
  304.  
  305. plt.show()
  306.  
  307.  
  308. if type(compareA) is list:
  309. compareB_counter=0
  310. for scan in compareA:
  311.  
  312. plotXBIC_loop_single(scan=scan,fig=fig,fontsize=fontsize,voltage_dic=voltage_dic,loop_count=loop_count,compare=True,compareB=compareB,compareB_counter=compareB_counter)
  313.  
  314. loop_count += 1
  315. compareB_counter += 1
  316.  
  317.  
  318. plt.show()
  319.  
  320.  
  321. # In[147]:
  322.  
  323.  
  324. def plotXBIC_loop_single(scan, fig, fontsize, voltage_dic, loop_count, compareB=None, compareB_counter=None, compare=False, dpi=None, savepng=False):
  325.  
  326. start = time.time() # measure time for each plot
  327.  
  328. #fig.suptitle("Reduced LIA count normalized", fontsize=2*fontsize, x=0.7, y=0.92) # optional title for the figure (with this x and y it is centered and has a good distance)
  329.  
  330. # load position and define y, z and f(y,z) as arrays that can be interpreted by the imshow() function
  331. positions = load_h5(scan, "positions")
  332. y_axis_h5 = positions["/data/encoder_fast/data"]
  333. z_axis_h5 = positions["/data/encoder_slow/data"]
  334. y = np.array(y_axis_h5)
  335. z = np.array(z_axis_h5)
  336.  
  337. channels = {
  338. 1: "lock-in_-10-0V",
  339. 2: "lock_in_0-10V",
  340. 3: "lock_in_R_0-10V",
  341. 4: "solar_cell_-10-0V",
  342. 5: "solar_cell_0-10V"
  343. }
  344.  
  345.  
  346. for index in range(5):
  347. counts_as_array = np.array(load_h5(scan, "counter")["/data/" + channels[index+1]]).astype(float)
  348.  
  349. # load photon counts
  350. loaded_photon_counts = load_h5(scan, "counter")["/data/qbpm_micro_sum"]
  351. photon_counts_as_array = np.array(loaded_photon_counts).astype(float) # this integer array must be converted to float, otherwise np.reciprocal will return only zeros
  352.  
  353. # load exposure times and turn it into 2d array
  354. loaded_exposure_times = load_h5(scan, "counter")["/data/exposure_time"]
  355. exposure_times_as_array = np.array(loaded_exposure_times)
  356.  
  357. # normalize counts and photons to one second
  358. c_rate = (counts_as_array/exposure_times_as_array)
  359. ph_rate = photon_counts_as_array/exposure_times_as_array
  360.  
  361. # normalize counts to the average photon rate and one second
  362. f_DAQ = c_rate * np.mean(ph_rate)/ph_rate # multiply each LIA count by the ratio of the average photon count to the respective photon count (e.g. twice as much photons as the average should be normalized to half of the XBIC curent)
  363.  
  364. # calculate the conversion factor
  365. if scan in [178,179,180,181,182,183,184,185,186,191,192]: # these scans have a sensitivity of 1 μA/V
  366. A_PA = 10**6 # "P_A" = 1/sensitivity: Preamplifier amplification factor in V/A, values taken from LogbuchStrahlzeitPetraIII31.10.-6.11.2018.pptx, slide 54f.
  367. if scan in [187,188,189,190]: # these scans have a sensitivity of 100 mA/V
  368. A_PA = 10
  369. A_LIA = 1 # "A_LIA" = 1/scaling = Lock-in amplifier amplification factor in V/V, values also taken from the pptx logbook
  370. V2f = 1000000
  371. Wff = math.sqrt(2) # the output signal (in this case a sine signal) of the LIA is the RMS amplitude, but we are interested in the peak-to-peak value (see jove paper, p.4)
  372. H_conv = 2*Wff/(V2f*A_LIA*A_PA)
  373.  
  374. # finally multiply the conversion factor with the normalized count of each pixel
  375. S_XBIC = f_DAQ * H_conv * 10**9
  376.  
  377. current = S_XBIC
  378.  
  379. if compare:
  380. counts2amps_A = current
  381. counts2amps_B = counts2amps(compareB[compareB_counter])
  382.  
  383. # append NaN: scan 180 has the shape (40199,) and thus cannot be broadcast together with the other scans which have shapes of (40200,)
  384. if scan == 180:
  385. counts2amps_A = np.append(current,np.nan)
  386. if compareB[compareB_counter] == 180:
  387. counts2amps_B = np.append(counts2amps(compareB[compareB_counter]),np.nan)
  388. current = counts2amps_A-counts2amps_B
  389.  
  390. y_grid, z_grid, current_array = supergrid(y,z,current,1000)
  391.  
  392.  
  393. fig = plt.figure()
  394. ax = fig.add_subplot(111)
  395.  
  396. # spacing to other subplots
  397. plt.subplots_adjust(right=1.3, hspace=0.5, wspace=0.5)
  398.  
  399. # y and z labels
  400. ax.set_xlabel("Position Y [μm]", labelpad = 0, style = "italic", fontsize=fontsize)
  401. ax.set_ylabel("Position Z [μm]", labelpad = 0, style = "italic", fontsize=fontsize)
  402.  
  403. # title
  404. bias_voltage = voltage_dic[scan]
  405. if compare:
  406. plt.title("Scan #" + str(scan) + " minus Scan #" + str(compareB[compareB_counter]), pad = 15, fontsize=round(9/8*fontsize))
  407. else:
  408. plt.title("Scan #" + str(scan) + bias_voltage, pad = 15, fontsize=round(9/8*fontsize))
  409.  
  410. # individual ticks: it's an extrapolated plot from 201x201 to 1000x1000 pixels, but this corresponds to 10x10 micrometers on the solar cell
  411. ax.xaxis.set_ticklabels([0,5,10],fontsize=round(4/5*fontsize))
  412. ax.xaxis.set_ticks([0,500,999]) # if 1000 instead of 999 it won't display
  413. ax.yaxis.set_ticklabels([0,5,10],fontsize=round(4/5*fontsize))
  414. ax.yaxis.set_ticks([0,500,999])
  415. ax.xaxis.set_minor_locator(MultipleLocator(50)) # Minor ticks are set to multiples of 50
  416. ax.yaxis.set_minor_locator(MultipleLocator(50))
  417.  
  418. # plot the data
  419. im = ax.imshow(current_array, interpolation='nearest', cmap=cm.afmhot, origin='lower')
  420.  
  421. # add a colorbar as legend
  422. ax_divider = make_axes_locatable(ax) # Introduce a divider next to the axis already in place
  423. cax = ax_divider.append_axes("right", size = "15%", pad = "5%") # Append a new axis object with name "cax" to the divider. Width ("size") and distance to the 2D-Plot ("pad") can be given in % of the width of the x axis.
  424. legend = colorbar(im, cax = cax) # Introduce a legend (colorbar) where the new axis has been placed
  425. cax.set_ylabel(r"$\frac{XBIC}{pixel \cdot photons_{avg}}$" + " in [nA]", rotation = -90, labelpad = 50 , style = "italic", fontsize=5/4*fontsize) # Place this label next to the colorbar; labelpad denotes the distance of the colorbar
  426. cax.yaxis.set_major_locator(AutoLocator())
  427. cax.yaxis.set_minor_locator(AutoMinorLocator())
  428.  
  429. plt.show()
  430.  
  431. if savepng:
  432. from datetime import datetime
  433. now = datetime.now()
  434. dt_string = now.strftime("%d-%m-%Y_%H_%M_%S")
  435. if dpi is None:
  436. fig.savefig("savefig/plotXBIC_singlecell/plotXBIC_singlecell_" + dt_string + ".png", dpi=fig.dpi, bbox_inches="tight")
  437. else:
  438. fig.savefig("savefig/plotXBIC_singlecell/plotXBIC_singlecell_" + dt_string + ".png", dpi=dpi, bbox_inches="tight")
  439.  
  440.  
  441. end = time.time()
  442.  
  443. if compare:
  444. print("Scan " + str(scan) + " minus Scan " + str(compareB[compareB_counter]) + " took " + str(round(end-start,2)) + " seconds to plot.")
  445. else:
  446. print("Scan " + str(scan) + " took " + str(round(end-start,2)) + " seconds to plot.")
  447.  
  448.  
  449. # In[11]:
  450.  
  451.  
  452. def supergrid(yvalues, zvalues, currents, gridres):
  453. """This function creates a rectangular grid where both axes have the given length. The given datapoints, which
  454. location is characterized by a tuple of y- and z-values, are interpolated such that every point in the grid gets
  455. assigned a value according to the nearest neighbor method.
  456.  
  457. ARGUMENTS:
  458. yvalues (1D-array): Corresponding y-values for every measurement
  459. zvalues (1D-array): Corresponding x-values for every measurement
  460. currents (1D-array): All currents measured on the respective y- and z-coordinates
  461. gridres (float): Resolution of the grid insofar as it is the length of both axes of the grid in pixels
  462.  
  463. RETURNS:
  464. (yvalues_new, zvalues_new, currents_supergrid) (Tuple of three 2D-Arrays): three grids with corresponding
  465. y-values, z-values and currents at every single point in the grid.
  466. """
  467.  
  468. if np.size(yvalues) != np.size(zvalues):
  469. raise Exception("Arrays 'yvalues' and 'zvalues' must have same size.")
  470. else:
  471. if np.size(yvalues) - np.size(currents) == -1: # This paragraph is to catch an error that is raised when
  472. currents = currents[:np.size(currents) - 1] # dealing with the XRF scan XBIC data. It appears that
  473. if np.size(yvalues) - np.size(currents) == 1: # the y- and z-arrays or the currents are too long by one
  474. yvalues = yvalues[:np.size(yvalues) - 1] # element where no measurement was done. This element is
  475. zvalues = zvalues[:np.size(zvalues) - 1] # removed from the respective array to align points and data.
  476. if np.size(yvalues) - np.size(currents) == 0:
  477. pass
  478. else:
  479. raise Exception("Positions (y, z) and corresponding data points can't be aligned due to their different size.")
  480.  
  481. yvalues_shift = yvalues - yvalues.min() # shift y-values to obtain the relative position
  482. zvalues_shift = zvalues - zvalues.min() # shift y-values to obtain the relative position
  483.  
  484. # Create grid of y- and z-values with respect to the selected grid resolution (gridres)
  485. yvalues_new, zvalues_new = np.mgrid[0:yvalues_shift.max():gridres * 1j, 0:zvalues_shift.max():gridres * 1j]
  486.  
  487. # Interpolate given currents such that they fit the grid of x- and y-values
  488. currents_supergrid = griddata((yvalues_shift, zvalues_shift), currents, (yvalues_new, zvalues_new), method = "nearest")
  489.  
  490. return yvalues_new, zvalues_new, currents_supergrid.T
  491.  
  492.  
  493. # In[12]:
  494.  
  495.  
  496. def plotXBIC_loop(scan, fig, fontsize, voltage_dic, loop_count, compareB=None, compareB_counter=None, compare=False):
  497.  
  498. start = time.time() # measure time for each plot
  499.  
  500. #fig.suptitle("Reduced LIA count normalized", fontsize=2*fontsize, x=0.7, y=0.92) # optional title for the figure (with this x and y it is centered and has a good distance)
  501.  
  502. # load position and define y, z and f(y,z) as arrays that can be interpreted by the imshow() function
  503. positions = load_h5(scan, "positions")
  504. y_axis_h5 = positions["/data/encoder_fast/data"]
  505. z_axis_h5 = positions["/data/encoder_slow/data"]
  506. y = np.array(y_axis_h5)
  507. z = np.array(z_axis_h5)
  508. current = counts2amps(scan)
  509. if compare:
  510. counts2amps_A = current
  511. counts2amps_B = counts2amps(compareB[compareB_counter])
  512.  
  513. # append NaN: scan 180 has the shape (40199,) and thus cannot be broadcast together with the other scans which have shapes of (40200,)
  514. if scan == 180:
  515. counts2amps_A = np.append(current,np.nan)
  516. if compareB[compareB_counter] == 180:
  517. counts2amps_B = np.append(counts2amps(compareB[compareB_counter]),np.nan)
  518. current = counts2amps_A-counts2amps_B
  519.  
  520. y_grid, z_grid, current_array = supergrid(y,z,current,1000)
  521.  
  522. # axes for new subplot
  523. ax = fig.add_subplot(4, 4, loop_count)
  524.  
  525. # spacing to other subplots
  526. plt.subplots_adjust(right=1.3, hspace=0.5, wspace=0.5)
  527.  
  528. # y and z labels
  529. ax.set_xlabel("Position Y [μm]", labelpad = 0, style = "italic", fontsize=fontsize)
  530. ax.set_ylabel("Position Z [μm]", labelpad = 0, style = "italic", fontsize=fontsize)
  531.  
  532. # title
  533. bias_voltage = voltage_dic[scan]
  534. if compare:
  535. plt.title("Scan #" + str(scan) + " minus Scan #" + str(compareB[compareB_counter]), pad = 15, fontsize=round(9/8*fontsize))
  536. else:
  537. plt.title("Scan #" + str(scan) + bias_voltage, pad = 15, fontsize=round(9/8*fontsize))
  538.  
  539. # individual ticks: it's an extrapolated plot from 201x201 to 1000x1000 pixels, but this corresponds to 10x10 micrometers on the solar cell
  540. ax.xaxis.set_ticklabels([0,5,10],fontsize=round(4/5*fontsize))
  541. ax.xaxis.set_ticks([0,500,999]) # if 1000 instead of 999 it won't display
  542. ax.yaxis.set_ticklabels([0,5,10],fontsize=round(4/5*fontsize))
  543. ax.yaxis.set_ticks([0,500,999])
  544. ax.xaxis.set_minor_locator(MultipleLocator(50)) # Minor ticks are set to multiples of 50
  545. ax.yaxis.set_minor_locator(MultipleLocator(50))
  546.  
  547. # plot the data
  548. im = ax.imshow(current_array, interpolation='nearest', cmap=cm.afmhot, origin='lower')
  549.  
  550. # add a colorbar as legend
  551. ax_divider = make_axes_locatable(ax) # Introduce a divider next to the axis already in place
  552. cax = ax_divider.append_axes("right", size = "15%", pad = "5%") # Append a new axis object with name "cax" to the divider. Width ("size") and distance to the 2D-Plot ("pad") can be given in % of the width of the x axis.
  553. legend = colorbar(im, cax = cax) # Introduce a legend (colorbar) where the new axis has been placed
  554. cax.set_ylabel(r"$\frac{XBIC}{pixel \cdot photons_{avg}}$" + " in [nA]", rotation = -90, labelpad = 50 , style = "italic", fontsize=5/4*fontsize) # Place this label next to the colorbar; labelpad denotes the distance of the colorbar
  555. cax.yaxis.set_major_locator(AutoLocator())
  556. cax.yaxis.set_minor_locator(AutoMinorLocator())
  557.  
  558. end = time.time()
  559.  
  560. if compare:
  561. print("Scan " + str(scan) + " minus Scan " + str(compareB[compareB_counter]) + " took " + str(round(end-start,2)) + " seconds to plot.")
  562. else:
  563. print("Scan " + str(scan) + " took " + str(round(end-start,2)) + " seconds to plot.")
  564.  
  565.  
  566. # In[13]:
  567.  
  568.  
  569. def plotXBIC(plot_range=None, singleplots=None, compareA=None, compareB=None, figsize=(30,30), savepng=False, dpi=None):
  570. '''
  571. This function plots the XBIC, using data from the previously defined counts2amps() function. Look at the examples to see how to use it:
  572.  
  573. plotXBIC(plot_range=14) will do the following:
  574. It will plot 14 datasets, starting with #178 and ending with #192 (and omitting 184 which is still counted).
  575.  
  576. plotXBIC(singleplots=[178,185,192]) will do the following:
  577. It will plot #178, #185 and #192.
  578.  
  579. plotXBIC(compareA=[178,178,185], compareB=[187,189,189]) will do the following:
  580. It will plot
  581. Scan 178 minus Scan 187
  582. Scan 178 minus Scan 189
  583. Scan 185 minus Scan 189.
  584. '''
  585.  
  586. # the best looking fontsize is about half of the width of the figsize
  587. fontsize = figsize[0]//2
  588.  
  589. # individualize titles for each scan if there is a bias voltage applied (information from LogbuchStrahlzeitPetraIII31.10.-6.11.2018.pptx, slide 54f., corresponding to handwritten logbook)
  590. voltage_dic = {
  591. 178: "",
  592. 179: "",
  593. 180: "",
  594. 181: "",
  595. 182: " (+ 100 mV)",
  596. 183: " (- 100 mV)",
  597. 185: " (- 200 mV)",
  598. 186: " (+ 200 mV)",
  599. 187: " (+ 500 mV)",
  600. 188: "(- 500 mV)",
  601. 189: " (- 1 V)",
  602. 190: " (+ 600 mv)",
  603. 191: "",
  604. 192: ""
  605. }
  606.  
  607. # create a figure for all plots
  608. fig = plt.figure(figsize=figsize)
  609.  
  610. loop_count = 1 # the subplot number should be independent of omitted scans (e.g. scan #184); otherwise you would see an empty space at that position
  611.  
  612. if type(plot_range) is int:
  613. if plot_range > 6:
  614. plot_range += 1 # scan #184 is omitted, but still counted by the for-loop
  615. for scan in range(178, 178 + plot_range):
  616.  
  617. if scan == 184:
  618. continue # scan 184 was aborted
  619.  
  620. plotXBIC_loop(scan=scan,fig=fig,fontsize=fontsize,voltage_dic=voltage_dic,loop_count=loop_count)
  621.  
  622. loop_count += 1
  623.  
  624. plt.show()
  625.  
  626. if type(singleplots) is list:
  627. for scan in singleplots:
  628.  
  629. if scan == 184:
  630. continue # scan 184 was aborted
  631.  
  632. plotXBIC_loop(scan=scan,fig=fig,fontsize=fontsize,voltage_dic=voltage_dic,loop_count=loop_count)
  633.  
  634. loop_count += 1
  635.  
  636. plt.show()
  637.  
  638.  
  639. if type(compareA) is list:
  640. compareB_counter=0
  641. for scan in compareA:
  642.  
  643. plotXBIC_loop(scan=scan,fig=fig,fontsize=fontsize,voltage_dic=voltage_dic,loop_count=loop_count,compare=True,compareB=compareB,compareB_counter=compareB_counter)
  644.  
  645. loop_count += 1
  646. compareB_counter += 1
  647.  
  648.  
  649. plt.show()
  650.  
  651. if savepng:
  652. from datetime import datetime
  653. now = datetime.now()
  654. dt_string = now.strftime("%d-%m-%Y_%H_%M_%S")
  655. if dpi is None:
  656. fig.savefig("savefig/plotXBIC_" + dt_string + ".png", dpi=fig.dpi, bbox_inches="tight")
  657. else:
  658. fig.savefig("savefig/plotXBIC_" + dt_string + ".png", dpi=dpi, bbox_inches="tight")
  659.  
  660.  
  661. # In[14]:
  662.  
  663.  
  664. def ImageRegistration(scan1,scan2,cell=None,printdetails=False):
  665.  
  666. positions = load_h5(scan1, "positions")
  667. y_axis_h5 = positions["/data/encoder_fast/data"]
  668. z_axis_h5 = positions["/data/encoder_slow/data"]
  669. y = np.array(y_axis_h5)
  670. z = np.array(z_axis_h5)
  671. current1 = counts2amps(scan1)
  672. current2 = counts2amps(scan2)
  673.  
  674.  
  675. y_grid1, z_grid1, current1_array_original = supergrid(y,z,current1,1000)
  676. y_grid2, z_grid2, current2_array_original = supergrid(y,z,current2,1000)
  677.  
  678. # convert current1_array to a grayscale image format (values between 0 and 255)
  679. current1_array_8bitgrayscale = current1_array_original/current1_array_original.max()
  680. current1_array_8bitgrayscale *= (1/1-current1_array_8bitgrayscale.min())
  681. current1_array_8bitgrayscale += 1 - current1_array_8bitgrayscale.max()
  682. current1_array_8bitgrayscale[current1_array_8bitgrayscale < 0] = 0
  683. current1_array_8bitgrayscale = np.array(current1_array_8bitgrayscale*255, dtype = np.uint8)
  684.  
  685. current2_array_8bitgrayscale = current2_array_original/current2_array_original.max()
  686. current2_array_8bitgrayscale *= (1/1-current2_array_8bitgrayscale.min())
  687. current2_array_8bitgrayscale += 1 - current2_array_8bitgrayscale.max()
  688. current2_array_8bitgrayscale[current2_array_8bitgrayscale < 0] = 0
  689. current2_array_8bitgrayscale = np.array(current2_array_8bitgrayscale*255, dtype = np.uint8)
  690.  
  691. shape = np.shape(current1_array_8bitgrayscale)
  692.  
  693. warp_mode = cv2.MOTION_TRANSLATION # we only need translation in direction of y and z (no rotation etc.)
  694.  
  695. warp_matrix = np.eye(2, 3, dtype=np.float32) # this is the matrix that the results of the ECC algorithm are stored in
  696.  
  697. number_of_iterations = 5000 # Specify the number of iterations
  698. termination_eps = 1e-10 # Specify the threshold of the increment in the correlation coefficient between two iterations
  699.  
  700. # Specify the overall criteria
  701. criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, number_of_iterations, termination_eps)
  702.  
  703. (cc, warp_matrix) = cv2.findTransformECC(current1_array_8bitgrayscale, current2_array_8bitgrayscale, warp_matrix, warp_mode, criteria, None, 1)
  704.  
  705. if printdetails == True:
  706. scan2_aligned = cv2.warpAffine(current2_array_8bitgrayscale, warp_matrix, (shape[1], shape[0]), flags = cv2.INTER_LINEAR + cv2.WARP_INVERSE_MAP).astype(np.float32)
  707.  
  708. # show where the values of the registered image lie (XBIC as a function of the 40200 datapoints)
  709. scan2_aligned_ravel = scan2_aligned.ravel()
  710. x = np.arange(np.shape(scan2_aligned_ravel)[0])
  711. plt.figure(figsize=(50,5))
  712. plt.scatter(x, scan2_aligned_ravel)
  713. plt.show()
  714.  
  715. fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize = (15, 15), constrained_layout = True)
  716.  
  717. im1 = ax1.imshow(current1_array_8bitgrayscale, origin = "lower", cmap = cm.afmhot)
  718. ax1.set_title("Scan #" + str(scan1))
  719.  
  720. ax1_divider = make_axes_locatable(ax1) # Introduce a divider next to the axis already in place
  721. cax1 = ax1_divider.append_axes("right", size = "15%", pad = "5%") # Append a new axis object with name "cax" to the divider. Width ("size") and distance to the 2D-Plot ("pad") can be given in % of the width of the x axis.
  722. legend = colorbar(im1, cax = cax1) # Introduce a legend (colorbar) where the new axis has been placed
  723. cax1.yaxis.set_major_locator(AutoLocator())
  724. cax1.yaxis.set_minor_locator(AutoMinorLocator())
  725.  
  726. im2 = ax2.imshow(current2_array_8bitgrayscale, origin = "lower", cmap = cm.afmhot)
  727. ax2.set_title("Scan #" + str(scan2))
  728.  
  729. ax2_divider = make_axes_locatable(ax2) # Introduce a divider next to the axis already in place
  730. cax2 = ax2_divider.append_axes("right", size = "15%", pad = "5%") # Append a new axis object with name "cax" to the divider. Width ("size") and distance to the 2D-Plot ("pad") can be given in % of the width of the x axis.
  731. legend = colorbar(im2, cax = cax2) # Introduce a legend (colorbar) where the new axis has been placed
  732. cax2.yaxis.set_major_locator(AutoLocator())
  733. cax2.yaxis.set_minor_locator(AutoMinorLocator())
  734.  
  735.  
  736. im3 = ax3.imshow(scan2_aligned, origin = "lower", cmap = "inferno")
  737. ax3.set_title("Scan #" + str(scan2) + " aligned")
  738. ax3.set_ylim(bottom = 0)
  739.  
  740. ax3_divider = make_axes_locatable(ax3) # Introduce a divider next to the axis already in place
  741. cax3 = ax3_divider.append_axes("right", size = "15%", pad = "5%") # Append a new axis object with name "cax" to the divider. Width ("size") and distance to the 2D-Plot ("pad") can be given in % of the width of the x axis.
  742. legend = colorbar(im3, cax = cax3) # Introduce a legend (colorbar) where the new axis has been placed
  743. cax3.yaxis.set_major_locator(AutoLocator())
  744. cax3.yaxis.set_minor_locator(AutoMinorLocator())
  745.  
  746. plt.tight_layout(w_pad=6)
  747.  
  748. return warp_matrix
  749.  
  750. ImageRegistration(181,182,printdetails=True)
  751.  
  752.  
  753. # In[15]:
  754.  
  755.  
  756. print(ImageRegistration(181,182))
  757.  
  758.  
  759. # In[16]:
  760.  
  761.  
  762. ImageRegistration(181,182)[0][2]
  763.  
  764.  
  765. # In[17]:
  766.  
  767.  
  768. def warpTransform(scan):
  769. warp_matrix = ImageRegistration(181,scan)
  770.  
  771. scan_array = supergrid(np.array(load_h5(scan, "positions")["/data/encoder_fast/data"]), np.array(load_h5(scan, "positions")["/data/encoder_slow/data"]), counts2amps(scan), 1000)
  772.  
  773. # Create a template array for the warped image
  774. zero_array = np.zeros((np.shape(scan_array)[0],np.shape(scan_array)[1]))
  775. transformY = ImageRegistration(181,scan)[0][2]
  776. transformZ = ImageRegistration(181,scan)[1][2]
  777.  
  778. registered_image = transformY
  779.  
  780. return registered_image
  781.  
  782.  
  783. # In[18]:
  784.  
  785.  
  786. def plotXBIC_loop2(scan, fig, fontsize, voltage_dic, loop_count, compareB=None, compareB_counter=None, compare=False):
  787.  
  788. start = time.time() # measure time for each plot
  789.  
  790. # fig.suptitle("Reduced LIA count normalized", fontsize=2*fontsize, x=0.7, y=0.92) # optional title for the figure (with this x and y it is centered and has a good distance)
  791.  
  792. # load position and define y, z and f(y,z) as arrays that can be interpreted by the imshow() function
  793. positions = load_h5(scan, "positions")
  794. y_axis_h5 = positions["/data/encoder_fast/data"]
  795. z_axis_h5 = positions["/data/encoder_slow/data"]
  796. y = np.array(y_axis_h5)
  797. z = np.array(z_axis_h5)
  798. current = counts2amps(scan)
  799. if compare:
  800. counts2amps_A = current
  801. counts2amps_B = counts2amps(compareB[compareB_counter])
  802.  
  803. # append NaN: scan 180 has the shape (40199,) and thus cannot be broadcast together with the other scans which have shapes of (40200,)
  804. if scan == 180:
  805. counts2amps_A = np.append(current,np.nan)
  806. if compareB[compareB_counter] == 180:
  807. counts2amps_B = np.append(counts2amps(compareB[compareB_counter]),np.nan)
  808. current = counts2amps_A-counts2amps_B
  809.  
  810. y_grid, z_grid, current_array = supergrid(y,z,current,1000)
  811.  
  812. # axes for new subplot
  813. ax = fig.add_subplot(4, 4, loop_count)
  814.  
  815. # spacing to other subplots
  816. plt.subplots_adjust(right=1.3, hspace=0.5, wspace=0.5)
  817.  
  818. # y and z labels
  819. ax.set_xlabel("Position Y [μm]", labelpad = 0, style = "italic", fontsize=fontsize)
  820. ax.set_ylabel("Position Z [μm]", labelpad = 0, style = "italic", fontsize=fontsize)
  821.  
  822. # title
  823. bias_voltage = voltage_dic[scan]
  824. if compare:
  825. plt.title("Scan #" + str(scan) + " minus Scan #" + str(compareB[compareB_counter]), pad = 15, fontsize=round(9/8*fontsize))
  826. else:
  827. plt.title("Scan #" + str(scan) + bias_voltage, pad = 15, fontsize=round(9/8*fontsize))
  828.  
  829. # individual ticks: it's an extrapolated plot from 201x201 to 1000x1000 pixels, but this corresponds to 10x10 micrometers on the solar cell
  830. ax.xaxis.set_ticklabels([0,5,10],fontsize=round(4/5*fontsize))
  831. ax.xaxis.set_ticks([0,500,999]) # if 1000 instead of 999 it won't display
  832. ax.yaxis.set_ticklabels([0,5,10],fontsize=round(4/5*fontsize))
  833. ax.yaxis.set_ticks([0,500,999])
  834. ax.xaxis.set_minor_locator(MultipleLocator(50)) # Minor ticks are set to multiples of 50
  835. ax.yaxis.set_minor_locator(MultipleLocator(50))
  836.  
  837. shape = np.shape(current_array)
  838.  
  839. if scan in [178,179]: # scan 178 and 179 were at another position than the rest of the scans
  840. warp_matrix = ImageRegistration(178,scan)
  841. else:
  842. warp_matrix = ImageRegistration(181,scan)
  843.  
  844. if scan not in [178,181]: # scan 178 and 181 are reference scans for the warp matrices, so they don't need to be transformed
  845. current_array = cv2.warpAffine(current_array, warp_matrix, (shape[1], shape[0]), flags = cv2.INTER_LINEAR + cv2.WARP_INVERSE_MAP, borderValue = float("NaN")).astype(np.float32)
  846.  
  847. current_array_ravel = current_array.ravel()
  848. x = np.arange(np.shape(current_array_ravel)[0])
  849. plt.figure(figsize=(50,5))
  850. plt.scatter(x, current_array_ravel)
  851. #plt.show()
  852.  
  853. # plot the data
  854. im = ax.imshow(current_array, interpolation='nearest', cmap=cm.afmhot, origin='lower')
  855.  
  856. # add a colorbar as legend
  857. ax_divider = make_axes_locatable(ax) # Introduce a divider next to the axis already in place
  858. cax = ax_divider.append_axes("right", size = "15%", pad = "5%") # Append a new axis object with name "cax" to the divider. Width ("size") and distance to the 2D-Plot ("pad") can be given in % of the width of the x axis.
  859. legend = colorbar(im, cax = cax) # Introduce a legend (colorbar) where the new axis has been placed
  860. cax.set_ylabel(r"$\frac{XBIC}{pixel \cdot photons_{avg}}$" + " in [nA]", rotation = -90, labelpad = 50 , style = "italic", fontsize=5/4*fontsize) # Place this label next to the colorbar; labelpad denotes the distance of the colorbar
  861. cax.yaxis.set_major_locator(AutoLocator())
  862. cax.yaxis.set_minor_locator(AutoMinorLocator())
  863.  
  864. end = time.time()
  865.  
  866. if compare:
  867. print("Scan " + str(scan) + " minus Scan " + str(compareB[compareB_counter]) + " took " + str(round(end-start,2)) + " seconds to plot.")
  868. else:
  869. print("Scan " + str(scan) + " took " + str(round(end-start,2)) + " seconds to plot.")
  870.  
  871.  
  872. # In[19]:
  873.  
  874.  
  875. def plotXBIC2(plot_range=None, singleplots=None, compareA=None, compareB=None, figsize=(30,30), savepng=False, dpi=None):
  876. '''
  877. This function plots the XBIC, using data from the previously defined counts2amps() function. Look at the examples to see how to use it:
  878.  
  879. plotXBIC(plot_range=14) will do the following:
  880. It will plot 14 datasets, starting with #178 and ending with #192 (and omitting 184 which is still counted).
  881.  
  882. plotXBIC(singleplots=[178,185,192]) will do the following:
  883. It will plot #178, #185 and #192.
  884.  
  885. plotXBIC(compareA=[178,178,185], compareB=[187,189,189]) will do the following:
  886. It will plot
  887. Scan 178 minus Scan 187
  888. Scan 178 minus Scan 189
  889. Scan 185 minus Scan 189.
  890. '''
  891.  
  892. # the best looking fontsize is about half of the width of the figsize
  893. fontsize = figsize[0]//2
  894.  
  895. # individualize titles for each scan if there is a bias voltage applied (information from LogbuchStrahlzeitPetraIII31.10.-6.11.2018.pptx, slide 54f., corresponding to handwritten logbook)
  896. voltage_dic = {
  897. 178: "",
  898. 179: "",
  899. 180: "",
  900. 181: "",
  901. 182: " (+ 100 mV)",
  902. 183: " (- 100 mV)",
  903. 185: " (- 200 mV)",
  904. 186: " (+ 200 mV)",
  905. 187: " (+ 500 mV)",
  906. 188: "(- 500 mV)",
  907. 189: " (- 1 V)",
  908. 190: " (+ 600 mv)",
  909. 191: "",
  910. 192: ""
  911. }
  912.  
  913. # create a figure for all plots
  914. fig = plt.figure(figsize=figsize)
  915.  
  916. loop_count = 1 # the subplot number should be independent of omitted scans (e.g. scan #184); otherwise you would see an empty space at that position
  917.  
  918. if type(plot_range) is int:
  919. if plot_range > 6:
  920. plot_range += 1 # scan #184 is omitted, but still counted by the for-loop
  921. for scan in range(178, 178 + plot_range):
  922.  
  923. if scan == 184:
  924. continue # scan 184 was aborted
  925.  
  926. plotXBIC_loop2(scan=scan,fig=fig,fontsize=fontsize,voltage_dic=voltage_dic,loop_count=loop_count)
  927.  
  928. loop_count += 1
  929.  
  930. plt.show()
  931.  
  932. if type(singleplots) is list:
  933. for scan in singleplots:
  934.  
  935. if scan == 184:
  936. continue # scan 184 was aborted
  937.  
  938. plotXBIC_loop2(scan=scan,fig=fig,fontsize=fontsize,voltage_dic=voltage_dic,loop_count=loop_count)
  939.  
  940. loop_count += 1
  941.  
  942. plt.show()
  943.  
  944. if type(compareA) is list:
  945. compareB_counter=0
  946. for scan in compareA:
  947.  
  948. plotXBIC_loop2(scan=scan,fig=fig,fontsize=fontsize,voltage_dic=voltage_dic,loop_count=loop_count,compare=True,compareB=compareB,compareB_counter=compareB_counter)
  949.  
  950. loop_count += 1
  951. compareB_counter += 1
  952.  
  953.  
  954. plt.show()
  955.  
  956. if savepng:
  957. from datetime import datetime
  958. now = datetime.now()
  959. dt_string = now.strftime("%d-%m-%Y_%H_%M_%S")
  960. if dpi is None:
  961. fig.savefig("savefig/plotXBIC_" + dt_string + ".png", dpi=fig.dpi, bbox_inches="tight")
  962. else:
  963. fig.savefig("savefig/plotXBIC_" + dt_string + ".png", dpi=dpi, bbox_inches="tight")
  964.  
  965.  
  966. # In[20]:
  967.  
  968.  
  969. plotXBIC2(singleplots=[181,182,183])
  970.  
  971.  
  972. # In[21]:
  973.  
  974.  
  975. plotXBIC(14)
  976.  
  977.  
  978. # In[22]:
  979.  
  980.  
  981. def plotIV(thinning=10,savepng=False):
  982.  
  983. start = time.time()
  984. # voltages
  985. voltages = [-1000,-500,-200,-100,0,100,200,500,600]
  986. # scans (ordered by voltages)
  987. scans_ordered = [189,188,185,183,181,182,186,187,190]
  988.  
  989. current_mean = []
  990. pixelplotting_array = np.empty([5,1000,1000])
  991.  
  992. pixelplotting_array_x = 0
  993. for scan in scans_ordered[2:-2]:
  994.  
  995. positions = load_h5(scan, "positions")
  996. y_axis_h5 = positions["/data/encoder_fast/data"]
  997. z_axis_h5 = positions["/data/encoder_slow/data"]
  998. y_axis = np.array(y_axis_h5)
  999. z_axis = np.array(z_axis_h5)
  1000. current = counts2amps(scan)
  1001.  
  1002. y_grid, z_grid, current_array = supergrid(y_axis,z_axis,current,1000)
  1003.  
  1004. current_mean.append(np.mean(current))
  1005.  
  1006. for y in range(1000):
  1007. for z in range(1000):
  1008. pixelplotting_array[pixelplotting_array_x,z,y] = current_array[y,z]
  1009.  
  1010. pixelplotting_array_x += 1
  1011.  
  1012. fig = plt.figure(figsize=(40,20))
  1013. ax1 = fig.add_subplot(121)
  1014.  
  1015.  
  1016. for y in np.linspace(0,999,1000/thinning,dtype=int):
  1017. for z in np.linspace(0,999,1000/thinning,dtype=int):
  1018. ax1.plot(voltages[2:-2], pixelplotting_array[:,y,z],linewidth = 0.2,color="blue")
  1019.  
  1020. ax2 = fig.add_subplot(122)
  1021. ax2.plot(voltages[2:-2], current_mean)
  1022.  
  1023. end = time.time()
  1024. print(end-start)
  1025.  
  1026. plt.show()
  1027.  
  1028. plotIV(thinning=50)
  1029.  
  1030.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement