From f89397beae9c3da3221f9c9ab90f9739f5de0097 Mon Sep 17 00:00:00 2001 From: Anna Troff Date: Tue, 11 Nov 2025 18:48:57 +0100 Subject: [PATCH 01/14] Path naming compatible with windows --- ledsa/core/ConfigData.py | 12 +++++++----- ledsa/core/image_reading.py | 2 +- ledsa/data_extraction/init_functions.py | 4 ++-- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/ledsa/core/ConfigData.py b/ledsa/core/ConfigData.py index 261806a..1d3cd52 100644 --- a/ledsa/core/ConfigData.py +++ b/ledsa/core/ConfigData.py @@ -1,3 +1,4 @@ +import os import configparser as cp from datetime import datetime, timedelta @@ -271,10 +272,11 @@ def in_time_diff_to_img_time(self) -> None: time = input('Please give the time shown on the clock in the time reference image in hh:mm:ss: ') self['DEFAULT']['time_ref_img_time'] = str(time) time = self['DEFAULT']['time_ref_img_time'] - print(self['DEFAULT']['img_directory'] + self['DEFAULT']['time_img_id']) + print(os.path.join(self['DEFAULT']['img_directory'], self['DEFAULT']['img_name_string'].format( + self['DEFAULT']['time_img_id']))) tag = 'EXIF DateTimeOriginal' - exif_entry = get_exif_entry(self['DEFAULT']['img_directory'] + self['DEFAULT']['img_name_string'].format( - self['DEFAULT']['time_img_id']), tag) + exif_entry = get_exif_entry(os.path.join(self['DEFAULT']['img_directory'], self['DEFAULT']['img_name_string'].format( + self['DEFAULT']['time_img_id'])), tag) date, time_meta = exif_entry.split(' ') self['DEFAULT']['date'] = date img_time = _get_datetime_from_str(date, time_meta) @@ -351,8 +353,8 @@ def get_start_time(self) -> None: Updates the 'DEFAULT' key with the 'start_time' computed. """ - exif_entry = get_exif_entry(self['DEFAULT']['img_directory'] + self['DEFAULT']['img_name_string'].format( - self['DEFAULT']['first_img_experiment_id']), 'EXIF DateTimeOriginal') + exif_entry = get_exif_entry(os.path.join(self['DEFAULT']['img_directory'], self['DEFAULT']['img_name_string'].format( + self['DEFAULT']['first_img_experiment_id'])), 'EXIF DateTimeOriginal') date, time_meta = exif_entry.split(' ') time_img = _get_datetime_from_str(date, time_meta) start_time = time_img - timedelta(seconds=self['DEFAULT'].getint('exif_time_infront_real_time')) diff --git a/ledsa/core/image_reading.py b/ledsa/core/image_reading.py index 0878385..53bf7cf 100644 --- a/ledsa/core/image_reading.py +++ b/ledsa/core/image_reading.py @@ -22,7 +22,7 @@ def read_channel_data_from_img(filename: str, channel: int) -> np.ndarray: extension = os.path.splitext(filename)[-1] if extension in ['.JPG', '.JPEG', '.jpg', '.jpeg', '.PNG', '.png']: channel_array = _read_channel_data_from_img_file(filename, channel) - elif extension in ['.CR2']: + elif extension in ['.CR2','.CR3']: channel_array = _read_channel_data_from_raw_file(filename, channel) return channel_array diff --git a/ledsa/data_extraction/init_functions.py b/ledsa/data_extraction/init_functions.py index 901a2f2..5f3117c 100644 --- a/ledsa/data_extraction/init_functions.py +++ b/ledsa/data_extraction/init_functions.py @@ -107,8 +107,8 @@ def _calc_experiment_and_real_time(build_type: str, config: ConfigData, tag: str :return: Tuple containing experiment time and real time. :rtype: tuple """ - exif_entry = get_exif_entry(config['DEFAULT']['img_directory'] + - config['DEFAULT']['img_name_string'].format(int(img_number)), tag) + exif_entry = get_exif_entry(os.path.join(config['DEFAULT']['img_directory'], + config['DEFAULT']['img_name_string'].format(int(img_number))), tag) date, time_meta = exif_entry.split(' ') date_time_img = _get_datetime_from_str(date, time_meta) From 5741a90de169516318fba9083e8cd9c0be6c6f5b Mon Sep 17 00:00:00 2001 From: Anna Troff Date: Wed, 12 Nov 2025 09:59:26 +0100 Subject: [PATCH 02/14] Add compatible date format --- ledsa/core/ConfigData.py | 3 +++ ledsa/data_extraction/init_functions.py | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ledsa/core/ConfigData.py b/ledsa/core/ConfigData.py index 1d3cd52..8b92298 100644 --- a/ledsa/core/ConfigData.py +++ b/ledsa/core/ConfigData.py @@ -368,6 +368,7 @@ def _get_datetime_from_str(date: str, time: str) -> datetime: The function can handle two formats: 1. '%Y:%m:%d %H:%M:%S' - standard format with colons in the date. 2. '%d.%m.%Y %H:%M:%S' - format with periods in the date. + 3. '%d-%m-%Y %H:%M:%S' - format with hyphens in the date. :param date: The date string. :type date: str @@ -378,6 +379,8 @@ def _get_datetime_from_str(date: str, time: str) -> datetime: """ if date.find(":") != -1: date_time = datetime.strptime(date + ' ' + time, '%Y:%m:%d %H:%M:%S') + elif date.find("-") != -1: + date_time = datetime.strptime(date + ' ' + time, '%Y-%m-%d %H:%M:%S') else: date_time = datetime.strptime(date + ' ' + time, '%d.%m.%Y %H:%M:%S') return date_time diff --git a/ledsa/data_extraction/init_functions.py b/ledsa/data_extraction/init_functions.py index 5f3117c..0bbd390 100644 --- a/ledsa/data_extraction/init_functions.py +++ b/ledsa/data_extraction/init_functions.py @@ -125,7 +125,7 @@ def _get_datetime_from_str(date: str, time: str) -> datetime: """ Convert date and time strings to a datetime object. - :param date: Date string in the format '%Y:%m:%d' or '%d.%m.%Y'. + :param date: Date string in the format '%Y:%m:%d' or '%d.%m.%Y' or '%Y-%m-%d'. :type date: str :param time: Time string in the format '%H:%M:%S'. :type time: str @@ -134,6 +134,8 @@ def _get_datetime_from_str(date: str, time: str) -> datetime: """ if date.find(":") != -1: date_time = datetime.strptime(date + ' ' + time, '%Y:%m:%d %H:%M:%S') + elif date.find("-") != -1: + date_time = datetime.strptime(date + ' ' + time, '%Y-%m-%d %H:%M:%S') else: date_time = datetime.strptime(date + ' ' + time, '%d.%m.%Y %H:%M:%S') return date_time From b13207ccfc284632e4ea9593db1d12988bed6490 Mon Sep 17 00:00:00 2001 From: Anna Troff Date: Wed, 12 Nov 2025 10:02:52 +0100 Subject: [PATCH 03/14] Read exif entry compatible for .CR3 --- ledsa/core/image_reading.py | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/ledsa/core/image_reading.py b/ledsa/core/image_reading.py index 53bf7cf..9b656df 100644 --- a/ledsa/core/image_reading.py +++ b/ledsa/core/image_reading.py @@ -1,5 +1,7 @@ import os - +from hachoir.parser import createParser +from hachoir.metadata import extractMetadata +from pathlib import Path import exifread import numpy as np import rawpy @@ -91,6 +93,27 @@ def get_exif_entry(filename: str, tag: str) -> str: :rtype: str :raises KeyError: If the EXIF tag is not found in the image metadata. """ + if '.CR3' in filename: + parser = createParser(str(filename)) + if not parser: + raise ValueError(f"Konnte Datei nicht parsen: {filename}") + + metadata = extractMetadata(parser) + if not metadata: + raise ValueError("Keine Metadaten gefunden.") + + # Alle Metadaten anzeigen, falls du schauen willst was verfügbar ist + # print(metadata.exportPlaintext()) + + # Versuch, die Aufnahmezeit zu finden + try: + for line in metadata.exportPlaintext(): + if "Creation date" in line or "Date/Time Original" in line: + return line.split(":", 1)[1].strip() + except: + print("Keine Aufnahmezeit gefunden.") + exit(1) + with open(filename, 'rb') as f: exif = exifread.process_file(f, details=False, stop_tag=tag) try: From 0148822afcea4f855cfdedafe56bc2f997a0d6da Mon Sep 17 00:00:00 2001 From: Anna Troff Date: Wed, 12 Nov 2025 10:06:33 +0100 Subject: [PATCH 04/14] Input img_number as string --- ledsa/data_extraction/init_functions.py | 6 +++--- ledsa/data_extraction/step_3_functions.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ledsa/data_extraction/init_functions.py b/ledsa/data_extraction/init_functions.py index 0bbd390..70200d7 100644 --- a/ledsa/data_extraction/init_functions.py +++ b/ledsa/data_extraction/init_functions.py @@ -92,7 +92,7 @@ def generate_image_infos_csv(config: ConfigData, build_experiment_infos=False, b _save_analysis_infos(img_data) -def _calc_experiment_and_real_time(build_type: str, config: ConfigData, tag: str, img_number: int) -> None: +def _calc_experiment_and_real_time(build_type: str, config: ConfigData, tag: str, img_number: str) -> None: """ Calculate experiment and real-time based on image metadata and config settings. @@ -108,7 +108,7 @@ def _calc_experiment_and_real_time(build_type: str, config: ConfigData, tag: str :rtype: tuple """ exif_entry = get_exif_entry(os.path.join(config['DEFAULT']['img_directory'], - config['DEFAULT']['img_name_string'].format(int(img_number))), tag) + config['DEFAULT']['img_name_string'].format(img_number)), tag) date, time_meta = exif_entry.split(' ') date_time_img = _get_datetime_from_str(date, time_meta) @@ -197,7 +197,7 @@ def _build_img_data_string(build_type: str, config: ConfigData) -> str: for img_id in img_id_list: tag = 'EXIF DateTimeOriginal' experiment_time, time = _calc_experiment_and_real_time(build_type, config, tag, img_id) - img_data += (str(img_idx) + ',' + config[build_type]['img_name_string'].format(int(img_id)) + + img_data += (str(img_idx) + ',' + config[build_type]['img_name_string'].format(img_id) + ',' + time.strftime('%H:%M:%S') + ',' + str(experiment_time) + '\n') img_idx += 1 return img_data diff --git a/ledsa/data_extraction/step_3_functions.py b/ledsa/data_extraction/step_3_functions.py index acbfac1..607613f 100644 --- a/ledsa/data_extraction/step_3_functions.py +++ b/ledsa/data_extraction/step_3_functions.py @@ -58,7 +58,7 @@ def generate_analysis_data(img_filename: str, channel: int, search_areas: np.nda return img_analysis_data -def create_fit_result_file(img_data: List[LEDAnalysisData], img_id: int, channel: int) -> None: # TODO: rename because misleading +def create_fit_result_file(img_data: List[LEDAnalysisData], img_id: str, channel: int) -> None: # TODO: rename because misleading """ Create a result file for a single image, containing the pixel values and, if applicable, the fit results of all LEDs. From 9066b02ce068b2ffa8fd69b94838eb14585bb261 Mon Sep 17 00:00:00 2001 From: Anna Troff Date: Thu, 27 Nov 2025 13:55:41 +0100 Subject: [PATCH 05/14] librarys updaten --- doc/conf.py | 1 + ledsa/core/image_reading.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/conf.py b/doc/conf.py index 0c07ed5..8151928 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -40,6 +40,7 @@ "exifread", "rawpy", "opencv-python", + "hachoir" ] diff --git a/ledsa/core/image_reading.py b/ledsa/core/image_reading.py index 9b656df..bff93ad 100644 --- a/ledsa/core/image_reading.py +++ b/ledsa/core/image_reading.py @@ -24,7 +24,7 @@ def read_channel_data_from_img(filename: str, channel: int) -> np.ndarray: extension = os.path.splitext(filename)[-1] if extension in ['.JPG', '.JPEG', '.jpg', '.jpeg', '.PNG', '.png']: channel_array = _read_channel_data_from_img_file(filename, channel) - elif extension in ['.CR2','.CR3']: + elif extension in ['.CR2','.CR3','.cr3']: channel_array = _read_channel_data_from_raw_file(filename, channel) return channel_array From 722de04adcd5941298c665283f35745c7af73b05 Mon Sep 17 00:00:00 2001 From: Anna Troff Date: Mon, 1 Dec 2025 14:37:50 +0100 Subject: [PATCH 06/14] add nicon format --- ledsa/core/image_reading.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ledsa/core/image_reading.py b/ledsa/core/image_reading.py index bff93ad..cccba9a 100644 --- a/ledsa/core/image_reading.py +++ b/ledsa/core/image_reading.py @@ -24,7 +24,7 @@ def read_channel_data_from_img(filename: str, channel: int) -> np.ndarray: extension = os.path.splitext(filename)[-1] if extension in ['.JPG', '.JPEG', '.jpg', '.jpeg', '.PNG', '.png']: channel_array = _read_channel_data_from_img_file(filename, channel) - elif extension in ['.CR2','.CR3','.cr3']: + elif extension in ['.CR2','.CR3','.NEF']: channel_array = _read_channel_data_from_raw_file(filename, channel) return channel_array From 1e4133e3c1569c2d05c723d05acff8a4009bd690 Mon Sep 17 00:00:00 2001 From: Anna Troff Date: Mon, 1 Dec 2025 14:38:13 +0100 Subject: [PATCH 07/14] add scripts auswertung and exposure_checker --- ledsa/postprocessing/auswertung.py | 101 +++++++++++++++++++++++++++++ ledsa/tools/exposure_checker.py | 41 ++++++++++++ 2 files changed, 142 insertions(+) create mode 100644 ledsa/postprocessing/auswertung.py create mode 100644 ledsa/tools/exposure_checker.py diff --git a/ledsa/postprocessing/auswertung.py b/ledsa/postprocessing/auswertung.py new file mode 100644 index 0000000..50f3f88 --- /dev/null +++ b/ledsa/postprocessing/auswertung.py @@ -0,0 +1,101 @@ +import matplotlib.pyplot as plt +from matplotlib import rcParams +from mpl_toolkits.axes_grid1.inset_locator import InsetPosition +import seaborn as sns +import numpy as np +import pandas as pd +from ledsa.postprocessing.simulation import SimData +import os +from matplotlib.ticker import FormatStrFormatter + +rcParams['font.family'] = 'serif' +rcParams['font.size'] = 10 +cm = 1 / 2.54 + +# Input Dir (Simulations) !alle channel müssen abgegriffen werden +path_simulation = os.getcwd() +sim = SimData(path_simulation) +output_path = os.path.join(path_simulation,'output') + +if not os.path.isdir(output_path): + os.makedirs (output_path) + + +#read possible times +df_info = pd.read_csv('image_infos.csv', header = 0) +times = df_info['Experiment_Time[s]'] + +# Parameters +led_array_id = 0 # LED array to analyze +window = 1 # Size of moving average window +color_channels = [0, 1, 2] # RGB channels + +# Create figure Extinction +fig, ax = plt.subplots(figsize=(10, 6)) + +# Plot extinction coefficients for each channel +for channel in color_channels: + # Get extinction coefficients at specified height + extco = sim.get_extco_at_led_array(channel=channel, led_array_id=led_array_id, window=window, yaxis='layer') + middleIndex = (len(extco.columns) - 1)//2 + # Plot with different colors for each channel + colors = ['red', 'green', 'blue'] + ax.plot(extco.index, extco.iloc[:,middleIndex], + color=colors[channel], + label=f'Channel {channel}') + # ax.fill_between(extco.index, 10,20, color=colors[channel], alpha = 0.5) + ax.fill_between(extco.index, extco.iloc[:,:].T.max(), extco.iloc[:,:].T.min(), color=colors[channel], alpha = 0.1) + +ax.set_xlabel('Time / s') +ax.set_ylabel('Extinction Coefficient / $\mathrm{m^{-1}}$') +ax.set_title(f'Extinction Coefficients at LED-ID {middleIndex}, LED Array {led_array_id}') +ax.grid(True) +ax.legend() +plt.tight_layout() +plt.savefig(os.path.join(output_path,'extco_time_range.png')) +plt.close() + +# Create figure +fig, ax = plt.subplots(figsize=(10, 6)) + +# Plot extinction coefficients for each channel +for channel in color_channels: + # Get extinction coefficients at specified height + extco = sim.get_ledparams_at_led_array(channel=channel, led_array_id=led_array_id, window=window, yaxis='height') + middleIndex = (len(extco.columns) - 1)//2 + # Plot with different colors for each channel + colors = ['red', 'green', 'blue'] + ax.plot(extco.index, extco.iloc[:,middleIndex], + color=colors[channel], + label=f'Channel {channel}') + ax.fill_between(extco.index, extco.iloc[:,:].T.max(), extco.iloc[:,:].T.min(), color=colors[channel], alpha = 0.2) + +ax.set_xlabel('Time / s') +ax.set_ylabel('LED Parameters') +ax.set_title(f'LED Parameters at LED Parameter {middleIndex}, LED Array {led_array_id}') +ax.grid(True) +ax.legend() +plt.tight_layout() +plt.savefig(os.path.join(output_path,'led_time_range.png')) +plt.close() + +# Parameters +for channel in color_channels: + fig, ax = plt.subplots(figsize=(10, 6)) + extco = sim.get_extco_at_led_array(channel = channel, led_array_id =led_array_id, yaxis='height', window=window).T + extco = extco.set_index(np.round(extco.index, decimals = 2)) + sns.heatmap(extco, cmap='jet', vmax=extco.max().max(), vmin=0, cbar_kws={'label': 'Extinction Coefficient / $\mathrm{m^{-1}}$'})#,yticklabels = np.round(extco.index, decimals=2)) + plt.tight_layout() + plt.title(f'channel {channel}') + plt.savefig(os.path.join(output_path,f'sns_extco_time_{channel}.png')) + plt.close() + +for channel in color_channels: + fig, ax = plt.subplots(figsize=(10, 6)) + extco = sim.get_ledparams_at_led_array(channel=channel, led_array_id=0, window=window, yaxis='height').T #, n_ref=10 + extco = extco.set_index(np.round(extco.index, decimals = 2)) + sns.heatmap(extco[::-1], cmap='jet', vmax=1.0,vmin= 0.1, cbar_kws={'label': 'LED-Parameter'})#,yticklabels = np.round(extco.index, decimals=2)) + plt.tight_layout() + plt.title(f'channel{channel}') + plt.savefig(os.path.join(output_path,f'sns_led_time_{channel}.png')) + plt.close() \ No newline at end of file diff --git a/ledsa/tools/exposure_checker.py b/ledsa/tools/exposure_checker.py new file mode 100644 index 0000000..2d74f38 --- /dev/null +++ b/ledsa/tools/exposure_checker.py @@ -0,0 +1,41 @@ +import os +from ledsa.core.image_reading import read_channel_data_from_img, get_exif_entry +import pandas as pd + +# Configure the image path and range +image_dir = os.getcwd() # Update this to your image directory +list_image = [f for f in os.listdir(image_dir) if '.CR3' in f or '.CR2' in f or '.NEF' in f] + +# image_name_string = "DSC_{:04d}.CR3" # F-string template for image names +# image_range = range(23, 24) # Range of image numbers to process +channels = [0,1,2] # Color channel to analyze (0=Red, 1=Green, 2=Blue) +saturation = 2**14-1 + +df_exposure_test = pd.DataFrame() +# Process each image in the range +for img in list_image: + # Create the image filename using the template + image_filename = os.path.join(image_dir,img) + + # Check if the file exists + if not os.path.exists(image_filename): + print(f"Image {image_filename} not found, skipping.") + continue + + print(f"Processing image: {image_filename}") + + # Read the image data for the specified channel + try: + for channel in channels: + channel_array = read_channel_data_from_img(image_filename, channel) + df_exposure_test.loc[img,f'ch{channel}'] = channel_array.max() + df_exposure_test.loc[img,f'ch{channel}_sat'] = channel_array.max()/saturation*100 + except: + pass + +print(f'Image with min Channel 0 Saturation {df_exposure_test['ch0_sat'].min()}') +print(f'Image with max Channel 0 Saturation {df_exposure_test['ch0_sat'].max()}') +print(f'Image with min Channel 1 Saturation {df_exposure_test['ch1_sat'].min()}') +print(f'Image with max Channel 1 Saturation {df_exposure_test['ch1_sat'].max()}') +print(f'Image with min Channel 2 Saturation {df_exposure_test['ch2_sat'].min()}') +print(f'Image with max Channel 2 Saturation {df_exposure_test['ch2_sat'].max()}') \ No newline at end of file From 38b0dcac07c3296cfa99fcb72766a469deb0aa26 Mon Sep 17 00:00:00 2001 From: Anna Troff Date: Tue, 2 Dec 2025 11:59:53 +0100 Subject: [PATCH 08/14] change .arw --- ledsa/core/image_reading.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ledsa/core/image_reading.py b/ledsa/core/image_reading.py index cccba9a..d2fecf8 100644 --- a/ledsa/core/image_reading.py +++ b/ledsa/core/image_reading.py @@ -24,7 +24,7 @@ def read_channel_data_from_img(filename: str, channel: int) -> np.ndarray: extension = os.path.splitext(filename)[-1] if extension in ['.JPG', '.JPEG', '.jpg', '.jpeg', '.PNG', '.png']: channel_array = _read_channel_data_from_img_file(filename, channel) - elif extension in ['.CR2','.CR3','.NEF']: + elif extension in ['.CR2','.CR3','.NEF','.ARW']: channel_array = _read_channel_data_from_raw_file(filename, channel) return channel_array From 7fa4d9dafd1b1b442844f4b7d79a6f6490cd3cca Mon Sep 17 00:00:00 2001 From: Anna Troff Date: Thu, 4 Dec 2025 10:37:05 +0100 Subject: [PATCH 09/14] change photo_renamer to work with CR3 --- ledsa/tools/photo_renamer.py | 65 ++++++++++++------------------------ 1 file changed, 21 insertions(+), 44 deletions(-) diff --git a/ledsa/tools/photo_renamer.py b/ledsa/tools/photo_renamer.py index 343b4ed..934857e 100644 --- a/ledsa/tools/photo_renamer.py +++ b/ledsa/tools/photo_renamer.py @@ -4,7 +4,7 @@ from os import path import csv import pandas as pd -import exifread +from ledsa.core.image_reading import get_exif_entry def set_working_dir(): @@ -33,9 +33,7 @@ def get_files(): """ # Get file type inputs from user image_types = input("What image types do you want to take into account? (Seperate by \",\"):") - raw_types = input("What raw types do you want to take into account? (Seperate by \",\"):") image_types = [x.strip() for x in image_types.split(',')] - raw_types = [x.strip() for x in raw_types.split(',')] image_dict = {} image_files = [] @@ -47,31 +45,21 @@ def get_files(): for image in image_files: # Extract EXIF datetime data with open(image, 'rb') as image_file: - tag_datetime = 'DateTimeOriginal' - tag_subsectime = 'SubSecTimeDigitized' - exif = exifread.process_file(image_file, details=False) - capture_date = exif[f"EXIF {tag_datetime}"].values - try: - # Try parsing with subsecond precision - subsec_time = exif[f"EXIF {tag_subsectime}"].values - datetime_object = datetime.strptime(capture_date + "." + subsec_time, '%Y:%m:%d %H:%M:%S.%f') - except: - # Fall back to second precision - datetime_object = datetime.strptime(capture_date, '%Y:%m:%d %H:%M:%S') - - # Find matching raw file if it exists - for file_type in raw_types: - raw_file = image.rsplit(".", 1)[0] + "." + file_type - if path.isfile(raw_file): - raw_file = raw_file - break + if '.CR3' in image: + tag_datetime = 'Creation date' else: - raw_file = "NaT" - - image_dict[image] = [datetime_object, raw_file] + tag_datetime = 'DateTimeOriginal' + capture_date = get_exif_entry(image,tag_datetime) + # Fall back to second precision + if '-' in capture_date: + datetime_object = datetime.strptime(capture_date, '%Y-%m-%d %H:%M:%S') + else: + datetime_object = datetime.strptime(capture_date, '%Y:%m:%d %H:%M:%S') + image_file.close() + image_dict[image] = [datetime_object] # Create and sort DataFrame - image_df = pd.DataFrame.from_dict(image_dict, columns=["capture_date", "raw_file"], orient='index') + image_df = pd.DataFrame.from_dict(image_dict, columns=["capture_date"], orient='index') image_df = image_df.sort_values(by=['capture_date'], ascending=True) return image_df @@ -99,20 +87,14 @@ def rename_images_by_date(image_df): # Preview rename changes and write to log with open(filename, 'w') as log_file: writer = csv.writer(log_file) - writer.writerow(("old_image_name", "new_image_name", "old_raw_name", "new_raw_name")) + writer.writerow(("old_image_name", "new_image_name")) for index, row in image_df.iterrows(): - image_year = row['capture_date'].strftime('%-y%m%d') - raw_old_name = row['raw_file'] + image_year = row['capture_date'].strftime('%y%m%d') # Generate new filenames - if pd.isnull(raw_old_name): - raw_new_name = "NaT" - else: - file_extension = raw_old_name.split('.')[-1] - raw_new_name = "{0}_{1}_{2}.{3}".format(image_year, name, count, file_extension) - new_image_name = "{0}_{1}_{2}.jpg".format(image_year, name, count) - print("{0} --> {1} {2} --> {3}".format(index, new_image_name, raw_old_name, raw_new_name)) - writer.writerow((index, new_image_name, raw_old_name, raw_new_name)) + new_image_name = "{0}_{1}.{2}".format(name, f'{count:04d}',index.split('.')[-1]) + print("{0} --> {1}".format(index, new_image_name)) + writer.writerow((index, new_image_name)) count += 1 # Process user choice to proceed or cancel @@ -122,14 +104,9 @@ def rename_images_by_date(image_df): # Perform the actual renaming count = 1 for index, row in image_df.iterrows(): - image_year = row['capture_date'].strftime('%-y%m%d') - raw_old_name = row['raw_file'] - - if not pd.isnull(raw_old_name): - file_extension = raw_old_name.split('.')[-1] - raw_new_name = "{0}_{1}_{2}.{3}".format(image_year, name, count, file_extension) - os.rename(raw_old_name, raw_new_name) - new_image_name = "{0}_{1}_{2}.jpg".format(image_year, name, count) + image_year = row['capture_date'].strftime('%y%m%d') + new_image_name = "{0}_{1}.{2}".format(name, f'{count:04d}',index.split('.')[-1]) + os.rename(index, new_image_name) count += 1 print("Files successfully renamed!".format(count)) From 59a1b6bca5e6409de5760fc1cd184e5488af630b Mon Sep 17 00:00:00 2001 From: Anna Troff Date: Thu, 4 Dec 2025 10:38:11 +0100 Subject: [PATCH 10/14] include tag for cr3 exif reading --- ledsa/core/ConfigData.py | 13 +++++++++++-- ledsa/core/image_reading.py | 4 ++-- ledsa/data_extraction/init_functions.py | 5 ++++- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/ledsa/core/ConfigData.py b/ledsa/core/ConfigData.py index 8b92298..e4e4318 100644 --- a/ledsa/core/ConfigData.py +++ b/ledsa/core/ConfigData.py @@ -274,7 +274,11 @@ def in_time_diff_to_img_time(self) -> None: time = self['DEFAULT']['time_ref_img_time'] print(os.path.join(self['DEFAULT']['img_directory'], self['DEFAULT']['img_name_string'].format( self['DEFAULT']['time_img_id']))) - tag = 'EXIF DateTimeOriginal' + if '.CR3' in os.path.join(self['DEFAULT']['img_directory'], self['DEFAULT']['img_name_string'].format( + self['DEFAULT']['time_img_id'])): + tag = 'Creation date' + else: + tag = 'EXIF DateTimeOriginal' exif_entry = get_exif_entry(os.path.join(self['DEFAULT']['img_directory'], self['DEFAULT']['img_name_string'].format( self['DEFAULT']['time_img_id'])), tag) date, time_meta = exif_entry.split(' ') @@ -353,8 +357,13 @@ def get_start_time(self) -> None: Updates the 'DEFAULT' key with the 'start_time' computed. """ + if '.CR3' in os.path.join(self['DEFAULT']['img_directory'], self['DEFAULT']['img_name_string'].format( + self['DEFAULT']['first_img_experiment_id'])): + tag = 'Creation date' + else: + tag = 'EXIF DateTimeOriginal' exif_entry = get_exif_entry(os.path.join(self['DEFAULT']['img_directory'], self['DEFAULT']['img_name_string'].format( - self['DEFAULT']['first_img_experiment_id'])), 'EXIF DateTimeOriginal') + self['DEFAULT']['first_img_experiment_id'])), tag) date, time_meta = exif_entry.split(' ') time_img = _get_datetime_from_str(date, time_meta) start_time = time_img - timedelta(seconds=self['DEFAULT'].getint('exif_time_infront_real_time')) diff --git a/ledsa/core/image_reading.py b/ledsa/core/image_reading.py index d2fecf8..1815ec7 100644 --- a/ledsa/core/image_reading.py +++ b/ledsa/core/image_reading.py @@ -24,7 +24,7 @@ def read_channel_data_from_img(filename: str, channel: int) -> np.ndarray: extension = os.path.splitext(filename)[-1] if extension in ['.JPG', '.JPEG', '.jpg', '.jpeg', '.PNG', '.png']: channel_array = _read_channel_data_from_img_file(filename, channel) - elif extension in ['.CR2','.CR3','.NEF','.ARW']: + elif extension in ['.CR2','.CR3','.NEF','.ARW','.DNG']: channel_array = _read_channel_data_from_raw_file(filename, channel) return channel_array @@ -108,7 +108,7 @@ def get_exif_entry(filename: str, tag: str) -> str: # Versuch, die Aufnahmezeit zu finden try: for line in metadata.exportPlaintext(): - if "Creation date" in line or "Date/Time Original" in line: + if tag in line: return line.split(":", 1)[1].strip() except: print("Keine Aufnahmezeit gefunden.") diff --git a/ledsa/data_extraction/init_functions.py b/ledsa/data_extraction/init_functions.py index 70200d7..cd53be5 100644 --- a/ledsa/data_extraction/init_functions.py +++ b/ledsa/data_extraction/init_functions.py @@ -195,7 +195,10 @@ def _build_img_data_string(build_type: str, config: ConfigData) -> str: img_increment = config.getint(build_type, 'num_skip_imgs') + 1 if build_type == 'analyse_photo' else 1 img_id_list = _find_img_number_list(first_img_id, last_img_id, img_increment) for img_id in img_id_list: - tag = 'EXIF DateTimeOriginal' + if '.CR3' in config['DEFAULT']['img_name_string']: + tag = 'Creation date' + else: + tag = 'EXIF DateTimeOriginal' experiment_time, time = _calc_experiment_and_real_time(build_type, config, tag, img_id) img_data += (str(img_idx) + ',' + config[build_type]['img_name_string'].format(img_id) + ',' + time.strftime('%H:%M:%S') + ',' + str(experiment_time) + '\n') From e42f711ca364f89f243aa9f3d0834a712faba33d Mon Sep 17 00:00:00 2001 From: Anna Troff Date: Thu, 4 Dec 2025 16:09:27 +0100 Subject: [PATCH 11/14] add .dng --- ledsa/tools/exposure_checker.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ledsa/tools/exposure_checker.py b/ledsa/tools/exposure_checker.py index 2d74f38..9ba1db9 100644 --- a/ledsa/tools/exposure_checker.py +++ b/ledsa/tools/exposure_checker.py @@ -4,7 +4,7 @@ # Configure the image path and range image_dir = os.getcwd() # Update this to your image directory -list_image = [f for f in os.listdir(image_dir) if '.CR3' in f or '.CR2' in f or '.NEF' in f] +list_image = [f for f in os.listdir(image_dir) if '.CR3' in f or '.CR2' in f or '.NEF' in f or '.ARW' in f or '.DNG' in f] # image_name_string = "DSC_{:04d}.CR3" # F-string template for image names # image_range = range(23, 24) # Range of image numbers to process From 2cae1c1b43cca11535e9dbdc5e801212061dcea1 Mon Sep 17 00:00:00 2001 From: Anna Troff Date: Thu, 15 Jan 2026 13:08:14 +0100 Subject: [PATCH 12/14] cr3 format for exposure checker --- ledsa/tools/exposure_checker.ipynb | 64 ++++++++------ ledsa/tools/exposure_checker.py | 41 --------- ledsa/tools/photo_renamer.py | 66 +++++++++----- ledsa/tools/photo_renamer_cr3.py | 137 +++++++++++++++++++++++++++++ 4 files changed, 220 insertions(+), 88 deletions(-) delete mode 100644 ledsa/tools/exposure_checker.py create mode 100644 ledsa/tools/photo_renamer_cr3.py diff --git a/ledsa/tools/exposure_checker.ipynb b/ledsa/tools/exposure_checker.ipynb index 21e14c5..427ed3c 100644 --- a/ledsa/tools/exposure_checker.ipynb +++ b/ledsa/tools/exposure_checker.ipynb @@ -1,43 +1,50 @@ { "cells": [ { - "metadata": {}, "cell_type": "markdown", + "id": "d5b8be1e27d27315", + "metadata": {}, "source": [ "# Image Exposure Checker\n", "\n", - "This notebook allows you to check the exposure of a series of pictures. It calculates the pixel saturation value as a percentage.\n" - ], - "id": "d5b8be1e27d27315" + "This notebook allows you to check the exposure of a series of pictures. It calculates the pixel saturation value as a percentage.\n", + "\n", + "Does not work for Images in CR3 format.\n" + ] }, { - "metadata": {}, "cell_type": "markdown", - "source": "# Dependencies\n", - "id": "9df8a44a552be70" + "id": "9df8a44a552be70", + "metadata": {}, + "source": [ + "# Dependencies\n" + ] }, { - "metadata": {}, "cell_type": "code", - "outputs": [], "execution_count": null, + "id": "41c98f47ba1f266f", + "metadata": {}, + "outputs": [], "source": [ "import os\n", "from ledsa.core.image_reading import read_channel_data_from_img, get_exif_entry" - ], - "id": "41c98f47ba1f266f" + ] }, { - "metadata": {}, "cell_type": "markdown", - "source": "# Configuration\n", - "id": "8bab111a65dd1b89" + "id": "8bab111a65dd1b89", + "metadata": {}, + "source": [ + "# Configuration\n" + ] }, { - "metadata": {}, "cell_type": "code", - "outputs": [], "execution_count": null, + "id": "aa799b526e7eb076", + "metadata": {}, + "outputs": [], "source": [ "# Configure the image path and range\n", "image_dir = \"/path/to/your/images\" # Update this to your image directory\n", @@ -45,20 +52,22 @@ "image_range = range(1, 10) # Range of image numbers to process\n", "channel = 0 # Color channel to analyze (0=Red, 1=Green, 2=Blue)\n", "saturation = 255" - ], - "id": "aa799b526e7eb076" + ] }, { - "metadata": {}, "cell_type": "markdown", - "source": "# Process Images\n", - "id": "9b3295c6d521431e" + "id": "9b3295c6d521431e", + "metadata": {}, + "source": [ + "# Process Images\n" + ] }, { - "metadata": {}, "cell_type": "code", - "outputs": [], "execution_count": null, + "id": "344c5f7ce039571b", + "metadata": {}, + "outputs": [], "source": [ "# Process each image in the range\n", "for img_id in image_range:\n", @@ -89,11 +98,14 @@ "\n", " \n", "\n" - ], - "id": "344c5f7ce039571b" + ] } ], - "metadata": {}, + "metadata": { + "language_info": { + "name": "python" + } + }, "nbformat": 4, "nbformat_minor": 5 } diff --git a/ledsa/tools/exposure_checker.py b/ledsa/tools/exposure_checker.py deleted file mode 100644 index 9ba1db9..0000000 --- a/ledsa/tools/exposure_checker.py +++ /dev/null @@ -1,41 +0,0 @@ -import os -from ledsa.core.image_reading import read_channel_data_from_img, get_exif_entry -import pandas as pd - -# Configure the image path and range -image_dir = os.getcwd() # Update this to your image directory -list_image = [f for f in os.listdir(image_dir) if '.CR3' in f or '.CR2' in f or '.NEF' in f or '.ARW' in f or '.DNG' in f] - -# image_name_string = "DSC_{:04d}.CR3" # F-string template for image names -# image_range = range(23, 24) # Range of image numbers to process -channels = [0,1,2] # Color channel to analyze (0=Red, 1=Green, 2=Blue) -saturation = 2**14-1 - -df_exposure_test = pd.DataFrame() -# Process each image in the range -for img in list_image: - # Create the image filename using the template - image_filename = os.path.join(image_dir,img) - - # Check if the file exists - if not os.path.exists(image_filename): - print(f"Image {image_filename} not found, skipping.") - continue - - print(f"Processing image: {image_filename}") - - # Read the image data for the specified channel - try: - for channel in channels: - channel_array = read_channel_data_from_img(image_filename, channel) - df_exposure_test.loc[img,f'ch{channel}'] = channel_array.max() - df_exposure_test.loc[img,f'ch{channel}_sat'] = channel_array.max()/saturation*100 - except: - pass - -print(f'Image with min Channel 0 Saturation {df_exposure_test['ch0_sat'].min()}') -print(f'Image with max Channel 0 Saturation {df_exposure_test['ch0_sat'].max()}') -print(f'Image with min Channel 1 Saturation {df_exposure_test['ch1_sat'].min()}') -print(f'Image with max Channel 1 Saturation {df_exposure_test['ch1_sat'].max()}') -print(f'Image with min Channel 2 Saturation {df_exposure_test['ch2_sat'].min()}') -print(f'Image with max Channel 2 Saturation {df_exposure_test['ch2_sat'].max()}') \ No newline at end of file diff --git a/ledsa/tools/photo_renamer.py b/ledsa/tools/photo_renamer.py index 934857e..e470e83 100644 --- a/ledsa/tools/photo_renamer.py +++ b/ledsa/tools/photo_renamer.py @@ -4,8 +4,9 @@ from os import path import csv import pandas as pd -from ledsa.core.image_reading import get_exif_entry +import exifread +#does not work for Images in CR3 format def set_working_dir(): """ @@ -33,7 +34,9 @@ def get_files(): """ # Get file type inputs from user image_types = input("What image types do you want to take into account? (Seperate by \",\"):") + raw_types = input("What raw types do you want to take into account? (Seperate by \",\"):") image_types = [x.strip() for x in image_types.split(',')] + raw_types = [x.strip() for x in raw_types.split(',')] image_dict = {} image_files = [] @@ -45,21 +48,31 @@ def get_files(): for image in image_files: # Extract EXIF datetime data with open(image, 'rb') as image_file: - if '.CR3' in image: - tag_datetime = 'Creation date' - else: - tag_datetime = 'DateTimeOriginal' - capture_date = get_exif_entry(image,tag_datetime) - # Fall back to second precision - if '-' in capture_date: - datetime_object = datetime.strptime(capture_date, '%Y-%m-%d %H:%M:%S') - else: + tag_datetime = 'DateTimeOriginal' + tag_subsectime = 'SubSecTimeDigitized' + exif = exifread.process_file(image_file, details=False) + capture_date = exif[f"EXIF {tag_datetime}"].values + try: + # Try parsing with subsecond precision + subsec_time = exif[f"EXIF {tag_subsectime}"].values + datetime_object = datetime.strptime(capture_date + "." + subsec_time, '%Y:%m:%d %H:%M:%S.%f') + except: + # Fall back to second precision datetime_object = datetime.strptime(capture_date, '%Y:%m:%d %H:%M:%S') - image_file.close() - image_dict[image] = [datetime_object] + + # Find matching raw file if it exists + for file_type in raw_types: + raw_file = image.rsplit(".", 1)[0] + "." + file_type + if path.isfile(raw_file): + raw_file = raw_file + break + else: + raw_file = "NaT" + + image_dict[image] = [datetime_object, raw_file] # Create and sort DataFrame - image_df = pd.DataFrame.from_dict(image_dict, columns=["capture_date"], orient='index') + image_df = pd.DataFrame.from_dict(image_dict, columns=["capture_date", "raw_file"], orient='index') image_df = image_df.sort_values(by=['capture_date'], ascending=True) return image_df @@ -87,14 +100,20 @@ def rename_images_by_date(image_df): # Preview rename changes and write to log with open(filename, 'w') as log_file: writer = csv.writer(log_file) - writer.writerow(("old_image_name", "new_image_name")) + writer.writerow(("old_image_name", "new_image_name", "old_raw_name", "new_raw_name")) for index, row in image_df.iterrows(): - image_year = row['capture_date'].strftime('%y%m%d') + image_year = row['capture_date'].strftime('%-y%m%d') + raw_old_name = row['raw_file'] # Generate new filenames - new_image_name = "{0}_{1}.{2}".format(name, f'{count:04d}',index.split('.')[-1]) - print("{0} --> {1}".format(index, new_image_name)) - writer.writerow((index, new_image_name)) + if pd.isnull(raw_old_name): + raw_new_name = "NaT" + else: + file_extension = raw_old_name.split('.')[-1] + raw_new_name = "{0}_{1}_{2}.{3}".format(image_year, name, count, file_extension) + new_image_name = "{0}_{1}_{2}.jpg".format(image_year, name, count) + print("{0} --> {1} {2} --> {3}".format(index, new_image_name, raw_old_name, raw_new_name)) + writer.writerow((index, new_image_name, raw_old_name, raw_new_name)) count += 1 # Process user choice to proceed or cancel @@ -104,9 +123,14 @@ def rename_images_by_date(image_df): # Perform the actual renaming count = 1 for index, row in image_df.iterrows(): - image_year = row['capture_date'].strftime('%y%m%d') - new_image_name = "{0}_{1}.{2}".format(name, f'{count:04d}',index.split('.')[-1]) - + image_year = row['capture_date'].strftime('%-y%m%d') + raw_old_name = row['raw_file'] + + if not pd.isnull(raw_old_name): + file_extension = raw_old_name.split('.')[-1] + raw_new_name = "{0}_{1}_{2}.{3}".format(image_year, name, count, file_extension) + os.rename(raw_old_name, raw_new_name) + new_image_name = "{0}_{1}_{2}.jpg".format(image_year, name, count) os.rename(index, new_image_name) count += 1 print("Files successfully renamed!".format(count)) diff --git a/ledsa/tools/photo_renamer_cr3.py b/ledsa/tools/photo_renamer_cr3.py new file mode 100644 index 0000000..d789900 --- /dev/null +++ b/ledsa/tools/photo_renamer_cr3.py @@ -0,0 +1,137 @@ +import glob +import os +from datetime import datetime +from os import path +import csv +import pandas as pd +from ledsa.core.image_reading import get_exif_entry + + +def set_working_dir(): + """ + Prompts user for directory path and changes to that directory if it exists. + Exits program if directory is invalid. + """ + working_dir = input("Set Working directory:") + if path.exists(working_dir): + os.chdir(working_dir) + print("Working directory is set to \"{0}\"".format(os.getcwd())) + else: + print("\"{0}\" does not exist!".format(os.getcwd())) + exit() + + +def get_files(): + """ + Prompts user for image and raw file types to process. + Extracts capture date from EXIF data of images. + Finds corresponding raw files if they exist. + + Returns: + pd.DataFrame: DataFrame containing image filenames as index and columns for + capture date and associated raw filenames, sorted by capture date. + """ + # Get file type inputs from user + image_types = input("What image types do you want to take into account? (Seperate by \",\"):") + image_types = [x.strip() for x in image_types.split(',')] + image_dict = {} + image_files = [] + + # Find all matching image files + for file_type in image_types: + image_files.extend(glob.glob('*.{}'.format(file_type))) + + # Process each image file + for image in image_files: + # Extract EXIF datetime data + with open(image, 'rb') as image_file: + if '.CR3' in image: + tag_datetime = 'Creation date' + else: + tag_datetime = 'EXIF DateTimeOriginal' + capture_date = get_exif_entry(image,tag_datetime) + # Fall back to second precision + if '-' in capture_date: + datetime_object = datetime.strptime(capture_date, '%Y-%m-%d %H:%M:%S') + else: + datetime_object = datetime.strptime(capture_date, '%Y:%m:%d %H:%M:%S') + image_file.close() + image_dict[image] = [datetime_object] + + # Create and sort DataFrame + image_df = pd.DataFrame.from_dict(image_dict, columns=["capture_date"], orient='index') + image_df = image_df.sort_values(by=['capture_date'], ascending=True) + return image_df + + +def rename_images_by_date(image_df): + """ + Rename image and raw files based on capture date and user-provided name. + + Creates a log file of all renames. After previewing changes, user can choose + to proceed with renaming or cancel. User can also choose to keep or delete + the log file afterwards. + + Args: + image_df (pd.DataFrame): DataFrame containing image metadata and filenames + to be processed. + """ + # Get base name from user and setup logging + name = input("Please enter name for image:") + print("Files are renamed as follows:") + count = 1 + now = datetime.now() + now_str = now.strftime("%Y_%m_%d_%H_%M_%S") + filename = f"{now_str}_{name}_rename_log.csv" + + # Preview rename changes and write to log + with open(filename, 'w') as log_file: + writer = csv.writer(log_file) + writer.writerow(("old_image_name", "new_image_name")) + for index, row in image_df.iterrows(): + image_year = row['capture_date'].strftime('%y%m%d') + + # Generate new filenames + new_image_name = "{0}_{1}.{2}".format(name, f'{count:04d}',index.split('.')[-1]) + print("{0} --> {1}".format(index, new_image_name)) + writer.writerow((index, new_image_name)) + count += 1 + + # Process user choice to proceed or cancel + while True: + continue_rename = input("Do you want to continue? yes[y] or no[n]") + if continue_rename == "y": + # Perform the actual renaming + count = 1 + for index, row in image_df.iterrows(): + image_year = row['capture_date'].strftime('%y%m%d') + new_image_name = "{0}_{1}.{2}".format(name, f'{count:04d}',index.split('.')[-1]) + + os.rename(index, new_image_name) + count += 1 + print("Files successfully renamed!".format(count)) + + # Handle log file retention + keep_log = input("Do you want to keep the changelog? yes[y] or no[n]") + if keep_log == 'y': + print(f"{filename} saved!") + exit() + elif keep_log == 'n': + os.remove(filename) + print("Changelog deleted!") + exit() + elif continue_rename == "n": + print("No files were renamed!") + exit() + else: + continue + + +def main(): + set_working_dir() + image_df = get_files() + rename_images_by_date(image_df) + + +if __name__ == '__main__': + main() From ae3e821cec2f2481bd7629fc6c5a90b9b1c8e95d Mon Sep 17 00:00:00 2001 From: Anna Troff Date: Thu, 15 Jan 2026 13:08:40 +0100 Subject: [PATCH 13/14] comment cr3 format for image reading --- ledsa/core/image_reading.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/ledsa/core/image_reading.py b/ledsa/core/image_reading.py index 1815ec7..2bbbbee 100644 --- a/ledsa/core/image_reading.py +++ b/ledsa/core/image_reading.py @@ -93,6 +93,8 @@ def get_exif_entry(filename: str, tag: str) -> str: :rtype: str :raises KeyError: If the EXIF tag is not found in the image metadata. """ + + #Read Metadata CR3 (! ISO, Blende und Verschlusszeit kann durch diese Methode nicht ausgegeben werden) if '.CR3' in filename: parser = createParser(str(filename)) if not parser: @@ -102,10 +104,6 @@ def get_exif_entry(filename: str, tag: str) -> str: if not metadata: raise ValueError("Keine Metadaten gefunden.") - # Alle Metadaten anzeigen, falls du schauen willst was verfügbar ist - # print(metadata.exportPlaintext()) - - # Versuch, die Aufnahmezeit zu finden try: for line in metadata.exportPlaintext(): if tag in line: From 39ba3ebdb948002a5e9a2c3833de2986d0610023 Mon Sep 17 00:00:00 2001 From: Anna Troff Date: Thu, 15 Jan 2026 13:15:36 +0100 Subject: [PATCH 14/14] remove postprocessing overview --- ledsa/postprocessing/auswertung.py | 101 ----------------------------- 1 file changed, 101 deletions(-) delete mode 100644 ledsa/postprocessing/auswertung.py diff --git a/ledsa/postprocessing/auswertung.py b/ledsa/postprocessing/auswertung.py deleted file mode 100644 index 50f3f88..0000000 --- a/ledsa/postprocessing/auswertung.py +++ /dev/null @@ -1,101 +0,0 @@ -import matplotlib.pyplot as plt -from matplotlib import rcParams -from mpl_toolkits.axes_grid1.inset_locator import InsetPosition -import seaborn as sns -import numpy as np -import pandas as pd -from ledsa.postprocessing.simulation import SimData -import os -from matplotlib.ticker import FormatStrFormatter - -rcParams['font.family'] = 'serif' -rcParams['font.size'] = 10 -cm = 1 / 2.54 - -# Input Dir (Simulations) !alle channel müssen abgegriffen werden -path_simulation = os.getcwd() -sim = SimData(path_simulation) -output_path = os.path.join(path_simulation,'output') - -if not os.path.isdir(output_path): - os.makedirs (output_path) - - -#read possible times -df_info = pd.read_csv('image_infos.csv', header = 0) -times = df_info['Experiment_Time[s]'] - -# Parameters -led_array_id = 0 # LED array to analyze -window = 1 # Size of moving average window -color_channels = [0, 1, 2] # RGB channels - -# Create figure Extinction -fig, ax = plt.subplots(figsize=(10, 6)) - -# Plot extinction coefficients for each channel -for channel in color_channels: - # Get extinction coefficients at specified height - extco = sim.get_extco_at_led_array(channel=channel, led_array_id=led_array_id, window=window, yaxis='layer') - middleIndex = (len(extco.columns) - 1)//2 - # Plot with different colors for each channel - colors = ['red', 'green', 'blue'] - ax.plot(extco.index, extco.iloc[:,middleIndex], - color=colors[channel], - label=f'Channel {channel}') - # ax.fill_between(extco.index, 10,20, color=colors[channel], alpha = 0.5) - ax.fill_between(extco.index, extco.iloc[:,:].T.max(), extco.iloc[:,:].T.min(), color=colors[channel], alpha = 0.1) - -ax.set_xlabel('Time / s') -ax.set_ylabel('Extinction Coefficient / $\mathrm{m^{-1}}$') -ax.set_title(f'Extinction Coefficients at LED-ID {middleIndex}, LED Array {led_array_id}') -ax.grid(True) -ax.legend() -plt.tight_layout() -plt.savefig(os.path.join(output_path,'extco_time_range.png')) -plt.close() - -# Create figure -fig, ax = plt.subplots(figsize=(10, 6)) - -# Plot extinction coefficients for each channel -for channel in color_channels: - # Get extinction coefficients at specified height - extco = sim.get_ledparams_at_led_array(channel=channel, led_array_id=led_array_id, window=window, yaxis='height') - middleIndex = (len(extco.columns) - 1)//2 - # Plot with different colors for each channel - colors = ['red', 'green', 'blue'] - ax.plot(extco.index, extco.iloc[:,middleIndex], - color=colors[channel], - label=f'Channel {channel}') - ax.fill_between(extco.index, extco.iloc[:,:].T.max(), extco.iloc[:,:].T.min(), color=colors[channel], alpha = 0.2) - -ax.set_xlabel('Time / s') -ax.set_ylabel('LED Parameters') -ax.set_title(f'LED Parameters at LED Parameter {middleIndex}, LED Array {led_array_id}') -ax.grid(True) -ax.legend() -plt.tight_layout() -plt.savefig(os.path.join(output_path,'led_time_range.png')) -plt.close() - -# Parameters -for channel in color_channels: - fig, ax = plt.subplots(figsize=(10, 6)) - extco = sim.get_extco_at_led_array(channel = channel, led_array_id =led_array_id, yaxis='height', window=window).T - extco = extco.set_index(np.round(extco.index, decimals = 2)) - sns.heatmap(extco, cmap='jet', vmax=extco.max().max(), vmin=0, cbar_kws={'label': 'Extinction Coefficient / $\mathrm{m^{-1}}$'})#,yticklabels = np.round(extco.index, decimals=2)) - plt.tight_layout() - plt.title(f'channel {channel}') - plt.savefig(os.path.join(output_path,f'sns_extco_time_{channel}.png')) - plt.close() - -for channel in color_channels: - fig, ax = plt.subplots(figsize=(10, 6)) - extco = sim.get_ledparams_at_led_array(channel=channel, led_array_id=0, window=window, yaxis='height').T #, n_ref=10 - extco = extco.set_index(np.round(extco.index, decimals = 2)) - sns.heatmap(extco[::-1], cmap='jet', vmax=1.0,vmin= 0.1, cbar_kws={'label': 'LED-Parameter'})#,yticklabels = np.round(extco.index, decimals=2)) - plt.tight_layout() - plt.title(f'channel{channel}') - plt.savefig(os.path.join(output_path,f'sns_led_time_{channel}.png')) - plt.close() \ No newline at end of file