Repository: mie-lab/trackintel

Issue:
generate_staypoints produce stps with duration smaller than time_threshold
Some of the `stps` generated by the function have very short durations (even 0). The problem is in file `trackintel\trackintel\preprocessing\positionfixes.py`

I am not very sure the cause, but it seems `delta_t` and the `if` statement in Line 308 is correct, but in Line 319 `staypoint['finished_at'] = pfs[j - 1]['tracked_at']` the `j-1` is different than `j` used elsewhere.

Discussion:
codecov[bot]: # [Codecov](https://codecov.io/gh/mie-lab/trackintel/pull/194?src=pr&el=h1) Report
> Merging [#194](https://codecov.io/gh/mie-lab/trackintel/pull/194?src=pr&el=desc) (675c639) into [master](https://codecov.io/gh/mie-lab/trackintel/commit/481aaf8a583b00da5ca4741d09825bcb8c3267ae?el=desc) (481aaf8) will **decrease** coverage by `0.22%`.
> The diff coverage is `92.77%`.

[![Impacted file tree graph](https://codecov.io/gh/mie-lab/trackintel/pull/194/graphs/tree.svg?width=650&height=150&src=pr&token=ITDZEEE1MO)](https://codecov.io/gh/mie-lab/trackintel/pull/194?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master     #194      +/-   ##
==========================================
- Coverage   85.92%   85.70%   -0.23%     
==========================================
  Files          36       36              
  Lines        1485     1483       -2     
  Branches      260      258       -2     
==========================================
- Hits         1276     1271       -5     
- Misses        159      162       +3     
  Partials       50       50              
```


| [Impacted Files](https://codecov.io/gh/mie-lab/trackintel/pull/194?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [trackintel/preprocessing/positionfixes.py](https://codecov.io/gh/mie-lab/trackintel/pull/194/diff?src=pr&el=tree#diff-dHJhY2tpbnRlbC9wcmVwcm9jZXNzaW5nL3Bvc2l0aW9uZml4ZXMucHk=) | `95.91% <92.40%> (-1.40%)` | :arrow_down: |
| [trackintel/model/positionfixes.py](https://codecov.io/gh/mie-lab/trackintel/pull/194/diff?src=pr&el=tree#diff-dHJhY2tpbnRlbC9tb2RlbC9wb3NpdGlvbmZpeGVzLnB5) | `96.87% <100.00%> (ø)` | |
| [trackintel/preprocessing/triplegs.py](https://codecov.io/gh/mie-lab/trackintel/pull/194/diff?src=pr&el=tree#diff-dHJhY2tpbnRlbC9wcmVwcm9jZXNzaW5nL3RyaXBsZWdzLnB5) | `90.90% <100.00%> (-0.76%)` | :arrow_down: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/mie-lab/trackintel/pull/194?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/mie-lab/trackintel/pull/194?src=pr&el=footer). Last update [481aaf8...675c639](https://codecov.io/gh/mie-lab/trackintel/pull/194?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/docs/tutorial.rst b/docs/tutorial.rst
index 901b693..75cb40a 100644
--- a/docs/tutorial.rst
+++ b/docs/tutorial.rst
@@ -44,7 +44,7 @@ at which the user stayed for a certain amount of time)::
     from trackintel.geogr.distances import meters_to_decimal_degrees
 
     stps = pfs.as_positionfixes.extract_staypoints(method='sliding', 
-        dist_threshold=100, time_threshold=60)
+        dist_threshold=100, time_threshold=5)
     stps.as_staypoints.plot(out_filename='staypoints.png',
         radius=meters_to_decimal_degrees(100, 47.5), positionfixes=pfs, plot_osm=True)
 
diff --git a/examples/preprocess_trajectories.py b/examples/preprocess_trajectories.py
index 563da4a..b9e6521 100644
--- a/examples/preprocess_trajectories.py
+++ b/examples/preprocess_trajectories.py
@@ -16,7 +16,7 @@ logging.basicConfig(filename='examples/log/preprocessing.log', level=logging.INF
 pfs = ti.read_positionfixes_csv('examples/data/geolife_trajectory.csv', sep=';', crs='EPSG:4326', index_col=None)
 pfs.as_positionfixes.plot(out_filename='examples/out/gps_trajectory_positionfixes.png', plot_osm=True)
 
-_, spts = pfs.as_positionfixes.generate_staypoints(method='sliding', dist_threshold=100, time_threshold=5*60)
+_, spts = pfs.as_positionfixes.generate_staypoints(method='sliding', dist_threshold=100, time_threshold=5)
 spts.as_staypoints.plot(out_filename='examples/out/gps_trajectory_staypoints.png',
                         radius=100, positionfixes=pfs, plot_osm=True)
 
@@ -25,7 +25,7 @@ locs.as_locations.plot(out_filename='examples/out/gps_trajectory_locations.png',
                        positionfixes=pfs, staypoints=spts, staypoints_radius=100,
                        plot_osm=True)
 
-_, tpls = pfs.as_positionfixes.generate_triplegs(staypoints=spts)
+_, tpls = pfs.as_positionfixes.generate_triplegs(stps_input=spts)
 tpls.as_triplegs.plot(out_filename='examples/out/gpsies_trajectory_triplegs.png', staypoints=spts,
                       staypoints_radius=100, plot_osm=True)
 
@@ -33,19 +33,19 @@ tpls.as_triplegs.plot(out_filename='examples/out/gpsies_trajectory_triplegs.png'
 pfs = ti.read_positionfixes_csv('examples/data/geolife_trajectory.csv', sep=';', crs='EPSG:4326', index_col=None)
 pfs.as_positionfixes.plot(out_filename='examples/out/geolife_trajectory_positionfixes.png', plot_osm=False)
 
-_, spts = pfs.as_positionfixes.generate_staypoints(method='sliding', dist_threshold=100, time_threshold=10*60)
+_, spts = pfs.as_positionfixes.generate_staypoints(method='sliding', dist_threshold=100, time_threshold=10)
 spts.as_staypoints.plot(out_filename='examples/out/geolife_trajectory_staypoints.png',
                         radius=100, positionfixes=pfs, plot_osm=True)
 
 # Google trajectory.
 pfs = ti.read_positionfixes_csv('examples/data/google_trajectory.csv', sep=';', crs='EPSG:4326', index_col=None)
-_, spts = pfs.as_positionfixes.generate_staypoints(method='sliding', dist_threshold=75, time_threshold=10*60)
+_, spts = pfs.as_positionfixes.generate_staypoints(method='sliding', dist_threshold=75, time_threshold=10)
 spts.as_staypoints.plot(out_filename='examples/out/google_trajectory_staypoints.png',
                         radius=75, positionfixes=pfs, plot_osm=True)
 
 # Posmo trajectory.
 pfs = ti.read_positionfixes_csv('examples/data/posmo_trajectory.csv', sep=';', crs='EPSG:4326', index_col=None,
                                 tz='UTC')
-_, spts = pfs.as_positionfixes.generate_staypoints(method='sliding', dist_threshold=50, time_threshold=1*60)
+_, spts = pfs.as_positionfixes.generate_staypoints(method='sliding', dist_threshold=50, time_threshold=1)
 spts.as_staypoints.plot(out_filename='examples/out/posmo_trajectory_staypoints.png',
                         radius=50, positionfixes=pfs, plot_osm=False)
diff --git a/examples/trackintel_basic_tutorial.ipynb b/examples/trackintel_basic_tutorial.ipynb
index 44becda..5068408 100644
--- a/examples/trackintel_basic_tutorial.ipynb
+++ b/examples/trackintel_basic_tutorial.ipynb
@@ -120,7 +120,7 @@
    "metadata": {},
    "outputs": [],
    "source": [
-    "pfs, stps = pfs.as_positionfixes.generate_staypoints(method='sliding', dist_threshold=25, time_threshold=5*60)"
+    "pfs, stps = pfs.as_positionfixes.generate_staypoints(method='sliding', dist_threshold=25, time_threshold=5)"
    ]
   },
   {
diff --git a/trackintel/model/positionfixes.py b/trackintel/model/positionfixes.py
index b233e68..a892fa4 100644
--- a/trackintel/model/positionfixes.py
+++ b/trackintel/model/positionfixes.py
@@ -72,13 +72,13 @@ class PositionfixesAccessor(object):
         """
         return ti.preprocessing.positionfixes.generate_staypoints(self._obj, *args, **kwargs)
 
-    def generate_triplegs(self, staypoints=None, *args, **kwargs):
+    def generate_triplegs(self, stps_input=None, *args, **kwargs):
         """
         Generate triplegs from this collection of positionfixes.
         
         See :func:`trackintel.preprocessing.positionfixes.generate_triplegs`.
         """
-        return ti.preprocessing.positionfixes.generate_triplegs(self._obj, staypoints, *args, **kwargs)
+        return ti.preprocessing.positionfixes.generate_triplegs(self._obj, stps_input, *args, **kwargs)
     
     def plot(self, *args, **kwargs):
         """
diff --git a/trackintel/preprocessing/positionfixes.py b/trackintel/preprocessing/positionfixes.py
index 3fe86b6..ef2f6da 100644
--- a/trackintel/preprocessing/positionfixes.py
+++ b/trackintel/preprocessing/positionfixes.py
@@ -5,56 +5,70 @@ from shapely.geometry import LineString, Point
 from sklearn.cluster import DBSCAN
 
 import datetime
-from math import radians
+from tqdm import tqdm
 
 from trackintel.geogr.distances import haversine_dist
 
 
-def generate_staypoints(positionfixes,
-                        method='sliding',
-                        dist_func=haversine_dist,
-                        dist_threshold=50,
-                        time_threshold=300,
-                        epsilon=100,
-                        num_samples=1):
+def generate_staypoints(
+    pfs_input,
+    method="sliding",
+    distance_metric="haversine",
+    dist_threshold=100,
+    time_threshold=5.0,
+    gap_threshold=1e6,
+    include_last=False,
+    print_progress=False,
+):
     """
     Generate staypoints from positionfixes.
     
     Parameters
     ----------
-    positionfixes : GeoDataFrame (as trackintel positionfixes)
+    pfs_input : GeoDataFrame (as trackintel positionfixes)
         The positionfixes have to follow the standard definition for positionfixes DataFrames.
 
-    method : {'sliding' or 'dbscan'}
-        Method to create staypoints. 
-        
-        - 'sliding' : Applies a sliding window over the data.
-        - 'dbscan' : Uses the DBSCAN algorithm to find clusters of staypoints.
+    method : {'sliding'}
+        Method to create staypoints. 'sliding' applies a sliding window over the data.
         
-    dist_func : {'haversine_dist'}
+    distance_metric : {'haversine'}
         The distance metric used by the applied method.
         
-    dist_threshold : float, default 50
+    dist_threshold : float, default 100
         The distance threshold for the 'sliding' method, i.e., how far someone has to travel to
         generate a new staypoint. Units depend on the dist_func parameter.
 
-    time_threshold : float, default 300 (seconds)
-        The time threshold for the 'sliding' method in seconds
+    time_threshold : float, default 5.0 (minutes)
+        The time threshold for the 'sliding' method in minutes.
         
-    epsilon : float, default 100
-        The epsilon for the 'dbscan' method. Units depend on the dist_func parameter.
+    gap_threshold : float, default 1e6 (minutes)
+        The time threshold of determine whether a gap exists between consecutive pfs. Staypoints 
+        will not be generated between gaps. Only valid in 'sliding' method.
         
-    num_samples : int, default 1
-        The num_samples for the 'dbscan' method. The minimal number of samples in a cluster. 
+    include_last: boolen, default False
+        The original algorithm (see Li et al. (2008)) only detects staypoint if the user steps out
+        of that staypoint. This will omit the last staypoint (if any). Set 'include_last'
+        to True to include this last staypoint.
+        
+    print_progress: boolen, default False
+        Show per-user progress if set to True.
     
     Returns
     -------
-    ret_pfs: GeoDataFrame (as trackintel positionfixes)
+    pfs: GeoDataFrame (as trackintel positionfixes)
         The original positionfixes with a new column ``[`staypoint_id`]``.
         
-    ret_spts: GeoDataFrame (as trackintel staypoints)
+    stps: GeoDataFrame (as trackintel staypoints)
         The generated staypoints.
-
+        
+    Notes
+    -----
+    The 'sliding' method is adapted from Li et al. (2008). In the original algorithm, the 'finished_at'
+    time for the current staypoint lasts until the 'tracked_at' time of the first positionfix outside 
+    this staypoint. This implies potential tracking gaps may be included in staypoints, and users 
+    are assumed to be stationary during this missing period. To avoid including too large gaps, set
+    'gap_threshold' parameter to a small value, e.g., 15 min.
+    
     Examples
     --------
     >>> pfs.as_positionfixes.generate_staypoints('sliding', dist_threshold=100)
@@ -69,88 +83,86 @@ def generate_staypoints(positionfixes,
     conference on Advances in geographic information systems (p. 34). ACM.
     """
     # copy the original pfs for adding 'staypoint_id' column
-    ret_pfs = positionfixes.copy()
+    pfs = pfs_input.copy()
 
-    elevation_flag = 'elevation' in ret_pfs.columns  # if there is elevation data
+    elevation_flag = "elevation" in pfs.columns  # if there is elevation data
 
-    name_geocol = ret_pfs.geometry.name
-    ret_spts = pd.DataFrame(columns=['id', 'user_id', 'started_at', 'finished_at', 'geom'])
+    geo_col = pfs.geometry.name
+    if elevation_flag:
+        spts_column = ["user_id", "started_at", "finished_at", "elevation", geo_col]
+    else:
+        spts_column = ["user_id", "started_at", "finished_at", geo_col]
 
     # TODO: tests using a different distance function, e.g., L2 distance
-    if method == 'sliding':
+    if method == "sliding":
         # Algorithm from Li et al. (2008). For details, please refer to the paper.
-        ret_spts = ret_pfs.groupby('user_id', as_index=False).apply(_generate_staypoints_sliding_user,
-                                                                    name_geocol,
-                                                                    elevation_flag,
-                                                                    dist_threshold,
-                                                                    time_threshold,
-                                                                    dist_func).reset_index(drop=True)
+        if print_progress:
+            tqdm.pandas(desc="User staypoint generation")
+            stps = (
+                pfs.groupby("user_id", as_index=False)
+                .progress_apply(
+                    _generate_staypoints_sliding_user,
+                    geo_col=geo_col,
+                    elevation_flag=elevation_flag,
+                    dist_threshold=dist_threshold,
+                    time_threshold=time_threshold,
+                    gap_threshold=gap_threshold,
+                    distance_metric=distance_metric,
+                    include_last=include_last,
+                )
+                .reset_index(drop=True)
+            )
+        else:
+            stps = (
+                pfs.groupby("user_id", as_index=False)
+                .apply(
+                    _generate_staypoints_sliding_user,
+                    geo_col=geo_col,
+                    elevation_flag=elevation_flag,
+                    dist_threshold=dist_threshold,
+                    time_threshold=time_threshold,
+                    gap_threshold=gap_threshold,
+                    distance_metric=distance_metric,
+                    include_last=include_last,
+                )
+                .reset_index(drop=True)
+            )
         # index management
-        ret_spts['id'] = np.arange(len(ret_spts))
-        ret_spts.set_index('id', inplace=True)
+        stps["id"] = np.arange(len(stps))
+        stps.set_index("id", inplace=True)
 
-        # Assign staypoint_id to ret_pfs if spts is detected 
-        if not ret_spts.empty:
-            stps2pfs_map = ret_spts[['pfs_id']].to_dict()['pfs_id']
+        # Assign staypoint_id to ret_pfs if spts is detected
+        if not stps.empty:
+            stps2pfs_map = stps[["pfs_id"]].to_dict()["pfs_id"]
 
             ls = []
             for key, values in stps2pfs_map.items():
                 for value in values:
                     ls.append([value, key])
-            temp = pd.DataFrame(ls, columns=['id', 'staypoint_id']).set_index('id')
+            temp = pd.DataFrame(ls, columns=["id", "staypoint_id"]).set_index("id")
             # pfs with no stps receives nan in 'staypoint_id'
-            ret_pfs = ret_pfs.join(temp, how='left')
-            ret_spts.drop(columns={'pfs_id'}, inplace=True)
-        # if no staypoint is identified
+            pfs = pfs.join(temp, how="left")
+            stps.drop(columns={"pfs_id"}, inplace=True)
+
+        # if no staypoint at all is identified
         else:
-            ret_pfs['staypoint_id'] = np.nan
-
-    # TODO: create tests for dbscan method
-    # TODO: currently only support haversine distance, provode support for other distances, 
-    # we could use the same structure as generate_location function
-    elif method == 'dbscan':
-        # TODO: Make sure time information is included in the clustering!
-        # time information is in the column 'started at', however the user should be able to
-        # adjust the distance metric e.g. chebychev
-
-        # TODO: fix bug: generated staypoints has id starting from 0 for each user
-        ret_pfs = ret_pfs.groupby("user_id").apply(_generate_staypoints_dbscan_user,
-                                                   name_geocol,
-                                                   epsilon,
-                                                   num_samples)
-
-        # TODO: staypoint 'elevation' field
-        # TODO: using dissolve for staypoint generation
-        # create staypoints as the center of the grouped positionfixes
-        grouped_df = ret_pfs.groupby(['user_id', 'staypoint_id'])
-        for combined_id, group in grouped_df:
-            user_id, staypoint_id = combined_id
-
-            if int(staypoint_id) != -1:
-                staypoint = {}
-                staypoint['user_id'] = user_id
-                staypoint['id'] = staypoint_id
-
-                # point geometry of staypoint
-                staypoint[name_geocol] = Point(group[name_geocol].x.mean(),
-                                               group[name_geocol].y.mean())
-
-                ret_spts = ret_spts.append(staypoint, ignore_index=True)
-        ret_spts.set_index('id', inplace=True)
-        
-    ret_pfs = gpd.GeoDataFrame(ret_pfs, geometry=name_geocol,crs=ret_pfs.crs)
-    ret_spts = gpd.GeoDataFrame(ret_spts, geometry=name_geocol,crs=ret_pfs.crs)
-    
-    ## dtype consistency 
+            pfs["staypoint_id"] = np.nan
+
+    pfs = gpd.GeoDataFrame(pfs, geometry=geo_col, crs=pfs.crs)
+    stps = gpd.GeoDataFrame(stps, columns=spts_column, geometry=geo_col, crs=pfs.crs)
+    # rearange column order
+    stps = stps[spts_column]
+
+    ## dtype consistency
     # stps id (generated by this function) should be int64
-    ret_spts.index = ret_spts.index.astype('int64')
+    stps.index = stps.index.astype("int64")
     # ret_pfs['staypoint_id'] should be Int64 (missing values)
-    ret_pfs['staypoint_id'] = ret_pfs['staypoint_id'].astype('Int64')
+    pfs["staypoint_id"] = pfs["staypoint_id"].astype("Int64")
 
     # user_id of spts should be the same as ret_pfs
-    ret_spts['user_id'] = ret_spts['user_id'].astype(ret_pfs['user_id'].dtype)
+    stps["user_id"] = stps["user_id"].astype(pfs["user_id"].dtype)
 
-    return ret_pfs, ret_spts
+    return pfs, stps
 
 def generate_triplegs(pfs_input, stps_input, method="between_staypoints", gap_threshold=15):
     """Generate triplegs from positionfixes.
@@ -158,21 +170,21 @@ def generate_triplegs(pfs_input, stps_input, method="between_staypoints", gap_th
     Parameters
     ----------
     pfs_input : GeoDataFrame (as trackintel positionfixes)
-        The pfs have to follow the standard definition for positionfixes DataFrames. 
+        The positionfixes have to follow the standard definition for positionfixes DataFrames. 
         If 'staypoint_id' column is not found, stps_input needs to be given.
 
     stps_input : GeoDataFrame (as trackintel staypoints), optional
-        The stps (corresponding to the positionfixes). If this is not passed, the
+        The staypoints (corresponding to the positionfixes). If this is not passed, the
         positionfixes need 'staypoint_id' associated with them.
 
     method: {'between_staypoints'}
-        Method to create triplegs. 'between_staypoints' method defines a tripleg as all pfs 
-        between two stps. This method requires either a column 'staypoint_id' on 
-        the pfs or passing stps as an input.
+        Method to create triplegs. 'between_staypoints' method defines a tripleg as all positionfixes 
+        between two staypoints (no overlap). This method requires either a column 'staypoint_id' on 
+        the positionfixes or passing staypoints as an input.
             
     gap_threshold: float, default 15 (minutes)
         Maximum allowed temporal gap size in minutes. If tracking data is missing for more than 
-        `gap_threshold` minutes, then a new tripleg will be generated.
+        `gap_threshold` minutes, a new tripleg will be generated.
 
     Returns
     -------
@@ -188,7 +200,11 @@ def generate_triplegs(pfs_input, stps_input, method="between_staypoints", gap_th
     positionfixes or passing some staypoints that correspond to the positionfixes! 
     This means you usually should call ``generate_staypoints()`` first.
     
-    The first pfs after a stp is regarded as the first pfs of the generated tpl.
+    The first positionfix after a staypoint is regarded as the first positionfix of the 
+    generated tripleg. The generated tripleg will not have overlapping positionfix with 
+    the existing staypoints. This means a small temporal gap in user's trace will occur 
+    between the first positionfix of staypoint and the last positionfix of tripleg:
+    pfs_stp_first['tracked_at'] - pfs_tpl_last['tracked_at'].
 
     Examples
     --------
@@ -223,7 +239,7 @@ def generate_triplegs(pfs_input, stps_input, method="between_staypoints", gap_th
                 # step 1
                 # All positionfixes with timestamp between staypoints are assigned the value 0
                 # Intersect all positionfixes of a user with all staypoints of the same user
-                intervals = pd.IntervalIndex.from_arrays(spts_user["started_at"], spts_user["finished_at"], closed="both")
+                intervals = pd.IntervalIndex.from_arrays(spts_user["started_at"], spts_user["finished_at"], closed="left")
                 is_in_interval = pfs_user["tracked_at"].apply(lambda x: intervals.contains(x).any()).astype("bool")
                 pfs.loc[is_in_interval[is_in_interval].index, "staypoint_id"] = 0
 
@@ -271,13 +287,45 @@ def generate_triplegs(pfs_input, stps_input, method="between_staypoints", gap_th
         cond_all = cond_new_user | cond_gap | cond_stp
         # make sure not to create triplegs within staypoints:
         cond_all = cond_all & pd.isna(pfs["staypoint_id"])
-
         cond_all.sort_index(inplace=True)
+        
         # get the start position of tpls
         tpls_starts = np.where(cond_all)[0]
+        tpls_diff = np.diff(tpls_starts)
+        
+        # get the start position of stps
+        # pd.NA causes error in boolen comparision, replace to -1
+        stps_id = pfs["staypoint_id"].copy().fillna(-1)
+        unique_stps, stps_starts = np.unique(stps_id, return_index=True)
+        # get the index of where the tpls_starts belong in stps_starts
+        stps_starts = stps_starts[unique_stps != -1]
+        tpls_place_in_stps = np.searchsorted(stps_starts, tpls_starts)
+        
+        # get the length between each stp and tpl
+        try:
+            # pfs ends with stp
+            stps_tpls_diff = stps_starts[tpls_place_in_stps] - tpls_starts
+
+            # tpls_lengths is the minimum of tpls_diff and stps_tpls_diff
+            # stps_tpls_diff one larger than tpls_diff
+            tpls_lengths = np.minimum(tpls_diff, stps_tpls_diff[:-1])
+
+            # the last tpl has length (last stp begin - last tpl begin)
+            tpls_lengths = np.append(tpls_lengths, stps_tpls_diff[-1])
+        except IndexError:
+            # pfs ends with tpl
+            # ignore the tpls after the last stps stps_tpls_diff
+            ignore_index = tpls_place_in_stps == len(stps_starts)
+            stps_tpls_diff = stps_starts[tpls_place_in_stps[~ignore_index]] - tpls_starts[~ignore_index]
+
+            # tpls_lengths is the minimum of tpls_diff and stps_tpls_diff
+            tpls_lengths = np.minimum(tpls_diff[: len(stps_tpls_diff)], stps_tpls_diff)
+            tpls_lengths = np.append(tpls_lengths, tpls_diff[len(stps_tpls_diff) :])
+
+            # add the length of the last tpl
+            tpls_lengths = np.append(tpls_lengths, len(pfs) - tpls_starts[-1])
 
         # a valid linestring needs 2 points
-        tpls_lengths = np.diff(tpls_starts)
         cond_to_remove = np.take(tpls_starts, np.where(tpls_lengths < 2)[0])
         cond_all.iloc[cond_to_remove] = False
         pfs.loc[pfs.index.isin(cond_to_remove), "tripleg_id"] = -1
@@ -325,91 +373,80 @@ def generate_triplegs(pfs_input, stps_input, method="between_staypoints", gap_th
         raise AttributeError(f"Method unknown. We only support 'between_staypoints'. You passed {method}")
 
 
-def _generate_staypoints_sliding_user(df,
-                                      name_geocol,
-                                      elevation_flag,
-                                      dist_threshold=50,
-                                      time_threshold=300,
-                                      dist_func=haversine_dist):
-    ret_spts = pd.DataFrame(columns=['user_id', 'started_at', 'finished_at', 'geom'])
-    df.sort_values('tracked_at', inplace=True)
+def _generate_staypoints_sliding_user(
+    df, geo_col, elevation_flag, dist_threshold, time_threshold, gap_threshold, distance_metric, include_last=False
+):
+    """User level staypoint geenration using sliding method, see generate_staypoints() function for parameter meaning."""
+    if distance_metric == "haversine":
+        dist_func = haversine_dist
+    else:
+        raise AttributeError("distance_metric unknown. We only support ['haversine']. " f"You passed {distance_metric}")
 
+    df.sort_values("tracked_at", inplace=True)
     # pfs id should be in index, create separate idx for storing the matching
-    pfs = df.to_dict('records')
+    pfs = df.to_dict("records")
     idx = df.index.to_list()
 
-    num_pfs = len(pfs)
+    ret_spts = []
+    start = 0
 
-    i = 0
-    j = 0  # is zero because it gets incremented in the beginning
-    while i < num_pfs:
-        if j == num_pfs:
-            # We're at the end, this can happen if in the last "bin", 
-            # the dist_threshold is never crossed anymore.
-            break
-        else:
-            j = i + 1
-
-        while j < num_pfs:
-            # TODO: Can we make distance function independent of projection?
-            dist = dist_func(pfs[i][name_geocol].x, pfs[i][name_geocol].y,
-                             pfs[j][name_geocol].x, pfs[j][name_geocol].y)
-
-            if dist > dist_threshold:
-                delta_t = pfs[j]['tracked_at'] - pfs[i]['tracked_at']
-                if delta_t.total_seconds() > time_threshold:
-                    staypoint = {}
-                    staypoint['user_id'] = pfs[i]['user_id']
-                    staypoint[name_geocol] = Point(np.mean([pfs[k][name_geocol].x for k in range(i, j)]),
-                                                   np.mean([pfs[k][name_geocol].y for k in range(i, j)]))
-                    if elevation_flag:
-                        staypoint['elevation'] = np.mean([pfs[k]['elevation'] for k in range(i, j)])
-                    staypoint['started_at'] = pfs[i]['tracked_at']
-                    staypoint['finished_at'] = pfs[j - 1]['tracked_at']
-
-                    # store matching, index should be the id of pfs
-                    staypoint['pfs_id'] = [idx[k] for k in range(i, j)]
-
-                    # add staypoint
-                    ret_spts = ret_spts.append(staypoint, ignore_index=True)
-
-                    # TODO Discussion: Is this last point really a staypoint? As we don't know if the
-                    #      person "moves on" afterwards...
-                    if j == num_pfs - 1:
-                        staypoint = {}
-                        staypoint['user_id'] = pfs[j]['user_id']
-                        staypoint[name_geocol] = Point(pfs[j][name_geocol].x, pfs[j][name_geocol].y)
-                        if elevation_flag:
-                            staypoint['elevation'] = pfs[j]['elevation']
-                        staypoint['started_at'] = pfs[j]['tracked_at']
-                        staypoint['finished_at'] = pfs[j]['tracked_at']
-                        # store matching, index should be the id of pfs
-                        staypoint['pfs_id'] = [idx[j]]
-
-                        ret_spts = ret_spts.append(staypoint, ignore_index=True)
-                i = j
-                break
-            j = j + 1
+    # as start begin from 0, curr begin from 1
+    for i in range(1, len(pfs)):
+        curr = i
+
+        delta_dist = dist_func(pfs[start][geo_col].x, pfs[start][geo_col].y, pfs[curr][geo_col].x, pfs[curr][geo_col].y)
+
+        if delta_dist >= dist_threshold:
+            # the total duration of the staypoints
+            delta_t = (pfs[curr]["tracked_at"] - pfs[start]["tracked_at"]).total_seconds()
+            # the duration of gap in the last two pfs
+            gap_t = (pfs[curr]["tracked_at"] - pfs[curr - 1]["tracked_at"]).total_seconds()
+
+            # we want the spt to have long duration, but the gap of missing signal should not be too long
+            if (delta_t >= (time_threshold * 60)) and (gap_t < gap_threshold * 60):
+                new_stps = __create_new_staypoints(start, curr, pfs, idx, elevation_flag, geo_col)
+                # add staypoint
+                ret_spts.append(new_stps)
+
+            # distance larger but time too short -> not a stay point
+            # also initializer when new stp is added
+            start = curr
+
+        # if we arrive at the last positionfix, and want to include the last staypoint
+        if (curr == len(pfs) - 1) and include_last:
+            # additional control: we want to create stps with duration larger than time_threshold
+            delta_t = (pfs[curr]["tracked_at"] - pfs[start]["tracked_at"]).total_seconds()
+            if delta_t >= (time_threshold * 60):
+                new_stps = __create_new_staypoints(start, curr, pfs, idx, elevation_flag, geo_col, last_flag=True)
+
+                # add staypoint
+                ret_spts.append(new_stps)
 
+    ret_spts = pd.DataFrame(ret_spts)
+    ret_spts["user_id"] = df["user_id"].unique()[0]
     return ret_spts
 
 
-def _generate_staypoints_dbscan_user(pfs,
-                                     name_geocol,
-                                     epsilon=100,
-                                     num_samples=1):
-    db = DBSCAN(eps=epsilon / 6371000, min_samples=num_samples, algorithm='ball_tree', metric='haversine')
+def __create_new_staypoints(start, end, pfs, idx, elevation_flag, geo_col, last_flag=False):
+    """Create a staypoint with relevant infomation from start to end pfs."""
+    new_stps = {}
 
-    # TODO: enable transformations to temporary (metric) system
-    transform_crs = None
-    if transform_crs is not None:
-        pass
+    # Here we consider pfs[end] time for stp 'finished_at', but only include
+    # pfs[end - 1] for stp geometry and pfs linkage.
+    new_stps["started_at"] = pfs[start]["tracked_at"]
+    new_stps["finished_at"] = pfs[end]["tracked_at"]
 
-    # get staypoint matching
-    p = np.array([[radians(g.y), radians(g.x)] for g in pfs[name_geocol]])
-    labels = db.fit_predict(p)
+    # if end is the last pfs, we want to include the info from it as well
+    if last_flag:
+        end = len(pfs)
 
-    # add positionfixes - staypoint matching to original positionfixes
-    pfs['staypoint_id'] = labels
+    new_stps[geo_col] = Point(
+        np.median([pfs[k][geo_col].x for k in range(start, end)]),
+        np.median([pfs[k][geo_col].y for k in range(start, end)]),
+    )
+    if elevation_flag:
+        new_stps["elevation"] = np.median([pfs[k]["elevation"] for k in range(start, end)])
+    # store matching, index should be the id of pfs
+    new_stps["pfs_id"] = [idx[k] for k in range(start, end)]
 
-    return pfs
\ No newline at end of file
+    return new_stps
diff --git a/trackintel/preprocessing/triplegs.py b/trackintel/preprocessing/triplegs.py
index 2818bba..c58b4cf 100644
--- a/trackintel/preprocessing/triplegs.py
+++ b/trackintel/preprocessing/triplegs.py
@@ -37,7 +37,7 @@ def smoothen_triplegs(triplegs, tolerance=1.0, preserve_topology=True):
     return ret_tpls
 
 
-def generate_trips(stps_input, tpls_input, gap_threshold=15, id_offset=0, print_progress=False):
+def generate_trips(stps_input, tpls_input, gap_threshold=15, print_progress=False):
     """Generate trips based on staypoints and triplegs.
 
     Parameters
@@ -51,9 +51,6 @@ def generate_trips(stps_input, tpls_input, gap_threshold=15, id_offset=0, print_
     gap_threshold : float, default 15 (minutes)
         Maximum allowed temporal gap size in minutes. If tracking data is missing for more than 
         `gap_threshold` minutes, then a new trip begins after the gap.
-                
-    id_offset : int, default 0
-        IDs for trips are incremented starting from this value.
 
     Returns
     -------
@@ -119,7 +116,7 @@ def generate_trips(stps_input, tpls_input, gap_threshold=15, id_offset=0, print_
                                   as_index=False).apply(_generate_trips_user, gap_threshold=gap_threshold).reset_index(drop=True)
     
     # index management
-    trips['id'] = np.arange(len(trips)) + id_offset
+    trips['id'] = np.arange(len(trips))
     trips.set_index('id', inplace=True)
     
     # assign trip_id to tpls


Test patch:
diff --git a/tests/analysis/test_modal_split.py b/tests/analysis/test_modal_split.py
index a6524ef..7f41abd 100644
--- a/tests/analysis/test_modal_split.py
+++ b/tests/analysis/test_modal_split.py
@@ -17,7 +17,7 @@ def read_geolife_with_modes():
 
     pfs, spts = pfs.as_positionfixes.generate_staypoints(method='sliding',
                                                          dist_threshold=25,
-                                                         time_threshold=5 * 60)
+                                                         time_threshold=5)
     _, tpls = pfs.as_positionfixes.generate_triplegs(spts, method='between_staypoints')
 
     tpls_with_modes = geolife_add_modes_to_triplegs(tpls, labels)
diff --git a/tests/analysis/test_tracking_quality.py b/tests/analysis/test_tracking_quality.py
index a1cb1b4..f0cedea 100644
--- a/tests/analysis/test_tracking_quality.py
+++ b/tests/analysis/test_tracking_quality.py
@@ -9,7 +9,7 @@ import trackintel as ti
 def testdata_stps_tpls_geolife_long():
     """Generate stps and tpls sequences of the original pfs for subsequent testing."""
     pfs, _ = ti.io.dataset_reader.read_geolife(os.path.join("tests", "data", "geolife_long"))
-    pfs, stps = pfs.as_positionfixes.generate_staypoints(method="sliding", dist_threshold=25, time_threshold=5 * 60)
+    pfs, stps = pfs.as_positionfixes.generate_staypoints(method="sliding", dist_threshold=25, time_threshold=5)
     pfs, tpls = pfs.as_positionfixes.generate_triplegs(stps, method="between_staypoints")
 
     tpls["type"] = "tripleg"
@@ -33,8 +33,9 @@ class TestTemporal_tracking_quality:
 
         # test if the result of the user agrees
         quality = ti.analysis.tracking_quality.temporal_tracking_quality(stps_tpls, granularity="all")
-
+        
         assert quality_manual == quality.loc[quality["user_id"] == 0, "quality"].values[0]
+        assert (quality['quality']<=1).all()
 
     def test_tracking_quality_day(self, testdata_stps_tpls_geolife_long):
         """Test if the calculated tracking quality per day is correct."""
@@ -53,6 +54,7 @@ class TestTemporal_tracking_quality:
         quality = ti.analysis.tracking_quality.temporal_tracking_quality(stps_tpls, granularity="day")
 
         assert quality_manual == quality.loc[(quality["user_id"] == 0) & (quality["day"] == 0), "quality"].values[0]
+        assert (quality['quality']<1).all()
 
     def test_tracking_quality_week(self, testdata_stps_tpls_geolife_long):
         """Test if the calculated tracking quality per week is correct."""
@@ -74,6 +76,7 @@ class TestTemporal_tracking_quality:
         quality = ti.analysis.tracking_quality.temporal_tracking_quality(stps_tpls, granularity="week")
 
         assert quality_manual == quality.loc[(quality["user_id"] == 0), "quality"].values[0]
+        assert (quality['quality']<1).all()
 
     def test_tracking_quality_weekday(self, testdata_stps_tpls_geolife_long):
         """Test if the calculated tracking quality per weekday is correct."""
@@ -97,6 +100,7 @@ class TestTemporal_tracking_quality:
         quality = ti.analysis.tracking_quality.temporal_tracking_quality(stps_tpls, granularity="weekday")
 
         assert quality_manual == quality.loc[(quality["user_id"] == 0) & (quality["weekday"] == 3), "quality"].values[0]
+        assert (quality['quality']<1).all()
 
     def test_tracking_quality_hour(self, testdata_stps_tpls_geolife_long):
         """Test if the calculated tracking quality per hour is correct."""
@@ -120,6 +124,7 @@ class TestTemporal_tracking_quality:
         quality = ti.analysis.tracking_quality.temporal_tracking_quality(stps_tpls, granularity="hour")
 
         assert quality_manual == quality.loc[(quality["user_id"] == 0) & (quality["hour"] == 2), "quality"].values[0]
+        assert (quality['quality']<1).all()
 
     def test_tracking_quality_error(self, testdata_stps_tpls_geolife_long):
         """Test if the an error is raised when passing unknown 'granularity' to temporal_tracking_quality()."""
diff --git a/tests/data/geolife/geolife_positionfixes_with_ids.csv b/tests/data/geolife/geolife_positionfixes_with_ids.csv
deleted file mode 100644
index 55be512..0000000
--- a/tests/data/geolife/geolife_positionfixes_with_ids.csv
+++ /dev/null
@@ -1,245 +0,0 @@
-id,lat,lon,elevation,tracked_at,user_id,accuracy,staypoint_id,tripleg_id,longitude,latitude
-0,40.008303999999995,116.31987600000001,149.9616,2008-10-24 02:09:59+00:00,0,,,0.0,116.31987600000001,40.008303999999995
-1,40.008413,116.31996200000002,149.6568,2008-10-24 02:10:04+00:00,0,,,0.0,116.31996200000002,40.008413
-2,40.007171,116.31945800000001,-14.020800000000001,2008-10-24 02:10:09+00:00,0,,,0.0,116.31945800000001,40.007171
-3,40.007209,116.319484,-14.630400000000002,2008-10-24 02:10:14+00:00,0,,,0.0,116.319484,40.007209
-4,40.007287,116.31958999999999,-12.4968,2008-10-24 02:10:19+00:00,0,,,0.0,116.31958999999999,40.007287
-5,40.007366,116.319727,-12.192,2008-10-24 02:10:24+00:00,0,,,0.0,116.319727,40.007366
-6,40.007428999999995,116.319873,-11.8872,2008-10-24 02:10:29+00:00,0,,,0.0,116.319873,40.007428999999995
-7,40.007498999999996,116.32001299999999,-11.8872,2008-10-24 02:10:34+00:00,0,,,0.0,116.32001299999999,40.007498999999996
-8,40.007514,116.32016499999999,-11.8872,2008-10-24 02:10:39+00:00,0,,,0.0,116.32016499999999,40.007514
-9,40.007578,116.320176,-12.192,2008-10-24 02:10:44+00:00,0,,,0.0,116.320176,40.007578
-10,40.007694,116.32021399999999,-11.5824,2008-10-24 02:10:49+00:00,0,,,0.0,116.32021399999999,40.007694
-11,40.007739,116.320357,-11.8872,2008-10-24 02:10:54+00:00,0,,,0.0,116.320357,40.007739
-12,40.007834,116.320544,-6.096,2008-10-24 02:10:59+00:00,0,,,0.0,116.320544,40.007834
-13,40.007907,116.32070800000001,-3.6576000000000004,2008-10-24 02:11:04+00:00,0,,,0.0,116.32070800000001,40.007907
-14,40.007940999999995,116.32086100000001,-4.2672,2008-10-24 02:11:09+00:00,0,,,0.0,116.32086100000001,40.007940999999995
-15,40.007989,116.32098899999998,-4.2672,2008-10-24 02:11:14+00:00,0,,,0.0,116.32098899999998,40.007989
-16,40.008131,116.321041,-3.3528000000000002,2008-10-24 02:11:19+00:00,0,,,0.0,116.321041,40.008131
-17,40.008316,116.321118,8.5344,2008-10-24 02:11:24+00:00,0,,,0.0,116.321118,40.008316
-18,40.008486,116.321152,19.2024,2008-10-24 02:11:29+00:00,0,,,0.0,116.321152,40.008486
-19,40.00861,116.32119099999998,21.640800000000002,2008-10-24 02:11:34+00:00,0,,,0.0,116.32119099999998,40.00861
-20,40.008716,116.321251,23.4696,2008-10-24 02:11:39+00:00,0,,,0.0,116.321251,40.008716
-21,40.008815999999996,116.321301,24.9936,2008-10-24 02:11:44+00:00,0,,,0.0,116.321301,40.008815999999996
-22,40.008875,116.321349,24.384,2008-10-24 02:11:49+00:00,0,,,0.0,116.321349,40.008875
-23,40.008912,116.321366,24.0792,2008-10-24 02:11:54+00:00,0,,,0.0,116.321366,40.008912
-24,40.008912,116.321366,24.0792,2008-10-24 02:11:57+00:00,0,,,0.0,116.321366,40.008912
-25,40.008915,116.321366,23.4696,2008-10-24 02:11:59+00:00,0,,,0.0,116.321366,40.008915
-26,40.008921,116.321375,23.4696,2008-10-24 02:12:04+00:00,0,,,0.0,116.321375,40.008921
-27,40.008931,116.321385,23.4696,2008-10-24 02:12:09+00:00,0,,,0.0,116.321385,40.008931
-28,40.00894,116.321394,23.7744,2008-10-24 02:12:14+00:00,0,,,0.0,116.321394,40.00894
-29,40.008948,116.321401,23.7744,2008-10-24 02:12:19+00:00,0,,,0.0,116.321401,40.008948
-30,40.008951,116.321405,24.0792,2008-10-24 02:12:24+00:00,0,,,0.0,116.321405,40.008951
-31,40.008951,116.321405,24.0792,2008-10-24 02:12:27+00:00,0,,,0.0,116.321405,40.008951
-32,40.008951,116.321408,24.0792,2008-10-24 02:12:29+00:00,0,,,0.0,116.321408,40.008951
-33,40.008946,116.32143799999999,24.384,2008-10-24 02:12:34+00:00,0,,,0.0,116.32143799999999,40.008946
-34,40.008953999999996,116.321506,24.9936,2008-10-24 02:12:39+00:00,0,,,0.0,116.321506,40.008953999999996
-35,40.008943,116.321554,24.9936,2008-10-24 02:12:44+00:00,0,,,0.0,116.321554,40.008943
-36,40.008924,116.32158999999999,25.2984,2008-10-24 02:12:49+00:00,0,,,0.0,116.32158999999999,40.008924
-37,40.008967999999996,116.321514,24.384,2008-10-24 02:12:54+00:00,0,,,0.0,116.321514,40.008967999999996
-38,40.008998999999996,116.32146499999999,23.7744,2008-10-24 02:12:59+00:00,0,,,0.0,116.32146499999999,40.008998999999996
-39,40.009019,116.32143300000001,23.7744,2008-10-24 02:13:04+00:00,0,,,0.0,116.32143300000001,40.009019
-40,40.009052000000004,116.321394,24.0792,2008-10-24 02:13:09+00:00,0,,,0.0,116.321394,40.009052000000004
-41,40.009085,116.321351,24.9936,2008-10-24 02:13:14+00:00,0,,,0.0,116.321351,40.009085
-42,40.009085999999996,116.321348,24.9936,2008-10-24 02:13:19+00:00,0,,,0.0,116.321348,40.009085999999996
-43,40.009085999999996,116.32134599999999,24.9936,2008-10-24 02:13:24+00:00,0,,,0.0,116.32134599999999,40.009085999999996
-44,40.009089,116.32134599999999,24.9936,2008-10-24 02:13:29+00:00,0,,,0.0,116.32134599999999,40.009089
-45,40.009089,116.321345,24.9936,2008-10-24 02:13:34+00:00,0,,,0.0,116.321345,40.009089
-46,40.009089,116.32134599999999,25.2984,2008-10-24 02:13:39+00:00,0,,,0.0,116.32134599999999,40.009089
-47,40.009088,116.32134599999999,25.2984,2008-10-24 02:13:44+00:00,0,,,0.0,116.32134599999999,40.009088
-48,40.009087,116.321347,25.2984,2008-10-24 02:13:49+00:00,0,,,0.0,116.321347,40.009087
-49,40.009088,116.32134599999999,25.2984,2008-10-24 02:13:54+00:00,0,,,0.0,116.32134599999999,40.009088
-50,40.009089,116.321344,25.2984,2008-10-24 02:13:59+00:00,0,,,0.0,116.321344,40.009089
-51,40.00909,116.32134099999999,25.2984,2008-10-24 02:14:04+00:00,0,,,0.0,116.32134099999999,40.00909
-52,40.009088,116.321344,25.2984,2008-10-24 02:14:09+00:00,0,,,0.0,116.321344,40.009088
-53,40.009085999999996,116.32134599999999,25.2984,2008-10-24 02:14:14+00:00,0,,,0.0,116.32134599999999,40.009085999999996
-54,40.009084,116.321349,25.2984,2008-10-24 02:14:19+00:00,0,,,0.0,116.321349,40.009084
-55,40.009084,116.321349,25.2984,2008-10-24 02:14:22+00:00,0,,,0.0,116.321349,40.009084
-56,40.009077000000005,116.32135600000001,25.2984,2008-10-24 02:14:24+00:00,0,,,0.0,116.32135600000001,40.009077000000005
-57,40.009055,116.321386,25.2984,2008-10-24 02:14:29+00:00,0,,,0.0,116.321386,40.009055
-58,40.009001,116.32146000000002,25.908,2008-10-24 02:14:34+00:00,0,,,0.0,116.32146000000002,40.009001
-59,40.008971,116.321519,27.736800000000002,2008-10-24 02:14:39+00:00,0,,,0.0,116.321519,40.008971
-60,40.008922999999996,116.32158100000001,28.956000000000003,2008-10-24 02:14:44+00:00,0,,,0.0,116.32158100000001,40.008922999999996
-61,40.008859,116.321706,30.48,2008-10-24 02:14:49+00:00,0,,,0.0,116.321706,40.008859
-62,40.008809,116.321794,31.3944,2008-10-24 02:14:54+00:00,0,,,0.0,116.321794,40.008809
-63,40.008779,116.32186200000001,32.308800000000005,2008-10-24 02:14:59+00:00,0,,,0.0,116.32186200000001,40.008779
-64,40.008755,116.32189699999999,34.1376,2008-10-24 02:15:04+00:00,0,,,0.0,116.32189699999999,40.008755
-65,40.008755,116.321917,36.2712,2008-10-24 02:15:09+00:00,0,,,0.0,116.321917,40.008755
-66,40.008739,116.32194799999999,38.1,2008-10-24 02:15:14+00:00,0,,,0.0,116.32194799999999,40.008739
-67,40.008727,116.321975,38.7096,2008-10-24 02:15:19+00:00,0,,0.0,0.0,116.321975,40.008727
-68,40.008708,116.321995,39.9288,2008-10-24 02:15:24+00:00,0,,0.0,,116.321995,40.008708
-69,40.0087,116.322015,40.8432,2008-10-24 02:15:29+00:00,0,,0.0,1.0,116.322015,40.0087
-70,40.008951,116.32205400000001,34.7472,2008-10-24 02:21:54+00:00,0,,,1.0,116.32205400000001,40.008951
-71,40.008965,116.32210900000001,35.052,2008-10-24 02:21:59+00:00,0,,,1.0,116.32210900000001,40.008965
-72,40.009025,116.322134,35.052,2008-10-24 02:22:04+00:00,0,,,1.0,116.322134,40.009025
-73,40.009199,116.322217,35.9664,2008-10-24 02:22:09+00:00,0,,,1.0,116.322217,40.009199
-74,40.009279,116.322252,38.7096,2008-10-24 02:22:14+00:00,0,,,1.0,116.322252,40.009279
-75,40.009314,116.32233899999999,42.062400000000004,2008-10-24 02:22:19+00:00,0,,,1.0,116.32233899999999,40.009314
-76,40.0093,116.322406,45.72,2008-10-24 02:22:24+00:00,0,,,1.0,116.322406,40.0093
-77,40.009231,116.32245900000001,49.0728,2008-10-24 02:22:29+00:00,0,,,1.0,116.32245900000001,40.009231
-78,40.009094,116.322483,51.816,2008-10-24 02:22:34+00:00,0,,,1.0,116.322483,40.009094
-79,40.008967999999996,116.32243700000001,53.0352,2008-10-24 02:22:39+00:00,0,,,1.0,116.32243700000001,40.008967999999996
-80,40.008905,116.32239399999999,53.0352,2008-10-24 02:22:44+00:00,0,,,1.0,116.32239399999999,40.008905
-81,40.008845,116.322382,51.816,2008-10-24 02:22:49+00:00,0,,1.0,1.0,116.322382,40.008845
-82,40.008764,116.322373,50.9016,2008-10-24 02:22:54+00:00,0,,1.0,,116.322373,40.008764
-83,40.008734999999994,116.322402,49.9872,2008-10-24 02:22:59+00:00,0,,1.0,,116.322402,40.008734999999994
-84,40.008734999999994,116.322402,49.9872,2008-10-24 02:23:02+00:00,0,,1.0,,116.322402,40.008734999999994
-85,40.008727,116.3224,49.6824,2008-10-24 02:23:04+00:00,0,,1.0,,116.3224,40.008727
-86,40.008697,116.322429,48.768,2008-10-24 02:23:09+00:00,0,,1.0,,116.322429,40.008697
-87,40.008694,116.32243100000001,48.4632,2008-10-24 02:23:14+00:00,0,,1.0,,116.32243100000001,40.008694
-88,40.008694,116.322432,48.4632,2008-10-24 02:23:19+00:00,0,,1.0,,116.322432,40.008694
-89,40.008697,116.322433,48.1584,2008-10-24 02:23:24+00:00,0,,1.0,,116.322433,40.008697
-90,40.008697,116.322433,48.1584,2008-10-24 02:23:27+00:00,0,,1.0,,116.322433,40.008697
-91,40.008695,116.322432,48.1584,2008-10-24 02:23:29+00:00,0,,1.0,,116.322432,40.008695
-92,40.008685,116.322427,47.8536,2008-10-24 02:23:34+00:00,0,,1.0,,116.322427,40.008685
-93,40.008649,116.322456,48.1584,2008-10-24 02:23:39+00:00,0,,1.0,,116.322456,40.008649
-94,40.008633,116.322464,47.5488,2008-10-24 02:23:44+00:00,0,,1.0,,116.322464,40.008633
-95,40.008633,116.322464,47.5488,2008-10-24 02:23:47+00:00,0,,1.0,,116.322464,40.008633
-96,40.008634,116.32246699999999,47.8536,2008-10-24 02:23:49+00:00,0,,1.0,,116.32246699999999,40.008634
-97,40.008644,116.322469,47.5488,2008-10-24 02:23:54+00:00,0,,1.0,,116.322469,40.008644
-98,40.008643,116.32246799999999,47.244,2008-10-24 02:23:59+00:00,0,,1.0,,116.32246799999999,40.008643
-99,40.008644,116.32246699999999,46.9392,2008-10-24 02:24:04+00:00,0,,1.0,,116.32246699999999,40.008644
-100,40.008644,116.32246699999999,46.9392,2008-10-24 02:24:07+00:00,0,,1.0,,116.32246699999999,40.008644
-101,40.008644,116.32246699999999,46.6344,2008-10-24 02:24:09+00:00,0,,1.0,,116.32246699999999,40.008644
-102,40.00865,116.322455,46.0248,2008-10-24 02:24:14+00:00,0,,1.0,,116.322455,40.00865
-103,40.008678,116.322475,45.415200000000006,2008-10-24 02:24:19+00:00,0,,1.0,,116.322475,40.008678
-104,40.008707,116.322496,43.586400000000005,2008-10-24 02:24:24+00:00,0,,1.0,,116.322496,40.008707
-105,40.008734000000004,116.32249399999999,41.757600000000004,2008-10-24 02:24:29+00:00,0,,1.0,,116.32249399999999,40.008734000000004
-106,40.008742,116.32246,39.624,2008-10-24 02:24:34+00:00,0,,1.0,,116.32246,40.008742
-107,40.008728999999995,116.32243799999999,39.3192,2008-10-24 02:24:39+00:00,0,,1.0,,116.32243799999999,40.008728999999995
-108,40.008726,116.32243600000001,39.0144,2008-10-24 02:24:44+00:00,0,,1.0,,116.32243600000001,40.008726
-109,40.008726,116.32243600000001,39.0144,2008-10-24 02:24:47+00:00,0,,1.0,,116.32243600000001,40.008726
-110,40.008720000000004,116.32243899999999,38.7096,2008-10-24 02:24:49+00:00,0,,1.0,,116.32243899999999,40.008720000000004
-111,40.008703000000004,116.32243600000001,38.4048,2008-10-24 02:24:54+00:00,0,,1.0,,116.32243600000001,40.008703000000004
-112,40.008686,116.32244299999999,37.7952,2008-10-24 02:24:59+00:00,0,,1.0,,116.32244299999999,40.008686
-113,40.008679,116.32245400000001,38.1,2008-10-24 02:25:04+00:00,0,,1.0,,116.32245400000001,40.008679
-114,40.008679,116.32246599999999,39.0144,2008-10-24 02:25:09+00:00,0,,1.0,,116.32246599999999,40.008679
-115,40.008679,116.322476,39.0144,2008-10-24 02:25:14+00:00,0,,1.0,,116.322476,40.008679
-116,40.008676,116.32248100000001,39.0144,2008-10-24 02:25:19+00:00,0,,1.0,,116.32248100000001,40.008676
-117,40.008676,116.32248100000001,39.0144,2008-10-24 02:25:22+00:00,0,,1.0,,116.32248100000001,40.008676
-118,40.008671,116.32248799999999,38.7096,2008-10-24 02:25:24+00:00,0,,1.0,,116.32248799999999,40.008671
-119,40.008665,116.322499,38.4048,2008-10-24 02:25:29+00:00,0,,1.0,,116.322499,40.008665
-120,40.008672999999995,116.322483,37.1856,2008-10-24 02:25:34+00:00,0,,1.0,,116.322483,40.008672999999995
-121,40.008693,116.322461,35.6616,2008-10-24 02:25:39+00:00,0,,1.0,,116.322461,40.008693
-122,40.008725,116.32242099999999,36.576,2008-10-24 02:25:44+00:00,0,,1.0,,116.32242099999999,40.008725
-123,40.008725,116.32242099999999,36.576,2008-10-24 02:25:47+00:00,0,,1.0,,116.32242099999999,40.008725
-124,40.008732,116.322419,36.2712,2008-10-24 02:25:49+00:00,0,,1.0,,116.322419,40.008732
-125,40.008736,116.322397,35.9664,2008-10-24 02:25:54+00:00,0,,1.0,,116.322397,40.008736
-126,40.008722999999996,116.32238400000001,35.6616,2008-10-24 02:25:59+00:00,0,,1.0,,116.32238400000001,40.008722999999996
-127,40.008718,116.322383,35.6616,2008-10-24 02:26:04+00:00,0,,1.0,,116.322383,40.008718
-128,40.008718,116.322383,35.6616,2008-10-24 02:26:09+00:00,0,,1.0,,116.322383,40.008718
-129,40.008719,116.32238400000001,35.6616,2008-10-24 02:26:14+00:00,0,,1.0,,116.32238400000001,40.008719
-130,40.008714000000005,116.322383,35.6616,2008-10-24 02:26:19+00:00,0,,1.0,,116.322383,40.008714000000005
-131,40.008712,116.322382,35.9664,2008-10-24 02:26:24+00:00,0,,1.0,,116.322382,40.008712
-132,40.008711,116.322382,35.9664,2008-10-24 02:26:29+00:00,0,,1.0,,116.322382,40.008711
-133,40.008711,116.322382,35.9664,2008-10-24 02:26:32+00:00,0,,1.0,,116.322382,40.008711
-134,40.008714000000005,116.32238400000001,35.6616,2008-10-24 02:26:34+00:00,0,,1.0,,116.32238400000001,40.008714000000005
-135,40.008715,116.322396,35.3568,2008-10-24 02:26:39+00:00,0,,1.0,,116.322396,40.008715
-136,40.00871,116.3224,35.3568,2008-10-24 02:26:44+00:00,0,,1.0,,116.3224,40.00871
-137,40.00871,116.3224,35.3568,2008-10-24 02:26:47+00:00,0,,1.0,,116.3224,40.00871
-138,40.008712,116.322402,35.6616,2008-10-24 02:26:49+00:00,0,,1.0,,116.322402,40.008712
-139,40.008722,116.32241699999999,35.052,2008-10-24 02:26:54+00:00,0,,1.0,,116.32241699999999,40.008722
-140,40.008722999999996,116.32242,35.3568,2008-10-24 02:26:59+00:00,0,,1.0,,116.32242,40.008722999999996
-141,40.00873,116.32242099999999,35.6616,2008-10-24 02:27:04+00:00,0,,1.0,,116.32242099999999,40.00873
-142,40.00873,116.32242099999999,35.6616,2008-10-24 02:27:07+00:00,0,,1.0,,116.32242099999999,40.00873
-143,40.008734999999994,116.32241599999999,35.6616,2008-10-24 02:27:09+00:00,0,,1.0,,116.32241599999999,40.008734999999994
-144,40.008749,116.322429,35.9664,2008-10-24 02:27:14+00:00,0,,1.0,,116.322429,40.008749
-145,40.008757,116.322453,35.9664,2008-10-24 02:27:19+00:00,0,,1.0,,116.322453,40.008757
-146,40.008790999999995,116.32243700000001,34.7472,2008-10-24 02:27:24+00:00,0,,1.0,,116.32243700000001,40.008790999999995
-147,40.0088,116.32241599999999,34.4424,2008-10-24 02:27:29+00:00,0,,1.0,,116.32241599999999,40.0088
-148,40.008807,116.322382,33.528,2008-10-24 02:27:34+00:00,0,,1.0,,116.322382,40.008807
-149,40.008813,116.322378,33.528,2008-10-24 02:27:39+00:00,0,,1.0,,116.322378,40.008813
-150,40.008807,116.322376,33.2232,2008-10-24 02:27:44+00:00,0,,1.0,,116.322376,40.008807
-151,40.008804,116.322379,32.9184,2008-10-24 02:27:49+00:00,0,,1.0,,116.322379,40.008804
-152,40.008801,116.32238100000001,32.9184,2008-10-24 02:27:54+00:00,0,,1.0,,116.32238100000001,40.008801
-153,40.0088,116.322383,32.9184,2008-10-24 02:27:59+00:00,0,,1.0,,116.322383,40.0088
-154,40.0088,116.322383,32.9184,2008-10-24 02:28:02+00:00,0,,1.0,,116.322383,40.0088
-155,40.008804999999995,116.32238799999999,32.9184,2008-10-24 02:28:04+00:00,0,,1.0,,116.32238799999999,40.008804999999995
-156,40.008806,116.32241200000001,33.2232,2008-10-24 02:28:09+00:00,0,,1.0,,116.32241200000001,40.008806
-157,40.008809,116.322414,33.2232,2008-10-24 02:28:14+00:00,0,,1.0,,116.322414,40.008809
-158,40.008803,116.32240800000001,33.528,2008-10-24 02:28:19+00:00,0,,1.0,,116.32240800000001,40.008803
-159,40.008803,116.32240800000001,33.528,2008-10-24 02:28:22+00:00,0,,1.0,,116.32240800000001,40.008803
-160,40.008802,116.322402,33.528,2008-10-24 02:28:24+00:00,0,,1.0,,116.322402,40.008802
-161,40.008772,116.32241699999999,34.7472,2008-10-24 02:28:29+00:00,0,,1.0,,116.32241699999999,40.008772
-162,40.008773,116.32241100000002,34.4424,2008-10-24 02:28:31+00:00,0,,1.0,,116.32241100000002,40.008773
-163,40.008763,116.322406,34.7472,2008-10-24 02:28:36+00:00,0,,1.0,,116.322406,40.008763
-164,40.008763,116.322406,34.7472,2008-10-24 02:28:39+00:00,0,,1.0,,116.322406,40.008763
-165,40.008764,116.322414,35.052,2008-10-24 02:28:41+00:00,0,,1.0,,116.322414,40.008764
-166,40.008767999999996,116.32239299999999,35.6616,2008-10-24 02:28:46+00:00,0,,1.0,,116.32239299999999,40.008767999999996
-167,40.008765000000004,116.32238999999998,35.6616,2008-10-24 02:28:51+00:00,0,,1.0,,116.32238999999998,40.008765000000004
-168,40.008765000000004,116.32238999999998,35.6616,2008-10-24 02:28:54+00:00,0,,1.0,,116.32238999999998,40.008765000000004
-169,40.008767999999996,116.32238999999998,35.6616,2008-10-24 02:28:56+00:00,0,,1.0,,116.32238999999998,40.008767999999996
-170,40.008742,116.322304,35.3568,2008-10-24 02:29:01+00:00,0,,1.0,,116.322304,40.008742
-171,40.008722,116.32229199999999,35.3568,2008-10-24 02:29:06+00:00,0,,1.0,,116.32229199999999,40.008722
-172,40.008715,116.32226499999999,35.052,2008-10-24 02:29:11+00:00,0,,1.0,,116.32226499999999,40.008715
-173,40.008702,116.322221,35.052,2008-10-24 02:29:16+00:00,0,,1.0,,116.322221,40.008702
-174,40.008691999999996,116.322194,35.052,2008-10-24 02:29:21+00:00,0,,1.0,,116.322194,40.008691999999996
-175,40.008671,116.322162,35.052,2008-10-24 02:29:26+00:00,0,,2.0,2.0,116.322162,40.008671
-176,40.008963,116.322994,-142.0368,2008-10-24 02:41:31+00:00,0,,,2.0,116.322994,40.008963
-177,40.008716,116.322254,24.0792,2008-10-24 02:41:36+00:00,0,,,2.0,116.322254,40.008716
-178,40.008829,116.322251,29.8704,2008-10-24 02:41:41+00:00,0,,,2.0,116.322251,40.008829
-179,40.008745000000005,116.322172,29.260800000000003,2008-10-24 02:41:46+00:00,0,,,2.0,116.322172,40.008745000000005
-180,40.00871,116.322158,28.956000000000003,2008-10-24 02:41:51+00:00,0,,,2.0,116.322158,40.00871
-181,40.008767999999996,116.322217,29.260800000000003,2008-10-24 02:41:56+00:00,0,,,2.0,116.322217,40.008767999999996
-182,40.008795,116.322319,29.260800000000003,2008-10-24 02:42:01+00:00,0,,,2.0,116.322319,40.008795
-183,40.008818,116.322352,29.5656,2008-10-24 02:42:06+00:00,0,,,2.0,116.322352,40.008818
-184,40.008851,116.32236499999999,29.8704,2008-10-24 02:42:11+00:00,0,,,2.0,116.32236499999999,40.008851
-185,40.008821000000005,116.322432,32.9184,2008-10-24 02:42:16+00:00,0,,,2.0,116.322432,40.008821000000005
-186,40.008907,116.32251699999999,32.308800000000005,2008-10-24 02:42:21+00:00,0,,,2.0,116.32251699999999,40.008907
-187,40.008927,116.32248899999999,30.48,2008-10-24 02:42:26+00:00,0,,,2.0,116.32248899999999,40.008927
-188,40.00892,116.322484,30.1752,2008-10-24 02:42:31+00:00,0,,,2.0,116.322484,40.00892
-189,40.008919,116.322484,30.1752,2008-10-24 02:42:36+00:00,0,,,2.0,116.322484,40.008919
-190,40.008919,116.322484,30.1752,2008-10-24 02:42:39+00:00,0,,,2.0,116.322484,40.008919
-191,40.008927,116.32248700000001,30.1752,2008-10-24 02:42:41+00:00,0,,,2.0,116.32248700000001,40.008927
-192,40.008946,116.32249499999999,29.5656,2008-10-24 02:42:46+00:00,0,,,2.0,116.32249499999999,40.008946
-193,40.008953000000005,116.3225,29.8704,2008-10-24 02:42:51+00:00,0,,,2.0,116.3225,40.008953000000005
-194,40.008947,116.322496,30.1752,2008-10-24 02:42:56+00:00,0,,,2.0,116.322496,40.008947
-195,40.008942,116.32249499999999,30.48,2008-10-24 02:43:01+00:00,0,,,2.0,116.32249499999999,40.008942
-196,40.008943,116.32249399999999,30.48,2008-10-24 02:43:06+00:00,0,,,2.0,116.32249399999999,40.008943
-197,40.008946,116.32249399999999,31.0896,2008-10-24 02:43:11+00:00,0,,,2.0,116.32249399999999,40.008946
-198,40.008951,116.32249399999999,31.6992,2008-10-24 02:43:16+00:00,0,,,2.0,116.32249399999999,40.008951
-199,40.008956,116.322493,32.308800000000005,2008-10-24 02:43:21+00:00,0,,,2.0,116.322493,40.008956
-200,40.008959999999995,116.322492,33.2232,2008-10-24 02:43:26+00:00,0,,,2.0,116.322492,40.008959999999995
-201,40.008963,116.322493,33.8328,2008-10-24 02:43:31+00:00,0,,,2.0,116.322493,40.008963
-202,40.008964,116.32249399999999,34.7472,2008-10-24 02:43:36+00:00,0,,,2.0,116.32249399999999,40.008964
-203,40.008967,116.32249399999999,35.9664,2008-10-24 02:43:41+00:00,0,,,2.0,116.32249399999999,40.008967
-204,40.008972,116.32249499999999,36.8808,2008-10-24 02:43:46+00:00,0,,,2.0,116.32249499999999,40.008972
-205,40.008977,116.322496,38.1,2008-10-24 02:43:51+00:00,0,,,2.0,116.322496,40.008977
-206,40.008981,116.322497,39.3192,2008-10-24 02:43:56+00:00,0,,,2.0,116.322497,40.008981
-207,40.008982,116.322492,41.148,2008-10-24 02:44:01+00:00,0,,,2.0,116.322492,40.008982
-208,40.008987,116.32248799999999,42.976800000000004,2008-10-24 02:44:06+00:00,0,,,2.0,116.32248799999999,40.008987
-209,40.008993,116.32248600000001,44.500800000000005,2008-10-24 02:44:11+00:00,0,,,2.0,116.32248600000001,40.008993
-210,40.008998,116.322484,46.0248,2008-10-24 02:44:16+00:00,0,,,2.0,116.322484,40.008998
-211,40.009001,116.32248999999999,47.244,2008-10-24 02:44:21+00:00,0,,,2.0,116.32248999999999,40.009001
-212,40.009001,116.32248999999999,47.244,2008-10-24 02:44:24+00:00,0,,,2.0,116.32248999999999,40.009001
-213,40.009005,116.32248999999999,48.1584,2008-10-24 02:44:26+00:00,0,,,2.0,116.32248999999999,40.009005
-214,40.009001,116.322503,46.0248,2008-10-24 02:44:31+00:00,0,,,2.0,116.322503,40.009001
-215,40.009001,116.322503,46.0248,2008-10-24 02:44:34+00:00,0,,,2.0,116.322503,40.009001
-216,40.009007000000004,116.322505,46.3296,2008-10-24 02:44:36+00:00,0,,,2.0,116.322505,40.009007000000004
-217,40.009053,116.322478,46.3296,2008-10-24 02:44:41+00:00,0,,,2.0,116.322478,40.009053
-218,40.009112,116.322452,45.72,2008-10-24 02:44:46+00:00,0,,,2.0,116.322452,40.009112
-219,40.009211,116.322405,45.72,2008-10-24 02:44:51+00:00,0,,,2.0,116.322405,40.009211
-220,40.009311,116.32235800000001,49.6824,2008-10-24 02:44:56+00:00,0,,,2.0,116.32235800000001,40.009311
-221,40.009415000000004,116.322349,53.644800000000004,2008-10-24 02:45:01+00:00,0,,,2.0,116.322349,40.009415000000004
-222,40.009464,116.322313,54.559200000000004,2008-10-24 02:45:06+00:00,0,,,2.0,116.322313,40.009464
-223,40.009423999999996,116.32224099999999,53.0352,2008-10-24 02:45:11+00:00,0,,,2.0,116.32224099999999,40.009423999999996
-224,40.009403000000006,116.32218300000001,50.292,2008-10-24 02:45:16+00:00,0,,,2.0,116.32218300000001,40.009403000000006
-225,40.009329,116.32215500000001,44.805600000000005,2008-10-24 02:45:21+00:00,0,,,2.0,116.32215500000001,40.009329
-226,40.009298,116.32208600000001,42.062400000000004,2008-10-24 02:45:26+00:00,0,,,2.0,116.32208600000001,40.009298
-227,40.009256,116.322052,39.0144,2008-10-24 02:45:31+00:00,0,,,2.0,116.322052,40.009256
-228,40.009190999999994,116.32200700000001,38.1,2008-10-24 02:45:36+00:00,0,,,2.0,116.32200700000001,40.009190999999994
-229,40.009161999999996,116.32196,36.2712,2008-10-24 02:45:41+00:00,0,,,2.0,116.32196,40.009161999999996
-230,40.009167,116.321946,33.8328,2008-10-24 02:45:46+00:00,0,,,2.0,116.321946,40.009167
-231,40.009144,116.32188700000002,32.308800000000005,2008-10-24 02:45:51+00:00,0,,,2.0,116.32188700000002,40.009144
-232,40.009108000000005,116.321798,30.1752,2008-10-24 02:45:56+00:00,0,,,2.0,116.321798,40.009108000000005
-233,40.009038000000004,116.32171899999999,27.736800000000002,2008-10-24 02:46:01+00:00,0,,,2.0,116.32171899999999,40.009038000000004
-234,40.00893,116.321666,27.127200000000002,2008-10-24 02:46:06+00:00,0,,,2.0,116.321666,40.00893
-235,40.008848,116.32164399999999,27.127200000000002,2008-10-24 02:46:11+00:00,0,,,2.0,116.32164399999999,40.008848
-236,40.008809,116.321615,27.432000000000002,2008-10-24 02:46:16+00:00,0,,,2.0,116.321615,40.008809
-237,40.008773,116.321572,26.5176,2008-10-24 02:46:21+00:00,0,,,2.0,116.321572,40.008773
-238,40.008725,116.321582,25.908,2008-10-24 02:46:26+00:00,0,,,2.0,116.321582,40.008725
-239,40.00871,116.32158600000001,24.9936,2008-10-24 02:46:31+00:00,0,,,2.0,116.32158600000001,40.00871
-240,40.009134,116.321215,55.778400000000005,2008-10-24 02:46:51+00:00,0,,,2.0,116.321215,40.009134
-241,40.009199,116.32111100000002,28.041600000000003,2008-10-24 02:46:56+00:00,0,,,2.0,116.32111100000002,40.009199
-242,40.009215000000005,116.32115800000001,25.6032,2008-10-24 02:47:01+00:00,0,,,2.0,116.32115800000001,40.009215000000005
-243,40.009209000000006,116.32116200000002,25.6032,2008-10-24 02:47:06+00:00,0,,,2.0,116.32116200000002,40.009209000000006
diff --git a/tests/data/geolife/geolife_triplegs_short.csv b/tests/data/geolife/geolife_triplegs_short.csv
deleted file mode 100644
index 08493e4..0000000
--- a/tests/data/geolife/geolife_triplegs_short.csv
+++ /dev/null
@@ -1,4 +0,0 @@
-id,user_id,started_at,finished_at,geom
-0,0,2008-10-24 02:09:59+00:00,2008-10-24 02:15:19+00:00,"LINESTRING (116.3198760000000078 40.0083039999999954, 116.3199620000000181 40.0084129999999973, 116.3194580000000116 40.0071709999999996, 116.3194840000000028 40.0072090000000031, 116.3195899999999909 40.0072869999999980, 116.3197270000000003 40.0073659999999975, 116.3198730000000012 40.0074289999999948, 116.3200129999999888 40.0074989999999957, 116.3201649999999887 40.0075140000000005, 116.3201760000000036 40.0075780000000023, 116.3202139999999929 40.0076940000000008, 116.3203570000000013 40.0077390000000008, 116.3205439999999982 40.0078340000000026, 116.3207080000000104 40.0079070000000030, 116.3208610000000078 40.0079409999999953, 116.3209889999999831 40.0079890000000020, 116.3210409999999939 40.0081309999999988, 116.3211179999999985 40.0083160000000007, 116.3211519999999979 40.0084859999999978, 116.3211909999999847 40.0086099999999973, 116.3212510000000037 40.0087159999999997, 116.3213010000000054 40.0088159999999959, 116.3213489999999979 40.0088750000000033, 116.3213659999999976 40.0089120000000023, 116.3213659999999976 40.0089120000000023, 116.3213659999999976 40.0089150000000018, 116.3213750000000033 40.0089210000000008, 116.3213850000000065 40.0089309999999969, 116.3213939999999980 40.0089400000000026, 116.3214009999999945 40.0089479999999966, 116.3214049999999986 40.0089510000000033, 116.3214049999999986 40.0089510000000033, 116.3214080000000052 40.0089510000000033, 116.3214379999999863 40.0089460000000017, 116.3215059999999994 40.0089539999999957, 116.3215540000000061 40.0089430000000021, 116.3215899999999863 40.0089240000000004, 116.3215139999999934 40.0089679999999959, 116.3214649999999892 40.0089989999999958, 116.3214330000000132 40.0090190000000021, 116.3213939999999980 40.0090520000000041, 116.3213510000000070 40.0090849999999989, 116.3213480000000004 40.0090859999999964, 116.3213459999999912 40.0090859999999964, 116.3213459999999912 40.0090890000000030, 116.3213449999999938 40.0090890000000030, 116.3213459999999912 40.0090890000000030, 116.3213459999999912 40.0090879999999984, 116.3213470000000029 40.0090870000000010, 116.3213459999999912 40.0090879999999984, 116.3213439999999963 40.0090890000000030, 116.3213409999999897 40.0090900000000005, 116.3213439999999963 40.0090879999999984, 116.3213459999999912 40.0090859999999964, 116.3213489999999979 40.0090840000000014, 116.3213489999999979 40.0090840000000014, 116.3213560000000086 40.0090770000000049, 116.3213860000000039 40.0090549999999965, 116.3214600000000161 40.0090009999999978, 116.3215189999999950 40.0089710000000025, 116.3215810000000090 40.0089229999999958, 116.3217060000000060 40.0088590000000011, 116.3217939999999970 40.0088089999999994, 116.3218620000000101 40.0087789999999970, 116.3218969999999928 40.0087550000000007, 116.3219169999999991 40.0087550000000007, 116.3219479999999919 40.0087389999999985, 116.3219749999999948 40.0087270000000004)"
-1,0,2008-10-24 02:15:29+00:00,2008-10-24 02:22:49+00:00,"LINESTRING (116.3220149999999933 40.0086999999999975, 116.3220540000000085 40.0089510000000033, 116.3221090000000117 40.0089650000000034, 116.3221340000000055 40.0090250000000012, 116.3222169999999949 40.0091990000000024, 116.3222520000000060 40.0092789999999994, 116.3223389999999853 40.0093140000000034, 116.3224060000000009 40.0093000000000032, 116.3224590000000092 40.0092309999999998, 116.3224830000000054 40.0090939999999975, 116.3224370000000079 40.0089679999999959, 116.3223939999999885 40.0089049999999986, 116.3223820000000046 40.0088450000000009)"
-2,0,2008-10-24 02:29:26+00:00,2008-10-24 02:47:06+00:00,"LINESTRING (116.3221620000000058 40.0086709999999997, 116.3229939999999942 40.0089630000000014, 116.3222540000000009 40.0087159999999997, 116.3222509999999943 40.0088289999999986, 116.3221719999999948 40.0087450000000047, 116.3221580000000017 40.0087100000000007, 116.3222169999999949 40.0087679999999963, 116.3223189999999931 40.0087949999999992, 116.3223519999999951 40.0088179999999980, 116.3223649999999907 40.0088509999999999, 116.3224320000000063 40.0088210000000046, 116.3225169999999906 40.0089070000000007, 116.3224889999999903 40.0089269999999999, 116.3224840000000029 40.0089200000000034, 116.3224840000000029 40.0089189999999988, 116.3224840000000029 40.0089189999999988, 116.3224870000000095 40.0089269999999999, 116.3224949999999893 40.0089460000000017, 116.3225000000000051 40.0089530000000053, 116.3224960000000010 40.0089469999999992, 116.3224949999999893 40.0089419999999976, 116.3224939999999918 40.0089430000000021, 116.3224939999999918 40.0089460000000017, 116.3224939999999918 40.0089510000000033, 116.3224929999999944 40.0089559999999977, 116.3224919999999969 40.0089599999999947, 116.3224929999999944 40.0089630000000014, 116.3224939999999918 40.0089639999999989, 116.3224939999999918 40.0089669999999984, 116.3224949999999893 40.0089720000000000, 116.3224960000000010 40.0089770000000016, 116.3224969999999985 40.0089809999999986, 116.3224919999999969 40.0089820000000032, 116.3224879999999928 40.0089869999999976, 116.3224860000000120 40.0089929999999967, 116.3224840000000029 40.0089979999999983, 116.3224899999999877 40.0090009999999978, 116.3224899999999877 40.0090009999999978, 116.3224899999999877 40.0090050000000019, 116.3225029999999975 40.0090009999999978, 116.3225029999999975 40.0090009999999978, 116.3225050000000067 40.0090070000000040, 116.3224780000000038 40.0090530000000015, 116.3224519999999984 40.0091120000000018, 116.3224050000000034 40.0092110000000005, 116.3223580000000084 40.0093109999999967, 116.3223490000000027 40.0094150000000042, 116.3223129999999941 40.0094640000000012, 116.3222409999999911 40.0094239999999957, 116.3221830000000097 40.0094030000000060, 116.3221550000000093 40.0093290000000010, 116.3220860000000130 40.0092980000000011, 116.3220519999999993 40.0092560000000006, 116.3220070000000135 40.0091909999999942, 116.3219600000000042 40.0091619999999963, 116.3219459999999970 40.0091669999999979, 116.3218870000000180 40.0091439999999992, 116.3217980000000011 40.0091080000000048, 116.3217189999999874 40.0090380000000039, 116.3216659999999933 40.0089299999999994, 116.3216439999999920 40.0088480000000004, 116.3216149999999942 40.0088089999999994, 116.3215720000000033 40.0087729999999979, 116.3215820000000065 40.0087249999999983, 116.3215860000000106 40.0087100000000007, 116.3212149999999951 40.0091340000000031, 116.3211110000000161 40.0091990000000024, 116.3211580000000112 40.0092150000000046, 116.3211620000000153 40.0092090000000056)"
diff --git a/tests/data/geolife_long/stps_tpls.csv b/tests/data/geolife_long/stps_tpls.csv
new file mode 100644
index 0000000..3a1bbc9
--- /dev/null
+++ b/tests/data/geolife_long/stps_tpls.csv
@@ -0,0 +1,45 @@
+id,started_at,finished_at,user_id,type,activity,trip_id,prev_trip_id,next_trip_id,started_at_next,activity_next,gap
+0,2008-10-23 02:53:04+00:00,2008-10-23 03:05:00+00:00,0,tripleg,False,0,,,2008-10-23 03:05:05+00:00,True,False
+0,2008-10-23 03:05:05+00:00,2008-10-23 04:08:07+00:00,0,staypoint,True,,0,1,2008-10-23 04:08:07+00:00,False,False
+1,2008-10-23 04:08:07+00:00,2008-10-23 04:34:37+00:00,0,tripleg,False,1,,,2008-10-23 04:34:42+00:00,True,False
+1,2008-10-23 04:34:42+00:00,2008-10-23 09:42:25+00:00,0,staypoint,True,,1,2,2008-10-23 09:42:25+00:00,False,False
+2,2008-10-23 09:42:25+00:00,2008-10-23 09:55:26+00:00,0,tripleg,False,2,,,2008-10-23 09:55:31+00:00,False,False
+2,2008-10-23 09:55:31+00:00,2008-10-23 10:03:39+00:00,0,staypoint,False,2,,,2008-10-23 10:03:39+00:00,False,False
+3,2008-10-23 10:03:39+00:00,2008-10-23 10:20:46+00:00,0,tripleg,False,2,,,2008-10-23 10:20:56+00:00,False,False
+3,2008-10-23 10:20:56+00:00,2008-10-23 10:26:35+00:00,0,staypoint,False,2,,,2008-10-23 10:26:35+00:00,False,False
+4,2008-10-23 10:26:35+00:00,2008-10-23 10:32:30+00:00,0,tripleg,False,2,,,2008-10-23 10:32:35+00:00,False,False
+4,2008-10-23 10:32:35+00:00,2008-10-23 10:44:31+00:00,0,staypoint,False,2,,,2008-10-23 10:44:31+00:00,False,False
+5,2008-10-23 10:44:31+00:00,2008-10-23 10:45:41+00:00,0,tripleg,False,2,,,2008-10-23 10:45:46+00:00,True,False
+5,2008-10-23 10:45:46+00:00,2008-10-23 11:09:22+00:00,0,staypoint,True,,2,3,2008-10-23 11:09:22+00:00,False,False
+6,2008-10-23 11:09:22+00:00,2008-10-23 11:10:57+00:00,0,tripleg,False,3,,,2008-10-23 11:11:02+00:00,True,False
+6,2008-10-23 11:11:02+00:00,2008-10-24 02:09:59+00:00,0,staypoint,True,,3,4,2008-10-24 02:09:59+00:00,False,False
+7,2008-10-24 02:09:59+00:00,2008-10-24 02:15:14+00:00,0,tripleg,False,4,,,2008-10-24 02:15:19+00:00,False,False
+7,2008-10-24 02:15:19+00:00,2008-10-24 02:21:54+00:00,0,staypoint,False,4,,,2008-10-24 02:21:54+00:00,False,False
+8,2008-10-24 02:21:54+00:00,2008-10-24 02:22:44+00:00,0,tripleg,False,4,,,2008-10-24 02:22:49+00:00,False,False
+8,2008-10-24 02:22:49+00:00,2008-10-24 02:29:26+00:00,0,staypoint,False,4,,,2008-10-24 02:29:26+00:00,False,False
+9,2008-10-24 02:29:26+00:00,2008-10-24 02:41:31+00:00,0,staypoint,False,4,,,2008-10-24 02:41:31+00:00,False,False
+9,2008-10-24 02:41:31+00:00,2008-10-24 02:47:06+00:00,0,tripleg,False,4,,,2008-10-23 05:53:05+00:00,False,True
+10,2008-10-23 05:53:05+00:00,2008-10-23 06:01:42+00:00,1,tripleg,False,5,,,2008-10-23 06:01:47+00:00,True,False
+10,2008-10-23 06:01:47+00:00,2008-10-23 10:32:53+00:00,1,staypoint,True,,5,6,2008-10-23 10:32:53+00:00,False,False
+11,2008-10-23 10:32:53+00:00,2008-10-23 11:10:19+00:00,1,tripleg,False,6,,,2008-10-23 11:10:24+00:00,True,False
+11,2008-10-23 11:10:24+00:00,2008-10-23 11:49:08+00:00,1,staypoint,True,,6,7,2008-10-23 11:49:08+00:00,False,False
+12,2008-10-23 11:49:08+00:00,2008-10-23 11:49:48+00:00,1,tripleg,False,7,,,2008-10-23 11:49:53+00:00,True,False
+12,2008-10-23 11:49:53+00:00,2008-10-23 23:43:46+00:00,1,staypoint,True,,7,8,2008-10-23 23:43:46+00:00,False,False
+13,2008-10-23 23:43:46+00:00,2008-10-24 00:14:57+00:00,1,tripleg,False,8,,,2008-10-24 00:15:00+00:00,False,False
+13,2008-10-24 00:15:00+00:00,2008-10-24 00:20:39+00:00,1,staypoint,False,8,,,2008-10-24 00:20:39+00:00,False,False
+14,2008-10-24 00:20:39+00:00,2008-10-24 00:23:03+00:00,1,tripleg,False,8,,,2008-10-24 00:23:08+00:00,True,False
+14,2008-10-24 00:23:08+00:00,2008-10-24 01:45:41+00:00,1,staypoint,True,,8,9,2008-10-24 01:45:41+00:00,False,False
+15,2008-10-24 01:45:41+00:00,2008-10-24 02:02:46+00:00,1,tripleg,False,9,,,2008-10-24 02:02:51+00:00,True,False
+15,2008-10-24 02:02:51+00:00,2008-10-24 02:28:19+00:00,1,staypoint,True,,9,10,2008-10-24 02:28:19+00:00,False,False
+16,2008-10-24 02:28:19+00:00,2008-10-24 02:31:32+00:00,1,tripleg,False,10,,,2008-10-24 02:31:37+00:00,True,False
+16,2008-10-24 02:31:37+00:00,2008-10-24 03:16:35+00:00,1,staypoint,True,,10,11,2008-10-24 03:16:35+00:00,False,False
+17,2008-10-24 03:16:35+00:00,2008-10-24 03:26:30+00:00,1,tripleg,False,11,,,2008-10-24 03:26:35+00:00,False,False
+17,2008-10-24 03:26:35+00:00,2008-10-24 03:33:15+00:00,1,staypoint,False,11,,,2008-10-24 03:33:15+00:00,False,False
+18,2008-10-24 03:33:15+00:00,2008-10-24 03:46:25+00:00,1,staypoint,False,11,,,2008-10-24 03:46:25+00:00,False,False
+18,2008-10-24 03:46:25+00:00,2008-10-24 04:00:13+00:00,1,tripleg,False,11,,,2008-10-24 04:00:18+00:00,False,False
+19,2008-10-24 04:00:18+00:00,2008-10-24 04:07:56+00:00,1,staypoint,False,11,,,2008-10-24 04:07:56+00:00,False,False
+19,2008-10-24 04:07:56+00:00,2008-10-24 04:12:50+00:00,1,tripleg,False,11,,,2008-10-24 04:12:55+00:00,True,False
+20,2008-10-24 04:12:55+00:00,2008-10-24 05:28:05+00:00,1,staypoint,True,,11,12,2008-10-24 05:28:05+00:00,False,False
+20,2008-10-24 05:28:05+00:00,2008-10-24 05:39:50+00:00,1,tripleg,False,12,,,2008-10-24 05:39:53+00:00,True,False
+21,2008-10-24 05:39:53+00:00,2008-10-24 06:08:42+00:00,1,staypoint,True,,12,13,2008-10-24 06:08:42+00:00,False,False
+21,2008-10-24 06:08:42+00:00,2008-10-24 06:35:50+00:00,1,tripleg,False,13,,,,,False
diff --git a/tests/data/geolife_long/tpls_spts.csv b/tests/data/geolife_long/tpls_spts.csv
deleted file mode 100644
index 860aa81..0000000
--- a/tests/data/geolife_long/tpls_spts.csv
+++ /dev/null
@@ -1,45 +0,0 @@
-id,started_at,finished_at,user_id,type,activity,trip_id,prev_trip_id,next_trip_id,started_at_next,activity_next,gap
-0,2008-10-23 02:53:04+00:00,2008-10-23 03:05:05+00:00,0,tripleg,False,0.0,,,2008-10-23 03:05:05+00:00,False,False
-0,2008-10-23 03:05:05+00:00,2008-10-23 03:05:15+00:00,0,staypoint,False,0.0,,,2008-10-23 03:05:15+00:00,False,False
-1,2008-10-23 03:05:15+00:00,2008-10-23 04:34:42+00:00,0,tripleg,False,0.0,,,2008-10-23 04:34:42+00:00,False,False
-1,2008-10-23 04:34:42+00:00,2008-10-23 04:34:52+00:00,0,staypoint,False,0.0,,,2008-10-23 04:34:52+00:00,False,False
-2,2008-10-23 04:34:52+00:00,2008-10-23 09:55:31+00:00,0,tripleg,False,0.0,,,2008-10-23 09:55:31+00:00,True,False
-2,2008-10-23 09:55:31+00:00,2008-10-23 10:02:29+00:00,0,staypoint,True,,0.0,1.0,2008-10-23 10:02:29+00:00,False,False
-3,2008-10-23 10:02:29+00:00,2008-10-23 10:20:56+00:00,0,tripleg,False,1.0,,,2008-10-23 10:20:56+00:00,False,False
-3,2008-10-23 10:20:56+00:00,2008-10-23 10:21:16+00:00,0,staypoint,False,1.0,,,2008-10-23 10:21:16+00:00,False,False
-4,2008-10-23 10:21:16+00:00,2008-10-23 10:32:35+00:00,0,tripleg,False,1.0,,,2008-10-23 10:32:35+00:00,False,False
-4,2008-10-23 10:32:35+00:00,2008-10-23 10:33:20+00:00,0,staypoint,False,1.0,,,2008-10-23 10:33:20+00:00,False,False
-5,2008-10-23 10:33:20+00:00,2008-10-23 10:45:46+00:00,0,tripleg,False,1.0,,,2008-10-23 10:45:46+00:00,True,False
-5,2008-10-23 10:45:46+00:00,2008-10-23 11:08:22+00:00,0,staypoint,True,,1.0,2.0,2008-10-23 11:08:22+00:00,False,False
-6,2008-10-23 11:08:22+00:00,2008-10-23 11:11:02+00:00,0,tripleg,False,2.0,,,2008-10-23 11:11:02+00:00,False,False
-6,2008-10-23 11:11:02+00:00,2008-10-23 11:11:12+00:00,0,staypoint,False,2.0,,,2008-10-23 11:11:12+00:00,False,False
-7,2008-10-23 11:11:12+00:00,2008-10-24 02:15:19+00:00,0,tripleg,False,2.0,,,2008-10-24 02:15:19+00:00,False,False
-7,2008-10-24 02:15:19+00:00,2008-10-24 02:15:29+00:00,0,staypoint,False,2.0,,,2008-10-24 02:15:29+00:00,False,False
-8,2008-10-24 02:15:29+00:00,2008-10-24 02:22:49+00:00,0,tripleg,False,2.0,,,2008-10-24 02:22:49+00:00,True,False
-8,2008-10-24 02:22:49+00:00,2008-10-24 02:29:21+00:00,0,staypoint,True,,2.0,3.0,2008-10-24 02:29:26+00:00,False,False
-9,2008-10-24 02:29:26+00:00,2008-10-24 02:29:26+00:00,0,staypoint,False,3.0,,,2008-10-24 02:29:26+00:00,False,False
-9,2008-10-24 02:29:26+00:00,2008-10-24 02:47:06+00:00,0,tripleg,False,3.0,,,2008-10-23 05:53:05+00:00,False,True
-10,2008-10-23 05:53:05+00:00,2008-10-23 06:01:47+00:00,1,tripleg,False,4.0,,,2008-10-23 06:01:47+00:00,False,False
-10,2008-10-23 06:01:47+00:00,2008-10-23 06:01:57+00:00,1,staypoint,False,4.0,,,2008-10-23 06:01:57+00:00,False,False
-11,2008-10-23 06:01:57+00:00,2008-10-23 11:10:24+00:00,1,tripleg,False,4.0,,,2008-10-23 11:10:24+00:00,False,False
-11,2008-10-23 11:10:24+00:00,2008-10-23 11:10:29+00:00,1,staypoint,False,4.0,,,2008-10-23 11:10:29+00:00,False,False
-12,2008-10-23 11:10:29+00:00,2008-10-23 11:49:53+00:00,1,tripleg,False,4.0,,,2008-10-23 11:49:53+00:00,True,False
-12,2008-10-23 11:49:53+00:00,2008-10-23 23:43:41+00:00,1,staypoint,True,,4.0,5.0,2008-10-23 23:43:41+00:00,False,False
-13,2008-10-23 23:43:41+00:00,2008-10-24 00:15:00+00:00,1,tripleg,False,5.0,,,2008-10-24 00:15:00+00:00,False,False
-13,2008-10-24 00:15:00+00:00,2008-10-24 00:15:00+00:00,1,staypoint,False,5.0,,,2008-10-24 00:15:00+00:00,False,False
-14,2008-10-24 00:15:00+00:00,2008-10-24 00:23:08+00:00,1,tripleg,False,5.0,,,2008-10-24 00:23:08+00:00,False,False
-14,2008-10-24 00:23:08+00:00,2008-10-24 00:23:18+00:00,1,staypoint,False,5.0,,,2008-10-24 00:23:18+00:00,False,False
-15,2008-10-24 00:23:18+00:00,2008-10-24 02:02:51+00:00,1,tripleg,False,5.0,,,2008-10-24 02:02:51+00:00,False,False
-15,2008-10-24 02:02:51+00:00,2008-10-24 02:03:11+00:00,1,staypoint,False,5.0,,,2008-10-24 02:03:11+00:00,False,False
-16,2008-10-24 02:03:11+00:00,2008-10-24 02:31:37+00:00,1,tripleg,False,5.0,,,2008-10-24 02:31:37+00:00,False,False
-16,2008-10-24 02:31:37+00:00,2008-10-24 02:32:37+00:00,1,staypoint,False,5.0,,,2008-10-24 02:32:37+00:00,False,False
-17,2008-10-24 02:32:37+00:00,2008-10-24 03:26:35+00:00,1,tripleg,False,5.0,,,2008-10-24 03:26:35+00:00,False,False
-17,2008-10-24 03:26:35+00:00,2008-10-24 03:29:40+00:00,1,staypoint,False,5.0,,,2008-10-24 03:33:15+00:00,True,False
-18,2008-10-24 03:33:15+00:00,2008-10-24 03:46:20+00:00,1,staypoint,True,,5.0,6.0,2008-10-24 03:46:20+00:00,False,False
-18,2008-10-24 03:46:20+00:00,2008-10-24 04:00:18+00:00,1,tripleg,False,6.0,,,2008-10-24 04:00:18+00:00,True,False
-19,2008-10-24 04:00:18+00:00,2008-10-24 04:07:51+00:00,1,staypoint,True,,6.0,7.0,2008-10-24 04:07:51+00:00,False,False
-19,2008-10-24 04:07:51+00:00,2008-10-24 04:12:55+00:00,1,tripleg,False,7.0,,,2008-10-24 04:12:55+00:00,False,False
-20,2008-10-24 04:12:55+00:00,2008-10-24 04:13:35+00:00,1,staypoint,False,7.0,,,2008-10-24 04:13:35+00:00,False,False
-20,2008-10-24 04:13:35+00:00,2008-10-24 05:39:53+00:00,1,tripleg,False,7.0,,,2008-10-24 05:39:53+00:00,False,False
-21,2008-10-24 05:39:53+00:00,2008-10-24 05:40:23+00:00,1,staypoint,False,7.0,,,2008-10-24 05:40:23+00:00,False,False
-21,2008-10-24 05:40:23+00:00,2008-10-24 06:35:50+00:00,1,tripleg,False,7.0,,,,,False
diff --git a/tests/data/geolife_long/trips.csv b/tests/data/geolife_long/trips.csv
index 6d3dc29..6a4ea07 100644
--- a/tests/data/geolife_long/trips.csv
+++ b/tests/data/geolife_long/trips.csv
@@ -1,9 +1,15 @@
 id,user_id,started_at,finished_at,origin_staypoint_id,destination_staypoint_id
-0,0,2008-10-23 02:53:04+00:00,2008-10-23 09:55:31+00:00,,2.0
-1,0,2008-10-23 10:02:29+00:00,2008-10-23 10:45:46+00:00,2.0,5.0
-2,0,2008-10-23 11:08:22+00:00,2008-10-24 02:22:49+00:00,5.0,8.0
-3,0,2008-10-24 02:29:26+00:00,2008-10-24 02:47:06+00:00,8.0,
-4,1,2008-10-23 05:53:05+00:00,2008-10-23 11:49:53+00:00,,12.0
-5,1,2008-10-23 23:43:41+00:00,2008-10-24 03:29:40+00:00,12.0,18.0
-6,1,2008-10-24 03:46:20+00:00,2008-10-24 04:00:18+00:00,18.0,19.0
-7,1,2008-10-24 04:07:51+00:00,2008-10-24 06:35:50+00:00,19.0,
+0,0,2008-10-23 02:53:04+00:00,2008-10-23 03:05:00+00:00,,0.0
+1,0,2008-10-23 04:08:07+00:00,2008-10-23 04:34:37+00:00,0.0,1.0
+2,0,2008-10-23 09:42:25+00:00,2008-10-23 10:45:41+00:00,1.0,5.0
+3,0,2008-10-23 11:09:22+00:00,2008-10-23 11:10:57+00:00,5.0,6.0
+4,0,2008-10-24 02:09:59+00:00,2008-10-24 02:47:06+00:00,6.0,
+5,1,2008-10-23 05:53:05+00:00,2008-10-23 06:01:42+00:00,,10.0
+6,1,2008-10-23 10:32:53+00:00,2008-10-23 11:10:19+00:00,10.0,11.0
+7,1,2008-10-23 11:49:08+00:00,2008-10-23 11:49:48+00:00,11.0,12.0
+8,1,2008-10-23 23:43:46+00:00,2008-10-24 00:23:03+00:00,12.0,14.0
+9,1,2008-10-24 01:45:41+00:00,2008-10-24 02:02:46+00:00,14.0,15.0
+10,1,2008-10-24 02:28:19+00:00,2008-10-24 02:31:32+00:00,15.0,16.0
+11,1,2008-10-24 03:16:35+00:00,2008-10-24 04:12:50+00:00,16.0,20.0
+12,1,2008-10-24 05:28:05+00:00,2008-10-24 05:39:50+00:00,20.0,21.0
+13,1,2008-10-24 06:08:42+00:00,2008-10-24 06:35:50+00:00,21.0,
diff --git a/tests/io/test_dataset_reader.py b/tests/io/test_dataset_reader.py
index adcf362..fda22d5 100644
--- a/tests/io/test_dataset_reader.py
+++ b/tests/io/test_dataset_reader.py
@@ -18,7 +18,7 @@ def read_geolife_triplegs_with_modes(read_geolife_modes):
     pfs, labels = read_geolife_modes
     pfs, spts = pfs.as_positionfixes.generate_staypoints(method='sliding',
                                                          dist_threshold=25,
-                                                         time_threshold=5 * 60)
+                                                         time_threshold=5)
     _, tpls = pfs.as_positionfixes.generate_triplegs(spts, method='between_staypoints')
 
     return tpls, labels
diff --git a/tests/model/test_triplegs.py b/tests/model/test_triplegs.py
index c410504..615a74f 100644
--- a/tests/model/test_triplegs.py
+++ b/tests/model/test_triplegs.py
@@ -9,7 +9,7 @@ import trackintel as ti
 def testdata_tpls():
     """Read triplegs test data from files."""
     pfs, _ = ti.io.dataset_reader.read_geolife(os.path.join("tests", "data", "geolife"))
-    pfs, stps = pfs.as_positionfixes.generate_staypoints(method="sliding", dist_threshold=25, time_threshold=5 * 60)
+    pfs, stps = pfs.as_positionfixes.generate_staypoints(method="sliding", dist_threshold=25, time_threshold=5)
     _, tpls = pfs.as_positionfixes.generate_triplegs(stps, method="between_staypoints")
         
     return tpls
diff --git a/tests/preprocessing/test_positionfixes.py b/tests/preprocessing/test_positionfixes.py
index 8efcfd0..878d21a 100644
--- a/tests/preprocessing/test_positionfixes.py
+++ b/tests/preprocessing/test_positionfixes.py
@@ -1,7 +1,6 @@
 import datetime
 import os
 import sys
-from math import radians
 
 import geopandas as gpd
 from geopandas.testing import assert_geodataframe_equal
@@ -9,144 +8,124 @@ from geopandas.testing import assert_geodataframe_equal
 import numpy as np
 import pandas as pd
 import pytest
-from shapely.geometry import Point
-from sklearn.cluster import DBSCAN
 
 import trackintel as ti
-from trackintel.geogr.distances import haversine_dist
-
 
 @pytest.fixture
-def pfs_geolife():
-    pfs, _ = ti.io.dataset_reader.read_geolife(os.path.join('tests', 'data', 'geolife'))
-    return pfs
-
-
-@pytest.fixture
-def pfs_geolife_long():
+def geolife_pfs_stps_long():
+    """Read geolife_long and generate stps."""
     pfs, _ = ti.io.dataset_reader.read_geolife(os.path.join('tests', 'data', 'geolife_long'))
-    return pfs
-
-
-@pytest.fixture
-def geolife_pfs_stps_short(pfs_geolife):
-    pfs, stps = pfs_geolife.as_positionfixes.generate_staypoints(method='sliding',
-                                                                 dist_threshold=25,
-                                                                 time_threshold=5 * 60)
-    return pfs, stps
-
-
-@pytest.fixture
-def geolife_pfs_stps_long(pfs_geolife_long):
-    pfs, stps = pfs_geolife_long.as_positionfixes.generate_staypoints(method='sliding',
-                                                                      dist_threshold=25,
-                                                                      time_threshold=5 * 60)
+    pfs, stps = pfs.as_positionfixes.generate_staypoints(method='sliding', dist_threshold=25, time_threshold=5)
     return pfs, stps
 
 
-@pytest.fixture
-def testdata_tpls_geolife():
-    tpls_file = os.path.join('tests', 'data', 'geolife', 'geolife_triplegs_short.csv')
-    tpls = ti.read_triplegs_csv(tpls_file, tz='utc', index_col='id')
-    tpls.geometry = tpls.geometry.set_crs(epsg=4326)
-    return tpls
-
-
-@pytest.fixture
-def testdata_pfs_ids_geolife():
-    pfs_file = os.path.join('tests', 'data', 'geolife', 'geolife_positionfixes_with_ids.csv')
-    pfs = ti.read_positionfixes_csv(pfs_file, index_col='id')
-    pfs['staypoint_id'] = pfs['staypoint_id'].astype('Int64')
-    pfs['tripleg_id'] = pfs['tripleg_id'].astype('Int64')
-    pfs.geometry = pfs.geometry.set_crs(epsg=4326)
-    return pfs
-
-
 class TestGenerate_staypoints():
-    def test_generate_staypoints_sliding_min(self):
-        pfs_file = os.path.join('tests', 'data', 'positionfixes.csv')
-        pfs = ti.read_positionfixes_csv(pfs_file, sep=';', tz='utc', index_col='id')
-        pfs, stps = pfs.as_positionfixes.generate_staypoints(method='sliding', dist_threshold=0, time_threshold=0)
-        assert len(stps) == len(pfs), "With small thresholds, staypoint extraction should yield each positionfix"
-
-    def test_generate_staypoints_sliding_max(self):
-        pfs_file = os.path.join('tests', 'data', 'positionfixes.csv')
-        pfs = ti.read_positionfixes_csv(pfs_file, sep=';', tz='utc', index_col='id')
+    """Tests for generate_staypoints() method."""
+    
+    def test_sliding_min(self):
+        """Test if using small thresholds, stp extraction yields each pfs."""
+        pfs, _ = ti.io.dataset_reader.read_geolife(os.path.join('tests', 'data', 'geolife'))
+        pfs, stps = pfs.as_positionfixes.generate_staypoints(method='sliding', 
+                                                             dist_threshold=0, 
+                                                             time_threshold=0, 
+                                                             include_last=True)
+        assert len(stps) == len(pfs)
+
+    def test_sliding_max(self):
+        """Test if using large thresholds, stp extraction yield no pfs."""
+        pfs, _ = ti.io.dataset_reader.read_geolife(os.path.join('tests', 'data', 'geolife'))
         _, stps = pfs.as_positionfixes.generate_staypoints(method='sliding',
                                                            dist_threshold=sys.maxsize,
                                                            time_threshold=sys.maxsize)
-        assert len(stps) == 0, "With large thresholds, staypoint extraction should not yield positionfixes"
+        assert len(stps) == 0
 
-    def test_generate_staypoints_missing_link(self, geolife_pfs_stps_long):
+    def test_missing_link(self):
         """Test nan is assigned for missing link between pfs and stps."""
-        pfs_file = os.path.join('tests', 'data', 'positionfixes.csv')
-        pfs = ti.read_positionfixes_csv(pfs_file, sep=';', tz='utc', index_col='id')
+        pfs, _ = ti.io.dataset_reader.read_geolife(os.path.join('tests', 'data', 'geolife'))
         pfs, _ = pfs.as_positionfixes.generate_staypoints(method='sliding',
                                                           dist_threshold=sys.maxsize,
                                                           time_threshold=sys.maxsize)
 
         assert pd.isna(pfs['staypoint_id']).any()
 
-    def test_generate_staypoints_dtype_consistent(self):
+    def test_dtype_consistent(self, geolife_pfs_stps_long):
         """Test the dtypes for the generated columns."""
-        pfs_file = os.path.join('tests', 'data', 'positionfixes.csv')
-        pfs = ti.read_positionfixes_csv(pfs_file, sep=';', tz='utc', index_col='id')
-        pfs, stps = pfs.as_positionfixes.generate_staypoints(method='sliding',
-                                                             dist_threshold=25,
-                                                             time_threshold=5 * 60)
+        pfs, stps = geolife_pfs_stps_long
+        
         assert pfs['user_id'].dtype == stps['user_id'].dtype
         assert pfs['staypoint_id'].dtype == "Int64"
         assert stps.index.dtype == "int64"
 
-    def test_generate_staypoints_index_start(self):
+    def test_index_start(self, geolife_pfs_stps_long):
         """Test the generated index start from 0 for different methods."""
-        pfs_file = os.path.join('tests', 'data', 'positionfixes.csv')
-        pfs_ori = ti.read_positionfixes_csv(pfs_file, sep=';', tz='utc', index_col='id')
-
-        _, stps_sliding = pfs_ori.as_positionfixes.generate_staypoints(method='sliding',
-                                                                       dist_threshold=25,
-                                                                       time_threshold=300)
-        _, stps_dbscan = pfs_ori.as_positionfixes.generate_staypoints(method='dbscan')
-
-        assert (stps_sliding.index == np.arange(len(stps_sliding))).any()
-        assert (stps_dbscan.index == np.arange(len(stps_dbscan))).any()
-
-    def test_generate_staypoints_groupby_sliding(self):
-        """Test the 'sliding' result obtained using user_id for loop (previous) with groupby.apply (current)."""
-        pfs_file = os.path.join('tests', 'data', 'positionfixes.csv')
-        pfs_ori = ti.read_positionfixes_csv(pfs_file, sep=';', tz='utc', index_col='id')
-
-        # stps detection using groupby
-        pfs_groupby, stps_groupby = pfs_ori.as_positionfixes.generate_staypoints(method='sliding',
-                                                                                 dist_threshold=25,
-                                                                                 time_threshold=300)
-        # stps detection using for loop
-        pfs_for, stps_for = _generate_staypoints_original(pfs_ori,
-                                                          method='sliding',
-                                                          dist_threshold=25,
-                                                          time_threshold=300)
-
-        pd.testing.assert_frame_equal(stps_groupby, stps_for, check_dtype=False)
-        pd.testing.assert_frame_equal(pfs_groupby, pfs_for, check_dtype=False)
-
-    def test_generate_staypoints_groupby_dbscan(self):
-        """Test the 'dbscan' result obtained using user_id for loop (previous) with groupby.apply (current)."""
-        pfs_file = os.path.join('tests', 'data', 'positionfixes.csv')
-        pfs_ori = ti.read_positionfixes_csv(pfs_file, sep=';', tz='utc', index_col='id')
-
-        # stps detection using groupby
-        pfs_groupby, stps_groupby = pfs_ori.as_positionfixes.generate_staypoints(method='dbscan')
-        # stps detection using for loop
-        pfs_for, stps_for = _generate_staypoints_original(pfs_ori, method='dbscan')
-
-        pd.testing.assert_frame_equal(stps_groupby, stps_for, check_dtype=False)
-        pd.testing.assert_frame_equal(pfs_groupby, pfs_for, check_dtype=False)
-
+        _, stps = geolife_pfs_stps_long
+
+        assert (stps.index == np.arange(len(stps))).any()
+
+    def test_include_last(self):
+        """Test if the include_last arguement will include the last pfs as stp."""
+        pfs, _ = ti.io.dataset_reader.read_geolife(os.path.join('tests', 'data', 'geolife'))
+
+        pfs_wo, stps_wo = pfs.as_positionfixes.generate_staypoints(method='sliding',
+                                                           dist_threshold=100,
+                                                           time_threshold=5.0,
+                                                           include_last=False)
+        pfs_include, stps_include = pfs.as_positionfixes.generate_staypoints(method='sliding',
+                                                           dist_threshold=100,
+                                                           time_threshold=5.0,
+                                                           include_last=True)
+        # stps_wo does not include the last staypoint
+        assert len(stps_wo) == len(stps_include) - 1
+        # the last pfs of pfs_include has stp connection
+        assert not pfs_include.tail(1)['staypoint_id'].isna().all()
+        assert pfs_wo.tail(1)['staypoint_id'].isna().all()
+        
+    def test_print_progress(self):
+        """Test if the result from print progress agrees with the original."""
+        pfs, _ = ti.io.dataset_reader.read_geolife(os.path.join('tests', 'data', 'geolife'))
+        pfs_ori, stps_ori = pfs.as_positionfixes.generate_staypoints(method='sliding', 
+                                                             dist_threshold=100, 
+                                                             time_threshold=5)
+        pfs_print, stps_print = pfs.as_positionfixes.generate_staypoints(method='sliding', 
+                                                             dist_threshold=100, 
+                                                             time_threshold=5,
+                                                             print_progress=True)
+        assert_geodataframe_equal(pfs_ori, pfs_print)
+        assert_geodataframe_equal(stps_ori, stps_print)
+        
+    def test_temporal(self):
+        """Test if the stps generation result follows predefined time_threshold and gap_threshold."""
+        pfs_input, _ = ti.io.dataset_reader.read_geolife(os.path.join('tests', 'data', 'geolife_long'))
+        
+        # the duration should be not longer than time_threshold
+        time_threshold_ls = [3, 5, 10]
+        for time_threshold in time_threshold_ls:
+            _, stps = pfs_input.as_positionfixes.generate_staypoints(method='sliding', 
+                                                                dist_threshold=50, 
+                                                                time_threshold=time_threshold)
+
+            duration_stps_min = (stps['finished_at'] - stps['started_at']).dt.total_seconds() / 60
+            # all durations should be longer than the time_threshold
+            assert (duration_stps_min > time_threshold).all()
+        
+        # the missing time should not exceed gap_threshold
+        gap_threshold_ls = [10, 15, 20]
+        for gap_threshold in gap_threshold_ls:
+            pfs, _ = pfs_input.as_positionfixes.generate_staypoints(method='sliding', 
+                                                                dist_threshold=50, 
+                                                                time_threshold=time_threshold,
+                                                                gap_threshold=gap_threshold)
+            # get the difference between pfs tracking time, and assign back to the previous pfs
+            pfs["diff"] = ((pfs['tracked_at'] - pfs['tracked_at'].shift(1)).dt.total_seconds() / 60).shift(-1)
+            # get the last pf of stps and check the gap size
+            pfs.dropna(subset=["staypoint_id"], inplace=True)
+            pfs.drop_duplicates(subset=["staypoint_id"], keep='last', inplace=True)
+            # all last pfs should be shorter than the gap_threshold
+            assert (pfs["diff"]<gap_threshold).all()
+        
 
 class TestGenerate_triplegs:
     """Tests for generate_triplegs() method."""
-    
-    # TODO: add test for temporal gap
 
     def test_user_without_stps(self, geolife_pfs_stps_long):
         """Check if it is safe to have users that have pfs but no stps."""
@@ -174,6 +153,7 @@ class TestGenerate_triplegs:
         _, tpls_case1 = pfs.as_positionfixes.generate_triplegs(stps, method="between_staypoints")
         # only keep pfs where staypoint id is nan
         pfs_nostps = pfs[pd.isna(pfs["staypoint_id"])].drop(columns="staypoint_id")
+        print(pfs_nostps)
         _, tpls_case2 = pfs_nostps.as_positionfixes.generate_triplegs(stps, method="between_staypoints")
 
         assert_geodataframe_equal(tpls_case1, tpls_case2)
@@ -228,11 +208,9 @@ class TestGenerate_triplegs:
         assert_geodataframe_equal(pfs_ori.reset_index(drop=True), pfs_index.reset_index(drop=True))
         assert_geodataframe_equal(tpls_ori, tpls_index)
 
-    def test_dtype_consistent(self, pfs_geolife):
+    def test_dtype_consistent(self, geolife_pfs_stps_long):
         """Test the dtypes for the generated columns."""
-        pfs, stps = pfs_geolife.as_positionfixes.generate_staypoints(
-            method="sliding", dist_threshold=25, time_threshold=5 * 60
-        )
+        pfs, stps = geolife_pfs_stps_long
         pfs, tpls = pfs.as_positionfixes.generate_triplegs(stps)
         assert pfs["user_id"].dtype == tpls["user_id"].dtype
         assert pfs["tripleg_id"].dtype == "Int64"
@@ -265,10 +243,26 @@ class TestGenerate_triplegs:
         with pytest.raises(AttributeError, match="Method unknown"):
             pfs.as_positionfixes.generate_triplegs(stps, method=12345)
 
-    def test_stps_tpls_overlap(self, pfs_geolife_long):
+    def test_temporal(self, geolife_pfs_stps_long):
+        """Test if the tpls generation result follows predefined gap_threshold."""
+        pfs_input, stps = geolife_pfs_stps_long
+        
+        gap_threshold_ls = [0.1, 0.2, 1, 2]
+        for gap_threshold in gap_threshold_ls:
+            pfs, _ = pfs_input.as_positionfixes.generate_triplegs(stps, gap_threshold=gap_threshold)
+            
+            # conti_tpl checks whether the next pfs is in the same tpl
+            pfs["conti_tpl"] = (pfs['tripleg_id'] - pfs['tripleg_id'].shift(1)).shift(-1)
+            # get the time difference of pfs, and assign to the previous pfs
+            pfs["diff"] = ((pfs['tracked_at'] - pfs['tracked_at'].shift(1)).dt.total_seconds() / 60).shift(-1)
+            # we only take tpls that are splitted in the middle (tpl - tpl) and the second user
+            pfs = pfs.loc[(pfs["conti_tpl"] == 1) & (pfs["user_id"] == 1)]
+            # check if the cuts are appropriate 
+            assert (pfs['diff'] > gap_threshold).all()
+            
+    def test_stps_tpls_overlap(self, geolife_pfs_stps_long):
         """Tpls and spts should not overlap when generated using the default extract triplegs method."""
-        pfs = pfs_geolife_long
-        pfs, stps = pfs.as_positionfixes.generate_staypoints(method="sliding", dist_threshold=25, time_threshold=5 * 60)
+        pfs, stps = geolife_pfs_stps_long
         pfs, tpls = pfs.as_positionfixes.generate_triplegs(stps)
 
         stps = stps[["started_at", "finished_at", "user_id"]]
@@ -283,148 +277,4 @@ class TestGenerate_triplegs:
             diff = diff.values[1:]
 
             # all values have to greater or equal to zero. Otherwise there is an overlap
-            assert all(diff >= np.timedelta64(datetime.timedelta()))
-
-
-def _generate_staypoints_original(positionfixes, method='sliding',
-                                  dist_threshold=50, time_threshold=300, epsilon=100,
-                                  dist_func=haversine_dist, num_samples=1):
-    """
-    Original function using 'user_id' for-loop to generate staypoints based on pfs.
-    
-    Used for comparing with the current groupby.apply() method.
-    """
-    # copy the original pfs for adding 'staypoint_id' column
-    ret_pfs = positionfixes.copy()
-    ret_pfs.sort_values(by='user_id', inplace=True)
-
-    elevation_flag = 'elevation' in ret_pfs.columns  # if there is elevation data
-
-    name_geocol = ret_pfs.geometry.name
-    ret_stps = pd.DataFrame(columns=['id', 'user_id', 'started_at', 'finished_at', 'geom'])
-
-    if method == 'sliding':
-        # Algorithm from Li et al. (2008). For details, please refer to the paper.
-        staypoint_id_counter = 0
-        ret_pfs['staypoint_id'] = np.nan  # this marks all that are not part of a SP
-
-        for user_id_this in ret_pfs['user_id'].unique():
-
-            positionfixes_user_this = ret_pfs.loc[ret_pfs['user_id'] == user_id_this]  # this is no copy
-
-            positionfixes_user_this = positionfixes_user_this.sort_values('tracked_at')
-            pfs = positionfixes_user_this.to_dict('records')
-            idx = positionfixes_user_this.index.to_list()
-            num_pfs = len(pfs)
-
-            posfix_staypoint_matching = {}
-
-            i = 0
-            j = 0  # is zero because it gets incremented in the beginning
-            while i < num_pfs:
-                if j == num_pfs:
-                    # We're at the end, this can happen if in the last "bin", 
-                    # the dist_threshold is never crossed anymore.
-                    break
-                else:
-                    j = i + 1
-                while j < num_pfs:
-                    # TODO: Can we make distance function independent of projection?
-                    dist = dist_func(pfs[i][name_geocol].x, pfs[i][name_geocol].y,
-                                     pfs[j][name_geocol].x, pfs[j][name_geocol].y)
-
-                    if dist > dist_threshold:
-                        delta_t = pfs[j]['tracked_at'] - pfs[i]['tracked_at']
-                        if delta_t.total_seconds() > time_threshold:
-                            staypoint = {}
-                            staypoint['user_id'] = pfs[i]['user_id']
-                            staypoint[name_geocol] = Point(np.mean([pfs[k][name_geocol].x for k in range(i, j)]),
-                                                           np.mean([pfs[k][name_geocol].y for k in range(i, j)]))
-                            if elevation_flag:
-                                staypoint['elevation'] = np.mean([pfs[k]['elevation'] for k in range(i, j)])
-                            staypoint['started_at'] = pfs[i]['tracked_at']
-                            staypoint['finished_at'] = pfs[j - 1]['tracked_at']
-                            staypoint['id'] = staypoint_id_counter
-
-                            # store matching 
-                            posfix_staypoint_matching[staypoint_id_counter] = [idx[k] for k in range(i, j)]
-                            staypoint_id_counter += 1
-
-                            # add staypoint
-                            ret_stps = ret_stps.append(staypoint, ignore_index=True)
-
-                            # TODO Discussion: Is this last point really a staypoint? As we don't know if the
-                            #      person "moves on" afterwards...
-                            if j == num_pfs - 1:
-                                staypoint = {}
-                                staypoint['user_id'] = pfs[j]['user_id']
-                                staypoint[name_geocol] = Point(pfs[j][name_geocol].x, pfs[j][name_geocol].y)
-                                if elevation_flag:
-                                    staypoint['elevation'] = pfs[j]['elevation']
-                                staypoint['started_at'] = pfs[j]['tracked_at']
-                                staypoint['finished_at'] = pfs[j]['tracked_at']
-                                staypoint['id'] = staypoint_id_counter
-
-                                # store matching
-                                posfix_staypoint_matching[staypoint_id_counter] = [idx[j]]
-                                staypoint_id_counter += 1
-                                ret_stps = ret_stps.append(staypoint, ignore_index=True)
-                        i = j
-                        break
-                    j = j + 1
-
-            # add matching to original positionfixes (for every user)
-
-            for staypoints_id, posfix_idlist in posfix_staypoint_matching.items():
-                # note that we use .loc because above we have saved the id 
-                # of the positionfixes not thier absolut position
-                ret_pfs.loc[posfix_idlist, 'staypoint_id'] = staypoints_id
-
-
-    elif method == 'dbscan':
-
-        db = DBSCAN(eps=epsilon / 6371000, min_samples=num_samples, algorithm='ball_tree', metric='haversine')
-
-        for user_id_this in ret_pfs['user_id'].unique():
-
-            user_positionfixes = ret_pfs[ret_pfs['user_id'] == user_id_this]  # this is not a copy!
-
-            # TODO: enable transformations to temporary (metric) system
-            transform_crs = None
-            if transform_crs is not None:
-                pass
-
-            # get staypoint matching
-            coordinates = np.array([[radians(g.y), radians(g.x)] for g in user_positionfixes[name_geocol]])
-            labels = db.fit_predict(coordinates)
-
-            # add positionfixes - staypoint matching to original positionfixes
-            ret_pfs.loc[user_positionfixes.index, 'staypoint_id'] = labels
-
-        # create staypoints as the center of the grouped positionfixes
-        grouped_df = ret_pfs.groupby(['user_id', 'staypoint_id'])
-        for combined_id, group in grouped_df:
-            user_id, staypoint_id = combined_id
-
-            if int(staypoint_id) != -1:
-                staypoint = {}
-                staypoint['user_id'] = user_id
-                staypoint['id'] = staypoint_id
-
-                # point geometry of staypoint
-                staypoint[name_geocol] = Point(group[name_geocol].x.mean(),
-                                               group[name_geocol].y.mean())
-
-                ret_stps = ret_stps.append(staypoint, ignore_index=True)
-
-    ret_stps = gpd.GeoDataFrame(ret_stps, geometry=name_geocol, crs=ret_pfs.crs)
-    ret_pfs = gpd.GeoDataFrame(ret_pfs, geometry=name_geocol, crs=ret_pfs.crs)
-
-    ## ensure dtype consistency 
-    ret_stps['id'] = ret_stps['id'].astype('int64')
-    ret_stps.set_index('id', inplace=True)
-    ret_pfs['staypoint_id'] = ret_pfs['staypoint_id'].astype('float')
-
-    ret_stps['user_id'] = ret_stps['user_id'].astype(ret_pfs['user_id'].dtype)
-
-    return ret_pfs, ret_stps
+            assert all(diff >= np.timedelta64(datetime.timedelta()))
\ No newline at end of file
diff --git a/tests/preprocessing/test_triplegs.py b/tests/preprocessing/test_triplegs.py
index 37ea5b8..02306a8 100644
--- a/tests/preprocessing/test_triplegs.py
+++ b/tests/preprocessing/test_triplegs.py
@@ -26,23 +26,23 @@ class TestSmoothen_triplegs():
         assert len(line2_smoothed.coords) == 3
 
 class TestGenerate_trips():
-    # def test_generate_trips(self):
-    #     """Test if we can generate the example trips based on example data."""
-    #     gap_threshold = 15
-    #     # load pregenerated trips
-    #     trips_loaded = ti.read_trips_csv(os.path.join('tests', 'data', 'geolife_long', 'trips.csv'), index_col='id')
-
-    #     # create trips from geolife (based on positionfixes)
-    #     pfs, _ = ti.io.dataset_reader.read_geolife(os.path.join('tests', 'data', 'geolife_long'))
-    #     pfs, stps = pfs.as_positionfixes.generate_staypoints(method='sliding', dist_threshold=25,
-    #                                                          time_threshold=5 * 60)
-    #     stps = stps.as_staypoints.create_activity_flag()
-    #     pfs, tpls = pfs.as_positionfixes.generate_triplegs(stps)
-
-    #     # generate trips and a joint staypoint/triplegs dataframe
-    #     stps, tpls, trips = ti.preprocessing.triplegs.generate_trips(stps, tpls, gap_threshold=gap_threshold, id_offset=0)
-    #     # test if generated trips are equal
-    #     pd.testing.assert_frame_equal(trips_loaded, trips)
+    """Tests for generate_trips() method."""
+    
+    def test_generate_trips(self):
+        """Test if we can generate the example trips based on example data."""
+        # load pregenerated trips
+        trips_loaded = ti.read_trips_csv(os.path.join('tests', 'data', 'geolife_long', 'trips.csv'), index_col='id')
+
+        # create trips from geolife (based on positionfixes)
+        pfs, _ = ti.io.dataset_reader.read_geolife(os.path.join('tests', 'data', 'geolife_long'))
+        pfs, stps = pfs.as_positionfixes.generate_staypoints(method='sliding', dist_threshold=25, time_threshold=5)
+        stps = stps.as_staypoints.create_activity_flag(time_threshold=15)
+        pfs, tpls = pfs.as_positionfixes.generate_triplegs(stps)
+
+        # generate trips and a joint staypoint/triplegs dataframe
+        stps, tpls, trips = ti.preprocessing.triplegs.generate_trips(stps, tpls, gap_threshold=15)
+        # test if generated trips are equal
+        pd.testing.assert_frame_equal(trips_loaded, trips)
         
     def test_generate_trips_missing_link(self):
         """Test nan is assigned for missing link between spts and trips, and tpls and trips."""
@@ -50,14 +50,12 @@ class TestGenerate_trips():
         pfs, _ = ti.io.dataset_reader.read_geolife(os.path.join('tests', 'data', 'geolife_long'))
         pfs, stps = pfs.as_positionfixes.generate_staypoints(method='sliding',
                                                              dist_threshold=25,
-                                                             time_threshold=5 * 60)
-        stps = stps.as_staypoints.create_activity_flag()
+                                                             time_threshold=5)
+        stps = stps.as_staypoints.create_activity_flag(time_threshold=15)
         pfs, tpls = pfs.as_positionfixes.generate_triplegs(stps)
 
         # generate trips and a joint staypoint/triplegs dataframe
-        stps, tpls, _ = ti.preprocessing.triplegs.generate_trips(stps, tpls,
-                                                                 gap_threshold=15,
-                                                                 id_offset=0)
+        stps, tpls, _ = ti.preprocessing.triplegs.generate_trips(stps, tpls, gap_threshold=15)
         assert pd.isna(stps['trip_id']).any()
         assert pd.isna(stps['prev_trip_id']).any()
         assert pd.isna(stps['next_trip_id']).any()
@@ -68,14 +66,12 @@ class TestGenerate_trips():
         pfs, _ = ti.io.dataset_reader.read_geolife(os.path.join('tests', 'data', 'geolife_long'))
         pfs, stps = pfs.as_positionfixes.generate_staypoints(method='sliding',
                                                              dist_threshold=25,
-                                                             time_threshold=5 * 60)
-        stps = stps.as_staypoints.create_activity_flag()
+                                                             time_threshold=5)
+        stps = stps.as_staypoints.create_activity_flag(time_threshold=15)
         pfs, tpls = pfs.as_positionfixes.generate_triplegs(stps)
 
         # generate trips and a joint staypoint/triplegs dataframe
-        stps, tpls, trips = ti.preprocessing.triplegs.generate_trips(stps, tpls,
-                                                                     gap_threshold=15,
-                                                                     id_offset=0)
+        stps, tpls, trips = ti.preprocessing.triplegs.generate_trips(stps, tpls, gap_threshold=15)
         
         assert stps['user_id'].dtype == trips['user_id'].dtype
         assert trips.index.dtype == "int64"
@@ -90,14 +86,12 @@ class TestGenerate_trips():
         pfs, _ = ti.io.dataset_reader.read_geolife(os.path.join('tests', 'data', 'geolife_long'))
         pfs, stps = pfs.as_positionfixes.generate_staypoints(method='sliding',
                                                              dist_threshold=25,
-                                                             time_threshold=5 * 60)
-        stps = stps.as_staypoints.create_activity_flag()
+                                                             time_threshold=5)
+        stps = stps.as_staypoints.create_activity_flag(time_threshold=15)
         pfs, tpls = pfs.as_positionfixes.generate_triplegs(stps)
         
         # generate trips and a joint staypoint/triplegs dataframe
-        _, _, trips = ti.preprocessing.triplegs.generate_trips(stps, tpls,
-                                                               gap_threshold=15, 
-                                                               id_offset=0)
+        _, _, trips = ti.preprocessing.triplegs.generate_trips(stps, tpls, gap_threshold=15)
         
         assert (trips.index == np.arange(len(trips))).any()
         
@@ -146,9 +140,7 @@ class TestGenerate_trips():
         stps_tpls_loaded['finished_at'] = pd.to_datetime(stps_tpls_loaded['finished_at'], utc=True)
 
         # generate trips and a joint staypoint/triplegs dataframe
-        stps_proc, tpls_proc, trips = ti.preprocessing.triplegs.generate_trips(stps_in, tpls_in,
-                                                                               gap_threshold=15,
-                                                                               id_offset=0)
+        stps_proc, tpls_proc, trips = ti.preprocessing.triplegs.generate_trips(stps_in, tpls_in, gap_threshold=15)
         spts_tpls = _create_debug_spts_tpls_data(stps_proc, tpls_proc, gap_threshold=gap_threshold)
 
         # test if generated trips are equal
@@ -157,36 +149,30 @@ class TestGenerate_trips():
         # test if generated staypoints/triplegs are equal (especially important for trip ids)
         pd.testing.assert_frame_equal(stps_tpls_loaded, spts_tpls, check_dtype=False)
         
-    # def test_generate_trips_id_management(self):
-    #     """
-    #     Test if we can generate the example trips based on example data
-    #     """
-    #     gap_threshold = 15
+    def test_generate_trips_id_management(self):
+        """Test if we can generate the example trips based on example data."""
+        stps_tpls_loaded = pd.read_csv(os.path.join('tests', 'data', 'geolife_long', 'stps_tpls.csv'), index_col='id')
+        stps_tpls_loaded['started_at'] = pd.to_datetime(stps_tpls_loaded['started_at'])
+        stps_tpls_loaded['started_at_next'] = pd.to_datetime(stps_tpls_loaded['started_at_next'])
+        stps_tpls_loaded['finished_at'] = pd.to_datetime(stps_tpls_loaded['finished_at'])
 
-    #     stps_tpls_loaded = pd.read_csv(os.path.join('tests', 'data', 'geolife_long', 'tpls_spts.csv'), index_col='id')
-    #     stps_tpls_loaded['started_at'] = pd.to_datetime(stps_tpls_loaded['started_at'])
-    #     stps_tpls_loaded['started_at_next'] = pd.to_datetime(stps_tpls_loaded['started_at_next'])
-    #     stps_tpls_loaded['finished_at'] = pd.to_datetime(stps_tpls_loaded['finished_at'])
-
-    #     # create trips from geolife (based on positionfixes)
-    #     pfs, _ = ti.io.dataset_reader.read_geolife(os.path.join('tests', 'data', 'geolife_long'))
-    #     pfs, stps = pfs.as_positionfixes.generate_staypoints(method='sliding', dist_threshold=25, time_threshold=5 * 60)
-    #     stps = stps.as_staypoints.create_activity_flag()
-    #     pfs, tpls = pfs.as_positionfixes.generate_triplegs(stps)
+        # create trips from geolife (based on positionfixes)
+        pfs, _ = ti.io.dataset_reader.read_geolife(os.path.join('tests', 'data', 'geolife_long'))
+        pfs, stps = pfs.as_positionfixes.generate_staypoints(method='sliding', dist_threshold=25, time_threshold=5)
+        stps = stps.as_staypoints.create_activity_flag(time_threshold=15)
+        pfs, tpls = pfs.as_positionfixes.generate_triplegs(stps)
 
-    #     # generate trips and a joint staypoint/triplegs dataframe
-    #     stps, tpls, _ = ti.preprocessing.triplegs.generate_trips(stps, tpls, gap_threshold=gap_threshold, id_offset=0)
-    #     spts_tpls = _create_debug_spts_tpls_data(stps, tpls, gap_threshold=gap_threshold)
+        # generate trips and a joint staypoint/triplegs dataframe
+        gap_threshold = 15
+        stps, tpls, _ = ti.preprocessing.triplegs.generate_trips(stps, tpls, gap_threshold=gap_threshold)
+        spts_tpls = _create_debug_spts_tpls_data(stps, tpls, gap_threshold=gap_threshold)
 
-    #     # test if generated staypoints/triplegs are equal (especially important for trip ids)
-    #     pd.testing.assert_frame_equal(stps_tpls_loaded, spts_tpls, check_dtype=False)
+        # test if generated staypoints/triplegs are equal (especially important for trip ids)
+        pd.testing.assert_frame_equal(stps_tpls_loaded, spts_tpls, check_dtype=False)
 
 
 def _create_debug_spts_tpls_data(stps, tpls, gap_threshold):
-    """Helper function for "test_generate_trips_*."""
-    stps = stps.copy()
-    tpls = tpls.copy()
-
+    """Preprocess stps and tpls for "test_generate_trips_*."""
     # create table with relevant information from triplegs and staypoints.
     tpls['type'] = 'tripleg'
     stps['type'] = 'staypoint'
diff --git a/tests/visualization/test_modal_split.py b/tests/visualization/test_modal_split.py
index 36bde87..5f48bcb 100644
--- a/tests/visualization/test_modal_split.py
+++ b/tests/visualization/test_modal_split.py
@@ -12,11 +12,11 @@ from trackintel.visualization.modal_split import plot_modal_split
 
 @pytest.fixture
 def get_geolife_triplegs_with_modes():
-    """Get modal split for a small part of the geolife dataset"""
+    """Get modal split for a small part of the geolife dataset."""
     pfs, labels = read_geolife(os.path.join('tests', 'data', 'geolife_modes'))
     pfs, spts = pfs.as_positionfixes.generate_staypoints(method='sliding',
                                                          dist_threshold=25,
-                                                         time_threshold=5 * 60)
+                                                         time_threshold=5)
     _, tpls = pfs.as_positionfixes.generate_triplegs(spts, method='between_staypoints')
 
     tpls_with_modes = geolife_add_modes_to_triplegs(tpls, labels)
@@ -25,7 +25,7 @@ def get_geolife_triplegs_with_modes():
 
 @pytest.fixture
 def get_test_triplegs_with_modes():
-    """get modal split for randomly generated data"""
+    """Get modal split for randomly generated data."""
     n = 200
     day_1_h1 = pd.Timestamp('1970-01-01 00:00:00', tz='utc')
     one_day = datetime.timedelta(days=1)