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

plot nmf

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.

model = scp.NMF(n_components=4, log_level="INFO")

Fit the model

violation: 1.0
violation: 0.14017421024501978
violation: 0.06158195065493229
violation: 0.034777744528725035
violation: 0.023155912689776844
violation: 0.016289564836607213
violation: 0.011732197722809614
violation: 0.009261179153190293
violation: 0.007770502529914591
violation: 0.006957471610158982
violation: 0.006457414370355111
violation: 0.0061911151252819745
violation: 0.006057238974457616
violation: 0.006000777806339122
violation: 0.00586835789130873
violation: 0.005802918028534259
violation: 0.005772367658830108
violation: 0.005756947971777928
violation: 0.005733332889919082
violation: 0.005700606624644824
violation: 0.005667827078790745
violation: 0.00558773663004825
violation: 0.005529135183167155
violation: 0.005460760674075842
violation: 0.005375194673451704
violation: 0.005288054442075198
violation: 0.00520328493961163
violation: 0.005110269931845116
violation: 0.005004969613317512
violation: 0.0048894019445672975
violation: 0.004778610916794489
violation: 0.004657040705272632
violation: 0.004527642308383379
violation: 0.004393717477174929
violation: 0.0042671241389262305
violation: 0.00413392813301626
violation: 0.0040127559281390125
violation: 0.00389146535192658
violation: 0.003765260270042891
violation: 0.0036375148218630066
violation: 0.0035147101661545735
violation: 0.0033965138303583783
violation: 0.0032925205579804884
violation: 0.003194164813272194
violation: 0.0031049470293334634
violation: 0.003022167403549878
violation: 0.00293896463903368
violation: 0.0028561158500454054
violation: 0.0027738912186802997
violation: 0.002692711668737082
violation: 0.0026129548289077044
violation: 0.0025351644702120897
violation: 0.0024587403634383424
violation: 0.002384202690791125
violation: 0.0023133039094789787
violation: 0.002243736743481115
violation: 0.0021751169925786473
violation: 0.002108409449092292
violation: 0.002043667805247942
violation: 0.0019806643593508364
violation: 0.0019243270194361757
violation: 0.0018713261632057098
violation: 0.0018195678200699477
violation: 0.001769274901286767
violation: 0.0017204657491195366
violation: 0.0016731692686998611
violation: 0.001627495035146969
violation: 0.0015839173329698865
violation: 0.001541896030927202
violation: 0.0015014385431316869
violation: 0.0014629272012158052
violation: 0.0014262081321622367
violation: 0.0013907597658088685
violation: 0.0013601582805156753
violation: 0.0013328464824006738
violation: 0.001306592398823193
violation: 0.001281335749480946
violation: 0.0012569657401121923
violation: 0.0012363658727402777
violation: 0.001219011469955099
violation: 0.001199211654450386
violation: 0.0011775622624510213
violation: 0.0011582609085413079
violation: 0.0011389415923632213
violation: 0.0011199124929359933
violation: 0.0011006754884539728
violation: 0.0010832777040276627
violation: 0.0010661363692303714
violation: 0.001049193369469892
violation: 0.0010318244102607015
violation: 0.0010150792321238222
violation: 0.000998820180929954
violation: 0.0009841318528812748
violation: 0.0009699922960877311
violation: 0.0009545966012010385
violation: 0.0009396363331385346
violation: 0.0009266599168143468
violation: 0.0009140262172602871
violation: 0.0009015875006378824
violation: 0.0008902182357105174
violation: 0.0008780499311869399
violation: 0.0008660457470919526
violation: 0.0008543517499938388
violation: 0.0008428706003288063
violation: 0.0008315536804371233
violation: 0.0008208847158800381
violation: 0.0008104269807762881
violation: 0.0007997522484736462
violation: 0.0007893350738951732
violation: 0.0007791326607911395
violation: 0.0007691414390018927
violation: 0.0007597179067852407
violation: 0.0007504652538892435
violation: 0.0007412456856971567
violation: 0.000732296617053857
violation: 0.0007235915691681398
violation: 0.0007151920055396738
violation: 0.0007069372346704034
violation: 0.0006987637535246475
violation: 0.0006907733550823738
violation: 0.0006830298779798921
violation: 0.0006754181243924809
violation: 0.0006679795936491698
violation: 0.0006606893398229823
violation: 0.0006536091296349057
violation: 0.0006466641120997176
violation: 0.0006399762615476121
violation: 0.0006335488650772355
violation: 0.0006273957420687808
violation: 0.0006215236000710672
violation: 0.0006161518203755469
violation: 0.0006113918151773609
violation: 0.0006071251736134046
violation: 0.0006030938520870693
violation: 0.0005992255771889676
violation: 0.0005955122189370903
violation: 0.0005919356405960356
violation: 0.0005884735105281923
violation: 0.0005851626197891191
violation: 0.0005819472966807398
violation: 0.0005788624242482186
violation: 0.0005759087479599886
violation: 0.0005730546137309707
violation: 0.0005702968600985189
violation: 0.0005676053787185186
violation: 0.0005650176785172765
violation: 0.0005624480584368074
violation: 0.0005599281471042559
violation: 0.0005574208102720276
violation: 0.0005549930907514969
violation: 0.0005526263090688307
violation: 0.000550323786350852
violation: 0.0005480875748006177
violation: 0.0005458976082896053
violation: 0.0005437570853968881
violation: 0.0005416726314728367
violation: 0.0005396329582221692
violation: 0.000537638171860599
violation: 0.0005358628850808985
violation: 0.0005342566446343596
violation: 0.0005327134944357914
violation: 0.0005311700256180133
violation: 0.0005296374901745963
violation: 0.0005281469649348856
violation: 0.0005266549474164336
violation: 0.0005251860718894726
violation: 0.0005237318107591358
violation: 0.0005222955570669155
violation: 0.0005208942964238947
violation: 0.0005195265168845561
violation: 0.0005181813428115051
violation: 0.0005168846752739009
violation: 0.0005156608680270287
violation: 0.0005144616554313465
violation: 0.0005132891688187352
violation: 0.0005121515266406981
violation: 0.0005110364330892773
violation: 0.000509944731506295
violation: 0.0005088753613794317
violation: 0.0005078236610584979
violation: 0.0005067909112021982
violation: 0.0005057740763561168
violation: 0.0005047767175617049
violation: 0.000503795893364869
violation: 0.0005028222129276202
violation: 0.0005018650428479519
violation: 0.0005009224423800293
violation: 0.0004999974962488823
violation: 0.0004990872395195682
violation: 0.0004981962000749241
violation: 0.0004973147318191169
violation: 0.000496441729673478
violation: 0.0004955753197880594
violation: 0.0004946901218459929
violation: 0.0004938210437305216
violation: 0.0004929673596842007
violation: 0.0004921226355846851
violation: 0.000491287120279446
violation: 0.0004904596528539505
violation: 0.0004896376456529611
/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

violation: 1.0
violation: 0.27811881011285666
violation: 0.21103839273442318
violation: 0.16365897573755145
violation: 0.1263812450285739
violation: 0.09689398092858023
violation: 0.07386553913526434
violation: 0.05726304883639097
violation: 0.04639710696895057
violation: 0.03776270101072386
violation: 0.030324671559647957
violation: 0.024000077998569274
violation: 0.01870505431885501
violation: 0.01428242709162762
violation: 0.010676123451468397
violation: 0.008016534827385544
violation: 0.006238616114828094
violation: 0.005124394633030079
violation: 0.004490757479656583
violation: 0.004053115751123518
violation: 0.0037443026036689973
violation: 0.003428962811660944
violation: 0.0030323190347560313
violation: 0.0027272537391468165
violation: 0.002386505694047106
violation: 0.0020851628627840983
violation: 0.0017697484695162469
violation: 0.0014925716272857397
violation: 0.001248860197404511
violation: 0.0010438675111377495
violation: 0.0008573236692761995
violation: 0.0006991377766200677
violation: 0.0005706218431926921
violation: 0.00046362862409553453
violation: 0.0003748723547989979
violation: 0.00030325790844271073
violation: 0.00024636638593844394
violation: 0.0001982580479040781
violation: 0.00015827733519296251
violation: 0.00012439075792815735
violation: 9.611089606617966e-05
Converged at iteration 42

Plot results

_ = C.T.plot(title="Concentration", colormap=None, legend=C.k.labels)
Concentration
m = St.ptp()
for i in range(St.shape[0]):
    St.data[i] -= i * m / 2
ax = St.plot(title="Components", colormap=None, legend=St.k.labels)
_ = ax.set_yticks([])
Components

Uncomment the following line to display all figures when running the script directly with Python.

# scp.show()

Total running time of the script: (0 minutes 1.370 seconds)