here's my script

import tkinter as tk
from tkinter import filedialog
import pandas as pd
import geopandas as gpd
from shapely.geometry import Point, LineString
import os
import sys

def select_files():
    root = tk.Tk()
    root.withdraw()
    file_paths = filedialog.askopenfilenames(title="Select CSV/TXT files", filetypes=[("CSV/TXT files", ".csv .txt")])
    return file_paths

def merge_files(file_paths):
    dfs = []
    for file_path in file_paths:
        df = pd.read_csv(file_path)
        dfs.append(df)
    merged_df = pd.concat(dfs, ignore_index=True)
    return merged_df

def convert_to_geodf(df, x_col, y_col):
    geometry = df.apply(lambda row: Point(row[x_col], row[y_col]), axis=1)
    geodf = gpd.GeoDataFrame(df, geometry=geometry)
    return geodf

def save_as_shapefile(geodf, output_path):
    geodf.to_file(output_path)

def get_input(prompt, default=None, cast_type=str):
    while True:
        if default is not None:
            user_input = input(f"{prompt} [{default}]: ")
            if user_input == "":
                user_input = default
        else:
            user_input = input(f"{prompt}: ")
        try:
            return cast_type(user_input)
        except ValueError:
            print(f"Invalid input. Please enter a value of type {cast_type.__name__}.")

def main():
    while True:
        print("=== Points to Paths Conversion ===\n")
        print("1. Select shape file")
        print("2. Select multiple CSV/TXT files")
        choice = input("Enter your choice: ")
        if choice == "1":
            input_shapefile = input("Enter the path to your input points shapefile (.shp): ").strip('"').strip("'")
            if not os.path.isfile(input_shapefile):
                print("Error: The specified shapefile does not exist.")
                continue

            try:
                gdf = gpd.read_file(input_shapefile)
            except Exception as e:
                print(f"Error loading shapefile: {e}")
                continue

            fields = list(gdf.columns)
            print("\nAvailable Fields:")
            for i, field in enumerate(fields, 1):
                print(f"{i}. {field}")

            time_field = get_input("\nEnter the name of the Time field from the above list", default="Time")
            while time_field not in fields:
                print("Error: Field not found. Please enter a valid field name.")
                time_field = get_input("\nEnter the name of the Time field from the above list", default="Time")

            if not pd.api.types.is_numeric_dtype(gdf[time_field]):
                print(f"Error: The field '{time_field}' is not numeric. Please choose a numeric field.")
                continue

            gap_threshold = get_input("\nEnter the gap threshold (same units as Time)", default=5.0, cast_type=float)

            default_group_field = "PathID"
            group_field = input(f"\nEnter the name for the group field [default: {default_group_field}]: ").strip()
            if group_field == "":
                group_field = default_group_field

            if group_field not in gdf.columns:
                gdf[group_field] = 0

            gdf_sorted = gdf.sort_values(by=time_field).reset_index(drop=True)

            current_group = 1
            previous_time = None
            path_ids = []
            gaps = []  # To store gaps information

            for idx, row in gdf_sorted.iterrows():
                current_time = row[time_field]
                if pd.isna(current_time):
                    print(f"Warning: NaN value encountered in Time field at index {idx}. Assigning to current group.")
                    path_ids.append(current_group)
                    continue
                if previous_time is not None:
                    gap = current_time - previous_time
                    gaps.append({
                        "Entry_Index": idx-1,
                        "Previous_Time": previous_time,
                        "Current_Time": current_time,
                        "Gap": gap
                    })
                    if gap > gap_threshold:
                        print(f"Gap detected between index {idx-1} and {idx}: Gap = {gap} exceeds threshold of {gap_threshold}. Creating a new PathID.")
                        current_group += 1
                path_ids.append(current_group)
                previous_time = current_time

            gdf_sorted[group_field] = path_ids

            gaps_df = pd.DataFrame(gaps)

            save_gaps = get_input("\nDo you want to save the gaps report to a CSV file? (y/n)", default="n").lower()
            if save_gaps == 'y':
                gaps_output = input("Enter the path for the gaps report CSV file (e.g., gaps_report.csv): ").strip('"').strip("'")
                gaps_df.to_csv(gaps_output, index=False)
                print(f"Gaps report saved to '{gaps_output}'.")

            output_shapefile = input("\nEnter the path for the output paths shapefile (.shp): ").strip('"').strip("'")
            output_dir = os.path.dirname(output_shapefile)
            if output_dir and not os.path.exists(output_dir):
                os.makedirs(output_dir)

            if not output_shapefile.lower().endswith('.shp'):
                output_shapefile += '.shp'

            try:
                valid_groups = gdf_sorted.groupby(group_field).filter(lambda x: len(x) > 1)

                if valid_groups.empty:
                    print("Error: No groups contain more than one point. Cannot create LineStrings.")
                    continue

                paths = valid_groups.groupby(group_field)['geometry'].apply(lambda x: LineString(x.tolist())).reset_index()
                paths.rename(columns={0: 'geometry'}, inplace=True)

                paths_gdf = gpd.GeoDataFrame(paths, geometry='geometry')

                paths_gdf.set_crs(gdf_sorted.crs, inplace=True)

                if not gdf_sorted.crs.is_projected:
                    print("\nWarning: The input CRS is not projected. Reprojecting to EPSG:3857 for distance calculations.")
                    paths_gdf = paths_gdf.to_crs(epsg=3857)

                paths_gdf['Length_km'] = paths_gdf.length / 1000  

                total_distance_km = paths_gdf['Length_km'].sum()
                print(f"\nTotal Distance of All Paths: {total_distance_km:.3f} kilometers.")

                save_lengths = get_input("\nDo you want to save the paths with length information? (y/n)", default="n").lower()
                if save_lengths == 'y':
                    paths_with_lengths = paths_gdf.copy()
                    if not gdf_sorted.crs.is_projected:
                        paths_with_lengths = paths_with_lengths.to_crs(gdf_sorted.crs)
                    paths_with_lengths.to_file(output_shapefile)
                    print(f"\nSuccess: Paths with length information have been saved to '{output_shapefile}'.")
                else:
                    paths_gdf.drop(columns=['Length_km']).to_file(output_shapefile)
                    print(f"\nSuccess: Paths have been saved to '{output_shapefile}'.")

                generate_summary = get_input("\nDo you want to generate a summary report of the paths? (y/n)", default="n").lower()
                if generate_summary == 'y':
                    summary = paths_gdf.copy()
                    summary['Start_Time'] = gdf_sorted.groupby(group_field)[time_field].transform('min')
                    summary['End_Time'] = gdf_sorted.groupby(group_field)[time_field].transform('max')
                    summary_summary = summary[['PathID', 'Length_km', 'Start_Time', 'End_Time']].drop_duplicates()
                    summary_output = os.path.splitext(output_shapefile)[0] + "_summary.csv"
                    summary_summary.to_csv(summary_output, index=False)
                    print(f"Summary report saved to '{summary_output}'.")

            except Exception as e:
                print(f"Error generating paths: {e}")
                continue

            cont = input("\nDo you want to continue? (y/n): ")
            if cont.lower() != 'y':
                break

        elif choice == "2":
            file_paths = select_files()
            dfs = []
            for file_path in file_paths:
                df = pd.read_csv(file_path)
                print("Columns in the file:")
                for i, col in enumerate(df.columns):
                    print(f"{i+1}. {col}")
                remove_cols = input("Enter the numbers of columns you want to remove (separated by spaces), or press Enter to keep all columns: ")
                if remove_cols:
                    remove_cols = [int(x) - 1 for x in remove_cols.split()]
                    df = df.drop(df.columns[remove_cols], axis=1)
                dfs.append(df)
            merged_df = pd.concat(dfs, ignore_index=True)
            x_col = input("Enter the column name for X coordinate (default is 'X'): ") or 'X'
            y_col = input("Enter the column name for Y coordinate (default is 'Y'): ") or 'Y'
            geodf = convert_to_geodf(merged_df, x_col, y_col)
            output_path = input("Enter the output path for the shape file: ")
            save_as_shapefile(geodf, output_path)
        else:
            print("Invalid choice. Please try again.")

if __name__ == "__main__":
    main()


and i get this errors:

Traceback (most recent call last):
  File "C:\Users\SPL\scoop\apps\python\current\Lib\site-packages\pandas\core\indexes\base.py", line 3805, in get_loc
    return self._engine.get_loc(casted_key)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "index.pyx", line 167, in pandas._libs.index.IndexEngine.get_loc
  File "index.pyx", line 196, in pandas._libs.index.IndexEngine.get_loc
  File "pandas\\_libs\\hashtable_class_helper.pxi", line 7081, in pandas._libs.hashtable.PyObjectHashTable.get_item
  File "pandas\\_libs\\hashtable_class_helper.pxi", line 7089, in pandas._libs.hashtable.PyObjectHashTable.get_item
KeyError: 'x'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "C:\Users\SPL\Documents\points_to_paths_0.0.10.py", line 206, in <module>
    main()
  File "C:\Users\SPL\Documents\points_to_paths_0.0.10.py", line 199, in main
    geodf = convert_to_geodf(merged_df, x_col, y_col)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\SPL\Documents\points_to_paths_0.0.10.py", line 24, in convert_to_geodf
    geometry = df.apply(lambda row: Point(row[x_col], row[y_col]), axis=1)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\SPL\scoop\apps\python\current\Lib\site-packages\pandas\core\frame.py", line 10374, in apply
    return op.apply().__finalize__(self, method="apply")
           ^^^^^^^^^^
  File "C:\Users\SPL\scoop\apps\python\current\Lib\site-packages\pandas\core\apply.py", line 916, in apply
    return self.apply_standard()
           ^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\SPL\scoop\apps\python\current\Lib\site-packages\pandas\core\apply.py", line 1063, in apply_standard
    results, res_index = self.apply_series_generator()
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\SPL\scoop\apps\python\current\Lib\site-packages\pandas\core\apply.py", line 1081, in apply_series_generator
    results[i] = self.func(v, *self.args, **self.kwargs)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\SPL\Documents\points_to_paths_0.0.10.py", line 24, in <lambda>
    geometry = df.apply(lambda row: Point(row[x_col], row[y_col]), axis=1)
                                          ~~~^^^^^^^
  File "C:\Users\SPL\scoop\apps\python\current\Lib\site-packages\pandas\core\series.py", line 1121, in __getitem__
    return self._get_value(key)
           ^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\SPL\scoop\apps\python\current\Lib\site-packages\pandas\core\series.py", line 1237, in _get_value
    loc = self.index.get_loc(label)
          ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\SPL\scoop\apps\python\current\Lib\site-packages\pandas\core\indexes\base.py", line 3812, in get_loc
    raise KeyError(key) from err
KeyError: 'x'