IsoSpec 2.2.1
Loading...
Searching...
No Matches
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 ...
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.
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