Index: fact/tools/PyDimCtrl/fpydim.py
===================================================================
--- fact/tools/PyDimCtrl/fpydim.py	(revision 13788)
+++ fact/tools/PyDimCtrl/fpydim.py	(revision 13789)
@@ -1,139 +1,239 @@
 #!/usr/bin/python -tti
+
+# for tab completion
 import rlcompleter
 import readline
 readline.parse_and_bind('tab: complete')
 
-import sys
-import pydim
-import types
-import time # for sleep
-from pprint import pprint
-from keyword import iskeyword
+import sys      # for sys.exit() during bebugging mostly :-)
+import types                    # for dynamic class construction
+import time                     # for time.sleep
+from pprint import pprint       # for nice printing 
+
+from keyword import iskeyword   # in case dynamic methods are equal to keywords
+
+import pydim                    # for the C-API Dim Call Wrappers
+
+# using this line makes 'export DIM_DNS_NODE=daq' obsolete
 pydim.dic_set_dns_node('daq')
 
-# making server list
-rawlist = pydim.dic_sync_info_service('DIS_DNS/SERVER_LIST','C')
-# the output needs to be treated a bit .. it is a tuple with only one long string in it
-# the string contains | and the strange character \x00
-# I use both to cut the list apart
-rawlist = rawlist[0].split('\x00')
-servers_n_hosts = rawlist[0].split('|')
-server_ids = rawlist[1].split('|')
-
-servers = {}
-for i,snh in enumerate(servers_n_hosts):
-	snh = snh.split('@')
-	s = snh[0]
-	h = snh[1]
-	sid = server_ids[i]
-	servers[s] = (sid, h)
-
-# delete unneeded vars
-del servers_n_hosts
-del rawlist
-del server_ids
-
-# print servers
-
-# make service list
-services = {}
-dd = {}
-for serv in servers.keys():
-	# print serv+'/SERVICE_LIST'
-	sl_raw = pydim.dic_sync_info_service(serv+'/SERVICE_LIST','C')[0]
-	if serv+'/SERVICE_DESC' in sl_raw:
-		sd_raw = pydim.dic_sync_info_service(serv+'/SERVICE_DESC','C')[0]
-	else:
-		# print "Warning:", serv+'/SERVICE_DESC' , "not in SERVICE_LIST of", serv
-		sd_raw = ''
-	sl_raw = sl_raw.rstrip('\x00\n')
-	sl_raw = sl_raw.replace('\x00','')
-	sd_raw = sd_raw.rstrip('\x00\n')
-	sl = sl_raw.split('\n')
-	sd = sd_raw.split('\n')
-	
-	# create descripton dict dd from service_desc list sd
-	for d_str in sd:
-		service,equalsign,desc = d_str.partition('=')
-		#if '=' != equalsign:
-			# print "Error: server:", serv, "desc:", d_str
-		dd[service] = desc
-
-
-	services[serv] = {}
-	for service in sl:
-		service = service.split('|')
-		if service[0] in dd:
-			services[serv][service[0]] = (
-					service[1], service[2], dd[service[0]])
-	 #	else:
-			# print service[0], 'has no DESC in SERVICE_DESC'
-
-# pprint( services )
-
 class FactDimServer( object ):
 
-	def __init__(self, name):
-		self.name = name
-
-	def cmd(self, cmdstr, *args):
-		#args = cmdstr.split(' ')
-		#for i in range(len(args)):
-	#		i = len(args)-1-i
-	#		if not args[i]:
-	#			del args[i]
-		cmdstr=self.name+'/'+cmdstr.upper()
-	#	args = tuple(args[1:])
-		desc = services[self.name][cmdstr.upper()][0]
-		# there is a bug in the pydim library ... 
-		# even if a command need no argument
-		# one has to give one ... need to tell Niko about it.
-		if len(desc) == 0:
-			desc = 'I'
-			args=(1,)
-		# print 'cmd: cmdstr:', cmdstr,
-		# print '-args:', args,
-		# print '-desc:', desc
-		pydim.dic_sync_cmnd_service(cmdstr, args, desc, timeout=None)
-	def get(self, service):
-		full_srv_name = self.name+'/'+service.upper()
-		desc = services[self.name][full_srv_name][0]
-		return pydim.dic_sync_info_service(full_srv_name, desc)
-
-	def __call__(self):
-		""" get Server State as numeric code
-		    for convenience
-		"""
-		if hasattr(self, 'state'):
-			s = self.state()[0]
-			return int(s[ s.find('[')+1 : s.find(']') ])
-		else:
-			raise TypeError(self.name+' has no CMD called STATE')
-	
-	def wait(self, state_num, timeout=None):
-		""" waits for a certain state
-			BLOCKING
-			returns True if state was reached
-			returns False if timeout occured
-			raises TypeError if Server has no method state
-		"""
-
-		if not hasattr(self, 'state'):
-			raise TypeError(self.name+' has no CMD called STATE')
-		if timeout == None:
-			timeout = float('inf')
-		else:
-			timeout = float(timeout)
-		start = time.time()
-		while not self() == state_num:
-			time.sleep(0.1)
-			if time.time() >= start+timeout:
-				return False
-		return True
+    def __init__(self, name):
+        """ sets name of instance to name of server, all uppercase
+        """
+        self.name = name.upper()
+
+    def _cmd(self, cmdstr, *args):
+        """ used by all dynamicly created methods, which call a Dim CMD
+        """
+        cmdstr=self.name+'/'+cmdstr.upper()
+        desc = services[self.name][cmdstr.upper()][0]
+        
+        # there is a work around for a bug in pydim
+        # even if a command needs no argument, and desc is also empty string
+        # one has to give one ... need to tell Niko about it.
+        if not desc:
+            desc = 'I'
+            args=(1,)
+        pydim.dic_sync_cmnd_service(cmdstr, args, desc, timeout=None)
+
+
+    def _get(self, service):
+        """ used by all dynamicly created methods, which get a service 
+        """
+        full_srv_name = self.name+'/'+service.upper()
+        desc = services[self.name][full_srv_name][0]
+        return pydim.dic_sync_info_service(full_srv_name, desc)
+
+
+    def __call__(self):
+        """ Wrapper / For Convenience
+            self.state() returns a string (if it exists)
+            *returns* numeric state code, parsed from return of self.state()
+        """
+        if hasattr(self, 'state'):
+            s = self.state()[0]
+            return int(s[ s.find('[')+1 : s.find(']') ])
+        else:
+            raise TypeError(self.name+' has no CMD called STATE')
+    
+    def wait(self, state_num, timeout=None):
+        """ waits for a certain state
+            BLOCKING
+            returns True if state was reached
+            returns False if timeout occured
+            raises TypeError if Server has no method state
+        """
+
+        if not hasattr(self, 'state'):
+            raise TypeError(self.name+' has no CMD called STATE')
+        if timeout == None:
+            timeout = float('inf')
+        else:
+            timeout = float(timeout)
+        start = time.time()
+        while not self() == state_num:
+            time.sleep(0.1)
+            if time.time() >= start+timeout:
+                return False
+        return True
+
+
+
+# utility functions for dynamic addid of methods to classes
+def add_command(cls, name): 
+    meth_name = name.split('/')[1].lower()
+    if iskeyword(meth_name):
+        meth_name += '_cmd'
+        
+    # this is the new command, it simple calls the _cmd() method
+    def new_command(self, *args):
+        self._cmd(meth_name, *args)
+        
+    new_command.__name__ = meth_name
+    
+    # from this line on, the docstring of the method is created
+    if name in dd:
+        if not dd[name]:
+            new_command.__doc__ = "DESC in SERVICE_DESC is empty ?!"
+        else:
+            new_command.__doc__ = dd[name]
+    else:
+        new_command.__doc__ = "-- no DESC found in SERVICE_DESC --"
+    new_command.__doc__ += '\n'
+    new_command.__doc__ += services[name.split('/')[0]][name][0]
+    
+    # this line make the new_command() method, a method of the class cls
+    # giving it the name new_command.__name__
+    setattr( cls, new_command.__name__, new_command)
+
+# add_getter is very similar to add_command,
+# the only difference is, that it calls _get() instead of _cmd()
+# and since _get() has a return value, this return value is vorwarded to the user
+def add_getter(cls, name): 
+    meth_name = name.split('/')[1].lower()
+    if iskeyword(meth_name):
+        meth_name += '_cmd'
+    def new_command(self):
+        return self._get(meth_name)
+    new_command.__name__ = meth_name
+    if name in dd:
+        if not dd[name]:
+            new_command.__doc__ = "DESC in SERVICE_DESC is empty ?!"
+        else:
+            new_command.__doc__ = dd[name]
+    else:
+        new_command.__doc__ = "-- no DESC found in SERVICE_DESC --"
+    new_command.__doc__ += '\n'
+    new_command.__doc__ += services[name.split('/')[0]][name][0]
+    setattr( cls, new_command.__name__, new_command)
+
+
+
+
+
+# In order to create classes according to the Dim-Servers, currently connected
+# to the DIS_DNS I have to parse DIS_DNS/SERVER_LIST
+# This is done in two steps, first I get the list of Server Names from DIS_DNS
+# and the I get the list of each servers services and cmds, 
+# from each servers SERVICE_LIST and the service/command description 
+# from each servers SERVICE_DESC
+# I get quite a lot of information, which I store in python dicts, or
+# even nested dicts, if necessary.
+
+def ParseDnsServerList():
+    # making server list
+    rawlist = pydim.dic_sync_info_service('DIS_DNS/SERVER_LIST','C')
+    # the output needs to be treated a bit .. it is a tuple with only one long string in it
+    # the string contains | and the strange character \x00
+    # I use both to cut the list apart
+    rawlist = rawlist[0].split('\x00')
+    servers_n_hosts = rawlist[0].split('|')
+    server_ids = rawlist[1].split('|')
+
+    servers = {}
+    for i,snh in enumerate(servers_n_hosts):
+        snh = snh.split('@')
+        s = snh[0]
+        h = snh[1]
+        sid = server_ids[i]
+        servers[s] = (sid, h)
+
+    return servers
+
+
+
+# servers should be a dict containing uppercase server names as keys,
+# the values are not needed, so it might be any iteratable python listlike type 
+# to be precise
+def ParseServersServiceList( servers )
+    
+    services = {}
+    dd = {}
+    for server in servers:
+        # sl_raw is a tuple, with an really long string, which needs to be parsed
+        sl_raw = pydim.dic_sync_info_service(server+'/SERVICE_LIST','C')[0]
+        
+        # even without parsing, I can find out, if this server also gives me a 
+        # service description list. In case it does not, this is fine as well
+        # the doc string of the dynamicly created methods, will then contain 
+        # a note, that therer was no SERVICE_DESC ... 
+        if server+'/SERVICE_DESC' in sl_raw:
+            sd_raw = pydim.dic_sync_info_service(server+'/SERVICE_DESC','C')[0]
+        else:
+            sd_raw = ''
+        
+        # now before parsing, I strip off all ASCII zeroes '\x00' and all 
+        # line breaks off the *end* of the long string of both
+        # the service list sl
+        # and service description sd
+        #
+        # I think in sl_raw were alse some '\x00' in the middle .. these 
+        # are replaced by nothing, in case they are there.
+        sl_raw = sl_raw.rstrip('\x00\n')
+        sl_raw = sl_raw.replace('\x00','')
+        sd_raw = sd_raw.rstrip('\x00\n')
+        
+        # The lists are seperated by line breaks, so I split them using this
+        sl = sl_raw.split('\n')
+        sd = sd_raw.split('\n')
+        
+        # First I parse the service descriptons, so I have them available, 
+        # when I create the dict full of services.
+        # All desciptions look like this
+        # 'SERVER/SERVICE=some descriptive text' or
+        # 'SERVER/SERVICE='
+        # this I use to create the dictionary.
+        # create descripton dict dd from service_desc list sd
+        for d_str in sd:
+            service,equalsign,desc = d_str.partition('=')
+            #if '=' != equalsign:
+                # print "Error: server:", server, "desc:", d_str
+            dd[service] = desc
+
+        # Now I fill ther services dict. Each server gets a nested dict
+        # inside services. 
+        # Each service is explained in a string with a '|' in between.
+        # I use this for spliting. 
+        # The string look like this 
+        # SERVER/SERVICE|format-desc-str(e.g. I:2;C)|-empty- or CMD or RPC|
+        services[server] = {}
+        for service in sl:
+            service = service.split('|')
+            if service[0] in dd:
+                services[server][service[0]] = (
+                        service[1], service[2], dd[service[0]])
+    return services
+
+
+servers = ParseDnsServerList()
+services = ParseServersServiceList( servers )
+
 # create one class for each Fact Dim Server
 FactDimServerClasses = []
 for server_name in servers:
-	FactDimServerClasses.append( 
-			types.ClassType( server_name, (FactDimServer,), {}) )
+    FactDimServerClasses.append( 
+            types.ClassType( server_name, (FactDimServer,), {}) )
 
 # create an instace of each of the classes
@@ -143,6 +243,6 @@
 all_dims = []
 for i,server_name in enumerate(servers):
-	new_instance = FactDimServerClasses[i](server_name)
-	all_dims.append( new_instance )
+    new_instance = FactDimServerClasses[i](server_name)
+    all_dims.append( new_instance )
 del new_instance
 
@@ -150,96 +250,84 @@
 #print "connecting to Dim Servers... "
 for dim in all_dims:
-#	print dim.name.lower()
-	if dim.name == 'DIS_DNS':
-		continue
-	globals()[dim.name.lower()] = dim
-	dims.append(dim)
-
-# utility class for dynamic addid of methods to classes
-def add_command(cls, name): 
-	meth_name = name.split('/')[1].lower()
-	if iskeyword(meth_name):
-		meth_name += '_cmd'
-	def new_command(self, *args):
-		self.cmd(meth_name, *args)
-	new_command.__name__ = meth_name
-	if name in dd:
-		if not dd[name]:
-			new_command.__doc__ = "DESC in SERVICE_DESC is empty ?!"
-		else:
-			new_command.__doc__ = dd[name]
-	else:
-		new_command.__doc__ = "-- no DESC found in SERVICE_DESC --"
-	new_command.__doc__ += '\n'
-	new_command.__doc__ += services[name.split('/')[0]][name][0]
-	setattr( cls, new_command.__name__, new_command)
-
-def add_getter(cls, name): 
-	meth_name = name.split('/')[1].lower()
-	if iskeyword(meth_name):
-		meth_name += '_cmd'
-	def new_command(self):
-		return self.get(meth_name)
-	new_command.__name__ = meth_name
-	if name in dd:
-		if not dd[name]:
-			new_command.__doc__ = "DESC in SERVICE_DESC is empty ?!"
-		else:
-			new_command.__doc__ = dd[name]
-	else:
-		new_command.__doc__ = "-- no DESC found in SERVICE_DESC --"
-	new_command.__doc__ += '\n'
-	new_command.__doc__ += services[name.split('/')[0]][name][0]
-	setattr( cls, new_command.__name__, new_command)
+#    print dim.name.lower()
+    if dim.name == 'DIS_DNS':
+        continue
+    globals()[dim.name.lower()] = dim
+    dims.append(dim)
 
 for i,dim in enumerate(all_dims):
-	for cmd in services[dim.name]:
-		if 'CMD' in services[dim.name][cmd][1]:
-			cmdname = cmd.split('/')[1]
-			add_command(FactDimServerClasses[i], cmd)
-		elif not services[dim.name][cmd][1]:
-			cmdname = cmd.split('/')[1]
-			add_getter(FactDimServerClasses[i], cmd)
-
+    for cmd in services[dim.name]:
+        if 'CMD' in services[dim.name][cmd][1]:
+            cmdname = cmd.split('/')[1]
+            add_command(FactDimServerClasses[i], cmd)
+        elif not services[dim.name][cmd][1]:
+            cmdname = cmd.split('/')[1]
+            add_getter(FactDimServerClasses[i], cmd)
+
+##############################################################################
+# class for colored printing
 
 class bcolors:
-	    HEADER = '\033[95m'
-	    OKBLUE = '\033[94m'
-	    OKGREEN = '\033[92m'
-	    WARNING = '\033[93m'
-	    FAIL = '\033[91m'
-	    ENDC = '\033[0m'
-
-	    def disable(self):
-	        self.HEADER = ''
-	        self.OKBLUE = ''
-	        self.OKGREEN = ''
-	        self.WARNING = ''
-	        self.FAIL = ''
-	        self.ENDC = ''
+        HEADER = '\033[95m'
+        OKBLUE = '\033[94m'
+        OKGREEN = '\033[92m'
+        WARNING = '\033[93m'
+        FAIL = '\033[91m'
+        ENDC = '\033[0m'
+
+        def disable(self):
+            self.HEADER = ''
+            self.OKBLUE = ''
+            self.OKGREEN = ''
+            self.WARNING = ''
+            self.FAIL = ''
+            self.ENDC = ''
+
+##############################################################################
+# class which implements colored printing
+# method calls can be used instead of Python print calls 
+# for conveniently printing colored output.
+
+
 class MSG( bcolors):
-	def __init__(self, verbose = True):
-		self.output = verbose
-	
-	def fail(self, text ):
-		text = str(text)
-		if self.output:
-			print bcolors.FAIL + "ERROR:" + bcolors.ENDC,
-			print bcolors.FAIL + text + bcolors.ENDC
-
-	def warn(self, text ):
-		text = str(text)
-		if self.output:
-			print bcolors.WARNING + text + bcolors.ENDC
-
-	def ok(self, text ):
-		text = str(text)
-		if self.output:
-			print bcolors.OKGREEN + text + bcolors.ENDC
-
-	def __call__(self, *args):
-		if self.output:
-			for arg in args:
-				print arg,
-			print
-
+    def __init__(self, verbose = True):
+        """ create MSG instance, 
+            default is verbose,
+            sets self.output
+            
+            if:
+            self.*output* = True, object behaves as expeted
+            if False, no call return anything
+        """
+        self.output = verbose
+    
+    def fail(self, text ):
+        """ print in RED
+        """
+        text = str(text)
+        if self.output:
+            print bcolors.FAIL + "ERROR:" + bcolors.ENDC,
+            print bcolors.FAIL + text + bcolors.ENDC
+
+    def warn(self, text ):
+        """ print in YELLOW
+        """
+        text = str(text)
+        if self.output:
+            print bcolors.WARNING + text + bcolors.ENDC
+
+    def ok(self, text ):
+        """ print in GREEN
+        """
+        text = str(text)
+        if self.output:
+            print bcolors.OKGREEN + text + bcolors.ENDC
+
+    def __call__(self, *args):
+        """ print as Python print would do 
+        """
+        if self.output:
+            for arg in args:
+                print arg,
+            print
+
Index: fact/tools/PyDimCtrl/service.py
===================================================================
--- fact/tools/PyDimCtrl/service.py	(revision 13788)
+++ fact/tools/PyDimCtrl/service.py	(revision 13789)
@@ -1,263 +1,314 @@
-#!/usr/bin/python -tt
-	from fpydim import *
+#!/usr/bin/python -tti
+#from fpydim import *
+
+
 
 def IsReadyForDataTaking( verbose = True ):
-	drive = drive_control
-	bias = bias_control
-	fad = fad_control
-	
-	msg = MSG()
-	msg.output = verbose
-	msg("Checking if System isready for data taking... ")
-
-	ok = True
-	if not drive() == 7:
-		msg.warn( drive.state()[0] + "  NOT ok")
-		ok = False
-	if not feedback() == 12:
-		msg.warn( feedback.state()[0] + "  NOT ok")
-		ok = False
-	if not bias() == 9:
-		msg.warn( bias.state()[0] + "  NOT ok")
-		ok = False
-	if not fad() == 4:
-		msg.warn( fad.state()[0] + "  NOT ok")
-		ok = False
-	
-	if ok:
-		msg.ok( " all ok " )
-
-	return ok
+    drive = drive_control
+    bias = bias_control
+    fad = fad_control
+    
+    msg = MSG()
+    msg.output = verbose
+    msg("Checking if System isready for data taking... ")
+
+    ok = True
+    if not drive() == 7:
+        msg.warn( drive.state()[0] + "  NOT ok")
+        ok = False
+    if not feedback() == 12:
+        msg.warn( feedback.state()[0] + "  NOT ok")
+        ok = False
+    if not bias() == 9:
+        msg.warn( bias.state()[0] + "  NOT ok")
+        ok = False
+    if not fad() == 4:
+        msg.warn( fad.state()[0] + "  NOT ok")
+        ok = False
+    
+    if ok:
+        msg.ok( " all ok " )
+
+    return ok
 
 def StopTracking( verbose = True ):
-	msg = MSG()
-	msg.output = verbose
-
-	# defining a shortcut 
-	drive = drive_control
-
-	drive.stop()
-	if not drive.wait(5, 10):
-		msg.warn("drive did not reach state 5 after 10 seconds")
-		msg.warn( drive.state()[0].rstrip('\x00') )
-		return False
-
-	return True
+    msg = MSG()
+    msg.output = verbose
+
+    # defining a shortcut 
+    drive = drive_control
+
+    drive.stop()
+    if not drive.wait(5, 10):
+        msg.warn("drive did not reach state 5 after 10 seconds")
+        msg.warn( drive.state()[0].rstrip('\x00') )
+        return False
+
+    return True
 
 def TakeDataRun( verbose = True ):
-	fad = fad_control	
-	msg = MSG()
-	msg.output = verbose
-	if not IsReadyForDataTaking( verbose=False ):
-		msg.fail("System not Ready for DataTaking")
-		IsReadyForDataTaking( verbose=True )
-		return False
-	mcp.start(300,-1,'data\0')
-	if not fad.wait(8, 10):
-		msg.warn("FAD not in Writing Data after 10seconds")
-		return False
-	msg("... taking data: 300 seconds - normal data run")
-	if not fad.wait(4, 330):
-		msg.warn("FAD did not return to Connected, after 330 seconds")
-		return False
-	return True
+    fad = fad_control    
+    msg = MSG()
+    msg.output = verbose
+    if not IsReadyForDataTaking( verbose=False ):
+        msg.fail("System not Ready for DataTaking")
+        IsReadyForDataTaking( verbose=True )
+        return False
+    mcp.start(300,-1,'data\0')
+    if not fad.wait(8, 10):
+        msg.warn("FAD not in Writing Data after 10seconds")
+        return False
+    msg("... taking data: 300 seconds - normal data run")
+    if not fad.wait(4, 330):
+        msg.warn("FAD did not return to Connected, after 330 seconds")
+        return False
+    return True
 
 def TrackSource( Shift=0.6, Angle=50, SrcName='Crab', verbose=True):
-	drive = drive_control
-	
-	msg = MSG()
-	msg.output = verbose
-
-	if not drive.wait(5, 10):
-		msg.warn("drive not ready after 10sec")
-		msg.warn( drive.state()[0].rstrip('\x00') )
-		return False
-
-	SrcName += '\0'
-	drive.track_source( Shift, Angle, SrcName)
-	
-	return True
+    drive = drive_control
+    
+    msg = MSG()
+    msg.output = verbose
+
+    if not drive.wait(5, 10):
+        msg.warn("drive not ready after 10sec")
+        msg.warn( drive.state()[0].rstrip('\x00') )
+        return False
+
+    SrcName += '\0'
+    drive.track_source( Shift, Angle, SrcName)
+    
+    return True
 
 def WaitForTracking( CalmDownTime = 30, verbose = True):
-	drive = drive_control
-
-	msg = MSG()
-	msg.output = verbose
-
-	if not drive.wait(6, 10):
-		msg.warn("drive not in state moving after 10sec")
-		return False
-
-	if not drive.wait(7, 10):
-		msg.warn("drive not in state Tracking after 10sec")
-		return False
-
-	msg("waiting "+str(CalmDownTime)\
-			+"sec for drive to calm down and tracking to be stable")
-	time.sleep(CalmDownTime)
-	zoreturn True
+    drive = drive_control
+
+    msg = MSG()
+    msg.output = verbose
+
+    if not drive.wait(6, 10):
+        msg.warn("drive not in state moving after 10sec")
+        return False
+
+    if not drive.wait(7, 10):
+        msg.warn("drive not in state Tracking after 10sec")
+        return False
+
+    msg("waiting "+str(CalmDownTime)\
+            +"sec for drive to calm down and tracking to be stable")
+    time.sleep(CalmDownTime)
+    return True
 
 def PrepareBias( verbose = True):
-	msg = MSG()
-	msg.output = verbose
-	bias = bias_control
-
-	if feedback() != 12:
-		msg.warn("feedback is not in Current Control")
-		return False
-
-	bias.set_global_dac(1)
-	if not bias.wait(9, 10):
-		msg.warn("bias not in Voltage ON after 10sec")
-		return False
-	if not bias.wait(5, 10):
-		msg.warn("bias not Ramping after 10sec")
-		return False
-	if not bias.wait(9, 30):
-		msg.warn("bias not fully ramped up after 30sec")
-		return False
-
-	msg("waiting 45sec...")	
-	time.sleep(45)
-	return True
+    msg = MSG()
+    msg.output = verbose
+    bias = bias_control
+
+    if feedback() != 12:
+        msg.warn("feedback is not in Current Control")
+        return False
+
+    bias.set_global_dac(1)
+    if not bias.wait(9, 10):
+        msg.warn("bias not in Voltage ON after 10sec")
+        return False
+    if not bias.wait(5, 10):
+        msg.warn("bias not Ramping after 10sec")
+        return False
+    if not bias.wait(9, 30):
+        msg.warn("bias not fully ramped up after 30sec")
+        return False
+
+    msg("waiting 45sec...")    
+    time.sleep(45)
+    return True
 
 def TakePedestalOnRun( verbose = True ):
-	msg = MSG()
-	msg.output = verbose
-	if not IsReadyForDataTaking( verbose=False ):
-		msg.fail("System not Ready for DataTaking")
-		IsReadyForDataTaking( verbose=True )
-		return False
-	mcp.start(-1,1000,'pedestal\0')
-	if not fad.wait(8, 10):
-		msg.warn("FAD not in Writing Data after 10seconds")
-		return False
-	msg("... taking ped: 1000evts @25Hz")
-	if not fad.wait(4, 50):
-		msg.warn("FAD did not return to Connected, after 50 seconds")
-		return False
-	return True
-	
+    msg = MSG()
+    msg.output = verbose
+    if not IsReadyForDataTaking( verbose=False ):
+        msg.fail("System not Ready for DataTaking")
+        IsReadyForDataTaking( verbose=True )
+        return False
+    mcp.start(-1,1000,'pedestal\0')
+    if not fad.wait(8, 10):
+        msg.warn("FAD not in Writing Data after 10seconds")
+        return False
+    msg("... taking ped: 1000evts @25Hz")
+    if not fad.wait(4, 50):
+        msg.warn("FAD did not return to Connected, after 50 seconds")
+        return False
+    return True
+    
 def TakeExtLpRun( verbose = True ):
-	msg = MSG()
-	msg.output = verbose
-	if not IsReadyForDataTaking( verbose=False ):
-		msg.fail("System not Ready for DataTaking")
-		IsReadyForDataTaking( verbose=True )
-		return False
-	mcp.start(-1,1000,'light-pulser-ext\0')
-	if not fad.wait(8, 10):
-		msg.warn("FAD not in Writing Data after 10seconds")
-		return False
-	msg("... taking light-pulser-ext: 1000evts @25Hz")
-	if not fad.wait(4, 50):
-		msg.warn("FAD did not return to Connected, after 50 seconds")
-		return False
-	zoreturn True
+    msg = MSG()
+    msg.output = verbose
+    if not IsReadyForDataTaking( verbose=False ):
+        msg.fail("System not Ready for DataTaking")
+        IsReadyForDataTaking( verbose=True )
+        return False
+    mcp.start(-1,1000,'light-pulser-ext\0')
+    if not fad.wait(8, 10):
+        msg.warn("FAD not in Writing Data after 10seconds")
+        return False
+    msg("... taking light-pulser-ext: 1000evts @25Hz")
+    if not fad.wait(4, 50):
+        msg.warn("FAD did not return to Connected, after 50 seconds")
+        return False
+    return True
 
 def TakeData( verbose = True):
-	msg = MSG()
-	msg.output = verbose
-	TakePedestalOnRun()
-	TakeExtLpRun()
-	for i in range(4):
-		i +=1
-		msg("Taking Data Run "+str(i)+" of 4")
-		TakeDataRun()
+    msg = MSG()
+    msg.output = verbose
+    TakePedestalOnRun()
+    TakeExtLpRun()
+    for i in range(4):
+        i +=1
+        msg("Taking Data Run "+str(i)+" of 4")
+        TakeDataRun()
 
 def Take( time=0, events=0, runtype='drs-pedestal', verbose=True):
-	msg = MSG()
-	msg.output = verbose
-	fad = fad_control
-	runtype += '\0'
-	if not fad.wait(4, 10):
-		msg.warn("fad not connected after 10sec")
-		return False
-	mcp.start( time, events, runtype)
-	if not fad.wait(8, 30):
-		msg.warn("fad not Writing Data after 30sec")
-		return False
-	timeout = float('inf')
-	if time != -1:
-		timeout = time*1.1
-	if not fad.wait(4, timeout):
-		msg.warn("Data Writing not finished after "+str(timeout)+"sec")
-		return False
-	return True
+    msg = MSG()
+    msg.output = verbose
+    fad = fad_control
+    runtype += '\0'
+    if not fad.wait(4, 10):
+        msg.warn("fad not connected after 10sec")
+        return False
+    mcp.start( time, events, runtype)
+    if not fad.wait(8, 30):
+        msg.warn("fad not Writing Data after 30sec")
+        return False
+    timeout = float('inf')
+    if time != -1:
+        timeout = time*1.1
+    if not fad.wait(4, timeout):
+        msg.warn("Data Writing not finished after "+str(timeout)+"sec")
+        return False
+    return True
 
 def TakeDrsCalibration( verbose = True):
-	msg = MSG()
-	msg.output = verbose
-	bias = bias_control
-	fad = fad_control
-
-	bias.set_zero_voltage()
-	if not bias.wait(7, 10):
-		msg.warn("bias has not switched of after 10sec")
-		return False
-	fad.start_drs_calibration()
-	Take( -1, 1000, 'drs-pedestal')
-	Take( -1, 1000, 'drs-gain')
-	Take( -1, 1000, 'drs-pedestal')
-	fad.set_file_format(2)
-	Take( -1, 1000, 'drs-pedestal')
-	Take( -1, 1000, 'drs-time')
-	Take( -1, 1000, 'drs-time-upshifted')
-	fad.reset_secondary_drs_baseline()
-	Take(-1, 1000, 'pedestal')
-	fad.set_file_format(2)
-	Take(-1, 1000, 'pedestal')
+    msg = MSG()
+    msg.output = verbose
+    bias = bias_control
+    fad = fad_control
+
+    bias.set_zero_voltage()
+    if not bias.wait(7, 10):
+        msg.warn("bias has not switched of after 10sec")
+        return False
+    fad.start_drs_calibration()
+    Take( -1, 1000, 'drs-pedestal')
+    Take( -1, 1000, 'drs-gain')
+    Take( -1, 1000, 'drs-pedestal')
+    fad.set_file_format(2)
+    Take( -1, 1000, 'drs-pedestal')
+    Take( -1, 1000, 'drs-time')
+    Take( -1, 1000, 'drs-time-upshifted')
+    fad.reset_secondary_drs_baseline()
+    Take(-1, 1000, 'pedestal')
+    fad.set_file_format(2)
+    Take(-1, 1000, 'pedestal')
 
 def BlinkenLights(verbose = True):
-	msg = MSG(verbose)
-	fad = fad_control
-
-	for i in range(10):
-		fad.set_file_format(2)
-		time.sleep(1)
-		fad.set_file_format(0)
-		time.sleep(1)
+    msg = MSG(verbose)
+    fad = fad_control
+
+    for i in range(10):
+        fad.set_file_format(2)
+        time.sleep(1)
+        fad.set_file_format(0)
+        time.sleep(1)
 
 def TakeAmplCalib( roi=1024, verbose=True):
-	msg = MSG(verbose)
-	bias = bias_control
-	fad  = fad_control
-	if (roi!=1024) and (roi!=300):
-		raise ValueError('roi must be 300 or 1024')
-	# I do not understand, why the out put needs to be ENABLED??
-	feedback.enable_output(0)
-	bias.set_zero_voltage()
-	bias.wait(7) # VoltageOff
-	fad.start_drs_calibration
-	
-	Take(-1, 1000, 'drs-pedestal')
-	Take(-1, 1000, 'drs-gain')
-	if roi == 300:
-		Take(-1, 1000, 'pedestal')
-	if roi == 1024:
-		Take(-1, 1000, 'drs-pedestal')
-
-	fad.set_file_format(2)
-	if roi == 300:
-		Take(-1, 1000, 'pedestal')
-	if roi == 1024:
-		Take(-1, 1000, 'drs-pedestal')
+    msg = MSG(verbose)
+    bias = bias_control
+    fad  = fad_control
+    if (roi!=1024) and (roi!=300):
+        raise ValueError('roi must be 300 or 1024')
+    # I do not understand, why the out put needs to be ENABLED??
+    feedback.enable_output(0)
+    bias.set_zero_voltage()
+    bias.wait(7) # VoltageOff
+    fad.start_drs_calibration
+    
+    Take(-1, 1000, 'drs-pedestal')
+    Take(-1, 1000, 'drs-gain')
+    if roi == 300:
+        Take(-1, 1000, 'pedestal')
+    if roi == 1024:
+        Take(-1, 1000, 'drs-pedestal')
+
+    fad.set_file_format(2)
+    if roi == 300:
+        Take(-1, 1000, 'pedestal')
+    if roi == 1024:
+        Take(-1, 1000, 'drs-pedestal')
 
 def TakeTimeCalib( verbose=True ):
-	msg = MSG( verbose )
-	feedback.enable_output(0)
-	if bias() != 7:
-		bias.set_zero_voltage()
-		if not bias.wait(7, 10):
-			msg.warn("bias not ramped down after 10sec")
-			return False
-	fad.set_file_format(2)
-	Take(-1, 1000, 'drs-time')
-	Take(-1, 1000, 'drs-time-upshifted')
+    msg = MSG( verbose )
+    feedback.enable_output(0)
+    if bias() != 7:
+        bias.set_zero_voltage()
+        if not bias.wait(7, 10):
+            msg.warn("bias not ramped down after 10sec")
+            return False
+    fad.set_file_format(2)
+    Take(-1, 1000, 'drs-time')
+    Take(-1, 1000, 'drs-time-upshifted')
+
+
+# create introduction:
+class INTRO(object):
+    def __init__(self):
+        # nothing to do
+        pass
+        
+    def __repr__(self):
+        print "welcome to PyDimCtrl V0.1:"
+        print "--------------------------"
+        print "If the hardware is ON but not all the software is connected try:"
+        print "      Connect()"
+        print "If all the programs are already up and running, you might want to"
+        print "     TakeDrsAmplitudeCalibration(roi=1024) or "
+        print "     TakeDrsAmplitudeCalibration(roi=300)"
+        print "         i.e. ped, gain, trigger_offset + extra ped(for X-check)"
+        print "     TakeDrsTimeCalibration( type='upshifted' ) or "
+        print "     TakeDrsTimeCalibration( type='old' ) or "
+        print "     "
+        print "In case you would like to ramp up the Bias voltage try:"
+        print "     VoltageOn( mode='temperature' ) or"
+        print "     VoltageOn( mode='current' ) or"
+        print "     VoltageOn( mode='light_pulser' )"
+        print "Switch off with:"
+        print "     VoltageOff()"
+        print ""
+        print "In case you would like a Watchdog to check, if the Voltage is up"
+        print "and the BiasCrate is not disconnected, then try:"
+        print "     VoltageOn( mode='--see above--', Watchdog=True )"
+        print "PLEASE NOTE: The Watchdog will monitor the State of BIAS_CONTROL"
+        print "and in case of a connection loss, it will: "
+        print "     * print a warning"
+        print "     * issue a the RECONNECT command" 
+        print "     * issue SET_ZERO_VOLTAGE - since this is the only way to get referenced"
+        print "     * Ramp up again, using the same settings as before"
+        print "     * possible OverCurrent situation will be treated as usual"
+        print "The Watchdog will not react on any other state change, like OverCurrent or VoltageOff"
+        print ""
+        print ""
+        return ""
+        
+
+intro = INTRO()
 
 if __name__ == '__main__':
-	IsReadyForDataTaking()
-	TrackSource( Shift=0.6, Angle=50, SrcName='Crab', verbose=True)
-	WaitForTracking( CalmDownTime = 30, verbose = True)
-	TakeDataRun()
-	StopTracking()
+    print "welcome:"
+    print " type: intro"
+    print " for a short introduction"
+
+    
+    #IsReadyForDataTaking()
+    #TrackSource( Shift=0.6, Angle=50, SrcName='Crab', verbose=True)
+    #WaitForTracking( CalmDownTime = 30, verbose = True)
+    #TakeDataRun()
+    #StopTracking()
