-
Notifications
You must be signed in to change notification settings - Fork 16
SHRIMP: Sub ParseRawData
[The following is a generalised function, used and reused by SQUID 2.50 multiple times during a 'typical' data-reduction. As such, the inputs and outputs of the functions have generalised names. The identities of the specific inputs and outputs are defined when the function is called.]
The subroutine examines, on an analysis-by-analysis basis, the (already-)parsed XML file and extracts 'useful' information such as the spot-label (as string), analysis date and time (as string), the number of mass-stations (integer), and the number of scans (integer). Pending the results of some test, the subroutine then proceeds to the calculations documented in SHRIMP: Step 2. The comment in the SQUID VBA code fort this subroutine reads "Extracts data for a single SHRIMP spot, correcting for background counts; assumes cursor is on the sample-name column & row of the raw data."
In addition to the spot index-number SpotNumber, ParseRawData has a pair of mandatory Booleans: FirstPass and IgnoredChangedRunTable. FirstPass is an input that caters for the fact that although SQUID 'parses' individual sets (and subsets) of analyses multiple times, there are some aspects of this process that need only be done once. IgnoredChangedRunTable is a nominal input, as it is always explicitly set FALSE early in the subroutine. It is a flag monitoring the compatibility of each individual analysis with (a) the number of mass-stations specified in the governing Task, and (b) minimum standards for sensible data-reduction in general. Data reduction proceeds smoothly for as long as IgnoredChangedRunTable is FALSE.
ParseRawData(SpotNumber, FirstPass, IgnoredChangedRuntable, sDate, GetTrim, DelMT, GetTrimSigma)
SpotNumber: Index number of the analysis within the XML file, starting at 1 and assigned chronologically (i.e. SpotNumber = 1 is the first analysis acquired, and all analyses are time-sequenced, irrespective of whether they classify as 'standards' or 'unknowns').
FirstPass: Boolean input which dictates, for each specific invocation of ParseRawData, whether the 'once-only' operations are to be conducted.
IgnoredChangedRunTable: Boolean operating effectively as an error-trapping measure. It is explicitly set to FALSE early in ParseRawData, so its value as an input is inconsequential. During smooth data-processing, it remains FALSE throughout. It only becomes TRUE if a 'test' is failed; these tests are detailed below.
sDate: A string comprising the comma-separated date and time the analysis was commenced, in the form "YYYY-MM-DD, HH24:MI:SS". Default is the blank value "".
GetTrim: Boolean dictating whether or not trim-mass information is collated. Default value is TRUE.
DelMT: Boolean of uncertain purpose; not used in subroutine. Default value is FALSE.
GetTrimSigma: Boolean of uncertain purpose; not used in subroutine. Default value is FALSE.
Values of type Boolean
FirstPass, GetTrim, IgnoredChangedRunTable [, DelMT, GetTrimSigma]
Values of type String
psSpotName, sDate
Values of type Integer
j, k, SpotNpeaks, SpotNscans, SpotNumber, Task.Npeaks, SBM_zero_cps
Values of type Double
BackgroundCPS, CalcBkrdCPS, CalcVariance, MeanNetCps, Seconds, StartTime, SumBkrdCPS
Vectors comprising values of type Double
BkrdCPS, count_time_sec, NetCps, TotCps
Arrays comprising values of type Double
AbsNetPkCps, NetPkCps, PkCounts, PkCps, PkFerr, SBMCounts, SBMCps, time_stamp_sec, TrimMass, TrimTime
Arrays comprising values of type String
psaSpotNames, psaSpotDateTime
The function of the subroutine is paraphrased as follows:
If SpotNumber < 1
Exit Sub
End If
psSpotName = psaSpotNames[SpotNumber]
IgnoredChangedRunTable = FALSE
If FirstPass = TRUE
sDate = psaSpotDateTime[SpotNumber]
<<Convert sDate string to an integer number of Seconds since
the commencement of calendar 1990.>>
StartTime = Seconds
End If
<<For SpotNumber, extract SpotDateTime, SpotNpeaks, SpotNscans.>>
The subroutine then runs a series of tests to see whether the analysis meets some fundamental criteria (both in itself, and by reference to the Task in use). If one of the tests fails, the subroutine exits, or data-processing stops with the offending analysis selected.
If SpotNpeaks <> Task.Npeaks
If FirstPass = TRUE and IgnoredChangedRunTable = FALSE
MsgBox("Run Table changes from " & StR(Task.Npeaks) &
" mass stations to " & StR(SpotNpeaks) & " at spot number "
& StR(SpotNumber) & ". Ignoring all peaks not having the
original Run Table.")
End If
IgnoredChangedRunTable = TRUE
Exit Sub
ElseIf FirstPass = FALSE And (SpotNpeaks < 2 Or Task.Npeaks < 2)
MsgBox("Invalid number of pks obtained when parsing the PD file.")
<<Select offending row, and End.>>
ElseIf SpotNscans < 1
If FirstPass = TRUE
MsgBox("Ignoring spot" & StR(SpotNumber) & " -- fewer than 2 scans.")
--Note the apparent discrepancy between MsgBox and ElseIf criterion:
--both are reproduced verbatim from the VBA code.
End If
IgnoredChangedRunTable = TRUE
Exit Sub
End If
Assuming that the subroutine has not been exited by this point, the remainder of its workings are essentially equivalent to the code previously presented as SHRIMP: Step 2. There are some minor differences (mostly additions), and these added lines are marked in the code-blocks below with triple-asterisks at each end.
For each analysis/fraction, we have thus far generated a matrix of data comprising SpotNscans (= 6 in demo XML) measurements at each of SpotNpeaks (= 10 in demo XML) nuclides, for a total of 60 "peak" measurements. For each of these peaks, the previously calculated values of interest (from SHRIMP: Step 1) can be defined as:
For j = 1 to SpotNscans
For k = 1 to SpotNpeaks
PkCounts[j, k] = 'total counts at mass'[j, k]
SBMCounts[j, k] = 'total SBM counts'[j, k]
***If GetTrim = TRUE and FirstPass = TRUE***
***TrimMass[j, k] = 'trim mass at peak'[j, k]***
***TrimTime[j, k] = (StartTime + time_stamp_sec[j, k]) / 3600***
***End If***
Next k
Next j
For each peak, start by calculating the PkCps and SBMCps values, correcting the latter for the measured SBM_zero_cps.
[SBM_zero_cps is a measure of the reading on the secondary beam monitor when the beam is off, and its numeric value depends on the range to which the SBM monitor has been set, using the SHRIMP control software. There is only one sbm_zero_cps value per analysis.]
In implementing the below, note that a means of identifying the background peak is needed, including determination of whether a background peak even exists in the XML file being processed. (This is because there is no formal analytical requirement to measure background, and obviously background-correction should not happen if background has not been measured.) In the demo XML, background corresponds to k = 3.
For j = 1 to SpotNscans
For k = 1 to SpotNpeaks
PkCps[j, k] = PkCounts[j, k] / count_time_sec[k]
SBMCps[j, k] = (SBMCounts[j, k] / count_time_sec[k]) - SBM_zero_cps
If k = background --isolate its PkCps vector of length SpotNscans,
--and maintain its sum:
BkrdCps[k] = PkCps[j, k]
SumBkrdCps = SumBkrdCps + BkrdCps[k]
End If
Next k
Next j
If [background exists within collection of species]
CalcBkrdCps = SumBkrdCps / SpotNscans
If CalcBkrdCps < 10
BackgroundCps = CalcBkrdCps
Else
BackgroundCps = [biweight value of BkrdCps, with tuning = 9]
End If
Else
BackgroundCps = 0
End If
Now use this value to perform the background correction for each peak, and calculate the associated fractional error:
For k = 1 to SpotNpeaks
If k is NOT background
For j = 1 to SpotNscans
NetPkCps[j, k] = PkCps[j, k] – BackgroundCps
AbsNetPkCps[j, k] = abs( NetPkCps[j, k] )
If AbsNetPkCps[j, k] > 1e-6
CalcVariance = PkCounts[j, k] + ( abs( BackgroundCps ) *
( count_time_sec[k] / count_time_sec[background] ) ^2 )
PkFerr[j, k] = sqrt( CalcVariance ) /
( AbsNetPkCps[j, k] * count_time_sec[k] )
Else
PkFerr[j, k] = 1 --this is to control the magnitudes of
--errors associated with ~0 cps
End If
Next j
End If
Next k
If FirstPass = TRUE, calculate 'total cps' values for placement as columns on StandardData and SampleData sheets:
***If FirstPass = TRUE***
For k = 1 to Task.Npeaks
For j = 1 to SpotNscans
NetCps[j] = NetPkCps[j, k]
Next j
MeanNetCps = average( NetCps )
TotCps[k] = MeanNetCps + BackgroundCps
--Bodorkos 2017-04-04: next line inserted to force VBA-Java match
TotCps[k] = SigDigStrDbl( TotCps[k], 12 ) --12 sig. digits
Next k
***End If***
--Bodorkos 2017-04-04: next line inserted to force VBA-Java match
BackgroundCps = SigDigStrDbl( BackgroundCps, 12 ) --12 sig. digits