ProteoWizard
diff_std.hpp
Go to the documentation of this file.
1//
2// $Id$
3//
4//
5// Original author: Robert Burke <robert.burke@proteowizard.org>
6//
7// Copyright 2009 Spielberg Family Center for Applied Proteomics
8// University of Southern California, Los Angeles, California 90033
9//
10// Licensed under the Apache License, Version 2.0 (the "License");
11// you may not use this file except in compliance with the License.
12// You may obtain a copy of the License at
13//
14// http://www.apache.org/licenses/LICENSE-2.0
15//
16// Unless required by applicable law or agreed to in writing, software
17// distributed under the License is distributed on an "AS IS" BASIS,
18// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19// See the License for the specific language governing permissions and
20// limitations under the License.
21//
22
23
24#ifndef _DIFF_STD_HPP_
25#define _DIFF_STD_HPP_
26
28#include <string>
29#include <vector>
30#include <cmath>
31#include <limits>
32#include <stdexcept>
33#include "ParamTypes.hpp"
34#include <boost/logic/tribool.hpp>
35
36
37namespace pwiz {
38namespace data {
39
40
42{
43 BaseDiffConfig(double _precision = 1e-6) : precision(_precision), partialDiffOK(false), ignoreVersions(false) {}
44 double precision;
45 bool partialDiffOK; // if true, can stop checking at first difference found
46 bool ignoreVersions; // if true, don't sweat version number mismatches
47};
48
49
50namespace diff_impl {
51
52
54void diff(const std::string& a,
55 const std::string& b,
56 std::string& a_b,
57 std::string& b_a,
58 const BaseDiffConfig& config);
59
60// special handling for strings which are likely
61// to differ only by a trailing version number
63void diff_ids(const std::string& a,
64 const std::string& b,
65 std::string& a_b,
66 std::string& b_a,
67 const BaseDiffConfig& config);
68
70void diff(const boost::logic::tribool& a,
71 const boost::logic::tribool& b,
72 boost::logic::tribool& a_b,
73 boost::logic::tribool& b_a,
74 const BaseDiffConfig& config);
75
77void diff(const CV& a,
78 const CV& b,
79 CV& a_b,
80 CV& b_a,
81 const BaseDiffConfig& config);
82
84void diff(CVID a,
85 CVID b,
86 CVID& a_b,
87 CVID& b_a,
88 const BaseDiffConfig& config);
89
91void diff(const CVParam& a,
92 const CVParam& b,
93 CVParam& a_b,
94 CVParam& b_a,
95 const BaseDiffConfig& config);
96
98void diff(const UserParam& a,
99 const UserParam& b,
100 UserParam& a_b,
101 UserParam& b_a,
102 const BaseDiffConfig& config);
103
105void diff(const ParamContainer& a,
106 const ParamContainer& b,
107 ParamContainer& a_b,
108 ParamContainer& b_a,
109 const BaseDiffConfig& config);
110
112void diff(const ParamGroup& a,
113 const ParamGroup& b,
114 ParamGroup& a_b,
115 ParamGroup& b_a,
116 const BaseDiffConfig& config);
117
118
119} // namespace diff_impl
120
121
122///
123/// Calculate diffs of objects in a ProteoWizard data model hierarchy.
124///
125/// A diff between two objects a and b calculates the set differences
126/// a\b and b\a.
127///
128/// The Diff struct acts as a functor, but also stores the
129/// results of the diff calculation.
130///
131/// The bool conversion operator is provided to indicate whether
132/// the two objects are different (either a\b or b\a is non-empty).
133///
134/// object_type requirements:
135/// object_type a;
136/// a.empty();
137/// pwiz::data::diff::diff(const object_type& a, const object_type& b, object_result_type& a_b, object_result_type& b_a);
138///
139/// config_type must be pwiz::data::diff::BaseDiffConfig or derived from it
140///
141template <typename object_type, typename config_type = BaseDiffConfig, typename object_result_type = object_type>
142struct Diff
143{
144 Diff(const config_type& config = config_type())
145 : config_(config)
146 {}
147
148 Diff(const object_type& a,
149 const object_type& b,
150 const config_type& config = config_type())
151 : config_(config)
152 {
154 }
155
156 object_result_type a_b;
157 object_result_type b_a;
158
159 /// conversion to bool, with same semantics as *nix diff command:
160 /// true == different
161 /// false == not different
162 operator bool() {return !(a_b.empty() && b_a.empty());}
163
164 Diff& operator()(const object_type& a,
165 const object_type& b)
166 {
168 return *this;
169 }
170
171 private:
172 config_type config_;
173};
174
175
176template <typename textwriter_type, typename diff_type>
177std::string diff_string(const diff_type& diff)
178{
179 std::ostringstream os;
180 textwriter_type write(os, 1);
181
182 if (!diff.a_b.empty())
183 {
184 os << "+\n";
185 write(diff.a_b);
186 }
187
188 if (!diff.b_a.empty())
189 {
190 os << "-\n";
191 write(diff.b_a);
192 }
193
194 return os.str();
195}
196
197
198/// stream insertion of Diff results
199template <typename textwriter_type, typename object_type, typename config_type>
200std::ostream& operator<<(std::ostream& os, const Diff<object_type, config_type>& diff)
201{
202 textwriter_type write(os, 1);
203
204 if (!diff.a_b.empty())
205 {
206 os << "+\n";
207 write(diff.a_b);
208 }
209
210 if (!diff.b_a.empty())
211 {
212 os << "-\n";
213 write(diff.b_a);
214 }
215
216 return os;
217}
218
219
220namespace diff_impl {
221
222
223template <typename string_type>
224void diff_string(const string_type& a,
225 const string_type& b,
226 string_type& a_b,
227 string_type& b_a)
228{
229 a_b.clear();
230 b_a.clear();
231
232 if (a != b)
233 {
234 a_b = a;
235 b_a = b;
236 }
237}
238
239
240template <typename char_type>
241void diff_char(const char_type& a,
242 const char_type& b,
243 char_type& a_b,
244 char_type& b_a)
245{
246 a_b = 0;
247 b_a = 0;
248
249 if (a != b)
250 {
251 a_b = a;
252 b_a = b;
253 }
254}
255
256
257template <typename integral_type>
258void diff_integral(const integral_type& a,
259 const integral_type& b,
260 integral_type& a_b,
261 integral_type& b_a,
262 const BaseDiffConfig& config)
263{
264 a_b = integral_type();
265 b_a = integral_type();
266
267 if (a != b)
268 {
269 a_b = static_cast<integral_type>(a);
270 b_a = static_cast<integral_type>(b);
271 }
272}
273
274
275template <typename floating_type>
276void diff_floating(const floating_type& a,
277 const floating_type& b,
278 floating_type& a_b,
279 floating_type& b_a,
280 const BaseDiffConfig& config)
281{
282 a_b = 0;
283 b_a = 0;
284
285 if (fabs(a - b) > config.precision + std::numeric_limits<floating_type>::epsilon())
286 {
287 a_b = fabs(a - b);
288 b_a = fabs(a - b);
289 }
290}
291
292
293/// measure maximum relative difference between elements in the vectors
294template <typename floating_type>
295floating_type maxdiff(const std::vector<floating_type>& a, const std::vector<floating_type>& b)
296{
297 if (a.size() != b.size())
298 throw std::runtime_error("[Diff::maxdiff()] Sizes differ.");
299
300 typename std::vector<floating_type>::const_iterator i = a.begin();
301 typename std::vector<floating_type>::const_iterator j = b.begin();
302
303 floating_type max = 0;
304
305 for (; i!=a.end(); ++i, ++j)
306 {
307 floating_type denominator = std::min(*i, *j);
308 if (denominator == 0) denominator = 1;
309 floating_type current = fabs(*i - *j)/denominator;
310 if (max < current) max = current;
311
312 }
313
314 return max;
315}
316
317
318template <typename object_type>
319void vector_diff(const std::vector<object_type>& a,
320 const std::vector<object_type>& b,
321 std::vector<object_type>& a_b,
322 std::vector<object_type>& b_a)
323{
324 // calculate set differences of two vectors
325
326 a_b.clear();
327 b_a.clear();
328
329 for (typename std::vector<object_type>::const_iterator it=a.begin(); it!=a.end(); ++it)
330 if (std::find(b.begin(), b.end(), *it) == b.end())
331 a_b.push_back(*it);
332
333 for (typename std::vector<object_type>::const_iterator it=b.begin(); it!=b.end(); ++it)
334 if (std::find(a.begin(), a.end(), *it) == a.end())
335 b_a.push_back(*it);
336}
337
338
339template <typename object_type>
340struct HasID
341{
342 const std::string& id_;
343 HasID(const std::string& id) : id_(id) {}
344 bool operator()(const boost::shared_ptr<object_type>& objectPtr) {return objectPtr->id == id_;}
345};
346
347
348template <typename object_type, typename config_type>
349class Same
350{
351 public:
352
353 Same(const object_type& object,
354 const config_type& config)
355 : mine_(object), config_(config)
356 {}
357
358 bool operator()(const object_type& yours)
359 {
360 // true iff yours is the same as mine
362 }
363
364 private:
365 const object_type& mine_;
366 const config_type& config_;
367};
368
369
370template <typename object_type, typename config_type>
371void vector_diff_diff(const std::vector<object_type>& a,
372 const std::vector<object_type>& b,
373 std::vector<object_type>& a_b,
374 std::vector<object_type>& b_a,
375 const config_type& config)
376{
377 // calculate set differences of two vectors, using diff on each object
378
379 a_b.clear();
380 b_a.clear();
381
382 for (typename std::vector<object_type>::const_iterator it=a.begin(); it!=a.end(); ++it)
383 if (std::find_if(b.begin(), b.end(), Same<object_type, config_type>(*it, config)) == b.end())
384 a_b.push_back(*it);
385
386 for (typename std::vector<object_type>::const_iterator it=b.begin(); it!=b.end(); ++it)
387 if (std::find_if(a.begin(), a.end(), Same<object_type, config_type>(*it, config)) == a.end())
388 b_a.push_back(*it);
389}
390
391
392template <typename object_type, typename config_type>
394{
395 public:
396
397 SameDeep(const object_type& object,
398 const config_type& config)
399 : mine_(object), config_(config)
400 {}
401
402 bool operator()(const boost::shared_ptr<object_type>& yours)
403 {
404 // true iff yours is the same as mine
406 }
407
408 private:
409 const object_type& mine_;
410 const config_type& config_;
411};
412
413
414template <typename object_type, typename config_type>
415void vector_diff_deep(const std::vector< boost::shared_ptr<object_type> >& a,
416 const std::vector< boost::shared_ptr<object_type> >& b,
417 std::vector< boost::shared_ptr<object_type> >& a_b,
418 std::vector< boost::shared_ptr<object_type> >& b_a,
419 const config_type& config)
420{
421 // calculate set differences of two vectors of ObjectPtrs (deep compare using diff)
422
423 a_b.clear();
424 b_a.clear();
425
426 config_type quick_config(config);
427 quick_config.partialDiffOK = true; // for fastest check in SameDeep
428
429 for (typename std::vector< boost::shared_ptr<object_type> >::const_iterator it=a.begin(); it!=a.end(); ++it)
430 if (std::find_if(b.begin(), b.end(), SameDeep<object_type, config_type>(**it, quick_config)) == b.end())
431 a_b.push_back(*it);
432
433 for (typename std::vector< boost::shared_ptr<object_type> >::const_iterator it=b.begin(); it!=b.end(); ++it)
434 if (std::find_if(a.begin(), a.end(), SameDeep<object_type, config_type>(**it, quick_config)) == a.end())
435 b_a.push_back(*it);
436}
437
438
439template <typename object_type, typename config_type>
440void ptr_diff(const boost::shared_ptr<object_type>& a,
441 const boost::shared_ptr<object_type>& b,
442 boost::shared_ptr<object_type>& a_b,
443 boost::shared_ptr<object_type>& b_a,
444 const config_type& config)
445{
446 if (!a.get() && !b.get()) return;
447
448 boost::shared_ptr<object_type> a_temp = a.get() ? a : boost::shared_ptr<object_type>(new object_type);
449 boost::shared_ptr<object_type> b_temp = b.get() ? b : boost::shared_ptr<object_type>(new object_type);
450
451 if (!a_b.get()) a_b = boost::shared_ptr<object_type>(new object_type);
452 if (!b_a.get()) b_a = boost::shared_ptr<object_type>(new object_type);
453 diff(*a_temp, *b_temp, *a_b, *b_a, config);
454
455 if (a_b->empty()) a_b = boost::shared_ptr<object_type>();
456 if (b_a->empty()) b_a = boost::shared_ptr<object_type>();
457}
458
459
460} // namespace diff_impl
461} // namespace data
462} // namespace pwiz
463
464
465#endif // _DIFF_STD_HPP_
#define PWIZ_API_DECL
Definition Export.hpp:32
void diff(const string &filename1, const string &filename2)
bool operator()(const boost::shared_ptr< object_type > &yours)
Definition diff_std.hpp:402
const object_type & mine_
Definition diff_std.hpp:409
const config_type & config_
Definition diff_std.hpp:410
SameDeep(const object_type &object, const config_type &config)
Definition diff_std.hpp:397
const config_type & config_
Definition diff_std.hpp:366
const object_type & mine_
Definition diff_std.hpp:365
Same(const object_type &object, const config_type &config)
Definition diff_std.hpp:353
bool operator()(const object_type &yours)
Definition diff_std.hpp:358
void vector_diff_deep(const std::vector< boost::shared_ptr< object_type > > &a, const std::vector< boost::shared_ptr< object_type > > &b, std::vector< boost::shared_ptr< object_type > > &a_b, std::vector< boost::shared_ptr< object_type > > &b_a, const config_type &config)
Definition diff_std.hpp:415
void diff_floating(const floating_type &a, const floating_type &b, floating_type &a_b, floating_type &b_a, const BaseDiffConfig &config)
Definition diff_std.hpp:276
void ptr_diff(const boost::shared_ptr< object_type > &a, const boost::shared_ptr< object_type > &b, boost::shared_ptr< object_type > &a_b, boost::shared_ptr< object_type > &b_a, const config_type &config)
Definition diff_std.hpp:440
PWIZ_API_DECL void diff_ids(const std::string &a, const std::string &b, std::string &a_b, std::string &b_a, const BaseDiffConfig &config)
void diff_char(const char_type &a, const char_type &b, char_type &a_b, char_type &b_a)
Definition diff_std.hpp:241
void vector_diff(const std::vector< object_type > &a, const std::vector< object_type > &b, std::vector< object_type > &a_b, std::vector< object_type > &b_a)
Definition diff_std.hpp:319
PWIZ_API_DECL void diff(const std::string &a, const std::string &b, std::string &a_b, std::string &b_a, const BaseDiffConfig &config)
void diff_integral(const integral_type &a, const integral_type &b, integral_type &a_b, integral_type &b_a, const BaseDiffConfig &config)
Definition diff_std.hpp:258
void vector_diff_diff(const std::vector< object_type > &a, const std::vector< object_type > &b, std::vector< object_type > &a_b, std::vector< object_type > &b_a, const config_type &config)
Definition diff_std.hpp:371
floating_type maxdiff(const std::vector< floating_type > &a, const std::vector< floating_type > &b)
measure maximum relative difference between elements in the vectors
Definition diff_std.hpp:295
std::string diff_string(const diff_type &diff)
Definition diff_std.hpp:177
std::ostream & operator<<(std::ostream &os, const Diff< object_type, config_type > &diff)
stream insertion of Diff results
Definition diff_std.hpp:200
Information about an ontology or CV source and a short 'lookup' tag to refer to.
Definition cv.hpp:14916
BaseDiffConfig(double _precision=1e-6)
Definition diff_std.hpp:43
represents a tag-value pair, where the tag comes from the controlled vocabulary
Calculate diffs of objects in a ProteoWizard data model hierarchy.
Definition diff_std.hpp:143
object_result_type a_b
Definition diff_std.hpp:156
Diff(const object_type &a, const object_type &b, const config_type &config=config_type())
Definition diff_std.hpp:148
config_type config_
Definition diff_std.hpp:172
Diff & operator()(const object_type &a, const object_type &b)
Definition diff_std.hpp:164
object_result_type b_a
Definition diff_std.hpp:157
Diff(const config_type &config=config_type())
Definition diff_std.hpp:144
The base class for elements that may contain cvParams, userParams, or paramGroup references.
A collection of CVParam and UserParam elements that can be referenced from elsewhere in this mzML doc...
Uncontrolled user parameters (essentially allowing free text). Before using these,...
HasID(const std::string &id)
Definition diff_std.hpp:343
bool operator()(const boost::shared_ptr< object_type > &objectPtr)
Definition diff_std.hpp:344
const std::string & id_
Definition diff_std.hpp:342