Author: Glenn Davis
Date: 2025-06-08

# Photon Counting

#### Glenn Davis

#### 2025-06-08

This colorSpec vignette is a response to the question:

> Is there any program that given the lumen and the colour spectrum (relative intensity at any wavelength) of a light source and it outputs the total amount of photons per wavelength?

that was asked on a stackexchange forum, see [2]. Featured functions in this vignette are: `actinometric()` and `photometric()`.

    library( colorSpec )

## Read Relative Radiant Power and Scale to Specified Luminous Flux

Read the SPD for a domestic LED bulb from the Lamp Spectral Power Distribution Database, see [1]. The unique ID is `LED_A19_dim_domestic-use_softwhite-color_CREE-brand_6W_120V_75Lum_2700K_bernard`.

    wave = 275:899
    path = system.file( "extdata/sources/Cree-LED.txt", package="colorSpec" )
    bulb = readSpectra( path, wavelength=wave )
    par( omi=c(0,0,0,0), mai=c(0.6,0.8,0.1,0.1) )
    plot( bulb, main='' )

Figure 1. Energy Spectrum of a Domestic LED Bulb, manufactured by Cree

The energy unit is unknown. But it does not matter, because we are now going to scale so that the luminous flux of the SPD is 75 lumens, as specified by the manufacturer.

    luminous.flux = photometric( bulb ) ; luminous.flux

    ##                 photopic1924 scotopic1951 photopic1978 photopic2008
    ## Cree-LED.energy     1046.456     1193.872     1047.376     1101.321

The unit is lumen, but the first one - `photopic1924` - is the appropriate official standard. Scale spectrum to have 75 lumens.

    bulb = multiply( bulb, 75/luminous.flux[1] ) ; bulb

    ##
    ## colorSpec object.   The organization is 'df.col'.  Object size is 13120 bytes.
    ## the object describes a single source of light, and the quantity is 'energy' (energy of photons, which is radiometric).
    ## Wavelength range: 275 to 899 nm.  Step size is 1 nm.
    ##
    ## 1 spectra
    ## 625 data points / spectrum
    ##
    ##            Source Min         Max LambdaMax  Integral
    ## 1 Cree-LED.energy   0 0.001675584       605 0.2235534

    #   check that the luminous flux is now 75 lumens
    photometric( bulb )

    ##                 photopic1924 scotopic1951 photopic1978 photopic2008
    ## Cree-LED.energy           75     85.56539     75.06593      78.9322

From the man page for `photometric()` we know that the unit for `bulb` is \(\textrm{watt} * \textrm{nm}^{-1}\).

    par( omi=c(0,0,0,0), mai=c(0.6,0.95,0.1,0.1) )
    ylab = expression( 'Radiant Power'  ~~~  '[watt * ' ~ nm^-1 ~ ']' )
    plot( bulb, main='', ylab=ylab )

Figure 2. Energy Spectrum of a Domestic LED Bulb, manufactured by Cree

## Convert from an Energy-Based to a Photon-Based Spectrum

The unit is currently energy-based (energy of photons, aka radiometric), but we need photon-based (number of photons, aka actinometric). From the man page for `actinometric()` we know that the output unit is \(\mu \textrm{mole} * \textrm{sec}^{-1} * \textrm{nm}^{-1}\).

    bulb = actinometric( bulb )
    par( omi=c(0,0,0,0), mai=c(0.6,0.9,0.1,0.1) )
    ylab = expression( 'Photon Flux'  ~~~  '[' ~ mu ~ 'mole * ' ~ sec^-1 ~ nm^-1 ~ ']'  )
    plot( bulb, main='', ylab=ylab )

Figure 3. Photon Flux of a Domestic LED Bulb, manufactured by Cree

This plot looks similar but note that \(\lambda_{max}\) has moved slightly higher. For the total number of photons/sec from this bulb, compute the integral over \(\lambda\).

    bulb

    ##
    ## colorSpec object.   The organization is 'df.col'.  Object size is 13120 bytes.
    ## the object describes a single source of light, and the quantity is 'photons' (number of photons, which is actinometric).
    ## Wavelength range: 275 to 899 nm.  Step size is 1 nm.
    ##
    ## 1 spectra
    ## 625 data points / spectrum
    ##
    ##            Source Min         Max LambdaMax Integral
    ## 1 Cree-LED.energy   0 0.008500948       609 1.102559

So the total photon flux of the bulb is \(1.102559 ~ \mu \textrm{mole/sec}\). To convert this to exaphotons, multiply by \(0.602214 ~ \textrm{exaphotons/} (\mu \textrm{mole of photons} )\) to get \(0.663976 ~ \textrm{exaphotons/sec}\).

## References

[1]
JOHANNE ROBY, Antoine Morin-Paulhus, Martin Aubé and CYR, Louis-Olivier. Lamp Spectral Power Distribution Database [online]. 2014. Available at: https://lspdd.org/app/en/lamps
[2]
KOGRJA. Calculate number of photons of a light source given the lumen and the color spectrum [online]. B.m.: Electronics Stack Exchange. Available at: https://electronics.stackexchange.com/questions/174314/

## Session Information

    R version 4.5.0 (2025-04-11 ucrt)
    Platform: x86_64-w64-mingw32/x64
    Running under: Windows 11 x64 (build 26100)

    Matrix products: default
      LAPACK version 3.12.1

    locale:
    [1] LC_COLLATE=C
    [2] LC_CTYPE=English_United States.utf8
    [3] LC_MONETARY=English_United States.utf8
    [4] LC_NUMERIC=C
    [5] LC_TIME=English_United States.utf8

    time zone: America/Los_Angeles
    tzcode source: internal

    attached base packages:
    [1] stats     graphics  grDevices utils     datasets  methods   base

    other attached packages:
    [1] spacesRGB_1.7-0 colorSpec_1.8-0

    loaded via a namespace (and not attached):
     [1] digest_0.6.37        R6_2.6.1             microbenchmark_1.5.0
     [4] fastmap_1.2.0        xfun_0.52            glue_1.8.0
     [7] cachem_1.1.0         knitr_1.50           htmltools_0.5.8.1
    [10] logger_0.4.0         rmarkdown_2.29       lifecycle_1.0.4
    [13] cli_3.6.5            sass_0.4.10          jquerylib_0.1.4
    [16] compiler_4.5.0       tools_4.5.0          evaluate_1.0.3
    [19] bslib_0.9.0          yaml_2.3.10          rlang_1.1.6
    [22] jsonlite_2.0.0