Closed KoprivcLuka closed 10 months ago
Thanks, @KoprivcLuka. Since you are now fresh with this issue, can you please look at the algorithm and try to find a part of the algorithm that may raise this issue? Algorithms are straightforward for now, but control parameters may have an influence.
I also include @luckyLukac and @alenrajsp to check this issue and find a solution.
After analyzing the algorithm I think I've found the issue. In the method, once a hill is identified, the I index is not set and double checks the data. I've implemented an exampled of a quick and dirty fix locally which seems to work
def identify_hills(self) -> None:
"""
Method for identifying hills and extracting
total ascent and descent from data.\n
Note:
[WIP]
Algorithm is still in its preliminary stage.
"""
differences = []
for i in range(1, len(self.altitudes)):
if not type(self.altitudes[i]) is float and type(self.altitudes[i]) is float:
continue
differences.append(self.altitudes[i] - self.altitudes[i - 1])
self.total_ascent = sum(x for x in differences if x > 0)
self.total_descent = sum(-x for x in differences if x < 0)
hill_segment = []
hill_segment_ascent = 0.0
i = 0
while i < len(differences): # Replaced this with a while loop
total_ascent = 0.0
selected_IDs = []
selected_IDs.append(i)
descent_counter = 0
for j in range(i + 1, len(differences)):
NEXT = differences[j]
if NEXT >= 0.0:
total_ascent = total_ascent + NEXT
selected_IDs.append(j)
else:
if len(selected_IDs) == 1:
break
else:
selected_IDs.append(j)
descent_counter = descent_counter + 1
if descent_counter == 10:
selected_IDs = selected_IDs[
: len(selected_IDs) - descent_counter
]
break
if self.return_hill(total_ascent):
if len(hill_segment) < 3: # Nothing happens...
hill_segment = selected_IDs
hill_segment_ascent = total_ascent
else:
length_of_intersection = len(
set(hill_segment).intersection(selected_IDs)
)
calculation = float(
float(length_of_intersection)
/ float(len(hill_segment))
)
if calculation < 0.1: # if less than 10% of nodes repeat
avg_grade = None
is_a_list = isinstance(self.distances, numpy.ndarray) or isinstance(self.distances, list)
hill_segment_grade = None
if is_a_list and len(self.distances) == len(self.altitudes):
end_distance = self.distances[hill_segment[-1]]
start_distance = self.distances[hill_segment[0]]
hill_segment_distance = end_distance - start_distance
hill_segment_grade = self.__calculate_hill_grade(hill_segment_distance, hill_segment_ascent)
self.identified_hills.append(
StoredSegments(hill_segment, hill_segment_ascent, hill_segment_grade)
)
i = hill_segment[-1] # Set i to last segment
hill_segment = []
hill_segment_ascent = 0.0
i = i + 1 # Increment i as it is now in a while loop
After visualizing the new hills, overlaying hills (red section is old algorithm) no longer exist. However, out of 22 identified hills, 1 no longer qualifies as one due to a height difference bellow threshold.
At this point I would also suggest the descent / end of hill part be looked at. I believe the algorithm would work better if instead of looking at amount of points - which are not really good data as they can be very far or very close, depending on recorded data - it would be based on elevation instead (let's assume elevation data is accurate 😄 ) - If I put this in a sentence - "My hills is a hill as long as I haven't lost more than xy elevation during a climb at once.". This should result in what I believe cyclist consider a realistic hill climb. As is, under correct conditions, a short plateau can break a climb, like pictured bellow
@KoprivcLuka, thanks. I agree with you. Please make corrections and submit a PR. I will then release a new version.
Thanks for all the hard work!
@KoprivcLuka, if I remember correctly, you have already improved the hill detection algorithm currently residing within this package. Can you pull request changes? Are there any specific challenges?
@firefly-cpp I've only made the quick changes described above. I haven't had time to work on this more, as I'm VERY busy working on my project and have sort of pivoted away from hills for now and am trying to scale my algorithms to work on entire activities. I'll hopefully email you this month for a check-up :)
@KoprivcLuka, thanks for the update. Anyway, please incorporate even minor changes in the current project since the existing algorithms for hill detection are essential, and enhancement may help improve it.
It would appear detected hills can overlap. After creation of visuals of hill climbs using the algorithm, I've noticed weird behavior when processing the data further - my bug seems to appear from hills being allowed to overlap, which I don't know if is the desired behavior. Here is the issue visualized in google earth - There are actually 4 dots in the picture Here are the two hills on top of each other This is an outtake of my exported and processed XML file The problem isn't export related as I can see the values in my debugger. I'm attaching the problematic file bellow
02_25_2019_10_51_26_trackMap.zip