diff --git a/core/functions/tracks.py b/core/functions/tracks.py
index bff48680a3ab1f46f656865270fdcc6d5e7722ee..ecc4e0f56742b720ffb01e7d9ac79c325983a72f 100644
--- a/core/functions/tracks.py
+++ b/core/functions/tracks.py
@@ -214,13 +214,12 @@ def get_joinable(tracks, smooth=False, tol=0.1, window=5, degree=3) -> dict:
     """
 
     tracks.index.names = [
-        "pos",
         "trap",
         "cell",
     ]  # TODO remove this once it is integrated in the tracker
     # contig=tracks.groupby(['pos','trap']).apply(tracks2contig)
     clean = clean_tracks(tracks, min_len=window + 1, min_gr=0.9)  # get useful tracks
-    contig = clean.groupby(["pos", "trap"]).apply(get_contiguous_pairs)
+    contig = clean.groupby(["trap"]).apply(get_contiguous_pairs)
     contig = contig.loc[contig.apply(len) > 0]
     # candict = {k:v for d in contig.values for k,v in d.items()}
 
diff --git a/core/merger.py b/core/merger.py
index 6000a2b5467629e0d9a3097db60a3262e1d48f17..7659a6807cb3183ea02852df59f1a979639b7ecc 100644
--- a/core/merger.py
+++ b/core/merger.py
@@ -1,5 +1,36 @@
-# Classes in charge of merging tracks
+class Parameters:
+    """
+    :param tol: float or int threshold of average (prediction error/std) necessary
+        to consider two tracks the same. If float is fraction of first track,
+        if int it is absolute units.
+    :param window: int value of window used for savgol_filter
+    :param degree: int value of polynomial degree passed to savgol_filter
+    """
 
-class Merger(BasePicker):
+    def __init__(
+        self,
+        smooth: bool = False,
+        tolerance: float = 0.1,
+        window: int = 5,
+        degree: int = 3,
+        min_avg_delta: float = 0.9,
+    ):
+
+        self.smooth = smooth
+
+        self.tolerance = tolerance
+
+        self.window = window
+
+        self.degree = degree
+
+        self.min_avg_delta = min_avg_delta
+
+
+class Merger:
+    # Class in charge of merging tracks
     def __init__(self, parameters):
-        pass
+        self.parameters = parameters
+
+    def run(self, signal):
+        merged, joint_pairs = merge_tracks(signal, min_len=self.window + 1)
diff --git a/core/picker.py b/core/picker.py
index 0a4ed16652354581ca4c59a31c8517e50220c135..2618ae99a99b307918eebec00a1c8fb4b10dc728 100644
--- a/core/picker.py
+++ b/core/picker.py
@@ -1,11 +1,10 @@
-# from abc import ABC, abstractmethod
 from typing import Tuple, Union, List
 
 import numpy as np
 import pandas as pd
 
 from core.cells import CellsHDF
-from postprocessor.core.functions.tracks import max_ntps, max_nonstop_ntps
+from postprocessor.core.functions.signals import max_ntps, max_nonstop_ntps
 
 
 # def BasePicker(ABC):
@@ -18,24 +17,24 @@ from postprocessor.core.functions.tracks import max_ntps, max_nonstop_ntps
 
 class Picker:
     """
-    :tracks: pd.DataFrame
+    :signals: pd.DataFrame of data used for selection, such as area or GFP/np.max/mean
     :cells: Cell object passed to the constructor
     :condition: Tuple with condition and associated parameter(s), conditions can be
     "present", "nonstoply_present" or "quantile".
-    Determines the thersholds or fractions of tracks/signals to use.
-    :lineage: str {"mothers", "daughters", "families", "orphans"}. Mothers/daughters picks cells with those tags, families pick the union of both and orphans the difference between the total and families.
+    Determines the thersholds or fractions of signals/signals to use.
+    :lineage: str {"mothers", "daughters", "families" (mothers AND daughters), "orphans"}. Mothers/daughters picks cells with those tags, families pick the union of both and orphans the difference between the total and families.
     """
 
     def __init__(
         self,
-        tracks: pd.DataFrame,
+        signals: pd.DataFrame,
         cells: CellsHDF,
         condition: Tuple[str, Union[float, int]] = None,
         lineage: str = None,
         sequence: List[str] = ["lineage", "condition"],
     ):
-        self.tracks = tracks
-        self._index = tracks.index
+        self.signals = signals
+        self._index = signals.index
         self._cells = cells
         self.condition = condition
         self.lineage = lineage
@@ -57,7 +56,7 @@ class Picker:
         return mb_matrix
 
     def pick_by_lineage(self):
-        idx = self.tracks.index
+        idx = self.signals.index
 
         if self.lineage:
             ma = self._cells["mother_assign"]
@@ -75,18 +74,18 @@ class Picker:
                     idx = idx[list(set(range(len(idx))).difference(families))]
 
             idx = self._index[idx]
-            idx = list(set(idx).intersection(self.tracks.index))
+            idx = list(set(idx).intersection(self.signals.index))
 
-        return self.tracks.loc[idx]
+        return self.signals.loc[idx]
 
     def pick_by_condition(self):
-        idx = switch_case(self.condition[0], self.tracks, self.condition[1])
-        return self.tracks.loc[idx]
+        idx = switch_case(self.condition[0], self.signals, self.condition[1])
+        return self.signals.loc[idx]
 
     def run(self):
         for alg in self.sequence:
-            self.tracks = getattr(self, "pick_by" + alg)()
-        return self.tracks
+            self.signals = getattr(self, "pick_by" + alg)()
+        return self.signals
 
 
 def as_int(threshold: Union[float, int], ntps: int):
@@ -97,13 +96,13 @@ def as_int(threshold: Union[float, int], ntps: int):
 
 def switch_case(
     condition: str,
-    tracks: pd.DataFrame,
+    signals: pd.DataFrame,
     threshold: Union[float, int],
 ):
-    threshold_asint = as_int(threshold, tracks.shape[1])
+    threshold_asint = as_int(threshold, signals.shape[1])
     case_mgr = {
-        "present": tracks.apply(max_ntps, axis=1) > threshold_asint,
-        "nonstoply_present": tracks.apply(max_nonstop_ntps, axis=1) > threshold_asint,
-        "quantile": [np.quantile(tracks.values[tracks.notna()], threshold)],
+        "present": signals.apply(max_ntps, axis=1) > threshold_asint,
+        "nonstoply_present": signals.apply(max_nonstop_ntps, axis=1) > threshold_asint,
+        "quantile": [np.quantile(signals.values[signals.notna()], threshold)],
     }
     return case_mgr[condition]
diff --git a/core/processor.py b/core/processor.py
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..917b951773a11d0b4d591be8951993382f824bbb 100644
--- a/core/processor.py
+++ b/core/processor.py
@@ -0,0 +1,13 @@
+class PostProcessor:
+    def __init__(self, parameters):
+        self.parameters = parameters
+
+        self.merger = Merger(parameters["merger"])
+        self.picker = Picker(parameters["picker"])
+        self.processes, self.branches = [
+            (self.get_process(process), branch)
+            for process, branch in parameters["processes"]
+        ]
+
+    def run(self):
+        pass