Note
Go to the end to download the full example code.
NMF analysis example
Import the spectrochempy API package
import spectrochempy as scp
Prepare the dataset to NMF factorize
Here we use a FTIR dataset corresponding the dehydration of a NH4Y zeolite and recorded in the OMNIC format.
dataset = scp.read_omnic("irdata/nh4y-activation.spg")
Mask some columns (features) which correspond to saturated parts of the spectra. Note that we use float number for defining the limits for masking as coordinates (integer numbers would mean point index and s would lead t incorrect results)
dataset[:, 882.0:1280.0] = scp.MASKED
Make sure all data are positive. For this we use the math functionalities of NDDataset
objects (min function to find the minimum value of the dataset
and the - operator for subtrating this value to all spectra of the dataset.
Plot it for a visual check
_ = dataset.plot()

Create a NMF object
As argument of the object constructor we define log_level to "INFO" to
obtain verbose output during fit, and we set the number of component to use at 4.
Fit the model
violation: 1.0
violation: 0.1401742102450195
violation: 0.06158195065493241
violation: 0.03477774452872513
violation: 0.02315591268977667
violation: 0.016289564836607293
violation: 0.01173219772280954
violation: 0.009261179153190089
violation: 0.0077705025299143575
violation: 0.006957471610159151
violation: 0.00645741437035502
violation: 0.0061911151252820725
violation: 0.006057238974457735
violation: 0.006000777806339385
violation: 0.005868357891308692
violation: 0.005802918028533996
violation: 0.005772367658829912
violation: 0.005756947971777792
violation: 0.005733332889918833
violation: 0.0057006066246449
violation: 0.005667827078790989
violation: 0.0055877366300482985
violation: 0.005529135183166999
violation: 0.005460760674075929
violation: 0.005375194673451687
violation: 0.0052880544420750705
violation: 0.005203284939611527
violation: 0.005110269931845185
violation: 0.0050049696133175675
violation: 0.0048894019445671535
violation: 0.004778610916794761
violation: 0.00465704070527272
violation: 0.004527642308383199
violation: 0.004393717477174965
violation: 0.004267124138925999
violation: 0.004133928133016198
violation: 0.004012755928138755
violation: 0.0038914653519267275
violation: 0.003765260270042897
violation: 0.003637514821862962
violation: 0.0035147101661543753
violation: 0.0033965138303582703
violation: 0.003292520557980681
violation: 0.0031941648132723503
violation: 0.0031049470293335116
violation: 0.003022167403550128
violation: 0.0029389646390339226
violation: 0.0028561158500454075
violation: 0.0027738912186805725
violation: 0.002692711668736959
violation: 0.002612954828908022
violation: 0.0025351644702121838
violation: 0.0024587403634379924
violation: 0.002384202690791081
violation: 0.002313303909478765
violation: 0.002243736743481113
violation: 0.0021751169925784872
violation: 0.0021084094490922516
violation: 0.002043667805247927
violation: 0.001980664359350578
violation: 0.0019243270194358323
violation: 0.001871326163205584
violation: 0.0018195678200698168
violation: 0.0017692749012870324
violation: 0.0017204657491193078
violation: 0.0016731692686996042
violation: 0.0016274950351471292
violation: 0.001583917332970034
violation: 0.0015418960309271576
violation: 0.001501438543131338
violation: 0.0014629272012161795
violation: 0.0014262081321621137
violation: 0.0013907597658087956
violation: 0.0013601582805158035
violation: 0.0013328464824006786
violation: 0.0013065923988234357
violation: 0.0012813357494811386
violation: 0.0012569657401119393
violation: 0.0012363658727395713
violation: 0.0012190114699550689
violation: 0.0011992116544501043
violation: 0.0011775622624513908
violation: 0.0011582609085414722
violation: 0.001138941592363273
violation: 0.001119912492935978
violation: 0.0011006754884538273
violation: 0.0010832777040278593
violation: 0.0010661363692303664
violation: 0.001049193369469965
violation: 0.0010318244102610174
violation: 0.0010150792321236151
violation: 0.0009988201809300113
violation: 0.0009841318528817362
violation: 0.0009699922960874142
violation: 0.0009545966012007311
violation: 0.0009396363331385092
violation: 0.0009266599168144965
violation: 0.0009140262172600162
violation: 0.0009015875006379092
violation: 0.0008902182357106498
violation: 0.0008780499311871812
violation: 0.000866045747092004
violation: 0.0008543517499941411
violation: 0.0008428706003287361
violation: 0.0008315536804370632
violation: 0.0008208847158799527
violation: 0.0008104269807766029
violation: 0.0007997522484733408
violation: 0.0007893350738953303
violation: 0.0007791326607914113
violation: 0.0007691414390018895
violation: 0.0007597179067851812
violation: 0.0007504652538891272
violation: 0.0007412456856970323
violation: 0.00073229661705407
violation: 0.0007235915691684942
violation: 0.0007151920055395829
violation: 0.0007069372346702277
violation: 0.0006987637535246623
violation: 0.0006907733550825587
violation: 0.0006830298779797132
violation: 0.0006754181243926209
violation: 0.0006679795936492443
violation: 0.0006606893398230935
violation: 0.0006536091296352644
violation: 0.0006466641120996083
violation: 0.0006399762615473376
violation: 0.0006335488650772302
violation: 0.0006273957420688322
violation: 0.0006215236000712568
violation: 0.0006161518203753597
violation: 0.0006113918151775875
violation: 0.0006071251736135659
violation: 0.000603093852087237
violation: 0.0005992255771887175
violation: 0.0005955122189367905
violation: 0.0005919356405963047
violation: 0.0005884735105285549
violation: 0.0005851626197890518
violation: 0.000581947296680294
violation: 0.0005788624242479325
violation: 0.000575908747959909
violation: 0.0005730546137307581
violation: 0.0005702968600985666
violation: 0.0005676053787183945
violation: 0.0005650176785170347
violation: 0.000562448058436888
violation: 0.0005599281471046676
violation: 0.0005574208102720205
violation: 0.000554993090751253
violation: 0.0005526263090686474
violation: 0.0005503237863509951
violation: 0.0005480875748008686
violation: 0.0005458976082894849
violation: 0.0005437570853967846
violation: 0.0005416726314726139
violation: 0.0005396329582219819
violation: 0.0005376381718608065
violation: 0.0005358628850809591
violation: 0.0005342566446344992
violation: 0.0005327134944356407
violation: 0.0005311700256181086
violation: 0.0005296374901747214
violation: 0.0005281469649346123
violation: 0.0005266549474164035
violation: 0.0005251860718896566
violation: 0.0005237318107590842
violation: 0.0005222955570666272
violation: 0.0005208942964236531
violation: 0.0005195265168843108
violation: 0.0005181813428111234
violation: 0.0005168846752735616
violation: 0.0005156608680270697
violation: 0.0005144616554312643
violation: 0.0005132891688190808
violation: 0.0005121515266403668
violation: 0.0005110364330891068
violation: 0.0005099447315065442
violation: 0.0005088753613794309
violation: 0.0005078236610581435
violation: 0.0005067909112021608
violation: 0.0005057740763562787
violation: 0.0005047767175619363
violation: 0.0005037958933647711
violation: 0.0005028222129278904
violation: 0.0005018650428479888
violation: 0.0005009224423798104
violation: 0.0004999974962486368
violation: 0.0004990872395198145
violation: 0.000498196200075019
violation: 0.000497314731819207
violation: 0.0004964417296739579
violation: 0.0004955753197883155
violation: 0.0004946901218458694
violation: 0.0004938210437304784
violation: 0.0004929673596843528
violation: 0.0004921226355844983
violation: 0.000491287120279602
violation: 0.0004904596528539429
violation: 0.0004896376456527903
/home/runner/work/spectrochempy/spectrochempy/.venv/lib/python3.13/site-packages/sklearn/decomposition/_nmf.py:1723: ConvergenceWarning: Maximum number of iterations 200 reached. Increase it to improve convergence.
warnings.warn(
Get the results
The concentration \(C\) and the transposed matrix of spectra \(S^T\) can be obtained as follow
C = model.transform()
St = model.components
violation: 1.0
violation: 0.2781188101128499
violation: 0.21103839273441857
violation: 0.16365897573754895
violation: 0.12638124502857273
violation: 0.09689398092858019
violation: 0.07386553913526493
violation: 0.057263048836391474
violation: 0.04639710696895098
violation: 0.0377627010107243
violation: 0.030324671559648426
violation: 0.02400007799856972
violation: 0.01870505431885551
violation: 0.014282427091628115
violation: 0.010676123451468626
violation: 0.008016534827385714
violation: 0.006238616114828234
violation: 0.005124394633030078
violation: 0.004490757479656516
violation: 0.0040531157511233
violation: 0.003744302603668796
violation: 0.0034289628116608278
violation: 0.003032319034755866
violation: 0.002727253739146701
violation: 0.0023865056940469845
violation: 0.0020851628627840194
violation: 0.0017697484695161577
violation: 0.0014925716272856744
violation: 0.0012488601974044316
violation: 0.0010438675111377092
violation: 0.0008573236692761815
violation: 0.0006991377766200158
violation: 0.0005706218431926882
violation: 0.0004636286240955465
violation: 0.0003748723547989588
violation: 0.00030325790844272624
violation: 0.00024636638593841575
violation: 0.00019825804790406476
violation: 0.00015827733519297642
violation: 0.00012439075792817193
violation: 9.611089606616343e-05
Converged at iteration 42
Plot results
_ = C.T.plot(title="Concentration", colormap=None, legend=C.k.labels)


This ends the example ! The following line can be uncommented if no plot shows when running the .py script with python
# scp.show()
Total running time of the script: (0 minutes 1.131 seconds)