diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml
new file mode 100644
index 0000000..28cdccc
--- /dev/null
+++ b/.github/workflows/pypi.yml
@@ -0,0 +1,25 @@
+name: Publish
+
+on:
+  release:
+    types: [published]
+
+jobs:
+  publish:
+    runs-on: ubuntu-latest
+    steps:
+    - uses: actions/checkout@v2
+    - name: Set up Python
+      uses: actions/setup-python@v1
+      with:
+        python-version: 3.7
+    - name: Install dependencies
+      run: |
+        python -m pip install --upgrade pip
+        pip install setuptools wheel twine
+        python setup.py bdist_wheel
+    - name: Publish package
+      uses: pypa/gh-action-pypi-publish@master
+      with:
+        user: __token__
+        password: ${{ secrets.PYPI_TOKEN }}
diff --git a/laserchicken/feature_extractor/band_ratio_feature_extractor.py b/laserchicken/feature_extractor/band_ratio_feature_extractor.py
index 318dd7c..3bf65eb 100644
--- a/laserchicken/feature_extractor/band_ratio_feature_extractor.py
+++ b/laserchicken/feature_extractor/band_ratio_feature_extractor.py
@@ -47,10 +47,10 @@ class BandRatioFeatureExtractor(FeatureExtractor):
         """
         name = 'band_ratio_'
         if self.lower_limit is not None:
-            name += str(self.lower_limit) + '<'
+            name += str(self.lower_limit) + '_'
         name += self.data_key
         if self.upper_limit is not None:
-            name += '<' + str(self.upper_limit)
+            name += '_' + str(self.upper_limit)
         return [name]
 
     def extract(self, point_cloud, neighborhoods, target_point_cloud, target_index, volume_description):

diff --git a/laserchicken/feature_extractor/test_band_ratio_feature_extractor.py b/laserchicken/feature_extractor/test_band_ratio_feature_extractor.py
index 43e3c83..c08403a 100644
--- a/laserchicken/feature_extractor/test_band_ratio_feature_extractor.py
+++ b/laserchicken/feature_extractor/test_band_ratio_feature_extractor.py
@@ -86,22 +86,22 @@ class TestBandRatioFeatureExtractorSimpleArtificialData(unittest.TestCase):
         assert_expected_ratio(volume=InfiniteCylinder(5))
 
     def test_provides_simple(self):
-        self.assertEqual(['band_ratio_6<z<20'], BandRatioFeatureExtractor(6, 20).provides())
+        self.assertEqual(['band_ratio_6_z_20'], BandRatioFeatureExtractor(6, 20).provides())
 
     def test_provides_with_only_upper_limit(self):
-        self.assertEqual(['band_ratio_z<20'], BandRatioFeatureExtractor(None, 20).provides())
+        self.assertEqual(['band_ratio_z_20'], BandRatioFeatureExtractor(None, 20).provides())
 
     def test_provides_with_only_lower_limit(self):
-        self.assertEqual(['band_ratio_20<z'], BandRatioFeatureExtractor(20, None).provides())
+        self.assertEqual(['band_ratio_20_z'], BandRatioFeatureExtractor(20, None).provides())
 
     def test_provides_with_zero_lower_limit(self):
-        self.assertEqual(['band_ratio_0<z'], BandRatioFeatureExtractor(0, None).provides())
+        self.assertEqual(['band_ratio_0_z'], BandRatioFeatureExtractor(0, None).provides())
 
     def test_provides_with_zero_upper_limit(self):
-        self.assertEqual(['band_ratio_z<0'], BandRatioFeatureExtractor(None, 0).provides())
+        self.assertEqual(['band_ratio_z_0'], BandRatioFeatureExtractor(None, 0).provides())
 
     def test_provides_with_data_key(self):
-        self.assertEqual(['band_ratio_1<normalized_height<3'],
+        self.assertEqual(['band_ratio_1_normalized_height_3'],
                          BandRatioFeatureExtractor(1, 3, data_key=keys.normalized_height).provides())
 
 
diff --git a/laserchicken/test_integration_tests.py b/laserchicken/test_integration_tests.py
index 48d28c8..0749999 100644
--- a/laserchicken/test_integration_tests.py
+++ b/laserchicken/test_integration_tests.py
@@ -48,7 +48,7 @@ class FromTutorial(unittest.TestCase):
 
         cylinder = build_volume("infinite cylinder", radius=5)
         neighborhoods = compute_neighborhoods(point_cloud, targets, cylinder)
-        compute_features(point_cloud, neighborhoods, targets, ['band_ratio_1<normalized_height<2'], cylinder)
+        compute_features(point_cloud, neighborhoods, targets, ['band_ratio_1_normalized_height_2'], cylinder)
 
         from laserchicken import export
         export(point_cloud, 'my_output.ply')

Rename band ratio
Drop the "<" symbols from the band ratio features. This significantly simplify the handling of files named after these features on Windows (which does not support such characters in the file name). 
laserchicken/feature_extractor/test_band_ratio_feature_extractor.py::TestBandRatioFeatureExtractorSimpleArtificialData::test_provides_simple laserchicken/feature_extractor/test_band_ratio_feature_extractor.py::TestBandRatioFeatureExtractorSimpleArtificialData::test_provides_with_data_key laserchicken/feature_extractor/test_band_ratio_feature_extractor.py::TestBandRatioFeatureExtractorSimpleArtificialData::test_provides_with_only_lower_limit laserchicken/feature_extractor/test_band_ratio_feature_extractor.py::TestBandRatioFeatureExtractorSimpleArtificialData::test_provides_with_only_upper_limit laserchicken/feature_extractor/test_band_ratio_feature_extractor.py::TestBandRatioFeatureExtractorSimpleArtificialData::test_provides_with_zero_lower_limit laserchicken/feature_extractor/test_band_ratio_feature_extractor.py::TestBandRatioFeatureExtractorSimpleArtificialData::test_provides_with_zero_upper_limit