4
\$\begingroup\$

This is a school project I have been working on. I have created a program utilizing Tkinter, and I was hoping to get some feedback on the way I have gone about things. I feel like it is pretty messy and there are several parts that could be reduced. The transfromation/snapping gui is something I threw together due to time constraints. I would rather split them if I had more time. It is rather long so I appreciate anyone taking the time to go over it.

from shapely.geometry import asShape
import re
import pandas as pd
from pyproj import Proj
from pyproj import transform
from pyproj import _datadir,datadir
import tkinter as tk
import tkinter.messagebox
import tkinter.filedialog
from geopy import GoogleV3,Nominatim

# to do list:
# ****General****
# update the application when you open a new file
# fix grid in tools; may want to use columnspan
# may want to add a way to check the value of what is in data_text rather than continuing to overwrite the self.input_df
# see if there is a way to make a single function (moment where you can ask for columns and pass that to other classes)
# change it so the data_text shows the first 100 rows (self.input.head(100))
# progress bars
# ****Join****
# add ability to save joined file
# ****normalization****
# add shortcuts for normalizing rows
# ****snapping****
# add ability to save snapped file
#

class Toolbar(tk.Frame):
    """
    A class used to house separate the tool bar menu and house other classes.

    Attributes
    ----------

    None

    Methods
    -------
    file_save_to_excel()
        Saves a file in xlsx format

    file_open_xlsx()
        Opens a file in xlsx format

    read_excel()
        reads an excel file to a pandas dataframe

    """
    def __init__(self, parent, data_text, tools):
        """
        Parameters
        ----------
        parent: tk object
            The tikinter root object
        data_text: tk object
            Tkinter text box object that displays the dataframe
        tools: list
            List of dictionaries that contain tool labels and classes

        """

        tk.Frame.__init__(self, parent)

        self.parent = parent
        self.input_df = pd.DataFrame()

        self.menu = tk.Menu(self.parent)
        self.parent.config(menu=self.menu)

        self.data_text = data_text
        self.input_df = pd.DataFrame()
        self.input_file_name = "No File Selected"

        self.file_submenu = tk.Menu(self.menu, tearoff=0)
        self.menu.add_cascade(label="File", menu=self.file_submenu)
        self.file_submenu.add_command(label="Save", command=self.file_save)
        self.file_submenu.add_command(label="Open", command=self.file_open_xlsx)
        self.file_submenu.add_command(label="Contact Info", command=self.info_gui)

        self.tool_submenus = []
        self.tool_submenu = tk.Menu(self.menu, tearoff=0)
        self.menu.add_cascade(label="Tools", menu=self.tool_submenu)

        for tool in tools:
            self.tool_submenus.append(self.tool_submenu.add_command(label=tool["label"], command=tool["function"]))

    def file_save(self):
        """Saves a file to excel

        The function uses tkinter's asksaveasfile method to get the file name, and pandas to_excel method save the file

        Parameters
        ----------
        None

        Raises
        ------
        """

        file_path = tkinter.filedialog.asksaveasfile(mode="w",defaultextension=".*",
                                                     filetypes=(("Excel files","*.xlsx"),
                                                                ("Json files","*.json"),
                                                                ("Comma Seperated Value files","*.csv")))
        extension = file_path.name.split(".")[1]

        if extension == "xlsx":
            self.input_df.to_excel(file_path.name)
        elif extension == "csv":
            self.input_df.to_csv(file_path.name)
        elif extension == "json":
            self.input_df.to_json(file_path.name)
        else:
            print("file was not saved")

    def file_open_xlsx(self):

        file = tkinter.filedialog.askopenfile(mode="r")
        self.input_file_name = file.name
        if self.input_file_name.split(".")[1] is "xlsx" or "csv":
            self.read_excel()

    def read_excel(self):

        def set_pandas_options() -> None:
            pd.options.display.max_columns = 1000
            pd.options.display.max_rows = 1000
            pd.options.display.max_colwidth = 50
            pd.options.display.width = 400

        self.input_df = pd.read_excel(self.input_file_name)

        set_pandas_options()

        self.data_text.delete(1.0, "end-1c")
        self.data_text.insert("end-1c", self.input_df.head(100))

    def info_gui(self):
        self.api_top = tk.Toplevel(self.parent)
        self.api_top.minsize(270, 70)

        self.api_top.title("Info")

        self.api_msg = tk.Message(self.api_top, text="Contact: kmcnew2@gmail.com", anchor="w", width=300,
                                  justify="left")
        self.api_msg2 = tk.Message(self.api_top, text="Website: keaganmcnew.com", anchor="w", width=300, justify="left")
        self.api_msg3 = tk.Message(self.api_top, text="Credit: Keagan McNew", anchor="w", width=300, justify="left")
        self.api_msg.pack()
        self.api_msg2.pack()
        self.api_msg3.pack()

class Table(tk.Frame):
    def __init__(self, parent, *args, **kwargs):
        tk.Frame.__init__(self, parent, *args, **kwargs)
        self.parent = parent

        self.data_text = tk.Text(self.parent, width=100, height=50, wrap="none", borderwidth=0)
        self.data_text_vsb = tk.Scrollbar(self.parent, orient="vertical", command=self.data_text.yview)
        self.data_text_hsb = tk.Scrollbar(self.parent, orient="horizontal", command=self.data_text.xview)
        self.data_text.configure(yscrollcommand=self.data_text_vsb.set, xscrollcommand=self.data_text_hsb.set)

        self.data_text_vsb.grid(row=0, rowspan=3, column=4, sticky="nsw")
        self.data_text_hsb.grid(row=3, column=1,columnspan=3, sticky="ew")

        self.data_text.grid(row=0,rowspan=3, column=1,columnspan=3, sticky="nswe")
class InputContainer(tk.Frame):
    def __init__(self, parent, input_df, data_text, *args, **kwargs):
        tk.Frame.__init__(self, parent, *args, **kwargs)
        self.parent = parent

        self.input_df = input_df
        self.data_text = data_text

        text = "Budapest Project v0.01\n\n" \
               "Note, this is a very first version of this program.\n" \
               " Several features are to be included in" \
               "newer versions:\n\n" \
               "- update application when opening a new file\n" \
               "- shortcuts for regex functions\n" \
               "- only display first 100 rows\n" \
               "- progress bars\n" \
               "- error messages\n" \
               "- various informational messages\n" \
               "- help windows with links to resources\n" \
               "- fix sizing issues\n" \
               "- refactor code; document code\n" \
               "- add database/sql functionality*\n" \
               "- overall better look\n\n" \
               "* note this may not be implemented\n\n" \
               "To start please first open an excel file and then choose a tool"

        self.input_container = tk.Frame(self.parent, bd=10, relief="sunken").grid(row=0, column=0,sticky="w")
        self.input_label = tk.Label(self.input_container, text=text).grid(row=0,column=0, sticky="nw")

class NormalizationGUI(InputContainer):
    def __init__(self, parent, input_df, data_text, *args, **kwargs):
        InputContainer.__init__(self, parent, input_df, data_text, *args, **kwargs)

        self.input_container = tk.Frame(self.parent, bd=5,padx=10, relief="sunken")
        self.input_label = tk.Label(self.input_container, text="Normalization",font=("Times New Roman",12)).grid(row=0, sticky="w",pady=20)

        self.normalization_column_input = tk.Label(self.input_container, text="Column")
        self.normalization_column_input.grid(row=2, sticky="w")
        self.normalization_columns = tk.StringVar()

        try:
            keys = [item for item in self.input_df.columns]
            self.normalization_columns.set(keys[0])
        except IndexError:
            keys = ["nan"]
            self.normalization_columns.set("nan")

        self.normalization_column_options = tk.OptionMenu(self.input_container, self.normalization_columns, *keys).grid(
            row=3, sticky="w")

        self.normalization_re_input = tk.Label(self.input_container, text="Regular Expression").grid(row=4, sticky="w")
        self.re = tk.StringVar()
        self.normalization_re_entry = tk.Entry(self.input_container, textvariable=self.re)
        self.normalization_re_entry.grid(row=5, column=0,sticky="w")

        self.replacement_label = tk.Label(self.input_container, text="Replacement Value").grid(row=6, column=0,
                                                                                               sticky="w")
        self.replacement = tk.StringVar()
        self.normalization_replacement_entry = tk.Entry(self.input_container, textvariable=self.replacement).grid(row=7,
                                                                                                                  column=0,
                                                                                                                  sticky="w")

        self.button_test_re = tk.Button(self.input_container, text="test regular expression",
                                        command=self.print_regex_example, bd=2).grid(row=8, sticky="w")
        self.re_test_text = tk.Text(self.input_container, width=50, height=2)
        self.re_test_text.grid(row=9,columnspan=3)

        self.button_run_re = tk.Button(self.input_container, text="run regular expression", command=self.normalize_column,
                                       bd=2).grid(row=10,columnspan=2,pady=10)

        self.address_input_label = tk.Label(self.input_container, text="Address Normalization and Parsing",font=("Times New Roman",12)).grid(row=11, sticky="w",pady=20)
        self.address_column_input = tk.Label(self.input_container, text="Column")
        self.address_column_input.grid(row=12, sticky="w")
        self.address_columns = tk.StringVar()

        try:
            ad_keys = [item for item in self.input_df.columns]
            self.address_columns.set(ad_keys[0])
        except (TypeError,IndexError):
            ad_keys = ["nan"]
            self.address_columns.set(ad_keys[0])

        self.address_column_options = tk.OptionMenu(self.input_container, self.address_columns, *ad_keys).grid(
            row=13, sticky="w")

        self.before_address_components_label = tk.Label(self.input_container,
                                                        text="Components to Be placed before Address").grid(row=14,
                                                                                                            sticky="w")
        self.before_address_components = tk.StringVar()
        self.before_address_components_entry = tk.Entry(self.input_container, textvariable=self.before_address_components)
        self.before_address_components_entry.grid(row=15,sticky="w")

        self.after_address_components_label = tk.Label(self.input_container,
                                                        text="Components to Be placed after Address").grid(row=16,
                                                                                                            sticky="w")
        self.after_address_components = tk.StringVar()
        self.after_address_components_entry = tk.Entry(self.input_container, textvariable=self.after_address_components)
        self.after_address_components_entry.grid(row=17,sticky="w")

        self.test_address_normal_button = tk.Button(self.input_container, text="test address normalization",
                                        command=self.print_address_example, bd=2).grid(row=18, sticky="w")
        self.test_address_normal_text = tk.Text(self.input_container, width=50, height=2)
        self.test_address_normal_text.grid(row=19, columnspan=3)

        self.address_normal_button = tk.Button(self.input_container, text="Normalize Addresses",
                                                    command=self.create_full_address, bd=2).grid(row=20, columnspan=2,pady=10)

        self.seperate_street_number_button = tk.Button(self.input_container, text="Seperate Streets/Numbers",
                                               command=self.seperate_street_and_number, bd=2).grid(row=21,sticky="w")

        self.input_container.grid(row=0, column=0, sticky="nswe")
        self.input_container.update()

    def seperate_street_and_number(self):
        self.input_df["number"] = self.input_df[self.address_columns.get()].str.extract(r"(\d+\-\d+|\d+\/*\w*|\(\-\))")
        self.input_df["street"] = self.input_df[self.address_columns.get()].str.replace(r"\d+\-\d+|\d+\/*\w*|\(\-\)", "")

        self.data_text.delete(1.0, "end-1c")
        self.data_text.insert("end-1c", self.input_df)

    def create_full_address(self,):

        before_items = self.before_address_components.get().split(",")
        after_items = self.after_address_components.get().split(",")

        address = self.input_df[self.address_columns.get()]

        for before_item in reversed(before_items):
            if before_item is not "":
               address = before_item + ", " + address
        for after_item in reversed(after_items):
            if after_item is not "":
                address = address + ", " + after_item

        self.input_df["full address"] = address

        self.data_text.delete(1.0, "end-1c")
        self.data_text.insert("end-1c",self.input_df)

    def print_address_example(self,):

        before_items = self.before_address_components.get().split(",")
        after_items = self.after_address_components.get().split(",")

        address = self.input_df.iloc[0][self.address_columns.get()]

        for before_item in reversed(before_items):
            if before_item is not "":
                address = before_item + ", " + address
        for after_item in reversed(after_items):
            if after_item is not "":
                address = address + ", " + after_item

        self.test_address_normal_text.delete(1.0, "end-1c")
        self.test_address_normal_text.insert("end-1c",
                                             self.input_df.iloc[0][self.address_columns.get()] + "----> " + address)

    def print_regex_example(self):

        def test_re(text, regex_pattern, replacement_text):
            pattern = re.compile(regex_pattern)
            result = re.findall(pattern, text)

            for item in result:
                text = text.replace(str(item), replacement_text)

            return text

        self.example_re = test_re(self.input_df.iloc[0][self.normalization_columns.get()],
                                  r'{}'.format(self.re.get()), self.replacement.get())
        self.re_test_text.delete(1.0, "end-1c")
        self.re_test_text.insert("end-1c",
                                 self.input_df.iloc[0][self.normalization_columns.get()] + " ----> " + self.example_re)

    def normalize_column(self):
        self.input_df[self.normalization_columns.get()] = \
            self.input_df[self.normalization_columns.get()].str.replace(self.re.get(), self.replacement.get())
        self.data_text.delete(1.0, "end-1c")
        self.data_text.insert("end-1c", self.input_df)


class JoinGUI(InputContainer):
    def __init__(self, parent, input_df, input_file_name, data_text, *args, **kwargs):

        self.input_file = input_file_name

        InputContainer.__init__(self, parent, input_df, data_text, *args, **kwargs)

        def open_join_file():

            self.join_file = tkinter.filedialog.askopenfile(mode="r").name
            self.join_df = pd.read_excel(self.join_file)

            self.join_text.delete(1.0, "end-1c")
            self.join_text.insert("end-1c", self.join_file)

        def merge_dataframes():

            self.merged_datasets = pd.merge(self.input_df,self.join_df, on=self.join_columns.get(), how=self.join_method.get())
            self.input_df = self.merged_datasets

            self.data_text.delete(1.0, "end-1c")
            self.data_text.insert("end-1c", self.input_df)


        self.join_file = ""

        self.input_container = tk.Frame(self.parent, bd=1, relief="sunken")
        self.input_label = tk.Label(self.input_container, text="Join").grid(row=0, padx=2, sticky="w")

        self.input_label = tk.Label(self.input_container, text="Input File(left):").grid(row=1,sticky="w")

        self.input_join_text = tk.Text(self.input_container,width=50,height=2)
        self.input_join_text.grid(row=2)
        self.input_join_text.delete(1.0, "end-1c")
        self.input_join_text.insert("end-1c", self.input_file)

        self.join_label = tk.Label(self.input_container, text="Join File(right):").grid(row=3, sticky="w")

        self.open_join_file_button = tk.Button(self.input_container,text="open",command=open_join_file).grid(row=4,sticky="w")
        self.join_text = tk.Text(self.input_container, width=50, height=2)
        self.join_text.grid(row=5)

        self.join_columns = tk.StringVar()
        try:
            keys = [item for item in self.input_df.columns]
            self.join_columns.set(keys[0])
        except IndexError:
            keys = ["nan"]
            self.join_columns.set("nan")


        self.join_column_options = tk.OptionMenu(self.input_container, self.join_columns, *keys).grid(row=6, sticky="w")

        join_options = ["left","right","outer","inner"]
        self.join_method = tk.StringVar()
        self.join_method.set(join_options[0])
        self.join_method_label = tk.Label(self.input_container,text="Join Method").grid(row=7,sticky="w")
        self.join_method_entry = tk.OptionMenu(self.input_container,self.join_method,*join_options).grid(row=8,sticky="w")

        self.run_join_button = tk.Button(self.input_container,text="join",command=merge_dataframes).grid(row=9,sticky="w")

        self.input_container.grid(row=0, column=0, sticky="nswe")
        self.input_container.update()
class GeocoderGUI(InputContainer):
    def __init__(self, parent, input_df,  data_text, *args, **kwargs):
        InputContainer.__init__(self, parent, input_df, data_text, *args, **kwargs)

        self.input_container = tk.Frame(self.parent, bd=1, relief="sunken")
        self.input_label = tk.Label(self.input_container, text="Geocoder")
        self.input_label.grid(row=0, padx=2, sticky="w")

        self.geocoder_options_label = tk.Label(self.input_container, text="Geocoder").grid(row=2, sticky="w")
        geocoder_options_list = ["Google","Open Street Maps"]
        self.geocoder_options = tk.StringVar()
        self.geocoder_options.set(geocoder_options_list[0])
        self.geocoder_options_menu = tk.OptionMenu(self.input_container, self.geocoder_options, *geocoder_options_list).grid(
            row=3, sticky="w")

        self.useragent_apikey_label = tk.Label(self.input_container,text="User Key or API Key").grid(row=4,sticky="w")
        self.useragent_apikey= tk.StringVar()
        self.useragent_apikey_entry = tk.Entry(self.input_container,textvariable=self.useragent_apikey)
        self.useragent_apikey_entry.grid(row=5,sticky="w")

        self.address_options_label = tk.Label(self.input_container, text="Address Column").grid(row=6,sticky="w")
        self.address_options = tk.StringVar()

        try:
            address_options_list = [key for key in self.input_df.columns]
            self.address_options.set(address_options_list[0])
        except IndexError:
            address_options_list = ["nan"]
            self.address_options.set("nan")


        self.address_options_menu = tk.OptionMenu(self.input_container,self.address_options,*address_options_list).grid(row=7,sticky="w")

        self.geocoder_button = tk.Button(self.input_container,text="Geocode",command=self.geocoder).grid(row=8,sticky="w")

        self.input_container.grid(row=0, column=0, sticky="nswe")
        self.input_container.update()

    def geocoder(self):

        if self.geocoder_options.get() == "Open Street Maps":
            geolocator = Nominatim(user_agent=str(self.useragent_apikey.get()), timeout=30)
        elif self.geocoder_options.get() == "Google":
            geolocator = GoogleV3(api_key=str(self.useragent_apikey.get()), timeout=30)
        else:
            print("did not find geocoder")
            return "nan", "nan"

        lat = []
        long = []

        for item in self.input_df[self.address_options.get()]:
            try:
                location = geolocator.geocode(item)
                lat.append(location.latitude)
                long.append(location.longitude)
            except AttributeError:
                lat.append("nan")
                long.append("nan")

        self.input_df["lat"] = lat
        self.input_df["long"] = long

        self.data_text.delete(1.0, "end-1c")
        self.data_text.insert("end-1c", self.input_df)
class TransformationandSnappingGUI(InputContainer):
    def __init__(self, parent, input_df, input_file_name, data_text, *args, **kwargs):
        InputContainer.__init__(self, parent, input_df, data_text, *args, **kwargs)

        self.input_file = input_file_name

        try:
            self.reference_address_list = self.create_reference_address_list(self.input_df)
        except KeyError:
            self.reference_address_list = ["nan"]

        self.input_container = tk.Frame(self.parent, bd=1, relief="sunken")

        self.points_label = tk.Label(self.input_container, text="Points File:").grid(row=1, sticky="w")
        self.points_text = tk.Text(self.input_container, width=50, height=2)
        self.points_text.grid(row=2)
        self.points_text.delete(1.0, "end-1c")
        self.points_text.insert("end-1c", self.input_file)

        self.streets_label = tk.Label(self.input_container, text="Streets File:").grid(row=3, sticky="w")
        self.open_streets_file_button = tk.Button(self.input_container, text="open", command=self.open_streets_file).grid(row=4,
                                                                                                               sticky="w")
        self.streets_text = tk.Text(self.input_container, width=50, height=2)
        self.streets_text.grid(row=5)

        self.trans_label = tk.Label(self.input_container,text="Transformations").grid(row=6,sticky="w")

        self.trans_input_label = tk.Label(self.input_container, text="Current Coordinate System").grid(row=7, sticky="w")
        self.current_espg_label = tk.Label(self.input_container, text="EPSG:").grid(row=8,sticky="w")
        self.trans_current_coordinate_system = tk.StringVar()
        self.trans_current_coordinate_system_entry = tk.Entry(self.input_container,
                                                          textvariable=self.trans_current_coordinate_system)
        self.trans_current_coordinate_system_entry.grid(row=8,column=1, sticky="w")

        self.trans_input_label = tk.Label(self.input_container, text="New Coordinate System").grid(row=9,sticky="w")
        self.new_espg_label = tk.Label(self.input_container, text="EPSG:").grid(row=10, sticky="w")
        self.trans_new_coordinate_system = tk.StringVar()
        self.trans_new_coordinate_system_entry = tk.Entry(self.input_container,textvariable=self.trans_new_coordinate_system)
        self.trans_new_coordinate_system_entry.grid(row=10,column=1,sticky="w")

        self.snap_button = tk.Button(self.input_container,text="snap points",command=self.snapping_function).grid(row=11,sticky="w")

        self.input_container.grid(row=0, column=0, sticky="nswe")
        self.input_container.update()

    def create_reference_address_list(self,address_df):
        address_list = list(set(address_df["street"].values.tolist()))
        address_list.pop(0)

        return address_list

    def open_streets_file(self):
        self.streets_file = tkinter.filedialog.askopenfile(mode="r").name
        self.streets_df = pd.read_excel(self.streets_file)

        self.streets_text.delete(1.0, "end-1c")
        self.streets_text.insert("end-1c", self.streets_file)

    def snapping_function(self,):

        def seperate_streets(streets_df,reference_address_list):

            poi_street_list = []
            poi_street_dictionary = {}

            for street in streets_df.itertuples():
                try:
                    if str(street.Name) == reference_address_list[0]:
                        poi_street_dictionary["street"] = street.Name
                        poi_street_dictionary["lat_begin"] = street.lat_begin
                        poi_street_dictionary["long_begin"] = street.long_begin
                        poi_street_dictionary["lat_end"] = street.lat_end
                        poi_street_dictionary["long_end"] = street.long_end

                        poi_street_list.append(poi_street_dictionary.copy())

                except AttributeError:
                    pass

            return poi_street_list

        def seperate_addresses(input_df,reference_address_list):

            poi_address_list = []
            poi_address_dictionary = {}

            for address in input_df.itertuples():
                try:
                    if str(address.street) == reference_address_list[0]:
                        poi_address_dictionary["full_address"] = address.full_address
                        poi_address_dictionary["street"] = address.street
                        poi_address_dictionary["number"] = address.number
                        poi_address_dictionary["lat"] = address.lat
                        poi_address_dictionary["long"] = address.long

                        poi_address_list.append(poi_address_dictionary.copy())
                except AttributeError:
                    pass
            return poi_address_list

        def convert_to_streets_and_addresses_to_geojson(streets_list, address_list):

            line_segments = []
            line_name = ""
            for segment in streets_list:
                coordinates_begin = [segment["long_begin"], segment["lat_begin"]]
                coordinates_end = [segment["long_end"], segment["lat_end"]]

                line_name = segment["street"]
                line_segments.append(coordinates_begin)
                line_segments.append(coordinates_end)

            line = {"street": line_name,
                    "type": "Feature",
                    "properties": {},
                    "geometry":
                        {"type": "LineString",
                         "coordinates": line_segments}}

            points = []
            point = {}
            for point_d in address_list:
                point = {"full_address": point_d["full_address"],
                         "street": point_d["street"],
                         "number": point_d["number"],
                         "type": "Feature",
                         "properties": {},
                         "geometry":
                             {"type":
                                  "Point",
                              "coordinates": [point_d["long"], point_d["lat"]]}}

                points.append(point.copy())

            return points, line

        def transform_geom(orig_geojs, in_crs, out_crs):
            """
            transform a GeoJSON linestring or Point to
              a new coordinate system
            :param orig_geojs: input GeoJSON
            :param in_crs: original input crs
            :param out_crs: destination crs
            :return: a new GeoJSON
            """

            wgs84_coords = []
            # transfrom each coordinate
            if orig_geojs['geometry']['type'] == "LineString":
                for x, y in orig_geojs['geometry']['coordinates']:
                    x1, y1 = transform(in_crs, out_crs, x, y)
                    orig_geojs['geometry']['coordinates'] = x1, y1
                    wgs84_coords.append([x1, y1])
                # create new GeoJSON
                new_wgs_geojs = dict(type='Feature', properties={})
                new_wgs_geojs['geometry'] = dict(type='LineString')
                new_wgs_geojs['geometry']['coordinates'] = wgs84_coords

                return new_wgs_geojs

            elif orig_geojs['geometry']['type'] == "Point":

                x = orig_geojs['geometry']['coordinates'][0]
                y = orig_geojs['geometry']['coordinates'][1]
                x1, y1 = transform(in_crs, out_crs, x, y)
                orig_geojs['geometry']['coordinates'] = x1, y1
                coord = x1, y1
                wgs84_coords.append(coord)

                new_wgs_geojs = dict(type='Feature', properties={})
                new_wgs_geojs['geometry'] = dict(type='Point')
                new_wgs_geojs['geometry']['coordinates'] = wgs84_coords

                return new_wgs_geojs
            else:
                print("sorry this geometry type is not supported")

        current_coordinate_system = Proj("+init=EPSG:{}".format(self.trans_current_coordinate_system.get()))
        new_coordinate_system = Proj("+init=EPSG:{}".format(self.trans_new_coordinate_system.get()))

        new_points = []

        while self.reference_address_list:
            poi_address_list = seperate_addresses(self.input_df, self.reference_address_list)
            poi_streets_list = seperate_streets(self.streets_df, self.reference_address_list)

            points,line = convert_to_streets_and_addresses_to_geojson(poi_streets_list,poi_address_list)

            new_line = transform_geom(line,current_coordinate_system,new_coordinate_system)

            for point in points:

                new_point = transform_geom(point, current_coordinate_system, new_coordinate_system)
                new_point["full_address"] = point["full_address"]
                new_point["street"] = point["street"]
                new_point["number"] = point["number"]
                try:
                    shply_line = asShape(new_line["geometry"])
                    shply_point = asShape(new_point["geometry"])

                    pt_interpolate = shply_line.interpolate(shply_line.project(shply_point))

                    print("origin point location: {}".format(new_point["geometry"]["coordinates"]))
                    print("interpolated point location: {}".format(pt_interpolate.bounds[0], pt_interpolate.bounds[1]))
                    new_point["interpolated_x"] = pt_interpolate.bounds[0]
                    new_point["interpolated_y"] = pt_interpolate.bounds[1]

                    print("distance from origin to interpolated point: {}".format(shply_point.distance(pt_interpolate)))
                    new_point["interpolated_distance"] = shply_point.distance(pt_interpolate)

                except TypeError:
                    new_point["interpolated_x"] = "nan"
                    new_point["interpolated_y"] = "nan"
                    new_point["interpolated_distance"] = "nan"

                new_points.append(new_point.copy())

            self.reference_address_list.pop(0)

            self.snapped_points_df = pd.DataFrame(new_points)

            self.data_text.delete(1.0, "end-1c")
            self.data_text.insert("end-1c", self.snapped_points_df)

class Main(tk.Frame):

    def __init__(self, parent, *args, **kwargs):
        tk.Frame.__init__(self, parent, *args, **kwargs)
        self.parent = parent
        self.parent.title("Budapest Program")

        self.table = Table(self.parent)

        self.tools = [{
            "label": "Normalization",
            "function": lambda : NormalizationGUI(self.parent, self.toolbar.input_df, self.table.data_text)
        },{
            "label": "Join",
            "function": lambda : JoinGUI(self.parent, self.toolbar.input_df, self.toolbar.input_file_name, self.table.data_text)
        },{
            "label": "Geocoder",
            "function": lambda : GeocoderGUI(self.parent, self.toolbar.input_df,self.table.data_text)
        },{
            "label": "Transformation",
            "function": lambda : TransformationandSnappingGUI(self.parent, self.toolbar.input_df, self.toolbar.input_file_name, self.table.data_text)
        }]

        self.toolbar = Toolbar(self.parent, self.table.data_text, self.tools)

        self.input_df = self.toolbar.input_df

        self.input_container = InputContainer(self.parent, self.input_df, self.table.data_text)

        self.parent.grid_columnconfigure(0, weight=1)
        self.parent.grid_rowconfigure(0,weight=1)


if __name__ == "__main__":
    root = tk.Tk()
    Main(root)
    root.mainloop()




\$\endgroup\$
  • 1
    \$\begingroup\$ Hello, it'd be useful if you could explain in more detail what your code is supposed to do. \$\endgroup\$ – IEatBagels Aug 22 at 19:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.