diff --git a/scripts/main_seq_2arms.py b/scripts/main_seq_2arms.py index 80f8bd0..d27df4c 100644 --- a/scripts/main_seq_2arms.py +++ b/scripts/main_seq_2arms.py @@ -55,23 +55,23 @@ collection_access = 'public' #'private'# Np = 64 # Number of pixels in one dimension of the image (image: NpxNp) ti = 1 # Integration time of the spectrometer -zoom = 1 # Numerical zoom applied in the DMD -xw_offset = 128 #Np*(zoom-1)/(2*zoom), -yh_offset = 0 #Np*(zoom-1)/(2*zoom)) +zoom = 2 # Numerical zoom applied in the DMD +xw_offset = 401 #Np*(zoom-1)/(2*zoom), +yh_offset = 301 #Np*(zoom-1)/(2*zoom)) pattern_compression = 1 scan_mode = 'Walsh' #'Walsh_inv' #'Raster_inv' #'Raster' # source = 'white_LED'#'Thorlabs_White_halogen_lamp'#'White_Zeiss_KL-2500-LCD_lamp'#No-light'#Laser_405nm_1.2W_A_0.14'#'''#' + white LED might'#'Bioblock power: II',#'HgAr multilines Source (HG-1 Oceanoptics)' -object_name = 'cat_pat5'#'Arduino_box_position_1'#'biopsy-9-posterior-margin'#GP-without-sample'##-OP'# -data_folder_name = '2024-09-13_test_adaptativePatterns'#'Patient-69_exvivo_LGG_BU' +object_name = 'cat2'#'Arduino_box_position_1'#'biopsy-9-posterior-margin'#GP-without-sample'##-OP'# +data_folder_name = '2024-10-18_test_without_dll'#'Patient-69_exvivo_LGG_BU' data_name = 'obj_' + object_name + '_source_' + source + '_' + scan_mode + '_im_'+str(Np)+'x'+str(Np)+'_ti_'+str(ti)+'ms_zoom_x'+str(zoom) camPar.acq_mode = 'snapshot'#'video' # camPar.vidFormat = 'avi' #'bin'# camPar.insert_patterns = 0 # 0: no insertion / 1: insert white patterns for the camera / In the case of snapshot, put 0 to avoid bad reco -camPar.gate_period = 16 # a multiple of the integration time of the spectro, between [2 - 16] (2: insert one white pattern between each pattern) +camPar.gate_period = 16 # a multiple of the integration time of the spectro, between [2 - 16] (2: insert one white pattern between each pattern) camPar.black_pattern_num = 1 # insert the picture number (in the pattern_source folder) of the pattern you want to insert -all_path = func_path(data_folder_name, data_name) -if 'mask_index' not in locals(): mask_index = []; x_mask_coord = []; y_mask_coord = []# execute "mask_index = []" to not apply the mask +all_path = func_path(data_folder_name, data_name, ask_overwrite = True) +if 'mask_index' not in locals(): mask_index = []; x_mask_coord = []; y_mask_coord = [] # execute "mask_index = []" to not apply the mask if all_path.aborted == False: metadata = MetaData( @@ -83,11 +83,11 @@ light_source = source, object = object_name, filter = 'Diffuser', #+ OD=0.3',#optical density = 0.1''No filter',#'linear colored filter',#'Orange filter (600nm)',#'Dichroic_420nm',#'HighPass_500nm + LowPass_750nm + Dichroic_560nm',#'BandPass filter 560nm Dl=10nm',#'None', # + , #'Nothing',#'Diffuser + HighPass_500nm + LowPass_750nm',##'Microsope objective x40',#'' linear colored filter + OD#0',#'Nothing',# - description = 'insert patterns into a freehand or geometrical ROI.' + description = 'last test before to merge the remote branches: main and install_without_lib.' # description = 'two positions of the lens 80mm, P1:12cm (zoom=0.5), P2:22cm (zoom=1.5) from the DMD. Dichroic plate (T:>420nm, R:<420nm), HighPass_500nm in front of the cam, GP: Glass Plate, OP: other position, OA: out of anapath', ) try: change_patterns(DMD = DMD, acquisition_params = acquisition_parameters, zoom = zoom, xw_offset = xw_offset, yh_offset = yh_offset, - force_change = True) + force_change = False) except: pass acquisition_parameters = AcquisitionParameters(pattern_compression = pattern_compression, pattern_dimension_x = Np, pattern_dimension_y = Np, @@ -134,7 +134,6 @@ GT = reconstruction_hadamard(acquisition_parameters, 'walsh', Q, spectral_data, Np) plot_reco_without_NN(acquisition_parameters, GT, all_path) #%% Neural Network setup (executed it just one time) -Meas = Np*Np if Np == 64: img_size_reco = 128 else: @@ -142,7 +141,7 @@ network_param = ReconstructionParameters( # Reconstruction network - M = Meas,#Np*Np-1, # Number of measurements + M = Np*Np, # Number of measurements img_size = img_size_reco, # Image size of the NN reconstruction arch = 'dc-net', # Main architecture denoi = 'unet', # Image domain denoiser (possibility to do not apply, put : None) @@ -175,8 +174,8 @@ setup_version, data_folder_name, data_name, collection_access, upload_metadata = 1) #%% Draw a ROI # Comment data_folder_name & data_name to draw a ROI in the current acquisition, else specify the acquisition name -# data_folder_name = '2024-09-13_test_adaptativePatterns' -# data_name = 'obj_cat_freehand_source_white_LED_Walsh_im_64x64_ti_1ms_zoom_x1' +# data_folder_name = '2024-09-16_test_without_dll' +# data_name = 'obj_cat3_source_white_LED_Walsh_im_64x64_ti_1ms_zoom_x1' mask_index, x_mask_coord, y_mask_coord = extract_ROI_coord(DMD_params, acquisition_parameters, all_path, data_folder_name, data_name, GT, ti, Np) #%% Disconnect diff --git a/setup.py b/setup.py index cccc760..40fca1a 100644 --- a/setup.py +++ b/setup.py @@ -12,12 +12,12 @@ long_description=readme, long_description_content_type = "text/markdown", install_requires=[ - 'ALP4lib @ git+https://github.com/guilhermebene/ALP4lib.git@7e35abf3a5c2e31652f7cfb2e4243b279b6a3a47', + 'ALP4lib @ git+https://github.com/openspyrit/ALP4lib@3db7bec88b260e5396626b1b185d7a2f678e9bbf', 'dataclasses-json (==0.5.2)', 'certifi', 'cycler', 'kiwisolver', - 'matplotlib', + 'matplotlib==3.7.5', 'numpy', 'msl-equipment @ git+https://github.com/MSLNZ/msl-equipment.git', 'Pillow', @@ -30,7 +30,10 @@ 'spyrit', 'wincertstore', 'pyueye', - 'girder-client' + 'tensorboard', + 'girder-client', + 'plotter', + 'tikzplotlib' ], packages=find_packages() ) diff --git a/spas/acquisition.py b/spas/acquisition.py index 4d59cb4..565d92e 100644 --- a/spas/acquisition.py +++ b/spas/acquisition.py @@ -92,7 +92,7 @@ class ALP4: import time import threading from plotter import Plotter -import cv2 + #from spas.visualization import snapshotVisu @@ -428,7 +428,9 @@ def _update_sequence(DMD: ALP4, bitplanes (int, optional): Pattern bitplanes. Defaults to 1. """ - + + import cv2 + path_base = Path(pattern_source) seqId = DMD.SeqAlloc(nbImg=len(pattern_order), @@ -450,7 +452,7 @@ def _update_sequence(DMD: ALP4, apply_mask = False mask_index = acquisition_params.mask_index - if mask_index != []: + if len(mask_index) > 0: apply_mask = True Npx = acquisition_params.pattern_dimension_x Npy = acquisition_params.pattern_dimension_y @@ -490,12 +492,12 @@ def _update_sequence(DMD: ALP4, patterns[y_offset:y_offset+len_im[0], x_offset:x_offset+len_im[1]] = im_HD - if pattern_name == 151: + if pattern_name == 800: plt.figure() # plt.imshow(pat_c_re) # plt.imshow(pat_mask_all_mat) # plt.imshow(pat_mask_all_mat_DMD) - plt.imshow(patterns) + plt.imshow(np.rot90(patterns,2)) plt.colorbar() plt.title('pattern n°' + str(pattern_name)) @@ -1274,7 +1276,7 @@ def measurement_callback(handle, info): # If we want to reconstruct during callb DMD_params.picture_time_us / 1e+6 / 10) DMD.Halt() else: - sleep(1) + sleep(0.1) timestamp, spectrum = ava.get_data() spectral_data_1 = (np.ctypeslib.as_array(spectrum[0:pixel_amount])) @@ -1291,10 +1293,8 @@ def measurement_callback(handle, info): # If we want to reconstruct during callb plt.yticks(fontsize=14) plt.grid() printed = False - while(True): - try: - # sleep(0.01) - + while(True): + try: timestamp, spectrum = ava.get_data() spectral_data_1 = (np.ctypeslib.as_array(spectrum[0:pixel_amount])) @@ -1303,7 +1303,7 @@ def measurement_callback(handle, info): # If we want to reconstruct during callb figure.canvas.draw() # drawing updated values figure.canvas.flush_events() # flush prior plot - + if not printed: print('Press "Ctrl + c" to exit') if np.amax(spectral_data_1) >= 65535: @@ -1317,13 +1317,9 @@ def measurement_callback(handle, info): # If we want to reconstruct during callb plt.close() get_ipython().run_line_magic('matplotlib', 'inline') break - - - ava.stop_measure() - AcquisitionResult = namedtuple('AcquisitionResult', [ 'spectral_data', 'spectrum_index', @@ -1459,7 +1455,7 @@ def acquire(ava: Avantes, (data, spectrum_index, timestamp, time, start_measurement_time, saturation_detected) = AcquisitionResults - print('Data acquired') + print('Acquisition number : ' + str(repetition) + ' finished') if reconstruct == True: queue_to_recon.put(data.T) @@ -1480,11 +1476,11 @@ def acquire(ava: Avantes, acquisition_params.acquired_spectra += spectrum_index acquisition_params.saturation_detected = saturation_detected - - # Print data for each repetition only if there are not too many repetitions - if (verbose) and repetitions <= 10: - if saturation_detected is True: - print('Saturation detected!') + + if saturation_detected is True: + print('!!!!!!!!!! Saturation detected in the spectro !!!!!!!!!!') + # Print data for each repetition + if (verbose): print('Spectra acquired: {}'.format(spectrum_index)) print('Mean callback acquisition time: {} ms'.format( np.mean(time))) @@ -1502,21 +1498,9 @@ def acquire(ava: Avantes, acquisition_params.update_timings(timestamps, measurement_time) # Real time between each spectrum acquisition by the spectrometer - print('Complete acquisition results:') - print('Spectra acquired: {}'.format( - acquisition_params.acquired_spectra)) - if acquisition_params.saturation_detected is True: - print('!!!!!!!!!! Saturation detected in the spectro !!!!!!!!!!') - print('Mean callback acquisition time: {} ms'.format( - acquisition_params.mean_callback_acquisition_time_ms)) - print('Total callback acquisition time: {} s'.format( - acquisition_params.total_callback_acquisition_time_s)) - print('Mean spectrometer acquisition time: {} ms'.format( - acquisition_params.mean_spectrometer_acquisition_time_ms)) - print('Total spectrometer acquisition time: {} s'.format( - acquisition_params.total_spectrometer_acquisition_time_s)) - print(f'Acquisition matrix dimension: {spectral_data.shape}') - + print('Complete acquisition done') + print('Spectra acquired: {}'.format(acquisition_params.acquired_spectra)) + print('Total acquisition time: {} s'.format(acquisition_params.total_spectrometer_acquisition_time_s)) print(f'Saving data to {metadata.output_directory}') _save_acquisition(metadata, DMD_params, spectrometer_params, @@ -1541,115 +1525,169 @@ def acquire(ava: Avantes, return spectral_data -def setup_tuneSpectro(spectrometer, - DMD, - DMD_initial_memory, - pattern_to_display, - ti : float = 1, - zoom : int = 1, - xw_offset: int = 128, - yh_offset: int = 0, - mask_index : np.array = []): - """ Setup the hadrware to tune the spectrometer in live. The goal is to find - the integration time of the spectrometer, noise is around 700 counts, - saturation is equak to 2**16=65535 - +def _acquire_raw_2arms(ava: Avantes, + DMD: ALP4, + camPar, + spectrometer_params: SpectrometerParameters, + DMD_params: DMDParameters, + acquisition_params: AcquisitionParameters, + metadata, + repetition, + repetitions + ) -> NamedTuple: + """Raw data acquisition. + + Setups a callback function to receive messages from spectrometer whenever a + measurement is ready to be read. Reads a measurement via a callback. + Args: - spectrometer (Avantes): + ava (Avantes): Connected spectrometer (Avantes object). - DMD (ALP4): + DMD (ALP4): Connected DMD. - DMD_initial_memory (int): - Initial memory available in DMD after initialization. - metadata (MetaData): - Metadata concerning the experiment, paths, file inputs and file - outputs. Must be created and filled up by the user. - acquisition_params (AcquisitionParameters): - Acquisition related metadata object. User must partially fill up - with pattern_compression, pattern_dimension_x, pattern_dimension_y. - pattern_to_display (string): - display one pattern on the DMD to tune the spectrometer. Default is - white pattern - ti (float): - The integration time of the spectrometer during one scan in miliseconds. - Default is 1 ms. - zoom (int): - digital zoom on the DMD. Default is 1 - xw_offset (int): - offset of the pattern in the DMD for zoom > 1 in the width (x) direction - yh_offset (int): - offset of the pattern in the DMD for zoom > 1 in the heihgt (y) direction - mask_index (Union[np.ndarray, str], optional): - Array of `int` type corresponding to the index of the mask vector where - the value is egal to 1 - - return: - metadata (MetaData): - Metadata concerning the experiment, paths, file inputs and file - outputs. Must be created and filled up by the user. spectrometer_params (SpectrometerParameters): Spectrometer metadata object with spectrometer configurations. DMD_params (DMDParameters): DMD metadata object with DMD configurations. + acquisition_params (AcquisitionParameters): + Acquisition related metadata object. + + Returns: + NamedTuple: NamedTuple containig spectral data and measurement timings. + spectral_data (ndarray): + 2D array of `float` of size (pattern_amount x pixel_amount) + containing measurements received from the spectrometer for each + pattern of a sequence. + spectrum_index (int): + Index of the last acquired spectrum. + timestamps (np.ndarray): + 1D array with `float` type elapsed time between each measurement + made by the spectrometer based on its internal clock. + Units in milliseconds. + measurement_time (np.ndarray): + 1D array with `float` type elapsed times between each callback. + Units in milliseconds. + start_measurement_time (float): + Time when acquisition started. + saturation_detected (bool): + Boolean incating if saturation was detected during acquisition. """ - - data_folder_name = 'Tune' - data_name = 'test' - # all_path = func_path(data_folder_name, data_name) + # def for spectrometer acquisition + def register_callback(measurement_time, timestamps, + spectral_data, ava): + + def measurement_callback(handle, info): # If we want to reconstruct during callback; can use it in here. Add function as parameter. + nonlocal spectrum_index + nonlocal saturation_detected - scan_mode = 'Walsh' - Np = 64 - source = '' - object_name = '' + measurement_time[spectrum_index] = perf_counter_ns() + + if info.contents.value >= 0: + timestamp,spectrum = ava.get_data() + spectral_data[spectrum_index,:] = ( + np.ctypeslib.as_array(spectrum[0:pixel_amount])) + + if np.any(ava.get_saturated_pixels() > 0): + saturation_detected = True - metadata = MetaData( - output_directory = '',#all_path.subfolder_path, - pattern_order_source = 'C:/openspyrit/spas/stats/pattern_order_' + scan_mode + '_' + str(Np) + 'x' + str(Np) + '.npz', - pattern_source = 'C:/openspyrit/spas/Patterns/Zoom_x' + str(zoom) + '/' + scan_mode + '_' + str(Np) + 'x' + str(Np), - pattern_prefix = scan_mode + '_' + str(Np) + 'x' + str(Np), - experiment_name = data_name, - light_source = source, - object = object_name, - filter = '', - description = '' - ) + timestamps[spectrum_index] = np.ctypeslib.as_array(timestamp) + + else: # Set values to zero if an error occured + spectral_data[spectrum_index,:] = 0 + timestamps[spectrum_index] = 0 + + spectrum_index += 1 - acquisition_parameters = AcquisitionParameters( - pattern_compression = 1, - pattern_dimension_x = 1, - pattern_dimension_y = 1, - zoom = zoom, - xw_offset = xw_offset, - yh_offset = yh_offset, - mask_index = [] ) + return measurement_callback - acquisition_parameters.pattern_amount = 1 - - spectrometer_params, DMD_params = setup( - spectrometer = spectrometer, - DMD = DMD, - DMD_initial_memory = DMD_initial_memory, - metadata = metadata, - acquisition_params = acquisition_parameters, - pattern_to_display = pattern_to_display, - integration_time = ti, - loop = True ) + # def for camera acquisition + if repetition == 0: + camPar = stopCapt_DeallocMem(camPar) + camPar.trigger_mode = 'hard'#'soft'# + imageQueue(camPar) + camPar = prepareCam(camPar, metadata) + camPar.timeout = 1000 # time out in ms for the "is_WaitForNextImage" function + start_chrono = time.time() + x = threading.Thread(target = runCam_thread, args=(camPar, start_chrono)) + x.start() - return metadata, spectrometer_params, DMD_params, acquisition_parameters + pixel_amount = (spectrometer_params.stop_pixel - + spectrometer_params.start_pixel + 1) -def displaySpectro(ava: Avantes, + measurement_time = np.zeros((acquisition_params.pattern_amount)) + timestamps = np.zeros((acquisition_params.pattern_amount),dtype=np.uint32) + spectral_data = np.zeros( + (acquisition_params.pattern_amount,pixel_amount),dtype=np.float64) + + # Boolean to indicate if saturation was detected during acquisition + saturation_detected = False + + spectrum_index = 0 # Accessed as nonlocal variable inside the callback + + #spectro.register_callback(-2,acquisition_params.pattern_amount,pixel_amount) + callback = register_callback(measurement_time, timestamps, + spectral_data, ava) + measurement_callback = MeasureCallback(callback) + ava.measure_callback(-2, measurement_callback) + + # time.sleep(0.5) + # Run the whole sequence only once + DMD.Run(loop=False) + start_measurement_time = perf_counter_ns() + #sleep(13) + + while(True): + if(spectrum_index >= acquisition_params.pattern_amount): + break + elif((perf_counter_ns() - start_measurement_time) / 1e+6 > + (2 * acquisition_params.pattern_amount * + DMD_params.picture_time_us / 1e+3)): + print('Stopping measurement. One of the equipments may be blocked ' + 'or disconnected.') + break + else: + time.sleep(acquisition_params.pattern_amount * + DMD_params.picture_time_us / 1e+6 / 10) + + ava.stop_measure() + DMD.Halt() + camPar.Exit = 2 + if repetition == repetitions-1: + camPar = stopCam(camPar) + #Yprint('MAIN :// camPar.camActivated = ' + str(camPar.camActivated)) + AcquisitionResult = namedtuple('AcquisitionResult', [ + 'spectral_data', + 'spectrum_index', + 'timestamps', + 'measurement_time', + 'start_measurement_time', + 'saturation_detected']) + + return AcquisitionResult(spectral_data, + spectrum_index, + timestamps, + measurement_time, + start_measurement_time, + saturation_detected) + + +def acquire_2arms(ava: Avantes, DMD: ALP4, + camPar, metadata: MetaData, spectrometer_params: SpectrometerParameters, DMD_params: DMDParameters, acquisition_params: AcquisitionParameters, + repetitions: int = 1, + verbose: bool = False, + reconstruct: bool = False, reconstruction_params: ReconstructionParameters = None - ): - """Perform a continousely acquisition on the spectrometer for optical tuning. + ) -> Tuple[np.ndarray, np.ndarray, np.ndarray]: + """Perform a complete acquisition. - Send a pattern on the DMD to project light on the spectrometer. The goal is - to have a look on the amplitude of the spectrum to tune the illumination to - avoid saturation (sat >= 65535) and noisy signal (amp <= 650). + Performs single or multiple acquisitions using the same setup configurations + previously chosen. + Finnaly saves all acqusition related data and metadata. Args: ava (Avantes): @@ -1668,445 +1706,282 @@ def displaySpectro(ava: Avantes, wavelengths (List[float]): List of float corresponding to the wavelengths associated with spectrometer's start and stop pixels. + repetitions (int): + Number of times the acquisition will be repeated with the same + configurations. Default is 1, a single acquisition. + verbose (bool): + Chooses if data concerning each acquisition should be printed to + user. If False, only overall data regarding all repetitions is + printed. Default is False. + reconstruct (bool): + If True, will perform reconstruction alongside acquisition using + multiprocessing. reconstruction_params (ReconstructionParameters): Object containing parameters of the neural network to be loaded for reconstruction. - """ - - loop = True # is to project continuously a unique pattern to tune the spectrometer - - pixel_amount = (spectrometer_params.stop_pixel - - spectrometer_params.start_pixel + 1) - # measurement_time = np.zeros( - # (acquisition_params.pattern_amount)) - # timestamps = np.zeros( - # ((acquisition_params.pattern_amount - 1)), - # dtype=np.float32) - spectral_data = np.zeros( - (acquisition_params.pattern_amount,pixel_amount), - dtype=np.float64) - - acquisition_params.acquired_spectra = 0 - - AcquisitionResults = _acquire_raw(ava, DMD, spectrometer_params, - DMD_params, acquisition_params, loop) - - (data, spectrum_index, timestamp, time, - start_measurement_time, saturation_detected) = AcquisitionResults - - - time, timestamp = _calculate_elapsed_time( - start_measurement_time, time, timestamp) - begin = acquisition_params.pattern_amount - end = 2 * acquisition_params.pattern_amount - spectral_data[begin:end] = data - # measurement_time[begin:end] = time - - # begin = (acquisition_params.pattern_amount - 1) - # end = 2 * (acquisition_params.pattern_amount - 1) - # timestamps[begin:end] = timestamp + Returns: + Tuple[ndarray, ndarray, ndarray]: Tuple containig spectral data and + measurement timings. + spectral_data (ndarray): + 2D array of `float` of size (pattern_amount x pixel_amount) + containing measurements received from the spectrometer for each + pattern of a sequence. + timestamps (np.ndarray): + 1D array with `float` type elapsed time between each measurement + made by the spectrometer based on its internal clock. + Units in milliseconds. + measurement_time (np.ndarray): + 1D array with `float` type elapsed times between each callback. + Units in milliseconds. + """ - acquisition_params.acquired_spectra += spectrum_index + if reconstruct == True: + print('Creating reconstruction processes') - acquisition_params.saturation_detected = saturation_detected + # Creating a Queue for sending spectral data to reconstruction process + queue_to_recon = Queue() + # Creating a Queue for sending reconstructed images to plot + queue_reconstructed = Queue() + sleep_time = (acquisition_params.pattern_amount * + DMD_params.picture_time_us/1e+6) - # acquisition_params.update_timings(timestamps, measurement_time) - # Real time between each spectrum acquisition by the spectrometer + # Creating reconstruction process + recon_process = Process(target=reconstruct_process, + args=(reconstruction_params.model, + reconstruction_params.device, + queue_to_recon, + queue_reconstructed, + reconstruction_params.batches, + reconstruction_params.noise, + sleep_time)) + # Creating plot process + plot_process = Process(target=plot_recon, + args=(queue_reconstructed, sleep_time)) -def check_ueye(func, *args, exp=0, raise_exc=True, txt=None): - ret = func(*args) - if not txt: - txt = "{}: Expected {} but ret={}!".format(str(func), exp, ret) - if ret != exp: - if raise_exc: - raise RuntimeError(txt) - else: - logging.critical(txt) + # Starting processes + recon_process.start() + plot_process.start() + + pixel_amount = (spectrometer_params.stop_pixel - + spectrometer_params.start_pixel + 1) + measurement_time = np.zeros( + (acquisition_params.pattern_amount * repetitions)) + timestamps = np.zeros( + ((acquisition_params.pattern_amount - 1) * repetitions), + dtype=np.float32) + spectral_data = np.zeros( + (acquisition_params.pattern_amount * repetitions,pixel_amount), + dtype=np.float64) + acquisition_params.acquired_spectra = 0 + print() -def stopCapt_DeallocMem(camPar): - # Stop capture and deallocate camera memory if need to change AOI - if camPar.camActivated == 1: - nRet = ueye.is_StopLiveVideo(camPar.hCam, ueye.IS_FORCE_VIDEO_STOP) - if nRet == ueye.IS_SUCCESS: - camPar.camActivated = 0 - print('video stop successful') - else: - print('problem to stop the video') - - if camPar.Memory == 1: - nRet = ueye.is_FreeImageMem(camPar.hCam, camPar.pcImageMemory, camPar.MemID) - if nRet == ueye.IS_SUCCESS: - camPar.Memory = 0 - print('deallocate memory successful') - else: - print('Problem to deallocate memory of the camera') - - return camPar + for repetition in range(repetitions): + if verbose: + print(f"Acquisition {repetition}") -def stopCapt_DeallocMem_ExitCam(camPar): - # Stop capture and deallocate camera memory if need to change AOI - if camPar.camActivated == 1: - nRet = ueye.is_StopLiveVideo(camPar.hCam, ueye.IS_FORCE_VIDEO_STOP) - if nRet == ueye.IS_SUCCESS: - camPar.camActivated = 0 - print('video stop successful') - else: - print('problem to stop the video') - - if camPar.Memory == 1: - nRet = ueye.is_FreeImageMem(camPar.hCam, camPar.pcImageMemory, camPar.MemID) - if nRet == ueye.IS_SUCCESS: - camPar.Memory = 0 - print('deallocate memory successful') - else: - print('Problem to deallocate memory of the camera') + AcquisitionResults = _acquire_raw_2arms(ava, DMD, camPar, spectrometer_params, + DMD_params, acquisition_params, metadata, repetition, repetitions) - if camPar.Exit == 2: - nRet = ueye.is_ExitCamera(camPar.hCam) - if nRet == ueye.IS_SUCCESS: - camPar.Exit = 0 - print('Camera disconnected') - else: - print('Problem to disconnect camera, need to restart spyder') - - return camPar + (data, spectrum_index, timestamp, time, + start_measurement_time, saturation_detected) = AcquisitionResults -class ImageBuffer: - pcImageMemory = None - MemID = None - width = None - height = None - nbitsPerPixel = None + print('Acquisition number : ' + str(repetition) + ' finished') -def imageQueue(camPar): - # Create Imagequeue --------------------------------------------------------- - # - allocate 3 ore more buffers depending on the framerate - # - initialize Imagequeue - # --------------------------------------------------------- - sleep(1) # is required (delay of 1s was not optimized!!) - buffers = [] - for y in range(10): - buffers.append(ImageBuffer()) + if reconstruct == True: + queue_to_recon.put(data.T) + print('Data sent') - for x in range(len(buffers)): - buffers[x].nbitsPerPixel = camPar.nBitsPerPixel # RAW8 - buffers[x].height = camPar.rectAOI.s32Height # sensorinfo.nMaxHeight - buffers[x].width = camPar.rectAOI.s32Width # sensorinfo.nMaxWidth - buffers[x].MemID = ueye.int(0) - buffers[x].pcImageMemory = ueye.c_mem_p() - check_ueye(ueye.is_AllocImageMem, camPar.hCam, buffers[x].width, buffers[x].height, buffers[x].nbitsPerPixel, - buffers[x].pcImageMemory, buffers[x].MemID) - check_ueye(ueye.is_AddToSequence, camPar.hCam, buffers[x].pcImageMemory, buffers[x].MemID) + time, timestamp = _calculate_elapsed_time( + start_measurement_time, time, timestamp) - check_ueye(ueye.is_InitImageQueue, camPar.hCam, ueye.c_int(0)) - if camPar.trigger_mode == 'soft': - check_ueye(ueye.is_SetExternalTrigger, camPar.hCam, ueye.IS_SET_TRIGGER_SOFTWARE) - elif camPar.trigger_mode == 'hard': - check_ueye(ueye.is_SetExternalTrigger, camPar.hCam, ueye.IS_SET_TRIGGER_LO_HI) + begin = repetition * acquisition_params.pattern_amount + end = (repetition + 1) * acquisition_params.pattern_amount + spectral_data[begin:end] = data + measurement_time[begin:end] = time -def prepareCam(camPar, metadata): - cam_path = metadata.output_directory + '\\' + metadata.experiment_name + '_video.' + camPar.vidFormat - strFileName = ueye.c_char_p(cam_path.encode('utf-8')) - - if camPar.vidFormat == 'avi': - # print('Video format : AVI') - camPar.avi = ueye.int() - nRet = ueye_tools.isavi_InitAVI(camPar.avi, camPar.hCam) - # print("isavi_InitAVI") - if nRet != ueye_tools.IS_AVI_NO_ERR: - print("isavi_InitAVI ERROR") - - nRet = ueye_tools.isavi_SetImageSize(camPar.avi, camPar.m_nColorMode, camPar.rectAOI.s32Width , camPar.rectAOI.s32Height, 0, 0, 0) - nRet = ueye_tools.isavi_SetImageQuality(camPar.avi, 100) - if nRet != ueye_tools.IS_AVI_NO_ERR: - print("isavi_SetImageQuality ERROR") - - nRet = ueye_tools.isavi_OpenAVI(camPar.avi, strFileName) - if nRet != ueye_tools.IS_AVI_NO_ERR: - print("isavi_OpenAVI ERROR") - print('Error code = ' + str(nRet)) - print('Certainly, it is a problem with the file name, Avoid special character like "µ" or try to redcue its size') - - nRet = ueye_tools.isavi_SetFrameRate(camPar.avi, camPar.fps) - if nRet != ueye_tools.IS_AVI_NO_ERR: - print("isavi_SetFrameRate ERROR") - nRet = ueye_tools.isavi_StartAVI(camPar.avi) - # print("isavi_StartAVI") - if nRet != ueye_tools.IS_AVI_NO_ERR: - print("isavi_StartAVI ERROR") + begin = repetition * (acquisition_params.pattern_amount - 1) + end = (repetition + 1) * (acquisition_params.pattern_amount - 1) + timestamps[begin:end] = timestamp - - elif camPar.vidFormat == 'bin': - camPar.punFileID = ueye.c_uint() - nRet = ueye_tools.israw_InitFile(camPar.punFileID, ueye_tools.IS_FILE_ACCESS_MODE_WRITE) - if nRet != ueye_tools.IS_AVI_NO_ERR: - print("INIT RAW FILE ERROR") - - nRet = ueye_tools.israw_SetImageInfo(camPar.punFileID, camPar.rectAOI.s32Width, camPar.rectAOI.s32Height, camPar.nBitsPerPixel) - if nRet != ueye_tools.IS_AVI_NO_ERR: - print("SET IMAGE INFO ERROR") - - if nRet == ueye.IS_SUCCESS: - # print('initFile ok') - # print('SetImageInfo ok') - nRet = ueye_tools.israw_OpenFile(camPar.punFileID, strFileName) - # if nRet == ueye.IS_SUCCESS: - # # print('OpenFile success') - - # nShutterMode = ueye.c_uint(ueye.IS_DEVICE_FEATURE_CAP_SHUTTER_MODE_ROLLING_GLOBAL_START) - # nRet = ueye.is_DeviceFeature(camPar.hCam, ueye.IS_DEVICE_FEATURE_CMD_SET_SHUTTER_MODE, nShutterMode, - # ueye.sizeof(nShutterMode)) - # print('shutter mode = ' + str(nShutterMode.value) + ' / enable : ' + str(nRet)) - - # # Read the global flash params - # flashParams = ueye.IO_FLASH_PARAMS() - # nRet = ueye.is_IO(camPar.hCam, ueye.IS_IO_CMD_FLASH_GET_GLOBAL_PARAMS, flashParams, ueye.sizeof(flashParams)) - # if (nRet == ueye.IS_SUCCESS): - # nDelay = flashParams.s32Delay - # print('nDelay = ' + str(nDelay.value)) - # nDuration = flashParams.u32Duration - # print('nDuration = ' + str(nDuration.value)) + acquisition_params.acquired_spectra += spectrum_index - # flashParams.s32Delay.value = 0 - # flashParams.u32Duration.value = 40 - # # Apply the global flash params and set the flash params to these values - # nRet = ueye.is_IO(camPar.hCam, ueye.IS_IO_CMD_FLASH_SET_PARAMS, flashParams, ueye.sizeof(flashParams)) + acquisition_params.saturation_detected = saturation_detected + if saturation_detected is True: + print('!!!!!!!!!! Saturation detected in the spectro !!!!!!!!!!') + # Print data for each repetition + if (verbose): + print('Spectra acquired: {}'.format(spectrum_index)) + print('Mean callback acquisition time: {} ms'.format( + np.mean(time))) + print('Total callback acquisition time: {} s'.format( + np.sum(time)/1000)) + print('Mean spectrometer acquisition time: {} ms'.format( + np.mean(timestamp))) + print('Total spectrometer acquisition time: {} s'.format( + np.sum(timestamp)/1000)) - # nRet = ueye.is_IO(camPar.hCam, ueye.IS_IO_CMD_FLASH_GET_PARAMS, flashParams, ueye.sizeof(flashParams)) - # if (nRet == ueye.IS_SUCCESS): - # nDelay = flashParams.s32Delay - # print('nDelay = ' + str(nDelay.value)) - # nDuration = flashParams.u32Duration - # print('nDuration = ' + str(nDuration.value)) - - # --------------------------------------------------------- - # Activates the camera's live video mode (free run mode) - # --------------------------------------------------------- - nRet = ueye.is_CaptureVideo(camPar.hCam, ueye.IS_DONT_WAIT) - # nRet = ueye.is_FreezeVideo(camPar.hCam, ueye.IS_DONT_WAIT) - if nRet != ueye.IS_SUCCESS: - print("is_CaptureVideo ERROR") - else: - camPar.camActivated = 1 + # Print shape of acquisition matrix for one repetition + print(f'Partial acquisition matrix dimensions:' + f'{data.shape}') + print() - return camPar + acquisition_params.update_timings(timestamps, measurement_time) + # Real time between each spectrum acquisition by the spectrometer + print('Complete acquisition done') + print('Spectra acquired: {}'.format(acquisition_params.acquired_spectra)) + print('Total acquisition time: {} s'.format(acquisition_params.total_spectrometer_acquisition_time_s)) + print(f'Saving data to {metadata.output_directory}') - -def runCam_thread(camPar, start_chrono): - imageinfo = ueye.UEYEIMAGEINFO() - current_buffer = ueye.c_mem_p() - current_id = ueye.int() - # inc = 0 - entier_old = 0 - # time.sleep(0.01) - while True: - nret = ueye.is_WaitForNextImage(camPar.hCam, camPar.timeout, current_buffer, current_id) - if nret == ueye.IS_SUCCESS: - check_ueye(ueye.is_GetImageInfo, camPar.hCam, current_id, imageinfo, ueye.sizeof(imageinfo)) - start_time = time.time() - counter = start_time - start_chrono - camPar.time_array.append(counter) - if camPar.vidFormat == 'avi': - nRet = ueye_tools.isavi_AddFrame(camPar.avi, current_buffer) - elif camPar.vidFormat == 'bin': - nRet = ueye_tools.israw_AddFrame(camPar.punFileID, current_buffer, imageinfo.u64TimestampDevice) - - check_ueye(ueye.is_UnlockSeqBuf, camPar.hCam, current_id, current_buffer) - else: - # nRet = ueye.is_FreeImageMem (camPar.hCam, current_buffer, current_id) - # if nRet != ueye.IS_SUCCESS: - # print('ERROR to free the memory') - # print(nRet) - print('Thread finished') - break - # else: - # print('thread cam stop correctly') - # break + # delete acquisition with black pattern (white for the camera) + if camPar.insert_patterns == 1: + black_pattern_index = np.where(acquisition_params.patterns_wp == -1) + # print('index of white patterns :') + # print(black_pattern_index[0:38]) + if acquisition_params.patterns_wp.shape == acquisition_params.patterns.shape: + acquisition_params.patterns = np.delete(acquisition_params.patterns, black_pattern_index) + spectral_data = np.delete(spectral_data, black_pattern_index, axis = 0) + acquisition_params.timestamps = np.delete(acquisition_params.timestamps, black_pattern_index[1:]) + acquisition_params.measurement_time = np.delete(acquisition_params.measurement_time, black_pattern_index) + acquisition_params.acquired_spectra = len(acquisition_params.patterns) + + _save_acquisition_2arms(metadata, DMD_params, spectrometer_params, camPar, + acquisition_params, spectral_data) -def stopCam(camPar): - if camPar.vidFormat == 'avi': - ueye_tools.isavi_StopAVI(camPar.hCam) - ueye_tools.isavi_CloseAVI(camPar.hCam) - ueye_tools.isavi_ExitAVI(camPar.hCam) - elif camPar.vidFormat == 'bin': - ueye_tools.israw_CloseFile(camPar.punFileID) - ueye_tools.israw_ExitFile(camPar.punFileID) - camPar.punFileID = ueye.c_uint() + # Joining processes and closing queues + if reconstruct == True: + queue_to_recon.put('kill') # Sends a message to stop reconstruction + recon_process.join() + queue_to_recon.close() + plot_process.join() + queue_reconstructed.close() - # camPar = stopCapt_DeallocMem(camPar) - - return camPar - + maxi = np.amax(spectral_data[0,:]) + print('------------------------------------------------') + print('maximum in the spectrum = ' + str(maxi)) + print('------------------------------------------------') + if maxi >= 65535: + print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!') + print('!!!!! warning, spectrum saturation !!!!!!!!') + print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!') -def _acquire_raw_2arms(ava: Avantes, - DMD: ALP4, - camPar, - spectrometer_params: SpectrometerParameters, - DMD_params: DMDParameters, - acquisition_params: AcquisitionParameters, - metadata, - repetition, - repetitions - ) -> NamedTuple: - """Raw data acquisition. + return spectral_data - Setups a callback function to receive messages from spectrometer whenever a - measurement is ready to be read. Reads a measurement via a callback. +def setup_tuneSpectro(spectrometer, + DMD, + DMD_initial_memory, + pattern_to_display, + ti : float = 1, + zoom : int = 1, + xw_offset: int = 128, + yh_offset: int = 0, + mask_index : np.array = []): + """ Setup the hadrware to tune the spectrometer in live. The goal is to find + the integration time of the spectrometer, noise is around 700 counts, + saturation is equal to 2**16=65535 + Args: - ava (Avantes): + spectrometer (Avantes): Connected spectrometer (Avantes object). - DMD (ALP4): + DMD (ALP4): Connected DMD. - spectrometer_params (SpectrometerParameters): - Spectrometer metadata object with spectrometer configurations. - DMD_params (DMDParameters): - DMD metadata object with DMD configurations. - acquisition_params (AcquisitionParameters): - Acquisition related metadata object. - - Returns: - NamedTuple: NamedTuple containig spectral data and measurement timings. - spectral_data (ndarray): - 2D array of `float` of size (pattern_amount x pixel_amount) - containing measurements received from the spectrometer for each - pattern of a sequence. - spectrum_index (int): - Index of the last acquired spectrum. - timestamps (np.ndarray): - 1D array with `float` type elapsed time between each measurement - made by the spectrometer based on its internal clock. - Units in milliseconds. - measurement_time (np.ndarray): - 1D array with `float` type elapsed times between each callback. - Units in milliseconds. - start_measurement_time (float): - Time when acquisition started. - saturation_detected (bool): - Boolean incating if saturation was detected during acquisition. - """ - # def for spectrometer acquisition - def register_callback(measurement_time, timestamps, - spectral_data, ava): - - def measurement_callback(handle, info): # If we want to reconstruct during callback; can use it in here. Add function as parameter. - nonlocal spectrum_index - nonlocal saturation_detected - - measurement_time[spectrum_index] = perf_counter_ns() - - if info.contents.value >= 0: - timestamp,spectrum = ava.get_data() - spectral_data[spectrum_index,:] = ( - np.ctypeslib.as_array(spectrum[0:pixel_amount])) - - if np.any(ava.get_saturated_pixels() > 0): - saturation_detected = True - - timestamps[spectrum_index] = np.ctypeslib.as_array(timestamp) - - else: # Set values to zero if an error occured - spectral_data[spectrum_index,:] = 0 - timestamps[spectrum_index] = 0 + DMD_initial_memory (int): + Initial memory available in DMD after initialization. + metadata (MetaData): + Metadata concerning the experiment, paths, file inputs and file + outputs. Must be created and filled up by the user. + acquisition_params (AcquisitionParameters): + Acquisition related metadata object. User must partially fill up + with pattern_compression, pattern_dimension_x, pattern_dimension_y. + pattern_to_display (string): + display one pattern on the DMD to tune the spectrometer. Default is + white pattern + ti (float): + The integration time of the spectrometer during one scan in miliseconds. + Default is 1 ms. + zoom (int): + digital zoom on the DMD. Default is 1 + xw_offset (int): + offset of the pattern in the DMD for zoom > 1 in the width (x) direction + yh_offset (int): + offset of the pattern in the DMD for zoom > 1 in the heihgt (y) direction + mask_index (Union[np.ndarray, str], optional): + Array of `int` type corresponding to the index of the mask vector where + the value is egal to 1 - spectrum_index += 1 - - return measurement_callback - - # def for camera acquisition - if repetition == 0: - camPar = stopCapt_DeallocMem(camPar) - camPar.trigger_mode = 'hard'#'soft'# - imageQueue(camPar) - camPar = prepareCam(camPar, metadata) - camPar.timeout = 1000 # time out in ms for the "is_WaitForNextImage" function - start_chrono = time.time() - x = threading.Thread(target = runCam_thread, args=(camPar, start_chrono)) - x.start() + return: + metadata (MetaData): + Metadata concerning the experiment, paths, file inputs and file + outputs. Must be created and filled up by the user. + spectrometer_params (SpectrometerParameters): + Spectrometer metadata object with spectrometer configurations. + DMD_params (DMDParameters): + DMD metadata object with DMD configurations. + """ - pixel_amount = (spectrometer_params.stop_pixel - - spectrometer_params.start_pixel + 1) - - measurement_time = np.zeros((acquisition_params.pattern_amount)) - timestamps = np.zeros((acquisition_params.pattern_amount),dtype=np.uint32) - spectral_data = np.zeros( - (acquisition_params.pattern_amount,pixel_amount),dtype=np.float64) - - # Boolean to indicate if saturation was detected during acquisition - saturation_detected = False + data_folder_name = 'Tune' + data_name = 'test' + # all_path = func_path(data_folder_name, data_name) - spectrum_index = 0 # Accessed as nonlocal variable inside the callback + scan_mode = 'Walsh' + Np = 16 + source = '' + object_name = '' - #spectro.register_callback(-2,acquisition_params.pattern_amount,pixel_amount) - callback = register_callback(measurement_time, timestamps, - spectral_data, ava) - measurement_callback = MeasureCallback(callback) - ava.measure_callback(-2, measurement_callback) + metadata = MetaData( + output_directory = '',#all_path.subfolder_path, + pattern_order_source = 'C:/openspyrit/spas/stats/pattern_order_' + scan_mode + '_' + str(Np) + 'x' + str(Np) + '.npz', + pattern_source = 'C:/openspyrit/spas/Patterns/' + scan_mode + '_' + str(Np) + 'x' + str(Np), + pattern_prefix = scan_mode + '_' + str(Np) + 'x' + str(Np), + experiment_name = data_name, + light_source = source, + object = object_name, + filter = '', + description = '' + ) + + acquisition_parameters = AcquisitionParameters( + pattern_compression = 1, + pattern_dimension_x = 16, + pattern_dimension_y = 16, + zoom = zoom, + xw_offset = xw_offset, + yh_offset = yh_offset, + mask_index = [] ) - # time.sleep(0.5) - # Run the whole sequence only once - DMD.Run(loop=False) - start_measurement_time = perf_counter_ns() - #sleep(13) + acquisition_parameters.pattern_amount = 1 + + spectrometer_params, DMD_params = setup( + spectrometer = spectrometer, + DMD = DMD, + DMD_initial_memory = DMD_initial_memory, + metadata = metadata, + acquisition_params = acquisition_parameters, + pattern_to_display = pattern_to_display, + integration_time = ti, + loop = True ) - while(True): - if(spectrum_index >= acquisition_params.pattern_amount): - break - elif((perf_counter_ns() - start_measurement_time) / 1e+6 > - (2 * acquisition_params.pattern_amount * - DMD_params.picture_time_us / 1e+3)): - print('Stopping measurement. One of the equipments may be blocked ' - 'or disconnected.') - break - else: - time.sleep(acquisition_params.pattern_amount * - DMD_params.picture_time_us / 1e+6 / 10) - - ava.stop_measure() - DMD.Halt() - camPar.Exit = 2 - if repetition == repetitions-1: - camPar = stopCam(camPar) - #Yprint('MAIN :// camPar.camActivated = ' + str(camPar.camActivated)) - AcquisitionResult = namedtuple('AcquisitionResult', [ - 'spectral_data', - 'spectrum_index', - 'timestamps', - 'measurement_time', - 'start_measurement_time', - 'saturation_detected']) - - return AcquisitionResult(spectral_data, - spectrum_index, - timestamps, - measurement_time, - start_measurement_time, - saturation_detected) - + return metadata, spectrometer_params, DMD_params, acquisition_parameters -def acquire_2arms(ava: Avantes, +def displaySpectro(ava: Avantes, DMD: ALP4, - camPar, metadata: MetaData, spectrometer_params: SpectrometerParameters, DMD_params: DMDParameters, acquisition_params: AcquisitionParameters, - repetitions: int = 1, - verbose: bool = False, - reconstruct: bool = False, reconstruction_params: ReconstructionParameters = None - ) -> Tuple[np.ndarray, np.ndarray, np.ndarray]: - """Perform a complete acquisition. + ): + """Perform a continousely acquisition on the spectrometer for optical tuning. - Performs single or multiple acquisitions using the same setup configurations - previously chosen. - Finnaly saves all acqusition related data and metadata. + Send a pattern on the DMD to project light on the spectrometer. The goal is + to have a look on the amplitude of the spectrum to tune the illumination to + avoid saturation (sat >= 65535) and noisy signal (amp <= 650). Args: ava (Avantes): @@ -2125,185 +2000,285 @@ def acquire_2arms(ava: Avantes, wavelengths (List[float]): List of float corresponding to the wavelengths associated with spectrometer's start and stop pixels. - repetitions (int): - Number of times the acquisition will be repeated with the same - configurations. Default is 1, a single acquisition. - verbose (bool): - Chooses if data concerning each acquisition should be printed to - user. If False, only overall data regarding all repetitions is - printed. Default is False. - reconstruct (bool): - If True, will perform reconstruction alongside acquisition using - multiprocessing. reconstruction_params (ReconstructionParameters): Object containing parameters of the neural network to be loaded for reconstruction. - - Returns: - Tuple[ndarray, ndarray, ndarray]: Tuple containig spectral data and - measurement timings. - spectral_data (ndarray): - 2D array of `float` of size (pattern_amount x pixel_amount) - containing measurements received from the spectrometer for each - pattern of a sequence. - timestamps (np.ndarray): - 1D array with `float` type elapsed time between each measurement - made by the spectrometer based on its internal clock. - Units in milliseconds. - measurement_time (np.ndarray): - 1D array with `float` type elapsed times between each callback. - Units in milliseconds. """ + + loop = True # is to project continuously a unique pattern to tune the spectrometer + + pixel_amount = (spectrometer_params.stop_pixel - + spectrometer_params.start_pixel + 1) + # measurement_time = np.zeros( + # (acquisition_params.pattern_amount)) + # timestamps = np.zeros( + # ((acquisition_params.pattern_amount - 1)), + # dtype=np.float32) + spectral_data = np.zeros( + (acquisition_params.pattern_amount,pixel_amount), + dtype=np.float64) - if reconstruct == True: - print('Creating reconstruction processes') + acquisition_params.acquired_spectra = 0 - # Creating a Queue for sending spectral data to reconstruction process - queue_to_recon = Queue() + AcquisitionResults = _acquire_raw(ava, DMD, spectrometer_params, + DMD_params, acquisition_params, loop) - # Creating a Queue for sending reconstructed images to plot - queue_reconstructed = Queue() + (data, spectrum_index, timestamp, time, + start_measurement_time, saturation_detected) = AcquisitionResults - sleep_time = (acquisition_params.pattern_amount * - DMD_params.picture_time_us/1e+6) - # Creating reconstruction process - recon_process = Process(target=reconstruct_process, - args=(reconstruction_params.model, - reconstruction_params.device, - queue_to_recon, - queue_reconstructed, - reconstruction_params.batches, - reconstruction_params.noise, - sleep_time)) + time, timestamp = _calculate_elapsed_time( + start_measurement_time, time, timestamp) - # Creating plot process - plot_process = Process(target=plot_recon, - args=(queue_reconstructed, sleep_time)) + begin = acquisition_params.pattern_amount + end = 2 * acquisition_params.pattern_amount + spectral_data[begin:end] = data + # measurement_time[begin:end] = time - # Starting processes - recon_process.start() - plot_process.start() - - pixel_amount = (spectrometer_params.stop_pixel - - spectrometer_params.start_pixel + 1) - measurement_time = np.zeros( - (acquisition_params.pattern_amount * repetitions)) - timestamps = np.zeros( - ((acquisition_params.pattern_amount - 1) * repetitions), - dtype=np.float32) - spectral_data = np.zeros( - (acquisition_params.pattern_amount * repetitions,pixel_amount), - dtype=np.float64) + # begin = (acquisition_params.pattern_amount - 1) + # end = 2 * (acquisition_params.pattern_amount - 1) + # timestamps[begin:end] = timestamp - acquisition_params.acquired_spectra = 0 - print() + acquisition_params.acquired_spectra += spectrum_index - for repetition in range(repetitions): - if verbose: - print(f"Acquisition {repetition}") + acquisition_params.saturation_detected = saturation_detected - AcquisitionResults = _acquire_raw_2arms(ava, DMD, camPar, spectrometer_params, - DMD_params, acquisition_params, metadata, repetition, repetitions) + + + # acquisition_params.update_timings(timestamps, measurement_time) + # Real time between each spectrum acquisition by the spectrometer + + +def check_ueye(func, *args, exp=0, raise_exc=True, txt=None): + ret = func(*args) + if not txt: + txt = "{}: Expected {} but ret={}!".format(str(func), exp, ret) + if ret != exp: + if raise_exc: + raise RuntimeError(txt) + else: + logging.critical(txt) + + +def stopCapt_DeallocMem(camPar): + # Stop capture and deallocate camera memory if need to change AOI + if camPar.camActivated == 1: + nRet = ueye.is_StopLiveVideo(camPar.hCam, ueye.IS_FORCE_VIDEO_STOP) + if nRet == ueye.IS_SUCCESS: + camPar.camActivated = 0 + print('video stop successful') + else: + print('problem to stop the video') + + if camPar.Memory == 1: + nRet = ueye.is_FreeImageMem(camPar.hCam, camPar.pcImageMemory, camPar.MemID) + if nRet == ueye.IS_SUCCESS: + camPar.Memory = 0 + print('deallocate memory successful') + else: + print('Problem to deallocate memory of the camera') + + return camPar + + +def stopCapt_DeallocMem_ExitCam(camPar): + # Stop capture and deallocate camera memory if need to change AOI + if camPar.camActivated == 1: + nRet = ueye.is_StopLiveVideo(camPar.hCam, ueye.IS_FORCE_VIDEO_STOP) + if nRet == ueye.IS_SUCCESS: + camPar.camActivated = 0 + print('video stop successful') + else: + print('problem to stop the video') + + if camPar.Memory == 1: + nRet = ueye.is_FreeImageMem(camPar.hCam, camPar.pcImageMemory, camPar.MemID) + if nRet == ueye.IS_SUCCESS: + camPar.Memory = 0 + print('deallocate memory successful') + else: + print('Problem to deallocate memory of the camera') - (data, spectrum_index, timestamp, time, - start_measurement_time, saturation_detected) = AcquisitionResults - - print('Data acquired') + if camPar.Exit == 2: + nRet = ueye.is_ExitCamera(camPar.hCam) + if nRet == ueye.IS_SUCCESS: + camPar.Exit = 0 + print('Camera disconnected') + else: + print('Problem to disconnect camera, need to restart spyder') + + return camPar - if reconstruct == True: - queue_to_recon.put(data.T) - print('Data sent') - time, timestamp = _calculate_elapsed_time( - start_measurement_time, time, timestamp) +class ImageBuffer: + pcImageMemory = None + MemID = None + width = None + height = None + nbitsPerPixel = None - begin = repetition * acquisition_params.pattern_amount - end = (repetition + 1) * acquisition_params.pattern_amount - spectral_data[begin:end] = data - measurement_time[begin:end] = time - begin = repetition * (acquisition_params.pattern_amount - 1) - end = (repetition + 1) * (acquisition_params.pattern_amount - 1) - timestamps[begin:end] = timestamp +def imageQueue(camPar): + # Create Imagequeue --------------------------------------------------------- + # - allocate 3 ore more buffers depending on the framerate + # - initialize Imagequeue + # --------------------------------------------------------- + sleep(1) # is required (delay of 1s was not optimized!!) + buffers = [] + for y in range(10): + buffers.append(ImageBuffer()) - acquisition_params.acquired_spectra += spectrum_index + for x in range(len(buffers)): + buffers[x].nbitsPerPixel = camPar.nBitsPerPixel # RAW8 + buffers[x].height = camPar.rectAOI.s32Height # sensorinfo.nMaxHeight + buffers[x].width = camPar.rectAOI.s32Width # sensorinfo.nMaxWidth + buffers[x].MemID = ueye.int(0) + buffers[x].pcImageMemory = ueye.c_mem_p() + check_ueye(ueye.is_AllocImageMem, camPar.hCam, buffers[x].width, buffers[x].height, buffers[x].nbitsPerPixel, + buffers[x].pcImageMemory, buffers[x].MemID) + check_ueye(ueye.is_AddToSequence, camPar.hCam, buffers[x].pcImageMemory, buffers[x].MemID) - acquisition_params.saturation_detected = saturation_detected + check_ueye(ueye.is_InitImageQueue, camPar.hCam, ueye.c_int(0)) + if camPar.trigger_mode == 'soft': + check_ueye(ueye.is_SetExternalTrigger, camPar.hCam, ueye.IS_SET_TRIGGER_SOFTWARE) + elif camPar.trigger_mode == 'hard': + check_ueye(ueye.is_SetExternalTrigger, camPar.hCam, ueye.IS_SET_TRIGGER_LO_HI) - # Print data for each repetition only if there are not too many repetitions - if (verbose) and repetitions <= 10: - if saturation_detected is True: - print('Saturation detected!') - print('Spectra acquired: {}'.format(spectrum_index)) - print('Mean callback acquisition time: {} ms'.format( - np.mean(time))) - print('Total callback acquisition time: {} s'.format( - np.sum(time)/1000)) - print('Mean spectrometer acquisition time: {} ms'.format( - np.mean(timestamp))) - print('Total spectrometer acquisition time: {} s'.format( - np.sum(timestamp)/1000)) - # Print shape of acquisition matrix for one repetition - print(f'Partial acquisition matrix dimensions:' - f'{data.shape}') - print() +def prepareCam(camPar, metadata): + cam_path = metadata.output_directory + '\\' + metadata.experiment_name + '_video.' + camPar.vidFormat + strFileName = ueye.c_char_p(cam_path.encode('utf-8')) + + if camPar.vidFormat == 'avi': + # print('Video format : AVI') + camPar.avi = ueye.int() + nRet = ueye_tools.isavi_InitAVI(camPar.avi, camPar.hCam) + # print("isavi_InitAVI") + if nRet != ueye_tools.IS_AVI_NO_ERR: + print("isavi_InitAVI ERROR") + + nRet = ueye_tools.isavi_SetImageSize(camPar.avi, camPar.m_nColorMode, camPar.rectAOI.s32Width , camPar.rectAOI.s32Height, 0, 0, 0) + nRet = ueye_tools.isavi_SetImageQuality(camPar.avi, 100) + if nRet != ueye_tools.IS_AVI_NO_ERR: + print("isavi_SetImageQuality ERROR") + + nRet = ueye_tools.isavi_OpenAVI(camPar.avi, strFileName) + if nRet != ueye_tools.IS_AVI_NO_ERR: + print("isavi_OpenAVI ERROR") + print('Error code = ' + str(nRet)) + print('Certainly, it is a problem with the file name, Avoid special character like "µ" or try to redcue its size') + + nRet = ueye_tools.isavi_SetFrameRate(camPar.avi, camPar.fps) + if nRet != ueye_tools.IS_AVI_NO_ERR: + print("isavi_SetFrameRate ERROR") + nRet = ueye_tools.isavi_StartAVI(camPar.avi) + # print("isavi_StartAVI") + if nRet != ueye_tools.IS_AVI_NO_ERR: + print("isavi_StartAVI ERROR") + + elif camPar.vidFormat == 'bin': + camPar.punFileID = ueye.c_uint() + nRet = ueye_tools.israw_InitFile(camPar.punFileID, ueye_tools.IS_FILE_ACCESS_MODE_WRITE) + if nRet != ueye_tools.IS_AVI_NO_ERR: + print("INIT RAW FILE ERROR") + + nRet = ueye_tools.israw_SetImageInfo(camPar.punFileID, camPar.rectAOI.s32Width, camPar.rectAOI.s32Height, camPar.nBitsPerPixel) + if nRet != ueye_tools.IS_AVI_NO_ERR: + print("SET IMAGE INFO ERROR") + + if nRet == ueye.IS_SUCCESS: + # print('initFile ok') + # print('SetImageInfo ok') + nRet = ueye_tools.israw_OpenFile(camPar.punFileID, strFileName) + # if nRet == ueye.IS_SUCCESS: + # # print('OpenFile success') - acquisition_params.update_timings(timestamps, measurement_time) - print('Acquisition completed') - # Real time between each spectrum acquisition by the spectrometer - # print('Complete acquisition results:') - # print('Spectra acquired: {}'.format( - # acquisition_params.acquired_spectra)) - if acquisition_params.saturation_detected is True: - print('Saturation detected!') - print('Mean callback acquisition time: {} ms'.format( - acquisition_params.mean_callback_acquisition_time_ms)) - # print('Total callback acquisition time: {} s'.format( - # acquisition_params.total_callback_acquisition_time_s)) - # print('Mean spectrometer acquisition time: {} ms'.format( - # acquisition_params.mean_spectrometer_acquisition_time_ms)) - print('Total spectrometer acquisition time: {} s'.format( - acquisition_params.total_spectrometer_acquisition_time_s)) - # print(f'Acquisition matrix dimension: {spectral_data.shape}') + # nShutterMode = ueye.c_uint(ueye.IS_DEVICE_FEATURE_CAP_SHUTTER_MODE_ROLLING_GLOBAL_START) + # nRet = ueye.is_DeviceFeature(camPar.hCam, ueye.IS_DEVICE_FEATURE_CMD_SET_SHUTTER_MODE, nShutterMode, + # ueye.sizeof(nShutterMode)) + # print('shutter mode = ' + str(nShutterMode.value) + ' / enable : ' + str(nRet)) + + # # Read the global flash params + # flashParams = ueye.IO_FLASH_PARAMS() + # nRet = ueye.is_IO(camPar.hCam, ueye.IS_IO_CMD_FLASH_GET_GLOBAL_PARAMS, flashParams, ueye.sizeof(flashParams)) + # if (nRet == ueye.IS_SUCCESS): + # nDelay = flashParams.s32Delay + # print('nDelay = ' + str(nDelay.value)) + # nDuration = flashParams.u32Duration + # print('nDuration = ' + str(nDuration.value)) - print(f'Saving data to {metadata.output_directory}') + # flashParams.s32Delay.value = 0 + # flashParams.u32Duration.value = 40 + # # Apply the global flash params and set the flash params to these values + # nRet = ueye.is_IO(camPar.hCam, ueye.IS_IO_CMD_FLASH_SET_PARAMS, flashParams, ueye.sizeof(flashParams)) - # delete acquisition with black pattern (white for the camera) - if camPar.insert_patterns == 1: - black_pattern_index = np.where(acquisition_params.patterns_wp == -1) - # print('index of white patterns :') - # print(black_pattern_index[0:38]) - if acquisition_params.patterns_wp.shape == acquisition_params.patterns.shape: - acquisition_params.patterns = np.delete(acquisition_params.patterns, black_pattern_index) - spectral_data = np.delete(spectral_data, black_pattern_index, axis = 0) - acquisition_params.timestamps = np.delete(acquisition_params.timestamps, black_pattern_index[1:]) - acquisition_params.measurement_time = np.delete(acquisition_params.measurement_time, black_pattern_index) - acquisition_params.acquired_spectra = len(acquisition_params.patterns) - _save_acquisition_2arms(metadata, DMD_params, spectrometer_params, camPar, - acquisition_params, spectral_data) + # nRet = ueye.is_IO(camPar.hCam, ueye.IS_IO_CMD_FLASH_GET_PARAMS, flashParams, ueye.sizeof(flashParams)) + # if (nRet == ueye.IS_SUCCESS): + # nDelay = flashParams.s32Delay + # print('nDelay = ' + str(nDelay.value)) + # nDuration = flashParams.u32Duration + # print('nDuration = ' + str(nDuration.value)) + + # --------------------------------------------------------- + # Activates the camera's live video mode (free run mode) + # --------------------------------------------------------- + nRet = ueye.is_CaptureVideo(camPar.hCam, ueye.IS_DONT_WAIT) + # nRet = ueye.is_FreezeVideo(camPar.hCam, ueye.IS_DONT_WAIT) + if nRet != ueye.IS_SUCCESS: + print("is_CaptureVideo ERROR") + else: + camPar.camActivated = 1 + + return camPar + + +def runCam_thread(camPar, start_chrono): + imageinfo = ueye.UEYEIMAGEINFO() + current_buffer = ueye.c_mem_p() + current_id = ueye.int() + # inc = 0 + entier_old = 0 + # time.sleep(0.01) + while True: + nret = ueye.is_WaitForNextImage(camPar.hCam, camPar.timeout, current_buffer, current_id) + if nret == ueye.IS_SUCCESS: + check_ueye(ueye.is_GetImageInfo, camPar.hCam, current_id, imageinfo, ueye.sizeof(imageinfo)) + start_time = time.time() + counter = start_time - start_chrono + camPar.time_array.append(counter) + if camPar.vidFormat == 'avi': + nRet = ueye_tools.isavi_AddFrame(camPar.avi, current_buffer) + elif camPar.vidFormat == 'bin': + nRet = ueye_tools.israw_AddFrame(camPar.punFileID, current_buffer, imageinfo.u64TimestampDevice) + + check_ueye(ueye.is_UnlockSeqBuf, camPar.hCam, current_id, current_buffer) + else: + # nRet = ueye.is_FreeImageMem (camPar.hCam, current_buffer, current_id) + # if nRet != ueye.IS_SUCCESS: + # print('ERROR to free the memory') + # print(nRet) + print('Thread finished') + break + # else: + # print('thread cam stop correctly') + # break - # Joining processes and closing queues - if reconstruct == True: - queue_to_recon.put('kill') # Sends a message to stop reconstruction - recon_process.join() - queue_to_recon.close() - plot_process.join() - queue_reconstructed.close() +def stopCam(camPar): + if camPar.vidFormat == 'avi': + ueye_tools.isavi_StopAVI(camPar.hCam) + ueye_tools.isavi_CloseAVI(camPar.hCam) + ueye_tools.isavi_ExitAVI(camPar.hCam) + elif camPar.vidFormat == 'bin': + ueye_tools.israw_CloseFile(camPar.punFileID) + ueye_tools.israw_ExitFile(camPar.punFileID) + camPar.punFileID = ueye.c_uint() - maxi = np.amax(spectral_data[0,:]) - print('------------------------------------------------') - print('maximum in the spectrum = ' + str(maxi)) - print('------------------------------------------------') - if maxi >= 65535: - print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!') - print('!!!!! warning, spectrum saturation !!!!!!!!') - print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!') + # camPar = stopCapt_DeallocMem(camPar) + + return camPar - return spectral_data def disconnect(ava: Optional[Avantes]=None, DMD: Optional[ALP4]=None): """Disconnect spectrometer and DMD. @@ -2321,7 +2296,8 @@ def disconnect(ava: Optional[Avantes]=None, DMD: Optional[ALP4]=None): if ava is not None: ava.disconnect() - + print('Spectro disconnected') + if DMD is not None: # Stop the sequence display @@ -2332,6 +2308,7 @@ def disconnect(ava: Optional[Avantes]=None, DMD: Optional[ALP4]=None): DMD.FreeSeq() DMD.Free() + print('DMD disconnected') def disconnect_2arms(ava: Optional[Avantes]=None, DMD: Optional[ALP4]=None, camPar=None): @@ -2352,21 +2329,21 @@ def disconnect_2arms(ava: Optional[Avantes]=None, DMD: Optional[ALP4]=None, camP ava.disconnect() print('Spectro disconnected') - if DMD is not None: - + if DMD is not None: # Stop the sequence display try: DMD.Halt() + # Free the sequence from the onboard memory (if any is present) + if (DMD.Seqs): + DMD.FreeSeq() + + DMD.Free() + print('DMD disconnected') + except: print('probelm to Halt the DMD') - # Free the sequence from the onboard memory (if any is present) - if (DMD.Seqs): - DMD.FreeSeq() - - DMD.Free() - print('DMD disconnected') - + if camPar.camActivated == 1: nRet = ueye.is_StopLiveVideo(camPar.hCam, ueye.IS_FORCE_VIDEO_STOP) if nRet == ueye.IS_SUCCESS: @@ -2387,7 +2364,6 @@ def disconnect_2arms(ava: Optional[Avantes]=None, DMD: Optional[ALP4]=None, camP if nRet == ueye.IS_SUCCESS: camPar.Exit = 0 print('Camera disconnected') - print("END") else: print('Problem to disconnect camera, need to restart spyder') @@ -2467,7 +2443,6 @@ def _init_CAM(): ) # # Camera Initialization --- - # print("START Initialization of the IDS camera") ### Starts the driver and establishes the connection to the camera nRet = ueye.is_InitCamera(camPar.hCam, None) if nRet != ueye.IS_SUCCESS: @@ -2496,34 +2471,16 @@ def _init_CAM(): # setup the color depth to the current windows setting ueye.is_GetColorDepth(camPar.hCam, camPar.nBitsPerPixel, camPar.m_nColorMode) camPar.bytes_per_pixel = int(camPar.nBitsPerPixel / 8) - # print("IS_COLORMODE_BAYER: ", ) - # print("\tm_nColorMode: \t\t", m_nColorMode) - # print("\tnBitsPerPixel: \t\t", nBitsPerPixel) - # print("\tbytes_per_pixel: \t\t", bytes_per_pixel) - # print() - elif int.from_bytes(camPar.sInfo.nColorMode.value, byteorder='big') == ueye.IS_COLORMODE_CBYCRY: # for color camera models use RGB32 mode camPar.m_nColorMode = ueye.IS_CM_BGRA8_PACKED camPar.nBitsPerPixel = ueye.INT(32) camPar.bytes_per_pixel = int(camPar.nBitsPerPixel / 8) - # print("IS_COLORMODE_CBYCRY: ", ) - # print("\tm_nColorMode: \t\t", m_nColorMode) - # print("\tnBitsPerPixel: \t\t", nBitsPerPixel) - # print("\tbytes_per_pixel: \t\t", bytes_per_pixel) - # print() - elif int.from_bytes(camPar.sInfo.nColorMode.value, byteorder='big') == ueye.IS_COLORMODE_MONOCHROME: # for color camera models use RGB32 mode camPar.m_nColorMode = ueye.IS_CM_MONO8 camPar.nBitsPerPixel = ueye.INT(8) camPar.bytes_per_pixel = int(camPar.nBitsPerPixel / 8) - # print("IS_COLORMODE_MONOCHROME: ", ) - # print("\tm_nColorMode: \t\t", m_nColorMode) - # print("\tnBitsPerPixel: \t\t", nBitsPerPixel) - # print("\tbytes_per_pixel: \t\t", bytes_per_pixel) - # print() - else: # for monochrome camera models use Y8 mode camPar.m_nColorMode = ueye.IS_CM_MONO8 @@ -2549,26 +2506,6 @@ def _init_CAM(): # get the bandwidth (in MByte/s) camPar.bandwidth = ueye.is_GetUsedBandwidth(camPar.hCam) - # print('Bandwidth = ' + str(camPar.bandwidth) + ' MB/s') - - - # width = rectAOI.s32Width - # height = rectAOI.s32Height - - # Prints out some information about the camera and the sensor - # print("Camera model:\t\t", sInfo.strSensorName.decode('utf-8')) - # print("Camera serial no.:\t", cInfo.SerNo.decode('utf-8')) - # print("Maximum image width:\t", width) - # print("Maximum image height:\t", height) - # print() - - # self.hCam = hCam - # self.sInfo = sInfo - # self.cInfo = cInfo - # self.nBitsPerPixel = nBitsPerPixel - # self.m_nColorMode = m_nColorMode - # self.bytes_per_pixel = bytes_per_pixel - # self.rectAOI = rectAOI camPar.Exit = 1 diff --git a/spas/metadata.py b/spas/metadata.py index 7ede940..f7c4aa3 100644 --- a/spas/metadata.py +++ b/spas/metadata.py @@ -213,42 +213,42 @@ class CAM: insert_patterns (int) : 0 => no insertion / 1=> insert white patterns for the camera acq_mode (str) : mode of the acquisition => 'video' or 'snapshot' mode """ - - hCam: Optional[ueye.c_uint] = None - sInfo: Optional[ueye.SENSORINFO] = None - cInfo: Optional[ueye.BOARDINFO] = None - nBitsPerPixel: Optional[ueye.c_int] = None - m_nColorMode: Optional[ueye.c_int] = None - bytes_per_pixel: Optional[int] = None - rectAOI: Optional[ueye.IS_RECT] = None - pcImageMemory: Optional[ueye.c_mem_p] = None - MemID: Optional[ueye.c_int] = None - pitch: Optional[ueye.c_int] = None - fps: Optional[float] = None - gain: Optional[int] = None - gainBoost: Optional[str] = None - gamma: Optional[float] = None - exposureTime: Optional[float] = None - blackLevel: Optional[int] = None - camActivated : Optional[bool] = None - pixelClock : Optional[int] = None - bandwidth : Optional[float] = None - Memory : Optional[bool] = None - Exit : Optional[int] = None - vidFormat : Optional[str] = None - gate_period : Optional[int] = None - trigger_mode : Optional[str] = None - avi : Optional[ueye.int] = None - punFileID : Optional[ueye.c_int] = None - timeout : Optional[int] = None - time_array : Optional[Union[List[float], str]] = field(default=None, repr=False) - int_time_spect : Optional[float] = None - black_pattern_num : Optional[int] = None - insert_patterns : Optional[int] = None - acq_mode : Optional[str] = None - - class_description: str = 'IDS camera configuration' - + if dll_pyueye_installed: + hCam: Optional[ueye.c_uint] = None + sInfo: Optional[ueye.SENSORINFO] = None + cInfo: Optional[ueye.BOARDINFO] = None + nBitsPerPixel: Optional[ueye.c_int] = None + m_nColorMode: Optional[ueye.c_int] = None + bytes_per_pixel: Optional[int] = None + rectAOI: Optional[ueye.IS_RECT] = None + pcImageMemory: Optional[ueye.c_mem_p] = None + MemID: Optional[ueye.c_int] = None + pitch: Optional[ueye.c_int] = None + fps: Optional[float] = None + gain: Optional[int] = None + gainBoost: Optional[str] = None + gamma: Optional[float] = None + exposureTime: Optional[float] = None + blackLevel: Optional[int] = None + camActivated : Optional[bool] = None + pixelClock : Optional[int] = None + bandwidth : Optional[float] = None + Memory : Optional[bool] = None + Exit : Optional[int] = None + vidFormat : Optional[str] = None + gate_period : Optional[int] = None + trigger_mode : Optional[str] = None + avi : Optional[ueye.int] = None + punFileID : Optional[ueye.c_int] = None + timeout : Optional[int] = None + time_array : Optional[Union[List[float], str]] = field(default=None, repr=False) + int_time_spect : Optional[float] = None + black_pattern_num : Optional[int] = None + insert_patterns : Optional[int] = None + acq_mode : Optional[str] = None + + class_description: str = 'IDS camera configuration' + def undo_readable_class_CAM(self) -> None: """Changes the time_array attribute from `str` to `List` of `int`.""" @@ -403,9 +403,9 @@ class AcquisitionParameters: pattern_compression: float pattern_dimension_x: int pattern_dimension_y: int - zoom: int - xw_offset: int - yh_offset: int + zoom: Optional[int] = field(default=None) + xw_offset: Optional[int] = field(default=None) + yh_offset: Optional[int] = field(default=None) mask_index: Optional[Union[np.ndarray, str]] = field(default=None, repr=False) x_mask_coord: Optional[Union[np.ndarray, str]] = field(default=None, @@ -1084,19 +1084,21 @@ def save_metadata_2arms(metadata: MetaData, @dataclass_json @dataclass class func_path: - def __init__(self, data_folder_name, data_name): + def __init__(self, data_folder_name, data_name, ask_overwrite=False): if not os.path.exists('../data/' + data_folder_name): os.makedirs('../data/' + data_folder_name) if not os.path.exists('../data/' + data_folder_name + '/' + data_name): os.makedirs('../data/' + data_folder_name + '/' + data_name) aborted = False - else: + elif ask_overwrite == True: res = input('Acquisition already exists, overwrite it ?[y/n]') if res == 'n': aborted = True else: aborted = False + else: + aborted = True self.aborted = aborted self.subfolder_path = '../data/' + data_folder_name + '/' + data_name @@ -1113,4 +1115,4 @@ def __init__(self, data_folder_name, data_name): self.nn_reco_path = self.data_path + '_nn_reco.npz' self.fig_nn_reco_path = self.overview_path + '/' + data_name - \ No newline at end of file + diff --git a/spas/reconstruction.py b/spas/reconstruction.py index d9ef003..291649e 100644 --- a/spas/reconstruction.py +++ b/spas/reconstruction.py @@ -51,7 +51,7 @@ def reconstruction_hadamard(acquisition_parameters: AcquisitionParameters, frames /= N*N mask_index = acquisition_parameters.mask_index - if mask_index != []: + if len(mask_index) > 0: x_mask_coord = acquisition_parameters.x_mask_coord y_mask_coord = acquisition_parameters.y_mask_coord x_mask_length = x_mask_coord[1] - x_mask_coord[0] diff --git a/spas/transfer_data_to_girder.py b/spas/transfer_data_to_girder.py index 57c98c2..eb863d5 100644 --- a/spas/transfer_data_to_girder.py +++ b/spas/transfer_data_to_girder.py @@ -264,6 +264,9 @@ def transfer_data_2arms(metadata, acquisition_parameters, spectrometer_params, D del dict['b)_ACQ_measurement_time'] del dict['b)_ACQ_timestamps'] del dict['b)_ACQ_wavelengths'] + del dict['b)_ACQ_mask_index'] + del dict['b)_ACQ_x_mask_coord'] + del dict['b)_ACQ_y_mask_coord'] del dict['c)_SPECTRO_initial_available_pixels'] del dict['c)_SPECTRO_store_to_ram'] del dict['c)_SPECTRO_class_description'] diff --git a/spas/visualization.py b/spas/visualization.py index fd3f284..ec039ce 100644 --- a/spas/visualization.py +++ b/spas/visualization.py @@ -15,7 +15,6 @@ from spas.noise import noiseClass from spas.reconstruction_nn import reorder_subsample, reconstruct from spas.metadata import DMDParameters, read_metadata -import cv2 import time # Libraries for the IDS CAMERA try: @@ -23,7 +22,6 @@ except: print('ueye DLL not installed') - def spectral_binning(F: np.ndarray, wavelengths: np.ndarray, lambda_min: int, lambda_max: int, n_bin: int, noise: noiseClass=None ) -> Tuple[np.ndarray, np.ndarray, np.ndarray, Optional[noiseClass]]: @@ -395,7 +393,7 @@ def plot_color(F: np.ndarray, wavelengths: np.ndarray, filename: str = None, cax = divider.append_axes('right', size='5%', pad=0.05) im = ax.imshow(F[bin_,:,:], cmap=colormap) - ax.set_title('$\lambda=$'f'{wavelengths[bin_]:.2f}', + ax.set_title('$\\lambda=$'f'{wavelengths[bin_]:.2f}', fontsize=fontsize) cbar = fig.colorbar(im, cax=cax, orientation='vertical') @@ -442,53 +440,47 @@ def displayVid(camPar): Args: CAM: a structure containing the parameters of the IDS camera """ - ii = 0 - start_time = time.time() + + import cv2 + # Creating a cv2 window + window_name = "Camera of the Spatial Arm" + cv2.namedWindow(window_name) + + # Create a function 'nothing' for creating trackbar + def nothing(x): + pass + + # waiting time inside the loop of the display of the window t1 = camPar.exposureTime/1000 t2 = 1/camPar.fps t_wait = max(t1, t2) - print('Press "q" on the new window to exit') - window_name = "Camera of the Spatial Arm" - # start_point = (0, int(camPar.rectAOI.s32Width.value/2)) - # end_point = (int(camPar.rectAOI.s32Height.value), int(camPar.rectAOI.s32Width.value/2)) - # color = (255, 0, 0) - # thickness = 3 - first_passage = False + + first_passage = True while 1: time.sleep(t_wait) # Sleep for 1 seconds - ii = ii + 1 - + # extract the data of the image memory array = ueye.get_data(camPar.pcImageMemory, camPar.rectAOI.s32Width, camPar.rectAOI.s32Height, camPar.nBitsPerPixel, camPar.pitch, copy=False) - - # ...reshape it in an numpy array... + + # reshape it in an numpy array frame = np.reshape(array,(camPar.rectAOI.s32Height.value, camPar.rectAOI.s32Width.value, camPar.bytes_per_pixel)) - if first_passage == False: + if first_passage == True: maxi = np.max(frame) - fac = round(225/maxi) - if fac == 0: - fac = 1 - elif fac > 255: - fac = 255 print('maxi = ' + str(maxi)) - first_passage = True - - if ii%100 == 0: - print('frame max = ' + str(np.amax(frame*fac))) - print('frame min = ' + str(np.amin(frame*fac))) - print('fac = ' + str(fac)) - print("--- enlapse time :" + str(round((time.time() - start_time)*1000)/100) + 'ms') - start_time = time.time() - - #...and finally display it - cv2.imshow(window_name, frame*fac) + # Creating trackbars for color change + cv2.createTrackbar('brightness', window_name, maxi, 510, nothing) + first_passage = False - # if cv2.waitKey(1) & 0xFF == ord('p'): - # plt.figure() - # plt.plot(frame[:, int(camPar.rectAOI.s32Height.value/2)]) - - # Press q if you want to end the loop + # Get current positions of trackbar + brightness = cv2.getTrackbarPos('brightness', window_name) + + frame = frame.astype(np.float64) + frame2=frame*brightness/maxi + frame3=frame2.astype(np.uint8) + #*brightness/maxi + cv2.imshow(window_name, frame3) + if cv2.waitKey(1) & 0xFF == ord('q'): cv2.destroyWindow(window_name) break @@ -665,7 +657,9 @@ def extract_ROI_coord(DMD_params, acquisition_parameters, all_path, data_folder_ y_mask_coord (np.array): the y coord, first and last point of the rectangular that most closely the freehand ROI """ - + + import cv2 + if data_name != all_path.data_name and data_name != '': print('Warning, you read an old acquisition') print('') @@ -832,8 +826,8 @@ def freehand_ROI(event,former_x,former_y,flags,param): lim_mask_rot = np.stack(np.nonzero(mask_rot_re), axis=-1) y_mask_coord_HD = np.array([lim_mask_rot[:,0].min(), lim_mask_rot[:,0].max()], dtype=np.uint64) x_mask_coord_HD = np.array([lim_mask_rot[:,1].min(), lim_mask_rot[:,1].max()], dtype=np.uint64) - print('x_mask_HD = ' + str(x_mask_coord_HD)) - print('y_mask_HD = ' + str(y_mask_coord_HD)) + # print('x_mask_HD = ' + str(x_mask_coord_HD)) + # print('y_mask_HD = ' + str(y_mask_coord_HD)) # pour info, à commenter ultéreirement x_mask_HD_length = x_mask_coord_HD[1] - x_mask_coord_HD[0] y_mask_HD_length = y_mask_coord_HD[1] - y_mask_coord_HD[0] @@ -861,7 +855,7 @@ def freehand_ROI(event,former_x,former_y,flags,param): print('Selected zoom = x' + str(zoom_i)) print('With image size = (' + str(Npx) + ',' + str(Npy) + ')') - val = input("Are you ok with this image size ?[y/n] ") + val = input("Are you ok with this image size ?[y/n]") if val == 'n': Np_new = input('please entre the image side size you want (Np) : ') Npx = int(Np_new) @@ -1046,4 +1040,4 @@ def freehand_ROI(event,former_x,former_y,flags,param): - \ No newline at end of file +