'''

Author: Federica Lionetto
Date: March 5th, 2015

Description:
Automated measurement for CCE scan (bias voltage, attenuation, and delay).
The script takes a pedestal run, moves the laser to the starting position along x and z and then takes care of the data acquisitions with the Alibava system.
After the measurement, the position of the laser along x and z is reset.

Parameters:
- <sensor>, the type of sensor;
- <measurement>, the type of measurement;
- <firstpar>, the first value of the parameter identifying the measurement;
- <lastpar>, the last value of the parameter identifying the measurement;
- <steppar>, the step size along the value of the parameter identifying the measurement;
- <z>, the z position;
- <firstx>, the first x position;
- <lastx>, the last x position;
- <stepx>, the step size along x;
- <yyyymmdd>, the date according to the yyyymmdd format.

Some more information about <par>.
If <measurement> = <CCEBiasVoltageScan>, <firstpar> = 100 && <lastpar> = 200 && <steppar> = 20 means that the measurement is taken from 100 V to 200 V in 20 V steps.
If <measurement> = <CCEAttenuationScan>, <firstpar> = 21.0 && <lastpar> = 25.0 && <steppar> = 0.5 means that the measurement is taken from 21.0 dB to 25.0 dB in 0.5 dB steps.
If <measurement> = <CCEDelayScan>, <firstpar> = 67 && <lastpar> = 75 && <steppar> = 1 means that the measurement is taken from 67 ns to 75 ns in 1 ns steps.
More functionalities can be implemented.

Meaurements of type "CCEBiasVoltageScan" and "CCEDelayScan" have int parameters but measurements of type "CCEAttenuationScan" have float parameters. So float are used all the time, but casting them to int if necessary.

If the measurement is of type "CCEDelayScan" we need a different configuration file for each value of the delay. All these files are in "CCEDelayScanConfig" folder.

How to run it:
python ElectronicMonkeyCCEScan.py --s <sensor> --m <measurement> --fp <firstpar> --lp <lastpar> --sp <steppar> --z <z> --fx <firstx> --lx <lastx> --sx <stepx> --date <yyyymmdd>

For example:
python ElectronicMonkeyCCEScan.py --s Hans410 --m CCEBiasVoltageScan --fp 100 --lp 200 --sp 20 --z 176 --fx 0 --lx 50 --sx 2 --date 20150106

Arduino device ID:
DEVICE ID 2341:0042 on Bus 001 Address 045, Communications Device (in hexadecimal)

To get some information on the device:
lsusb -v -d 2341:0042

'''

import argparse
import subprocess
import os

import serial

import time

import numpy as np

import sys
sys.path.insert(0,'../Tools')
from SendEmail import *

parser = argparse.ArgumentParser(description='Define the parameters of the automated measurement for CCE scan.')

parser.add_argument('--s',help='type of sensor')
parser.add_argument('--m',help='type of measurement')

# Meaurements of type "CCEBiasVoltageScan" and "CCEDelayScan" have int parameters but measurements of type "CCEAttenuationScan" have float parameters. So float are used all the time, but casting them to int if necessary.
parser.add_argument('--fp',type=float,help='first value of the parameter identifying the measurement')
parser.add_argument('--lp',type=float,help='last value of the parameter identifying the measurement')
parser.add_argument('--sp',type=float,help='step size along the value of the parameter identifying the measurement')

parser.add_argument('--z',type=int,help='z position')

parser.add_argument('--fx',type=int,help='first x position')
parser.add_argument('--lx',type=int,help='last x position')
parser.add_argument('--sx',type=int,help='step size along x')

parser.add_argument('--date',type=int,help='date according to the yyyymmdd format')

args = parser.parse_args()

# Parameters and configuration.
sensor = args.s
measurement = args.m

firstpar = args.fp
lastpar = args.lp
steppar = args.sp

z = args.z

firstx = args.fx
lastx = args.lx
stepx = args.sx

yyyymmdd = args.date

nevents = 10000

folder = '/disk/groups/hep/flionett/TestStand/Data'
filename = ''
config = '/home/hep/flionett/TestStand/Repository/TestStandRepository/Software/AutomatedMeasurements'

print 'Type of sensor: ', sensor
print 'Type of measurement: ', measurement 

print 'First value of the parameter identifying the measurement: %.1f steps' % firstpar
print 'Last value of the parameter identifying the measurement: %.1f steps' % lastpar
print 'Step size along the value of the parameter identifying the measurement: %.1f steps' % steppar

print 'z position: %i steps' % z

print 'First x position: %i steps' % firstx
print 'Last x position: %i steps' % lastx
print 'Step size along x: %i steps' % stepx

print 'Number of events per DAQ: %i' % nevents

# Number of scanned values of the parameter identifying the measurement.
stepspar = (int(lastpar)-int(firstpar))/int(steppar)+1
print 'Number of scanned values of the parameter identifying the measurement: %i' % stepspar

# Number of scanned x positions.
stepsx = (lastx-firstx)/stepx+1
print 'Number of scanned x positions: %i' % stepsx

# Find Arduino.
ser = serial.Serial('/dev/ttyACM0',9600)

# Move the laser to the starting position along x and z.
print 'Move the laser to the starting position along x and z.'
# +10 if firstx is positive, +20 if firstx is negative, firstx times.
for xcounter in range(abs(firstx)) :
    print 'Step along x %i of %i' % (xcounter,firstx)
    if (firstx > 0) :
        ser.write('+10')
    elif (firstx < 0) :
        ser.write('+20')
    time.sleep(1)
# +01 if z is positive, +02 if z is negative, z times.
for zcounter in range(abs(z)) :
    print 'Step along z %i of %i' % (zcounter,z)
    if (z > 0) :
        ser.write('+01')
    elif (z < 0) :
        ser.write('+02')
    time.sleep(1)

# Take a pedestal run.
if not os.path.exists(folder+"/"+sensor+"/"+measurement):
    os.makedirs(folder+"/"+sensor+"/"+measurement)
filename = folder+"/"+sensor+"/"+measurement+"/"+str(yyyymmdd)+"-216-"+"ped.ali"
configped = config+"/FocusingConfig"

printcommand = "echo alibava-gui --no-gui --nevts="+str(nevents)+" --out="+filename+" --pedestal "+configped
command = "alibava-gui --no-gui --nevts="+str(nevents)+" --out="+filename+" --pedestal "+configped
print '***'
subprocess.call(printcommand,shell=True)
subprocess.call(command,shell=True)

# Perform the measurement.
daqx = 0.
daqpar = 0.
for pospar in np.linspace(firstpar,lastpar,(lastpar-firstpar)/steppar+1) :
    daqx = 0.
    daqpar = daqpar+1.
    # If the measurement is of type "CCEDelayScan" we need a different configuration file for each value of the delay. All these files are in "CCEDelayScanConfig" folder.
    if (measurement == "CCEDelayScan") :
        configlas = config+"/CCEDelayScanConfig/"+"CCEDelayScanConfig"+str(int(pospar))+"ns"
    else :
        configlas = configped
      
    for posx in range(firstx,lastx+stepx,stepx) :
        daqx = daqx+1.
        status = 100*((daqx-1)+(daqpar-1)*stepsx)/(stepsx*stepspar)
        print 'Value of the parameter identifying the measurement: %i steps' % pospar
        print 'Position along x: %i steps' % posx
        print 'Position along z: %i steps' % z
        print 'Status: %.2f %% completed' % status

        if (measurement == "CCEBiasVoltageScan") :
            filename = folder+"/"+sensor+"/"+measurement+"/"+str(yyyymmdd)+"-"+str(int(pospar))+"V"+"-216-"+str(posx)+"x-"+str(z)+"z-las.ali"
        elif (measurement == "CCEAttenuationScan") :
            filename = folder+"/"+sensor+"/"+measurement+"/"+str(yyyymmdd)+"-"+str(pospar)+"dB"+"-216-"+str(posx)+"x-"+str(z)+"z-las.ali"
        elif (measurement == "CCEDelayScan") :
            filename = folder+"/"+sensor+"/"+measurement+"/"+str(yyyymmdd)+"-"+str(int(pospar))+"ns"+"-216-"+str(posx)+"x-"+str(z)+"z-las.ali"
        else :
            filename = folder+"/"+sensor+"/"+measurement+"/"+str(yyyymmdd)+"-216-"+str(posx)+"x-"+str(z)+"z-las.ali"

        printcommand = "echo alibava-gui --no-gui --nevts="+str(nevents)+" --out="+filename+" --laser "+configlas
        command = "alibava-gui --no-gui --nevts="+str(nevents)+" --out="+filename+" --laser "+configlas
        print '***'
        subprocess.call(printcommand,shell=True)
        subprocess.call(command,shell=True)
        # Move the stepper motor along x.
        # Send +10 (forward step of 5 microns) stepx times.
        if (posx < lastx) :
            for counter in range(stepx) :
                print '+10 %i' % counter
                ser.write('+10')
                time.sleep(2)
    # Reset the position of the stepper motor along x, to make it ready for the DAQs at the following value of the parameter identifying the measurement.
    # Send +20 (backward step of 5 microns) stepx*len(range(firstx,lastx,stepx)) times.
    for counter in range(stepx*len(range(firstx,lastx,stepx))) :
        print '+20 %i' % counter
        ser.write('+20')
        time.sleep(2)
print '***'

# Move the laser to the starting position along x and z.
print 'Move the laser to the starting position along x and z.'
# +20 if firstx is positive, +10 if firstx is negative, firstx times.
for xcounter in range(abs(firstx)) :
    print 'Step along x %i of %i' % (xcounter,firstx)
    if (firstx > 0) :
        ser.write('+20')
    elif (firstx < 0) :
        ser.write('+10')
    time.sleep(1)
# +02 if z is positive, +01 if z is negative, z times.
for zcounter in range(abs(z)) :
    print 'Step along z %i of %i' % (zcounter,z)
    if (z > 0) :
        ser.write('+02')
    elif (z < 0) :
        ser.write('+01')
    time.sleep(1)

print 'End of the measurement!'

# Send email.
sender = 'federica.lionetto@cern.ch'
receiver = 'federica.lionetto@cern.ch'
# receiver = 'philipp.gloor@gmail.com'
message = 'End of the measurement! Go to switch off the stepper motors ;)'
subject = 'End of the measurement!'
send_email(sender,receiver,message,subject)
