IsoSpecPy 2.5.0__py3-none-win_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. IsoSpecPy/Advanced.py +32 -0
  2. IsoSpecPy/Distributions.py +93 -0
  3. IsoSpecPy/Formulas.py +71 -0
  4. IsoSpecPy/IsoSpec++/aligned_ptr.h +638 -0
  5. IsoSpecPy/IsoSpec++/allocator.h +69 -0
  6. IsoSpecPy/IsoSpec++/btrd.h +206 -0
  7. IsoSpecPy/IsoSpec++/composition.h +126 -0
  8. IsoSpecPy/IsoSpec++/conf.h +38 -0
  9. IsoSpecPy/IsoSpec++/cwrapper.h +271 -0
  10. IsoSpecPy/IsoSpec++/dirtyAllocator.h +58 -0
  11. IsoSpecPy/IsoSpec++/element_lookup.h +36 -0
  12. IsoSpecPy/IsoSpec++/element_tables.h +50 -0
  13. IsoSpecPy/IsoSpec++/fasta.h +70 -0
  14. IsoSpecPy/IsoSpec++/fasta_mods.h +70 -0
  15. IsoSpecPy/IsoSpec++/fixedEnvelopes.h +418 -0
  16. IsoSpecPy/IsoSpec++/isa_kernel_impl.h +192 -0
  17. IsoSpecPy/IsoSpec++/isa_kernels.h +172 -0
  18. IsoSpecPy/IsoSpec++/isoMath.h +121 -0
  19. IsoSpecPy/IsoSpec++/isoSpec++.h +801 -0
  20. IsoSpecPy/IsoSpec++/iso_simd.h +48 -0
  21. IsoSpecPy/IsoSpec++/marginalTrek++.h +614 -0
  22. IsoSpecPy/IsoSpec++/misc.h +229 -0
  23. IsoSpecPy/IsoSpec++/mman.h +67 -0
  24. IsoSpecPy/IsoSpec++/operators.h +150 -0
  25. IsoSpecPy/IsoSpec++/platform.h +180 -0
  26. IsoSpecPy/IsoSpec++/platform_incl.h +33 -0
  27. IsoSpecPy/IsoSpec++/pod_vector.h +400 -0
  28. IsoSpecPy/IsoSpec++/summator.h +118 -0
  29. IsoSpecPy/IsoSpec++/unimod.h +80 -0
  30. IsoSpecPy/IsoSpec++/unimod_support.h +2169 -0
  31. IsoSpecPy/IsoSpec++/unimod_table_data.h +1027 -0
  32. IsoSpecPy/IsoSpecPy.py +1088 -0
  33. IsoSpecPy/IsoSpecPyOld.py +290 -0
  34. IsoSpecPy/PeriodicTbl.py +51 -0
  35. IsoSpecPy/__init__.py +19 -0
  36. IsoSpecPy/__main__.py +25 -0
  37. IsoSpecPy/approximations.py +122 -0
  38. IsoSpecPy/confs_passthrough.py +16 -0
  39. IsoSpecPy/isoFFI.py +290 -0
  40. bin/IsoSpecCppPy.dll +0 -0
  41. isospecpy-2.5.0.dist-info/METADATA +220 -0
  42. isospecpy-2.5.0.dist-info/RECORD +45 -0
  43. isospecpy-2.5.0.dist-info/WHEEL +5 -0
  44. isospecpy-2.5.0.dist-info/licenses/LICENCE +35 -0
  45. lib/IsoSpecCppPy.lib +0 -0
IsoSpecPy/isoFFI.py ADDED
@@ -0,0 +1,290 @@
1
+ import cffi
2
+ import platform
3
+ from pathlib import Path
4
+
5
+
6
+ class IsoFFI:
7
+ def __init__(self):
8
+ self.ffi = cffi.FFI()
9
+ self.ffi.cdef(
10
+ """
11
+ void * setupIso(int dimNumber,
12
+ const int* isotopeNumbers,
13
+ const int* atomCounts,
14
+ const double* isotopeMasses,
15
+ const double* isotopeProbabilities);
16
+
17
+ void * isoFromFasta(const char* fasta, bool use_nominal_masses, bool add_water);
18
+
19
+ double getLightestPeakMassIso(void* iso);
20
+ double getLightestPeakLProbIso(void* iso);
21
+ void getLightestPeakSignature(void* iso, int* space);
22
+ double getHeaviestPeakMassIso(void* iso);
23
+ double getHeaviestPeakLProbIso(void* iso);
24
+ void getHeaviestPeakSignature(void* iso, int* space);
25
+ double getMonoisotopicPeakMassIso(void* iso);
26
+ double getMonoisotopicPeakLProbIso(void* iso);
27
+ void getMonoisotopicPeakSignature(void* iso, int* space);
28
+ double getModeLProbIso(void* iso);
29
+ double getModeMassIso(void* iso);
30
+ double getTheoreticalAverageMassIso(void* iso);
31
+ double getIsoVariance(void* iso);
32
+ double getIsoStddev(void* iso);
33
+ double* getMarginalLogSizeEstimates(void* iso, double target_total_prob);
34
+
35
+ void deleteIso(void* iso);
36
+
37
+ void* setupIsoThresholdGenerator(void* iso,
38
+ double threshold,
39
+ bool _absolute,
40
+ int _tabSize,
41
+ int _hashSize,
42
+ bool reorder_marginals);
43
+ double massIsoThresholdGenerator(void* generator);
44
+ double lprobIsoThresholdGenerator(void* generator);
45
+ double probIsoThresholdGenerator(void* generator);
46
+ bool advanceToNextConfigurationIsoThresholdGenerator(void* generator);
47
+ void deleteIsoThresholdGenerator(void* generator);
48
+ void get_conf_signatureIsoThresholdGenerator(void* generator, int* space);
49
+
50
+
51
+
52
+ void* setupIsoLayeredGenerator(void* iso,
53
+ int _tabSize,
54
+ int _hashSize,
55
+ bool reorder_marginals,
56
+ double t_prob_hint);
57
+ double massIsoLayeredGenerator(void* generator);
58
+ double lprobIsoLayeredGenerator(void* generator);
59
+ double probIsoLayeredGenerator(void* generator);
60
+ bool advanceToNextConfigurationIsoLayeredGenerator(void* generator);
61
+ void deleteIsoLayeredGenerator(void* generator);
62
+ void get_conf_signatureIsoLayeredGenerator(void* generator, int* space);
63
+
64
+
65
+ void* setupIsoOrderedGenerator(void* iso,
66
+ int _tabSize,
67
+ int _hashSize);
68
+ double massIsoOrderedGenerator(void* generator);
69
+ double lprobIsoOrderedGenerator(void* generator);
70
+ double probIsoOrderedGenerator(void* generator);
71
+ bool advanceToNextConfigurationIsoOrderedGenerator(void* generator);
72
+ void deleteIsoOrderedGenerator(void* generator);
73
+ void get_conf_signatureIsoOrderedGenerator(void* generator, int* space);
74
+
75
+ void* setupIsoStochasticGenerator(void* iso,
76
+ size_t no_molecules,
77
+ double precision,
78
+ double beta_bias);
79
+ double massIsoStochasticGenerator(void* generator);
80
+ double lprobIsoStochasticGenerator(void* generator);
81
+ double probIsoStochasticGenerator(void* generator);
82
+ bool advanceToNextConfigurationIsoStochasticGenerator(void* generator);
83
+ void deleteIsoStochasticGenerator(void* generator);
84
+ void get_conf_signatureIsoStochasticGenerator(void* generator, int* space);
85
+
86
+ void* setupThresholdFixedEnvelope(void* iso,
87
+ double threshold,
88
+ bool absolute,
89
+ bool get_confs);
90
+
91
+ void* setupTotalProbFixedEnvelope(void* iso,
92
+ double taget_coverage,
93
+ bool optimize,
94
+ bool get_confs);
95
+
96
+ void* setupStochasticFixedEnvelope(void* iso,
97
+ size_t no_molecules,
98
+ double precision,
99
+ double beta_bias,
100
+ bool get_confs);
101
+
102
+ void* setupBinnedFixedEnvelope(void* iso,
103
+ double target_total_prob,
104
+ double bin_width,
105
+ double bin_middle);
106
+
107
+ void* setupFixedEnvelope(double* masses, double* probs, size_t size, bool mass_sorted, bool prob_sorted, double total_prob);
108
+ void* setupFixedEnvelopeWithConfs(double* masses, double* probs, int* confs, size_t size, int allDim, bool mass_sorted, bool prob_sorted, double total_prob);
109
+ void* copyFixedEnvelope(void* other);
110
+ void deleteFixedEnvelope(void* tabulator, bool releaseEverything);
111
+
112
+ const double* massesFixedEnvelope(void* tabulator);
113
+ const double* probsFixedEnvelope(void* tabulator);
114
+ const int* confsFixedEnvelope(void* tabulator);
115
+ size_t confs_noFixedEnvelope(void* tabulator);
116
+
117
+ typedef void (*IsoSpecArrayDeleter)(void* array, size_t size);
118
+
119
+ double* massesFixedEnvelopeWithDeleter(void* tabulator, size_t* size_out, IsoSpecArrayDeleter* deleter_out);
120
+ double* probsFixedEnvelopeWithDeleter(void* tabulator, size_t* size_out, IsoSpecArrayDeleter* deleter_out);
121
+ int* confsFixedEnvelopeWithDeleter(void* tabulator, size_t* size_out, IsoSpecArrayDeleter* deleter_out);
122
+ void freeReleasedArrayWithDeleter(void* array, size_t size, IsoSpecArrayDeleter deleter);
123
+
124
+ double empiricAverageMass(void* tabulator);
125
+ double empiricVariance(void* tabulator);
126
+ double empiricStddev(void* tabulator);
127
+
128
+ double wassersteinDistance(void* tabulator1, void* tabulator2);
129
+ double orientedWassersteinDistance(void* tabulator1, void* tabulator2);
130
+ double abyssalWassersteinDistance(void* tabulator1, void* tabulator2, double abyss_depth, double other_scale);
131
+ // double abyssalWassersteinDistanceGrad(void* const* envelopes, const double* scales, double* ret_gradient, size_t N, double abyss_depth_exp, double abyss_depth_the);
132
+
133
+ struct ws_match_res{
134
+ double res1;
135
+ double res2;
136
+ double flow;
137
+ };
138
+
139
+ struct ws_match_res wassersteinMatch(void* tabulator1, void* tabulator2, double flow_dist, double other_scale);
140
+
141
+ void* addEnvelopes(void* tabulator1, void* tabulator2);
142
+ void* convolveEnvelopes(void* tabulator1, void* tabulator2);
143
+
144
+ double getTotalProbOfEnvelope(void* envelope);
145
+ void scaleEnvelope(void* envelope, double factor);
146
+ void normalizeEnvelope(void* envelope);
147
+ void shiftMassEnvelope(void* envelope, double d_mass);
148
+ void resampleEnvelope(void* envelope, size_t ionic_current, double beta_bias);
149
+ void* binnedEnvelope(void* envelope, double width, double middle);
150
+ void* linearCombination(void* const * const envelopes, const double* intensities, size_t count);
151
+
152
+ void sortEnvelopeByMass(void* envelope);
153
+ void sortEnvelopeByProb(void* envelope);
154
+
155
+ void freeReleasedArray(void* array);
156
+ void array_add(double* array, size_t N, double what);
157
+ void array_mul(double* array, size_t N, double what);
158
+ void array_fma(double* array, size_t N, double mul, double add);
159
+
160
+ void parse_fasta_c(const char* fasta, int atomCounts[6]);
161
+
162
+ void* isoFromFastaWithMods(const char* sequence, bool use_nominal_masses, bool add_water, const char* unimod_db_path);
163
+ void* parseFastaWithModsC(const char* sequence, const char* unimod_db_path);
164
+ size_t compositionSizeC(void* composition);
165
+ const char* const* compositionSymbolsC(void* composition);
166
+ const int* compositionCountsC(void* composition);
167
+ void deleteCompositionC(void* composition);
168
+
169
+ void* expandCompositionC(const char* const* symbols, const int* counts, size_t size, bool use_nominal_masses);
170
+ const int* expandedIsotopeNumbersC(void* expanded);
171
+ const int* expandedAtomCountsC(void* expanded);
172
+ const double* expandedIsotopeMassesC(void* expanded);
173
+ const double* expandedIsotopeProbabilitiesC(void* expanded);
174
+ void deleteExpandedCompositionC(void* expanded);
175
+
176
+ const char* activeSimdLevel(void);
177
+
178
+ // Must be kept in sync by hand with ISOSPEC_NUMBER_OF_ISOTOPIC_ENTRIES
179
+ // in element_tables.h -- see PeriodicTbl.py's comment on why this
180
+ // can't be read from isospec_number_of_isotopic_entries (the real
181
+ // compiled variable, right below) instead: cffi's dlopen ABI mode
182
+ // can't access plain extern const globals, only #define constants
183
+ // like this one. A stale value here silently drops table entries in
184
+ // Python without erroring (already happened once, #51/deuterium).
185
+ #define NUMBER_OF_ISOTOPIC_ENTRIES 293
186
+ extern const size_t isospec_number_of_isotopic_entries;
187
+ extern const int elem_table_atomicNo[NUMBER_OF_ISOTOPIC_ENTRIES];
188
+ extern const double elem_table_probability[NUMBER_OF_ISOTOPIC_ENTRIES];
189
+ extern const double elem_table_mass[NUMBER_OF_ISOTOPIC_ENTRIES];
190
+ extern const double elem_table_massNo[NUMBER_OF_ISOTOPIC_ENTRIES];
191
+ extern const int elem_table_extraNeutrons[NUMBER_OF_ISOTOPIC_ENTRIES];
192
+ extern const char* elem_table_element[NUMBER_OF_ISOTOPIC_ENTRIES];
193
+ extern const char* elem_table_symbol[NUMBER_OF_ISOTOPIC_ENTRIES];
194
+ extern const bool elem_table_Radioactive[NUMBER_OF_ISOTOPIC_ENTRIES];
195
+ """
196
+ )
197
+
198
+ mod_dir = Path(__file__).resolve().parent
199
+
200
+ libnames = ["IsoSpecCppPy*", "IsoSpec++*"]
201
+ libprefix = ["", "lib", "Lib"]
202
+ extension = [".so", ".dylib", ".dll"]
203
+ try:
204
+ if platform.system() == "Linux":
205
+ extension = [".so", ".pyd"]
206
+ elif platform.system() == "Windows":
207
+ extension = [".dll", ".pyd"]
208
+ except:
209
+ pass
210
+
211
+ prebuilt = ["", "prebuilt-"]
212
+
213
+ def cprod(ll1, ll2):
214
+ res = []
215
+ for l1 in ll1:
216
+ for l2 in ll2:
217
+ res.append(l1 + l2)
218
+ return res
219
+
220
+ paths_to_check = cprod(prebuilt, cprod(libprefix, cprod(libnames, extension)))
221
+ dpc = []
222
+
223
+ search_dirs = [
224
+ mod_dir,
225
+ mod_dir.parent,
226
+ mod_dir.parent / "bin",
227
+ mod_dir.parent / "lib",
228
+ ]
229
+
230
+ # Editable installs (scikit-build-core) redirect this module's
231
+ # __file__ to the source tree, but build the compiled extension
232
+ # straight into the installed package's own site-packages
233
+ # directory instead -- mod_dir above never sees it. Search that
234
+ # directory too, when it isn't already mod_dir.
235
+ try:
236
+ import importlib.util
237
+
238
+ installed_pkg = importlib.util.find_spec("IsoSpecPy")
239
+ for loc in installed_pkg.submodule_search_locations or []:
240
+ loc = Path(loc)
241
+ if loc not in search_dirs:
242
+ search_dirs.append(loc)
243
+ except (ImportError, AttributeError, ValueError):
244
+ pass
245
+
246
+ for dirpath in search_dirs:
247
+ dpc.extend([dirpath / p for p in paths_to_check])
248
+
249
+ paths_to_check = dpc
250
+ # expand glob patterns using pathlib (keep only actual matches, like glob.glob did)
251
+ expanded = []
252
+ for p in paths_to_check:
253
+ expanded.extend(p.parent.glob(p.name))
254
+ paths_to_check = expanded
255
+ try:
256
+ import importlib
257
+
258
+ paths_to_check.insert(
259
+ 0, Path(importlib.util.find_spec("IsoSpecCppPy").origin)
260
+ )
261
+ except (ImportError, AttributeError):
262
+ pass
263
+
264
+ errors = []
265
+
266
+ self.clib = None
267
+ for libpath in set(paths_to_check):
268
+ try:
269
+ self.clib = self.ffi.dlopen(str(libpath))
270
+ self.libpath = libpath
271
+ break
272
+ except (IndexError, OSError) as e:
273
+ errmsg = (
274
+ "Load libIsoSpec++.so, tried: "
275
+ + str(libpath)
276
+ + "\n"
277
+ + "Got error: "
278
+ + str(type(e))
279
+ + ": "
280
+ + str(e)
281
+ )
282
+ errors.append(errmsg)
283
+
284
+ if self.clib == None:
285
+ raise ImportError(
286
+ "Cannot find or load the C++ part of the library\n" + "\n".join(errors)
287
+ )
288
+
289
+
290
+ isoFFI = IsoFFI() # This is done while including the module
bin/IsoSpecCppPy.dll ADDED
Binary file
@@ -0,0 +1,220 @@
1
+ Metadata-Version: 2.4
2
+ Name: IsoSpecPy
3
+ Version: 2.5.0
4
+ Summary: IsoSpecPy is a Python library for computing isotopic distributions of molecules.
5
+ Keywords: isotopic distribution,mass spectrometry,chemistry,isotopic envelope,isotopologues
6
+ Author: Michał Startek, Mateusz Łącki
7
+ License-Expression: BSD-2-Clause
8
+ License-File: LICENCE
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.9
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: Programming Language :: Python :: 3.14
16
+ Classifier: Programming Language :: Python :: 3.15
17
+ Classifier: Programming Language :: Python :: Implementation :: CPython
18
+ Classifier: Programming Language :: Python :: Implementation :: PyPy
19
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
20
+ Classifier: Development Status :: 5 - Production/Stable
21
+ Classifier: Operating System :: OS Independent
22
+ Project-URL: Homepage, https://github.com/MatteoLacki/IsoSpec
23
+ Project-URL: Repository, https://github.com/MatteoLacki/IsoSpec
24
+ Requires-Python: >=3.9
25
+ Requires-Dist: cffi
26
+ Provides-Extra: testing
27
+ Requires-Dist: pytest; extra == "testing"
28
+ Requires-Dist: OldIsoSpecPy; extra == "testing"
29
+ Description-Content-Type: text/markdown
30
+
31
+ # IsoSpec
32
+
33
+ IsoSpec is a fine-structure isotopic distribution calculator for chemical formulas — given a molecule, it computes the masses and probabilities of its isotopologues. It is fast enough to handle large molecules (proteins, oligonucleotides) where the full distribution has astronomically many configurations, and it returns provably-optimal subsets that cover a chosen fraction of the total probability mass.
34
+
35
+ IsoSpec is primarily used as a library by mass spectrometry software. It is implemented in C++ (`src/IsoSpec++/`) and shipped with first-class bindings for Python (`IsoSpecPy`, on PyPI) and R (`IsoSpecR`, on CRAN).
36
+
37
+ ## Installation
38
+
39
+ ### Python
40
+
41
+ ```bash
42
+ pip install IsoSpecPy
43
+ ```
44
+
45
+ The wheel bundles the C++ library — no separate native install required. Compatible with CPython and PyPy on Linux, macOS, Windows, and Cygwin/MinGW. Python ≥ 3.9.
46
+
47
+ To build from source: `pip install .` from a checkout. A C++20 compiler is required.
48
+
49
+ ### R
50
+
51
+ ```r
52
+ install.packages("IsoSpecR")
53
+ ```
54
+
55
+ From source: `cd src && R CMD build IsoSpecR && R CMD INSTALL IsoSpecR_*.tar.gz`.
56
+
57
+ ### C++ library
58
+
59
+ ```bash
60
+ cd src/IsoSpec++
61
+ make # produces libIsoSpec++.so
62
+ ```
63
+
64
+ Or via CMake from the repo root:
65
+
66
+ ```bash
67
+ cmake -B build -DCMAKE_BUILD_TYPE=Release
68
+ cmake --build build
69
+ sudo cmake --install build
70
+ ```
71
+
72
+ Requires a C++20 compiler. CMake produces both shared and static libraries and installs headers under `${CMAKE_INSTALL_INCLUDEDIR}/IsoSpec++`.
73
+
74
+ ## Quick start
75
+
76
+ The most common usage is `IsoTotalProb`: ask for the smallest set of isotopologues whose summed probability covers a chosen fraction of the spectrum (typically 0.99–0.9999). The result is a materialized envelope — arrays of masses and probabilities you can read directly.
77
+
78
+ ### Python
79
+
80
+ ```python
81
+ import IsoSpecPy
82
+
83
+ # Isotopologues covering at least 99.9% of the probability mass of water.
84
+ iso = IsoSpecPy.IsoTotalProb(formula="H2O1", prob_to_cover=0.999)
85
+
86
+ for mass, prob in zip(iso.masses, iso.probs):
87
+ print(mass, prob)
88
+
89
+ # From an amino-acid sequence:
90
+ iso = IsoSpecPy.IsoTotalProb(peptide_sequence="AAAPPGQAAC", prob_to_cover=0.999)
91
+ print(list(zip(iso.masses, iso.probs)))
92
+
93
+ # ...optionally carrying [UNIMOD:<id>] modification tags (the notation this
94
+ # monorepo's SAGE search-engine fork writes: [UNIMOD:<id>]-SEQUENCE prefix
95
+ # for an N-terminal mod, X[UNIMOD:<id>] inline for an internal one,
96
+ # SEQUENCE-[UNIMOD:<id>] suffix for a C-terminal one):
97
+ iso = IsoSpecPy.IsoTotalProb(peptide_sequence="PEPTC[UNIMOD:4]DEK", prob_to_cover=0.999)
98
+ print(list(zip(iso.masses, iso.probs)))
99
+
100
+ # Mind the water: peptide_sequence= yields the *residue* composition, without
101
+ # the terminal H2O of a free peptide, so the masses above are 18.0106 Da
102
+ # lighter than the neutral molecule. Add it explicitly for the real peptide
103
+ # (the C++ Iso::FromFASTAWithMods below adds it by default -- the two APIs
104
+ # differ here, and this is the older Python behaviour kept for compatibility):
105
+ iso = IsoSpecPy.IsoTotalProb(peptide_sequence="PEPTC[UNIMOD:4]DEK", formula="H2O1",
106
+ prob_to_cover=0.999)
107
+
108
+ # Or get just the composition (element -> atom count), no envelope:
109
+ composition = IsoSpecPy.ParsePeptideSequence("PEPTC[UNIMOD:4]DEK")
110
+ print(dict(composition)) # {'H': 60, 'C': 39, 'N': 10, 'O': 16, 'S': 1}
111
+ ```
112
+
113
+ Resolves against a table of ~980 Unimod entries embedded in the library (isotope-labelled and glycan/derivatization "brick" modifications are excluded -- they aren't representable as a pure elemental delta). Pass `unimod_db_path="/path/to/table.csv"` to either function to resolve against a different table instead (same `id,name,mono_mass,composition` CSV shape as the embedded default).
114
+
115
+ See `Examples/Python/` for radiolabelling, custom elements, binned spectra, and FASTA/Unimod modifications.
116
+
117
+ ### C++
118
+
119
+ ```cpp
120
+ #include "IsoSpec++/isoSpec++.h"
121
+ #include "IsoSpec++/fixedEnvelopes.h"
122
+
123
+ using namespace IsoSpec;
124
+
125
+ int main() {
126
+ FixedEnvelope iso = FixedEnvelope::FromTotalProb("H2O1", 0.999, true, true);
127
+
128
+ for (size_t i = 0; i < iso.confs_no(); ++i) {
129
+ std::cout << iso.mass(i) << '\t' << iso.prob(i) << '\n';
130
+ }
131
+ }
132
+ ```
133
+
134
+ From a peptide sequence, optionally carrying `[UNIMOD:<id>]` modification tags (`fasta_mods.h`; same notation as the Python/R examples above):
135
+
136
+ ```cpp
137
+ #include "IsoSpec++/isoSpec++.h"
138
+ #include "IsoSpec++/fasta_mods.h"
139
+ #include "IsoSpec++/fixedEnvelopes.h"
140
+
141
+ using namespace IsoSpec;
142
+
143
+ int main() {
144
+ FixedEnvelope iso = FixedEnvelope::FromTotalProb(
145
+ Iso::FromFASTAWithMods("PEPTC[UNIMOD:4]DEK"), 0.999, true, true);
146
+
147
+ for (size_t i = 0; i < iso.confs_no(); ++i) {
148
+ std::cout << iso.mass(i) << '\t' << iso.prob(i) << '\n';
149
+ }
150
+ }
151
+ ```
152
+
153
+ `Iso::FromFASTAWithMods` takes an optional trailing `unimod_db_path` argument to resolve against a different Unimod table instead of the one embedded at compile time. For just the composition, no envelope, call `parse_fasta_with_mods`/`parse_fasta_with_mods_full` directly (or the allocation-free `_into` forms, for a hot loop over many sequences) — see `fasta_mods.h`.
154
+
155
+ Quickest way to build:
156
+
157
+ ```bash
158
+ clang++ -std=c++20 water.cpp src/IsoSpec++/unity-build.cpp -o water
159
+ ```
160
+
161
+ (`unity-build.cpp` is a single translation unit that `#include`s every source file — see `Examples/C++/COMPILING`.)
162
+
163
+ ### R
164
+
165
+ ```r
166
+ library(IsoSpecR)
167
+ water <- c(H = 2, O = 1)
168
+ IsoSpecify(molecule = water, stopCondition = 0.999)
169
+ ```
170
+
171
+ `IsoSpecify` only ever takes a raw named-integer-vector `molecule` -- it has no sequence-string parameter -- so a `[UNIMOD:<id>]`-annotated peptide sequence takes two calls instead of one: `RParsePeptideSequence()` to resolve the sequence into a composition, then `IsoSpecify()` as above.
172
+
173
+ ```r
174
+ composition <- RParsePeptideSequence("PEPTC[UNIMOD:4]DEK")
175
+ print(composition) # H C N O S
176
+ # 60 39 10 16 1
177
+ IsoSpecify(molecule = composition, stopCondition = 0.999)
178
+ ```
179
+
180
+ Like the Python `ParsePeptideSequence`, this returns the residue composition without a free peptide's terminal H2O -- add `c(H = 2, O = 1)` to it for the neutral molecule. A modification whose delta removes more atoms of an element than the bare sequence provides gives a negative count (`"G[UNIMOD:11]"` nets `H -1`, `S -1`); `IsoSpecify` rejects such a vector rather than quietly dropping those elements.
181
+
182
+ See `Examples/R/` for radiolabelling, full-spectrum extraction, and Unimod-annotated sequences.
183
+
184
+ ## Advanced features
185
+
186
+ - **Alternative algorithms** — for cases where `IsoTotalProb` isn't the right shape:
187
+ - `IsoThreshold` — all isotopologues with probability above a fixed threshold.
188
+ - `IsoStochastic` — simulate a measured spectrum by sampling integer ion counts.
189
+ - `IsoBinned` — histogram-style envelope at a chosen bin width.
190
+ - **FASTA/peptide-sequence support** — build an `Iso` directly from an amino-acid sequence, with `[UNIMOD:<id>]` modification tags recognized inline; optionally include the N/C-terminal water.
191
+ - **Custom isotopic tables** — override natural abundances per element (e.g. for radio- or stable-isotope labelling). See `Examples/*/radiolabelling.*`.
192
+ - **Fixed-envelope arithmetic** — addition, normalization, convolution, Wasserstein distance.
193
+ - **Nominal-mass mode** — compute distributions over nucleon counts instead of real masses.
194
+ - **Streaming generators (for performance)** — the tabulated functions above materialize the full envelope into arrays. For large molecules where that uses too much memory, or for pipelines that consume one configuration at a time (e.g. binning on the fly), use the generator classes instead: `IsoThresholdGenerator`, `IsoLayeredGenerator`, `IsoOrderedGenerator`, `IsoStochasticGenerator`. They yield one isotopologue per call to `advanceToNextConfiguration()` without ever storing the full set. `IsoOrderedGenerator` additionally streams in strict order of decreasing probability.
195
+
196
+ Algorithmic details are in the papers cited below; the Supporting Information of each is the better starting point for implementation specifics.
197
+
198
+ ## Repository layout
199
+
200
+ ```
201
+ src/IsoSpec++/ C++ core library (the algorithms live here)
202
+ src/IsoSpecPy/ Python binding, loaded via cffi
203
+ src/IsoSpecR/ R binding, via Rcpp
204
+ Examples/ Working examples in each language
205
+ tests/ C, C++, and Python test suites
206
+ skbuild/ scikit-build-core entry point used when installing the Python wheel
207
+ ```
208
+
209
+ ## Citation
210
+
211
+ If IsoSpec is useful in your research, please cite:
212
+
213
+ - Łącki, M. K.; Valkenborg, D.; Startek, M. P. *IsoSpec2: Ultrafast Fine Structure Calculator.* Analytical Chemistry **2020**, *92* (14), 9472–9475. <https://doi.org/10.1021/acs.analchem.0c00959>
214
+ - Łącki, M. K.; Startek, M.; Valkenborg, D.; Gambin, A. *IsoSpec: Hyperfast Fine Structure Calculator.* Analytical Chemistry **2017**, *89* (6), 3272–3277. <https://doi.org/10.1021/acs.analchem.6b01459>
215
+
216
+ The Supporting Information of each paper has the algorithmic detail.
217
+
218
+ ## License
219
+
220
+ 2-clause BSD (see `LICENCE`). If you need different licensing terms, contact the authors. The authors appreciate (but do not require) being told when IsoSpec is used in other software.
@@ -0,0 +1,45 @@
1
+ bin/IsoSpecCppPy.dll,sha256=XUfxu6zbvOIZ1eYki0tuP2fWiCXGoaXU5vaXr4GAQvc,262144
2
+ IsoSpecPy/__init__.py,sha256=Tjgv2E5pcPq4iSFiuZD4oJiOpqzaMuzkvzQVU843rrE,504
3
+ IsoSpecPy/__main__.py,sha256=Xr6SHPmCkpA3rPFbSBwxd2xl85eEKs6XDTLVWKZxcp4,1034
4
+ IsoSpecPy/Advanced.py,sha256=70LP-AOVr3lsfmCP_zivaXU0auhKWfgt6I8icbptxxg,1090
5
+ IsoSpecPy/approximations.py,sha256=e9kLSARQ-VMoXFayfyp8byrbVLxk6IFwoGz1iHXzKlI,4241
6
+ IsoSpecPy/confs_passthrough.py,sha256=Ythe_zSlI2Z69ajCCftubZSqLvHKz2kSRjF1Vc-pE6M,284
7
+ IsoSpecPy/Distributions.py,sha256=-GayrDO1bfs5EdPBMFf5K_b8QRgY-bqgg8qKH7P62fE,2582
8
+ IsoSpecPy/Formulas.py,sha256=blOy63xIfJcfR5WDYHNSCX3CMsdsOvVWpcAraKm67uE,1730
9
+ IsoSpecPy/isoFFI.py,sha256=HyWpphPVTHwM_yin3Cik3VCXHTp-KBNzGP4ucjgl4ZM,13350
10
+ IsoSpecPy/IsoSpec++/aligned_ptr.h,sha256=5Ul3I3Qkrwrb_V8cpguS50K1FQVro10PrwpvTZ9jlfs,23323
11
+ IsoSpecPy/IsoSpec++/allocator.h,sha256=dyWhQvpCZnDEby0YMyFbA_dVhYrKwMv8Pk4hLubYaLw,1662
12
+ IsoSpecPy/IsoSpec++/btrd.h,sha256=tPbQ6GZk1XpT9ESt4xEqL8TERKzbEnNRIKKGSq4nlNo,6226
13
+ IsoSpecPy/IsoSpec++/composition.h,sha256=sOE3Gf4iae9ky_A46UY2mWD0sBpLTuBCgxy8CrzQDWI,6078
14
+ IsoSpecPy/IsoSpec++/conf.h,sha256=N_dBUbO3RVO9LoSAvjRWtnrjVOqMbcKgbp5q9bJp93M,1008
15
+ IsoSpecPy/IsoSpec++/cwrapper.h,sha256=TMmCCRXn_dmSDc7MMIYX5F1la_0UqoOCDAxm0IVukqk,14525
16
+ IsoSpecPy/IsoSpec++/dirtyAllocator.h,sha256=aB1ebPacCfIPtGXmcxfCP7XJZpu7AuNQrsKlcOE48aI,1472
17
+ IsoSpecPy/IsoSpec++/element_lookup.h,sha256=uAGQJZlMVLFpCRJ6wzPuU3do6_W9niUrTq9A2UEW-fs,1394
18
+ IsoSpecPy/IsoSpec++/element_tables.h,sha256=Y8Okqc2_4ce7znXt9LArBR4JCaK0Wh_-Ih6Nh9YnLfE,1844
19
+ IsoSpecPy/IsoSpec++/fasta.h,sha256=OwJVrrsV6P6fFmhjohxwRJkazOJhJxP1Qc9FxB7bQIE,2325
20
+ IsoSpecPy/IsoSpec++/fasta_mods.h,sha256=pGBIp7ni3jzgOScMY9IiJnSlp4JSry0UEV1KG4P_hiU,3508
21
+ IsoSpecPy/IsoSpec++/fixedEnvelopes.h,sha256=_oTh3R0F9QXePOzqdnLmYzt_Qg9bW_DbfuhtEjD_4Uk,17639
22
+ IsoSpecPy/IsoSpec++/isa_kernel_impl.h,sha256=qKPfLZgYHgBfwQnHUplhMalsS595SPhXTsQhGGHcylA,7974
23
+ IsoSpecPy/IsoSpec++/isa_kernels.h,sha256=NPTB5NYBNY8mZ6fKVt-PtYiFhwXT4g6HVYoWQgw44UA,8753
24
+ IsoSpecPy/IsoSpec++/iso_simd.h,sha256=lkQ7wVZHp9XAMgW4FEIe1t3mWbctJKHueQPKdAX0_B4,2111
25
+ IsoSpecPy/IsoSpec++/isoMath.h,sha256=2tGDWvSruE-eJ2Kcnm0FUakcURYzCxiVdp7S7YepNLk,4275
26
+ IsoSpecPy/IsoSpec++/isoSpec++.h,sha256=weTRGJ8jY5ktTi_50KeJdQq3GXYrtQ4RtLvngRWBy78,36434
27
+ IsoSpecPy/IsoSpec++/marginalTrek++.h,sha256=82iOh5EVrQEjd3w09_oqvqvkwCOMt64o2QUN2JkRGO8,28321
28
+ IsoSpecPy/IsoSpec++/misc.h,sha256=zoBy5nhsZo0rdIQN4d1AbuGQdUQ-rywLJVV3FMcasC8,6100
29
+ IsoSpecPy/IsoSpec++/mman.h,sha256=RxwibELl7IRwWbn672Gg4-DeDGXXL6tFhM12kIMx5EE,1751
30
+ IsoSpecPy/IsoSpec++/operators.h,sha256=tD5hL-lPpLQ_LOEZMH61eenn-5L67Io-JJ8v7NovUpc,4131
31
+ IsoSpecPy/IsoSpec++/platform.h,sha256=gzaU4INxV7WQn7tbmFP2GuegdLnuIox-giHz5Wigimk,7092
32
+ IsoSpecPy/IsoSpec++/platform_incl.h,sha256=6MW4V759ZXdHaHtfH9o5nNmOXj2kCx8E_SiRO1mgBiM,966
33
+ IsoSpecPy/IsoSpec++/pod_vector.h,sha256=apnrfZS_4mNZ_xRoa6TmP1atyMC79HYG6ofeemt7_pk,11823
34
+ IsoSpecPy/IsoSpec++/summator.h,sha256=M-2IV9NU4PTWXIa3fq9Nz3StR9ZT22cZFH1utnmcf98,2425
35
+ IsoSpecPy/IsoSpec++/unimod.h,sha256=MOBn1HTHn4uLQRYwwH6w9Ow8xtDGchHAFayofiiiHxE,3368
36
+ IsoSpecPy/IsoSpec++/unimod_support.h,sha256=ESWUkCGzeA5ou9-2vGSMlNRBcMNIaxrdWLhmKftCxUk,122473
37
+ IsoSpecPy/IsoSpec++/unimod_table_data.h,sha256=LRlguv9E5dhRHRlBKwom4e7BEFpSRIEt_N4YcV2A3fY,37860
38
+ IsoSpecPy/IsoSpecPy.py,sha256=AG0DWfxBQYLyl7TgC5WI1AVjfPqQ0j1e0yKhQIvTveU,50472
39
+ IsoSpecPy/IsoSpecPyOld.py,sha256=6w1sZBhtyA87zGrAibsAvVDxKfqAZwbmYk_57x70GsI,11383
40
+ IsoSpecPy/PeriodicTbl.py,sha256=5EeB5zLJlBnWGodde-AevsCNrI0S1sgn9Nod1t1_xVs,2587
41
+ lib/IsoSpecCppPy.lib,sha256=S9UHc4qUqCVfgH0C3CVZklGo_NGasEruJGUpWEhn4eU,27540
42
+ isospecpy-2.5.0.dist-info/METADATA,sha256=81b8S8_GyeGmWCnqkbMMrvinLWgEzYZ5LSFpNPwvhKU,10480
43
+ isospecpy-2.5.0.dist-info/WHEEL,sha256=5341l7rLjEaIZp8mesTxb1JV3JsiKV2GLmJQcYtx6lg,102
44
+ isospecpy-2.5.0.dist-info/licenses/LICENCE,sha256=gfZw5llAwrHH4rkp5FJuq9VAuamp1x7x8MDmDjj8dpw,1705
45
+ isospecpy-2.5.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: scikit-build-core 1.1.0
3
+ Root-Is-Purelib: false
4
+ Tag: py3-none-win_arm64
5
+
@@ -0,0 +1,35 @@
1
+ IsoSpec is provided under the terms of 2-clause BSD licence.
2
+ If you require other licensing terms, please contact the authors.
3
+
4
+ We would appreciate if you let us know if you use this library in
5
+ your own software, but you are under no legal obligation to do so.
6
+
7
+
8
+ -------------------------------------------------------------------------
9
+
10
+
11
+ Copyright (c) 2015-2025, Michał Startek and Mateusz Łącki
12
+
13
+ All rights reserved.
14
+
15
+ Redistribution and use in source and binary forms, with or without
16
+ modification, are permitted provided that the following conditions are met:
17
+
18
+ 1. Redistributions of source code must retain the above copyright notice, this
19
+ list of conditions and the following disclaimer.
20
+ 2. Redistributions in binary form must reproduce the above copyright notice,
21
+ this list of conditions and the following disclaimer in the documentation
22
+ and/or other materials provided with the distribution.
23
+
24
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
25
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
28
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
+
35
+
lib/IsoSpecCppPy.lib ADDED
Binary file