diff --git a/src/data/beach_orientations.m b/src/data/beach_orientations.m new file mode 100644 index 0000000..d537ad6 --- /dev/null +++ b/src/data/beach_orientations.m @@ -0,0 +1,73 @@ +% Calculate orientation the beach profile at each unique site and save to .mat file +% Needs the following coastal tools: +% J:\Coastal\Tools\MALT Logspiral Transformation +% J:\Coastal\Tools\Coordinate Transformations + +clear +clc + +% Load profile data, this is where we want to calculate orientations. +warning('off','all') +data = load('C:\Users\z5189959\Desktop\nsw_2016_storm_impact\data\raw\processed_shorelines\profiles.mat'); +data = data.data; + +output = []; + +for ii = 1:n + disp(num2str(ii)) + lat = data(ii).lat; + lon = data(ii).lon; + beach = data(ii).site{1}; + [x,y,utmzone] = deg2utm(lat,lon); + + if strcmp(beach, 'BOOM') == 1 || strcmp(beach, 'HARGn') == 1 || strcmp(beach, 'BILG') == 1 || strcmp(beach, 'HARGs') == 1 || strcmp(beach, 'DEEWHYn') == 1 + % log spiral transformation file is out of date. Talk to Mitch + continue + end + + if strcmp(beach, 'AVOCAs') == 1 + % negative solution. Talk to Mitch + continue + end + + % Get the sp log spiral transformed coordinates + xyz.x = x; + xyz.y = y; + xyz.z = 0; + out = xyz2spz(xyz,beach); + + % Define new bounds towards land and towards sea + % Distance is the number of m in the section to go towards + distance = 200; + s = out.s; + p_center = out.p; + + % Convert landwards and seawrds point back to lat/lon + spz_land.s = out.s; + spz_land.p = out.p-distance; + spz_land.z = 0; + xyz_land = spz2xyz(spz_land,beach); + [lat_land,lon_land] = utm2deg(xyz_land.x,xyz_land.y,utmzone); + + spz_sea.s = out.s; + spz_sea.p = out.p+distance; + spz_sea.z = 0; + xyz_sea = spz2xyz(spz_sea,beach); + [lat_sea,lon_sea] = utm2deg(xyz_sea.x,xyz_sea.y,utmzone); + + % Orientation in degrees anticlockwise from east, pointing towards land + orientation = radtodeg(atan2((xyz_land.y - xyz_sea.y), (xyz_land.x - xyz_sea.x))); + + row.lat_center = lat; + row.lon_center = lon; + row.lat_land = lat_land; + row.lon_land = lat_land; + row.lat_sea = lat_sea; + row.lon_sea = lon_sea; + row.orientation = orientation; + row.beach = beach; + output = [output; row]; +end +warning('on','all') + +save('orientations.mat','output','-v7') diff --git a/src/data/mat_to_csv.py b/src/data/mat_to_csv.py index 6643d35..2bbf471 100644 --- a/src/data/mat_to_csv.py +++ b/src/data/mat_to_csv.py @@ -12,6 +12,50 @@ logging.config.fileConfig('../logging.conf', disable_existing_loggers=False) logger = logging.getLogger(__name__) +def parse_orientations(orientations_mat): + """ + Parses the raw orientations.mat file and returns a pandas dataframe. Note that orientations are the direction + towards land measured in degrees anti-clockwise from east. + :param orientations_mat: + :return: + """ + logger.info('Parsing %s', orientations_mat) + mat_data = loadmat(orientations_mat)['output'] + rows = [] + for i in range(0, len(mat_data['beach'])): + rows.append({ + 'beach': mat_data['beach'][i], + 'orientation': mat_data['orientation'][i], + 'lat_center': mat_data['lat_center'][i], + 'lon_center': mat_data['lon_center'][i], + 'lat_land': mat_data['lat_land'][i], + 'lon_land': mat_data['lon_land'][i], + 'lat_sea': mat_data['lat_sea'][i], + 'lon_sea': mat_data['lon_sea'][i], + }) + + df = pd.DataFrame(rows) + return df + +def combine_sites_and_orientaions(df_sites, df_orientations): + """ + Replaces beach/lat/lon columns with the unique site_id + :param dfs: + :param df_sites: + :return: + """ + + df_merged_sites = df_sites.merge(df_orientations[['beach', 'lat_center', 'lon_center', 'orientation']], + left_on=['beach', 'lat', 'lon'], + right_on=['beach', 'lat_center', 'lon_center']) + + # Check that all our records have a unique site identifier + n_unmatched = len(df_sites) - len(df_merged_sites) + if n_unmatched > 0: + logger.warning('Not all records (%d of %d) matched with an orientation', n_unmatched, len(df_sites)) + + return df_merged_sites + def parse_waves(waves_mat): """ Parses the raw waves.mat file and returns a pandas dataframe @@ -156,12 +200,16 @@ def main(): df_tides = parse_tides(tides_mat='../../data/raw/tides.mat') df_profiles = parse_profiles(profiles_mat='../../data/raw/profiles.mat') df_sites = get_unique_sites(dfs=[df_waves, df_tides, df_profiles]) + df_orientations = parse_orientations(orientations_mat='./data/raw/processed_shorelines/orientations.mat') logger.info('Identifying unique sites') df_waves = replace_unique_sites(df_waves, df_sites) df_tides = replace_unique_sites(df_tides, df_sites) df_profiles = replace_unique_sites(df_profiles, df_sites) + logger.info('Combine orientations into sites') + df_sites = combine_sites_and_orientaions(df_sites, df_orientations) + logger.info('Setting pandas index') df_profiles.set_index(['site_id', 'profile_type', 'x'], inplace=True) df_waves.set_index(['site_id', 'datetime'], inplace=True)