#!/Users/lances/anaconda2/bin//python
##########################################################################################
#! /usr/bin/env python
#NAME:
#  GetElevation.py
#PURPOSE:
#  To get the elevation profile from a waypoint xml file
#
#INPUTS:
#  [ARG1] = FileName: str 
#
#KEYWORDS:
#  Device: str
#    This string can either be 
#      1) Garmin
#      2) Magellan
#    based upon what device the waypoints were recorded with
#  Offset: int
#    The offset from the edges of the x range of the final elevation vs. distance plot
#  SavRange: int
#    The width of the Savgol filter used
#  SavDegree: int
#    The degree of the polynomial used in the Savgol filter
#  MinElevation: int
#    The minimum elevation to consider.  Elevations lower than this will be discarded
#
#EXAMPLES:
#  Canyon of the Muro Blanco -----
#  run GetElevation.py GPSMaps/CanyonOfTheMuroBlanco_9_10RealWpt.xml --Device='Magellan' --Offset=0 --SavDegree=5 --SavRange=2
#  Wawona Loop -------------------
#  run GetElevation.py GPSMaps/WawonaLoop06_Edited.xml --Device='Garmin' --Offset=0 --SavDegree=5 --SavRange=2
#  Enchanted Gorge ---------------
#  run GetElevation.py GPSMaps/ECHTDGORGE-9-07.xml --Device='Garmin' --Offset=0 --SavDegree=4 --SavRange=2#  
#  Cerro Del Plomo----------------
#  run GetElevation.py GPSMaps/CerroDelPlomo_3_10.xml --Device='Magellan' --Offset=0 --SavDegree=4 --SavRange=2 
#  Happy Isles to Tuolumne Meadows 08---------------
#  run GetElevation.py GPSMaps/MercedLakeToTuolomne.xml --Device='Magellan'
#  Happy Isles to Tuolumne Meadows 09 (completed)--------------
#  run GetElevation.py GPSMaps/HappyIslesToTuolomne_4_09.GPX --Device='Garmin' --Offset=0 --SavDegree=4 --SavRange=2
#  Copper Creek Trail--------------
#  run GetElevation.py GPSMaps/CopperCreekTrail_7_10Wpt.GPX --Device='Garmin' --Offset=0 --SavDegree=4 --SavRange=2
#  High Sierra Trail---------------
#  run GetElevation.py GPSMaps/SequoiaHighSierraTrail_9_09_Wpt_w_Alt.GPX --Device='Garmin' --Offset=0 --SavDegree=4 --SavRange=2
#  Anza Borrego -------------------
#  run GetElevation.py GPSMaps/AnzaBorregoTrack.GPX --Device='Garmin' --Offset=0 --SavDegree=4 --SavRange=2
#  Mineral King -------------------
#  run GetElevation.py GPSMaps/MINERAL-KING-07-25-08.xml --Device='Magellan' --Offset=0 --SavDegree=4 --SavRange=2
#  Death Valley -------------------
#  run GetElevation.py GPSMaps/DeathValley_CottonwoodCanyon_12_10RealWpt.GPX --Device='Garmin' --Offset=0 --SavDegree=4 --SavRange=2
#  Isle Royale
#  run GetElevation.py GPSMaps/IsleRoyalRouteElevationOnly.xml --Device='Magellan' --Offset=0 --SavDegree=4 --SavRange=2
#  Ranger Lake
#  run GetElevation.py GPSMaps/RangerLake_9_10RealWpt.xml --Device='Magellan' --Offset=0 --SavDegree=4 --SavRange=2
#  Starr King Meadow
#  run GetElevation.py GPSMaps/StarrKingMeadow_4_11_Total.GPX --Device='Magellan' --Offset=0 --SavDegree=4 --SavRange=2
#  Skyline to the Sea
#  run GetElevation.py GPSMaps/SkylineToTheSea_8_11_RealWpt.GPX --Device='Magellan' --Offset=0 --SavDegree=4 --SavRange=2
#  Kaweah Basin
#  run GetElevation.py GPSMaps/KawaehBasin_9_11.GPX --Device='Garmin' --Offset=0 --SavDegree=4 --SavRange=2  
#  Nine Lakes Basin
#  run GetElevation.py GPSMaps/NineLakesBasin_9_11_RealWpt.GPX --Device='Garmin' --Offset=0 --SavDegree=4 --SavRange=2
#  Joshua Tree
#  run GetElevation.py GPSMaps/JoshuaTree_2_12_RealWpt.GPX --Device='Garmin' --Offset=0 --SavDegree=4 --SavRange=2
#  Denali National Park (Before Trip)
#  run GetElevation.py GPSMaps/Denali_SanctuaryRiver_9_12.GPX --Device='Garmin' --Offset=0 --SavDegree=4 --SavRange=2
#  run GetElevation.py GPSMaps/Denali_SavageToSanctuaryRiver_9_12.xml --Device='Garmin' --Offset=0 --SavDegree=4 --SavRange=2
#  run GetElevation.py GPSMaps/Denali_SavageToSanctuaryRiver_9_12_RealWpt.xml --Device='Garmin' --Offset=0 --SavDegree=4 --SavRange=2
#  run GetElevation.py GPSMaps/Yosemite_ObeliskLake_4_13_Planned.GPX --Device='Garmin' --Offset=0 --SavDegree=4 --SavRange=2 !! DOESN"T WORK YET
#  run GetElevation.py GPSMaps/LaVerkinCreek_10_13.GPX --Device='Garmin' --Offset=0 --SavDegree=4 --SavRange=2 
#  run GetElevation.py GPSMaps/HohRiverTrail_08_14_Completed.xml.GPX --Device='Garmin' --Offset=0 --SavDegree=4 --SavRange=2
#  run GetElevation.py GPSMaps/AdairLake_10_14_Cmp.xml --Device='Garmin' --Offset=0 --SavDegree=4 --SavRange=2
#  run GetElevation.py GPSMaps/ObeliskLake_09_15_Cmp.xml --Device='Garmin' --Offset=0 --SavDegree=4 --SavRange=2
#  run GetElevation.py GPSMaps/MammothCaveNationalPark_10_22_15RealWpt.xml --Device='Garmin' --Offset=0 --SavDegree=4 --SavRange=2
#  run GetElevation.py GPSMaps/BrionesRegionalPark_2016_03_26.GPX --Device='Garmin' --Offset=0 --SavDegree=4 --SavRange=2
#  run GetElevation.py GPSMaps/MtAssiniboineLoop_09_03_16.GPX --Device='Garmin' --Offset=0 --SavDegree=4 --SavRange=2
#  run GetElevation.py GPSMaps/IcebergCircuit_11_10_17.GPX --Device='Garmin' --Offset=0 --SavDegree=4 --SavRange=2
#  run GetElevation.py GPSMaps/PalisadeBasinBackpackingGPS_Waypoints.xml --Device='Garmin' --Offset=0 --SavDegree=4 --SavRange=2
#  
##########################################################################################
import sys
import os
import scipy
from numpy import *
from sg_filter import *
import matplotlib.pylab as mplot
import getopt

#Variables for determining the smooth plot
##PARSE KEYWORDS
keywords    = ['Device=','Offset=','SavRange=','SavDegree=', 'MinElevation=']

#DEFAULT VALUES FOR KEYWORDS
Device           = 'Garmin'
Offset           = 4 
SavRange         = 5  
SavDegree        = 4  
MinElevation     = 200  
MinPlotElevation = 6000
 
#NOW PARSE KEYWORDS
opts, extraparams = getopt.getopt(sys.argv[2:],'',keywords)
for o,p in opts:
  if o in ['--Device']:
    Device = p
  elif o in ['--SavRange']:
    SavRange  = int(p)
  elif o in ['--SavDegree']:
    SavDegree = int(p)
  elif o in ['--Offset']:
    Offset    = int(p)
  elif o in ['--MinPlotElevation']:
    MinPlotElevation = int(p)

#Declare the arrays to hold the quanitites
ElArr    = []
LatArr   = []
LonArr   = []
DisArr   = [0]
Distance = 0
DisInt   = 0
#Get the file from the command line
FileName = sys.argv[1]
print 'Extracting Data for : ' + FileName
#FileName = '/Users/lances/Desktop/Software/Python/GPS/GPSMaps/'+FileName
F = open(FileName,'r')

#Go through all lines and fill the arrays
if Device == 'Magellan':
  for line in F:
    if line.find('ele') != -1:
      print line[line.find('<ele>')+5:line.find('</ele>')-1]
      ThisEl = float(line[line.find('<ele>')+5:line.find('</ele>')-1])
      ElArr.append(3.26*ThisEl)
    if line.find(' lat=') !=-1:
      print line[line.find('lat')+5:line.find('lat')+14]
      ThisLat = float(line[line.find('lat')+5:line.find('lat')+14])
      LatArr.append(ThisLat)
    if line.find(' lon=') !=-1:
      print line[line.find('lon')+5:line.find('lon')+14]
      ThisLon = float(line[line.find('lon')+5:line.find('lon')+14])
      LonArr.append(ThisLon)
 
elif Device == 'Garmin':
  for line in F:
    if line.find('name') != -1:
      print line
    if line.find('ele') != -1:
      print line[line.find('ele')+4:line.find('ele')+10]
      ThisEl = float(line[line.find('ele')+4:line.find('ele')+10])
      ElArr.append(ThisEl)
    if line.find(' lat=') !=-1:
      print line[line.find('lat')+5:line.find('lat')+15]
      ThisLat = float(line[line.find('lat')+5:line.find('lat')+15])
      LatArr.append(ThisLat)
    if line.find(' lon=') !=-1:
      print line[line.find('lon')+5:line.find('lon')+16]
      ThisLon = float(line[line.find('lon')+5:line.find('lon')+16])
      LonArr.append(ThisLon)

#Keep track of elevation
ThisClimb   = 0
ThisDescent = 0 
for i in (arange(len(LonArr)-1)+1): 
  #Calculate the distances
  ThisDelLat = (LatArr[i]-LatArr[i-1])*69.047
  ThisDelLon = (LonArr[i]-LonArr[i-1])*69.047*cos(LonArr[i])
  ThisDis    = sqrt(ThisDelLat**2+ThisDelLon**2)
  Distance   = Distance+ThisDis
  DisArr.append(Distance)
  #Tabulate elevation change
  DelEl = ElArr[i]-ElArr[i-1]
  if DelEl <= 0 : ThisDescent = ThisDescent+DelEl
  if DelEl >  0 : ThisClimb   = ThisClimb+DelEl

#Try to smooth the elevation profile a bit
#Form the Coefficients for the Savgol filter
coeff = calc_coeff(SavRange,SavDegree)
Smooth_Elevation=smooth(ElArr, coeff)

#Keep track of elevation
ThisClimbSmooth   = 0
ThisDescentSmooth = 0
#Get the elevation
for i in arange(len(Smooth_Elevation)-1)+1:

  if (Smooth_Elevation[i] > MinElevation) and (Smooth_Elevation[i-1] > MinElevation) :
    #Tabulate elevation change
    DelEl = Smooth_Elevation[i]-Smooth_Elevation[i-1]
    if DelEl <= 0 : ThisDescentSmooth = ThisDescentSmooth+DelEl
    if DelEl >  0 : ThisClimbSmooth   = ThisClimbSmooth+DelEl

#Now plot
ImFig=mplot.figure(0, figsize=[8,5.0])
mplot.clf()
FirstAx=ImFig.add_axes([0.12, 0.12, .650, 0.81])
mplot.plot(DisArr, ElArr, 'go')
mplot.plot(DisArr[Offset:(size(DisArr)-Offset)], Smooth_Elevation[Offset:(size(DisArr)-Offset)])
mplot.xlabel('Distance (Miles)')
mplot.ylabel('Elevation (feet)')

#Write the text on the plot
mplot.figtext(0.80, 0.90, 'Max Elevation:')
mplot.figtext(0.80, 0.83, str(max(ElArr)))
mplot.figtext(0.80, 0.74, 'Min Elevation:')
mplot.figtext(0.80, 0.67, str(min(ElArr)))
mplot.figtext(0.80, 0.58, 'Total Climb:')
mplot.figtext(0.80, 0.51, "%.2f" % (ThisClimbSmooth))
mplot.figtext(0.80, 0.42, 'Total Descent:')
mplot.figtext(0.80, 0.35, "%.2f" % (ThisDescentSmooth))
mplot.figtext(0.80, 0.26, 'Total Mileage:')
mplot.figtext(0.80, 0.20, "%.2f" % (DisArr[size(DisArr)-1]))


#Save the file with a different name
if FileName.find('.xml') != -1:
  FileBase = FileName[0:FileName.find('.xml')]
else:
  FileBase = FileName[0:FileName.find('.GPX')]
FileBase = FileBase+'_ElevationProfile.png'
mplot.savefig(FileBase)
print 'Max Elevation  : ' + str(max(ElArr))
print 'Min Elevation  : ' + str(min(ElArr))
print 'Total Climb    : ' + str(ThisClimb)
print 'Total Descent  : ' + str(ThisDescent)
print 'Total SClimb   : ' + str(ThisClimbSmooth)
print 'Total SDescent : ' + str(ThisDescentSmooth)

