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.14017421024502016
violation: 0.061581950654932424
violation: 0.03477774452872511
violation: 0.02315591268977678
violation: 0.016289564836607318
violation: 0.011732197722809765
violation: 0.009261179153190024
violation: 0.007770502529914423
violation: 0.006957471610159184
violation: 0.00645741437035492
violation: 0.00619111512528207
violation: 0.006057238974457781
violation: 0.006000777806339328
violation: 0.005868357891308759
violation: 0.00580291802853388
violation: 0.005772367658829859
violation: 0.005756947971778007
violation: 0.005733332889918984
violation: 0.005700606624644778
violation: 0.005667827078790921
violation: 0.005587736630048132
violation: 0.005529135183167
violation: 0.005460760674075795
violation: 0.005375194673451833
violation: 0.005288054442075181
violation: 0.005203284939611763
violation: 0.005110269931845264
violation: 0.0050049696133175475
violation: 0.0048894019445672445
violation: 0.004778610916794654
violation: 0.004657040705272598
violation: 0.004527642308383189
violation: 0.004393717477174867
violation: 0.004267124138925763
violation: 0.004133928133016254
violation: 0.0040127559281387705
violation: 0.0038914653519267735
violation: 0.0037652602700428447
violation: 0.0036375148218630157
violation: 0.0035147101661545314
violation: 0.003396513830358394
violation: 0.003292520557980597
violation: 0.003194164813272556
violation: 0.003104947029333446
violation: 0.003022167403549983
violation: 0.0029389646390339842
violation: 0.0028561158500457207
violation: 0.0027738912186801882
violation: 0.002692711668736865
violation: 0.0026129548289076034
violation: 0.002535164470211976
violation: 0.00245874036343812
violation: 0.0023842026907911844
violation: 0.00231330390947869
violation: 0.002243736743480978
violation: 0.002175116992578489
violation: 0.0021084094490923986
violation: 0.002043667805247647
violation: 0.0019806643593506955
violation: 0.0019243270194362822
violation: 0.0018713261632058397
violation: 0.0018195678200697788
violation: 0.001769274901286386
violation: 0.001720465749119218
violation: 0.0016731692686996584
violation: 0.001627495035146969
violation: 0.0015839173329701634
violation: 0.001541896030927267
violation: 0.001501438543131552
violation: 0.0014629272012162738
violation: 0.001426208132161849
violation: 0.001390759765809029
violation: 0.001360158280515679
violation: 0.001332846482400466
violation: 0.0013065923988234323
violation: 0.0012813357494813424
violation: 0.0012569657401119397
violation: 0.0012363658727397612
violation: 0.0012190114699552708
violation: 0.0011992116544500629
violation: 0.0011775622624511884
violation: 0.0011582609085415984
violation: 0.0011389415923632852
violation: 0.0011199124929364849
violation: 0.0011006754884538737
violation: 0.0010832777040279125
violation: 0.0010661363692302192
violation: 0.0010491933694700237
violation: 0.0010318244102608916
violation: 0.0010150792321238482
violation: 0.0009988201809299126
violation: 0.0009841318528815385
violation: 0.0009699922960877013
violation: 0.000954596601200467
violation: 0.0009396363331386363
violation: 0.0009266599168145299
violation: 0.0009140262172602445
violation: 0.0009015875006377918
violation: 0.0008902182357106372
violation: 0.0008780499311870002
violation: 0.000866045747091889
violation: 0.0008543517499935334
violation: 0.000842870600328805
violation: 0.0008315536804373527
violation: 0.000820884715879995
violation: 0.0008104269807765843
violation: 0.0007997522484735464
violation: 0.0007893350738950996
violation: 0.0007791326607915445
violation: 0.0007691414390015541
violation: 0.000759717906784928
violation: 0.0007504652538894929
violation: 0.0007412456856972268
violation: 0.0007322966170539278
violation: 0.0007235915691684959
violation: 0.0007151920055394405
violation: 0.0007069372346702184
violation: 0.0006987637535246147
violation: 0.0006907733550823892
violation: 0.000683029877979938
violation: 0.0006754181243926416
violation: 0.0006679795936492872
violation: 0.0006606893398229292
violation: 0.0006536091296354546
violation: 0.0006466641120994376
violation: 0.0006399762615476952
violation: 0.0006335488650773348
violation: 0.0006273957420689825
violation: 0.0006215236000710489
violation: 0.0006161518203753096
violation: 0.0006113918151773032
violation: 0.0006071251736135953
violation: 0.0006030938520871208
violation: 0.0005992255771889271
violation: 0.0005955122189365534
violation: 0.0005919356405960146
violation: 0.0005884735105288906
violation: 0.0005851626197891836
violation: 0.0005819472966805041
violation: 0.0005788624242479114
violation: 0.0005759087479598554
violation: 0.0005730546137310279
violation: 0.0005702968600984117
violation: 0.0005676053787181421
violation: 0.000565017678517244
violation: 0.0005624480584371221
violation: 0.0005599281471048911
violation: 0.0005574208102716491
violation: 0.0005549930907512517
violation: 0.000552626309068683
violation: 0.0005503237863511139
violation: 0.0005480875748009054
violation: 0.0005458976082893522
violation: 0.0005437570853967153
violation: 0.0005416726314728435
violation: 0.0005396329582224423
violation: 0.0005376381718609505
violation: 0.0005358628850809918
violation: 0.0005342566446346507
violation: 0.0005327134944353884
violation: 0.0005311700256183512
violation: 0.0005296374901747157
violation: 0.0005281469649348428
violation: 0.0005266549474163417
violation: 0.000525186071889191
violation: 0.0005237318107592327
violation: 0.0005222955570667139
violation: 0.0005208942964238188
violation: 0.0005195265168841678
violation: 0.0005181813428111227
violation: 0.0005168846752736574
violation: 0.0005156608680269033
violation: 0.0005144616554312331
violation: 0.0005132891688189617
violation: 0.0005121515266404262
violation: 0.0005110364330893343
violation: 0.00050994473150659
violation: 0.0005088753613793798
violation: 0.0005078236610583771
violation: 0.0005067909112023631
violation: 0.000505774076355985
violation: 0.0005047767175614998
violation: 0.0005037958933647781
violation: 0.0005028222129276422
violation: 0.0005018650428482406
violation: 0.000500922442379729
violation: 0.0004999974962488784
violation: 0.000499087239519465
violation: 0.0004981962000748009
violation: 0.0004973147318190522
violation: 0.0004964417296740213
violation: 0.0004955753197879482
violation: 0.0004946901218458134
violation: 0.0004938210437306058
violation: 0.0004929673596844637
violation: 0.0004921226355846086
violation: 0.0004912871202794866
violation: 0.000490459652854369
violation: 0.0004896376456528893
/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.2781188101128544
violation: 0.21103839273442182
violation: 0.16365897573755053
violation: 0.12638124502857334
violation: 0.09689398092857998
violation: 0.0738655391352644
violation: 0.05726304883639134
violation: 0.046397106968951114
violation: 0.0377627010107245
violation: 0.030324671559648655
violation: 0.02400007799856994
violation: 0.018705054318855736
violation: 0.014282427091628323
violation: 0.010676123451468908
violation: 0.008016534827386058
violation: 0.006238616114828533
violation: 0.005124394633030342
violation: 0.004490757479656688
violation: 0.004053115751123518
violation: 0.003744302603668964
violation: 0.003428962811660974
violation: 0.0030323190347560283
violation: 0.002727253739146881
violation: 0.002386505694047125
violation: 0.0020851628627841295
violation: 0.0017697484695162746
violation: 0.001492571627285805
violation: 0.0012488601974045385
violation: 0.0010438675111378096
violation: 0.0008573236692762506
violation: 0.0006991377766200616
violation: 0.0005706218431927305
violation: 0.0004636286240955771
violation: 0.00037487235479901417
violation: 0.0003032579084427067
violation: 0.0002463663859384325
violation: 0.00019825804790408604
violation: 0.0001582773351929673
violation: 0.00012439075792819175
violation: 9.611089606619568e-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.101 seconds)