import numpy as np from datetime import datetime import numpy as np import pandas as pd import sys import os.path import warnings import glob warnings.filterwarnings("ignore") path = '//atlas/ProjectLibrary/902305_Event_Detection_with_SES/Analyses/2025 MARS deployment/2025July_Nov' #import attenuance atn_files = glob.glob(path+'/*sip*') atn = pd.concat((pd.read_csv(f) for f in atn_files), ignore_index=True) atn["DateTime"] = pd.to_datetime(atn["Datetime"]) atn = atn.sort_values(by='DateTime') atn['atn'] = pd.to_numeric(atn['atn'], errors='coerce') atn['rounded_hour'] = atn['DateTime'].dt.round('H') numeric_colsatn = atn.select_dtypes(include=['number']).columns atn = atn.groupby('rounded_hour')['atn'].mean(numeric_only=True).reset_index() atn['rm150atn'] = atn['atn'].rolling(150, min_periods=23).mean() atn['Slope_rm_150atn'] = atn['rm150atn'].diff() #import fluorescence fluorescence = pd.read_csv('//atlas/ProjectLibrary/902305_Event_Detection_with_SES/Deployments/2026 Mooring/Prep analyses/TestingTriggerDualChannel_fluorescence.csv') fluorescence["DateTime"] = pd.to_datetime(fluorescence["SES Timestamp (ISO601)"]) fluorescence = fluorescence.sort_values(by='DateTime') fluorescence['Fluorescense_690'] = fluorescence['Fluorescense 690 Counts']-fluorescence['Dark Ref 690 Counts'] fluorescence['rounded_hour'] = fluorescence['DateTime'].dt.round('H') fluorescence = fluorescence.groupby('rounded_hour').mean(numeric_only=True).reset_index() #Round to nearest hour first. This will make it easier to combine later. fluorescence['rm150Fluorescense_690'] = fluorescence['Fluorescense_690'].rolling(150, min_periods=23).mean() fluorescence['Slope_rm_150fluoro'] = fluorescence['rm150Fluorescense_690'].diff() #triggering values lowtrigger_atn = 0.007 hightrigger_atn = 0.011 hightrigger_fluoro= 2.4 lowtrigger_fluoro= 1.8 use_min_period = 24 nrec=150 # Trigger code #Combine by floor minute merged_df = pd.merge(atn[['rounded_hour','rm150atn' ,'Slope_rm_150atn']], fluorescence[['rounded_hour', 'rm150Fluorescense_690','Slope_rm_150fluoro']], on='rounded_hour', how='outer') #atn trigger base merged_df["TriggerHigh_atn"] = np.where(merged_df['Slope_rm_150atn'] >= hightrigger_atn, 'Trigger', 'Wait') merged_df['Rate_HighTrigger_atn'] = (merged_df['TriggerHigh_atn'] == 'Trigger').rolling(144, min_periods=2).sum() merged_df['Max_HighTrigger_rate_atn'] = merged_df['Rate_HighTrigger_atn'].cummax() merged_df["TriggerLow_atn"] = np.where(merged_df['Slope_rm_150atn'] >= lowtrigger_atn, 'Trigger', 'Wait') merged_df['Rate_LowTrigger_atn'] = (merged_df['TriggerLow_atn'] == 'Trigger').rolling(144, min_periods=2).sum() merged_df['Max_LowTrigger_rate_atn'] = merged_df['Rate_LowTrigger_atn'].cummax() conditionsatn = [ (merged_df['Rate_LowTrigger_atn'] <= 1), #fire one low, then switch to high trigger (merged_df['Rate_HighTrigger_atn'] <= 1), #fire two high, then switch to higher trigger (merged_df['Rate_HighTrigger_atn'] ==3), #fire more 3 highs then even higher trigger (merged_df['Max_HighTrigger_rate_atn'] >= 4),#fire four or more highs, then use max trigger ((merged_df['Rate_HighTrigger_atn']).rolling(window=240, min_periods=1).sum()==0), #more than 1.5 week since last trigger, use the lower gear ] # Define corresponding choices (results) choicesatn = [np.where(merged_df['Slope_rm_150atn'] >= lowtrigger_atn, 'FireLow', 'Wait'), np.where(merged_df['Slope_rm_150atn'] >= hightrigger_atn, 'FireHigh', 'Wait'), np.where(merged_df['Slope_rm_150atn'] >= (hightrigger_atn*1.1), 'Fire1_1High', 'Wait'), np.where(merged_df['Slope_rm_150atn'] >= (hightrigger_atn*1.2), 'Fire1_2High', 'Wait'), np.where(merged_df['Slope_rm_150atn'] >= (hightrigger_atn), 'Fire_High', 'Wait')] merged_df["Fire_trigger_atn"] = np.select(conditionsatn, choicesatn, default='Wait') #fluoro trigger base merged_df["TriggerHigh_fluoro"] = np.where(merged_df['Slope_rm_150fluoro'] >= hightrigger_fluoro, 'Trigger', 'Wait') merged_df['Rate_HighTrigger_fluoro'] = (merged_df['TriggerHigh_fluoro'] == 'Trigger').rolling(144, min_periods=2).sum() merged_df['Max_HighTrigger_rate_fluoro'] = merged_df['Rate_HighTrigger_fluoro'].cummax() merged_df["TriggerLow_fluoro"] = np.where(merged_df['Slope_rm_150fluoro'] >= lowtrigger_fluoro, 'Trigger', 'Wait') merged_df['Rate_LowTrigger_fluoro'] = (merged_df['TriggerLow_fluoro'] == 'Trigger').rolling(144, min_periods=2).sum() merged_df['Max_LowTrigger_rate_fluoro'] = merged_df['Rate_LowTrigger_fluoro'].cummax() conditionsfluoro = [ (merged_df['Rate_LowTrigger_fluoro'] <= 1), #fire one low, then switch to high trigger (merged_df['Rate_HighTrigger_fluoro'] <= 2), #fire two high, then switch to higher trigger (merged_df['Rate_HighTrigger_fluoro'] ==3), #fire more 3 highs then even higher trigger (merged_df['Max_HighTrigger_rate_fluoro'] >= 4),#fire four or more highs, then use max trigger ((merged_df['Rate_HighTrigger_fluoro']).rolling(window=240, min_periods=1).sum()==0), #more than 1.5 week since last trigger, use the lower gear ] # Define corresponding choices (results) choicesfluoro = [np.where(merged_df['Slope_rm_150fluoro'] >= lowtrigger_fluoro, 'FireLow', 'Wait'), np.where(merged_df['Slope_rm_150fluoro'] >= hightrigger_fluoro, 'FireHigh', 'Wait'), np.where(merged_df['Slope_rm_150fluoro'] >= (hightrigger_fluoro*1.1), 'Fire1_1High', 'Wait'), np.where(merged_df['Slope_rm_150fluoro'] >= (hightrigger_fluoro*1.2), 'Fire1_2High', 'Wait'), np.where(merged_df['Slope_rm_150fluoro'] >= (hightrigger_fluoro), 'Fire_High', 'Wait')] merged_df["Fire_trigger_fluoro"] = np.select(conditionsfluoro, choicesfluoro, default='Wait') #Combine both channels merged_df['combined_fire'] = np.where(merged_df['Fire_trigger_atn'].str.contains('ire')|merged_df['Fire_trigger_fluoro'].str.contains('ire'), 'Fire', 'Wait') #Send trigger signal on "Get_down == "Fire!" merged_df["Get_Down"] = np.where( (merged_df['combined_fire'] != 'Wait').rolling(window=48, min_periods=1).sum()==1, np.where((merged_df['combined_fire'] != 'Wait'), 'Fire!', 'Wait'), np.where(((merged_df['combined_fire'] == 'Wait').rolling(336, min_periods=2).sum()==0), 'Fire!', 'Wait'), ) #save results merged_df.to_csv('//atlas/ProjectLibrary/902305_Event_Detection_with_SES/Deployments/2026 Mooring/Prep analyses/merged_df.csv')