Repository: TUW-GEO/pygeogrids

Issue:
Error when searching nearest neighbour with custom gpis
I get an error when using the new `find_nearest_gpi` function (with `max_dist`) from #66 

``` python
>> import pygeogrids
>>pygeogrids.__version__
'0.3.1'
>> grid = pygeogrids.BasicGrid(lon=[16,17], lat=[45,46], gpis=[100,200])
>> grid.find_nearest_gpi(0,0)
(100, 5082354.193805456)
>> grid.find_nearest_gpi(0,0, max_dist=1000)
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "C:\Users\wpreimes\Anaconda3\envs\ismn\lib\site-packages\pygeogrids\grids.py", line 400, in find_nearest_gpi
    gpi, distance = self.find_k_nearest_gpi(lon, lat, max_dist=max_dist, k=1)
  File "C:\Users\wpreimes\Anaconda3\envs\ismn\lib\site-packages\pygeogrids\grids.py", line 441, in find_k_nearest_gpi
    gpi = self.activegpis[ind]
IndexError: arrays used as indices must be of integer (or boolean) type
```
I think the function should return an empty array instead.

It works when I dont set the gpis manually when creating the grid
```python
>> grid = pygeogrids.BasicGrid(lon=[16,17], lat=[45,46])
>> grid.find_nearest_gpi(0,0, max_dist=1000)
(array([], dtype=float64), array([], dtype=float64))
```

At some point the GPI is used for looking up the lon/lat I think, which only works for default GPIs (starting at 0)

@s-scherrer can you fix this?

Discussion:

Patch:
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
new file mode 100644
index 0000000..5ded9b6
--- /dev/null
+++ b/.github/workflows/publish.yml
@@ -0,0 +1,48 @@
+name: pypi
+
+# This workflow uploads a release to pypi. A released must be triggered
+# via github (releases) and will include a version number tag (leading 'v'!!)
+# This will NOT repeat testing, draft a release only from tested branches!
+
+env:
+  # RELEASE_ACCOUNT: Only tagged commits in repo under this account are published
+  # Additional safety measure so that publishing from a fork is never possible.
+  RELEASE_ACCOUNT: 'TUW-GEO'
+
+on:
+  release:
+    types: [released] # only on tagged github releases, (a simple tag is not enough!)
+  push:
+    tags:
+      - v*
+
+jobs:
+  publish:
+    name: Upload to Pypi 🚀
+    # needs original repo (TUW-GEO) and tagged commit (v*)
+    if: startsWith(github.ref, 'refs/tags/v') && startsWith(github.repository, '$RELEASE_ACCOUNT/')
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+        with:
+          repository: ${{ github.repository }}
+          ref: ${{ github.ref }}
+      - name: Set up Python
+        uses: actions/setup-python@v2
+        with:
+          python-version: 3.x
+      - name: Build
+        shell: bash -l {0}
+        run: |
+          python setup.py --version
+          python setup.py sdist
+          pip install wheel && python setup.py bdist_wheel
+      - name: Publish distribution to Test PyPI
+        uses: pypa/gh-action-pypi-publish@v1.4.1
+        with:
+          skip_existing: true
+          verbose: true
+          verify_metadata: true
+          packages_dir: dist/
+          user: __token__
+          password: ${{ secrets.PYPI_API_TOKEN }} # todo: add token to github actions secrets
diff --git a/.gitignore b/.gitignore
index 2be14f0..44358fd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -48,3 +48,4 @@ MANIFEST
 
 # Per-project virtualenvs
 .venv*/
+.artifacts/*
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index b41e248..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,53 +0,0 @@
-dist: xenial
-language: python
-notifications:
-  email: false
-python:
-  # We don't actually use the Travis Python, but this keeps it organized.
-  - "3.6"
-  - "3.7"
-  - "3.8"
-env:
-  - PINNED=true # use fixed dependencies
-  - PINNED=false # use latest dependencies
-matrix:
-  exclude:
-    - python: "3.8"
-      env: PINNED=false
-install:
-  # You may want to periodically update this, although the conda update
-  # conda line below will keep everything up-to-date.  We do this
-  # conditionally because it saves us some downloading if the version is
-  # the same.
-  - wget http://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh;
-  - pinned_yml=environment_pinned_py3.yml;
-  - bash miniconda.sh -b -p $HOME/miniconda
-  - export PATH="$HOME/miniconda/bin:$PATH"
-  - hash -r
-  - conda config --set always_yes yes --set changeps1 no
-  - conda update -q conda
-  # Useful for debugging any issues with conda
-  - conda info -a
-
-  - conda create -n pygeogrids python=${TRAVIS_PYTHON_VERSION}
-
-  - if $PINNED; then
-        conda env update -f $pinned_yml -n pygeogrids;
-    else
-        conda env update -f environment.yml -n pygeogrids;
-    fi
-    
-  - source activate pygeogrids
-  - python setup.py install
-
-  - conda list
-  - pip list
-  - which pip
-  - which python
-
-script:
-  - python setup.py test
-after_success:
-  # report coverage results to coveralls.io
-  - pip install coveralls
-  - coveralls
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 4892a1f..33a9239 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -2,6 +2,12 @@
 Changelog
 =========
 
+Version x.x.x
+=============
+
+- FIX: Nearest neighbour search for grids with non-default GPIs
+- Replace Travis CI with Github Actions workflows.
+
 Version 0.2.7
 =============
 
diff --git a/environment.yml b/environment.yml
index 30ed543..6c29ed2 100644
--- a/environment.yml
+++ b/environment.yml
@@ -1,4 +1,4 @@
-name: pygeogrids_dev
+name: pygeogrids
 channels:
   - conda-forge
 dependencies:
diff --git a/environment_pinned_py3.yml b/environment_pinned.yml
similarity index 100%
rename from environment_pinned_py3.yml
rename to environment_pinned.yml
diff --git a/src/pygeogrids/grids.py b/src/pygeogrids/grids.py
index 3a04fa6..81f8e37 100644
--- a/src/pygeogrids/grids.py
+++ b/src/pygeogrids/grids.py
@@ -391,11 +391,13 @@ class BasicGrid(object):
         Returns
         -------
         gpi : long
-            Grid point index.
+            Grid point index. If no point was found within the maximum
+            distance to consider, an empty array is returned.
         distance : float
             Distance of gpi to given lon, lat.
             At the moment not on a great circle but in spherical
-            cartesian coordinates.
+            cartesian coordinates. If no point was found within the maximum
+            distance to consider, an empty array is returned.
         """
         gpi, distance = self.find_k_nearest_gpi(lon, lat, max_dist=max_dist, k=1)
 
@@ -435,7 +437,7 @@ class BasicGrid(object):
         distance, ind = self.kdTree.find_nearest_index(
             lon, lat, max_dist=max_dist, k=k)
 
-        if self.gpidirect and self.allpoints:
+        if self.gpidirect and self.allpoints or len(ind) == 0:
             gpi = ind
         else:
             gpi = self.activegpis[ind]


Test patch:
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
new file mode 100644
index 0000000..2a51825
--- /dev/null
+++ b/.github/workflows/test.yml
@@ -0,0 +1,85 @@
+# This workflow will install Python dependencies and run tests on
+# windows and linux systems with a variety of Python versions
+
+# For more information see:
+# https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
+
+name: test
+
+on:
+  push:
+  pull_request:
+  schedule: # only upstream, won't trigger on forks!
+    - cron: '0 0 * * *' # daily
+jobs:
+  build:
+    strategy:
+      matrix:
+        os: ["ubuntu-latest", "windows-latest"]
+        python-version: ['3.6', '3.7']
+        ymlfile: ['environment.yml']
+        include: # test with environment_pinned.yml
+          - os: ubuntu-latest
+            python-version: '3.6'
+            ymlfile: environment_pinned.yml
+    name: Py${{ matrix.python-version }}@${{ matrix.os }}|${{ matrix.ymlfile }}🐍
+    runs-on: ${{ matrix.os }}
+
+    steps:
+      - uses: actions/checkout@v2
+        with:
+          submodules: true
+      - uses: conda-incubator/setup-miniconda@v2.0.1
+        with:
+          miniconda-version: "latest"
+          auto-update-conda: true
+          python-version: ${{ matrix.python-version }}
+          environment-file: ${{ matrix.ymlfile }}
+          activate-environment: pygeogrids # todo: must match with name in environment.yml
+          auto-activate-base: false
+      - name: Print Infos
+        shell: bash -l {0}
+        run: |
+          conda info -a
+          conda list
+          pip list
+          which pip
+          which python
+      - name: Export Environment
+        shell: bash -l {0}
+        run: |
+          if [ ${{ matrix.ymlfile }} == "environment.yml" ]
+          then
+              mkdir -p .artifacts
+              filename=env_py${{ matrix.python-version }}_${{ matrix.os }}.yml
+              conda env export --no-builds | grep -v "prefix" > .artifacts/$filename
+          fi
+      - name: Upload Artifacts
+        uses: actions/upload-artifact@v2
+        with:
+          name: os_py_environments
+          path: .artifacts/*
+      - name: Install package and test
+        shell: bash -l {0}
+        run: |
+          python setup.py install
+          python setup.py test
+      - name: Upload Coverage
+        shell: bash -l {0}
+        run: |
+          pip install coveralls && coveralls
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+          COVERALLS_FLAG_NAME: ${{ matrix.python-version }}
+          COVERALLS_PARALLEL: true
+  coveralls:
+    name: Submit Coveralls 👚
+    needs: build
+    runs-on: ubuntu-latest
+    container: python:3-slim
+    steps:
+      - name: Finished
+        run: |
+          pip3 install --upgrade coveralls && coveralls --finish
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
\ No newline at end of file
diff --git a/tests/test_grid.py b/tests/test_grid.py
index a5c84d1..8becac3 100644
--- a/tests/test_grid.py
+++ b/tests/test_grid.py
@@ -151,6 +151,13 @@ class TestFindNearestNeighbor(unittest.TestCase):
         assert len(gpi) == 0
         assert len(dist) == 0
 
+        # test with custom gpi, see issue #68
+        grid = grids.BasicGrid(lon=[16,17], lat=[45,46], gpis=[100,200])
+        gpi, dist = grid.find_nearest_gpi(0,0, max_dist=1000)
+        assert len(gpi) == 0
+        assert len(dist) == 0
+                                                
+
 class TestCellGridNotGpiDirect(unittest.TestCase):
 
     """