IsoSpec  2.2.1
cwrapper.cpp
1 /*
2  * Copyright (C) 2015-2020 Mateusz Łącki and Michał Startek.
3  *
4  * This file is part of IsoSpec.
5  *
6  * IsoSpec is free software: you can redistribute it and/or modify
7  * it under the terms of the Simplified ("2-clause") BSD licence.
8  *
9  * IsoSpec is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12  *
13  * You should have received a copy of the Simplified BSD Licence
14  * along with IsoSpec. If not, see <https://opensource.org/licenses/BSD-2-Clause>.
15  */
16 
17 
18 #include <cstring>
19 #include <algorithm>
20 #include <utility>
21 #include <stdexcept>
22 #include "cwrapper.h"
23 #include "misc.h"
24 #include "marginalTrek++.h"
25 #include "isoSpec++.h"
26 #include "fixedEnvelopes.h"
27 #include "fasta.h"
28 
29 using namespace IsoSpec; // NOLINT(build/namespaces) - all of this really should be in a namespace IsoSpec, but C doesn't have them...
30 
31 
32 extern "C"
33 {
34 void * setupIso(int dimNumber,
35  const int* isotopeNumbers,
36  const int* atomCounts,
37  const double* isotopeMasses,
38  const double* isotopeProbabilities)
39 {
40  Iso* iso = new Iso(dimNumber, isotopeNumbers, atomCounts, isotopeMasses, isotopeProbabilities);
41 
42  return reinterpret_cast<void*>(iso);
43 }
44 
45 void * isoFromFasta(const char* fasta, bool use_nominal_masses, bool add_water)
46 {
47  Iso* iso = new Iso(Iso::FromFASTA(fasta, use_nominal_masses, add_water));
48 
49  return reinterpret_cast<void*>(iso);
50 }
51 
52 void deleteIso(void* iso)
53 {
54  delete reinterpret_cast<Iso*>(iso);
55 }
56 
57 double getLightestPeakMassIso(void* iso)
58 {
59  return reinterpret_cast<Iso*>(iso)->getLightestPeakMass();
60 }
61 
62 double getHeaviestPeakMassIso(void* iso)
63 {
64  return reinterpret_cast<Iso*>(iso)->getHeaviestPeakMass();
65 }
66 
67 double getMonoisotopicPeakMassIso(void* iso)
68 {
69  return reinterpret_cast<Iso*>(iso)->getMonoisotopicPeakMass();
70 }
71 
72 double getModeLProbIso(void* iso)
73 {
74  return reinterpret_cast<Iso*>(iso)->getModeLProb();
75 }
76 
77 double getModeMassIso(void* iso)
78 {
79  return reinterpret_cast<Iso*>(iso)->getModeMass();
80 }
81 
82 double getTheoreticalAverageMassIso(void* iso)
83 {
84  return reinterpret_cast<Iso*>(iso)->getTheoreticalAverageMass();
85 }
86 
87 double getIsoVariance(void* iso)
88 {
89  return reinterpret_cast<Iso*>(iso)->variance();
90 }
91 
92 double getIsoStddev(void* iso)
93 {
94  return reinterpret_cast<Iso*>(iso)->stddev();
95 }
96 
97 
98 double* getMarginalLogSizeEstimates(void* iso, double target_total_prob)
99 {
100  Iso* i = reinterpret_cast<Iso*>(iso);
101  double* ret = reinterpret_cast<double*>(malloc(sizeof(double)*i->getDimNumber()));
102  if(ret != nullptr)
103  i->saveMarginalLogSizeEstimates(ret, target_total_prob);
104  return ret;
105 }
106 
107 
108 
109 #define ISOSPEC_C_FN_CODE(generatorType, dataType, method)\
110 dataType method##generatorType(void* generator){ return reinterpret_cast<generatorType*>(generator)->method(); }
111 
112 #define ISOSPEC_C_FN_CODE_GET_CONF_SIGNATURE(generatorType)\
113 void get_conf_signature##generatorType(void* generator, int* space)\
114 { reinterpret_cast<generatorType*>(generator)->get_conf_signature(space); }
115 
116 
117 #define ISOSPEC_C_FN_DELETE(generatorType) void delete##generatorType(void* generator){ delete reinterpret_cast<generatorType*>(generator); }
118 
119 #define ISOSPEC_C_FN_CODES(generatorType)\
120 ISOSPEC_C_FN_CODE(generatorType, double, mass) \
121 ISOSPEC_C_FN_CODE(generatorType, double, lprob) \
122 ISOSPEC_C_FN_CODE(generatorType, double, prob) \
123 ISOSPEC_C_FN_CODE_GET_CONF_SIGNATURE(generatorType) \
124 ISOSPEC_C_FN_CODE(generatorType, bool, advanceToNextConfiguration) \
125 ISOSPEC_C_FN_DELETE(generatorType)
126 
127 
128 
129 // ______________________________________________________THRESHOLD GENERATOR
130 void* setupIsoThresholdGenerator(void* iso,
131  double threshold,
132  bool _absolute,
133  int _tabSize,
134  int _hashSize,
135  bool reorder_marginals)
136 {
138  std::move(*reinterpret_cast<Iso*>(iso)),
139  threshold,
140  _absolute,
141  _tabSize,
142  _hashSize,
143  reorder_marginals);
144 
145  return reinterpret_cast<void*>(iso_tmp);
146 }
147 ISOSPEC_C_FN_CODES(IsoThresholdGenerator)
148 
149 
150 // ______________________________________________________LAYERED GENERATOR
151 void* setupIsoLayeredGenerator(void* iso,
152  int _tabSize,
153  int _hashSize,
154  bool reorder_marginals,
155  double t_prob_hint
156  )
157 {
159  std::move(*reinterpret_cast<Iso*>(iso)),
160  _tabSize,
161  _hashSize,
162  reorder_marginals,
163  t_prob_hint
164  );
165 
166  return reinterpret_cast<void*>(iso_tmp);
167 }
168 ISOSPEC_C_FN_CODES(IsoLayeredGenerator)
169 
170 
171 // ______________________________________________________ORDERED GENERATOR
172 void* setupIsoOrderedGenerator(void* iso,
173  int _tabSize,
174  int _hashSize)
175 {
177  std::move(*reinterpret_cast<Iso*>(iso)),
178  _tabSize,
179  _hashSize);
180 
181  return reinterpret_cast<void*>(iso_tmp);
182 }
183 ISOSPEC_C_FN_CODES(IsoOrderedGenerator)
184 
185 // ______________________________________________________STOCHASTIC GENERATOR
186 void* setupIsoStochasticGenerator(void* iso,
187  size_t no_molecules,
188  double precision,
189  double beta_bias)
190 {
192  std::move(*reinterpret_cast<Iso*>(iso)),
193  no_molecules,
194  precision,
195  beta_bias);
196 
197  return reinterpret_cast<void*>(iso_tmp);
198 }
199 ISOSPEC_C_FN_CODES(IsoStochasticGenerator)
200 
201 // ______________________________________________________ FixedEnvelopes
202 
203 void* setupThresholdFixedEnvelope(void* iso,
204  double threshold,
205  bool absolute,
206  bool get_confs)
207 {
208  FixedEnvelope* ret = new FixedEnvelope( // Use copy elision to allocate on heap with named constructor
209  FixedEnvelope::FromThreshold(Iso(*reinterpret_cast<const Iso*>(iso), true),
210  threshold,
211  absolute,
212  get_confs));
213 
214  return reinterpret_cast<void*>(ret);
215 }
216 
217 void* setupTotalProbFixedEnvelope(void* iso,
218  double target_coverage,
219  bool optimize,
220  bool get_confs)
221 {
222  FixedEnvelope* ret = new FixedEnvelope( // Use copy elision to allocate on heap with named constructor
223  FixedEnvelope::FromTotalProb(Iso(*reinterpret_cast<const Iso*>(iso), true),
224  target_coverage,
225  optimize,
226  get_confs));
227 
228  return reinterpret_cast<void*>(ret);
229 }
230 
231 void* setupStochasticFixedEnvelope(void* iso,
232  size_t no_molecules,
233  double precision,
234  double beta_bias,
235  bool get_confs)
236 {
237  FixedEnvelope* ret = new FixedEnvelope( // Use copy elision to allocate on heap with named constructor
238  FixedEnvelope::FromStochastic(Iso(*reinterpret_cast<const Iso*>(iso), true),
239  no_molecules,
240  precision,
241  beta_bias,
242  get_confs));
243 
244  return reinterpret_cast<void*>(ret);
245 }
246 
247 
248 void* setupBinnedFixedEnvelope(void* iso,
249  double target_total_prob,
250  double bin_width,
251  double bin_middle)
252 {
253  FixedEnvelope* ret = new FixedEnvelope( // Use copy elision to allocate on heap with named constructor
254  FixedEnvelope::Binned(Iso(*reinterpret_cast<const Iso*>(iso), true),
255  target_total_prob,
256  bin_width,
257  bin_middle));
258 
259  return reinterpret_cast<void*>(ret);
260 }
261 
262 void* setupFixedEnvelope(double* masses, double* probs, size_t size, bool mass_sorted, bool prob_sorted, double total_prob)
263 {
264  FixedEnvelope* ret = new FixedEnvelope(masses, probs, size, mass_sorted, prob_sorted, total_prob);
265  return reinterpret_cast<void*>(ret);
266 }
267 
268 void deleteFixedEnvelope(void* t, bool release_everything)
269 {
270  FixedEnvelope* tt = reinterpret_cast<FixedEnvelope*>(t);
271  if(release_everything)
272  {
273  tt->release_masses();
274  tt->release_probs();
275  tt->release_confs();
276  }
277  delete tt;
278 }
279 
280 void* copyFixedEnvelope(void* other)
281 {
282  FixedEnvelope* ret = new FixedEnvelope(*reinterpret_cast<FixedEnvelope*>(other));
283  return reinterpret_cast<void*>(ret);
284 }
285 
286 const double* massesFixedEnvelope(void* tabulator)
287 {
288  return reinterpret_cast<FixedEnvelope*>(tabulator)->release_masses();
289 }
290 
291 const double* probsFixedEnvelope(void* tabulator)
292 {
293  return reinterpret_cast<FixedEnvelope*>(tabulator)->release_probs();
294 }
295 
296 const int* confsFixedEnvelope(void* tabulator)
297 {
298  return reinterpret_cast<FixedEnvelope*>(tabulator)->release_confs();
299 }
300 
301 size_t confs_noFixedEnvelope(void* tabulator)
302 {
303  return reinterpret_cast<FixedEnvelope*>(tabulator)->confs_no();
304 }
305 
306 double empiricAverageMass(void* tabulator)
307 {
308  return reinterpret_cast<FixedEnvelope*>(tabulator)->empiric_average_mass();
309 }
310 
311 double empiricVariance(void* tabulator)
312 {
313  return reinterpret_cast<FixedEnvelope*>(tabulator)->empiric_variance();
314 }
315 
316 double empiricStddev(void* tabulator)
317 {
318  return reinterpret_cast<FixedEnvelope*>(tabulator)->empiric_stddev();
319 }
320 
321 double wassersteinDistance(void* tabulator1, void* tabulator2)
322 {
323  try
324  {
325  return reinterpret_cast<FixedEnvelope*>(tabulator1)->WassersteinDistance(*reinterpret_cast<FixedEnvelope*>(tabulator2));
326  }
327  catch(std::logic_error&)
328  {
329  return NAN;
330  }
331 }
332 
333 double orientedWassersteinDistance(void* tabulator1, void* tabulator2)
334 {
335  try
336  {
337  return reinterpret_cast<FixedEnvelope*>(tabulator1)->OrientedWassersteinDistance(*reinterpret_cast<FixedEnvelope*>(tabulator2));
338  }
339  catch(std::logic_error&)
340  {
341  return NAN;
342  }
343 }
344 
345 double abyssalWassersteinDistance(void* tabulator1, void* tabulator2, double abyss_depth, double other_scale)
346 {
347  return reinterpret_cast<FixedEnvelope*>(tabulator1)->AbyssalWassersteinDistance(*reinterpret_cast<FixedEnvelope*>(tabulator2), abyss_depth, other_scale);
348 }
349 
350 #if 0
351 double abyssalWassersteinDistanceGrad(void* const* envelopes, const double* scales, double* ret_gradient, size_t N, double abyss_depth_exp, double abyss_depth_the)
352 {
353  return AbyssalWassersteinDistanceGrad(reinterpret_cast<FixedEnvelope* const*>(envelopes), scales, ret_gradient, N, abyss_depth_exp, abyss_depth_the);
354 }
355 #endif
356 
357 struct ws_match_res wassersteinMatch(void* tabulator1, void* tabulator2, double flow_dist, double other_scale)
358 {
359  struct ws_match_res res;
360  auto [t1, t2, t3] = reinterpret_cast<FixedEnvelope*>(tabulator1)->WassersteinMatch(*reinterpret_cast<FixedEnvelope*>(tabulator2), flow_dist, other_scale);
361  res.res1 = t1;
362  res.res2 = t2;
363  res.flow = t3;
364  return res;
365 }
366 
367 void* addEnvelopes(void* tabulator1, void* tabulator2)
368 {
369  // Hopefully the compiler will do the copy elision...
370  return reinterpret_cast<void*>(new FixedEnvelope((*reinterpret_cast<FixedEnvelope*>(tabulator1))+(*reinterpret_cast<FixedEnvelope*>(tabulator2))));
371 }
372 
373 void* convolveEnvelopes(void* tabulator1, void* tabulator2)
374 {
375  // Hopefully the compiler will do the copy elision...
376  return reinterpret_cast<void*>(new FixedEnvelope((*reinterpret_cast<FixedEnvelope*>(tabulator1))*(*reinterpret_cast<FixedEnvelope*>(tabulator2))));
377 }
378 
379 double getTotalProbOfEnvelope(void* envelope)
380 {
381  return reinterpret_cast<FixedEnvelope*>(envelope)->get_total_prob();
382 }
383 
384 void scaleEnvelope(void* envelope, double factor)
385 {
386  reinterpret_cast<FixedEnvelope*>(envelope)->scale(factor);
387 }
388 
389 void normalizeEnvelope(void* envelope)
390 {
391  reinterpret_cast<FixedEnvelope*>(envelope)->normalize();
392 }
393 
394 void shiftMassEnvelope(void* envelope, double d_mass)
395 {
396  reinterpret_cast<FixedEnvelope*>(envelope)->shift_mass(d_mass);
397 }
398 
399 void resampleEnvelope(void* envelope, size_t ionic_current, double beta_bias)
400 {
401  reinterpret_cast<FixedEnvelope*>(envelope)->resample(ionic_current, beta_bias);
402 }
403 
404 
405 void* binnedEnvelope(void* envelope, double width, double middle)
406 {
407  // Again, counting on copy elision...
408  return reinterpret_cast<void*>(new FixedEnvelope(reinterpret_cast<FixedEnvelope*>(envelope)->bin(width, middle)));
409 }
410 
411 void* linearCombination(void* const * const envelopes, const double* intensities, size_t count)
412 {
413  // Same...
414  return reinterpret_cast<void*>(new FixedEnvelope(FixedEnvelope::LinearCombination(reinterpret_cast<const FixedEnvelope* const *>(envelopes), intensities, count)));
415 }
416 
417 void sortEnvelopeByMass(void* envelope)
418 {
419  reinterpret_cast<FixedEnvelope*>(envelope)->sort_by_mass();
420 }
421 
422 void sortEnvelopeByProb(void* envelope)
423 {
424  reinterpret_cast<FixedEnvelope*>(envelope)->sort_by_prob();
425 }
426 
427 void freeReleasedArray(void* array)
428 {
429  free(array);
430 }
431 
432 void array_add(double* array, size_t N, double what)
433 {
434  for(size_t ii = 0; ii < N; ii++)
435  array[ii] += what;
436 }
437 
438 void array_mul(double* array, size_t N, double what)
439 {
440  for(size_t ii = 0; ii < N; ii++)
441  array[ii] *= what;
442 }
443 
444 void array_fma(double* array, size_t N, double mul, double add)
445 {
446  for(size_t ii = 0; ii < N; ii++)
447 #if defined(FP_FAST_FMA)
448  array[ii] = std::fma(array[ii], mul, add);
449 #else
450  array[ii] += (array[ii] * mul) + add;
451 #endif
452 }
453 
454 void parse_fasta_c(const char* fasta, int atomCounts[6])
455 {
456  // Same thing, only this time with C linkage
457  parse_fasta(fasta, atomCounts);
458 }
459 } // extern "C" ends here
The Iso class for the calculation of the isotopic distribution.
Definition: isoSpec++.h:49
void saveMarginalLogSizeEstimates(double *priorities, double target_total_prob) const
Save estimates of logarithms of target sizes of marginals using Gaussian approximation into argument ...
Definition: isoSpec++.cpp:335
int getDimNumber() const
Get the number of elements in the chemical formula of the molecule.
Definition: isoSpec++.h:166
static Iso FromFASTA(const char *fasta, bool use_nominal_masses=false, bool add_water=true)
Constructor (named) from aminoacid FASTA sequence as C string.
Definition: isoSpec++.cpp:169
The generator of isotopologues sorted by their probability of occurrence.
Definition: isoSpec++.h:237
The generator of isotopologues above a given threshold value.
Definition: isoSpec++.h:296