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
29using namespace IsoSpec; // NOLINT(build/namespaces) - all of this really should be in a namespace IsoSpec, but C doesn't have them...
30
31
32extern "C"
33{
34void * 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
45void * 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
52void deleteIso(void* iso)
53{
54 delete reinterpret_cast<Iso*>(iso);
55}
56
57double getLightestPeakMassIso(void* iso)
58{
59 return reinterpret_cast<Iso*>(iso)->getLightestPeakMass();
60}
61
62double getHeaviestPeakMassIso(void* iso)
63{
64 return reinterpret_cast<Iso*>(iso)->getHeaviestPeakMass();
65}
66
67double getMonoisotopicPeakMassIso(void* iso)
68{
69 return reinterpret_cast<Iso*>(iso)->getMonoisotopicPeakMass();
70}
71
72double getModeLProbIso(void* iso)
73{
74 return reinterpret_cast<Iso*>(iso)->getModeLProb();
75}
76
77double getModeMassIso(void* iso)
78{
79 return reinterpret_cast<Iso*>(iso)->getModeMass();
80}
81
82double getTheoreticalAverageMassIso(void* iso)
83{
84 return reinterpret_cast<Iso*>(iso)->getTheoreticalAverageMass();
85}
86
87double getIsoVariance(void* iso)
88{
89 return reinterpret_cast<Iso*>(iso)->variance();
90}
91
92double getIsoStddev(void* iso)
93{
94 return reinterpret_cast<Iso*>(iso)->stddev();
95}
96
97
98double* 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)\
110dataType method##generatorType(void* generator){ return reinterpret_cast<generatorType*>(generator)->method(); }
111
112#define ISOSPEC_C_FN_CODE_GET_CONF_SIGNATURE(generatorType)\
113void 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)\
120ISOSPEC_C_FN_CODE(generatorType, double, mass) \
121ISOSPEC_C_FN_CODE(generatorType, double, lprob) \
122ISOSPEC_C_FN_CODE(generatorType, double, prob) \
123ISOSPEC_C_FN_CODE_GET_CONF_SIGNATURE(generatorType) \
124ISOSPEC_C_FN_CODE(generatorType, bool, advanceToNextConfiguration) \
125ISOSPEC_C_FN_DELETE(generatorType)
126
127
128
129// ______________________________________________________THRESHOLD GENERATOR
130void* 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}
147ISOSPEC_C_FN_CODES(IsoThresholdGenerator)
148
149
150// ______________________________________________________LAYERED GENERATOR
151void* 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}
168ISOSPEC_C_FN_CODES(IsoLayeredGenerator)
169
170
171// ______________________________________________________ORDERED GENERATOR
172void* 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}
183ISOSPEC_C_FN_CODES(IsoOrderedGenerator)
184
185// ______________________________________________________STOCHASTIC GENERATOR
186void* 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}
199ISOSPEC_C_FN_CODES(IsoStochasticGenerator)
200
201// ______________________________________________________ FixedEnvelopes
202
203void* 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
217void* 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
231void* 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
248void* 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
262void* 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
268void 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
280void* copyFixedEnvelope(void* other)
281{
282 FixedEnvelope* ret = new FixedEnvelope(*reinterpret_cast<FixedEnvelope*>(other));
283 return reinterpret_cast<void*>(ret);
284}
285
286const double* massesFixedEnvelope(void* tabulator)
287{
288 return reinterpret_cast<FixedEnvelope*>(tabulator)->release_masses();
289}
290
291const double* probsFixedEnvelope(void* tabulator)
292{
293 return reinterpret_cast<FixedEnvelope*>(tabulator)->release_probs();
294}
295
296const int* confsFixedEnvelope(void* tabulator)
297{
298 return reinterpret_cast<FixedEnvelope*>(tabulator)->release_confs();
299}
300
301size_t confs_noFixedEnvelope(void* tabulator)
302{
303 return reinterpret_cast<FixedEnvelope*>(tabulator)->confs_no();
304}
305
306double empiricAverageMass(void* tabulator)
307{
308 return reinterpret_cast<FixedEnvelope*>(tabulator)->empiric_average_mass();
309}
310
311double empiricVariance(void* tabulator)
312{
313 return reinterpret_cast<FixedEnvelope*>(tabulator)->empiric_variance();
314}
315
316double empiricStddev(void* tabulator)
317{
318 return reinterpret_cast<FixedEnvelope*>(tabulator)->empiric_stddev();
319}
320
321double 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
333double 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
345double 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
351double 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
357struct 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
367void* 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
373void* 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
379double getTotalProbOfEnvelope(void* envelope)
380{
381 return reinterpret_cast<FixedEnvelope*>(envelope)->get_total_prob();
382}
383
384void scaleEnvelope(void* envelope, double factor)
385{
386 reinterpret_cast<FixedEnvelope*>(envelope)->scale(factor);
387}
388
389void normalizeEnvelope(void* envelope)
390{
391 reinterpret_cast<FixedEnvelope*>(envelope)->normalize();
392}
393
394void shiftMassEnvelope(void* envelope, double d_mass)
395{
396 reinterpret_cast<FixedEnvelope*>(envelope)->shift_mass(d_mass);
397}
398
399void resampleEnvelope(void* envelope, size_t ionic_current, double beta_bias)
400{
401 reinterpret_cast<FixedEnvelope*>(envelope)->resample(ionic_current, beta_bias);
402}
403
404
405void* 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
411void* 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
417void sortEnvelopeByMass(void* envelope)
418{
419 reinterpret_cast<FixedEnvelope*>(envelope)->sort_by_mass();
420}
421
422void sortEnvelopeByProb(void* envelope)
423{
424 reinterpret_cast<FixedEnvelope*>(envelope)->sort_by_prob();
425}
426
427void freeReleasedArray(void* array)
428{
429 free(array);
430}
431
432void 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
438void 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
444void 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
454void 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
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