text: # -*- coding: utf-8 -*-
  
  # Removes too shallow soundings from the point data
  # Fairway areas must be mechanically swept to make sure not hard targets are removed from the data!
  # Other restrictions for possible use cases exist, use good judgement!
  # Experimental, use at your own risk
  
  # Load packages (install first):
  from shapely.geometry import Point
  import geopandas as gpd
  import Tkinter as Tk  # File IO-dialog
  from tkFileDialog import askopenfilename  # File IO-dialog
  
  
  # Function for fairway areas shapefile input:
  def input_fairwayareas_path():
      Tk.Tk().withdraw()  # Keep the root window from appearing
      filetype = [('ESRI Shapefile', '.shp')]
      info = 'Select fairway areas shapefile:'
      try:
          filepath = askopenfilename(filetypes=filetype, initialdir='C:\Users', title=info)  # show an 'Open' dialog box and return the path to the selected file
      except Exception:
          filepath = None
      return filepath
  
  
  # Function for points file input:
  def input_points():
      Tk.Tk().withdraw()
      filetype = [('Ascii XYZ', '.xyz')]
      info = 'Select XYZ points file:'
      try:
          filepath = askopenfilename(filetypes=filetype, initialdir='C:\Users', title=info)  # show an 'Open' dialog box and return the path to the selected file
      except Exception:
          filepath = None
      return filepath
  
  
  # Function for output (point-) file paths parsing:
  def parse_outputfilepaths(input_path):
      corrected_points_path = input_path.split(".")[0] + "_corrected.xyz"
      tracking_list_path = input_path.split(".")[0] + "_tracking_list.xyz"
      return corrected_points_path, tracking_list_path
  
  
  # Function for EPSG CRS code input:
  def epsg_input():
      print 'Enter EPSG code for point data CRS:'
      while True:
          epsg = raw_input('')
          if (epsg == ''):
              print 'No EPSG code defined. Exiting.'
              exit()
          try:
              epsg = int(epsg)
              break
          except Exception:
              print "Illegal argument. Enter an (integer type) EPSG code."
      return epsg
  
  
  # Function to read in fairwayareas:
  def read_fairways(path):
      try:
          fairway = gpd.read_file(path)  # NOTICE: CRS must match ASCII points CRS for intersection to work properly!
          deepsweep = max(fairway["SDEPFWYARE"])  # Get deepest swept depth
          epsg = fairway.crs  # Get dataset CRS as EPSG code
      except Exception:
          print "Error reading fairway shapefile. Exiting."
          exit()
  
      return fairway, deepsweep, epsg
  
  
  # Function to reproject vector data to given CRS:
  def reproject_data(data, point_epsg):
      try:
          print "\nReprojecting data to: ", point_epsg
          data = data.to_crs(epsg=point_epsg)
          print "Reprojection OK."
      except Exception:
          print "Error: Reprojection failed."
          exit()
  
  
  # Function to erase new files that include errors:
  def deleteContent(cleanfile):
      cleanfile.seek(0)
      cleanfile.truncate()
  
  
  # Function to check the correction outcome and erase files and exit if errors were found
  def check_correction(loop, corrected, tracklist, points):
      if (loop is False):  # Was looping not clean, came up with errors?
          print "Something went wrong. Emptying new files and exiting."
          deleteContent(corrected)
          deleteContent(tracklist)
          exit()
  
  
  # Point iterator function:
  def iterate_points(points, fairwayareas, deepest_sweep, corrected_out, tracklist_out):
      try:
          print "\nIterating over points file.. (please be patient as this might take a while)"
          for p in points:
              point_coordinates = p.split(" ")
              if (abs(float(point_coordinates[2])) >= deepest_sweep):
                  corrected_out.write(p)  # Point depth >= deepest sweep, can be written right away to make processing faster
              else:
                  writerFunction(fairwayareas, p, point_coordinates, corrected_out, tracklist_out)  # Point directed to further processing
          return True
  
      except Exception:
          return False
  
  
  # Function to check, correct and write points:
  def writerFunction(fairway, p, point_coordinates, corrected_out, tracklist_out):
      try:
          var_point = Point(float(point_coordinates[0]), float(point_coordinates[1]))
          var_depth = abs(float(point_coordinates[2]))
  
          for i in range(len(fairway)):   # Loop trough fairway areas
              sweep_depth = fairway.loc[i]["SDEPFWYARE"]
              sweep_geometry = fairway.loc[i]["geometry"]
  
              if (sweep_geometry.intersects(var_point)):  # Point on fairway area?
                  if (var_depth < sweep_depth):   # Depth shallower than swept depth?
  
                      tracklist_out.write(p)  # Original points are stored on a tracking list
                      point_coordinates[2] = str(0.0 - sweep_depth)  # Set point depth to swept depth
                      row = point_coordinates[0] + " " + point_coordinates[1] + " " + point_coordinates[2] + "\n"  # Define row (single point in XYZ)
                      corrected_out.write(row)    # Write corrected point
                      print("Conflicting point detected: Point Z = " + str(var_depth) + ", swept depth = " + str(sweep_depth))
                      return  # Point written, return
  
                  else:
                      corrected_out.write(p)  # Point OK --> write
                      return  # Point written, return
  
          corrected_out.write(p)  # Point not on fairways --> OK --> write
          return  # Point written, return
  
      except Exception:  # Error protection
          print "Error: error writing points to a file. Exiting."
          exit()
  
  
  # # # # # # # #
  # Main method #
  # # # # # # # #
  
  # Get points file, parse output filepaths:
  points_fp = input_points()  # Get original points filepath
  corrected_fp, tracklist_fp = parse_outputfilepaths(points_fp)  # Parse output filepaths
  point_crs = epsg_input()  # Get point data EPSG
  
  # Read in fairways in ESRI shapefile format:
  fairway_fp = input_fairwayareas_path()  # Get path
  fairways, deepest_sweep, fairway_epsg = read_fairways(fairway_fp)  # Get file pointer, deepest swepth depth and EPSG code
  
  # Reproject fairway areas to match points CRS:
  reproject_data(fairways, point_crs)
  
  
  # Open files (also takes care of closing the files in all cases):
  with open(points_fp, "r") as points, \
          open(corrected_fp, "a") as corrected_out, \
          open(tracklist_fp, "a") as tracklist_out:
  
      # Correct the points, write output files and check if everything went ok:
      correction_successful = iterate_points(points, fairways, deepest_sweep, corrected_out, tracklist_out)
      check_correction(correction_successful, corrected_out, tracklist_out, points)  # If errors were found, output files will be empty
  
      # In case of success:
      print "\nSweeping successful! Check new files: "
      print corrected_fp
      print tracklist_fp, "\n"
  