-
Notifications
You must be signed in to change notification settings - Fork 16
Sq2.50 Procedural Framework: Part 3
Task parameters: Every Task has two fundamental binary switches that control its function and roles of its built-in expressions:
- "Ratio of primary interest": The choices are 206Pb/238U (i.e. 'primary parent nuclide' Booleans pbU = TRUE, pbTh = FALSE) or 208Pb/232Th (i.e. pbU = FALSE, pbTh = TRUE), and exactly one of these combinations must be chosen.
- "Method for calculating secondary ratio": The choices are "Directly, via the reference zircon" or "Indirectly, via 232Th/238U", and exactly one must be chosen. SQUID 2.50 stores this as a Boolean named Switch.DirectAltPD.
The first of these is self-explanatory (and 99+% of the time, it is 206Pb/238U, so pbU = TRUE, and pbTh = FALSE). Note that 'built-in' EqNum = -1 always refers to the ratio of primary interest, no matter which is chosen.
The secondary ratio is simply whichever of the two candidates was not chosen as the primary ratio, and there are two ways in which it can be calculated. The first (but more rare!) is to simply determine the secondary ratio directly, via calculation of calibration constants analogous to those used for the primary ratio. In the case of zircon, this would entail calculating a '208Pb/232Th calib. constant' alongside the 206Pb/238U calib. constant we are already familiar with. The problem with this approach is usually the reference zircon: it is unusual for any material to be perfectly fit for purpose in both the U-Pb and Th-Pb systems, as the geochemical behaviour of U and Th are quite different in most geological environments, and properly closed U-Th-Pb systems seem to be quite difficult to maintain in nature. If (and only if) the 'direct' method is employed, ' built-in' EqNum = -2 always refers to the ratio of secondary interest, no matter which is chosen. If the 'direct' method is not selected, EqNum = -2 is null, and EqNum = -3 will be non-null (see below).
The alternative (but more common!) method of calculating the secondary ratio is indirect, and relies on the appropriate rearrangement of the general equation:
(208Pb/232Th) = (206Pb/238U) * (238U/232Th) * (208Pb/206Pb)
Note that one of the first two ratios is independently accounted for (as the primary ratio of interest, via EqNum = -1), and the other is the secondary ratio we are interested in evaluating. In general, the fourth ratio is relatively easily measured, which means we can determine our target ratio if we have a means of evaluating the third ratio. In the case of zircon, Williams et al. (1996) formulated an empirical relationship that works well enough; it takes the (familiar) form:
232Th/238U = (0.03446 * ["254/238"] + 0.868) * ["248/254"]
where the ratios in square brackets represent isotopic "ratios of interest" measured directly via SHRIMP. If (and only if) the 'indirect' method is employed, ' built-in' EqNum = -3 always refers to the expression specifically governing 232Th/238U. If the 'indirect' method is not selected, EqNum = -3 is null, and EqNum = -2 will be non-null (see above).
So in general, one of EqNum = -2 and EqNum = -3 will always be null, and it is possible for both to be null, in the special case where only one system is being investigated (e.g. U-Pb geochronology where no proxy for Th is being measured (e.g. a 'normal' zircon list of mass-stations lacking the 248 (ThO) peak).
So, there are four permutations of the two binary switches, and they are all valid in an isotopic sense:
- Case 1: Primary ratio = 206Pb/238U, Switch.DirectAltPD = FALSE (this is the most common in SHRIMP geochronology)
- Case 2: Primary ratio = 206Pb/238U, Switch.DirectAltPD = TRUE
- Case 3: Primary ratio = 208Pb/232Th, Switch.DirectAltPD = FALSE
- Case 4: Primary ratio = 208Pb/232Th, Switch.DirectAltPD = TRUE
Iteration-specific parameters for a Task: The above relates to fundamental properties of an individual Task. There are a series of auxiliary settings, applied to a Task solely for a specific iteration of its use. In theory, these auxiliary settings should not interact with the fundamental Task properties... in practice, the way SQUID 2.50 is constructed, there is some overlap.
We have already dealt with two of these 'auxiliary' settings:
- SBM-normalisation (on or off), and
- Isotope-ratio calculation (weighted average or linear regression)
A third, which unfortunately does interact with the four Cases above, is the choice of 'index isotope'. The 'index isotope' refers to the identity of the isotope of Pb used to calculate the proportion of non-radiogenic Pb present in any given analysis, and perform the appropriate correction. The two most-frequently used options are 204Pb and 207Pb, as neither are used in the fundamental daughter-parent ratios that form the basis of U-Th-Pb geochronology. SQUID 2.50 does offer a third option: 208Pb. Note, however, that this option is not available to any Task involving direct calculation of a 208Pb/232Th calibration constant (irrespective of whether 208Pb/232Th is the primary or secondary ratio), and this restriction rules out Cases 2-4. As a result, when index isotope is added to the permutations, there are nine valid combinations requiring consideration:
- Case 1a: Primary ratio = 206Pb/238U, Switch.DirectAltPD = FALSE, index isotope = 204Pb
- Case 1b: Primary ratio = 206Pb/238U, Switch.DirectAltPD = FALSE, index isotope = 207Pb
- Case 1c: Primary ratio = 206Pb/238U, Switch.DirectAltPD = FALSE, index isotope = 208Pb
- Case 2a: Primary ratio = 206Pb/238U, Switch.DirectAltPD = TRUE, index isotope = 204Pb
- Case 2b: Primary ratio = 206Pb/238U, Switch.DirectAltPD = TRUE, index isotope = 207Pb
- Case 3a: Primary ratio = 208Pb/232Th, Switch.DirectAltPD = FALSE, index isotope = 204Pb
- Case 3b: Primary ratio = 208Pb/232Th, Switch.DirectAltPD = FALSE, index isotope = 207Pb
- Case 4a: Primary ratio = 208Pb/232Th, Switch.DirectAltPD = TRUE, index isotope = 204Pb
- Case 4b: Primary ratio = 208Pb/232Th, Switch.DirectAltPD = TRUE, index isotope = 207Pb
Traditionally, SQUID 2.50 requires the user to select a single index isotope, and the calculations for one of the nine permutations above are carried out. In general, I think it would be better if, once the Case number is established from the binary switch settings, the calculations were carried out for all valid index isotopes for that Case. This would save the user needing to test each index isotope via sequential iterations of data reduction (as SQUID 2.50 currently requires).
The superset of calculatable parameters, identified by column-header, is given below. In all cases, these are row-by-row calculations aimed at filling cells in an array where the rows represent individual analyses, as per the StandardData sheet produced by SQUID 2.50. Note that no single data-reduction will ever calculate all of these: every Case will exclude some of them. The parameters are grouped in the list below, to try and highlight some of the data structure.
Calibration constants uncorrected for common Pb
- UncorrPb/Uconst
- UncorrPb/Uconst %err
- UncorrPb/Thconst
- UncorrPb/Thconst %err
Pb/U calibration constants corrected from common Pb
- 4-corr206Pb/238Ucalibr.const
- 4-corr206Pb/238Ucalibr.const %err
- 4-corr206Pb/238U Age(Ma)
- 4-corr206Pb/238U Age(Ma) ±1s
- 7-corr206Pb/238Ucalibr.const
- 7-corr206Pb/238Ucalibr.const %err
- 7-corr206Pb/238U Age(Ma)
- 7-corr206Pb/238U Age(Ma) ±1s
- 8-corr206Pb/238Ucalibr.const
- 8-corr206Pb/238Ucalibr.const %err
- 8-corr206Pb/238U Age(Ma)
- 8-corr206Pb/238U Age(Ma) ±1s
Pb/Th calibration constants corrected for common Pb
- 4-corr208Pb/232Thcalibr.const
- 4-corr208Pb/232Thcalibr.const %err
- 4-corr208Pb/232Th Age(Ma)
- 4-corr208Pb/232Th Age(Ma) ±1s
- 7-corr208Pb/232Thcalibr.const
- 7-corr208Pb/232Thcalibr.const %err
- 7-corr208Pb/232Th Age(Ma)
- 7-corr208Pb/232Th Age(Ma) ±1s
Geochemical parameters
- ppmU
- ppmTh
- 232Th/238U
- 232Th/238U %err
Common and radiogenic 206Pb and 208Pb
- 4-corr%com206
- 7-corr%com206
- 8-corr%com206
- 4-corr%com208
- 7-corr%com208
- 4-corr208Pb*/206Pb*
- 4-corr208Pb*/206Pb* %err
- 7-corr208Pb*/206Pb*
- 7-corr208Pb*/206Pb* %err
204Pb overcounts assessed via 207Pb and 208Pb
- 204overcts/sec(fr. 207)
- 204overcts/sec(fr. 208)
- 204/206(fr. 207)
- 204/206(fr. 207) %err
- 204/206(fr. 208)
- 7-corr206Pb/238Uconst.delta%
- 8-corr206Pb/238Uconst.delta%
Dates and Concordia data
- 4-corr207Pb/206Pbage
- 4-corr207Pb/206Pbage ±1s
- 4-corr207Pb/206Pb
- 4-corr207Pb/206Pb %err
- 4-corr207*/235
- 4-corr207*/235 %err
- 4-corr206*/238
- 4-corr206*/238 %err
- 4-corr errcorr
- 7-corr206*/238
- 7-corr206*/238 %err
- 8-corr207Pb/206Pbage
- 8-corr207Pb/206Pbage ±1s
- 8-corr207Pb/206Pb
- 8-corr207Pb/206Pb %err
- 8-corr207*/235
- 8-corr207*/235 %err
- 8-corr206*/238
- 8-corr206*/238 %err
- 8-corr errcorr
With this 'Task-anatomy' defined, we can rejoin the code. The next phase of Loop A is aimed at the evaluation of many of the columns listed above, with emphasis on the role of the Case-number in defining the exact expression used.
Loop A remains unfinished, but now that the first loop through the spot-groups has been completed (via Loop B and subsequent), it is time to reset the counters and prepare for the second loop through the spots. This second loop encompasses the calculation and placement, row-by-row, of the Daughter-Parent ratios/constants, using the built-in expressions.
Do --Start of Loop D ("second loop of spots": calculation and placement, row-by-row,
--of the Daughter-Parent ratios/constants)
Do --Start of Loop E (counting, and "basic" parsing of spot, as per Loop C)
piaSpotCt[-pbStd] = 1 + piaSpotCt[-pbStd]
piaSpotIndx[-pbStd] = 1 + piaSpotIndx[-pbStd]
piSpotNum = piaSpots[-pbStd, piaSpotIndx[-pbStd] ]
ParseRawData piSpotNum, FALSE, IgnoredChangedRunTable
Loop Until IgnoredChangedRunTable = FALSE --End of Loop E
See separately documented subroutine ParseRawData for the argument list. Note that (1) FirstPass = FALSE here (as opposed to the prior call of ParseRawData in Sq2.50 Procedure Pt 2, and (2) the prior value of IgnoredChangedRunTable is not specified, but this is ultimately irrelevant as it is set to FALSE near the start of ParseRawData anyway. (I am not certain of the purpose of Loop E, given that every analysis that reaches this point has already been through Loop C.)
SQUID 2.50 proceeds by determining how many Daughter-Parent ratios require direct evaluation. If Switch.DirectAltPD = TRUE, then piNumDauPar = 2 (i.e. calibration constants must be calculated for both 206Pb/238U and 208Pb/232Th); otherwise, piNumDauPar = 1. SQUID 2.50 starts by eliminating the trivial case where the user has specified Switch.DirectAltPD = TRUE but provided no expression for evaluation of the calibration constant of the secondary ratio. The incomplete Loop D proceeds as follows:
plSpotOutputRw = 1 + plSpotOutputRw
plOutputRw = plSpotOutputRw
MaxDPnum = piNumDauPar
If MaxDPnum = 2 AND Switch.DirectAltPD = TRUE AND Task.Eqns[-2] = ""
MaxDPnum = 1
End If
SQUID 2.50 then proceeds to evaluate as many calibration constants as are needed (at least one, via EqNum = -1, is mandatory), using the EqnInterp subroutine documented previously, and placing the result in the appropriate column. SQUID 2.50 does this slightly awkwardly, because it always stores the primary ratio calibration constant in the same place; it just applies different column-header names depending on whether the primary ratio is 206Pb/238U or 208Pb/232Th. I think it would be a better idea to simply have all the relevant columns permanently available and named, calculate whichever values are necessary/permitted, and then designate which of the calibration constants is the primary one.
The following code-block populates at least some of UncorrPb/Uconst, UncorrPb/Uconst %err, UncorrPb/Thconst, UncorrPb/Thconst %err, depending on binary switch settings. Note that the EqnInterp-related arithmetic has already been performed (without context) in Calamari, and the result has been output under the name '206/238 Calib Const'.
For DauParNum = 1 To MaxDPnum
EqnInterp Task.Eqns[-DauParNum], -DauParNum, EqnRes, EqnFerr, 1, TmpRej
--Next 'If' simply identifies sheets/columns for placing calculated values
If pbStd = TRUE
ValCol = piaStdUnCorrAcol[DauParNum]
ErCol = piaStdUnCorrAerCol[DauParNum]
Else
ErCol = piaAeCol[DauParNum]
If pbCanDriftCorr = TRUE --beyond current scope of SQUID 3.0!
ValCol = piUnDriftCorrConstCol
Else
ValCol = piaAcol[DauParNum]
End If
End If
--Now place EqnRes in ValCol, and EqnFerr (as %) in ErCol
CFs plSpotOutputRw, ValCol, fsS(EqnRes) --corrects Ludwig's CDbl-CSng-CDbl error
--fsS is a Ludwig function that converts a double-precision number to a string.
--It is not obvious why fsS is employed here.
If EqnRes <> SQUID_Error_Value AND EqnFerr <> SQUID_Error_Value
CFs plSpotOutputRw, ErCol, fsS(100 * EqnFerr) --corrects Ludwig's CDbl-CSng-CDbl error
--fsS is a Ludwig function that converts a double-precision number to a string.
--It is not obvious why fsS is employed here.
End If
If DauParNum = 1
piWLrej = TmpRej
End If
Next DauParNum
The next step is to populate row-by-row the concentrations of the 'primary element' ppm values. This will populate at most one of the columns ppmU, ppmTh:
StdElePpm pbStd, plSpotOutputRw --subroutine documented separately
Next is a test to see if the run-table contains both U-bearing peaks and Th-bearing peaks. If so, then it is possible (but not mandatory), based on the 'primary element' ppm values, to calculate 232Th/238U, as well as 'secondary element' ppm values.
SQUID 2.50 uses the Booleans pbHasU and pbHasTh to represent the existence of U- and Th-bearing peaks in the run-table of interest. The values are assigned in a fairly unsophisticated way: pbHasU = TRUE if there is a mass-station in the run-table with a nominal mass of 238 (= U) and/or 254 (= UO) and/or 270 (= UO2), and likewise PbHasTh = TRUE if there is a mass-station in the run-table with a nominal mass of 232 (= Th) and/or 248 (= ThO) and/or 264 (= ThO2). These tests are a good first approximation, but should not be the sole determinant of the Boolean values (as they currently are in SQUID 2.50).
A more rigorous approach for SQUID 3.0 would be to display check-boxes next to each mass-station on the run-table screen (one for 'U-bearing' and one for 'Th-bearing'), each ticked TRUE or FALSE according to the above criteria, but user-editable in case of unforeseen nominal masses for U- and/or Th-bearing mass-stations. Then pbHasU could be an aggregated Boolean i.e. set to TRUE if one or more of the mass-station-specific 'U-bearing' check-boxes was marked; likewise pbHasTh would be set to TRUE if one or more of the mass-station-specific 'Th-bearing' check-boxes was marked. Feedback to this effect could be displayed on the run-table screen.
The incomplete Loop D proceeds:
If pbHasTh = TRUE AND pbHasU = TRUE
If piNumDauPar = 1 --"number of daughter-parents"
--i.e. Switch.DirectAltPD = FALSE and therefore
--Secondary U-Th/Pb expression (EqNum = -2) is NULL
ThUfromFormula pbStd, plSpotOutputRw
--calculates 232Th/238U using EqNum = -3
--Calamari already does this, without context
--subroutine documented separately
SecondaryParentPpmFromThU pbStd, plSpotOutputRw
--calculates 'secondary element' ppm value, using combination
--of 'primary element' value and calculated 232Th/238U
--subroutine documented separately
The 'Else' of this unfinished 'If' relates to piNumDauPar = 2, which corresponds to Switch.DirectAltPD = TRUE and therefore Secondary U-Th/Pb expression (EqNum = -2) = NOT NULL. It predominantly caters for Sample (rather than Standard) analyses, for which 'total 206/238' (as well as 'total 238/206' when pbU = TRUE) and 'total 208/232' values are calculated using the respective calibration constants.
From there, and irrespective of whether the analysis is Standard or Sample, 232Th/238U is also calculated based on each pair of calibration constants (although Ludwig has noted these expressions need to be re-evaluated later because 'column mean' values for the calibration constants do not yet exist).
Finally, for Sample analyses only, the 'secondary element' ppm value is calculated, using the combination of 'primary element' ppm value and calculated 232Th/238U. The incomplete 'If' statement proceeds as follows:
Else --i.e. if piNumDauPar = 2
--i.e. Switch.DirectAltPD = TRUE and therefore Secondary
--U-Th/Pb expression (EqNum = -2) is NOT NULL
If pbStd = FALSE --i.e. sample analysis
Tot68_82_fromA plSpotOutputRw
--Produces total 206/238 and total 208/232 from
--calibration constants A(206/238) and A(208/232)
--subroutine documented separately
End If
ThUfromA1A2 pbStd, plSpotOutputRw, TRUE --following from Ludwig:
--NOTE: must recalc later because WtdMeanA1/2 range doesn't yet exist
--subroutine documented separately
If pbStd = FALSE --i.e. sample analysis
SecondaryParentPpmFromThU pbStd, plSpotOutputRw
--subroutine documented separately
End If
End If
The next stage of the incomplete Loop D deals with Standard analyses ONLY, firstly by evaluating 204 'overcounts' on a spot-by-spot basis, and secondly by applying a 'common-Pb correction' to the calculated calibration constant value(s) for each spot (and augmenting the calibration constant %err value for each spot, to reflect the additional uncertainty associated with the 'common Pb correction').
The first part of Ludwig Q4 populates the following StandardData columns:
- 204overcts/sec(fr. 207)
- 204overcts/sec(fr. 208)
- 204/206(fr. 207)
- 204/206(fr. 207) %err
- 204/206(fr. 208)
- 7-corr206Pb/238Uconst.delta%
- 8-corr206Pb/238Uconst.delta%
The second part of Ludwig Q4 populates the following StandardData columns:
- 4-corr206Pb/238Ucalibr.const
- 4-corr206Pb/238Ucalibr.const %err
- 7-corr206Pb/238Ucalibr.const
- 7-corr206Pb/238Ucalibr.const %err
- 8-corr206Pb/238Ucalibr.const
- 8-corr206Pb/238Ucalibr.const %err
- 4-corr208Pb/232Thcalibr.const
- 4-corr208Pb/232Thcalibr.const %err
- 7-corr208Pb/232Thcalibr.const
- 7-corr208Pb/232Thcalibr.const %err
The incomplete Loop D proceeds as follows:
If pbStd = TRUE
If Switch.ShowOverCtCols = TRUE --SQUID 2.50 does not offer this
--Switch as a User-option; presumably set to TRUE by default
OvercountColumns (plSpotOutputRw)
--calculates & places apparent 204 overcount data
--subroutine documented separately
--first part of Ludwig Q4 completed
End If
--Second part of Ludwig Q4 commences:
--correct 206/238 and/or 208/232 calibration constants for common Pb, and
--augment calibration constant %errs to reflect uncertainty related to correction
For DauParNum = 1 to piNumDauPar
--i.e. for one or both of the daughter-parent combinations that can be calibrated directly,
--check to see if the system (for this iteration) is Pb/U or Pb/Th, by setting Boolean IsPbTh:
If (pbU = TRUE AND DauParNum = 2) OR (pbTh = TRUE AND DauParNum = 1)
IsPbTh = TRUE
Else
IsPbTh = FALSE
End If
--Now calculate common Pb-corrected calibration constant VALUES:
--piStdCorrType = 0 means '204-corrected'
--piStdCorrType = 1 means '207-corrected'
--piStdCorrType = 2 means '208-corrected'
--Traditionally SQUID 2.50 requires ONE piStdCorrType value, but
--I would like SQUID 3.0 to calculate ALL piStdCorrType values.
If piStdCorrType = 0 -- '204-corrected'
If IsPbTh = TRUE
FinalTerm1 = (1 - ["204/206"] / ["208/206"] * sComm84) * ["UncorrPb/Thconst"]
--fills column ["4-corr208Pb/232Thcalibr.const"]
Else
FinalTerm1 = (1 - ["204/206"] * sComm64) * ["UncorrPb/Uconst"]
--fills column ["4-corr206Pb/238Ucalibr.const"]
End If
Elseif piStdCorrType = 1 -- '207-corrected'
If IsPbTh = TRUE
FinalTerm1 = (1 - ["204/206(fr. 207)"] / ["208/206"] * sComm84) * ["UncorrPb/Thconst"]
--fills column ["7-corr208Pb/232Thcalibr.const"]
Else
FinalTerm1 = (1 - ["204/206(fr. 207)"] * sComm64) * ["UncorrPb/Uconst"]
--fills column ["7-corr206Pb/238Ucalibr.const"]
End If
Elseif piStdCorrType = 2 -- '208-corrected', can't use Pb/Th calibration here
FinalTerm1 = (1 - ["204/206(fr. 208)"] * sComm64) * ["UncorrPb/Uconst"]
--fills column ["8-corr206Pb/238Ucalibr.const"]
--typo in original expression now corrected (2018-03-17)
End If
PlaceFormulae FinalTerm1, plSpotOutputRw, piaSacol[DauParNum]
--Now calculate common Pb-corrected calibration constant ERRORS:
If piStdCorrType = 0 -- '204-corrected'
If IsPbTh = TRUE
Term1 = ["UncorrPb/Thconst %err"]^2 +
( sComm84 / ( ["208/206"] / ["204/206"] - sComm84 ) )^2 * ["204/206 %err"]^2
FinalTerm2 = sqrt( Term1 )
--fills column ["4-corr208Pb/232Thcalibr.const %err"]
Else
Term1 = ["UncorrPb/Uconst %err"]^2 +
( sComm64 / ( 1 / ["204/206"] - sComm64 ) )^2 * ["204/206 %err"]^2
FinalTerm2 = sqrt( Term1 )
--fills column ["4-corr206Pb/238Ucalibr.const %err"]
End If
Elseif piStdCorrType = 1 -- '207-corrected'
If IsPbTh = TRUE
Term1 = ["UncorrPb/Thconst %err"]^2 +
( sComm84 / ( ["208/206"] / ["204/206(fr. 207)"] - sComm84 ) )^2 *
( ["208/206 %err"]^2 + ["204/206(fr. 207) %err"]^2 )
FinalTerm2 = sqrt( Term1 )
--fills column ["7-corr208Pb/232Thcalibr.const %err"]
Else
Term1 = ["UncorrPb/Uconst %err"]^2 +
( sComm64 / (1 / ["204/206(fr. 207)"] - sComm64 ) )^2 *
["204/206(fr. 207) %err"]^2
FinalTerm2 = sqrt( Term1 )
--fills column ["7-corr206Pb/238Ucalibr.const %err"]
End If
Elseif piStdCorrType = 2 -- '208-corrected', can't use Pb/Th calibration here
--NOTE that it is also necessary for calculated 232Th/238U and its %err to exist!
--Eqns for Term1 and FinalTerm2 corrected 2017-12-31
--Eqn for Term1 replaced with Term2, and FinalTerm2 RE-corrected 2018-03-19
Term2 = ( sComm64 * ["UncorrPb/Uconst"] * ["204/206(fr. 208)"]
/ ["8-corr206Pb/238Ucalibr.const"] )^2
Term3 = ( ["208/206"] * ["208/206 %err"] /
( ["208/206"] - StdRad86fact * ["232Th/238U"] ) )^2
Term4 = 1 / ( ["208/206"] - StdRad86fact * ["232Th/238U"] ) +
sComm64 / ( sComm84 - sComm64 * StdRad86fact * ["232Th/238U"] )
Term6 = ( Term4 * StdRad86fact * ["232Th/238U"] * ["232Th/238U %err"] )^2
FinalTerm2 = sqrt( ["UncorrPb/Uconst %err"]^2 + (Term2 * (Term3 + Term6)) )
--fills column ["8-corr206Pb/238Ucalibr.const %err"]
End If
If FinalTerm2 <> "" --FinalTerm2 is placed in the "calib.const. %err" column
PlaceFormulae FinalTerm2, plSpotOutputRw, piaSaEcol[DauParNum]
End If
Next DauParNum
End If --end of Ludwig Q4
plHdrRw = flHeaderRow[pbStd]
--just returns the cursor to the top row of StandardData data, I think
Loop Until piaSpotIndx[-pbStd] = piaEndSpotIndx[-pbStd] --End of Loop D
Loop A still remains unfinished, but now that the second loop through the spot-groups has been completed (via Loop D and subsequent), it is time to do the rest of the simple row-by-row calculations, followed by preparations for calculation of the key "column mean" values, which are in turn used in other row-by-row expressions. The remainder of Loop A, encompassing these processes, is documented in Sq2.50 Procedural Framework: Part 4.