Repository: mie-lab/trackintel (python)

Issue:
Remove wildcard imports from __init__.py files
We should remove Wildcard imports from the \_\_init\_\_.py files. [Example from trackintel](https://github.com/mie-lab/trackintel/blob/master/trackintel/analysis/__init__.py)

Reasons:

[Official python documentation](https://docs.python.org/3/tutorial/modules.html)
>This imports all names except those beginning with an underscore (_). In most cases Python programmers do not use this facility since it introduces an unknown set of names into the interpreter, possibly hiding some things you have already defined.

>Note that in general the practice of importing * from a module or package is frowned upon, since it often causes poorly readable code. However, it is okay to use it to save typing in interactive sessions.

[PEP8](https://www.python.org/dev/peps/pep-0008/#imports)
>Wildcard imports (from <module> import *) should be avoided, as they make it unclear which names are present in the namespace, confusing both readers and many automated tools. There is one defensible use case for a wildcard import, which is to republish an internal interface as part of a public API (for example, overwriting a pure Python implementation of an interface with the definitions from an optional accelerator module and exactly which definitions will be overwritten isn't known in advance).

[geopandas](https://geopandas.readthedocs.io/en/latest/community/contributing.html#contributing-to-geopandas)
> Imports should be grouped with standard library imports first, 3rd-party libraries next, and GeoPandas imports third. Within each grouping, imports should be alphabetized. *Always use absolute imports when possible*, and explicit relative imports for local imports when necessary in tests.

[geopandas \_\_init\_\_.py example](https://github.com/geopandas/geopandas/blob/master/geopandas/tools/__init__.py)

Pull request description:
ENH: Fix init.py and label module
closes #242

- the imports of read functions (e.g., `from trackintel.io.file import read_positionfixes_csv`) in `trackintel/__init__.py` ensures we can directly call `ti.read_positionfixes_csv()` instead of going into the IO module (e.g., `ti.io.file.read_positionfixes_csv()`). I am doing this because many of our test functions use this, but of course, we can delete this shortcut
- the `__all__` ensures that if someone calls, e.g., `from ti.analysis import *`, still only the function defined in `__all__` would be imported.

Also, the module `label `is now renamed to `labelling`

Patch:
diff --git a/docs/modules/analysis.rst b/docs/modules/analysis.rst
index 49b95e5..9803348 100644
--- a/docs/modules/analysis.rst
+++ b/docs/modules/analysis.rst
@@ -4,12 +4,12 @@ Analysis
 The analysis module provides a variety of functions to analyze the mobility
 datasets computed by trackintel. 
 
-Label
-=====
+Labelling
+=========
 
-.. autofunction:: trackintel.analysis.label.create_activity_flag
+.. autofunction:: trackintel.analysis.labelling.create_activity_flag
 
-.. autofunction:: trackintel.analysis.label.predict_transport_mode
+.. autofunction:: trackintel.analysis.labelling.predict_transport_mode
 
 Tracking Quality
 ================
@@ -28,4 +28,4 @@ Location Identification
 
 .. autofunction:: trackintel.analysis.location_identification.pre_filter_locations
 
-.. autofunction:: trackintel.analysis.location_identification.freq_recipe
\ No newline at end of file
+.. autofunction:: trackintel.analysis.location_identification.freq_method
\ No newline at end of file
diff --git a/examples/trackintel_basic_tutorial.ipynb b/examples/trackintel_basic_tutorial.ipynb
index a274394..03e9363 100644
--- a/examples/trackintel_basic_tutorial.ipynb
+++ b/examples/trackintel_basic_tutorial.ipynb
@@ -250,7 +250,7 @@
     "# we concate stps and tpls to get the whole mobility trace\n",
     "trace = stps.append(tpls)\n",
     "# calculate the overall tracking coverage\n",
-    "ti.temporal_tracking_quality(trace, granularity='all')"
+    "ti.analysis.tracking_quality.temporal_tracking_quality(trace, granularity='all')"
    ]
   },
   {
@@ -261,8 +261,8 @@
    "outputs": [],
    "source": [
     "# or coverage by day or hour\n",
-    "ti.temporal_tracking_quality(trace, granularity='hour')\n",
-    "ti.temporal_tracking_quality(trace, granularity='day')"
+    "ti.analysis.tracking_quality.temporal_tracking_quality(trace, granularity='hour')\n",
+    "ti.analysis.tracking_quality.temporal_tracking_quality(trace, granularity='day')"
    ]
   },
   {
@@ -365,4 +365,4 @@
  },
  "nbformat": 4,
  "nbformat_minor": 5
-}
\ No newline at end of file
+}
diff --git a/trackintel/__init__.py b/trackintel/__init__.py
index 7b3fdf4..a6fcd84 100644
--- a/trackintel/__init__.py
+++ b/trackintel/__init__.py
@@ -1,4 +1,13 @@
-from .core import *
-from .model import *
-from .io import *
-from .analysis import *
+import trackintel.model
+import trackintel.analysis
+import trackintel.geogr
+import trackintel.preprocessing
+
+from trackintel.io.file import read_positionfixes_csv
+from trackintel.io.file import read_triplegs_csv
+from trackintel.io.file import read_staypoints_csv
+from trackintel.io.file import read_locations_csv
+from trackintel.io.file import read_trips_csv
+
+#
+from .core import print_version
diff --git a/trackintel/analysis/__init__.py b/trackintel/analysis/__init__.py
index 93845f4..b1f1727 100644
--- a/trackintel/analysis/__init__.py
+++ b/trackintel/analysis/__init__.py
@@ -1,3 +1,22 @@
-from .tracking_quality import *
-from .label import *
-from .modal_split import *
+from .tracking_quality import temporal_tracking_quality
+from .tracking_quality import _split_overlaps as split_overlaps
+
+from .labelling import create_activity_flag
+from .labelling import predict_transport_mode
+
+from .modal_split import calculate_modal_split
+
+from .location_identification import location_identifier
+from .location_identification import pre_filter_locations
+from .location_identification import freq_method
+
+__all__ = [
+    "temporal_tracking_quality",
+    "split_overlaps",
+    "create_activity_flag",
+    "predict_transport_mode",
+    "calculate_modal_split",
+    "location_identifier",
+    "pre_filter_locations",
+    "freq_method",
+]
diff --git a/trackintel/analysis/label.py b/trackintel/analysis/labelling.py
similarity index 100%
rename from trackintel/analysis/label.py
rename to trackintel/analysis/labelling.py
diff --git a/trackintel/geogr/__init__.py b/trackintel/geogr/__init__.py
index e69de29..c20d403 100644
--- a/trackintel/geogr/__init__.py
+++ b/trackintel/geogr/__init__.py
@@ -0,0 +1,6 @@
+from .distances import calculate_distance_matrix
+
+
+__all__ = [
+    "calculate_distance_matrix",
+]
diff --git a/trackintel/io/__init__.py b/trackintel/io/__init__.py
index 16243f9..7b78224 100644
--- a/trackintel/io/__init__.py
+++ b/trackintel/io/__init__.py
@@ -29,3 +29,4 @@ from .postgis import write_trips_postgis
 from .from_geopandas import read_trips_gpd
 
 from .dataset_reader import read_geolife
+from .dataset_reader import geolife_add_modes_to_triplegs
diff --git a/trackintel/io/dataset_reader.py b/trackintel/io/dataset_reader.py
index 9f3d98e..862a46c 100644
--- a/trackintel/io/dataset_reader.py
+++ b/trackintel/io/dataset_reader.py
@@ -42,8 +42,8 @@ def read_geolife(geolife_path, print_progress=False):
 
     Notes
     -----
-    The geopandas dataframe has the following columns and datatype: 'lat': float64, Latitude WGS84;
-    'lon': float64, Longitude WGS84; 'elevation': float64, in meters; 'tracked_at': datetime64[ns];
+    The geopandas dataframe has the following columns and datatype: 'latitude': float64, Latitude WGS84;
+    'longitude': float64, Longitude WGS84; 'elevation': float64, in meters; 'tracked_at': datetime64[ns];
     'user_id': int64; 'geom': geopandas/shapely geometry; 'accuracy': None;
 
     For some users, travel mode labels are provided as .txt file. These labels are read and returned as label dictionary.
@@ -138,7 +138,7 @@ def read_geolife(geolife_path, print_progress=False):
                 input_file_this,
                 skiprows=6,
                 header=None,
-                names=["lat", "lon", "zeros", "elevation", "date days", "date", "time"],
+                names=["latitude", "longitude", "zeros", "elevation", "date days", "date", "time"],
             )
 
             data_this["tracked_at"] = pd.to_datetime(
@@ -149,7 +149,7 @@ def read_geolife(geolife_path, print_progress=False):
             data_this["user_id"] = user_id
             data_this["elevation"] = data_this["elevation"] * FEET2METER
 
-            data_this["geom"] = list(zip(data_this["lon"], data_this["lat"]))
+            data_this["geom"] = list(zip(data_this["longitude"], data_this["latitude"]))
             data_this["geom"] = data_this["geom"].apply(Point)
 
             df_list_days.append(data_this)
diff --git a/trackintel/model/staypoints.py b/trackintel/model/staypoints.py
index 0232098..777865f 100644
--- a/trackintel/model/staypoints.py
+++ b/trackintel/model/staypoints.py
@@ -83,9 +83,9 @@ class StaypointsAccessor(object):
         """
         Set a flag if a staypoint is also an activity.
 
-        See :func:`trackintel.analysis.label.create_activity_flag`.
+        See :func:`trackintel.analysis.labelling.create_activity_flag`.
         """
-        return ti.analysis.label.create_activity_flag(self._obj, *args, **kwargs)
+        return ti.analysis.labelling.create_activity_flag(self._obj, *args, **kwargs)
 
     def spatial_filter(self, *args, **kwargs):
         """
diff --git a/trackintel/model/triplegs.py b/trackintel/model/triplegs.py
index f778cd0..92dcf32 100644
--- a/trackintel/model/triplegs.py
+++ b/trackintel/model/triplegs.py
@@ -124,9 +124,9 @@ class TriplegsAccessor(object):
         """
         Predict/impute the transport mode with which each tripleg was likely covered.
 
-        See :func:`trackintel.analysis.label.predict_transport_mode`.
+        See :func:`trackintel.analysis.labelling.predict_transport_mode`.
         """
-        return ti.analysis.label.predict_transport_mode(self._obj, *args, **kwargs)
+        return ti.analysis.labelling.predict_transport_mode(self._obj, *args, **kwargs)
 
     def calculate_modal_split(self, *args, **kwargs):
         """
diff --git a/trackintel/preprocessing/__init__.py b/trackintel/preprocessing/__init__.py
index 706f569..a21032e 100644
--- a/trackintel/preprocessing/__init__.py
+++ b/trackintel/preprocessing/__init__.py
@@ -7,3 +7,12 @@ from .staypoints import generate_locations
 
 from .triplegs import smoothen_triplegs
 from .triplegs import generate_trips
+
+__all__ = [
+    "generate_staypoints",
+    "generate_triplegs",
+    "spatial_filter",
+    "generate_locations",
+    "smoothen_triplegs",
+    "generate_trips",
+]
diff --git a/trackintel/visualization/__init__.py b/trackintel/visualization/__init__.py
index 3908011..0252869 100644
--- a/trackintel/visualization/__init__.py
+++ b/trackintel/visualization/__init__.py
@@ -1,6 +1,16 @@
-from .locations import *
-from .osm import *
-from .positionfixes import *
-from .staypoints import *
-from .triplegs import *
-from .modal_split import *
+from .locations import plot_locations
+from .osm import plot_osm_streets
+from .positionfixes import plot_positionfixes
+from .staypoints import plot_staypoints
+from .triplegs import plot_triplegs
+from .modal_split import plot_modal_split
+
+
+__all__ = [
+    "plot_locations",
+    "plot_osm_streets",
+    "plot_positionfixes",
+    "plot_staypoints",
+    "plot_triplegs",
+    "plot_modal_split",
+]


Test patch:
diff --git a/tests/analysis/test_label.py b/tests/analysis/test_label.py
index fdceefd..01704eb 100644
--- a/tests/analysis/test_label.py
+++ b/tests/analysis/test_label.py
@@ -5,7 +5,7 @@ import pandas as pd
 import pytest
 
 import trackintel as ti
-from trackintel.analysis.label import _check_categories
+from trackintel.analysis.labelling import _check_categories
 
 
 class TestCreate_activity_flag:
diff --git a/tests/io/test_dataset_reader.py b/tests/io/test_dataset_reader.py
index 510d205..ab52372 100644
--- a/tests/io/test_dataset_reader.py
+++ b/tests/io/test_dataset_reader.py
@@ -5,6 +5,8 @@ import numpy as np
 import pandas as pd
 import pytest
 
+from geopandas.testing import assert_geoseries_equal
+
 import trackintel as ti
 from trackintel.io.dataset_reader import read_geolife, geolife_add_modes_to_triplegs
 
@@ -82,29 +84,30 @@ class TestReadGeolife:
     def test_loop_read(self):
         """Use read_geolife reader, store posfix as .csv, load them again."""
         pfs, _ = read_geolife(os.path.join("tests", "data", "geolife"), print_progress=True)
-        tmp_file = os.path.join("tests", "data", "positionfixes_test.csv")
-        pfs.as_positionfixes.to_csv(tmp_file)
-        pfs2 = ti.read_positionfixes_csv(tmp_file, index_col="id")[pfs.columns]
-        os.remove(tmp_file)
-        assert np.isclose(0, (pfs.lat - pfs2.lat).abs().sum())
+
+        saved_file = os.path.join("tests", "data", "positionfixes_test.csv")
+        pfs.as_positionfixes.to_csv(saved_file)
+        pfs_reRead = ti.read_positionfixes_csv(saved_file, index_col="id", crs="epsg:4326")
+        os.remove(saved_file)
+
+        assert_geoseries_equal(pfs.geometry, pfs_reRead.geometry)
 
     def test_print_progress_flag(self, capsys):
-        """Test if the print_progress par controls the printing behavior"""
+        """Test if the print_progress bar controls the printing behavior."""
         g_path = os.path.join("tests", "data", "geolife")
-        pfs, _ = read_geolife(g_path, print_progress=True)
+        read_geolife(g_path, print_progress=True)
         captured_print = capsys.readouterr()
         assert captured_print.err != ""
 
-        pfs, _ = read_geolife(g_path, print_progress=False)
+        read_geolife(g_path, print_progress=False)
         captured_noprint = capsys.readouterr()
         assert captured_noprint.err == ""
 
         assert True
 
     def test_label_reading(self):
-        """test data types of the labels returned by read_geolife"""
-
-        pfs, labels = read_geolife(os.path.join("tests", "data", "geolife_modes"))
+        """Test data types of the labels returned by read_geolife."""
+        _, labels = read_geolife(os.path.join("tests", "data", "geolife_modes"))
         # the output is a dictionary
         assert isinstance(labels, dict)
 
@@ -114,9 +117,8 @@ class TestReadGeolife:
             assert isinstance(value, pd.DataFrame)
 
     def test_unavailable_label_reading(self):
-        """test data types of the labels returned by read_geolife from a dictionary without label files"""
-
-        pfs, labels = read_geolife(os.path.join("tests", "data", "geolife_long"))
+        """Test data types of the labels returned by read_geolife from a dictionary without label files."""
+        _, labels = read_geolife(os.path.join("tests", "data", "geolife_long"))
 
         # the output is a dictionary
         assert isinstance(labels, dict)
@@ -126,7 +128,7 @@ class TestReadGeolife:
             assert isinstance(value, pd.DataFrame)
 
     def test_wrong_folder_name(self):
-        """Check if invalid folder names raise an exception"""
+        """Check if invalid folder names raise an exception."""
         geolife_path = os.path.join("tests", "data", "geolife")
         temp_dir = os.path.join(geolife_path, "123 - invalid folder ()%")
         os.mkdir(temp_dir)