diff --git a/US/CA/SLAC/.index b/US/CA/SLAC/.index index 47fe5412..7d7de527 100644 --- a/US/CA/SLAC/.index +++ b/US/CA/SLAC/.index @@ -1,3 +1,4 @@ ica_analysis electrification loadfactor +anticipation diff --git a/US/CA/SLAC/anticipation/.catalog b/US/CA/SLAC/anticipation/.catalog new file mode 100644 index 00000000..612c49b3 --- /dev/null +++ b/US/CA/SLAC/anticipation/.catalog @@ -0,0 +1,7 @@ +header.glm:a=r +folium.glm:a=r +add_info.py:a=rx +status_log.py:a=rx +folium_data.py:a=rx +convert_to_csv.glm:a=rx +veg_data_preprocess.py:a=rx \ No newline at end of file diff --git a/US/CA/SLAC/anticipation/add_info.py b/US/CA/SLAC/anticipation/add_info.py new file mode 100644 index 00000000..c0954481 --- /dev/null +++ b/US/CA/SLAC/anticipation/add_info.py @@ -0,0 +1,7 @@ +import pandas as pd +csv_input = pd.read_csv('path_vege.csv') +wind_speed = 10 +width = 5 +csv_input['wind_speed'] = wind_speed +csv_input['width'] = width +csv_input.to_csv('path_vege.csv', index=False) \ No newline at end of file diff --git a/US/CA/SLAC/anticipation/convert_to_csv.glm b/US/CA/SLAC/anticipation/convert_to_csv.glm new file mode 100644 index 00000000..f485bbb8 --- /dev/null +++ b/US/CA/SLAC/anticipation/convert_to_csv.glm @@ -0,0 +1 @@ +#write ${modelname/.glm/}_feeder.csv overhead_line,node:phases \ No newline at end of file diff --git a/US/CA/SLAC/anticipation/folium.glm b/US/CA/SLAC/anticipation/folium.glm new file mode 100644 index 00000000..3779dfc4 --- /dev/null +++ b/US/CA/SLAC/anticipation/folium.glm @@ -0,0 +1,47 @@ +module powerflow; +#set relax_naming_rules=TRUE +class pole +{ + double pole_height; + double position; + double linesag; + double linesway; + double contact; + double strike; +} +class point +{ + double latitude; + double longitude; + double position; + double linesag; + double linesway; + double contact; + double strike; + char1024 status; +} +object pole_configuration +{ + name "tower"; +} +object pole_configuration +{ + name "3pole"; +} +object pole_configuration +{ + name "2pole"; +} +object pole_configuration +{ + name "vert3"; +} +object pole_configuration +{ + name "sideT"; +} +object pole_configuration +{ + name "flat3"; +} +#input "path_result_plot.csv" -f "table" -t "object" -C "point" -M "powerflow" \ No newline at end of file diff --git a/US/CA/SLAC/anticipation/folium_data.py b/US/CA/SLAC/anticipation/folium_data.py new file mode 100644 index 00000000..6d5d3a3c --- /dev/null +++ b/US/CA/SLAC/anticipation/folium_data.py @@ -0,0 +1,10 @@ +import pandas as pd +csv_input = pd.read_csv('path_result.csv', \ + usecols = ['position', 'latitude', 'longitude', 'linesag', 'linesway', 'contact', 'strike']) +csv_input['status'] = 'OK' # set default as OK +# read the strike value +strike_threshold = 0.1 +for index, row in csv_input.iterrows(): + if row['strike'] > strike_threshold: + csv_input.loc[index, "status"] = 'FAILED' +csv_input.to_csv('path_result_plot.csv', index=False) \ No newline at end of file diff --git a/US/CA/SLAC/anticipation/header.glm b/US/CA/SLAC/anticipation/header.glm new file mode 100644 index 00000000..7cf89c90 --- /dev/null +++ b/US/CA/SLAC/anticipation/header.glm @@ -0,0 +1,76 @@ +// Test poles +// +// +// Convert command: +// gridlabd convert CARDINAL_Polar\ -\ Design\ CalcDesign\ DSO.xlsx cardinal_poles.csv -f xlsx-spida -t csv-geodata +// +// Run command: +// gridlabd main_cardinal_poles.glm // cardinal_poles.glm +// +// Python command: +// convert('CARDINAL_Polar - Design CalcDesign DSO.xlsx', 'CARDINAL_PolarDesign Attachment and Equipment_Asset Details from SPIDA and SAP.xlsx', 'cardinal_poles.csv', options={'extract_equipment':'yes','include_network':'yes', 'include_mount':'yes', 'include_network':'CARDINAL.csv'}) +// +#define suppress_repeat_messages=TRUE +#define pythonpath="/usr/local/opt/gridlabd/current/share/gridlabd/template/US/CA/SLAC/anticipation" +//#exec printenv +#set minimum_timestep=3600 + + +module status_log; +module climate; +module tape; + +module powerflow { + solver_method NR; + line_capacitance true; + message_flags VERBOSE; + } +#ifdef RELIABILITY_ON +module reliability { + report_event_log true; +} +object fault_check { + name test_fault; + check_mode ONCHANGE; + reliability_mode true; +// output_filename ${FAULT_OUT_PATH}; + grid_association true; +}; + +object power_metrics { + name pwrmetrics; + base_time_value 1 h; +} + +object metrics { + name testmetrics; + report_file metrics.txt; + module_metrics_object pwrmetrics; + metrics_of_interest "SAIFI,SAIDI,CAIDI,ASAI,MAIFI"; + customer_group "class=meter"; + metric_interval 5 h; + report_interval 5 h; +}; +#endif +clock { + starttime "${STARTTIME}"; + stoptime "${STOPTIME}"; + timezone "${TIMEZONE}"; +} + + +#ifdef WIND_SPEED +object climate { + name weather; + object player { + property wind_speed; + file ${WIND_SPEED}; + }; +} +#else +#weather get CA-Chino_Airport.tmy3 +object climate { + name weather; + tmyfile "CA-Chino_Airport.tmy3"; +} +#endif \ No newline at end of file diff --git a/US/CA/SLAC/anticipation/status_log.py b/US/CA/SLAC/anticipation/status_log.py new file mode 100644 index 00000000..ca54315e --- /dev/null +++ b/US/CA/SLAC/anticipation/status_log.py @@ -0,0 +1,53 @@ +import pandas as pd +import datetime + +metered_energy = {} +pole_status = {} +objs = {} +wrn_count = 0 + +def get_info(t, object_class, target_property) : + for obj in objs: + if gridlabd.get_object(obj)['class'] == object_class: + if t not in data: + data[t] = {} + data[t][obj] = gridlabd.get_object(obj)[target_property] + return data + +def dump_csv(data,file_name ) : + # Flatten the nested dictionary + flat_data = [] + + for timestamp, item in data.items(): + row = {'timestamp': datetime.datetime.fromtimestamp(timestamp).strftime('%Y-%m-%d %H:%M:%S')} + row.update(item) + flat_data.append(row) + + # Create a DataFrame + df = pd.DataFrame(flat_data).set_index('timestamp') + df.to_csv(file_name, index=True) + return df + +def on_init(t) : + global objs + objs = gridlabd.get('objects') + return True + +def on_commit(t) : + global pole_status, metered_energy, wrn_count + pole_status.update(get_info(t,'pole', 'status')) + # pole_status.update(get_info(t,'pole', 'total_moment')) + try : + metered_energy.update(get_info(t,'meter','measured_real_energy')) + finally : + if wrn_count == 0 : + print(f"WARNING [status_log]: meters are not available in the model.") + wrn_count = 1 + return True + +def on_term(t) : + global pole_status, metered_energy + + df_energy = dump_csv(pole_status,'/tmp/output/pole_status.csv') + dump_csv(metered_energy, '/tmp/output/metered_energy.csv') + return None \ No newline at end of file diff --git a/US/CA/SLAC/anticipation/veg_data_preprocess.py b/US/CA/SLAC/anticipation/veg_data_preprocess.py new file mode 100644 index 00000000..dba4f4c2 --- /dev/null +++ b/US/CA/SLAC/anticipation/veg_data_preprocess.py @@ -0,0 +1,35 @@ +import pandas as pd +import sys + +def extract_poles() : + input_file_name = sys.argv[1] + output_file_name = sys.argv[2] + + df = pd.read_csv(input_file_name) + + # Create a new DataFrame with only rows where 'class' is 'pole' + filtered_df = df[df['class'] == 'pole'] + + # Reset the index of the filtered DataFrame + filtered_df.reset_index(drop=True, inplace=True) + + # Extract 'pole_length' from the corresponding 'pole_configuration' rows + pole_length_map = dict(zip(df[df['class'] == 'pole_configuration']['name'], df[df['class'] == 'pole_configuration']['pole_length'])) + + # Map 'pole_length' values based on 'class' using .map after creating a copy + filtered_df = filtered_df.copy() # Create a copy to avoid SettingWithCopyWarning + + filtered_df['pole_length'] = filtered_df['configuration'].map(pole_length_map) + + # Check for missing values in latitude and longitude columns and drop rows with any missing value + filtered_df.dropna(subset=["latitude", "longitude"], inplace=True) + + # Reset the index + filtered_df.reset_index(drop=True, inplace=True) + + # Display the final DataFrame + filtered_df.to_csv(output_file_name, index=False) + + +if __name__ == "__main__": + extract_poles() \ No newline at end of file