def loadcurrent(shot, scope='3'): """ helper function to read in the current""" data = sdr.scope_data(shot, scope) time = data.time eastcurrent = -data.ch2 * 170000 #East gun 170kA/V westcurrent = -data.ch4 * 190000 #West gun 190kA/V return time, eastcurrent, westcurrent
def plot_voltage(shot, scope='3'): """ helper function to read in the current""" data = sdr.scope_data(shot, scope) time = data.time eastvolt = data.ch1 #East gun 170kA/V westvolt = data.ch3 #West gun 190kA/V plt.plot(time, eastvolt, label="East Voltage") plt.plot(time, westvolt, label="West Voltage") plt.legend() plt.show()
def dens_calib(calib_shot, cutoff=1, scope='1'): """ day - str, mmddyy, with date of the shot taken shot - int, shot number cutoff - float, cutoff frequency in MHz for lowpass filter used to improve data scope - str, scope returns: env - envelope, range of data for signal 1 and 2 offset - minima of both signals phasediff - phase error between cos and sin, in radians """ #load the data data = sdr.scope_data(calib_shot, scope) names = ['signal1', 'signal2'] if scope == '2': channels = (1, 2) if scope == '1': channels = (3, 4) #channels = (3, 4) mult = (1, 1) data.setScopeProperties(names, channels, mult) cos, sin, t = data.signal1[data.time > 50], data.signal2[ data.time > 50], data.time[data.time > 50] # removes first bit of the data due to occasional noise at t = 0 cos = mytools.lowpass_gfilter(t, cos, cutoff, return_mean=True) sin = mytools.lowpass_gfilter(t, sin, cutoff, return_mean=True) #apply lowpass filter to make the fits better print("stage 1 completed...") env = [max(cos) - min(cos), max(sin) - min(sin)] offset = [min(cos), min(sin)] #find ranges for the data cos = (cos - offset[0]) / env[0] sin = (sin - offset[1]) / env[1] #calibrate the data #find the phase error x_ym_list = [] #array of xvals around the ymax pt weights_list = [] for i in range(len(cos)): if sin[i] > 0.98: x_ym_list.append(cos[i]) weights_list.append(np.abs((0.98 - sin[i]) / 0.02)) #find weighted average max pt. #x_ym = np.mean(x_ym_list) x_ym = np.dot(x_ym_list, weights_list) / sum(weights_list) #use cosine when sin = 1 to find phase error phasediff = np.arccos((x_ym - 0.5) * 2) - np.pi / 2 print("stage 2 completed...") return env, offset, phasediff
def load_smallbdot(shot, scope = '1'): data = sdr.scope_data(shot, scope) time = data.time X_bdot = data.ch1 #*170000#East gun 170kA/V Y_bdot = data.ch2 #*190000#West gun 190kA/V Z_bdot = data.ch3 Bx = sp.integrate.cumtrapz(X_bdot,time) By = sp.integrate.cumtrapz(Y_bdot,time) Bz = sp.integrate.cumtrapz(Z_bdot,time) timeb = time[:-1] return timeb, Bx, By, Bz
def sxr(run, scope='2', showPlot=False): """Plots the SXR data.""" data = sdr.scope_data(run, scope) data.ylabel = 'mA' names = data.header[1:] channels = (1, 2, 3, 4) mult = (1 / 50. * 1000, ) * 4 units = (data.ylabel, ) * 4 data.setScopeProperties(names, channels, mult, units) return data
def vuv(run, scope='1', amp=100e-6, channel=4): """VUV data. amp is in amps/volt, so 100 ua/v is 100e-6.""" data = sdr.scope_data(run, scope) names = ['vuv'] channels = [channel] mult = [amp] units = ['A'] data.setScopeProperties(names, channels, mult, units) return data
def tripleProbe(run, scope='2', smoothing=100, mult=None): """Reads data from triple probe and analysizes it. This hasn't been updated in a long time so use at your discretion. It probably eneds to be tweaked.""" data = sdr.scope_data(run, scope) names = ('vd2', 'vd3', 'i1', 'vfloat') channels = (1, 2, 3, 4) if not mult: mult = (-50, -50, 10, 200) units = ('V', 'V', 'A', 'V') data.setScopeProperties(names, channels, mult, units) data.temperature = data.vd2 / np.log(2) data.temperature2 = data.vd2 / (np.log(2) - np.log(1 + 11.3205 * (data.vd2 / data.vd3)**3.53217)) data.temperatureSmooth = mf.smooth(data.vd2, smoothing) / np.log(2) data.temperature2Smooth = mf.smooth(data.vd2, smoothing) / ( np.log(2) - np.log(1 + 11.3205 * (mf.smooth(data.vd2, smoothing) / mf.smooth(data.vd3, smoothing))**3.53217)) mi = 1.6726e-27 elecCharge = 1.6022e-19 tconv = 1.1604e4 area = 3.6e-6 boltz = 1.3807e-23 data.isat = data.i1 * (np.exp(-(data.vd2 / data.temperature))) / ( 1 - np.exp(-(data.vd2 / data.temperature))) data.isatSmooth = mf.smooth(data.i1, smoothing) * ( np.exp(-(mf.smooth(data.vd2, smoothing) / data.temperature2Smooth)) ) / (1 - np.exp(-(mf.smooth(data.vd2, smoothing) / data.temperature2Smooth))) data.density = (data.isat * np.exp(.5)) / (elecCharge * area) * sqrt( mi / (data.temperature * tconv * boltz)) / 1e6 data.density2 = (data.isatSmooth * np.exp(.5)) / (elecCharge * area) * sqrt( mi / (data.temperature2Smooth * tconv * boltz)) / 1e6 return data
def gunPlots(shot, scope='3', writeFiles=False, ext='png'): """Plots gun data from scope 3.""" data = sdr.scope_data(shot, scope) fig = figure(12, **ssxdef.f) fig.clear() a = axes() a.plot(data.time, data.ch2 * 170, label='East') a.plot(data.time, data.ch4 * 190, label='West') xlabel('Time (us)') ylabel('Gun Current (kA)') title(data.shotname) a.legend() fig2 = figure(13, **ssxdef.f) fig2.clear() a = axes() a.plot(data.time, data.ch1, label='East') a.plot(data.time, data.ch3, label='West') xlabel('Time (us)') ylabel('Gun voltage ()') title(data.shotname) a.legend() if writeFiles: fName = ssxutil.ssxPath('guncurrent.' + ext, 'output', data.runYear + '/' + data.runDate + '/' + data.shotname, mkdir=True) fig.savefig(fName) fName2 = ssxutil.ssxPath( 'gunvoltage.' + ext, 'output', data.runYear + '/' + data.runDate + '/' + data.shotname) fig2.savefig(fName2) else: show() return data
def calibrationDTAC_david(calibInfo, probeinfo, prefunc = None): """Modification to calibration() for the dtac data. Data from the dtac units needs to be integrated before we calibrate it. The integrated data is used for fitting. probeinfo has some dtac specific data stashed in it. - probe is the probe name (m1). - filestrings is the dtac filestring names. - dir relates the probe coords (1,2,3) to lab coords (r,t,z). Specifically, you pass in ['r', 't', 'z'] in this variable (in the appropriate order) if the probe data has *different* names, like ['1', '2', '3']. This probably will never need to be used for the dtac probes, but it's here in just in case. This was originally for the colorado probe - look in the functions calibcolorado and calibrationCol for more on the implementation.""" import hiresmag_david as hr nump = calibInfo['numProbes'] numc = calibInfo['numChan'] pretrig = calibInfo['pretrigger'] calibData = zeros((3, nump, 4)) # dir = c,b,a # dir = a,b,c # dir2 = r,t,z dir = calibInfo['dir'] # helmholtz fields - triplet location, shot orientation, components (r,t,z) b = zeros((nump,3,3)) # data from 3 calibration shots, triplet position, components (r,z,t) voltages = zeros((3, nump, 3)) dir2 = probeinfo['dir'] for i, k in enumerate(dir): d = dir2[i] print "Calculating b fields - %s" % d # calculate the field from the helmholtz coils as *should* be measured # by each probe in the right location b0 = calibBFields2(d, calibInfo) # stick it into the big b array b[:,i,:] = b0 if calibInfo['coil'] == 2: peakrange = [25,60] elif calibInfo['coil'] == 1: peakrange = [50,130] for i,run in enumerate(calibInfo['runs']): print "using run %s" % run # Get the data from the scopes shotdata = sdr.scope_data(run, calibInfo['scope']) # get the calibrated current for the shot current = getattr(shotdata, shotdata.names[calibInfo['currentChan'] - 1]) * 170000. #(1000./0.00541/1.025) # the above is our calibration for the gun current. # - 170 kA/V for east gun # - 190 kA/V for west gun # - 180 kA/V was the historical value # get the peak of the current currentMax = polyPeak(shotdata.time, current, range = peakrange, timebase = 200) # read in the dtac mag data and get it ready # hiresmag_data should be kosher to use for any dtac setup, but I'm not # sure. We might have to modify this. magdata = hr.hiresmag_data(run, probeinfo['probe']) magdata.filestrings = probeinfo['filestrings'] magdata._getData() magdata._makeFullData() magdata.removeOffsets() # call our preprocessing function on the data, if we need it if prefunc: prefunc(magdata) magdata.iFullData = np.ma.zeros(magdata.fullData.shape) magdata.iFullData.mask = True magdata.iFullData[:,1:] = sp.integrate.cumtrapz(magdata.fullData, dx = magdata.deltat * 1e6, axis = 1) print 'fullData ',magdata.fullData.shape print 'iFullData ',magdata.iFullData.shape # tmp = ma.masked_outside(magdata.fullData[:,2:100], -.50, .50).mean(1) # offsets = np.expand_dims(tmp, 2) # dat = magdata.fullData - offsets # magdata.iFullData = np.ma.zeros(magdata.fullData.shape) # magdata.iFullData.mask = True # magdata.iFullData[:,1:] = sp.integrate.cumtrapz(dat, dx = # magdata.deltat * 1e6, axis = 1) # magmax = zeros(numc) magmax = zeros((nump, 3)) # Outer loop is for each probe location (i.e. 16 probes) # Inner loop is for directions (i.e. r,t,z) # So the progression goes: 1r, 1t, 1z, 2r, 2t, 2z... for j in xrange(nump): for k,p in enumerate(dir): # first figure out the name of our probe channel - ex. m2r1 probeNum = "%s%s%i" % (probeinfo['probe'], p, j+1) print "%s: i = %i, j = %i, k = %i" % (probeNum, i, j, k) # find the peak in the mag signal #chan = magdata.channelNames.index(probeNum) chan = (16*k)+j #Dschaffner changed 5/16/2014 to convert [3,16] to [48] print 'Chan = ',chan timebase = int(1e-6 / magdata.deltat) # tmpmag = polyPeak(magdata.time, magdata.iFullData[chan], # timebase = timebase, pretrigger = 100) tmpmag = polyPeak(magdata.time, magdata.iFullData[chan,:], range = peakrange, timebase = timebase, pretrigger = pretrig) #DSchaffner changed magdata.iFullData[chan] to magdata.iFullData[k,j] # print tmpmag, currentMax, tmpmag/ currentMax # normalize to the current # No longer normalize to the double turn helmholtz coil. First # of all that was stupid - why not just spit that out in the # helmholtz function? Secondly, we have a new coil which is # only one turn, so we need to be able to toggle that on and # off, and it seems to make the most sense to do it in the... # helmholtz function. # # We will still normalize the measured field here with the # current magmax[j, k] = tmpmag / (currentMax) # our normalized B signals - takes into account current # magmax is now number of probes x number of axis long. So for a 16 # channel, 3 axis probe, it should be 48 channels (16,3). # Voltages is the same size as magmax, but with an extra dimension. The # extra dimension is number of calibration directions (3 # usually). So it would be [3,16,3]. voltages[i] = magmax # Outer loop is for each probe location (i.e. 16 probes) # inner loops is r, t, z for i in xrange(nump): for j,d in enumerate(dir): # so we are going to dot the normalized voltages into the inverse # of the expected field. The indices in voltages makes sure we get # a single coil (m2r1) for all three calibration orientations # (r,t,z). u = dot((voltages[:,i,j]), inv(b[i,:,:])) # all the magic is in the above line. All we are doing is dotting # the measured voltages (r,t,z) into the inverse of the 3x3 array # of the fields we should be measuring ((r,t,z) for each of the 3 # orientations r, t, and z (though I think the indices of b are as # follows: # - first index is probe number # - second index is calibration orientation # - third index is component of field # dot sums over the last dimension of the first array and the 2nd # to last dimension of the second array. So we are dotting the # calib orientation of voltages and the calib orientation of b. At # this point in time, b should more or less be diagonal (ignoring # any error fields in the coil due to non-uniform fields in the # helmholtz). # # this normalizes it all modu = sqrt(dot(u,u)) calibData[j,i,:3] = u/modu calibData[j,i,3] = modu # Reshape before we send it back. This is getting written to a file so it # needs to be 2-D. Note, I think the data is going to get put down in the # file as 1-16r, 1-16t, then 1-16z. When we read it in later, just run # reshape() again, this time like reshape((3, nump, 4)) where nump is 16 # most likely. # # This is a change of how this data used to be stored. It used to be # stored in a 48x4 array, where the first three lines formed a 3x4 array # that consisted of 1r,1t,1z data, etc. We also just used to parse the # array with a bunch of stupid indices. Now we reshape to get our 3x16 for # axis x probe. Mind you, we choose 3x16 instead of 16x3 because of the # way the dtac data is read in, organized and easily reshaped. This way we # don't have to think about indices (dtac data is 3x16) nor do we have to # worry about making the 3D arrays 2D, just use reshape and things go # together in the correct way for unreshaping it later. return calibData.reshape((nump*3,4))
def interferometer(run, env, offset, phasediff, linfit=True, cutoff=1, scope='1', diam=0.155575, showPlot=False, writeFiles=False): """Interferometer analysis routine. Reads data from the scope data files and runs the analysis. Inputting a proper diameter is necessary. Diameter is path length of interferometer in cm. In oblate flux conservers it should be 50 cm. For neck part of oblate conservers, it should be 15.5575 cm. run - str, mmddyy+'r'+shot number env - envelope output from densitycalibration, should be shot from same day offset - offset output from densitycalibration, should be shot from same day phasediff - phasediff output from densitycalibration , should be shot from same day linfit - whether or not to subtract a linear fit from the data. should set to false for calibration shots cutoff - float, lowpass filter cutoff frequency in MHz calib_shot - controls whether or not to subtract a linear fit to the density data before t = 3 ms to remove phase drift. I.e. usually false for looking at calibration data Written by Emma Suen-Lewis 2017, adapted from Tim Gray """ print('Shot ' + run + ': analyzing density') data = sdr.scope_data(run, scope) names = ['signal1', 'signal2'] channels = (3, 4) mult = (1, 1) data.setScopeProperties(names, channels, mult) data.runname = run #save run name for folder naming in other functions data.cutoff = cutoff # save lowpass cutoff frequency t = data.time cos = mytools.lowpass_gfilter(t, data.signal1, cutoff, return_mean=True) sin = mytools.lowpass_gfilter(t, data.signal2, cutoff, return_mean=True) #load cos/sin data and apply lowpass filter cos = (cos - offset[0]) / env[0] sin = (sin - offset[1]) / env[1] #calibrate data with envelope and offsets #change ranges from [0,1] to [-1,1] for i in range(len(cos)): cos[i] = 2 * cos[i] - 1 sin[i] = 2 * sin[i] - 1 data.sig1cal = cos.copy() data.sig2cal = sin.copy() for i in range(len(cos)): cos[i] = (cos[i] / np.cos(phasediff) + (sin[i]) * np.tan(phasediff)) #remove effects of phase error #will output cosine and sine data (note that this doesn't include corrections #for low-frequency phase drift) data.cos = cos.copy() data.sin = sin.copy() phi = np.arctan(sin / cos) #calculate phase in radians #get rid of jumps due to the range of arctan for i in range(len(phi)): if i < len(phi) - 1: if phi[i + 1] - phi[i] > 3: phi[i + 1:] = phi[i + 1:] - np.pi if phi[i + 1] - phi[i] < -3: phi[i + 1:] = phi[i + 1:] + np.pi dphi = phi - np.mean(phi[0:10]) #subtract out initial phase data.p = [] #linear fit to data before firing if linfit == True: time_mask = t < 35 p = np.polyfit( t[time_mask], ism.iter_smooth(dphi, loops=10, window_len=15)[time_mask], 1) dphi = dphi - p[1] - p[0] * t data.p = p data.dphi = dphi # .155575 m is the ID of the small part of the flux conserver # mks #density = (dphi * 4 * pi * (3e8)**2 * 8.854e- 12 * 9.109e-31) / #((1.602e-19)**2 * 632.8e-9 * .155575) #cgs #density = (dphi * (3e10)**2 * 9.109e-28) / ((4.8032e-10)**2 * 632.8e-7 * # diam) density = 5.62e14 * dphi / diam data.pathlength = diam data.density = density if showPlot or writeFiles: fig = figure(13, **ssxdef.f) fig.clear() a = axes() a.plot(data.time, data.density, 'k-') xlabel('Time (us)') ylabel('Density (#/cm$^3$)') title(data.shotname) if writeFiles: # make output directory fName = ssxutil.ssxPath( 'interferometer.png', 'output', data.runYear + '/' + data.runDate + '/' + run) dir, trash = os.path.split(fName) os.spawnlp(os.P_WAIT, 'mkdir', 'mkdir', '-p', dir) fig.savefig(fName) else: show() return data
def loadcurrent(shot, scope = '3'): data = sdr.scope_data(shot, scope) time = data.time eastcurrent = -data.ch2*170000#East gun 170kA/V westcurrent = -data.ch4*190000#West gun 190kA/V return time,eastcurrent,westcurrent
def interferometer_mod(run, calib, s1=[], s2=[], scope='2', diam=0.155575, showPlot=False, writeFiles=False): """Interferometer analysis routine. Reads data from the altered cosine/sine data and runs the analysis. Inputting a proper diameter is necessary. Diameter is path length of interferometer in cm. In oblate flux conservers it should be 50 cm. For neck part of oblate conservers, it should be 15.5575 cm. calib should be a tuple/list of the maximum and minimums observed on the scope for each channel at the beginning of the run day.""" data = sdr.scope_data(run, scope) names = ['signal1', 'signal2'] channels = (1, 2) mult = (1, 1) units = ('arb', 'arb') data.setScopeProperties(names, channels, mult) data.calib = dict(zip(names, calib)) if s1 == []: dv1 = data.signal1 - np.mean(data.signal1[0:10]) else: dv1 = s1 - np.mean(s1[0:10]) if s2 == []: dv2 = data.signal2 - np.mean(data.signal2[0:10]) else: dv2 = s2 - np.mean(s2[0:10]) arg = 1 - 0.5 * ((dv1 / data.calib[names[0]])**2 + (dv2 / data.calib[names[1]])**2) #remove values outside of arccos domain spikes = np.where(arg < -1.0) arg[spikes] = -1.0 dphi = np.arccos(arg) data.dphi = dphi # .155575 m is the ID of the small part of the flux conserver # mks #density = (dphi * 4 * pi * (3e8)**2 * 8.854e-12 * 9.109e-31) / #((1.602e-19)**2 * 632.8e-9 * .155575) #cgs #density = (dphi * (3e10)**2 * 9.109e-28) / ((4.8032e-10)**2 * 632.8e-7 * # diam) density = 5.62e14 * dphi / diam data.pathlength = diam data.density = density if showPlot or writeFiles: fig = figure(13, **ssxdef.f) fig.clear() a = axes() a.plot(data.time, data.density, 'k-') xlabel('Time (us)') ylabel('Density (#/cm$^3$)') title(data.shotname) if writeFiles: # make output directory fName = ssxutil.ssxPath( 'interferometer.png', 'output', data.runYear + '/' + data.runDate + '/' + run) dir, trash = os.path.split(fName) os.spawnlp(os.P_WAIT, 'mkdir', 'mkdir', '-p', dir) fig.savefig(fName) else: show() x1, x2 = data.signal1, data.signal2 k1, k2 = calib[0], calib[1] error = (3.6 * 10**15) * 0.00627 * (x1 * (k1**-2) + x2 * (k2**-2)) / np.sqrt(4 * ((x1 / k1)**2 + (x2 / k2)**2) - ((x1 / k1)**2 + (x2 / k2)**2)**2) return data, error