Project

General

Profile

Product Mixing » History » Version 17

Kyle Knoepfel, 08/13/2018 04:29 PM

1 1 Christopher Green
h1. Product Mixing
2 15 Kyle Knoepfel
3 15 Kyle Knoepfel
{{>toc}}
4 1 Christopher Green
5 13 Christopher Green
[ The product mixing feature was significantly extended for art version:2.06.00, and the current version of this page reflects those improvements. For the earlier documentation, please see "Product_Mixing@12":https://cdcvs.fnal.gov/redmine/projects/art/wiki/Product_Mixing/12. ]
6 13 Christopher Green
7 1 Christopher Green
h2. Overview.
8 1 Christopher Green
9 13 Christopher Green
*Product Mixing* is our label for the ability to take a feed from a source of secondary events, and combine the products (usually collections) from multiple events into a single (possibly different type of) product or collection to be placed in the primary event. The motivation is of course obvious: background (e.g., cosmic) events or pile-up. Since art version:2.06.00, this functionality has been extended to subrun and run products, although with certain caveats which are discussed later.
10 1 Christopher Green
11 1 Christopher Green
This feature is implemented by providing a module template, @MixFilter@ as a skeleton to handle the low-level interaction with the primary event and secondary files, including the collection of multiple products from different secondary events and the registration of outgoing products. The user must provide a "detail" class implementation which has some mandatory and some optional members in order to register necessary products at the right time and mix the prepared groups of incoming products. The @MixFilter@ will take care of reading the secondary data, either sequentially or randomly and cycling through multiple secondary input files as necessary.
12 1 Christopher Green
13 1 Christopher Green
In order to make the mixing task easier, we have provided several auxiliary utilities which will be described later.
14 1 Christopher Green
15 8 Christopher Green
In summary, the @MixFilter@ module will do the following tasks:
16 1 Christopher Green
17 1 Christopher Green
# Construct a @MixHelper@ object for use by the user's detail class, hereafter referred to as @Detail@ (class) or @detail@ (object).
18 10 Walter E Brown
# Construct @detail@, passing the helper and the module's parameter set. At this point, @detail@ should register any mix operations (one per product to be mixed) using @MixHelper::declareMixOp<>()@, and any non-mixing products to go in to the event (e.g., bookkeeping objects) using @MixHelper::produces<>()@.
19 1 Christopher Green
# For each primary event:
20 1 Christopher Green
## Call the optional @Detail::startEvent()@ function if it exists so @detail@ can position itself for the coming event.
21 1 Christopher Green
## Call @Detail::nSecondaries()@ to decide how many secondary events to read.
22 1 Christopher Green
## Decide which secondary events are to be read.
23 13 Christopher Green
## Call the optional @Detail::processEventIDs()@ function in case the @Detail@ class is interested in the sequence of event IDs (e.g., for bookkeeping purposes). The analogous optional @Detail::processEventAuxiliaries()@ function will also be called at this time.
24 12 Christopher Green
## Call the registered mixing operation for each product to be mixed _in the order in which they were declared by_ @detail@, providing the secondary data to be mixed and putting the resultant mixed product into the primary event.
25 1 Christopher Green
## Call the optional @Detail::finalizeEvent()@ function to tidy up and possibly put any bookkeeping products (registered with @MixHelper::produces<>()@) into the primary event.
26 1 Christopher Green
27 1 Christopher Green
The @MixFilter@ module will take care of opening new secondary files as necessary, and will additionally call an optional function @Detail::eventsToSkip()@ as each file is opened (in sequential mode only) if it is desired to have a particular offset into each file to insure against coherent backgrounds in events.
28 1 Christopher Green
29 13 Christopher Green
30 2 Christopher Green
h2. Mix operations: what are they and what do they need to do?
31 3 Christopher Green
32 1 Christopher Green
A mix operation is a function provided by the user which returns a @bool@ and expects three arguments:
33 3 Christopher Green
34 17 Kyle Knoepfel
* @vector<PROD const*> const&@ containing the secondary products to be mixed;
35 17 Kyle Knoepfel
* @OPROD&@, the output product to be filled by the mix function; and
36 17 Kyle Knoepfel
* @PtrRemapper const&@, a helper for use remapping @Ptr@ and friends (see below).
37 3 Christopher Green
38 13 Christopher Green
It may be a free function, a member function of @Detail@ or some other user class, or a function object ("functor") whose @operator()@ has the correct signature (see source:art/Framework/IO/ProductMix/MixTypes.h for a definition of a useful template alias, @art::MixFunc@). This mix function supposed to use the information contained in the secondary products to fill the output product, using the @PtrRemapper@ if appropriate, and return a @bool@ indicating whether the output product should be placed in the event.
39 1 Christopher Green
40 1 Christopher Green
All mix operations must be declared _at construction time_ by @detail@, using the @MixHelper@ provided as a constructor argument.
41 1 Christopher Green
42 13 Christopher Green
Mix operations are always called in the event loop. The @art::MixFilter@ module template and associated utilities take care of registering the primary output product, marshaling the secondary data streams, and obtaining and organizing the products from the secondary data stream for mixing into each primary event. If the mix function returns true, the output product will be written into the primary event.
43 13 Christopher Green
44 13 Christopher Green
For non-event-level products, the mix operation is called for every primary event with the sequence of subrun or run products corresponding to the events chosen for mixing from the secondary stream. The user is responsible for handling duplicates. If data are intended for the primary event, then the provided @OPROD@ is the appropriate place; if data are intended for the primary subrun or run, then the detail object's @endSubRun()@ or @endRun()@ function(s) are responsible for putting those (explicitly declared) products into the primary data stream.
45 13 Christopher Green
46 13 Christopher Green
Note that since @art::Ptr@ may not be used in subrun- and run-level products currently, the @art::PtrRemapper@ provided to non-event-level mix operations is unintialized and should not be used.
47 13 Christopher Green
48 1 Christopher Green
h2. Mandatory interface for @Detail@.
49 1 Christopher Green
50 1 Christopher Green
h3. Constructor.
51 1 Christopher Green
52 17 Kyle Knoepfel
<pre><code class="cplusplus">
53 17 Kyle Knoepfel
Detail(fhicl::ParameterSet const& ps, art::MixHelper& helper);
54 17 Kyle Knoepfel
</code></pre>
55 1 Christopher Green
56 17 Kyle Knoepfel
The constructor should use the provided parameter set to extract any configuration; and the helper to declare mix operations and any bookkeeping products with @declareMixOp<>()@ and @produces<>()@;
57 17 Kyle Knoepfel
58 3 Christopher Green
h3. @nSecondaries()@.
59 1 Christopher Green
60 17 Kyle Knoepfel
<pre><code class="cplusplus">
61 17 Kyle Knoepfel
size_t nSecondaries();
62 17 Kyle Knoepfel
</code></pre>
63 3 Christopher Green
64 17 Kyle Knoepfel
Tell @MixFilter@ how many secondaries to read for merging into this primary. If required, a random number engine may be obtained from the @RandomNumberGenerator@ service.
65 17 Kyle Knoepfel
66 1 Christopher Green
h2. Optional interface for @Detail@.
67 3 Christopher Green
68 1 Christopher Green
h3. @startEvent()@.
69 4 Christopher Green
70 17 Kyle Knoepfel
<pre><code class="cplusplus">
71 17 Kyle Knoepfel
void startEvent(art::Event const& evt);
72 17 Kyle Knoepfel
</code></pre>
73 1 Christopher Green
74 17 Kyle Knoepfel
Do any per-event initialization of @detail@ here.
75 1 Christopher Green
76 17 Kyle Knoepfel
77 4 Christopher Green
h3. @eventsToSkip()@.
78 1 Christopher Green
79 17 Kyle Knoepfel
<pre><code class="cplusplus">
80 17 Kyle Knoepfel
size_t eventsToSkip();
81 17 Kyle Knoepfel
</code></pre>
82 1 Christopher Green
83 17 Kyle Knoepfel
If provided and the @MixFilter@ is in sequential secondary mode, this function will be called at the beginning of every file to ascertain how many events to skip before pulling products to merge.
84 1 Christopher Green
85 17 Kyle Knoepfel
86 1 Christopher Green
h3. @processEventIDs()@.
87 13 Christopher Green
88 17 Kyle Knoepfel
<pre><code class="cplusplus">
89 17 Kyle Knoepfel
void processEventIDs(art::EventIDSequence const& seq);
90 17 Kyle Knoepfel
</code></pre>
91 13 Christopher Green
92 17 Kyle Knoepfel
@seq@ is an ordered sequence of @art::EventID@ as defined in source:art/Framework/IO/ProductMix/MixTypes.h. Use as you will.
93 13 Christopher Green
94 17 Kyle Knoepfel
95 1 Christopher Green
h3. @processEventAuxiliaries()@.
96 1 Christopher Green
97 17 Kyle Knoepfel
<pre><code class="cplusplus">
98 17 Kyle Knoepfel
void processEventAuxiliaries(art::EventAuxiliarySequence const& seq);
99 17 Kyle Knoepfel
</code></pre>
100 1 Christopher Green
101 17 Kyle Knoepfel
@seq@ is an ordered sequence of @art::EventAuxiliary@ as defined in source:art/Framework/IO/ProductMix/MixTypes.h. Use as you will.
102 1 Christopher Green
103 17 Kyle Knoepfel
104 1 Christopher Green
h3. @finalizeEvent()@.
105 1 Christopher Green
106 17 Kyle Knoepfel
<pre><code class="cplusplus">
107 17 Kyle Knoepfel
void finalizeEvent(art::Event& evt);
108 17 Kyle Knoepfel
</code></pre>
109 13 Christopher Green
110 17 Kyle Knoepfel
Write any non-merge products (i.e. those you declared with @MixHelper::produces<>()@) to the event with @evt.put<>()@.
111 13 Christopher Green
112 17 Kyle Knoepfel
113 1 Christopher Green
h3. @respondToXXXX()@.
114 1 Christopher Green
115 17 Kyle Knoepfel
<pre><code class="cplusplus">
116 17 Kyle Knoepfel
void respondToOpenInputFile(art::FileBlock const& fb);
117 17 Kyle Knoepfel
void respondToCloseInputFile(art::FileBlock const& fb);
118 17 Kyle Knoepfel
void respondToOpenOutputFiles(art::FileBlock const& fb);
119 17 Kyle Knoepfel
void respondToCloseOutputFiles(art::FileBlock const& fb);
120 17 Kyle Knoepfel
</code></pre>
121 1 Christopher Green
122 1 Christopher Green
Equivalent to the eponymous functions of a module, called at the appropriate times.
123 13 Christopher Green
124 1 Christopher Green
125 13 Christopher Green
h3. @beginSubRun()@
126 1 Christopher Green
127 17 Kyle Knoepfel
<pre><code class="cplusplus">
128 17 Kyle Knoepfel
void beginSubRun(art::SubRun const& sr);
129 17 Kyle Knoepfel
</code></pre>
130 1 Christopher Green
131 17 Kyle Knoepfel
Analogous to the eponymous module function, providing read-only access to the primary subrun.
132 1 Christopher Green
133 17 Kyle Knoepfel
134 1 Christopher Green
h3. @endSubRun()@
135 13 Christopher Green
136 17 Kyle Knoepfel
<pre><code class="cplusplus">
137 17 Kyle Knoepfel
void endSubRun(art::SubRun& sr);
138 17 Kyle Knoepfel
</code></pre>
139 13 Christopher Green
140 17 Kyle Knoepfel
Analogous to the eponymous module function, providing write access to the primary subrun. Products registered for the primary subrun may be @put()@ into the @art::SubRun@ at this time.
141 13 Christopher Green
142 17 Kyle Knoepfel
143 13 Christopher Green
h3. @beginRun()@
144 13 Christopher Green
145 17 Kyle Knoepfel
<pre><code class="cplusplus">
146 17 Kyle Knoepfel
void beginRun(art::Run const& r);
147 17 Kyle Knoepfel
</code></pre>
148 13 Christopher Green
149 17 Kyle Knoepfel
Analogous to the eponymous module function, providing read-only access to the primary run.
150 1 Christopher Green
151 17 Kyle Knoepfel
152 1 Christopher Green
h3. @endRun()@
153 1 Christopher Green
154 17 Kyle Knoepfel
<pre><code class="cplusplus">
155 17 Kyle Knoepfel
void endRun(art::Run& r);
156 17 Kyle Knoepfel
</code></pre>
157 4 Christopher Green
158 17 Kyle Knoepfel
Analogous to the eponymous module function, providing write access to the primary run. Products registered for the primary run may be @put()@ into the @art::Run@ at this time.
159 4 Christopher Green
160 17 Kyle Knoepfel
161 4 Christopher Green
h2. Helper utilities.
162 1 Christopher Green
163 1 Christopher Green
h3. @MixHelper@.
164 13 Christopher Green
165 13 Christopher Green
h4. @produces<>()@.
166 13 Christopher Green
167 17 Kyle Knoepfel
Analogous to producer or filter @produces<>()@ calls: declare products to be put into the event, subrun or run which are _not_ direct products of a single mix operation.
168 1 Christopher Green
169 17 Kyle Knoepfel
<pre><code class="cplusplus">
170 17 Kyle Knoepfel
template <class PROD>
171 17 Kyle Knoepfel
void produces(std::string const& instanceName = std::string());
172 17 Kyle Knoepfel
173 1 Christopher Green
template <class PROD, BranchType B>
174 17 Kyle Knoepfel
void produces(std::string const& instanceName = std::string());
175 17 Kyle Knoepfel
</code></pre>
176 4 Christopher Green
177 13 Christopher Green
h4. @DeclareMixOp<>()@.
178 6 Christopher Green
179 4 Christopher Green
These function templates should be used to declare a mix operation.
180 13 Christopher Green
181 13 Christopher Green
All of the available @declareMixOp()@ function templates have the following template arguments:
182 5 Christopher Green
183 4 Christopher Green
# The BranchType (defaults to art::InEvent). Specify explicitly if you wish to mix subrun or run products, or if you need to specify explicitly any of the other template arguments.
184 4 Christopher Green
# The incoming product type (deduced from the provided callable mixer argument).
185 4 Christopher Green
# The outgoing product type (deduced from the provided callable mixer argument).
186 4 Christopher Green
187 4 Christopher Green
Mix operations operation may be specified by providing to the appropriate @declareMixOp<>()@ function:
188 4 Christopher Green
189 4 Christopher Green
# an @InputTag@ specifying which secondary products should be mixed;
190 4 Christopher Green
# an optional instance label for the mixed product (defaulting to the instance label of the incoming product if unspecified); and
191 17 Kyle Knoepfel
# a callable mixer such as:
192 17 Kyle Knoepfel
193 17 Kyle Knoepfel
<pre><code class="cplusplus">bool mixfunc(std::vector<PROD const*> const&,
194 17 Kyle Knoepfel
             OPROD&,
195 17 Kyle Knoepfel
             PtrRemapper const&);
196 17 Kyle Knoepfel
</code></pre>
197 17 Kyle Knoepfel
198 17 Kyle Knoepfel
As the user may prefer, the mixer may take the form of:
199 1 Christopher Green
** an arbitrarily-named free function, or
200 1 Christopher Green
** a function object whose @operator()@ must have the correct type (see @mixfunc@ above), or
201 5 Christopher Green
** an arbitrarily-named member function of any class. In each case, the mixer must have the same type (i.e., the same return type and the same parameter types) illustrated by @mixfunc@ above. The return value of the mix function is taken to indicate whether the product should be placed in the event.
202 5 Christopher Green
   For most situations, the product type template arguments need not be specified as they can be deduced from the signature of the provided callable object.
203 5 Christopher Green
   If the provided callable object is a member function it may be provided bound to the object upon which it is to be called by the user (in which case it is treated as a free function by the registration method) or by specifying the member function followed by the object to which it should be bound (in which case the bind will be done for the user). In this latter case the template argument specifying the product types need *not* be specified usually as they may be deduced from the signature of the provided function. If one specifies an overload set however (e.g., in the case where a class has several @mix()@ member functions, each with arguments indicating a different product) then either the template arguments must be specified in order to constrain the overload set to a single function, or the function argument must be @const_cast<>()@ to specify the desired signature.
204 4 Christopher Green
# An optional @bool@, "outputProduct," defaulting to, "true." A false value for this parameter indicates that the mix product will *never* be put into the event and should therefore not be declared by the @MixHelper@. If the mix operation so registered ever returns true an exception will be thrown.
205 5 Christopher Green
206 4 Christopher Green
@declareMixOp<>()@ may be called with any of the following argument combinations:
207 1 Christopher Green
208 1 Christopher Green
# Provide an @InputTag@ and a mixer that is a free function or function object (or pre-bound member function).
209 1 Christopher Green
# Provide an @InputTag@, an output instance label, and a mixer that is a free function or function object (or pre-bound member function).
210 1 Christopher Green
# Provide an @InputTag@, a mixer that is a non-@const@ member function (of any class), and an object to which that member function should be bound.
211 1 Christopher Green
# Provide an @InputTag@, an output instance label, a mixer that is a non-@const@ member function (of any class), and an object to which that member function should be bound.
212 1 Christopher Green
# As 3, but with a @const@ member function.
213 1 Christopher Green
# As 4, but with a @const@ member function.
214 5 Christopher Green
215 1 Christopher Green
216 1 Christopher Green
h3. @CollectionUtilities.h@: @concatContainers()@ and @flattenCollections()@.
217 1 Christopher Green
218 1 Christopher Green
This header provides two utilities for dealing with the merging of collections:
219 1 Christopher Green
220 1 Christopher Green
h4. @concatContainers()@.
221 1 Christopher Green
222 1 Christopher Green
<pre><code class="cplusplus">template <class CONTAINER>
223 1 Christopher Green
void
224 17 Kyle Knoepfel
concatContainers(CONTAINER& out, CONTAINER const& in);
225 17 Kyle Knoepfel
</code></pre>
226 1 Christopher Green
227 1 Christopher Green
Append the contents of container @in@ to those of container @out@.
228 1 Christopher Green
229 1 Christopher Green
h4. @flattenCollections()@.
230 5 Christopher Green
231 5 Christopher Green
<pre><code class="cplusplus">template <class COLLECTION>
232 1 Christopher Green
void
233 17 Kyle Knoepfel
flattenCollections(vector<COLLECTION const*> in, COLLECTION& out);
234 1 Christopher Green
235 5 Christopher Green
template <class COLLECTION, class OFFSETS>
236 5 Christopher Green
void
237 17 Kyle Knoepfel
flattenCollections(vector<COLLECTION const*> in,
238 17 Kyle Knoepfel
                   COLLECTION& out,
239 17 Kyle Knoepfel
                   OFFSETS& offsets);
240 17 Kyle Knoepfel
</code></pre>
241 1 Christopher Green
242 17 Kyle Knoepfel
Given a sequence of collections by @const*@ accumulate them into @out@, possibly storing the offsets (for use in remapping @Ptr@ into these collections) for use by @PtrRemapper@ (see below). *N.B.* if @COLLECTION@ is a @PtrVector<T>@ then the extra check is made that the individual @PtrVector<T>@ are compatible (ie point to the same product). If this is not the case, you should merge their underlying collections into a single merged product first (in a separate merge operation) and then use @PtrRemapper@ to re-base and merge the @PtrVector<T>@ collections.
243 1 Christopher Green
244 17 Kyle Knoepfel
h3. @PtrRemapper@.
245 1 Christopher Green
246 1 Christopher Green
If at some point you have one or more @Ptr@ objects pointing to collections which have been merged, they will need to be re-based against the merged collection. This will mean changing the underlying @ProductID@ of the pointer-to product and also adjusting the offset by an amount related to the pointed-to collection's position within the new, merged collection. It goes without saying therefore, that the underlying collections should be merged before attempting to re-base any @Ptr@ into them.
247 1 Christopher Green
248 17 Kyle Knoepfel
Each merge function, every event, is provided via its interface with a reference to a @PtrRemapper@ functor which is primed to be capable of re-basing @Ptr@ objects in the current event. @PtrRemapper@ has several @operator()@ templates that accomplish this. Given @PtrRemapper const& remamp@:
249 1 Christopher Green
250 1 Christopher Green
# Remap a single @Ptr@.<pre><code class="cplusplus">Ptr<A> newPtr(remap(oldPtr, offset));</code></pre>
251 1 Christopher Green
# Remap a single @PtrVector@.<pre><code class="cplusplus">PtrVector<A> newPV(remap(oldPV, offset));</code></pre>
252 17 Kyle Knoepfel
# Remap a compatible collection (including @PtrVector@) of @Ptr@ providing begin, end iterators (This will also remap a compatible collection of @PtrVector@, but not of @PtrVector const*@ -- for the latter, see 4-10.)
253 17 Kyle Knoepfel
254 17 Kyle Knoepfel
<pre><code class="cplusplus">
255 17 Kyle Knoepfel
PtrVector<A> newPV;
256 17 Kyle Knoepfel
remap(oldPV.begin(),
257 17 Kyle Knoepfel
      oldPV.end(),
258 17 Kyle Knoepfel
      std::back_inserter(newPV),
259 17 Kyle Knoepfel
      offset);
260 17 Kyle Knoepfel
</code></pre>
261 17 Kyle Knoepfel
262 1 Christopher Green
# Remap and flatten a set of products which are containers of @Ptrs@ (which includes @PtrVector@).<pre><code class="cplusplus">remap(in, out, offsets);</code></pre>where offsets is likely calculated by the appropriate call to @art::flattenCollections<>()@. See source:art/Persistency/Common/CollectionUtilities.h for details.
263 17 Kyle Knoepfel
# Remap and flatten a set of containers of @Ptrs@ (including @PtrVector@) which may be obtained from a component of the provided product. Provide a free function of the correct signature to return a reference to the container of @Ptrs@ given a secondary product, e.g.:
264 17 Kyle Knoepfel
265 17 Kyle Knoepfel
<pre><code class="cplusplus">
266 17 Kyle Knoepfel
PtrVector<B> const& myfunc(A const* prod)
267 17 Kyle Knoepfel
{
268 1 Christopher Green
  return prod->myBs();
269 1 Christopher Green
}
270 1 Christopher Green
271 17 Kyle Knoepfel
remap(in, out, offsets, &myfunc);
272 17 Kyle Knoepfel
</code></pre>
273 17 Kyle Knoepfel
274 1 Christopher Green
# Remap and flatten a set of containers of @Ptrs@ (including @PtrVector@) which may be obtained from a component of the provided product. Provide the name of a member function of the provided product which is an accessor for the container (taking no arguments).<pre><code class="cplusplus">remap(in, out, offsets, &A::myBs);</code></pre>
275 1 Christopher Green
# Remap and flatten a set of containers of @Ptrs@ (including @PtrVector@) which may be obtained from a component of the provided product. Provide the name of a member datum of the provided product which is the container.<pre><code class="cplusplus">remap(in, out, offsets, &A::myBs);</code></pre>
276 5 Christopher Green
# Remap and flatten a set of containers of @Ptrs@ (including @PtrVector@) which is a component of the provided product using the provided accessor member function of a class which is not the product.<pre><code class="cplusplus">class Aprocessor {
277 5 Christopher Green
public:
278 17 Kyle Knoepfel
  B const& myBs(A const*);
279 1 Christopher Green
};
280 1 Christopher Green
281 6 Christopher Green
Aprocessor myAp;
282 6 Christopher Green
283 17 Kyle Knoepfel
remap(in, out, offsets, Aprocessor::myBs, myAp);</code></pre>Note: if the compiler complains about an unresolved overload set for this signature, try an explicit:
284 17 Kyle Knoepfel
285 17 Kyle Knoepfel
<pre><code class="cplusplus">
286 17 Kyle Knoepfel
const_cast<Aprocessor&>(myAp);
287 17 Kyle Knoepfel
</code></pre>
288 17 Kyle Knoepfel
289 17 Kyle Knoepfel
# Remap and flatten a set of containers of @Ptrs@ (including @PtrVector@) which is a component of the provided product using the provided @const@ accessor member function of a class which is not the product.
290 17 Kyle Knoepfel
291 17 Kyle Knoepfel
<pre><code class="cplusplus">
292 17 Kyle Knoepfel
class Aprocessor {
293 10 Walter E Brown
public:
294 17 Kyle Knoepfel
  B const& myBs(A const*) const;
295 6 Christopher Green
};
296 6 Christopher Green
297 6 Christopher Green
Aprocessor myAp;
298 6 Christopher Green
299 17 Kyle Knoepfel
remap(in, out, offsets, Aprocessor::myBs, myAp);
300 17 Kyle Knoepfel
</code></pre>
301 17 Kyle Knoepfel
302 17 Kyle Knoepfel
Note: if the compiler complains about an unresolved overload set for this signature, try an explicit:
303 17 Kyle Knoepfel
304 17 Kyle Knoepfel
<pre><code class="cplusplus">
305 17 Kyle Knoepfel
const_cast<Aprocessor const&>(myAp);
306 17 Kyle Knoepfel
</code></pre>
307 17 Kyle Knoepfel
308 17 Kyle Knoepfel
# More general version of 5-9 that takes a final argument which is of arbitrary type provided it or its @operator()@ has the correct signature. The drawback is that one of the template arguments (@CONT@, specifying the type of the collection of Ptrs you wish to remap) is not deducible, meaning that instead of:
309 17 Kyle Knoepfel
310 17 Kyle Knoepfel
<pre><code class="cplusplus">
311 17 Kyle Knoepfel
remap(...);
312 17 Kyle Knoepfel
</code></pre>
313 17 Kyle Knoepfel
314 17 Kyle Knoepfel
one must type, for example:
315 17 Kyle Knoepfel
316 17 Kyle Knoepfel
<pre><code class="cplusplus">
317 17 Kyle Knoepfel
remap.operator()<std::vector<art::Ptr<B>>>(...)
318 17 Kyle Knoepfel
</code></pre>
319 17 Kyle Knoepfel
320 17 Kyle Knoepfel
Therefore, 4-9 are the recommended signatures for straightforward client code -- this one is provided for maximum flexibility and for use internally by signatures 5-9.
321 7 Christopher Green
322 16 Kyle Knoepfel
h2. Examples.
323 16 Kyle Knoepfel
324 1 Christopher Green
* art:source:art/test/Integration/MixFilterTest_module.cc
325 1 Christopher Green
* mu2eofflinesoftwaremu2eoffline:source:EventMixing/src/MixMCEvents_module.cc