diff --git a/backend/gRPCProjector/python/oldGenerated/projector_pb2.py b/backend/gRPCProjector/python/oldGenerated/projector_pb2.py
new file mode 100644
index 0000000000000000000000000000000000000000..3f34f7013e3463ae66d6eccbf6a8ba4069907ad1
--- /dev/null
+++ b/backend/gRPCProjector/python/oldGenerated/projector_pb2.py
@@ -0,0 +1,239 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: projector.proto
+
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import message as _message
+from google.protobuf import reflection as _reflection
+from google.protobuf import symbol_database as _symbol_database
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+from google.protobuf import empty_pb2 as google_dot_protobuf_dot_empty__pb2
+
+
+DESCRIPTOR = _descriptor.FileDescriptor(
+  name='projector.proto',
+  package='provee',
+  syntax='proto3',
+  serialized_options=b'\n\017nl.uuvig.proveeB\022ProveProjectorGRCPP\001\242\002\006PROVEE',
+  create_key=_descriptor._internal_create_key,
+  serialized_pb=b'\n\x0fprojector.proto\x12\x06provee\x1a\x1bgoogle/protobuf/empty.proto\")\n\x05Point\x12\n\n\x02id\x18\x01 \x01(\x05\x12\t\n\x01x\x18\x02 \x01(\x02\x12\t\n\x01y\x18\x03 \x01(\x02\"D\n\x0bTrainingSet\x12\x0f\n\x07modelid\x18\x01 \x01(\t\x12$\n\x04rows\x18\x02 \x03(\x0b\x32\x16.provee.TrainingSetRow\"2\n\x0eTrainingSetRow\x12\n\n\x02id\x18\x01 \x01(\t\x12\x14\n\x08hdvector\x18\x02 \x03(\x01\x42\x02\x10\x01\x32\xf9\x01\n\tProjector\x12\x37\n\x05start\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\x12\x36\n\x04stop\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\x12\x42\n\x13getProjectionPoints\x12\x16.provee.TrainingSetRow\x1a\r.provee.Point\"\x00(\x01\x30\x01\x12\x37\n\ngetUpdates\x12\x16.google.protobuf.Empty\x1a\r.provee.Point\"\x00\x30\x01\x42\x30\n\x0fnl.uuvig.proveeB\x12ProveProjectorGRCPP\x01\xa2\x02\x06PROVEEb\x06proto3'
+  ,
+  dependencies=[google_dot_protobuf_dot_empty__pb2.DESCRIPTOR,])
+
+
+
+
+_POINT = _descriptor.Descriptor(
+  name='Point',
+  full_name='provee.Point',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='id', full_name='provee.Point.id', index=0,
+      number=1, type=5, cpp_type=1, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='x', full_name='provee.Point.x', index=1,
+      number=2, type=2, cpp_type=6, label=1,
+      has_default_value=False, default_value=float(0),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='y', full_name='provee.Point.y', index=2,
+      number=3, type=2, cpp_type=6, label=1,
+      has_default_value=False, default_value=float(0),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=56,
+  serialized_end=97,
+)
+
+
+_TRAININGSET = _descriptor.Descriptor(
+  name='TrainingSet',
+  full_name='provee.TrainingSet',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='modelid', full_name='provee.TrainingSet.modelid', index=0,
+      number=1, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=b"".decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='rows', full_name='provee.TrainingSet.rows', index=1,
+      number=2, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=99,
+  serialized_end=167,
+)
+
+
+_TRAININGSETROW = _descriptor.Descriptor(
+  name='TrainingSetRow',
+  full_name='provee.TrainingSetRow',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='id', full_name='provee.TrainingSetRow.id', index=0,
+      number=1, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=b"".decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='hdvector', full_name='provee.TrainingSetRow.hdvector', index=1,
+      number=2, type=1, cpp_type=5, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=b'\020\001', file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=169,
+  serialized_end=219,
+)
+
+_TRAININGSET.fields_by_name['rows'].message_type = _TRAININGSETROW
+DESCRIPTOR.message_types_by_name['Point'] = _POINT
+DESCRIPTOR.message_types_by_name['TrainingSet'] = _TRAININGSET
+DESCRIPTOR.message_types_by_name['TrainingSetRow'] = _TRAININGSETROW
+_sym_db.RegisterFileDescriptor(DESCRIPTOR)
+
+Point = _reflection.GeneratedProtocolMessageType('Point', (_message.Message,), {
+  'DESCRIPTOR' : _POINT,
+  '__module__' : 'projector_pb2'
+  # @@protoc_insertion_point(class_scope:provee.Point)
+  })
+_sym_db.RegisterMessage(Point)
+
+TrainingSet = _reflection.GeneratedProtocolMessageType('TrainingSet', (_message.Message,), {
+  'DESCRIPTOR' : _TRAININGSET,
+  '__module__' : 'projector_pb2'
+  # @@protoc_insertion_point(class_scope:provee.TrainingSet)
+  })
+_sym_db.RegisterMessage(TrainingSet)
+
+TrainingSetRow = _reflection.GeneratedProtocolMessageType('TrainingSetRow', (_message.Message,), {
+  'DESCRIPTOR' : _TRAININGSETROW,
+  '__module__' : 'projector_pb2'
+  # @@protoc_insertion_point(class_scope:provee.TrainingSetRow)
+  })
+_sym_db.RegisterMessage(TrainingSetRow)
+
+
+DESCRIPTOR._options = None
+_TRAININGSETROW.fields_by_name['hdvector']._options = None
+
+_PROJECTOR = _descriptor.ServiceDescriptor(
+  name='Projector',
+  full_name='provee.Projector',
+  file=DESCRIPTOR,
+  index=0,
+  serialized_options=None,
+  create_key=_descriptor._internal_create_key,
+  serialized_start=222,
+  serialized_end=471,
+  methods=[
+  _descriptor.MethodDescriptor(
+    name='start',
+    full_name='provee.Projector.start',
+    index=0,
+    containing_service=None,
+    input_type=google_dot_protobuf_dot_empty__pb2._EMPTY,
+    output_type=google_dot_protobuf_dot_empty__pb2._EMPTY,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+  _descriptor.MethodDescriptor(
+    name='stop',
+    full_name='provee.Projector.stop',
+    index=1,
+    containing_service=None,
+    input_type=google_dot_protobuf_dot_empty__pb2._EMPTY,
+    output_type=google_dot_protobuf_dot_empty__pb2._EMPTY,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+  _descriptor.MethodDescriptor(
+    name='getProjectionPoints',
+    full_name='provee.Projector.getProjectionPoints',
+    index=2,
+    containing_service=None,
+    input_type=_TRAININGSETROW,
+    output_type=_POINT,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+  _descriptor.MethodDescriptor(
+    name='getUpdates',
+    full_name='provee.Projector.getUpdates',
+    index=3,
+    containing_service=None,
+    input_type=google_dot_protobuf_dot_empty__pb2._EMPTY,
+    output_type=_POINT,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+])
+_sym_db.RegisterServiceDescriptor(_PROJECTOR)
+
+DESCRIPTOR.services_by_name['Projector'] = _PROJECTOR
+
+# @@protoc_insertion_point(module_scope)
diff --git a/backend/gRPCProjector/python/oldGenerated/projector_pb2_grpc.py b/backend/gRPCProjector/python/oldGenerated/projector_pb2_grpc.py
new file mode 100644
index 0000000000000000000000000000000000000000..f36b3e05eee43d386a43cd7478846f73688d6141
--- /dev/null
+++ b/backend/gRPCProjector/python/oldGenerated/projector_pb2_grpc.py
@@ -0,0 +1,183 @@
+# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
+"""Client and server classes corresponding to protobuf-defined services."""
+import grpc
+
+from google.protobuf import empty_pb2 as google_dot_protobuf_dot_empty__pb2
+import projector_pb2 as projector__pb2
+
+
+class ProjectorStub(object):
+    """Interface exported by the server.
+    """
+
+    def __init__(self, channel):
+        """Constructor.
+
+        Args:
+            channel: A grpc.Channel.
+        """
+        self.start = channel.unary_unary(
+                '/provee.Projector/start',
+                request_serializer=google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString,
+                response_deserializer=google_dot_protobuf_dot_empty__pb2.Empty.FromString,
+                )
+        self.stop = channel.unary_unary(
+                '/provee.Projector/stop',
+                request_serializer=google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString,
+                response_deserializer=google_dot_protobuf_dot_empty__pb2.Empty.FromString,
+                )
+        self.getProjectionPoints = channel.stream_stream(
+                '/provee.Projector/getProjectionPoints',
+                request_serializer=projector__pb2.TrainingSetRow.SerializeToString,
+                response_deserializer=projector__pb2.Point.FromString,
+                )
+        self.getUpdates = channel.unary_stream(
+                '/provee.Projector/getUpdates',
+                request_serializer=google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString,
+                response_deserializer=projector__pb2.Point.FromString,
+                )
+
+
+class ProjectorServicer(object):
+    """Interface exported by the server.
+    """
+
+    def start(self, request, context):
+        """A simple RPC.
+
+        Start the Projector calculation
+        """
+        context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+        context.set_details('Method not implemented!')
+        raise NotImplementedError('Method not implemented!')
+
+    def stop(self, request, context):
+        """Stop the Projector calculation
+        """
+        context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+        context.set_details('Method not implemented!')
+        raise NotImplementedError('Method not implemented!')
+
+    def getProjectionPoints(self, request_iterator, context):
+        """A server-to-client streaming RPC.
+
+        Obtains the Projection Points in 2D given the trainings values stored in a row format.  Results are
+        streamed rather than returned at once (e.g. in a response message with a
+        repeated field).
+        """
+        context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+        context.set_details('Method not implemented!')
+        raise NotImplementedError('Method not implemented!')
+
+    def getUpdates(self, request, context):
+        """A server-to-client streaming RPC.
+
+        Obtains the Projection Points in 2D given the trainings values stored in a row format.  Results are
+        streamed rather than returned at once (e.g. in a response message with a
+        repeated field).
+        """
+        context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+        context.set_details('Method not implemented!')
+        raise NotImplementedError('Method not implemented!')
+
+
+def add_ProjectorServicer_to_server(servicer, server):
+    rpc_method_handlers = {
+            'start': grpc.unary_unary_rpc_method_handler(
+                    servicer.start,
+                    request_deserializer=google_dot_protobuf_dot_empty__pb2.Empty.FromString,
+                    response_serializer=google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString,
+            ),
+            'stop': grpc.unary_unary_rpc_method_handler(
+                    servicer.stop,
+                    request_deserializer=google_dot_protobuf_dot_empty__pb2.Empty.FromString,
+                    response_serializer=google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString,
+            ),
+            'getProjectionPoints': grpc.stream_stream_rpc_method_handler(
+                    servicer.getProjectionPoints,
+                    request_deserializer=projector__pb2.TrainingSetRow.FromString,
+                    response_serializer=projector__pb2.Point.SerializeToString,
+            ),
+            'getUpdates': grpc.unary_stream_rpc_method_handler(
+                    servicer.getUpdates,
+                    request_deserializer=google_dot_protobuf_dot_empty__pb2.Empty.FromString,
+                    response_serializer=projector__pb2.Point.SerializeToString,
+            ),
+    }
+    generic_handler = grpc.method_handlers_generic_handler(
+            'provee.Projector', rpc_method_handlers)
+    server.add_generic_rpc_handlers((generic_handler,))
+
+
+ # This class is part of an EXPERIMENTAL API.
+class Projector(object):
+    """Interface exported by the server.
+    """
+
+    @staticmethod
+    def start(request,
+            target,
+            options=(),
+            channel_credentials=None,
+            call_credentials=None,
+            insecure=False,
+            compression=None,
+            wait_for_ready=None,
+            timeout=None,
+            metadata=None):
+        return grpc.experimental.unary_unary(request, target, '/provee.Projector/start',
+            google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString,
+            google_dot_protobuf_dot_empty__pb2.Empty.FromString,
+            options, channel_credentials,
+            insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
+
+    @staticmethod
+    def stop(request,
+            target,
+            options=(),
+            channel_credentials=None,
+            call_credentials=None,
+            insecure=False,
+            compression=None,
+            wait_for_ready=None,
+            timeout=None,
+            metadata=None):
+        return grpc.experimental.unary_unary(request, target, '/provee.Projector/stop',
+            google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString,
+            google_dot_protobuf_dot_empty__pb2.Empty.FromString,
+            options, channel_credentials,
+            insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
+
+    @staticmethod
+    def getProjectionPoints(request_iterator,
+            target,
+            options=(),
+            channel_credentials=None,
+            call_credentials=None,
+            insecure=False,
+            compression=None,
+            wait_for_ready=None,
+            timeout=None,
+            metadata=None):
+        return grpc.experimental.stream_stream(request_iterator, target, '/provee.Projector/getProjectionPoints',
+            projector__pb2.TrainingSetRow.SerializeToString,
+            projector__pb2.Point.FromString,
+            options, channel_credentials,
+            insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
+
+    @staticmethod
+    def getUpdates(request,
+            target,
+            options=(),
+            channel_credentials=None,
+            call_credentials=None,
+            insecure=False,
+            compression=None,
+            wait_for_ready=None,
+            timeout=None,
+            metadata=None):
+        return grpc.experimental.unary_stream(request, target, '/provee.Projector/getUpdates',
+            google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString,
+            projector__pb2.Point.FromString,
+            options, channel_credentials,
+            insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
diff --git a/backend/gRPCProjector/python/protos/README.md b/backend/gRPCProjector/python/protos/README.md
deleted file mode 100644
index 128e4b2fa1fce1c43af79e2956e931e79b266d90..0000000000000000000000000000000000000000
--- a/backend/gRPCProjector/python/protos/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# protos
-
-Contains all Protos (gRCP) files that are used to communicate between services in Provee
\ No newline at end of file
diff --git a/backend/grpcKNN/protos/README.md b/backend/grpcKNN/protos/README.md
deleted file mode 100644
index 128e4b2fa1fce1c43af79e2956e931e79b266d90..0000000000000000000000000000000000000000
--- a/backend/grpcKNN/protos/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# protos
-
-Contains all Protos (gRCP) files that are used to communicate between services in Provee
\ No newline at end of file
diff --git a/backend/grpcKNN/protos/v3/knn.proto b/backend/webSocketGateway/protos/v3/old/knn.proto
similarity index 100%
rename from backend/grpcKNN/protos/v3/knn.proto
rename to backend/webSocketGateway/protos/v3/old/knn.proto
diff --git a/backend/gRPCProjector/python/protos/v3/projector.proto b/backend/webSocketGateway/protos/v3/old/projector.proto
similarity index 100%
rename from backend/gRPCProjector/python/protos/v3/projector.proto
rename to backend/webSocketGateway/protos/v3/old/projector.proto
diff --git a/protos/build.sh b/protos/build.sh
index cd978c8b4ab906fa3256e48639a28f0c90ad3959..40fedf74c664ca83ad545b3ee7e3ae90a6129ab0 100755
--- a/protos/build.sh
+++ b/protos/build.sh
@@ -1,18 +1,28 @@
 #!/bin/bash
-
+echo "test"
 DIR="$(dirname "$0")"
+PROTOS_DIRECTORY="$PWD/protos"
+PROJECTOR_PROTO_FILE="$PROTOS_DIRECTORY/projector.proto"
+KNN_PROTO_FILE="$PROTOS_DIRECTORY/knn.proto"
 
-PROJECTOR_PROTO_FILE="$DIR/projector.proto"
-
-FRONTEND_GENERATED_DIR="$DIR/../frontend/src/generated"
-BACKEND_GATEWAY_GENERATED_DIR="$DIR/../backend/gateway/src/generated"
+BACKEND_PROJECTOR_GENERATED_DIR="$PWD/../backend/gRPCProjector/python"
+BACKEND_KNN_GENERATED_DIR="$PWD/../backend/grpcKNN"
+BACKEND_GATEWAY_PROTO_DIR="$PWD/../backend/webSocketGateway/protos/v3"
+#Projector
+python -m grpc_tools.protoc \
+        -I "$PROTOS_DIRECTORY" \
+        --python_out="$BACKEND_PROJECTOR_GENERATED_DIR" \
+        --grpc_python_out="$BACKEND_PROJECTOR_GENERATED_DIR" \
+        "$PROJECTOR_PROTO_FILE"
 
-protoc \
-    "$PROJECTOR_PROTO_FILE" \
-    --js_out=import_style=commonjs:"$FRONTEND_GENERATED_DIR" \
-    --grpc-web_out=import_style=commonjs,mode=grpcwebtext:"$FRONTEND_GENERATED_DIR"
+#KNN
+python -m grpc_tools.protoc \
+        -I "$PROTOS_DIRECTORY" \
+        --python_out="$BACKEND_KNN_GENERATED_DIR" \
+        --grpc_python_out="$BACKEND_KNN_GENERATED_DIR" \
+        "$KNN_PROTO_FILE"
 
-grpc_tools_node_protoc \
-    "$PROJECTOR_PROTO_FILE" \
-    --js_out=import_style=commonjs:"$BACKEND_GATEWAY_GENERATED_DIR" \
-    --grpc_out=grpc_js:"$BACKEND_GATEWAY_GENERATED_DIR"
\ No newline at end of file
+#Copy for the gateway
+echo "$BACKEND_GATEWAY_PROTO_DIR"
+cp -fr "$PROJECTOR_PROTO_FILE" "$BACKEND_GATEWAY_PROTO_DIR"
+cp -fr "$KNN_PROTO_FILE" "$BACKEND_GATEWAY_PROTO_DIR"
\ No newline at end of file
diff --git a/protos/protos/knn.proto b/protos/protos/knn.proto
new file mode 100644
index 0000000000000000000000000000000000000000..2bdc51b9b654be823d2db65e7ee50e7b4dacf903
--- /dev/null
+++ b/protos/protos/knn.proto
@@ -0,0 +1,48 @@
+syntax = "proto3";
+
+package provee;
+
+import "google/protobuf/empty.proto";
+
+option java_multiple_files = true;
+option java_package = "nl.uuvig.provee";
+option java_outer_classname = "ProveProjectorGRCP";
+option objc_class_prefix = "PROVEE";
+
+
+// Interface exported by the server.
+service KNN {
+
+
+  rpc sendProjectionPoints(stream TrainingSetRow) returns (google.protobuf.Empty) {}
+  rpc getKNNRequest(knnRequest) returns (Neighbours) {}
+  rpc getIDfromServer(google.protobuf.Empty) returns (ID) {}
+}
+
+message ID{
+  string id = 1;
+}
+
+message knnRequest{
+  int32 k = 1;
+  string words = 2;
+}
+
+message Neighbours {
+  repeated Row rows = 1;
+}
+
+message Row {
+  string id = 1;
+  float distance = 2;
+}
+
+// Needs documentation
+message TrainingSetRow {
+  // The id of the row, e.g., row index.
+  string id = 1;
+
+  // The hd vector of the item.
+  repeated double hdvector = 2 [packed=true];
+}
+
diff --git a/protos/projector.proto b/protos/protos/projector.proto
similarity index 94%
rename from protos/projector.proto
rename to protos/protos/projector.proto
index a2a1dab64955b20ba82e8482070f4131dc483881..de425c04e965f933bfdeac12364f6048b8374035 100644
--- a/protos/projector.proto
+++ b/protos/protos/projector.proto
@@ -25,7 +25,7 @@ service Projector {
   // Obtains the Projection Points in 2D given the trainings values stored in a row format.  Results are
   // streamed rather than returned at once (e.g. in a response message with a
   // repeated field).
-  rpc getProjectionPoints(TrainingSet) returns (stream Point) {}
+  rpc getProjectionPoints(stream TrainingSetRow) returns (stream Point) {}
 
   // A server-to-client streaming RPC.
   //
@@ -50,8 +50,8 @@ service Projector {
 // Points are represented as x-y pairs
 message Point {
   int32 id = 1;
-  int32 x = 2;
-  int32 y = 3;
+  float x = 2;
+  float y = 3;
 }
 
 // Needs description