Пример #1
0
    def __init__(self, config_file=".\\ExExposure_config.dat"):
        super().__init__()  # Initialise the parent classes
        self.lastImage = np.zeros((32, 32))  # last acquired image
        self.BufferSize = 0  # number of images that can fit in the buffer

        self.emg = 1.0  # applied EM gain
        self.pag = 4.50  # preamp gain sensitivity (e- per AD count)
        self.Nr = 8.8  # readout noise (counts)

        self.ind = 0  # counter for number of images taken
        self.idle_time = 0  # time between acquisitions
        self.t0 = time.time()  # time at start of acquisition
        self.t1 = 0  # time time just after get acquisition
        self.t2 = time.time()  # time after emitting signals
        self.timeout = 5e3  # number of milliseconds to wait for acquire

        self.initialised = 0  # check whether the camera functions were loaded
        try:
            self.AF = Andor()  # functions for Andor camera
            self.AF.verbosity = False  # Set True for debugging
            self.AF.connected = False
            self.initialised = 1  # functions loaded but camera not connected
            if self.AF.OS == "Windows" and self.AF.architecture == "64bit":
                self.CameraConnect()
                self.initialised = 2  # camera connected, default config
                if self.AF.connected == True:
                    self.AF.SetDriverEvent(int(self.AcquisitionEvent))
                    self.ApplySettingsFromConfig(config_file=config_file)
                    # self.StabiliseTemperature()
                    self.initialised = 3  # fully initialised
            else:
                error("Andor SDK requires Windows 64 bit")
        except Exception as e:
            self.initialised = 0
            warning('Andor EMCCD not initialised.\n' + str(e))
Пример #2
0
 def add_column_to_array(self):
     """Make a list of values and add it to the given column 
     in the multirun values array. The function is chosen by the user.
     Values are repeated a set number of times, ordered according to the 
     ComboBox text. The selected channels are stored in lists."""
     try:  # make the list of values
         table = np.array(self.get_table()).T
         c = [column.astype(float) for column in table if '' not in column]
         vals = eval(self.col_range.text())
     except Exception as e:
         warning('Add column to multirun: invalid syntax "' +
                 self.col_range.text() + '".\n' + str(e))
         return 0
     col = int(self.col_index.text()) if self.col_index.text() else 0
     # store the selected channels
     self.ui_param['Order'] = self.order_edit.currentText()
     for key in self.measures.keys(
     ):  # ['Variable label', 'measure', 'measure_prefix', '1st hist ID']
         if self.measures[key].text(
         ):  # don't do anything if the line edit is empty
             self.ui_param[key] = self.types[key](self.measures[key].text())
     # order the list of values
     if self.ui_param['Order'] == 'descending':
         vals = list(reversed(vals))
     elif 'random' in self.ui_param['Order']:
         vals = list(vals)
         shuffle(vals)
     for i in range(self.table.rowCount()):
         try:  # set vals in table cells
             self.table.item(i, col).setText('%.4f' % vals[i])
         except IndexError:  # occurs if invalid range
             self.table.item(i, col).setText('')
Пример #3
0
 def load_config(self, file_name='daqconfig.dat'):
     """Load the acquisition settings from the config file."""
     self.stats[
         'config_file'] = file_name if file_name else self.try_browse(
             file_type='dat (*.dat);;all (*)')
     try:
         with open(self.stats['config_file'], 'r') as f:
             for line in f:
                 if len(line.split('=')) == 2:
                     key, val = line.replace('\n', '').split(
                         '=')  # there should only be one = per line
                     try:
                         self.stats[key] = self.types[key](val)
                     except KeyError as e:
                         warning(
                             'Failed to load DAQ default config line: ' +
                             line + '\n' + str(e))
         self.set_table()  # make sure the updates are displayed
         self.set_n(self.stats['n'])
         self.set_save_dir(self.stats['save_dir'])
         self.set_trace_file(self.stats['trace_file'])
         self.set_graph_file(self.stats['graph_file'])
         self.dc.channels = list(self.stats['channels'].keys())
         info('DAQ config loaded from ' + self.stats['config_file'])
     except FileNotFoundError as e:
         warning('DAQ settings could not find the config file.\n' + str(e))
Пример #4
0
 def set_n(self, dxn):
     """Change the Dexter run number to the new value.
     If it's during a multirun, check that the right number of 
     images were taken in the last run."""
     if self._k != self._m and self.seq.mr.ind > 1:
         warning('Run %s took %s / %s images.' %
                 (self._n, self._k, self._m))
     self._n = int(dxn)
     self._k = 0  # reset image count --- each run should start with im0
Пример #5
0
 def check_path(self, path, datepath):
     """Check if Python has permission to write to the given directory, path.
     If so, make a dated directory from that path."""
     try: # create directory by date if it doesn't already exist
         os.makedirs(path + datepath, exist_ok=True) # requies version > 3.2
         return path + datepath
     except PermissionError as e: 
         warning('Image saver could not create directory: '+
             path +'\nUsing current directory instead\n'+str(e))
         os.makedirs('.' + datepath, exist_ok=True)
         return '.' + datepath
Пример #6
0
 def make_roi_grid(self, toggle=True, method=''):
     """Create a grid of ROIs and assign them to analysers that are using the
     same image. Methods:
     Single ROI       -- make all ROIs the same as the first analyser's 
     Square grid      -- evenly divide the image into a square region for
         each of the analysers on this image.  
     2D Gaussian masks-- fit 2D Gaussians to atoms in the image."""
     method = method if method else self.sender().text()
     pos, shape = self.rh.ROIs[0].roi.pos(), self.rh.ROIs[0].roi.size()
     if method == 'Single ROI':
         for r in self.rh.ROIs:
             r.resize(*map(int, [pos[0], pos[1], shape[0], shape[1]]))
     elif method == 'Square grid':
         n = len(self.rh.ROIs)  # number of ROIs
         d = int((n - 1)**0.5 + 1)  # number of ROIs per row
         X = int(self.rh.shape[0] / d)  # horizontal distance between ROIs
         Y = int(self.rh.shape[1] /
                 int((n - 3 / 4)**0.5 + 0.5))  # vertical distance
         for i in range(n):  # ID of ROI
             try:
                 newx, newy = int(X * (i % d + 0.5)), int(Y *
                                                          (i // d + 0.5))
                 if any(
                     [newx // self.rh.shape[0], newy // self.rh.shape[1]]):
                     warning(
                         'Tried to set square ROI grid with (xc, yc) = (%s, %s)'
                         % (newx, newy) + ' outside of the image')
                     newx, newy = 0, 0
                 self.rh.ROIs[i].resize(*map(int, [newx, newy, 1, 1]))
             except ZeroDivisionError as e:
                 error('Invalid parameters for square ROI grid: ' +
                       'x - %s, y - %s, pic size - %s, roi size - %s.\n' %
                       (pos[0], pos[1], self.rh.shape[0],
                        (shape[0], shape[1])) +
                       'Calculated width - %s, height - %s.\n' % (X, Y) +
                       str(e))
     elif method == '2D Gaussian masks':
         try:
             im = self.im_canvas.image.copy() - self.rh.bias
             if np.size(np.shape(im)) == 2:
                 for r in self.rh.ROIs:
                     r.create_gauss_mask(
                         im)  # fit 2D Gaussian to max pixel region
                     # then block that region out of the image
                     try:
                         im[r.x - r.w:r.x + r.w + 1,
                            r.y - r.h:r.y + r.h + 1] = np.zeros(
                                (2 * r.w + 1, 2 * r.h + 1)) + np.min(im)
                     except (IndexError, ValueError):
                         pass
         except AttributeError:
             pass
Пример #7
0
 def EmptyBuffer(self):
     """Get all of the images currently stored in the camera buffer
     that have not yet been retreived. The dimensions of the returned
     array are: (# images, # kinetic scans, ROI width, ROI height)."""
     istart, iend = self.AF.GetNumberNewImages()
     if iend > istart:
         if iend >= self.BufferSize:
             warning("While emptying camera buffer: The camera buffer "
                     "was full, some images may have been overwritten")
         return self.AF.GetImages(istart, iend, self.AF.ROIwidth,
                                  self.AF.ROIheight)
     else:
         return []
Пример #8
0
 def apply_slice(self):
     """Use the text in the index slice line edit to select time steps"""
     try:
         self.chan_choices['Time step name'].clearSelection()
         for i in eval(self.index_slice.text()):
             try:
                 self.chan_choices['Time step name'].item(i).setSelected(
                     True)
             except AttributeError:
                 pass  # index out of range
         self.save_chan_selection()
     except (TypeError, ValueError, NameError) as e:
         warning('Invalid selection command for multirun timesteps "' +
                 self.index_slice.text() + '".\n' + str(e))
Пример #9
0
 def reset_dates(self, config_file='./config/config.dat', 
         date=time.strftime("%d %b %B %Y", time.localtime()).split(" ")):
     # load paths used from config.dat
     self.dirs_dict = self.get_dirs(config_file) # handy dict contains them all
     self.image_storage_path = self.dirs_dict['Image Storage Path: ']
     self.dexter_sync_file_name = self.dirs_dict['Dexter Sync File: ']
     self.results_path = self.dirs_dict['Results Path: ']
     self.sequences_path = self.dirs_dict['Sequences path: ']
     if self.image_storage_path: # =0 if get_dirs couldn't find config.dat, else continue
         # get the date to be used for file labeling
         self.date = date # day short_month long_month year
         datepath = r'\%s\%s\%s'%(self.date[3],self.date[2],self.date[0])
         self.image_storage_path = self.check_path(self.image_storage_path, datepath)
         self.results_path = self.check_path(self.results_path, datepath)
         # self.sequences_path = self.check_path(self.sequences_path, datepath)
     else: warning('Image saver could not load paths from config file: '+config_file)
Пример #10
0
 def load_from_files(self, trigger=None):
     """Prompt the user to select image files to process using the file
     browser.
     Keyword arguments:
         trigger:        Boolean passed from the QObject that triggers
                         this function."""
     im_list = []
     file_list = self.try_browse(title='Select Files',
                                 file_type='Images(*.asc);;all (*)',
                                 open_func=QFileDialog.getOpenFileNames)
     for file_name in file_list:
         try:
             im_vals = self.rh.load_full_im(file_name)
             im_list.append(im_vals)
         except Exception as e:  # probably file size was wrong
             warning("Failed to load image file: " + file_name + '\n' +
                     str(e))
     return im_list
Пример #11
0
 def set_chan_listbox(self, col):
     """Set the selected channels and timesteps with the values
     previously stored for the given column col. If there were
     no values stored previously or the index is out of range,
     reset the selection."""
     try:
         col = int(col) if col else 0
         mrtype = self.ui_param['Type'][col]
         antype = self.ui_param['Analogue type'][col]
         sel = {
             'Time step name':
             self.ui_param['Time step name'][col],
             'Analogue channel':
             self.ui_param['Analogue channel'][col] if any(
                 mrtype == x for x in self.column_options) else []
         }
         list_ind = self.ui_param['list index'][col]
         col_range_txt = self.col_range_text[col]
     except (IndexError, ValueError):
         mrtype, antype = 'Time step length', 'Fast analogue'
         sel = {'Time step name': [], 'Analogue channel': []}
         list_ind = 0
         col_range_txt = ''
     self.col_range.setText(col_range_txt)
     self.list_index.setText(str(list_ind))
     self.chan_choices['Type'].setCurrentText(mrtype)
     self.chan_choices['Analogue type'].setCurrentText(antype)
     self.chan_choices['Analogue channel'].setEnabled(
         any(mrtype == x for x in self.column_options))
     for key in ['Time step name', 'Analogue channel']:
         self.chan_choices[key].setCurrentRow(
             0, QItemSelectionModel.Clear)  # clear previous selection
         try:
             for i in sel[key]:  # select items at the stored indices
                 self.chan_choices[key].item(i).setSelected(True)
         except IndexError:
             pass  # perhaps sequence was updated but using old selection indices
         except AttributeError as e:
             warning(
                 "Couldn't set channels for the loaded multirun parameters. Load the sequence first, then load multirun parameters.\n"
                 + str(e))
Пример #12
0
    def ApplySettingsFromConfig(self, config_file="./ExExposure_config.dat"):
        """Read in a configuration file and apply camera settings from it.
        See the DocString for ApplySettings for descriptions of the 
        parameters.
        Keyword arguments:
        config_file -- the file used to load in config settings."""
        try:
            with open(config_file, 'r') as config_file:
                config_data = config_file.read().split("\n")
        except FileNotFoundError:
            warning("Andor camera config.dat file not found. " +
                    "Applying default settings.")
            self.ApplySettings()
            return [1]

        cvals = []
        for row in config_data:
            if row[:2] != '20':
                cvals.append(int(row.split('=')[-1]))
            else:  # exposure time is a float
                cvals.append(float(row.split('=')[-1]))

        errors = []
        errors.append(ERROR_CODE[self.AF.CoolerON()])
        errors.append(ERROR_CODE[self.AF.SetTemperature(cvals[0])])
        errors.append(ERROR_CODE[self.AF.SetCoolerMode(cvals[1])])
        errors.append(ERROR_CODE[self.AF.SetShutter(1, cvals[2])])
        errors.append(ERROR_CODE[self.AF.SetOutputAmplifier(cvals[3])])
        AmpMode = 12 * cvals[3]  # the first 12 settings are EM gain mode
        errors.append(ERROR_CODE[self.AF.SetHSSpeed(cvals[3], cvals[4])])
        errors.append(ERROR_CODE[self.AF.SetVSSpeed(cvals[5])])
        errors.append(ERROR_CODE[self.AF.SetPreAmpGain(cvals[6])])
        try:
            self.pag = Sensitivity[AmpMode + 3 * cvals[4] + cvals[6] - 1]
            self.Nr = ReadNoise[AmpMode + 3 * cvals[4] + cvals[6] - 1]
        except IndexError as e:
            self.pag = 4.50
            self.Nr = 8.8
            warning('Invalid camera acquisition settings: ' + 'PAG ' +
                    str(cvals[6]) + ', hsspeed ' + str(cvals[4]) + '\n' +
                    str(e))
        errors.append(ERROR_CODE[self.AF.SetEMCCDGain(cvals[7])])
        self.emg = cvals[7]
        self.AF.ROI = (cvals[9], cvals[10], cvals[12], cvals[13])
        errors.append(ERROR_CODE[self.AF.SetReadMode(cvals[15])])
        errors.append(ERROR_CODE[self.AF.SetAcquisitionMode(cvals[16])])
        if cvals[22] > 1:
            errors.append(ERROR_CODE[self.AF.SetNumberKinetics(cvals[22])])
        self.AF.PrevTrigger = cvals[
            17]  # store the trigger mode so it can be reset later
        errors.append(ERROR_CODE[self.AF.SetTriggerMode(cvals[17])])
        errors.append(ERROR_CODE[self.AF.SetFrameTransferMode(cvals[18])])
        errors.append(ERROR_CODE[self.AF.SetFastExtTrigger(cvals[19])])
        # crop mode requires frame transfer and external trigger modes
        errors.append(ERROR_CODE[self.SetROI(self.AF.ROI,
                                             hbin=cvals[8],
                                             vbin=cvals[11],
                                             crop=cvals[14])])
        errors.append(ERROR_CODE[self.AF.SetExposureTime(cvals[20])])
        errors.append(ERROR_CODE[self.AF.GetAcquisitionTimings()])
        self.BufferSize = self.AF.GetSizeOfCircularBuffer()
        if abs(cvals[20] - self.AF.exposure) / cvals[20] > 0.01:
            warning("Tried to set exposure time %.3g s" % cvals[20] +
                    " but acquisition settings require min. exposure time " +
                    "%.3g s." % self.AF.exposure)
        self.AF.verbosity = bool(cvals[21])
        self.AF.kscans = 1
        check_success = [e != 'DRV_SUCCESS' for e in errors]
        if any(check_success):
            warning("Didn't get DRV_SUCCESS for setting " +
                    str(check_success.index(True)))
        self.SettingsChanged.emit(self.emg, self.pag, self.Nr, True)
        return check_success
Пример #13
0
 def ApplySettings(self,
                   setPointT=-60,
                   coolerMode=1,
                   shutterMode=2,
                   outamp=0,
                   hsspeed=2,
                   vsspeed=4,
                   preampgain=3,
                   EMgain=1,
                   ROI=None,
                   hbin=1,
                   vbin=1,
                   cropMode=0,
                   readmode=4,
                   acqumode=5,
                   triggerMode=7,
                   frameTransf=0,
                   fastTrigger=0,
                   expTime=70e-6,
                   verbosity=False,
                   numKin=1):
     """Apply user settings.
     Keyword arguments:
     setPointT   -- temperature set point in degrees Celsius. 
     coolerMode  -- 1: temperature maintained on camera shutdown
                    2: ambient temperature on camera shutdown
     shutterMode -- typ=1: TTL high to open shutter
                    mod=1: internal shutter permanently open
                    mod=2: internal shutter permanently closed
     outamp      -- output amplification setting.
                     0: electron multiplication
                     1: conventional
     hsspeed     -- Horizontal shift speed (MHz)
           value - EM mode shift speed - conventional mode shift speed
             0:         17.0                         3.0
             1:         10.0                         1.0
             2:          5.0                         0.08
             3:          1.0 
     vsspeed     -- Vertical shift speeds (us / row).
                     0: 0.3  
                     1: 0.5
                     2: 0.9 
                     3: 1.7
                     4: 3.3 (default)
     preampgain  -- Pre-amp gain setting. The value can be 1, 2 or 3. 
                 See the system booklet for what these correspond to.
     EMgain      -- electron-multiplying gain factor.
     ROI         -- Region of Interest on the CCD. A tuple of form:
                     (xmin, xmax, ymin, ymax).
     hbin        -- number of horizontal pixels to bin in software
     vbin        -- number of vertical pixels to bin in software
     cropMode    -- reduce the active area of the CCD to improve 
                     throughput.
                     0: off        1: on
     readmode    -- 4: imaging readout mode
     acqumode    -- Camera acquisition mode
                     1: Single Scan
                     2: Accumulate
                     3. Kinetics
                     4: Fast Kinetics 
                     5: Run till abort
     triggerMode -- Mode for camera triggering
                     0: internal
                     1: External
                     6: External Start
                     7: External Exposure (Bulb)
                     9: External FVB EM (only valid for EM Newton models)
                     10: Software Trigger
                     12: External Charge Shifting
     frameTransf -- enable/disable frame transfer mode (not compatible
                     with external exposure mode).
                     0: off        1: on        
     fastTrigger -- enable/disable fast external triggering
                     0: off        1: on
     expTime     -- exposure time when not in external exposure trigger
                     mode. Units: seconds.
     verbosity   -- True for debugging info
     numKin      -- number of scans in kinetic mode."""
     errors = []
     errors.append(ERROR_CODE[self.AF.CoolerON()])
     errors.append(ERROR_CODE[self.AF.SetCoolerMode(coolerMode)])
     errors.append(ERROR_CODE[self.AF.SetTemperature(setPointT)])
     errors.append(ERROR_CODE[self.AF.SetShutter(1, shutterMode)])
     errors.append(ERROR_CODE[self.AF.SetOutputAmplifier(outamp)])
     AmpMode = 12 * outamp  # the first 12 settings are EM gain mode
     errors.append(ERROR_CODE[self.AF.SetHSSpeed(outamp, hsspeed)])
     errors.append(ERROR_CODE[self.AF.SetVSSpeed(vsspeed)])
     errors.append(ERROR_CODE[self.AF.SetPreAmpGain(preampgain)])
     errors.append(ERROR_CODE[self.AF.SetEMCCDGain(EMgain)])
     self.emg = EMgain
     try:
         self.pag = Sensitivity[AmpMode + 3 * hsspeed + preampgain - 1]
         self.Nr = ReadNoise[AmpMode + 3 * hsspeed + preampgain - 1]
     except IndexError as e:
         self.pag = 4.50
         self.Nr = 8.8
         warning('Invalid camera acquisition settings: ' + 'PAG ' +
                 str(preampgain) + ', hsspeed ' + str(hsspeed) + '\n' +
                 str(e))
     self.AF.ROI = ROI
     errors.append(ERROR_CODE[self.AF.SetReadMode(readmode)])
     errors.append(ERROR_CODE[self.AF.SetAcquisitionMode(acqumode)])
     if numKin > 1:
         errors.append(ERROR_CODE[self.AF.SetNumberKinetics(numKin)])
         # errors.append(ERROR_CODE[self.cam.AF.SetFastKineticsEx(
         #                     100, numKin, expTime, 4, 1, 1, 1)])
     self.AF.PrevTrigger = triggerMode  # store the trigger mode so it can be reset later
     errors.append(ERROR_CODE[self.AF.SetTriggerMode(triggerMode)])
     errors.append(ERROR_CODE[self.AF.SetFastExtTrigger(fastTrigger)])
     errors.append(ERROR_CODE[self.AF.SetFrameTransferMode(frameTransf)])
     # crop mode requires frame transfer and external trigger modes
     errors.append(ERROR_CODE[self.SetROI(self.AF.ROI,
                                          hbin=hbin,
                                          vbin=vbin,
                                          crop=cropMode)])
     errors.append(ERROR_CODE[self.AF.SetExposureTime(expTime)])
     errors.append(ERROR_CODE[self.AF.GetAcquisitionTimings()])
     self.BufferSize = self.AF.GetSizeOfCircularBuffer()
     if abs(expTime - self.AF.exposure) / expTime > 0.01:
         warning("Tried to set exposure time %.3g s" % expTime +
                 " but acquisition settings require min. exposure time " +
                 "%.3g s." % self.AF.exposure)
     self.AF.verbosity = verbosity
     check_success = [e != 'DRV_SUCCESS' for e in errors]
     if any(check_success):
         warning("Didn't get DRV_SUCCESS for setting " +
                 str(check_success.index(True)))
     self.SettingsChanged.emit(self.emg, self.pag, self.Nr, True)
     return check_success