def pressure(self,f,add_to_pressbuffer=True):
		"""
		press,unit = pressuresensor_OMEGA.pressure(f,add_to_pressbuffer=True)
		
		Read out current pressure value.
		
		INPUT:
		f: file object for writing data (see datafile.py). If f = 'nofile', data is not written to any data file.
		add_to_pressbuffer (optional): flag to indicate if data get appended to pressure buffer (default=True)

		OUTPUT:
		press: pressure value in hPa (float)
		unit: unit of pressure value (string)
		"""	

		p = None;
		unit = '?';
		t = misc.now_UNIX()
		if not(hasattr(self,'ser')):
			self.warning( 'sensor is not initialised, could not read data.' )
		else:
			try:
				# get pressure reading from the sensor:
				self.ser.write(('P\r').encode('utf-8')) # send command to serial port
				ans =  self.ser.readline().decode('utf-8') # read response and decode ASCII
				if ans[0] == '>':
					# fix > character dangling in the serial buffer from previous reading
					ans = ans[1:]
				self.ser.flushInput() 	# make sure input is empty
				
				ans = ans.split(' ')
				p = float( ans[0] ) # convert string to float
				unit = ans[1]
				if unit != 'bar':
					raise ValueError( 'OMEGA pressure sensor returned unit = ' + unit + ', not bar!')
				else:
					# convert to mbar = hPa:
					p = 1000 * p
					unit = 'hPa'
						
				# get timestamp
				t = misc.now_UNIX()

				# add data to peakbuffer
				if add_to_pressbuffer:
					self.pressbuffer_add(t,p,unit)

			except ValueError as e:
				self.warning( e )
			except:
				self.warning( 'An unknown error occured while reading the OMEGA pressure sensor!' )

		# write data to datafile
		if not ( f == 'nofile' ):
			f.write_pressure('PRESSURESENSOR_WIKA',self.label(),p,unit,t)

		return p,unit
Beispiel #2
0
    def pressure(self, f, add_to_pressbuffer=True):
        """
		press,unit = pressuresensor_VIRTUAL.pressure(f,add_to_pressbuffer=True)
		
		Read out current pressure value.
		
		INPUT:
		f: file object for writing data (see datafile.py). If f = 'nofile', data is not written to any data file.
		add_to_pressbuffer (optional): flag to indicate if data get appended to pressure buffer (default=True)

		OUTPUT:
		press: pressure value in hPa (float)
		unit: unit of pressure value (string)
		"""

        p = 1000 + (numpy.random.randn() - 0.5) * 50
        unit = 'hPa'

        # get timestamp
        t = misc.now_UNIX()

        # add data to peakbuffer
        if add_to_pressbuffer:
            self.pressbuffer_add(t, p, unit)

        # write data to datafile
        if not (f == 'nofile'):
            f.write_pressure('PRESSURESENSOR_VIRTUAL', self.label(), p, unit,
                             t)

        return p, unit
Beispiel #3
0
	def pressbuffer_add(self,t,p,unit):
		"""
		pressuresensor_OMEGA.pressbuffer_add(t,p,unit)
		
		Add data to pressure data buffer
				
		INPUT:
		t: epoch time
		p: pressure value
		unit: unit of pressure value (char/string)
		
		OUTPUT:
		(none)
		"""
				
		self._pressbuffer_t = numpy.append( self._pressbuffer_t , t )
		self._pressbuffer_p = numpy.append( self._pressbuffer_p , p )
		self._pressbuffer_unit.append( unit )

		N = self._pressbuffer_max_len
		
		if self._pressbuffer_t.shape[0] > N:
			self._pressbuffer_t    = self._pressbuffer_t[-N:]
			self._pressbuffer_p    = self._pressbuffer_p[-N:]
			self._pressbuffer_unit = self._pressbuffer_unit[-N:]

		self._pressbuffer_lastupdate_timestamp = misc.now_UNIX()
	def temperature(self,f,add_to_tempbuffer=True):
		"""
		temp,unit = temperaturesensor_VIRTUAL.temperature(f)
		
		Read out current temperaure value.
		
		INPUT:
		f: file object for writing data (see datafile.py). If f = 'nofile', data is not written to any data file.
		add_to_tempbuffer (optional): flag to indicate if data get appended to temperature buffer (default=True)

		OUTPUT:
		temp: temperature value (float)
		unit: unit of temperature value (string)
		"""	
		
		temp = 15 + (numpy.random.randn()-0.5)*5;
		unit = 'deg.C';

		# get timestamp
		t = misc.now_UNIX()

		# add data to peakbuffer
		if add_to_tempbuffer:
			self.tempbuffer_add(t,temp,unit)

		# write data to datafile
		if not ( f == 'nofile' ):
			f.write_temperature('TEMPERATURESENSOR_VIRTUAL',self.label(),temp,unit,t)

		return temp,unit
	def tempbuffer_add(self,t,T,unit):
		"""
		temperaturesensor_VIRTUAL.tempbuffer_add(t,T,unit)
		
		Add data to temperature data buffer
				
		INPUT:
		t: epoch time
		T: temperature value
		unit: unit of pressure value (char/string)
		
		OUTPUT:
		(none)
		"""
				
		self._tempbuffer_t = numpy.append( self._tempbuffer_t , t )
		self._tempbuffer_T = numpy.append( self._tempbuffer_T , T )
		self._tempbuffer_unit.append( unit )

		N = self._tempbuffer_max_len
		
		if self._tempbuffer_t.shape[0] > N:
			self._tempbuffer_t    = self._tempbuffer_t[-N:]
			self._tempbuffer_T    = self._tempbuffer_T[-N:]
			self._tempbuffer_unit = self._tempbuffer_unit[-N:]

		self._tempbuffer_lastupdate_timestamp = misc.now_UNIX()
Beispiel #6
0
	def setpos(self,val,f):
		'''
		selectorvalve_VICI.setpos(val,f)

		Set valve position

		INPUT:
		val: new valve position (integer)
		f: datafile object for writing data (see datafile.py). If f = 'nofile', data is not written to any data file.

		OUTPUT:
		(none)
		'''
		
		val = int(val)
		
		if val > self.getnumpos():
			self.warning( 'Cannot set valve position to ' + str(val) + ': number of valve positions = ' + str(self.getnumpos()) + '. Skipping...' )
		
		if val < 1:
			self.warning( 'Cannot set valve position to ' + str(val) + '. Skipping...' )
		else:
			curpos = self.getpos()
			if not curpos == val: # check if valve is already at desired position
				# send command to serial port:
				self.ser.write(('GO' + str(val) + '\r\n').encode('ascii'))
			
			# write to datafile
			if not f == 'nofile':
				f.write_valve_pos('SELECTORVALVE_VICI',self.label(),val,misc.now_UNIX())

			# give the valve some time to actually do the switch:
			time.sleep(0.5)
Beispiel #7
0
    def setpos(self, val, f):
        '''
		selectorvalve_VICI.setpos(val,f)

		Set valve position

		INPUT:
		val: new valve position (integer)
		f: datafile object for writing data (see datafile.py). If f = 'nofile', data is not written to any data file.

		OUTPUT:
		(none)
		'''

        val = int(val)
        curpos = self.getpos()
        if not curpos == val:  # check if valve is already at desired position
            # send command to serial port:
            self.ser.write(('GO' + str(val) + '\r\n').encode('ascii'))

        # write to datafile
        if not f == 'nofile':
            f.write_valve_pos('SELECTORVALVE_VICI', self.label(), val,
                              misc.now_UNIX())

        # give the valve some time to actually do the switch:
        time.sleep(0.5)
Beispiel #8
0
	def pressure(self,f,add_to_pressbuffer=True):
		"""
		press,unit = pressuresensor_WIKA.pressure(f,add_to_pressbuffer=True)
		
		Read out current pressure value.
		
		INPUT:
		f: file object for writing data (see datafile.py). If f = 'nofile', data is not written to any data file.
		add_to_pressbuffer (optional): flag to indicate if data get appended to pressure buffer (default=True)

		OUTPUT:
		press: pressure value in hPa (float)
		unit: unit of pressure value (string)
		"""	

		cmd = 'PZ\x00' # command string to set polling mode
		cs = self.serial_checksum(cmd) # determine check sum
		self.ser.write((cmd + chr(cs) + '\r').encode('utf-8')) # send command with check sum to serial port
		ans = self.ser.read(1) # first byte (not used)
		ans = self.ser.read(4) # four bytes of IEEE754 float number
		p = struct.unpack('<f',ans)[0] # convert to 4 bytes to float
		ans = self.ser.read(1) # unit
		self.ser.read(2) # last two bytes (not used)
		
		# get timestamp
		t = misc.now_UNIX()

		# get unit:
		if ans == b'\xFF':
			unit = 'bar'
		elif ans == b'\xFE':
			unit = 'bar-rel.'
		elif ans == b'\x1F':
			unit = 'Psi'
		elif ans == b'\x1E':
			unit = 'Psi-rel.'
		elif ans == b'\xAF':
			unit = 'MPa'
		elif ans == b'\xAE':
			unit = 'MPa-rel.'
		elif ans == b'\xBF':
			unit = 'kg/cm2'
		elif ans == b'\xBE':
			unit = 'kg/cm2-rel.'
		else:
			self.warning('WIKA pressure sensor returned unknown pressure unit')
			unit = '???'

		# add data to peakbuffer
		if add_to_pressbuffer:
			self.pressbuffer_add(t,p,unit)

		# write data to datafile
		if not ( f == 'nofile' ):
			f.write_pressure('PRESSURESENSOR_WIKA',self.label(),p,unit,t)
			# self.warning('writing pressure value to data file is not yet implemented!')

		return p,unit
Beispiel #9
0
    def plot_tempbuffer(self):
        '''
		temperaturesensor_MAXIM.plot_tempbuffer()

		Plot trend (or update plot) of values in temperature data buffer (e.g. after adding data)
		NOTE: plotting may be slow, and it may therefore be a good idea to keep the update interval low to avoid affecting the duty cycle.

		INPUT:
		(none)

		OUTPUT:
		(none)
		'''

        if not self._has_display:
            self.warning(
                'Plotting of tempbuffer trend not possible (no display system available).'
            )

        else:

            try:  # make sure data analysis does not fail due to a silly plotting issue

                if not self._figwindow_is_shown:
                    # show the window on screen
                    self._fig.show()
                    self._figwindow_is_shown = True

                # Set plot data:
                t0 = misc.now_UNIX()
                self._tempbuffer_ax.lines[0].set_data(self._tempbuffer_t - t0,
                                                      self._tempbuffer_T)

                # Scale axes:
                self._tempbuffer_ax.relim()
                self._tempbuffer_ax.autoscale_view()

                # set title and axis labels:
                t0 = time.strftime("%b %d %Y %H:%M:%S", time.localtime(t0))
                t = 'TEMPBUFFER'
                if self._plot_title:
                    t = t + ' (' + self._plot_title + ')'
                self._tempbuffer_ax.set_title(t + ' at ' + t0)

                # Get temperature units right:
                self._tempbuffer_ax.set_ylabel('Temperature (' +
                                               str(self._tempbuffer_unit[0]) +
                                               ')')

                # Update the plot:
                # self._fig.canvas.draw()
                self._fig.canvas.flush_events()

            except:
                self.warning('Error during plotting of tempbuffer trend (' +
                             str(sys.exc_info()[0]) + ').')
	def plot_tempbuffer(self):
		'''
		temperaturesensor_MAXIM.plot_tempbuffer()

		Plot trend (or update plot) of values in temperature data buffer (e.g. after adding data)
		NOTE: plotting may be slow, and it may therefore be a good idea to keep the update interval low to avoid affecting the duty cycle.

		INPUT:
		(none)

		OUTPUT:
		(none)
		'''

		if not self._has_display:
			self.warning('Plotting of tempbuffer trend not possible (no display system available).')

		else:

			try: # make sure data analysis does not fail due to a silly plotting issue

				if not self._figwindow_is_shown:
					# show the window on screen
					self._fig.show()
					self._figwindow_is_shown = True

				# Set plot data:
				t0 = misc.now_UNIX()
				self._tempbuffer_ax.lines[0].set_data( self._tempbuffer_t - t0 , self._tempbuffer_T )

				# Scale axes:
				self._tempbuffer_ax.relim()
				self._tempbuffer_ax.autoscale_view()
				
				# set title and axis labels:
				t0 = time.strftime("%b %d %Y %H:%M:%S", time.localtime(t0))
				t = 'TEMPBUFFER'
				if self._plot_title:
					t = t + ' (' + self._plot_title + ')'
				self._tempbuffer_ax.set_title(t + ' at ' + t0)

				# Get temperature units right:
				self._tempbuffer_ax.set_ylabel('Temperature (' + str(self._tempbuffer_unit[0]) + ')' )

				# Update the plot:
				# self._fig.canvas.draw()
				self._fig.canvas.flush_events()

			except:
				self.warning( 'Error during plotting of tempbuffer trend (' + str(sys.exc_info()[0]) + ').' )
Beispiel #11
0
	def write_sample_desc(self,desc):
		"""
		datafile.write_sample_desc(self,desc)
		
		Write line with sample description (e.g., name or ID of sample)
		
		INPUT:
		desc: sample description, name, or ID (string)
		
		OUTPUT:
		(none)
		"""
		
		self.writeln(self.label(),'','SAMPLENAME',desc,misc.now_UNIX())
Beispiel #12
0
    def write_sample_desc(self, desc):
        """
		datafile.write_sample_desc(self,desc)
		
		Write line with sample description (e.g., name or ID of sample)
		
		INPUT:
		desc: sample description, name, or ID (string)
		
		OUTPUT:
		(none)
		"""

        self.writeln(self.label(), '', 'SAMPLENAME', desc, misc.now_UNIX())
Beispiel #13
0
	def write_comment(self,caller,cmt):
		"""
		datafile.write_comment(caller,cmt)
		
		Write COMMENT line to the data file.
		
		INPUT:
		caller: label / name of the calling object (string)
		cmt: comment string
		
		OUTPUT:
		(none)
		"""
		
		# cmt: comment line
		self.writeln( caller, '' , 'COMMENT' , cmt , misc.now_UNIX() )
Beispiel #14
0
    def write_comment(self, caller, cmt):
        """
		datafile.write_comment(caller,cmt)
		
		Write COMMENT line to the data file.
		
		INPUT:
		caller: label / name of the calling object (string)
		cmt: comment string
		
		OUTPUT:
		(none)
		"""

        # cmt: comment line
        self.writeln(caller, '', 'COMMENT', cmt, misc.now_UNIX())
Beispiel #15
0
    def pressbuffer_clear(self):
        """
		pressuresensor_VIRTUAL.pressbuffer_clear()

		Clear the buffer of pressure readings

		INPUT:
		(none)

		OUTPUT:
		(none)
		"""

        # clear data buffer for PRESSURE values:
        self._pressbuffer_t = self._pressbuffer_t[[]]
        self._pressbuffer_p = self._pressbuffer_p[[]]
        self._pressbuffer_unit = ['x'] * 0  # empty list
        self._pressbuffer_lastupdate_timestamp = misc.now_UNIX()
	def tempbuffer_clear(self):
		"""
		temperaturesensor_VIRTUAL.pressbuffer_clear()

		Clear the buffer of temperature readings

		INPUT:
		(none)

		OUTPUT:
		(none)
		"""

		# clear data buffer for TEMPERATURE values:
		self._tempbuffer_t = self._tempbuffer_t[[]]
		self._tempbuffer_T = self._tempbuffer_T[[]]
		self._tempbuffer_unit = ['x'] * 0 # empty list
		self._tempbuffer_lastupdate_timestamp = misc.now_UNIX()
Beispiel #17
0
	def writestatusfile(self,pos):
		if self._statusfile is not None:
			try:
				p = 'UNKNOWN'
				t = str(misc.now_UNIX()) # get current UNIX / Epoch time
				try:
					if pos > 0:
						p = str(pos)
				except:
					pass
				p = str(t) + ": POSITION = " + p
				self._statusfile.seek(0)   # clear the file
				self._statusfile.truncate()   # clear the file
				self._statusfile.write(p+'\n') # write valve position to file
				self._statusfile.flush()       # make sure data gets written to file now (don't wait for flushing file buffer)
				# time.sleep(0.05)
			except:
				self.warning('Could not write valve position to status file')
Beispiel #18
0
	def write_standard_conc(self,species,conc,mz):
		"""
		datafile.write_standard_conc(species,conc,mz)
		
		Write line with standard/calibration gas information to data file: name, concentration/mixing ratio, and mz value of gas species.
		
		INPUT:
		caller: type of calling object, i.e. the "data origin" (string)
		species: name of gas species (string)
		conc: volumetric concentration / mixing ratio (float)
		mz: mz value (integer)
		
		OUTPUT:
		(none)
		"""
		
		s = 'species=' + species + ' ; concentration=' + str(conc) + ' vol/vol ; mz=' + str(mz)
		self.writeln(self.label(),'','STANDARD',s,misc.now_UNIX())
Beispiel #19
0
    def write_standard_conc(self, species, conc, mz):
        """
		datafile.write_standard_conc(species,conc,mz)
		
		Write line with standard/calibration gas information to data file: name, concentration/mixing ratio, and mz value of gas species.
		
		INPUT:
		caller: type of calling object, i.e. the "data origin" (string)
		species: name of gas species (string)
		conc: volumetric concentration / mixing ratio (float)
		mz: mz value (integer)
		
		OUTPUT:
		(none)
		"""

        s = 'species=' + species + ' ; concentration=' + str(
            conc) + ' vol/vol ; mz=' + str(mz)
        self.writeln(self.label(), '', 'STANDARD', s, misc.now_UNIX())
Beispiel #20
0
    def temperature(self, f, add_to_tempbuffer=True):
        """
		temp,unit = temperaturesensor_MAXIM.temperature(f)
		
		Read out current temperaure value.
		
		INPUT:
		f: file object for writing data (see datafile.py). If f = 'nofile', data is not written to any data file.
		add_to_tempbuffer (optional): flag to indicate if data get appended to temperature buffer (default=True)

		OUTPUT:
		temp: temperature value (float)
		unit: unit of temperature value (string)
		"""

        temp = None
        unit = '?'
        t = misc.now_UNIX()
        if not (hasattr(self, '_sensor')):
            self.warning('sensor is not initialised, could not read data.')
        else:
            try:
                self.get_UART_lock()
                temp = self._sensor.get_temperature()
                self.release_UART_lock()
                unit = 'deg.C'

                # add data to peakbuffer
                if add_to_tempbuffer:
                    self.tempbuffer_add(t, temp, unit)
            except:
                self.release_UART_lock()
                self.warning('could not read sensor!')

        # write data to datafile
        if not (f == 'nofile'):
            # get timestamp

            f.write_temperature('TEMPERATURESENSOR_MAXIM', self.label(), temp,
                                unit, t)

        return temp, unit
Beispiel #21
0
	def pressbuffer_clear(self):
		"""
		pressuresensor_OMEGA.pressbuffer_clear()

		Clear the buffer of pressure readings

		INPUT:
		(none)

		OUTPUT:
		(none)
		"""

		# clear data buffer for PRESSURE values:
		if not(hasattr(self,'ser')):
			self.warning( 'sensor is not initialised, could not clear data buffer.' )
		else:
			self._pressbuffer_t = self._pressbuffer_t[[]]
			self._pressbuffer_p = self._pressbuffer_p[[]]
			self._pressbuffer_unit = ['x'] * 0 # empty list
			self._pressbuffer_lastupdate_timestamp = misc.now_UNIX()
	def temperature(self,f,add_to_tempbuffer=True):
		"""
		temp,unit = temperaturesensor_MAXIM.temperature(f)
		
		Read out current temperaure value.
		
		INPUT:
		f: file object for writing data (see datafile.py). If f = 'nofile', data is not written to any data file.
		add_to_tempbuffer (optional): flag to indicate if data get appended to temperature buffer (default=True)

		OUTPUT:
		temp: temperature value (float)
		unit: unit of temperature value (string)
		"""	

		temp = None;
		unit = '?';
		t = misc.now_UNIX()
		if not(hasattr(self,'_sensor')):
			self.warning( 'sensor is not initialised, could not read data.' )
		else:
			try:
				temp = self._sensor.get_temperature()
				unit = 'deg.C'
		
				# add data to peakbuffer
				if add_to_tempbuffer:
					self.tempbuffer_add(t,temp,unit)
			except:
				self.warning( 'could not read sensor!' )

		# write data to datafile
		if not ( f == 'nofile' ):
			# get timestamp

			f.write_temperature('TEMPERATURESENSOR_MAXIM',self.label(),temp,unit,t)

		return temp,unit
Beispiel #23
0
	def setpos(self,val,f):
		'''
		selectorvalve_VICI.setpos(val,f)

		Set valve position

		INPUT:
		val: new valve position (integer)
		f: datafile object for writing data (see datafile.py). If f = 'nofile', data is not written to any data file.

		OUTPUT:
		(none)
		'''
		
		val = int(val)
		
		if val > self.getnumpos():
			self.warning( 'Cannot set valve position to ' + str(val) + ': number of valve positions = ' + str(self.getnumpos()) + '. Skipping...' )
		
		if val < 1:
			self.warning( 'Cannot set valve position to ' + str(val) + '. Skipping...' )
		else:
			curpos = self.getpos()
			if not curpos == val: # check if valve is already at desired position
				# send command to serial port:
				self.get_serial_lock()
				self.ser.write(('GO' + str(val) + '\r\n').encode('ascii'))
				self.release_serial_lock()
			
			# write to datafile
			if not f == 'nofile':
				f.write_valve_pos('SELECTORVALVE_VICI',self.label(),val,misc.now_UNIX())

			# give the valve some time to actually do the switch:
			time.sleep(0.5)
			
			# write valve position to status file:
			self.writestatusfile(val)
Beispiel #24
0
    def tempbuffer_clear(self):
        """
		temperaturesensor_MAXIM.pressbuffer_clear()

		Clear the buffer of temperature readings

		INPUT:
		(none)

		OUTPUT:
		(none)
		"""

        # clear data buffer for TEMPERATURE values:

        if not (hasattr(self, '_sensor')):
            self.warning(
                'sensor is not initialised, could not clear data buffer.')
        else:
            self._tempbuffer_t = self._tempbuffer_t[[]]
            self._tempbuffer_T = self._tempbuffer_T[[]]
            self._tempbuffer_unit = ['x'] * 0  # empty list
            self._tempbuffer_lastupdate_timestamp = misc.now_UNIX()
    def setpos(self, val, f):
        '''
		selectorvalve_compositeVICI.setpos(val,f)

		Set valve position

		INPUT:
		val: new valve position (integer)
		f: datafile object for writing data (see datafile.py). If f = 'nofile', data is not written to any data file.

		OUTPUT:
		(none)
		'''

        val = int(val)

        if val > self.getnumpos():
            self.warning('Cannot set valve position to ' + str(val) +
                         ': number of valve positions = ' +
                         str(self.getnumpos()) + '. Skipping...')

        if val < 1:
            self.warning('Cannot set valve position to ' + str(val) +
                         '. Skipping...')
        else:
            curpos = self.getpos()
            if not curpos == val:  # check if valve is already at desired position
                # set positions of individual hardware valves:
                for i in range(len(self._hw_valves)):
                    self._hw_valves[i].setpos(self._valvespostable[val - 1][i],
                                              'nofile')
                self._lastpos = val

            # write to datafile
            if not f == 'nofile':
                f.write_valve_pos('SELECTORVALVE_COMPOSITEVICI', self.label(),
                                  val, misc.now_UNIX())
Beispiel #26
0
	def next( self , typ='' , samplename='' , standardconc=[] ):
		"""
		datafile.next( typ='MISC' , samplename='' , standardconc=[] )
				
		Close then current data file (if it's still open) and start a new file.
		
		INPUT:
		typ (optional): analysis type (string, default: typ = 'MISC'). The analysis type is written to the data file, and is appended to the file name. typ can be one of the following analysis types:
			typ = 'SAMPLE' (for sample analyses)
			typ = 'STANDARD' (for standard / calibration analyses)
			typ = 'BLANK' (for blank analyses)
			typ = 'MISC' (for miscellaneous analysis types, useful for testing, maintenance, or similar purposes)
		samplename (optional, only used if typ='SAMPLE'): description, name, or ID of sample (string)
		standardconc (optional, only used if typ='STANDARD'): standard gas information, list of 3-tuples, one tuple for each mz-value). Each tuple has the following 3 fields:
			field-1: name of species (string)
			field-2: volumetric species concentration in standard gas
			field-3: mz value used for analysis of this species
			
			example for N2 and Ar-40 in air, analyzed on mz=28 and mz=40: standardconc = [ ('N2',0.781,28) , ('Ar-40',0.9303,40) ]
					
		OUTPUT:
		(none)
		"""

		# close the current datafile (if it exists and is still open)
		self.close()
		
		# parse analysis type:
		typ = typ.replace(' ','')
		typ = typ.upper()
		if not ( typ == '' ):
			if not ( typ in ( 'SAMPLE' , 'STANDARD' , 'BLANK' , 'MISC' ) ):
				self.warning ( 'Unknown analysis type ' + typ + '. Ignoring analysis type...' )
				typ = ''
		
		# determine file name for new file
		n = misc.now_string()
		n = n.replace(':','-')
		n = n.replace(' ','_')
		if not ( typ == '' ):
			n = n + '_' + typ
		
		# check if file exists already:
		n0 = self.basepath() + os.sep + n
		n = n0
		k = 1
		while os.path.isfile(n + '.txt'):
			n = n0 + '+' + str(k)
			k = k+1
		
		# open the file
		n = n + '.txt'
		try:
			self.fid = open(n, 'w')
			    		
		except IOError as e:
			self.fid = -1;
			self.warning ('could not open new file (' + n + '): ' + str(e))
			return # exit

		# write header with data format info:
		self.write_comment(self.label(),'RUEDI data file created ' + misc.now_string() )
		self.write_comment(self.label(),'Data format:')
		self.write_comment(self.label(),'EPOCHTIME DATASOURCE[LABEL/NAME] TYPE: DATAFIELD-1; DATAFIELD-2; DATAFIELD-3; ...')
		self.write_comment(self.label(),'EPOCH TIME: UNIX time (seconds after Jan 01 1970 UTC), DATASOURCE: data origin (with optional label of origin object), TYPE: type of data, DATAFIELD-i: data fields, separated by colons. The field format and number of fields depends on the DATASOURCE and TYPE of data.')
	   	
	   	# write analysis type:
		if typ == '':
			typ = 'UNKNOWN'
		self.writeln( self.label() ,'','ANALYSISTYPE' , typ , misc.now_UNIX() )
		
		# write sample name:
		if typ == 'SAMPLE':
			if samplename == '':
				self.warning('No sample name given!')
			else:
				self.writeln( self.label() ,'','SAMPLENAME' , samplename , misc.now_UNIX() )

		# write standard gas information:
		if typ == 'STANDARD':
			if len(standardconc) == 0:
				self.warning('Standard gas information missing!')
			else:
				for i in range(0,len(standardconc)):
					self.write_standard_conc(standardconc[i][0],standardconc[i][1],standardconc[i][2])
Beispiel #27
0
	def pressure(self,f,add_to_pressbuffer=True):
		"""
		press,unit = pressuresensor_WIKA.pressure(f,add_to_pressbuffer=True)
		
		Read out current pressure value.
		
		INPUT:
		f: file object for writing data (see datafile.py). If f = 'nofile', data is not written to any data file.
		add_to_pressbuffer (optional): flag to indicate if data get appended to pressure buffer (default=True)

		OUTPUT:
		press: pressure value in hPa (float)
		unit: unit of pressure value (string)
		"""	

		p = None;
		unit = '?';
		t = misc.now_UNIX()
		if not(hasattr(self,'ser')):
			self.warning( 'sensor is not initialised, could not read data.' )
		else:
			try:
				cmd = 'PZ\x00' # command string to set polling mode
				cs = self.serial_checksum(cmd) # determine check sum
				self.ser.write((cmd + chr(cs) + '\r').encode('utf-8')) # send command with check sum to serial port
				ans = self.ser.read(1) # first byte (not used)
				ans = self.ser.read(4) # four bytes of IEEE754 float number
				p = struct.unpack('<f',ans)[0] # convert to 4 bytes to float
				ans = self.ser.read(1) # unit
				self.ser.read(2) # last two bytes (not used)
		
				# get timestamp
				t = misc.now_UNIX()

				# get unit:
				if ans == b'\xFF':
					unit = 'bar'
				elif ans == b'\xFE':
					unit = 'bar-rel.'
				elif ans == b'\x1F':
					unit = 'Psi'
				elif ans == b'\x1E':
					unit = 'Psi-rel.'
				elif ans == b'\xAF':
					unit = 'MPa'
				elif ans == b'\xAE':
					unit = 'MPa-rel.'
				elif ans == b'\xBF':
					unit = 'kg/cm2'
				elif ans == b'\xBE':
					unit = 'kg/cm2-rel.'
				else:
					self.warning('WIKA pressure sensor returned unknown pressure unit')
					unit = '???'

				# add data to peakbuffer
				if add_to_pressbuffer:
					self.pressbuffer_add(t,p,unit)

			except:
				self.warning( 'could not read sensor!' )

		# write data to datafile
		if not ( f == 'nofile' ):
			f.write_pressure('PRESSURESENSOR_WIKA',self.label(),p,unit,t)

		return p,unit
Beispiel #28
0
    def zero(self, mz, mz_offset, gate, f, zerotype=None):
        '''
		val,unit = rgams_SRS_virtual.zero(mz,mz_offset,gate,f,zerotype=None)
		
		Read out detector signal at single mass with relative offset to given m/z value (this is useful to determine the baseline near a peak at a given m/z value), see rgams_SRS.peak())
		The detector signal is read at mz+mz_offset
		
		INPUT:
		mz: m/z value (integer)
		mz_offset: offset relative m/z value (integer).
		gate: gate time (seconds) NOTE: gate time can be longer than the max. gate time supported by the hardware (2.4 seconds). If so, the multiple zero readings will be averaged to achieve the requested gate time.
		f: file object for writing data (see datafile.py). If f = 'nofile', data is not written to any data file.
		zerotype (optional): string to indicate the "type" of the ZERO reading (default: type=None). See 'peaktype' argument for self.peak(...).
		
		OUTPUT:
		val: signal intensity (float)
		unit: unit (string)
		
		NOTE FROM THE SRS RGA MANUAL:
		Single mass measurements are commonly performed in sets
		where several different masses are monitored sequencially
		and in a merry-go-round fashion.
		For best accuracy of results, it is best to perform the consecutive
		mass measurements in a set with the same type of detector
		and at the same noise floor (NF) setting.
		Fixed detector settings eliminate settling time problems
		in the electrometer and in the CDEM's HV power supply.
		'''

        # check for range of input values:
        mz = int(mz)
        mz_offset = int(mz_offset)

        # get timestamp
        t = misc.now_UNIX()

        if mz + mz_offset < 1:
            self.warning(
                'mz+mz_offset must be positive! Skipping zero measurement...')
            val = '-1'
            unit = '(none)'

        elif mz + mz_offset > self.mz_max():
            self.warning('mz+mz_offset value must be ' + self.mz_max() +
                         ' or less! Skipping zero measurement...')
            val = '-1'
            unit = '(none)'

        else:  # proceed with measurement

            # deal with gate times longer than 2.4 seconds (max. allowed with SRS-RGA):

            val = 1E-15
            unit = 'A'

        det = self.get_detector()
        if det == 'M':
            val = 1E4 * val

        if not (f == 'nofile'):
            f.write_zero('RGA_SRS', self.label(), mz, mz_offset, val, unit,
                         self.get_detector(), gate, t, zerotype)

        return val, unit
Beispiel #29
0
	def pressure(self,f,add_to_pressbuffer=True):
		"""
		press,unit = pressuresensor_OMEGA.pressure(f,add_to_pressbuffer=True)
		
		Read out current pressure value.
		
		INPUT:
		f: file object for writing data (see datafile.py). If f = 'nofile', data is not written to any data file.
		add_to_pressbuffer (optional): flag to indicate if data get appended to pressure buffer (default=True)

		OUTPUT:
		press: pressure value in hPa (float)
		unit: unit of pressure value (string)
		"""	

		p = None;
		unit = '?';
		t = misc.now_UNIX()
		if not(hasattr(self,'ser')):
			self.warning( 'sensor is not initialised, could not read data.' )
		else:
			try:
				# get pressure reading from the sensor:
				self.get_serial_lock()
				self.ser.write(('P\r').encode('utf-8')) # send command to serial port
				ans =  self.ser.readline().decode('utf-8') # read response and decode ASCII
				if ans[0] == '>':
					# fix > character dangling in the serial buffer from previous reading
					ans = ans[1:]
				self.ser.flushInput()  # make sure input is empty
				self.release_serial_lock()
				
				ans = ans.split(' ')
				p = float( ans[0] )    # convert string to float
				unit = ans[1]
				if unit != 'bar':
					raise ValueError( 'OMEGA pressure sensor returned unit = ' + unit + ', not bar!')
				else:
					# convert to mbar = hPa:
					p = 1000 * p
					unit = 'hPa'
						
				# get timestamp
				t = misc.now_UNIX()

				# add data to peakbuffer
				if add_to_pressbuffer:
					self.pressbuffer_add(t,p,unit)

			except ValueError as e:
				self.release_serial_lock()
				self.warning( e )
			except:
				self.release_serial_lock()
				self.warning( 'An unknown error occured while reading the OMEGA pressure sensor!' )

		# write data to datafile
		if not ( f == 'nofile' ):
			f.write_pressure('PRESSURESENSOR_OMEGA',self.label(),p,unit,t)

		return p,unit
Beispiel #30
0
    def peak(self, mz, gate, f, add_to_peakbuffer=True, peaktype=None):
        '''
		val,unit = rgams_SRS_virtual.peak(mz,gate,f,add_to_peakbuffer=True,peaktype=None)
		
		Read out detector signal at single mass (m/z value).
		
		INPUT:
		mz: m/z value (integer)
		gate: gate time (seconds) NOTE: gate time can be longer than the max. gate time supported by the hardware (2.4 seconds). If so, the multiple peak readings will be averaged to achieve the requested gate time.
		f: file object for writing data (see datafile.py). If f = 'nofile', data is not written to any data file.
		add_to_peakbuffer (optional): flag to choose if peak value is added to peakbuffer (default: add_to_peakbuffer=True)
		peaktype (optional): string to indicate the "type" of the PEAK reading (default: type=None). Specifying type will add the type string the the PEAK identifier in the data file in order to tell the processing tool(s) to use the PEAK_xyz reading for a specific purpose. Example: type='DECONV' will change the PEAK identifier to PEAK_DECONV, which will be used for deconvolution of mass spectrometric overlaps.
		
		OUTPUT:
		val: signal intensity (float)
		unit: unit (string)
		
		NOTE FROM THE SRS RGA MANUAL:
		Single mass measurements are commonly performed in sets
		where several different masses are monitored sequencially
		and in a merry-go-round fashion.
		For best accuracy of results, it is best to perform the consecutive
		mass measurements in a set with the same type of detector
		and at the same noise floor (NF) setting.
		Fixed detector settings eliminate settling time problems
		in the electrometer and in the CDEM's HV power supply.
		'''

        # check for range of input values:
        mz = int(mz)

        # get timestamp
        t = misc.now_UNIX()

        if mz < 1:
            self.warning(
                'mz value must be positive! Skipping peak measurement...')
            val = '-1'
            unit = '(none)'

        elif mz > self.mz_max():
            self.warning('mz value must be ' + str(self.mz_max()) +
                         ' or less! Skipping peak measurement...')
            val = '-1'
            unit = '(none)'

        else:  # proceed with measurement

            # deal with gate times longer than 2.4 seconds (max. allowed with SRS-RGA):
            v = 0.0

            if gate > 2.4:
                N = int(round(gate / 2.4))
                gt = 2.4
            else:
                N = 1
                gt = gate

            for k in range(N):

                # peak reading:
                time.sleep(gt)
                if self.get_electron_emission() > 0.0:
                    if mz == 4:
                        u = 1E-14
                    elif mz == 14:
                        u = 1.1E-10
                    elif mz == 15:
                        u = 1E-13
                    elif mz == 16:
                        u = 5E-13
                    elif mz == 18:
                        u = 1.0E-11
                    elif mz == 20:
                        u = 1.0E-12
                    elif mz == 22:
                        u = 1.0E-13
                    elif mz == 28:
                        u = 1.23E-9
                    elif mz == 32:
                        u = 2.4E-10
                    elif mz == 36:
                        u = 1E-13
                    elif mz == 40:
                        u = 3E-11
                    elif mz == 44:
                        u = 1E-12
                    elif mz == 84:
                        u = 1E-14
                    else:
                        u = 1E-15
                else:
                    u = 1.23e-15

                u = u / 1E-16
                u = (1 + (random.random() - 0.5) / 5) * u

                v = v + u

            v = v / N
            val = v * 1E-16  # multiply by 1E-16 to convert to Amperes
            unit = 'A'

        det = self.get_detector()
        if det == 'M':
            val = 1E4 * val
            if val > 1.3E-7:
                val = 1.3E-7

        if not (f == 'nofile'):
            f.write_peak('RGA_SRS', self.label(), mz, val, unit, det, gate, t,
                         peaktype)

        # add data to peakbuffer
        if add_to_peakbuffer:
            self.peakbuffer_add(t, mz, val, det, unit)

        return val, unit
Beispiel #31
0
    def next(self, typ='', samplename='', standardconc=[]):
        """
		datafile.next( typ='MISC' , samplename='' , standardconc=[] )
				
		Close then current data file (if it's still open) and start a new file.
		
		INPUT:
		typ (optional): analysis type (string, default: typ = 'MISC'). The analysis type is written to the data file, and is appended to the file name. typ can be one of the following analysis types:
			typ = 'SAMPLE' (for sample analyses)
			typ = 'STANDARD' (for standard / calibration analyses)
			typ = 'BLANK' (for blank analyses)
			typ = 'MISC' (for miscellaneous analysis types, useful for testing, maintenance, or similar purposes)
		samplename (optional, only used if typ='SAMPLE'): description, name, or ID of sample (string)
		standardconc (optional, only used if typ='STANDARD'): standard gas information, list of 3-tuples, one tuple for each mz-value). Each tuple has the following 3 fields:
			field-1: name of species (string)
			field-2: volumetric species concentration in standard gas
			field-3: mz value used for analysis of this species
			
			example for N2 and Ar-40 in air, analyzed on mz=28 and mz=40: standardconc = [ ('N2',0.781,28) , ('Ar-40',0.9303,40) ]
					
		OUTPUT:
		(none)
		"""

        # close the current datafile (if it exists and is still open)
        self.close()

        # parse analysis type:
        typ = typ.replace(' ', '')
        typ = typ.upper()
        if not (typ == ''):
            if not (typ in ('SAMPLE', 'STANDARD', 'BLANK', 'MISC')):
                self.warning('Unknown analysis type ' + typ +
                             '. Ignoring analysis type...')
                typ = ''

        # determine file name for new file
        n = misc.now_string()
        n = n.replace(':', '-')
        n = n.replace(' ', '_')
        if not (typ == ''):
            n = n + '_' + typ

        # check if file exists already:
        n0 = self.basepath() + os.sep + n
        n = n0
        k = 1
        while os.path.isfile(n + '.txt'):
            n = n0 + '+' + str(k)
            k = k + 1

        # open the file
        n = n + '.txt'
        try:
            self.fid = open(n, 'w')

        except IOError as e:
            self.fid = -1
            self.warning('could not open new file (' + n + '): ' + str(e))
            return  # exit

        # write header with data format info:
        self.write_comment(self.label(),
                           'RUEDI data file created ' + misc.now_string())
        self.write_comment(self.label(), 'Data format:')
        self.write_comment(
            self.label(),
            'EPOCHTIME DATASOURCE[LABEL/NAME] TYPE: DATAFIELD-1; DATAFIELD-2; DATAFIELD-3; ...'
        )
        self.write_comment(
            self.label(),
            'EPOCH TIME: UNIX time (seconds after Jan 01 1970 UTC), DATASOURCE: data origin (with optional label of origin object), TYPE: type of data, DATAFIELD-i: data fields, separated by colons. The field format and number of fields depends on the DATASOURCE and TYPE of data.'
        )

        # write analysis type:
        if typ == '':
            typ = 'UNKNOWN'
        self.writeln(self.label(), '', 'ANALYSISTYPE', typ, misc.now_UNIX())

        # write sample name:
        if typ == 'SAMPLE':
            if samplename == '':
                self.warning('No sample name given!')
            else:
                self.writeln(self.label(), '', 'SAMPLENAME', samplename,
                             misc.now_UNIX())

        # write standard gas information:
        if typ == 'STANDARD':
            if len(standardconc) == 0:
                self.warning('Standard gas information missing!')
            else:
                for i in range(0, len(standardconc)):
                    self.write_standard_conc(standardconc[i][0],
                                             standardconc[i][1],
                                             standardconc[i][2])
Beispiel #32
0
    def scan(self, low, high, step, gate, f):
        '''
		M,Y,unit = rgams_SRS_virtual.scan(low,high,step,gate,f)

		Analog scan

		INPUT:
		low: low m/z value (integer or decimal)
		high: high m/z value (integer or decimal)
		step: scan resolution (number of mass increment steps per amu)
		   step = integer number (10...25) --> use given number (high number equals small mass increments between steps)
		   step = '*' use default value (step = 10)
		gate: gate time (seconds)
		f: file object or 'nofile':
			if f is a DATAFILE object, the scan data is written to the current data file
			if f = 'nofile' (string), the scan data is not written to a datafile

		OUTPUT:
		M: mass values (mz, in amu)
		Y: signal intensity values (float)
		unit: unit of Y (string)
		'''

        # check for range of input values:
        llow = low
        hhigh = high
        low = math.floor(low)
        high = math.ceil(high)
        step = int(step)
        if step < 10:
            self.warning('Scan step must be 10 or higher! Using step = 10...')
            step = 10
        if step > 25:
            self.warning('Scan step must be 25 or less! Using step = 25...')
            step = 25
        if low < 0:
            self.warning(
                'Scan must start at m/z=0 or higher! Starting at m/z=0...')
            low = 0
        if high > self.mz_max():
            self.warning('Scan must end at m/z=' + self.mz_max() +
                         ' or lower! Ending at m/z= ' + self.mz_max() + '...')
            low = self.mz_max()
        if low > high:
            self.warning(
                'Scan m/z value at start must be lower than at end. Swapping values...'
            )
            x = low
            low = high
            high = x

        # configure RGA (gate time):
        self.set_gate_time(gate)

        # get time stamp:
        t = misc.now_UNIX()

        # number of scan points:
        N = (high - low) * step

        # determine scan data:
        low = float(low)
        high = float(high)
        M = [low + x * (high - low) / N for x in range(N)]
        Y = []
        for mz in M:
            y = self.peak(round(mz),
                          gate / N,
                          'nofile',
                          add_to_peakbuffer=False)[0]
            y0 = self.peak(100, gate / N, 'nofile', add_to_peakbuffer=False)[0]
            d = abs(mz - round(mz))
            if d > 0.35:
                # baseline:
                y = y0
            elif d > 0.15:
                # flank:
                y = y0 + 0.8 * (0.35 - d) / 0.15 * y

            Y.append(y)

        # set unit:
        unit = 'A'

        # discard data that are out of the desired mz range:
        Y = [Y[i] for i in range(len(M)) if (M[i] >= llow) & (M[i] <= hhigh)]
        M = [m for m in M if (m >= llow) & (m <= hhigh)]

        # write to data file:
        if not (f == 'nofile'):
            det = self.get_detector()
            f.write_scan('RGA_SRS', self.label(), M, Y, unit, det, gate, t)

        return M, Y, unit