From 72297eb9cb3470bce2ae2a089e4384de788e7197 Mon Sep 17 00:00:00 2001
From: Mercadier <mercadil@win.desy.de>
Date: Fri, 22 Mar 2019 14:54:45 +0100
Subject: [PATCH] Add plotting option to calibrateTIM() Add RunDirectory as
 attribute of the DataSet in load()

---
 Load.py | 12 ++------
 xgm.py  | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 84 insertions(+), 13 deletions(-)

diff --git a/Load.py b/Load.py
index c9bf086..7bb712f 100644
--- a/Load.py
+++ b/Load.py
@@ -1,11 +1,3 @@
-# -*- coding: utf-8 -*-
-""" Toolbox for SCS.
-
-    Various utilities function to quickly process data measured at the SCS instruments.
-
-    Copyright (2019) SCS Team.
-"""
-
 import numpy as np
 from karabo_data import RunDirectory
 import xarray as xr
@@ -221,4 +213,6 @@ def load(fields, runNB, proposalNB, semesterNB, topic='SCS', display=False, vali
 
     aligned_vals = xr.align(*vals, join='inner')
     result = dict(zip(keys, aligned_vals))
-    return xr.Dataset(result)
+    result = xr.Dataset(result)
+    result.attrs['run'] = run
+    return result
diff --git a/xgm.py b/xgm.py
index b638e27..5ef58ba 100644
--- a/xgm.py
+++ b/xgm.py
@@ -1,3 +1,10 @@
+# -*- coding: utf-8 -*-
+""" Toolbox for SCS.
+
+    Various utilities function to quickly process data measured at the SCS instruments.
+
+    Copyright (2019) SCS Team.
+"""
 import matplotlib.pyplot as plt
 import numpy as np
 import xarray as xr
@@ -429,9 +436,9 @@ def getTIMapd(data, mcp=1, use_apd=True, intstart=None, intstop=None,
         else:
             tim = xr.concat([tim, temp], dim='trainId')
     return tim
-    
 
-def calibrateTIM(data, rollingWindow=200, mcp=1, use_apd=True, intstart=None, intstop=None,
+
+def calibrateTIM(data, rollingWindow=200, mcp=1, plot=False, use_apd=True, intstart=None, intstop=None,
               bkgstart=None, bkgstop=None, t_offset=1760, npulses_apd=None):
     ''' Calibrate TIM signal (Peak-integrated signal) to the slow ion signal of SCS_XGM
         (photocurrent read by Keithley, channel 'pulseEnergy.photonFlux.value').
@@ -453,6 +460,7 @@ def calibrateTIM(data, rollingWindow=200, mcp=1, use_apd=True, intstart=None, in
             data: xarray Dataset
             rollingWindow: length of running average to calculate TIM_avg
             mcp: MCP channel
+            plot: boolean. If True, plot calibration results.
             use_apd: boolean. If False, the TIM pulse peaks are extract from raw traces using
                      getTIMapd
             intstart: trace index of integration start
@@ -484,6 +492,75 @@ def calibrateTIM(data, rollingWindow=200, mcp=1, use_apd=True, intstart=None, in
     ratio = ((data['npulses_sase3']+data['npulses_sase1']) *
              data['SCS_XGM_SLOW'] * sa3contrib) / (avgFast*data['npulses_sase3'])
     F = float(ratio[start:stop].median().values)
-    #print('calibration factor TIM: %f'%F)
-    return F
 
+    if plot:
+        fig = plt.figure(figsize=(8,5))
+        ax = plt.subplot(211)
+        ax.set_title('E[uJ] = {:2e} x TIM (MCP{})'.format(F, mcp))
+        ax.plot(data['SCS_XGM_SLOW'], label='SCS XGM slow (all SASE)', color='C0')
+        slow_avg_sase3 = data['SCS_XGM_SLOW']*(data['npulses_sase1']
+                                                    +data['npulses_sase3'])*sa3contrib/data['npulses_sase3']
+        ax.plot(slow_avg_sase3, label='SCS XGM slow (SASE3 only)', color='C1')
+        ax.plot(avgFast*F, label='Calibrated TIM rolling avg', color='C2')
+        ax.legend(loc='upper left', fontsize=8)
+        ax.set_ylabel('Energy [$\mu$J]', size=10)
+        #ax2=ax#.twinx()
+        ax.plot(filteredTIM.mean(axis=1)*F, label='Calibrated TIM train avg', alpha=0.2, color='C9')
+        #ax2.set_ylabel('Calibrated TIM (MCP{}) [uJ]'.format(mcp))
+        ax.legend(loc='best', fontsize=8, ncol=2)
+        plt.xlabel('train in run')
+        
+        ax = plt.subplot(234)
+        xgm_fast = selectSASEinXGM(data)
+        ax.scatter(filteredTIM, xgm_fast, s=5, alpha=0.1)
+        fit, cov = np.polyfit(filteredTIM.values.flatten(),xgm_fast.values.flatten(),1, cov=True)
+        y=np.poly1d(fit)
+        x=np.linspace(filteredTIM.min(), filteredTIM.max(), 10)
+        ax.plot(x, y(x), lw=2, color='r')
+        ax.set_ylabel('Raw HAMP [$\mu$J]', size=10)
+        ax.set_xlabel('TIM (MCP{}) signal'.format(mcp), size=10)
+        ax.annotate(s='y(x) = F x + A\n'+
+                    'F = %.3e\n$\Delta$F/F = %.2e\n'%(fit[0],np.abs(np.sqrt(cov[0,0])/fit[0]))+
+                    'A = %.3e'%fit[1],
+                    xy=(0.5,0.6), xycoords='axes fraction', fontsize=10, color='r')
+        print('TIM calibration factor: %e'%(F))
+        
+        ax = plt.subplot(235)
+        ax.hist(filteredTIM.values.flatten()*F, bins=50, rwidth=0.8)
+        ax.set_ylabel('number of pulses', size=10)
+        ax.set_xlabel('Pulse energy MCP{} [uJ]'.format(mcp), size=10)
+        #ax2 = ax.twiny()
+        #ax2.set_xlabel('MCP 1 APD')
+        #toRaw = lambda x: x/F
+        #ax2.set_xlim((toRaw(ax.get_xlim()[0]),toRaw(ax.get_xlim()[1])))
+        ax.set_yscale('log')
+        
+        ax = plt.subplot(236)
+        if not use_apd:
+            pulseStart = intstart
+            pulseStop = intstop
+        else:
+            pulseStart = data.attrs['run'].get_array(
+                'SCS_UTC1_ADQ/ADC/1', 'board1.apd.channel_0.pulseStart.value')[0].values
+            pulseStop = data.attrs['run'].get_array(
+                'SCS_UTC1_ADQ/ADC/1', 'board1.apd.channel_0.pulseStop.value')[0].values
+            
+        if 'MCP{}raw'.format(mcp) not in data:
+            tid, data = data.attrs['run'].train_from_index(0)
+            trace = data['SCS_UTC1_ADQ/ADC/1:network']['digitizers.channel_1_D.raw.samples']
+            print('no raw data for MCP{}. Loading trace from MCP1'.format(mcp))
+            label_trace='MCP1 Voltage [V]'
+        else:
+            trace = data['MCP{}raw'.format(mcp)][0]
+            label_trace='MCP{} Voltage [V]'.format(mcp)
+        ax.plot(trace[:pulseStop+25], 'o-', ms=2, label='trace')
+        ax.axvspan(pulseStart, pulseStop, color='C2', alpha=0.2, label='APD region')
+        ax.axvline(pulseStart, color='gray', ls='--')
+        ax.axvline(pulseStop, color='gray', ls='--')
+        ax.set_xlim(pulseStart - 25, pulseStop + 25)
+        ax.set_ylabel(label_trace, size=10)
+        ax.set_xlabel('sample #', size=10)
+        ax.legend(fontsize=8)
+        plt.tight_layout()
+
+    return F
-- 
GitLab