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