Take a sequence of colorSpec objects and compute their product. Only certain types of sequences are allowed. The return value can be a new colorSpec object or a matrix; see Details.
# S3 method for colorSpec
product( ... )
product()
returns either a colorSpec object or a matrix, see Details.
If product()
returns a colorSpec object, the organization
of the object is 'matrix'
or 'vector'
;
any extradata
is lost.
However, all terms in the product are saved in attr(*,'sequence')
.
One can use str()
to inspect this attribute.
If product()
returns a matrix,
this matrix can sometimes be ambiguous, see Note.
All actinometric terms are converted to radiometric on-the-fly and the returned colorSpec object is also radiometric.
In case of ERROR it returns NULL
.
unnamed arguments are colorSpec objects, and possibly a single character string, see Details. Possible named arguments are:
wavelength
The default wavelength='identical'
means that all the colorSpec objects must have the same wavelength sequence; if they do not it is an ERROR. wavelength
can be a new wavelength sequence, and all the objects are then
resample
d at these new wavelengths. wavelength
can also be 'auto'
or NULL
which means to compute a suitable wavelength sequence from those of the objects, see Details. It is OK to abbreviate the string wavelength
(e.g. to wave
); see Examples.
It is OK for the wavelength sequence to be irregular;
when the return value is a matrix
the integration weights the spectrum values appropriately.
method
, span
, extrapolation
, clamp
passed to resample()
with no checking or changes
integration
only applies when the return type is matrix.
The default option is 'rectangular'
, which means to weight the spectrum
value equally at all wavelengths; this is the ASTM E308-01 recommendation.
The other option is 'trapezoidal'
, which means to give the 2 endpoint
wavelength values 1/2 the weight of the others.
Trapezoidal integration is provided mostly for compatibility with other software.
To explain the allowable product sequences it is helpful to introduce some simple notation for the objects:
notation | colorSpec type | description of the object |
light | a light source | |
material | a material | |
responsivity.light | a light responder (aka detector) | |
responsivity.material | a material responder (e.g. a scanner) |
It is also helpful to define a sequence of positive integers
to be conformable iff it has at most one value greater than 1.
For example,
a sequence of all 1s is conformable. A sequence of all c(1,3)
and c(1,1,4,1,1,4,1)
are conformable,
but c(1,1,4,1,3,4,1)
is not.
There are 6 types of sequences for which the product is defined:
1.
The product of *
- the Hadamard product.
The numbers of spectra in the terms must be conformable.
If some objects have 1 spectrum and all the others have NULL
.
As an example, suppose
2.
The product of a light source followed by
As an example, suppose
3.
The product of
As an example, suppose
4.
This is the strangest product.
The bullet symbol • means that a variable material is inserted at that slot
in the sequence (or light path).
For each material spectrum inserted there is a response from
In the function product()
the location of the • is marked
by any character string whatsoever - it's up to the user who might choose
something that describes the typical material (between the light source and camera).
For example one might choose:
scanner = product( A.1nm, 'photo', Flea2.RGB, wave='auto')
to model a scanner that is most commonly used to scan photographs.
Other possible strings could be 'artwork'
, 'crystal'
, 'varmaterial'
,
or even 'slot'
.
See the vignette Viewing Object Colors in a Gallery for a worked-out example.
5.
The product of a light source, followed by %*%
of the transpose of the left part times and right part,
which is
As an example, think of a light source followed by a
reflective color target with 24 patches
followed by an RGB camera.
The sequence of spectra counts is c(1,24,3)
which is splittable into c(1,24)
and c(3)
.
The product matrix is 24×3.
See the vignette Viewing Object Colors in a Gallery for a worked-out example.
Note that is OK for there to be no materials in this product;
it is OK if
6.
The product of calibrate
the material responder separately in a customizable way.
See the vignette Viewing Object Colors in a Gallery
for a worked-out example with a flatbed scanner.
Note that sequences 5. and 6. are the only ones that
use the usual matrix product %*%
.
They may also use the Hadamard matrix product *
, as in sequences 1 to 4.
The argument wavelength
can also be 'auto'
or NULL
.
In this case the intersection of all the wavelength ranges of the objects is computed.
If the intersection is empty, it is an ERROR and the function returns NULL
.
The wavelength step step.wl
is taken to be the smallest over all the object wavelength sequences.
If the minimum step.wl
is less than 1 nanometer,
it is rounded off to the nearest power of 2 (e.g 1, 0.5, 0.25, ...).
Edward J. Giorgianni and Thomas E. Madden. Digital Color Management: Encoding Solutions. 2nd Edition John Wiley. 2009. Figure 10.11a. page 141.
Wikipedia. Hadamard product (matrices). https://en.wikipedia.org/wiki/Hadamard_product_(matrices)
ASTM E308-01. Standard Practice for Computing the Colors of Objects by Using the CIE System. (2001).
wavelength
,
type
,
resample
,
calibrate
,
radiometric
,
step.wl
# sequence 1.
path = system.file( "extdata/objects/Midwest-SP700-2014.txt", package='colorSpec' )
blocker.IR = readSpectra( path )
product( blocker.IR, Hoya, wave='auto' )
# sequence 2.
product( subset(solar.irradiance,1), atmosphere2003, blocker.IR, Hoya, wave='auto' )
# sequence 3.
plumbicon = readSpectra( system.file( "extdata/cameras/plumbicon30mm.txt", package='colorSpec' ) )
product( blocker.IR, subset(Hoya,1:3), plumbicon, wave='auto' )
# sequence 4.
# make an RGB scanner
bluebalancer = subset(Hoya,'LB')
# combine tungsten light source A.1nm with blue light-balance filter
# use the string 'artwork' to mark the variable material slot
scanner = product( A.1nm, bluebalancer, 'artwork', Flea2.RGB, wave='auto' )
# sequence 5.
product( D65.1nm, Flea2.RGB, wave='auto' ) # a 1x3 matrix, no materials
product( D65.1nm, neutralMaterial(0.01), Flea2.RGB, wave='auto' ) # a 1x3 matrix, 1 material
path = system.file( "extdata/sources/Lumencor-SpectraX.txt", package='colorSpec' )
lumencor = readSpectra( path, wave=340:660 )
product( lumencor, Flea2.RGB, wave='auto' ) # a 7x3 matrix, no materials
# sequence 6.
scanner = calibrate( scanner )
target = readSpectra( system.file( "extdata/targets/N130501.txt", package='colorSpec') )
product( target, scanner, wave='auto' ) # a 288x3 matrix
Run the code above in your browser using DataLab