VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
  Persistable = 0  'NotPersistable
  DataBindingBehavior = 0  'vbNone
  DataSourceBehavior  = 0  'vbNone
  MTSTransactionMode  = 0  'NotAnMTSObject
END
Attribute VB_Name = "MeasurementBlocks"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Attribute VB_Ext_KEY = "SavedWithClassBuilder6" ,"Yes"
Attribute VB_Ext_KEY = "Collection" ,"MeasurementBlock"
Attribute VB_Ext_KEY = "Member0" ,"MeasurementBlock"
Attribute VB_Ext_KEY = "Top_Level" ,"Yes"
'local variable to hold collection
Private mCol As Collection

Public Sub Assimilate(blocks As MeasurementBlocks)
    Dim workingBlock As MeasurementBlock
    For Each workingBlock In blocks
        Add workingBlock
    Next workingBlock
End Sub

Public Function Add(ByVal block As MeasurementBlock, Optional sKey As String) As MeasurementBlock
    'create a new object
    
    Dim i As Integer
    Dim objNewMember As MeasurementBlock
    Set objNewMember = New MeasurementBlock
    
    With block
        For i = 1 To 4
            objNewMember.SetSample i, .Sample(i)
            objNewMember.SetHolder i, .Holder(i)
        Next i
        For i = 1 To 2
            objNewMember.SetBaseline i, .Baselines(i)
        Next i
        objNewMember.isUp = .isUp
    End With

    If Len(sKey) = 0 Then
        mCol.Add objNewMember
    Else
        mCol.Add objNewMember, sKey
    End If

    'return the object created
    Set Add = objNewMember
    Set objNewMember = Nothing

End Function

Public Property Get Last() As MeasurementBlock
    Set Last = Item(Count)
End Property

Public Property Get Item(vntIndexKey As Variant) As MeasurementBlock
Attribute Item.VB_UserMemId = 0
    'used when referencing an element in the collection
    'vntIndexKey contains either the Index or Key to the collection,
    'this is why it is declared as a Variant
    'Syntax: Set foo = x.Item(xyz) or Set foo = x.Item(5)
  Set Item = mCol(vntIndexKey)
End Property



Public Property Get Count() As Long
    'used when retrieving the number of elements in the
    'collection. Syntax: Debug.Print x.Count
    Count = mCol.Count
End Property


Public Sub Remove(vntIndexKey As Variant)
    'used when removing an element from the collection
    'vntIndexKey contains either the Index or Key, which is why
    'it is declared as a Variant
    'Syntax: x.Remove(xyz)


    mCol.Remove vntIndexKey
End Sub


Public Property Get NewEnum() As IUnknown
Attribute NewEnum.VB_UserMemId = -4
Attribute NewEnum.VB_MemberFlags = "40"
    'this property allows you to enumerate
    'this collection with the For...Each syntax
    Set NewEnum = mCol.[_NewEnum]
End Property


Private Sub Class_Initialize()
    'creates the collection when this class is created
    Set mCol = New Collection
End Sub


Private Sub Class_Terminate()
    'destroys collection when this class is terminated
    Set mCol = Nothing
End Sub

Public Property Get VectSum() As Cartesian3D
    Dim i As Integer
    Dim cnt As Integer
    Set VectSum = New Cartesian3D
    
    cnt = Count
    If cnt = 0 Then Exit Property
    With VectSum
        For i = 1 To cnt
            .x = .x + Item(i).sum.x
            .y = .y + Item(i).sum.y
            .z = .z + Item(i).sum.z
        Next i
    End With
End Property

Public Property Get VectAvg() As Cartesian3D
    Dim i As Integer
    Dim cnt As Integer
    Dim workingvector As Cartesian3D
    
    Set workingvector = VectSum
    Set VectAvg = New Cartesian3D
    
    cnt = Count * 4
    If cnt = 0 Then Exit Property
    With VectAvg
        .x = workingvector.x / cnt
        .y = workingvector.y / cnt
        .z = workingvector.z / cnt
    End With
    Set workingvector = Nothing
End Property


Public Property Get VectSumSqs() As Cartesian3D
    Dim i As Integer
    Dim cnt As Integer
    Set VectSumSqs = New Cartesian3D
    
    cnt = Count
    If cnt = 0 Then Exit Property
    With VectSumSqs
        For i = 1 To cnt
            .x = .x + Item(i).SumSqs.x
            .y = .y + Item(i).SumSqs.y
            .z = .z + Item(i).SumSqs.z
        Next i
    End With
End Property

Public Property Get VectSumInd() As Cartesian3D
    Dim i As Integer
    Dim cnt As Integer
    Set VectSumInd = New Cartesian3D
    
    cnt = Count
    If cnt = 0 Then Exit Property
    With VectSumInd
        For i = 1 To cnt
            .x = .x + Item(i).induced.x
            .y = .y + Item(i).induced.y
            .z = .z + Item(i).induced.z
        Next i
    End With
End Property

Public Property Get AverageBlock() As MeasurementBlock
    Dim i As Integer, j As Integer
    Dim cnt As Integer
    Dim sumMeasurements(1 To 4) As Cartesian3D
    Dim workingvector As Cartesian3D
    Set AverageBlock = New MeasurementBlock
    
    For j = 1 To 4
        Set sumMeasurements(j) = New Cartesian3D
    Next j
    
    cnt = Count
    If cnt = 0 Then Exit Property
    For i = 1 To cnt
            For j = 1 To 4
                Set workingvector = Item(i).BaselineAdjustedSample(j)
                With sumMeasurements(j)
                    .x = .x + workingvector.x
                    .y = .y + workingvector.y
                    .z = .z + workingvector.z
                End With
                Set workingvector = Nothing
            Next j
    Next i
    
    
    For i = 1 To 4
        With sumMeasurements(i)
            .x = .x / cnt
            .y = .y / cnt
            .z = .z / cnt
        End With
        AverageBlock.SetSample i, sumMeasurements(i)
    Next i
    
    For j = 1 To 4
        Set sumMeasurements(j) = Nothing
    Next j
End Property

Public Property Get NumMeasurements() As Integer
    NumMeasurements = Count * 4
End Property

Public Property Get VectSD() As Cartesian3D
    ' the standard deviation around each X,Y, & Z components
    
    Dim cnt As Integer
    Dim sumsq As Cartesian3D, sum As Cartesian3D
    Set VectSD = New Cartesian3D
    
    cnt = Count * 4
    If cnt = 0 Then Exit Property
    
    Set sumsq = VectSumSqs
    Set sum = VectSum
    
    With VectSD
        .x = Sqr(Abs((sumsq.x * cnt - sum.x ^ 2) _
                    / (cnt * (cnt - 1))))
        .y = Sqr(Abs((sumsq.y * cnt - sum.y ^ 2) _
                    / (cnt * (cnt - 1))))
        .z = Sqr(Abs((sumsq.z * cnt - sum.z ^ 2) _
                    / (cnt * (cnt - 1))))
    End With
    
    Set sumsq = Nothing
    Set sum = Nothing
End Property

Public Property Get VectInd() As Cartesian3D
    Dim i As Integer
    Dim cnt As Integer
    Dim workingvector As Cartesian3D
    
    Set workingvector = VectSumInd
    Set VectInd = New Cartesian3D
    
    cnt = Count
    If cnt = 0 Then Exit Property
    With VectInd
        .x = workingvector.x / cnt
        .y = workingvector.y / cnt
        .z = workingvector.z / cnt
    End With
End Property

Public Property Get DirectionalSubset(isUp As Boolean) As MeasurementBlocks
    Dim i As Integer
    Dim cnt As Integer

    Set DirectionalSubset = New MeasurementBlocks
    cnt = Count
    If cnt = 0 Then Exit Property
    
    For i = 1 To cnt
        If Item(i).isUp = isUp Then
            DirectionalSubset.Add Item(i)
        End If
    Next i
End Property

Public Property Get UpToDown() As Double
    Dim dataUp As MeasurementBlocks, datadown As MeasurementBlocks
    Set dataUp = DirectionalSubset(True)
    Set datadown = DirectionalSubset(False)

    Dim datadownmag As Double
    Dim dataupmag As Double
    
    datadownmag = datadown.VectAvg.mag
    dataupmag = dataUp.VectAvg.mag
    If datadownmag = 0 Then
        UpToDown = 0
        Exit Property
    End If
    UpToDown = dataUp.VectAvg.mag / datadownmag
End Property

Public Property Get ErrorHorizontal() As Double
    Dim dataUp As MeasurementBlocks, datadown As MeasurementBlocks
    Set dataUp = DirectionalSubset(True)
    Set datadown = DirectionalSubset(False)

    If datadown.Count = 0 Or dataUp.Count = 0 Then
        ErrorHorizontal = 0
    Else
        ErrorHorizontal = RadToDeg((atan2(dataUp.VectAvg.x, dataUp.VectAvg.y) - _
            atan2(datadown.VectAvg.x, datadown.VectAvg.y)))
    End If
End Property

Public Property Get HolderFVal() As Double
    Dim cnt As Integer, i As Integer
    cnt = Count
    If cnt = 0 Then Exit Property
    
    For i = 1 To cnt
        HolderFVal = HolderFVal + Item(i).HolderFVal / cnt
    Next i
End Property

Public Property Get MomentVector() As Cartesian3D
    Dim workingvector As Cartesian3D
    Set workingvector = VectAvg
    Set MomentVector = VectAvg
    With MomentVector
        .x = workingvector.x * RangeFact
        .y = workingvector.y * RangeFact
        .z = workingvector.z * RangeFact
    End With
    Set workingvector = Nothing
End Property

Public Property Get Moment() As Double
    Moment = VectAvg.mag * RangeFact
End Property

Public Property Get SigNoise() As Double
    Dim noise As Double
    
    noise = VectSD.mag
    If noise = 0 Then noise = 0.000000001
    SigNoise = VectAvg.mag / noise
End Property

Public Property Get SigInduced() As Double
    Dim induced As Double
    
    induced = VectInd.mag
    If induced = 0 Then induced = 0.000000001
    SigInduced = VectAvg.mag / induced
End Property

Public Property Get SigDrift() As Double
    Dim DriftMag As Double
    Dim cnt As Integer, i As Integer
    
    cnt = Count
    If cnt > 0 Then
        For i = 1 To cnt
            DriftMag = DriftMag + Item(i).driftc.mag / cnt
        Next i
    End If
    
    If DriftMag = 0 Then DriftMag = 0.000000001
    SigDrift = VectAvg.mag / DriftMag
End Property


Public Property Get SigHolder() As Double
    Dim HolderMag As Double
    
    HolderMag = HolderFVal
    If HolderMag = 0 Then HolderMag = 0.000000001
    SigHolder = VectAvg.mag / HolderMag
End Property

Public Property Get Kappa() As Double
    Dim n As Integer
    Dim R As Double
    
    n = Count * 4
    R = ResultantVector.mag
    If n = R Then
        Kappa = 0.000000001
    Else
        Kappa = (n - 1) / (n - R)
    End If
End Property

Public Property Get ResultantVector() As Cartesian3D
    Dim i As Integer
    Dim cnt As Integer
    Dim workingvector As Cartesian3D
    
    Set ResultantVector = New Cartesian3D
    
    cnt = Count
    If cnt = 0 Then Exit Property
    
    For i = 1 To cnt
        Set workingvector = Item(i).SumUnitVectors
        With ResultantVector
            .x = .x + workingvector.x
            .y = .y + workingvector.y
            .z = .z + workingvector.z
        End With
        Set workingvector = Nothing
    Next i
    
End Property

Public Property Get FischerSD() As Double
    ' returns theta-63
    ' this is circular SD from Fischer distribution
    
    FischerSD = 81 / Sqr(Kappa)
End Property

