diff --git a/src/calng/ShmemTrainMatcher.py b/src/calng/ShmemTrainMatcher.py
index 4a08f9a4497fd2bcee8b1793bbeb6c0082c364dd..c77240fe17d67f01b99528ecf3d7cda90d0230f1 100644
--- a/src/calng/ShmemTrainMatcher.py
+++ b/src/calng/ShmemTrainMatcher.py
@@ -91,11 +91,23 @@ class ShmemTrainMatcher(TrainMatcher.TrainMatcher):
             .displayedName("Array stacking")
             .allowedStates(State.PASSIVE)
             .description(
-                "List source or key patterns to merge their data arrays, e.g. to "
-                "combine multiple detector sources or digitizer channels into a single "
-                "source or key. Both source or key patterns may be regular expressions,"
-                " but only one may have multiple matches at the same time. The merged "
-                "source or key is substituted by the replacement value."
+                "Specify which source(s) or key(s) to stack."
+                "When stacking sources, the 'Source pattern' is interpreted as a "
+                "regular expression and the 'Key pattern' is interpreted as an "
+                "ordinary string. From all sources matching the source pattern, the "
+                "data under this key (should be array with same dimensions across all "
+                "stacked sources) is stacked in the same order as the sources are "
+                "listed in 'Data sources' and the result is under the same key name in "
+                "a new source named by 'Replacement'. "
+                "When stacking keys, both the 'Source pattern' and the 'Key pattern' "
+                "are regular expressions. Within each source matching the source "
+                "pattern, all keys matching the key pattern are stacked and the result "
+                "is put under the key named by 'Replacement'. "
+                "While source stacking is optimized and can use thread pool, key "
+                "stacking will iterate over all paths in matched sources and naively "
+                "call np.stack for each key pattern. In either case, data that is used "
+                "for stacking is removed from its original location (e.g. key is erased "
+                "from hash)."
             )
             .setColumns(merge_schema())
             .assignmentOptional()
@@ -293,7 +305,6 @@ class ShmemTrainMatcher(TrainMatcher.TrainMatcher):
                 data_hash[new_key] = stacked
 
     def on_matched_data(self, train_id, sources):
-
         new_sources_map = {}
         if self._thread_pool is None:
             for source, (data, timestamp) in sources.items():