def readInterval(self, pulseIdInterval, path=None): """ **[DEPRECATED]** Access to data by an macrobunch ID interval. Useful for scans that would otherwise hit the machine's memory limit. **Parameters**\n pulseIdInterval: (int, int) The starting and ending macrobunch IDs, [start, end). path: str | None (default to ``self.DATA_RAW_DIR``) The path to location where raw HDF5 files are stored. """ # allow for using the default path, which can be redefined as class variable. leaving retrocompatibility print('WARNING: readInterval method is obsolete. Please use readData(pulseIdInterval=xxx).') if path is None: path = self.DATA_RAW_DIR self.pulseIdInterval = pulseIdInterval # Import the dataset dldPosXName = "/uncategorised/FLASH1_USER2/FLASH.FEL/HEXTOF.DAQ/DLD1:0/dset" dldPosYName = "/uncategorised/FLASH1_USER2/FLASH.FEL/HEXTOF.DAQ/DLD1:1/dset" dldTimeName = "/uncategorised/FLASH1_USER2/FLASH.FEL/HEXTOF.DAQ/DLD1:3/dset" dldMicrobunchIdName = "/uncategorised/FLASH1_USER2/FLASH.FEL/HEXTOF.DAQ/DLD1:2/dset" dldAuxName = "/uncategorised/FLASH1_USER2/FLASH.FEL/HEXTOF.DAQ/DLD1:4/dset" # delayStageName = "/Experiment/Pump probe laser/laser delay" # ENC.DELAY seems to be the wrong channel! Values appear in groups of ~10 identical values # -> ENC.DELAY is read out with 1 Hz # delayStageName = "/Experiment/Pump probe laser/delay line IK220.0/ENC.DELAY" # Proper channel is culumn with index 1 of ENC delayStageName = "/Experiment/Pump probe laser/delay line IK220.0/ENC" bamName = '/Electron Diagnostic/BAM/4DBC3/electron bunch arrival time (low charge)' bunchChargeName = '/Electron Diagnostic/Bunch charge/after undulator' macroBunchPulseIdName = '/Timing/Bunch train info/index 1.sts' opticalDiodeName = '/Experiment/PG/SIS8300 100MHz ADC/CH9/pulse energy/TD' gmdTunnelName = '/Photon Diagnostic/GMD/Pulse resolved energy/energy tunnel' gmdBdaName = '/Photon Diagnostic/GMD/Pulse resolved energy/energy BDA' # adc1Name = '/Experiment/PG/SIS8300 100MHz ADC/CH6/TD' # adc2Name = '/Experiment/PG/SIS8300 100MHz ADC/CH7/TD' daqAccess = BeamtimeDaqAccess.create(path) print('reading DAQ data') # ~ print("reading dldPosX") self.dldPosX = daqAccess.valuesOfInterval(dldPosXName, pulseIdInterval) # ~ print("reading dldPosY") self.dldPosY = daqAccess.valuesOfInterval(dldPosYName, pulseIdInterval) # ~ print("reading dldTime") self.dldTime = daqAccess.valuesOfInterval(dldTimeName, pulseIdInterval) # ~ print("reading dldMicrobunchId") self.dldMicrobunchId = daqAccess.valuesOfInterval(dldMicrobunchIdName, pulseIdInterval) # ~ print("reading dldAux") self.dldAux = daqAccess.valuesOfInterval(dldAuxName, pulseIdInterval) # ~ print("reading delayStage") self.delayStage = daqAccess.valuesOfInterval(delayStageName, pulseIdInterval) self.delayStage = self.delayStage[:, 1] # ~ print("reading BAM") self.bam = daqAccess.valuesOfInterval(bamName, pulseIdInterval) self.opticalDiode = daqAccess.valuesOfInterval(opticalDiodeName, pulseIdInterval) # ~ print("reading bunchCharge") self.bunchCharge = daqAccess.valuesOfInterval(bunchChargeName, pulseIdInterval) self.macroBunchPulseId = daqAccess.valuesOfInterval(macroBunchPulseIdName, pulseIdInterval) # self.macroBunchPulseId -= self.macroBunchPulseId[self.macroBunchPulseId > 0].min() self.macroBunchPulseId -= pulseIdInterval[0] self.gmdTunnel = daqAccess.valuesOfInterval(gmdTunnelName, pulseIdInterval) self.gmdBda = daqAccess.valuesOfInterval(gmdBdaName, pulseIdInterval) electronsToCount = self.dldPosX.copy().flatten() electronsToCount = np.nan_to_num(electronsToCount) electronsToCount = electronsToCount[electronsToCount > 0] electronsToCount = electronsToCount[electronsToCount < 10000] numOfElectrons = len(electronsToCount) print("Number of electrons: {0:,} ".format(numOfElectrons)) print("Creating data frame: Please wait...") self.createDataframePerElectron() self.createDataframePerMicrobunch() print('dataframe created')
def readData(self, runNumber=None, pulseIdInterval=None, path=None): """Read data by run number or macrobunch pulseID interval. Useful for scans that would otherwise hit the machine's memory limit. **Parameters**\n runNumber: int | None (default to ``self.runNumber``) number of the run from which to read data. If None, requires pulseIdInterval. pulseIdInterval: (int, int) | None (default to ``self.pulseIdInterval``) first and last macrobunches of selected data range. If None, the whole run defined by runNumber will be taken. path: str | None (default to ``self.DATA_RAW_DIR``) path to location where raw HDF5 files are stored. This is a union of the readRun and readInterval methods defined in previous versions. """ # Update instance attributes based on input parameters if runNumber is None: runNumber = self.runNumber else: self.runNumber = runNumber if pulseIdInterval is None: pulseIdInterval = self.pulseIdInterval else: self.pulseIdInterval = pulseIdInterval if (pulseIdInterval is None) and (runNumber is None): raise ValueError('Need either runNumber or pulseIdInterval to know what data to read.') if path is not None: try: daqAccess = BeamtimeDaqAccess.create(path) except: self.path_to_run = misc.get_path_to_run(runNumber, path) daqAccess = BeamtimeDaqAccess.create(self.path_to_run) else: path = self.DATA_RAW_DIR self.path_to_run = misc.get_path_to_run(runNumber, path) daqAccess = BeamtimeDaqAccess.create(self.path_to_run) self.daqAddresses = [] self.pulseIdInterval = self.getIds(runNumber, path) # Parse the settings file in the DAQ channels section for the list of # h5 addresses to read from raw and add to the dataframe. print('loading data...') for name, entry in self.settings['DAQ channels'].items(): name = misc.camelCaseIt(name) val = str(entry) if daqAccess.isChannelAvailable(val, self.pulseIdInterval): self.daqAddresses.append(name) if _VERBOSE: print('assigning address: {}: {}'.format(name.ljust(20), val)) setattr(self, name, val) else: # if _VERBOSE: print('skipping address missing from data: {}: {}'.format(name.ljust(20), val)) # TODO: get the available pulse id from PAH if pulseIdInterval is None: print('Reading DAQ data from run {}... Please wait...'.format(runNumber)) for address_name in self.daqAddresses: if _VERBOSE: print('reading address: {}'.format(address_name)) try: attrVal = getattr(self, address_name) values, otherStuff = daqAccess.allValuesOfRun(attrVal, runNumber) except AssertionError: print('Assertion error: {}'.format(address_name, attrVal, values, otherStuff )) setattr(self, address_name, values) if address_name == 'macroBunchPulseId': # catch the value of the first macrobunchID pulseIdInterval = (otherStuff[0], otherStuff[-1]) self.pulseIdInterval = pulseIdInterval macroBunchPulseId_correction = pulseIdInterval[0] if address_name == 'timeStamp': # catch the time stamps startEndTime = (values[0,0], values[-1,0]) self.startEndTime = startEndTime numOfMacrobunches = pulseIdInterval[1] - pulseIdInterval[0] else: print('reading DAQ data from interval {}'.format(pulseIdInterval)) self.pulseIdInterval = pulseIdInterval for address_name in self.daqAddresses: if _VERBOSE: print('reading address: {}'.format(address_name)) setattr(self, address_name, daqAccess.valuesOfInterval(getattr(self, address_name), pulseIdInterval)) numOfMacrobunches = pulseIdInterval[1] - pulseIdInterval[0] macroBunchPulseId_correction = pulseIdInterval[0] # necessary corrections for specific channels: try: self.delayStage = self.delayStage[:, 1] except: try: self.delayStage = self.delayStage[:, 0] print('1030nm Laser') except: print('no delay stage') self.macroBunchPulseId -= macroBunchPulseId_correction self.dldMicrobunchId -= self.UBID_OFFSET if _VERBOSE: print('Counting electrons...') electronsToCount = self.dldPosX.copy().flatten() electronsToCount = np.nan_to_num(electronsToCount) electronsToCount = electronsToCount[electronsToCount > 0] electronsToCount = electronsToCount[electronsToCount < 10000] self.numOfElectrons = len(electronsToCount) self.electronsPerMacrobunch = int(self.numOfElectrons / numOfMacrobunches) self.runInfo = { 'runNumber':self.runNumber, 'pulseIdInterval':self.pulseIdInterval, 'numberOfMacrobunches': numOfMacrobunches, 'numberOfElectrons':self.numOfElectrons, 'electronsPerMacrobunch': self.electronsPerMacrobunch, } try: self.runInfo['timestampStart'] = self.startEndTime[0].astype(int) self.runInfo['timestampStop'] = self.startEndTime[1].astype(int) self.runInfo['timestampDuration'] = self.startEndTime[1]-self.startEndTime[0].astype(int) self.runInfo['timeStart'] = datetime.utcfromtimestamp(self.startEndTime[0]).strftime('%Y-%m-%d %H:%M:%S') self.runInfo['timeStop'] = datetime.utcfromtimestamp(self.startEndTime[1]).strftime('%Y-%m-%d %H:%M:%S') self.runInfo['timeDuration'] = datetime.timedelta(self.startEndTime[1]-self.startEndTime[0]) except: self.runInfo['timestampStart'] = None self.runInfo['timestampStop'] = None self.runInfo['timestampDuration'] = None self.runInfo['timeStart'] = None self.runInfo['timeStop'] = None self.runInfo['timeDuration'] = None self.printRunOverview() # Old Print style # print('Run {0} contains {1:,} Macrobunches, from {2:,} to {3:,}' \ # .format(runNumber, numOfMacrobunches, pulseIdInterval[0], pulseIdInterval[1])) # try: # print("start time: {}, end time: {}, total time: {}" # .format(datetime.utcfromtimestamp(startEndTime[0]).strftime('%Y-%m-%d %H:%M:%S'), # datetime.utcfromtimestamp(startEndTime[1]).strftime('%Y-%m-%d %H:%M:%S'), # datetime.utcfromtimestamp(startEndTime[1] - startEndTime[0]).strftime('%H:%M:%S'))) # except: # pass # # print("Number of electrons: {0:,}; {1:,} e/Mb ".format(self.numOfElectrons, self.electronsPerMacrobunch)) print("Creating dataframes... Please wait...") with ProgressBar(): self.createDataframePerElectron() print('Electron dataframe created.') self.createDataframePerMicrobunch() print('Microbunch dataframe created.') print('Reading Complete.')
def readRun(self, runNumber=None, path=None): """ **[DEPRECATED]** Read a run. Generates dd and dd_micrubunches attributes as pd.DataFrame containing data from the given run. **Parameters**\n runNumber: int | None number corresponding to the rung to read data from. if None, it uses the value defined in the runNumber attribute. path: str | None path to location where raw HDF5 files are stored. If None, it uses the value from SETTINGS.ini. **Raise**\n Throws AttributeError if the run number is not given :Example: :: processor = DldFlashProcessor() processor.readRun(19059) """ print('WARNING: readRun method is obsolete. Please use readData(runNumber=xxx).') if path is None: # allow for using the default path, which can be redefined as class variable. path = self.DATA_RAW_DIR if runNumber is None: runNumber = self.runNumber assert runNumber is not None, 'No run number assigned!' else: self.runNumber = runNumber if self.runNumber is None: raise AttributeError('Run number not defined. ') # Import the dataset dldPosXName = "/uncategorised/FLASH1_USER2/FLASH.FEL/HEXTOF.DAQ/DLD1:0/dset" dldPosYName = "/uncategorised/FLASH1_USER2/FLASH.FEL/HEXTOF.DAQ/DLD1:1/dset" dldTimeName = "/uncategorised/FLASH1_USER2/FLASH.FEL/HEXTOF.DAQ/DLD1:3/dset" dldMicrobunchIdName = "/uncategorised/FLASH1_USER2/FLASH.FEL/HEXTOF.DAQ/DLD1:2/dset" dldAuxName = "/uncategorised/FLASH1_USER2/FLASH.FEL/HEXTOF.DAQ/DLD1:4/dset" # delayStageName = "/Experiment/Pump probe laser/laser delay" # ENC.DELAY seems to be the wrong channel! Values appear in groups of exactly the same value # delayStageName = "/Experiment/Pump probe laser/delay line IK220.0/ENC.DELAY" # Proper channel is column with index 1 of ENC delayStageName = "/Experiment/Pump probe laser/delay line IK220.0/ENC" bamName = '/Electron Diagnostic/BAM/4DBC3/electron bunch arrival time (low charge)' bunchChargeName = '/Electron Diagnostic/Bunch charge/after undulator' macroBunchPulseIdName = '/Timing/Bunch train info/index 1.sts' opticalDiodeName = '/Experiment/PG/SIS8300 100MHz ADC/CH9/pulse energy/TD' gmdTunnelName = '/Photon Diagnostic/GMD/Pulse resolved energy/energy tunnel' gmdBdaName = '/Photon Diagnostic/GMD/Pulse resolved energy/energy BDA' # adc1Name = '/Experiment/PG/SIS8300 100MHz ADC/CH6/TD' # adc2Name = '/Experiment/PG/SIS8300 100MHz ADC/CH7/TD' daqAccess = BeamtimeDaqAccess.create(path) print('reading DAQ data') # ~ print("reading dldPosX") self.dldPosX, otherStuff = daqAccess.allValuesOfRun(dldPosXName, runNumber) print('run contains macrobunchID from {0:,} to {1:,} \n-> {2:,} total macrobunches'.format(otherStuff[0], otherStuff[1], otherStuff[1] - otherStuff[0])) # ~ print("reading dldPosY") self.dldPosY, otherStuff = daqAccess.allValuesOfRun(dldPosYName, runNumber) # ~ print("reading dldTime") self.dldTime, otherStuff = daqAccess.allValuesOfRun(dldTimeName, runNumber) # ~ print("reading dldMicrobunchId") self.dldMicrobunchId, otherStuff = daqAccess.allValuesOfRun(dldMicrobunchIdName, runNumber) # ~ print("reading dldAux") self.dldAux, otherStuff = daqAccess.allValuesOfRun(dldAuxName, runNumber) # ~ print("reading delayStage") self.delayStage, otherStuff = daqAccess.allValuesOfRun(delayStageName, runNumber) self.delayStage = self.delayStage[:, 1] # ~ print("reading BAM") self.bam, otherStuff = daqAccess.allValuesOfRun(bamName, runNumber) self.opticalDiode, otherStuff = daqAccess.allValuesOfRun(opticalDiodeName, runNumber) # ~ print("reading bunchCharge") self.bunchCharge, otherStuff = daqAccess.allValuesOfRun(bunchChargeName, runNumber) self.macroBunchPulseId, otherStuff = daqAccess.allValuesOfRun(macroBunchPulseIdName, runNumber) self.macroBunchPulseId -= otherStuff[0] self.gmdTunnel, otherStuff = daqAccess.allValuesOfRun(gmdTunnelName, runNumber) self.gmdBda, otherStuff = daqAccess.allValuesOfRun(gmdBdaName, runNumber) electronsToCount = self.dldPosX.copy().flatten() electronsToCount = np.nan_to_num(electronsToCount) electronsToCount = electronsToCount[electronsToCount > 0] electronsToCount = electronsToCount[electronsToCount < 10000] numOfElectrons = len(electronsToCount) print("Number of electrons: {0:,} ".format(numOfElectrons)) print("Creating data frame: Please wait...") self.createDataframePerElectron() self.createDataframePerMicrobunch() print('dataframe created')
def readData(self, runNumber=None, pulseIdInterval=None, path=None): """Read data by run number or macrobunch pulseID interval. Useful for scans that would otherwise hit the machine's memory limit. :Parameters: runNumber : int | None (default to ``self.runNumber``) number of the run from which to read data. If None, requires pulseIdInterval. pulseIdInterval : (int, int) | None (default to ``self.pulseIdInterval``) first and last macrobunches of selected data range. If None, the whole run defined by runNumber will be taken. path : str | None (default to ``self.DATA_RAW_DIR``) path to location where raw HDF5 files are stored This is a union of the readRun and readInterval methods defined in previous versions. """ # Update instance attributes based on input parameters if runNumber is None: runNumber = self.runNumber else: self.runNumber = runNumber if pulseIdInterval is None: pulseIdInterval = self.pulseIdInterval else: self.pulseIdInterval = pulseIdInterval if (pulseIdInterval is None) and (runNumber is None): raise ValueError( 'Need either runNumber or pulseIdInterval to know what data to read.' ) # parse settings and set all dataset addresses as attributes. settings = ConfigParser() if os.path.isfile( os.path.join(os.path.dirname(__file__), 'SETTINGS.ini')): settings.read( os.path.join(os.path.dirname(__file__), 'SETTINGS.ini')) else: settings.read( os.path.join(os.path.dirname(os.path.dirname(__file__)), 'SETTINGS.ini')) section = 'DAQ channels' print('searching for data...') if path is not None: try: daqAccess = BeamtimeDaqAccess.create(path) except: self.path_to_run = misc.get_path_to_run(runNumber, path) daqAccess = BeamtimeDaqAccess.create(self.path_to_run) else: path = self.DATA_RAW_DIR self.path_to_run = misc.get_path_to_run(runNumber, path) daqAccess = BeamtimeDaqAccess.create(self.path_to_run) self.daqAddresses = [] for entry in settings[section]: name = misc.camelCaseIt(entry) val = str(settings[section][entry]) if daqAccess.isChannelAvailable(val, self.getIds(runNumber, path)): self.daqAddresses.append(name) if _VERBOSE: print('assigning address: {}: {}'.format( name.ljust(20), val)) setattr(self, name, val) else: # if _VERBOSE: print('skipping address missing from data: {}: {}'.format( name.ljust(20), val)) # TODO: get the available pulse id from PAH if pulseIdInterval is None: print('Reading DAQ data from run {}... Please wait...'.format( runNumber)) for address_name in self.daqAddresses: if _VERBOSE: print('reading address: {}'.format(address_name)) try: attrVal = getattr(self, address_name) values, otherStuff = daqAccess.allValuesOfRun( attrVal, runNumber) except AssertionError: print('Assertion error: {}'.format(address_name, attrVal, values, otherStuff)) setattr(self, address_name, values) if address_name == 'macroBunchPulseId': # catch the value of the first macrobunchID pulseIdInterval = (otherStuff[0], otherStuff[-1]) self.pulseIdInterval = pulseIdInterval macroBunchPulseId_correction = pulseIdInterval[0] if address_name == 'timeStamp': # catch the time stamps startEndTime = (values[0, 0], values[-1, 0]) self.startEndTime = startEndTime numOfMacrobunches = pulseIdInterval[1] - pulseIdInterval[0] print('Run {0} contains {1:,} Macrobunches, from {2:,} to {3:,}'\ .format(runNumber, numOfMacrobunches, pulseIdInterval[0], pulseIdInterval[1])) print("start time: {}, end time: {}, total time: {}".format( datetime.utcfromtimestamp( startEndTime[0]).strftime('%Y-%m-%d %H:%M:%S'), datetime.utcfromtimestamp( startEndTime[1]).strftime('%Y-%m-%d %H:%M:%S'), datetime.utcfromtimestamp( startEndTime[1] - startEndTime[0]).strftime('%H:%M:%S'))) else: print('reading DAQ data from interval {}'.format(pulseIdInterval)) self.pulseIdInterval = pulseIdInterval for address_name in self.daqAddresses: if _VERBOSE: print('reading address: {}'.format(address_name)) setattr( self, address_name, daqAccess.valuesOfInterval(getattr(self, address_name), pulseIdInterval)) numOfMacrobunches = pulseIdInterval[1] - pulseIdInterval[0] macroBunchPulseId_correction = pulseIdInterval[0] # necessary corrections for specific channels: self.delayStage = self.delayStage[:, 1] self.macroBunchPulseId -= macroBunchPulseId_correction self.dldMicrobunchId -= self.UBID_OFFSET if _VERBOSE: print('Counting electrons...') electronsToCount = self.dldPosX.copy().flatten() electronsToCount = np.nan_to_num(electronsToCount) electronsToCount = electronsToCount[electronsToCount > 0] electronsToCount = electronsToCount[electronsToCount < 10000] self.numOfElectrons = len(electronsToCount) self.electronsPerMacrobunch = int(self.numOfElectrons / numOfMacrobunches) print("Number of electrons: {0:,}; {1:,} e/Mb ".format( self.numOfElectrons, self.electronsPerMacrobunch)) print("Creating dataframes... Please wait...") pbar = ProgressBar() with pbar: self.createDataframePerElectron() print('Electron dataframe created.') self.createDataframePerMicrobunch() print('Microbunch dataframe created.')