diff --git a/CHANGELOG b/CHANGELOG index f6e346cea7556fe4bc4e5dd4c5ab0932d66b3b8a..99d9c6eb984a6a2e7274f95096db2cb1ca8e5c27 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,19 +1,40 @@ <<<<<<< HEAD +XX.06.2020: Update to V3.5.0 + - add download maximum heat flux and wetted area +16.06.2020: Update to V3.4.1 + - updated and improved documentation + - include chache function and a request for all ports for heat flux and divertor load 08.02.2020: Update to V3.4.0 - Bugfix: download_images_by_times produzierte doppelte Werte im Zeit und Bildvektor - - + - Bugfix: download divertor load gave print back that request was made, although no request was made (fixed) + - Bugfix: correction of version bug from last commit and change of default value for the profile extraction functions to None + - Readme added Update to V3.3.3: - - + - added function for peaking factor and strike line width calculation in tools + - bugfix: bug fix get_trigger_from_PID which caused an error in get_latest_version if it was used for non IR data Update to V3.3.2: - - + - extended feedback for download_heatflux + - changes of wetted area calculation + - changes of wetted area calculation + - bugfix: get_trigger_PID, get_finger and during import (see issues 6,7) Update to V3.3.1: - - + - bugfix: FOV for AEF50 was not working correctly Update to V3.3.0: - - + - IR_config_constants: added path to Test archive and use this variable in downloadversionIRdata when building an archive path + - downloadversionIRdata: consistent use of testmode parameter + - downloadversionIRdata: added testmode to all reading routines allowing reading from Test archive + - IR_image_tools: no longer sets working directory to script file location + - IR_config_constants: sets parameter_file_path as absolute path + - downloadversionIRdata: new function get_trigger_from_PID() wraps get_program_from_PID() and allows getting timestamps for lab data + - downloadversionIRdata: download_images_by_time_via_png() now uses nanosecond timestamps to call AKF_2.get_time_intervals() + - downloadversionIRdata: disable DeprecationWarning in import of archivedb (timezone issue on Windows) + - downloadversionIRdata: get_NUC_by_times() uses the reference cold frame in case no cold frame (NUC frame) was found for this time + - downloadversionIRdata: unified use of stoptime instead of endtime + - downloadversionIRdata: expanded testing sections (profile, coldframe, timestamps and scene model) Update to V3.2.5: - + - remove of old, not needed function and dependencies, update of download_background function Update to V3.2.4: - + - smaller bugfixes and setup.py got added Update to V3.2.3: - bugfix: finding right version for meta informations Update to V3.2.2: @@ -84,7 +105,8 @@ bugfixes in downloadversionIRdata: - fixed: wrong time intervall for TC divertor data Versions: -V3.4.0: chaching functionality included, request for all cameras included + Bugfixes +V3.5.0: download of wetted area, peak loads for different targets and +V3.4.1: chaching functionality included, request for all cameras included + Bugfixes V3.3.0: code-cleaning, unification of variable names, new functions: get_trigger_from_PID, V3.2.0: download of scene models possible, temperature profiles can be extracted, downsampled temperature images available V3.1.0: add of divertor loads in the upload and the download diff --git a/IR_image_tools.py b/IR_image_tools.py index ea65f9c1feb0d1959099936f209a57c990aaf0f4..ce8eefcb760143f010e964aa7f919405a9524f6a 100644 --- a/IR_image_tools.py +++ b/IR_image_tools.py @@ -25,14 +25,16 @@ 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. - IN: - time_ns - integer of nanosecond time stamp, + INPUT + ----- + time_ns: - integer of nanosecond time stamp, e.g. 1511972727249834301 (OPTIONAL) shot_no - integer of MDSplus style shot number, e.g. 171207022 (OPTIONAL) program_str - string of CoDaQ ArchiveDB style prgram number or date, e.g. '20171207.022' or '20171207' (OPTIONAL) - RETURN: + RESULT + ------ conn - MDSplus connection object, to be used in e.g. 1511972727249834301 read_MDSplus_image_simple(), read_MDSplus_metadata() ''' @@ -639,7 +641,13 @@ def reconstruct_coldframe (exposuretime, sT, a, bnew, coldref): """ INPUT ------ - + exposuretime: integer + the exposure time + sT: + a: + bnew: + coldref: numpy array + the reference cold frame as the base for the reconstruction RESULT ------ @@ -689,17 +697,27 @@ def get_work_list(pipepath,typ="q"): """ INPUT ------ - + pipepath: string + the path to the folder where the files are located + typ: string + the typ of data which is requested in the working list\n + possiblities: q, Aw, qpeak, width, load\n + or anything else for the problematic programs RESULT ------ - + cam_programs: list + a list containing two coloumns, cameras and programs + reasons: list, optional, only for problematic programs + a list showing the reasons, why data are not processed NOTE ------ """ today=datetime.datetime.now() cam_programs=[] - if typ in ('q','load'): + if typ in ('q_old','load_old'): f=open(pipepath+str(today.year)+str(today.month)+"_"+typ+"_requests.txt") + elif typ in ('q','load','qpeak','Aw','width'): + f=open(pipepath+"Auto_"+typ+"_requests.txt") else: reasons=[] f = open(pipepath+"problematic_programs.txt") diff --git a/ToDO.txt b/ToDO.txt index ccd2421383ddca6edd9d3b785efa1c2fb28a18a3..d03c20de5d2fff827541f84e955a1af730b55179 100644 --- a/ToDO.txt +++ b/ToDO.txt @@ -6,3 +6,6 @@ download: - implement download of the stored temperature data (After the upload) - implement download of the stored heat flux data --> done in V3.0.0 - implement download of FLIR data --> Done in V2.8.0, in testing phase +- implement caching +- implement download of wetted area, peak heat flux and average strike line width +- implement request of all ports diff --git a/downloadversionIRdata.py b/downloadversionIRdata.py index f564fa4ca0713f487d61a14fc46e1cb68135904a..be2437c8cefd5c2a849d882842cef992348140df 100644 --- a/downloadversionIRdata.py +++ b/downloadversionIRdata.py @@ -4,7 +4,7 @@ Created on Wed Oct 25 15:51:46 2017 updated on Tue Aug 21 10:20:00 2018 last update on Fr Nov 23 15:37:00 2018 -Version: 3.4.0 +Version: 3.4.1 (Numbering: #of big changes(OP1.2a download V1, OP1.2b download V2, heatflux V3) . #of updates to add functionalities @@ -12,7 +12,7 @@ Version: 3.4.0 #number of updates for bug fixes ) @author: holn """ -version="V3.4.0" +version = "V3.4.1" import numpy as np import IR_image_tools as IR_tools @@ -28,7 +28,7 @@ from IR_config_constants import archivepath, testarchivepath, portcamdict, camli import datetime import urllib.request import urllib.error - +import logging import json from PIL import Image from io import BytesIO @@ -36,7 +36,7 @@ from os.path import join import matplotlib.pyplot as plt try: import threading - import archivedb as AKF_2 + import w7xarchive as AKF_2 # disbale deprecation warnings, because of timezone warning spam import warnings warnings.filterwarnings("ignore", category=DeprecationWarning) @@ -81,12 +81,12 @@ def get_latest_version(stream, project="W7X", testmode=False, t_from=None, return int of version number of None if non-versioned or non-existing stream author: G. Schlisio, edit by holn """ - if testmode: + if testmode:#check which archive should be used base = testarchivepath else: base = archivepath - if program == None and t_from == None and t_to == None: + if program == None and t_from == None and t_to == None:# check wheather any time information was given request = urllib.request.Request(base +project+"/" + stream + "/_versions.json", headers={"Accept": "application/json"}) else: if program is not None: @@ -192,42 +192,56 @@ def download_LUT(port, time, exposure=0, emissivity=0, camera_filter=0, version= testmode=False, verbose=0): """ download_LUT(camera, port, time, exposure=0, emissivity=0, camera_filter=0, version=1): - time in ns + download of the look up table for the infrared cameras from the database for OP1.2(a+b) Have to swap 11, 21 until correction in the database INPUT ------ - port: - time: - exposure: - emissivity: - camera_filter: - version: - testmode: - verbose: - + port: interger + number of the AEF camera port + time: integer + nanosecond timestamp for the LUT + exposure: integer + requested exposure time in microseconds + emissivity: float, string or integer + emissivity value to identify which LUT is requested + camera_filter: inter or string, only needed for port 50 + filter number of the Infratec camera in port AEF50 + version: integer, optional, default 0 + Version of the data in the archiveDB, in case of 0 the highest version will be used + testmode: boolean, optional, default False + if True, the data will be loaded from the test archive + verbose: integer, optional, default 0 + feedback level (details of print messages) RESULT ------ - + exist: boolean + True if Look up table was found, False if not + LUT: list + contains the calibration information: [digital level, temperature, temperature error] NOTE ------ + function need to be adapted for OP2, if AEK ports come into opperation """ - OP = IR_tools.get_OP_by_time(time_ns=time) - if port == 21: + OP = IR_tools.get_OP_by_time(time_ns=time)#getting operation phase + if port == 21:# swapping both ports (21 and 11) port = 11 elif port == 11: port = 21 - if testmode: + if testmode: #check which archive should be used larchivepath = testarchivepath+project+"/"+portpathdict[OP]["AEF"+str(port)]+"LUT_" else: larchivepath = archivepath+project+"/"+portpathdict[OP]["AEF"+str(port)]+"LUT_" + #camera dependend request string generation if port == 50 and OP == "OP1.2a":# camera=="INFRATEC" or camera=="infratec" or camera=="Infratec": query = "Filter_"+str(camera_filter)+"_Texp_"+str(int(exposure))+"us_e_"+str(float(emissivity)) elif port in [10, 11, 20, 21, 30, 31, 40, 41, 51] or OP == "OP1.2b":#camera=="IRCAM" or camera=="IRcam" or camera=="ircam": query = "Texp_"+str(int(exposure))+"us_e_"+str(float(emissivity)) else: - print("download_LUT: Error! Camera unknown, stopping here.") - raise Exception - if version == 0: +# print("download_LUT: Error! Camera unknown, stopping here.") + logging.warning("download_LUT: Error! Camera unknown, stopping here.") + return False, 0 +# raise Exception + if version == 0:#version check, if 0 version = get_latest_version(portpathdict[OP]["AEF"+str(port)]+"LUT_DATASTREAM", t_from=time, testmode=testmode) if verbose > 0: print("download_LUT: LUT V"+str(version)+" is used") @@ -259,12 +273,27 @@ def read_LUT_from_file(port, this_time, t_exp, emissivity, cfilter, verbose=0):# Read LUT V3 from local files for testing new calibration. INPUT ------ - + port: integer or string + the port number of the AEF port + this_time: integer + nanosecond timestamp for the LUT + t_exp: integer + requested exposure time in microseconds + emissivity: float, string or integer + emissivity value to identify which LUT is requested + cfilter: inter or string, only needed for port 50 + filter number of the Infratec camera in port AEF50 + verbose: integer, optional, default 0 + feedback level (details of print messages) RESULT ------ - + exist: boolean + True if Look up table was found, False if not + LUT: list + contains the calibration information: [digital level, temperature, temperature error] NOTE ------ + function need to be adapted for OP2, if AEK ports come into opperation """ LUT_dir = '\\\\sv-e4-fs-1\\E4-Mitarbeiter\\E4 Diagnostics\\QIR\\testingLUT' OP = IR_tools.get_OP_by_time(time_ns=this_time) @@ -284,14 +313,32 @@ def read_LUT_from_file(port, this_time, t_exp, emissivity, cfilter, verbose=0):# def download_NUC_by_program(port, program, exposure, version=0, testmode=False, verbose=0): ''' + download the NUC data for a given port, program and exposure time of the camera INPUT ------ - + port: integer or string + port number of the AEF port of the camera + program: string + program id in the form of 'YYYYMMDD.XXX', e.g. '20181016.016' + exposure: integer + exposure time in microseconds + version: integer, optional, default 0 + Version of the data in the archiveDB, in case of 0 the highest version will be used + testmode: boolean, optional, default False + if True, the data will be loaded from the test archive + verbose: integer, optional, default 0 + feedback level (details of print messages) RESULT ------ - + exist: boolean + True if NUC data was found, False if not + NUC: list + a list vontaining images of gain, offset, cold, badpixels, gain_error and offset_error + NUC_describtion: list + a list which entry in NUC is what, looks like ['gain', 'offset', 'cold', 'badpixels', 'gain_error', 'offset_error'] NOTE ------ + function need to be adapted for OP2, if AEK ports come into opperation ''' # prog=get_program_from_PID(program) # try: @@ -310,14 +357,34 @@ def download_NUC_by_program(port, program, exposure, version=0, testmode=False, def download_NUC_by_times(port, starttime, stoptime, exposure, testmode=False, version=0, verbose=0): ''' + download the NUC data for a given port, start and endtime in ns and exposure time of the camera INPUT ------ - + port: integer or string + port number of the AEF port of the camera + starttime: integer + time in ns where the search should start + stoptime: integer + time in sn where the search should end + exposure: integer + exposure time in microseconds + version: integer, optional + Version of the data in the archiveDB, in case of 0 the highest version will be used + testmode: boolean, optional + if True, the data will be loaded from the test archive + verbose: integer, optional + feedback level (details of print messages) RESULT ------ - + exist: boolean + True if NUC data was found, False if not + NUC: list + a list vontaining images of gain, offset, cold, badpixels, gain_error and offset_error + NUC_describtion: list + a list which entry in NUC is what, looks like ['gain', 'offset', 'cold', 'badpixels', 'gain_error', 'offset_error'] NOTE ------ + function need to be adapted for OP2, if AEK ports come into opperation ''' OP = IR_tools.get_OP_by_time(time_ns=starttime) if testmode: @@ -370,12 +437,29 @@ def get_NUC_by_program(port, program, exposure, version=0, testmode=False, verbo the cold frame and/or compute the gain, offset from the hot and cold frame. INPUT ------ - + port: integer or string + port number of the AEF port of the camera + program: string + program id in the form of 'YYYYMMDD.XXX', e.g. '20181016.016' + exposure: integer + exposure time in microseconds + version: integer, optional + Version of the data in the archiveDB, in case of 0 the highest version will be used + testmode: boolean, optional + if True, the data will be loaded from the test archive + verbose: integer, optional + feedback level (details of print messages) RESULT ------ - + exist: boolean + True if NUC data was found, False if not + NUC: list + a list vontaining images of gain, offset, cold, badpixels, gain_error and offset_error + NUC_describtion: list + a list which entry in NUC is what, looks like ['gain', 'offset', 'cold', 'badpixels', 'gain_error', 'offset_error'] NOTE ------ + function need to be adapted for OP2, if AEK ports come into opperation ''' # prog=get_program_from_PID(program) # try: @@ -399,23 +483,46 @@ def get_NUC_by_times(port, starttime, stoptime, t_exp, version=0, testmode=False Loads NUC elements (gain, offset cold image, bad pixels) for an IR camera in a given port and time interval. Depending on time and camera, reconstruct the cold frame and/or compute the gain, offset from the hot and cold frame. + the result is operation phase dependent, due to changes in the aquisition and saving programs + INPUT ------ - + port: integer or string + port number of the AEF port of the camera + starttime: integer + time in ns where the search should start + stoptime: integer + time in sn where the search should end + exposure: integer + exposure time in microseconds + version: integer, optional + Version of the data in the archiveDB, in case of 0 the highest version will be used + testmode: boolean, optional + if True, the data will be loaded from the test archive + OP: string, optional, default None + name of operation phase + verbose: integer, optional + feedback level (details of print messages) RESULT ------ - + exist: boolean + True if NUC data was found, False if not + NUC: list + a list vontaining images of gain, offset, cold, badpixels, gain_error and offset_error + NUC_describtion: list + a list which entry in NUC is what, looks like ['gain', 'offset', 'cold', 'badpixels', 'gain_error', 'offset_error'] NOTE ------ + function need to be adapted for OP2, if AEK ports come into opperation """ - if OP is None: + if OP is None: #get operation phase if not given OP = IR_tools.get_OP_by_time(time_ns=stoptime) - if OP == "OP1.2a": + if OP == "OP1.2a": # check for operation phase t1 = stoptime t0 = starttime prog = read_program(t1) program = prog[1]['id'] - if (port == 31) or (port == 21 and float(program[4:]) > 1110): + if (port == 31) or (port == 21 and float(program[4:]) > 1110):#camera 31 and 21 need after 20171110 new coldframes due to a open shutter during the recording of the coldframes if verbose > 0: print("get_NUC_by_times: rebuilding coldframe") #use any way the rebuilt coldframe. @@ -427,7 +534,9 @@ def get_NUC_by_times(port, starttime, stoptime, t_exp, version=0, testmode=False coldref = hotcold[1] hotref = hotcold[0] else: - raise Exception("get_NUC_by_times: unable to download reference frames") +# raise Exception("get_NUC_by_times: unable to download reference frames") + logging.warning("get_NUC_by_times: unable to download reference frames") + return False, 0, 0 filestring = 'AEF' + str(port) + '_et' + str(int(t_exp)) amap = np.load(join(IRCamColdframes_fittingpath, filestring + '_a.npy')) bmap = np.load(join(IRCamColdframes_fittingpath, filestring + '_b.npy')) @@ -441,7 +550,7 @@ def get_NUC_by_times(port, starttime, stoptime, t_exp, version=0, testmode=False gain_error = 0 offset_error = 0 return True, [gain, offset, cirebuild, badpixels, gain_error, offset_error], ['gain', 'offset', 'cold', 'badpixels', 'gain_error', 'offset_error'] - elif (port == 11) or (port == 21): + elif (port == 11) or (port == 21): # case of the swaped cameras if verbose > 0: print('get_NUC_by_times: downloading NUC') # coldref, hotref = IR_tools.load_ref_images('AEF' + str(port), t_exp) @@ -450,10 +559,14 @@ def get_NUC_by_times(port, starttime, stoptime, t_exp, version=0, testmode=False coldref = hotcold[1] hotref = hotcold[0] else: - raise Exception("get_NUC_by_times: unable to download reference frames") +# raise Exception("get_NUC_by_times: unable to download reference frames") + logging.warning("get_NUC_by_times: unable to download reference frames") + return False, 0, 0 NUC_DL = download_NUC_by_times(port, t0, t1, t_exp, version, testmode) if NUC_DL[0] == False: - raise Exception("get_NUC_by_times: NUC was not found") +# raise Exception("get_NUC_by_times: NUC was not found") + logging.warning("get_NUC_by_times: NUC was not found") + return False, 0, 0 else: ci = NUC_DL[1][2] gain, offset = IR_tools.calculate_gain_offset_image(ci, None, coldref, hotref, verbose=verbose-1) @@ -463,7 +576,7 @@ def get_NUC_by_times(port, starttime, stoptime, t_exp, version=0, testmode=False gain_error = 0 offset_error = 0 return True, [gain, offset, ci, badpixels, gain_error, offset_error], ['gain', 'offset', 'cold', 'badpixels', 'gain_error', 'offset_error'] - else: + else: #all other cases, the "normal" case if verbose > 0: print('get_NUC_by_times: downloading NUC') NUC_DL = download_NUC_by_times(port, starttime, stoptime, t_exp, testmode=testmode) @@ -480,13 +593,15 @@ def get_NUC_by_times(port, starttime, stoptime, t_exp, version=0, testmode=False coldref = hotcold[1] hotref = hotcold[0] else: - raise Exception("get_NUC_by_times: unable to download reference frames") +# raise Exception("get_NUC_by_times: unable to download reference frames") + logging.warning("get_NUC_by_times: unable to download reference frames") + return False, 0, 0 ### get the cold frame: 1. get the metastream frametype and exposuretime and check in it for the positions, if -1 type is unknown, when if needs to be identified in a different way try: exist, _, coldframes = download_calibration_raw_files_by_time(port, t_exp, starttime, stoptime, frametype=0, version=0, testmode=testmode, verbose=verbose-1) except: exist = False - if exist: + if exist:#okay it exist, average the cold frames cold = np.zeros(np.shape(coldframes[0]), dtype=np.uint64) for ele in coldframes: cold += ele @@ -499,30 +614,54 @@ def get_NUC_by_times(port, starttime, stoptime, t_exp, version=0, testmode=False badpixels = find_badpixels(port, gain, offset, niterations=10, tolerance=10, verbose=verbose-1) return True, [gain, offset, cold, badpixels, gain_error, offset_error], ['gain', 'offset', 'cold', 'badpixels', 'gain_error', 'offset_error'] else: - raise Exception("get_NUC_by_times: unknown Operation phase or NUC method not implemented for this OP") +# raise Exception("get_NUC_by_times: unknown Operation phase or NUC method not implemented for this OP") + logging.warning("get_NUC_by_times: unknown Operation phase or NUC method not implemented for this OP") + return False, 0, 0 def download_calibration_raw_files_by_time(port, t_exp, starttime, stoptime, frametype=0, version=0, testmode=False, verbose=0): """ - download_calibration_raw_files_by_time(port, t_exp, starttime, stoptime, frametype=0, version=0) + download of the calibration raw files which are recorded between t0 and t1 trigger frametype: 0 for closed shutter frames (cold), 1 for open shutter frames (background) + INPUT ------ - + port: integer + port number of the AEF port of the camera + t_exp: integer + exposure time in microseconds + starttime: integer + time in ns where the search should start + stoptime: integer + time in sn where the search should end + frametype: integer, default 0 + defines which type of frames should be returned, 0 for cold frames, 1 for background frames + version: integer, optional + Version of the data in the archiveDB, in case of 0 the highest version will be used + testmode: boolean, optional + if True, the data will be loaded from the test archive + verbose: integer, optional + feedback level (details of print messages) RESULT ------ - + exist: boolean + True if data was found, False if not + time: list + a list containing the time stamp of each frame + frames: list + a list of frames, 2D numpy arrays NOTE ------ + function need to be adapted for OP2, if AEK ports come into opperation """ gotit, time_t, texp_t = get_exposure_by_times(port, int(starttime-100), int(stoptime-20e6), testmode=testmode) OP = IR_tools.get_OP_by_time(time_ns=stoptime) if gotit: expinds = np.where(texp_t == t_exp)[0] if len(expinds) == 0: - print("download_calibration_raw_files_by_time: Error! cannot find the exposure time in the given data") + logging.warning("download_calibration_raw_files_by_time: Error! cannot find the exposure time in the given data") return False, [0], [0] else: - print("download_calibration_raw_files_by_time: Error! exposure time not found") + logging.warning("download_calibration_raw_files_by_time: Error! exposure time not found") return False, [0], [0] gotitf, timef, values_f = get_frametype_by_times(port, int(starttime-100), int(stoptime-20e6), testmode=testmode) if gotitf: @@ -545,7 +684,9 @@ def download_calibration_raw_files_by_time(port, t_exp, starttime, stoptime, fra ref_t = [np.min(frametimes[turnpoint+1:]), np.max(frametimes[turnpoint+1:])] # print((ref_t[1]-ref_t[0])/1e9) else: - raise Exception("download_calibration_raw_files_by_time: requested Frametype unknown and not implemented!") +# raise Exception("download_calibration_raw_files_by_time: requested Frametype unknown and not implemented!") + logging.warning("download_calibration_raw_files_by_time: requested Frametype unknown and not implemented!") + return False, [0], [0] else: print("download_calibration_raw_files_by_time: Error! frametype not found") frametimes = time_t[expinds] @@ -559,7 +700,9 @@ def download_calibration_raw_files_by_time(port, t_exp, starttime, stoptime, fra ref_t = [np.min(frametimes[turnpoint+1:]), np.max(frametimes[turnpoint+1:])] print((ref_t[1]-ref_t[0])/1e9) else: - raise Exception("download_calibration_raw_files_by_time: requested Frametype unknown and not implemented!") +# raise Exception("download_calibration_raw_files_by_time: requested Frametype unknown and not implemented!") + logging.warning("download_calibration_raw_files_by_time: requested Frametype unknown and not implemented!") + return False, [0], [0] # return False, [0], [0] t1date = datetime.datetime.utcfromtimestamp((stoptime-100)/1e9) t1date = t1date.isoformat() @@ -588,12 +731,29 @@ def download_hot_cold_reference_by_times(port, exposure, starttime=1503907200000 Uses first calibration frames if time is not defined. INPUT ------ - + port: integer or string + port number of the AEF port of the camera, or string containing the full port name + exposure: integer + exposure time in microseconds + starttime: integer + time in ns where the search should start + version: integer, optional + Version of the data in the archiveDB, in case of 0 the highest version will be used + testmode: boolean, optional + if True, the data will be loaded from the test archive + verbose: integer, optional + feedback level (details of print messages) RESULT ------ - + exist: boolean + True if data was found, False if not + images: list + a list vontaining images of gain, offset, cold, badpixels, gain_error and offset_error + image_describtion: list + a list which entry in NUC is what, looks like ['hot','cold'] NOTE ------ + function need to be adapted for OP2, if AEK ports come into opperation """ OP = IR_tools.get_OP_by_time(time_ns=starttime) if isinstance(port, int): @@ -648,15 +808,37 @@ def download_hot_cold_reference_by_times(port, exposure, starttime=1503907200000 def download_background_by_program(port, program, exposure, camera_filter=0, version=0, testmode=False, verbose=0): ''' + download the background from the AEF cameras in OP1.2a, which are recorded between t0 and t1 trigger returned exist, time, frame INPUT ------ - + port: integer + port number of the AEF port of the camera + program: string + program id in the form of 'YYYYMMDD.XXX', e.g. '20181016.016' + exposure: integer + exposure time in microseconds + camera_filter: integer or string, only needed for port 50 + filter number of the Infratec camera in port AEF50 + version: integer, optional + Version of the data in the archiveDB, in case of 0 the highest version will be used + testmode: boolean, optional + if True, the data will be loaded from the test archive + verbose: integer, optional + feedback level (details of print messages) + OP: string, optional, default None + name of operation phase RESULT ------ - + exist: boolean + True if data was found, False if not + time: list + a list containing the time stamp of each frame + frames: list + a list of frames, 2D numpy arrays NOTE ------ + function need to be adapted for OP2, if AEK ports come into opperation ''' # prog=get_program_from_PID(program) # try: @@ -674,6 +856,40 @@ def download_background_by_program(port, program, exposure, camera_filter=0, ver def download_background_by_times(port, starttime, stoptime, exposure, camera_filter=0, version=0, testmode=False, verbose=0): + """ + download the background frames for a given time intervall in nanoseconds, defined by start and stop time + + INPUT + ------ + port: integer + port number of the AEF port of the camera + starttime: integer + time in ns where the search should start + stoptime: integer + time in sn where the search should end + exposure: integer + exposure time in microseconds + camera_filter: integer or string, only needed for port 50 + filter number of the Infratec camera in port AEF50 + version: integer, optional + Version of the data in the archiveDB, in case of 0 the highest version will be used + testmode: boolean, optional + if True, the data will be loaded from the test archive + verbose: integer, optional + feedback level (details of print messages) + + RESULT + ------ + exist: boolean + True if data was found, False if not + time: list + a list containing the time stamp of each frame + frames: list + a list of frames, 2D numpy arrays + NOTE + ------ + function need to be adapted for OP2, if AEK ports come into opperation + """ OP = IR_tools.get_OP_by_time(time_ns=starttime) if OP == "OP1.2a": stream = portpathdict[OP]["AEF"+str(port)]+"background_" @@ -720,8 +936,9 @@ def download_background_by_times(port, starttime, stoptime, exposure, camera_fil elif OP == "OP1.2b": NUC_DL = get_NUC_by_times(port, starttime, stoptime, t_exp=exposure, version=version, testmode=testmode, verbose=verbose-1)#download_NUC_by_times(port, t0, t1, t_exp, version) if NUC_DL[0] == False: - raise Warning("download_background_by_times: NUC was not found") -# return False, 0, 0 +# raise Warning("download_background_by_times: NUC was not found") + logging.warning("download_background_by_times: NUC was not found") + return False, 0, 0 else: # extract NUC elements gain = [] @@ -737,14 +954,42 @@ def download_background_by_times(port, starttime, stoptime, exposure, camera_fil def get_NUCed_background_by_times(port, t0, t1, t_exp, cfilter, gain, offset, version=0, testmode=False, plot_it=False, verbose=0): """ OP1.2b function + download the background frame and applies the NUC onto the background, given by gain und offset + it is an average over 30 frames. + INPUT ------ - + port: integer + port number of the AEF port of the camera + t0: integer + nanoseconds timestamp of the t0 trigger, start of the program + t1: integer + nanoseconds timestamp of the t1 trigger, start of the heating + t_exp: integer + exposure time in microseconds + gain: numpy array + the gain image from the calibration to convert the counts into digital level + offset: numpy array + the offset image from the calibration to convert the counts into digital level + version: integer, optional + Version of the data in the archiveDB, in case of 0 the highest version will be used + testmode: boolean, optional + if True, the data will be loaded from the test archive + plot_it: boolean, optional, default False + if True, the data will be plotted directly + verbose: integer, optional + feedback level (details of print messages) RESULT ------ - + exist: boolean + True if data was found, False if not + time: integer + the timestamp of the background frame (firest timestamp of the 30 frames) + background_frame: numpy array + the background frame NOTE ------ + function need to be adapted for OP2, if AEK ports come into opperation """ exist, btime, backgroundframes = download_calibration_raw_files_by_time(port, t_exp, t0, t1, frametype=1, version=version, testmode=testmode, verbose=verbose-1) camera = portcamdict["OP1.2b"]["AEF"+str(port)] @@ -856,14 +1101,35 @@ def get_NUCed_coldframe_by_program(port, program, exposure=None, version=0, def download_raw_images_by_program(port, program, time_window=0, version=0, testmode=False, verbose=0): """ + download the raw frames (counts) from the infrared cameras for a given program + INPUT ------ - + port: integer + port number of the AEF port of the camera + program: string + program id in the form of 'YYYYMMDD.XXX', e.g. '20181016.016' + time_window: list, array, integer or float, optional, default 0 + if integer or float: size of the window in seconds from t1 + if list or array: start and endpoint of the window in seconds from t1 + if 0 the full program will be downloaded (t1 until t6) + version: integer, optional, default 0 + Version of the data in the archiveDB, in case of 0 the highest version will be used + testmode: boolean, optional, default False + if True, the data will be loaded from the test archive + verbose: integer, optional, default 0 + feedback level (details of print messages) RESULT ------ - + exist: boolean + True if data was found, False if not + time: list + a list containing the time stamp of each frame + frames: list + a list of frames, 2D numpy arrays NOTE ------ + the timewindow will be substructured into intervalls, and each intervall will be downloaded one after the other to avoid a overfilling of the RAM. A to large intervall can still overflow the RAM """ exist, _, starttime, stoptime = get_trigger_from_PID(program, port, testmode, verbose=verbose-1) # prog=AKF_1.get_program_from_PID(program) @@ -876,11 +1142,15 @@ def download_raw_images_by_program(port, program, time_window=0, version=0, test if exist: if type(time_window) == list or type(time_window) == np.ndarray: if len(time_window) > 2 or time_window[0] > 1000: - raise Exception("download_raw_images_by_program: invalid input for the time_window!") +# raise Exception("download_raw_images_by_program: invalid input for the time_window!") + logging.warning("download_raw_images_by_program: invalid input for the time_window!") + return False, 0, 0 tstart = time_window[0] tstop = time_window[1] if tstop <tstart: - raise Exception("download_raw_images_by_program: t_stop before t_start") +# raise Exception("download_raw_images_by_program: t_stop before t_start") + logging.warning("download_raw_images_by_program: t_stop before t_start") + return False, 0, 0 return download_raw_images_by_times(port, int(starttime+tstart*1e9), int(starttime+tstop*1e9), version, testmode=testmode, verbose=verbose) else: if time_window == 0: @@ -893,14 +1163,35 @@ def download_raw_images_by_program(port, program, time_window=0, version=0, test def download_raw_images_by_times(port, starttime, stoptime, version=0, intervalSize=1E9, testmode=False, verbose=0): """ + download the raw frames (counts) from the infrared cameras for a given time interval in nanoseconds + INPUT ------ - + port: integer + port number of the AEF port of the camera + starttime: integer + time in ns where the search should start + stoptime: integer + time in sn where the search should end + version: integer, optional, default 0 + Version of the data in the archiveDB, in case of 0 the highest version will be used + intervalSize: integer, optional, default 1e9 (1 second) + size of the intervall to be downloaded in nanoseconds + testmode: boolean, optional, default False + if True, the data will be loaded from the test archive + verbose: integer, optional, default 0 + feedback level (details of print messages) RESULT ------ - + exist: boolean + True if data was found, False if not + time: list + a list containing the time stamp of each frame + frames: list + a list of frames, 2D numpy arrays NOTE ------ + the timewindow will be substructured into intervalls, and each intervall will be downloaded one after the other to avoid a overfilling of the RAM. A to large intervall can still overflow the RAM """ OP = IR_tools.get_OP_by_time(time_ns=starttime) if version == 0: @@ -915,12 +1206,27 @@ def download_images_by_times(larchivepath, starttime, stoptime, intervalSize=1E9 """ INPUT ------ - + larchivepath: string + local archivepath, the URL to download the images + starttime: integer + time in ns where the search should start + stoptime: integer + time in sn where the search should end + intervalSize: integer, optional, default 1e9 (1 second) + size of the intervall to be downloaded in nanoseconds + verbose: integer, optional, default 0 + feedback level (details of print messages) RESULT ------ - + exist: boolean + True if data was found, False if not + time: list + a list containing the time stamp of each frame + frames: list + a list of frames, 2D numpy arrays NOTE ------ + the timewindow will be substructured into intervalls, and each intervall will be downloaded one after the other to avoid a overfilling of the RAM. A to large intervall can still overflow the RAM """ if '_raw' in larchivepath: typo = np.uint16 @@ -985,12 +1291,36 @@ if fastDL: def download_raw_images_by_program_via_png(port, program, time_window=0, version=0, threads=1, testmode=False, verbose=0): """ + download of the raw images in png format instead of json for a given program. + number of threads can be defined to download several pngs in parallel + INPUT ------ - + port: integer + port number of the AEF port of the camera + program: string + program id in the form of 'YYYYMMDD.XXX', e.g. '20181016.016' + time_window: list, array, integer or float, optional, default 0 + if integer or float: size of the window in seconds from t1 + if list or array: start and endpoint of the window in seconds from t1 + if 0 the full program will be downloaded (t1 until t6) + version: integer, optional, default 0 + Version of the data in the archiveDB, in case of 0 the highest version will be used + threads: integer, default 1 + number of parallel threads to download the images + (approx. max. 2x number of cores and max. timeintervall/0.5 for best performance) + testmode: boolean, optional, default False + if True, the data will be loaded from the test archive + verbose: integer, optional, default 0 + feedback level (details of print messages) RESULT ------ - + exist: boolean + True if data was found, False if not + time: numpa array + an array containing the time stamp of each frame + frames: list + a list of frames, 2D numpy arrays NOTE ------ """ @@ -1025,12 +1355,38 @@ if fastDL: def download_images_by_time_via_png(larchivepath, starttime, stoptime, time_window=0, threads=1, version=0, verbose=0, framerate='max'): """ + download of the images in png format instead of json for a given timeintervall defined by start and stop time. + number of threads can be defined to download several pngs in parallel + INPUT ------ - + larchivepath: string + local archivepath, the URL to download the images + starttime: integer + time in ns where the search should start + stoptime: integer + time in sn where the search should end + time_window: list, array, integer or float, optional, default 0 + if integer or float: size of the window in seconds from t1 + if list or array: start and endpoint of the window in seconds from t1 + if 0 the full program will be downloaded (t1 until t6) + threads: integer, default 1 + number of parallel threads to download the images + (approx. max. 2x number of cores and max. timeintervall/0.5 for best performance) + version: integer, optional, default 0 + Version of the data in the archiveDB, in case of 0 the highest version will be used + verbose: integer, optional, default 0 + feedback level (details of print messages) + framerate: string or integer, optional, default 'max' + sets the framerate to downsample the data. normal rate is 100. RESULT ------ - + exist: boolean + True if data was found, False if not + time: numpa array + an array containing the time stamp of each frame + frames: list + a list of frames, 2D numpy arrays NOTE ------ """ @@ -1039,10 +1395,14 @@ if fastDL: tstart = time_window[0] tstop = time_window[1] if tstop < tstart: - raise Exception("download_images_by_time_via_png: t_stop before t_start") +# raise Exception("download_images_by_time_via_png: t_stop before t_start") + logging.warning("download_images_by_time_via_png: t_stop before t_start") + return False, [0], [0] time_from = (starttime-100)+int(tstart*1E9) if stoptime < time_from: - raise Exception("download_images_by_time_via_png: time_window after stoptime") +# raise Exception("download_images_by_time_via_png: time_window after stoptime") + logging.warning("download_images_by_time_via_png: time_window after stoptime") + return False, [0], [0] time_to = starttime+int(tstop*1E9) if stoptime < time_to: time_to = stoptime @@ -1070,8 +1430,9 @@ if fastDL: except Exception as E: # print('download_images_by_time_via_png: Error loading times from ', larchivepath, stdate.replace("T", " "), enddate.replace("T", " ")) print('download_images_by_time_via_png: Error loading times from {0} between [{1}, {2}]'.format(larchivepath, time_from, time_to)) - raise Warning(E) -# return False, [0], [0] +# raise Warning(E) + logging.warning(E) + return False, [0], [0] if framerate != 'max': if verbose > 5: @@ -1136,7 +1497,31 @@ if fastDL: class download_images_thread(threading.Thread): + """ + class for parallel download of images.\n + contains an init function and a run function + """ def __init__(self, threadID, larchivepath, times, resultlist, version=0): + """ + INPUT + ------ + theadID: integer + identification number of the thread + larchivepath: string + local archivepath, the URL to download the images + times: list + the timestamps of each frames for the download + resultlist: list + list which is returned after the thread is done + version: integer, optional, default 0 + Version of the data in the archiveDB, in case of 0 the highest version will be used + RESULT + ------ + resultlist: list + list containing the ID, exist, time and the images + NOTE + ------ + """ threading.Thread.__init__(self) self.threadID = threadID self.times = times @@ -1158,16 +1543,52 @@ if fastDL: self.resultlist.append([self.threadID, successes, time, images]) class convert_raw_to_temp_thread(threading.Thread): + """ + class for parallel download of images and parallel application the NUC and temperature conversion.\n + contains an init function and a run function + """ def __init__(self, larchivepath, times,resultlist, threadID, version=0, background=0, LUT=[[], [], []],refT=28.5, gain=0, offset=0, gain_error=0, offset_error=0, give_ERROR=False, FOV=0, badpixels=[], verbose=0): """ INPUT ------ - + larchivepath: string + local archivepath, the URL to download the images + times: list + the timestamps of each frames for the download + resultlist: list + list which is returned after the thread is done + theadID: integer + identification number of the thread + version: integer, optional, default 0 + Version of the data in the archiveDB, in case of 0 the highest version will be used + background: numpy array + background image + LUT: list + the look up table, containing the digital level, the temperature and the temperature error + refT: float + reference temperature for the calibration + gain: numpy array + the gain image from the calibration to convert the counts into digital level + offset: numpy array + the offset image from the calibration to convert the counts into digital level + gain_error: numpy array, optional + the gain error image from the calibration to calculate the error, needed if give_ERROR=True + offset_error: numpy array, optional + the offset error image from the calibration to calculate the error, needed if give_ERROR=True + give_ERROR: boolean + switch to activate the error calculation and returning of the error + FOV: numpy array + field of view image, with 1 in the visible region and 0 in the dark region + badpixels: list + list of the bad pixels for the corrections + verbose: integer, optional, default 0 + feedback level (details of print messages) RESULT ------ - + resultlist: list + list containing the ID, exist, time and the images NOTE ------ """ @@ -1192,10 +1613,11 @@ if fastDL: """ INPUT ------ - + same as init RESULT ------ - + resultlist: list + list containing the ID, exist, time and the images NOTE ------ """ @@ -1223,11 +1645,53 @@ if fastDL: self.resultlist.append([self.threadID, successes, time, images]) class NUC_raw_thread(threading.Thread): + """ + class for parallel calculation of nuced raw images + """ def __init__ (self, larchivepath, times,resultlist, threadID, version=0, background=0, LUT=[[], [], []],refT=28.5, gain=0, offset=0, gain_error=0, offset_error=0, give_ERROR=False, FOV=0, badpixels=[], verbose=0): """ - + INPUT + ------ + larchivepath: string + local archivepath, the URL to download the images + times: list + the timestamps of each frames for the download + resultlist: list + list which is returned after the thread is done + theadID: integer + identification number of the thread + version: integer, optional, default 0 + Version of the data in the archiveDB, in case of 0 the highest version will be used + background: numpy array + background image + LUT: list + the look up table, containing the digital level, the temperature and the temperature error + refT: float + reference temperature for the calibration + gain: numpy array + the gain image from the calibration to convert the counts into digital level + offset: numpy array + the offset image from the calibration to convert the counts into digital level + gain_error: numpy array, optional + the gain error image from the calibration to calculate the error, needed if give_ERROR=True + offset_error: numpy array, optional + the offset error image from the calibration to calculate the error, needed if give_ERROR=True + give_ERROR: boolean + switch to activate the error calculation and returning of the error + FOV: numpy array + field of view image, with 1 in the visible region and 0 in the dark region + badpixels: list + list of the bad pixels for the corrections + verbose: integer, optional, default 0 + feedback level (details of print messages) + RESULT + ------ + resultlist: list + list containing the ID, exist, time and the images + NOTE + ------ """ threading.Thread.__init__(self) self.threadID = threadID @@ -1279,12 +1743,40 @@ def download_raw_FLIR_images_via_png(t1, t6, time_window=0, version=0, threads=1 """ INPUT ------ - + t1: integer + nanoseconds timestamp of the t1 trigger, start of the heating + t6: integer + nanoseconds timestamp of the t6 trigger, end of the program + time_window: list, array, integer or float, optional, default 0 + if integer or float: size of the window in seconds from t1 + if list or array: start and endpoint of the window in seconds from t1 + if 0 the full program will be downloaded (t1 until t6) + version: integer, optional, default 0 + Version of the data in the archiveDB, in case of 0 the highest version will be used + threads: integer, default 1 + number of parallel threads to download the images + (approx. max. 2x number of cores and max. timeintervall/0.5 for best performance) + verbose: integer, optional, default 0 + feedback level (details of print messages) + testmode: boolean, optional, default True + if True, the data will be loaded from the test archive RESULT ------ - + exist: boolean + True if data was found, False if not + time: list + a list containing the time stamp of each frame + frames: list + a list of frames, 2D numpy arrays + mode: integer + kind of data structure,\n 1= pre-sets stored in different lists\n; 2=presets stored interlaced in one list + tsets: list + contains the information which frame belongs to which pre-set + versions: list + contains the informations of the version of each pre-set NOTE ------ + the FLIR camera is capable to run in superframing mode, recording frames with different exposure times in an interlaced mode. each exposure time frame is stored in a different file named after the pre-set """ if testmode: larchivepath=testarchivepath+project+"/QSR07_FLIR/AEK51_raw" @@ -1294,7 +1786,9 @@ def download_raw_FLIR_images_via_png(t1, t6, time_window=0, version=0, threads=1 tstart=time_window[0] tstop=time_window[1] if tstop<tstart: - raise Exception("download_raw_FLIR_images_via_png: t_stop before t_start") +# raise Exception("download_raw_FLIR_images_via_png: t_stop before t_start") + logging.warning("download_raw_FLIR_images_via_png: t_stop before t_start") + return False, [0], [0], 0, [0], [0] starttime=int(t1-100+tstart*1e9) stoptime=int(t1+tstop*1e9) # stdate=datetime.datetime.utcfromtimestamp((t1-100)/1e9+tstart) @@ -1330,7 +1824,9 @@ def download_raw_FLIR_images_via_png(t1, t6, time_window=0, version=0, threads=1 ### we not know the times for all presets for the program, now we have to download them, if times is not empty exist, time, frames, tsets=download_FLIR_Psets(larchivepath, timess, threads, versions, verbose=verbose-1) elif mode==2:##the data is stored only in one datastream, at least this datastream exist - raise Exception("download_raw_FLIR_images_via_png: not implemented") +# raise Exception("download_raw_FLIR_images_via_png: not implemented") + logging.warning("download_raw_FLIR_images_via_png: not implemented") + return False, [0], [0], 0, [0], [0] #download data and downlaod LUT # time=[] @@ -1347,18 +1843,34 @@ def download_raw_FLIR_images_via_png(t1, t6, time_window=0, version=0, threads=1 # success=False # return success, np.array(time), images else: - raise Exception("download_raw_FLIR_images_via_png: cannot identifie the way the searched data is stored!") +# raise Exception("download_raw_FLIR_images_via_png: cannot identifie the way the searched data is stored!") + logging.warning("download_raw_FLIR_images_via_png: cannot identifie the way the searched data is stored!") + return False, [0], [0], 0, [0], [0] return exist, time, frames,mode, tsets, versions def get_FLIR_Pset_times(stdate, enddate, version=0, verbose=0, testmode=True): """ + Download of the timevector for the different pre-sets of the recorded FLIR images + INPUT ------ - + stdate: integer + time in ns where the search should start + enddate: integer + time in sn where the search should end + version: integer, optional, default 0 + Version of the data in the archiveDB, in case of 0 the highest version will be used + verbose: integer, optional, default 0 + feedback level (details of print messages) + testmode: boolean, optional, default True + if True, the data will be loaded from the test archive RESULT ------ - + timess: list + timevectors of each pre-set + versions: list + list of the versions of each pre-set NOTE ------ """ @@ -1417,12 +1929,30 @@ def get_FLIR_Pset_times(stdate, enddate, version=0, verbose=0, testmode=True): def download_FLIR_Psets(larchivepath, timess, threads, versions, verbose=0): """ + Download of the FLIR datasets, which are stored as different datasets. Each dataset has a different exposure time + INPUT ------ - + larchivepath: string + local archivepath, the URL to download the images + timess: list + list of the timevectors for each pre-set (pset) + threads: integer, default 1 + number of parallel threads to download the images, one or two per pre-set + version: integer, optional, default 0 + Version of the data in the archiveDB, in case of 0 the highest version will be used + verbose: integer, optional, default 0 + feedback level (details of print messages) RESULT ------ - + exist: boolean + True if data was found, False if not + time: list + a list containing the time stamp of each frame + frames: list + a list of frames, 2D numpy arrays + tsets: list + contains the information which frames belong to which pre-set NOTE ------ """ @@ -1526,12 +2056,22 @@ def download_FLIR_Psets(larchivepath, timess, threads, versions, verbose=0): def download_last_raw_image_by_time(larchivepath, starttime, stoptime):#, version=0 """ + downloads for a given time intervall the image as png. it if always the last image in the intervall + INPUT ------ - + larchivepath: string + local archivepath, the URL to download the images + starttime: integer + time in ns where the search should start + stoptime: integer + time in sn where the search should end RESULT ------ - + exist: boolean + True if data was found, False if not + frame: list + a list of frame, 2D numpy array NOTE ------ """ @@ -1552,12 +2092,29 @@ def download_last_raw_image_by_time(larchivepath, starttime, stoptime):#, versio def download_raw_parlog_by_program(port, program, version=0, testmode=False, verbose=0): """ + download of the additional information for the raw data of the AEF cameras for a given program, which are stored in the parlog. contains information as frame width, height bitdepth. + INPUT ------ + port: integer + port number of the AEF port of the camera + program: string + program id in the form of 'YYYYMMDD.XXX', e.g. '20181016.016' + version: integer, optional, default 0 + Version of the data in the archiveDB, in case of 0 the highest version will be used + testmode: boolean, optional, default False + if True, the data will be loaded from the test archive + verbose: integer, optional, default 0 + feedback level (details of print messages) RESULT ------ - + exist: boolean + True if data was found, False if not + time: list + a list containing the time stamp of the parlog (from to) + meta-data: dictionary/list + the meta-data from the parlog converted from JSON NOTE ------ """ @@ -1577,12 +2134,31 @@ def download_raw_parlog_by_program(port, program, version=0, testmode=False, ver def download_raw_parlog_by_times(port, starttime, stoptime, version=0, testmode=False): """ + download of the additional information for the raw data of the AEF cameras for a given time intervall, which are stored in the parlog. contains information as frame width, height bitdepth. + INPUT ------ + port: integer + port number of the AEF port of the camera + starttime: integer + time in ns where the search should start + stoptime: integer + time in sn where the search should end + version: integer, optional, default 0 + Version of the data in the archiveDB, in case of 0 the highest version will be used + testmode: boolean, optional, default False + if True, the data will be loaded from the test archive + verbose: integer, optional, default 0 + feedback level (details of print messages) RESULT ------ - + exist: boolean + True if data was found, False if not + time: list + a list containing the time stamp of the parlog (from to) + meta-data: dictionary/list + the meta-data from the parlog converted from JSON NOTE ------ """ @@ -1612,12 +2188,28 @@ def download_raw_parlog_by_times(port, starttime, stoptime, version=0, testmode= def get_INFRATEC_filter_by_program(program, port=50, version=0, testmode=False, verbose=0): """ + downlods the information of the used filter of the INFRATEC camera for a given program + INPUT ------ - + program: string + program id in the form of 'YYYYMMDD.XXX', e.g. '20181016.016' + port: integer, optional, default 50 + port number of the AEF port of the camera + version: integer, optional, default 0 + Version of the data in the archiveDB, in case of 0 the highest version will be used + testmode: boolean, optional, default False + if True, the data will be loaded from the test archive + verbose: integer, optional, default 0 + feedback level (details of print messages) RESULT ------ - + exist: boolean + True if data was found, False if not + time: list + a list containing the time stamp of the parlog (from to) + filter: integer + the number of the used filter NOTE ------ """ @@ -1637,12 +2229,30 @@ def get_INFRATEC_filter_by_program(program, port=50, version=0, testmode=False, def get_INFRATEC_filter_by_times(starttime, stoptime, port=50, version=0, testmode=False): """ + Idownlods the information of the used filter of the INFRATEC camera for a given time intervall + INPUT ------ - + starttime: integer + time in ns where the search should start + stoptime: integer + time in sn where the search should end + port: integer, optional, default 50 + port number of the AEF port of the camera + version: integer, optional, default 0 + Version of the data in the archiveDB, in case of 0 the highest version will be used + testmode: boolean, optional, default False + if True, the data will be loaded from the test archive + verbose: integer, optional, default 0 + feedback level (details of print messages) RESULT ------ - + exist: boolean + True if data was found, False if not + time: list + a list containing the time stamp of the parlog (from to) + filter: integer + the number of the used filter NOTE ------ """ @@ -1672,12 +2282,29 @@ def get_INFRATEC_filter_by_times(starttime, stoptime, port=50, version=0, testmo def get_exposure_by_program(port, program, version=0, testmode=False, verbose=0): """ + download the exposure time for a given camera and program for each frame + INPUT ------ + port: integer + port number of the AEF port of the camera + program: string + program id in the form of 'YYYYMMDD.XXX', e.g. '20181016.016' + version: integer, optional, default 0 + Version of the data in the archiveDB, in case of 0 the highest version will be used + testmode: boolean, optional, default False + if True, the data will be loaded from the test archive + verbose: integer, optional, default 0 + feedback level (details of print messages) RESULT ------ - + exist: boolean + True if data was found, False if not + time: list + a list containing the time stamp of each frame + exposure time: list + the exposure time of the camera for each frame NOTE ------ """ @@ -1698,12 +2325,28 @@ def get_exposure_by_program(port, program, version=0, testmode=False, verbose=0) def get_exposure_by_times(port, starttime, stoptime, version=0, testmode=False): """ + download the exposure time for a given camera and each frame in a given time intervall + INPUT ------ - + port: integer + port number of the AEF port of the camera + starttime: integer + time in ns where the search should start + stoptime: integer + time in sn where the search should end + version: integer, optional, default 0 + Version of the data in the archiveDB, in case of 0 the highest version will be used + testmode: boolean, optional, default False + if True, the data will be loaded from the test archive RESULT ------ - + exist: boolean + True if data was found, False if not + time: list + a list containing the time stamp of each frame + exposure time: list + the exposure time of the camera for each frame NOTE ------ """ @@ -1719,12 +2362,29 @@ def get_exposure_by_times(port, starttime, stoptime, version=0, testmode=False): def get_camera_temp_by_program(port, program, version=0, testmode=False, verbose=0): """ + download the camera temperature for a given camera and program for each frame + INPUT ------ + port: integer + port number of the AEF port of the camera + program: string + program id in the form of 'YYYYMMDD.XXX', e.g. '20181016.016' + version: integer, optional, default 0 + Version of the data in the archiveDB, in case of 0 the highest version will be used + testmode: boolean, optional, default False + if True, the data will be loaded from the test archive + verbose: integer, optional, default 0 + feedback level (details of print messages) RESULT ------ - + exist: boolean + True if data was found, False if not + time: list + a list containing the time stamp of each frame + temperature: list + the temperature of the camera for each frame NOTE ------ """ @@ -1744,14 +2404,30 @@ def get_camera_temp_by_program(port, program, version=0, testmode=False, verbose def get_camera_temp_by_times(port, starttime, stoptime, version=0, testmode=False): """ + download the camera temperature for a given camera and each frame in a given time intervall + INPUT ------ - + port: integer + port number of the AEF port of the camera + starttime: integer + time in ns where the search should start + stoptime: integer + time in sn where the search should end + version: integer, optional, default 0 + Version of the data in the archiveDB, in case of 0 the highest version will be used + testmode: boolean, optional, default False + if True, the data will be loaded from the test archive RESULT ------ - + exist: boolean + True if data was found, False if not + time: list + a list containing the time stamp of each frame + temperature: list + the temperature of the camera for each frame NOTE - ------ + ----- """ OP = IR_tools.get_OP_by_time(time_ns=stoptime) stream=portpathdict[OP]["AEF"+str(port)]+"meta_" @@ -1769,12 +2445,29 @@ def get_camera_temp_by_times(port, starttime, stoptime, version=0, testmode=Fals def get_sensor_temp_by_program(port, program, version=0, testmode=False, verbose=0): """ + download the sensor temperature for a given camera and program for each frame + INPUT ------ + port: integer + port number of the AEF port of the camera + program: string + program id in the form of 'YYYYMMDD.XXX', e.g. '20181016.016' + version: integer, optional, default 0 + Version of the data in the archiveDB, in case of 0 the highest version will be used + testmode: boolean, optional, default False + if True, the data will be loaded from the test archive + verbose: integer, optional, default 0 + feedback level (details of print messages) RESULT ------ - + exist: boolean + True if data was found, False if not + time: list + a list containing the time stamp of each frame + temperature: list + the temperature of the camera sensor for each frame NOTE ------ """ @@ -1794,14 +2487,30 @@ def get_sensor_temp_by_program(port, program, version=0, testmode=False, verbose def get_sensor_temp_by_times(port, starttime, stoptime, version=0, testmode=False): """ + download the sensor temperature for a given camera and each frame in a given time intervall + INPUT ------ - + port: integer + port number of the AEF port of the camera + starttime: integer + time in ns where the search should start + stoptime: integer + time in sn where the search should end + version: integer, optional, default 0 + Version of the data in the archiveDB, in case of 0 the highest version will be used + testmode: boolean, optional, default False + if True, the data will be loaded from the test archive RESULT ------ - + exist: boolean + True if data was found, False if not + time: list + a list containing the time stamp of each frame + temperature: list + the temperature of the camera sensor for each frame NOTE - ------ + ----- """ OP = IR_tools.get_OP_by_time(time_ns=stoptime) stream=portpathdict[OP]["AEF"+str(port)]+"meta_" @@ -1815,12 +2524,29 @@ def get_sensor_temp_by_times(port, starttime, stoptime, version=0, testmode=Fals def get_camera_framerate_by_program(port, program, version=0, testmode=False, verbose=0): """ + download the framerate for a given camera and program for each frame + INPUT ------ + port: integer + port number of the AEF port of the camera + program: string + program id in the form of 'YYYYMMDD.XXX', e.g. '20181016.016' + version: integer, optional, default 0 + Version of the data in the archiveDB, in case of 0 the highest version will be used + testmode: boolean, optional, default False + if True, the data will be loaded from the test archive + verbose: integer, optional, default 0 + feedback level (details of print messages) RESULT ------ - + exist: boolean + True if data was found, False if not + time: list + a list containing the time stamp of each frame + framerate: list + the framerate of the camera for each frame NOTE ------ """ @@ -1841,14 +2567,30 @@ def get_camera_framerate_by_program(port, program, version=0, testmode=False, ve def get_camera_framerate_by_times(port, starttime, stoptime, version=0, testmode=False): """ + download the framerate for a given camera and each frame in a given time intervall + INPUT ------ - + port: integer + port number of the AEF port of the camera + starttime: integer + time in ns where the search should start + stoptime: integer + time in sn where the search should end + version: integer, optional, default 0 + Version of the data in the archiveDB, in case of 0 the highest version will be used + testmode: boolean, optional, default False + if True, the data will be loaded from the test archive RESULT ------ - + exist: boolean + True if data was found, False if not + time: list + a list containing the time stamp of each frame + framerate: list + the framerate of the camera for each frame NOTE - ------ + ----- """ OP = IR_tools.get_OP_by_time(time_ns=stoptime) stream=portpathdict[OP]["AEF"+str(port)]+"meta_" @@ -1863,12 +2605,29 @@ def get_camera_framerate_by_times(port, starttime, stoptime, version=0, testmode def get_frametype_by_program(port, program, version=0, testmode=False, verbose=0): """ + download the frametype for a given camera and program for each frame + INPUT ------ + port: integer + port number of the AEF port of the camera + program: string + program id in the form of 'YYYYMMDD.XXX', e.g. '20181016.016' + version: integer, optional, default 0 + Version of the data in the archiveDB, in case of 0 the highest version will be used + testmode: boolean, optional, default False + if True, the data will be loaded from the test archive + verbose: integer, optional, default 0 + feedback level (details of print messages) RESULT ------ - + exist: boolean + True if data was found, False if not + time: list + a list containing the time stamp of each frame + frametype: list + the frametype of the camera for each frame NOTE ------ """ @@ -1888,14 +2647,30 @@ def get_frametype_by_program(port, program, version=0, testmode=False, verbose=0 def get_frametype_by_times(port, starttime, stoptime, version=0, testmode=False): """ + download the frametyp for a given camera and each frame in a given time intervall + INPUT ------ - + port: integer + port number of the AEF port of the camera + starttime: integer + time in ns where the search should start + stoptime: integer + time in sn where the search should end + version: integer, optional, default 0 + Version of the data in the archiveDB, in case of 0 the highest version will be used + testmode: boolean, optional, default False + if True, the data will be loaded from the test archive RESULT ------ - + exist: boolean + True if data was found, False if not + time: list + a list containing the time stamp of each frame + frametype: list + the frametype of the camera for each frame NOTE - ------ + ----- """ OP = IR_tools.get_OP_by_time(time_ns=starttime) stream=portpathdict[OP]["AEF"+str(port)]+"meta_" @@ -1909,12 +2684,29 @@ def get_frametype_by_times(port, starttime, stoptime, version=0, testmode=False) def get_framenumber_by_program(port, program, version=0, testmode=False, verbose=0): """ + download the framenumber for a given camera and program for each frame + INPUT ------ + port: integer + port number of the AEF port of the camera + program: string + program id in the form of 'YYYYMMDD.XXX', e.g. '20181016.016' + version: integer, optional, default 0 + Version of the data in the archiveDB, in case of 0 the highest version will be used + testmode: boolean, optional, default False + if True, the data will be loaded from the test archive + verbose: integer, optional, default 0 + feedback level (details of print messages) RESULT ------ - + exist: boolean + True if data was found, False if not + time: list + a list containing the time stamp of each frame + framenumber: list + the framenumber of the camera for each frame NOTE ------ """ @@ -1934,14 +2726,30 @@ def get_framenumber_by_program(port, program, version=0, testmode=False, verbose def get_framenumber_by_times(port, starttime, stoptime, version=0, testmode=False): """ + download the framenumber for a given camera and each frame in a given time intervall + INPUT ------ - + port: integer + port number of the AEF port of the camera + starttime: integer + time in ns where the search should start + stoptime: integer + time in sn where the search should end + version: integer, optional, default 0 + Version of the data in the archiveDB, in case of 0 the highest version will be used + testmode: boolean, optional, default False + if True, the data will be loaded from the test archive RESULT ------ - + exist: boolean + True if data was found, False if not + time: list + a list containing the time stamp of each frame + framenumber: list + the framenumber of the camera for each frame NOTE - ------ + ----- """ OP = IR_tools.get_OP_by_time(time_ns=starttime) stream=portpathdict[OP]["AEF"+str(port)]+"meta_" @@ -1955,12 +2763,30 @@ def get_framenumber_by_times(port, starttime, stoptime, version=0, testmode=Fals def get_average_divertor_TC_for_camtemp(port, starttime, stoptime, part="all", TC=0): """ + download of an mean divertor temperature measured by the thermocouples in the divertor with respect to a camera observing this divertor + INPUT ------ - + port: integer + port number of the AEF port of the camera + starttime: integer + time in ns where the search should start + stoptime: integer + time in sn where the search should end + part: string or integer, optional, default "all" + defines the divertor region for the evaluation of the thermocouples (TC)\n + options are 'h' (horizontal), 'v' (vertical), 'hli' (horizontal low iota), 'hhi' (horizontal high iota) 's' or 'single' for only one TC\n + if it is a number, one thermocouple will be used, as counted from low to high iota region(7), going from 0 to 10, 8-10 vor vertical + TC: integer, optional, only for part 's' + TC number if part is 'single' or 's' RESULT ------ - + exist: boolean + True if data was found, False if not + time: list + a list containing the time stamp of each temperature + temperature: list + averaged TC temperature for each timestamp in time NOTE ------ """ @@ -1976,8 +2802,10 @@ def get_average_divertor_TC_for_camtemp(port, starttime, stoptime, part="all", T portnr=port+1 offset=(port//10-1)*32+16 else: - print("get_average_divertor_TC_for_camtemp: Error! unknown port") - raise Exception + #print("get_average_divertor_TC_for_camtemp: Error! unknown port") + #raise Exception + logging.warning("get_average_divertor_TC_for_camtemp: Error! unknown port") + return False, [0], [0] if portnr==50: offset=0 elif portnr==51: @@ -2045,12 +2873,18 @@ def get_average_divertor_TC_for_camtemp(port, starttime, stoptime, part="all", T def get_divertor_TC_coordinate(cameraport, TC=0): """ + returns the information of the thermocouple + INPUT ------ - + cameraport: integer + port number of the AEF port of the camera + TC: integer, default is 0 + TC number going from 0 to 10 RESULT ------ - + TC_info: dictionary + contains x,y,z information and in which target it is located NOTE ------ """ @@ -2065,13 +2899,28 @@ def get_divertor_TC_coordinate(cameraport, TC=0): def get_TC_data_for_port_by_program(port, program, part=0, version=0, verbose=0): """ + download the thermocouple (TC) data for a thermocouple in the port (immersion tube or endoscope) + INPUT ------ + port: integer + port number of the AEF port of the camera + program: string + program id in the form of 'YYYYMMDD.XXX', e.g. '20181016.016' + part: integer, default 0 + 0 or the number of the TC in the port + version: integer, optional, default 0 + Version of the data in the archiveDB, in case of 0 the highest version will be used verbose: integer, optional, default 0 feedback level (details of print messages) RESULT ------ - + exist: boolean + True if data was found, False if not + time: list + a list containing the time stamp of each frame + temperature: list + temperature from the TC for each time stamp in time NOTE ------ """ @@ -2091,11 +2940,30 @@ def get_TC_data_for_port_by_program(port, program, part=0, version=0, verbose=0) def get_TC_data_for_port(port, starttime, stoptime, part=0):#, version=0 """ + download the thermocouple (TC) data for a thermocouple in the port (immersion tube or endoscope) + INPUT ------ - + port: integer + port number of the AEF port of the camera + starttime: integer + time in ns where the search should start + stoptime: integer + time in sn where the search should end + part: integer, default 0 + 0 or the number of the TC in the port + version: integer, optional, default 0 + Version of the data in the archiveDB, in case of 0 the highest version will be used + verbose: integer, optional, default 0 + feedback level (details of print messages) RESULT ------ + exist: boolean + True if data was found, False if not + time: list + a list containing the time stamp of each frame + temperature: list + temperature from the TC for each time stamp in time NOTE ------ @@ -2159,12 +3027,18 @@ def get_TC_data_for_port(port, starttime, stoptime, part=0):#, version=0 def temp_from_LUT(LUT, images): """ + apply the look up table(LUT) onto images to get temperature images + INPUT ------ - + LUT: list + list in the form [Temperaure,temperature_error] + images: list + the frames as a list of 2D numpy arrays RESULT ------ - + images: list + list of numpy arrays NOTE ------ """ @@ -2172,12 +3046,18 @@ def temp_from_LUT(LUT, images): def terror_from_LUT(LUT, images): """ + apply the look up table(LUT) onto images to get temperature error images + INPUT ------ - + LUT: list + list in the form [Temperaure,temperature_error] + images: list + the frames as a list of 2D numpy arrays RESULT ------ - + images: list + list of numpy arrays NOTE ------ """ @@ -2187,12 +3067,25 @@ def check_temperature_range(time,maxvalue_C,minvalue_C, port, exposure, cfilter= """ INPUT ------ - + time: integer + nanosecond time stamp to identify the right camera + maxvalue_C: float or integer + the maximum value in the data + minvalue_C: float or integer + the minimum value in the data + port: integer + port number of the AEF port of the camera + exposure: integer + exposure time in microseconds + cfilter: integer, optional, default 0 + the filter for the infratec camera + RESULT ------ - + no return NOTE ------ + not fully functional and slow! """ try: cam=portcamdict[IR_tools.get_OP_by_time(time_ns=time)]['AEF'+str(port)] @@ -2218,13 +3111,43 @@ def check_temperature_range(time,maxvalue_C,minvalue_C, port, exposure, cfilter= def get_temp_from_raw_by_program_V1(portnr, program, time_window=0, emi=0.8,divertorpart="all", version=0, intervalSize=1E9, give_ERROR=False, testmode=False, verbose=0): """ + downloads the raw data of the cameras, the calibration and applies it to the data to deliver the temperature data + This function is outdated + INPUT ------ + portnr: integer + port number of the AEF port of the camera + program: string + program id in the form of 'YYYYMMDD.XXX', e.g. '20181016.016' + time_window: list, array, integer or float, optional, default 0 + if integer or float: size of the window in seconds from t1 + if list or array: start and endpoint of the window in seconds from t1 + if 0 the full program will be downloaded (t1 until t6) + emi: float, optional, default 0.8 + the emissivity value for the calibration + divertorpart, optional, default "all" + the region of the divertor, which should be used as the reference temperature + version: integer, optional, default 0 + Version of the data in the archiveDB, in case of 0 the highest version will be used + intervalSize: integer, optional, default 1e9 (1 second) + size of the intervall to be downloaded in nanoseconds + give_ERROR: boolean, optional default False + switch to turn on the return of error images + testmode: boolean, optional, default False + if True, the data will be loaded from the test archive verbose: integer, optional, default 0 feedback level (details of print messages) RESULT ------ - + exist: boolean + True if data was found, False if not + time: list + a list containing the time stamp of each frame + frames: list + a list of frames, 2D numpy arrays + optional: error_frames: list + a list of frames, 2D numpy arrays NOTE ------ """ @@ -2248,7 +3171,9 @@ def get_temp_from_raw_by_program_V1(portnr, program, time_window=0, emi=0.8,dive tstart=time_window[0] tstop=time_window[1] if tstop<tstart: - raise Exception("get_temp_from_raw_by_program_V1: t_stop before t_start") +# raise Exception("get_temp_from_raw_by_program_V1: t_stop before t_start") + logging.warning("get_temp_from_raw_by_program_V1: t_stop before t_start") + return False, [0], [0] stoptime=int(starttime+tstop*1e9) starttime=int(starttime+tstart*1e9) else: @@ -2283,7 +3208,9 @@ def get_temp_from_raw_by_program_V1(portnr, program, time_window=0, emi=0.8,dive times=times+time del time, images else: - raise Exception("get_temp_from_raw_by_program_V1: cannot download the raw images") +# raise Exception("get_temp_from_raw_by_program_V1: cannot download the raw images") + logging.warning("get_temp_from_raw_by_program_V1: cannot download the raw images") + return False, [0], [0] else: raw_dl=download_raw_images_by_times(portnr, starttime, stoptime, version, intervalSize, testmode=testmode, verbose=verbose-1) if raw_dl[0]: @@ -2316,13 +3243,41 @@ def get_temp_from_raw_by_program_V2(portnr, program, time_window=0, emi=0.8, ver threads=1, give_ERROR=False,use_firstframe_as_background=False, verbose=0): """ + downloads the raw data of the cameras, the calibration and applies it to the data to deliver the temperature data + INPUT ------ + portnr: integer + port number of the AEF port of the camera + program: string + program id in the form of 'YYYYMMDD.XXX', e.g. '20181016.016' + time_window: list, array, integer or float, optional, default 0 + if integer or float: size of the window in seconds from t1 + if list or array: start and endpoint of the window in seconds from t1 + if 0 the full program will be downloaded (t1 until t6) + emi: float, optional, default 0.8 + the emissivity value for the calibration + version: integer, optional, default 0 + Version of the data in the archiveDB, in case of 0 the highest version will be used + threads: integer, optional, default 1 + number of parallel threads to download the images + (approx. max. 2x number of cores and max. timeintervall/0.5 for best performance) + give_ERROR: boolean, optional default False + switch to turn on the return of error images + use_firstframe_as_background: boolean + in case the background frames are not available, the first frame can be used verbose: integer, optional, default 0 feedback level (details of print messages) RESULT ------ - + exist: boolean + True if data was found, False if not + time: list + a list containing the time stamp of each frame + frames: list + a list of frames, 2D numpy arrays + optional: error_frames: list + a list of frames, 2D numpy arrays NOTE ------ """ @@ -2337,20 +3292,59 @@ def get_temp_from_raw_by_program(portnr, program, time_window=0, emi=0.8, T_vers use_firstframe_as_background=False, back_emissivity=0.8, verbose=0, testmode=False, framerate='max'): """ + downloads the raw data of the cameras, the calibration and applies it to the data to deliver the temperature data + several threads can be used to download in parallel the data + INPUT ------ + portnr: integer + port number of the AEF port of the camera + program: string + program id in the form of 'YYYYMMDD.XXX', e.g. '20181016.016' + time_window: list, array, integer or float, optional, default 0 + if integer or float: size of the window in seconds from t1 + if list or array: start and endpoint of the window in seconds from t1 + if 0 the full program will be downloaded (t1 until t6) + emi: float, optional, default 0.8 + the emissivity value for the calibration + T_version: integer, default 2 + set the version of the calibration method, see more on the QRT wiki + version: integer, optional, default 0 + Version of the data in the archiveDB, in case of 0 the highest version will be used + threads: integer, optional, default 1 + number of parallel threads to download the images + (approx. max. 2x number of cores and max. timeintervall/0.5 for best performance) + give_ERROR: boolean, optional default False + switch to turn on the return of error images + use_firstframe_as_background: boolean + in case the background frames are not available, the first frame can be used + back_emissivity: float, optional, default 0.8 + set the emissivity value for the background region for the calibration verbose: integer, optional, default 0 feedback level (details of print messages) + testmode: boolean, optional, default False + if True, the data will be loaded from the test archive + framerate: string or integer, optional, default 'max' + sets the framerate to downsample the data. normal rate is 100. RESULT ------ - + exist: boolean + True if data was found, False if not + time: list + a list containing the time stamp of each frame + frames: list + a list of frames, 2D numpy arrays, values are in Kelvin + optional: error_frames: list + a list of frames, 2D numpy arrays NOTE ------ """ FLIR=False trigger_exist, t0, t1, t6 = get_trigger_from_PID(program, portnr, testmode, verbose=verbose-1) if not trigger_exist: - raise Exception("get_temp_from_raw_by_program: unknown Program") +# raise Exception("get_temp_from_raw_by_program: unknown Program") + logging.warning("get_temp_from_raw_by_program: unknown Program") + return False, [0], [0] success=True OP = IR_tools.get_OP_by_time(time_ns=t1) @@ -2372,8 +3366,9 @@ def get_temp_from_raw_by_program(portnr, program, time_window=0, emi=0.8, T_vers FLIR=False portnr=int(portnr) else: - raise Exception("get_temp_from_raw_by_program: the given port is neither a number or a valid String!") - +# raise Exception("get_temp_from_raw_by_program: the given port is neither a number or a valid String!") + logging.warning("get_temp_from_raw_by_program: the given port is neither a number or a valid String!") + return False, [0], [0] if FLIR: # --- Glens FLIR camera --- # @@ -2479,7 +3474,8 @@ def get_temp_from_raw_by_program(portnr, program, time_window=0, emi=0.8, T_vers if exist: frames = [im.swapaxes(0,1) for im in frames] if not exist: - raise Warning("get_temp_from_raw_by_program: data not found in database!") +# raise Warning("get_temp_from_raw_by_program: data not found in database!") + logging.warning("get_temp_from_raw_by_program: data not found in database!") return False, [0], [0], False if verbose > 0: print(datetime.datetime.now(), "get_temp_from_raw_by_program: raw download finished") @@ -2537,13 +3533,45 @@ def get_temp_from_raw_by_program_fullthreads(portnr, program, time_window=0, emi give_ERROR=False, check_range=True, testmode=False, verbose=0): """ + downloads the raw data and converting it to temeprature images + INPUT ------ + portnr: integer + port number of the AEF port of the camera + program: string + program id in the form of 'YYYYMMDD.XXX', e.g. '20181016.016' + time_window: list, array, integer or float, optional, default 0 + if integer or float: size of the window in seconds from t1 + if list or array: start and endpoint of the window in seconds from t1 + if 0 the full program will be downloaded (t1 until t6) + emi: float, optional, default 0.8 + the emissivity value for the calibration + T_version: integer, default 2 + set the version of the calibration method, see more on the QRT wiki + version: integer, optional, default 0 + Version of the data in the archiveDB, in case of 0 the highest version will be used + threads: integer, optional, default 1 + number of parallel threads to download the images + (approx. max. 2x number of cores and max. timeintervall/0.5 for best performance) + give_ERROR: boolean, optional default False + switch to turn on the return of error images + check_range: boolean, optional, default True + switch to turn the temperature range check on or off + testmode: boolean, optional, default False + if True, the data will be loaded from the test archive verbose: integer, optional, default 0 - feedback level (details of print messages) + feedback level (details of print messages) RESULT ------ - + exist: boolean + True if data was found, False if not + time: list + a list containing the time stamp of each frame + frames: list + a list of frames, 2D numpy arrays, values are in Kelvin + optional: error_frames: list + a list of frames, 2D numpy arrays NOTE ------ """ @@ -2563,7 +3591,10 @@ def get_temp_from_raw_by_program_fullthreads(portnr, program, time_window=0, emi portnr=int(portnr.split("AEF")[1]) goon=True except Exception as E: - raise Exception("get_temp_from_raw_by_program_fullthreads: unknown Port!"+E) +# raise Exception("get_temp_from_raw_by_program_fullthreads: unknown Port!"+E) + logging.warning("get_temp_from_raw_by_program_fullthreads: unknown Port!"+E) + return False, [0], [0] + elif type(portnr) is int: FLIR = False goon = True @@ -2591,7 +3622,9 @@ def get_temp_from_raw_by_program_fullthreads(portnr, program, time_window=0, emi tstart = time_window[0] tstop = time_window[1] if tstop < tstart: - raise Exception("get_temp_from_raw_by_program_fullthreads: t_stop before t_start") +# raise Exception("get_temp_from_raw_by_program_fullthreads: t_stop before t_start") + logging.warning("get_temp_from_raw_by_program_fullthreads: t_stop before t_start") + return False, [0], [0] stdate = datetime.datetime.utcfromtimestamp((starttime-100)/1e9+tstart) stdate = stdate.isoformat() enddate = datetime.datetime.utcfromtimestamp((starttime)/1e9+tstop) @@ -2672,13 +3705,45 @@ def get_nuced_raw_by_program(portnr, program, time_window=0,version=0, emi=1, T_version=2, threads=1, give_ERROR=False, testmode=False, verbose=0): """ + download the raw data and applies the non uniformity correction to make the image understandable + INPUT ------ + portnr: integer + port number of the AEF port of the camera + program: string + program id in the form of 'YYYYMMDD.XXX', e.g. '20181016.016' + time_window: list, array, integer or float, optional, default 0 + if integer or float: size of the window in seconds from t1 + if list or array: start and endpoint of the window in seconds from t1 + if 0 the full program will be downloaded (t1 until t6) + version: integer, optional, default 0 + Version of the data in the archiveDB, in case of 0 the highest version will be used + emi: float, optional, default 0.8 + the emissivity value for the calibration + T_version: integer, default 2 + set the version of the calibration method, see more on the QRT wiki + threads: integer, default 1 + number of parallel threads to download the images + (approx. max. 2x number of cores and max. timeintervall/0.5 for best performance) + give_ERROR: boolean, optional default False + switch to turn on the return of error images + testmode: boolean, optional, default False + if True, the data will be loaded from the test archive verbose: integer, optional, default 0 feedback level (details of print messages) RESULT ------ - + exist: boolean + True if data was found, False if not + time: list + a list containing the time stamp of each frame + frames: list + a list of frames, 2D numpy arrays + valid: boolean + status wheather the data can be used + optional frames_error: list + a list of frames, 2D numpy arrays NOTE ------ """ @@ -2694,7 +3759,9 @@ def get_nuced_raw_by_program(portnr, program, time_window=0,version=0, if exist: frames=[im.swapaxes(0,1) for im in frames] else: - raise Exception("get_nuced_raw_by_program: no data found") +# raise Exception("get_nuced_raw_by_program: no data found") + logging.warning("get_nuced_raw_by_program: no data found") + return False, [0], [0], False if verbose > 0: print(datetime.datetime.now(), "get_nuced_raw_by_program: raw download finished") FOV=get_FOV_mask(portnr) @@ -2722,13 +3789,45 @@ def get_nuced_raw_by_program_fullthreads(portnr, program, time_window=0, emi=0.8 give_ERROR=False, check_range=True, testmode=False, verbose=0): """ + download the raw data and applies the non uniformity correction to make the image understandable by using threads for all steps + INPUT ------ + portnr: integer + port number of the AEF port of the camera + program: string + program id in the form of 'YYYYMMDD.XXX', e.g. '20181016.016' + time_window: list, array, integer or float, optional, default 0 + if integer or float: size of the window in seconds from t1 + if list or array: start and endpoint of the window in seconds from t1 + if 0 the full program will be downloaded (t1 until t6) + emi: float, optional, default 0.8 + the emissivity value for the calibration + T_version: integer, default 2 + set the version of the calibration method, see more on the QRT wiki + version: integer, optional, default 0 + Version of the data in the archiveDB, in case of 0 the highest version will be used + threads: integer, default 1 + number of parallel threads to download the images + (approx. max. 2x number of cores and max. timeintervall/0.5 for best performance) + give_ERROR: boolean, optional default False + switch to turn on the return of error images + testmode: boolean, optional, default False + if True, the data will be loaded from the test archive verbose: integer, optional, default 0 feedback level (details of print messages) RESULT ------ - + exist: boolean + True if data was found, False if not + time: list + a list containing the time stamp of each frame + frames: list + a list of frames, 2D numpy arrays + valid: boolean + status wheather the data can be used + optional frames_error: list + a list of frames, 2D numpy arrays NOTE ------ """ @@ -2764,7 +3863,9 @@ def get_nuced_raw_by_program_fullthreads(portnr, program, time_window=0, emi=0.8 tstart = time_window[0] tstop = time_window[1] if tstop < tstart: - raise Exception("get_nuced_raw_by_program_fullthreads: t_stop before t_start") +# raise Exception("get_nuced_raw_by_program_fullthreads: t_stop before t_start") + logging.warning("get_nuced_raw_by_program_fullthreads: t_stop before t_start") + return False, [0], [0], False stdate = datetime.datetime.utcfromtimestamp((starttime-100)/1e9+tstart) stdate = stdate.isoformat() enddate = datetime.datetime.utcfromtimestamp((starttime)/1e9+tstop) @@ -2832,16 +3933,41 @@ def get_nuced_raw_by_program_fullthreads(portnr, program, time_window=0, emi=0.8 def apply_calib_on_raw(images, background, LUT,refT=28.5, gain=0, offset=0, gain_error=0, offset_error=0, fullbackground=False, give_ERROR=False, verbose=0): """ - apply_calib_on_raw - return success, images and if give_Error: errorimages + + applies the calibration onto the given raw images and return the temperature images INPUT ------ + images: list + a list of frames, 2D numpy arrays + background: integer or 2D array + the value of the background for calibration, which get subtracted from the images + LUT: list + list or array containing the look up table in the form of [[DL],[temperature],[error]] + refT: float, default 28.5 + reference temperature in degree celcius of the background + gain: numpy array + the gain image from the calibration to convert the counts into digital level + offset: numpy array + the offset image from the calibration to convert the counts into digital level + gain_error: numpy array + the gain error image from the calibration to convert the counts into digital level + offset_error: numpy array + the offset error image from the calibration to convert the counts into digital level + fullbackground: boolean, default False + switch to set the treatment of the backgroun input + give_ERROR: boolean, optional default False + switch to turn on the return of error images verbose: integer, optional, default 0 feedback level (details of print messages) RESULT ------ - + exist: boolean + True if data was found, False if not + frames: list + a list of frames, 2D numpy arrays, values are in Kelvin + optional frames_error: list + a list of frames, 2D numpy arrays NOTE ------ """ @@ -2894,20 +4020,37 @@ def apply_calib_on_raw(images, background, LUT,refT=28.5, gain=0, offset=0, gain images[i]=(images[i]+(refT+273.15)).astype(np.float32) return True, images except Exception as E: - raise Warning('apply_calib_on_raw: '+E) -# return False, [0] +# raise Warning('apply_calib_on_raw: '+E) + logging.warning('apply_calib_on_raw: '+E) + return False, [0] def apply_NUC(images, gain, offset, gain_error=0, offset_error=0, give_error=False): """ apply_NUC(images=numpy array(time,width,height), gain, offset =numpy array(width,height) ) + applies the non-uniformity correction onto the given raw images + INPUT ------ + frames: list + a list of frames, 2D numpy arrays + gain: numpy array + the gain image from the calibration to convert the counts into digital level + offset: numpy array + the offset image from the calibration to convert the counts into digital level + gain_error: numpy array + the gain error image from the calibration to convert the counts into digital level + offset_error: numpy array + the offset error image from the calibration to convert the counts into digital level + give_error RESULT ------ - + frames: list + a list of frames, 2D numpy arrays + optional frames_error: list + a list of frames, 2D numpy arrays NOTE ------ """ @@ -2930,12 +4073,20 @@ def apply_NUC(images, gain, offset, gain_error=0, offset_error=0, give_error=Fal def get_cooling_water_temperature_by_time(time_ns): """ + downloads the information of the water temperture in the cooling cycle of W7-X + INPUT ------ - + time_ns: integer + nanosecond time stamp to identify the time window RESULT ------ - + exist: boolean + True if data was found, False if not + inlet: float + the water temperature of the inflow water + outlet: float + the water temperature of the outgoing water NOTE ------ """ @@ -2971,16 +4122,57 @@ def get_cooling_water_temperature_by_time(time_ns): def get_calib_data(port, program=None, t0=None, t1=None, t6=None, emissivity=0.8, T_version=2, version=0, back_emissivity=0.82, testmode=False, verbose=0): """ - get_calib_data - return exist, background, LUT,refT, gain, offset, badpixels, t_exp, cfilter, gain_error, offset_error + get_calib_data downloads the calibration data for the application onto the images + INPUT ------ + port: integer + port number of the AEF port of the camera + program: string, default None + program id in the form of 'YYYYMMDD.XXX', e.g. '20181016.016' + t0: integer, default None + nanoseconds timestamp of the t0 trigger, start of the program + t1: integer, default None + nanoseconds timestamp of the t1 trigger, start of the heating + t6: integer, default None + nanoseconds timestamp of the t6 trigger, end of the program + emissivity: float, optional, default 0.8 + the emissivity value for the calibration + T_version: intger, default 2, + set the calibration version, in version 1 the full background image is subtracted\n in version 2 the background value is subtracted, version 3 + version: integer, optional, default 0 + Version of the data in the archiveDB, in case of 0 the highest version will be used + back_emissivity: float, optional, default 0.82, experimental + emissivity value for the background treatment, only needed for T_version 3 + testmode: boolean, optional, default False + if True, the data will be loaded from the test archive verbose: integer, optional, default 0 feedback level (details of print messages) RESULT ------ - + exist: boolean + True if data was found, False if not + background: integer or numpy array + background image for calibration method 1 and a value for method 2 + LUT: list + the look up table for the temperature calibration, form [[Digital level],[temperature],[error]] + refT: float + reference temperature of the background for the calibration + gain: numpy array + the gain image from the calibration to convert the counts into digital level + offset: numpy array + the offset image from the calibration to convert the counts into digital level + badpixels: list + list of badpixels + t_exp: integer + exposure time in microseconds + cfilter: integer or string, only needed for port 50 + filter number of the Infratec camera in port AEF50 + gain_error: numpy array + the gain error image from the calibration to convert the counts into digital level for the error + offset_error: numpy array + the offset error image from the calibration to convert the counts into digital level for the error NOTE ------ """ @@ -2991,12 +4183,16 @@ def get_calib_data(port, program=None, t0=None, t1=None, t6=None, emissivity=0.8 elif t1 is not None: program = AKF_2.get_program_id(t1) else: - raise Exception('get_calib_data: ERROR! Missing time definition!') +# raise Exception('get_calib_data: ERROR! Missing time definition!') # print(' function requires either a program ID or the trigger times t0, t1 and t6') + logging.warning('get_calib_data: ERROR! Missing time definition!') + return False, 0, [], 0, [], [], [], 0, 0, [], [] # get start and end times from program ID exist, t0, t1, t6 = get_trigger_from_PID(program, port, testmode, verbose=verbose-1) if not exist: - raise Exception('get_calib_data: ERROR! program {0} not found!'.format(program)) +# raise Exception('get_calib_data: ERROR! program {0} not found!'.format(program)) + logging.warning(f'get_calib_data: ERROR! program {program} not found!') + return False, 0, [], 0, [], [], [], 0, 0, [], [] # determin camera in this port and OP OP = IR_tools.get_OP_by_time(time_ns=t0) @@ -3011,8 +4207,9 @@ def get_calib_data(port, program=None, t0=None, t1=None, t6=None, emissivity=0.8 cfilter = cf[2] else: cfilter = -1 - raise Warning("get_calib_data: Filter not found for INFRATEC Camera for Program "+AKF_2.get_program_id(t0)) -# return False, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +# raise Warning("get_calib_data: Filter not found for INFRATEC Camera for Program "+AKF_2.get_program_id(t0)) + logging.warning(f"get_calib_data: Filter not found for INFRATEC Camera for Program {AKF_2.get_program_id(t0)}") + return False, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 else: cfilter=0 @@ -3022,8 +4219,9 @@ def get_calib_data(port, program=None, t0=None, t1=None, t6=None, emissivity=0.8 t_exp = int(expo_DL[2][0]) del expo_DL else: - raise Warning("get_calib_data: no exposure time found") -# return False, 0, 0, 0, 0, 0, 0, 0, cfilter, 0, 0 +# raise Warning("get_calib_data: no exposure time found") + logging.warning("get_calib_data: no exposure time found") + return False, 0, 0, 0, 0, 0, 0, 0, cfilter, 0, 0 # get Look-Up-Table (LUT) time = int(TimeToNs([2017,9,26], [8, 0, 0, 0])) @@ -3032,8 +4230,9 @@ def get_calib_data(port, program=None, t0=None, t1=None, t6=None, emissivity=0.8 LUT=LUT_DL[1] del LUT_DL else: - raise Warning("get_calib_data: no LUT found") -# return False, 0, 0, 0, 0, 0, 0, t_exp, cfilter, 0, 0 +# raise Warning("get_calib_data: no LUT found") + logging.warning("get_calib_data: no LUT found") + return False, 0, 0, 0, 0, 0, 0, t_exp, cfilter, 0, 0 # treat cameras with and w/o filters differently if cfilter==0 and not Camera.split("_")[0] == "Infratec": @@ -3042,8 +4241,9 @@ def get_calib_data(port, program=None, t0=None, t1=None, t6=None, emissivity=0.8 print('get_calib_data: getting NUC arrays') NUC_DL=get_NUC_by_times(port, t0, t1, t_exp, version, testmode, verbose=verbose-1)#download_NUC_by_times(port, t0, t1, t_exp, version) if NUC_DL[0]==False: - raise Warning("get_calib_data: NUC was not found") -# return False, 0, LUT, 0, 0, 0, 0, t_exp, cfilter, 0, 0 +# raise Warning("get_calib_data: NUC was not found") + logging.warning("get_calib_data: NUC was not found") + return False, 0, LUT, 0, 0, 0, 0, t_exp, cfilter, 0, 0 # extract NUC elements gain = [] offset = [] @@ -3081,8 +4281,9 @@ def get_calib_data(port, program=None, t0=None, t1=None, t6=None, emissivity=0.8 bim = apply_NUC([frames[0]], gain, offset) background = get_average_background_recangle(port, bim[0]) else: - raise Warning("get_calib_data: cannot find the first frame of the discharge, reconstruction failed") -# return False, 0, LUT, 0, gain, offset, badpixels, t_exp, cfilter, gain_error, offset_error +# raise Warning("get_calib_data: cannot find the first frame of the discharge, reconstruction failed") + logging.warning("get_calib_data: cannot find the first frame of the discharge, reconstruction failed") + return False, 0, LUT, 0, gain, offset, badpixels, t_exp, cfilter, gain_error, offset_error else: # --- Infratec Camera case --- gain = 0 @@ -3097,9 +4298,13 @@ def get_calib_data(port, program=None, t0=None, t1=None, t6=None, emissivity=0.8 elif OP == "OP1.2b": back_DL = get_NUCed_background_by_times(port, t0, t1, t_exp, cfilter, gain, offset, version, testmode, verbose=verbose-1) else: - raise Exception("get_calib_data: unknown Operation Phase or calibration method not implemented for this campaign") +# raise Exception("get_calib_data: unknown Operation Phase or calibration method not implemented for this campaign") + logging.warning("get_calib_data: unknown Operation Phase or calibration method not implemented for this campaign") + return False, 0, [], 0, [], [], [], 0, 0, [], [] if not back_DL[0]: - raise Warning("get_calib_data: no background image found") +# raise Warning("get_calib_data: no background image found") + logging.warning("get_calib_data: no background image found") + return False, 0, [], 0, [], [], [], 0, 0, [], [] # return False, 0, LUT, 0, gain, offset, badpixels, t_exp, cfilter, gain_error, offset_error background = back_DL[2] @@ -3118,7 +4323,9 @@ def get_calib_data(port, program=None, t0=None, t1=None, t6=None, emissivity=0.8 if TCT_dl[0]: refT = np.average(TCT_dl[2]) else: - raise Exception("get_calib_data: Unable to find thermocouple data") +# raise Exception("get_calib_data: Unable to find thermocouple data") + logging.warning("get_calib_data: Unable to find thermocouple data") + return elif T_version == 2: if verbose > 0: print('get_calib_data: use temperature calibration version 2') @@ -3154,7 +4361,9 @@ def get_calib_data(port, program=None, t0=None, t1=None, t6=None, emissivity=0.8 # back_off=estimate_offset(port, program) # background=(background-back_off)/(back_emissivity)+back_off else: - raise Warning("get_calib_data: Unknown temperature calibration method") +# raise Warning("get_calib_data: Unknown temperature calibration method") + logging.warning("get_calib_data: Unknown temperature calibration method") + return False, 0, [], 0, [], [], [], 0, 0, [], [] # return False, background, LUT, 0, gain, offset, badpixels, t_exp, cfilter, gain_error, offset_error # get bad pixels @@ -3178,13 +4387,30 @@ def get_calib_data(port, program=None, t0=None, t1=None, t6=None, emissivity=0.8 def find_badpixels(port, gain, offset, init_bp_list=None, niterations=3, tolerance=10, plot_it=False, verbose=0): """ + find the bad pixels by searching outliers in the gain and offset image + INPUT ------ + port: integer + port number of the AEF port of the camera + gain: numpy array + the gain image from the calibration to convert the counts into digital level + offset: numpy array + the offset image from the calibration to convert the counts into digital level + init_bp_list: list, default None + initial bad pixel list + niterations: intger, default 3 + number of interation in the process of finding bad pixels + tolerance: integer, default 10 + tolerance value for the idenfication of outlier in the images to identify the bad pixels + plot_it: boolean, default False, + if True the result of the bad pixel finding will be plotted verbose: integer, optional, default 0 feedback level (details of print messages) RESULT ------ - + badpixels: numpy array + list of the bad pixels NOTE ------ """ @@ -3229,12 +4455,15 @@ def find_badpixels(port, gain, offset, init_bp_list=None, niterations=3, def make_FOV_mask(port): """ + creates the field of view image for the requested port and saves it locally + INPUT ------ - + port: integer + port number of the AEF port of the camera RESULT ------ - + no return NOTE ------ """ @@ -3281,12 +4510,16 @@ def make_FOV_mask(port): def get_FOV_mask(port): """ + loads the locally saved field of view images for the requested port, see also make_FOV_mask + INPUT ------ - + port: integer + port number of the AEF port of the camera RESULT ------ - + FOV: numpy array + the image showing the field of view with 1 and 0 for the region of the image which is outside the field of view NOTE ------ """ @@ -3306,12 +4539,18 @@ def get_FOV_mask(port): def get_background(port, image): """ + extracts from a given background image the minimum in the field of view + INPUT ------ - + port: integer + port number of the AEF port of the camera + image: numpy array + 2D numpy arrays RESULT ------ - + background: integer (or float if image contains float values) + returns the background value, extracted from the given image NOTE ------ """ @@ -3326,12 +4565,18 @@ def get_background(port, image): def get_average_background_recangle(port, image): """ + extracts from a given background image the minimum in a defined rectangular region + INPUT ------ - + port: integer + port number of the AEF port of the camera + image: numpy array + 2D numpy arrays RESULT ------ - + background: integer (or float if image contains float values) + returns the background value, extracted from the given image NOTE ------ """ @@ -3346,13 +4591,22 @@ def get_average_background_recangle(port, image): def estimate_offset(port, program, plot_it=False, verbose=0): """ + estimates the offset value based on the background values for different exposure times + INPUT ------ + port: integer + port number of the AEF port of the camera + program: string + program id in the form of 'YYYYMMDD.XXX', e.g. '20181016.016' + plot_it: boolean, default False + if True the result of the bad pixel finding will be plotted verbose: integer, optional, default 0 feedback level (details of print messages) RESULT ------ - + Offset: integer + estimated offset value NOTE ------ """ @@ -3382,24 +4636,44 @@ def estimate_offset(port, program, plot_it=False, verbose=0): return -1 def download_heatflux_by_program(port, program, time_window=0, testmode=False, - version=0, verbose=0, givealpha=False,request=True,moffset=0):#threads=1, - """ - port: string or integer - program: string - time_window: integer, float or list/numpy array of interger/float, single value: t1 until so many seconds, two values, t1+ first value until t1+ second value - threads: integer, number of threads for parallel download - testmode: True to load data from testarchive - version: integer, version number for 0 the highest version will be used - verbose: interger, level of outputs - returns downlad_heatflux_by_times + version=0, verbose=0, givealpha=False,request=True):#threads=1, + """ + download the heatflux for a given program and port, if the data is not available a request is made for the automated evaluation of the heat flux\n + if the data is not available or already requested a message will be returned in the console\n + For extended use of the heat flux data see also the following functions:\n + download_heatflux_mapping_reference --> for a better interpretation of the data with respect to the used coordinate system + download_heatflux_scene_model_reference --> for remapping of the data into W7-X coordinates and pixel coordiantes + extract_heatflux_profile_from_DL --> to extract a profile out of the data returned by this funciton + + INPUT ------ + port: string or integer + the camera port, for which the data is requested + program: string + program id in the form of 'YYYYMMDD.XXX', e.g. '20181016.016' + time_window: integer, float or list/numpy array of interger/float, + time window for the heat flux, single value: t1 until so many seconds, two values, t1+ first value until t1+ second value + testmode: boolean, default False + True to load data from testarchive + version: integer, default 0 + version number for 0 the highest version will be used verbose: integer, optional, default 0 feedback level (details of print messages) + givealpha: boolean, default False + switch to turn on or off the return of the alpha image from the THEODOR calculation, it wil be returned as first image + request: boolean, default True + switch to turn on or off the request of data if the data is not available in the database RESULT ------ - + (returns downlad_heatflux_by_times) + exist: boolean + True if data was found, False if not + time: list + a list containing the time stamp of each frame + frames: list + a list of frames, 2D numpy arrays, first frame is the alpha frame if it is requested NOTE ------ """ @@ -3424,39 +4698,59 @@ def download_heatflux_by_program(port, program, time_window=0, testmode=False, tstart=int(t1) tend=int(t1+time_window[0]*1e9) except Exception as E: - raise Exception("download_heatflux_by_program: an Exception occured interpretating the time_window: ", E) +# raise Exception("download_heatflux_by_program: an Exception occured interpretating the time_window: ", E) + logging.warning("download_heatflux_by_program: an Exception occured interpretating the time_window: "+E) + return False, [0], [0] elif type(time_window)==int or type(time_window)==float: tstart=int(t1) tend=int(t1+time_window*1e9) else: - raise Exception("download_heatflux_by_program: given time_window type is not supported") +# raise Exception("download_heatflux_by_program: given time_window type is not supported") + logging.warning("download_heatflux_by_program: given time_window type is not supported") + return False, [0], [0] if givealpha: tstart=tstart-1.1e9 return download_heatflux_by_times(port=port, tstart=tstart, tend=tend, time_window=0, testmode=testmode, version=version, verbose=verbose, - request=request,moffset=moffset) + request=request) -def download_heatflux_by_times(port, tstart, tend, time_window=0, threads=1, testmode=False, - version=0, verbose=0,request=True,moffset=0): - """ - port: string or integer - tstart: int64 timestamp in ns from which point the download should start - tend: int64 timestamp in ns - threads: integer, number of threads for parallel download - testmode: True to load data from testarchive - version: integer, version number for 0 the highest version will be used - verbose: interger, level of outputs - returns found, time, images +def download_heatflux_by_times(port, tstart, tend, time_window=0, testmode=False, + version=0, verbose=0,request=True,request_ALL=False):#threads=1, ,moffset=0 + """ + + download the heatflux for a given start, endtime and port, if the data is not available a request is made for the automated evaluation of the heat flux\n + if the data is not available or already requested a message will be returned in the console INPUT ------ + port: string or integer + the camera port, for which the data is requested + tstart: integer + time in ns where the search should start + tend: integer + time in sn where the search should end + time_window: integer, float or list/numpy array of interger/float, + time window for the heat flux, single value: t1 until so many seconds, two values, t1+ first value until t1+ second value + testmode: boolean, default False + True to load data from testarchive + version: integer, default 0 + version number for 0 the highest version will be used verbose: integer, optional, default 0 feedback level (details of print messages) + request: boolean, default True + switch to turn on or off the request of data if the data is not available in the database + request_ALL: boolean, optional, default False + switch to turn on the request of data for all AEF ports RESULT ------ - + exist: boolean + True if data was found, False if not + time: list + a list containing the time stamp of each frame, time is in nanoseconds UTC + frames: list + a list of frames, 2D numpy arrays, values in the images are in W/m2 NOTE ------ """ @@ -3475,7 +4769,9 @@ def download_heatflux_by_times(port, tstart, tend, time_window=0, threads=1, tes port=int(port.split("AEF")[1]) goon=True except Exception as E: - raise Exception("download_heatflux_by_times: unknown Port!"+E) +# raise Exception("download_heatflux_by_times: unknown Port!"+E) + logging.warning("download_heatflux_by_times: unknown Port!"+E) + return False, [0], [0] elif isinstance(port, (int, np.integer, float, np.float)): FLIR=False goon=True @@ -3501,6 +4797,7 @@ def download_heatflux_by_times(port, tstart, tend, time_window=0, threads=1, tes if verbose > 0: print(datetime.datetime.now(), "download_heatflux_by_times: heat flux download started") if False: ## does not work, the png pictures are interpretated as colors, values are lost + threads = 1 exist, time, frames=download_images_by_time_via_png(larchivepath, starttime=tstart, stoptime=tend, time_window=time_window, version=version, threads=threads, verbose=verbose-1) else: exist, time, frames=download_images_by_times(larchivepath, starttime=tstart, stoptime=tend, verbose=verbose-1) @@ -3523,9 +4820,13 @@ def download_heatflux_by_times(port, tstart, tend, time_window=0, threads=1, tes cam_progs_ig,reasons=IR_tools.get_work_list(heatflux_requestlist_path, typ='ignore') except: cam_progs_ig=[] - if (programid, "AEF"+str(port)) not in cam_progs and (programid, "AEF"+str(port)) not in cam_progs_ig: - f=open(heatflux_requestlist_path+str(now.year)+str(now.month+moffset)+"_q_requests.txt", 'a') - f.write(programid+"\tAEF"+str(port)+"\n") + cam_p = cam_progs + cam_progs_ig + if (programid, "AEF"+str(port)) not in cam_p and (programid, "ALL") not in cam_p: + f=open(heatflux_requestlist_path+"Auto_q_requests.txt", 'a') + if request_ALL: + f.write(programid+"\tALL\n") + else: + f.write(programid+"\tAEF"+str(port)+"\n") f.close() if verbose > 0: print("download_heatflux_by_times: heat flux calculation request logged for automatic processing (within ca. 1 day)") @@ -3540,15 +4841,26 @@ def download_heatflux_by_times(port, tstart, tend, time_window=0, threads=1, tes def download_heatflux_mapping_reference(timepoint=None, version=0, testmode=False, get_thickness=False, verbose=0): """ - return exist(boolean) and dictonary of the mappings informations + returns the mapping informations for the heatflux to relate each pixel in the heat flux image to different additional parameters. e.g., X and Y coordiante of the divertor mapping INPUT ------ + timepoint: integer, optional, default None + set the timepoint in nanoseconds where/when to search for the mapping in the database + version: integer, optional, default 0 + Version of the data in the archiveDB, in case of 0 the highest version will be used + testmode: boolean, optional, default False + if True, the data will be loaded from the test archive + get_thickness: boolean, optional, default False + turns on the return of the thickness verbose: integer, optional, default 0 feedback level (details of print messages) RESULT ------ - + exist: boolean + True if data was found, False if not + mappings: dictionary + the mapping informations containing: surface coordinate s, divertor coordinate system X,Y, Finger coordiante system X, Y, Finger Id, Thickness, target, Target_Module\n all coordinates in meter NOTE ------ """ @@ -3682,15 +4994,28 @@ def download_heatflux_mapping_reference(timepoint=None, version=0, testmode=Fals def download_heatflux_scene_model_reference(port, timepoint=None, program=None, version=0, testmode=False, verbose=0): """ - return exist(boolean) and dictonary of the mappings informations + returns the mapping informations based on the scene model for the heatflux to relate each pixel in the heat flux image to different additional parameters. e.g., X and Y coordiante in the original image or the CAD geometry in X,Y,Z INPUT ------ + port: integer or string + port of the AEF port of the camera + timepoint: integer, optional, default None + set the timepoint in nanoseconds where/when to search for the mapping in the database + version: integer, optional, default 0 + Version of the data in the archiveDB, in case of 0 the highest version will be used + testmode: boolean, optional, default False + if True, the data will be loaded from the test archive + get_thickness: boolean, optional, default False + turns on the return of the thickness verbose: integer, optional, default 0 feedback level (details of print messages) RESULT ------ - + exist: boolean + True if data was found, False if not + mappings: dictionary + the mapping informations containing: most likely Pixel coordiante X,Y, CAD X,Y,Z and the component id as PFC, \n all coordinates in meter NOTE ------ """ @@ -3755,16 +5080,22 @@ def download_heatflux_scene_model_reference(port, timepoint=None, program=None, def give_finger_ID(profile, finger=None, verbose=0): """ - profile: string, integer or float, string: "TM3h_5_5" or "1605" or "16.05" or "5", similar for float and integer. single number only if the finger is given! - finger: string or integer, string "TM3h_5" or "16" or 16 or 1600 or None + returns for a given profile (and finger) information the finger ID which is internally used in the mappings INPUT ------ + profile: string, integer or float, + string: "TM3h_5_5" or "1605" or "16.05" or "5", similar for float and integer. single number only if the finger is given! + finger: string or integer, optional, default None + string "TM3h_5" or "16" or 16 or 1600 or None verbose: integer, optional, default 0 feedback level (details of print messages) RESULT ------ - + success: boolean + gives the information whether the idenfication of the fingerID went well or not + fingerID: integer + the finger idendifikation in the form of XXXYY with XXX the fingernumber *100 and YY the profile number, starting with 0 NOTE ------ """ @@ -3853,20 +5184,46 @@ def give_finger_ID(profile, finger=None, verbose=0): def get_heatflux_profile(port, profile, finger=None, timepoint=None, program=None, tstart=None, tend=None, testmode=False, version=0, verbose=0): """ - returns exist, time, s in m, heat flux in W/m2 + returns a heat flux profile for a given port, profile (and finger) and timepoint in a program/time intervall defined by tstart and tend + \n it is a combination of the following functions:\n + download_heatflux_by_prrogram or download_heatflux_by_times\n + extract_heatflux_profile_from_DL, since it is called in the end\n + and also give_finger_ID for the interpretation of the profile/finger input\n - parameters: - port: string or integer - profile: string, integer or float, string: "TM3h_5_5" or "1605" or "16.05" or "5", similar for float and integer. single number only if the finger is given! - finger: string or integer, string "TM3h_5" or "16" + in case you want several profiles, please use the function extract_heatflux_profile_from_DL to lower the amount of downloaded data (speed things up) INPUT ------ + port: string or integer + the port for which the data is requested, normally a AEF port + profile: string, integer or float, + string: "TM3h_5_5" or "1605" or "16.05" or "5", similar for float and integer. single number only if the finger is given! + finger: string or integer, + string "TM3h_5" or "16" + timepoint: integer, default None + the timepoint for the profile in seconds from T1 trigger + program: string + program id in the form of 'YYYYMMDD.XXX', e.g. '20181016.016' + tstart: integer + time in ns where the search should start + tend: integer + time in ns where the search should end + testmode: boolean, default False + True to load data from testarchive + version: integer, optional, default 0 + Version of the data in the archiveDB, in case of 0 the highest version will be used verbose: integer, optional, default 0 feedback level (details of print messages) RESULT ------ - + exist: boolean + True if data was found, False if not + time: list + timestamp of the profile in seconds + s: list of float + surface coordinate in meter for each profile position + heatflux: list of float + the heat flux in in W/m2 for each profile position NOTE ------ """ @@ -3923,15 +5280,18 @@ def get_heatflux_profile(port, profile, finger=None, timepoint=None, program=Non port = int(port.split("AEF")[1]) goon = True except Exception as E: - raise Warning("get_heatflux_profile: unknown Port!"+E) -# return False, 0, 0, 0 +# raise Warning("get_heatflux_profile: unknown Port!"+E) + logging.warning("get_heatflux_profile: unknown Port!"+E) + return False, 0, 0, 0 elif isinstance(port, (int, np.integer, float, np.float)): FLIR = False goon = True else: goon = False if not goon or FLIR: - raise Exception("get_heatflux_profile: Unknown port, FLIR data is unsupported at the moment") +# raise Exception("get_heatflux_profile: Unknown port, FLIR data is unsupported at the moment") + logging.warning("get_heatflux_profile: Unknown port, FLIR data is unsupported at the moment") + return False, 0, 0, 0 else: ### if the program goes up to here, time okay, finger okay, port okay, lets download it exist, timo, frames=download_heatflux_by_times(port, tstart, tend, time_window=0, threads=1, testmode=testmode, version=version, verbose=verbose-1) @@ -3945,30 +5305,39 @@ def get_heatflux_profile(port, profile, finger=None, timepoint=None, program=Non def extract_heatflux_profile_from_DL(time, images, profile, finger=None, time_window=None, inputchecked=False, verbose=0, testmode=False): """ - return exist, time, s in m, heat flux in W/m2 - time_point default (None) returns entire shot. + extracts from given heat flux images the requested profile for the given time window INPUT ------ - time: - - images: - - profile: - - finger: - - time_window: - - inputchecked: - + time: list + the timevector of the data in seconds + images: list + list of frames in form of numpy arrays with the heat flux data + profile: string, integer or float, + string: "TM3h_5_5" or "1605" or "16.05" or "5", similar for float and integer. single number only if the finger is given! + finger: string or integer, + string "TM3h_5" or "16" + time_window: integer, float or list/numpy array + defines the timewindow, if only a number is give or an array/list with only one number, it searches one profile for the given timevector, \n + if a list or array is given, several profiles will be returned, in case of None, the full program will be returned + inputchecked: boolean, optional, default False + defines whether the input parameters have been checked for correct format or not (profile and finger) verbose: integer, optional, default 0 feedback level (details of print messages) testmode: boolean, optional, default 0 if True, the data will be loaded from the test archive RESULT ------ - + exist: boolean + indicates whether data was found (True) or not (False) + time: list + the timestamps of the profile + s: list + the surface coordinates of the profile in meter + heatflux: list + the heat flux for the profile in W/m2 + + NOTE ------ """ @@ -4027,7 +5396,7 @@ def extract_temperature_profile_from_DL(port, time, images, profile, finger=None time_window=None, inputchecked=False, verbose=0, reference_time=0): """ - + for a given heatflux image and profile and finger information, a profile can be extracted. INPUT ------ port: int or str @@ -4036,14 +5405,15 @@ def extract_temperature_profile_from_DL(port, time, images, profile, finger=None the time vector for the given images images: numpy array temperature flux images, from which the profile should be extracted - profile: float - ABC - finger: - - time_window: - - inputchecked: - + profile: string, integer or float, + string: "TM3h_5_5" or "1605" or "16.05" or "5", similar for float and integer. single number only if the finger is given! + finger: string or integer, + string "TM3h_5" or "16" + time_window: integer, float or list/numpy array + defines the timewindow, if only a number is give or an array/list with only one number, it searches one profile for the given timevector, \n + if a list or array is given, several profiles will be returned, in case of None, the full program will be returned + inputchecked: boolean, optional, default False + defines whether the input parameters have been checked for correct format or not (profile and finger) verbose: integer, optional feedback level (details of print messages) reference_time : float, optional, default is 0 @@ -4051,15 +5421,13 @@ def extract_temperature_profile_from_DL(port, time, images, profile, finger=None RESULT ------ exist: boolean - indicates whether data was found (True) or not (False) - - time - s in m - heat flux in W/m2 - - - - + indicates whether data was found (True) or not (False) + time: list + the timestamps of the profiles + s: list + the surface coordinates of the profiles in meter + heatflux: list + the heat flux for each profile in W/m2 NOTES ----- """ @@ -4121,8 +5489,15 @@ def extract_temperature_profile_from_DL(port, time, images, profile, finger=None def download_divertor_load(port, targetmodule=None, program=None, tstart=None, tend=None, version=0, verbose=0, testmode=False, - request=True): + request=True, request_ALL=False): """ + downloads the integrated divertor load, based on the heat flux evaluation of the temperature data from the IR cameras.\n + The data is structed in total load per divertor, identified by the port, and also in target-modules of the divertor.\n + An estiamted error for the data is given back. + To get the total divertor load, please download the data of each of the 10 AEF ports.\n + In case one or more ports are missing, request can be created (console will give feedback on the request).\n + The data will be evaluated by a server over time. + INPUT ------ port: int or str @@ -4131,21 +5506,30 @@ def download_divertor_load(port, targetmodule=None, program=None, tstart=None, name or description of the target module, nothing wil return total load program: str program id as str in the format yyyymmdd.pid - tstart: uint64 - - tend: uint64 - - version: int - + tstart: integer + time in ns where the search should start + tend: integer + time in ns where the search should end + version: integer, optional, default 0 + Version of the data in the archiveDB, in case of 0 the highest version will be used verbose: integer, optional feedback level (details of print messages) - testmode: - + testmode: boolean, default False + True to load data from testarchive request: boolean, optional, default True + switch to turn on or off the request of data if the data is not available in the database + request_ALL: boolean, optional, default False + switch to turn on the request of data for all AEF ports RESULT ------ exist: boolean - + True if data was found, False if not + time: list + a list containing the time stamp of each frame, time is in nanoseconds UTC + load: list + a list of values, values in the images are in W + error: list + a list of values, the error of each timepoint, values are in W """ TMchadict={ 'ALL':(0,1, 'divertor_total_load'), 'FULL':(0,1, 'divertor_total_load'), @@ -4274,9 +5658,13 @@ def download_divertor_load(port, targetmodule=None, program=None, tstart=None, programid=str(tstart) cam_progs=IR_tools.get_work_list(heatflux_requestlist_path, typ='load') cam_progs_ig,reasons=IR_tools.get_work_list(heatflux_requestlist_path, typ='ignore') - if (programid, str(port)) not in cam_progs and (programid, str(port)) not in cam_progs_ig: - f = open(heatflux_requestlist_path+str(now.year)+str(now.month)+"_load_requests.txt", 'a') - f.write(programid+"\t"+str(port)+"\n") + cam_p = cam_progs+cam_progs_ig + if (programid, str(port)) not in cam_p and (programid, "ALL") not in cam_p: + f = open(heatflux_requestlist_path+"Auto_load_requests.txt", 'a') + if request_ALL: + f.write(programid+"\tALL\n") + else: + f.write(programid+"\t"+str(port)+"\n") f.close() if verbose > 0: print(now, "download_divertor_load: request created") @@ -4330,7 +5718,9 @@ def download_scene_model(port, program=None, timepoint=None, version=0, testmode # else: exist, _, timepoint, _ = get_trigger_from_PID(program, port, testmode, verbose=verbose-1) if not exist: - raise Exception("download_scene_model: Error! Program "+program+" not found!") +# raise Exception("download_scene_model: Error! Program "+program+" not found!") + logging.warning("download_scene_model: Error! Program "+program+" not found!") + return False, 0 if testmode: base=testarchivepath else: @@ -4371,6 +5761,59 @@ def download_scene_model(port, program=None, timepoint=None, version=0, testmode return exist, scene_model else: return False, [0] +#%% caching, requested by Lukas R, sample function supplied by Lukas R. +import os +def extract_heatflux_profile_from_cache(port, program, time_window=0, profile="TM3h_5_5", **kwargs): + """Returns exists, time, position, heat_flux_profiles + """ + kwargs.setdefault('verbose',0) + kwargs.setdefault('testmode',False) + data_folder = os.path.join(os.path.dirname(__file__), 'cache') + save_path = data_folder + '/'.join(["", program, str(port), ""]) + start = time_window[0] if hasattr(time_window, '__iter__') else 0.0 + end = time_window[-1] if hasattr(time_window, '__iter__') else time_window + path = save_path + "heatflux_images_[{s:.2f}-{e:.2f}].npz".format(s=start, e=end) + if not os.path.isfile(path): + if kwargs['verbose'] > 0: + print("Generating cache for {program} port {port} timewindow [{s:.2f}-{e:.2f}]".format( + port=port, program=program, s=start, e=end + )) + cache_heatflux_by_program(port, program, time_window=time_window, **kwargs) + cache_file = np.load(path) + found,time,images = [cache_file[kw] for kw in ['found','time','images']] + if not found: + raise ValueError("Download was invalid") + exist, _, t1, t6 = get_trigger_from_PID( + program, port, kwargs['testmode'], verbose=kwargs['verbose']-1) + return extract_heatflux_profile_from_DL((np.asarray(time)-t1)/1e9, images, profile, time_window=time_window, **kwargs) + +def cache_heatflux_by_program(port, program, time_window=0, **kwargs): + """ + """ + data_folder = os.path.join(os.path.dirname(__file__), 'cache') + save_path = data_folder + '/'.join(["", program, str(port), ""]) + check_path_and_make_folders(True, save_path) + found, time, images = download_heatflux_by_program(port, program, + time_window=time_window, **kwargs) + start = time_window[0] if hasattr(time_window, '__iter__') else 0.0 + end = time_window[-1] if hasattr(time_window, '__iter__') else time_window + np.savez(save_path + "heatflux_images_[{s:.2f}-{e:.2f}]".format(s=start, e=end), + found=found, time=time, images=images) + +def check_path_and_make_folders(activate, path, sep='', folder=''): + '''Does nothing if file structure already exists. + Otherwise recursively goes up layers until existing file is found, then creates subfolders. + This kind of thing should be in an independent & general caching handler + ''' + if not activate: + return + if not os.path.exists(path): + check_path_and_make_folders(activate, *path.rpartition('/')) + try: + os.mkdir(path+sep+folder) + except FileExistsError: + pass + #%% general download functions """ @@ -4383,7 +5826,8 @@ def read_restdb_old(request_url): Reads JSON data from W7-X REST API INPUT ------ - + request_url: string + the url from there the data should be loaded Returns ------ valid: bolean @@ -4414,7 +5858,10 @@ def read_restdb_old(request_url): def read_restdb(request_url): """ Reads JSON data from W7-X REST API. Signals are converted into double - + INPUT + ------ + request_url: string + the url from there the data should be loaded Returns: ------ valid: bolean diff --git a/plot_heatflux_example.py b/plot_heatflux_example.py index 88c6a82619ae708bcc851f82b42e10474327e308..f86f3047ae7902995b77d5b9253d06a2e7d94831 100644 --- a/plot_heatflux_example.py +++ b/plot_heatflux_example.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- """ Created on Thu Nov 29 17:41:40 2018 -V3.2.0 +V3.4.1 @author: holn """ import numpy as np @@ -18,7 +18,7 @@ if __name__=='__main__': #%% loading data print(datetime.datetime.now(),"start") - status,times,images=IR.download_heatflux_by_program(port,program,time_window=[0,2],version=2,threads=1,verbose=5,testmode=False) + status,times,images=IR.download_heatflux_by_program(port,program,time_window=[0,2],version=2,verbose=5,testmode=False) print('done') #%% plotting data diff --git a/setup.py b/setup.py index f38725a255ef74d0410898445f738df17c2965b6..9bde9f6074bfb0fb77ff2a31a305fc5fb95e7ef5 100644 --- a/setup.py +++ b/setup.py @@ -16,7 +16,7 @@ setup( 'plot_heatflux_example' ], data_files=[ - ('',['upload_config','CHANGELOG','ToDo.txt']), + ('',['upload_config','CHANGELOG','ToDo.txt','README.md']), ('data',['data/AEF10_coldframes_background_fails_real.txt', 'data/AEF11_coldframes_background_fails_real.txt', 'data/AEF20_coldframes_background_fails_real.txt', @@ -30,7 +30,7 @@ setup( 'data/finger_info_TDU.csv']) ], install_requires = [ - 'archivedb>=0.2.0' + 'w7xarchive>=0.11.21' ] );