class Data: """Class providing an interface to the raw data NetCDF files.""" def __init__(self): """Constructor.""" self.filename = None # The filename the data was loaded from. # Laser fire times come from the laser diode data in mdsplus. self.laserFireTimes = None self.shotNum = None self.data = {} self.polyList = None self.segments = None self.prelasing = None def loadData(self, shotNum, skipAPD = 1): """Load all the data for the given shot. Parameters: shotNum -- The shot number to load. skipAPD -- Set to 1 to skip the first APD (because of saturation). """ from numpy import arange self.shotNum = shotNum self.data = {} # Clear old data. self.filename = util.getDataFilePath(shotNum) nc = pycdf.CDF(self.filename) #print "Loading Raw Data\n" str_rawData = nc.var('str_rawdata').get() str_voltsPerBit = nc.var('str_voltsperbit').get() str_deltat = nc.var('str_deltat').get() str_zeroBit = nc.var('str_offset').get() acq_rawData = nc.var('rawdata').get() acq_voltsPerBit = nc.var('voltsperbit').get() acq_deltat = nc.var('deltat').get() acq_offset = nc.var('offset').get() roa = nc.var('roa').get() # take the poly list from the netCDF file (one entry for each channel) and unique-ify it # to have only one entry per poly plist_long = nc.var('poly').get() seen = {} for item in plist_long: seen[item] = 1 plist_short = seen.keys() plist_short.sort() # probably unnecessary, but just in case self.polyList = plist_short # load the calibration data after the file data, so that the poly list can be loaded for this shot self.calib = Calibration() self.calib.loadCalibration(shotNum, plist_short, skipAPD) # The number of data segments is one less than the total number of # segments. The last segment in the data file is used for calculating # the amplifier offsets. self.segments = arange(str_rawData.shape[1] - 1) apdIndex = 0 for poly in self.polyList: self.data[poly] = {} calib = self.calib.getPolyCalibration(poly) for segment in self.segments: numAPD = calib.numAPD ps = PolySegData() ps.calib = calib ps.poly = poly ps.segment = segment ps.shotNum=self.shotNum # If calib.skipAPD is 1, then we don't load the data for the # first APD. start = apdIndex + calib.skipAPD end = apdIndex + numAPD ps.str_voltsPerBit = str_voltsPerBit[start:end] ps.str_deltat = str_deltat[start:end] ps.str_zeroBit = str_zeroBit[start:end] ps.acq_voltsPerBit = acq_voltsPerBit[start:end] ps.acq_deltat = acq_deltat[start:end] ps.acq_offset = acq_offset[start:end] ps.roa = roa[start] # correction because p20 and p21 were flipped in the calib file # for Fall 2012 only, radial calib redone in December #if poly == 20: # ps.roa = 0.6030 #elif poly == 21: # ps.roa = 0.5181 ps.str_rawData = str_rawData[start:end, segment] ps.acq_rawData = acq_rawData[start:end, segment] # It's a bit inefficient to store the offset data with each # PolySegData object, but it is simple. ps.str_offsetRaw = str_rawData[start:end, len(self.segments)] ps.acq_offsetRaw = acq_rawData[start:end, len(self.segments)] # Set the usability flags for the DC and AC channels # The AC channels are set to be unused until AC calib is figured out ps.chanFlagDC = ones(numAPD - calib.skipAPD) #ps.chanFlagAC = ones(numAPD - calib.skipAPD) ps.chanFlagAC = zeros(numAPD - calib.skipAPD) self.data[poly][segment] = ps apdIndex += numAPD def getSegments(self): """Return a list of available segment numbers.""" return self.segments def getPolyList(self): """Return the list of polys to fit.""" return self.polyList def getPolyListSortedROA(self): """Return the list of polys in order of increasing ROA.""" def sortFn(p1, p2): ps1 = self.getPolySegData(p1, 0) ps2 = self.getPolySegData(p2, 0) if ps1.roa == ps2.roa: return 0 elif ps1.roa > ps2.roa: return 1 else: return -1 tmpList = list(self.getPolyList()) tmpList.sort(sortFn) return tmpList def getPolySegData(self, poly, segment): """Get the data for a given poly and segment combination. Parameters: poly -- The poly number. segment -- The segment number. Returns: The data for the given poly and segment in the form of a PolySegData object. """ return self.data[poly][segment] def setPolySegData(self, poly, segment, ps): """Set the data for a given poly and segment to the given PolySegData object. Parameters: poly -- The poly number. segment -- The segment number. ps -- The PolySegData object. Returns: Nothing. """ self.data[poly][segment] = ps def getReadme(self, bCompact=True): """Return a string to save to the readme variable in mdsplus.""" ret = '' for segment in self.getSegments(): for poly in self.getPolyList(): ps = self.getPolySegData(poly, segment) st = None if bCompact: st = ps.getCompactErrWarnStr() else: st = ps.getErrWarnStr() if st != None: ret += '%s\n' % st return ret