Movatterモバイル変換


[0]ホーム

URL:


Phenol Red - pH Indicator

Glenn Davis

2025-06-08

Phenol red is an indicator commonly used to measure pH in swimmingpool test kits, see e.g.[2]. The goal ofthiscolorSpec vignette is to reproduce the colors seenin such a test kit, for typical values of pool pH. Calculations likethis one might make a good project for a college freshman chemistryclass. Featured functions in this vignette are:interpolate() andcalibrate().

library( colorSpec )library( spacesRGB )# for functions plotPatchesRGB() and SignalRGBfromLinearRGB()


Absorbance Spectra at Different pH Values

The absorbance data for phenol red has already been digitized from[1]:

path=system.file("extdata/stains/PhenolRed-Fig7.txt",package="colorSpec" )wave=350:650phenolred=readSpectra( path,wavelength=wave )par(omi=c(0,0,0,0),mai=c(0.6,0.7,0.4,0.2) )plot( phenolred,main='Absorbance Spectra of Phenol Red at Different pH Values' )

Compare this plot with[1], Fig. 7.Unfortunately, the concentration and optical path length are unknown,but these curves can still be used as ‘relative absorbance’.


Absorbance at Selected Wavelengths

We investigate how absorbance depends on pH for a few selectedwavelengths.

wavesel=c(365,430,477,520,560,590 )# 365 and 477 are 'isosbestic points'mat=apply(as.matrix(wavesel),1,function( lambda ) {as.numeric(lambda== wave) } )colnames( mat )=sprintf("%g nm", wavesel )mono=colorSpec( mat,wavelength=wave,quantity='power' )RGB=product( mono, BT.709.RGB,wavelength=wave )# this is *linear* RGBcolvec= grDevices::rgb(SignalRGBfromLinearRGB( RGB/max(RGB),which='scene' )$RGB )phenolsel=resample( phenolred, wavesel )pH=as.numeric(sub('[^0-9]*([0-9]+)$','\\1',specnames(phenolred) ) )pHvec=seq(min(pH),max(pH),by=0.05)phenolsel=interpolate( phenolsel, pH, pHvec )mat=t(as.matrix( phenolsel ) )par(omi=c(0,0,0,0),mai=c(0.8,0.9,0.6,0.4) )plot(range(pH),range(mat),las=1,xlab='pH',ylab='absorbance',type='n' )grid(lty=1 ) ;abline(h=0 )matlines( pHvec, mat,lwd=3,col=colvec,lty=1 )title("Absorbance of Phenol Red at Selected Wavelengths")legend('topleft',specnames(mono),col=colvec,lty=1,lwd=3,bty='n' )


Note that the curves for the isosbestic points 365 and 477 nm areapproximately flat, as expected. But for 430 nm the curve is distinctlynon-monotone. This indicates that the solution is not truly a mixture ofthe acidic and basic species (especially for pH\(\le\) 6), and there may be an undesiredside reaction, see[3].


Interpolation from pH=6.8 to pH=8.2

Swimming pools should be slightly basic; a standard test kit coversthe range from pH=6.8 to pH=8.2.

pHvec=seq(6.8,8.2,by=0.2)phenolpool=interpolate( phenolred, pH, pHvec )par(omi=c(0,0,0,0),mai=c(0.6,0.7,0.4,0.2) )plot( phenolpool,main="Absorbance Spectra of Phenol Red at Swimming Pool pH Values" )

The rest of this section is best viewed on a display calibrated forsRGB, see[4].

# create an uncalibrated 'material responder'testkit=product( D65.1nm,'solution', BT.709.RGB,wave=wave )# now calibrate so that fully transparent pure water has response RGB=c(1,1,1)testkit=calibrate( testkit,response=1 )RGB=product( phenolpool, testkit )RGB
##                R         G         B## pH=6.8 1.0282473 0.6840105 0.2260205## pH=7   1.0237233 0.5938036 0.2506686## pH=7.2 1.0182971 0.4961330 0.2788955## pH=7.4 1.0124869 0.4022827 0.3100400## pH=7.6 1.0067433 0.3195781 0.3440245## pH=7.8 1.0014227 0.2505541 0.3812950## pH=8   0.9969035 0.1947707 0.4225796## pH=8.2 0.9935212 0.1503867 0.4683717

Unfortunately, in some cases the red value is greater than 1 (G and Bare OK). The color is outside the sRGB gamut. Start over andrecalibrate.

testkit=product( D65.1nm,'solution', BT.709.RGB,wave=wave )# recalibrate, but lower the background a little, to allow more 'headroom' for indicator colorsbglin=0.96#  graylevel for the background, lineartestkit=calibrate( testkit,response=bglin )RGB=product( phenolpool, testkit )# this is *linear* sRGBRGB
##                R         G         B## pH=6.8 0.9871174 0.6566501 0.2169797## pH=7   0.9827743 0.5700514 0.2406419## pH=7.2 0.9775652 0.4762877 0.2677396## pH=7.4 0.9719874 0.3861913 0.2976384## pH=7.6 0.9664736 0.3067950 0.3302635## pH=7.8 0.9613658 0.2405320 0.3660432## pH=8   0.9570273 0.1869799 0.4056764## pH=8.2 0.9537803 0.1443713 0.4496368

All values have been multiplied bybglin, and are nowOK. Draw the RGB patches on a white background multiplied by the sameamount.

df.RGB=data.frame(LEFT=1:nrow(RGB),TOP=0,WIDTH=1,HEIGHT=2 )df.RGB$RGB= RGBpar(omi=c(0,0,0,0),mai=c(0.3,0,0.3,0) )plotPatchesRGB( df.RGB,space='sRGB',which='scene',labels=F,background=bglin )text( (1:nrow(RGB))+0.5,2,sprintf("%.1f",pHvec),adj=c(0.5,1.2),xpd=NA )title(main='Calculated Colors for pH from 6.8 to 8.2' )

The background color is that of pure water, and is not the fullRGB=(255,255,255).

In the first figure above, the phenol red concentration and opticalpath length are unknown. Compared to a real test kit, the calculatedcolors look a little faded. An absorbance multiplier can easily tweakthe unknown concentration, as follows.

tweak=1.3phenolpool=multiply( phenolpool, tweak )df.RGB=data.frame(LEFT=1:nrow(RGB),TOP=0,WIDTH=1,HEIGHT=2 )df.RGB$RGB=product( phenolpool, testkit )# this is *linear scene* sRGBpar(omi=c(0,0,0,0),mai=c(0.3,0,0.3,0) )plotPatchesRGB( df.RGB,space='sRGB',which='scene',background=bglin,labels=F )text( (1:nrow(RGB))+0.5,2,sprintf("%.1f",pHvec),adj=c(0.5,1.2),xpd=NA )main=sprintf('Calculated Colors for pH from 6.8 to 8.2 (absorbance multiplier=%g)', tweak )title(main=main )

These colors are a better match to those in the test kit.

References

[1]
LUIGI ROVATI, Luca Ferrari, Paola Fabbri andPILATI, Francesco.Plastic Optical Fiber pH SensorUsing a Sol-Gel Sensing Matrix. In: MOH. YASIN Sulaiman W. Harunand Hamzah AROF, eds.Fiber Optic Sensors[online]. B.m.: InTech, 2012. Available at: doi:10.5772/26517
[2]
TAYLOR TECHNOLOGIES, Inc.K-1000 sureCHECK Safety Test, Bromine & Chlorine (hirange), OT/pH [online]. 2017. Available at: https://www.taylortechnologies.com/en/product/test-kits/surecheck-safety-test-bromine-chlorine-hi-range-otph--K-1000
[3]
WIKIPEDIA.pHindicator — Wikipedia, The Free Encyclopedia[online]. 2017. Available at: https://en.wikipedia.org/w/index.php?title=PH_indicator.[Online; accessed 10-November-2017]
[4]
WIKIPEDIA.SRGB — wikipedia,the free encyclopedia [online]. 2017. Available at: https://en.wikipedia.org/w/index.php?title=SRGB.[Online; accessed 13-November-2017]



Session Information

R version 4.5.0 (2025-04-11 ucrt)Platform: x86_64-w64-mingw32/x64Running under: Windows 11 x64 (build 26100)Matrix products: default  LAPACK version 3.12.1locale:[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_Angelestzcode source: internalattached base packages:[1] stats     graphics  grDevices utils     datasets  methods   base     other attached packages:[1] spacesRGB_1.7-0 colorSpec_1.8-0loaded 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

[8]ページ先頭

©2009-2025 Movatter.jp