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.14017421024501953
violation: 0.061581950654932376
violation: 0.034777744528725014
violation: 0.023155912689776726
violation: 0.016289564836607234
violation: 0.011732197722809713
violation: 0.009261179153190033
violation: 0.007770502529914549
violation: 0.006957471610159304
violation: 0.0064574143703548526
violation: 0.006191115125282052
violation: 0.006057238974457571
violation: 0.006000777806339296
violation: 0.005868357891308749
violation: 0.005802918028533863
violation: 0.005772367658829956
violation: 0.005756947971777759
violation: 0.005733332889918976
violation: 0.005700606624644986
violation: 0.00566782707879108
violation: 0.005587736630048217
violation: 0.005529135183167076
violation: 0.005460760674075853
violation: 0.005375194673451553
violation: 0.005288054442075108
violation: 0.005203284939611697
violation: 0.005110269931845265
violation: 0.005004969613317578
violation: 0.00488940194456723
violation: 0.004778610916794741
violation: 0.004657040705272529
violation: 0.004527642308383214
violation: 0.004393717477174782
violation: 0.004267124138926018
violation: 0.004133928133016152
violation: 0.004012755928138858
violation: 0.0038914653519266833
violation: 0.0037652602700427246
violation: 0.003637514821862794
violation: 0.0035147101661545115
violation: 0.003396513830358286
violation: 0.0032925205579802373
violation: 0.003194164813272468
violation: 0.003104947029333542
violation: 0.0030221674035499934
violation: 0.0029389646390336
violation: 0.0028561158500455897
violation: 0.002773891218680672
violation: 0.002692711668736579
violation: 0.0026129548289077014
violation: 0.0025351644702120836
violation: 0.00245874036343842
violation: 0.0023842026907913644
violation: 0.0023133039094784488
violation: 0.002243736743481161
violation: 0.0021751169925785943
violation: 0.002108409449092238
violation: 0.0020436678052480656
violation: 0.0019806643593507853
violation: 0.0019243270194365105
violation: 0.0018713261632057722
violation: 0.0018195678200700002
violation: 0.0017692749012865687
violation: 0.0017204657491197513
violation: 0.0016731692686996378
violation: 0.001627495035146773
violation: 0.001583917332970256
violation: 0.0015418960309273133
violation: 0.0015014385431319566
violation: 0.0014629272012158633
violation: 0.0014262081321622403
violation: 0.00139075976580856
violation: 0.001360158280515678
violation: 0.0013328464824007625
violation: 0.0013065923988231937
violation: 0.00128133574948116
violation: 0.0012569657401122866
violation: 0.0012363658727400006
violation: 0.0012190114699550923
violation: 0.001199211654450312
violation: 0.0011775622624512383
violation: 0.0011582609085416633
violation: 0.0011389415923630673
violation: 0.0011199124929360724
violation: 0.0011006754884535796
violation: 0.0010832777040277043
violation: 0.0010661363692304692
violation: 0.0010491933694702182
violation: 0.0010318244102607232
violation: 0.0010150792321238814
violation: 0.0009988201809299558
violation: 0.0009841318528821812
violation: 0.0009699922960878204
violation: 0.0009545966012011598
violation: 0.000939636333138234
violation: 0.0009266599168144082
violation: 0.0009140262172602078
violation: 0.0009015875006377242
violation: 0.0008902182357108199
violation: 0.000878049931186956
violation: 0.0008660457470920332
violation: 0.0008543517499937517
violation: 0.0008428706003286279
violation: 0.0008315536804368244
violation: 0.0008208847158802236
violation: 0.0008104269807767253
violation: 0.0007997522484736729
violation: 0.0007893350738954459
violation: 0.0007791326607913659
violation: 0.0007691414390018048
violation: 0.0007597179067852243
violation: 0.0007504652538891234
violation: 0.0007412456856967101
violation: 0.0007322966170540472
violation: 0.0007235915691683479
violation: 0.0007151920055394426
violation: 0.0007069372346702603
violation: 0.0006987637535245996
violation: 0.00069077335508239
violation: 0.0006830298779795734
violation: 0.0006754181243925498
violation: 0.0006679795936491864
violation: 0.0006606893398231069
violation: 0.0006536091296355104
violation: 0.000646664112099969
violation: 0.000639976261547236
violation: 0.0006335488650772283
violation: 0.0006273957420689858
violation: 0.0006215236000711356
violation: 0.0006161518203756123
violation: 0.0006113918151774329
violation: 0.0006071251736134513
violation: 0.0006030938520871144
violation: 0.0005992255771889327
violation: 0.0005955122189365806
violation: 0.0005919356405963333
violation: 0.0005884735105283864
violation: 0.0005851626197891752
violation: 0.0005819472966809881
violation: 0.0005788624242478358
violation: 0.0005759087479597278
violation: 0.0005730546137307157
violation: 0.0005702968600983413
violation: 0.0005676053787180839
violation: 0.0005650176785172682
violation: 0.00056244805843675
violation: 0.0005599281471045037
violation: 0.0005574208102721264
violation: 0.0005549930907512917
violation: 0.0005526263090688108
violation: 0.0005503237863512633
violation: 0.0005480875748006239
violation: 0.0005458976082895199
violation: 0.0005437570853969171
violation: 0.0005416726314731295
violation: 0.0005396329582217905
violation: 0.0005376381718609349
violation: 0.000535862885081229
violation: 0.0005342566446344321
violation: 0.0005327134944357551
violation: 0.0005311700256180138
violation: 0.000529637490174912
violation: 0.0005281469649349371
violation: 0.0005266549474164366
violation: 0.0005251860718893971
violation: 0.0005237318107592918
violation: 0.000522295557066584
violation: 0.0005208942964238079
violation: 0.0005195265168847426
violation: 0.000518181342811467
violation: 0.0005168846752738919
violation: 0.0005156608680270721
violation: 0.0005144616554311006
violation: 0.000513289168819009
violation: 0.0005121515266401843
violation: 0.0005110364330892999
violation: 0.0005099447315066015
violation: 0.0005088753613795402
violation: 0.0005078236610584091
violation: 0.0005067909112024534
violation: 0.0005057740763560762
violation: 0.0005047767175615177
violation: 0.0005037958933650828
violation: 0.0005028222129277717
violation: 0.0005018650428478898
violation: 0.0005009224423801244
violation: 0.0004999974962490146
violation: 0.0004990872395198469
violation: 0.0004981962000748277
violation: 0.0004973147318188065
violation: 0.0004964417296736238
violation: 0.0004955753197880696
violation: 0.0004946901218459942
violation: 0.0004938210437309485
violation: 0.0004929673596845571
violation: 0.0004921226355845868
violation: 0.0004912871202795689
violation: 0.0004904596528540375
violation: 0.0004896376456530961
/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.27811881011285894
violation: 0.21103839273442432
violation: 0.1636589757375516
violation: 0.126381245028573
violation: 0.09689398092857913
violation: 0.07386553913526324
violation: 0.057263048836390884
violation: 0.04639710696895042
violation: 0.037762701010723536
violation: 0.03032467155964754
violation: 0.02400007799856873
violation: 0.01870505431885449
violation: 0.014282427091627097
violation: 0.010676123451467871
violation: 0.008016534827385315
violation: 0.0062386161148280115
violation: 0.005124394633030019
violation: 0.004490757479656487
violation: 0.004053115751123436
violation: 0.0037443026036689028
violation: 0.0034289628116608763
violation: 0.0030323190347559324
violation: 0.002727253739146812
violation: 0.0023865056940469845
violation: 0.0020851628627839677
violation: 0.0017697484695161178
violation: 0.0014925716272856568
violation: 0.0012488601974043698
violation: 0.0010438675111376539
violation: 0.0008573236692761383
violation: 0.0006991377766199556
violation: 0.0005706218431926179
violation: 0.00046362862409549837
violation: 0.0003748723547989616
violation: 0.000303257908442672
violation: 0.00024636638593837076
violation: 0.0001982580479040574
violation: 0.0001582773351929701
violation: 0.00012439075792814125
violation: 9.611089606615778e-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 0.767 seconds)