diff --git a/IR_config_constants.py b/IR_config_constants.py
index 701d7a9b467d1d48da02cea42bfa8fce87ed97d7..0341ddcae4c9ff882db436e6e401d68727cac374 100644
--- a/IR_config_constants.py
+++ b/IR_config_constants.py
@@ -11,6 +11,7 @@ IRCamColdframes_fittingpath=calibpath+"IRCamColdframes_fitting\\"
 IRCamRefImagespath = calibpath+'IRCamReferenceImages\\'
 IRCAMBadPixels_path = calibpath + 'IRCAMBadPixels\\'
 heatflux_requestlist_path="\\\\x-drive\\Diagnostic-logbooks\\QRT-DivertorThermography\\ArchiveDB_heatflux_pipeline\\"
+parameter_file_path = ".\\data"
 try:
 #    import sys
     path=str(repr(__file__)).split("IR_config_constants")[0].split("'")[1]+"upload_config"
diff --git a/IR_image_tools.py b/IR_image_tools.py
index 22e3fe729c279d9c67bbab2a6a0c528fa57afa39..c811c303981567050cd9e725e6b83652c1465215 100644
--- a/IR_image_tools.py
+++ b/IR_image_tools.py
@@ -14,12 +14,16 @@ Tools for:
 """
 import numpy as np
 import matplotlib.pyplot as plt
-from IR_config_constants import portcamdict,IRCamRefImagespath,IRCAMBadPixels_path
+import matplotlib.patches as patches
+from IR_config_constants import portcamdict,IRCamRefImagespath,IRCAMBadPixels_path,parameter_file_path
 import h5py
-from os.path import join, basename
+import os
 import glob
 import datetime
 
+# set working directory to local directory of script
+os.chdir(os.path.dirname(__file__))
+
 def get_OP_by_time(time_ns=None, shot_no=None, program_str=None):
     '''Derives operation phase (OP) of W7-X based on either:
        a nanosacond time stamp, a MDSplus style shot no. or a program ID.
@@ -483,19 +487,19 @@ def load_ref_images(port, exposuretime, verbose=0):
     '''
     cameraname = portcamdict['OP1.2a'][port]
     foldername = cameraname.split('_')[0] + '_' + cameraname.split('_')[2]
-    scanpath = join(IRCamRefImagespath, foldername)
+    scanpath = os.path.join(IRCamRefImagespath, foldername)
     coldref, hotref = [], []
     for filename in glob.iglob(scanpath + '\*' + str(int(exposuretime)) + 'us.h5', recursive=True):
         if 'hot' in filename:
             if verbose>0:
                 print('load_ref_images: read from ',filename)
             with h5py.File(filename, 'r') as h5in:
-                hotref = h5in[basename(filename)].value
+                hotref = h5in[os.path.basename(filename)].value
         elif 'cold' in filename:
             if verbose>0:
                 print('load_ref_images: read from ',filename)
             with h5py.File(filename, 'r') as h5in:
-                coldref = h5in[basename(filename)].value
+                coldref = h5in[os.path.basename(filename)].value
     return coldref, hotref
 
 def reconstruct_coldframe (exposuretime, sT, a, bnew, coldref):
@@ -516,4 +520,406 @@ def check_dublicates_2(array):
         if x not in seen:
             uniq.append(x)
             seen.add(x)
-    return uniq,seen
\ No newline at end of file
+    return uniq,seen
+
+#%% functions regarding wetted area calculation
+
+def read_finger_info(file_name=None, OP='OP1.2b', verbose=0):
+    '''Read divertor finger information from file. The referenced fingers are those
+       defined in the IR profile mapping, i.e. the target modlues 5 and 6 are
+       divided in inner and outer fingers (see 'finger_part' in result dictionary).
+    
+       INPUT
+       -----
+           file_name: str, optional
+               file name of csv fiel with finger information
+               (OPTIONAL: default is None, i.e. decide by OP)
+           OP: str, optional
+               label of operation phase of interest, e.g. 'OP1.2b'
+               (OPTIONAL: default is 'OP1.2b', i.e. load TDU file)
+           verbose: integer, optional
+               feedback level (details of print messages)
+               (OPTIONAL: if not provided, only ERROR output)
+       RESULT
+       ------
+           finger_dic: dictionary
+               dictionary with keys 'ID', 'target', 'target_element','n_profiles', 'width', 'finger_part' (see NOTES)
+       NOTES
+       -----
+           contents of result dictionary:
+               * 'ID' numpy array of integers of continuous finger number
+               * 'target' list of strings of target identifier ('h_l' horizontal low-iota, 'h_m' horizontal middle part, 'h_h' horizontal high-iota, 'v' vertical)
+               * 'target_element' numpy array of integers of target module number (1..9 on horizontal target, 1..3 on vertical target)
+               * 'n_profiles' numpy array of integers of number of profiles defined on this finger
+               * 'width' numpy array of floats of centre width of finger in meters
+               * 'finger_part' numpy array of integers indicating with 0 this is a full finger and with 1 this is the second part of the previous finger
+    '''
+    if file_name is None:
+        # assume OP is given
+        if OP.startswith('OP1'):
+            file_name='finger_info_TDU.csv'
+        elif OP.startswith('OP2'):
+            file_name='finger_info_HHF.csv'
+    full_path = os.path.join(parameter_file_path, file_name)
+    print(full_path)
+    if verbose>0:
+        print('read_finger_info: reading from file {0} in {1}'.format(file_name, parameter_file_path))
+    if not os.path.isfile(full_path):
+        raise Exception('read_finger_info: ERROR! file not found')
+    
+    finger_dic = {'ID': [],
+                  'target': [],
+                  'target_element':[],
+                  'n_profiles':[],
+                  'width':[],
+                  'finger_part':[]}
+    
+    data = np.genfromtxt(full_path, delimiter=';', dtype=(int, "|S3", int, int, float, int))
+    for i in range(len(data)):
+        finger_dic['ID'].append( data[i][0] )
+        finger_dic['target'].append( data[i][1].decode('UTF-8') )
+        finger_dic['target_element'].append( data[i][2] )
+        finger_dic['n_profiles'].append( data[i][3] )
+        finger_dic['width'].append( data[i][4] )
+        finger_dic['finger_part'].append( data[i][5] )
+    
+    finger_dic['ID'] = np.array(finger_dic['ID'])
+    finger_dic['target_element'] = np.array(finger_dic['target_element'])
+    finger_dic['n_profiles'] = np.array(finger_dic['n_profiles'])
+    finger_dic['width'] = np.array(finger_dic['width'])
+    finger_dic['finger_part'] = np.array(finger_dic['finger_part'])
+    
+    return finger_dic
+
+
+def derive_wetted_area_per_module(heat_flux, mapping, mode='average', q_max=None,
+                                  profile_average_range=3, noise_threshold=2E5,
+                                  ports_loaded=None, plot_it=False, verbose=0):
+    ''' Derive wetted area of heat flux array by integrating the total power load
+        and dividing with a peak heat flux value.
+        The peak heat flux value is either:
+            1) the maximum within each divertor finger (mode='finger')
+            2) the maximum of a whole divertor module (mode='module')
+            3) the maximum of the mean divertor averaged toroidally (mode='average').
+        Mode average is default. In case the input heat flux has only 2 dimensions 
+        (from one divertor), mode 'average' and 'module' result in the same.
+        Returned are the wetted area(s) and the corresponding q_max value(s).
+    
+       INPUT
+       -----
+           heat_flux: numpy array
+               array of heat fluxes from THEODOR on the profiles defined 
+               in the IR mapping; can be 2D (one divertor), or 3D (multiple divertor modules)
+           mapping: dictionary
+               IR profile mapping information as returned by 
+               downloadversionIRdara.download_heatflux_mapping_reference();
+               minimum necessary keys are 'finger_ID' and 's'
+           mode: str, optional
+               label to identify the normalization mode, either 
+               'module' (normalize by peak heat flux per torus module),
+               'average' (normalize by peak heat flux in the toroidally mean heat flux pattern),
+               'finger' (normalize by peak heat flux per finger in each torus module)
+               (OPTIONAL: default is 'average')
+           q_max: float or numpy array, optional
+               either single peak heat flux value or a peak heat flux for each 
+               divertor module or each finger (depends on mode)
+               (OPTIONAL: default is None, i.e. derived based on mode)
+           profile_average_range: int, optional
+               number of central profiles on each finger to average the 
+               integral heat flux on (this avoids hot leading edges and shadowed edges)
+               (OPTIONAL: default is 3 profiles)
+           noise_threshold: float, optional
+               minimum heat flux level to crop heat_flux to, if heat flux has negative values
+               (OPTIONAL: default is 200kW/m²)
+           ports_loaded: list or str or int, optinal
+               label of divertor modules provided in heat_flux array for plots; 
+               int of port number for single divertor data and list of 
+               port numbers for heat flux from multiple divertor modules; #
+               gets renamed if a mean heat flux pattern is used (mode 'average')
+               (OPTIONAL: default is None, i.e. label will be 'A_w')
+           plot_it: bool, optional
+               switch of whether to plot intermediate results or not
+               (OPTIONAL: deafult is NOT to plot)
+           verbose: integer, optional
+               feedback level (details of print messages)
+               (OPTIONAL: if not provided, only ERROR output)
+       RESULT
+       ------
+           total_wetted_area: float or numpy array
+               wetted area in a shape that depends on the mode (see NOTES)
+           q_max: float or numpy array
+               peak heat flux used for normalizatin in a shape that depends on the mode (see NOTES)
+       NOTES
+       -----
+           The shape of the results varies depending on the dimension of the input
+               * 2D: singel divertor modules heat flux
+               * 3D: heat flux from multiple divertor modules
+           and the mode to derive q_max ('module', 'average', 'finger'):
+               * '2D' + 'module' or 'average' --> one value for total_wetted_area and q_max
+               * '3D' + 'average' --> one value for total_wetted_area and q_max
+               * '3D' + 'module' --> 1D numpy arays with a value for each torus module (first dimension of heat_flux)
+               * '2D' + 'finger' --> 1D numpy arays with a value for each divertor finger
+               * '3D' + 'finger' --> 2D numpy arays with a value for each torus module and each divertor finger
+    '''
+    
+    # prepare mapping and finger information
+    finger_dic = read_finger_info(verbose=verbose-1)
+    finger_ID = finger_dic['ID']
+    profile_no = mapping['Finger_ID'][0]
+    
+    # find profile IDs of central profiles on each finger
+    central_profiles_on_finger = []
+    is_central_profile = []
+    for i_finger in range(len(finger_ID)):
+        n_profiles = finger_dic['n_profiles'][i_finger]
+        i_profile_start = n_profiles//2 - profile_average_range//2 -1
+        central_profiles = i_finger*100 + np.arange(i_profile_start, i_profile_start+profile_average_range)
+        central_profiles_on_finger.append(central_profiles)
+        is_central_profile.append( np.logical_or.reduce([profile_no == centre_profile for centre_profile in central_profiles]) )
+    central_profiles_on_finger = np.array(central_profiles_on_finger)
+    
+    if np.nanmin(heat_flux) < 0:
+        heat_flux[heat_flux<noise_threshold] = 0
+        if verbose>0:
+            print('derive_wetted_area_per_module: set heat_flux < {0:.1f}kW/m² to 0'.format(noise_threshold/1E3))
+            
+    heat_flux_dim = len(np.shape(heat_flux))
+    # reduce dimension of heat_flux if in 'average' mode
+    if heat_flux_dim == 2 and mode == 'average':
+        mode = 'module'
+    elif heat_flux_dim == 3 and mode == 'average':
+        heat_flux = np.nanmean(heat_flux, axis=0)
+        heat_flux_dim = 2
+        ports_loaded = 'mean heat flux'
+        if verbose>0:
+            print('derive_wetted_area_per_module: averaged 3D heat flux array over first dimension')
+    
+    if heat_flux_dim==3:
+        # assume dimensions: toroidal index (camera ports), row, column
+        n_ports, n_rows, n_cols = np.shape(heat_flux)
+        if verbose>0:
+            print('derive_wetted_area_per_module: deriving wetted area on {0} divertor modules in {1} mode...'.format(n_ports, mode))
+        # derive q_max for normalization of integral
+        if q_max is None:
+            # derive q_max on every finger
+            q_max_on_finger = []
+            for i_finger in range(len(finger_ID)):
+                q_max_on_finger.append([np.nanmax(h[is_central_profile[i_finger]]) for h in heat_flux])
+            q_max_on_finger = np.array(q_max_on_finger)
+            q_max_on_finger[q_max_on_finger==0] = 1
+            if mode == 'module':
+                # one value per torus half module
+                q_max = np.nanmax(q_max_on_finger, axis=0)
+            elif mode == 'finger':
+                # one value per finger in each torus half module
+                q_max = q_max_on_finger
+            q_max[q_max==0] = 1
+        # integrate over profiles
+        finger_wetted_area = np.zeros([len(finger_ID), n_ports])
+        for i_finger in range(len(finger_ID)):
+            # initialize temporary line integral for each module
+            central_line_integral = np.zeros(n_ports)
+            # integrate over each central profile and average    
+            for i_profile in central_profiles_on_finger[i_finger]:
+                ij_profile = np.where(profile_no==i_profile)
+                s = mapping['s'][ij_profile]
+                h = heat_flux[:,ij_profile[0],ij_profile[1]]
+                central_line_integral += np.nan_to_num( np.trapz(h, x=s, axis=1) )
+            # complete averaging process
+            central_line_integral = central_line_integral / profile_average_range
+            # normalize by q_max and multiply with width of finger
+            if mode == 'module':
+                finger_wetted_area[i_finger,:] = central_line_integral / q_max * finger_dic['width'][i_finger]
+            elif mode == 'finger':
+                finger_wetted_area[i_finger,:] = central_line_integral / q_max[i_finger] * finger_dic['width'][i_finger]
+            
+        # get example profiles and wetted area widths at local maxima
+        i_finger_max = np.argmax(q_max_on_finger, axis=0)
+        h_max = []
+        s_max = []
+        width_max = []
+        height_max = []
+        for i in range(len(i_finger_max)):
+            central_profiles = central_profiles_on_finger[i_finger_max[i]]
+            h_profiles = [ heat_flux[i][profile_no == cp] for cp in central_profiles ] 
+            i_max = np.argmax([np.sum(h) for h in h_profiles])
+#            i_max = np.argsort([np.sum(h) for h in h_profiles])[profile_average_range//2]
+            h_max.append( h_profiles[ i_max ] )
+            s_max.append( mapping['s'][profile_no == central_profiles[i_max]] )
+            if mode == 'module':
+                width_max.append(np.nan_to_num(np.trapz(h_max[-1], x=s_max[-1]) / q_max[i]))
+                height_max.append(q_max[i])
+            elif mode == 'finger':
+                width_max.append(np.nan_to_num(np.trapz(h_max[-1], x=s_max[-1]) / q_max[i_finger_max[i],i]))
+                height_max.append(q_max[i_finger_max[i],i])
+        i_samples = [np.argmin(width_max), np.argsort(width_max)[len(width_max)//2], np.argmax(width_max)]
+        i_centre = np.argsort(width_max)[len(width_max)//2]
+        s_max = [s_max[np.argmin(width_max)], s_max[i_centre], s_max[np.argmax(width_max)]]
+        h_max = [h_max[np.argmin(width_max)], h_max[i_centre], h_max[np.argmax(width_max)]]
+        height_max = [height_max[np.argmin(width_max)], height_max[i_centre], height_max[np.argmax(width_max)]]
+        width_max = [width_max[np.argmin(width_max)], width_max[i_centre], width_max[np.argmax(width_max)]]
+        
+    elif heat_flux_dim==2:
+        # assume dimensions: row, column
+        if verbose>0:
+            print('derive_wetted_area_per_module: deriving wetted area on single divertor module in {0} mode...'.format(mode))
+        # derive q_max for normalization of integral
+        if q_max is None:
+            if mode == 'average' or mode == 'module':
+                # one value
+                q_max = np.nanmax(heat_flux[np.logical_or.reduce(is_central_profile)])
+            elif mode == 'finger':
+                # one value per finger
+                q_max = []
+                for i_finger in range(len(finger_ID)):
+                    q_max.append( np.nanmax(heat_flux[is_central_profile[i_finger]]) )
+                q_max = np.array(q_max)
+                q_max[q_max==0] = 1
+        # integrate over profiles
+        finger_wetted_area = np.zeros([len(finger_ID)])
+        for i_finger in range(len(finger_ID)):
+            # integrate over each central profile and average
+            central_line_integral = 0
+            for i_profile in central_profiles_on_finger[i_finger]:
+                ij_profile = np.where(profile_no==i_profile)
+                s = mapping['s'][ij_profile]            
+                h = heat_flux[ij_profile[0],ij_profile[1]]
+                central_line_integral += np.nan_to_num( np.trapz(h, x=s, axis=0) )
+            central_line_integral = central_line_integral / profile_average_range
+            if mode == 'average' or mode == 'module':
+                finger_wetted_area[i_finger] = central_line_integral / q_max * finger_dic['width'][i_finger]
+            elif mode == 'finger':
+                finger_wetted_area[i_finger] = central_line_integral / q_max[i_finger] * finger_dic['width'][i_finger]
+        
+        # get example profiles and wetted area widths at local maxima
+        i_samples = [np.nanargmin(finger_wetted_area), np.argsort(finger_wetted_area)[len(finger_wetted_area)//2], np.nanargmax(finger_wetted_area)]
+        h_max = []
+        s_max = []
+        width_max = []
+        height_max = []
+        for i in range(len(i_samples)):
+            central_profiles = central_profiles_on_finger[i_samples[i]]
+            h_profiles = [ heat_flux[profile_no == cp] for cp in central_profiles ] 
+            i_max = np.argmax([np.sum(h) for h in h_profiles])
+            h_max.append( h_profiles[ i_max ] )
+            s_max.append( mapping['s'][profile_no == central_profiles[i_max]] )
+            if mode == 'module' or mode == 'average':
+                width_max.append(np.nan_to_num(np.trapz(h_max[-1], x=s_max[-1]) / q_max))
+                height_max.append(q_max)
+            elif mode == 'finger':
+                width_max.append(np.nan_to_num(np.trapz(h_max[-1], x=s_max[-1]) / q_max[i_samples[i]]))
+                height_max.append(q_max[i_samples[i]])
+        
+    
+    # merge half-fingers of TM5 and TM6
+    if np.any(finger_dic['finger_part']):
+        if verbose>0:
+            print('derive_wetted_area_per_module: merge wetted area on half fingers of TM05 and TM06')
+        new_finger_ID = np.copy(finger_ID)
+        # scan backwards over fingers, merge and delete second finger halfs
+        for i_finger in finger_ID[:0:-1]:
+            if finger_dic['finger_part'][i_finger]:
+                new_finger_ID = np.delete(new_finger_ID, i_finger)
+                if heat_flux_dim==3 and mode != 'average':
+                    finger_wetted_area[i_finger-1,:] = finger_wetted_area[i_finger-1,:] + finger_wetted_area[i_finger,:] 
+                else:
+                    finger_wetted_area[i_finger-1] = finger_wetted_area[i_finger-1] + finger_wetted_area[i_finger] 
+                finger_wetted_area = np.delete(finger_wetted_area, i_finger, axis=0)
+                if mode == 'finger' and heat_flux_dim==3:
+                    q_max[i_finger-1,:] = np.maximum(q_max[i_finger-1,:], q_max[i_finger,:])
+                    q_max = np.delete(q_max, i_finger, axis=0)
+                elif mode == 'finger' and heat_flux_dim==2:
+                    q_max[i_finger-1] = np.maximum(q_max[i_finger-1], q_max[i_finger])
+                    q_max = np.delete(q_max, i_finger, axis=0)
+    
+    # sum up
+    # 'average' mode: sum all fingers over all torus modules --> wetted area of all divertors
+    #                divide by n_ports --> get average wetted area per divertor
+    # 'module' mode:  in each torus module sum over wetted area on all fingers 
+    #                --> individual wetted areas per divertor
+    # 'finger' mode: do not sum, since each finger was normalized with a differen q_max
+    #                --> individual wetted areas per finger
+    # if only one divertors heat flux is given, proceed as in local mode
+    if mode == 'finger':
+        total_wetted_area = finger_wetted_area
+    else:
+        total_wetted_area = np.sum(finger_wetted_area, axis=0)
+
+    # if requested, make some visalization
+    if plot_it:
+        if ports_loaded is None:
+            if heat_flux_dim==3:
+                ports_label = ['port index {0}'.format(i) for i in range(n_ports)]
+            elif heat_flux_dim==2:
+                ports_label = ['A_w']
+        elif isinstance(ports_loaded, list) or isinstance(ports_loaded, np.ndarray):
+            ports_label = ['module {0} {1}'.format(int(port/10), ['L','U'][port%10]) for port in ports_loaded]
+        elif isinstance(ports_loaded, int) or isinstance(ports_loaded, np.int_):
+            ports_label = ['module {0} {1}'.format(int(int(ports_loaded)/10), ['L','U'][int(ports_loaded)%10])]
+        elif isinstance(ports_loaded, str):
+            ports_label = [ports_loaded]
+            
+        # wetted areas vs fingers
+        plt.figure()
+        if heat_flux_dim==3 and mode != 'average':
+            for i_port in range(n_ports):
+                plt.plot(new_finger_ID, finger_wetted_area[:,i_port]*1E4, label=ports_label[i_port])
+        elif heat_flux_dim==3 and mode == 'average':
+            plt.plot(new_finger_ID, finger_wetted_area*1E4, label='mean heat flux')
+        else:
+            plt.plot(new_finger_ID, finger_wetted_area*1E4, label=ports_label[0])
+        plt.title('normalized with q_max of {0}'.format(mode))
+        plt.xlabel('finger no.')
+        plt.ylabel('wetted area [cm²]')
+        plt.legend()
+        plt.show()
+        
+        # wetted areas vs torus modules
+        if heat_flux_dim==3:
+            if mode == 'module':
+                i_ports = np.arange(n_ports)
+                plt.figure()
+                plt.plot(i_ports, total_wetted_area*1E2)
+                plt.xticks(i_ports, [port[-3:] for port in ports_label], rotation='vertical')
+                plt.xlabel('module')
+                plt.ylabel('wetted area [dm²]')
+                plt.tight_layout()
+                plt.show()
+        
+        # central finger profiles and the rectangle with the same integral
+        # (the width represented to contribution to the wetted area)
+        plt.figure()
+        if heat_flux_dim==3:
+            label_str = [ports_label[i] for i in i_samples]
+            if mode=='module':
+                plt.title('wetted area examples from fingers with max Int[q]\nintegrated on their respective divertor and normalized to a local q_max')
+            elif mode == 'average':
+                plt.title('wetted area examples from fingers with max Int[q]\nintegrated on the mean heat flux pattern and normalized to a global q_max')
+            elif mode == 'finger':
+                plt.title('wetted area examples from fingers with max Int[q]\nintegrated on their respective divertor and normalized to a finger q_max')
+        elif heat_flux_dim==2:
+            label_str = ['min(A_w)', 'median(A_w)', 'max(A_w)']
+            if mode == 'finger':
+                plt.title('wetted area examples from fingers\nintegrated on their respective divertor and normalized to a finger q_max')
+            elif mode  == 'module':
+                plt.title('wetted area examples from fingers\nintegrated on their respective divertor and normalized to a local q_max')
+            elif mode  == 'average':
+                plt.title('wetted area examples from fingers\nintegrated on a mean heat flux pattern and normalized to a its q_max')
+        color_str = ['b', 'g', 'r']
+        rect = []
+        for i in range(len(i_samples)):
+            plt.plot(s_max[i], h_max[i]/1E3, label=label_str[i], 
+                     color=color_str[i])
+            width = width_max[i]
+            height = height_max[i]/1E3
+            start_point = (s_max[i][np.argmax(h_max[i])]-width/2,0)
+            rect.append(patches.Rectangle(start_point,width,height,linewidth=1,
+                                          edgecolor=color_str[i],
+                                          facecolor='none'))
+            plt.gca().add_patch(rect[-1])
+        plt.xlabel('s [m]')
+        plt.ylabel('q [kW/m²]')
+        plt.legend()
+        plt.show()
+
+    return total_wetted_area, q_max
\ No newline at end of file
diff --git a/data/finger_info_HHF.csv b/data/finger_info_HHF.csv
new file mode 100644
index 0000000000000000000000000000000000000000..7dcd00384be71a957ac9470c994e5c70a02fa3e7
--- /dev/null
+++ b/data/finger_info_HHF.csv
@@ -0,0 +1,140 @@
+# Finger widths of TDU;;;;;
+# continuous ID of divertor fingers;ID of divertor section;target module number within horizontal or vertical target;number of profiles in standard mapping;width used for integration of averaged central profile;finger_part indicates if finger is the second part of the previous finger (in h_m)
+# finger_ID;target;target element;n_profiles;width [m];finger_part
+0;h_l;1;13;0.0553;0
+1;h_l;1;14;0.0538;0
+2;h_l;1;14;0.0538;0
+3;h_l;1;14;0.0538;0
+4;h_l;1;14;0.0538;0
+5;h_l;1;14;0.0538;0
+6;h_l;1;14;0.0537;0
+7;h_l;2;14;0.0537;0
+8;h_l;2;14;0.0538;0
+9;h_l;2;14;0.0538;0
+10;h_l;2;15;0.0582;0
+11;h_l;2;15;0.0582;0
+12;h_l;2;14;0.0538;0
+13;h_l;2;14;0.0582;0
+14;h_l;3;14;0.0569;0
+15;h_l;3;13;0.0523;0
+16;h_l;3;13;0.0523;0
+17;h_l;3;13;0.0523;0
+18;h_l;3;13;0.0523;0
+19;h_l;3;13;0.0523;0
+20;h_l;3;13;0.0523;0
+21;h_l;3;13;0.0523;0
+22;h_l;4;13;0.0523;0
+23;h_l;4;13;0.0523;0
+24;h_l;4;13;0.0523;0
+25;h_l;4;13;0.0523;0
+26;h_l;4;13;0.0523;0
+27;h_l;4;13;0.0523;0
+28;h_l;4;13;0.0523;0
+29;h_l;4;13;0.0523;0
+30;h_m;5;14;0.0543;0
+31;h_m;5;15;0.0543;1
+32;h_m;5;14;0.0543;0
+33;h_m;5;15;0.0543;1
+34;h_m;5;14;0.0542;0
+35;h_m;5;15;0.0542;1
+36;h_m;5;14;0.0542;0
+37;h_m;5;15;0.0542;1
+38;h_m;5;14;0.0541;0
+39;h_m;5;15;0.0541;1
+40;h_m;5;14;0.0541;0
+41;h_m;5;15;0.0541;1
+42;h_m;5;14;0.0541;0
+43;h_m;5;15;0.0541;1
+44;h_m;5;14;0.0541;0
+45;h_m;5;15;0.0541;1
+46;h_m;5;14;0.0541;0
+47;h_m;5;15;0.0541;1
+48;h_m;5;14;0.0541;0
+49;h_m;5;15;0.0541;1
+50;h_m;5;14;0.0541;0
+51;h_m;5;15;0.0541;1
+52;h_m;5;14;0.0541;0
+53;h_m;5;15;0.0541;1
+54;h_m;6;14;0.0539;0
+55;h_m;6;15;0.0539;1
+56;h_m;6;14;0.0539;0
+57;h_m;6;15;0.0539;1
+58;h_m;6;14;0.0539;0
+59;h_m;6;15;0.0539;1
+60;h_m;6;14;0.0539;0
+61;h_m;6;15;0.0539;1
+62;h_m;6;14;0.0539;0
+63;h_m;6;15;0.0539;1
+64;h_m;6;14;0.0541;0
+65;h_m;6;15;0.0541;1
+66;h_m;6;14;0.0541;0
+67;h_m;6;15;0.0541;1
+68;h_m;6;14;0.0541;0
+69;h_m;6;15;0.0541;1
+70;h_m;6;14;0.0541;0
+71;h_m;6;15;0.0541;1
+72;h_m;6;14;0.0541;0
+73;h_m;6;15;0.0541;1
+74;h_m;6;14;0.0541;0
+75;h_m;6;15;0.0541;1
+76;h_m;6;14;0.0541;0
+77;h_m;6;15;0.0541;1
+78;h_h;7;15;0.0552;0
+79;h_h;7;14;0.0522;0
+80;h_h;7;14;0.0522;0
+81;h_h;7;14;0.0522;0
+82;h_h;7;14;0.0522;0
+83;h_h;7;15;0.0567;0
+84;h_h;8;16;0.0602;0
+85;h_h;8;15;0.0557;0
+86;h_h;8;15;0.0557;0
+87;h_h;8;15;0.0557;0
+88;h_h;8;15;0.0557;0
+89;h_h;8;15;0.0557;0
+90;h_h;8;15;0.0557;0
+91;h_h;8;15;0.0557;0
+92;h_h;8;15;0.0557;0
+93;h_h;8;15;0.0557;0
+94;h_h;8;15;0.0557;0
+95;h_h;8;15;0.0557;0
+96;h_h;9;15;0.0557;0
+97;h_h;9;15;0.0557;0
+98;h_h;9;15;0.0557;0
+99;h_h;9;15;0.0557;0
+100;h_h;9;15;0.0557;0
+101;h_h;9;15;0.0557;0
+102;h_h;9;15;0.0557;0
+103;h_h;9;15;0.0557;0
+104;h_h;9;15;0.0557;0
+105;h_h;9;15;0.0557;0
+106;h_h;9;15;0.0557;0
+107;h_h;9;15;0.0557;0
+108;v;1;15;0.0547;0
+109;v;1;15;0.0548;0
+110;v;1;15;0.0548;0
+111;v;1;15;0.0549;0
+112;v;1;15;0.0548;0
+113;v;1;15;0.0548;0
+114;v;1;15;0.0548;0
+115;v;1;15;0.0548;0
+116;v;1;15;0.0548;0
+117;v;1;15;0.0547;0
+118;v;2;15;0.0547;0
+119;v;2;15;0.0547;0
+120;v;2;15;0.0547;0
+121;v;2;15;0.0547;0
+122;v;2;15;0.0547;0
+123;v;2;15;0.0547;0
+124;v;2;15;0.0547;0
+125;v;2;15;0.0547;0
+126;v;2;15;0.0547;0
+127;v;2;15;0.0547;0
+128;v;3;15;0.0547;0
+129;v;3;15;0.0548;0
+130;v;3;15;0.0547;0
+131;v;3;15;0.0548;0
+132;v;3;15;0.0547;0
+133;v;3;15;0.0549;0
+134;v;3;15;0.0547;0
+135;v;3;15;0.0547;0
+136;v;3;15;0.0547;0
diff --git a/data/finger_info_TDU.csv b/data/finger_info_TDU.csv
new file mode 100644
index 0000000000000000000000000000000000000000..e1629562f2a6e611f804d24c3fa8639ddb7a17f1
--- /dev/null
+++ b/data/finger_info_TDU.csv
@@ -0,0 +1,140 @@
+# Finger widths of TDU;;;;;
+# continuous ID of divertor fingers;ID of divertor section;target module number within horizontal or vertical target;number of profiles in standard mapping;width used for integration of averaged central profile;finger_part indicates if finger is the second part of the previous finger (in h_m)
+# finger_ID;target;target element;n_profiles;width [m];finger_part
+0;h_l;1;13;0.051072;0
+1;h_l;1;14;0.053565;0
+2;h_l;1;14;0.053565;0
+3;h_l;1;14;0.053565;0
+4;h_l;1;14;0.053565;0
+5;h_l;1;14;0.053565;0
+6;h_l;1;14;0.053565;0
+7;h_l;2;14;0.053565;0
+8;h_l;2;14;0.053565;0
+9;h_l;2;14;0.053565;0
+10;h_l;2;15;0.058047;0
+11;h_l;2;15;0.05794;0
+12;h_l;2;14;0.053565;0
+13;h_l;2;14;0.055486;0
+14;h_l;3;14;0.054198;0
+15;h_l;3;13;0.052192;0
+16;h_l;3;13;0.052192;0
+17;h_l;3;13;0.052192;0
+18;h_l;3;13;0.052192;0
+19;h_l;3;13;0.052192;0
+20;h_l;3;13;0.052192;0
+21;h_l;3;13;0.052192;0
+22;h_l;4;13;0.052192;0
+23;h_l;4;13;0.052192;0
+24;h_l;4;13;0.052192;0
+25;h_l;4;13;0.052192;0
+26;h_l;4;13;0.052192;0
+27;h_l;4;13;0.052192;0
+28;h_l;4;13;0.052192;0
+29;h_l;4;13;0.052192;0
+30;h_m;5;14;0.054328;0
+31;h_m;5;15;0.054328;1
+32;h_m;5;14;0.054328;0
+33;h_m;5;15;0.054328;1
+34;h_m;5;14;0.054152;0
+35;h_m;5;15;0.054152;1
+36;h_m;5;14;0.054152;0
+37;h_m;5;15;0.054152;1
+38;h_m;5;14;0.05408;0
+39;h_m;5;15;0.05408;1
+40;h_m;5;14;0.054134;0
+41;h_m;5;15;0.054134;1
+42;h_m;5;14;0.054134;0
+43;h_m;5;15;0.054134;1
+44;h_m;5;14;0.054134;0
+45;h_m;5;15;0.054134;1
+46;h_m;5;14;0.054134;0
+47;h_m;5;15;0.054134;1
+48;h_m;5;14;0.054134;0
+49;h_m;5;15;0.054134;1
+50;h_m;5;14;0.054134;0
+51;h_m;5;15;0.054134;1
+52;h_m;5;14;0.054134;0
+53;h_m;5;15;0.054134;1
+54;h_m;6;14;0.053823;0
+55;h_m;6;15;0.053823;1
+56;h_m;6;14;0.053823;0
+57;h_m;6;15;0.053823;1
+58;h_m;6;14;0.053823;0
+59;h_m;6;15;0.053823;1
+60;h_m;6;14;0.053823;0
+61;h_m;6;15;0.053823;1
+62;h_m;6;14;0.053823;0
+63;h_m;6;15;0.053823;1
+64;h_m;6;14;0.05406;0
+65;h_m;6;15;0.05406;1
+66;h_m;6;14;0.05406;0
+67;h_m;6;15;0.05406;1
+68;h_m;6;14;0.05406;0
+69;h_m;6;15;0.05406;1
+70;h_m;6;14;0.05406;0
+71;h_m;6;15;0.05406;1
+72;h_m;6;14;0.05406;0
+73;h_m;6;15;0.05406;1
+74;h_m;6;14;0.05406;0
+75;h_m;6;15;0.05406;1
+76;h_m;6;14;0.05406;0
+77;h_m;6;15;0.05406;1
+78;h_h;7;15;0.056351;0
+79;h_h;7;14;0.052463;0
+80;h_h;7;14;0.052463;0
+81;h_h;7;14;0.052463;0
+82;h_h;7;14;0.052463;0
+83;h_h;7;15;0.054963;0
+84;h_h;8;16;0.057662;0
+85;h_h;8;15;0.055162;0
+86;h_h;8;15;0.055162;0
+87;h_h;8;15;0.055162;0
+88;h_h;8;15;0.055162;0
+89;h_h;8;15;0.055162;0
+90;h_h;8;15;0.055162;0
+91;h_h;8;15;0.055162;0
+92;h_h;8;15;0.055162;0
+93;h_h;8;15;0.055162;0
+94;h_h;8;15;0.055162;0
+95;h_h;8;15;0.055162;0
+96;h_h;9;15;0.055162;0
+97;h_h;9;15;0.055162;0
+98;h_h;9;15;0.055162;0
+99;h_h;9;15;0.055162;0
+100;h_h;9;15;0.055162;0
+101;h_h;9;15;0.055162;0
+102;h_h;9;15;0.055162;0
+103;h_h;9;15;0.055162;0
+104;h_h;9;15;0.055162;0
+105;h_h;9;15;0.055162;0
+106;h_h;9;15;0.055162;0
+107;h_h;9;15;0.055162;0
+108;v;1;15;0.054426;0
+109;v;1;15;0.054426;0
+110;v;1;15;0.054426;0
+111;v;1;15;0.054426;0
+112;v;1;15;0.054426;0
+113;v;1;15;0.054426;0
+114;v;1;15;0.054426;0
+115;v;1;15;0.054426;0
+116;v;1;15;0.054426;0
+117;v;1;15;0.054426;0
+118;v;2;15;0.054426;0
+119;v;2;15;0.054426;0
+120;v;2;15;0.054426;0
+121;v;2;15;0.054426;0
+122;v;2;15;0.054426;0
+123;v;2;15;0.054426;0
+124;v;2;15;0.054426;0
+125;v;2;15;0.054426;0
+126;v;2;15;0.054426;0
+127;v;2;15;0.054426;0
+128;v;3;15;0.054426;0
+129;v;3;15;0.054426;0
+130;v;3;15;0.054426;0
+131;v;3;15;0.054426;0
+132;v;3;15;0.054426;0
+133;v;3;15;0.054426;0
+134;v;3;15;0.054426;0
+135;v;3;15;0.054426;0
+136;v;3;15;0.054426;0
diff --git a/downloadversionIRdata.py b/downloadversionIRdata.py
index c284487e8d05fc0c3e68135763f0a25ea8a976ea..e7718dffec25744285c27cebf55a9d2c4e0bac72 100644
--- a/downloadversionIRdata.py
+++ b/downloadversionIRdata.py
@@ -430,7 +430,8 @@ def download_hot_cold_reference_by_times(port,exposure,starttime=150390720000000
     if version==0:
         version=get_latest_version(portpathdict[OP]["AEF"+str(port)]+"raw_DATASTREAM",t_from=starttime)
     try:
-        res = urllib.request.urlopen(larchivepath+"PARLOG/V"+str(version)+"/_signal.json?from="+str(starttime)+"&upto="+str(int(starttime+1e9)))
+        path_string = larchivepath+"PARLOG/V"+str(version)+"/_signal.json?from="+str(starttime)+"&upto="+str(int(starttime+1e9))
+        res = urllib.request.urlopen(path_string)
         signal_list = json.loads(res.read().decode('utf-8'))
         res.close()
         goon=True
@@ -550,6 +551,97 @@ def get_NUCed_background_by_times(port,t0,t1,t_exp,cfilter,gain,offset,version=0
         plt.title("background image nuced")
     return exist,btime[0],background
 
+
+def get_NUCed_coldframe_by_program(port, program, exposure=None, version=0, plot_it=False, verbose=0):
+    """ 
+       Load the raw cold refences frame taken bofore this program and NUC it with 
+       the NUC of the previous program (or next one, if the previous does not exist).
+
+       INPUT
+       -----
+           port: int
+               number of camera AEF port (e.g. 10, 11, 20,...)
+           program: str
+               experiment program identifier as a string of format 'DATE.PROG_NO',
+               e.g. '20180904.015'
+           exposure: float, optional
+               camera exposure time in us
+               (OPTIONAL: default is to take the exposure time of the first data frame)
+           version: int, optional
+               calibration version to be used
+               (OPTIONAL: default is 0)
+           plot_it: bool, optional
+               switch of whether to plot intermediate results or not
+               (OPTIONAL: deafult is NOT to plot)
+           verbose: integer, optional
+               feedback level (details of print messages)
+               (OPTIONAL: if not provided, only ERROR output)
+              
+       RESULT
+       ------
+           exist: bool
+               indicator, of coldframe could be found
+           coldframe: numpy array
+               NUCed cold frame
+    """
+    if exposure is None:
+        try:
+            exist, t, exposure = get_exposure_by_program(port, program, version=version)
+        except:
+            print('get_NUCed_coldframe_by_program: ERROR! no exposure time found!')
+            return False, []
+            
+        t_exp = exposure[0]
+    else:
+        if verbose>0:
+            print('get_NUCed_coldframe_by_program: using exposure time {0}'.format(exposure))
+        t_exp = exposure
+    try:
+        exist, data, desc = get_NUC_by_program(port, program, t_exp, version=version, verbose=verbose-1)
+    except:
+        print('get_NUCed_coldframe_by_program: ERROR! no cold frame found!')
+        return False, []
+    
+    if exist:
+        cold_raw = data[2]
+        porg_nr = int(program.split('.')[1])
+        
+        ref_program = '{0}.{1:03d}'.format(program.split('.')[0], porg_nr-1)
+        exist2, data, desc = get_NUC_by_program(port, ref_program, t_exp, version=version, verbose=verbose-1)
+        if exist2:
+            coldframe = apply_NUC([cold_raw],data[0],data[1])[0]
+            if verbose>0:
+                print('get_NUCed_coldframe_by_program: using NUC of program {0}'.format(ref_program))
+        else:
+            ref_program = '{0}.{1:03d}'.format(program.split('.')[0], porg_nr+1)
+            if verbose>0:
+                print('get_NUCed_coldframe_by_program: program {0} has no predecessor.\n   --> using NUC of {1}'.format(program, ref_program))
+            exist2, data, desc = get_NUC_by_program(port, ref_program, t_exp, version=version, verbose=verbose-1)
+            if exist2:
+                coldframe = apply_NUC([cold_raw],data[0],data[1])[0]
+            else:
+                print('get_NUCed_coldframe_by_program: WARNING! no adjacent program found! --> cold frame is not NUCed')
+                coldframe = cold_raw
+        
+        if plot_it:
+            plt.figure(figsize=[8,4])
+            plt.subplot(1,2,1)
+            plt.imshow(cold_raw, vmin=np.percentile(cold_raw, 1), vmax=np.percentile(cold_raw, 99) )
+            plt.colorbar()
+            plt.title('raw cold frame\nof {0}'.format(program))
+            plt.subplot(1,2,2)
+            plt.imshow(coldframe, vmin=np.percentile(coldframe, 1), vmax=np.percentile(coldframe, 99) )
+            plt.colorbar()
+            plt.title('NUCed based on\ngain/offset from {0}'.format(ref_program))
+            plt.tight_layout()
+            plt.show()
+    else:
+        print('get_NUCed_coldframe_by_program: ERROR! No cold frame found for program {0}!'.foramt(program))
+        coldframe = []
+    
+    return exist, coldframe
+
+
 def download_raw_images_by_program(port,program,time_window=0,version=0,verbose=0):
     """
     """
@@ -2748,7 +2840,7 @@ def download_heatflux_mapping_reference(timepoint=None,version=0,testmode=False,
                     d[np.where(profile_no==i_profile)] = \
                         abs((y2_p-y1_p)*x_f - (x2_p-x1_p)*y_f + x2_p*y1_p - y2_p*x1_p) / np.sqrt((y2_p-y1_p)**2 + (x2_p-x1_p)**2) /2 + \
                         abs((y2_n-y1_n)*x_f - (x2_n-x1_n)*y_f + x2_n*y1_n - y2_n*x1_n) / np.sqrt((y2_n-y1_n)**2 + (x2_n-x1_n)**2) /2 
-            mappings['thickness'] = d
+            mappings['Thickness'] = d
             if verbose>0:
                 print("download_heatflux_mapping_reference: 'thickness' of profiles added to mapping reference dictionary")
                 
@@ -2763,7 +2855,29 @@ def download_heatflux_mapping_reference(timepoint=None,version=0,testmode=False,
             Y[index_ver] = -np.sin(22.5/180*np.pi)*x1 + np.cos(22.5/180*np.pi)*y1 + 0.7
             if verbose>0:
                 print("download_heatflux_mapping_reference: vertical target moved and rotated in 'X' and 'Y' for better plotting")
-                
+        
+        # define target modules array
+        TM = (np.copy(mappings['Finger_ID'][0]),{1:'TM1h', 2:'TM2h', 3:'TM3h', 4:'TM4h', 
+                                                 5:'TM5h', 6:'TM6h', 
+                                                 7:'TM7h', 8:'TM8h', 9:'TM9h',
+                                                 10:'TM1v', 11:'TM2v', 12:'TM3v'})
+        Finger_ID = np.copy(mappings['Finger_ID'][0])
+        Finger_ID[np.isnan(Finger_ID)] = -1
+        TM[0][np.logical_and(Finger_ID >= 0, Finger_ID < 700)] = 1
+        TM[0][np.logical_and(Finger_ID >= 700, Finger_ID < 1400)] = 2
+        TM[0][np.logical_and(Finger_ID >= 1400, Finger_ID < 2200)] = 3
+        TM[0][np.logical_and(Finger_ID >= 2200, Finger_ID < 3000)] = 4
+        TM[0][np.logical_and(Finger_ID >= 3000, Finger_ID < 5400)] = 5
+        TM[0][np.logical_and(Finger_ID >= 5400, Finger_ID < 7800)] = 6
+        TM[0][np.logical_and(Finger_ID >= 7800, Finger_ID < 8400)] = 7
+        TM[0][np.logical_and(Finger_ID >= 8400, Finger_ID < 9600)] = 8
+        TM[0][np.logical_and(Finger_ID >= 9600, Finger_ID < 10800)] = 9
+        TM[0][np.logical_and(Finger_ID >= 10800, Finger_ID < 11800)] = 10
+        TM[0][np.logical_and(Finger_ID >= 11800, Finger_ID < 12800)] = 11
+        TM[0][np.logical_and(Finger_ID >= 12800, Finger_ID < 13700)] = 12
+        TM[0][TM[0]==-1] = np.nan
+        mappings['Target_Module'] = TM
+    
     return exist,mappings
 
 def download_heatflux_scene_model_reference(port,timepoint=None,program=None,version=0,testmode=False,verbose=0):
@@ -2909,7 +3023,7 @@ def get_heatflux_profile(port,profile,finger=None,timepoint=1,program=None,tstar
     """
     ### checking whether input is valid and whether the download can be started
     if program==None and tstart==None:
-        raise Exception("get_heatflux_profile: No Program given, please specify the program you are want heatflux from")
+        raise Exception("get_heatflux_profile: No Program given, please specify the program you want heatflux from")
     else:
         ### some informations about the program are given, is the timepoint given in a usefull way?
         if timepoint==None or (type(timepoint)!=int and type(timepoint)!=float):
@@ -3021,7 +3135,7 @@ def extract_heatflux_profile_from_DL(time,images,profile,finger=None,time_window
         else:
             fingerID=finger*100+profile
         ### okay finderID is fine, data is given, lets get the mapping
-        exist,mapping=download_heatflux_mapping_reference(testmode=testmode)
+        exist,mapping=download_heatflux_mapping_reference(testmode=testmode, verbose=verbose-1)
         if exist:
             Fingermap=np.asarray(mapping['Finger_ID'][0],dtype=np.int)            
             locs=np.where(Fingermap==fingerID)
@@ -3224,6 +3338,8 @@ def download_divertor_load(port,targetmodule=None,program=None,tstart=None,tend=
     return exist,time,load,error
 
 def download_scene_model(port,program=None,timepoint=None,version=0,verbose=0):
+    """
+    """
     if type(port)==int or type(port)==float:
         portnam="AEF"+str(port)
     elif type(port)==str:
@@ -3269,7 +3385,7 @@ def download_scene_model(port,program=None,timepoint=None,version=0,verbose=0):
                 "x":          channels[8],          
                 "y":          channels[9],          
                 "z":          channels[10]
-            } 
+            }
         return exist,scene_model
     else:
         return False,[0]
@@ -3448,6 +3564,7 @@ if __name__=='__main__':
 #        plt.figure(),plt.imshow(images[50],vmin=0)
 #    status,mapping=download_heatflux_mapping_reference(verbose=4)
 #    test=get_heatflux_profile(20,1605,timepoint=1,program="20171109.008",verbose=4)
+    
 #%% loads test
 #    port=10
 #    prog="20171207.016"#"20181011.015"#"20171114.052"    
@@ -3478,3 +3595,10 @@ if __name__=='__main__':
 #            dset.write_direct(imags)
 #            File.create_dataset('timestamps', data=list(bla[1]), dtype='uint64')#,compression="gzip")
 #            File.close()
+
+#%% get hot cold image test
+    port=10
+    program="20180904.002"
+    
+    exist, coldframe = get_NUCed_coldframe_by_program(port, program, exposure=None, version=0, plot_it=True, verbose=3)
+  
\ No newline at end of file