diff --git a/.gitignore b/.gitignore
index 0414760f748247b419a3846cd9ea6971d1239ab0..3bf900279cbd166eefb172b46786772d381a0b2f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,6 @@ venv/
 __pycache__/
 *.pyc
 .coverage
-Lotte.egg-info/
+Quid.egg-info/
 dist/
 build/
\ No newline at end of file
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 36049c83228240d291d73adbeddaec15b6c4ee26..1263cfc7e2a65cd62a20cbc7002372d54aa8c8b3 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -14,9 +14,9 @@ cache:
 stages:
   - test
   - badge
-  - upload
-  - release
-  - zenodo
+#  - upload
+#  - release
+#  - zenodo
 
 test:
   stage: test
@@ -28,7 +28,7 @@ test:
     - pip install -r requirements.txt
     - pip install coverage
   script:
-    - coverage run --source=lotte,match,key_passager,visualization -m unittest discover -p 'Test*.py'
+    - coverage run --source=quid -m unittest discover -p 'Test*.py'
     - coverage report -m
 
 badge:
@@ -45,35 +45,35 @@ badge:
   only:
     - tags
 
-upload:
-  stage: upload
-  script:
-    - pip install twine
-    - cat $PYPIRC > /tmp/.pypirc
-    - python -m pip install --upgrade build
-    - python -m build
-    - python -m twine upload --repository pypi dist/* --config-file /tmp/.pypirc
-  only:
-    - tags
+#upload:
+#  stage: upload
+#  script:
+#    - pip install twine
+#    - cat $PYPIRC > /tmp/.pypirc
+#    - python -m pip install --upgrade build
+#    - python -m build
+#    - python -m twine upload --repository pypi dist/* --config-file /tmp/.pypirc
+#  only:
+#    - tags
 
-release_job:
-  stage: release
-  image: registry.gitlab.com/gitlab-org/release-cli:latest
-  script:
-    - echo $CI_COMMIT_TAG
-  release:
-    tag_name: $CI_COMMIT_TAG
-    name: 'Lotte $CI_COMMIT_TAG'
-    description: 'Release $CI_COMMIT_TAG'
-  only:
-    - tags
+#release_job:
+#  stage: release
+#  image: registry.gitlab.com/gitlab-org/release-cli:latest
+#  script:
+#    - echo $CI_COMMIT_TAG
+#  release:
+#    tag_name: $CI_COMMIT_TAG
+#    name: 'Quid $CI_COMMIT_TAG'
+#    description: 'Release $CI_COMMIT_TAG'
+#  only:
+#    - tags
 
-zenodo_upload:
-  stage: zenodo
-  before_script:
-    - pip install requests
-  script:
-    - git archive --format zip --output Lotte-$CI_COMMIT_TAG.zip $CI_COMMIT_TAG
-    - python zenodo.py --access-token $ZENODO_ACCESS_TOKEN --id 6123229 --title Lotte --version $CI_COMMIT_TAG --file-path Lotte-$CI_COMMIT_TAG.zip
-  only:
-    - tags
\ No newline at end of file
+#zenodo_upload:
+#  stage: zenodo
+#  before_script:
+#    - pip install requests
+#  script:
+#    - git archive --format zip --output Quid-$CI_COMMIT_TAG.zip $CI_COMMIT_TAG
+#    - python zenodo.py --access-token $ZENODO_ACCESS_TOKEN --id 6123229 --title Quid --version $CI_COMMIT_TAG --file-path Quid-$CI_COMMIT_TAG.zip
+#  only:
+#    - tags
\ No newline at end of file
diff --git a/DATA_STRUCTURE_README.md b/DATA_STRUCTURE_README.md
index 39b6c4f5b75c2f11ddd256e928c6581e8801bc28..e1ee9f6884e91fdee9ccdb64ddf775f3ca78f3c1 100644
--- a/DATA_STRUCTURE_README.md
+++ b/DATA_STRUCTURE_README.md
@@ -5,6 +5,7 @@
 - The extent of a match between source text and target text is always indicated with a start character position, and an end character position.
 
 ## Building blocks
+- Each building block has a corresponding Python class in the `passager` package. This file gives a high level description for each class.
 
 ### SourceSegment
 - One block of text in the source text ranging from `start` to `end`.
@@ -13,7 +14,7 @@
 - A group of overlapping `SourceSegments`
 
 ### TargetLocation
-- One block of text in the target text ranging from `start` to `end`.
+- One block of text (i.e. a quotation) in the target text ranging from `start` to `end`.
 
 ### TargetText
 - One scholarly work with a `filename` and a list of `TargetLocations`.
@@ -26,4 +27,20 @@
 - Only used in combination with `CitationSourceLink` to map `CitationSources` to `TargetLocations`.
 
 ### CitationSourceLink
-- Links a `CitationSource` to a `TargetText` and matched `TargetLocations` via `TargetLocationSelections`.
\ No newline at end of file
+- Links a `CitationSource` to a `TargetText` and matched `TargetLocations` via `TargetLocationSelections`.
+
+## File documentation
+
+### citation_sources.json
+- A list of `CitationSources`. Each `CitationSource` has an ID and a list of `SourceSegments`.
+- A `SourceSegment` has an ID, start and end position, a frequency, a length in tokens and the text of the segment.
+
+### citation_source_links.json
+- A list of `CitationSourceLinks`.
+
+### target_texts.json
+- A list of `TargetTexts`. Each `TargetText` has an ID, a filename and a list of `TargetLocations`.
+- A `TargetLocation` has an ID, a start and end position and the text of the location.
+
+### target_text_location_links.json
+- A list of `TargetTextLocationLinks`.
\ No newline at end of file
diff --git a/README.md b/README.md
index 9c3f495eccf44e0207feaf628ad7b88d1fe04847..d453d289d4314d590b956547fffd970d9cc8c6cf 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,8 @@
 # Readme
 
-Lotte is a tool for quotation detection in texts and can deal with common properties of quotations, for example, ellipses or inaccurate quotations.
+Quid is a tool for quotation detection in texts and can deal with common properties of quotations, for example, ellipses or inaccurate quotations.
 
-If you use Lotte or base your work on our code, please cite our paper:
+If you use Quid or base your work on our code, please cite our paper:
 ~~~
 @inproceedings{arnold2021lotte,
   title = {Lotte and Annette: A Framework for Finding and Exploring Key Passages in Literary Works},
@@ -14,7 +14,7 @@ If you use Lotte or base your work on our code, please cite our paper:
 For a prepint, see [Lotte and Annette: A Framework for Finding and Exploring Key Passages in Literary Works](https://amor.cms.hu-berlin.de/~arnolfre/paper/NLP4DH_2021_arnold_lotte_preprint.pdf)
 
 ## Overview
-Lotte is a tool to find quotations in two texts, called source and target. If known, the source text should be the one that is quoted by the target text. This allows the algorithm to handle things like ellipsis in quotations, e.g.
+Quid is a tool to find quotations in two texts, called source and target. If known, the source text should be the one that is quoted by the target text. This allows the algorithm to handle things like ellipsis in quotations, e.g.
 ~~~
 0	52	This is a long Text and the long test goes on and on
 0	45	This is a long Text [...] test goes on and on
@@ -22,30 +22,30 @@ Lotte is a tool to find quotations in two texts, called source and target. If kn
 
 ## Installation
 ~~~
-pip install Lotte
+pip install Quid
 ~~~
 
 ## Usage
 There are two ways to use the algorithm. The following two sections describe the use of the algorithm in code and from the command line.
 
 ### In code
-The algorithm can be found in the package `lotte`. To use it create a `Lotte` object which expects the following arguments:
+The algorithm can be found in the package `quid`. To use it create a `Quid` object which expects the following arguments:
 - The length of the shortest match (default: 5)
 - The number of tokens to skip when looking backwards (default: 10)
 - The number of tokens to skip when looking ahead (default: 3)
 - The maximum distance in tokens between to matches considered for merging (default: 2)
 - The maximum distance in tokens between two matches considered for merging where the target text contains an ellipsis between the matches (default: 10)
 
-
 Then call the `compare` method on the object which expects two texts to be compared.
-The method returns a list with the following structure: `List[Match]`. `Match` stores two `MatchSegments`. One for the source text and one for the target text. `MatchSegment` stores the `character_start_pos` and `character_end_pos` for the matching segments in the source and target text.
+The method returns a list with the following structure: `List[Match]`. `Match` stores two `MatchSpans`. One for the source text and one for the target text. `MatchSpan` stores the `start` and `end` character positions for the matching spans in the source and target text.
 
 ### Command line
-The `lotte compare` command provides a command line interface to the algorithm.
+The `quid compare` command provides a command line interface to the algorithm.
 
 ~~~
-usage: LotteCLI.py compare [-h] [--text] [--no-text]
-                           [--output-type {json,text}]
+usage: QuidCLI.py compare [-h] [--text] [--no-text]
+                           [--output-type {json,text, csv}]
+                           [--csv-sep CSV_SEP]
                            [--output-folder-path OUTPUT_FOLDER_PATH]
                            [--min-match-length MIN_MATCH_LENGTH]
                            [--look-back-limit LOOK_BACK_LIMIT]
@@ -59,7 +59,7 @@ usage: LotteCLI.py compare [-h] [--text] [--no-text]
                            [--no-keep-ambiguous-matches]
                            source-file-path target-path
 
-Lotte compare allows the user to find quotations in two texts, a source text
+Quid compare allows the user to find quotations in two texts, a source text
 and a target text. If known, the source text should be the one that is quoted
 by the target text. This allows the algorithm to handle things like ellipsis
 in quotations.
@@ -73,8 +73,9 @@ optional arguments:
   --text                Include matched text in the returned data structure
   --no-text             Don't include matched text in the returned data
                         structure
-  --output-type {json,text}
+  --output-type {json,text, csv}
                         The output type
+  --csv-sep CSV_SEP     output separator for csv (default: '\t')
   --output-folder-path OUTPUT_FOLDER_PATH
                         The output folder path. If this option is set the
                         output will be saved to a file created in the
@@ -109,20 +110,20 @@ optional arguments:
                         Don't ambiguous matches
 ~~~
 
-By default, the result is returned as a json structure: `List[Match]`. `Match` stores two `MatchSegments`. One for the source text and one for the target text. `MatchSegment` stores the `character_start_pos` and `character_end_pos` for the matching segments in the source and target text.
+By default, the result is returned as a json structure: `List[Match]`. `Match` stores two `MatchSpans`. One for the source text and one for the target text. `MatchSpan` stores the `start` and `end` character positions for the matching spans in the source and target text.
 For example,
 
 ~~~
 [
   {
-    "source_match_segment": {
-      "character_start_pos": 0,
-      "character_end_pos": 52,
+    "source_span": {
+      "start": 0,
+      "end": 52,
       "text": "This is a long Text and the long test goes on and on"
     },
-    "target_match_segment": {
-      "character_start_pos": 0,
-      "character_end_pos": 45,
+    "target_span": {
+      "start": 0,
+      "end": 45,
       "text": "This is a long Text [...] test goes on and on"
     }
   }
@@ -138,16 +139,17 @@ Alternatively, the result can be printed in a human-readable text format, e.g.:
 
 In case the matching text is not needed, the option --no-text allows to exclude the text from the output.
 
-## KeyPassager
-The package `key_passager` contains code to extract key passages from the found matches. The resulting data structure is documented in the [data structure readme](DATA_STRUCTURE_README.md).
+## Passager
+The package `passager` contains code to extract key passages from the found matches. The `passage` command produces several json files.
+The resulting data structure is documented in the [data structure readme](DATA_STRUCTURE_README.md).
 
 ### Usage
 ~~~
-usage: LotteCLI.py keypassage [-h]
+usage: QuidCLI.py passage [-h]
                               source-file-path target-folder-path
                               matches-folder-path output-folder-path
 
-Lotte keypassage allows the user to extract key passages from the found
+Quid passage allows the user to extract key passages from the found
 matches.
 
 positional arguments:
@@ -159,24 +161,24 @@ positional arguments:
 
 ## Visualization
 The package `visualization` contains code to create the content for a web page to visualize the key passages.
-For the website, see [LotteVizEx](/../../../../lottevizex/).
+For a white label version of the website, see [LotteVizEx](https://scm.cms.hu-berlin.de/schluesselstellen/lottevizex).
 
 ### Usage
 ~~~
-usage: LotteCLI.py visualize [-h] [--title TITLE] [--author AUTHOR]
+usage: QuidCLI.py visualize [-h] [--title TITLE] [--author AUTHOR]
                              [--year YEAR] [--censor]
                              source-file-path target-folder-path
-                             key-passages-folder-path output-folder-path
+                             passages-folder-path output-folder-path
 
-Lotte visualize allows the user to create the files needed for a website that
-visualizes the lotte algorithm results.
+Quid visualize allows the user to create the files needed for a website that
+visualizes the Quid algorithm results.
 
 positional arguments:
   source-file-path      Path to the source text file
   target-folder-path    Path to the target texts folder path
-  key-passages-folder-path
+  passages-folder-path
                         Path to the folder with the key passages files, i.e.
-                        the resulting files from lotte keypassage
+                        the resulting files from Quid passage
   output-folder-path    Path to the output folder
 
 optional arguments:
diff --git a/lotte/InternalMatch.py b/lotte/InternalMatch.py
deleted file mode 100644
index 296b5f66869752c11a3359a23fb69be814bfa4b0..0000000000000000000000000000000000000000
--- a/lotte/InternalMatch.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from dataclasses import dataclass
-from lotte.InternalMatchSegment import InternalMatchSegment
-
-
-@dataclass
-class InternalMatch:
-    source_match_segment: InternalMatchSegment
-    target_match_segment: InternalMatchSegment
diff --git a/lotte/InternalMatchSegment.py b/lotte/InternalMatchSegment.py
deleted file mode 100644
index f619871214a58618526dc39b1f007154bce2484e..0000000000000000000000000000000000000000
--- a/lotte/InternalMatchSegment.py
+++ /dev/null
@@ -1,9 +0,0 @@
-class InternalMatchSegment:
-    def __init__(self, token_start_pos: int, token_length: int, character_start_pos: int, character_end_pos: int):
-        self.token_start_pos = token_start_pos
-        self.token_length = token_length
-        self.character_start_pos = character_start_pos
-        self.character_end_pos = character_end_pos
-
-    def __str__(self):  # pragma: no cover
-        return "MatchSegment (" + str(self.character_start_pos) + ", " + str(self.character_end_pos) + ")"
diff --git a/match/Match.py b/match/Match.py
deleted file mode 100644
index 3f0310ac6c28e9bb797aa068efc4585e59668fee..0000000000000000000000000000000000000000
--- a/match/Match.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from dataclasses import dataclass
-from match.MatchSegment import MatchSegment
-
-
-@dataclass
-class Match:
-    source_match_segment: MatchSegment
-    target_match_segment: MatchSegment
diff --git a/match/MatchSegment.py b/match/MatchSegment.py
deleted file mode 100644
index 8198d86fd25325e3e6f4c6d1d1c5311c7e2a2fd0..0000000000000000000000000000000000000000
--- a/match/MatchSegment.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from dataclasses import dataclass
-
-
-@dataclass
-class MatchSegment:
-    character_start_pos: int
-    character_end_pos: int
-    text: str = ''
diff --git a/quid/__init__.py b/quid/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/cli/LotteCLI.py b/quid/cli/QuidCLI.py
similarity index 74%
rename from cli/LotteCLI.py
rename to quid/cli/QuidCLI.py
index b235a4497adaa6a6b375492fa298737dce1ce19e..2bfcc54ddb4417cf452c46e9e0daa0dd7d8610b9 100644
--- a/cli/LotteCLI.py
+++ b/quid/cli/QuidCLI.py
@@ -1,11 +1,11 @@
-import argparse
+import sys
 import logging
-from argparse import ArgumentParser
+from argparse import ArgumentParser, Action
 from typing import List
 
-from key_passager.KeyPassager import KeyPassager
-from key_passager.TextWithMatches import TextWithMatches
-from lotte.Lotte import Lotte
+from quid.passager.Passager import Passager
+from quid.passager.TextWithMatches import TextWithMatches
+from quid.core.Quid import Quid
 import json
 import time
 from os.path import join, isfile, splitext, basename
@@ -14,26 +14,26 @@ from shutil import copyfile
 import multiprocessing
 from datetime import datetime
 from pathlib import Path
-from key_passager.CitationSource import CitationSource
-from key_passager.CitationSourceLink import CitationSourceLink
-from key_passager.ImportantSegment import ImportantSegment
-from key_passager.ImportantSegmentLink import ImportantSegmentLink
-from key_passager.SourceSegment import SourceSegment
-from key_passager.TargetLocation import TargetLocation
-from key_passager.TargetLocationSelection import TargetLocationSelection
-from key_passager.TargetText import TargetText
-from key_passager.TargetTextLocationLink import TargetTextLocationLink
-from match.MatchSegment import MatchSegment
-from visualization.Info import Info
-from visualization.TargetTextWithContent import TargetTextWithContent
-from visualization.Visualizer import Visualizer
-from helper.Loader import load_matches, load_citation_sources, load_citation_source_links
+from quid.passager.CitationSource import CitationSource
+from quid.passager.CitationSourceLink import CitationSourceLink
+from quid.passager.ImportantSegment import ImportantSegment
+from quid.passager.ImportantSegmentLink import ImportantSegmentLink
+from quid.passager.SourceSegment import SourceSegment
+from quid.passager.TargetLocation import TargetLocation
+from quid.passager.TargetLocationSelection import TargetLocationSelection
+from quid.passager.TargetText import TargetText
+from quid.passager.TargetTextLocationLink import TargetTextLocationLink
+from quid.match.MatchSpan import MatchSpan
+from quid.visualization.Info import Info
+from quid.visualization.TargetTextWithContent import TargetTextWithContent
+from quid.visualization.Visualizer import Visualizer
+from quid.helper.Loader import load_matches, load_citation_sources, load_citation_source_links
 
 
 logging.getLogger().setLevel(logging.INFO)
 
 
-class IntCheckAction(argparse.Action):
+class IntCheckAction(Action):
 
     def __call__(self, parser, namespace, values, option_string=None):
 
@@ -66,8 +66,8 @@ def __json_decoder_target_text(json_input):
         return TargetLocation(json_input['my_id'], json_input['start'], json_input['end'], json_input['text'])
 
 
-def __json_encoder_lotte(obj):
-    if isinstance(obj, MatchSegment):
+def __json_encoder_quid(obj):
+    if isinstance(obj, MatchSpan):
         result_dict = obj.__dict__
 
         if not result_dict['text']:
@@ -78,7 +78,7 @@ def __json_encoder_lotte(obj):
     return obj.__dict__
 
 
-def __json_encoder_key_passager(obj):
+def __json_encoder_passager(obj):
     return __json_encoder(obj, False)
 
 
@@ -152,7 +152,7 @@ def __json_encoder(obj, strip):
     return obj
 
 
-def __run_compare(source_file_path, target_path, export_text, output_type, min_match_length, look_ahead_limit,
+def __run_compare(source_file_path, target_path, export_text, output_type, csv_sep, min_match_length, look_ahead_limit,
                   look_back_limit, max_merge_distance, max_merge_ellipsis_distance, output_folder_path,
                   num_of_processes, keep_ambiguous_matches):
     with open(source_file_path, 'r', encoding='utf-8') as source_file:
@@ -165,7 +165,7 @@ def __run_compare(source_file_path, target_path, export_text, output_type, min_m
 
         filename = splitext(basename(target_path))[0]
 
-        __process_file(source_file_content, target_file_content, export_text, output_type, min_match_length,
+        __process_file(source_file_content, target_file_content, export_text, output_type, csv_sep, min_match_length,
                        look_ahead_limit, look_back_limit, max_merge_distance, max_merge_ellipsis_distance,
                        output_folder_path, filename, keep_ambiguous_matches)
     else:
@@ -180,7 +180,7 @@ def __run_compare(source_file_path, target_path, export_text, output_type, min_m
 
                 filename = splitext(basename(full_path))[0]
                 pool.apply_async(__process_file, args=(source_file_content, target_file_content, export_text,
-                                                       output_type, min_match_length, look_ahead_limit,
+                                                       output_type, csv_sep, min_match_length, look_ahead_limit,
                                                        look_back_limit, max_merge_distance,
                                                        max_merge_ellipsis_distance, output_folder_path,
                                                        filename, keep_ambiguous_matches))
@@ -189,37 +189,52 @@ def __run_compare(source_file_path, target_path, export_text, output_type, min_m
         pool.join()
 
 
-def __process_file(source_file_content, target_file_content, export_text, output_type, min_match_length,
+def __process_file(source_file_content, target_file_content, export_text, output_type, csv_sep, min_match_length,
                    look_ahead_limit, look_back_limit, max_merge_distance, max_merge_ellipsis_distance,
                    output_folder_path, filename, keep_ambiguous_matches):
-    lotte = Lotte(min_match_length, look_back_limit, look_ahead_limit, max_merge_distance, max_merge_ellipsis_distance,
-                  export_text, keep_ambiguous_matches)
-    matches = lotte.compare(source_file_content, target_file_content)
+    quid = Quid(min_match_length, look_back_limit, look_ahead_limit, max_merge_distance, max_merge_ellipsis_distance,
+                export_text, keep_ambiguous_matches)
+    matches = quid.compare(source_file_content, target_file_content)
 
     if not export_text:
         for match in matches:
-            match.source_match_segment.text = ''
-            match.target_match_segment.text = ''
+            match.source_span.text = ''
+            match.target_span.text = ''
 
     if output_type == 'json':
-        result = json.dumps(matches, default=__json_encoder_lotte)
+        result = json.dumps(matches, default=__json_encoder_quid)
         file_ending = 'json'
+    elif output_type == 'csv':
+        result = ''
+
+        for match in matches:
+            source_span = match.source_span
+            target_span = match.target_span
+
+            result += f'\n{source_span.start}{csv_sep}{source_span.end}{csv_sep}{target_span.start}' \
+                      f'{csv_sep}{target_span.end}'
+
+            if export_text:
+                result += f'{csv_sep}{source_span.text}{csv_sep}{target_span.text}'
+
+        result = result.strip()
+        file_ending = 'csv'
     else:
         result = ''
 
         for match in matches:
-            source_segment = match.source_match_segment
-            target_segment = match.target_match_segment
+            source_span = match.source_span
+            target_span = match.target_span
 
-            result += f'\n\n{source_segment.character_start_pos}\t{source_segment.character_end_pos}'
+            result += f'\n\n{source_span.start}\t{source_span.end}'
 
             if export_text:
-                result += f'\t{source_segment.text}'
+                result += f'\t{source_span.text}'
 
-            result += f'\n{target_segment.character_start_pos}\t{target_segment.character_end_pos}'
+            result += f'\n{target_span.start}\t{target_span.end}'
 
             if export_text:
-                result += f'\t{target_segment.text}'
+                result += f'\t{target_span.text}'
 
         result = result.strip()
         file_ending = 'txt'
@@ -234,8 +249,8 @@ def __process_file(source_file_content, target_file_content, export_text, output
         print(result)
 
 
-def __run_key_passager(source_file_path, target_folder_path, matches_folder_path, output_folder_path):
-    key_passager = KeyPassager()
+def __run_passager(source_file_path, target_folder_path, matches_folder_path, output_folder_path):
+    passager = Passager()
 
     with open(source_file_path, 'r', encoding='utf-8') as source_file:
         source_content = source_file.read()
@@ -252,45 +267,45 @@ def __run_key_passager(source_file_path, target_folder_path, matches_folder_path
                 target_content = target_file.read()
 
             matches = load_matches(matches_file_path)
-            matches.sort(key=lambda x: x.source_match_segment.character_start_pos)
+            matches.sort(key=lambda x: x.source_span.start)
 
             target_text_matches_list.append(TextWithMatches(filename, target_content, matches))
 
-    analyzed_work = key_passager.generate(target_text_matches_list, source_content)
+    analyzed_work = passager.generate(target_text_matches_list, source_content)
 
     with open(join(output_folder_path, 'target_texts.json'), 'w', encoding='utf-8') as target_works_output_file:
-        content = json.dumps(analyzed_work.target_texts, default=__json_encoder_key_passager)
+        content = json.dumps(analyzed_work.target_texts, default=__json_encoder_passager)
         target_works_output_file.write(content)
 
     with open(join(output_folder_path, 'citation_sources.json'), 'w', encoding='utf-8') as segments_output_file:
-        content = json.dumps(list(analyzed_work.citation_sources), default=__json_encoder_key_passager)
+        content = json.dumps(list(analyzed_work.citation_sources), default=__json_encoder_passager)
         segments_output_file.write(content)
 
     with open(join(output_folder_path, 'target_text_location_links.json'), 'w', encoding='utf-8') as \
             target_text_location_links_output_file:
-        content = json.dumps(analyzed_work.target_text_location_links, default=__json_encoder_key_passager)
+        content = json.dumps(analyzed_work.target_text_location_links, default=__json_encoder_passager)
         target_text_location_links_output_file.write(content)
 
     with open(join(output_folder_path, 'citation_source_links.json'), 'w', encoding='utf-8') as \
             citation_source_links_output_file:
-        content = json.dumps(analyzed_work.citation_source_links, default=__json_encoder_key_passager)
+        content = json.dumps(analyzed_work.citation_source_links, default=__json_encoder_passager)
         citation_source_links_output_file.write(content)
 
     with open(join(output_folder_path, 'important_segment_links.json'), 'w', encoding='utf-8') as \
             important_segment_links_output_file:
-        content = json.dumps(analyzed_work.important_segment_links, default=__json_encoder_key_passager)
+        content = json.dumps(analyzed_work.important_segment_links, default=__json_encoder_passager)
         important_segment_links_output_file.write(content)
 
 
-def __run_visualize(source_file_path, target_folder_path, key_passages_folder_path, output_folder_path, title, author,
+def __run_visualize(source_file_path, target_folder_path, passages_folder_path, output_folder_path, title, author,
                     year, censor):
     with open(source_file_path, 'r', encoding='utf-8') as source_file:
         source_content = source_file.read()
 
-    citation_sources = load_citation_sources(join(key_passages_folder_path, 'citation_sources.json'))
-    citation_source_links = load_citation_source_links(join(key_passages_folder_path, 'citation_source_links.json'))
+    citation_sources = load_citation_sources(join(passages_folder_path, 'citation_sources.json'))
+    citation_source_links = load_citation_source_links(join(passages_folder_path, 'citation_source_links.json'))
 
-    with open(join(key_passages_folder_path, 'target_texts.json'), 'r', encoding='utf-8') as target_texts_file:
+    with open(join(passages_folder_path, 'target_texts.json'), 'r', encoding='utf-8') as target_texts_file:
         target_texts = json.load(target_texts_file, object_hook=__json_decoder_target_text)
 
     target_texts_with_content: List[TargetTextWithContent] = []
@@ -320,12 +335,12 @@ def __run_visualize(source_file_path, target_folder_path, key_passages_folder_pa
                 target_html_output_file:
             target_html_output_file.write(target_html.text)
 
-    copyfile(join(key_passages_folder_path, 'citation_source_links.json'), join(output_folder_path,
-                                                                                'citation_source_links.json'))
-    copyfile(join(key_passages_folder_path, 'important_segment_links.json'), join(output_folder_path,
-                                                                                  'important_segment_links.json'))
-    copyfile(join(key_passages_folder_path, 'target_text_location_links.json'), join(output_folder_path,
-                                                                                     'target_text_location_links.json'))
+    copyfile(join(passages_folder_path, 'citation_source_links.json'), join(output_folder_path,
+                                                                            'citation_source_links.json'))
+    copyfile(join(passages_folder_path, 'important_segment_links.json'), join(output_folder_path,
+                                                                              'important_segment_links.json'))
+    copyfile(join(passages_folder_path, 'target_text_location_links.json'), join(output_folder_path,
+                                                                                 'target_text_location_links.json'))
 
     with open(join(output_folder_path, 'citation_sources.json'), 'w', encoding='utf-8') as citation_sources_output_file:
         content = json.dumps(citation_sources, default=__json_encoder_visualization)
@@ -336,12 +351,12 @@ def __run_visualize(source_file_path, target_folder_path, key_passages_folder_pa
         target_texts_output_file.write(content)
 
 
-def main():
-    compare_description = "Lotte compare allows the user to find quotations in two texts, a source text and a target " \
+def main(argv=None):
+    compare_description = "Quid compare allows the user to find quotations in two texts, a source text and a target " \
                           "text. If known, the source text should be the one that is quoted by the target text. " \
                           "This allows the algorithm to handle things like ellipsis in quotations."
 
-    argument_parser = ArgumentParser(description="Lotte is a tool to find quotations in texts and to visualize the"
+    argument_parser = ArgumentParser(description="Quid is a tool to find quotations in texts and to visualize the"
                                                  " matching segments.")
 
     subparsers = argument_parser.add_subparsers(dest='command')
@@ -357,8 +372,10 @@ def main():
                                 help="Include matched text in the returned data structure")
     parser_compare.add_argument('--no-text', dest='export_text', action='store_false',
                                 help="Don't include matched text in the returned data structure")
-    parser_compare.add_argument('--output-type', choices=['json', 'text'], dest="output_type", default="json",
+    parser_compare.add_argument('--output-type', choices=['json', 'text', 'csv'], dest="output_type", default="json",
                                 help="The output type")
+    parser_compare.add_argument('--csv-sep', dest='csv_sep', type=str, help="output separator for csv (default: '\\t')",
+                                default='\t')
     parser_compare.add_argument('--output-folder-path', dest="output_folder_path",
                                 help="The output folder path. If this option is set the output will be saved to a file"
                                      " created in the specified folder")
@@ -391,33 +408,32 @@ def main():
     parser_compare.add_argument('--no-keep-ambiguous-matches', dest='keep_ambiguous_matches', action='store_false',
                                 help="Don't ambiguous matches")
 
-    keypassage_description = 'Lotte keypassage allows the user to extract key passages from the found matches.'
+    passage_description = 'Quid passage allows the user to extract key passages from the found matches.'
 
-    parser_key_passage = subparsers.add_parser('keypassage', help=keypassage_description,
-                                               description=keypassage_description)
+    parser_passage = subparsers.add_parser('passage', help=passage_description, description=passage_description)
 
-    parser_key_passage.add_argument("source_file_path", nargs=1, metavar="source-file-path",
-                                    help="Path to the source text file")
-    parser_key_passage.add_argument("target_folder_path", nargs=1, metavar="target-folder-path",
-                                    help="Path to the target texts folder path")
-    parser_key_passage.add_argument("matches_folder_path", nargs=1, metavar="matches-folder-path",
-                                    help="Path to the folder with the match files, i.e. the results from lotte compare")
-    parser_key_passage.add_argument("output_folder_path", nargs=1, metavar="output-folder-path",
-                                    help="Path to the output folder")
+    parser_passage.add_argument("source_file_path", nargs=1, metavar="source-file-path",
+                                help="Path to the source text file")
+    parser_passage.add_argument("target_folder_path", nargs=1, metavar="target-folder-path",
+                                help="Path to the target texts folder path")
+    parser_passage.add_argument("matches_folder_path", nargs=1, metavar="matches-folder-path",
+                                help="Path to the folder with the match files, i.e. the results from quid compare")
+    parser_passage.add_argument("output_folder_path", nargs=1, metavar="output-folder-path",
+                                help="Path to the output folder")
 
     parser_visualize = subparsers.add_parser('visualize',
-                                             help="Lotte visualize allows the user to create the files needed"
-                                                  " for a website that visualizes the lotte algorithm results.",
-                                             description="Lotte visualize allows the user to create the files needed"
-                                                         " for a website that visualizes the lotte algorithm results.")
+                                             help="Quid visualize allows the user to create the files needed"
+                                                  " for a website that visualizes the quid algorithm results.",
+                                             description="Quid visualize allows the user to create the files needed"
+                                                         " for a website that visualizes the quid algorithm results.")
 
     parser_visualize.add_argument("source_file_path", nargs=1, metavar="source-file-path",
                                   help="Path to the source text file")
     parser_visualize.add_argument("target_folder_path", nargs=1, metavar="target-folder-path",
                                   help="Path to the target texts folder path")
-    parser_visualize.add_argument("key_passages_folder_path", nargs=1, metavar="key-passages-folder-path",
+    parser_visualize.add_argument("passages_folder_path", nargs=1, metavar="passages-folder-path",
                                   help="Path to the folder with the key passages files, i.e. the resulting files from"
-                                       " lotte keypassage")
+                                       " quid passage")
     parser_visualize.add_argument("output_folder_path", nargs=1, metavar="output-folder-path",
                                   help="Path to the output folder")
     parser_visualize.add_argument("--title", dest="title", help="Title of the work", default="NN")
@@ -426,13 +442,14 @@ def main():
     parser_visualize.add_argument('--censor', dest="censor", default=False, action='store_true',
                                   help="Censor scholarly works to prevent copyright violations")
 
-    args = argument_parser.parse_args()
+    args = argument_parser.parse_args(argv)
 
     if args.command == 'compare':
         source_path = args.source_file_path[0]
         target_path = args.target_path[0]
         export_text = args.export_text
         output_type = args.output_type
+        csv_sep = bytes(args.csv_sep, "utf-8").decode("unicode_escape")
         output_folder_path = args.output_folder_path
         min_match_length = args.min_match_length
         look_ahead_limit = args.look_ahead_limit
@@ -451,23 +468,23 @@ def main():
 
         start_time = time.perf_counter()
 
-        __run_compare(source_path, target_path, export_text, output_type, min_match_length, look_ahead_limit,
+        __run_compare(source_path, target_path, export_text, output_type, csv_sep, min_match_length, look_ahead_limit,
                       look_back_limit, max_merge_distance, max_merge_ellipsis_distance, output_folder_path,
                       max_num_processes, keep_ambiguous_matches)
 
         end_time = time.perf_counter()
         logging.info(f'\n--- Runtime: {end_time - start_time: .2f} seconds ---')
-    elif args.command == 'keypassage':
+    elif args.command == 'passage':
         source_file_path = args.source_file_path[0]
         target_folder_path = args.target_folder_path[0]
         matches_folder_path = args.matches_folder_path[0]
         output_folder_path = args.output_folder_path[0]
 
-        __run_key_passager(source_file_path, target_folder_path, matches_folder_path, output_folder_path)
+        __run_passager(source_file_path, target_folder_path, matches_folder_path, output_folder_path)
     elif args.command == 'visualize':
         source_file_path = args.source_file_path[0]
         target_folder_path = args.target_folder_path[0]
-        key_passages_folder_path = args.key_passages_folder_path[0]
+        passages_folder_path = args.passages_folder_path[0]
         output_folder_path = args.output_folder_path[0]
         title = args.title
 
@@ -476,11 +493,11 @@ def main():
         censor = args.censor
 
         start_time = time.perf_counter()
-        __run_visualize(source_file_path, target_folder_path, key_passages_folder_path, output_folder_path, title,
+        __run_visualize(source_file_path, target_folder_path, passages_folder_path, output_folder_path, title,
                         author, year, censor)
         end_time = time.perf_counter()
         logging.info(f'\n--- Runtime: {end_time - start_time: .2f} seconds ---')
 
 
 if __name__ == '__main__':
-    main()
+    sys.exit(main())
diff --git a/quid/cli/__init__.py b/quid/cli/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/lotte/BestMatch.py b/quid/core/BestMatch.py
similarity index 63%
rename from lotte/BestMatch.py
rename to quid/core/BestMatch.py
index bf1761ae327ab13caadab138bcdb39db87ae18b9..6c5c5720412e25ac030dcbcf9eab112323511008 100644
--- a/lotte/BestMatch.py
+++ b/quid/core/BestMatch.py
@@ -3,7 +3,7 @@ from dataclasses import dataclass
 
 @dataclass
 class BestMatch:
-    source_token_start_pos: int
-    target_token_start_pos: int
+    source_token_start: int
+    target_token_start: int
     source_length: int
     target_length: int
diff --git a/quid/core/InternalMatch.py b/quid/core/InternalMatch.py
new file mode 100644
index 0000000000000000000000000000000000000000..db8af633c145480df2584b4ce0459b8dc8e30e5f
--- /dev/null
+++ b/quid/core/InternalMatch.py
@@ -0,0 +1,8 @@
+from dataclasses import dataclass
+from quid.core.InternalMatchSpan import InternalMatchSpan
+
+
+@dataclass
+class InternalMatch:
+    source_match_span: InternalMatchSpan
+    target_match_span: InternalMatchSpan
diff --git a/quid/core/InternalMatchSpan.py b/quid/core/InternalMatchSpan.py
new file mode 100644
index 0000000000000000000000000000000000000000..27a7b9e8695852579d6aa506ef18c77c2bed19bc
--- /dev/null
+++ b/quid/core/InternalMatchSpan.py
@@ -0,0 +1,9 @@
+class InternalMatchSpan:
+    def __init__(self, token_start: int, token_length: int, character_start: int, character_end: int):
+        self.token_start_pos = token_start
+        self.token_length = token_length
+        self.character_start = character_start
+        self.character_end = character_end
+
+    def __str__(self):  # pragma: no cover
+        return "MatchSpan (" + str(self.character_start) + ", " + str(self.character_end) + ")"
diff --git a/lotte/Lotte.py b/quid/core/Quid.py
similarity index 78%
rename from lotte/Lotte.py
rename to quid/core/Quid.py
index 28c363046e9550f388a9480996d564cc2d902c99..eaf196341e9a34fbdb9e1b2806affe6fc5129c1a 100644
--- a/lotte/Lotte.py
+++ b/quid/core/Quid.py
@@ -1,13 +1,13 @@
 import warnings
 from typing import List, Dict, Optional
-from lotte.InternalMatch import InternalMatch
-from lotte.BestMatch import BestMatch
-from lotte.InternalMatchSegment import InternalMatchSegment
-from match.Match import Match
-from match.MatchSegment import MatchSegment
-from lotte.Text import Text
+from quid.core.InternalMatch import InternalMatch
+from quid.core.BestMatch import BestMatch
+from quid.core.InternalMatchSpan import InternalMatchSpan
+from quid.match.Match import Match
+from quid.match.MatchSpan import MatchSpan
+from quid.core.Text import Text
 import re
-from lotte.Token import Token
+from quid.core.Token import Token
 from rapidfuzz import fuzz, process
 from datasketch import MinHash, MinHashLSH
 
@@ -16,7 +16,7 @@ from datasketch import MinHash, MinHashLSH
 # This algorithm is based on the algorithm by Dick Grune, see https://dickgrune.com/Programs/similarity_tester/.
 # And a Javascript implementation, see
 # https://people.f4.htw-berlin.de/~weberwu/simtexter/522789_Sofia-Kalaidopoulou_bachelor-thesis.pdf
-class Lotte:
+class Quid:
     tokens: List[Token]
     texts: List[Text]
     forward_references: Dict[int, List[int]]
@@ -48,23 +48,23 @@ class Lotte:
         """
 
         if min_match_length < 1:
-            raise ValueError("min match length must be >= 1")
+            raise ValueError('min match length must be >= 1')
 
         if min_match_length < 3:
-            warnings.warn("A small minimal match length can lead to long processing times "
-                          "(recommendation: min_match_length >= 3)")
+            warnings.warn('A small minimal match length can lead to long processing times '
+                          '(recommendation: min_match_length >= 3)')
 
         if look_back_limit < 0:
-            raise ValueError("look back limit must be positive")
+            raise ValueError('look back limit must be positive')
 
         if look_ahead_limit < 0:
-            raise ValueError("look ahead limit must be positive")
+            raise ValueError('look ahead limit must be positive')
 
         if max_merge_distance < 0:
-            raise ValueError("max merge distance must be positive")
+            raise ValueError('max merge distance must be positive')
 
         if max_merge_ellipse_distance < 0:
-            raise ValueError("max merge ellipse distance must be positive")
+            raise ValueError('max merge ellipse distance must be positive')
 
         self.initial_match_length = min(3, min_match_length)
         self.min_match_length = min_match_length
@@ -98,12 +98,12 @@ class Lotte:
         min_length_match_positions, hashes = self.__make_min_length_match_starting_positions(self.texts[0])
         self.__make_forward_references(self.texts[1], min_length_match_positions, hashes)
         matches: List[InternalMatch] = self.__get_similarities(self.texts[0], self.texts[1])
-        matches.sort(key=lambda x: x.target_match_segment.character_start_pos, reverse=False)
+        matches.sort(key=lambda x: x.target_match_span.character_start, reverse=False)
 
         # self.__print_matches(matches, source_text, target_text)
 
         cleaned_matches: List[InternalMatch] = self.__merge_neighbouring_matches(matches)
-        cleaned_matches = self.__remove_matches_with_overlapping_target_match_segments(cleaned_matches)
+        cleaned_matches = self.__remove_matches_with_overlapping_target_match_spans(cleaned_matches)
         cleaned_matches = self.__remove_too_short_matches(cleaned_matches)
         self.__remove_boundary_overshoot(cleaned_matches)
 
@@ -111,21 +111,21 @@ class Lotte:
 
         result: List[Match] = []
         for internal_match in cleaned_matches:
-            source_match_segment = MatchSegment(internal_match.source_match_segment.character_start_pos,
-                                                internal_match.source_match_segment.character_end_pos)
-            target_match_segment = MatchSegment(internal_match.target_match_segment.character_start_pos,
-                                                internal_match.target_match_segment.character_end_pos)
+            source_match_span = MatchSpan(internal_match.source_match_span.character_start,
+                                          internal_match.source_match_span.character_end)
+            target_match_span = MatchSpan(internal_match.target_match_span.character_start,
+                                          internal_match.target_match_span.character_end)
 
             if self.include_text_in_result:
-                segment_source_text = source_text[source_match_segment.character_start_pos:
-                                                  source_match_segment.character_end_pos]
-                segment_target_text = target_text[target_match_segment.character_start_pos:
-                                                  target_match_segment.character_end_pos]
+                segment_source_text = source_text[source_match_span.start:
+                                                  source_match_span.end]
+                segment_target_text = target_text[target_match_span.start:
+                                                  target_match_span.end]
 
-                source_match_segment.text = segment_source_text
-                target_match_segment.text = segment_target_text
+                source_match_span.text = segment_source_text
+                target_match_span.text = segment_target_text
 
-            result.append(Match(source_match_segment, target_match_segment))
+            result.append(Match(source_match_span, target_match_span))
 
         return result
 
@@ -149,7 +149,7 @@ class Lotte:
         cleaned_text = self.__clean_text(input_text)
         tokens = []
 
-        for match in re.finditer("[^\\s]+", cleaned_text):
+        for match in re.finditer(r'\S+', cleaned_text):
             token = self.__clean_word(match.group())
 
             if len(token) > 0:
@@ -160,10 +160,10 @@ class Lotte:
         return tokens
 
     def __clean_text(self, input_text: str) -> str:
-        input_text = re.sub("(\\[\\.\\.\\.]|\\[…]|\\.\\.\\.|…)", lambda x: '@' * len(x.group(1)), input_text)
-        input_text = re.sub("[.;!?]", self.SENTENCE_DELIMITER, input_text)
-        input_text = re.sub(f"[^a-zA-Z0-9äüöÄÜÖß@{self.SENTENCE_DELIMITER} ]", " ", input_text)
-        input_text = re.sub("[0-9]", " ", input_text)
+        input_text = re.sub('(\\[\\.\\.\\.]|\\[…]|\\.\\.\\.|…)', lambda x: '@' * len(x.group(1)), input_text)
+        input_text = re.sub('[.;!?]', self.SENTENCE_DELIMITER, input_text)
+        input_text = re.sub(f'[^a-zA-Z\\däüöÄÜÖß@{self.SENTENCE_DELIMITER} ]', ' ', input_text)
+        input_text = re.sub(r'\d', ' ', input_text)
         return input_text.lower()
 
     def __clean_word(self, input_word: str) -> str:
@@ -176,10 +176,10 @@ class Lotte:
 
     def __remove_special_characters(self, input_string: str) -> str:
 
-        input_string = re.sub("[^a-zA-Z0-9äüöÄÜÖß@ ]", "", input_string)
+        input_string = re.sub(r'[^a-zA-Z\däüöÄÜÖß@ ]', '', input_string)
 
-        if re.search('[a-zA-Z0-9äüöÄÜÖß]', input_string):
-            input_string = re.sub("@", "", input_string)
+        if re.search(r'[a-zA-Z\däüöÄÜÖß]', input_string):
+            input_string = re.sub('@', '', input_string)
 
         return input_string
 
@@ -286,25 +286,25 @@ class Lotte:
                                                                     source_token_start_pos)
 
             if best_match and best_match.source_length > 0:
-                source_character_start_pos = self.tokens[best_match.source_token_start_pos].start_pos
+                source_character_start_pos = self.tokens[best_match.source_token_start].start_pos
                 source_character_end_pos = self.tokens[
-                    best_match.source_token_start_pos + best_match.source_length - 1].end_pos
-                target_character_start_pos = self.tokens[best_match.target_token_start_pos].start_pos
+                    best_match.source_token_start + best_match.source_length - 1].end_pos
+                target_character_start_pos = self.tokens[best_match.target_token_start].start_pos
                 target_character_end_pos = self.tokens[
-                    best_match.target_token_start_pos + best_match.target_length - 1].end_pos
+                    best_match.target_token_start + best_match.target_length - 1].end_pos
 
-                source_match_segment = InternalMatchSegment(best_match.source_token_start_pos, best_match.source_length,
-                                                            source_character_start_pos, source_character_end_pos)
-                target_match_segment = InternalMatchSegment(best_match.target_token_start_pos, best_match.target_length,
-                                                            target_character_start_pos, target_character_end_pos)
+                source_match_span = InternalMatchSpan(best_match.source_token_start, best_match.source_length,
+                                                      source_character_start_pos, source_character_end_pos)
+                target_match_span = InternalMatchSpan(best_match.target_token_start, best_match.target_length,
+                                                      target_character_start_pos, target_character_end_pos)
 
-                matches.append(InternalMatch(source_match_segment, target_match_segment))
+                matches.append(InternalMatch(source_match_span, target_match_span))
 
-                best_match_token_start_pos = best_match.target_token_start_pos
-                best_match_token_end_pos = best_match.target_token_start_pos + best_match.target_length
+                best_match_token_start_pos = best_match.target_token_start
+                best_match_token_end_pos = best_match.target_token_start + best_match.target_length
 
-                best_match_source_token_start_pos = best_match.source_token_start_pos
-                best_match_source_token_end_pos = best_match.source_token_start_pos + best_match.source_length
+                best_match_source_token_start_pos = best_match.source_token_start
+                best_match_source_token_end_pos = best_match.source_token_start + best_match.source_length
 
                 for target_token_pos in range(best_match_token_start_pos + 1, best_match_token_end_pos):
                     if target_token_pos in target_position_to_source_positions_map:
@@ -501,7 +501,7 @@ class Lotte:
 
         return None
 
-    def __remove_matches_with_overlapping_target_match_segments(self, matches: List[InternalMatch]):
+    def __remove_matches_with_overlapping_target_match_spans(self, matches: List[InternalMatch]):
         """
         Removes matches which overlap in the target texts. When keep_ambiguous_matches is true, then matches are only
         removed if they also overlap in the source text.
@@ -520,18 +520,18 @@ class Lotte:
             while match_position < len(matches):
                 next_match = matches[match_position]
 
-                current_target_match_segment = current_match.target_match_segment
-                next_target_match_segment = next_match.target_match_segment
+                current_target_match_span = current_match.target_match_span
+                next_target_match_span = next_match.target_match_span
 
-                current_end_pos = current_target_match_segment.character_end_pos
-                next_start_pos = next_target_match_segment.character_start_pos
+                current_end_pos = current_target_match_span.character_end
+                next_start_pos = next_target_match_span.character_start
 
                 if next_start_pos >= current_end_pos:
                     result.append(current_match)
                     current_match = next_match
                 else:
-                    current_token_length = current_target_match_segment.token_length
-                    next_token_length = next_target_match_segment.token_length
+                    current_token_length = current_target_match_span.token_length
+                    next_token_length = next_target_match_span.token_length
 
                     if current_token_length < next_token_length:
                         current_match = next_match
@@ -545,25 +545,25 @@ class Lotte:
                 for next_match_pos in range(current_match_pos, len(matches)):
                     next_match = matches[next_match_pos]
 
-                    current_target_match_segment = current_match.target_match_segment
-                    next_target_match_segment = next_match.target_match_segment
+                    current_target_match_span = current_match.target_match_span
+                    next_target_match_span = next_match.target_match_span
 
-                    current_end_pos = current_target_match_segment.character_end_pos
-                    next_start_pos = next_target_match_segment.character_start_pos
+                    current_end_pos = current_target_match_span.character_end
+                    next_start_pos = next_target_match_span.character_start
 
                     if next_start_pos < current_end_pos:
-                        source_current_start_pos = current_match.source_match_segment.character_start_pos
-                        source_current_end_pos = current_match.source_match_segment.character_end_pos
-                        source_next_start_pos = next_match.source_match_segment.character_end_pos
-                        source_next_end_pos = next_match.source_match_segment.character_end_pos
+                        source_current_start_pos = current_match.source_match_span.character_start
+                        source_current_end_pos = current_match.source_match_span.character_end
+                        source_next_start_pos = next_match.source_match_span.character_end
+                        source_next_end_pos = next_match.source_match_span.character_end
 
                         overlap_start = max(source_current_start_pos, source_next_start_pos)
                         overlap_end = min(source_current_end_pos, source_next_end_pos)
                         overlap_length = overlap_end - overlap_start
 
                         if overlap_length > 0:
-                            current_token_length = current_target_match_segment.token_length
-                            next_token_length = next_target_match_segment.token_length
+                            current_token_length = current_target_match_span.token_length
+                            next_token_length = next_target_match_span.token_length
 
                             if current_token_length < next_token_length:
                                 found_conflict = True
@@ -593,10 +593,10 @@ class Lotte:
             for i in range(1, len(remaining_matches)):
                 next_match = remaining_matches[i]
 
-                current_source_sim = current_match.source_match_segment
-                next_source_sim = next_match.source_match_segment
-                current_target_sim = current_match.target_match_segment
-                next_target_sim = next_match.target_match_segment
+                current_source_sim = current_match.source_match_span
+                next_source_sim = next_match.source_match_span
+                current_target_sim = current_match.target_match_span
+                next_target_sim = next_match.target_match_span
 
                 current_source_start = current_source_sim.token_start_pos
                 current_target_start = current_target_sim.token_start_pos
@@ -616,20 +616,20 @@ class Lotte:
                         or (next_target_end > current_target_end > next_target_start > current_target_start
                             and next_source_end > current_source_end > next_source_start > current_source_start)):
 
-                    source_match_segment = InternalMatchSegment(current_source_sim.token_start_pos,
-                                                                next_source_sim.token_start_pos +
-                                                                next_source_sim.token_length -
-                                                                current_source_sim.token_start_pos,
-                                                                current_source_sim.character_start_pos,
-                                                                next_source_sim.character_end_pos)
-
-                    target_match_segment = InternalMatchSegment(current_target_sim.token_start_pos,
-                                                                next_target_sim.token_start_pos +
-                                                                next_target_sim.token_length -
-                                                                current_target_sim.token_start_pos,
-                                                                current_target_sim.character_start_pos,
-                                                                next_target_sim.character_end_pos)
-                    current_match = InternalMatch(source_match_segment, target_match_segment)
+                    source_match_span = InternalMatchSpan(current_source_sim.token_start_pos,
+                                                          next_source_sim.token_start_pos +
+                                                          next_source_sim.token_length -
+                                                          current_source_sim.token_start_pos,
+                                                          current_source_sim.character_start,
+                                                          next_source_sim.character_end)
+
+                    target_match_span = InternalMatchSpan(current_target_sim.token_start_pos,
+                                                          next_target_sim.token_start_pos +
+                                                          next_target_sim.token_length -
+                                                          current_target_sim.token_start_pos,
+                                                          current_target_sim.character_start,
+                                                          next_target_sim.character_end)
+                    current_match = InternalMatch(source_match_span, target_match_span)
 
                     positions_to_delete.append(i)
                 elif 0 <= next_target_start - current_target_end > self.max_merge_distance:
@@ -651,15 +651,15 @@ class Lotte:
         result: List[InternalMatch] = []
 
         for match in matches:
-            if match.target_match_segment.token_length >= self.min_match_length:
+            if match.target_match_span.token_length >= self.min_match_length:
                 result.append(match)
-            elif (match.target_match_segment.token_length >= self.min_match_length - 1 and
-                  self.tokens[match.target_match_segment.token_start_pos].text.startswith('@')):
+            elif (match.target_match_span.token_length >= self.min_match_length - 1 and
+                  self.tokens[match.target_match_span.token_start_pos].text.startswith('@')):
                 result.append(match)
-            elif (match.target_match_segment.token_length >= self.min_match_length - 1 and
-                  match.target_match_segment.token_start_pos - 1 >= self.texts[0].tk_end_pos and
-                  (self.tokens[match.target_match_segment.token_start_pos].text.startswith('@') or
-                   self.tokens[match.target_match_segment.token_start_pos - 1].text.startswith('@'))):
+            elif (match.target_match_span.token_length >= self.min_match_length - 1 and
+                  match.target_match_span.token_start_pos - 1 >= self.texts[0].tk_end_pos and
+                  (self.tokens[match.target_match_span.token_start_pos].text.startswith('@') or
+                   self.tokens[match.target_match_span.token_start_pos - 1].text.startswith('@'))):
                 result.append(match)
 
         return result
@@ -671,17 +671,17 @@ class Lotte:
         @return: The cleaned matches.
         """
         for match in matches:
-            current_source_match_segment = match.source_match_segment
-            current_target_match_segment = match.target_match_segment
+            current_source_match_span = match.source_match_span
+            current_target_match_span = match.target_match_span
 
             found = False
-            if current_source_match_segment.token_length > 3:
-                source_token_end_pos = current_source_match_segment.token_start_pos + \
-                                       current_source_match_segment.token_length
+            if current_source_match_span.token_length > 3:
+                source_token_end_pos = current_source_match_span.token_start_pos + \
+                                       current_source_match_span.token_length
                 source_token_text = self.tokens[source_token_end_pos - 1].text
 
-                target_token_end_pos = (current_target_match_segment.token_start_pos +
-                                        current_target_match_segment.token_length)
+                target_token_end_pos = (current_target_match_span.token_start_pos +
+                                        current_target_match_span.token_length)
 
                 target_token_text = self.tokens[target_token_end_pos - 1].text
 
@@ -705,12 +705,12 @@ class Lotte:
                             if target_token_text in source_token_text:
                                 found = True
 
-                                current_source_match_segment.token_length -= i
-                                current_target_match_segment.token_length -= j
+                                current_source_match_span.token_length -= i
+                                current_target_match_span.token_length -= j
 
-                                current_source_match_segment.character_end_pos = self.tokens[
+                                current_source_match_span.character_end = self.tokens[
                                     source_token_end_pos - i].end_pos
-                                current_target_match_segment.character_end_pos = self.tokens[
+                                current_target_match_span.character_end = self.tokens[
                                     target_token_end_pos - j].end_pos
                                 break
 
@@ -722,17 +722,17 @@ class Lotte:
         result = ''
 
         for match in matches:
-            similarity_literature = match.source_match_segment
-            similarity_scientific = match.target_match_segment
+            similarity_literature = match.source_span
+            similarity_scientific = match.target_span
 
             content = literature_content[
-                      similarity_literature.character_start_pos:similarity_literature.character_end_pos]
-            result += f'\n\n{similarity_literature.character_start_pos}\t{similarity_literature.character_end_pos}' \
+                      similarity_literature.start:similarity_literature.end]
+            result += f'\n\n{similarity_literature.start}\t{similarity_literature.end}' \
                       f'\t{content}'
 
             content = scientific_content[
-                      similarity_scientific.character_start_pos:similarity_scientific.character_end_pos]
-            result += f'\n{similarity_scientific.character_start_pos}\t{similarity_scientific.character_end_pos}' \
+                      similarity_scientific.start:similarity_scientific.end]
+            result += f'\n{similarity_scientific.start}\t{similarity_scientific.end}' \
                       f'\t{content}'
 
         print(result)
diff --git a/lotte/Text.py b/quid/core/Text.py
similarity index 100%
rename from lotte/Text.py
rename to quid/core/Text.py
diff --git a/lotte/Token.py b/quid/core/Token.py
similarity index 100%
rename from lotte/Token.py
rename to quid/core/Token.py
diff --git a/quid/core/__init__.py b/quid/core/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/helper/Decoder.py b/quid/helper/Decoder.py
similarity index 64%
rename from helper/Decoder.py
rename to quid/helper/Decoder.py
index 8e19ee9a5dfe9ca5758064d66ef67161f52a9df0..ba8216db5c7ba62d10f2c99d9c762411165d85c4 100644
--- a/helper/Decoder.py
+++ b/quid/helper/Decoder.py
@@ -1,18 +1,18 @@
-from key_passager.CitationSource import CitationSource
-from key_passager.CitationSourceLink import CitationSourceLink
-from key_passager.ImportantSegment import ImportantSegment
-from key_passager.SourceSegment import SourceSegment
-from key_passager.TargetLocationSelection import TargetLocationSelection
-from key_passager.TargetTextLocationLink import TargetTextLocationLink
-from match.Match import Match
-from match.MatchSegment import MatchSegment
+from quid.passager.CitationSource import CitationSource
+from quid.passager.CitationSourceLink import CitationSourceLink
+from quid.passager.ImportantSegment import ImportantSegment
+from quid.passager.SourceSegment import SourceSegment
+from quid.passager.TargetLocationSelection import TargetLocationSelection
+from quid.passager.TargetTextLocationLink import TargetTextLocationLink
+from quid.match.Match import Match
+from quid.match.MatchSpan import MatchSpan
 
 
 def json_decoder_match(json_input):
-    if 'source_match_segment' in json_input and 'target_match_segment' in json_input:
-        return Match(json_input['source_match_segment'], json_input['target_match_segment'])
+    if 'source_span' in json_input and 'target_span' in json_input:
+        return Match(json_input['source_span'], json_input['target_span'])
     else:
-        return MatchSegment(json_input['character_start_pos'], json_input['character_end_pos'])
+        return MatchSpan(json_input['start'], json_input['end'])
 
 
 def json_decoder_citation_source(json_input):
diff --git a/helper/Loader.py b/quid/helper/Loader.py
similarity index 89%
rename from helper/Loader.py
rename to quid/helper/Loader.py
index ba052a796d2c6eed5f3cf638325017931682406d..572961ceff84f3053aa5bb914cd8db422b3dcb15 100644
--- a/helper/Loader.py
+++ b/quid/helper/Loader.py
@@ -1,5 +1,5 @@
 import json
-from helper.Decoder import json_decoder_match, json_decoder_citation_source, json_decoder_target_text_location_link, \
+from quid.helper.Decoder import json_decoder_match, json_decoder_citation_source, json_decoder_target_text_location_link, \
     json_decoder_citation_source_link
 
 
diff --git a/quid/helper/__init__.py b/quid/helper/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/quid/match/Match.py b/quid/match/Match.py
new file mode 100644
index 0000000000000000000000000000000000000000..5e14fcb8a885f7bc909b41482df1ed189ed8da78
--- /dev/null
+++ b/quid/match/Match.py
@@ -0,0 +1,8 @@
+from dataclasses import dataclass
+from quid.match.MatchSpan import MatchSpan
+
+
+@dataclass
+class Match:
+    source_span: MatchSpan
+    target_span: MatchSpan
diff --git a/quid/match/MatchSpan.py b/quid/match/MatchSpan.py
new file mode 100644
index 0000000000000000000000000000000000000000..237940cd456aa003434499b356b26b61633b6bde
--- /dev/null
+++ b/quid/match/MatchSpan.py
@@ -0,0 +1,8 @@
+from dataclasses import dataclass
+
+
+@dataclass
+class MatchSpan:
+    start: int
+    end: int
+    text: str = ''
diff --git a/quid/match/__init__.py b/quid/match/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/key_passager/AnalyzedWork.py b/quid/passager/AnalyzedWork.py
similarity index 53%
rename from key_passager/AnalyzedWork.py
rename to quid/passager/AnalyzedWork.py
index 19bc044df7f0fcfeb037028d42b379f011c72fb5..86ec80ccef74820784af75eae6b90509dd2e90b9 100644
--- a/key_passager/AnalyzedWork.py
+++ b/quid/passager/AnalyzedWork.py
@@ -1,11 +1,11 @@
 from dataclasses import dataclass
 from typing import List
 
-from key_passager.CitationSource import CitationSource
-from key_passager.CitationSourceLink import CitationSourceLink
-from key_passager.ImportantSegmentLink import ImportantSegmentLink
-from key_passager.TargetText import TargetText
-from key_passager.TargetTextLocationLink import TargetTextLocationLink
+from quid.passager.CitationSource import CitationSource
+from quid.passager.CitationSourceLink import CitationSourceLink
+from quid.passager.ImportantSegmentLink import ImportantSegmentLink
+from quid.passager.TargetText import TargetText
+from quid.passager.TargetTextLocationLink import TargetTextLocationLink
 
 
 @dataclass(frozen=True)
diff --git a/key_passager/CitationSource.py b/quid/passager/CitationSource.py
similarity index 85%
rename from key_passager/CitationSource.py
rename to quid/passager/CitationSource.py
index 3f76c777ae2125dbe951a4f7292a3cb99a7a4b07..ec58b77b892a4c8525d8e100fc59fb0b5892bf31 100644
--- a/key_passager/CitationSource.py
+++ b/quid/passager/CitationSource.py
@@ -1,8 +1,8 @@
 from dataclasses import dataclass
 from typing import List
 
-from key_passager.ImportantSegment import ImportantSegment
-from key_passager.SourceSegment import SourceSegment
+from quid.passager.ImportantSegment import ImportantSegment
+from quid.passager.SourceSegment import SourceSegment
 
 
 @dataclass
diff --git a/key_passager/CitationSourceLink.py b/quid/passager/CitationSourceLink.py
similarity index 100%
rename from key_passager/CitationSourceLink.py
rename to quid/passager/CitationSourceLink.py
diff --git a/key_passager/ImportantSegment.py b/quid/passager/ImportantSegment.py
similarity index 100%
rename from key_passager/ImportantSegment.py
rename to quid/passager/ImportantSegment.py
diff --git a/key_passager/ImportantSegmentLink.py b/quid/passager/ImportantSegmentLink.py
similarity index 100%
rename from key_passager/ImportantSegmentLink.py
rename to quid/passager/ImportantSegmentLink.py
diff --git a/key_passager/Location.py b/quid/passager/Location.py
similarity index 100%
rename from key_passager/Location.py
rename to quid/passager/Location.py
diff --git a/key_passager/KeyPassager.py b/quid/passager/Passager.py
similarity index 93%
rename from key_passager/KeyPassager.py
rename to quid/passager/Passager.py
index e161c96d4bad954a5bd5db87dcd7192c5b5536dc..b307b28675a76ba0f17d6caf48f89a8e7c740814 100644
--- a/key_passager/KeyPassager.py
+++ b/quid/passager/Passager.py
@@ -2,23 +2,23 @@ import copy
 import re
 from typing import List, Dict
 
-from key_passager.ImportantSegment import ImportantSegment
-from key_passager.ImportantSegmentLink import ImportantSegmentLink
-from key_passager.AnalyzedWork import AnalyzedWork
-from key_passager.Location import Location
-from key_passager.TargetMatch import TargetMatch
-from key_passager.TextWithMatches import TextWithMatches
-from key_passager.CitationSource import CitationSource
-from key_passager.CitationSourceLink import CitationSourceLink
-from key_passager.SourceSegment import SourceSegment
-from key_passager.TargetLocation import TargetLocation
-from key_passager.TargetLocationSelection import TargetLocationSelection
-from key_passager.TargetText import TargetText
-from key_passager.TargetTextLocationLink import TargetTextLocationLink
+from quid.passager.ImportantSegment import ImportantSegment
+from quid.passager.ImportantSegmentLink import ImportantSegmentLink
+from quid.passager.AnalyzedWork import AnalyzedWork
+from quid.passager.Location import Location
+from quid.passager.TargetMatch import TargetMatch
+from quid.passager.TextWithMatches import TextWithMatches
+from quid.passager.CitationSource import CitationSource
+from quid.passager.CitationSourceLink import CitationSourceLink
+from quid.passager.SourceSegment import SourceSegment
+from quid.passager.TargetLocation import TargetLocation
+from quid.passager.TargetLocationSelection import TargetLocationSelection
+from quid.passager.TargetText import TargetText
+from quid.passager.TargetTextLocationLink import TargetTextLocationLink
 
 
 # noinspection PyMethodMayBeStatic
-class KeyPassager:
+class Passager:
 
     def __init__(self):
         self.next_id = 1
@@ -30,8 +30,8 @@ class KeyPassager:
 
     def generate(self, texts_with_matches: List[TextWithMatches], source_text: str) -> AnalyzedWork:
         """
-        Generate key passages from from matches between a source text and a number of target texts.
-        :param texts_with_matches: A list of texts with the matches found by Lotte
+        Generate key passages from matches between a source text and a number of target texts.
+        :param texts_with_matches: A list of texts with the matches found by Quid
         :param source_text: The source text
         :return: The results wrapped in an AnalyzedWork
         """
@@ -100,13 +100,13 @@ class KeyPassager:
 
         filename = text_with_matches.name
         for match in text_with_matches.matches:
-            source_match_segment = match.source_match_segment
-            target_match_segment = match.target_match_segment
+            source_match_span = match.source_span
+            target_match_span = match.target_span
 
-            source_match_start = source_match_segment.character_start_pos
-            source_match_end = source_match_segment.character_end_pos
-            target_match_start = target_match_segment.character_start_pos
-            target_match_end = target_match_segment.character_end_pos
+            source_match_start = source_match_span.start
+            source_match_end = source_match_span.end
+            target_match_start = target_match_span.start
+            target_match_end = target_match_span.end
 
             conflicting_sources = []
             conflicting_positions = []
@@ -282,12 +282,12 @@ class KeyPassager:
         target_location_id_to_source_location_map: Dict[int, Location] = {}
 
         for match in target_text_matches.matches:
-            source_match_segment = match.source_match_segment
-            target_match_segment = match.target_match_segment
-            source_character_start_pos = source_match_segment.character_start_pos
-            source_character_end_pos = source_match_segment.character_end_pos
-            target_character_start_pos = target_match_segment.character_start_pos
-            target_character_end_pos = target_match_segment.character_end_pos
+            source_match_segment = match.source_span
+            target_match_segment = match.target_span
+            source_character_start_pos = source_match_segment.start
+            source_character_end_pos = source_match_segment.end
+            target_character_start_pos = target_match_segment.start
+            target_character_end_pos = target_match_segment.end
 
             text = target_content[target_character_start_pos:target_character_end_pos]
 
@@ -449,7 +449,7 @@ class KeyPassager:
                         count += 1
                         segment_pos += 1
                     elif diff_next and diff_next < diff_last and diff_next <= 2:
-                        text = re.sub(r'^[\W]+', '', text)
+                        text = re.sub(r'^\W+', '', text)
                         important_segments.append(ImportantSegment(self.__generate_next_id(), source_segment_ids,
                                                                    round(frequency_sum / count, 1), token_length, text))
                         source_segment_ids = [segment.my_id, next_segment.my_id]
@@ -460,7 +460,7 @@ class KeyPassager:
                         count = 2
                         segment_pos += 2
                     else:
-                        text = re.sub(r'^[\W]+', '', text)
+                        text = re.sub(r'^\W+', '', text)
                         important_segments.append(ImportantSegment(self.__generate_next_id(), source_segment_ids,
                                                                    round(frequency_sum / count, 1), token_length, text))
                         source_segment_ids = [segment.my_id]
@@ -471,7 +471,7 @@ class KeyPassager:
                         count = 1
                         segment_pos += 1
 
-            text = re.sub(r'^[\W]+', '', text)
+            text = re.sub(r'^\W+', '', text)
 
             important_segments.append(ImportantSegment(self.__generate_next_id(), source_segment_ids,
                                                        round(frequency_sum / count, 1), token_length, text))
diff --git a/key_passager/SourceSegment.py b/quid/passager/SourceSegment.py
similarity index 100%
rename from key_passager/SourceSegment.py
rename to quid/passager/SourceSegment.py
diff --git a/key_passager/TargetLocation.py b/quid/passager/TargetLocation.py
similarity index 100%
rename from key_passager/TargetLocation.py
rename to quid/passager/TargetLocation.py
diff --git a/key_passager/TargetLocationSelection.py b/quid/passager/TargetLocationSelection.py
similarity index 100%
rename from key_passager/TargetLocationSelection.py
rename to quid/passager/TargetLocationSelection.py
diff --git a/key_passager/TargetMatch.py b/quid/passager/TargetMatch.py
similarity index 100%
rename from key_passager/TargetMatch.py
rename to quid/passager/TargetMatch.py
diff --git a/key_passager/TargetText.py b/quid/passager/TargetText.py
similarity index 100%
rename from key_passager/TargetText.py
rename to quid/passager/TargetText.py
diff --git a/key_passager/TargetTextLocationLink.py b/quid/passager/TargetTextLocationLink.py
similarity index 100%
rename from key_passager/TargetTextLocationLink.py
rename to quid/passager/TargetTextLocationLink.py
diff --git a/key_passager/TextWithMatches.py b/quid/passager/TextWithMatches.py
similarity index 84%
rename from key_passager/TextWithMatches.py
rename to quid/passager/TextWithMatches.py
index 144217886000040e174b44d3226a8166a36774fb..83e72d269d1cfa36c8b04ff7fdc3df579914dae6 100644
--- a/key_passager/TextWithMatches.py
+++ b/quid/passager/TextWithMatches.py
@@ -1,6 +1,6 @@
 from dataclasses import dataclass, field
 from typing import List
-from match.Match import Match
+from quid.match.Match import Match
 
 
 @dataclass
diff --git a/quid/passager/__init__.py b/quid/passager/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/visualization/Info.py b/quid/visualization/Info.py
similarity index 100%
rename from visualization/Info.py
rename to quid/visualization/Info.py
diff --git a/visualization/TargetHtml.py b/quid/visualization/TargetHtml.py
similarity index 100%
rename from visualization/TargetHtml.py
rename to quid/visualization/TargetHtml.py
diff --git a/visualization/TargetTextWithContent.py b/quid/visualization/TargetTextWithContent.py
similarity index 74%
rename from visualization/TargetTextWithContent.py
rename to quid/visualization/TargetTextWithContent.py
index 8ae38658f04366a1146958f687a0675475c716ea..32a189da8c45e886748bab40b99b74ac829e4c46 100644
--- a/visualization/TargetTextWithContent.py
+++ b/quid/visualization/TargetTextWithContent.py
@@ -1,5 +1,5 @@
 from dataclasses import dataclass
-from key_passager.TargetText import TargetText
+from quid.passager import TargetText
 
 
 @dataclass(frozen=True)
diff --git a/visualization/Visualization.py b/quid/visualization/Visualization.py
similarity index 65%
rename from visualization/Visualization.py
rename to quid/visualization/Visualization.py
index 442b430179004964be7a79060465659a7a1b3307..1e1f1b0c5278d4e199206bee9adc3503c76b87a4 100644
--- a/visualization/Visualization.py
+++ b/quid/visualization/Visualization.py
@@ -1,7 +1,7 @@
 from dataclasses import dataclass
 from typing import List
-from visualization.Info import Info
-from visualization.TargetHtml import TargetHtml
+from quid.visualization.Info import Info
+from quid.visualization.TargetHtml import TargetHtml
 
 
 @dataclass(frozen=True)
diff --git a/visualization/Visualizer.py b/quid/visualization/Visualizer.py
similarity index 96%
rename from visualization/Visualizer.py
rename to quid/visualization/Visualizer.py
index ae435f4cf1793612e135b8053c36a376b84184b2..467a069ac201c198f9f281d4cb191c12f8558ccb 100644
--- a/visualization/Visualizer.py
+++ b/quid/visualization/Visualizer.py
@@ -3,13 +3,13 @@ from typing import List
 from yattag import Doc
 from math import ceil
 
-from key_passager.CitationSource import CitationSource
-from visualization.Info import Info
+from quid.passager.CitationSource import CitationSource
+from quid.visualization.Info import Info
 import re
 
-from visualization.TargetHtml import TargetHtml
-from visualization.TargetTextWithContent import TargetTextWithContent
-from visualization.Visualization import Visualization
+from quid.visualization.TargetHtml import TargetHtml
+from quid.visualization.TargetTextWithContent import TargetTextWithContent
+from quid.visualization.Visualization import Visualization
 
 
 # noinspection PyMethodMayBeStatic
diff --git a/quid/visualization/__init__.py b/quid/visualization/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/setup.cfg b/setup.cfg
index 7138273a2d7e3475e29b0f4f2809644918ffc1b3..9c9a09518faf4a6c0500ee531b2ffeeb682ba38a 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,37 +1,29 @@
 [metadata]
-# replace with your username:
-name = Lotte
-version = 1.3.3
+name = Quid
+version = 2.0.0-beta01
 author = Frederik Arnold
 author_email = frederik.arnold@hu-berlin.de
-description = Lotte is a tool for quotation detection in texts and can deal with common properties of quotations, for example, ellipses or inaccurate quotations.
+description = Quid is a tool for quotation detection in texts and can deal with common properties of quotations, for example, ellipses or inaccurate quotations.
 long_description = file: README.md
 long_description_content_type = text/markdown
-keywords = quotation detection, literal citation extraction, key passages, natural language processing, nlp, text reuse
-url = https://scm.cms.hu-berlin.de/schluesselstellen/lotte
+keywords = quotation detection, quotation identification, literal citation extraction, key passages, natural language processing, nlp, text reuse
+url = https://hu.berlin/quid
 project_urls =
-    Source = https://scm.cms.hu-berlin.de/schluesselstellen/lotte
+    Source = https://hu.berlin/quid
 classifiers =
     Programming Language :: Python :: 3
     License :: OSI Approved :: Apache Software License
     Operating System :: OS Independent
 
 [options]
-# package_dir =
-#    = .
-#packages = find:
-packages = cli,lotte,match,visualization,key_passager,helper
+packages = quid, quid.cli, quid.core, quid.helper, quid.match, quid.passager, quid.visualization
 python_requires = >=3.7
 install_requires =
     numpy>=1.20.1
     yattag>=1.14.0
     rapidfuzz>=1.3.3
     datasketch>=1.5.3
-#py_modules = LotteCLI
-
-#[options.packages.find]
-#where = .
 
 [options.entry_points]
 console_scripts =
-    lotte = cli.LotteCLI:main
\ No newline at end of file
+    quid = quid.cli.QuidCLI:main
\ No newline at end of file
diff --git a/test/Helper.py b/test/Helper.py
index 2a9368a856c63bb4ebb45d535bb8bb2353b8570e..c29f58f34eed742c2df9e435da6f3ad9b1fb22ba 100644
--- a/test/Helper.py
+++ b/test/Helper.py
@@ -1,2 +1,2 @@
-def get_text(text, match_segment):
-    return text[match_segment.character_start_pos:match_segment.character_end_pos]
\ No newline at end of file
+def get_text(text, match_span):
+    return text[match_span.start:match_span.end]
diff --git a/test/TestCLI.py b/test/TestCLI.py
new file mode 100644
index 0000000000000000000000000000000000000000..7375193fe70f6c777e6e02c1d07e8779ecb66320
--- /dev/null
+++ b/test/TestCLI.py
@@ -0,0 +1,83 @@
+from unittest import TestCase, mock
+from quid.cli.QuidCLI import main
+from quid.match.Match import Match
+from quid.match.MatchSpan import MatchSpan
+from quid.visualization.Visualizer import Visualizer
+
+
+class CLITestCase(TestCase):
+
+    @mock.patch('quid.cli.QuidCLI.isfile')
+    @mock.patch('quid.cli.QuidCLI.listdir')
+    @mock.patch('quid.cli.QuidCLI.Path.mkdir')
+    @mock.patch('quid.cli.QuidCLI.Quid')
+    def test_cli_compare(self, mock_quid, mock_mkdir, mock_list_dir, mock_is_file):
+        quid_instance = mock_quid.return_value
+
+        match_1_source_match_span = MatchSpan(0, 10)
+        match_1_target_match_span = MatchSpan(0, 10)
+        match_1 = Match(match_1_source_match_span, match_1_target_match_span)
+
+        quid_instance.compare.return_value = [match_1]
+        mock_is_file.return_value = True
+
+        with mock.patch("builtins.open", mock.mock_open(read_data='')) as file_mock:
+            handler_1 = file_mock.return_value
+
+            with mock.patch("builtins.open", mock.mock_open(read_data='')) as file_mock_2:
+                handler_2 = file_mock_2.return_value
+
+                handlers = (handler_1, handler_1, handler_2)
+                file_mock.side_effect = handlers
+
+                main(["compare", "test.txt", "test.txt", "--output-folder-path", "output"])
+
+                handler_2.write.assert_called_once_with('[{"source_span": {"start": 0, "end": 10}, '
+                                                        '"target_span": {"start": 0, "end": 10}}]')
+
+    @mock.patch('quid.cli.QuidCLI.listdir')
+    @mock.patch('quid.cli.QuidCLI.isfile')
+    @mock.patch('quid.cli.QuidCLI.load_matches')
+    def test_cli_passage(self, mock_load_matches, mock_is_file, mock_list_dir):
+        mock_list_dir.return_value = ['test.json']
+        mock_is_file.return_value = True
+        mock_load_matches.return_value = []
+
+        with mock.patch("builtins.open", mock.mock_open(read_data='')) as file_mock:
+            handler_1 = file_mock.return_value
+
+            with mock.patch("builtins.open", mock.mock_open(read_data='')) as file_mock_2:
+                handler_2 = file_mock_2.return_value
+
+                handlers = (handler_1, handler_1, handler_2)
+                file_mock.side_effect = handlers
+
+                main(["passage", "folder", "folder", "folder", "folder"])
+
+                self.assertEqual(5, handler_2.write.call_count)
+
+    @mock.patch('quid.cli.QuidCLI.Path.mkdir')
+    @mock.patch('quid.cli.QuidCLI.json.load')
+    @mock.patch('quid.cli.QuidCLI.copyfile')
+    @mock.patch('quid.cli.QuidCLI.load_citation_source_links')
+    @mock.patch('quid.cli.QuidCLI.load_citation_sources')
+    @mock.patch('quid.cli.QuidCLI.Visualizer')
+    def test_cli_visualize(self, mock_visualizer, mock_load_citation_sources, mock_load_citation_source_links,
+                           mock_copyfile, mock_json_load, mock_mkdir):
+        mock_visualizer.return_value = Visualizer()
+        mock_load_citation_sources.return_value = []
+        mock_load_citation_source_links.return_value = []
+        mock_json_load.return_value = []
+
+        with mock.patch("builtins.open", mock.mock_open(read_data='')) as file_mock:
+            handler_1 = file_mock.return_value
+
+            with mock.patch("builtins.open", mock.mock_open(read_data='')) as file_mock_2:
+                handler_2 = file_mock_2.return_value
+
+                handlers = (handler_1, handler_1, handler_2)
+                file_mock.side_effect = handlers
+
+                main(["visualize", "folder", "folder", "folder", "folder"])
+
+                self.assertEqual(4, handler_2.write.call_count)
diff --git a/test/TestCustomValues.py b/test/TestCustomValues.py
index a76cefda772ef042c8fff51b0397257fc6681ddd..008de9bfeeb7e521b93085f9323824a6e3563a2e 100644
--- a/test/TestCustomValues.py
+++ b/test/TestCustomValues.py
@@ -1,88 +1,88 @@
 import unittest
-from lotte.Lotte import Lotte
+from quid.core.Quid import Quid
 from test.Helper import get_text
 
 
-class LotteTestCase(unittest.TestCase):
+class QuidTestCase(unittest.TestCase):
 
     def test_max_merge_ellipse_distance(self):
         source_text = 'This is a long Text but there are too many words here are even more words here to test.'
         target_text = 'This is a long Text ... even more words here to test.'
 
-        lotte = Lotte(5, look_back_limit=2, max_merge_ellipse_distance=3)
-        matches = lotte.compare(source_text, target_text)
+        quid = Quid(5, look_back_limit=2, max_merge_ellipse_distance=3)
+        matches = quid.compare(source_text, target_text)
 
         self.assertEqual(2, len(matches))
-        self.assertEqual(0, matches[0].source_match_segment.character_start_pos)
-        self.assertEqual(19, matches[0].source_match_segment.character_end_pos)
-        self.assertEqual(0, matches[0].target_match_segment.character_start_pos)
-        self.assertEqual(19, matches[0].target_match_segment.character_end_pos)
+        self.assertEqual(0, matches[0].source_span.start)
+        self.assertEqual(19, matches[0].source_span.end)
+        self.assertEqual(0, matches[0].target_span.start)
+        self.assertEqual(19, matches[0].target_span.end)
 
-        self.assertEqual(58, matches[1].source_match_segment.character_start_pos)
-        self.assertEqual(87, matches[1].source_match_segment.character_end_pos)
-        self.assertEqual(24, matches[1].target_match_segment.character_start_pos)
-        self.assertEqual(53, matches[1].target_match_segment.character_end_pos)
+        self.assertEqual(58, matches[1].source_span.start)
+        self.assertEqual(87, matches[1].source_span.end)
+        self.assertEqual(24, matches[1].target_span.start)
+        self.assertEqual(53, matches[1].target_span.end)
 
         self.assertEqual('This is a long Text',
-                         get_text(source_text, matches[0].source_match_segment))
+                         get_text(source_text, matches[0].source_span))
         self.assertEqual('This is a long Text',
-                         get_text(target_text, matches[0].target_match_segment))
+                         get_text(target_text, matches[0].target_span))
 
-        lotte = Lotte(5, look_back_limit=2, max_merge_ellipse_distance=10)
-        matches = lotte.compare(source_text, target_text)
+        quid = Quid(5, look_back_limit=2, max_merge_ellipse_distance=10)
+        matches = quid.compare(source_text, target_text)
 
         self.assertEqual(1, len(matches))
-        self.assertEqual(0, matches[0].source_match_segment.character_start_pos)
-        self.assertEqual(87, matches[0].source_match_segment.character_end_pos)
-        self.assertEqual(0, matches[0].target_match_segment.character_start_pos)
-        self.assertEqual(53, matches[0].target_match_segment.character_end_pos)
+        self.assertEqual(0, matches[0].source_span.start)
+        self.assertEqual(87, matches[0].source_span.end)
+        self.assertEqual(0, matches[0].target_span.start)
+        self.assertEqual(53, matches[0].target_span.end)
 
         self.assertEqual('This is a long Text but there are too many words here are even more words here to test.',
-                         get_text(source_text, matches[0].source_match_segment))
+                         get_text(source_text, matches[0].source_span))
         self.assertEqual('This is a long Text ... even more words here to test.',
-                         get_text(target_text, matches[0].target_match_segment))
+                         get_text(target_text, matches[0].target_span))
 
     def test_max_merge_distance(self):
         source_text = 'This is a long Text okay why do even more words here to test.'
         target_text = 'This is a long Text some not fitting even more words here to test.'
 
-        lotte = Lotte(5, look_back_limit=2, max_merge_distance=2)
-        matches = lotte.compare(source_text, target_text)
+        quid = Quid(5, look_back_limit=2, max_merge_distance=2)
+        matches = quid.compare(source_text, target_text)
 
         self.assertEqual(2, len(matches))
-        self.assertEqual(0, matches[0].source_match_segment.character_start_pos)
-        self.assertEqual(19, matches[0].source_match_segment.character_end_pos)
-        self.assertEqual(0, matches[0].target_match_segment.character_start_pos)
-        self.assertEqual(19, matches[0].target_match_segment.character_end_pos)
+        self.assertEqual(0, matches[0].source_span.start)
+        self.assertEqual(19, matches[0].source_span.end)
+        self.assertEqual(0, matches[0].target_span.start)
+        self.assertEqual(19, matches[0].target_span.end)
 
-        self.assertEqual(32, matches[1].source_match_segment.character_start_pos)
-        self.assertEqual(61, matches[1].source_match_segment.character_end_pos)
-        self.assertEqual(37, matches[1].target_match_segment.character_start_pos)
-        self.assertEqual(66, matches[1].target_match_segment.character_end_pos)
+        self.assertEqual(32, matches[1].source_span.start)
+        self.assertEqual(61, matches[1].source_span.end)
+        self.assertEqual(37, matches[1].target_span.start)
+        self.assertEqual(66, matches[1].target_span.end)
 
         self.assertEqual('This is a long Text',
-                         get_text(source_text, matches[0].source_match_segment))
+                         get_text(source_text, matches[0].source_span))
         self.assertEqual('This is a long Text',
-                         get_text(target_text, matches[0].target_match_segment))
+                         get_text(target_text, matches[0].target_span))
 
         self.assertEqual('even more words here to test.',
-                         get_text(source_text, matches[1].source_match_segment))
+                         get_text(source_text, matches[1].source_span))
         self.assertEqual('even more words here to test.',
-                         get_text(target_text, matches[1].target_match_segment))
+                         get_text(target_text, matches[1].target_span))
 
-        lotte = Lotte(5, look_back_limit=2, max_merge_distance=10)
-        matches = lotte.compare(source_text, target_text)
+        quid = Quid(5, look_back_limit=2, max_merge_distance=10)
+        matches = quid.compare(source_text, target_text)
 
         self.assertEqual(1, len(matches))
-        self.assertEqual(0, matches[0].source_match_segment.character_start_pos)
-        self.assertEqual(61, matches[0].source_match_segment.character_end_pos)
-        self.assertEqual(0, matches[0].target_match_segment.character_start_pos)
-        self.assertEqual(66, matches[0].target_match_segment.character_end_pos)
+        self.assertEqual(0, matches[0].source_span.start)
+        self.assertEqual(61, matches[0].source_span.end)
+        self.assertEqual(0, matches[0].target_span.start)
+        self.assertEqual(66, matches[0].target_span.end)
 
         self.assertEqual('This is a long Text okay why do even more words here to test.',
-                         get_text(source_text, matches[0].source_match_segment))
+                         get_text(source_text, matches[0].source_span))
         self.assertEqual('This is a long Text some not fitting even more words here to test.',
-                         get_text(target_text, matches[0].target_match_segment))
+                         get_text(target_text, matches[0].target_span))
 
 
 if __name__ == '__main__':
diff --git a/test/TestDefaultValues.py b/test/TestDefaultValues.py
index f34d9956833929c5c9571375c4e7ab9f925a8f1d..f896cada05639e763382c11baca98ea8e5c45dff 100644
--- a/test/TestDefaultValues.py
+++ b/test/TestDefaultValues.py
@@ -1,200 +1,200 @@
 import unittest
-from lotte.Lotte import Lotte
+from quid.core.Quid import Quid
 from test.Helper import get_text
 
 
-class LotteTestCase(unittest.TestCase):
+class QuidTestCase(unittest.TestCase):
 
     def setUp(self):
-        self.lotte = Lotte(5)
+        self.quid = Quid(5)
 
     def test_full(self):
         source_text = 'This is a long Text and the long test goes on and on and on'
         target_text = 'This is [...] and the long test goes on'
 
-        matches = self.lotte.compare(source_text, target_text)
+        matches = self.quid.compare(source_text, target_text)
 
         self.assertEqual(1, len(matches))
-        self.assertEqual(0, matches[0].source_match_segment.character_start_pos)
-        self.assertEqual(45, matches[0].source_match_segment.character_end_pos)
-        self.assertEqual(0, matches[0].target_match_segment.character_start_pos)
-        self.assertEqual(39, matches[0].target_match_segment.character_end_pos)
+        self.assertEqual(0, matches[0].source_span.start)
+        self.assertEqual(45, matches[0].source_span.end)
+        self.assertEqual(0, matches[0].target_span.start)
+        self.assertEqual(39, matches[0].target_span.end)
 
         self.assertEqual('This is a long Text and the long test goes on',
-                         get_text(source_text, matches[0].source_match_segment))
+                         get_text(source_text, matches[0].source_span))
         self.assertEqual('This is [...] and the long test goes on',
-                         get_text(target_text, matches[0].target_match_segment))
+                         get_text(target_text, matches[0].target_span))
 
     def test_sentence_boundary_1(self):
         source_text = 'This is a long Text and the long test goes on. And continues'
         target_text = 'This is [...] and the long test goes on. And continues'
 
-        matches = self.lotte.compare(source_text, target_text)
+        matches = self.quid.compare(source_text, target_text)
 
         self.assertEqual(1, len(matches))
-        self.assertEqual(0, matches[0].source_match_segment.character_start_pos)
-        self.assertEqual(46, matches[0].source_match_segment.character_end_pos)
-        self.assertEqual(0, matches[0].target_match_segment.character_start_pos)
-        self.assertEqual(40, matches[0].target_match_segment.character_end_pos)
+        self.assertEqual(0, matches[0].source_span.start)
+        self.assertEqual(46, matches[0].source_span.end)
+        self.assertEqual(0, matches[0].target_span.start)
+        self.assertEqual(40, matches[0].target_span.end)
 
     def test_sentence_boundary_2(self):
         source_text = 'This is a long Text and the long test goes on. And continues!'
         target_text = 'This is [...] and the long test goes on. And continues!'
 
-        matches = self.lotte.compare(source_text, target_text)
+        matches = self.quid.compare(source_text, target_text)
 
         self.assertEqual(1, len(matches))
-        self.assertEqual(0, matches[0].source_match_segment.character_start_pos)
-        self.assertEqual(61, matches[0].source_match_segment.character_end_pos)
-        self.assertEqual(0, matches[0].target_match_segment.character_start_pos)
-        self.assertEqual(55, matches[0].target_match_segment.character_end_pos)
+        self.assertEqual(0, matches[0].source_span.start)
+        self.assertEqual(61, matches[0].source_span.end)
+        self.assertEqual(0, matches[0].target_span.start)
+        self.assertEqual(55, matches[0].target_span.end)
 
     def test_quoted_twice(self):
         source_text = 'This is a long Text and the long test goes on.\n\n'
         target_text = 'This is a long Text and the long test goes on.\n\n' \
                       'And now some other Text. And now is a long Text and the long test goes on again'
 
-        matches = self.lotte.compare(source_text, target_text)
+        matches = self.quid.compare(source_text, target_text)
 
         self.assertEqual(2, len(matches))
-        self.assertEqual(0, matches[0].source_match_segment.character_start_pos)
-        self.assertEqual(46, matches[0].source_match_segment.character_end_pos)
-        self.assertEqual(0, matches[0].target_match_segment.character_start_pos)
-        self.assertEqual(46, matches[0].target_match_segment.character_end_pos)
+        self.assertEqual(0, matches[0].source_span.start)
+        self.assertEqual(46, matches[0].source_span.end)
+        self.assertEqual(0, matches[0].target_span.start)
+        self.assertEqual(46, matches[0].target_span.end)
 
-        self.assertEqual(5, matches[1].source_match_segment.character_start_pos)
-        self.assertEqual(46, matches[1].source_match_segment.character_end_pos)
-        self.assertEqual(81, matches[1].target_match_segment.character_start_pos)
-        self.assertEqual(121, matches[1].target_match_segment.character_end_pos)
+        self.assertEqual(5, matches[1].source_span.start)
+        self.assertEqual(46, matches[1].source_span.end)
+        self.assertEqual(81, matches[1].target_span.start)
+        self.assertEqual(121, matches[1].target_span.end)
 
     def test_backward_extension(self):
         source_text = 'This is a long Text and the long test goes on.\n\n'
         target_text = 'This is [...] and the long test goes on.\n\n'
 
-        matches = self.lotte.compare(source_text, target_text)
+        matches = self.quid.compare(source_text, target_text)
 
         self.assertEqual(1, len(matches))
-        self.assertEqual(0, matches[0].source_match_segment.character_start_pos)
-        self.assertEqual(46, matches[0].source_match_segment.character_end_pos)
-        self.assertEqual(0, matches[0].target_match_segment.character_start_pos)
-        self.assertEqual(40, matches[0].target_match_segment.character_end_pos)
+        self.assertEqual(0, matches[0].source_span.start)
+        self.assertEqual(46, matches[0].source_span.end)
+        self.assertEqual(0, matches[0].target_span.start)
+        self.assertEqual(40, matches[0].target_span.end)
 
     def test_similar_quotations(self):
         source_text = 'This is a long Text and the long test goes on.\n\n' \
                       'This a long Text and the long test doesn\'t go on'
         target_text = 'This is a long Text the long test goes on.\n\n'
 
-        matches = self.lotte.compare(source_text, target_text)
+        matches = self.quid.compare(source_text, target_text)
 
         self.assertEqual(1, len(matches))
-        self.assertEqual(0, matches[0].source_match_segment.character_start_pos)
-        self.assertEqual(46, matches[0].source_match_segment.character_end_pos)
-        self.assertEqual(0, matches[0].target_match_segment.character_start_pos)
-        self.assertEqual(42, matches[0].target_match_segment.character_end_pos)
+        self.assertEqual(0, matches[0].source_span.start)
+        self.assertEqual(46, matches[0].source_span.end)
+        self.assertEqual(0, matches[0].target_span.start)
+        self.assertEqual(42, matches[0].target_span.end)
 
     def test_fuzzy_matching_1(self):
         source_text = 'This is a long Text and the long test goes on.'
         target_text = 'This is a long Teext the long test goes on.'
 
-        matches = self.lotte.compare(source_text, target_text)
+        matches = self.quid.compare(source_text, target_text)
 
         self.assertEqual(1, len(matches))
-        self.assertEqual(0, matches[0].source_match_segment.character_start_pos)
-        self.assertEqual(46, matches[0].source_match_segment.character_end_pos)
-        self.assertEqual(0, matches[0].target_match_segment.character_start_pos)
-        self.assertEqual(43, matches[0].target_match_segment.character_end_pos)
+        self.assertEqual(0, matches[0].source_span.start)
+        self.assertEqual(46, matches[0].source_span.end)
+        self.assertEqual(0, matches[0].target_span.start)
+        self.assertEqual(43, matches[0].target_span.end)
 
     def test_missing_word(self):
         source_text = 'This is a long Text and the test goes on.'
         target_text = 'This is a long Text and the long test goes on.'
 
-        matches = self.lotte.compare(source_text, target_text)
+        matches = self.quid.compare(source_text, target_text)
 
         self.assertEqual(1, len(matches))
 
-        self.assertEqual(0, matches[0].source_match_segment.character_start_pos)
-        self.assertEqual(41, matches[0].source_match_segment.character_end_pos)
-        self.assertEqual(0, matches[0].target_match_segment.character_start_pos)
-        self.assertEqual(46, matches[0].target_match_segment.character_end_pos)
+        self.assertEqual(0, matches[0].source_span.start)
+        self.assertEqual(41, matches[0].source_span.end)
+        self.assertEqual(0, matches[0].target_span.start)
+        self.assertEqual(46, matches[0].target_span.end)
 
         self.assertEqual('This is a long Text and the test goes on.',
-                         get_text(source_text, matches[0].source_match_segment))
+                         get_text(source_text, matches[0].source_span))
         self.assertEqual('This is a long Text and the long test goes on.',
-                         get_text(target_text, matches[0].target_match_segment))
+                         get_text(target_text, matches[0].target_span))
 
     def test_overlapping_target_matches(self):
         source_text = 'And the long test goes. And the long test goes on.'
         target_text = 'This is a long Text and the long test goes on.'
 
-        matches = self.lotte.compare(source_text, target_text)
+        matches = self.quid.compare(source_text, target_text)
 
         self.assertEqual(1, len(matches))
 
-        self.assertEqual(24, matches[0].source_match_segment.character_start_pos)
-        self.assertEqual(50, matches[0].source_match_segment.character_end_pos)
-        self.assertEqual(20, matches[0].target_match_segment.character_start_pos)
-        self.assertEqual(46, matches[0].target_match_segment.character_end_pos)
+        self.assertEqual(24, matches[0].source_span.start)
+        self.assertEqual(50, matches[0].source_span.end)
+        self.assertEqual(20, matches[0].target_span.start)
+        self.assertEqual(46, matches[0].target_span.end)
 
         self.assertEqual('And the long test goes on.',
-                         get_text(source_text, matches[0].source_match_segment))
+                         get_text(source_text, matches[0].source_span))
         self.assertEqual('and the long test goes on.',
-                         get_text(target_text, matches[0].target_match_segment))
+                         get_text(target_text, matches[0].target_span))
 
     def test_look_back(self):
         source_text = 'A long Text but so on and on.'
         target_text = 'A long Text but so bla blub bleh bloh blieh bluh on and on.'
 
-        matches = self.lotte.compare(source_text, target_text)
+        matches = self.quid.compare(source_text, target_text)
 
         self.assertEqual(1, len(matches))
 
-        self.assertEqual(0, matches[0].source_match_segment.character_start_pos)
-        self.assertEqual(18, matches[0].source_match_segment.character_end_pos)
-        self.assertEqual(0, matches[0].target_match_segment.character_start_pos)
-        self.assertEqual(18, matches[0].target_match_segment.character_end_pos)
+        self.assertEqual(0, matches[0].source_span.start)
+        self.assertEqual(18, matches[0].source_span.end)
+        self.assertEqual(0, matches[0].target_span.start)
+        self.assertEqual(18, matches[0].target_span.end)
 
         self.assertEqual('A long Text but so',
-                         get_text(source_text, matches[0].source_match_segment))
+                         get_text(source_text, matches[0].source_span))
         self.assertEqual('A long Text but so',
-                         get_text(target_text, matches[0].target_match_segment))
+                         get_text(target_text, matches[0].target_span))
 
     def test_merging_matches_1(self):
         source_text = 'This is a long Text but there are too many words here.'
         target_text = 'This is a long Text but too many words here.'
 
-        matches = self.lotte.compare(source_text, target_text)
+        matches = self.quid.compare(source_text, target_text)
 
         self.assertEqual(1, len(matches))
 
-        self.assertEqual(0, matches[0].source_match_segment.character_start_pos)
-        self.assertEqual(54, matches[0].source_match_segment.character_end_pos)
-        self.assertEqual(0, matches[0].target_match_segment.character_start_pos)
-        self.assertEqual(44, matches[0].target_match_segment.character_end_pos)
+        self.assertEqual(0, matches[0].source_span.start)
+        self.assertEqual(54, matches[0].source_span.end)
+        self.assertEqual(0, matches[0].target_span.start)
+        self.assertEqual(44, matches[0].target_span.end)
 
         self.assertEqual('This is a long Text but there are too many words here.',
-                         get_text(source_text, matches[0].source_match_segment))
+                         get_text(source_text, matches[0].source_span))
         self.assertEqual('This is a long Text but too many words here.',
-                         get_text(target_text, matches[0].target_match_segment))
+                         get_text(target_text, matches[0].target_span))
 
     def test_merging_matches_2(self):
         source_text = 'This is a long Text but there are too many words here and then there are ' \
                       'even more words too many.'
         target_text = 'This is a long Text but too many words here. There are even more words.'
 
-        matches = self.lotte.compare(source_text, target_text)
+        matches = self.quid.compare(source_text, target_text)
 
         self.assertEqual(1, len(matches))
 
-        self.assertEqual(0, matches[0].source_match_segment.character_start_pos)
-        self.assertEqual(88, matches[0].source_match_segment.character_end_pos)
-        self.assertEqual(0, matches[0].target_match_segment.character_start_pos)
-        self.assertEqual(71, matches[0].target_match_segment.character_end_pos)
+        self.assertEqual(0, matches[0].source_span.start)
+        self.assertEqual(88, matches[0].source_span.end)
+        self.assertEqual(0, matches[0].target_span.start)
+        self.assertEqual(71, matches[0].target_span.end)
 
         self.assertEqual('This is a long Text but there are too many words here and then there are '
                          'even more words',
-                         get_text(source_text, matches[0].source_match_segment))
+                         get_text(source_text, matches[0].source_span))
         self.assertEqual('This is a long Text but too many words here. There are even more words.',
-                         get_text(target_text, matches[0].target_match_segment))
+                         get_text(target_text, matches[0].target_span))
 
     def test_merging_matches_3(self):
         source_text = 'A long Text but so on and on.\n\n' \
@@ -203,19 +203,19 @@ class LotteTestCase(unittest.TestCase):
 
         target_text = 'This is a long Text but too many words here.'
 
-        matches = self.lotte.compare(source_text, target_text)
+        matches = self.quid.compare(source_text, target_text)
 
         self.assertEqual(1, len(matches))
 
-        self.assertEqual(31, matches[0].source_match_segment.character_start_pos)
-        self.assertEqual(84, matches[0].source_match_segment.character_end_pos)
-        self.assertEqual(0, matches[0].target_match_segment.character_start_pos)
-        self.assertEqual(44, matches[0].target_match_segment.character_end_pos)
+        self.assertEqual(31, matches[0].source_span.start)
+        self.assertEqual(84, matches[0].source_span.end)
+        self.assertEqual(0, matches[0].target_span.start)
+        self.assertEqual(44, matches[0].target_span.end)
 
         self.assertEqual('This is a long Text but there are too many words here',
-                         get_text(source_text, matches[0].source_match_segment))
+                         get_text(source_text, matches[0].source_span))
         self.assertEqual('This is a long Text but too many words here.',
-                         get_text(target_text, matches[0].target_match_segment))
+                         get_text(target_text, matches[0].target_span))
 
     @unittest.expectedFailure
     def test_merging_matches_4(self):
@@ -229,71 +229,71 @@ class LotteTestCase(unittest.TestCase):
 
         target_text = 'This is a long Text but too many words here.'
 
-        matches = self.lotte.compare(source_text, target_text)
+        matches = self.quid.compare(source_text, target_text)
 
         self.assertEqual(1, len(matches))
 
-        self.assertEqual(0, matches[0].source_match_segment.character_start_pos)
-        self.assertEqual(88, matches[0].source_match_segment.character_end_pos)
-        self.assertEqual(0, matches[0].target_match_segment.character_start_pos)
-        self.assertEqual(71, matches[0].target_match_segment.character_end_pos)
+        self.assertEqual(0, matches[0].source_span.start)
+        self.assertEqual(88, matches[0].source_span.end)
+        self.assertEqual(0, matches[0].target_span.start)
+        self.assertEqual(71, matches[0].target_span.end)
 
         self.assertEqual('This is a long Text but there are too many words here',
-                         get_text(source_text, matches[0].source_match_segment))
+                         get_text(source_text, matches[0].source_span))
         self.assertEqual('This is a long Text but too many words here.',
-                         get_text(target_text, matches[0].target_match_segment))
+                         get_text(target_text, matches[0].target_span))
 
     def test_merging_matches_5(self):
         source_text = 'A long Text but so on and on and on and on.'
         target_text = 'A long Text but so bla blub bleh bloh blieh bluh on and on and on and on.'
 
-        matches = self.lotte.compare(source_text, target_text)
+        matches = self.quid.compare(source_text, target_text)
 
         self.assertEqual(2, len(matches))
 
-        self.assertEqual(0, matches[0].source_match_segment.character_start_pos)
-        self.assertEqual(18, matches[0].source_match_segment.character_end_pos)
-        self.assertEqual(0, matches[0].target_match_segment.character_start_pos)
-        self.assertEqual(18, matches[0].target_match_segment.character_end_pos)
+        self.assertEqual(0, matches[0].source_span.start)
+        self.assertEqual(18, matches[0].source_span.end)
+        self.assertEqual(0, matches[0].target_span.start)
+        self.assertEqual(18, matches[0].target_span.end)
 
-        self.assertEqual(19, matches[1].source_match_segment.character_start_pos)
-        self.assertEqual(43, matches[1].source_match_segment.character_end_pos)
-        self.assertEqual(49, matches[1].target_match_segment.character_start_pos)
-        self.assertEqual(73, matches[1].target_match_segment.character_end_pos)
+        self.assertEqual(19, matches[1].source_span.start)
+        self.assertEqual(43, matches[1].source_span.end)
+        self.assertEqual(49, matches[1].target_span.start)
+        self.assertEqual(73, matches[1].target_span.end)
 
         self.assertEqual('A long Text but so',
-                         get_text(source_text, matches[0].source_match_segment))
+                         get_text(source_text, matches[0].source_span))
         self.assertEqual('A long Text but so',
-                         get_text(target_text, matches[0].target_match_segment))
+                         get_text(target_text, matches[0].target_span))
         self.assertEqual('on and on and on and on.',
-                         get_text(source_text, matches[1].source_match_segment))
+                         get_text(source_text, matches[1].source_span))
         self.assertEqual('on and on and on and on.',
-                         get_text(target_text, matches[1].target_match_segment))
+                         get_text(target_text, matches[1].target_span))
 
     def test_merging_matches_6(self):
         source_text = 'With a tree on the roof.\n\n' \
                       'A house in a forest dummy dummy with a tree on the roof.'
         target_text = 'A house in a forest with a tree on the roof.'
 
-        matches = self.lotte.compare(source_text, target_text)
+        matches = self.quid.compare(source_text, target_text)
 
         self.assertEqual(1, len(matches))
 
-        self.assertEqual(26, matches[0].source_match_segment.character_start_pos)
-        self.assertEqual(82, matches[0].source_match_segment.character_end_pos)
-        self.assertEqual(0, matches[0].target_match_segment.character_start_pos)
-        self.assertEqual(44, matches[0].target_match_segment.character_end_pos)
+        self.assertEqual(26, matches[0].source_span.start)
+        self.assertEqual(82, matches[0].source_span.end)
+        self.assertEqual(0, matches[0].target_span.start)
+        self.assertEqual(44, matches[0].target_span.end)
 
         self.assertEqual('A house in a forest dummy dummy with a tree on the roof.',
-                         get_text(source_text, matches[0].source_match_segment))
+                         get_text(source_text, matches[0].source_span))
         self.assertEqual('A house in a forest with a tree on the roof.',
-                         get_text(target_text, matches[0].target_match_segment))
+                         get_text(target_text, matches[0].target_span))
 
     def test_too_short_matches(self):
         source_text = 'This is a long Text but there are too many words here.'
         target_text = 'This is a long'
 
-        matches = self.lotte.compare(source_text, target_text)
+        matches = self.quid.compare(source_text, target_text)
 
         self.assertEqual(0, len(matches))
 
@@ -301,97 +301,97 @@ class LotteTestCase(unittest.TestCase):
         source_text = 'This is a long Text but there are too many words here and then there are even more words.'
         target_text = 'This is a long Text ... even more words.'
 
-        matches = self.lotte.compare(source_text, target_text)
+        matches = self.quid.compare(source_text, target_text)
 
         self.assertEqual(1, len(matches))
 
-        self.assertEqual(0, matches[0].source_match_segment.character_start_pos)
-        self.assertEqual(19, matches[0].source_match_segment.character_end_pos)
-        self.assertEqual(0, matches[0].target_match_segment.character_start_pos)
-        self.assertEqual(19, matches[0].target_match_segment.character_end_pos)
+        self.assertEqual(0, matches[0].source_span.start)
+        self.assertEqual(19, matches[0].source_span.end)
+        self.assertEqual(0, matches[0].target_span.start)
+        self.assertEqual(19, matches[0].target_span.end)
 
         self.assertEqual('This is a long Text',
-                         get_text(source_text, matches[0].source_match_segment))
+                         get_text(source_text, matches[0].source_span))
         self.assertEqual('This is a long Text',
-                         get_text(target_text, matches[0].target_match_segment))
+                         get_text(target_text, matches[0].target_span))
 
     def test_ellipse_2(self):
         source_text = 'This is a long Text but there are too many words here are even more words.'
         target_text = 'This is a long Text ... even more words.'
 
-        matches = self.lotte.compare(source_text, target_text)
+        matches = self.quid.compare(source_text, target_text)
 
         self.assertEqual(1, len(matches))
 
-        self.assertEqual(0, matches[0].source_match_segment.character_start_pos)
-        self.assertEqual(74, matches[0].source_match_segment.character_end_pos)
-        self.assertEqual(0, matches[0].target_match_segment.character_start_pos)
-        self.assertEqual(40, matches[0].target_match_segment.character_end_pos)
+        self.assertEqual(0, matches[0].source_span.start)
+        self.assertEqual(74, matches[0].source_span.end)
+        self.assertEqual(0, matches[0].target_span.start)
+        self.assertEqual(40, matches[0].target_span.end)
 
         self.assertEqual('This is a long Text but there are too many words here are even more words.',
-                         get_text(source_text, matches[0].source_match_segment))
+                         get_text(source_text, matches[0].source_span))
         self.assertEqual('This is a long Text ... even more words.',
-                         get_text(target_text, matches[0].target_match_segment))
+                         get_text(target_text, matches[0].target_span))
 
     def test_ellipse_forward_extending(self):
         source_text = 'This is a long Text but there even more words.'
         target_text = 'This is a long Text ... even more words.'
 
-        matches = self.lotte.compare(source_text, target_text)
+        matches = self.quid.compare(source_text, target_text)
 
         self.assertEqual(1, len(matches))
 
-        self.assertEqual(0, matches[0].source_match_segment.character_start_pos)
-        self.assertEqual(46, matches[0].source_match_segment.character_end_pos)
-        self.assertEqual(0, matches[0].target_match_segment.character_start_pos)
-        self.assertEqual(40, matches[0].target_match_segment.character_end_pos)
+        self.assertEqual(0, matches[0].source_span.start)
+        self.assertEqual(46, matches[0].source_span.end)
+        self.assertEqual(0, matches[0].target_span.start)
+        self.assertEqual(40, matches[0].target_span.end)
 
         self.assertEqual('This is a long Text but there even more words.',
-                         get_text(source_text, matches[0].source_match_segment))
+                         get_text(source_text, matches[0].source_span))
         self.assertEqual('This is a long Text ... even more words.',
-                         get_text(target_text, matches[0].target_match_segment))
+                         get_text(target_text, matches[0].target_span))
 
     def test_combine_two_tokens_in_source(self):
         source_text = 'This is a long Text but there are more words.'
         target_text = 'This is a long Text but there aremore words.'
 
-        matches = self.lotte.compare(source_text, target_text)
+        matches = self.quid.compare(source_text, target_text)
 
         self.assertEqual(1, len(matches))
 
-        self.assertEqual(0, matches[0].source_match_segment.character_start_pos)
-        self.assertEqual(45, matches[0].source_match_segment.character_end_pos)
-        self.assertEqual(0, matches[0].target_match_segment.character_start_pos)
-        self.assertEqual(44, matches[0].target_match_segment.character_end_pos)
+        self.assertEqual(0, matches[0].source_span.start)
+        self.assertEqual(45, matches[0].source_span.end)
+        self.assertEqual(0, matches[0].target_span.start)
+        self.assertEqual(44, matches[0].target_span.end)
 
         self.assertEqual('This is a long Text but there are more words.',
-                         get_text(source_text, matches[0].source_match_segment))
+                         get_text(source_text, matches[0].source_span))
         self.assertEqual('This is a long Text but there aremore words.',
-                         get_text(target_text, matches[0].target_match_segment))
+                         get_text(target_text, matches[0].target_span))
 
     def test_combine_two_tokens_in_target(self):
         source_text = 'This is a long Text but there aremore words.'
         target_text = 'This is a long Text but there are more words.'
 
-        matches = self.lotte.compare(source_text, target_text)
+        matches = self.quid.compare(source_text, target_text)
 
         self.assertEqual(1, len(matches))
 
-        self.assertEqual(0, matches[0].source_match_segment.character_start_pos)
-        self.assertEqual(44, matches[0].source_match_segment.character_end_pos)
-        self.assertEqual(0, matches[0].target_match_segment.character_start_pos)
-        self.assertEqual(45, matches[0].target_match_segment.character_end_pos)
+        self.assertEqual(0, matches[0].source_span.start)
+        self.assertEqual(44, matches[0].source_span.end)
+        self.assertEqual(0, matches[0].target_span.start)
+        self.assertEqual(45, matches[0].target_span.end)
 
         self.assertEqual('This is a long Text but there aremore words.',
-                         get_text(source_text, matches[0].source_match_segment))
+                         get_text(source_text, matches[0].source_span))
         self.assertEqual('This is a long Text but there are more words.',
-                         get_text(target_text, matches[0].target_match_segment))
+                         get_text(target_text, matches[0].target_span))
 
     def test_no_matches(self):
         source_text = 'This is a long Text but there are no matches.'
         target_text = 'And here is another Text and this time again we can\'t find anything'
 
-        matches = self.lotte.compare(source_text, target_text)
+        matches = self.quid.compare(source_text, target_text)
 
         self.assertEqual(0, len(matches))
 
@@ -399,19 +399,19 @@ class LotteTestCase(unittest.TestCase):
         source_text = 'This is a long Text but there are more words in this one and I really like that.'
         target_text = 'This is a long Text but there are words in this one and I like that.'
 
-        matches = self.lotte.compare(source_text, target_text)
+        matches = self.quid.compare(source_text, target_text)
 
         self.assertEqual(1, len(matches))
 
-        self.assertEqual(0, matches[0].source_match_segment.character_start_pos)
-        self.assertEqual(62, matches[0].source_match_segment.character_end_pos)
-        self.assertEqual(0, matches[0].target_match_segment.character_start_pos)
-        self.assertEqual(57, matches[0].target_match_segment.character_end_pos)
+        self.assertEqual(0, matches[0].source_span.start)
+        self.assertEqual(62, matches[0].source_span.end)
+        self.assertEqual(0, matches[0].target_span.start)
+        self.assertEqual(57, matches[0].target_span.end)
 
         self.assertEqual('This is a long Text but there are more words in this one and I',
-                         get_text(source_text, matches[0].source_match_segment))
+                         get_text(source_text, matches[0].source_span))
         self.assertEqual('This is a long Text but there are words in this one and I',
-                         get_text(target_text, matches[0].target_match_segment))
+                         get_text(target_text, matches[0].target_span))
 
 
 if __name__ == '__main__':
diff --git a/test/TestKeyPassager.py b/test/TestPassager.py
similarity index 73%
rename from test/TestKeyPassager.py
rename to test/TestPassager.py
index a73f76aba459811e4e8d70ccbe642d1008a278a3..785ec5691a71ed4edff44f766f3b8044b3750d4d 100644
--- a/test/TestKeyPassager.py
+++ b/test/TestPassager.py
@@ -1,35 +1,35 @@
 import unittest
 
-from key_passager.KeyPassager import KeyPassager
-from key_passager.TextWithMatches import TextWithMatches
-from match.Match import Match
-from match.MatchSegment import MatchSegment
+from quid.passager.Passager import Passager
+from quid.passager.TextWithMatches import TextWithMatches
+from quid.match.Match import Match
+from quid.match.MatchSpan import MatchSpan
 
 
-class KeyPassagerTestCase(unittest.TestCase):
+class PassagerTestCase(unittest.TestCase):
 
     def setUp(self) -> None:
-        self.key_passager = KeyPassager()
+        self.passager = Passager()
 
-    def test_key_passager(self):
+    def test_passager(self):
         source_content = 'aa bb cc dd ee ff gg\nhh. dd ee ff gg hh ii.\njjj kkk lll mmm nnn ooo ppp\n' \
                          'qqq rrr sss ttt uuu vvv www\nxxx yyy zzz'
         text_1 = 'aa bb cc dd kkk lll mmm ...\nwww xxx yyy zzz. axc bzu fyo\nloi uiq dd ee ff gg hh\n' \
                  'ii. jjj kkk\ndd ee ff'
 
-        match_1_source_match_segment = MatchSegment(50, 113)
-        match_1_target_match_segment = MatchSegment(12, 44)
+        match_1_source_match_segment = MatchSpan(50, 113)
+        match_1_target_match_segment = MatchSpan(12, 44)
         match_1 = Match(match_1_source_match_segment, match_1_target_match_segment)
 
-        match_2_source_match_segment = MatchSegment(26, 44)
-        match_2_target_match_segment = MatchSegment(65, 83)
+        match_2_source_match_segment = MatchSpan(26, 44)
+        match_2_target_match_segment = MatchSpan(65, 83)
         match_2 = Match(match_2_source_match_segment, match_2_target_match_segment)
 
         matches = [match_1, match_2]
 
         target_text_matches = TextWithMatches('text 1', text_1, matches)
         target_text_matches_list = [target_text_matches]
-        result = self.key_passager.generate(target_text_matches_list, source_content)
+        result = self.passager.generate(target_text_matches_list, source_content)
 
         self.assertIsNotNone(result)
         self.assertEqual(2, len(result.citation_source_links))
@@ -44,31 +44,31 @@ class KeyPassagerTestCase(unittest.TestCase):
         text_2 = 'Dies ist ein kurzer kleiner Test um das Erkennen von Overlap ein bisschen zu testen und außerdem sicherzustellen, dass auch vielfach Überlappungen erkannt werden müssen.'
 
         # Text 1
-        text_1_match_1_source_match_segment = MatchSegment(5, 32)
-        text_1_match_1_target_match_segment = MatchSegment(12, 39)
+        text_1_match_1_source_match_segment = MatchSpan(5, 32)
+        text_1_match_1_target_match_segment = MatchSpan(12, 39)
         text_1_match_1 = Match(text_1_match_1_source_match_segment, text_1_match_1_target_match_segment)
 
-        text_1_match_2_source_match_segment = MatchSegment(53, 83)
-        text_1_match_2_target_match_segment = MatchSegment(79, 109)
+        text_1_match_2_source_match_segment = MatchSpan(53, 83)
+        text_1_match_2_target_match_segment = MatchSpan(79, 109)
         text_1_match_2 = Match(text_1_match_2_source_match_segment, text_1_match_2_target_match_segment)
 
-        text_1_match_3_source_match_segment = MatchSegment(119, 161)
-        text_1_match_3_target_match_segment = MatchSegment(150, 193)
+        text_1_match_3_source_match_segment = MatchSpan(119, 161)
+        text_1_match_3_target_match_segment = MatchSpan(150, 193)
         text_1_match_3 = Match(text_1_match_3_source_match_segment, text_1_match_3_target_match_segment)
 
         text_1_matches = [text_1_match_1, text_1_match_2, text_1_match_3]
         text_1_text_with_matches = TextWithMatches('text 1', text_1, text_1_matches)
 
         # Text 2
-        text_2_match_1_source_match_segment = MatchSegment(0, 169)
-        text_2_match_1_target_match_segment = MatchSegment(0, 169)
+        text_2_match_1_source_match_segment = MatchSpan(0, 169)
+        text_2_match_1_target_match_segment = MatchSpan(0, 169)
         text_2_match_1 = Match(text_2_match_1_source_match_segment, text_2_match_1_target_match_segment)
 
         text_2_matches = [text_2_match_1]
         text_2_text_with_matches = TextWithMatches('text 2', text_2, text_2_matches)
 
         texts_with_matches = [text_1_text_with_matches, text_2_text_with_matches]
-        result = self.key_passager.generate(texts_with_matches, source_content)
+        result = self.passager.generate(texts_with_matches, source_content)
 
         self.assertIsNotNone(result)
         self.assertEqual(1, len(result.citation_sources))
@@ -91,31 +91,31 @@ class KeyPassagerTestCase(unittest.TestCase):
         text_3 = 'um die Erstellung von important segments ein bisschen zu testen und außerdem.'
 
         # Text 1
-        text_1_match_1_source_match_segment = MatchSegment(0, 50)
-        text_1_match_1_target_match_segment = MatchSegment(0, 50)
+        text_1_match_1_source_match_segment = MatchSpan(0, 50)
+        text_1_match_1_target_match_segment = MatchSpan(0, 50)
         text_1_match_1 = Match(text_1_match_1_source_match_segment, text_1_match_1_target_match_segment)
 
         text_1_matches = [text_1_match_1]
         text_1_text_with_matches = TextWithMatches('text 1', text_1, text_1_matches)
 
         # Text 2
-        text_2_match_1_source_match_segment = MatchSegment(33, 110)
-        text_2_match_1_target_match_segment = MatchSegment(0, 77)
+        text_2_match_1_source_match_segment = MatchSpan(33, 110)
+        text_2_match_1_target_match_segment = MatchSpan(0, 77)
         text_2_match_1 = Match(text_2_match_1_source_match_segment, text_2_match_1_target_match_segment)
 
         text_2_matches = [text_2_match_1]
         text_2_text_with_matches = TextWithMatches('text 2', text_2, text_2_matches)
 
         # Text 3
-        text_3_match_1_source_match_segment = MatchSegment(33, 110)
-        text_3_match_1_target_match_segment = MatchSegment(0, 77)
+        text_3_match_1_source_match_segment = MatchSpan(33, 110)
+        text_3_match_1_target_match_segment = MatchSpan(0, 77)
         text_3_match_1 = Match(text_3_match_1_source_match_segment, text_3_match_1_target_match_segment)
 
         text_3_matches = [text_3_match_1]
         text_3_text_with_matches = TextWithMatches('text 3', text_3, text_3_matches)
 
         texts_with_matches = [text_1_text_with_matches, text_2_text_with_matches, text_3_text_with_matches]
-        result = self.key_passager.generate(texts_with_matches, source_content)
+        result = self.passager.generate(texts_with_matches, source_content)
 
         self.assertIsNotNone(result)
         self.assertEqual(1, len(result.citation_sources))
@@ -134,40 +134,40 @@ class KeyPassagerTestCase(unittest.TestCase):
         text_5 = 'um die Erstellung von important segments'
 
         # Text 1
-        text_1_match_1_source_match_segment = MatchSegment(0, 73)
-        text_1_match_1_target_match_segment = MatchSegment(0, 73)
+        text_1_match_1_source_match_segment = MatchSpan(0, 73)
+        text_1_match_1_target_match_segment = MatchSpan(0, 73)
         text_1_match_1 = Match(text_1_match_1_source_match_segment, text_1_match_1_target_match_segment)
 
         text_1_matches = [text_1_match_1]
         text_1_text_with_matches = TextWithMatches('text 1', text_1, text_1_matches)
 
         # Text 2
-        text_2_match_1_source_match_segment = MatchSegment(0, 73)
-        text_2_match_1_target_match_segment = MatchSegment(0, 73)
+        text_2_match_1_source_match_segment = MatchSpan(0, 73)
+        text_2_match_1_target_match_segment = MatchSpan(0, 73)
         text_2_match_1 = Match(text_2_match_1_source_match_segment, text_2_match_1_target_match_segment)
 
         text_2_matches = [text_2_match_1]
         text_2_text_with_matches = TextWithMatches('text 2', text_2, text_2_matches)
 
         # Text 3
-        text_3_match_1_source_match_segment = MatchSegment(33, 110)
-        text_3_match_1_target_match_segment = MatchSegment(0, 77)
+        text_3_match_1_source_match_segment = MatchSpan(33, 110)
+        text_3_match_1_target_match_segment = MatchSpan(0, 77)
         text_3_match_1 = Match(text_3_match_1_source_match_segment, text_3_match_1_target_match_segment)
 
         text_3_matches = [text_3_match_1]
         text_3_text_with_matches = TextWithMatches('text 3', text_3, text_3_matches)
 
         # Text 4
-        text_4_match_1_source_match_segment = MatchSegment(33, 73)
-        text_4_match_1_target_match_segment = MatchSegment(0, 40)
+        text_4_match_1_source_match_segment = MatchSpan(33, 73)
+        text_4_match_1_target_match_segment = MatchSpan(0, 40)
         text_4_match_1 = Match(text_4_match_1_source_match_segment, text_4_match_1_target_match_segment)
 
         text_4_matches = [text_4_match_1]
         text_4_text_with_matches = TextWithMatches('text 4', text_4, text_4_matches)
 
         # Text 5
-        text_5_match_1_source_match_segment = MatchSegment(33, 73)
-        text_5_match_1_target_match_segment = MatchSegment(0, 40)
+        text_5_match_1_source_match_segment = MatchSpan(33, 73)
+        text_5_match_1_target_match_segment = MatchSpan(0, 40)
         text_5_match_1 = Match(text_5_match_1_source_match_segment, text_5_match_1_target_match_segment)
 
         text_5_matches = [text_5_match_1]
@@ -175,7 +175,7 @@ class KeyPassagerTestCase(unittest.TestCase):
 
         texts_with_matches = [text_1_text_with_matches, text_2_text_with_matches, text_3_text_with_matches,
                               text_4_text_with_matches, text_5_text_with_matches]
-        result = self.key_passager.generate(texts_with_matches, source_content)
+        result = self.passager.generate(texts_with_matches, source_content)
 
         self.assertIsNotNone(result)
         self.assertEqual(1, len(result.citation_sources))
diff --git a/test/TestSetup.py b/test/TestSetup.py
index ecf92679ce212fbfc6289b372dc2aac0c47a0711..35244bf2b18221aa6f09dc2f692fc45b61285b66 100644
--- a/test/TestSetup.py
+++ b/test/TestSetup.py
@@ -1,50 +1,50 @@
 import unittest
 
-from lotte.Lotte import Lotte
+from quid.core.Quid import Quid
 
 
 class SetupTestCase(unittest.TestCase):
 
     def test_setup_working(self):
         try:
-            Lotte(5)
+            Quid(5)
         except ValueError:
             self.fail("ValueError raised unexpectedly!")
 
     def test_setup_incorrect_min_match_length(self):
         with self.assertRaises(Exception) as context:
-            Lotte(0)
+            Quid(0)
         self.assertEqual('min match length must be >= 1', context.exception.args[0])
 
     def test_setup_incorrect_look_back_limit(self):
         with self.assertRaises(Exception) as context:
-            Lotte(3, look_back_limit=-1)
+            Quid(3, look_back_limit=-1)
         self.assertEqual('look back limit must be positive', context.exception.args[0])
 
     def test_setup_incorrect_look_ahead_limit(self):
         with self.assertRaises(Exception) as context:
-            Lotte(3, look_ahead_limit=-1)
+            Quid(3, look_ahead_limit=-1)
         self.assertEqual('look ahead limit must be positive', context.exception.args[0])
 
     def test_setup_incorrect_max_merge_distance(self):
         with self.assertRaises(Exception) as context:
-            Lotte(3, max_merge_distance=-1)
+            Quid(3, max_merge_distance=-1)
         self.assertEqual('max merge distance must be positive', context.exception.args[0])
 
     def test_setup_incorrect_max_merge_ellipse_distance(self):
         with self.assertRaises(Exception) as context:
-            Lotte(3, max_merge_ellipse_distance=-1)
+            Quid(3, max_merge_ellipse_distance=-1)
         self.assertEqual('max merge ellipse distance must be positive', context.exception.args[0])
 
     def test_empty_source_input(self):
-        lotte = Lotte(5)
-        matches = lotte.compare('', 'test')
+        quid = Quid(5)
+        matches = quid.compare('', 'test')
 
         self.assertEqual(0, len(matches))
 
     def test_empty_target_input(self):
-        lotte = Lotte(5)
-        matches = lotte.compare('test', '')
+        quid = Quid(5)
+        matches = quid.compare('test', '')
 
         self.assertEqual(0, len(matches))
 
diff --git a/test/TestVisualizer.py b/test/TestVisualizer.py
index 3f15cf1560aa9366508fd15d5deb457502eecc0c..ab49ac3b96cbf65c5a5a9125a2c0cab4067726ad 100644
--- a/test/TestVisualizer.py
+++ b/test/TestVisualizer.py
@@ -1,14 +1,14 @@
 import unittest
 
-from key_passager.CitationSource import CitationSource
-from key_passager.CitationSourceLink import CitationSourceLink
-from key_passager.ImportantSegment import ImportantSegment
-from key_passager.SourceSegment import SourceSegment
-from key_passager.TargetLocation import TargetLocation
-from key_passager.TargetLocationSelection import TargetLocationSelection
-from key_passager.TargetText import TargetText
-from visualization.TargetTextWithContent import TargetTextWithContent
-from visualization.Visualizer import Visualizer
+from quid.passager.CitationSource import CitationSource
+from quid.passager.CitationSourceLink import CitationSourceLink
+from quid.passager.ImportantSegment import ImportantSegment
+from quid.passager.SourceSegment import SourceSegment
+from quid.passager.TargetLocation import TargetLocation
+from quid.passager.TargetLocationSelection import TargetLocationSelection
+from quid.passager.TargetText import TargetText
+from quid.visualization.TargetTextWithContent import TargetTextWithContent
+from quid.visualization.Visualizer import Visualizer
 
 
 class VisualizerTestCase(unittest.TestCase):