" & vbCrLf
+ Case gcmRTF
+ ' RTF Mode
+ strRowSuffix = " \par ": blnIncludeSuffixInFinalRow = True
+ strCellSuffix = " \tab "
+ strHighlightPrefix = "{\b\cf1 ": strHighlightSuffix = "}"
+ ' Add the necessary RTF header string to strCopyText
+ strCopyText = "{\rtf1\ansi\deff0\deftab720{\fonttbl{\f0\fswiss MS Sans Serif;}{\f1\froman\fcharset2 Symbol;}{\f2\froman " & "Courier New" & ";}{\f3\froman Times New Roman;}{\f4\fswiss\fprq2 System;}}{\colortbl\red0\green0\blue0;\red255\green0\blue0;\red255\green255\blue255;}\deflang1033\pard\plain\f2\fs" & Trim(Str$(Int(FONT_SIZE * 2))) & " "
+ Case Else
+ ' Includes gcmText: Text mode
+ strCellSuffix = vbTab
+ strRowSuffix = vbCrLf
+ End Select
+
+ frmThisForm.MousePointer = vbHourglass
+
+ With grdThisGrid
+ intRowSaved = .Row
+ intColSaved = .Col
+
+ If intRowStart < 0 Then intRowStart = .Row
+ If intRowEnd < 0 Then intRowEnd = .RowSel
+
+ If intColStart < 0 Then intColStart = .Col
+ If intColEnd < 0 Then intColEnd = .ColSel
+
+ If intRowStart > intRowEnd Then SwapValues intRowStart, intRowEnd
+ If intColStart > intColEnd Then SwapValues intColStart, intColEnd
+
+ If (intRowEnd > intRowStart Or blnIncludeHeaders) And eCopyMode = gcmText Then
+ blnIncludeSuffixInFinalRow = True
+ End If
+
+ If intRowStart = 0 Then
+ ' Headers will automatically be included
+ blnIncludeHeaders = False
+ End If
+
+ ' Copy info, separating cells in a row using tabs, and separating rows by vbCrLf
+ intRowIndex = intRowStart
+ Do While intRowIndex <= intRowEnd
+ If blnIncludeHeaders And Not blnHeadersCopied Then
+ intRowIndex = 0
+ End If
+
+ strCopyText = strCopyText & strRowPrefix
+ For intColIndex = intColStart To intColEnd
+ strCopyText = strCopyText & strCellPrefix
+ If eCopyMode <> gcmText Then
+ ' Check cell back color
+ .Row = intRowIndex: .Col = intColIndex
+ If .CellBackColor > 0 Then
+ blnHighlightCell = True
+ Else
+ blnHighlightCell = False
+ End If
+ End If
+ If blnHighlightCell Then strCopyText = strCopyText & strHighlightPrefix
+
+ strCopyText = strCopyText & .TextMatrix(intRowIndex, intColIndex)
+
+ If blnHighlightCell Then strCopyText = strCopyText & strHighlightSuffix
+
+ If intColIndex < intColEnd Or blnIncludeSuffixInFinalCol Then
+ strCopyText = strCopyText & strCellSuffix
+ End If
+ Next intColIndex
+
+ If blnIncludeHeaders And Not blnHeadersCopied Then
+ intRowIndex = intRowStart - 1
+ If blnIncludeSuffixInFinalRow Then
+ strCopyText = strCopyText & strRowSuffix
+ End If
+ blnHeadersCopied = True
+ Else
+ If intRowIndex < intRowEnd Or blnIncludeSuffixInFinalRow Then
+ strCopyText = strCopyText & strRowSuffix
+ End If
+ End If
+ intRowIndex = intRowIndex + 1
+ Loop
+
+ .Row = intRowSaved
+ .Col = intColSaved
+ End With
+
+ Select Case eCopyMode
+ Case gcmHTML
+ ' Html Mode
+ strCopyText = strCopyText & "
" & vbCrLf
+ lngCopyFormat = vbCFText
+ Case gcmRTF
+ ' RTF Mode
+ strCopyText = strCopyText & " }"
+ lngCopyFormat = vbCFRTF
+ Case Else
+ ' gcmText
+ lngCopyFormat = vbCFText
+ End Select
+
+ On Error Resume Next
+ Clipboard.Clear
+ Clipboard.SetText strCopyText, lngCopyFormat
+
+ FlexGridCopyInfo = strCopyText
+
+ frmThisForm.MousePointer = vbDefault
+
+End Function
+
+Public Sub CopyRoutine(frmCallingForm As VB.Form, blnCalledFromMenu As Boolean)
+ ' If blnCalledFromMenu = true, then need to manually copy
+ ' Otherwise, CTRL+C was pressed and the RTF box already copied the text; must validate it, though
+ Dim strCopyText As String
+
+On Error GoTo CopyRoutineErrorHandler
+
+ If blnCalledFromMenu Then
+ ' Called from menu
+ strCopyText = frmCallingForm.ActiveControl.SelText
+ Else
+ ' Validate copied text; for safety, add a 50 msec delay
+ ' This helps to prevent error code 521 = "Can't open clipboard" from occurring
+ Sleep 50
+ strCopyText = GetClipboardTextSmart()
+ If Len(strCopyText) = 0 Then
+ ' Abort copy; probably couldn't open clipboard
+ Exit Sub
+ End If
+ End If
+
+ RemoveHeightAdjustChar strCopyText
+
+ ' Copy corrected text to Clipboard.
+ Clipboard.Clear
+ Clipboard.SetText strCopyText, vbCFText
+
+ Exit Sub
+
+CopyRoutineErrorHandler:
+ GeneralErrorHandler "MwtWinProcedures|CopyRoutine", Err.Number, Err.Description
+
+End Sub
+
+Public Sub CutRoutine(frmCallingForm As VB.Form, blnCalledFromMenu As Boolean)
+ CopyRoutine frmCallingForm, blnCalledFromMenu
+
+ ' If called from a menu, then manually need to clear the selected text
+ ' If called by the user pressing Ctrl+x in the RTF box, then selected text is automatically cleared
+ If blnCalledFromMenu Then
+ frmCallingForm.ActiveControl.SelText = ""
+ End If
+
+End Sub
+
+Public Function DetermineMaxAllowableFormulaIndex() As Integer
+ Dim intMaxAllowableFormulaIndex As Integer
+
+ ' The following table shows the ideal number of formulas to show for standard resolutions:
+ ' 640x480 6
+ ' 800x600 8
+ ' 1024x768 11
+ ' 1152x864 13
+ ' 1280x960 15
+ ' 1280x1024 17
+ ' 1600x1200 20
+ '
+ ' I plotted Screen.Height / 15 vs. the above desired values to obtain the
+ ' equation used to compute intMaxAllowableFormulaIndex
+
+ intMaxAllowableFormulaIndex = Round((Screen.Height / 15) * 0.0199 - 3.8675, 0)
+ If intMaxAllowableFormulaIndex < 6 Then
+ intMaxAllowableFormulaIndex = 6
+ End If
+
+ DetermineMaxAllowableFormulaIndex = intMaxAllowableFormulaIndex
+
+End Function
+
+Public Sub DisplayCurrentFormulaOnSubForm(frmThisForm As VB.Form)
+ ' Used by frmCapillaryCalcs and frmMMConvert
+
+ Dim intEqualLoc As Integer
+
+ With frmThisForm
+ .lblFormula.Caption = LookupLanguageCaption(7460, "Current formula is") & ":"
+ .rtfCurrentFormula.TextRTF = frmMain.rtfFormula(frmMain.GetCurrentFormulaIndex).TextRTF
+ .lblMWTValue.Caption = frmMain.txtMWT(frmMain.GetCurrentFormulaIndex).Text
+ intEqualLoc = InStr(.lblMWTValue.Caption, "=")
+ If intEqualLoc > 0 Then
+ .lblMWTValue.Caption = Mid(.lblMWTValue.Caption, intEqualLoc + 1)
+ intEqualLoc = InStr(.lblMWTValue.Caption, "(")
+ If intEqualLoc > 0 Then
+ .lblMWTValue.Caption = Left(.lblMWTValue.Caption, intEqualLoc - 1)
+ End If
+ .lblMWTValue.Caption = CStr(CDblSafe(.lblMWTValue.Caption))
+ End If
+ .lblMWT = LookupLanguageCaption(4040, "MW") & " = "
+ End With
+
+End Sub
+
+Public Sub ExitProgram()
+ Dim eResponse As VbMsgBoxResult
+
+ If frmProgramPreferences.optExitConfirmation(exmEscapeKeyConfirmExit).value = True Or frmProgramPreferences.optExitConfirmation(exmIgnoreEscapeKeyConfirmExit).value = True Then
+ ' Display the dialog box and get user's Response.
+ eResponse = YesNoBox(LookupLanguageCaption(3790, "Are you sure you want quit?"), _
+ LookupLanguageCaption(3795, "Exiting Program"))
+
+ ' Evaluate the user's Response.
+ If eResponse = vbYes Then
+ ' It's good practice to unload the form before ending the program
+ ' Plus, it causes the default settings files to be saved
+ Unload frmMain
+ End If
+ Else
+ ' It's good practice to unload the form before ending the program
+ ' Plus, it causes the default settings files to be saved
+ Unload frmMain
+ End If
+
+End Sub
+
+Public Function FormatMaximumFormulasToShowString(Optional intDesiredMaxIndex As Integer = -1) As String
+
+ If intDesiredMaxIndex = -1 Then
+ With frmProgramPreferences
+ intDesiredMaxIndex = Val(.cboMaximumFormulasToShow.List(.cboMaximumFormulasToShow.ListIndex)) - 1
+ End With
+ End If
+
+ FormatMaximumFormulasToShowString = CStr(intDesiredMaxIndex) & "::" & CStr(Val(frmProgramPreferences.cboMaximumFormulasToShow.List(frmProgramPreferences.cboMaximumFormulasToShow.ListCount - 1)) - 1)
+End Function
+
+Public Function FormatForLocale(strWork As String) As String
+ ' Searches through strWork, changing , to . (if decimal point is .) or . to , (if decimal point is ,)
+
+ Dim strSearchChar As String, strReplaceChar As String, intDecPtLoc As Integer
+
+ If glbDecimalSeparator = "," Then
+ strSearchChar = ".": strReplaceChar = ","
+ Else
+ strSearchChar = ",": strReplaceChar = "."
+ End If
+
+ intDecPtLoc = InStr(strWork, strSearchChar)
+ Do While intDecPtLoc > 0
+ strWork = Left(strWork, intDecPtLoc - 1) & strReplaceChar & Mid(strWork, intDecPtLoc + 1)
+ intDecPtLoc = InStr(strWork, strSearchChar)
+ Loop
+
+ FormatForLocale = strWork
+
+End Function
+
+Public Sub FormatLabel(lblThisLabel As Label, dblNewValue As Double)
+
+ If frmProgramPreferences.optStdDevType(1).value = True Or dblNewValue < 0.0001 Or dblNewValue > 100000 Then
+ ' Use scientific notation
+ lblThisLabel.Caption = Trim(Format(dblNewValue, "0.0###E+00"))
+ Else
+ ' Display result in 0.000 notation rather than exponential
+ lblThisLabel.Caption = Trim(Format(dblNewValue, "#0.0###"))
+ End If
+
+End Sub
+
+Public Sub FormatTextBox(txtThisTextBox As TextBox, dblNewValue As Double)
+
+ If dblNewValue = 0 Then
+ txtThisTextBox.Text = "0"
+ Else
+ If frmProgramPreferences.optStdDevType(1).value = True Or dblNewValue < 0.0001 Or dblNewValue > 100000 Then
+ ' Use scientific notation
+ txtThisTextBox.Text = Format(dblNewValue, "0.0###E+00")
+ Else
+ ' Display result in 0.000 notation rather than exponential
+ txtThisTextBox.Text = Format(dblNewValue, "#0.0#####")
+ End If
+ End If
+
+End Sub
+
+Public Sub GeneralErrorHandler(strSourceForm As String, Optional lngErrorNumber As Long = 0, Optional strErrorDescription As String = "")
+ Dim strMessage As String
+
+ If lngErrorNumber = 6 Then
+ MsgBox LookupMessage(590), vbOKOnly + vbExclamation, LookupMessage(350)
+ Else
+ strMessage = LookupMessage(600) & ": " & strErrorDescription & vbCrLf & _
+ " (" & strSourceForm & " handler, #" & Trim(lngErrorNumber) & ")"
+ strMessage = strMessage & vbCrLf & LookupMessage(605)
+ MsgBox strMessage, vbOKOnly + vbExclamation, LookupMessage(350)
+ End If
+End Sub
+
+Private Sub GetColorAPIDlg(ByVal Ownerhwnd As Long, ThingColor As Long)
+ Dim ChClr As ChooseColorType
+ Dim CustColor(15) As Long
+ Dim I As Integer
+ Dim Res As Long
+
+ For I = 0 To 15
+ CustColor(I) = GetSysColor(I)
+ Next I
+
+ ChClr.lStructSize = Len(ChClr)
+ ChClr.hwndOwner = Ownerhwnd
+ ChClr.rgbResult = ThingColor
+ ChClr.hInstance = 0
+ ChClr.lpCustColors = VarPtr(CustColor(0))
+ ChClr.flags = 0
+ Res = ChooseColor(ChClr)
+ If Res = 1 Then
+ ThingColor = ChClr.rgbResult
+ Else
+ ' return 0 means Canceled, other Error
+ ThingColor = ThingColor
+ End If
+End Sub
+
+Public Sub HideFormShowMain(frmThisForm As VB.Form, Optional PossiblyExitProgram As Boolean = False)
+ Dim boolStartupFormClosed As Boolean
+
+ frmThisForm.Hide
+ frmMain.Visible = True
+ If frmMain.WindowState = vbMinimized Then frmMain.WindowState = vbNormal
+
+ ' If the user has a specific form showing at startup, then exit entire program if user clicks
+ ' the X on the given startup form
+ If PossiblyExitProgram Then
+ If frmProgramPreferences.cboStartupModule.ListIndex > 0 Then
+ boolStartupFormClosed = False
+ ' 0: Main
+ ' 1: Formula Finder
+ ' 2: Capillary Flow Calculator
+ ' 3: Mole/Mass Converter
+ ' 4: Peptide Sequence Fragmentation Modeller
+ ' 5: Amino Acid Notation Converter
+ ' 6: Isotopic Distribution Modeller
+ Select Case frmProgramPreferences.cboStartupModule.ListIndex
+ Case 1: If frmThisForm.Name = "frmFinder" Then boolStartupFormClosed = True
+ Case 2: If frmThisForm.Name = "frmCapillaryCalcs" Then boolStartupFormClosed = True
+ Case 3: If frmThisForm.Name = "frmMMConvert" Then boolStartupFormClosed = True
+ Case 4: If frmThisForm.Name = "frmFragmentationModelling" Then boolStartupFormClosed = True
+ Case 5: If frmThisForm.Name = "frmAminoAcidConverter" Then boolStartupFormClosed = True
+ Case 6: If frmThisForm.Name = "frmIsotopicDistribution" Then boolStartupFormClosed = True
+ Case Else
+ ' A request was given to close a form that cannot be auto-shown at startup
+ ' Do not exit entire program
+ End Select
+
+ If boolStartupFormClosed Then ExitProgram
+ End If
+ End If
+End Sub
+
+Public Sub HighlightOnFocus(ThisControl As TextBox)
+ If cChkBox(frmProgramPreferences.chkHighlightTextFields) Then
+ ThisControl.SelStart = 0
+ ThisControl.SelLength = Len(ThisControl.Text)
+ End If
+ SetMostRecentTextBoxValue ThisControl.Text
+End Sub
+
+Public Sub InitializeGlobalVariables(Optional blnShowDebugPrompts As Boolean = False)
+ Dim intMaxAllowableFormulaIndex As Integer
+
+On Error GoTo InitializeGlobalVariablesErrorHandler
+
+ ' Store program path
+ gCurrentPath = App.Path
+
+ App.HelpFile = App.Path
+ If Right(App.HelpFile, 1) <> "\" Then App.HelpFile = App.HelpFile & "\"
+ App.HelpFile = App.HelpFile & HELP_FILENAME
+
+ gBlnStatusCaution = False ' No caution warnings yet
+ gBlnAccessFilesOnDrive = True ' Allow program to read elements and abbreviations from drive
+ gBlnWriteFilesOnDrive = True ' Allow program to write files to drive
+ gBlnLoadStatusOK = True ' For now, assume the LoadElements and LoadAbbreviations procedures will be successfull
+ gCurrentLanguage = "English" ' Current language
+ gCurrentLanguageFileName = DEFAULT_LANGUAGE_FILENAME
+ gLastFileOpenSaveFolder = App.Path
+ gMWAbbreviation = "MW" ' Abbreviation for Molecular Weight; must be exactly two letters long
+
+ If blnShowDebugPrompts Then MsgBox "Determine decimal point based on locale"
+ glbDecimalSeparator = DetermineDecimalPoint()
+
+ gMaxFormulaIndex = MAX_FORMULAS - 1 ' Max number of formulas (counting the first formula as 0)
+
+ ' Need to make sure Screen is large enough to fit gMaxFormulaIndex formulas in Window
+ ' Make smaller if not big enough
+ intMaxAllowableFormulaIndex = DetermineMaxAllowableFormulaIndex()
+
+ If gMaxFormulaIndex > intMaxAllowableFormulaIndex Then
+ gMaxFormulaIndex = intMaxAllowableFormulaIndex
+ End If
+
+ If blnShowDebugPrompts Then MsgBox "First call to MwtWinDll"
+ ' Make sure the maximum element index defined in MwtWinProcedures matches that in objMwtWin
+ If objMwtWin.GetElementCount <> MAX_ELEMENT_INDEX Then
+ Debug.Assert False
+ If blnShowDebugPrompts Then MsgBox "Error: objMwtWin.GetElementCount returned " & Trim(objMwtWin.GetElementCount) & " rather than " & Trim(MAX_ELEMENT_INDEX)
+ End If
+
+ objMwtWin.BracketsTreatedAsParentheses = False
+ objMwtWin.ShowErrorDialogs = blnShowDebugPrompts
+
+ Exit Sub
+
+InitializeGlobalVariablesErrorHandler:
+ If Err.Number = -2147024770 Or Err.Number = 429 Then
+ MsgBox "Unable to connect to MwtWinDll.Dll -- you probably need to reinstall the application to properly register the file. The MwtwinDll.Dll file is required for program operation, and the program will therefore be terminated.", _
+ vbOKOnly + vbExclamation, "Dll Not found"
+ End
+ Else
+ GeneralErrorHandler "frmFinder|cmdCalculate", Err.Number, Err.Description
+ End If
+
+End Sub
+
+Public Function LookupToolTipLanguageCaption(strCaptionID As String, strDefaultTooltip As String) As String
+ ' ToolTip captions are equal to the CaptionID value plus 1
+ If IsNumeric(strCaptionID) And cChkBox(frmProgramPreferences.chkShowToolTips) Then
+ LookupToolTipLanguageCaption = LookupLanguageCaption(CStr(CLng(strCaptionID) + 1), strDefaultTooltip)
+ Else
+ LookupToolTipLanguageCaption = strDefaultTooltip
+ End If
+End Function
+
+Public Function LookupLanguageCaption(ByVal strCaptionID As String, ByVal strOldCaption As String, Optional ByVal boolMenuItem As Boolean = False, Optional ByVal strMenuControlName As String) As String
+ Dim lngCaptionID As Long, strNewCaption As String, strMenuCaption As String
+
+ If IsNumeric(strCaptionID) Then
+ lngCaptionID = CLng(strCaptionID)
+
+ ' Use lngCaptionID to search grdLanguageStrings for caption
+ strNewCaption = LookupLanguageCaptionInGrid(lngCaptionID, frmStrings.grdLanguageStrings, frmStrings.grdLanguageStringsCrossRef)
+
+ If Len(strNewCaption) = 0 Then
+ ' Caption not found
+ ' If caption is for a Menu then load English version of caption from frmStrings
+ ' Note that Menu id values on frmMain are 1000 to 3599
+ ' while menu ID's on other forms are larger numbers; thus the check for >= 1000 and <= 3599 will only work for frmMain)
+ If (lngCaptionID >= 1000 And lngCaptionID <= 3599 And IsNumeric(strOldCaption)) Or boolMenuItem Then
+ strMenuCaption = LookupMenuCaption(lngCaptionID, strMenuControlName)
+ If strMenuCaption <> "" Then
+ strNewCaption = strMenuCaption
+ End If
+ Else
+ strNewCaption = strOldCaption
+ End If
+ End If
+ Else
+ If Len(strCaptionID) > 0 And strCaptionID <> "-" And strCaptionID <> "RightClickMenu" Then
+ ' This code should not be reached
+ Debug.Assert False
+ End If
+ strNewCaption = strOldCaption
+ End If
+
+ ' Caption still not found, return strOldCaption
+ LookupLanguageCaption = strNewCaption
+
+End Function
+
+Private Function LookupLanguageCaptionInGrid(lngCaptionID As Long, grdThisLanguageGrid As MSFlexGrid, grdThisLanguageGridCrossRef As MSFlexGrid) As String
+ Dim lngIndex As Long, lngStartRow As Long, lngLookupRow As Long
+ Dim lngNewCaption As String
+
+ If lngCaptionID > 0 Then
+
+ ' The CrossRef grids are lookup tables that contain info on what row in
+ ' grdThisLanguageGrid to start searching for a given lngCaptionID
+ ' For example, ID's between 1000 and 1999 would have lngStartRow =0
+ ' 2000 to 2999 might have lngStartRow = 20
+ ' 3000 to 3999 might have lngStartRow = 50
+ ' etc.
+ ' This way, when searching for a large lngCaptionID (like 20000), we don't start
+ ' searching at row 0 of grdThisLanguageGrid.
+ With grdThisLanguageGridCrossRef
+ ' The lookup row in the CrossRef grid is the integer portion of lngCaptionID/1000
+ ' Must use the Int() function to assure lngCaptionID / 1000 rounds down
+ lngLookupRow = Int(lngCaptionID / 1000) - 1
+ ' Make sure lngLookupRow isn't invalid
+ If lngLookupRow < .Rows Then
+ lngStartRow = grdThisLanguageGridCrossRef.TextMatrix(lngLookupRow, 1)
+ Else
+ ' Most likely the CrossRef grid hasn't been filled yet
+ lngStartRow = 0
+ End If
+ End With
+
+ With grdThisLanguageGrid
+ For lngIndex = lngStartRow To .Rows - 1
+ If IsNumeric(.TextMatrix(lngIndex, 0)) Then
+ If Val(.TextMatrix(lngIndex, 0)) = lngCaptionID Then
+ lngNewCaption = .TextMatrix(lngIndex, 1)
+ Exit For
+ End If
+ End If
+ Next lngIndex
+ End With
+ Else
+ lngNewCaption = ""
+ End If
+
+ LookupLanguageCaptionInGrid = lngNewCaption
+
+End Function
+
+Private Function LookupMenuCaption(lngMenuCaptionID As Long, strMenuControlName As String) As String
+ Dim strMenuCaption As String, lngIndex As Long
+
+ With frmStrings.grdMenuInfo
+ For lngIndex = 0 To .Rows - 1
+ If CLng(.TextMatrix(lngIndex, 0)) = lngMenuCaptionID Or _
+ LCase(.TextMatrix(lngIndex, 1)) = LCase(strMenuControlName) Then
+ strMenuCaption = .TextMatrix(lngIndex, 2)
+ Exit For
+ End If
+ Next lngIndex
+ End With
+
+ LookupMenuCaption = strMenuCaption
+
+End Function
+
+Public Function LookupMessage(lngMessageID As Long, Optional strAppendText As String = "") As String
+ Dim strMessage As String
+
+On Error GoTo LookupMessageErrorHandler
+
+ With objMwtWin
+ strMessage = .GetMessageStatement(lngMessageID, strAppendText)
+
+ ' lngMessageID's 1 and 18 may need to have an addendum added
+ If lngMessageID = 1 Then
+ If frmProgramPreferences.optConvertType(1).value = True Then
+ strMessage = strMessage & " (" & .GetMessageStatement(680) & ")"
+ End If
+ ElseIf lngMessageID = 18 Then
+ If Not cChkBox(frmProgramPreferences.chkBracketsAsParentheses) Then
+ strMessage = strMessage & " (" & .GetMessageStatement(685) & ")"
+ Else
+ strMessage = strMessage & " (" & .GetMessageStatement(690) & ")"
+ End If
+ End If
+ End With
+
+ If Len(strMessage) = 0 Then
+ strMessage = "Unknown error"
+ Debug.Assert False
+ End If
+
+ LookupMessage = strMessage
+ Exit Function
+
+LookupMessageErrorHandler:
+ GeneralErrorHandler "MwtWinProcedures|LookupMessage", Err.Number, Err.Description
+ LookupMessage = "Unknown message"
+
+End Function
+
+Public Sub Main()
+
+ ' Only need this if we don't use the New keyword when declaring objMwtWin
+ ' Set objMwtWin = New MolecularWeightCalculator
+
+ frmMain.Show
+
+ If Not gNonSaveExitApp Then
+ If Not gBlnLoadStatusOK Then
+ frmIntro.cmdOK.SetFocus
+ End If
+ Else
+ If gCommandLineInstructionsDisplayed Then
+ frmMain.Hide
+ Else
+ Unload frmMain
+
+ ' This shouldn't ever get reached, since the program should end when the
+ ' Unload event on frmMain finishes
+ Debug.Assert False
+ Set objMwtWin = Nothing
+ End If
+ End If
+End Sub
+
+Public Sub MemoryLoadAllStringConstants()
+ ' Load Menu captions and codes into frmStrings
+ MemoryLoadMenuCaptions
+
+End Sub
+
+Private Sub MemoryLoadMenuCaptions()
+ With frmStrings
+ With .grdMenuInfo
+ .Clear
+ .Rows = 0
+ .Cols = 3
+ .ColWidth(0) = 650
+ .ColWidth(1) = 2000
+ .ColWidth(2) = 3000
+ End With
+
+ ' Note that we must add the items in order numerically
+ FlexGridAddItems .grdMenuInfo, "1000", "mnuFile", "&File"
+ FlexGridAddItems .grdMenuInfo, "1010", "mnuEditElements", "Edit &Elements Table..."
+ FlexGridAddItems .grdMenuInfo, "1020", "mnuEditAbbrev", "Edit &Abbreviations..."
+ FlexGridAddItems .grdMenuInfo, "1030", "mnuCalculateFile", "&Calculate weights from text file"
+ FlexGridAddItems .grdMenuInfo, "1040", "mnuPrint", "&Print Results..."
+ FlexGridAddItems .grdMenuInfo, "1050", "mnuExit", "E&xit..."
+ FlexGridAddItems .grdMenuInfo, "1500", "mnuEdit", "&Edit"
+ FlexGridAddItems .grdMenuInfo, "1500", "mnuRightClick", "Right Click Menu" ' This menu is hidden, so its caption doesn't matter; I'll use the Edit menu's menu code here
+ FlexGridAddItems .grdMenuInfo, "1505", "mnuRightClickUndo", "&Undo"
+ FlexGridAddItems .grdMenuInfo, "1510", "mnuCut", "Cu&t"
+ FlexGridAddItems .grdMenuInfo, "1510", "mnuRightClickCut", "Cu&t" ' Duplicate of 1510 above
+ FlexGridAddItems .grdMenuInfo, "1520", "mnuCopy", "&Copy"
+ FlexGridAddItems .grdMenuInfo, "1520", "mnuRightClickCopy", "&Copy" ' Duplicate of 1520 above
+ FlexGridAddItems .grdMenuInfo, "1530", "mnuPaste", "&Paste"
+ FlexGridAddItems .grdMenuInfo, "1530", "mnuRightClickPaste", "&Paste" ' Duplicate of 1530 above
+ FlexGridAddItems .grdMenuInfo, "1540", "mnuDelete", "&Delete"
+ FlexGridAddItems .grdMenuInfo, "1540", "mnuRightClickDelete", "&Delete" ' Duplicate of 1540 above
+ FlexGridAddItems .grdMenuInfo, "1545", "mnuRightClickSelectAll", "Select &All"
+ FlexGridAddItems .grdMenuInfo, "1550", "mnuCopyRTF", "Copy Current Formula as &RTF"
+ FlexGridAddItems .grdMenuInfo, "1560", "mnuCopyMWT", "Copy Current &Molecular Weight"
+ FlexGridAddItems .grdMenuInfo, "1570", "mnuCopyPC", "Copy P&ercent Composition Data"
+ FlexGridAddItems .grdMenuInfo, "1580", "mnuCopyCurrent", "Duplicate Current &Formula"
+ FlexGridAddItems .grdMenuInfo, "1590", "mnuEraseAll", "Erase &All Formulas..."
+ FlexGridAddItems .grdMenuInfo, "1600", "mnuEraseCurrent", "Erase Current Formula..."
+ FlexGridAddItems .grdMenuInfo, "1610", "mnuExpandAbbrev", "E&xpand Abbreviations..."
+ FlexGridAddItems .grdMenuInfo, "1620", "mnuEmpirical", "Convert to Empirical F&ormula..."
+ FlexGridAddItems .grdMenuInfo, "2000", "mnuView", "&View"
+ FlexGridAddItems .grdMenuInfo, "2010", "mnuViewType", "&Multi View"
+ FlexGridAddItems .grdMenuInfo, "2020", "mnuViewType", "&Single View"
+ FlexGridAddItems .grdMenuInfo, "2030", "mnuPercentSolver", "&Percent Solver"
+ FlexGridAddItems .grdMenuInfo, "2040", "mnuPercentType", "O&ff"
+ FlexGridAddItems .grdMenuInfo, "2050", "mnuPercentType", "&On"
+ FlexGridAddItems .grdMenuInfo, "2500", "mnuTools", "&Tools"
+ FlexGridAddItems .grdMenuInfo, "2510", "mnuMMConvert", "&Mole/Mass Converter..."
+ FlexGridAddItems .grdMenuInfo, "2520", "mnuFinder", "&Formula Finder..."
+ FlexGridAddItems .grdMenuInfo, "2530", "mnuAminoAcidNotationConverter", "&Amino Acid Notation Converter..."
+
+ FlexGridAddItems .grdMenuInfo, "2533", "mnuPeptideSequenceFragmentation", "&Peptide Sequence Fragmentation Modelling..."
+ FlexGridAddItems .grdMenuInfo, "2536", "mnuIsotopicDistribution", "&Isotopic Distribution Modelling..."
+ FlexGridAddItems .grdMenuInfo, "2538", "mnuDisplayIsotopicDistribution", "Show Isotopic &Distribution for Current Formula"
+
+ FlexGridAddItems .grdMenuInfo, "2540", "mnuCalculator", "Math &Calculator..."
+ FlexGridAddItems .grdMenuInfo, "2550", "mnuCapillaryFlow", "Capillar&y Flow Calculator"
+
+ FlexGridAddItems .grdMenuInfo, "3000", "mnuOptions", "&Options"
+ FlexGridAddItems .grdMenuInfo, "3010", "mnuChooseLanguage", "Choose &Language..."
+ FlexGridAddItems .grdMenuInfo, "3020", "mnuProgramOptions", "Change Program &Preferences..."
+ FlexGridAddItems .grdMenuInfo, "3030", "mnuChangeFont", "Change &Formula Font..."
+ FlexGridAddItems .grdMenuInfo, "3040", "mnuStayOnTop", "Stay on &Top"
+ FlexGridAddItems .grdMenuInfo, "3050", "mnuDefaultsOptions", "&Save and Restore Default Values"
+ FlexGridAddItems .grdMenuInfo, "3060", "mnuRestoreValues", "&Restore Default Values and Formulas..."
+ FlexGridAddItems .grdMenuInfo, "3070", "mnuSaveValues", "Save &Values and Formulas Now!"
+ FlexGridAddItems .grdMenuInfo, "3500", "mnuHelp", "&Help"
+ FlexGridAddItems .grdMenuInfo, "3510", "mnuOverview", "&Program Overview"
+ FlexGridAddItems .grdMenuInfo, "3530", "mnuShowTips", "&Show Tool Tips"
+ FlexGridAddItems .grdMenuInfo, "3540", "mnuAbout", "&About MWT..."
+
+ ' frmCapillaryFlow
+ FlexGridAddItems .grdMenuInfo, "7900", "mnuLoadCapValues", "&Load Values"
+ FlexGridAddItems .grdMenuInfo, "7910", "mnuSaveCapValues", "&Save Values"
+ FlexGridAddItems .grdMenuInfo, "7950", "mnuCapillaryFlowHelp", "&Capillary Flow Calculations"
+
+ ' frmFragmentationModelling
+ FlexGridAddItems .grdMenuInfo, "12800", "mnuLoadSequenceInfo", "&Load Sequence Info"
+ FlexGridAddItems .grdMenuInfo, "12810", "mnuSaveSequenceInfo", "&Save Sequence Info"
+ FlexGridAddItems .grdMenuInfo, "12820", "mnuLoadIonList", "Load List of &Ions or .Dta file to Match"
+ FlexGridAddItems .grdMenuInfo, "12830", "mnuClose", "&Close"
+ FlexGridAddItems .grdMenuInfo, "12840", "mnuCopyPredictedIons", "&Copy Predicted Ions"
+ FlexGridAddItems .grdMenuInfo, "12850", "mnuCopyPredictedIonsAsRTF", "Copy Predicted Ions as &RTF"
+ FlexGridAddItems .grdMenuInfo, "12855", "mnuCopyPredictedIonsAsHtml", "Copy Predicted Ions as Html"
+ FlexGridAddItems .grdMenuInfo, "12860", "mnuPasteIonList", "&Paste List of Ions to Match"
+ FlexGridAddItems .grdMenuInfo, "12865", "mnuCopySequenceMW", "Copy Sequence Molecular &Weight"
+ FlexGridAddItems .grdMenuInfo, "12870", "mnuClearMatchIonList", "Clear Match Ion &List"
+ FlexGridAddItems .grdMenuInfo, "12880", "mnuViewMatchIonList", "List of &Ions to Match"
+ FlexGridAddItems .grdMenuInfo, "12900", "mnuShowMassSpectrum", "&Mass Spectrum"
+ FlexGridAddItems .grdMenuInfo, "12910", "mnuUpdateSpectrum", "&Update Spectrum on Change"
+ FlexGridAddItems .grdMenuInfo, "12915", "mnuViewDtaTxtBrowser", "&Dta.Txt File Browser"
+ FlexGridAddItems .grdMenuInfo, "12920", "mnuIonMatchListOptions", "Ion Match List &Options"
+ FlexGridAddItems .grdMenuInfo, "12925", "mnuEditModificationSymbols", "Edit Residue &Modification Symbols"
+ FlexGridAddItems .grdMenuInfo, "12930", "mnuAutoAlign", "&Automatically Align Ions to Match"
+ FlexGridAddItems .grdMenuInfo, "12940", "mnuFragmentationModellingHelp", "&Fragmentation Modelling"
+
+ FlexGridAddItems .grdMenuInfo, "12950", "mnuIonMatchListRightClick", "IonMatchListRightClickMenu" ' This menu is hidden, so its caption doesn't matter; I'll use 12950 here
+ FlexGridAddItems .grdMenuInfo, "12950", "mnuIonMatchListRightClickCopy", "&Copy Selected Ions"
+ FlexGridAddItems .grdMenuInfo, "12860", "mniIonMatchListRightClickPaste", "&Paste List of Ions to Match"
+ FlexGridAddItems .grdMenuInfo, "12960", "mnuIonMatchListRightClickDeleteAll", "&Delete All (Clear list)"
+ FlexGridAddItems .grdMenuInfo, "1545", "mnuIonMatchListRightClickSelectAll", "Select &All"
+
+ ' frmMsPlot
+ FlexGridAddItems .grdMenuInfo, "13100", "mnuExportData", "&Export Data"
+ FlexGridAddItems .grdMenuInfo, "13150", "mnuPlotType", "&Plot Type"
+ FlexGridAddItems .grdMenuInfo, "13160", "mnuPlotTypeSticksToZero", "&Sticks To Zero"
+ FlexGridAddItems .grdMenuInfo, "13170", "mnuPlotTypeGaussianPeaks", "&Gaussian Peaks"
+ FlexGridAddItems .grdMenuInfo, "13180", "mnuSetResolution", "Set Effective &Resolution"
+ FlexGridAddItems .grdMenuInfo, "13190", "mnuGridLinesXAxis", "X Axis Gridlines"
+ FlexGridAddItems .grdMenuInfo, "13200", "mnuGridLinesYAxis", "Y Axis Gridlines"
+ FlexGridAddItems .grdMenuInfo, "13210", "mnuTicks", "&Ticks to label (approx.)"
+ FlexGridAddItems .grdMenuInfo, "13220", "mnuTicksXAxis", "&X Axis"
+ FlexGridAddItems .grdMenuInfo, "13230", "mnuTicksYAxis", "&Y Axis"
+ FlexGridAddItems .grdMenuInfo, "13235", "mnuPlotQuality", "Plot &Quality (affects speed)"
+ FlexGridAddItems .grdMenuInfo, "13240", "mnuGaussianQuality", "&Gaussian Representation Quality"
+ FlexGridAddItems .grdMenuInfo, "13245", "mnuApproximationFactor", "&Approximation Factor"
+ FlexGridAddItems .grdMenuInfo, "13250", "mnuSetRangeX", "Set &X Range"
+ FlexGridAddItems .grdMenuInfo, "13260", "mnuSetRangeY", "Set &Y Range"
+ FlexGridAddItems .grdMenuInfo, "13270", "mnuAutoScaleYAxis", "&Autoscale Y Axis"
+ FlexGridAddItems .grdMenuInfo, "13280", "mnuFixMinimumYAtZero", "&Fix mimimum Y at zero"
+ FlexGridAddItems .grdMenuInfo, "13290", "mnuZoomOutToPrevious", "&Zoom Out to Previous"
+ FlexGridAddItems .grdMenuInfo, "13300", "mnuZoomOutFullScale", "Zoom Out to Show All"
+ FlexGridAddItems .grdMenuInfo, "13310", "mnuCursorMode", "&Cursor Mode"
+ FlexGridAddItems .grdMenuInfo, "13320", "mnuCursorModeZoom", "&Zoom"
+ FlexGridAddItems .grdMenuInfo, "13330", "mnuCursorModeMove", "&Move"
+ FlexGridAddItems .grdMenuInfo, "13340", "mnuShowCurrentPosition", "&Show Current Position"
+ FlexGridAddItems .grdMenuInfo, "13342", "mnuShowLegend", "Show &Legend"
+ FlexGridAddItems .grdMenuInfo, "13345", "mnuResetToDefaults", "Reset to &Default Options"
+ FlexGridAddItems .grdMenuInfo, "13350", "mnuZoomOptions", "&Zoom Box"
+ FlexGridAddItems .grdMenuInfo, "13360", "mnuZoomIn", "Zoom &In"
+ FlexGridAddItems .grdMenuInfo, "13370", "mnuZoomInHorizontal", "Zoom In Horizontal"
+ FlexGridAddItems .grdMenuInfo, "13380", "mnuZoomInVertical", "Zoom In Vertical"
+ FlexGridAddItems .grdMenuInfo, "13390", "mnuZoomOut", "Zoom &Out"
+ FlexGridAddItems .grdMenuInfo, "13400", "mnuZoomOutHorizontal", "Zoom Out Horizontal"
+ FlexGridAddItems .grdMenuInfo, "13410", "mnuZoomOutVertical", "Zoom Out Vertical"
+
+ End With
+End Sub
+
+Public Sub ModSymbolKeyPressHandler(txtThisTextBox As VB.TextBox, ByRef KeyAscii As Integer)
+
+ ' Checks KeyAscii to see if it's valid
+ ' If it isn't, it is set to 0
+
+ ' Valid Mod Symbols are ! # $ % & ' * + ? ^ _ ` ~
+ If Not objMwtWin.IsModSymbol(Chr(KeyAscii)) Then
+
+ Select Case KeyAscii
+ Case 1 ' Ctrl+A -- select entire textbox
+ txtThisTextBox.SelStart = 0
+ txtThisTextBox.SelLength = Len(txtThisTextBox.Text)
+ KeyAscii = 0
+ Case 24, 3, 22 ' Cut, Copy, Paste is allowed
+ Case 26
+ ' Ctrl+Z = Undo
+ KeyAscii = 0
+ txtThisTextBox.Text = GetMostRecentTextBoxValue()
+ Case 8 ' Backspace key is allowed
+ Case 48 To 57 ' Numbers are not allowed ' ToDo: Possibly allow them for side-chains
+ KeyAscii = 0
+ Case 32 ' Spaces are not allowed
+ KeyAscii = 0
+ Case 40 To 41 ' Parentheses are not allowed ' ToDo: Possibly allow them for side-chains
+ KeyAscii = 0
+ Case 43: ' Plus sign is allowed
+ Case 45: ' Negative sign is not allowed
+ KeyAscii = 0
+ Case 44, 46: ' Decimal point (. or ,) is not allowed
+ KeyAscii = 0
+ Case 65 To 90, 97 To 122 ' Characters are not allowed
+ KeyAscii = 0
+ Case 95: ' Underscore is allowed
+ Case Else
+ KeyAscii = 0
+ End Select
+ End If
+
+End Sub
+
+Public Sub PasteRoutine(frmCallingForm As VB.Form, blnCalledFromMenu As Boolean)
+ ' If blnCalledFromMenu = True, then need to manually paste
+ ' Otherwise, CTRL+V was pressed and the RTF box already pasted the text for me
+
+ Dim strPasteText As String
+
+On Error GoTo PasteRoutineErrorHandler
+
+ If blnCalledFromMenu Then
+ ' Place text from Clipboard into active control.
+ If Clipboard.GetFormat(vbCFRTF) Then
+ ' rtf on clipboard
+ strPasteText = GetClipboardTextSmart(vbCFRTF)
+ If TypeOf frmCallingForm.ActiveControl Is RichTextBox Then
+ frmCallingForm.ActiveControl.SelRTF = strPasteText
+ End If
+ Else
+ strPasteText = GetClipboardTextSmart()
+ frmCallingForm.ActiveControl.SelText = strPasteText
+ End If
+ End If
+
+ Exit Sub
+
+PasteRoutineErrorHandler:
+ GeneralErrorHandler "MwtWinProcedures|PasteRoutine", Err.Number, Err.Description
+
+End Sub
+
+Public Sub PopulateComboBox(cboThisComboBox As ComboBox, boolLookupLanguageItems As Boolean, Optional strDefaultItemsToPopulate As String = "", Optional intListIndexToSet As Integer = -1)
+ ' Note: This sub assumes the maximum number of items assigned to a combo box is 30
+
+ Dim intNewListIndex As Integer, intOldListCount As Integer
+ Dim strPotentialItemsToPopulate As String
+ Dim strItemsArray(30) As String, intItemsCount As Integer, intIndex As Integer
+ Dim lngComboBoxID As Long, intSepLoc As Integer
+
+ With cboThisComboBox
+ If intListIndexToSet >= 0 Then
+ intNewListIndex = intListIndexToSet
+ Else
+ intNewListIndex = .ListIndex
+ End If
+ intOldListCount = .ListCount
+
+ If boolLookupLanguageItems Then
+ ' See if the combo box has an ID and see if it's in frmstrings.grdLanguageStrings
+ If IsNumeric(.Tag) Then
+ lngComboBoxID = CLng(.Tag)
+
+ ' Use lngCaptionID to search grdLanguageStrings for caption
+ strPotentialItemsToPopulate = ""
+ strPotentialItemsToPopulate = LookupLanguageCaptionInGrid(lngComboBoxID, frmStrings.grdLanguageStrings, frmStrings.grdLanguageStringsCrossRef)
+ End If
+ End If
+
+ If Len(strPotentialItemsToPopulate) = 0 Then
+ strPotentialItemsToPopulate = strDefaultItemsToPopulate
+ End If
+
+ If Len(strPotentialItemsToPopulate) > 0 Then
+ intSepLoc = InStr(strPotentialItemsToPopulate, "|")
+ If intSepLoc Then
+ Do While intSepLoc > 0
+ intItemsCount = intItemsCount + 1
+ strItemsArray(intItemsCount) = Left(strPotentialItemsToPopulate, intSepLoc - 1)
+ strPotentialItemsToPopulate = Mid(strPotentialItemsToPopulate, intSepLoc + 1)
+ intSepLoc = InStr(strPotentialItemsToPopulate, "|")
+ Loop
+ If Len(strPotentialItemsToPopulate) > 0 Then
+ intItemsCount = intItemsCount + 1
+ strItemsArray(intItemsCount) = strPotentialItemsToPopulate
+ End If
+
+ ' If there were more items in the old list than were found in strPotentialItemsToPopulate,
+ ' then grab items from the old list and add to strItemsArray()
+ Do While intOldListCount > intItemsCount
+ intItemsCount = intItemsCount + 1
+ strItemsArray(intItemsCount) = .List(intItemsCount - 1)
+ Loop
+
+ ' Finally, update the list
+ .Clear
+ For intIndex = 1 To intItemsCount
+ .AddItem (strItemsArray(intIndex))
+ Next intIndex
+ Else
+ ' Item separator (|) not found
+ ' If intOldListCount = 0 or intOldListCount = 1 then update list
+ If intOldListCount <= 1 Then
+ .Clear
+ .AddItem strPotentialItemsToPopulate
+ End If
+ End If
+ If intNewListIndex < .ListCount Then
+ .ListIndex = intNewListIndex
+ End If
+ Else
+ ' Nothing to populate list with
+ End If
+ End With
+End Sub
+
+Public Sub PositionWeightSourceframeControls(frmThisForm As VB.Form)
+
+ With frmThisForm
+ .optWeightSource(0).Top = 0
+ .optWeightSource(0).Left = 0
+ .optWeightSource(1).Top = 260
+ .optWeightSource(1).Left = .optWeightSource(0).Left
+
+ .lblFormula.Top = 720
+ .lblFormula.Left = 120
+ With .rtfCurrentFormula
+ .Top = 600
+ .Left = 1800
+ .Width = 3850
+ .Height = 500
+ End With
+ .lblMWT.Top = 1200
+ .lblMWT.Left = .lblFormula.Left
+
+ .lblCustomMass.Top = .lblFormula.Top
+ .lblCustomMass.Left = .lblFormula.Left
+ .txtCustomMass.Top = .lblCustomMass.Top - 40
+ .txtCustomMass.Left = .rtfCurrentFormula.Left
+ .lblCustomMassUnits.Top = .lblCustomMass.Top
+ .lblCustomMassUnits.Left = .txtCustomMass.Left + .txtCustomMass.Width + 100
+ End With
+End Sub
+
+' Purpose: Called by the Form_Activate function of each form to hide frmMain if .chkHideInactiveForms = vbChecked
+Public Sub PossiblyHideMainWindow()
+ If cChkBox(frmProgramPreferences.chkHideInactiveForms) Then
+ frmMain.Visible = False
+ End If
+End Sub
+
+Public Sub RecalculateAllFormulas(Optional blnSetFocusToCurrentFormula As Boolean = True)
+ Dim intIndex As Integer
+
+ With frmMain
+ ' ReCalculate
+ For intIndex = 0 To frmMain.GetTopFormulaIndex
+ .rtfFormula(intIndex).Tag = FORMULA_CHANGED
+ Next intIndex
+ .Calculate True, True, True, 0, False, False, False, 1, blnSetFocusToCurrentFormula
+ .LabelStatus
+ End With
+
+End Sub
+
+Public Sub QueryUnloadFormHandler(frmThisForm As VB.Form, ByRef boolCancel As Integer, UnloadMode As Integer)
+ If UnloadMode = vbFormControlMenu Then
+ boolCancel = True
+ HideFormShowMain frmThisForm, True
+ End If
+End Sub
+
+Public Sub RaiseLabelStatusError(ThisErrorID As Long)
+ frmMain.lblStatus.ForeColor = QBColor(COLOR_ERR)
+ frmMain.lblStatus.Caption = LookupMessage(ThisErrorID)
+ gBlnErrorPresent = True
+End Sub
+
+Public Sub RemoveHeightAdjustChar(ByRef strText As String)
+ If InStr(strText, RTF_HEIGHT_ADJUSTCHAR) > 0 Then
+ ' Remove the tilde sign
+ strText = Left(strText, InStr(strText, RTF_HEIGHT_ADJUSTCHAR) - 1)
+ End If
+
+End Sub
+
+Public Function RemoveRTFHeightAdjust(rtfText As String, Optional strReplaceText As String = "") As String
+
+ ' Search for tilde signs and get rid of them, replacing "\cf1 ~" with strReplaceText
+ rtfText = Replace(rtfText, "\cf1 " & RTF_HEIGHT_ADJUSTCHAR, strReplaceText)
+
+ If InStr(rtfText, RTF_HEIGHT_ADJUSTCHAR) > 0 Then
+ rtfText = Replace(rtfText, "\cf2 " & RTF_HEIGHT_ADJUSTCHAR, strReplaceText)
+ End If
+
+ RemoveRTFHeightAdjust = rtfText
+
+End Function
+
+Public Sub ResetMenuCaptions(boolResetToText As Boolean)
+ ' If boolResetToText = True then captions are reset to default text
+ ' Otherwise, they are reset to default numeric values
+
+ ' Reset menus on frmMain
+ ResetMenuCaptionsWork frmMain, boolResetToText
+
+ ' Reset on other forms
+ ResetMenuCaptionsWork frmFinder, boolResetToText
+ ResetMenuCaptionsWork frmCalculator, boolResetToText
+ ResetMenuCaptionsWork frmCapillaryCalcs, boolResetToText
+ ResetMenuCaptionsWork frmFragmentationModelling, boolResetToText
+''' ResetMenuCaptionsWork frmMsPlot, boolResetToText
+
+ If boolResetToText = True Then
+ ' Add shortcut keys to menu captions
+ AppendShortcutKeysToMenuCaptions
+ End If
+
+End Sub
+
+Private Sub ResetMenuCaptionsWork(frmThisForm As VB.Form, boolResetToText As Boolean)
+ ' Reset the menu captions to either and ID number (so that an international text value can be loaded)
+ ' or to the default English text
+
+ Dim ctlThisControl As Control
+ Dim intViewTypeChecked As Integer, intPercentTypeChecked As Integer
+ Dim lngIndex As Long, lngOffSet As Long
+ Dim boolReset As Boolean
+
+ ' Note: intViewTypeChecked and intPercentTypeChecked apply to frmMain only
+ intViewTypeChecked = 0
+ intPercentTypeChecked = 0
+ For Each ctlThisControl In frmThisForm.Controls
+ If TypeName(ctlThisControl) = "Menu" Then
+ With frmStrings.grdMenuInfo
+ Select Case ctlThisControl.Name
+ Case "mnuViewType"
+ lngOffSet = intViewTypeChecked * 10
+ intViewTypeChecked = intViewTypeChecked + 1
+ Case "mnuPercentType"
+ lngOffSet = intPercentTypeChecked * 10
+ intPercentTypeChecked = intPercentTypeChecked + 1
+ Case Else
+ lngOffSet = 0
+ End Select
+
+ boolReset = False
+ For lngIndex = 0 To .Rows - 1
+ If .TextMatrix(lngIndex, 1) = ctlThisControl.Name Then
+ boolReset = True
+ If boolResetToText Then
+ ' Reset to text value
+ ctlThisControl.Caption = .TextMatrix(lngIndex + lngOffSet / 10, 2)
+ Else
+ ' Reset to numeric ID
+ ctlThisControl.Caption = CStr(CLng(.TextMatrix(lngIndex, 0)) + lngOffSet)
+ End If
+ Exit For
+ End If
+ Next lngIndex
+
+ ' Unless the menu caption is a dash (which means a separator menu), make sure
+ ' that boolReset = True
+ ' If it isn't, then there probably is not an entry for ctlThisControl.Name in grdMenuInfo
+ ' Need to edit MemoryLoadMenuCaptions
+ If ctlThisControl.Caption <> "-" Then
+ Debug.Assert boolReset
+ End If
+ End With
+ End If
+ Next
+
+End Sub
+
+Public Sub RTFBoxKeyPressHandler(frmCallingForm As VB.Form, ThisRichTextBox As RichTextBox, ByRef KeyAscii As Integer, Optional blnDisplayErrorsInStatusLabel As Boolean = True, Optional blnAllowAminoAcidModSymbols As Boolean = False)
+ Dim blnCharOK As Boolean
+
+ If blnAllowAminoAcidModSymbols Then
+ If objMwtWin.IsModSymbol(Chr(KeyAscii)) Then blnCharOK = True
+ End If
+
+ If Not blnCharOK Then
+ Select Case KeyAscii
+ Case 44, 46
+ Select Case glbDecimalSeparator
+ Case ","
+ If KeyAscii = 46 Then
+ KeyAscii = 0
+ If blnDisplayErrorsInStatusLabel Then RaiseLabelStatusError 94
+ End If
+ Case Else ' includes "."
+ If KeyAscii = 44 Then
+ KeyAscii = 0
+ If blnDisplayErrorsInStatusLabel Then RaiseLabelStatusError 93
+ End If
+ End Select
+ Case 40 To 41, 43, 45, 48 To 57, 62, 65 To 90, 91, 93, 94, 95, 97 To 122, 123, 125
+ ' Valid Characters are:
+ ' ( and ) are 40 and 41 - is 45 + is 43
+ ' { and } are 123 and 125
+ ' Numbers are 48 to 57 . is 46
+ ' Lowercase letters are 97 to 122
+ ' Uppercase letters are 65 to 90
+ ' > is 62
+ ' _ is 95
+ Case 8
+ ' Backspace; it is valid
+ Case 9
+ ' Tab; it is valid
+ Case 32
+ ' Space
+ If blnDisplayErrorsInStatusLabel Then RaiseLabelStatusError 610
+ KeyAscii = 0
+ Case 3
+ ' User pressed CTRL-C (copy)
+ CopyRoutine frmCallingForm, False
+ Case 22
+ ' User pressed CTRL-V (paste)
+ PasteRoutine frmCallingForm, False
+ Case 24
+ ' User pressed CTRL-X (cut)
+ CutRoutine frmCallingForm, False
+ Case 1
+ ' Ctrl+A - rtfTextBox automatically highlights entire box
+ Case 26
+ ' Ctrl+Z - Undo
+ ThisRichTextBox.Text = GetMostRecentTextBoxValue()
+ Case 0
+ ' This is set by Form_KeyDown, we should just ignore the entry
+ Case vbKeyEscape
+ ' Ignore the key if it got this far
+ KeyAscii = 0
+ Case Else
+ ' All other ASCII characters are invalid
+ If blnDisplayErrorsInStatusLabel Then
+ frmMain.lblStatus.ForeColor = QBColor(COLOR_ERR)
+ If KeyAscii >= 1 And KeyAscii <= 26 Then
+ frmMain.lblStatus.Caption = LookupMessage(620) & " Ctrl+" & Chr$(KeyAscii + 64) ' & "#" & Str(keyascii)
+ Else
+ frmMain.lblStatus.Caption = LookupMessage(620) & " " & Chr$(KeyAscii) ' & "#" & Str(keyascii)
+ End If
+ End If
+ KeyAscii = 0
+ End Select
+ End If
+
+End Sub
+
+Public Sub SelectCustomColor(frmCallingForm As VB.Form, lblThisLabel As Label)
+ Dim lngTemporaryColor As Long
+
+ lngTemporaryColor = lblThisLabel.BackColor
+ Call GetColorAPIDlg(frmCallingForm.hwnd, lngTemporaryColor)
+ If lngTemporaryColor >= 0 Then
+ lblThisLabel.BackColor = lngTemporaryColor
+ End If
+
+End Sub
+
+Public Sub SetAllTooltips(Optional blnShowDebugPrompts As Boolean = False)
+ Dim intIndex As Integer
+
+On Error GoTo SetAllTooltipsErrorHandler
+
+ If blnShowDebugPrompts Then MsgBox "Set ToolTips: frmAminoAcidConverter"
+ With frmAminoAcidConverter
+ .txt1LetterSequence.ToolTipText = LookupToolTipLanguageCaption(6030, "Enter sequence using 1 letter abbreviations here")
+ .txt3LetterSequence.ToolTipText = LookupToolTipLanguageCaption(6040, "Enter sequence using 3 letter abbreviations here")
+ End With
+
+ If blnShowDebugPrompts Then MsgBox "Set ToolTips: frmCalculator"
+ With frmCalculator
+ .rtfExpression.ToolTipText = LookupToolTipLanguageCaption(6510, "Enter a mathematical expression to evaluate here")
+ .cmdCalculate.ToolTipText = LookupToolTipLanguageCaption(6520, "Evaluates the current expression")
+ End With
+
+ If blnShowDebugPrompts Then MsgBox "Set ToolTips: frmDiff"
+ frmDiff.cmdCopy.ToolTipText = LookupToolTipLanguageCaption(8610, "Copies the results to the clipboard")
+
+ If blnShowDebugPrompts Then MsgBox "Set ToolTips: frmEditElem"
+ With frmEditElem
+ .cmdReset.ToolTipText = LookupToolTipLanguageCaption(9210, "Resets elemental weights to their average weights")
+ .cmdAverageMass.ToolTipText = LookupToolTipLanguageCaption(9230, "Sets all elemental weights to their average weights found in nature")
+ .cmdIsotopicMass.ToolTipText = LookupToolTipLanguageCaption(9240, "Sets all elemental weights to the weight of the element's most common isotope (for high resolution mass spectrometry)")
+ .cmdIntegerMass.ToolTipText = LookupToolTipLanguageCaption(9245, "Sets all elemental weights to the nominal integer weight of the element's most common isotope (for low resolution mass spectrometry)")
+ .grdElem.ToolTipText = LookupToolTipLanguageCaption(9340, "Click to change an element's weight or uncertainty")
+ End With
+
+ If blnShowDebugPrompts Then MsgBox "Set ToolTips: frmEditAbbrev"
+ With frmEditAbbrev
+ .cmdReset.ToolTipText = LookupToolTipLanguageCaption(9010, "Resets the abbreviations to the program defaults")
+ .grdAmino.ToolTipText = LookupToolTipLanguageCaption(9140, "Click to change an abbreviation")
+ .grdNormal.ToolTipText = LookupToolTipLanguageCaption(9140, "Click to change an abbreviation")
+ End With
+
+ If blnShowDebugPrompts Then MsgBox "Set ToolTips: frmFinder"
+ With frmFinder
+ .txtHits.ToolTipText = LookupToolTipLanguageCaption(10240, "Maximum number of target compounds to find")
+ .txtWeightTolerance.ToolTipText = LookupToolTipLanguageCaption(10220, "Amount that target compound's weight can be from the target weight")
+ .txtPercentTolerance.ToolTipText = LookupToolTipLanguageCaption(10230, "Amount that elemental percent compositions can be from the target percentage")
+ .cmdCalculate.ToolTipText = LookupToolTipLanguageCaption(10310, "Find the compounds that match the specified parameters")
+ .cmdCopyAsRTF.ToolTipText = LookupToolTipLanguageCaption(10330, "Copy results to clipboard in Rich Text Format")
+ .cmdCopy.ToolTipText = LookupToolTipLanguageCaption(10340, "Copy results to clipboard")
+ .cmdDisplayIsotopicAbundance.ToolTipText = LookupToolTipLanguageCaption(10345, "Display the Isotopic Distribution of the currently selected compound (Ctrl+D)")
+ .cmdFinderOptions.ToolTipText = LookupToolTipLanguageCaption(10300, "Shortcut: Ctrl+O")
+ For intIndex = 0 To 9
+ .txtMin(intIndex).ToolTipText = LookupToolTipLanguageCaption(10250, "Minimum number of atoms in target compound") & _
+ " (" & .chkElements(intIndex).Caption & ")"
+ .txtMax(intIndex).ToolTipText = LookupToolTipLanguageCaption(10255, "Maximum number of atoms in target compound") & _
+ " (" & .chkElements(intIndex).Caption & ")"
+ .txtPercent(intIndex).ToolTipText = LookupToolTipLanguageCaption(10260, "Percent composition of target compound that is") & _
+ " " & .chkElements(intIndex).Caption
+ Next intIndex
+ For intIndex = 4 To 9
+ .txtWeight(intIndex).ToolTipText = LookupToolTipLanguageCaption(10270, "Type a weight for the custom element, an elemental symbol, or an abbreviation")
+ Next intIndex
+ End With
+
+ If blnShowDebugPrompts Then MsgBox "Set ToolTips: frmFinderOptions"
+ With frmFinderOptions
+ .chkFindCharge.ToolTipText = LookupToolTipLanguageCaption(10900, "Compute the overall charge of each compound found")
+ .chkLimitChargeRange.ToolTipText = LookupToolTipLanguageCaption(10910, "Limit the displayed compounds to a specific charge range")
+ .chkFindMtoZ.ToolTipText = LookupToolTipLanguageCaption(10920, "Compute the mass to charge ratio for each compound found")
+ .chkFindTargetMtoZ.ToolTipText = LookupToolTipLanguageCaption(10930, "Find compounds with m/z values equivalent to the target")
+ .chkSort.ToolTipText = LookupToolTipLanguageCaption(10940, "Convert results to empirical formulas and sort them")
+ .chkVerifyHydrogens.ToolTipText = LookupToolTipLanguageCaption(10950, "Limit number of hydrogen atoms in found compounds to a realistic number")
+ .chkAutoSetBounds.ToolTipText = LookupToolTipLanguageCaption(10960, "Automatically adjust the Min and Max search values to a valid range for the given target weight")
+ .txtChargeMin.ToolTipText = LookupToolTipLanguageCaption(10820, "Minimum charge to limit compounds to")
+ .txtChargeMax.ToolTipText = LookupToolTipLanguageCaption(10830, "Maximum charge to limit compounds to")
+ .cboSearchType.ToolTipText = LookupToolTipLanguageCaption(10840, "A thorough search finds all matching compounds while a bounded search finds compounds within a specific atomic range (thorough is usually faster).")
+ .cboSortResults.ToolTipText = LookupToolTipLanguageCaption(10850, "Method to sort results. Re-calculate to re-sort.")
+ End With
+
+ If blnShowDebugPrompts Then MsgBox "Set ToolTips: frmMain"
+ With frmMain
+ .rtfFormulaSingle.ToolTipText = LookupToolTipLanguageCaption(5050, "Type the molecular formula here")
+ .grdPC.ToolTipText = LookupToolTipLanguageCaption(5200, "Click to set or reset a target value")
+ .cmdNewFormula.ToolTipText = ConstructAddFormulaToolTip
+ .cmdCalculate.ToolTipText = LookupToolTipLanguageCaption(5100, "Determines the molecular weight of the current formula")
+ .lblStatus.ToolTipText = LookupToolTipLanguageCaption(5300, "Double click the status line to expand it")
+ For intIndex = 0 To frmMain.GetTopFormulaIndex
+ .rtfFormula(intIndex).ToolTipText = LookupToolTipLanguageCaption(5050, "Type the molecular formula here")
+ Next intIndex
+ .optElementMode(0).ToolTipText = LookupToolTipLanguageCaption(5020, "Use average weights of elements")
+ .optElementMode(1).ToolTipText = LookupToolTipLanguageCaption(5030, "Use weight of most common isotope")
+ .optElementMode(2).ToolTipText = LookupToolTipLanguageCaption(5040, "Use nominal integer weight of most common isotope")
+ End With
+
+ If blnShowDebugPrompts Then MsgBox "Set ToolTips: frmMMConvert"
+ With frmMMConvert
+ .cboAction.ToolTipText = LookupToolTipLanguageCaption(11010, "Perform conversions between different amounts of compound or perform molarity-related calculations")
+ .SetDynamicToolTips
+ .txtCustomMass.ToolTipText = LookupToolTipLanguageCaption(7600, "Enter custom numerical mass for use in computations")
+ .cmdFindAmount.ToolTipText = LookupToolTipLanguageCaption(11150, "Calculate the amount using the volume and molarity")
+ .cmdFindVolume.ToolTipText = LookupToolTipLanguageCaption(11160, "Calculate the volume using the amount and molarity")
+ .cmdFindConcentration.ToolTipText = LookupToolTipLanguageCaption(11170, "Calculate the concentration using the amount and volume")
+ .txtDensity.ToolTipText = LookupToolTipLanguageCaption(11110, "Density of the compound")
+ ' Note: cboTo has .Tag = 11020 so that combo box elements match cboFrom
+ ' However, its .ToolTipText phrase is stored in 11041, thus we use 11040 in the next statement
+ .cboTo.ToolTipText = LookupToolTipLanguageCaption(11040, "Units of amount to convert to")
+ .txtVolume.ToolTipText = LookupToolTipLanguageCaption(11120, "Volume of solvent the compound is dissolved in")
+ .cboVolume.ToolTipText = LookupToolTipLanguageCaption(11030, "Units of volume")
+ .txtConcentration.ToolTipText = LookupToolTipLanguageCaption(11130, "Concentration of compound in the solvent")
+ .cboConcentration.ToolTipText = LookupToolTipLanguageCaption(11050, "Units of concentration")
+
+ .cboDilutionMode.ToolTipText = LookupToolTipLanguageCaption(11210, "Quantity to find for dilution calculations")
+ .chkLinkMolarities.ToolTipText = LookupToolTipLanguageCaption(11220, "Copy the Computed Concentration for converting amounts to the Initial Concentration for dilutions and vice versa if either changes")
+ .chkLinkDilutionVolumeUnits.ToolTipText = LookupToolTipLanguageCaption(11230, "Synchronize the units for the Volume of Stock, Volume of Solvent, and Final Total Volume")
+
+ .txtDilutionConcentrationInitial.ToolTipText = LookupToolTipLanguageCaption(11255, "Concentration of solute in stock solution")
+ .txtStockSolutionVolume.ToolTipText = LookupToolTipLanguageCaption(11265, "Volume (aliquot) of stock solution to remove when performing dilution")
+ .txtDilutionConcentrationFinal.ToolTipText = LookupToolTipLanguageCaption(11275, "Concentration of solute in final solution following dilution")
+ .txtDilutingSolventVolume.ToolTipText = LookupToolTipLanguageCaption(11285, "Volume of solvent to mix with the stock solution (aliquot) removed for dilution")
+ .txtTotalVolume.ToolTipText = LookupToolTipLanguageCaption(11295, "Total volume of the final solution following mixing of stock and diluting solvent")
+ End With
+
+ If blnShowDebugPrompts Then MsgBox "Set ToolTips: frmProgramPreferences"
+ With frmProgramPreferences
+ .optAbbrevType(0).ToolTipText = LookupToolTipLanguageCaption(11650, "Recognize normal abbreviations, but not amino acids")
+ .optAbbrevType(1).ToolTipText = LookupToolTipLanguageCaption(11655, "Recognize normal abbreviations and amino acids")
+ .optAbbrevType(2).ToolTipText = LookupToolTipLanguageCaption(11660, "Ignore all abbreviations")
+ .optConvertType(0).ToolTipText = LookupToolTipLanguageCaption(11665, "Correctly capitalize formulas while parsing")
+ .optConvertType(1).ToolTipText = LookupToolTipLanguageCaption(11670, "Require user to type formulas with correct capitalization")
+ .optConvertType(2).ToolTipText = LookupToolTipLanguageCaption(11675, "Interpret lowercase formulas, and do not capitalize them")
+ .optStdDevType(0).ToolTipText = LookupToolTipLanguageCaption(11680, "Display standard deviations in abbreviated form")
+ .optStdDevType(1).ToolTipText = LookupToolTipLanguageCaption(11685, "Display standard deviations in scientific notation")
+ .optStdDevType(2).ToolTipText = LookupToolTipLanguageCaption(11690, "Display standard deviations in long decimal form")
+ .optStdDevType(3).ToolTipText = LookupToolTipLanguageCaption(11695, "Do not display standard deviations")
+ For intIndex = 0 To 3
+ .optExitConfirmation(intIndex).ToolTipText = LookupToolTipLanguageCaption(11700, "Determines if the escape key exits program and whether to confirm program exit")
+ Next intIndex
+ .chkAdvanceOnCalculate.ToolTipText = LookupToolTipLanguageCaption(11750, "Move to a new formula line after calculating a formula's weight")
+ .chkBracketsAsParentheses.ToolTipText = LookupToolTipLanguageCaption(11760, "Treat brackets, [ and ], as parentheses, rather than as percent solver placeholders")
+ .chkAutoCopyCurrentMWT.ToolTipText = LookupToolTipLanguageCaption(11770, "Automatically copy the selected formula's molecular weight value to the clipboard after each calculation")
+ .chkComputeCharge.ToolTipText = LookupToolTipLanguageCaption(11780, "Compute charge of compounds (very basic rules, cannot correct for double or triple bonds, etc.)")
+ .chkAlwaysSwitchToIsotopic.ToolTipText = LookupToolTipLanguageCaption(11800, "Switch to isotopic weights automatically upon entering the formula finder or peptide fragmentation module")
+ .chkNeverShowFormulaFinderWarning.ToolTipText = LookupToolTipLanguageCaption(11810, "Never prompt about current weight mode when entering the formula finder or peptide fragmentation module")
+ .chkAutosaveValues.ToolTipText = LookupToolTipLanguageCaption(11820, "Automatically save options, values, and formulas on program exit")
+ .chkShowCaution.ToolTipText = LookupToolTipLanguageCaption(11830, "Caution when possibly confusing elemental combinations are in formulas (like Co vs. CO)")
+ .chkShowQuickSwitch.ToolTipText = LookupToolTipLanguageCaption(11840, "Show option to quickly change elemental weight modes")
+ .chkShowToolTips.ToolTipText = LookupToolTipLanguageCaption(11850, "Show short help messages when mouse passes over certain buttons and areas")
+ .chkHighlightTextFields.ToolTipText = LookupToolTipLanguageCaption(11860, "Highlight the entire text field when moving to it")
+ .chkHideInactiveForms.ToolTipText = LookupToolTipLanguageCaption(11870, "Hide the main program window when using the Formula Finder, Mole/Mass calculator, etc.")
+ .cboStartupModule.ToolTipText = LookupToolTipLanguageCaption(11895, "Module to show when program starts")
+ .cboMaximumFormulasToShow.ToolTipText = LookupToolTipLanguageCaption(11880, "Choose a smaller number to prevent the formula window from filling the screen. If lowering, must exit and restart program before takes effect. Maximum is dependent upon screen resolution.")
+ End With
+
+ If blnShowDebugPrompts Then MsgBox "Set ToolTips: frmCapillaryCalcs"
+ With frmCapillaryCalcs
+ .cboCapillaryType.ToolTipText = LookupToolTipLanguageCaption(7010, "Toggle between open and packed capillaries")
+ .txtCapValue(cctViscosity).ToolTipText = LookupToolTipLanguageCaption(7850, "Typical viscosity value is 0.0089 poise")
+ .txtCapValue(cctPorosity).ToolTipText = LookupToolTipLanguageCaption(7860, "Typical porosity value is 0.4")
+ .txtCapValue(cctBdDiffusionCoefficient).ToolTipText = LookupToolTipLanguageCaption(7870, "Typical diffusion coefficient for small organics is 0.00001, i.e. 1E-5; Typical value for peptides is 0.000005, i.e. 5E-6")
+ .txtCustomMass.ToolTipText = LookupToolTipLanguageCaption(7600, "Enter custom numerical mass for use in computations")
+ End With
+
+ If blnShowDebugPrompts Then MsgBox "Set ToolTips: frmFragmentationModelling"
+ With frmFragmentationModelling
+ .cboNotation.ToolTipText = LookupToolTipLanguageCaption(12010, "Amino acid sequence notation type")
+ .txtSequence.ToolTipText = LookupToolTipLanguageCaption(12050, "Enter amino acid sequence here")
+ .txtAlignment.ToolTipText = LookupToolTipLanguageCaption(12060, "Shifts the loaded ions to be matched by the given amount to correct for post-translational modifications.")
+ .lstIonsToModify.ToolTipText = LookupToolTipLanguageCaption(12235, "Choose ions to which losses will be applied")
+ .cboDoubleCharge.ToolTipText = LookupToolTipLanguageCaption(12285, "The 2+ m/z value will be computed for ions above this m/z")
+ End With
+
+ If blnShowDebugPrompts Then MsgBox "Set ToolTips: frmFragmentationModelling"
+ With frmIonMatchOptions
+ .lblFragSpectrumColor.ToolTipText = LookupToolTipLanguageCaption(14257, "Click to change")
+ .lblMatchingIonDataColor.ToolTipText = LookupToolTipLanguageCaption(14257, "Click to change")
+ End With
+
+ If blnShowDebugPrompts Then MsgBox "Set ToolTips: frmAminoAcidModificationSymbols"
+ With frmAminoAcidModificationSymbols
+ .grdModSymbols.ToolTipText = LookupToolTipLanguageCaption(15100, "Click to change a modification symbol")
+ .cmdReset.ToolTipText = LookupToolTipLanguageCaption(15300, "Resets modification symbols to defaults")
+ End With
+
+ If blnShowDebugPrompts Then MsgBox "Set ToolTips: frmDtaTxtFileBrowser"
+ With frmDtaTxtFileBrowser
+ .cmdJumpToScan.ToolTipText = LookupToolTipLanguageCaption(16100, "Shortcut is Ctrl+J")
+ End With
+
+ If blnShowDebugPrompts Then MsgBox "Set ToolTips: frmIsotopicDistribution"
+ With frmIsotopicDistribution
+ .lblPlotColor.ToolTipText = LookupToolTipLanguageCaption(15125, "Click to change")
+ .lblComparisonListPlotColor.ToolTipText = LookupToolTipLanguageCaption(15125, "Click to change")
+ .txtResults.ToolTipText = LookupToolTipLanguageCaption(15150, "Isotopic distribution results")
+ End With
+
+ Exit Sub
+
+SetAllTooltipsErrorHandler:
+ GeneralErrorHandler "MwtWinProcedures|SetAllTooltips", Err.Number, Err.Description
+
+End Sub
+
+Public Sub SetDefaultOptions()
+
+On Error GoTo SetDefaultsErrorHandler
+
+ With frmMain
+ .SetViewMode vmdMultiView
+ .ShowHideQuickSwitch vbChecked
+ End With
+
+ With frmProgramPreferences
+ .optConvertType(0).value = True
+ .optAbbrevType(1).value = True
+ .optStdDevType(0).value = True
+ gBlnShowStdDevWithMass = True
+
+ .chkShowCaution.value = vbChecked
+ .chkAdvanceOnCalculate.value = vbUnchecked
+ .chkComputeCharge.value = vbUnchecked
+ .chkShowQuickSwitch.value = vbChecked
+
+ SetFonts "Arial", 10
+
+ .optExitConfirmation(exmEscapeKeyConfirmExit).value = True
+ .chkShowToolTips.value = vbChecked
+ .chkHideInactiveForms.value = vbUnchecked
+ .chkAutosaveValues.value = vbChecked
+ .chkBracketsAsParentheses = vbUnchecked
+ .chkAutoCopyCurrentMWT.value = vbUnchecked
+
+ .cboStartupModule.ListIndex = 0
+ .cboMaximumFormulasToShow = "9"
+
+ .chkAlwaysSwitchToIsotopic.value = vbUnchecked
+ .chkNeverShowFormulaFinderWarning.value = vbUnchecked
+
+ .chkHighlightTextFields = vbUnchecked
+ End With
+
+ frmFinderOptions.cboSearchType.ListIndex = 0
+
+ Exit Sub
+
+SetDefaultsErrorHandler:
+ GeneralErrorHandler "MwtWinProcedures|SetDefaults", Err.Number, Err.Description
+ Resume Next
+
+End Sub
+
+Private Sub SetDefaultCapillaryFlowValues()
+
+ gCapFlowComputationTypeSave = 3 ' cptVolFlowRate = 3
+ gCapFlowLinkMassRateFlowRateSave = 1 ' Link Flow Rate
+ gCapFlowLinkBdLinearVelocitySave = 1 ' Link Linear Velocity
+ gCapFlowShowPeakBroadeningSave = 0 ' Hide the peak broadening screen
+
+ OpenCapVals.TextValues(cctPressure) = 50 ' Pressure
+ OpenCapVals.ComboValues(cccPressureUnits) = uprPsi ' Pressure Units
+ OpenCapVals.TextValues(cctColumnLength) = 50 ' Col Length
+ OpenCapVals.ComboValues(cccColumnLengthUnits) = ulnCM ' Col Length
+ OpenCapVals.TextValues(cctColumnID) = 30 ' Col ID
+ OpenCapVals.ComboValues(cccColumnIDUnits) = ulnMicrons ' Column Inner Diameter Units
+ OpenCapVals.TextValues(cctViscosity) = 0.0089 ' Viscosity
+ OpenCapVals.ComboValues(cccViscosityUnits) = uviPoise ' Viscosity Units
+ OpenCapVals.TextValues(cctParticleDiamter) = 5 ' Particle Diameter
+ OpenCapVals.ComboValues(cccParticleDiameterUnits) = ulnMicrons ' Particle Diameter Units
+ OpenCapVals.TextValues(cctFlowRate) = 100 ' Flow Rate
+ OpenCapVals.ComboValues(cccFlowRateUnits) = ufrNLPerMin ' Flow Rate Units
+ OpenCapVals.ComboValues(cccLinearVelocityUnits) = ulvCmPerSec ' Linear Velocity Units
+ OpenCapVals.TextValues(cctDeadTime) = 1 ' Dead time
+ OpenCapVals.ComboValues(cccDeadTimeUnits) = utmSeconds ' Dead Time Units
+ OpenCapVals.TextValues(cctPorosity) = 0.4 ' Porosity
+ OpenCapVals.ComboValues(cccVolumeUnits) = uvoNL ' Volume Units
+
+ OpenCapVals.TextValues(cctMassRateConcentration) = 1 ' Concentration
+ OpenCapVals.ComboValues(cccMassRateConcentrationUnits) = ucoMicroMolar ' Concentration Units
+ OpenCapVals.TextValues(cctMassRateVolFlowRate) = 100 ' MassRateVolFlowRate
+ OpenCapVals.ComboValues(cccMassRateVolFlowRateUnits) = ufrNLPerMin ' MassRateVolFlowRate Units
+ OpenCapVals.TextValues(cctMassRateInjectionTime) = 30 ' Injection Time
+ OpenCapVals.ComboValues(cccMassRateInjectionTimeUnits) = utmSeconds ' Injection Time Units
+ OpenCapVals.ComboValues(cccMassFlowRateUnits) = umfFmolPerSec ' Mass Flow Rate
+ OpenCapVals.ComboValues(cccMassRateMolesInjectedUnits) = umaFemtoMoles ' Moles Injected Units
+
+ OpenCapVals.TextValues(cctBdLinearVelocity) = 1 ' Broadening Linear velocity
+ OpenCapVals.ComboValues(cccBdLinearVelocityUnits) = ulvCmPerSec ' Broadening Linear Velocity Units
+ OpenCapVals.TextValues(cctBdDiffusionCoefficient) = 0.000005 ' Broadening diffusion coefficient
+ OpenCapVals.TextValues(cctBdOpenTubeLength) = 5 ' Open Tube Length
+ OpenCapVals.ComboValues(cccBdOpenTubeLengthUnits) = ulnCM ' Open Tube Col Length
+ OpenCapVals.TextValues(cctBdOpenTubeID) = 50 ' Open Tube Inner Diameter
+ OpenCapVals.ComboValues(cccBdOpenTubeIDUnits) = ulnMicrons ' Open Tube Inner Diameter Units
+ OpenCapVals.TextValues(cctBdInitialPeakWidth) = 30 ' Initial Peak Width
+ OpenCapVals.ComboValues(cccBdInitialPeakWidthUnits) = utmSeconds ' Initial Peak Width
+ OpenCapVals.TextValues(cctBdAdditionalVariance) = 0 ' Additional Variance (in square seconds)
+ OpenCapVals.ComboValues(cccBdResultantPeakWidthUnits) = utmSeconds ' Resultant Peak Width Units
+
+ ' Most of the packed capillary values are identical to the open capillary values
+ '
+ PackedCapVals.TextValues(cctPressure) = 3000 ' Pressure
+ PackedCapVals.ComboValues(cccPressureUnits) = OpenCapVals.ComboValues(cccPressureUnits)
+ PackedCapVals.TextValues(cctColumnLength) = 50 ' Column Length
+ PackedCapVals.ComboValues(cccColumnLengthUnits) = OpenCapVals.ComboValues(cccColumnLengthUnits)
+ PackedCapVals.TextValues(cctColumnID) = 75 ' Column ID
+ PackedCapVals.ComboValues(cccColumnIDUnits) = OpenCapVals.ComboValues(cccColumnIDUnits)
+ PackedCapVals.TextValues(cctViscosity) = OpenCapVals.TextValues(cctViscosity)
+ PackedCapVals.ComboValues(cccViscosityUnits) = OpenCapVals.ComboValues(cccViscosityUnits)
+ PackedCapVals.TextValues(cctParticleDiamter) = OpenCapVals.TextValues(cctParticleDiamter)
+ PackedCapVals.ComboValues(cccParticleDiameterUnits) = OpenCapVals.ComboValues(cccParticleDiameterUnits)
+ PackedCapVals.TextValues(cctFlowRate) = OpenCapVals.TextValues(cctFlowRate)
+ PackedCapVals.ComboValues(cccFlowRateUnits) = OpenCapVals.ComboValues(cccFlowRateUnits)
+ PackedCapVals.ComboValues(cccLinearVelocityUnits) = OpenCapVals.ComboValues(cccLinearVelocityUnits)
+ PackedCapVals.TextValues(cctDeadTime) = OpenCapVals.TextValues(cctDeadTime)
+ PackedCapVals.ComboValues(cccDeadTimeUnits) = OpenCapVals.ComboValues(cccDeadTimeUnits)
+ PackedCapVals.TextValues(cctPorosity) = OpenCapVals.TextValues(cctPorosity)
+ PackedCapVals.ComboValues(cccVolumeUnits) = OpenCapVals.ComboValues(cccVolumeUnits)
+
+ PackedCapVals.TextValues(cctMassRateConcentration) = OpenCapVals.TextValues(cctMassRateConcentration)
+ PackedCapVals.ComboValues(cccMassRateConcentrationUnits) = OpenCapVals.ComboValues(cccMassRateConcentrationUnits)
+ PackedCapVals.TextValues(cctMassRateVolFlowRate) = OpenCapVals.TextValues(cctMassRateVolFlowRate)
+ PackedCapVals.ComboValues(cccMassRateVolFlowRateUnits) = OpenCapVals.ComboValues(cccMassRateVolFlowRateUnits)
+ PackedCapVals.TextValues(cctMassRateInjectionTime) = OpenCapVals.TextValues(cctMassRateInjectionTime)
+ PackedCapVals.ComboValues(cccMassRateInjectionTimeUnits) = OpenCapVals.ComboValues(cccMassRateInjectionTimeUnits)
+ PackedCapVals.ComboValues(cccMassFlowRateUnits) = OpenCapVals.ComboValues(cccMassFlowRateUnits)
+ PackedCapVals.ComboValues(cccMassRateMolesInjectedUnits) = OpenCapVals.ComboValues(cccMassRateMolesInjectedUnits)
+
+ PackedCapVals.TextValues(cctBdLinearVelocity) = OpenCapVals.TextValues(cctBdLinearVelocity)
+ PackedCapVals.ComboValues(cccBdLinearVelocityUnits) = OpenCapVals.ComboValues(cccBdLinearVelocityUnits)
+ PackedCapVals.TextValues(cctBdDiffusionCoefficient) = OpenCapVals.TextValues(cctBdDiffusionCoefficient)
+ PackedCapVals.TextValues(cctBdOpenTubeLength) = OpenCapVals.TextValues(cctBdOpenTubeLength)
+ PackedCapVals.ComboValues(cccBdOpenTubeLengthUnits) = OpenCapVals.ComboValues(cccBdOpenTubeLengthUnits)
+ PackedCapVals.TextValues(cctBdOpenTubeID) = OpenCapVals.TextValues(cctBdOpenTubeID)
+ PackedCapVals.ComboValues(cccBdOpenTubeIDUnits) = OpenCapVals.ComboValues(cccBdOpenTubeIDUnits)
+ PackedCapVals.TextValues(cctBdInitialPeakWidth) = OpenCapVals.TextValues(cctBdInitialPeakWidth)
+ PackedCapVals.ComboValues(cccBdInitialPeakWidthUnits) = OpenCapVals.ComboValues(cccBdInitialPeakWidthUnits)
+ PackedCapVals.TextValues(cctBdAdditionalVariance) = OpenCapVals.TextValues(cctBdAdditionalVariance)
+ PackedCapVals.ComboValues(cccBdLinearVelocityUnits) = OpenCapVals.ComboValues(cccBdLinearVelocityUnits)
+ PackedCapVals.ComboValues(cccBdOpenTubeIDUnits) = OpenCapVals.ComboValues(cccBdOpenTubeIDUnits)
+ PackedCapVals.ComboValues(cccBdResultantPeakWidthUnits) = OpenCapVals.ComboValues(cccBdResultantPeakWidthUnits)
+
+End Sub
+
+Public Sub SetDefaultValuesAndFormulas(blnResetToDefaultFormulas As Boolean, Optional blnShowDebugPrompts As Boolean = False)
+
+ Dim intFormulaCount As Integer
+ Dim blnSuccess As Boolean
+ Dim intIndex As Integer
+ Dim eViewModeSaved As vmdViewModeConstants
+
+On Error GoTo SetDefaultValuesAndFormulasErrorHandler
+
+ ' Make sure we have at least 6 formulas
+ If blnResetToDefaultFormulas Then
+ With frmMain
+ frmMain.Show
+
+ eViewModeSaved = .GetViewMode()
+
+ If eViewModeSaved <> vmdMultiView Then
+ .SetViewMode vmdMultiView
+ End If
+
+ intFormulaCount = .GetTopFormulaIndex() + 1
+ Do While intFormulaCount < 6
+ blnSuccess = .AddNewFormulaWrapper(True)
+ Debug.Assert blnSuccess
+ intFormulaCount = intFormulaCount + 1
+ Loop
+
+ .EraseAllFormulas False
+
+ .rtfFormula(0).Text = "BrCH2(CH2)7CH2Br"
+ .rtfFormula(1).Text = "FeCl3-6H2O"
+ .rtfFormula(2).Text = "Co(Bpy)(CO)4"
+ .rtfFormula(3).Text = "^13C6H6-.1H2O"
+ .rtfFormula(4).Text = "HGlyLeuTyrOH"
+ .rtfFormula(5).Text = "BrCH2(CH2)7CH2Br>CH8"
+
+ .SetFocusToFormulaByIndex 0
+
+ If eViewModeSaved = vmdSingleView Then
+ .SetViewMode vmdSingleView
+ End If
+ End With
+ End If
+
+ With frmAminoAcidConverter
+ .txt1LetterSequence = "GLY"
+ .txt3LetterSequence = "Gly-Leu-Tyr"
+ SetCheckBox .chkSpaceEvery10, True
+ SetCheckBox .chkSeparateWithDash, True
+ End With
+
+ With frmMMConvert
+ SetCheckBox .chkLinkMolarities, False
+ SetCheckBox .chkLinkDilutionVolumeUnits, True
+
+ .optWeightSource(0).value = True
+ .txtCustomMass.Text = "100"
+ .cboAction.ListIndex = 2 ' mmaDilutionCalculations
+ .txtFromNum.Text = "1"
+ .cboFrom.ListIndex = uamMoles
+ .txtDensity.Text = "1"
+ .cboTo.ListIndex = uamGrams
+ .txtVolume.Text = "100"
+ .cboVolume.ListIndex = uevML
+ .txtConcentration.Text = "1"
+ .cboConcentration.ListIndex = ummcMolar
+
+ .cboDilutionMode.ListIndex = 0 ' dmFindRequiredDilutionVolumes
+ .txtDilutionConcentrationInitial.Text = "10"
+ .cboDilutionConcentrationInitial.ListIndex = ummcMolar
+ .txtStockSolutionVolume.Text = "3"
+ .cboStockSolutionVolume.ListIndex = uevML
+ .txtDilutionConcentrationFinal.Text = "2"
+ .cboDilutionConcentrationFinal.ListIndex = ummcMolar
+ .txtDilutingSolventVolume.Text = "12"
+ .cboDilutingSolventVolume.ListIndex = uevML
+ .txtTotalVolume.Text = "15"
+ .cboTotalVolume.ListIndex = uevML
+ End With
+
+ frmCalculator.rtfExpression.Text = "6^3-8.5*3"
+
+ With frmFinder
+ .optType(0).value = True
+ .txtMWT.Text = "200"
+ .txtPercentMaxWeight.Text = "400"
+ SetCheckBox .chkPpmMode, False
+ SetCheckBox .chkShowDeltaMass, True
+ .txtWeightTolerance.Text = "0.05"
+ .txtPercentTolerance.Text = "1"
+ .txtHits.Text = "100"
+ End With
+
+ With frmFinderOptions
+ SetCheckBox .chkAutoSetBounds, True
+ .cboSortResults.ListIndex = 0
+ SetCheckBox .chkSort, True
+ SetCheckBox .chkVerifyHydrogens, True
+ SetCheckBox .chkFindCharge, False
+ SetCheckBox .chkFindMtoZ, False
+ SetCheckBox .chkLimitChargeRange, False
+ .txtChargeMin.Text = "-4"
+ .txtChargeMax.Text = "4"
+ SetCheckBox .chkFindTargetMtoZ, False
+ .UpdateCheckBoxes
+ End With
+
+ With frmFinder
+ '.InitializeForm
+ For intIndex = 0 To .GetMaxElementCount() - 1
+ .txtMin(intIndex).Text = 0
+ .txtMax(intIndex).Text = 10
+
+ ' By default, check the first 4 elements
+ SetCheckBox .chkElements(intIndex), (intIndex <= 3)
+
+ .txtPercent(intIndex).Text = LookupLanguageCaption(10260, "Percent")
+ If intIndex >= 4 Then
+ .txtWeight(intIndex).Text = LookupLanguageCaption(10270, "# or Element or Abbrev.")
+ End If
+ Next intIndex
+ End With
+
+ SetDefaultCapillaryFlowValues
+ If frmCapillaryCalcs.cboCapillaryType.ListIndex <> 0 Then
+ ' Setting .ListIndex to 0 will automatically call UpdateCapillaryType
+ frmCapillaryCalcs.cboCapillaryType.ListIndex = 0
+ Else
+ frmCapillaryCalcs.UpdateCapillaryType
+ End If
+
+ With frmFragmentationModelling
+ .cboNotation.ListIndex = 1
+ .txtSequence = "Arg-His-Pro-Glu-Tyr-Ala-Val"
+ .cboNTerminus.ListIndex = ntgHydrogen
+ .cboCTerminus.ListIndex = ctgHydroxyl
+ SetCheckBox .chkIonType(0), False
+ SetCheckBox .chkIonType(1), True
+ SetCheckBox .chkIonType(2), True
+ .lstIonsToModify.Selected(0) = False
+ .lstIonsToModify.Selected(1) = True
+ .lstIonsToModify.Selected(2) = True
+ SetCheckBox .chkWaterLoss, True
+ SetCheckBox .chkAmmoniaLoss, False
+ SetCheckBox .chkPhosphateLoss, False
+ SetCheckBox .chkDoubleCharge, False
+ .cboDoubleCharge.ListIndex = 8
+ SetCheckBox .chkRemovePrecursorIon, True
+ .txtPrecursorIonMass = "300"
+ .txtPrecursorMassWindow = "2"
+ .txtIonMatchingWindow = "0.5"
+ .txtAlignment = "0"
+ End With
+
+ With frmIonMatchOptions
+ .txtIonIntensity(0) = "10"
+ .txtIonIntensity(1) = "50"
+ .txtIonIntensity(2) = "50"
+ .txtBYIonShoulders = "25"
+ .txtNeutralLosses = "10"
+ SetCheckBox .chkGroupSimilarIons, False
+ .txtGroupIonMassWindow = ".5"
+ .txtNormalizedIntensity = "100"
+ .txtIonCountToUse = "200"
+ .txtMassRegions = "1"
+ SetCheckBox .chkFragSpecLabelMainIons, True
+ SetCheckBox .chkFragSpecLabelOtherIons, False
+ SetCheckBox .chkFragSpecEmphasizeProlineYIons, False
+ SetCheckBox .chkPlotSpectrumInverted, True
+ SetCheckBox .chkAutoLabelMass, False
+ .lblFragSpectrumColor.BackColor = RGB(0, 0, 255)
+ .lblMatchingIonDataColor.BackColor = RGB(0, 128, 0)
+ End With
+
+ frmIsotopicDistribution.EnableDisablePlotUpdates True
+ With frmIsotopicDistribution
+ .cboPlotType.ListIndex = 1 ' ipmGaussian
+ .lblPlotColor.BackColor = vbBlue
+ .txtEffectiveResolution = 5000
+ .txtEffectiveResolutionMass = 1000
+ .txtGaussianQualityFactor = 50
+
+ .lblComparisonListPlotColor.BackColor = vbRed
+ .cboComparisonListPlotType.ListIndex = 0 ' ipmSticksToZero
+ SetCheckBox .chkComparisonListNormalize, True
+
+ SetCheckBox .chkAutoLabelPeaks, False
+ SetCheckBox .chkPlotResults, True
+ End With
+
+ If blnShowDebugPrompts Then MsgBox "Call objMwtWin.Peptide.SetDefaultModificationSymbols"
+ objMwtWin.Peptide.SetDefaultModificationSymbols
+
+ If blnShowDebugPrompts Then MsgBox "Call frmFragmentationModelling.ResetCWSpectrumOptions"
+ frmFragmentationModelling.ResetCWSpectrumOptions
+
+ If blnShowDebugPrompts Then MsgBox "Call frmIsotopicDistribution.ResetCWSpectrumOptions"
+ frmIsotopicDistribution.ResetCWSpectrumOptions
+
+ frmIsotopicDistribution.EnableDisablePlotUpdates False
+
+ Exit Sub
+
+SetDefaultValuesAndFormulasErrorHandler:
+ Debug.Assert False
+ GeneralErrorHandler "MwtWinProcedures|SetDefaultValuesAndFormulas", Err.Number, Err.Description
+ Resume Next
+
+End Sub
+
+Public Sub SetFonts(strFontName As String, intFontSize As Integer)
+ Dim intIndex As Integer
+
+On Error GoTo SetFontsErrorHandler
+
+ If Len(strFontName) = 0 Then Exit Sub
+
+ objMwtWin.RtfFontName = strFontName
+ objMwtWin.RtfFontSize = intFontSize
+
+ With frmMain
+ .rtfFormulaSingle.Font.Name = objMwtWin.RtfFontName
+ .rtfFormulaSingle.Font.Size = objMwtWin.RtfFontSize
+
+ With .txtMWTSingle
+ .Font = objMwtWin.RtfFontName
+ .FontSize = objMwtWin.RtfFontSize
+ .FontItalic = False
+ End With
+ For intIndex = 0 To frmMain.GetTopFormulaIndex
+ .rtfFormula(intIndex).Font.Name = objMwtWin.RtfFontName
+ .rtfFormula(intIndex).Font.Size = objMwtWin.RtfFontSize
+ With .txtMWT(intIndex)
+ .Font = objMwtWin.RtfFontName
+ .FontSize = objMwtWin.RtfFontSize
+ .FontItalic = False
+ End With
+ ' Make changes appear
+ .rtfFormula(intIndex).TextRTF = objMwtWin.TextToRTF(.rtfFormula(intIndex).Text)
+ Next intIndex
+ End With
+
+ frmMain.Refresh
+
+ frmFinder.lstResults.FontName = objMwtWin.RtfFontName
+ frmFinder.rtfResults.Font.Name = objMwtWin.RtfFontName
+ frmFinder.rtfResults.Font.Size = objMwtWin.RtfFontSize
+ frmFinder.Refresh
+
+ Exit Sub
+
+SetFontsErrorHandler:
+ GeneralErrorHandler "MwtWinProcedures|SetFonts", Err.Number, Err.Description
+
+End Sub
+
+Public Sub ShowDefaultFormAtLoad()
+ Dim intListIndex As Integer
+
+ ' 0: Main
+ ' 1: Formula Finder
+ ' 2: Capillary Flow Calculator
+ ' 3: Mole/Mass Converter
+ ' 4: Peptide Sequence Fragmentation Modeller
+ ' 5: Amino Acid Notation Converter
+ ' 6: Isotopic Distribution Modeller
+
+ intListIndex = frmProgramPreferences.cboStartupModule.ListIndex
+ Select Case intListIndex
+ Case 1: frmMain.ShowFormulaFinder
+ Case 2: frmMain.ShowCapillaryFlowModule
+ Case 3: frmMain.ShowMoleMassConverter
+ Case 4: frmMain.ShowPeptideSequenceModeller
+ Case 5: frmMain.ShowAminoAcidNotationModule
+ Case 6: frmMain.ShowIsoDistributionModeller
+ Case Else
+ ' Do nothing, let frmMain be shown
+ End Select
+
+End Sub
+
+Public Sub ShowHelpPage(hwnd As Long, lngContextID As Long)
+ On Error GoTo ErrHandler
+
+ 'hWnd is a Long defined elsewhere to be the window handle
+ 'that will be the parent to the help window.
+ Dim hwndHelp As Long
+
+ 'The return value is the window handle of the created help window.
+ hwndHelp = HtmlHelp(hwnd, App.HelpFile, HH_HELP_CONTEXT, lngContextID)
+
+ Exit Sub
+
+ErrHandler:
+ ' User pressed cancel button
+ Exit Sub
+
+End Sub
+
+Public Sub ShowHideMassInputControlsGlobal(frmThisForm As VB.Form)
+ Dim blnCustomVisible As Boolean
+
+ With frmThisForm
+ If .optWeightSource(0).value = True Then
+ .eMassMode = mmcComputedMass
+ Else
+ .eMassMode = mmcCustomMass
+ End If
+
+ If .eMassMode = mmcComputedMass Then
+ blnCustomVisible = False
+ Else
+ blnCustomVisible = True
+ End If
+
+ .lblFormula.Visible = Not blnCustomVisible
+ .rtfCurrentFormula.Visible = Not blnCustomVisible
+ .lblMWT.Visible = Not blnCustomVisible
+ .lblMWTValue.Visible = Not blnCustomVisible
+
+ .lblCustomMass.Visible = blnCustomVisible
+ .txtCustomMass.Visible = blnCustomVisible
+ End With
+End Sub
+
+Public Sub SwitchWeightMode(eNewElementMode As emElementModeConstants, Optional blnRecalculateAllFormulas As Boolean = True, Optional blnSetFocusToCurrentFormula As Boolean = True)
+ ' eNewElementMode = 1 is average weights (emAverageMass)
+ ' eNewElementMode = 2 is isotopic weights (emIsotopicMass)
+ ' eNewElementMode = 3 is integer weights (emIntegerMass)
+
+ If eNewElementMode < emAverageMass Or eNewElementMode > emIntegerMass Then
+ eNewElementMode = emAverageMass
+ End If
+
+ objMwtWin.SetElementMode eNewElementMode
+
+ If blnRecalculateAllFormulas Then
+ RecalculateAllFormulas blnSetFocusToCurrentFormula
+ End If
+
+ ' Make sure QuickSwitch Element Mode value is correct
+ frmMain.ShowHideQuickSwitch frmProgramPreferences.chkShowQuickSwitch.value
+
+End Sub
+
+Public Sub SwitchWeightModeInteger(intNewElementMode As Integer, Optional blnRecalculateAllFormulas As Boolean = True)
+ ' This sub is used to call SwitchWeightMode when the integer equivalent of the weight mode is known
+
+ If intNewElementMode = emIsotopicMass Then
+ SwitchWeightMode emIsotopicMass, blnRecalculateAllFormulas
+ ElseIf intNewElementMode = emIntegerMass Then
+ SwitchWeightMode emIntegerMass, blnRecalculateAllFormulas
+ Else
+ ' Assume intNewElementMode = emAverageMass
+ SwitchWeightMode emAverageMass, blnRecalculateAllFormulas
+ End If
+
+End Sub
+
+Public Sub ShowPopupRightClickMenu(frmParentForm As VB.Form, rtfThisTextBox As RichTextBox, Optional blnEnableUndoMenu As Boolean = True, Optional blnAllowPasteAndDelete As Boolean = True)
+ ' Enable/Disable the appropriate menus
+
+ With frmParentForm
+ .mnuRightClickUndo.Enabled = blnEnableUndoMenu
+
+ .mnuRightClickCut.Enabled = (rtfThisTextBox.SelLength > 0)
+ .mnuRightClickCopy.Enabled = (rtfThisTextBox.SelLength > 0)
+
+ If blnAllowPasteAndDelete Then
+ If Clipboard.GetFormat(vbCFText) Or Clipboard.GetFormat(vbCFRTF) Then
+ .mnuRightClickPaste.Enabled = True
+ Else
+ .mnuRightClickPaste.Enabled = False
+ End If
+
+ .mnuRightClickDelete.Enabled = (rtfThisTextBox.SelLength > 0)
+ Else
+ .mnuRightClickPaste.Enabled = False
+ .mnuRightClickDelete.Enabled = False
+ End If
+
+ .mnuRightClickSelectAll.Enabled = (Len(rtfThisTextBox.Text) > 0)
+
+ frmParentForm.PopupMenu .mnuRightClick
+ End With
+
+End Sub
+
+Public Sub SwitchTips(blnShowToolTips As Boolean)
+ Dim ThisForm As VB.Form, ThisControl As Control
+
+ If blnShowToolTips Then
+ ' Set all the tooltips
+ SetAllTooltips
+ Else
+ ' Cancel all the tooltips
+ On Error Resume Next
+ For Each ThisForm In Forms
+ For Each ThisControl In ThisForm
+ If Not (TypeOf ThisControl Is CommonDialog Or TypeOf ThisControl Is Menu) Then
+ ThisControl.ToolTipText = ""
+ End If
+ Next ThisControl
+ Next ThisForm
+ End If
+
+ frmMain.mnuShowTips.Checked = blnShowToolTips
+
+End Sub
+
+Public Sub ZoomLine(strCaption As String)
+ MsgBox LookupLanguageCaption(3600, "The entire line is") & vbCrLf & strCaption, vbOKOnly, LookupLanguageCaption(3605, "Zooming")
+End Sub
+
diff --git a/MWT_ABBR.DAT b/MWT_ABBR.DAT
new file mode 100644
index 0000000..a3a5662
--- /dev/null
+++ b/MWT_ABBR.DAT
@@ -0,0 +1,65 @@
+; Abbreviations File for MWTWIN program (v6.41)
+;
+; Comments may be added by preceding with a semicolon
+; Two group headings must exist: [AMINO ACIDS] and [ABBREVIATIONS]
+; Abbreviations may be added; simply type the abbreviation and molecular
+; formula under the appropriate column in either section
+; Note: Only the first letter of an abbreviation is allowed to be capitalized
+;
+; The abbreviations in the Amino Acid section are treated as extended level
+; abbreviations: they are only recognized when extended abbreviations are on
+; If this file becomes corrupted, the MWTWIN program will inform the user
+; and ignore incorrect lines
+; If this file becomes deleted, the MWTWIN program will create a new file
+; with the default abbreviations
+;
+; Default Amino Acids are in their ionic form
+; Amino Acid abbreviation names may be up to 6 characters long
+[AMINO ACIDS]
+Ala C3H5NO 0 A ; Alanine
+Arg C6H12N4O 0 R ; Arginine, (unprotonated NH2)
+Asn C4H6N2O2 0 N ; Asparagine
+Asp C4H5NO3 0 D ; Aspartic acid (undissociated COOH)
+Cys C3H5NOS 0 C ; Cysteine (no disulfide link)
+Gla C6H7NO5 0 U ; gamma-Carboxyglutamate
+Gln C5H8N2O2 0 Q ; Glutamine
+Glu C5H7NO3 0 E ; Glutamic acid (undissociated COOH)
+Gly C2H3NO 0 G ; Glycine
+His C6H7N3O 0 H ; Histidine (unprotonated NH)
+Hse C4H7NO2 0 ; Homoserine
+Hyl C6H12N2O2 0 ; Hydroxylysine
+Hyp C5H7NO2 0 ; Hydroxyproline
+Ile C6H11NO 0 I ; Isoleucine
+Leu C6H11NO 0 L ; Leucine
+Lys C6H12N2O 0 K ; Lysine (unprotonated NH2)
+Met C5H9NOS 0 M ; Methionine
+Orn C5H10N2O 0 O ; Ornithine
+Phe C9H9NO 0 F ; Phenylalanine
+Pro C5H7NO 0 P ; Proline
+Pyr C5H5NO2 0 ; Pyroglutamic acid
+Sar C3H5NO 0 ; Sarcosine
+Ser C3H5NO2 0 S ; Serine
+Thr C4H7NO2 0 T ; Threonine
+Trp C11H10N2O 0 W ; Tryptophan
+Tyr C9H9NO2 0 Y ; Tyrosine
+Val C5H9NO 0 V ; Valine
+Xxx C6H12N2O 0 X ; Unknown
+
+; Normal abbreviation names may be up to 6 characters long
+[ABBREVIATIONS]
+Bpy C10H8N2 0 ; Bipyridine
+Bu C4H9 1 ; Butyl
+D ^2.014H 1 ; Deuterium
+En C2H8N2 0 ; Ethylenediamine
+Et CH3CH2 1 ; Ethyl
+Me CH3 1 ; Methyl
+Ms CH3SOO -1 ; Mesyl
+Oac C2H3O2 -1 ; Acetate
+Otf OSO2CF3 -1 ; Triflate
+Ox C2O4 -2 ; Oxalate
+Ph C6H5 1 ; Phenyl
+Phen C12H8N2 0 ; Phenanthroline
+Py C5H5N 0 ; Pyridine
+Tpp (C4H2N(C6H5C)C4H2N(C6H5C))2 0 ; Tetraphenylporphyrin, mw 612.733
+Ts CH3C6H4SOO -1 ; Tosyl
+Urea H2NCONH2 0 ; Urea
diff --git a/MWT_ABBR.bak b/MWT_ABBR.bak
new file mode 100644
index 0000000..1f1bf9b
--- /dev/null
+++ b/MWT_ABBR.bak
@@ -0,0 +1,65 @@
+; Abbreviations File for MWTWIN program (v6.37)
+;
+; Comments may be added by preceding with a semicolon
+; Two group headings must exist: [AMINO ACIDS] and [ABBREVIATIONS]
+; Abbreviations may be added; simply type the abbreviation and molecular
+; formula under the appropriate column in either section
+; Note: Only the first letter of an abbreviation is allowed to be capitalized
+;
+; The abbreviations in the Amino Acid section are treated as extended level
+; abbreviations: they are only recognized when extended abbreviations are on
+; If this file becomes corrupted, the MWTWIN program will inform the user
+; and ignore incorrect lines
+; If this file becomes deleted, the MWTWIN program will create a new file
+; with the default abbreviations
+;
+; Default Amino Acids are in their ionic form
+; Amino Acid abbreviation names may be up to 6 characters long
+[AMINO ACIDS]
+Ala C3H5NO 0 A ; Alanine
+Arg C6H12N4O 0 R ; Arginine, (unprotonated NH2)
+Asn C4H6N2O2 0 N ; Asparagine
+Asp C4H5NO3 0 D ; Aspartic acid (undissociated COOH)
+Cys C3H5NOS 0 C ; Cysteine (no disulfide link)
+Gla C6H7NO5 0 U ; gamma-Carboxyglutamate
+Gln C5H8N2O2 0 Q ; Glutamine
+Glu C5H7NO3 0 E ; Glutamic acid (undissociated COOH)
+Gly C2H3NO 0 G ; Glycine
+His C6H7N3O 0 H ; Histidine (unprotonated NH)
+Hse C4H7NO2 0 ; Homoserine
+Hyl C6H12N2O2 0 ; Hydroxylysine
+Hyp C5H7NO2 0 ; Hydroxyproline
+Ile C6H11NO 0 I ; Isoleucine
+Leu C6H11NO 0 L ; Leucine
+Lys C6H12N2O 0 K ; Lysine (unprotonated NH2)
+Met C5H9NOS 0 M ; Methionine
+Orn C5H10N2O 0 O ; Ornithine
+Phe C9H9NO 0 F ; Phenylalanine
+Pro C5H7NO 0 P ; Proline
+Pyr C5H5NO2 0 ; Pyroglutamic acid
+Sar C3H5NO 0 ; Sarcosine
+Ser C3H5NO2 0 S ; Serine
+Thr C4H7NO2 0 T ; Threonine
+Trp C11H10N2O 0 W ; Tryptophan
+Tyr C9H9NO2 0 Y ; Tyrosine
+Val C5H9NO 0 V ; Valine
+Xxx C6H12N2O 0 X ; Unknown
+
+; Normal abbreviation names may be up to 6 characters long
+[ABBREVIATIONS]
+Bpy C10H8N2 0 ; Bipyridine
+Bu C4H9 1 ; Butyl
+D ^2.014H 1 ; Deuterium
+En C2H8N2 0 ; Ethylenediamine
+Et CH3CH2 1 ; Ethyl
+Me CH3 1 ; Methyl
+Ms CH3SOO -1 ; Mesyl
+Oac C2H3O2 -1 ; Acetate
+Otf OSO2CF3 -1 ; Triflate
+Ox C2O4 -2 ; Oxalate
+Ph C6H5 1 ; Phenyl
+Phen C12H8N2 0 ; Phenanthroline
+Py C5H5N 0 ; Pyridine
+Tpp (C4H2N(C6H5C)C4H2N(C6H5C))2 0 ; Tetraphenylporphyrin
+Ts CH3C6H4SOO -1 ; Tosyl
+Urea H2NCONH2 0 ; Urea
diff --git a/MWT_ELEM.bak b/MWT_ELEM.bak
new file mode 100644
index 0000000..39aeae6
--- /dev/null
+++ b/MWT_ELEM.bak
@@ -0,0 +1,128 @@
+; Elements File for MWTWIN program (v6.41)
+;
+; Comments may be added by preceding with a semicolon
+; The heading [ELEMENTWEIGHTTYPE] 1 signifies that Average Elemental Weights are
+; being used while [ELEMENTWEIGHTTYPE] 2 signifies the use of Isotopic Weights
+; and [ELEMENTWEIGHTTYPE] 3 signifies the use of Integer Weights
+; The group heading [ELEMENTS] must exist to signify the start of the elements
+; Elemental values may be changed, but new elements may not be added
+; If you wish to add new elements, simply add them as abbreviations
+; If this file becomes deleted, the MWTWIN program will create a new file
+; with the default values
+; Uncertainties from CRC Handbook of Chemistry and Physics
+; For Radioactive elements, the most stable isotope is NOT used;
+; instead, an average Mol. Weight is used, just like with other elements.
+; Data obtained from the Perma-Chart Science Series periodic table, 1993.
+; Uncertainties from CRC Handoobk of Chemistry and Physics, except for
+; Radioactive elements, where uncertainty was estimated to be .n5 where
+; n represents the number digits after the decimal point but before the last
+; number of the molecular weight.
+; For example, for No, MW = 259.1009 (±0.0005)
+;
+[ELEMENTWEIGHTTYPE] 1
+; The values signify:
+; Weight Uncertainty Charge
+[ELEMENTS]
+H 1.00794 0.00007 1
+He 4.002602 0.000002 0
+Li 6.941 0.002 1
+Be 9.012182 0.000003 2
+B 10.811 0.007 3
+C 12.0107 0.0008 4
+N 14.00674 0.00007 -3
+O 15.9994 0.0003 -2
+F 18.9984032 0.0000005 -1
+Ne 20.1797 0.0006 0
+Na 22.98977 0.000002 1
+Mg 24.305 0.0006 2
+Al 26.981538 0.000002 3
+Si 28.0855 0.0003 4
+P 30.973761 0.000002 -3
+S 32.066 0.006 -2
+Cl 35.4527 0.0009 -1
+Ar 39.948 0.001 0
+K 39.0983 0.0001 1
+Ca 40.078 0.004 2
+Sc 44.95591 0.000008 3
+Ti 47.867 0.001 4
+V 50.9415 0.0001 5
+Cr 51.9961 0.0006 3
+Mn 54.938049 0.000009 2
+Fe 55.845 0.002 3
+Co 58.9332 0.000009 2
+Ni 58.6934 0.0002 2
+Cu 63.546 0.003 2
+Zn 65.39 0.02 2
+Ga 69.723 0.001 3
+Ge 72.61 0.02 4
+As 74.9216 0.00002 -3
+Se 78.96 0.03 -2
+Br 79.904 0.001 -1
+Kr 83.8 0.01 0
+Rb 85.4678 0.0003 1
+Sr 87.62 0.01 2
+Y 88.90585 0.00002 3
+Zr 91.224 0.002 4
+Nb 92.90638 0.00002 5
+Mo 95.94 0.01 6
+Tc 97.9072 0.0005 7
+Ru 101.07 0.02 4
+Rh 102.9055 0.00002 3
+Pd 106.42 0.01 2
+Ag 107.8682 0.0002 1
+Cd 112.411 0.008 2
+In 114.818 0.003 3
+Sn 118.71 0.007 4
+Sb 121.76 0.001 -3
+Te 127.6 0.03 -2
+I 126.90447 0.00003 -1
+Xe 131.29 0.02 0
+Cs 132.90545 0.00002 1
+Ba 137.327 0.007 2
+La 138.9055 0.0002 3
+Ce 140.116 0.001 3
+Pr 140.90765 0.00002 4
+Nd 144.24 0.03 3
+Pm 144.9127 0.0005 3
+Sm 150.36 0.03 3
+Eu 151.964 0.001 3
+Gd 157.25 0.03 3
+Tb 158.92534 0.00002 3
+Dy 162.5 0.03 3
+Ho 164.93032 0.00002 3
+Er 167.26 0.03 3
+Tm 168.93421 0.00002 3
+Yb 173.04 0.03 3
+Lu 174.967 0.001 3
+Hf 178.49 0.02 4
+Ta 180.9479 0.0001 5
+W 183.84 0.01 6
+Re 186.207 0.001 7
+Os 190.23 0.03 4
+Ir 192.217 0.03 4
+Pt 195.078 0.002 4
+Au 196.96655 0.00002 3
+Hg 200.59 0.02 2
+Tl 204.3833 0.0002 1
+Pb 207.2 0.1 2
+Bi 208.98038 0.00002 3
+Po 208.9824 0.0005 4
+At 209.9871 0.0005 -1
+Rn 222.0176 0.0005 0
+Fr 223.0197 0.0005 1
+Ra 226.0254 0.0001 2
+Ac 227.0278 0.00001 3
+Th 232.0381 0.0001 4
+Pa 231.03588 0.00002 5
+U 238.0289 0.0001 6
+Np 237.0482 0.0005 5
+Pu 244.0642 0.0005 4
+Am 243.0614 0.0005 3
+Cm 247.0703 0.0005 3
+Bk 247.0703 0.0005 3
+Cf 251.0796 0.0005 3
+Es 252.083 0.005 3
+Fm 257.0951 0.0005 3
+Md 258.1 0.05 3
+No 259.1009 0.0005 3
+Lr 262.11 0.05 3
diff --git a/MWT_VALU.bak b/MWT_VALU.bak
new file mode 100644
index 0000000..b8c925e
--- /dev/null
+++ b/MWT_VALU.bak
@@ -0,0 +1,950 @@
+; Values File for MWTWIN Program (v6.42)
+;
+; File Automatically Created -- Select Save Values and Formulas under the Options Menu
+;
+Formula0=BrCH2(CH2)7CH2Br
+Formula1=FeCl3-6H2O
+Formula2=Co(Bpy)(CO)4
+Formula3=^13C6H6-.1H2O
+Formula4=HGlyLeuTyrOH
+Formula5=BrCH2(CH2)7CH2Br>CH8
+AminoAcidConvertOneLetter=GLY
+AminoAcidConvertThreeLetter=Gly-Leu-Tyr
+AminoAcidConvertSpaceOneLetter=1
+AminoAcidConvertDashThreeLetter=1
+Mole/MassWeightSource=0
+Mole/MassCustomMass=100
+Mole/MassAction=2
+Mole/MassFrom=1
+Mole/MassFromUnits=0
+Mole/MassDensity=1
+Mole/MassToUnits=8
+Mole/MassVolume=100
+Mole/MassVolumeUnits=2
+Mole/MassMolarity=10.0
+Mole/MassMolarityUnits=0
+Mole/MassDilutionMode=0
+Mole/MassMolarityInitial=10
+Mole/MassMolarityInitialUnits=0
+Mole/MassVolumeInitial=3.0
+Mole/MassVolumeInitialUnits=2
+Mole/MassMolarityFinal=2
+Mole/MassMolarityFinalUnits=0
+Mole/MassVolumeSolvent=12.0
+Mole/MassVolumeSolventUnits=2
+Mole/MassVolumeTotal=15
+Mole/MassVolumeTotalUnits=2
+Mole/MassLinkConcentrations=0
+Mole/MassLinkDilutionVolumeUnits=1
+CapillaryFlowFileFormatVersion=2
+CapillaryFlowMode=0
+CapillaryFlowComputationType=3
+CapillaryFlowLinkFlowRate=1
+CapillaryFlowLinkLinearVelocity=1
+CapillaryFlowShowPeakBroadeningSave=0
+CapillaryFlowWeightSource=0
+CapillaryFlowCustomMass=100
+CapillaryFlowOpenText0=50
+CapillaryFlowPackedText0=3000
+CapillaryFlowOpenText1=50
+CapillaryFlowPackedText1=50
+CapillaryFlowOpenText2=30
+CapillaryFlowPackedText2=75
+CapillaryFlowOpenText3=0.0089
+CapillaryFlowPackedText3=0.0089
+CapillaryFlowOpenText4=5
+CapillaryFlowPackedText4=5
+CapillaryFlowOpenText5=100
+CapillaryFlowPackedText5=100
+CapillaryFlowOpenText6=1
+CapillaryFlowPackedText6=1
+CapillaryFlowOpenText7=0.4
+CapillaryFlowPackedText7=0.4
+CapillaryFlowOpenText8=1
+CapillaryFlowPackedText8=1
+CapillaryFlowOpenText9=100
+CapillaryFlowPackedText9=100
+CapillaryFlowOpenText10=30
+CapillaryFlowPackedText10=30
+CapillaryFlowOpenText11=1
+CapillaryFlowPackedText11=1
+CapillaryFlowOpenText12=0.000005
+CapillaryFlowPackedText12=0.000005
+CapillaryFlowOpenText13=5
+CapillaryFlowPackedText13=5
+CapillaryFlowOpenText14=50
+CapillaryFlowPackedText14=50
+CapillaryFlowOpenText15=30
+CapillaryFlowPackedText15=30
+CapillaryFlowOpenText16=0
+CapillaryFlowPackedText16=0
+CapillaryFlowOpenCombo0=0
+CapillaryFlowPackedCombo0=0
+CapillaryFlowOpenCombo1=1
+CapillaryFlowPackedCombo1=1
+CapillaryFlowOpenCombo2=3
+CapillaryFlowPackedCombo2=3
+CapillaryFlowOpenCombo3=0
+CapillaryFlowPackedCombo3=0
+CapillaryFlowOpenCombo4=3
+CapillaryFlowPackedCombo4=3
+CapillaryFlowOpenCombo5=2
+CapillaryFlowPackedCombo5=2
+CapillaryFlowOpenCombo6=4
+CapillaryFlowPackedCombo6=4
+CapillaryFlowOpenCombo7=2
+CapillaryFlowPackedCombo7=2
+CapillaryFlowOpenCombo8=2
+CapillaryFlowPackedCombo8=2
+CapillaryFlowOpenCombo9=2
+CapillaryFlowPackedCombo9=2
+CapillaryFlowOpenCombo10=2
+CapillaryFlowPackedCombo10=2
+CapillaryFlowOpenCombo11=2
+CapillaryFlowPackedCombo11=2
+CapillaryFlowOpenCombo12=4
+CapillaryFlowPackedCombo12=4
+CapillaryFlowOpenCombo13=5
+CapillaryFlowPackedCombo13=5
+CapillaryFlowOpenCombo14=4
+CapillaryFlowPackedCombo14=4
+CapillaryFlowOpenCombo15=1
+CapillaryFlowPackedCombo15=1
+CapillaryFlowOpenCombo16=3
+CapillaryFlowPackedCombo16=3
+CapillaryFlowOpenCombo17=2
+CapillaryFlowPackedCombo17=2
+CapillaryFlowOpenCombo18=2
+CapillaryFlowPackedCombo18=2
+ViscosityMeCNPercentAcetontrile=20
+ViscosityMeCNTemperature=25
+ViscosityMeCNTemperatureUnits=0
+Calculator=6^3-8.5*3
+IonPlotColor=16711680
+IonPlotShowPlot=1
+IonPlotType=1
+IonPlotResolution=5000
+IonPlotResolutionMass=1000
+IonPlotGaussianQuality=50
+IonComparisonPlotColor=255
+IonComparisonPlotType=0
+IonComparisonPlotNormalize=1
+FinderAction=0
+FinderMWT=200
+FinderPercentMaxWeight=400
+FinderPPM=0
+FinderShowDeltaMass=1
+FinderWtTolerance=0.05
+FinderPercentTolerance=1
+FinderMaxHits=100
+FinderSortResults=1
+FinderSmartH=1
+FinderFindCharge=0
+FinderFindMtoZ=0
+FinderLimitChargeRange=0
+FinderChargeRangeMin=-4
+FinderChargeRangeMax=4
+FinderFindTargetMtoZ=0
+FinderHighlightText=0
+FinderAutoBoundsSet=1
+FinderSortMode=0
+FinderMin0=0
+FinderMax0=10
+FinderCheckElements0=1
+FinderPercentValue0=Percent
+FinderMin1=0
+FinderMax1=10
+FinderCheckElements1=1
+FinderPercentValue1=Percent
+FinderMin2=0
+FinderMax2=10
+FinderCheckElements2=1
+FinderPercentValue2=Percent
+FinderMin3=0
+FinderMax3=10
+FinderCheckElements3=1
+FinderPercentValue3=Percent
+FinderMin4=0
+FinderMax4=10
+FinderCheckElements4=0
+FinderPercentValue4=Percent
+FinderCustomWeight1=# or Element or Abbrev.
+FinderMin5=0
+FinderMax5=10
+FinderCheckElements5=0
+FinderPercentValue5=Percent
+FinderCustomWeight2=# or Element or Abbrev.
+FinderMin6=0
+FinderMax6=10
+FinderCheckElements6=0
+FinderPercentValue6=Percent
+FinderCustomWeight3=# or Element or Abbrev.
+FinderMin7=0
+FinderMax7=10
+FinderCheckElements7=0
+FinderPercentValue7=Percent
+FinderCustomWeight4=# or Element or Abbrev.
+FinderMin8=0
+FinderMax8=10
+FinderCheckElements8=0
+FinderPercentValue8=Percent
+FinderCustomWeight5=# or Element or Abbrev.
+FinderMin9=0
+FinderMax9=10
+FinderCheckElements9=0
+FinderPercentValue9=Percent
+FinderCustomWeight6=# or Element or Abbrev.
+FragModelModificationSymbolsCount=10
+FragModelModificationSymbol1=*,79.9663326,True,Phosphorylation [HPO3]
+FragModelModificationSymbol2=+,14.01565,False,Methylation [CH2]
+FragModelModificationSymbol3=@,15.99492,False,Oxidation [O]
+FragModelModificationSymbol4=!,57.02146,False,Carbamidomethylation [C2H3NO]
+FragModelModificationSymbol5=&,58.00548,False,Carboxymethylation [CH2CO2]
+FragModelModificationSymbol6=#,71.03711,False,Acrylamide [CHCH2CONH2]
+FragModelModificationSymbol7=$,227.127,False,Cleavable ICAT [(^12C10)H17N3O3]
+FragModelModificationSymbol8=%,236.127,False,Cleavable ICAT [(^13C9)(^12C)H17N3O3]
+FragModelModificationSymbol9=~,442.225,False,ICAT D0 [C20H34N4O5S]
+FragModelModificationSymbol10=`,450.274,False,ICAT D8 [C20H26D8N4O5S]
+FragModelNotationMode=1
+FragModelSequence=Arg-His-Pro-Glu-Tyr-Ala-Val
+FragModelNTerminus=0
+FragModelCTerminus=0
+FragModelIonType0=0
+FragModelIonType1=1
+FragModelIonType2=1
+FragModelIonsToModify0=0
+FragModelIonsToModify1=1
+FragModelIonsToModify2=1
+FragModelWaterLoss=1
+FragModelAmmoniaLoss=0
+FragModelPhosphateLoss=0
+FragModelDoubleCharge=0
+FragModelDoubleChargeThreshold=8
+FragModelPrecursorIonRemove=1
+FragModelPrecursorIonMass=300
+FragModelPrecursorIonMassWindow=2
+FragModelIonMatchWindow=0.5
+FragModelIonIntensity0=10
+FragModelIonIntensity1=50
+FragModelIonIntensity2=50
+FragModelShoulderIntensity=25
+FragModelNeutralLossIntensity=10
+FragModelGroupIons=0
+FragModelGroupIonsMassWindow=.5
+FragModelNormalizedIntensity=100
+FragModelNormalizationIonsUseCount=200
+FragModelNormalizationMassRegions=1
+FragModelLabelMainIons=1
+FragModelLabelOtherIons=0
+FragModelEmphasizeProlineYIons=0
+FragModelPlotPredictedSpectrumInverted=1
+FragModelAutoLabelMass=0
+FragModelFragSpectrumColor=16711680
+FragModelMatchingIonDataColor=32768
+FragModelIonMatchList=637
+379.461,6
+380.339,1.2
+384.326,2.9
+389.005,7.8
+411.377,3.1
+414.084,2.7
+437.125,6.5
+460.34,6.9
+462.034,2.8
+472.466,23.4
+478.512,8.3
+481.635,3.9
+500.2,7.9
+507.284,2.7
+508.232,10.1
+521.179,1.4
+530.629,2.2
+534.312,18.4
+539.964,3.8
+541.164,4.2
+543.388,7.2
+545.858,2.3
+549.199,9.7
+554.196,6.8
+561.151,3.8
+562.317,2.5
+565.096,7.1
+566.305,8.1
+567.031,9.4
+568.379,1.7
+570.055,4.6
+571.17,11.1
+576.61,13.8
+582.438,9
+586.32,19.5
+590.33,5.8
+601.675,2.7
+603.215,12.5
+611.299,2.7
+613.391,7.7
+615.37,2.7
+617.419,13.3
+618.294,4.8
+620.439,8.9
+622.059,3.5
+627.106,2
+650.276,3.1
+657.377,3.5
+661.3,12
+680.892,7.5
+682.203,5.8
+683.548,13.1
+685.302,6.7
+697.146,8.1
+697.948,3.2
+706.225,19.4
+707.906,11.1
+711.2,14.5
+727.823,4.8
+732.249,3.5
+734.557,11.1
+737.084,10.3
+746.159,2.7
+748.313,30.4
+757.809,4.8
+760.14,6.1
+761.4,22.1
+769.285,19.6
+770.036,7.4
+771.12,18
+774.113,20.2
+776.248,15.6
+781.326,10.4
+782.236,16.6
+784.55,21.3
+785.355,7.2
+791.449,16.8
+795.524,10.3
+797.897,23.3
+802.239,4.2
+806.178,9
+807.325,5.9
+808.151,28
+810.506,17.6
+812.404,9.9
+814.347,14.9
+823.687,9.1
+827.2,18.4
+828.495,30.1
+830.456,7.4
+843.74,6.8
+845.378,25.6
+846.124,8.3
+850.279,3.2
+857.077,3.8
+860.066,9.2
+861.488,6.5
+862.229,10.5
+863.078,4.4
+863.694,17.1
+864.537,3.4
+865.37,29
+866.245,2.9
+866.961,5
+867.685,18
+869.123,9.5
+871.775,23.1
+873.595,33
+875.707,15.5
+877.188,8.6
+878.644,40.1
+879.973,24.3
+884.381,12.1
+886.129,4.1
+889.206,23.3
+892.502,5.8
+898.276,6
+898.927,16.5
+900.03,14.9
+909.412,27
+910.736,14.3
+912.761,5.4
+918.955,7.1
+921.403,9.3
+926.314,4.4
+927.264,44.7
+931.4,14
+935.755,38.2
+936.443,115.8
+937.157,28.8
+938.027,22.2
+941.158,10.1
+943.544,11
+944.188,7.1
+948.636,10.5
+949.992,24.9
+953.302,21.2
+954.427,4.4
+955.785,18.5
+956.486,19.9
+957.483,3.3
+958.353,1.8
+960.501,27.3
+963.173,9.4
+964.142,22.2
+965.36,6.2
+968.71,2.3
+972.337,18.3
+977.187,7.9
+977.883,31.1
+979.576,2.3
+981.127,16.5
+982.614,28.6
+985.816,5.4
+987.76,2.7
+988.615,33.4
+989.659,1.4
+991.94,7.3
+997.515,9.1
+998.981,4.4
+1006.169,29.1
+1010.57,37
+1011.619,8.7
+1012.56,16.6
+1013.532,2.3
+1014.498,14.6
+1015.608,15.3
+1019.642,10
+1021.028,41.7
+1022.413,9.2
+1023.351,5.5
+1027.299,33.5
+1028.18,30.7
+1029.408,38.6
+1030.477,7.8
+1036.909,37.6
+1039.308,8.1
+1040.937,11.2
+1044.367,12.5
+1045.892,39.2
+1050.997,37.2
+1051.764,12.1
+1052.551,6.8
+1054.741,35.6
+1063.992,5.6
+1066.194,78.2
+1067.027,17.5
+1067.858,8.2
+1073.451,14.9
+1079.227,25.6
+1079.99,8.4
+1082.4,16.5
+1084.332,2
+1086.278,22.7
+1089.943,5.9
+1093.599,9.8
+1095.441,18.3
+1098.684,19.2
+1100.082,36.8
+1101.255,39.7
+1102.073,36.5
+1104.673,21.7
+1105.894,39.8
+1107.651,81.8
+1108.383,5.1
+1110.158,34.4
+1112.243,8.9
+1113.991,31.6
+1114.941,21.8
+1117.156,37.9
+1118.251,13.7
+1119.673,13.6
+1121.348,7.2
+1123.233,10.2
+1127.54,43.5
+1128.585,21.7
+1129.482,19.5
+1130.406,51.5
+1131.208,4.5
+1132.497,5.8
+1133.583,6.7
+1134.654,30.1
+1137.003,28.5
+1137.673,13.1
+1138.498,47.4
+1139.625,6.8
+1140.367,23.8
+1141.502,22.6
+1142.81,40.5
+1144.252,51.2
+1145.315,4.5
+1147.506,29.2
+1148.341,32.5
+1151.129,126.4
+1152.22,60.4
+1152.823,14.7
+1154.932,31
+1162.154,49
+1164.805,76.8
+1166.633,47.6
+1167.393,26.2
+1171.333,25
+1172.483,37.4
+1175.112,2.9
+1176.211,11.2
+1178.166,19
+1184.656,69.2
+1187.041,11.2
+1188.91,4.9
+1189.981,16.8
+1191.568,56.8
+1192.313,39.5
+1194.053,97.9
+1198.711,14.1
+1200.49,46.3
+1201.23,87.7
+1203.361,35.4
+1204.856,31.6
+1205.686,15.6
+1208.25,162.5
+1209.074,105.6
+1210.19,27.5
+1211.234,95.1
+1212.46,20.1
+1213.107,6.3
+1214.067,17.5
+1215.322,31.3
+1216.301,61.7
+1217.571,2.3
+1219.321,22
+1220.489,66.3
+1221.754,27
+1224.069,89.6
+1225.273,30.7
+1227.152,52.9
+1228.536,91.2
+1229.343,42.7
+1231.135,98.6
+1232.771,60.1
+1233.689,24.2
+1234.882,31.4
+1235.614,8.8
+1237.141,127.1
+1237.827,4.4
+1238.749,13
+1240.373,34.6
+1241.888,103.3
+1242.591,16.9
+1243.577,44.3
+1245.452,9.8
+1246.217,46.5
+1247.278,78
+1247.923,116.4
+1248.606,32.7
+1251.051,89.4
+1252.053,70.9
+1253.464,33.1
+1254.479,6.9
+1255.237,59.6
+1257.995,26.8
+1258.606,11.3
+1259.428,35.9
+1260.38,8.7
+1261.228,12.7
+1261.916,28.4
+1263.386,139.8
+1264.383,107.9
+1265.479,59.8
+1266.553,34
+1268.225,19.6
+1293.355,43.3
+1295.413,7.2
+1296.031,4
+1296.665,6.3
+1301.846,13.4
+1307.085,3.1
+1308.874,1.7
+1313.282,9.5
+1315.804,172
+1316.719,6.9
+1319.764,79.3
+1321.402,7.2
+1322.577,22.7
+1324.4,65.6
+1327.032,22.2
+1330.641,37
+1334.25,7
+1338.436,102.5
+1339.314,55.7
+1340.176,29.1
+1343.637,88.2
+1345.073,44.8
+1346.231,211.3
+1348.111,36.6
+1348.961,36.9
+1350.008,17.9
+1351.19,103.6
+1352.408,35.3
+1353.43,14.2
+1354.406,27.6
+1357.8,114
+1360.742,9.2
+1361.683,65.7
+1364.713,56.9
+1366.008,138
+1366.94,148.6
+1368.956,3.8
+1369.623,49.2
+1371.214,44.1
+1371.996,9.7
+1373.184,32.9
+1374.701,51.1
+1375.658,19.1
+1376.811,78.7
+1377.861,58.7
+1379.2,23
+1380.332,9
+1381.758,54.9
+1382.655,9.4
+1385.597,3.5
+1388.394,34
+1389.752,23.4
+1394.69,57.8
+1396.199,87.4
+1398.121,24.5
+1399.263,50.7
+1399.986,39.5
+1400.976,22.2
+1401.658,19.8
+1404.554,4.7
+1406.023,149.8
+1407.653,102.3
+1408.662,122.2
+1410.262,9.1
+1412.521,55.2
+1413.722,28
+1414.519,7.4
+1415.885,46.8
+1416.529,68.8
+1417.396,43.8
+1418.646,15.6
+1419.44,19.9
+1420.465,37.1
+1421.18,15.6
+1421.781,11.7
+1425.811,66.4
+1426.508,21.9
+1427.809,100.8
+1428.738,40.9
+1429.699,38.1
+1430.719,149.2
+1431.797,17.1
+1433.272,44.9
+1434.431,19.6
+1435.499,3.7
+1436.441,157.8
+1437.197,10.1
+1438.124,44.7
+1439.672,34.1
+1440.665,21
+1443.418,95.4
+1445.228,1.9
+1452.395,64.6
+1453.295,6.1
+1457.18,56.3
+1457.937,14.4
+1461.855,59.9
+1462.94,56.6
+1465.69,66.5
+1467.527,3.1
+1468.586,46.6
+1469.345,7.4
+1471.001,10.1
+1471.636,26.3
+1472.641,4.9
+1474.849,37.1
+1476.141,18.8
+1477.515,27.1
+1478.308,24
+1479.975,69.4
+1480.648,1.6
+1482.259,44.5
+1483.001,11.9
+1485.136,105.5
+1485.775,34
+1487.783,45.4
+1488.809,24.7
+1489.921,17.7
+1490.549,26.3
+1491.54,14.1
+1492.506,33.6
+1495.197,17.3
+1497.236,89.7
+1499.61,22.2
+1501.811,4.1
+1503.396,5.3
+1506.86,62.9
+1507.815,26.3
+1509.434,8.5
+1510.356,73.2
+1511.509,23.9
+1512.637,4.4
+1513.458,43.5
+1514.126,49.2
+1515.093,14.2
+1516.977,116.6
+1517.984,101.5
+1518.663,2
+1519.405,14.7
+1521.016,71.6
+1522.858,55.3
+1523.861,22.3
+1530.29,22.9
+1532.912,14.9
+1533.566,4.7
+1534.514,4
+1536.546,43.2
+1540.464,35.4
+1541.603,34.5
+1542.626,70.3
+1543.92,23.6
+1547.329,33.5
+1548.741,1.8
+1550.543,37.9
+1552.905,208.3
+1554.226,189.6
+1555.085,75.2
+1555.735,1.7
+1557.289,29.8
+1559.157,324.6
+1559.952,107.5
+1560.63,24.8
+1561.873,47.9
+1564.207,32
+1566.253,16.2
+1570.567,71.9
+1574.427,87.7
+1575.359,18.2
+1576.878,10.9
+1578.463,27.1
+1579.13,18.7
+1585.852,27.3
+1586.662,14.1
+1587.379,5.2
+1588.339,42.1
+1589.874,9.1
+1591.224,51.8
+1591.911,36.4
+1592.852,1.8
+1593.993,18.1
+1599.533,19.1
+1600.61,3.4
+1603.868,22
+1607.7,35.2
+1608.997,46
+1609.724,14.5
+1612.595,25.5
+1614.184,38.3
+1615.699,21.4
+1617.191,5.8
+1621.281,9.5
+1622.297,10
+1623.798,12.5
+1625.681,9.9
+1627.395,91.3
+1628.626,12.3
+1629.541,46.3
+1631.565,28.9
+1632.856,25.7
+1635.644,62.6
+1636.626,18.5
+1637.368,5.4
+1638.403,10.8
+1639.443,10
+1641.071,138.9
+1642.24,43.3
+1643.216,25.1
+1645.007,56.8
+1645.741,6.7
+1646.584,14.5
+1647.69,20.6
+1649.052,10.8
+1650.903,15.4
+1652.112,6.8
+1652.983,26.7
+1655.4,5
+1657.846,12.2
+1660.164,48.9
+1661.677,9.7
+1668.584,81.2
+1669.305,4
+1671.813,11.1
+1673.349,3.8
+1674.4,2
+1677.662,18.3
+1680.044,33.1
+1681.242,10.9
+1683.692,8.4
+1684.381,27.5
+1685.214,10.7
+1686.462,29
+1687.508,4
+1691.522,14.7
+1692.641,26.8
+1696.366,52.5
+1697.557,16.6
+1701.681,10.7
+1703.762,54.7
+1704.699,28
+1706.526,43.6
+1709.564,38.9
+1710.894,10.8
+1712.526,34.4
+1713.199,23.2
+1714.573,14.4
+1716.483,22.7
+1721.385,11.8
+1722.673,35.4
+1723.455,25.4
+1724.685,20.4
+1725.61,6.2
+1729.942,28.7
+1732.083,30.6
+1733.53,50.2
+1734.614,16.2
+1738.318,12.7
+1739.396,14.5
+1742.212,15.2
+1742.843,5.2
+1743.916,10.3
+1745.901,12.1
+1747.494,6.9
+1750.433,25.8
+1754.032,5.9
+1755.026,11.5
+1757.642,29.6
+1758.323,3.1
+1763.382,16
+1769.582,8.3
+1771.219,14.2
+1773.064,4.5
+1776.647,2.2
+1782.317,21.7
+1786.912,19.8
+1793.615,25.1
+1795.543,7.2
+1796.843,1.4
+1798.764,12.9
+1800.335,2.7
+1802.575,17.4
+1813.584,15.1
+1814.362,6
+1817.63,30.6
+1821.513,15.7
+1823.36,42.8
+1824.44,16.3
+1827.192,16.4
+1828.6,27.1
+1829.759,12
+1832.786,40.6
+1836.984,92.8
+1837.818,13.8
+1840.404,17.8
+1841.535,6.7
+1848.037,25.9
+1848.717,3.8
+1850.918,2
+1852.771,8.4
+1853.778,7.8
+1854.645,26.5
+1857.714,21.1
+1862.614,11.2
+1871.483,53.1
+1874.175,18.6
+1874.981,15.3
+1877.145,6
+1879.476,23.2
+1894.793,19.1
+1895.553,5.4
+1897.367,7.7
+1898.021,1.2
+1906.242,14.3
+1914.824,4.1
+1919.659,3.5
+1924.77,36.3
+1937.047,20.7
+1939.232,18.3
+1942.525,9.2
+1943.27,6.3
+1948.095,13.3
+1951.771,25.6
+1961.532,9.5
+1967.624,9.9
+1969.254,7.2
+1971.767,6.8
+1987.625,23
+1990.602,4.4
+FragModelIonMatchListEnd
+FragModelIonMatchListCaption=CaM_S5_005_060925_: Scan 11275
+FragModelIonAlignment=0
+[PlotOptions_Series1]
+SeriesPlotMode=1
+SeriesLineStyle=0
+SeriesLineWidth=1
+SeriesLineColor=255
+SeriesLineToBaseColor=255
+SeriesBarFillColor=255
+SeriesPointStyle=0
+SeriesPointColor=255
+AnnotationFontName=Arial
+AnnotationFontSize=10
+AnnotationFontColor=0
+[PlotOptions_Series2]
+SeriesPlotMode=1
+SeriesLineStyle=0
+SeriesLineWidth=1
+SeriesLineColor=40960
+SeriesLineToBaseColor=40960
+SeriesBarFillColor=40960
+SeriesPointStyle=0
+SeriesPointColor=40960
+AnnotationFontName=Arial
+AnnotationFontSize=10
+AnnotationFontColor=0
+[GlobalPlotOptions]
+Title=
+Subtitle=
+XAxis=
+YAxis=
+LabelFontName=Arial
+LabelFontSize=Arial
+LabelFontColor=0
+PlotBackgroundColor=16777215
+NormalizeOnLoadOrPaste=True
+NormalizationConstant=100
+GridLinesXColorMajor=0
+GridLinesXColorMinor=8421504
+GridLinesYColorMajor=0
+GridLinesYColorMinor=8421504
+GridLinesXVisibleMajor=False
+GridLinesXVisibleMinor=False
+GridLinesYVisibleMajor=False
+GridLinesYVisibleMinor=False
+AnnotationDensityAutoHideCaptions=True
+AnnotationDensityToleranceAutoAdjust=True
+AnnotationDensityToleranceX=0.562291337199086
+AnnotationDensityToleranceY=0.5420054200542
+AutoScaleVisibleY=False
+FixMinimumYAtZero=False
+AutoAdjustScalingToIncludeCaptions=True
+PrecisionX=2
+PrecisionY=1
+CursorVisible=True
+CursorSnapToData=False
+CursorColor=0
+CursorPositionX=0
+CursorPositionY=0
+AutoLabelPeaksDisplayXPosition=True
+AutoLabelPeaksDisplayYPosition=False
+AutoLabelPeaksIncludeArrow=False
+AutoLabelPeaksHideInDenseRegions=True
+AutoLabelPeaksCaptionAngle=0
+AutoLabelPeaksIntensityThresholdMinimum=10
+AutoLabelPeaksMinimumIntensityPercentageOfMaximum=0
+AutoLabelPeaksPeakWidthMinimumPoints=5
+AutoLabelPeaksLabelCountMaximum=100
diff --git a/Mercury_FromRockwood/SN15-M b/Mercury_FromRockwood/SN15-M
new file mode 100644
index 0000000..62fee6a
--- /dev/null
+++ b/Mercury_FromRockwood/SN15-M
@@ -0,0 +1,2048 @@
+1716.652710 -0.000000
+1716.715210 0.000000
+1716.777710 -0.000000
+1716.840210 0.000000
+1716.902710 -0.000000
+1716.965210 0.000000
+1717.027710 -0.000000
+1717.090210 0.000000
+1717.152710 -0.000000
+1717.215210 0.000000
+1717.277710 -0.000000
+1717.340210 0.000000
+1717.402710 -0.000000
+1717.465210 0.000000
+1717.527710 -0.000000
+1717.590210 0.000000
+1717.652710 -0.000000
+1717.715210 0.000000
+1717.777710 -0.000000
+1717.840210 0.000000
+1717.902710 -0.000000
+1717.965210 0.000000
+1718.027710 -0.000000
+1718.090210 0.000000
+1718.152710 -0.000000
+1718.215210 0.000000
+1718.277710 -0.000000
+1718.340210 0.000000
+1718.402710 -0.000000
+1718.465210 0.000000
+1718.527710 -0.000000
+1718.590210 0.000000
+1718.652710 -0.000000
+1718.715210 0.000000
+1718.777710 -0.000000
+1718.840210 0.000000
+1718.902710 -0.000000
+1718.965210 0.000000
+1719.027710 -0.000000
+1719.090210 0.000000
+1719.152710 -0.000000
+1719.215210 0.000000
+1719.277710 -0.000000
+1719.340210 0.000000
+1719.402710 -0.000000
+1719.465210 0.000000
+1719.527710 -0.000000
+1719.590210 0.000000
+1719.652710 -0.000000
+1719.715210 0.000000
+1719.777710 -0.000000
+1719.840210 0.000000
+1719.902710 -0.000000
+1719.965210 0.000000
+1720.027710 -0.000000
+1720.090210 0.000000
+1720.152710 0.000000
+1720.215210 -0.000000
+1720.277710 0.000000
+1720.340210 -0.000000
+1720.402710 0.000000
+1720.465210 0.000000
+1720.527710 0.000000
+1720.590210 0.000000
+1720.652710 0.000000
+1720.715210 -0.000000
+1720.777710 0.000000
+1720.840210 -0.000000
+1720.902710 0.000000
+1720.965210 -0.000000
+1721.027710 0.000000
+1721.090210 -0.000000
+1721.152710 0.000000
+1721.215210 -0.000000
+1721.277710 0.000000
+1721.340210 -0.000000
+1721.402710 0.000000
+1721.465210 -0.000000
+1721.527710 0.000000
+1721.590210 -0.000000
+1721.652710 0.000000
+1721.715210 -0.000000
+1721.777710 0.000000
+1721.840210 -0.000000
+1721.902710 0.000000
+1721.965210 -0.000000
+1722.027710 0.000000
+1722.090210 -0.000000
+1722.152710 0.000000
+1722.215210 -0.000000
+1722.277710 0.000000
+1722.340210 -0.000000
+1722.402710 0.000000
+1722.465210 -0.000000
+1722.527710 0.000000
+1722.590210 -0.000000
+1722.652710 0.000000
+1722.715210 -0.000000
+1722.777710 0.000000
+1722.840210 -0.000000
+1722.902710 0.000000
+1722.965210 -0.000000
+1723.027710 0.000000
+1723.090210 -0.000000
+1723.152710 0.000000
+1723.215210 -0.000000
+1723.277710 0.000000
+1723.340210 -0.000000
+1723.402710 0.000000
+1723.465210 0.000000
+1723.527710 0.000000
+1723.590210 0.000000
+1723.652710 0.000000
+1723.715210 -0.000000
+1723.777710 0.000000
+1723.840210 -0.000000
+1723.902710 0.000000
+1723.965210 -0.000000
+1724.027710 0.000000
+1724.090210 -0.000000
+1724.152710 0.000000
+1724.215210 -0.000000
+1724.277710 0.000000
+1724.340210 -0.000000
+1724.402710 0.000000
+1724.465210 0.000000
+1724.527710 0.000000
+1724.590210 0.000000
+1724.652710 0.000000
+1724.715210 -0.000000
+1724.777710 0.000000
+1724.840210 -0.000000
+1724.902710 0.000000
+1724.965210 -0.000000
+1725.027710 0.000000
+1725.090210 -0.000000
+1725.152710 0.000000
+1725.215210 -0.000000
+1725.277710 0.000000
+1725.340210 -0.000000
+1725.402710 0.000000
+1725.465210 0.000000
+1725.527710 0.000000
+1725.590210 0.000000
+1725.652710 0.000000
+1725.715210 0.000000
+1725.777710 0.000000
+1725.840210 -0.000000
+1725.902710 0.000000
+1725.965210 -0.000000
+1726.027710 0.000000
+1726.090210 -0.000000
+1726.152710 0.000000
+1726.215210 -0.000000
+1726.277710 0.000000
+1726.340210 0.000000
+1726.402710 0.000000
+1726.465210 0.000000
+1726.527710 0.000000
+1726.590210 0.000000
+1726.652710 0.000000
+1726.715210 0.000000
+1726.777710 0.000000
+1726.840210 -0.000000
+1726.902710 0.000000
+1726.965210 -0.000000
+1727.027710 0.000000
+1727.090210 -0.000000
+1727.152710 0.000000
+1727.215210 -0.000000
+1727.277710 0.000000
+1727.340210 0.000000
+1727.402710 0.000000
+1727.465210 0.000000
+1727.527710 0.000000
+1727.590210 0.000000
+1727.652710 0.000000
+1727.715210 0.000000
+1727.777710 0.000000
+1727.840210 -0.000000
+1727.902710 0.000000
+1727.965210 -0.000000
+1728.027710 0.000000
+1728.090210 -0.000000
+1728.152710 0.000000
+1728.215210 -0.000000
+1728.277710 0.000000
+1728.340210 0.000000
+1728.402710 0.000000
+1728.465210 0.000001
+1728.527710 0.000001
+1728.590210 0.000001
+1728.652710 0.000001
+1728.715210 0.000000
+1728.777710 0.000000
+1728.840210 -0.000000
+1728.902710 0.000000
+1728.965210 -0.000000
+1729.027710 0.000000
+1729.090210 -0.000000
+1729.152710 0.000000
+1729.215210 -0.000000
+1729.277710 0.000000
+1729.340210 0.000000
+1729.402710 0.000001
+1729.465210 0.000001
+1729.527710 0.000002
+1729.590210 0.000001
+1729.652710 0.000001
+1729.715210 0.000000
+1729.777710 0.000000
+1729.840210 -0.000000
+1729.902710 0.000000
+1729.965210 -0.000000
+1730.027710 0.000000
+1730.090210 -0.000000
+1730.152710 0.000000
+1730.215210 -0.000000
+1730.277710 0.000000
+1730.340210 0.000001
+1730.402710 0.000001
+1730.465210 0.000002
+1730.527710 0.000003
+1730.590210 0.000003
+1730.652710 0.000002
+1730.715210 0.000001
+1730.777710 0.000000
+1730.840210 0.000000
+1730.902710 0.000000
+1730.965210 -0.000000
+1731.027710 0.000000
+1731.090210 -0.000000
+1731.152710 0.000000
+1731.215210 0.000000
+1731.277710 0.000000
+1731.340210 0.000001
+1731.402710 0.000003
+1731.465210 0.000004
+1731.527710 0.000006
+1731.590210 0.000005
+1731.652710 0.000003
+1731.715210 0.000002
+1731.777710 0.000001
+1731.840210 0.000000
+1731.902710 0.000000
+1731.965210 -0.000000
+1732.027710 0.000000
+1732.090210 -0.000000
+1732.152710 0.000000
+1732.215210 0.000000
+1732.277710 0.000001
+1732.340210 0.000002
+1732.402710 0.000005
+1732.465210 0.000008
+1732.527710 0.000011
+1732.590210 0.000010
+1732.652710 0.000007
+1732.715210 0.000003
+1732.777710 0.000001
+1732.840210 0.000000
+1732.902710 0.000000
+1732.965210 -0.000000
+1733.027710 0.000000
+1733.090210 -0.000000
+1733.152710 0.000000
+1733.215210 0.000000
+1733.277710 0.000001
+1733.340210 0.000004
+1733.402710 0.000009
+1733.465210 0.000015
+1733.527710 0.000019
+1733.590210 0.000018
+1733.652710 0.000012
+1733.715210 0.000006
+1733.777710 0.000002
+1733.840210 0.000000
+1733.902710 0.000000
+1733.965210 -0.000000
+1734.027710 0.000000
+1734.090210 -0.000000
+1734.152710 0.000000
+1734.215210 0.000000
+1734.277710 0.000002
+1734.340210 0.000007
+1734.402710 0.000017
+1734.465210 0.000029
+1734.527710 0.000036
+1734.590210 0.000033
+1734.652710 0.000022
+1734.715210 0.000011
+1734.777710 0.000004
+1734.840210 0.000001
+1734.902710 0.000000
+1734.965210 -0.000000
+1735.027710 0.000000
+1735.090210 -0.000000
+1735.152710 0.000000
+1735.215210 0.000001
+1735.277710 0.000004
+1735.340210 0.000013
+1735.402710 0.000031
+1735.465210 0.000052
+1735.527710 0.000065
+1735.590210 0.000059
+1735.652710 0.000039
+1735.715210 0.000019
+1735.777710 0.000007
+1735.840210 0.000002
+1735.902710 0.000000
+1735.965210 -0.000000
+1736.027710 0.000000
+1736.090210 -0.000000
+1736.152710 0.000000
+1736.215210 0.000002
+1736.277710 0.000008
+1736.340210 0.000024
+1736.402710 0.000056
+1736.465210 0.000094
+1736.527710 0.000117
+1736.590210 0.000106
+1736.652710 0.000071
+1736.715210 0.000035
+1736.777710 0.000013
+1736.840210 0.000003
+1736.902710 0.000001
+1736.965210 0.000000
+1737.027710 0.000000
+1737.090210 -0.000000
+1737.152710 0.000001
+1737.215210 0.000003
+1737.277710 0.000014
+1737.340210 0.000043
+1737.402710 0.000100
+1737.465210 0.000168
+1737.527710 0.000207
+1737.590210 0.000188
+1737.652710 0.000125
+1737.715210 0.000061
+1737.777710 0.000022
+1737.840210 0.000006
+1737.902710 0.000001
+1737.965210 0.000000
+1738.027710 0.000000
+1738.090210 0.000000
+1738.152710 0.000001
+1738.215210 0.000006
+1738.277710 0.000025
+1738.340210 0.000078
+1738.402710 0.000178
+1738.465210 0.000298
+1738.527710 0.000367
+1738.590210 0.000332
+1738.652710 0.000221
+1738.715210 0.000108
+1738.777710 0.000039
+1738.840210 0.000010
+1738.902710 0.000002
+1738.965210 0.000000
+1739.027710 0.000000
+1739.090210 0.000000
+1739.152710 0.000002
+1739.215210 0.000010
+1739.277710 0.000044
+1739.340210 0.000135
+1739.402710 0.000309
+1739.465210 0.000518
+1739.527710 0.000637
+1739.590210 0.000576
+1739.652710 0.000383
+1739.715210 0.000187
+1739.777710 0.000067
+1739.840210 0.000018
+1739.902710 0.000004
+1739.965210 0.000000
+1740.027710 0.000000
+1740.090210 0.000000
+1740.152710 0.000003
+1740.215210 0.000018
+1740.277710 0.000077
+1740.340210 0.000237
+1740.402710 0.000538
+1740.465210 0.000900
+1740.527710 0.001105
+1740.590210 0.000997
+1740.652710 0.000662
+1740.715210 0.000322
+1740.777710 0.000116
+1740.840210 0.000030
+1740.902710 0.000006
+1740.965210 0.000001
+1741.027710 0.000000
+1741.090210 0.000001
+1741.152710 0.000006
+1741.215210 0.000031
+1741.277710 0.000131
+1741.340210 0.000404
+1741.402710 0.000918
+1741.465210 0.001531
+1741.527710 0.001878
+1741.590210 0.001692
+1741.652710 0.001121
+1741.715210 0.000545
+1741.777710 0.000195
+1741.840210 0.000051
+1741.902710 0.000010
+1741.965210 0.000001
+1742.027710 0.000000
+1742.090210 0.000001
+1742.152710 0.000009
+1742.215210 0.000053
+1742.277710 0.000223
+1742.340210 0.000689
+1742.402710 0.001563
+1742.465210 0.002603
+1742.527710 0.003187
+1742.590210 0.002867
+1742.652710 0.001895
+1742.715210 0.000920
+1742.777710 0.000329
+1742.840210 0.000086
+1742.902710 0.000017
+1742.965210 0.000002
+1743.027710 0.000001
+1743.090210 0.000002
+1743.152710 0.000016
+1743.215210 0.000089
+1743.277710 0.000374
+1743.340210 0.001151
+1743.402710 0.002607
+1743.465210 0.004337
+1743.527710 0.005302
+1743.590210 0.004763
+1743.652710 0.003144
+1743.715210 0.001525
+1743.777710 0.000544
+1743.840210 0.000142
+1743.902710 0.000028
+1743.965210 0.000004
+1744.027710 0.000001
+1744.090210 0.000003
+1744.152710 0.000026
+1744.215210 0.000149
+1744.277710 0.000624
+1744.340210 0.001920
+1744.402710 0.004339
+1744.465210 0.007206
+1744.527710 0.008795
+1744.590210 0.007887
+1744.652710 0.005197
+1744.715210 0.002516
+1744.777710 0.000895
+1744.840210 0.000234
+1744.902710 0.000045
+1744.965210 0.000006
+1745.027710 0.000001
+1745.090210 0.000005
+1745.152710 0.000043
+1745.215210 0.000244
+1745.277710 0.001022
+1745.340210 0.003138
+1745.402710 0.007083
+1745.465210 0.011747
+1745.527710 0.014317
+1745.590210 0.012821
+1745.652710 0.008437
+1745.715210 0.004079
+1745.777710 0.001450
+1745.840210 0.000378
+1745.902710 0.000073
+1745.965210 0.000010
+1746.027710 0.000002
+1746.090210 0.000009
+1746.152710 0.000070
+1746.215210 0.000399
+1746.277710 0.001666
+1746.340210 0.005109
+1746.402710 0.011515
+1746.465210 0.019069
+1746.527710 0.023204
+1746.590210 0.020748
+1746.652710 0.013633
+1746.715210 0.006582
+1746.777710 0.002335
+1746.840210 0.000609
+1746.902710 0.000117
+1746.965210 0.000016
+1747.027710 0.000003
+1747.090210 0.000015
+1747.152710 0.000113
+1747.215210 0.000639
+1747.277710 0.002665
+1747.340210 0.008163
+1747.402710 0.018375
+1747.465210 0.030390
+1747.527710 0.036934
+1747.590210 0.032983
+1747.652710 0.021644
+1747.715210 0.010436
+1747.777710 0.003698
+1747.840210 0.000963
+1747.902710 0.000184
+1747.965210 0.000026
+1748.027710 0.000005
+1748.090210 0.000023
+1748.152710 0.000180
+1748.215210 0.001019
+1748.277710 0.004243
+1748.340210 0.012978
+1748.402710 0.029171
+1748.465210 0.048177
+1748.527710 0.058468
+1748.590210 0.052139
+1748.652710 0.034166
+1748.715210 0.016451
+1748.777710 0.005821
+1748.840210 0.001513
+1748.902710 0.000289
+1748.965210 0.000041
+1749.027710 0.000008
+1749.090210 0.000037
+1749.152710 0.000282
+1749.215210 0.001594
+1749.277710 0.006630
+1749.340210 0.020256
+1749.402710 0.045475
+1749.465210 0.075017
+1749.527710 0.090935
+1749.590210 0.080997
+1749.652710 0.053014
+1749.715210 0.025497
+1749.777710 0.009011
+1749.840210 0.002340
+1749.902710 0.000447
+1749.965210 0.000063
+1750.027710 0.000012
+1750.090210 0.000057
+1750.152710 0.000439
+1750.215210 0.002480
+1750.277710 0.010298
+1750.340210 0.031422
+1750.402710 0.070452
+1750.465210 0.116069
+1750.527710 0.140515
+1750.590210 0.124998
+1750.652710 0.081708
+1750.715210 0.039247
+1750.777710 0.013853
+1750.840210 0.003592
+1750.902710 0.000685
+1750.965210 0.000096
+1751.027710 0.000018
+1751.090210 0.000088
+1751.152710 0.000671
+1751.215210 0.003786
+1751.277710 0.015705
+1751.340210 0.047868
+1751.402710 0.107213
+1751.465210 0.176449
+1751.527710 0.213389
+1751.590210 0.189625
+1751.652710 0.123823
+1751.715210 0.059413
+1751.777710 0.020948
+1751.840210 0.005427
+1751.902710 0.001033
+1751.965210 0.000145
+1752.027710 0.000028
+1752.090210 0.000134
+1752.152710 0.001018
+1752.215210 0.005740
+1752.277710 0.023784
+1752.340210 0.072409
+1752.402710 0.161989
+1752.465210 0.266291
+1752.527710 0.321666
+1752.590210 0.285515
+1752.652710 0.186222
+1752.715210 0.089251
+1752.777710 0.031432
+1752.840210 0.008134
+1752.902710 0.001547
+1752.965210 0.000217
+1753.027710 0.000041
+1753.090210 0.000199
+1753.152710 0.001517
+1753.215210 0.008544
+1753.277710 0.035369
+1753.340210 0.107581
+1753.402710 0.240455
+1753.465210 0.394916
+1753.527710 0.476598
+1753.590210 0.422644
+1753.652710 0.275406
+1753.715210 0.131871
+1753.777710 0.046399
+1753.840210 0.011996
+1753.902710 0.002279
+1753.965210 0.000320
+1754.027710 0.000061
+1754.090210 0.000295
+1754.152710 0.002243
+1754.215210 0.012620
+1754.277710 0.052187
+1754.340210 0.158577
+1754.402710 0.354075
+1754.465210 0.580931
+1754.527710 0.700375
+1754.590210 0.620459
+1754.652710 0.403899
+1754.715210 0.193201
+1754.777710 0.067909
+1754.840210 0.017539
+1754.902710 0.003329
+1754.965210 0.000467
+1755.027710 0.000089
+1755.090210 0.000429
+1755.152710 0.003255
+1755.215210 0.018300
+1755.277710 0.075617
+1755.340210 0.229595
+1755.402710 0.512246
+1755.465210 0.839783
+1755.527710 1.011651
+1755.590210 0.895507
+1755.652710 0.582484
+1755.715210 0.278403
+1755.777710 0.097778
+1755.840210 0.025234
+1755.902710 0.004786
+1755.965210 0.000671
+1756.027710 0.000127
+1756.090210 0.000617
+1756.152710 0.004684
+1756.215210 0.026311
+1756.277710 0.108627
+1756.340210 0.329535
+1756.402710 0.734583
+1756.465210 1.203245
+1756.527710 1.448245
+1756.590210 1.280871
+1756.652710 0.832425
+1756.715210 0.397522
+1756.777710 0.139494
+1756.840210 0.035969
+1756.902710 0.006816
+1756.965210 0.000955
+1757.027710 0.000181
+1757.090210 0.000873
+1757.152710 0.006615
+1757.215210 0.037138
+1757.277710 0.153230
+1757.340210 0.464551
+1757.402710 1.034896
+1757.465210 1.694070
+1757.527710 2.037696
+1757.590210 1.801030
+1757.652710 1.169707
+1757.715210 0.558223
+1757.777710 0.195756
+1757.840210 0.050443
+1757.902710 0.009552
+1757.965210 0.001337
+1758.027710 0.000253
+1758.090210 0.001222
+1758.152710 0.009257
+1758.215210 0.051938
+1758.277710 0.214139
+1758.340210 0.648753
+1758.402710 1.444223
+1758.465210 2.362444
+1758.527710 2.839631
+1758.590210 2.508049
+1758.652710 1.627739
+1758.715210 0.776263
+1758.777710 0.272025
+1758.840210 0.070046
+1758.902710 0.013255
+1758.965210 0.001854
+1759.027710 0.000349
+1759.090210 0.001679
+1759.152710 0.012714
+1759.215210 0.071297
+1759.277710 0.293817
+1759.340210 0.889718
+1759.402710 1.979692
+1759.465210 3.236779
+1759.527710 3.888659
+1759.590210 3.432877
+1759.652710 2.226842
+1759.715210 1.061436
+1759.777710 0.371769
+1759.840210 0.095681
+1759.902710 0.018096
+1759.965210 0.002530
+1760.027710 0.000475
+1760.090210 0.002285
+1760.152710 0.017290
+1760.215210 0.096909
+1760.277710 0.399151
+1760.340210 1.208023
+1760.402710 2.686481
+1760.465210 4.389978
+1760.527710 5.271230
+1760.590210 4.650859
+1760.652710 3.015275
+1760.715210 1.436461
+1760.777710 0.502846
+1760.840210 0.129345
+1760.902710 0.024449
+1760.965210 0.003416
+1761.027710 0.000638
+1761.090210 0.003051
+1761.152710 0.023070
+1761.215210 0.129269
+1761.277710 0.532268
+1761.340210 1.610393
+1761.402710 3.580145
+1761.465210 5.848401
+1761.527710 7.020089
+1761.590210 6.191810
+1761.652710 4.012944
+1761.715210 1.911084
+1761.777710 0.668757
+1761.840210 0.171961
+1761.902710 0.032493
+1761.965210 0.004538
+1762.027710 0.000846
+1762.090210 0.004031
+1762.152710 0.030467
+1762.215210 0.170651
+1762.277710 0.702394
+1762.340210 2.124310
+1762.402710 4.720875
+1762.465210 7.708939
+1762.527710 9.249864
+1762.590210 8.155402
+1762.652710 5.283546
+1762.715210 2.515224
+1762.777710 0.879832
+1762.840210 0.226149
+1762.902710 0.042715
+1762.965210 0.005963
+1763.027710 0.001104
+1763.090210 0.005223
+1763.152710 0.039466
+1763.215210 0.221025
+1763.277710 0.909601
+1763.340210 2.750576
+1763.402710 6.111685
+1763.465210 9.978460
+1763.527710 11.971053
+1763.590210 10.552814
+1763.652710 6.835530
+1763.715210 3.253456
+1763.777710 1.137856
+1763.840210 0.292415
+1763.902710 0.055221
+1763.965210 0.007707
+1764.027710 0.001421
+1764.090210 0.006695
+1764.152710 0.050577
+1764.215210 0.283195
+1764.277710 1.165211
+1764.340210 3.522794
+1764.402710 7.825896
+1764.465210 12.774560
+1764.527710 15.322291
+1764.590210 13.504180
+1764.652710 8.745413
+1764.715210 4.161605
+1764.777710 1.455160
+1764.840210 0.373879
+1764.902710 0.070589
+1764.965210 0.009849
+1765.027710 0.001802
+1765.090210 0.008414
+1765.152710 0.063559
+1765.215210 0.355895
+1765.277710 1.464378
+1765.340210 4.427364
+1765.402710 9.835560
+1765.465210 16.055197
+1765.527710 19.257315
+1765.590210 16.972283
+1765.652710 10.991327
+1765.715210 5.230296
+1765.777710 1.828814
+1765.840210 0.469874
+1765.902710 0.088711
+1765.965210 0.012377
+1766.027710 0.002254
+1766.090210 0.010460
+1766.152710 0.079000
+1766.215210 0.442338
+1766.277710 1.819992
+1766.340210 5.502316
+1766.402710 12.223148
+1766.465210 19.951841
+1766.527710 23.930186
+1766.590210 21.089839
+1766.652710 13.657317
+1766.715210 6.498653
+1766.777710 2.272207
+1766.840210 0.583768
+1766.902710 0.110209
+1766.965210 0.015374
+1767.027710 0.002775
+1767.090210 0.012744
+1767.152710 0.096256
+1767.215210 0.539073
+1767.277710 2.218449
+1767.340210 6.708265
+1767.402710 14.904933
+1767.465210 24.333796
+1767.527710 29.191107
+1767.590210 25.730787
+1767.652710 16.665495
+1767.715210 7.931348
+1767.777710 2.773577
+1767.840210 0.712688
+1767.902710 0.134568
+1767.965210 0.018773
+1768.027710 0.003369
+1768.090210 0.015357
+1768.152710 0.115988
+1768.215210 0.649662
+1768.277710 2.673913
+1768.340210 8.086592
+1768.402710 17.969771
+1768.465210 29.341299
+1768.527710 35.202762
+1768.590210 31.033849
+1768.652710 20.102815
+1768.715210 9.568446
+1768.777710 3.346493
+1768.840210 0.860011
+1768.902710 0.162405
+1768.965210 0.022657
+1769.027710 0.004027
+1769.090210 0.018131
+1769.152710 0.136966
+1769.215210 0.767455
+1769.277710 3.159914
+1769.340210 9.559909
+1769.402710 21.251454
+1769.465210 34.712112
+1769.527710 41.661192
+1769.590210 36.740207
+1769.652710 23.807379
+1769.715210 11.335552
+1769.777710 3.965844
+1769.840210 1.019511
+1769.902710 0.192587
+1769.965210 0.026873
+1770.027710 0.004745
+1770.090210 0.021173
+1770.152710 0.159965
+1770.215210 0.896589
+1770.277710 3.692706
+1770.340210 11.175133
+1770.402710 24.849462
+1770.465210 40.601182
+1770.527710 48.743703
+1770.590210 42.998913
+1770.652710 27.871243
+1770.715210 13.274436
+1770.777710 4.645553
+1770.840210 1.194599
+1770.902710 0.225727
+1770.965210 0.031503
+1771.027710 0.005504
+1771.090210 0.024217
+1771.152710 0.183025
+1771.215210 1.026405
+1771.277710 4.229686
+1771.340210 12.807126
+1771.402710 28.493726
+1771.465210 46.580262
+1771.527710 55.951342
+1771.590210 49.382830
+1771.652710 32.025738
+1771.715210 15.260931
+1771.777710 5.343457
+1771.840210 1.374753
+1771.902710 0.259897
+1771.965210 0.036286
+1772.027710 0.006294
+1772.090210 0.027405
+1772.152710 0.207167
+1772.215210 1.162328
+1772.277710 4.792004
+1772.340210 14.516440
+1772.402710 32.311510
+1772.465210 52.845701
+1772.527710 63.506486
+1772.590210 56.076828
+1772.652710 36.383670
+1772.715210 17.345558
+1772.777710 6.076162
+1772.840210 1.563981
+1772.902710 0.295806
+1772.965210 0.041313
+1773.027710 0.007086
+1773.090210 0.030365
+1773.152710 0.229643
+1773.215210 1.289364
+1773.277710 5.319573
+1773.340210 16.126125
+1773.402710 35.919906
+1773.465210 58.788638
+1773.527710 70.697717
+1773.590210 62.470089
+1773.652710 40.559669
+1773.715210 19.349655
+1773.777710 6.782803
+1773.840210 1.747045
+1773.902710 0.330652
+1773.965210 0.046205
+1774.027710 0.007863
+1774.090210 0.033302
+1774.152710 0.251953
+1774.215210 1.415486
+1774.277710 5.843500
+1774.340210 17.725281
+1774.402710 39.506230
+1774.465210 64.698093
+1774.527710 77.852308
+1774.590210 68.834559
+1774.652710 44.719541
+1774.715210 21.347395
+1774.777710 7.487722
+1774.840210 1.929806
+1774.902710 0.365467
+1774.965210 0.051094
+1775.027710 0.008592
+1775.090210 0.035747
+1775.152710 0.270602
+1775.215210 1.521621
+1775.277710 6.287244
+1775.340210 19.088183
+1775.402710 42.581306
+1775.465210 69.795040
+1775.527710 84.058578
+1775.590210 74.386197
+1775.652710 48.367792
+1775.715210 23.108659
+1775.777710 8.112382
+1775.840210 2.092565
+1775.902710 0.396623
+1775.965210 0.055491
+1776.027710 0.009255
+1776.090210 0.038007
+1776.152710 0.287860
+1776.215210 1.619887
+1776.277710 6.698368
+1776.340210 20.351879
+1776.402710 45.435033
+1776.465210 74.529642
+1776.527710 89.829650
+1776.590210 79.554316
+1776.652710 51.768054
+1776.715210 24.752264
+1776.777710 8.696080
+1776.840210 2.244861
+1776.902710 0.425817
+1776.965210 0.059612
+1777.027710 0.009820
+1777.090210 0.039533
+1777.152710 0.299620
+1777.215210 1.687854
+1777.277710 6.986804
+1777.340210 21.250602
+1777.402710 47.491114
+1777.465210 77.983559
+1777.527710 94.090106
+1777.590210 83.413429
+1777.652710 54.335019
+1777.715210 26.006173
+1777.777710 9.145899
+1777.840210 2.363368
+1777.902710 0.448747
+1777.965210 0.062878
+1778.027710 0.010272
+1778.090210 0.040770
+1778.152710 0.309177
+1778.215210 1.743256
+1778.277710 7.222636
+1778.340210 21.987732
+1778.402710 49.182951
+1778.465210 80.834960
+1778.527710 97.619130
+1778.590210 86.620869
+1778.652710 56.475837
+1778.715210 27.055543
+1778.777710 9.523657
+1778.840210 2.463241
+1778.902710 0.468140
+1778.965210 0.065645
+1779.027710 0.010587
+1779.090210 0.041106
+1779.152710 0.311976
+1779.215210 1.761196
+1779.277710 7.305903
+1779.340210 22.268332
+1779.402710 49.871041
+1779.465210 82.064859
+1779.527710 99.223531
+1779.590210 88.149864
+1779.652710 57.541184
+1779.715210 27.598600
+1779.777710 9.726282
+1779.840210 2.518605
+1779.902710 0.479221
+1779.965210 0.067270
+1780.027710 0.010760
+1780.090210 0.041143
+1780.152710 0.312473
+1780.215210 1.765809
+1780.277710 7.332585
+1780.340210 22.372762
+1780.402710 50.156856
+1780.465210 82.620966
+1780.527710 100.000000
+1780.590210 88.932458
+1780.652710 58.112792
+1780.715210 27.901991
+1780.777710 9.843534
+1780.840210 2.551649
+1780.902710 0.486020
+1780.965210 0.068286
+1781.027710 0.010779
+1781.090210 0.040229
+1781.152710 0.305799
+1781.215210 1.730500
+1781.277710 7.195940
+1781.340210 21.986191
+1781.402710 49.358049
+1781.465210 81.416528
+1781.527710 98.676633
+1781.590210 87.874737
+1781.652710 57.499271
+1781.715210 27.644587
+1781.777710 9.765798
+1781.840210 2.534878
+1781.902710 0.483466
+1781.965210 0.068010
+1782.027710 0.010649
+1782.090210 0.039108
+1782.152710 0.297508
+1782.215210 1.685506
+1782.277710 7.016899
+1782.340210 21.463884
+1782.402710 48.241240
+1782.465210 79.666683
+1782.527710 96.668181
+1782.590210 86.186582
+1782.652710 56.460612
+1782.715210 27.177039
+1782.777710 9.611909
+1782.840210 2.497870
+1782.902710 0.476969
+1782.965210 0.067164
+1783.027710 0.010376
+1783.090210 0.037101
+1783.152710 0.282513
+1783.215210 1.603042
+1783.277710 6.683943
+1783.340210 20.476979
+1783.402710 46.093859
+1783.465210 76.236931
+1783.527710 92.647425
+1783.590210 82.727083
+1783.652710 54.276150
+1783.715210 26.164845
+1783.777710 9.267774
+1783.840210 2.412030
+1783.902710 0.461261
+1783.965210 0.065042
+1784.027710 0.009971
+1784.090210 0.035060
+1784.152710 0.267197
+1784.215210 1.518031
+1784.277710 6.337437
+1784.340210 19.439898
+1784.402710 43.814741
+1784.465210 72.559363
+1784.527710 88.290506
+1784.590210 78.937357
+1784.652710 51.856076
+1784.715210 25.030296
+1784.777710 8.877319
+1784.840210 2.313390
+1784.902710 0.442969
+1784.965210 0.062534
+1785.027710 0.009456
+1785.090210 0.032287
+1785.152710 0.246320
+1785.215210 1.401820
+1785.277710 5.862304
+1785.340210 18.013089
+1785.402710 40.667788
+1785.465210 67.461578
+1785.527710 82.225484
+1785.590210 73.637857
+1785.652710 48.455279
+1785.715210 23.427564
+1785.777710 8.322609
+1785.840210 2.172401
+1785.902710 0.416653
+1785.965210 0.058909
+1786.027710 0.008845
+1786.090210 0.029686
+1786.152710 0.226682
+1786.215210 1.291788
+1786.277710 5.409443
+1786.340210 16.644094
+1786.402710 37.628125
+1786.465210 62.504422
+1786.527710 76.287779
+1786.590210 68.414149
+1786.652710 45.080012
+1786.715210 21.825790
+1786.777710 7.764329
+1786.840210 2.029493
+1786.902710 0.389786
+1786.965210 0.055179
+1787.027710 0.008170
+1787.090210 0.026550
+1787.152710 0.202960
+1787.215210 1.158777
+1787.277710 4.861541
+1787.340210 14.986165
+1787.402710 33.942814
+1787.465210 56.486813
+1787.527710 69.069855
+1787.590210 62.054458
+1787.652710 40.963858
+1787.715210 19.868858
+1787.777710 7.080915
+1787.840210 1.854181
+1787.902710 0.356752
+1787.965210 0.050588
+1788.027710 0.007443
+1788.090210 0.023775
+1788.152710 0.181915
+1788.215210 1.040095
+1788.277710 4.369845
+1788.340210 13.489767
+1788.402710 30.597524
+1788.465210 50.993242
+1788.527710 62.442990
+1788.590210 56.182376
+1788.652710 37.141737
+1788.715210 18.041419
+1788.777710 6.439107
+1788.840210 1.688608
+1788.902710 0.325375
+1788.965210 0.046200
+1789.027710 0.006702
+1789.090210 0.020660
+1789.152710 0.158257
+1789.215210 0.906677
+1789.277710 3.817061
+1789.340210 11.807180
+1789.402710 26.835038
+1789.465210 44.812403
+1789.527710 54.983778
+1789.590210 49.569202
+1789.652710 32.834522
+1789.715210 15.980547
+1789.777710 5.714719
+1789.840210 1.501559
+1789.902710 0.289893
+1789.965210 0.041238
+1790.027710 0.005950
+1790.090210 0.018036
+1790.152710 0.138294
+1790.215210 0.793475
+1790.277710 3.345451
+1790.340210 10.363834
+1790.402710 23.590019
+1790.465210 39.452931
+1790.527710 48.481219
+1790.590210 43.773541
+1790.652710 29.039825
+1790.715210 14.155367
+1790.777710 5.069827
+1790.840210 1.334172
+1790.902710 0.257976
+1790.965210 0.036749
+1791.027710 0.005226
+1791.090210 0.015232
+1791.152710 0.116931
+1791.215210 0.672387
+1791.277710 2.841162
+1791.340210 8.820874
+1791.402710 20.121670
+1791.465210 33.725190
+1791.527710 41.532010
+1791.590210 37.579445
+1791.652710 24.983713
+1791.715210 12.204039
+1791.777710 4.380162
+1791.840210 1.155098
+1791.902710 0.223816
+1791.965210 0.031948
+1792.027710 0.004524
+1792.090210 0.012978
+1792.152710 0.099727
+1792.215210 0.574329
+1792.277710 2.430528
+1792.340210 7.557600
+1792.402710 17.266636
+1792.465210 28.984994
+1792.527710 35.750361
+1792.590210 32.398877
+1792.652710 21.573571
+1792.715210 10.554977
+1792.777710 3.794335
+1792.840210 1.002211
+1792.902710 0.194504
+1792.965210 0.027804
+1793.027710 0.003880
+1793.090210 0.010655
+1793.152710 0.081970
+1793.215210 0.473191
+1793.277710 2.007272
+1793.340210 6.256232
+1793.402710 14.326952
+1793.465210 24.106291
+1793.527710 29.801822
+1793.590210 27.070218
+1793.652710 18.066645
+1793.715210 8.859329
+1793.777710 3.191991
+1793.840210 0.845011
+1793.902710 0.164363
+1793.965210 0.023547
+1794.027710 0.003275
+1794.090210 0.008870
+1794.152710 0.068307
+1794.215210 0.394926
+1794.277710 1.677869
+1794.340210 5.237722
+1794.402710 12.013398
+1794.465210 20.245539
+1794.527710 25.068763
+1794.590210 22.807471
+1794.652710 15.246219
+1794.715210 7.488393
+1794.777710 2.702442
+1794.840210 0.716585
+1794.902710 0.139612
+1794.965210 0.020031
+1795.027710 0.002745
+1795.090210 0.007080
+1795.152710 0.054581
+1795.215210 0.316375
+1795.277710 1.347571
+1795.340210 4.217315
+1795.402710 9.697334
+1795.465210 16.383315
+1795.527710 20.336887
+1795.590210 18.548172
+1795.652710 12.429451
+1795.715210 6.119807
+1795.777710 2.213902
+1795.840210 0.588459
+1795.902710 0.114924
+1795.965210 0.016528
+1796.027710 0.002261
+1796.090210 0.005765
+1796.152710 0.044493
+1796.215210 0.258299
+1796.277710 1.101907
+1796.340210 3.453889
+1796.402710 7.954428
+1796.465210 13.460088
+1796.527710 16.734979
+1796.590210 15.287672
+1796.652710 10.261161
+1796.715210 5.060475
+1796.777710 1.833688
+1796.840210 0.488204
+1796.902710 0.095503
+1796.965210 0.013755
+1797.027710 0.001853
+1797.090210 0.004474
+1797.152710 0.034558
+1797.215210 0.201170
+1797.277710 0.860549
+1797.340210 2.704707
+1797.402710 6.245881
+1797.465210 10.597362
+1797.527710 13.210896
+1797.590210 12.100351
+1797.652710 8.143199
+1797.715210 4.026468
+1797.777710 1.462802
+1797.840210 0.390464
+1797.902710 0.076579
+1797.965210 0.011058
+1798.027710 0.001489
+1798.090210 0.003568
+1798.152710 0.027592
+1798.215210 0.160866
+1798.277710 0.689191
+1798.340210 2.169472
+1798.402710 5.017688
+1798.465210 8.526875
+1798.527710 10.646640
+1798.590210 9.767251
+1798.652710 6.583686
+1798.715210 3.260646
+1798.777710 1.186521
+1798.840210 0.317240
+1798.902710 0.062321
+1798.965210 0.009013
+1799.027710 0.001195
+1799.090210 0.002691
+1799.152710 0.020824
+1799.215210 0.121764
+1799.277710 0.523201
+1799.340210 1.651777
+1799.402710 3.831421
+1799.465210 6.529741
+1799.527710 8.176350
+1799.590210 7.522310
+1799.652710 5.084770
+1799.715210 2.525344
+1799.777710 0.921507
+1799.840210 0.247064
+1799.902710 0.048668
+1799.965210 0.007057
+1800.027710 0.000937
+1800.090210 0.002105
+1800.152710 0.016307
+1800.215210 0.095496
+1800.277710 0.410939
+1800.340210 1.299299
+1800.402710 3.018382
+1800.465210 5.151981
+1800.527710 6.461133
+1800.590210 5.953582
+1800.652710 4.030724
+1800.715210 2.005042
+1800.777710 0.732823
+1800.840210 0.196795
+1800.902710 0.038829
+1800.965210 0.005639
+1801.027710 0.000736
+1801.090210 0.001542
+1801.152710 0.011951
+1801.215210 0.070210
+1801.277710 0.303085
+1801.340210 0.961302
+1801.402710 2.240149
+1801.465210 3.835470
+1801.527710 4.824856
+1801.590210 4.459388
+1801.652710 3.028247
+1801.715210 1.510892
+1801.777710 0.553861
+1801.840210 0.149176
+1801.902710 0.029520
+1801.965210 0.004300
+1802.027710 0.000563
+1802.090210 0.001185
+1802.152710 0.009194
+1802.215210 0.054085
+1802.277710 0.233801
+1802.340210 0.742606
+1802.402710 1.733008
+1802.465210 2.971503
+1802.527710 3.743552
+1802.590210 3.465173
+1802.652710 2.356670
+1802.715210 1.177624
+1802.777710 0.432362
+1802.840210 0.116634
+1802.902710 0.023117
+1802.965210 0.003372
+1803.027710 0.000434
+1803.090210 0.000842
+1803.152710 0.006538
+1803.215210 0.038591
+1803.277710 0.167393
+1803.340210 0.533478
+1803.402710 1.249142
+1803.465210 2.148964
+1803.527710 2.716234
+1803.590210 2.522475
+1803.652710 1.721109
+1803.715210 0.862805
+1803.777710 0.317789
+1803.840210 0.085999
+1803.902710 0.017098
+1803.965210 0.002502
+1804.027710 0.000324
+1804.090210 0.000637
+1804.152710 0.004948
+1804.215210 0.029247
+1804.277710 0.127026
+1804.340210 0.405361
+1804.402710 0.950425
+1804.465210 1.637292
+1804.527710 2.072356
+1804.590210 1.927231
+1804.652710 1.316842
+1804.715210 0.661098
+1804.777710 0.243853
+1804.840210 0.066089
+1804.902710 0.013159
+1804.965210 0.001928
+1805.027710 0.000245
+1805.090210 0.000439
+1805.152710 0.003410
+1805.215210 0.020230
+1805.277710 0.088186
+1805.340210 0.282442
+1805.402710 0.664616
+1805.465210 1.149028
+1805.527710 1.459511
+1805.590210 1.362081
+1805.652710 0.933934
+1805.715210 0.470489
+1805.777710 0.174140
+1805.840210 0.047356
+1805.902710 0.009461
+1805.965210 0.001391
+1806.027710 0.000178
+1806.090210 0.000327
+1806.152710 0.002544
+1806.215210 0.015112
+1806.277710 0.065949
+1806.340210 0.211472
+1806.402710 0.498214
+1806.465210 0.862402
+1806.527710 1.096810
+1806.590210 1.024902
+1806.652710 0.703657
+1806.715210 0.354953
+1806.777710 0.131555
+1806.840210 0.035825
+1806.902710 0.007167
+1806.965210 0.001055
+1807.027710 0.000132
+1807.090210 0.000218
+1807.152710 0.001697
+1807.215210 0.010118
+1807.277710 0.044330
+1807.340210 0.142706
+1807.402710 0.337516
+1807.465210 0.586491
+1807.527710 0.748757
+1807.590210 0.702322
+1807.652710 0.484000
+1807.715210 0.245059
+1807.777710 0.091161
+1807.840210 0.024916
+1807.902710 0.005003
+1807.965210 0.000739
+1808.027710 0.000094
+1808.090210 0.000161
+1808.152710 0.001250
+1808.215210 0.007465
+1808.277710 0.032738
+1808.340210 0.105496
+1808.402710 0.249769
+1808.465210 0.434478
+1808.527710 0.555292
+1808.590210 0.521439
+1808.652710 0.359758
+1808.715210 0.182367
+1808.777710 0.067921
+1808.840210 0.018587
+1808.902710 0.003737
+1808.965210 0.000553
+1809.027710 0.000068
+1809.090210 0.000104
+1809.152710 0.000805
+1809.215210 0.004829
+1809.277710 0.021267
+1809.340210 0.068823
+1809.402710 0.163628
+1809.465210 0.285821
+1809.527710 0.366808
+1809.590210 0.345857
+1809.652710 0.239587
+1809.715210 0.121939
+1809.777710 0.045596
+1809.840210 0.012527
+1809.902710 0.002528
+1809.965210 0.000376
+1810.027710 0.000047
+1810.090210 0.000076
+1810.152710 0.000588
+1810.215210 0.003527
+1810.277710 0.015546
+1810.340210 0.050350
+1810.402710 0.119807
+1810.465210 0.209456
+1810.527710 0.269045
+1810.590210 0.253913
+1810.652710 0.176062
+1810.715210 0.089696
+1810.777710 0.033574
+1810.840210 0.009234
+1810.902710 0.001865
+1810.965210 0.000278
+1811.027710 0.000034
+1811.090210 0.000047
+1811.152710 0.000365
+1811.215210 0.002199
+1811.277710 0.009737
+1811.340210 0.031682
+1811.402710 0.075729
+1811.465210 0.132994
+1811.527710 0.171594
+1811.590210 0.162660
+1811.652710 0.113283
+1811.715210 0.057964
+1811.777710 0.021790
+1811.840210 0.006018
+1811.902710 0.001221
+1811.965210 0.000183
+1812.027710 0.000023
+1812.090210 0.000034
+1812.152710 0.000264
+1812.215210 0.001595
+1812.277710 0.007064
+1812.340210 0.022998
+1812.402710 0.055004
+1812.465210 0.096657
+1812.527710 0.124792
+1812.590210 0.118377
+1812.652710 0.082502
+1812.715210 0.042247
+1812.777710 0.015894
+1812.840210 0.004394
+1812.902710 0.000892
+1812.965210 0.000134
+1813.027710 0.000016
+1813.090210 0.000021
+1813.152710 0.000157
+1813.215210 0.000956
+1813.277710 0.004254
+1813.340210 0.013919
+1813.402710 0.033454
+1813.465210 0.059075
+1813.527710 0.076640
+1813.590210 0.073049
+1813.652710 0.051153
+1813.715210 0.026317
+1813.777710 0.009947
+1813.840210 0.002763
+1813.902710 0.000563
+1813.965210 0.000085
+1814.027710 0.000010
+1814.090210 0.000015
+1814.152710 0.000114
+1814.215210 0.000690
+1814.277710 0.003072
+1814.340210 0.010055
+1814.402710 0.024175
+1814.465210 0.042705
+1814.527710 0.055424
+1814.590210 0.052850
+1814.652710 0.037025
+1814.715210 0.019058
+1814.777710 0.007207
+1814.840210 0.002003
+1814.902710 0.000409
+1814.965210 0.000062
+1815.027710 0.000007
+1815.090210 0.000009
+1815.152710 0.000065
+1815.215210 0.000396
+1815.277710 0.001773
+1815.340210 0.005834
+1815.402710 0.014101
+1815.465210 0.025042
+1815.527710 0.032670
+1815.590210 0.031315
+1815.652710 0.022051
+1815.715210 0.011409
+1815.777710 0.004336
+1815.840210 0.001211
+1815.902710 0.000248
+1815.965210 0.000038
+1816.027710 0.000004
+1816.090210 0.000006
+1816.152710 0.000047
+1816.215210 0.000286
+1816.277710 0.001279
+1816.340210 0.004209
+1816.402710 0.010173
+1816.465210 0.018067
+1816.527710 0.023572
+1816.590210 0.022597
+1816.652710 0.015915
+1816.715210 0.008236
+1816.777710 0.003131
+1816.840210 0.000875
+1816.902710 0.000179
+1816.965210 0.000027
+1817.027710 0.000003
+1817.090210 0.000004
+1817.152710 0.000025
+1817.215210 0.000157
+1817.277710 0.000704
+1817.340210 0.002332
+1817.402710 0.005668
+1817.465210 0.010125
+1817.527710 0.013285
+1817.590210 0.012807
+1817.652710 0.009070
+1817.715210 0.004720
+1817.777710 0.001804
+1817.840210 0.000507
+1817.902710 0.000104
+1817.965210 0.000016
+1818.027710 0.000002
+1818.090210 0.000003
+1818.152710 0.000018
+1818.215210 0.000113
+1818.277710 0.000510
+1818.340210 0.001687
+1818.402710 0.004099
+1818.465210 0.007318
+1818.527710 0.009600
+1818.590210 0.009253
+1818.652710 0.006552
+1818.715210 0.003409
+1818.777710 0.001303
+1818.840210 0.000366
+1818.902710 0.000075
+1818.965210 0.000012
+1819.027710 0.000001
+1819.090210 0.000001
+1819.152710 0.000009
+1819.215210 0.000059
+1819.277710 0.000267
+1819.340210 0.000888
+1819.402710 0.002171
+1819.465210 0.003901
+1819.527710 0.005149
+1819.590210 0.004993
+1819.652710 0.003557
+1819.715210 0.001862
+1819.777710 0.000716
+1819.840210 0.000202
+1819.902710 0.000042
+1819.965210 0.000007
+1820.027710 0.000001
+1820.090210 0.000001
+1820.152710 0.000007
+1820.215210 0.000043
+1820.277710 0.000194
+1820.340210 0.000647
+1820.402710 0.001581
+1820.465210 0.002838
+1820.527710 0.003743
+1820.590210 0.003628
+1820.652710 0.002583
+1820.715210 0.001351
+1820.777710 0.000519
+1820.840210 0.000147
+1820.902710 0.000030
+1820.965210 0.000005
+1821.027710 0.000000
+1821.090210 0.000001
+1821.152710 0.000003
+1821.215210 0.000021
+1821.277710 0.000096
+1821.340210 0.000322
+1821.402710 0.000792
+1821.465210 0.001431
+1821.527710 0.001900
+1821.590210 0.001854
+1821.652710 0.001329
+1821.715210 0.000700
+1821.777710 0.000270
+1821.840210 0.000077
+1821.902710 0.000016
+1821.965210 0.000003
+1822.027710 0.000000
+1822.090210 0.000000
+1822.152710 0.000002
+1822.215210 0.000016
+1822.277710 0.000071
+1822.340210 0.000238
+1822.402710 0.000583
+1822.465210 0.001053
+1822.527710 0.001397
+1822.590210 0.001361
+1822.652710 0.000975
+1822.715210 0.000513
+1822.777710 0.000198
+1822.840210 0.000056
+1822.902710 0.000012
+1822.965210 0.000002
+1823.027710 0.000000
+1823.090210 0.000000
+1823.152710 0.000001
+1823.215210 0.000007
+1823.277710 0.000033
+1823.340210 0.000111
+1823.402710 0.000274
+1823.465210 0.000500
+1823.527710 0.000667
+1823.590210 0.000655
+1823.652710 0.000472
+1823.715210 0.000250
+1823.777710 0.000097
+1823.840210 0.000028
+1823.902710 0.000006
+1823.965210 0.000001
+1824.027710 -0.000000
+1824.090210 0.000000
+1824.152710 0.000001
+1824.215210 0.000006
+1824.277710 0.000025
+1824.340210 0.000083
+1824.402710 0.000206
+1824.465210 0.000374
+1824.527710 0.000498
+1824.590210 0.000489
+1824.652710 0.000352
+1824.715210 0.000186
+1824.777710 0.000072
+1824.840210 0.000021
+1824.902710 0.000004
+1824.965210 0.000001
+1825.027710 -0.000000
+1825.090210 0.000000
+1825.152710 0.000000
+1825.215210 0.000002
+1825.277710 0.000011
+1825.340210 0.000036
+1825.402710 0.000090
+1825.465210 0.000166
+1825.527710 0.000222
+1825.590210 0.000220
+1825.652710 0.000159
+1825.715210 0.000085
+1825.777710 0.000033
+1825.840210 0.000010
+1825.902710 0.000002
+1825.965210 0.000000
+1826.027710 -0.000000
+1826.090210 0.000000
+1826.152710 0.000000
+1826.215210 0.000002
+1826.277710 0.000008
+1826.340210 0.000028
+1826.402710 0.000069
+1826.465210 0.000127
+1826.527710 0.000170
+1826.590210 0.000168
+1826.652710 0.000121
+1826.715210 0.000065
+1826.777710 0.000025
+1826.840210 0.000007
+1826.902710 0.000001
+1826.965210 0.000000
+1827.027710 -0.000000
+1827.090210 0.000000
+1827.152710 -0.000000
+1827.215210 0.000001
+1827.277710 0.000003
+1827.340210 0.000011
+1827.402710 0.000028
+1827.465210 0.000052
+1827.527710 0.000070
+1827.590210 0.000070
+1827.652710 0.000051
+1827.715210 0.000027
+1827.777710 0.000011
+1827.840210 0.000003
+1827.902710 0.000001
+1827.965210 0.000000
+1828.027710 -0.000000
+1828.090210 0.000000
+1828.152710 -0.000000
+1828.215210 0.000001
+1828.277710 0.000003
+1828.340210 0.000009
+1828.402710 0.000022
+1828.465210 0.000041
+1828.527710 0.000055
+1828.590210 0.000055
+1828.652710 0.000040
+1828.715210 0.000022
+1828.777710 0.000008
+1828.840210 0.000003
+1828.902710 0.000000
+1828.965210 0.000000
+1829.027710 -0.000000
+1829.090210 0.000000
+1829.152710 -0.000000
+1829.215210 0.000000
+1829.277710 0.000001
+1829.340210 0.000003
+1829.402710 0.000008
+1829.465210 0.000016
+1829.527710 0.000021
+1829.590210 0.000021
+1829.652710 0.000015
+1829.715210 0.000008
+1829.777710 0.000003
+1829.840210 0.000001
+1829.902710 0.000000
+1829.965210 0.000000
+1830.027710 -0.000000
+1830.090210 0.000000
+1830.152710 -0.000000
+1830.215210 0.000000
+1830.277710 0.000001
+1830.340210 0.000003
+1830.402710 0.000007
+1830.465210 0.000013
+1830.527710 0.000017
+1830.590210 0.000017
+1830.652710 0.000012
+1830.715210 0.000007
+1830.777710 0.000003
+1830.840210 0.000001
+1830.902710 0.000000
+1830.965210 0.000000
+1831.027710 -0.000000
+1831.090210 0.000000
+1831.152710 -0.000000
+1831.215210 0.000000
+1831.277710 0.000000
+1831.340210 0.000001
+1831.402710 0.000002
+1831.465210 0.000004
+1831.527710 0.000006
+1831.590210 0.000006
+1831.652710 0.000004
+1831.715210 0.000002
+1831.777710 0.000001
+1831.840210 0.000000
+1831.902710 -0.000000
+1831.965210 0.000000
+1832.027710 -0.000000
+1832.090210 0.000000
+1832.152710 -0.000000
+1832.215210 0.000000
+1832.277710 0.000000
+1832.340210 0.000001
+1832.402710 0.000002
+1832.465210 0.000004
+1832.527710 0.000005
+1832.590210 0.000005
+1832.652710 0.000004
+1832.715210 0.000002
+1832.777710 0.000001
+1832.840210 0.000000
+1832.902710 -0.000000
+1832.965210 0.000000
+1833.027710 -0.000000
+1833.090210 0.000000
+1833.152710 -0.000000
+1833.215210 0.000000
+1833.277710 -0.000000
+1833.340210 0.000000
+1833.402710 0.000001
+1833.465210 0.000001
+1833.527710 0.000001
+1833.590210 0.000002
+1833.652710 0.000001
+1833.715210 0.000001
+1833.777710 0.000000
+1833.840210 0.000000
+1833.902710 -0.000000
+1833.965210 0.000000
+1834.027710 -0.000000
+1834.090210 0.000000
+1834.152710 -0.000000
+1834.215210 0.000000
+1834.277710 -0.000000
+1834.340210 0.000000
+1834.402710 0.000000
+1834.465210 0.000001
+1834.527710 0.000001
+1834.590210 0.000002
+1834.652710 0.000001
+1834.715210 0.000001
+1834.777710 0.000000
+1834.840210 0.000000
+1834.902710 -0.000000
+1834.965210 0.000000
+1835.027710 -0.000000
+1835.090210 0.000000
+1835.152710 -0.000000
+1835.215210 0.000000
+1835.277710 -0.000000
+1835.340210 0.000000
+1835.402710 0.000000
+1835.465210 0.000000
+1835.527710 0.000000
+1835.590210 0.000000
+1835.652710 0.000000
+1835.715210 0.000000
+1835.777710 0.000000
+1835.840210 0.000000
+1835.902710 -0.000000
+1835.965210 0.000000
+1836.027710 -0.000000
+1836.090210 0.000000
+1836.152710 -0.000000
+1836.215210 0.000000
+1836.277710 -0.000000
+1836.340210 0.000000
+1836.402710 0.000000
+1836.465210 0.000000
+1836.527710 0.000000
+1836.590210 0.000000
+1836.652710 0.000000
+1836.715210 0.000000
+1836.777710 0.000000
+1836.840210 0.000000
+1836.902710 -0.000000
+1836.965210 0.000000
+1837.027710 -0.000000
+1837.090210 0.000000
+1837.152710 -0.000000
+1837.215210 0.000000
+1837.277710 -0.000000
+1837.340210 0.000000
+1837.402710 -0.000000
+1837.465210 0.000000
+1837.527710 0.000000
+1837.590210 0.000000
+1837.652710 0.000000
+1837.715210 0.000000
+1837.777710 -0.000000
+1837.840210 0.000000
+1837.902710 -0.000000
+1837.965210 0.000000
+1838.027710 -0.000000
+1838.090210 0.000000
+1838.152710 -0.000000
+1838.215210 0.000000
+1838.277710 -0.000000
+1838.340210 0.000000
+1838.402710 -0.000000
+1838.465210 0.000000
+1838.527710 0.000000
+1838.590210 0.000000
+1838.652710 0.000000
+1838.715210 0.000000
+1838.777710 -0.000000
+1838.840210 0.000000
+1838.902710 -0.000000
+1838.965210 0.000000
+1839.027710 -0.000000
+1839.090210 0.000000
+1839.152710 -0.000000
+1839.215210 0.000000
+1839.277710 -0.000000
+1839.340210 0.000000
+1839.402710 -0.000000
+1839.465210 0.000000
+1839.527710 -0.000000
+1839.590210 0.000000
+1839.652710 -0.000000
+1839.715210 0.000000
+1839.777710 -0.000000
+1839.840210 0.000000
+1839.902710 -0.000000
+1839.965210 0.000000
+1840.027710 -0.000000
+1840.090210 0.000000
+1840.152710 -0.000000
+1840.215210 0.000000
+1840.277710 -0.000000
+1840.340210 0.000000
+1840.402710 -0.000000
+1840.465210 0.000000
+1840.527710 -0.000000
+1840.590210 0.000000
+1840.652710 -0.000000
+1840.715210 0.000000
+1840.777710 -0.000000
+1840.840210 0.000000
+1840.902710 -0.000000
+1840.965210 0.000000
+1841.027710 -0.000000
+1841.090210 0.000000
+1841.152710 -0.000000
+1841.215210 0.000000
+1841.277710 -0.000000
+1841.340210 0.000000
+1841.402710 -0.000000
+1841.465210 0.000000
+1841.527710 -0.000000
+1841.590210 0.000000
+1841.652710 -0.000000
+1841.715210 0.000000
+1841.777710 -0.000000
+1841.840210 0.000000
+1841.902710 -0.000000
+1841.965210 0.000000
+1842.027710 -0.000000
+1842.090210 0.000000
+1842.152710 -0.000000
+1842.215210 0.000000
+1842.277710 -0.000000
+1842.340210 0.000000
+1842.402710 -0.000000
+1842.465210 0.000000
+1842.527710 -0.000000
+1842.590210 0.000000
+1842.652710 -0.000000
+1842.715210 0.000000
+1842.777710 -0.000000
+1842.840210 0.000000
+1842.902710 -0.000000
+1842.965210 0.000000
+1843.027710 -0.000000
+1843.090210 0.000000
+1843.152710 -0.000000
+1843.215210 0.000000
+1843.277710 -0.000000
+1843.340210 0.000000
+1843.402710 -0.000000
+1843.465210 0.000000
+1843.527710 -0.000000
+1843.590210 0.000000
+1843.652710 -0.000000
+1843.715210 0.000000
+1843.777710 -0.000000
+1843.840210 0.000000
+1843.902710 -0.000000
+1843.965210 0.000000
+1844.027710 -0.000000
+1844.090210 0.000000
+1844.152710 -0.000000
+1844.215210 0.000000
+1844.277710 -0.000000
+1844.340210 0.000000
+1844.402710 -0.000000
+1844.465210 0.000000
+1844.527710 -0.000000
+1844.590210 0.000000
diff --git a/Mercury_FromRockwood/Sn15_comparison.doc b/Mercury_FromRockwood/Sn15_comparison.doc
new file mode 100644
index 0000000..ac1129f
Binary files /dev/null and b/Mercury_FromRockwood/Sn15_comparison.doc differ
diff --git a/Mercury_FromRockwood/Sn15_m6 b/Mercury_FromRockwood/Sn15_m6
new file mode 100644
index 0000000..b35a6f4
--- /dev/null
+++ b/Mercury_FromRockwood/Sn15_m6
@@ -0,0 +1,128 @@
+1716.521089 0.000000
+1717.521325 0.000000
+1718.521562 0.000000
+1719.521798 0.000000
+1720.522035 0.000000
+1721.522272 0.000000
+1722.522508 0.000000
+1723.522745 0.000000
+1724.522981 0.000000
+1725.523218 0.000000
+1726.523454 0.000000
+1727.523691 0.000000
+1728.523927 0.000001
+1729.524164 0.000002
+1730.524400 0.000003
+1731.524637 0.000006
+1732.524873 0.000011
+1733.525110 0.000019
+1734.525347 0.000036
+1735.525583 0.000065
+1736.525820 0.000117
+1737.526056 0.000208
+1738.526293 0.000368
+1739.526529 0.000639
+1740.526766 0.001108
+1741.527002 0.001882
+1742.527239 0.003192
+1743.527475 0.005310
+1744.527712 0.008805
+1745.527948 0.014331
+1746.528185 0.023222
+1747.528422 0.036957
+1748.528658 0.058493
+1749.528895 0.090960
+1750.529131 0.140533
+1751.529368 0.213389
+1752.529604 0.321625
+1753.529841 0.476486
+1754.530077 0.700135
+1755.530314 1.011214
+1756.530550 1.447493
+1757.530787 2.036492
+1758.531023 2.837758
+1759.531260 3.885880
+1760.531497 5.267189
+1761.531733 7.014433
+1762.531970 9.242080
+1763.532206 11.960696
+1764.532443 15.308723
+1765.532679 19.240103
+1766.532916 23.908679
+1767.533152 29.165085
+1768.533389 35.171757
+1769.533625 41.625482
+1770.533862 48.703236
+1771.534098 55.907178
+1772.534335 63.459162
+1773.534572 70.649246
+1774.534808 77.803797
+1775.535045 84.012932
+1776.535281 89.788258
+1777.535518 94.056415
+1778.535754 97.594290
+1779.535991 99.210965
+1780.536227 100.000000
+1781.536464 98.692001
+1782.536700 96.697870
+1783.536937 92.693189
+1784.537173 88.349807
+1785.537410 82.298922
+1786.537647 76.371584
+1787.537883 69.163693
+1788.538120 62.542447
+1789.538356 55.088018
+1790.538593 48.585906
+1791.538829 41.636273
+1792.539066 35.850574
+1793.539302 29.897426
+1794.539539 25.157231
+1795.539775 20.418117
+1796.540012 16.807635
+1797.540248 13.275296
+1798.540485 10.702484
+1799.540722 8.224227
+1800.540958 6.501479
+1801.541195 4.858351
+1802.541431 3.771041
+1803.541668 2.738346
+1804.541904 2.090064
+1805.542141 1.473314
+1806.542377 1.107618
+1807.542614 0.756918
+1808.542850 0.561553
+1809.543087 0.371382
+1810.543323 0.272492
+1811.543560 0.174027
+1812.543797 0.126597
+1813.544033 0.077869
+1814.544270 0.056324
+1815.544506 0.033260
+1816.544743 0.024000
+1817.544979 0.013553
+1818.545216 0.009794
+1819.545452 0.005265
+1820.545689 0.003827
+1821.545925 0.001948
+1822.546162 0.001431
+1823.546398 0.000686
+1824.546635 0.000512
+1825.546872 0.000229
+1826.547108 0.000175
+1827.547345 0.000073
+1828.547581 0.000057
+1829.547818 0.000022
+1830.548054 0.000018
+1831.548291 0.000006
+1832.548527 0.000005
+1833.548764 0.000002
+1834.549000 0.000001
+1835.549237 0.000000
+1836.549474 0.000000
+1837.549710 0.000000
+1838.549947 0.000000
+1839.550183 0.000000
+1840.550420 0.000000
+1841.550656 0.000000
+1842.550893 0.000000
+1843.551129 0.000000
diff --git a/Mercury_FromRockwood/mercury_full.ZIP b/Mercury_FromRockwood/mercury_full.ZIP
new file mode 100644
index 0000000..2ac2ab3
Binary files /dev/null and b/Mercury_FromRockwood/mercury_full.ZIP differ
diff --git a/MsPlot.bas b/MsPlot.bas
new file mode 100644
index 0000000..6c033f9
--- /dev/null
+++ b/MsPlot.bas
@@ -0,0 +1,1454 @@
+Attribute VB_Name = "MsPlotRoutines"
+Option Explicit
+
+Private Const NUM_TWIPS_PER_DIGIT = 90
+Public Const MAX_DATA_SETS = 2 ' Up to 2 data sets may be graphed simultaneously (uses indices 0 and 1)
+
+Public Const cPlotTypeSticks = 0
+Public Const cPlotTypeGaussian = 1
+
+Public Type usrAxisOptions
+ Show As Boolean ' Whether or not to show the axis
+ ShowLabels As Boolean ' whether or not to label axes
+ MajorTicksToShow As Integer ' The number of major tick values to show
+ ShowMinorTicks As Boolean ' Whether or not to show minor ticks
+ MinorTickMinimumPixelSep As Integer ' Minimum spacing in pixels between minor ticks before showing them
+
+ ShowGridLinesMajor As Boolean
+ ShowTickLinesMinor As Boolean
+
+End Type
+
+Public Type usrPlotRangeDetails
+ Val As Double
+ Pos As Long
+End Type
+
+Public Type usrPlotRangeAxis
+ ValStart As usrPlotRangeDetails
+ ValEnd As usrPlotRangeDetails
+ ValNegativeValueCorrectionOffset As Double
+End Type
+
+Public Type usrPlotRange
+ x As usrPlotRangeAxis
+ Y As usrPlotRangeAxis
+End Type
+
+Public Type usrGaussianOptions
+ ResolvingPower As Long ' Effective resolution (M / delta M)
+ XValueOfSpecification As Double ' X Value where effective resolution applies
+ QualityFactor As Integer ' The higher this value is, the more data points are created for each Gaussian peak
+End Type
+
+Public Type usrPlotDataOptions
+
+ PlotTypeCode As Integer ' Whether the plot is a stick plot (0) or line-between-points plot (1)
+ GaussianConversion As usrGaussianOptions
+ ApproximationFactor As Integer ' Affects when and how many data points are discarded when approximating the graph
+
+ ' Zoom options
+ ZoomOutFull As Boolean ' When true, the data is shown fully zoomed out, ignoring the XVal and YVal Start and End values
+ AutoScaleY As Boolean ' When true, will zoom the x data as requested but always keep the y data at full scale
+ FixYAxisMinimumAtZero As Boolean ' Only used if AutoScaleY = True; keeps the minimum y scaling at 0 at all times (i.e. makes YValStart = 0)
+
+ ' Scaling options
+ Scaling As usrPlotRange ' Note that I do not use ValNegativeValueCorrectionOffset in Scaling, only in DataLimits
+ DataLimits(MAX_DATA_SETS) As usrPlotRange ' Records the largest and smallest values of the given data set
+ SortData As Boolean ' Whether or not to sort the data by x value before plotting
+
+ ' The following define the size of the spectrum in the parent frame
+ PlotLeft As Integer ' In Twips (VB units)
+ PlotTop As Integer ' In Twips (VB units)
+ PlotWidth As Integer ' In Twips (VB units)
+ PlotHeight As Integer ' In Twips (VB units)
+ PlotLeftLargeNumberOffset As Integer ' In Twips - used to offset the left of the graph to the right a little for very large or very small numbers
+
+ XAxis As usrAxisOptions
+ YAxis As usrAxisOptions
+
+ MajorTicksLoaded As Long ' There is a label and gridline loaded for each major tick loaded
+ MinorTicksLoaded As Long
+
+ blnLongOperationsRequired As Boolean ' Set to true when long operations are encountered, thus requiring an hourglass cursor
+
+ IndexToHighlight As Long ' Index of the x,y data pair to highlight (if any)
+ HighlightColor As Long ' default vbRed
+
+ LinesLoadedCount As Long ' Records the number of lines and labels that have been dynamically loaded
+End Type
+
+Public Type usrXYData
+ XVal As Double ' Note: Single data type is -3.402823E38 to 3.402823E38
+ YVal As Double
+End Type
+
+Public Type usrXYDataSet
+ XYDataList() As usrXYData ' Index 1 to XYDataListCount
+ XYDataListCount As Long
+ XYDataListCountDimmed As Long
+End Type
+
+Private Sub CheckForLongOperation(ThisForm As VB.Form, lngSecondsElapsedAtStart As Long, ThesePlotOptions As usrPlotDataOptions, lngCurrentIteration As Long, lngTotalIterations As Long, strCurrentTask As String)
+ ' Checks to see if the current value of Timer() is greater than lngSecondsElapsedAtStart + 1
+ ' If it is then blnLongOperationsRequired is turned on and the pointer is changed to an hourglass
+ ' The blnLongOperationsRequired value is saved for future calls to the sub so that the hourglass
+ ' will be activated immediately on future calls
+ ' Furthermore, if over 2 seconds have elapsed, then a progress box is shown
+ Dim lngSecElapsedSinceOperationStart As Long
+
+ lngSecElapsedSinceOperationStart = Timer() - lngSecondsElapsedAtStart
+
+ If lngSecElapsedSinceOperationStart >= 1 Or ThesePlotOptions.blnLongOperationsRequired Then
+ ThesePlotOptions.blnLongOperationsRequired = True
+ If ThisForm.MousePointer <> vbHourglass Then
+ ThisForm.MousePointer = vbHourglass
+ End If
+
+ If lngSecElapsedSinceOperationStart >= 2 Then
+ ' Process has taken over 2 seconds
+ ' Show the progress form if not shown yet
+ If frmProgress.Visible = False Then
+ frmProgress.InitializeForm strCurrentTask, 0, lngTotalIterations
+ frmProgress.ToggleAlwaysOnTop True
+ End If
+ frmProgress.UpdateProgressBar lngCurrentIteration + 1
+ End If
+ End If
+
+End Sub
+
+Private Sub CheckDynamicXYData(ByRef ThisXYDataList() As usrXYData, ThisXYDataListCount As Long, ByRef ThisXYDataListCountDimmed As Long, Optional lngIncrement As Long = 100)
+ If ThisXYDataListCount > ThisXYDataListCountDimmed Then
+ ThisXYDataListCountDimmed = ThisXYDataListCountDimmed + lngIncrement
+ If ThisXYDataListCountDimmed < ThisXYDataListCount Then
+ ThisXYDataListCountDimmed = ThisXYDataListCount
+ End If
+ ReDim Preserve ThisXYDataList(ThisXYDataListCountDimmed)
+ End If
+End Sub
+
+Public Function ConvertStickDataToGaussian(ThisForm As VB.Form, ThisXYDataSet As usrXYDataSet, ThesePlotOptions As usrPlotDataOptions, intDataSetIndex As Integer) As usrXYDataSet
+ ' Note: Assumes ThisXYDataSet is sorted in the x direction
+
+ Dim lngDataIndex As Long, lngMidPointIndex As Long
+ Dim lngStickIndex As Long, DeltaX As Double
+ Dim intQualityFactor As Integer
+
+ Dim dblXValRange As Double, dblXValWindowRange As Double, dblRangeWork As Double
+ Dim dblMinimalXValOfWindow As Double, dblMinimalXValSpacing As Double
+
+ Dim dblXOffSet As Double, sigma As Double
+ Dim lngExponentValue As Long
+ Dim lngSecondsElapsedAtStart As Long, strCurrentTask As String
+
+ Dim XYSummation() As usrXYData, XYSummationCount As Long, XYSummationCountDimmed As Long
+ Dim lngSummationIndex As Long, lngMinimalSummationIndex As Long
+ Dim DataToAdd() As usrXYData, lngDataToAddCount As Long, blnAppendNewData As Boolean
+ Dim ThisDataPoint As usrXYData
+
+ If ThisXYDataSet.XYDataListCount = 0 Then Exit Function
+
+ lngSecondsElapsedAtStart = Timer()
+
+ If ThesePlotOptions.GaussianConversion.ResolvingPower < 1 Then
+ ThesePlotOptions.GaussianConversion.ResolvingPower = 1
+ End If
+
+ XYSummationCount = 0
+ XYSummationCountDimmed = 100
+ ReDim XYSummation(XYSummationCountDimmed)
+
+ With ThisXYDataSet
+ ' Make sure the Y Data range is defined
+ CheckYDataRange .XYDataList(), .XYDataListCount, ThesePlotOptions, intDataSetIndex
+
+ ThesePlotOptions.DataLimits(intDataSetIndex).x.ValStart.Val = .XYDataList(1).XVal
+ ThesePlotOptions.DataLimits(intDataSetIndex).x.ValEnd.Val = .XYDataList(.XYDataListCount).XVal
+ End With
+
+ With ThesePlotOptions
+ dblXValRange = .DataLimits(intDataSetIndex).x.ValEnd.Val - .DataLimits(intDataSetIndex).x.ValStart.Val
+
+ intQualityFactor = .GaussianConversion.QualityFactor
+
+ If intQualityFactor < 1 Or intQualityFactor > 50 Then
+ intQualityFactor = 20
+ End If
+
+ ' Set DeltaX using .ResolvingPower and .XValueOfSpecification
+ ' Do not allow the DeltaX to be so small that the total points required > 100,000
+ DeltaX = .GaussianConversion.XValueOfSpecification / .GaussianConversion.ResolvingPower / intQualityFactor
+ ' Make sure DeltaX is a reasonable number
+ DeltaX = RoundToMultipleOf10(DeltaX)
+ If DeltaX = 0 Then DeltaX = 1
+
+ ' Set the Window Range to 1/10 the magnitude of the midpoint x value
+ dblRangeWork = .DataLimits(intDataSetIndex).x.ValStart.Val + dblXValRange / 2
+ dblRangeWork = RoundToMultipleOf10(dblRangeWork, lngExponentValue)
+
+ sigma = (.GaussianConversion.XValueOfSpecification / .GaussianConversion.ResolvingPower) / Sqr(5.54)
+
+ ' Set the window range (the xvalue window width range) to calculate the Gaussian representation for each data point
+ ' The width at the base of a peak is 4 sigma
+ ' Use a width of 2 * 6 sigma
+ dblXValWindowRange = 2 * 6 * sigma
+
+ If dblXValWindowRange / DeltaX > 50000 Then
+ DeltaX = dblXValWindowRange / 50000
+ End If
+
+ lngDataToAddCount = CLng(dblXValWindowRange / DeltaX)
+ ' Make sure lngDataToAddCount is odd
+ If CSng(lngDataToAddCount) / 2! = Round(CSng(lngDataToAddCount) / 2!, 0) Then
+ lngDataToAddCount = lngDataToAddCount + 1
+ End If
+ ReDim DataToAdd(lngDataToAddCount)
+ lngMidPointIndex = (lngDataToAddCount + 1) / 2
+ End With
+
+ With ThisXYDataSet
+ strCurrentTask = LookupMessage(1130)
+
+ For lngStickIndex = 1 To .XYDataListCount
+ If lngStickIndex Mod 25 = 0 Then
+ CheckForLongOperation ThisForm, lngSecondsElapsedAtStart, ThesePlotOptions, lngStickIndex, .XYDataListCount, strCurrentTask
+ If KeyPressAbortProcess Then Exit For
+ End If
+
+ ' Search through XYSummation to determine the index of the smallest XValue with which
+ ' data in DataToAdd could be combined
+ lngMinimalSummationIndex = 1
+ dblMinimalXValOfWindow = .XYDataList(lngStickIndex).XVal - (lngMidPointIndex - 1) * DeltaX
+ If dblMinimalXValOfWindow > XYSummation(XYSummationCount).XVal Then
+ lngMinimalSummationIndex = XYSummationCount
+ Else
+ For lngSummationIndex = 1 To XYSummationCount
+ If XYSummation(lngSummationIndex).XVal >= dblMinimalXValOfWindow Then
+ lngMinimalSummationIndex = lngSummationIndex - 1
+ If lngMinimalSummationIndex < 1 Then lngMinimalSummationIndex = 1
+ Exit For
+ End If
+ Next lngSummationIndex
+ If lngSummationIndex > XYSummationCount Then
+ lngMinimalSummationIndex = XYSummationCount
+ End If
+ End If
+
+ ' Construct the Gaussian representation for this Data Point
+ ThisDataPoint = .XYDataList(lngStickIndex)
+
+ ' Round ThisDataPoint.XVal to the nearest DeltaX
+ ' If .XVal is not an even multiple of DeltaX then bump up .XVal until it is
+ ThisDataPoint.XVal = RoundToEvenMultiple(ThisDataPoint.XVal, DeltaX, True)
+
+ For lngDataIndex = 1 To lngDataToAddCount
+ ' Equation for Gaussian is: Amplitude * Exp[ -(x - mu)^2 / (2*sigma^2) ]
+ ' Use lngDataIndex, .YVal, and DeltaX
+ dblXOffSet = (lngMidPointIndex - lngDataIndex) * DeltaX
+ DataToAdd(lngDataIndex).XVal = ThisDataPoint.XVal - dblXOffSet
+ DataToAdd(lngDataIndex).YVal = ThisDataPoint.YVal * Exp(-(dblXOffSet) ^ 2 / (2 * sigma ^ 2))
+ Next lngDataIndex
+
+ ' Now merge DataToAdd into XYSummation
+ ' XValues in DataToAdd and those in XYSummation have the same DeltaX value
+ ' The XValues in DataToAdd might overlap partially with those in XYSummation
+
+ lngDataIndex = 1
+ ' First, see if the first XValue in DataToAdd is larger than the last XValue in XYSummation
+ If DataToAdd(lngDataIndex).XVal > XYSummation(XYSummationCount).XVal Then
+ blnAppendNewData = True
+ Else
+ blnAppendNewData = False
+ ' Step through XYSummation() starting at lngMinimalSummationIndex, looking for
+ ' the index to start combining data at
+ For lngSummationIndex = lngMinimalSummationIndex To XYSummationCount
+ If DataToAdd(lngDataIndex).XVal = XYSummation(lngSummationIndex).XVal Or DataToAdd(lngDataIndex).XVal < XYSummation(lngSummationIndex).XVal Then
+ '''Debug.Assert XYSummation(lngSummationIndex).XVal = DataToAdd(lngDataIndex).XVal
+ ' Within Tolerance; start combining the values here
+ Do While lngSummationIndex <= XYSummationCount
+ XYSummation(lngSummationIndex).YVal = XYSummation(lngSummationIndex).YVal + DataToAdd(lngDataIndex).YVal
+ lngSummationIndex = lngSummationIndex + 1
+ lngDataIndex = lngDataIndex + 1
+ If lngDataIndex > lngDataToAddCount Then
+ ' Successfully combined all of the data
+ Exit Do
+ End If
+ Loop
+ If lngDataIndex <= lngDataToAddCount Then
+ ' Data still remains to be added
+ blnAppendNewData = True
+ End If
+ Exit For
+ End If
+ Next lngSummationIndex
+ End If
+
+ If blnAppendNewData = True Then
+ CheckDynamicXYData XYSummation(), XYSummationCount + lngDataToAddCount - lngDataIndex + 1, XYSummationCountDimmed
+ Do While lngDataIndex <= lngDataToAddCount
+ ThisDataPoint = DataToAdd(lngDataIndex)
+ XYSummationCount = XYSummationCount + 1
+ XYSummation(XYSummationCount) = ThisDataPoint
+ lngDataIndex = lngDataIndex + 1
+ Loop
+ End If
+
+ Next lngStickIndex
+
+ End With
+
+ ' Step through XYSummation and remove areas of sequential equivalent values
+ lngSummationIndex = 1
+ RoundToMultipleOf10 DeltaX, lngExponentValue
+
+ ' Assure there is a data point at each 1% point along x range
+ ' Probably need to add data, but may need to remove some
+ dblMinimalXValSpacing = dblXValRange / 100
+
+ Do While lngSummationIndex <= XYSummationCount - 1
+ If XYSummation(lngSummationIndex).XVal + dblMinimalXValSpacing < XYSummation(lngSummationIndex + 1).XVal Then
+ ' Need to insert a data point
+ XYSummationCount = XYSummationCount + 1
+ CheckDynamicXYData XYSummation, XYSummationCount, XYSummationCountDimmed
+ For lngDataIndex = XYSummationCount To lngSummationIndex + 2 Step -1
+ XYSummation(lngDataIndex) = XYSummation(lngDataIndex - 1)
+ Next lngDataIndex
+
+ ' Choose the appropriate new .XVal
+ dblRangeWork = XYSummation(lngSummationIndex + 1).XVal - XYSummation(lngSummationIndex).XVal
+ If dblRangeWork < dblMinimalXValSpacing * 2 Then
+ dblRangeWork = dblRangeWork / 2
+ Else
+ dblRangeWork = dblMinimalXValSpacing
+ End If
+ XYSummation(lngSummationIndex + 1).XVal = XYSummation(lngSummationIndex).XVal + dblRangeWork
+
+ ' The new .YVal is the average of that at lngSummationIndex and that at lngSummationIndex + 1
+ XYSummation(lngSummationIndex + 1).YVal = (XYSummation(lngSummationIndex).YVal + XYSummation(lngSummationIndex + 1).YVal) / 2
+ End If
+ lngSummationIndex = lngSummationIndex + 1
+ Loop
+
+ frmProgress.HideForm
+
+ ' Reset the blnLongOperationsRequired bit
+ ThesePlotOptions.blnLongOperationsRequired = False
+
+ ' ReDim XYSummation to XYSummationCount since DrawPlot assumes this is the case
+ XYSummationCountDimmed = XYSummationCount
+ ReDim Preserve XYSummation(XYSummationCountDimmed)
+
+ ' Assign data in XYSummation to the function so that it gets returned
+ ConvertStickDataToGaussian.XYDataList = XYSummation
+ ConvertStickDataToGaussian.XYDataListCount = XYSummationCount
+ ConvertStickDataToGaussian.XYDataListCountDimmed = XYSummationCountDimmed
+
+End Function
+
+Private Sub CheckYDataRange(ThisXYData() As usrXYData, ThisXYDataCount As Long, ThesePlotOptions As usrPlotDataOptions, intDataSetIndex As Integer)
+ Dim lngIndex As Long
+ Dim dblMaximumIntensity As Double, dblMinimumIntensity As Double
+ Dim dblXYDataPoint As Double
+
+ If ThesePlotOptions.DataLimits(intDataSetIndex).Y.ValStart.Val = 0 And ThesePlotOptions.DataLimits(intDataSetIndex).Y.ValEnd.Val = 0 Then
+ ' Data Limits not defined
+ ' Figure out what they are and sort data if necessary
+
+ ' Find the Y scale data limits
+ ' At the same time, see if the data is sorted
+ dblMaximumIntensity = LowestValueForDoubleDataType
+ dblMinimumIntensity = HighestValueForDoubleDataType
+ For lngIndex = 1 To ThisXYDataCount
+ dblXYDataPoint = ThisXYData(lngIndex).YVal
+ If dblXYDataPoint > dblMaximumIntensity Then dblMaximumIntensity = dblXYDataPoint
+ If dblXYDataPoint < dblMinimumIntensity Then dblMinimumIntensity = dblXYDataPoint
+ Next lngIndex
+ ThesePlotOptions.DataLimits(intDataSetIndex).Y.ValStart.Val = dblMinimumIntensity
+ ThesePlotOptions.DataLimits(intDataSetIndex).Y.ValEnd.Val = dblMaximumIntensity
+ End If
+
+End Sub
+
+Public Sub DrawPlot(ThisForm As VB.Form, ByRef ThesePlotOptions As usrPlotDataOptions, ByRef ThisXYDataArray() As usrXYDataSet, ByRef PlotRange() As usrPlotRange, intDataSetsLoaded As Integer)
+ ' Draw a graphical representation of a list of x,y data pairs in one or more data sets (stored in ThisXYDataArray)
+ ' Assumes the x,y data point array is 1-based (i.e. the first data point is in index 1
+ ' Note: Assumes the data is sorted in the x direction
+
+ ' ThesePlotOptions.Scaling is the axis range the user wishes to see
+ ' The range actually used to display the data is stored in PlotRange
+
+ Dim intDataSetIndex As Integer
+ Dim lngIndex As Long, lngLineIndex As Long
+ Dim PlotBottom As Long, lngLeftOffset As Long
+ Dim lngSecondsElapsedAtStart As Long
+ Dim intKeepEveryXthPoint As Integer, lngXYDataToCountTrack As Long
+ Dim intDataDiscardValue As Integer, strCurrentTask As String
+
+ Const MaxLinesCount = 32000
+
+ Dim XYDataToPlot() As usrXYData, XYDataToPlotCount As Long
+
+ Dim HighlightIndex As Long
+ Dim dblPreviousMinimum As Double
+ Dim lngChunkSize As Long, lngMinimumValIndex As Long, lngMaximumValIndex As Long
+
+ Dim StartXValIndex As Long, EndXValIndex As Long
+ Dim dblWork As Double
+
+ Dim intDynamicObjectOffset As Integer, lngDataSetLineColor As Long
+ Dim dblMinimumIntensity As Double, dblMaximumIntensity As Double
+
+ ' Need to determine the correct scaling values if autoscaling the y-axis
+ ' Only works if the data is sorted in the x direction
+ If ThesePlotOptions.AutoScaleY Or ThesePlotOptions.FixYAxisMinimumAtZero Then
+ ' Find the minimum and maximum y intensities for all data sets within the range of x data being shown
+ dblMaximumIntensity = LowestValueForDoubleDataType
+ dblMinimumIntensity = HighestValueForDoubleDataType
+ For intDataSetIndex = 0 To intDataSetsLoaded - 1
+ With ThisXYDataArray(intDataSetIndex)
+ If .XYDataListCount > 0 Then
+ ' Step through .XYDataList and find index of the start x value
+ For lngIndex = 1 To .XYDataListCount
+ If .XYDataList(lngIndex).XVal >= ThesePlotOptions.Scaling.x.ValStart.Val Then
+ StartXValIndex = lngIndex
+ Exit For
+ End If
+ Next lngIndex
+
+ ' Step through .XYDataList and find index of the end x value
+ For lngIndex = .XYDataListCount To 1 Step -1
+ If .XYDataList(lngIndex).XVal <= ThesePlotOptions.Scaling.x.ValEnd.Val Then
+ EndXValIndex = lngIndex
+ Exit For
+ End If
+ Next lngIndex
+
+ For lngIndex = StartXValIndex To EndXValIndex
+ dblWork = .XYDataList(lngIndex).YVal
+ If dblWork > dblMaximumIntensity Then
+ dblMaximumIntensity = dblWork
+ End If
+ If dblWork < dblMinimumIntensity Then
+ dblMinimumIntensity = dblWork
+ End If
+ Next lngIndex
+ End If
+ End With
+ Next intDataSetIndex
+
+ If dblMaximumIntensity <= LowestValueForDoubleDataType Then dblMaximumIntensity = 1
+ If dblMinimumIntensity >= HighestValueForDoubleDataType Then dblMinimumIntensity = 0
+
+ If ThesePlotOptions.FixYAxisMinimumAtZero Then
+ ' Fix Y axis range at zero
+ ThesePlotOptions.Scaling.Y.ValStart.Val = 0
+ Else
+ ThesePlotOptions.Scaling.Y.ValStart.Val = dblMinimumIntensity
+ End If
+
+ If ThesePlotOptions.AutoScaleY Then
+ ThesePlotOptions.Scaling.Y.ValEnd.Val = dblMaximumIntensity
+ End If
+ End If
+
+ strCurrentTask = LookupMessage(1130)
+
+ lngSecondsElapsedAtStart = Timer()
+
+ intDynamicObjectOffset = 0
+ For intDataSetIndex = 0 To intDataSetsLoaded - 1
+ lngDataSetLineColor = GetPlotSeriesColor(intDataSetIndex)
+
+ If ThisXYDataArray(intDataSetIndex).XYDataListCount > 0 Then
+
+ ' Make sure the Y Data range is defined
+ CheckYDataRange ThisXYDataArray(intDataSetIndex).XYDataList, ThisXYDataArray(intDataSetIndex).XYDataListCount, ThesePlotOptions, intDataSetIndex
+
+ With ThisXYDataArray(intDataSetIndex)
+
+ ' Determine the location in the parent frame of the bottom of the Plot
+ PlotBottom = ThesePlotOptions.PlotTop + ThesePlotOptions.PlotHeight
+
+ StartXValIndex = 1
+ EndXValIndex = .XYDataListCount
+
+ ' Record the X scale data limits
+ ThesePlotOptions.DataLimits(intDataSetIndex).x.ValStart.Val = .XYDataList(StartXValIndex).XVal
+ ThesePlotOptions.DataLimits(intDataSetIndex).x.ValEnd.Val = .XYDataList(EndXValIndex).XVal
+
+ ' Initialize .Scaling.x.ValStart.Val and .Scaling.y.ValStart.Val if necessary
+ If ThesePlotOptions.Scaling.x.ValStart.Val = 0 And ThesePlotOptions.Scaling.x.ValEnd.Val = 0 Then
+ ThesePlotOptions.Scaling.x.ValStart.Val = .XYDataList(StartXValIndex).XVal
+ ThesePlotOptions.Scaling.x.ValEnd.Val = .XYDataList(EndXValIndex).XVal
+ End If
+
+ ' Make sure .Scaling.X.ValStart.Val < .Scaling.X.ValEnd
+ If ThesePlotOptions.Scaling.x.ValStart.Val > ThesePlotOptions.Scaling.x.ValEnd.Val Then
+ SwapValues ThesePlotOptions.Scaling.x.ValStart.Val, ThesePlotOptions.Scaling.x.ValEnd.Val
+ End If
+
+ If Not ThesePlotOptions.ZoomOutFull Then
+ ' Step through .XYDataList and find index of the start x value
+ For lngIndex = 1 To .XYDataListCount
+ If .XYDataList(lngIndex).XVal >= ThesePlotOptions.Scaling.x.ValStart.Val Then
+ StartXValIndex = lngIndex
+ Exit For
+ End If
+ Next lngIndex
+
+ ' Step through .XYDataList and find index of the end x value
+ For lngIndex = .XYDataListCount To 1 Step -1
+ If .XYDataList(lngIndex).XVal < ThesePlotOptions.Scaling.x.ValEnd.Val Then
+ EndXValIndex = lngIndex
+ Exit For
+ End If
+ Next lngIndex
+ End If
+
+ ' Make sure StartValIndex <= EndValIndex
+ If StartXValIndex > EndXValIndex Then
+ SwapValues StartXValIndex, EndXValIndex
+ End If
+
+ ' Check to see if Mouse Pointer should be changed to hourglass
+ CheckForLongOperation ThisForm, lngSecondsElapsedAtStart, ThesePlotOptions, 2, 10, strCurrentTask
+
+ ' Copy the data into XYDataToPlot, reindexing to start at 1 and going to XYDataToPlotCount
+ ' Although this uses more memory because it duplicates the data, I soon replace the
+ ' raw data values with location positions in twips
+ '
+ ' In addition, if there is far more data than could be possibly plotted,
+ ' I throw away every xth data point, though with a twist
+
+ XYDataToPlotCount = EndXValIndex - StartXValIndex + 1
+
+ intDataDiscardValue = ThesePlotOptions.ApproximationFactor
+ If intDataDiscardValue < 1 Then
+ intDataDiscardValue = 1
+ ElseIf intDataDiscardValue > 50 Then
+ intDataDiscardValue = 50
+ End If
+
+ If XYDataToPlotCount > ThesePlotOptions.PlotWidth / intDataDiscardValue Then
+ ' Throw away some of the data: Note that CIntSafe will round 2.5 up to 3
+ intKeepEveryXthPoint = CIntSafeDbl(XYDataToPlotCount / (ThesePlotOptions.PlotWidth / intDataDiscardValue))
+ lngChunkSize = intKeepEveryXthPoint * 2
+ Else
+ intKeepEveryXthPoint = 1
+ End If
+
+ ReDim XYDataToPlot(CLngRoundUp(XYDataToPlotCount / intKeepEveryXthPoint) + intDataDiscardValue)
+
+ If intKeepEveryXthPoint = 1 Then
+ lngXYDataToCountTrack = 0
+ For lngIndex = StartXValIndex To EndXValIndex
+ lngXYDataToCountTrack = lngXYDataToCountTrack + 1
+ XYDataToPlot(lngXYDataToCountTrack) = .XYDataList(lngIndex)
+ If lngIndex = ThesePlotOptions.IndexToHighlight Then
+ HighlightIndex = lngXYDataToCountTrack
+ End If
+ Next lngIndex
+ Else
+ ' Step through the data examining chunks of numbers twice the length of intKeepEveryXthPoint
+ ' Find the minimum and maximum value in each chunk of numbers
+ ' Store these values in the array to keep (minimum followed by maximum)
+ ' Swap the stored order if both numbers are less than the previous two numbers
+
+ ' Store the first value of .xydatalist() in the output array
+ lngXYDataToCountTrack = 1
+ XYDataToPlot(lngXYDataToCountTrack) = .XYDataList(StartXValIndex)
+ If StartXValIndex = ThesePlotOptions.IndexToHighlight Then
+ HighlightIndex = lngXYDataToCountTrack
+ End If
+
+ dblPreviousMinimum = LowestValueForDoubleDataType
+ For lngIndex = StartXValIndex + 1 To EndXValIndex - 1 Step lngChunkSize
+
+ FindMinimumAndMaximum lngMinimumValIndex, lngMaximumValIndex, .XYDataList(), lngIndex, lngIndex + lngChunkSize
+
+ ' Check if the maximum value of this pair of points is less than the minimum value of the previous pair
+ ' If it is, the y values of the two points should be exchanged
+ If .XYDataList(lngMaximumValIndex).YVal < dblPreviousMinimum Then
+ ' Update dblPreviousMinimum
+ dblPreviousMinimum = .XYDataList(lngMinimumValIndex).YVal
+ ' Swap minimum and maximum so that maximum gets saved to array first
+ SwapValues lngMinimumValIndex, lngMaximumValIndex
+ Else
+ ' Update dblPreviousMinimum
+ dblPreviousMinimum = .XYDataList(lngMinimumValIndex).YVal
+ End If
+
+ lngXYDataToCountTrack = lngXYDataToCountTrack + 1
+ XYDataToPlot(lngXYDataToCountTrack) = .XYDataList(lngMinimumValIndex)
+ If lngMinimumValIndex = ThesePlotOptions.IndexToHighlight Then
+ HighlightIndex = lngXYDataToCountTrack
+ End If
+
+ lngXYDataToCountTrack = lngXYDataToCountTrack + 1
+ XYDataToPlot(lngXYDataToCountTrack) = .XYDataList(lngMaximumValIndex)
+ If lngMaximumValIndex = ThesePlotOptions.IndexToHighlight Then
+ HighlightIndex = lngXYDataToCountTrack
+ End If
+
+ ' Now check to see if the .XVal of the first value is greater than the first
+ ' If so, swap the .XVals
+ If XYDataToPlot(lngXYDataToCountTrack - 1).XVal > XYDataToPlot(lngXYDataToCountTrack).XVal Then
+ SwapValues XYDataToPlot(lngXYDataToCountTrack - 1).XVal, XYDataToPlot(lngXYDataToCountTrack).XVal
+ End If
+ Next lngIndex
+
+ ' Store the last value of .xydatalist() in the output array
+ lngXYDataToCountTrack = lngXYDataToCountTrack + 1
+ XYDataToPlot(lngXYDataToCountTrack) = .XYDataList(EndXValIndex)
+ If EndXValIndex = ThesePlotOptions.IndexToHighlight Then
+ HighlightIndex = lngXYDataToCountTrack
+ End If
+
+ End If
+
+ ' Set XYDataToPlotCount to the lngXYDataToCountTrack value resulting from the copying
+ XYDataToPlotCount = lngXYDataToCountTrack
+
+ End With
+
+ ' Scale the data vertically according to ThesePlotOptions.height
+ ' i.e., replace the actual y values with locations in twips for where the data point belongs on the graph
+ ' The new value will range from 0 to ThesePlotOptions.Height
+ ' Note that ThesePlotOptions.PlotLeftLargeNumberOffset is computed in ScaleData for the Y axis
+ ScaleData ThesePlotOptions, XYDataToPlot(), XYDataToPlotCount, PlotRange(intDataSetIndex).Y, ThesePlotOptions.Scaling.Y, False, ThesePlotOptions.AutoScaleY
+
+ ' Now scale the data to twips, ranging 0 to .PlotWidth and 0 to .PlotHeight
+ ' X axis
+ ScaleData ThesePlotOptions, XYDataToPlot(), XYDataToPlotCount, PlotRange(intDataSetIndex).x, ThesePlotOptions.Scaling.x, True, False
+
+ ' Load lines and labels for each XVal
+ If ThesePlotOptions.LinesLoadedCount = 0 Then
+ ' Only initialize to 1 the first time this sub is called
+ ThesePlotOptions.LinesLoadedCount = 1
+ End If
+
+ ' Limit the total points shown if greater than MaxLinesCount
+ If XYDataToPlotCount > MaxLinesCount Then
+ ' This code should not be reached since extra data should have been thrown away above
+ Debug.Assert False
+ XYDataToPlotCount = MaxLinesCount
+ End If
+
+ ' Load dynamic plot objects as needed
+ LoadDynamicPlotObjects ThisForm, ThesePlotOptions, intDynamicObjectOffset + XYDataToPlotCount
+
+ If ThesePlotOptions.LinesLoadedCount < intDynamicObjectOffset + XYDataToPlotCount Then
+ ' User aborted the process of dynamically loading lines
+ ' Need to limit XYDataToPlotCount to the correct value
+ XYDataToPlotCount = ThesePlotOptions.LinesLoadedCount - intDynamicObjectOffset
+ End If
+
+ ' Check to see if Mouse Pointer should be changed to hourglass
+ CheckForLongOperation ThisForm, lngSecondsElapsedAtStart, ThesePlotOptions, 3, 10, strCurrentTask
+
+ ' Label the axes and add ticks and gridlines
+ FormatAxes ThisForm, ThesePlotOptions, PlotBottom, PlotRange(intDataSetIndex)
+
+ ' Position the lines and labels
+ lngLeftOffset = ThesePlotOptions.PlotLeft + ThesePlotOptions.PlotLeftLargeNumberOffset
+
+ strCurrentTask = LookupMessage(1135)
+
+ For lngIndex = 1 To XYDataToPlotCount
+ With ThisForm
+ If lngIndex Mod 50 = 0 Then
+ ' Check to see if Mouse Pointer should be changed to hourglass
+ CheckForLongOperation ThisForm, lngSecondsElapsedAtStart, ThesePlotOptions, lngIndex, XYDataToPlotCount, strCurrentTask
+ If KeyPressAbortProcess > 1 Then Exit For
+ End If
+
+ lngLineIndex = lngIndex + intDynamicObjectOffset
+
+ .linData(lngLineIndex).Visible = True
+
+ If ThesePlotOptions.PlotTypeCode = cPlotTypeSticks Then
+ ' Plot the data as sticks to zero
+
+ .linData(lngLineIndex).x1 = lngLeftOffset + XYDataToPlot(lngIndex).XVal
+ .linData(lngLineIndex).x2 = .linData(lngLineIndex).x1
+ .linData(lngLineIndex).y1 = PlotBottom
+ .linData(lngLineIndex).y2 = PlotBottom - XYDataToPlot(lngIndex).YVal
+ If HighlightIndex = lngIndex Then
+ .linData(lngLineIndex).BorderColor = ThesePlotOptions.HighlightColor
+ Else
+ .linData(lngLineIndex).BorderColor = lngDataSetLineColor
+ End If
+ Else
+ ' Plot the data as lines between points
+ If lngIndex < XYDataToPlotCount Then
+ .linData(lngLineIndex).x1 = lngLeftOffset + XYDataToPlot(lngIndex).XVal
+ .linData(lngLineIndex).x2 = lngLeftOffset + XYDataToPlot(lngIndex + 1).XVal
+ .linData(lngLineIndex).y1 = PlotBottom - XYDataToPlot(lngIndex).YVal
+ .linData(lngLineIndex).y2 = PlotBottom - XYDataToPlot(lngIndex + 1).YVal
+ .linData(lngLineIndex).BorderColor = lngDataSetLineColor
+ Else
+ .linData(lngLineIndex).Visible = False
+ End If
+ End If
+ End With
+
+ Next lngIndex
+
+ If KeyPressAbortProcess > 1 Then
+ intDynamicObjectOffset = intDynamicObjectOffset + lngIndex
+ Exit For
+ Else
+ intDynamicObjectOffset = intDynamicObjectOffset + XYDataToPlotCount
+ End If
+
+ End If
+ Next intDataSetIndex
+
+ With ThisForm
+ If intDynamicObjectOffset + 1 < ThesePlotOptions.LinesLoadedCount Then
+ If intDynamicObjectOffset < 0 Then lngIndex = 0
+
+ ' Hide the other lines and labels
+ For lngLineIndex = intDynamicObjectOffset + 1 To ThesePlotOptions.LinesLoadedCount
+ ThisForm.linData(lngLineIndex).Visible = False
+ Next lngLineIndex
+ End If
+
+ End With
+
+ frmProgress.HideForm
+
+End Sub
+
+Private Sub FindMinimumAndMaximum(lngMinimumValIndex As Long, lngMaximumValIndex As Long, ThisXYData() As usrXYData, lngStartIndex As Long, lngStopIndex As Long)
+ Dim lngIndex As Long, XYDataPoint As Long
+ Dim dblMinimumVal As Double, dblMaximumVal As Double
+
+ If lngStopIndex > UBound(ThisXYData()) Then
+ lngStopIndex = UBound(ThisXYData())
+ End If
+
+ lngMinimumValIndex = lngStartIndex
+ lngMaximumValIndex = lngStartIndex
+
+ dblMaximumVal = ThisXYData(lngStartIndex).YVal
+ dblMinimumVal = ThisXYData(lngStartIndex).YVal
+
+ For lngIndex = lngStartIndex + 1 To lngStopIndex
+ XYDataPoint = ThisXYData(lngIndex).YVal
+ If XYDataPoint < dblMinimumVal Then
+ dblMinimumVal = XYDataPoint
+ lngMinimumValIndex = lngIndex
+ End If
+ If XYDataPoint > dblMaximumVal Then
+ dblMaximumVal = XYDataPoint
+ lngMaximumValIndex = lngIndex
+ End If
+ Next lngIndex
+
+ If lngMinimumValIndex = lngMaximumValIndex Then
+ ' All of the data was the same
+ ' Set lngMaximumValIndex to the halfway-point index between lngStopIndex and lngStartIndex
+ lngMaximumValIndex = lngStartIndex + (lngStopIndex - lngStartIndex) / 2
+ End If
+End Sub
+
+Private Sub FormatAxes(ThisForm As VB.Form, ThesePlotOptions As usrPlotDataOptions, PlotBottom As Long, PlotRange As usrPlotRange)
+ Dim intInitialTickIndex As Integer, intInitialTickMinorIndex As Integer
+ Dim lngRightOrTopMostPos As Long
+
+ With ThisForm
+ ' Position the x axis
+ .linXAxis.x1 = ThesePlotOptions.PlotLeft + ThesePlotOptions.PlotLeftLargeNumberOffset
+ .linXAxis.x2 = ThesePlotOptions.PlotLeft + ThesePlotOptions.PlotWidth + 50
+ .linXAxis.y1 = PlotBottom + 50
+ .linXAxis.y2 = PlotBottom + 50
+ .linXAxis.Visible = ThesePlotOptions.XAxis.Show
+
+ ' Position the y axis
+ .linYAxis.x1 = ThesePlotOptions.PlotLeft + ThesePlotOptions.PlotLeftLargeNumberOffset
+ .linYAxis.x2 = ThesePlotOptions.PlotLeft + ThesePlotOptions.PlotLeftLargeNumberOffset
+ .linYAxis.y1 = PlotBottom + 50
+ .linYAxis.y2 = ThesePlotOptions.PlotTop - 50
+ .linYAxis.Visible = ThesePlotOptions.YAxis.Show
+ End With
+
+ ' Note: The x and y axes share the same dynamic lines for major and minor tick marks,
+ ' gridlines, and labels. The x axis objects will start with index 1 of each object type
+ ' the intInitialTickIndex and intInitialTickMinorIndex values will be modified by sub
+ ' FormatThisAxis during the creation of the objects for the x axis so that they will
+ ' be the value of the next unused object for operations involving the y axis
+ intInitialTickIndex = 0
+ intInitialTickMinorIndex = 0
+ FormatThisAxis ThisForm, ThesePlotOptions, True, ThesePlotOptions.XAxis, PlotRange.x, intInitialTickIndex, intInitialTickMinorIndex, lngRightOrTopMostPos
+ If lngRightOrTopMostPos > ThisForm.linXAxis.x2 Then
+ ThisForm.linXAxis.x2 = lngRightOrTopMostPos + 50
+ End If
+
+ FormatThisAxis ThisForm, ThesePlotOptions, False, ThesePlotOptions.YAxis, PlotRange.Y, intInitialTickIndex, intInitialTickMinorIndex, lngRightOrTopMostPos
+ If lngRightOrTopMostPos < ThisForm.linYAxis.y2 Then
+ ThisForm.linYAxis.y2 = lngRightOrTopMostPos - 50
+ End If
+
+End Sub
+
+Private Function FindDigitsInLabelUsingRange(PlotRangeForAxis As usrPlotRangeAxis, intMajorTicksToShow As Integer, ByRef strFormatString As String) As Integer
+ Dim ValRange As Double, DeltaVal As Double, lngExponentValue As Long
+ Dim intDigitsInStartNumber As Integer, intDigitsInEndNumber As Integer
+
+ With PlotRangeForAxis
+ ValRange = .ValEnd.Val - .ValStart.Val
+ End With
+
+ If intMajorTicksToShow = 0 Then
+ DeltaVal = ValRange
+ Else
+ ' Take ValRange divided by intMajorTicksToShow
+ DeltaVal = ValRange / intMajorTicksToShow
+ End If
+
+ ' Round DeltaVal to nearest 1, 2, or 5 (or multiple of 10 thereof)
+ DeltaVal = RoundToMultipleOf10(DeltaVal, lngExponentValue)
+
+ strFormatString = ConstructFormatString(DeltaVal)
+
+ ' Note: I use the absolute value of ValEnd so that all tick labels will have the
+ ' same width, positive or negative
+ intDigitsInStartNumber = Len(Trim(Format(Abs(PlotRangeForAxis.ValStart.Val), strFormatString))) + 1
+ intDigitsInEndNumber = Len(Trim(Format(Abs(PlotRangeForAxis.ValEnd.Val), strFormatString))) + 1
+
+ If intDigitsInEndNumber > intDigitsInStartNumber Then
+ FindDigitsInLabelUsingRange = intDigitsInEndNumber
+ Else
+ FindDigitsInLabelUsingRange = intDigitsInStartNumber
+ End If
+
+End Function
+
+Private Sub FormatThisAxis(ThisForm As VB.Form, ThesePlotOptions As usrPlotDataOptions, blnXAxis As Boolean, AxisOptions As usrAxisOptions, PlotRangeForAxis As usrPlotRangeAxis, ByRef intInitialTickIndex As Integer, ByRef intInitialTickMinorIndex As Integer, lngRightOrTopMostPos As Long)
+ Dim objTickMajor As Line
+
+ Dim intMajorTicksToShow As Integer
+ Dim intMinorTicksPerMajorTick As Integer, intMinorTicksRequired As Integer
+ Dim intTickIndex As Integer, intTickIndexToHide As Integer
+ Dim intKeepEveryXthTick As Integer
+ Dim intTickIndexMinor As Integer, intTickIndexMinorTrack As Integer
+ Dim lngAddnlMinorTickPos As Long, lngAddnlMinorTickStopPos As Long
+ Dim PosStart As Long, DeltaPos As Double, DeltaPosMinor As Double
+ Dim ValStart As Double, ValEnd As Double, ValRange As Double, DeltaVal As Double
+ Dim LengthStartPos As Long, LengthEndPos As Long, GridlineEndPos As Long
+ Dim LengthStartPosMinor As Long, LengthEndPosMinor As Long
+ Dim intDigitsInLabel As Integer
+
+ Dim strFormatString As String, intTickLabelWidth As Integer
+
+ ' Position and label the x axis major tick marks and labels
+ intMajorTicksToShow = AxisOptions.MajorTicksToShow
+ If intMajorTicksToShow < 2 Then
+ intMajorTicksToShow = 2
+ AxisOptions.MajorTicksToShow = intMajorTicksToShow
+ End If
+
+ With PlotRangeForAxis
+ ValStart = .ValStart.Val
+ ValEnd = .ValEnd.Val
+ ValRange = ValEnd - ValStart
+ End With
+
+ ' Take ValRange divided by intMajorTicksToShow
+ DeltaVal = ValRange / intMajorTicksToShow
+
+ ' Round DeltaVal to nearest 1, 2, or 5 (or multiple of 10 thereof)
+ DeltaVal = RoundToMultipleOf10(DeltaVal)
+
+ ' If ValStart is not an even multiple of DeltaVal then bump up ValStart until it is
+ ValStart = RoundToEvenMultiple(ValStart, DeltaVal, True)
+
+ ' Do the same for ValEnd, but bump down instead
+ ValEnd = RoundToEvenMultiple(ValEnd, DeltaVal, False)
+
+ ' Recompute ValRange
+ ValRange = ValEnd - ValStart
+
+ ' Determine actual number of ticks to show
+ intMajorTicksToShow = ValRange / DeltaVal + 1
+
+ ' Convert ValStart to ValPos
+ PosStart = XYValueToPos(ValStart, PlotRangeForAxis, False)
+
+ ' Convert DeltaVal to DeltaPos
+ DeltaPos = XYValueToPos(DeltaVal, PlotRangeForAxis, True)
+
+ If blnXAxis Then
+ LengthStartPos = ThisForm.linXAxis.y1 + 200
+ LengthEndPos = ThisForm.linXAxis.y1
+ Else
+ LengthStartPos = ThisForm.linYAxis.x1 - 200
+ LengthEndPos = ThisForm.linYAxis.x1
+ End If
+
+ With AxisOptions
+ If .ShowMinorTicks Then
+ ' Insert 1, 4, or 9 minor ticks, depending on whether they'll fit
+ intMinorTicksPerMajorTick = 0
+ Do
+ Select Case intMinorTicksPerMajorTick
+ Case 0: intMinorTicksPerMajorTick = 9
+ Case 9: intMinorTicksPerMajorTick = 4
+ Case 4: intMinorTicksPerMajorTick = 1
+ Case Else
+ intMinorTicksPerMajorTick = 0
+ Exit Do
+ End Select
+ DeltaPosMinor = DeltaPos / (intMinorTicksPerMajorTick + 1)
+ Loop While Abs(DeltaPosMinor) < .MinorTickMinimumPixelSep
+ Else
+ DeltaPosMinor = 0
+ End If
+
+ If blnXAxis Then
+ LengthStartPosMinor = LengthStartPos - 150
+ LengthEndPosMinor = LengthEndPos
+ Else
+ LengthStartPosMinor = LengthStartPos + 100
+ LengthEndPosMinor = LengthEndPos
+ End If
+
+ If .ShowGridLinesMajor Then
+ If blnXAxis Then
+ GridlineEndPos = ThesePlotOptions.PlotTop
+ Else
+ GridlineEndPos = ThesePlotOptions.PlotLeft + ThesePlotOptions.PlotWidth
+ End If
+ Else
+ GridlineEndPos = LengthEndPos
+ End If
+ End With
+
+ ' Initialize ThesePlotOptions.MajorTicksLoaded and ThesePlotOptions.MinorTicksLoaded if needed
+ If ThesePlotOptions.MajorTicksLoaded = 0 Then ThesePlotOptions.MajorTicksLoaded = 1 ' There is always at least 1 loaded
+ If ThesePlotOptions.MinorTicksLoaded = 0 Then ThesePlotOptions.MinorTicksLoaded = 1 ' There is always at least 1 loaded
+
+ ' Call FindDigitsInLabelUsingRange to determine the digits in the label and construct the format string
+ intDigitsInLabel = FindDigitsInLabelUsingRange(PlotRangeForAxis, intMajorTicksToShow, strFormatString)
+
+ ' Each number requires 90 pixels
+ intTickLabelWidth = intDigitsInLabel * NUM_TWIPS_PER_DIGIT
+
+ intTickIndexMinorTrack = intInitialTickMinorIndex
+ For intTickIndex = intInitialTickIndex + 1 To intInitialTickIndex + intMajorTicksToShow
+
+ With AxisOptions
+ If ThesePlotOptions.MajorTicksLoaded < intTickIndex Then
+ ThesePlotOptions.MajorTicksLoaded = ThesePlotOptions.MajorTicksLoaded + 1
+ Load ThisForm.linTickMajor(ThesePlotOptions.MajorTicksLoaded)
+ Load ThisForm.lblTick(ThesePlotOptions.MajorTicksLoaded)
+ Load ThisForm.linGridline(ThesePlotOptions.MajorTicksLoaded)
+ End If
+ End With
+
+ With ThisForm.linTickMajor(intTickIndex)
+ .x1 = PosStart + CLng(((intTickIndex - intInitialTickIndex) - 1) * DeltaPos)
+ .x2 = .x1
+ .y1 = LengthStartPos
+ .y2 = LengthEndPos
+ .Visible = True
+ End With
+ Set objTickMajor = ThisForm.linTickMajor(intTickIndex)
+ With ThisForm.linGridline(intTickIndex)
+ .x1 = objTickMajor.x1
+ .x2 = objTickMajor.x2
+ .y1 = objTickMajor.y1
+ .y2 = GridlineEndPos
+ .BorderColor = RGB(0, 192, 0)
+ .Visible = True
+ End With
+
+ lngRightOrTopMostPos = LengthEndPos
+ If Not blnXAxis Then
+ SwapLineCoordinates ThisForm.linTickMajor(intTickIndex)
+ SwapLineCoordinates ThisForm.linGridline(intTickIndex)
+ Set objTickMajor = ThisForm.linTickMajor(intTickIndex)
+ End If
+
+ With ThisForm.lblTick(intTickIndex)
+ .Width = intTickLabelWidth
+ .Caption = Format(ValStart + CDbl((intTickIndex - intInitialTickIndex) - 1) * DeltaVal, strFormatString)
+ .Visible = True
+ If blnXAxis Then
+ .top = objTickMajor.y1 + 50
+ .Left = objTickMajor.x1 - .Width / 2
+ Else
+ .top = objTickMajor.y1 - .Height / 2
+ .Left = objTickMajor.x1 - .Width - 50
+ .Alignment = vbRightJustify
+ End If
+ End With
+
+ If ValStart + ((intTickIndex - intInitialTickIndex) - 1) * DeltaVal > PlotRangeForAxis.ValEnd.Val Then
+ ' Tick and/or label is past the end of the axis; Do not keep labeling
+ ' Before exitting for loop, must add 1 to intTickIndex since it will normally
+ ' exit the for loop with a value of intMajorTicksToShow + 1, but we are exiting prematurely
+ intTickIndex = intTickIndex + 1
+ Exit For
+ End If
+
+ ' Only load minor ticks if not on the last major tick
+ With AxisOptions
+ ' Load minor ticks as needed
+ intMinorTicksRequired = intTickIndexMinorTrack + intMinorTicksPerMajorTick
+ Do While ThesePlotOptions.MinorTicksLoaded < intMinorTicksRequired
+ ThesePlotOptions.MinorTicksLoaded = ThesePlotOptions.MinorTicksLoaded + 1
+ Load ThisForm.linTickMinor(ThesePlotOptions.MinorTicksLoaded)
+ Loop
+ End With
+
+ For intTickIndexMinor = 1 To intMinorTicksPerMajorTick
+ intTickIndexMinorTrack = intTickIndexMinorTrack + 1
+ If blnXAxis Then
+ lngAddnlMinorTickPos = objTickMajor.x1 + DeltaPosMinor * intTickIndexMinor
+ Else
+ lngAddnlMinorTickPos = objTickMajor.y1 + DeltaPosMinor * intTickIndexMinor
+ End If
+
+ lngRightOrTopMostPos = lngAddnlMinorTickPos
+
+ ' Add the minor tick mark
+ AddMinorTickmark ThisForm, intTickIndexMinor, intTickIndexMinorTrack, lngAddnlMinorTickPos, LengthStartPosMinor, LengthEndPosMinor, blnXAxis
+ Next intTickIndexMinor
+ Next intTickIndex
+
+ ' See if minor ticks can be added before the first major tick
+ If AxisOptions.ShowMinorTicks Then
+ If blnXAxis Then
+ lngAddnlMinorTickPos = ThisForm.linTickMajor(1).x1
+ lngAddnlMinorTickStopPos = ThisForm.linXAxis.x1
+ Else
+ lngAddnlMinorTickPos = ThisForm.linTickMajor(intInitialTickIndex + 1).y1
+ lngAddnlMinorTickStopPos = ThisForm.linYAxis.y1
+ End If
+
+ intTickIndexMinor = 1
+ ' This loop will execute at most 50 times
+ ' Most likely, it will only execute a few times before the Exit Do clause becomes true
+ Do While intTickIndexMinor < 50
+ If blnXAxis Then
+ If lngAddnlMinorTickPos - Abs(DeltaPosMinor) <= lngAddnlMinorTickStopPos Then Exit Do
+ lngAddnlMinorTickPos = lngAddnlMinorTickPos - Abs(DeltaPosMinor)
+ Else
+ If lngAddnlMinorTickPos + Abs(DeltaPosMinor) >= lngAddnlMinorTickStopPos Then Exit Do
+ lngAddnlMinorTickPos = lngAddnlMinorTickPos + Abs(DeltaPosMinor)
+ End If
+
+ intTickIndexMinor = intTickIndexMinor + 1
+ intTickIndexMinorTrack = intTickIndexMinorTrack + 1
+
+ ' May need to load more minor ticks
+ If ThesePlotOptions.MinorTicksLoaded < intTickIndexMinorTrack Then
+ ThesePlotOptions.MinorTicksLoaded = ThesePlotOptions.MinorTicksLoaded + 1
+ Load ThisForm.linTickMinor(ThesePlotOptions.MinorTicksLoaded)
+ End If
+
+ ' Add the minor tick mark
+ AddMinorTickmark ThisForm, intTickIndexMinor, intTickIndexMinorTrack, lngAddnlMinorTickPos, LengthStartPosMinor, LengthEndPosMinor, blnXAxis
+ Loop
+ End If
+
+ With ThisForm
+ ' Check for overlapping tick labels
+ ' If there is overlap, then show every other or every 5th label
+ intKeepEveryXthTick = 1
+ If intMajorTicksToShow >= 3 Then
+ If blnXAxis Then
+ If .lblTick(1).Left + .lblTick(1).Width > .lblTick(3).Left Then intKeepEveryXthTick = 5
+ Else
+ If .lblTick(intInitialTickIndex + 3).top + .lblTick(intInitialTickIndex + 3).Height > .lblTick(intInitialTickIndex + 1).top Then intKeepEveryXthTick = 5
+ End If
+ End If
+
+ If intKeepEveryXthTick = 1 And intMajorTicksToShow >= 2 Then
+ If blnXAxis Then
+ If .lblTick(1).Left + .lblTick(1).Width > .lblTick(2).Left Then intKeepEveryXthTick = 2
+ Else
+ If .lblTick(intInitialTickIndex + 2).top + .lblTick(intInitialTickIndex + 2).Height > .lblTick(intInitialTickIndex + 1).top Then intKeepEveryXthTick = 2
+ End If
+ End If
+
+ If intKeepEveryXthTick > 1 Then
+ For intTickIndexToHide = intInitialTickIndex + 1 To intInitialTickIndex + intMajorTicksToShow
+ If intTickIndexToHide Mod intKeepEveryXthTick <> 0 Then
+ .lblTick(intTickIndexToHide).Visible = False
+ End If
+ Next intTickIndexToHide
+ End If
+ End With
+
+ ' Store intTickIndex in intInitialTickIndex
+ intInitialTickIndex = intTickIndex - 1
+
+ ' Store intTickIndexMinorTrack in intInitialTickMinorIndex
+ intInitialTickMinorIndex = intTickIndexMinorTrack
+
+
+ With ThisForm
+ ' Hide remaining loaded ticks
+ For intTickIndexToHide = intInitialTickIndex + 1 To ThesePlotOptions.MajorTicksLoaded
+ .linTickMajor(intTickIndexToHide).Visible = False
+ .linGridline(intTickIndexToHide).Visible = False
+ .lblTick(intTickIndexToHide).Visible = False
+ Next intTickIndexToHide
+
+ For intTickIndexToHide = intInitialTickMinorIndex + 1 To ThesePlotOptions.MinorTicksLoaded
+ .linTickMinor(intTickIndexToHide).Visible = False
+ Next intTickIndexToHide
+ End With
+
+End Sub
+
+Private Sub AddMinorTickmark(ThisForm As VB.Form, intTickIndexMinor As Integer, intTickIndexMinorTrack As Integer, lngAddnlMinorTickPos As Long, LengthStartPosMinor As Long, LengthEndPosMinor As Long, blnXAxis As Boolean)
+ With ThisForm.linTickMinor(intTickIndexMinorTrack)
+ .x1 = lngAddnlMinorTickPos
+ .x2 = .x1
+ .y1 = LengthStartPosMinor + 20
+ .y2 = LengthEndPosMinor
+ If intTickIndexMinor Mod 5 = 0 Then
+ ' Draw the minor tick mark a little longer
+ If blnXAxis Then
+ .y1 = .y1 + 70
+ .y2 = .y2
+ Else
+ .y1 = .y1 - 50
+ .y2 = .y2
+ End If
+ End If
+ .Visible = True
+ End With
+
+ If Not blnXAxis Then SwapLineCoordinates ThisForm.linTickMinor(intTickIndexMinorTrack)
+
+End Sub
+
+Private Sub LoadDynamicPlotObjects(ThisForm As VB.Form, ThesePlotOptions As usrPlotDataOptions, XYDataToPlotCount As Long)
+ Dim lngLinesLoadedCountPrevious As Long
+ Dim blnShowProgress As Boolean, strCurrentTask As String
+
+ strCurrentTask = LookupMessage(1130)
+
+ With ThisForm
+ ' Load lines for data points if needed
+ If ThesePlotOptions.LinesLoadedCount < XYDataToPlotCount Then
+ lngLinesLoadedCountPrevious = ThesePlotOptions.LinesLoadedCount
+ If Abs(XYDataToPlotCount - lngLinesLoadedCountPrevious) > 100 Then
+ blnShowProgress = True
+ frmProgress.InitializeForm strCurrentTask, 0, Abs(XYDataToPlotCount - lngLinesLoadedCountPrevious)
+ frmProgress.ToggleAlwaysOnTop True
+ End If
+
+ Do While ThesePlotOptions.LinesLoadedCount < XYDataToPlotCount
+ If blnShowProgress Then
+ If ThesePlotOptions.LinesLoadedCount Mod 10 = 0 Then
+ frmProgress.UpdateProgressBar Abs(ThesePlotOptions.LinesLoadedCount - lngLinesLoadedCountPrevious) + 1
+ If KeyPressAbortProcess > 1 Then Exit Do
+ End If
+ End If
+
+ ThesePlotOptions.LinesLoadedCount = ThesePlotOptions.LinesLoadedCount + 1
+ Load .linData(ThesePlotOptions.LinesLoadedCount)
+ .linData(ThesePlotOptions.LinesLoadedCount).Visible = False
+ Loop
+ If blnShowProgress Then frmProgress.HideForm
+ End If
+ End With
+
+End Sub
+
+Public Function GetPlotSeriesColor(intSeriesNumber As Integer) As Long
+ ' intSeriesNumber can be 0, 1, 2, or other
+
+ Select Case intSeriesNumber
+ Case 0: GetPlotSeriesColor = RGB(0, 0, 150)
+ Case 1: GetPlotSeriesColor = vbRed
+ Case 2: GetPlotSeriesColor = vbGreen
+ Case Else: GetPlotSeriesColor = vbMagenta
+ End Select
+
+End Function
+
+Private Function RoundToEvenMultiple(ByVal dblValueToRound As Double, ByVal MultipleValue As Double, ByVal blnRoundUp As Boolean) As Double
+ Dim intLoopCount As Integer
+ Dim strWork As String, dblWork As Double
+ Dim lngExponentValue As Long
+
+ ' Find the exponent of MultipleValue
+ strWork = Format(MultipleValue, "0E+000")
+ lngExponentValue = CIntSafe(Right(strWork, 4))
+
+ intLoopCount = 0
+ Do While Trim(Str(dblValueToRound / MultipleValue)) <> Trim(Str(Round(dblValueToRound / MultipleValue, 0)))
+ dblWork = dblValueToRound / 10 ^ (lngExponentValue)
+ dblWork = Format(dblWork, "0")
+ dblWork = dblWork * 10 ^ (lngExponentValue)
+ If blnRoundUp Then
+ If dblWork <= dblValueToRound Then
+ dblWork = dblWork + 10 ^ lngExponentValue
+ End If
+ Else
+ If dblWork >= dblValueToRound Then
+ dblWork = dblWork - 10 ^ lngExponentValue
+ End If
+ End If
+ dblValueToRound = dblWork
+ intLoopCount = intLoopCount + 1
+ If intLoopCount > 500 Then
+ ' Bug
+' Debug.Assert False
+ Exit Do
+ End If
+ Loop
+
+ RoundToEvenMultiple = dblValueToRound
+End Function
+
+Public Function RoundToMultipleOf10(ByVal dblThisNum As Double, Optional ByRef lngExponentValue As Long) As Double
+ Dim strWork As String, dblWork As Double
+
+ ' Round to nearest 1, 2, or 5 (or multiple of 10 thereof)
+ ' First, find the exponent of dblThisNum
+ strWork = Format(dblThisNum, "0E+000")
+ lngExponentValue = CIntSafe(Right(strWork, 4))
+ dblWork = dblThisNum / 10 ^ lngExponentValue
+ dblWork = CIntSafeDbl(dblWork)
+
+ ' dblWork should now be between 0 and 9
+ Select Case dblWork
+ Case 0, 1: dblThisNum = 1
+ Case 2 To 4: dblThisNum = 2
+ Case Else: dblThisNum = 5
+ End Select
+
+ ' Convert dblThisNum back to the correct magnitude
+ dblThisNum = dblThisNum * 10 ^ lngExponentValue
+
+ RoundToMultipleOf10 = dblThisNum
+End Function
+
+Private Sub ScaleData(ThesePlotOptions As usrPlotDataOptions, XYDataToPlot() As usrXYData, XYDataToPlotCount As Long, ByRef ThisAxisRange As usrPlotRangeAxis, ThisAxisScaling As usrPlotRangeAxis, blnXAxis As Boolean, blnAutoScaleAxis As Boolean)
+
+ Dim dblMinimumIntensity As Double
+ Dim lngIndex As Long, dblDataPoint As Double
+ Dim dblValRange As Double, dblDeltaScaler As Double, ThisAxisWindowLength As Long
+ Dim strFormatString As String, intDigitsInLabel As Integer
+
+ ' First step through valid data and find the minimum YVal value
+ ' Necessary to check if negative
+ dblMinimumIntensity = HighestValueForDoubleDataType
+ For lngIndex = 1 To XYDataToPlotCount
+ If blnXAxis Then
+ dblDataPoint = XYDataToPlot(lngIndex).XVal
+ Else
+ dblDataPoint = XYDataToPlot(lngIndex).YVal
+ End If
+ If dblDataPoint < dblMinimumIntensity Then
+ dblMinimumIntensity = dblDataPoint
+ End If
+ Next lngIndex
+
+ ' Reset .ValNegativeValueCorrectionOffset
+ ThisAxisRange.ValNegativeValueCorrectionOffset = 0
+
+ If blnAutoScaleAxis Then
+ If dblMinimumIntensity < 0 Then
+ ' Need to correct all y data by making it positive
+ ThisAxisRange.ValNegativeValueCorrectionOffset = Abs(dblMinimumIntensity)
+ End If
+ Else
+ ' The user has supplied ValStart and ValEnd values
+ ' Make sure .ValStart.Val < .ValEnd.Val
+ ' No need to use a NegativeValueCorrectionOffset since I perform bounds checking during the conversion from val to pos
+ If ThisAxisScaling.ValStart.Val > ThisAxisScaling.ValEnd.Val Then
+ SwapValues ThisAxisScaling.ValStart.Val, ThisAxisScaling.ValEnd.Val
+ End If
+ End If
+
+ If ThisAxisRange.ValNegativeValueCorrectionOffset > 0 Then
+ For lngIndex = 1 To XYDataToPlotCount
+ If blnXAxis Then
+ XYDataToPlot(lngIndex).XVal = XYDataToPlot(lngIndex).XVal + ThisAxisRange.ValNegativeValueCorrectionOffset
+ Else
+ XYDataToPlot(lngIndex).YVal = XYDataToPlot(lngIndex).YVal + ThisAxisRange.ValNegativeValueCorrectionOffset
+ End If
+ Next lngIndex
+ End If
+
+ ' Record the current plot range for future reference when zooming
+ ThisAxisRange.ValStart.Val = ThisAxisScaling.ValStart.Val - ThisAxisRange.ValNegativeValueCorrectionOffset
+ ThisAxisRange.ValEnd.Val = ThisAxisScaling.ValEnd.Val - ThisAxisRange.ValNegativeValueCorrectionOffset
+
+ dblValRange = ThisAxisScaling.ValEnd.Val - ThisAxisScaling.ValStart.Val
+ If dblValRange = 0 Then dblValRange = 1
+
+ ' Scale the data according to ThesePlotOptions.height
+
+ If blnXAxis Then
+ ThisAxisWindowLength = ThesePlotOptions.PlotWidth
+ Else
+ ThisAxisWindowLength = ThesePlotOptions.PlotHeight
+ End If
+
+ dblDeltaScaler = CDbl(ThisAxisWindowLength) / CDbl(dblValRange)
+
+ For lngIndex = 1 To XYDataToPlotCount
+ If blnXAxis Then
+ dblDataPoint = XYDataToPlot(lngIndex).XVal
+ Else
+ dblDataPoint = XYDataToPlot(lngIndex).YVal
+ End If
+
+ dblDataPoint = Format((dblDataPoint - ThisAxisScaling.ValStart.Val) * dblDeltaScaler, "0")
+
+ If dblDataPoint > ThisAxisWindowLength Then
+ dblDataPoint = ThisAxisWindowLength
+ Else
+ If dblDataPoint < 0 Then
+ dblDataPoint = 0
+ End If
+ End If
+
+ If blnXAxis Then
+ XYDataToPlot(lngIndex).XVal = dblDataPoint
+ Else
+ XYDataToPlot(lngIndex).YVal = dblDataPoint
+ End If
+
+ Next lngIndex
+
+ If Not blnXAxis Then
+ ' Need to recompute .PlotLeftLargeNumberOffset
+ ' Call FindDigitsInLabelUsingRange to determine the digits in the label and construct the format string
+ intDigitsInLabel = FindDigitsInLabelUsingRange(ThisAxisRange, ThesePlotOptions.YAxis.MajorTicksToShow, strFormatString)
+
+ ' Store in .PlotLeftLargeNumberOffset
+ ThesePlotOptions.PlotLeftLargeNumberOffset = intDigitsInLabel * NUM_TWIPS_PER_DIGIT
+ End If
+
+ ' Record the current plot range for future reference when zooming
+ If blnXAxis Then
+ ThisAxisRange.ValStart.Pos = ThesePlotOptions.PlotLeft + ThesePlotOptions.PlotLeftLargeNumberOffset
+ ThisAxisRange.ValEnd.Pos = ThesePlotOptions.PlotLeft + ThesePlotOptions.PlotLeftLargeNumberOffset + ThesePlotOptions.PlotWidth
+ Else
+ ThisAxisRange.ValStart.Pos = ThesePlotOptions.PlotTop + ThesePlotOptions.PlotHeight
+ ThisAxisRange.ValEnd.Pos = ThesePlotOptions.PlotTop ' equivalent to: PlotBottom - CLng((dblValRange - ThisAxisScaling.ValStart) * dblDeltaScaler)
+ End If
+
+End Sub
+
+Public Sub ShellSortXYData(ByRef XYData() As usrXYData, ByRef XYDataPointerArray() As Long, ByVal lngLowIndex As Long, ByVal lngHighIndex As Long)
+ ' Sort the data by XYData().XVal
+ ' Rather than sorting the data itself, sorts a pointer array to the data
+
+ Dim lngCount As Long
+ Dim lngIncrement As Long
+ Dim lngIndex As Long
+ Dim lngIndexCompare As Long
+ Dim lngPointerSwap As Long
+
+ ' sort XYDataPointerArray[lngLowIndex..lngHighIndex]
+
+ ' compute largest increment
+ lngCount = lngHighIndex - lngLowIndex + 1
+ lngIncrement = 1
+ If (lngCount < 14) Then
+ lngIncrement = 1
+ Else
+ Do While lngIncrement < lngCount
+ lngIncrement = 3 * lngIncrement + 1
+ Loop
+ lngIncrement = lngIncrement \ 3
+ lngIncrement = lngIncrement \ 3
+ End If
+
+ Do While lngIncrement > 0
+ ' sort by insertion in increments of lngIncrement
+ For lngIndex = lngLowIndex + lngIncrement To lngHighIndex
+ lngPointerSwap = XYDataPointerArray(lngIndex)
+ For lngIndexCompare = lngIndex - lngIncrement To lngLowIndex Step -lngIncrement
+ ' Use <= to sort ascending; Use > to sort descending
+ If XYData(XYDataPointerArray(lngIndexCompare)).XVal <= XYData(lngPointerSwap).XVal Then Exit For
+ XYDataPointerArray(lngIndexCompare + lngIncrement) = XYDataPointerArray(lngIndexCompare)
+ Next lngIndexCompare
+ XYDataPointerArray(lngIndexCompare + lngIncrement) = lngPointerSwap
+ Next lngIndex
+ lngIncrement = lngIncrement \ 3
+ Loop
+
+End Sub
+
+Private Sub SwapLineCoordinates(ThisLine As Line)
+ Dim lngTemp As Long
+
+ With ThisLine
+ ' Setting y axis values
+ ' Must swap x1 and y1, and x2 and y2
+ lngTemp = .x1
+ .x1 = .y1
+ .y1 = lngTemp
+
+ lngTemp = .x2
+ .x2 = .y2
+ .y2 = lngTemp
+
+ End With
+End Sub
+Public Function XYPosToValue(ThisPos As Long, ThisRange As usrPlotRangeAxis) As Double
+ Dim PosRange As Long, ValRange As Double
+ Dim ScaledPos As Double
+
+ With ThisRange
+ ' Convert the x pos in ZoomBoxCoords to the actual x value
+ PosRange = .ValEnd.Pos - .ValStart.Pos
+ ValRange = .ValEnd.Val - .ValStart.Val
+
+ If PosRange <> 0 Then
+ ' ScaledPos is a value between 0 and 1 indicating the percentage between RangeEnd and RangeStart that ThisPos is
+ ScaledPos = (ThisPos - .ValStart.Pos) / PosRange
+
+ ' Now Convert to the displayed value
+ XYPosToValue = ScaledPos * ValRange + .ValStart.Val
+ Else
+ XYPosToValue = .ValStart.Val
+ End If
+ End With
+
+End Function
+
+Public Function XYValueToPos(ThisValue As Double, ThisRange As usrPlotRangeAxis, IsDeltaValue As Boolean) As Double
+ Dim PosRange As Long, ValRange As Double
+ Dim ScaledPos As Double
+
+ With ThisRange
+ ' Convert the x pos in ZoomBoxCoords to the actual x value
+ PosRange = .ValEnd.Pos - .ValStart.Pos
+ ValRange = .ValEnd.Val - .ValStart.Val
+
+ If ValRange <> 0 Then
+ If IsDeltaValue Then
+ ScaledPos = ThisValue / ValRange
+
+ ' Now Convert to correct position
+ XYValueToPos = ScaledPos * PosRange
+ Else
+ ' ScaledPos is a value between 0 and 1 indicating the percentage between RangeEnd and RangeStart that ThisPos is
+ ScaledPos = (ThisValue - .ValStart.Val) / ValRange
+
+ ' Now Convert to correct position
+ XYValueToPos = ScaledPos * PosRange + .ValStart.Pos
+ End If
+ Else
+ XYValueToPos = ThisRange.ValStart.Pos
+ End If
+ End With
+
+End Function
+
+
diff --git a/MsPlot/Cursors.zip b/MsPlot/Cursors.zip
new file mode 100644
index 0000000..f98ab8a
Binary files /dev/null and b/MsPlot/Cursors.zip differ
diff --git a/MsPlot/MsPlot.bas b/MsPlot/MsPlot.bas
new file mode 100644
index 0000000..06cabe0
--- /dev/null
+++ b/MsPlot/MsPlot.bas
@@ -0,0 +1,1596 @@
+Attribute VB_Name = "MsPlotRoutines"
+Option Explicit
+
+Private Const NUM_TWIPS_PER_DIGIT = 90
+Public Const MAX_DATA_SETS = 2 ' Up to 2 data sets may be graphed simultaneously (uses indices 0 and 1)
+
+Public Const LowestValueForDoubleDataType = -1.79E+308 ' -3.4E+38
+Public Const HighestValueForDoubleDataType = 1.79E+308 ' 3.4E+38
+
+Public Type usrAxisOptions
+ Show As Boolean ' Whether or not to show the axis
+ ShowLabels As Boolean ' whether or not to label axes
+ MajorTicksToShow As Integer ' The number of major tick values to show
+ ShowMinorTicks As Boolean ' Whether or not to show minor ticks
+ MinorTickMinimumPixelSep As Integer ' Minimum spacing in pixels between minor ticks before showing them
+
+ ShowGridLinesMajor As Boolean
+ ShowTickLinesMinor As Boolean
+
+End Type
+
+Public Type usrPlotRangeDetails
+ Val As Double
+ Pos As Long
+End Type
+
+Public Type usrPlotRangeAxis
+ ValStart As usrPlotRangeDetails
+ ValEnd As usrPlotRangeDetails
+ ValNegativeValueCorrectionOffset As Double
+End Type
+
+Public Type usrPlotRange
+ x As usrPlotRangeAxis
+ y As usrPlotRangeAxis
+End Type
+
+Public Type usrGaussianOptions
+ ResolvingPower As Long ' Effective resolution (M / delta M)
+ XValueOfSpecification As Single ' X Value where effective resolution applies
+End Type
+
+Public Type usrPlotDataOptions
+
+ PlotTypeCode As Integer ' Whether the plot is a stick plot (0) or line-between-points plot (1)
+ GaussianConversion As usrGaussianOptions
+
+ ' Zoom options
+ ZoomOutFull As Boolean ' When true, the data is shown fully zoomed out, ignoring the XVal and YVal Start and End values
+ AutoScaleY As Boolean ' When true, will zoom the x data as requested but always keep the y data at full scale
+ FixYAxisMinimumAtZero As Boolean ' Only used if AutoScaleY = True; keeps the minimum y scaling at 0 at all times (i.e. makes YValStart = 0)
+
+ ' Scaling options
+ Scaling As usrPlotRange ' Note that I do not use ValNegativeValueCorrectionOffset in Scaling, only in DataLimits
+ DataLimits(MAX_DATA_SETS) As usrPlotRange ' Records the largest and smallest values of the given data set
+ SortData As Boolean ' Whether or not to sort the data by x value before plotting
+
+ ' The following define the size of the spectrum in the parent frame
+ PlotLeft As Integer ' In Twips (VB units)
+ PlotTop As Integer ' In Twips (VB units)
+ PlotWidth As Integer ' In Twips (VB units)
+ PlotHeight As Integer ' In Twips (VB units)
+ PlotLeftLargeNumberOffset As Integer ' In Twips - used to offset the left of the graph to the right a little for very large or very small numbers
+
+ XAxis As usrAxisOptions
+ YAxis As usrAxisOptions
+
+ MajorTicksLoaded As Long ' There is a label and gridline loaded for each major tick loaded
+ MinorTicksLoaded As Long
+
+ boolLongOperationsRequired As Boolean ' Set to true when long operations are encountered, thus requiring an hourglass cursor
+
+ ' Labeling options
+ ShowDataPointLabels As Boolean ' Whether to label or not
+ LabelsToShow As Integer ' Number of labels to show
+ IndexToHighlight As Long ' Index of the x,y data pair to highlight (if any)
+ HighlightColor As Long ' default vbRed
+
+ LinesLoadedCount As Long ' Records the number of lines and labels that have been dynamically loaded
+End Type
+
+Public Type usrXYData
+ XVal As Double ' Note: Single data type is -3.402823E38 to 3.402823E38
+ YVal As Double
+End Type
+
+Public Type usrXYDataSet
+ XYDataList() As usrXYData ' Index 1 to XYDataListCount
+ XYDataListCount As Long
+ XYDataListCountDimmed As Long
+End Type
+
+Private Sub CheckForLongOperation(ThisForm As Form, lngSecondsElapsedAtStart As Long, PlotOptions As usrPlotDataOptions)
+ ' Checks to see if the current Timer() value (sec elapsed since midnight) is
+ ' greater than lngSecondsElapsedAtStart. If it is, it turns boolSavedCheckBit on
+ ' and sets the pointer to an hourglass
+ ' The boolSavedCheckBit value is saved for future calls to the sub so that the hourglass
+ ' will be activated immediately on future calls
+
+ If Timer() - lngSecondsElapsedAtStart > 1 Or PlotOptions.boolLongOperationsRequired Then
+ PlotOptions.boolLongOperationsRequired = True
+ ThisForm.MousePointer = vbHourglass
+ End If
+
+End Sub
+
+Public Function ConstructFormatString(dblThisValue As Double, Optional ByRef intDigitsInFormattedValue As Integer) As String
+ ' Examines dblThisValue and constructs a format string based on its magnitude
+ ' For example, dblThisValue = 1234 will return "0"
+ ' dblThisValue = 2.4323 will return "0.0000"
+ '
+ ' In addition, returns the length of the string representation of dblThisValue using the determined format string
+ Dim lngExponentValue As Long, intDigitsInLabel As Integer
+ Dim strWork As String, strFormatString As String
+
+ ' Determine width of label to use and construct formatting string for labels
+ ' First, find the exponent of dblThisValue
+ strWork = Format(dblThisValue, "0E+000")
+ lngExponentValue = CIntSafe(Right(strWork, 4))
+
+ ' Determine number of digits in dblThisValue, rounded according to lngExponentVal
+ If lngExponentValue >= 0 Then
+ intDigitsInLabel = 0
+ strFormatString = "0"
+ Else
+ ' Add 1 for the decimal point
+ intDigitsInLabel = -lngExponentValue + 1
+ strFormatString = "0." & String(-lngExponentValue, "0")
+ End If
+
+ intDigitsInFormattedValue = Len(Format(dblThisValue, strFormatString))
+
+ ConstructFormatString = strFormatString
+End Function
+
+Public Sub CheckDynamicXYData(ByRef ThisXYDataList() As usrXYData, ThisXYDataListCount As Long, ByRef ThisXYDataListCountDimmed As Long, Optional lngIncrement As Long = 100)
+ If ThisXYDataListCount > ThisXYDataListCountDimmed Then
+ ThisXYDataListCountDimmed = ThisXYDataListCountDimmed + lngIncrement
+ If ThisXYDataListCountDimmed < ThisXYDataListCount Then
+ ThisXYDataListCountDimmed = ThisXYDataListCount
+ End If
+ ReDim Preserve ThisXYDataList(ThisXYDataListCountDimmed)
+ End If
+End Sub
+
+Public Function ConvertStickDataToGaussian(ThisForm As Form, ThisXYDataSet As usrXYDataSet, PlotOptions As usrPlotDataOptions, intDataSetIndex As Integer) As usrXYDataSet
+ Dim XYDataPointerArray() As Long, XYDataPointerArrayCount As Long
+ Dim lngDataIndex As Long, lngMidPointIndex As Long
+ Dim lngStickIndex As Long, DeltaX As Double
+
+ Dim dblXValRange As Double, dblXValWindowRange As Double, dblRangeWork As Double
+ Dim dblMinimalXValOfWindow As Double, dblMinimalXValSpacing As Double
+
+ Dim dblXOffSet As Double, sigma As Double
+ Dim intDigitsToRoundTo As Integer, lngExponentValue As Long
+ Dim lngSecElapsedAtStart As Long
+
+ Dim XYSummation() As usrXYData, XYSummationCount As Long, XYSummationCountDimmed As Long
+ Dim lngSummationIndex As Long, lngMinimalSummationIndex As Long, lngOffsetIndex As Long
+ Dim DataToAdd() As usrXYData, lngDataToAddCount As Long, boolAppendNewData As Boolean
+ Dim boolSequentialValueFound As Boolean
+ Dim ThisDataPoint As usrXYData
+
+ Const NUM_CHUNKS = 100
+
+ If ThisXYDataSet.XYDataListCount = 0 Then Exit Function
+
+ lngSecElapsedAtStart = Timer()
+
+ If PlotOptions.GaussianConversion.ResolvingPower < 1 Then
+ PlotOptions.GaussianConversion.ResolvingPower = 1
+ End If
+
+ XYSummationCount = 0
+ XYSummationCountDimmed = 100
+ ReDim XYSummation(XYSummationCountDimmed)
+
+ With ThisXYDataSet
+ ' Initialize the Pointer Array
+ XYDataPointerArrayCount = .XYDataListCount
+ ReDim XYDataPointerArray(XYDataPointerArrayCount)
+ For lngDataIndex = 1 To XYDataPointerArrayCount
+ XYDataPointerArray(lngDataIndex) = lngDataIndex
+ Next lngDataIndex
+
+ ' See if data is sorted; if not, sort it
+ ' Force .SortData to be True
+ PlotOptions.SortData = True
+ CheckDataLimitsAndSortData ThisForm, .XYDataList(), XYDataPointerArray(), XYDataPointerArrayCount, PlotOptions, intDataSetIndex
+
+ PlotOptions.DataLimits(intDataSetIndex).x.ValStart.Val = .XYDataList(XYDataPointerArray(1)).XVal
+ PlotOptions.DataLimits(intDataSetIndex).x.ValEnd.Val = .XYDataList(XYDataPointerArray(XYDataPointerArrayCount)).XVal
+ End With
+
+ With PlotOptions
+ dblXValRange = .DataLimits(intDataSetIndex).x.ValEnd.Val - .DataLimits(intDataSetIndex).x.ValStart.Val
+
+ ' Set DeltaX using .ResolvingPower and .XValueOfSpecification
+ ' Do not allow the DeltaX to be so small that the total points required > 100,000
+ DeltaX = .GaussianConversion.XValueOfSpecification / .GaussianConversion.ResolvingPower / 20
+ ' Make sure DeltaX is a reasonable number
+ DeltaX = RoundToMultipleOf10(DeltaX)
+ If DeltaX = 0 Then DeltaX = 1
+
+ ' Set the Window Range to 1/10 the magnitude of the midpoint x value
+ dblRangeWork = .DataLimits(intDataSetIndex).x.ValStart.Val + dblXValRange / 2
+ dblRangeWork = RoundToMultipleOf10(dblRangeWork, lngExponentValue)
+
+ sigma = (.GaussianConversion.XValueOfSpecification / .GaussianConversion.ResolvingPower) / Sqr(5.54)
+
+ ' Set the window range (the xvalue window width range) to calculate the Gaussian representation for each data point
+ ' The width at the base of a peak is 4 sigma
+ ' Use a width of 2 * 6 sigma
+ dblXValWindowRange = 2 * 6 * sigma
+
+ If dblXValWindowRange / DeltaX > 50000 Then
+ DeltaX = dblXValWindowRange / 50000
+ End If
+
+ lngDataToAddCount = CLng(dblXValWindowRange / DeltaX)
+ ' Make sure lngDataToAddCount is odd
+ If CSng(lngDataToAddCount) / 2! = Round(CSng(lngDataToAddCount) / 2!, 0) Then
+ lngDataToAddCount = lngDataToAddCount + 1
+ End If
+ ReDim DataToAdd(lngDataToAddCount)
+ lngMidPointIndex = (lngDataToAddCount + 1) / 2
+ End With
+
+ With ThisXYDataSet
+''' frmProgress.InitializeForm "Creating Gaussian Representation", 0, XYDataPointerArrayCount
+ For lngStickIndex = 1 To XYDataPointerArrayCount
+''' frmProgress.UpdateProgressBar lngStickIndex
+ If lngStickIndex Mod 50 = 0 Then
+ CheckForLongOperation ThisForm, lngSecElapsedAtStart, PlotOptions
+ End If
+
+ ' Search through XYSummation to determine the index of the smallest XValue with which
+ ' data in DataToAdd could be combined
+ lngMinimalSummationIndex = 1
+ dblMinimalXValOfWindow = .XYDataList(XYDataPointerArray(lngStickIndex)).XVal - (lngMidPointIndex - 1) * DeltaX
+ If dblMinimalXValOfWindow > XYSummation(XYSummationCount).XVal Then
+ lngMinimalSummationIndex = XYSummationCount
+ Else
+ For lngSummationIndex = 1 To XYSummationCount
+ If XYSummation(lngSummationIndex).XVal >= dblMinimalXValOfWindow Then
+ lngMinimalSummationIndex = lngSummationIndex - 1
+ If lngMinimalSummationIndex < 1 Then lngMinimalSummationIndex = 1
+ Exit For
+ End If
+ Next lngSummationIndex
+ If lngSummationIndex > XYSummationCount Then
+ lngMinimalSummationIndex = XYSummationCount
+ End If
+ End If
+
+ ' Construct the Gaussian representation for this Data Point
+ ThisDataPoint = .XYDataList(XYDataPointerArray(lngStickIndex))
+
+ ' Round ThisDataPoint.XVal to the nearest DeltaX
+ ' If .XVal is not an even multiple of DeltaX then bump up .XVal until it is
+ ThisDataPoint.XVal = RoundToEvenMultiple(ThisDataPoint.XVal, DeltaX, True)
+
+ For lngDataIndex = 1 To lngDataToAddCount
+ ' Equation for Gaussian is: Amplitude * Exp[ -(x - mu)^2 / (2*sigma^2) ]
+ ' Use lngDataIndex, .YVal, and DeltaX
+ dblXOffSet = (lngMidPointIndex - lngDataIndex) * DeltaX
+ DataToAdd(lngDataIndex).XVal = ThisDataPoint.XVal - dblXOffSet
+ DataToAdd(lngDataIndex).YVal = ThisDataPoint.YVal * Exp(-(dblXOffSet) ^ 2 / (2 * sigma ^ 2))
+ Next lngDataIndex
+
+ ' Now merge DataToAdd into XYSummation
+ ' XValues in DataToAdd and those in XYSummation have the same DeltaX value
+ ' The XValues in DataToAdd might overlap partially with those in XYSummation
+
+ lngDataIndex = 1
+ ' First, see if the first XValue in DataToAdd is larger than the last XValue in XYSummation
+ If DataToAdd(lngDataIndex).XVal > XYSummation(XYSummationCount).XVal Then
+ boolAppendNewData = True
+ Else
+ boolAppendNewData = False
+ ' Step through XYSummation() starting at lngMinimalSummationIndex, looking for
+ ' the index to start combining data at
+ For lngSummationIndex = lngMinimalSummationIndex To XYSummationCount
+ If DataToAdd(lngDataIndex).XVal = XYSummation(lngSummationIndex).XVal Or DataToAdd(lngDataIndex).XVal < XYSummation(lngSummationIndex).XVal Then
+ '''Debug.Assert XYSummation(lngSummationIndex).XVal = DataToAdd(lngDataIndex).XVal
+ ' Within Tolerance; start combining the values here
+ Do While lngSummationIndex <= XYSummationCount
+ XYSummation(lngSummationIndex).YVal = XYSummation(lngSummationIndex).YVal + DataToAdd(lngDataIndex).YVal
+ lngSummationIndex = lngSummationIndex + 1
+ lngDataIndex = lngDataIndex + 1
+ If lngDataIndex > lngDataToAddCount Then
+ ' Successfully combined all of the data
+ Exit Do
+ End If
+ Loop
+ If lngDataIndex <= lngDataToAddCount Then
+ ' Data still remains to be added
+ boolAppendNewData = True
+ End If
+ Exit For
+ End If
+ Next lngSummationIndex
+ End If
+
+ If boolAppendNewData = True Then
+ CheckDynamicXYData XYSummation(), XYSummationCount + lngDataToAddCount - lngDataIndex + 1, XYSummationCountDimmed
+ Do While lngDataIndex <= lngDataToAddCount
+ ThisDataPoint = DataToAdd(lngDataIndex)
+ XYSummationCount = XYSummationCount + 1
+ XYSummation(XYSummationCount) = ThisDataPoint
+ lngDataIndex = lngDataIndex + 1
+ Loop
+ End If
+
+ Next lngStickIndex
+
+ End With
+
+ ' Step through XYSummation and remove areas of sequential equivalent values
+ lngSummationIndex = 1
+ RoundToMultipleOf10 DeltaX, lngExponentValue
+ If lngExponentValue < 0 Then
+ intDigitsToRoundTo = Abs(lngExponentValue)
+ Else
+ intDigitsToRoundTo = 0
+ End If
+
+ ' Assure there is a data point at each 1% point along x range
+ ' Probably need to add data, but may need to remove some
+ dblMinimalXValSpacing = dblXValRange / 100
+
+ Do While lngSummationIndex <= XYSummationCount - 1
+ If XYSummation(lngSummationIndex).XVal + dblMinimalXValSpacing < XYSummation(lngSummationIndex + 1).XVal Then
+ ' Need to insert a data point
+ XYSummationCount = XYSummationCount + 1
+ CheckDynamicXYData XYSummation, XYSummationCount, XYSummationCountDimmed
+ For lngDataIndex = XYSummationCount To lngSummationIndex + 2 Step -1
+ XYSummation(lngDataIndex) = XYSummation(lngDataIndex - 1)
+ Next lngDataIndex
+ XYSummation(lngSummationIndex + 1).XVal = XYSummation(lngSummationIndex + 1).XVal + dblMinimalXValSpacing
+ XYSummation(lngSummationIndex + 1).YVal = (XYSummation(lngSummationIndex + 1).YVal + XYSummation(lngSummationIndex + 2).YVal) / 2
+ End If
+ lngSummationIndex = lngSummationIndex + 1
+ Loop
+
+ HideProgressForm
+
+ ' Reset the boolLongOperationsRequired bit
+ PlotOptions.boolLongOperationsRequired = False
+
+ ' ReDim XYSummation to XYSummationCount since DrawPlot assumes this is the case
+ XYSummationCountDimmed = XYSummationCount
+ ReDim Preserve XYSummation(XYSummationCountDimmed)
+
+ ' Assign data in XYSummation to the function so that it gets returned
+ ConvertStickDataToGaussian.XYDataList = XYSummation
+ ConvertStickDataToGaussian.XYDataListCount = XYSummationCount
+ ConvertStickDataToGaussian.XYDataListCountDimmed = XYSummationCountDimmed
+
+End Function
+
+Private Sub CheckDataLimitsAndSortData(ThisForm As Form, ThisXYData() As usrXYData, XYDataPointerArray() As Long, XYDataPointerArrayCount As Long, PlotOptions As usrPlotDataOptions, intDataSetIndex As Integer)
+ Dim boolNeedsSorting As Boolean, lngIndex As Long
+ Dim dblMaximumIntensity As Double, dblMinimumIntensity As Double
+ Dim dblXYDataPoint As Double
+
+
+ If PlotOptions.DataLimits(intDataSetIndex).y.ValStart.Val = 0 And PlotOptions.DataLimits(intDataSetIndex).y.ValEnd.Val = 0 Then
+ ' Data Limits not defined
+ ' Figure out what they are and sort data if necessary
+
+ ' Find the Y scale data limits
+ ' At the same time, see if the data is sorted
+ dblMaximumIntensity = LowestValueForDoubleDataType
+ dblMinimumIntensity = HighestValueForDoubleDataType
+ boolNeedsSorting = False
+ For lngIndex = 1 To XYDataPointerArrayCount
+ dblXYDataPoint = ThisXYData(XYDataPointerArray(lngIndex)).YVal
+ If dblXYDataPoint > dblMaximumIntensity Then dblMaximumIntensity = dblXYDataPoint
+ If dblXYDataPoint < dblMinimumIntensity Then dblMinimumIntensity = dblXYDataPoint
+ If lngIndex < XYDataPointerArrayCount Then
+ If ThisXYData(XYDataPointerArray(lngIndex)).XVal > ThisXYData(XYDataPointerArray(lngIndex + 1)).XVal Then
+ boolNeedsSorting = True
+ End If
+ End If
+ Next lngIndex
+ PlotOptions.DataLimits(intDataSetIndex).y.ValStart.Val = dblMinimumIntensity
+ PlotOptions.DataLimits(intDataSetIndex).y.ValEnd.Val = dblMaximumIntensity
+
+ If boolNeedsSorting And PlotOptions.SortData Then
+ ' Need to sort data
+ ThisForm.MousePointer = vbHourglass
+ SortXYData ThisXYData(), XYDataPointerArray(), XYDataPointerArrayCount, False
+ End If
+ End If
+
+End Sub
+
+Public Sub DrawPlot(ThisForm As Form, PlotOptions As usrPlotDataOptions, ThisXYDataArray() As usrXYDataSet, ByRef PlotRange() As usrPlotRange, intDataSetsLoaded As Integer)
+ ' Draw a graphical representation of a list of x,y data pairs in one or more data sets (stored in ThisXYDataArray)
+ ' Assumes the x,y data point array is 1-based (i.e. the first data point is in index 1
+
+ Dim intDataSetIndex As Integer
+ Dim lngIndex As Long, lngLineIndex As Long
+ Dim PlotBottom As Long, lngLeftOffset As Long
+ Dim lngSecElapsedAtStart As Long
+ Dim intKeepEveryXthPoint As Integer, lngXYDataToCountTrack As Long
+
+ Const MaxLinesCount = 32000
+
+ Dim XYDataToPlot() As usrXYData, XYDataToPlotCount As Long
+
+ Dim XYDataPointerArray() As Long
+ Dim XYDataPointerArrayCount As Long, XYDataIndex As Long
+
+ Dim HighlightIndex As Long
+ Dim dblPreviousMinimum As Double
+ Dim lngChunkSize As Long, lngMinimumValIndex As Long, lngMaximumValIndex As Long
+ Dim boolNeedsSorting As Boolean
+
+ Dim StartXVal As Double, XValRange As Double, DeltaXScaler As Double
+ Dim StartXValIndex As Long, EndXValIndex As Long
+ Dim strWork As String, intExponentValue As Integer, dblWork As Double
+
+ Dim LastLabelTwip As Long, TwipsBetweenLabels As Long
+ Dim intDynamicObjectOffset As Integer, lngDataSetLineColor As Long
+ Dim dblMinimumIntensity As Double, dblMaximumIntensity As Double
+
+ ' Need to determine the correct scaling values if autoscaling the y-axis
+ ' Only works if the data is sorted in the x direction
+ If PlotOptions.AutoScaleY Or PlotOptions.FixYAxisMinimumAtZero Then
+ ' Find the minimum and maximum y intensities for all data sets within the range of x data being shown
+ dblMaximumIntensity = LowestValueForDoubleDataType
+ dblMinimumIntensity = HighestValueForDoubleDataType
+ For intDataSetIndex = 0 To intDataSetsLoaded - 1
+ With ThisXYDataArray(intDataSetIndex)
+ ' Step through .XYDataList and find index of the start x value
+ For lngIndex = 1 To .XYDataListCount
+ If .XYDataList(lngIndex).XVal >= PlotOptions.Scaling.x.ValStart.Val Then
+ StartXValIndex = lngIndex
+ Exit For
+ End If
+ Next lngIndex
+
+ ' Step through .XYDataList and find index of the end x value
+ For lngIndex = .XYDataListCount To 1 Step -1
+ If .XYDataList(lngIndex).XVal <= PlotOptions.Scaling.x.ValEnd.Val Then
+ EndXValIndex = lngIndex
+ Exit For
+ End If
+ Next lngIndex
+
+ For lngIndex = StartXValIndex To EndXValIndex
+ dblWork = .XYDataList(lngIndex).YVal
+ If dblWork > dblMaximumIntensity Then
+ dblMaximumIntensity = dblWork
+ End If
+ If dblWork < dblMinimumIntensity Then
+ dblMinimumIntensity = dblWork
+ End If
+ Next lngIndex
+ End With
+ Next intDataSetIndex
+
+ If PlotOptions.FixYAxisMinimumAtZero Then
+ ' Only fix Y axis range at zero, and only fix if .FixYAxisMinimumAtZero is true
+ PlotOptions.Scaling.y.ValStart.Val = 0
+ Else
+ PlotOptions.Scaling.y.ValStart.Val = dblMinimumIntensity ' + ThisAxisRange.ValNegativeValueCorrectionOffset
+ End If
+
+ PlotOptions.Scaling.y.ValEnd.Val = dblMaximumIntensity ' + ThisAxisRange.ValNegativeValueCorrectionOffset
+ End If
+
+ intDynamicObjectOffset = 0
+ For intDataSetIndex = 0 To intDataSetsLoaded - 1
+ Select Case intDataSetIndex
+ Case 0: lngDataSetLineColor = vbBlack
+ Case 1: lngDataSetLineColor = vbRed
+ Case 2: lngDataSetLineColor = vbGreen
+ Case Else: lngDataSetLineColor = vbMagenta
+ End Select
+
+ If ThisXYDataArray(intDataSetIndex).XYDataListCount > 0 Then
+
+ lngSecElapsedAtStart = Timer()
+
+ ' Initialize the pointer array
+ XYDataPointerArrayCount = ThisXYDataArray(intDataSetIndex).XYDataListCount
+ ReDim XYDataPointerArray(XYDataPointerArrayCount)
+ For lngIndex = 1 To XYDataPointerArrayCount
+ XYDataPointerArray(lngIndex) = lngIndex
+ Next lngIndex
+
+ ' See if data is sorted; if not, sort it
+ CheckDataLimitsAndSortData ThisForm, ThisXYDataArray(intDataSetIndex).XYDataList, XYDataPointerArray(), XYDataPointerArrayCount, PlotOptions, intDataSetIndex
+
+ With ThisXYDataArray(intDataSetIndex)
+
+ ' Determine the location in the parent frame of the bottom of the Plot
+ PlotBottom = PlotOptions.PlotTop + PlotOptions.PlotHeight
+
+ StartXValIndex = 1
+ EndXValIndex = .XYDataListCount
+
+ ' Record the X scale data limits
+ PlotOptions.DataLimits(intDataSetIndex).x.ValStart.Val = .XYDataList(XYDataPointerArray(StartXValIndex)).XVal
+ PlotOptions.DataLimits(intDataSetIndex).x.ValEnd.Val = .XYDataList(XYDataPointerArray(EndXValIndex)).XVal
+
+ ' Initialize .Scaling.x.ValStart.Val and .Scaling.y.ValStart.Val if necessary
+ If PlotOptions.Scaling.x.ValStart.Val = 0 And PlotOptions.Scaling.x.ValEnd.Val = 0 Then
+ PlotOptions.Scaling.x.ValStart.Val = .XYDataList(XYDataPointerArray(StartXValIndex)).XVal
+ PlotOptions.Scaling.x.ValEnd.Val = .XYDataList(XYDataPointerArray(EndXValIndex)).XVal
+ End If
+
+ ' Make sure .Scaling.X.ValStart.Val < .Scaling.X.ValEnd
+ If PlotOptions.Scaling.x.ValStart.Val > PlotOptions.Scaling.x.ValEnd.Val Then
+ SwapValues PlotOptions.Scaling.x.ValStart.Val, PlotOptions.Scaling.x.ValEnd.Val
+ End If
+
+ If Not PlotOptions.ZoomOutFull Then
+ ' Step through .XYDataList and find index of the start x value
+ For lngIndex = 1 To .XYDataListCount
+ If .XYDataList(XYDataPointerArray(lngIndex)).XVal >= PlotOptions.Scaling.x.ValStart.Val Then
+ StartXValIndex = lngIndex
+ Exit For
+ End If
+ Next lngIndex
+
+ ' Step through .XYDataList and find index of the end x value
+ For lngIndex = .XYDataListCount To 1 Step -1
+ If .XYDataList(XYDataPointerArray(lngIndex)).XVal <= PlotOptions.Scaling.x.ValEnd.Val Then
+ EndXValIndex = lngIndex
+ Exit For
+ End If
+ Next lngIndex
+ End If
+
+ ' Make sure StartValIndex <= EndValIndex
+ If StartXValIndex > EndXValIndex Then
+ SwapValues StartXValIndex, EndXValIndex
+ End If
+
+ ' Check to see if Mouse Pointer should be changed to hourglass
+ CheckForLongOperation ThisForm, lngSecElapsedAtStart, PlotOptions
+
+ ' Copy the data into XYDataToPlot, reindexing to start at 1 and going to XYDataToPlotCount
+ ' Although this uses more memory because it duplicates the data, I soon replace the
+ ' raw data values with location positions in twips
+ '
+ ' In addition, if there is far more data than could be possibly plotted,
+ ' I throw away every xth data point, though with a twist
+
+ XYDataToPlotCount = EndXValIndex - StartXValIndex + 1
+
+ If XYDataToPlotCount > PlotOptions.PlotWidth / 10 Then
+ ' Throw away some of the data: Note that CIntSafe will round 2.5 up to 3
+ intKeepEveryXthPoint = CIntSafeDbl(XYDataToPlotCount / (PlotOptions.PlotWidth / 10))
+ lngChunkSize = intKeepEveryXthPoint * 2
+ Else
+ intKeepEveryXthPoint = 1
+ End If
+
+ ReDim XYDataToPlot(CLngRoundUp(XYDataToPlotCount / intKeepEveryXthPoint) + 10)
+
+ If intKeepEveryXthPoint = 1 Then
+ lngXYDataToCountTrack = 0
+ For lngIndex = StartXValIndex To EndXValIndex
+ lngXYDataToCountTrack = lngXYDataToCountTrack + 1
+ XYDataToPlot(lngXYDataToCountTrack) = .XYDataList(XYDataPointerArray(lngIndex))
+ If XYDataPointerArray(lngIndex) = PlotOptions.IndexToHighlight Then
+ HighlightIndex = lngXYDataToCountTrack
+ End If
+ Next lngIndex
+ Else
+ ' Step through the data examining chunks of numbers twice the length of intKeepEveryXthPoint
+ ' Find the minimum and maximum value in each chunk of numbers
+ ' Store these values in the array to keep (minimum followed by maximum)
+ ' Swap the stored order if both numbers are less than the previous two numbers
+
+ ' Store the first value of .xydatalist() in the output array
+ lngXYDataToCountTrack = 1
+ XYDataToPlot(lngXYDataToCountTrack) = .XYDataList(XYDataPointerArray(StartXValIndex))
+ If XYDataPointerArray(StartXValIndex) = PlotOptions.IndexToHighlight Then
+ HighlightIndex = lngXYDataToCountTrack
+ End If
+
+ dblPreviousMinimum = LowestValueForDoubleDataType
+ For lngIndex = StartXValIndex + 1 To EndXValIndex - 1 Step lngChunkSize
+
+ FindMinimumAndMaximum lngMinimumValIndex, lngMaximumValIndex, .XYDataList(), XYDataPointerArray(), lngIndex, lngIndex + lngChunkSize
+
+ ' Check if the maximum value of this pair of points is less than the minimum value of the previous pair
+ ' If it is, the y values of the two points should be exchanged
+ If .XYDataList(XYDataPointerArray(lngMaximumValIndex)).YVal < dblPreviousMinimum Then
+ ' Update dblPreviousMinimum
+ dblPreviousMinimum = .XYDataList(XYDataPointerArray(lngMinimumValIndex)).YVal
+ ' Swap minimum and maximum so that maximum gets saved to array first
+ SwapValues lngMinimumValIndex, lngMaximumValIndex
+ Else
+ ' Update dblPreviousMinimum
+ dblPreviousMinimum = .XYDataList(XYDataPointerArray(lngMinimumValIndex)).YVal
+ End If
+
+ lngXYDataToCountTrack = lngXYDataToCountTrack + 1
+ XYDataToPlot(lngXYDataToCountTrack) = .XYDataList(XYDataPointerArray(lngMinimumValIndex))
+ If XYDataPointerArray(lngMinimumValIndex) = PlotOptions.IndexToHighlight Then
+ HighlightIndex = lngXYDataToCountTrack
+ End If
+
+ lngXYDataToCountTrack = lngXYDataToCountTrack + 1
+ XYDataToPlot(lngXYDataToCountTrack) = .XYDataList(XYDataPointerArray(lngMaximumValIndex))
+ If XYDataPointerArray(lngMaximumValIndex) = PlotOptions.IndexToHighlight Then
+ HighlightIndex = lngXYDataToCountTrack
+ End If
+
+ ' Now check to see if the .XVal of the first value is greater than the first
+ ' If so, swap the .XVals
+ If XYDataToPlot(lngXYDataToCountTrack - 1).XVal > XYDataToPlot(lngXYDataToCountTrack).XVal Then
+ SwapValues XYDataToPlot(lngXYDataToCountTrack - 1).XVal, XYDataToPlot(lngXYDataToCountTrack).XVal
+ End If
+ Next lngIndex
+
+ ' Store the last value of .xydatalist() in the output array
+ lngXYDataToCountTrack = lngXYDataToCountTrack + 1
+ XYDataToPlot(lngXYDataToCountTrack) = .XYDataList(XYDataPointerArray(EndXValIndex))
+ If XYDataPointerArray(EndXValIndex) = PlotOptions.IndexToHighlight Then
+ HighlightIndex = lngXYDataToCountTrack
+ End If
+
+ End If
+
+ ' Set XYDataToPlotCount to the lngXYDataToCountTrack value resulting from the copying
+ XYDataToPlotCount = lngXYDataToCountTrack
+
+ End With
+
+ ' Scale the data vertically according to PlotOptions.height
+ ' i.e., replace the actual y values with locations in twips for where the data point belongs on the graph
+ ' The new value will range from 0 to PlotOptions.Height
+ ' Note that PlotOptions.PlotLeftLargeNumberOffset is computed in ScaleData for the Y axis
+ ScaleData PlotOptions, XYDataToPlot(), XYDataToPlotCount, PlotRange(intDataSetIndex).y, PlotOptions.Scaling.y, False, PlotOptions.AutoScaleY
+
+ ' Now scale the data to twips, ranging 0 to .PlotWidth and 0 to .PlotHeight
+ ' X axis
+ ScaleData PlotOptions, XYDataToPlot(), XYDataToPlotCount, PlotRange(intDataSetIndex).x, PlotOptions.Scaling.x, True, False
+
+ ' Load lines and labels for each XVal
+ If PlotOptions.LinesLoadedCount = 0 Then
+ ' Only initialize to 1 the first time this sub is called
+ PlotOptions.LinesLoadedCount = 1
+ End If
+
+ ' Limit the total points shown if greater than MaxLinesCount
+ If XYDataToPlotCount > MaxLinesCount Then
+ ' This code should not be reached since extra data should have been thrown away above
+ Debug.Assert False
+ XYDataToPlotCount = MaxLinesCount
+ End If
+
+ ' Load dynamic plot objects as needed
+ LoadDynamicPlotObjects ThisForm, PlotOptions, intDynamicObjectOffset + XYDataToPlotCount
+
+ ' Must re-initialize the pointer array
+ XYDataPointerArrayCount = XYDataToPlotCount
+ ReDim XYDataPointerArray(XYDataToPlotCount)
+ For lngIndex = 1 To XYDataToPlotCount
+ XYDataPointerArray(lngIndex) = lngIndex
+ Next lngIndex
+
+ If PlotOptions.PlotTypeCode = 0 Then
+ ' Plot the data as sticks to zero
+ If PlotOptions.ShowDataPointLabels And PlotOptions.LabelsToShow > 0 Then
+ ' Sort the data by YVal, draw in order of YVal, and only label top specified peaks
+ SortXYData XYDataToPlot, XYDataPointerArray, XYDataPointerArrayCount, True
+ End If
+ Else
+ ' Plot the data as lines between points
+ ' Plot in order of XVal, thus, don't need to sort
+ PlotOptions.ShowDataPointLabels = False
+ End If
+
+ ' Check to see if Mouse Pointer should be changed to hourglass
+ CheckForLongOperation ThisForm, lngSecElapsedAtStart, PlotOptions
+
+ ' Label the axes and add ticks and gridlines
+ FormatAxes ThisForm, PlotOptions, PlotBottom, PlotRange(intDataSetIndex)
+
+ ' Position the lines and labels
+ LastLabelTwip = 0
+
+ lngLeftOffset = PlotOptions.PlotLeft + PlotOptions.PlotLeftLargeNumberOffset
+
+ For lngIndex = 1 To XYDataToPlotCount
+ With ThisForm
+ If lngIndex Mod 50 = 0 Then
+ ' Check to see if Mouse Pointer should be changed to hourglass
+ CheckForLongOperation ThisForm, lngSecElapsedAtStart, PlotOptions
+ End If
+
+ XYDataIndex = XYDataPointerArray(lngIndex)
+ lngLineIndex = lngIndex + intDynamicObjectOffset
+
+ .linData(lngLineIndex).Visible = True
+
+ If PlotOptions.PlotTypeCode = 0 Then
+ ' Plot the data as sticks to zero
+
+ .linData(lngLineIndex).x1 = lngLeftOffset + XYDataToPlot(XYDataIndex).XVal
+ .linData(lngLineIndex).x2 = .linData(lngLineIndex).x1
+ .linData(lngLineIndex).y1 = PlotBottom
+ .linData(lngLineIndex).y2 = PlotBottom - XYDataToPlot(XYDataIndex).YVal
+ If HighlightIndex = XYDataIndex Then
+ .linData(lngLineIndex).BorderColor = PlotOptions.HighlightColor
+ Else
+ .linData(lngLineIndex).BorderColor = lngDataSetLineColor
+ End If
+ Else
+ ' Plot the data as lines between points
+ If lngIndex < XYDataToPlotCount Then
+ .linData(lngLineIndex).x1 = lngLeftOffset + XYDataToPlot(XYDataIndex).XVal
+ .linData(lngLineIndex).x2 = lngLeftOffset + XYDataToPlot(XYDataIndex + 1).XVal
+ .linData(lngLineIndex).y1 = PlotBottom - XYDataToPlot(XYDataIndex).YVal
+ .linData(lngLineIndex).y2 = PlotBottom - XYDataToPlot(XYDataIndex + 1).YVal
+ .linData(lngLineIndex).BorderColor = lngDataSetLineColor
+ Else
+ .linData(lngLineIndex).Visible = False
+ End If
+ End If
+ End With
+
+ With ThisXYDataArray(intDataSetIndex)
+ If PlotOptions.ShowDataPointLabels Then
+
+ If XYDataIndex = HighlightIndex Or lngIndex <= PlotOptions.LabelsToShow Then
+ LastLabelTwip = ThisForm.lblPlotIntensity(lngLineIndex).Left
+ ThisForm.lblPlotIntensity(lngLineIndex).Visible = True
+ ThisForm.lblPlotIntensity(lngLineIndex).Tag = "Visible"
+ If XYDataIndex = HighlightIndex Then
+ ' Include charge in label
+ ThisForm.lblPlotIntensity(lngLineIndex).Caption = Format(.XYDataList(StartXValIndex + XYDataIndex - 1).XVal, "0.0000")
+ ThisForm.lblPlotIntensity(lngLineIndex).Width = 1200
+ Else
+ ThisForm.lblPlotIntensity(lngLineIndex).Caption = Format(.XYDataList(StartXValIndex + XYDataIndex - 1).XVal, "0.0000")
+ ThisForm.lblPlotIntensity(lngLineIndex).Width = 800
+ End If
+ ThisForm.lblPlotIntensity(lngLineIndex).ToolTipText = Format(.XYDataList(StartXValIndex + XYDataIndex - 1).XVal, "0.0000")
+ ThisForm.lblPlotIntensity(lngLineIndex).Height = 200
+ ThisForm.lblPlotIntensity(lngLineIndex).Top = ThisForm.linData(lngLineIndex).y2 - ThisForm.lblPlotIntensity(lngLineIndex).Height
+ ThisForm.lblPlotIntensity(lngLineIndex).Left = ThisForm.linData(lngLineIndex).x1 - 200
+ Else
+ ThisForm.lblPlotIntensity(lngLineIndex).Visible = True
+ ThisForm.lblPlotIntensity(lngLineIndex).Tag = "Hidden"
+ ThisForm.lblPlotIntensity(lngLineIndex).Caption = ""
+ ThisForm.lblPlotIntensity(lngLineIndex).ToolTipText = Format(.XYDataList(StartXValIndex + XYDataIndex - 1).XVal, "0.0000")
+ ThisForm.lblPlotIntensity(lngLineIndex).Width = 50
+ ThisForm.lblPlotIntensity(lngLineIndex).Height = Abs(ThisForm.linData(lngLineIndex).y1 - ThisForm.linData(lngLineIndex).y2)
+ ThisForm.lblPlotIntensity(lngLineIndex).Top = ThisForm.linData(lngLineIndex).y2
+ ThisForm.lblPlotIntensity(lngLineIndex).Left = ThisForm.linData(lngLineIndex).x2
+ End If
+ Else
+ ThisForm.lblPlotIntensity(lngLineIndex).Visible = False
+ End If
+ End With
+ Next lngIndex
+
+ intDynamicObjectOffset = intDynamicObjectOffset + XYDataToPlotCount
+
+ End If
+ Next intDataSetIndex
+
+ With ThisForm
+ If intDynamicObjectOffset < PlotOptions.LinesLoadedCount Then
+ If intDynamicObjectOffset < 1 Then lngIndex = 1
+
+ ' Hide the other lines and labels
+ For lngLineIndex = intDynamicObjectOffset To PlotOptions.LinesLoadedCount
+ ThisForm.linData(lngLineIndex).Visible = False
+ ThisForm.lblPlotIntensity(lngLineIndex).Visible = False
+ Next lngLineIndex
+ End If
+
+ End With
+
+ If PlotOptions.ShowDataPointLabels Then
+ TwipsBetweenLabels = "0.5" * DeltaXScaler * XValRange
+ RepositionDataLabels ThisForm, XYDataToPlotCount, TwipsBetweenLabels, LastLabelTwip
+ End If
+
+End Sub
+
+Private Sub FindMinimumAndMaximum(lngMinimumValIndex As Long, lngMaximumValIndex As Long, ThisXYData() As usrXYData, XYDataPointerArray() As Long, lngStartIndex As Long, lngStopIndex As Long)
+ Dim lngIndex As Long, XYDataPoint As Long
+ Dim dblMinimumVal As Double, dblMaximumVal As Double
+
+ If lngStopIndex > UBound(ThisXYData()) Then
+ lngStopIndex = UBound(ThisXYData())
+ End If
+
+ lngMinimumValIndex = lngStartIndex
+ lngMaximumValIndex = lngStartIndex
+
+ dblMaximumVal = ThisXYData(XYDataPointerArray(lngStartIndex)).YVal
+ dblMinimumVal = ThisXYData(XYDataPointerArray(lngStartIndex)).YVal
+
+ For lngIndex = lngStartIndex + 1 To lngStopIndex
+ XYDataPoint = ThisXYData(XYDataPointerArray(lngIndex)).YVal
+ If XYDataPoint < dblMinimumVal Then
+ dblMinimumVal = XYDataPoint
+ lngMinimumValIndex = lngIndex
+ End If
+ If XYDataPoint > dblMaximumVal Then
+ dblMaximumVal = XYDataPoint
+ lngMaximumValIndex = lngIndex
+ End If
+ Next lngIndex
+
+ If lngMinimumValIndex = lngMaximumValIndex Then
+ ' All of the data was the same
+ ' Set lngMaximumValIndex to the halfway-point index between lngStopIndex and lngStartIndex
+ lngMaximumValIndex = lngStartIndex + (lngStopIndex - lngStartIndex) / 2
+ End If
+End Sub
+
+Private Sub FormatAxes(ThisForm As Form, PlotOptions As usrPlotDataOptions, PlotBottom As Long, PlotRange As usrPlotRange)
+ Dim intInitialTickIndex As Integer, intInitialTickMinorIndex As Integer
+ Dim lngRightOrTopMostPos As Long
+
+ With ThisForm
+ ' Position the x axis
+ .linXAxis.x1 = PlotOptions.PlotLeft + PlotOptions.PlotLeftLargeNumberOffset
+ .linXAxis.x2 = PlotOptions.PlotLeft + PlotOptions.PlotWidth + 50
+ .linXAxis.y1 = PlotBottom + 50
+ .linXAxis.y2 = PlotBottom + 50
+ .linXAxis.Visible = PlotOptions.XAxis.Show
+
+ ' Position the y axis
+ .linYAxis.x1 = PlotOptions.PlotLeft + PlotOptions.PlotLeftLargeNumberOffset
+ .linYAxis.x2 = PlotOptions.PlotLeft + PlotOptions.PlotLeftLargeNumberOffset
+ .linYAxis.y1 = PlotBottom + 50
+ .linYAxis.y2 = PlotOptions.PlotTop - 50
+ .linYAxis.Visible = PlotOptions.YAxis.Show
+ End With
+
+ ' Note: The x and y axes share the same dynamic lines for major and minor tick marks,
+ ' gridlines, and labels. The x axis objects will start with index 1 of each object type
+ ' the intInitialTickIndex and intInitialTickMinorIndex values will be modified by sub
+ ' FormatThisAxis during the creation of the objects for the x axis so that they will
+ ' be the value of the next unused object for operations involving the y axis
+ intInitialTickIndex = 0
+ intInitialTickMinorIndex = 0
+ FormatThisAxis ThisForm, PlotOptions, True, PlotOptions.XAxis, PlotRange.x, intInitialTickIndex, intInitialTickMinorIndex, lngRightOrTopMostPos
+ If lngRightOrTopMostPos > ThisForm.linXAxis.x2 Then
+ ThisForm.linXAxis.x2 = lngRightOrTopMostPos + 50
+ End If
+
+ FormatThisAxis ThisForm, PlotOptions, False, PlotOptions.YAxis, PlotRange.y, intInitialTickIndex, intInitialTickMinorIndex, lngRightOrTopMostPos
+ If lngRightOrTopMostPos < ThisForm.linYAxis.y2 Then
+ ThisForm.linYAxis.y2 = lngRightOrTopMostPos - 50
+ End If
+
+End Sub
+
+Private Function FindDigitsInLabelUsingRange(PlotRangeForAxis As usrPlotRangeAxis, intMajorTicksToShow As Integer, ByRef strFormatString As String) As Integer
+ Dim ValRange As Double, DeltaVal As Double, lngExponentValue As Long
+ Dim intDigitsInStartNumber As Integer, intDigitsInEndNumber As Integer
+
+ With PlotRangeForAxis
+ ValRange = .ValEnd.Val - .ValStart.Val
+ End With
+
+ If intMajorTicksToShow = 0 Then
+ DeltaVal = ValRange
+ Else
+ ' Take ValRange divided by intMajorTicksToShow
+ DeltaVal = ValRange / intMajorTicksToShow
+ End If
+
+ ' Round DeltaVal to nearest 1, 2, or 5 (or multiple of 10 thereof)
+ DeltaVal = RoundToMultipleOf10(DeltaVal, lngExponentValue)
+
+ strFormatString = ConstructFormatString(DeltaVal)
+
+ ' Note: I use the absolute value of ValEnd so that all tick labels will have the
+ ' same width, positive or negative
+ intDigitsInStartNumber = Len(Trim(Format(Abs(PlotRangeForAxis.ValStart.Val), strFormatString))) + 1
+ intDigitsInEndNumber = Len(Trim(Format(Abs(PlotRangeForAxis.ValEnd.Val), strFormatString))) + 1
+
+ If intDigitsInEndNumber > intDigitsInStartNumber Then
+ FindDigitsInLabelUsingRange = intDigitsInEndNumber
+ Else
+ FindDigitsInLabelUsingRange = intDigitsInStartNumber
+ End If
+
+End Function
+
+Private Sub FormatThisAxis(ThisForm As Form, PlotOptions As usrPlotDataOptions, boolXAxis As Boolean, AxisOptions As usrAxisOptions, PlotRangeForAxis As usrPlotRangeAxis, ByRef intInitialTickIndex As Integer, ByRef intInitialTickMinorIndex As Integer, lngRightOrTopMostPos As Long)
+ Dim objTickMajor As Line
+
+ Dim intMajorTicksToShow As Integer
+ Dim intMinorTicksPerMajorTick As Integer, intMinorTicksRequired As Integer
+ Dim intTickIndex As Integer, intTickIndexToHide As Integer
+ Dim intKeepEveryXthTick As Integer
+ Dim intTickIndexMinor As Integer, intTickIndexMinorTrack As Integer
+ Dim lngAddnlMinorTickPos As Long, lngAddnlMinorTickStopPos As Long
+ Dim PosStart As Long, DeltaPos As Double, DeltaPosMinor As Double
+ Dim ValStart As Double, ValEnd As Double, ValRange As Double, DeltaVal As Double
+ Dim LengthStartPos As Long, LengthEndPos As Long, GridlineEndPos As Long
+ Dim LengthStartPosMinor As Long, LengthEndPosMinor As Long
+ Dim intDigitsInLabel As Integer
+
+ Dim strFormatString As String, intTickLabelWidth As Integer
+
+ ' Position and label the x axis major tick marks and labels
+ intMajorTicksToShow = AxisOptions.MajorTicksToShow
+ If intMajorTicksToShow < 2 Then
+ intMajorTicksToShow = 2
+ AxisOptions.MajorTicksToShow = intMajorTicksToShow
+ End If
+
+ With PlotRangeForAxis
+ ValStart = .ValStart.Val
+ ValEnd = .ValEnd.Val
+ ValRange = ValEnd - ValStart
+ End With
+
+ ' Take ValRange divided by intMajorTicksToShow
+ DeltaVal = ValRange / intMajorTicksToShow
+
+ ' Round DeltaVal to nearest 1, 2, or 5 (or multiple of 10 thereof)
+ DeltaVal = RoundToMultipleOf10(DeltaVal)
+
+ ' If ValStart is not an even multiple of DeltaVal then bump up ValStart until it is
+ ValStart = RoundToEvenMultiple(ValStart, DeltaVal, True)
+
+ ' Do the same for ValEnd, but bump down instead
+ ValEnd = RoundToEvenMultiple(ValEnd, DeltaVal, False)
+
+ ' Recompute ValRange
+ ValRange = ValEnd - ValStart
+
+ ' Determine actual number of ticks to show
+ intMajorTicksToShow = ValRange / DeltaVal + 1
+
+ ' Convert ValStart to ValPos
+ PosStart = XYValueToPos(ValStart, PlotRangeForAxis, False)
+
+ ' Convert DeltaVal to DeltaPos
+ DeltaPos = XYValueToPos(DeltaVal, PlotRangeForAxis, True)
+
+ If boolXAxis Then
+ LengthStartPos = ThisForm.linXAxis.y1 + 200
+ LengthEndPos = ThisForm.linXAxis.y1
+ Else
+ LengthStartPos = ThisForm.linYAxis.x1 - 200
+ LengthEndPos = ThisForm.linYAxis.x1
+ End If
+
+ With AxisOptions
+ If .ShowMinorTicks Then
+ ' Insert 1, 4, or 9 minor ticks, depending on whether they'll fit
+ intMinorTicksPerMajorTick = 0
+ Do
+ Select Case intMinorTicksPerMajorTick
+ Case 0: intMinorTicksPerMajorTick = 9
+ Case 9: intMinorTicksPerMajorTick = 4
+ Case 4: intMinorTicksPerMajorTick = 1
+ Case Else
+ intMinorTicksPerMajorTick = 0
+ Exit Do
+ End Select
+ DeltaPosMinor = DeltaPos / (intMinorTicksPerMajorTick + 1)
+ Loop While Abs(DeltaPosMinor) < .MinorTickMinimumPixelSep
+ Else
+ DeltaPosMinor = 0
+ End If
+
+ If boolXAxis Then
+ LengthStartPosMinor = LengthStartPos - 150
+ LengthEndPosMinor = LengthEndPos
+ Else
+ LengthStartPosMinor = LengthStartPos + 100
+ LengthEndPosMinor = LengthEndPos
+ End If
+
+ If .ShowGridLinesMajor Then
+ If boolXAxis Then
+ GridlineEndPos = PlotOptions.PlotTop
+ Else
+ GridlineEndPos = PlotOptions.PlotLeft + PlotOptions.PlotWidth
+ End If
+ Else
+ GridlineEndPos = LengthEndPos
+ End If
+ End With
+
+ ' Initialize PlotOptions.MajorTicksLoaded and PlotOptions.MinorTicksLoaded if needed
+ If PlotOptions.MajorTicksLoaded = 0 Then PlotOptions.MajorTicksLoaded = 1 ' There is always at least 1 loaded
+ If PlotOptions.MinorTicksLoaded = 0 Then PlotOptions.MinorTicksLoaded = 1 ' There is always at least 1 loaded
+
+ ' Call FindDigitsInLabelUsingRange to determine the digits in the label and construct the format string
+ intDigitsInLabel = FindDigitsInLabelUsingRange(PlotRangeForAxis, intMajorTicksToShow, strFormatString)
+
+ ' Each number requires 90 pixels
+ intTickLabelWidth = intDigitsInLabel * NUM_TWIPS_PER_DIGIT
+
+ intTickIndexMinorTrack = intInitialTickMinorIndex
+ For intTickIndex = intInitialTickIndex + 1 To intInitialTickIndex + intMajorTicksToShow
+
+ With AxisOptions
+ If PlotOptions.MajorTicksLoaded < intTickIndex Then
+ PlotOptions.MajorTicksLoaded = PlotOptions.MajorTicksLoaded + 1
+ Load ThisForm.linTickMajor(PlotOptions.MajorTicksLoaded)
+ Load ThisForm.lblTick(PlotOptions.MajorTicksLoaded)
+ Load ThisForm.linGridline(PlotOptions.MajorTicksLoaded)
+ End If
+ End With
+
+ With ThisForm.linTickMajor(intTickIndex)
+ .x1 = PosStart + CLng(((intTickIndex - intInitialTickIndex) - 1) * DeltaPos)
+ .x2 = .x1
+ .y1 = LengthStartPos
+ .y2 = LengthEndPos
+ .Visible = True
+ End With
+ Set objTickMajor = ThisForm.linTickMajor(intTickIndex)
+ With ThisForm.linGridline(intTickIndex)
+ .x1 = objTickMajor.x1
+ .x2 = objTickMajor.x2
+ .y1 = objTickMajor.y1
+ .y2 = GridlineEndPos
+ .Visible = True
+ End With
+
+ lngRightOrTopMostPos = LengthEndPos
+ If Not boolXAxis Then
+ SwapLineCoordinates ThisForm.linTickMajor(intTickIndex)
+ SwapLineCoordinates ThisForm.linGridline(intTickIndex)
+ Set objTickMajor = ThisForm.linTickMajor(intTickIndex)
+ End If
+
+ With ThisForm.lblTick(intTickIndex)
+ .Width = intTickLabelWidth
+ .Caption = Format(ValStart + CDbl((intTickIndex - intInitialTickIndex) - 1) * DeltaVal, strFormatString)
+ .Visible = True
+ If boolXAxis Then
+ .Top = objTickMajor.y1 + 50
+ .Left = objTickMajor.x1 - .Width / 2
+ Else
+ .Top = objTickMajor.y1 - .Height / 2
+ .Left = objTickMajor.x1 - .Width - 50
+ .Alignment = vbRightJustify
+ End If
+ End With
+
+ If ValStart + ((intTickIndex - intInitialTickIndex) - 1) * DeltaVal > PlotRangeForAxis.ValEnd.Val Then
+ ' Tick and/or label is past the end of the axis; Do not keep labeling
+ ' Before exitting for loop, must add 1 to intTickIndex since it will normally
+ ' exit the for loop with a value of intMajorTicksToShow + 1, but we are exiting prematurely
+ intTickIndex = intTickIndex + 1
+ Exit For
+ End If
+
+ With AxisOptions
+ ' Load minor ticks as needed
+ intMinorTicksRequired = intTickIndexMinorTrack + intMinorTicksPerMajorTick
+ Do While PlotOptions.MinorTicksLoaded < intMinorTicksRequired
+ PlotOptions.MinorTicksLoaded = PlotOptions.MinorTicksLoaded + 1
+ Load ThisForm.linTickMinor(PlotOptions.MinorTicksLoaded)
+ Loop
+ End With
+
+ For intTickIndexMinor = 1 To intMinorTicksPerMajorTick
+ intTickIndexMinorTrack = intTickIndexMinorTrack + 1
+ If boolXAxis Then
+ lngAddnlMinorTickPos = objTickMajor.x1 + DeltaPosMinor * intTickIndexMinor
+ Else
+ lngAddnlMinorTickPos = objTickMajor.y1 + DeltaPosMinor * intTickIndexMinor
+ End If
+
+ lngRightOrTopMostPos = lngAddnlMinorTickPos
+
+ ' Add the minor tick mark
+ AddMinorTickmark ThisForm, intTickIndexMinor, intTickIndexMinorTrack, lngAddnlMinorTickPos, LengthStartPosMinor, LengthEndPosMinor, boolXAxis
+ Next intTickIndexMinor
+ Next intTickIndex
+
+ ' See if minor ticks can be added before the first major tick
+ If AxisOptions.ShowMinorTicks Then
+ If boolXAxis Then
+ lngAddnlMinorTickPos = ThisForm.linTickMajor(1).x1
+ lngAddnlMinorTickStopPos = ThisForm.linXAxis.x1
+ Else
+ lngAddnlMinorTickPos = ThisForm.linTickMajor(intInitialTickIndex + 1).y1
+ lngAddnlMinorTickStopPos = ThisForm.linYAxis.y1
+ End If
+
+ intTickIndexMinor = 1
+ ' This loop will execute at most 50 times
+ ' Most likely, it will only execute a few times before the Exit Do clause becomes true
+ Do While intTickIndexMinor < 50
+ If boolXAxis Then
+ If lngAddnlMinorTickPos - Abs(DeltaPosMinor) <= lngAddnlMinorTickStopPos Then Exit Do
+ lngAddnlMinorTickPos = lngAddnlMinorTickPos - Abs(DeltaPosMinor)
+ Else
+ If lngAddnlMinorTickPos + Abs(DeltaPosMinor) >= lngAddnlMinorTickStopPos Then Exit Do
+ lngAddnlMinorTickPos = lngAddnlMinorTickPos + Abs(DeltaPosMinor)
+ End If
+
+ intTickIndexMinor = intTickIndexMinor + 1
+ intTickIndexMinorTrack = intTickIndexMinorTrack + 1
+
+ ' May need to load more minor ticks
+ If PlotOptions.MinorTicksLoaded < intTickIndexMinorTrack Then
+ PlotOptions.MinorTicksLoaded = PlotOptions.MinorTicksLoaded + 1
+ Load ThisForm.linTickMinor(PlotOptions.MinorTicksLoaded)
+ End If
+
+ ' Add the minor tick mark
+ AddMinorTickmark ThisForm, intTickIndexMinor, intTickIndexMinorTrack, lngAddnlMinorTickPos, LengthStartPosMinor, LengthEndPosMinor, boolXAxis
+ Loop
+ End If
+
+ With ThisForm
+ ' Check for overlapping tick labels
+ ' If there is overlap, then show every other or every 5th label
+ intKeepEveryXthTick = 1
+ If intMajorTicksToShow >= 3 Then
+ If boolXAxis Then
+ If .lblTick(1).Left + .lblTick(1).Width > .lblTick(3).Left Then intKeepEveryXthTick = 5
+ Else
+ If .lblTick(intInitialTickIndex + 3).Top + .lblTick(intInitialTickIndex + 3).Height > .lblTick(intInitialTickIndex + 1).Top Then intKeepEveryXthTick = 5
+ End If
+ End If
+
+ If intKeepEveryXthTick = 1 And intMajorTicksToShow >= 2 Then
+ If boolXAxis Then
+ If .lblTick(1).Left + .lblTick(1).Width > .lblTick(2).Left Then intKeepEveryXthTick = 2
+ Else
+ If .lblTick(intInitialTickIndex + 2).Top + .lblTick(intInitialTickIndex + 2).Height > .lblTick(intInitialTickIndex + 1).Top Then intKeepEveryXthTick = 2
+ End If
+ End If
+
+ If intKeepEveryXthTick > 1 Then
+ For intTickIndexToHide = intInitialTickIndex + 1 To intInitialTickIndex + intMajorTicksToShow
+ If intTickIndexToHide Mod intKeepEveryXthTick <> 0 Then
+ .lblTick(intTickIndexToHide).Visible = False
+ End If
+ Next intTickIndexToHide
+ End If
+ End With
+
+ ' Store intTickIndex in intInitialTickIndex
+ intInitialTickIndex = intTickIndex - 1
+
+ ' Store intTickIndexMinorTrack in intInitialTickMinorIndex
+ intInitialTickMinorIndex = intTickIndexMinorTrack
+
+
+ With ThisForm
+ ' Hide remaining loaded ticks
+ For intTickIndexToHide = intInitialTickIndex + 1 To PlotOptions.MajorTicksLoaded
+ .linTickMajor(intTickIndexToHide).Visible = False
+ .linGridline(intTickIndexToHide).Visible = False
+ .lblTick(intTickIndexToHide).Visible = False
+ Next intTickIndexToHide
+
+ For intTickIndexToHide = intInitialTickMinorIndex + 1 To PlotOptions.MinorTicksLoaded
+ .linTickMinor(intTickIndexToHide).Visible = False
+ Next intTickIndexToHide
+ End With
+
+End Sub
+
+Private Sub AddMinorTickmark(ThisForm As Form, intTickIndexMinor As Integer, intTickIndexMinorTrack As Integer, lngAddnlMinorTickPos As Long, LengthStartPosMinor As Long, LengthEndPosMinor As Long, boolXAxis As Boolean)
+ With ThisForm.linTickMinor(intTickIndexMinorTrack)
+ .x1 = lngAddnlMinorTickPos
+ .x2 = .x1
+ .y1 = LengthStartPosMinor + 20
+ .y2 = LengthEndPosMinor
+ If intTickIndexMinor Mod 5 = 0 Then
+ ' Draw the minor tick mark a little longer
+ If boolXAxis Then
+ .y1 = .y1 + 70
+ .y2 = .y2
+ Else
+ .y1 = .y1 - 50
+ .y2 = .y2
+ End If
+ End If
+ .Visible = True
+ End With
+
+ If Not boolXAxis Then SwapLineCoordinates ThisForm.linTickMinor(intTickIndexMinorTrack)
+
+End Sub
+
+Private Sub LoadDynamicPlotObjects(ThisForm As Form, PlotOptions As usrPlotDataOptions, XYDataToPlotCount As Long)
+ Dim lngLinesLoadedCountPrevious As Long
+ Dim boolShowProgress As Boolean
+
+ With ThisForm
+ ' Load lines for data points if needed
+ If PlotOptions.LinesLoadedCount < XYDataToPlotCount Then
+ lngLinesLoadedCountPrevious = PlotOptions.LinesLoadedCount
+ If Abs(XYDataToPlotCount - lngLinesLoadedCountPrevious) > 100 Then
+ boolShowProgress = True
+ frmProgress.InitializeForm "Preparing graph", 0, Abs(XYDataToPlotCount - lngLinesLoadedCountPrevious)
+ End If
+
+ Do While PlotOptions.LinesLoadedCount < XYDataToPlotCount
+ If boolShowProgress Then
+ If PlotOptions.LinesLoadedCount Mod 10 = 0 Then frmProgress.UpdateProgressBar Abs(PlotOptions.LinesLoadedCount - lngLinesLoadedCountPrevious)
+ End If
+
+ PlotOptions.LinesLoadedCount = PlotOptions.LinesLoadedCount + 1
+ Load .linData(PlotOptions.LinesLoadedCount)
+ Load .lblPlotIntensity(PlotOptions.LinesLoadedCount)
+ .lblPlotIntensity(PlotOptions.LinesLoadedCount).Height = 200
+ Loop
+ If boolShowProgress Then frmProgress.Hide
+ End If
+ End With
+
+End Sub
+
+Private Sub RepositionDataLabels(ThisForm As Form, XYDataToPlotCount As Long, TwipsBetweenLabels As Long, LastLabelTwip As Long)
+ Dim LabelLocPointerArray() As Long, LabelLocPointerArrayCount As Long
+ Dim LabelShiftedCount As Integer, LabelShifted As Boolean
+
+ Dim lngIndex As Integer
+
+ With ThisForm
+ ' Reposition the labels
+ ReDim LabelLocPointerArray(XYDataToPlotCount)
+ LabelLocPointerArrayCount = 0
+ For lngIndex = 1 To XYDataToPlotCount
+ If .lblPlotIntensity(lngIndex).Tag = "Visible" Then
+ LabelLocPointerArrayCount = LabelLocPointerArrayCount + 1
+ LabelLocPointerArray(LabelLocPointerArrayCount) = lngIndex
+ End If
+ Next lngIndex
+
+ LabelShiftedCount = 0
+ Do
+ LabelShiftedCount = LabelShiftedCount + 1
+ LabelShifted = False
+ ' sort the Pointer Array
+ SortLabelLoc ThisForm, LabelLocPointerArray(), LabelLocPointerArrayCount
+
+ ' Step through labels from the one at the bottom to the one at the top and shift upward if needed
+ For lngIndex = 1 To LabelLocPointerArrayCount - 1
+ If .lblPlotIntensity(LabelLocPointerArray(lngIndex + 1)).Top + .lblPlotIntensity(LabelLocPointerArray(lngIndex + 1)).Height > .lblPlotIntensity(lngIndex).Top And .lblPlotIntensity(lngIndex + 1).Top < .lblPlotIntensity(LabelLocPointerArray(lngIndex)).Top Then
+ ' May Need to shift upward; see if adjacent
+ If Abs(LabelLocPointerArray(lngIndex + 1) - LabelLocPointerArray(lngIndex)) = 1 Then
+ ' Yes, they're adjacent; shift upward
+ .lblPlotIntensity(LabelLocPointerArray(lngIndex + 1)).Top = .lblPlotIntensity(LabelLocPointerArray(lngIndex)).Top - .lblPlotIntensity(LabelLocPointerArray(lngIndex + 1)).Height
+ LabelShifted = True
+ End If
+ End If
+ Next lngIndex
+ Loop While LabelShifted And LabelShiftedCount < 5
+ End With
+
+End Sub
+
+Private Function RoundToEvenMultiple(ByVal dblValueToRound As Double, ByVal MultipleValue As Double, ByVal boolRoundUp As Boolean) As Double
+ Dim intLoopCount As Integer
+ Dim strWork As String, dblWork As Double
+ Dim lngExponentValue As Long
+
+ ' Find the exponent of MultipleValue
+ strWork = Format(MultipleValue, "0E+000")
+ lngExponentValue = CIntSafe(Right(strWork, 4))
+
+ intLoopCount = 0
+ Do While Trim(Str(dblValueToRound / MultipleValue)) <> Trim(Str(Round(dblValueToRound / MultipleValue, 0)))
+ dblWork = dblValueToRound / 10 ^ (lngExponentValue)
+ dblWork = CLng(dblWork)
+ dblWork = dblWork * 10 ^ (lngExponentValue)
+ If boolRoundUp Then
+ If dblWork <= dblValueToRound Then
+ dblWork = dblWork + 10 ^ lngExponentValue
+ End If
+ Else
+ If dblWork >= dblValueToRound Then
+ dblWork = dblWork - 10 ^ lngExponentValue
+ End If
+ End If
+ dblValueToRound = dblWork
+ intLoopCount = intLoopCount + 1
+ If intLoopCount > 500 Then
+ ' Bug
+' Debug.Assert False
+ Exit Do
+ End If
+ Loop
+
+ RoundToEvenMultiple = dblValueToRound
+End Function
+
+Public Function RoundToMultipleOf10(ByVal dblThisNum As Double, Optional ByRef lngExponentValue As Long) As Double
+ Dim strWork As String, dblWork As Double
+
+ ' Round to nearest 1, 2, or 5 (or multiple of 10 thereof)
+ ' First, find the exponent of dblThisNum
+ strWork = Format(dblThisNum, "0E+000")
+ lngExponentValue = CIntSafe(Right(strWork, 4))
+ dblWork = dblThisNum / 10 ^ lngExponentValue
+ dblWork = CIntSafeDbl(dblWork)
+
+ ' dblWork should now be between 0 and 9
+ Select Case dblWork
+ Case 0, 1: dblThisNum = 1
+ Case 2 To 4: dblThisNum = 2
+ Case Else: dblThisNum = 5
+ End Select
+
+ ' Convert dblThisNum back to the correct magnitude
+ dblThisNum = dblThisNum * 10 ^ lngExponentValue
+
+ RoundToMultipleOf10 = dblThisNum
+End Function
+
+Private Sub ScaleData(PlotOptions As usrPlotDataOptions, XYDataToPlot() As usrXYData, XYDataToPlotCount As Long, ByRef ThisAxisRange As usrPlotRangeAxis, ThisAxisScaling As usrPlotRangeAxis, boolIsXAxis As Boolean, boolAutoScaleAxis As Boolean)
+
+ Dim dblMinimumIntensity As Double
+ Dim lngIndex As Long, dblDataPoint As Double
+ Dim dblValRange As Double, dblDeltaScaler As Double, ThisAxisWindowLength As Long
+ Dim strFormatString As String, intDigitsInLabel As Integer
+
+ ' First step through valid data and find the minimum YVal value
+ ' Necessary to check if negative
+ dblMinimumIntensity = HighestValueForDoubleDataType
+ For lngIndex = 1 To XYDataToPlotCount
+ If boolIsXAxis Then
+ dblDataPoint = XYDataToPlot(lngIndex).XVal
+ Else
+ dblDataPoint = XYDataToPlot(lngIndex).YVal
+ End If
+ If dblDataPoint < dblMinimumIntensity Then
+ dblMinimumIntensity = dblDataPoint
+ End If
+ Next lngIndex
+
+ ' Reset .ValNegativeValueCorrectionOffset
+ ThisAxisRange.ValNegativeValueCorrectionOffset = 0
+
+ If boolAutoScaleAxis Then
+ If dblMinimumIntensity < 0 Then
+ ' Need to correct all y data by making it positive
+ ThisAxisRange.ValNegativeValueCorrectionOffset = Abs(dblMinimumIntensity)
+ End If
+ Else
+ ' The user has supplied ValStart and ValEnd values
+ ' Make sure .ValStart.Val < .ValEnd.Val
+ ' No need to use a NegativeValueCorrectionOffset since I perform bounds checking during the conversion from val to pos
+ If ThisAxisScaling.ValStart.Val > ThisAxisScaling.ValEnd.Val Then
+ SwapValues ThisAxisScaling.ValStart.Val, ThisAxisScaling.ValEnd.Val
+ End If
+ End If
+
+ If ThisAxisRange.ValNegativeValueCorrectionOffset > 0 Then
+ For lngIndex = 1 To XYDataToPlotCount
+ If boolIsXAxis Then
+ XYDataToPlot(lngIndex).XVal = XYDataToPlot(lngIndex).XVal + ThisAxisRange.ValNegativeValueCorrectionOffset
+ Else
+ XYDataToPlot(lngIndex).YVal = XYDataToPlot(lngIndex).YVal + ThisAxisRange.ValNegativeValueCorrectionOffset
+ End If
+ Next lngIndex
+ End If
+
+ ' Record the current plot range for future reference when zooming
+ ThisAxisRange.ValStart.Val = ThisAxisScaling.ValStart.Val - ThisAxisRange.ValNegativeValueCorrectionOffset
+ ThisAxisRange.ValEnd.Val = ThisAxisScaling.ValEnd.Val - ThisAxisRange.ValNegativeValueCorrectionOffset
+
+ dblValRange = ThisAxisScaling.ValEnd.Val - ThisAxisScaling.ValStart.Val
+ If dblValRange = 0 Then dblValRange = 1
+
+ ' Scale the data according to PlotOptions.height
+
+ If boolIsXAxis Then
+ ThisAxisWindowLength = PlotOptions.PlotWidth
+ Else
+ ThisAxisWindowLength = PlotOptions.PlotHeight
+ End If
+
+ dblDeltaScaler = CDbl(ThisAxisWindowLength) / CDbl(dblValRange)
+
+ For lngIndex = 1 To XYDataToPlotCount
+ If boolIsXAxis Then
+ dblDataPoint = XYDataToPlot(lngIndex).XVal
+ Else
+ dblDataPoint = XYDataToPlot(lngIndex).YVal
+ End If
+
+ dblDataPoint = CLng((dblDataPoint - ThisAxisScaling.ValStart.Val) * dblDeltaScaler)
+ If dblDataPoint > ThisAxisWindowLength Then
+ dblDataPoint = ThisAxisWindowLength
+ Else
+ If dblDataPoint < 0 Then
+ dblDataPoint = 0
+ End If
+ End If
+
+ If boolIsXAxis Then
+ XYDataToPlot(lngIndex).XVal = dblDataPoint
+ Else
+ XYDataToPlot(lngIndex).YVal = dblDataPoint
+ End If
+
+ Next lngIndex
+
+ If Not boolIsXAxis Then
+ ' Need to recompute .PlotLeftLargeNumberOffset
+ ' Call FindDigitsInLabelUsingRange to determine the digits in the label and construct the format string
+ intDigitsInLabel = FindDigitsInLabelUsingRange(ThisAxisRange, PlotOptions.YAxis.MajorTicksToShow, strFormatString)
+
+ ' Store in .PlotLeftLargeNumberOffset
+ PlotOptions.PlotLeftLargeNumberOffset = intDigitsInLabel * NUM_TWIPS_PER_DIGIT
+ End If
+
+ ' Record the current plot range for future reference when zooming
+ If boolIsXAxis Then
+ ThisAxisRange.ValStart.Pos = PlotOptions.PlotLeft + PlotOptions.PlotLeftLargeNumberOffset
+ ThisAxisRange.ValEnd.Pos = PlotOptions.PlotLeft + PlotOptions.PlotLeftLargeNumberOffset + PlotOptions.PlotWidth
+ Else
+ ThisAxisRange.ValStart.Pos = PlotOptions.PlotTop + PlotOptions.PlotHeight
+ ThisAxisRange.ValEnd.Pos = PlotOptions.PlotTop ' equivalent to: PlotBottom - CLng((dblValRange - ThisAxisScaling.ValStart) * dblDeltaScaler)
+ End If
+
+End Sub
+
+Private Sub SortLabelLoc(ThisForm As Form, LabelLocPointerArray() As Long, LabelLocPointerArrayCount As Long)
+
+ ' Sorts a list of labels based on their location vertically on a form
+ Dim low%, high%, IndexTemp As Long
+
+ low% = 1
+ high% = LabelLocPointerArrayCount
+
+ ' Sort the list via a shell sort
+ Dim MaxRow As Integer, offset As Integer, limit As Integer, switch As Integer
+ Dim row As Integer
+
+ ' Set comparison offset to half the number of records
+ MaxRow = high
+ offset = MaxRow \ 2
+
+ Do While offset > 0 ' Loop until offset gets to zero.
+
+ limit = MaxRow - offset
+ Do
+ switch = 0 ' Assume no switches at this offset.
+
+ ' Compare elements and switch ones out of order:
+ For row = low To limit
+ If ThisForm.lblPlotIntensity(LabelLocPointerArray(row)).Top < ThisForm.lblPlotIntensity(LabelLocPointerArray(row + offset)).Top Then
+ IndexTemp = LabelLocPointerArray(row + offset)
+ LabelLocPointerArray(row + offset) = LabelLocPointerArray(row)
+ LabelLocPointerArray(row) = IndexTemp
+ switch = row
+ End If
+ Next row
+
+ ' Sort on next pass only to where last switch was made:
+ limit = switch - offset
+ Loop While switch
+
+ ' No switches at last offset, try one half as big:
+ offset = offset \ 2
+
+ Loop
+
+End Sub
+
+Private Sub SortXYData(XYData() As usrXYData, XYDataPointerArray() As Long, XYDataPointerCount As Long, boolSortByIntensity As Boolean)
+
+ ' Sorts a list of data by x value or by YVal (y values), depending on boolSortByIntensity
+
+ ' Rather than sorting the data itself, sorts a pointer array to the data
+ Dim lngLow As Long, lngHigh As Long, IndexTemp As Long, boolSwapThem As Boolean
+
+ lngLow = 1
+ lngHigh = XYDataPointerCount
+
+ ' Sort the list via a shell sort
+ Dim lngRowMax As Long, lngOffSet As Long, lngLimit As Long, lngSwitch As Long
+ Dim lngRow As Long
+
+ ' Set comparison lngOffSet to half the number of records
+ lngRowMax = lngHigh
+ lngOffSet = lngRowMax \ 2
+
+ Do While lngOffSet > 0 ' Loop until lngOffSet gets to zero.
+
+ lngLimit = lngRowMax - lngOffSet
+ Do
+ lngSwitch = 0 ' Assume no switches at this lngOffSet.
+
+ ' Compare elements and lngSwitch ones out of order:
+ For lngRow = lngLow To lngLimit
+ If boolSortByIntensity Then
+ boolSwapThem = (XYData(XYDataPointerArray(lngRow)).YVal < XYData(XYDataPointerArray(lngRow + lngOffSet)).YVal)
+ Else
+ boolSwapThem = (XYData(XYDataPointerArray(lngRow)).XVal > XYData(XYDataPointerArray(lngRow + lngOffSet)).XVal)
+ End If
+
+ If boolSwapThem Then
+ IndexTemp = XYDataPointerArray(lngRow + lngOffSet)
+ XYDataPointerArray(lngRow + lngOffSet) = XYDataPointerArray(lngRow)
+ XYDataPointerArray(lngRow) = IndexTemp
+ lngSwitch = lngRow
+ End If
+ Next lngRow
+
+ ' Sort on next pass only to where last lngSwitch was made:
+ lngLimit = lngSwitch - lngOffSet
+ Loop While lngSwitch
+
+ ' No switches at last lngOffSet, try one half as big:
+ lngOffSet = lngOffSet \ 2
+
+ Loop
+
+End Sub
+
+Private Sub SwapLineCoordinates(ThisLine As Line)
+ Dim lngTemp As Long
+
+ With ThisLine
+ ' Setting y axis values
+ ' Must swap x1 and y1, and x2 and y2
+ lngTemp = .x1
+ .x1 = .y1
+ .y1 = lngTemp
+
+ lngTemp = .x2
+ .x2 = .y2
+ .y2 = lngTemp
+
+ End With
+End Sub
+Public Function XYPosToValue(ThisPos As Long, ThisRange As usrPlotRangeAxis)
+ Dim PosRange As Long, ValRange As Double
+ Dim ScaledPos As Double
+
+ With ThisRange
+ ' Convert the x pos in ZoomBoxCoords to the actual x value
+ PosRange = .ValEnd.Pos - .ValStart.Pos
+ ValRange = .ValEnd.Val - .ValStart.Val
+
+ If PosRange <> 0 Then
+ ' ScaledPos is a value between 0 and 1 indicating the percentage between RangeEnd and RangeStart that ThisPos is
+ ScaledPos = (ThisPos - .ValStart.Pos) / PosRange
+
+ ' Now Convert to the displayed value
+ XYPosToValue = ScaledPos * ValRange + .ValStart.Val
+ Else
+ XYPosToValue = .ValStart.Val
+ End If
+ End With
+
+End Function
+
+Public Function XYValueToPos(ThisValue As Double, ThisRange As usrPlotRangeAxis, IsDeltaValue As Boolean)
+ Dim PosRange As Long, ValRange As Double
+ Dim ScaledPos As Double
+
+
+ With ThisRange
+ ' Convert the x pos in ZoomBoxCoords to the actual x value
+ PosRange = .ValEnd.Pos - .ValStart.Pos
+ ValRange = .ValEnd.Val - .ValStart.Val
+
+ If ValRange <> 0 Then
+ If IsDeltaValue Then
+ ScaledPos = ThisValue / ValRange
+
+ ' Now Convert to correct position
+ XYValueToPos = ScaledPos * PosRange
+ Else
+ ' ScaledPos is a value between 0 and 1 indicating the percentage between RangeEnd and RangeStart that ThisPos is
+ ScaledPos = (ThisValue - .ValStart.Val) / ValRange
+
+ ' Now Convert to correct position
+ XYValueToPos = ScaledPos * PosRange + .ValStart.Pos
+ End If
+ Else
+ XYValueToPos = ThisRange.ValStart.Pos
+ End If
+ End With
+
+End Function
+
+
diff --git a/MsPlot/MsPlot.frm b/MsPlot/MsPlot.frm
new file mode 100644
index 0000000..24a7c90
--- /dev/null
+++ b/MsPlot/MsPlot.frm
@@ -0,0 +1,1834 @@
+VERSION 5.00
+Object = "{F9043C88-F6F2-101A-A3C9-08002B2F49FB}#1.2#0"; "COMDLG32.OCX"
+Begin VB.Form frmMsPlot
+ Caption = "Plot"
+ ClientHeight = 5460
+ ClientLeft = 165
+ ClientTop = 735
+ ClientWidth = 7665
+ KeyPreview = -1 'True
+ LinkTopic = "Form1"
+ ScaleHeight = 5460
+ ScaleWidth = 7665
+ StartUpPosition = 3 'Windows Default
+ Begin MSComDlg.CommonDialog CommonDialog1
+ Left = 5400
+ Top = 720
+ _ExtentX = 847
+ _ExtentY = 847
+ _Version = 393216
+ End
+ Begin VB.Frame fraPlot
+ BorderStyle = 0 'None
+ Height = 2985
+ Left = 0
+ TabIndex = 0
+ Top = 120
+ Width = 4785
+ Begin VB.Timer tmrUpdatePlot
+ Interval = 100
+ Left = 4320
+ Top = 0
+ End
+ Begin VB.Frame fraOptions
+ Caption = "Options (hidden)"
+ Height = 1275
+ Left = 1560
+ TabIndex = 4
+ Top = 1320
+ Visible = 0 'False
+ Width = 2175
+ Begin VB.TextBox txtXAxisTickCount
+ Height = 285
+ Left = 1440
+ TabIndex = 7
+ Text = "5"
+ Top = 120
+ Width = 615
+ End
+ Begin VB.TextBox txtYAxisTickCount
+ Height = 285
+ Left = 1440
+ TabIndex = 6
+ Text = "5"
+ Top = 480
+ Width = 615
+ End
+ Begin VB.ComboBox cboLabelsToShow
+ Height = 315
+ Left = 1440
+ Style = 2 'Dropdown List
+ TabIndex = 5
+ Top = 840
+ Width = 615
+ End
+ Begin VB.Label lblXAxisTickCount
+ Caption = "# of x axis ticks"
+ Height = 255
+ Left = 120
+ TabIndex = 10
+ Top = 240
+ Width = 1215
+ End
+ Begin VB.Label lblYAxisTickCount
+ Caption = "# of y axis ticks"
+ Height = 255
+ Left = 120
+ TabIndex = 9
+ Top = 480
+ Width = 1215
+ End
+ Begin VB.Label lblLabelsToShow
+ Caption = "# of ions to label:"
+ Height = 255
+ Left = 120
+ TabIndex = 8
+ Top = 840
+ Width = 1215
+ End
+ End
+ Begin VB.Line linData
+ Index = 1
+ Visible = 0 'False
+ X1 = 2160
+ X2 = 2160
+ Y1 = 600
+ Y2 = 1080
+ End
+ Begin VB.Line linTickMajor
+ DrawMode = 9 'Not Mask Pen
+ Index = 1
+ Visible = 0 'False
+ X1 = 840
+ X2 = 840
+ Y1 = 240
+ Y2 = 720
+ End
+ Begin VB.Line linXAxis
+ Visible = 0 'False
+ X1 = 1320
+ X2 = 600
+ Y1 = 720
+ Y2 = 720
+ End
+ Begin VB.Line linYAxis
+ Visible = 0 'False
+ X1 = 600
+ X2 = 600
+ Y1 = 720
+ Y2 = 120
+ End
+ Begin VB.Label lblCurrentPos
+ Caption = "Loc: 0,0"
+ Height = 195
+ Left = 1680
+ TabIndex = 3
+ Top = 0
+ Width = 2115
+ End
+ Begin VB.Label lblTick
+ BackStyle = 0 'Transparent
+ Caption = "123.45"
+ Height = 200
+ Index = 1
+ Left = 720
+ TabIndex = 2
+ Top = 840
+ Visible = 0 'False
+ Width = 500
+ End
+ Begin VB.Line linTickMinor
+ DrawMode = 9 'Not Mask Pen
+ Index = 1
+ Visible = 0 'False
+ X1 = 960
+ X2 = 960
+ Y1 = 480
+ Y2 = 720
+ End
+ Begin VB.Shape shpZoomBox
+ BorderColor = &H000000FF&
+ BorderStyle = 4 'Dash-Dot
+ Height = 855
+ Left = 240
+ Top = 1440
+ Width = 855
+ End
+ Begin VB.Label lblPlotIntensity
+ BackStyle = 0 'Transparent
+ Caption = "123.43"
+ Height = 195
+ Index = 1
+ Left = 2160
+ TabIndex = 1
+ Top = 360
+ Visible = 0 'False
+ Width = 615
+ End
+ Begin VB.Line linGridline
+ BorderColor = &H00FF0000&
+ BorderStyle = 3 'Dot
+ DrawMode = 9 'Not Mask Pen
+ Index = 1
+ Visible = 0 'False
+ X1 = 720
+ X2 = 720
+ Y1 = 240
+ Y2 = 720
+ End
+ End
+ Begin VB.Menu mnuFile
+ Caption = "&File"
+ Begin VB.Menu mnuContinousData
+ Caption = "Continuous Data"
+ End
+ Begin VB.Menu mnuStickDataSome
+ Caption = "Stick Data (some)"
+ End
+ Begin VB.Menu mnuStickDataLots
+ Caption = "Stick Data (Lots)"
+ End
+ Begin VB.Menu mnuExportData
+ Caption = "&Export Data..."
+ End
+ Begin VB.Menu mnuFileSepBar1
+ Caption = "-"
+ End
+ Begin VB.Menu mnuClose
+ Caption = "&Close"
+ End
+ End
+ Begin VB.Menu mnuOptions
+ Caption = "&Options"
+ Begin VB.Menu mnuPlotType
+ Caption = "&Plot Type"
+ Begin VB.Menu mnuPlotTypeSticksToZero
+ Caption = "&Sticks to Zero"
+ End
+ Begin VB.Menu mnuPlotTypeLinesBetweenPoints
+ Caption = "&Lines Between Points"
+ Checked = -1 'True
+ End
+ End
+ Begin VB.Menu mnuSetResolution
+ Caption = "Set Effective &Resolution..."
+ End
+ Begin VB.Menu mnuOptionsSepBar6
+ Caption = "-"
+ End
+ Begin VB.Menu mnuGridLinesXAxis
+ Caption = "X Axis Gridlines"
+ Shortcut = ^X
+ End
+ Begin VB.Menu mnuGridLinesYAxis
+ Caption = "Y Axis Gridlines"
+ Shortcut = ^Y
+ End
+ Begin VB.Menu mnuTicks
+ Caption = "&Ticks to show (approx.)"
+ Begin VB.Menu mnuTicksXAxis
+ Caption = "&X Axis..."
+ End
+ Begin VB.Menu mnuTicksYAxis
+ Caption = "&Y Axis..."
+ End
+ End
+ Begin VB.Menu mnuPeaksToLabel
+ Caption = "Peaks To &Label..."
+ Enabled = 0 'False
+ End
+ Begin VB.Menu mnuOptionsSepBar4
+ Caption = "-"
+ End
+ Begin VB.Menu mnuSetRangeX
+ Caption = "Set &X Range..."
+ End
+ Begin VB.Menu mnuSetRangeY
+ Caption = "Set &Y Range..."
+ End
+ Begin VB.Menu mnuAutoScaleYAxis
+ Caption = "&Autoscale Y Axis"
+ Shortcut = ^F
+ End
+ Begin VB.Menu mnuFixMinimumYAtZero
+ Caption = "&Fix mimimum Y at zero"
+ End
+ Begin VB.Menu mnuOptionsSepBar5
+ Caption = "-"
+ End
+ Begin VB.Menu mnuZoomOutToPrevious
+ Caption = "&Zoom Out to Previous"
+ End
+ Begin VB.Menu mnuZoomOutFullScale
+ Caption = "Zoom Out to Show All"
+ Shortcut = ^A
+ End
+ Begin VB.Menu mnuOptionsSepBar1
+ Caption = "-"
+ End
+ Begin VB.Menu mnuCursorMode
+ Caption = "&Cursor Mode"
+ Begin VB.Menu mnuCursorModeZoom
+ Caption = "&Zoom"
+ Checked = -1 'True
+ End
+ Begin VB.Menu mnuCursorModeMove
+ Caption = "&Move"
+ End
+ End
+ Begin VB.Menu mnuShowCurrentPosition
+ Caption = "&Show Current Position"
+ Checked = -1 'True
+ End
+ End
+ Begin VB.Menu mnuZoomOptions
+ Caption = "&Zoom Box"
+ Begin VB.Menu mnuZoomIn
+ Caption = "Zoom &In"
+ End
+ Begin VB.Menu mnuZoomInHorizontal
+ Caption = "Zoom In Horizontal"
+ End
+ Begin VB.Menu mnuZoomInVertical
+ Caption = "Zoom In Vertical"
+ End
+ Begin VB.Menu mnuZoomSepBar2
+ Caption = "-"
+ End
+ Begin VB.Menu mnuZoomOut
+ Caption = "Zoom &Out"
+ End
+ Begin VB.Menu mnuZoomOutHorizontal
+ Caption = "Zoom Out Horizontal"
+ End
+ Begin VB.Menu mnuZoomOutVertical
+ Caption = "Zoom Out Vertical"
+ End
+ End
+End
+Attribute VB_Name = "frmMsPlot"
+Attribute VB_GlobalNameSpace = False
+Attribute VB_Creatable = False
+Attribute VB_PredeclaredId = True
+Attribute VB_Exposed = False
+Option Explicit
+
+Private Type usrRect
+ x1 As Long
+ y1 As Long
+ x2 As Long
+ y2 As Long
+End Type
+
+Private Type usrScalingRangeValues
+ PlotRangeStretchVal As Double
+ StartVal As Double
+ EndVal As Double
+ LowerLimit As Double
+ UpperLimit As Double
+End Type
+
+Private ZoomBoxCoords As usrRect
+Private PlotOptions As usrPlotDataOptions
+
+Private boolSlidingGraph As Boolean, PlotRangeAtMoveStart As usrPlotRange
+Private boolResizingWindow As Boolean, boolDrawingZoomBox As Boolean, boolZoomBoxDrawn As Boolean
+
+Private intDataSetsLoaded As Integer ' Count of the number of data sets loaded (originally 0); 1 if 1 data set (index 0 of LoadedXYData), 2 if 2 data sets, etc.
+Private LoadedXYData(MAX_DATA_SETS) As usrXYDataSet ' The data to plot; 0-based array, using indices 0 and 1 since MAX_DATA_SETS = 1
+Private InitialStickData(MAX_DATA_SETS) As usrXYDataSet ' 0-based array: If the user submits Stick Data (discrete data points) and requests that the sticks be converted
+ ' to a Gaussian representation, then the original, unmodified data is stored here
+
+Public TicksElapsedSinceStart As Long ' Actually increments 10 times per second rather than 1000 per second since tmrPlot.Interval = 100
+Private TickCountToUpdateAt As Long
+
+Private boolUpdatePosition As Boolean, CurrentPosX As Double, CurrentPosY As Double
+
+Const PLOT_RANGE_HISTORY_COUNT = 20
+Private PlotRangeHistory(PLOT_RANGE_HISTORY_COUNT, MAX_DATA_SETS) As usrPlotRange ' Keeps track of the last 5 plot ranges displayed to allow for undoing
+
+Private Sub EnableDisableZoomMenus(boolEnableMenus As Boolean)
+
+ mnuZoomOptions.Visible = boolEnableMenus
+
+End Sub
+
+Private Sub DetermineCurrentScalingRange(ThisAxisScaling As usrPlotRangeAxis, TheseDataLimits As usrPlotRangeAxis, CurrentScalingRange As usrScalingRangeValues)
+
+ With CurrentScalingRange
+ .PlotRangeStretchVal = (ThisAxisScaling.ValEnd.Val - ThisAxisScaling.ValStart.Val) * 0.1
+
+ .StartVal = ThisAxisScaling.ValStart.Val - ThisAxisScaling.ValNegativeValueCorrectionOffset
+ .EndVal = ThisAxisScaling.ValEnd.Val - ThisAxisScaling.ValNegativeValueCorrectionOffset
+ .LowerLimit = TheseDataLimits.ValStart.Val - .PlotRangeStretchVal
+ .UpperLimit = TheseDataLimits.ValEnd.Val + .PlotRangeStretchVal
+ End With
+
+End Sub
+
+Private Sub EnableDisableExportDataMenu()
+ Dim intDataSetIndex As Integer, boolDataPresent As Boolean
+
+ boolDataPresent = False
+
+ For intDataSetIndex = 0 To intDataSetsLoaded - 1
+ If LoadedXYData(intDataSetIndex).XYDataListCount > 0 Then
+ boolDataPresent = True
+ Exit For
+ End If
+ Next intDataSetIndex
+
+ mnuExportData.Enabled = boolDataPresent
+
+End Sub
+
+Private Sub EnableDisableMenuCheckmarks()
+
+ With PlotOptions
+ mnuPlotTypeSticksToZero.Checked = (.PlotTypeCode = 0)
+ mnuPlotTypeLinesBetweenPoints.Checked = (.PlotTypeCode = 1)
+ mnuGridLinesXAxis.Checked = .XAxis.ShowGridLinesMajor
+ mnuGridLinesYAxis.Checked = .YAxis.ShowGridLinesMajor
+ mnuAutoScaleYAxis.Checked = .AutoScaleY
+ mnuFixMinimumYAtZero.Checked = .FixYAxisMinimumAtZero
+ mnuFixMinimumYAtZero.Enabled = Not mnuAutoScaleYAxis.Checked
+ End With
+
+End Sub
+
+Public Sub ExportData()
+ Dim lngIndex As Long, strFilepath As String, strOutput As String
+ Dim intDataSetIndex As Integer, lngMaxDataListCount As Long
+
+ On Error GoTo WriteProblem
+
+ ' Display the File Open dialog box.
+ With CommonDialog1
+ .FilterIndex = 1
+ ' 1520 = Data Files, 1525 = .csv
+ .Filter = "CSV File (*.csv)|*.csv|All Files (*.*)|*.*"
+ .Flags = cdlOFNHideReadOnly Or cdlOFNOverwritePrompt
+ .CancelError = True
+ .FileName = ""
+ End With
+ On Error Resume Next
+ CommonDialog1.ShowSave
+
+ If Err.Number <> 0 Then
+ ' No file selected from the Save File dialog box (or other error)
+ Exit Sub
+ End If
+
+ strFilepath = CommonDialog1.FileName
+
+ Open strFilepath For Output As #1
+
+ If intDataSetsLoaded > 1 Then
+ strOutput = ""
+ For intDataSetIndex = 0 To intDataSetsLoaded - 1
+ strOutput = strOutput & "Data Set " & Trim(CStr(intDataSetIndex + 1)) & " X" & "," & "Data Set " & Trim(CStr(intDataSetIndex + 1)) & " Y"
+ If intDataSetIndex < intDataSetsLoaded - 1 Then strOutput = strOutput & ","
+ Next intDataSetIndex
+ Print #1, strOutput
+ End If
+
+ ' Determine maximum .XyDataListCount value
+ lngMaxDataListCount = 0
+ For intDataSetIndex = 0 To intDataSetsLoaded - 1
+ If LoadedXYData(intDataSetIndex).XYDataListCount > lngMaxDataListCount Then
+ lngMaxDataListCount = LoadedXYData(intDataSetIndex).XYDataListCount
+ End If
+ Next intDataSetIndex
+
+ For lngIndex = 1 To lngMaxDataListCount
+ strOutput = ""
+ For intDataSetIndex = 0 To intDataSetsLoaded - 1
+ If lngIndex <= LoadedXYData(intDataSetIndex).XYDataListCount Then
+ With LoadedXYData(intDataSetIndex).XYDataList(lngIndex)
+ strOutput = strOutput & .XVal & "," & .YVal
+ End With
+ If intDataSetIndex < intDataSetsLoaded - 1 Then strOutput = strOutput & ","
+ End If
+ Next intDataSetIndex
+ Print #1, strOutput
+ Next lngIndex
+ Close
+
+ Exit Sub
+
+WriteProblem:
+ MsgBox "Error exporting data" & ": " & strFilepath
+
+End Sub
+
+Private Function FixUpCoordinates(TheseCoords As usrRect) As usrRect
+ Dim FixedCoords As usrRect
+
+ FixedCoords = TheseCoords
+
+ With FixedCoords
+ If .x1 > .x2 Then
+ SwapValues .x1, .x2
+ End If
+ If .y1 > .y2 Then
+ SwapValues .y1, .y2
+ End If
+ End With
+
+ FixUpCoordinates = FixedCoords
+
+End Function
+
+Private Sub HidePlotForm()
+ Unload Me
+End Sub
+Private Sub HideZoomBox(Button As Integer, boolPerformZoom As Boolean)
+
+ EnableDisableZoomMenus False
+ boolZoomBoxDrawn = False
+ boolDrawingZoomBox = False
+
+ If shpZoomBox.Visible = False Then
+ Exit Sub
+ End If
+
+ shpZoomBox.Visible = False
+
+ If Button = vbLeftButton Then
+ If boolPerformZoom Then
+ PerformZoom
+ End If
+ End If
+
+End Sub
+
+Private Sub InitializeDummyData(intDataType As Integer)
+ ' intDataType can be 0: continuous sine wave
+ ' 1: stick data (only 20 points)
+ ' 2: stick data (1000's of points, mostly zero, with a few spikes)
+
+ Dim ThisXYDataSet As usrXYDataSet
+ Dim x As Long, sngOffset As Single
+
+ Const PI = 3.14159265359
+ Const DegToRadiansMultiplier = PI / 180 / 10
+
+ Randomize Timer
+
+ Select Case intDataType
+ Case 1
+ With ThisXYDataSet
+ .XYDataListCount = 14
+ ReDim .XYDataList(.XYDataListCount)
+ .XYDataList(1).XVal = 154
+ .XYDataList(1).YVal = 79
+ .XYDataList(2).XVal = 154.51
+ .XYDataList(2).YVal = 25
+ .XYDataList(3).XVal = 154.95
+ .XYDataList(3).YVal = 15
+ .XYDataList(4).XVal = 280.2
+ .XYDataList(4).YVal = 60
+ .XYDataList(5).XVal = 281.15
+ .XYDataList(5).YVal = 20
+ .XYDataList(6).XVal = 282.201
+ .XYDataList(6).YVal = 10
+ .XYDataList(7).XVal = 312
+ .XYDataList(7).YVal = 23
+ .XYDataList(8).XVal = 312.332
+ .XYDataList(8).YVal = 5
+ .XYDataList(9).XVal = 312.661
+ .XYDataList(9).YVal = 2
+ .XYDataList(10).XVal = 500
+ .XYDataList(10).YVal = 10
+ .XYDataList(11).XVal = 589
+ .XYDataList(11).YVal = 102
+ .XYDataList(12).XVal = 589.247
+ .XYDataList(12).YVal = 72.3
+ .XYDataList(13).XVal = 589.523
+ .XYDataList(13).YVal = 50.7
+ .XYDataList(14).XVal = 589.78
+ .XYDataList(14).YVal = 30
+ End With
+ SetXYData ThisXYDataSet, True, True
+ Case 2
+ With ThisXYDataSet
+ .XYDataListCount = 50000
+ ReDim .XYDataList(.XYDataListCount)
+ For x = 1 To .XYDataListCount
+ .XYDataList(x).XVal = 100 + x / 500
+ If x Mod 5000 = 0 Then
+ .XYDataList(x).YVal = Rnd(1) * .XYDataListCount / 200 * Rnd(1)
+ ElseIf x Mod 3000 = 0 Then
+ .XYDataList(x).YVal = Rnd(1) * .XYDataListCount / 650 * Rnd(1)
+ Else
+ .XYDataList(x).YVal = Rnd(1) * 3
+ End If
+ Next x
+ End With
+ SetXYData ThisXYDataSet, True, False
+ Case Else
+ With ThisXYDataSet
+ .XYDataListCount = 360! * 100!
+
+ ReDim .XYDataList(.XYDataListCount)
+ sngOffset = 10
+ For x = 1 To .XYDataListCount
+ If x Mod 5050 = 0 Then
+ sngOffset = Rnd(1) + 10
+ End If
+ .XYDataList(x).XVal = CDbl(x) / 1000 - 5
+ .XYDataList(x).YVal = sngOffset - Abs((x - .XYDataListCount / 2)) / 10000 + Sin(DegToRadiansMultiplier * x) * Cos(DegToRadiansMultiplier * x / 2) * 1.29967878493163
+ Next x
+ End With
+ SetXYData ThisXYDataSet, False, False
+ End Select
+
+ PlotOptions.IndexToHighlight = ThisXYDataSet.XYDataListCount / 2
+
+ ZoomOut True
+
+ UpdatePlot
+End Sub
+
+Private Sub InitializeZoomOrMove(Button As Integer, x As Single, y As Single)
+ If Button = vbLeftButton Then
+ With ZoomBoxCoords
+ .x1 = x
+ .y1 = y
+ .x2 = .x1
+ .y2 = .y1
+ End With
+
+ If mnuCursorModeZoom.Checked Then
+ ' Zooming
+ ' Begin drawing zoom/move box
+ shpZoomBox.Visible = True
+ boolZoomBoxDrawn = False
+ EnableDisableZoomMenus False
+ RedrawZoomBox
+ Else
+ ' Moving (dragging) plot
+ ' Will still update the zoom/move box to keep track of how far dragged
+ ' but will not draw the box
+ shpZoomBox.Visible = False
+ boolDrawingZoomBox = False
+ boolSlidingGraph = True
+ PlotRangeAtMoveStart = PlotRangeHistory(1, 0)
+ End If
+
+ Else
+ If shpZoomBox.Visible = True Then
+ ' User clicked outside of zoom box (not left button), hide it
+ HideZoomBox Button, False
+ Else
+ If Button = vbRightButton Then
+ ZoomOut False
+ End If
+ End If
+ End If
+
+End Sub
+
+Private Sub RespondZoomModeClick(Button As Integer, x As Single, y As Single)
+ ' The Zoom Box is visible and the user clicked inside the box
+ ' Handle the click differently depending on the location and the button
+
+ If IsZoomBoxLargeEnough(ZoomBoxCoords) Then
+ If Button = vbLeftButton Then
+ ' Left click inside box: Remove zoom/move box and zoom
+ HideZoomBox Button, True
+ ElseIf Button = vbRightButton Then
+ ' Right click inside box: Show zoom menu
+ PopupMenu mnuZoomOptions, vbPopupMenuLeftAlign
+ End If
+ Else
+ ' Clicked inside box but it's too small
+ HideZoomBox Button, False
+ SetCursorIcon
+
+ If Button = vbLeftButton Then
+ ' Left click outside box: Start a new zoom box
+ InitializeZoomOrMove Button, x, y
+ End If
+ End If
+
+End Sub
+
+Private Sub ResetMousePointer(Optional Button As Integer = 0)
+ If Button = 0 And Me.MousePointer <> vbDefault Then Me.MousePointer = vbDefault
+End Sub
+
+Private Sub ResizeZoomBox(Button As Integer, x As Single, y As Single)
+ ' For both zooming and moving, resizes the Zoom Box
+
+ ' If zooming, then redraw the box
+ If shpZoomBox.Visible = True And Button = vbLeftButton Then
+ ' Resize zoom/move box
+ ZoomBoxCoords.x2 = x
+ ZoomBoxCoords.y2 = y
+
+ RedrawZoomBox
+ End If
+
+ ' If moving, then call the PerformMove sub to initiate a move
+ If mnuCursorModeMove.Checked And Button = vbLeftButton Then
+ ' Resize zoom/move box
+ ZoomBoxCoords.x2 = x
+ ZoomBoxCoords.y2 = y
+
+ ' Moving plot
+ PerformMove
+ End If
+
+End Sub
+
+Public Sub SetAutoscaleY(boolEnable As Boolean)
+
+ If boolEnable Then
+ ' Auto Scale just turned on - replot
+ PlotOptions.AutoScaleY = True
+ UpdatePlot
+ Else
+ ' Auto Scale just turned off
+ PlotOptions.AutoScaleY = True
+ UpdatePlot
+ PlotOptions.AutoScaleY = False
+ End If
+ EnableDisableMenuCheckmarks
+
+End Sub
+
+Private Sub SetCursorIcon(Optional x As Single = 0, Optional y As Single = 0)
+ If mnuCursorModeMove.Checked Then
+ ' Move mode
+ ' Me.MouseIcon = imgMouseHand
+ ' Me.MousePointer = vbCustom
+ Me.MousePointer = vbSizeAll
+ Else
+ ' Zoom Mode
+ If boolZoomBoxDrawn Then
+ If IsClickInBox(x, y, ZoomBoxCoords) Then
+ If Me.MousePointer <> vbArrowQuestion Then
+ If IsZoomBoxLargeEnough(ZoomBoxCoords) Then
+' Me.MouseIcon = imgMouseMagnify
+' Me.MousePointer = vbCustom
+ 'Me.MousePointer = vbArrowQuestion
+ Me.MousePointer = vbUpArrow
+ End If
+ End If
+ Else
+ Me.MousePointer = vbCrosshair
+ End If
+ Else
+ Me.MousePointer = vbCrosshair
+ End If
+ End If
+ EnableDisableMenuCheckmarks
+End Sub
+
+Public Sub SetCursorMode(boolMoveMode As Boolean)
+
+ mnuCursorModeZoom.Checked = Not boolMoveMode
+ mnuCursorModeMove.Checked = boolMoveMode
+
+ SetCursorIcon
+
+End Sub
+
+Public Sub SetFixMinimumAtZero(boolEnable As Boolean)
+ PlotOptions.FixYAxisMinimumAtZero = boolEnable
+ SetPlotOptions True, True
+ EnableDisableMenuCheckmarks
+End Sub
+
+Public Sub SetGridlinesXAxis(boolEnable As Boolean)
+ PlotOptions.XAxis.ShowGridLinesMajor = boolEnable
+ SetPlotOptions True, False
+ EnableDisableMenuCheckmarks
+End Sub
+
+Public Sub SetGridlinesYAxis(boolEnable As Boolean)
+ PlotOptions.YAxis.ShowGridLinesMajor = boolEnable
+ SetPlotOptions True, False
+ EnableDisableMenuCheckmarks
+End Sub
+
+Public Sub SetNewRange(boolIsXAxis As Boolean, boolPromptUserForValues As Boolean, Optional dblNewStartVal As Double = 0, Optional dblNewEndVal As Double = 0)
+ Dim CurrentScalingRange As usrScalingRangeValues, ThisDataSetScalingRange As usrScalingRangeValues
+ Dim dblDefaultSeparationValue As Double
+ Dim intDataSetIndex As Integer
+ Dim strFormatString As String
+
+ For intDataSetIndex = 0 To intDataSetsLoaded - 1
+ If boolIsXAxis Then
+ DetermineCurrentScalingRange PlotOptions.Scaling.x, PlotOptions.DataLimits(intDataSetIndex).x, ThisDataSetScalingRange
+ Else
+ DetermineCurrentScalingRange PlotOptions.Scaling.y, PlotOptions.DataLimits(intDataSetIndex).y, ThisDataSetScalingRange
+ End If
+ If intDataSetIndex = 0 Then
+ CurrentScalingRange = ThisDataSetScalingRange
+ Else
+ With CurrentScalingRange
+ If ThisDataSetScalingRange.LowerLimit < .LowerLimit Then
+ .LowerLimit = ThisDataSetScalingRange.LowerLimit
+ End If
+ If ThisDataSetScalingRange.UpperLimit < .UpperLimit Then
+ .UpperLimit = ThisDataSetScalingRange.UpperLimit
+ End If
+ If ThisDataSetScalingRange.StartVal < .StartVal Then
+ .StartVal = ThisDataSetScalingRange.StartVal
+ End If
+ If ThisDataSetScalingRange.EndVal < .EndVal Then
+ .EndVal = ThisDataSetScalingRange.EndVal
+ End If
+ End With
+ End If
+ Next intDataSetIndex
+
+ With CurrentScalingRange
+ If .StartVal = 0 And .EndVal = 0 Then
+ .StartVal = .LowerLimit
+ .EndVal = .UpperLimit
+ End If
+ End With
+
+ If boolPromptUserForValues Or (dblNewStartVal = 0 And dblNewEndVal = 0) Then
+
+ With PlotRangeHistory(1, 0)
+ If boolIsXAxis Then
+ strFormatString = ConstructFormatString(Abs(.x.ValEnd.Val - .x.ValStart.Val) / 100)
+ Else
+ strFormatString = ConstructFormatString(Abs(.y.ValEnd.Val - .y.ValStart.Val) / 100)
+ End If
+ End With
+
+ With CurrentScalingRange
+ .StartVal = Format(.StartVal, strFormatString)
+ .EndVal = Format(.EndVal, strFormatString)
+ End With
+
+ With frmSetValue
+ .Caption = "Set Range"
+ .lblStartVal.Caption = "Start Val"
+ .txtStartVal = CurrentScalingRange.StartVal
+ .lblEndVal.Caption = "End Val"
+ .txtEndVal = CurrentScalingRange.EndVal
+
+ ' Round dblDefaultSeparationValue to nearest 1, 2, or 5 (or multiple of 10 thereof)
+ dblDefaultSeparationValue = RoundToMultipleOf10((CurrentScalingRange.EndVal - CurrentScalingRange.StartVal) / 10)
+
+ .SetLimits True, CurrentScalingRange.LowerLimit, CurrentScalingRange.UpperLimit, dblDefaultSeparationValue
+
+ If boolIsXAxis Then
+ .Caption = "Set X Axis Range"
+ Else
+ .Caption = "Set Y Axis Range"
+ End If
+
+ .Show vbModal
+ End With
+
+ If UCase(frmSetValue.lblHiddenStatus) <> "OK" Then Exit Sub
+
+ ' Set New Range
+ With frmSetValue
+ If IsNumeric(.txtStartVal) Then dblNewStartVal = CDbl(.txtStartVal)
+ If IsNumeric(.txtEndVal) Then dblNewEndVal = CDbl(.txtEndVal)
+ End With
+ End If
+
+ ' Set new scaling value for all loaded data sets
+ If boolIsXAxis Then
+ PlotOptions.Scaling.x.ValStart.Val = dblNewStartVal
+ PlotOptions.Scaling.x.ValEnd.Val = dblNewEndVal
+ Else
+ PlotOptions.Scaling.y.ValStart.Val = dblNewStartVal
+ PlotOptions.Scaling.y.ValEnd.Val = dblNewEndVal
+ End If
+
+ UpdatePlot True
+End Sub
+
+Public Sub SetXYDataVia2DArray(NewXYData() As Double, NewXYDataCount As Long, intDataSetIndexToUse As Integer, boolTreatDataAsDiscretePoints As Boolean, Optional boolConvertStickDataToGaussianRepresentation As Boolean = False, Optional boolZoomOutCompletely As Boolean = True)
+ ' Assumes NewXYData() is a 2D array with 2 columns
+ ' Further, assumes NewXYData() is a 1-based array in the first dimension but 0-based in the second
+
+ Dim ThisXYDataSet As usrXYDataSet, lngIndex As Long
+
+ If intDataSetIndexToUse < 0 Then
+ MsgBox "Invalid data set number. Must be between 0 and " & Trim(Str(MAX_DATA_SETS - 1)) & " Assuming value of 0", vbExclamation + vbOKOnly, "Error"
+ intDataSetIndexToUse = 0
+ ElseIf intDataSetIndexToUse > MAX_DATA_SETS - 1 Then
+ MsgBox "Invalid data set number. Must be between 0 and " & Trim(Str(MAX_DATA_SETS - 1)) & " Assuming value of " & Trim(Str(MAX_DATA_SETS - 1)), vbExclamation + vbOKOnly, "Error"
+ intDataSetIndexToUse = MAX_DATA_SETS - 1
+ End If
+
+
+ With ThisXYDataSet
+ .XYDataListCount = NewXYDataCount
+ .XYDataListCountDimmed = NewXYDataCount + 1
+ ReDim .XYDataList(.XYDataListCountDimmed)
+
+ For lngIndex = 1 To NewXYDataCount
+ .XYDataList(lngIndex).XVal = NewXYData(lngIndex, 0)
+ .XYDataList(lngIndex).YVal = NewXYData(lngIndex, 1)
+ Next lngIndex
+ End With
+
+ SetXYData ThisXYDataSet, boolTreatDataAsDiscretePoints, intDataSetIndexToUse, boolConvertStickDataToGaussianRepresentation, boolZoomOutCompletely
+
+End Sub
+
+Private Sub SetXYData(NewXYData As usrXYDataSet, boolTreatDataAsDiscretePoints As Boolean, intDataSetIndexToUse As Integer, Optional boolConvertStickDataToGaussianRepresentation As Boolean = False, Optional boolZoomOutCompletely As Boolean = True)
+ ' intDataSetIndexToUse can be 0 up to MAX_DATA_SETS, indicating which data set to use
+ Dim intDataSetIndex As Integer, dblCompareVal As Double
+
+ If intDataSetIndexToUse < 0 Then
+ MsgBox "Invalid data set number. Must be between 0 and " & Trim(Str(MAX_DATA_SETS - 1)) & " Assuming value of 0", vbExclamation + vbOKOnly, "Error"
+ intDataSetIndexToUse = 0
+ ElseIf intDataSetIndexToUse > MAX_DATA_SETS - 1 Then
+ MsgBox "Invalid data set number. Must be between 0 and " & Trim(Str(MAX_DATA_SETS - 1)) & " Assuming value of " & Trim(Str(MAX_DATA_SETS - 1)), vbExclamation + vbOKOnly, "Error"
+ intDataSetIndexToUse = MAX_DATA_SETS - 1
+ End If
+
+ ' Reset .DataLimits
+ With PlotOptions.DataLimits(intDataSetIndexToUse)
+ .x.ValStart.Val = 0
+ .y.ValEnd.Val = 0
+ .y.ValStart.Val = 0
+ .y.ValEnd.Val = 0
+ End With
+
+ ' Initialize Plot options
+ InitializePlotOptions
+
+ If intDataSetIndexToUse > intDataSetsLoaded - 1 Then
+ ' The number of data sets loaded must be at least intDataSetIndexToUse + 1
+ intDataSetsLoaded = intDataSetIndexToUse + 1
+ End If
+
+ If boolTreatDataAsDiscretePoints Then
+ InitialStickData(intDataSetIndexToUse) = NewXYData
+
+ SetPlotOptions False, False
+
+ ' Load New Data into LoadedXYData; accomplished using SetPlotType provided
+ ' InitialStickData(intDataSetIndex).XYDataListCount > 0
+ SetPlotType boolConvertStickDataToGaussianRepresentation, False
+ Else
+ InitialStickData(intDataSetIndexToUse).XYDataListCount = 0
+ LoadedXYData(intDataSetIndexToUse) = NewXYData
+ SetPlotType True, False
+ End If
+
+ If boolZoomOutCompletely Then
+ With PlotOptions
+ .Scaling = .DataLimits(0)
+
+ ' Check other data sets to see if data limits are outside limits in .Scaling
+ For intDataSetIndex = 1 To intDataSetsLoaded - 1
+ dblCompareVal = .DataLimits(intDataSetIndexToUse).x.ValStart.Val
+ If dblCompareVal < .Scaling.x.ValStart.Val Then
+ .Scaling.x.ValStart.Val = dblCompareVal
+ End If
+
+ dblCompareVal = .DataLimits(intDataSetIndexToUse).x.ValEnd.Val
+ If dblCompareVal < .Scaling.x.ValEnd.Val Then
+ .Scaling.x.ValEnd.Val = dblCompareVal
+ End If
+
+ dblCompareVal = .DataLimits(intDataSetIndexToUse).y.ValStart.Val
+ If dblCompareVal > .Scaling.y.ValStart.Val Then
+ .Scaling.y.ValStart.Val = dblCompareVal
+ End If
+
+ dblCompareVal = .DataLimits(intDataSetIndexToUse).y.ValEnd.Val
+ If dblCompareVal > .Scaling.y.ValEnd.Val Then
+ .Scaling.y.ValEnd.Val = dblCompareVal
+ End If
+ Next intDataSetIndex
+
+ End With
+
+ End If
+
+ ' Reset the boolLongOperationsRequired bit
+ PlotOptions.boolLongOperationsRequired = False
+
+ ' Erase all data in PlotRangeHistory()
+ ' Since this array is dimensioned using the const PLOT_RANGE_HISTORY_COUNT and MAX_DATA_SETS, it
+ ' does not need to be re-dimensioned after erasing
+ Erase PlotRangeHistory()
+
+ RefreshPlot boolZoomOutCompletely
+
+End Sub
+
+Public Sub SetPeaksToLabel(Optional intPeaksToLabel As Integer = -1)
+ Dim strResponse As String, intNewLabelCount As Integer
+
+ If intPeaksToLabel < 0 Then
+ strResponse = InputBox("Please enter the number of peaks (sticks) to label by decreasing intensity" & ":", "Peaks to Label", cboLabelsToShow.ListIndex)
+ Else
+ strResponse = Trim(CStr(intPeaksToLabel))
+ End If
+
+ If IsNumeric(strResponse) Then
+ intNewLabelCount = CIntSafe(strResponse)
+ If intNewLabelCount < 0 Or intNewLabelCount >= cboLabelsToShow.ListCount Then
+ intNewLabelCount = 3
+ End If
+ If intNewLabelCount < cboLabelsToShow.ListCount Then
+ cboLabelsToShow.ListIndex = intNewLabelCount
+ End If
+ End If
+
+ SetPlotOptions True, False
+End Sub
+Private Sub InitializePlotOptions()
+ txtXAxisTickCount = "5"
+ txtYAxisTickCount = "5"
+ cboLabelsToShow.ListIndex = 0
+
+ With PlotOptions
+ .XAxis.Show = True
+ .XAxis.MinorTickMinimumPixelSep = 100
+ .XAxis.ShowMinorTicks = True
+
+ .YAxis.Show = True
+ .YAxis.MinorTickMinimumPixelSep = 100
+ .YAxis.ShowMinorTicks = True
+
+ .GaussianConversion.ResolvingPower = 5000
+ .GaussianConversion.XValueOfSpecification = 500
+ .HighlightColor = vbRed
+ End With
+
+End Sub
+
+Private Sub SetPlotOptions(Optional boolUpdatePlot As Boolean = True, Optional boolUpdateHistory As Boolean = True)
+ With PlotOptions
+ .XAxis.MajorTicksToShow = txtXAxisTickCount
+
+ .YAxis.MajorTicksToShow = txtYAxisTickCount
+
+ .LabelsToShow = Val(cboLabelsToShow)
+ .ShowDataPointLabels = (.LabelsToShow > 0)
+ End With
+
+ If boolUpdatePlot Then UpdatePlot boolUpdateHistory
+
+End Sub
+
+Public Sub SetPlotType(boolLinesBetweenPoints As Boolean, Optional boolUpdatePlot As Boolean = True)
+ Dim intDataSetIndex As Integer
+
+ If boolLinesBetweenPoints Then
+ PlotOptions.PlotTypeCode = 1
+ Else
+ PlotOptions.PlotTypeCode = 0
+ End If
+ mnuPeaksToLabel.Enabled = Not boolLinesBetweenPoints
+
+ For intDataSetIndex = 0 To intDataSetsLoaded - 1
+
+ ' Reset .DataLimits
+ With PlotOptions.DataLimits(intDataSetIndex)
+ .x.ValStart.Val = 0
+ .y.ValEnd.Val = 0
+ .y.ValStart.Val = 0
+ .y.ValEnd.Val = 0
+ End With
+
+ If InitialStickData(intDataSetIndex).XYDataListCount > 0 Then
+ ' Stick data is present; need to take action
+ If boolLinesBetweenPoints Then
+ LoadedXYData(intDataSetIndex) = ConvertStickDataToGaussian(Me, InitialStickData(intDataSetIndex), PlotOptions, intDataSetIndex)
+ Else
+ LoadedXYData(intDataSetIndex) = InitialStickData(intDataSetIndex)
+ End If
+ Else
+ ' Clear data in LoadedXYData()
+ LoadedXYData(intDataSetIndex).XYDataListCount = 0
+ End If
+ Next intDataSetIndex
+
+ SetPlotOptions boolUpdatePlot, False
+ EnableDisableMenuCheckmarks
+
+End Sub
+
+Public Sub SetResolution(Optional lngNewResolvingPower As Long = -1, Optional dblNewXValResLocation As Double = 500)
+ Dim strResponse As String
+
+ If lngNewResolvingPower < 1 Then
+ With frmSetValue
+ .Caption = "Resolving Power Specifications"
+ .lblStartVal.Caption = "Resolving Power"
+ .txtStartVal = PlotOptions.GaussianConversion.ResolvingPower
+ .lblEndVal.Caption = "X Value of Specification"
+ .txtEndVal = PlotOptions.GaussianConversion.XValueOfSpecification
+
+ .SetLimits False
+
+ .Show vbModal
+ End With
+
+ If UCase(frmSetValue.lblHiddenStatus) <> "OK" Then Exit Sub
+
+ ' Set New Range
+ With frmSetValue
+ If IsNumeric(.txtStartVal) Then
+ lngNewResolvingPower = CLng(.txtStartVal)
+ Else
+ lngNewResolvingPower = 5000
+ End If
+ If IsNumeric(.txtEndVal) Then
+ dblNewXValResLocation = CDbl(.txtEndVal)
+ Else
+ dblNewXValResLocation = 500
+ End If
+ End With
+
+ End If
+
+ If lngNewResolvingPower < 1 Or lngNewResolvingPower > 1E+38 Then
+ lngNewResolvingPower = 5000
+ End If
+ PlotOptions.GaussianConversion.ResolvingPower = lngNewResolvingPower
+
+ PlotOptions.GaussianConversion.XValueOfSpecification = dblNewXValResLocation
+
+ SetPlotOptions False, False
+ SetPlotType mnuPlotTypeLinesBetweenPoints.Checked, True
+
+End Sub
+
+Public Sub SetShowCursorPosition(boolEnable As Boolean)
+ mnuShowCurrentPosition.Checked = boolEnable
+ lblCurrentPos.Visible = boolEnable
+ EnableDisableMenuCheckmarks
+End Sub
+
+Private Sub TickCountUpdateByUser(txtThisTextBox As TextBox, Optional strAxisLetter As String = "X")
+ Dim strResponse As String, intNewTickCount As Integer
+
+ strAxisLetter = UCase(Trim(strAxisLetter))
+
+ If Len(strAxisLetter) = 0 Then strAxisLetter = "X"
+
+ strResponse = InputBox("Please enter the approximate number of ticks to show on the axis" & " (" & strAxisLetter & ", 2 - 30):", "Axis Ticks", txtThisTextBox)
+
+ If IsNumeric(strResponse) Then
+ intNewTickCount = CIntSafe(strResponse)
+ If intNewTickCount < 2 Or intNewTickCount > 30 Then
+ intNewTickCount = 5
+ End If
+ txtThisTextBox = Trim(CStr(intNewTickCount))
+ End If
+
+ SetPlotOptions True, False
+
+End Sub
+
+Private Sub UpdateCurrentPos()
+ Dim XValue As Double, YValue As Double
+ Dim strNewString As String
+ Dim strFormatStringX As String, strFormatStringY As String
+
+ If mnuShowCurrentPosition.Checked Then
+ With PlotRangeHistory(1, 0)
+ XValue = XYPosToValue(CLng(CurrentPosX), .x)
+ YValue = XYPosToValue(CLng(CurrentPosY), .y)
+ strNewString = ConstructFormatString(Abs(.x.ValEnd.Val - .x.ValStart.Val) / 100)
+ strFormatStringX = strNewString
+
+ strNewString = ConstructFormatString(Abs(.y.ValEnd.Val - .y.ValStart.Val) / 100)
+ strFormatStringY = strNewString
+ End With
+
+ lblCurrentPos = "Loc" & ": " & Format(XValue, strFormatStringX) & ", " & Format(YValue, strFormatStringY)
+ End If
+
+ boolUpdatePosition = False
+End Sub
+
+Private Sub UpdatePlot(Optional boolUpdateHistory As Boolean = True)
+ Dim MostRecentPlotRange(MAX_DATA_SETS) As usrPlotRange, intHistoryIndex As Integer
+ Dim intDataSetIndex As Integer
+
+ With PlotOptions
+ If .PlotTypeCode = 0 Then
+ .PlotTop = 500
+ Else
+ .PlotTop = 250
+ End If
+ .PlotLeft = 300
+ .PlotWidth = fraPlot.Width - .PlotLeft - 250
+ .PlotHeight = fraPlot.Height - .PlotTop - 700
+ End With
+
+ For intDataSetIndex = 0 To intDataSetsLoaded - 1
+ MostRecentPlotRange(intDataSetIndex) = PlotRangeHistory(1, intDataSetIndex)
+ Next intDataSetIndex
+
+ ' Hide the plot so it gets updated faster
+ fraPlot.Visible = False
+
+ ' Perform the actual update
+ DrawPlot Me, PlotOptions, LoadedXYData(), MostRecentPlotRange(), intDataSetsLoaded
+
+ ' Show the plot
+ fraPlot.Visible = True
+
+ If boolUpdateHistory Then
+ ' Update the plot range history
+ For intHistoryIndex = PLOT_RANGE_HISTORY_COUNT To 2 Step -1
+ For intDataSetIndex = 0 To intDataSetsLoaded - 1
+ PlotRangeHistory(intHistoryIndex, intDataSetIndex) = PlotRangeHistory(intHistoryIndex - 1, intDataSetIndex)
+ Next intDataSetIndex
+ Next intHistoryIndex
+ End If
+
+ If Me.MousePointer = vbHourglass Then Me.MousePointer = vbDefault
+
+ For intDataSetIndex = 0 To intDataSetsLoaded - 1
+ PlotRangeHistory(1, intDataSetIndex) = MostRecentPlotRange(intDataSetIndex)
+ Next intDataSetIndex
+End Sub
+
+Private Sub UpdatePlotWhenIdle()
+ Dim boolUpdateHistory As Boolean
+
+ If TickCountToUpdateAt < TicksElapsedSinceStart Then
+ ' Update the plot, but don't update the history if sliding
+ If boolSlidingGraph Or boolResizingWindow Then
+ boolUpdateHistory = False
+ Else
+ boolUpdateHistory = True
+ End If
+ UpdatePlot boolUpdateHistory
+
+ TickCountToUpdateAt = 0
+ boolResizingWindow = False
+ End If
+
+End Sub
+
+Private Sub ZoomInHorizontal()
+ ' Zoom in along the horizontal axis but
+ ' Do not change the vertical range
+
+ FixUpCoordinates ZoomBoxCoords
+ With ZoomBoxCoords
+ .y1 = PlotRangeHistory(1, 0).y.ValEnd.Pos
+ .y2 = PlotRangeHistory(1, 0).y.ValStart.Pos
+ End With
+
+ HideZoomBox vbLeftButton, True
+
+End Sub
+
+Private Sub ZoomInVertical()
+ ' Zoom in along the horizontal axis but
+ ' Do not change the vertical range
+
+ FixUpCoordinates ZoomBoxCoords
+ With ZoomBoxCoords
+ .x1 = PlotRangeHistory(1, 0).x.ValStart.Pos
+ .x2 = PlotRangeHistory(1, 0).x.ValEnd.Pos
+ End With
+
+ HideZoomBox vbLeftButton, True
+
+End Sub
+
+Private Sub ZoomOut(ByVal boolZoomOutCompletely As Boolean)
+ Dim intHistoryIndex As Integer, lngIndex As Long, intDataSetIndex As Integer
+ Dim dblCompareXVal As Double, dblMinXVal As Double, dblMaxXVal As Double
+ Dim dblPlotRangeStretchVal As Double
+
+ If Not boolZoomOutCompletely Then
+ ' See if any previous PlotRange data exists in the history
+ ' If not then set boolZoomOutCompletely to True
+ With PlotRangeHistory(2, 0)
+ If .x.ValStart.Pos = 0 And .x.ValEnd.Pos = 0 And .x.ValStart.Pos = 0 And .x.ValEnd.Pos = 0 Then
+ ' Most recent saved zoom range is all zeroes -- not usable
+ boolZoomOutCompletely = True
+ End If
+ End With
+ End If
+
+ If boolZoomOutCompletely Then
+ ' Call SetPlotOptions to make sure all options are up to date
+ SetPlotOptions False
+
+ With PlotOptions
+ ' Override the AutoScaleY option and turn on ZoomOutFull
+ .ZoomOutFull = True
+ .AutoScaleY = True
+
+ ' Initialize .Scaling.x.ValStart.Val and .Scaling.y.ValStart.Val
+ ' Examine all loaded data sets to determine minimum and maximum XVal
+ For intDataSetIndex = 0 To intDataSetsLoaded - 1
+ If LoadedXYData(intDataSetIndex).XYDataListCount > 0 Then
+ ' Data in LoadedXYData is not necessarily sorted by mass
+ ' Must step through data to determine minimum and maximum XVal
+ If dblMinXVal = 0 Then
+ dblMinXVal = LoadedXYData(intDataSetIndex).XYDataList(1).XVal
+ End If
+ If dblMaxXVal = 0 Then
+ dblMaxXVal = LoadedXYData(intDataSetIndex).XYDataList(LoadedXYData(intDataSetIndex).XYDataListCount).XVal
+ End If
+
+ For lngIndex = 1 To LoadedXYData(intDataSetIndex).XYDataListCount
+ dblCompareXVal = LoadedXYData(intDataSetIndex).XYDataList(lngIndex).XVal
+ If dblCompareXVal < dblMinXVal Then dblMinXVal = dblCompareXVal
+ If dblCompareXVal > dblMaxXVal Then dblMaxXVal = dblCompareXVal
+ Next lngIndex
+
+ End If
+ Next intDataSetIndex
+
+ .Scaling.x.ValStart.Val = dblMinXVal
+ .Scaling.x.ValEnd.Val = dblMaxXVal
+
+ If .PlotTypeCode = 0 Or .PlotTypeCode = 1 Then
+ ' Displaying a sticks to zero plot and zoomed out full
+ ' Need to stretch the limits of the plot by 5% of the total range
+ dblPlotRangeStretchVal = (.Scaling.x.ValEnd.Val - .Scaling.x.ValStart.Val) * 0.05
+ .Scaling.x.ValEnd.Val = .Scaling.x.ValEnd.Val + dblPlotRangeStretchVal
+ .Scaling.x.ValStart.Val = .Scaling.x.ValStart.Val - dblPlotRangeStretchVal
+ End If
+
+ End With
+
+ ' Update the plot
+ UpdatePlot
+
+ ' Call SetPlotOptions again in case .AutoScaleY should be false
+ SetPlotOptions False
+ Else
+ ' Zoom to previous range
+
+ PlotOptions.Scaling = PlotRangeHistory(2, 0)
+
+ UpdatePlot False
+
+ ' Update the plot range history
+ For intHistoryIndex = 2 To PLOT_RANGE_HISTORY_COUNT - 1
+ For intDataSetIndex = 0 To intDataSetsLoaded - 1
+ PlotRangeHistory(intHistoryIndex, intDataSetIndex) = PlotRangeHistory(intHistoryIndex + 1, intDataSetIndex)
+ Next intDataSetIndex
+ Next intHistoryIndex
+
+ End If
+
+End Sub
+
+Private Sub ZoomShrink(boolFixHorizontal As Boolean, boolFixVertical As Boolean)
+ ' Zoom out, but not completely
+
+ Dim lngViewRangePosX As Long, lngViewRangePosY As Long
+ Dim lngBoxSizeX As Double, lngBoxSizeY As Double
+ Dim lngPosCorrectionFactorX As Long, lngPosCorrectionFactorY As Long
+ Dim TheseCoords As usrRect
+
+ With PlotRangeHistory(1, 0)
+ lngViewRangePosX = .x.ValEnd.Pos - .x.ValStart.Pos
+ lngViewRangePosY = .y.ValEnd.Pos - .y.ValStart.Pos
+ End With
+
+ If lngViewRangePosX = 0 Or lngViewRangePosY = 0 Then Exit Sub
+
+ TheseCoords = ZoomBoxCoords
+ FixUpCoordinates TheseCoords
+ With TheseCoords
+ lngBoxSizeX = Abs(.x2 - .x1)
+ lngBoxSizeY = Abs(.y2 - .y1)
+ If boolFixVertical Then
+ .x1 = PlotRangeHistory(1, 0).x.ValStart.Pos
+ .x2 = PlotRangeHistory(1, 0).x.ValEnd.Pos
+ Else
+ If lngBoxSizeX > 0 Then
+ lngPosCorrectionFactorX = (CLng(lngViewRangePosX * CDbl(lngViewRangePosX) / CDbl(lngBoxSizeX))) / 2
+ .x1 = .x1 - lngPosCorrectionFactorX
+ .x2 = .x2 + lngPosCorrectionFactorX
+ End If
+ End If
+ If boolFixHorizontal Then
+ .y1 = PlotRangeHistory(1, 0).y.ValEnd.Pos
+ .y2 = PlotRangeHistory(1, 0).y.ValStart.Pos
+ Else
+ If lngBoxSizeY > 0 Then
+ lngPosCorrectionFactorY = (CLng(lngViewRangePosY * CDbl(lngViewRangePosY) / CDbl(lngBoxSizeY))) / 2
+ .y1 = .y1 - lngPosCorrectionFactorY
+ .y2 = .y2 + lngPosCorrectionFactorY
+ End If
+ End If
+ End With
+
+ If lngBoxSizeX > 0 And lngBoxSizeY > 0 Then
+ ZoomBoxCoords = TheseCoords
+ HideZoomBox vbLeftButton, True
+ Else
+ HideZoomBox vbLeftButton, False
+ End If
+
+End Sub
+
+Private Function IsClickInBox(x As Single, y As Single, TheseZoomBoxCoords As usrRect) As Boolean
+ Dim FixedCoords As usrRect
+
+ ' Determine if click was inside or outside of zoom box
+ FixedCoords = FixUpCoordinates(TheseZoomBoxCoords)
+
+ With FixedCoords
+ If x >= .x1 And x <= .x2 And _
+ y >= .y1 And y <= .y2 Then
+ IsClickInBox = True
+ Else
+ IsClickInBox = False
+ End If
+ End With
+
+End Function
+
+Private Function IsZoomBoxLargeEnough(TheseCoords As usrRect) As Boolean
+
+ With TheseCoords
+ ' Don't zoom if box size is less than 150 by 150 twips
+ If Abs(.x2 - .x1) >= 150 And Abs(.y2 - .y1) >= 150 Then
+ IsZoomBoxLargeEnough = True
+ Else
+ IsZoomBoxLargeEnough = False
+ End If
+ End With
+
+End Function
+Private Sub PerformMove()
+
+ Dim TheseCoords As usrRect
+ Dim intDataSetIndex As Integer
+ Dim dblCompareVal As Double, dblMinDefinedXVal As Double, dblMaxDefinedXVal As Double
+ Dim DeltaXVal As Double, DeltaYVal As Double
+ Dim dblMinAllowableXVal As Double, dblMaxAllowableXVal As Double, MaximumRange As Double
+
+ TheseCoords = ZoomBoxCoords
+
+ With PlotRangeAtMoveStart
+ DeltaXVal = XYPosToValue(TheseCoords.x2, .x) - XYPosToValue(TheseCoords.x1, .x)
+ DeltaYVal = XYPosToValue(TheseCoords.y2, .y) - XYPosToValue(TheseCoords.y1, .y)
+ End With
+
+ PlotOptions.ZoomOutFull = False
+ With PlotOptions
+ ' First determine minimum and maximum defined x values for all loaded data sets
+ dblMinDefinedXVal = .DataLimits(0).x.ValStart.Val
+ dblMaxDefinedXVal = .DataLimits(0).x.ValEnd.Val
+ For intDataSetIndex = 1 To intDataSetsLoaded - 1
+ dblCompareVal = .DataLimits(intDataSetIndex).x.ValStart.Val
+ If dblCompareVal < dblMinDefinedXVal Then dblMinDefinedXVal = dblCompareVal
+
+ dblCompareVal = .DataLimits(intDataSetIndex).x.ValEnd.Val
+ If dblCompareVal > dblMaxDefinedXVal Then dblMaxDefinedXVal = dblCompareVal
+ Next intDataSetIndex
+
+ MaximumRange = dblMinDefinedXVal - dblMaxDefinedXVal
+ .Scaling.x.ValStart.Val = PlotRangeAtMoveStart.x.ValStart.Val - DeltaXVal
+ dblMinAllowableXVal = dblMinDefinedXVal - MaximumRange / 10
+ If .Scaling.x.ValStart.Val < dblMinAllowableXVal Then
+ .Scaling.x.ValStart.Val = dblMinAllowableXVal
+ .Scaling.x.ValEnd.Val = .Scaling.x.ValStart.Val + (PlotRangeAtMoveStart.x.ValEnd.Val - PlotRangeAtMoveStart.x.ValStart.Val)
+ Else
+ .Scaling.x.ValEnd.Val = PlotRangeAtMoveStart.x.ValEnd.Val - DeltaXVal
+ End If
+
+ dblMaxAllowableXVal = dblMaxDefinedXVal + MaximumRange / 10
+ If .Scaling.x.ValEnd.Val > dblMaxAllowableXVal Then
+ .Scaling.x.ValEnd.Val = dblMaxAllowableXVal
+ .Scaling.x.ValStart.Val = .Scaling.x.ValEnd.Val - (PlotRangeAtMoveStart.x.ValEnd.Val - PlotRangeAtMoveStart.x.ValStart.Val)
+ End If
+ .Scaling.y.ValStart.Val = PlotRangeAtMoveStart.y.ValStart.Val - DeltaYVal
+ .Scaling.y.ValEnd.Val = PlotRangeAtMoveStart.y.ValEnd.Val - DeltaYVal
+
+ End With
+
+ ' By setting TickCountToUpdateAt to a nonzero value (>= TicksElapsedSinceStart), the
+ ' move will be performed when TicksElapsedSinceStart reaches TickCountToUpdateAt
+ TickCountToUpdateAt = TicksElapsedSinceStart
+End Sub
+
+Private Sub PerformZoom()
+ Dim TheseCoords As usrRect, boolAbortZoom As Boolean
+ Dim PlotRangeSaved As usrPlotRange
+
+ ' Use the numbers stored in PlotRangeSaved to update the PlotOptions with the desired zoom range
+ PlotRangeSaved = PlotRangeHistory(1, 0) ' The most recent plot range
+
+ TheseCoords = FixUpCoordinates(ZoomBoxCoords)
+
+ If IsZoomBoxLargeEnough(TheseCoords) Then
+ PlotOptions.ZoomOutFull = False
+ With PlotOptions.Scaling
+ .x.ValStart.Val = XYPosToValue(TheseCoords.x1, PlotRangeSaved.x)
+ .x.ValEnd.Val = XYPosToValue(TheseCoords.x2, PlotRangeSaved.x)
+ .y.ValStart.Val = XYPosToValue(TheseCoords.y1, PlotRangeSaved.y)
+ .y.ValEnd.Val = XYPosToValue(TheseCoords.y2, PlotRangeSaved.y)
+ End With
+
+ UpdatePlot
+ End If
+
+End Sub
+
+Private Sub PositionControls()
+ Dim PlotHeight As Long
+
+ With fraOptions
+ .Left = 50
+ .Top = Me.Height - .Height - 700
+ .Visible = False
+ End With
+
+ With fraPlot
+ .Top = 50
+ .Left = 50
+ .Width = Me.Width - 250
+ If fraOptions.Visible Then
+ PlotHeight = Me.Height - fraOptions.Height - 600
+ Else
+ PlotHeight = Me.Height - 600
+ End If
+
+ If PlotHeight < 1 Then PlotHeight = 1
+ .Height = PlotHeight
+
+ lblCurrentPos.Top = 0
+ lblCurrentPos.Left = fraPlot.Width - lblCurrentPos.Width - 100
+
+''' dynMSPlot.Left = .Left
+''' dynMSPlot.top = .top
+''' dynMSPlot.Width = .Width
+''' dynMSPlot.Height = .Height
+ End With
+
+
+End Sub
+
+Private Sub RedrawZoomBox()
+ Dim TheseCoords As usrRect
+
+ TheseCoords = ZoomBoxCoords
+
+ With TheseCoords
+ If .x1 > .x2 Then
+ SwapValues .x1, .x2
+ End If
+ If .y1 > .y2 Then
+ SwapValues .y1, .y2
+ End If
+
+ End With
+
+ ' When the box size gets large enough, turn on boolDrawingZoomBox
+ If IsZoomBoxLargeEnough(TheseCoords) Then
+ boolDrawingZoomBox = True
+ End If
+
+ With shpZoomBox
+ .Left = TheseCoords.x1
+ .Top = TheseCoords.y1
+ .Width = TheseCoords.x2 - TheseCoords.x1
+ .Height = TheseCoords.y2 - TheseCoords.y1
+ End With
+End Sub
+
+Public Sub RefreshPlot(Optional boolZoomOutCompletely As Boolean = True)
+ If boolZoomOutCompletely Then
+ ZoomOut boolZoomOutCompletely
+ Else
+ UpdatePlot False
+ End If
+End Sub
+
+Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
+ If KeyCode = 32 Then
+ SetCursorMode True
+ SetCursorIcon
+ ElseIf KeyCode = vbKeyEscape Then
+ mnuClose_Click
+ ElseIf KeyCode = 90 And (Shift Or vbCtrlMask) Then
+ ' Ctrl+Z
+ ZoomOut False
+ End If
+
+End Sub
+Private Sub Form_KeyUp(KeyCode As Integer, Shift As Integer)
+ If KeyCode = 32 Then
+ SetCursorMode False
+ SetCursorIcon
+ End If
+End Sub
+
+Private Sub Form_Load()
+ SizeAndCenterWindow Me, cWindowBottomRight, 8000, 7000, True
+
+ Dim x As Integer
+
+ With cboLabelsToShow
+ For x = 0 To 20
+ .AddItem Trim(CStr(x))
+ Next x
+ .ListIndex = 3
+ End With
+
+ InitializePlotOptions
+
+ ' Hide the Peaks to Label menu since not yet implemented
+ mnuPeaksToLabel.Visible = False
+
+ shpZoomBox.Visible = False
+
+ EnableDisableZoomMenus False
+
+End Sub
+
+Private Sub Form_MouseMove(Button As Integer, Shift As Integer, x As Single, y As Single)
+ ResetMousePointer Button
+End Sub
+
+Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
+ If UnloadMode = vbFormControlMenu Then
+ Cancel = True
+ HidePlotForm
+ End If
+End Sub
+
+Private Sub Form_Resize()
+ PositionControls
+ If Me.WindowState <> vbMinimized Then
+ TickCountToUpdateAt = TicksElapsedSinceStart + 1
+ boolResizingWindow = True
+ End If
+End Sub
+
+Private Sub fraOptions_MouseMove(Button As Integer, Shift As Integer, x As Single, y As Single)
+ ResetMousePointer Button
+End Sub
+
+Private Sub fraPlot_MouseDown(Button As Integer, Shift As Integer, x As Single, y As Single)
+
+ Dim boolClickInsideBox As Boolean
+ boolClickInsideBox = IsClickInBox(x, y, ZoomBoxCoords)
+
+ If Not shpZoomBox.Visible Or Not boolClickInsideBox Then
+ InitializeZoomOrMove Button, x, y
+ Else
+ ' The Zoom Box is visible
+ ' The click is also handled in Sub fraPlot_MouseUp since it is more customary to handle clicks with _MouseUp events
+ If boolZoomBoxDrawn = True Then
+ RespondZoomModeClick Button, x, y
+ End If
+ End If
+End Sub
+
+Private Sub fraPlot_MouseMove(Button As Integer, Shift As Integer, x As Single, y As Single)
+ If Button = 0 Then
+ SetCursorIcon x, y
+ End If
+
+ ResizeZoomBox Button, x, y
+
+ boolUpdatePosition = True
+ CurrentPosX = x
+ CurrentPosY = y
+
+End Sub
+
+Private Sub fraPlot_MouseUp(Button As Integer, Shift As Integer, x As Single, y As Single)
+ Dim intHistoryIndex As Integer, intDataSetIndex As Integer
+
+ If mnuCursorModeZoom.Checked Then
+ ' Zooming, the box is shown at the size the user chose
+ ' Handle the click differently depending on the location and the button
+
+ If boolZoomBoxDrawn = True Then
+ ' Do nothing
+ ElseIf boolDrawingZoomBox Then
+ boolZoomBoxDrawn = True
+ EnableDisableZoomMenus IsZoomBoxLargeEnough(ZoomBoxCoords)
+ End If
+ Else
+ ' Moving plot
+ ' Turn off boolSlidingGraph
+ boolSlidingGraph = False
+
+ ' Set TickCountToUpdateAt back to 0 so no more udpates occur
+ TickCountToUpdateAt = 0
+
+ ' Update the plot one more time so new view gets saved to history
+ UpdatePlot True
+
+ ' For some reason the history still has two copies of the most recent view
+ ' Remove one of them
+ For intHistoryIndex = 2 To PLOT_RANGE_HISTORY_COUNT - 1
+ For intDataSetIndex = 1 To intDataSetsLoaded - 1
+ PlotRangeHistory(intHistoryIndex, intDataSetIndex) = PlotRangeHistory(intHistoryIndex + 1, intDataSetIndex)
+ Next intDataSetIndex
+ Next intHistoryIndex
+ End If
+
+End Sub
+
+
+Private Sub mnuAutoScaleYAxis_Click()
+ SetAutoscaleY Not mnuAutoScaleYAxis.Checked
+End Sub
+
+Private Sub mnuClose_Click()
+ HidePlotForm
+End Sub
+
+Private Sub mnuContinousData_Click()
+ InitializeDummyData 0
+End Sub
+
+Private Sub mnuCursorModeMove_Click()
+ SetCursorMode True
+End Sub
+
+Private Sub mnuCursorModeZoom_Click()
+ SetCursorMode False
+End Sub
+
+Private Sub mnuExportData_Click()
+ ExportData
+End Sub
+
+Private Sub mnuFile_Click()
+ ' EnableDisable mnuExportData
+
+ EnableDisableExportDataMenu
+End Sub
+
+Private Sub mnuFixMinimumYAtZero_Click()
+ SetFixMinimumAtZero Not mnuFixMinimumYAtZero.Checked
+End Sub
+
+Private Sub mnuGridLinesXAxis_Click()
+ SetGridlinesXAxis Not mnuGridLinesXAxis.Checked
+End Sub
+
+Private Sub mnuGridLinesYAxis_Click()
+ SetGridlinesYAxis Not mnuGridLinesYAxis.Checked
+End Sub
+
+Private Sub mnuOptions_Click()
+ EnableDisableMenuCheckmarks
+End Sub
+
+Private Sub mnuPeaksToLabel_Click()
+ SetPeaksToLabel
+End Sub
+
+Private Sub mnuPlotTypeLinesBetweenPoints_Click()
+ SetPlotType True
+End Sub
+
+Private Sub mnuPlotTypeSticksToZero_Click()
+ SetPlotType False
+End Sub
+
+Private Sub mnuSetRangeX_Click()
+ SetNewRange True, False
+End Sub
+
+Private Sub mnuSetRangeY_Click()
+ SetNewRange False, True
+End Sub
+
+Private Sub mnuSetResolution_Click()
+ SetResolution
+End Sub
+
+Private Sub mnuShowCurrentPosition_Click()
+ SetShowCursorPosition Not mnuShowCurrentPosition.Checked
+End Sub
+
+Private Sub mnuStickDataLots_Click()
+ InitializeDummyData 2
+End Sub
+
+Private Sub mnuStickDataSome_Click()
+ InitializeDummyData 1
+End Sub
+
+Private Sub mnuTicksXAxis_Click()
+ TickCountUpdateByUser txtXAxisTickCount, "X"
+End Sub
+
+Private Sub mnuTicksYAxis_Click()
+ TickCountUpdateByUser txtYAxisTickCount, "Y"
+End Sub
+
+Private Sub mnuZoomIn_Click()
+ HideZoomBox vbLeftButton, True
+End Sub
+
+Private Sub mnuZoomInHorizontal_Click()
+ ZoomInHorizontal
+End Sub
+
+Private Sub mnuZoomInVertical_Click()
+ ZoomInVertical
+End Sub
+
+Private Sub mnuZoomOut_Click()
+ ZoomShrink False, False
+End Sub
+
+Private Sub mnuZoomOutFullScale_Click()
+ ZoomOut True
+End Sub
+
+Private Sub mnuZoomOutHorizontal_Click()
+ ZoomShrink True, False
+End Sub
+
+Private Sub mnuZoomOutToPrevious_Click()
+ ZoomOut False
+End Sub
+
+Private Sub mnuZoomOutVertical_Click()
+ ZoomShrink False, True
+End Sub
+
+Private Sub tmrUpdatePlot_Timer()
+ ' Note: the internal for the timer is 250 msec
+
+ TicksElapsedSinceStart = TicksElapsedSinceStart + 1
+ If TickCountToUpdateAt > 0 Then
+ UpdatePlotWhenIdle
+ End If
+
+ If boolUpdatePosition Then UpdateCurrentPos
+End Sub
+
+Private Sub txtXAxisTickCount_KeyPress(KeyAscii As Integer)
+ TextBoxKeyPressHandler txtXAxisTickCount, KeyAscii, True, False
+End Sub
+
+Private Sub txtXAxisTickCount_Validate(Cancel As Boolean)
+ ValidateTextboxValueDbl txtXAxisTickCount, 2, 50, 10
+ SetPlotOptions True, False
+End Sub
+
+Private Sub txtYAxisTickCount_KeyPress(KeyAscii As Integer)
+ TextBoxKeyPressHandler txtYAxisTickCount, KeyAscii, True, False
+End Sub
+
+Private Sub txtYAxisTickCount_Validate(Cancel As Boolean)
+ ValidateTextboxValueDbl txtYAxisTickCount, 2, 50, 10
+ SetPlotOptions True, False
+End Sub
diff --git a/MsPlot/MsPlot.log b/MsPlot/MsPlot.log
new file mode 100644
index 0000000..96cf64c
--- /dev/null
+++ b/MsPlot/MsPlot.log
@@ -0,0 +1,2 @@
+Line 14: Class MSChart20Lib.MSChart of control chtPlot was not a loaded control class.
+Line 17: The property name OleObjectBlob in chtPlot is invalid.
diff --git a/MsPlot/MsPlot.vbp b/MsPlot/MsPlot.vbp
new file mode 100644
index 0000000..9e147ab
--- /dev/null
+++ b/MsPlot/MsPlot.vbp
@@ -0,0 +1,43 @@
+Type=Exe
+Form=MsPlot.frm
+Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#D:\WINDOWS\System32\stdole2.tlb#OLE Automation
+Module=MsPlotRoutines; MsPlot.bas
+Module=SharedVBRoutines; ..\SharedVBRoutines.bas
+Object={831FDD16-0C5C-11D2-A9FC-0000F8754DA1}#2.0#0; MSCOMCTL.OCX
+Form=..\Progress.frm
+Form=..\MyMsgBox.frm
+Form=SetRange.frm
+Object={F9043C88-F6F2-101A-A3C9-08002B2F49FB}#1.2#0; COMDLG32.OCX
+IconForm="frmMsPlot"
+Startup="frmMsPlot"
+HelpFile=""
+Title="Ms Plot"
+ExeName32="MsPlot.exe"
+Command32=""
+Name="MsPlot"
+HelpContextID="0"
+CompatibleMode="0"
+MajorVer=1
+MinorVer=0
+RevisionVer=0
+AutoIncrementVer=0
+ServerSupportFiles=0
+VersionCompanyName="University of North Carolina"
+CompilationType=0
+OptimizationType=0
+FavorPentiumPro(tm)=0
+CodeViewDebugInfo=0
+NoAliasing=0
+BoundsCheck=0
+OverflowCheck=0
+FlPointCheck=0
+FDIVCheck=0
+UnroundedFP=0
+StartMode=0
+Unattended=0
+Retained=0
+ThreadPerObject=0
+MaxNumberOfThreads=1
+
+[MS Transaction Server]
+AutoRefresh=1
diff --git a/MsPlot/MsPlot.vbw b/MsPlot/MsPlot.vbw
new file mode 100644
index 0000000..06ebcd0
--- /dev/null
+++ b/MsPlot/MsPlot.vbw
@@ -0,0 +1,6 @@
+frmMsPlot = 110, 110, 782, 568, , 66, 66, 738, 524, C
+MsPlotRoutines = 22, 22, 694, 480,
+SharedVBRoutines = 44, 44, 716, 502,
+frmProgress = 22, 22, 680, 392, , 22, 22, 507, 384, C
+frmMyMsgBox = 0, 0, 0, 0, C, 0, 0, 485, 362, C
+frmSetValue = 44, 44, 529, 406, , 95, 86, 803, 448, C
diff --git a/MsPlot/MsPlot.zip b/MsPlot/MsPlot.zip
new file mode 100644
index 0000000..2beb67e
Binary files /dev/null and b/MsPlot/MsPlot.zip differ
diff --git a/MsPlot/Old/MsPlot.bas b/MsPlot/Old/MsPlot.bas
new file mode 100644
index 0000000..af737ed
--- /dev/null
+++ b/MsPlot/Old/MsPlot.bas
@@ -0,0 +1,1550 @@
+Attribute VB_Name = "MsPlotRoutines"
+Option Explicit
+
+Private Const LowestValueForDataType = -1.79E+308 ' -3.4E+38
+Private Const HighestValueForDataType = 1.79E+308 ' 3.4E+38
+Private Const NUM_TWIPS_PER_DIGIT = 90
+
+Public Type usrAxisOptions
+ Show As Boolean ' Whether or not to show the axis
+ ShowLabels As Boolean ' whether or not to label axes
+ MajorTicksToShow As Integer ' The number of major tick values to show
+ ShowMinorTicks As Boolean ' Whether or not to show minor ticks
+ MinorTickMinimumPixelSep As Integer ' Minimum spacing in pixels between minor ticks before showing them
+
+ ShowGridLinesMajor As Boolean
+ ShowTickLinesMinor As Boolean
+
+End Type
+
+Public Type usrPlotRangeDetails
+ Val As Double
+ Pos As Long
+End Type
+
+Public Type usrPlotRangeAxis
+ ValStart As usrPlotRangeDetails
+ ValEnd As usrPlotRangeDetails
+ ValNegativeValueCorrectionOffset As Double
+End Type
+
+Public Type usrPlotRange
+ x As usrPlotRangeAxis
+ y As usrPlotRangeAxis
+End Type
+
+Public Type usrGaussianOptions
+ ResolvingPower As Long ' Effective resolution (M / delta M)
+ XValueOfSpecification As Single ' X Value where effective resolution applies
+End Type
+
+Public Type usrPlotDataOptions
+
+ PlotTypeCode As Integer ' Whether the plot is a stick plot (0) or line-between-points plot (1)
+ GaussianConversion As usrGaussianOptions
+
+ ' Zoom options
+ ZoomOutFull As Boolean ' When true, the data is shown fully zoomed out, ignoring the XVal and YVal Start and End values
+ AutoScaleY As Boolean ' When true, will zoom the x data as requested but always keep the y data at full scale
+ FixYAxisMinimumAtZero As Boolean ' Only used if AutoScaleY = True; keeps the minimum y scaling at 0 at all times (i.e. makes YValStart = 0)
+
+ ' Scaling options
+ Scaling As usrPlotRange
+ DataLimits As usrPlotRange ' Records the largest and smallest values of the given data set
+ SortData As Boolean ' Whether or not to sort the data by x value before plotting
+
+ ' The following define the size of the spectrum in the parent frame
+ PlotLeft As Integer ' In Twips (VB units)
+ PlotTop As Integer ' In Twips (VB units)
+ PlotWidth As Integer ' In Twips (VB units)
+ PlotHeight As Integer ' In Twips (VB units)
+ PlotLeftLargeNumberOffset As Integer ' In Twips - used to offset the left of the graph to the right a little for very large or very small numbers
+
+ XAxis As usrAxisOptions
+ YAxis As usrAxisOptions
+
+ MajorTicksLoaded As Long ' There is a label and gridline loaded for each major tick loaded
+ MinorTicksLoaded As Long
+
+ boolLongOperationsRequired As Boolean ' Set to true when long operations are encountered, thus requiring an hourglass cursor
+
+ ' Labeling options
+ ShowDataPointLabels As Boolean ' Whether to label or not
+ LabelsToShow As Integer ' Number of labels to show
+ IndexToHighlight As Long ' Index of the x,y data pair to highlight (if any)
+ HighlightColor As Long ' default vbRed
+
+ LinesLoadedCount As Long ' Records the number of lines and labels that have been dynamically loaded
+End Type
+
+Public Type usrXYData
+ XVal As Double ' Note: Single data type is -3.402823E38 to 3.402823E38
+ YVal As Double
+End Type
+
+Public Type usrXYDataSet
+ XYDataList() As usrXYData ' Index 1 to XYDataListCount
+ XYDataListCount As Long
+ XYDataListCountDimmed As Long
+End Type
+
+Private Sub CheckForLongOperation(ThisForm As Form, lngSecondsElapsedAtStart As Long, PlotOptions As usrPlotDataOptions)
+ ' Checks to see if the current Timer() value (sec elapsed since midnight) is
+ ' greater than lngSecondsElapsedAtStart. If it is, it turns boolSavedCheckBit on
+ ' and sets the pointer to an hourglass
+ ' The boolSavedCheckBit value is saved for future calls to the sub so that the hourglass
+ ' will be activated immediately on future calls
+
+ If Timer() - lngSecondsElapsedAtStart > 1 Or PlotOptions.boolLongOperationsRequired Then
+ PlotOptions.boolLongOperationsRequired = True
+ ThisForm.MousePointer = vbHourglass
+ End If
+
+End Sub
+
+Public Function ConstructFormatString(dblThisValue As Double, Optional ByRef intDigitsInFormattedValue As Integer) As String
+ ' Examines dblThisValue and constructs a format string based on its magnitude
+ ' For example, dblThisValue = 1234 will return "0"
+ ' dblThisValue = 2.4323 will return "0.0000"
+ '
+ ' In addition, returns the length of the string representation of dblThisValue using the determined format string
+ Dim lngExponentValue As Long, intDigitsInLabel As Integer
+ Dim strWork As String, strFormatString As String
+
+ ' Determine width of label to use and construct formatting string for labels
+ ' First, find the exponent of dblThisValue
+ strWork = Format(dblThisValue, "0E+000")
+ lngExponentValue = CInt(Right(strWork, 4))
+
+ ' Determine number of digits in dblThisValue, rounded according to lngExponentVal
+ If lngExponentValue >= 0 Then
+ intDigitsInLabel = 0
+ strFormatString = "0"
+ Else
+ ' Add 1 for the decimal point
+ intDigitsInLabel = -lngExponentValue + 1
+ strFormatString = "0." & String(-lngExponentValue, "0")
+ End If
+
+ intDigitsInFormattedValue = Len(Format(dblThisValue, strFormatString))
+
+ ConstructFormatString = strFormatString
+End Function
+
+Private Sub CheckDynamicXYData(ByRef ThisXYDataList() As usrXYData, ThisXYDataListCount As Long, ByRef ThisXYDataListCountDimmed As Long, Optional lngIncrement As Long = 100)
+ If ThisXYDataListCount > ThisXYDataListCountDimmed Then
+ ThisXYDataListCountDimmed = ThisXYDataListCountDimmed + lngIncrement
+ If ThisXYDataListCountDimmed < ThisXYDataListCount Then
+ ThisXYDataListCountDimmed = ThisXYDataListCount
+ End If
+ ReDim Preserve ThisXYDataList(ThisXYDataListCountDimmed)
+ End If
+End Sub
+
+Public Function ConvertStickDataToGaussian(ThisForm As Form, ThisXYDataSet As usrXYDataSet, PlotOptions As usrPlotDataOptions) As usrXYDataSet
+ Dim XYDataPointerArray() As Long, XYDataPointerArrayCount As Long
+ Dim lngDataIndex As Long, lngMidPointIndex As Long
+ Dim lngStickIndex As Long, DeltaX As Double
+
+ Dim dblXValRange As Double, dblXValWindowRange As Double, dblRangeWork As Double
+ Dim dblMinimalXValOfWindow As Double, dblMinimalXValSpacing As Double
+
+ Dim dblXOffSet As Double, sigma As Double
+ Dim intDigitsToRoundTo As Integer, lngExponentValue As Long
+
+ Dim XYSummation() As usrXYData, XYSummationCount As Long, XYSummationCountDimmed As Long
+ Dim lngSummationIndex As Long, lngMinimalSummationIndex As Long, lngOffsetIndex As Long
+ Dim DataToAdd() As usrXYData, lngDataToAddCount As Long, boolAppendNewData As Boolean
+ Dim boolSequentialValueFound As Boolean
+ Dim ThisDataPoint As usrXYData
+
+ Const NUM_CHUNKS = 100
+
+ If ThisXYDataSet.XYDataListCount = 0 Then Exit Function
+
+ If PlotOptions.GaussianConversion.ResolvingPower < 1 Then
+ PlotOptions.GaussianConversion.ResolvingPower = 1
+ End If
+
+ XYSummationCount = 0
+ XYSummationCountDimmed = 100
+ ReDim XYSummation(XYSummationCountDimmed)
+
+ With ThisXYDataSet
+ ' Initialize the Pointer Array
+ XYDataPointerArrayCount = .XYDataListCount
+ ReDim XYDataPointerArray(XYDataPointerArrayCount)
+ For lngDataIndex = 1 To XYDataPointerArrayCount
+ XYDataPointerArray(lngDataIndex) = lngDataIndex
+ Next lngDataIndex
+
+ ' See if data is sorted; if not, sort it
+ ' Force .SortData to be True
+ PlotOptions.SortData = True
+ CheckDataLimitsAndSortData ThisForm, .XYDataList(), XYDataPointerArray(), XYDataPointerArrayCount, PlotOptions
+
+ PlotOptions.DataLimits.x.ValStart.Val = .XYDataList(XYDataPointerArray(1)).XVal
+ PlotOptions.DataLimits.x.ValEnd.Val = .XYDataList(XYDataPointerArray(XYDataPointerArrayCount)).XVal
+ End With
+
+ With PlotOptions
+ dblXValRange = .DataLimits.x.ValEnd.Val - .DataLimits.x.ValStart.Val
+
+ ' Set DeltaX using .ResolvingPower and .XValueOfSpecification
+ ' Do not allow the DeltaX to be so small that the total points required > 100,000
+ DeltaX = .GaussianConversion.XValueOfSpecification / .GaussianConversion.ResolvingPower / 20
+ ' Make sure DeltaX is a reasonable number
+ DeltaX = RoundToMultipleOf10(DeltaX)
+ If DeltaX = 0 Then DeltaX = 1
+
+ ' Set the Window Range to 1/10 the magnitude of the midpoint x value
+ dblRangeWork = .DataLimits.x.ValStart.Val + dblXValRange / 2
+ dblRangeWork = RoundToMultipleOf10(dblRangeWork, lngExponentValue)
+
+ sigma = (.GaussianConversion.XValueOfSpecification / .GaussianConversion.ResolvingPower) / Sqr(5.54)
+
+ ' Set the window range (the xvalue window width range) to calculate the Gaussian representation for each data point
+ ' The width at the base of a peak is 4 sigma
+ ' Use a width of 2 * 6 sigma
+ dblXValWindowRange = 2 * 6 * sigma
+
+ If dblXValWindowRange / DeltaX > 50000 Then
+ DeltaX = dblXValWindowRange / 50000
+ End If
+
+ lngDataToAddCount = CLng(dblXValWindowRange / DeltaX)
+ ' Make sure lngDataToAddCount is odd
+ If CSng(lngDataToAddCount) / 2! = Round(CSng(lngDataToAddCount) / 2!, 0) Then
+ lngDataToAddCount = lngDataToAddCount + 1
+ End If
+ ReDim DataToAdd(lngDataToAddCount)
+ lngMidPointIndex = (lngDataToAddCount + 1) / 2
+ End With
+
+ With ThisXYDataSet
+ frmProgress.InitializeForm "Creating Gaussian Representation", 0, XYDataPointerArrayCount
+ For lngStickIndex = 1 To XYDataPointerArrayCount
+ frmProgress.UpdateProgressBar lngStickIndex
+ ' Search through XYSummation to determine the index of the smallest XValue with which
+ ' data in DataToAdd could be combined
+ lngMinimalSummationIndex = 1
+ dblMinimalXValOfWindow = .XYDataList(XYDataPointerArray(lngStickIndex)).XVal - (lngMidPointIndex - 1) * DeltaX
+ If dblMinimalXValOfWindow > XYSummation(XYSummationCount).XVal Then
+ lngMinimalSummationIndex = XYSummationCount
+ Else
+ For lngSummationIndex = 1 To XYSummationCount
+ If XYSummation(lngSummationIndex).XVal >= dblMinimalXValOfWindow Then
+ lngMinimalSummationIndex = lngSummationIndex - 1
+ If lngMinimalSummationIndex < 1 Then lngMinimalSummationIndex = 1
+ Exit For
+ End If
+ Next lngSummationIndex
+ If lngSummationIndex > XYSummationCount Then
+ lngMinimalSummationIndex = XYSummationCount
+ End If
+ End If
+
+ ' Construct the Gaussian representation for this Data Point
+ ThisDataPoint = .XYDataList(XYDataPointerArray(lngStickIndex))
+
+ ' Round ThisDataPoint.XVal to the nearest DeltaX
+ ' If .XVal is not an even multiple of DeltaX then bump up .XVal until it is
+ ThisDataPoint.XVal = RoundToEvenMultiple(ThisDataPoint.XVal, DeltaX, True)
+
+ For lngDataIndex = 1 To lngDataToAddCount
+ ' Equation for Gaussian is: Amplitude * Exp[ -(x - mu)^2 / (2*sigma^2) ]
+ ' Use lngDataIndex, .YVal, and DeltaX
+ dblXOffSet = (lngMidPointIndex - lngDataIndex) * DeltaX
+ DataToAdd(lngDataIndex).XVal = ThisDataPoint.XVal - dblXOffSet
+ DataToAdd(lngDataIndex).YVal = ThisDataPoint.YVal * Exp(-(dblXOffSet) ^ 2 / (2 * sigma ^ 2))
+ Next lngDataIndex
+
+ ' Now merge DataToAdd into XYSummation
+ ' XValues in DataToAdd and those in XYSummation have the same DeltaX value
+ ' The XValues in DataToAdd might overlap partially with those in XYSummation
+
+ lngDataIndex = 1
+ ' First, see if the first XValue in DataToAdd is larger than the last XValue in XYSummation
+ If DataToAdd(lngDataIndex).XVal > XYSummation(XYSummationCount).XVal Then
+ boolAppendNewData = True
+ Else
+ boolAppendNewData = False
+ ' Step through XYSummation() starting at lngMinimalSummationIndex, looking for
+ ' the index to start combining data at
+ For lngSummationIndex = lngMinimalSummationIndex To XYSummationCount
+ If DataToAdd(lngDataIndex).XVal = XYSummation(lngSummationIndex).XVal Or DataToAdd(lngDataIndex).XVal < XYSummation(lngSummationIndex).XVal Then
+ '''Debug.Assert XYSummation(lngSummationIndex).XVal = DataToAdd(lngDataIndex).XVal
+ ' Within Tolerance; start combining the values here
+ Do While lngSummationIndex <= XYSummationCount
+ XYSummation(lngSummationIndex).YVal = XYSummation(lngSummationIndex).YVal + DataToAdd(lngDataIndex).YVal
+ lngSummationIndex = lngSummationIndex + 1
+ lngDataIndex = lngDataIndex + 1
+ If lngDataIndex > lngDataToAddCount Then
+ ' Successfully combined all of the data
+ Exit Do
+ End If
+ Loop
+ If lngDataIndex <= lngDataToAddCount Then
+ ' Data still remains to be added
+ boolAppendNewData = True
+ End If
+ Exit For
+ End If
+ Next lngSummationIndex
+ End If
+
+ If boolAppendNewData = True Then
+ CheckDynamicXYData XYSummation(), XYSummationCount + lngDataToAddCount - lngDataIndex + 1, XYSummationCountDimmed
+ Do While lngDataIndex <= lngDataToAddCount
+ ThisDataPoint = DataToAdd(lngDataIndex)
+ XYSummationCount = XYSummationCount + 1
+ XYSummation(XYSummationCount) = ThisDataPoint
+ lngDataIndex = lngDataIndex + 1
+ Loop
+ End If
+
+ Next lngStickIndex
+
+ End With
+
+ ' Step through XYSummation and remove areas of sequential equivalent values
+ lngSummationIndex = 1
+ RoundToMultipleOf10 DeltaX, lngExponentValue
+ If lngExponentValue < 0 Then
+ intDigitsToRoundTo = Abs(lngExponentValue)
+ Else
+ intDigitsToRoundTo = 0
+ End If
+
+ ' #ToDo: Assure there is a data point at each 1% point along x range
+ ' Probably need to add data, but may need to remove some
+ dblMinimalXValSpacing = dblXValRange / 100
+
+ Do While lngSummationIndex <= XYSummationCount - 1
+ If XYSummation(lngSummationIndex).XVal + dblMinimalXValSpacing < XYSummation(lngSummationIndex + 1).XVal Then
+ ' Need to insert a data point
+ XYSummationCount = XYSummationCount + 1
+ CheckDynamicXYData XYSummation, XYSummationCount, XYSummationCountDimmed
+ For lngDataIndex = XYSummationCount To lngSummationIndex + 2 Step -1
+ XYSummation(lngDataIndex) = XYSummation(lngDataIndex - 1)
+ Next lngDataIndex
+ XYSummation(lngSummationIndex + 1).XVal = XYSummation(lngSummationIndex + 1).XVal + dblMinimalXValSpacing
+ XYSummation(lngSummationIndex + 1).YVal = (XYSummation(lngSummationIndex + 1).YVal + XYSummation(lngSummationIndex + 2).YVal) / 2
+ End If
+ lngSummationIndex = lngSummationIndex + 1
+ Loop
+
+
+ HideProgressForm
+
+ ' Reset the boolLongOperationsRequired bit
+ PlotOptions.boolLongOperationsRequired = False
+
+ ' ReDim XYSummation to XYSummationCount since DrawPlot assumes this is the case
+ XYSummationCountDimmed = XYSummationCount
+ ReDim Preserve XYSummation(XYSummationCountDimmed)
+
+ ' Assign data in XYSummation to the function so that it gets returned
+ ConvertStickDataToGaussian.XYDataList = XYSummation
+ ConvertStickDataToGaussian.XYDataListCount = XYSummationCount
+ ConvertStickDataToGaussian.XYDataListCountDimmed = XYSummationCountDimmed
+
+End Function
+
+Private Sub CheckDataLimitsAndSortData(ThisForm As Form, ThisXYData() As usrXYData, XYDataPointerArray() As Long, XYDataPointerArrayCount As Long, PlotOptions As usrPlotDataOptions)
+ Dim boolNeedsSorting As Boolean, lngIndex As Long
+ Dim dblMaximumIntensity As Double, dblMinimumIntensity As Double
+ Dim dblXYDataPoint As Double
+
+
+ If PlotOptions.DataLimits.y.ValStart.Val = 0 And PlotOptions.DataLimits.y.ValEnd.Val = 0 Then
+ ' Data Limits not defined
+ ' Figure out what they are and sort data if necessary
+
+ ' Find the Y scale data limits
+ ' At the same time, see if the data is sorted
+ dblMaximumIntensity = LowestValueForDataType
+ dblMinimumIntensity = HighestValueForDataType
+ boolNeedsSorting = False
+ For lngIndex = 1 To XYDataPointerArrayCount
+ dblXYDataPoint = ThisXYData(XYDataPointerArray(lngIndex)).YVal
+ If dblXYDataPoint > dblMaximumIntensity Then dblMaximumIntensity = dblXYDataPoint
+ If dblXYDataPoint < dblMinimumIntensity Then dblMinimumIntensity = dblXYDataPoint
+ If lngIndex < XYDataPointerArrayCount Then
+ If ThisXYData(XYDataPointerArray(lngIndex)).XVal > ThisXYData(XYDataPointerArray(lngIndex + 1)).XVal Then
+ boolNeedsSorting = True
+ End If
+ End If
+ Next lngIndex
+ PlotOptions.DataLimits.y.ValStart.Val = dblMinimumIntensity
+ PlotOptions.DataLimits.y.ValEnd.Val = dblMaximumIntensity
+
+ If boolNeedsSorting And PlotOptions.SortData Then
+ ' Need to sort data
+ ThisForm.MousePointer = vbHourglass
+ SortXYData ThisXYData(), XYDataPointerArray(), XYDataPointerArrayCount, False
+ End If
+ End If
+
+End Sub
+
+Public Sub DrawPlot(ThisForm As Form, PlotOptions As usrPlotDataOptions, ThisXYData() As usrXYData, ThisXYDataCount As Long, ByRef PlotRange As usrPlotRange)
+ ' Draw a graphical representation of a list of x,y data pairs
+ ' Assumes the x,y data point array is 1-based (i.e. the first data point is in index 1
+
+ Dim lngIndex As Long, lngLineIndex As Long
+ Dim PlotBottom As Long, lngLeftOffset As Long
+ Dim lngSecElapsedAtStart As Long
+ Dim intKeepEveryXthPoint As Integer, lngXYDataToCountTrack As Long
+
+ Const MaxLinesCount = 32000
+
+ Dim XYDataToPlot() As usrXYData, XYDataToPlotCount As Long
+
+ Dim XYDataPointerArray() As Long
+ Dim XYDataPointerArrayCount As Long, XYDataIndex As Long
+
+ Dim HighlightIndex As Long
+ Dim dblPreviousMinimum As Double
+ Dim lngChunkSize As Long, lngMinimumValIndex As Long, lngMaximumValIndex As Long
+ Dim boolNeedsSorting As Boolean
+
+ Dim StartXVal As Double, XValRange As Double, DeltaXScaler As Double
+ Dim StartXValIndex As Long, EndXValIndex As Long
+ Dim yvalRange As Double, DeltaYScaler As Double
+ Dim strWork As String, intExponentValue As Integer, dblWork As Double
+
+ Dim LastLabelTwip As Long, TwipsBetweenLabels As Long
+
+ If ThisXYDataCount < 1 Then Exit Sub
+
+ lngSecElapsedAtStart = Timer()
+
+ ' Initialize the pointer array
+ XYDataPointerArrayCount = ThisXYDataCount
+ ReDim XYDataPointerArray(XYDataPointerArrayCount)
+ For lngIndex = 1 To XYDataPointerArrayCount
+ XYDataPointerArray(lngIndex) = lngIndex
+ Next lngIndex
+
+ ' See if data is sorted; if not, sort it
+ CheckDataLimitsAndSortData ThisForm, ThisXYData(), XYDataPointerArray(), XYDataPointerArrayCount, PlotOptions
+
+ With PlotOptions
+
+ ' Determine the location in the parent frame of the bottom of the Plot
+ PlotBottom = .PlotTop + .PlotHeight
+
+ StartXValIndex = 1
+ EndXValIndex = ThisXYDataCount
+
+ ' Record the X scale data limits
+ .DataLimits.x.ValStart.Val = ThisXYData(XYDataPointerArray(StartXValIndex)).XVal
+ .DataLimits.x.ValEnd.Val = ThisXYData(XYDataPointerArray(EndXValIndex)).XVal
+
+ ' Initialize .Scaling.x.ValStart.Val and .Scaling.y.ValStart.Val if necessary
+ If .Scaling.x.ValStart.Val = 0 And .Scaling.x.ValEnd.Val = 0 Then
+ .Scaling.x.ValStart.Val = ThisXYData(XYDataPointerArray(StartXValIndex)).XVal
+ .Scaling.x.ValEnd.Val = ThisXYData(XYDataPointerArray(EndXValIndex)).XVal
+ End If
+
+ ' Make sure .Scaling.X.ValStart.Val < .Scaling.X.ValEnd
+ If .Scaling.x.ValStart.Val > .Scaling.x.ValEnd.Val Then
+ SwapValues .Scaling.x.ValStart.Val, .Scaling.x.ValEnd.Val
+ End If
+
+ If Not .ZoomOutFull Then
+ ' Step through ThisXYData and find index of the start x value
+ For lngIndex = 1 To ThisXYDataCount
+ If ThisXYData(XYDataPointerArray(lngIndex)).XVal >= .Scaling.x.ValStart.Val Then
+ StartXValIndex = lngIndex
+ Exit For
+ End If
+ Next lngIndex
+
+ ' Step through ThisXYData and find index of the end x value
+ For lngIndex = ThisXYDataCount To 1 Step -1
+ If ThisXYData(XYDataPointerArray(lngIndex)).XVal <= .Scaling.x.ValEnd.Val Then
+ EndXValIndex = lngIndex
+ Exit For
+ End If
+ Next lngIndex
+ End If
+
+ ' Make sure StartValIndex <= EndValIndex
+ If StartXValIndex > EndXValIndex Then
+ SwapValues StartXValIndex, EndXValIndex
+ End If
+
+ ' Check to see if Mouse Pointer should be changed to hourglass
+ CheckForLongOperation ThisForm, lngSecElapsedAtStart, PlotOptions
+
+ ' Copy the data into XYDataToPlot, reindexing to start at 1 and going to XYDataToPlotCount
+ ' Although this uses more memory because it duplicates the data, I soon replace the
+ ' raw data values with location positions in twips
+ '
+ ' In addition, if there is far more data than could be possibly plotted,
+ ' I throw away every xth data point, though with a twist
+
+ XYDataToPlotCount = EndXValIndex - StartXValIndex + 1
+
+ If XYDataToPlotCount > PlotOptions.PlotWidth / 10 Then
+ ' Throw away some of the data: Note that CInt will round 2.5 up to 3
+ intKeepEveryXthPoint = CInt(XYDataToPlotCount / (PlotOptions.PlotWidth / 10))
+ lngChunkSize = intKeepEveryXthPoint * 2
+ Else
+ intKeepEveryXthPoint = 1
+ End If
+
+ ReDim XYDataToPlot(CLngRoundUp(XYDataToPlotCount / intKeepEveryXthPoint) + 2)
+
+ If intKeepEveryXthPoint = 1 Then
+ lngXYDataToCountTrack = 0
+ For lngIndex = StartXValIndex To EndXValIndex
+ lngXYDataToCountTrack = lngXYDataToCountTrack + 1
+ XYDataToPlot(lngXYDataToCountTrack) = ThisXYData(XYDataPointerArray(lngIndex))
+ If XYDataPointerArray(lngIndex) = .IndexToHighlight Then
+ HighlightIndex = lngXYDataToCountTrack
+ End If
+ Next lngIndex
+ Else
+ ' Step through the data examining chunks of numbers twice the length of intKeepEveryXthPoint
+ ' Find the minimum and maximum value in each chunk of numbers
+ ' Store these values in the array to keep (minimum followed by maximum)
+ ' Swap the stored order if both numbers are less than the previous two numbers
+
+ ' Store the first value of ThisXYData() in the output array
+ lngXYDataToCountTrack = 1
+ XYDataToPlot(lngXYDataToCountTrack) = ThisXYData(XYDataPointerArray(StartXValIndex))
+ If XYDataPointerArray(StartXValIndex) = .IndexToHighlight Then
+ HighlightIndex = lngXYDataToCountTrack
+ End If
+
+ dblPreviousMinimum = LowestValueForDataType
+ For lngIndex = StartXValIndex + 1 To EndXValIndex - 1 Step lngChunkSize
+
+ FindMinimumAndMaximum lngMinimumValIndex, lngMaximumValIndex, ThisXYData(), XYDataPointerArray(), lngIndex, lngIndex + lngChunkSize
+
+ ' Check if the maximum value of this pair of points is less than the minimum value of the previous pair
+ ' If it is, the y values of the two points should be exchanged
+ If ThisXYData(XYDataPointerArray(lngMaximumValIndex)).YVal < dblPreviousMinimum Then
+ ' Update dblPreviousMinimum
+ dblPreviousMinimum = ThisXYData(XYDataPointerArray(lngMinimumValIndex)).YVal
+ ' Swap minimum and maximum so that maximum gets saved to array first
+ SwapValues lngMinimumValIndex, lngMaximumValIndex
+ Else
+ ' Update dblPreviousMinimum
+ dblPreviousMinimum = ThisXYData(XYDataPointerArray(lngMinimumValIndex)).YVal
+ End If
+
+ lngXYDataToCountTrack = lngXYDataToCountTrack + 1
+ XYDataToPlot(lngXYDataToCountTrack) = ThisXYData(XYDataPointerArray(lngMinimumValIndex))
+ If XYDataPointerArray(lngMinimumValIndex) = .IndexToHighlight Then
+ HighlightIndex = lngXYDataToCountTrack
+ End If
+
+ lngXYDataToCountTrack = lngXYDataToCountTrack + 1
+ XYDataToPlot(lngXYDataToCountTrack) = ThisXYData(XYDataPointerArray(lngMaximumValIndex))
+ If XYDataPointerArray(lngMaximumValIndex) = .IndexToHighlight Then
+ HighlightIndex = lngXYDataToCountTrack
+ End If
+
+ ' Now check to see if the .XVal of the first value is greater than the first
+ ' If so, swap the .XVals
+ If XYDataToPlot(lngXYDataToCountTrack - 1).XVal > XYDataToPlot(lngXYDataToCountTrack).XVal Then
+ SwapValues XYDataToPlot(lngXYDataToCountTrack - 1).XVal, XYDataToPlot(lngXYDataToCountTrack).XVal
+ End If
+ Next lngIndex
+
+ ' Store the last value of ThisXYData() in the output array
+ lngXYDataToCountTrack = lngXYDataToCountTrack + 1
+ XYDataToPlot(lngXYDataToCountTrack) = ThisXYData(XYDataPointerArray(EndXValIndex))
+ If XYDataPointerArray(EndXValIndex) = .IndexToHighlight Then
+ HighlightIndex = lngXYDataToCountTrack
+ End If
+
+ End If
+
+ ' Set XYDataToPlotCount to the lngXYDataToCountTrack value resulting from the copying
+ XYDataToPlotCount = lngXYDataToCountTrack
+
+ End With
+
+ ' Scale the data vertically according to PlotOptions.height
+ ' i.e., replace the actual y values with locations in twips for where the data point belongs on the graph
+ ' The new value will range from 0 to PlotOptions.Height
+ ' Note that PlotOptions.PlotLeftLargeNumberOffset is computed in ScaleData for the Y axis
+ ScaleData PlotOptions, XYDataToPlot(), XYDataToPlotCount, PlotRange.y, PlotOptions.Scaling.y, False, PlotOptions.AutoScaleY
+
+ ' Now scale the data to twips, ranging 0 to .PlotWidth and 0 to .PlotHeight
+ ' X axis
+ ScaleData PlotOptions, XYDataToPlot(), XYDataToPlotCount, PlotRange.x, PlotOptions.Scaling.x, True, False
+
+ ' Load lines and labels for each XVal
+ If PlotOptions.LinesLoadedCount = 0 Then
+ ' Only initialize to 1 the first time this sub is called
+ PlotOptions.LinesLoadedCount = 1
+ End If
+
+ ' Limit the total points shown if greater than MaxLinesCount
+ If XYDataToPlotCount > MaxLinesCount Then
+ XYDataToPlotCount = MaxLinesCount
+ Debug.Assert False
+ End If
+
+ ' Load dynamic plot objects as needed
+ LoadDynamicPlotObjects ThisForm, PlotOptions, XYDataToPlotCount
+
+ ' Must re-initialize the pointer array
+ XYDataPointerArrayCount = XYDataToPlotCount
+ ReDim XYDataPointerArray(XYDataToPlotCount)
+ For lngIndex = 1 To XYDataToPlotCount
+ XYDataPointerArray(lngIndex) = lngIndex
+ Next lngIndex
+
+ If PlotOptions.PlotTypeCode = 0 Then
+ ' Plot the data as sticks to zero
+ If PlotOptions.ShowDataPointLabels And PlotOptions.LabelsToShow > 0 Then
+ ' Sort the data by YVal, draw in order of YVal, and only label top specified peaks
+ SortXYData XYDataToPlot, XYDataPointerArray, XYDataPointerArrayCount, True
+ End If
+ Else
+ ' Plot the data as lines between points
+ ' Plot in order of XVal, thus, don't need to sort
+ PlotOptions.ShowDataPointLabels = False
+ End If
+
+ ' Check to see if Mouse Pointer should be changed to hourglass
+ CheckForLongOperation ThisForm, lngSecElapsedAtStart, PlotOptions
+
+ ' Label the axes and add ticks and gridlines
+ FormatAxes ThisForm, PlotOptions, PlotBottom, PlotRange
+
+ ' Position the lines and labels
+ LastLabelTwip = 0
+ With ThisForm
+ lngLeftOffset = PlotOptions.PlotLeft + PlotOptions.PlotLeftLargeNumberOffset
+
+ For lngIndex = 1 To XYDataToPlotCount
+ If lngIndex Mod 50 = 0 Then
+ ' Check to see if Mouse Pointer should be changed to hourglass
+ CheckForLongOperation ThisForm, lngSecElapsedAtStart, PlotOptions
+ End If
+
+ XYDataIndex = XYDataPointerArray(lngIndex)
+
+ .linData(XYDataIndex).Visible = True
+
+ If PlotOptions.PlotTypeCode = 0 Then
+ ' Plot the data as sticks to zero
+
+ .linData(XYDataIndex).x1 = lngLeftOffset + XYDataToPlot(XYDataIndex).XVal
+ .linData(XYDataIndex).x2 = .linData(XYDataIndex).x1
+ .linData(XYDataIndex).y1 = PlotBottom
+ .linData(XYDataIndex).y2 = PlotBottom - XYDataToPlot(XYDataIndex).YVal
+ If HighlightIndex = XYDataIndex Then
+ .linData(XYDataIndex).BorderColor = PlotOptions.HighlightColor
+ Else
+ .linData(XYDataIndex).BorderColor = vbBlack
+ End If
+ Else
+ ' Plot the data as lines between points
+ If lngIndex < XYDataToPlotCount Then
+ .linData(XYDataIndex).x1 = lngLeftOffset + XYDataToPlot(XYDataIndex).XVal
+ .linData(XYDataIndex).x2 = lngLeftOffset + XYDataToPlot(XYDataIndex + 1).XVal
+ .linData(XYDataIndex).y1 = PlotBottom - XYDataToPlot(XYDataIndex).YVal
+ .linData(XYDataIndex).y2 = PlotBottom - XYDataToPlot(XYDataIndex + 1).YVal
+ .linData(XYDataIndex).BorderColor = vbBlack
+ Else
+ .linData(XYDataIndex).Visible = False
+ End If
+ End If
+
+ If PlotOptions.ShowDataPointLabels Then
+
+ If XYDataIndex = HighlightIndex Or lngIndex <= PlotOptions.LabelsToShow Then
+ LastLabelTwip = .lblPlotIntensity(XYDataIndex).Left
+ .lblPlotIntensity(XYDataIndex).Visible = True
+ .lblPlotIntensity(XYDataIndex).Tag = "Visible"
+ If XYDataIndex = HighlightIndex Then
+ ' Include charge in label
+ .lblPlotIntensity(XYDataIndex).Caption = Format(ThisXYData(StartXValIndex + XYDataIndex - 1).XVal, "0.0000")
+ .lblPlotIntensity(XYDataIndex).Width = 1200
+ Else
+ .lblPlotIntensity(XYDataIndex).Caption = Format(ThisXYData(StartXValIndex + XYDataIndex - 1).XVal, "0.0000")
+ .lblPlotIntensity(XYDataIndex).Width = 800
+ End If
+ .lblPlotIntensity(XYDataIndex).ToolTipText = Format(ThisXYData(StartXValIndex + XYDataIndex - 1).XVal, "0.0000")
+ .lblPlotIntensity(XYDataIndex).Height = 200
+ .lblPlotIntensity(XYDataIndex).Top = .linData(XYDataIndex).y2 - .lblPlotIntensity(XYDataIndex).Height
+ .lblPlotIntensity(XYDataIndex).Left = .linData(XYDataIndex).x1 - 200
+ Else
+ .lblPlotIntensity(XYDataIndex).Visible = True
+ .lblPlotIntensity(XYDataIndex).Tag = "Hidden"
+ .lblPlotIntensity(XYDataIndex).Caption = ""
+ .lblPlotIntensity(XYDataIndex).ToolTipText = Format(ThisXYData(StartXValIndex + XYDataIndex - 1).XVal, "0.0000")
+ .lblPlotIntensity(XYDataIndex).Width = 50
+ .lblPlotIntensity(XYDataIndex).Height = Abs(.linData(XYDataIndex).y1 - .linData(XYDataIndex).y2)
+ .lblPlotIntensity(XYDataIndex).Top = .linData(XYDataIndex).y2
+ .lblPlotIntensity(XYDataIndex).Left = .linData(XYDataIndex).x2
+ End If
+ Else
+ .lblPlotIntensity(XYDataIndex).Visible = False
+ End If
+ Next lngIndex
+
+ If lngIndex < PlotOptions.LinesLoadedCount Then
+ ' Hide the other lines and labels
+ For lngLineIndex = lngIndex To PlotOptions.LinesLoadedCount
+ .linData(lngLineIndex).Visible = False
+ .lblPlotIntensity(lngLineIndex).Visible = False
+ Next lngLineIndex
+ End If
+
+ End With
+
+ If PlotOptions.ShowDataPointLabels Then
+ TwipsBetweenLabels = "0.5" * DeltaXScaler * XValRange
+ RepositionDataLabels ThisForm, XYDataToPlotCount, TwipsBetweenLabels, LastLabelTwip
+ End If
+
+End Sub
+
+Private Sub FindMinimumAndMaximum(lngMinimumValIndex As Long, lngMaximumValIndex As Long, ThisXYData() As usrXYData, XYDataPointerArray() As Long, lngStartIndex As Long, lngStopIndex As Long)
+ Dim lngIndex As Long, XYDataPoint As Long
+ Dim dblMinimumVal As Double, dblMaximumVal As Double
+
+ If lngStopIndex > UBound(ThisXYData()) Then
+ lngStopIndex = UBound(ThisXYData())
+ End If
+
+ lngMinimumValIndex = lngStartIndex
+ lngMaximumValIndex = lngStartIndex
+
+ dblMaximumVal = ThisXYData(XYDataPointerArray(lngStartIndex)).YVal
+ dblMinimumVal = ThisXYData(XYDataPointerArray(lngStartIndex)).YVal
+
+ For lngIndex = lngStartIndex + 1 To lngStopIndex
+ XYDataPoint = ThisXYData(XYDataPointerArray(lngIndex)).YVal
+ If XYDataPoint < dblMinimumVal Then
+ dblMinimumVal = XYDataPoint
+ lngMinimumValIndex = lngIndex
+ End If
+ If XYDataPoint > dblMaximumVal Then
+ dblMaximumVal = XYDataPoint
+ lngMaximumValIndex = lngIndex
+ End If
+ Next lngIndex
+
+ If lngMinimumValIndex = lngMaximumValIndex Then
+ ' All of the data was the same
+ ' Set lngMaximumValIndex to the halfway-point index between lngStopIndex and lngStartIndex
+ lngMaximumValIndex = lngStartIndex + (lngStopIndex - lngStartIndex) / 2
+ End If
+End Sub
+
+Private Sub FormatAxes(ThisForm As Form, PlotOptions As usrPlotDataOptions, PlotBottom As Long, PlotRange As usrPlotRange)
+ Dim intInitialTickIndex As Integer, intInitialTickMinorIndex As Integer
+ Dim lngRightOrTopMostPos As Long
+
+ With ThisForm
+ ' Position the x axis
+ .linXAxis.x1 = PlotOptions.PlotLeft + PlotOptions.PlotLeftLargeNumberOffset
+ .linXAxis.x2 = PlotOptions.PlotLeft + PlotOptions.PlotWidth + 50
+ .linXAxis.y1 = PlotBottom + 50
+ .linXAxis.y2 = PlotBottom + 50
+ .linXAxis.Visible = PlotOptions.XAxis.Show
+
+ ' Position the y axis
+ .linYAxis.x1 = PlotOptions.PlotLeft + PlotOptions.PlotLeftLargeNumberOffset
+ .linYAxis.x2 = PlotOptions.PlotLeft + PlotOptions.PlotLeftLargeNumberOffset
+ .linYAxis.y1 = PlotBottom + 50
+ .linYAxis.y2 = PlotOptions.PlotTop - 50
+ .linYAxis.Visible = PlotOptions.YAxis.Show
+ End With
+
+ ' Note: The x and y axes share the same dynamic lines for major and minor tick marks,
+ ' gridlines, and labels. The x axis objects will start with index 1 of each object type
+ ' the intInitialTickIndex and intInitialTickMinorIndex values will be modified by sub
+ ' FormatThisAxis during the creation of the objects for the x axis so that they will
+ ' be the value of the next unused object for operations involving the y axis
+ intInitialTickIndex = 0
+ intInitialTickMinorIndex = 0
+ FormatThisAxis ThisForm, PlotOptions, True, PlotOptions.XAxis, PlotRange.x, intInitialTickIndex, intInitialTickMinorIndex, lngRightOrTopMostPos
+ If lngRightOrTopMostPos > ThisForm.linXAxis.x2 Then
+ ThisForm.linXAxis.x2 = lngRightOrTopMostPos + 50
+ End If
+
+ FormatThisAxis ThisForm, PlotOptions, False, PlotOptions.YAxis, PlotRange.y, intInitialTickIndex, intInitialTickMinorIndex, lngRightOrTopMostPos
+ If lngRightOrTopMostPos < ThisForm.linYAxis.y2 Then
+ ThisForm.linYAxis.y2 = lngRightOrTopMostPos - 50
+ End If
+
+End Sub
+
+Private Function FindDigitsInLabelUsingRange(PlotRangeForAxis As usrPlotRangeAxis, intMajorTicksToShow As Integer, ByRef strFormatString As String) As Integer
+ Dim ValRange As Double, DeltaVal As Double, lngExponentValue As Long
+ Dim intDigitsInStartNumber As Integer, intDigitsInEndNumber As Integer
+
+ With PlotRangeForAxis
+ ValRange = .ValEnd.Val - .ValStart.Val
+ End With
+
+ If intMajorTicksToShow = 0 Then
+ DeltaVal = ValRange
+ Else
+ ' Take ValRange divided by intMajorTicksToShow
+ DeltaVal = ValRange / intMajorTicksToShow
+ End If
+
+ ' Round DeltaVal to nearest 1, 2, or 5 (or multiple of 10 thereof)
+ DeltaVal = RoundToMultipleOf10(DeltaVal, lngExponentValue)
+
+ strFormatString = ConstructFormatString(DeltaVal)
+
+ ' Note: I use the absolute value of ValEnd so that all tick labels will have the
+ ' same width, positive or negative
+ intDigitsInStartNumber = Len(Trim(Format(Abs(PlotRangeForAxis.ValStart.Val), strFormatString))) + 1
+ intDigitsInEndNumber = Len(Trim(Format(Abs(PlotRangeForAxis.ValEnd.Val), strFormatString))) + 1
+
+ If intDigitsInEndNumber > intDigitsInStartNumber Then
+ FindDigitsInLabelUsingRange = intDigitsInEndNumber
+ Else
+ FindDigitsInLabelUsingRange = intDigitsInStartNumber
+ End If
+
+End Function
+
+Private Sub FormatThisAxis(ThisForm As Form, PlotOptions As usrPlotDataOptions, boolXAxis As Boolean, AxisOptions As usrAxisOptions, PlotRangeForAxis As usrPlotRangeAxis, ByRef intInitialTickIndex As Integer, ByRef intInitialTickMinorIndex As Integer, lngRightOrTopMostPos As Long)
+ Dim objTickMajor As Line
+
+ Dim intMajorTicksToShow As Integer
+ Dim intMinorTicksPerMajorTick As Integer, intMinorTicksRequired As Integer
+ Dim intTickIndex As Integer, intTickIndexToHide As Integer
+ Dim intKeepEveryXthTick As Integer
+ Dim intTickIndexMinor As Integer, intTickIndexMinorTrack As Integer
+ Dim lngAddnlMinorTickPos As Long, lngAddnlMinorTickStopPos As Long
+ Dim PosStart As Long, DeltaPos As Double, DeltaPosMinor As Double
+ Dim ValStart As Double, ValEnd As Double, ValRange As Double, DeltaVal As Double
+ Dim LengthStartPos As Long, LengthEndPos As Long, GridlineEndPos As Long
+ Dim LengthStartPosMinor As Long, LengthEndPosMinor As Long
+ Dim intDigitsInLabel As Integer
+
+ Dim strFormatString As String, intTickLabelWidth As Integer
+
+ ' Position and label the x axis major tick marks and labels
+ intMajorTicksToShow = AxisOptions.MajorTicksToShow
+ If intMajorTicksToShow < 2 Then
+ intMajorTicksToShow = 2
+ AxisOptions.MajorTicksToShow = intMajorTicksToShow
+ End If
+
+ With PlotRangeForAxis
+ ValStart = .ValStart.Val
+ ValEnd = .ValEnd.Val
+ ValRange = ValEnd - ValStart
+ End With
+
+ ' Take ValRange divided by intMajorTicksToShow
+ DeltaVal = ValRange / intMajorTicksToShow
+
+ ' Round DeltaVal to nearest 1, 2, or 5 (or multiple of 10 thereof)
+ DeltaVal = RoundToMultipleOf10(DeltaVal)
+
+ ' If ValStart is not an even multiple of DeltaVal then bump up ValStart until it is
+ ValStart = RoundToEvenMultiple(ValStart, DeltaVal, True)
+
+ ' Do the same for ValEnd, but bump down instead
+ ValEnd = RoundToEvenMultiple(ValEnd, DeltaVal, False)
+
+ ' Recompute ValRange
+ ValRange = ValEnd - ValStart
+
+ ' Determine actual number of ticks to show
+ intMajorTicksToShow = ValRange / DeltaVal + 1
+
+ ' Convert ValStart to ValPos
+ PosStart = XYValueToPos(ValStart, PlotRangeForAxis, False)
+
+ ' Convert DeltaVal to DeltaPos
+ DeltaPos = XYValueToPos(DeltaVal, PlotRangeForAxis, True)
+
+ If boolXAxis Then
+ LengthStartPos = ThisForm.linXAxis.y1 + 200
+ LengthEndPos = ThisForm.linXAxis.y1
+ Else
+ LengthStartPos = ThisForm.linYAxis.x1 - 200
+ LengthEndPos = ThisForm.linYAxis.x1
+ End If
+
+ With AxisOptions
+ If .ShowMinorTicks Then
+ ' Insert 1, 4, or 9 minor ticks, depending on whether they'll fit
+ intMinorTicksPerMajorTick = 0
+ Do
+ Select Case intMinorTicksPerMajorTick
+ Case 0: intMinorTicksPerMajorTick = 9
+ Case 9: intMinorTicksPerMajorTick = 4
+ Case 4: intMinorTicksPerMajorTick = 1
+ Case Else
+ intMinorTicksPerMajorTick = 0
+ Exit Do
+ End Select
+ DeltaPosMinor = DeltaPos / (intMinorTicksPerMajorTick + 1)
+ Loop While Abs(DeltaPosMinor) < .MinorTickMinimumPixelSep
+ Else
+ DeltaPosMinor = 0
+ End If
+
+ If boolXAxis Then
+ LengthStartPosMinor = LengthStartPos - 150
+ LengthEndPosMinor = LengthEndPos
+ Else
+ LengthStartPosMinor = LengthStartPos + 100
+ LengthEndPosMinor = LengthEndPos
+ End If
+
+ If .ShowGridLinesMajor Then
+ If boolXAxis Then
+ GridlineEndPos = PlotOptions.PlotTop
+ Else
+ GridlineEndPos = PlotOptions.PlotLeft + PlotOptions.PlotWidth
+ End If
+ Else
+ GridlineEndPos = LengthEndPos
+ End If
+ End With
+
+ ' Initialize PlotOptions.MajorTicksLoaded and PlotOptions.MinorTicksLoaded if needed
+ If PlotOptions.MajorTicksLoaded = 0 Then PlotOptions.MajorTicksLoaded = 1 ' There is always at least 1 loaded
+ If PlotOptions.MinorTicksLoaded = 0 Then PlotOptions.MinorTicksLoaded = 1 ' There is always at least 1 loaded
+
+ ' Call FindDigitsInLabelUsingRange to determine the digits in the label and construct the format string
+ intDigitsInLabel = FindDigitsInLabelUsingRange(PlotRangeForAxis, intMajorTicksToShow, strFormatString)
+
+ ' Each number requires 90 pixels
+ intTickLabelWidth = intDigitsInLabel * NUM_TWIPS_PER_DIGIT
+
+ intTickIndexMinorTrack = intInitialTickMinorIndex
+ For intTickIndex = intInitialTickIndex + 1 To intInitialTickIndex + intMajorTicksToShow
+
+ With AxisOptions
+ If PlotOptions.MajorTicksLoaded < intTickIndex Then
+ PlotOptions.MajorTicksLoaded = PlotOptions.MajorTicksLoaded + 1
+ Load ThisForm.linTickMajor(PlotOptions.MajorTicksLoaded)
+ Load ThisForm.lblTick(PlotOptions.MajorTicksLoaded)
+ Load ThisForm.linGridline(PlotOptions.MajorTicksLoaded)
+ End If
+ End With
+
+ With ThisForm.linTickMajor(intTickIndex)
+ .x1 = PosStart + CLng(((intTickIndex - intInitialTickIndex) - 1) * DeltaPos)
+ .x2 = .x1
+ .y1 = LengthStartPos
+ .y2 = LengthEndPos
+ .Visible = True
+ End With
+ Set objTickMajor = ThisForm.linTickMajor(intTickIndex)
+ With ThisForm.linGridline(intTickIndex)
+ .x1 = objTickMajor.x1
+ .x2 = objTickMajor.x2
+ .y1 = objTickMajor.y1
+ .y2 = GridlineEndPos
+ .Visible = True
+ End With
+
+ lngRightOrTopMostPos = LengthEndPos
+ If Not boolXAxis Then
+ SwapLineCoordinates ThisForm.linTickMajor(intTickIndex)
+ SwapLineCoordinates ThisForm.linGridline(intTickIndex)
+ Set objTickMajor = ThisForm.linTickMajor(intTickIndex)
+ End If
+
+ With ThisForm.lblTick(intTickIndex)
+ .Width = intTickLabelWidth
+ .Caption = Format(ValStart + CDbl((intTickIndex - intInitialTickIndex) - 1) * DeltaVal, strFormatString)
+ .Visible = True
+ If boolXAxis Then
+ .Top = objTickMajor.y1 + 50
+ .Left = objTickMajor.x1 - .Width / 2
+ Else
+ .Top = objTickMajor.y1 - .Height / 2
+ .Left = objTickMajor.x1 - .Width - 50
+ .Alignment = vbRightJustify
+ End If
+ End With
+
+ If ValStart + ((intTickIndex - intInitialTickIndex) - 1) * DeltaVal > PlotRangeForAxis.ValEnd.Val Then
+ ' Tick and/or label is past the end of the axis; Do not keep labeling
+ ' Before exitting for loop, must add 1 to intTickIndex since it will normally
+ ' exit the for loop with a value of intMajorTicksToShow + 1, but we are exiting prematurely
+ intTickIndex = intTickIndex + 1
+ Exit For
+ End If
+
+ With AxisOptions
+ ' Load minor ticks as needed
+ intMinorTicksRequired = intTickIndexMinorTrack + intMinorTicksPerMajorTick
+ Do While PlotOptions.MinorTicksLoaded < intMinorTicksRequired
+ PlotOptions.MinorTicksLoaded = PlotOptions.MinorTicksLoaded + 1
+ Load ThisForm.linTickMinor(PlotOptions.MinorTicksLoaded)
+ Loop
+ End With
+
+ For intTickIndexMinor = 1 To intMinorTicksPerMajorTick
+ intTickIndexMinorTrack = intTickIndexMinorTrack + 1
+ If boolXAxis Then
+ lngAddnlMinorTickPos = objTickMajor.x1 + DeltaPosMinor * intTickIndexMinor
+ Else
+ lngAddnlMinorTickPos = objTickMajor.y1 + DeltaPosMinor * intTickIndexMinor
+ End If
+
+ lngRightOrTopMostPos = lngAddnlMinorTickPos
+
+ ' Add the minor tick mark
+ AddMinorTickmark ThisForm, intTickIndexMinor, intTickIndexMinorTrack, lngAddnlMinorTickPos, LengthStartPosMinor, LengthEndPosMinor, boolXAxis
+ Next intTickIndexMinor
+ Next intTickIndex
+
+ ' See if minor ticks can be added before the first major tick
+ If AxisOptions.ShowMinorTicks Then
+ If boolXAxis Then
+ lngAddnlMinorTickPos = ThisForm.linTickMajor(1).x1
+ lngAddnlMinorTickStopPos = ThisForm.linXAxis.x1
+ Else
+ lngAddnlMinorTickPos = ThisForm.linTickMajor(intInitialTickIndex + 1).y1
+ lngAddnlMinorTickStopPos = ThisForm.linYAxis.y1
+ End If
+
+ intTickIndexMinor = 1
+ ' This loop will execute at most 50 times
+ ' Most likely, it will only execute a few times before the Exit Do clause becomes true
+ Do While intTickIndexMinor < 50
+ If boolXAxis Then
+ If lngAddnlMinorTickPos - Abs(DeltaPosMinor) <= lngAddnlMinorTickStopPos Then Exit Do
+ lngAddnlMinorTickPos = lngAddnlMinorTickPos - Abs(DeltaPosMinor)
+ Else
+ If lngAddnlMinorTickPos + Abs(DeltaPosMinor) >= lngAddnlMinorTickStopPos Then Exit Do
+ lngAddnlMinorTickPos = lngAddnlMinorTickPos + Abs(DeltaPosMinor)
+ End If
+
+ intTickIndexMinor = intTickIndexMinor + 1
+ intTickIndexMinorTrack = intTickIndexMinorTrack + 1
+
+ ' May need to load more minor ticks
+ If PlotOptions.MinorTicksLoaded < intTickIndexMinorTrack Then
+ PlotOptions.MinorTicksLoaded = PlotOptions.MinorTicksLoaded + 1
+ Load ThisForm.linTickMinor(PlotOptions.MinorTicksLoaded)
+ End If
+
+ ' Add the minor tick mark
+ AddMinorTickmark ThisForm, intTickIndexMinor, intTickIndexMinorTrack, lngAddnlMinorTickPos, LengthStartPosMinor, LengthEndPosMinor, boolXAxis
+ Loop
+ End If
+
+ With ThisForm
+ ' Check for overlapping tick labels
+ ' If there is overlap, then show every other or every 5th label
+ intKeepEveryXthTick = 1
+ If intMajorTicksToShow >= 3 Then
+ If boolXAxis Then
+ If .lblTick(1).Left + .lblTick(1).Width > .lblTick(3).Left Then intKeepEveryXthTick = 5
+ Else
+ If .lblTick(intInitialTickIndex + 3).Top + .lblTick(intInitialTickIndex + 3).Height > .lblTick(intInitialTickIndex + 1).Top Then intKeepEveryXthTick = 5
+ End If
+ End If
+
+ If intKeepEveryXthTick = 1 And intMajorTicksToShow >= 2 Then
+ If boolXAxis Then
+ If .lblTick(1).Left + .lblTick(1).Width > .lblTick(2).Left Then intKeepEveryXthTick = 2
+ Else
+ If .lblTick(intInitialTickIndex + 2).Top + .lblTick(intInitialTickIndex + 2).Height > .lblTick(intInitialTickIndex + 1).Top Then intKeepEveryXthTick = 2
+ End If
+ End If
+
+ If intKeepEveryXthTick > 1 Then
+ For intTickIndexToHide = intInitialTickIndex + 1 To intInitialTickIndex + intMajorTicksToShow
+ If intTickIndexToHide Mod intKeepEveryXthTick <> 0 Then
+ .lblTick(intTickIndexToHide).Visible = False
+ End If
+ Next intTickIndexToHide
+ End If
+ End With
+
+ ' Store intTickIndex in intInitialTickIndex
+ intInitialTickIndex = intTickIndex - 1
+
+ ' Store intTickIndexMinorTrack in intInitialTickMinorIndex
+ intInitialTickMinorIndex = intTickIndexMinorTrack
+
+
+ With ThisForm
+ ' Hide remaining loaded ticks
+ For intTickIndexToHide = intInitialTickIndex + 1 To PlotOptions.MajorTicksLoaded
+ .linTickMajor(intTickIndexToHide).Visible = False
+ .linGridline(intTickIndexToHide).Visible = False
+ .lblTick(intTickIndexToHide).Visible = False
+ Next intTickIndexToHide
+
+ For intTickIndexToHide = intInitialTickMinorIndex + 1 To PlotOptions.MinorTicksLoaded
+ .linTickMinor(intTickIndexToHide).Visible = False
+ Next intTickIndexToHide
+ End With
+
+End Sub
+
+Private Sub AddMinorTickmark(ThisForm As Form, intTickIndexMinor As Integer, intTickIndexMinorTrack As Integer, lngAddnlMinorTickPos As Long, LengthStartPosMinor As Long, LengthEndPosMinor As Long, boolXAxis As Boolean)
+ With ThisForm.linTickMinor(intTickIndexMinorTrack)
+ .x1 = lngAddnlMinorTickPos
+ .x2 = .x1
+ .y1 = LengthStartPosMinor + 20
+ .y2 = LengthEndPosMinor
+ If intTickIndexMinor Mod 5 = 0 Then
+ ' Draw the minor tick mark a little longer
+ If boolXAxis Then
+ .y1 = .y1 + 70
+ .y2 = .y2
+ Else
+ .y1 = .y1 - 50
+ .y2 = .y2
+ End If
+ End If
+ .Visible = True
+ End With
+
+ If Not boolXAxis Then SwapLineCoordinates ThisForm.linTickMinor(intTickIndexMinorTrack)
+
+End Sub
+
+
+Private Sub LoadDynamicPlotObjects(ThisForm As Form, PlotOptions As usrPlotDataOptions, XYDataToPlotCount As Long)
+ Dim lngLinesLoadedCountPrevious As Long
+ Dim boolShowProgress As Boolean
+
+ With ThisForm
+ ' Load lines for data points if needed
+ If PlotOptions.LinesLoadedCount < XYDataToPlotCount Then
+ lngLinesLoadedCountPrevious = PlotOptions.LinesLoadedCount
+ If Abs(XYDataToPlotCount - lngLinesLoadedCountPrevious) > 100 Then
+ boolShowProgress = True
+ frmProgress.InitializeForm "Preparing graph", 0, Abs(XYDataToPlotCount - lngLinesLoadedCountPrevious)
+ End If
+
+ Do While PlotOptions.LinesLoadedCount < XYDataToPlotCount
+ If boolShowProgress Then
+ If PlotOptions.LinesLoadedCount Mod 10 = 0 Then frmProgress.UpdateProgressBar Abs(PlotOptions.LinesLoadedCount - lngLinesLoadedCountPrevious)
+ End If
+
+ PlotOptions.LinesLoadedCount = PlotOptions.LinesLoadedCount + 1
+ Load .linData(PlotOptions.LinesLoadedCount)
+ Load .lblPlotIntensity(PlotOptions.LinesLoadedCount)
+ .lblPlotIntensity(PlotOptions.LinesLoadedCount).Height = 200
+ Loop
+ If boolShowProgress Then frmProgress.Hide
+ End If
+ End With
+
+End Sub
+
+Public Sub Main()
+ frmMsPlot.Show
+
+End Sub
+
+Private Sub RepositionDataLabels(ThisForm As Form, XYDataToPlotCount As Long, TwipsBetweenLabels As Long, LastLabelTwip As Long)
+ Dim LabelLocPointerArray() As Long, LabelLocPointerArrayCount As Long
+ Dim LabelShiftedCount As Integer, LabelShifted As Boolean
+
+ Dim lngIndex As Integer
+
+ With ThisForm
+ ' Reposition the labels
+ ReDim LabelLocPointerArray(XYDataToPlotCount)
+ LabelLocPointerArrayCount = 0
+ For lngIndex = 1 To XYDataToPlotCount
+ If .lblPlotIntensity(lngIndex).Tag = "Visible" Then
+ LabelLocPointerArrayCount = LabelLocPointerArrayCount + 1
+ LabelLocPointerArray(LabelLocPointerArrayCount) = lngIndex
+ End If
+ Next lngIndex
+
+ LabelShiftedCount = 0
+ Do
+ LabelShiftedCount = LabelShiftedCount + 1
+ LabelShifted = False
+ ' sort the Pointer Array
+ SortLabelLoc ThisForm, LabelLocPointerArray(), LabelLocPointerArrayCount
+
+ ' Step through labels from the one at the bottom to the one at the top and shift upward if needed
+ For lngIndex = 1 To LabelLocPointerArrayCount - 1
+ If .lblPlotIntensity(LabelLocPointerArray(lngIndex + 1)).Top + .lblPlotIntensity(LabelLocPointerArray(lngIndex + 1)).Height > .lblPlotIntensity(lngIndex).Top And .lblPlotIntensity(lngIndex + 1).Top < .lblPlotIntensity(LabelLocPointerArray(lngIndex)).Top Then
+ ' May Need to shift upward; see if adjacent
+ If Abs(LabelLocPointerArray(lngIndex + 1) - LabelLocPointerArray(lngIndex)) = 1 Then
+ ' Yes, they're adjacent; shift upward
+ .lblPlotIntensity(LabelLocPointerArray(lngIndex + 1)).Top = .lblPlotIntensity(LabelLocPointerArray(lngIndex)).Top - .lblPlotIntensity(LabelLocPointerArray(lngIndex + 1)).Height
+ LabelShifted = True
+ End If
+ End If
+ Next lngIndex
+ Loop While LabelShifted And LabelShiftedCount < 5
+ End With
+
+End Sub
+
+Private Function RoundToEvenMultiple(ByVal dblValueToRound As Double, ByVal MultipleValue As Double, ByVal boolRoundUp As Boolean) As Double
+ Dim intLoopCount As Integer
+ Dim strWork As String, dblWork As Double
+ Dim lngExponentValue As Long
+
+ ' Find the exponent of MultipleValue
+ strWork = Format(MultipleValue, "0E+000")
+ lngExponentValue = CInt(Right(strWork, 4))
+
+ intLoopCount = 0
+ Do While Trim(Str(dblValueToRound / MultipleValue)) <> Trim(Str(Round(dblValueToRound / MultipleValue, 0)))
+ dblWork = dblValueToRound / 10 ^ (lngExponentValue)
+ dblWork = CLng(dblWork)
+ dblWork = dblWork * 10 ^ (lngExponentValue)
+ If boolRoundUp Then
+ If dblWork <= dblValueToRound Then
+ dblWork = dblWork + 10 ^ lngExponentValue
+ End If
+ Else
+ If dblWork >= dblValueToRound Then
+ dblWork = dblWork - 10 ^ lngExponentValue
+ End If
+ End If
+ dblValueToRound = dblWork
+ intLoopCount = intLoopCount + 1
+ If intLoopCount > 500 Then
+ ' Bug
+' Debug.Assert False
+ Exit Do
+ End If
+ Loop
+
+ RoundToEvenMultiple = dblValueToRound
+End Function
+
+Public Function RoundToMultipleOf10(ByVal dblThisNum As Double, Optional ByRef lngExponentValue As Long) As Double
+ Dim strWork As String, dblWork As Double
+
+ ' Round to nearest 1, 2, or 5 (or multiple of 10 thereof)
+ ' First, find the exponent of dblThisNum
+ strWork = Format(dblThisNum, "0E+000")
+ lngExponentValue = CInt(Right(strWork, 4))
+ dblWork = dblThisNum / 10 ^ lngExponentValue
+ dblWork = Int(dblWork)
+
+ ' dblWork should now be between 0 and 9
+ Select Case dblWork
+ Case 0, 1: dblThisNum = 1
+ Case 2 To 4: dblThisNum = 2
+ Case Else: dblThisNum = 5
+ End Select
+
+ ' Convert dblThisNum back to the correct magnitude
+ dblThisNum = dblThisNum * 10 ^ lngExponentValue
+
+ RoundToMultipleOf10 = dblThisNum
+End Function
+
+Private Sub ScaleData(PlotOptions As usrPlotDataOptions, XYDataToPlot() As usrXYData, XYDataToPlotCount As Long, ByRef ThisAxisRange As usrPlotRangeAxis, ThisAxisScaling As usrPlotRangeAxis, boolIsXAxis As Boolean, boolAutoScaleAxis As Boolean)
+
+ Dim dblMaximumIntensity As Double, dblMinimumIntensity As Double
+ Dim lngIndex As Long, dblDataPoint As Double
+ Dim dblValRange As Double, dblDeltaScaler As Double, ThisAxisWindowLength As Long
+ Dim strFormatString As String, intDigitsInLabel As Integer
+
+ ' First step through valid data and find the minimum and maximum YVal values
+ dblMaximumIntensity = LowestValueForDataType
+ dblMinimumIntensity = HighestValueForDataType
+ For lngIndex = 1 To XYDataToPlotCount
+ If boolIsXAxis Then
+ dblDataPoint = XYDataToPlot(lngIndex).XVal
+ Else
+ dblDataPoint = XYDataToPlot(lngIndex).YVal
+ End If
+ If dblDataPoint > dblMaximumIntensity Then
+ dblMaximumIntensity = dblDataPoint
+ End If
+ If dblDataPoint < dblMinimumIntensity Then
+ dblMinimumIntensity = dblDataPoint
+ End If
+ Next lngIndex
+
+ ' Reset .ValNegativeValueCorrectionOffset
+ ThisAxisRange.ValNegativeValueCorrectionOffset = 0
+
+ If boolAutoScaleAxis Then
+ If dblMinimumIntensity < 0 Then
+ ' Need to correct all y data by making it positive
+ ThisAxisRange.ValNegativeValueCorrectionOffset = Abs(dblMinimumIntensity)
+ End If
+ Else
+ ' The user has supplied ValStart and ValEnd values
+ ' Make sure .ValStart.Val < .ValEnd.Val
+ ' No need to use a NegativeValueCorrectionOffset since I perform bounds checking during the conversion from val to pos
+ If ThisAxisScaling.ValStart.Val > ThisAxisScaling.ValEnd.Val Then
+ SwapValues ThisAxisScaling.ValStart.Val, ThisAxisScaling.ValEnd.Val
+ End If
+ End If
+
+ If ThisAxisRange.ValNegativeValueCorrectionOffset > 0 Then
+ For lngIndex = 1 To XYDataToPlotCount
+ If boolIsXAxis Then
+ XYDataToPlot(lngIndex).XVal = XYDataToPlot(lngIndex).XVal + ThisAxisRange.ValNegativeValueCorrectionOffset
+ Else
+ XYDataToPlot(lngIndex).YVal = XYDataToPlot(lngIndex).YVal + ThisAxisRange.ValNegativeValueCorrectionOffset
+ End If
+ Next lngIndex
+ End If
+
+ If boolAutoScaleAxis Then
+ If Not boolIsXAxis And PlotOptions.FixYAxisMinimumAtZero Then
+ ' Only fix Y axis range at zero, and only fix if .FixYAxisMinimumAtZero is true
+ ThisAxisScaling.ValStart.Val = 0
+ Else
+ ThisAxisScaling.ValStart.Val = dblMinimumIntensity + ThisAxisRange.ValNegativeValueCorrectionOffset
+ End If
+
+ ThisAxisScaling.ValEnd.Val = dblMaximumIntensity + ThisAxisRange.ValNegativeValueCorrectionOffset
+
+ ' Record the current plot range for future reference when zooming
+ ThisAxisRange.ValStart.Val = ThisAxisScaling.ValStart.Val - ThisAxisRange.ValNegativeValueCorrectionOffset
+ ThisAxisRange.ValEnd.Val = ThisAxisScaling.ValEnd.Val - ThisAxisRange.ValNegativeValueCorrectionOffset
+ Else
+ ' Record the current plot range for future reference when zooming
+ ThisAxisRange.ValStart.Val = ThisAxisScaling.ValStart.Val
+ ThisAxisRange.ValEnd.Val = ThisAxisScaling.ValEnd.Val
+ End If
+
+ dblValRange = ThisAxisScaling.ValEnd.Val - ThisAxisScaling.ValStart.Val
+ If dblValRange = 0 Then dblValRange = 1
+
+ ' Scale the data according to PlotOptions.height
+
+ If boolIsXAxis Then
+ ThisAxisWindowLength = PlotOptions.PlotWidth
+ Else
+ ThisAxisWindowLength = PlotOptions.PlotHeight
+ End If
+
+ dblDeltaScaler = CDbl(ThisAxisWindowLength) / CDbl(dblValRange)
+
+ For lngIndex = 1 To XYDataToPlotCount
+ If boolIsXAxis Then
+ dblDataPoint = XYDataToPlot(lngIndex).XVal
+ Else
+ dblDataPoint = XYDataToPlot(lngIndex).YVal
+ End If
+
+ dblDataPoint = CLng((dblDataPoint - ThisAxisScaling.ValStart.Val) * dblDeltaScaler)
+ If dblDataPoint > ThisAxisWindowLength Then
+ dblDataPoint = ThisAxisWindowLength
+ Else
+ If dblDataPoint < 0 Then
+ dblDataPoint = 0
+ End If
+ End If
+
+ If boolIsXAxis Then
+ XYDataToPlot(lngIndex).XVal = dblDataPoint
+ Else
+ XYDataToPlot(lngIndex).YVal = dblDataPoint
+ End If
+
+ Next lngIndex
+
+ If Not boolIsXAxis Then
+ ' Need to recompute .PlotLeftLargeNumberOffset
+ ' Call FindDigitsInLabelUsingRange to determine the digits in the label and construct the format string
+ intDigitsInLabel = FindDigitsInLabelUsingRange(ThisAxisRange, PlotOptions.YAxis.MajorTicksToShow, strFormatString)
+
+ ' Store in .PlotLeftLargeNumberOffset
+ PlotOptions.PlotLeftLargeNumberOffset = intDigitsInLabel * NUM_TWIPS_PER_DIGIT
+ End If
+
+ ' Record the current plot range for future reference when zooming
+ If boolIsXAxis Then
+ ThisAxisRange.ValStart.Pos = PlotOptions.PlotLeft + PlotOptions.PlotLeftLargeNumberOffset
+ ThisAxisRange.ValEnd.Pos = PlotOptions.PlotLeft + PlotOptions.PlotLeftLargeNumberOffset + PlotOptions.PlotWidth
+ Else
+ ThisAxisRange.ValStart.Pos = PlotOptions.PlotTop + PlotOptions.PlotHeight
+ ThisAxisRange.ValEnd.Pos = PlotOptions.PlotTop ' equivalent to: PlotBottom - CLng((dblValRange - ThisAxisScaling.ValStart) * dblDeltaScaler)
+ End If
+
+End Sub
+
+Private Sub SortLabelLoc(ThisForm As Form, LabelLocPointerArray() As Long, LabelLocPointerArrayCount As Long)
+
+ ' Sorts a list of labels based on their location vertically on a form
+ Dim low%, high%, IndexTemp As Long
+
+ low% = 1
+ high% = LabelLocPointerArrayCount
+
+ ' Sort the list via a shell sort
+ Dim MaxRow As Integer, offset As Integer, limit As Integer, switch As Integer
+ Dim row As Integer
+
+ ' Set comparison offset to half the number of records
+ MaxRow = high
+ offset = MaxRow \ 2
+
+ Do While offset > 0 ' Loop until offset gets to zero.
+
+ limit = MaxRow - offset
+ Do
+ switch = 0 ' Assume no switches at this offset.
+
+ ' Compare elements and switch ones out of order:
+ For row = low To limit
+ If ThisForm.lblPlotIntensity(LabelLocPointerArray(row)).Top < ThisForm.lblPlotIntensity(LabelLocPointerArray(row + offset)).Top Then
+ IndexTemp = LabelLocPointerArray(row + offset)
+ LabelLocPointerArray(row + offset) = LabelLocPointerArray(row)
+ LabelLocPointerArray(row) = IndexTemp
+ switch = row
+ End If
+ Next row
+
+ ' Sort on next pass only to where last switch was made:
+ limit = switch - offset
+ Loop While switch
+
+ ' No switches at last offset, try one half as big:
+ offset = offset \ 2
+
+ Loop
+
+End Sub
+
+Private Sub SortXYData(XYData() As usrXYData, XYDataPointerArray() As Long, XYDataPointerCount As Long, boolSortByIntensity As Boolean)
+
+ ' Sorts a list of data by x value or by YVal (y values), depending on boolSortByIntensity
+
+ ' Rather than sorting the data itself, sorts a pointer array to the data
+ Dim lngLow As Long, lngHigh As Long, IndexTemp As Long, boolSwapThem As Boolean
+
+ lngLow = 1
+ lngHigh = XYDataPointerCount
+
+ ' Sort the list via a shell sort
+ Dim lngRowMax As Long, lngOffSet As Long, lngLimit As Long, lngSwitch As Long
+ Dim lngRow As Long
+
+ ' Set comparison lngOffSet to half the number of records
+ lngRowMax = lngHigh
+ lngOffSet = lngRowMax \ 2
+
+ Do While lngOffSet > 0 ' Loop until lngOffSet gets to zero.
+
+ lngLimit = lngRowMax - lngOffSet
+ Do
+ lngSwitch = 0 ' Assume no switches at this lngOffSet.
+
+ ' Compare elements and lngSwitch ones out of order:
+ For lngRow = lngLow To lngLimit
+ If boolSortByIntensity Then
+ boolSwapThem = (XYData(XYDataPointerArray(lngRow)).YVal < XYData(XYDataPointerArray(lngRow + lngOffSet)).YVal)
+ Else
+ boolSwapThem = (XYData(XYDataPointerArray(lngRow)).XVal > XYData(XYDataPointerArray(lngRow + lngOffSet)).XVal)
+ End If
+
+ If boolSwapThem Then
+ IndexTemp = XYDataPointerArray(lngRow + lngOffSet)
+ XYDataPointerArray(lngRow + lngOffSet) = XYDataPointerArray(lngRow)
+ XYDataPointerArray(lngRow) = IndexTemp
+ lngSwitch = lngRow
+ End If
+ Next lngRow
+
+ ' Sort on next pass only to where last lngSwitch was made:
+ lngLimit = lngSwitch - lngOffSet
+ Loop While lngSwitch
+
+ ' No switches at last lngOffSet, try one half as big:
+ lngOffSet = lngOffSet \ 2
+
+ Loop
+
+End Sub
+
+Private Sub SwapLineCoordinates(ThisLine As Line)
+ Dim lngTemp As Long
+
+ With ThisLine
+ ' Setting y axis values
+ ' Must swap x1 and y1, and x2 and y2
+ lngTemp = .x1
+ .x1 = .y1
+ .y1 = lngTemp
+
+ lngTemp = .x2
+ .x2 = .y2
+ .y2 = lngTemp
+
+ End With
+End Sub
+Public Function XYPosToValue(ThisPos As Long, ThisRange As usrPlotRangeAxis)
+ Dim PosRange As Long, ValRange As Double
+ Dim ScaledPos As Double
+
+ With ThisRange
+ ' Convert the x pos in ZoomBoxCoords to the actual x value
+ PosRange = .ValEnd.Pos - .ValStart.Pos
+ ValRange = .ValEnd.Val - .ValStart.Val
+
+ If PosRange <> 0 Then
+ ' ScaledPos is a value between 0 and 1 indicating the percentage between RangeEnd and RangeStart that ThisPos is
+ ScaledPos = (ThisPos - .ValStart.Pos) / PosRange
+
+ ' Now Convert to the displayed value
+ XYPosToValue = ScaledPos * ValRange + .ValStart.Val
+ Else
+ XYPosToValue = .ValStart.Val
+ End If
+ End With
+
+End Function
+
+Private Function WithinTolerance(ThisNumber As Double, CompareNumber As Double, ThisTolerance As Double) As Boolean
+ If ThisNumber <= CompareNumber + ThisTolerance And _
+ ThisNumber >= CompareNumber - ThisTolerance Then
+ WithinTolerance = True
+ Else
+ WithinTolerance = False
+ End If
+End Function
+
+Public Function XYValueToPos(ThisValue As Double, ThisRange As usrPlotRangeAxis, IsDeltaValue As Boolean)
+ Dim PosRange As Long, ValRange As Double
+ Dim ScaledPos As Double
+
+
+ With ThisRange
+ ' Convert the x pos in ZoomBoxCoords to the actual x value
+ PosRange = .ValEnd.Pos - .ValStart.Pos
+ ValRange = .ValEnd.Val - .ValStart.Val
+
+ If ValRange <> 0 Then
+ If IsDeltaValue Then
+ ScaledPos = ThisValue / ValRange
+
+ ' Now Convert to correct position
+ XYValueToPos = ScaledPos * PosRange
+ Else
+ ' ScaledPos is a value between 0 and 1 indicating the percentage between RangeEnd and RangeStart that ThisPos is
+ ScaledPos = (ThisValue - .ValStart.Val) / ValRange
+
+ ' Now Convert to correct position
+ XYValueToPos = ScaledPos * PosRange + .ValStart.Pos
+ End If
+ Else
+ XYValueToPos = ThisRange.ValStart.Pos
+ End If
+ End With
+
+End Function
+
+
diff --git a/MsPlot/Old/MsPlot.frm b/MsPlot/Old/MsPlot.frm
new file mode 100644
index 0000000..7003949
--- /dev/null
+++ b/MsPlot/Old/MsPlot.frm
@@ -0,0 +1,1566 @@
+VERSION 5.00
+Begin VB.Form frmMsPlot
+ Caption = "Plot"
+ ClientHeight = 3495
+ ClientLeft = 165
+ ClientTop = 735
+ ClientWidth = 6000
+ KeyPreview = -1 'True
+ LinkTopic = "Form1"
+ ScaleHeight = 3495
+ ScaleWidth = 6000
+ StartUpPosition = 3 'Windows Default
+ Begin VB.Frame fraPlot
+ BorderStyle = 0 'None
+ Height = 2985
+ Left = 120
+ TabIndex = 0
+ Top = 120
+ Width = 4785
+ Begin VB.Timer tmrUpdatePlot
+ Interval = 100
+ Left = 4320
+ Top = 0
+ End
+ Begin VB.Frame fraOptions
+ Caption = "Options (hidden)"
+ Height = 1275
+ Left = 1560
+ TabIndex = 4
+ Top = 1320
+ Visible = 0 'False
+ Width = 2175
+ Begin VB.TextBox txtXAxisTickCount
+ Height = 285
+ Left = 1440
+ TabIndex = 7
+ Text = "5"
+ Top = 120
+ Width = 615
+ End
+ Begin VB.TextBox txtYAxisTickCount
+ Height = 285
+ Left = 1440
+ TabIndex = 6
+ Text = "5"
+ Top = 480
+ Width = 615
+ End
+ Begin VB.ComboBox cboLabelsToShow
+ Height = 315
+ Left = 1440
+ Style = 2 'Dropdown List
+ TabIndex = 5
+ Top = 840
+ Width = 615
+ End
+ Begin VB.Label lblXAxisTickCount
+ Caption = "# of x axis ticks"
+ Height = 255
+ Left = 120
+ TabIndex = 10
+ Top = 240
+ Width = 1215
+ End
+ Begin VB.Label lblYAxisTickCount
+ Caption = "# of y axis ticks"
+ Height = 255
+ Left = 120
+ TabIndex = 9
+ Top = 480
+ Width = 1215
+ End
+ Begin VB.Label lblLabelsToShow
+ Caption = "# of ions to label:"
+ Height = 255
+ Left = 120
+ TabIndex = 8
+ Top = 840
+ Width = 1215
+ End
+ End
+ Begin VB.Line linData
+ Index = 1
+ Visible = 0 'False
+ X1 = 2160
+ X2 = 2160
+ Y1 = 600
+ Y2 = 1080
+ End
+ Begin VB.Line linTickMajor
+ DrawMode = 9 'Not Mask Pen
+ Index = 1
+ Visible = 0 'False
+ X1 = 840
+ X2 = 840
+ Y1 = 240
+ Y2 = 720
+ End
+ Begin VB.Line linXAxis
+ Visible = 0 'False
+ X1 = 1320
+ X2 = 600
+ Y1 = 720
+ Y2 = 720
+ End
+ Begin VB.Line linYAxis
+ Visible = 0 'False
+ X1 = 600
+ X2 = 600
+ Y1 = 720
+ Y2 = 120
+ End
+ Begin VB.Label lblCurrentPos
+ Caption = "Loc: 0,0"
+ Height = 195
+ Left = 1680
+ TabIndex = 3
+ Top = 0
+ Width = 1995
+ End
+ Begin VB.Label lblTick
+ BackStyle = 0 'Transparent
+ Caption = "123.45"
+ Height = 200
+ Index = 1
+ Left = 720
+ TabIndex = 2
+ Top = 840
+ Visible = 0 'False
+ Width = 500
+ End
+ Begin VB.Line linTickMinor
+ DrawMode = 9 'Not Mask Pen
+ Index = 1
+ Visible = 0 'False
+ X1 = 960
+ X2 = 960
+ Y1 = 480
+ Y2 = 720
+ End
+ Begin VB.Shape shpZoomBox
+ BorderColor = &H000000FF&
+ BorderStyle = 4 'Dash-Dot
+ Height = 855
+ Left = 240
+ Top = 1440
+ Width = 855
+ End
+ Begin VB.Label lblPlotIntensity
+ BackStyle = 0 'Transparent
+ Caption = "123.43"
+ Height = 195
+ Index = 1
+ Left = 2160
+ TabIndex = 1
+ Top = 360
+ Visible = 0 'False
+ Width = 615
+ End
+ Begin VB.Line linGridline
+ BorderColor = &H00FF0000&
+ BorderStyle = 3 'Dot
+ DrawMode = 9 'Not Mask Pen
+ Index = 1
+ Visible = 0 'False
+ X1 = 720
+ X2 = 720
+ Y1 = 240
+ Y2 = 720
+ End
+ End
+ Begin VB.Menu mnuFile
+ Caption = "&File"
+ Begin VB.Menu mnuInitializeData
+ Caption = "&Initialize with Dummy Data"
+ End
+ Begin VB.Menu mnuInitializeStickDataLots
+ Caption = "Initialize with MS Stick Data (lots)"
+ End
+ Begin VB.Menu mnuInitializeStickData
+ Caption = "Initialize with MS Stick Data (just a few)"
+ End
+ Begin VB.Menu mnuExportData
+ Caption = "&Export Data"
+ End
+ Begin VB.Menu mnuFileSepBar1
+ Caption = "-"
+ End
+ Begin VB.Menu mnuClose
+ Caption = "&Close"
+ End
+ End
+ Begin VB.Menu mnuOptions
+ Caption = "&Options"
+ Begin VB.Menu mnuPlotType
+ Caption = "&Plot Type"
+ Begin VB.Menu mnuPlotTypeSticksToZero
+ Caption = "&Sticks to Zero"
+ End
+ Begin VB.Menu mnuPlotTypeLinesBetweenPoints
+ Caption = "&Lines Between Points"
+ Checked = -1 'True
+ End
+ End
+ Begin VB.Menu mnuSetResolution
+ Caption = "Set Effective Resolution"
+ End
+ Begin VB.Menu mnuOptionsSepBar6
+ Caption = "-"
+ End
+ Begin VB.Menu mnuGridLinesXAxis
+ Caption = "X Axis Gridlines"
+ Shortcut = ^X
+ End
+ Begin VB.Menu mnuGridLinesYAxis
+ Caption = "Y Axis Gridlines"
+ Shortcut = ^Y
+ End
+ Begin VB.Menu mnuTicks
+ Caption = "&Ticks to show (approx.)"
+ Begin VB.Menu mnuTicksXAxis
+ Caption = "&X Axis..."
+ End
+ Begin VB.Menu mnuTicksYAxis
+ Caption = "&Y Axis..."
+ End
+ End
+ Begin VB.Menu mnuPeaksToLabel
+ Caption = "Peaks To &Label..."
+ Enabled = 0 'False
+ End
+ Begin VB.Menu mnuOptionsSepBar4
+ Caption = "-"
+ End
+ Begin VB.Menu mnuSetRangeX
+ Caption = "Set &X Range..."
+ End
+ Begin VB.Menu mnuSetRangeY
+ Caption = "Set &Y Range..."
+ End
+ Begin VB.Menu mnuAutoScaleYAxis
+ Caption = "&Autoscale Y Axis"
+ Shortcut = ^F
+ End
+ Begin VB.Menu mnuFixMinimumYAtZero
+ Caption = "&Fix mimimum Y at zero"
+ End
+ Begin VB.Menu mnuOptionsSepBar5
+ Caption = "-"
+ End
+ Begin VB.Menu mnuZoomOutToPrevious
+ Caption = "&Zoom Out to Previous "
+ End
+ Begin VB.Menu mnuZoomOutFullScale
+ Caption = "Zoom Out to Show All"
+ Shortcut = ^A
+ End
+ Begin VB.Menu mnuOptionsSepBar1
+ Caption = "-"
+ End
+ Begin VB.Menu mnuCursorMode
+ Caption = "&Cursor Mode"
+ Begin VB.Menu mnuCursorModeZoom
+ Caption = "&Zoom"
+ Checked = -1 'True
+ End
+ Begin VB.Menu mnuCursorModeMove
+ Caption = "&Move"
+ End
+ End
+ Begin VB.Menu mnuShowCurrentPosition
+ Caption = "Show Current &Position"
+ Checked = -1 'True
+ End
+ End
+ Begin VB.Menu mnuZoomOptions
+ Caption = "&Zoom Box"
+ Begin VB.Menu mnuZoomIn
+ Caption = "Zoom &In"
+ End
+ Begin VB.Menu mnuZoomInHorizontal
+ Caption = "Zoom In Horizontal"
+ End
+ Begin VB.Menu mnuZoomInVertical
+ Caption = "Zoom In Vertical"
+ End
+ Begin VB.Menu mnuZoomSepBar2
+ Caption = "-"
+ End
+ Begin VB.Menu mnuZoomOut
+ Caption = "Zoom &Out"
+ End
+ Begin VB.Menu mnuZoomOutHorizontal
+ Caption = "Zoom Out Horizontal"
+ End
+ Begin VB.Menu mnuZoomOutVertical
+ Caption = "Zoom Out Vertical"
+ End
+ End
+End
+Attribute VB_Name = "frmMsPlot"
+Attribute VB_GlobalNameSpace = False
+Attribute VB_Creatable = False
+Attribute VB_PredeclaredId = True
+Attribute VB_Exposed = False
+Option Explicit
+
+Private Type usrRect
+ x1 As Long
+ y1 As Long
+ x2 As Long
+ y2 As Long
+End Type
+
+Private ZoomBoxCoords As usrRect
+Private PlotOptions As usrPlotDataOptions
+
+Private boolSlidingGraph As Boolean, PlotRangeAtMoveStart As usrPlotRange
+Private boolResizingWindow As Boolean, boolDrawingZoomBox As Boolean, boolZoomBoxDrawn As Boolean
+
+Private LoadedXYData As usrXYDataSet ' The data to plot
+Private InitialStickData As usrXYDataSet ' If the user submits Stick Data (discrete data points) and requests that the sticks be converted to a
+ ' Gaussian representation, then the original, unmodified data is stored here
+
+Private dblPlotRangeStretchVal As Double
+
+Public TicksElapsedSinceStart As Long ' Actually increments 10 times per second rather than 1000 per second since tmrPlot.Interval = 100
+Private TickCountToUpdateAt As Long
+
+Private boolUpdatePosition As Boolean, CurrentPosX As Double, CurrentPosY As Double
+
+Const PLOT_RANGE_HISTORY_COUNT = 20
+Private PlotRangeHistory(PLOT_RANGE_HISTORY_COUNT) As usrPlotRange ' Keeps track of the last 5 plot ranges displayed to allow for undoing
+
+Private Sub EnableDisableZoomMenus(boolEnableMenus As Boolean)
+
+ mnuZoomOptions.Visible = boolEnableMenus
+
+End Sub
+
+Private Sub EnableDisableMenuCheckmarks()
+
+ With PlotOptions
+ mnuPlotTypeSticksToZero.Checked = (.PlotTypeCode = 0)
+ mnuPlotTypeLinesBetweenPoints.Checked = (.PlotTypeCode = 1)
+ mnuGridLinesXAxis.Checked = .XAxis.ShowGridLinesMajor
+ mnuGridLinesYAxis.Checked = .YAxis.ShowGridLinesMajor
+ mnuAutoScaleYAxis.Checked = .AutoScaleY
+ mnuFixMinimumYAtZero.Checked = .FixYAxisMinimumAtZero
+ End With
+
+End Sub
+
+Public Sub ExportData()
+ Dim lngIndex As Long, strFilepath As String
+
+ On Error GoTo WriteProblem
+
+ strFilepath = "d:\DataOut.csv"
+ Open strFilepath For Output As #1
+ For lngIndex = 1 To LoadedXYData.XYDataListCount
+ With LoadedXYData.XYDataList(lngIndex)
+ Print #1, .XVal & "," & .YVal
+ End With
+ Next lngIndex
+ Close
+
+ MsgBox "Data written to file " & strFilepath
+
+ Exit Sub
+
+WriteProblem:
+ MsgBox "Error writing data to file " & strFilepath
+
+End Sub
+
+Private Function FixUpCoordinates(TheseCoords As usrRect) As usrRect
+ Dim FixedCoords As usrRect
+
+ FixedCoords = TheseCoords
+
+ With FixedCoords
+ If .x1 > .x2 Then
+ SwapValues .x1, .x2
+ End If
+ If .y1 > .y2 Then
+ SwapValues .y1, .y2
+ End If
+ End With
+
+ FixUpCoordinates = FixedCoords
+
+End Function
+
+Private Sub HideZoomBox(Button As Integer, boolPerformZoom As Boolean)
+
+ EnableDisableZoomMenus False
+ boolZoomBoxDrawn = False
+ boolDrawingZoomBox = False
+
+ If shpZoomBox.Visible = False Then
+ Exit Sub
+ End If
+
+ shpZoomBox.Visible = False
+
+ If Button = vbLeftButton Then
+ If boolPerformZoom Then
+ PerformZoom
+ End If
+ End If
+
+End Sub
+
+Private Sub InitializeDummyData(intDataType As Integer)
+ ' intDataType can be 0: continuous sine wave
+ ' 1: stick data (only 20 points)
+ ' 2: stick data (1000's of points, mostly zero, with a few spikes)
+
+ Dim ThisXYDataSet As usrXYDataSet
+ Dim x As Long, sngOffset As Single
+
+ Const PI = 3.14159265359
+ Const DegToRadiansMultiplier = PI / 180 / 10
+
+ Randomize Timer
+
+ Select Case intDataType
+ Case 1
+ With ThisXYDataSet
+ .XYDataListCount = 14
+ ReDim .XYDataList(.XYDataListCount)
+ .XYDataList(1).XVal = 154
+ .XYDataList(1).YVal = 79
+ .XYDataList(2).XVal = 154.51
+ .XYDataList(2).YVal = 25
+ .XYDataList(3).XVal = 154.95
+ .XYDataList(3).YVal = 15
+ .XYDataList(4).XVal = 280.2
+ .XYDataList(4).YVal = 60
+ .XYDataList(5).XVal = 281.15
+ .XYDataList(5).YVal = 20
+ .XYDataList(6).XVal = 282.201
+ .XYDataList(6).YVal = 10
+ .XYDataList(7).XVal = 312
+ .XYDataList(7).YVal = 23
+ .XYDataList(8).XVal = 312.332
+ .XYDataList(8).YVal = 5
+ .XYDataList(9).XVal = 312.661
+ .XYDataList(9).YVal = 2
+ .XYDataList(10).XVal = 500
+ .XYDataList(10).YVal = 10
+ .XYDataList(11).XVal = 589
+ .XYDataList(11).YVal = 102
+ .XYDataList(12).XVal = 589.247
+ .XYDataList(12).YVal = 72.3
+ .XYDataList(13).XVal = 589.523
+ .XYDataList(13).YVal = 50.7
+ .XYDataList(14).XVal = 589.78
+ .XYDataList(14).YVal = 30
+ End With
+ SetXYData ThisXYDataSet, True, True
+ Case 2
+ With ThisXYDataSet
+ .XYDataListCount = 50000
+ ReDim .XYDataList(.XYDataListCount)
+ For x = 1 To .XYDataListCount
+ .XYDataList(x).XVal = 100 + x / 500
+ If x Mod 5000 = 0 Then
+ .XYDataList(x).YVal = Rnd(1) * .XYDataListCount / 200 * Rnd(1)
+ ElseIf x Mod 3000 = 0 Then
+ .XYDataList(x).YVal = Rnd(1) * .XYDataListCount / 650 * Rnd(1)
+ Else
+ .XYDataList(x).YVal = Rnd(1) * 3
+ End If
+ Next x
+ End With
+ SetXYData ThisXYDataSet, True, False
+ Case Else
+ With ThisXYDataSet
+ .XYDataListCount = 360! * 100!
+
+ ReDim .XYDataList(.XYDataListCount)
+ sngOffset = 10
+ For x = 1 To .XYDataListCount
+ If x Mod 5050 = 0 Then
+ sngOffset = Rnd(1) + 10
+ End If
+ .XYDataList(x).XVal = CDbl(x) / 1000 - 5
+ .XYDataList(x).YVal = sngOffset - Abs((x - .XYDataListCount / 2)) / 10000 + Sin(DegToRadiansMultiplier * x) * Cos(DegToRadiansMultiplier * x / 2) * 1.29967878493163
+ Next x
+ End With
+ SetXYData ThisXYDataSet, False, False
+ End Select
+
+ PlotOptions.IndexToHighlight = ThisXYDataSet.XYDataListCount / 2
+
+ ZoomOut True
+
+End Sub
+Private Sub InitializeZoomOrMove(Button As Integer, x As Single, y As Single)
+ If Button = vbLeftButton Then
+ With ZoomBoxCoords
+ .x1 = x
+ .y1 = y
+ .x2 = .x1
+ .y2 = .y1
+ End With
+
+ If mnuCursorModeZoom.Checked Then
+ ' Zooming
+ ' Begin drawing zoom/move box
+ shpZoomBox.Visible = True
+ boolZoomBoxDrawn = False
+ EnableDisableZoomMenus False
+ RedrawZoomBox
+ Else
+ ' Moving (dragging) plot
+ ' Will still update the zoom/move box to keep track of how far dragged
+ ' but will not draw the box
+ shpZoomBox.Visible = False
+ boolDrawingZoomBox = False
+ boolSlidingGraph = True
+ PlotRangeAtMoveStart = PlotRangeHistory(1)
+ End If
+
+ Else
+ If shpZoomBox.Visible = True Then
+ ' User clicked outside of zoom box (not left button), hide it
+ HideZoomBox Button, False
+ Else
+ If Button = vbRightButton Then
+ ZoomOut False
+ End If
+ End If
+ End If
+
+End Sub
+
+Private Sub RespondZoomModeClick(Button As Integer, x As Single, y As Single)
+ ' The Zoom Box is visible and the user clicked inside the box
+ ' Handle the click differently depending on the location and the button
+
+ If IsZoomBoxLargeEnough(ZoomBoxCoords) Then
+ If Button = vbLeftButton Then
+ ' Left click inside box: Remove zoom/move box and zoom
+ HideZoomBox Button, True
+ ElseIf Button = vbRightButton Then
+ ' Right click inside box: Show zoom menu
+ PopupMenu mnuZoomOptions, vbPopupMenuLeftAlign
+ End If
+ Else
+ ' Clicked inside box but it's too small
+ HideZoomBox Button, False
+ SetCursorIcon
+
+ If Button = vbLeftButton Then
+ ' Left click outside box: Start a new zoom box
+ InitializeZoomOrMove Button, x, y
+ End If
+ End If
+
+End Sub
+
+Private Sub ResetMousePointer(Optional Button As Integer = 0)
+ If Button = 0 And Me.MousePointer <> vbDefault Then Me.MousePointer = vbDefault
+End Sub
+
+Private Sub ResizeZoomBox(Button As Integer, x As Single, y As Single)
+ ' For both zooming and moving, resizes the Zoom Box
+
+ ' If zooming, then redraw the box
+ If shpZoomBox.Visible = True And Button = vbLeftButton Then
+ ' Resize zoom/move box
+ ZoomBoxCoords.x2 = x
+ ZoomBoxCoords.y2 = y
+
+ RedrawZoomBox
+ End If
+
+ ' If moving, then call the PerformMove sub to initiate a move
+ If mnuCursorModeMove.Checked And Button = vbLeftButton Then
+ ' Resize zoom/move box
+ ZoomBoxCoords.x2 = x
+ ZoomBoxCoords.y2 = y
+
+ ' Moving plot
+ PerformMove
+ End If
+
+End Sub
+
+Public Sub SetAutoscaleY(boolEnable As Boolean)
+
+ If boolEnable Then
+ ' Auto Scale just turned on - replot
+ PlotOptions.AutoScaleY = True
+ UpdatePlot
+ Else
+ ' Auto Scale just turned off
+ PlotOptions.AutoScaleY = True
+ UpdatePlot
+ PlotOptions.AutoScaleY = False
+ End If
+ EnableDisableMenuCheckmarks
+
+End Sub
+
+Private Sub SetCursorIcon(Optional x As Single = 0, Optional y As Single = 0)
+ If mnuCursorModeMove.Checked Then
+ ' Move mode
+ ' Me.MouseIcon = imgMouseHand
+ ' Me.MousePointer = vbCustom
+ Me.MousePointer = vbSizeAll
+ Else
+ ' Zoom Mode
+ If boolZoomBoxDrawn Then
+ If IsClickInBox(x, y, ZoomBoxCoords) Then
+ If Me.MousePointer <> vbArrowQuestion Then
+ If IsZoomBoxLargeEnough(ZoomBoxCoords) Then
+' Me.MouseIcon = imgMouseMagnify
+' Me.MousePointer = vbCustom
+ 'Me.MousePointer = vbArrowQuestion
+ Me.MousePointer = vbUpArrow
+ End If
+ End If
+ Else
+ Me.MousePointer = vbCrosshair
+ End If
+ Else
+ Me.MousePointer = vbCrosshair
+ End If
+ End If
+ EnableDisableMenuCheckmarks
+End Sub
+
+Public Sub SetCursorMode(boolMoveMode As Boolean)
+
+ mnuCursorModeZoom.Checked = Not boolMoveMode
+ mnuCursorModeMove.Checked = boolMoveMode
+
+ SetCursorIcon
+
+End Sub
+
+Public Sub SetFixMinimumAtZero(boolEnable As Boolean)
+ PlotOptions.FixYAxisMinimumAtZero = boolEnable
+ SetPlotOptions True, True
+ EnableDisableMenuCheckmarks
+End Sub
+
+Public Sub SetGridlinesXAxis(boolEnable As Boolean)
+ PlotOptions.XAxis.ShowGridLinesMajor = boolEnable
+ SetPlotOptions True, False
+ EnableDisableMenuCheckmarks
+End Sub
+
+Public Sub SetGridlinesYAxis(boolEnable As Boolean)
+ PlotOptions.YAxis.ShowGridLinesMajor = boolEnable
+ SetPlotOptions True, False
+ EnableDisableMenuCheckmarks
+End Sub
+
+Public Sub SetNewRange(boolIsXAxis As Boolean, boolPromptUserForValues As Boolean, Optional dblNewStartVal As Double = 0, Optional dblNewEndVal As Double = 0)
+ Dim dblStartVal As Double, dblEndVal As Double, dblLowerLimit As Double, dblUpperLimit As Double
+ Dim dblDefaultSeparationValue As Double
+ Dim strFormatString As String
+
+ If boolIsXAxis Then
+ dblStartVal = PlotOptions.Scaling.x.ValStart.Val - PlotOptions.Scaling.x.ValNegativeValueCorrectionOffset
+ dblEndVal = PlotOptions.Scaling.x.ValEnd.Val - PlotOptions.Scaling.x.ValNegativeValueCorrectionOffset
+ dblLowerLimit = PlotOptions.DataLimits.x.ValStart.Val
+ dblUpperLimit = PlotOptions.DataLimits.x.ValEnd.Val
+ Else
+ dblStartVal = PlotOptions.Scaling.y.ValStart.Val - PlotOptions.Scaling.y.ValNegativeValueCorrectionOffset
+ dblEndVal = PlotOptions.Scaling.y.ValEnd.Val - PlotOptions.Scaling.y.ValNegativeValueCorrectionOffset
+ dblLowerLimit = PlotOptions.DataLimits.y.ValStart.Val
+ dblUpperLimit = PlotOptions.DataLimits.y.ValEnd.Val
+ End If
+
+ If dblStartVal = 0 And dblEndVal = 0 Then
+ dblStartVal = dblLowerLimit
+ dblEndVal = dblUpperLimit
+ End If
+
+ If boolPromptUserForValues Or (dblNewStartVal = 0 And dblNewEndVal = 0) Then
+
+ With PlotRangeHistory(1)
+ If boolIsXAxis Then
+ strFormatString = ConstructFormatString(Abs(.x.ValEnd.Val - .x.ValStart.Val) / 100)
+ Else
+ strFormatString = ConstructFormatString(Abs(.y.ValEnd.Val - .y.ValStart.Val) / 100)
+ End If
+ End With
+
+ dblStartVal = Format(dblStartVal, strFormatString)
+ dblEndVal = Format(dblEndVal, strFormatString)
+
+ With frmSetValue
+ .Caption = "Set Range"
+ .lblStartVal.Caption = "Start Val"
+ .txtStartVal = dblStartVal
+ .lblEndVal.Caption = "End Val"
+ .txtEndVal = dblEndVal
+
+ ' Round dblDefaultSeparationValue to nearest 1, 2, or 5 (or multiple of 10 thereof)
+ dblDefaultSeparationValue = RoundToMultipleOf10((dblEndVal - dblStartVal) / 10)
+
+ .SetLimits True, dblLowerLimit, dblUpperLimit, dblDefaultSeparationValue
+
+ If boolIsXAxis Then
+ .Caption = "Set X Axis Range"
+ Else
+ .Caption = "Set Y Axis Range"
+ End If
+
+ .Show vbModal
+ End With
+
+ If UCase(frmSetValue.Tag) <> "OK" Then Exit Sub
+
+ ' Set New Range
+ With frmSetValue
+ If IsNumeric(.txtStartVal) Then dblNewStartVal = CDbl(.txtStartVal)
+ If IsNumeric(.txtEndVal) Then dblNewEndVal = CDbl(.txtEndVal)
+ End With
+ End If
+
+ If boolIsXAxis Then
+ PlotOptions.Scaling.x.ValStart.Val = dblNewStartVal
+ PlotOptions.Scaling.x.ValEnd.Val = dblNewEndVal
+ Else
+ PlotOptions.Scaling.y.ValStart.Val = dblNewStartVal
+ PlotOptions.Scaling.y.ValEnd.Val = dblNewEndVal
+ End If
+
+ UpdatePlot True
+End Sub
+
+Public Sub SetXYData(NewXYData As usrXYDataSet, boolTreatDataAsDiscretePoints As Boolean, Optional boolConvertStickDataToGaussianRepresentation As Boolean = False)
+
+ ' Reset .DataLimits
+ With PlotOptions.DataLimits
+ .x.ValStart.Val = 0
+ .y.ValEnd.Val = 0
+ .y.ValStart.Val = 0
+ .y.ValEnd.Val = 0
+ End With
+
+ ' Initialize Plot options
+ InitializePlotOptions
+
+ If boolTreatDataAsDiscretePoints Then
+ InitialStickData = NewXYData
+ ' Load New Data into LoadedXYData
+ SetPlotOptions False, False
+ SetPlotType boolConvertStickDataToGaussianRepresentation, False
+ Else
+ InitialStickData.XYDataListCount = 0
+ LoadedXYData = NewXYData
+ SetPlotType True, False ' Note: Automatically loads data into LoadedXYData
+ End If
+
+ PlotOptions.Scaling = PlotOptions.DataLimits
+
+ ' Reset the boolLongOperationsRequired bit
+ PlotOptions.boolLongOperationsRequired = False
+
+ ' Erase all data in PlotRangeHistory()
+ ' Since this array is dimensioned using the const PLOT_RANGE_HISTORY_COUNT, it
+ ' does not need to be re-dimensioned after erasing
+ Erase PlotRangeHistory()
+
+End Sub
+
+Public Sub SetPeaksToLabel(Optional intPeaksToLabel As Integer = -1)
+ Dim strResponse As String, intNewLabelCount As Integer
+
+ If intPeaksToLabel < 0 Then
+ strResponse = InputBox("Please enter the number of peaks (sticks) to label by decreasing intensity:", "Peaks to Label", cboLabelsToShow.ListIndex)
+ Else
+ strResponse = Trim(Str(intPeaksToLabel))
+ End If
+
+ If IsNumeric(strResponse) Then
+ intNewLabelCount = CInt(strResponse)
+ If intNewLabelCount < 0 Or intNewLabelCount >= cboLabelsToShow.ListCount Then
+ intNewLabelCount = 3
+ End If
+ If intNewLabelCount < cboLabelsToShow.ListCount Then
+ cboLabelsToShow.ListIndex = intNewLabelCount
+ End If
+ End If
+
+ SetPlotOptions True, False
+End Sub
+Private Sub InitializePlotOptions()
+ txtXAxisTickCount = "5"
+ txtYAxisTickCount = "5"
+ cboLabelsToShow.ListIndex = 0
+
+ With PlotOptions
+ .XAxis.Show = True
+ .XAxis.MinorTickMinimumPixelSep = 100
+ .XAxis.ShowMinorTicks = True
+
+ .YAxis.Show = True
+ .YAxis.MinorTickMinimumPixelSep = 100
+ .YAxis.ShowMinorTicks = True
+
+ .GaussianConversion.ResolvingPower = 5000
+ .GaussianConversion.XValueOfSpecification = 500
+ .HighlightColor = vbRed
+ End With
+
+End Sub
+
+Private Sub SetPlotOptions(Optional boolUpdatePlot As Boolean = True, Optional boolUpdateHistory As Boolean = True)
+ With PlotOptions
+ .XAxis.MajorTicksToShow = txtXAxisTickCount
+
+ .YAxis.MajorTicksToShow = txtYAxisTickCount
+
+ .LabelsToShow = Val(cboLabelsToShow)
+ .ShowDataPointLabels = (.LabelsToShow > 0)
+ End With
+
+ If boolUpdatePlot Then UpdatePlot boolUpdateHistory
+
+End Sub
+
+Public Sub SetPlotType(boolLinesBetweenPoints As Boolean, Optional boolUpdatePlot As Boolean = True)
+
+ If boolLinesBetweenPoints Then
+ PlotOptions.PlotTypeCode = 1
+ Else
+ PlotOptions.PlotTypeCode = 0
+ End If
+ mnuPeaksToLabel.Enabled = Not boolLinesBetweenPoints
+
+ If InitialStickData.XYDataListCount > 0 Then
+ ' Stick data is present; need to take action
+ If boolLinesBetweenPoints Then
+ LoadedXYData = ConvertStickDataToGaussian(Me, InitialStickData, PlotOptions)
+ Else
+ LoadedXYData = InitialStickData
+ End If
+ End If
+
+ SetPlotOptions boolUpdatePlot, False
+ EnableDisableMenuCheckmarks
+
+End Sub
+
+Public Sub SetResolution(Optional lngNewResolvingPower As Long = -1, Optional dblNewXValResLocation As Double = 500)
+ Dim strResponse As String
+
+ If lngNewResolvingPower < 1 Then
+ With frmSetValue
+ .Caption = "Resolving Power Specifications"
+ .lblStartVal.Caption = "Resolving Power"
+ .txtStartVal = PlotOptions.GaussianConversion.ResolvingPower
+ .lblEndVal.Caption = "X Value of Specification"
+ .txtEndVal = PlotOptions.GaussianConversion.XValueOfSpecification
+
+ .SetLimits False
+
+ .Show vbModal
+ End With
+
+ If UCase(frmSetValue.Tag) <> "OK" Then Exit Sub
+
+ ' Set New Range
+ With frmSetValue
+ If IsNumeric(.txtStartVal) Then
+ lngNewResolvingPower = CLng(.txtStartVal)
+ Else
+ lngNewResolvingPower = 5000
+ End If
+ If IsNumeric(.txtEndVal) Then
+ dblNewXValResLocation = CDbl(.txtEndVal)
+ Else
+ dblNewXValResLocation = 500
+ End If
+ End With
+
+ End If
+
+ If lngNewResolvingPower < 1 Or lngNewResolvingPower > 1E+38 Then
+ lngNewResolvingPower = 5000
+ End If
+ PlotOptions.GaussianConversion.ResolvingPower = lngNewResolvingPower
+
+ PlotOptions.GaussianConversion.XValueOfSpecification = dblNewXValResLocation
+
+ SetPlotOptions False, False
+ SetPlotType mnuPlotTypeLinesBetweenPoints.Checked, True
+
+End Sub
+
+Public Sub SetShowCursorPosition(boolEnable As Boolean)
+ mnuShowCurrentPosition.Checked = boolEnable
+ EnableDisableMenuCheckmarks
+End Sub
+
+Private Sub TickCountUpdateByUser(txtThisTextBox As TextBox, Optional strAxisLetter As String = "X")
+ Dim strResponse As String, intNewTickCount As Integer
+
+ strAxisLetter = UCase(Trim(strAxisLetter))
+
+ If Len(strAxisLetter) = 0 Then strAxisLetter = "X"
+
+ strResponse = InputBox("Please enter the approximate number of ticks to show on the " & strAxisLetter & " axis (2 to 30):", strAxisLetter & " Axis Ticks", txtThisTextBox)
+
+ If IsNumeric(strResponse) Then
+ intNewTickCount = CInt(strResponse)
+ If intNewTickCount < 2 Or intNewTickCount > 30 Then
+ intNewTickCount = 5
+ End If
+ txtThisTextBox = Trim(Str(intNewTickCount))
+ End If
+
+ SetPlotOptions True, False
+
+End Sub
+
+Private Sub UpdateCurrentPos()
+ Dim XValue As Double, YValue As Double
+ Dim strFormatStringX As String, strFormatStringY As String
+
+ If mnuShowCurrentPosition.Checked Then
+ With PlotRangeHistory(1)
+ XValue = XYPosToValue(CLng(CurrentPosX), .x)
+ YValue = XYPosToValue(CLng(CurrentPosY), .y)
+ strFormatStringX = ConstructFormatString(Abs(.x.ValEnd.Val - .x.ValStart.Val) / 100)
+ strFormatStringY = ConstructFormatString(Abs(.y.ValEnd.Val - .y.ValStart.Val) / 100)
+ End With
+
+ lblCurrentPos = "Loc: " & Format(XValue, strFormatStringX) & ", " & Format(YValue, strFormatStringY)
+ End If
+
+ boolUpdatePosition = False
+End Sub
+
+Private Sub UpdatePlot(Optional boolUpdateHistory As Boolean = True)
+ Dim MostRecentPlotRange As usrPlotRange, intIndex As Integer
+
+ With PlotOptions
+ If .PlotTypeCode = 0 Then
+ .PlotTop = 500
+ Else
+ .PlotTop = 250
+ End If
+ .PlotLeft = 300
+ .PlotWidth = fraPlot.Width - .PlotLeft - 250
+ .PlotHeight = fraPlot.Height - .PlotTop - 700
+ End With
+
+ MostRecentPlotRange = PlotRangeHistory(1)
+
+ ' Hide the plot so it gets updated faster
+ fraPlot.Visible = False
+
+ ' Perform the actual update
+ DrawPlot Me, PlotOptions, LoadedXYData.XYDataList, LoadedXYData.XYDataListCount, MostRecentPlotRange
+
+ ' Show the plot
+ fraPlot.Visible = True
+
+ If boolUpdateHistory Then
+' If PlotRangeHistory(1).X.ValEnd.Val <> PlotRangeHistory(2).X.ValEnd.Val Or _
+ PlotRangeHistory(1).X.ValStart.Val <> PlotRangeHistory(2).X.ValStart.Val Or _
+ PlotRangeHistory(1).Y.ValEnd.Val <> PlotRangeHistory(2).Y.ValEnd.Val Or _
+ PlotRangeHistory(1).Y.ValStart.Val <> PlotRangeHistory(2).Y.ValStart.Val Then
+ ' Update the plot range history
+ For intIndex = PLOT_RANGE_HISTORY_COUNT To 2 Step -1
+ PlotRangeHistory(intIndex) = PlotRangeHistory(intIndex - 1)
+ Next intIndex
+' End If
+ End If
+
+ If Me.MousePointer = vbHourglass Then Me.MousePointer = vbDefault
+
+ PlotRangeHistory(1) = MostRecentPlotRange
+End Sub
+
+Private Sub UpdatePlotWhenIdle()
+ Dim boolUpdateHistory As Boolean
+
+ If TickCountToUpdateAt < TicksElapsedSinceStart Then
+ ' Update the plot, but don't update the history if sliding
+ If boolSlidingGraph Or boolResizingWindow Then
+ boolUpdateHistory = False
+ Else
+ boolUpdateHistory = True
+ End If
+ UpdatePlot boolUpdateHistory
+
+ TickCountToUpdateAt = 0
+ boolResizingWindow = False
+ End If
+
+End Sub
+
+Private Sub ZoomInHorizontal()
+ ' Zoom in along the horizontal axis but
+ ' Do not change the vertical range
+
+ FixUpCoordinates ZoomBoxCoords
+ With ZoomBoxCoords
+ .y1 = PlotRangeHistory(1).y.ValEnd.Pos
+ .y2 = PlotRangeHistory(1).y.ValStart.Pos
+ End With
+
+ HideZoomBox vbLeftButton, True
+
+End Sub
+
+Private Sub ZoomInVertical()
+ ' Zoom in along the horizontal axis but
+ ' Do not change the vertical range
+
+ FixUpCoordinates ZoomBoxCoords
+ With ZoomBoxCoords
+ .x1 = PlotRangeHistory(1).x.ValStart.Pos
+ .x2 = PlotRangeHistory(1).x.ValEnd.Pos
+ End With
+
+ HideZoomBox vbLeftButton, True
+
+End Sub
+
+Private Sub ZoomOut(ByVal boolZoomOutCompletely As Boolean)
+ Dim intIndex As Integer
+
+ If Not boolZoomOutCompletely Then
+ ' See if any previous PlotRange data exists in the history
+ ' If not then set boolZoomOutCompletely to True
+ With PlotRangeHistory(2)
+ If .x.ValStart.Pos = 0 And .x.ValEnd.Pos = 0 And .x.ValStart.Pos = 0 And .x.ValEnd.Pos = 0 Then
+ ' Most recent saved zoom range is all zeroes -- not usable
+ boolZoomOutCompletely = True
+ End If
+ End With
+ End If
+
+ If boolZoomOutCompletely Then
+ ' Call SetPlotOptions to make sure all options are up to date
+ SetPlotOptions False
+
+ With PlotOptions
+ ' Override the AutoScaleY option and turn on ZoomOutFull
+ .ZoomOutFull = True
+ .AutoScaleY = True
+
+ ' Initialize .Scaling.x.ValStart.Val and .Scaling.y.ValStart.Val if necessary
+ If LoadedXYData.XYDataListCount > 0 Then
+ .Scaling.x.ValStart.Val = LoadedXYData.XYDataList(1).XVal
+ .Scaling.x.ValEnd.Val = LoadedXYData.XYDataList(LoadedXYData.XYDataListCount).XVal
+ End If
+
+ If .PlotTypeCode = 0 Then
+ ' Displaying a sticks to zero plot and zoomed out full
+ ' Need to stretch the limits of the plot by 2% of the total range
+ dblPlotRangeStretchVal = (.Scaling.x.ValEnd.Val - .Scaling.x.ValStart.Val) * 0.05
+ .Scaling.x.ValEnd.Val = .Scaling.x.ValEnd.Val + dblPlotRangeStretchVal
+ .Scaling.x.ValStart.Val = .Scaling.x.ValStart.Val - dblPlotRangeStretchVal
+ End If
+
+ End With
+
+
+ ' Update theplot
+ UpdatePlot
+
+ ' Call SetPlotOptions again in case .AutoScaleY should be false
+ SetPlotOptions False
+ Else
+ ' Zoom to previous range
+
+ PlotOptions.Scaling = PlotRangeHistory(2)
+
+ UpdatePlot False
+
+ ' Update the plot range history
+ For intIndex = 2 To PLOT_RANGE_HISTORY_COUNT - 1
+ PlotRangeHistory(intIndex) = PlotRangeHistory(intIndex + 1)
+ Next intIndex
+
+ End If
+
+End Sub
+
+Private Sub ZoomShrink(boolFixHorizontal As Boolean, boolFixVertical As Boolean)
+ ' Zoom out, but not completely
+
+ Dim lngViewRangePosX As Long, lngViewRangePosY As Long
+ Dim lngBoxSizeX As Double, lngBoxSizeY As Double
+ Dim lngPosCorrectionFactorX As Long, lngPosCorrectionFactorY As Long
+ Dim TheseCoords As usrRect
+
+ lngViewRangePosX = PlotRangeHistory(1).x.ValEnd.Pos - PlotRangeHistory(1).x.ValStart.Pos
+ lngViewRangePosY = PlotRangeHistory(1).y.ValEnd.Pos - PlotRangeHistory(1).y.ValStart.Pos
+
+ If lngViewRangePosX = 0 Or lngViewRangePosY = 0 Then Exit Sub
+
+ TheseCoords = ZoomBoxCoords
+ FixUpCoordinates TheseCoords
+ With TheseCoords
+ lngBoxSizeX = Abs(.x2 - .x1)
+ lngBoxSizeY = Abs(.y2 - .y1)
+ If boolFixVertical Then
+ .x1 = PlotRangeHistory(1).x.ValStart.Pos
+ .x2 = PlotRangeHistory(1).x.ValEnd.Pos
+ Else
+ If lngBoxSizeX > 0 Then
+ lngPosCorrectionFactorX = (CLng(lngViewRangePosX * CDbl(lngViewRangePosX) / CDbl(lngBoxSizeX))) / 2
+ .x1 = .x1 - lngPosCorrectionFactorX
+ .x2 = .x2 + lngPosCorrectionFactorX
+ End If
+ End If
+ If boolFixHorizontal Then
+ .y1 = PlotRangeHistory(1).y.ValEnd.Pos
+ .y2 = PlotRangeHistory(1).y.ValStart.Pos
+ Else
+ If lngBoxSizeY > 0 Then
+ lngPosCorrectionFactorY = (CLng(lngViewRangePosY * CDbl(lngViewRangePosY) / CDbl(lngBoxSizeY))) / 2
+ .y1 = .y1 - lngPosCorrectionFactorY
+ .y2 = .y2 + lngPosCorrectionFactorY
+ End If
+ End If
+ End With
+
+ If lngBoxSizeX > 0 And lngBoxSizeY > 0 Then
+ ZoomBoxCoords = TheseCoords
+ HideZoomBox vbLeftButton, True
+ Else
+ HideZoomBox vbLeftButton, False
+ End If
+
+End Sub
+
+Private Function IsClickInBox(x As Single, y As Single, TheseZoomBoxCoords As usrRect) As Boolean
+ Dim FixedCoords As usrRect
+
+ ' Determine if click was inside or outside of zoom box
+ FixedCoords = FixUpCoordinates(TheseZoomBoxCoords)
+
+ With FixedCoords
+ If x >= .x1 And x <= .x2 And _
+ y >= .y1 And y <= .y2 Then
+ IsClickInBox = True
+ Else
+ IsClickInBox = False
+ End If
+ End With
+
+End Function
+
+Private Function IsZoomBoxLargeEnough(TheseCoords As usrRect) As Boolean
+
+ With TheseCoords
+ ' Don't zoom if box size is less than 150 by 150 twips
+ If Abs(.x2 - .x1) >= 150 And Abs(.y2 - .y1) >= 150 Then
+ IsZoomBoxLargeEnough = True
+ Else
+ IsZoomBoxLargeEnough = False
+ End If
+ End With
+
+End Function
+Private Sub PerformMove()
+
+ Dim TheseCoords As usrRect
+ Dim DeltaXVal As Double, DeltaYVal As Double
+ Dim MinimumXVal As Double, MaximumXVal As Double, MaximumRange As Double
+
+ TheseCoords = ZoomBoxCoords
+
+ With PlotRangeAtMoveStart
+ DeltaXVal = XYPosToValue(TheseCoords.x2, .x) - XYPosToValue(TheseCoords.x1, .x)
+ DeltaYVal = XYPosToValue(TheseCoords.y2, .y) - XYPosToValue(TheseCoords.y1, .y)
+ End With
+
+ PlotOptions.ZoomOutFull = False
+ With PlotOptions
+ MaximumRange = .DataLimits.x.ValEnd.Val - .DataLimits.x.ValStart.Val
+ .Scaling.x.ValStart.Val = PlotRangeAtMoveStart.x.ValStart.Val - DeltaXVal
+ MinimumXVal = .DataLimits.x.ValStart.Val - MaximumRange / 10
+ If .Scaling.x.ValStart.Val < MinimumXVal Then
+ .Scaling.x.ValStart.Val = MinimumXVal
+ .Scaling.x.ValEnd.Val = .Scaling.x.ValStart.Val + (PlotRangeAtMoveStart.x.ValEnd.Val - PlotRangeAtMoveStart.x.ValStart.Val)
+ Else
+ .Scaling.x.ValEnd.Val = PlotRangeAtMoveStart.x.ValEnd.Val - DeltaXVal
+ End If
+
+ MaximumXVal = .DataLimits.x.ValEnd.Val + MaximumRange / 10
+ If .Scaling.x.ValEnd.Val > MaximumXVal Then
+ .Scaling.x.ValEnd.Val = MaximumXVal
+ .Scaling.x.ValStart.Val = .Scaling.x.ValEnd.Val - (PlotRangeAtMoveStart.x.ValEnd.Val - PlotRangeAtMoveStart.x.ValStart.Val)
+ End If
+ .Scaling.y.ValStart.Val = PlotRangeAtMoveStart.y.ValStart.Val - DeltaYVal
+ .Scaling.y.ValEnd.Val = PlotRangeAtMoveStart.y.ValEnd.Val - DeltaYVal
+ End With
+
+ ' By setting TickCountToUpdateAt to a nonzero value (>= TicksElapsedSinceStart), the
+ ' move will be performed when TicksElapsedSinceStart reaches TickCountToUpdateAt
+ TickCountToUpdateAt = TicksElapsedSinceStart
+End Sub
+
+Private Sub PerformZoom()
+ Dim TheseCoords As usrRect, boolAbortZoom As Boolean
+ Dim PlotRangeSaved As usrPlotRange
+
+ ' Use the numbers stored in PlotRangeSaved to update the PlotOptions with the desired zoom range
+ PlotRangeSaved = PlotRangeHistory(1) ' The most recent plot range
+
+ TheseCoords = FixUpCoordinates(ZoomBoxCoords)
+
+ If IsZoomBoxLargeEnough(TheseCoords) Then
+ PlotOptions.ZoomOutFull = False
+ With PlotOptions.Scaling
+ .x.ValStart.Val = XYPosToValue(TheseCoords.x1, PlotRangeSaved.x)
+ .x.ValEnd.Val = XYPosToValue(TheseCoords.x2, PlotRangeSaved.x)
+ .y.ValStart.Val = XYPosToValue(TheseCoords.y1, PlotRangeSaved.y)
+ .y.ValEnd.Val = XYPosToValue(TheseCoords.y2, PlotRangeSaved.y)
+ End With
+
+ UpdatePlot
+ End If
+
+End Sub
+
+Private Sub PositionControls()
+ Dim PlotHeight As Long
+
+ With fraOptions
+ .Left = 50
+ .Top = Me.Height - .Height - 700
+ .Visible = False
+ End With
+
+ With fraPlot
+ .Top = 50
+ .Left = 50
+ .Width = Me.Width - 250
+ If fraOptions.Visible Then
+ PlotHeight = Me.Height - fraOptions.Height - 600
+ Else
+ PlotHeight = Me.Height - 600
+ End If
+
+ If PlotHeight < 1 Then PlotHeight = 1
+ .Height = PlotHeight
+
+ lblCurrentPos.Top = 0
+ lblCurrentPos.Left = fraPlot.Width - lblCurrentPos.Width - 100
+ End With
+
+End Sub
+
+Private Sub RedrawZoomBox()
+ Dim TheseCoords As usrRect
+
+ TheseCoords = ZoomBoxCoords
+
+ With TheseCoords
+ If .x1 > .x2 Then
+ SwapValues .x1, .x2
+ End If
+ If .y1 > .y2 Then
+ SwapValues .y1, .y2
+ End If
+
+ End With
+
+ ' When the box size gets large enough, turn on boolDrawingZoomBox
+ If IsZoomBoxLargeEnough(TheseCoords) Then
+ boolDrawingZoomBox = True
+ End If
+
+ With shpZoomBox
+ .Left = TheseCoords.x1
+ .Top = TheseCoords.y1
+ .Width = TheseCoords.x2 - TheseCoords.x1
+ .Height = TheseCoords.y2 - TheseCoords.y1
+ End With
+End Sub
+
+Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
+ If KeyCode = 32 Then
+ SetCursorMode True
+ SetCursorIcon
+ ElseIf KeyCode = vbKeyEscape Then
+ mnuClose_Click
+ ElseIf KeyCode = 90 And (Shift Or vbCtrlMask) Then
+ ' Ctrl+Z
+ ZoomOut False
+ End If
+
+End Sub
+Private Sub Form_KeyUp(KeyCode As Integer, Shift As Integer)
+ If KeyCode = 32 Then
+ SetCursorMode False
+ SetCursorIcon
+ End If
+End Sub
+
+Private Sub Form_Load()
+ SizeAndCenterWindow Me, cWindowExactCenter, 8000, 7000, True
+
+ Dim x As Integer
+
+ With cboLabelsToShow
+ For x = 0 To 20
+ .AddItem Trim(Str(x))
+ Next x
+ .ListIndex = 3
+ End With
+
+ InitializePlotOptions
+
+ shpZoomBox.Visible = False
+
+ mnuCursorMode.Caption = mnuCursorMode.Caption & vbTab & "Space Enables Move"
+ mnuZoomIn.Caption = mnuZoomIn.Caption & vbTab & "Left Click"
+ mnuZoomOutToPrevious.Caption = mnuZoomOutToPrevious.Caption & vbTab & "Ctrl+Z or Right Click"
+
+ EnableDisableZoomMenus False
+
+End Sub
+
+Private Sub Form_MouseMove(Button As Integer, Shift As Integer, x As Single, y As Single)
+ ResetMousePointer Button
+End Sub
+
+Private Sub Form_Resize()
+ PositionControls
+ If Me.WindowState <> vbMinimized Then
+ TickCountToUpdateAt = TicksElapsedSinceStart + 1
+ boolResizingWindow = True
+ End If
+End Sub
+
+Private Sub Form_Unload(Cancel As Integer)
+ Dim objThisForm As Form
+
+ For Each objThisForm In Forms
+ If objThisForm.Name <> Me.Name Then
+ Unload objThisForm
+ End If
+ Next
+End Sub
+
+Private Sub fraOptions_MouseMove(Button As Integer, Shift As Integer, x As Single, y As Single)
+ ResetMousePointer Button
+End Sub
+
+Private Sub fraPlot_MouseDown(Button As Integer, Shift As Integer, x As Single, y As Single)
+
+ Dim boolClickInsideBox As Boolean
+ boolClickInsideBox = IsClickInBox(x, y, ZoomBoxCoords)
+
+ If Not shpZoomBox.Visible Or Not boolClickInsideBox Then
+ InitializeZoomOrMove Button, x, y
+ Else
+ ' The Zoom Box is visible
+ ' The click is also handled in Sub fraPlot_MouseUp since it is more customary to handle clicks with _MouseUp events
+ If boolZoomBoxDrawn = True Then
+ RespondZoomModeClick Button, x, y
+ End If
+ End If
+End Sub
+
+Private Sub fraPlot_MouseMove(Button As Integer, Shift As Integer, x As Single, y As Single)
+ If Button = 0 Then
+ SetCursorIcon x, y
+ End If
+
+ ResizeZoomBox Button, x, y
+
+ boolUpdatePosition = True
+ CurrentPosX = x
+ CurrentPosY = y
+
+End Sub
+
+Private Sub fraPlot_MouseUp(Button As Integer, Shift As Integer, x As Single, y As Single)
+ Dim intIndex As Integer
+
+ If mnuCursorModeZoom.Checked Then
+ ' Zooming, the box is shown at the size the user chose
+ ' Handle the click differently depending on the location and the button
+
+ If boolZoomBoxDrawn = True Then
+ ' Do nothing
+ ElseIf boolDrawingZoomBox Then
+ boolZoomBoxDrawn = True
+ EnableDisableZoomMenus IsZoomBoxLargeEnough(ZoomBoxCoords)
+ End If
+ Else
+ ' Moving plot
+ ' Turn off boolSlidingGraph
+ boolSlidingGraph = False
+
+ ' Set TickCountToUpdateAt back to 0 so no more udpates occur
+ TickCountToUpdateAt = 0
+
+ ' Update the plot one more time so new view gets saved to history
+ UpdatePlot True
+
+ ' For some reason the history still has two copies of the most recent view
+ ' Remove one of them
+ For intIndex = 2 To PLOT_RANGE_HISTORY_COUNT - 1
+ PlotRangeHistory(intIndex) = PlotRangeHistory(intIndex + 1)
+ Next intIndex
+ End If
+
+End Sub
+
+
+Private Sub mnuAutoScaleYAxis_Click()
+ SetAutoscaleY Not mnuAutoScaleYAxis.Checked
+End Sub
+
+Private Sub mnuClose_Click()
+ Unload Me
+End Sub
+
+Private Sub mnuCursorModeMove_Click()
+ SetCursorMode True
+End Sub
+
+Private Sub mnuCursorModeZoom_Click()
+ SetCursorMode False
+End Sub
+
+Private Sub mnuExportData_Click()
+ ExportData
+End Sub
+
+Private Sub mnuFixMinimumYAtZero_Click()
+ SetFixMinimumAtZero Not mnuFixMinimumYAtZero.Checked
+End Sub
+
+Private Sub mnuGridLinesXAxis_Click()
+ SetGridlinesXAxis Not mnuGridLinesXAxis.Checked
+End Sub
+
+Private Sub mnuGridLinesYAxis_Click()
+ SetGridlinesYAxis Not mnuGridLinesYAxis.Checked
+End Sub
+
+Private Sub mnuInitializeData_Click()
+ InitializeDummyData 0
+End Sub
+
+Private Sub mnuInitializeStickData_Click()
+ InitializeDummyData 1
+End Sub
+
+Private Sub mnuInitializeStickDataLots_Click()
+ InitializeDummyData 2
+
+End Sub
+
+Private Sub mnuOptions_Click()
+ EnableDisableMenuCheckmarks
+End Sub
+
+Private Sub mnuPeaksToLabel_Click()
+ SetPeaksToLabel
+End Sub
+
+Private Sub mnuPlotTypeLinesBetweenPoints_Click()
+ SetPlotType True
+End Sub
+
+Private Sub mnuPlotTypeSticksToZero_Click()
+ SetPlotType False
+End Sub
+
+Private Sub mnuSetRangeX_Click()
+ SetNewRange True, False
+End Sub
+
+Private Sub mnuSetRangeY_Click()
+ SetNewRange False, True
+End Sub
+
+Private Sub mnuSetResolution_Click()
+ SetResolution
+End Sub
+
+Private Sub mnuShowCurrentPosition_Click()
+ SetShowCursorPosition Not mnuShowCurrentPosition.Checked
+End Sub
+
+Private Sub mnuTicksXAxis_Click()
+ TickCountUpdateByUser txtXAxisTickCount, "X"
+End Sub
+
+Private Sub mnuTicksYAxis_Click()
+ TickCountUpdateByUser txtYAxisTickCount, "Y"
+End Sub
+
+Private Sub mnuZoomIn_Click()
+ HideZoomBox vbLeftButton, True
+End Sub
+
+Private Sub mnuZoomInHorizontal_Click()
+ ZoomInHorizontal
+End Sub
+
+Private Sub mnuZoomInVertical_Click()
+ ZoomInVertical
+End Sub
+
+Private Sub mnuZoomOut_Click()
+ ZoomShrink False, False
+End Sub
+
+Private Sub mnuZoomOutFullScale_Click()
+ ZoomOut True
+End Sub
+
+Private Sub mnuZoomOutHorizontal_Click()
+ ZoomShrink True, False
+End Sub
+
+Private Sub mnuZoomOutToPrevious_Click()
+ ZoomOut False
+End Sub
+
+Private Sub mnuZoomOutVertical_Click()
+ ZoomShrink False, True
+End Sub
+
+Private Sub tmrUpdatePlot_Timer()
+ ' Note: the internal for the timer is 250 msec
+
+ TicksElapsedSinceStart = TicksElapsedSinceStart + 1
+ If TickCountToUpdateAt > 0 Then
+ UpdatePlotWhenIdle
+ End If
+
+ If boolUpdatePosition Then UpdateCurrentPos
+End Sub
+
+Private Sub txtXAxisTickCount_KeyPress(KeyAscii As Integer)
+ TextBoxKeyPressHandler txtXAxisTickCount, KeyAscii, True, False
+End Sub
+
+Private Sub txtXAxisTickCount_Validate(Cancel As Boolean)
+ ValidateTextboxValueDbl txtXAxisTickCount, 2, 50, 10
+ SetPlotOptions True, False
+End Sub
+
+Private Sub txtYAxisTickCount_KeyPress(KeyAscii As Integer)
+ TextBoxKeyPressHandler txtYAxisTickCount, KeyAscii, True, False
+End Sub
+
+Private Sub txtYAxisTickCount_Validate(Cancel As Boolean)
+ ValidateTextboxValueDbl txtYAxisTickCount, 2, 50, 10
+ SetPlotOptions True, False
+End Sub
diff --git a/MsPlot/SetRange.frm b/MsPlot/SetRange.frm
new file mode 100644
index 0000000..71ad44f
--- /dev/null
+++ b/MsPlot/SetRange.frm
@@ -0,0 +1,140 @@
+VERSION 5.00
+Begin VB.Form frmSetValue
+ BorderStyle = 3 'Fixed Dialog
+ Caption = "Set Range"
+ ClientHeight = 1065
+ ClientLeft = 45
+ ClientTop = 330
+ ClientWidth = 3945
+ ClipControls = 0 'False
+ ControlBox = 0 'False
+ LinkTopic = "Form1"
+ MaxButton = 0 'False
+ MinButton = 0 'False
+ ScaleHeight = 1065
+ ScaleWidth = 3945
+ ShowInTaskbar = 0 'False
+ StartUpPosition = 3 'Windows Default
+ Begin VB.TextBox txtEndVal
+ Height = 285
+ Left = 1320
+ TabIndex = 3
+ Text = "5"
+ Top = 600
+ Width = 975
+ End
+ Begin VB.CommandButton cmdCancel
+ Cancel = -1 'True
+ Caption = "&Cancel"
+ Height = 375
+ Left = 2760
+ TabIndex = 5
+ Top = 600
+ Width = 1095
+ End
+ Begin VB.CommandButton cmdSet
+ Caption = "&Set"
+ Default = -1 'True
+ Height = 375
+ Left = 2760
+ TabIndex = 4
+ Top = 120
+ Width = 1095
+ End
+ Begin VB.TextBox txtStartVal
+ Height = 285
+ Left = 120
+ TabIndex = 1
+ Text = "5"
+ Top = 600
+ Width = 975
+ End
+ Begin VB.Label lblHiddenStatus
+ Caption = "Hidden Status"
+ Height = 255
+ Left = 120
+ TabIndex = 6
+ Top = 960
+ Visible = 0 'False
+ Width = 1335
+ End
+ Begin VB.Label lblEndVal
+ Caption = "End Val"
+ Height = 435
+ Left = 1320
+ TabIndex = 2
+ Top = 120
+ Width = 1215
+ End
+ Begin VB.Label lblStartVal
+ Caption = "Start Val"
+ Height = 435
+ Left = 120
+ TabIndex = 0
+ Top = 120
+ Width = 1035
+ End
+End
+Attribute VB_Name = "frmSetValue"
+Attribute VB_GlobalNameSpace = False
+Attribute VB_Creatable = False
+Attribute VB_PredeclaredId = True
+Attribute VB_Exposed = False
+Option Explicit
+
+Private boolCoerceDataWithinLimits As Boolean
+Private TheseDataLimits As usrPlotRangeAxis
+Private localDefaultSeparationValue As Double
+
+Public Sub SetLimits(boolLclCoerceDataWithinLimits As Boolean, Optional dblLowerLimit As Double = 0, Optional dblUpperLimit As Double = 100, Optional dblDefaultSeparationValue As Double = 1)
+ boolCoerceDataWithinLimits = boolLclCoerceDataWithinLimits
+ If boolLclCoerceDataWithinLimits Then
+ TheseDataLimits.ValStart.Val = dblLowerLimit
+ TheseDataLimits.ValEnd.Val = dblUpperLimit
+ localDefaultSeparationValue = dblDefaultSeparationValue
+ End If
+End Sub
+
+Private Sub cmdCancel_Click()
+ lblHiddenStatus = "Cancel"
+ Me.Hide
+End Sub
+
+Private Sub cmdSet_Click()
+ ' Must re-validate data since data is not validated if user presses Enter after changing a value
+ If boolCoerceDataWithinLimits Then
+ ValidateDualTextBoxes txtStartVal, txtEndVal, False, CDbl(TheseDataLimits.ValStart.Val), CDbl(TheseDataLimits.ValEnd.Val), CDbl(localDefaultSeparationValue)
+ End If
+
+ lblHiddenStatus = "Ok"
+ Me.Hide
+End Sub
+
+Private Sub Form_Activate()
+ cmdSet.Caption = "&Set"
+ cmdCancel.Caption = "&Cancel"
+End Sub
+
+Private Sub Form_Load()
+ SizeAndCenterWindow Me, cWindowUpperThird, , , False
+End Sub
+
+Private Sub txtEndVal_KeyPress(KeyAscii As Integer)
+ TextBoxKeyPressHandler txtEndVal, KeyAscii, True, True, True, False, False, False, False, False, False, True, True
+End Sub
+
+Private Sub txtEndVal_Validate(Cancel As Boolean)
+ If boolCoerceDataWithinLimits Then
+ ValidateDualTextBoxes txtEndVal, txtEndVal, False, CDbl(TheseDataLimits.ValStart.Val), CDbl(TheseDataLimits.ValEnd.Val), CDbl(localDefaultSeparationValue)
+ End If
+End Sub
+
+Private Sub txtStartVal_KeyPress(KeyAscii As Integer)
+ TextBoxKeyPressHandler txtStartVal, KeyAscii, True, True, True, False, False, False, False, False, False, True, True
+End Sub
+
+Private Sub txtStartVal_Validate(Cancel As Boolean)
+ If boolCoerceDataWithinLimits Then
+ ValidateDualTextBoxes txtStartVal, txtEndVal, False, CDbl(TheseDataLimits.ValStart.Val), CDbl(TheseDataLimits.ValEnd.Val), CDbl(localDefaultSeparationValue)
+ End If
+End Sub
diff --git a/MsPlot/msplot.exe b/MsPlot/msplot.exe
new file mode 100644
index 0000000..e6e1eef
Binary files /dev/null and b/MsPlot/msplot.exe differ
diff --git a/MsiSetup/Edit MwtWin_Installer.bat b/MsiSetup/Edit MwtWin_Installer.bat
new file mode 100644
index 0000000..4111505
--- /dev/null
+++ b/MsiSetup/Edit MwtWin_Installer.bat
@@ -0,0 +1 @@
+"C:\Program Files\Microsoft Visual Studio\Common\IDE\IDE98\DEVENV.EXE" "D:\My Documents\Projects\DataMining\MwtWin\MsiSetup\MwtWinMsiSetup.sln"
\ No newline at end of file
diff --git a/MsiSetup/MwtWinMsiSetup.cache b/MsiSetup/MwtWinMsiSetup.cache
new file mode 100644
index 0000000..551f8da
Binary files /dev/null and b/MsiSetup/MwtWinMsiSetup.cache differ
diff --git a/MsiSetup/MwtWinMsiSetup.sln b/MsiSetup/MwtWinMsiSetup.sln
new file mode 100644
index 0000000..e0c7e05
--- /dev/null
+++ b/MsiSetup/MwtWinMsiSetup.sln
@@ -0,0 +1,11 @@
+Microsoft Visual Studio Solution File, Format Version 1.00
+Project("{73393D18-DAC4-11D1-88FC-0000F8064EBB}") = "Molecular Weight Calculator", "MwtWinMsiSetup.wip", "{33F9AE61-54B2-11D4-AB35-BA6DD7159C2F}"
+EndProject
+Global
+ GlobalSection(LocalDeployment) = postSolution
+ StartupProject = {00000000-0000-0000-0000-000000000000}
+ EndGlobalSection
+ GlobalSection(BuildOrder) = postSolution
+ 0 = {33F9AE61-54B2-11D4-AB35-BA6DD7159C2F}
+ EndGlobalSection
+EndGlobal
diff --git a/MsiSetup/MwtWinMsiSetup.wip b/MsiSetup/MwtWinMsiSetup.wip
new file mode 100644
index 0000000..e9b1724
Binary files /dev/null and b/MsiSetup/MwtWinMsiSetup.wip differ
diff --git a/MsiSetup/ZippedForUpload/SetupHelp.txt b/MsiSetup/ZippedForUpload/SetupHelp.txt
new file mode 100644
index 0000000..fef0489
--- /dev/null
+++ b/MsiSetup/ZippedForUpload/SetupHelp.txt
@@ -0,0 +1,56 @@
+Molecular Weight Calculator
+
+This program can calculate the molecular weight and percent composition
+of chemical formulas and amino acids, providing a graphical user interface to
+edit the formulas and parsing options. It recognizes user-definable
+abbreviations, custom elemental isotopes, and can display up to 20 compounds
+simultaneously. It also includes a Mole/Mass Converter, Formula Finder,
+Capillary Flow Modeller, Amino Acid Notation Converter, Peptide Sequence
+Fragmentation Modeler, Isotopic Distribution Calculator, and built-in
+calculator. Full program documentation is available by pressing F1 during
+program operation.
+
+To install the Molecular Weight Calculator for Windows
+9x/NT/00/ME/XP, run the "Molecular Weight Calculator.msi" file by
+double-clicking on it. The install program should take care of
+copying the files to the correct locations and registering all of
+the components. If replacing an older version, the .INI and .DAT
+files will be replaced. If you have abbreviations you want to save,
+backup the MWT_ABBR.DAT file before installing.
+
+Note: Sometimes when upgrading from a previous version the Lang*.Ini
+and MwtWin.Chm files do not get upgraded to the current version.
+For this reason, if uprgrading, please delete the Lang*.ini and MwtWin.Chm
+files in the Molecular Weight Calculator directory before running the
+"Molecular Weight Calculator.msi" file. I apologize for the
+inconvenience but have not found a way to fix the problem using the
+current version of the Windows Installer. There are new versions of the
+installer available, but I do not want to force users to have to update
+their Windows Installer simply to install this software.
+
+If you do not have the Windows Installer on your machine, the .msi
+file will not run and you must install the Windows Installer (it is
+included by default in Windows 2000 and higher). I did not include the
+Windows Installer as part of this download because it is an additional
+1.4 MB to download. You can download the Windows Installer from Microsoft:
+
+If running Windows 95/98, download
+ http://download.microsoft.com/download/platformsdk/wininst/1.1/W9X/EN-US/InstMsi.exe
+
+If running Windows NT, download
+ http://download.microsoft.com/download/platformsdk/wininst/1.1/NT4/EN-US/InstMsi.exe
+
+Once you have installed the Windows Installer, you should be able
+to run the "Molecular Weight Calculator.msi" setup file.
+
+-------------------------------------------------------------------------------
+Written by Matthew Monroe for the Department of Energy (PNNL, Richland, WA)
+
+E-mail: matthew.monroe@pnl.gov or matt@alchemistmatt.com
+Website: http://ncrr.pnl.gov/ or http://www.sysbio.org/resources/staff/ or
+http://www.alchemistmatt.com/ or http://come.to/alchemistmatt/
+-------------------------------------------------------------------------------
+
+Licensed under the Apache License, Version 2.0; you may not use this file except
+in compliance with the License. You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
diff --git a/Mwt Dos/COMMENT.TXT b/Mwt Dos/COMMENT.TXT
new file mode 100644
index 0000000..460741e
--- /dev/null
+++ b/Mwt Dos/COMMENT.TXT
@@ -0,0 +1,11 @@
+
+
+ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
+º º
+º This is a self extracting zip file. You can erase it after º
+º it has created the MWT.EXE, MWT.HLP, and MWT.ICO files º
+º Type MWT to start the program. Type MWT /? for program information. º
+º Be sure to read the MWT.HLP file. º
+º º
+ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ
+
diff --git a/Mwt Dos/COMMENT2.TXT b/Mwt Dos/COMMENT2.TXT
new file mode 100644
index 0000000..4d17225
--- /dev/null
+++ b/Mwt Dos/COMMENT2.TXT
@@ -0,0 +1,9 @@
+
+
+ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
+º º
+º Type MWT to start the program. Type MWT /? for program information. º
+º Be sure to read the README.TXT and MWT.HLP files. º
+º º
+ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ
+
diff --git a/Mwt Dos/MAKEIT.BAT b/Mwt Dos/MAKEIT.BAT
new file mode 100644
index 0000000..35274f0
--- /dev/null
+++ b/Mwt Dos/MAKEIT.BAT
@@ -0,0 +1,10 @@
+echo Re-creating MWT2_87.ZIP and .EXE files
+del mwt2_87*.*
+attrib mwt*.* -r
+fd mwt*.* /d1-1-97 /t2:08a
+attrib mwt_abbr.bkk +r
+pkzip mwt2_87.zip mwt*.* -ex -z < comment.txt
+zip2exe mwt2_87.zip
+rem uuencode -s mwt2_85.exe
+fd mwt2_87.* /d1-1-97 /t2:08a
+echo.
diff --git a/Mwt Dos/MAKESIMT.BAT b/Mwt Dos/MAKESIMT.BAT
new file mode 100644
index 0000000..0b2b1af
--- /dev/null
+++ b/Mwt Dos/MAKESIMT.BAT
@@ -0,0 +1,9 @@
+echo Re-creating MWT2_87s.ZIP
+del mwt2_87*.*
+attrib mwt*.* -r
+fd mwt*.* /d1-1-97 /t2:08a
+fd readme.txt /d1-1-97 /t2:08a
+attrib mwt_abbr.bkk +r
+pkzip mwt2_87s.zip mwt*.* -ex -z < comment2.txt
+pkzip mwt2_87s.zip readme.txt -a -ex
+fd mwt2_87s.* /d1-1-97 /t2:08a
diff --git a/Mwt Dos/MWT.EXE b/Mwt Dos/MWT.EXE
new file mode 100644
index 0000000..26ba23b
Binary files /dev/null and b/Mwt Dos/MWT.EXE differ
diff --git a/Mwt Dos/MWT.HLP b/Mwt Dos/MWT.HLP
new file mode 100644
index 0000000..4dd57a9
--- /dev/null
+++ b/Mwt Dos/MWT.HLP
@@ -0,0 +1,776 @@
+ MOLECULAR WEIGHT CALCULATOR
+ by Matthew Monroe
+ Revision 2.87 January 1997
+
+ This program is Freeware; distribute freely.
+
+
+FEATURES
+-------------------------------------------------------------------------------
+ Full On-Line Help - Eleven help screens available during program operation.
+
+ Smart Case Conversion - The program will automatically convert lowercase
+ letters to uppercase where appropriate for ease
+ of entering a formula. Exact case matching and
+ non-conversion are available too.
+
+ Multi-Line Display - Display of up to seven formulas with their
+ molecular weights simultaneously.
+
+ Percent Composition - Percent composition of up to seven formulas.
+
+ Parentheses Are Allowed: (CH3)3CH2CH3
+ Handles up to 4 layers of embedded parentheses.
+
+ Hydrates or other appended compounds are allowed: FeCl3-6H2O
+
+ User-definable abbreviations.
+ Default abbreviations are included for common parts of compounds,
+ including amino acids.
+ See full list below.
+ For example: PhCl = C6H5Cl
+ HOac = CH3COOH
+
+ The MWTPATH environment variable may be set to avoid creation of
+ duplicate MWT_ABBR.DAT files on the hard drive.
+
+ Isotopes are now recognized using the following notation:
+ ^13C is Carbon-13
+ C6H5^18OH is heavy-oxygen (Oxygen-18) labeled phenol
+
+ Feature of weighting parts of a compound relative to the other parts.
+ For example: [.2Na]Cl would have a weight of 0.2*22.989768+35.4527=40.0507
+ or NaCl-[.5H2O] would have a weight of:
+ 22.989768+35.4527+0.5*(2*1.00794+15.9994)=67.4501
+
+ Percent Solver mode for finding the value of "x" in a compound that
+ satisfies user-specified percent composition requirements.
+
+ Built in calculator that understands operator precedence:
+ 4*5-2*3 = 14
+ (23.43-2.64*3)/6 = 2.585
+ 2+2^4 = 18
+
+ Optional display of time during program operation.
+
+ Accuracy of the final digit of the molecular wt. and percent composition.
+
+ Capability to set optional features at the command line when starting
+ the program.
+
+
+AVAILABILITY
+-------------------------------------------------------------------------------
+ Dos Version (MWT v2.87)
+
+The program is available via the web at http://plains.uwyo.edu/~monroem/ or at
+http://www.coast.net/SimTel/msdos/chemstry.html and
+http://www.cdrom.com/simtel.net/msdos/chemstry.html and
+http://www.simtel.net/pub/simtelnet/msdos/chemstry/ in the mwt2_87.zip file
+
+The program is also available via Anonymous FTP at ftp.coast.net under the
+SimTel/msdos/chemstry/ directory in the mwt2_87.zip file, at ftp.simtel.net
+under pub/simtelnet/msdos/chemstry/ in the mwt2_87.zip file, and ftp.osc.edu
+under the pub/chemistry/software/MS-DOS/Molecular-Weight-Calculator/ directory
+in the mwt2_87.exe file.
+
+
+ Windows Version (MWT Win v3.2)
+
+The program is available via the web at http://plains.uwyo.edu/~monroem/ or at
+http://www.coast.net/SimTel/win3/chem.html and
+http://www.cdrom.com/simtel.net/win3/chem.html and
+http://www.simtel.net/pub/simtelnet/win3/chem/ under the file mwt3_2.zip
+
+The program is also available via Anonymous FTP at ftp.coast.net under the
+SimTel/win3/chem/ directory in the mwt3_2.zip file, at ftp.simtel.net under
+pub/simtelnet/win3/chem/ in the mwt3_2.zip file, and ftp.osc.edu under the
+pub/chemistry/software/MS-WINDOWS/Molecular_Weight/ directory in the
+mwt3_2.exe or mwt3_2s.exe files.
+
+ As a final option, I can mail you a UUEncoded or MIME encoded version
+via e-mail; just drop me a line.
+
+
+INSTRUCTIONS
+-------------------------------------------------------------------------------
+Directions for Use:
+ Start the program by typing MWT at the command line. Typing MWT /? shows
+ a list of options for setting internal program options before starting
+ the program. All of the options may also be toggled while the program
+ is running.
+
+Formulas
+ Once the program starts, you may enter a molecule's formula on the
+ numbered line. Use the LEFT and RIGHT arrow keys, HOME key, and END key
+ to navigate a line. Press the INSERT key to toggle Insert/Overstrike
+ which affects how typed characters modify the current line. Calculate
+ the weight of a formula by pressing the ENTER key. In multi-formula mode,
+ this will create a new blank line for a new formula, with a maximum of
+ seven formulas. This is useful for comparing molecular weights of
+ compounds. Move among the lines using the UP and DOWN arrow keys or
+ the TAB and SHIFT-TAB keys. Pressing ENTER on line 'n' when
+ line 'n+1' already has a formula will simply move the cursor to line n+1.
+ A formula can consist of elements, element subscripts, parentheses, and
+ dashes (-) followed by numbers to separate parts of a compound
+ (!!NOT!! subtract them). For example FeCl3-6H2O means ferric chloride
+ with 6 water molecules attached. As shown, an integer can follow the dash,
+ though it's not required. In fact, the dash can be used many times to add
+ multiple hydrates onto a compound (if you have the desire). Also, other
+ molecules besides hydrates can be added. For example (fictional compound)
+ C6H6-H2O-2ZnHgMg-U would be benzene + water + 2*(zinc-mercury-magnesium) +
+ uranium for a total molecular weight of 1152.76
+
+ NOTE: For Radioactive elements, the most stable isotope is NOT used;
+ Instead, an average Mol. Weight is used, just like with other elements.
+ See the Isotopes section for the method of indicating an exact isotopic
+ mass. Data obtained from the Perma-Chart Science Series Chemical Periodic
+ Table, 1993; ISBN 1-55080-063-9.
+
+Brackets
+ One more feature a formula may contain is brackets to "weight" specific
+ parts of a compound relative to the other parts. For example,
+ [.2Na]Cl would have a weight of 0.2*22.989768+35.4527=40.0507
+ and NaCl-[.5H2O] would have a weight of:
+ 22.989768+35.4527+0.5*(2*1.00794+15.9994)=67.4501
+ A colleague of mine requested this feature for the purpose of trying to
+ figure out if a compound he had synthesized and sent off for elemental
+ analysis had a little bit of water in it (hadn't been completely
+ dried), as in C6H6-[.1H2O], to see if the theoretical percent composition
+ data would better match the actual lab results. As you can see, decimal
+ numbers can be used after brackets whereas they cannot be used after
+ closing parentheses or after a dash.
+
+ NOTE: The percent solver feature will perform this operation
+ for you -- see the percent solver section below.
+
+Percent Composition
+ You can see the percent composition of the compounds by pressing the
+ F1 key. Although only one formula is shown at a time, the other formulas
+ are kept in memory and can be cycled through using the UP and DOWN keys
+ or TAB and SHIFT-TAB keys without switching back to Multi-Mode. In
+ Single-View Mode the formulas can still be completely modified. Again,
+ the ENTER key will calculate a formula's molecular weight and percent
+ composition. However, in Single-View Mode, pressing the ENTER key will
+ keep the same formula visible; only the UP and DOWN arrow keys will move
+ to a new formula in Single-View Mode.
+
+Abbreviations
+ Use the F3 key to cycle through the three abbreviation recognition
+ modes: No recognition, Normal recognition, and Amino Acid (Extended)
+ recognition. The MWT_ABBR.DAT file contains the default abbreviations
+ included with the program (listed below). You can add your own
+ abbreviations, up to 100 normal and 50 extended abbreviations. The
+ following conventions must be followed: 1) Comments may be added by
+ preceding the comment with an apostrophe; 2) Two group headings must exist:
+ [AMINO ACIDS] and [ABBREVIATIONS]; 3) Abbreviations consist of the
+ abbreviation and molecular formula under the appropriate column in
+ either section; 4) Only the first letter of an abbreviation is allowed
+ to be capitalized; 5) Elements MUST be properly capitalized; eg. na is
+ incorrect, use Na; 6) Parentheses and dashes are NOT allowed; eg. CH3(CH2)2
+ is incorrect, use C3H7 or CH3CH2CH2; 7) The abbreviations in the Amino Acid
+ section are treated as extended level abbreviations -- they are only
+ recognized when extended abbreviations are on; 8) The maximum length of
+ any abbreviation is 6 characters; 9) Abbreviation names may contain only
+ letters, while abbreviation formulas may contain letters and numbers only.
+ If the MWT_ABBR.DAT file becomes corrupted, the MWT program will inform
+ the user and ignore incorrect lines. If the file becomes deleted, the
+ MWT program will create a new file with the default abbreviations,
+ but without the abbreviation descriptions. The file MWT_ABBR.BKK is a
+ read-only file included in case the MWT_ABBR.DAT file is deleted and the
+ user wishes to manually restore it with all of the comments. The .BKK
+ file is not needed for abbreviation file re-creation, it is simply
+ included as a courtesy. Thus, if you were to copy just the MWT.EXE program
+ to a new computer/directory/etc., the program would recreate a fully
+ functional default MWT_ABBR.DAT file, even though the MWT_ABBR.BKK file
+ would not be present.
+ The MWTPATH environment variable may be set in your AUTOEXEC.BAT file
+ in order to ensure that multiple copies of the MWT_ABBR.DAT file are not
+ created on the hard drive. If not for this feature, multiple copies
+ would be created if the MWT.EXE program were located in a directory in
+ the path and you typed MWT from a different directory, causing the
+ program to re-create the MWT_ABBR.DAT file in each directory MWT is typed.
+ Two options are now available for avoiding this:
+ 1. Take the MWT.EXE program out of the path, put it in its own
+ directory, and write a batch file to run it, putting the batch
+ file in a directory in the path. A sample batch file is:
+ @ECHO OFF
+ C:
+ CD \MWT
+ MWT.EXE
+ CD \
+ 2. Place the following line in your AUTOEXEC.BAT file:
+ SET MWTPATH=C:\MWT
+ replacing C:\MWT with the directory where the program is located.
+ Now, when you type MWT from any directory, the program will run
+ (provided the C:\MWT directory is in the path), and it will look
+ in the C:\MWT directory for the MWT_ABBR.DAT file. Be sure to
+ update the SET MWTPATH= command if you move the MWT.EXE program and
+ the MWT_ABBR.DAT file. Also be sure to use the form MWTPATH= and
+ not MWTPATH = since the second one will not work.
+ One quirky aspect of abbreviation recognition is that the first
+ abbreviation of a user entered formula (during program operation) that is
+ matched to the available abbreviations is the abbreviation that will be
+ used -- furthermore, extended abbreviations are matched first if they
+ are turned on. For example, say the user types in the formula phen2-meph.
+ If only normal abbreviations are turned on, the program will match phen
+ to Phen and not to Ph and En since Phen appears first in the MWT_ABBR.DAT
+ file. To force the Ph and En abbreviations, type PhEn2-MePh. However, if
+ extended abbreviations have been activated (by pressing F3), the formula
+ phen2-meph will be translated to PheN2-MePh and nothing else, since the
+ program will match Phe to the amino acid phenylalanine, leaving the n to
+ be interpreted as nitrogen. Three methods exist to avoid this specific
+ problem: 1) Don't use extended abbreviations; 2) Erase the Phe amino acid;
+ 3) Place the Phen abbreviation in the amino acid section ABOVE the Phe
+ abbreviation, so that the program tries to match Phen before Phe. This
+ example should serve as a model for how to handle possible future
+ abbreviation conflicts. This example should also illustrate that if the
+ Phen abbreviation is placed anywhere below the Ph or En abbreviations in
+ the MWT_ABBR.DAT file, it will be IMPOSSIBLE for the program to recognize
+ it, since it will match Ph or En or both before even encountering Phen.
+ The following is a list of the default abbreviations included with this
+ program. Be aware that BPY is Boron-Phosphorus-Yttrium while Bpy is
+ bipyridine.
+
+ Default Abbreviations for Normal Recognition
+ (quasi-alphabetically, same as the order in the MWT_ABBR.DAT file)
+ (it is strongly suggested that longer abbreviations be placed first)
+ Abbreviation Group Formula Mol. Wt.
+ -------------------------------------------------------------------
+ Phen 1,10-Phenanthroline C12H8N2 180.209
+ Urea Urea H2NCONH2 60.05564
+ Bpy 2,2'-Bipyridine C10H8N2 156.187
+ (See Note 1)
+ Oac Acetate CH3COO 59.04462
+ Otf Triflate OSOOCF3 149.0704
+ Tpp Tetraphenylporphyrin (See Note 2) 612.7333
+ Bu Butyl CH3CH2CH2 57.11546
+ En Ethylenediamine H2NCH2CH2NH2 60.099
+ Et Ethyl CH3CH2 29.0617
+ Me Methyl CH3 15.03482
+ Ms Mesyl CH3SOO 79.09962
+ Ox Oxalate C2O4 88.0196
+ Ph Phenyl C6H5 77.1057
+ Py Pyridine C5H5N 79.10143
+ Ts Tosyl CH3C6H4SOO 155.1974
+ D (See Note 3) Deuterium Heavy hydrogen 2.01588
+
+ Note 1: 2,2'-Bipyridine is also known as 2,2'-Dipyridyl
+ Note 2: Tpp is (C4H2N(C6H5C)C4H2N(C6H5C))2 and is assumed to be
+ bound to a metal. Thus solid, pure Tpp would be notated
+ H2Tpp to add back the two hydrogens that leave upon complex formation.
+ Tpp is also known as 5,10,15,20-Tetraphenyl-21H,23H-porphine.
+ Note 3: It is suggested that D be used for deuterium rather than ^2H since
+ most deuterium used in the laboratory is of weight 2.0159 rather than
+ exactly 2, which is the weight ^2H would calculate as.
+
+ Default Abbreviations for Amino Acids
+ (alphabetically, same as the order in the MWT_ABBR.DAT file)
+ Abbreviation Amino Acid Formula Mol. Wt.
+ -------------------------------------------------------------------
+ Ala Alanine C3H5NO 71.07884
+ Arg Arginine C6H12N4O 156.1876
+ (unprotonated NH2)
+ Asn Asparagine C4H6N2O2 114.1039
+ Asp Aspartic acid C4H5NO3 115.0886
+ (undissociated COOH)
+ Cys Cysteine C3H5NOS 103.1448
+ (no disulfide link)
+ Gln Glutamine C5H8N2O2 128.1308
+ Glu Glutamic acid C5H7NO3 129.1155
+ (undissociated COOH)
+ Gly Glycine C2H3NO 57.05196
+ His Histidine C6H7N3O 137.1412
+ (unprotonated NH)
+ Hyp Hydroxyproline C5H7NO2 113.1161
+ Ile or Leu Isoleucine or Leucine C6H11NO 113.1595
+ Lys Lysine C6H12N2O 128.1742
+ (unprotonated NH2)
+ Met Methionine C5H9NOS 131.1986
+ Phe Phenylalanine C9H9NO 147.1766
+ Pro Proline C5H7NO 97.11671
+ Ser Serine C3H5NO2 87.07824
+ Thr Threonine C4H7NO2 101.1051
+ Trp Tryptophan C11H10N2O 186.2133
+ Tyr Tyrosine C9H9NO2 163.176
+ Val Valine C5H9NO 99.13259
+
+Isotopes
+ Isotopes may be entered in the form ^xY where x is the isotopic mass of
+ the isotope and Y is the name of the element. For example, ^13C is
+ carbon-13 and ^59Fe is iron-59. The program will check to make sure that
+ the isotopic mass entered is a reasonable value for the particular element
+ that it is associated with (see last section of Appendix B below). The
+ caret symbol (^) may be entered before any element in a formula, not
+ just at the beginning. For example, C6H5^18OH is oxygen-18 labeled
+ phenol. It has molecular weight 96.114 instead of 94.113
+ The isotopic mass entered is also used when figuring the percent
+ composition of a compound. Thus, C6H6 is 92.258% carbon and 7.7421%
+ hydrogen while ^13C6H6 is 92.8045% carbon and 7.1955% hydrogen.
+ Isotopic masses may not be entered for abbreviations. For example,
+ ^166Bpy is invalid. I considered allowing this, so that 166 would be
+ used for the weight of Bpy (rather than 156.187), but I decided that the
+ percent composition calculations would then be invalid since the program
+ would not know which elements in the abbreviation were contributing the
+ extra (or less) weight of the abbreviation. Therefore, for carbon-13
+ labeled Bpy, for example, simply type ^13C10H8N2 instead of ^166Bpy.
+
+ NOTE: It is suggested that D be used for deuterium rather than ^2H since
+ most deuterium used in the laboratory is of weight 2.0159 rather than
+ exactly 2, which is the weight ^2H would calculate as.
+
+Case Recognition
+ Use the F4 key to toggle the case recognition mode for the analysis of
+ a formula. In Exact Case Mode elements must be properly capitalized for
+ the program to recognize them. Only the first letter of abbreviations are
+ capitalized. In Smart Case Mode elements can be typed in lower case or
+ upper case and the program will make an educated guess as to what the
+ elements are. For example, nacl would be interpreted as sodium chloride.
+ However, the line will be left displayed the way it was typed in. In
+ Convert Case Up Mode the program will convert a line to proper notation
+ after it has analyzed the line. In the above example, the program would
+ redisplay the formula as NaCl. Another example, c6h6cl would become
+ C6H5Cl for chlorobenzene.
+
+Copying Formulas
+ Press the F2 key to copy a formula to a blank line (valid in both Multi
+ and Single-View modes). The program will search for a blank line on
+ all seven lines, and put the copy on that line. If no line is blank,
+ it will copy the formula to a new line, unless seven formulas already
+ exist. Also note that the program will not copy a blank line to a new
+ blank line.
+
+Erasing Single Formulas
+ Press the F6 key to erase the current formula or the calculator line.
+ The program will prompt you for confirmation. In Single-View mode this
+ will leave you with a blank line. Again, the other formulas (if present)
+ can be viewed using the UP and DOWN arrow keys.
+
+Erasing All Formulas
+ Press the F10 key to erase all the formulas and the calculator line.
+ Again, the program will prompt for confirmation. Pressing N (or any key
+ besides Y) will cause the screen to be re-written, but no formulas to be
+ erased.
+
+ NOTE: All Y,N prompts are not case sensitive; n is the same as N.
+
+Creating Blank Lines in Single-View Mode
+ The F5 key creates a new blank line in Single-View Mode and ONLY in that
+ mode. This is because ENTER in Single-View Mode calculates the current
+ line and does not create a new line. F5 is disabled in Multi-View mode
+ since there a new line is created whenever ENTER is pressed and the cursor
+ is on the lowest formula of the screen.
+
+Clock
+ The display of the time can be turned on or off with the F7 key.
+
+Help Screens
+ Use the F8 key to cycle through the nine help screens (disabled during
+ calculator mode).
+
+Standard Deviation
+ The F12 key cycles through the four standard deviation modes.
+ For H2O with molecular weight 18.01528 and std. dev. of ñ0.0003159114,
+ Mode 1 displays the result as 18.0153(ñ3)
+ Mode 2 displays it as 18.0153 (ñ3.159114E-04) (scientific notation)
+ Mode 3 displays it as 18.01528 (ñ.0003) (no rounding)
+ Off mode displays it as 18.01528, without standard deviation or rounding.
+
+Percent Solver Mode
+ The F11 key, or the PAGE UP and PAGE DOWN keys set the program in percent
+ solver mode. Use the PAGE UP and PAGE DOWN keys to move among the percent
+ compositions shown, and type in the target values for the solver to aim
+ for. Once you have typed in a value, a blue "L" will appear indicating
+ that the value is "Locked" to the user-specified value. Use the ENTER key
+ while on a percent composition line to toggle whether the percent is
+ or is not locked to the user specified value.
+ Before the solver can work, you need to place an x in the formula,
+ directly after a bracket. For example, "C6H6-[xH2O]" is useful for
+ calculating the amount of water in a benzene sample, provided elemental
+ analysis data is available. The formula must be in bracketed form for the
+ solver to work. If you have the formula "NaClx", where you wish to find
+ the number of chlorine atoms based on data, simply retype the formula in
+ the form "Na[xCl]" for the percent solver to be able to interpret the it.
+ When at least one percent is locked and an x is present after a bracket
+ in the formula, you may navigate the cursor to the formula line (via
+ PAGE UP and PAGE DOWN), then press ENTER to begin solving. The computer
+ will show you the progress of its calculations. Press any key during the
+ calculations to stop them before they are completed. The computer should
+ stop calculating once it gets the same answer four times in a row, which
+ should be to approximately four or five decimal places. Press the F11
+ key again to exit percent solver mode.
+
+ NOTE: If the program is not in Percent Solver mode, but an x is
+ present in the formula after a bracket, the program will calculate
+ the molecular weight based on x equaling one.
+
+The Calculator
+ The F9 key toggles display of the calculator. The calculator handles
+ the four operators +,-,*, and / plus parentheses, where / is for division.
+ The calculator also recognizes the caret (^) symbol for raising a number
+ to a power. For example, 2^3 is 8 and (5+3)^2 is 64. The calculator
+ understands operator precedence and will multiply and divide before adding
+ and subtracting. Furthermore, parentheses are obeyed. Press ENTER to
+ calculate the result. The result will stay visible even after F9 is
+ pressed again to return to the formulas, but will disappear when an error
+ occurs or when F9 is pressed AGAIN to return to the calculator. The
+ calculator can handle any number of parentheses.
+
+Errors
+ The program will display errors in red above the help section when
+ an incorrect entry is inputted. A red caret (^) symbol or red greater
+ than sign (>) will point to the location of the error in a formula. The
+ error message will disappear when a key is pressed. Any actual program
+ errors (errors with the code) should be trapped by an error trapping
+ routine, though I have tried to beta-test the program as much as possible
+ with every situation I can think of. Please just print the screen and
+ send me a note if you encounter and unhandled error.
+ The program will also display numerous "caution" messages for possibly
+ erroneous entries. This feature may be toggled on and off with CTRL-C.
+ It may also be set at the command line by typing
+
+Printing
+ The entire screen can be printed by pressing the PRINT-SCREEN key.
+ In Windows, use SHIFT-PRINT-SCREEN instead of just PRINT-SCREEN.
+
+Windows
+ This program will run perfectly well in a Dos window under Microsoft
+ Windows (or OS/2 for that matter). Simple create a new shortcut (Win95)
+ or program item (Win 3.x) with MWT.EXE as the program file name. I have
+ also included the file MWT.ICO, a simple icon file that can be referenced
+ via the "Change Icon" button while setting up the shortcut or program item.
+ I suggest running the program full screen, though, if you wish, it can
+ be run windowed so that you use the mouse to highlight any part of the
+ screen (select Edit-Mark under the top left box) and copy it to a Windows
+ based program. Note that there is also a Windows version of this program
+ available (see the availability section above).
+
+Exiting the Program
+ Press the ESC key and then press y or Y key to exit the program.
+
+
+THE AUTHOR
+-------------------------------------------------------------------------------
+Contacting the Author
+ You can contact me by E-mail at Monroem@UWyo.Edu until
+ I graduate in May 1997. After that, E-mail BPat@UWyo.Edu
+ for information on my whereabouts.
+
+About the Author
+ I am an undergraduate chemistry major at the University of Wyoming
+ in Laramie, Wyoming. I plan to attend graduate school and aim to
+ obtain a doctorate in chemistry. I taught myself to program in BASIC on
+ an Apple //c (with 128 Kb of Ram and no hard disk) in 1986 during
+ 6th grade. Since then, I have updated to GW-Basic, then QuickBasic v4.5,
+ QuickBasic v7.1 for DOS, and Visual Basic 3.0 for Windows. I am familiar
+ with C, and, though I know it is much faster than Basic, I stick with the
+ various forms of Basic since I am much more comfortable with the language.
+ I have also been told that Visual Basic is easier to learn than Visual C,
+ and, in fact, I taught myself Visual basic in two days.
+
+
+APPENDIX A - Table of Key Strokes
+-------------------------------------------------------------------------------
+
+KEY ACTION
+- - - - - - - -
+F1 Toggles between Multi View and Single View Modes
+F2 Copies a formula to a new line or to a currently blank line
+F3 Cycles through abbreviation recognition modes (like Ph for phenyl)
+F4 Cycles through case recognition modes: Exact --> Smart --> Convert Up
+F5 Creates a new blank line, ONLY available in Single View Mode.
+F6 Erases the current formula.
+F7 Toggles display of the time.
+F8 Cycles through the on-line help screens.
+F9 Toggles display of the calculator.
+F10 Erases all formulas.
+F11 Toggles percent solver mode.
+F12 Cycles through standard deviation modes (see Std. Dev. section above)
+
+Up and Down arrows move between the formula lines.
+Left and Right arrows move along the current line.
+Enter key calculates the mol. wt. and % composition when on the formula line.
+Enter key toggles Locking of the % composition value when on a % comp line.
+Page Up and Page Down move among % composition lines during % Solver mode.
+Tab key and Shift-Tab key are equivalent to the up and down arrows.
+Insert key toggles insert/overstrike mode.
+Delete key deletes the character the cursor is on.
+CTRL-C toggles display of caution statements.
+
+
+APPENDIX B - Calculations
+-------------------------------------------------------------------------------
+Calculation Note:
+ For Radioactive elements, the most stable isotope is NOT used;
+ Instead, an average Mol. Weight is used, just like with other elements.
+ See the Isotopes section for the method of indicating an exact isotopic
+ mass. Data obtained from the Perma-Chart Science Series Chemical Periodic
+ Table, 1993; ISBN 1-55080-063-9.
+ Uncertainties from CRC Handbook of Chemistry and Physics, except for
+ Radioactive elements, where uncertainty was estimated to be .n5 where
+ n represents the number of digits after the decimal point but before the
+ last number of the molecular weight.
+ For example, for Nobelium, MW = 259.1009 (ñ0.0005)
+
+ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
+³ The Mathematics behind the Molecular Weight, Percent Composition, and ³
+³ Standard Deviation Calculations ³
+ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
+ (Concept from Molar Mass program by Christopher King at
+ Eastern Oregon State College).
+
+ NOTE: s_f means s subscript f and is one term; likewise s_mw means
+ s subscript mw and is also simply one term.
+
+For Addition:
+In general: For f = x + y - z, the standard deviation of f, s_f, is
+ equal to û[(s_x)ý + (s_y)ý + (s_z)ý], which is in words,
+ the std. dev. of f is equal to the square root of the sum
+ of the squares of the std. deviations of each term in the
+ original sum.
+
+Applied to the Molecular Weight of a molecule:
+ MW = ax + by + cz + ..., where a is the number of atoms of
+ weight x, b is the number of atoms of weight y, etc.
+ The Std. Dev. of MW, s_mw = û[a(s_x)ý + b(s_y)ý + ...]
+
+Note, the reason the equation uses a(s_x)ý is that if the terms were added
+up consecutively 'a' times for the same element, we would have
+ (s_x)ý + (s_x)ý + (s_x)ý etc. up to 'a' times, which combines to be
+ a(s_x)ý
+
+For example, for chlorobenzene, C6H5Cl:
+ MW = 6*12.011 + 5*1.00794 + 35.4527 = 112.5584
+ s_mw = û[6*(.001)ý + 5*(.00007)ý + (.0009)ý] = .002614
+
+ Resulting MW is 112.558 (ñ0.003) = 112.558(ñ3)
+
+For Multiplication:
+In general: For f = x*yöz, the standard deviation of f, s_f is equal to
+ y*û[(s_x ö x)ý + (s_y ö y)ý + (s_z ö z)ý], which in words,
+ the std. dev. of f is equal to f times the square root of the sum
+ of squares of the quotients of the std. deviations of each term
+ divided by each term itself.
+
+Applied to the Percent Composition of a molecule:
+ %Comp = (a*xöMW)*100, where a is the number of atoms of weight x
+ and MW is the total molecular weight of the molecule.
+ The Std. Dev. of %Comp, s_%c = %c*û[(s_aöa)ý + (s_xöx)ý + (s_mwömw)ý]
+ But, since a is a finite number, its s_a = 0, so the formula becomes:
+ s_%c = %c*û[(s_x ö x)ý + (s_mw ö mw)ý]
+
+For example, for chlorobenzene, C6H5Cl:
+ %Comp of Carbon = 6*12.011ö112.5584*100 = 64.02543%
+ s_%c = 64.02543*û[(.001ö12.011)ý + (.002614ö112.5584)ý] = .00553
+ Resulting %Comp of Carbon = 64.025% (ñ0.006) = 64.025(ñ6)%
+
+ %Comp of Hydrogen = 5*1.00794ö112.5584*100 = 4.47741%
+ s_%c = 4.47741*û[(.00007ö1.00794)ý + (.002614ö112.5584)ý] = .0003279
+ Resulting %Comp of Hydrogen = 4.4774% (ñ0.0003) = 4.4774(ñ3)%
+
+ %Comp of Chlorine = 35.4527ö112.5584*100 = 31.49716%
+ s_%c = 31.49716*û[(.0009ö35.4527)ý + (.002614ö112.5584)ý] = .0010837
+ Resulting %Comp of Hydrogen = 31.497% (ñ0.001) = 31.497(ñ1)%
+
+
+ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
+³ The Mathematics behind the Percent Solver routine ³
+ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
+ For determining the closest fit between multiple target values and
+actually calculated data, the value of the following formula is minimized:
+ diff = ä(actual_%value_i - target_%value_i)ý, which in words is the summation
+of the ith calculated percentage value minus the ith target value. The
+minimum value of this formula should be obtained when all actual values are
+closest to their target values.
+
+
+ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
+³ The Mathematics behind the Isotopic Extremes error handler ³
+ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
+ When a user types in an isotopic mass (eg. ^13C for carbon-13), the
+program checks to see if the isotope is a reasonable value. Obviously, ^5C
+(carbon-5) would be unreasonable because any compound with 6 protons (i.e.
+carbon) must have a minimum weight of 6. However, upon examining the Table
+of Isotopes in the CRC Handbook of Chemistry and Physics, I found that very
+few compounds have zero neutrons (and thus an atomic weight equal to the
+number of protons in the element). Therefore, I examined the table and used
+MS Excel 5.0 to create a graph of the highest and lowest isotopic masses for
+every element. I then determined two fit-lines that encompassed all the data
+points -- one for the upper extreme and one for the lower extreme.
+ Since most isotopic masses occur somewhere around the value twice the
+atomic number (Z) of the element, I chose to work with the value:
+ x = isotope_value - Z*2
+where isotope_value is the value present after the caret (^) in the formula.
+
+ The curve that describes the upper limit of these x values is:
+ max_x = INTEGER(0.63*Z + 6)
+ where max_x is the maximum allowable x value before a warning is issued.
+
+ The curve that describes the lower limit of these x values is:
+ min_x = INTEGER(0.008*Zý - 0.4*Z - 6)
+ where min_x is the minimum allowable x value before a warning is issued.
+ The results were converted to integers to aid in program design.
+
+Finally, because the min_x value is too low for some of the lighter elements,
+I included a test to make sure that isotope_value was at least as large as Z,
+or else a warning was again issued to the user. The method is an approximate
+test on the isotope value, and is designed to catch the outrageous isotopic
+masses. It does not catch the borderline ones since that would have increased
+the program size and memory usage by too much.
+
+Examples:
+For Carbon:
+ ^13C has z = 6, x = 1, max_x = 9 and min_x = -9
+ Because x < 9 and x > -9 and x > 6, no warning is issued.
+ (The average atomic weight of carbon is 12.011)
+
+ ^25C has z = 6, x = 10, max_x = 9 and min_x = -9
+ Because x > 9, a warning that 25 is probably too large is given.
+ In reality, the heaviest known carbon isotope is carbon-16.
+
+ ^5C has z = 6, x = -7, max_x = 9 and min_x = -9
+ Although x < 9 and x > -9, x is less than 6 so a warning is again issued.
+ In reality, the lightest known carbon isotope is carbon-9.
+
+For Silver
+ ^100Ag has z = 47, x = 6, max_x = 35 and min_x = -8
+ Because x < 35 and x > -8 and x > 47, no warning is issued.
+ (The average atomic weight of silver is 107.87)
+
+ ^130Ag has z = 47, x = 36, max_x = 35 and min_x = -8
+ Because x > 35, a warning that 130 is probably too large is given.
+ In reality, the heaviest known silver isotope is silver-122.
+
+ ^85Ag has z = 47, x = -9, max_x = 35 and min_x = -8
+ Because x < -8 a warning that 85 is probably too small is given.
+ In reality, the lightest known silver isotope is carbon-96.
+
+The above calculations show, as mentioned above, that this method catches the
+outrageous isotopic masses but does not catch the borderline cases.
+Furthermore, it should also be evident that this method is more accurate for
+the heavier elements, a consequence of the unusual isotopic behavior of the
+lighter elements.
+
+
+APPENDIX C - REVISIONS
+-------------------------------------------------------------------------------
+Revision History for the Molecular Weight Calculator program by Matthew Monroe
+
+Revision 1 Completed August 6, 1995
+ Contains basic features including:
+ formula weight calculation
+ percent composition calculation
+ can handle parentheses, up to 2 sets of embedding
+ can handle hydrates and other additional compounds
+ can handle numbers up to 2 digits long
+ two types of case conversion
+ help screen
+
+Revision 2.0 Completed August 8, 1995
+ Contains the following new features:
+ can handle numbers up to 6 digits long
+ can handle up to 4 sets of embedded parentheses
+ ability to handle brackets and partial weights
+ three types of case conversion
+ expanded help screens
+
+Revision 2.1 Completed August 9, 1995
+ Contains the following new features:
+ display of time
+
+Revision 2.2 Completed August 10, 1995
+ Contains the following new features:
+ calculator
+
+Revision 2.21 Completed August 17, 1995
+ Contains minor bug fixes.
+
+Revision 2.3 Completed September 2, 1995
+ Contains the following new features:
+ added command line switches to control internal settings
+ added standard deviation option
+ added recognition Bu for butyl group
+
+Revision 2.4 Completed December 1, 1995
+ Contains the following new features:
+ Percent solver program.
+ Combined F11 and F12 std. deviation options into just F12
+ Contains Screen update bug fixes.
+
+Revision 2.5 Completed December 7, 1995
+ Improved speed of the % solver algorithm.
+ Contains the following new features:
+ added recognition of Urea, Ox, Py, En, Tpp, Otf.
+
+Revision 2.55 Completed December 17, 1995
+ Added error trapping routines.
+ Improved handling of exponentially large and small numbers.
+ Added warning statements for possibly ambiguous abbreviations
+ such as Bpy and Py.
+
+Revision 2.6 Completed January 16, 1996
+ Contains the following new features:
+ Recognizes Amino Acid abbreviations.
+ Recognizes Deuterium, D abbreviation.
+ Percent Solver values can now be set for all elements of
+ a formula.
+ Displays differences between actual and theoretical values
+ at the conclusion of the percent solver routine.
+ Added CTRL-P option to print results.
+ Added more error messages/explanations for incorrect user
+ entries.
+
+Revision 2.7 Completed March 1, 1996
+ Contains the following new features:
+ Able to handle isotopes; use the caret (^) symbol.
+ Able to calculate powers of numbers in the calculator.
+ Added more error messages/explanations for incorrect entries.
+ Included a moderately accurate error handler to check the
+ validity of entered isotopic masses.
+ Added numerous "caution" statements for possibly erroneous
+ entries: eg. Co vs. CO and Sc vs. SC
+ This feature may be toggled on and off with CTRL-C
+ Improved speed of the % solver algorithm; watch it blaze!
+ Removed CTRL-P option -- use PRINT-SCREEN or SHIFT-PRINT-SCREEN
+ Changed the order and layout of the on-line help screens.
+ Fixed typos in help screens and added two more help screens.
+
+Revision 2.8 Completed May 1, 1996
+ Contains the following new features:
+ Able to handle user-defined abbreviations listed in the
+ MWT_ABBR.DAT file.
+ Error checking to prevent duplicate abbreviations or
+ abbreviations duplicating elements.
+ Automatic re-creation of the abbreviation file if it
+ is deleted/missing.
+ Ability to run without abbreviations if program is run on
+ a write-protected drive.
+ Command-line switch (/X) to stop any attempts of reading
+ or creating an abbreviation file (useful on a
+ write-protected drive).
+
+Revision 2.85 Completed September 1, 1996
+ Contains the following new feature:
+ Recognition of the MWTPATH environment variable for
+ specification of the location of the MWT_ABBR.DAT file.
+
+Revision 2.87 Complete January 1, 1997
+ Updated the help file to reflect the latest Windows version
+ of the program.
+
+Version 3.2 of Molecular Weight Calculator for Windows is also available
+ (See the availability section above):
+
+ Features: New Windows Interface
+ Modify elemental values (element weight and uncertainty)
+ Edit and save abbreviations and elemental values while
+ program is running
+ Save options as defaults
+ Copy and paste information to/from other Windows programs
+ Unlimited formula length
+ Ability to print results
+ Ability to change the font used to display formulas
+ Mole/Mass Converter
+ Formula Finder
+ Full hypertext help
+
diff --git a/Mwt Dos/MWT.ICO b/Mwt Dos/MWT.ICO
new file mode 100644
index 0000000..2683ac1
Binary files /dev/null and b/Mwt Dos/MWT.ICO differ
diff --git a/Mwt Dos/MWT2_87.ZIP b/Mwt Dos/MWT2_87.ZIP
new file mode 100644
index 0000000..029be2f
Binary files /dev/null and b/Mwt Dos/MWT2_87.ZIP differ
diff --git a/Mwt Dos/MWT_ABBR.DAT b/Mwt Dos/MWT_ABBR.DAT
new file mode 100644
index 0000000..06a4f77
--- /dev/null
+++ b/Mwt Dos/MWT_ABBR.DAT
@@ -0,0 +1,62 @@
+' Abbreviation File for MWT program
+'
+' Comments may be added by preceding with an apostrophe
+' Two group headings must exist: [AMINO ACIDS] and [ABBREVIATIONS]
+' Abbreviations may be added; simply type the abbreviation and molecular
+' formula under the appropriate column in either section
+' Note: Only the first letter of an abbreviation is allowed to be capitalized
+' Note: Elements MUST be properly capitalized; eg. na is incorrect, use Na
+' Note: Parentheses and dashes are NOT allowed; eg. CH3(CH2)2 is incorrect
+' use C3H7 or CH3CH2CH2
+' The abbreviations in the Amino Acid section are treated as extended level
+' abbreviations: they are only recognized when extended abbreviations are on
+' If this file becomes corrupted, the MWT program will inform the user and
+ ignore incorrect lines
+' If this file becomes deleted, the MWT program will create a new file with
+ the default abbreviations, but without the abbreviation descriptions
+'
+' Default Amino Acids are in their ionic form
+' Amino Acid abbreviations may be up to 6 characters long
+' It is strongly advised that longer abbreviations be placed first
+[AMINO ACIDS]
+Ala C3H5NO ' Alanine
+Arg C6H12N4O ' Arginine, (unprotonated NH2)
+Asn C4H6N2O2 ' Asparagine
+Asp C4H5NO3 ' Aspartic acid (undissociated COOH)
+Cys C3H5NOS ' Cysteine (no disulfide link)
+Gln C5H8N2O2 ' Glutamine
+Glu C5H7NO3 ' Glutamic acid (undissociated COOH)
+Gly C2H3NO ' Glycine
+His C6H7N3O ' Histidine (unprotonated NH)
+Hyp C5H7NO2 ' Hydroxyproline
+Ile C6H11NO ' Isoleucine (same as Leucine)
+Leu C6H11NO ' Leucine (same as Isoleucine)
+Lys C6H12N2O ' Lysine (unprotonated NH2)
+Met C5H9NOS ' Methionine
+Phe C9H9NO ' Phenylalanine
+Pro C5H7NO ' Proline
+Ser C3H5NO2 ' Serine
+Thr C4H7NO2 ' Threonine
+Trp C11H10N2O ' Tryptophan
+Tyr C9H9NO2 ' Tyrosine
+Val C5H9NO ' Valine
+
+' Normal abbreviations may be up to 6 characters long
+' It is strongly advised that longer abbreviations be placed first
+[ABBREVIATIONS]
+Phen C12H8N2 ' Phenanthroline
+Urea CON2H4 ' Urea, H2NCONH2
+Bpy C10H8N2 ' Bipyridine
+Oac C2H3O2 ' Acetate
+Otf CO3SF3 ' Triflate, OSO2CF3
+Tpp C44H28N4 ' Tetraphenylporphyrin, (C4H2N(C6H5C)C4H2N(C6H5C))2, mw 612.733
+Bu C4H9 ' Butyl
+En C2H8N2 ' Ethylenediamine, H2NCH2CH2NH2
+Et C2H5 ' Ethyl, CH3CH2
+Me CH3 ' Methyl
+Ms CH3SO2 ' Mesyl, CH3SOO
+Ox C2O4 ' Oxalate
+Ph C6H5 ' Phenyl
+Py C5H5N ' Pyridine
+Ts C7H7SO2 ' Tosyl, CH3C6H4SOO
+D H2 ' Deuterium
diff --git a/Mwt Dos/PROMO.WIN b/Mwt Dos/PROMO.WIN
new file mode 100644
index 0000000..38c60d2
--- /dev/null
+++ b/Mwt Dos/PROMO.WIN
@@ -0,0 +1,158 @@
+
+Version 3.2 of Molecular Weight Calculator for Windows now available.
+
+ New Features: Allows use of abbreviations as custom elements in
+ formula finder.
+ For Percent Solver, added display of differences
+ between target percentages and obtained percentages.
+ Changed comment delimeter to be a semicolon in the
+ MWTWIN.INI file and the .DAT files.
+ Added detection of a mouse click to stop the percent
+ solver and formula finder.
+
+ Why is it better than other programs available? First of all it's
+free, yet fully functional. I feel it is very powerful, more functional
+and more user friendly than other molecular weight programs I've found
+over the net. I'm making it available for others so that they can use it
+in their research and studies. Plus, the program is fully Windows 95
+compatible (beside Win 3.x). The Dos version is also still available.
+
+
+AVAILABILITY
+------------------------------------------------------------------------------
+ Windows Version (MWTWin v3.2)
+
+The program is available via the web at http://plains.uwyo.edu/~monroem/ or
+at http://www.coast.net/SimTel/win3/chem.html and
+http://www.cdrom.com/simtel.net/win3/chem.html and
+http://www.simtel.net/pub/simtelnet/win3/chem/ in the mwt3_2.zip file.
+
+The program is also available via Anonymous FTP at ftp.coast.net under the
+SimTel/win3/chem/ directory in the mwt3_2.zip file, at ftp.simtel.net under
+pub/simtelnet/win3/chem/ in the mwt3_2.zip file, and ftp.osc.edu under the
+pub/chemistry/software/MS-WINDOWS/Molecular_Weight/ directory in the
+mwt3_2.exe or mwt3_2s.exe files.
+
+
+ Dos Version (MWT v2.87)
+
+The program is available via the web at http://plains.uwyo.edu/~monroem/ or
+at http://www.coast.net/SimTel/msdos/chemstry.html and
+http://www.cdrom.com/simtel.net/msdos/chemstry.html and
+http://www.simtel.net/pub/simtelnet/msdos/chemstry/ in the mwt2_87.zip file.
+
+The program is also available via Anonymous FTP at ftp.coast.net under the
+SimTel/msdos/chemstry/ directory in the mwt2_87.zip file, at ftp.simtel.net
+under pub/simtelnet/msdos/chemstry/ in the mwt2_87.zip file, and ftp.osc.edu
+under the pub/chemistry/software/MS-DOS/Molecular-Weight-Calculator/
+directory in the mwt2_87.exe file.
+
+ As a final option, I can mail you a UUEncoded or MIME encoded version
+via e-mail; just drop me a line.
+
+
+Please see my home page for the Dos version features.
+
+As for the Windows version, ...
+
+
+FEATURES
+-----------------------------------------------------------------------------
+Multi Line Display Display of up to seven formulas with their molecular
+weights simultaneously.
+
+Percent Composition Percent composition of up to seven formulas.
+
+Parentheses Are Allowed Handles up to 4 layers of embedded parentheses.
+
+For example, (CH3)3CH2CH3 is equivalent to CH3CH3CH3CH2CH3.
+
+Hydrates or other appended compounds are allowed.
+
+For example, FeCl3-6H2O.
+
+User-definable abbreviations Default abbreviations are included for common
+parts of compounds, including amino acids. See full list.
+
+For example, PhCl = C6H5Cl and HOac = CH3COOH.
+
+Smart Case Conversion The program will automatically convert lowercase
+letters to uppercase where appropriate for ease of entering a formula. Exact
+case matching and non-conversion are also available.
+
+Edit and save abbreviations while program is running.
+
+Isotopes are recognized using the following notation:
+
+^13C is Carbon-13
+ C6H5^18OH is heavy-oxygen (Oxygen-18) labeled phenol
+
+Feature of weighting parts of a compound relative to the other parts.
+
+For example,
+
+[.2Na]Cl would have a weight of 0.2*22.989768+35.4527=40.0507
+NaCl-[.5H2O] would have a weight of
+22.989768+35.4527+0.5*(2*1.00794+15.9994)=67.4501
+
+Percent Solver mode for finding the value of "x" in a compound that satisfies
+user-specified percent composition requirements.
+
+Edit and save elemental values while program is running.
+
+Accuracy of the final digit of the molecular wt. and percent composition.
+
+Capability to set optional features at the command line when starting the
+program.
+
+Capability of saving options as defaults and automatic loading of the saved
+options upon program start.
+
+Easily Cut, Copy, and Paste information between the Molecular Weight Calculator
+and other Windows applications.
+
+Mole/Mass Converter for easily translating moles to mass (kg, g, mg, pounds,
+ounces) and back.
+
+Formula Finder for finding possible compound empirical formulas for a given
+molecular weight or for a given set of percent composition data.
+
+Capability of printing results.
+
+Extensive On-Line Help and Error Checking
+
+
+THE AUTHOR
+------------------------------------------------------------------------------
+Contacting the Author
+
+You can contact me by E-mail at Monroem@UWyo.Edu until I graduate in May 1997.
+After that, E-mail BPat@UWyo.Edu for information on my whereabouts.
+
+About the Author
+
+I am an undergraduate chemistry major at the University of Wyoming in Laramie,
+Wyoming. I plan to attend graduate school and aim to obtain a doctorate in
+chemistry. I taught myself to program in BASIC on an Apple //c (with 128 Kb
+of Ram and no hard disk) in 1986 during 6th grade. Since then, I have updated
+to GW-Basic, then QuickBasic v4.5, QuickBasic v7.1 for DOS, and now Visual
+Basic 3.0 for Windows. I am familiar with C, and, though I know it is much
+faster than Basic, I stick with the various forms of Basic since I am much
+more comfortable with the language. I have also been told that Visual Basic
+is easier to learn than Visual C, and, in fact, I taught myself Visual Basic
+in two days.
+
+
+/============================================================================\
+I was goin' Chopin', but I forgot my Lizst! Had to go Bach to get it.
+
+ What are the following?
+Matthew Monroe Black Angus : Black Angus
+Chemistry Major Black Angus : Texas Longhorn
+University of Wyoming Black Angus : Brown Swiss
+ -------------------------------------------------
+monroem@uwyo.edu Homogeneous Catalyst : Heterogeneous Catalyst
+
+/----------------------------------\
+| http://plains.uwyo.edu/~monroem/ | This tagline is umop apisdn.
+\============================================================================/
diff --git a/Mwt Dos/README.TXT b/Mwt Dos/README.TXT
new file mode 100644
index 0000000..1d4e596
--- /dev/null
+++ b/Mwt Dos/README.TXT
@@ -0,0 +1,13 @@
+
+ MWT.EXE
+
+ This program will calculate the molecular weight and percent composition
+of up to seven compounds simultaneously. It recognizes user-definable
+abbreviations and all isotopes. See the MWT.HLP file for complete
+information. Type MWT.EXE to start the program, or type MWT /? for
+additional program information. This program is FreeWare and may be
+distributed freely.
+
+Send E-Mail to MonroeM@UWyo.Edu
+WWW is at http://plains.uwyo.edu/~monroem/
+After May 1997 send E-Mail to BPat@UWyo.Edu for information on my whereabouts.
diff --git a/Mwt Dos/SIMTEL.TXT b/Mwt Dos/SIMTEL.TXT
new file mode 100644
index 0000000..7b3183a
--- /dev/null
+++ b/Mwt Dos/SIMTEL.TXT
@@ -0,0 +1,322 @@
+From: IN%"chris@SimTel.Coast.NET" 27-FEB-1996 16:11:00.84
+To: IN%"MONROEM@uwyo.edu"
+CC:
+Subj: RE: Wish to upload a Chemistry Program
+
+Return-path:
+Received: from roper.uwyo.edu (SYSTEM@roper.uwyo.edu)
+ by PLAINS.UWYO.EDU (PMDF V5.0-4 #14244)
+ id <01I1PPMTR2R4002BZ0@PLAINS.UWYO.EDU> for MONROEM@PLAINS.UWYO.EDU; Tue,
+ 27 Feb 1996 16:10:55 -0700 (MST)
+Received: from DIRECTORY-DAEMON by ROPER.UWYO.EDU (PMDF V5.0-4 #14244)
+ id <01I1PPMMO1IO0014JD@ROPER.UWYO.EDU> for MONROEM@plains.uwyo.edu; Tue,
+ 27 Feb 1996 16:10:41 -0700 (MST)
+Received: from jupiter.tacom.army.mil (jupiter.tacom.army.mil)
+ by ROPER.UWYO.EDU (PMDF V5.0-4 #14244) id <01I1PPML3MWW001I7P@ROPER.UWYO.EDU>
+ for MONROEM@uwyo.edu; Tue, 27 Feb 1996 16:10:40 -0700 (MST)
+Received: from simtel.coast.net by jupiter.tacom.army.mil (8.7.1/8.7.1-kbp)
+ with ESMTP id RAA03803; Tue, 27 Feb 1996 17:42:49 -0500 (EST)
+Received: by simtel.coast.net (8.7.1/8.7.1-kbp) id SAA00542; Tue,
+ 26 Dec 1995 18:12:42 -0500 (EST)
+Date: Tue, 26 Dec 1995 18:12:27 -0500 (EST)
+From: chris@SimTel.Coast.NET (Chris Gavula)
+Subject: Re: Wish to upload a Chemistry Program
+In-reply-to: Message of Wed, 06 Dec 1995 11:10:43 -0700 (MST)
+To: MONROEM@uwyo.edu (Alchemist Matt)
+Message-id: <951226181227.chris@SimTel.Coast.NET>
+Content-transfer-encoding: 7BIT
+
+MONROEM@UWYO.EDU (Alchemist Matt) wrote:
+> Hello,
+>
+> I would like to be granted access to upload a Chemistry Molecular Weight
+> Calculator program for MS-DOS. I would prefer to use the FTP method to
+> send you this initial version and subsequent versions.
+> The Molecular Weight Calculator has the unique feature of being able
+> to display up to seven formulas and their molecular weights simultaneously,
+> besides finding percent composition. The program includes many advanced
+> features like recognition of abbreviations for chemical groups and standard
+> deviations of results.
+>
+> Thank you for your time,
+> Matt
+>
+> ==============================================================================
+> What are the following?
+>
+> Matthew Monroe Black Angus : Black Angus
+> Chemistry Major Black Angus : Texas Longhorn
+> University of Wyoming Black Angus : Brown Swiss
+> -------------------------------------------------
+> monroem@uwyo.edu Homogeneous Catalyst : Heterogeneous Catalyst
+>
+> This tagline is umop apisdn.
+> ==============================================================================
+
+Thank you for inquiring about how to include your software
+program in SimTel, the Coast to Coast Software Repository (tm).
+
+As you may know, the Repository is maintained by Coast to Coast
+Telecommunications, Inc. (CCT) on its host computer on the Internet
+located at "SimTel.Coast.NET" which is not accessible without our
+express permission.
+
+Our Repository exists to help software authors gain a wider audience for
+their programs than they can individually give them. Thus we allow many
+so called "mirror sites", currently about 65, on the worldwide Internet,
+to copy our host Repository (at irregular intervals of their choosing),
+as long as the mirror sites are accessible FREE OF CHARGE to Internet
+users for browsing and downloading any program. We insure this free
+access by asserting our compilation copyright on the Repository, and
+on report of abuse by a mirror site, denying access to our host.
+
+One mirror site is FTP.Coast.NET. Please read our copyright notice on
+that host. We understand that the author maintains his or her authorship
+copyright which is how the author may expect to gain compensation from
+the actual end user of the program(s) and that the author can also
+control all other aspects of distribution of these works not related
+to us.
+
+To support our efforts, we offer (800) access to the host Repository and
+make CD-ROM disks of the entire Repository for sale. If we accept your
+program, it most likely will be included in future editions of OUR
+CD-ROMs. To enlarge exposure of programs to the potential universe
+of end users, we occasionally license other CD-ROM vendors to offer
+abridged and unabridged versions of the Repository on CD-ROMs made by
+them. Our licenses have the option whether or not to include your
+program(s) on their offerings.
+
+Please do NOT upload your program(s) if you object to such activities
+without compensation from CCT and its licensees. By uploading your
+program(s) you agree to look to the individual end user(s) for your
+sole source of compensation for the use of your work, and *not* CCT,
+its distributors, licensees or their distributors, or any Internet
+mirror sites.
+
+You also understand and agree that we can not call your program back
+from such distribution. If we accept a program, we try to update our
+host as soon as possible, and once it appears there we will not stop
+further distribution... so please if you have any concern about our
+distribution system, do NOT upload, because once you do, it's too late.
+
+NOTE: By the act of uploading you affirm that you are the author or the
+author's authorized agent and that the author has read and agreed with
+the terms of our compilation copyright and distribution policies.
+
+[Note: This is private information. Do not forward or quote from it.]
+
+The upload account used for submissions of files to the SimTel
+Software Repository is:
+
+ Site: SimTel.Coast.NET (205.149.128.6) (this is *not* ftp.coast.net)
+ Username: incoming
+ Password: bqvsp2xr
+
+This account and password information is for your eyes only.
+
+ZIP v2.x is the preferred format for uploads. ZIP v1.10 files are also
+accepted but will be repacked in ZIP v2.x format. We cannot handle other
+archive formats at this time.
+
+SimTel policy does not allow self-extracting files (except for archivers,
+where a chicken-and-the-egg situation exists) because a few downloaders
+have destroyed their file systems by improperly transferring binary files
+in text mode. This problem does not exist on BBSs, but it's a very real
+one for Internet users. If the program you are submitting is an archiver
+it must be uploaded inside a ZIP file for error checking purposes.
+
+You can convert a self-extracting archive file to its native format with
+Vernon Buerg's "FV" program.
+
+SimTel/msdos/arcutil/
+fv145.zip View dirs of ARC/DWC/LBR/LZH/PAK/ZIP/ZOO/SFXs
+
+It preserves any -AVs the ZIP may have because it simply trims the SFX
+executable off the front of the input file and makes a new file.
+
+Please try to limit the size of each file to 700K or less so that
+downloaders can put them on a diskette. This is a guideline, not a
+requirement. Experience has shown that larger files get less downloads
+due to downloader's disk space or modem time limitations.
+
+Please do not upload a large number of files at one time. SimTel
+receives about 360 uploads per month. If one person uploads a large
+number of files at one time they are usually put aside so they will not
+disrupt processing of other uploads. It may take as long as two months
+to get around to screening and cataloging them.
+
+Please remember to use the "binary" or "tenex" mode when uploading binary
+files with FTP. Please check the filesize in SimTel's incoming directory
+with the dir command after uploading to make sure that it's the same as
+the original file.
+
+SimTel policy does not allow replacing an existing file by another with
+the same name because we cannot guarantee that every mirror site or ANY
+of the TRICKLE sites will replace the old file with the new file. Most
+mirror sites will get it because it has a different datestamp and size,
+but most TRICKLE sites will NOT re-fetch files they have already gotten
+in response to user requests.
+
+Please choose a name with the version number in it in order to help
+users spot updates.
+
+Please note: Files or programs submitted without upload announcements
+will not be accepted. To assure authenticity, SimTel requires that
+upload announcements (in English) be sent to me by e-mail and the real
+name of the uploader must be included in the announcement. Upload
+announcements in the form of text files uploaded to the incoming
+directory are deleted by script that removes all non-zip files from the
+incoming directory before the uploaded files are moved to the reviewing
+area.
+
+Send your announcement to me by e-mail with a one line description
+for each file you have uploaded. A longer description of 10-20 lines
+should also be included in the same message, which will be used for my
+announcement of the file to the net. Please include a suggestion of
+the SimTel directory that would be the best place to put your file.
+
+The one-line description should use the format shown in this sample
+template.
+
+SimTel/msdos/io_util/
+whtprt40.zip Displays system serial ports & IRQ assignments
+12345678.123____123456789.123456789.123456789.123456789.123456
+^^^^^^^^^^^^ ^--46 characters maximum in the description--^
+ ^ ^--description starts at column 17
+ ^--filename all lower case, left-justified with no blanks
+
+The longer description should begin at the left margin (column 1) and
+not exceed 76 characters per line.
+
+Experience has shown that potential downloaders of new files are "turned
+off" by announcements which are worded more like press releases than
+informative postings. Please avoid the use of superlatives. Here are
+some guidelines to help you avoid the appearance of "hype" in your
+announcement.
+
+ - A good announcement informs.
+ - A bad announcement persuades.
+
+You can most easily tell persuasion from information by the modifiers.
+Adjectives and adverbs that make judgments are almost always persuaders
+("great") as are those that would appeal to the user based on irrelevant
+criteria ("new"). Claims that are not backed up by easily available
+facts, including subjective claims ("best", "greatest"), are persuaders,
+not information. A claim of benefit to the user, other than those
+implied by the product itself, is likely a persuader.
+
+One example: "This will do your taxes", in the description of a tax
+preparation program, is a claim of benefit to the user, implied by the
+program; that's information. "This will do your taxes better than any
+other program" is not. It has a judgment ("better") modifier, which is
+a big clue.
+
+Please make the description tell the purpose/use of the file, not things
+like "Newest version of WOW.ZIP" or "Newest version of Chuck Forsberg's
+DSZ". In either of those examples I am left to answer questions from the
+users about what the program does.
+
+If there are special requirements such as EGA/VGA/SVGA, 286/386/486,
+Pentium, EMS/XMS, etc., please include that information.
+
+If you are the author of the program please include that information
+in the announcement. A simple "Uploaded by the author." is sufficient.
+
+If you wish to include optional Usenet "Newsgroups:" and "Followup-To:"
+information either in the header or as the first two lines of the
+upload announcement that is mailed to me, they will be used for the
+posting but inappropriate newsgroup(s) will be deleted. If you don't
+know what this information means, do not include these lines.
+
+If the program is for Windows and you wish to have your announcement
+posted to comp.os.ms-windows.announce you will have to do that yourself
+by sending it by e-mail to comp-os-ms-windows-announce@mail.uu.net
+because the moderator of that newsgroup will not allow SimTel to post
+your announcement to his newsgroup.
+
+Each file should be announced in a separate message unless it is related
+to one or more of the other files, such as a multi-part package. The
+message should be in the format described above.
+
+Here is a sample upload announcement. Each line has been offset by "> "
+for this example to make it clear where the example begins and ends. Do
+not include the "> " in your announcement. Begin your announcement with
+the line "I have uploaded:" as shown below. Do not include the header,
+which is shown here only for clarity.
+
+> From: bgu@cu.nih.gov (Bruce Guthrie)
+> To: w8sdz@SimTel.Coast.NET (Keith Petersen)
+> Subject: dirto312.zip - Directory lister and totaller
+> Newsgroups: comp.archives.msdos.announce
+> Followup-To: comp.archives.msdos.d
+>
+> I have uploaded:
+>
+> SimTel/msdos/dirutil/
+> dirto312.zip Directory lister and totaller
+>
+> DIRTO v3.12 prepares a report showing files in subdirectory or drive.
+> It allows some restriction requests (show only files with date greater
+> than a certain value). It is similar to Norton's FF and Ray Van Tassle's
+> WIZ command (which is a great program but it doesn't work on network or
+> CD-ROM discs) in some ways but presents a more formal report. It also
+> allows you to look for duplicate file names and search by attributes or
+> dates.
+>
+> Special requirements: None
+>
+> Changes: A number of bug fixes were made. Now runs on Novell drives.
+> A number of enhancements were made to the /DUPS option.
+>
+> dirto312.zip has replaced dirto311.zip.
+>
+> ShareWare. Uploaded by the author.
+>
+> Bruce Guthrie
+> bgu@cu.nih.gov
+
+All uploads must run on or be related to MS-DOS, MS-Windows or Windows
+95. If your program uses Visual Basic's VBRUNxxx.DLL it is recommended
+that it not be included because it is already available from the SimTel
+collection as vbrun100.zip, vbrun200.zip, or vbrun300.zip.
+
+Windows-NT uploads should be coordinated with winnt@SimTel.Coast.NET.
+OS2 uploads should be coordinated with os2@SimTel.Coast.NET. Please do
+not upload NT or OS2 programs to the incoming directory listed above.
+
+All files or programs must include documentation in the English language
+(other languages are allowed but English must also be included). There
+must be a file included in the uploaded zip file that the user can read,
+without running a program, which tells:
+
+ 1. What the program does, and how to use it.
+ 2. The program's status (Public Domain, FreeWare, ShareWare).
+ 3. The program's distribution status (it must be freely distributable).
+ 4. How to contact the author in case of questions or problems (mailing
+ address, phone number and/or e-mail address).
+
+If the user has to run a program to get this information there is a
+chicken-and-the-egg problem if that program does not run because of an
+incompatibility or a corrupted download.
+
+Programs that stop working after a fixed date will not be accepted.
+
+Because SimTel's collections are available all over the world, SimTel
+cannot accept programs that are or might be subject to U.S. technology
+export restrictions. Encryption and decryption programs will not be
+accepted, no matter what method is used.
+
+Programs that crack copy protection or passwords will not be accepted.
+
+Games are not accepted unless they are strictly educational. There
+are several sites on the Internet which specialize in other types of
+games.
+
+Thanks!
+
+--Chris
+
+Chris Gavula
+Windows Archivist for SimTel, the Coast to Coast Software Repository (tm)
+Internet: chris@SimTel.Coast.NET ftp://ftp.coast.net/SimTel/
+Uucp: uunet!simtel.coast.net!chris http://www.coast.net/SimTel/
diff --git a/MwtWinDll/ErrorLog.txt b/MwtWinDll/ErrorLog.txt
new file mode 100644
index 0000000..79eb32e
--- /dev/null
+++ b/MwtWinDll/ErrorLog.txt
@@ -0,0 +1,2 @@
+11/5/2006 10:02:05 PM -- Error in MwtWinDll|ComputeIsotopicAbundances: Subscript out of range (#9)
+
diff --git a/MwtWinDll/MwtWinDll.vbw b/MwtWinDll/MwtWinDll.vbw
new file mode 100644
index 0000000..e5228b9
--- /dev/null
+++ b/MwtWinDll/MwtWinDll.vbw
@@ -0,0 +1,8 @@
+MolecularWeightCalculator = 22, 24, 746, 516,
+MWCompoundClass = 132, 144, 856, 636, C
+MWPeptideClass = 132, 144, 856, 636, C
+ElementAndMassRoutines = 154, 168, 891, 660, C
+modSharedVBRoutines = 0, 0, 795, 492, C
+MWCapillaryFlowClass = 154, 168, 884, 660, C
+frmProgress = 115, 115, 784, 491, C, 23, 23, 670, 391, C
+MWMoleMassDilutionClass = 23, 23, 652, 404, C
diff --git a/MwtWinDll/MwtWinDllTest.bas b/MwtWinDll/MwtWinDllTest.bas
new file mode 100644
index 0000000..1595203
--- /dev/null
+++ b/MwtWinDll/MwtWinDllTest.bas
@@ -0,0 +1,15 @@
+Attribute VB_Name = "modMwtWinDllTest"
+Option Explicit
+
+' Molecular Weight Calculator Dll test program
+' Written by Matthew Monroe for the Department of Energy (PNNL, Richland, WA)
+
+Public objMwtWin As MwtWinDll.MolecularWeightCalculator
+Public Declare Function GetTickCount Lib "kernel32" () As Long
+
+Sub Main()
+ Set objMwtWin = New MolecularWeightCalculator
+ frmMwtWinDllTest.Show
+
+End Sub
+
diff --git a/MwtWinDll/MwtWinDllTest.exe b/MwtWinDll/MwtWinDllTest.exe
new file mode 100644
index 0000000..696a5fd
Binary files /dev/null and b/MwtWinDll/MwtWinDllTest.exe differ
diff --git a/MwtWinDll/MwtWinDllTest.frm b/MwtWinDll/MwtWinDllTest.frm
new file mode 100644
index 0000000..36007c6
--- /dev/null
+++ b/MwtWinDll/MwtWinDllTest.frm
@@ -0,0 +1,786 @@
+VERSION 5.00
+Object = "{3B7C8863-D78F-101B-B9B5-04021C009402}#1.2#0"; "RICHTX32.OCX"
+Object = "{5E9E78A0-531B-11CF-91F6-C2863C385E30}#1.0#0"; "MSFLXGRD.OCX"
+Begin VB.Form frmMwtWinDllTest
+ Caption = "Mwt Win Dll Test"
+ ClientHeight = 6690
+ ClientLeft = 60
+ ClientTop = 375
+ ClientWidth = 9780
+ LinkTopic = "Form1"
+ ScaleHeight = 6690
+ ScaleWidth = 9780
+ StartUpPosition = 3 'Windows Default
+ Begin VB.CommandButton cmdTestGetTrypticName
+ Caption = "Test Get Tryptic Name"
+ Height = 615
+ Left = 3840
+ TabIndex = 19
+ Top = 4440
+ Width = 1335
+ End
+ Begin MSFlexGridLib.MSFlexGrid grdFlexGrid
+ Height = 5000
+ Left = 5280
+ TabIndex = 7
+ Top = 960
+ Width = 4000
+ _ExtentX = 7064
+ _ExtentY = 8811
+ _Version = 393216
+ End
+ Begin VB.CommandButton cmdExpandAbbreviations
+ Caption = "Expand Abbreviations"
+ Height = 615
+ Left = 4320
+ TabIndex = 4
+ Top = 120
+ Width = 1335
+ End
+ Begin VB.CommandButton cmdTestFunctions
+ Caption = "Test Functions"
+ Height = 615
+ Left = 7680
+ TabIndex = 6
+ Top = 120
+ Width = 1335
+ End
+ Begin VB.ComboBox cboStdDevMode
+ Height = 315
+ Left = 1560
+ Style = 2 'Dropdown List
+ TabIndex = 3
+ Top = 3720
+ Width = 2175
+ End
+ Begin VB.ComboBox cboWeightMode
+ Height = 315
+ Left = 1560
+ Style = 2 'Dropdown List
+ TabIndex = 2
+ Top = 3360
+ Width = 2175
+ End
+ Begin VB.CommandButton cmdConvertToEmpirical
+ Caption = "Convert to &Empirical"
+ Height = 615
+ Left = 6000
+ TabIndex = 5
+ Top = 120
+ Width = 1335
+ End
+ Begin RichTextLib.RichTextBox rtfFormula
+ Height = 495
+ Left = 1560
+ TabIndex = 1
+ Top = 1320
+ Width = 3495
+ _ExtentX = 6165
+ _ExtentY = 873
+ _Version = 393217
+ Enabled = -1 'True
+ TextRTF = $"MwtWinDllTest.frx":0000
+ End
+ Begin VB.CommandButton cmdFindMass
+ Caption = "&Calculate"
+ Default = -1 'True
+ Height = 495
+ Left = 120
+ TabIndex = 8
+ Top = 4560
+ Width = 1335
+ End
+ Begin VB.TextBox txtFormula
+ Height = 285
+ Left = 1560
+ TabIndex = 0
+ Text = "Cl2PhH4OH"
+ Top = 240
+ Width = 1935
+ End
+ Begin VB.CommandButton cmdClose
+ Cancel = -1 'True
+ Caption = "Cl&ose"
+ Height = 495
+ Left = 1560
+ TabIndex = 9
+ Top = 4560
+ Width = 1335
+ End
+ Begin VB.Label lblStdDevMode
+ Caption = "Std Dev Mode"
+ Height = 255
+ Left = 120
+ TabIndex = 18
+ Top = 3720
+ Width = 1095
+ End
+ Begin VB.Label lblWeightMode
+ Caption = "Weight Mode"
+ Height = 255
+ Left = 120
+ TabIndex = 17
+ Top = 3360
+ Width = 1095
+ End
+ Begin VB.Label lblStatusLabel
+ Caption = "Status:"
+ Height = 255
+ Left = 120
+ TabIndex = 16
+ Top = 2040
+ Width = 1095
+ End
+ Begin VB.Label lblMassAndStdDevLabel
+ Caption = "Mass and StdDev:"
+ Height = 255
+ Left = 120
+ TabIndex = 15
+ Top = 960
+ Width = 1335
+ End
+ Begin VB.Label lblMassAndStdDev
+ Caption = "0"
+ Height = 255
+ Left = 1560
+ TabIndex = 14
+ Top = 960
+ Width = 3135
+ End
+ Begin VB.Label lblStatus
+ Height = 1095
+ Left = 1560
+ TabIndex = 13
+ Top = 1920
+ Width = 3375
+ End
+ Begin VB.Label lblMass
+ Caption = "0"
+ Height = 255
+ Left = 1560
+ TabIndex = 12
+ Top = 600
+ Width = 1935
+ End
+ Begin VB.Label lblMassLabel
+ Caption = "Mass:"
+ Height = 255
+ Left = 120
+ TabIndex = 11
+ Top = 600
+ Width = 1095
+ End
+ Begin VB.Label lblFormula
+ Caption = "Formula:"
+ Height = 255
+ Left = 120
+ TabIndex = 10
+ Top = 240
+ Width = 1335
+ End
+End
+Attribute VB_Name = "frmMwtWinDllTest"
+Attribute VB_GlobalNameSpace = False
+Attribute VB_Creatable = False
+Attribute VB_PredeclaredId = True
+Attribute VB_Exposed = False
+Option Explicit
+
+' Molecular Weight Calculator Dll test program
+' Written by Matthew Monroe for the Department of Energy (PNNL, Richland, WA) in Richland, WA
+' Copyright 2005, Battelle Memorial Institute
+
+Private Sub FindPercentComposition()
+ Dim intIndex As Integer, intElementCount As Integer
+ Dim dblPctCompForCarbon As Double, strPctCompForCarbon As String
+ Dim strSymbol As String
+
+ Dim strPctCompositions() As String
+
+ With objMwtWin.Compound
+ .Formula = txtFormula
+
+ dblPctCompForCarbon = .GetPercentCompositionForElement(6)
+ strPctCompForCarbon = .GetPercentCompositionForElementAsString(6)
+
+ intElementCount = objMwtWin.GetElementCount
+ ReDim strPctCompositions(intElementCount)
+
+ .GetPercentCompositionForAllElements strPctCompositions()
+
+ End With
+
+ With grdFlexGrid
+ .Clear
+ .Rows = 2
+ .Cols = 2
+ .ColWidth(1) = 1500
+ .FixedCols = 0
+ .FixedRows = 1
+ .TextMatrix(0, 0) = "Element": .TextMatrix(0, 1) = "Pct Comp"
+
+ For intIndex = 1 To intElementCount
+ If Left(strPctCompositions(intIndex), 5) <> "" Then
+ objMwtWin.GetElement intIndex, strSymbol, 0, 0, 0, 0
+ .TextMatrix(.Rows - 1, 0) = strSymbol
+ .TextMatrix(.Rows - 1, 1) = strPctCompositions(intIndex)
+ .Rows = .Rows + 1
+ End If
+ Next intIndex
+ End With
+End Sub
+
+Private Sub FindMass()
+ ' Can simply compute the mass of a formula using ComputeMass
+ lblMass = objMwtWin.ComputeMass(txtFormula)
+
+ ' If we want to do more complex operations, need to fill objMwtWin.Compound with valid info
+ ' Then, can read out values from it
+ With objMwtWin.Compound
+ .Formula = txtFormula
+
+ If .ErrorDescription = "" Then
+ lblMass = .Mass
+ lblStatus = .CautionDescription
+ txtFormula = .FormulaCapitalized
+ rtfFormula.TextRTF = .FormulaRTF
+ lblMassAndStdDev = .MassAndStdDevString
+ Else
+ lblStatus = .ErrorDescription
+ End If
+ End With
+
+End Sub
+
+Private Sub PopulateComboBoxes()
+ With cboWeightMode
+ .Clear
+ .AddItem "Average mass"
+ .AddItem "Isotopic mass"
+ .AddItem "Integer mass"
+ .ListIndex = 0
+ End With
+
+ With cboStdDevMode
+ .Clear
+ .AddItem "Short"
+ .AddItem "Scientific"
+ .AddItem "Decimal"
+ .ListIndex = 0
+ End With
+
+
+End Sub
+
+Public Sub TestAccessFunctions()
+ Dim intIndex As Integer, intResult As Integer, lngIndex As Long
+ Dim lngItemCount As Long
+ Dim strSymbol As String, strFormula As String, sngCharge As Single, blnIsAminoAcid As Boolean
+ Dim strOneLetterSymbol As String, strComment As String
+ Dim strStatement As String
+ Dim dblmass As Double, dblUncertainty As Double, intIsotopeCount As Integer, intIsotopeCount2 As Integer
+ Dim dblIsotopeMasses() As Double, sngIsotopeAbundances() As Single
+ Dim dblNewPressure As Double
+
+ Dim objCompound As New MWCompoundClass
+
+ With objMwtWin
+ ' Test Abbreviations
+ lngItemCount = .GetAbbreviationCount
+ For intIndex = 1 To lngItemCount
+ intResult = .GetAbbreviation(intIndex, strSymbol, strFormula, sngCharge, blnIsAminoAcid, strOneLetterSymbol, strComment)
+ Debug.Assert intResult = 0
+ Debug.Assert .GetAbbreviationID(strSymbol) = intIndex
+
+ intResult = .SetAbbreviation(strSymbol, strFormula, sngCharge, blnIsAminoAcid, strOneLetterSymbol, strComment)
+ Debug.Assert intResult = 0
+ Next intIndex
+
+ ' Test Caution statements
+ lngItemCount = .GetCautionStatementCount
+ For intIndex = 1 To lngItemCount
+ intResult = .GetCautionStatement(intIndex, strSymbol, strStatement)
+ Debug.Assert intResult = 0
+ Debug.Assert .GetCautionStatementID(strSymbol) = intIndex
+
+ intResult = .SetCautionStatement(strSymbol, strStatement)
+ Debug.Assert intResult = 0
+ Next intIndex
+
+ ' Test Element access
+ lngItemCount = .GetElementCount
+ For intIndex = 1 To lngItemCount
+ intResult = .GetElement(intIndex, strSymbol, dblmass, dblUncertainty, sngCharge, intIsotopeCount)
+ Debug.Assert intResult = 0
+ Debug.Assert .GetElementID(strSymbol) = intIndex
+
+ intResult = .SetElement(strSymbol, dblmass, dblUncertainty, sngCharge, False)
+ Debug.Assert intResult = 0
+
+ ReDim dblIsotopeMasses(intIsotopeCount + 1)
+ ReDim sngIsotopeAbundances(intIsotopeCount + 1)
+
+ intResult = .GetElementIsotopes(intIndex, intIsotopeCount2, dblIsotopeMasses(), sngIsotopeAbundances())
+ Debug.Assert intIsotopeCount = intIsotopeCount2
+ Debug.Assert intResult = 0
+
+ intResult = .SetElementIsotopes(strSymbol, intIsotopeCount, dblIsotopeMasses(), sngIsotopeAbundances())
+ Debug.Assert intResult = 0
+ Next intIndex
+
+ ' Test Message Statements access
+ lngItemCount = .GetMessageStatementCount
+ For lngIndex = 1 To lngItemCount
+ strStatement = .GetMessageStatement(lngIndex)
+
+ intResult = .SetMessageStatement(lngIndex, strStatement)
+ Next lngIndex
+
+ ' Test Capillary flow functions
+
+ With .CapFlow
+ .SetAutoComputeEnabled False
+ .SetBackPressure 2000, uprPsi
+ .SetColumnLength 40, ulnCM
+ .SetColumnID 50, ulnMicrons
+ .SetSolventViscosity 0.0089, uviPoise
+ .SetInterparticlePorosity 0.33
+ .SetParticleDiameter 2, ulnMicrons
+ .SetAutoComputeEnabled True
+
+ Debug.Print ""
+ Debug.Print "Check capillary flow calcs"
+ Debug.Print "Linear Velocity: " & .ComputeLinearVelocity(ulvCmPerSec)
+ Debug.Print "Vol flow rate: " & .ComputeVolFlowRate(ufrNLPerMin) & " (newly computed)"
+
+ Debug.Print "Vol flow rate: " & .GetVolFlowRate
+ Debug.Print "Back pressure: " & .ComputeBackPressure(uprPsi)
+ Debug.Print "Column Length: " & .ComputeColumnLength(ulnCM)
+ Debug.Print "Column ID: " & .ComputeColumnID(ulnMicrons)
+ Debug.Print "Column Volume: " & .ComputeColumnVolume(uvoNL)
+ Debug.Print "Dead time: " & .ComputeDeadTime(utmSeconds)
+
+ Debug.Print ""
+
+ Debug.Print "Repeat Computations, but in a different order (should give same results)"
+ Debug.Print "Vol flow rate: " & .ComputeVolFlowRate(ufrNLPerMin)
+ Debug.Print "Column ID: " & .ComputeColumnID(ulnMicrons)
+ Debug.Print "Back pressure: " & .ComputeBackPressure(uprPsi)
+ Debug.Print "Column Length: " & .ComputeColumnLength(ulnCM)
+
+ Debug.Print ""
+
+ Debug.Print "Old Dead time: " & .GetDeadTime(utmMinutes)
+
+ .SetAutoComputeMode acmVolFlowrateUsingDeadTime
+
+ .SetDeadTime 25, utmMinutes
+ Debug.Print "Dead time is now 25.0 minutes"
+
+ Debug.Print "Vol flow rate: " & .GetVolFlowRate(ufrNLPerMin) & " (auto-computed since AutoComputeMode = acmVolFlowrateUsingDeadTime)"
+
+ ' Confirm that auto-compute worked
+
+ Debug.Print "Vol flow rate: " & .ComputeVolFlowRateUsingDeadTime(ufrNLPerMin, dblNewPressure, uprPsi) & " (confirmation of computed volumetric flow rate)"
+ Debug.Print "New pressure: " & dblNewPressure
+
+ Debug.Print ""
+
+ ' Can set a new back pressure, but since auto-compute is on, and the
+ ' auto-compute mode is acmVolFlowRateUsingDeadTime, the pressure will get changed back to
+ ' the pressure needed to give a vol flow rate matching the dead time
+ .SetBackPressure 2000
+ Debug.Print "Pressure set to 2000 psi, but auto-compute mode is acmVolFlowRateUsingDeadTime, so pressure"
+ Debug.Print " was automatically changed back to pressure needed to give vol flow rate matching dead time"
+ Debug.Print "Pressure is now: " & .GetBackPressure(uprPsi) & " psi (thus, not 2000 as one might expect)"
+
+ .SetAutoComputeMode acmVolFlowrate
+ Debug.Print "Changed auto-compute mode to acmVolFlowrate. Can now set pressure to 2000 and it will stick; plus, vol flow rate gets computed."
+
+ .SetBackPressure 2000, uprPsi
+
+ ' Calling GetVolFlowRate will get the new computed vol flow rate (since auto-compute is on)
+ Debug.Print "Vol flow rate: " & .GetVolFlowRate
+
+ .SetMassRateConcentration 1, ucoMicroMolar
+ .SetMassRateVolFlowRate 600, ufrNLPerMin
+ .SetMassRateInjectionTime 5, utmMinutes
+
+ Debug.Print "Mass flow rate: " & .GetMassFlowRate(umfFmolPerSec) & " fmol/sec"
+ Debug.Print "Moles injected: " & .GetMassRateMolesInjected(umaFemtoMoles) & " fmoles"
+
+ .SetMassRateSampleMass 1234
+ .SetMassRateConcentration 1, ucongperml
+
+ Debug.Print "Computing mass flow rate for compound weighing 1234 g/mol and at 1 ng/mL concentration "
+ Debug.Print "Mass flow rate: " & .GetMassFlowRate(umfAmolPerMin) & " amol/min"
+ Debug.Print "Moles injected: " & .GetMassRateMolesInjected(umaFemtoMoles) & " fmoles"
+
+ .SetExtraColumnBroadeningLinearVelocity 4, ulvCmPerMin
+ .SetExtraColumnBroadeningDiffusionCoefficient 0.0003, udcCmSquaredPerMin
+ .SetExtraColumnBroadeningOpenTubeLength 5, ulnCM
+ .SetExtraColumnBroadeningOpenTubeID 250, ulnMicrons
+ .SetExtraColumnBroadeningInitialPeakWidthAtBase 30, utmSeconds
+
+ Debug.Print "Computing broadening for 30 second wide peak through a 250 um open tube that is 5 cm long (4 cm/min)"
+ Debug.Print .GetExtraColumnBroadeningResultantPeakWidth(utmSeconds)
+
+ End With
+ End With
+
+
+ Dim udtFragSpectrumOptions As udtFragmentationSpectrumOptionsType
+ Dim udtFragSpectrum() As udtFragmentationSpectrumDataType
+ Dim lngIonCount As Long
+ Dim strNewSeq As String
+
+ With objMwtWin.Peptide
+
+ .SetSequence "K.ACYEFGHRKACYEFGHRK.G", ntgHydrogen, ctgHydroxyl, False, True
+
+ ' Can change the terminii to various standard groups
+ .SetNTerminusGroup ntgCarbamyl
+ .SetCTerminusGroup ctgAmide
+
+ ' Can change the terminii to any desired elements
+ .SetNTerminus "C2OH3" ' Acetyl group
+ .SetCTerminus "NH2" ' Amide group
+
+ ' Can mark third residue, Tyr, as phorphorylated
+ .SetResidue 3, "Tyr", True, True
+
+ ' Can define that the * modification equals 15
+ .SetModificationSymbol "*", 15, False, ""
+
+ strNewSeq = "Ala-Cys-Tyr-Glu-Phe-Gly-His-Arg*-Lys-Ala-Cys-Tyr-Glu-Phe-Gly-His-Arg-Lys"
+ Debug.Print strNewSeq
+ .SetSequence strNewSeq
+
+ .SetSequence "K.TQPLE*VK.-", ntgHydrogenPlusProton, ctgHydroxyl, False, True
+
+ Debug.Print .GetSequence(True, False, True, False)
+ Debug.Print .GetSequence(False, True, False, False)
+ Debug.Print .GetSequence(True, False, True, True)
+
+ .SetCTerminusGroup ctgNone
+ Debug.Print .GetSequence(True, False, True, True)
+
+ udtFragSpectrumOptions = .GetFragmentationSpectrumOptions()
+
+ udtFragSpectrumOptions.DoubleChargeIonsShow = False
+ udtFragSpectrumOptions.DoubleChargeIonsThreshold = 200
+ udtFragSpectrumOptions.IntensityOptions.BYIonShoulder = 0
+
+ udtFragSpectrumOptions.IonTypeOptions(itAIon).ShowIon = True
+
+ .SetFragmentationSpectrumOptions udtFragSpectrumOptions
+
+ lngIonCount = .GetFragmentationMasses(udtFragSpectrum())
+
+ End With
+
+ With grdFlexGrid
+ .Clear
+
+ .Rows = lngIonCount + 1
+ .Cols = 3
+ .ColWidth(0) = 1500
+ .ColWidth(1) = 1000
+ .ColWidth(2) = 1000
+
+ .FixedCols = 0
+ .FixedRows = 1
+ .TextMatrix(0, 0) = "Mass"
+ .TextMatrix(0, 1) = "Intensity"
+ .TextMatrix(0, 2) = "Symbol"
+
+ For lngIndex = 0 To lngIonCount - 1
+ .TextMatrix(lngIndex + 1, 0) = udtFragSpectrum(lngIndex).Mass
+ .TextMatrix(lngIndex + 1, 1) = udtFragSpectrum(lngIndex).Intensity
+ .TextMatrix(lngIndex + 1, 2) = udtFragSpectrum(lngIndex).Symbol
+
+ If udtFragSpectrum(lngIndex).Symbol <> "" Then
+' Debug.Print sngIonMassesZeroBased(lngIndex) & ", " & sngIonIntensitiesZeroBased(lngIndex) & ", " & strIonSymbolsZeroBased(lngIndex)
+ End If
+ Next lngIndex
+
+ Debug.Print "Peptide mass: " & objMwtWin.Peptide.GetPeptideMass
+
+
+ End With
+
+
+ Dim intSuccess As Integer
+ Dim strResults As String
+ Dim ConvolutedMSData2D() As Double, ConvolutedMSDataCount As Long
+
+ With objMwtWin
+ Debug.Print ""
+ intSuccess = .ComputeIsotopicAbundances("C1255H43O2Cl", 1, strResults, ConvolutedMSData2D(), ConvolutedMSDataCount)
+ Debug.Print strResults
+ End With
+
+
+End Sub
+
+Private Sub TestTrypticName()
+ Const DIM_CHUNK = 1000
+
+ Const ITERATIONS_TO_RUN = 5
+ Const MIN_PROTEIN_LENGTH = 50
+ Const MAX_PROTEIN_LENGTH = 200
+ Const POSSIBLE_RESIDUES = "ACDEFGHIKLMNPQRSTVWY"
+
+ Dim lngMultipleIteration As Long
+
+ Dim strProtein As String, strPeptideResidues As String
+ Dim lngResidueStart As Long, lngResidueEnd As Long
+ Dim strPeptideNameMwtWin() As String
+ Dim strPeptideNameIcr2ls() As String
+ Dim strPeptideName As String
+
+ Dim lngMwtWinResultCount As Long, lngIcr2lsResultCount As Long
+ Dim lngMwtWinDimCount As Long, lngICR2lsDimCount As Long
+ Dim lngIndex As Long
+ Dim lngResidueRand As Long, lngProteinLengthRand As Long
+ Dim strNewResidue As String
+
+ Dim lngStartTime As Long, lngStopTime As Long
+ Dim lngMwtWinWorkTime As Long
+ Dim strPeptideFragMwtWin As String
+ Dim lngMatchCount As Long
+ Dim blnDifferenceFound As Boolean
+
+ lngMwtWinDimCount = DIM_CHUNK
+ ReDim strPeptideNameMwtWin(lngMwtWinDimCount)
+
+ Me.MousePointer = vbHourglass
+
+ frmResults.Show
+ frmResults.txtResults = ""
+
+'' Dim lngIcr2lsWorkTime As Long
+'' Dim lngIcr2lsTime As Long
+'' strPeptideFragIcr2ls As String
+'' lngICR2lsDimCount = DIM_CHUNK
+'' ReDim strPeptideNameIcr2ls(lngICR2lsDimCount)
+''
+'' Dim ICRTools As Object
+''
+'' Set ICRTools = CreateObject("ICR2LS.ICR2LScls")
+''
+'' frmResults.AddToResults "ICR2ls Version: " & ICRTools.ICR2LSversion
+
+ 'strProtein = "MGNISFLTGGNPSSPQSIAESIYQLENTSVVFLSAWQRTTPDFQRAARASQEAMLHLDHIVNEIMRNRDQLQADGTYTGSQLEGLLNISRAVSVSPVTRAEQDDLANYGPGNGVLPSAGSSISMEKLLNKIKHRRTNSANFRIGASGEHIFIIGVDKPNRQPDSIVEFIVGDFCQHCSDIAALI"
+
+ ' Bigger protein
+ strProtein = "MMKANVTKKTLNEGLGLLERVIPSRSSNPLLTALKVETSEGGLTLSGTNLEIDLSCFVPAEVQQPENFVVPAHLFAQIVRNLGGELVELELSGQELSVRSGGSDFKLQTGDIEAYPPLSFPAQADVSLDGGELSRAFSSVRYAASNEAFQAVFRGIKLEHHGESARVVASDGYRVAIRDFPASGDGKNLIIPARSVDELIRVLKDGEARFTYGDGMLTVTTDRVKMNLKLLDGDFPDYERVIPKDIKLQVTLPATALKEAVNRVAVLADKNANNRVEFLVSEGTLRLAAEGDYGRAQDTLSVTQGGTEQAMSLAFNARHVLDALGPIDGDAELLFSGSTSPAIFRARRWGRRVYGGHGHAARLRGLLRPLRGMSALAHHPESSPPLEPRPEFA"
+
+ frmResults.AddToResults "Testing GetTrypticNameMultipleMatches() function"
+ frmResults.AddToResults "MatchList for NL: " & objMwtWin.Peptide.GetTrypticNameMultipleMatches(strProtein, "NL", lngMatchCount)
+ frmResults.AddToResults "MatchCount = " & lngMatchCount
+
+ frmResults.AddToResults ""
+ frmResults.AddToResults "Testing GetTrypticPeptideByFragmentNumber function"
+ For lngIndex = 1 To 43
+ strPeptideFragMwtWin = objMwtWin.Peptide.GetTrypticPeptideByFragmentNumber(strProtein, CInt(lngIndex), lngResidueStart, lngResidueEnd)
+'' strPeptideFragIcr2ls = ICRTools.TrypticPeptide(strProtein, CInt(lngIndex))
+''
+'' Debug.Assert strPeptideFragMwtWin = strPeptideFragIcr2ls
+
+ If Len(strPeptideFragMwtWin) > 1 Then
+ ' Make sure lngResidueStart and lngResidueEnd are correct
+ ' Do this using .GetTrypticNameMultipleMatches()
+ strPeptideName = objMwtWin.Peptide.GetTrypticNameMultipleMatches(strProtein, Mid(strProtein, lngResidueStart, lngResidueEnd - lngResidueStart + 1))
+ Debug.Assert InStr(strPeptideName, "t" & Trim(Str(lngIndex))) > 0
+ End If
+ Next lngIndex
+ frmResults.AddToResults "Check of GetTrypticPeptideByFragmentNumber Complete"
+ frmResults.AddToResults ""
+
+
+ frmResults.AddToResults "Test tryptic digest of: " & strProtein
+ lngIndex = 1
+ Do
+ strPeptideFragMwtWin = objMwtWin.Peptide.GetTrypticPeptideByFragmentNumber(strProtein, CInt(lngIndex), lngResidueStart, lngResidueEnd)
+ frmResults.AddToResults "Tryptic fragment " & Trim(lngIndex) & ": " & strPeptideFragMwtWin
+ lngIndex = lngIndex + 1
+ Loop While Len(strPeptideFragMwtWin) > 0
+
+
+ frmResults.AddToResults ""
+ Randomize
+ For lngMultipleIteration = 1 To ITERATIONS_TO_RUN
+ ' Generate random protein
+ lngProteinLengthRand = Int((MAX_PROTEIN_LENGTH - MIN_PROTEIN_LENGTH + 1) * Rnd + MIN_PROTEIN_LENGTH)
+
+ strProtein = ""
+ For lngResidueRand = 1 To lngProteinLengthRand
+ strNewResidue = Mid(POSSIBLE_RESIDUES, Int(Len(POSSIBLE_RESIDUES)) * Rnd + 1, 1)
+ strProtein = strProtein & strNewResidue
+ Next lngResidueRand
+
+ frmResults.AddToResults "Iteration: " & lngMultipleIteration & " = " & strProtein
+
+ lngMwtWinResultCount = 0
+ Debug.Print "Starting residue is ";
+ lngStartTime = GetTickCount()
+ For lngResidueStart = 1 To Len(strProtein)
+ If lngResidueStart Mod 10 = 0 Then
+ Debug.Print lngResidueStart & ", ";
+ DoEvents
+ End If
+
+ For lngResidueEnd = 1 To Len(strProtein) - lngResidueStart
+ If lngResidueEnd - lngResidueStart > 50 Then
+ Exit For
+ End If
+
+ strPeptideResidues = Mid(strProtein, lngResidueStart, lngResidueEnd)
+ strPeptideNameMwtWin(lngMwtWinResultCount) = objMwtWin.Peptide.GetTrypticName(strProtein, strPeptideResidues, 0, 0, True)
+
+ lngMwtWinResultCount = lngMwtWinResultCount + 1
+ If lngMwtWinResultCount > lngMwtWinDimCount Then
+ lngMwtWinDimCount = lngMwtWinDimCount + DIM_CHUNK
+ ReDim Preserve strPeptideNameMwtWin(lngMwtWinDimCount)
+ End If
+
+ Next lngResidueEnd
+ Next lngResidueStart
+ lngStopTime = GetTickCount()
+ lngMwtWinWorkTime = lngStopTime - lngStartTime
+ Debug.Print ""
+ Debug.Print "MwtWin time (" & lngMwtWinResultCount & " peptides) = " & lngMwtWinWorkTime & " msec"
+
+'' lngIcr2lsResultCount = 0
+'' Debug.Print "Starting residue is ";
+'' lngStartTime = GetTickCount()
+'' For lngResidueStart = 1 To Len(strProtein)
+'' If lngResidueStart Mod 10 = 0 Then
+'' Debug.Print lngResidueStart & ", ";
+'' DoEvents
+'' End If
+'' ' Use DoEvents on every iteration since Icr2ls is quite slow
+'' DoEvents
+''
+'' For lngResidueEnd = 1 To Len(strProtein) - lngResidueStart
+'' If lngResidueEnd - lngResidueStart > 50 Then
+'' Exit For
+'' End If
+''
+'' strPeptideResidues = Mid(strProtein, lngResidueStart, lngResidueEnd)
+'' strPeptideNameIcr2ls(lngIcr2lsResultCount) = ICRTools.TrypticName(strProtein, strPeptideResidues)
+''
+'' lngIcr2lsResultCount = lngIcr2lsResultCount + 1
+'' If lngIcr2lsResultCount > lngICR2lsDimCount Then
+'' lngICR2lsDimCount = lngICR2lsDimCount + DIM_CHUNK
+'' ReDim Preserve strPeptideNameIcr2ls(lngICR2lsDimCount)
+'' End If
+'' Next lngResidueEnd
+'' Next lngResidueStart
+'' lngStopTime = GetTickCount()
+'' lngIcr2lsWorkTime = lngStopTime - lngStartTime
+'' Debug.Print ""
+'' Debug.Print "Icr2ls time (" & lngMwtWinResultCount & " peptides) = " & lngIcr2lsWorkTime & " msec"
+
+'' ' Check that results match
+'' For lngIndex = 0 To lngMwtWinResultCount - 1
+'' If Left(strPeptideNameMwtWin(lngIndex), 1) = "t" Then
+'' If Val(Right(strPeptideNameMwtWin(lngIndex), 1)) < 5 Then
+'' ' Icr2LS does not return the correct name when strPeptideResidues contains 5 or more tryptic peptides
+'' If strPeptideNameMwtWin(lngIndex) <> strPeptideNameIcr2ls(lngIndex) Then
+'' frmResults.AddToResults "Difference found, index = " & lngIndex & ", " & strPeptideNameMwtWin(lngIndex) & " vs. " & strPeptideNameIcr2ls(lngIndex)
+'' blnDifferenceFound = True
+'' End If
+'' End If
+'' Else
+'' If strPeptideNameMwtWin(lngIndex) <> strPeptideNameIcr2ls(lngIndex) Then
+'' frmResults.AddToResults "Difference found, index = " & lngIndex & ", " & strPeptideNameMwtWin(lngIndex) & " vs. " & strPeptideNameIcr2ls(lngIndex)
+'' blnDifferenceFound = True
+'' End If
+'' End If
+'' Next lngIndex
+
+ Next lngMultipleIteration
+
+ frmResults.AddToResults "Check of Tryptic Sequence functions Complete"
+
+ Me.MousePointer = vbNormal
+End Sub
+
+Private Sub UpdateResultsForCompound(objCompound As MWCompoundClass)
+ With objCompound
+ If .ErrorDescription = "" Then
+ txtFormula = .FormulaCapitalized
+ FindMass
+ Else
+ lblStatus = .ErrorDescription
+ End If
+ End With
+
+End Sub
+Private Sub cboStdDevMode_Click()
+ Select Case cboStdDevMode.ListIndex
+ Case 1
+ objMwtWin.StdDevMode = smScientific
+ Case 2
+ objMwtWin.StdDevMode = smDecimal
+ Case Else
+ objMwtWin.StdDevMode = smShort
+ End Select
+
+End Sub
+
+Private Sub cboWeightMode_Click()
+ Select Case cboWeightMode.ListIndex
+ Case 1
+ objMwtWin.SetElementMode emIsotopicMass
+ Case 2
+ objMwtWin.SetElementMode emIntegerMass
+ Case Else
+ objMwtWin.SetElementMode emAverageMass
+ End Select
+End Sub
+
+Private Sub cmdClose_Click()
+ Set objMwtWin = Nothing
+ Unload Me
+ End
+End Sub
+
+Private Sub cmdConvertToEmpirical_Click()
+ With objMwtWin.Compound
+ .Formula = txtFormula
+ .ConvertToEmpirical
+ End With
+
+ UpdateResultsForCompound objMwtWin.Compound
+
+End Sub
+
+Private Sub cmdExpandAbbreviations_Click()
+ With objMwtWin.Compound
+ .Formula = txtFormula
+ .ExpandAbbreviations
+ End With
+
+ UpdateResultsForCompound objMwtWin.Compound
+End Sub
+
+Private Sub cmdFindMass_Click()
+ FindMass
+ FindPercentComposition
+End Sub
+
+Private Sub cmdTestFunctions_Click()
+ TestAccessFunctions
+End Sub
+
+Private Sub cmdTestGetTrypticName_Click()
+ TestTrypticName
+End Sub
+
+Private Sub Form_Load()
+ PopulateComboBoxes
+End Sub
+
diff --git a/MwtWinDll/MwtWinDllTest.frx b/MwtWinDll/MwtWinDllTest.frx
new file mode 100644
index 0000000..8ebef8e
Binary files /dev/null and b/MwtWinDll/MwtWinDllTest.frx differ
diff --git a/MwtWinDll/MwtWinDllTest.vbp b/MwtWinDll/MwtWinDllTest.vbp
new file mode 100644
index 0000000..e36454c
--- /dev/null
+++ b/MwtWinDll/MwtWinDllTest.vbp
@@ -0,0 +1,40 @@
+Type=Exe
+Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#C:\WINDOWS\system32\stdole2.tlb#OLE Automation
+Reference=*\G{40A1F1BF-ADB0-441E-BF5F-0A5E4A1DDC48}#1.0#0#MwtWindll.dll#Molecular Weight Calculator - Dll Version
+Object={3B7C8863-D78F-101B-B9B5-04021C009402}#1.2#0; richtx32.ocx
+Object={5E9E78A0-531B-11CF-91F6-C2863C385E30}#1.0#0; MSFLXGRD.OCX
+Form=MwtWinDllTest.frm
+Module=modMwtWinDllTest; MwtWinDllTest.bas
+Form=frmresults.frm
+IconForm="frmMwtWinDllTest"
+Startup="Sub Main"
+HelpFile=""
+ExeName32="MwtWinDllTest.exe"
+Command32=""
+Name="MwtWinDllTest"
+HelpContextID="0"
+CompatibleMode="0"
+MajorVer=1
+MinorVer=0
+RevisionVer=0
+AutoIncrementVer=0
+ServerSupportFiles=0
+VersionCompanyName="PNNL"
+CompilationType=0
+OptimizationType=0
+FavorPentiumPro(tm)=0
+CodeViewDebugInfo=0
+NoAliasing=0
+BoundsCheck=0
+OverflowCheck=0
+FlPointCheck=0
+FDIVCheck=0
+UnroundedFP=0
+StartMode=0
+Unattended=0
+Retained=0
+ThreadPerObject=0
+MaxNumberOfThreads=1
+
+[MS Transaction Server]
+AutoRefresh=1
diff --git a/MwtWinDll/MwtWinDllTest.vbw b/MwtWinDll/MwtWinDllTest.vbw
new file mode 100644
index 0000000..7262593
--- /dev/null
+++ b/MwtWinDll/MwtWinDllTest.vbw
@@ -0,0 +1,3 @@
+frmMwtWinDllTest = 75, 21, 514, 513, , 10, -7, 777, 590, C
+modMwtWinDllTest = 22, 24, 866, 533, C
+frmResults = 110, 120, 952, 647, , 66, 72, 908, 599, C
diff --git a/MwtWinDll/MwtWinDllTestGroup.vbg b/MwtWinDll/MwtWinDllTestGroup.vbg
new file mode 100644
index 0000000..348d760
--- /dev/null
+++ b/MwtWinDll/MwtWinDllTestGroup.vbg
@@ -0,0 +1,3 @@
+VBGROUP 5.0
+Project=MwtWindll.vbp
+StartupProject=MwtWinDllTest.vbp
diff --git a/MwtWinDll/MwtWinDll_MergeModule/EditMwtWinDll_Installer.bat b/MwtWinDll/MwtWinDll_MergeModule/EditMwtWinDll_Installer.bat
new file mode 100644
index 0000000..9f5bd1a
--- /dev/null
+++ b/MwtWinDll/MwtWinDll_MergeModule/EditMwtWinDll_Installer.bat
@@ -0,0 +1 @@
+"C:\Program Files\Microsoft Visual Studio\Common\IDE\IDE98\DEVENV.EXE" "D:\My Documents\Projects\DataMining\MwtWinDll\MwtWinDll_MergeModule\MwtWinDll_MergeModule.sln"
\ No newline at end of file
diff --git a/MwtWinDll/MwtWinDll_MergeModule/MwtWinDll_MergeModule.cache b/MwtWinDll/MwtWinDll_MergeModule/MwtWinDll_MergeModule.cache
new file mode 100644
index 0000000..8ccabea
Binary files /dev/null and b/MwtWinDll/MwtWinDll_MergeModule/MwtWinDll_MergeModule.cache differ
diff --git a/MwtWinDll/MwtWinDll_MergeModule/MwtWinDll_MergeModule.sln b/MwtWinDll/MwtWinDll_MergeModule/MwtWinDll_MergeModule.sln
new file mode 100644
index 0000000..bfd8bbc
--- /dev/null
+++ b/MwtWinDll/MwtWinDll_MergeModule/MwtWinDll_MergeModule.sln
@@ -0,0 +1,13 @@
+Microsoft Visual Studio Solution File, Format Version 1.00
+Project("{73393D18-DAC4-11D1-88FC-0000F8064EBB}") = "MwtWindll", "MwtWinDll_MergeModule.wip", "{666A1CAC-4DC6-4814-B14D-B886AC18B4EE}"
+EndProject
+Global
+ GlobalSection(LocalDeployment) = postSolution
+ StartupProject = {00000000-0000-0000-0000-000000000000}
+ EndGlobalSection
+ GlobalSection(BuildOrder) = postSolution
+ 0 = {666A1CAC-4DC6-4814-B14D-B886AC18B4EE}
+ EndGlobalSection
+ GlobalSection(DeploymentRoot) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/MwtWinDll/MwtWinDll_MergeModule/MwtWinDll_MergeModule.wip b/MwtWinDll/MwtWinDll_MergeModule/MwtWinDll_MergeModule.wip
new file mode 100644
index 0000000..28ec334
Binary files /dev/null and b/MwtWinDll/MwtWinDll_MergeModule/MwtWinDll_MergeModule.wip differ
diff --git a/MwtWinDll/MwtWindll.dll b/MwtWinDll/MwtWindll.dll
new file mode 100644
index 0000000..db5985d
Binary files /dev/null and b/MwtWinDll/MwtWindll.dll differ
diff --git a/MwtWinDll/MwtWindll.exp b/MwtWinDll/MwtWindll.exp
new file mode 100644
index 0000000..aaee5d0
Binary files /dev/null and b/MwtWinDll/MwtWindll.exp differ
diff --git a/MwtWinDll/MwtWindll.lib b/MwtWinDll/MwtWindll.lib
new file mode 100644
index 0000000..88c7a12
Binary files /dev/null and b/MwtWinDll/MwtWindll.lib differ
diff --git a/MwtWinDll/MwtWindll.vbp b/MwtWinDll/MwtWindll.vbp
new file mode 100644
index 0000000..bc9fa58
--- /dev/null
+++ b/MwtWinDll/MwtWindll.vbp
@@ -0,0 +1,50 @@
+Type=OleDll
+Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#C:\WINDOWS\system32\stdole2.tlb#OLE Automation
+Reference=*\G{F935DC20-1CF0-11D0-ADB9-00C04FD58A0B}#1.0#0#C:\WINDOWS\system32\wshom.ocx#Windows Script Host Object Model
+Class=MolecularWeightCalculator; clsMwtWin.cls
+Class=MWCompoundClass; clsCompound.cls
+Class=MWPeptideClass; clsPeptideClass.cls
+Module=ElementAndMassRoutines; WorkingRoutines.bas
+Module=modSharedVBRoutines; SharedVBRoutines.bas
+Class=MWCapillaryFlowClass; clsCapillaryFlowClass.cls
+Form=frmProgress.frm
+Class=MWMoleMassDilutionClass; clsMoleMassDilutionClass.cls
+Startup="(None)"
+HelpFile=""
+Title="MwtWindll"
+ExeName32="MwtWindll.dll"
+Command32=""
+Name="MwtWinDll"
+HelpContextID="0"
+Description="Molecular Weight Calculator - Dll Version"
+CompatibleMode="0"
+CompatibleEXE32="MwtWindll.dll"
+MajorVer=2
+MinorVer=36
+RevisionVer=68
+AutoIncrementVer=1
+ServerSupportFiles=0
+VersionComments="Written by Matthew Monroe"
+VersionCompanyName="PNNL"
+VersionFileDescription="Contact e-mail: Matt@AlchemistMatt.com"
+VersionProductName="Molecular Weight Calculator - Dll Version"
+CompilationType=0
+OptimizationType=0
+FavorPentiumPro(tm)=0
+CodeViewDebugInfo=0
+NoAliasing=0
+BoundsCheck=0
+OverflowCheck=0
+FlPointCheck=0
+FDIVCheck=0
+UnroundedFP=0
+StartMode=1
+Unattended=0
+Retained=0
+ThreadPerObject=0
+MaxNumberOfThreads=1
+ThreadingModel=1
+DebugStartupOption=0
+
+[MS Transaction Server]
+AutoRefresh=1
diff --git a/MwtWinDll/PeptideRoutines.txt b/MwtWinDll/PeptideRoutines.txt
new file mode 100644
index 0000000..914b3a6
--- /dev/null
+++ b/MwtWinDll/PeptideRoutines.txt
@@ -0,0 +1,525 @@
+' Note: Example function call for determining if Tryptic
+'
+' strRuleResidues = "KR"
+' strExceptionResidues = "P"
+' strTerminiiSymbol = "-"
+' blnAllowPartialCleavage = False
+'
+' blnMatchesCleavageRule = CheckSequenceAgainstCleavageRule(strSequence, strRuleResidues, strExceptionResidues, blnAllowPartialCleavage, ".", strTerminiiSymbol, blnIgnoreCase, intRuleMatchCount)
+'
+' If fully tryptic, then blnMatchesCleavageRule = True
+' Examine intRuleMatchCount to determine if partially tryptic (intRuleMatchCount = 1)
+'
+
+
+Const TERMINII_SYMBOL = "-"
+Const TRYPTIC_RULE_RESIDUES = "KR"
+Const TRYPTIC_EXCEPTION_RESIDUES = "P"
+
+'
+' The following can be used to determine if a sequence matches a given cleavage rule
+'
+Public Function CheckSequenceAgainstCleavageRule(ByVal strSequence As String, ByVal strRuleResidues As String, ByVal strExceptionSuffixResidues As String, ByVal blnAllowPartialCleavage As Boolean, Optional ByVal strSeparationChar As String = ".", Optional ByVal strTerminiiSymbol As String = TERMINII_SYMBOL, Optional ByVal blnIgnoreCase As Boolean = True, Optional ByRef intRuleMatchCount As Integer)
+ ' Checks strSequence to see if it matches the cleavage rule
+ ' Returns True if valid, False if invalid
+ ' Returns True if doesn't contain any periods, and thus, can't be examined
+ ' The ByRef variable intRuleMatchCount can be used to retrieve the number of ends that matched the rule (0, 1, or 2)
+
+ ' The residues in strRuleResidues specify the cleavage rule
+ ' The peptide must end in one of the residues, or in -
+ ' The preceding residue must be one of the residues or be -
+ ' EXCEPTION: if blnAllowPartialCleavage = True then the rules need only apply to one end
+ ' Finally, the suffix residue cannot match any of the residues in strExceptionSuffixResidues
+
+ ' For example, if strRuleResidues = "KR" and strExceptionSuffixResidues = "P"
+ ' Then if strSequence = "R.AEQDDLANYGPGNGVLPSAGSSISMEK.L" then blnMatchesCleavageRule = True
+ ' However, if strSequence = "R.IGASGEHIFIIGVDK.P" then blnMatchesCleavageRule = False since strSuffix = "P"
+ ' Finally, if strSequence = "R.IGASGEHIFIIGVDKPNR.Q" then blnMatchesCleavageRule = True since K is ignored, but the final R.Q is valid
+
+ Dim strSequenceStart As String, strSequenceEnd As String
+ Dim strPrefix As String, strSuffix As String
+ Dim blnMatchesCleavageRule As Boolean, blnSkipThisEnd As Boolean, blnPossiblySkipEnd As Boolean
+ Dim intTerminiiCount As Integer
+ Dim strTestResidue As String
+ Dim intEndToCheck As Integer
+
+ ' First, make sure the sequence is in the form A.BCDEFG.H or A.BCDEFG or BCDEFG.H
+ ' If it isn't, then we can't check it (we'll return true)
+
+ If Len(strRuleResidues) = 0 Then
+ ' No rules
+ CheckSequenceAgainstCleavageRule = True
+ Exit Function
+ End If
+
+ If InStr(strSequence, strSeparationChar) = 0 Then
+ ' No periods, can't check
+ Debug.Assert False
+ CheckSequenceAgainstCleavageRule = True
+ Exit Function
+ End If
+
+ If blnIgnoreCase Then
+ strSequence = UCase(strSequence)
+ End If
+
+ ' Find the prefix residue and starting residue
+ If Mid(strSequence, 2, 1) = strSeparationChar Then
+ strPrefix = Left(strSequence, 1)
+ strSequenceStart = Mid(strSequence, 3, 1)
+ Else
+ strSequenceStart = Left(strSequence, 1)
+ End If
+
+ ' Find the suffix residue and the ending residue
+ If Mid(strSequence, Len(strSequence) - 1, 1) = strSeparationChar Then
+ strSuffix = Right(strSequence, 1)
+ strSequenceEnd = Mid(strSequence, Len(strSequence) - 2, 1)
+ Else
+ strSequenceEnd = Right(strSequence, 1)
+ End If
+
+ If strRuleResidues = strTerminiiSymbol Then
+ ' Peptide database rules
+ ' See if prefix and suffix are "" or are strTerminiiSymbol
+ If (strPrefix = strTerminiiSymbol And strSuffix = strTerminiiSymbol) Or _
+ (strPrefix = "" And strSuffix = "") Then
+ blnMatchesCleavageRule = True
+ Else
+ blnMatchesCleavageRule = False
+ End If
+ Else
+ If blnIgnoreCase Then
+ strRuleResidues = UCase(strRuleResidues)
+ End If
+
+ ' Test each character in strRuleResidues against both strPrefix and strSequenceEnd
+ ' Make sure strSuffix does not match strExceptionSuffixResidues
+ For intEndToCheck = 0 To 1
+ blnSkipThisEnd = False
+ If intEndToCheck = 0 Then
+ strTestResidue = strPrefix
+ If strPrefix = strTerminiiSymbol Then
+ intTerminiiCount = intTerminiiCount + 1
+ blnSkipThisEnd = True
+ Else
+ ' See if strSequenceStart matches one of the exception residues
+ ' If it does, make sure strPrefix does not match one of the rule residues
+ blnPossiblySkipEnd = False
+ If CheckSequenceAgainstCleavageRuleMatchTestResidue(strSequenceStart, strExceptionSuffixResidues) Then
+ ' Match found; need to examine strPrefix
+ blnPossiblySkipEnd = True
+ End If
+
+ If blnPossiblySkipEnd Then
+ ' Make sure strPrefix does not match one of the rule residues
+ If CheckSequenceAgainstCleavageRuleMatchTestResidue(strPrefix, strRuleResidues) Then
+ ' Match found; thus does not match cleavage rule
+ blnSkipThisEnd = True
+ End If
+ End If
+ End If
+ Else
+ strTestResidue = strSequenceEnd
+ If strSuffix = strTerminiiSymbol Then
+ intTerminiiCount = intTerminiiCount + 1
+ blnSkipThisEnd = True
+ Else
+ ' Make sure strSuffix does not match strExceptionSuffixResidues
+ If CheckSequenceAgainstCleavageRuleMatchTestResidue(strSuffix, strExceptionSuffixResidues) Then
+ ' Match found; thus does not match cleavage rule
+ blnSkipThisEnd = True
+ End If
+ End If
+ End If
+
+ If Not blnSkipThisEnd Then
+ If CheckSequenceAgainstCleavageRuleMatchTestResidue(strTestResidue, strRuleResidues) Then
+ intRuleMatchCount = intRuleMatchCount + 1
+ End If
+ End If
+ Next intEndToCheck
+
+ If intRuleMatchCount > 0 Then
+ If intRuleMatchCount = 2 Then
+ blnMatchesCleavageRule = True
+ ElseIf intRuleMatchCount >= 1 And intTerminiiCount >= 1 Then
+ blnMatchesCleavageRule = True
+ ' Bump up intRuleMatchCount to 2 since having at least one terminus and
+ ' and one rule match essentially means two rule matches
+ ' E.g., for RuleResidues = "KR", and sequence = "-.ABCDER.-", this is fully tryptic,
+ ' so we should set intRuleMatchCount to 2
+ intRuleMatchCount = 2
+ ElseIf intRuleMatchCount >= 1 And blnAllowPartialCleavage Then
+ blnMatchesCleavageRule = True
+ End If
+ ElseIf intTerminiiCount = 2 Then
+ blnMatchesCleavageRule = True
+ ' Both ends are terminii, bump up intRuleMatchCount to 2
+ intRuleMatchCount = 2
+ End If
+ End If
+
+ CheckSequenceAgainstCleavageRule = blnMatchesCleavageRule
+
+End Function
+
+Private Function CheckSequenceAgainstCleavageRuleMatchTestResidue(strTestResidue As String, strRuleResidues As String) As Boolean
+ ' Checks to see if strTestResidue matches one of the residues in strRuleResidues
+ ' Used to test by Rule Residues and Exception Residues
+
+ Dim intCharLocInRuleResidues As Integer
+ Dim strCompareResidue As String
+ Dim blnMatchFound As Boolean
+
+ For intCharLocInRuleResidues = 1 To Len(strRuleResidues)
+ strCompareResidue = Trim(Mid(strRuleResidues, intCharLocInRuleResidues, 1))
+ If Len(strCompareResidue) > 0 Then
+ If strTestResidue = strCompareResidue Then
+ blnMatchFound = True
+ Exit For
+ End If
+ End If
+ Next intCharLocInRuleResidues
+
+ CheckSequenceAgainstCleavageRuleMatchTestResidue = blnMatchFound
+
+End Function
+
+
+'
+' The following functions can be used to retrieve the name of a peptide, given a Protein sequence
+'
+Public Function GetTrypticName(ByVal strProteinResidues As String, ByVal strPeptideResidues As String, Optional ByRef lngReturnResidueStart As Long = 0, Optional ByRef lngReturnResidueEnd As Long = 0, Optional ByVal blnICR2LSCompatible As Boolean, Optional ByVal strRuleResidues As String = TRYPTIC_RULE_RESIDUES, Optional ByVal strExceptionResidues As String = TRYPTIC_EXCEPTION_RESIDUES, Optional ByVal strTerminiiSymbol As String = TERMINII_SYMBOL, Optional ByVal blnIgnoreCase As Boolean = True, Optional ByVal lngProteinSearchStartLoc As Long = 1) As String
+ ' Examines strPeptideResidues to see where they exist in strProteinResidues
+ ' Constructs a name string based on their position and based on whether the fragment is truly tryptic
+ ' In addition, returns the position of the first and last residue in lngReturnResidueStart and lngReturnResidueEnd
+ ' The tryptic name in the following format
+ ' t1 indicates tryptic peptide 1
+ ' t2 represents tryptic peptide 2, etc.
+ ' t1.2 indicates tryptic peptide 1, plus one more tryptic peptide, i.e. t1 and t2
+ ' t5.2 indicates tryptic peptide 5, plus one more tryptic peptide, i.e. t5 and t6
+ ' t5.3 indicates tryptic peptide 5, plus two more tryptic peptides, i.e. t5, t6, and t7
+ ' 40.52 means that the residues are not tryptic, and simply range from residue 40 to 52
+ ' If the peptide residues are not present in strProteinResidues, then returns ""
+ ' Since a peptide can occur multiple times in a protein, one can set lngProteinSearchStartLoc to a value larger than 1 to ignore previous hits
+
+ ' If blnICR2LSCompatible is True, then the values returned when a peptide is not tryptic are modified to
+ ' range from the starting residue, to the ending residue +1
+ ' lngReturnResidueEnd is always equal to the position of the final residue, regardless of blnICR2LSCompatible
+
+ ' For example, if strProteinResidues = "IGKANR"
+ ' Then when strPeptideResidues = "IGK", the TrypticName is t1
+ ' Then when strPeptideResidues = "ANR", the TrypticName is t2
+ ' Then when strPeptideResidues = "IGKANR", the TrypticName is t1.2
+ ' Then when strPeptideResidues = "IG", the TrypticName is 1.2
+ ' Then when strPeptideResidues = "KANR", the TrypticName is 3.6
+ ' Then when strPeptideResidues = "NR", the TrypticName is 5.6
+
+ ' However, if blnICR2LSCompatible = True, then the last three are changed to:
+ ' Then when strPeptideResidues = "IG", the TrypticName is 1.3
+ ' Then when strPeptideResidues = "KANR", the TrypticName is 3.7
+ ' Then when strPeptideResidues = "NR", the TrypticName is 5.7
+
+ Dim intStartLoc As Integer, intEndLoc As Integer
+ Dim strTrypticName As String
+ Dim strPeptideResiduesPlusPrefix As String
+ Dim strPrefix As String, strSuffix As String, strSequenceEnd As String
+ Dim strTestResidue As String, strCompareResidue As String
+ Dim strResidueFollowingSearchResidues As String
+ Dim blnSkipThisEnd As Boolean, blnMatchesCleavageRule As Boolean
+ Dim intEndToCheck As Integer, intTerminiiCount As Integer
+ Dim intCharLocInRuleResidues As Integer, intMatchCount As Integer
+
+ Dim intTrypticResidueNumber As Integer
+ Dim intRuleResidueMatchCount As Integer
+ Dim lngRuleResidueLoc As Long
+ Dim strProteinResiduesBeforeStartLoc As String
+ Dim lngPeptideResiduesLength As Long
+
+ If blnIgnoreCase Then
+ strProteinResidues = UCase(strProteinResidues)
+ strPeptideResidues = UCase(strPeptideResidues)
+ End If
+
+ If lngProteinSearchStartLoc <= 1 Then
+ intStartLoc = InStr(strProteinResidues, strPeptideResidues)
+ Else
+ intStartLoc = InStr(Mid(strProteinResidues, lngProteinSearchStartLoc), strPeptideResidues)
+ If intStartLoc > 0 Then
+ intStartLoc = intStartLoc + lngProteinSearchStartLoc - 1
+ End If
+ End If
+
+ lngPeptideResiduesLength = Len(strPeptideResidues)
+
+ If intStartLoc > 0 And Len(strProteinResidues) > 0 And lngPeptideResiduesLength > 0 Then
+ intEndLoc = intStartLoc + lngPeptideResiduesLength - 1
+
+ ' Determine if the residue is tryptic
+ ' Use CheckSequenceAgainstCleavageRule() for this
+ If intStartLoc > 1 Then
+ strPrefix = Mid(strProteinResidues, intStartLoc - 1, 1)
+ Else
+ strPrefix = strTerminiiSymbol
+ End If
+
+ If intEndLoc = Len(strProteinResidues) Then
+ strSuffix = strTerminiiSymbol
+ Else
+ strSuffix = Mid(strProteinResidues, intEndLoc + 1, 1)
+ End If
+
+ strSequenceEnd = Right(strPeptideResidues, 1)
+
+ blnMatchesCleavageRule = CheckSequenceAgainstCleavageRule(strPrefix & "." & strPeptideResidues & "." & strSuffix, strRuleResidues, strExceptionResidues, False, ".", strTerminiiSymbol, blnIgnoreCase)
+
+ If blnMatchesCleavageRule Then
+ ' Construct strTrypticName
+
+ ' Determine which tryptic residue strPeptideResidues is
+ If intStartLoc = 1 Then
+ intTrypticResidueNumber = 1
+ Else
+ intTrypticResidueNumber = 0
+ strProteinResiduesBeforeStartLoc = Left(strProteinResidues, intStartLoc - 1)
+ strResidueFollowingSearchResidues = Left(strPeptideResidues, 1)
+ intTrypticResidueNumber = 0
+ lngRuleResidueLoc = 0
+ Do
+ lngRuleResidueLoc = GetTrypticNameFindNextCleavageLoc(strProteinResiduesBeforeStartLoc, strResidueFollowingSearchResidues, lngRuleResidueLoc + 1, strRuleResidues, strExceptionResidues, strTerminiiSymbol)
+ If lngRuleResidueLoc > 0 Then
+ intTrypticResidueNumber = intTrypticResidueNumber + 1
+ End If
+ Loop While lngRuleResidueLoc > 0 And lngRuleResidueLoc + 1 < intStartLoc
+ intTrypticResidueNumber = intTrypticResidueNumber + 1
+ End If
+
+ ' Determine number of K or R residues in strPeptideResidues
+ ' Ignore K or R residues followed by Proline
+ intRuleResidueMatchCount = 0
+ lngRuleResidueLoc = 0
+ Do
+ lngRuleResidueLoc = GetTrypticNameFindNextCleavageLoc(strPeptideResidues, strSuffix, lngRuleResidueLoc + 1, strRuleResidues, strExceptionResidues, strTerminiiSymbol)
+ If lngRuleResidueLoc > 0 Then
+ intRuleResidueMatchCount = intRuleResidueMatchCount + 1
+ End If
+ Loop While lngRuleResidueLoc > 0 And lngRuleResidueLoc < lngPeptideResiduesLength
+
+ strTrypticName = "t" & Trim(Str(intTrypticResidueNumber))
+ If intRuleResidueMatchCount > 1 Then
+ strTrypticName = strTrypticName & "." & Trim(Str((intRuleResidueMatchCount)))
+ End If
+ Else
+ If blnICR2LSCompatible Then
+ strTrypticName = Trim(Str(intStartLoc)) & "." & Trim(Str(intEndLoc + 1))
+ Else
+ strTrypticName = Trim(Str(intStartLoc)) & "." & Trim(Str(intEndLoc))
+ End If
+ End If
+
+ lngReturnResidueStart = intStartLoc
+ lngReturnResidueEnd = intEndLoc
+ GetTrypticName = strTrypticName
+ Else
+ ' Residues not found
+ lngReturnResidueStart = 0
+ lngReturnResidueEnd = 0
+ GetTrypticName = ""
+ End If
+
+End Function
+
+Public Function GetTrypticNameMultipleMatches(ByVal strProteinResidues As String, ByVal strPeptideResidues As String, Optional ByRef lngReturnMatchCount As Long, Optional ByRef lngReturnResidueStart As Long = 0, Optional ByRef lngReturnResidueEnd As Long = 0, Optional ByVal blnICR2LSCompatible As Boolean, Optional ByVal strRuleResidues As String = TRYPTIC_RULE_RESIDUES, Optional ByVal strExceptionResidues As String = TRYPTIC_EXCEPTION_RESIDUES, Optional ByVal strTerminiiSymbol As String = TERMINII_SYMBOL, Optional ByVal blnIgnoreCase As Boolean = True, Optional ByVal lngProteinSearchStartLoc As Long = 1, Optional ByVal strListDelimeter As String = ", ") As String
+ ' Examines strPeptideResidues to see where they exist in strProteinResidues
+ ' Looks for all possible matches, returning them as a comma separated list
+ ' Returns the number of matches in lngReturnMatchCount
+
+ ' See GetTrypticName for additional information
+
+ Dim strNameList As String, strCurrentName As String
+ Dim lngCurrentSearchLoc As Long
+ Dim lngCurrentResidueStart As Long, lngCurrentResidueEnd As Long
+
+ lngCurrentSearchLoc = lngProteinSearchStartLoc
+ lngReturnMatchCount = 0
+ Do
+ strCurrentName = GetTrypticName(strProteinResidues, strPeptideResidues, lngCurrentResidueStart, lngCurrentResidueEnd, blnICR2LSCompatible, strRuleResidues, strExceptionResidues, strTerminiiSymbol, blnIgnoreCase, lngCurrentSearchLoc)
+
+ If Len(strCurrentName) > 0 Then
+ If Len(strNameList) > 0 Then
+ strNameList = strNameList & strListDelimeter
+ End If
+ strNameList = strNameList & strCurrentName
+ lngCurrentSearchLoc = lngCurrentResidueEnd + 1
+ lngReturnMatchCount = lngReturnMatchCount + 1
+ If lngCurrentSearchLoc > Len(strProteinResidues) Then Exit Do
+ Else
+ Exit Do
+ End If
+ Loop
+
+ GetTrypticNameMultipleMatches = strNameList
+
+End Function
+
+Private Function GetTrypticNameFindNextCleavageLoc(strSearchResidues As String, strResidueFollowingSearchResidues As String, ByVal lngStartChar As Long, Optional ByVal strSearchChars As String = TRYPTIC_RULE_RESIDUES, Optional ByVal strExceptionSuffixResidues As String = TRYPTIC_EXCEPTION_RESIDUES, Optional ByVal strTerminiiSymbol As String = TERMINII_SYMBOL) As Long
+ ' Finds the location of the next strSearchChar in strSearchResidues (K or R by default)
+ ' Assumes strSearchResidues are already upper case
+ ' Examines the residue following the matched residue
+ ' If it matches one of the characters in strExceptionSuffixResidues, then the match is not counted
+ ' Note that strResidueFollowingSearchResidues is necessary in case the potential cleavage residue is the final residue in strSearchResidues
+ ' We need to know the next residue to determine if it matches an exception residue
+ ' For example, if strSearchResidues = "IGASGEHIFIIGVDKPNR"
+ ' and the protein it is part of is: TNSANFRIGASGEHIFIIGVDKPNRQPDS
+ ' and strSearchChars = "KR while strExceptionSuffixResidues = "P"
+ ' Then the K in IGASGEHIFIIGVDKPNR is ignored because the following residue is P,
+ ' while the R in IGASGEHIFIIGVDKPNR is OK because strResidueFollowingSearchResidues is Q
+ ' It is the calling function's responsibility to assign the correct residue to strResidueFollowingSearchResidues
+ ' If no match is found, but strResidueFollowingSearchResidues is "-", then the cleavage location returned is Len(strSearchResidues) + 1
+
+ Dim intCharLocInSearchChars As Integer
+ Dim lngCharLoc As Long, lngMinCharLoc As Long
+ Dim intExceptionSuffixResidueCount As Integer
+ Dim intCharLocInExceptionChars As Integer
+ Dim strResidueFollowingCleavageResidue As String
+ Dim lngExceptionCharLocInSearchResidues As Long, lngCharLocViaRecursiveSearch As Long
+
+ intExceptionSuffixResidueCount = Len(strExceptionSuffixResidues)
+
+ lngMinCharLoc = -1
+ For intCharLocInSearchChars = 1 To Len(strSearchChars)
+ lngCharLoc = InStr(Mid(strSearchResidues, lngStartChar), Mid(strSearchChars, intCharLocInSearchChars, 1))
+ If lngCharLoc > 0 And intExceptionSuffixResidueCount > 0 Then
+ lngCharLoc = lngCharLoc + lngStartChar - 1
+
+ ' Make sure strSuffixResidue does not match strExceptionSuffixResidues
+ If lngCharLoc < Len(strSearchResidues) Then
+ lngExceptionCharLocInSearchResidues = lngCharLoc + 1
+ strResidueFollowingCleavageResidue = Mid(strSearchResidues, lngExceptionCharLocInSearchResidues, 1)
+ Else
+ ' Matched the last residue in strSearchResidues
+ lngExceptionCharLocInSearchResidues = Len(strSearchResidues) + 1
+ strResidueFollowingCleavageResidue = strResidueFollowingSearchResidues
+ End If
+
+ For intCharLocInExceptionChars = 1 To intExceptionSuffixResidueCount
+ If strResidueFollowingCleavageResidue = Mid(strExceptionSuffixResidues, intCharLocInExceptionChars, 1) Then
+ ' Exception char is the following character; can't count this as the cleavage point
+
+ If lngExceptionCharLocInSearchResidues < Len(strSearchResidues) Then
+ ' Recursively call this function to find the next cleavage position, using an updated lngStartChar position
+ lngCharLocViaRecursiveSearch = GetTrypticNameFindNextCleavageLoc(strSearchResidues, strResidueFollowingSearchResidues, lngExceptionCharLocInSearchResidues, strSearchChars, strExceptionSuffixResidues, strTerminiiSymbol)
+
+ If lngCharLocViaRecursiveSearch > 0 Then
+ ' Found a residue further along that is a valid cleavage point
+ lngCharLoc = lngCharLocViaRecursiveSearch
+ Else
+ lngCharLoc = 0
+ End If
+ Else
+ lngCharLoc = 0
+ End If
+ Exit For
+ End If
+ Next intCharLocInExceptionChars
+ End If
+
+ If lngCharLoc > 0 Then
+ If lngMinCharLoc < 0 Then
+ lngMinCharLoc = lngCharLoc
+ Else
+ If lngCharLoc < lngMinCharLoc Then
+ lngMinCharLoc = lngCharLoc
+ End If
+ End If
+ End If
+ Next intCharLocInSearchChars
+
+ If lngMinCharLoc < 0 And strResidueFollowingSearchResidues = strTerminiiSymbol Then
+ lngMinCharLoc = Len(strSearchResidues) + 1
+ End If
+
+ If lngMinCharLoc < 0 Then
+ GetTrypticNameFindNextCleavageLoc = 0
+ Else
+ GetTrypticNameFindNextCleavageLoc = lngMinCharLoc
+ End If
+
+End Function
+
+Public Function GetTrypticPeptideByFragmentNumber(ByVal strProteinResidues As String, ByVal intDesiredPeptideNumber As Integer, Optional ByRef lngReturnResidueStart As Long, Optional ByRef lngReturnResidueEnd As Long, Optional ByVal strRuleResidues As String = TRYPTIC_RULE_RESIDUES, Optional ByVal strExceptionResidues As String = TRYPTIC_EXCEPTION_RESIDUES, Optional ByVal strTerminiiSymbol As String = TERMINII_SYMBOL, Optional ByVal blnIgnoreCase As Boolean = True) As String
+ ' Returns the desired tryptic peptide from strProteinResidues
+ ' For example, if strProteinResidues = "IGKANRMTFGL" then
+ ' when intDesiredPeptideNumber = 1, returns "IGK"
+ ' when intDesiredPeptideNumber = 2, returns "ANR"
+ ' when intDesiredPeptideNumber = 3, returns "MTFGL"
+
+ ' Optionally, returns the position of the start and end residues
+ ' using lngReturnResidueStart and lngReturnResidueEnd
+
+
+ Dim lngStartLoc As Long, lngRuleResidueLoc As Long
+ Dim lngPrevStartLoc As Long
+ Dim lngProteinResiduesLength As Long
+ Dim intCurrentTrypticPeptideNumber As Integer
+
+ Dim strMatchingFragment As String
+
+ If intDesiredPeptideNumber < 1 Then
+ GetTrypticPeptideByFragmentNumber = ""
+ Exit Function
+ End If
+
+ If blnIgnoreCase Then
+ strProteinResidues = UCase(strProteinResidues)
+ End If
+ lngProteinResiduesLength = Len(strProteinResidues)
+
+ lngStartLoc = 1
+ lngRuleResidueLoc = 0
+ intCurrentTrypticPeptideNumber = 0
+ Do
+ lngRuleResidueLoc = GetTrypticNameFindNextCleavageLoc(strProteinResidues, strTerminiiSymbol, lngStartLoc, strRuleResidues, strExceptionResidues, strTerminiiSymbol)
+ If lngRuleResidueLoc > 0 Then
+ intCurrentTrypticPeptideNumber = intCurrentTrypticPeptideNumber + 1
+ lngPrevStartLoc = lngStartLoc
+ lngStartLoc = lngRuleResidueLoc + 1
+
+ If lngPrevStartLoc > lngProteinResiduesLength Then
+ ' User requested a peptide number that doesn't exist
+ GetTrypticPeptideByFragmentNumber = ""
+ Exit Function
+ End If
+ Else
+ ' I don't think I'll ever reach this code
+ Debug.Assert False
+ Exit Do
+ End If
+ Loop While intCurrentTrypticPeptideNumber < intDesiredPeptideNumber
+
+ strMatchingFragment = ""
+ If intCurrentTrypticPeptideNumber > 0 And lngPrevStartLoc > 0 Then
+ If lngPrevStartLoc > Len(strProteinResidues) Then
+ ' User requested a peptide number that is too high
+ lngReturnResidueStart = 0
+ lngReturnResidueEnd = 0
+ strMatchingFragment = ""
+ Else
+ ' Match found, find the extent of this peptide
+ lngReturnResidueStart = lngPrevStartLoc
+ If lngRuleResidueLoc > lngProteinResiduesLength Then
+ lngReturnResidueEnd = lngProteinResiduesLength
+ Else
+ lngReturnResidueEnd = lngRuleResidueLoc
+ End If
+ strMatchingFragment = Mid(strProteinResidues, lngPrevStartLoc, lngRuleResidueLoc - lngPrevStartLoc + 1)
+ End If
+ Else
+ strMatchingFragment = strProteinResidues
+ End If
+
+ GetTrypticPeptideByFragmentNumber = strMatchingFragment
+
+End Function
+
diff --git a/MwtWinDll/RevisionHistory.txt b/MwtWinDll/RevisionHistory.txt
new file mode 100644
index 0000000..4380fa2
--- /dev/null
+++ b/MwtWinDll/RevisionHistory.txt
@@ -0,0 +1,8 @@
+MwtWin.Dll Change Log
+
+Version 2.36, Build 67; November 5, 2006
+ - Updated ComputeIsotopicAbundancesInternal to properly interpret Charge state
+ - If intChargeState=0, then returns neutral masses
+ - If intChargeState=1, then returns M+H masses
+ - If intChargeState>1, then returns convoluted m/z masses
+ - Updated ConvoluteMassInternal to convert from neutral mass to M+H and to return 0 if the current charge or desired charge is 0
diff --git a/MwtWinDll/SharedVBRoutines.bas b/MwtWinDll/SharedVBRoutines.bas
new file mode 100644
index 0000000..2cf4e5c
--- /dev/null
+++ b/MwtWinDll/SharedVBRoutines.bas
@@ -0,0 +1,3028 @@
+Attribute VB_Name = "modSharedVBRoutines"
+Option Explicit
+
+'
+' Collection of Visual Basic Functions
+' Written by Matthew Monroe for use in applications
+'
+' First written in Chapel Hill, NC in roughly 2000
+'
+' Last Modified: July 13, 2003
+' Version: 1.59
+
+Public KeyPressAbortProcess As Integer ' Used with frmProgress
+Public glbDecimalSeparator As String ' Used to record whether the . or the , is the decimal point indicator (. in US while , in Europe)
+Private mTextBoxValueSaved As String ' Used to undo changes to a textbox
+
+Private Const FIELD_DELIMETER = ","
+
+' Constants for Centering Windows
+Public Const cWindowExactCenter = 0
+Public Const cWindowUpperThird = 1
+Public Const cWindowLowerThird = 2
+Public Const cWindowMiddleLeft = 3
+Public Const cWindowMiddleRight = 4
+Public Const cWindowTopCenter = 5
+Public Const cWindowBottomCenter = 6
+Public Const cWindowBottomRight = 7
+Public Const cWindowBottomLeft = 8
+Public Const cWindowTopRight = 9
+Public Const cWindowTopLeft = 10
+
+' The following function and constants are used to keep the application window
+' "on top" of other windows
+'
+Public Declare Function SetWindowPos Lib "user32" _
+ (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, _
+ ByVal x As Long, ByVal y As Long, ByVal cx As Long, _
+ ByVal cy As Long, ByVal wFlags As Long) As Long
+
+' Set some constant values (from WIN32API.TXT).
+Private Const conHwndTopmost = -1
+Private Const conHwndNoTopmost = -2
+Private Const conSwpNoActivate = &H10
+Private Const conSwpShowWindow = &H40
+
+'' Used for Internet Access
+''' Used in the GetUrlSource() Function
+''' from http://www.planet-source-code.com/vb/scripts/ShowCode.asp?lngWId=1&txtCodeId=24465
+''Public Declare Function InternetOpen Lib "wininet.dll" Alias "InternetOpenA" (ByVal sAgent As String, ByVal lAccessType As Long, ByVal sProxyName As String, ByVal sProxyBypass As String, ByVal lFlags As Long) As Long
+''Public Declare Function InternetOpenUrl Lib "wininet.dll" Alias "InternetOpenUrlA" (ByVal hInternetSession As Long, ByVal sURL As String, ByVal sHeaders As String, ByVal lHeadersLength As Long, ByVal lFlags As Long, ByVal lContext As Long) As Long
+''Public Declare Function InternetReadFile Lib "wininet.dll" (ByVal hFile As Long, ByVal sBuffer As String, ByVal lNumBytesToRead As Long, lNumberOfBytesRead As Long) As Integer
+''Public Declare Function InternetCloseHandle Lib "wininet.dll" (ByVal hInet As Long) As Integer
+''
+''Public Const IF_FROM_CACHE = &H1000000
+''Public Const IF_MAKE_PERSISTENT = &H2000000
+''Public Const IF_NO_CACHE_WRITE = &H4000000
+''
+''
+'''used for shelling out to the default web browser
+''Public Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hWnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long
+''Public Const conSwNormal = 1
+''
+''Private Const BUFFER_LEN = 2048
+
+
+' Return the handle of a window given its name or class. Pass only one of the parameters,
+' using vbNullString for the other.
+'
+' For example: hwnd = FindWindow(vbNullString, "My Window Caption")
+'
+Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
+Public Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
+Public Declare Function GetParent Lib "user32" (ByVal hwnd As Long) As Long
+Public Declare Function GetActiveWindow Lib "user32" () As Long
+Public Declare Function GetTopWindow Lib "user32" (ByVal hwnd As Long) As Long
+Public Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
+
+' GetWindow() Constants
+Public Const GW_HWNDFIRST = 0
+Public Const GW_HWNDLAST = 1
+Public Const GW_HWNDNEXT = 2
+Public Const GW_HWNDPREV = 3
+Public Const GW_OWNER = 4
+Public Const GW_CHILD = 5
+Public Const GW_MAX = 5
+Public Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, ByVal wCmd As Long) As Long
+
+'
+' More Window Functions
+'
+Public Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
+Public Declare Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" (ByVal hwnd As Long) As Long
+Public Declare Function GetNextWindow Lib "user32" Alias "GetWindow" (ByVal hwnd As Long, ByVal wFlag As Long) As Long
+
+' Functions for finding the size of the desktop
+
+Private Type Rect
+ Left As Long
+ Top As Long
+ Right As Long
+ Bottom As Long
+End Type
+
+Private Type POINTAPI
+ x As Long
+ y As Long
+End Type
+
+Private Type WINDOWPLACEMENT
+ Length As Long
+ flags As Long
+ showCmd As Long
+ ptMinPosition As POINTAPI
+ ptMaxPosition As POINTAPI
+ rcNormalPosition As Rect
+End Type
+
+Private Declare Function GetDesktopWindow Lib "user32" () As Long
+Private Declare Function GetWindowPlacement Lib "user32" (ByVal hwnd As Long, lpwndpl As WINDOWPLACEMENT) As Long
+
+' Other functions
+'
+Private Declare Function GetTempPath Lib "kernel32" Alias "GetTempPathA" (ByVal nBufferLength As Long, ByVal lpBuffer As String) As Long
+Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
+
+' Api Functions
+Public Declare Function GetTickCount Lib "kernel32" () As Long
+
+' Functions for selecting a directory (Function BrowseForFolder)
+
+Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As String) As Long
+Private Declare Function SHBrowseForFolder Lib "shell32" (lpbi As BROWSEINFO) As Long
+Private Declare Function SHGetPathFromIDList Lib "shell32" (ByVal pidList As Long, ByVal lpBuffer As String) As Long
+Private Declare Function lstrcat Lib "kernel32" Alias "lstrcatA" (ByVal lpString1 As String, ByVal lpString2 As String) As Long
+Private Declare Sub CoTaskMemFree Lib "ole32" (ByVal hMem As Long)
+Private Declare Function GetOpenFileName Lib "comdlg32" Alias "GetOpenFileNameA" (pOpenfilename As OPENFILENAME) As Long
+Private Declare Function GetSaveFileName Lib "comdlg32" Alias "GetSaveFileNameA" (pOpenfilename As OPENFILENAME) As Long
+
+Private Type BROWSEINFO
+ hwndOwner As Long
+ pidlRoot As Long
+ pszDisplayName As Long
+ lpszTitle As Long
+ ulFlags As Long
+ lpfnCallback As Long
+ lParam As Long
+ iImage As Long
+End Type
+
+'used with GetOpenFileName function
+Private Type OPENFILENAME
+ lStructSize As Long
+ hwndOwner As Long
+ hInstance As Long
+ lpstrFilter As String
+ lpstrCustomFilter As String
+ nMaxCustFilter As Long
+ nFilterIndex As Long
+ lpstrFile As String
+ nMaxFile As Long
+ lpstrFileTitle As String
+ nMaxFileTitle As Long
+ lpstrInitialDir As String
+ lpstrTitle As String
+ flags As Long
+ nFileOffset As Integer
+ nFileExtension As Integer
+ lpstrDefExt As String
+ lCustData As Long
+ lpfnHook As Long
+ lpTemplateName As String
+End Type
+
+' Possibly, this should be MAX_PATH = 257
+Private Const MAX_PATH = 512
+
+Private Const WM_USER = &H400
+Private Const BFFM_INITIALIZED = 1
+Private Const BFFM_SELCHANGED = 2
+Private Const BFFM_SETSTATUSTEXT = (WM_USER + 100)
+Private Const BFFM_SETSELECTION = (WM_USER + 102)
+
+Private Const BIF_RETURNONLYFSDIRS = &H1
+Private Const BIF_DONTGOBELOWDOMAIN = &H2
+Private Const BIF_STATUSTEXT = &H4
+Private Const BIF_RETURNFSANCESTORS = &H8
+Private Const BIF_EDITBOX = &H10
+Private Const BIF_NEWDIALOGSTYLE = &H20
+Private Const BIF_USENEWUI = &H40
+Private Const BIF_INCLUDECOMPUTERS = &H1000
+Private Const BIF_INCLUDEPRINTERS = &H2000
+Private Const BIF_INCLUDEFILES = &H4000
+
+'OPENFILENAME structure flags constants (used with Open & Save dialogs)
+Private Const OFN_ALLOWMULTISELECT = &H200
+Private Const OFN_CREATEPROMPT = &H2000
+Private Const OFN_ENABLEHOOK = &H20
+Private Const OFN_ENABLETEMPLATE = &H40
+Private Const OFN_ENABLETEMPLATEHANDLE = &H80
+Private Const OFN_EXPLORER = &H80000
+Private Const OFN_EXTENSIONDIFFERENT = &H400
+Private Const OFN_FILEMUSTEXIST = &H1000
+Private Const OFN_HIDEREADONLY = &H4
+Private Const OFN_LONGNAMES = &H200000
+Private Const OFN_NOCHANGEDIR = &H8
+Private Const OFN_NODEREFERENCELINKS = &H100000
+Private Const OFN_NOLONGNAMES = &H40000
+Private Const OFN_NONETWORKBUTTON = &H20000
+Private Const OFN_NOREADONLYRETURN = &H8000
+Private Const OFN_NOTESTFILECREATE = &H10000
+Private Const OFN_NOVALIDATE = &H100
+Private Const OFN_OVERWRITEPROMPT = &H2
+Private Const OFN_PATHMUSTEXIST = &H800
+Private Const OFN_READONLY = &H1
+Private Const OFN_SHAREAWARE = &H4000
+Private Const OFN_SHAREFALLTHROUGH = 2
+Private Const OFN_SHARENOWARN = 1
+Private Const OFN_SHAREWARN = 0
+Private Const OFN_SHOWHELP = &H10
+Private Const OFS_MAXPATHNAME = 512
+
+Private mCurrentDirectory As String ' The last directory selected using BrowseForFolder()
+'
+
+Public Sub AppendToString(ByRef strThisString As String, strAppendText As String, Optional blnAddCarriageReturn As Boolean = False)
+ strThisString = strThisString & strAppendText
+
+ If blnAddCarriageReturn Then
+ strThisString = strThisString & vbCrLf
+ End If
+End Sub
+
+Public Function AssureNonZero(lngNumber As Long) As Long
+ ' Returns a non-zero number, either -1 if lngNumber = 0 or lngNumber if it's nonzero
+ If lngNumber = 0 Then
+ AssureNonZero = -1
+ Else
+ AssureNonZero = lngNumber
+ End If
+End Function
+
+Public Function BrowseForFileOrFolder(ByVal lngOwnderhwnd As Long, Optional ByRef strStartPath As String, Optional ByVal strTitle As String = "Select File", Optional blnReturnFoldersOnly As Boolean = False, Optional strFilterDescription As String = "All") As String
+ ' Returns the path to the selected file or folder
+ ' Returns "" if cancelled
+
+ '=====================================================================================
+ ' Browse for a Folder using SHBrowseForFolder API function with a callback
+ ' function BrowseCallbackProc.
+ '
+ ' This Extends the functionality that was given in the
+ ' MSDN Knowledge Base article Q179497 "HOWTO: Select a Directory
+ ' Without the Common Dialog Control".
+ '
+ ' After reading the MSDN knowledge base article Q179378 "HOWTO: Browse for
+ ' Folders from the Current Directory", I was able to figure out how to add
+ ' a callback function that sets the starting directory and displays the
+ ' currently selected path in the "Browse For Folder" dialog.
+ '
+ ' I used VB 6.0 (SP3) to compile this code. Should work in VB 5.0.
+ ' However, because it uses the AddressOf operator this code will not
+ ' work with versions below 5.0.
+ '
+ ' This code works in Window 95a so I assume it will work with later versions.
+ '
+ ' Stephen Fonnesbeck
+ ' steev@xmission.com
+ ' http://www.xmission.com/~steev
+ ' Feb 20, 2000
+ '
+ '=====================================================================================
+ ' Usage:
+ '
+ ' Dim folder As String
+ ' folder = BrowseForFileOrFolder(Me, "C:\startdir\anywhere", True, "Select a Directory")
+ ' If Len(folder) = 0 Then Exit Sub 'User Selected Cancel
+ '
+ '=====================================================================================
+ '
+ '
+ ' Code extended by Matthew Monroe to also allow selection of files, using an example
+ ' from http://www.thescarms.com/VBasic/DirectoryBrowser.asp
+ '
+
+ Dim lpIDList As Long
+ Dim sBuffer As String
+ Dim tBrowseInfo As BROWSEINFO
+
+ If Len(strStartPath) > 0 Then
+ mCurrentDirectory = strStartPath & vbNullChar
+ End If
+
+ If Len(mCurrentDirectory) = 0 Then mCurrentDirectory = vbNullChar
+
+ With tBrowseInfo
+ .hwndOwner = lngOwnderhwnd
+ .lpszTitle = lstrcat(strTitle, "")
+ .ulFlags = BIF_RETURNONLYFSDIRS Or BIF_DONTGOBELOWDOMAIN Or BIF_STATUSTEXT Or BIF_EDITBOX Or BIF_NEWDIALOGSTYLE Or BIF_USENEWUI
+ If Not blnReturnFoldersOnly Then
+ .ulFlags = .ulFlags Or BIF_INCLUDEFILES
+ End If
+ .lpfnCallback = GetAddressofFunction(AddressOf BrowseCallbackProc) 'get address of function.
+ End With
+
+ lpIDList = SHBrowseForFolder(tBrowseInfo)
+ If (lpIDList) Then
+ sBuffer = Space(MAX_PATH)
+ SHGetPathFromIDList lpIDList, sBuffer
+ sBuffer = Left(sBuffer, InStr(sBuffer, vbNullChar) - 1)
+
+ Call CoTaskMemFree(lpIDList)
+
+ BrowseForFileOrFolder = sBuffer
+ strStartPath = sBuffer
+ Else
+ BrowseForFileOrFolder = ""
+ End If
+
+End Function
+
+' Used with BrowseForFolder
+Private Function BrowseCallbackProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal lp As Long, ByVal pData As Long) As Long
+
+ Dim lpIDList As Long
+ Dim Ret As Long
+ Dim sBuffer As String
+
+ On Error Resume Next 'Sugested by MS to prevent an error from propagating back into the calling process.
+
+ Select Case uMsg
+ Case BFFM_INITIALIZED
+ Call SendMessage(hwnd, BFFM_SETSELECTION, 1, mCurrentDirectory)
+
+ Case BFFM_SELCHANGED
+ sBuffer = Space(MAX_PATH)
+
+ Ret = SHGetPathFromIDList(lp, sBuffer)
+ If Ret = 1 Then
+ Call SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, sBuffer)
+ End If
+
+ End Select
+
+ BrowseCallbackProc = 0
+
+End Function
+
+' This function allows you to assign a function pointer to a vaiable.
+' Used with BrowseForFolder
+Private Function GetAddressofFunction(add As Long) As Long
+ GetAddressofFunction = add
+End Function
+
+Public Function cChkBox(value As Integer) As Boolean
+ ' Converts a checkbox value to true or false
+ If value = vbChecked Then
+ cChkBox = True
+ Else
+ cChkBox = False
+ End If
+End Function
+
+Public Function CLngRoundUp(dblValue As Double) As Long
+ Dim lngNewValue As Long
+ lngNewValue = CLng(dblValue)
+
+ If lngNewValue <> dblValue Then
+ lngNewValue = lngNewValue + 1
+ End If
+
+ CLngRoundUp = lngNewValue
+End Function
+
+Public Function CLngSafe(strValue As String) As Long
+ On Error Resume Next
+ If IsNumeric(strValue) Then
+ CLngSafe = CLng(strValue)
+ End If
+End Function
+
+Public Function CBoolSafe(strValue As String) As Boolean
+ On Error GoTo ReturnFalse
+ CBoolSafe = CBool(Trim(strValue))
+ Exit Function
+ReturnFalse:
+ CBoolSafe = False
+End Function
+
+Public Function CDblSafe(strWork As String) As Double
+ On Error Resume Next
+ If IsNumeric(strWork) Then
+ CDblSafe = CDbl(strWork)
+ End If
+End Function
+
+Public Function CIntSafeDbl(dblWork As Double) As Integer
+ If dblWork <= 32767 And dblWork >= -32767 Then
+ CIntSafeDbl = CInt(dblWork)
+ Else
+ If dblWork < 0 Then
+ CIntSafeDbl = -32767
+ Else
+ CIntSafeDbl = 32767
+ End If
+ End If
+End Function
+
+Public Function CIntSafe(strWork As String) As Integer
+ If IsNumeric(strWork) Then
+ CIntSafe = CIntSafeDbl(CDbl(strWork))
+ ElseIf LCase(strWork) = "true" Then
+ CIntSafe = -1
+ Else
+ CIntSafe = 0
+ End If
+End Function
+
+Public Function Combinatorial(a As Integer, B As Integer) As Single
+ If a > 170 Or B > 170 Then
+ Debug.Print "Cannot compute factorial of a number over 170. Thus, cannot compute the combination."
+ Combinatorial = -1
+ ElseIf a < B Then
+ Debug.Print "First number should be greater than or equal to the second number"
+ Combinatorial = -1
+ Else
+ Combinatorial = Factorial(a) / (Factorial(B) * Factorial(a - B))
+ End If
+End Function
+
+Public Function CompactPathString(ByVal strPathToCompact As String, Optional ByVal lngMaxLength As Long = 40) As String
+ ' Recursive function to shorten strPathToCompact to a maximum length of lngMaxLength
+
+ ' The following is example output
+ ' Note that when drive letters or subdirectories are present, the a minimum length is imposed
+ ' For "C:\My Documents\Readme.txt"
+ ' Minimum string returned= C:\M..\Rea..
+ ' Length for 20 characters= C:\My D..\Readme.txt
+ ' Length for 25 characters= C:\My Docume..\Readme.txt
+ '
+ ' For "C:\My Documents\Word\Business\Finances.doc"
+ ' Minimum string returned= C:\...\B..\Fin..
+ ' Length for 20 characters= C:\...\B..\Finance..
+ ' Length for 25 characters= C:\...\Bus..\Finances.doc
+ ' Length for 32 characters= C:\...\W..\Business\Finances.doc
+ ' Length for 40 characters= C:\My Docum..\Word\Business\Finances.doc
+
+ Dim strPath(4) As String ' 0-based array
+ Dim intPartCount As Integer
+
+ Dim strLeadingChars As String
+ Dim strShortenedPath As String
+
+ Dim lngCharLoc As Long
+ Dim intLoopCount As Integer, intFileNameIndex As Integer
+ Dim lngShortLength As Long, lngOverLength As Long
+ Dim lngLeadingCharsLength As Long
+ Dim intMultiPathCorrection As Integer
+
+ If lngMaxLength < 3 Then lngMaxLength = 3
+
+ ' Determine the name of the first directory following the leading ?:\ or \\
+
+ strPathToCompact = Trim(strPathToCompact)
+
+ If Len(strPathToCompact) <= lngMaxLength Then
+ CompactPathString = strPathToCompact
+ Exit Function
+ End If
+
+ intPartCount = 1
+ If Left(strPathToCompact, 2) = "\\" Then
+ strLeadingChars = "\\"
+ lngCharLoc = InStr(3, strPathToCompact, "\")
+ If lngCharLoc > 0 Then
+ strLeadingChars = "\\" & Mid(strPathToCompact, 3, lngCharLoc - 2)
+ strPath(0) = Mid(strPathToCompact, lngCharLoc + 1)
+ Else
+ strPath(0) = Mid(strPathToCompact, 3)
+ End If
+ ElseIf Left(strPathToCompact, 2) = ".\" Then
+ strLeadingChars = Left(strPathToCompact, 2)
+ strPath(0) = Mid(strPathToCompact, 3)
+ ElseIf Left(strPathToCompact, 3) = "..\" Or Mid(strPathToCompact, 2, 2) = ":\" Then
+ strLeadingChars = Left(strPathToCompact, 3)
+ strPath(0) = Mid(strPathToCompact, 4)
+ Else
+ strPath(0) = strPathToCompact
+ End If
+
+ ' Examine strPath(0) to see if there are 1, 2, or more subdirectories
+ intLoopCount = 0
+ Do
+ lngCharLoc = InStr(strPath(intPartCount - 1), "\")
+ If lngCharLoc > 0 Then
+ strPath(intPartCount) = Mid(strPath(intPartCount - 1), lngCharLoc + 1)
+ strPath(intPartCount - 1) = Left(strPath(intPartCount - 1), lngCharLoc)
+ intPartCount = intPartCount + 1
+ End If
+ intLoopCount = intLoopCount + 1
+ Loop While intLoopCount < 3
+
+ If intPartCount = 1 Then
+ ' No \ found, we're forced to shorten the filename (though if a UNC, then can shorten part of the UNC)
+
+ If Left(strLeadingChars, 2) = "\\" Then
+ lngLeadingCharsLength = Len(strLeadingChars)
+ If lngLeadingCharsLength > 5 Then
+ ' Can shorten the server name as needed
+ lngShortLength = lngMaxLength - Len(strPath(0)) - 3
+ If lngShortLength < lngLeadingCharsLength Then
+ If lngShortLength < 3 Then lngShortLength = 3
+ strLeadingChars = Left(strLeadingChars, lngShortLength) & "..\"
+ End If
+
+ End If
+ End If
+
+ lngShortLength = lngMaxLength - Len(strLeadingChars) - 2
+ If lngShortLength < 3 Then lngShortLength = 3
+ If lngShortLength < Len(strPath(0)) - 2 Then
+ strShortenedPath = strLeadingChars & Left(strPath(0), lngShortLength) & ".."
+ Else
+ strShortenedPath = strLeadingChars & strPath(0)
+ End If
+ Else
+ ' Found one (or more) subdirectories
+
+ ' First check if strPath(1) = "...\"
+ If strPath(0) = "...\" Then
+ intMultiPathCorrection = 4
+ strPath(0) = strPath(1)
+ strPath(1) = strPath(2)
+ strPath(2) = strPath(3)
+ strPath(3) = ""
+ intPartCount = 3
+ Else
+ intMultiPathCorrection = 0
+ End If
+
+ ' Shorten the first to as little as possible
+ ' If not short enough, replace the first with ... and call this function again
+ lngShortLength = lngMaxLength - Len(strLeadingChars) - Len(strPath(3)) - Len(strPath(2)) - Len(strPath(1)) - 3 - intMultiPathCorrection
+ If lngShortLength < 1 And Len(strPath(2)) > 0 Then
+ ' Not short enough, but other subdirectories are present
+ ' Thus, can call this function recursively
+ strShortenedPath = strLeadingChars & "...\" & strPath(1) & strPath(2) & strPath(3)
+ strShortenedPath = CompactPathString(strShortenedPath, lngMaxLength)
+ Else
+ If Left(strLeadingChars, 2) = "\\" Then
+ lngLeadingCharsLength = Len(strLeadingChars)
+ If lngLeadingCharsLength > 5 Then
+ ' Can shorten the server name as needed
+ lngShortLength = lngMaxLength - Len(strPath(3)) - Len(strPath(2)) - Len(strPath(1)) - 7 - intMultiPathCorrection
+ If lngShortLength < lngLeadingCharsLength - 3 Then
+ If lngShortLength < 3 Then lngShortLength = 3
+ strLeadingChars = Left(strLeadingChars, lngShortLength) & "..\"
+ End If
+
+ ' Recompute lngShortLength
+ lngShortLength = lngMaxLength - Len(strLeadingChars) - Len(strPath(3)) - Len(strPath(2)) - Len(strPath(1)) - 3 - intMultiPathCorrection
+ End If
+ End If
+
+ If intMultiPathCorrection > 0 Then
+ strLeadingChars = strLeadingChars & "...\"
+ End If
+
+ If lngShortLength < 1 Then lngShortLength = 1
+ strPath(0) = Left(strPath(0), lngShortLength) & "..\"
+ strShortenedPath = strLeadingChars & strPath(0) & strPath(1) & strPath(2) & strPath(3)
+
+ ' See if still to long
+ ' If it is, then will need to shorten the filename too
+ lngOverLength = Len(strShortenedPath) - lngMaxLength
+ If lngOverLength > 0 Then
+ ' Need to shorten filename too
+ ' Determine which index the filename is in
+ For intFileNameIndex = intPartCount - 1 To 0 Step -1
+ If Len(strPath(intFileNameIndex)) > 0 Then Exit For
+ Next intFileNameIndex
+
+ lngShortLength = Len(strPath(intFileNameIndex)) - lngOverLength - 2
+ If lngShortLength < 4 Then
+ strPath(intFileNameIndex) = Left(strPath(intFileNameIndex), 3) & ".."
+ Else
+ strPath(intFileNameIndex) = Left(strPath(intFileNameIndex), lngShortLength) & ".."
+ End If
+
+ strShortenedPath = strLeadingChars & strPath(0) & strPath(1) & strPath(2) & strPath(3)
+ End If
+
+ End If
+ End If
+
+ CompactPathString = strShortenedPath
+End Function
+
+Public Function TestCompactFileName(strTestString As String)
+ Dim lngIndex As Long
+
+ For lngIndex = 15 To Len(strTestString) + 2
+ Debug.Print Format(lngIndex, "000") & ": " & CompactPathString(strTestString, lngIndex)
+ Next lngIndex
+End Function
+
+Private Function ComputeAverage(ByRef sngArrayZeroBased() As Single, lngArrayCount As Long, Optional ByRef sngMedian As Single, Optional ByRef sngMinimum As Single, Optional ByRef sngMaximum As Single) As Single
+ ' Computes the average and returns it
+ ' Computes other stats and returns them
+
+ Dim lngIndex As Long
+ Dim sngSumForAveraging As Single, lclAverage As Single, lclMedian As Single
+ Dim lclMinimum As Single, lclMaximum As Single
+
+ If lngArrayCount = 0 Then
+ lclAverage = 0
+ lclMedian = 0
+ Else
+ lclMinimum = sngArrayZeroBased(0)
+ lclMaximum = lclMinimum
+
+ sngSumForAveraging = 0
+ For lngIndex = 0 To lngArrayCount - 1
+ sngSumForAveraging = sngSumForAveraging + sngArrayZeroBased(lngIndex)
+
+ If sngArrayZeroBased(lngIndex) < lclMinimum Then
+ lclMinimum = sngArrayZeroBased(lngIndex)
+ End If
+
+ If sngArrayZeroBased(lngIndex) > lclMaximum Then
+ lclMaximum = sngArrayZeroBased(lngIndex)
+ End If
+
+ Next lngIndex
+
+ lclAverage = sngSumForAveraging / lngArrayCount
+
+ lclMedian = ComputeMedian(sngArrayZeroBased(), lngArrayCount)
+ End If
+
+
+ sngMinimum = lclMinimum
+ sngMaximum = lclMaximum
+
+ sngMedian = lclMedian
+ ComputeAverage = lclAverage
+
+End Function
+
+Public Function ComputeMedian(ByRef sngArrayZeroBased() As Single, lngArrayCount As Long, Optional blnRigorousMedianForEvenNumberedDatasets As Boolean = True) As Single
+ ' Finds the median value in sngIniputArrayZeroBased() using the Select() function from Numerical Recipes in C
+ ' Returns the median
+
+ ' If lngArrayCount is Odd, then calls Select, (N+1)/2 for lngElementToSelect
+ ' If lngArrayCount is Even, and blnRigorousMedianForEvenNumberedDatasets is True, or lngArrayCount < 100,
+ ' then calls the select function twice, grabbing element N/2 and N/2 + 1
+ ' Otherwise, if lngArrayCount is Even, but blnRigorousMedianForEvenNumberedDatasets (and lngArrayCount >= 100)
+ ' then simply calls the function one, grabbing element N/2 and using this as an approximate median value
+
+ Dim lngIndex As Long, lngElementToGrab As Long
+ Dim blnEvenCount As Boolean
+ Dim sngInputArrayOneBased() As Single
+ Dim sngMedianValue As Single, sngMedianValueNextLarger As Single
+
+ If lngArrayCount <= 0 Then Exit Function
+
+ If lngArrayCount = 1 Then
+ ComputeMedian = sngArrayZeroBased(0)
+ Exit Function
+ End If
+
+ ' Since the Select function requires the array be one-based, I make a copy of the data in the Zero Based array
+ ' This also prevents sngArrayZeroBased() from being disturbed
+
+ ReDim sngInputArrayOneBased(lngArrayCount)
+
+ For lngIndex = 0 To lngArrayCount - 1
+ sngInputArrayOneBased(lngIndex + 1) = sngArrayZeroBased(lngIndex)
+ Next lngIndex
+
+ If lngArrayCount / 2# = CLng(lngArrayCount / 2#) Then
+ ' lngArrayCount is even
+ blnEvenCount = True
+ Else
+ ' lngArrayCount is odd
+ blnEvenCount = False
+ End If
+
+ If blnEvenCount Then
+ lngElementToGrab = lngArrayCount / 2
+ sngMedianValue = SelectValue(sngInputArrayOneBased(), lngArrayCount, lngElementToGrab)
+
+ If blnRigorousMedianForEvenNumberedDatasets Or lngArrayCount < 100 Then
+ sngMedianValueNextLarger = SelectValue(sngInputArrayOneBased(), lngArrayCount, lngElementToGrab + 1)
+ sngMedianValue = (sngMedianValue + sngMedianValueNextLarger) / 2
+ End If
+ Else
+ lngElementToGrab = (lngArrayCount + 1) / 2
+ sngMedianValue = SelectValue(sngInputArrayOneBased(), lngArrayCount, lngElementToGrab)
+ End If
+
+ ComputeMedian = sngMedianValue
+
+End Function
+
+Public Function ConstructFormatString(ByVal dblThisValue As Double, Optional ByRef intDigitsInFormattedValue As Integer) As String
+ ' Examines dblThisValue and constructs a format string based on its magnitude
+ ' For example, dblThisValue = 1234 will return "0"
+ ' dblThisValue = 2.4323 will return "0.0000"
+ '
+ ' In addition, returns the length of the string representation of dblThisValue
+ ' using the determined format string
+ Dim lngExponentValue As Long, intDigitsInLabel As Integer
+ Dim strWork As String, strFormatString As String
+
+ ' Determine width of label to use and construct formatting string for labels
+ ' First, find the exponent of dblThisValue
+ strWork = Format(dblThisValue, "0E+000")
+ lngExponentValue = CIntSafe(Right(strWork, 4))
+
+ ' Determine number of digits in dblThisValue, rounded according to lngExponentVal
+ If lngExponentValue >= 0 Then
+ intDigitsInLabel = 0
+ strFormatString = "0"
+ Else
+ ' Add 1 for the decimal point
+ intDigitsInLabel = -lngExponentValue + 1
+ strFormatString = "0." & String(-lngExponentValue, "0")
+ End If
+
+ intDigitsInFormattedValue = Len(Format(dblThisValue, strFormatString))
+
+ ConstructFormatString = strFormatString
+End Function
+
+Public Function CountOccurrenceInString(ByVal strStringToSearch As String, ByVal strSearchString As String, Optional ByVal blnCaseSensitive As Boolean = False) As Long
+ ' Counts the number of times strSearchString occurs in strStringToSearch
+
+ Dim lngMatchCount As Long, lngCharLoc As Long
+
+ If Not blnCaseSensitive Then
+ strStringToSearch = LCase(strStringToSearch)
+ strSearchString = LCase(strSearchString)
+ End If
+
+On Error GoTo CountOccurrenceInStringErrorHandler
+
+ If Len(strSearchString) = 0 Or Len(strStringToSearch) = 0 Then
+ lngMatchCount = 0
+ Else
+ lngCharLoc = 1
+ Do
+ lngCharLoc = InStr(lngCharLoc, strStringToSearch, strSearchString)
+ If lngCharLoc > 0 Then
+ lngMatchCount = lngMatchCount + 1
+ lngCharLoc = lngCharLoc + Len(strSearchString)
+ End If
+ Loop While lngCharLoc > 0
+ End If
+
+ CountOccurrenceInString = lngMatchCount
+ Exit Function
+
+CountOccurrenceInStringErrorHandler:
+ Debug.Assert False
+ Debug.Print "Error in CountOccurrenceInString Function: " & Err.Description
+ CountOccurrenceInString = lngMatchCount
+
+End Function
+
+Public Function CountInstancesOfApp(frmThisForm As VB.Form) As Integer
+ Dim lngHWnd As Long, strCaption As String, intInstances As Integer
+ Dim strClassName As String, nRtn As Long, lngMaxCount As Long
+
+ lngMaxCount = 100
+
+ ' See if other copies of the Software are already loaded
+ ' A hidden window bearing the name of the application is loaded for each instance of the app,
+ ' regardless of the caption of frmMain
+ '
+ ' Thus, I can search for all forms with the caption frmThisForm,
+ ' then examine the ClassName of the form.
+ ' Windows explorer folders are class CabinetWClass
+ ' All VB Apps are class ThunderMain (if in VB IDE) or ThunderRT6Main (if compiled to .Exe)
+ ' In addition, if frmMain's caption is App.Title, it will also be found,
+ ' However, it is class ThunderFormDC or ThunderRT6FormDC
+
+ ' Finally, note that I could use App.Previnstance to see if other instances of the Application are running
+ ' However, this only works for other instances with the identical version number
+ ' Thus, I'll use the Window-Handle method shown below.
+
+ On Error GoTo ExitCountInstances
+
+ lngHWnd = frmThisForm.hwnd
+ intInstances = 0
+ Do
+ DoEvents
+ If lngHWnd = 0 Then Exit Do
+ strCaption = GetWindowCaption(lngHWnd)
+
+ If LCase(strCaption) = LCase(App.Title) Then
+ ' Note: Usage of GetClassName from Joe Garrick, at
+ ' http://www.citilink.com/~jgarrick/vbasic/tips/appact.html
+ ' Must fill strClassName with spaces (or nulls) before sending to GetClassName
+ ' All VB Apps are class Thunder, and each app has one window with Thunder and Main
+ ' Windows explorer folders are class CabinetWClass
+
+ strClassName = Space(lngMaxCount)
+ nRtn = GetClassName(lngHWnd, strClassName, lngMaxCount)
+
+' If Len(strCaption) > 0 Then
+' Debug.Print "(" & lngHWnd&; ") " & strCaption & ": "; strClassName
+' End If
+
+ strClassName = Trim(LCase(strClassName))
+ If InStr(strClassName, "thunder") Then
+ If InStr(strClassName, "main") Then
+ intInstances = intInstances + 1
+ End If
+ End If
+ End If
+
+ lngHWnd = GetNextWindow(lngHWnd, 2)
+ Loop
+
+ExitCountInstances:
+ CountInstancesOfApp = intInstances
+End Function
+
+Public Function GetMostRecentTextBoxValue() As String
+ GetMostRecentTextBoxValue = mTextBoxValueSaved
+End Function
+
+Public Function GetTemporaryDir(Optional blnFavorAPI As Boolean = True) As String
+ ' Uses two different methods to get the temporary directory path
+
+ Dim strTempDirViaEnviron As String, strTempDirViaAPI As String
+ Dim strResult As String
+ Dim lngCount As Long
+ Const MAX_LENGTH = 1024
+
+ ' Get temp directory using the Environ() Function
+ strTempDirViaEnviron = Environ("TMP")
+ If Len(strTempDirViaEnviron) = 0 Then
+ strTempDirViaEnviron = Environ("TEMP")
+ End If
+
+ If Len(strTempDirViaEnviron) > 0 Then
+ If Right(strTempDirViaEnviron, 1) <> "\" Then
+ strTempDirViaEnviron = strTempDirViaEnviron & "\"
+ End If
+ End If
+
+ ' Get temp directory using an API call
+ strResult = Space(MAX_LENGTH)
+ lngCount = GetTempPath(MAX_LENGTH, strResult)
+
+ If lngCount > 0 Then
+ If lngCount > Len(strResult) Then
+ strResult = Space(lngCount + 1)
+ lngCount = GetTempPath(MAX_LENGTH, strResult)
+ End If
+ End If
+
+ If lngCount > 0 Then
+ strTempDirViaAPI = Left(strResult, lngCount)
+ Else
+ strTempDirViaAPI = ""
+ End If
+
+ If strTempDirViaAPI = strTempDirViaEnviron Then
+ GetTemporaryDir = strTempDirViaAPI
+ Else
+ If blnFavorAPI Then
+ GetTemporaryDir = strTempDirViaAPI
+ Else
+ GetTemporaryDir = strTempDirViaEnviron
+ End If
+
+ End If
+
+End Function
+
+Private Function GetWindowCaption(lngHWnd As Long) As String
+ Dim strCaption As String, lngLength As Long
+
+ lngLength = GetWindowTextLength(lngHWnd)
+
+ strCaption = String(lngLength, 0&)
+
+ GetWindowText lngHWnd, strCaption, lngLength + 1
+ GetWindowCaption = strCaption
+
+End Function
+
+Public Function CreateFolderByPath(ByVal strFolderPathToCreate As String) As Boolean
+ ' strFolderPathToCreate must have a fully qualified folder path
+ ' For example: C:\Temp\MyFolder
+ ' or \\MyServer\MyShare\NewFolder
+ ' This function will recursively step through the parent folders of the given folder,
+ ' creating them as needed
+ ' Thus, if strFolderPathToCreate = "C:\Temp\SubFolder\Docs\Working" and only C:\Temp exists
+ ' then 3 folders will be created: SubFolder, Docs, and Working
+
+ ' Returns True if the folder already exists or if it is successfully created
+ ' Returns False if an error occurs or if the folder can't be created
+
+ Dim fso As New FileSystemObject
+ Dim strParentFolderPath As String
+ Dim blnSuccess As Boolean
+
+On Error GoTo CreateFolderByPathErrorHandler
+
+ strParentFolderPath = fso.GetParentFolderName(strFolderPathToCreate)
+
+ If Len(strParentFolderPath) = 0 Then Exit Function
+
+ If Not fso.FolderExists(strParentFolderPath) Then
+ blnSuccess = CreateFolderByPath(strParentFolderPath)
+ Else
+ blnSuccess = True
+ End If
+
+ If fso.FolderExists(strParentFolderPath) And blnSuccess Then
+ If Not fso.FolderExists(strFolderPathToCreate) Then
+ On Error Resume Next
+ fso.CreateFolder (strFolderPathToCreate)
+ If Err.Number = 0 Then
+ blnSuccess = True
+ Else
+ Err.Clear
+ blnSuccess = False
+ End If
+ Else
+ ' Desired folder already exists
+ blnSuccess = True
+ End If
+ Else
+ blnSuccess = False
+ End If
+
+ CreateFolderByPath = blnSuccess
+
+ Set fso = Nothing
+ Exit Function
+
+CreateFolderByPathErrorHandler:
+ CreateFolderByPath = False
+
+End Function
+
+Public Function CSngSafe(strValue As String) As Single
+ If IsNumeric(strValue) Then
+ CSngSafe = CSng(strValue)
+ End If
+End Function
+
+Public Function CStrIfNonZero(ByVal dblThisNumber As Double, Optional strAppendString As String = "", Optional intNumDecimalPlacesToRound As Integer = -1, Optional blnEmptyStringForZero As Boolean = True, Optional blnEmptyStringForNegative As Boolean = True) As String
+ Dim strFormattingString As String
+
+ If (blnEmptyStringForZero And dblThisNumber = 0) Then
+ CStrIfNonZero = ""
+ Else
+ If (blnEmptyStringForNegative And dblThisNumber < 0) Then
+ CStrIfNonZero = ""
+ Else
+ If intNumDecimalPlacesToRound = -1 Then
+ CStrIfNonZero = Trim(CStr(dblThisNumber)) & strAppendString
+ Else
+ If intNumDecimalPlacesToRound = 0 Then
+ strFormattingString = "0"
+ Else
+ strFormattingString = "0." & String(intNumDecimalPlacesToRound, "0")
+ End If
+ CStrIfNonZero = Format(dblThisNumber, strFormattingString) & strAppendString
+ End If
+ End If
+ End If
+End Function
+
+' The following subroutines require the presence of the Microsoft Internet Connection Control on a form
+'''Public Function DownloadWebPage(frmICControlForm as VB.Form, strHtmlLink As String, Optional boolUpdateProgressForm As Boolean = False) As String
+''' ' Returns the text of the page at strHtmlLink
+'''
+''' ' This function requires a Microsoft Internet Connection control to be present on the form specified by
+''' ' frmICControlForm
+''' ' In addition, frmProgress must be present in the project
+'''
+''' ' When using this function (in conjunction with the Microsoft URL Control)
+''' ' the browser appears in the web server logs as 'Microsoft URL Control - 6.00.8862'
+'''
+''' If boolUpdateProgressForm Then
+''' frmProgress.UpdateCurrentSubTask "Downloading web page"
+''' End If
+'''
+''' frmICControlForm.Inet1.AccessType = icUseDefault
+''' DownloadWebPage = frmICControlForm.Inet1.OpenURL(strHtmlLink, 0)
+'''
+''' If boolUpdateProgressForm Then
+''' frmProgress.UpdateCurrentSubTask "Done"
+''' End If
+'''End Function
+'''
+'''Public Function DownloadWebPageAsByteArray(frmICControlForm as VB.Form, strHtmlLink As String, Optional boolUpdateProgressForm As Boolean = False) As Variant
+''' ' Returns a byte array of the data at strHtmlLink
+'''
+''' ' This function requires a Microsoft Internet Connection control to be present on the form specified by
+''' ' frmICControlForm
+''' ' In addition, frmProgress must be present in the project
+'''
+''''''' Note: To download a picture to the hard drive use the following code in the sub calling this function
+'''''' Dim ByteArray() As Byte
+''''''
+'''''' ByteArray = DownloadWebPageAsByteArray(frmMain, strHtmlLink, False)
+''''''
+'''''' If UBound(ByteArray()) > 0 Then
+'''''' ' Save the data to disk
+'''''' Open strFilepath For Binary Access Write As #1
+'''''' Put #1, , ByteArray()
+'''''' Close #1
+'''''' End If
+'''''''
+'''
+''' If boolUpdateProgressForm Then
+''' frmProgress.UpdateCurrentSubTask "Downloading web page"
+''' End If
+'''
+''' frmICControlForm.Inet1.AccessType = icUseDefault
+''' DownloadWebPageAsByteArray = frmICControlForm.Inet1.OpenURL(strHtmlLink, icByteArray)
+'''
+''' If boolUpdateProgressForm Then
+''' frmProgress.UpdateCurrentSubTask "Done"
+''' End If
+'''End Function
+
+Public Function DetermineDecimalPoint() As String
+ Dim strTestNumber As String, sglConversionResult As Double
+
+ ' I need to use the On Error Resume Next statement
+ ' Since the Trim(Str(Cdbl(...))) statement causes an error when the
+ ' user's computer is configured for using , for decimal points but not . for the
+ ' thousand's separator (instead, perhaps, using a space for thousands)
+ On Error Resume Next
+
+ ' Determine what locale we're in (. or , for decimal point)
+ strTestNumber = "5,500"
+ sglConversionResult = CDbl(strTestNumber)
+ If sglConversionResult = 5.5 Then
+ ' Use comma as Decimal point
+ DetermineDecimalPoint = ","
+ Else
+ ' Use period as Decimal point
+ DetermineDecimalPoint = "."
+ End If
+
+End Function
+
+Public Function FlattenStringArray(strArrayZeroBased() As String, lngArrayCount As Long, Optional strLineDelimeter As String = vbCrLf, Optional blnShowProgressFormOnLongOperation As Boolean = True, Optional blnIncludeDelimeterAfterFinalItem As Boolean = True) As String
+ ' Flattens the entries in strArrayZeroBased() into a single string, separating each entry by strLineDelimeter
+ ' Uses some recursive tricks to speed up this process vs. simply concatenating all the entries to a single string variable
+
+ Const MIN_PROGRESS_COUNT = 2500
+
+ ' Note: The following must be evenly divisible by 10
+ Const CUMULATIVE_CHUNK_SIZE = 500
+
+ Dim lngFillStringMaxIndex As Long
+ Dim lngSrcIndex As Long
+ Dim blnShowProgress As Boolean
+ Dim FillStringArray() As String
+ Dim FillStringCumulative As String
+
+ lngFillStringMaxIndex = -1
+
+ If lngArrayCount > MIN_PROGRESS_COUNT And blnShowProgressFormOnLongOperation Then blnShowProgress = True
+
+ If blnShowProgress Then frmProgress.InitializeForm "Copying data to clipboard", 0, lngArrayCount, False, False, False
+
+ ReDim FillStringArray(CLng(lngArrayCount / CUMULATIVE_CHUNK_SIZE) + 2)
+
+ For lngSrcIndex = 0 To lngArrayCount - 1
+ If lngSrcIndex Mod CUMULATIVE_CHUNK_SIZE / 10 = 0 Then
+ If lngSrcIndex Mod CUMULATIVE_CHUNK_SIZE = 0 Then
+ lngFillStringMaxIndex = lngFillStringMaxIndex + 1
+ End If
+
+ If blnShowProgress Then
+ frmProgress.UpdateProgressBar lngSrcIndex
+ If KeyPressAbortProcess > 1 Then Exit For
+ End If
+ End If
+
+ FillStringArray(lngFillStringMaxIndex) = FillStringArray(lngFillStringMaxIndex) & strArrayZeroBased(lngSrcIndex) & strLineDelimeter
+
+ Next lngSrcIndex
+
+ If lngFillStringMaxIndex >= 0 And Not blnIncludeDelimeterAfterFinalItem Then
+ FillStringArray(lngFillStringMaxIndex) = Left(FillStringArray(lngFillStringMaxIndex), Len(FillStringArray(lngFillStringMaxIndex)) - Len(strLineDelimeter))
+ End If
+
+ For lngSrcIndex = 0 To lngFillStringMaxIndex
+ FillStringCumulative = FillStringCumulative & FillStringArray(lngSrcIndex)
+ Next lngSrcIndex
+
+ FlattenStringArray = FillStringCumulative
+
+ If blnShowProgress Then frmProgress.HideForm
+
+End Function
+
+Public Function FolderExists(strPath As String) As Boolean
+ Dim fso As New FileSystemObject
+
+ If Len(strPath) > 0 Then
+
+ FolderExists = fso.FolderExists(strPath)
+ Else
+ FolderExists = False
+ End If
+
+ Set fso = Nothing
+End Function
+
+Public Function FormatNumberAsString(ByVal dblNumber As Double, Optional lngMaxLength As Long = 10, Optional lngMaxDigitsOfPrecision As Long = 8, Optional blnUseScientificWhenTooLong As Boolean = True) As String
+
+ Dim strNumberAsText As String
+ Dim strZeroes As String
+
+ If lngMaxDigitsOfPrecision <= 1 Then
+ strZeroes = "0"
+ Else
+ strZeroes = "0." & String(lngMaxDigitsOfPrecision - 1, "0")
+ End If
+
+ dblNumber = CDbl(Format(dblNumber, strZeroes & "E+0"))
+
+ strNumberAsText = CStr(dblNumber)
+
+ If Len(strNumberAsText) > lngMaxLength Then
+ If blnUseScientificWhenTooLong Then
+ If lngMaxLength < 5 Then lngMaxLength = 5
+
+ strZeroes = String(lngMaxLength - 5, "0")
+ strNumberAsText = Format(dblNumber, "0." & strZeroes & "E+0")
+ Else
+ If lngMaxLength < 3 Then lngMaxLength = 3
+ strNumberAsText = Round(dblNumber, lngMaxLength - 2)
+ End If
+ End If
+
+ FormatNumberAsString = strNumberAsText
+
+End Function
+
+Public Function Factorial(Number As Integer) As Double
+ ' Compute the factorial of a number; uses recursion
+ ' Number should be an integer number between 0 and 170
+
+ On Error GoTo FactorialOverflow
+
+ If Number > 170 Then
+ Debug.Print "Cannot compute factorial of a number over 170"
+ Factorial = -1
+ Exit Function
+ End If
+
+ If Number < 0 Then
+ Debug.Print "Cannot compute factorial of a negative number"
+ Factorial = -1
+ Exit Function
+ End If
+
+ If Number = 0 Then
+ Factorial = 1
+ Else
+ Factorial = Number * Factorial(Number - 1)
+ End If
+
+ Exit Function
+
+FactorialOverflow:
+ Debug.Print "Number too large"
+ Factorial = -1
+End Function
+
+'''Public Function FileExists(strFilepath As String, Optional blnIncludeReadOnly As Boolean = True, Optional blnIncludeHidden As Boolean = False) As Boolean
+''' Warning: This function will match both files and folders
+'''
+''' Dim strTestFile As String
+''' Dim intAttributes As Integer
+'''
+''' If Len(strFilepath) = 0 Then
+''' FileExists = False
+''' Exit Function
+''' End If
+'''
+''' If blnIncludeReadOnly Then intAttributes = intAttributes Or vbReadOnly
+''' If blnIncludeHidden Then intAttributes = intAttributes Or vbHidden
+'''
+''' On Error Resume Next
+''' strTestFile = Dir(strFilepath, intAttributes)
+'''
+''' If Len(strTestFile) > 0 Then
+''' FileExists = True
+''' Else
+''' FileExists = False
+''' End If
+'''
+'''End Function
+
+Public Function FileExists(strFilePath As String) As Boolean
+ Dim fso As New FileSystemObject
+
+ If Len(strFilePath) > 0 Then
+ FileExists = fso.FileExists(strFilePath)
+ Else
+ FileExists = False
+ End If
+
+ Set fso = Nothing
+End Function
+
+Public Function FileExtensionForce(ByVal strFilePath As String, ByVal strExtensionToForce As String, Optional ByVal blnReplaceExistingExtension As Boolean = True) As String
+ ' Guarantees that strFilePath has the desired extension
+ ' Returns strFilePath, with the extension appended if it isn't present
+ '
+ ' Example Call: strFilePath = FileExtensionForce("MyTextFile", "txt")
+ ' will return MyTextFile.txt
+ ' Second Example: strFilePath = FileExtensionForce("MyTextFile.txt", "txt")
+ ' will return MyTextFile.txt
+
+ Dim fso As New FileSystemObject
+ Dim strExistingExtension As String
+
+ strExtensionToForce = Trim(strExtensionToForce)
+ If Left(strExtensionToForce, 1) = "." Then strExtensionToForce = Mid(strExtensionToForce, 2)
+
+ strExistingExtension = fso.GetExtensionName(strFilePath)
+ If UCase(strExistingExtension) <> UCase(strExtensionToForce) Then
+ If blnReplaceExistingExtension And Len(strExistingExtension) > 0 Then
+ FileExtensionForce = Left(strFilePath, Len(strFilePath) - Len(strExistingExtension)) & strExtensionToForce
+ Else
+ FileExtensionForce = strFilePath & "." & strExtensionToForce
+ End If
+ Else
+ FileExtensionForce = strFilePath
+ End If
+
+ Set fso = Nothing
+End Function
+
+' Finds a window containg strCaption and returns the handle to the window
+' Returns 0 if no matches
+Public Function FindWindowCaption(ByVal strCaptionToFind As String, Optional ByRef strClassOfMatch As String) As Long
+
+ Dim strCaption As String
+ Dim lngHWnd As Long, nRtn As Long
+ Const lngMaxCount = 32
+
+ lngHWnd = GetTopWindow(0)
+ Do While lngHWnd <> 0
+ strCaption = GetWindowCaption(lngHWnd)
+
+ If InStr(LCase(strCaption), LCase(strCaptionToFind)) Then
+ nRtn = GetClassName(lngHWnd, strClassOfMatch, lngMaxCount)
+ FindWindowCaption = lngHWnd
+ Exit Do
+ End If
+
+ lngHWnd = GetNextWindow(lngHWnd, 2)
+ Loop
+
+End Function
+
+Private Function GetDesktopSize(ByRef lngHeight As Long, ByRef lngWidth As Long, blnUseTwips As Boolean) As Long
+ ' Determines the height and width of the desktop
+ ' Returns values in Twips, if requested
+ ' Returns the width
+ Dim lngHWnd As Long, lngReturn As Long
+ Dim lpWindowPlacement As WINDOWPLACEMENT
+
+ lngHWnd = GetDesktopWindow()
+
+ lngReturn = GetWindowPlacement(lngHWnd, lpWindowPlacement)
+
+ With lpWindowPlacement.rcNormalPosition
+ lngHeight = .Bottom - .Top
+ lngWidth = .Right - .Left
+ End With
+
+ If blnUseTwips Then
+ lngWidth = lngWidth * Screen.TwipsPerPixelX
+ lngHeight = lngHeight * Screen.TwipsPerPixelY
+ End If
+
+ GetDesktopSize = lngWidth
+End Function
+
+Public Function GetClipboardTextSmart() As String
+ Dim intAttempts As Integer, strClipboardText As String
+ Const cMaxAttempts = 5
+
+ intAttempts = 0
+
+TryAgain:
+ Err.Clear
+ On Error GoTo TryAgain
+ intAttempts = intAttempts + 1
+ If intAttempts <= cMaxAttempts Then
+ Sleep 100
+ strClipboardText = Clipboard.GetText()
+ Else
+ strClipboardText = ""
+ MsgBox Err.Description & vbCrLf & "Continuing without retrieving any clipboard text", vbInformation + vbOKOnly
+ End If
+
+ GetClipboardTextSmart = strClipboardText
+
+End Function
+
+''Public Function GetUrlSource(sURL As String, Optional boolUpdateProgressForm As Boolean = False) As String
+'' ' Function from http://www.planet-source-code.com/vb/scripts/ShowCode.asp?lngWId=1&txtCodeId=24465
+''
+'' ' Note: When using this function, the browser appears in the web server logs as the currently installed web browser (typically MSIE 5.x or MSIE 6.x)
+''
+'' Dim sBuffer As String * BUFFER_LEN, iResult As Integer, sData As String
+'' Dim hInternet As Long, hSession As Long, lReturn As Long
+''
+'' If boolUpdateProgressForm Then
+'' frmProgress.UpdateCurrentSubTask "Initializing internal web browser"
+'' End If
+''
+'' 'get the handle of the current internet connection
+'' hSession = InternetOpen("vb wininet", 1, vbNullString, vbNullString, 0)
+''
+'' 'get the handle of the url
+'' If hSession Then
+'' hInternet = InternetOpenUrl(hSession, sURL, vbNullString, 0, IF_NO_CACHE_WRITE, 0)
+'' End If
+''
+'' If boolUpdateProgressForm Then
+'' frmProgress.UpdateCurrentSubTask "Downloading web page"
+'' End If
+''
+'' 'if we have the handle, then start reading the web page
+'' If hInternet Then
+'' 'get the first chunk & buffer it.
+'' iResult = InternetReadFile(hInternet, sBuffer, BUFFER_LEN, lReturn)
+'' sData = sBuffer
+'' 'if there's more data then keep reading it into the buffer
+'' Do While lReturn <> 0
+'' If boolUpdateProgressForm Then
+'' With frmProgress.lblCurrentSubTask
+'' .Caption = .Caption & "."
+'' If Len(.Caption) > 50 Then .Caption = ""
+'' End With
+'' DoEvents
+'' End If
+''
+'' iResult = InternetReadFile(hInternet, sBuffer, BUFFER_LEN, lReturn)
+'' sData = sData + Mid(sBuffer, 1, lReturn)
+'' Loop
+'' End If
+''
+'' 'close the URL
+'' iResult = InternetCloseHandle(hInternet)
+''
+'' If boolUpdateProgressForm Then
+'' frmProgress.UpdateCurrentSubTask "Done"
+'' End If
+''
+'' GetUrlSource = sData
+''End Function
+
+Public Function IsCharacter(TestString As String) As Boolean
+ ' Returns true if the first letter of TestString is a character (i.e. a lowercase or uppercase letter)
+ Dim AsciiValue As Integer
+ If Len(TestString) > 0 Then
+ AsciiValue = Asc(Left(TestString, 1))
+ Select Case AsciiValue
+ Case 65 To 90, 97 To 122
+ IsCharacter = True
+ Case Else
+ IsCharacter = False
+ End Select
+ Else
+ IsCharacter = False
+ End If
+End Function
+
+'for use in a .bas module or class contained in
+'the same project as the form(s) being tested for
+Public Function IsLoaded(FormName As String) As Boolean
+
+ Dim strFormName As String
+ Dim objForm As VB.Form
+
+ strFormName = UCase(FormName)
+
+ For Each objForm In Forms
+ If UCase(objForm.Name) = strFormName Then
+ IsLoaded = True
+ Exit Function
+ End If
+ Next
+
+End Function
+
+Public Function Log10(x As Double) As Double
+ On Error Resume Next
+ Log10 = Log(x) / Log(10#)
+End Function
+
+''''For use in a class contained in an external .dll
+''Public Function IsLoaded(FormName As String, FormCollection As Object) As Boolean
+''
+'' Dim strFormName As String
+'' Dim f as VB.Form
+''
+'' strFormName = ucase(FormName)
+''
+'' On Error Resume Next
+'' For Each f In FormCollection
+'' If ucase(f.Name) = strFormName Then
+'' IsLoaded = True
+'' Exit Function
+'' End If
+'' Next
+''
+''End Function
+
+''
+''Public Sub LaunchDefaultWebBrowser(frmParentForm as VB.Form, strHtmlAddressToView As String)
+'' ' Any valid form can be passed as the parent form
+'' ' Necessary since an hWnd value is required to run ShellExecute
+''
+'' ShellExecute frmParentForm.hWnd, "open", strHtmlAddressToView, vbNullString, vbNullString, conSwNormal
+''End Sub
+
+Public Function MatchAndSplit(ByRef strSearchString As String, strTextBefore As String, strTextAfter As String, Optional boolRemoveTextBeforeAndMatch As Boolean = True) As String
+ ' Looks for strTextBefore in the string
+ ' Next looks for strTextAfter in the string
+ ' Returns the text between strTextBefore and strTextAfter
+ ' If strTextBefore is not found, starts at the beginning of the string
+ ' If strTextAfter is not found, continues to end of string
+
+ ' In addition, can remove strTextBefore and the matching string from strWork, though keeping strTextAfter
+
+ Dim lngMatchIndex As Long, strWork As String, strMatch As String
+
+ strWork = strSearchString
+
+ lngMatchIndex = InStr(strWork, strTextBefore)
+ If lngMatchIndex > 0 Then
+ strWork = Mid(strWork, lngMatchIndex + Len(strTextBefore))
+ End If
+ lngMatchIndex = InStr(strWork, strTextAfter)
+
+ If lngMatchIndex > 0 Then
+ strMatch = Left(strWork, lngMatchIndex - 1)
+ strWork = Mid(strWork, lngMatchIndex)
+ Else
+ strMatch = strWork
+ strWork = ""
+ End If
+
+ If boolRemoveTextBeforeAndMatch Then
+ strSearchString = strWork
+ End If
+
+ MatchAndSplit = strMatch
+End Function
+
+Public Sub ParseAndSortList(strSearchList As String, ByRef strTextArrayZeroBased() As String, ByRef lngTextArrayCount As Long, Optional ByVal strDelimeters As String = ",;", Optional blnSpaceDelimeter As Boolean = True, Optional blnCarriageReturnDelimeter As Boolean = True, Optional blnSortItems As Boolean = True, Optional blnSortItemsAsNumbers As Boolean = False, Optional blnRemoveDuplicates As Boolean = True, Optional ByVal lngMaxParseCount As Long = 1000)
+ ' Breaks apart strSearchList according to the delimeter specifications
+ ' Places the subparts in strTextArrayZeroBased()
+ ' Optionally sorts the items
+ ' Optionally removes duplicate items
+ '
+ '
+ ' Since this sub requires the use of a special, single character to represent
+ ' a carriage return, if strDelimeters = "" and blnSpaceDelimeter = False, but
+ ' blnCarriageReturnDelimeter = True, then we must choose a substitute single
+ ' character delimeter. We've chosen to use Chr(1). Thus, strSearchList should
+ ' not contain Chr(1) in this special case
+
+ Dim strCrLfReplacement As String
+ Dim lngArrayCountBeforeDuplicatesRemoval As Long
+ Dim lngIndex As Long
+
+ If lngMaxParseCount <= 0 Then lngMaxParseCount = 1000000000#
+
+ ' Possibly add a space to strDelimeters
+ If blnSpaceDelimeter Then strDelimeters = strDelimeters & " "
+ If Len(strDelimeters) = 0 And blnCarriageReturnDelimeter Then
+ ' Need to have at least one character in strDelimeters for the Replace() statement below to work
+ ' I'll use Chr(1) since
+ strDelimeters = Chr(1)
+ End If
+
+ If Len(strDelimeters) = 0 Then
+ ' No delimeters
+ ' Place all of the text in strTextArrayZeroBased(0)
+ lngTextArrayCount = 1
+ ReDim strTextArrayZeroBased(0)
+ strTextArrayZeroBased(0) = strSearchList
+ Exit Sub
+ End If
+
+ If blnCarriageReturnDelimeter Then
+ ' To make life easier, replace all of the carriage returns in strSearchList with
+ ' the first delimeter in strDelimeters (stored in strCrLfReplacement)
+ strCrLfReplacement = Left(strDelimeters, 1)
+ strSearchList = Replace(strSearchList, vbCrLf, strCrLfReplacement)
+ End If
+
+ lngTextArrayCount = ParseString(strSearchList, strTextArrayZeroBased(), lngMaxParseCount, strDelimeters, "", False, True, False)
+
+ If lngTextArrayCount >= 1 Then
+ ReDim Preserve strTextArrayZeroBased(0 To lngTextArrayCount - 1)
+
+ If blnSortItems Then
+ ShellSortString strTextArrayZeroBased(), 0, lngTextArrayCount - 1, blnSortItemsAsNumbers
+ End If
+
+ lngArrayCountBeforeDuplicatesRemoval = lngTextArrayCount
+ If blnRemoveDuplicates Then
+ RemoveDuplicates strTextArrayZeroBased(), lngTextArrayCount
+ End If
+ Else
+ lngTextArrayCount = 0
+ ReDim strTextArrayZeroBased(0)
+ End If
+
+End Sub
+
+Public Function ParseString(ByVal strWork As String, ByRef strParsedVals() As String, lngParseTrackMax As Long, Optional strFieldDelimeter As String = FIELD_DELIMETER, Optional strRemaining As String, Optional boolMatchWholeDelimeter As Boolean = True, Optional boolCombineConsecutiveDelimeters As Boolean = False, Optional blnOneBaseArray As Boolean = True) As Long
+ ' Scans strWork, looking for strFieldDelimeter, splitting strWork into a maximum of lngParseTrackMax parts
+ ' and storing the results in strParsedVals()
+ ' Note that strParsedVals() is a 1-based array if blnOneBaseArray = True (which is default)
+
+ ' strFieldDelimeter may be 1 or more characters long. If multiple characters, use
+ ' boolMatchWholeDelimeter = True to treat strFieldDelimeter as just one delimeter
+ ' Use boolMatchWholeDelimeter = False to treat each of the characters in strFieldDelimeter as a delimeter (token)
+ ' When boolCombineConsecutiveDelimeters is true, then consecutive delimeters (like ,,, or two or more spaces) will be treated as just one delimeter
+
+ ' Returns the number of values found
+ ' If there was strParsedVals() gets filled to lngParseTrackMax, then the remaining text is placed in strRemaining
+
+ Const DIM_CHUNK_SIZE = 10
+
+ Dim lngParseTrack As Long, lngMatchIndex As Long
+ Dim lngParseTrackDimCount As Long
+
+ Dim lngIndexOffset As Long
+ Dim lngCharLoc As Long
+
+ If blnOneBaseArray Then
+ lngIndexOffset = 0
+ Else
+ lngIndexOffset = 1
+ End If
+
+ lngParseTrackDimCount = DIM_CHUNK_SIZE
+
+ ' Need to use On Error Resume Next here in case strParsedVals() has a fixed size (i.e. was dimmed at design time)
+ On Error Resume Next
+ ReDim strParsedVals(lngParseTrackDimCount + 1) ' Must add 1 since any remainder is placed in array (following the Do While-Loop)
+ On Error GoTo ParseStringErrorHandler
+
+ lngParseTrack = 0
+ lngMatchIndex = ParseStringFindNextDelimeter(strWork, strFieldDelimeter, boolMatchWholeDelimeter, boolCombineConsecutiveDelimeters)
+ Do While lngMatchIndex > 0 And lngParseTrack < lngParseTrackMax
+ lngParseTrack = lngParseTrack + 1
+ If lngParseTrack >= lngParseTrackDimCount Then
+ lngParseTrackDimCount = lngParseTrackDimCount + DIM_CHUNK_SIZE
+ On Error Resume Next
+ ReDim Preserve strParsedVals(lngParseTrackDimCount + 1) ' Must add 1 since any remainder is placed in array (following the Do While-Loop)
+ On Error GoTo ParseStringErrorHandler
+ End If
+
+ If lngMatchIndex > 1 Then
+ strParsedVals(lngParseTrack - lngIndexOffset) = Left(strWork, lngMatchIndex - 1)
+ Else
+ strParsedVals(lngParseTrack - lngIndexOffset) = ""
+ End If
+
+ If boolMatchWholeDelimeter Then
+ strWork = Mid(strWork, lngMatchIndex + Len(strFieldDelimeter))
+ Else
+ strWork = Mid(strWork, lngMatchIndex + 1)
+ If boolCombineConsecutiveDelimeters Then
+ ' Need to check for, and remove, any delimeters at the end of strParsedVals(lngParseTrack - lngIndexOffset)
+ Do
+ lngCharLoc = ParseStringFindNextDelimeter(strParsedVals(lngParseTrack - lngIndexOffset), strFieldDelimeter, False, True)
+ If lngCharLoc > 0 Then
+ strParsedVals(lngParseTrack - lngIndexOffset) = Left(strParsedVals(lngParseTrack - lngIndexOffset), lngCharLoc - 1) & Mid(strParsedVals(lngParseTrack - lngIndexOffset), lngCharLoc + 1)
+ End If
+ Loop While lngCharLoc > 0
+ End If
+ End If
+ lngMatchIndex = ParseStringFindNextDelimeter(strWork, strFieldDelimeter, boolMatchWholeDelimeter, boolCombineConsecutiveDelimeters)
+ Loop
+
+ If Len(strWork) > 0 Then
+ ' Items still remain; append to strParsedVals() or place in strRemaining
+ If lngParseTrack < lngParseTrackMax Then
+ lngParseTrack = lngParseTrack + 1
+ strParsedVals(lngParseTrack - lngIndexOffset) = strWork
+ Else
+ strRemaining = strWork
+ End If
+ End If
+
+ ParseString = lngParseTrack
+ Exit Function
+
+ParseStringErrorHandler:
+ Debug.Assert False
+ Debug.Print "Error with ParseString: " & Err.Description
+ ParseString = lngParseTrack
+
+End Function
+
+Public Function ParseStringValues(ByVal strWork As String, ByRef intParsedVals() As Integer, intParseTrackMax As Integer, Optional strFieldDelimeter As String = FIELD_DELIMETER, Optional strRemaining As String, Optional boolMatchWholeDelimeter As Boolean = True, Optional boolCombineConsecutiveDelimeters As Boolean = False, Optional blnOneBaseArray As Boolean = True) As Integer
+ ' See ParseString for parameter descriptions
+
+ Dim intParseTrack As Integer
+ Dim intIndex As Integer, intMaxIndexToCopy As Integer
+ Dim strParsedVals() As String
+
+ If intParseTrackMax < 0 Then intParseTrackMax = 0
+ ReDim strParsedVals(intParseTrackMax + 1)
+
+ ' Need to use On Error Resume Next here in case intParsedVals() has a fixed size (i.e. was dimmed at design time)
+ On Error Resume Next
+ ReDim intParsedVals(intParseTrackMax + 1)
+ On Error GoTo ParseStringValuesErrorHandler
+
+ intParseTrack = ParseString(strWork, strParsedVals(), CLng(intParseTrackMax), strFieldDelimeter, strRemaining, boolMatchWholeDelimeter, boolCombineConsecutiveDelimeters, blnOneBaseArray)
+
+ intMaxIndexToCopy = intParseTrackMax
+ If UBound(intParsedVals) < intMaxIndexToCopy Then
+ intMaxIndexToCopy = UBound(intParsedVals)
+ End If
+
+ For intIndex = 0 To intMaxIndexToCopy
+ If IsNumeric(strParsedVals(intIndex)) Then
+ intParsedVals(intIndex) = CInt(strParsedVals(intIndex))
+ Else
+ intParsedVals(intIndex) = 0
+ End If
+ Next intIndex
+
+ ParseStringValues = intParseTrack
+ Exit Function
+
+ParseStringValuesErrorHandler:
+ Debug.Assert False
+ Debug.Print "Error with ParseStringValues: " & Err.Description
+ ParseStringValues = intParseTrack
+
+End Function
+
+Public Function ParseStringValuesDbl(ByVal strWork As String, ByRef dblParsedVals() As Double, intParseTrackMax As Integer, Optional strFieldDelimeter As String = FIELD_DELIMETER, Optional strRemaining As String, Optional boolMatchWholeDelimeter As Boolean = True, Optional boolCombineConsecutiveDelimeters As Boolean = False, Optional blnOneBaseArray As Boolean = True) As Integer
+ ' See ParseStringText
+
+ Dim intParseTrack As Integer
+ Dim intIndex As Integer, intMaxIndexToCopy As Integer
+ Dim strParsedVals() As String
+
+ If intParseTrackMax < 0 Then intParseTrackMax = 0
+ ReDim strParsedVals(intParseTrackMax + 1)
+
+ ' Need to use On Error Resume Next here in case dblParsedVals() has a fixed size (i.e. was dimmed at design time)
+ On Error Resume Next
+ ReDim dblParsedVals(intParseTrackMax + 1)
+ On Error GoTo ParseStringValuesDblErrorHandler
+
+ intParseTrack = ParseString(strWork, strParsedVals(), CLng(intParseTrackMax), strFieldDelimeter, strRemaining, boolMatchWholeDelimeter, boolCombineConsecutiveDelimeters, blnOneBaseArray)
+
+ intMaxIndexToCopy = intParseTrackMax
+ If UBound(dblParsedVals) < intMaxIndexToCopy Then
+ intMaxIndexToCopy = UBound(dblParsedVals)
+ End If
+
+ For intIndex = 0 To intMaxIndexToCopy
+ If IsNumeric(strParsedVals(intIndex)) Then
+ dblParsedVals(intIndex) = CDbl(strParsedVals(intIndex))
+ Else
+ dblParsedVals(intIndex) = 0
+ End If
+ Next intIndex
+
+ ParseStringValuesDbl = intParseTrack
+ Exit Function
+
+ParseStringValuesDblErrorHandler:
+ Debug.Assert False
+ Debug.Print "Error with ParseStringValuesDbl: " & Err.Description
+ ParseStringValuesDbl = intParseTrack
+
+End Function
+
+Public Function ParseStringFindCrlfIndex(ByRef strWork As String, ByRef intDelimeterLength As Integer) As Long
+ ' First looks for vbCrLf in strWork
+ ' Returns index if found, setting intDelimeterLength to 2
+ ' If not found, uses ParseStringFindNextDelimeter to search for just CR or just LF,
+ ' returning location and setting intDelimeterLength to 1
+
+ Dim lngCrLfLoc As Long
+
+ lngCrLfLoc = InStr(strWork, vbCrLf)
+ If lngCrLfLoc = 0 Then
+ ' CrLf not found; look for just Cr or just LF
+ lngCrLfLoc = ParseStringFindNextDelimeter(strWork, vbCrLf, False)
+ intDelimeterLength = 1
+ Else
+ intDelimeterLength = 2
+ End If
+
+ ParseStringFindCrlfIndex = lngCrLfLoc
+End Function
+
+Private Function ParseStringFindNextDelimeter(ByVal strWork As String, strFieldDelimeter As String, Optional boolMatchWholeDelimeter As Boolean = True, Optional boolCombineConsecutiveDelimeters As Boolean = False) As Long
+ ' Scans strWork, looking for next delimeter (token)
+ ' strFieldDelimeter may be 1 or more characters long. If multiple characters, use
+ ' boolMatchWholeDelimeter = True to treat strFieldDelimeter as just one delimeter
+ ' Use boolMatchWholeDelimeter = False to treat each of the characters in strFieldDelimeter as a delimeter (token)
+
+ Dim intFieldDelimeterLength As Integer, intDelimeterIndex As Integer
+ Dim lngMatchIndex As Long, lngSmallestMatchIndex As Long
+ Dim blnDelimeterMatched As Boolean
+
+ intFieldDelimeterLength = Len(strFieldDelimeter)
+
+ If intFieldDelimeterLength = 0 Then
+ lngSmallestMatchIndex = 0
+ Else
+ If boolMatchWholeDelimeter Or intFieldDelimeterLength = 1 Then
+ lngSmallestMatchIndex = InStr(strWork, strFieldDelimeter)
+ Else
+ ' Look for each of the characters in strFieldDelimeter, returning the smallest nonzero index found
+ lngSmallestMatchIndex = 0
+ For intDelimeterIndex = 1 To Len(strFieldDelimeter)
+ lngMatchIndex = InStr(strWork, Mid(strFieldDelimeter, intDelimeterIndex, 1))
+ If lngMatchIndex > 0 Then
+ If lngMatchIndex < lngSmallestMatchIndex Or lngSmallestMatchIndex = 0 Then
+ lngSmallestMatchIndex = lngMatchIndex
+ End If
+ End If
+ Next intDelimeterIndex
+ End If
+
+ ' If boolCombineConsecutiveDelimeters is true, then examine adjacent text for more delimeters, returning location of final delimeter
+ If boolCombineConsecutiveDelimeters Then
+ lngMatchIndex = lngSmallestMatchIndex + 1
+ Do While lngMatchIndex <= Len(strWork)
+ If boolMatchWholeDelimeter Or intFieldDelimeterLength = 1 Then
+ If Mid(strWork, lngMatchIndex, intFieldDelimeterLength) = strFieldDelimeter Then
+ lngMatchIndex = lngMatchIndex + intFieldDelimeterLength
+ Else
+ Exit Do
+ End If
+ Else
+ blnDelimeterMatched = False
+ For intDelimeterIndex = 1 To Len(strFieldDelimeter)
+ If Mid(strWork, lngMatchIndex, 1) = Mid(strFieldDelimeter, intDelimeterIndex, 1) Then
+ blnDelimeterMatched = True
+ Exit For
+ End If
+ Next intDelimeterIndex
+ If blnDelimeterMatched Then
+ lngMatchIndex = lngMatchIndex + 1
+ Else
+ Exit Do
+ End If
+ End If
+ Loop
+ lngSmallestMatchIndex = lngMatchIndex - 1
+ End If
+
+ End If
+
+ ParseStringFindNextDelimeter = lngSmallestMatchIndex
+
+End Function
+
+Public Sub RemoveDuplicates(ByRef strTextArrayZeroBased() As String, ByRef lngArrayCount As Long)
+ Dim lngIndex As Long
+ Dim lngCompareIndex As Long
+ Dim lngShiftIndex As Long
+
+ lngIndex = 0
+ Do While lngIndex < lngArrayCount
+ lngCompareIndex = lngArrayCount - 1
+ Do While lngCompareIndex > lngIndex
+ If strTextArrayZeroBased(lngIndex) = strTextArrayZeroBased(lngCompareIndex) Then
+ ' Remove duplicate item
+ For lngShiftIndex = lngCompareIndex To lngArrayCount - 2
+ strTextArrayZeroBased(lngShiftIndex) = strTextArrayZeroBased(lngShiftIndex + 1)
+ Next lngShiftIndex
+ lngArrayCount = lngArrayCount - 1
+ strTextArrayZeroBased(lngArrayCount) = ""
+ If lngCompareIndex >= lngArrayCount Then Exit Do
+ Else
+ lngCompareIndex = lngCompareIndex - 1
+ End If
+ Loop
+ lngIndex = lngIndex + 1
+ Loop
+
+End Sub
+
+Public Function ReplaceSubString(ByRef strSearchString As String, strTextToFind As String, strTextToReplaceWith As String) As Boolean
+ ' Returns true if a change was made to strSearchString
+
+ Dim lngMatchIndex As Long, intSearchTextLength As Integer, boolReplaced As Boolean
+
+ boolReplaced = False
+ intSearchTextLength = Len(strTextToFind)
+
+ Do
+ lngMatchIndex = InStr(strSearchString, strTextToFind)
+ If lngMatchIndex > 0 Then
+ strSearchString = Left(strSearchString, lngMatchIndex - 1) & strTextToReplaceWith & Mid(strSearchString, lngMatchIndex + intSearchTextLength)
+ boolReplaced = True
+ End If
+ Loop While lngMatchIndex > 0
+
+ ReplaceSubString = boolReplaced
+
+End Function
+
+Public Function RoundToNearest(ByVal dblNumberToRound As Double, ByVal lngMultipleToRoundTo As Long, ByVal blnRoundUp As Boolean) As Long
+ ' Rounds a number to the nearest Multiple specified
+ ' If blnRoundUp = True, then always rounds up
+ ' If blnRoundUp = False, then always rounds down
+ Dim lngRoundedNumber As Long
+
+ If lngMultipleToRoundTo = 0 Then lngMultipleToRoundTo = 1
+
+ ' Use Int() to get the floor of the number
+ lngRoundedNumber = Int(dblNumberToRound / CDbl(lngMultipleToRoundTo)) * lngMultipleToRoundTo
+
+ If blnRoundUp And lngRoundedNumber < dblNumberToRound Then
+ lngRoundedNumber = lngRoundedNumber + lngMultipleToRoundTo
+ End If
+ RoundToNearest = lngRoundedNumber
+End Function
+
+Public Function SelectFile(ByVal Ownerhwnd As Long, ByVal sTitle As String, Optional ByRef strStartPath As String = "", Optional blnSaveFile As Boolean = False, Optional strDefaultFileName As String = "", Optional ByVal strFileFilterCodes As String = "All Files (*.*)|*.*|Text Files (*.txt)|*.txt", Optional ByRef intFilterIndexDefault As Integer = 1, Optional blnFileMustExistOnOpen As Boolean = True) As String
+ ' Returns file name if user selects a file (for opening) or enters a valid path (for saving)
+ ' Returns "" if user canceled dialog
+ ' If strStartPath = "", then uses last directory for default directory
+ ' Updates strStartPath to contain the directory of the selected file
+ ' Updates intFilterIndexDefault to have the filter index of the selected file (if a valid file is chosen)
+
+ Dim ofDlg As OPENFILENAME
+ Dim Res As Long
+ Dim Chr0Pos As Integer
+
+ Dim sFilter As String
+ Dim nFilterInd As Integer
+ Dim strSelectedFile As String
+ Dim strSuggestedFileName As String
+
+ If Len(strFileFilterCodes) = 0 Then
+ sFilter = "All Files" & Chr(0) & "*.*"
+ nFilterInd = 1
+ Else
+ sFilter = Replace(strFileFilterCodes, "|", Chr(0))
+ sFilter = sFilter & Chr(0)
+ nFilterInd = intFilterIndexDefault
+ End If
+
+ If Len(strStartPath) > 0 Then
+ mCurrentDirectory = strStartPath & vbNullChar
+ End If
+
+ If Len(mCurrentDirectory) = 0 Then mCurrentDirectory = vbNullChar
+
+ strSuggestedFileName = strDefaultFileName
+
+ ' GetSaveFileName() doesn't like having colons in the suggested filename
+ strSuggestedFileName = Replace(strSuggestedFileName, ":", "")
+
+ With ofDlg
+ .lStructSize = Len(ofDlg)
+ .hwndOwner = Ownerhwnd
+ .hInstance = App.hInstance
+ .lpstrFilter = sFilter
+ .nFilterIndex = nFilterInd
+ If Len(strSuggestedFileName) > 0 Then
+ .lpstrFile = strSuggestedFileName & String(MAX_PATH, 0)
+ Else
+ .lpstrFile = String(MAX_PATH, 0)
+ End If
+ .nMaxFile = Len(.lpstrFile) - 1
+ .lpstrFileTitle = .lpstrFile
+ .nMaxFileTitle = .nMaxFile
+ .lpstrInitialDir = mCurrentDirectory
+ .lpstrTitle = sTitle
+ If blnSaveFile Then
+ .flags = OFN_LONGNAMES Or OFN_OVERWRITEPROMPT Or OFN_HIDEREADONLY
+ Else
+ If blnFileMustExistOnOpen Then
+ .flags = OFN_FILEMUSTEXIST
+ Else
+ .flags = 0
+ End If
+ End If
+ End With
+
+ If blnSaveFile Then
+ Res = GetSaveFileName(ofDlg)
+ Else
+ Res = GetOpenFileName(ofDlg)
+ End If
+
+ ' Give Windows a chance to refresh (i.e., close the dialog)
+ DoEvents
+
+ If Res = 0 Then
+ SelectFile = ""
+ Else
+ Chr0Pos = InStr(1, ofDlg.lpstrFile, Chr(0))
+ If Chr0Pos > 0 Then
+ strSelectedFile = Left(ofDlg.lpstrFile, Chr0Pos - 1)
+ Else
+ strSelectedFile = Trim(ofDlg.lpstrFile)
+ End If
+
+ StripFullPath strSelectedFile, mCurrentDirectory
+ strStartPath = mCurrentDirectory
+ intFilterIndexDefault = ofDlg.nFilterIndex
+
+ SelectFile = strSelectedFile
+ End If
+
+End Function
+
+Private Function SelectValue(ByRef sngInputArrayOneBased() As Single, lngArrayCount As Long, lngElementToSelect As Long) As Single
+ ' Rearranges sngInputArrayZeroBased such that the lngElementToSelect'th element is in sngInputArrayZeroBased(lngElementToSelect)
+ ' Code is from Numerical Recipes In C (Section 8.5, page 375)
+
+ ' Returns the kth smallest value in the array arr[1...n]. The input array will be rearranged
+ ' to have this value in location arr[k], with all smaller elements moved to arr[1..k-1] (in
+ ' arbitrary order) and all larger elements in arr[k+1..n] (also in arbitrary order).
+
+ Dim i As Long, ir As Long, j As Long, l As Long, lngMidPoint As Long
+
+ Dim a As Single
+
+ l = 1
+ ir = lngArrayCount
+
+ ' Loop until the Exit Do statement is reached
+ Do
+
+ If ir <= l + 1 Then
+ If ir = l + 1 And sngInputArrayOneBased(ir) < sngInputArrayOneBased(l) Then
+ SwapSingle sngInputArrayOneBased(l), sngInputArrayOneBased(ir)
+ End If
+ Exit Do
+ Else
+ lngMidPoint = Int((l + ir) / 2)
+ SwapSingle sngInputArrayOneBased(lngMidPoint), sngInputArrayOneBased(l + 1)
+
+ If sngInputArrayOneBased(l) > sngInputArrayOneBased(ir) Then
+ SwapSingle sngInputArrayOneBased(l), sngInputArrayOneBased(ir)
+ End If
+ If sngInputArrayOneBased(l + 1) > sngInputArrayOneBased(ir) Then
+ SwapSingle sngInputArrayOneBased(l + 1), sngInputArrayOneBased(ir)
+ End If
+ If sngInputArrayOneBased(l) > sngInputArrayOneBased(l + 1) Then
+ SwapSingle sngInputArrayOneBased(l), sngInputArrayOneBased(l + 1)
+ End If
+ i = l + 1
+ j = ir
+ a = sngInputArrayOneBased(l + 1)
+
+ Do
+ Do
+ i = i + 1
+ Loop While sngInputArrayOneBased(i) < a
+
+ Do
+ j = j - 1
+ Loop While sngInputArrayOneBased(j) > a
+
+ If j < i Then Exit Do
+
+ SwapSingle sngInputArrayOneBased(i), sngInputArrayOneBased(j)
+ Loop
+ sngInputArrayOneBased(l + 1) = sngInputArrayOneBased(j)
+ sngInputArrayOneBased(j) = a
+ If j >= lngElementToSelect Then ir = j - 1
+ If j <= lngElementToSelect Then l = i
+
+ End If
+ Loop
+
+ SelectValue = sngInputArrayOneBased(lngElementToSelect)
+
+'' Debug.Print "Checking median; should be " & sngInputArrayOneBased(lngElementToSelect)
+'' For j = 1 To lngArrayCount
+'' Debug.Print sngInputArrayOneBased(j)
+'' Next j
+'' Debug.Print ""
+
+End Function
+
+Public Function SetCheckBox(ByRef chkThisCheckBox As VB.CheckBox, blnIsChecked As Boolean)
+ If blnIsChecked Then
+ chkThisCheckBox.value = vbChecked
+ Else
+ chkThisCheckBox.value = vbUnchecked
+ End If
+End Function
+
+Public Sub SetMostRecentTextBoxValue(strNewText As String)
+ mTextBoxValueSaved = strNewText
+End Sub
+
+Public Sub ShellSortLong(ByRef lngArray() As Long, ByVal lngLowIndex As Long, ByVal lngHighIndex As Long)
+ Dim lngCount As Long
+ Dim lngIncrement As Long
+ Dim lngIndex As Long
+ Dim lngIndexCompare As Long
+ Dim lngCompareVal As Long
+
+On Error GoTo ShellSortLongErrorHandler
+
+' sort array[lngLowIndex..lngHighIndex]
+
+ ' compute largest increment
+ lngCount = lngHighIndex - lngLowIndex + 1
+ lngIncrement = 1
+ If (lngCount < 14) Then
+ lngIncrement = 1
+ Else
+ Do While lngIncrement < lngCount
+ lngIncrement = 3 * lngIncrement + 1
+ Loop
+ lngIncrement = lngIncrement \ 3
+ lngIncrement = lngIncrement \ 3
+ End If
+
+ Do While lngIncrement > 0
+ ' sort by insertion in increments of lngIncrement
+ For lngIndex = lngLowIndex + lngIncrement To lngHighIndex
+ lngCompareVal = lngArray(lngIndex)
+ For lngIndexCompare = lngIndex - lngIncrement To lngLowIndex Step -lngIncrement
+ ' Use <= to sort ascending; Use > to sort descending
+ If lngArray(lngIndexCompare) <= lngCompareVal Then Exit For
+ lngArray(lngIndexCompare + lngIncrement) = lngArray(lngIndexCompare)
+ Next lngIndexCompare
+ lngArray(lngIndexCompare + lngIncrement) = lngCompareVal
+ Next lngIndex
+ lngIncrement = lngIncrement \ 3
+ Loop
+
+ Exit Sub
+
+ShellSortLongErrorHandler:
+ Debug.Assert False
+End Sub
+
+' Shell Sort
+Public Sub ShellSortSingle(ByRef sngArray() As Single, ByVal lngLowIndex As Long, ByVal lngHighIndex As Long)
+ Dim lngCount As Long
+ Dim lngIncrement As Long
+ Dim lngIndex As Long
+ Dim lngIndexCompare As Long
+ Dim sngCompareVal As Single
+
+On Error GoTo ShellSortSingleErrorHandler
+
+' sort array[lngLowIndex..lngHighIndex]
+
+ ' compute largest increment
+ lngCount = lngHighIndex - lngLowIndex + 1
+ lngIncrement = 1
+ If (lngCount < 14) Then
+ lngIncrement = 1
+ Else
+ Do While lngIncrement < lngCount
+ lngIncrement = 3 * lngIncrement + 1
+ Loop
+ lngIncrement = lngIncrement \ 3
+ lngIncrement = lngIncrement \ 3
+ End If
+
+ Do While lngIncrement > 0
+ ' sort by insertion in increments of lngIncrement
+ For lngIndex = lngLowIndex + lngIncrement To lngHighIndex
+ sngCompareVal = sngArray(lngIndex)
+ For lngIndexCompare = lngIndex - lngIncrement To lngLowIndex Step -lngIncrement
+ ' Use <= to sort ascending; Use > to sort descending
+ If sngArray(lngIndexCompare) <= sngCompareVal Then Exit For
+ sngArray(lngIndexCompare + lngIncrement) = sngArray(lngIndexCompare)
+ Next lngIndexCompare
+ sngArray(lngIndexCompare + lngIncrement) = sngCompareVal
+ Next lngIndex
+ lngIncrement = lngIncrement \ 3
+ Loop
+
+'' Debug.Assert VerifySort(sngArray(), lngLowIndex, lngHighIndex)
+ Exit Sub
+
+ShellSortSingleErrorHandler:
+ Debug.Assert False
+End Sub
+
+
+' This sub is about 3 times slower than the above ShellSortSingle routine
+Public Sub ShellSortSingleOld(ByRef sngArray() As Single, ByVal lngLowIndex As Long, ByVal lngHighIndex As Long)
+ Dim sngSwap As Single
+
+ ' Sort the list via a shell sort
+ Dim lngMaxRow As Long, lngOffSet As Long, lngLimit As Long, lngSwitch As Long
+ Dim lngRow As Long
+
+ ' Set comparison lngOffset to half the number of records
+ lngMaxRow = lngHighIndex
+ lngOffSet = lngMaxRow \ 2
+
+ ' When just two data points in the array, need to make sure at least one comparison occurs
+ If (lngHighIndex - lngLowIndex - 1) = 2 Then lngOffSet = 1
+
+ Do While lngOffSet > 0 ' Loop until lngOffset gets to zero.
+
+ lngLimit = lngMaxRow - lngOffSet
+ Do
+ lngSwitch = 0 ' Assume no switches at this lngOffset.
+
+ ' Compare elements and Switch ones out of order:
+ For lngRow = lngLowIndex To lngLimit
+ ' Use > to sort ascending, < to sort descending
+ If sngArray(lngRow) > sngArray(lngRow + lngOffSet) Then
+ sngSwap = sngArray(lngRow + lngOffSet)
+ sngArray(lngRow + lngOffSet) = sngArray(lngRow)
+ sngArray(lngRow) = sngSwap
+ lngSwitch = lngRow
+ End If
+ Next lngRow
+
+ ' Sort on next pass only to where last lngSwitch was made:
+ lngLimit = lngSwitch - lngOffSet
+ Loop While lngSwitch
+
+ ' No switches at last lngOffset, try one half as big:
+ lngOffSet = lngOffSet \ 2
+
+ Loop
+End Sub
+
+Public Sub ShellSortString(ByRef strArray() As String, ByVal lngLowIndex As Long, ByVal lngHighIndex As Long, Optional blnSortItemsAsNumbers As Boolean = False)
+ Dim lngCount As Long
+ Dim lngIncrement As Long
+ Dim lngIndex As Long
+ Dim lngIndexCompare As Long
+ Dim strCompareVal As String
+
+On Error GoTo ShellSortStringErrorHandler
+
+ ' sort array[lngLowIndex..lngHighIndex]
+
+ ' compute largest increment
+ lngCount = lngHighIndex - lngLowIndex + 1
+ lngIncrement = 1
+ If (lngCount < 14) Then
+ lngIncrement = 1
+ Else
+ Do While lngIncrement < lngCount
+ lngIncrement = 3 * lngIncrement + 1
+ Loop
+ lngIncrement = lngIncrement \ 3
+ lngIncrement = lngIncrement \ 3
+ End If
+
+ If blnSortItemsAsNumbers Then
+ Do While lngIncrement > 0
+ ' sort by insertion in increments of lngIncrement
+ For lngIndex = lngLowIndex + lngIncrement To lngHighIndex
+ strCompareVal = strArray(lngIndex)
+ For lngIndexCompare = lngIndex - lngIncrement To lngLowIndex Step -lngIncrement
+ ' Use <= to sort ascending; Use > to sort descending
+ If Val(strArray(lngIndexCompare)) <= Val(strCompareVal) Then Exit For
+ strArray(lngIndexCompare + lngIncrement) = strArray(lngIndexCompare)
+ Next lngIndexCompare
+ strArray(lngIndexCompare + lngIncrement) = strCompareVal
+ Next lngIndex
+ lngIncrement = lngIncrement \ 3
+ Loop
+ Else
+ Do While lngIncrement > 0
+ ' sort by insertion in increments of lngIncrement
+ For lngIndex = lngLowIndex + lngIncrement To lngHighIndex
+ strCompareVal = strArray(lngIndex)
+ For lngIndexCompare = lngIndex - lngIncrement To lngLowIndex Step -lngIncrement
+ ' Use <= to sort ascending; Use > to sort descending
+ If strArray(lngIndexCompare) <= strCompareVal Then Exit For
+ strArray(lngIndexCompare + lngIncrement) = strArray(lngIndexCompare)
+ Next lngIndexCompare
+ strArray(lngIndexCompare + lngIncrement) = strCompareVal
+ Next lngIndex
+ lngIncrement = lngIncrement \ 3
+ Loop
+ End If
+
+ Exit Sub
+
+ShellSortStringErrorHandler:
+Debug.Assert False
+
+End Sub
+
+' Quick sort
+Public Sub QuickSort(ByRef sngArray() As Single, ByVal lngLowIndex As Long, ByVal lngHighIndex As Long)
+ ' From http://oopweb.com/Algorithms/Documents/Sman/Volume/s_vsq2.txt
+ Dim lbStack(32) As Long
+ Dim ubStack(32) As Long
+ Dim lngStackPointer As Long ' stack pointer
+ Dim lngCurrentLowerBoundIndex As Long ' current lower-bound
+ Dim lngCurrentUpperBoundIndex As Long ' current upper-bound
+ Dim lngPivotIndex As Long ' index to pivot
+ Dim i As Long
+ Dim j As Long
+ Dim m As Long
+ Dim sngSwapVal As Single ' temp used for exchanges
+
+ lbStack(0) = lngLowIndex
+ ubStack(0) = lngHighIndex
+ lngStackPointer = 0
+ Do While lngStackPointer >= 0
+ lngCurrentLowerBoundIndex = lbStack(lngStackPointer)
+ lngCurrentUpperBoundIndex = ubStack(lngStackPointer)
+
+ Do While (lngCurrentLowerBoundIndex < lngCurrentUpperBoundIndex)
+
+ ' select pivot and exchange with 1st element
+ lngPivotIndex = lngCurrentLowerBoundIndex + (lngCurrentUpperBoundIndex - lngCurrentLowerBoundIndex) \ 2
+
+ ' exchange lngCurrentLowerBoundIndex, lngPivotIndex
+ sngSwapVal = sngArray(lngCurrentLowerBoundIndex)
+ sngArray(lngCurrentLowerBoundIndex) = sngArray(lngPivotIndex)
+ sngArray(lngPivotIndex) = sngSwapVal
+
+ ' partition into two segments
+ i = lngCurrentLowerBoundIndex + 1
+ j = lngCurrentUpperBoundIndex
+ Do
+ Do While i < j
+ If sngArray(lngCurrentLowerBoundIndex) <= sngArray(i) Then Exit Do
+ i = i + 1
+ Loop
+
+ Do While j >= i
+ If sngArray(j) <= sngArray(lngCurrentLowerBoundIndex) Then Exit Do
+ j = j - 1
+ Loop
+
+ If i >= j Then Exit Do
+
+ ' exchange i, j
+ sngSwapVal = sngArray(i)
+ sngArray(i) = sngArray(j)
+ sngArray(j) = sngSwapVal
+
+ j = j - 1
+ i = i + 1
+ Loop
+
+ ' pivot belongs in sngArray[j]
+ ' exchange lngCurrentLowerBoundIndex, j
+ sngSwapVal = sngArray(lngCurrentLowerBoundIndex)
+ sngArray(lngCurrentLowerBoundIndex) = sngArray(j)
+ sngArray(j) = sngSwapVal
+
+ m = j
+
+ ' keep processing smallest segment, and stack largest
+ If m - lngCurrentLowerBoundIndex <= lngCurrentUpperBoundIndex - m Then
+ If m + 1 < lngCurrentUpperBoundIndex Then
+ lbStack(lngStackPointer) = m + 1
+ ubStack(lngStackPointer) = lngCurrentUpperBoundIndex
+ lngStackPointer = lngStackPointer + 1
+ End If
+ lngCurrentUpperBoundIndex = m - 1
+ Else
+ If m - 1 > lngCurrentLowerBoundIndex Then
+ lbStack(lngStackPointer) = lngCurrentLowerBoundIndex
+ ubStack(lngStackPointer) = m - 1
+ lngStackPointer = lngStackPointer + 1
+ End If
+ lngCurrentLowerBoundIndex = m + 1
+ End If
+ Loop
+ lngStackPointer = lngStackPointer - 1
+ Loop
+
+ Debug.Assert VerifySort(sngArray(), lngLowIndex, lngHighIndex)
+End Sub
+
+Public Sub TestSortRoutines()
+ Const DATA_COUNT = 10000
+ Const LOOP_COUNT = 25
+ Const MOD_CHUNK = 1
+ Dim sngTest(DATA_COUNT) As Single, sngArrayToSort(DATA_COUNT) As Single
+ Dim lngRandomNumberSeed As Long
+ Dim lngIndex As Long, lngLoop As Long
+ Dim lngStartTime As Long, lngStopTime As Long
+
+ Debug.Print "Testing Data_Count = " & DATA_COUNT
+ lngRandomNumberSeed = Timer
+
+ ' Call Rnd() with a negative number before calling Randomize() lngRandomNumberSeed in order to
+ ' guarantee that we get the same order of random numbers each time
+ Call Rnd(-1)
+ Randomize lngRandomNumberSeed
+ lngStartTime = GetTickCount()
+ For lngLoop = 0 To LOOP_COUNT - 1
+ If lngLoop Mod MOD_CHUNK = 0 Then Debug.Print ".";
+
+ For lngIndex = 0 To DATA_COUNT - 1
+ sngTest(lngIndex) = Rnd(1)
+ sngArrayToSort(lngIndex) = sngTest(lngIndex)
+ Next lngIndex
+
+ ' Call ShellSort
+ ShellSortSingleOld sngArrayToSort(), 0, DATA_COUNT - 1
+
+ ' Restore sngArrayToSort() to original order
+ For lngIndex = 0 To DATA_COUNT - 1
+ sngArrayToSort(lngIndex) = sngTest(lngIndex)
+ Next lngIndex
+ Next lngLoop
+ lngStopTime = GetTickCount()
+ Debug.Print "ShellSortOld took " & lngStopTime - lngStartTime & " msec total"
+
+
+ Call Rnd(-1)
+ Randomize lngRandomNumberSeed
+ lngStartTime = GetTickCount()
+ For lngLoop = 0 To LOOP_COUNT - 1
+ If lngLoop Mod MOD_CHUNK = 0 Then Debug.Print ".";
+
+ For lngIndex = 0 To DATA_COUNT - 1
+ sngTest(lngIndex) = Rnd(1)
+ sngArrayToSort(lngIndex) = sngTest(lngIndex)
+ Next lngIndex
+
+ ' Call ShellSort
+ ShellSortSingle sngArrayToSort(), 0, DATA_COUNT - 1
+
+ ' Restore sngArrayToSort() to original order
+ For lngIndex = 0 To DATA_COUNT - 1
+ sngArrayToSort(lngIndex) = sngTest(lngIndex)
+ Next lngIndex
+ Next lngLoop
+ lngStopTime = GetTickCount()
+ Debug.Print "ShellSort took " & lngStopTime - lngStartTime & " msec total"
+
+
+ Call Rnd(-1)
+ Randomize lngRandomNumberSeed
+ lngStartTime = GetTickCount()
+ For lngLoop = 0 To LOOP_COUNT - 1
+ If lngLoop Mod MOD_CHUNK = 0 Then Debug.Print ".";
+
+ For lngIndex = 0 To DATA_COUNT - 1
+ sngTest(lngIndex) = Rnd(1)
+ sngArrayToSort(lngIndex) = sngTest(lngIndex)
+ Next lngIndex
+
+ ' Call QuickSort
+ QuickSort sngArrayToSort(), 0, DATA_COUNT - 1
+
+ ' Restore sngArrayToSort() to original order
+ For lngIndex = 0 To DATA_COUNT - 1
+ sngArrayToSort(lngIndex) = sngTest(lngIndex)
+ Next lngIndex
+ Next lngLoop
+ lngStopTime = GetTickCount()
+ Debug.Print "QuickSort took " & lngStopTime - lngStartTime & " msec total"
+
+End Sub
+
+Public Sub SizeAndCenterWindow(frmThisForm As VB.Form, Optional intCenterMode As Integer = 0, Optional lngWindowWidth As Long = -1, Optional lngWindowHeight As Long = -1, Optional boolSizeAndCenterOnlyOncePerProgramSession As Boolean = True, Optional intDualMonitorToUse As Integer = -1)
+ ' Sub revision 1.2
+
+ ' Center Mode uses one of the following:
+ ' Public Const cWindowExactCenter = 0
+ ' Public Const cWindowUpperThird = 1
+ ' Public Const cWindowLowerThird = 2
+ ' Public Const cWindowMiddleLeft = 3
+ ' Public Const cWindowMiddleRight = 4
+ ' Public Const cWindowTopCenter = 5
+ ' Public Const cWindowBottomCenter = 6
+ ' Public Const cWindowBottomRight = 7
+ ' Public Const cWindowBottomLeft = 8
+ ' Public Const cWindowTopRight = 9
+ ' Public Const cWindowTopLeft = 10
+
+ ' This sub routine properly recognizes dual monitors, centering the form to just one monitor
+
+ ' lngWindowWidth and lngWindowHeight are in twips (there are 15 twips in one pixel)
+ ' intDualMonitorToUse can be 0 or 1, signifying the first or second monitor
+ ' boolSizeAndCenterOnlyOncePerProgramSession is useful when the SizeAndCenterWindow sub is called from the Form_Activate sub of a form
+ ' Note: It is suggested that this be set to false if called from Form_Load in case the user closes the form (thus unloading it)
+
+ Const MAX_RESIZE_FORMS_TO_REMEMBER = 100
+ Dim lngWindowAreaWidth As Long, lngWindowAreaHeight As Long, dblAspectRatio As Double
+ Dim lngWorkingAreaWidth As Long, lngWorkingAreaHeight As Long
+ Dim boolDualMonitor As Boolean, boolHorizontalDual As Boolean
+ Dim lngWindowTopToSet As Long, lngWindowLeftToSet As Long
+ Dim frmMainAppForm As VB.Form
+ Static strFormsCentered(MAX_RESIZE_FORMS_TO_REMEMBER) As String ' 0-based array
+ Static intFormsCenteredCount As Integer
+ Dim boolSubCalledPreviously As Boolean, intIndex As Integer
+
+ ' See if the form has already called this sub
+ ' If not, add to strFormsCentered()
+ boolSubCalledPreviously = False
+ For intIndex = 0 To intFormsCenteredCount - 1
+ If strFormsCentered(intIndex) = frmThisForm.Name Then
+ boolSubCalledPreviously = True
+ Exit For
+ End If
+ Next intIndex
+
+ If Not boolSubCalledPreviously Then
+ ' First time sub called this sub
+ ' Add to strFormsCentered()
+ If intFormsCenteredCount < MAX_RESIZE_FORMS_TO_REMEMBER Then
+ intFormsCenteredCount = intFormsCenteredCount + 1
+ strFormsCentered(intFormsCenteredCount - 1) = frmThisForm.Name
+ Else
+ Debug.Assert False
+ End If
+ End If
+
+ ' If form called previously and boolSizeAndCenterOnlyOncePerProgramSessionis true, then exit sub
+ If boolSizeAndCenterOnlyOncePerProgramSession And boolSubCalledPreviously Then
+ Exit Sub
+ End If
+
+ ' Resize Window
+ With frmThisForm
+ .WindowState = vbNormal
+ If lngWindowWidth > 0 Then .Width = lngWindowWidth
+ If lngWindowHeight > 0 Then .Height = lngWindowHeight
+ End With
+
+ ' Assume the first form loaded is the main form
+ ' May need to be customized if ported to other applications
+ Set frmMainAppForm = Forms(0)
+
+ ' Find the desktop area (width and height)
+ lngWindowAreaWidth = Screen.Width
+ lngWindowAreaHeight = Screen.Height
+
+ ' Check the aspect ratio of WindowAreaWidth / WindowAreaHeight
+ If lngWindowAreaHeight > 0 Then
+ dblAspectRatio = lngWindowAreaWidth / lngWindowAreaHeight
+ Else
+ dblAspectRatio = 1.333
+ End If
+
+ ' Typical desktop areas and aspect ratios
+ ' Normal Desktops have aspect ratios of 1.33 or 1.5
+ ' HDTV desktops have an aspect ratio of 1.6 or 1.7
+ ' Horizontal Dual Monitors have an aspect ratio of 2.66 or 2.5
+ ' Vertical Dual Monitors have an aspectr ratio of 0.67 or 0.62
+
+ ' Determine if using dual monitors
+ If dblAspectRatio < 1 Or dblAspectRatio > 2 Then
+ boolDualMonitor = True
+ If dblAspectRatio > 2 Then
+ ' Aspect ratio greater than 2 - using horizontal dual monitors
+ boolHorizontalDual = True
+ lngWorkingAreaWidth = Screen.Width / 2
+ lngWorkingAreaHeight = Screen.Height
+
+ If frmMainAppForm.Left > lngWorkingAreaWidth Then
+ ' Main app window on second monitor
+ ' Set intDualMonitorToUse if not explicitly set
+ If intDualMonitorToUse < 0 Then
+ intDualMonitorToUse = 1
+ End If
+ End If
+ Else
+ ' Aspect ratio must be less than 1 - using vertical dual monitors
+ boolHorizontalDual = False
+ lngWorkingAreaWidth = Screen.Width
+ lngWorkingAreaHeight = Screen.Height / 2
+
+ If frmMainAppForm.Top > lngWorkingAreaHeight Then
+ ' Main app window on second monitor
+ ' Set intDualMonitorToUse if not explicitly set
+ If intDualMonitorToUse < 0 Then
+ intDualMonitorToUse = 1
+ End If
+ End If
+ End If
+ Else
+ ' Aspect ratio between 1 and 2
+ ' Using a single monitor
+ boolDualMonitor = False
+ lngWorkingAreaWidth = Screen.Width
+ lngWorkingAreaHeight = Screen.Height
+ End If
+
+ With frmThisForm
+ ' Position window
+ Select Case intCenterMode
+ Case cWindowUpperThird
+ lngWindowLeftToSet = (lngWorkingAreaWidth - .Width) \ 2
+ lngWindowTopToSet = (lngWorkingAreaHeight - .Height) \ 3
+ Case cWindowLowerThird
+ lngWindowLeftToSet = (lngWorkingAreaWidth - .Width) \ 2
+ lngWindowTopToSet = (lngWorkingAreaHeight - .Height) * 2 \ 3
+ Case cWindowMiddleLeft
+ lngWindowLeftToSet = 0
+ lngWindowTopToSet = (lngWorkingAreaHeight - .Height) \ 2
+ Case cWindowMiddleRight
+ lngWindowLeftToSet = lngWorkingAreaWidth - .Width
+ lngWindowTopToSet = (lngWorkingAreaHeight - .Height) \ 2
+ Case cWindowTopCenter
+ lngWindowLeftToSet = (lngWorkingAreaWidth - .Width) \ 2
+ lngWindowTopToSet = 0
+ Case cWindowBottomCenter
+ lngWindowLeftToSet = (lngWorkingAreaWidth - .Width) \ 2
+ lngWindowTopToSet = lngWorkingAreaHeight - .Height - 500
+ Case cWindowBottomRight
+ lngWindowLeftToSet = lngWorkingAreaWidth - .Width
+ lngWindowTopToSet = lngWorkingAreaHeight - .Height - 500
+ Case cWindowBottomLeft
+ lngWindowLeftToSet = 0
+ lngWindowTopToSet = lngWorkingAreaHeight - .Height - 500
+ Case cWindowTopRight
+ lngWindowLeftToSet = lngWorkingAreaWidth - .Width
+ lngWindowTopToSet = 0
+ Case cWindowTopLeft
+ lngWindowLeftToSet = 0
+ lngWindowTopToSet = 0
+ Case Else ' Includes cWindowExactCenter = 0
+ lngWindowLeftToSet = (lngWorkingAreaWidth - .Width) \ 2
+ lngWindowTopToSet = (lngWorkingAreaHeight - .Height) \ 2
+ End Select
+
+ ' Move to second monitor if explicitly stated or if the main window is already on the second monitor
+ If boolDualMonitor And intDualMonitorToUse > 0 Then
+ ' Place window on second monitor
+ If boolHorizontalDual Then
+ ' Horizontal dual - Shift to the right
+ lngWindowLeftToSet = lngWindowLeftToSet + lngWorkingAreaWidth
+ Else
+ ' Vertical dual - Shift down
+ lngWindowTopToSet = lngWindowTopToSet + lngWorkingAreaHeight
+ End If
+ End If
+
+ ' Actually position the window
+ .Move lngWindowLeftToSet, lngWindowTopToSet
+ End With
+
+End Sub
+
+Public Function SpacePad(strWork As String, intLength As Integer) As String
+ ' Adds spaces to strWork until the length = intLength
+
+ Do While Len(strWork) < intLength
+ strWork = strWork & " "
+ Loop
+ SpacePad = strWork
+End Function
+
+Public Function SpacePadToFront(strWork As String, intLength As Integer) As String
+ ' Adds spaces to the beginning of strWork until the length = intLength
+
+ Do While Len(strWork) < intLength
+ strWork = " " & strWork
+ Loop
+ SpacePadToFront = strWork
+End Function
+
+Public Function StringToNumber(ByVal strWork As String, Optional ByRef intNumLength As Integer, Optional ByRef intErrorCode As Integer, Optional blnAllowMinusSign As Boolean = False, Optional blnAllowPlusSign As Boolean = False, Optional blnAllowESymbol As Boolean = False, Optional blnMultipleDecimalPointIsError As Boolean = True, Optional ByVal strDecimalPointSymbol As String = ".") As Double
+ ' Looks for a number at the start of strWork and returns it if found
+ ' strWork can contain non-numeric characters after the number; only the number will be returned
+ ' intNumLength returns the length of the number, including the decimal point and any negative sign or E symbol
+ ' When blnAllowESymbol = True, then looks for exponential numbers, like 3.23E+04 or 2.48E-084
+ ' If an error is found or no number is present, then 0 is returned and intNumLength is set to 0, and intErrorCode is assigned the error code:
+ ' 0 = No Error
+ ' -1 = No number
+ ' -3 = No number at all or (more likely) no number after decimal point
+ ' -4 = More than one decimal point
+
+ ' Examples:
+ ' 23Text Returns 23 and intNumLength = 2
+ ' 23.432Text Returns 23.432 and intNumLength = 6
+ ' .3Text Returns 0.3 and intNumLength = 2
+ ' 0.3Text Returns 0.3 and intNumLength = 3
+ ' 3Text Returns 3 and intNumLength = 1
+ ' 3.Text Returns 3 and intNumLength = 2
+ ' Text Returns 0 and intNumLength = 0 and intErrorCode = -3
+ ' .Text Returns 0 and intNumLength = 0 and intErrorCode = -3
+ ' 4.23.Text Returns 0 and intNumLength = 0 and intErrorCode = -4 (must have blnMultipleDecimalPointIsError = True)
+ ' -43Text Returns -43 and intNumLength = 2 (must have blnAllowMinusSign = True)
+ ' 32E+48Text Returns 32E+48 and intNumLength = 6 (must have blnAllowESymbol = True)
+
+ Dim strTestChar As String
+ Dim strFoundNum As String, intIndex As Integer, intDecPtCount As Integer
+ Dim blnNumberFound As Boolean, blnESymbolFound As Boolean
+
+ If strDecimalPointSymbol = "" Then
+ strDecimalPointSymbol = DetermineDecimalPoint()
+ End If
+
+ ' Set intNumLength to -1 for now
+ ' If it doesn't get set to 0 (due to an error), it will get set to the
+ ' length of the matched number before exiting the sub
+ intNumLength = -1
+
+ If Len(strWork) > 0 Then
+ strFoundNum = Left(strWork, 1)
+ If IsNumeric(strFoundNum) Then
+ blnNumberFound = True
+ ElseIf strFoundNum = strDecimalPointSymbol Then
+ blnNumberFound = True
+ intDecPtCount = intDecPtCount + 1
+ ElseIf (strFoundNum = "-" And blnAllowMinusSign) Then
+ blnNumberFound = True
+ ElseIf (strFoundNum = "+" And blnAllowPlusSign) Then
+ blnNumberFound = True
+ End If
+ End If
+
+ If blnNumberFound Then
+ ' Start of string is a number or a decimal point, or (if allowed) a negative or plus sign
+ ' Continue looking
+
+ intIndex = 2
+ Do While intIndex <= Len(strWork)
+ strTestChar = Mid(strWork, intIndex, 1)
+ If IsNumeric(strTestChar) Then
+ strFoundNum = strFoundNum & strTestChar
+ ElseIf strTestChar = strDecimalPointSymbol Then
+ intDecPtCount = intDecPtCount + 1
+ If intDecPtCount = 1 Then
+ strFoundNum = strFoundNum & strTestChar
+ Else
+ Exit Do
+ End If
+ ElseIf (UCase(strTestChar) = "E" And blnAllowESymbol) Then
+ ' E symbol found; only add to strFoundNum if followed by a + and a number,
+ ' a - and a number, or another number
+ strTestChar = Mid(strWork, intIndex + 1, 1)
+ If IsNumeric(strTestChar) Then
+ strFoundNum = strFoundNum & "E" & strTestChar
+ intIndex = intIndex + 2
+ blnESymbolFound = True
+ ElseIf strTestChar = "+" Or strTestChar = "-" Then
+ If IsNumeric(Mid(strWork, intIndex + 2, 1)) Then
+ strFoundNum = strFoundNum & "E" & strTestChar & Mid(strWork, intIndex + 2, 1)
+ intIndex = intIndex + 3
+ blnESymbolFound = True
+ End If
+ End If
+
+ If blnESymbolFound Then
+ ' Continue looking for numbers after the E symbol
+ ' However, only allow pure numbers; not + or - or .
+
+ Do While intIndex <= Len(strWork)
+ strTestChar = Mid(strWork, intIndex, 1)
+ If IsNumeric(strTestChar) Then
+ strFoundNum = strFoundNum & strTestChar
+ ElseIf strTestChar = strDecimalPointSymbol Then
+ If blnMultipleDecimalPointIsError Then
+ ' Set this to 2 to force the multiple decimal point error to appear
+ intDecPtCount = 2
+ End If
+ Exit Do
+ Else
+ Exit Do
+ End If
+ intIndex = intIndex + 1
+ Loop
+ End If
+
+ Exit Do
+ Else
+ Exit Do
+ End If
+ intIndex = intIndex + 1
+ Loop
+
+ If intDecPtCount > 1 And blnMultipleDecimalPointIsError Then
+ ' Too many decimal points
+ intNumLength = 0 ' No number found
+ intErrorCode = -4
+ StringToNumber = 0
+ ElseIf Len(strFoundNum) = 0 Or strFoundNum = strDecimalPointSymbol Then
+ ' No number at all or (more likely) no number after decimal point
+ intNumLength = 0 ' No number found
+ intErrorCode = -3
+ StringToNumber = 0
+ Else
+ ' All is fine
+ intNumLength = Len(strFoundNum)
+ intErrorCode = 0
+ StringToNumber = CDblSafe(strFoundNum)
+ End If
+ Else
+ intNumLength = 0 ' No number found
+ intErrorCode = -1
+ StringToNumber = 0
+ End If
+
+End Function
+
+Public Function StripChrZero(ByRef DataString As String) As String
+ Dim intCharLoc As Integer
+
+ intCharLoc = InStr(DataString, Chr(0))
+ If intCharLoc > 0 Then
+ DataString = Left(DataString, intCharLoc - 1)
+ End If
+ StripChrZero = DataString
+
+End Function
+
+Public Function StripFullPath(ByVal strFilePathIn As String, Optional ByRef strStrippedPath As String) As String
+ ' Removes all path info from strFilePathIn, returning just the filename
+ ' The path of the file is returned in strStrippedPath (including the trailing \)
+
+ Dim fso As New FileSystemObject
+
+ strStrippedPath = fso.GetParentFolderName(strFilePathIn)
+ If Right(strStrippedPath, 1) <> "\" And Right(strStrippedPath, 1) <> "/" Then strStrippedPath = strStrippedPath & "\"
+
+ StripFullPath = fso.GetFileName(strFilePathIn)
+
+ Set fso = Nothing
+
+'' Dim intCharLoc As Integer
+''
+'' intCharLoc = InStrRev(strFilePathIn, "\")
+'' If intCharLoc > 0 Then
+'' strStrippedPath = Left(strFilePathIn, intCharLoc)
+'' StripFullPath = Mid(strFilePathIn, intCharLoc + 1)
+'' Else
+'' StripFullPath = strFilePathIn
+'' End If
+
+End Function
+
+Private Sub SwapSingle(ByRef FirstValue As Single, ByRef SecondValue As Single)
+ Dim sngTemp As Single
+ sngTemp = FirstValue
+ FirstValue = SecondValue
+ SecondValue = sngTemp
+End Sub
+
+Public Sub SwapValues(ByRef FirstValue As Variant, ByRef SecondValue As Variant)
+ Dim varTemp As Variant
+ varTemp = FirstValue
+ FirstValue = SecondValue
+ SecondValue = varTemp
+End Sub
+
+Public Sub TextBoxKeyPressHandler(txtThisTextBox As TextBox, ByRef KeyAscii As Integer, Optional AllowNumbers As Boolean = True, Optional AllowDecimalPoint As Boolean = False, Optional AllowNegativeSign As Boolean = False, Optional AllowCharacters As Boolean = False, Optional AllowPlusSign As Boolean = False, Optional AllowUnderscore As Boolean = False, Optional AllowDollarSign As Boolean = False, Optional AllowEmailChars As Boolean = False, Optional AllowSpaces As Boolean = False, Optional AllowECharacter As Boolean = False, Optional boolAllowCutCopyPaste As Boolean = True)
+ ' Note that the AllowECharacter option has been added to allow the
+ ' user to type numbers in scientific notation
+
+ ' Checks KeyAscii to see if it's valid
+ ' If it isn't, it is set to 0
+
+ Select Case KeyAscii
+ Case 1
+ ' Ctrl+A -- Highlight entire text box
+ txtThisTextBox.SelStart = 0
+ txtThisTextBox.SelLength = Len(txtThisTextBox.Text)
+ KeyAscii = 0
+ Case 24, 3, 22
+ ' Cut, copy, paste, or delete was pressed; let the command occur
+ If Not boolAllowCutCopyPaste Then KeyAscii = 0
+ Case 26
+ ' Ctrl+Z = Undo
+ KeyAscii = 0
+ txtThisTextBox.Text = mTextBoxValueSaved
+ Case 8
+ ' Backspace is allowed
+ Case 48 To 57: If Not AllowNumbers Then KeyAscii = 0
+ Case 32: If Not AllowSpaces Then KeyAscii = 0
+ Case 36: If Not AllowDollarSign Then KeyAscii = 0
+ Case 43: If Not AllowPlusSign Then KeyAscii = 0
+ Case 45: If Not AllowNegativeSign Then KeyAscii = 0
+ Case 44, 46:
+ Select Case glbDecimalSeparator
+ Case ","
+ If KeyAscii = 46 Then KeyAscii = 0
+ Case Else ' includes "."
+ If KeyAscii = 44 Then KeyAscii = 0
+ End Select
+ If Not AllowDecimalPoint Then KeyAscii = 0
+ Case 64: If Not AllowEmailChars Then KeyAscii = 0
+ Case 65 To 90, 97 To 122
+ If Not AllowCharacters Then
+ If Not AllowECharacter Then
+ KeyAscii = 0
+ Else
+ If KeyAscii = 69 Or KeyAscii = 101 Then
+ KeyAscii = 69
+ Else
+ KeyAscii = 0
+ End If
+ End If
+ End If
+ Case 95: If Not AllowUnderscore Then KeyAscii = 0
+ Case Else
+ KeyAscii = 0
+ End Select
+
+End Sub
+
+Public Sub TextBoxGotFocusHandler(txtThisTextBox As VB.TextBox, Optional blnSelectAll As Boolean = True)
+ ' Selects the text in the given textbox if blnSelectAll = true
+ ' Stores the current textbox value in mTextBoxValueSaved
+
+ If blnSelectAll Then
+ txtThisTextBox.SelStart = 0
+ txtThisTextBox.SelLength = Len(txtThisTextBox.Text)
+ End If
+
+ SetMostRecentTextBoxValue txtThisTextBox.Text
+End Sub
+
+Public Function TrimFileName(strFilePath As String) As String
+ ' Examines strFilePath, looking from the right for a \
+ ' If found, returns only the portion after \
+ ' Otherwise, returns the enter string
+ Dim lngLastSlashLoc As Long
+ Dim strTrimmedPath As String
+
+ lngLastSlashLoc = InStrRev(strFilePath, "\")
+
+ If lngLastSlashLoc > 0 Then
+ strTrimmedPath = Mid(strFilePath, lngLastSlashLoc + 1)
+ Else
+ strTrimmedPath = strFilePath
+ End If
+
+ TrimFileName = strTrimmedPath
+End Function
+
+Public Sub UnloadAllForms(strCallingFormName As String)
+
+ Dim frmThisForm As VB.Form
+ ' Unload all the other forms
+ For Each frmThisForm In Forms
+ If frmThisForm.Name <> strCallingFormName Then
+ Unload frmThisForm
+ End If
+ Next
+
+ ' If all the other forms did not unload, then the following will be false and
+ ' the program will break. Force the application to end.
+ Debug.Assert Forms.Count = 1
+ If Forms.Count > 1 Then
+ 'End
+ End If
+
+End Sub
+
+Public Function ValidateDualTextBoxes(txtFirstTextBox As TextBox, txtSecondTextBox As TextBox, boolFavorFirstTextBox As Boolean, dblLowerBound As Double, dblUpperBound As Double, Optional dblDefaultSeparationAmount As Double = 1) As Boolean
+
+ ' Makes sure txtFirstTextBox is less than or equal to txtSecondTextBox
+ ' Returns True if all is OK; returns False if one of the textboxes had to be corrected
+
+ Dim blnTextboxUpdated As Boolean
+
+ If dblUpperBound > 0 Then
+ If boolFavorFirstTextBox Then
+ If Val(txtFirstTextBox) > Val(txtSecondTextBox) Then
+ txtSecondTextBox = CStr(Val(txtFirstTextBox) + dblDefaultSeparationAmount)
+ blnTextboxUpdated = True
+ End If
+ Else
+ If Val(txtFirstTextBox) > Val(txtSecondTextBox) Then
+ txtFirstTextBox = CStr(Val(txtSecondTextBox) - dblDefaultSeparationAmount)
+ blnTextboxUpdated = True
+ End If
+ End If
+
+ If Val(txtSecondTextBox) > dblUpperBound Then
+ txtSecondTextBox = Format(dblUpperBound, "0.00")
+ blnTextboxUpdated = True
+ End If
+ If Val(txtFirstTextBox) < dblLowerBound Then
+ txtFirstTextBox = Format(dblLowerBound, "0.00")
+ blnTextboxUpdated = True
+ End If
+
+ If boolFavorFirstTextBox Then
+ blnTextboxUpdated = Not ValidateDualTextBoxes(txtFirstTextBox, txtSecondTextBox, False, dblLowerBound, dblUpperBound)
+ End If
+ End If
+
+ ValidateDualTextBoxes = Not blnTextboxUpdated
+
+End Function
+
+Public Function ValidateTextboxValueLng(txtThisTextControl As TextBox, lngMinimumVal As Long, lngMaximumVal As Long, lngdefaultVal As Long) As Long
+ If Val(txtThisTextControl) < lngMinimumVal Or Val(txtThisTextControl) > lngMaximumVal Or Not IsNumeric(txtThisTextControl) Then
+ txtThisTextControl = Trim(Str(lngdefaultVal))
+ End If
+ ValidateTextboxValueLng = Val(txtThisTextControl)
+End Function
+
+Public Function ValidateTextboxValueDbl(txtThisTextControl As TextBox, dblMinimumVal As Double, dblMaximumVal As Double, dbldefaultVal As Double) As Double
+ If Val(txtThisTextControl) < dblMinimumVal Or Val(txtThisTextControl) > dblMaximumVal Or Not IsNumeric(txtThisTextControl) Then
+ txtThisTextControl = Trim(Str(dbldefaultVal))
+ End If
+ ValidateTextboxValueDbl = Val(txtThisTextControl)
+End Function
+
+Public Function ValidateValueDbl(ByRef dblThisValue As Double, dblMinimumVal As Double, dblMaximumVal As Double, dbldefaultVal As Double) As Double
+ If dblThisValue < dblMinimumVal Or dblThisValue > dblMaximumVal Then
+ dblThisValue = dbldefaultVal
+ End If
+
+ ValidateValueDbl = dblThisValue
+End Function
+
+Public Function ValidateValueLng(ByRef lngThisValue As Long, lngMinimumVal As Long, lngMaximumVal As Long, lngdefaultVal As Long) As Long
+ If lngThisValue < lngMinimumVal Or lngThisValue > lngMaximumVal Then
+ lngThisValue = lngdefaultVal
+ End If
+
+ ValidateValueLng = lngThisValue
+End Function
+
+Private Function VerifySort(sngArray() As Single, lngLowIndex As Long, lngHighIndex As Long) As Boolean
+ Dim blnInOrder As Boolean
+ Dim lngIndex As Long
+
+ blnInOrder = True
+
+ For lngIndex = lngLowIndex To lngHighIndex - 1
+ If sngArray(lngIndex) > sngArray(lngIndex + 1) Then
+ blnInOrder = False
+ Exit For
+ End If
+ Next lngIndex
+
+ VerifySort = blnInOrder
+End Function
+
+Public Sub VerifyValidWindowPos(frmThisForm As VB.Form, Optional lngMinWidth As Long = 500, Optional lngMinHeight As Long = 500, Optional MinVisibleFormArea As Long = 500)
+ ' Make sure the window isn't too small and is visible on the desktop
+
+ Dim lngReturn As Long
+ Dim lngScreenWidth As Long, lngScreenHeight As Long
+
+ lngReturn = GetDesktopSize(lngScreenHeight, lngScreenWidth, True)
+
+ If lngScreenHeight < Screen.Height Then lngScreenHeight = Screen.Height
+ If lngScreenWidth < Screen.Width Then lngScreenWidth = Screen.Width
+
+ On Error GoTo VerifyValidWindowPosErrorHandler
+ With frmThisForm
+ If .WindowState = vbMinimized Then
+ .WindowState = vbNormal
+ End If
+
+ If .Width < lngMinWidth Then .Width = lngMinWidth
+ If .Height < lngMinHeight Then .Height = lngMinHeight
+
+ If .Left > lngScreenWidth - MinVisibleFormArea Or _
+ .Top > lngScreenHeight - MinVisibleFormArea Or _
+ .Left < 0 Or .Top < 0 Then
+ SizeAndCenterWindow frmThisForm, cWindowUpperThird, .Width, .Height, False
+ End If
+ End With
+
+ Exit Sub
+
+VerifyValidWindowPosErrorHandler:
+ ' An error occured
+ ' The form is probably minimized; we'll ignore it
+ Debug.Print "Error occured in VerifyValidWindowPos: " & Err.Description
+
+End Sub
+
+Public Sub WindowStayOnTop(hwnd As Long, boolStayOnTop As Boolean, Optional lngFormPosLeft As Long = 0, Optional lngFormPosTop As Long = 0, Optional lngFormPosWidth As Long = 600, Optional lngFormPosHeight As Long = 500)
+ ' Toggles the behavior of the given window to "stay on top" of all other windows
+ ' The new form sizes (lngFormPosLeft, lngFormPosTop, lngFormPosWidth, lngFormPosHeight)
+ ' are in pixels
+
+ Dim lngTopMostSwitch As Long
+
+ If boolStayOnTop Then
+ ' Turn on the TopMost attribute.
+ lngTopMostSwitch = conHwndTopmost
+ Else
+ ' Turn off the TopMost attribute.
+ lngTopMostSwitch = conHwndNoTopmost
+ End If
+
+ SetWindowPos hwnd, lngTopMostSwitch, lngFormPosLeft, lngFormPosTop, lngFormPosWidth, lngFormPosHeight, conSwpNoActivate Or conSwpShowWindow
+End Sub
+
+Public Function YesNoBox(strMessage As String, strTitle As String) As VbMsgBoxResult
+ ' Displays a Message Box with OK/Cancel buttons (i.e. yes/no)
+ ' uses vbDefaultButton2 to make sure No or Cancel is the default button
+
+ Dim DialogType As Integer
+
+ ' The dialog box should have Yes and No buttons,
+ ' and a question icon.
+ DialogType = vbYesNo + vbQuestion + vbDefaultButton2
+
+ ' Display the dialog box and get user's response.
+ YesNoBox = MsgBox(strMessage, DialogType, strTitle)
+End Function
+
diff --git a/MwtWinDll/WorkingRoutines.bas b/MwtWinDll/WorkingRoutines.bas
new file mode 100644
index 0000000..6875df2
--- /dev/null
+++ b/MwtWinDll/WorkingRoutines.bas
@@ -0,0 +1,4666 @@
+Attribute VB_Name = "ElementAndMassRoutines"
+Option Explicit
+
+' Last Modified: November 22, 2003
+
+Public Const ELEMENT_COUNT = 103
+Public Const MAX_ABBREV_COUNT = 500
+
+Private Const MESSAGE_STATEMENT_DIMCOUNT = 1600
+Private Const MAX_ABBREV_LENGTH = 6
+Private Const MAX_ISOTOPES = 11
+Private Const MAX_CAUTION_STATEMENTS = 100
+
+Private Const EMPTY_STRINGCHAR As String = "~"
+Private Const RTF_HEIGHT_ADJUSTCHAR As String = "~" ' A hidden character to adjust the height of Rtf Text Boxes when using superscripts
+Private Const LowestValueForDoubleDataType = -1.79E+308 ' Use -3.4E+38 for Single
+Private Const HighestValueForDoubleDataType = 1.79E+308 ' Use 3.4E+38 for Single
+
+' Note that these Enums are duplicated in MolecularWeightCalculator.cls as Public versions
+Public Enum emElementModeConstantsPrivate
+ emAverageMass = 1
+ emIsotopicMass = 2
+ emIntegerMass = 3
+End Enum
+
+Public Enum smStdDevModeConstantsPrivate
+ smShort = 0
+ smScientific = 1
+ smDecimal = 2
+End Enum
+
+Public Enum ccCaseConversionConstantsPrivate
+ ccConvertCaseUp = 0
+ ccExactCase = 1
+ ccSmartCase = 2
+End Enum
+
+Private Enum smtSymbolMatchTypeConstants
+ smtUnknown = 0
+ smtElement = 1
+ smtAbbreviation = 2
+End Enum
+
+Public Type udtOptionsType
+ AbbrevRecognitionMode As arAbbrevRecognitionModeConstants
+ BracketsAsParentheses As Boolean
+ CaseConversion As ccCaseConversionConstantsPrivate
+ DecimalSeparator As String
+ RtfFontName As String
+ RtfFontSize As Integer
+ StdDevMode As smStdDevModeConstantsPrivate ' Can be 0, 1, or 2 (see smStdDevModeConstants)
+End Type
+
+Public Type usrIsotopicAtomInfoType
+ Count As Double ' Can have non-integer counts of atoms, eg. ^13C5.5
+ Mass As Double
+End Type
+
+Public Type udtElementUseStatsType
+ Used As Boolean
+ Count As Double ' Can have non-integer counts of atoms, eg. C5.5
+ IsotopicCorrection As Double
+ IsotopeCount As Integer ' Number of specific isotopes defined
+ Isotopes() As usrIsotopicAtomInfoType
+End Type
+
+Public Type udtPctCompType
+ PercentComposition As Double
+ StdDeviation As Double
+End Type
+
+Public Type udtComputationStatsType
+ Elements(ELEMENT_COUNT) As udtElementUseStatsType ' 1-based array
+ TotalMass As Double
+ PercentCompositions(ELEMENT_COUNT) As udtPctCompType
+ Charge As Single
+ StandardDeviation As Double
+End Type
+
+Public Type udtIsotopeInfoType
+ Mass As Double
+ Abundance As Single
+End Type
+
+Public Type udtElementStatsType
+ Symbol As String
+ Mass As Double
+ Uncertainty As Double
+ Charge As Single
+ IsotopeCount As Integer ' # of isotopes an element has
+ Isotopes(MAX_ISOTOPES) As udtIsotopeInfoType ' Masses and Abundances of the isotopes; 1-based array
+End Type
+
+Public Type udtAbbrevStatsType
+ Symbol As String ' The symbol for the abbreviation, e.g. Ph for the phenyl group or Ala for alanine (3 letter codes for amino acids)
+ Formula As String ' Cannot contain other abbreviations
+ Mass As Double ' Computed mass for quick reference
+ Charge As Single
+ IsAminoAcid As Boolean ' True if an amino acid
+ OneLetterSymbol As String ' Only used for amino acids
+ Comment As String ' Description of the abbreviation
+ InvalidSymbolOrFormula As Boolean
+End Type
+
+Private Type udtErrorDescriptionType
+ ErrorID As Long ' Contains the error number (used in the LookupMessage function). In addition, if a program error occurs, ErrorParams.ErrorID = -10
+ ErrorPosition As Integer
+ ErrorCharacter As String
+End Type
+
+Private Type udtIsoResultsByElementType
+ ElementIndex As Integer ' Index of element in ElementStats() array; look in ElementStats() to get information on its isotopes
+ boolExplicitIsotope As Boolean ' True if an explicitly defined isotope
+ ExplicitMass As Double
+ AtomCount As Long ' Number of atoms of this element in the formula being parsed
+ ResultsCount As Long ' Number of masses in MassAbundances
+ StartingResultsMass As Long ' Starting mass of the results for this element
+ MassAbundances() As Single ' Abundance of each mass, starting with StartingResultsMass
+End Type
+
+Private Type udtIsoResultsOverallType
+ Abundance As Single
+ Multiplicity As Long
+End Type
+
+Private Type udtAbbrevSymbolStackType
+ Count As Integer
+ SymbolReferenceStack() As Integer ' 0-based array
+End Type
+
+Public gComputationOptions As udtOptionsType
+
+Private ElementAlph(ELEMENT_COUNT) As String ' Stores the elements in alphabetical order; used for constructing empirical formulas; 1 to ELEMENT_COUNT
+Private ElementStats(ELEMENT_COUNT) As udtElementStatsType ' 1 to ELEMENT_COUNT
+
+' No number for array size since I dynamically allocate memory for it
+Private MasterSymbolsList() As String ' Stores the element symbols, abbreviations, & amino acids in order of longest symbol length to shortest length, non-alphabatized, for use in symbol matching when parsing a formula; 1 To MasterSymbolsListcount
+Private MasterSymbolsListCount As Integer
+
+Private AbbrevStats(MAX_ABBREV_COUNT) As udtAbbrevStatsType ' Includes both abbreviations and amino acids; 1-based array
+Private AbbrevAllCount As Integer
+
+Private CautionStatements(MAX_CAUTION_STATEMENTS, 2) As String ' CautionStatements(x,0) holds the symbol combo to look for, CautionStatements(x, 1) holds the caution statement; 1-based array
+Private CautionStatementCount As Long
+
+Private MessageStatements(MESSAGE_STATEMENT_DIMCOUNT) As String ' Holds error messages; 1-based array
+Private MessageStatmentCount As Long
+
+Private ErrorParams As udtErrorDescriptionType
+
+Private mChargeCarrierMass As Double ' 1.00727649 for monoisotopic mass or 1.00739 for average mass
+
+Private mCurrentElementMode As emElementModeConstantsPrivate
+Private mStrCautionDescription As String
+Private mComputationStatsSaved As udtComputationStatsType
+
+Private mShowErrorMessageDialogs As Boolean
+
+Private Sub AbbrevSymbolStackAdd(udtAbbrevSymbolStack As udtAbbrevSymbolStackType, SymbolReference As Integer)
+
+On Error GoTo AbbrevSymbolStackAddErrorHandler
+
+ With udtAbbrevSymbolStack
+ .Count = .Count + 1
+ ReDim Preserve .SymbolReferenceStack(.Count - 1)
+ .SymbolReferenceStack(.Count - 1) = SymbolReference
+ End With
+
+ Exit Sub
+
+AbbrevSymbolStackAddErrorHandler:
+ Debug.Assert False
+
+End Sub
+
+Private Sub AbbrevSymbolStackAddRemoveMostRecent(udtAbbrevSymbolStack As udtAbbrevSymbolStackType)
+ With udtAbbrevSymbolStack
+ If .Count > 0 Then
+ .Count = .Count - 1
+ End If
+ End With
+End Sub
+
+Private Sub AddAbbreviationWork(intAbbrevIndex As Integer, strSymbol As String, strFormula As String, sngCharge As Single, blnIsAminoAcid As Boolean, Optional strOneLetter As String = "", Optional strComment As String = "", Optional blnInvalidSymbolOrFormula As Boolean = False)
+ With AbbrevStats(intAbbrevIndex)
+ .InvalidSymbolOrFormula = blnInvalidSymbolOrFormula
+ .Symbol = strSymbol
+ .Formula = strFormula
+ .Mass = ComputeFormulaWeight(strFormula)
+ If .Mass < 0 Then
+ ' Error occurred computing mass for abbreviation
+ .Mass = 0
+ .InvalidSymbolOrFormula = True
+ End If
+ .Charge = sngCharge
+ .OneLetterSymbol = UCase(strOneLetter)
+ .IsAminoAcid = blnIsAminoAcid
+ .Comment = strComment
+ End With
+End Sub
+
+Private Sub AddToCautionDescription(strTextToAdd As String)
+ If Len(mStrCautionDescription) > 0 Then
+ mStrCautionDescription = mStrCautionDescription
+ End If
+ mStrCautionDescription = mStrCautionDescription & strTextToAdd
+End Sub
+
+Private Sub CheckCaution(strFormulaExcerpt As String)
+ Dim strTest As String
+ Dim strNewCaution As String
+ Dim intIndex As Integer
+
+ For intIndex = 1 To MAX_ABBREV_LENGTH
+ strTest = Left(strFormulaExcerpt, intIndex)
+ strNewCaution = LookupCautionStatement(strTest)
+ If Len(strNewCaution) > 0 Then
+ AddToCautionDescription strNewCaution
+ Exit For
+ End If
+ Next intIndex
+
+End Sub
+
+Private Sub CatchParsenumError(AdjacentNum As Double, numsizing As Integer, curcharacter As Integer, symbollength As Integer)
+
+ If AdjacentNum < 0 And numsizing = 0 Then
+ Select Case AdjacentNum
+ Case -1
+ ' No number, but no error
+ ' That's ok
+ Case -3
+ ' Error: No number after decimal point
+ ErrorParams.ErrorID = 12: ErrorParams.ErrorPosition = curcharacter + symbollength
+ Case -4
+ ' Error: More than one decimal point
+ ErrorParams.ErrorID = 27: ErrorParams.ErrorPosition = curcharacter + symbollength
+ Case Else
+ ' Error: General number error
+ ErrorParams.ErrorID = 14: ErrorParams.ErrorPosition = curcharacter + symbollength
+ End Select
+ End If
+
+End Sub
+
+Private Function CheckElemAndAbbrev(strFormulaExcerpt As String, ByRef SymbolReference As Integer) As smtSymbolMatchTypeConstants
+ ' Returns smtElement if matched an element
+ ' Returns smtAbbreviation if matched an abbreviation or amino acid
+ ' Returns smtUnknown if no match
+
+ ' SymbolReference is the index of the matched element or abbreviation in MasterSymbolsList()
+
+ Dim intIndex As Integer
+ Dim eSymbolMatchType As smtSymbolMatchTypeConstants
+
+ ' MasterSymbolsList() stores the element symbols, abbreviations, & amino acids in order of longest length to
+ ' shortest length, non-alphabatized, for use in symbol matching when parsing a formula
+
+ ' MasterSymbolsList(intIndex,0) contains the symbol to be matched
+ ' MasterSymbolsList(intIndex,1) contains E for element, A for amino acid, or N for normal abbreviation, followed by
+ ' the reference number in the master list
+ ' For example for Carbon, MasterSymbolsList(intIndex,0) = "C" and MasterSymbolsList(intIndex,1) = "E6"
+
+ ' Look for match, stepping directly through MasterSymbolsList()
+ ' List is sorted by reverse length, so can do all at once
+
+ For intIndex = 1 To MasterSymbolsListCount
+ If Len(MasterSymbolsList(intIndex, 0)) > 0 Then
+ If Left(strFormulaExcerpt, Len(MasterSymbolsList(intIndex, 0))) = MasterSymbolsList(intIndex, 0) Then
+ ' Matched a symbol
+ Select Case UCase(Left(MasterSymbolsList(intIndex, 1), 1))
+ Case "E" ' An element
+ eSymbolMatchType = smtElement
+ Case "A" ' An abbreviation or amino acid
+ eSymbolMatchType = smtAbbreviation
+ Case Else
+ ' error
+ eSymbolMatchType = smtUnknown
+ SymbolReference = -1
+ End Select
+ If eSymbolMatchType <> smtUnknown Then
+ SymbolReference = Val(Mid(MasterSymbolsList(intIndex, 1), 2))
+ End If
+ Exit For
+ End If
+ Else
+ Debug.Assert False
+ End If
+ Next intIndex
+
+ CheckElemAndAbbrev = eSymbolMatchType
+
+End Function
+
+Public Function ComputeFormulaWeight(strFormula As String) As Double
+ ' Simply returns the weight of a formula (or abbreviation)
+ ' Returns -1 if an error occurs
+ ' Error information is stored in ErrorParams
+
+ Dim udtComputationStats As udtComputationStatsType
+ Dim dblMass As Double
+
+ dblMass = ParseFormulaPublic(strFormula, udtComputationStats, False)
+
+ If ErrorParams.ErrorID = 0 Then
+ ComputeFormulaWeight = udtComputationStats.TotalMass
+ Else
+ ComputeFormulaWeight = -1
+ End If
+End Function
+
+Public Function TestComputeIsotopicAbundances(ByRef strFormulaIn As String, ByVal intChargeState As Integer)
+
+ Dim strResults As String
+
+ Dim ConvolutedMSData2DOneBased() As Double
+ Dim ConvolutedMSDataCount As Long
+
+ Dim intReturn As Integer
+ Static ProgramInitialized As Boolean
+
+ If Not ProgramInitialized Then
+ MemoryLoadAll emElementModeConstantsPrivate.emIsotopicMass
+ ProgramInitialized = True
+ End If
+
+ intReturn = ComputeIsotopicAbundancesInternal(strFormulaIn, intChargeState, strResults, ConvolutedMSData2DOneBased, ConvolutedMSDataCount)
+
+ Debug.Print strResults
+
+End Function
+
+Public Function ComputeIsotopicAbundancesInternal(ByRef strFormulaIn As String, ByVal intChargeState As Integer, ByRef strResults As String, ByRef ConvolutedMSData2DOneBased() As Double, ByRef ConvolutedMSDataCount As Long, Optional ByVal strHeaderIsotopicAbundances As String = "Isotopic Abundances for", Optional ByVal strHeaderMassToCharge As String = "Mass/Charge", Optional ByVal strHeaderFraction As String = "Fraction", Optional ByVal strHeaderIntensity As String = "Intensity", Optional blnUseFactorials As Boolean = False) As Integer
+ ' Computes the Isotopic Distribution for a formula, returns uncharged mass vlaues if intChargeState=0,
+ ' M+H values if intChargeState=1, and convoluted m/z if intChargeState is > 1
+ ' Updates strFormulaIn to the properly formatted formula
+ ' Returns the results in strResults
+ ' Returns 0 if success, or -1 if an error
+
+ Dim strFormula As String, strModifiedFormula As String
+ Dim dblWorkingFormulaMass As Double
+ Dim dblExactBaseIsoMass As Double, dblMassDefect As Double, dblMaxPercentDifference As Double
+ Dim intElementIndex As Integer, intElementCount As Integer
+ Dim lngMassIndex As Long, lngRowIndex As Long
+ Dim udtComputationStats As udtComputationStatsType
+ Dim dblTemp As Double
+
+ Dim IsoStats() As udtIsoResultsByElementType
+
+ Dim IsotopeCount As Integer, IsotopeStartingMass As Integer, IsotopeEndingMass As Integer
+ Dim MasterElementIndex As Integer, AtomCount As Long, dblCount As Double
+ Dim PredictedCombos As Long, CombosFound As Long
+ Dim ComboIndex As Long, IsotopeIndex As Integer, intIndex As Integer
+ Dim IndexToStoreAbundance As Long
+ Dim dblThisComboFractionalAbundance As Double, dblNextComboFractionalAbundance As Double
+ Dim blnRatioMethodUsed As Boolean, blnRigorousMethodUsed As Boolean
+
+ Const strDeuteriumEquiv = "^2.014H"
+ Dim blnReplaceDeuterium As Boolean, intAsciiOfNext As Integer
+
+ Dim IsotopeCountInThisCombo As Long
+ Dim strOutput As String
+
+ Dim blnShowProgressForm As Boolean
+ Dim PredictedConvIterations As Long
+ Dim PredictedTotalComboCalcs As Long, CompletedComboCalcs As Long
+ Const COMBO_ITERATIONS_SHOW_PROGRESS = 500
+ Const MIN_ABUNDANCE_TO_KEEP = 0.000001
+ Const CUTOFF_FOR_RATIO_METHOD = 0.00001
+
+ ' AbundDenom and AbundSuffix are only needed if using the easily-overflowed factorial method
+ Dim AbundDenom As Double, AbundSuffix As Double
+
+ Dim AtomTrackHistory() As Long
+
+ Dim IsoCombos() As Long ' 2D array: Holds the # of each isotope for each combination
+ ' For example, Two chlorines, Cl2, has at most 6 combos since Cl isotopes are 35, 36, and 37
+ ' m1 m2 m3
+ ' 2 0 0
+ ' 1 1 0
+ ' 1 0 1
+ ' 0 2 0
+ ' 0 1 1
+ ' 0 0 2
+
+ Dim ConvolutedAbundances() As udtIsoResultsOverallType ' Fractional abundance at each mass; 1-based array
+ Dim ConvolutedAbundanceStartMass As Long
+
+ Dim MinWeight As Long, MaxWeight As Long, ResultingMassCountForElement As Long
+ Dim blnExplicitIsotopesPresent As Boolean, ExplicitIsotopeCount As Integer
+
+ Dim SubIndex As Long, lngSigma As Long
+ Dim dblLogSigma As Double, dblSumI As Double, dblSumF As Double
+ Dim dblWorkingSum As Double
+ Dim dblLogFreq As Double
+
+ Dim dblFractionalAbundanceSaved As Double, dblLogRho As Double, dblRho As Double
+ Dim lngM As Double, lngMPrime As Double
+ Dim dblRatioOfFreqs As Double
+
+ ' Make sure formula is not blank
+ If Len(strFormulaIn) = 0 Then
+ ComputeIsotopicAbundancesInternal = -1
+ Exit Function
+ End If
+
+ On Error GoTo IsoAbundanceErrorHandler
+
+ ' Change strHeaderMassToCharge to "Neutral Mass" if intChargeState = 0 and strHeaderMassToCharge is "Mass/Charge"
+ If intChargeState = 0 Then
+ If strHeaderMassToCharge = "Mass/Charge" Then
+ strHeaderMassToCharge = "Neutral Mass"
+ End If
+ End If
+
+ ' Parse Formula to determine if valid and number of each element
+ strFormula = strFormulaIn
+ dblWorkingFormulaMass = ParseFormulaPublic(strFormula, udtComputationStats, False)
+
+ If dblWorkingFormulaMass < 0 Then
+ ' Error occurred; information is stored in ErrorParams
+ ComputeIsotopicAbundancesInternal = -1
+ strResults = LookupMessage(350) & ": " & LookupMessage(ErrorParams.ErrorID)
+ Exit Function
+ End If
+
+ ' See if Deuterium is present by looking for a fractional amount of Hydrogen
+ ' strFormula will contain a capital D followed by a number or another letter (or the end of formula)
+ ' If found, replace each D with ^2.014H and re-compute
+ dblCount = udtComputationStats.Elements(1).Count
+ If dblCount <> CLng(dblCount) Then
+ ' Deuterium is present
+ strModifiedFormula = ""
+ intIndex = 1
+ Do While intIndex <= Len(strFormula)
+ blnReplaceDeuterium = False
+ If Mid(strFormula, intIndex, 1) = "D" Then
+ If intIndex = Len(strFormula) Then
+ blnReplaceDeuterium = True
+ Else
+ intAsciiOfNext = Asc(Mid(strFormula, intIndex + 1, 1))
+ If intAsciiOfNext < 97 Or intAsciiOfNext > 122 Then
+ blnReplaceDeuterium = True
+ End If
+ End If
+ If blnReplaceDeuterium Then
+ If intIndex > 1 Then
+ strModifiedFormula = Left(strFormula, intIndex - 1)
+ End If
+ strModifiedFormula = strModifiedFormula & strDeuteriumEquiv
+ If intIndex < Len(strFormula) Then
+ strModifiedFormula = strModifiedFormula & Mid(strFormula, intIndex + 1)
+ End If
+ strFormula = strModifiedFormula
+ intIndex = 0
+ End If
+ End If
+ intIndex = intIndex + 1
+ Loop
+
+ ' Re-Parse Formula since D's are now ^2.014H
+ dblWorkingFormulaMass = ParseFormulaPublic(strFormula, udtComputationStats, False)
+
+ If dblWorkingFormulaMass < 0 Then
+ ' Error occurred; information is stored in ErrorParams
+ ComputeIsotopicAbundancesInternal = -1
+ strResults = LookupMessage(350) & ": " & LookupMessage(ErrorParams.ErrorID)
+ Exit Function
+ End If
+ End If
+
+ ' Make sure there are no fractional atoms present (need to specially handle Deuterium)
+ For intElementIndex = 1 To ELEMENT_COUNT
+ dblCount = udtComputationStats.Elements(intElementIndex).Count
+ If dblCount <> CLng(dblCount) Then
+ ComputeIsotopicAbundancesInternal = -1
+ strResults = LookupMessage(350) & ": " & LookupMessage(805) & ": " & ElementStats(intElementIndex).Symbol & dblCount
+ Exit Function
+ End If
+ Next intElementIndex
+
+ ' Remove occurrences of explicitly defined isotopes from the formula
+ For intElementIndex = 1 To ELEMENT_COUNT
+ With udtComputationStats.Elements(intElementIndex)
+ If .IsotopeCount > 0 Then
+ blnExplicitIsotopesPresent = True
+ ExplicitIsotopeCount = ExplicitIsotopeCount + .IsotopeCount
+ For IsotopeIndex = 1 To .IsotopeCount
+ .Count = .Count - .Isotopes(IsotopeIndex).Count
+ Next IsotopeIndex
+ End If
+ End With
+ Next intElementIndex
+
+ ' Determine the number of elements present in strFormula
+ intElementCount = 0
+ For intElementIndex = 1 To ELEMENT_COUNT
+ If udtComputationStats.Elements(intElementIndex).Used Then
+ intElementCount = intElementCount + 1
+ End If
+ Next intElementIndex
+
+ If blnExplicitIsotopesPresent Then
+ intElementCount = intElementCount + ExplicitIsotopeCount
+ End If
+
+ If intElementCount = 0 Or dblWorkingFormulaMass = 0 Then
+ ' No elements or no weight
+ ComputeIsotopicAbundancesInternal = -1
+ Exit Function
+ End If
+
+ ' The formula seems valid, so update strFormulaIn
+ strFormulaIn = strFormula
+
+ ' Reserve memory for IsoStats() array
+ ReDim IsoStats(intElementCount)
+
+ ' Step through udtComputationStats.Elements() again and copy info into IsoStats()
+ ' In addition, determine minimum and maximum weight for the molecule
+ intElementCount = 0
+ MinWeight = 0
+ MaxWeight = 0
+ For intElementIndex = 1 To ELEMENT_COUNT
+ If udtComputationStats.Elements(intElementIndex).Used Then
+ If udtComputationStats.Elements(intElementIndex).Count > 0 Then
+ intElementCount = intElementCount + 1
+ IsoStats(intElementCount).ElementIndex = intElementIndex
+ IsoStats(intElementCount).AtomCount = udtComputationStats.Elements(intElementIndex).Count ' Note: Ignoring .Elements(intElementIndex).IsotopicCorrection
+ IsoStats(intElementCount).ExplicitMass = ElementStats(intElementIndex).Mass
+
+ With ElementStats(intElementIndex)
+ MinWeight = MinWeight + IsoStats(intElementCount).AtomCount * Round(.Isotopes(1).Mass, 0)
+ MaxWeight = MaxWeight + IsoStats(intElementCount).AtomCount * Round(.Isotopes(.IsotopeCount).Mass, 0)
+ End With
+ End If
+ End If
+ Next intElementIndex
+
+ If blnExplicitIsotopesPresent Then
+ ' Add the isotopes, pretending they are unique elements
+ For intElementIndex = 1 To ELEMENT_COUNT
+ With udtComputationStats.Elements(intElementIndex)
+ If .IsotopeCount > 0 Then
+ For IsotopeIndex = 1 To .IsotopeCount
+ intElementCount = intElementCount + 1
+
+ IsoStats(intElementCount).boolExplicitIsotope = True
+ IsoStats(intElementCount).ElementIndex = intElementIndex
+ IsoStats(intElementCount).AtomCount = .Isotopes(IsotopeIndex).Count
+ IsoStats(intElementCount).ExplicitMass = .Isotopes(IsotopeIndex).Mass
+
+ With IsoStats(intElementCount)
+ MinWeight = MinWeight + .AtomCount * .ExplicitMass
+ MaxWeight = MaxWeight + .AtomCount * .ExplicitMass
+ End With
+
+ Next IsotopeIndex
+ End If
+ End With
+ Next intElementIndex
+ End If
+
+ If MinWeight < 0 Then MinWeight = 0
+
+ ' Create an array to hold the Fractional Abundances for all the masses
+ ConvolutedMSDataCount = MaxWeight - MinWeight + 1
+ ConvolutedAbundanceStartMass = MinWeight
+ ReDim ConvolutedAbundances(ConvolutedMSDataCount)
+
+ ' Predict the total number of computations required; show progress if necessary
+ PredictedTotalComboCalcs = 0
+ For intElementIndex = 1 To intElementCount
+ MasterElementIndex = IsoStats(intElementIndex).ElementIndex
+ AtomCount = IsoStats(intElementIndex).AtomCount
+ IsotopeCount = ElementStats(MasterElementIndex).IsotopeCount
+
+ PredictedCombos = FindCombosPredictIterations(AtomCount, IsotopeCount)
+ PredictedTotalComboCalcs = PredictedTotalComboCalcs + PredictedCombos
+ Next intElementIndex
+
+ If PredictedTotalComboCalcs > COMBO_ITERATIONS_SHOW_PROGRESS Then
+ blnShowProgressForm = True
+ frmProgress.InitializeForm "Finding Isotopic Abundances", 0, PredictedTotalComboCalcs, False
+ frmProgress.UpdateCurrentSubTask "Computing abundances"
+ End If
+
+ ' For each element, compute all of the possible combinations
+ CompletedComboCalcs = 0
+ For intElementIndex = 1 To intElementCount
+
+ MasterElementIndex = IsoStats(intElementIndex).ElementIndex
+ AtomCount = IsoStats(intElementIndex).AtomCount
+
+ If IsoStats(intElementIndex).boolExplicitIsotope Then
+ IsotopeCount = 1
+ IsotopeStartingMass = IsoStats(intElementIndex).ExplicitMass
+ IsotopeEndingMass = IsotopeStartingMass
+ Else
+ With ElementStats(MasterElementIndex)
+ IsotopeCount = .IsotopeCount
+ IsotopeStartingMass = Round(.Isotopes(1).Mass, 0)
+ IsotopeEndingMass = Round(.Isotopes(IsotopeCount).Mass, 0)
+ End With
+ End If
+
+ PredictedCombos = FindCombosPredictIterations(AtomCount, IsotopeCount)
+
+ If PredictedCombos > 10000000 Then
+ MsgBox "Too many combinations necessary for prediction of isotopic distribution: " & Format(PredictedCombos, "#,##0") & vbCrLf & "Please use a simpler formula or reduce the isotopic range defined for the element (currently " & IsotopeCount & ")"
+ ComputeIsotopicAbundancesInternal = -1
+ Exit Function
+ End If
+
+ ReDim IsoCombos(PredictedCombos, IsotopeCount)
+
+ ReDim AtomTrackHistory(IsotopeCount)
+ AtomTrackHistory(1) = AtomCount
+
+ CombosFound = FindCombosRecurse(IsoCombos(), AtomCount, IsotopeCount, IsotopeCount, 1, 1, AtomTrackHistory())
+
+ ' The predicted value should always match the actual value, unless blnExplicitIsotopesPresent = True
+ If Not blnExplicitIsotopesPresent Then
+ Debug.Assert PredictedCombos = CombosFound
+ End If
+
+ ' Reserve space for the abundances based on the minimum and maximum weight of the isotopes of the element
+ MinWeight = AtomCount * IsotopeStartingMass
+ MaxWeight = AtomCount * IsotopeEndingMass
+ ResultingMassCountForElement = MaxWeight - MinWeight + 1
+ IsoStats(intElementIndex).StartingResultsMass = MinWeight
+ IsoStats(intElementIndex).ResultsCount = ResultingMassCountForElement
+ ReDim IsoStats(intElementIndex).MassAbundances(ResultingMassCountForElement)
+
+ If IsoStats(intElementIndex).boolExplicitIsotope Then
+ ' Explicitly defined isotope; there is only one "combo" and its abundance = 1
+ IsoStats(intElementIndex).MassAbundances(1) = 1
+ Else
+ dblFractionalAbundanceSaved = 0
+ For ComboIndex = 1 To CombosFound
+ CompletedComboCalcs = CompletedComboCalcs + 1
+ If blnShowProgressForm Then
+ If CompletedComboCalcs Mod 10 = 0 Then
+ frmProgress.UpdateProgressBar CompletedComboCalcs
+ If KeyPressAbortProcess > 1 Then Exit For
+ End If
+ End If
+
+ dblThisComboFractionalAbundance = -1
+ blnRatioMethodUsed = False
+ blnRigorousMethodUsed = False
+
+ If blnUseFactorials Then
+ ' #######
+ ' Rigorous, slow, easily overflowed method
+ ' #######
+ '
+ blnRigorousMethodUsed = True
+
+ AbundDenom = 1
+ AbundSuffix = 1
+ With ElementStats(MasterElementIndex)
+ For IsotopeIndex = 1 To IsotopeCount
+ IsotopeCountInThisCombo = IsoCombos(ComboIndex, IsotopeIndex)
+ If IsotopeCountInThisCombo > 0 Then
+ AbundDenom = AbundDenom * Factorial(CDbl(IsotopeCountInThisCombo))
+ AbundSuffix = AbundSuffix * .Isotopes(IsotopeIndex).Abundance ^ IsotopeCountInThisCombo
+ End If
+ Next IsotopeIndex
+ End With
+
+ dblThisComboFractionalAbundance = Factorial(CDbl(AtomCount)) / (AbundDenom) * AbundSuffix
+ Else
+ If dblFractionalAbundanceSaved < CUTOFF_FOR_RATIO_METHOD Then
+ ' #######
+ ' Equivalent of rigorous method, but uses logarithms
+ ' #######
+ '
+ blnRigorousMethodUsed = True
+
+ dblLogSigma = 0
+ For lngSigma = 1 To AtomCount
+ dblLogSigma = dblLogSigma + Log(CDbl(lngSigma))
+ Next lngSigma
+
+ dblSumI = 0
+ For IsotopeIndex = 1 To IsotopeCount
+ If IsoCombos(ComboIndex, IsotopeIndex) > 0 Then
+ dblWorkingSum = 0
+ For SubIndex = 1 To IsoCombos(ComboIndex, IsotopeIndex)
+ dblWorkingSum = dblWorkingSum + Log(CDbl(SubIndex))
+ Next SubIndex
+ dblSumI = dblSumI + dblWorkingSum
+ End If
+ Next IsotopeIndex
+
+ With ElementStats(MasterElementIndex)
+ dblSumF = 0
+ For IsotopeIndex = 1 To IsotopeCount
+ If .Isotopes(IsotopeIndex).Abundance > 0 Then
+ dblSumF = dblSumF + IsoCombos(ComboIndex, IsotopeIndex) * Log(CDbl(.Isotopes(IsotopeIndex).Abundance))
+ End If
+ Next IsotopeIndex
+ End With
+
+ dblLogFreq = dblLogSigma - dblSumI + dblSumF
+ dblThisComboFractionalAbundance = Exp(dblLogFreq)
+
+ dblFractionalAbundanceSaved = dblThisComboFractionalAbundance
+ End If
+
+ ' Use dblThisComboFractionalAbundance to predict
+ ' the Fractional Abundance of the Next Combo
+ If ComboIndex < CombosFound And dblFractionalAbundanceSaved >= CUTOFF_FOR_RATIO_METHOD Then
+ ' #######
+ ' Third method, determines the ratio of this combo's abundance and the next combo's abundance
+ ' #######
+ '
+ dblRatioOfFreqs = 1
+
+ For IsotopeIndex = 1 To IsotopeCount
+ lngM = IsoCombos(ComboIndex, IsotopeIndex)
+ lngMPrime = IsoCombos(ComboIndex + 1, IsotopeIndex)
+
+ If lngM > lngMPrime Then
+ dblLogSigma = 0
+ For SubIndex = lngMPrime + 1 To lngM
+ dblLogSigma = dblLogSigma + Log(SubIndex)
+ Next SubIndex
+
+ With ElementStats(MasterElementIndex)
+ dblLogRho = dblLogSigma - (lngM - lngMPrime) * Log(CDbl(.Isotopes(IsotopeIndex).Abundance))
+ End With
+ ElseIf lngM < lngMPrime Then
+ dblLogSigma = 0
+ For SubIndex = lngM + 1 To lngMPrime
+ dblLogSigma = dblLogSigma + Log(SubIndex)
+ Next SubIndex
+
+ With ElementStats(MasterElementIndex)
+ If .Isotopes(IsotopeIndex).Abundance > 0 Then
+ dblLogRho = (lngMPrime - lngM) * Log(CDbl(.Isotopes(IsotopeIndex).Abundance)) - dblLogSigma
+ End If
+ End With
+ Else
+ ' lngM = lngMPrime
+ dblLogRho = 0
+ End If
+
+ dblRho = Exp(dblLogRho)
+ dblRatioOfFreqs = dblRatioOfFreqs * dblRho
+
+ Next IsotopeIndex
+
+ dblNextComboFractionalAbundance = dblFractionalAbundanceSaved * dblRatioOfFreqs
+
+ dblFractionalAbundanceSaved = dblNextComboFractionalAbundance
+ blnRatioMethodUsed = True
+ End If
+ End If
+
+ If blnRigorousMethodUsed Then
+ ' Determine nominal mass of this combination; depends on number of atoms of each isotope
+ IndexToStoreAbundance = FindIndexForNominalMass(IsoCombos(), ComboIndex, IsotopeCount, AtomCount, ElementStats(MasterElementIndex).Isotopes())
+
+ ' Store the abundance in .MassAbundances() at location IndexToStoreAbundance
+ With IsoStats(intElementIndex)
+ .MassAbundances(IndexToStoreAbundance) = .MassAbundances(IndexToStoreAbundance) + dblThisComboFractionalAbundance
+ End With
+ End If
+
+ If blnRatioMethodUsed Then
+ ' Store abundance for next Combo
+ IndexToStoreAbundance = FindIndexForNominalMass(IsoCombos(), ComboIndex + 1, IsotopeCount, AtomCount, ElementStats(MasterElementIndex).Isotopes())
+
+ ' Store the abundance in .MassAbundances() at location IndexToStoreAbundance
+ With IsoStats(intElementIndex)
+ .MassAbundances(IndexToStoreAbundance) = .MassAbundances(IndexToStoreAbundance) + dblNextComboFractionalAbundance
+ End With
+ End If
+
+ If blnRatioMethodUsed And ComboIndex + 1 = CombosFound Then
+ ' No need to compute the last combo since we just did it
+ Exit For
+ End If
+
+ Next ComboIndex
+ End If
+
+ If KeyPressAbortProcess > 1 Then Exit For
+
+ Next intElementIndex
+
+ If KeyPressAbortProcess > 1 Then
+ ' Process Aborted
+ strResults = LookupMessage(940)
+ If blnShowProgressForm Then frmProgress.HideForm
+ ComputeIsotopicAbundancesInternal = -1
+ Exit Function
+ End If
+
+ ' Step Through IsoStats from the end to the beginning, shortening the length to the
+ ' first value greater than MIN_ABUNDANCE_TO_KEEP
+ ' This greatly speeds up the convolution
+ For intElementIndex = 1 To intElementCount
+ With IsoStats(intElementIndex)
+ lngRowIndex = .ResultsCount
+ Do While .MassAbundances(lngRowIndex) < MIN_ABUNDANCE_TO_KEEP
+ lngRowIndex = lngRowIndex - 1
+ If lngRowIndex = 1 Then Exit Do
+ Loop
+ .ResultsCount = lngRowIndex
+ End With
+ Next intElementIndex
+
+ ' Examine IsoStats() to predict the number of ConvolutionIterations
+ PredictedConvIterations = IsoStats(1).ResultsCount
+ For intElementIndex = 2 To intElementCount
+ PredictedConvIterations = PredictedConvIterations * IsoStats(2).ResultsCount
+ Next intElementIndex
+
+ If blnShowProgressForm Then
+ frmProgress.InitializeForm "Finding Isotopic Abundances", 0, IsoStats(1).ResultsCount, False
+ frmProgress.UpdateCurrentSubTask "Convoluting results"
+ End If
+
+ ' Convolute the results for each element using a recursive convolution routine
+ Dim ConvolutionIterations As Long
+ ConvolutionIterations = 0
+ For lngRowIndex = 1 To IsoStats(1).ResultsCount
+ If blnShowProgressForm Then
+ frmProgress.UpdateProgressBar lngRowIndex - 1
+ If KeyPressAbortProcess > 1 Then Exit For
+ End If
+ ConvoluteMasses ConvolutedAbundances(), ConvolutedAbundanceStartMass, lngRowIndex, 1, 0, 1, IsoStats(), intElementCount, ConvolutionIterations
+ Next lngRowIndex
+
+ If KeyPressAbortProcess > 1 Then
+ ' Process Aborted
+ strResults = LookupMessage(940)
+ If blnShowProgressForm Then frmProgress.HideForm
+ ComputeIsotopicAbundancesInternal = -1
+ Exit Function
+ End If
+
+ ' Compute mass defect (difference of initial isotope's mass from integer mass)
+ dblExactBaseIsoMass = 0
+ For intElementIndex = 1 To intElementCount
+ With IsoStats(intElementIndex)
+ If .boolExplicitIsotope Then
+ dblExactBaseIsoMass = dblExactBaseIsoMass + .AtomCount * .ExplicitMass
+ Else
+ dblExactBaseIsoMass = dblExactBaseIsoMass + .AtomCount * ElementStats(.ElementIndex).Isotopes(1).Mass
+ End If
+ End With
+ Next intElementIndex
+
+ dblMassDefect = Round(dblExactBaseIsoMass - ConvolutedAbundanceStartMass, 5)
+
+ ' Assure that the mass defect is only a small percentage of the total mass
+ ' This won't be true for very small compounds so dblTemp is set to at least 10
+ If ConvolutedAbundanceStartMass < 10 Then
+ dblTemp = 10
+ Else
+ dblTemp = ConvolutedAbundanceStartMass
+ End If
+ dblMaxPercentDifference = 10 ^ -(3 - Round(Log10(CDbl(dblTemp)), 0))
+ Debug.Assert Abs(dblMassDefect / dblExactBaseIsoMass) < dblMaxPercentDifference
+
+ ' Step Through ConvolutedAbundances(), starting at the end, and find the first value above MIN_ABUNDANCE_TO_KEEP
+ ' Decrease ConvolutedMSDataCount to remove the extra values below MIN_ABUNDANCE_TO_KEEP
+ For lngMassIndex = ConvolutedMSDataCount To 1 Step -1
+ If ConvolutedAbundances(lngMassIndex).Abundance > MIN_ABUNDANCE_TO_KEEP Then
+ ConvolutedMSDataCount = lngMassIndex
+ Exit For
+ End If
+ Next lngMassIndex
+
+ strOutput = strHeaderIsotopicAbundances & " " & strFormula & vbCrLf
+ strOutput = strOutput & SpacePad(" " & strHeaderMassToCharge, 12) & vbTab & SpacePad(strHeaderFraction, 9) & vbTab & strHeaderIntensity & vbCrLf
+
+ ' Initialize ConvolutedMSData2DOneBased()
+ ReDim ConvolutedMSData2DOneBased(ConvolutedMSDataCount, 2)
+
+ ' Find Maximum Abundance
+ Dim dblMaxAbundance As Double
+ dblMaxAbundance = 0
+ For lngMassIndex = 1 To ConvolutedMSDataCount
+ If ConvolutedAbundances(lngMassIndex).Abundance > dblMaxAbundance Then
+ dblMaxAbundance = ConvolutedAbundances(lngMassIndex).Abundance
+ End If
+ Next lngMassIndex
+
+ ' Populate the results array with the masses and abundances
+ ' Also, if intChargeState is >= 1, then convolute the mass to the appropriate m/z
+ If dblMaxAbundance = 0 Then dblMaxAbundance = 1
+ For lngMassIndex = 1 To ConvolutedMSDataCount
+ With ConvolutedAbundances(lngMassIndex)
+ ConvolutedMSData2DOneBased(lngMassIndex, 0) = (ConvolutedAbundanceStartMass + lngMassIndex - 1) + dblMassDefect
+ ConvolutedMSData2DOneBased(lngMassIndex, 1) = .Abundance / dblMaxAbundance * 100
+
+ If intChargeState >= 1 Then
+ ConvolutedMSData2DOneBased(lngMassIndex, 0) = ConvoluteMassInternal(ConvolutedMSData2DOneBased(lngMassIndex, 0), 0, intChargeState)
+ End If
+ End With
+ Next lngMassIndex
+
+ ' Step through ConvolutedMSData2DOneBased() from the beginning to find the
+ ' first value greater than MIN_ABUNDANCE_TO_KEEP
+ lngRowIndex = 1
+ Do While ConvolutedMSData2DOneBased(lngRowIndex, 1) < MIN_ABUNDANCE_TO_KEEP
+ lngRowIndex = lngRowIndex + 1
+ If lngRowIndex = ConvolutedMSDataCount Then Exit Do
+ Loop
+
+ ' If lngRowIndex > 1 then remove rows from beginning since value is less than MIN_ABUNDANCE_TO_KEEP
+ If lngRowIndex > 1 And lngRowIndex < ConvolutedMSDataCount Then
+ lngRowIndex = lngRowIndex - 1
+ ' Remove rows from the start of ConvolutedMSData2DOneBased() since 0 mass
+ For lngMassIndex = lngRowIndex + 1 To ConvolutedMSDataCount
+ ConvolutedMSData2DOneBased(lngMassIndex - lngRowIndex, 0) = ConvolutedMSData2DOneBased(lngMassIndex, 0)
+ ConvolutedMSData2DOneBased(lngMassIndex - lngRowIndex, 1) = ConvolutedMSData2DOneBased(lngMassIndex, 1)
+ Next lngMassIndex
+ ConvolutedMSDataCount = ConvolutedMSDataCount - lngRowIndex
+ End If
+
+ ' Write to strOutput
+ For lngMassIndex = 1 To ConvolutedMSDataCount
+ strOutput = strOutput & SpacePadFront(Format(ConvolutedMSData2DOneBased(lngMassIndex, 0), "#0.00000"), 12) & vbTab
+ strOutput = strOutput & Format(ConvolutedMSData2DOneBased(lngMassIndex, 1) * dblMaxAbundance / 100, "0.0000000") & vbTab
+ strOutput = strOutput & SpacePadFront(Format(ConvolutedMSData2DOneBased(lngMassIndex, 1), "##0.00"), 7) & vbCrLf
+ ''ToDo: Fix Multiplicity
+ '' strOutput = strOutput & Format(.Multiplicity, "##0") & vbCrLf
+ Next lngMassIndex
+
+ strResults = strOutput
+
+ If blnShowProgressForm Then frmProgress.HideForm
+
+ ComputeIsotopicAbundancesInternal = 0 ' Success
+
+LeaveSub:
+ Exit Function
+
+IsoAbundanceErrorHandler:
+ MwtWinDllErrorHandler "MwtWinDll|ComputeIsotopicAbundances"
+ ErrorParams.ErrorID = 590
+ ErrorParams.ErrorPosition = 0
+ ComputeIsotopicAbundancesInternal = -1
+ Resume LeaveSub
+
+End Function
+
+Public Sub ComputePercentComposition(udtComputationStats As udtComputationStatsType)
+
+ Dim intElementIndex As Integer, dblElementTotalMass As Double
+ Dim dblPercentComp As Double, dblStdDeviation As Double
+
+ With udtComputationStats
+ ' Determine the number of elements in the formula
+
+ For intElementIndex = 1 To ELEMENT_COUNT
+ If .TotalMass > 0 Then
+ dblElementTotalMass = .Elements(intElementIndex).Count * ElementStats(intElementIndex).Mass + _
+ .Elements(intElementIndex).IsotopicCorrection
+
+ ' Percent is the percent composition
+ dblPercentComp = dblElementTotalMass / .TotalMass * 100#
+ .PercentCompositions(intElementIndex).PercentComposition = dblPercentComp
+
+
+ ' Calculate standard deviation
+ If .Elements(intElementIndex).IsotopicCorrection = 0 Then
+ ' No isotopic mass correction factor exists
+ dblStdDeviation = dblPercentComp * Sqr((ElementStats(intElementIndex).Uncertainty / ElementStats(intElementIndex).Mass) ^ 2 + _
+ (.StandardDeviation / .TotalMass) ^ 2)
+ Else
+ ' Isotopic correction factor exists, assume no error in it
+ dblStdDeviation = dblPercentComp * Sqr((.StandardDeviation / .TotalMass) ^ 2)
+ End If
+
+ If dblElementTotalMass = .TotalMass And dblPercentComp = 100 Then
+ dblStdDeviation = 0
+ End If
+
+ .PercentCompositions(intElementIndex).StdDeviation = dblStdDeviation
+ Else
+ .PercentCompositions(intElementIndex).PercentComposition = 0
+ .PercentCompositions(intElementIndex).StdDeviation = 0
+ End If
+ Next intElementIndex
+
+ End With
+
+End Sub
+
+Public Sub ConstructMasterSymbolsList()
+ ' Call after loading or changing abbreviations or elements
+ ' Call after loading or setting abbreviation mode
+
+ ReDim MasterSymbolsList(ELEMENT_COUNT + AbbrevAllCount, 1)
+ Dim intIndex As Integer
+ Dim blnIncludeAmino As Boolean
+
+ ' MasterSymbolsList(,0) contains the symbol to be matched
+ ' MasterSymbolsList(,1) contains E for element, A for amino acid, or N for normal abbreviation, followed by
+ ' the reference number in the master list
+ ' For example for Carbon, MasterSymbolsList(intIndex,0) = "C" and MasterSymbolsList(intIndex,1) = "E6"
+
+ ' Construct search list
+ For intIndex = 1 To ELEMENT_COUNT
+ MasterSymbolsList(intIndex, 0) = ElementStats(intIndex).Symbol
+ MasterSymbolsList(intIndex, 1) = "E" & Trim(Str(intIndex))
+ Next intIndex
+ MasterSymbolsListCount = ELEMENT_COUNT
+
+ ' Note: AbbrevStats is 1-based
+ If gComputationOptions.AbbrevRecognitionMode <> arNoAbbreviations Then
+ If gComputationOptions.AbbrevRecognitionMode = arNormalPlusAminoAcids Then
+ blnIncludeAmino = True
+ Else
+ blnIncludeAmino = False
+ End If
+
+ For intIndex = 1 To AbbrevAllCount
+ With AbbrevStats(intIndex)
+ ' If blnIncludeAmino = False then do not include amino acids
+ If blnIncludeAmino Or (Not blnIncludeAmino And Not .IsAminoAcid) Then
+ ' Do not include if the formula is invalid
+ If Not .InvalidSymbolOrFormula Then
+ MasterSymbolsListCount = MasterSymbolsListCount + 1
+
+ MasterSymbolsList(MasterSymbolsListCount, 0) = .Symbol
+ MasterSymbolsList(MasterSymbolsListCount, 1) = "A" & Trim(Str(intIndex))
+ End If
+ End If
+ End With
+ Next intIndex
+ End If
+
+ ' Sort the search list
+ ShellSortSymbols 1, CLng(MasterSymbolsListCount)
+
+End Sub
+
+Public Function ConvoluteMassInternal(ByVal dblMassMZ As Double, ByVal intCurrentCharge As Integer, Optional ByVal intDesiredCharge As Integer = 1, Optional ByVal dblChargeCarrierMass As Double = 0) As Double
+ ' Converts dblMassMZ to the MZ that would appear at the given intDesiredCharge
+ ' To return the neutral mass, set intDesiredCharge to 0
+
+ ' If dblChargeCarrierMass is 0, then uses mChargeCarrierMass
+
+ Const DEFAULT_CHARGE_CARRIER_MASS_MONOISO = 1.00727649
+
+ Dim dblNewMZ As Double
+
+ If dblChargeCarrierMass = 0 Then dblChargeCarrierMass = mChargeCarrierMass
+ If dblChargeCarrierMass = 0 Then dblChargeCarrierMass = DEFAULT_CHARGE_CARRIER_MASS_MONOISO
+
+ If intCurrentCharge = intDesiredCharge Then
+ dblNewMZ = dblMassMZ
+ Else
+ If intCurrentCharge = 1 Then
+ dblNewMZ = dblMassMZ
+ ElseIf intCurrentCharge > 1 Then
+ ' Convert dblMassMZ to M+H
+ dblNewMZ = (dblMassMZ * intCurrentCharge) - dblChargeCarrierMass * (intCurrentCharge - 1)
+ ElseIf intCurrentCharge = 0 Then
+ ' Convert dblMassMZ (which is neutral) to M+H and store in dblNewMZ
+ dblNewMZ = dblMassMZ + dblChargeCarrierMass
+ Else
+ ' Negative charges are not supported; return 0
+ ConvoluteMassInternal = 0
+ Exit Function
+ End If
+
+ If intDesiredCharge > 1 Then
+ dblNewMZ = (dblNewMZ + dblChargeCarrierMass * (intDesiredCharge - 1)) / intDesiredCharge
+ ElseIf intDesiredCharge = 1 Then
+ ' Return M+H, which is currently stored in dblNewMZ
+ ElseIf intDesiredCharge = 0 Then
+ ' Return the neutral mass
+ dblNewMZ = dblNewMZ - dblChargeCarrierMass
+ Else
+ ' Negative charges are not supported; return 0
+ dblNewMZ = 0
+ End If
+ End If
+
+ ConvoluteMassInternal = dblNewMZ
+
+End Function
+
+' Converts strFormula to its corresponding empirical formula
+Public Function ConvertFormulaToEmpirical(ByVal strFormula As String) As String
+ ' Returns the empirical formula for strFormula
+ ' If an error occurs, returns -1
+
+ Dim dblMass As Double
+ Dim udtComputationStats As udtComputationStatsType
+ Dim strEmpiricalFormula As String
+ Dim intElementIndex As Integer, intElementSearchIndex As Integer
+ Dim intElementIndexToUse As Integer
+ Dim dblThisElementCount As Double
+
+ ' Call ParseFormulaPublic to compute the formula's mass and fill udtComputationStats
+ dblMass = ParseFormulaPublic(strFormula, udtComputationStats)
+
+ If ErrorParams.ErrorID = 0 Then
+ ' Convert to empirical formula
+ strEmpiricalFormula = ""
+ ' Carbon first, then hydrogen, then the rest alphabetically
+ ' This is correct to start at -1
+ For intElementIndex = -1 To ELEMENT_COUNT
+ If intElementIndex = -1 Then
+ ' Do Carbon first
+ intElementIndexToUse = 6
+ ElseIf intElementIndex = 0 Then
+ ' Then do Hydrogen
+ intElementIndexToUse = 1
+ Else
+ ' Then do the rest alphabetically
+ If ElementAlph(intElementIndex) = "C" Or ElementAlph(intElementIndex) = "H" Then
+ ' Increment intElementIndex when we encounter carbon or hydrogen
+ intElementIndex = intElementIndex + 1
+ End If
+ For intElementSearchIndex = 2 To ELEMENT_COUNT ' Start at 2 to since we've already done hydrogen
+ ' find the element in the numerically ordered array that corresponds to the alphabetically ordered array
+ If ElementStats(intElementSearchIndex).Symbol = ElementAlph(intElementIndex) Then
+ intElementIndexToUse = intElementSearchIndex
+ Exit For
+ End If
+ Next intElementSearchIndex
+ End If
+
+ ' Only display the element if it's in the formula
+ With mComputationStatsSaved
+ dblThisElementCount = .Elements(intElementIndexToUse).Count
+ If dblThisElementCount = 1# Then
+ strEmpiricalFormula = strEmpiricalFormula & ElementStats(intElementIndexToUse).Symbol
+ ElseIf dblThisElementCount > 0 Then
+ strEmpiricalFormula = strEmpiricalFormula & ElementStats(intElementIndexToUse).Symbol & Trim(CStr(dblThisElementCount))
+ End If
+ End With
+ Next intElementIndex
+
+ ConvertFormulaToEmpirical = strEmpiricalFormula
+ Else
+ ConvertFormulaToEmpirical = -1
+ End If
+
+End Function
+
+' Expands abbreviations in formula to elemental equivalent
+Public Function ExpandAbbreviationsInFormula(ByVal strFormula As String) As String
+ ' Returns the result
+ ' If an error occurs, returns -1
+
+ Dim dblMass As Double
+ Dim udtComputationStats As udtComputationStatsType
+
+ ' Call ExpandAbbreviationsInFormula to compute the formula's mass
+ dblMass = ParseFormulaPublic(strFormula, udtComputationStats, True)
+
+ If ErrorParams.ErrorID = 0 Then
+ ExpandAbbreviationsInFormula = strFormula
+ Else
+ ExpandAbbreviationsInFormula = -1
+ End If
+
+End Function
+
+Private Function FindIndexForNominalMass(IsoCombos() As Long, ComboIndex As Long, IsotopeCount As Integer, AtomCount As Long, ThisElementsIsotopes() As udtIsotopeInfoType) As Long
+ Dim lngWorkingMass As Long
+ Dim IsotopeIndex As Integer
+
+ lngWorkingMass = 0
+ For IsotopeIndex = 1 To IsotopeCount
+ lngWorkingMass = lngWorkingMass + IsoCombos(ComboIndex, IsotopeIndex) * (Round(ThisElementsIsotopes(IsotopeIndex).Mass, 0))
+ Next IsotopeIndex
+
+' (lngWorkingMass - IsoStats(ElementIndex).StartingResultsMass) + 1
+ FindIndexForNominalMass = (lngWorkingMass - AtomCount * Round(ThisElementsIsotopes(1).Mass, 0)) + 1
+End Function
+
+Private Sub ConvoluteMasses(ByRef ConvolutedAbundances() As udtIsoResultsOverallType, ByRef ConvolutedAbundanceStartMass As Long, ByRef WorkingRow As Long, ByRef WorkingAbundance As Single, ByRef WorkingMassTotal As Long, ByRef ElementTrack As Integer, ByRef IsoStats() As udtIsoResultsByElementType, ByRef ElementCount As Integer, ByRef Iterations As Long)
+ ' Recursive function to Convolute the Results in IsoStats() and store in ConvolutedAbundances(); 1-based array
+
+ Dim IndexToStoreResult As Long, RowIndex As Long
+ Dim NewAbundance As Single, NewMassTotal As Long
+
+ If KeyPressAbortProcess > 1 Then Exit Sub
+
+ Iterations = Iterations + 1
+ If Iterations Mod 10000 = 0 Then
+ DoEvents
+ End If
+
+ NewAbundance = WorkingAbundance * IsoStats(ElementTrack).MassAbundances(WorkingRow)
+ NewMassTotal = WorkingMassTotal + (IsoStats(ElementTrack).StartingResultsMass + WorkingRow - 1)
+
+ If ElementTrack >= ElementCount Then
+ IndexToStoreResult = NewMassTotal - ConvolutedAbundanceStartMass + 1
+ With ConvolutedAbundances(IndexToStoreResult)
+ If NewAbundance > 0 Then
+ .Abundance = .Abundance + NewAbundance
+ .Multiplicity = .Multiplicity + 1
+ End If
+ End With
+ Else
+ For RowIndex = 1 To IsoStats(ElementTrack + 1).ResultsCount
+ ConvoluteMasses ConvolutedAbundances(), ConvolutedAbundanceStartMass, RowIndex, NewAbundance, NewMassTotal, ElementTrack + 1, IsoStats(), ElementCount, Iterations
+ Next RowIndex
+ End If
+End Sub
+
+' Note: This function is unused
+Private Function FindCombinations(Optional AtomCount As Long = 2, Optional IsotopeCount As Integer = 2, Optional boolPrintOutput As Boolean = False) As Long
+ ' Find Combinations of atoms for a given number of atoms and number of potential isotopes
+ ' Can print results to debug window
+
+ Dim ComboResults() As Long
+ Dim AtomTrackHistory() As Long
+ Dim PredictedCombos As Long, CombosFound As Long
+
+ PredictedCombos = FindCombosPredictIterations(AtomCount, IsotopeCount)
+
+ If PredictedCombos > 10000000 Then
+ MsgBox "Too many combinations necessary for prediction of isotopic distribution: " & Format(PredictedCombos, "#,##0") & vbCrLf & "Please use a simpler formula or reduce the isotopic range defined for the element (currently " & IsotopeCount & ")"
+ FindCombinations = -1
+ Exit Function
+ End If
+
+ On Error GoTo FindCombinationsErrorHandler
+
+ ReDim ComboResults(PredictedCombos, IsotopeCount)
+
+ ReDim AtomTrackHistory(IsotopeCount)
+ AtomTrackHistory(1) = AtomCount
+
+ CombosFound = FindCombosRecurse(ComboResults(), AtomCount, IsotopeCount, IsotopeCount, 1, 1, AtomTrackHistory())
+
+ If boolPrintOutput Then
+ Dim RowIndex As Long, ColIndex As Integer
+ Dim strOutput As String, strHeader As String
+
+ strHeader = CombosFound & " combos found for " & AtomCount & " atoms for element with " & IsotopeCount & " isotopes"
+ If CombosFound > 5000 Then
+ strHeader = strHeader & vbCrLf & "Only displaying the first 5000 combinations"
+ End If
+
+ Debug.Print strHeader
+
+ For RowIndex = 1 To CombosFound
+ strOutput = ""
+ For ColIndex = 1 To IsotopeCount
+ strOutput = strOutput & ComboResults(RowIndex, ColIndex) & vbTab
+ Next ColIndex
+ Debug.Print strOutput
+ If RowIndex > 5000 Then Exit For
+ Next RowIndex
+
+ If CombosFound > 50 Then Debug.Print strHeader
+
+ End If
+
+ FindCombinations = CombosFound
+LeaveSub:
+ Exit Function
+
+FindCombinationsErrorHandler:
+ MwtWinDllErrorHandler "MwtWinDll|FindCombinations"
+ ErrorParams.ErrorID = 590
+ ErrorParams.ErrorPosition = 0
+ FindCombinations = -1
+ Resume LeaveSub
+
+End Function
+
+Private Function FindCombosPredictIterations(AtomCount As Long, IsotopeCount As Integer) As Long
+ ' Determines the number of Combo results (iterations) for the given
+ ' number of Atoms for an element with the given number of Isotopes
+
+ ' Empirically determined the following results and figured out that the RunningSum()
+ ' method correctly predicts the results
+
+ ' IsotopeCount AtomCount Total Iterations
+ ' 2 1 2
+ ' 2 2 3
+ ' 2 3 4
+ ' 2 4 5
+ '
+ ' 3 1 3
+ ' 3 2 6
+ ' 3 3 10
+ ' 3 4 15
+ '
+ ' 4 1 4
+ ' 4 2 10
+ ' 4 3 20
+ ' 4 4 35
+ '
+ ' 5 1 5
+ ' 5 2 15
+ ' 5 3 35
+ ' 5 4 70
+ '
+ ' 6 1 6
+ ' 6 2 21
+ ' 6 3 56
+ ' 6 4 126
+
+ Dim IsotopeIndex As Integer, AtomIndex As Long
+ Dim PredictedCombos As Long
+ Dim RunningSum() As Long, PreviousComputedValue As Long
+
+ ReDim RunningSum(AtomCount)
+
+ On Error GoTo PredictCombinationsErrorHandler
+
+ If AtomCount = 1 Or IsotopeCount = 1 Then
+ PredictedCombos = IsotopeCount
+ Else
+ ' Initialize RunningSum()
+ For AtomIndex = 1 To AtomCount
+ RunningSum(AtomIndex) = AtomIndex + 1
+ Next AtomIndex
+
+ For IsotopeIndex = 3 To IsotopeCount
+ PreviousComputedValue = IsotopeIndex
+ For AtomIndex = 2 To AtomCount
+ ' Compute new count for this AtomIndex
+ RunningSum(AtomIndex) = PreviousComputedValue + RunningSum(AtomIndex)
+
+ ' Also place result in RunningSum(AtomIndex)
+ PreviousComputedValue = RunningSum(AtomIndex)
+ Next AtomIndex
+ Next IsotopeIndex
+
+ PredictedCombos = RunningSum(AtomCount)
+ End If
+
+ FindCombosPredictIterations = PredictedCombos
+
+LeaveSub:
+ Exit Function
+
+PredictCombinationsErrorHandler:
+ MwtWinDllErrorHandler "MwtWinDll|FindCombosPredictIterations"
+ ErrorParams.ErrorID = 590
+ ErrorParams.ErrorPosition = 0
+ FindCombosPredictIterations = -1
+ Resume LeaveSub
+
+End Function
+
+Private Function FindCombosRecurse(ByRef ComboResults() As Long, ByRef AtomCount As Long, ByRef MaxIsotopeCount As Integer, CurrentIsotopeCount As Integer, CurrentRow As Long, CurrentCol As Integer, AtomTrackHistory() As Long) As Long
+ ' Recursive function to find all the combinations
+ ' of a number of atoms with the given maximum isotopic count
+
+ ' IsoCombos() is a 2D array holding the # of each isotope for each combination
+ ' For example, Two chlorines, Cl2, has at most 6 combos since Cl isotopes are 35, 36, and 37
+ ' m1 m2 m3
+ ' 2 0 0
+ ' 1 1 0
+ ' 1 0 1
+ ' 0 2 0
+ ' 0 1 1
+ ' 0 0 2
+
+ ' Returns the number of combinations found, or -1 if an error
+
+ Dim ColIndex As Integer
+ Dim AtomTrack As Long
+ Dim intNewColumn As Integer
+
+ If CurrentIsotopeCount = 1 Or AtomCount = 0 Then
+ ' End recursion
+ ComboResults(CurrentRow, CurrentCol) = AtomCount
+ Else
+ AtomTrack = AtomCount
+
+ ' Store AtomTrack value at current position
+ ComboResults(CurrentRow, CurrentCol) = AtomTrack
+
+ Do While AtomTrack > 0
+ CurrentRow = CurrentRow + 1
+
+ ' Went to a new row; if CurrentCol > 1 then need to assign previous values to previous columns
+ If (CurrentCol > 1) Then
+ For ColIndex = 1 To CurrentCol - 1
+ ComboResults(CurrentRow, ColIndex) = AtomTrackHistory(ColIndex)
+ Next ColIndex
+ End If
+
+ AtomTrack = AtomTrack - 1
+ ComboResults(CurrentRow, CurrentCol) = AtomTrack
+
+ If CurrentCol < MaxIsotopeCount Then
+ intNewColumn = CurrentCol + 1
+ AtomTrackHistory(intNewColumn - 1) = AtomTrack
+ FindCombosRecurse ComboResults(), AtomCount - AtomTrack, MaxIsotopeCount, CurrentIsotopeCount - 1, CurrentRow, intNewColumn, AtomTrackHistory
+ Else
+ Debug.Assert "Program bug. This line should not be reached."
+ End If
+ Loop
+
+ ' Reached AtomTrack = 0; end recursion
+ End If
+
+ FindCombosRecurse = CurrentRow
+
+End Function
+
+Public Sub GeneralErrorHandler(strCallingProcedure As String, lngErrorNumber As Long, Optional strErrorDescriptionAddnl As String = "")
+ Dim strMessage As String
+ Dim strErrorFilePath As String
+ Dim intOutFileNum As Integer
+
+ strMessage = "Error in " & strCallingProcedure & ": " & Error(lngErrorNumber) & " (#" & Trim(lngErrorNumber) & ")"
+ If Len(strErrorDescriptionAddnl) > 0 Then strMessage = strMessage & vbCrLf & strErrorDescriptionAddnl
+
+ If mShowErrorMessageDialogs Then
+ MsgBox strMessage, vbExclamation + vbOKOnly, "Error in MwtWinDll"
+ Else
+ Debug.Print strMessage
+ Debug.Assert False
+ End If
+
+ On Error Resume Next
+ strErrorFilePath = App.Path
+ If Right(strErrorFilePath, 1) <> "\" Then strErrorFilePath = strErrorFilePath & "\"
+ strErrorFilePath = strErrorFilePath & "ErrorLog.txt"
+
+ intOutFileNum = FreeFile()
+ Open strErrorFilePath For Append As #intOutFileNum
+
+ Print #intOutFileNum, Now() & " -- " & strMessage & vbCrLf
+ Close #intOutFileNum
+
+End Sub
+
+Public Function GetAbbreviationCountInternal() As Long
+ GetAbbreviationCountInternal = AbbrevAllCount
+End Function
+
+Public Function GetAbbreviationIDInternal(ByVal strSymbol As String, Optional blnAminoAcidsOnly As Boolean = False) As Long
+ ' Returns 0 if not found, the ID if found
+
+ Dim lngIndex As Long
+
+ For lngIndex = 1 To AbbrevAllCount
+ If LCase(AbbrevStats(lngIndex).Symbol) = LCase(strSymbol) Then
+ If Not blnAminoAcidsOnly Or (blnAminoAcidsOnly And AbbrevStats(lngIndex).IsAminoAcid) Then
+ GetAbbreviationIDInternal = lngIndex
+ Exit Function
+ End If
+ End If
+ Next lngIndex
+
+ GetAbbreviationIDInternal = 0
+End Function
+
+Public Function GetAbbreviationInternal(ByVal lngAbbreviationID As Long, ByRef strSymbol As String, ByRef strFormula As String, ByRef sngCharge As Single, ByRef blnIsAminoAcid As Boolean, Optional ByRef strOneLetterSymbol As String, Optional ByRef strComment As String, Optional ByRef blnInvalidSymbolOrFormula As Boolean) As Long
+ ' Returns the contents of AbbrevStats() in the ByRef variables
+ ' Returns 0 if success, 1 if failure
+
+ If lngAbbreviationID >= 1 And lngAbbreviationID <= AbbrevAllCount Then
+ With AbbrevStats(lngAbbreviationID)
+ strSymbol = .Symbol
+ strFormula = .Formula
+ sngCharge = .Charge
+ blnIsAminoAcid = .IsAminoAcid
+ strOneLetterSymbol = .OneLetterSymbol
+ strComment = .Comment
+ blnInvalidSymbolOrFormula = .InvalidSymbolOrFormula
+ End With
+ GetAbbreviationInternal = 0
+ Else
+ GetAbbreviationInternal = 1
+ End If
+
+End Function
+
+Public Function GetAbbreviationMass(ByVal lngAbbreviationID As Long) As Double
+ ' Returns the mass if success, 0 if failure
+ ' Could return -1 if failure, but might mess up some calculations
+
+ ' This function does not recompute the abbreviation mass each time it is called
+ ' Rather, it uses the .Mass member of AbbrevStats
+ ' This requires that .Mass be updated if the abbreviation is changed, if an element is changed, or if the element mode is changed
+
+ If lngAbbreviationID >= 1 And lngAbbreviationID <= AbbrevAllCount Then
+ GetAbbreviationMass = AbbrevStats(lngAbbreviationID).Mass
+ Else
+ GetAbbreviationMass = 0
+ End If
+
+End Function
+
+Public Function GetAminoAcidSymbolConversionInternal(strSymbolToFind As String, bln1LetterTo3Letter As Boolean) As String
+ ' If bln1LetterTo3Letter = True, then converting 1 letter codes to 3 letter codes
+ ' Returns the symbol, if found
+ ' Otherwise, returns ""
+ Dim lngIndex As Long, strReturnSymbol As String, strCompareSymbol As String
+
+ strReturnSymbol = ""
+ ' Use AbbrevStats() array to lookup code
+ For lngIndex = 1 To AbbrevAllCount
+ If AbbrevStats(lngIndex).IsAminoAcid Then
+ If bln1LetterTo3Letter Then
+ strCompareSymbol = AbbrevStats(lngIndex).OneLetterSymbol
+ Else
+ strCompareSymbol = AbbrevStats(lngIndex).Symbol
+ End If
+
+ If LCase(strCompareSymbol) = LCase(strSymbolToFind) Then
+ If bln1LetterTo3Letter Then
+ strReturnSymbol = AbbrevStats(lngIndex).Symbol
+ Else
+ strReturnSymbol = AbbrevStats(lngIndex).OneLetterSymbol
+ End If
+ Exit For
+ End If
+ End If
+ Next lngIndex
+
+ GetAminoAcidSymbolConversionInternal = strReturnSymbol
+
+End Function
+
+Public Function GetCautionStatementCountInternal() As Long
+ GetCautionStatementCountInternal = CautionStatementCount
+End Function
+
+Public Function GetCautionStatementIDInternal(ByVal strSymbolCombo As String) As Long
+ ' Returns -1 if not found, the ID if found
+
+ Dim intIndex As Integer
+
+ For intIndex = 1 To CautionStatementCount
+ If CautionStatements(intIndex, 0) = strSymbolCombo Then
+ GetCautionStatementIDInternal = intIndex
+ Exit Function
+ End If
+ Next intIndex
+
+ GetCautionStatementIDInternal = -1
+End Function
+
+Public Function GetCautionStatementInternal(ByVal lngCautionStatementID As Long, ByRef strSymbolCombo As String, ByRef strCautionStatement As String) As Long
+ ' Returns the contents of CautionStatements() in the ByRef variables
+ ' Returns 0 if success, 1 if failure
+
+ If lngCautionStatementID >= 1 And lngCautionStatementID <= CautionStatementCount Then
+ strSymbolCombo = CautionStatements(lngCautionStatementID, 0)
+ strCautionStatement = CautionStatements(lngCautionStatementID, 1)
+ GetCautionStatementInternal = 0
+ Else
+ GetCautionStatementInternal = 1
+ End If
+End Function
+
+Public Function GetCautionDescription() As String
+ GetCautionDescription = mStrCautionDescription
+End Function
+
+Public Function GetChargeCarrierMassInternal() As Double
+ GetChargeCarrierMassInternal = mChargeCarrierMass
+End Function
+
+Public Function GetElementCountInternal() As Long
+ GetElementCountInternal = ELEMENT_COUNT
+End Function
+
+Public Function GetElementInternal(ByVal intElementID As Integer, ByRef strSymbol As String, ByRef dblMass As Double, ByRef dblUncertainty As Double, ByRef sngCharge As Single, ByRef intIsotopeCount As Integer) As Long
+ ' Returns the contents of ElementStats() in the ByRef variables
+ ' Returns 0 if success, 1 if failure
+
+ If intElementID >= 1 And intElementID <= ELEMENT_COUNT Then
+ strSymbol = ElementAlph(intElementID)
+ With ElementStats(intElementID)
+ strSymbol = .Symbol
+ dblMass = .Mass
+ dblUncertainty = .Uncertainty
+ sngCharge = .Charge
+ intIsotopeCount = .IsotopeCount
+ End With
+ GetElementInternal = 0
+ Else
+ GetElementInternal = 1
+ End If
+
+End Function
+
+Public Function GetElementIDInternal(ByVal strSymbol As String) As Long
+ ' Returns 0 if not found, the ID if found
+ Dim intIndex As Integer
+
+ For intIndex = 1 To ELEMENT_COUNT
+ If LCase(ElementStats(intIndex).Symbol) = LCase(strSymbol) Then
+ GetElementIDInternal = intIndex
+ Exit Function
+ End If
+ Next intIndex
+
+ GetElementIDInternal = 0
+End Function
+
+Public Function GetElementIsotopesInternal(ByVal intElementID As Integer, ByRef intIsotopeCount As Integer, ByRef dblIsotopeMasses() As Double, ByRef sngIsotopeAbundances() As Single) As Long
+ Dim intIsotopeindex As Integer
+
+ If intElementID >= 1 And intElementID <= ELEMENT_COUNT Then
+ With ElementStats(intElementID)
+ intIsotopeCount = .IsotopeCount
+ For intIsotopeindex = 1 To .IsotopeCount
+ dblIsotopeMasses(intIsotopeindex) = .Isotopes(intIsotopeindex).Mass
+ sngIsotopeAbundances(intIsotopeindex) = .Isotopes(intIsotopeindex).Abundance
+ Next intIsotopeindex
+ End With
+ GetElementIsotopesInternal = 0
+ Else
+ GetElementIsotopesInternal = 1
+ End If
+End Function
+
+Public Function GetElementModeInternal() As emElementModeConstantsPrivate
+ GetElementModeInternal = mCurrentElementMode
+End Function
+
+Public Function GetElementSymbolInternal(ByVal intElementID As Integer) As String
+
+ If intElementID >= 1 And intElementID <= ELEMENT_COUNT Then
+ GetElementSymbolInternal = ElementStats(intElementID).Symbol
+ Else
+ GetElementSymbolInternal = ""
+ End If
+
+End Function
+
+Public Function GetElementStatInternal(ByVal intElementID As Integer, ByVal eElementStat As esElementStatsConstants) As Double
+ ' Returns a single bit of information about a single element
+ ' Since a value may be negavite, simply returns 0 if an error
+
+ If intElementID >= 1 And intElementID <= ELEMENT_COUNT Then
+ Select Case eElementStat
+ Case esMass
+ GetElementStatInternal = ElementStats(intElementID).Mass
+ Case esCharge
+ GetElementStatInternal = ElementStats(intElementID).Charge
+ Case esUncertainty
+ GetElementStatInternal = ElementStats(intElementID).Uncertainty
+ Case Else
+ GetElementStatInternal = 0
+ End Select
+ Else
+ GetElementStatInternal = 0
+ End If
+
+End Function
+
+Public Function GetErrorDescription() As String
+ If ErrorParams.ErrorID <> 0 Then
+ GetErrorDescription = LookupMessage(ErrorParams.ErrorID)
+ Else
+ GetErrorDescription = ""
+ End If
+End Function
+
+Public Function GetErrorID() As Long
+ GetErrorID = ErrorParams.ErrorID
+End Function
+
+Public Function GetErrorCharacter() As String
+ GetErrorCharacter = ErrorParams.ErrorCharacter
+End Function
+
+Public Function GetErrorPosition() As Long
+ GetErrorPosition = ErrorParams.ErrorPosition
+End Function
+
+Public Function GetMessageStatementCountInternal() As Long
+ GetMessageStatementCountInternal = MessageStatmentCount
+End Function
+
+Public Function GetMessageStatementInternal(lngMessageID As Long, Optional strAppendText As String = "") As String
+' GetMessageStringInternal simply returns the message for lngMessageID
+' LookupMessage formats the message, and possibly combines multiple messages, depending on the message number
+ Dim strMessage As String
+
+ If lngMessageID > 0 And lngMessageID <= MessageStatmentCount Then
+ strMessage = MessageStatements(lngMessageID)
+
+ ' Append Prefix to certain strings
+ Select Case lngMessageID
+ ' Add Error: to the front of certain error codes
+ Case 1 To 99, 120, 130, 140, 260, 270, 300
+ strMessage = GetMessageStatementInternal(350) & ": " & strMessage
+ End Select
+
+ ' Now append strAppendText
+ GetMessageStatementInternal = strMessage & strAppendText
+ Else
+ GetMessageStatementInternal = ""
+ End If
+End Function
+
+Private Function IsPresentInAbbrevSymbolStack(udtAbbrevSymbolStack As udtAbbrevSymbolStackType, SymbolReference As Integer) As Boolean
+ ' Checks for presence of SymbolReference in udtAbbrevSymbolStack
+ ' If found, returns true
+
+ Dim intIndex As Integer
+ Dim blnFound As Boolean
+
+On Error GoTo IsPresentInAbbrevSymbolStackErrorHandler
+
+ With udtAbbrevSymbolStack
+ blnFound = False
+ For intIndex = 0 To .Count - 1
+ If .SymbolReferenceStack(intIndex) = SymbolReference Then
+ blnFound = True
+ Exit For
+ End If
+ Next intIndex
+ End With
+
+ IsPresentInAbbrevSymbolStack = blnFound
+ Exit Function
+
+IsPresentInAbbrevSymbolStackErrorHandler:
+ Debug.Assert False
+ IsPresentInAbbrevSymbolStack = False
+
+End Function
+
+Public Function IsModSymbolInternal(strTestChar As String) As Boolean
+ ' Returns True if the first letter of strTestChar is a ModSymbol
+ ' Invalid Mod Symbols are letters, numbers, ., -, space, (, or )
+ ' Valid Mod Symbols are ! # $ % & ' * + ? ^ _ ` ~
+
+ Dim strFirstChar As String, blnIsModSymbol As Boolean
+
+ blnIsModSymbol = False
+ If Len(strTestChar) > 0 Then
+ strFirstChar = Left(strTestChar, 1)
+
+ Select Case Asc(strFirstChar)
+ Case 34 ' " is not allowed
+ blnIsModSymbol = False
+ Case 40 To 41 ' ( and ) are not allowed
+ blnIsModSymbol = False
+ Case 44 To 62 ' . and - and , and / and numbers and : and ; and < and = and > are not allowed
+ blnIsModSymbol = False
+ Case 33 To 43, 63 To 64, 94 To 96, 126
+ blnIsModSymbol = True
+ Case Else
+ blnIsModSymbol = False
+ End Select
+ Else
+ blnIsModSymbol = False
+ End If
+
+ IsModSymbolInternal = blnIsModSymbol
+
+End Function
+
+Private Function IsStringAllLetters(strTest As String) As Boolean
+ ' Tests if all of the characers in strTest are letters
+
+ Dim blnAllLetters As Boolean, intIndex As Integer
+
+ ' Assume true until proven otherwise
+ blnAllLetters = True
+ For intIndex = 1 To Len(strTest)
+ If Not IsCharacter(Mid(strTest, intIndex, 1)) Then
+ blnAllLetters = False
+ Exit For
+ End If
+ Next intIndex
+
+ IsStringAllLetters = blnAllLetters
+End Function
+
+Private Function LookupCautionStatement(strCompareText As String) As String
+ Dim intIndex As Integer
+
+ For intIndex = 1 To CautionStatementCount
+ If strCompareText = CautionStatements(intIndex, 0) Then
+ LookupCautionStatement = CautionStatements(intIndex, 1)
+ Exit For
+ End If
+ Next intIndex
+End Function
+
+Private Function LookupMessage(lngMessageID As Long, Optional strAppendText As String) As String
+ ' Looks up the message for lngMessageID
+ ' Also appends any data in strAppendText to the message
+ ' Returns the complete message
+
+ Dim strMessage As String
+
+ If MessageStatmentCount = 0 Then MemoryLoadMessageStatements
+
+ ' First assume we can't find the message number
+ strMessage = "General unspecified error"
+
+ ' Now try to find it
+ If lngMessageID < MESSAGE_STATEMENT_DIMCOUNT Then
+ If Len(MessageStatements(lngMessageID)) > 0 Then
+ strMessage = MessageStatements(lngMessageID)
+ End If
+ End If
+
+ ' Now prepend Prefix to certain strings
+ Select Case lngMessageID
+ ' Add Error: to the front of certain error codes
+ Case 1 To 99, 120, 130, 140, 260, 270, 300
+ strMessage = LookupMessage(350) & ": " & strMessage
+ End Select
+
+ ' Now append strAppendText
+ strMessage = strMessage & strAppendText
+
+ ' lngMessageID's 1 and 18 may need to have an addendum added
+ If lngMessageID = 1 Then
+ If gComputationOptions.CaseConversion = ccExactCase Then
+ strMessage = strMessage & " (" & LookupMessage(680) & ")"
+ End If
+ ElseIf lngMessageID = 18 Then
+ If Not gComputationOptions.BracketsAsParentheses Then
+ strMessage = strMessage & " (" & LookupMessage(685) & ")"
+ Else
+ strMessage = strMessage & " (" & LookupMessage(690) & ")"
+ End If
+ End If
+
+ LookupMessage = strMessage
+End Function
+
+Public Function MassToPPMInternal(ByVal dblMassToConvert As Double, ByVal dblCurrentMZ As Double) As Double
+ ' Converts dblMassToConvert to ppm, based on the value of dblCurrentMZ
+
+ If dblCurrentMZ > 0 Then
+ MassToPPMInternal = dblMassToConvert * 1000000# / dblCurrentMZ
+ Else
+ MassToPPMInternal = 0
+ End If
+End Function
+
+Public Function MonoMassToMZInternal(ByVal dblMonoisotopicMass As Double, ByVal intCharge As Integer, Optional ByVal dblChargeCarrierMass As Double = 0) As Double
+ ' If dblChargeCarrierMass is 0, then uses mChargeCarrierMass
+ If dblChargeCarrierMass = 0 Then dblChargeCarrierMass = mChargeCarrierMass
+
+ ' Call ConvoluteMass to convert to the desired charge state
+ MonoMassToMZInternal = ConvoluteMassInternal(dblMonoisotopicMass + dblChargeCarrierMass, 1, intCharge, dblChargeCarrierMass)
+End Function
+
+Public Sub MemoryLoadAll(eElementMode As emElementModeConstantsPrivate)
+
+ MemoryLoadElements eElementMode
+
+ ' Reconstruct master symbols list
+ ConstructMasterSymbolsList
+
+ MemoryLoadIsotopes
+
+ MemoryLoadAbbreviations
+
+ ' Reconstruct master symbols list
+ ConstructMasterSymbolsList
+
+ MemoryLoadCautionStatements
+
+ MemoryLoadMessageStatements
+
+End Sub
+
+Public Sub MemoryLoadAbbreviations()
+ Dim intIndex As Integer
+
+ ' Symbol Formula 1 letter abbreviation
+ Const AminoAbbrevCount = 28
+
+ AbbrevAllCount = AminoAbbrevCount
+ For intIndex = 1 To AbbrevAllCount
+ AbbrevStats(intIndex).IsAminoAcid = True
+ Next intIndex
+
+ AddAbbreviationWork 1, "Ala", "C3H5NO", 0, True, "A", "Alanine"
+ AddAbbreviationWork 2, "Arg", "C6H12N4O", 0, True, "R", "Arginine, (unprotonated NH2)"
+ AddAbbreviationWork 3, "Asn", "C4H6N2O2", 0, True, "N", "Asparagine"
+ AddAbbreviationWork 4, "Asp", "C4H5NO3", 0, True, "D", "Aspartic acid (undissociated COOH)"
+ AddAbbreviationWork 5, "Cys", "C3H5NOS", 0, True, "C", "Cysteine (no disulfide link)"
+ AddAbbreviationWork 6, "Gla", "C6H7NO5", 0, True, "U", "gamma-Carboxyglutamate"
+ AddAbbreviationWork 7, "Gln", "C5H8N2O2", 0, True, "Q", "Glutamine"
+ AddAbbreviationWork 8, "Glu", "C5H7NO3", 0, True, "E", "Glutamic acid (undissociated COOH)"
+ AddAbbreviationWork 9, "Gly", "C2H3NO", 0, True, "G", "Glycine"
+ AddAbbreviationWork 10, "His", "C6H7N3O", 0, True, "H", "Histidine (unprotonated NH)"
+ AddAbbreviationWork 11, "Hse", "C4H7NO2", 0, True, "", "Homoserine"
+ AddAbbreviationWork 12, "Hyl", "C6H12N2O2", 0, True, "", "Hydroxylysine"
+ AddAbbreviationWork 13, "Hyp", "C5H7NO2", 0, True, "", "Hydroxyproline"
+ AddAbbreviationWork 14, "Ile", "C6H11NO", 0, True, "I", "Isoleucine"
+ AddAbbreviationWork 15, "Leu", "C6H11NO", 0, True, "L", "Leucine"
+ AddAbbreviationWork 16, "Lys", "C6H12N2O", 0, True, "K", "Lysine (unprotonated NH2)"
+ AddAbbreviationWork 17, "Met", "C5H9NOS", 0, True, "M", "Methionine"
+ AddAbbreviationWork 18, "Orn", "C5H10N2O", 0, True, "O", "Ornithine"
+ AddAbbreviationWork 19, "Phe", "C9H9NO", 0, True, "F", "Phenylalanine"
+ AddAbbreviationWork 20, "Pro", "C5H7NO", 0, True, "P", "Proline"
+ AddAbbreviationWork 21, "Pyr", "C5H5NO2", 0, True, "", "Pyroglutamic acid"
+ AddAbbreviationWork 22, "Sar", "C3H5NO", 0, True, "", "Sarcosine"
+ AddAbbreviationWork 23, "Ser", "C3H5NO2", 0, True, "S", "Serine"
+ AddAbbreviationWork 24, "Thr", "C4H7NO2", 0, True, "T", "Threonine"
+ AddAbbreviationWork 25, "Trp", "C11H10N2O", 0, True, "W", "Tryptophan"
+ AddAbbreviationWork 26, "Tyr", "C9H9NO2", 0, True, "Y", "Tyrosine"
+ AddAbbreviationWork 27, "Val", "C5H9NO", 0, True, "V", "Valine"
+ AddAbbreviationWork 28, "Xxx", "C6H12N2O", 0, True, "X", "Unknown"
+
+ Const NormalAbbrevCount = 16
+ AbbrevAllCount = AbbrevAllCount + NormalAbbrevCount
+ For intIndex = AminoAbbrevCount + 1 To AbbrevAllCount
+ AbbrevStats(intIndex).IsAminoAcid = False
+ Next intIndex
+
+ AddAbbreviationWork AminoAbbrevCount + 1, "Bpy", "C10H8N2", 0, False, "", "Bipyridine"
+ AddAbbreviationWork AminoAbbrevCount + 2, "Bu", "C4H9", 1, False, "", "Butyl"
+ AddAbbreviationWork AminoAbbrevCount + 3, "D", "^2.014H", 1, False, "", "Deuterium"
+ AddAbbreviationWork AminoAbbrevCount + 4, "En", "C2H8N2", 0, False, "", "Ethylenediamine"
+ AddAbbreviationWork AminoAbbrevCount + 5, "Et", "CH3CH2", 1, False, "", "Ethyl"
+ AddAbbreviationWork AminoAbbrevCount + 6, "Me", "CH3", 1, False, "", "Methyl"
+ AddAbbreviationWork AminoAbbrevCount + 7, "Ms", "CH3SOO", -1, False, "", "Mesyl"
+ AddAbbreviationWork AminoAbbrevCount + 8, "Oac", "C2H3O2", -1, False, "", "Acetate"
+ AddAbbreviationWork AminoAbbrevCount + 9, "Otf", "OSO2CF3", -1, False, "", "Triflate"
+ AddAbbreviationWork AminoAbbrevCount + 10, "Ox", "C2O4", -2, False, "", "Oxalate"
+ AddAbbreviationWork AminoAbbrevCount + 11, "Ph", "C6H5", 1, False, "", "Phenyl"
+ AddAbbreviationWork AminoAbbrevCount + 12, "Phen", "C12H8N2", 0, False, "", "Phenanthroline"
+ AddAbbreviationWork AminoAbbrevCount + 13, "Py", "C5H5N", 0, False, "", "Pyridine"
+ AddAbbreviationWork AminoAbbrevCount + 14, "Tpp", "(C4H2N(C6H5C)C4H2N(C6H5C))2", 0, False, "", "Tetraphenylporphyrin"
+ AddAbbreviationWork AminoAbbrevCount + 15, "Ts", "CH3C6H4SOO", -1, False, "", "Tosyl"
+ AddAbbreviationWork AminoAbbrevCount + 16, "Urea", "H2NCONH2", 0, False, "", "Urea"
+
+' ' Note Asx or B is often used for Asp or Asn
+' ' Note Glx or Z is often used for Glu or Gln
+' ' Note X is often used for "unknown"
+'
+' ' Other amino acids without widely agreed upon 1 letter codes
+'
+' FlexGridAddItems .grdAminoAcids, "Aminosuberic Acid", "Asu" ' A pair of Cys residues bonded by S-S
+' FlexGridAddItems .grdAminoAcids, "Cystine", "Cyn"
+' FlexGridAddItems .grdAminoAcids, "Homocysteine", "Hcy"
+' FlexGridAddItems .grdAminoAcids, "Homoserine", "Hse" ' 101.04 (C4H7NO2)
+' FlexGridAddItems .grdAminoAcids, "Hydroxylysine", "Hyl" ' 144.173 (C6H12N2O2)
+' FlexGridAddItems .grdAminoAcids, "Hydroxyproline", "Hyp" ' 113.116 (C5H7NO2)
+' FlexGridAddItems .grdAminoAcids, "Norleucine", "Nle" ' 113.06
+' FlexGridAddItems .grdAminoAcids, "Norvaline", "Nva"
+' FlexGridAddItems .grdAminoAcids, "Pencillamine", "Pen"
+' FlexGridAddItems .grdAminoAcids, "Phosphoserine", "Sep"
+' FlexGridAddItems .grdAminoAcids, "Phosphothreonine", "Thp"
+' FlexGridAddItems .grdAminoAcids, "Phosphotyrosine", "Typ"
+' FlexGridAddItems .grdAminoAcids, "Pyroglutamic Acid", "Pyr" ' 111.03 (C5H5NO2) (also Glp in some tables)
+' FlexGridAddItems .grdAminoAcids, "Sarcosine", "Sar" ' 71.08 (C3H5NO)
+' FlexGridAddItems .grdAminoAcids, "Statine", "Sta"
+' FlexGridAddItems .grdAminoAcids, "b-[2-Thienyl]Ala", "Thi"
+
+
+' Need to explore http://www.abrf.org/ABRF/ResearchCommittees/deltamass/deltamass.html
+
+ ' Isoelectric points
+' TYR Y C9H9NO2 163.06333 163.1760 0 9.8
+' HIS H C6H7N3O 137.05891 137.1411 1 6.8
+' LYS K C6H12N2O 128.09496 128.1741 1 10.1
+' ASP D C4H5NO3 115.02694 115.0886 1 4.5
+' GLU E C5H7NO3 129.04259 129.1155 1 4.5
+' CYS C C3H5NOS 103.00919 103.1388 0 8.6
+' ARG R C6H12N4O 156.10111 156.1875 1 12.0
+
+
+End Sub
+
+' Use objMwtWin.ClearCautionStatements and objMwtWin.AddCautionStatement to
+' set these based on language
+Public Sub MemoryLoadCautionStatements()
+
+ CautionStatementCount = 41
+
+ CautionStatements(1, 0) = "Bi": CautionStatements(1, 1) = "Bi means bismuth; BI means boron-iodine. "
+ CautionStatements(2, 0) = "Bk": CautionStatements(2, 1) = "Bk means berkelium; BK means boron-potassium. "
+ CautionStatements(3, 0) = "Bu": CautionStatements(3, 1) = "Bu means the butyl group; BU means boron-uranium. "
+ CautionStatements(4, 0) = "Cd": CautionStatements(4, 1) = "Cd means cadmium; CD means carbon-deuterium. "
+ CautionStatements(5, 0) = "Cf": CautionStatements(5, 1) = "Cf means californium; CF means carbon-fluorine. "
+ CautionStatements(6, 0) = "Co": CautionStatements(6, 1) = "Co means cobalt; CO means carbon-oxygen. "
+ CautionStatements(7, 0) = "Cs": CautionStatements(7, 1) = "Cs means cesium; CS means carbon-sulfur. "
+ CautionStatements(8, 0) = "Cu": CautionStatements(8, 1) = "Cu means copper; CU means carbon-uranium. "
+ CautionStatements(9, 0) = "Dy": CautionStatements(9, 1) = "Dy means dysprosium; DY means deuterium-yttrium. "
+ CautionStatements(10, 0) = "Hf": CautionStatements(10, 1) = "Hf means hafnium; HF means hydrogen-fluorine. "
+ CautionStatements(11, 0) = "Ho": CautionStatements(11, 1) = "Ho means holmium; HO means hydrogen-oxygen. "
+ CautionStatements(12, 0) = "In": CautionStatements(12, 1) = "In means indium; IN means iodine-nitrogen. "
+ CautionStatements(13, 0) = "Nb": CautionStatements(13, 1) = "Nb means niobium; NB means nitrogen-boron. "
+ CautionStatements(14, 0) = "Nd": CautionStatements(14, 1) = "Nd means neodymium; ND means nitrogen-deuterium. "
+ CautionStatements(15, 0) = "Ni": CautionStatements(15, 1) = "Ni means nickel; NI means nitrogen-iodine. "
+ CautionStatements(16, 0) = "No": CautionStatements(16, 1) = "No means nobelium; NO means nitrogen-oxygen. "
+ CautionStatements(17, 0) = "Np": CautionStatements(17, 1) = "Np means neptunium; NP means nitrogen-phosphorus. "
+ CautionStatements(18, 0) = "Os": CautionStatements(18, 1) = "Os means osmium; OS means oxygen-sulfur. "
+ CautionStatements(19, 0) = "Pd": CautionStatements(19, 1) = "Pd means palladium; PD means phosphorus-deuterium. "
+ CautionStatements(20, 0) = "Ph": CautionStatements(20, 1) = "Ph means phenyl, PH means phosphorus-hydrogen. "
+ CautionStatements(21, 0) = "Pu": CautionStatements(21, 1) = "Pu means plutonium; PU means phosphorus-uranium. "
+ CautionStatements(22, 0) = "Py": CautionStatements(22, 1) = "Py means pyridine; PY means phosphorus-yttrium. "
+ CautionStatements(23, 0) = "Sb": CautionStatements(23, 1) = "Sb means antimony; SB means sulfor-boron. "
+ CautionStatements(24, 0) = "Sc": CautionStatements(24, 1) = "Sc means scandium; SC means sulfur-carbon. "
+ CautionStatements(25, 0) = "Si": CautionStatements(25, 1) = "Si means silicon; SI means sulfur-iodine. "
+ CautionStatements(26, 0) = "Sn": CautionStatements(26, 1) = "Sn means tin; SN means sulfor-nitrogen. "
+ CautionStatements(27, 0) = "TI": CautionStatements(27, 1) = "TI means tritium-iodine, Ti means titanium. "
+ CautionStatements(28, 0) = "Yb": CautionStatements(28, 1) = "Yb means ytterbium; YB means yttrium-boron. "
+ CautionStatements(29, 0) = "BPY": CautionStatements(29, 1) = "BPY means boron-phosphorus-yttrium; Bpy means bipyridine. "
+ CautionStatements(30, 0) = "BPy": CautionStatements(30, 1) = "BPy means boron-pyridine; Bpy means bipyridine. "
+ CautionStatements(31, 0) = "Bpy": CautionStatements(31, 1) = "Bpy means bipyridine. "
+ CautionStatements(32, 0) = "Cys": CautionStatements(32, 1) = "Cys means cysteine; CYS means carbon-yttrium-sulfur. "
+ CautionStatements(33, 0) = "His": CautionStatements(33, 1) = "His means histidine; HIS means hydrogen-iodine-sulfur. "
+ CautionStatements(34, 0) = "Hoh": CautionStatements(34, 1) = "HoH means holmium-hydrogen; HOH means hydrogen-oxygen-hydrogen (aka water). "
+ CautionStatements(35, 0) = "Hyp": CautionStatements(35, 1) = "Hyp means hydroxyproline; HYP means hydrogen-yttrium-phosphorus. "
+ CautionStatements(36, 0) = "OAc": CautionStatements(36, 1) = "OAc means oxygen-actinium; Oac means acetate. "
+ CautionStatements(37, 0) = "Oac": CautionStatements(37, 1) = "Oac means acetate. "
+ CautionStatements(38, 0) = "Pro": CautionStatements(38, 1) = "Pro means proline; PrO means praseodymium-oxygen. "
+ CautionStatements(39, 0) = "PrO": CautionStatements(39, 1) = "Pro means proline; PrO means praseodymium-oxygen. "
+ CautionStatements(40, 0) = "Val": CautionStatements(40, 1) = "Val means valine; VAl means vanadium-aluminum. "
+ CautionStatements(41, 0) = "VAl": CautionStatements(41, 1) = "Val means valine; VAl means vanadium-aluminum. "
+
+End Sub
+
+Public Sub MemoryLoadElements(eElementMode As emElementModeConstantsPrivate, Optional intSpecificElement As Integer = 0, Optional eSpecificStatToReset As esElementStatsConstants = esMass)
+ ' intSpecificElement and intSpecificElementProperty are zero when updating all of the elements
+ ' nonzero intSpecificElement and intSpecificElementProperty values will set just that specific value to the default
+ ' eElementMode = 0 should not occur
+ ' eElementMode = 1 means to use the average elemental weights
+ ' eElementMode = 2 means to use isotopic elemental weights
+ ' eElementMode = 3 means to use integer isotopic weights
+
+ Const DEFAULT_CHARGE_CARRIER_MASS_AVG = 1.00739
+ Const DEFAULT_CHARGE_CARRIER_MASS_MONOISO = 1.00727649
+
+ ' This array stores the element names
+ Dim strElementNames(ELEMENT_COUNT) As String
+
+ ' dblElemVals(intElementIndex,1) stores the element's weight
+ ' dblElemVals(intElementIndex,2) stores the element's uncertainty
+ ' dblElemVals(intElementIndex,3) stores the element's charge
+ ' Note: I could make this array of type udtElementStatsType, but the size of this sub would increase dramatically
+ Dim dblElemVals(ELEMENT_COUNT, 3) As Double
+
+ Dim intElementIndex As Integer, intIndex As Integer, intCompareIndex As Integer
+ Dim strSwap As String
+
+ ' Data Load Statements
+ ' Uncertainties from CRC Handbook of Chemistry and Physics
+ ' For Radioactive elements, the most stable isotope is NOT used;
+ ' instead, an average Mol. Weight is used, just like with other elements.
+ ' Data obtained from the Perma-Chart Science Series periodic table, 1993.
+ ' Uncertainties from CRC Handoobk of Chemistry and Physics, except for
+ ' Radioactive elements, where uncertainty was estimated to be .n5 where
+ ' intSpecificElementProperty represents the number digits after the decimal point but before the last
+ ' number of the molecular weight.
+ ' For example, for No, MW = 259.1009 (±0.0005)
+
+ ' Define the charge carrier mass
+ If eElementMode = emAverageMass Then
+ SetChargeCarrierMassInternal DEFAULT_CHARGE_CARRIER_MASS_AVG
+ Else
+ SetChargeCarrierMassInternal DEFAULT_CHARGE_CARRIER_MASS_MONOISO
+ End If
+
+ ' Assigning element names, Charges
+ strElementNames(1) = "H": dblElemVals(1, 3) = 1
+ strElementNames(2) = "He": dblElemVals(2, 3) = 0
+ strElementNames(3) = "Li": dblElemVals(3, 3) = 1
+ strElementNames(4) = "Be": dblElemVals(4, 3) = 2
+ strElementNames(5) = "B": dblElemVals(5, 3) = 3
+ strElementNames(6) = "C": dblElemVals(6, 3) = 4
+ strElementNames(7) = "N": dblElemVals(7, 3) = -3
+ strElementNames(8) = "O": dblElemVals(8, 3) = -2
+ strElementNames(9) = "F": dblElemVals(9, 3) = -1
+ strElementNames(10) = "Ne": dblElemVals(10, 3) = 0
+ strElementNames(11) = "Na": dblElemVals(11, 3) = 1
+ strElementNames(12) = "Mg": dblElemVals(12, 3) = 2
+ strElementNames(13) = "Al": dblElemVals(13, 3) = 3
+ strElementNames(14) = "Si": dblElemVals(14, 3) = 4
+ strElementNames(15) = "P": dblElemVals(15, 3) = -3
+ strElementNames(16) = "S": dblElemVals(16, 3) = -2
+ strElementNames(17) = "Cl": dblElemVals(17, 3) = -1
+ strElementNames(18) = "Ar": dblElemVals(18, 3) = 0
+ strElementNames(19) = "K": dblElemVals(19, 3) = 1
+ strElementNames(20) = "Ca": dblElemVals(20, 3) = 2
+ strElementNames(21) = "Sc": dblElemVals(21, 3) = 3
+ strElementNames(22) = "Ti": dblElemVals(22, 3) = 4
+ strElementNames(23) = "V": dblElemVals(23, 3) = 5
+ strElementNames(24) = "Cr": dblElemVals(24, 3) = 3
+ strElementNames(25) = "Mn": dblElemVals(25, 3) = 2
+ strElementNames(26) = "Fe": dblElemVals(26, 3) = 3
+ strElementNames(27) = "Co": dblElemVals(27, 3) = 2
+ strElementNames(28) = "Ni": dblElemVals(28, 3) = 2
+ strElementNames(29) = "Cu": dblElemVals(29, 3) = 2
+ strElementNames(30) = "Zn": dblElemVals(30, 3) = 2
+ strElementNames(31) = "Ga": dblElemVals(31, 3) = 3
+ strElementNames(32) = "Ge": dblElemVals(32, 3) = 4
+ strElementNames(33) = "As": dblElemVals(33, 3) = -3
+ strElementNames(34) = "Se": dblElemVals(34, 3) = -2
+ strElementNames(35) = "Br": dblElemVals(35, 3) = -1
+ strElementNames(36) = "Kr": dblElemVals(36, 3) = 0
+ strElementNames(37) = "Rb": dblElemVals(37, 3) = 1
+ strElementNames(38) = "Sr": dblElemVals(38, 3) = 2
+ strElementNames(39) = "Y": dblElemVals(39, 3) = 3
+ strElementNames(40) = "Zr": dblElemVals(40, 3) = 4
+ strElementNames(41) = "Nb": dblElemVals(41, 3) = 5
+ strElementNames(42) = "Mo": dblElemVals(42, 3) = 6
+ strElementNames(43) = "Tc": dblElemVals(43, 3) = 7
+ strElementNames(44) = "Ru": dblElemVals(44, 3) = 4
+ strElementNames(45) = "Rh": dblElemVals(45, 3) = 3
+ strElementNames(46) = "Pd": dblElemVals(46, 3) = 2
+ strElementNames(47) = "Ag": dblElemVals(47, 3) = 1
+ strElementNames(48) = "Cd": dblElemVals(48, 3) = 2
+ strElementNames(49) = "In": dblElemVals(49, 3) = 3
+ strElementNames(50) = "Sn": dblElemVals(50, 3) = 4
+ strElementNames(51) = "Sb": dblElemVals(51, 3) = -3
+ strElementNames(52) = "Te": dblElemVals(52, 3) = -2
+ strElementNames(53) = "I": dblElemVals(53, 3) = -1
+ strElementNames(54) = "Xe": dblElemVals(54, 3) = 0
+ strElementNames(55) = "Cs": dblElemVals(55, 3) = 1
+ strElementNames(56) = "Ba": dblElemVals(56, 3) = 2
+ strElementNames(57) = "La": dblElemVals(57, 3) = 3
+ strElementNames(58) = "Ce": dblElemVals(58, 3) = 3
+ strElementNames(59) = "Pr": dblElemVals(59, 3) = 4
+ strElementNames(60) = "Nd": dblElemVals(60, 3) = 3
+ strElementNames(61) = "Pm": dblElemVals(61, 3) = 3
+ strElementNames(62) = "Sm": dblElemVals(62, 3) = 3
+ strElementNames(63) = "Eu": dblElemVals(63, 3) = 3
+ strElementNames(64) = "Gd": dblElemVals(64, 3) = 3
+ strElementNames(65) = "Tb": dblElemVals(65, 3) = 3
+ strElementNames(66) = "Dy": dblElemVals(66, 3) = 3
+ strElementNames(67) = "Ho": dblElemVals(67, 3) = 3
+ strElementNames(68) = "Er": dblElemVals(68, 3) = 3
+ strElementNames(69) = "Tm": dblElemVals(69, 3) = 3
+ strElementNames(70) = "Yb": dblElemVals(70, 3) = 3
+ strElementNames(71) = "Lu": dblElemVals(71, 3) = 3
+ strElementNames(72) = "Hf": dblElemVals(72, 3) = 4
+ strElementNames(73) = "Ta": dblElemVals(73, 3) = 5
+ strElementNames(74) = "W": dblElemVals(74, 3) = 6
+ strElementNames(75) = "Re": dblElemVals(75, 3) = 7
+ strElementNames(76) = "Os": dblElemVals(76, 3) = 4
+ strElementNames(77) = "Ir": dblElemVals(77, 3) = 4
+ strElementNames(78) = "Pt": dblElemVals(78, 3) = 4
+ strElementNames(79) = "Au": dblElemVals(79, 3) = 3
+ strElementNames(80) = "Hg": dblElemVals(80, 3) = 2
+ strElementNames(81) = "Tl": dblElemVals(81, 3) = 1
+ strElementNames(82) = "Pb": dblElemVals(82, 3) = 2
+ strElementNames(83) = "Bi": dblElemVals(83, 3) = 3
+ strElementNames(84) = "Po": dblElemVals(84, 3) = 4
+ strElementNames(85) = "At": dblElemVals(85, 3) = -1
+ strElementNames(86) = "Rn": dblElemVals(86, 3) = 0
+ strElementNames(87) = "Fr": dblElemVals(87, 3) = 1
+ strElementNames(88) = "Ra": dblElemVals(88, 3) = 2
+ strElementNames(89) = "Ac": dblElemVals(89, 3) = 3
+ strElementNames(90) = "Th": dblElemVals(90, 3) = 4
+ strElementNames(91) = "Pa": dblElemVals(91, 3) = 5
+ strElementNames(92) = "U": dblElemVals(92, 3) = 6
+ strElementNames(93) = "Np": dblElemVals(93, 3) = 5
+ strElementNames(94) = "Pu": dblElemVals(94, 3) = 4
+ strElementNames(95) = "Am": dblElemVals(95, 3) = 3
+ strElementNames(96) = "Cm": dblElemVals(96, 3) = 3
+ strElementNames(97) = "Bk": dblElemVals(97, 3) = 3
+ strElementNames(98) = "Cf": dblElemVals(98, 3) = 3
+ strElementNames(99) = "Es": dblElemVals(99, 3) = 3
+ strElementNames(100) = "Fm": dblElemVals(100, 3) = 3
+ strElementNames(101) = "Md": dblElemVals(101, 3) = 3
+ strElementNames(102) = "No": dblElemVals(102, 3) = 3
+ strElementNames(103) = "Lr": dblElemVals(103, 3) = 3
+
+ ' Set uncertainty to 0 for all elements if using exact isotopic or integer isotopic weights
+ If eElementMode = 2 Or eElementMode = 3 Then
+ For intIndex = 1 To ELEMENT_COUNT
+ dblElemVals(intIndex, 2) = 0
+ Next intIndex
+ End If
+
+ Select Case eElementMode
+ Case 3
+ ' Integer Isotopic Weights
+ dblElemVals(1, 1) = 1
+ dblElemVals(2, 1) = 4
+ dblElemVals(3, 1) = 7
+ dblElemVals(4, 1) = 9
+ dblElemVals(5, 1) = 11
+ dblElemVals(6, 1) = 12
+ dblElemVals(7, 1) = 14
+ dblElemVals(8, 1) = 16
+ dblElemVals(9, 1) = 19
+ dblElemVals(10, 1) = 20
+ dblElemVals(11, 1) = 23
+ dblElemVals(12, 1) = 24
+ dblElemVals(13, 1) = 27
+ dblElemVals(14, 1) = 28
+ dblElemVals(15, 1) = 31
+ dblElemVals(16, 1) = 32
+ dblElemVals(17, 1) = 35
+ dblElemVals(18, 1) = 40
+ dblElemVals(19, 1) = 39
+ dblElemVals(20, 1) = 40
+ dblElemVals(21, 1) = 45
+ dblElemVals(22, 1) = 48
+ dblElemVals(23, 1) = 51
+ dblElemVals(24, 1) = 52
+ dblElemVals(25, 1) = 55
+ dblElemVals(26, 1) = 56
+ dblElemVals(27, 1) = 59
+ dblElemVals(28, 1) = 58
+ dblElemVals(29, 1) = 63
+ dblElemVals(30, 1) = 64
+ dblElemVals(31, 1) = 69
+ dblElemVals(32, 1) = 72
+ dblElemVals(33, 1) = 75
+ dblElemVals(34, 1) = 80
+ dblElemVals(35, 1) = 79
+ dblElemVals(36, 1) = 84
+ dblElemVals(37, 1) = 85
+ dblElemVals(38, 1) = 88
+ dblElemVals(39, 1) = 89
+ dblElemVals(40, 1) = 90
+ dblElemVals(41, 1) = 93
+ dblElemVals(42, 1) = 98
+ dblElemVals(43, 1) = 98
+ dblElemVals(44, 1) = 102
+ dblElemVals(45, 1) = 103
+ dblElemVals(46, 1) = 106
+ dblElemVals(47, 1) = 107
+ dblElemVals(48, 1) = 114
+ dblElemVals(49, 1) = 115
+ dblElemVals(50, 1) = 120
+ dblElemVals(51, 1) = 121
+ dblElemVals(52, 1) = 130
+ dblElemVals(53, 1) = 127
+ dblElemVals(54, 1) = 132
+ dblElemVals(55, 1) = 133
+ dblElemVals(56, 1) = 138
+ dblElemVals(57, 1) = 139
+ dblElemVals(58, 1) = 140
+ dblElemVals(59, 1) = 141
+ dblElemVals(60, 1) = 142
+ dblElemVals(61, 1) = 145
+ dblElemVals(62, 1) = 152
+ dblElemVals(63, 1) = 153
+ dblElemVals(64, 1) = 158
+ dblElemVals(65, 1) = 159
+ dblElemVals(66, 1) = 164
+ dblElemVals(67, 1) = 165
+ dblElemVals(68, 1) = 166
+ dblElemVals(69, 1) = 169
+ dblElemVals(70, 1) = 174
+ dblElemVals(71, 1) = 175
+ dblElemVals(72, 1) = 180
+ dblElemVals(73, 1) = 181
+ dblElemVals(74, 1) = 184
+ dblElemVals(75, 1) = 187
+ dblElemVals(76, 1) = 192
+ dblElemVals(77, 1) = 193
+ dblElemVals(78, 1) = 195
+ dblElemVals(79, 1) = 197
+ dblElemVals(80, 1) = 202
+ dblElemVals(81, 1) = 205
+ dblElemVals(82, 1) = 208
+ dblElemVals(83, 1) = 209
+ dblElemVals(84, 1) = 209
+ dblElemVals(85, 1) = 210
+ dblElemVals(86, 1) = 222
+ dblElemVals(87, 1) = 223
+ dblElemVals(88, 1) = 227
+ dblElemVals(89, 1) = 227
+ dblElemVals(90, 1) = 232
+ dblElemVals(91, 1) = 231
+ dblElemVals(92, 1) = 238
+ dblElemVals(93, 1) = 237
+ dblElemVals(94, 1) = 244
+ dblElemVals(95, 1) = 243
+ dblElemVals(96, 1) = 247
+ dblElemVals(97, 1) = 247
+ dblElemVals(98, 1) = 251
+ dblElemVals(99, 1) = 252
+ dblElemVals(100, 1) = 257
+ dblElemVals(101, 1) = 258
+ dblElemVals(102, 1) = 269
+ dblElemVals(103, 1) = 260
+
+ ' Unused elements
+ ' data 104,Unq,Unnilquadium,261.11,.05, 105,Unp,Unnilpentium,262.114,005, 106,Unh,Unnilhexium,263.118,.005, 107,Uns,Unnilseptium,262.12,.05
+
+ Case 2
+ ' isotopic Element Weights
+ dblElemVals(1, 1) = 1.0078246
+ dblElemVals(2, 1) = 4.0026029
+ dblElemVals(3, 1) = 7.016005
+ dblElemVals(4, 1) = 9.012183
+ dblElemVals(5, 1) = 11.009305
+ dblElemVals(6, 1) = 12
+ dblElemVals(7, 1) = 14.003074
+ dblElemVals(8, 1) = 15.994915
+ dblElemVals(9, 1) = 18.9984032
+ dblElemVals(10, 1) = 19.992439
+ dblElemVals(11, 1) = 22.98977
+ dblElemVals(12, 1) = 23.98505
+ dblElemVals(13, 1) = 26.981541
+ dblElemVals(14, 1) = 27.976928
+ dblElemVals(15, 1) = 30.973763
+ dblElemVals(16, 1) = 31.972072
+ dblElemVals(17, 1) = 34.968853
+ dblElemVals(18, 1) = 39.962383
+ dblElemVals(19, 1) = 38.963708
+ dblElemVals(20, 1) = 39.962591
+ dblElemVals(21, 1) = 44.955914
+ dblElemVals(22, 1) = 47.947947
+ dblElemVals(23, 1) = 50.943963
+ dblElemVals(24, 1) = 51.94051
+ dblElemVals(25, 1) = 54.938046
+ dblElemVals(26, 1) = 55.934939
+ dblElemVals(27, 1) = 58.933198
+ dblElemVals(28, 1) = 57.935347
+ dblElemVals(29, 1) = 62.929599
+ dblElemVals(30, 1) = 63.929145
+ dblElemVals(31, 1) = 68.925581
+ dblElemVals(32, 1) = 71.92208
+ dblElemVals(33, 1) = 74.921596
+ dblElemVals(34, 1) = 79.916521
+ dblElemVals(35, 1) = 78.918336
+ dblElemVals(36, 1) = 83.911506
+ dblElemVals(37, 1) = 84.9118
+ dblElemVals(38, 1) = 87.905625
+ dblElemVals(39, 1) = 88.905856
+ dblElemVals(40, 1) = 89.904708
+ dblElemVals(41, 1) = 92.906378
+ dblElemVals(42, 1) = 97.905405
+ dblElemVals(43, 1) = 98
+ dblElemVals(44, 1) = 101.90434
+ dblElemVals(45, 1) = 102.905503
+ dblElemVals(46, 1) = 105.903475
+ dblElemVals(47, 1) = 106.905095
+ dblElemVals(48, 1) = 113.903361
+ dblElemVals(49, 1) = 114.903875
+ dblElemVals(50, 1) = 119.902199
+ dblElemVals(51, 1) = 120.903824
+ dblElemVals(52, 1) = 129.906229
+ dblElemVals(53, 1) = 126.904477
+ dblElemVals(54, 1) = 131.904148
+ dblElemVals(55, 1) = 132.905433
+ dblElemVals(56, 1) = 137.905236
+ dblElemVals(57, 1) = 138.906355
+ dblElemVals(58, 1) = 139.905442
+ dblElemVals(59, 1) = 140.907657
+ dblElemVals(60, 1) = 141.907731
+ dblElemVals(61, 1) = 145
+ dblElemVals(62, 1) = 151.919741
+ dblElemVals(63, 1) = 152.921243
+ dblElemVals(64, 1) = 157.924111
+ dblElemVals(65, 1) = 158.92535
+ dblElemVals(66, 1) = 163.929183
+ dblElemVals(67, 1) = 164.930332
+ dblElemVals(68, 1) = 165.930305
+ dblElemVals(69, 1) = 168.934225
+ dblElemVals(70, 1) = 173.938873
+ dblElemVals(71, 1) = 174.940785
+ dblElemVals(72, 1) = 179.946561
+ dblElemVals(73, 1) = 180.948014
+ dblElemVals(74, 1) = 183.950953
+ dblElemVals(75, 1) = 186.955765
+ dblElemVals(76, 1) = 191.960603
+ dblElemVals(77, 1) = 192.962942
+ dblElemVals(78, 1) = 194.964785
+ dblElemVals(79, 1) = 196.96656
+ dblElemVals(80, 1) = 201.970632
+ dblElemVals(81, 1) = 204.97441
+ dblElemVals(82, 1) = 207.976641
+ dblElemVals(83, 1) = 208.980388
+ dblElemVals(84, 1) = 209
+ dblElemVals(85, 1) = 210
+ dblElemVals(86, 1) = 222
+ dblElemVals(87, 1) = 223
+ dblElemVals(88, 1) = 227
+ dblElemVals(89, 1) = 227
+ dblElemVals(90, 1) = 232.038054
+ dblElemVals(91, 1) = 231
+ dblElemVals(92, 1) = 238.050786
+ dblElemVals(93, 1) = 237
+ dblElemVals(94, 1) = 244
+ dblElemVals(95, 1) = 243
+ dblElemVals(96, 1) = 247
+ dblElemVals(97, 1) = 247
+ dblElemVals(98, 1) = 251
+ dblElemVals(99, 1) = 252
+ dblElemVals(100, 1) = 257
+ dblElemVals(101, 1) = 258
+ dblElemVals(102, 1) = 269
+ dblElemVals(103, 1) = 260
+
+ ' Unused elements
+ ' data 104,Unq,Unnilquadium,261.11,.05, 105,Unp,Unnilpentium,262.114,005, 106,Unh,Unnilhexium,263.118,.005, 107,Uns,Unnilseptium,262.12,.05
+
+ Case Else
+ ' Weight Uncertainty
+ ' Average Element Weights
+ dblElemVals(1, 1) = 1.00794: dblElemVals(1, 2) = 0.00007
+ dblElemVals(2, 1) = 4.002602: dblElemVals(2, 2) = 0.000002
+ dblElemVals(3, 1) = 6.941: dblElemVals(3, 2) = 0.002
+ dblElemVals(4, 1) = 9.012182: dblElemVals(4, 2) = 0.000003
+ dblElemVals(5, 1) = 10.811: dblElemVals(5, 2) = 0.007
+ dblElemVals(6, 1) = 12.0107: dblElemVals(6, 2) = 0.0008
+ dblElemVals(7, 1) = 14.00674: dblElemVals(7, 2) = 0.00007
+ dblElemVals(8, 1) = 15.9994: dblElemVals(8, 2) = 0.0003
+ dblElemVals(9, 1) = 18.9984032: dblElemVals(9, 2) = 0.0000005
+ dblElemVals(10, 1) = 20.1797: dblElemVals(10, 2) = 0.0006
+ dblElemVals(11, 1) = 22.98977: dblElemVals(11, 2) = 0.000002
+ dblElemVals(12, 1) = 24.305: dblElemVals(12, 2) = 0.0006
+ dblElemVals(13, 1) = 26.981538: dblElemVals(13, 2) = 0.000002
+ dblElemVals(14, 1) = 28.0855: dblElemVals(14, 2) = 0.0003
+ dblElemVals(15, 1) = 30.973761: dblElemVals(15, 2) = 0.000002
+ dblElemVals(16, 1) = 32.066: dblElemVals(16, 2) = 0.006
+ dblElemVals(17, 1) = 35.4527: dblElemVals(17, 2) = 0.0009
+ dblElemVals(18, 1) = 39.948: dblElemVals(18, 2) = 0.001
+ dblElemVals(19, 1) = 39.0983: dblElemVals(19, 2) = 0.0001
+ dblElemVals(20, 1) = 40.078: dblElemVals(20, 2) = 0.004
+ dblElemVals(21, 1) = 44.95591: dblElemVals(21, 2) = 0.000008
+ dblElemVals(22, 1) = 47.867: dblElemVals(22, 2) = 0.001
+ dblElemVals(23, 1) = 50.9415: dblElemVals(23, 2) = 0.0001
+ dblElemVals(24, 1) = 51.9961: dblElemVals(24, 2) = 0.0006
+ dblElemVals(25, 1) = 54.938049: dblElemVals(25, 2) = 0.000009
+ dblElemVals(26, 1) = 55.845: dblElemVals(26, 2) = 0.002
+ dblElemVals(27, 1) = 58.9332: dblElemVals(27, 2) = 0.000009
+ dblElemVals(28, 1) = 58.6934: dblElemVals(28, 2) = 0.0002
+ dblElemVals(29, 1) = 63.546: dblElemVals(29, 2) = 0.003
+ dblElemVals(30, 1) = 65.39: dblElemVals(30, 2) = 0.02
+ dblElemVals(31, 1) = 69.723: dblElemVals(31, 2) = 0.001
+ dblElemVals(32, 1) = 72.61: dblElemVals(32, 2) = 0.02
+ dblElemVals(33, 1) = 74.9216: dblElemVals(33, 2) = 0.00002
+ dblElemVals(34, 1) = 78.96: dblElemVals(34, 2) = 0.03
+ dblElemVals(35, 1) = 79.904: dblElemVals(35, 2) = 0.001
+ dblElemVals(36, 1) = 83.8: dblElemVals(36, 2) = 0.01
+ dblElemVals(37, 1) = 85.4678: dblElemVals(37, 2) = 0.0003
+ dblElemVals(38, 1) = 87.62: dblElemVals(38, 2) = 0.01
+ dblElemVals(39, 1) = 88.90585: dblElemVals(39, 2) = 0.00002
+ dblElemVals(40, 1) = 91.224: dblElemVals(40, 2) = 0.002
+ dblElemVals(41, 1) = 92.90638: dblElemVals(41, 2) = 0.00002
+ dblElemVals(42, 1) = 95.94: dblElemVals(42, 2) = 0.01
+ dblElemVals(43, 1) = 97.9072: dblElemVals(43, 2) = 0.0005
+ dblElemVals(44, 1) = 101.07: dblElemVals(44, 2) = 0.02
+ dblElemVals(45, 1) = 102.9055: dblElemVals(45, 2) = 0.00002
+ dblElemVals(46, 1) = 106.42: dblElemVals(46, 2) = 0.01
+ dblElemVals(47, 1) = 107.8682: dblElemVals(47, 2) = 0.0002
+ dblElemVals(48, 1) = 112.411: dblElemVals(48, 2) = 0.008
+ dblElemVals(49, 1) = 114.818: dblElemVals(49, 2) = 0.003
+ dblElemVals(50, 1) = 118.71: dblElemVals(50, 2) = 0.007
+ dblElemVals(51, 1) = 121.76: dblElemVals(51, 2) = 0.001
+ dblElemVals(52, 1) = 127.6: dblElemVals(52, 2) = 0.03
+ dblElemVals(53, 1) = 126.90447: dblElemVals(53, 2) = 0.00003
+ dblElemVals(54, 1) = 131.29: dblElemVals(54, 2) = 0.02
+ dblElemVals(55, 1) = 132.90545: dblElemVals(55, 2) = 0.00002
+ dblElemVals(56, 1) = 137.327: dblElemVals(56, 2) = 0.007
+ dblElemVals(57, 1) = 138.9055: dblElemVals(57, 2) = 0.0002
+ dblElemVals(58, 1) = 140.116: dblElemVals(58, 2) = 0.001
+ dblElemVals(59, 1) = 140.90765: dblElemVals(59, 2) = 0.00002
+ dblElemVals(60, 1) = 144.24: dblElemVals(60, 2) = 0.03
+ dblElemVals(61, 1) = 144.9127: dblElemVals(61, 2) = 0.0005
+ dblElemVals(62, 1) = 150.36: dblElemVals(62, 2) = 0.03
+ dblElemVals(63, 1) = 151.964: dblElemVals(63, 2) = 0.001
+ dblElemVals(64, 1) = 157.25: dblElemVals(64, 2) = 0.03
+ dblElemVals(65, 1) = 158.92534: dblElemVals(65, 2) = 0.00002
+ dblElemVals(66, 1) = 162.5: dblElemVals(66, 2) = 0.03
+ dblElemVals(67, 1) = 164.93032: dblElemVals(67, 2) = 0.00002
+ dblElemVals(68, 1) = 167.26: dblElemVals(68, 2) = 0.03
+ dblElemVals(69, 1) = 168.93421: dblElemVals(69, 2) = 0.00002
+ dblElemVals(70, 1) = 173.04: dblElemVals(70, 2) = 0.03
+ dblElemVals(71, 1) = 174.967: dblElemVals(71, 2) = 0.001
+ dblElemVals(72, 1) = 178.49: dblElemVals(72, 2) = 0.02
+ dblElemVals(73, 1) = 180.9479: dblElemVals(73, 2) = 0.0001
+ dblElemVals(74, 1) = 183.84: dblElemVals(74, 2) = 0.01
+ dblElemVals(75, 1) = 186.207: dblElemVals(75, 2) = 0.001
+ dblElemVals(76, 1) = 190.23: dblElemVals(76, 2) = 0.03
+ dblElemVals(77, 1) = 192.217: dblElemVals(77, 2) = 0.03
+ dblElemVals(78, 1) = 195.078: dblElemVals(78, 2) = 0.002
+ dblElemVals(79, 1) = 196.96655: dblElemVals(79, 2) = 0.00002
+ dblElemVals(80, 1) = 200.59: dblElemVals(80, 2) = 0.02
+ dblElemVals(81, 1) = 204.3833: dblElemVals(81, 2) = 0.0002
+ dblElemVals(82, 1) = 207.2: dblElemVals(82, 2) = 0.1
+ dblElemVals(83, 1) = 208.98038: dblElemVals(83, 2) = 0.00002
+ dblElemVals(84, 1) = 208.9824: dblElemVals(84, 2) = 0.0005
+ dblElemVals(85, 1) = 209.9871: dblElemVals(85, 2) = 0.0005
+ dblElemVals(86, 1) = 222.0176: dblElemVals(86, 2) = 0.0005
+ dblElemVals(87, 1) = 223.0197: dblElemVals(87, 2) = 0.0005
+ dblElemVals(88, 1) = 226.0254: dblElemVals(88, 2) = 0.0001
+ dblElemVals(89, 1) = 227.0278: dblElemVals(89, 2) = 0.00001
+ dblElemVals(90, 1) = 232.0381: dblElemVals(90, 2) = 0.0001
+ dblElemVals(91, 1) = 231.03588: dblElemVals(91, 2) = 0.00002
+ dblElemVals(92, 1) = 238.0289: dblElemVals(92, 2) = 0.0001
+ dblElemVals(93, 1) = 237.0482: dblElemVals(93, 2) = 0.0005
+ dblElemVals(94, 1) = 244.0642: dblElemVals(94, 2) = 0.0005
+ dblElemVals(95, 1) = 243.0614: dblElemVals(95, 2) = 0.0005
+ dblElemVals(96, 1) = 247.0703: dblElemVals(96, 2) = 0.0005
+ dblElemVals(97, 1) = 247.0703: dblElemVals(97, 2) = 0.0005
+ dblElemVals(98, 1) = 251.0796: dblElemVals(98, 2) = 0.0005
+ dblElemVals(99, 1) = 252.083: dblElemVals(99, 2) = 0.005
+ dblElemVals(100, 1) = 257.0951: dblElemVals(100, 2) = 0.0005
+ dblElemVals(101, 1) = 258.1: dblElemVals(101, 2) = 0.05
+ dblElemVals(102, 1) = 259.1009: dblElemVals(102, 2) = 0.0005
+ dblElemVals(103, 1) = 262.11: dblElemVals(103, 2) = 0.05
+
+ ' Unused elements
+ ' data 104,Unq,Unnilquadium,261,1, 105,Unp,Unnilpentium,262,1, 106,Unh,Unnilhexium,263,1
+ End Select
+
+ If intSpecificElement = 0 Then
+ ' Updating all the elements
+ For intElementIndex = 1 To ELEMENT_COUNT
+ With ElementStats(intElementIndex)
+ .Symbol = strElementNames(intElementIndex)
+ .Mass = dblElemVals(intElementIndex, 1)
+ .Uncertainty = dblElemVals(intElementIndex, 2)
+ .Charge = dblElemVals(intElementIndex, 3)
+
+ ElementAlph(intElementIndex) = .Symbol
+ End With
+ Next intElementIndex
+
+ ' Alphabatize ElementAlph() array via bubble sort
+ For intCompareIndex = ELEMENT_COUNT To 2 Step -1 ' Sort from end to start
+ For intIndex = 1 To intCompareIndex - 1
+ If ElementAlph(intIndex) > ElementAlph(intIndex + 1) Then
+ ' Swap them
+ strSwap = ElementAlph(intIndex)
+ ElementAlph(intIndex) = ElementAlph(intIndex + 1)
+ ElementAlph(intIndex + 1) = strSwap
+ End If
+ Next intIndex
+ Next intCompareIndex
+
+ Else
+ If intSpecificElement >= 1 And intSpecificElement <= ELEMENT_COUNT Then
+ With ElementStats(intSpecificElement)
+ Select Case eSpecificStatToReset
+ Case esMass
+ .Mass = dblElemVals(intSpecificElement, 1)
+ Case esUncertainty
+ .Uncertainty = dblElemVals(intSpecificElement, 2)
+ Case esCharge
+ .Charge = dblElemVals(intSpecificElement, 3)
+ Case Else
+ ' Ignore it
+ End Select
+ End With
+ End If
+ End If
+
+End Sub
+
+Private Sub MemoryLoadIsotopes()
+ ' Stores isotope information in ElementStats()
+
+ Dim intElementIndex As Integer, intIsotopeindex As Integer
+
+ ' The dblIsoMasses() array holds the mass of each isotope
+ ' starting with dblIsoMasses(x,1), dblIsoMasses(x, 2), etc.
+ Dim dblIsoMasses(ELEMENT_COUNT, MAX_ISOTOPES) As Double
+
+ ' The sngIsoAbun() array holds the isotopic abundances of each of the isotopes,
+ ' starting with sngIsoAbun(x,1) and corresponding to dblIsoMasses()
+ Dim sngIsoAbun(ELEMENT_COUNT, MAX_ISOTOPES) As Single
+
+ dblIsoMasses(1, 1) = 1.0078246: sngIsoAbun(1, 1) = 0.99985
+ dblIsoMasses(1, 2) = 2.014: sngIsoAbun(1, 2) = 0.00015
+ dblIsoMasses(2, 1) = 3.01603: sngIsoAbun(2, 1) = 0.00000137
+ dblIsoMasses(2, 2) = 4.0026029: sngIsoAbun(2, 2) = 0.99999863
+ dblIsoMasses(3, 1) = 6.01512: sngIsoAbun(3, 1) = 0.0759
+ dblIsoMasses(3, 2) = 7.016005: sngIsoAbun(3, 2) = 0.9241
+ dblIsoMasses(4, 1) = 9.012183: sngIsoAbun(4, 1) = 1
+ dblIsoMasses(5, 1) = 10.0129: sngIsoAbun(5, 1) = 0.199
+ dblIsoMasses(5, 2) = 11.009305: sngIsoAbun(5, 2) = 0.801
+ dblIsoMasses(6, 1) = 12: sngIsoAbun(6, 1) = 0.9893
+ dblIsoMasses(6, 2) = 13.00335: sngIsoAbun(6, 2) = 0.0107
+ dblIsoMasses(7, 1) = 14.003074: sngIsoAbun(7, 1) = 0.99632
+ dblIsoMasses(7, 2) = 15.00011: sngIsoAbun(7, 2) = 0.00368
+ dblIsoMasses(8, 1) = 15.994915: sngIsoAbun(8, 1) = 0.99757
+ dblIsoMasses(8, 2) = 16.999131: sngIsoAbun(8, 2) = 0.00038
+ dblIsoMasses(8, 3) = 17.99916: sngIsoAbun(8, 3) = 0.00205
+ dblIsoMasses(9, 1) = 18.9984032: sngIsoAbun(9, 1) = 1
+ dblIsoMasses(10, 1) = 19.992439: sngIsoAbun(10, 1) = 0.9048
+ dblIsoMasses(10, 2) = 20.99395: sngIsoAbun(10, 2) = 0.0027
+ dblIsoMasses(10, 3) = 21.99138: sngIsoAbun(10, 3) = 0.0925
+ dblIsoMasses(11, 1) = 22.98977: sngIsoAbun(11, 1) = 1
+ dblIsoMasses(12, 1) = 23.98505: sngIsoAbun(12, 1) = 0.7899
+ dblIsoMasses(12, 2) = 24.98584: sngIsoAbun(12, 2) = 0.1
+ dblIsoMasses(12, 3) = 25.98259: sngIsoAbun(12, 3) = 0.1101
+ dblIsoMasses(13, 1) = 26.981541: sngIsoAbun(13, 1) = 1
+ dblIsoMasses(14, 1) = 27.976928: sngIsoAbun(14, 1) = 0.922297
+ dblIsoMasses(14, 2) = 28.97649: sngIsoAbun(14, 2) = 0.046832
+ dblIsoMasses(14, 3) = 29.97376: sngIsoAbun(14, 3) = 0.030871
+ dblIsoMasses(15, 1) = 30.973763: sngIsoAbun(15, 1) = 1
+ dblIsoMasses(16, 1) = 31.972072: sngIsoAbun(16, 1) = 0.9493
+ dblIsoMasses(16, 2) = 32.97146: sngIsoAbun(16, 2) = 0.0076
+ dblIsoMasses(16, 3) = 33.96786: sngIsoAbun(16, 3) = 0.0429
+ dblIsoMasses(16, 4) = 35.96709: sngIsoAbun(16, 4) = 0.0002
+ dblIsoMasses(17, 1) = 34.968853: sngIsoAbun(17, 1) = 0.7578
+ dblIsoMasses(17, 2) = 36.99999: sngIsoAbun(17, 2) = 0.2422
+ dblIsoMasses(18, 1) = 35.96755: sngIsoAbun(18, 1) = 0.003365
+ dblIsoMasses(18, 2) = 37.96272: sngIsoAbun(18, 2) = 0.000632
+ dblIsoMasses(18, 3) = 39.96999: sngIsoAbun(18, 3) = 0.996003 ' Note: Alternate mass is 39.962383
+ dblIsoMasses(19, 1) = 38.963708: sngIsoAbun(19, 1) = 0.932581
+ dblIsoMasses(19, 2) = 39.963999: sngIsoAbun(19, 2) = 0.000117
+ dblIsoMasses(19, 3) = 40.961825: sngIsoAbun(19, 3) = 0.067302
+ dblIsoMasses(20, 1) = 39.962591: sngIsoAbun(20, 1) = 0.96941
+ dblIsoMasses(20, 2) = 41.958618: sngIsoAbun(20, 2) = 0.00647
+ dblIsoMasses(20, 3) = 42.958766: sngIsoAbun(20, 3) = 0.00135
+ dblIsoMasses(20, 4) = 43.95548: sngIsoAbun(20, 4) = 0.02086
+ dblIsoMasses(20, 5) = 45.953689: sngIsoAbun(20, 5) = 0.00004
+ dblIsoMasses(20, 6) = 47.952533: sngIsoAbun(20, 6) = 0.00187
+ dblIsoMasses(21, 1) = 44.959404: sngIsoAbun(21, 1) = 1 ' Note: Alternate mass is 44.955914
+ dblIsoMasses(22, 1) = 45.952629: sngIsoAbun(22, 1) = 0.0825
+ dblIsoMasses(22, 2) = 46.951764: sngIsoAbun(22, 2) = 0.0744
+ dblIsoMasses(22, 3) = 47.947947: sngIsoAbun(22, 3) = 0.7372
+ dblIsoMasses(22, 4) = 48.947871: sngIsoAbun(22, 4) = 0.0541
+ dblIsoMasses(22, 5) = 49.944792: sngIsoAbun(22, 5) = 0.0518
+ dblIsoMasses(23, 1) = 49.947161: sngIsoAbun(23, 1) = 0.0025
+ dblIsoMasses(23, 2) = 50.943963: sngIsoAbun(23, 2) = 0.9975
+ dblIsoMasses(24, 1) = 49.946046: sngIsoAbun(24, 1) = 0.04345
+ dblIsoMasses(24, 2) = 51.940509: sngIsoAbun(24, 2) = 0.83789
+ dblIsoMasses(24, 3) = 52.940651: sngIsoAbun(24, 3) = 0.09501
+ dblIsoMasses(24, 4) = 53.938882: sngIsoAbun(24, 4) = 0.02365
+ dblIsoMasses(25, 1) = 54.938046: sngIsoAbun(25, 1) = 1
+ dblIsoMasses(26, 1) = 53.939612: sngIsoAbun(26, 1) = 0.05845
+ dblIsoMasses(26, 2) = 55.934939: sngIsoAbun(26, 2) = 0.91754
+ dblIsoMasses(26, 3) = 56.935396: sngIsoAbun(26, 3) = 0.02119
+ dblIsoMasses(26, 4) = 57.933277: sngIsoAbun(26, 4) = 0.00282
+ dblIsoMasses(27, 1) = 58.933198: sngIsoAbun(27, 1) = 1
+ dblIsoMasses(28, 1) = 57.935347: sngIsoAbun(28, 1) = 0.680769
+ dblIsoMasses(28, 2) = 59.930788: sngIsoAbun(28, 2) = 0.262231
+ dblIsoMasses(28, 3) = 60.931058: sngIsoAbun(28, 3) = 0.011399
+ dblIsoMasses(28, 4) = 61.928346: sngIsoAbun(28, 4) = 0.036345
+ dblIsoMasses(28, 5) = 63.927968: sngIsoAbun(28, 5) = 0.009256
+ dblIsoMasses(29, 1) = 62.939598: sngIsoAbun(29, 1) = 0.6917 ' Note: Alternate mass is 62.929599
+ dblIsoMasses(29, 2) = 64.927793: sngIsoAbun(29, 2) = 0.3083
+ dblIsoMasses(30, 1) = 63.929145: sngIsoAbun(30, 1) = 0.4863
+ dblIsoMasses(30, 2) = 65.926034: sngIsoAbun(30, 2) = 0.279
+ dblIsoMasses(30, 3) = 66.927129: sngIsoAbun(30, 3) = 0.041
+ dblIsoMasses(30, 4) = 67.924846: sngIsoAbun(30, 4) = 0.1875
+ dblIsoMasses(30, 5) = 69.925325: sngIsoAbun(30, 5) = 0.0062
+ dblIsoMasses(31, 1) = 68.925581: sngIsoAbun(31, 1) = 0.60108
+ dblIsoMasses(31, 2) = 70.9247: sngIsoAbun(31, 2) = 0.39892
+ dblIsoMasses(32, 1) = 69.92425: sngIsoAbun(32, 1) = 0.2084
+ dblIsoMasses(32, 2) = 71.922079: sngIsoAbun(32, 2) = 0.2754
+ dblIsoMasses(32, 3) = 72.923463: sngIsoAbun(32, 3) = 0.0773
+ dblIsoMasses(32, 4) = 73.921177: sngIsoAbun(32, 4) = 0.3628
+ dblIsoMasses(32, 5) = 75.921401: sngIsoAbun(32, 5) = 0.0761
+ dblIsoMasses(33, 1) = 74.921596: sngIsoAbun(33, 1) = 1
+ dblIsoMasses(34, 1) = 73.922475: sngIsoAbun(34, 1) = 0.0089
+ dblIsoMasses(34, 2) = 75.919212: sngIsoAbun(34, 2) = 0.0937
+ dblIsoMasses(34, 3) = 76.919912: sngIsoAbun(34, 3) = 0.0763
+ dblIsoMasses(34, 4) = 77.919: sngIsoAbun(34, 4) = 0.2377
+ dblIsoMasses(34, 5) = 79.916521: sngIsoAbun(34, 5) = 0.4961
+ dblIsoMasses(34, 6) = 81.916698: sngIsoAbun(34, 6) = 0.0873
+ dblIsoMasses(35, 1) = 78.918336: sngIsoAbun(35, 1) = 0.5069
+ dblIsoMasses(35, 2) = 80.916289: sngIsoAbun(35, 2) = 0.4931
+ dblIsoMasses(36, 1) = 77.92: sngIsoAbun(36, 1) = 0.0035
+ dblIsoMasses(36, 2) = 79.91638: sngIsoAbun(36, 2) = 0.0228
+ dblIsoMasses(36, 3) = 81.913482: sngIsoAbun(36, 3) = 0.1158
+ dblIsoMasses(36, 4) = 82.914135: sngIsoAbun(36, 4) = 0.1149
+ dblIsoMasses(36, 5) = 83.911506: sngIsoAbun(36, 5) = 0.57
+ dblIsoMasses(36, 6) = 85.910616: sngIsoAbun(36, 6) = 0.173
+ dblIsoMasses(37, 1) = 84.911794: sngIsoAbun(37, 1) = 0.7217
+ dblIsoMasses(37, 2) = 86.909187: sngIsoAbun(37, 2) = 0.2783
+ dblIsoMasses(38, 1) = 83.91343: sngIsoAbun(38, 1) = 0.0056
+ dblIsoMasses(38, 2) = 85.909267: sngIsoAbun(38, 2) = 0.0986
+ dblIsoMasses(38, 3) = 86.908884: sngIsoAbun(38, 3) = 0.07
+ dblIsoMasses(38, 4) = 87.905625: sngIsoAbun(38, 4) = 0.8258
+ dblIsoMasses(39, 1) = 88.905856: sngIsoAbun(39, 1) = 1
+ dblIsoMasses(40, 1) = 89.904708: sngIsoAbun(40, 1) = 0.5145
+ dblIsoMasses(40, 2) = 90.905644: sngIsoAbun(40, 2) = 0.1122
+ dblIsoMasses(40, 3) = 91.905039: sngIsoAbun(40, 3) = 0.1715
+ dblIsoMasses(40, 4) = 93.906314: sngIsoAbun(40, 4) = 0.1738
+ dblIsoMasses(40, 5) = 95.908275: sngIsoAbun(40, 5) = 0.028
+ dblIsoMasses(41, 1) = 92.906378: sngIsoAbun(41, 1) = 1
+ dblIsoMasses(42, 1) = 91.906808: sngIsoAbun(42, 1) = 0.1484
+ dblIsoMasses(42, 2) = 93.905085: sngIsoAbun(42, 2) = 0.0925
+ dblIsoMasses(42, 3) = 94.90584: sngIsoAbun(42, 3) = 0.1592
+ dblIsoMasses(42, 4) = 95.904678: sngIsoAbun(42, 4) = 0.1668
+ dblIsoMasses(42, 5) = 96.90602: sngIsoAbun(42, 5) = 0.0955
+ dblIsoMasses(42, 6) = 97.905405: sngIsoAbun(42, 6) = 0.2413
+ dblIsoMasses(42, 7) = 99.907477: sngIsoAbun(42, 7) = 0.0963
+ dblIsoMasses(43, 1) = 97.9072: sngIsoAbun(43, 1) = 1
+ dblIsoMasses(44, 1) = 95.907599: sngIsoAbun(44, 1) = 0.0554
+ dblIsoMasses(44, 2) = 97.905287: sngIsoAbun(44, 2) = 0.0187
+ dblIsoMasses(44, 3) = 98.905939: sngIsoAbun(44, 3) = 0.1276
+ dblIsoMasses(44, 4) = 99.904219: sngIsoAbun(44, 4) = 0.126
+ dblIsoMasses(44, 5) = 100.905582: sngIsoAbun(44, 5) = 0.1706
+ dblIsoMasses(44, 6) = 101.904348: sngIsoAbun(44, 6) = 0.3155
+ dblIsoMasses(44, 7) = 103.905424: sngIsoAbun(44, 7) = 0.1862
+ dblIsoMasses(45, 1) = 102.905503: sngIsoAbun(45, 1) = 1
+ dblIsoMasses(46, 1) = 101.905634: sngIsoAbun(46, 1) = 0.0102
+ dblIsoMasses(46, 2) = 103.904029: sngIsoAbun(46, 2) = 0.1114
+ dblIsoMasses(46, 3) = 104.905079: sngIsoAbun(46, 3) = 0.2233
+ dblIsoMasses(46, 4) = 105.903475: sngIsoAbun(46, 4) = 0.2733
+ dblIsoMasses(46, 5) = 107.903895: sngIsoAbun(46, 5) = 0.2646
+ dblIsoMasses(46, 6) = 109.905167: sngIsoAbun(46, 6) = 0.1172
+ dblIsoMasses(47, 1) = 106.905095: sngIsoAbun(47, 1) = 0.51839
+ dblIsoMasses(47, 2) = 108.904757: sngIsoAbun(47, 2) = 0.48161
+ dblIsoMasses(48, 1) = 105.906461: sngIsoAbun(48, 1) = 0.0125
+ dblIsoMasses(48, 2) = 107.904176: sngIsoAbun(48, 2) = 0.0089
+ dblIsoMasses(48, 3) = 109.903005: sngIsoAbun(48, 3) = 0.1249
+ dblIsoMasses(48, 4) = 110.904182: sngIsoAbun(48, 4) = 0.128
+ dblIsoMasses(48, 5) = 111.902758: sngIsoAbun(48, 5) = 0.2413
+ dblIsoMasses(48, 6) = 112.9044: sngIsoAbun(48, 6) = 0.1222
+ dblIsoMasses(48, 7) = 113.903361: sngIsoAbun(48, 7) = 0.2873
+ dblIsoMasses(48, 8) = 115.904754: sngIsoAbun(48, 8) = 0.0749
+ dblIsoMasses(49, 1) = 112.904061: sngIsoAbun(49, 1) = 0.0429
+ dblIsoMasses(49, 2) = 114.903875: sngIsoAbun(49, 2) = 0.9571
+ dblIsoMasses(50, 1) = 111.904826: sngIsoAbun(50, 1) = 0.0097
+ dblIsoMasses(50, 2) = 113.902784: sngIsoAbun(50, 2) = 0.0066
+ dblIsoMasses(50, 3) = 114.903348: sngIsoAbun(50, 3) = 0.0034
+ dblIsoMasses(50, 4) = 115.901747: sngIsoAbun(50, 4) = 0.1454
+ dblIsoMasses(50, 5) = 116.902956: sngIsoAbun(50, 5) = 0.0768
+ dblIsoMasses(50, 6) = 117.901609: sngIsoAbun(50, 6) = 0.2422
+ dblIsoMasses(50, 7) = 118.90331: sngIsoAbun(50, 7) = 0.0859
+ dblIsoMasses(50, 8) = 119.902199: sngIsoAbun(50, 8) = 0.3258
+ dblIsoMasses(50, 9) = 121.90344: sngIsoAbun(50, 9) = 0.0463
+ dblIsoMasses(50, 10) = 123.905274: sngIsoAbun(50, 10) = 0.0579
+ dblIsoMasses(51, 1) = 120.903824: sngIsoAbun(51, 1) = 0.5721
+ dblIsoMasses(51, 2) = 122.904216: sngIsoAbun(51, 2) = 0.4279
+ dblIsoMasses(52, 1) = 119.904048: sngIsoAbun(52, 1) = 0.0009
+ dblIsoMasses(52, 2) = 121.903054: sngIsoAbun(52, 2) = 0.0255
+ dblIsoMasses(52, 3) = 122.904271: sngIsoAbun(52, 3) = 0.0089
+ dblIsoMasses(52, 4) = 123.902823: sngIsoAbun(52, 4) = 0.0474
+ dblIsoMasses(52, 5) = 124.904433: sngIsoAbun(52, 5) = 0.0707
+ dblIsoMasses(52, 6) = 125.903314: sngIsoAbun(52, 6) = 0.1884
+ dblIsoMasses(52, 7) = 127.904463: sngIsoAbun(52, 7) = 0.3174
+ dblIsoMasses(52, 8) = 129.906229: sngIsoAbun(52, 8) = 0.3408
+ dblIsoMasses(53, 1) = 126.904477: sngIsoAbun(53, 1) = 1
+ dblIsoMasses(54, 1) = 123.905894: sngIsoAbun(54, 1) = 0.0009
+ dblIsoMasses(54, 2) = 125.904281: sngIsoAbun(54, 2) = 0.0009
+ dblIsoMasses(54, 3) = 127.903531: sngIsoAbun(54, 3) = 0.0192
+ dblIsoMasses(54, 4) = 128.90478: sngIsoAbun(54, 4) = 0.2644
+ dblIsoMasses(54, 5) = 129.903509: sngIsoAbun(54, 5) = 0.0408
+ dblIsoMasses(54, 6) = 130.905072: sngIsoAbun(54, 6) = 0.2118
+ dblIsoMasses(54, 7) = 131.904148: sngIsoAbun(54, 7) = 0.2689
+ dblIsoMasses(54, 8) = 133.905395: sngIsoAbun(54, 8) = 0.1044
+ dblIsoMasses(54, 9) = 135.907214: sngIsoAbun(54, 9) = 0.0887
+ dblIsoMasses(55, 1) = 132.905433: sngIsoAbun(55, 1) = 1
+ dblIsoMasses(56, 1) = 129.906282: sngIsoAbun(56, 1) = 0.00106
+ dblIsoMasses(56, 2) = 131.905042: sngIsoAbun(56, 2) = 0.00101
+ dblIsoMasses(56, 3) = 133.904486: sngIsoAbun(56, 3) = 0.02417
+ dblIsoMasses(56, 4) = 134.905665: sngIsoAbun(56, 4) = 0.06592
+ dblIsoMasses(56, 5) = 135.904553: sngIsoAbun(56, 5) = 0.07854
+ dblIsoMasses(56, 6) = 136.905812: sngIsoAbun(56, 6) = 0.11232
+ dblIsoMasses(56, 7) = 137.905236: sngIsoAbun(56, 7) = 0.71698
+ dblIsoMasses(57, 1) = 137.907105: sngIsoAbun(57, 1) = 0.0009
+ dblIsoMasses(57, 2) = 138.906355: sngIsoAbun(57, 2) = 0.9991
+ dblIsoMasses(58, 1) = 135.90714: sngIsoAbun(58, 1) = 0.00185
+ dblIsoMasses(58, 2) = 137.905985: sngIsoAbun(58, 2) = 0.00251
+ dblIsoMasses(58, 3) = 139.905442: sngIsoAbun(58, 3) = 0.8845
+ dblIsoMasses(58, 4) = 141.909241: sngIsoAbun(58, 4) = 0.11114
+ dblIsoMasses(59, 1) = 140.907657: sngIsoAbun(59, 1) = 1
+ dblIsoMasses(60, 1) = 141.907731: sngIsoAbun(60, 1) = 0.272
+ dblIsoMasses(60, 2) = 142.90981: sngIsoAbun(60, 2) = 0.122
+ dblIsoMasses(60, 3) = 143.910083: sngIsoAbun(60, 3) = 0.238
+ dblIsoMasses(60, 4) = 144.91257: sngIsoAbun(60, 4) = 0.083
+ dblIsoMasses(60, 5) = 145.913113: sngIsoAbun(60, 5) = 0.172
+ dblIsoMasses(60, 6) = 147.916889: sngIsoAbun(60, 6) = 0.057
+ dblIsoMasses(60, 7) = 149.920887: sngIsoAbun(60, 7) = 0.056
+ dblIsoMasses(61, 1) = 144.9127: sngIsoAbun(61, 1) = 1
+ dblIsoMasses(62, 1) = 143.911998: sngIsoAbun(62, 1) = 0.0307
+ dblIsoMasses(62, 2) = 146.914895: sngIsoAbun(62, 2) = 0.1499
+ dblIsoMasses(62, 3) = 147.91482: sngIsoAbun(62, 3) = 0.1124
+ dblIsoMasses(62, 4) = 148.917181: sngIsoAbun(62, 4) = 0.1382
+ dblIsoMasses(62, 5) = 149.917273: sngIsoAbun(62, 5) = 0.0738
+ dblIsoMasses(62, 6) = 151.919741: sngIsoAbun(62, 6) = 0.2675
+ dblIsoMasses(62, 7) = 153.922206: sngIsoAbun(62, 7) = 0.2275
+ dblIsoMasses(63, 1) = 150.919847: sngIsoAbun(63, 1) = 0.4781
+ dblIsoMasses(63, 2) = 152.921243: sngIsoAbun(63, 2) = 0.5219
+ dblIsoMasses(64, 1) = 151.919786: sngIsoAbun(64, 1) = 0.002
+ dblIsoMasses(64, 2) = 153.920861: sngIsoAbun(64, 2) = 0.0218
+ dblIsoMasses(64, 3) = 154.922618: sngIsoAbun(64, 3) = 0.148
+ dblIsoMasses(64, 4) = 155.922118: sngIsoAbun(64, 4) = 0.2047
+ dblIsoMasses(64, 5) = 156.923956: sngIsoAbun(64, 5) = 0.1565
+ dblIsoMasses(64, 6) = 157.924111: sngIsoAbun(64, 6) = 0.2484
+ dblIsoMasses(64, 7) = 159.927049: sngIsoAbun(64, 7) = 0.2186
+ dblIsoMasses(65, 1) = 158.92535: sngIsoAbun(65, 1) = 1
+ dblIsoMasses(66, 1) = 155.925277: sngIsoAbun(66, 1) = 0.0006
+ dblIsoMasses(66, 2) = 157.924403: sngIsoAbun(66, 2) = 0.001
+ dblIsoMasses(66, 3) = 159.925193: sngIsoAbun(66, 3) = 0.0234
+ dblIsoMasses(66, 4) = 160.92693: sngIsoAbun(66, 4) = 0.1891
+ dblIsoMasses(66, 5) = 161.926795: sngIsoAbun(66, 5) = 0.2551
+ dblIsoMasses(66, 6) = 162.928728: sngIsoAbun(66, 6) = 0.249
+ dblIsoMasses(66, 7) = 163.929183: sngIsoAbun(66, 7) = 0.2818
+ dblIsoMasses(67, 1) = 164.930332: sngIsoAbun(67, 1) = 1
+ dblIsoMasses(68, 1) = 161.928775: sngIsoAbun(68, 1) = 0.0014
+ dblIsoMasses(68, 2) = 163.929198: sngIsoAbun(68, 2) = 0.0161
+ dblIsoMasses(68, 3) = 165.930305: sngIsoAbun(68, 3) = 0.3361
+ dblIsoMasses(68, 4) = 166.932046: sngIsoAbun(68, 4) = 0.2293
+ dblIsoMasses(68, 5) = 167.932368: sngIsoAbun(68, 5) = 0.2678
+ dblIsoMasses(68, 6) = 169.935461: sngIsoAbun(68, 6) = 0.1493
+ dblIsoMasses(69, 1) = 168.934225: sngIsoAbun(69, 1) = 1
+ dblIsoMasses(70, 1) = 167.932873: sngIsoAbun(70, 1) = 0.0013
+ dblIsoMasses(70, 2) = 169.934759: sngIsoAbun(70, 2) = 0.0304
+ dblIsoMasses(70, 3) = 170.936323: sngIsoAbun(70, 3) = 0.1428
+ dblIsoMasses(70, 4) = 171.936387: sngIsoAbun(70, 4) = 0.2183
+ dblIsoMasses(70, 5) = 172.938208: sngIsoAbun(70, 5) = 0.1613
+ dblIsoMasses(70, 6) = 173.938873: sngIsoAbun(70, 6) = 0.3183
+ dblIsoMasses(70, 7) = 175.942564: sngIsoAbun(70, 7) = 0.1276
+ dblIsoMasses(71, 1) = 174.940785: sngIsoAbun(71, 1) = 0.9741
+ dblIsoMasses(71, 2) = 175.942679: sngIsoAbun(71, 2) = 0.0259
+ dblIsoMasses(72, 1) = 173.94004: sngIsoAbun(72, 1) = 0.0016
+ dblIsoMasses(72, 2) = 175.941406: sngIsoAbun(72, 2) = 0.0526
+ dblIsoMasses(72, 3) = 176.943217: sngIsoAbun(72, 3) = 0.186
+ dblIsoMasses(72, 4) = 177.943696: sngIsoAbun(72, 4) = 0.2728
+ dblIsoMasses(72, 5) = 178.945812: sngIsoAbun(72, 5) = 0.1362
+ dblIsoMasses(72, 6) = 179.946561: sngIsoAbun(72, 6) = 0.3508
+ dblIsoMasses(73, 1) = 179.947462: sngIsoAbun(73, 1) = 0.00012
+ dblIsoMasses(73, 2) = 180.948014: sngIsoAbun(73, 2) = 0.99988
+ dblIsoMasses(74, 1) = 179.946701: sngIsoAbun(74, 1) = 0.0012
+ dblIsoMasses(74, 2) = 181.948202: sngIsoAbun(74, 2) = 0.265
+ dblIsoMasses(74, 3) = 182.95022: sngIsoAbun(74, 3) = 0.1431
+ dblIsoMasses(74, 4) = 183.950953: sngIsoAbun(74, 4) = 0.3064
+ dblIsoMasses(74, 5) = 185.954357: sngIsoAbun(74, 5) = 0.2843
+ dblIsoMasses(75, 1) = 184.952951: sngIsoAbun(75, 1) = 0.374
+ dblIsoMasses(75, 2) = 186.955765: sngIsoAbun(75, 2) = 0.626
+ dblIsoMasses(76, 1) = 183.952488: sngIsoAbun(76, 1) = 0.0002
+ dblIsoMasses(76, 2) = 185.95383: sngIsoAbun(76, 2) = 0.0159
+ dblIsoMasses(76, 3) = 186.955741: sngIsoAbun(76, 3) = 0.0196
+ dblIsoMasses(76, 4) = 187.95586: sngIsoAbun(76, 4) = 0.1324
+ dblIsoMasses(76, 5) = 188.958137: sngIsoAbun(76, 5) = 0.1615
+ dblIsoMasses(76, 6) = 189.958436: sngIsoAbun(76, 6) = 0.2626
+ dblIsoMasses(76, 7) = 191.961467: sngIsoAbun(76, 7) = 0.4078 ' Note: Alternate mass is 191.960603
+ dblIsoMasses(77, 1) = 190.960584: sngIsoAbun(77, 1) = 0.373
+ dblIsoMasses(77, 2) = 192.962942: sngIsoAbun(77, 2) = 0.627
+ dblIsoMasses(78, 1) = 189.959917: sngIsoAbun(78, 1) = 0.00014
+ dblIsoMasses(78, 2) = 191.961019: sngIsoAbun(78, 2) = 0.00782
+ dblIsoMasses(78, 3) = 193.962655: sngIsoAbun(78, 3) = 0.32967
+ dblIsoMasses(78, 4) = 194.964785: sngIsoAbun(78, 4) = 0.33832
+ dblIsoMasses(78, 5) = 195.964926: sngIsoAbun(78, 5) = 0.25242
+ dblIsoMasses(78, 6) = 197.967869: sngIsoAbun(78, 6) = 0.07163
+ dblIsoMasses(79, 1) = 196.966543: sngIsoAbun(79, 1) = 1
+ dblIsoMasses(80, 1) = 195.965807: sngIsoAbun(80, 1) = 0.0015
+ dblIsoMasses(80, 2) = 197.966743: sngIsoAbun(80, 2) = 0.0997
+ dblIsoMasses(80, 3) = 198.968254: sngIsoAbun(80, 3) = 0.1687
+ dblIsoMasses(80, 4) = 199.9683: sngIsoAbun(80, 4) = 0.231
+ dblIsoMasses(80, 5) = 200.970277: sngIsoAbun(80, 5) = 0.1318
+ dblIsoMasses(80, 6) = 201.970632: sngIsoAbun(80, 6) = 0.2986
+ dblIsoMasses(80, 7) = 203.973467: sngIsoAbun(80, 7) = 0.0687
+ dblIsoMasses(81, 1) = 202.97232: sngIsoAbun(81, 1) = 0.29524
+ dblIsoMasses(81, 2) = 204.974401: sngIsoAbun(81, 2) = 0.70476
+ dblIsoMasses(82, 1) = 203.97302: sngIsoAbun(82, 1) = 0.014
+ dblIsoMasses(82, 2) = 205.97444: sngIsoAbun(82, 2) = 0.241
+ dblIsoMasses(82, 3) = 206.975872: sngIsoAbun(82, 3) = 0.221
+ dblIsoMasses(82, 4) = 207.976641: sngIsoAbun(82, 4) = 0.524
+ dblIsoMasses(83, 1) = 208.980388: sngIsoAbun(83, 1) = 1
+ dblIsoMasses(84, 1) = 209: sngIsoAbun(84, 1) = 1
+ dblIsoMasses(85, 1) = 210: sngIsoAbun(85, 1) = 1
+ dblIsoMasses(86, 1) = 222: sngIsoAbun(86, 1) = 1
+ dblIsoMasses(87, 1) = 223: sngIsoAbun(87, 1) = 1
+ dblIsoMasses(88, 1) = 226: sngIsoAbun(88, 1) = 1
+ dblIsoMasses(89, 1) = 227: sngIsoAbun(89, 1) = 1
+ dblIsoMasses(90, 1) = 232.038054: sngIsoAbun(90, 1) = 1
+ dblIsoMasses(91, 1) = 231: sngIsoAbun(91, 1) = 1
+ dblIsoMasses(92, 1) = 234.041637: sngIsoAbun(92, 1) = 0.000055
+ dblIsoMasses(92, 2) = 235.043924: sngIsoAbun(92, 2) = 0.0072
+ dblIsoMasses(92, 3) = 238.050786: sngIsoAbun(92, 3) = 0.992745
+ dblIsoMasses(93, 1) = 237: sngIsoAbun(93, 1) = 1
+ dblIsoMasses(94, 1) = 244: sngIsoAbun(94, 1) = 1
+ dblIsoMasses(95, 1) = 243: sngIsoAbun(95, 1) = 1
+ dblIsoMasses(96, 1) = 247: sngIsoAbun(96, 1) = 1
+ dblIsoMasses(97, 1) = 247: sngIsoAbun(97, 1) = 1
+ dblIsoMasses(98, 1) = 251: sngIsoAbun(98, 1) = 1
+ dblIsoMasses(99, 1) = 252: sngIsoAbun(99, 1) = 1
+ dblIsoMasses(100, 1) = 257: sngIsoAbun(100, 1) = 1
+ dblIsoMasses(101, 1) = 258: sngIsoAbun(101, 1) = 1
+ dblIsoMasses(102, 1) = 259: sngIsoAbun(102, 1) = 1
+ dblIsoMasses(103, 1) = 262: sngIsoAbun(103, 1) = 1
+
+ ' Note: I chose to store the desired values in the dblIsoMasses() and sngIsoAbun() 2D arrays
+ ' then copy to the ElementStats() array since this method actually decreases
+ ' the size of this subroutine
+ For intElementIndex = 1 To ELEMENT_COUNT
+ With ElementStats(intElementIndex)
+ intIsotopeindex = 1
+ Do While dblIsoMasses(intElementIndex, intIsotopeindex) > 0
+ .Isotopes(intIsotopeindex).Abundance = sngIsoAbun(intElementIndex, intIsotopeindex)
+ .Isotopes(intIsotopeindex).Mass = dblIsoMasses(intElementIndex, intIsotopeindex)
+ intIsotopeindex = intIsotopeindex + 1
+ If intIsotopeindex > MAX_ISOTOPES Then Exit Do
+ Loop
+ .IsotopeCount = intIsotopeindex - 1
+ End With
+ Next intElementIndex
+End Sub
+
+Public Sub MemoryLoadMessageStatements()
+
+ MessageStatmentCount = 1555
+
+ MessageStatements(1) = "Unknown element"
+ MessageStatements(2) = "Obsolete msg: Cannot handle more than 4 layers of embedded parentheses"
+ MessageStatements(3) = "Missing closing parentheses"
+ MessageStatements(4) = "Unmatched parentheses"
+ MessageStatements(5) = "Cannot have a 0 directly after an element or dash (-)"
+ MessageStatements(6) = "Number too large or must only be after [, -, ), or caret (^)"
+ MessageStatements(7) = "Number too large"
+ MessageStatements(8) = "Obsolete msg: Cannot start formula with a number; use parentheses, brackets, or dash (-)"
+ MessageStatements(9) = "Obsolete msg: Decimal numbers cannot be used after parentheses; use a [ or a caret (^)"
+ MessageStatements(10) = "Obsolete msg: Decimal numbers less than 1 must be in the form .5 and not 0.5"
+ MessageStatements(11) = "Numbers should follow left brackets, not right brackets (unless 'treat brackets' as parentheses is on)"
+ MessageStatements(12) = "A number must be present after a bracket and/or after the decimal point"
+ MessageStatements(13) = "Missing closing bracket, ]"
+ MessageStatements(14) = "Misplaced number; should only be after an element, [, ), -, or caret (^)"
+ MessageStatements(15) = "Unmatched bracket"
+ MessageStatements(16) = "Cannot handle nested brackets or brackets inside multiple hydrates (unless 'treat brackets as parentheses' is on)"
+ MessageStatements(17) = "Obsolete msg: Cannot handle multiple hydrates (extras) in brackets"
+ MessageStatements(18) = "Unknown element "
+ MessageStatements(19) = "Obsolete msg: Cannot start formula with a dash (-)"
+ MessageStatements(20) = "There must be an isotopic mass number following the caret (^)"
+ MessageStatements(21) = "Obsolete msg: Zero after caret (^); an isotopic mass of zero is not allowed"
+ MessageStatements(22) = "An element must be present after the isotopic mass after the caret (^)"
+ MessageStatements(23) = "Negative isotopic masses are not allowed after the caret (^)"
+ MessageStatements(24) = "Isotopic masses are not allowed for abbreviations"
+ MessageStatements(25) = "An element must be present after the leading coefficient of the dash"
+ MessageStatements(26) = "Isotopic masses are not allowed for abbreviations; D is an abbreviation"
+ MessageStatements(27) = "Numbers cannot contain more than one decimal point"
+ MessageStatements(28) = "Circular abbreviation reference; can't have an abbreviation referencing a second abbreviation that depends upon the first one"
+ MessageStatements(29) = "Obsolete msg: Cannot run percent solver until one or more lines are locked to a value."
+ MessageStatements(30) = "Invalid formula subtraction; one or more atoms (or too many atoms) in the right-hand formula are missing (or less abundant) in the left-hand formula"
+
+ ' Cases 50 through 74 are used during the % Solver routine
+ MessageStatements(50) = "Target value is greater than 100%, an impossible value."
+
+ ' Cases 75 through 99 are used in frmCalculator
+ MessageStatements(75) = "Letters are not allowed in the calculator line"
+ MessageStatements(76) = "Missing closing parenthesis"
+ MessageStatements(77) = "Unmatched parentheses"
+ MessageStatements(78) = "Misplaced number; or number too large, too small, or too long"
+ MessageStatements(79) = "Obsolete msg: Misplaced parentheses"
+ MessageStatements(80) = "Misplaced operator"
+ MessageStatements(81) = "Track variable is less than or equal to 1; program bug; please notify programmer"
+ MessageStatements(82) = "Missing operator. Note: ( is not needed OR allowed after a + or -"
+ MessageStatements(83) = "Obsolete msg: Brackets not allowed in calculator; simply use nested parentheses"
+ MessageStatements(84) = "Obsolete msg: Decimal numbers less than 1 must be in the form .5 and not 0.5"
+ MessageStatements(85) = "Cannot take negative numbers to a decimal power"
+ MessageStatements(86) = "Cannot take zero to a negative power"
+ MessageStatements(87) = "Cannot take zero to the zeroth power"
+ MessageStatements(88) = "Obsolete msg: Only a single positive or negative number is allowed after a caret (^)"
+ MessageStatements(89) = "A single positive or negative number must be present after a caret (^)"
+ MessageStatements(90) = "Numbers cannot contain more than one decimal point"
+ MessageStatements(91) = "You tried to divide a number by zero. Please correct the problem and recalculate."
+ MessageStatements(92) = "Spaces are not allowed in mathematical expressions"
+
+ ' Note that tags 93 and 94 are also used on frmMain
+ MessageStatements(93) = "Use a period for a decimal point"
+ MessageStatements(94) = "Use a comma for a decimal point"
+ MessageStatements(95) = "A number must be present after a decimal point"
+
+
+ ' Cases 100 and up are shown when loading data from files and starting application
+ MessageStatements(100) = "Error Saving Abbreviation File"
+ MessageStatements(110) = "The default abbreviation file has been re-created."
+ MessageStatements(115) = "The old file has been renamed"
+ MessageStatements(120) = "[AMINO ACIDS] heading not found in MWT_ABBR.DAT file. This heading must be located before/above the [ABBREVIATIONS] heading."
+ MessageStatements(125) = "Obsolete msg: Select OK to continue without any abbreviations."
+ MessageStatements(130) = "[ABBREVIATIONS] heading not found in MWT_ABBR.DAT file. This heading must be located before/above the [AMINO ACIDS] heading."
+ MessageStatements(135) = "Select OK to continue with amino acids abbreviations only."
+ MessageStatements(140) = "The Abbreviations File was not found in the program directory"
+ MessageStatements(150) = "Error Loading/Creating Abbreviation File"
+ MessageStatements(160) = "Ignoring Abbreviation -- Invalid Formula"
+ MessageStatements(170) = "Ignoring Duplicate Abbreviation"
+ MessageStatements(180) = "Ignoring Abbreviation; Invalid Character"
+ MessageStatements(190) = "Ignoring Abbreviation; too long"
+ MessageStatements(192) = "Ignoring Abbreviation; symbol length cannot be 0"
+ MessageStatements(194) = "Ignoring Abbreviation; symbol most only contain letters"
+ MessageStatements(196) = "Ignoring Abbreviation; Too many abbreviations in memory"
+ MessageStatements(200) = "Ignoring Invalid Line"
+ MessageStatements(210) = "The default elements file has been re-created."
+ MessageStatements(220) = "Possibly incorrect weight for element"
+ MessageStatements(230) = "Possibly incorrect uncertainty for element"
+ MessageStatements(250) = "Ignoring Line; Invalid Element Symbol"
+ MessageStatements(260) = "[ELEMENTS] heading not found in MWT_ELEM.DAT file. This heading must be located in the file."
+ MessageStatements(265) = "Select OK to continue with default Element values."
+ MessageStatements(270) = "The Elements File was not found in the program directory"
+ MessageStatements(280) = "Error Loading/Creating Elements File"
+ MessageStatements(305) = "Continuing with default captions."
+ MessageStatements(320) = "Error Saving Elements File"
+ MessageStatements(330) = "Error Loading/Creating Values File"
+ MessageStatements(340) = "Select OK to continue without loading default Values and Formulas."
+ MessageStatements(345) = "If using a Read-Only drive, use the /X switch at the command line to prevent this error."
+ MessageStatements(350) = "Error"
+ MessageStatements(360) = "Error Saving Default Options File"
+ MessageStatements(370) = "Obsolete msg: If using a Read-Only drive, you cannot save the default options."
+ MessageStatements(380) = "Error Saving Values and Formulas File"
+ MessageStatements(390) = "Obsolete msg: If using a Read-Only drive, you cannot save the values and formulas."
+ MessageStatements(400) = "Error Loading/Creating Default Options File"
+ MessageStatements(410) = "Select OK to continue without loading User Defaults."
+ MessageStatements(420) = "Obsolete msg: The Default Options file was corrupted; it will be re-created."
+ MessageStatements(430) = "Obsolete msg: The Values and Formulas file was corrupted; it will be re-created."
+ MessageStatements(440) = "The language file could not be successfully opened or was formatted incorrectly."
+ MessageStatements(450) = "Unable to load language-specific captions"
+ MessageStatements(460) = "The language file could not be found in the program directory"
+ MessageStatements(470) = "The file requested for molecular weight processing was not found"
+ MessageStatements(480) = "File Not Found"
+ MessageStatements(490) = "This file already exists. Replace it?"
+ MessageStatements(500) = "File Exists"
+ MessageStatements(510) = "Error Reading/Writing files for batch processing"
+ MessageStatements(515) = "Select OK to abort batch file processing."
+ MessageStatements(520) = "Error in program"
+ MessageStatements(530) = "These lines of code should not have been encountered. Please notify programmer."
+ MessageStatements(540) = "Obsolete msg: You can't edit elements because the /X switch was used at the command line."
+ MessageStatements(545) = "Obsolete msg: You can't edit abbreviations because the /X switch was used at the command line."
+ MessageStatements(550) = "Percent solver cannot be used when brackets are being treated as parentheses. You can change the bracket recognition mode by choosing Change Program Preferences under the Options menu."
+ MessageStatements(555) = "Percent Solver not Available"
+ MessageStatements(560) = "Maximum number of formula fields exist."
+ MessageStatements(570) = "Current formula is blank."
+ MessageStatements(580) = "Turn off Percent Solver (F11) before creating a new formula."
+ MessageStatements(590) = "An overflow error has occured. Please reduce number sizes and recalculate."
+ MessageStatements(600) = "An error has occured"
+ MessageStatements(605) = "Please exit the program and report the error to the programmer. Select About from the Help menu to see the E-mail address."
+ MessageStatements(610) = "Spaces are not allowed in formulas"
+ MessageStatements(620) = "Invalid Character"
+ MessageStatements(630) = "Cannot copy to new formula."
+ MessageStatements(645) = "Obsolete msg: Maximum number of formulas is 7"
+ MessageStatements(650) = "Current formula is blank."
+ MessageStatements(655) = "Percent Solver mode is on (F11 to exit mode)."
+ MessageStatements(660) = "Warning, isotopic mass is probably too large for element"
+ MessageStatements(662) = "Warning, isotopic mass is probably too small for element"
+ MessageStatements(665) = "vs avg atomic wt of"
+ MessageStatements(670) = "Warning, isotopic mass is impossibly small for element"
+ MessageStatements(675) = "protons"
+ MessageStatements(680) = "Note: Exact Mode is on"
+ MessageStatements(685) = "Note: for % Solver, a left bracket must precede an x"
+ MessageStatements(690) = "Note: brackets are being treated as parentheses"
+ MessageStatements(700) = "One or more elements must be checked."
+ MessageStatements(705) = "Maximum hits must be greater than 0."
+ MessageStatements(710) = "Maximum hits must be less than "
+ MessageStatements(715) = "Minimum number of elements must be 0 or greater."
+ MessageStatements(720) = "Minimum number of elements must be less than maximum number of elements."
+ MessageStatements(725) = "Maximum number of elements must be less than 65,025"
+ MessageStatements(730) = "An atomic weight must be entered for custom elements."
+ MessageStatements(735) = "Atomic Weight must be greater than 0 for custom elements."
+ MessageStatements(740) = "Target molecular weight must be entered."
+ MessageStatements(745) = "Target molecular weight must be greater than 0."
+ MessageStatements(750) = "Obsolete msg: Weight tolerance must be 0 or greater."
+ MessageStatements(755) = "A maximum molecular weight must be entered."
+ MessageStatements(760) = "Maximum molecular weight must be greater than 0."
+ MessageStatements(765) = "Target percentages must be entered for element"
+ MessageStatements(770) = "Target percentage must be greater than 0."
+ MessageStatements(775) = "Custom elemental weights must contain only numbers or only letters. If letters are used, they must be for a single valid elemental symbol or abbreviation."
+ MessageStatements(780) = "Custom elemental weight is empty. If letters are used, they must be for a single valid elemental symbol or abbreviation."
+ MessageStatements(785) = "Unknown element or abbreviation for custom elemental weight"
+ MessageStatements(790) = "Only single elemental symbols or abbreviations are allowed."
+ MessageStatements(800) = "Caution, no abbreviations were loaded -- Command has no effect."
+ MessageStatements(805) = "Cannot handle fractional numbers of atoms"
+ MessageStatements(910) = "Ions are already present in the ion list. Replace with new ions?"
+ MessageStatements(920) = "Replace Existing Ions"
+ MessageStatements(930) = "Loading Ion List"
+ MessageStatements(940) = "Process aborted"
+ MessageStatements(945) = " aborted"
+ MessageStatements(950) = "Normalizing ions"
+ MessageStatements(960) = "Normalizing by region"
+ MessageStatements(965) = "Sorting by Intensity"
+ MessageStatements(970) = "Matching Ions"
+ MessageStatements(980) = "The clipboard is empty. No ions to paste."
+ MessageStatements(985) = "No ions"
+ MessageStatements(990) = "Pasting ion list"
+ MessageStatements(1000) = "Determining number of ions in list"
+ MessageStatements(1010) = "Parsing list"
+ MessageStatements(1020) = "No valid ions were found on the clipboard. A valid ion list is a list of mass and intensity pairs, separated by commas, tabs, or spaces. One mass/intensity pair should be present per line."
+
+ MessageStatements(1030) = "Error writing data to file"
+ MessageStatements(1040) = "Set Range"
+ MessageStatements(1050) = "Start Val"
+ MessageStatements(1055) = "End Val"
+ MessageStatements(1060) = "Set X Axis Range"
+ MessageStatements(1065) = "Set Y Axis Range"
+ MessageStatements(1070) = "Enter a new Gaussian Representation quality factor. Higher numbers result in smoother Gaussian curves, but slower updates. Valid range is 1 to 50, default is 20."
+ MessageStatements(1072) = "Gaussian Representation Quality"
+ MessageStatements(1075) = "Enter a new plotting approximation factor. Higher numbers result in faster updates, but give a less accurate graphical representation when viewing a wide mass range (zoomed out). Valid range is 1 to 50, default is 10."
+ MessageStatements(1077) = "Plotting Approximation Factor"
+ MessageStatements(1080) = "Resolving Power Specifications"
+ MessageStatements(1090) = "Resolving Power"
+ MessageStatements(1100) = "X Value of Specification"
+ MessageStatements(1110) = "Please enter the approximate number of ticks to show on the axis"
+ MessageStatements(1115) = "Axis Ticks"
+ MessageStatements(1120) = "Creating Gaussian Representation"
+ MessageStatements(1130) = "Preparing plot"
+ MessageStatements(1135) = "Drawing plot"
+ MessageStatements(1140) = "Are you sure you want to restore the default plotting options?"
+ MessageStatements(1145) = "Restore Default Options"
+ MessageStatements(1150) = "Auto Align Ions"
+ MessageStatements(1155) = "Maximum Offset"
+ MessageStatements(1160) = "Offset Increment"
+ MessageStatements(1165) = "Aligning Ions"
+
+ MessageStatements(1200) = "Caution symbol must be 1 to " & MAX_ABBREV_LENGTH & " characters long"
+ MessageStatements(1205) = "Caution symbol most only contain letters"
+ MessageStatements(1210) = "Caution description length cannot be 0"
+ MessageStatements(1215) = "Too many caution statements. Unable to add another one."
+
+ MessageStatements(1500) = "All Files"
+ MessageStatements(1510) = "Text Files"
+ MessageStatements(1515) = "txt"
+ MessageStatements(1520) = "Data Files"
+ MessageStatements(1525) = "csv"
+ MessageStatements(1530) = "Sequence Files"
+ MessageStatements(1535) = "seq"
+ MessageStatements(1540) = "Ion List Files"
+ MessageStatements(1545) = "txt"
+ MessageStatements(1550) = "Capillary Flow Info Files"
+ MessageStatements(1555) = "cap"
+
+End Sub
+
+Private Sub MwtWinDllErrorHandler(strSourceForm As String)
+ Dim strMessage As String
+ Dim blnShowErrorMessageDialogsSaved As Boolean
+
+ If Err.Number = 6 Then
+ MsgBox LookupMessage(590), vbOKOnly + vbExclamation, LookupMessage(350)
+ Else
+ strMessage = LookupMessage(600) & ": " & Err.Description & vbCrLf & _
+ " (" & strSourceForm & " handler)"
+ strMessage = strMessage & vbCrLf & LookupMessage(605)
+ MsgBox strMessage, vbOKOnly + vbExclamation, LookupMessage(350)
+
+ blnShowErrorMessageDialogsSaved = mShowErrorMessageDialogs
+ mShowErrorMessageDialogs = False
+
+ ' Call GeneralErrorHandler so that the error gets logged to ErrorLog.txt
+ GeneralErrorHandler strSourceForm, Err.Number
+
+ mShowErrorMessageDialogs = blnShowErrorMessageDialogsSaved
+
+ End If
+End Sub
+
+Private Sub InitializeAbbrevSymbolStack(ByRef udtAbbrevSymbolStack As udtAbbrevSymbolStackType)
+ With udtAbbrevSymbolStack
+ .Count = 0
+ ReDim .SymbolReferenceStack(0)
+ End With
+End Sub
+
+Private Sub InitializeComputationStats(ByRef udtComputationStats As udtComputationStatsType)
+ Dim intElementIndex As Integer
+
+ With udtComputationStats
+ .Charge = 0!
+ .StandardDeviation = 0#
+ .TotalMass = 0#
+
+ For intElementIndex = 0 To ELEMENT_COUNT
+ With .Elements(intElementIndex)
+ .Used = False ' whether element is present
+ .Count = 0 ' # of each element
+ .IsotopicCorrection = 0 ' isotopic correction
+ .IsotopeCount = 0 ' Count of the number of atoms defined as specific isotopes
+ ReDim .Isotopes(2) ' Default to have room for 2 explicitly defined isotopes
+ End With
+ Next intElementIndex
+ End With
+
+End Sub
+
+Public Function ParseFormulaPublic(ByRef strFormula As String, ByRef udtComputationStats As udtComputationStatsType, Optional blnExpandAbbreviations As Boolean = False, Optional dblValueForX As Double = 1#) As Double
+ ' Determines the molecular weight and elemental composition of strFormula
+ ' Returns the computed molecular weight if no error; otherwise, returns -1
+ ' ErrorParams will hold information on errors that occur (previous errors are cleared when this function is called)
+ ' Returns other useful information in udtComputationStats()
+ ' Use ComputeFormulaWeight if you only want to know the weight of a formula (it calls this function)
+
+ Dim intElementIndex As Integer
+ Dim dblStdDevSum As Double
+ Dim udtAbbrevSymbolStack As udtAbbrevSymbolStackType
+
+On Error GoTo ParseFormulaPublicErrorHandler
+
+ InitializeComputationStats udtComputationStats
+ InitializeAbbrevSymbolStack udtAbbrevSymbolStack
+
+ dblStdDevSum = 0#
+
+ ' Reset ErrorParams to clear any prior errors
+ ResetErrorParamsInternal
+
+ ' Reset Caution Description
+ mStrCautionDescription = ""
+
+ If Len(strFormula) > 0 Then
+ strFormula = ParseFormulaRecursive(strFormula, udtComputationStats, udtAbbrevSymbolStack, blnExpandAbbreviations, dblStdDevSum, dblValueForX)
+ End If
+
+ ' Copy udtComputationStats to mComputationStatsSaved
+ mComputationStatsSaved = udtComputationStats
+
+ If ErrorParams.ErrorID = 0 Then
+ With udtComputationStats
+
+ ' Compute the standard deviation
+ .StandardDeviation = Sqr(dblStdDevSum)
+
+ ' Compute the total molecular weight
+ .TotalMass = 0 ' Reset total weight of compound to 0 so we can add to it
+ For intElementIndex = 1 To ELEMENT_COUNT
+ ' Increase total weight by multipling the count of each element by the element's mass
+ ' In addition, add in the Isotopic Correction value
+ .TotalMass = .TotalMass + _
+ ElementStats(intElementIndex).Mass * .Elements(intElementIndex).Count + _
+ .Elements(intElementIndex).IsotopicCorrection
+ Next intElementIndex
+ End With
+ ParseFormulaPublic = udtComputationStats.TotalMass
+ Else
+ ParseFormulaPublic = -1
+ End If
+
+ Exit Function
+
+ParseFormulaPublicErrorHandler:
+ GeneralErrorHandler "MWPeptideClass.ParseFormulaPublic", Err.Number
+
+End Function
+
+Private Function ParseFormulaRecursive(ByVal strFormula As String, ByRef udtComputationStats As udtComputationStatsType, ByRef udtAbbrevSymbolStack As udtAbbrevSymbolStackType, ByVal blnExpandAbbreviations As Boolean, ByRef dblStdDevSum As Double, Optional dblValueForX As Double = 1#, Optional ByVal intCharCountPrior As Integer = 0, Optional ByVal dblParenthMultiplier As Double = 1#, Optional ByVal dblDashMultiplierPrior As Double = 1#, Optional ByVal dblBracketMultiplierPrior As Double = 1#, Optional ByRef CarbonOrSiliconReturnCount As Long = 0, Optional ByVal intParenthLevelPrevious As Integer = 0) As String
+
+ ' Determine elements in an abbreviation or elements and abbreviations in a formula
+ ' Stores results in udtComputationStats
+ ' ErrorParams will hold information on errors that occur
+ ' Returns the formatted formula
+
+ ' blnDisplayMessages indicates whether to display error messages
+ ' dblParenthMultiplier is the value to multiply all values by if inside parentheses
+ ' dblStdDevSum is the sum of the squares of the standard deviations
+ ' CarbonOrSiliconReturnCount records the number of carbon and silicon atoms found; used when correcting for charge inside parentheses or inside an abbreviation
+
+ ' ( and ) are 40 and 41 - is 45 { and } are 123 and 125
+ ' Numbers are 48 to 57 . is 46
+ ' Uppercase letters are 65 to 90
+ ' Lowercase letters are 97 to 122
+ ' [ and ] are 91 and 93
+ ' ^ is 94
+ ' _ is 95
+
+ Dim intAddonCount As Integer, intSymbolLength As Integer
+ Dim blnCaretPresent As Boolean, intElementIndex As Integer, intNumLength As Integer
+ Dim intCharIndex As Integer, intMinusSymbolLoc As Integer
+ Dim strLeftHalf As String, strRightHalf As String, blnMatchFound As Boolean
+ Dim strNewFormulaRightHalf As String
+ Dim udtComputationStatsRightHalf As udtComputationStatsType
+ Dim udtAbbrevSymbolStackRightHalf As udtAbbrevSymbolStackType
+ Dim dblStdDevSumRightHalf As Double
+ Dim dblAdjacentNum As Double, dblCaretVal As Double, dblCaretValDifference As Double
+ Dim dblAtomCountToAdd As Double
+ Dim dblBracketMultiplier As Double, blnInsideBrackets As Boolean
+ Dim intDashPos As Integer, dblDashMultiplier As Double
+ Dim sngChargeSaved As Single
+ Dim eSymbolMatchType As smtSymbolMatchTypeConstants
+ Dim strChar1 As String, strChar2 As String, strChar3 As String, strCharRemain As String
+ Dim strFormulaExcerpt As String
+ Dim strCharVal As String, intCharAsc As Integer
+ Dim LoneCarbonOrSilicon As Long
+ Dim dblIsoDifferenceTop As Double, dblIsoDifferenceBottom As Double
+
+ Dim SymbolReference As Integer, PrevSymbolReference As Integer
+ Dim strReplace As String, strNewFormula As String, strSubFormula As String
+ Dim intParenthClose As Integer, intParenthLevel As Integer
+ Dim intExpandAbbrevAdd As Integer
+
+On Error GoTo ErrorHandler
+
+ dblDashMultiplier = dblDashMultiplierPrior ' Leading coefficient position and default value
+ dblBracketMultiplier = dblBracketMultiplierPrior ' Bracket correction factor
+ blnInsideBrackets = False ' Switch for in or out of brackets
+
+ intDashPos = 0
+
+ LoneCarbonOrSilicon = 0 ' The number of carbon or silicon atoms
+ CarbonOrSiliconReturnCount = 0
+
+ ' Look for the > symbol
+ ' If found, this means take First Part minus the Second Part
+ intMinusSymbolLoc = InStr(strFormula, ">")
+ If intMinusSymbolLoc > 0 Then
+ ' Look for the first occurrence of >
+ intCharIndex = 1
+ blnMatchFound = False
+ Do
+ If Mid(strFormula, intCharIndex, 1) = ">" Then
+ blnMatchFound = True
+ strLeftHalf = Left(strFormula, intCharIndex - 1)
+ strRightHalf = Mid(strFormula, intCharIndex + 1)
+
+ ' Parse the first half
+ strNewFormula = ParseFormulaRecursive(strLeftHalf, udtComputationStats, udtAbbrevSymbolStack, blnExpandAbbreviations, dblStdDevSum, dblValueForX, intCharCountPrior, dblParenthMultiplier, dblDashMultiplier, dblBracketMultiplier, CarbonOrSiliconReturnCount, intParenthLevelPrevious)
+
+ ' Parse the second half
+ InitializeComputationStats udtComputationStatsRightHalf
+ InitializeAbbrevSymbolStack udtAbbrevSymbolStackRightHalf
+
+ strNewFormulaRightHalf = ParseFormulaRecursive(strRightHalf, udtComputationStatsRightHalf, udtAbbrevSymbolStackRightHalf, blnExpandAbbreviations, dblStdDevSumRightHalf, dblValueForX, intCharCountPrior + intCharIndex, dblParenthMultiplier, dblDashMultiplier, dblBracketMultiplier, CarbonOrSiliconReturnCount, intParenthLevelPrevious)
+
+ Exit Do
+ End If
+ intCharIndex = intCharIndex + 1
+ Loop While intCharIndex <= Len(strFormula)
+ ' blnMatchFound should always be true; thus, I can probably remove it
+ Debug.Assert blnMatchFound
+
+ If blnMatchFound Then
+ ' Update strFormula
+ strFormula = strNewFormula & ">" & strNewFormulaRightHalf
+
+ ' Update udtComputationStats by subtracting the atom counts of the first half minus the second half
+ ' If any atom counts become < 0 then, then raise an error
+ For intElementIndex = 1 To ELEMENT_COUNT
+ With udtComputationStats.Elements(intElementIndex)
+ If ElementStats(intElementIndex).Mass * .Count + .IsotopicCorrection >= _
+ ElementStats(intElementIndex).Mass * udtComputationStatsRightHalf.Elements(intElementIndex).Count + udtComputationStatsRightHalf.Elements(intElementIndex).IsotopicCorrection Then
+
+ .Count = .Count - udtComputationStatsRightHalf.Elements(intElementIndex).Count
+ If .Count < 0 Then
+ ' This shouldn't happen
+ Debug.Assert False
+ .Count = 0
+ End If
+
+ If udtComputationStatsRightHalf.Elements(intElementIndex).IsotopicCorrection <> 0 Then
+ ' This assertion is here simply because I want to check the code
+ Debug.Assert False
+ .IsotopicCorrection = .IsotopicCorrection - udtComputationStatsRightHalf.Elements(intElementIndex).IsotopicCorrection
+ End If
+ Else
+ ' Invalid Formula; raise error
+ ErrorParams.ErrorID = 30: ErrorParams.ErrorPosition = intCharIndex
+ End If
+ End With
+ If ErrorParams.ErrorID <> 0 Then Exit For
+ Next intElementIndex
+
+ ' Adjust the overall charge
+ udtComputationStats.Charge = udtComputationStats.Charge - udtComputationStatsRightHalf.Charge
+ End If
+ Else
+
+ ' Formula does not contain >
+ ' Parse it
+ intCharIndex = 1
+ Do
+ strChar1 = Mid(strFormula, intCharIndex, 1)
+ strChar2 = Mid(strFormula, intCharIndex + 1, 1)
+ strChar3 = Mid(strFormula, intCharIndex + 2, 1)
+ strCharRemain = Mid(strFormula, intCharIndex + 3)
+ If gComputationOptions.CaseConversion <> ccExactCase Then strChar1 = UCase(strChar1)
+
+ If gComputationOptions.BracketsAsParentheses Then
+ If strChar1 = "[" Then strChar1 = "("
+ If strChar1 = "]" Then strChar1 = ")"
+ End If
+
+ eSymbolMatchType = smtUnknown
+ If strChar1 = "" Then strChar1 = EMPTY_STRINGCHAR
+ If strChar2 = "" Then strChar2 = EMPTY_STRINGCHAR
+ If strChar3 = "" Then strChar3 = EMPTY_STRINGCHAR
+ If strCharRemain = "" Then strCharRemain = EMPTY_STRINGCHAR
+
+ strFormulaExcerpt = strChar1 & strChar2 & strChar3 & strCharRemain
+
+ ' Check for needed caution statements
+ CheckCaution strFormulaExcerpt
+
+ Select Case Asc(strChar1)
+ Case 40, 123 ' ( Record its position
+ ' See if a number is present just after the opening parenthesis
+ If IsNumeric(strChar2) Or strChar2 = "." Then
+ ' Misplaced number
+ ErrorParams.ErrorID = 14: ErrorParams.ErrorPosition = intCharIndex
+ End If
+
+ If ErrorParams.ErrorID = 0 Then
+ ' search for closing parenthesis
+ intParenthLevel = 1
+ For intParenthClose = intCharIndex + 1 To Len(strFormula)
+ Select Case Mid(strFormula, intParenthClose, 1)
+ Case "(", "{", "["
+ ' Another opening parentheses
+ ' increment parenthtrack
+ If Not gComputationOptions.BracketsAsParentheses And Mid(strFormula, intParenthClose, 1) = "[" Then
+ ' Do not count the bracket
+ Else
+ intParenthLevel = intParenthLevel + 1
+ End If
+ Case ")", "}", "]"
+ If Not gComputationOptions.BracketsAsParentheses And Mid(strFormula, intParenthClose, 1) = "]" Then
+ ' Do not count the bracket
+ Else
+ intParenthLevel = intParenthLevel - 1
+ If intParenthLevel = 0 Then
+ dblAdjacentNum = ParseNum(Mid(strFormula, intParenthClose + 1), intNumLength)
+ CatchParsenumError dblAdjacentNum, intNumLength, intCharIndex, intSymbolLength
+
+ If dblAdjacentNum < 0 Then
+ dblAdjacentNum = 1#
+ intAddonCount = 0
+ Else
+ intAddonCount = intNumLength
+ End If
+
+ strSubFormula = Mid(strFormula, intCharIndex + 1, intParenthClose - (intCharIndex + 1))
+
+ ' Note, must pass parenthnum * dblAdjacentNum to preserve previous parentheses stuff
+ strNewFormula = ParseFormulaRecursive(strSubFormula, udtComputationStats, udtAbbrevSymbolStack, blnExpandAbbreviations, dblStdDevSum, dblValueForX, intCharCountPrior + intCharIndex, dblParenthMultiplier * dblAdjacentNum, dblDashMultiplier, dblBracketMultiplier, CarbonOrSiliconReturnCount, intParenthLevelPrevious + 1)
+
+ ' If expanding abbreviations, then strNewFormula might be longer than strFormula, must add this onto intCharIndex also
+ intExpandAbbrevAdd = Len(strNewFormula) - Len(strSubFormula)
+
+ ' Must replace the part of the formula parsed with the strNewFormula part, in case the formula was expanded or elements were capitalized
+ strFormula = Left(strFormula, intCharIndex) & strNewFormula & Mid(strFormula, intParenthClose)
+ intCharIndex = intParenthClose + intAddonCount + intExpandAbbrevAdd
+
+ ' Correct charge
+ If CarbonOrSiliconReturnCount > 0 Then
+ udtComputationStats.Charge = udtComputationStats.Charge - 2 * dblAdjacentNum
+ If dblAdjacentNum > 1 And CarbonOrSiliconReturnCount > 1 Then
+ udtComputationStats.Charge = udtComputationStats.Charge - 2 * (dblAdjacentNum - 1) * (CarbonOrSiliconReturnCount - 1)
+ End If
+ End If
+ Exit For
+ End If
+ End If
+ End Select
+ Next intParenthClose
+ End If
+
+ If intParenthLevel > 0 And ErrorParams.ErrorID = 0 Then
+ ' Missing closing parenthesis
+ ErrorParams.ErrorID = 3: ErrorParams.ErrorPosition = intCharIndex
+ End If
+ PrevSymbolReference = 0
+ Case 41, 125 ' ) Repeat a section of a formula
+ ' Should have been skipped
+ ' Unmatched closing parentheses
+ ErrorParams.ErrorID = 4: ErrorParams.ErrorPosition = intCharIndex
+
+ Case 45 ' -
+ ' Used to denote a leading coefficient
+ dblAdjacentNum = ParseNum(strChar2 & strChar3 & strCharRemain, intNumLength)
+ CatchParsenumError dblAdjacentNum, intNumLength, intCharIndex, intSymbolLength
+
+ If dblAdjacentNum > 0 Then
+ intDashPos = intCharIndex + intNumLength
+ dblDashMultiplier = dblAdjacentNum * dblDashMultiplierPrior
+ intCharIndex = intCharIndex + intNumLength
+ Else
+ If dblAdjacentNum = 0 Then
+ ' Cannot have 0 after a dash
+ ErrorParams.ErrorID = 5: ErrorParams.ErrorPosition = intCharIndex + 1
+ Else
+ ' No number is present, that's just fine
+ ' Make sure defaults are set, though
+ intDashPos = 0
+ dblDashMultiplier = dblDashMultiplierPrior
+ End If
+ End If
+ PrevSymbolReference = 0
+ Case 44, 46, 48 To 57 ' . or , and Numbers 0 to 9
+ ' They should only be encountered as a leading coefficient
+ ' Should have been bypassed when the coefficient was processed
+ If intCharIndex = 1 Then
+ ' Formula starts with a number -- multiply section by number (until next dash)
+ dblAdjacentNum = ParseNum(strFormulaExcerpt, intNumLength)
+ CatchParsenumError dblAdjacentNum, intNumLength, intCharIndex, intSymbolLength
+
+ If dblAdjacentNum >= 0 Then
+ intDashPos = intCharIndex + intNumLength - 1
+ dblDashMultiplier = dblAdjacentNum * dblDashMultiplierPrior
+ intCharIndex = intCharIndex + intNumLength - 1
+ Else
+ ' A number less then zero should have been handled by CatchParsenumError above
+ ' Make sure defaults are set, though
+ intDashPos = 0
+ dblDashMultiplier = dblDashMultiplierPrior
+ End If
+ Else
+ If CDblSafe(Mid(strFormula, intCharIndex - 1, 1)) > 0 Then
+ ' Number too large
+ ErrorParams.ErrorID = 7: ErrorParams.ErrorPosition = intCharIndex
+ Else
+ ' Misplaced number
+ ErrorParams.ErrorID = 14: ErrorParams.ErrorPosition = intCharIndex
+ End If
+ End If
+ PrevSymbolReference = 0
+ Case 91 ' [
+ If UCase(strChar2) = "X" Then
+ If strChar3 = "e" Then
+ dblAdjacentNum = ParseNum(strChar2 & strChar3 & strCharRemain, intNumLength)
+ CatchParsenumError dblAdjacentNum, intNumLength, intCharIndex, intSymbolLength
+ Else
+ dblAdjacentNum = dblValueForX
+ intNumLength = 1
+ End If
+ Else
+ dblAdjacentNum = ParseNum(strChar2 & strChar3 & strCharRemain, intNumLength)
+ CatchParsenumError dblAdjacentNum, intNumLength, intCharIndex, intSymbolLength
+
+ End If
+
+ If ErrorParams.ErrorID = 0 Then
+ If blnInsideBrackets Then
+ ' No Nested brackets.
+ ErrorParams.ErrorID = 16: ErrorParams.ErrorPosition = intCharIndex
+ Else
+ If dblAdjacentNum < 0 Then
+ ' No number after bracket
+ ErrorParams.ErrorID = 12: ErrorParams.ErrorPosition = intCharIndex + 1
+ Else
+ ' Coefficient for bracketed section.
+ blnInsideBrackets = True
+ dblBracketMultiplier = dblAdjacentNum * dblBracketMultiplierPrior ' Take times dblBracketMultiplierPrior in case it wasn't 1 to start with
+ intCharIndex = intCharIndex + intNumLength
+ End If
+ End If
+ End If
+ PrevSymbolReference = 0
+ Case 93 ' ]
+ dblAdjacentNum = ParseNum(strChar2 & strChar3 & strCharRemain, intNumLength)
+ CatchParsenumError dblAdjacentNum, intNumLength, intCharIndex, intSymbolLength
+
+ If dblAdjacentNum >= 0 Then
+ ' Number following bracket
+ ErrorParams.ErrorID = 11: ErrorParams.ErrorPosition = intCharIndex + 1
+ Else
+ If blnInsideBrackets Then
+ If intDashPos > 0 Then
+ ' Need to set intDashPos and dblDashMultiplier back to defaults, since a dash number goes back to one inside brackets
+ intDashPos = 0
+ dblDashMultiplier = 1
+ End If
+ blnInsideBrackets = False
+ dblBracketMultiplier = dblBracketMultiplierPrior
+ Else
+ ' Unmatched bracket
+ ErrorParams.ErrorID = 15: ErrorParams.ErrorPosition = intCharIndex
+ End If
+ End If
+ Case 65 To 90, 97 To 122, 43, 95 ' Uppercase A to Z and lowercase a to z, and the plus (+) sign, and the underscore (_)
+ eSymbolMatchType = smtUnknown
+ intAddonCount = 0
+ dblAdjacentNum = 0
+
+ eSymbolMatchType = CheckElemAndAbbrev(strFormulaExcerpt, SymbolReference)
+
+ Select Case eSymbolMatchType
+ Case smtElement
+ ' Found an element
+ ' SymbolReference is the elemental number
+ intSymbolLength = Len(ElementStats(SymbolReference).Symbol)
+ If intSymbolLength = 0 Then
+ ' No elements in ElementStats yet
+ ' Set intSymbolLength to 1
+ intSymbolLength = 1
+ End If
+ ' Look for number after element
+ dblAdjacentNum = ParseNum(Mid(strFormula, intCharIndex + intSymbolLength), intNumLength)
+ CatchParsenumError dblAdjacentNum, intNumLength, intCharIndex, intSymbolLength
+
+ If dblAdjacentNum < 0 Then
+ dblAdjacentNum = 1
+ End If
+
+ ' Note that intNumLength = 0 if dblAdjacentNum was -1 or otherwise < 0
+ intAddonCount = intNumLength + intSymbolLength - 1
+
+ If dblAdjacentNum = 0 Then
+ ' Zero after element
+ ErrorParams.ErrorID = 5: ErrorParams.ErrorPosition = intCharIndex + intSymbolLength
+ Else
+ If Not blnCaretPresent Then
+ dblAtomCountToAdd = dblAdjacentNum * dblBracketMultiplier * dblParenthMultiplier * dblDashMultiplier
+ With udtComputationStats.Elements(SymbolReference)
+ .Count = .Count + dblAtomCountToAdd
+ .Used = True ' Element is present tag
+ dblStdDevSum = dblStdDevSum + dblAtomCountToAdd * ((ElementStats(SymbolReference).Uncertainty) ^ 2)
+ End With
+
+ With udtComputationStats
+ ' Compute charge
+ If SymbolReference = 1 Then
+ ' Dealing with hydrogen
+ Select Case PrevSymbolReference
+ Case 1, 3 To 6, 11 To 14, 19 To 32, 37 To 50, 55 To 82, 87 To 109
+ ' Hydrogen is -1 with metals (non-halides)
+ .Charge = .Charge + dblAtomCountToAdd * (-1)
+ Case Else
+ .Charge = .Charge + dblAtomCountToAdd * (ElementStats(SymbolReference).Charge)
+ End Select
+ Else
+ .Charge = .Charge + dblAtomCountToAdd * (ElementStats(SymbolReference).Charge)
+ End If
+ End With
+
+ If SymbolReference = 6 Or SymbolReference = 14 Then
+ ' Sum up number lone C and Si (not in abbreviations)
+ LoneCarbonOrSilicon = LoneCarbonOrSilicon + dblAdjacentNum
+ CarbonOrSiliconReturnCount = CarbonOrSiliconReturnCount + dblAdjacentNum
+ End If
+ Else
+ ' blnCaretPresent = True
+ ' Check to make sure isotopic mass is reasonable
+ dblIsoDifferenceTop = CIntSafeDbl(0.63 * SymbolReference + 6)
+ dblIsoDifferenceBottom = CIntSafeDbl(0.008 * SymbolReference ^ 2 - 0.4 * SymbolReference - 6)
+ dblCaretValDifference = dblCaretVal - SymbolReference * 2
+
+ If dblCaretValDifference >= dblIsoDifferenceTop Then
+ ' Probably too high isotopic mass
+ AddToCautionDescription LookupMessage(660) & ": " & ElementStats(SymbolReference).Symbol & " - " & CStr(dblCaretVal) & " " & LookupMessage(665) & " " & CStr(ElementStats(SymbolReference).Mass)
+ ElseIf dblCaretVal < SymbolReference Then
+ ' Definitely too low isotopic mass
+ AddToCautionDescription LookupMessage(670) & ": " & ElementStats(SymbolReference).Symbol & " - " & CStr(SymbolReference) & " " & LookupMessage(675)
+ ElseIf dblCaretValDifference <= dblIsoDifferenceBottom Then
+ ' Probably too low isotopic mass
+ AddToCautionDescription LookupMessage(662) & ": " & ElementStats(SymbolReference).Symbol & " - " & CStr(dblCaretVal) & " " & LookupMessage(665) & " " & CStr(ElementStats(SymbolReference).Mass)
+ End If
+
+ ' Put in isotopic correction factor
+ dblAtomCountToAdd = dblAdjacentNum * dblBracketMultiplier * dblParenthMultiplier * dblDashMultiplier
+ With udtComputationStats.Elements(SymbolReference)
+ ' Increment element counting bin
+ .Count = .Count + dblAtomCountToAdd
+
+ ' Store information in .Isotopes()
+ ' Increment the isotope counting bin
+ .IsotopeCount = .IsotopeCount + 1
+
+ If UBound(.Isotopes) < .IsotopeCount Then
+ ReDim Preserve .Isotopes(UBound(.Isotopes) + 2)
+ End If
+
+ With .Isotopes(.IsotopeCount)
+ .Count = .Count + dblAtomCountToAdd
+ .Mass = dblCaretVal
+ End With
+
+ ' Add correction amount to udtComputationStats.elements(SymbolReference).IsotopicCorrection
+ .IsotopicCorrection = .IsotopicCorrection + (dblCaretVal * dblAtomCountToAdd - ElementStats(SymbolReference).Mass * dblAtomCountToAdd)
+
+ ' Set bit that element is present
+ .Used = True
+
+ ' Assume no error in caret value, no need to change dblStdDevSum
+ End With
+
+ ' Reset blnCaretPresent
+ blnCaretPresent = False
+ End If
+ If gComputationOptions.CaseConversion = ccConvertCaseUp Then
+ strFormula = Left(strFormula, intCharIndex - 1) + UCase(Mid(strFormula, intCharIndex, 1)) + Mid(strFormula, intCharIndex + 1)
+ End If
+ intCharIndex = intCharIndex + intAddonCount
+ End If
+
+ Case smtAbbreviation
+ ' Found an abbreviation or amino acid
+ ' SymbolReference is the abbrev or amino acid number
+
+ If IsPresentInAbbrevSymbolStack(udtAbbrevSymbolStack, SymbolReference) Then
+ ' Circular Reference: Can't have an abbreviation referencing an abbreviation that depends upon it
+ ' For example, the following is impossible: Lor = C6H5Tal and Tal = H4O2Lor
+ ' Furthermore, can't have this either: Lor = C6H5Tal and Tal = H4O2Vin and Vin = S3Lor
+ ErrorParams.ErrorID = 28: ErrorParams.ErrorPosition = intCharIndex
+ Else
+ ' Found an abbreviation
+ If blnCaretPresent Then
+ ' Cannot have isotopic mass for an abbreviation, including deuterium
+ If UCase(strChar1) = "D" And strChar2 <> "y" Then
+ ' Isotopic mass used for Deuterium
+ ErrorParams.ErrorID = 26: ErrorParams.ErrorPosition = intCharIndex
+ Else
+ ErrorParams.ErrorID = 24: ErrorParams.ErrorPosition = intCharIndex
+ End If
+ Else
+ ' Parse abbreviation
+ ' Simply treat it like a formula surrounded by parentheses
+ ' Thus, find the number after the abbreviation, then call ParseFormulaRecursive, sending it the formula for the abbreviation
+ ' Update the udtAbbrevSymbolStack before calling so that we can check for circular abbreviation references
+
+ ' Record the abbreviation length
+ intSymbolLength = Len(AbbrevStats(SymbolReference).Symbol)
+
+ ' Look for number after abbrev/amino
+ dblAdjacentNum = ParseNum(Mid(strFormula, intCharIndex + intSymbolLength), intNumLength)
+ CatchParsenumError dblAdjacentNum, intNumLength, intCharIndex, intSymbolLength
+
+ If dblAdjacentNum < 0 Then
+ dblAdjacentNum = 1
+ intAddonCount = intSymbolLength - 1
+ Else
+ intAddonCount = intNumLength + intSymbolLength - 1
+ End If
+
+ ' Add this abbreviation symbol to the Abbreviation Symbol Stack
+ AbbrevSymbolStackAdd udtAbbrevSymbolStack, SymbolReference
+
+ ' Compute the charge prior to calling ParseFormulaRecursive
+ ' During the call to ParseFormulaRecursive, udtComputationStats.Charge will be
+ ' modified according to the atoms in the abbreviations's formula
+ ' This is not what we want; instead, we want to use the defined charge for the abbreviation
+ ' We'll use the dblAtomCountToAdd variable here, though instead of an atom count, it's really an abbreviation occurrence count
+ dblAtomCountToAdd = dblAdjacentNum * dblBracketMultiplier * dblParenthMultiplier * dblDashMultiplier
+ sngChargeSaved = udtComputationStats.Charge + dblAtomCountToAdd * (AbbrevStats(SymbolReference).Charge)
+
+ ' When parsing an abbreviation, do not pass on the value of blnExpandAbbreviations
+ ' This way, an abbreviation containing an abbreviation will only get expanded one level
+ ParseFormulaRecursive AbbrevStats(SymbolReference).Formula, udtComputationStats, udtAbbrevSymbolStack, False, dblStdDevSum, dblValueForX, intCharCountPrior + intCharIndex, dblParenthMultiplier * dblAdjacentNum, dblDashMultiplier, dblBracketMultiplier, CarbonOrSiliconReturnCount, intParenthLevelPrevious
+
+ ' Update the charge to sngChargeSaved
+ udtComputationStats.Charge = sngChargeSaved
+
+ ' Remove this symbol from the Abbreviation Symbol Stack
+ AbbrevSymbolStackAddRemoveMostRecent udtAbbrevSymbolStack
+
+ If ErrorParams.ErrorID = 0 Then
+
+ If blnExpandAbbreviations Then
+ ' Replace abbreviation with empirical formula
+ strReplace = AbbrevStats(SymbolReference).Formula
+
+ ' Look for a number after the abbreviation or amino acid
+ dblAdjacentNum = ParseNum(Mid(strFormula, intCharIndex + intSymbolLength), intNumLength)
+ CatchParsenumError dblAdjacentNum, intNumLength, intCharIndex, intSymbolLength
+
+ If InStr(strReplace, ">") Then
+ ' The > symbol means take First Part minus the Second Part
+ ' If we are parsing a subformula inside parentheses, or if there are
+ ' symbols (elements, abbreviations, or numbers) after the abbreviation, then
+ ' we cannot let the > symbol remain in the abbreviation
+ ' For example, if Jk = C6H5Cl2>HCl
+ ' and the user enters Jk2 then chooses Expand Abbreviations
+ ' Then, naively we might replace this with (C6H5Cl2>HCl)2
+ ' However, this will generate an error because (C6H5Cl2>HCl)2 gets split
+ ' to (C6H5Cl2 and HCl)2 which will both generate an error
+ ' The only option is to convert the abbreviation to its empirical formula
+ If intParenthLevelPrevious > 0 Or intParenthLevel > 0 Or intCharIndex + intSymbolLength <= Len(strFormula) Then
+ strReplace = ConvertFormulaToEmpirical(strReplace)
+ End If
+ End If
+
+ If dblAdjacentNum < 0 Then
+ ' No number after abbreviation
+ strFormula = Left(strFormula, intCharIndex - 1) & strReplace & Mid(strFormula, intCharIndex + intSymbolLength)
+ intSymbolLength = Len(strReplace)
+ dblAdjacentNum = 1
+ intAddonCount = intSymbolLength - 1
+ Else
+ ' Number after abbreviation -- must put abbreviation in parentheses
+ ' Parentheses can handle integer or decimal number
+ strReplace = "(" & strReplace & ")"
+ strFormula = Left(strFormula, intCharIndex - 1) & strReplace & Mid(strFormula, intCharIndex + intSymbolLength)
+ intSymbolLength = Len(strReplace)
+ intAddonCount = intNumLength + intSymbolLength - 1
+ End If
+ End If
+
+ If gComputationOptions.CaseConversion = ccConvertCaseUp Then
+ strFormula = Left(strFormula, intCharIndex - 1) + UCase(Mid(strFormula, intCharIndex, 1)) + Mid(strFormula, intCharIndex + 1)
+ End If
+ End If
+ End If
+ End If
+ intCharIndex = intCharIndex + intAddonCount
+ Case Else
+ ' Element not Found
+ If UCase(strChar1) = "X" Then
+ ' X for solver but no preceding bracket
+ ErrorParams.ErrorID = 18
+ Else
+ ErrorParams.ErrorID = 1
+ End If
+ ErrorParams.ErrorPosition = intCharIndex
+ End Select
+ PrevSymbolReference = SymbolReference
+ Case 94 ' ^ (caret)
+ dblAdjacentNum = ParseNum(strChar2 & strChar3 & strCharRemain, intNumLength)
+ CatchParsenumError dblAdjacentNum, intNumLength, intCharIndex, intSymbolLength
+
+ If ErrorParams.ErrorID <> 0 Then
+ ' Problem, don't go on.
+ Else
+ strCharVal = Mid(strFormula, intCharIndex + 1 + intNumLength, 1)
+ If Len(strCharVal) > 0 Then intCharAsc = Asc(strCharVal) Else intCharAsc = 0
+ If dblAdjacentNum >= 0 Then
+ If (intCharAsc >= 65 And intCharAsc <= 90) Or (intCharAsc >= 97 And intCharAsc <= 122) Then ' Uppercase A to Z and lowercase a to z
+ blnCaretPresent = True
+ dblCaretVal = dblAdjacentNum
+ intCharIndex = intCharIndex + intNumLength
+ Else
+ ' No letter after isotopic mass
+ ErrorParams.ErrorID = 22: ErrorParams.ErrorPosition = intCharIndex + intNumLength + 1
+ End If
+ Else
+ ' Adjacent number is < 0 or not present
+ ' Record error
+ blnCaretPresent = False
+ If Mid(strFormula, intCharIndex + 1, 1) = "-" Then
+ ' Negative number following caret
+ ErrorParams.ErrorID = 23: ErrorParams.ErrorPosition = intCharIndex + 1
+ Else
+ ' No number following caret
+ ErrorParams.ErrorID = 20: ErrorParams.ErrorPosition = intCharIndex + 1
+ End If
+ End If
+ End If
+ Case Else
+ ' There shouldn't be anything else (except the ~ filler character). If there is, we'll just ignore it
+ End Select
+
+ If intCharIndex = Len(strFormula) Then
+ ' Need to make sure compounds are present after a leading coefficient after a dash
+ If dblDashMultiplier > 0 Then
+ If intCharIndex <> intDashPos Then
+ ' Things went fine, no need to set anything
+ Else
+ ' No compounds after leading coefficient after dash
+ ErrorParams.ErrorID = 25: ErrorParams.ErrorPosition = intCharIndex
+ End If
+ End If
+ End If
+
+ If ErrorParams.ErrorID <> 0 Then
+ intCharIndex = Len(strFormula)
+ End If
+
+ intCharIndex = intCharIndex + 1
+ Loop While intCharIndex <= Len(strFormula)
+ End If
+
+ If blnInsideBrackets Then
+ If ErrorParams.ErrorID = 0 Then
+ ' Missing closing bracket
+ ErrorParams.ErrorID = 13: ErrorParams.ErrorPosition = intCharIndex
+ End If
+ End If
+
+ With ErrorParams
+ If .ErrorID <> 0 And Len(.ErrorCharacter) = 0 Then
+ .ErrorCharacter = strChar1
+ .ErrorPosition = .ErrorPosition + intCharCountPrior
+ End If
+ End With
+
+
+ If LoneCarbonOrSilicon > 1 Then
+ ' Correct Charge for number of C and Si
+ udtComputationStats.Charge = udtComputationStats.Charge - CLng(LoneCarbonOrSilicon - 1) * 2
+
+ CarbonOrSiliconReturnCount = LoneCarbonOrSilicon
+ Else
+ CarbonOrSiliconReturnCount = 0
+ End If
+
+ ' Return strFormula, which is possibly now capitalized correctly
+ ' It will also contain expanded abbreviations
+ ParseFormulaRecursive = strFormula
+ Exit Function
+
+ErrorHandler:
+ MwtWinDllErrorHandler "MwtWinDll_WorkingRoutines|ParseFormula"
+ ErrorParams.ErrorID = -10
+ ErrorParams.ErrorPosition = 0
+
+End Function
+
+Private Function ParseNum(strWork As String, ByRef intNumLength As Integer, Optional blnAllowNegative As Boolean = False) As Double
+ ' Looks for a number and returns it if found
+ ' If an error is found, it returns a negative number for the error code and sets intNumLength = 0
+ ' -1 = No number
+ ' -2 = (unused)
+ ' -3 = No number at all or (more likely) no number after decimal point
+ ' -4 = More than one decimal point
+
+ Dim strWorking As String, strFoundNum As String, intIndex As Integer, intDecPtCount As Integer
+
+ If gComputationOptions.DecimalSeparator = "" Then
+ gComputationOptions.DecimalSeparator = DetermineDecimalPoint()
+ End If
+
+ ' Set intNumLength to -1 for now
+ ' If it doesn't get set to 0 (due to an error), it will get set to the
+ ' length of the matched number before exiting the sub
+ intNumLength = -1
+
+ If strWork = "" Then strWork = EMPTY_STRINGCHAR
+ If (Asc(Left(strWork, 1)) < 48 Or Asc(Left(strWork, 1)) > 57) And _
+ Left(strWork, 1) <> gComputationOptions.DecimalSeparator And _
+ Not (Left(strWork, 1) = "-" And blnAllowNegative = True) Then
+ intNumLength = 0 ' No number found
+ ParseNum = -1
+ Else
+ ' Start of string is a number or a decimal point, or (if allowed) a negative sign
+ For intIndex = 1 To Len(strWork)
+ strWorking = Mid(strWork, intIndex, 1)
+ If IsNumeric(strWorking) Or strWorking = gComputationOptions.DecimalSeparator Or _
+ (blnAllowNegative = True And strWorking = "-") Then
+ strFoundNum = strFoundNum & strWorking
+ Else
+ Exit For
+ End If
+ Next intIndex
+
+ If Len(strFoundNum) = 0 Or strFoundNum = gComputationOptions.DecimalSeparator Then
+ ' No number at all or (more likely) no number after decimal point
+ strFoundNum = -3
+ intNumLength = 0
+ Else
+ ' Check for more than one decimal point (. or ,)
+ intDecPtCount = 0
+ For intIndex = 1 To Len(strFoundNum)
+ If Mid(strFoundNum, intIndex, 1) = gComputationOptions.DecimalSeparator Then intDecPtCount = intDecPtCount + 1
+ Next intIndex
+ If intDecPtCount > 1 Then
+ ' more than one intDecPtCount
+ strFoundNum = -4
+ intNumLength = 0
+ Else
+ ' All is fine
+ End If
+ End If
+
+ If intNumLength < 0 Then intNumLength = Len(strFoundNum)
+ ParseNum = CDblSafe(strFoundNum)
+ End If
+
+End Function
+
+Public Function PlainTextToRtfInternal(strWorkText As String, Optional CalculatorMode As Boolean = False, Optional blnHighlightCharFollowingPercentSign As Boolean = True, Optional blnOverrideErrorID As Boolean = False, Optional lngErrorIDOverride As Long = 0) As String
+ Dim strWorkChar As String, strWorkCharPrev As String, strRTF As String
+ Dim intCharIndex As Integer, intCharIndex2 As Integer, blnSuperFound As Boolean
+ Dim lngErrorID As Long
+
+ ' Converts plain text to formatted rtf text.
+ ' Rtf string must begin with {{\fonttbl{\f0\fcharset0\fprq2 Times New Roman;}}\pard\plain\fs25
+ ' and must end with } or {\fs30 }} if superscript was used
+
+ ' "{\super 3}C{\sub 6}H{\sub 6}{\fs30 }}"
+ 'strRTF = "{{\fonttbl{\f0\fcharset0\fprq2 " & rtfFormula(0).font & ";}}\pard\plain\fs25 "
+ ' Old: strRTF = "{\rtf1\ansi\deff0\deftab720{\fonttbl{\f0\fswiss MS Sans Serif;}{\f1\froman\fcharset2 Symbol;}{\f2\froman\fcharset2 Times New Roman;}{\f3\froman " & lblMWT(0).FontName & ";}}{\colortbl\red0\green0\blue0;\red255\green0\blue0;}\deflang1033\pard\plain\f3\fs25 "
+ ' old: strRTF = "{\rtf1\ansi\deff0\deftab720{\fonttbl{\f0\fswiss MS Sans Serif;}{\f1\froman\fcharset2 Symbol;}{\f2\froman " & lblMWT(0).FontName & ";}{\f3\fswiss\fprq2 System;}}{\colortbl\red0\green0\blue0;\red255\green0\blue0;}\deflang1033\pard\plain\f2\fs25 "
+ ' f0 f1 f2 f3 f4 cf0 (black) cf1 (red) cf3 (white)
+ strRTF = "{\rtf1\ansi\deff0\deftab720{\fonttbl{\f0\fswiss MS Sans Serif;}{\f1\froman\fcharset2 Symbol;}{\f2\froman " & gComputationOptions.RtfFontName & ";}{\f3\froman Times New Roman;}{\f4\fswiss\fprq2 System;}}{\colortbl\red0\green0\blue0;\red255\green0\blue0;\red255\green255\blue255;}\deflang1033\pard\plain\f2\fs" & Trim(Str(CIntSafeDbl(gComputationOptions.RtfFontSize * 2.5))) & " "
+
+ If strWorkText = "" Then
+ ' Return a blank RTF string
+ PlainTextToRtfInternal = strRTF & "}"
+ Exit Function
+ End If
+
+ blnSuperFound = False
+ strWorkCharPrev = ""
+ For intCharIndex = 1 To Len(strWorkText)
+ strWorkChar = Mid(strWorkText, intCharIndex, 1)
+ If strWorkChar = "%" And blnHighlightCharFollowingPercentSign Then
+ ' An error was found and marked by a % sign
+ ' Highlight the character at the % sign, and remove the % sign
+ If intCharIndex = Len(strWorkText) Then
+ ' At end of line
+ If blnOverrideErrorID And lngErrorIDOverride <> 0 Then
+ lngErrorID = lngErrorIDOverride
+ Else
+ lngErrorID = ErrorParams.ErrorID
+ End If
+
+ Select Case lngErrorID
+ Case 2 To 4
+ ' Error involves a parentheses, find last opening parenthesis, (, or opening curly bracket, {
+ For intCharIndex2 = Len(strRTF) To 2 Step -1
+ If Mid(strRTF, intCharIndex2, 1) = "(" Then
+ strRTF = Left(strRTF, intCharIndex2 - 1) & "{\cf1 (}" & Mid(strRTF, intCharIndex2 + 1)
+ Exit For
+ ElseIf Mid(strRTF, intCharIndex2, 1) = "{" Then
+ strRTF = Left(strRTF, intCharIndex2 - 1) & "{\cf1 \{}" & Mid(strRTF, intCharIndex2 + 1)
+ Exit For
+ End If
+ Next intCharIndex2
+ Case 13, 15
+ ' Error involves a bracket, find last opening bracket, [
+ For intCharIndex2 = Len(strRTF) To 2 Step -1
+ If Mid(strRTF, intCharIndex2, 1) = "[" Then
+ strRTF = Left(strRTF, intCharIndex2 - 1) & "{\cf1 [}" & Mid(strRTF, intCharIndex2 + 1)
+ Exit For
+ End If
+ Next intCharIndex2
+ Case Else
+ ' Nothing to highlight
+ End Select
+ Else
+ ' Highlight next character and skip % sign
+ strWorkChar = Mid(strWorkText, intCharIndex + 1, 1)
+ ' Handle curly brackets
+ If strWorkChar = "{" Or strWorkChar = "}" Then strWorkChar = "\" & strWorkChar
+ strRTF = strRTF & "{\cf1 " & strWorkChar & "}"
+ intCharIndex = intCharIndex + 1
+ End If
+ ElseIf strWorkChar = "^" Then
+ strRTF = strRTF & "{\super ^}"
+ blnSuperFound = True
+ ElseIf strWorkChar = "_" Then
+ strRTF = strRTF & "{\super _}"
+ blnSuperFound = True
+ ElseIf strWorkChar = "+" And Not CalculatorMode Then
+ strRTF = strRTF & "{\super +}"
+ blnSuperFound = True
+ ElseIf strWorkChar = EMPTY_STRINGCHAR Then
+ ' skip it, the tilde sign is used to add additional height to the formula line when isotopes are used
+ ' If it's here from a previous time, we ignore it, adding it at the end if needed (if blnSuperFound = true)
+ ElseIf IsNumeric(strWorkChar) Or strWorkChar = gComputationOptions.DecimalSeparator Then
+ ' Number or period, so super or subscript it if needed
+ If intCharIndex = 1 Then
+ ' at beginning of line, so leave it alone. Probably out of place
+ strRTF = strRTF & strWorkChar
+ ElseIf Not CalculatorMode And (IsCharacter(strWorkCharPrev) Or strWorkCharPrev = ")" Or strWorkCharPrev = "\}" Or strWorkCharPrev = "+" Or strWorkCharPrev = "_" Or Left(Right(strRTF, 6), 3) = "sub") Then
+ ' subscript if previous character was a character, parentheses, curly bracket, plus sign, or was already subscripted
+ ' But, don't use subscripts in calculator
+ strRTF = strRTF & "{\sub " & strWorkChar & "}"
+ ElseIf Not CalculatorMode And gComputationOptions.BracketsAsParentheses And strWorkCharPrev = "]" Then
+ ' only subscript after closing bracket, ], if brackets are being treated as parentheses
+ strRTF = strRTF & "{\sub " & strWorkChar & "}"
+ ElseIf Left(Right(strRTF, 8), 5) = "super" Then
+ ' if previous character was superscripted, then superscript this number too
+ strRTF = strRTF & "{\super " & strWorkChar & "}"
+ blnSuperFound = True
+ Else
+ strRTF = strRTF & strWorkChar
+ End If
+ ElseIf strWorkChar = " " Then
+ ' Ignore it
+ Else
+ ' Handle curly brackets
+ If strWorkChar = "{" Or strWorkChar = "}" Then strWorkChar = "\" & strWorkChar
+ strRTF = strRTF & strWorkChar
+ End If
+ strWorkCharPrev = strWorkChar
+ Next intCharIndex
+
+ If blnSuperFound Then
+ ' Add an extra tall character, the tilde sign (~, RTF_HEIGHT_ADJUSTCHAR)
+ ' It is used to add additional height to the formula line when isotopes are used
+ ' It is colored white so the user does not see it
+ strRTF = strRTF & "{\fs" & Trim(Str(CIntSafeDbl(gComputationOptions.RtfFontSize * 3))) & "\cf2 " & RTF_HEIGHT_ADJUSTCHAR & "}}"
+ Else
+ strRTF = strRTF & "}"
+ End If
+
+ PlainTextToRtfInternal = strRTF
+
+End Function
+
+Public Sub RecomputeAbbreviationMassesInternal()
+ ' Recomputes the Mass for all of the loaded abbreviations
+
+ Dim lngIndex As Long
+
+ For lngIndex = 1 To AbbrevAllCount
+ With AbbrevStats(lngIndex)
+ .Mass = ComputeFormulaWeight(.Formula)
+ End With
+ Next lngIndex
+End Sub
+
+Public Sub RemoveAllCautionStatementsInternal()
+ CautionStatementCount = 0
+End Sub
+
+Public Sub RemoveAllAbbreviationsInternal()
+ AbbrevAllCount = 0
+ ConstructMasterSymbolsList
+End Sub
+
+Public Function RemoveAbbreviationInternal(ByVal strAbbreviationSymbol As String) As Long
+ ' Look for the abbreviation and remove it
+ ' Returns 0 if found and removed; 1 if error
+
+ Dim lngIndex As Long
+ Dim blnRemoved As Boolean
+
+ strAbbreviationSymbol = LCase(strAbbreviationSymbol)
+
+ For lngIndex = 1 To AbbrevAllCount
+ If LCase(AbbrevStats(lngIndex).Symbol) = strAbbreviationSymbol Then
+ RemoveAbbreviationByIDInternal lngIndex
+ blnRemoved = True
+ End If
+ Next lngIndex
+
+ If blnRemoved Then
+ RemoveAbbreviationInternal = 0
+ Else
+ RemoveAbbreviationInternal = 1
+ End If
+End Function
+
+Public Function RemoveAbbreviationByIDInternal(ByVal lngAbbreviationID As Long) As Long
+ ' Remove the abbreviation at index lngAbbreviationID
+ ' Returns 0 if found and removed; 1 if error
+
+ Dim blnRemoved As Boolean
+ Dim lngIndexRemove As Long
+
+ If lngAbbreviationID >= 1 And lngAbbreviationID <= AbbrevAllCount Then
+ For lngIndexRemove = lngAbbreviationID To AbbrevAllCount - 1
+ AbbrevStats(lngIndexRemove) = AbbrevStats(lngIndexRemove + 1)
+ Next lngIndexRemove
+ AbbrevAllCount = AbbrevAllCount - 1
+ ConstructMasterSymbolsList
+ blnRemoved = True
+ Else
+ blnRemoved = False
+ End If
+
+ If blnRemoved Then
+ RemoveAbbreviationByIDInternal = 0
+ Else
+ RemoveAbbreviationByIDInternal = 1
+ End If
+End Function
+
+Public Function RemoveCautionStatementInternal(ByVal strCautionSymbol As String) As Long
+ ' Look for the abbreviation
+ ' Returns 0 if found and removed; 1 if error
+
+ Dim intIndex As Integer, intIndexRemove As Integer
+ Dim blnRemoved As Boolean
+
+ For intIndex = 1 To CautionStatementCount
+ If CautionStatements(intIndex, 0) = strCautionSymbol Then
+ For intIndexRemove = intIndex To CautionStatementCount - 1
+ CautionStatements(intIndexRemove, 0) = CautionStatements(intIndexRemove + 1, 0)
+ CautionStatements(intIndexRemove, 1) = CautionStatements(intIndexRemove + 1, 1)
+ Next intIndexRemove
+ CautionStatementCount = CautionStatementCount - 1
+ blnRemoved = True
+ End If
+ Next intIndex
+
+ If blnRemoved Then
+ RemoveCautionStatementInternal = 0
+ Else
+ RemoveCautionStatementInternal = 1
+ End If
+End Function
+
+Public Sub ResetErrorParamsInternal()
+ With ErrorParams
+ .ErrorCharacter = ""
+ .ErrorID = 0
+ .ErrorPosition = 0
+ End With
+End Sub
+
+Public Function ReturnFormattedMassAndStdDev(dblMass As Double, dblStdDev As Double, Optional blnIncludeStandardDeviation As Boolean = True, Optional blnIncludePctSign As Boolean = False) As String
+ ' Plan:
+ ' Round dblStdDev to 1 final digit.
+ ' Round dblMass to the appropriate place based on stddev.
+
+ ' dblMass is the main number
+ ' dblStdDev is the standard deviation
+
+ On Local Error GoTo StdErrorHandler
+
+ Dim strResult As String
+ Dim strStdDevShort As String
+ Dim dblRoundedStdDev As Double, dblRoundedMain As Double
+ Dim strWork As String, dblWork As Double, intExponentValue As Integer
+ Dim strPctSign As String
+
+ ' blnIncludePctSign is True when formatting Percent composition values
+ If blnIncludePctSign Then
+ strPctSign = "%"
+ Else
+ strPctSign = ""
+ End If
+
+ If Val(dblStdDev) = 0 Then
+ ' Standard deviation value is 0; simply return the result
+ strResult = Format(dblMass, "0.0####") & strPctSign & " (" & Chr$(177) & "0)"
+
+ ' dblRoundedMain is used later, must copy dblMass to it
+ dblRoundedMain = dblMass
+ Else
+
+ ' First round dblStdDev to show just one number
+ dblRoundedStdDev = CDbl(Format(dblStdDev, "0E+000"))
+
+ ' Now round dblMass
+ ' Simply divide dblMass by 10^Exponent of the Standard Deviation
+ ' Next round
+ ' Now multiply to get back the rounded dblMass
+ strWork = Format(dblStdDev, "0E+000")
+ strStdDevShort = Left(strWork, 1)
+
+ intExponentValue = CIntSafe(Right(strWork, 4))
+ dblWork = dblMass / 10 ^ intExponentValue
+ dblWork = Round(dblWork, 0)
+ dblRoundedMain = dblWork * 10 ^ intExponentValue
+
+ strWork = Format(dblRoundedMain, "0.0##E+00")
+
+ If gComputationOptions.StdDevMode = smShort Then
+ ' StdDevType Short (Type 0)
+ strResult = CStr(dblRoundedMain)
+ If blnIncludeStandardDeviation Then
+ strResult = strResult & "(" & Chr$(177) & strStdDevShort & ")"
+ End If
+ strResult = strResult & strPctSign
+ ElseIf gComputationOptions.StdDevMode = smScientific Then
+ ' StdDevType Scientific (Type 1)
+ strResult = CStr(dblRoundedMain) & strPctSign
+ If blnIncludeStandardDeviation Then
+ strResult = strResult & " (" & Chr$(177) & Trim(Format(dblStdDev, "0.000E+00")) & ")"
+ End If
+ Else
+ ' StdDevType Decimal
+ strResult = Format(dblMass, "0.0####") & strPctSign
+ If blnIncludeStandardDeviation Then
+ strResult = strResult & " (" & Chr$(177) & Trim(CStr(dblRoundedStdDev)) & ")"
+ End If
+ End If
+ End If
+
+ ReturnFormattedMassAndStdDev = strResult
+
+StdStart:
+ 'This code skips the error handler
+ Exit Function
+
+StdErrorHandler:
+ MwtWinDllErrorHandler "MwtWinDll_WorkingRoutines|ReturnFormattedMassAndStdDev"
+ ErrorParams.ErrorID = -10
+ ErrorParams.ErrorPosition = 0
+ Resume StdStart
+End Function
+
+Public Function SetAbbreviationInternal(ByVal strSymbol As String, ByVal strFormula As String, ByVal sngCharge As Single, ByVal blnIsAminoAcid As Boolean, Optional ByVal strOneLetterSymbol As String = "", Optional strComment As String = "", Optional blnValidateFormula As Boolean = True) As Long
+ ' Adds a new abbreviation or updates an existing one (based on strSymbol)
+ ' Returns 0 if successful, otherwise, returns an error ID
+
+ Dim blnAlreadyPresent As Boolean
+ Dim lngIndex As Long, lngAbbrevID As Long
+
+ ' See if the abbreviation is alrady present
+ blnAlreadyPresent = False
+ For lngIndex = 1 To AbbrevAllCount
+ If UCase(AbbrevStats(lngIndex).Symbol) = UCase(strSymbol) Then
+ blnAlreadyPresent = True
+ lngAbbrevID = lngIndex
+ Exit For
+ End If
+ Next lngIndex
+
+ ' AbbrevStats is a 1-based array
+ If Not blnAlreadyPresent Then
+ If AbbrevAllCount < MAX_ABBREV_COUNT Then
+ lngAbbrevID = AbbrevAllCount + 1
+ AbbrevAllCount = AbbrevAllCount + 1
+ Else
+ ' Too many abbreviations
+ ErrorParams.ErrorID = 196
+ End If
+ End If
+
+ If lngAbbrevID >= 1 Then
+ SetAbbreviationByIDInternal lngAbbrevID, strSymbol, strFormula, sngCharge, blnIsAminoAcid, strOneLetterSymbol, strComment, blnValidateFormula
+ End If
+
+ SetAbbreviationInternal = ErrorParams.ErrorID
+
+End Function
+
+Public Function SetAbbreviationByIDInternal(ByVal intAbbrevID As Integer, ByVal strSymbol As String, ByVal strFormula As String, ByVal sngCharge As Single, ByVal blnIsAminoAcid As Boolean, Optional ByVal strOneLetterSymbol As String = "", Optional strComment As String = "", Optional blnValidateFormula As Boolean = True) As Long
+ ' Adds a new abbreviation or updates an existing one (based on intAbbrevID)
+ ' If intAbbrevID < 1 then adds as a new abbreviation
+ ' Returns 0 if successful, otherwise, returns an error ID
+
+ Dim udtComputationStats As udtComputationStatsType
+ Dim udtAbbrevSymbolStack As udtAbbrevSymbolStackType
+ Dim blnInvalidSymbolOrFormula As Boolean
+ Dim eSymbolMatchType As smtSymbolMatchTypeConstants
+ Dim intSymbolReference As Integer
+
+ ResetErrorParamsInternal
+
+ InitializeComputationStats udtComputationStats
+ InitializeAbbrevSymbolStack udtAbbrevSymbolStack
+
+ If Len(strSymbol) < 1 Then
+ ' Symbol length is 0
+ ErrorParams.ErrorID = 192
+ ElseIf Len(strSymbol) > MAX_ABBREV_LENGTH Then
+ ' Abbreviation symbol too long
+ ErrorParams.ErrorID = 190
+ Else
+ If IsStringAllLetters(strSymbol) Then
+ If Len(strFormula) > 0 Then
+ ' Convert symbol to proper case mode
+ strSymbol = UCase(Left(strSymbol, 1)) & LCase(Mid(strSymbol, 2))
+
+ ' If intAbbrevID is < 1 or larger than AbbrevAllCount, then define it
+ If intAbbrevID < 1 Or intAbbrevID > AbbrevAllCount + 1 Then
+ If AbbrevAllCount < MAX_ABBREV_COUNT Then
+ AbbrevAllCount = AbbrevAllCount + 1
+ intAbbrevID = AbbrevAllCount
+ Else
+ ' Too many abbreviations
+ ErrorParams.ErrorID = 196
+ intAbbrevID = -1
+ End If
+ End If
+
+ If intAbbrevID >= 1 Then
+ ' Make sure the abbreviation doesn't match one of the standard elements
+ eSymbolMatchType = CheckElemAndAbbrev(strSymbol, intSymbolReference)
+
+ If eSymbolMatchType = smtElement Then
+ If ElementStats(intSymbolReference).Symbol = strSymbol Then
+ blnInvalidSymbolOrFormula = True
+ End If
+ End If
+
+ If Not blnInvalidSymbolOrFormula And blnValidateFormula Then
+ ' Make sure the abbreviation's formula is valid
+ ' This will also auto-capitalize the formula if auto-capitalize is turned on
+ strFormula = ParseFormulaRecursive(strFormula, udtComputationStats, udtAbbrevSymbolStack, False, 0)
+
+ If ErrorParams.ErrorID <> 0 Then
+ ' An error occurred while parsing
+ ' Already present in ErrorParams.ErrorID
+ ' We'll still add the formula, but mark it as invalid
+ blnInvalidSymbolOrFormula = True
+ End If
+ End If
+
+ AddAbbreviationWork intAbbrevID, strSymbol, strFormula, sngCharge, blnIsAminoAcid, strOneLetterSymbol, strComment, blnInvalidSymbolOrFormula
+
+ ConstructMasterSymbolsList
+ End If
+ Else
+ ' Invalid formula (actually, blank formula)
+ ErrorParams.ErrorID = 160
+ End If
+ Else
+ ' Symbol does not just contain letters
+ ErrorParams.ErrorID = 194
+ End If
+ End If
+
+ SetAbbreviationByIDInternal = ErrorParams.ErrorID
+
+End Function
+
+Public Function SetCautionStatementInternal(strSymbolCombo As String, strNewCautionStatement As String) As Long
+ ' Adds a new caution statement or updates an existing one (based on strSymbolCombo)
+ ' Returns 0 if successful, otherwise, returns an Error ID
+
+ Dim blnAlreadyPresent As Boolean, intIndex As Integer
+
+ ResetErrorParamsInternal
+
+ If Len(strSymbolCombo) >= 1 And Len(strSymbolCombo) <= MAX_ABBREV_LENGTH Then
+ ' Make sure all the characters in strSymbolCombo are letters
+ If IsStringAllLetters(strSymbolCombo) Then
+ If Len(strNewCautionStatement) > 0 Then
+ ' See if strSymbolCombo is present in CautionStatements()
+ For intIndex = 1 To CautionStatementCount
+ If CautionStatements(intIndex, 0) = strSymbolCombo Then
+ blnAlreadyPresent = True
+ Exit For
+ End If
+ Next intIndex
+
+ ' Caution statements is a 0-based array
+ If Not blnAlreadyPresent Then
+ If CautionStatementCount < MAX_CAUTION_STATEMENTS Then
+ CautionStatementCount = CautionStatementCount + 1
+ intIndex = CautionStatementCount
+ Else
+ ' Too many caution statements
+ ErrorParams.ErrorID = 1215
+ intIndex = -1
+ End If
+ End If
+
+ If intIndex >= 1 Then
+ CautionStatements(intIndex, 0) = strSymbolCombo
+ CautionStatements(intIndex, 1) = strNewCautionStatement
+ End If
+ Else
+ ' Caution description length is 0
+ ErrorParams.ErrorID = 1210
+ End If
+ Else
+ ' Caution symbol doesn't just contain letters
+ ErrorParams.ErrorID = 1205
+ End If
+ Else
+ ' Symbol length is 0 or is greater than MAX_ABBREV_LENGTH
+ ErrorParams.ErrorID = 1200
+ End If
+
+ SetCautionStatementInternal = ErrorParams.ErrorID
+
+End Function
+
+Public Function SetChargeCarrierMassInternal(dblMass As Double)
+ mChargeCarrierMass = dblMass
+End Function
+
+Public Function SetElementInternal(strSymbol As String, dblMass As Double, dblUncertainty As Double, sngCharge As Single, Optional blnRecomputeAbbreviationMasses As Boolean = True) As Long
+ ' Used to update the values for a single element (based on strSymbol)
+ ' Set blnRecomputeAbbreviationMasses to False if updating several elements
+
+ Dim intIndex As Integer, blnFound As Boolean
+
+ For intIndex = 1 To ELEMENT_COUNT
+ If LCase(strSymbol) = LCase(ElementStats(intIndex).Symbol) Then
+ With ElementStats(intIndex)
+ .Mass = dblMass
+ .Uncertainty = dblUncertainty
+ .Charge = sngCharge
+ End With
+ blnFound = True
+ Exit For
+ End If
+ Next intIndex
+
+ If blnFound Then
+ If blnRecomputeAbbreviationMasses Then RecomputeAbbreviationMassesInternal
+ SetElementInternal = 0
+ Else
+ SetElementInternal = 1
+ End If
+End Function
+
+Public Function SetElementIsotopesInternal(ByVal strSymbol As String, ByVal intIsotopeCount As Integer, ByRef dblIsotopeMassesOneBased() As Double, ByRef sngIsotopeAbundancesOneBased() As Single) As Long
+
+ Dim intIndex As Integer, intIsotopeindex As Integer, blnFound As Boolean
+
+ For intIndex = 1 To ELEMENT_COUNT
+ If LCase(strSymbol) = LCase(ElementStats(intIndex).Symbol) Then
+ With ElementStats(intIndex)
+ If intIsotopeCount < 0 Then intIsotopeCount = 0
+ .IsotopeCount = intIsotopeCount
+ For intIsotopeindex = 1 To .IsotopeCount
+ If intIsotopeindex > MAX_ISOTOPES Then Exit For
+ .Isotopes(intIsotopeindex).Mass = dblIsotopeMassesOneBased(intIsotopeindex)
+ .Isotopes(intIsotopeindex).Abundance = sngIsotopeAbundancesOneBased(intIsotopeindex)
+ Next intIsotopeindex
+ End With
+ blnFound = True
+ Exit For
+ End If
+ Next intIndex
+
+ If blnFound Then
+ SetElementIsotopesInternal = 0
+ Else
+ SetElementIsotopesInternal = 1
+ End If
+End Function
+
+Public Sub SetElementModeInternal(NewElementMode As emElementModeConstantsPrivate, Optional blnMemoryLoadElementValues As Boolean = True)
+ ' The only time you would want blnMemoryLoadElementValues to be False is if you're
+ ' manually setting element weight values, but want to let the software know that
+ ' they're average, isotopic, or integer values
+
+On Error GoTo SetElementModeInternalErrorHandler
+
+ If NewElementMode >= emAverageMass And NewElementMode <= emIntegerMass Then
+ If NewElementMode <> mCurrentElementMode Or blnMemoryLoadElementValues Then
+ mCurrentElementMode = NewElementMode
+
+ If blnMemoryLoadElementValues Then
+ MemoryLoadElements mCurrentElementMode
+ End If
+
+ ConstructMasterSymbolsList
+ RecomputeAbbreviationMassesInternal
+ End If
+ End If
+
+ Exit Sub
+
+SetElementModeInternalErrorHandler:
+ GeneralErrorHandler "MWPeptideClass.SetElementModeInternal", Err.Number
+
+End Sub
+
+Public Function SetMessageStatementInternal(lngMessageID As Long, strNewMessage As String) As Long
+ ' Used to replace the default message strings with foreign language equivalent ones
+ ' Returns 0 if success; 1 if failure
+ If lngMessageID >= 1 And lngMessageID <= MESSAGE_STATEMENT_DIMCOUNT And Len(strNewMessage) > 0 Then
+ MessageStatements(lngMessageID) = strNewMessage
+ SetMessageStatementInternal = 0
+ Else
+ SetMessageStatementInternal = 1
+ End If
+End Function
+
+Private Sub ShellSortSymbols(lngLowIndex As Long, lngHighIndex As Long)
+ Dim lngIndex As Long
+
+ ReDim PointerArray(lngHighIndex) As Long
+ ReDim SymbolsStore(lngHighIndex, 1) As String
+
+ ' MasterSymbolsList starts at lngLowIndex
+ For lngIndex = lngLowIndex To lngHighIndex
+ PointerArray(lngIndex) = lngIndex
+ Next lngIndex
+
+ ShellSortSymbolsWork PointerArray(), lngLowIndex, lngHighIndex
+
+ ' Reassign MasterSymbolsList array according to pointerarray order
+ ' First, copy to a temporary array (I know it eats up memory, but I have no choice)
+ For lngIndex = lngLowIndex To lngHighIndex
+ SymbolsStore(lngIndex, 0) = MasterSymbolsList(lngIndex, 0)
+ SymbolsStore(lngIndex, 1) = MasterSymbolsList(lngIndex, 1)
+ Next lngIndex
+
+ ' Now, put them back into the MasterSymbolsList() array in the correct order
+ ' Use pointerarray() for this
+ For lngIndex = lngLowIndex To lngHighIndex
+ MasterSymbolsList(lngIndex, 0) = SymbolsStore(PointerArray(lngIndex), 0)
+ MasterSymbolsList(lngIndex, 1) = SymbolsStore(PointerArray(lngIndex), 1)
+ Next lngIndex
+
+End Sub
+
+Private Sub ShellSortSymbolsWork(ByRef PointerArray() As Long, ByVal lngLowIndex As Long, ByVal lngHighIndex As Long)
+ ' Sort the list using a shell sort
+ Dim lngCount As Long
+ Dim lngIncrement As Long
+ Dim lngIndex As Long
+ Dim lngIndexCompare As Long
+ Dim lngPointerSwap As Long
+ Dim Length1 As Long, Length2 As Long
+
+ ' Sort PointerArray[lngLowIndex..lngHighIndex] by comparing
+ ' Len(MasterSymbolsList(PointerArray(x)) and sorting by decreasing length
+ ' If same length, sort alphabetically (increasing)
+
+ ' Compute largest increment
+ lngCount = lngHighIndex - lngLowIndex + 1
+ lngIncrement = 1
+ If (lngCount < 14) Then
+ lngIncrement = 1
+ Else
+ Do While lngIncrement < lngCount
+ lngIncrement = 3 * lngIncrement + 1
+ Loop
+ lngIncrement = lngIncrement \ 3
+ lngIncrement = lngIncrement \ 3
+ End If
+
+ Do While lngIncrement > 0
+ ' Sort by insertion in increments of lngIncrement
+ For lngIndex = lngLowIndex + lngIncrement To lngHighIndex
+ lngPointerSwap = PointerArray(lngIndex)
+ For lngIndexCompare = lngIndex - lngIncrement To lngLowIndex Step -lngIncrement
+ ' Use <= to sort ascending; Use > to sort descending
+ ' Sort by decreasing length
+ Length1 = Len(MasterSymbolsList(PointerArray(lngIndexCompare), 0))
+ Length2 = Len(MasterSymbolsList(lngPointerSwap, 0))
+ If Length1 > Length2 Then Exit For
+ ' If same length, sort alphabetically
+ If Length1 = Length2 Then
+ If UCase(MasterSymbolsList(PointerArray(lngIndexCompare), 0)) <= UCase(MasterSymbolsList(lngPointerSwap, 0)) Then Exit For
+ End If
+ PointerArray(lngIndexCompare + lngIncrement) = PointerArray(lngIndexCompare)
+ Next lngIndexCompare
+ PointerArray(lngIndexCompare + lngIncrement) = lngPointerSwap
+ Next lngIndex
+ lngIncrement = lngIncrement \ 3
+ Loop
+
+End Sub
+
+Public Sub SetShowErrorMessageDialogs(blnValue As Boolean)
+ mShowErrorMessageDialogs = blnValue
+End Sub
+
+Public Function ShowErrorMessageDialogs() As Boolean
+ ShowErrorMessageDialogs = mShowErrorMessageDialogs
+End Function
+
+Public Sub SortAbbreviationsInternal()
+ Dim lngLowIndex As Long, lngHighIndex As Long
+ Dim lngCount As Long
+ Dim lngIncrement As Long
+ Dim lngIndex As Long
+ Dim lngIndexCompare As Long
+ Dim udtCompare As udtAbbrevStatsType
+
+ lngCount = AbbrevAllCount
+ lngLowIndex = 1
+ lngHighIndex = lngCount
+
+ ' sort array[lngLowIndex..lngHighIndex]
+
+ ' compute largest increment
+ lngCount = lngHighIndex - lngLowIndex + 1
+ lngIncrement = 1
+ If (lngCount < 14) Then
+ lngIncrement = 1
+ Else
+ Do While lngIncrement < lngCount
+ lngIncrement = 3 * lngIncrement + 1
+ Loop
+ lngIncrement = lngIncrement \ 3
+ lngIncrement = lngIncrement \ 3
+ End If
+
+ Do While lngIncrement > 0
+ ' sort by insertion in increments of lngIncrement
+ For lngIndex = lngLowIndex + lngIncrement To lngHighIndex
+ udtCompare = AbbrevStats(lngIndex)
+ For lngIndexCompare = lngIndex - lngIncrement To lngLowIndex Step -lngIncrement
+ ' Use <= to sort ascending; Use > to sort descending
+ If AbbrevStats(lngIndexCompare).Symbol <= udtCompare.Symbol Then Exit For
+ AbbrevStats(lngIndexCompare + lngIncrement) = AbbrevStats(lngIndexCompare)
+ Next lngIndexCompare
+ AbbrevStats(lngIndexCompare + lngIncrement) = udtCompare
+ Next lngIndex
+ lngIncrement = lngIncrement \ 3
+ Loop
+
+ ' Need to re-construct the master symbols list
+ ConstructMasterSymbolsList
+
+End Sub
+
+Private Function SpacePadFront(ByRef strWork As String, intLength As Integer) As String
+
+ Do While Len(strWork) < intLength
+ strWork = " " & strWork
+ Loop
+ SpacePadFront = strWork
+
+End Function
+
+Public Function ValidateAllAbbreviationsInternal() As Long
+ ' Checks the formula of all abbreviations to make sure it's valid
+ ' Marks any abbreviations as Invalid if a problem is found or a circular reference exists
+ ' Returns a count of the number of invalid abbreviations found
+
+ Dim intAbbrevIndex As Integer
+ Dim intInvalidAbbreviationCount As Integer
+
+ For intAbbrevIndex = 1 To AbbrevAllCount
+ With AbbrevStats(intAbbrevIndex)
+ SetAbbreviationByIDInternal intAbbrevIndex, .Symbol, .Formula, .Charge, .IsAminoAcid, .OneLetterSymbol, .Comment, True
+ If .InvalidSymbolOrFormula Then
+ intInvalidAbbreviationCount = intInvalidAbbreviationCount + 1
+ End If
+ End With
+ Next intAbbrevIndex
+
+ ValidateAllAbbreviationsInternal = intInvalidAbbreviationCount
+
+End Function
diff --git a/MwtWinDll/clsCapillaryFlowClass.cls b/MwtWinDll/clsCapillaryFlowClass.cls
new file mode 100644
index 0000000..d0c2a9a
--- /dev/null
+++ b/MwtWinDll/clsCapillaryFlowClass.cls
@@ -0,0 +1,1312 @@
+VERSION 1.0 CLASS
+BEGIN
+ MultiUse = -1 'True
+ Persistable = 0 'NotPersistable
+ DataBindingBehavior = 0 'vbNone
+ DataSourceBehavior = 0 'vbNone
+ MTSTransactionMode = 0 'NotAnMTSObject
+END
+Attribute VB_Name = "MWCapillaryFlowClass"
+Attribute VB_GlobalNameSpace = False
+Attribute VB_Creatable = True
+Attribute VB_PredeclaredId = False
+Attribute VB_Exposed = True
+Option Explicit
+
+' Molecular Weight Calculator routines with ActiveX Class interfaces: MWCapillaryFlowClass
+' Written by Matthew Monroe in Richland, WA
+
+'
+Public Enum ctCapillaryTypeConstants
+ ctOpenTubularCapillary = 0
+ ctPackedCapillary
+End Enum
+
+Public Enum uprUnitsPressureConstants
+ uprPsi = 0
+ uprPascals
+ uprKiloPascals
+ uprAtmospheres
+ uprBar
+ uprTorr
+ uprDynesPerSquareCm
+End Enum
+
+Public Enum ulnUnitsLengthConstants
+ ulnM = 0
+ ulnCM
+ ulnMM
+ ulnMicrons
+ ulnInches
+End Enum
+
+Public Enum uviUnitsViscosityConstants
+ uviPoise = 0
+ uviCentiPoise
+End Enum
+
+Public Enum ufrUnitsFlowRateConstants
+ ufrMLPerMin = 0
+ ufrULPerMin
+ ufrNLPerMin
+End Enum
+
+Public Enum ulvUnitsLinearVelocityConstants
+ ulvCmPerHr = 0
+ ulvMmPerHr
+ ulvCmPerMin
+ ulvMmPerMin
+ ulvCmPerSec
+ ulvMmPerSec
+End Enum
+
+Public Enum utmUnitsTimeConstants
+ utmHours = 0
+ utmMinutes
+ utmSeconds
+End Enum
+
+Public Enum uvoUnitsVolumeConstants
+ uvoML = 0
+ uvoUL
+ uvoNL
+ uvoPL
+End Enum
+
+Public Enum ucoUnitsConcentrationConstants
+ ucoMolar = 0
+ ucoMilliMolar
+ ucoMicroMolar
+ ucoNanoMolar
+ ucoPicoMolar
+ ucoFemtoMolar
+ ucoAttoMolar
+ ucoMgPerML
+ ucoUgPerML
+ ucongperml
+ ucoUgPerUL
+ ucoNgPerUL
+End Enum
+
+Public Enum utpUnitsTemperatureConstants
+ utpCelsius = 0
+ utpKelvin
+ utpFahrenheit
+End Enum
+
+Public Enum umfMassFlowRateConstants
+ umfPmolPerMin = 0
+ umfFmolPerMin
+ umfAmolPerMin
+ umfPmolPerSec
+ umfFmolPerSec
+ umfAmolPerSec
+ umfMolesPerMin
+End Enum
+
+Public Enum umaMolarAmountConstants
+ umaMoles = 0
+ umaMilliMoles
+ umaMicroMoles
+ umaNanoMoles
+ umaPicoMoles
+ umaFemtoMoles
+ umaAttoMoles
+End Enum
+
+Public Enum udcDiffusionCoefficientConstants
+ udcCmSquaredPerHr = 0
+ udcCmSquaredPerMin
+ udcCmSquaredPerSec
+End Enum
+
+Public Enum acmAutoComputeModeConstants
+ acmBackPressure = 0
+ acmColumnID
+ acmColumnLength
+ acmDeadTime
+ acmLinearVelociy
+ acmVolFlowrate
+ acmVolFlowrateUsingDeadTime
+End Enum
+'
+
+'
+Private Type udtCapillaryFlowParametersType
+ CapillaryType As ctCapillaryTypeConstants
+ BackPressure As Double ' in dynes/cm^2
+ ColumnLength As Double ' in cm
+ ColumnID As Double ' in cm
+ SolventViscosity As Double ' in poise
+ ParticleDiameter As Double ' in cm
+ VolumetricFlowRate As Double ' in mL/min
+ LinearVelocity As Double ' cm/min
+ ColumnDeadTime As Double ' in min
+ InterparticlePorosity As Double
+End Type
+
+Private Type udtMassRateParametersType
+ SampleConcentration As Double ' in Molar
+ SampleMass As Double ' in g/mole
+ VolumetricFlowRate As Double ' in mL/min
+ InjectionTime As Double ' in min
+ MassFlowRate As Double ' in Moles/min
+ MolesInjected As Double ' in moles
+End Type
+
+Private Type udtExtraColumnBroadeningParametersType
+ LinearVelocity As Double ' in cm/min
+ DiffusionCoefficient As Double ' in cm^2/sec
+ OpenTubeLength As Double ' in cm
+ OpenTubeID As Double ' in cm
+ InitialPeakWidth As Double ' in sec
+ TemporalVariance As Double ' in sec^2
+ AdditionalTemporalVariance As Double ' in sec^2
+ ResultantPeakWidth As Double ' in sec
+End Type
+'
+
+' Conversion Factors
+Private Const CM_PER_INCH As Single = 2.54
+Private Const PI As Double = 3.14159265359
+
+Private mCapillaryFlowParameters As udtCapillaryFlowParametersType
+Private mMassRateParameters As udtMassRateParametersType
+Private mExtraColumnBroadeningParameters As udtExtraColumnBroadeningParametersType
+
+Private mAutoCompute As Boolean ' When true, automatically compute results whenever any value changes
+Private mAutoComputeMode As acmAutoComputeModeConstants ' The value to compute when mAutoCompute is true
+
+Private Sub CheckAutoCompute()
+ If mAutoCompute Then
+ Select Case mAutoComputeMode
+ Case acmBackPressure: ComputeBackPressure
+ Case acmColumnID: ComputeColumnID
+ Case acmColumnLength: ComputeColumnLength
+ Case acmDeadTime: ComputeDeadTime
+ Case acmLinearVelociy: ComputeLinearVelocity
+ Case acmVolFlowrateUsingDeadTime: ComputeVolFlowRateUsingDeadTime
+ Case Else
+ ' Includes acmVolFlowRate
+ ComputeVolFlowRate
+ End Select
+ End If
+End Sub
+
+Public Function ComputeBackPressure(Optional eUnits As uprUnitsPressureConstants = uprPsi, Optional blnComputeDeadTime As Boolean = True) As Double
+ ' Computes the back pressure, stores in .BackPressure, and returns it
+
+ Dim dblBackPressure As Double, dblRadius As Double
+
+ With mCapillaryFlowParameters
+
+ dblRadius = .ColumnID / 2#
+
+ If dblRadius <> 0 Then
+ If .CapillaryType = ctOpenTubularCapillary Then
+ ' Open tubular capillary
+ dblBackPressure = (.VolumetricFlowRate * 8 * .SolventViscosity * .ColumnLength) / (dblRadius ^ 4 * PI * 60) ' Pressure in dynes/cm^2
+ Else
+ ' Packed capillary
+ If .ParticleDiameter <> 0 And .InterparticlePorosity <> 0 Then
+ ' Flow rate in mL/sec
+ dblBackPressure = (.VolumetricFlowRate * 180 * .SolventViscosity * .ColumnLength * (1 - .InterparticlePorosity) ^ 2) / _
+ (.ParticleDiameter ^ 2 * .InterparticlePorosity ^ 2 * PI * dblRadius ^ 2 * 60) / .InterparticlePorosity
+ Else
+ dblBackPressure = 0
+ End If
+ End If
+ Else
+ dblBackPressure = 0
+ End If
+
+ .BackPressure = dblBackPressure
+ End With
+
+ If blnComputeDeadTime Then
+ ComputeDeadTime utmMinutes, False
+ End If
+
+ ' Compute Linear Velocity
+ ComputeLinearVelocity ulvCmPerSec, False
+
+ ' Return Back Pressure
+ ComputeBackPressure = ConvertPressure(dblBackPressure, uprDynesPerSquareCm, eUnits)
+
+End Function
+
+Public Function ComputeColumnLength(Optional eUnits As ulnUnitsLengthConstants = ulnCM) As Double
+ ' Computes the column length, stores in .ColumnLength, and returns it
+
+ Dim dblColumnLength As Double, dblRadius As Double
+
+ With mCapillaryFlowParameters
+
+ dblRadius = .ColumnID / 2#
+
+ If .SolventViscosity <> 0 And .VolumetricFlowRate <> 0 Then
+ If .CapillaryType = ctOpenTubularCapillary Then
+ ' Open tubular capillary
+ dblColumnLength = (.BackPressure * dblRadius ^ 4 * PI * 60) / (8 * .SolventViscosity * .VolumetricFlowRate) ' Column length in cm
+ Else
+ ' Packed capillary
+ If .InterparticlePorosity <> 1 Then
+ ' Flow rate in mL/sec
+ dblColumnLength = (.BackPressure * .ParticleDiameter ^ 2 * .InterparticlePorosity ^ 2 * PI * dblRadius ^ 2 * 60) * .InterparticlePorosity / _
+ (180 * .SolventViscosity * .VolumetricFlowRate * (1 - .InterparticlePorosity) ^ 2)
+ Else
+ dblColumnLength = 0
+ End If
+ End If
+ Else
+ dblColumnLength = 0
+ End If
+
+ .ColumnLength = dblColumnLength
+ End With
+
+ ' Compute Dead Time (and Linear Velocity)
+ ComputeDeadTime utmMinutes, False
+
+ ' Return Column Length
+ ComputeColumnLength = ConvertLength(dblColumnLength, ulnCM, eUnits)
+
+End Function
+
+Public Function ComputeColumnVolume(Optional eUnits As uvoUnitsVolumeConstants) As Double
+ ' Computes the column volume and returns it (does not store it)
+
+ Dim dblColumnVolume As Double, dblRadius As Double
+
+ With mCapillaryFlowParameters
+
+ dblRadius = .ColumnID / 2#
+
+ dblColumnVolume = .ColumnLength * PI * dblRadius ^ 2 ' In mL
+
+ If .CapillaryType = ctPackedCapillary Then
+ dblColumnVolume = dblColumnVolume * .InterparticlePorosity
+ End If
+ End With
+
+ ComputeColumnVolume = ConvertVolume(dblColumnVolume, uvoML, eUnits)
+
+End Function
+
+Public Function ComputeColumnID(Optional eUnits As ulnUnitsLengthConstants = ulnMicrons) As Double
+ ' Computes the column length, stores in .ColumnLength, and returns it
+
+ Dim dblRadius As Double
+
+ With mCapillaryFlowParameters
+
+ If .BackPressure <> 0 Then
+ If .CapillaryType = ctOpenTubularCapillary Then
+ ' Open tubular capillary
+ dblRadius = ((.VolumetricFlowRate * 8 * .SolventViscosity * .ColumnLength) / _
+ (.BackPressure * PI * 60)) ^ (0.25)
+ Else
+ ' Packed capillary
+ If .ParticleDiameter <> 0 And .InterparticlePorosity <> 1 And .InterparticlePorosity <> 0 Then
+ ' Flow rate in mL/sec
+ dblRadius = ((.VolumetricFlowRate * 180 * .SolventViscosity * .ColumnLength * (1 - .InterparticlePorosity) ^ 2) / _
+ (.BackPressure * .ParticleDiameter ^ 2 * .InterparticlePorosity ^ 2 * PI * 60) / .InterparticlePorosity) ^ 0.5
+ Else
+ dblRadius = 0
+ End If
+ End If
+ Else
+ dblRadius = 0
+ End If
+
+ .ColumnID = dblRadius * 2#
+ End With
+
+ ' Compute Dead Time (and Linear Velocity)
+ ComputeDeadTime utmMinutes, False
+
+ ' Return Column ID
+ ComputeColumnID = ConvertLength(dblRadius * 2#, ulnCM, eUnits)
+
+End Function
+
+Public Function ComputeDeadTime(Optional eUnits As utmUnitsTimeConstants = utmMinutes, Optional blnRecalculateVolFlowRate As Boolean = True) As Double
+ ' Computes the column dead time, stores in .ColumnDeadTime, and returns it
+
+ Dim dblDeadTime As Double
+
+ ' Dead time is dependent on Linear Velocity, so compute
+ ComputeLinearVelocity ulvCmPerSec, blnRecalculateVolFlowRate
+
+ With mCapillaryFlowParameters
+
+ If .LinearVelocity <> 0 Then
+ dblDeadTime = .ColumnLength / .LinearVelocity ' Dead time in minutes
+ Else
+ dblDeadTime = 0
+ End If
+
+ .ColumnDeadTime = dblDeadTime
+ End With
+
+ ' Return Dead Time
+ ComputeDeadTime = ConvertTime(mCapillaryFlowParameters.ColumnDeadTime, utmMinutes, eUnits)
+
+End Function
+
+Public Function ComputeExtraColumnBroadeningResultantPeakWidth(Optional eUnits As utmUnitsTimeConstants = utmSeconds) As Double
+ ComputeExtraColumnBroadeningValues
+
+ ComputeExtraColumnBroadeningResultantPeakWidth = GetExtraColumnBroadeningResultantPeakWidth(eUnits)
+End Function
+
+Private Sub ComputeExtraColumnBroadeningValues()
+ Dim dblInitialPeakVariance As Double
+ Dim dblSumOfVariances As Double
+
+ With mExtraColumnBroadeningParameters
+ If .LinearVelocity <> 0 And .DiffusionCoefficient <> 0 Then
+ .TemporalVariance = .OpenTubeID ^ 2 * .OpenTubeLength / (96 * .DiffusionCoefficient * .LinearVelocity / 60) ' in sec^2
+ Else
+ .TemporalVariance = 0
+ End If
+
+ dblInitialPeakVariance = (.InitialPeakWidth / 4) ^ 2
+
+ dblSumOfVariances = dblInitialPeakVariance + .TemporalVariance + .AdditionalTemporalVariance
+
+ If dblSumOfVariances >= 0 Then
+ ' ResultantPeakWidth at the base = 4 sigma and sigma = Sqr(Total_Variance)
+ .ResultantPeakWidth = 4 * Sqr(dblSumOfVariances)
+ Else
+ .ResultantPeakWidth = 0
+ End If
+ End With
+End Sub
+
+Public Function ComputeLinearVelocity(Optional eUnits As ulvUnitsLinearVelocityConstants = ulvCmPerSec, Optional blnRecalculateVolFlowRate As Boolean = True) As Double
+ ' Computes the Linear velocity, stores in .LinearVelocity, and returns it
+
+ Dim dblLinearVelocity As Double, dblRadius As Double
+
+ If blnRecalculateVolFlowRate Then
+ ComputeVolFlowRate ufrMLPerMin
+ End If
+
+ With mCapillaryFlowParameters
+ dblRadius = .ColumnID / 2#
+ If dblRadius <> 0 Then
+ dblLinearVelocity = .VolumetricFlowRate / (PI * dblRadius ^ 2) ' Units in cm/min
+
+ ' Divide Linear Velocity by epsilon if a packed capillary
+ If .CapillaryType = ctPackedCapillary And .InterparticlePorosity <> 0 Then
+ dblLinearVelocity = dblLinearVelocity / .InterparticlePorosity
+ End If
+ Else
+ dblLinearVelocity = 0
+ End If
+
+ .LinearVelocity = dblLinearVelocity
+ End With
+
+ ' Return Linear Velocity
+ ComputeLinearVelocity = ConvertLinearVelocity(dblLinearVelocity, ulvCmPerMin, eUnits)
+
+End Function
+
+Public Function ComputeMassFlowRate(Optional eUnits As umfMassFlowRateConstants = umfFmolPerSec) As Double
+ ' Computes the MassFlowRate and Moles Injected, stores in .MassFlowRate and .MolesInjected, and returns MassFlowRate
+
+ ComputeMassRateValues
+ ComputeMassFlowRate = GetMassFlowRate(eUnits)
+
+End Function
+
+Public Function ComputeMassRateMolesInjected(Optional eUnits As umaMolarAmountConstants = umaFemtoMoles) As Double
+ ' Computes the MassFlowRate and Moles Injected, stores in .MassFlowRate and .MolesInjected, and returns MassFlowRate
+
+ ComputeMassRateValues
+ ComputeMassRateMolesInjected = GetMassRateMolesInjected(eUnits)
+
+End Function
+
+Private Sub ComputeMassRateValues()
+
+ With mMassRateParameters
+ .MassFlowRate = .SampleConcentration * .VolumetricFlowRate / 1000 ' Compute mass flowrate in moles/min
+
+ .MolesInjected = .MassFlowRate * .InjectionTime ' Compute moles injected in moles
+ End With
+
+End Sub
+
+Public Function ComputeOptimumLinearVelocityUsingParticleDiamAndDiffusionCoeff(Optional eUnits As ulvUnitsLinearVelocityConstants = ulvCmPerSec) As Double
+ ' Computes the optimum linear velocity, based on
+ ' mCapillaryFlowParameters.ParticleDiameter
+ ' and mExtraColumnBroadeningParameters.DiffusionCoefficient
+
+ Dim dblOptimumLinearVelocity As Double
+
+ With mCapillaryFlowParameters
+ If .ParticleDiameter <> 0 Then
+ dblOptimumLinearVelocity = 3 * mExtraColumnBroadeningParameters.DiffusionCoefficient / .ParticleDiameter
+
+ dblOptimumLinearVelocity = ConvertLinearVelocity(dblOptimumLinearVelocity, ulvCmPerSec, eUnits)
+ End If
+ End With
+
+ ComputeOptimumLinearVelocityUsingParticleDiamAndDiffusionCoeff = dblOptimumLinearVelocity
+
+End Function
+
+Public Function ComputeMeCNViscosity(dblPercentAcetonitrile As Double, dblTemperature As Double, Optional eTemperatureUnits As utpUnitsTemperatureConstants = utpCelsius, Optional eViscosityUnits As uviUnitsViscosityConstants = uviPoise) As Double
+
+ Dim dblPhi As Double ' Fraction Acetonitrile
+ Dim dblKelvin As Double
+ Dim dblViscosityInCentiPoise As Double
+
+ On Error GoTo ComputeMeCNViscosityErrorHandler
+
+ dblPhi = dblPercentAcetonitrile / 100#
+ If dblPhi < 0 Then dblPhi = 0
+ If dblPhi > 100 Then dblPhi = 100
+
+ dblKelvin = ConvertTemperature(dblTemperature, eTemperatureUnits, utpKelvin)
+
+ If dblKelvin > 0 Then
+ dblViscosityInCentiPoise = Exp(dblPhi * (-3.476 + 726 / dblKelvin) + (1 - dblPhi) * (-5.414 + 1566 / dblKelvin) + dblPhi * (1 - dblPhi) * (-1.762 + 929 / dblKelvin))
+ Else
+ dblViscosityInCentiPoise = 0
+ End If
+
+ ComputeMeCNViscosity = ConvertViscosity(dblViscosityInCentiPoise, uviCentiPoise, eViscosityUnits)
+ Exit Function
+
+ComputeMeCNViscosityErrorHandler:
+ ComputeMeCNViscosity = 0
+
+End Function
+
+
+Public Function ComputeVolFlowRate(Optional eUnits As ufrUnitsFlowRateConstants = ufrNLPerMin) As Double
+ ' Computes the Volumetric flow rate, stores in .VolumetricFlowRate, and returns it
+
+ Dim dblVolFlowRate As Double, dblRadius As Double
+
+ With mCapillaryFlowParameters
+
+ dblRadius = .ColumnID / 2#
+
+ If .SolventViscosity <> 0 And .ColumnLength <> 0 Then
+ If .CapillaryType = ctOpenTubularCapillary Then
+ ' Open tubular capillary
+ dblVolFlowRate = (.BackPressure * dblRadius ^ 4 * PI) / (8 * .SolventViscosity * .ColumnLength) ' Flow rate in mL/sec
+ Else
+ ' Packed capillary
+ If .InterparticlePorosity <> 1 Then
+ ' Flow rate in mL/sec
+ dblVolFlowRate = (.BackPressure * .ParticleDiameter ^ 2 * .InterparticlePorosity ^ 2 * PI * dblRadius ^ 2) * .InterparticlePorosity / _
+ (180 * .SolventViscosity * .ColumnLength * (1 - .InterparticlePorosity) ^ 2)
+ Else
+ dblVolFlowRate = 0
+ End If
+ End If
+
+ ' Convert dblVolFlowRate to mL/min
+ dblVolFlowRate = dblVolFlowRate * 60
+ Else
+ dblVolFlowRate = 0
+ End If
+
+ .VolumetricFlowRate = dblVolFlowRate
+ End With
+
+ ' Compute Dead Time (and Linear Velocity)
+ ComputeDeadTime utmMinutes, False
+
+ ComputeVolFlowRate = ConvertVolFlowRate(dblVolFlowRate, ufrMLPerMin, eUnits)
+End Function
+
+Public Function ComputeVolFlowRateUsingDeadTime(Optional eUnits As ufrUnitsFlowRateConstants = ufrNLPerMin, Optional ByRef dblNewBackPressure As Double, Optional ePressureUnits As uprUnitsPressureConstants = uprPsi) As Double
+ ' Computes the Volumetric flow rate using the dead time, stores in .VolumetricFlowRate, and returns it
+ ' This requires modifying the pressure value to give the computed volumetric flow rate
+
+ Dim dblVolFlowRate As Double, dblRadius As Double
+
+ With mCapillaryFlowParameters
+
+ dblRadius = .ColumnID / 2#
+
+ ' First find vol flow rate that gives observed dead time
+ If .ColumnDeadTime <> 0 Then
+
+ dblVolFlowRate = .ColumnLength * (PI * dblRadius ^ 2) / .ColumnDeadTime ' Vol flow rate in mL/sec
+
+ If .CapillaryType = ctPackedCapillary Then
+ ' Packed Capillary
+ dblVolFlowRate = dblVolFlowRate * .InterparticlePorosity
+ End If
+
+ ' Store the new value
+ .VolumetricFlowRate = dblVolFlowRate
+
+ ' Now find pressure that gives computed dblVolFlowRate
+ ' The ComputeBackPressure sub will store the new pressure
+ dblNewBackPressure = ComputeBackPressure(ePressureUnits, False)
+ Else
+ dblVolFlowRate = 0
+ .VolumetricFlowRate = 0
+ End If
+
+ End With
+
+ ' Compute Linear Velocity (but not the dead time)
+ ComputeLinearVelocity ulvCmPerSec, False
+
+ ComputeVolFlowRateUsingDeadTime = ConvertVolFlowRate(dblVolFlowRate, ufrMLPerMin, eUnits)
+End Function
+
+' Duplicated function, in both MWCapillaryFlowClass and MWMoleMassDilutionClass
+Public Function ConvertConcentration(dblConcentrationIn As Double, eCurrentUnits As ucoUnitsConcentrationConstants, eNewUnits As ucoUnitsConcentrationConstants) As Double
+ Dim dblValue As Double, dblFactor As Double
+ Dim dblSampleMass As Double
+
+ If eCurrentUnits = eNewUnits Then
+ ConvertConcentration = dblConcentrationIn
+ Exit Function
+ End If
+
+ dblSampleMass = mMassRateParameters.SampleMass
+
+ dblFactor = FactorConcentration(eCurrentUnits, dblSampleMass)
+ If dblFactor = -1 Then
+ ConvertConcentration = -1
+ Exit Function
+ Else
+ dblValue = dblConcentrationIn * dblFactor
+ End If
+
+ dblFactor = FactorConcentration(eNewUnits, dblSampleMass)
+ If dblFactor = -1 Or dblFactor = 0 Then
+ ConvertConcentration = -1
+ Else
+ ConvertConcentration = dblValue / dblFactor
+ End If
+
+End Function
+
+Public Function ConvertDiffusionCoefficient(dblDiffusionCoefficientIn As Double, eCurrentUnits As udcDiffusionCoefficientConstants, eNewUnits As udcDiffusionCoefficientConstants) As Double
+ Dim dblValue As Double, dblFactor As Double
+
+ If eCurrentUnits = eNewUnits Then
+ ConvertDiffusionCoefficient = dblDiffusionCoefficientIn
+ Exit Function
+ End If
+
+ dblFactor = FactorDiffusionCoeff(eCurrentUnits)
+ If dblFactor = -1 Then
+ ConvertDiffusionCoefficient = -1
+ Exit Function
+ Else
+ dblValue = dblDiffusionCoefficientIn * dblFactor
+ End If
+
+ dblFactor = FactorDiffusionCoeff(eNewUnits)
+ If dblFactor = -1 Or dblFactor = 0 Then
+ ConvertDiffusionCoefficient = -1
+ Else
+ ConvertDiffusionCoefficient = dblValue / dblFactor
+ End If
+
+End Function
+
+Public Function ConvertLength(dblLengthIn As Double, eCurrentUnits As ulnUnitsLengthConstants, eNewUnits As ulnUnitsLengthConstants) As Double
+ Dim dblValue As Double, dblFactor As Double
+
+ If eCurrentUnits = eNewUnits Then
+ ConvertLength = dblLengthIn
+ Exit Function
+ End If
+
+ dblFactor = FactorLength(eCurrentUnits)
+ If dblFactor = -1 Then
+ ConvertLength = -1
+ Exit Function
+ Else
+ dblValue = dblLengthIn * dblFactor
+ End If
+
+ dblFactor = FactorLength(eNewUnits)
+ If dblFactor = -1 Or dblFactor = 0 Then
+ ConvertLength = -1
+ Else
+ ConvertLength = dblValue / dblFactor
+ End If
+
+End Function
+
+Public Function ConvertLinearVelocity(dblLinearVelocityIn As Double, eCurrentUnits As ulvUnitsLinearVelocityConstants, eNewUnits As ulvUnitsLinearVelocityConstants) As Double
+ Dim dblValue As Double, dblFactor As Double
+
+ If eCurrentUnits = eNewUnits Then
+ ConvertLinearVelocity = dblLinearVelocityIn
+ Exit Function
+ End If
+
+ dblFactor = FactorLinearVelocity(eCurrentUnits)
+ If dblFactor = -1 Then
+ ConvertLinearVelocity = -1
+ Exit Function
+ Else
+ dblValue = dblLinearVelocityIn * dblFactor
+ End If
+
+ dblFactor = FactorLinearVelocity(eNewUnits)
+ If dblFactor = -1 Or dblFactor = 0 Then
+ ConvertLinearVelocity = -1
+ Else
+ ConvertLinearVelocity = dblValue / dblFactor
+ End If
+
+End Function
+
+Public Function ConvertMassFlowRate(dblMassFlowRateIn As Double, eCurrentUnits As umfMassFlowRateConstants, eNewUnits As umfMassFlowRateConstants) As Double
+ Dim dblValue As Double, dblFactor As Double
+
+ If eCurrentUnits = eNewUnits Then
+ ConvertMassFlowRate = dblMassFlowRateIn
+ Exit Function
+ End If
+
+ dblFactor = FactorMassFlowRate(eCurrentUnits)
+ If dblFactor = -1 Then
+ ConvertMassFlowRate = -1
+ Exit Function
+ Else
+ dblValue = dblMassFlowRateIn * dblFactor
+ End If
+
+ dblFactor = FactorMassFlowRate(eNewUnits)
+ If dblFactor = -1 Or dblFactor = 0 Then
+ ConvertMassFlowRate = -1
+ Else
+ ConvertMassFlowRate = dblValue / dblFactor
+ End If
+
+End Function
+
+Public Function ConvertMoles(dblMolesIn As Double, eCurrentUnits As umaMolarAmountConstants, eNewUnits As umaMolarAmountConstants) As Double
+ Dim dblValue As Double, dblFactor As Double
+
+ If eCurrentUnits = eNewUnits Then
+ ConvertMoles = dblMolesIn
+ Exit Function
+ End If
+
+ dblFactor = FactorMoles(eCurrentUnits)
+ If dblFactor = -1 Then
+ ConvertMoles = -1
+ Exit Function
+ Else
+ dblValue = dblMolesIn * dblFactor
+ End If
+
+ dblFactor = FactorMoles(eNewUnits)
+ If dblFactor = -1 Or dblFactor = 0 Then
+ ConvertMoles = -1
+ Else
+ ConvertMoles = dblValue / dblFactor
+ End If
+
+End Function
+
+
+Public Function ConvertPressure(dblPressureIn As Double, eCurrentUnits As uprUnitsPressureConstants, eNewUnits As uprUnitsPressureConstants) As Double
+ Dim dblValue As Double, dblFactor As Double
+
+ If eCurrentUnits = eNewUnits Then
+ ConvertPressure = dblPressureIn
+ Exit Function
+ End If
+
+ dblFactor = FactorPressure(eCurrentUnits)
+ If dblFactor = -1 Then
+ ConvertPressure = -1
+ Exit Function
+ Else
+ dblValue = dblPressureIn * dblFactor
+ End If
+
+ dblFactor = FactorPressure(eNewUnits)
+ If dblFactor = -1 Or dblFactor = 0 Then
+ ConvertPressure = -1
+ Else
+ ConvertPressure = dblValue / dblFactor
+ End If
+
+End Function
+
+Public Function ConvertTemperature(dblTemperatureIn As Double, eCurrentUnits As utpUnitsTemperatureConstants, eNewUnits As utpUnitsTemperatureConstants) As Double
+ Dim dblValue As Double
+
+ If eCurrentUnits = eNewUnits Then
+ ConvertTemperature = dblTemperatureIn
+ Exit Function
+ End If
+
+ ' First convert to Kelvin
+ Select Case eCurrentUnits
+ Case utpCelsius
+ ' K = C + 273
+ dblValue = dblTemperatureIn + 273
+ Case utpFahrenheit
+ ' Convert to Kelvin: C = 5/9*(F-32) and K = C + 273
+ dblValue = 5# / 9# * (dblTemperatureIn - 32) + 273
+ Case Else
+ ' Includes utpKelvin
+ ' Assume already Kelvin
+ End Select
+
+ ' We cannot get colder than absolute 0
+ If dblValue < 0 Then dblValue = 0
+
+ ' Now convert to the target units
+ Select Case eNewUnits
+ Case utpCelsius
+ ' C = K - 273
+ dblValue = dblValue - 273
+ Case utpFahrenheit
+ ' Convert to Fahrenheit: C = K - 273 and F = (9/5)C + 32
+ dblValue = 9# / 5# * (dblValue - 273) + 32
+ Case Else
+ ' Includes utpKelvin
+ ' Already in Kelvin
+ End Select
+
+ ConvertTemperature = dblValue
+
+End Function
+
+Public Function ConvertTime(dblTimeIn As Double, eCurrentUnits As utmUnitsTimeConstants, eNewUnits As utmUnitsTimeConstants) As Double
+ Dim dblValue As Double, dblFactor As Double
+
+ If eCurrentUnits = eNewUnits Then
+ ConvertTime = dblTimeIn
+ Exit Function
+ End If
+
+ dblFactor = FactorTime(eCurrentUnits)
+ If dblFactor = -1 Then
+ ConvertTime = -1
+ Exit Function
+ Else
+ dblValue = dblTimeIn * dblFactor
+ End If
+
+ dblFactor = FactorTime(eNewUnits)
+ If dblFactor = -1 Or dblFactor = 0 Then
+ ConvertTime = -1
+ Else
+ ConvertTime = dblValue / dblFactor
+ End If
+
+End Function
+
+Public Function ConvertViscosity(dblViscosityIn As Double, eCurrentUnits As uviUnitsViscosityConstants, eNewUnits As uviUnitsViscosityConstants) As Double
+ Dim dblValue As Double, dblFactor As Double
+
+ If eCurrentUnits = eNewUnits Then
+ ConvertViscosity = dblViscosityIn
+ Exit Function
+ End If
+
+ dblFactor = FactorViscosity(eCurrentUnits)
+ If dblFactor = -1 Then
+ ConvertViscosity = -1
+ Exit Function
+ Else
+ dblValue = dblViscosityIn * dblFactor
+ End If
+
+ dblFactor = FactorViscosity(eNewUnits)
+ If dblFactor = -1 Or dblFactor = 0 Then
+ ConvertViscosity = -1
+ Else
+ ConvertViscosity = dblValue / dblFactor
+ End If
+
+End Function
+
+Public Function ConvertVolFlowRate(dblVolFlowRateIn As Double, eCurrentUnits As ufrUnitsFlowRateConstants, eNewUnits As ufrUnitsFlowRateConstants) As Double
+ Dim dblValue As Double, dblFactor As Double
+
+ If eCurrentUnits = eNewUnits Then
+ ConvertVolFlowRate = dblVolFlowRateIn
+ Exit Function
+ End If
+
+ dblFactor = FactorVolFlowRate(eCurrentUnits)
+ If dblFactor = -1 Then
+ ConvertVolFlowRate = -1
+ Exit Function
+ Else
+ dblValue = dblVolFlowRateIn * dblFactor
+ End If
+
+ dblFactor = FactorVolFlowRate(eNewUnits)
+ If dblFactor = -1 Or dblFactor = 0 Then
+ ConvertVolFlowRate = -1
+ Else
+ ConvertVolFlowRate = dblValue / dblFactor
+ End If
+
+End Function
+
+Public Function ConvertVolume(dblVolume As Double, eCurrentUnits As uvoUnitsVolumeConstants, eNewUnits As uvoUnitsVolumeConstants) As Double
+ Dim dblValue As Double, dblFactor As Double
+
+ If eCurrentUnits = eNewUnits Then
+ ConvertVolume = dblVolume
+ Exit Function
+ End If
+
+ dblFactor = FactorVolume(eCurrentUnits)
+ If dblFactor = -1 Then
+ ConvertVolume = -1
+ Exit Function
+ Else
+ dblValue = dblVolume * dblFactor
+ End If
+
+ dblFactor = FactorVolume(eNewUnits)
+ If dblFactor = -1 Or dblFactor = 0 Then
+ ConvertVolume = -1
+ Else
+ ConvertVolume = dblValue / dblFactor
+ End If
+
+End Function
+
+' Multiplication factor for converting from eUnits to M
+' dblSampleMass is required for mass-based units
+' Duplicated function, in both MWCapillaryFlowClass and MWMoleMassDilutionClass
+Private Function FactorConcentration(eUnits As ucoUnitsConcentrationConstants, Optional ByVal dblSampleMass As Double = 0) As Double
+ Dim dblFactor As Double
+
+ If dblSampleMass = 0 Then
+ dblFactor = -1
+ Else
+ Select Case eUnits
+ Case ucoMolar: dblFactor = 1#
+ Case ucoMilliMolar: dblFactor = 1 / 1000#
+ Case ucoMicroMolar: dblFactor = 1 / 1000000#
+ Case ucoNanoMolar: dblFactor = 1 / 1000000000#
+ Case ucoPicoMolar: dblFactor = 1 / 1000000000000#
+ Case ucoFemtoMolar: dblFactor = 1 / 1E+15
+ Case ucoAttoMolar: dblFactor = 1 / 1E+18
+ Case ucoMgPerML: dblFactor = 1 / dblSampleMass '1/[(1 g / 1000 mg) * (1 / MW) * (1000 mL/L)]
+ Case ucoUgPerML: dblFactor = 1 / (dblSampleMass * 1000#) '1/[(1 g / 1000000 ug) * (1 / MW) * (1000 mL/L)]
+ Case ucongperml: dblFactor = 1 / (dblSampleMass * 1000000#) '1/[(1 g / 1000000000 ng) * (1 / MW) * (1000 mL/L)]
+ Case ucoUgPerUL: dblFactor = 1 / (dblSampleMass) '1/[(1 g / 1000000 ug) * (1 / MW) * (1000000 uL/L)]
+ Case ucoNgPerUL: dblFactor = 1 / (dblSampleMass * 1000#) '1/[(1 g / 1000000000 ng) * (1 / MW) * (1000000 uL/L)]
+ Case Else: dblFactor = -1
+ End Select
+ End If
+
+ FactorConcentration = dblFactor
+End Function
+
+' Multiplication factor for converting from eUnits to Cm
+Private Function FactorLength(eUnits As ulnUnitsLengthConstants) As Double
+
+ Select Case eUnits
+ Case ulnM: FactorLength = 100#
+ Case ulnCM: FactorLength = 1#
+ Case ulnMM: FactorLength = 1 / 10#
+ Case ulnMicrons: FactorLength = 1 / 10000#
+ Case ulnInches: FactorLength = CM_PER_INCH
+ Case Else: FactorLength = -1
+ End Select
+
+End Function
+
+' Multiplication factor for converting from eUnits to Cm/Min
+Private Function FactorLinearVelocity(eUnits As ulvUnitsLinearVelocityConstants) As Double
+
+ Select Case eUnits
+ Case ulvCmPerHr: FactorLinearVelocity = 1 / 60#
+ Case ulvMmPerHr: FactorLinearVelocity = 1 / 60# / 10#
+ Case ulvCmPerMin: FactorLinearVelocity = 1
+ Case ulvMmPerMin: FactorLinearVelocity = 1 / 10#
+ Case ulvCmPerSec: FactorLinearVelocity = 60#
+ Case ulvMmPerSec: FactorLinearVelocity = 60# / 10#
+ Case Else: FactorLinearVelocity = -1
+ End Select
+
+End Function
+
+' Multiplication factor for converting from eUnits to moles/min
+Private Function FactorMassFlowRate(eUnits As umfMassFlowRateConstants) As Double
+
+ Select Case eUnits
+ Case umfPmolPerMin: FactorMassFlowRate = 1 / 1000000000000#
+ Case umfFmolPerMin: FactorMassFlowRate = 1 / 1E+15
+ Case umfAmolPerMin: FactorMassFlowRate = 1 / 1E+18
+ Case umfPmolPerSec: FactorMassFlowRate = 1 / (1000000000000# / 60#)
+ Case umfFmolPerSec: FactorMassFlowRate = 1 / (1E+15 / 60#)
+ Case umfAmolPerSec: FactorMassFlowRate = 1 / (1E+18 / 60#)
+ Case umfMolesPerMin: FactorMassFlowRate = 1#
+ Case Else: FactorMassFlowRate = -1
+ End Select
+
+End Function
+
+' Multiplication factor for converting from eUnits to moles
+Private Function FactorMoles(eUnits As umaMolarAmountConstants) As Double
+
+ Select Case eUnits
+ Case umaMoles: FactorMoles = 1#
+ Case umaMilliMoles: FactorMoles = 1 / 1000#
+ Case umaMicroMoles: FactorMoles = 1 / 1000000#
+ Case umaNanoMoles: FactorMoles = 1 / 1000000000#
+ Case umaPicoMoles: FactorMoles = 1 / 1000000000000#
+ Case umaFemtoMoles: FactorMoles = 1 / 1E+15
+ Case umaAttoMoles: FactorMoles = 1 / 1E+18
+ Case Else: FactorMoles = -1
+ End Select
+
+End Function
+
+' Multiplication factor for converting from eUnits to dynes per cm^2
+Private Function FactorPressure(eUnits As uprUnitsPressureConstants) As Double
+
+ Select Case eUnits
+ Case uprPsi: FactorPressure = 68947.57
+ Case uprPascals: FactorPressure = 10#
+ Case uprKiloPascals: FactorPressure = 10000#
+ Case uprAtmospheres: FactorPressure = 1013250#
+ Case uprBar: FactorPressure = 1000000#
+ Case uprTorr: FactorPressure = 1333.22
+ Case uprDynesPerSquareCm: FactorPressure = 1
+ Case Else: FactorPressure = -1
+ End Select
+
+End Function
+
+' Multiplication factor for converting from eUnits to minutes
+Private Function FactorTime(eUnits As utmUnitsTimeConstants) As Double
+
+ Select Case eUnits
+ Case utmHours: FactorTime = 60#
+ Case utmMinutes: FactorTime = 1#
+ Case utmSeconds: FactorTime = 1 / 60#
+ Case Else: FactorTime = -1
+ End Select
+
+End Function
+
+' Multiplication factor for converting from eUnits to cm^2/sec
+Private Function FactorDiffusionCoeff(eUnits As udcDiffusionCoefficientConstants) As Double
+
+ Select Case eUnits
+ Case udcCmSquaredPerHr: FactorDiffusionCoeff = 1 / 3600#
+ Case udcCmSquaredPerMin: FactorDiffusionCoeff = 1 / 60#
+ Case udcCmSquaredPerSec: FactorDiffusionCoeff = 1#
+ Case Else: FactorDiffusionCoeff = -1
+ End Select
+
+End Function
+
+' Multiplication factor for converting from eUnits to poise
+Private Function FactorViscosity(eUnits As uviUnitsViscosityConstants) As Double
+
+ Select Case eUnits
+ Case uviPoise: FactorViscosity = 1#
+ Case uviCentiPoise: FactorViscosity = 1 / 100#
+ Case Else: FactorViscosity = -1
+ End Select
+
+End Function
+
+' Multiplication factor for converting from eUnits to mL/min
+Private Function FactorVolFlowRate(eUnits As ufrUnitsFlowRateConstants) As Double
+
+ Select Case eUnits
+ Case ufrMLPerMin: FactorVolFlowRate = 1#
+ Case ufrULPerMin: FactorVolFlowRate = 1 / 1000#
+ Case ufrNLPerMin: FactorVolFlowRate = 1 / 1000000#
+ Case Else: FactorVolFlowRate = -1
+ End Select
+
+End Function
+
+' Multiplication factor for converting from eUnits to mL
+Private Function FactorVolume(eUnits As uvoUnitsVolumeConstants) As Double
+
+ Select Case eUnits
+ Case uvoML: FactorVolume = 1#
+ Case uvoUL: FactorVolume = 1 / 1000#
+ Case uvoNL: FactorVolume = 1 / 1000000#
+ Case uvoPL: FactorVolume = 1 / 1000000000#
+ Case Else: FactorVolume = -1
+ End Select
+
+End Function
+
+' Get Subs
+' Gets the most recently computed value
+' If mAutoCompute = False, then must manually call a Compute Sub to recompute the value
+
+Public Function GetAutoComputeEnabled() As Boolean
+ GetAutoComputeEnabled = mAutoCompute
+End Function
+
+Public Function GetAutoComputeMode() As acmAutoComputeModeConstants
+ GetAutoComputeMode = mAutoComputeMode
+End Function
+
+Public Function GetBackPressure(Optional eUnits As uprUnitsPressureConstants = uprPsi) As Double
+ GetBackPressure = ConvertPressure(mCapillaryFlowParameters.BackPressure, uprDynesPerSquareCm, eUnits)
+End Function
+
+Public Function GetCapillaryType() As ctCapillaryTypeConstants
+ GetCapillaryType = mCapillaryFlowParameters.CapillaryType
+End Function
+
+Public Function GetColumnID(Optional eUnits As ulnUnitsLengthConstants = ulnMicrons) As Double
+ GetColumnID = ConvertLength(mCapillaryFlowParameters.ColumnID, ulnCM, eUnits)
+End Function
+
+Public Function GetColumnLength(Optional eUnits As ulnUnitsLengthConstants = ulnCM) As Double
+ GetColumnLength = ConvertLength(mCapillaryFlowParameters.ColumnLength, ulnCM, eUnits)
+End Function
+
+Public Function GetColumnVolume(Optional eUnits As uvoUnitsVolumeConstants = uvoUL) As Double
+ ' Column volume isn't stored; simply re-compute it
+ GetColumnVolume = ComputeColumnVolume(eUnits)
+End Function
+
+Public Function GetDeadTime(Optional eUnits As utmUnitsTimeConstants = utmMinutes) As Double
+ GetDeadTime = ConvertTime(mCapillaryFlowParameters.ColumnDeadTime, utmMinutes, eUnits)
+End Function
+
+Public Function GetExtraColumnBroadeningAdditionalVarianceInSquareSeconds() As Double
+ GetExtraColumnBroadeningAdditionalVarianceInSquareSeconds = mExtraColumnBroadeningParameters.AdditionalTemporalVariance
+End Function
+
+Public Function GetExtraColumnBroadeningDiffusionCoefficient(Optional eUnits As udcDiffusionCoefficientConstants = udcCmSquaredPerSec) As Double
+ GetExtraColumnBroadeningDiffusionCoefficient = ConvertDiffusionCoefficient(mExtraColumnBroadeningParameters.DiffusionCoefficient, udcCmSquaredPerSec, eUnits)
+End Function
+
+Public Function GetExtraColumnBroadeningInitialPeakWidthAtBase(Optional eUnits As utmUnitsTimeConstants = utmSeconds) As Double
+ GetExtraColumnBroadeningInitialPeakWidthAtBase = ConvertTime(mExtraColumnBroadeningParameters.InitialPeakWidth, utmSeconds, eUnits)
+End Function
+
+Public Function GetExtraColumnBroadeningLinearVelocity(Optional eUnits As ulvUnitsLinearVelocityConstants = ulvMmPerMin) As Double
+ GetExtraColumnBroadeningLinearVelocity = ConvertLinearVelocity(mExtraColumnBroadeningParameters.LinearVelocity, ulvCmPerMin, eUnits)
+End Function
+
+Public Function GetExtraColumnBroadeningOpenTubeID(Optional eUnits As ulnUnitsLengthConstants = ulnMicrons) As Double
+ GetExtraColumnBroadeningOpenTubeID = ConvertLength(mExtraColumnBroadeningParameters.OpenTubeID, ulnCM, eUnits)
+End Function
+
+Public Function GetExtraColumnBroadeningOpenTubeLength(Optional eUnits As ulnUnitsLengthConstants = ulnCM) As Double
+ GetExtraColumnBroadeningOpenTubeLength = ConvertLength(mExtraColumnBroadeningParameters.OpenTubeLength, ulnCM, eUnits)
+End Function
+
+Public Function GetExtraColumnBroadeningResultantPeakWidth(Optional eUnits As utmUnitsTimeConstants = utmSeconds) As Double
+ GetExtraColumnBroadeningResultantPeakWidth = ConvertTime(mExtraColumnBroadeningParameters.ResultantPeakWidth, utmSeconds, eUnits)
+End Function
+
+Public Function GetExtraColumnBroadeningTemporalVarianceInSquareSeconds() As Double
+ GetExtraColumnBroadeningTemporalVarianceInSquareSeconds = mExtraColumnBroadeningParameters.TemporalVariance
+End Function
+
+Public Function GetInterparticlePorosity() As Double
+ GetInterparticlePorosity = mCapillaryFlowParameters.InterparticlePorosity
+End Function
+
+Public Function GetLinearVelocity(Optional eUnits As ulvUnitsLinearVelocityConstants = ulvCmPerSec) As Double
+ GetLinearVelocity = ConvertLinearVelocity(mCapillaryFlowParameters.LinearVelocity, ulvCmPerMin, eUnits)
+End Function
+
+Public Function GetMassRateConcentration(Optional eUnits As ucoUnitsConcentrationConstants = ucoMicroMolar) As Double
+ GetMassRateConcentration = ConvertConcentration(mMassRateParameters.SampleConcentration, ucoMolar, eUnits)
+End Function
+
+Public Function GetMassRateInjectionTime(Optional eUnits As utmUnitsTimeConstants = utmMinutes) As Double
+ GetMassRateInjectionTime = ConvertTime(mMassRateParameters.InjectionTime, utmMinutes, eUnits)
+End Function
+
+Public Function GetMassFlowRate(Optional eUnits As umfMassFlowRateConstants = umfFmolPerSec) As Double
+ GetMassFlowRate = ConvertMassFlowRate(mMassRateParameters.MassFlowRate, umfMolesPerMin, eUnits)
+End Function
+
+Public Function GetMassRateMolesInjected(Optional eUnits As umaMolarAmountConstants = umaFemtoMoles) As Double
+ GetMassRateMolesInjected = ConvertMoles(mMassRateParameters.MolesInjected, umaMoles, eUnits)
+End Function
+
+Public Function GetMassRateSampleMass() As Double
+ GetMassRateSampleMass = mMassRateParameters.SampleMass
+End Function
+
+Public Function GetMassRateVolFlowRate(Optional eUnits As ufrUnitsFlowRateConstants = ufrNLPerMin) As Double
+ GetMassRateVolFlowRate = ConvertVolFlowRate(mMassRateParameters.VolumetricFlowRate, ufrMLPerMin, eUnits)
+End Function
+
+Public Function GetParticleDiameter(Optional eUnits As ulnUnitsLengthConstants = ulnMicrons) As Double
+ GetParticleDiameter = ConvertLength(mCapillaryFlowParameters.ParticleDiameter, ulnCM, eUnits)
+End Function
+
+Public Function GetSolventViscosity(Optional eUnits As uviUnitsViscosityConstants = uviPoise) As Double
+ GetSolventViscosity = ConvertViscosity(mCapillaryFlowParameters.SolventViscosity, uviPoise, eUnits)
+End Function
+
+Public Function GetVolFlowRate(Optional eUnits As ufrUnitsFlowRateConstants = ufrNLPerMin) As Double
+ GetVolFlowRate = ConvertVolFlowRate(mCapillaryFlowParameters.VolumetricFlowRate, ufrMLPerMin, eUnits)
+End Function
+
+
+' Set Subs
+' If mAutoCompute = False, then must manually call a Compute Sub to recompute other values
+
+Public Sub SetAutoComputeEnabled(blnAutoCompute As Boolean)
+ mAutoCompute = blnAutoCompute
+End Sub
+
+Public Sub SetAutoComputeMode(eAutoComputeMode As acmAutoComputeModeConstants)
+ If eAutoComputeMode >= acmBackPressure And eAutoComputeMode <= acmVolFlowrateUsingDeadTime Then
+ mAutoComputeMode = eAutoComputeMode
+ End If
+End Sub
+
+Public Sub SetBackPressure(dblBackPressure As Double, Optional eUnits As uprUnitsPressureConstants = uprPsi)
+ mCapillaryFlowParameters.BackPressure = ConvertPressure(dblBackPressure, eUnits, uprDynesPerSquareCm)
+ CheckAutoCompute
+End Sub
+
+Public Sub SetCapillaryType(eCapillaryType As ctCapillaryTypeConstants)
+ If eCapillaryType >= ctOpenTubularCapillary And eCapillaryType <= ctPackedCapillary Then
+ mCapillaryFlowParameters.CapillaryType = eCapillaryType
+ End If
+ CheckAutoCompute
+End Sub
+
+Public Sub SetColumnID(dblColumnID As Double, Optional eUnits As ulnUnitsLengthConstants = ulnMicrons)
+ mCapillaryFlowParameters.ColumnID = ConvertLength(dblColumnID, eUnits, ulnCM)
+ CheckAutoCompute
+End Sub
+
+Public Sub SetColumnLength(dblColumnLength As Double, Optional eUnits As ulnUnitsLengthConstants = ulnCM)
+ mCapillaryFlowParameters.ColumnLength = ConvertLength(dblColumnLength, eUnits, ulnCM)
+ CheckAutoCompute
+End Sub
+
+Public Sub SetDeadTime(dblDeadTime As Double, Optional eUnits As utmUnitsTimeConstants = utmMinutes)
+ mCapillaryFlowParameters.ColumnDeadTime = ConvertTime(dblDeadTime, eUnits, utmMinutes)
+ CheckAutoCompute
+End Sub
+
+Public Sub SetExtraColumnBroadeningAdditionalVariance(dblAdditionalVarianceInSquareSeconds As Double)
+ mExtraColumnBroadeningParameters.AdditionalTemporalVariance = dblAdditionalVarianceInSquareSeconds
+ ComputeExtraColumnBroadeningValues
+End Sub
+
+Public Sub SetExtraColumnBroadeningDiffusionCoefficient(dblDiffusionCoefficient As Double, Optional eUnits As udcDiffusionCoefficientConstants = udcCmSquaredPerSec)
+ mExtraColumnBroadeningParameters.DiffusionCoefficient = ConvertDiffusionCoefficient(dblDiffusionCoefficient, eUnits, udcCmSquaredPerSec)
+ ComputeExtraColumnBroadeningValues
+End Sub
+
+Public Sub SetExtraColumnBroadeningInitialPeakWidthAtBase(dblWidth As Double, Optional eUnits As utmUnitsTimeConstants = utmSeconds)
+ mExtraColumnBroadeningParameters.InitialPeakWidth = ConvertTime(dblWidth, eUnits, utmSeconds)
+ ComputeExtraColumnBroadeningValues
+End Sub
+
+Public Sub SetExtraColumnBroadeningLinearVelocity(dblLinearVelocity As Double, Optional eUnits As ulvUnitsLinearVelocityConstants = ulvMmPerMin)
+ mExtraColumnBroadeningParameters.LinearVelocity = ConvertLinearVelocity(dblLinearVelocity, eUnits, ulvCmPerMin)
+ ComputeExtraColumnBroadeningValues
+End Sub
+
+Public Sub SetExtraColumnBroadeningOpenTubeID(dblOpenTubeID As Double, Optional eUnits As ulnUnitsLengthConstants = ulnMicrons)
+ mExtraColumnBroadeningParameters.OpenTubeID = ConvertLength(dblOpenTubeID, eUnits, ulnCM)
+ ComputeExtraColumnBroadeningValues
+End Sub
+
+Public Sub SetExtraColumnBroadeningOpenTubeLength(dblLength As Double, Optional eUnits As ulnUnitsLengthConstants = ulnCM)
+ mExtraColumnBroadeningParameters.OpenTubeLength = ConvertLength(dblLength, eUnits, ulnCM)
+ ComputeExtraColumnBroadeningValues
+End Sub
+
+Public Sub SetInterparticlePorosity(dblPorosity As Double)
+ If dblPorosity >= 0 And dblPorosity <= 1 Then
+ mCapillaryFlowParameters.InterparticlePorosity = dblPorosity
+ End If
+ CheckAutoCompute
+End Sub
+
+Public Sub SetMassRateConcentration(dblConcentration As Double, Optional eUnits As ucoUnitsConcentrationConstants = ucoMicroMolar)
+ mMassRateParameters.SampleConcentration = ConvertConcentration(dblConcentration, eUnits, ucoMolar)
+ ComputeMassRateValues
+End Sub
+
+Public Sub SetMassRateInjectionTime(dblInjectionTime As Double, Optional eUnits As utmUnitsTimeConstants = utmMinutes)
+ mMassRateParameters.InjectionTime = ConvertTime(dblInjectionTime, eUnits, utmMinutes)
+ ComputeMassRateValues
+End Sub
+
+Public Function SetMassRateSampleMass(dblMassInGramsPerMole As Double) As Double
+ If dblMassInGramsPerMole >= 0 Then
+ mMassRateParameters.SampleMass = dblMassInGramsPerMole
+ Else
+ mMassRateParameters.SampleMass = 0
+ End If
+ ComputeMassRateValues
+End Function
+
+Public Sub SetMassRateVolFlowRate(dblVolFlowRate As Double, Optional eUnits As ufrUnitsFlowRateConstants = ufrNLPerMin)
+ mMassRateParameters.VolumetricFlowRate = ConvertVolFlowRate(dblVolFlowRate, eUnits, ufrMLPerMin)
+ ComputeMassRateValues
+End Sub
+
+Public Sub SetParticleDiameter(dblParticleDiameter As Double, Optional eUnits As ulnUnitsLengthConstants = ulnMicrons)
+ mCapillaryFlowParameters.ParticleDiameter = ConvertLength(dblParticleDiameter, eUnits, ulnCM)
+ CheckAutoCompute
+End Sub
+
+Public Sub SetSolventViscosity(dblSolventViscosity As Double, Optional eUnits As uviUnitsViscosityConstants = uviPoise)
+ mCapillaryFlowParameters.SolventViscosity = ConvertViscosity(dblSolventViscosity, eUnits, uviPoise)
+ CheckAutoCompute
+End Sub
+
+Public Sub SetVolFlowRate(dblVolFlowRate As Double, Optional eUnits As ufrUnitsFlowRateConstants = ufrNLPerMin)
+ mCapillaryFlowParameters.VolumetricFlowRate = ConvertVolFlowRate(dblVolFlowRate, eUnits, ufrMLPerMin)
+ CheckAutoCompute
+End Sub
+
+Private Sub Class_Initialize()
+ Me.SetAutoComputeEnabled False
+
+ Me.SetAutoComputeMode acmVolFlowrate
+ Me.SetCapillaryType ctPackedCapillary
+ Me.SetBackPressure 3000, uprPsi
+ Me.SetColumnLength 50, ulnCM
+ Me.SetColumnID 75, ulnMicrons
+ Me.SetSolventViscosity 0.0089, uviPoise
+ Me.SetParticleDiameter 5, ulnMicrons
+ Me.SetInterparticlePorosity 0.4
+
+ Me.SetMassRateConcentration 1, ucoMicroMolar
+ Me.SetMassRateVolFlowRate 600, ufrNLPerMin
+ Me.SetMassRateInjectionTime 5, utmMinutes
+
+ ' Recompute
+ ComputeVolFlowRate
+ ComputeMassRateValues
+ ComputeExtraColumnBroadeningValues
+
+ Me.SetAutoComputeEnabled True
+
+End Sub
+
+
+
diff --git a/MwtWinDll/clsCompound.cls b/MwtWinDll/clsCompound.cls
new file mode 100644
index 0000000..000183b
--- /dev/null
+++ b/MwtWinDll/clsCompound.cls
@@ -0,0 +1,310 @@
+VERSION 1.0 CLASS
+BEGIN
+ MultiUse = -1 'True
+ Persistable = 0 'NotPersistable
+ DataBindingBehavior = 0 'vbNone
+ DataSourceBehavior = 0 'vbNone
+ MTSTransactionMode = 0 'NotAnMTSObject
+END
+Attribute VB_Name = "MWCompoundClass"
+Attribute VB_GlobalNameSpace = False
+Attribute VB_Creatable = True
+Attribute VB_PredeclaredId = False
+Attribute VB_Exposed = True
+Attribute VB_Ext_KEY = "SavedWithClassBuilder6" ,"Yes"
+Attribute VB_Ext_KEY = "Top_Level" ,"Yes"
+Option Explicit
+
+' Molecular Weight Calculator routines with ActiveX Class interfaces: MWCompoundClass
+' Written by Matthew Monroe in Richland, WA
+
+' The compound class can be used to represent a compound
+' Use the Formula Property to enter the compound's formula
+' Use ErrorDescription and CautionDescription to see if there are any problems with the formula
+' Custom abbreviations can be defined using the SetAbbreviationInternal() function in ElementAndMassRoutines()
+' Note that the standard amino acids and 16 other abbreviations are defined by default (see MemoryLoadAbbreviations())
+
+' Use the Mass Property to get the mass of the compound
+
+Private mStrFormula As String
+Private mStrFormattedFormula As String
+
+Private mValueForX As Double ' The value to assign to x when present after a square bracket.
+ ' For example, in C6H6[xBr] if x = 1, then the formula is treated like C6H6Br
+ ' If x = 2, then the formula is treated like C6H6Br2
+
+Private mCautionDescription As String
+Private mErrorDescription As String
+Private mErrorID As Long
+
+Private mComputationStats As udtComputationStatsType
+
+Public Function ConvertToEmpirical() As String
+ ' Converts mStrFormula to its empirical formula and returns the result
+ Dim strResult As String
+
+ strResult = ConvertFormulaToEmpirical(mStrFormula)
+ UpdateErrorAndCaution
+
+ If mErrorDescription = "" Then
+ mStrFormula = strResult
+ mStrFormattedFormula = strResult
+ ConvertToEmpirical = strResult
+ Else
+ ConvertToEmpirical = ErrorDescription
+ End If
+End Function
+
+Public Function ElementPresent(intElementID As Integer) As Boolean
+ ' Returns True if the element is present
+ If intElementID >= 1 And intElementID <= ELEMENT_COUNT Then
+ ElementPresent = mComputationStats.Elements(intElementID).Used
+ Else
+ ElementPresent = False
+ End If
+
+End Function
+
+Public Function ExpandAbbreviations() As String
+ ' Expands abbreviations in mStrFormula and returns the result
+
+ Dim strResult As String
+
+ strResult = ExpandAbbreviationsInFormula(mStrFormula)
+ UpdateErrorAndCaution
+
+ If mErrorDescription = "" Then
+ mStrFormula = strResult
+ mStrFormattedFormula = strResult
+ ExpandAbbreviations = strResult
+ Else
+ ExpandAbbreviations = ErrorDescription
+ End If
+
+End Function
+
+Public Function GetAtomCountForElement(ByVal intElementID As Integer) As Double
+ ' Return the number of atoms of a given element that are present in the formula
+ ' Note that the number of atoms is not necessarily an integer (e.g. C5.5)
+
+ If intElementID >= 1 And intElementID <= ELEMENT_COUNT Then
+ GetAtomCountForElement = mComputationStats.Elements(intElementID).Count
+ Else
+ GetAtomCountForElement = 0
+ End If
+
+End Function
+
+Public Function GetPercentCompositionForElement(ByVal intElementID As Integer) As Double
+ ' Returns the percent composition for element
+ ' Returns -1 if an invalid ID
+
+ If intElementID >= 1 And intElementID <= ELEMENT_COUNT Then
+ GetPercentCompositionForElement = mComputationStats.PercentCompositions(intElementID).PercentComposition
+ Else
+ GetPercentCompositionForElement = -1
+ End If
+
+End Function
+
+Public Function GetPercentCompositionForElementAsString(ByVal intElementID As Integer, Optional blnIncludeStandardDeviation As Boolean = True) As String
+ ' Returns the percent composition and standard deviation for element
+ ' Returns "" if an invalid ID
+ Dim strElementSymbol As String
+ Dim strPctComposition As String
+
+ If intElementID >= 1 And intElementID <= ELEMENT_COUNT Then
+
+ With mComputationStats.PercentCompositions(intElementID)
+
+ strElementSymbol = GetElementSymbolInternal(intElementID) & ":"
+ strPctComposition = ReturnFormattedMassAndStdDev(.PercentComposition, .StdDeviation, blnIncludeStandardDeviation, True)
+ If .PercentComposition < 10 Then
+ strPctComposition = " " & strPctComposition
+ End If
+ GetPercentCompositionForElementAsString = SpacePad(strElementSymbol, 4) & strPctComposition
+ End With
+ Else
+ GetPercentCompositionForElementAsString = ""
+ End If
+
+End Function
+
+Public Sub GetPercentCompositionForAllElements(ByRef strPctCompositionsOneBased() As String)
+ ' Returns the percent composition for all elements in strPctCompositionsOneBased
+
+ Dim intElementIndex As Integer, intMaxIndex As Integer
+
+On Error GoTo GetPercentCompositionForAllElementsErrorHandler
+
+ intMaxIndex = UBound(strPctCompositionsOneBased())
+
+ If intMaxIndex < ELEMENT_COUNT Then
+ ' Try to reserve more space in strPctCompositionsOneBased()
+ On Error Resume Next
+ ReDim strPctCompositionsOneBased(ELEMENT_COUNT)
+
+ intMaxIndex = UBound(strPctCompositionsOneBased())
+
+ On Error GoTo GetPercentCompositionForAllElementsErrorHandler
+ End If
+
+ If intMaxIndex >= ELEMENT_COUNT Then intMaxIndex = ELEMENT_COUNT
+
+ ComputePercentComposition mComputationStats
+
+ For intElementIndex = 1 To intMaxIndex
+ With mComputationStats.PercentCompositions(intElementIndex)
+ If .PercentComposition > 0 Then
+ strPctCompositionsOneBased(intElementIndex) = ReturnFormattedMassAndStdDev(.PercentComposition, .StdDeviation)
+ Else
+ strPctCompositionsOneBased(intElementIndex) = ""
+ End If
+ End With
+ Next intElementIndex
+
+ Exit Sub
+
+GetPercentCompositionForAllElementsErrorHandler:
+ Debug.Print "Error occurred while copying percent composition values. Probably an uninitialized array."
+End Sub
+
+Public Function GetUsedElementCount() As Integer
+ ' Returns the number of unique elements present in mStrFormula
+
+ Dim intTotalElements As Integer
+ Dim intElementIndex As Integer
+
+ ' Determine # of elements in formula
+ intTotalElements = 0
+ For intElementIndex = 1 To ELEMENT_COUNT
+ ' Increment .TotalElements if element is present
+ If mComputationStats.Elements(intElementIndex).Used Then
+ intTotalElements = intTotalElements + 1
+ End If
+ Next intElementIndex
+
+ GetUsedElementCount = intTotalElements
+End Function
+
+Public Function SetFormula(ByVal strNewFormula As String) As Long
+ ' Provides an alternate method for setting the formula
+ ' Returns ErrorID (0 if no error)
+
+ Me.Formula = strNewFormula
+
+ SetFormula = Me.ErrorID
+End Function
+
+Private Sub UpdateErrorAndCaution()
+ mCautionDescription = GetCautionDescription()
+ mErrorDescription = GetErrorDescription()
+ mErrorID = GetErrorID()
+End Sub
+
+Private Sub UpdateMass()
+ Dim dblMass As Double
+
+ mStrFormattedFormula = mStrFormula
+
+ ' mStrFormattedFormula is passed ByRef
+ ' If gComputationOptions.CaseConversion = ccConvertCaseUp then mStrFormattedFormula is properly capitalized
+ ' The mass of the compound is stored in mComputationStats.TotalMass
+ dblMass = ParseFormulaPublic(mStrFormattedFormula, mComputationStats, False, mValueForX)
+
+ ComputePercentComposition mComputationStats
+
+ UpdateErrorAndCaution
+End Sub
+
+Public Function XIsPresentAfterBracket() As Boolean
+ Dim intCharLoc As Integer
+
+ If gComputationOptions.BracketsAsParentheses Then
+ ' Treating brackets as parentheses, therefore an x after a bracket isn't allowed
+ XIsPresentAfterBracket = False
+ Else
+ intCharLoc = InStr(LCase(mStrFormattedFormula), "[x")
+ If intCharLoc > 0 Then
+ If Mid(mStrFormattedFormula, intCharLoc + 1, 1) <> "e" Then
+ XIsPresentAfterBracket = True
+ Else
+ XIsPresentAfterBracket = False
+ End If
+ Else
+ XIsPresentAfterBracket = False
+ End If
+ End If
+
+End Function
+
+Public Property Get CautionDescription() As String
+ CautionDescription = mCautionDescription
+End Property
+
+Public Property Let Charge(ByVal sngNewCharge As Single)
+ mComputationStats.Charge = sngNewCharge
+End Property
+
+Public Property Get Charge() As Single
+ Charge = mComputationStats.Charge
+End Property
+
+Public Property Get ErrorDescription() As String
+ ErrorDescription = mErrorDescription
+End Property
+
+Public Property Get ErrorID() As Long
+ ErrorID = mErrorID
+End Property
+
+Public Property Let Formula(ByVal strNewFormula As String)
+ mStrFormula = strNewFormula
+
+ ' Recompute the mass for this formula
+ ' Updates Error and Caution statements if there is a problem
+ UpdateMass
+End Property
+
+Public Property Get Formula() As String
+ Formula = mStrFormula
+End Property
+
+Public Property Get FormulaCapitalized() As String
+ FormulaCapitalized = mStrFormattedFormula
+End Property
+
+Public Property Get FormulaRTF() As String
+ FormulaRTF = PlainTextToRtfInternal(Me.FormulaCapitalized, False)
+End Property
+
+Public Property Get Mass(Optional blnRecomputeMass As Boolean = True) As Double
+ If blnRecomputeMass Then UpdateMass
+
+ Mass = mComputationStats.TotalMass
+End Property
+
+Public Property Get MassAndStdDevString(Optional blnRecomputeMass As Boolean = True) As String
+ If blnRecomputeMass Then UpdateMass
+
+ With mComputationStats
+ MassAndStdDevString = ReturnFormattedMassAndStdDev(.TotalMass, .StandardDeviation)
+ End With
+End Property
+
+Public Property Get StandardDeviation() As Double
+ StandardDeviation = mComputationStats.StandardDeviation
+End Property
+
+Public Property Let ValueForX(dblValueForX As Double)
+ If dblValueForX >= 0 Then mValueForX = dblValueForX
+End Property
+
+Public Property Get ValueForX() As Double
+ ValueForX = mValueForX
+End Property
+
+Private Sub Class_Initialize()
+ mStrFormula = ""
+ ValueForX = 1#
+End Sub
diff --git a/MwtWinDll/clsMoleMassDilutionClass.cls b/MwtWinDll/clsMoleMassDilutionClass.cls
new file mode 100644
index 0000000..4d87f98
--- /dev/null
+++ b/MwtWinDll/clsMoleMassDilutionClass.cls
@@ -0,0 +1,656 @@
+VERSION 1.0 CLASS
+BEGIN
+ MultiUse = -1 'True
+ Persistable = 0 'NotPersistable
+ DataBindingBehavior = 0 'vbNone
+ DataSourceBehavior = 0 'vbNone
+ MTSTransactionMode = 0 'NotAnMTSObject
+END
+Attribute VB_Name = "MWMoleMassDilutionClass"
+Attribute VB_GlobalNameSpace = False
+Attribute VB_Creatable = True
+Attribute VB_PredeclaredId = False
+Attribute VB_Exposed = True
+Option Explicit
+
+' Molecular Weight Calculator routines with ActiveX Class interfaces: MWMoleMassDilutionClass
+' Written by Matthew Monroe in Richland, WA
+
+'
+Public Enum acdAutoComputeDilutionModeConstants
+ acdFindRequiredDilutionVolumes = 0
+ acdFindRequiredTotalVolume
+ acdFindFinalConcentration
+ acdFindInitialConcentration
+End Enum
+
+Public Enum acqAutoComputeQuantityModeConstants
+ acqFindAmount = 0
+ acqFindVolume
+ acqFindConcentration
+End Enum
+
+Private Const AMOUNT_UNITS_LIST_COUNT = 22
+Private Const AMOUNT_UNITS_VOLUME_INDEX_START = 13
+Private Const AMOUNT_UNITS_VOLUME_INDEX_END = 21
+Public Enum uamUnitsAmountConstants
+ uamMoles = 0
+ uamMillimoles
+ uamMicroMoles
+ uamNanoMoles
+ uamPicoMoles
+ uamFemtoMoles
+ uamAttoMoles
+ uamKilograms
+ uamGrams
+ uamMilligrams
+ uamMicrograms
+ uamPounds
+ uamOunces
+ uamLiters
+ uamDeciLiters
+ uamMilliLiters
+ uamMicroLiters
+ uamNanoLiters
+ uamPicoLiters
+ uamGallons
+ uamQuarts
+ uamPints
+End Enum
+
+Public Enum uevUnitsExtendedVolumeConstants
+ uevL = 0
+ uevDL
+ uevML
+ uevUL
+ uevNL
+ uevPL
+ uevGallons
+ uevQuarts
+ uevPints
+End Enum
+
+Public Enum ummcUnitsMoleMassConcentrationConstants
+ ummcMolar = 0
+ ummcMilliMolar
+ ummcMicroMolar
+ ummcNanoMolar
+ ummcPicoMolar
+ ummcFemtoMolar
+ ummcAttoMolar
+ ummcMgPerDL
+ ummcMgPerML
+ ummcUgPerML
+ ummcNgPerML
+ ummcUgPerUL
+ ummcNgPerUL
+End Enum
+
+
+'
+
+'
+Private Type udtMoleMassQuantityType
+ Amount As Double ' In Moles
+ Volume As Double ' In L
+ Concentration As Double ' In Molar
+ SampleMass As Double ' In g
+ SampleDensity As Double ' In g/mL
+End Type
+
+Private Type udtMoleMassDilutionValuesType
+ InitialConcentration As Double ' In Molar
+ StockSolutionVolume As Double ' In L
+ FinalConcentration As Double ' In Molar
+ DilutingSolventVolume As Double ' In L
+ TotalFinalVolume As Double ' In L
+End Type
+'
+
+Private Const POUNDS_PER_KG As Single = 2.20462262
+Private Const GALLONS_PER_L As Single = 0.264172052
+
+Private mQuantity As udtMoleMassQuantityType
+Private mDilutionValues As udtMoleMassDilutionValuesType
+
+Private mAutoComputeDilution As Boolean ' When true, automatically compute dilution results whenever any value changes
+Private mAutoComputeDilutionMode As acdAutoComputeDilutionModeConstants ' The value to compute when mAutoComputeDilution is true
+
+Private mAutoComputeQuantity As Boolean ' When true, automatically compute quantities whenever any value changes
+Private mAutoComputeQuantityMode As acqAutoComputeQuantityModeConstants ' The value to compute when mAutoComputeQuantity is true
+
+Private Sub CheckAutoComputeDilution()
+ ' Checks if AutoCompute Dilution is enabled
+ ' If yes, calls the appropriate function
+
+ If mAutoComputeDilution Then
+ Select Case mAutoComputeDilutionMode
+ Case acdFindRequiredTotalVolume: ComputeDilutionTotalVolume
+ Case acdFindFinalConcentration: ComputeDilutionFinalConcentration
+ Case acdFindInitialConcentration: ComputeDilutionInitialConcentration
+ Case Else
+ ' Includes acdFindRequiredDilutionVolumes
+ ComputeDilutionRequiredStockAndDilutingSolventVolumes
+ End Select
+ End If
+End Sub
+
+Private Sub CheckAutoComputeQuantity()
+ ' Checks if AutoCompute Quantity is enabled
+ ' If yes, calls the appropriate function
+
+ If mAutoComputeQuantity Then
+ Select Case mAutoComputeQuantityMode
+ Case acqFindVolume: ComputeQuantityVolume
+ Case acqFindConcentration: ComputeQuantityConcentration
+ Case Else
+ ' Includes acqFindAmount
+ ComputeQuantityAmount
+ End Select
+ End If
+End Sub
+
+Public Function ComputeDilutionFinalConcentration(Optional eUnits As ummcUnitsMoleMassConcentrationConstants = ummcMolar) As Double
+ ' Computes the Final Concentration, storing in .FinalConcentration, and returning it
+
+ With mDilutionValues
+ If .TotalFinalVolume <> 0 Then
+ .FinalConcentration = .InitialConcentration * .StockSolutionVolume / .TotalFinalVolume
+ Else
+ .TotalFinalVolume = 0
+ End If
+
+ .DilutingSolventVolume = .TotalFinalVolume - .StockSolutionVolume
+ If .DilutingSolventVolume < 0 Then .DilutingSolventVolume = -1
+ End With
+
+ ComputeDilutionFinalConcentration = ConvertConcentration(mDilutionValues.FinalConcentration, ummcMolar, eUnits)
+
+End Function
+
+Public Function ComputeDilutionInitialConcentration(Optional eUnits As ummcUnitsMoleMassConcentrationConstants = ummcMolar) As Double
+ ' Computes the Initial Concentration, storing in .InitialConcentration, and returning it
+
+ With mDilutionValues
+ If .StockSolutionVolume <> 0 Then
+ .InitialConcentration = .FinalConcentration * .TotalFinalVolume / .StockSolutionVolume
+ Else
+ .InitialConcentration = 0
+ End If
+
+ .DilutingSolventVolume = .TotalFinalVolume - .StockSolutionVolume
+ If .DilutingSolventVolume < 0 Then .DilutingSolventVolume = -1
+ End With
+
+ ComputeDilutionInitialConcentration = ConvertConcentration(mDilutionValues.InitialConcentration, ummcMolar, eUnits)
+
+End Function
+
+Public Function ComputeDilutionRequiredStockAndDilutingSolventVolumes(Optional eStockSolutionUnits As uevUnitsExtendedVolumeConstants = uevML, Optional ByRef dblNewDilutingSolventVolume As Double, Optional eDilutingSolventUnits As uevUnitsExtendedVolumeConstants = uevML) As Double
+ ' Computes the required dilution volumes using initial concentration, final concentration
+ ' and total final volume, storing in .StockSolutionVolume and .DilutingSolventVolume,
+ ' and returning .StockSolutionVolume
+ ' In addition, returns the .DilutingSolventVolume using the ByRef parameter dblNewDilutingSolventVolume
+
+ With mDilutionValues
+ If .InitialConcentration <> 0 Then
+ .StockSolutionVolume = .FinalConcentration * .TotalFinalVolume / .InitialConcentration
+ Else
+ .StockSolutionVolume = 0
+ End If
+
+ .DilutingSolventVolume = .TotalFinalVolume - .StockSolutionVolume
+
+ If .DilutingSolventVolume < 0 Then
+ .DilutingSolventVolume = -1
+ .StockSolutionVolume = -1
+ End If
+ End With
+
+ dblNewDilutingSolventVolume = ConvertVolumeExtended(mDilutionValues.DilutingSolventVolume, uevL, eDilutingSolventUnits)
+
+ ComputeDilutionRequiredStockAndDilutingSolventVolumes = ConvertVolumeExtended(mDilutionValues.StockSolutionVolume, uevL, eStockSolutionUnits)
+
+End Function
+
+Public Function ComputeDilutionTotalVolume(Optional eTotalVolumeUnits As uevUnitsExtendedVolumeConstants = uevML, Optional ByRef dblNewDilutingSolventVolume As Double, Optional eDilutingSolventUnits As uevUnitsExtendedVolumeConstants = uevML) As Double
+ ' Compute the total volume following the dilution, storing in .TotalFinalVolume, and returning it
+
+ With mDilutionValues
+ If .InitialConcentration > 0 And .FinalConcentration > 0 Then
+ .TotalFinalVolume = .InitialConcentration * .StockSolutionVolume / .FinalConcentration
+ If .TotalFinalVolume < 0 Then
+ .TotalFinalVolume = 0
+ End If
+ Else
+ .TotalFinalVolume = 0
+ End If
+
+ .DilutingSolventVolume = .TotalFinalVolume - .StockSolutionVolume
+ If .DilutingSolventVolume < 0 Then .DilutingSolventVolume = -1
+ End With
+
+ dblNewDilutingSolventVolume = ConvertVolumeExtended(mDilutionValues.DilutingSolventVolume, uevL, eDilutingSolventUnits)
+
+ ComputeDilutionTotalVolume = ConvertVolumeExtended(mDilutionValues.TotalFinalVolume, uevL, eTotalVolumeUnits)
+
+End Function
+
+Public Function ComputeQuantityAmount(Optional eUnits As uamUnitsAmountConstants = uamMoles) As Double
+ ' Computes .Amount using .Volume and .Concentration, storing the result
+ ' in .Amount and returning it
+
+ With mQuantity
+ .Amount = .Concentration * .Volume
+ End With
+
+ ComputeQuantityAmount = ConvertAmount(mQuantity.Amount, uamMoles, eUnits)
+End Function
+
+Public Function ComputeQuantityConcentration(Optional eUnits As ummcUnitsMoleMassConcentrationConstants = ummcMolar) As Double
+ ' Computes .Concentration using .Amount and .Volume, storing the result
+ ' in .Concentration and returning it
+
+ With mQuantity
+ If .Volume <> 0 Then
+ .Concentration = .Amount / .Volume
+ Else
+ .Concentration = 0
+ End If
+ End With
+
+ ComputeQuantityConcentration = ConvertConcentration(mQuantity.Concentration, ummcMolar, eUnits)
+End Function
+
+Public Function ComputeQuantityVolume(Optional eUnits As uevUnitsExtendedVolumeConstants = uevL) As Double
+ ' Computes .Volume using .Amount and .Concentration, storing the result
+ ' in .Volume and returning it
+
+ With mQuantity
+ If .Concentration <> 0 Then
+ .Volume = .Amount / .Concentration
+ Else
+ .Volume = 0
+ End If
+ End With
+
+ ComputeQuantityVolume = ConvertVolumeExtended(mQuantity.Volume, uevL, eUnits)
+End Function
+
+' This function uses .SampleMass and .SampleDensity if the units are mass and/or volume-based
+Public Function ConvertAmount(dblAmountIn As Double, eCurrentUnits As uamUnitsAmountConstants, eNewUnits As uamUnitsAmountConstants) As Double
+ Dim dblValue As Double, dblFactor As Double
+ Dim dblSampleMass As Double, dblSampleDensity As Double
+ Dim eCurrentVolumeUnits As uevUnitsExtendedVolumeConstants
+ Dim eNewVolumeUnits As uevUnitsExtendedVolumeConstants
+
+ If eCurrentUnits = eNewUnits Then
+ ' No conversion, simply return dblAmountIn
+ ConvertAmount = dblAmountIn
+ Exit Function
+ End If
+
+ If eCurrentUnits >= AMOUNT_UNITS_VOLUME_INDEX_START And eCurrentUnits <= AMOUNT_UNITS_VOLUME_INDEX_END And _
+ eNewUnits >= AMOUNT_UNITS_VOLUME_INDEX_START And eNewUnits <= AMOUNT_UNITS_VOLUME_INDEX_END Then
+ ' Converting from one volume unit to another volume unit
+ ' No need to explicitly specify mass or density
+
+ eCurrentVolumeUnits = eCurrentUnits - AMOUNT_UNITS_VOLUME_INDEX_START
+ eNewVolumeUnits = eNewUnits - AMOUNT_UNITS_VOLUME_INDEX_START
+
+ ConvertAmount = ConvertVolumeExtended(dblAmountIn, eCurrentVolumeUnits, eNewVolumeUnits)
+ Else
+
+ dblSampleMass = mQuantity.SampleMass
+ dblSampleDensity = mQuantity.SampleDensity
+
+ dblFactor = FactorAmount(eCurrentUnits, dblSampleMass, dblSampleDensity)
+ If dblFactor = -1 Then
+ ConvertAmount = -1
+ Exit Function
+ Else
+ dblValue = dblAmountIn * dblFactor
+ End If
+
+ dblFactor = FactorAmount(eNewUnits, dblSampleMass, dblSampleDensity)
+ If dblFactor = -1 Or dblFactor = 0 Then
+ ConvertAmount = -1
+ Else
+ ConvertAmount = dblValue / dblFactor
+ End If
+ End If
+
+End Function
+
+' Duplicated function, in both MWCapillaryFlowClass and MWMoleMassDilutionClass
+Public Function ConvertConcentration(dblConcentrationIn As Double, eCurrentUnits As ummcUnitsMoleMassConcentrationConstants, eNewUnits As ummcUnitsMoleMassConcentrationConstants) As Double
+ Dim dblValue As Double, dblFactor As Double
+ Dim dblSampleMass As Double
+
+ If eCurrentUnits = eNewUnits Then
+ ConvertConcentration = dblConcentrationIn
+ Exit Function
+ End If
+
+ dblSampleMass = mQuantity.SampleMass
+
+ dblFactor = FactorConcentration(eCurrentUnits, dblSampleMass)
+ If dblFactor = -1 Then
+ ConvertConcentration = -1
+ Exit Function
+ Else
+ dblValue = dblConcentrationIn * dblFactor
+ End If
+
+ dblFactor = FactorConcentration(eNewUnits, dblSampleMass)
+ If dblFactor = -1 Or dblFactor = 0 Then
+ ConvertConcentration = -1
+ Else
+ ConvertConcentration = dblValue / dblFactor
+ End If
+
+End Function
+
+Public Function ConvertVolumeExtended(dblVolume As Double, eCurrentUnits As uevUnitsExtendedVolumeConstants, eNewUnits As uevUnitsExtendedVolumeConstants) As Double
+ Dim dblValue As Double, dblFactor As Double
+
+ If eCurrentUnits = eNewUnits Then
+ ConvertVolumeExtended = dblVolume
+ Exit Function
+ End If
+
+ dblFactor = FactorVolumeExtended(eCurrentUnits)
+ If dblFactor = -1 Then
+ ConvertVolumeExtended = -1
+ Exit Function
+ Else
+ dblValue = dblVolume * dblFactor
+ End If
+
+ dblFactor = FactorVolumeExtended(eNewUnits)
+ If dblFactor = -1 Or dblFactor = 0 Then
+ ConvertVolumeExtended = -1
+ Else
+ ConvertVolumeExtended = dblValue / dblFactor
+ End If
+
+End Function
+
+' Multiplication factor for converting from eUnits to Moles
+' dblSampleMass is required for mass-based units
+' In addition is required for volume-based units
+Private Function FactorAmount(eUnits As uamUnitsAmountConstants, Optional dblSampleMass As Double = -1, Optional dblSampleDensity As Double = 0) As Double
+ Dim dblFactor As Double
+
+ If dblSampleMass = 0 Then
+ dblFactor = -1
+ Else
+ ' Determine the Amount multiplication dblFactor
+ Select Case eUnits
+ Case uamMoles: dblFactor = 1
+ Case uamMillimoles: dblFactor = 1 / 1000#
+ Case uamMicroMoles: dblFactor = 1 / 1000000#
+ Case uamNanoMoles: dblFactor = 1 / 1000000000#
+ Case uamPicoMoles: dblFactor = 1 / 1000000000000#
+ Case uamFemtoMoles: dblFactor = 1 / 1E+15
+ Case uamAttoMoles: dblFactor = 1 / 1E+18
+ Case uamKilograms: dblFactor = 1000# / dblSampleMass
+ Case uamGrams: dblFactor = 1 / dblSampleMass
+ Case uamMilligrams: dblFactor = 1 / (dblSampleMass * 1000#)
+ Case uamMicrograms: dblFactor = 1 / (dblSampleMass * 1000000#)
+ Case uamPounds: dblFactor = 1000# / (dblSampleMass * POUNDS_PER_KG)
+ Case uamOunces: dblFactor = 1000# / (dblSampleMass * POUNDS_PER_KG * 16)
+ Case uamLiters: dblFactor = dblSampleDensity / dblSampleMass * FactorVolumeExtended(uevL)
+ Case uamDeciLiters: dblFactor = dblSampleDensity / dblSampleMass * FactorVolumeExtended(uevDL)
+ Case uamMilliLiters: dblFactor = dblSampleDensity / dblSampleMass * FactorVolumeExtended(uevML)
+ Case uamMicroLiters: dblFactor = dblSampleDensity / dblSampleMass * FactorVolumeExtended(uevUL)
+ Case uamNanoLiters: dblFactor = dblSampleDensity / dblSampleMass * FactorVolumeExtended(uevNL)
+ Case uamPicoLiters: dblFactor = dblSampleDensity / dblSampleMass * FactorVolumeExtended(uevPL)
+ Case uamGallons: dblFactor = dblSampleDensity / dblSampleMass * FactorVolumeExtended(uevGallons)
+ Case uamQuarts: dblFactor = dblSampleDensity / dblSampleMass * FactorVolumeExtended(uevQuarts)
+ Case uamPints: dblFactor = dblSampleDensity / dblSampleMass * FactorVolumeExtended(uevPints)
+ Case Else: dblFactor = -1
+ End Select
+ End If
+
+ FactorAmount = dblFactor
+
+End Function
+
+' Multiplication factor for converting from eUnits to M
+' dblSampleMass is required for mass-based units
+' Duplicated function, in both MWCapillaryFlowClass and MWMoleMassDilutionClass
+Private Function FactorConcentration(eUnits As ummcUnitsMoleMassConcentrationConstants, Optional ByVal dblSampleMass As Double = 0) As Double
+ Dim dblFactor As Double
+
+ If dblSampleMass = 0 Then
+ dblFactor = -1
+ Else
+ Select Case eUnits
+ Case ummcMolar: dblFactor = 1#
+ Case ummcMilliMolar: dblFactor = 1 / 1000#
+ Case ummcMicroMolar: dblFactor = 1 / 1000000#
+ Case ummcNanoMolar: dblFactor = 1 / 1000000000#
+ Case ummcPicoMolar: dblFactor = 1 / 1000000000000#
+ Case ummcFemtoMolar: dblFactor = 1 / 1E+15
+ Case ummcAttoMolar: dblFactor = 1 / 1E+18
+ Case ummcMgPerDL: dblFactor = 1 / dblSampleMass / 100# '1/[(1 g / 1000 mg) * (1 / MW) * (10 dL/L)]
+ Case ummcMgPerML: dblFactor = 1 / dblSampleMass '1/[(1 g / 1000 mg) * (1 / MW) * (1000 mL/L)]
+ Case ummcUgPerML: dblFactor = 1 / (dblSampleMass * 1000#) '1/[(1 g / 1000000 ug) * (1 / MW) * (1000 mL/L)]
+ Case ummcNgPerML: dblFactor = 1 / (dblSampleMass * 1000000#) '1/[(1 g / 1000000000 ng) * (1 / MW) * (1000 mL/L)]
+ Case ummcUgPerUL: dblFactor = 1 / (dblSampleMass) '1/[(1 g / 1000000 ug) * (1 / MW) * (1000000 uL/L)]
+ Case ummcNgPerUL: dblFactor = 1 / (dblSampleMass * 1000#) '1/[(1 g / 1000000000 ng) * (1 / MW) * (1000000 uL/L)]
+ Case Else: dblFactor = -1
+ End Select
+ End If
+
+ FactorConcentration = dblFactor
+End Function
+
+' Multiplication factor for converting from eUnits to mL
+' An extended version of the FactorVolume function in MWCapillaryFlowClass
+Private Function FactorVolumeExtended(eUnits As uevUnitsExtendedVolumeConstants) As Double
+
+ ' Note: 4 quarts per gallon, 2 pints per quart
+ Select Case eUnits
+ Case uevL: FactorVolumeExtended = 1 * 1000#
+ Case uevDL: FactorVolumeExtended = 1 * 100#
+ Case uevML: FactorVolumeExtended = 1#
+ Case uevUL: FactorVolumeExtended = 1 / 1000#
+ Case uevNL: FactorVolumeExtended = 1 / 1000000#
+ Case uevPL: FactorVolumeExtended = 1 / 1000000000#
+ Case uevGallons: FactorVolumeExtended = 1000# / GALLONS_PER_L
+ Case uevQuarts: FactorVolumeExtended = 1000# / GALLONS_PER_L / 4#
+ Case uevPints: FactorVolumeExtended = 1000# / GALLONS_PER_L / 8#
+ Case Else: FactorVolumeExtended = -1
+ End Select
+
+End Function
+
+
+' Get Subs
+' Gets the most recently computed value
+' If mAutoComputeDilution = False, then must manually call a Compute Sub to recompute the value
+' Similarly, if mAutoComputeQuantity = False, then must manually call a Compute Sub to recompute the value
+
+Public Function GetAutoComputeDilutionEnabled() As Boolean
+ GetAutoComputeDilutionEnabled = mAutoComputeDilution
+End Function
+
+Public Function GetAutoComputeDilutionMode() As acdAutoComputeDilutionModeConstants
+ GetAutoComputeDilutionMode = mAutoComputeDilutionMode
+End Function
+
+Public Function GetAutoComputeQuantityEnabled() As Boolean
+ GetAutoComputeQuantityEnabled = mAutoComputeQuantity
+End Function
+
+Public Function GetAutoComputeQuantityMode() As acqAutoComputeQuantityModeConstants
+ GetAutoComputeQuantityMode = mAutoComputeQuantityMode
+End Function
+
+Public Function GetDilutionFinalConcentration(Optional eUnits As ummcUnitsMoleMassConcentrationConstants = ummcMolar) As Double
+ GetDilutionFinalConcentration = ConvertConcentration(mDilutionValues.FinalConcentration, ummcMolar, eUnits)
+End Function
+
+Public Function GetDilutionInitialConcentration(Optional eUnits As ummcUnitsMoleMassConcentrationConstants = ummcMolar) As Double
+ GetDilutionInitialConcentration = ConvertConcentration(mDilutionValues.InitialConcentration, ummcMolar, eUnits)
+End Function
+
+Public Function GetDilutionTotalFinalVolume(Optional eUnits As uevUnitsExtendedVolumeConstants = uevML) As Double
+ GetDilutionTotalFinalVolume = ConvertVolumeExtended(mDilutionValues.TotalFinalVolume, uevL, eUnits)
+End Function
+
+Public Function GetDilutionVolumeDilutingSolvent(Optional eUnits As uevUnitsExtendedVolumeConstants = uevML) As Double
+ GetDilutionVolumeDilutingSolvent = ConvertVolumeExtended(mDilutionValues.DilutingSolventVolume, uevL, eUnits)
+End Function
+
+Public Function GetDilutionVolumeStockSolution(Optional eUnits As uevUnitsExtendedVolumeConstants = uevML) As Double
+ GetDilutionVolumeStockSolution = ConvertVolumeExtended(mDilutionValues.StockSolutionVolume, uevL, eUnits)
+End Function
+
+
+Public Function GetQuantityAmount(Optional eUnits As uamUnitsAmountConstants = uamMoles) As Double
+ GetQuantityAmount = ConvertAmount(mQuantity.Amount, uamMoles, eUnits)
+End Function
+
+Public Function GetQuantityConcentration(Optional eUnits As ummcUnitsMoleMassConcentrationConstants = ummcMolar) As Double
+ GetQuantityConcentration = ConvertConcentration(mQuantity.Concentration, ummcMolar, eUnits)
+End Function
+
+Public Function GetQuantityVolume(Optional eUnits As uevUnitsExtendedVolumeConstants = uevML) As Double
+ GetQuantityVolume = ConvertVolumeExtended(mQuantity.Volume, uevL, eUnits)
+End Function
+
+Public Function GetSampleDensity() As Double
+ GetSampleDensity = mQuantity.SampleDensity
+End Function
+
+Public Function GetSampleMass() As Double
+ GetSampleMass = mQuantity.SampleMass
+End Function
+
+
+' Set Subs
+' If mAutoComputeDilution = False, then must manually call a Compute Sub to recompute the value
+' Similarly, if mAutoComputeQuantity = False, then must manually call a Compute Sub to recompute the value
+
+Public Sub SetAutoComputeDilutionEnabled(blnAutoCompute As Boolean)
+ mAutoComputeDilution = blnAutoCompute
+End Sub
+
+Public Sub SetAutoComputeDilutionMode(eAutoComputeMode As acdAutoComputeDilutionModeConstants)
+ If eAutoComputeMode >= acdFindRequiredDilutionVolumes And eAutoComputeMode <= acdFindFinalConcentration Then
+ mAutoComputeDilutionMode = eAutoComputeMode
+ End If
+End Sub
+
+Public Sub SetAutoComputeQuantityEnabled(blnAutoCompute As Boolean)
+ mAutoComputeQuantity = blnAutoCompute
+End Sub
+
+Public Sub SetAutoComputeQuantityMode(eAutoComputeMode As acqAutoComputeQuantityModeConstants)
+ If eAutoComputeMode >= acqFindAmount And eAutoComputeMode <= acqFindConcentration Then
+ mAutoComputeQuantityMode = eAutoComputeMode
+ End If
+End Sub
+
+
+Public Sub SetDilutionFinalConcentration(dblConcentration As Double, Optional eUnits As ummcUnitsMoleMassConcentrationConstants = ummcMolar)
+ mDilutionValues.FinalConcentration = ConvertConcentration(dblConcentration, eUnits, ummcMolar)
+ CheckAutoComputeDilution
+End Sub
+
+Public Sub SetDilutionInitialConcentration(dblConcentration As Double, Optional eUnits As ummcUnitsMoleMassConcentrationConstants = ummcMolar)
+ mDilutionValues.InitialConcentration = ConvertConcentration(dblConcentration, eUnits, ummcMolar)
+ CheckAutoComputeDilution
+End Sub
+
+Public Sub SetDilutionTotalFinalVolume(dblVolume As Double, Optional eUnits As uevUnitsExtendedVolumeConstants = uevML)
+ mDilutionValues.TotalFinalVolume = ConvertVolumeExtended(dblVolume, eUnits, uevL)
+ CheckAutoComputeDilution
+End Sub
+
+Public Sub SetDilutionVolumeDilutingSolvent(dblVolume As Double, Optional eUnits As uevUnitsExtendedVolumeConstants = uevML)
+ mDilutionValues.DilutingSolventVolume = ConvertVolumeExtended(dblVolume, eUnits, uevL)
+ CheckAutoComputeDilution
+End Sub
+
+Public Sub SetDilutionVolumeStockSolution(dblVolume As Double, Optional eUnits As uevUnitsExtendedVolumeConstants = uevML)
+ mDilutionValues.StockSolutionVolume = ConvertVolumeExtended(dblVolume, eUnits, uevL)
+ CheckAutoComputeDilution
+End Sub
+
+
+Public Sub SetQuantityAmount(dblAmount As Double, Optional eUnits As uamUnitsAmountConstants = uamMoles)
+ mQuantity.Amount = ConvertAmount(dblAmount, eUnits, uamMoles)
+ CheckAutoComputeQuantity
+End Sub
+
+Public Sub SetQuantityConcentration(dblConcentration As Double, Optional eUnits As ummcUnitsMoleMassConcentrationConstants = ummcMolar)
+ mQuantity.Concentration = ConvertConcentration(dblConcentration, eUnits, ummcMolar)
+ CheckAutoComputeQuantity
+End Sub
+
+Public Sub SetQuantityVolume(dblVolume As Double, Optional eUnits As uevUnitsExtendedVolumeConstants = uevML)
+ mQuantity.Volume = ConvertVolumeExtended(dblVolume, eUnits, uevL)
+End Sub
+
+Public Function SetSampleDensity(dblDensityInGramsPerML As Double) As Double
+ If dblDensityInGramsPerML >= 0 Then
+ mQuantity.SampleDensity = dblDensityInGramsPerML
+ Else
+ mQuantity.SampleDensity = 0
+ End If
+ CheckAutoComputeQuantity
+End Function
+
+Public Function SetSampleMass(dblMassInGramsPerMole As Double) As Double
+ If dblMassInGramsPerMole >= 0 Then
+ mQuantity.SampleMass = dblMassInGramsPerMole
+ Else
+ mQuantity.SampleMass = 0
+ End If
+ CheckAutoComputeQuantity
+End Function
+
+
+Private Sub Class_Initialize()
+ Me.SetAutoComputeDilutionEnabled False
+ Me.SetAutoComputeQuantityEnabled False
+
+ Me.SetAutoComputeDilutionMode acdFindRequiredDilutionVolumes
+
+ Me.SetAutoComputeQuantityMode acqFindConcentration
+
+ Me.SetQuantityAmount 1, uamMoles
+ Me.SetQuantityVolume 100, uevML
+ Me.SetQuantityConcentration 1, ummcMolar
+
+ Me.SetDilutionInitialConcentration 10, ummcMolar
+ Me.SetDilutionVolumeStockSolution 3, uevML
+ Me.SetDilutionFinalConcentration 2, ummcMolar
+ Me.SetDilutionVolumeDilutingSolvent 12, uevML
+ Me.SetDilutionTotalFinalVolume 15, uevML
+
+ ' Recompute
+ Me.ComputeQuantityAmount
+ Me.ComputeDilutionRequiredStockAndDilutingSolventVolumes
+
+ Me.SetAutoComputeDilutionEnabled True
+ Me.SetAutoComputeQuantityEnabled True
+
+End Sub
+
+Public Property Get AmountsUnitListCount() As Integer
+ AmountsUnitListCount = AMOUNT_UNITS_LIST_COUNT
+End Property
+
+Public Property Get AmountsUnitListVolumeIndexStart() As Integer
+ AmountsUnitListVolumeIndexStart = AMOUNT_UNITS_VOLUME_INDEX_START
+End Property
+
+Public Property Get AmountsUnitListVolumeIndexEnd() As Integer
+ AmountsUnitListVolumeIndexEnd = AMOUNT_UNITS_VOLUME_INDEX_END
+End Property
+
diff --git a/MwtWinDll/clsMwtWin.cls b/MwtWinDll/clsMwtWin.cls
new file mode 100644
index 0000000..22285b8
--- /dev/null
+++ b/MwtWinDll/clsMwtWin.cls
@@ -0,0 +1,443 @@
+VERSION 1.0 CLASS
+BEGIN
+ MultiUse = -1 'True
+ Persistable = 0 'NotPersistable
+ DataBindingBehavior = 0 'vbNone
+ DataSourceBehavior = 0 'vbNone
+ MTSTransactionMode = 0 'NotAnMTSObject
+END
+Attribute VB_Name = "MolecularWeightCalculator"
+Attribute VB_GlobalNameSpace = False
+Attribute VB_Creatable = True
+Attribute VB_PredeclaredId = False
+Attribute VB_Exposed = True
+Attribute VB_Ext_KEY = "SavedWithClassBuilder6" ,"Yes"
+Attribute VB_Ext_KEY = "Top_Level" ,"Yes"
+Option Explicit
+
+' Molecular Weight Calculator routines with ActiveX Class interfaces
+'
+' Based on Molecular Weight Calculator, v6.20 code, written by Matthew Monroe 1995-2002
+'
+' ActiveX Dll version written by Matthew Monroe in Richland, WA
+'
+' Project started: November 12, 2002
+
+Private Const PROGRAM_DATE = "November 5, 2006"
+Private Const PROGRAM_VERSION = "2.36"
+
+' Duplicate of enum statements in ElementAndMassRoutines.bas
+Public Enum emElementModeConstants
+ emAverageMass = 1
+ emIsotopicMass = 2
+ emIntegerMass = 3
+End Enum
+
+Public Enum smStdDevModeConstants
+ smShort = 0
+ smScientific = 1
+ smDecimal = 2
+End Enum
+
+Public Enum ccCaseConversionConstants
+ ccConvertCaseUp = 0
+ ccExactCase = 1
+ ccSmartCase = 2
+End Enum
+
+Public Enum arAbbrevRecognitionModeConstants
+ arNormalOnly = 0
+ arNormalPlusAminoAcids = 1
+ arNoAbbreviations = 2
+End Enum
+
+Public Enum esElementStatsConstants
+ esMass = 0
+ esUncertainty = 1
+ esCharge = 2
+End Enum
+
+Private mDataInitialized As Boolean
+
+Public Compound As New MWCompoundClass
+Public CapFlow As New MWCapillaryFlowClass
+Public Peptide As New MWPeptideClass
+
+Public Sub ClearError()
+ ResetErrorParamsInternal
+End Sub
+
+Public Function ComputeMass(ByVal strFormula As String) As Double
+ Dim objCompound As New MWCompoundClass
+
+ With objCompound
+ ' Simply assigning strFormula to .Formula will update the Mass
+ .Formula = strFormula
+ ComputeMass = .Mass
+ End With
+
+ Set objCompound = Nothing
+
+End Function
+
+Public Function ComputeIsotopicAbundances(ByRef strFormulaIn As String, ByVal intChargeState As Integer, ByRef strResults As String, ByRef ConvolutedMSData2DOneBased() As Double, ByRef ConvolutedMSDataCount As Long, Optional ByVal strHeaderIsotopicAbundances As String = "Isotopic Abundances for", Optional ByVal strHeaderMass As String = "Mass", Optional ByVal strHeaderFraction As String = "Fraction", Optional ByVal strHeaderIntensity As String = "Intensity") As Integer
+ ' Computes the Isotopic Distribution for a formula
+ ' Returns 0 if success, or -1 if an error
+
+ ComputeIsotopicAbundances = ComputeIsotopicAbundancesInternal(strFormulaIn, intChargeState, strResults, ConvolutedMSData2DOneBased(), ConvolutedMSDataCount, strHeaderIsotopicAbundances, strHeaderMass, strHeaderFraction, strHeaderIntensity, False)
+End Function
+
+Public Function ConvoluteMass(ByVal dblMassMZ As Double, ByVal intCurrentCharge As Integer, Optional ByVal intDesiredCharge As Integer = 1, Optional ByVal dblChargeCarrierMass As Double = 0) As Double
+ ConvoluteMass = ConvoluteMassInternal(dblMassMZ, intCurrentCharge, intDesiredCharge, dblChargeCarrierMass)
+End Function
+
+Public Function GetAbbreviation(ByVal lngAbbreviationID As Long, ByRef strSymbol As String, ByRef strFormula As String, ByRef sngCharge As Single, ByRef blnIsAminoAcid As Boolean, Optional ByRef strOneLetterSymbol As String, Optional ByRef strComment As String, Optional ByRef blnInvalidSymbolOrFormula As Boolean) As Long
+ ' Returns 0 if success, 1 if failure
+ GetAbbreviation = GetAbbreviationInternal(lngAbbreviationID, strSymbol, strFormula, sngCharge, blnIsAminoAcid, strOneLetterSymbol, strComment, blnInvalidSymbolOrFormula)
+End Function
+
+Public Function GetAbbreviationCount() As Long
+ GetAbbreviationCount = GetAbbreviationCountInternal()
+End Function
+
+Public Function GetAbbreviationCountMax() As Long
+ GetAbbreviationCountMax = MAX_ABBREV_COUNT
+End Function
+
+Public Function GetAbbreviationID(ByVal strSymbol As String) As Long
+ ' Returns 0 if not found, the ID if found
+ GetAbbreviationID = GetAbbreviationIDInternal(strSymbol)
+End Function
+
+Public Function GetAminoAcidSymbolConversion(strSymbolToFind As String, bln1LetterTo3Letter As Boolean) As String
+ ' If bln1LetterTo3Letter = True, then converting 1 letter codes to 3 letter codes
+ ' Returns the symbol, if found
+ ' Otherwise, returns ""
+ GetAminoAcidSymbolConversion = GetAminoAcidSymbolConversionInternal(strSymbolToFind, bln1LetterTo3Letter)
+End Function
+
+Public Function GetCautionStatement(ByVal lngCautionStatementID As Long, ByRef strSymbolCombo As String, ByRef strCautionStatement As String) As Long
+ ' Returns the contents of CautionStatements() in the ByRef variables
+ ' Returns 0 if success, 1 if failure
+ GetCautionStatement = GetCautionStatementInternal(lngCautionStatementID, strSymbolCombo, strCautionStatement)
+End Function
+
+Public Function GetCautionStatementCount() As Long
+ ' Returns the number of Caution Statements in memory
+ GetCautionStatementCount = GetCautionStatementCountInternal()
+End Function
+
+Public Function GetCautionStatementID(ByVal strSymbolCombo As String) As Long
+ ' Returns -1 if not found, the ID if found
+ GetCautionStatementID = GetCautionStatementIDInternal(strSymbolCombo)
+End Function
+
+Public Function GetChargeCarrierMass() As Double
+ GetChargeCarrierMass = GetChargeCarrierMassInternal()
+End Function
+
+Public Function GetElement(ByVal intElementID As Integer, ByRef strSymbol As String, ByRef dblMass As Double, ByRef dblUncertainty As Double, ByRef sngCharge As Single, ByRef intIsotopeCount As Integer) As Long
+ ' Returns the settings for the element with intElementID in the ByRef variables
+ ' Returns 0 if success, 1 if failure
+ GetElement = GetElementInternal(intElementID, strSymbol, dblMass, dblUncertainty, sngCharge, intIsotopeCount)
+End Function
+
+Public Function GetElementCount() As Long
+ ' Returns the number of elements in memory
+ GetElementCount = GetElementCountInternal()
+End Function
+
+Public Function GetElementID(ByVal strSymbol As String) As Long
+ ' Returns 0 if not found, the ID if found
+ GetElementID = GetElementIDInternal(strSymbol)
+End Function
+
+Public Function GetElementIsotopes(ByVal intElementID As Integer, ByRef intIsotopeCount As Integer, ByRef dblIsotopeMasses() As Double, ByRef sngIsotopeAbundances() As Single) As Long
+ ' Returns the Isotope masses for the element with intElementID
+ GetElementIsotopes = GetElementIsotopesInternal(intElementID, intIsotopeCount, dblIsotopeMasses(), sngIsotopeAbundances())
+End Function
+
+Public Function GetElementMode() As emElementModeConstants
+ ' Returns the element mode:
+ ' emAverageMass = 1
+ ' emIsotopicMass = 2
+ ' emIntegerMass = 3
+ GetElementMode = GetElementModeInternal()
+End Function
+
+Public Function GetElementSymbol(ByVal intElementID As Integer) As String
+ ' Returns the symbol for the given element ID
+ GetElementSymbol = GetElementSymbolInternal(intElementID)
+End Function
+
+Public Function GetElementStat(ByVal intElementID As Integer, ByVal eElementStat As esElementStatsConstants) As Double
+ ' Returns a single bit of information about a single element
+ GetElementStat = GetElementStatInternal(intElementID, eElementStat)
+End Function
+
+Public Function GetMessageStatement(lngMessageID As Long, Optional strAppendText As String = "") As String
+ ' Returns the message for lngMessageID
+ GetMessageStatement = GetMessageStatementInternal(lngMessageID, strAppendText)
+End Function
+
+Public Function GetMessageStatementCount() As Long
+ GetMessageStatementCount = GetMessageStatementCountInternal()
+End Function
+
+Public Function IsModSymbol(strSymbol As String) As Boolean
+ ' Returns True if strSymbol starts with a ModSymbol
+ IsModSymbol = IsModSymbolInternal(strSymbol)
+End Function
+
+Private Sub LoadDefaults()
+ MemoryLoadAll emAverageMass
+
+ Me.SetElementMode emAverageMass
+ Me.AbbreviationRecognitionMode = arNormalPlusAminoAcids
+ Me.BracketsTreatedAsParentheses = True
+ Me.CaseConversionMode = ccConvertCaseUp
+ Me.DecimalSeparator = "."
+ Me.RtfFontName = "Arial"
+ Me.RtfFontSize = 10
+ Me.StdDevMode = smDecimal
+
+ gComputationOptions.DecimalSeparator = DetermineDecimalPoint()
+
+ mDataInitialized = True
+End Sub
+
+Public Sub RemoveAllAbbreviations()
+ RemoveAllAbbreviationsInternal
+End Sub
+
+Public Sub RemoveAllCautionStatements()
+ RemoveAllCautionStatementsInternal
+End Sub
+
+Public Function MassToPPM(ByVal dblMassToConvert As Double, ByVal dblCurrentMZ As Double) As Double
+ MassToPPM = MassToPPMInternal(dblMassToConvert, dblCurrentMZ)
+End Function
+
+Public Function MonoMassToMZ(ByVal dblMonoisotopicMass As Double, ByVal intCharge As Integer, Optional ByVal dblChargeCarrierMass As Double = 0) As Double
+ MonoMassToMZ = MonoMassToMZInternal(dblMonoisotopicMass, intCharge, dblChargeCarrierMass)
+End Function
+
+Public Sub RecomputeAbbreviationMasses()
+ ' Use this sub to manually recompute the masses of the abbreviations
+ ' Useful if we just finished setting lots of element masses, and
+ ' had blnRecomputeAbbreviationMasses = False when calling .SetElement()
+ RecomputeAbbreviationMassesInternal
+End Sub
+
+Public Function RemoveAbbreviation(ByVal strAbbreviationSymbol As String) As Long
+ RemoveAbbreviation = RemoveAbbreviationInternal(strAbbreviationSymbol)
+End Function
+
+Public Function RemoveAbbreviationByID(ByVal lngAbbreviationID As Long) As Long
+ RemoveAbbreviationByID = RemoveAbbreviationByIDInternal(lngAbbreviationID)
+End Function
+
+Public Function RemoveCautionStatement(ByVal strCautionSymbol As String) As Long
+ RemoveCautionStatement = RemoveCautionStatementInternal(strCautionSymbol)
+End Function
+
+Public Sub ResetAbbreviations()
+ MemoryLoadAbbreviations
+End Sub
+
+Public Sub ResetCautionStatements()
+ MemoryLoadCautionStatements
+End Sub
+
+Public Sub ResetElement(intElementID As Integer, eSpecificStatToReset As esElementStatsConstants)
+ MemoryLoadElements GetElementMode(), intElementID, eSpecificStatToReset
+End Sub
+
+Public Sub ResetMessageStatements()
+ MemoryLoadMessageStatements
+End Sub
+
+Public Function SetAbbreviation(strSymbol As String, strFormula As String, sngCharge As Single, blnIsAminoAcid As Boolean, Optional strOneLetterSymbol As String = "", Optional strComment As String = "", Optional blnValidateFormula As Boolean = True) As Long
+ ' Adds a new abbreviation or updates an existing one (based on strSymbol)
+ ' If blnValidateFormula = True, then makes sure the formula is valid
+ ' It is useful to set blnValidateFormula = False when you're defining all of the abbreviations at once,
+ ' since one abbreviation can depend upon another, and if the second abbreviation hasn't yet been
+ ' defined, then the parsing of the first abbreviation will fail
+ ' Returns 0 if successful, otherwise, returns an Error ID
+ SetAbbreviation = SetAbbreviationInternal(strSymbol, strFormula, sngCharge, blnIsAminoAcid, strOneLetterSymbol, strComment, blnValidateFormula)
+End Function
+
+Public Function SetAbbreviationByID(lngAbbrevID As Long, strSymbol As String, strFormula As String, sngCharge As Single, blnIsAminoAcid As Boolean, Optional strOneLetterSymbol As String = "", Optional strComment As String = "", Optional blnValidateFormula As Boolean = True) As Long
+ ' Adds a new abbreviation or updates an existing one (based on strSymbol)
+ ' If blnValidateFormula = True, then makes sure the formula is valid
+ ' It is useful to set blnValidateFormula = False when you're defining all of the abbreviations at once,
+ ' since one abbreviation can depend upon another, and if the second abbreviation hasn't yet been
+ ' defined, then the parsing of the first abbreviation will fail
+ ' Returns 0 if successful, otherwise, returns an Error ID
+ SetAbbreviationByID = SetAbbreviationByIDInternal(lngAbbrevID, strSymbol, strFormula, sngCharge, blnIsAminoAcid, strOneLetterSymbol, strComment, blnValidateFormula)
+End Function
+
+Public Function SetCautionStatement(strNewSymbolCombo As String, strNewCautionStatement As String) As Long
+ ' Adds a new caution statement or updates an existing one (based on strSymbol)
+ ' Returns 0 if successful, otherwise, returns an Error ID
+ SetCautionStatement = SetCautionStatementInternal(strNewSymbolCombo, strNewCautionStatement)
+End Function
+
+Public Function SetChargeCarrierMass(dblMass As Double)
+ SetChargeCarrierMassInternal dblMass
+End Function
+
+Public Function SetElement(strSymbol As String, dblMass As Double, dblUncertainty As Double, sngCharge As Single, Optional blnRecomputeAbbreviationMasses As Boolean = True) As Long
+ ' Used to update the values for a single element (based on strSymbol)
+ SetElement = SetElementInternal(strSymbol, dblMass, dblUncertainty, sngCharge, blnRecomputeAbbreviationMasses)
+End Function
+
+Public Function SetElementIsotopes(ByVal strSymbol As String, ByVal intIsotopeCount As Integer, ByRef dblIsotopeMassesOneBased() As Double, ByRef sngIsotopeAbundancesOneBased() As Single) As Long
+ SetElementIsotopes = SetElementIsotopesInternal(strSymbol, intIsotopeCount, dblIsotopeMassesOneBased(), sngIsotopeAbundancesOneBased())
+End Function
+
+Public Sub SetElementMode(NewElementMode As emElementModeConstants, Optional blnMemoryLoadElementValues As Boolean = True)
+ SetElementModeInternal NewElementMode, blnMemoryLoadElementValues
+End Sub
+
+Public Sub SetStandardProgressCaptionText(Optional ByVal strMinutesElapsedRemaining As String = "min. elapsed/remaining", Optional ByVal strPreparingToPause As String = "Preparing to Pause", Optional ByVal strResuming As String = "Resuming", Optional ByVal strClickToPause As String = "Click to Pause", Optional ByVal strPaused As String = "Paused", Optional ByVal strPressEscapeToAbort As String = "(Press Escape to abort)")
+ frmProgress.SetStandardCaptionText strMinutesElapsedRemaining, strPreparingToPause, strResuming, strClickToPause, strPaused, strPressEscapeToAbort
+End Sub
+
+Public Function SetMessageStatement(lngMessageID As Long, strNewMessage As String) As Long
+ ' Used to replace the default message strings with foreign language equivalent ones
+ SetMessageStatement = SetMessageStatementInternal(lngMessageID, strNewMessage)
+End Function
+
+Public Sub SortAbbreviations()
+ SortAbbreviationsInternal
+End Sub
+
+Public Function TextToRTF(strTextToConvert As String, Optional CalculatorMode As Boolean = False, Optional blnHighlightCharFollowingPercentSign As Boolean = True, Optional blnOverrideErrorID As Boolean = False, Optional lngErrorIDOverride As Long = 0) As String
+ ' Converts an RTF string for the given text
+ ' If blnHighlightCharFollowingPercentSign is true, then changes the character
+ ' following a percent sign to red (and removes the percent sign)
+
+ ' When blnCalculatorMode = True, then does not superscript + signs and numbers following + signs
+ TextToRTF = PlainTextToRtfInternal(strTextToConvert, CalculatorMode, blnHighlightCharFollowingPercentSign, blnOverrideErrorID, lngErrorIDOverride)
+End Function
+
+Public Function ValidateAllAbbreviations() As Long
+ ' Checks the formula of all abbreviations to make sure it's valid
+ ' Marks any abbreviations as Invalid if a problem is found or a circular reference exists
+ ' Returns a count of the number of invalid abbreviations found
+
+ ValidateAllAbbreviations = ValidateAllAbbreviationsInternal()
+End Function
+
+Private Sub Class_Initialize()
+ If Not mDataInitialized Then LoadDefaults
+End Sub
+
+Private Sub Class_Terminate()
+ Set Peptide = Nothing
+ Set CapFlow = Nothing
+ Set Compound = Nothing
+End Sub
+
+Public Property Get AbbreviationRecognitionMode() As arAbbrevRecognitionModeConstants
+ AbbreviationRecognitionMode = gComputationOptions.AbbrevRecognitionMode
+End Property
+
+Public Property Let AbbreviationRecognitionMode(eAbbrevRecognitionMode As arAbbrevRecognitionModeConstants)
+ If eAbbrevRecognitionMode >= arNormalOnly And eAbbrevRecognitionMode <= arNoAbbreviations Then
+ gComputationOptions.AbbrevRecognitionMode = eAbbrevRecognitionMode
+ ConstructMasterSymbolsList
+ End If
+End Property
+
+Public Property Get AppDate() As String
+ AppDate = PROGRAM_DATE
+End Property
+
+Public Property Get AppVersion() As String
+ AppVersion = PROGRAM_VERSION
+End Property
+
+Public Property Let BracketsTreatedAsParentheses(boolBracketSet As Boolean)
+ gComputationOptions.BracketsAsParentheses = boolBracketSet
+End Property
+
+Public Property Get BracketsTreatedAsParentheses() As Boolean
+ BracketsTreatedAsParentheses = gComputationOptions.BracketsAsParentheses
+End Property
+
+Public Property Let CaseConversionMode(NewCaseConversionMode As ccCaseConversionConstants)
+ If NewCaseConversionMode >= ccConvertCaseUp And NewCaseConversionMode <= ccSmartCase Then
+ gComputationOptions.CaseConversion = NewCaseConversionMode
+ End If
+End Property
+
+Public Property Get CaseConversionMode() As ccCaseConversionConstants
+ CaseConversionMode = gComputationOptions.CaseConversion
+End Property
+
+Public Property Let DecimalSeparator(strNewDecimalSeparator As String)
+ If Len(strNewDecimalSeparator) = 1 Then
+ gComputationOptions.DecimalSeparator = strNewDecimalSeparator
+ End If
+End Property
+
+Public Property Get DecimalSeparator() As String
+ DecimalSeparator = gComputationOptions.DecimalSeparator
+End Property
+
+Public Property Get ErrorDescription() As String
+ ErrorDescription = GetErrorDescription()
+End Property
+
+Public Property Get ErrorID() As Long
+ ErrorID = GetErrorID()
+End Property
+
+Public Property Get ErrorCharacter() As String
+ ErrorCharacter = GetErrorCharacter()
+End Property
+
+Public Property Get ErrorPosition() As Long
+ ErrorPosition = GetErrorPosition()
+End Property
+
+Public Property Let RtfFontName(strNewFontName As String)
+ If Len(strNewFontName) > 0 Then
+ gComputationOptions.RtfFontName = strNewFontName
+ End If
+End Property
+
+Public Property Get RtfFontName() As String
+ RtfFontName = gComputationOptions.RtfFontName
+End Property
+
+Public Property Let RtfFontSize(intNewFontSize As Integer)
+ If intNewFontSize > 0 Then
+ gComputationOptions.RtfFontSize = intNewFontSize
+ End If
+End Property
+
+Public Property Get RtfFontSize() As Integer
+ RtfFontSize = gComputationOptions.RtfFontSize
+End Property
+
+Public Property Get ShowErrorDialogs() As Boolean
+ ShowErrorDialogs = ShowErrorMessageDialogs()
+End Property
+
+Public Property Let ShowErrorDialogs(blnValue As Boolean)
+ SetShowErrorMessageDialogs blnValue
+End Property
+
+Public Property Let StdDevMode(NewStdDevMode As smStdDevModeConstants)
+ If NewStdDevMode >= smShort And NewStdDevMode <= smDecimal Then
+ gComputationOptions.StdDevMode = NewStdDevMode
+ End If
+End Property
+
+Public Property Get StdDevMode() As smStdDevModeConstants
+ StdDevMode = gComputationOptions.StdDevMode
+End Property
+
diff --git a/MwtWinDll/clsPeptideClass.cls b/MwtWinDll/clsPeptideClass.cls
new file mode 100644
index 0000000..92ec28a
--- /dev/null
+++ b/MwtWinDll/clsPeptideClass.cls
@@ -0,0 +1,2150 @@
+VERSION 1.0 CLASS
+BEGIN
+ MultiUse = -1 'True
+ Persistable = 0 'NotPersistable
+ DataBindingBehavior = 0 'vbNone
+ DataSourceBehavior = 0 'vbNone
+ MTSTransactionMode = 0 'NotAnMTSObject
+END
+Attribute VB_Name = "MWPeptideClass"
+Attribute VB_GlobalNameSpace = False
+Attribute VB_Creatable = True
+Attribute VB_PredeclaredId = False
+Attribute VB_Exposed = True
+Attribute VB_Ext_KEY = "SavedWithClassBuilder6" ,"Yes"
+Attribute VB_Ext_KEY = "Top_Level" ,"No"
+Option Explicit
+
+' Molecular Weight Calculator routines with ActiveX Class interfaces: MWPeptideClass
+' Written by Matthew Monroe in Richland, WA
+
+Private Const RESIDUE_DIM_CHUNK = 50
+Private Const MAX_MODIFICATIONS = 6 ' Maximum number of modifications for a single residue
+Private Const UNKNOWN_SYMBOL = "Xxx"
+Private Const UNKNOWN_SYMBOL_ONE_LETTER = "X"
+Private Const ION_TYPE_COUNT = 3
+
+Private Const TERMINII_SYMBOL = "-"
+Private Const TRYPTIC_RULE_RESIDUES = "KR"
+Private Const TRYPTIC_EXCEPTION_RESIDUES = "P"
+
+Private Const SHOULDER_ION_PREFIX = "Shoulder-"
+
+Public Enum ctgCTerminusGroupConstants
+ ctgHydroxyl = 0
+ ctgAmide = 1
+ ctgNone = 2
+End Enum
+
+Public Enum ntgNTerminusGroupConstants
+ ntgHydrogen = 0
+ ntgHydrogenPlusProton = 1
+ ntgAcetyl = 2
+ ntgPyroGlu = 3
+ ntgCarbamyl = 4
+ ntgPTC = 5
+ ntgNone = 6
+End Enum
+
+Public Enum itIonTypeConstants
+ itAIon = 0
+ itBIon = 1
+ itYIon = 2
+End Enum
+
+Private Type udtModificationSymbolType
+ Symbol As String ' Symbol used for modification in formula; may be 1 or more characters; for example: + ++ * ** etc.
+ ModificationMass As Double ' Normally positive, but could be negative
+ IndicatesPhosphorylation As Boolean ' When true, then this symbol means a residue is phosphorylated
+ Comment As String
+End Type
+
+Private Type udtResidueType
+ Symbol As String ' 3 letter symbol
+ Mass As Double ' The mass of the residue alone (excluding any modification)
+ MassWithMods As Double ' The mass of the residue, including phosphorylation or any modification
+ IonMass(ION_TYPE_COUNT) As Double ' 0-based array; the masses that the a, b, and y ions ending/starting with this residue will produce in the mass spectrum (includes H+)
+ Phosphorylated As Boolean ' Technically, only Ser, Thr, or Tyr residues can be phosphorylated (H3PO4), but if the user phosphorylates other residues, we'll allow that
+ ModificationIDCount As Integer
+ ModificationIDs(MAX_MODIFICATIONS) As Long ' 1-based array
+End Type
+
+Private Type udtTerminusType
+ Formula As String
+ Mass As Double
+ PrecedingResidue As udtResidueType ' If the peptide sequence is part of a protein, the user can record the final residue of the previous peptide sequence here
+ FollowingResidue As udtResidueType ' If the peptide sequence is part of a protein, the user can record the first residue of the next peptide sequence here
+End Type
+
+Public Type udtFragmentionSpectrumIntensitiesType
+ IonType(ION_TYPE_COUNT) As Double ' 0-based array
+ BYIonShoulder As Double ' If > 0 then shoulder ions will be created by B and Y ions
+ NeutralLoss As Double
+End Type
+
+' Note: A ions can have ammonia and phosphate loss, but not water loss, so this is set to false by default
+' The graphical version of MwtWin does not allow this to be overridden, but a programmer could do so via a call to this Dll
+Public Type udtIonTypeOptionsType
+ ShowIon As Boolean
+ NeutralLossWater As Boolean
+ NeutralLossAmmonia As Boolean
+ NeutralLossPhosphate As Boolean
+End Type
+
+Public Type udtFragmentationSpectrumOptionsType
+ IntensityOptions As udtFragmentionSpectrumIntensitiesType
+ IonTypeOptions(ION_TYPE_COUNT) As udtIonTypeOptionsType
+ DoubleChargeIonsShow As Boolean
+ DoubleChargeIonsThreshold As Single
+End Type
+
+Public Type udtFragmentationSpectrumDataType
+ Mass As Double
+ Intensity As Double
+ Symbol As String ' The symbol, with the residue number (e.g. y1, y2, b3-H2O, Shoulder-y1, etc.)
+ SymbolGeneric As String ' The symbol, without the residue number (e.g. a, b, y, b++, Shoulder-y, etc.)
+ SourceResidueNumber As Long ' The residue number that resulted in this mass
+ SourceResidueSymbol3Letter As String ' The residue symbol that resulted in this mass
+ Charge As Integer
+ IonType As itIonTypeConstants
+ IsShoulderIon As Boolean ' B and Y ions can have Shoulder ions at +-1
+End Type
+
+' Note: A peptide goes from N to C, eg. HGlyLeuTyrOH has N-Terminus = H and C-Terminus = OH
+' Residue 1 would be Gly, Residue 2 would be Leu, Residue 3 would be Tyr
+Private Residues() As udtResidueType ' 1-based array
+Private ResidueCount As Long
+Private ResidueCountDimmed As Long
+
+' ModificationSymbols() holds a list of the potential modification symbols and the mass of each modification
+' Modification symbols can be 1 or more letters long
+Private ModificationSymbols() As udtModificationSymbolType ' 1-based array
+Private ModificationSymbolCount As Long
+Private ModificationSymbolCountDimmed As Long
+
+Private mNTerminus As udtTerminusType ' Formula on the N-Terminus
+Private mCTerminus As udtTerminusType ' Formula on the C-Terminus
+Private mTotalMass As Double
+
+Private mWaterLossSymbol As String ' -H2O
+Private mAmmoniaLossSymbol As String ' -NH3
+Private mPhosphoLossSymbol As String ' -H3PO4
+
+Private mFragSpectrumOptions As udtFragmentationSpectrumOptionsType
+
+Private dblHOHMass As Double
+Private dblNH3Mass As Double
+Private dblH3PO4Mass As Double
+Private dblPhosphorylationMass As Double ' H3PO4 minus HOH = 79.9663326
+Private dblHydrogenMass As Double ' Mass of hydrogen
+Private dblChargeCarrierMass As Double ' H minus one electron
+
+Private dblImmoniumMassDifference As Double ' CO minus H = 26.9871
+
+Private dblHistidineFW As Double ' 110
+Private dblPhenylalanineFW As Double ' 120
+Private dblTyrosineFW As Double ' 136
+
+Private mDelayUpdateResidueMass As Boolean
+'
+
+Private Sub AppendDataToFragSpectrum(lngIonCount As Long, FragSpectrumWork() As udtFragmentationSpectrumDataType, sngMass As Single, sngIntensity As Single, strIonSymbol As String, strIonSymbolGeneric As String, lngSourceResidue As Long, strSourceResidueSymbol3Letter As String, intCharge As Integer, eIonType As itIonTypeConstants, blnIsShoulderIon As Boolean)
+On Error GoTo AppendDataPointErrorHandler
+
+ If lngIonCount > UBound(FragSpectrumWork()) Then
+ ' This shouldn't happen
+ Debug.Assert False
+ ReDim Preserve FragSpectrumWork(UBound(FragSpectrumWork()) + 10)
+ End If
+
+ With FragSpectrumWork(lngIonCount)
+ .Mass = sngMass
+ .Intensity = sngIntensity
+ .Symbol = strIonSymbol
+ .SymbolGeneric = strIonSymbolGeneric
+ .SourceResidueNumber = lngSourceResidue
+ .SourceResidueSymbol3Letter = strSourceResidueSymbol3Letter
+ .Charge = intCharge
+ .IonType = eIonType
+ .IsShoulderIon = blnIsShoulderIon
+ End With
+ lngIonCount = lngIonCount + 1
+ Exit Sub
+
+AppendDataPointErrorHandler:
+ Debug.Print Err.Description
+ Debug.Assert False
+End Sub
+
+Private Function CheckForModifications(strPartialSequence As String, lngResidueIndex As Long, Optional blnAddMissingModificationSymbols As Boolean = False) As Long
+ ' Looks at strPartialSequence to see if it contains 1 or more modifications
+ ' If any modification symbols are found, the modification is recorded in .ModificationIDs()
+ ' If all or part of the modification symbol is not found in ModificationSymbols(), then a new entry
+ ' is added to ModificationSymbols()
+ ' Returns the total length of all modifications found
+
+ Dim lngCompareIndex As Long, lngSequenceStrLength As Long
+ Dim strModSymbolGroup As String
+ Dim lngModificationID As Long, lngModSymbolLengthTotal As Long
+ Dim strTestChar As String
+ Dim lngIndex As Long
+ Dim blnMatchFound As Boolean
+
+ lngSequenceStrLength = Len(strPartialSequence)
+
+ ' Find the entire group of potential modification symbols
+ strModSymbolGroup = ""
+ lngCompareIndex = 1
+ Do While lngCompareIndex <= lngSequenceStrLength
+ strTestChar = Mid(strPartialSequence, lngCompareIndex, 1)
+ If IsModSymbolInternal(strTestChar) Then
+ strModSymbolGroup = strModSymbolGroup & strTestChar
+ Else
+ Exit Do
+ End If
+ lngCompareIndex = lngCompareIndex + 1
+ Loop
+
+ lngModSymbolLengthTotal = Len(strModSymbolGroup)
+ Do While Len(strModSymbolGroup) > 0
+ ' Step through strModSymbolGroup to see if all of it or parts of it match any of the defined
+ ' modification symbols
+
+ blnMatchFound = False
+ For lngIndex = Len(strModSymbolGroup) To 1 Step -1
+ ' See if the modification is already defined
+ lngModificationID = GetModificationSymbolID(Left(strModSymbolGroup, lngIndex))
+ If lngModificationID > 0 Then
+ blnMatchFound = True
+ Exit For
+ End If
+ Next lngIndex
+
+ If Not blnMatchFound Then
+ If blnAddMissingModificationSymbols Then
+ ' Add strModSymbolGroup as a new modification, using a mass of 0 since we don't know the modification mass
+ SetModificationSymbol strModSymbolGroup, 0, False, ""
+ blnMatchFound = True
+ Else
+ ' Ignore the modification
+ strModSymbolGroup = 0
+ End If
+ strModSymbolGroup = ""
+ End If
+
+ If blnMatchFound Then
+ ' Record the modification for this residue
+ With Residues(lngResidueIndex)
+ If .ModificationIDCount < MAX_MODIFICATIONS Then
+ .ModificationIDCount = .ModificationIDCount + 1
+ .ModificationIDs(.ModificationIDCount) = lngModificationID
+ If ModificationSymbols(lngModificationID).IndicatesPhosphorylation Then
+ .Phosphorylated = True
+ End If
+ End If
+ End With
+
+ If lngIndex < Len(strModSymbolGroup) Then
+ ' Remove the matched portion from strModSymbolGroup and test again
+ strModSymbolGroup = Mid(strModSymbolGroup, lngIndex + 1)
+ Else
+ strModSymbolGroup = ""
+ End If
+ End If
+ Loop
+
+ CheckForModifications = lngModSymbolLengthTotal
+
+End Function
+
+Private Function ComputeMaxIonsPerResidue() As Integer
+ ' Estimate the total ions per residue that will be created
+ ' This number will nearly always be much higher than the number of ions that will actually
+ ' be stored for a given sequence, since not all will be doubly charged, and not all will show
+ ' all of the potential neutral losses
+
+ Dim eIonIndex As itIonTypeConstants, intIonCount As Integer
+
+ intIonCount = 0
+ With mFragSpectrumOptions
+ For eIonIndex = 0 To ION_TYPE_COUNT - 1
+ If .IonTypeOptions(eIonIndex).ShowIon Then
+ intIonCount = intIonCount + 1
+
+ If Abs(.IntensityOptions.BYIonShoulder) > 0 Then
+ If eIonIndex = itBIon Or eIonIndex = itYIon Then
+ intIonCount = intIonCount + 2
+ End If
+ End If
+
+ If .IonTypeOptions(eIonIndex).NeutralLossAmmonia Then intIonCount = intIonCount + 1
+ If .IonTypeOptions(eIonIndex).NeutralLossPhosphate Then intIonCount = intIonCount + 1
+ If .IonTypeOptions(eIonIndex).NeutralLossWater Then intIonCount = intIonCount + 1
+ End If
+ Next eIonIndex
+
+ ' Double Charge ions could be created for all ions, so simply double intIonCount
+ If .DoubleChargeIonsShow Then
+ intIonCount = intIonCount * 2
+ End If
+
+ End With
+
+ ComputeMaxIonsPerResidue = intIonCount
+
+End Function
+
+Private Function FillResidueStructureUsingSymbol(strSymbol As String, Optional blnUse3LetterCode As Boolean = True) As udtResidueType
+ ' Returns a variable of type udtResidueType containing strSymbol as the residue symbol
+ ' If strSymbol is a valid amino acid type, then also updates udtResidue with the default information
+
+ Dim strSymbol3Letter As String
+ Dim lngAbbrevID As Long
+ Dim udtResidue As udtResidueType
+
+ If Len(strSymbol) > 0 Then
+ If blnUse3LetterCode Then
+ strSymbol3Letter = strSymbol
+ Else
+ strSymbol3Letter = GetAminoAcidSymbolConversionInternal(strSymbol, True)
+ If strSymbol3Letter = "" Then strSymbol3Letter = strSymbol
+ End If
+
+ lngAbbrevID = GetAbbreviationIDInternal(strSymbol3Letter, True)
+ Else
+ lngAbbrevID = 0
+ End If
+
+ With udtResidue
+ .Symbol = strSymbol3Letter
+ .ModificationIDCount = 0
+ .Phosphorylated = False
+ If lngAbbrevID > 0 Then
+ .Mass = GetAbbreviationMass(lngAbbrevID)
+ Else
+ .Mass = 0
+ End If
+ .MassWithMods = .Mass
+ End With
+
+ FillResidueStructureUsingSymbol = udtResidue
+
+End Function
+
+'Public Function GetFragmentationMasses(ByVal lngMaxIonCount As Long, ByRef sngIonMassesZeroBased() As Single, ByRef sngIonIntensitiesZeroBased() As Single, ByRef strIonSymbolsZeroBased() As String) As Long
+Public Function GetFragmentationMasses(ByRef udtFragSpectrum() As udtFragmentationSpectrumDataType) As Long
+ ' Returns the number of ions in FragSpectrumWork()
+
+ Dim lngResidueIndex As Long, intChargeIndex As Integer, intShoulderIndex As Integer
+ Dim eIonType As itIonTypeConstants
+ Dim lngIndex As Long
+ Dim lngPredictedIonCount As Long, lngIonCount As Long
+ Dim sngIonIntensities(ION_TYPE_COUNT) As Single
+ Dim sngIonShoulderIntensity As Single, sngNeutralLossIntensity As Single
+ Dim blnShowDoublecharge As Boolean, sngDoubleChargeThreshold As Single
+ Dim sngBaseMass As Single, sngConvolutedMass As Single, sngObservedMass As Single
+ Dim strResidues As String
+ Dim blnPhosphorylated As Boolean
+ Dim sngIntensity As Single
+ Dim strIonSymbol As String, strIonSymbolGeneric As String
+ Dim FragSpectrumWork() As udtFragmentationSpectrumDataType
+ Dim PointerArray() As Long
+
+ If ResidueCount = 0 Then
+ ' No residues
+ GetFragmentationMasses = 0
+ Exit Function
+ End If
+
+ ' Copy some of the values from mFragSpectrumOptions to local variables to make things easier to read
+ With mFragSpectrumOptions
+ For eIonType = 0 To ION_TYPE_COUNT - 1
+ sngIonIntensities(eIonType) = .IntensityOptions.IonType(eIonType)
+ Next eIonType
+ sngIonShoulderIntensity = .IntensityOptions.BYIonShoulder
+ sngNeutralLossIntensity = .IntensityOptions.NeutralLoss
+
+ blnShowDoublecharge = .DoubleChargeIonsShow
+ sngDoubleChargeThreshold = .DoubleChargeIonsThreshold
+ End With
+
+ ' Populate sngIonMassesZeroBased() and sngIonIntensitiesZeroBased()
+ ' Put ion descriptions in strIonSymbolsZeroBased
+ lngPredictedIonCount = GetFragmentationSpectrumRequiredDataPoints()
+
+ If lngPredictedIonCount = 0 Then lngPredictedIonCount = ResidueCount
+ ReDim FragSpectrumWork(lngPredictedIonCount)
+
+ ' Need to update the residue masses in case the modifications have changed
+ UpdateResidueMasses
+
+ lngIonCount = 0
+ For lngResidueIndex = 1 To ResidueCount
+ With Residues(lngResidueIndex)
+
+ For eIonType = 0 To ION_TYPE_COUNT - 1
+ If mFragSpectrumOptions.IonTypeOptions(eIonType).ShowIon Then
+ If (lngResidueIndex = 1 Or lngResidueIndex = ResidueCount) And (eIonType = itAIon Or eIonType = itBIon) Then
+ ' Don't include a or b ions in the output masses
+ Else
+
+ ' Ion is used
+ sngBaseMass = .IonMass(eIonType) ' Already in the H+ state
+ sngIntensity = sngIonIntensities(eIonType)
+
+ ' Get the list of residues preceding or following this residue
+ ' Note that the residue symbols are separated by a space to avoid accidental matching by the InStr() functions below
+ strResidues = GetInternalResidues(lngResidueIndex, eIonType, blnPhosphorylated)
+
+ For intChargeIndex = 1 To 2
+ If intChargeIndex = 1 Or (intChargeIndex = 2 And blnShowDoublecharge) Then
+ If intChargeIndex = 1 Then
+ sngConvolutedMass = sngBaseMass
+ Else
+ ' Compute mass at higher charge
+ sngConvolutedMass = ConvoluteMassInternal(sngBaseMass, 1, intChargeIndex, dblChargeCarrierMass)
+ End If
+
+ If intChargeIndex > 1 And sngBaseMass < sngDoubleChargeThreshold Then
+ ' BaseMass is below threshold, do not add to Predicted Spectrum
+ Else
+ ' Add ion to Predicted Spectrum
+
+ ' Y Ions are numbered in decreasing order: y5, y4, y3, y2, y1
+ ' A and B ions are numbered in increasing order: a1, a2, etc. or b1, b2, etc.
+ strIonSymbolGeneric = LookupIonTypeString(eIonType)
+ If eIonType = itYIon Then
+ strIonSymbol = strIonSymbolGeneric & Trim(Str(ResidueCount - lngResidueIndex + 1))
+ Else
+ strIonSymbol = strIonSymbolGeneric & Trim(Str(lngResidueIndex))
+ End If
+
+ If intChargeIndex = 2 Then
+ strIonSymbol = strIonSymbol & "++"
+ strIonSymbolGeneric = strIonSymbolGeneric & "++"
+ End If
+
+ AppendDataToFragSpectrum lngIonCount, FragSpectrumWork(), sngConvolutedMass, sngIntensity, strIonSymbol, strIonSymbolGeneric, lngResidueIndex, .Symbol, intChargeIndex, eIonType, False
+
+ ' Add shoulder ions to PredictedSpectrum()
+ ' if a B or Y ion and the shoulder intensity is > 0
+ ' Need to use Abs() here since user can define negative theoretical intensities (which allows for plotting a spectrum inverted)
+ If Abs(sngIonShoulderIntensity) > 0 And (eIonType = itBIon Or eIonType = itYIon) Then
+ For intShoulderIndex = -1 To 1 Step 2
+ sngObservedMass = sngConvolutedMass + intShoulderIndex * (1 / intChargeIndex)
+ AppendDataToFragSpectrum lngIonCount, FragSpectrumWork(), sngObservedMass, sngIonShoulderIntensity, SHOULDER_ION_PREFIX & strIonSymbol, SHOULDER_ION_PREFIX & strIonSymbolGeneric, lngResidueIndex, .Symbol, intChargeIndex, eIonType, True
+ Next intShoulderIndex
+ End If
+
+ ' Apply neutral loss modifications
+ If mFragSpectrumOptions.IonTypeOptions(eIonType).NeutralLossWater Then
+ ' Loss of water only affects Ser, Thr, Asp, or Glu (S, T, E, or D)
+ ' See if the residues up to this point contain any of these residues
+ If InStr(strResidues, "Ser") Or InStr(strResidues, "Thr") Or InStr(strResidues, "Glu") Or InStr(strResidues, "Asp") Then
+ sngObservedMass = sngConvolutedMass - (dblHOHMass / intChargeIndex)
+ AppendDataToFragSpectrum lngIonCount, FragSpectrumWork(), sngObservedMass, sngNeutralLossIntensity, strIonSymbol & mWaterLossSymbol, strIonSymbolGeneric & mWaterLossSymbol, lngResidueIndex, .Symbol, intChargeIndex, eIonType, False
+ End If
+ End If
+
+ If mFragSpectrumOptions.IonTypeOptions(eIonType).NeutralLossAmmonia Then
+ ' Loss of Ammonia only affects Arg, Lys, Gln, or Asn (R, K, Q, or N)
+ ' See if the residues up to this point contain any of these residues
+ If InStr(strResidues, "Arg") Or InStr(strResidues, "Lys") Or InStr(strResidues, "Gln") Or InStr(strResidues, "Asn") Then
+ sngObservedMass = sngConvolutedMass - (dblNH3Mass / intChargeIndex)
+ AppendDataToFragSpectrum lngIonCount, FragSpectrumWork(), sngObservedMass, sngNeutralLossIntensity, strIonSymbol & mAmmoniaLossSymbol, strIonSymbolGeneric & mAmmoniaLossSymbol, lngResidueIndex, .Symbol, intChargeIndex, eIonType, False
+ End If
+ End If
+
+ If mFragSpectrumOptions.IonTypeOptions(eIonType).NeutralLossPhosphate Then
+ ' Loss of phosphate only affects phosphorylated residues
+ ' Technically, only Ser, Thr, or Tyr (S, T, or Y) can be phosphorylated, but if the user marks other residues as phosphorylated, we'll allow that
+ ' See if the residues up to this point contain phosphorylated residues
+ If blnPhosphorylated Then
+ sngObservedMass = sngConvolutedMass - (dblH3PO4Mass / intChargeIndex)
+ AppendDataToFragSpectrum lngIonCount, FragSpectrumWork(), sngObservedMass, sngNeutralLossIntensity, strIonSymbol & mPhosphoLossSymbol, strIonSymbolGeneric & mPhosphoLossSymbol, lngResidueIndex, .Symbol, intChargeIndex, eIonType, False
+ End If
+ End If
+
+ End If
+ End If
+ Next intChargeIndex
+ End If
+ End If
+ Next eIonType
+ End With
+ Next lngResidueIndex
+
+ ' Sort arrays by mass (using a pointer array to synchronize the arrays)
+ ReDim PointerArray(lngIonCount)
+
+ For lngIndex = 0 To lngIonCount - 1
+ PointerArray(lngIndex) = lngIndex
+ Next lngIndex
+
+ ShellSortFragSpectrum FragSpectrumWork(), PointerArray(), 0, lngIonCount - 1
+
+ ' Copy the data from FragSpectrumWork() to udtFragSpectrum()
+
+ ReDim udtFragSpectrum(lngIonCount)
+
+ For lngIndex = 0 To lngIonCount - 1
+ udtFragSpectrum(lngIndex) = FragSpectrumWork(PointerArray(lngIndex))
+ Next lngIndex
+
+ ' Return the actual number of ions computed
+ GetFragmentationMasses = lngIonCount
+
+End Function
+
+Public Function GetFragmentationSpectrumRequiredDataPoints() As Long
+ ' Determines the total number of data points that will be required for a theoretical fragmentation spectrum
+
+ GetFragmentationSpectrumRequiredDataPoints = ResidueCount * ComputeMaxIonsPerResidue()
+
+End Function
+
+Public Function GetFragmentationSpectrumOptions() As udtFragmentationSpectrumOptionsType
+
+On Error GoTo GetFragmentationSpectrumOptionsErrorHandler
+
+ GetFragmentationSpectrumOptions = mFragSpectrumOptions
+
+ Exit Function
+
+GetFragmentationSpectrumOptionsErrorHandler:
+ GeneralErrorHandler "MWPeptideClass.GetFragmentationSpectrumOptions", Err.Number
+
+End Function
+
+Public Function GetPeptideMass() As Double
+ ' Returns the mass of the entire peptide
+
+ ' Update the residue masses in order to update mTotalMass
+ UpdateResidueMasses
+
+ GetPeptideMass = mTotalMass
+End Function
+
+Private Function GetInternalResidues(lngCurrentResidueIndex As Long, eIonType As itIonTypeConstants, Optional ByRef blnPhosphorylated As Boolean) As String
+ ' Determines the residues preceding or following the given residue (up to and including the current residue)
+ ' If eIonType is a or b ions, then returns residues from the N terminus
+ ' If eIonType is y ion, then returns residues from the C terminus
+ ' Also, set blnPhosphorylated to true if any of the residues is Ser, Thr, or Tyr and is phosphorylated
+ '
+ ' Note that the residue symbols are separated by a space to avoid accidental matching by the InStr() function
+
+ Dim strInternalResidues As String
+ Dim lngResidueIndex As Long
+
+ strInternalResidues = ""
+ blnPhosphorylated = False
+ If eIonType = itYIon Then
+ For lngResidueIndex = lngCurrentResidueIndex To ResidueCount
+ With Residues(lngResidueIndex)
+ strInternalResidues = strInternalResidues & .Symbol & " "
+ If .Phosphorylated Then blnPhosphorylated = True
+ End With
+ Next lngResidueIndex
+ Else
+ For lngResidueIndex = 1 To lngCurrentResidueIndex
+ With Residues(lngResidueIndex)
+ strInternalResidues = strInternalResidues & .Symbol & " "
+ If .Phosphorylated Then blnPhosphorylated = True
+ End With
+ Next lngResidueIndex
+ End If
+
+ GetInternalResidues = strInternalResidues
+
+End Function
+
+Public Function GetModificationSymbol(ByVal lngModificationID As Long, ByRef strModSymbol As String, ByRef dblModificationMass As Double, ByRef blnIndicatesPhosphorylation As Boolean, ByRef strComment As String) As Long
+ ' Returns information on the modification with lngModificationID
+ ' Returns 0 if success, 1 if failure
+
+ If lngModificationID >= 1 And lngModificationID <= ModificationSymbolCount Then
+ With ModificationSymbols(lngModificationID)
+ strModSymbol = .Symbol
+ dblModificationMass = .ModificationMass
+ blnIndicatesPhosphorylation = .IndicatesPhosphorylation
+ strComment = .Comment
+ End With
+ GetModificationSymbol = 0
+ Else
+ strModSymbol = ""
+ dblModificationMass = 0
+ blnIndicatesPhosphorylation = False
+ strComment = ""
+ GetModificationSymbol = 1
+ End If
+
+End Function
+
+Public Function GetModificationSymbolCount() As Long
+ ' Returns the number of modifications defined
+
+ GetModificationSymbolCount = ModificationSymbolCount
+End Function
+
+Public Function GetModificationSymbolID(strModSymbol As String) As Long
+ ' Returns the ID for a given modification
+ ' Returns 0 if not found, the ID if found
+
+ Dim intIndex As Integer, lngModificationIDMatch As Long
+
+ For intIndex = 1 To ModificationSymbolCount
+ If ModificationSymbols(intIndex).Symbol = strModSymbol Then
+ lngModificationIDMatch = intIndex
+ Exit For
+ End If
+ Next intIndex
+
+ GetModificationSymbolID = lngModificationIDMatch
+
+End Function
+
+Public Function GetResidue(ByVal lngResidueNumber As Long, ByRef strSymbol As String, ByRef dblMass As Double, ByRef blnIsModified As Boolean, ByRef intModificationCount As Integer) As Long
+ ' Returns 0 if success, 1 if failure
+ If lngResidueNumber >= 1 And lngResidueNumber <= ResidueCount Then
+ With Residues(lngResidueNumber)
+ strSymbol = .Symbol
+ dblMass = .Mass
+ blnIsModified = (.ModificationIDCount > 0)
+ intModificationCount = .ModificationIDCount
+ End With
+ GetResidue = 0
+ Else
+ GetResidue = 1
+ End If
+End Function
+
+Public Function GetResidueCount() As Long
+ GetResidueCount = ResidueCount
+End Function
+
+Public Function GetResidueCountSpecificResidue(strResidueSymbol As String, Optional blnUse3LetterCode As Boolean = True) As Long
+ ' Returns the number of occurrences of the given residue in the loaded sequence
+
+ Dim strSearchResidue3Letter As String
+ Dim lngResidueCount As Long
+ Dim lngResidueIndex As Long
+
+ If blnUse3LetterCode Then
+ strSearchResidue3Letter = strResidueSymbol
+ Else
+ strSearchResidue3Letter = GetAminoAcidSymbolConversionInternal(strResidueSymbol, True)
+ End If
+
+ lngResidueCount = 0
+ For lngResidueIndex = 0 To ResidueCount - 1
+ If Residues(lngResidueIndex).Symbol = strSearchResidue3Letter Then
+ lngResidueCount = lngResidueCount + 1
+ End If
+
+ Next lngResidueIndex
+
+ GetResidueCountSpecificResidue = lngResidueCount
+End Function
+
+Public Function GetResidueModificationIDs(lngResidueNumber As Long, lngModificationIDsOneBased() As Long) As Long
+ ' Returns the number of Modifications
+ ' ReDims lngModificationIDsOneBased() to hold the values
+
+ Dim intIndex As Integer
+
+ If lngResidueNumber >= 1 And lngResidueNumber <= ResidueCount Then
+
+ With Residues(lngResidueNumber)
+
+ ' Need to use this in case the calling program is sending an array with fixed dimensions
+ On Error Resume Next
+ ReDim lngModificationIDsOneBased(.ModificationIDCount)
+
+ For intIndex = 1 To .ModificationIDCount
+ lngModificationIDsOneBased(intIndex) = .ModificationIDs(intIndex)
+ Next intIndex
+
+ GetResidueModificationIDs = .ModificationIDCount
+ End With
+ Else
+ GetResidueModificationIDs = 0
+ End If
+
+End Function
+
+Public Function GetResidueSymbolOnly(ByVal lngResidueNumber As Long, Optional blnUse3LetterCode As Boolean = True) As String
+ ' Returns the symbol at the given residue number, or "" if an invalid residue number
+
+ Dim strSymbol As String
+
+ If lngResidueNumber >= 1 And lngResidueNumber <= ResidueCount Then
+ With Residues(lngResidueNumber)
+ strSymbol = .Symbol
+ End With
+ If Not blnUse3LetterCode Then strSymbol = GetAminoAcidSymbolConversionInternal(strSymbol, False)
+ Else
+ strSymbol = ""
+ End If
+
+ GetResidueSymbolOnly = strSymbol
+
+End Function
+
+Public Function GetSequence(Optional blnUse3LetterCode As Boolean = True, Optional blnAddSpaceEvery10Residues As Boolean = False, Optional blnSeparateResiduesWithDash As Boolean = False, Optional blnIncludeNandCTerminii As Boolean = False, Optional blnIncludeModificationSymbols As Boolean = True) As String
+ ' Construct a text sequence using Residues() and the N and C Terminus info
+
+ Dim strSequence As String, strSymbol3Letter As String, strSymbol1Letter As String
+ Dim strDashAdd As String
+ Dim strModSymbol As String, strModSymbolComment As String
+ Dim blnIndicatesPhosphorylation As Boolean
+ Dim dblModMass As Double
+ Dim lngIndex As Long, intModIndex As Integer
+ Dim lngError As Long
+
+ If blnSeparateResiduesWithDash Then strDashAdd = "-" Else strDashAdd = ""
+
+ strSequence = ""
+ For lngIndex = 1 To ResidueCount
+ With Residues(lngIndex)
+ strSymbol3Letter = .Symbol
+ If blnUse3LetterCode Then
+ strSequence = strSequence & strSymbol3Letter
+ Else
+ strSymbol1Letter = GetAminoAcidSymbolConversionInternal(strSymbol3Letter, False)
+ If strSymbol1Letter = "" Then strSymbol1Letter = UNKNOWN_SYMBOL_ONE_LETTER
+ strSequence = strSequence & strSymbol1Letter
+ End If
+
+ If blnIncludeModificationSymbols Then
+ For intModIndex = 1 To .ModificationIDCount
+ lngError = GetModificationSymbol(.ModificationIDs(intModIndex), strModSymbol, dblModMass, blnIndicatesPhosphorylation, strModSymbolComment)
+ If lngError = 0 Then
+ strSequence = strSequence & strModSymbol
+ Else
+ Debug.Assert False
+ End If
+ Next intModIndex
+ End If
+
+ End With
+
+ If lngIndex <> ResidueCount Then
+ If blnAddSpaceEvery10Residues Then
+ If lngIndex Mod 10 = 0 Then
+ strSequence = strSequence & " "
+ Else
+ strSequence = strSequence & strDashAdd
+ End If
+ Else
+ strSequence = strSequence & strDashAdd
+ End If
+ End If
+
+ Next lngIndex
+
+ If blnIncludeNandCTerminii Then
+ strSequence = mNTerminus.Formula & strDashAdd & strSequence & strDashAdd & mCTerminus.Formula
+ End If
+
+ GetSequence = strSequence
+End Function
+
+Public Function GetSymbolWaterLoss() As String
+ GetSymbolWaterLoss = mWaterLossSymbol
+End Function
+
+Public Function GetSymbolPhosphoLoss() As String
+ GetSymbolPhosphoLoss = mPhosphoLossSymbol
+End Function
+
+Public Function GetSymbolAmmoniaLoss() As String
+ GetSymbolAmmoniaLoss = mAmmoniaLossSymbol
+End Function
+
+Public Function GetTrypticName(ByVal strProteinResidues As String, ByVal strPeptideResidues As String, Optional ByRef lngReturnResidueStart As Long = 0, Optional ByRef lngReturnResidueEnd As Long = 0, Optional ByVal blnICR2LSCompatible As Boolean = False, Optional ByVal strRuleResidues As String = TRYPTIC_RULE_RESIDUES, Optional ByVal strExceptionResidues As String = TRYPTIC_EXCEPTION_RESIDUES, Optional ByVal strTerminiiSymbol As String = TERMINII_SYMBOL, Optional ByVal blnIgnoreCase As Boolean = True, Optional ByVal lngProteinSearchStartLoc As Long = 1) As String
+ ' Examines strPeptideResidues to see where they exist in strProteinResidues
+ ' Constructs a name string based on their position and based on whether the fragment is truly tryptic
+ ' In addition, returns the position of the first and last residue in lngReturnResidueStart and lngReturnResidueEnd
+ ' The tryptic name in the following format
+ ' t1 indicates tryptic peptide 1
+ ' t2 represents tryptic peptide 2, etc.
+ ' t1.2 indicates tryptic peptide 1, plus one more tryptic peptide, i.e. t1 and t2
+ ' t5.2 indicates tryptic peptide 5, plus one more tryptic peptide, i.e. t5 and t6
+ ' t5.3 indicates tryptic peptide 5, plus two more tryptic peptides, i.e. t5, t6, and t7
+ ' 40.52 means that the residues are not tryptic, and simply range from residue 40 to 52
+ ' If the peptide residues are not present in strProteinResidues, then returns ""
+ ' Since a peptide can occur multiple times in a protein, one can set lngProteinSearchStartLoc to a value larger than 1 to ignore previous hits
+
+ ' If blnICR2LSCompatible is True, then the values returned when a peptide is not tryptic are modified to
+ ' range from the starting residue, to the ending residue +1
+ ' lngReturnResidueEnd is always equal to the position of the final residue, regardless of blnICR2LSCompatible
+
+ ' For example, if strProteinResidues = "IGKANR"
+ ' Then when strPeptideResidues = "IGK", the TrypticName is t1
+ ' Then when strPeptideResidues = "ANR", the TrypticName is t2
+ ' Then when strPeptideResidues = "IGKANR", the TrypticName is t1.2
+ ' Then when strPeptideResidues = "IG", the TrypticName is 1.2
+ ' Then when strPeptideResidues = "KANR", the TrypticName is 3.6
+ ' Then when strPeptideResidues = "NR", the TrypticName is 5.6
+
+ ' However, if blnICR2LSCompatible = True, then the last three are changed to:
+ ' Then when strPeptideResidues = "IG", the TrypticName is 1.3
+ ' Then when strPeptideResidues = "KANR", the TrypticName is 3.7
+ ' Then when strPeptideResidues = "NR", the TrypticName is 5.7
+
+ Dim intStartLoc As Integer, intEndLoc As Integer
+ Dim strTrypticName As String
+ Dim strPrefix As String, strSuffix As String
+ Dim strResidueFollowingSearchResidues As String
+ Dim blnMatchesCleavageRule As Boolean
+
+ Dim intTrypticResidueNumber As Integer
+ Dim intRuleResidueMatchCount As Integer
+ Dim lngRuleResidueLoc As Long
+ Dim strProteinResiduesBeforeStartLoc As String
+ Dim lngPeptideResiduesLength As Long
+
+ If blnIgnoreCase Then
+ strProteinResidues = UCase(strProteinResidues)
+ strPeptideResidues = UCase(strPeptideResidues)
+ End If
+
+ If lngProteinSearchStartLoc <= 1 Then
+ intStartLoc = InStr(strProteinResidues, strPeptideResidues)
+ Else
+ intStartLoc = InStr(Mid(strProteinResidues, lngProteinSearchStartLoc), strPeptideResidues)
+ If intStartLoc > 0 Then
+ intStartLoc = intStartLoc + lngProteinSearchStartLoc - 1
+ End If
+ End If
+
+ lngPeptideResiduesLength = Len(strPeptideResidues)
+
+ If intStartLoc > 0 And Len(strProteinResidues) > 0 And lngPeptideResiduesLength > 0 Then
+ intEndLoc = intStartLoc + lngPeptideResiduesLength - 1
+
+ ' Determine if the residue is tryptic
+ ' Use CheckSequenceAgainstCleavageRule() for this
+ If intStartLoc > 1 Then
+ strPrefix = Mid(strProteinResidues, intStartLoc - 1, 1)
+ Else
+ strPrefix = strTerminiiSymbol
+ End If
+
+ If intEndLoc = Len(strProteinResidues) Then
+ strSuffix = strTerminiiSymbol
+ Else
+ strSuffix = Mid(strProteinResidues, intEndLoc + 1, 1)
+ End If
+
+ blnMatchesCleavageRule = CheckSequenceAgainstCleavageRule(strPrefix & "." & strPeptideResidues & "." & strSuffix, strRuleResidues, strExceptionResidues, False, ".", strTerminiiSymbol, blnIgnoreCase)
+
+ If blnMatchesCleavageRule Then
+ ' Construct strTrypticName
+
+ ' Determine which tryptic residue strPeptideResidues is
+ If intStartLoc = 1 Then
+ intTrypticResidueNumber = 1
+ Else
+ intTrypticResidueNumber = 0
+ strProteinResiduesBeforeStartLoc = Left(strProteinResidues, intStartLoc - 1)
+ strResidueFollowingSearchResidues = Left(strPeptideResidues, 1)
+ intTrypticResidueNumber = 0
+ lngRuleResidueLoc = 0
+ Do
+ lngRuleResidueLoc = GetTrypticNameFindNextCleavageLoc(strProteinResiduesBeforeStartLoc, strResidueFollowingSearchResidues, lngRuleResidueLoc + 1, strRuleResidues, strExceptionResidues, strTerminiiSymbol)
+ If lngRuleResidueLoc > 0 Then
+ intTrypticResidueNumber = intTrypticResidueNumber + 1
+ End If
+ Loop While lngRuleResidueLoc > 0 And lngRuleResidueLoc + 1 < intStartLoc
+ intTrypticResidueNumber = intTrypticResidueNumber + 1
+ End If
+
+ ' Determine number of K or R residues in strPeptideResidues
+ ' Ignore K or R residues followed by Proline
+ intRuleResidueMatchCount = 0
+ lngRuleResidueLoc = 0
+ Do
+ lngRuleResidueLoc = GetTrypticNameFindNextCleavageLoc(strPeptideResidues, strSuffix, lngRuleResidueLoc + 1, strRuleResidues, strExceptionResidues, strTerminiiSymbol)
+ If lngRuleResidueLoc > 0 Then
+ intRuleResidueMatchCount = intRuleResidueMatchCount + 1
+ End If
+ Loop While lngRuleResidueLoc > 0 And lngRuleResidueLoc < lngPeptideResiduesLength
+
+ strTrypticName = "t" & Trim(Str(intTrypticResidueNumber))
+ If intRuleResidueMatchCount > 1 Then
+ strTrypticName = strTrypticName & "." & Trim(Str((intRuleResidueMatchCount)))
+ End If
+ Else
+ If blnICR2LSCompatible Then
+ strTrypticName = Trim(Str(intStartLoc)) & "." & Trim(Str(intEndLoc + 1))
+ Else
+ strTrypticName = Trim(Str(intStartLoc)) & "." & Trim(Str(intEndLoc))
+ End If
+ End If
+
+ lngReturnResidueStart = intStartLoc
+ lngReturnResidueEnd = intEndLoc
+ GetTrypticName = strTrypticName
+ Else
+ ' Residues not found
+ lngReturnResidueStart = 0
+ lngReturnResidueEnd = 0
+ GetTrypticName = ""
+ End If
+
+End Function
+
+Public Function GetTrypticNameMultipleMatches(ByVal strProteinResidues As String, ByVal strPeptideResidues As String, Optional ByRef lngReturnMatchCount As Long, Optional ByRef lngReturnResidueStart As Long = 0, Optional ByRef lngReturnResidueEnd As Long = 0, Optional ByVal blnICR2LSCompatible As Boolean, Optional ByVal strRuleResidues As String = TRYPTIC_RULE_RESIDUES, Optional ByVal strExceptionResidues As String = TRYPTIC_EXCEPTION_RESIDUES, Optional ByVal strTerminiiSymbol As String = TERMINII_SYMBOL, Optional ByVal blnIgnoreCase As Boolean = True, Optional ByVal lngProteinSearchStartLoc As Long = 1, Optional ByVal strListDelimeter As String = ", ") As String
+ ' Examines strPeptideResidues to see where they exist in strProteinResidues
+ ' Looks for all possible matches, returning them as a comma separated list
+ ' Returns the number of matches in lngReturnMatchCount
+ ' lngReturnResidueStart contains the residue number of the start of the first match
+ ' lngReturnResidueEnd contains the residue number of the end of the last match
+
+ ' See GetTrypticName for additional information
+
+ Dim strNameList As String, strCurrentName As String
+ Dim lngCurrentSearchLoc As Long
+ Dim lngCurrentResidueStart As Long, lngCurrentResidueEnd As Long
+
+ lngCurrentSearchLoc = lngProteinSearchStartLoc
+ lngReturnMatchCount = 0
+ Do
+ strCurrentName = GetTrypticName(strProteinResidues, strPeptideResidues, lngCurrentResidueStart, lngCurrentResidueEnd, blnICR2LSCompatible, strRuleResidues, strExceptionResidues, strTerminiiSymbol, blnIgnoreCase, lngCurrentSearchLoc)
+
+ If Len(strCurrentName) > 0 Then
+ If Len(strNameList) > 0 Then
+ strNameList = strNameList & strListDelimeter
+ End If
+ strNameList = strNameList & strCurrentName
+ lngCurrentSearchLoc = lngCurrentResidueEnd + 1
+ lngReturnMatchCount = lngReturnMatchCount + 1
+
+ If lngReturnMatchCount = 1 Then
+ lngReturnResidueStart = lngCurrentResidueStart
+ End If
+ lngReturnResidueEnd = lngCurrentResidueEnd
+
+ If lngCurrentSearchLoc > Len(strProteinResidues) Then Exit Do
+ Else
+ Exit Do
+ End If
+ Loop
+
+ GetTrypticNameMultipleMatches = strNameList
+
+End Function
+
+Private Function GetTrypticNameFindNextCleavageLoc(strSearchResidues As String, strResidueFollowingSearchResidues As String, ByVal lngStartChar As Long, Optional ByVal strSearchChars As String = TRYPTIC_RULE_RESIDUES, Optional ByVal strExceptionSuffixResidues As String = TRYPTIC_EXCEPTION_RESIDUES, Optional ByVal strTerminiiSymbol As String = TERMINII_SYMBOL) As Long
+ ' Finds the location of the next strSearchChar in strSearchResidues (K or R by default)
+ ' Assumes strSearchResidues are already upper case
+ ' Examines the residue following the matched residue
+ ' If it matches one of the characters in strExceptionSuffixResidues, then the match is not counted
+ ' Note that strResidueFollowingSearchResidues is necessary in case the potential cleavage residue is the final residue in strSearchResidues
+ ' We need to know the next residue to determine if it matches an exception residue
+ ' For example, if strSearchResidues = "IGASGEHIFIIGVDKPNR"
+ ' and the protein it is part of is: TNSANFRIGASGEHIFIIGVDKPNRQPDS
+ ' and strSearchChars = "KR while strExceptionSuffixResidues = "P"
+ ' Then the K in IGASGEHIFIIGVDKPNR is ignored because the following residue is P,
+ ' while the R in IGASGEHIFIIGVDKPNR is OK because strResidueFollowingSearchResidues is Q
+ ' It is the calling function's responsibility to assign the correct residue to strResidueFollowingSearchResidues
+ ' If no match is found, but strResidueFollowingSearchResidues is "-", then the cleavage location returned is Len(strSearchResidues) + 1
+
+ Dim intCharLocInSearchChars As Integer
+ Dim lngCharLoc As Long, lngMinCharLoc As Long
+ Dim intExceptionSuffixResidueCount As Integer
+ Dim intCharLocInExceptionChars As Integer
+ Dim strResidueFollowingCleavageResidue As String
+ Dim lngExceptionCharLocInSearchResidues As Long, lngCharLocViaRecursiveSearch As Long
+
+ intExceptionSuffixResidueCount = Len(strExceptionSuffixResidues)
+
+ lngMinCharLoc = -1
+ For intCharLocInSearchChars = 1 To Len(strSearchChars)
+ lngCharLoc = InStr(Mid(strSearchResidues, lngStartChar), Mid(strSearchChars, intCharLocInSearchChars, 1))
+
+ If lngCharLoc > 0 Then
+ lngCharLoc = lngCharLoc + lngStartChar - 1
+
+ If intExceptionSuffixResidueCount > 0 Then
+ ' Make sure strSuffixResidue does not match strExceptionSuffixResidues
+ If lngCharLoc < Len(strSearchResidues) Then
+ lngExceptionCharLocInSearchResidues = lngCharLoc + 1
+ strResidueFollowingCleavageResidue = Mid(strSearchResidues, lngExceptionCharLocInSearchResidues, 1)
+ Else
+ ' Matched the last residue in strSearchResidues
+ lngExceptionCharLocInSearchResidues = Len(strSearchResidues) + 1
+ strResidueFollowingCleavageResidue = strResidueFollowingSearchResidues
+ End If
+
+ For intCharLocInExceptionChars = 1 To intExceptionSuffixResidueCount
+ If strResidueFollowingCleavageResidue = Mid(strExceptionSuffixResidues, intCharLocInExceptionChars, 1) Then
+ ' Exception char is the following character; can't count this as the cleavage point
+
+ If lngExceptionCharLocInSearchResidues < Len(strSearchResidues) Then
+ ' Recursively call this function to find the next cleavage position, using an updated lngStartChar position
+ lngCharLocViaRecursiveSearch = GetTrypticNameFindNextCleavageLoc(strSearchResidues, strResidueFollowingSearchResidues, lngExceptionCharLocInSearchResidues, strSearchChars, strExceptionSuffixResidues, strTerminiiSymbol)
+
+ If lngCharLocViaRecursiveSearch > 0 Then
+ ' Found a residue further along that is a valid cleavage point
+ lngCharLoc = lngCharLocViaRecursiveSearch
+ Else
+ lngCharLoc = 0
+ End If
+ Else
+ lngCharLoc = 0
+ End If
+ Exit For
+ End If
+ Next intCharLocInExceptionChars
+ End If
+ End If
+
+ If lngCharLoc > 0 Then
+ If lngMinCharLoc < 0 Then
+ lngMinCharLoc = lngCharLoc
+ Else
+ If lngCharLoc < lngMinCharLoc Then
+ lngMinCharLoc = lngCharLoc
+ End If
+ End If
+ End If
+ Next intCharLocInSearchChars
+
+ If lngMinCharLoc < 0 And strResidueFollowingSearchResidues = strTerminiiSymbol Then
+ lngMinCharLoc = Len(strSearchResidues) + 1
+ End If
+
+ If lngMinCharLoc < 0 Then
+ GetTrypticNameFindNextCleavageLoc = 0
+ Else
+ GetTrypticNameFindNextCleavageLoc = lngMinCharLoc
+ End If
+
+End Function
+
+Public Function GetTrypticPeptideNext(ByVal strProteinResidues As String, ByVal lngSearchStartLoc As Long, Optional ByRef lngReturnResidueStart As Long, Optional ByRef lngReturnResidueEnd As Long, Optional ByVal strRuleResidues As String = TRYPTIC_RULE_RESIDUES, Optional ByVal strExceptionResidues As String = TRYPTIC_EXCEPTION_RESIDUES, Optional ByVal strTerminiiSymbol As String = TERMINII_SYMBOL) As String
+ ' Returns the next tryptic peptide in strProteinResidues, starting the search as lngSearchStartLoc
+ ' Useful when obtaining all of the tryptic peptides for a protein, since this function will operate
+ ' much faster than repeatedly calling GetTrypticPeptideByFragmentNumber()
+
+ ' Returns the position of the start and end residues using lngReturnResidueStart and lngReturnResidueEnd
+
+ Dim lngRuleResidueLoc As Long
+ Dim lngProteinResiduesLength As Long
+
+ If lngSearchStartLoc < 1 Then lngSearchStartLoc = 1
+
+ lngProteinResiduesLength = Len(strProteinResidues)
+ If lngSearchStartLoc > lngProteinResiduesLength Then
+ GetTrypticPeptideNext = ""
+ Exit Function
+ End If
+
+ lngRuleResidueLoc = GetTrypticNameFindNextCleavageLoc(strProteinResidues, strTerminiiSymbol, lngSearchStartLoc, strRuleResidues, strExceptionResidues, strTerminiiSymbol)
+ If lngRuleResidueLoc > 0 Then
+ lngReturnResidueStart = lngSearchStartLoc
+ If lngRuleResidueLoc > lngProteinResiduesLength Then
+ lngReturnResidueEnd = lngProteinResiduesLength
+ Else
+ lngReturnResidueEnd = lngRuleResidueLoc
+ End If
+ GetTrypticPeptideNext = Mid(strProteinResidues, lngReturnResidueStart, lngReturnResidueEnd - lngReturnResidueStart + 1)
+ Else
+ lngReturnResidueStart = 1
+ lngReturnResidueEnd = lngProteinResiduesLength
+ GetTrypticPeptideNext = strProteinResidues
+ End If
+
+End Function
+
+Public Function GetTrypticPeptideByFragmentNumber(ByVal strProteinResidues As String, ByVal intDesiredPeptideNumber As Integer, Optional ByRef lngReturnResidueStart As Long, Optional ByRef lngReturnResidueEnd As Long, Optional ByVal strRuleResidues As String = TRYPTIC_RULE_RESIDUES, Optional ByVal strExceptionResidues As String = TRYPTIC_EXCEPTION_RESIDUES, Optional ByVal strTerminiiSymbol As String = TERMINII_SYMBOL, Optional ByVal blnIgnoreCase As Boolean = True) As String
+ ' Returns the desired tryptic peptide from strProteinResidues
+ ' For example, if strProteinResidues = "IGKANRMTFGL" then
+ ' when intDesiredPeptideNumber = 1, returns "IGK"
+ ' when intDesiredPeptideNumber = 2, returns "ANR"
+ ' when intDesiredPeptideNumber = 3, returns "MTFGL"
+
+ ' Optionally, returns the position of the start and end residues
+ ' using lngReturnResidueStart and lngReturnResidueEnd
+
+
+ Dim lngStartLoc As Long, lngRuleResidueLoc As Long
+ Dim lngPrevStartLoc As Long
+ Dim lngProteinResiduesLength As Long
+ Dim intCurrentTrypticPeptideNumber As Integer
+
+ Dim strMatchingFragment As String
+
+ If intDesiredPeptideNumber < 1 Then
+ GetTrypticPeptideByFragmentNumber = ""
+ Exit Function
+ End If
+
+ If blnIgnoreCase Then
+ strProteinResidues = UCase(strProteinResidues)
+ End If
+ lngProteinResiduesLength = Len(strProteinResidues)
+
+ lngStartLoc = 1
+ lngRuleResidueLoc = 0
+ intCurrentTrypticPeptideNumber = 0
+ Do
+ lngRuleResidueLoc = GetTrypticNameFindNextCleavageLoc(strProteinResidues, strTerminiiSymbol, lngStartLoc, strRuleResidues, strExceptionResidues, strTerminiiSymbol)
+ If lngRuleResidueLoc > 0 Then
+ intCurrentTrypticPeptideNumber = intCurrentTrypticPeptideNumber + 1
+ lngPrevStartLoc = lngStartLoc
+ lngStartLoc = lngRuleResidueLoc + 1
+
+ If lngPrevStartLoc > lngProteinResiduesLength Then
+ ' User requested a peptide number that doesn't exist
+ GetTrypticPeptideByFragmentNumber = ""
+ Exit Function
+ End If
+ Else
+ ' I don't think I'll ever reach this code
+ Debug.Assert False
+ Exit Do
+ End If
+ Loop While intCurrentTrypticPeptideNumber < intDesiredPeptideNumber
+
+ strMatchingFragment = ""
+ If intCurrentTrypticPeptideNumber > 0 And lngPrevStartLoc > 0 Then
+ If lngPrevStartLoc > Len(strProteinResidues) Then
+ ' User requested a peptide number that is too high
+ lngReturnResidueStart = 0
+ lngReturnResidueEnd = 0
+ strMatchingFragment = ""
+ Else
+ ' Match found, find the extent of this peptide
+ lngReturnResidueStart = lngPrevStartLoc
+ If lngRuleResidueLoc > lngProteinResiduesLength Then
+ lngReturnResidueEnd = lngProteinResiduesLength
+ Else
+ lngReturnResidueEnd = lngRuleResidueLoc
+ End If
+ strMatchingFragment = Mid(strProteinResidues, lngPrevStartLoc, lngRuleResidueLoc - lngPrevStartLoc + 1)
+ End If
+ Else
+ lngReturnResidueStart = 1
+ lngReturnResidueEnd = lngProteinResiduesLength
+ strMatchingFragment = strProteinResidues
+ End If
+
+ GetTrypticPeptideByFragmentNumber = strMatchingFragment
+
+End Function
+
+Public Function CheckSequenceAgainstCleavageRule(ByVal strSequence As String, ByVal strRuleResidues As String, ByVal strExceptionSuffixResidues As String, ByVal blnAllowPartialCleavage As Boolean, Optional ByVal strSeparationChar As String = ".", Optional ByVal strTerminiiSymbol As String = TERMINII_SYMBOL, Optional ByVal blnIgnoreCase As Boolean = True, Optional ByRef intRuleMatchCount As Integer) As Boolean
+ ' Checks strSequence to see if it matches the cleavage rule
+ ' Returns True if valid, False if invalid
+ ' Returns True if doesn't contain any periods, and thus, can't be examined
+ ' The ByRef variable intRuleMatchCount can be used to retrieve the number of ends that matched the rule (0, 1, or 2); terminii are counted as rule matches
+
+ ' The residues in strRuleResidues specify the cleavage rule
+ ' The peptide must end in one of the residues, or in -
+ ' The preceding residue must be one of the residues or be -
+ ' EXCEPTION: if blnAllowPartialCleavage = True then the rules need only apply to one end
+ ' Finally, the suffix residue cannot match any of the residues in strExceptionSuffixResidues
+
+ ' For example, if strRuleResidues = "KR" and strExceptionSuffixResidues = "P"
+ ' Then if strSequence = "R.AEQDDLANYGPGNGVLPSAGSSISMEK.L" then blnMatchesCleavageRule = True
+ ' However, if strSequence = "R.IGASGEHIFIIGVDK.P" then blnMatchesCleavageRule = False since strSuffix = "P"
+ ' Finally, if strSequence = "R.IGASGEHIFIIGVDKPNR.Q" then blnMatchesCleavageRule = True since K is ignored, but the final R.Q is valid
+
+ Dim strSequenceStart As String, strSequenceEnd As String
+ Dim strPrefix As String, strSuffix As String
+ Dim blnMatchesCleavageRule As Boolean, blnSkipThisEnd As Boolean
+ Dim strTestResidue As String
+ Dim intEndToCheck As Integer
+
+ ' Need to reset this to zero since passed ByRef
+ intRuleMatchCount = 0
+
+ ' First, make sure the sequence is in the form A.BCDEFG.H or A.BCDEFG or BCDEFG.H
+ ' If it isn't, then we can't check it (we'll return true)
+
+ If Len(strRuleResidues) = 0 Then
+ ' No rules
+ CheckSequenceAgainstCleavageRule = True
+ Exit Function
+ End If
+
+ If InStr(strSequence, strSeparationChar) = 0 Then
+ ' No periods, can't check
+ Debug.Assert False
+ CheckSequenceAgainstCleavageRule = True
+ Exit Function
+ End If
+
+ If blnIgnoreCase Then
+ strSequence = UCase(strSequence)
+ End If
+
+ ' Find the prefix residue and starting residue
+ If Mid(strSequence, 2, 1) = strSeparationChar Then
+ strPrefix = Left(strSequence, 1)
+ strSequenceStart = Mid(strSequence, 3, 1)
+ Else
+ strSequenceStart = Left(strSequence, 1)
+ End If
+
+ ' Find the suffix residue and the ending residue
+ If Mid(strSequence, Len(strSequence) - 1, 1) = strSeparationChar Then
+ strSuffix = Right(strSequence, 1)
+ strSequenceEnd = Mid(strSequence, Len(strSequence) - 2, 1)
+ Else
+ strSequenceEnd = Right(strSequence, 1)
+ End If
+
+ If strRuleResidues = strTerminiiSymbol Then
+ ' Peptide database rules
+ ' See if prefix and suffix are "" or are strTerminiiSymbol
+ If (strPrefix = strTerminiiSymbol And strSuffix = strTerminiiSymbol) Or _
+ (strPrefix = "" And strSuffix = "") Then
+ intRuleMatchCount = 2
+ blnMatchesCleavageRule = True
+ Else
+ blnMatchesCleavageRule = False
+ End If
+ Else
+ If blnIgnoreCase Then
+ strRuleResidues = UCase(strRuleResidues)
+ End If
+
+ ' Test each character in strRuleResidues against both strPrefix and strSequenceEnd
+ ' Make sure strSuffix does not match strExceptionSuffixResidues
+ For intEndToCheck = 0 To 1
+ blnSkipThisEnd = False
+ If intEndToCheck = 0 Then
+ strTestResidue = strPrefix
+ If strPrefix = strTerminiiSymbol Then
+ intRuleMatchCount = intRuleMatchCount + 1
+ blnSkipThisEnd = True
+ Else
+ ' See if strSequenceStart matches one of the exception residues
+ ' If it does, make sure strPrefix does not match one of the rule residues
+ If CheckSequenceAgainstCleavageRuleMatchTestResidue(strSequenceStart, strExceptionSuffixResidues) Then
+ ' Match found
+ ' Make sure strPrefix does not match one of the rule residues
+ If CheckSequenceAgainstCleavageRuleMatchTestResidue(strPrefix, strRuleResidues) Then
+ ' Match found; thus does not match cleavage rule
+ blnSkipThisEnd = True
+ End If
+ End If
+ End If
+ Else
+ strTestResidue = strSequenceEnd
+ If strSuffix = strTerminiiSymbol Then
+ intRuleMatchCount = intRuleMatchCount + 1
+ blnSkipThisEnd = True
+ Else
+ ' Make sure strSuffix does not match strExceptionSuffixResidues
+ If CheckSequenceAgainstCleavageRuleMatchTestResidue(strSuffix, strExceptionSuffixResidues) Then
+ ' Match found; thus does not match cleavage rule
+ blnSkipThisEnd = True
+ End If
+ End If
+ End If
+
+ If Not blnSkipThisEnd Then
+ If CheckSequenceAgainstCleavageRuleMatchTestResidue(strTestResidue, strRuleResidues) Then
+ intRuleMatchCount = intRuleMatchCount + 1
+ End If
+ End If
+ Next intEndToCheck
+
+ If intRuleMatchCount = 2 Then
+ blnMatchesCleavageRule = True
+ ElseIf intRuleMatchCount >= 1 And blnAllowPartialCleavage Then
+ blnMatchesCleavageRule = True
+ End If
+ End If
+
+ CheckSequenceAgainstCleavageRule = blnMatchesCleavageRule
+
+End Function
+
+Private Function CheckSequenceAgainstCleavageRuleMatchTestResidue(strTestResidue As String, strRuleResidues As String) As Boolean
+ ' Checks to see if strTestResidue matches one of the residues in strRuleResidues
+ ' Used to test by Rule Residues and Exception Residues
+
+ Dim intCharLocInRuleResidues As Integer
+ Dim strCompareResidue As String
+ Dim blnMatchFound As Boolean
+
+ For intCharLocInRuleResidues = 1 To Len(strRuleResidues)
+ strCompareResidue = Trim(Mid(strRuleResidues, intCharLocInRuleResidues, 1))
+ If Len(strCompareResidue) > 0 Then
+ If strTestResidue = strCompareResidue Then
+ blnMatchFound = True
+ Exit For
+ End If
+ End If
+ Next intCharLocInRuleResidues
+
+ CheckSequenceAgainstCleavageRuleMatchTestResidue = blnMatchFound
+
+End Function
+
+Public Function ComputeImmoniumMass(dblResidueMass As Double) As Double
+ ComputeImmoniumMass = dblResidueMass - dblImmoniumMassDifference
+End Function
+
+Public Function LookupIonTypeString(eIonType As itIonTypeConstants) As String
+
+ Select Case eIonType
+ Case itAIon: LookupIonTypeString = "a"
+ Case itBIon: LookupIonTypeString = "b"
+ Case itYIon: LookupIonTypeString = "y"
+ Case Else: LookupIonTypeString = ""
+ End Select
+
+End Function
+
+Public Function RemoveAllResidues() As Long
+ ' Removes all the residues
+ ' Returns 0 on success, 1 on failure
+
+ ReserveMemoryForResidues 50, False
+ ResidueCount = 0
+ mTotalMass = 0
+
+ RemoveAllResidues = 0
+End Function
+
+Public Function RemoveAllModificationSymbols() As Long
+ ' Removes all possible Modification Symbols
+ ' Returns 0 on success, 1 on failure
+ ' Removing all modifications will invalidate any modifications present in a sequence
+
+ ReserveMemoryForModifications 10, False
+ ModificationSymbolCount = 0
+
+ RemoveAllModificationSymbols = 0
+End Function
+
+Private Function RemoveLeadingH(ByRef strWorkingSequence As String) As Boolean
+ ' Returns True if a leading H is removed
+ Dim lngAbbrevID As Long
+ Dim blnHRemoved As Boolean
+
+ blnHRemoved = False
+ If UCase(Left(strWorkingSequence, 1)) = "H" And Len(strWorkingSequence) >= 4 Then
+ ' If next character is not a character, then remove the H
+ If Not IsCharacter(Mid(strWorkingSequence, 2, 1)) Then
+ strWorkingSequence = Mid(strWorkingSequence, 3)
+ blnHRemoved = True
+ Else
+ ' Otherwise, see if next three characters are letters
+ If IsCharacter(Mid(strWorkingSequence, 2, 1)) And _
+ IsCharacter(Mid(strWorkingSequence, 3, 1)) And _
+ IsCharacter(Mid(strWorkingSequence, 4, 1)) Then
+ ' Formula starts with 4 characters and the first is H, see if the first 3 characters are a valid amino acid code
+ lngAbbrevID = GetAbbreviationIDInternal(Left(strWorkingSequence, 3), True)
+
+ If lngAbbrevID <= 0 Then
+ ' Doesn't start with a valid amino acid 3 letter abbreviation, so remove the initial H
+ strWorkingSequence = Mid(strWorkingSequence, 2)
+ blnHRemoved = True
+ End If
+ End If
+ End If
+ End If
+
+ RemoveLeadingH = blnHRemoved
+End Function
+
+Private Function RemoveTrailingOH(ByRef strWorkingSequence As String) As Boolean
+ ' Returns True if a trailing OH is removed
+ Dim lngAbbrevID As Long
+ Dim blnOHRemoved As Boolean
+ Dim lngStringLength As Long
+
+ blnOHRemoved = False
+ lngStringLength = Len(strWorkingSequence)
+ If UCase(Right(strWorkingSequence, 2)) = "OH" And lngStringLength >= 5 Then
+ ' If previous character is not a character, then remove the OH
+ If Not IsCharacter(Mid(strWorkingSequence, lngStringLength - 2, 1)) Then
+ strWorkingSequence = Left(strWorkingSequence, lngStringLength - 3)
+ blnOHRemoved = True
+ Else
+ ' Otherwise, see if previous three characters are letters
+ If IsCharacter(Mid(strWorkingSequence, lngStringLength - 2, 1)) Then
+ ' Formula ends with 3 characters and the last two are OH, see if the last 3 characters are a valid amino acid code
+ lngAbbrevID = GetAbbreviationIDInternal(Mid(strWorkingSequence, lngStringLength - 2, 3), True)
+
+ If lngAbbrevID <= 0 Then
+ ' Doesn't end with a valid amino acid 3 letter abbreviation, so remove the trailing OH
+ strWorkingSequence = Left(strWorkingSequence, lngStringLength - 2)
+ blnOHRemoved = True
+ End If
+ End If
+ End If
+ End If
+
+ RemoveTrailingOH = blnOHRemoved
+
+End Function
+
+Public Function RemoveModification(strModSymbol As String) As Long
+ ' Returns 0 if found and removed; 1 if error
+
+ Dim lngIndex As Long
+ Dim blnRemoved As Boolean
+
+ For lngIndex = 1 To ModificationSymbolCount
+ If ModificationSymbols(lngIndex).Symbol = strModSymbol Then
+ RemoveModificationByID lngIndex
+ blnRemoved = True
+ End If
+ Next lngIndex
+
+ If blnRemoved Then
+ RemoveModification = 0
+ Else
+ RemoveModification = 1
+ End If
+End Function
+
+Public Function RemoveModificationByID(ByVal lngModificationID As Long) As Long
+ ' Returns 0 if found and removed; 1 if error
+
+ Dim lngIndex As Long
+ Dim blnRemoved As Boolean
+
+ If lngModificationID >= 1 And lngModificationID <= ModificationSymbolCount Then
+ For lngIndex = lngModificationID To ModificationSymbolCount - 1
+ ModificationSymbols(lngIndex) = ModificationSymbols(lngIndex + 1)
+ Next lngIndex
+ ModificationSymbolCount = ModificationSymbolCount - 1
+ blnRemoved = True
+ Else
+ blnRemoved = False
+ End If
+
+ If blnRemoved Then
+ RemoveModificationByID = 0
+ Else
+ RemoveModificationByID = 1
+ End If
+
+End Function
+
+Public Function RemoveResidue(lngResidueNumber As Long) As Long
+ ' Returns 0 if found and removed; 1 if error
+
+ Dim lngIndex As Long
+
+ If lngResidueNumber >= 1 And lngResidueNumber <= ResidueCount Then
+ For lngIndex = lngResidueNumber To ResidueCount - 1
+ Residues(lngIndex) = Residues(lngIndex + 1)
+ Next lngIndex
+ ResidueCount = ResidueCount - 1
+ RemoveResidue = 0
+ Else
+ RemoveResidue = 1
+ End If
+
+End Function
+
+Private Sub ReserveMemoryForResidues(lngNewResidueCount As Long, blnPreserveContents As Boolean)
+ ' Only reserves the memory if necessary
+ ' Thus, do not use this sub to clear Residues()
+
+ If lngNewResidueCount > ResidueCountDimmed Then
+ ResidueCountDimmed = lngNewResidueCount + RESIDUE_DIM_CHUNK
+ If blnPreserveContents Then
+ ReDim Preserve Residues(ResidueCountDimmed)
+ Else
+ ReDim Residues(ResidueCountDimmed)
+ End If
+ End If
+End Sub
+
+Private Sub ReserveMemoryForModifications(lngNewModificationCount As Long, blnPreserveContents As Boolean)
+
+ If lngNewModificationCount > ModificationSymbolCountDimmed Then
+ ModificationSymbolCountDimmed = lngNewModificationCount + 10
+ If blnPreserveContents Then
+ ReDim Preserve ModificationSymbols(ModificationSymbolCountDimmed)
+ Else
+ ReDim ModificationSymbols(ModificationSymbolCountDimmed)
+ End If
+ End If
+End Sub
+
+Public Function SetCTerminus(strFormula As String, Optional strFollowingResidue As String = "", Optional blnUse3LetterCode As Boolean = True) As Long
+ ' Returns 0 if success; 1 if error
+
+ ' Typical N terminus mods
+ ' Free Acid = OH
+ ' Amide = NH2
+
+ With mCTerminus
+ .Formula = strFormula
+ .Mass = ComputeFormulaWeight(.Formula)
+ If .Mass < 0 Then
+ .Mass = 0
+ SetCTerminus = 1
+ Else
+ SetCTerminus = 0
+ End If
+ .PrecedingResidue = FillResidueStructureUsingSymbol("")
+ .FollowingResidue = FillResidueStructureUsingSymbol(strFollowingResidue, blnUse3LetterCode)
+ End With
+
+ UpdateResidueMasses
+End Function
+
+Public Function SetCTerminusGroup(eCTerminusGroup As ctgCTerminusGroupConstants, Optional strFollowingResidue As String = "", Optional blnUse3LetterCode As Boolean = True) As Long
+ ' Returns 0 if success; 1 if error
+ Dim lngError As Long
+
+ lngError = 0
+ Select Case eCTerminusGroup
+ Case ctgHydroxyl: lngError = SetCTerminus("OH", strFollowingResidue, blnUse3LetterCode)
+ Case ctgAmide: lngError = SetCTerminus("NH2", strFollowingResidue, blnUse3LetterCode)
+ Case ctgNone: lngError = SetCTerminus("", strFollowingResidue, blnUse3LetterCode)
+ Case Else: lngError = 1
+ End Select
+
+ SetCTerminusGroup = lngError
+
+End Function
+
+Public Sub SetDefaultModificationSymbols()
+
+ On Error GoTo SetDefaultModificationSymbolsErrorHandler
+
+ RemoveAllModificationSymbols
+
+ ' Add the symbol for phosphorylation
+ SetModificationSymbol "*", dblPhosphorylationMass, True, "Phosphorylation [HPO3]"
+
+ ' Define the other default modifications
+ ' Valid Mod Symbols are ! # $ % & ' * + ? ^ _ ` ~
+
+ SetModificationSymbol "+", 14.01565, False, "Methylation [CH2]"
+ SetModificationSymbol "@", 15.99492, False, "Oxidation [O]"
+ SetModificationSymbol "!", 57.02146, False, "Carbamidomethylation [C2H3NO]"
+ SetModificationSymbol "&", 58.00548, False, "Carboxymethylation [CH2CO2]"
+ SetModificationSymbol "#", 71.03711, False, "Acrylamide [CHCH2CONH2]"
+ SetModificationSymbol "$", 227.127, False, "Cleavable ICAT [(^12C10)H17N3O3]"
+ SetModificationSymbol "%", 236.127, False, "Cleavable ICAT [(^13C9)(^12C)H17N3O3]"
+ SetModificationSymbol "~", 442.225, False, "ICAT D0 [C20H34N4O5S]"
+ SetModificationSymbol "`", 450.274, False, "ICAT D8 [C20H26D8N4O5S]"
+
+ Exit Sub
+
+SetDefaultModificationSymbolsErrorHandler:
+ GeneralErrorHandler "MWPeptideClass.SetDefaultModificationSymbols", Err.Number
+
+End Sub
+
+Public Sub SetDefaultOptions()
+ Dim intIonIndex As Integer
+
+On Error GoTo SetDefaultOptionsErrorHandler
+
+ With mFragSpectrumOptions
+ With .IntensityOptions
+ .IonType(itAIon) = 20
+ .IonType(itBIon) = 100
+ .IonType(itYIon) = 100
+ .BYIonShoulder = 50
+ .NeutralLoss = 20
+ End With
+
+ ' A ions can have ammonia and phosphate loss, but not water loss
+ With .IonTypeOptions(itAIon)
+ .ShowIon = True
+ .NeutralLossAmmonia = True
+ .NeutralLossPhosphate = True
+ .NeutralLossWater = False
+ End With
+
+ For intIonIndex = itBIon To itYIon
+ With .IonTypeOptions(intIonIndex)
+ .ShowIon = True
+ .NeutralLossAmmonia = True
+ .NeutralLossPhosphate = True
+ .NeutralLossWater = True
+ End With
+ Next intIonIndex
+
+ .DoubleChargeIonsShow = True
+ .DoubleChargeIonsThreshold = 800
+ End With
+
+ SetSymbolWaterLoss "-H2O"
+ SetSymbolAmmoniaLoss "-NH3"
+ SetSymbolPhosphoLoss "-H3PO4"
+
+ UpdateStandardMasses
+
+ SetDefaultModificationSymbols
+
+Exit Sub
+
+SetDefaultOptionsErrorHandler:
+ GeneralErrorHandler "MWPeptideClass.SetDefaultOptions", Err.Number
+
+End Sub
+
+Public Sub SetFragmentationSpectrumOptions(udtNewFragSpectrumOptions As udtFragmentationSpectrumOptionsType)
+ mFragSpectrumOptions = udtNewFragSpectrumOptions
+End Sub
+
+Public Function SetModificationSymbol(ByVal strModSymbol As String, ByVal dblModificationMass As Double, blnIndicatesPhosphorylation As Boolean, strComment As String) As Long
+ ' Adds a new modification or updates an existing one (based on strModSymbol)
+ ' Returns 0 if successful, otherwise, returns -1
+
+ Dim strTestChar As String
+ Dim lngIndex As Long, lngIndexToUse As Long, lngErrorID As Long
+
+ lngErrorID = 0
+ If Len(strModSymbol) < 1 Then
+ lngErrorID = -1
+ Else
+ ' Make sure strModSymbol contains no letters, numbers, spaces, dashes, or periods
+ For lngIndex = 1 To Len(strModSymbol)
+ strTestChar = Mid(strModSymbol, lngIndex, 1)
+ If Not IsModSymbolInternal(strTestChar) Then
+ lngErrorID = -1
+ End If
+ Next lngIndex
+
+ If lngErrorID = 0 Then
+ ' See if the modification is alrady present
+ lngIndexToUse = GetModificationSymbolID(strModSymbol)
+
+ If lngIndexToUse = 0 Then
+ ' Need to add the modification
+ ModificationSymbolCount = ModificationSymbolCount + 1
+ lngIndexToUse = ModificationSymbolCount
+ ReserveMemoryForModifications ModificationSymbolCount, True
+ End If
+
+ With ModificationSymbols(lngIndexToUse)
+ .Symbol = strModSymbol
+ .ModificationMass = dblModificationMass
+ .IndicatesPhosphorylation = blnIndicatesPhosphorylation
+ .Comment = strComment
+ End With
+ End If
+ End If
+
+ SetModificationSymbol = lngErrorID
+
+End Function
+
+Public Function SetNTerminus(strFormula As String, Optional strPrecedingResidue As String = "", Optional blnUse3LetterCode As Boolean = True) As Long
+ ' Returns 0 if success; 1 if error
+
+ ' Typical N terminus mods
+ ' Hydrogen = H
+ ' Acetyl = C2OH3
+ ' PyroGlu = C5O2NH6
+ ' Carbamyl = CONH2
+ ' PTC = C7H6NS
+
+ With mNTerminus
+ .Formula = strFormula
+ .Mass = ComputeFormulaWeight(.Formula)
+ If .Mass < 0 Then
+ .Mass = 0
+ SetNTerminus = 1
+ Else
+ SetNTerminus = 0
+ End If
+ .PrecedingResidue = FillResidueStructureUsingSymbol(strPrecedingResidue, blnUse3LetterCode)
+ .FollowingResidue = FillResidueStructureUsingSymbol("")
+ End With
+
+ UpdateResidueMasses
+End Function
+
+Public Function SetNTerminusGroup(eNTerminusGroup As ntgNTerminusGroupConstants, Optional strPrecedingResidue As String = "", Optional blnUse3LetterCode As Boolean = True) As Long
+ ' Returns 0 if success; 1 if error
+ Dim lngError As Long
+
+ lngError = 0
+ Select Case eNTerminusGroup
+ Case ntgHydrogen: lngError = SetNTerminus("H", strPrecedingResidue, blnUse3LetterCode)
+ Case ntgHydrogenPlusProton: lngError = SetNTerminus("HH", strPrecedingResidue, blnUse3LetterCode)
+ Case ntgAcetyl: lngError = SetNTerminus("C2OH3", strPrecedingResidue, blnUse3LetterCode)
+ Case ntgPyroGlu: lngError = SetNTerminus("C5O2NH6", strPrecedingResidue, blnUse3LetterCode)
+ Case ntgCarbamyl: lngError = SetNTerminus("CONH2", strPrecedingResidue, blnUse3LetterCode)
+ Case ntgPTC: lngError = SetNTerminus("C7H6NS", strPrecedingResidue, blnUse3LetterCode)
+ Case ntgNone: lngError = SetNTerminus("", strPrecedingResidue, blnUse3LetterCode)
+ Case Else: lngError = 1
+ End Select
+
+ SetNTerminusGroup = lngError
+
+End Function
+
+Public Function SetResidue(ByVal lngResidueNumber As Long, strSymbol As String, Optional blnIs3LetterCode As Boolean = True, Optional blnPhosphorylated As Boolean = False) As Long
+ ' Sets or adds a residue (must add residues in order)
+ ' Returns the index of the modified residue, or the new index if added
+ ' Returns -1 if a problem
+
+ Dim lngIndexToUse As Long, str3LetterSymbol As String
+
+ If Len(strSymbol) = 0 Then
+ SetResidue = -1
+ Exit Function
+ End If
+
+ If lngResidueNumber > ResidueCount Then
+ ResidueCount = ResidueCount + 1
+ ReserveMemoryForResidues ResidueCount, True
+ lngIndexToUse = ResidueCount
+ Else
+ lngIndexToUse = lngResidueNumber
+ End If
+
+ With Residues(lngIndexToUse)
+ If blnIs3LetterCode Then
+ str3LetterSymbol = strSymbol
+ Else
+ str3LetterSymbol = GetAminoAcidSymbolConversionInternal(strSymbol, True)
+ End If
+
+ If Len(str3LetterSymbol) = 0 Then
+ .Symbol = UNKNOWN_SYMBOL
+ Else
+ .Symbol = str3LetterSymbol
+ End If
+
+ .Phosphorylated = blnPhosphorylated
+ If blnPhosphorylated Then
+ ' Only Ser, Thr, or Tyr should be phosphorylated
+ ' However, if the user sets other residues as phosphorylated, we'll allow that
+ Debug.Assert .Symbol = "Ser" Or .Symbol = "Thr" Or .Symbol = "Tyr"
+ End If
+
+ .ModificationIDCount = 0
+ End With
+
+ UpdateResidueMasses
+
+ SetResidue = lngIndexToUse
+End Function
+
+Public Function SetResidueModifications(ByVal lngResidueNumber As Long, ByVal intModificationCount As Integer, ByRef lngModificationIDsOneBased() As Long) As Long
+ ' Sets the modifications for a specific residue
+ ' Modification Symbols are defined using successive calls to SetModificationSymbol()
+
+ ' Returns 0 if modifications set; returns 1 if an error
+
+ Dim intIndex As Integer, lngNewModID As Long
+
+ If lngResidueNumber >= 1 And lngResidueNumber <= ResidueCount And intModificationCount >= 0 Then
+ With Residues(lngResidueNumber)
+ If intModificationCount > MAX_MODIFICATIONS Then
+ intModificationCount = MAX_MODIFICATIONS
+ End If
+
+ .ModificationIDCount = 0
+ .Phosphorylated = False
+ For intIndex = 1 To intModificationCount
+ lngNewModID = lngModificationIDsOneBased(intIndex)
+ If lngNewModID >= 1 And lngNewModID <= ModificationSymbolCount Then
+ .ModificationIDs(.ModificationIDCount) = lngNewModID
+
+ ' Check for phosphorylation
+ If ModificationSymbols(lngNewModID).IndicatesPhosphorylation Then
+ .Phosphorylated = True
+ End If
+
+ .ModificationIDCount = .ModificationIDCount + 1
+ End If
+ Next intIndex
+
+ End With
+
+ SetResidueModifications = 0
+ Else
+ SetResidueModifications = 1
+ End If
+
+End Function
+
+Public Function SetSequence(ByVal strSequence As String, Optional eNTerminus As ntgNTerminusGroupConstants = ntgHydrogen, Optional eCTerminus As ctgCTerminusGroupConstants = ctgHydroxyl, Optional blnIs3LetterCode As Boolean = True, Optional bln1LetterCheckForPrefixAndSuffixResidues As Boolean = True, Optional bln3LetterCheckForPrefixHandSuffixOH As Boolean = True, Optional blnAddMissingModificationSymbols As Boolean = False) As Long
+ ' If blnIs3LetterCode = false, then look for sequence of the form: R.ABCDEF.R
+ ' If found, remove the leading and ending residues since these aren't for this peptide
+ ' Returns 0 if success or 1 if an error
+ ' Will return 0 even in strSequence is blank or if it contains no valid residues
+
+ Dim lngSequenceStrLength As Long, lngIndex As Long, lngModSymbolLength As Long
+ Dim str1LetterSymbol As String, str3LetterSymbol As String, strFirstChar As String
+
+ strSequence = Trim(strSequence)
+
+ lngSequenceStrLength = Len(strSequence)
+ If lngSequenceStrLength = 0 Then Exit Function
+
+ ' Clear any old residue information
+ ResidueCount = 0
+ ReserveMemoryForResidues ResidueCount, False
+
+ If Not blnIs3LetterCode Then
+ ' Sequence is 1 letter codes
+
+ If bln1LetterCheckForPrefixAndSuffixResidues Then
+ ' First look if sequence is in the form A.BCDEFG.Z or -.BCDEFG.Z or A.BCDEFG.-
+ ' If so, then need to strip out the preceding A and Z residues since they aren't really part of the sequence
+ If lngSequenceStrLength > 1 And InStr(strSequence, ".") Then
+ If Mid(strSequence, 2, 1) = "." Then
+ strSequence = Mid(strSequence, 3)
+ lngSequenceStrLength = Len(strSequence)
+ End If
+
+ If Mid(strSequence, lngSequenceStrLength - 1, 1) = "." Then
+ strSequence = Left(strSequence, lngSequenceStrLength - 2)
+ lngSequenceStrLength = Len(strSequence)
+ End If
+
+ ' Also check for starting with a . or ending with a .
+ If Left(strSequence, 1) = "." Then
+ strSequence = Mid(strSequence, 2)
+ End If
+
+ If Right(strSequence, 1) = "." Then
+ strSequence = Left(strSequence, Len(strSequence) - 1)
+ End If
+
+ lngSequenceStrLength = Len(strSequence)
+ End If
+
+ End If
+
+ For lngIndex = 1 To lngSequenceStrLength
+ str1LetterSymbol = Mid(strSequence, lngIndex, 1)
+ If IsCharacter(str1LetterSymbol) Then
+ ' Character found
+ ' Look up 3 letter symbol
+ ' If none is found, this will return an empty string
+ str3LetterSymbol = GetAminoAcidSymbolConversionInternal(str1LetterSymbol, True)
+
+ If Len(str3LetterSymbol) = 0 Then str3LetterSymbol = UNKNOWN_SYMBOL
+
+ SetSequenceAddResidue str3LetterSymbol
+
+ ' Look at following character(s), and record any modification symbols present
+ lngModSymbolLength = CheckForModifications(Mid(strSequence, lngIndex + 1), ResidueCount, blnAddMissingModificationSymbols)
+
+ lngIndex = lngIndex + lngModSymbolLength
+ Else
+ ' If . or - or space, then ignore it
+ ' If a number, ignore it
+ ' If anything else, then should have been skipped, or should be skipped
+ If str1LetterSymbol = "." Or str1LetterSymbol = "-" Or str1LetterSymbol = " " Then
+ ' All is fine; we can skip this
+ Else
+ ' Ignore it
+ End If
+ End If
+ Next lngIndex
+
+ Else
+ ' Sequence is 3 letter codes
+ lngIndex = 1
+
+ If bln3LetterCheckForPrefixHandSuffixOH Then
+ ' Look for a leading H or trailing OH, provided those don't match any of the amino acids
+ RemoveLeadingH strSequence
+ RemoveTrailingOH strSequence
+
+ ' Recompute sequence length
+ lngSequenceStrLength = Len(strSequence)
+ End If
+
+ Do While lngIndex <= lngSequenceStrLength - 2
+ strFirstChar = Mid(strSequence, lngIndex, 1)
+ If IsCharacter(strFirstChar) Then
+ If IsCharacter(Mid(strSequence, lngIndex + 1, 1)) And _
+ IsCharacter(Mid(strSequence, lngIndex + 2, 1)) Then
+
+ str3LetterSymbol = UCase(strFirstChar) & LCase((Mid(strSequence, lngIndex + 1, 2)))
+
+ If GetAbbreviationIDInternal(str3LetterSymbol, True) = 0 Then
+ ' 3 letter symbol not found
+ ' Add anyway, but mark as Xxx
+ str3LetterSymbol = UNKNOWN_SYMBOL
+ End If
+
+ SetSequenceAddResidue str3LetterSymbol
+
+ ' Look at following character(s), and record any modification symbols present
+ lngModSymbolLength = CheckForModifications(Mid(strSequence, lngIndex + 3), ResidueCount, blnAddMissingModificationSymbols)
+
+ lngIndex = lngIndex + 3
+ lngIndex = lngIndex + lngModSymbolLength
+
+ Else
+ ' First letter is a character, but next two are not; ignore it
+ lngIndex = lngIndex + 1
+ End If
+ Else
+ ' If . or - or space, then ignore it
+ ' If a number, ignore it
+ ' If anything else, then should have been skipped or should be skipped
+ If strFirstChar = "." Or strFirstChar = "-" Or strFirstChar = " " Then
+ ' All is fine; we can skip this
+ Else
+ ' Ignore it
+ End If
+ lngIndex = lngIndex + 1
+ End If
+ Loop
+ End If
+
+ ' By calling SetNTerminus and SetCTerminus, the UpdateResidueMasses() Sub will also be called
+ mDelayUpdateResidueMass = True
+ SetNTerminusGroup eNTerminus
+ SetCTerminusGroup eCTerminus
+
+ mDelayUpdateResidueMass = False
+ UpdateResidueMasses
+
+ SetSequence = 0
+ Exit Function
+
+SetSequenceErrorHandler:
+ SetSequence = AssureNonZero(Err.Number)
+End Function
+
+Private Sub SetSequenceAddResidue(str3LetterSymbol As String)
+
+ If Len(str3LetterSymbol) = 0 Then
+ str3LetterSymbol = UNKNOWN_SYMBOL
+ End If
+
+ ResidueCount = ResidueCount + 1
+ ReserveMemoryForResidues ResidueCount, True
+
+ With Residues(ResidueCount)
+ .Symbol = str3LetterSymbol
+ .Phosphorylated = False
+ .ModificationIDCount = 0
+ End With
+
+End Sub
+
+Public Sub SetSymbolAmmoniaLoss(strNewSymbol As String)
+ If Len(strNewSymbol) > 0 Then
+ mAmmoniaLossSymbol = strNewSymbol
+ End If
+End Sub
+
+Public Sub SetSymbolPhosphoLoss(strNewSymbol As String)
+ If Len(strNewSymbol) > 0 Then
+ mPhosphoLossSymbol = strNewSymbol
+ End If
+End Sub
+
+Public Sub SetSymbolWaterLoss(strNewSymbol As String)
+ If Len(strNewSymbol) > 0 Then
+ mWaterLossSymbol = strNewSymbol
+ End If
+End Sub
+
+
+Private Sub ShellSortFragSpectrum(ByRef FragSpectrumWork() As udtFragmentationSpectrumDataType, ByRef PointerArray() As Long, ByVal lngLowIndex As Long, ByVal lngHighIndex As Long)
+ ' Sort the list using a shell sort
+ Dim lngCount As Long
+ Dim lngIncrement As Long
+ Dim lngIndex As Long
+ Dim lngIndexCompare As Long
+ Dim lngPointerSwap As Long
+
+ ' Sort PointerArray[lngLowIndex..lngHighIndex] by comparing FragSpectrumWork(PointerArray(x)).Mass
+
+ ' Compute largest increment
+ lngCount = lngHighIndex - lngLowIndex + 1
+ lngIncrement = 1
+ If (lngCount < 14) Then
+ lngIncrement = 1
+ Else
+ Do While lngIncrement < lngCount
+ lngIncrement = 3 * lngIncrement + 1
+ Loop
+ lngIncrement = lngIncrement \ 3
+ lngIncrement = lngIncrement \ 3
+ End If
+
+ Do While lngIncrement > 0
+ ' Sort by insertion in increments of lngIncrement
+ For lngIndex = lngLowIndex + lngIncrement To lngHighIndex
+ lngPointerSwap = PointerArray(lngIndex)
+ For lngIndexCompare = lngIndex - lngIncrement To lngLowIndex Step -lngIncrement
+ ' Use <= to sort ascending; Use > to sort descending
+ If FragSpectrumWork(PointerArray(lngIndexCompare)).Mass <= FragSpectrumWork(lngPointerSwap).Mass Then Exit For
+ PointerArray(lngIndexCompare + lngIncrement) = PointerArray(lngIndexCompare)
+ Next lngIndexCompare
+ PointerArray(lngIndexCompare + lngIncrement) = lngPointerSwap
+ Next lngIndex
+ lngIncrement = lngIncrement \ 3
+ Loop
+
+End Sub
+
+Private Sub UpdateResidueMasses()
+ Dim lngIndex As Long, lngAbbrevID As Long
+ Dim lngValidResidueCount As Long
+ Dim intModIndex As Integer
+ Dim dblRunningTotal As Double
+ Dim blnPhosphorylationMassAdded As Boolean
+ Dim blnProtonatedNTerminus As Boolean
+
+ If mDelayUpdateResidueMass Then Exit Sub
+
+ ' The N-terminus ions are the basis for the running total
+ dblRunningTotal = mNTerminus.Mass
+ If UCase(mNTerminus.Formula) = "HH" Then
+ ' ntgHydrogenPlusProton; since we add back in the proton below when computing the fragment masses,
+ ' we need to subtract it out here
+ ' However, we need to subtract out dblHydrogenMass, and not dblChargeCarrierMass since the current
+ ' formula's mass was computed using two hydrogens, and not one hydrogen and one charge carrier
+ blnProtonatedNTerminus = True
+ dblRunningTotal = dblRunningTotal - dblHydrogenMass
+ End If
+
+ For lngIndex = 1 To ResidueCount
+ With Residues(lngIndex)
+ lngAbbrevID = GetAbbreviationIDInternal(.Symbol, True)
+
+ If lngAbbrevID > 0 Then
+ lngValidResidueCount = lngValidResidueCount + 1
+ .Mass = GetAbbreviationMass(lngAbbrevID)
+
+ blnPhosphorylationMassAdded = False
+
+ ' Compute the mass, including the modifications
+ .MassWithMods = .Mass
+ For intModIndex = 1 To .ModificationIDCount
+ If .ModificationIDs(intModIndex) <= ModificationSymbolCount Then
+ .MassWithMods = .MassWithMods + ModificationSymbols(.ModificationIDs(intModIndex)).ModificationMass
+ If ModificationSymbols(.ModificationIDs(intModIndex)).IndicatesPhosphorylation Then
+ blnPhosphorylationMassAdded = True
+ End If
+ Else
+ ' Invalid ModificationID
+ Debug.Assert False
+ End If
+ Next intModIndex
+
+ If .Phosphorylated Then
+ ' Only add a mass if none of the .ModificationIDs has .IndicatesPhosphorylation = True
+ If Not blnPhosphorylationMassAdded Then
+ .MassWithMods = .MassWithMods + dblPhosphorylationMass
+ End If
+ End If
+
+ dblRunningTotal = dblRunningTotal + .MassWithMods
+
+ .IonMass(itAIon) = dblRunningTotal - dblImmoniumMassDifference - dblChargeCarrierMass
+ .IonMass(itBIon) = dblRunningTotal
+ Else
+ .Mass = 0
+ .MassWithMods = 0
+ Erase .IonMass()
+ End If
+ End With
+ Next lngIndex
+
+ dblRunningTotal = dblRunningTotal + mCTerminus.Mass
+ If blnProtonatedNTerminus Then
+ dblRunningTotal = dblRunningTotal + dblChargeCarrierMass
+ End If
+
+ If lngValidResidueCount > 0 Then
+ mTotalMass = dblRunningTotal
+ Else
+ mTotalMass = 0
+ End If
+
+ ' Now compute the y-ion masses
+ dblRunningTotal = mCTerminus.Mass + dblChargeCarrierMass
+
+ For lngIndex = ResidueCount To 1 Step -1
+ With Residues(lngIndex)
+ If .IonMass(itAIon) > 0 Then
+ dblRunningTotal = dblRunningTotal + .MassWithMods
+ .IonMass(itYIon) = dblRunningTotal + dblChargeCarrierMass
+ If lngIndex = 1 Then
+ ' Add the N-terminus mass to highest y ion
+ .IonMass(itYIon) = .IonMass(itYIon) + mNTerminus.Mass - dblChargeCarrierMass
+ If blnProtonatedNTerminus Then
+ ' ntgHydrogenPlusProton; since we add back in the proton below when computing the fragment masses,
+ ' we need to subtract it out here
+ ' However, we need to subtract out dblHydrogenMass, and not dblChargeCarrierMass since the current
+ ' formula's mass was computed using two hydrogens, and not one hydrogen and one charge carrier
+ .IonMass(itYIon) = .IonMass(itYIon) - dblHydrogenMass
+ End If
+ End If
+ End If
+ End With
+ Next lngIndex
+
+End Sub
+
+Public Sub UpdateStandardMasses()
+ Dim eElementModeSaved As emElementModeConstants
+
+On Error GoTo UpdateStandardMassesErrorHandler
+
+ eElementModeSaved = GetElementModeInternal()
+
+ SetElementModeInternal 2 ' emIsotopicMass
+
+ dblChargeCarrierMass = GetChargeCarrierMassInternal()
+
+ ' Update standard mass values
+ dblHOHMass = ComputeFormulaWeight("HOH")
+ dblNH3Mass = ComputeFormulaWeight("NH3")
+ dblH3PO4Mass = ComputeFormulaWeight("H3PO4")
+ dblHydrogenMass = ComputeFormulaWeight("H")
+
+ ' Phosphorylation is the loss of OH and the addition of H2PO4, for a net change of HPO3
+ dblPhosphorylationMass = ComputeFormulaWeight("HPO3")
+
+ ' The immonium mass is equal to the mass of CO minus the mass of H, thus typically 26.9871
+ dblImmoniumMassDifference = ComputeFormulaWeight("CO") - dblHydrogenMass
+
+ dblHistidineFW = ComputeFormulaWeight("His")
+ dblPhenylalanineFW = ComputeFormulaWeight("Phe")
+ dblTyrosineFW = ComputeFormulaWeight("Tyr")
+
+ SetElementModeInternal eElementModeSaved
+
+Exit Sub
+
+UpdateStandardMassesErrorHandler:
+ GeneralErrorHandler "MWPeptideClass.UpdateStandardMasses", Err.Number
+
+End Sub
+
+Private Sub Class_Initialize()
+ On Error GoTo InitPeptideClassErrorHandler
+
+ ResidueCountDimmed = 0
+ ResidueCount = 0
+ ReserveMemoryForResidues 50, False
+
+ ModificationSymbolCountDimmed = 0
+ ModificationSymbolCount = 0
+ ReserveMemoryForModifications 10, False
+
+ SetDefaultOptions
+
+ Exit Sub
+
+InitPeptideClassErrorHandler:
+ GeneralErrorHandler "MWPeptideClass.Class_Initialize", Err.Number
+End Sub
+
diff --git a/MwtWinDll/frmProgress.frm b/MwtWinDll/frmProgress.frm
new file mode 100644
index 0000000..1821e4d
--- /dev/null
+++ b/MwtWinDll/frmProgress.frm
@@ -0,0 +1,552 @@
+VERSION 5.00
+Begin VB.Form frmProgress
+ BorderStyle = 3 'Fixed Dialog
+ Caption = "Progress"
+ ClientHeight = 2385
+ ClientLeft = 45
+ ClientTop = 360
+ ClientWidth = 7350
+ KeyPreview = -1 'True
+ LinkTopic = "Form1"
+ MaxButton = 0 'False
+ MinButton = 0 'False
+ ScaleHeight = 2385
+ ScaleWidth = 7350
+ ShowInTaskbar = 0 'False
+ StartUpPosition = 3 'Windows Default
+ Tag = "14700"
+ Begin VB.Frame fraControls
+ BorderStyle = 0 'None
+ Caption = "Frame1"
+ Height = 735
+ Left = 3840
+ TabIndex = 5
+ Top = 1560
+ Width = 2415
+ Begin VB.CommandButton cmdPause
+ Caption = "Click to Pause"
+ Height = 375
+ Left = 360
+ TabIndex = 6
+ Tag = "14710"
+ Top = 0
+ Width = 1815
+ End
+ Begin VB.Label lblPressEscape
+ Alignment = 2 'Center
+ Caption = "(Press Escape to abort)"
+ Height = 255
+ Left = 0
+ TabIndex = 7
+ Tag = "14730"
+ Top = 480
+ Width = 2655
+ End
+ End
+ Begin VB.Shape pbarSubProgressBox
+ Height = 255
+ Left = 120
+ Top = 960
+ Width = 2775
+ End
+ Begin VB.Shape pbarSubProgress
+ BackColor = &H80000002&
+ FillColor = &H80000002&
+ FillStyle = 0 'Solid
+ Height = 255
+ Left = 120
+ Top = 960
+ Width = 1215
+ End
+ Begin VB.Shape pbarProgressBox
+ Height = 255
+ Left = 120
+ Top = 120
+ Width = 2775
+ End
+ Begin VB.Shape pbarProgress
+ BackColor = &H80000002&
+ FillColor = &H80000002&
+ FillStyle = 0 'Solid
+ Height = 255
+ Left = 120
+ Top = 120
+ Width = 1215
+ End
+ Begin VB.Label lblSubtaskProgress
+ Alignment = 2 'Center
+ Caption = "Current Task Progress"
+ Height = 255
+ Left = 120
+ TabIndex = 1
+ Tag = "14730"
+ Top = 1350
+ Width = 2655
+ End
+ Begin VB.Label lblOverallProgress
+ Alignment = 2 'Center
+ Caption = "Overall Progress"
+ Height = 255
+ Left = 120
+ TabIndex = 0
+ Tag = "14730"
+ Top = 510
+ Width = 2655
+ End
+ Begin VB.Label lblCurrentSubTask
+ Height = 735
+ Left = 3120
+ TabIndex = 4
+ Top = 720
+ Width = 4095
+ End
+ Begin VB.Label lblTimeStats
+ Caption = "Elapsed/remaining time"
+ Height = 255
+ Left = 240
+ TabIndex = 2
+ Top = 1800
+ Width = 3015
+ End
+ Begin VB.Label lblCurrentTask
+ Caption = "Current task"
+ Height = 495
+ Left = 3120
+ TabIndex = 3
+ Top = 120
+ Width = 4095
+ End
+End
+Attribute VB_Name = "frmProgress"
+Attribute VB_GlobalNameSpace = False
+Attribute VB_Creatable = False
+Attribute VB_PredeclaredId = True
+Attribute VB_Exposed = False
+Option Explicit
+
+' Written by Matthew Monroe for use in applications
+' First written in Chapel Hill, NC in roughly 2000
+'
+' Last Modified: July 24, 2003
+
+Private ePauseStatus As ppProgressPauseConstants
+
+Private lngProgressMin As Long
+Private lngProgressMax As Long
+Private dblLatestProgressBarValue As Double
+
+Private lngSubTaskProgressMin As Long
+Private lngSubTaskProgressMax As Long
+Private dblLatestSubTaskProgressBarValue As Double
+
+Private mblnWorking As Boolean
+Private mTextMinutesElapsedRemaining As String
+Private mTextPreparingToPause As String
+Private mTextResuming As String
+Private mTextClickToPause As String
+Private mTextPaused As String
+Private mTextPressEscapeToAbort As String
+Private mLastQueryUnloadTickCount As Long
+
+Private Enum ppProgressPauseConstants
+ ppUnpaused = 0
+ ppRequestPause
+ ppPaused
+ ppRequestUnpause
+End Enum
+
+Private Sub CheckForPauseUnpause()
+
+ Select Case ePauseStatus
+ Case ppRequestPause
+ cmdPause.Caption = mTextPaused
+ ePauseStatus = ppPaused
+ Me.MousePointer = vbNormal
+ Do
+ Sleep 100
+ DoEvents
+ Loop While ePauseStatus = ppPaused
+ ePauseStatus = ppUnpaused
+ cmdPause.Caption = mTextClickToPause
+ Me.MousePointer = vbHourglass
+ Case ppRequestUnpause
+ ePauseStatus = ppUnpaused
+ cmdPause.Caption = mTextClickToPause
+ Case Else
+ ' Nothing to pause or unpause
+ End Select
+
+End Sub
+
+Public Function GetElapsedTime() As Single
+ ' Examines lblTimeStats to find the last recorded elapsed time
+
+ Dim intColonLoc As Integer
+
+ intColonLoc = InStr(lblTimeStats, ":")
+
+ If intColonLoc > 0 Then
+ GetElapsedTime = Val(Left(lblTimeStats, intColonLoc - 1))
+ End If
+
+End Function
+
+Public Function GetProgressBarValue(ByRef lngMinimum As Long, ByRef lngMaximum As Long) As Double
+ ' Returns the current value of the progress bar, plus the Min and Max, returning them ByRef
+ lngMinimum = lngProgressMin
+ lngMaximum = lngProgressMax
+
+ GetProgressBarValue = dblLatestProgressBarValue
+End Function
+
+Public Function GetSubTaskProgressBarValue(ByRef lngMinimum As Long, ByRef lngMaximum As Long) As Double
+ ' Returns the current value of the subtask progress bar, plus the Min and Max, returning them ByRef
+ lngMinimum = lngSubTaskProgressMin
+ lngMaximum = lngSubTaskProgressMax
+
+ GetSubTaskProgressBarValue = dblLatestSubTaskProgressBarValue
+End Function
+
+Public Sub HideForm(Optional blnResetKeyPressAbortProcess As Boolean = True)
+
+ If blnResetKeyPressAbortProcess Then KeyPressAbortProcess = 0
+
+ frmProgress.MousePointer = vbNormal
+
+ mblnWorking = False
+
+ ' The following On Error is necessary in case a modal window is displayed
+ ' Also necessary since a call to .Hide when a form is already hidden generates an error
+ On Error Resume Next
+ frmProgress.Hide
+
+End Sub
+
+Public Sub InitializeSubtask(CurrentSubTask As String, SubTaskProgressBarMinNew As Long, SubTaskProgressBarMaxNew As Long)
+ lngSubTaskProgressMin = SubTaskProgressBarMinNew
+ lngSubTaskProgressMax = SubTaskProgressBarMaxNew
+
+ If lngSubTaskProgressMin > lngSubTaskProgressMax Then
+ ' Swap them
+ SwapValues lngSubTaskProgressMin, lngSubTaskProgressMax
+ End If
+
+ If lngSubTaskProgressMin < 0 Then lngSubTaskProgressMin = 0
+ If lngSubTaskProgressMin > lngSubTaskProgressMax Then lngSubTaskProgressMax = lngSubTaskProgressMin + 1
+ If lngSubTaskProgressMax < 1 Then lngSubTaskProgressMax = 1
+
+On Error GoTo InitializeSubtaskErrorHandler
+
+ UpdateCurrentSubTask CurrentSubTask
+
+ UpdateSubtaskProgressBar lngSubTaskProgressMin
+
+ mblnWorking = True
+
+ Exit Sub
+
+InitializeSubtaskErrorHandler:
+ MsgBox "An error occurred while initializing the sub-progress bar: " & vbCrLf & Err.Description, vbInformation + vbOKOnly, "Error"
+ Resume Next
+
+End Sub
+
+Public Sub InitializeForm(CurrentTask As String, OverallProgressBarMinNew As Long, OverallProgressBarMaxNew As Long, Optional blnShowTimeStats As Boolean = False, Optional blnShowSubTaskProgress As Boolean = False, Optional blnShowPauseButton As Boolean = True, Optional frmObjOwnerForm As Form)
+ lngProgressMin = OverallProgressBarMinNew
+ lngProgressMax = OverallProgressBarMaxNew
+
+ If lngProgressMin > lngProgressMax Then
+ ' Swap them
+ SwapValues lngProgressMin, lngProgressMax
+ End If
+
+ If lngProgressMin < 0 Then lngProgressMin = 0
+ If lngProgressMin > lngProgressMax Then lngProgressMax = lngProgressMin + 1
+ If lngProgressMax < 1 Then lngProgressMax = 1
+
+ lngSubTaskProgressMin = 0
+ lngSubTaskProgressMax = 1
+ pbarSubProgress.Width = 0
+
+On Error GoTo InitializeFormErrorHandler
+
+ UpdateCurrentTask CurrentTask
+ lblCurrentSubTask = ""
+
+ lblTimeStats.Visible = blnShowTimeStats
+
+ pbarSubProgress.Visible = blnShowSubTaskProgress
+ pbarSubProgressBox.Visible = blnShowSubTaskProgress
+ lblSubtaskProgress.Visible = blnShowSubTaskProgress
+
+ If blnShowSubTaskProgress Then
+ lblTimeStats.Top = 1800
+ fraControls.Top = 1650
+ fraControls.Left = 3840
+ Me.Height = 2800
+ Else
+ lblTimeStats.Top = 800
+ fraControls.Top = 1190
+ fraControls.Left = 240
+ Me.Height = 2350
+ End If
+
+ cmdPause.Visible = blnShowPauseButton
+ If ppPaused Then
+ ePauseStatus = ppRequestUnpause
+ CheckForPauseUnpause
+ End If
+
+ UpdateProgressBar lngProgressMin, True
+
+ KeyPressAbortProcess = 0
+ mLastQueryUnloadTickCount = 0
+ mblnWorking = True
+
+ If frmObjOwnerForm Is Nothing Then
+ frmProgress.Show vbModeless
+ Else
+ frmProgress.Show vbModeless, frmObjOwnerForm
+ End If
+
+ frmProgress.MousePointer = vbHourglass
+
+ Exit Sub
+
+InitializeFormErrorHandler:
+ If Err.Number = 401 Then
+ ' Tried to show frmProgress when a modal form is shown; this isn't allowed
+ ' Probably cannot use frmProgress in the calling routine
+ Debug.Assert False
+ Resume Next
+ Else
+ MsgBox "An error occurred while initializing the progress bar: " & vbCrLf & Err.Description, vbInformation + vbOKOnly, "Error"
+ Resume Next
+ End If
+
+End Sub
+
+Public Sub MoveToBottomCenter()
+ SizeAndCenterWindow Me, cWindowBottomCenter, -1, -1, False
+End Sub
+
+Public Function TaskInProgress() As Boolean
+ ' Returns True if the Progress form is currently displayed
+ ' Returns False otherwise
+
+ TaskInProgress = mblnWorking
+End Function
+
+Public Sub ToggleAlwaysOnTop(blnStayOnTop As Boolean)
+ Static blnCurrentlyOnTop As Boolean
+
+ If blnCurrentlyOnTop = blnStayOnTop Then Exit Sub
+
+ Me.ScaleMode = vbTwips
+
+ WindowStayOnTop Me.hWnd, blnStayOnTop, Me.ScaleX(Me.Left, vbTwips, vbPixels), Me.ScaleY(Me.Top, vbTwips, vbPixels), Me.ScaleX(Me.Width, vbTwips, vbPixels), Me.ScaleY(Me.Height, vbTwips, vbPixels)
+
+ blnCurrentlyOnTop = blnStayOnTop
+End Sub
+
+Public Sub UpdateProgressBar(ByVal NewValue As Double, Optional ResetStartTime As Boolean = False)
+
+ Static StartTime As Double
+ Static StopTime As Double
+
+ Dim MinutesElapsed As Double, MinutesTotal As Double, MinutesRemaining As Double
+ Dim dblRatioCompleted As Double
+
+ If ResetStartTime Then
+ StartTime = Now()
+ End If
+
+ dblRatioCompleted = SetProgressBarValue(NewValue, False)
+
+ StopTime = Now()
+ MinutesElapsed = (StopTime - StartTime) * 1440
+ If dblRatioCompleted <> 0 Then
+ MinutesTotal = MinutesElapsed / dblRatioCompleted
+ Else
+ MinutesTotal = 0
+ End If
+ MinutesRemaining = MinutesTotal - MinutesElapsed
+ lblTimeStats = Format(MinutesElapsed, "0.00") & " : " & Format(MinutesRemaining, "0.00 ") & mTextMinutesElapsedRemaining
+
+ CheckForPauseUnpause
+
+ DoEvents
+
+End Sub
+
+Public Sub SetStandardCaptionText(Optional ByVal strMinutesElapsedRemaining As String = "min. elapsed/remaining", Optional ByVal strPreparingToPause As String = "Preparing to Pause", Optional ByVal strResuming As String = "Resuming", Optional ByVal strClickToPause As String = "Click to Pause", Optional ByVal strPaused As String = "Paused", Optional ByVal strPressEscapeToAbort As String = "(Press Escape to abort)")
+ mTextMinutesElapsedRemaining = strMinutesElapsedRemaining
+ mTextPreparingToPause = strPreparingToPause
+ mTextResuming = strResuming
+ mTextClickToPause = strClickToPause
+ mTextPaused = strPaused
+ mTextPressEscapeToAbort = strPressEscapeToAbort
+
+ lblPressEscape.Caption = mTextPressEscapeToAbort
+End Sub
+
+Private Function SetProgressBarValue(ByRef dblNewValue As Double, Optional blnIncrementalUpdate As Boolean = False) As Double
+ ' Updates the value of the Progress bar based on dblNewValue, adjusting if necessary
+ ' Returns the % completed ratio
+ ' If blnIncrementalUpdate is true, then does not update dblLatestProgressBarValue
+
+ Dim dblRatioCompleted As Double
+
+ If dblNewValue < lngProgressMin Then dblNewValue = lngProgressMin
+ If dblNewValue > lngProgressMax Then dblNewValue = lngProgressMax
+
+ If lngProgressMax > lngProgressMin Then
+ dblRatioCompleted = (dblNewValue - lngProgressMin) / (lngProgressMax - lngProgressMin)
+ Else
+ dblRatioCompleted = 0
+ End If
+ If dblRatioCompleted < 0 Then dblRatioCompleted = 0
+ If dblRatioCompleted > 1 Then dblRatioCompleted = 1
+
+On Error GoTo ExitSetProgressBar
+
+ pbarProgress.Width = pbarProgressBox.Width * dblRatioCompleted
+
+ If Not blnIncrementalUpdate Then
+ dblLatestProgressBarValue = dblNewValue
+ End If
+
+ SetProgressBarValue = dblRatioCompleted
+
+ExitSetProgressBar:
+
+End Function
+
+Public Sub UpdateSubtaskProgressBar(ByVal dblNewValue As Double, Optional ByVal blnFractionallyIncreaseOverallProgressValue As Boolean = True)
+ Dim dblPartialIncrementToAdd As Double, dblNewTotalProgressValue As Double
+ Dim dblRatioCompleted As Double
+ Dim lngSubtaskProgressBarLength As Long
+
+ If dblNewValue < lngSubTaskProgressMin Then dblNewValue = lngSubTaskProgressMin
+ If dblNewValue > lngSubTaskProgressMax Then dblNewValue = lngSubTaskProgressMax
+
+ dblLatestSubTaskProgressBarValue = dblNewValue
+
+ If lngSubTaskProgressMax > 0 Then
+ dblRatioCompleted = (dblNewValue - lngSubTaskProgressMin) / lngSubTaskProgressMax
+ Else
+ dblRatioCompleted = 0
+ End If
+ If dblRatioCompleted < 0 Then dblRatioCompleted = 0
+ If dblRatioCompleted > 1 Then dblRatioCompleted = 1
+
+ On Error GoTo ExitUpdateSubProgressBarFunction
+
+ pbarSubProgress.Width = pbarSubProgressBox.Width * dblRatioCompleted
+
+ lngSubtaskProgressBarLength = lngSubTaskProgressMax - lngSubTaskProgressMin
+ If lngSubtaskProgressBarLength > 0 And blnFractionallyIncreaseOverallProgressValue Then
+ dblPartialIncrementToAdd = (dblNewValue - lngSubTaskProgressMin) / CDbl(lngSubtaskProgressBarLength)
+
+ dblNewTotalProgressValue = dblLatestProgressBarValue + dblPartialIncrementToAdd
+ If dblNewTotalProgressValue > dblLatestProgressBarValue Then
+ SetProgressBarValue dblNewTotalProgressValue, True
+ End If
+ End If
+
+ CheckForPauseUnpause
+
+ DoEvents
+
+ExitUpdateSubProgressBarFunction:
+
+End Sub
+
+Public Sub UpdateCurrentTask(strNewTask As String)
+ lblCurrentTask = strNewTask
+
+ CheckForPauseUnpause
+
+ DoEvents
+End Sub
+
+Public Sub UpdateCurrentSubTask(strNewSubTask As String)
+ lblCurrentSubTask = strNewSubTask
+
+ CheckForPauseUnpause
+
+ DoEvents
+End Sub
+
+Public Sub WasteTime(Optional Milliseconds As Integer = 250)
+ ' Wait the specified number of milliseconds
+
+ ' Use of the Sleep API call is more efficient than using a VB timer since it results in 0% processor usage
+ Sleep Milliseconds
+
+End Sub
+
+Private Sub cmdPause_Click()
+ Select Case ePauseStatus
+ Case ppUnpaused
+ ePauseStatus = ppRequestPause
+ cmdPause.Caption = mTextPreparingToPause
+ DoEvents
+ Case ppPaused
+ ePauseStatus = ppRequestUnpause
+ cmdPause.Caption = mTextResuming
+ DoEvents
+ Case Else
+ ' Ignore click
+ End Select
+
+End Sub
+
+Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
+ If KeyCode = vbKeyEscape Then
+ KeyPressAbortProcess = 2
+ KeyCode = 0
+ Shift = 0
+
+ ' Move the form to the bottom center of the screen to avoid having the msgbox popup under the form
+ MoveToBottomCenter
+ End If
+End Sub
+
+Private Sub Form_Load()
+
+ ' Put window in exact center of screen
+ SizeAndCenterWindow Me, cWindowLowerThird, 7450, 2800, False
+
+ SetStandardCaptionText
+
+ mblnWorking = False
+
+End Sub
+
+Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
+ Dim eResponse As VbMsgBoxResult
+ Dim lngCurrentTickCount As Long
+
+ If UnloadMode = vbFormControlMenu Then
+ ' If at least 20 seconds has elapsed since the last time the user tried
+ ' to close the form, then query whether they really want to do this
+ lngCurrentTickCount = GetTickCount()
+ If Abs(lngCurrentTickCount - mLastQueryUnloadTickCount) >= 20000 Then
+ ' Move the form to the bottom center of the screen to avoid having the msgbox popup under the form
+ Me.MoveToBottomCenter
+
+ eResponse = MsgBox("It appears that a task is currently in progress. Do you really want to close the progress window? If yes, this will cancel the currently running task.", vbQuestion + vbYesNo + vbDefaultButton2, "Cancel Task")
+ If eResponse = vbYes Then
+ ' Set KeyPressAbortProcess to 2 so that the program will cancel the task gracefully, and (hopefully) hide the progress window
+ KeyPressAbortProcess = 2
+ Else
+ ' User said no; set lngCurrentTickCount to 0 to guarantee MsgBox will reoccur if user clicks again
+ lngCurrentTickCount = 0
+ End If
+
+ Cancel = 1
+ End If
+ mLastQueryUnloadTickCount = lngCurrentTickCount
+ End If
+End Sub
diff --git a/MwtWinDll/frmResults.frm b/MwtWinDll/frmResults.frm
new file mode 100644
index 0000000..4e57403
--- /dev/null
+++ b/MwtWinDll/frmResults.frm
@@ -0,0 +1,44 @@
+VERSION 5.00
+Begin VB.Form frmResults
+ Caption = "Form1"
+ ClientHeight = 6510
+ ClientLeft = 60
+ ClientTop = 360
+ ClientWidth = 9285
+ LinkTopic = "Form1"
+ ScaleHeight = 6510
+ ScaleWidth = 9285
+ StartUpPosition = 3 'Windows Default
+ Begin VB.TextBox txtResults
+ Height = 5295
+ Left = -240
+ MultiLine = -1 'True
+ ScrollBars = 3 'Both
+ TabIndex = 0
+ Top = -120
+ Width = 7335
+ End
+End
+Attribute VB_Name = "frmResults"
+Attribute VB_GlobalNameSpace = False
+Attribute VB_Creatable = False
+Attribute VB_PredeclaredId = True
+Attribute VB_Exposed = False
+Option Explicit
+
+Public Function AddToResults(strNewText As String)
+ txtResults = txtResults & vbCrLf & strNewText
+ DoEvents
+End Function
+
+Private Sub Form_Resize()
+ On Error Resume Next
+
+ With txtResults
+ .Top = 0
+ .Left = 0
+ .Width = Me.ScaleWidth
+ .Height = Me.ScaleHeight
+ End With
+
+End Sub
diff --git a/MwtWin_Bug.jpg b/MwtWin_Bug.jpg
new file mode 100644
index 0000000..3293f02
Binary files /dev/null and b/MwtWin_Bug.jpg differ
diff --git a/MwtWin_InternationalCaptions(Macro).xls b/MwtWin_InternationalCaptions(Macro).xls
new file mode 100644
index 0000000..5962173
Binary files /dev/null and b/MwtWin_InternationalCaptions(Macro).xls differ
diff --git a/MwtWin_WithDll.vbg b/MwtWin_WithDll.vbg
new file mode 100644
index 0000000..6d6c220
--- /dev/null
+++ b/MwtWin_WithDll.vbg
@@ -0,0 +1,3 @@
+VBGROUP 5.0
+StartupProject=Mwtwin.vbp
+Project=MwtWinDll\MwtWindll.vbp
diff --git a/MwtZip/Batch.txt b/MwtZip/Batch.txt
new file mode 100644
index 0000000..0c771fb
--- /dev/null
+++ b/MwtZip/Batch.txt
@@ -0,0 +1,31 @@
+; Enable formula finder mode using FF=, specifying the elements to use in searching
+; Can also specify weight mode, maximum number of hits, and tolerance
+FF=C,H,N,O,Cl,Bpy,Asdfd
+WEIGHTMODE=ISOTOPIC
+MAXHITS=5
+TOLERANCE=0.05
+403.84
+300.58
+
+; The tolerance can be changed
+TOLERANCE=0.02
+403.885
+
+; The maximum number of hits can be changed
+MAXHITS=10
+632.43
+
+; The search elements can be changed
+FF=N,Br,H,Li
+MAXHITS=2
+389.32
+
+; Re-enable molecular weight searching using MW=
+; Subsequently, compounds to calculate a molecular weight for can be listed
+MW=
+NH2
+C6H5Cl
+^13C6H5Cl
+WEIGHTMODE=AVERAGE
+FeCl3-6H2O
+
diff --git a/MwtZip/Batch.txt.out b/MwtZip/Batch.txt.out
new file mode 100644
index 0000000..f420de6
--- /dev/null
+++ b/MwtZip/Batch.txt.out
@@ -0,0 +1,49 @@
+
+; Formula Finder Mode Enabled. Search elements/abbreviations: C, H, N, O, Cl, Bpy
+; Isotopic Weight Mode Enabled
+; FF Searching: 403.84
+Compounds found: 5
+C2BpyCl6N MW=403.8849368 dm=0.0449368
+C5H6Cl8N3O MW=403.8019086 dm=-0.0380914
+C6H6Cl8NO2 MW=403.7906756 dm=-0.0493244
+C6H8Cl8N2O MW=403.8144838 dm=-0.0255162
+C7H8Cl8O2 MW=403.8032508 dm=-0.0367492
+
+; FF Searching: 300.58
+Compounds found: 0
+
+; FF Searching: 403.885
+Compounds found: 5
+CH7Cl7N10 MW=403.8674832 dm=-0.0175168
+C2BpyCl6N MW=403.8849368 dm=-0.0000632
+C2H9Cl7N9 MW=403.8800584 dm=-0.0049416
+C3H2BpyCl6 MW=403.897512 dm=0.012512
+C3H9Cl7N7O MW=403.8688254 dm=-0.0161746
+
+; FF Searching: 632.43
+Compounds found: 10
+CH24Bpy3N8O MW=632.413531800001 dm=-0.0164682
+C2H26Bpy3N7O MW=632.426107000001 dm=-0.003893
+C3H26Bpy3N5O2 MW=632.414874000001 dm=-0.015126
+C4H28Bpy3N4O2 MW=632.427449200001 dm=-0.0025508
+C5H28Bpy3N2O3 MW=632.416216200001 dm=-0.0137838
+C5H30Bpy3N3O2 MW=632.440024400001 dm=0.0100244
+C6H30Bpy3NO3 MW=632.428791400001 dm=-0.0012086
+C7H31Bpy3ClN MW=632.420724000002 dm=-0.009276
+C7H32Bpy3O3 MW=632.441366600002 dm=0.0113666
+C8H33Bpy3Cl MW=632.433299200002 dm=0.0032992
+
+
+; Formula Finder Mode Enabled. Search elements/abbreviations: H, N, Br, Li
+; FF Searching: 389.32
+Compounds found: 2
+H47Br3Li11N2 MW=389.3049672 dm=-0.0150328
+H47Br3Li13N MW=389.3339032 dm=0.0139032
+
+
+; Molecular Weight Mode Enabled
+NH2 16.01872 (±0)
+C6H5Cl 112.00798 (±0)
+^13C6H5Cl 118.00798 (±0)
+; Average Weight Mode Enabled
+FeCl3-6H2O 270.295(±3)
diff --git a/MwtZip/Comdlg32.ocx b/MwtZip/Comdlg32.ocx
new file mode 100644
index 0000000..bb79309
Binary files /dev/null and b/MwtZip/Comdlg32.ocx differ
diff --git a/MwtZip/ExampleSequence.seq b/MwtZip/ExampleSequence.seq
new file mode 100644
index 0000000..47f37e5
--- /dev/null
+++ b/MwtZip/ExampleSequence.seq
@@ -0,0 +1,807 @@
+; Molecular Weight Calculator Sequence Information File
+FragModelNotationMode=0
+FragModelSequence=RHPEYAVSVLLR
+FragModelNTerminus=0
+FragModelCTerminus=0
+FragModelIonType0=1
+FragModelIonType1=1
+FragModelIonType2=1
+FragModelIonsToModify0=0
+FragModelIonsToModify1=1
+FragModelIonsToModify2=1
+FragModelWaterLoss=1
+FragModelAmmoniaLoss=1
+FragModelDoubleCharge=0
+FragModelDoubleChargeThreshold=5
+FragModelPrecursorIonRemove=1
+FragModelPrecursorIonMass=480.63
+FragModelPrecursorIonMassWindow=.5
+FragModelIonMatchWindow=0.5
+FragModelIonIntensity0=50
+FragModelIonIntensity1=50
+FragModelIonIntensity2=50
+FragModelShoulderIntensity=0
+FragModelNeutralLossIntensity=10
+FragModelGroupIons=0
+FragModelGroupIonsMassWindow=0.5
+FragModelNormalizedIntensity=100
+FragModelNormalizationIonsUseCount=100
+FragModelNormalizationMassRegions=10
+IonPlotType=0
+IonPlotResolution=5000
+IonPlotResolutionXVal=500
+IonPlotGridlinesX=0
+IonPlotGridlinesY=0
+IonPlotTicksX=5
+IonPlotTicksY=5
+IonPlotGaussianQuality=20
+IonPlotApproximationFactor=10
+IonPlotAutoscaleY=1
+IonPlotShowPosition=1
+IonPlotShowLegend=0
+FragModelIonMatchList=763
+112.0853,3
+136.0762,59
+137.0843,5
+139.0817,6
+139.1133,17
+139.377,2
+139.7315,2
+140.0848,5
+141.5006,1
+143.1274,15
+143.5475,1
+144.1294,2
+148.0963,2
+156.1161,4
+157.0959,5
+159.0842,2
+159.1246,34
+160.1297,2
+160.1751,1
+163.8093,6
+169.1121,3
+171.0814,1
+171.1163,7
+175.1257,37
+182.1106,3
+185.1759,5
+186.1721,1
+186.2184,1
+187.111,37
+188.121,6
+196.1191,3
+199.1189,12
+199.1768,2
+202.3497,2
+202.3897,6
+202.4608,2
+202.9548,1
+203.0119,3
+205.1135,2
+207.0992,4
+207.1408,8
+213.1642,4
+218.1487,2
+221.9199,2
+227.1035,31
+227.1788,4
+228.0981,4
+228.1437,4
+233.155,3
+235.0365,1
+235.1248,19
+236.1297,7
+240.1542,3
+245.6539,4
+246.3976,2
+246.6541,68
+246.8809,1
+247.1341,4
+247.1902,11
+249.1758,7
+250.6709,5
+250.7164,7
+251.1959,5
+251.2478,3
+251.6217,2
+251.6747,2
+252.1679,6
+255.6198,1
+258.2047,3
+259.1178,1
+259.1799,3
+260.295,4
+260.5264,2
+260.6527,149
+261.069,1
+261.1432,39
+261.4579,3
+261.6691,5
+262.1266,6
+262.2358,4
+263.0959,2
+263.1416,2
+266.1627,13
+266.2044,6
+266.9036,2
+267.548,2
+267.9639,1
+268.1754,8
+268.6133,1
+269.1628,4
+269.6667,1
+269.7262,2
+271.1963,17
+271.2502,4
+272.1867,2
+275.1514,1
+275.6785,2
+275.7574,1
+277.1639,12
+278.137,6
+286.1738,4
+287.0152,3
+288.2111,63
+288.5215,2
+288.9533,1
+289.1393,3
+289.2121,17
+293.1697,3
+293.6161,2
+293.6732,2
+294.1874,231
+294.455,5
+294.5085,3
+294.6884,14
+294.9955,1
+295.1794,42
+295.2924,2
+295.3462,1
+295.3869,2
+295.447,1
+295.5037,2
+295.9444,1
+296.1693,10
+296.3044,3
+300.1975,21
+300.2907,2
+301.2919,2
+304.7282,2
+306.1841,3
+306.2568,1
+312.2487,6
+319.6728,4
+320.2012,4
+322.2489,2
+327.1851,3
+327.3661,1
+328.1826,68
+328.2633,14
+328.3271,3
+328.6884,49
+328.7545,6
+329.1873,8
+333.1671,8
+333.6007,3
+334.2184,12
+334.2833,1
+334.7221,4
+334.7917,2
+337.7202,3
+339.5072,2
+340.7826,2
+341.0398,2
+341.7773,4
+342.1797,393
+342.3465,3
+342.4303,5
+342.4893,4
+342.5583,7
+342.6834,159
+342.817,13
+343.0197,4
+343.1782,28
+343.4868,4
+343.5865,2
+343.6495,5
+343.7368,36
+343.8218,10
+343.8938,4
+344.0427,2
+344.1109,1
+344.1737,4
+344.258,31
+344.5179,4
+344.5953,4
+344.7082,7
+344.8063,3
+344.9668,5
+345.2133,3
+346.1691,6
+346.7994,2
+346.8672,3
+347.1616,6
+347.3818,4
+349.0909,2
+351.1988,4
+351.2789,1
+351.6955,3
+355.2979,1
+356.1698,3
+356.6293,1
+357.2323,4
+362.1739,13
+362.2378,3
+363.2299,6
+363.3801,1
+363.7023,82
+364.1729,18
+364.2336,11
+364.3133,5
+364.5458,3
+364.6974,3
+365.1807,4
+365.5901,2
+366.2758,4
+366.8056,3
+368.689,13
+369.6983,3
+370.2689,5
+370.3798,2
+371.2562,5
+372.1652,3
+373.11,3
+373.2534,2
+375.1942,4
+376.0613,2
+376.4238,5
+377.0261,6
+377.1432,1
+377.2305,12
+377.4629,5
+377.5285,3
+377.7029,598
+377.9336,5
+377.9883,3
+378.2069,338
+378.5213,10
+378.5701,6
+378.691,51
+378.7713,34
+378.9062,3
+378.9558,1
+379.0303,10
+379.1436,4
+379.2068,21
+379.3916,8
+379.6018,9
+379.7127,3
+379.8116,4
+379.8799,9
+380.3029,2
+380.4071,1
+380.958,4
+382.7159,4
+384.207,5
+384.2823,21
+386.2754,4
+388.5695,2
+390.1915,52
+390.283,4
+391.1819,10
+391.2362,8
+392.1442,3
+392.2137,1
+393.5819,2
+393.9643,2
+394.8687,2
+400.2879,3
+400.4994,4
+400.5706,2
+401.1934,4
+401.3109,371
+401.6982,6
+402.3135,81
+402.4536,5
+402.5192,3
+402.6164,3
+402.7132,1
+402.9335,5
+403.259,12
+403.309,6
+403.3876,3
+403.4753,1
+403.7147,3
+404.2269,4
+404.3108,3
+404.7374,5
+404.8113,1
+405.2131,5
+405.3333,3
+405.6795,2
+407.8732,2
+411.0067,2
+413.0218,1
+413.0892,1
+413.2335,57
+413.3035,25
+413.7328,32
+413.8081,8
+414.2228,5
+414.2828,9
+414.3424,4
+414.4356,2
+414.6094,4
+414.7199,6
+414.87,2
+416.11,3
+418.711,4
+424.4149,2
+425.287,2
+426.2268,2
+426.7227,4
+426.9637,3
+427.2246,74
+427.2997,40
+427.4115,1
+427.7239,68
+427.8436,6
+427.9177,3
+428.0482,2
+428.1411,1
+428.2242,15
+428.3137,17
+428.787,6
+429.6598,3
+430.2758,3
+432.2763,1
+433.2212,6
+435.1302,3
+435.3378,4
+443.235,2
+443.6571,1
+444.9332,3
+445.2844,5
+446.3422,2
+447.2256,2
+448.7895,3
+449.2528,3
+449.5677,1
+450.1993,3
+451.8308,3
+452.2794,3
+452.8574,3
+456.3444,3
+456.815,2
+456.893,1
+457.3382,2
+458.089,2
+460.6348,4
+460.7936,7
+460.8852,4
+461.2248,43
+461.3586,8
+461.7555,134
+462.0425,2
+462.2522,92
+462.4144,5
+462.746,21
+462.8273,5
+463.2587,9
+464.1609,3
+464.2634,1
+469.518,3
+470.3055,3
+470.7576,81
+471.1271,5
+471.2655,46
+471.4061,6
+471.7367,9
+471.8181,6
+472.0988,5
+472.2733,7
+472.5045,1
+472.5667,1
+473.0598,2
+473.6369,1
+474.4301,2
+474.6018,11
+474.6872,10
+474.9321,10
+475.0013,21
+476.3438,3
+477.5691,2
+478.7099,2
+479.9517,4
+480.0665,2
+480.3365,10
+480.4079,2
+480.64,160
+480.8394,3
+480.9711,150
+481.1419,8
+481.295,87
+481.5169,2
+481.6326,26
+481.7563,5
+481.8299,2
+481.979,5
+482.067,2
+482.3113,8
+482.4529,2
+482.7108,8
+482.9548,4
+483.0466,2
+483.1181,4
+483.2962,2
+483.4197,6
+484.2981,4
+485.0859,3
+491.204,1
+491.2662,1
+491.3383,1
+491.7874,2
+491.8846,1
+492.295,20
+492.4422,3
+493.302,5
+493.504,3
+494.313,3
+495.3706,2
+497.7738,4
+498.8301,3
+498.9969,2
+499.2101,3
+499.649,2
+500.226,3
+500.3869,342
+500.56,5
+500.7669,5
+501.0752,2
+501.3755,91
+501.4952,9
+502.2757,5
+502.3503,14
+502.4227,10
+502.5471,4
+502.6361,4
+502.8102,2
+503.4046,5
+505.4753,2
+506.4412,4
+507.7981,3
+511.2679,14
+511.3341,17
+511.4388,2
+511.7908,27
+512.3044,5
+512.5751,3
+519.3084,4
+519.7026,4
+519.8273,2
+520.2967,328
+520.6697,1
+520.7661,3
+520.8824,7
+520.9682,2
+521.2927,94
+521.7892,3
+522.0936,2
+522.2187,5
+522.3113,12
+522.4092,7
+522.7855,1
+523.2501,3
+523.3372,1
+524.1531,2
+524.7791,3
+525.3735,1
+527.2947,8
+528.2895,3
+529.1505,2
+530.6804,2
+530.7861,2
+532.306,9
+533.3033,3
+535.361,3
+552.3618,2
+553.407,2
+554.7569,2
+558.5176,2
+559.6127,1
+560.287,5
+560.4134,3
+561.2498,1
+561.3267,4
+562.8124,2
+563.2944,3
+563.4239,1
+564.8261,6
+564.9099,4
+564.976,2
+565.2759,3
+565.3707,9
+565.5305,2
+566.4214,2
+568.4691,1
+569.3346,4
+569.4058,13
+569.5019,4
+569.5747,1
+569.6475,1
+570.3633,4
+570.4498,16
+571.2965,1
+571.4195,6
+571.4758,3
+571.5784,1
+572.381,3
+572.4486,2
+572.92,4
+573.3981,3
+573.7458,4
+573.8586,67
+573.9612,21
+574.066,3
+574.3539,61
+574.4537,17
+574.5536,2
+574.8405,19
+574.9592,2
+575.3185,11
+575.4207,4
+575.5056,2
+575.5826,1
+575.6589,1
+577.3074,9
+577.4223,3
+578.1526,3
+584.5505,3
+585.3615,11
+585.4314,10
+585.5741,3
+585.6603,7
+585.9116,3
+586.0613,5
+586.388,11
+586.5022,1
+586.5732,2
+586.846,12
+587.4271,1387
+587.7023,8
+587.7939,6
+587.8698,6
+588.0663,5
+588.2092,8
+588.4289,520
+588.6898,10
+588.7769,6
+588.993,12
+589.4146,97
+589.4962,51
+589.6946,13
+589.801,3
+590.3812,16
+590.5562,5
+592.2068,4
+592.8172,1
+593.0849,2
+593.4933,3
+595.6253,2
+596.3392,4
+597.3459,1
+597.4203,3
+597.515,2
+597.9026,1
+598.2836,3
+598.3417,8
+599.1752,2
+603.2936,2
+606.1924,2
+616.592,2
+617.423,1
+624.5602,2
+637.3413,3
+638.3671,3
+639.2586,1
+639.331,1
+639.8571,3
+642.108,1
+647.2784,4
+648.3354,5
+648.4521,2
+650.7113,2
+655.2712,2
+655.3664,30
+656.3695,8
+657.3942,3
+665.3284,4
+668.3688,2
+668.4735,6
+668.6234,1
+669.4628,3
+669.8121,1
+670.5142,3
+670.5972,2
+680.7796,3
+681.3997,1
+681.4736,3
+682.3482,2
+682.4495,5
+683.3481,219
+683.4712,44
+683.6359,6
+684.0644,3
+684.3716,106
+684.5844,6
+684.8958,1
+684.9804,3
+685.3737,14
+685.4988,4
+685.7285,5
+686.0152,7
+686.1675,5
+686.5014,557
+686.9116,8
+687.2289,2
+687.3205,3
+687.4829,171
+687.5939,93
+687.8615,9
+688.3171,3
+688.4927,40
+688.5773,13
+688.6929,9
+689.2798,1
+689.3668,1
+689.4847,4
+689.593,8
+689.8995,4
+690.908,2
+696.3164,2
+696.4634,5
+696.5764,1
+697.5877,2
+699.8672,3
+707.7047,2
+708.2455,1
+709.3156,4
+709.4521,2
+715.4932,1
+723.5035,3
+725.7914,1
+726.4122,90
+727.287,1
+727.3789,21
+727.4848,20
+727.9292,2
+734.0432,2
+736.162,1
+736.3848,13
+736.5123,4
+737.3798,5
+738.4948,3
+739.3513,3
+740.5328,9
+740.6787,2
+747.4741,2
+751.2795,4
+751.5072,2
+752.3605,7
+752.7471,3
+752.9329,6
+753.1516,5
+754.0845,9
+754.4078,773
+754.6768,22
+754.8329,5
+754.9259,3
+755.0079,9
+755.3988,315
+755.5961,32
+755.8419,8
+756.1276,5
+756.2121,3
+756.4058,84
+756.5536,8
+756.6567,1
+756.7365,4
+757.0129,8
+757.1477,5
+757.5342,249
+757.8083,8
+758.149,5
+758.3525,2
+758.5118,61
+758.5903,49
+758.8855,4
+759.4818,18
+759.5482,11
+759.7332,5
+760.4133,3
+760.5503,10
+760.9072,3
+761.6349,5
+762.7632,2
+763.4514,2
+764.3829,1
+764.4747,2
+768.6735,1
+770.4442,3
+785.5863,2
+793.6028,2
+808.385,1
+808.4804,2
+825.4254,18
+825.5293,15
+826.4259,8
+826.5468,8
+827.6287,3
+838.4358,2
+845.1581,1
+853.4627,103
+853.5911,23
+853.6886,16
+854.4817,49
+854.5994,22
+854.7208,4
+855.4445,15
+855.6116,1
+855.7076,1
+856.5129,2
+859.6588,1
+860.5162,2
+902.6061,5
+902.6943,2
+903.626,4
+903.7915,1
+905.4571,2
+913.6252,1
+915.7272,3
+917.6539,2
+920.3547,3
+920.5964,139
+920.7654,36
+920.9797,2
+921.5889,89
+921.7524,38
+922.0116,1
+922.1476,3
+922.4272,17
+922.5228,33
+922.6741,27
+922.817,4
+923.1877,1
+923.5013,29
+923.6208,5
+924.4304,4
+924.6093,6
+932.7939,2
+940.4985,30
+940.5948,8
+940.7292,6
+940.8721,3
+941.397,4
+941.5469,12
+941.7205,6
+1012.576,4
+1039.495,12
+1039.615,6
+1039.692,3
+1039.85,1
+1040.467,6
+1040.583,9
+1049.522,9
+1049.63,14
+1049.709,10
+1050.543,4
+1050.646,7
+1050.765,5
+1051.748,4
+1147.636,3
+1148.107,1
+1152.559,3
+1253.329,1
+FragModelIonMatchListEnd
+FragModelIonAlignment=0
diff --git a/MwtZip/Lang_English.ini b/MwtZip/Lang_English.ini
new file mode 100644
index 0000000..7e7e042
--- /dev/null
+++ b/MwtZip/Lang_English.ini
@@ -0,0 +1,1021 @@
+; Language customization file for the Molecular Weight Calculator program by Matthew Monroe
+; Contact at alchemistmatt@yahoo.com and http://come.to/alchemistmatt/ or http://www.alchemistmatt.com/
+;
+; When customizing the phrases in this file, the ampersand symbol (&) signifies a
+; keyboard shortcut. For example, the default value for key 1000 is &File. When
+; running the program, the F in File will be underlined and the user may press Alt-F
+; to access the File menu (in addition to clicking on the file menu)
+; To improve usability of the program, please try to include the & symbol in menu items
+; and buttons. Note, however, that if two controls on the same form have the same &
+; shortcut, they will not respond to the alt key in the usual way.
+;
+; In this file, items surround by brackets [] are section headers -- the program ignores them
+; when parsing the file. The key values (1000, 1010, 1020, etc.) should not be changed, with
+; the exception that new caution statements may be added at the end of the file.
+; Lines beginning with a semicolon (;) are also ignored since they are treated as comments
+; However, you should not place a ; at the end of a line with an actual key and caption.
+;
+; Keys with multiple values separated by a vertical line (|) represent multiple items loaded
+; into a ComboBox control. When translating to other languages, you must keep the same number
+; of items in the list, or program functionality will be lost. For example, key 7070 contains
+; hours|minutes|seconds Thus, hours, minutes, and seconds will be loaded into a control, from
+; which the user may select one of them. In Spanish, you would use 7070=horas|segundos|minutos
+;
+; If you create a new .Ini file for a foreign language and would like it posted on my
+; web page, simply e-mail it to me.
+
+; Original English version
+; For Molecular Weight Calculator v6.0
+
+[Language]
+Language=English
+
+
+[frmMain Menus]
+; Menu Items
+1000=&File
+1010=Edit &Elements Table
+1020=Edit &Abbreviations
+1030=&Calculate weights from text file
+1040=&Print Results
+1050=E&xit
+1500=&Edit
+1510=Cu&t
+1520=&Copy
+1530=&Paste
+1540=&Delete
+1550=Copy Current Formula as &RTF
+1560=Copy Current &Molecular Weight
+1570=Copy P&ercent Composition Data
+1580=Duplicate Current &Formula
+1590=Erase &All Formulas
+1600=Erase Current Formula
+1610=E&xpand Abbreviations
+1620=Convert to Empirical F&ormula
+2000=&View
+2010=&Multi View
+2020=&Single View
+2030=&Percent Solver
+2040=O&ff
+2050=&On
+2500=&Tools
+2510=&Mole/Mass/Dilution Converter
+2520=&Formula Finder
+2530=&Amino Acid Notation Converter
+2533=&Peptide Sequence Fragmentation Modelling
+2536=&Isotopic Distribution Modelling
+2538=Show Isotopic &Distribution for Current Formula
+2540=Math &Calculator
+2550=Capillar&y Flow Calculator
+3000=&Options
+3010=Choose &Language
+3020=Change Program &Preferences
+3030=Change &Formula Font
+3040=Stay on &Top
+3050=&Save and Restore Default Values
+3060=&Restore Default Values and Formulas
+3070=Save &Values and Formulas Now
+3500=&Help
+3510=&Program Overview
+3530=&Show Tool Tips
+3540=&About MWT
+
+[frmMain Status Messages and Verification Messages]
+3600=The entire line is
+3605=Zooming
+3610=Are you sure you want to convert the current formula into its empirical formula?
+3615=Convert to Empirical Formula
+3620=Are you sure you want to erase the current formula?
+3625=Erase Current Formula
+3630=Are you sure you want to expand the abbreviations of the current formula to their elemental equivalents?
+3635=Expand Abbreviations
+3640=Restoring the default values and formulas will clear the current formulas. Are you sure you want to do this?
+3645=Restoring Values and Formulas
+3650=Set the Percent Solver target percentage of this element to a percentage. Select Reset to un-target the percentage or Cancel to ignore any changes.
+3660=Use Page Up/Down or Up/Down arrows to move to the percents (F11 exits Percent Solver mode).
+3665=Press Enter or Click to change a percentage (F11 exits Percent Solver Mode).
+3670=Ready
+3700=Calculating, press any key or click the mouse to stop.
+3710=x is
+3720=Calculated Value
+3730=Target
+3740=Difference from Target
+3750=% Solver On
+3760=Molecular Weight Calculator Results
+3770=Default values and formulas restored.
+3780=Are you sure you want to erase all the formulas?
+3785=Erase all Formulas
+3790=Are you sure you want to quit?
+3795=Exiting Program
+3800=Loading Abbreviations
+3810=Loading Elements
+3820=(using average atomic weights)
+3830=(using isotopic elemental weights)
+3840=(using integer isotopic weights)
+3850=New default language saved.
+
+[Phrases common throughout application]
+4000=Cl&ose
+4010=&Ok
+4020=&Cancel
+4030=E&xit
+; The following is the abbreviation for Molecular Weight
+; It must be exactly two letters long
+4040=MW
+4050=Caution
+
+[frmMain]
+; Form Caption
+4900=Molecular Weight Calculator
+; Labels
+5000=Formula
+5010=Quick Switch Element Mode
+5020=&Average
+5021=Use average weights of elements
+5030=&Isotopic
+5031=Use weight of most common isotope
+5040=Inte&ger
+5041=Use nominal integer weight of most common isotope
+; TextBoxes
+5051=Type the molecular formula here
+; Buttons
+5100=&Calculate
+5101=Determines the molecular weight of the current formula
+5110=&New Formula
+5111=Adds a new, blank formula to the list
+5116=Displays a new, blank formula
+; Grid control
+5201=Click to set or reset a target value
+; Status control
+5301=Double click the status line to expand it
+5350=The Molecular Weight Calculator is already running. Are you sure you want to start another copy?
+5355=Already Running
+
+[frmAboutBox]
+5500=About MWT
+5510=This program is Freeware; distribute freely
+
+[frmIntro]
+5700=Loading
+
+[frmAminoAcidConverter]
+; Form Caption
+6000=Amino Acid Notation Converter
+; Labels
+6010=One letter-based amino acid sequence
+6020=Three letter-based amino acid sequence
+; TextBoxes
+6031=Enter sequence using 1 letter abbreviations here
+6041=Enter sequence using 3 letter abbreviations here
+; Buttons
+6050=&Copy 3 letter sequence to formula:
+6060=Copy to &Fragmentation Modeller
+; CheckBoxes
+6080=&Add space every 10 residues
+6090=&Separate residues with dash
+
+[frmCalculator]
+; Form caption
+6500=Calculator
+; Textbox
+6511=Enter a mathematical expression to evaluate here
+; Buttons
+6520=&Calculate
+6521=Evaluates the current expression
+; Status control
+6601=Double click the status line to expand it
+6610=Result
+
+[frmCapillaryCalcs]
+; Form Caption
+7000=Capillary Flow and Mass Rate Calculations
+; Combo Boxes
+7010=Open Tubular Capillary|Packed Capillary
+7011=Toggle between open and packed capillaries.
+7020=Find Back Pressure|Find Column Length|Find Inner Diameter|Find Volumetric Flow rate|Find Flow Rate using Dead Time
+7030=psi|Pascals|kiloPascals|Atmospheres|Bar|Torr (mm Hg)
+7035=um|inches
+7040=Poise [g/(cm-sec)]
+7050=mL/min|uL/min|nL/min
+7060=cm/hr|mm/hr|cm/min|mm/min|cm/sec|mm/sec
+7070=hours|minutes|seconds
+7080=mL|uL|nL|pL
+7090=Molar|milliMolar|microMolar|nanoMolar|picoMolar|femtoMolar|attoMolar|mg/mL|ug/mL|ng/mL|ug/uL|ng/uL
+7100=pmol/min|fmol/min|amol/min|pmol/sec|fmol/sec|amol/sec
+7110=Moles|milliMoles|microMoles|nanoMoles|picoMoles|femtoMoles|attoMoles
+; Labels and frames
+7200=Back Pressure
+7210=Column Length
+7220=Column Inner Diameter
+7230=Solvent Viscosity
+7240=Particle Diameter
+7250=Volumetric Flow Rate
+7260=Linear Velocity
+7270=Column Dead Time
+7280=Column Volume
+7290=Interparticle Porosity (epsilon)
+7300=Mass Rate Calculations
+7310=Sample Concentration
+7320=Injection Time
+7330=Mass Flow Rate
+7340=Moles Injected
+7350=Extra Column Broadening Calculations
+7360=Diffusion Coefficient
+7370=Open Tube Length
+7380=Open Tube I.D.
+7390=Initial Peak Width
+7400=Optimum Linear Velocity
+7410=(for 5 um particles)
+7420=Temporal Variance
+7430=Additional Variance
+7440=Resulting Peak Width
+7450=Percent Increase
+7460=Current Formula is
+7480=Custom Mass
+7500=cm
+7520=cm^2/sec
+7530=sec (at base)
+7540=cm/sec
+7550=sec^2
+7560=sec
+7570=g/mole
+; TextBoxes
+7601=Enter custom numerical mass for use in computations
+; Buttons
+7700=Show/Hide &Peak Broadening Calculations
+7710=&View Explanatory Equations
+7730=View Equations
+; Option Buttons
+7750=&Use mass of compound in current formula
+7760=&Enter custom numerical mass
+; CheckBoxes
+7800=&Link to Above
+; ToolTips
+7851=Typical viscosity value is 0.0089 poise
+7861=Typical porosity value is 0.4
+7871=Typical diffusion coefficient for small organics is 0.00001, i.e. 1E-5; Typical value for peptides is 0.000005, i.e. 5E-6
+; Menus
+7900=&Load Values
+7910=&Save Values
+7950=&Capillary Flow Calculations
+
+[frmChangeFont]
+; Form Caption
+8000=Change Formula Font
+; Combo Boxes
+; Labels
+8050=Formula Font is currently
+8060=Change Formula Font to:
+8070=Font Size:
+; Buttons
+
+[frmChangeValue]
+; Form Caption
+8200=Change Value
+; Buttons
+8210=&Reset to Default
+
+[frmChangeLanguage]
+8400=Choose Language
+; Labels
+8410=Available languages are shown below. Please choose the language you wish to use.
+8420=No language files are available. Visit the author's homepage to download alternate languages.
+
+[frmDiff]
+8600=Percent Solver Differences
+8610=&Copy
+8611=Copies the results to the clipboard
+
+[frmEditAbbrev]
+9000=Editing Abbreviations
+; Buttons
+9010=&Reset to Defaults
+9011=Resets abbreviations to the program defaults
+9020=&Remove
+; Messages
+9050=Maximum reached
+9060=Sorry, only 50 amino acid abbreviations are allowed.
+9070=Sorry, only 50 normal abbreviations are allowed.
+9080=Please add the entry as a normal abbreviation.
+9090=The abbreviation or molecular formula will be changed to the value you type. Select Remove to delete the abbreviation or Cancel to ignore any changes.
+9100=Are you sure you want to lose all changes?
+9105=Closing Edit Abbreviations Box
+9110=Are you sure you want to reset the abbreviations to the default abbreviations?
+9115=Reset to Defaults
+;Table Tool Tip
+9140=
+9141=Click to change an abbreviation
+; Table Column Titles
+9150=Charge
+9160=Molecular Formula
+9170=Normal Abbrev.
+9180=Amino Acid Name
+9190=1 letter
+
+[frmEditElem]
+9200=Editing Elements
+; Buttons
+9210=&Reset to Defaults
+9211=Resets elemental weights to their average weights
+9220=&Reset
+9230=Use &Average atomic weights
+9231=Sets all elemental weights to their average weights found in nature
+9240=Use weight of most common &Isotope
+9241=Sets all elemental weights to the weight of the element's most common isotope (for high resolution mass spectrometry)
+9245=Use &Nominal integer weight
+9246=Sets all elemental weights to the nominal integer weight of the element's most common isotope (for low resolution mass spectrometry)
+; Messages
+9250=The elemental weight or uncertainty will be changed to the value you type. Select Reset to reset to the default value or Cancel to ignore any changes.
+9260=Are you sure you want to reset all the values to their average elemental weights?
+9265=Change to Average Weights
+9270=Are you sure you want to reset all the values to their isotopic elemental weights?
+9275=Change to Isotopic Weights
+9280=Are you sure you want to reset all the values to their integer weights?
+9285=Change to Integer Weights
+9290=Are you sure you want to reset all the values to the default Elemental values (average weights)?
+9295=Reset to Defaults
+9300=If executed, this cannot be canceled.
+9310=Are you sure you want to lose all changes?
+9315=Closing Edit Elements Box
+;Table Tool Tip
+9340=
+9341=Click to change an element's weight or uncertainty
+;Table Column Titles
+9350=Element
+9360=Weight
+9370=Uncertainty
+; Combo boxes
+9380=Element Symbol|Atomic Number|Uncertainty|Charge
+9390=Sort Elements by:
+
+[frmEquationsBroadening]
+9500=Extra-column broadening equations
+
+[frmEquationsOpenTube]
+9550=Equations for flow in an open tube
+
+[frmEquationsPackedCapillary]
+9600=Equations for flow in a packed capillary
+
+[frmFinderModeWarn]
+; Instructions Label
+9700=The typical use of the Formula Finder feature is for when the monoisotopic mass (weight) of a compound is known (typically determined by Mass Spectrometry) and potential matching compounds are to be searched for.
+9701=For example, a mass of 16.0312984 Daltons is measured for a compound containing Carbon and Hydrogen, and the possible empirical formula is desired. Performing the search, with a weight tolerance of 5000 ppm results in three compounds, H2N, CH4, and O. Within 500 ppm only CH4 matches, which is the correct match.
+9702=To correctly achieve use this feature, the program must be set to Isotopic Weight mode. This can be done manually by choosing Edit Elements Table under the File menu, or the program can automatically switch to this mode for you.
+9703=Would you like to:
+9705=The typical use of the Fragmentation Modelling feature is for predicting the masses expected to be observed with a Mass Spectrometer when a peptide is ionized, enters the instrument, and fragments along the peptide backbone.
+9706=The peptide typically fragments at each amide bond. For example, the peptide Gly-Leu-Tyr will form the fragments Gly-Leu, Leu-Tyr, Gly, Leu, and Tyr. Additionally, the cleavage of the amide bond can occur at differing locations, resulting in varying weights.
+; Buttons
+9720=&Continue
+; Option Buttons
+9750=Switch to &Isotopic Weight mode now.
+9760=Always automatically switch to Isotopic &Weight mode.
+9770=Continue using &Average Weights.
+; CheckBoxes
+9780=&Stop showing this warning dialog.
+
+[frmFinder]
+10000=Formula Finder
+; Labels
+10010=Select appropriate elements or add your own, enter a molecular weight or percent compositions, then select calculate to find compounds that match the specifications.
+10020=Maximum Weight of Formula:
+10030=Molecular Weight of Target:
+10040=Weight Tolerance:
+10050=Percent Tolerance:
+10060=Min
+10070=Max
+10080=Element
+10090=Percent
+10100=Max Hits
+10105=Atomic Wt.
+; Percent completed status messages
+10110=% Completed
+10115=Sorting
+10120=Searching
+10125=Working
+10130=Completed
+10135=compounds
+10140=Sorting Interrupted
+10145=Calculations Interrupted
+10150=Formatting
+10155=Done
+10160=Formatting aborted
+; Listboxes & Textboxes
+10201=Double click any line to expand it
+10221=Amount that target compound's weight can be from the target weight
+10231=Amount that elemental percent compositions can be from the target percentage
+10241=Maximum number of target compounds to find
+10251=Minimum number of atoms in target compound
+10256=Maximum number of atoms in target compound
+10260=Percent
+10261=Percent composition of target compound that is
+10270=# or Element or Abbrev.
+10271=Type a weight for the custom element, an elemental symbol, or an abbreviation
+; Note the following is 'dm' in English, standing for 'delta mass' or the mass difference
+; of the given result's mass versus the target mass
+10280=dm
+; Note the following is 'ppm' in English, standing for 'parts per million'
+10285=ppm
+; Buttons
+10300=Formul&a Finder Options
+10301=Shortcut: Ctrl+O
+10310=&Calculate
+10311=Find the compounds that match the specified parameters
+10320=Prin&t ...
+10330=Copy as RT&F
+10331=Copy results to clipboard in Rich Text Format
+10340=Cop&y
+10341=Copy results to clipboard
+10345=&Display Iso Abundance
+10346=Display the Isotopic Distribution of the currently selected compound (Ctrl+D)
+; Option Buttons
+10350=Match &Molecular Weight
+10360=Match &Percent Compositions
+; CheckBoxes
+10370=Ppm Mode
+; Elements (and Custom element phrase)
+10400=Carbon
+10405=Hydrogen
+10410=Nitrogen
+10415=Oxygen
+10420=Custom
+; Messages
+10450=A key was pressed.
+10455=Abort
+10460=The mouse was clicked outside the results box.
+10465=Stopping formatting.
+10470=Stopping sort.
+10480=The sum of the percent compositions is not 100%.
+10485=Continue with calculation?
+10490=Cannot Calculate
+10500=A key was pressed.
+10505=The mouse was clicked outside the results box.
+10510=Stopping calculations.
+10515=The maximum number of hits has been reached.
+10520=Maximum Hits
+10530=Compounds found
+; Note: the following is used when displaying the results of a percent composition
+; search in the formula finder. A synonym for 'has' would be 'contains' or 'is composed of'
+10535=has
+10540=A memory error has occurred. The results list is probably full. Results so far are shown.
+10545=Out of Memory
+10550=The results box is empty.
+10555=Nothing to Copy
+10560=Nothing to Print
+10565=Are you sure you want to print the current result(s)?
+10570=Printing
+
+[frmFinderOptions]
+10800=Finder Options
+; Labels
+10810=Use the checkboxes to select various options for the Formula Finder.
+; Textboxes & Comboboxes
+10821=Minimum charge to limit compounds to
+10831=Maximum charge to limit compounds to
+10840=Thorough Search|Bounded Search
+10841=A thorough search finds all matching compounds while a bounded search finds compounds within a specific atomic range (thorough is usually faster).
+10850=Sort by Formula
+10851=Method to sort results. Re-calculate to re-sort.
+10855=Sort by Charge
+10860=Sort by MWT
+10865=Sort by m/z
+10870=Mass/Charge Ratio of Target
+10875=Molecular Weight of Target
+; CheckBoxes
+10900=Find &Charge
+10901=Compute the overall charge of each compound found
+10910=Limit Charge &Range
+10911=Limit the displayed compounds to a specific charge range
+10920=Find m/&z
+10921=Compute the mass to charge ratio for each compound found
+10930=Find &Target m/z
+10931=Find compounds with m/z values equivalent to the target
+10940=So&rt Results
+10941=Convert results to empirical formulas and sort them
+10950=&Smart H atoms
+10951=Limit number of hydrogen atoms in found compounds to a realistic number
+10960=&Automatically adjust Min and Max in bounded search.
+10961=Automatically adjust the Min and Max search values to a valid range for the given target weight
+
+[frmMMconvert]
+11000=Mole/Mass Converter and Dilution Calculator
+; Combo Boxes
+11010=Convert Amounts|Find Concentration|Dilution Calculations
+11011=Perform conversions between different amounts of compound or perform molarity-related calculations
+11020=Moles|Millimoles|microMoles|nanoMoles|picoMoles|femtoMoles|attoMoles|Kilograms|Grams|Milligrams|Micrograms|Pounds|Ounces|Microliters|Milliliters|Liters|Gallons|Quarts|Pints
+11021=Units of amount to convert from
+11026=Units of amount to use for concentration calculation
+11030=Microliters|Milliliters|Liters|Gallons|Quarts|Pints
+11031=Units of volume
+11041=Units of amount to convert to
+11051=Units of concentration
+; Labels
+11080=g/mL
+; Textboxes
+11101=Amount of compound to convert from
+11106=Amount of compound to be dissolved in solvent
+11111=Density of the compound
+11121=Volume of solvent the compound is dissolved in
+11131=Concentration of compound in the solvent
+; Buttons
+11150=Find &Amount
+11151=Calculate the amount using the volume and concentration
+11160=Find &Volume
+11161=Calculate the volume using the amount and concentration
+11170=Find &Concentration
+11171=Calculate the concentration using the amount and volume
+
+; Dilution-related controls
+11200=Dilution Calculations
+11205=Evaporation or Sublimation Calculations
+11210=Find Required Dilution Volumes|Find Required Total Volume|Find Final Concentration|Find Initial Concentration
+11211=Quantity to find for dilution calculations
+11220=&Link Initial Dilution Concentration and Convert Amounts Concentration
+11221=Copy the Computed Concentration for converting amounts to the Initial Concentration for dilutions and vice versa if either changes
+11230=Link Dilution Volume Units
+11231=Synchronize the units for the Volume of Stock, Volume of Solvent, and Final Total Volume
+; Dilution related labels and textbox tooltips
+11250=&Initial Concentration
+11256=Concentration of solute in stock solution
+11260=Volume of &Stock Solution
+11266=Volume (aliquot) of stock solution to remove when performing dilution
+11270=&Final Concentration
+11276=Concentration of solute in final solution following dilution
+11280=Volume of Solvent used for &Dilution
+11286=Volume of solvent to mix with the stock solution (aliquot) removed for dilution
+11290=&Total Final Volume
+11296=Total volume of the final solution following mixing of stock and diluting solvent
+
+[frmProgramPreferences]
+11500=Molecular Weight Calculator Preferences
+; Frame labels
+11510=Abbreviation Mode (F3)
+11520=Case Recognition Mode (F4)
+11530=Standard Deviation Mode (F12)
+11540=Advanced Tools Weight Mode Options
+11550=Exit Program Options
+; Buttons
+11600=&Save options as defaults
+11610=&Restore default options
+; Option Buttons
+11650=Normal
+11651=Recognize normal abbreviations, but not amino acids
+11655=Normal + Amino Acids
+11656=Recognize normal abbreviations and amino acids
+11660=Off
+11661=Ignore all abbreviations
+11665=Convert Case Up
+11666=Correctly capitalize formulas while parsing
+11670=Exact Case
+11671=Require user to type formulas with correct capitalization
+11675=Smart Case
+11676=Interpret lowercase formulas, and do not capitalize them
+11680=Short
+11681=Display standard deviations in abbreviated form
+11685=Scientific
+11686=Display standard deviations in scientific notation
+11690=Decimal
+11691=Display standard deviations in long decimal form
+11695=Off
+11696=Do not display standard deviations
+11700=Exit on Escape with confirmation
+11701=Determines if the escape key exits program and whether to confirm program exit
+11705=Exit on Escape without confirmation
+11710=Ignore escape key but confirm exit
+11715=Ignore escape key and do not confirm exit
+; CheckBoxes
+11750=Ad&vance on Calculate (F9)
+11751=Move to a new formula line after calculating a formula's weight
+11760=Treat &Brackets as Parentheses
+11761=Treat brackets, [ and ], as parentheses, rather than as percent solver placeholders
+11770=A&uto Copy Current Molecular Weight (Ctrl+U)
+11771=Automatically copy the selected formula's molecular weight value to the clipboard after each calculation
+11780=Compute Char&ge
+11781=Compute charge of compounds (very basic rules, cannot correct for double or triple bonds, etc.)
+11800=Always switch to &Isotopic Mode automatically
+11801=Switch to isotopic weights automatically upon entering the formula finder or peptide fragmentation module
+11810=&Never show the weight mode warning dialog
+11811=Never prompt about current weight mode when entering the formula finder or peptide fragmentation module
+11820=&Autosave options, values, and formulas on exit
+11821=Automatically save options, values, and formulas on program exit
+11830=Show Caution Statements (F7)
+11831=Caution when possibly confusing elemental combinations are in formulas (like Co vs. CO)
+11840=Show Element Mode &Quick Switch
+11841=Show option to quickly change elemental weight modes
+11850=Show Tool Tips
+11851=Show short help messages when mouse passes over certain buttons and areas
+11860=Highlight Text Fields when Selected
+11861=Highlight the entire text field when moving to it
+11870=&Hide inactive program windows
+11871=Hide the main program window when using the Formula Finder, Mole/Mass calculator, etc.
+11881=Choose a smaller number to prevent the formula window from filling the screen. If lowering, must exit and restart program before takes effect. Maximum is dependent upon screen resolution.
+11885=Maximum number of formulas to display
+11890=Module to show at startup
+11896=Module to show when the program starts
+11898=Main Window|Formula Finder|Capillary Flow Calculator|Mole/Mass Converter|Peptide Sequence Fragmentation Modeller|Amino Acid Notation Converter|Isotopic Distribution Modeller
+
+; Messages
+11900=Autosave values option saved.
+11910=Default options restored.
+11920=Values and formulas saved.
+11925=Values and formulas NOT saved since /X command line option was used.
+11930=Default options saved.
+11935=Default options NOT saved since /X command line option was used.
+
+[frmFragmentationModelling]
+12000=Peptide Sequence Fragmentation Modelling
+; General Combo Boxes
+12010=1 letter notation|3 letter notation
+12011=Amino acid sequence notation type
+12020=&Match Ions
+; Textboxes
+12051=Enter amino acid sequence here
+12061=Shifts the loaded ions to be matched by the given amount to correct for post-translational modifications.
+; Frames, labels, and checkboxes
+12100=Sequence:
+12150=N and C Terminus
+12160=&N
+12170=&C
+12180=H
+12190=OH
+12200=Ion Types
+12210=&A Ions
+12215=&B Ions
+12220=&Y Ions
+12230=Neutral Losses
+12236=Choose ions to which losses will be applied
+12240=Loss of H2O
+12250=Loss of NH3
+12260=Charge Options
+12270=&2+ charged ions
+12280=&Threshold
+12286=The 2+ m/z value will be computed for ions above this m/z
+12300=Ion Match Options
+12310=&Remove Precursor Ion
+12320=Ion Mass
+12330=Mass Window
+12340=&Ion Matching Window
+12350=Da
+12355=Alignment &Offset
+12360=Ion Statistics
+12370=Loaded
+12375=Remaining after binning
+12380=Within tolerance
+12385=Precursor not found
+12390=Precursor removed
+12395=Precursor not removed
+12400=Matches
+12405=Score
+
+; Column titles in grids
+; Note: # means 'number', Immon. means 'immonium', and Seq. means 'sequence'
+12500=#
+12510=Immon.
+12520=Seq.
+12550=Mass
+12560=Intensity
+
+; Ion Types (must be exactly one letter long)
+12600=a
+12610=b
+12620=y
+
+; Menu Items
+12800=&Load Sequence Info
+12810=&Save Sequence Info
+12820=Load List of &Ions to Match
+12830=&Close
+12840=&Copy Predicted Ions
+12850=Copy Predicted Ions as &RTF
+12855=Copy Predicted Ions as Html
+12860=&Paste List of Ions to Match
+12870=Clear Match Ion &List
+12880=List of &Ions to Match
+12900=Predicted &Mass Spectrum
+12910=&Update Spectrum on Change
+12920=Ion Match List &Options
+12930=&Automatically Align Ions to Match
+12940=&Fragmentation Modelling
+
+[frmMsPlot]
+13000=Plot
+; The following is an abbreviation for the word 'Location'
+13010=Loc
+
+; Legend Items
+13030=Predicted Ions
+13035=Loaded Ions
+
+; Menu Items
+13100=&Export Data
+13150=&Plot Type
+13160=&Sticks To Zero
+13170=&Gaussian Peaks
+13180=Set Effective &Resolution
+13190=X Axis Gridlines
+13200=Y Axis Gridlines
+13210=&Ticks to label (approx.)
+13220=&X Axis
+13230=&Y Axis
+13235=Plot &Quality (affects speed)
+13240=&Gaussian Representation Quality
+13245=&Approximation Factor
+13250=Set &X Range
+13260=Set &Y Range
+13270=&Autoscale Y Axis
+13280=&Fix mimimum Y at zero
+13290=&Zoom Out to Previous
+13295=Ctrl+Z or Right Click
+13300=Zoom Out to Show All
+13310=&Cursor Mode
+13315=Space Enables Move
+13320=&Zoom
+13330=&Move
+13340=&Show Current Position
+13342=Show &Legend
+13345=Reset to &Default Options
+13350=&Zoom Box
+13360=Zoom &In
+13365=Left Click
+13370=Zoom In Horizontal
+13380=Zoom In Vertical
+13390=Zoom &Out
+13400=Zoom Out Horizontal
+13410=Zoom Out Vertical
+
+[frmIonMatchOptions]
+14000=Ion Matching Options
+; Buttons
+14010=&Reset to Defaults
+
+; Explanations
+14050=When a list of ions is imported into the program, ions of similar mass may optionally be grouped together via a binning process to reduce the total number of data points. Next, ions around the precursor ion may be removed.
+14055=Then, the intensities are normalized to the given maximum intensity and ordered by decreasing intensity. The top-most ions (number of ions to use) are divided into distinct mass regions and the ions in each region again normalized.
+14060=The masses of the predicted ions for a given peptide sequence are easily computed. However, intensity values must also be assigned to the masses.
+14065=The B and Y ions are typically assigned the same intensity while the A ion is typically 5 times less intense. Shoulder ions (masses ± 1 Da from the B and Y ions) can be added, in addition to including neutral losses (H2O and NH3).
+
+; Frames, labels, and checkboxes
+14100=Normalization Options for Imported Data
+14110=&Group Similar Ions (Bin Data)
+14115=Mass Window
+14120=Normalized Intensity
+14130=Number of Ions to Use
+14140=Mass region subdivisions
+14150=Ion Intensities of Predicted Ions
+14160=A Ion Intensity
+14165=B Ion Intensity
+14170=Y Ion Intensity
+14180=B/Y Ion Shoulders
+14190=Neutral Losses
+
+[frmSetValue]
+14500=Set Value
+14510=&Set
+14520=&Start
+
+[frmProgress]
+14700=Progress
+14710=Click to Pause
+14715=Preparing to Pause
+14720=Paused
+14725=Resuming
+14730=(Press Escape to abort)
+14740=min. elapsed/remaining
+
+[frmIsotopicDistibution]
+15000=Isotopic Distribution
+; Frames, labels, and checkboxes
+15050=Formula:
+15060=Results:
+15100=&Plot Results
+15110=&Compute
+15151=Isotopic distribution results
+
+[ErrorAndStatusMessages]
+20001=Unknown element
+20003=Missing closing parentheses
+20004=Unmatched parentheses
+20005=Cannot have a 0 directly after an element or dash (-)
+20006=Number too large or must only be after [, -, ), or caret (^)
+20007=Number too large
+20011=Numbers should follow left brackets, not right brackets (unless 'treat brackets' as parentheses is on)
+20012=A number must be present after a bracket and/or after the decimal point
+20013=Missing closing bracket, ]
+20014=Misplaced number; should only be after an element, [, ), -, or caret (^)
+20015=Unmatched bracket
+20016=Cannot handle nested brackets or brackets inside multiple hydrates (unless 'treat brackets as parentheses' is on)
+20018=Unknown element
+20020=There must be an isotopic mass number following the caret (^)
+20022=An element must be present after the isotopic mass after the caret (^)
+20023=Negative isotopic masses are not allowed after the caret (^)
+20024=Isotopic masses are not allowed for abbreviations
+20025=An element must be present after the leading coefficient of the dash
+20026=Isotopic masses are not allowed for abbreviations; D is an abbreviation
+20027=Numbers cannot contain more than one decimal point
+20028=Abbreviations cannot be present in the definition for an abbreviation
+20050=Target value is greater than 100%, an impossible value.
+20075=Letters are not allowed in the calculator line
+20076=Missing closing parenthesis
+20077=Unmatched parentheses
+20078=Misplaced number; or number too large, too small, or too long
+20080=Misplaced operator
+20081=Track variable is less than or equal to 1; program bug; please notify programmer
+20082=Missing operator.
+20085=Cannot take negative numbers to a decimal power
+20086=Cannot take zero to a negative power
+20087=Cannot take zero to the zeroth power
+20089=A single positive or negative number must be present after a caret (^)
+20090=Numbers cannot contain more than one decimal point
+20091=You tried to divide a number by zero. Please correct the problem and recalculate.
+20092=Spaces are not allowed in mathematical expressions
+20093=Use a period for a decimal point
+20094=Use a comma for a decimal point
+20095=A number must be present after a decimal point
+20100=Error Saving Abbreviation File
+20110=The default abbreviation file has been re-created.
+20115=The old file has been renamed
+20120=[AMINO ACIDS] heading not found in MWT_ABBR.DAT file. This heading must be located before/above the [ABBREVIATIONS] heading.
+20125=Select OK to continue without any abbreviations.
+20130=[ABBREVIATIONS] heading not found in MWT_ABBR.DAT file. This heading must be located before/above the [AMINO ACIDS] heading.
+20135=Select OK to continue with amino acids abbreviations only.
+20140=The Abbreviations File was not found in the program directory
+20150=Error Loading/Creating Abbreviation File
+20160=Ignoring Abbreviation -- Invalid Formula
+20170=Ignoring Duplicate Abbreviation
+20180=Ignoring Abbreviation; Invalid Character
+20190=Ignoring Abbreviation; too long
+20200=Ignoring Invalid Line
+20210=The default elements file has been re-created.
+20220=Possibly incorrect weight for element
+20230=Possibly incorrect uncertainty for element
+20250=Ignoring Line; Invalid Element Symbol
+20260=[ELEMENTS] heading not found in MWT_ELEM.DAT file. This heading must be located in the file.
+20265=Select OK to continue with default Element values.
+20270=The Elements File was not found in the program directory
+20280=Error Loading/Creating Elements File
+20305=Continuing with default captions.
+20320=Error Saving Elements File
+20330=Error Loading/Creating Values File
+20340=Select OK to continue without loading default Values and Formulas.
+20345=If using a Read-Only drive, use the /X switch at the command line to prevent this error.
+20350=Error
+20360=Error Saving Default Options File
+20370=If using a Read-Only drive, you cannot save the default options.
+20380=Error Saving Values and Formulas File
+20390=If using a Read-Only drive, you cannot save the values and formulas.
+20400=Error Loading/Creating Default Options File
+20410=Select OK to continue without loading User Defaults.
+20440=The language file could not be successfully opened or was formatted incorrectly.
+20450=Unable to load language-specific captions
+20460=The language file could not be found in the program directory
+20470=The file requested for molecular weight processing was not found
+20480=File Not Found
+20490=This file already exists. Replace it?
+20500=File Exists
+20510=Error Reading/Writing files for batch processing
+20515=Select OK to abort batch file processing.
+20520=Error in program
+20530=These lines of code should not have been encountered. Please notify programmer.
+20540=You can't edit elements because the /X switch was used at the command line.
+20545=You can't edit abbreviations because the /X switch was used at the command line.
+20550=Percent solver cannot be used when brackets are being treated as parentheses. You can change the bracket recognition mode by choosing Change Program Preferences under the Options menu.
+20555=Percent Solver not Available
+20560=Maximum number of formula fields exist.
+20570=Current formula is blank.
+20580=Turn off Percent Solver (F11) before creating a new formula.
+20590=An overflow error has occured. Please reduce number sizes and recalculate.
+20600=An error has occured
+20605=Please exit the program and report the error to the programmer. Select About from the Help menu to see the E-mail address.
+20610=Spaces are not allowed in formulas
+20620=Invalid Character
+20630=Cannot copy to new formula.
+20650=Current formula is blank.
+20655=Percent Solver mode is on (F11 to exit mode).
+20660=Warning, isotopic mass is probably too large for element
+20662=Warning, isotopic mass is probably too small for element
+20665=vs avg atomic wt of
+20670=Warning, isotopic mass is impossibly small for element
+20675=protons
+20680=Note: Exact Case Mode is on
+20685=Note: for % Solver, a left bracket must precede an x
+20690=Note: brackets are being treated as parentheses
+20700=One or more elements must be checked.
+20705=Maximum hits must be greater than 0.
+20710=Maximum hits must be less than
+20715=Minimum number of elements must be 0 or greater.
+20720=Minimum number of elements must be less than maximum number of elements.
+20725=Maximum number of elements must be less than 65,025
+20730=An atomic weight must be entered for custom elements.
+20735=Atomic Weight must be greater than 0 for custom elements.
+20740=Target molecular weight must be entered.
+20745=Target molecular weight must be greater than 0.
+20755=A maximum molecular weight must be entered.
+20760=Maximum molecular weight must be greater than 0.
+20765=Target percentages must be entered for element
+20770=Target percentage must be greater than 0.
+20775=Custom elemental weights must contain only numbers or only letters. If letters are used, they must be for a single valid elemental symbol or abbreviation.
+20780=Custom elemental weight is empty. If letters are used, they must be for a single valid elemental symbol or abbreviation.
+20785=Unknown element or abbreviation for custom elemental weight
+20790=Only single elemental symbols or abbreviations are allowed.
+20800=Caution, no abbreviations were loaded -- Command has no effect.
+
+20900=Error Reading/Writing sequence information file.
+20910=Ions are already present in the ion list. Replace with new ions?
+20920=Replace Existing Ions
+20930=Loading Ion List
+20940=Process aborted
+20945=Aborted
+20950=Normalizing ions
+20960=Normalizing by region
+20965=Sorting by Intensity
+20970=Matching Ions
+20980=The clipboard is empty. No ions to paste.
+20985=No ions
+20990=Pasting ion list
+21000=Determining number of ions in list
+21010=Parsing list
+21020=No valid ions were found on the clipboard. A valid ion list is a list of mass and intensity pairs, separated by commas, tabs, or spaces. One mass/intensity pair should be present per line.
+21030=Error writing data to file
+21040=Set Range
+21050=Start Val
+21055=End Val
+21060=Set X Axis Range
+21065=Set Y Axis Range
+21070=Enter a new Gaussian Representation quality factor. Higher numbers result in smoother Gaussian curves, but slower updates. Valid range is 1 to 50, default is 20.
+21072=Gaussian Representation Quality
+21075=Enter a new plotting approximation factor. Higher numbers result in faster updates, but give a less accurate graphical representation when viewing a wide mass range (zoomed out). Valid range is 1 to 50, default is 10.
+21077=Plotting Approximation Factor
+21080=Resolving Power Specifications
+21090=Resolving Power
+21100=X Value of Specification
+21110=Please enter the approximate number of ticks to label on the axis
+21115=Axis Ticks
+21120=Creating Gaussian Representation
+21130=Preparing plot
+21135=Drawing plot
+21140=Are you sure you want to restore the default plotting options?
+21145=Restore Default Options
+21150=Auto Align Ions
+21155=Maximum Offset
+21160=Offset Increment
+21165=Aligning Ions
+
+21500=All Files
+21510=Text Files
+21515=txt
+21520=Data Files
+21525=csv
+21530=Sequence Files
+21535=seq
+21540=Ion List Files
+21545=txt
+21550=cap
+21555=Capillary Flow Info Files
+
+[CautionStatments]
+; Note: Caution statement keynames are case sensitive; i.e. Bi is different than BI
+; You may add new caution statements if desired; however, you will need to save
+; the file with a name other than Lang_English and change the Language= key
+; since this file is not loaded if the language is English
+22000=Caution
+Bi=Bi means bismuth; BI means boron-iodine.
+Bk=Bk means berkelium; BK means boron-potassium.
+Bu=Bu means the butyl group; BU means boron-uranium.
+Cd=Cd means cadmium; CD means carbon-deuterium.
+Cf=Cf means californium; CF means carbon-fluorine.
+Co=Co means cobalt; CO means carbon-oxygen.
+Cs=Cs means cesium; CS means carbon-sulfur.
+Cu=Cu means copper; CU means carbon-uranium.
+Dy=Dy means dysprosium; DY means deuterium-yttrium.
+Hf=Hf means hafnium; HF means hydrogen-fluorine.
+Ho=Ho means holmium; HO means hydrogen-oxygen.
+In=In means indium; IN means iodine-nitrogen.
+Nb=Nb means niobium; NB means nitrogen-boron.
+Nd=Nd means neodymium; ND means nitrogen-deuterium.
+Ni=Ni means nickel; NI means nitrogen-iodine.
+No=No means nobelium; NO means nitrogen-oxygen.
+Np=Np means neptunium; NP means nitrogen-phosphorus.
+Os=Os means osmium; OS means oxygen-sulfur.
+Pd=Pd means palladium; PD means phosphorus-deuterium.
+Ph=Ph means phenyl, PH means phosphorus-hydrogen.
+Pu=Pu means plutonium; PU means phosphorus-uranium.
+Py=Py means pyridine; PY means phosphorus-yttrium.
+Sb=Sb means antimony; SB means sulfor-boron.
+Sc=Sc means scandium; SC means sulfur-carbon.
+Si=Si means silicon; SI means sulfur-iodine.
+Sn=Sn means tin; SN means sulfor-nitrogen.
+TI=TI means tritium-iodine, Ti means titanium.
+Yb=Yb means ytterbium; YB means yttrium-boron.
+BPY=BPY means boron-phosphorus-yttrium; Bpy means bipyridine.
+BPy=BPy means boron-pyridine; Bpy means bipyridine.
+Bpy=Bpy means bipyridine.
+Cys=Cys means cysteine; CYS means carbon-yttrium-sulfur.
+His=His means histidine; HIS means hydrogen-iodine-sulfur.
+Hoh=HoH means holmium-hydrogen; HOH means hydrogen-oxygen-hydrogen (aka water).
+Hyp=Hyp means hydroxyproline; HYP means hydrogen-yttrium-phosphorus.
+OAc=OAc means oxygen-actinium; Oac means acetate.
+Oac=Oac means acetate.
+Pro=Pro means proline; PrO means praseodymium-oxygen.
+PrO=Pro means proline; PrO means praseodymium-oxygen.
+Val=Val means valine; VAl means vanadium-aluminum.
+VAl=Val means valine; VAl means vanadium-aluminum.
diff --git a/MwtZip/Lang_German.ini b/MwtZip/Lang_German.ini
new file mode 100644
index 0000000..7883415
--- /dev/null
+++ b/MwtZip/Lang_German.ini
@@ -0,0 +1,1022 @@
+; Language customization file for the Molecular Weight Calculator program by Matthew Monroe
+; Contact at alchemistmatt@yahoo.com and http://come.to/alchemistmatt/ or http://www.alchemistmatt.com/
+;
+; When customizing the phrases in this file, the ampersand symbol (&) signifies a
+; keyboard shortcut. For example, the default value for key 1000 is &File. When
+; running the program, the F in File will be underlined and the user may press Alt-F
+; to access the File menu (in addition to clicking on the file menu)
+; To improve usability of the program, please try to include the & symbol in menu items
+; and buttons. Note, however, that if two controls on the same form have the same &
+; shortcut, they will not respond to the alt key in the usual way.
+;
+; In this file, items surround by brackets [] are section headers -- the program ignores them
+; when parsing the file. The key values (1000, 1010, 1020, etc.) should not be changed, with
+; the exception that new caution statements may be added at the end of the file.
+; Lines beginning with a semicolon (;) are also ignored since they are treated as comments
+; However, you should not place a ; at the end of a line with an actual key and caption.
+;
+; Keys with multiple values separated by a vertical line (|) represent multiple items loaded
+; into a ComboBox control. When translating to other languages, you must keep the same number
+; of items in the list, or program functionality will be lost. For example, key 7070 contains
+; hours|minutes|seconds Thus, hours, minutes, and seconds will be loaded into a control, from
+; which the user may select one of them. In Spanish, you would use 7070=horas|segundos|minutos
+;
+; If you create a new .Ini file for a foreign language and would like it posted on my
+; web page, simply e-mail it to me.
+
+; German translation provided by Stefan Flueler; University of Zurich and Institute of Polytechnics
+; Please, report German translation errors to translator at fluss@bluewin.ch
+
+[Language]
+;version: b0
+Language=Deutsch
+
+[frmMain Menus]
+; Menu Items
+1000=&Datei
+1010=&Elemententafel bearbeiten
+1020=&Abkürzungen bearbeiten
+1030=&Gewichte gemäss Textdatei berechnen
+1040=&Resultat drucken
+1050=&Beenden
+1500=&Bearbeiten
+1510=&Ausschneiden
+1520=&Kopieren
+1530=&Einfügen
+1540=&Löschen
+1550=Aktuelle &Formel als RTF kopieren
+1560=Aktuelles &Molekulargewicht kopieren
+1570=Prozentuale &Zusammensetzung kopieren
+1580=Aktuelle Formel &duplizieren
+1590=Alle Formeln lö&schen
+1600=A&ktuelle Formel löschen
+1610=A&bkürzungen erweitern
+1620=Z&ur Summenformel konvertieren
+2000=&Ansicht
+2010=&Mehrfachformeln-Eingabe
+2020=&Einzelformel-Eingabe
+2030=&% - Ermittler umschalten
+2040=AU&S
+2050=EI&N
+2500=&Werkzeuge
+2510=&Mol/Masse-Konverter
+2520=&Formel-Finder
+2530=&Aminosäure Notations-Konverter
+2533=&Peptide Sequence Fragmentation Modelling
+2536=&Isotopic Distribution Modelling
+2538=Show Isotopic &Distribution for Current Formula
+2540=&Taschenrechner
+2550=&Kapillarfluss-Kalkulator
+3000=&Optionen
+3010=Sprach-&Auswahl (Language)
+3020=&Programm-Einstellungen ändern
+3030=&Schriftart ändern
+3040=&Immer im Vordergrund
+3050=&Zurücksetzen oder Speichern
+3060=Zurücksetzen auf &Voreinstellung
+3070=&Aktuelle Einstellungen und Formeln speichern
+3500=&Hilfe
+3510=&Programm Ueberblick
+3530=&Hinweise einblenden
+3540=&Ueber den Molekulargewicht-Kalkulator
+
+[frmMain Status Messages and Verification Messages]
+3600=Vollständiger Text der Statuszeile:
+3605=Erweiterte Ansicht
+3610=Wollen Sie die aktuelle Formel wirklich zur Summenformel reduzieren?
+3615=Reduziere zur Summenformel
+3620=Wollen Sie die aktuelle Formel wirklich löschen?
+3625=Lösche aktuelle Formel
+3630=Wollen Sie die Abkürzungen der aktuellen Formel wirklich durch ihre Aequivalente ersetzen?
+3635=Abkürzungen durch Aequivalente ersetzen
+3640=Zurücksetzen auf die Voreinstellung löscht alle aktuellen Eingaben. Wollen Sie das?
+3645=Auf Voreinstellung zurücksetzen
+3650=Ziel-Anteil für dieses Element eingeben, nach welchem der %-Ermittler die Anteile der andern Elemente berechnen soll.
+3660=Cursor Auf/Ab oder Seite Auf/Ab benutzen um die einzelnen Element-Anteile zu erreichen (F11 schaltet %-Ermittler EIN/AUS).
+3665=Enter-Taste drücken oder Wert anklicken, um ihn zu ändern (F11 schaltet %-Ermittler EIN/AUS).
+3670=Bereit
+3700=Berechnung läuft, mit Maus- oder Tastaturtaste abbrechen.
+3710=x =
+3720=Berechneter Wert
+3730=Ziel-Wert
+3740=Abweichung vom Ziel-Wert
+3750=% - Ermittler EIN
+3760=Resultate des Molekulargewicht-Kalkulators
+3770=Auf voreingestellte Werte und Formeln zurückgesetzt
+3780=Wollen Sie wirklich alle Formeln löschen?
+3785=Alle Formeln löschen
+3790=Wollen Sie das Programm wirklich verlassen?
+3795=Programm verlassen
+3800=Liste der Abkürzungen laden
+3810=Liste der Elemente laden
+3820=(Durchschnittliche Atomgewichte verwendet)
+3830=(Isotopenreine Atomgewichte verwendet)
+3840=(Ganzzahlige Atomgewichte verwendet)
+3850=Neue Sprache abgespeichert
+
+[Phrases common throughout application]
+4000=&Schliessen
+4010=&OK
+4020=&Ignorieren
+4030=&Beenden
+; The following is the abbreviation for Molecular Weight
+; It must be exactly two letters long
+4040=MG
+4050=Vorsicht
+
+[frmMain]
+; Form Caption
+4900=Molekulargewicht-Kalkulator
+; Labels
+5000=Formel
+5010=Schnellwahl der Atomgewichte
+5020=D&urchschnitt
+5021=Durchschnittliche Atomgewichte der Elemente verwenden
+5030=&Isotopenrein
+5031=Gewichte der häufigsten Isotope verwenden
+5040=&Ganzzahlig
+5041=Auf ganze Zahlen gerundete Gewichte der Elemente verwenden
+; TextBoxes
+5051=Formel der Verbindung hier eingeben
+; Buttons
+5100=Be&rechnen
+5101=Berechnet das Molekulargewicht der aktuellen Formel
+5110=&Neue Formel
+5111=Fügt ein neues Formel-Eingabefeld zur Liste hinzu
+5116=Erzeugt ein neues, leeres Formel-Eingabefeld
+; Grid control
+5201=Anklicken, um Ziel-Wert neu zu setzen oder rückgängig zu machen
+; Status control
+5301=Statuszeile doppelklicken, um ganze Zeile zu sehen
+5350=Molekulargewicht-Kalkulator ist schon gestartet. Wollen Sie wirklich noch einen zweiten starten?
+5355=Bereits gestartet
+
+[frmAboutBox]
+5500=Ueber MWT (Molekulargewicht-Kalkulator)
+5510=Dieses Programm ist Freeware; gratis + frei verwendbar
+
+[frmIntro]
+5700=Laden...
+
+[frmAminoAcidConverter]
+; Form Caption
+6000=Aminosäuren Notations-Konverter
+; Labels
+6010=Einbuchstabige Aminosäure-Sequenz
+6020=Dreibuchstabige Aminosäure-Sequenz
+; TextBoxes
+6031=Hier Sequenz mit einem Buchstaben pro Säure eingeben
+6041=Hier Sequenz mit dreibuchstabiger Abkürzung pro Säure eingeben
+; Buttons
+6050=&Kopiere dreibuchstabige Sequenz in die Formel:
+6060=Copy to &Fragmentation Modeller
+; CheckBoxes
+6080=&Pro Zehnergruppe Leerschlag einfügen
+6090=&Säuren mit Bindestrichen separieren
+
+[frmCalculator]
+; Form caption
+6500=Taschenrechner
+; Textbox
+6511= Mathematischen Ausdruck zur Berechnung eingeben
+; Buttons
+6520=&Berechnen
+6521=Berechnet den aktuellen mathematischen Ausdruck
+; Status control
+6601=Statuszeile doppelklicken, um ganze Zeile zu sehen
+6610=Resultat
+
+[frmCapillaryCalcs]
+; Form Caption
+7000=Kapillar- und Massenfluss-Kalkulation
+; Combo Boxes
+7010=Offenrohrige Kapillare|Gefüllte Kapillare
+7011=Umschalten zwischen offenrohriger und gefüllter Kapillare
+7020=Berechne Gegendruck|Berechne Kolonnenlänge|Berechne Innendurchmesser|Berechne volumetrische Durchflussrate|Berechne Durchflussrate mittels Totzeit
+7030=psi|Pascal|kiloPascal|Atmosphären|Bar|Torr (mm Hg)
+7035=um|inches
+7040=Poise [g/(cm-sec)]
+7050=mL/min|uL/min|nL/min
+7060=cm/h|mm/h|cm/min|mm/min|cm/s|mm/s
+7070=Stunden|Minuten|Sekunden
+7080=mL|uL|nL|pL
+7090=Molar|milliMolar|mikroMolar|nanoMolar|picoMolar|femtoMolar|attoMolar|mg/mL|ug/mL|ng/mL|ug/uL|ng/uL
+7100=pmol/min|fmol/min|amol/min|pmol/s|fmol/s|amol/s
+7110=Mol|milliMol|mikroMol|nanoMol|picoMol|femtoMol|attoMol
+; Labels and frames
+7200=Gegendruck
+7210=Kolonnen-Länge
+7220=Kolonnen-Innendurchmesser
+7230=Lösungsmittelviskosität
+7240=Teilchendurchmesser
+7250=Volumetrische Durchflussrate
+7260=Lineare Geschwindigkeit
+7270=Kolonnen-Totzeit
+7280=Kolonnen-Volumen
+7290=Interpartikel-Porosität (epsilon)
+7300=Massendurchfluss-Berechnung
+7310=Probenkonzentration
+7320=Injektionszeit
+7330=Massendurchfluss
+7340=Injizierte Menge
+7350=Berechnung der zusätzlichen Kolonnen-Aufweitung
+7360=Diffusions-Koeffizient
+7370=Offenrohr-Länge
+7380=Offenrohr-Innendurchmesser
+7390=Anfängliche Peak-Breite
+7400=Opt. lin. Geschwindigkeit
+7410=(für 5 um Teilchen)
+7420=Zeitliche Varianz
+7430=Zusätzliche Varianz
+7440=Resultierende Peak-Breite
+7450=Prozentualer Anstieg
+7460=Die aktuelle Formel ist
+7480=Freigewählte Masse
+7500=cm
+7520=cm^2/s
+7530=s (at base)
+7540=cm/s
+7550=s^2
+7560=s
+7570=g/mol
+; TextBoxes
+7601=Freigewählte numerische Masse als Berechnungsgrundlage eingeben
+; Buttons
+7700=Wechsle von/zu &Peak-Verbreiterungs-Maske
+7710=&Zeige Beispielgleichungen
+7730=Zeige Gleichungen
+; Option Buttons
+7750=M&asse der Verbindung in der aktuellen Formel benutzen
+7760=&Freigewählte numerische Masse eingeben
+; CheckBoxes
+7800=&Mit Obigem koppeln
+; ToolTips
+7851=Typischer Viskositätswert ist 0.0089 poise
+7861=Typischer Porositätswert ist 0.4
+7871=Typischer Diffusionskoeffizient für kleine organische Moleküle ist 0.000001, d.h. 1E-6; Typical value for peptides is 0.00005, d.h. 5E-5
+; Menus
+7900=&Load Values
+7910=&Save Values
+7950=&Capillary Flow Calculations
+
+[frmChangeFont]
+; Form Caption
+8000=Schriftart der Formel ändern
+; Combo Boxes
+; Labels
+8050=Die aktuelle Schriftart der Formel ist
+8060=Aendere die Formel-Schriftart auf:
+8070=Grösse:
+; Buttons
+
+[frmChangeValue]
+; Form Caption
+8200=Wert ändern
+; Buttons
+8210=&Zurücksetzen
+
+[frmChangeLanguage]
+8400=Sprache wählen
+; Labels
+8410=Die verfügbaren Sprachmodule sind unten angezeigt. Bitte wählen Sie die gewünschte Sprache aus:
+8420=Es sind keine weiteren Sprachmodule vorhanden. Besuchen Sie die Homepage des Autors um zusätzliche Sprachen herunterzuladen.
+
+[frmDiff]
+8600=%-Ermittler Abweichungen
+8610=&Kopieren
+8611=Resultate in die Zwischenablage kopieren
+
+[frmEditAbbrev]
+9000=Abweichungen bearbeiten
+; Buttons
+9010=&Zurücksetzen
+9011=Setzt die Abweichungen zurück auf die Voreinstellungen des Programms
+9020=&Entfernen
+; Messages
+9050=Das Maximum ist erreicht
+9060=Es sind leider nur 50 Abkürzungen für Aminosäuren erlaubt.
+9070=Es sind leider nur 50 Abkürzungen für Typische Verbindungen erlaubt.
+9080=Fügen Sie bitte die Eingabe als Abkürzung einer Typischen Verbindung ein.
+9090=Die Abkürzung oder Molekülformel wird durch den eingetippten Wert ersetzt. Mit 'Entfernen' Abkürzung löschen, mit 'Ignorieren' Aenderungen rückgängig machen.
+9100=Wollen Sie wirklich alle Aenderungen rückgängig machen?
+9105=Fenster zur Bearbeitung von Abkürzungen schliessen
+9110=Wollen Sie die Abkürzungen wirklich auf die Voreinstellungen zurücksetzen?
+9115=Auf Voreinstellungen zurücksetzen
+;Table Tool Tip
+9140=
+9141=Anklicken, um die Abkürzung zu ändern
+; Table Column Titles
+9150=Ladung
+9160=Molekulare Formel
+9170=Typische Abkürzung
+9180=Aminosäure Abkürzung
+9190=1 letter
+
+[frmEditElem]
+9200=Elemente bearbeiten
+; Buttons
+9210=&Zurücksetzen
+9211=Setzt die Gewichte der Element auf ihren Durchschnittswert zurück
+9220=&Zurücksetzen
+9230=&Durchschnittliche Atomgewichte verwenden
+9231=Setzt die Gewichte aller Elemente zurück auf den in der Natur vorgefundenen Durchschnittswert
+9240=&Häufigstes Isotopengewicht verwenden
+9241=Setzt die Gewichte aller Elemente auf diejenigen ihrer am häufigsten vorkommenden Isotope (für Massenspektrometrie mit hoher Auflösung)
+9245=&Ganzzahliges Atomgewicht verwenden
+9246=Setzt die Gewichte aller Elemente auf diejenige ganze Zahl, die ihren tatsächlichen Atomgewichten am nächsten ist (für Massenspektrometrie mit tiefer Auflösung)
+; Messages
+9250=Das Gewicht des Elements oder deren Unschärfe wird auf den eingetippten Wert geändert. Mit 'Zurücksetzen' wird der Wert auf die Voreinstellung zurückgesetzt, Mit 'Ignorieren' werden die Aenderungen wieder verworfen.
+9260=Wollen Sie wirklich alle Atomgewichte auf deren durchschnittlichen Wert zurücksetzen?
+9265=Auf durchschnittliche Atomgewichte ändern
+9270=Wollen Sie wirklich alle Atomgewichte auf die Werte ihrer häufigsten Isotope setzen?
+9275=Auf Isotopenreine Werte ändern
+9280=Wollen Sie wirklich alle Atomgewichte auf deren ganzzahligen Wert runden?
+9285=Auf ganzzahlige Werte ändern
+9290=Wollen Sie wirklich alle Werte der Elemente auf die voreingestellten Durchschnittswerte zurücksetzen?
+9295=Zurücksetzen auf Voreinstellung
+9300=Dieser Vorgang kann nicht rückgängig gemacht werden.
+9310=Wollen Sie wirklich alle diese Aenderungen rückgängig machen?
+9315=Fenster zur Bearbeitung der Elemente schliessen
+;Table Tool Tip
+9340=
+9341=Anklicken, um das Atomgewicht oder dessen Unschärfe bei einem Element zu ändern
+;Table Column Titles
+9350=Element
+9360=Atomgewicht
+9370=Unschärfe
+; Combo boxes
+9380=Element Symbol|Atom Nummer|Unschärfe|Ladung
+9390=Sortiere Elemente nach:
+
+[frmEquationsBroadening]
+9500=Gleichungen für die zusätzliche Kolonnen-Aufweitung
+
+[frmEquationsOpenTube]
+9550=Flussgleichungen für offene Rohre
+
+[frmEquationsPackedCapillary]
+9600=Flussgleichungen für gefüllte Rohre
+
+[frmFinderModeWarn]
+; Instructions Label
+9700=Das Formel-Finder-Werkzeug wird gewöhnlich dazu benutzt, um bei bekannter mono-isotopischer Masse (Gewicht) einer zu identifizierenden Verbindung (üblicherweise durch Massenspektrometrie ermittelt), passende bekannte Verbindungen zu suchen,
+9701=Angenommen, bei einer unbekannten Verbindung, die Kohlenstoff und Wasserstoff enthält, wird eine Masse von 16.0312984 Daltons gemessen. Nun möchte man auf empirische Weise eine plausible Formel finden. Die Suche ergibt innerhalb einer Toleranzbreite von 5000ppm drei Verbindungen, H2N, CH4 und O. Innerhalb 500 ppm passt nur CH4, was auch die richtige Verbindung ist.
+9702=Um die korrekte Antwort zu bekommen, muss das Programm die Atomgewichte der häufigsten Isotope verwenden. Dafür ist der Umschalter zwischen den drei verschiedenen Atomgewichten (durchschnittlich, isotopenrein, ganzzahlig) vorgesehen.
+9703=Wollen Sie im Formel-Finder:
+9705=The typical use of the Fragmentation Modelling feature is for predicting the masses expected to be observed with a Mass Spectrometer when a peptide is ionized, enters the instrument, and fragments along the peptide backbone.
+9706=The peptide typically fragments at each amide bond. For example, the peptide Gly-Leu-Tyr will form the fragments Gly-Leu, Leu-Tyr, Gly, Leu, and Tyr. Additionally, the cleavage of the amide bond can occur at differing locations, resulting in varying weights.
+; Buttons
+9720=&Weiterfahren
+; Option Buttons
+9750=die Atomgewichte der häufigsten Isotope verwenden.
+9760=Immer automatisch die Atomgewichte der häufigsten Isotope verwenden.
+9770=Weiterhin die Durchschnitts-Atomgewichte verwenden.
+; CheckBoxes
+9780=&Diesen Hinweis nicht mehr anzeigen.
+
+[frmFinder]
+10000=Formel-Finder
+; Labels
+10010=Vorgegebene oder selbstgewählte Elemente auswählen, Ziel-Molekulargewicht oder Ziel-Zusammensetzung eingeben, 'Suchen' findet passende Verbindungen.
+10020=Maximales Gewicht der Formel:
+10030=Gesuchtes Molekulargewicht:
+10040=Max. Gewichtsabweichung:
+10050=Max. Abweichung der Anteile in %:
+10060=Min.
+10070=Max.
+10080=Element
+10090=Prozent
+10100=Höchstzahl Gefundene
+10105=Atomgew.
+; Percent completed status messages
+10110=% abgearbeitet
+10115=Sortiere ...
+10120=Suche ...
+10125=Arbeite ...
+10130=Fertig
+10135=Verbindungen
+10140=Sortieren abgebrochen
+10145=Berechnung abgebrochen
+10150=Formatiere ...
+10155=Ausgeführt
+10160=Formatieren abgebrochen
+; Listboxes & Textboxes
+10201=Linie zur Ansicht doppelklicken
+10221=Tolerierte Abweichung des Gewichts vom Ziel-Gewicht in Prozent ( ppm-Modus: in Teilen pro Million )
+10231=Tolerierte Abweichung der Element-Anteile von der Ziel-Zusammensetzung in Prozent
+10241=Anzahl Treffer, nach denen die Suche automatisch beendet wird
+10251=Minimalzahl Atome pro Verbindung
+10256=Maximalzahl Atome pro Verbindung
+10260=Prozent
+10261=Anteil am Gesamtgewicht in Prozent,
+10270=Nummer oder Element oder Abkürzung.
+10271=Gewicht, Element-Symbol oder Abkürzung des selbstgewählten Elementes eingeben
+; Note the following is 'dm' in English, standing for 'delta mass' or the mass difference
+; of the given result's mass versus the target mass
+10280=dm
+; Note the following is 'ppm' in English, standing for 'parts per million'
+10285=ppm
+; Buttons
+10300=&Formel-Finder Einstellungen
+10301=Tastenkombination: Ctrl+O
+10310=S&uchen
+10311=Findet die Verbindungen, welche mit den Angaben übereinstimmen
+10320=&Drucken ...
+10330=&Als RTF kopieren
+10331=Kopiert die Resultate im Rich Text Format in die Zwischenablage
+10340=&Kopieren
+10341=Kopiert die Resultate in die Zwischenablage
+10345=&Display Iso Abundance
+10346=Display the Isotopic Distribution of the currently selected compound (Ctrl+D)
+; Option Buttons
+10350=Nach &Molekulargewicht suchen
+10360=Nach &Zusammensetzung suchen
+; CheckBoxes
+10370=ppm-Modus
+; Elements (and Custom element phrase)
+10400=K&ohlenstoff
+10405=W&asserstoff
+10410=S&tickstoff
+10415=Saue&rstoff
+10420=Erweiterung
+; Messages
+10450=Eine Taste wurde gedrückt.
+10455=Abbruch
+10460=Es wurde neben das Resultatfenster geklickt.
+10465=Formatieren gestoppt.
+10470=Sortieren gestoppt.
+10480=Die Summe der Anteile ist nicht 100%.
+10485=Suche weiterführen?
+10490=Keine Suche möglich
+10500=Eine Taste wurde gedrückt.
+10505=Es wurde neben das Resultatfenster geklickt.
+10510=Suche gestoppt.
+10515=Die Maximalzahl Gefundene ist erreicht.
+10520=Maximalzahl Gefundene
+10530=Gefundene Verbindungen
+; Note: the following is used when displaying the results of a percent composition
+; search in the formula finder. A synonym for 'has' would be 'contains' or 'is composed of'
+10535=enthält
+10540=Ein Speicherfehler ist aufgetreten. Wahrscheinlich ist die Liste der Resultate voll. Resultat der bisherigen Suche wird angezeigt.
+10545=Speicherüberlauf
+10550=Es gibt keine Resultate.
+10555=Nichts zu kopieren
+10560=Nichts zu drucken
+10565=Wollen Sie die aktuellen Resultate wirklich ausdrucken?
+10570=Drucken ...
+
+[frmFinderOptions]
+10800=Formel-Finder Einstellungen
+; Labels
+10810=Mit Hilfe der Schalter und Kombo-Boxen diverse Optionen des Formel-Finders einstellen.
+; Textboxes & Comboboxes
+10821=Minimale Ladung, welche die gefundenen Verbindungen aufweisen müssen
+10831=Maximale Ladung, welche die gefundenen Verbindungen aufweisen müssen
+10840=Vollständige Suche|Begrenzte Suche
+10841=Eine vollständige Suche findet alle passenden Verbindungen, während eine begrenzte Suche nur Verbindungen innerhalb eines bestimmten Bereichs findet (vollständig ist gewöhnlich schneller).
+10850=Sortiere nach Formel
+10851=Sortiermethode für die Resultate. Zum Nachsortieren erneut berechnen.
+10855=Sortiere nach Ladung
+10860=Sortiere nach Masse
+10865=Sortiere nach m/Q-Verhältnis
+10870=Gesuchtes Masse/Ladungs-Verhältnis
+10875=Gesuchtes Molekulargewicht
+; CheckBoxes
+10900=Berechne &Ladung
+10901=Berechne die Gesamtladung jeder gefundenen Verbindung
+10910=Begrenze Ladungs&bereich
+10911=Begrenze die angezeigten Verbindungen auf einen vordefinierten Ladungsbereich
+10920=Berechne m/&Q
+10921=Berechne das Masse/Ladungs-Verhältnis für jede gefundene Verbindung
+10930=O&ptimiere m/Q
+10931=Finde Verbindungen mit einem Masse/Ladungs-Verhältnis, das dem gesuchten entspricht
+10940=Sortiere die &Resultate
+10941=Konvertiere die Resultate zu empirischen Formeln und sortiere sie
+10950=&Intelligente H-Atome
+10951=Begrenze die Anzahl Wasserstoff-Atome in gefundenen Verbindungen auf eine physikalisch mögliche Zahl
+10960=&Min. und Max. Werte bei einer begrenzten Suche automatisch anpassen.
+10961=Die Minimal- und Maximalwerte bei einer Suche automatisch auf den gültigen Bereich des gesuchten Gewichts einstellen.
+
+[frmMMconvert]
+11000=Mol/Massen-Konverter
+; Combo Boxes
+11010=Konvertiere Einheiten|Berechne Konzentrationen|Dilution Calculations
+11011=Umwandeln zwischen diversen Mengeneinheiten oder Molaritäten berechnen
+11020=Mol|milliMol|mikroMol|nanoMol|picoMol|femtoMol|attoMol|Kilogramm|Gramm|Milligramm|Mikrogramm|Pounds|Ounces|Mikroliter|Milliliter|Liter|Gallons|Quarts|Pints
+11021=Mengeneinheit, aus welcher konvertiert wird
+11026=Mengeneinheit, welche bei Konzentrationsberechnungen verwendet wird
+11030=Mikroliter|Milliliter|Liter|Gallons|Quarts|Pints
+11031=Volumeneinheiten
+11041=Mengeneinheit, in welche konvertiert wird
+11051=Mengeneinheit, welche in der Molaritätsberechnung verwendet wird
+; Labels
+11080=g/mL
+; Textboxes
+11101=Menge der Verbindung, welche konvertiert wird
+11106=Menge der Verbindung, die im Lösungsmittel gelöst ist
+11111=Spezifische Dichte der Verbindung
+11121=Volumen des Lösungsmittels, in dem die Verbindung gelöst ist
+11131=Konzentration der Verbindung im Lösungsmittel
+; Buttons
+11150=&Menge ermitteln
+11151=Berechne die Menge gemäss Konzentrations- und Volumen-Angabe
+11160=&Volumen ermitteln
+11161=Berechne das Volumen gemäss Mengen- und Konzentrations-Angabe
+11170=&Konzentration ermitteln
+11171=Berechne die Konzentration gemäss Volumen- und Mengen-Angabe
+
+; Dilution-related controls
+11200=Dilution Calculations
+11205=Evaporation or Sublimation Calculations
+11210=Find Required Dilution Volumes|Find Required Total Volume|Find Final Concentration|Find Initial Concentration
+11211=Quantity to find for dilution calculations
+11220=&Link Initial Dilution Concentration and Convert Amounts Concentration
+11221=Copy the Computed Concentration for converting amounts to the Initial Concentration for dilutions and vice versa if either changes
+11230=Link Dilution Volume Units
+11231=Synchronize the units for the Volume of Stock, Volume of Solvent, and Final Total Volume
+; Dilution related labels and textbox tooltips
+11250=&Initial Concentration
+11256=Concentration of solute in stock solution
+11260=Volume of &Stock Solution
+11266=Volume (aliquot) of stock solution to remove when performing dilution
+11270=&Final Concentration
+11276=Concentration of solute in final solution following dilution
+11280=Volume of Solvent used for &Dilution
+11286=Volume of solvent to mix with the stock solution (aliquot) removed for dilution
+11290=&Total Final Volume
+11296=Total volume of the final solution following mixing of stock and diluting solvent
+
+[frmProgramPreferences]
+11500=Molekulargewicht-Kalkulator -> Einstellungen
+; Frame labels
+11510=Wahl der Erkennungsart von Abkürzungen (F3):
+11520=Wahl der Interpretationsart der Schreibweise (F4):
+11530=Wahl der Standard-Abweichung (F12):
+11540=Wahl des Atomgewicht-Modus beim Formel-Finder:
+11550=Beendigungsart des Programms
+; Buttons
+11600=&Einstellungen abspeichern
+11610=&Zurücksetzen
+; Option Buttons
+11650=Typische
+11651=Alle Abkürzungen ausser Aminosäuren erkennen
+11655=Aminosäuren + Typische
+11656=Alle Abkürzungen inklusive Aminosäuren erkennen
+11660=Ausschalten
+11661=Keine Abkürzungen erkennen
+11665=Klein- in Grossbuchstaben umwandeln
+11666=Gross/Kleinschreibung während des Einlesens der Formel wenn nötig anpassen
+11670=Exakte Gross/Kleinschreibung
+11671=Erfordert vom Benutzer die Eingabe der Formeln in korrekter Gross/Kleinschreibung
+11675=Automatische Erkennung
+11676=Kann beliebig geschriebene Formeln erkennen, ohne die Gross/Kleinschreibung anzupassen
+11680=Kurz
+11681=Die Anzeige der Standard-Abweichung wird auf vier Dezimalstellen gerundet
+11685=Wissenschaftlich
+11686=Die Standard-Abweichung wird in wissenschaftlicher Notation angezeigt
+11690=Dezimal
+11691=Die Standard-Abweichung wird mit allen verfügbaren Dezimalstellen angezeigt
+11695=Ausschalten
+11696=Die Standard-Abweichung wird nicht angezeigt (nur ganzzahlige Ergebnisse)
+11700=Bei Verlassen Escape-Taste zulassen, Bestätigung verlangen
+11701=Ermittelt, ob das Programm mittels Escape-Taste verlassen werden darf, und ob eine Bestätigung dafür verlangt werden soll
+11705=Escape-Taste zulassen, keine Bestätigung verlangen
+11710=Escape-Taste ignorieren; gegen Bestätigung beenden
+11715=Escape-Taste ignorieren; ohne Bestätigung beenden
+; CheckBoxes
+11750=&Nach Kalkulation weiterfahren (F9)
+11751=Nach der Berechnung eines Formelgewichtes zusätzliche neue Eingabelinie einrichten
+11760=&Betrachte Eckige Klammern als Runde Klammern
+11761=Behandle Eckige Klammern [ und ] als Runde Klammern, und nicht als Statthalter für den %-Ermittler
+11770=&Aktuelles Molekulargewicht automatisch kopieren (Ctrl+U)
+11771=Kopiere das Molekulargewicht der selektierten Formel nach der Kalkulation automatisch in die Zwischenablage
+11780=Berechne die &Ladung
+11781=Berechne die Ladung von Verbindungen (sehr rudimentär, kann keine Doppel- oder Dreifachbindungen etc erkennen)
+11800=Au&tomatisches Umschalten in den Isotopenreinen Gewichtsmodus
+11801=Schalte automatisch um zu isotopischen Atomgewichten, sobald der Formel-Finder gestartet wird
+11810=&Formel-Finder Gewichtsmodus-Warndialog auschalten
+11811=Zeige nie den Warnhinweis auf den aktuellen Gewichtsmodus beim Starten des Formel-Finders
+11820=A&m Ende automatisch Optionen, Werte, Formeln abspeichern
+11821=Beim Verlassen des Programms automatisch alle Einstellungen, Werte, und Formeln abspeichern
+11830=Zeige &Warn-Hinweise in der Statuszeile (F7)
+11831=Vorsicht vor Verwechslungen bei bestimmten Buchstaben-Kombinationen in der Formeleingabe (etwa Co gegen CO)
+11840=Zeige &den Atomgewicht-Schnellumschalter
+11841=Anzeige eines Schnellumschalters für die drei Atomgewichts-Modi unter der Formel-Eingabe
+11850=&Hinweise einblenden
+11851=Anzeige kurzer Hilfe-Texte beim Ueberfahren der Bedienelemente und Eingabefelder mit der Maus
+11860=A&ngewählte Textfelder hervorheben
+11861=Hebt das ganze Textfeld hervor, wenn es angewählt (mit der Maus angefahren) wird
+11870=&Verstecke inaktive Programmfenster
+11871=Verstecke das Hauptprogrammfenster, wenn Werkzeugfenster gestartet werden (zB Formel-Finder, Mol/Masse-Kalkulator, etc.)
+11881=Wählen Sie eine kleinere Zahl, falls das Formelfenster den Bildschirm zu sehr füllt. Nach Verminderung der Zahl muss das Programm neu gestartet werden. Die Maximalzahl hängt von der Bildschirmauflösung ab.
+11885=Maximalzahl anzeigbare Formeln.
+11890=Module to show at startup
+11896=Module to show when the program starts
+11898=Main Window|Formula Finder|Capillary Flow Calculator|Mole/Mass Converter|Peptide Sequence Fragmentation Modeller|Amino Acid Notation Converter|Isotopic Distribution Modeller
+
+; Messages
+11900=Autosave Option für die Einstellungen gespeichert.
+11910=Auf Voreinstellungen zurückgesetzt.
+11920=Werte und Formeln gespeichert.
+11925=Werte und Formeln NICHT gespeichert, weil /x Kommandozeilen-Parameter aktiv.
+11930=Eingestellte Optionen gespeichert.
+11935=Eingestellte Optionen NICHT gespeichert, weil /x Kommandozeilen-Parameter aktiv.
+
+[frmFragmentationModelling]
+12000=Peptide Sequence Fragmentation Modelling
+; General Combo Boxes
+12010=1 letter notation|3 letter notation
+12011=Amino acid sequence notation type
+12020=&Match Ions
+; Textboxes
+12051=Enter amino acid sequence here
+12061=Shifts the loaded ions to be matched by the given amount to correct for post-translational modifications.
+; Frames, labels, and checkboxes
+12100=Sequence:
+12150=N and C Terminus
+12160=&N
+12170=&C
+12180=H
+12190=OH
+12200=Ion Types
+12210=&A Ions
+12215=&B Ions
+12220=&Y Ions
+12230=Neutral Losses
+12236=Choose ions to which losses will be applied
+12240=Loss of H2O
+12250=Loss of NH3
+12260=Charge Options
+12270=&2+ charged ions
+12280=&Threshold
+12286=The 2+ m/z value will be computed for ions above this m/z
+12300=Ion Match Options
+12310=&Remove Precursor Ion
+12320=Ion Mass
+12330=Mass Window
+12340=&Ion Matching Window
+12350=Da
+12355=Alignment &Offset
+12360=Ion Statistics
+12370=Loaded
+12375=Remaining after binning
+12380=Within tolerance
+12385=Precursor not found
+12390=Precursor removed
+12395=Precursor not removed
+12400=Matches
+12405=Score
+
+; Column titles in grids
+; Note: # means 'number', Immon. means 'immonium', and Seq. means 'sequence'
+12500=#
+12510=Immon.
+12520=Seq.
+12550=Mass
+12560=Intensity
+
+; Ion Types (must be exactly one letter long)
+12600=a
+12610=b
+12620=y
+
+; Menu Items
+12800=&Load Sequence Info
+12810=&Save Sequence Info
+12820=Load List of &Ions to Match
+12830=&Close
+12840=&Copy Predicted Ions
+12850=Copy Predicted Ions as &RTF
+12855=Copy Predicted Ions as Html
+12860=&Paste List of Ions to Match
+12870=Clear Match Ion &List
+12880=List of &Ions to Match
+12900=Predicted &Mass Spectrum
+12910=&Update Spectrum on Change
+12920=Ion Match List &Options
+12930=&Automatically Align Ions to Match
+12940=&Fragmentation Modelling
+
+[frmMsPlot]
+13000=Plot
+; The following is an abbreviation for the word 'Location'
+13010=Loc
+
+; Legend Items
+13030=Predicted Ions
+13035=Loaded Ions
+
+; Menu Items
+13100=&Export Data
+13150=&Plot Type
+13160=&Sticks To Zero
+13170=&Gaussian Peaks
+13180=Set Effective &Resolution
+13190=X Axis Gridlines
+13200=Y Axis Gridlines
+13210=&Ticks to label (approx.)
+13220=&X Axis
+13230=&Y Axis
+13235=Plot &Quality (affects speed)
+13240=&Gaussian Representation Quality
+13245=&Approximation Factor
+13250=Set &X Range
+13260=Set &Y Range
+13270=&Autoscale Y Axis
+13280=&Fix mimimum Y at zero
+13290=&Zoom Out to Previous
+13295=Ctrl+Z or Right Click
+13300=Zoom Out to Show All
+13310=&Cursor Mode
+13315=Space Enables Move
+13320=&Zoom
+13330=&Move
+13340=&Show Current Position
+13342=Show &Legend
+13345=Reset to &Default Options
+13350=&Zoom Box
+13360=Zoom &In
+13365=Left Click
+13370=Zoom In Horizontal
+13380=Zoom In Vertical
+13390=Zoom &Out
+13400=Zoom Out Horizontal
+13410=Zoom Out Vertical
+
+[frmIonMatchOptions]
+14000=Ion Matching Options
+; Buttons
+14010=&Reset to Defaults
+
+; Explanations
+14050=When a list of ions is imported into the program, ions of similar mass may optionally be grouped together via a binning process to reduce the total number of data points. Next, ions around the precursor ion may be removed.
+14055=Then, the intensities are normalized to the given maximum intensity and ordered by decreasing intensity. The top-most ions (number of ions to use) are divided into distinct mass regions and the ions in each region again normalized.
+14060=The masses of the predicted ions for a given peptide sequence are easily computed. However, intensity values must also be assigned to the masses.
+14065=The B and Y ions are typically assigned the same intensity while the A ion is typically 5 times less intense. Shoulder ions (masses ± 1 Da from the B and Y ions) can be added, in addition to including neutral losses (H2O and NH3).
+
+; Frames, labels, and checkboxes
+14100=Normalization Options for Imported Data
+14110=&Group Similar Ions (Bin Data)
+14115=Mass Window
+14120=Normalized Intensity
+14130=Number of Ions to Use
+14140=Mass region subdivisions
+14150=Ion Intensities of Predicted Ions
+14160=A Ion Intensity
+14165=B Ion Intensity
+14170=Y Ion Intensity
+14180=B/Y Ion Shoulders
+14190=Neutral Losses
+
+[frmSetValue]
+14500=Set Value
+14510=&Set
+14520=&Start
+
+[frmProgress]
+14700=Progress
+14710=Click to Pause
+14715=Preparing to Pause
+14720=Paused
+14725=Resuming
+14730=(Press Escape to abort)
+14740=min. elapsed/remaining
+
+[frmIsotopicDistibution]
+15000=Isotopic Distribution
+; Frames, labels, and checkboxes
+15050=Formula:
+15060=Results:
+15100=&Plot Results
+15110=&Compute
+15151=Isotopic distribution results
+
+[ErrorMessages]
+20001=Unbekanntes Element
+20003=Fehlende Abschlussklammern
+20004=Klammern ohne Entsprechung gefunden
+20005=Null (0) direkt nach Abschlussklammer, Element oder Bindestrich (-) nicht erlaubt
+20006=Eingegebene Zahl zu gross oder nur nach [, -, ), oder ^ (Kapitälchen) erlaubt
+20007=Eingegebene Zahl zu gross
+20011=Zahlen sollten auf linke eckige Klammern folgen, nicht auf rechte eckige Klammern (ausser 'Betrachte eckige als runde Klammern' ist eingeschaltet)
+20012=Nach jeder eckigen Klammer und/oder einem Dezimalpunkt muss eine Zahl folgen
+20013=Eckige Abschlussklammer (]) fehlt
+20014=Falsch platzierte Zahl; sollte immer nach einem Element, [, ), -, oder Kapitälchen (^) stehen
+20015=Eckige Klammer ohne Gegenstück
+20016=Verschachtelte eckige Klammern oder eckige Klammern innerhalb von Mehrfach-Hydraten nicht erlaubt (ausser 'Betrachte eckige als runde Klammern' ist eingeschaltet)
+20018=Unbekanntes Element
+20020=Nach einem Kapitälchen (^) muss die Massenzahl eines Isotops folgen
+20022=Einem Kapitälchen (^), gefolgt von einer isotopischen Massenzahl, muss wiederum ein Element folgen
+20023=Nach einem Kapitälchen (^) sind negative isotopische Massenzahlen nicht erlaubt
+20024=Isotopische Massenzahlen für Abkürzungen sind nicht erlaubt
+20025=Nach einem Koeffizient, der einen Bindestrich anführt, muss ein Element folgen
+20026=Bei Abkürzungen sind isotopische Massen nicht erlaubt; D ist eine Abkürzung
+20027=Zahlen können nur einen einzigen Dezimalpunkt enthalten
+20028=In der Definition einer Abkürzung dürfen keine Abkürzungen stehen.
+20050=Ziel-Wert ist grösser als 100%, unmöglich bei Zusammensetzungen
+20075=In der Taschenrechner-Eingabe sind keine Buchstaben erlaubt
+20076=Runde Abschlussklammer fehlt
+20077=Runde Klammern ohne Gegenstück
+20078=Zahl am falschen Ort, zu gross, zu klein, oder zu lang
+20080=Operator-Zeichen am falschen Ort
+20081=Track-Variable ist kleiner oder gleich 1; Programmfehler; bitte Programm-Autor benachrichtigen
+20082=Fehlendes Operator-Zeichen.
+20085=Negative Zahlen hoch eine Dezimalzahl sind nicht erlaubt
+20086=Null hoch eine negative Zahl ist nicht möglich
+20087=Null in der nullten Potenz ist nicht möglich
+20089=Nach einem Kapitälchen (^) muss eine einzige positive oder negative Zahl folgen
+20090=Zahlen können nur einen einzigen Dezimalpunkt enthalten
+20091=Division durch Null nicht erlaubt. Fehler korrigieren und nochmals probieren
+20092=Leerschläge (Abstandszeichen) sind in mathematischen Ausdrücken nicht erlaubt
+20093=Verwende Punkt zur Anzeige von Dezimalstellen
+20094=Verwende Komma zur Anzeige von Dezimalstellen
+20095=Nach dem Dezimalpunkt muss eine Zahl folgen
+20100=Fehler beim Speichern der Abkürzungs-Datei MWT_ABBR.DAT
+20110=Die voreingestellte Abkürzungs-Datei wurde neu erzeugt.
+20115=Die vorherige Datei wurde umbenannt.
+20120=Kopfzeile [AMINO ACIDS] nicht gefunden in der Datei MWT_ABBR.DAT. Diese Kopfzeile muss VOR der Kopfzeile [ABBREVIATIONS] stehen.
+20125='OK' drücken, um ohne Abkürzungen weiterzumachen.
+20130=Kopfzeile [ABBREVIATIONS] nicht gefunden in der Datei MWT_ABBR.DAT. Diese Kopfzeile muss VOR der Kopfzeile [AMINO ACIDS] stehen.
+20135='OK' drücken, um nur mit den Aminosäuren-Abkürzungen weiterzumachen.
+20140=Abkürzungsdatei im Verzeichnis des Programms nicht gefunden.
+20150=Fehler beim Laden/Erzeugen der Abkürzungs-Datei
+20160=Ignoriere Abkürzung -- Formel ist ungültig
+20170=Ignoriere Duplizierte Abkürzung
+20180=Ignoriere Abkürzung; Ungültiges Zeichen
+20190=Ignoriere Abkürzung; zu lang
+20200=Ignoriere ungültige Zeile
+20210=Die voreingestellte Elementen-Datei wurde neu erzeugt.
+20220=Element hat möglicherweise inkorrektes Atomgewicht gesetzt
+20230=Element hat möglicherweise inkorrekte Unschärfe gesetzt
+20250=Ignoriere Zeile; Ungültiges Element-Symbol
+20260=Kopfzeile [ELEMENTS] nicht gefunden in der Datei MWT_ELEM.DAT. Datei muss diese Kopfzeile enthalten.
+20265='OK' drücken, um nur mit voreingestellten Element-Werten weiterzufahren.
+20270=Die Elementendatei im Ordner des Programms nicht gefunden.
+20280=Fehler beim Laden/Erzeugen der Elementen-Datei
+20305=Fahre mit der voreingestellten Sprache weiter.
+20320=Fehler beim Speichern der Elementen-Datei
+20330=Fehler beim Laden/Erzeugen der Werte-Datei
+20340='OK' drücken, um weiterzufahren, ohne die voreingestellten Werte und Formeln zu laden.
+20345=Falls Sie ein schreibgeschütztes Medium benutzen, sollten Sie auf der Kommando-Zeile den /X Schalter setzen, um diesen Fehler zu vermeiden.
+20350=Fehler
+20360=Fehler beim Speichern der Programmvoreinstellungen-Datei
+20370=Wenn Sie ein schreibgeschütztes Medium benutzen, können Sie keine Programm-Einstellungen abspeichern.
+20380=Fehler beim Speichern der Werte- und Formeln-Datei (MWT_NUM.DAT)
+20390=Wenn Sie ein schreibgeschütztes Medium benutzen, können Sie Ihre Werte und Formeln nicht abspeichern.
+20400=Fehler beim Laden/Erzeugen der Programm-Initialisierungs-Datei
+20410='OK' drücken, um weiterzufahren, ohne die benutzerseitigen Voreinstellungen zu laden.
+20440=Die sprachspezifische Initialisierungs-Datei konnte nicht geöffnet werden, oder hat ein falsches Format
+20450=Eine sprachspezifische Initialisierung konnte nicht geladen werden
+20460=Eine sprachspezifische Initialisierungs-Datei wurde nicht gefunden im Verzeichnis des Programms
+20470=Die Quell-Datei zur Berechnung von Molekulargewichten wurde nicht gefunden
+20480=Datei nicht gefunden
+20490=Die Datei existiert bereits. Ueberschreiben?
+20500=Die Datei existiert
+20510=Fehler beim Lesen/Schreiben von Dateien zur automatischen Bearbeitung
+20515='OK' drücken, um die automatische Dateibearbeitung zu beenden
+20520=Programmfehler
+20530=Das Programm ist in einen verbotenen Zustand geraten. Bitte benachrichtigen Sie den Programm-Autor.
+20540=Sie können keine Elemente bearbeiten, weil das Programm mit dem /x-Schalter auf der Kommandozeile gestartet wurde.
+20545=Sie können keine Abkürzungen bearbeiten, weil das Programm mit dem /x-Schalter auf der Kommandozeile gestartet wurde.
+20550=Der %-Ermittler kann nicht benützt werden, wenn eckige Klammern als runde behandelt werden. In den Programmeinstellungen kann die Klammer-Erkennung umgeschaltet werden.
+20555=Der %-Ermittler ist nicht benützbar
+20560=Die Zahl der Felder für die Formel-Eingabe ist beschränkt.
+20570=Die aktuelle Formel-Eingabe ist leer.
+20580=Schalten Sie den %-Ermittler (F11) aus, bevor Sie eine neue Formel erzeugen.
+20590=Ein Ueberlauf-Fehler ist aufgetreten. Bitte Zahlen verkleinern und Berechnung nochmals starten.
+20600=Ein Fehler ist aufgetreten
+20605=Bitte beenden Sie das Programm und melden Sie den Fehler dem Programm-Autor. Die Email-Adresse ist im Fenster 'Ueber den Molekulargewicht-Kalkulator' angegeben.
+20610=Innerhalb einer Formel sind keine Leerschläge (Abstandszeichen) erlaubt
+20620=Ungültiges Zeichen
+20630=Kopieren in eine neue Formel-Eingabe nicht möglich.
+20650=Die aktuelle Formel ist leer.
+20655=Der %-Ermittler ist eingeschaltet (mit F11 ausschalten).
+20660=Warnung, die isotopische Massenzahl ist vermutlich zu gross für das Element
+20662=Warnung, die isotopische Massenzahl ist vermutlich zu klein für das Element
+20665=vs avg atomic wt of
+20670=Warnung, isotopische Massenzahl ist unmöglich klein für das Element
+20675=Protonen
+20680=Notiz: Exakte Gross/Kleinschreibung eingeschaltet
+20685=Notiz: Für %-Ermittler muss eine linke eckige Klammer, gefolgt von einem x in der Formel stehen
+20690=Notiz: Eckige werden als runde Klammern behandelt
+20700=One or more elements must be checked.
+20705=Maximum hits must be greater than 0.
+20710=Maximum hits must be less than
+20715=Minimum number of elements must be 0 or greater.
+20720=Minimum number of elements must be less than maximum number of elements.
+20725=Maximum number of elements must be less than 65,025
+20730=Bei selbstdefinierten Elementen muss ein Atomgewicht eingegeben werden.
+20735=Bei selbstdefinierten Elementen muss das Atomgewicht grösser als Null sein.
+20740=Das gesuchte Molekulargewicht muss eingegeben werden.
+20745=Das gesuchte Molekulargewicht muss grösser als Null sein.
+20755=Ein maximales Molekulargewicht muss eingegeben werden.
+20760=Das maximale Molekulargewicht muss grösser als Null sein.
+20765=Der gesuchte Anteil des Elements muss eingegeben werden
+20770=Der gesuchte Anteil des Elements muss grösser als Null sein.
+20775=Custom elemental weights must contain only numbers or only letters. If letters are used, they must be for a single valid elemental symbol or abbreviation.
+20780=Custom elemental weight is empty. If letters are used, they must be for a single valid elemental symbol or abbreviation.
+20785=Unbekanntes Element-Symbol, Atom-Nummer oder Abkürzung bei einem selbstdefinierten Element.
+20790=Nur ein einziges Element-Symbol oder eine einzige Abkürzung sind erlaubt.
+20800=Vorsicht, es wurden keine Abkürzungen geladen - die Anweisung hat keinen Effekt.
+
+20900=Error Reading/Writing sequence information file.
+20910=Ions are already present in the ion list. Replace with new ions?
+20920=Replace Existing Ions
+20930=Loading Ion List
+20940=Process aborted
+20945=Aborted
+20950=Normalizing ions
+20960=Normalizing by region
+20965=Sorting by Intensity
+20970=Matching Ions
+20980=The clipboard is empty. No ions to paste.
+20985=No ions
+20990=Pasting ion list
+21000=Determining number of ions in list
+21010=Parsing list
+21020=No valid ions were found on the clipboard. A valid ion list is a list of mass and intensity pairs, separated by commas, tabs, or spaces. One mass/intensity pair should be present per line.
+21030=Error writing data to file
+21040=Set Range
+21050=Start Val
+21055=End Val
+21060=Set X Axis Range
+21065=Set Y Axis Range
+21070=Enter a new Gaussian Representation quality factor. Higher numbers result in smoother Gaussian curves, but slower updates. Valid range is 1 to 50, default is 20.
+21072=Gaussian Representation Quality
+21075=Enter a new plotting approximation factor. Higher numbers result in faster updates, but give a less accurate graphical representation when viewing a wide mass range (zoomed out). Valid range is 1 to 50, default is 10.
+21077=Plotting Approximation Factor
+21080=Resolving Power Specifications
+21090=Resolving Power
+21100=X Value of Specification
+21110=Please enter the approximate number of ticks to label on the axis
+21115=Axis Ticks
+21120=Creating Gaussian Representation
+21130=Preparing plot
+21135=Drawing plot
+21140=Are you sure you want to restore the default plotting options?
+21145=Restore Default Options
+21150=Auto Align Ions
+21155=Maximum Offset
+21160=Offset Increment
+21165=Aligning Ions
+
+21500=All Files
+21510=Text Files
+21515=txt
+21520=Data Files
+21525=csv
+21530=Sequence Files
+21535=seq
+21540=Ion List Files
+21545=txt
+21550=cap
+21555=Capillary Flow Info Files
+
+[CautionStatments]
+; Note: Caution statement keynames are case sensitive; i.e. Bi is different than BI
+; You may add new caution statements if desired; however, you will need to save
+; the file with a name other than Lang_English and change the Language= key
+; since this file is not loaded if the language is English
+22000=Vorsicht
+Bi=Mit Bi ist Wismut gemeint; mit BI ist Bor-Jod gemeint.
+Bk=Mit Bk ist Berkelium gemeint; mit BK ist Bor-Kalium gemeint.
+Bu=Mit Bu ist Butyl- gemeint; mit BU ist Bor-Uran gemeint.
+Cd=Mit Cd ist Kadmium gemeint; mit CD ist Kohlenstoff-Deuterium gemeint.
+Cf=Mit Cf ist Californium gemeint; mit CF ist Kohlenstoff-Fluor gemeint.
+Co=Mit Co ist Kobalt gemeint; mit CO ist Kohlenstoff-Sauerstoff gemeint.
+Cs=Mit Cs ist Cäsium gemeint; mit CS ist Kohlenstoff-Schwefel gemeint.
+Cu=Mit Cu ist Kupfer gemeint; mit CU ist Kohlenstoff-Uran gemeint.
+Dy=Mit Dy ist Dysprosium gemeint; mit DY ist Deuterium-Yttrium gemeint.
+Hf=Mit Hf ist Hafnium gemeint; mit HF ist Wasserstoff-Fluor gemeint.
+Ho=Mit Ho ist Holmium gemeint; mit HO ist Wasserstoff-Sauerstoff gemeint.
+In=Mit In ist Indium gemeint; mit IN ist Jod-Stickstoff gemeint.
+Nb=Mit Nb ist Niob gemeint; mit NB ist Stickstoff-Bor gemeint.
+Nd=Mit Nd ist Neodym gemeint; mit ND ist Stickstoff-Deuterium gemeint.
+Ni=Mit Ni ist Nickel gemeint; mit NI ist Stickstoff-Jod gemeint.
+No=Mit No ist Nobelium gemeint; mit NO ist Stickstoff-Sauerstoff gemeint.
+Np=Mit Np ist Neptunium gemeint; mit NP ist Stickstoff-Phosphor gemeint.
+Os=Mit Os ist Osmium gemeint; mit OS ist Sauerstoff-Schwefel gemeint.
+Pd=Mit Pd ist Palladium gemeint; mit PD ist Phosphor-Deuterium gemeint.
+Ph=Mit Ph ist Phenyl- gemeint, mit PH ist Phosphor-Stickstoff gemeint.
+Pu=Mit Pu ist Plutonium gemeint; mit PU ist Phosphor-Uran gemeint.
+Py=Mit Py ist Pyridin gemeint; mit PY ist Phosphor-Yttrium gemeint.
+Sb=Mit Sb ist Antimon gemeint; mit SB ist Schwefel-Bor gemeint.
+Sc=Mit Sc ist Scandium gemeint; mit SC ist Schwefel-Kohlenstoff gemeint.
+Si=Mit Si ist Silizium gemeint; mit SI ist Schwefel-Jod gemeint.
+Sn=Mit Sn ist Zinn gemeint; mit SN ist Schwefel-Stickstoff gemeint.
+TI=Mit TI ist Tritium-Jod gemeint, mit Ti ist Titan gemeint.
+Yb=Mit Yb ist Ytterbium gemeint; mit YB ist Yttrium-Bor gemeint.
+BPY=Mit BPY ist Bor-Phosphor-Yttrium gemeint; mit Bpy ist Bipyridin gemeint.
+BPy=Mit BPy ist Bor-Pyridin gemeint; mit Bpy ist Bipyridin gemeint.
+Bpy=Mit Bpy ist Bipyridin gemeint.
+Cys=Mit Cys ist Cystein gemeint; mit CYS ist Kohlenstoff-Yttrium-Schwefel gemeint.
+His=Mit His ist Histidin gemeint; mit HIS ist Wassrstoff-Jod-Schwefel gemeint.
+Hoh=Mit HoH ist Holmium-Wasserstoff gemeint; mit HOH ist Wasserstoff-Sauerstoff-Wasserstoff (aka-Wasser) gemeint.
+Hyp=Mit Hyp ist Hydroxyprolin gemeint; mit HYP ist Wasserstoff-Yttrium-Phosphor gemeint.
+OAc=Mit OAc ist Sauerstoff-Actinium gemeint; mit Oac ist Acetat gemeint.
+Oac=Mit Oac ist Acetat gemeint.
+Pro=Mit Pro ist Prolin gemeint; mit PrO ist Praseodym-Sauerstoff gemeint.
+PrO=Mit Pro ist Proline gemeint; mit PrO ist Praseodym-Sauerstoff gemeint.
+Val=Mit Val ist Valin gemeint; mit VAl ist Vanadium-Aluminium gemeint.
+VAl=Mit Val ist Valin gemeint; mit VAl ist Vanadium-Aluminium gemeint.
+VAl=Mit Val ist Valin gemeint; mit VAl ist Vanadium-Aluminium gemeint.
diff --git a/MwtZip/Lang_Portuguese.ini b/MwtZip/Lang_Portuguese.ini
new file mode 100644
index 0000000..c9dcf4e
--- /dev/null
+++ b/MwtZip/Lang_Portuguese.ini
@@ -0,0 +1,1021 @@
+; Language customization file for the Molecular Weight Calculator program by Matthew Monroe
+; Contact at alchemistmatt@yahoo.com and http://come.to/alchemistmatt/ or http://www.alchemistmatt.com/
+;
+; When customizing the phrases in this file, the ampersand symbol (&) signifies a
+; keyboard shortcut. For example, the default value for key 1000 is &File. When
+; running the program, the F in File will be underlined and the user may press Alt-F
+; to access the File menu (in addition to clicking on the file menu)
+; To improve usability of the program, please try to include the & symbol in menu items
+; and buttons. Note, however, that if two controls on the same form have the same &
+; shortcut, they will not respond to the alt key in the usual way.
+;
+; In this file, items surround by brackets [] are section headers -- the program ignores them
+; when parsing the file. The key values (1000, 1010, 1020, etc.) should not be changed, with
+; the exception that new caution statements may be added at the end of the file.
+; Lines beginning with a semicolon (;) are also ignored since they are treated as comments
+; However, you should not place a ; at the end of a line with an actual key and caption.
+;
+; Keys with multiple values separated by a vertical line (|) represent multiple items loaded
+; into a ComboBox control. When translating to other languages, you must keep the same number
+; of items in the list, or program functionality will be lost. For example, key 7070 contains
+; hours|minutes|seconds Thus, hours, minutes, and seconds will be loaded into a control, from
+; which the user may select one of them.
+;
+; If you create a new .Ini file for a foreign language and would like it posted on my
+; web page, simply e-mail it to me.
+
+; Portuguese translation generously provided by Alexandre R Soares; http://geocities.yahoo.com.br/ntegti
+[Language]
+Language=Português
+
+
+
+
+[frmMain Menus]
+; Menu Items
+1000=&Arquivo
+1010=Editar &Tabela de Elementos
+1020=Editar &Abreviaturas
+1030=&Calcular massas em arquivo texto
+1040=Im&primir
+1050=&Sair
+1500=&Editar
+1510=&Recortar
+1520=&Copiar
+1530=&Colar
+1540=&Limpar
+1550=Copiar Fórmula como &RTF
+1560=Copiar Massa Molecular
+1570=Copiar Composição P&ercentual
+1580=Duplicar &Fórmula
+1590=Apagar T&udo
+1600=Apagar Fórmula
+1610=E&xpandir Abreviaturas
+1620=Converter para Fórmula &Empírica
+2000=&Ver
+2010=Ver &Tudo
+2020=Visão &Simples
+2030=Resolver &Percentual
+2040=&Desliga
+2050=&Liga
+2500=&Ferramentas
+2510=Cálculos &Mol/Massa/Solução
+2520=Encontre &Fórmula
+2530=Conversor &Aminoácido
+2533=Modelagem de Seqüência de &Peptídio
+2536=Modelagem de Distribuição &Isotópica
+2538=Show Isotopic &Distribution for Current Formula
+2540=&Calculadora
+2550=Calculadora de Fluxo Cap&ilar
+3000=&Opções
+3010=Escolher &Idioma (Language)
+3020=Alterar &Preferências
+3030=Al&terar Fonte
+3040=Manter no &Topo
+3050=&Salvar e Restaurar Padrão
+3060=&Restaurar Padrão e Fórmulas
+3070=Salvar &Valores e Fórmulas Agora
+3500=Aj&uda
+3510=&Visão Geral
+3530=&Mostrar Dicas
+3540=&Sobre MWT
+
+[frmMain Status Messages and Verification Messages]
+3600=A linha completa é
+3605=Zooming
+3610=Tem certeza que deseja converter essa fórmula em empírica?
+3615=Converter em Fórmula Empírica
+3620=Tem certeza que deseja apagar essa fórmula?
+3625=Apagar a Fórmula
+3630=Tem certeza que deseja expandir as abreviaturas dessa fórmula para seus equivalentes elementais?
+3635=Expandir Abreviaturas
+3640=Restaurar padrão e fórmulas eliminará as fórmulas atuais. Tem certeza que deseja fazê-lo?
+3645=Restaurar Valores e Fórmulas
+3650=Modifique a porcentagem indicada para o elemento no Percent Solver. Selecione Restaurar para desmarcar a porcentagem ou Cancelar para ignorar alterações.
+3660=Use Page Up/Down ou setas para mover (F11 sai do modo Percent Solver).
+3665=Pressione Enter ou Clique para alterar a percentagem (F11 sai do modo Percent Solver).
+3670=Pronto
+3700=Calculando, prima qualquer tecla ou clique no mouse para parar.
+3710=x é
+3720=Valor Calculado
+3730=Procurado
+3740=Diferença para o Indicado
+3750=% Solver Ativado
+3760=Resultados do MWT
+3770=Valores e fórmulas padrão restaurados.
+3780=Tem certeza que deseja apagar todas as fórmulas?
+3785=Apagar todas as Fórmulas
+3790=Tem certeza que deseja sair?
+3795=Sair do Programa
+3800=Carregando Abreviaturas
+3810=Carregando Elementos
+3820=(usando massas atômicas médias)
+3830=(usando massas isotópicas elementais)
+3840=(usando massas isotópicas inteiras)
+3850=Alteração de idioma salva.
+
+[Phrases common throughout application]
+4000=&Fechar
+4010=&Ok
+4020=&Cancelar
+4030=Sa&ir
+; The following is the abbreviation for Molecular Weight
+; It must be exactly two letters long
+4040=MM
+4050=Aviso
+
+[frmMain]
+; Form Caption
+4900=Molecular Weight Calculator
+; Labels
+5000=Fórmula
+5010=Modo de Massa
+5020=&Média
+5021=Usar massas médias dos elementos
+5030=&Isotópico
+5031=Usar massa do isótopo mais comum
+5040=In&teiro
+5041=Usar massa inteira do isótopo mais comum
+; TextBoxes
+5051=Escreva a fórmula molecular aqui
+; Buttons
+5100=&Calcular
+5101=Determina a massa molecular da fórmula
+5110=&Nova Fórmula
+5111=Adiciona nova fórmula à lista
+5116=Mostra nova fórmula
+; Grid control
+5201=Clique para estabelecer ou restabelecer um valor alvo
+; Status control
+5301=Duplo clique para expandir linha de status
+5350=MWT já está sendo usado. Tem certeza que deseja abrir outra cópia?
+5355=Em uso
+
+[frmAboutBox]
+5500=Sobre MWT
+5510=Esse programa é Freeware; distribuição livre
+
+[frmIntro]
+5700=Carregando
+
+[frmAminoAcidConverter]
+; Form Caption
+6000=Registro de Conversão de Aminoácido
+; Labels
+6010=Seqüência de Aminoácidos com uma letra
+6020=Seqüência de Aminoácidos com três letras
+; TextBoxes
+6031=Entre aqui a seqüência usando abreviaturas com 1 letra
+6041=Entre aqui a seqüência usando abreviaturas com 3 letras
+; Buttons
+6050=&Copiar seqüência de 3 letras para fórmula:
+6060=Copiar para &Fragmentation Modeller
+; CheckBoxes
+6080=&Adicionar espaço a cada 10 resíduos
+6090=&Separar resíduos usando traços
+
+[frmCalculator]
+; Form caption
+6500=Calculadora
+; Textbox
+6511=Entre aqui uma expressão matemática para avaliar
+; Buttons
+6520=&Calcular
+6521=Avaliar a expressão atual
+; Status control
+6601=Duplo clique para expandir linha atual
+6610=Resultado
+
+[frmCapillaryCalcs]
+; Form Caption
+7000=Cálculo de Fluxo Capilar e Fração de Massa
+; Combo Boxes
+7010=Abrir Capilaridade Tubular|Capilaridade Fechada
+7011=Alternar entre capilaridade aberta e fechada.
+7020=Encontrar Pressão de Fundo|Comprimento da Coluna|Encontrar Diâmetro Interno|Encontrar Taxa de Fluxo Volumétrico|Encontrar Taxa de Fluxo usando Tempo Morto
+7030=psi|Pascals|quiloPascals|Atmosferas|Bar|Torr (mmHg)
+7035=um|pol
+7040=Poise [g/(cm-s)]
+7050=mL/min|uL/min|nL/min
+7060=cm/h|mm/h|cm/min|mm/min|cm/s|mm/s
+7070=horas|minutos|segundos
+7080=mL|uL|nL|pL
+7090=Mol/L|miliMol/L|microMol/L|nanoMol/L|picoMol/L|fentoMol/L|atoMol/L|mg/mL|ug/mL|ng/mL|ug/uL|ng/uL
+7100=pmol/min|fmol/min|amol/min|pmol/s|fmol/s|amol/s
+7110=Mols|miliMols|microMols|nanoMols|picoMols|fentoMols|atoMols
+; Labels and frames
+7200=Pressão de Fundo
+7210=Comprimento da Coluna
+7220=Diâmetro Interno da Coluna
+7230=Viscosidade do Solvente
+7240=Diâmetro da Partícula
+7250=Taxa de Fluxo Volumétrico
+7260=Velocidade Linear
+7270=Tempo Morto da Coluna
+7280=Volume da Coluna
+7290=Porosidade Interparticular (epsilon)
+7300=Cálculos de Taxa de Massa
+7310=Concentração da Amostra
+7320=Tempo de Injeção
+7330=Taxa de Fluxo de Massa
+7340=Mols Injetados
+7350=Extra Column Broadening Calculations
+7360=Coeficiente de Difusão
+7370=Comprimento do Tubo Aberto
+7380=Tubo Aberto Diâmetro Interno
+7390=Largura Inicial do Pico
+7400=Velocidade Linear Ótima
+7410=(para partículas de 5 um)
+7420=Variança de Tempo
+7430=Variança Adicional
+7440=Resulting Peak Width
+7450=Incremento Porcentual
+7460=Fórmula Atual
+7480=Massa Molar
+7500=cm
+7520=cm^2/s
+7530=s (na base)
+7540=cm/s
+7550=s^2
+7560=s
+7570=g/mol
+; TextBoxes
+7601=Escreva a massa desejada para fazer os cálculos
+; Buttons
+7700=Mostrar/Ocultar Peak Broadening Calculations
+7710=&Ver Equações Explanatórias
+7730=Ver Equações
+; Option Buttons
+7750=&Usar massa molar da fórmula atual
+7760=&Empregar outro valor de massa molar
+; CheckBoxes
+7800=&Link para Cima
+; ToolTips
+7851=Valor típico de viscosidade é 0,0089 poise
+7861=Valor típico de porosidade é 0,4
+7871=Coeficiente de difusão típico para compostos orgânicos pequenos é 0,000001, i.e., 1E-6;; Typical value for peptides is 0,00005, i.e. 5E-5
+; Menus
+7900=&Load Values
+7910=&Save Values
+7950=&Capillary Flow Calculations
+
+[frmChangeFont]
+; Form Caption
+8000=Alterar Fonte
+; Combo Boxes
+; Labels
+8050=Fonte atual é
+8060=Alterar Fonte para:
+8070=Tamanho:
+; Buttons
+
+[frmChangeValue]
+; Form Caption
+8200=Alterar Valor
+; Buttons
+8210=&Alterar para Padrão
+
+[frmChangeLanguage]
+8400=Escolher Idioma
+; Labels
+8410=Os idiomas disponíveis são mostrados abaixo. Por favor, escolha o idioma que deseja usar.
+8420=Arquivos de idioma não disponíveis. Visite a homepage do autor para download de outros idiomas.
+
+[frmDiff]
+8600=Percent Solver Differences
+8610=&Copiar
+8611=Copiar resultados para o clipboard
+
+[frmEditAbbrev]
+9000=Editar Abreviaturas
+; Buttons
+9010=&Alterar para Padrão
+9011=Reestabelecer padrão de abreviaturas
+9020=&Remover
+; Messages
+9050=Máximo encontrado
+9060=Desculpe-me, são permitidas até 50 abreviaturas para Aminoácidos.
+9070=Desculpe-me, são permitidas até 50 abreviaturas normais.
+9080=Por favor adicione a entrada como uma abreviatura normal.
+9090=A abreviatura ou fórmula molecular será alterada para a que você digitar. Selecione Remover para deletar a abreviatura ou Cancelar para ignorar qualquer alteração.
+9100=Tem certeza que deseja perder todas as alterações?
+9105=Fechando Caixa de Edição de Abreviaturas
+9110=Tem certeza que deseja restaurar para as abreviaturas padrão?
+9115=Restaurar para padrão
+;Table Tool Tip
+9140=
+9141=Clique para fazer alteração
+; Table Column Titles
+9150=Carga
+9160=Fórmula Molecular
+9170=Abrev. Normal
+9180=Nome do Aminoácido
+9190=1 letra
+
+[frmEditElem]
+9200=Editar Elementos
+; Buttons
+9210=&Restaurar Padrões
+9211=Restaurar massas para seus valores médios
+9220=&Restaurar
+9230=Usar Massas &Atômicas Médias
+9231=Altera todas as massas para valores médios encontrados na natureza
+9240=Usar massas do &Isótopo mais comum
+9241=Altera todas as massas para valor do isótopo mais comum (para alta resolução de espectrometria de massa)
+9245=Usar massa inteira &Nominal
+9246=Ajusta todas as massas elementais para a massa inteira nominal do isótopo mais comum do elemento (para espectroscopia de massa de baixa resolução)
+; Messages
+9250=A massa ou incerteza será substituída pelo valor digitado. Selecione Restaurar ou coloque em valor-padrão ou Cancelar para ignorar qualquer alteração.
+9260=Tem certeza que deseja alterar todos os valores para Massa elemental média?
+9265=Alterar para Massa Média
+9270=Tem certeza que deseja alterar todos os valores para Massa elemental isotópica?
+9275=Alterar para Massa Isotópica
+9280=Tem certeza que deseja alterar todos os valores para Massa Inteira?
+9285=Alterar para Massa Inteira
+9290=Tem certeza que deseja alterar todos os valores para valores padrão (Massa média)?
+9295=Alterar para padrão
+9300=Se executado, não poderá ser cancelado.
+9310=Tem certeza que deseja perder todasas alterações?
+9315=Fechando Caixa de Edição de Elementos
+;Table Tool Tip
+9340=
+9341=Clique para modificar a massa do elemento ou incerteza
+;Table Column Titles
+9350=Elemento
+9360=Massa
+9370=Incerteza
+; Combo boxes
+9380=Símbolo|Número Atômico|Incerteza|Carga
+9390=Classificar por:
+
+[frmEquationsBroadening]
+9500=Equações de Largura da Coluna Extra
+
+[frmEquationsOpenTube]
+9550=Equações para fluxo em um tubo aberto
+
+[frmEquationsPackedCapillary]
+9600=Equações para fluxo em capilaridade fechada
+
+[frmFinderModeWarn]
+; Instructions Label
+9700= Use o Formula Finder para encontrar a provável fórmula de um composto de massa monoisotópica conhecida (determinada tipicamente por Espectroscopia de Massa).
+9701=Por exemplo, para encontrar uma possível fórmula empírica de um composto formado por C e H cuja massa seja de 16,0312984 daltons. Ao executar a busca com uma tolerância de massa de 5000 ppm resulta em 3 compostos: H2N, CH4, e O. Se escolher 500 ppm, somente CH4 combinará, que é o composto apropriado.
+9702=Para conseguir corretamente esta resposta, o programa deve ser ajustado para o modo Massa Isotópica. Isto pode ser feito manualmente ao Editar a Tabela de Elementos (menu Arquivo), ou comutar automaticamente a esta modalidade (marque uma opção abaixo).
+9703=Você gostaria de:
+9705=O Fragmentation Modelling serve para predizer massas que devem ser encontradas no Espectrômetro de Massa quando se ioniza um peptídio, entra no instrumento, e fragmentos se juntam à cadeia principal do peptídio (peptide backbone).
+9706=O peptídio normalmente se fragmentas em cada ligação de amida. Por exemplo, o peptídio Gly-Leu-Tyr formará os fragmentos Gly-Leu, Leu-Tyr, Gly, Leu, e Tyr. Adicionalmente, a clivagem da ligação amida pode ocorrer em diferentes locais, resultando em variações de massa.
+; Buttons
+9720=&Continuar
+; Option Buttons
+9750=Alternar agora para Modo Massa &Isotópica.
+9760=Sempre alternar automaticamente para modo Massas Isotópicas.
+9770=Continuar usando Massas Médi&as.
+; CheckBoxes
+9780=Não mo&strar mais esta caixa de diálogo.
+
+[frmFinder]
+10000=Formula Finder
+; Labels
+10010=Selecione entre os elementos C, H, N e O ou adicione outros. A busca é feita por massa molecular ou composições percentuais. Clique em Calcular para encontrar os compostos.
+10020=Maior Massa da Fórmula:
+10030=Massa Molecular Indicada:
+10040=Tolerância da Massa:
+10050=% de Tolerância:
+10060=Mín
+10070=Máx
+10080=Elemento
+10090=%
+10100=Limite
+10105=Massa Atômica
+; Percent completed status messages
+10110=% Realizado
+10115=Escolhendo
+10120=Procurando
+10125=Trabalhando
+10130=Completado
+10135=compostos
+10140=Escolha Interrompida
+10145=Cálculos Interrompidos
+10150=Formatando
+10155=Feito
+10160=Formatação abortada
+; Listboxes & Textboxes
+10201=Duplo clique em qualquer linha para expandi-la
+10221=Faixa de tolerância na massa indicada
+10231=Quantidade possível de composições percentuais com a porcentagem indicada
+10241=Número máximo de compostos a procurar
+10251=Número mínimo de átomos no composto
+10256=Número máximo de átomos no composto
+10260=%
+10261=Composição porcentual de
+10270=# ou Elemento ou Abreviatura
+10271=Escreva uma massa para o elemento, um símbolo, ou uma abreviatura
+; Note the following is 'dm' in English, standing for 'delta mass' or the mass difference
+; of the given result's mass versus the target mass
+10280=dm
+; Note the following is 'ppm' in English, standing for 'parts per million'
+10285=ppm
+; Buttons
+10300=Opções do Formul&a Finder
+10301=Atalho: Ctrl+O
+10310=&Calcular
+10311=Encontre os compostos dentro dos parâmetros especificados
+10320=Im&primir ...
+10330=Copiar como RT&F
+10331=Copiar resultados para clipboard no formato RTF
+10340=Cop&iar
+10341=Copiar resultados para clipboard
+10345=&Display Iso Abundance
+10346=Display the Isotopic Distribution of the currently selected compound (Ctrl+D)
+; Option Buttons
+10350=Coincidir Massa &Molecular
+10360=Coincidir Composições &Porcentuais
+; CheckBoxes
+10370=Modo Ppm
+; Elements (and Custom element phrase)
+10400=Carbono
+10405=Hidrogênio
+10410=Nitrogênio
+10415=Oxigênio
+10420=Escolha
+; Messages
+10450=Uma tecla foi pressionada.
+10455=Abortar
+10460=O mouse foi clicado fora da caixa de resultados.
+10465=Interrompendo formatação.
+10470=Interrompendo escolha.
+10480=A soma das composições percentuais não é 100%.
+10485=Continuar calculando?
+10490=Não é possível calcular
+10500=Uma tecla foi pressionada.
+10505=O mouse foi clicado fora da caixa de resultados.
+10510=Interrompendo cálculos.
+10515=O Número máximo foi encontrado.
+10520=Máximo
+10530=Compostos encontrados
+; Note: the following is used when displaying the results of a percent composition
+; search in the formula finder. A synonym for 'has' would be 'contains' or 'is composed of'
+10535=contém
+10540=Ocorreu um erro de memória. A lista de resultados está provavelmente cheia.
+10545=Falta de Memória
+10550=A caixa de resultados está vazia.
+10555=Nada a copiar
+10560=Nada a imprimir
+10565=Tem certeza que deseja imprimir o(s) resultado(s)?
+10570=Imprimindo
+
+[frmFinderOptions]
+10800=Opções do Finder
+; Labels
+10810=Selecione os itens das várias opções do Formula Finder.
+; Textboxes & Comboboxes
+10821=Carga mínima a limitar compostos
+10831=Carga máxima a limitar compostos
+10840=Busca Completa |Busca Restrita
+10841=Uma busca completa encontra todos os compostos, enquanto uma busca restrita encontra compostos dentro de uma escala atômica específica (completa é geralmente mais rápida).
+10850=Ordenar por Fórmula
+10851=Método para ordenar resultados. Calcular de novo para reordenar.
+10855=Ordenar por Carga
+10860=Ordenar por MM
+10865=Ordenar por m/z
+10870=Razão Massa/Carga Indicada
+10875=Massa Molecular Indicada
+; CheckBoxes
+10900=Encontrar &Carga
+10901=Computar a carga global de cada composto encontrado
+10910=Faixa Limite de Ca&rga
+10911=Limitar exibição de compostos à faixa específica de carga
+10920=Encontrar m/&z
+10921=Computar a massa para razão de carga de cada composto encontrado
+10930=Encontrar m/z &Indicado
+10931=Encontrar compostos com valores m/z equivalentes ao indicado
+10940=O&rdenar Resultados
+10941=Converter resultados para fórmulas empíricas e ordená-las
+10950=&Regular átomos de H
+10951=Elimina fórmulas com número exagerado de átomos de hidrogênio
+10960=&Ajustar automaticamente Mín e Máx ao ligante procurado.
+10961=Ajusta automaticamente valores Mín e Máx procurados para uma faixa válida de massa dada
+
+[frmMMconvert]
+11000=Cálculos Mol/Massa/Solução
+; Combo Boxes
+11010=Converter Quantidades|Encontrar Concentração|Diluição
+11011=Cálculos de concentração ou cálculos e conversões de grandezas
+11020=Mols|miliMols|microMols|nanoMols|picoMols|fentoMols|atoMols|Quilogramas|Gramas|Miligramas|Microgramas|Libras|Onças|Microlitros|Mililitros|Litros|Galões|Quarts|Pints
+11021=Unidade a ser convertida
+11026=Unidade a usar no cálculo de concentração
+11030=Microlitros|Mililitros|Litros|Galões|Quarts|Pints
+11031=Unidade de volume
+11041=Unidade da grandeza a calcular
+11051=Unidade de concentração
+; Labels
+11080=g/mL
+; Textboxes
+11101=Quantidade, volume ou massa de composto
+11106=Quantidade, volume ou massa de soluto
+11111=Densidade da substância
+11121=Volume da solução
+11131=Concentração de soluto
+; Buttons
+11150=Encontrar &Quantidade
+11151=Calcula quantidade, volume ou massa usando volume e concentração
+11160=Encontrar &Volume
+11161=Calcula volume usando a quantidade e concentração
+11170=Encontrar &Concentração
+11171=Calcula concentração usando quantidade e volume
+
+; Dilution-related controls
+11200=Problemas de Diluição
+11205=Problemas de Evaporação ou Sublimação
+11210=Encontrar Volumes Necessários|Encontrar Volume Total|Encontrar Concentração Final|Encontrar Concentração Inicial
+11211=Escolha o que deseja calcular
+11220=&Vincular Concentração Calculada e Concentração Initial (Diluição)
+11221=Usa o mesmo valor para Concentração Calculada e Concentração Inicial
+11230=Vincular Unidades de Volume
+11231=Usa as mesmas unidades de Volume para Solução inicial, Solvente, e Volume Total Final
+; Dilution related labels and textbox tooltips
+11250=Concentração &Inicial
+11256=Concentração de soluto na solução inicial
+11260=Volume da Solução &Inicial
+11266=Volume (alíquota) da solução inicial necessária para a diluição
+11270=Concentração &Final
+11276=Concentração de soluto na solução final após diluição
+11280=Volume de Solvente usado na &Diluição
+11286=Volume de solvente a misturar com a alíquota da solução inicial
+11290=Volume &Total Final
+11296=Volume total da solução final após diluição com solvente
+
+[frmProgramPreferences]
+11500=Preferências do MWT
+; Frame labels
+11510=Modo Abreviatura (F3)
+11520=Modo Case Recognition (F4)
+11530=Modo Desvio-Padrão (F12)
+11540=Opções do Formula Finder
+11550=Opções para Sair do Programa
+; Buttons
+11600=&Salvar opções como padrão
+11610=&Restaurar opções padrão
+; Option Buttons
+11650=Normal
+11651=Reconhecer abreviaturas normais, mas não Aminoácidos
+11655=Normal + Aminoácidos
+11656=Reconhecer abreviaturas normais e Aminoácidos
+11660=Desabilitado
+11661=Ignorar todas abreviaturas
+11665=Conversor para Maiúsculas
+11666=Põe fórmulas em maiúsculas corretamente
+11670=Case Exato
+11671=Requer que o usuário escreva as fórmulas com maiúsculas e minúsculas corretas
+11675=Smart Case
+11676=Interpreta fórmulas em letras minúsculas sem alterá-las para maiúsculas
+11680=Curto
+11681=Mostrar Desvios-Padrão de forma abreviada
+11685=Científico
+11686=Mostrar Desvios-Padrão em notação científica
+11690=Decimal
+11691=Mostrar Desvios-Padrão na forma decimal longa
+11695=Desabilitado
+11696=Não mostrar desvios-padrão
+11700=Usa Esc para sair com confirmação
+11701=Determine se a tecla Esc será usada para sair do programa exibindo janela de confirmação
+11705=Usa Esc para sair sem confirmação
+11710=Ignora Esc mas confirma saída
+11715=Ignora Esc e não confirma saída
+; CheckBoxes
+11750=A&vança após Calcular (F9)
+11751=Muda para nova fórmula após calcular a massa.
+11760=Usa &Colchetes como Parênteses
+11761=Usa colchetes, [ e ], como parênteses (não usar com Percent Solver)
+11770=Copia a&utomaticamente Massa Molecular Atual (Ctrl+U)
+11771=Automaticamente copia o valor de massa molecular da fórmula selecionada para o clipboard após cada cálculo
+11780=Considera Car&ga
+11781=Considera carga dos compostos (regras básicas, não consegue corrigir ligações duplas ou triplas, etc.)
+11800=Sempre troca para Modo &Isotópico automaticamente
+11801=Alterna para Massa Isotópica ao entrar em Formula Finder
+11810=&Nunca mostra o aviso de modo Formula Finder
+11811=Nunca avisa sobre modo de massa atual quando entra em Formula Finder
+11820=Salva &Automaticamente opções, valores, e fórmulas ao sair
+11821=Automaticaticamente salva opções, valores, e fórmulas ao sair do programa
+11830=Apresenta Frases de Alerta (F7)
+11831=Alerta possíveis confusões na escrita de fórmulas (como Co em vez de CO)
+11840=Mostra Modo de Massa
+11841=Permite alternar rapidamente o modo de massa (média, isotópica, inteiro)
+11850=Mostra Dicas
+11851=Mostra mensagens curtas de ajuda quando o mouse passa sobre alguns botões e áreas
+11860=Destaca campos de texto quando selecionado
+11861=Destaca o campo de texto completo quando move para ele
+11870=&Oculta janelas de programas inativos
+11871=Oculta a janela principal do programa quando usa o Formula Finder, Calculadora Mol/Massa, etc.
+11881=Escolha o menor número para evitar que a janela de fórmulas encha a tela. O máximo depende da configuração da tela. Pode ser necessário reiniciar o programa.
+11885=Número máximo de fórmulas a exibir
+11890=Module to show at startup
+11896=Module to show when the program starts
+11898=Main Window|Formula Finder|Capillary Flow Calculator|Mole/Mass Converter|Peptide Sequence Fragmentation Modeller|Amino Acid Notation Converter|Isotopic Distribution Modeller
+
+; Messages
+11900=Salva automaticamente valores de opções salvas.
+11910=Opções padrão restauradas.
+11920=Valores e fórmulas salvas.
+11925=Valores e fórmulas NÃO foram salvos pois foi usado o comando /X.
+11930=Opções default salvas.
+11935=Opções default NÃO foram salvos pois foi usado o comando /X.
+
+[frmFragmentationModelling]
+12000=Modelagem de Seqüência de Peptídio
+; General Combo Boxes
+12010=notação 1 letra|notação 3 letras
+12011=Tipo de notação para seqüência de aminoácido
+12020=&Encontre Íons
+; Textboxes
+12051=Escreva a seqüência de aminoácido aqui
+12061=Shifts the loaded ions to be matched by the given amount to correct for post-translational modifications.
+; Frames, labels, and checkboxes
+12100=Seqüência:
+12150=Terminação N e C
+12160=&N
+12170=&C
+12180=H
+12190=OH
+12200=Tipos de Íon
+12210=&A Íons
+12215=&B Íons
+12220=&Y Íons
+12230=Perda Neutra
+12236=Escolha os íons cuja cuja perda será aplicada
+12240=Perda de H2O
+12250=Perda de NH3
+12260=Opções de Carga
+12270=Íons de carga &2+
+12280=&Mínimo
+12286=O valor m/z 2+ será computado pelos íons acima desse m/z
+12300=Opções para o Íon
+12310=&Remove Íon Precursor
+12320=Massa do Íon
+12330=Faixa de Massa
+12340=&Ion Matching Window
+12350=Da
+12355=Alinhamento &Offset
+12360=Estatísticas do Íon
+12370=Carregado
+12375=Remaining after binning
+12380=Faixa de tolerância
+12385=Precursor não encontrado
+12390=Precursor removido
+12395=Precursor não removido
+12400=Encontrados
+12405=Escore
+
+; Column titles in grids
+; Note: # means 'number', Immon. means 'immonium', and Seq. means 'sequence'
+12500=#
+12510=Immon.
+12520=Seq.
+12550=Massa
+12560=Intensidade
+
+; Ion Types (must be exactly one letter long)
+12600=a
+12610=b
+12620=y
+
+; Menu Items
+12800=&Abrir Seqüência Info
+12810=&Salvar Seqüência Info
+12820=Abrir Lista de &Íons a Encontrar
+12830=&Fechar
+12840=&Copiar Íons Previstos
+12850=Copiar Íons Previstos como &RTF
+12855=Copiar Íons Previstos como Html
+12860=Co&lar Lista de Íons para Encontrar
+12870=Limpar &Lista de Íons a Encontrar
+12880=Lista de &Ions a Encontar
+12900=Espectro de &Massa Previsto
+12910=A&tualizar Espectro na Alteração
+12920=Ion Match List &Options
+12930=&Alinhamento Automático de Íons
+12940=Modelagem de &Fragmentos
+
+[frmMsPlot]
+13000=Plot
+; The following is an abbreviation for the word 'Location'
+13010=Loc
+
+; Legend Items
+13030=Íons Previstos
+13035=Íons Carregados
+
+; Menu Items
+13100=&Exportar Dados
+13150=Tipo de &Gráfico
+13160=&Sticks To Zero
+13170=Picos &Gaussianos
+13180=Set Effective &Resolution
+13190=Linhas de Grade Eixo X
+13200=Linhas de Grade Eixo Y
+13210=&Marcar para etiqueta (aprox.)
+13220=Eixo &X
+13230=Eixo &Y
+13235=&Qualidade do Gráfico (afeta velocidade)
+13240=Qualidade da Representação &Gaussiana
+13245=Fator de &Aproximação
+13250=Determinar &X
+13260=Determinar &Y
+13270=&Autoescalar Eixo Y
+13280=&Corrigir mínimo Y em zero
+13290=&Reduzir para Anterior
+13295=Ctrl+Z ou Clique Direito
+13300=Reduzir para Exibir Tudo
+13310=Modo do &Cursor
+13315=Space Enables Move
+13320=&Zoom
+13330=&Mover
+13340=&Mostrar Posição Atual
+13342=Mostrar &Legenda
+13345=Restaurar Opções &Padrão
+13350=&Zoom Box
+13360=&Ampliar
+13365=Clique Esquerdo
+13370=Ampliar Horizontal
+13380=Ampliar Vertical
+13390=&Reduzir
+13400=Reduzir Horizontal
+13410=Reduzir Vertical
+
+[frmIonMatchOptions]
+14000=Opções de Busca de Íon
+; Buttons
+14010=&Alterar para Padrão
+
+; Explanations
+14050=Quando uma lista de íons é importada para o programa, íons de massa similar podem ser opcionalmente agrupados para reduzir o número total de pontos. Íons que cercam o íon precursor podem ser removidos.
+14055=Então, as intensidades são normalizadas para a máxima intensidade dada e colocadas em ordem decrescente de intensidade. Os íons "top-most" (número de íons a usar) são divididos em diferentes regiões de massa e os íons em cada região são novamente normalizados.
+14060=As massas dos íons previstos para uma dada seqüência de peptídios são facilmente computadas. Contudo, valores de intensidade também podem ser indicadas por massas.
+14065=Os íons B e Y são tipicamente de mesma intensidade enquanto o íon A é tipicamente 5 vezes menos intenso. Íons "shoulder" (massas ± 1 Da dos íons B e Y) podem ser adicionados, além de incluir perdas neutras (H2O e NH3).
+
+; Frames, labels, and checkboxes
+14100=Opções de Normalização para Dados Importados
+14110=&Group Similar Ions (Bin Data)
+14115=Faixa de Massa
+14120=Intensidade Normalizada
+14130=Número de Íons a Usar
+14140=Subdivisões de Região de Massa
+14150=Ion Intensities of Predicted Ions
+14160=Intensidade Íon A
+14165=Intensidade Íon B
+14170=Intensidade Íon Y
+14180=B/Y Ion Shoulders
+14190=Perda Neutra
+
+[frmSetValue]
+14500=Determinar Valor
+14510=&Determinar
+14520=&Iniciar
+
+[frmProgress]
+14700=Progresso
+14710=Clique para Pausa
+14715=Preparando Pausa
+14720=Em pausa
+14725=Resuming
+14730=(Use Esc para interromper)
+14740=min. elapsed/remaining
+
+[frmIsotopicDistibution]
+15000=Isotopic Distribution
+; Frames, labels, and checkboxes
+15050=Formula:
+15060=Results:
+15100=&Plot Results
+15110=&Compute
+15151=Isotopic distribution results
+
+[ErrorMessages]
+20001=Elemento desconhecido
+20003=Falta fechar parênteses
+20004=Parênteses desencontrados
+20005=Não deve ter um 0 logo após fechar elemento ou -
+20006=Número muito grande ou colocar somente após [, -, ), ou circunflexo (^)
+20007=Número muito grande
+20011=Números deveriam estar à esquerda de colchetes, não à direita (a menos que esteja no modo 'tratar colchetes' como parênteses)
+20012=Um número deve estar presente após um colchete e/ou após a vírgula decimal
+20013=Falta fechar colchete, ]
+20014=Número mal colocado; deveria estar apenas após um elemento, [, ), -, ou circunflexo, ^
+20015=Colchete não encontrado
+20016=Não pode nested brackets or brackets inside múltiplos hidratos (a menos que esteja no modo 'tratar colchetes' como parênteses)
+20018=Elemento desconhecido
+20020=Deve colocar número de massa do isótopo seguido de circunflexo (^)
+20022=Um elemento deve estar presente após a massa isotópica após o circunflexo (^)
+20023=Massas de isótopo negativas não são permitidas após circunflexo (^)
+20024=Massas isotópicas não são permitidas para abreviaturas
+20025=Um elemento deve estar presente após o leading coeficiente of the dash
+20026=Massas Isotópicas não são permitidas para abreviaturas; D é uma abreviatura
+20027=Números não podem conter mais que uma vírgula decimal
+20028=Abreviatura não pode estar presente na definição de uma abreviatura
+20050=Valor Indicado é maior que 100%, valor impossível.
+20075=Letras não são permitidas na linha da calculadora
+20076=Falta fechar parênteses
+20077=Parênteses não encontrado
+20078=Número mal colocado; ou número muito grande, muito pequeno, ou muito longo
+20080=Operador mal colocado
+20081=Faixa variável é menor que ou igual a 1; bug no programa; por favor notifique o programador
+20082=Faltando operador.
+20085=Não é possível usar números negativos para potência decimal
+20086=Não é possível usar zero para potência decimal
+20087=Não é possível usar zero para elevar à zeroésima potência
+20089=Um npumero positivo ou negativo deve estar presente após o circunflexo (^)
+20090=Números não podem conter mais que uma vírgula decimal
+20091=Você tentou dividir um número por zero. Por favor corrija o problema e recalcule.
+20092=Não são permitidos espaços em expressões matemáticas
+20093=Use ponto para decimais
+20094=Use vírgula para decimais
+20095=Deve ser colocado um algarismo após a vírgula
+20100=Erro ao salvar arquivo de abreviaturas
+20110=O arquivo de abreviaturas foi modificado.
+20115=O arquivo anterior foi renomeado
+20120=[AMINOÁCIDOS] cabeçalho não encontrado no arquivo MWT_ABBR.DAT . Ele deveria estar antes/acima do cabeçalho [ABBREVIATIONS].
+20125=Selecione OK para continuar sem qualquer abreviatura.
+20130=[ABBREVIATURAS] cabeçalho não encontrado no arquivo MWT_ABBR.DAT. Ele deveria estar antes/acima do cabeçalho [AMINOÁCIDOS].
+20135=Selecione OK para continuar somente com abreviaturas de Aminoácidos.
+20140=O arquivo de abreviaturas não foi encontrado na pasta do programa
+20150=Erro ao Carregar/Criar Arquivo de Abreviatura
+20160=Ignorando Abreviatura -- Fórmula Inválida
+20170=Ignorando Abreviatura Repetida
+20180=Ignorando Abreviatura; Caracter Inválido
+20190=Ignorando Abreviatura; muito comprido
+20200=Ignorando linha inválida
+20210=O arquivo contendo os elementos foi modificado.
+20220=Massa possivelmente incorreta
+20230=Incerteza possivelmente incorreta
+20250=Ignorando Linha; Símbolo de Elemento Invélido
+20260=[ELEMENTOS] cabeçalho não encontrado no arquivo MWT_ELEM.DAT . Ele deveria estar neste arquivo.
+20265=Selecione OK para continuar com valores padrão.
+20270=O arquivo de elementos não foi encontrado na pasta do programa.
+20280=Erro ao Carregar/Criar Arquivo de Elementos
+20305=Continuar com captions padrão.
+20320=Erro ao Salvar Arquivo de Elementos
+20330=Erro ao Carregar/Criar no Arquivo de Valores
+20340=Selecione OK para continuar a carregar Valores e Fórmulas Padrão.
+20345=Ao usar drive de leitura (Read-Only), use /X na linha de comando para evitar esse erro.
+20350=Erro
+20360=Erro ao Salvar no Arquivo Opções Padrão
+20370=Ao usar drive de leitura (Read-Only), não é possível salvar as opções padrão.
+20380=Erro ao Salvar no Arquivo de Valores e Fórmulas
+20390=Ao usar drive de leitura (Read-Only), não é possível salvar valores e fórmulas.
+20400=Erro ao Carregar/Criar no Arquivo de Opções Padrão
+20410=Selecione OK para continuar sem carregar Padrões do Usuário.
+20440=O arquivo de idioma não pode ser aberto corretamente ou foi formatado incorretamente.
+20450=Impossível carregar idioma especificado
+20460=O arquivo de idioma não foi encontrado na pasta (diretório) do programa.
+20470=O arquivo necessário para processar massa molecular não foi encontrado
+20480=Arquivo Não Encontrado
+20490=Este arquivo já existe. Substituí-lo?
+20500=Arquivo Existente
+20510=Erro ao Ler/Escrever arquivos de processamento batch
+20515=Selecione OK para abortar processamento de arquivo batch.
+20520=Erro no programa
+20530=These line code should not have been encountered. Please notify programmer.
+20540=Não é possível editar elementos pois foi usado /X na linha de comando.
+20545=Não é possível editar abreviaturas pois the /X na linha de comando.
+20550=Percent solver não pode ser usado quando colchetes são tratados como parênteses. Você pode modificar esse modo escolhendo Alterar Preferências no menu Opções.
+20555=Percent Solver não Disponível
+20560=Não é possível trabalhar com mais fórmulas.
+20570=Fórmula em branco.
+20580=Desabilite Percent Solver (F11) antes de criar uma fórmula nova.
+20590=Ocorreu um erro de overflow. Por favor reduza o tamanho dos números e recalcule.
+20600=Ocorreu um erro
+20605=Por favor, saia do programa e relate o erro ao programador. Selecione About MWT... no menu Ajuda para ver o endereço eletrônico (e-mail).
+20610=Espaços não são permitidos em fórmulas
+20620=Caracter Inválido
+20630=Não é possível copiar para nova fórmula.
+20650=Fórmula em branco.
+20655=O modo Percent Solver está habilitado (F11 para sair do modo).
+20660=Atenção, provavelmente a massa isotópica está muito grande para o elemento
+20662=Atenção, provavelmente a massa isotópica está muito pequena para o elemento
+20665=vs massa atômica média de
+20670=Atenção, a massa isotópica está exageradamente pequena para o elemento
+20675=prótons
+20680=Nota: Modo Exact Case está habilitado
+20685=Nota: para % Solver, um colchete esquerdo deve preceder um x
+20690=Nota: colchetes estão sendo tratados como parênteses
+20700=Um ou mais elementos devem ser verificados.
+20705=Maximum hits must be greater than 0.
+20710=Maximum hits deve ser menor que
+20715=Número mínimo de elementos deve ser 0 ou maior.
+20720=Número mínimo de elementos deve ser número máximo de elementos.
+20725=Número máximo de elementos deve ser menor que 65.025
+20730=Uma massa atômica deve ser colocada para elementos customizados.
+20735=Massa Atômica deve ser maior que 0 para elementos customizados.
+20740=Massa molecular deve ser fornecida.
+20745=Massa molecular deve ser maior que 0.
+20755=O máximo para a massa molecular deve ser fornecido.
+20760=O máximo para a massa molecular deve ser maior que 0.
+20765=A porcentagem de cada elemento deve ser fornecida
+20770=A porcentagem deve ser maior que 0.
+20775=As massas customizadas devem conter somente números ou somente letras. Se forem usadas letras, elas devem ser para um símbolo válido ou abreviatura.
+20780=Massa elemental customizada está vazia. Se forem usadas letras, elas devem ser para um símbolo válido ou abreviatura.
+20785=Elemento desconhecido ou abreviatura para massa elemental customizada
+20790=Somente símbolos de elementos ou abreviaturas são permitidas.
+20800=Cuidado, abreviaturas não foram carregadas -- Comando sem efeito.
+
+20900=Error Reading/Writing sequence information file.
+20910=Ions are already present in the ion list. Replace with new ions?
+20920=Subsutituir Íons Existentes
+20930=Carregando Lista de Íons
+20940=Processo interrompido
+20945=Abortado
+20950=Normalizando íons
+20960=Normalizando por região
+20965=Classificando por Intensidade
+20970=Encontrando Íons
+20980=O clipboard está vazio. Sem íons para colar.
+20985=Sem íons
+20990=Colando lista de íon
+21000=Determinando número de íons na lista
+21010=Parsing list
+21020=Não foram encontrados íons válidos no clipboard. Uma lista de íon válida é uma lista de massa intensidade aos pares, separados por vírgula, tabs, ou espaços. Deve ser colocado somente um par massa/intensidade por linha.
+21030=Erro ao gravar dados para arquivo
+21040=Set Range
+21050=Inciar Val
+21055=Finalizar Val
+21060=Set X Axis Range
+21065=Set Y Axis Range
+21070=Enter a new Gaussian Representation quality factor. Higher numbers result in smoother Gaussian curves, but slower updates. Valid range is 1 to 50, default is 20.
+21072=Gaussian Representation Quality
+21075=Enter a new plotting approximation factor. Higher numbers result in faster updates, but give a less accurate graphical representation when viewing a wide mass range (zoomed out). Valid range is 1 to 50, default is 10.
+21077=Plotting Approximation Factor
+21080=Resolving Power Specifications
+21090=Resolving Power
+21100=X Value of Specification
+21110=Please enter the approximate number of ticks to label on the axis
+21115=Axis Ticks
+21120=Creating Gaussian Representation
+21130=Preparing plot
+21135=Desenhando
+21140=Tem certeza que deseja restaurar as opções padrão?
+21145=Restaurar Opções Padrão
+21150=Alinhar Íons
+21155=Máximo Offset
+21160=Incremento Offset
+21165=Alinhando Íons
+
+21500=Todos Arquivos
+21510=Arquivos Texto
+21515=txt
+21520=Arquivos de Dados
+21525=csv
+21530=Arquivos de Seqüência
+21535=seq
+21540=Arquivos Lista de Íon
+21545=txt
+21550=cap
+21555=Capillary Flow Info Files
+
+[CautionStatments]
+; Note: Caution statement keynames are case sensitive; i.e. Bi is different than BI
+; You may add new caution statements if desired; however, you will need to save
+; the file with a name other than Lang_English and change the Language= key
+; since this file is not loaded if the language is English
+22000=Aviso
+Bi=Bi quer dizer bismuto; BI quer dizer boro-iodo.
+Bk=Bk quer dizer berquélio; BK quer dizer boro-potássio.
+Bu=Bu quer dizer o grupo butil; BU quer dizer boro-urânio.
+Cd=Cd quer dizer cádmio; CD quer dizer carbono-deutério.
+Cf=Cf quer dizer califórnio; CF quer dizer carbono-flúor.
+Co=Co quer dizer cobalto; CO quer dizer carbono-oxigênio.
+Cs=Cs quer dizer césio; CS quer dizer carbono-enxofre.
+Cu=Cu quer dizer cobre; CU quer dizer carbono-urânio.
+Dy=Dy quer dizer disprósio; DY quer dizer deutério-ítrio.
+Hf=Hf quer dizer hafnio; HF quer dizer hidrogênio-flúor.
+Ho=Ho quer dizer hólmio; HO quer dizer hidrogênio-oxigênio.
+In=In quer dizer índio; IN quer dizer iodo-nitrogênio.
+Nb=Nb quer dizer nióbio; NB quer dizer nitrogênio-boro.
+Nd=Nd quer dizer neodímio; ND quer dizer nitrogênio-deutério.
+Ni=Ni quer dizer níquel; NI quer dizer nitrogênio-iodo.
+No=No quer dizer nobélio; NO quer dizer nitrogênio-oxigênio.
+Np=Np quer dizer neptúnio; NP quer dizer nitrogênio-fósforo.
+Os=Os quer dizer ósmio; OS quer dizer oxigênio-enxofre.
+Pd=Pd quer dizer paládio; PD quer dizer fósforo-deutério.
+Ph=Ph quer dizer fenil, PH quer dizer fósforo-hidrogênio.
+Pu=Pu quer dizer plutônio; PU quer dizer fósforo-urânio.
+Py=Py quer dizer piridina; PY quer dizer fósforo-ítrio.
+Sb=Sb quer dizer antimônio; SB quer dizer enxofre-boro.
+Sc=Sc quer dizer escândio; SC quer dizer enxofre-carbono.
+Si=Si quer dizer silício; SI quer dizer enxofre-iodo.
+Sn=Sn quer dizer estanho; SN quer dizer sulfor-nitrogênio.
+TI=TI quer dizer trítio-iodo, Ti quer dizer titânio.
+Yb=Yb quer dizer itérbio; YB quer dizer ítrio-boro.
+BPY=BPY quer dizer boro-fósforo-ítrio; Bpy quer dizer bipiridina.
+BPy=BPy quer dizer boro-piridina; Bpy quer dizer bipiridina.
+Bpy=Bpy quer dizer bipiridina.
+Cys=Cys quer dizer cisteína; CYS quer dizer carbono-ítrio-enxofre.
+His=His quer dizer histidina; HIS quer dizer hidrogênio-iodo-enxofre.
+Hoh=HoH quer dizer hólmio-hidrogênio; HOH quer dizer hidrogênio-oxigênio-hidrogênio (água).
+Hyp=Hyp quer dizer hidroxiprolina; HYP quer dizer hidrogênio-ítrio-fósforo.
+OAc=OAc quer dizer oxigênio-actínio; Oac quer dizer acetato.
+Oac=Oac quer dizer acetato.
+Pro=Pro quer dizer prolina; PrO quer dizer praseodímio-oxigênio.
+PrO=Pro quer dizer prolina; PrO quer dizer praseodímio-oxigênio.
+Val=Val quer dizer valina; VAl quer dizer vanádio-alumínio.
+VAl=Val quer dizer valina; VAl quer dizer vanádio-alumínio.
diff --git a/MwtZip/Lang_Russian.ini b/MwtZip/Lang_Russian.ini
new file mode 100644
index 0000000..004140a
--- /dev/null
+++ b/MwtZip/Lang_Russian.ini
@@ -0,0 +1,1021 @@
+; Language customization file for the Molecular Weight Calculator program by Matthew Monroe
+; Contact at alchemistmatt@yahoo.com and http://come.to/alchemistmatt/ or http://www.alchemistmatt.com/
+;
+; When customizing the phrases in this file, the ampersand symbol (&) signifies a
+; keyboard shortcut. For example, the default value for key 1000 is &File. When
+; running the program, the F in File will be underlined and the user may press Alt-F
+; to access the File menu (in addition to clicking on the file menu)
+; To improve usability of the program, please try to include the & symbol in menu items
+; and buttons. Note, however, that if two controls on the same form have the same &
+; shortcut, they will not respond to the alt key in the usual way.
+;
+; In this file, items surround by brackets [] are section headers -- the program ignores them
+; when parsing the file. The key values (1000, 1010, 1020, etc.) should not be changed, with
+; the exception that new caution statements may be added at the end of the file.
+; Lines beginning with a semicolon (;) are also ignored since they are treated as comments
+; However, you should not place a ; at the end of a line with an actual key and caption.
+;
+; Keys with multiple values separated by a vertical line (|) represent multiple items loaded
+; into a ComboBox control. When translating to other languages, you must keep the same number
+; of items in the list, or program functionality will be lost. For example, key 7070 contains
+; hours|minutes|seconds Thus, hours, minutes, and seconds will be loaded into a control, from
+; which the user may select one of them. In Spanish, you would use 7070=horas|segundos|minutos
+;
+; If you create a new .Ini file for a foreign language and would like it posted on my
+; web page, simply e-mail it to me.
+;
+;
+; Translation to Russian - Ïåðåâîä íà ðóññêèé:
+; Michael I. Yahkind - yah@mailru.com - ßõêèíä Ìèõàèë Èëüè÷
+
+[Language]
+Language=Russian
+
+[frmMain Menus]
+; Menu Items
+1000=&Ôàéë
+1010=Ïðàâèòü òàáëèöó &ýëåìåíòîâ
+1020=Ïðàâèòü &àááðåâèàòóðû
+1030=&Âû÷èñëèòü ìàññû äëÿ òåêñòîâîãî ôàéëà
+1040=&Ïå÷àòü ðåçóëüòàòîâ
+1050=Â&ûõîä
+1500=&Ïðàâêà
+1510=&Âûðåçàòü
+1520=&Êîïèðîâàòü
+1530=Â&ñòàâèòü
+1540=&Óäàëèòü
+1550=Ê&îïèðîâàòü òåêóùóþ ôîðìóëó êàê RTF
+1560=Êîïèðîâàòü òåêóùóþ &ìîëåêóëÿðíóþ ìàññó
+1570=Êîïèðîâàòü äàííûå &ïðîöåíòíîãî ñîñòàâà
+1580=Ó&äâîèòü òåêóùóþ ôîðìóëó
+1590=Ñ&òåðåòü âñå ôîðìóëû
+1600=Ñòåðåòü òåêóùóþ &ôîðìóëó
+1610=Ðàñêðûòü &àááðåâèàòóðû
+1620=Ïðåîáðàçîâàòü â &ýìïèðè÷åñêóþ ôîðìóëó
+2000=&Âèä
+2010=&Ìíîãî ôîðìóë
+2020=&Îäíà ôîðìóëà
+2030=&Âû÷èñëèòåëü ïðîöåíòîâ
+2040=&Íåò
+2050=&Äà
+2500=Ñ&ðåäñòâà
+2510=Êîíâåðòåð &ìîëåé/ìàññû è êàëüêóëÿòîð ðàçâåäåíèÿ
+2520=&Èñêàòåëü ôîðìóë
+2530=Êîíâåðòåð îáîçíà÷åíèé &àìèíîêèñëîò
+2533=Ìîäåëèðîâàíèå &ôðàãìåíòàöèè ïåïòèäîâ
+2536=Ìîäåëèðîâàíèå èçîòîïíîãî &ðàñïðåäåëåíèÿ
+2538=Show Isotopic &Distribution for Current Formula
+2540=Ìàòåìàòè÷åñêèé &êàëüêóëÿòîð
+2550=Êàëüêóëÿòîð &ïîòîêîâ äëÿ êàïèëëÿðà
+3000=&Îïöèè
+3010=Âûáðàòü &ÿçûê (Choose Language)
+3020=Ñìåíèòü &ïàðàìåòðû ïðîãðàììû
+3030=Ñìåíèòü &øðèôò ôîðìóë
+3040=Ïî&âåðõ âñåõ îêîí
+3050=&Ñîõðàíèòü/âîññòàíîâèòü çíà÷åíèÿ ïî óìîë÷àíèþ
+3060=&Âîññòàíîâèòü çíà÷åíèÿ è ôîðìóëû ïî óìîë÷àíèþ
+3070=Ñîõðàíèòü &òåêóùèå çíà÷åíèÿ è ôîðìóëû
+3500=Ïî&ìîùü
+3510=&Îáçîð ïðîãðàììû
+3530=Ïîêàçûâàòü &âñïëûâàþùèå ïîäñêàçêè
+3540=Î &ïðîãðàììå MWT
+
+[frmMain Status Messages and Verification Messages]
+3600=Ýòà ñòðîêà:
+3605=Óâåëè÷åíèå
+3610=Âû óâåðåíû, ÷òî õîòèòå ïðåîáðàçîâàòü òåêóùóþ ôîðìóëó â ýìïèðè÷åñêóþ?
+3615=Ïðåîáðàçîâàòü â ýìïèðè÷åñêóþ ôîðìóëó
+3620=Âû óâåðåíû, ÷òî õîòèòå ñòåðåòü òåêóùóþ ôîðìóëó?
+3625=Ñòåðåòü òåêóùóþ ôîðìóëó
+3630=Âû óâåðåíû, ÷òî õîòèòå ðàñêðûòü àááðåâèàòóðû â òåêóùåé ôîðìóëå è çàìåíèòü èõ íà ýêâèâàëåíòû èç ýëåìåíòîâ?
+3635=Ðàñêðûòü àááðåâèàòóðû
+3640=Âîññòàíîâëåíèå çíà÷åíèé è ôîðìóë ïî óìîë÷àíèþ ñîòðåò òåêóùèå ôîðìóëû. Âû óâåðåíû, ÷òî õîòèòå ñäåëàòü ýòî?
+3645=Âîññòàíîâèòü çíà÷åíèÿ è ôîðìóëû ïî óìîë÷àíèþ
+3650=Ââåñòè çàäàííîå ïðîöåíòíîå ñîäåðæàíèå ýòîãî ýëåìåíòà. Ñáðîñ äëÿ âîññòàíîâëåíèÿ âû÷èñëåííîãî çíà÷åíèÿ, Îòìåíà - äëÿ îòìåíû èçìåíåíèé.
+3660=Êëàâèøè ñòðåëîê, PgUp/Dn - ïåðåõîäû (F11 - âûõîä èç Âû÷èñëèòåëÿ %%).
+3665=Ùåë÷îê èëè Enter äëÿ èçìåíåíèÿ çíà÷åíèÿ (F11 - âûõîä èç Âû÷èñëèòåëÿ %%).
+3670=Ãîòîâî
+3700=Âû÷èñëåíèÿ, ùåë÷îê ìûøè èëè ëþáàÿ êëàâèøà äëÿ îñòàíîâêè.
+3710=x =
+3720=Âû÷èñëåííîå çíà÷åíèå
+3730=Çàäàííîå çíà÷åíèå
+3740=Ðàçíîñòü ñ çàäàííûì
+3750=Âû÷èñëèòåëü %% âêë.
+3760=Ðåçóëüòàòû MWT Êàëüêóëÿòîðà ìîëåêóëÿðíûõ ìàññ
+3770=Çíà÷åíèÿ è ôîðìóëû ïî óìîë÷àíèþ âîññòàíîâëåíû.
+3780=Âû óâåðåíû, ÷òî õîòèòå ñòåðåòü âñå ôîðìóëû?
+3785=Ñòåðåòü âñå ôîðìóëû
+3790=Âû óâåðåíû, ÷òî õîòèòå âûéòè?
+3795=Âûõîä èç ïðîãðàììû
+3800=Çàãðóçêà àááðåâèàòóð
+3810=Çàãðóçêà ýëåìåíòîâ
+3820=(èñïîëüçóþòñÿ ñðåäíèå àòîìíûå ìàññû)
+3830=(èñïîëüçóþòñÿ ìàññû èçîòîïîâ)
+3840=(èñïîëüçóþòñÿ öåëûå ìàññû èçîòîïîâ)
+3850=Èñïîëüçîâàíèå íîâîãî ÿçûêà ñîõðàíåíî.
+
+[Phrases common throughout application]
+4000=&Çàêðûòü
+4010=&Äà
+4020=&Îòìåíà
+4030=Â&ûõîä
+; The following is the abbreviation for Molecular Weight
+; It must be exactly two letters long
+4040=MM
+4050=Âíèìàíèå
+
+[frmMain]
+; Form Caption
+4900=MWT Êàëüêóëÿòîð ìîëåêóëÿðíûõ ìàññ
+; Labels
+5000=Ôîðìóëà
+5010=Ðåæèì ìàññ ýëåìåíòîâ
+5020=&Ñðåäíèå
+5021=Èñïîëüçîâàòü ñðåäíèå àòîìíûå ìàññû ýëåìåíòîâ
+5030=&Èçîòîïíûå
+5031=Èñïîëüçîâàòü ìàññû íàèáîëåå ðàñïðîñòðàíåííûõ èçîòîïîâ
+5040=&Öåëûå
+5041=Èñïîëüçîâàòü öåëî÷èñëåííûå ìàññû íàèáîëåå ðàñïðîñòðàíåííûõ èçîòîïîâ
+; TextBoxes
+5051=Çäåñü ââîäÿò ôîðìóëó ìîëåêóëû
+; Buttons
+5100=Âû&÷èñëèòü
+5101=Îïðåäåëèòü ìîëåêóëÿðíóþ ìàññó äëÿ òåêóùåé ôîðìóëû
+5110=&Íîâàÿ ôîðìóëà
+5111=Äîáàâèòü ê ñïèñêó íîâóþ, ÷èñòóþ ñòðîêó äëÿ ôîðìóëû
+5116=Ñîçäàòü íîâóþ, ÷èñòóþ ñòðîêó äëÿ ôîðìóëû
+; Grid control
+5201=Ùåë÷îê äëÿ ââîäà èëè ñáðîñà çàäàííîãî çíà÷åíèÿ
+; Status control
+5301=Äâîéíîé ùåë÷îê ïî ñòðîêå ñîñòîÿíèÿ óâåëè÷èâàåò åå (èñïîëüçîâàòü äëÿ äëèííûõ ñîîáùåíèé)
+5350=MWT Êàëüêóëÿòîð ìîëåêóëÿðíûõ ìàññ óæå çàïóùåí. Âû óâåðåíû, ÷òî õîòèòå çàïóñòèòü íîâóþ êîïèþ?
+5355=Óæå çàïóùåí
+
+[frmAboutBox]
+5500=Î ïðîãðàììå MWT
+5510=Ýòà ïðîãðàììà Freeware, ò.å. áåñïëàòíàÿ
+
+[frmIntro]
+5700=Çàãðóçêà
+
+[frmAminoAcidConverter]
+; Form Caption
+6000=Êîíâåðòåð îáîçíà÷åíèé àìèíîêèñëîò
+; Labels
+6010=Íàáîð àìèíîêèñëîò â 1-áóêâåííîì îáîçíà÷åíèè
+6020=Íàáîð àìèíîêèñëîò â 3-áóêâåííîì îáîçíà÷åíèè
+; TextBoxes
+6031=Çäåñü ââîäÿò íàáîð àìèíîêèñëîò, èñïîëüçóÿ 1-áóêâåííûå îáîçíà÷åíèÿ
+6041=Çäåñü ââîäÿò íàáîð àìèíîêèñëîò, èñïîëüçóÿ 3-áóêâåííûå îáîçíà÷åíèÿ
+; Buttons
+6050=&Êîïèðîâàòü íàáîð àìèíîêèñëîò â ôîðìóëó:
+6060=Êîïèðîâàòü â Ìîäåëèðîâàíèå &ôðàãìåíòàöèè
+; CheckBoxes
+6080=&Äîáàâëÿòü ïðîáåë ïîñëå 10 îñòàòêîâ
+6090=&Ðàçäåëÿòü îñòàòêè òèðå
+
+[frmCalculator]
+; Form Caption
+6500=Êàëüêóëÿòîð
+; Textbox
+6511=Çäåñü ââîäÿò ìàòåìàòè÷åñêîå âûðàæåíèå äëÿ âû÷èñëåíèÿ
+; Buttons
+6520=Âû&÷èñëèòü
+6521=Âû÷èñëèòü òåêóùåå âûðàæåíèå
+; Status control
+6601=Äâîéíîé ùåë÷îê ïî ñòðîêå ñîñòîÿíèÿ óâåëè÷èâàåò åå (èñïîëüçîâàòü äëÿ äëèííûõ ñîîáùåíèé)
+6610=Ðåçóëüòàò
+
+[frmCapillaryCalcs]
+; Form Caption
+7000=Âû÷èñëåíèå îáúåìíîé è ìàññîâîé ñêîðîñòè äëÿ êàïèëëÿðà
+; Combo Boxes
+7010=Ïóñòîé òðóá÷àòûé êàïèëëÿð|Çàïîëíåííûé êàïèëëÿð
+7011=Ïåðåêëþ÷åíèå ìåæäó ïóñòûì è çàïîëíåííûì êàïèëëÿðîì
+7020=Íàéòè ïàäåíèå äàâëåíèÿ|Íàéòè äëèíó êîëîíêè|Íàéòè âíóòðåííèé äèàìåòð|Íàéòè îáúåìíóþ ñêîðîñòü ïîäà÷è|Íàéòè ñêîðîñòü ïîäà÷è, èñïîëüçóÿ "ìåðòâîå âðåìÿ"
+7030=ôóíòû/êâ.äþéì|Ïàñêàëè|êèëîÏàñêàëè|àòìîñôåðû|áàðû (àò)|òîððû (ìì Hg)
+7035=ìêì|äþéìû
+7040=Ïóàçû [ã/(ñì-ñåê)]
+7050=ìë/ìèí|ìêë/ìèí|íë/ìèí
+7060=ñì/÷àñ|ìì/÷àñ|ñì/ìèí|ìì/ìèí|ñì/ñåê|ìì/ñåê
+7070=÷àñû|ìèíóòû|ñåêóíäû
+7080=ìë|ìêë|íë|ïë
+7090=ìîëü/ë|ìèëëèìîëü/ë|ìèêðîìîëü/ë|íàíîìîëü/ë|ïèêîìîëü/ë|ôåìòîìîëü/ë|àòòîìîëü/ë|ìã/ìë|ìêã/ìë|íã/ìë|ìêã/ìêë|íã/ìêë
+7100=ïìîëü/ìèí|ôìîëü/ìèí|àìîëü/ìèí|ïìîëü/ñåê|ôìîëü/ñåê|àìîëü/ñåê
+7110=ìîëü|ììîëü|ìêìîëü|íìîëü|ïìîëü|ôìîëü|àìîëü
+; Labels and frames
+7200=Ïàäåíèå äàâëåíèÿ
+7210=Äëèíà êîëîíêè
+7220=Âíóòðåííèé äèàìåòð êîëîíêè
+7230=Âÿçêîñòü ðàñòâîðèòåëÿ
+7240=Äèàìåòð ÷àñòèö
+7250=Îáúåìíàÿ ñêîðîñòü ïîäà÷è
+7260=Ëèíåéíàÿ ñêîðîñòü
+7270="Ìåðòâîå âðåìÿ" êîëîíêè
+7280=Îáúåì êîëîíêè
+7290=Ïîðèñòîñòü ìåæäó ÷àñòèöàìè (ýïñèëîí)
+7300=Âû÷èñëåíèå ìàññîâîé ñêîðîñòè
+7310=Êîíöåíòðàöèÿ ïðîáû
+7320=Âðåìÿ âêàëûâàíèÿ
+7330=Ìàññîâàÿ ñêîðîñòü ïîäà÷è
+7340=Âêîëîòî ìîëåé
+7350=Âû÷èñëåíèå ðàñøèðåíèÿ ïèêà âíå êîëîíêè
+7360=Êîýôôèöèåíò äèôôóçèè
+7370=Äëèíà ïóñòîé òðóáêè
+7380=Âíóòðåííèé äèàìåòð òðóáêè
+7390=Íà÷àëüíàÿ øèðèíà ïèêà
+7400=Îïòèìàëüíàÿ ñêîðîñòü
+7410=(äëÿ ÷àñòèö 5 ìêì)
+7420=Îòêëîíåíèå âðåìåíè
+7430=Äîïîëíèòåëüíîå îòêëîíåíèå
+7440=Ðåçóëüòèðóþùàÿ øèðèíà ïèêà
+7450=Ïðîöåíò óâåëè÷åíèÿ
+7460=Ôîðìóëà
+7480=MM =
+7500=ñì
+7520=ñì^2/ñåê
+7530=ñåê (êàê îñíîâà)
+7540=ñì/ñåê
+7550=ñåê^2
+7560=ñåê
+7570=ã/ìîëü
+; TextBoxes
+7601=Çäåñü ââîäÿò ìîëåêóëÿðíóþ ìàññó äëÿ èñïîëüçîâàíèÿ â âû÷èñëåíèÿõ
+; Buttons
+7700=Ïîêàçàòü/Ñêðûòü âû&÷èñëåíèå ðàñøèðåíèÿ ïèêà
+7710=&Ïîêàçàòü ïîÿñíÿþùèå óðàâíåíèÿ
+7730=Ïîêàçàòü &óðàâíåíèÿ
+; Option Buttons
+7750=&Èñïîëüçîâàòü ìîëåêóëÿðíóþ ìàññó ñîåäèíåíèÿ òåêóùåé ôîðìóëû
+7760=&Ââåñòè ìîëåêóëÿðíóþ ìàññó
+; CheckBoxes
+7800=&Ñâÿçü ñ ïðåäûäóùèì
+; ToolTips
+7851=Îáû÷íîå çíà÷åíèå âÿçêîñòè 0,0089 Ïóàç
+7861=Îáû÷íîå çíà÷åíèå ïîðèñòîñòè 0,4
+7871=Îáû÷íûé êîýôôèöèåíò äèôôóçèè äëÿ íåáîëüøèõ îðãàíè÷åñêèõ ñîåäèíåíèé 0,000001, ò.å. 1E-6; äëÿ ïåïòèäîâ 0,00005, ò.å. 5E-5
+; Menus
+7900=&Load Values
+7910=&Save Values
+7950=&Capillary Flow Calculations
+
+[frmChangeFont]
+; Form Caption
+8000=Ñìåíèòü øðèôò ôîðìóë
+; Combo Boxes
+; Labels
+8050=Øðèôò ôîðìóë ñåé÷àñ:
+8060=Ñìåíèòü øðèôò ôîðìóë íà [ðåêîìåíäóåòñÿ MS Sans Serif]:
+8070=Ðàçìåð:
+; Buttons
+
+[frmChangeValue]
+; Form Caption
+8200=Èçìåíèòü çíà÷åíèå
+; Buttons
+8210=&Âîññòàíîâèòü ïî óìîë÷àíèþ
+
+[frmChangeLanguage]
+8400=Âûáðàòü ÿçûê (Choose Language)
+; Labels
+8410=Äîñòóïíûå ÿçûêè äàíû íèæå. Âûáåðèòå ÿçûê, êîòîðûé Âû õîòèòå èñïîëüçîâàòü. Available languages are shown below. Choose the language you wish to use.
+8420=No language files are available. Visit the author's homepage to download alternate languages.
+
+[frmDiff]
+8600=Ðàçíîñòè Âû÷èñëèòåëÿ ïðîöåíòîâ
+8610=&Êîïèðîâàòü
+8611=Êîïèðîâàòü ðåçóëüòàòû â áóôåð
+
+[frmEditAbbrev]
+9000=Ïðàâêà àááðåâèàòóð
+; Buttons
+9010=&Âîññòàíîâèòü ïî óìîë÷àíèþ
+9011=Âîññòàíîâèòü àááðåâèàòóðû, èñïîëüçóåìûå ïðîãðàììîé ïî óìîë÷àíèþ
+9020=&Óäàëèòü
+; Messages
+9050=Äîñòèãíóò ìàêñèìóì
+9060=Ñîæàëåþ, äîïóñòèìî òîëüêî 50 àááðåâèàòóð àìèíîêèñëîò.
+9070=Ñîæàëåþ, äîïóñòèìî òîëüêî 50 îáû÷íûõ àááðåâèàòóð.
+9080=Ñëåäóåò ââåñòè îáû÷íóþ àááðåâèàòóðó.
+9090=Àááðåâèàòóðà/ôîðìóëà áóäóò èçìåíåíû íà ââåäåííîå çíà÷åíèå. Âûáåðèòå Óäàëèòü äëÿ óäàëåíèÿ çíà÷åíèÿ, èëè Îòìåíà äëÿ îòìåíû èçìåíåíèé.
+9100=Âû óâåðåíû, ÷òî õîòèòå îòìåíèòü âñå èçìåíåíèÿ?
+9105=Çàêðûòèå êîðîáêè ïðàâêè àááðåâèàòóð
+9110=Âû óâåðåíû, ÷òî õîòèòå âîññòàíîâèòü àááðåâèàòóðû, èñïîëüçóåìûå ïðîãðàììîé ïî óìîë÷àíèþ?
+9115=Âîññòàíîâèòü àááðåâèàòóðû ïî óìîë÷àíèþ
+;Table Tool Tip
+9140=
+9141=Ùåë÷îê äëÿ èçìåíåíèÿ çíà÷åíèÿ
+; Table Column Titles
+9150=Çàðÿä
+9160=Ôîðìóëà
+9170=Îáû÷íàÿ àááðåâèàò.
+9180=Àìèíîêèñëîòà
+9190=1-áóêâåííûå
+
+[frmEditElem]
+9200=Ïðàâêà ýëåìåíòîâ
+; Buttons
+9210=&Âîññòàíîâèòü ïî óìîë÷àíèþ
+9211=Äëÿ âñåõ ýëåìåíòîâ âîññòàíîâèòü èõ ñðåäíèå àòîìíûå ìàññû, íàéäåííûå â ïðèðîäå
+9220=&Ñáðîñ
+9230=Èñïîëüçîâàòü &ñðåäíèå àòîìíûå ìàññû
+9231=Äëÿ âñåõ ýëåìåíòîâ âîññòàíîâèòü èõ ñðåäíèå àòîìíûå ìàññû, íàéäåííûå â ïðèðîäå
+9240=Èñïîëüçîâàòü ìàññû &èçîòîïîâ
+9241=Äëÿ âñåõ ýëåìåíòîâ âîññòàíîâèòü ìàññû èõ íàèáîëåå ðàñïðîñòðàíåííûõ èçîòîïîâ (äëÿ ìàññ-ñïåêòðîìåòðèè âûñîêîãî ðàçðåøåíèÿ)
+9245=Èñïîëüçîâàòü &öåëûå ìàññû èçîòîïîâ
+9246=Äëÿ âñåõ ýëåìåíòîâ âîññòàíîâèòü öåëî÷èñëåííûå ìàññû èõ íàèáîëåå ðàñïðîñòðàíåííûõ èçîòîïîâ (äëÿ ìàññ-ñïåêòðîìåòðèè íèçêîãî ðàçðåøåíèÿ)
+; Messages
+9250=Ìàññà/ïîãðåøíîñòü áóäóò èçìåíåíû íà ââåäåííîå çíà÷åíèå. Âûáåðèòå Ñáðîñ äëÿ çíà÷åíèÿ ïî óìîë÷àíèþ, èëè Îòìåíà äëÿ îòìåíû èçìåíåíèé.
+9260=Âû óâåðåíû, ÷òî õîòèòå âîññòàíîâèòü ñðåäíèå àòîìíûå ìàññû äëÿ âñåõ ýëåìåíòîâ?
+9265=Èñïîëüçîâàòü ñðåäíèå àòîìíûå ìàññû
+9270=Âû óâåðåíû, ÷òî õîòèòå âîññòàíîâèòü ìàññû íàèáîëåå ðàñïðîñòðàíåííûõ èçîòîïîâ äëÿ âñåõ ýëåìåíòîâ?
+9275=Èñïîëüçîâàòü ìàññû èçîòîïîâ
+9280=Âû óâåðåíû, ÷òî õîòèòå âîññòàíîâèòü öåëî÷èñëåííûå ìàññû íàèáîëåå ðàñïðîñòðàíåííûõ èçîòîïîâ äëÿ âñåõ ýëåìåíòîâ?
+9285=Èñïîëüçîâàòü öåëûå ìàññû èçîòîïîâ
+9290=Âû óâåðåíû, ÷òî õîòèòå âîññòàíîâèòü ìàññû, èñïîëüçóåìûå ïî óìîë÷àíèþ (ñðåäíèå àòîìíûå ìàññû), äëÿ âñåõ ýëåìåíòîâ?
+9295=Âîññòàíîâèòü ìàññû ïî óìîë÷àíèþ
+9300=Åñëè ñäåëàòü ýòî, îòìåíà íåâîçìîæíà.
+9310=Âû óâåðåíû, ÷òî õîòèòå îòìåíèòü âñå èçìåíåíèÿ?
+9315=Çàêðûòèå êîðîáêè ïðàâêè ýëåìåíòîâ
+;Table Tool Tip
+9340=
+9341=Ùåë÷îê äëÿ èçìåíåíèÿ çíà÷åíèÿ
+;Table Column Titles
+9350=Ýëåìåíò
+9360=Ìàññà
+9370=Ïîãðåøíîñòü
+; Combo boxes
+9380=Ñèìâîë ýëåìåíòà|Àòîìíûé íîìåð|Ïîãðåøíîñòü|Çàðÿä
+9390=Ñîðòèðîâàòü ýëåìåíòû ïî:
+
+[frmEquationsBroadening]
+9500=Óðàâíåíèÿ ðàñøèðåíèÿ ïèêà âíå êîëîíêè Extra-column broadening equations
+
+[frmEquationsOpenTube]
+9550=Óðàâíåíèÿ ïîòîêà â ïóñòîì êàïèëëÿðå Equations for flow in an open tube
+
+[frmEquationsPackedCapillary]
+9600=Óðàâíåíèÿ ïîòîêà â çàïîëíåííîì êàïèëëÿðå Equations for flow in a packed capillary
+
+[frmFinderModeWarn]
+; Instructions Label
+9700= Îáû÷íîå èñïîëüçîâàíèå Èñêàòåëÿ ôîðìóë - êîãäà èçâåñòíà ìîíîèçîòîïíàÿ ìàññà ñîåäèíåíèÿ (åå îáû÷íî îïðåäåëÿþò ìàññ-ñïåêòðîìåòðèåé) è íóæíî íàéòè ñîåäèíåíèÿ, ïîòåíöèàëüíî ñîîòâåòñòâóþùèå ýòîé ìàññå.
+9701=Íàïðèìåð, äëÿ ñîåäèíåíèÿ, êîòîðîå ìîæåò ñîäåðæàòü C,H,N,O, íàéäåíà ìàññà 16,0312984 Äàëüòîí, è íóæíû âîçìîæíûå ýìïèðè÷åñêèå ôîðìóëû. Ïîèñê ñ îòêëîíåíèåì äëÿ ìàññû 5000 ÷.í.ì. äàåò H2N, CH4 è O, ñ îòêëîíåíèåì 500 ÷.í.ì. - òîëüêî CH4, ÷òî ÿâëÿåòñÿ ïðàâèëüíûì îòâåòîì.
+9702=×òîáû ïðàâèëüíî èñïîëüçîâàòü ýòî ñðåäñòâî, ïðîãðàììà äîëæíà íàõîäèòüñÿ â ðåæèìå Èçîòîïíûõ ìàññ ýëåìåíòîâ. Ýòî ìîæíî ñäåëàòü, âûáðàâ Ïðàâèòü òàáëèöó ýëåìåíòîâ â ìåíþ Ôàéë, èëè â ãëàâíîì îêíå, èëè çäåñü, èëè ïðîãðàììà ìîæåò ïåðåõîäèòü â ýòîò ðåæèì àâòîìàòè÷åñêè.
+9703=×òî Âû õîòèòå:
+9705= Îáû÷íîå èñïîëüçîâàíèå Ìîäåëèðîâàíèÿ ôðàãìåíòàöèè - ïðåäñêàçàíèå ìàññ ôðàãìåíòîâ, êîòîðûå áóäóò íàáëþäàòüñÿ ïðè ìàññ-ñïåêòðîìåòðèè ïåïòèäà, êîãäà åãî èîíèçèðóþò, ââîäÿò â ïðèáîð è ïðîèñõîäèò åãî ôðàãìåíòàöèÿ ïî îñíîâíîé öåïè.
+9706=Ôðàãìåíòàöèÿ ïåïòèäîâ îáû÷íî èäåò ïî àìèäíûì ñâÿçÿì. Íàïðèìåð ïåïòèä Gly-Leu-Tyr áóäåò äàâàòü ôðàãìåíòû Gly-Leu, Leu-Tyr, Gly, Leu è Tyr. Êðîìå òîãî, ðàñùåïëåíèå àìèäíûõ ñâÿçåé ìîæåò ïðîèñõîäèòü â ðàçëè÷íûõ ìåñòàõ, è ýòî ïðèâîäèò ê ðàçíûì ìàññàì ôðàãìåíòîâ.
+; Buttons
+9720=&Ïðîäîëæèòü
+; Option Buttons
+9750=Ïåðåéòè ñåé÷àñ â ðåæèì &Èçîòîïíûõ ìàññ ýëåìåíòîâ.
+9760=Âñåãäà &àâòîìàòè÷åñêè ïåðåõîäèòü â ðåæèì Èçîòîïíûõ ìàññ.
+9770=Ïðîäîëæèòü, èñïîëüçóÿ ðåæèì &Ñðåäíèõ ìàññ ýëåìåíòîâ.
+; CheckBoxes
+9780=Ïðåêðàòèòü ïîêàçûâàòü ýòî &îêíî.
+
+[frmFinder]
+10000=Èñêàòåëü ôîðìóë
+; Labels
+10010=Âûáèðàþò íóæíûå ýëåìåíòû, ââîäÿò ìîëåêóëÿðíóþ ìàññó èëè ïðîöåíòíûé ñîñòàâ, çàòåì íàæèìàþò Âû÷èñëèòü, ÷òîáû íàéòè ñîåäèíåíèÿ, ñîîòâåòñòâóþùèå çàäàíèþ.
+10020=Ìàêñèìàëüíàÿ ìàññà ñîåäèíåíèÿ:
+10030=Çàäàííàÿ ìîëåêóëÿðíàÿ ìàññà:
+10040=Îòêëîíåíèå äëÿ ìàññû:
+10050=Îòêëîíåíèå äëÿ ïðîöåíòîâ:
+10060=Ìèí
+10070=Ìàêñ
+10080=Ýëåìåíòû
+10090=%%
+10100=Ìàêñ.÷èñëî ôîðìóë
+10105=Àòîìíàÿ ìàññà
+; Percent completed status messages
+10110=% âûïîëíåíî
+10115=Ñîðòèðîâêà
+10120=Ïîèñê
+10125=Ðàáîòà
+10130=Âûïîëíåíî
+10135=ñîåäèíåíèé
+10140=Ñîðòèðîâêà ïðåðâàíà
+10145=Âû÷èñëåíèÿ ïðåðâàíû
+10150=Ôîðìàò
+10155=Ñäåëàíî
+10160=Ôîðìàò ïðåðâàí
+; Listboxes & Textboxes
+10201=Äâîéíîé ùåë÷îê ïî ëþáîé ñòðîêå óâåëè÷èâàåò åå (èñïîëüçîâàòü äëÿ äëèííûõ ñòðîê)
+10221=Âåëè÷èíà, íà êîòîðóþ ìîëåêóëÿðíàÿ ìàññà íàéäåííîãî ñîåäèíåíèÿ ìîæåò îòêëîíÿòüñÿ îò çàäàííîé
+10231=Âåëè÷èíà, íà êîòîðóþ ïðîöåíòíûå ñîäåðæàíèÿ ýëåìåíòîâ â íàéäåííîì ñîåäèíåíèè ìîãóò îòêëîíÿòüñÿ îò çàäàííûõ
+10241=Ìàêñèìàëüíîå ÷èñëî íàéäåííûõ ñîåäèíåíèé
+10251=Ìèíèìàëüíîå ÷èñëî àòîìîâ â íàéäåííîì ñîåäèíåíèè
+10256=Ìàêñèìàëüíîå ÷èñëî àòîìîâ â íàéäåííîì ñîåäèíåíèè
+10260=%
+10261=Çàäàííîå ïðîöåíòíîå ñîäåðæàíèå ýëåìåíòà
+10270=Ý
+10271=Çäåñü ââîäÿò àòîìíóþ ìàññó ýòîãî ýëåìåíòà, èëè ñèìâîë ýëåìåíòà, èëè àááðåâèàòóðó
+; Note the following is 'dm' in English, standing for 'delta mass' or the mass difference
+; of the given result's mass versus the target mass
+10280=dM
+; Note the following is 'ppm' in English, standing for 'parts per million'
+10285=ppm
+; Buttons
+10300=&Îïöèè Èñêàòåëÿ ôîðìóë
+10301=Ãîðÿ÷àÿ êëàâèøà: Ctrl+O
+10310=Âû&÷èñëèòü
+10311=Íàéòè ñîåäèíåíèÿ, ñîîòâåòñòâóþùèå çàäàííûì ïàðàìåòðàì
+10320=&Ïå÷àòü ...
+10330=Êîïè&ðîâàòü êàê RTF
+10331=Êîïèðîâàòü ðåçóëüòàòû â áóôåð â ôîðìàòå RTF
+10340=&Êîïèðîâàòü
+10341=Êîïèðîâàòü ðåçóëüòàòû â áóôåð
+10345=&Display Iso Abundance
+10346=Display the Isotopic Distribution of the currently selected compound (Ctrl+D)
+; Option Buttons
+10350=Ïî &ìîëåêóëÿðíîé ìàññå
+10360=Ïî ïðîöåíòíîìó &ñîñòàâó
+; CheckBoxes
+10370=÷.í.ì. (ppm)
+; Elements (and Custom element phrase)
+10400=Óãëåðîä
+10405=Âîäîðîä
+10410=Àçîò
+10415=Êèñëîðîä
+10420=Äðóãîé
+; Messages
+10450=Íàæàòà êëàâèøà.
+10455=Îòìåíà
+10460=Ùåë÷îê ìûøè âíå êîðîáêè ðåçóëüòàòîâ.
+10465=Îñòàíîâêà ôîðìàòà.
+10470=Îñòàíîâêà ñîðòèðîâêè.
+10480=Ñóììà ïðîöåíòíûõ ñîäåðæàíèé íå ðàâíà 100%.
+10485=Ïðîäîëæèòü âû÷èñëåíèÿ?
+10490=Íåâîçìîæíî âû÷èñëèòü
+10500=Íàæàòà êëàâèøà.
+10505=Ùåë÷îê ìûøè âíå êîðîáêè ðåçóëüòàòîâ.
+10510=Îñòàíîâêà âû÷èñëåíèé.
+10515=Äîñòèãíóòî ìàêñèìàëüíîå ÷èñëî íàéäåííûõ ñîåäèíåíèé.
+10520=Ìàêñèìàëüíîå ÷èñëî ôîðìóë
+10530=Íàéäåíî ñîåäèíåíèé
+; Note: the following is used when displaying the results of a percent composition
+; search in the Formula Finder. A synonym for 'has' would be 'contains' or 'is composed of'
+10535=
+10540=Îøèáêà ïàìÿòè. Ñïèñîê ðåçóëüòàòîâ, âåðîÿòíî, ïîëîí. Ðåçóëüòàòû ïîêàçàíû.
+10545=Íåõâàòêà ïàìÿòè
+10550=Êîðîáêà ðåçóëüòàòîâ ïóñòà.
+10555=Íå÷åãî êîïèðîâàòü
+10560=Íå÷åãî ïå÷àòàòü
+10565=Âû óâåðåíû, ÷òî õîòèòå ðàñïå÷àòàòü òåêóùèå ðåçóëüòàòû?
+10570=Ïå÷àòü
+
+[frmFinderOptions]
+10800=Îïöèè Èñêàòåëÿ ôîðìóë
+; Labels
+10810=Èñïîëüçîâàòü ïåðåêëþ÷àòåëè äëÿ âûáîðà ðàçëè÷íûõ îïöèé Èñêàòåëÿ ôîðìóë.
+; Textboxes & Comboboxes
+10821=Ìèíèìàëüíûé çàðÿä, îãðàíè÷èâàþùèé íàéäåííûå ñîåäèíåíèÿ
+10831=Ìàêñèìàëüíûé çàðÿä, îãðàíè÷èâàþùèé íàéäåííûå ñîåäèíåíèÿ
+10840=Ïîëíûé ïîèñê|Îãðàíè÷åííûé ïîèñê
+10841=Ïîëíûé ïîèñê íàõîäèò âñå ñîîòâåòñòâóþùèå ñîåäèíåíèÿ, à îãðàíè÷åííûé - ñîåäèíåíèÿ â çàäàííîì èíòåðâàëå àòîìîâ (ïîëíûé îáû÷íî áûñòðåå)
+10850=Ñîðòèðîâêà ïî ôîðìóëå
+10851=Ìåòîä ñîðòèðîâêè ðåçóëüòàòîâ, ñëåäóåò ïîâòîðèòü âû÷èñëåíèÿ äëÿ íîâîé ñîðòèðîâêè
+10855=Ñîðòèðîâêà ïî çàðÿäó
+10860=Ñîðòèðîâêà ïî MM
+10865=Ñîðòèðîâêà ïî m/z
+10870=Çàäàííîå îòíîøåíèå ìàññà/çàðÿä
+10875=Çàäàííàÿ ìîëåêóëÿðíàÿ ìàññà
+; CheckBoxes
+10900=Âû÷èñëèòü &çàðÿä
+10901=Âû÷èñëèòü îáùèé çàðÿä äëÿ êàæäîãî íàéäåííîãî ñîåäèíåíèÿ
+10910=&Èíòåðâàë çàðÿäîâ
+10911=Îãðàíè÷èòü íàéäåííûå ñîåäèíåíèÿ çàäàííûì èíòåðâàëîì çàðÿäîâ
+10920=&Âû÷èñëèòü m/z
+10921=Âû÷èñëèòü îòíîøåíèå ìàññà/çàðÿä äëÿ êàæäîãî íàéäåííîãî ñîåäèíåíèÿ
+10930=&Íàéòè çàäàííîå m/z
+10931=Íàéòè ñîåäèíåíèÿ ñ îòíîøåíèåì ìàññà/çàðÿä, ðàâíûì çàäàííîìó
+10940=&Ñîðòèðîâêà
+10941=Ïðåâðàòèòü ðåçóëüòàòû â ýìïèðè÷åñêèå ôîðìóëû è îòñîðòèðîâàòü èõ
+10950=&Îãðàíè÷åíèå àòîìîâ H
+10951=Îãðàíè÷èòü êîëè÷åñòâî àòîìîâ âîäîðîäà â íàéäåííûõ ñîåäèíåíèÿõ ðåàëüíûì ÷èñëîì
+10960=&Àâòîìàòè÷åñêè óñòàíàâëèâàòü Ìèí è Ìàêñ ïðè îãðàíè÷åííîì ïîèñêå
+10961=Àâòîìàòè÷åñêè óñòàíàâëèâàòü çíà÷åíèÿ ìèíèìóìà è ìàêñèìóìà àòîìîâ ïðè îãðàíè÷åííîì ïîèñêå íà ðåàëüíûé äëÿ çàäàííîé ìàññû èíòåðâàë
+
+[frmMMconvert]
+11000=Êîíâåðòåð ìîëåé/ìàññû è êàëüêóëÿòîð ðàçâåäåíèÿ
+; Combo Boxes
+11010=Ïðåîáðàçîâàòü êîëè÷åñòâî|Íàéòè êîíöåíòðàöèþ|Âû÷èñëèòü ðàçâåäåíèå
+11011=Ïðåîáðàçîâàíèå ìåæäó ðàçëè÷íûìè åäèíèöàìè èçìåðåíèÿ êîëè÷åñòâà, èëè âû÷èñëåíèå êîíöåíòðàöèè ñîåäèíåíèÿ, à òàêæå âû÷èñëåíèå ðàçâåäåíèÿ
+11020=ìîëè|ìèëëèìîëè|ìèêðîìîëè|íàíîìîëè|ïèêîìîëè|ôåìòîìîëè|àòòîìîëè|êèëîãðàììû|ãðàììû|ìèëëèãðàììû|ìèêðîãðàììû|ôóíòû|óíöèè|ìèêðîëèòðû|ìèëëèëèòðû|ëèòðû|ãàëëîíû|êâàðòû|ïèíòû
+11021=Èñõîäíàÿ åäèíèöà èçìåðåíèÿ êîëè÷åñòâà
+11026=Åäèíèöà èçìåðåíèÿ êîëè÷åñòâà
+11030=ìèêðîëèòðû|ìèëëèëèòðû|ëèòðû|ãàëëîíû|êâàðòû|ïèíòû
+11031=Åäèíèöà èçìåðåíèÿ îáúåìà
+11041=Êîíå÷íàÿ åäèíèöà èçìåðåíèÿ êîëè÷åñòâà
+11051=Åäèíèöà èçìåðåíèÿ êîíöåíòðàöèè
+; Labels
+11080=ã/ìë
+; Textboxes
+11101=Êîëè÷åñòâî ñîåäèíåíèÿ â èñõîäíûõ åäèíèöàõ
+11106=Êîëè÷åñòâî ñîåäèíåíèÿ, ðàñòâîðåííîãî â ðàñòâîðèòåëå
+11111=Ïëîòíîñòü ñîåäèíåíèÿ
+11121=Îáúåì ðàñòâîðèòåëÿ, â êîòîðîì ðàñòâîðåíî ñîåäèíåíèå
+11131=Êîíöåíòðàöèÿ ñîåäèíåíèÿ â ðàñòâîðèòåëå
+; Buttons
+11150=Âû÷èñëèòü &êîëè÷åñòâî
+11151=Âû÷èñëèòü êîëè÷åñòâî ñîåäèíåíèÿ, èñïîëüçóÿ îáúåì è êîíöåíòðàöèþ
+11160=Âû÷èñëèòü &îáúåì
+11161=Âû÷èñëèòü îáúåì ðàñòâîðèòåëÿ, èñïîëüçóÿ êîëè÷åñòâî è êîíöåíòðàöèþ
+11170=Âû÷èñëèòü êîí&öåíòðàöèþ
+11171=Âû÷èñëèòü êîíöåíòðàöèþ ñîåäèíåíèÿ, èñïîëüçóÿ êîëè÷åñòâî è îáúåì
+
+; Dilution-related controls
+11200=Âû÷èñëåíèå ðàçâåäåíèÿ
+11205=Âû÷èñëåíèå èñïàðåíèÿ èëè ñóáëèìàöèè
+11210=Íàéòè îáúåìû ðàñòâîðà/ðàñòâîðèòåëÿ|Íàéòè îáùèé êîíå÷íûé îáúåì|Íàéòè êîíå÷íóþ êîíöåíòðàöèþ|Íàéòè èñõîäíóþ êîíöåíòðàöèþ
+11211=Âåëè÷èíà, êîòîðóþ íóæíî íàéòè ïðè âû÷èñëåíèè ðàçâåäåíèÿ
+11220=&Ñâÿçàòü èñõîäíóþ êîíöåíòðàöèþ ñ ðàñ÷åòíîé êîíöåíòðàöèåé
+11221=Êîïèðîâàòü ðàñ÷åòíóþ êîíöåíòðàöèþ èç âû÷èñëåíèÿ êîíöåíòðàöèè â èñõîäíóþ êîíöåíòðàöèþ äëÿ ðàçâåäåíèÿ (è íàîáîðîò ïðè èçìåíåíèè ïîñëåäíåé)
+11230=Ñâÿçàòü &åäèíèöû èçìåðåíèÿ îáúåìà
+11231=Èñïîëüçîâàòü îäèíàêîâûå åäèíèöû èçìåðåíèÿ äëÿ îáúåìà èñõîäíîãî ðàñòâîðà, îáúåìà ðàñòâîðèòåëÿ è îáùåãî êîíå÷íîãî îáúåìà
+; Dilution related labels and textbox tooltips
+11250=Èñ&õîäíàÿ êîíöåíòðàöèÿ
+11256=Êîíöåíòðàöèÿ ðàñòâîðåííîãî âåùåñòâà â èñõîäíîì ðàñòâîðå
+11260=Îá&úåì èñõîäíîãî ðàñòâîðà
+11266=Îáúåì (àëèêâîòà) èñõîäíîãî ðàñòâîðà, âçÿòûé äëÿ ðàçâåäåíèÿ
+11270=Êî&íå÷íàÿ êîíöåíòðàöèÿ
+11276=Êîíöåíòðàöèÿ ðàñòâîðåííîãî âåùåñòâà â êîíå÷íîì ðàñòâîðå ïîñëå ðàçâåäåíèÿ
+11280=Îáúåì &äîáàâëåííîãî ðàñòâîðèòåëÿ
+11286=Îáúåì ðàñòâîðèòåëÿ, äîáàâëåííûé ê îáúåìó (àëèêâîòå) èñõîäíîãî ðàñòâîðà
+11290=Îá&ùèé êîíå÷íûé îáúåì
+11296=Îáùèé îáúåì êîíå÷íîãî ðàñòâîðà ïîñëå ñìåøèâàíèÿ èñõîäíîãî ðàñòâîðà è äîáàâëåííîãî ðàñòâîðèòåëÿ
+
+[frmProgramPreferences]
+11500=Ïàðàìåòðû ïðîãðàììû MWT
+; Frame labels
+11510=Ðåæèì àááðåâèàòóð (F3)
+11520=Ðåæèì ðàñïîçíàâàíèÿ ðåãèñòðà (F4)
+11530=Ðåæèì ñòàíäàðòíûõ ïîãðåøíîñòåé (F12)
+11540=Îïöèè ðåæèìà ìàññ ýëåìåíòîâ äëÿ äîïîëíèòåëüíûõ ñðåäñòâ
+11550=Îïöèè âûõîäà èç ïðîãðàììû
+; Buttons
+11600=&Ñîõðàíèòü ïàðàìåòðû
+11610=&Âîññòàíîâèòü ïàðàìåòðû ïî óìîë÷àíèþ
+; Option Buttons
+11650=Îáû÷íûå
+11651=Ðàñïîçíàâàòü îáû÷íûå àááðåâèàòóðû, íî íå àááðåâèàòóðû àìèíîêèñëîò
+11655=Îáû÷íûå + Àìèíîêèñëîòû
+11656=Ðàñïîçíàâàòü îáû÷íûå àááðåâèàòóðû è àááðåâèàòóðû àìèíîêèñëîò
+11660=Íåò
+11661=Èãíîðèðîâàòü âñå àááðåâèàòóðû
+11665=Ïðåîáðàçîâàíèå â âåðõíèé ðåãèñòð
+11666=Ôîðìóëû ïðàâèëüíî ïðåîáðàçóþòñÿ â âåðõíèé ðåãèñòð ïðè àíàëèçå
+11670=Òî÷íîå ñîáëþäåíèå ðåãèñòðà
+11671=Ôîðìóëû íåîáõîäèìî ââîäèòü ñ ïðàâèëüíûì ñîáëþäåíèåì âåðõíåãî ðåãèñòðà
+11675=Ïðîèçâîëüíûé ðåãèñòð
+11676=Ïðè ââîäå ôîðìóë â íèæíåì ðåãèñòðå îíè ïðàâèëüíî âîñïðèíèìàþòñÿ áåç ïðåîáðàçîâàíèÿ â âåðõíèé ðåãèñòð
+11680=Ñîêðàùåííûå
+11681=Ïîêàçûâàòü ñòàíäàðòíûå ïîãðåøíîñòè â ñîêðàùåííîé ôîðìå
+11685=Ýêñïîíåíöèàëüíûå
+11686=Ïîêàçûâàòü ñòàíäàðòíûå ïîãðåøíîñòè â ýêñïîíåíöèàëüíîé ôîðìå
+11690=Äåñÿòè÷íûå
+11691=Ïîêàçûâàòü ñòàíäàðòíûå ïîãðåøíîñòè â ôîðìå äåñÿòè÷íîé äðîáè
+11695=Íåò
+11696=Íå ïîêàçûâàòü ñòàíäàðòíûå ïîãðåøíîñòè
+11700=Âûõîä ñ ïîäòâåðæäåíèåì, òàêæå ïî êëàâèøå Esc
+11701=Îïðåäåëÿåò, áóäåò ëè çàïðîñ íà ïîäòâåðæäåíèå ïðè âûõîäå èç ïðîãðàììû è âîçìîæåí ëè âûõîä ïî êëàâèøå Esc
+11705=Âûõîä áåç ïîäòâåðæäåíèÿ, òàêæå ïî êëàâèøå Esc
+11710=Âûõîä ñ ïîäòâåðæäåíèåì, êëàâèøà Esc íå èñïîëüçóåòñÿ
+11715=Âûõîä áåç ïîäòâåðæäåíèÿ, êëàâèøà Esc íå èñïîëüçóåòñÿ
+; CheckBoxes
+11750=&Ïåðåìåùåíèå âïåðåä ïðè âû÷èñëåíèÿõ (F9)
+11751=Ïåðåìåùàòü êóðñîð íà ëèíèþ ñëåäóþùåé ôîðìóëû ïîñëå âû÷èñëåíèÿ ìîëåêóëÿðíîé ìàññû òåêóùåé ôîðìóëû
+11760=Îáðàáàòûâàòü &êâàäðàòíûå ñêîáêè êàê êðóãëûå
+11761=Îáðàáàòûâàòü êâàäðàòíûå ñêîáêè, [ è ], êàê êðóãëûå, à íå êàê "çàïîëíèòåëè" Âû÷èñëèòåëÿ ïðîöåíòîâ
+11770=Àâòîêîïèðîâàíèå &ìîëåêóëÿðíîé ìàññû (Ctrl+U)
+11771=Àâòîìàòè÷åñêè êîïèðîâàòü ìîëåêóëÿðíóþ ìàññó âûáðàííîé ôîðìóëû â áóôåð ïîñëå êàæäîãî âû÷èñëåíèÿ
+11780=Âû&÷èñëÿòü çàðÿä
+11781=Âû÷èñëÿòü çàðÿä ñîåäèíåíèé (î÷åíü óïðîùåííûå ïðàâèëà, íå ó÷èòûâàþòñÿ äâîéíûå è òðîéíûå ñâÿçè è äð.)
+11800=Âñåãäà àâòîìàòè÷åñêè ïåðåõîäèòü â ðåæèì &Èçîòîïíûõ ìàññ ýëåìåíòîâ
+11801=Âñåãäà àâòîìàòè÷åñêè ïåðåõîäèòü â ðåæèì Èçîòîïíûõ ìàññ ýëåìåíòîâ ïðè âêëþ÷åíèè Èñêàòåëÿ ôîðìóë èëè Ìîäåëèðîâàíèÿ ôðàãìåíòàöèè
+11810=&Íèêîãäà íå ïîêàçûâàòü ïðåäóïðåäèòåëüíîå îêíî î ðåæèìå ìàññ ýëåìåíòîâ
+11811=Íèêîãäà íå ïîêàçûâàòü ïðåäóïðåäèòåëüíîå îêíî î òåêóùåì ðåæèìå ìàññ ýëåìåíòîâ ïðè âêëþ÷åíèè Èñêàòåëÿ ôîðìóë èëè Ìîäåëèðîâàíèÿ ôðàãìåíòàöèè
+11820=&Àâòîñîõðàíåíèå ïàðàìåòðîâ, çíà÷åíèé, ôîðìóë ïðè âûõîäå
+11821=Àâòîìàòè÷åñêè ñîõðàíÿòü ïàðàìåòðû, çíà÷åíèÿ è ôîðìóëû ïðè âûõîäå èç ïðîãðàììû
+11830=Ïîêàçûâàòü ïðåä&óïðåæäåíèÿ (F7)
+11831=Ïîêàçûâàòü ïðåäóïðåæäåíèÿ, êîãäà â ôîðìóëå âîçìîæíà íåîäíîçíà÷íàÿ êîìáèíàöèÿ ñèìâîëîâ (íàïðèìåð Co è CO)
+11840=Ïîêàçûâàòü ïåðåêëþ÷àòåëü &Ðåæèì ìàññ ýëåìåíòîâ
+11841= ãëàâíîì îêíå ïîêàçûâàòü ïåðåêëþ÷àòåëü äëÿ áûñòðîé ñìåíû ðåæèìîâ ìàññ ýëåìåíòîâ
+11850=Ïîêàç&ûâàòü âñïëûâàþùèå ïîäñêàçêè
+11851=Ïîêàçûâàòü êîðîòêèå ñîîáùåíèÿ-ïîäñêàçêè òîãäà, êîãäà ìûøü ïðîõîäèò íàä íåêîòîðûìè êíîïêàìè è çîíàìè
+11860=Âû&äåëåíèå ïîëÿ ââîäà ïðè âûáîðå
+11861=Âñå ïîëå ââîäà âûäåëÿåòñÿ ïðè ïåðåìåùåíèè ê íåìó êóðñîðà èëè ïðè ùåë÷êå ìûøüþ (íå äëÿ âñåõ ïîëåé)
+11870=Ñêðûâàòü íåàêòèâíîå &ãëàâíîå îêíî ïðîãðàììû
+11871=Ñêðûâàòü ãëàâíîå îêíî ïðîãðàììû ïðè èñïîëüçîâàíèè Èñêàòåëÿ ôîðìóë, Êîíâåðòåðà ìîëåé/ìàññû è ò.ï.
+11881=Óìåíüøèòü ÷èñëî, ÷òîáû îêíî ôîðìóë íå çàïîëíÿëî ýêðàí, ïîñëå ýòîãî çàêðûòü è ïåðåçàïóñòèòü ïðîãðàììó. Ìàêñèìóì çàâèñèò îò ðàçðåøåíèÿ ýêðàíà.
+11885=Ìàêñèìàëüíîå ÷èñëî ôîðìóë íà ýêðàíå
+11890=Module to show at startup
+11896=Module to show when the program starts
+11898=Main Window|Formula Finder|Capillary Flow Calculator|Mole/Mass Converter|Peptide Sequence Fragmentation Modeller|Amino Acid Notation Converter|Isotopic Distribution Modeller
+
+; Messages
+11900=Çíà÷åíèÿ è ïàðàìåòðû àâòîìàòè÷åñêè ñîõðàíåíû.
+11910=Ïàðàìåòðû ïî óìîë÷àíèþ âîññòàíîâëåíû.
+11920=Çíà÷åíèÿ è ôîðìóëû ñîõðàíåíû.
+11925=Çíà÷åíèÿ è ôîðìóëû ÍÅ ñîõðàíåíû, ïîñêîëüêó èñïîëüçóåòñÿ ïàðàìåòð /X â êîìàíäíîé ñòðîêå.
+11930=Ïàðàìåòðû ñîõðàíåíû.
+11935=Ïàðàìåòðû ÍÅ ñîõðàíåíû, ïîñêîëüêó èñïîëüçóåòñÿ ïàðàìåòð /X â êîìàíäíîé ñòðîêå..
+
+[frmFragmentationModelling]
+12000=Ìîäåëèðîâàíèå ôðàãìåíòàöèè ïåïòèäîâ
+; General Combo Boxes
+12010=1-áóêâåííûå îáîçíà÷åíèÿ|3-áóêâåííûå îáîçíà÷åíèÿ
+12011=Òèï îáîçíà÷åíèé àìèíîêèñëîò
+12020=Ïîäáîð &èîíîâ
+; Textboxes
+12051=Çäåñü ââîäÿò íàáîð àìèíîêèñëîò
+12061=Ñìåùåíèå íà äàííóþ âåëè÷èíó ìàññ çàãðóæåííûõ èîíîâ äëÿ ïîäáîðà ñ öåëüþ êîððåêòèðîâêè îòêëîíåíèé ìàññ-ñïåêòðà
+; Frames, labels, and checkboxes
+12100=Íàáîð:
+12150=Òåðìèíàëüíûå N è C
+12160=&N
+12170=&C
+12180=H
+12190=OH
+12200=Òèïû èîíîâ
+12210=&A èîíû
+12215=&B èîíû
+12220=&Y èîíû
+12230=Íåéòðàëüíûå ïîòåðè
+12236=Çäåñü âûáèðàþò èîíû, ê êîòîðûì îòíîñÿòñÿ ïîòåðè
+12240=Ïîòåðÿ H2O
+12250=Ïîòåðÿ NH3
+12260=Îïöèè çàðÿäà
+12270=Èîíû ñ &çàðÿäîì 2+
+12280=Ïîðî&ã
+12286=Äëÿ èîíîâ ñ m/z âûøå ýòîãî ïîðîãà áóäóò âû÷èñëÿòüñÿ çíà÷åíèÿ 2+ m/z
+12300=Îïöèè ïîäáîðà èîíîâ
+12310=&Óäàëÿòü èîí-ïðåäøåñòâåííèê
+12320=Ìàññà èîíà
+12330=Äîïóñê äëÿ ìàññû
+12340=&Äîïóñê äëÿ ïîäáîðà èîíà
+12350=Ä
+12355=&Êîððåêòèðîâêà
+12360=Ñòàòèñòèêà èîíîâ
+12370=Çàãðóæåíî
+12375=Îñòàëîñü ïîñëå ñáîðà
+12380=Â ïðåäåëàõ äîïóñêà
+12385=Ïðåäøåñòâåííèê íå íàéäåí
+12390=Ïðåäøåñòâåííèê óäàëåí
+12395=Ïðåäøåñòâåííèê íå óäàëåí
+12400=Ïîäîáðàíî èîíîâ
+12405=Îöåíêà
+
+; Column titles in grids
+; Note: # means 'number', Immon. means 'immonium', and Seq. means 'sequence'
+12500=#
+12510=Èììîí.
+12520=Íàáîð
+12550=Ìàññà
+12560=Èíòåíñèâí.
+
+; Ion Types (must be exactly one letter long)
+12600=a
+12610=b
+12620=y
+
+; Menu Items
+12800=Çàãðóçèòü èíôîðìàöèþ î &íàáîðå
+12810=&Ñîõðàíèòü èíôîðìàöèþ î íàáîðå
+12820=Çàãðóçèòü ñïèñîê &èîíîâ äëÿ ïîäáîðà
+12830=&Çàêðûòü
+12840=&Êîïèðîâàòü ïðåäñêàçàííûå èîíû
+12850=Ê&îïèðîâàòü ïðåäñêàçàííûå èîíû êàê RTF
+12855=Êî&ïèðîâàòü ïðåäñêàçàííûå èîíû êàê Html
+12860=&Âñòàâèòü ñïèñîê èîíîâ äëÿ ïîäáîðà
+12870=Î÷èñòèòü &ñïèñîê èîíîâ äëÿ ïîäáîðà
+12880=&Ñïèñîê èîíîâ äëÿ ïîäáîðà
+12900=Ïðåäñêàçàííûé &ìàññ-ñïåêòð
+12910=&Îáíîâëÿòü ìàññ-ñïåêòð ïðè èçìåíåíèÿõ
+12920=&Îïöèè ñïèñêà èîíîâ äëÿ ïîäáîðà
+12930=&Àâòîìàòè÷åñêàÿ êîððåêòèðîâêà èîíîâ äëÿ ïîäáîðà
+12940=&Ìîäåëèðîâàíèå ôðàãìåíòàöèè
+
+[frmMsPlot]
+13000=Ãðàôèê - Ìàññ-ñïåêòð
+; The following is an abbreviation for the word 'Location'
+13010=Ïîç.
+
+; Legend Items
+13030=Ïðåäñêàçàííûå èîíû
+13035=Çàãðóæåííûå èîíû
+
+; Menu Items
+13100=&Ýêñïîðò äàííûõ
+13150=&Òèï ãðàôèêà
+13160=&Ïðîñòûå ïèêè (óõîäÿùèå ê íóëþ)
+13170=&Ãàóññîâû ïèêè
+13180=Óñòàíîâèòü ýôôåêòèâíîå &ðàçðåøåíèå
+13190=Ëèíèè ñåòêè ïî îñè X
+13200=Ëèíèè ñåòêè ïî îñè Y
+13210=Îòìåòêè ñ &÷èñëàìè (ïðèáëèæåííî)
+13220=Ïî îñè &X
+13230=Ïî îñè &Y
+13235=&Êà÷åñòâî ãðàôèêà (âëèÿåò íà ñêîðîñòü)
+13240=Êà÷åñòâî &Ãàóññîâà ïðåäñòàâëåíèÿ
+13245=Êîýôôèöèåíò &àïïðîêñèìàöèè
+13250=Óñòàíîâèòü èíòåðâàë ïî îñè &X
+13260=Óñòàíîâèòü èíòåðâàë ïî îñè &Y
+13270=&Àâòîìàñøòàáèðîâàíèå ïî îñè Y
+13280=&Ôèêñèðîâàòü ìèíèìóì ïî îñè Y â íóëå
+13290=&Óìåíüøèòü äî ïðåäøåñòâóþùåãî
+13295=Ctrl+Z èëè ïðàâàÿ êíîïêà ìûøè
+13300=Óìåíüøèòü, ÷òîáû ïîêàçàòü &âñå
+13310=Ðåæèì êóðñîðà &ìûøè
+13315=Ïðîáåë ïîçâîëÿåò ñäâèíóòü
+13320=&Âûäåëèòü êîðîáêó äëÿ óâåëè÷åíèÿ/óìåíüøåíèÿ
+13330=&Ñäâèíóòü ãðàôèê
+13340=&Ïîêàçàòü òåêóùóþ ïîçèöèþ
+13342=Ïîêàçàòü &ëåãåíäó
+13345=Âîññòàíîâèòü &îïöèè ïî óìîë÷àíèþ
+13350=&Óâåëè÷èòü/óìåíüøèòü êîðîáêó
+13360=Ó&âåëè÷èòü
+13365=Ëåâàÿ êíîïêà ìûøè
+13370=Óâåëè÷èòü ïî ãîðèçîíòàëè
+13380=Óâåëè÷èòü ïî âåðòèêàëè
+13390=Ó&ìåíüøèòü
+13400=Óìåíüøèòü ïî ãîðèçîíòàëè
+13410=Óìåíüøèòü ïî âåðòèêàëè
+
+[frmIonMatchOptions]
+14000=Îïöèè ñïèñêà èîíîâ äëÿ ïîäáîðà
+; Buttons
+14010=&Âîññòàíîâèòü ïî óìîë÷àíèþ
+
+; Explanations
+14050=Êîãäà â ïðîãðàììó èìïîðòèðóþò ñïèñîê èîíîâ, èîíû ñ áëèçêèìè ìàññàìè ìîæíî îáúåäèíèòü âìåñòå ïðè ïîìîùè ïðîöåññà ñáîðà, ÷òîáû óìåíüøèòü îáùåå ÷èñëî òî÷åê äàííûõ. Ïîòîì èîíû îêîëî èîíà-ïðåäøåñòâåííèêà ìîæíî óäàëèòü.
+14055= Çàòåì èíòåíñèâíîñòè èîíîâ íîðìàëèçóþòñÿ ïî çàäàííîé èíòåíñèâíîñòè è îíè ðàñïîëàãàþòñÿ ïî óìåíüøåíèþ èíòåíñèâíîñòè. Èîíû ñ íàèáîëüøåé èíòåíñèâíîñòüþ (äî ÷èñëà èñïîëüçóåìûõ èîíîâ) äåëÿòñÿ íà îòäåëüíûå ãðóïïû ïî ìàññå è èîíû â êàæäîé ãðóïïå âíîâü íîðìàëèçóþòñÿ.
+14060=Íåòðóäíî âû÷èñëèòü ìàññû ïðåäñêàçàííûõ èîíîâ äëÿ äàííîãî ïåïòèäà. Îäíàêî ìàññàì òàêæå íóæíî íàçíà÷èòü çíà÷åíèÿ èíòåíñèâíîñòåé.
+14065= Èîíàì B è Y îáû÷íî íàçíà÷àþò îäèíàêîâóþ èíòåíñèâíîñòü, òîãäà êàê èîí A îáû÷íî èìååò èíòåíñèâíîñòü â 5 ðàç ìåíüøå. Ìîæíî äîáàâèòü "ïëå÷åâûå" èîíû (ñ ìàññàìè +/- 1 Ä îò ìàññû èîíîâ B è Y), à òàêæå ó÷åñòü íåéòðàëüíûå ïîòåðè (H2O è NH3).
+
+; Frames, labels, and checkboxes
+14100=Îïöèè íîðìàëèçàöèè ïðè èìïîðòå äàííûõ
+14110=&Îáúåäèíåíèå èîíîâ (Ñáîð äàííûõ)
+14115=Äîïóñê äëÿ ìàññû
+14120=Íîðìàëèçîâàííàÿ èíòåíñèâíîñòü
+14130=×èñëî èñïîëüçóåìûõ èîíîâ
+14140=Ãðóïï ïî ìàññå
+14150=Èíòåíñèâíîñòè ïðåäñêàçàííûõ èîíîâ
+14160=Èíòåíñèâíîñòü èîíà A
+14165=Èíòåíñèâíîñòü èîíà B
+14170=Èíòåíñèâíîñòü èîíà Y
+14180="Ïëå÷åâûå" èîíû äëÿ èîíîâ B/Y
+14190=Íåéòðàëüíûå ïîòåðè
+
+[frmSetValue]
+14500=Óñòàíîâèòü çíà÷åíèå
+14510=&Óñòàíîâèòü
+14520=&Çàïóñê
+
+[frmProgress]
+14700=Ïðîöåññ
+14710=Ùåë÷îê äëÿ ïàóçû
+14715=Ïîäãîòîâêà ê ïàóçå
+14720=Ïàóçà
+14725=Âîçîáíîâëåíèå
+14730=(Íàæàòü Esc äëÿ îòìåíû)
+14740=ìèí. ïðîøëî/îñòàëîñü
+
+[frmIsotopicDistibution]
+15000=Isotopic Distribution
+; Frames, labels, and checkboxes
+15050=Formula:
+15060=Results:
+15100=&Plot Results
+15110=&Compute
+15151=Isotopic distribution results
+
+[ErrorAndStatusMessages]
+20001=Íåèçâåñòíûé ýëåìåíò
+20003=Íå çàêðûòû êðóãëûå ñêîáêè
+20004=Íåñîîòâåòñòâèå êðóãëûõ ñêîáîê
+20005=Íåëüçÿ èñïîëüçîâàòü 0 ñðàçó ïîñëå ñèìâîëà ýëåìåíòà èëè -
+20006=×èñëî ñëèøêîì âåëèêî èëè äîëæíî áûòü òîëüêî ïîñëå [, ), - èëè ^
+20007=×èñëî ñëèøêîì âåëèêî
+20011=×èñëà äîëæíû ñòîÿòü çà ëåâûìè [, à íå çà ïðàâûìè ]
+20012=Ïîñëå ëåâîé [ èëè äåñÿòè÷íîé çàïÿòîé äîëæíî áûòü ÷èñëî
+20013=Íå çàêðûòû êâàäðàòíûå ñêîáêè
+20014=×èñëî ìîæåò áûòü òîëüêî ïîñëå ñèìâîëà ýëåìåíòà, [, ), - èëè ^
+20015=Íåñîîòâåòñòâèå êâàäðàòíûõ ñêîáîê
+20016=Íåëüçÿ èñïîëüçîâàòü âëîæåííûå [] èëè [] âíóòðè ïîëèãèäðàòîâ
+20018=Íåèçâåñòíûé ýëåìåíò
+20020=Ïîñëå ^ äîëæíî áûòü ÷èñëî - ìàññà èçîòîïà
+20022=Ïîñëå ìàññû èçîòîïà (÷èñëî ïîñëå ^) äîëæåí áûòü ñèìâîë ýëåìåíòà
+20023=Ìàññà èçîòîïà ïîñëå ^ íå ìîæåò áûòü îòðèöàòåëüíîé
+20024=Äëÿ àááðåâèàòóð ìàññû èçîòîïîâ íå èñïîëüçóþòñÿ
+20025=Ïîñëå ìíîæèòåëÿ (÷èñëî ïîñëå -) äîëæåí áûòü ñèìâîë ýëåìåíòà
+20026=Äëÿ àááðåâèàòóð ìàññû èçîòîïîâ íå èñïîëüçóþòñÿ; D - àááðåâèàòóðà
+20027=×èñëî íå ìîæåò ñîäåðæàòü áîëåå îäíîé äåñÿòè÷íîé çàïÿòîé
+20028=Â ôîðìóëå àááðåâèàòóðû íåëüçÿ èñïîëüçîâàòü äðóãèå àááðåâèàòóðû
+20050=Çàäàííîå çíà÷åíèå áîëåå 100% íåäîïóñòèìî.
+20075=Â ñòðîêå êàëüêóëÿòîðà íåëüçÿ èñïîëüçîâàòü áóêâû
+20076=Íå çàêðûòû êðóãëûå ñêîáêè
+20077=Íåñîîòâåòñòâèå êðóãëûõ ñêîáîê
+20078=×èñëî íå íà ìåñòå, ëèáî ñëèøêîì áîëüøîå/ìàëîå/äëèííîå
+20080=Îïåðàòîð íå íà ìåñòå
+20081=Ïåðåìåííàÿ òðåêà (track variable) ìåíåå èëè ðàâíà 1; äåôåêò ïðîãðàììû. Ïðîøó ñîîáùèòü ïðîãðàììèñòó.
+20082=Ïðîïóùåí îïåðàòîð.
+20085=Íåëüçÿ âîçâåñòè îòðèöàòåëüíîå ÷èñëî â äðîáíóþ ñòåïåíü
+20086=Íåëüçÿ âîçâåñòè íîëü â îòðèöàòåëüíóþ ñòåïåíü
+20087=Íåëüçÿ âîçâåñòè íîëü â íóëåâóþ ñòåïåíü
+20089=Ïîñëå ^ äîëæíî áûòü îäíî ÷èñëî (ìîæíî îòðèöàòåëüíîå)
+20090=×èñëî íå ìîæåò ñîäåðæàòü áîëåå îäíîé äåñÿòè÷íîé çàïÿòîé
+20091=Ïîïûòêà ïîäåëèòü ÷èñëî íà íîëü. Ñëåäóåò èñïðàâèòü âûðàæåíèå è ïîâòîðèòü âû÷èñëåíèÿ.
+20092= ìàòåìàòè÷åñêèõ âûðàæåíèÿõ ïðîáåëû íåäîïóñòèìû
+20093=Òî÷êà ÿâëÿåòñÿ äåñÿòè÷íûì ñèìâîëîì
+20094=Çàïÿòàÿ ÿâëÿåòñÿ äåñÿòè÷íûì ñèìâîëîì
+20095=Ïîñëå äåñÿòè÷íîé çàïÿòîé äîëæíà áûòü öèôðà
+20100=Îøèáêà ñîõðàíåíèÿ ôàéëà àááðåâèàòóð
+20110=Çàíîâî ñîçäàí ôàéë àááðåâèàòóð, èñïîëüçóåìûõ ïðîãðàììîé ïî óìîë÷àíèþ.
+20115=Ñòàðûé ôàéë ïåðåèìåíîâàí â
+20120=Â ôàéëå àááðåâèàòóð íå íàéäåí çàãîëîâîê [AMINO ACIDS]. Îí äîëæåí áûòü âûøå çàãîëîâêà [ABBREVIATIONS].
+20125=Íàæàòü Äà, ÷òîáû ïðîäîëæèòü áåçî âñåõ àááðåâèàòóð.
+20130=Â ôàéëå àááðåâèàòóð íå íàéäåí çàãîëîâîê [ABBREVIATIONS]. Îí äîëæåí áûòü íèæå çàãîëîâêà [AMINO ACIDS].
+20135=Íàæàòü Äà, ÷òîáû ïðîäîëæèòü òîëüêî ñ àááðåâèàòóðàìè àìèíîêèñëîò.
+20140=Ôàéë àááðåâèàòóð íå íàéäåí â êàòàëîãå ïðîãðàììû
+20150=Îøèáêà çàãðóçêè/ñîçäàíèÿ ôàéëà àááðåâèàòóð
+20160=Àááðåâèàòóðà èãíîðèðóåòñÿ; íåâåðíàÿ ôîðìóëà
+20170=Èãíîðèðóåòñÿ óäâîåííàÿ àááðåâèàòóðà
+20180=Àááðåâèàòóðà èãíîðèðóåòñÿ; íåâåðíûé ñèìâîë
+20190=Àááðåâèàòóðà èãíîðèðóåòñÿ; ñëèøêîì äëèííàÿ
+20200=Èãíîðèðóåòñÿ íåâåðíàÿ ñòðîêà
+20210=Çàíîâî ñîçäàí ôàéë ýëåìåíòîâ, èñïîëüçóåìûõ ïðîãðàììîé.
+20220=Âîçìîæíî íåâåðíàÿ ìàññà ýëåìåíòà
+20230=Âîçìîæíî íåâåðíàÿ ïîãðåøíîñòü äëÿ ýëåìåíòà
+20250=Ñòðîêà èãíîðèðóåòñÿ; íåâåðíûé ñèìâîë ýëåìåíòà
+20260=Â ôàéëå ýëåìåíòîâ íå íàéäåí çàãîëîâîê [ELEMENTS]. Îí äîëæåí áûòü â ôàéëå.
+20265=Íàæàòü Äà, ÷òîáû ïðîäîëæèòü ñ ìàññàìè ýëåìåíòîâ ïî óìîë÷àíèþ.
+20270=Ôàéë ýëåìåíòîâ íå íàéäåí â êàòàëîãå ïðîãðàììû
+20280=Îøèáêà çàãðóçêè/ñîçäàíèÿ ôàéëà ýëåìåíòîâ
+20305=Ïðîäîëæèòü ñ èñïîëüçóåìûì ðàíåå ôàéëîì òåêñòîâ.
+20320=Îøèáêà ñîõðàíåíèÿ ôàéëà ýëåìåíòîâ
+20330=Îøèáêà çàãðóçêè/ñîçäàíèÿ ôàéëà çíà÷åíèé è ôîðìóë
+20340=Íàæàòü Äà, ÷òîáû ïðîäîëæèòü áåç çàãðóçêè çíà÷åíèé è ôîðìóë.
+20345=Äëÿ óñòðîéñòâ "Òîëüêî äëÿ ÷òåíèÿ", ÷òîáû ïðåäîòâðàòèòü ýòó îøèáêó, èñïîëüçóþò ïàðàìåòð /X â êîìàíäíîé ñòðîêå.
+20350=Îøèáêà
+20360=Îøèáêà ñîõðàíåíèÿ ôàéëà ïàðàìåòðîâ
+20370=Äëÿ óñòðîéñòâ "Òîëüêî äëÿ ÷òåíèÿ" íåëüçÿ ñîõðàíèòü ïàðàìåòðû.
+20380=Îøèáêà ñîõðàíåíèÿ ôàéëà çíà÷åíèé è ôîðìóë
+20390=Äëÿ óñòðîéñòâ "Òîëüêî äëÿ ÷òåíèÿ" íåëüçÿ ñîõðàíèòü çíà÷åíèÿ è ôîðìóëû.
+20400=Îøèáêà çàãðóçêè/ñîçäàíèÿ ôàéëà ïàðàìåòðîâ
+20410=Íàæàòü Äà, ÷òîáû ïðîäîëæèòü áåç çàãðóçêè ïàðàìåòðîâ ïîëüçîâàòåëÿ.
+20440=Íåâîçìîæíî îòêðûòü ôàéë òåêñòîâ äëÿ äàííîãî ÿçûêà èëè îí èìååò íåïðàâèëüíûé ôîðìàò.
+20450=Íåâîçìîæíî çàãðóçèòü òåêñòû äëÿ äàííîãî ÿçûêà
+20460=Ôàéë òåêñòîâ äëÿ äàííîãî ÿçûêà íå íàéäåí â êàòàëîãå ïðîãðàììû
+20470=Íå íàéäåí ôàéë, íåîáõîäèìûé äëÿ âû÷èñëåíèÿ ìîëåêóëÿðíîé ìàññû
+20480=Ôàéë íå íàéäåí
+20490=Òàêîé ôàéë óæå ñóùåñòâóåò. Çàìåíèòü åãî?
+20500=Ôàéë ñóùåñòâóåò
+20510=Îøèáêà ÷òåíèÿ/çàïèñè ôàéëîâ äëÿ ïàêåòíîé îáðàáîòêè
+20515=Íàæàòü Äà äëÿ îòìåíû ïàêåòíîé îáðàáîòêè ôàéëîâ.
+20520=Îøèáêà â ïðîãðàììå
+20530=Ýòè ñòðîêè êîäà íå äîëæíû âñòðå÷àòüñÿ. Ïðîøó ñîîáùèòü ïðîãðàììèñòó.
+20540=Íåâîçìîæíî ïðàâèòü ýëåìåíòû, ïîñêîëüêó èñïîëüçóåòñÿ ïàðàìåòð /X â êîìàíäíîé ñòðîêå.
+20545=Íåâîçìîæíî ïðàâèòü àááðåâèàòóðû, ïîñêîëüêó èñïîëüçóåòñÿ ïàðàìåòð /X â êîìàíäíîé ñòðîêå.
+20550=Íåëüçÿ èñïîëüçîâàòü Âû÷èñëèòåëü ïðîöåíòîâ, êîãäà âêëþ÷åí ïàðàìåòð "Îáðàáàòûâàòü êâàäðàòíûå ñêîáêè êàê êðóãëûå". Ýòîò ïàðàìåòð ìîæíî èçìåíèòü, âûáðàâ Ñìåíèòü ïàðàìåòðû ïðîãðàììû â ìåíþ Îïöèè.
+20555=Âû÷èñëèòåëü ïðîöåíòîâ íåäîñòóïåí
+20560=Äîñòèãíóòî ìàêñèìàëüíîå êîëè÷åñòâî ñòðîê äëÿ ôîðìóë.
+20570=Òåêóùàÿ ôîðìóëà íå çàïîëíåíà.
+20580=Îòêëþ÷àþò Âû÷èñëèòåëü ïðîöåíòîâ (F11) ïåðåä ñîçäàíèåì íîâîé ñòðîêè äëÿ ôîðìóëû.
+20590=Îøèáêà ïåðåïîëíåíèÿ. Ñëåäóåò óìåíüøèòü ðàçìåð ÷èñëà è ïîâòîðèòü âû÷èñëåíèÿ.
+20600=Îøèáêà
+20605=Ïðîøó âûéòè èç ïðîãðàììû è ñîîáùèòü îá îøèáêå ïðîãðàììèñòó. E-mail - ñì. Î ïðîãðàììå MWT â ìåíþ Ïîìîùü.
+20610=Ïðîáåëû â ôîðìóëàõ íå äîïóñêàþòñÿ
+20620=Íåâåðíûé ñèìâîë
+20630=Íåâîçìîæíî êîïèðîâàòü â íîâóþ ôîðìóëó.
+20650=Òåêóùàÿ ôîðìóëà íå çàïîëíåíà.
+20655=Âêëþ÷åí Âû÷èñëèòåëü ïðîöåíòîâ (F11 äëÿ âûõîäà).
+20660=Âíèìàíèå, ìàññà èçîòîïà, âåðîÿòíî, ñëèøêîì âåëèêà äëÿ ýëåìåíòà
+20662=Âíèìàíèå, ìàññà èçîòîïà, âåðîÿòíî, ñëèøêîì ìàëà äëÿ ýëåìåíòà
+20665=ïðîòèâ ñðåäíåé AM
+20670=Âíèìàíèå, ìàññà èçîòîïà íåäîïóñòèìî ìàëà äëÿ ýëåìåíòà
+20675=ïðîòîí(à,îâ)
+20680=Âíèìàíèå: Âêëþ÷åí ðåæèì Òî÷íîå ñîáëþäåíèå ðåãèñòðà
+20685=Âíèìàíèå: äëÿ Âû÷èñëèòåëÿ ïðîöåíòîâ [ äîëæíà áûòü ïåðåä x
+20690=Âíèìàíèå: Êâàäðàòíûå ñêîáêè îáðàáàòûâàþòñÿ êàê êðóãëûå
+20700=Íåîáõîäèìî îòìåòèòü îäèí èëè íåñêîëüêî ýëåìåíòîâ.
+20705=Ìàêñèìàëüíîå ÷èñëî ôîðìóë äîëæíî áûòü áîëüøå 0.
+20710=Ìàêñèìàëüíîå ÷èñëî ôîðìóë äîëæíî áûòü ìåíüøå
+20715=Ìèíèìàëüíîå ÷èñëî àòîìîâ äîëæíî áûòü 0 èëè áîëüøå.
+20720=Ìèíèìàëüíîå ÷èñëî àòîìîâ äîëæíî áûòü ìåíüøå ìàêñèìàëüíîãî.
+20725=Ìàêñèìàëüíîå ÷èñëî àòîìîâ äîëæíî áûòü ìåíüøå 65 025
+20730=Äëÿ Äðóãîãî ýëåìåíòà íóæíî ââåñòè àòîìíóþ ìàññó.
+20735=Àòîìíàÿ ìàññà äëÿ Äðóãîãî ýëåìåíòà äîëæíà áûòü áîëüøå 0.
+20740=Íóæíî ââåñòè çàäàííóþ ìîëåêóëÿðíóþ ìàññó.
+20745=Çàäàííàÿ ìîëåêóëÿðíàÿ ìàññà äîëæíà áûòü áîëüøå 0.
+20755=Íóæíî ââåñòè ìàêñèìàëüíóþ ìîëåêóëÿðíóþ ìàññó ñîåäèíåíèÿ.
+20760=Ìàêñèìàëüíàÿ ìîëåêóëÿðíàÿ ìàññà ñîåäèíåíèÿ äîëæíà áûòü áîëüøå 0.
+20765=Íóæíî ââåñòè çàäàííîå ïðîöåíòíîå ñîäåðæàíèå äëÿ ýëåìåíòà
+20770=Çàäàííîå ïðîöåíòíîå ñîäåðæàíèå äîëæíî áûòü áîëüøå 0.
+20775= ïîëå Àòîìíàÿ ìàññà äëÿ Äðóãîãî ýëåìåíòà íóæíî ââîäèòü ëèáî òîëüêî ÷èñëî (ìàññó), ëèáî òîëüêî áóêâû. Åñëè èñïîëüçóþòñÿ áóêâû, îíè äîëæíû áûòü ñèìâîëîì îäíîãî ýëåìåíòà èëè îäíîé àááðåâèàòóðîé.
+20780=Íå çàïîëíåíî ïîëå Àòîìíàÿ ìàññà äëÿ Äðóãîãî ýëåìåíòà. Åñëè èñïîëüçóþòñÿ áóêâû, îíè äîëæíû áûòü ñèìâîëîì îäíîãî ýëåìåíòà èëè îäíîé àááðåâèàòóðîé.
+20785=Íåèçâåñòíûé ñèìâîë ýëåìåíòà èëè àááðåâèàòóðà â ïîëå Àòîìíàÿ ìàññà äëÿ Äðóãîãî ýëåìåíòà
+20790=Ìîæíî ââåñòè ñèìâîë òîëüêî îäíîãî ýëåìåíòà èëè îäíó àááðåâèàòóðó.
+20800=Âíèìàíèå, àááðåâèàòóðû íå çàãðóæåíû - Êîìàíäà íå âûïîëíÿåòñÿ.
+
+20900=Îøèáêà ÷òåíèÿ/çàïèñè ôàéëà èíôîðìàöèè î íàáîðå.
+20910=Â ñïèñêå èîíîâ óæå åñòü èîíû. Çàìåíèòü èõ íîâûìè èîíàìè?
+20920=Çàìåíèòü ñóùåñòâóþùèå èîíû
+20930=Çàãðóçêà ñïèñêà èîíîâ
+20940=Ïðîöåññ ïðåðâàí
+20945=Îòìåíà
+20950=Íîðìàëèçàöèÿ èîíîâ
+20960=Íîðìàëèçàöèÿ ïî ãðóïïàì
+20965=Ñîðòèðîâêà ïî èíòåíñèâíîñòè
+20970=Ïîäáîð èîíîâ
+20980=Áóôåð îáìåíà ïóñò. Íåò èîíîâ äëÿ âñòàâêè.
+20985=Íåò èîíîâ
+20990=Âñòàâêà ñïèñêà èîíîâ
+21000=Îïðåäåëåíèå ÷èñëà èîíîâ â ñïèñêå
+21010=Àíàëèç ñïèñêà
+21020=Â áóôåðå îáìåíà íåò ïðàâèëüíîãî ñïèñêà èîíîâ. Ïðàâèëüíûé ñïèñîê èîíîâ - ýòî ñïèñîê èç ïàð ìàññ è èíòåíñèâíîñòåé. Íà êàæäîé ñòðîêå äîëæíà áûòü îäíà ïàðà ìàññà/èíòåíñèâíîñòü, êîòîðûå îòäåëåíû äðóã îò äðóãà çàïÿòîé, ñèìâîëîì òàáóëÿöèè èëè ïðîáåëîì.
+21030=Îøèáêà çàïèñè äàííûõ â ôàéë
+21040=Óñòàíîâèòü èíòåðâàë
+21050=Íà÷àëî
+21055=Êîíåö
+21060=Óñòàíîâèòü èíòåðâàë ïî îñè X
+21065=Óñòàíîâèòü èíòåðâàë ïî îñè Y
+21070=Ââåäèòå íîâûé êîýôôèöèåíò êà÷åñòâà Ãàóññîâà ïðåäñòàâëåíèÿ. ×åì îí âûøå, òåì ïëàâíåå Ãàóññîâû êðèâûå, íî ìåäëåííåå îáíîâëåíèÿ. Èíòåðâàë îò 1 äî 50, ïî óìîë÷àíèþ 20
+21072=Êà÷åñòâî Ãàóññîâà ïðåäñòàâëåíèÿ
+21075=Ââåäèòå íîâûé êîýôôèöèåíò àïïðîêñèìàöèè ãðàôèêà. ×åì îí âûøå, òåì áûñòðåå îáíîâëåíèÿ, íî ìåíåå òî÷íû ãðàôè÷åñêèå ïðåäñòàâëåíèÿ ïðè ïðîñìîòðå øèðîêîãî èíòåðâàëà ìàññ (ïðè óìåíüøåíèè). Èíòåðâàë îò 1 äî 50, ïî óìîë÷àíèþ 10
+21077=Êîýôôèöèåíò àïïðîêñèìàöèè ãðàôèêà
+21080=Ñïåöèôèêàöèè ðàçðåøåíèÿ
+21090=Ðàçðåøåíèå
+21100=Ìàññà X äëÿ ðàçðåøåíèÿ
+21110=Ââåäèòå ïðèáëèæåííîå êîëè÷åñòâî îòìåòîê ñ ÷èñëàìè ïî îñè
+21115=Îòìåòêè ñ ÷èñëàìè ïî îñè
+21120=Ñîçäàíèå Ãàóññîâà ïðåäñòàâëåíèÿ
+21130=Ïîäãîòîâêà ãðàôèêà
+21135=Ðèñîâàíèå ãðàôèêà
+21140=Âû óâåðåíû, ÷òî õîòèòå âîññòàíîâèòü îïöèè ïî óìîë÷àíèþ äëÿ ïîñòðîåíèÿ ãðàôèêà?
+21145=Âîññòàíîâèòü îïöèè ïî óìîë÷àíèþ
+21150=Àâòîìàòè÷åñêàÿ êîððåêòèðîâêà èîíîâ
+21155=Ìàêñèìóì ñìåùåíèÿ
+21160=Øàã ñìåùåíèÿ
+21165=Êîððåêòèðîâêà èîíîâ
+
+21500=Âñå ôàéëû
+21510=Òåêñòîâûå ôàéëû
+21515=txt
+21520=Ôàéëû äàííûõ
+21525=csv
+21530=Ôàéëû íàáîðîâ
+21535=seq
+21540=Ôàéëû ñïèñêîâ èîíîâ
+21545=txt
+21550=cap
+21555=Capillary Flow Info Files
+
+[CautionStatments]
+; Note: Caution statement keynames are case sensitive; i.e. Bi is different than BI
+; You may add new caution statements if desired; however, you will need to save
+; the file with a name other than Lang_English and change the Language= key
+; since this file is not loaded if the language is English
+22000=Âíèìàíèå
+Bi=Bi çíà÷èò âèñìóò; BI çíà÷èò áîð-éîä.
+Bk=Bk çíà÷èò áåðêëèé; BK çíà÷èò áîð-êàëèé.
+Bu=Bu çíà÷èò áóòèë; BU çíà÷èò áîð-óðàí.
+Cd=Cd çíà÷èò êàäìèé; CD çíà÷èò óãëåðîä-äåéòåðèé.
+Cf=Cf çíà÷èò êàëèôîðíèé; CF çíà÷èò óãëåðîä-ôòîð.
+Co=Co çíà÷èò êîáàëüò; CO çíà÷èò óãëåðîä-êèñëîðîä.
+Cs=Cs çíà÷èò öåçèé; CS çíà÷èò óãëåðîä-ñåðà.
+Cu=Cu çíà÷èò ìåäü; CU çíà÷èò óãëåðîä-óðàí.
+Dy=Dy çíà÷èò äèñïðîçèé; DY çíà÷èò äåéòåðèé-èòòðèé.
+Hf=Hf çíà÷èò ãàôíèé; HF çíà÷èò âîäîðîä-ôòîð.
+Ho=Ho çíà÷èò ãîëüìèé; HO çíà÷èò âîäîðîä-êèñëîðîä.
+In=In çíà÷èò èíäèé; IN çíà÷èò éîä-àçîò.
+Nb=Nb çíà÷èò íèîáèé; NB çíà÷èò àçîò-áîð.
+Nd=Nd çíà÷èò íåîäèì; ND çíà÷èò àçîò-äåéòåðèé.
+Ni=Ni çíà÷èò íèêåëü; NI çíà÷èò àçîò-éîä.
+No=No çíà÷èò íîáåëèé; NO çíà÷èò àçîò-êèñëîðîä.
+Np=Np çíà÷èò íåïòóíèé; NP çíà÷èò àçîò-ôîñôîð.
+Os=Os çíà÷èò îñìèé; OS çíà÷èò êèñëîðîä-ñåðà.
+Pd=Pd çíà÷èò ïàëëàäèé; PD çíà÷èò ôîñôîð-äåéòåðèé.
+Ph=Ph çíà÷èò ôåíèë, PH çíà÷èò ôîñôîð-âîäîðîä.
+Pu=Pu çíà÷èò ïëóòîíèé; PU çíà÷èò ôîñôîð-óðàí.
+Py=Py çíà÷èò ïèðèäèí; PY çíà÷èò ôîñôîð-èòòðèé.
+Sb=Sb çíà÷èò ñóðüìà; SB çíà÷èò ñåðà-áîð.
+Sc=Sc çíà÷èò ñêàíäèé; SC çíà÷èò ñåðà-óãëåðîä.
+Si=Si çíà÷èò êðåìíèé; SI çíà÷èò ñåðà-éîä.
+Sn=Sn çíà÷èò îëîâî; SN çíà÷èò ñåðà-àçîò.
+Ti=TI çíà÷èò òðèòèé-éîä; Ti çíà÷èò òèòàí.
+Yb=Yb çíà÷èò èòòåðáèé; YB çíà÷èò èòòðèé-áîð.
+BPY=BPY çíà÷èò áîð-ôîñôîð-èòòðèé; Bpy çíà÷èò áèïèðèäèí.
+BPy=BPy çíà÷èò áîð-ïèðèäèí; Bpy çíà÷èò áèïèðèäèí.
+Bpy=Bpy çíà÷èò áèïèðèäèí.
+Cys=Cys çíà÷èò öèñòåèí; CYS çíà÷èò óãëåðîä-èòòðèé-ñåðà.
+His=His çíà÷èò ãèñòèäèí; HIS çíà÷èò âîäîðîä-éîä-ñåðà.
+Hoh=HoH çíà÷èò ãîëüìèé-âîäîðîä; HOH çíà÷èò âîäîðîä-êèñëîðîä-âîäîðîä (ò.å. âîäà).
+Hyp=Hyp çíà÷èò ãèäðîêñèïðîëèí; HYP çíà÷èò âîäîðîä-èòòðèé-ôîñôîð.
+OAc=OAc çíà÷èò êèñëîðîä-àêòèíèé; Oac çíà÷èò àöåòàò.
+Oac=Oac çíà÷èò àöåòàò.
+Pro=Pro çíà÷èò ïðîëèí; PrO çíà÷èò ïðàçåîäèì-êèñëîðîä.
+PrO=Pro çíà÷èò ïðîëèí; PrO çíà÷èò ïðàçåîäèì-êèñëîðîä.
+Val=Val çíà÷èò âàëèí; VAl çíà÷èò âàíàäèé-àëþìèíèé.
+VAl=Val çíà÷èò âàëèí; VAl çíà÷èò âàíàäèé-àëþìèíèé.
diff --git a/MwtZip/Lang_Spanish.ini b/MwtZip/Lang_Spanish.ini
new file mode 100644
index 0000000..cdca612
--- /dev/null
+++ b/MwtZip/Lang_Spanish.ini
@@ -0,0 +1,1021 @@
+; Language customization file for the Molecular Weight Calculator program by Matthew Monroe
+; Contact at alchemistmatt@yahoo.com and http://come.to/alchemistmatt/ or http://www.alchemistmatt.com/
+;
+; When customizing the phrases in this file, the ampersand symbol (&) signifies a
+; keyboard shortcut. For example, the default value for key 1000 is &File. When
+; running the program, the F in File will be underlined and the user may press Alt-F
+; to access the File menu (in addition to clicking on the file menu)
+; To improve usability of the program, please try to include the & symbol in menu items
+; and buttons. Note, however, that if two controls on the same form have the same &
+; shortcut, they will not respond to the alt key in the usual way.
+;
+; In this file, items surround by brackets [] are section headers -- the program ignores them
+; when parsing the file. The key values (1000, 1010, 1020, etc.) should not be changed, with
+; the exception that new caution statements may be added at the end of the file.
+; Lines beginning with a semicolon (;) are also ignored since they are treated as comments
+; However, you should not place a ; at the end of a line with an actual key and caption.
+;
+; Keys with multiple values separated by a vertical line (|) represent multiple items loaded
+; into a ComboBox control. When translating to other languages, you must keep the same number
+; of items in the list, or program functionality will be lost. For example, key 7070 contains
+; hours|minutes|seconds Thus, hours, minutes, and seconds will be loaded into a control, from
+; which the user may select one of them. In Spanish, you would use 7070=horas|segundos|minutos
+;
+; If you create a new .Ini file for a foreign language and would like it posted on my
+; web page, simply e-mail it to me.
+;
+; Spanish translation initially by Matthew Monroe and Alexandre R Soares (http://br.geocities.com/ntegti)
+; Improved by Perez de la Hoz (epdlh1@mundofree.com)
+
+[Language]
+Language=Spanish
+
+
+[frmMain Menus]
+; Menu Items
+1000=&Archivo
+1010=Editar Tabla de &Elementos
+1020=Editar &Abreviaturas
+1030=Calcular Masa Desde Valores en &Fichero
+1040=&Imprimir
+1050=&Salir
+1500=&Edición
+1510=Cortar
+1520=&Copiar
+1530=&Pegar
+1540=&Suprimir
+1550=Copiar formula en &RTF
+1560=Copiar &masa molecular
+1570=Copiar &valores porcentuales
+1580=&Duplicar fórmula actual
+1590=Borrar todas las &fórmulas
+1600=Borrar fórmula actual
+1610=Expandir &abreviaturas
+1620=Convertir a fórmula &empírica
+2000=&Ver
+2010=Ver &Todo
+2020=Ver &Una
+2030=Resolver desde &Porcetajes
+2040=&Desactivado
+2050=&Activado
+2500=&Herramientas
+2510=Convertidor de Dilución &Mol/Masa
+2520=Buscador de &Fórmulas
+2530=Convertidor de Nomenclatura de &Aminoacidos
+2533=&Peptide Sequence Fragmentation Modelling
+2536=&Isotopic Distribution Modelling
+2538=Show Isotopic &Distribution for Current Formula
+2540=Ca&lculadora
+2550=Calculador de Flujo &Capilar
+3000=&Opciones
+3010=Eligir &Idioma (Choose language)
+3020=&Preferencias del Programa
+3030=Cambiar &Fuente
+3040=Mantener &Activo
+3050=&Guardar o Restaurar
+3060=&Cargar Valores y Fórmulas por Defecto
+3070=&Guardar Valores y Fórmulas Actuales
+3500=A&yuda
+3510=&Descripción del Programa
+3530=Ver &Etiquetas
+3540=&Sobre Molecular Weight Calculator
+
+[frmMain Status Messages and Verification Messages]
+3600=La linea completa es
+3605=Zooming
+3610=Esta seguro de que desea convertir fórmula actual a empírica?
+3615=Convertir a formula empírica
+3620=Esta seguro de que desea borrar la fórmula?
+3625=Borrar Fórmula
+3630=Seguro que desea expandir las abreviaturas de la fórmula actual a sus equivalentes elementales?
+3635=Expandir abreviaturas
+3640=Se restablecen los valores y fórmulas por defecto, borrándose las fórmulas actuales. Seguro que desea hacer esto?
+3645=Restablecer valores y fórmulas
+3650=Fije el porcentaje objetivo de este elemento a un valor dado. Seleccione Borrar para reajustar el porcentaje o bien seleccione Cancelar para ignorar cualquier cambio.
+3660=Utilice las flechas de paginación Up/Down o Left/Right para moverse por los valores (F11 da salida del modo solver de porcentajes).
+3665=Haga clic sobre celda para cambiar un porcentaje (F11 da salida del modo solver de porcentajes).
+3670=Listo
+3700=Calculando; pulse una tecla o haga clic para interrumpir.
+3710=x es
+3720=Valor calculado
+3730=Target (objetivo)
+3740=Diferencia con el target
+3750=% Solver activado
+3760=Resultados de Molecular Weight Calculator
+3770=Valores y fórmulas por defecto restaurados.
+3780=Está seguro de que desea borrar todas las fórmulas?
+3785=Borrar todas las fórmulas
+3790=Seguro que desea salir?
+3795=Salir del programa
+3800=Cargando abreviaturas
+3810=Cargando elementos
+3820=(usando masas atómicas medias ponderadas)
+3830=(usando masas del isótopo mayoritario de los elementos)
+3840=(usando masas del isótopo mayoritario en número entero)
+3850=Nuevo idioma salvado
+
+[Phrases common throughout application]
+4000=Ce&rrar
+4010=&OK
+4020=&Cancelar
+4030=&Salir
+; The following is the abbreviation for Molecular Weight
+; It must be exactly two letters long
+4040=MW
+4050=Cuidado
+
+[frmMain]
+; Form Caption
+4900=Molecular Weight Calculator
+; Labels
+5000=Fórmula
+5010=Modo masa media de elementos
+5020=&Media
+5021=Utilizando masa media de los elementos
+5030=&Isótopo
+5031=Usando la masa del isótopo mayoritario en cada elemento
+5040=&Entero
+5041=Usando masa nominal entera del isótopo mayoritario
+; TextBoxes
+5051=Escriba aquí la fórmula molecular
+; Buttons
+5100=&Calcular
+5101=Determinar la masa molecular de la fórmula actual
+5110=&Nueva Fórmula
+5111=Agrega un nueva fórmula a la lista
+5116=Visualizar una nueva fórmula
+; Grid control
+5201=Teclear para fijar o borrar el valor objetivo
+; Status control
+5301=Teclear doble click en la línea para ampliarla
+5350=MWC ya se está ejecutando. Abrir otro nuevo MWC?
+5355=MWC todavía esta en uso
+
+[frmAboutBox]
+5500=Acerca de MWC
+5510=Este programa es freeware; distribuyalo libremente
+
+[frmIntro]
+5700=Inicializando
+
+[frmAminoAcidConverter]
+; Form Caption
+6000=Convertidor de Nomenclatura de Aminoácidos
+; Labels
+6010=Secuencia de aminoácido de una letra
+6020=Secuencia de aminoácido de tres letras
+; TextBoxes
+6031=Introducir secuencia de abrevación usando 1 letra aquí
+6041=Introducir secuencia de abrevación usando 3 letras aquí
+; Buttons
+6050=&Copiar Secuencia de Tres Letras a Cuadro de Fórmula:
+6060=Copy to &Fragmentation Modeller
+; CheckBoxes
+6080=&Añadir espacio cada 10 residuos
+6090=Residuos &separados por guión
+
+[frmCalculator]
+; Form caption
+6500=Calculadora
+; Textbox
+6511=Escriba la expresión matemática a evaluar aquí
+; Buttons
+6520=&Calcular
+6521=Evalua la actual expresión
+; Status control
+6601=Teclear doble click en la línea de status para ampliarla
+6610=Resultado
+
+[frmCapillaryCalcs]
+; Form Caption
+7000=Cálculos de Flujo Capilar y Velocidad Másica
+; Combo Boxes
+7010=Tubo capilar abierto|Red capilar
+7011=Cambiar entre tubo capilar abierto y red capilar.
+7020=Calcular presión final|Calcular longitud de columna|Calcular diámetro interior|Calcular caudal volumétrico|Calcular caudal usando tiempo muerto
+7030=psi|Pascales|kilo-Pascales|atmósferas|bares|Torr (mm Hg)
+7035=micro-m|inches
+7040=Poise [g/(cm*s)]
+7050=mililitro/min|microlitro/min|nanolitro/min
+7060=cm/h|mm/h|cm/min|mm/min|cm/s|mm/s
+7070=horas|minutos|segundos
+7080=mililitro|microlitro|nanolitro|picolitro
+7090=mol/litro|mili-mol/litro|micro-mol/litro|nano-mol/litro|pico-mol/litro|femto-mol/litro|atto-mol/litro|mg/mililitro|microgramo/mililitro|nanogramo/mililitro|microgramo/microlitro|nanogramo/microlitro
+7100=pico-mol/min|femto-mol/min|atto-mol/min|pico-mol/s|femto-mol/s|atto-mol/s
+7110=moles|mili-moles|micro-moles|nano-moles|pico-moles|femto-moles|atto-moles
+; Labels and frames
+7200=Presión final
+7210=Longitud de columna
+7220=Diámetro interior columna
+7230=Viscosidad del disolvente
+7240=Diámetro de partícula
+7250=Caudal volumétrico
+7260=Velocidad lineal
+7270=Tiempo muerto de columna
+7280=Volumen de columna
+7290=Porosidad de partícula (epsilon)
+7300=Cálculos de velocidad másica
+7310=Concentración de muestra
+7320=Tiempo de inyección
+7330=Velocidad caudal másico
+7340=Moles inyectados
+7350=Cálculos por ensanchamiento de columna
+7360=Coeficiente de difusión
+7370=Longitud tubo abierto
+7380=Diámetro interior tubo abierto
+7390=Anchura máxima inicial
+7400=Velocidad lineal óptima
+7410=(en partículas de 5 micro-m)
+7420=Variación de tiempo
+7430=Variación adicional
+7440=Máxima anchura resultante
+7450=Incremento porcentual
+7460=La fórmula actual es
+7480=Masa personalizada
+7500=cm
+7520=cm^2/s
+7530=s (en base)
+7540=cm/s
+7550=s^2
+7560=s
+7570=g/mol
+; TextBoxes
+7601=Introduzca el número de masa molecular (g/mol) personalizado para utilizar en los cálculos
+; Buttons
+7700=Mostrar/Ocultar Cálculos de Máximo &Ensanchamiento
+7710=&Mirar Textos Explicativos de Ecuaciones
+7730=Mirar Ecuaciones
+; Option Buttons
+7750=&Utilizar la masa del compuesto de la fórmula actual
+7760=Introducir masa molecular &personalizada
+; CheckBoxes
+7800=&Asociar con datos prev.
+; ToolTips
+7851=Un valor típico de viscosidad es 0,0089 poises
+7861=Un valor típico de porosidad es 0,4
+7871=Un coeficiente de difusión típico es 0,000001, es decir 1E-6; Coeficient típico por peptides es 0,00005, es decir 5E-5
+; Menus
+7900=&Load Values
+7910=&Save Values
+7950=&Capillary Flow Calculations
+
+[frmChangeFont]
+; Form Caption
+8000=Cambiar la fuente de la fórmula a:
+; Combo Boxes
+; Labels
+8050=Fuente usada actualmente es:
+8060=Cambiar la fuente a:
+8070=Tamaño:
+; Buttons
+
+[frmChangeValue]
+; Form Caption
+8200=Cambiar valor
+; Buttons
+8210=&Volver a valores por defecto
+
+[frmChangeLanguage]
+8400=Eligir idioma
+; Labels
+8410=Los idiomas disponibles se muestran abajo. Elija por favor el idioma que usted desea utilizar.
+8420=Si no hay ficheros con el idioma por usted deseado. Visite la Homepage del autor para descargar idiomas alternos.
+
+[frmDiff]
+8600=Diferencia porcentuales de Solver
+8610=&Copiar
+8611=Copiar los resultados al portapapeles
+
+[frmEditAbbrev]
+9000=Editar Abreviaturas
+; Buttons
+9010=&Cargar Abreviaturas por Defecto
+9011=Se borran todas las abreviaturas y se cargan las establecidas por defecto
+9020=&Borrar
+; Messages
+9050=Máximo alcanzado
+9060=Desgraciadamente sólo se permite una lista de 50 abreviaturas de aminoácidos.
+9070=Desgraciadamente sólo se permite una lista de 50 abreviaturas normales.
+9080=Por favor, agregue la entrada como abreviatura normal.
+9090=La abreviatura o fórmula molecular será cambiada por el valor que usted introduzca. Seleccione Borrar para suprimir la abreviatura o Cancelar para ignorar cualquier cambio.
+9100=Esta seguro que desea perder todas las modificaciones realizadas?
+9105=Cerrando ventana de edición de abreviaturas
+9110=Esta seguro que desea borrar las abreviaturas y cargar las abreviaturas establecidas por defecto?
+9115=Cargar valores por defecto
+;Table Tool Tip
+9140=
+9141=Haga click para cambiar una abreviatura, fórmula y/o carga eléctrica
+; Table Column Titles
+9150=Carga Eléctrica
+9160=Fórmula Molecular
+9170=Abreviatura Normal
+9180=Nombre Aminoácido
+9190=Una letra
+
+[frmEditElem]
+9200=Editor de Tabla de Elementos
+; Buttons
+9210=&Cargar Valores por Defecto
+9211=Asigna a las masas elementales los pesos isotópicos medios
+9220=&Borrar
+9230=Usar Masas Isotópicas &Medias
+9231=Fija todas las masas elementales a sus pesos medios encontrados en la naturaleza
+9240=Usar Masa del &Isótopo Mayoritario
+9241=Fija todas las masas elementales a la masa del isótopo más común en la naturaleza del elemento en cuestión (para espectrometría de alta resolución)
+9245=Usar Masa Isotópica Nominal &Entera
+9246=Fija todas las masas elementales a la masa nominal entera del isótopo más común en la naturaleza del elemento en cuestión (para espectrometría de baja resolución)
+; Messages
+9250=La masa elemental y/o su desviación será cambiada al valor que usted introduzca. Seleccione Borrar para volver al valor por defecto o Cancelar para ignorar cualquier cambio.
+9260=Esta seguro que desea borrar todos los valores actuales y cargar los valores de masas medias elementales establecidas por defecto?
+9265=Cambiar a las masas medias elementales
+9270=Esta seguro que desea reajustar todos los valores a masas elementales de isótopo mayoritario?
+9275=Cambiar a las masas isotópicas mayoritarias
+9280=Esta seguro que desea reajustar todos los valores a masas elementales de isótopo mayoritario en número entero?
+9285=Cambiar a las masas enteras nominales isotópicas mayoritarias
+9290=Esta seguro que desea reajustar todos los valores a masas elementales establecidas por defecto (masas medias)?
+9295=Cargar Valores por Defecto
+9300=De ser ejecutado, luego no podrá ser cancelado.
+9310=Esta seguro que desea perder todos los cambios realizados?
+9315=Cerrando la ventana del editor de tabla de elementos
+;Table Tool Tip
+9340=
+9341=Haga click para cambiar la masa, carga y/o desviación de un elemento
+;Table Column Titles
+9350=Elemento
+9360=Masa
+9370=Desviación
+; Combo boxes
+9380=Símbolo|Número atómico|Desviación|Carga eléctrica
+9390=Clasificar elementos por:
+
+[frmEquationsBroadening]
+9500=Ecuaciones de Ensanchamiento Adicional de Columna
+
+[frmEquationsOpenTube]
+9550=Ecuaciones de Flujo en Tubo Abierto
+
+[frmEquationsPackedCapillary]
+9600=Ecuaciones de Flujo en Red Capilar
+
+[frmFinderModeWarn]
+; Instructions Label
+9700=El uso típico del buscador de fórmulas resulta cuando la masa monoisotópica de un compuesto es conocida (determinada típicamente por espectrometría de masas) y el compuesto que corresponde con el potencial indicado debe ser buscado.
+9701=Por ejemplo; una masa de 16,0312984 Daltons es medida para una molécula que contiene carbono e hidrógeno, y se desea saber su fórmula empírica posible. Realizando la búsqueda, con una tolerancia del peso de 5.000 ppm los resultados son tres: H2N, CH4, y O. Dentro de 500 ppm solamente se obtiene CH4 que corresponde con el emparejamiento correcto.
+9702=Para alcanzar esta respuesta, el programa se debe fijar en modo Masas Isotópicas Mayoritarias. Esto se puede hacer manualmente o bien el programa puede hacerlo automáticamente.
+9703=Elección:
+9705=The typical use of the Fragmentation Modelling feature is for predicting the masses expected to be observed with a Mass Spectrometer when a peptide is ionized, enters the instrument, and fragments along the peptide backbone.
+9706=The peptide typically fragments at each amide bond. For example, the peptide Gly-Leu-Tyr will form the fragments Gly-Leu, Leu-Tyr, Gly, Leu, and Tyr. Additionally, the cleavage of the amide bond can occur at differing locations, resulting in varying weights.
+; Buttons
+9720=Continuar
+; Option Buttons
+9750=Cambiar al modo Masas &Isotópicas Mayoritarias.
+9760=Cambiar siempre &Automáticamente al modo Masas Isotópicas Mayoritarias.
+9770=Continuar usando Masas Isotópicas &Medias.
+; CheckBoxes
+9780=No &volver a mostrar más este diálogo
+
+[frmFinder]
+10000=Buscador de Fórmulas
+; Labels
+10010=Seleccione los elementos apropiados o agregue otros, introduzca un peso molecular o las composiciones porcentuales en los elementos, entonces pulse Calcular para encontrar los compuestos que corresponden con las especificaciones marcadas.
+10020=Masa máxima de la fórmula:
+10030=Masa molecular objetivo:
+10040=Tolerancia de masa:
+10050=Porcentaje de tolerancia:
+10060=Min.
+10070=Max.
+10080=Elemento
+10090=%
+10100=Nº máx de resultados
+10105=Peso atómico
+; Percent completed status messages
+10110=% terminado
+10115=Ordenando
+10120=Buscando
+10125=Ocupado
+10130=Finalizado
+10135=Compuestos
+10140=Ordenación interrumpida
+10145=Cálculos interrumpidos
+10150=Formateando
+10155=Hecho
+10160=Formato abortado
+; Listboxes & Textboxes
+10201=Haga doble click sobre cualquier línea para ampliarla
+10221=Cantidad de la masa del compuesto que proceda de la masa buscada u objetivo
+10231=Cantidad de porcentaje elemental que proceda del porcentaje buscado u objetivo
+10241=Número máximo de soluciones del compuesto a encontrar.
+10251=Número mínimo de átomos del compuesto a buscar
+10256=Número máximo de átomos del compuesto a buscar
+10260=Porcentaje
+10261=El porcentaje del elemento en la molécula objetivo es
+10270=Masa
+10271=Escriba una masa y una abreviatura, símbolo o marca para ese elemento
+; Note the following is 'dm' in English, standing for 'delta mass' or the mass difference
+; of the given result's mass versus the target mass
+10280=delta mass
+; Note the following is 'ppm' in English, standing for 'parts per million'
+10285=ppm
+; Buttons
+10300=&Opciones del Buscador
+10301=Atajo: Ctrl+O
+10310=&Buscar
+10311=Encuentra los compuestos que corresponden a los parámetros especificados
+10320=&Imprimir
+10330=Copiar &RTF
+10331=Copiar resultados al portapapeles en formato Rich Text Format
+10340=&Copiar
+10341=Copiar resultados al portapapeles
+10345=&Display Iso Abundance
+10346=Display the Isotopic Distribution of the currently selected compound (Ctrl+D)
+; Option Buttons
+10350=Buscar por Masa &Molecular
+10360=Buscar por Composición &Porcentual
+; CheckBoxes
+10370=Modo ppm
+; Elements (and Custom element phrase)
+10400=Carbono
+10405=Hidrógeno
+10410=Nitrógeno
+10415=Oxígeno
+10420=Otro
+; Messages
+10450=Un tecla fue presionada
+10455=Abortar
+10460=El ratón ha hecho click fuera de la ventana de resultados.
+10465=Parar el formato.
+10470=Parar clasificación.
+10480=La suma de los valores porcentuales no es igual a 100%.
+10485=Continuar con el cálculo?
+10490=No se puede calcular
+10500=Un tecla fue presionada.
+10505=El ratón ha hecho click fuera de la ventana de resultados.
+10510=Busqueda detenida.
+10515=El número máximo de soluciones ha sido alcanzado.
+10520=Número max de soluciones
+10530=Compuestos encontrados
+; Note: the following is used when displaying the results of a percent composition
+; search in the formula finder. A synonym for 'has' would be 'contains' or 'is composed of'
+10535=contiene
+10540=Ha ocurrido un error en la memoria. La lista de los soluciones probablemente este llena. Las soluciones encontradas hasta ahora son las indicadas.
+10545=Fuera de memoria.
+10550=El rectángulo de soluciones está vacío.
+10555=Nada que copiar.
+10560=Nada que imprimir.
+10565=Esta seguro que desea imprimir el resultado actual?
+10570=Imprimir
+
+[frmFinderOptions]
+10800=Opciones del Buscador
+; Labels
+10810=Marque las celdillas para activar las opciones del buscador del fórmulas.
+; Textboxes & Comboboxes
+10821=Límite carga mínima del compuesto
+10831=Límite carga máxima del compuesto
+10840=Búsqueda completa|Búsqueda limitada
+10841=Una búsqueda completa encuentra todos los compuestos que se ajusten mientras que una búsqueda limitada encuentra compuestos dentro de un rango atómico específico.
+10850=Clasificación de fórmulas
+10851=Métodos para clasificar resultados, recalcular o reclasificar.
+10855=Ordenar por carga
+10860=Ordenar por MWC
+10865=Ordenar por m/z
+10870=Relación masa/carga de la objetivo
+10875=Masa molecular objetivo
+; CheckBoxes
+10900=Encontrar &Carga
+10901=Calcular la carga media de cada uno de los elementos encontrados
+10910=&Rango de la Carga Límite
+10911=Límite de compuestos visualizados para un rango de carga específico
+10920=Encontrar m/&z
+10921=Calcular ratio m/z para cada compuesto encontrado
+10930=Buscar &Objetivo m/z
+10931=Buscar compuestos con valores de m/z equivalentes al objetivo
+10940=Or&denar Resultado:
+10941=Convertir resultados a fórmulas empíricas y ordenarlos
+10950=Átomos de H2 &Inteligentes
+10951=Limitar el número de átomos de hidrógeno en cada compuesto a un número realista
+10960=Ajustar &Automáticamente el mín y el máx en búsqueda limitada
+10961=Ajustar automáticamente los valores del mín y el máx de búsqueda a un rango válido para que encuentre la masa objetivo
+
+[frmMMconvert]
+11000=Conversor de Mol y Masa
+; Combo Boxes
+11010=Conversor de cantidades|Calcular concentración|Calcular dilución
+11011=Realiza conversiones con diferentes cantidades de compuesto o ejecuta cálculos de molaridad
+11020=moles|mili-moles|micro-moles|nano-moles|pico-moles|femto-moles|atto-moles|kilogramos|gramos|miligramos|microgramos|Libras|onzas|microlitros|mililitros|litros|Galones|cuartos|Pintas
+11021=Unidades origen desde donde convertir la cantidad
+11026=Unidades de cantidad a utilizar para el cálculo de la concentración
+11030=microlitros|mililitros|litros|Galones|cuartos|Pintas
+11031=Unidades del volumen
+11041=Unidades destino a donde convertir la cantidad
+11051=Unidades de concentración
+; Labels
+11080=g/ml
+; Textboxes
+11101=Cantidad a convertir del compuesto
+11106=Cantidad de compuesto que se disolverá en disolvente
+11111=Densidad del compuesto
+11121=El volumen de disolvente en que el compuesto se disuelve
+11131=Concentración del compuesto en la disolución
+; Buttons
+11150=Calcular Canti&dad
+11151=Calcula la cantidad de soluto usando el volumen y la concentración de la disolución
+11160=Calcular &Volumen
+11161=Calcula el volumen de disolución usando la cantidad de soluto y la concentración de la disolución
+11170=Calcular &Concentración
+11171=Calcula la concentración de la disolución usando la cantidad de soluto y el volumen de disolución
+
+; Dilution-related controls
+11200=Cálculos de dilución
+11205=Cálculos de evaporación o sublimación
+11210=Calcular volumen de dilución requerido|Calcular volumen total requerido|Encontrar concentración final|Encontrar concentración inicial
+11211=Cantidad a encontrar para cálculos de dilución
+11220=&Asociar resultado conversión como concentración inicial para dilución
+11221=Copia el resultado del conversor de cantidades como concentración inicial para las diluciones y viceversa si se hacen cambios
+11230=Unidades &homogéneas en la dilución
+11231=Homogeneización de las unidades de volumen soluto, disolvente acuoso y el volumen total final de la dilución
+; Dilution related labels and textbox tooltips
+11250=Concentración &Inicial
+11256=Concentración de la disolución de partida
+11260=Volu&men de concentración inicial
+11266=Volume de la disolución de partida antes de iniciar la dilución con agua destilada (pura)
+11270=Concentración &Final
+11276=Concentración final de soluto al terminar la dilución
+11280=Volumen de dilución re&querido
+11286=Volumen de agua destilada requerido para añadir a la disolución inicial en el proceso de dilución
+11290=Volumen final &Total
+11296=Volumen final de la disolución resultante después de la dilución
+
+[frmProgramPreferences]
+11500=Preferencias de Molecular Weight Calculator
+; Frame labels
+11510=Modo de reconocimiento de abreviaturas (F3)
+11520=Modo de reconocimiento de fórmulas (F4)
+11530=Modo desviación standar (F12)
+11540=Opciones del Buscador de Fórmulas
+11550=Opciones de salida de programa
+; Buttons
+11600=Grabar Opciones como &Defecto
+11610=Cargar &Opciones por Defecto
+; Option Buttons
+11650=Normal
+11651=Reconoce abreviaturas normales, pero no los aminoácidos
+11655=Normal + Aminoácidos
+11656=Reconoce abreviaturas normales y los aminoácidos
+11660=Desconectado
+11661=Ignora todas las abreviaturas
+11665=Por aproximación
+11666=Tantea la nomenclatura de las fórmulas mientras analiza
+11670=Exacto
+11671=Requiere usar fórmulas con nomenclatura exacta
+11675=Inteligente
+11676=Interpreta las fórmulas, y no las capitaliza
+11680=Abreviado
+11681=Visualización abreviada de las desviaciones standar
+11685=Científico
+11686=Visualización en notación científica de las desviaciones standar
+11690=Decimal
+11691=Visualización en forma decimal larga de las desviaciones standar
+11695=Desactivado
+11696=No visualiza las desviaciones standar
+11700=Salir del programa con ESC y luego confirmar salida
+11701=Establecer si la tecla ESCAPE es capaz de cerrar el programa y por otro lado si se exige confirmación a la salida o no
+11705=Salir del programa con ESC sin confirmar salida
+11710=Anulada ESC, pero confirmar salida de programa
+11715=Anulada ESC, y no confirmar salida de programa
+; CheckBoxes
+11750=Activar a&vance automático después de calcular
+11751=Movimiento a una nueva línea de fórmula después de calcular la masa de la fórmula anterior
+11760=Corchetes equivalen a &Paréntesis
+11761=Considerar los corchetes ( [...] ) como paréntesis, y no como ubicadores de porcentajes calculados
+11770=Copiar a&utomaticamente el peso molecular
+11771=Copia automáticamente el valor del peso molecular de la fórmula seleccionada al portapapeles después de cada cálculo
+11780=Cálcular car&ga
+11781=Cálcula la carga eléctrica de los compuestos (lo hace con reglas muy básicas, no pueden corregir anomalías por doble o triple enlace)
+11800=Cambiar automáticamente al modo &sótopo mayoritario
+11801=Cambia automáticamente a masas isotópicas al entrar en el Buscador Fórmulas
+11810=No mostrar &nunca diálogo de advertencia sobre modo de masa al entrar en Buscador
+11811=Activarlo implica que nunca se mostrará el cuadro de advertencia sobre modo de masa al entrar en el Buscador del Fórmulas
+11820=Salvar &automáticamente opciones, valores y fórmulas al salir
+11821=Salva automáticamente opciones, valores y fórmulas seleccionadas en el programa cada vez que se sale
+11830=Mostrar avisos de confusión en la nomenclatura
+11831=Advierte cuando las combinaciones elementales dan posiblemente origen a confusión en fórmulas (como el Co contra el CO)
+11840=Mostrar cambio rápido del modo &másico de elementos
+11841=Muestra el cuadro de opciones que permite cambiar rapidamente los modos másicos de los elementos
+11850=Mostrar etiquetas (tips)
+11851=Muestra brevemente mensajes de ayuda cuando el ratón se sitúa sobre ciertos botones o áreas operativas del programa
+11860=Resaltar campo de texto cuando esta seleccionado
+11861=Resalta la totalidad del campo de texto al moverse sobre él
+11870=Minimizar automáticamente las ventanas &inactivas del programa
+11871=Oculta la ventana principal del programa al usar el convertidor de mol/masa, el buscador de fórmulas ... etc.
+11881=Elija un número más pequeño para evitar que la ventana principal llene la pantalla. Si lo baja, debe salir y reinicializar de nuevo el programa. El número máximo aconsejado dependerá de la resolución en pantalla.
+11885=Número máximo de fórmulas a mostrar
+11890=Module to show at startup
+11896=Module to show when the program starts
+11898=Main Window|Formula Finder|Capillary Flow Calculator|Mole/Mass Converter|Peptide Sequence Fragmentation Modeller|Amino Acid Notation Converter|Isotopic Distribution Modeller
+
+; Messages
+11900=Opción de grabación automática de valores salvada.
+11910=Opciones por defecto restauradas.
+11920=Valores y fórmulas grabados.
+11925=Valores y fórmulas NO salvadas ya que la línea de comando / X fue utilizada.
+11930=Opciones por defecto grabadas.
+11935=Opciones por defecto NO salvadas ya que la línea de comando / X fue utilizada.
+
+[frmFragmentationModelling]
+12000=Peptide Sequence Fragmentation Modelling
+; General Combo Boxes
+12010=1 letter notation|3 letter notation
+12011=Amino acid sequence notation type
+12020=&Match Ions
+; Textboxes
+12051=Enter amino acid sequence here
+12061=Shifts the loaded ions to be matched by the given amount to correct for post-translational modifications.
+; Frames, labels, and checkboxes
+12100=Sequence:
+12150=N and C Terminus
+12160=&N
+12170=&C
+12180=H
+12190=OH
+12200=Ion Types
+12210=&A Ions
+12215=&B Ions
+12220=&Y Ions
+12230=Neutral Losses
+12236=Choose ions to which losses will be applied
+12240=Loss of H2O
+12250=Loss of NH3
+12260=Charge Options
+12270=&2+ charged ions
+12280=&Threshold
+12286=The 2+ m/z value will be computed for ions above this m/z
+12300=Ion Match Options
+12310=&Remove Precursor Ion
+12320=Ion Mass
+12330=Mass Window
+12340=&Ion Matching Window
+12350=Da
+12355=Alignment &Offset
+12360=Ion Statistics
+12370=Loaded
+12375=Remaining after binning
+12380=Within tolerance
+12385=Precursor not found
+12390=Precursor removed
+12395=Precursor not removed
+12400=Matches
+12405=Score
+
+; Column titles in grids
+; Note: # means 'number', Immon. means 'immonium', and Seq. means 'sequence'
+12500=#
+12510=Immon.
+12520=Seq.
+12550=Mass
+12560=Intensity
+
+; Ion Types (must be exactly one letter long)
+12600=a
+12610=b
+12620=y
+
+; Menu Items
+12800=&Load Sequence Info
+12810=&Save Sequence Info
+12820=Load List of &Ions to Match
+12830=&Close
+12840=&Copy Predicted Ions
+12850=Copy Predicted Ions as &RTF
+12855=Copy Predicted Ions as Html
+12860=&Paste List of Ions to Match
+12870=Clear Match Ion &List
+12880=List of &Ions to Match
+12900=Predicted &Mass Spectrum
+12910=&Update Spectrum on Change
+12920=Ion Match List &Options
+12930=&Automatically Align Ions to Match
+12940=&Fragmentation Modelling
+
+[frmMsPlot]
+13000=Plot
+; The following is an abbreviation for the word 'Location'
+13010=Loc
+
+; Legend Items
+13030=Predicted Ions
+13035=Loaded Ions
+
+; Menu Items
+13100=&Export Data
+13150=&Plot Type
+13160=&Sticks To Zero
+13170=&Gaussian Peaks
+13180=Set Effective &Resolution
+13190=X Axis Gridlines
+13200=Y Axis Gridlines
+13210=&Ticks to label (approx.)
+13220=&X Axis
+13230=&Y Axis
+13235=Plot &Quality (affects speed)
+13240=&Gaussian Representation Quality
+13245=&Approximation Factor
+13250=Set &X Range
+13260=Set &Y Range
+13270=&Autoscale Y Axis
+13280=&Fix mimimum Y at zero
+13290=&Zoom Out to Previous
+13295=Ctrl+Z or Right Click
+13300=Zoom Out to Show All
+13310=&Cursor Mode
+13315=Space Enables Move
+13320=&Zoom
+13330=&Move
+13340=&Show Current Position
+13342=Show &Legend
+13345=Reset to &Default Options
+13350=&Zoom Box
+13360=Zoom &In
+13365=Left Click
+13370=Zoom In Horizontal
+13380=Zoom In Vertical
+13390=Zoom &Out
+13400=Zoom Out Horizontal
+13410=Zoom Out Vertical
+
+[frmIonMatchOptions]
+14000=Ion Matching Options
+; Buttons
+14010=&Reset to Defaults
+
+; Explanations
+14050=When a list of ions is imported into the program, ions of similar mass may optionally be grouped together via a binning process to reduce the total number of data points. Next, ions around the precursor ion may be removed.
+14055=Then, the intensities are normalized to the given maximum intensity and ordered by decreasing intensity. The top-most ions (number of ions to use) are divided into distinct mass regions and the ions in each region again normalized.
+14060=The masses of the predicted ions for a given peptide sequence are easily computed. However, intensity values must also be assigned to the masses.
+14065=The B and Y ions are typically assigned the same intensity while the A ion is typically 5 times less intense. Shoulder ions (masses ± 1 Da from the B and Y ions) can be added, in addition to including neutral losses (H2O and NH3).
+
+; Frames, labels, and checkboxes
+14100=Normalization Options for Imported Data
+14110=&Group Similar Ions (Bin Data)
+14115=Mass Window
+14120=Normalized Intensity
+14130=Number of Ions to Use
+14140=Mass region subdivisions
+14150=Ion Intensities of Predicted Ions
+14160=A Ion Intensity
+14165=B Ion Intensity
+14170=Y Ion Intensity
+14180=B/Y Ion Shoulders
+14190=Neutral Losses
+
+[frmSetValue]
+14500=Set Value
+14510=&Set
+14520=&Start
+
+[frmProgress]
+14700=Progress
+14710=Click to Pause
+14715=Preparing to Pause
+14720=Paused
+14725=Resuming
+14730=(Press Escape to abort)
+14740=min. elapsed/remaining
+
+[frmIsotopicDistibution]
+15000=Isotopic Distribution
+; Frames, labels, and checkboxes
+15050=Formula:
+15060=Results:
+15100=&Plot Results
+15110=&Compute
+15151=Isotopic distribution results
+
+[ErrorMessages]
+20001=Elemento químico desconocido
+20003=Error; falta cerrar paréntesis
+20004=Incongruencia de paréntesis
+20005=No puede haber un 0 (cero) después de un elemento o guión ( - )
+20006=Numero demasiado grande o bien debería estar después de guión ( - ) o del signo de potencia (^)
+20007=Número demasiado grande
+20011=Los números deben preceder a corchete abierto ([), no a corchete cerrado (]) (a menos que 'corchetes equivalen a paréntesis' este activo)
+20012=Un número debe estar presente después de un corchete y/o después de la coma
+20013=Falta corchete de cierre (])
+20014=Número mal colocado; debería estar detrás de un elemento químico, [, ), -, o el signo de potenciación (^)
+20015=Incongruencia de corchete
+20016=No puede anidar corchetes o jerarquizar corchetes dentro de hidratos múltiples (a menos que 'corchetes equivalen a paréntesis' este activo)
+20018=Elemento químico desconocido
+20020=Debe haber un número de masa isotópica a continuación del signo de potenciación (^)
+20022=Hay un cero después del signo de potenciación (^); una masa isotópica nula no se permite
+20023=Masas isotópicas negativas no se permiten después del signo de potenciación (^)
+20024=Las masas isotópicas no se permiten como abreviaturas
+20025=Un elemento debe estar presente después del guión del coeficiente principal
+20026=Las masas isotópicas no se permiten como abreviaturas; D es una abreviatura
+20027=Los números fraccionarios no pueden contener más de una coma
+20028=Las abreviaturas no pueden estar presentes en la definición de una abreviatura
+20050=El valor de objetivo es mayor que 100%, un valor imposible.
+20075=Las letras no se permiten en la línea de operaciones de la calculadora
+20076=Falta cerrar paréntesis
+20077=Incongruencia de paréntesis
+20078=Número erroneo; o demasiado grande, o demasiado pequeño, o demasiado largo
+20080=Operador mal colocado
+20081=La variable comando es menor o igual a 1; fallo en funcionamiento del programa (program bug); por favor, notifiquelo al programador
+20082=Falta operador.
+20085=No puede haber números negativos en una potencia
+20086=No puede tener cero una potencia
+20087=No puede tener cero una potencia
+20089=Un único número positivo o negativo debe ir después de un signo de potenciación (^)
+20090=Los números fraccionarios no pueden contener más de una coma
+20091=Usted intentó dividir un número por cero. Por favor, solucione el problema y recalcule.
+20092=Los espacios en blanco no se permiten en las expresiones matemáticas
+20093=Utilice una coma como punto decimal
+20094=Utilice una coma como punto decimal
+20095=Algún número debe estar presente después de una coma
+20100=Error grabando fichero de abreviaturas
+20110=Se ha reconstruido el fichero abreviaturas a su valor por defecto.
+20115=Se ha cambiado el nombre al fichero antiguo
+20120=El encabezado [AMINO ACIDS] no se ha encontrado en el fichero MWT_ABBR.DAT. Este encabezado dede estar localizado antes o por encima del encabezado [ABBREVIATIONS].
+20125=Seleccione OK para continuar sin abreviaturas.
+20130=El encabezado [ABBREVIATIONS] no se ha encontrado en el fichero MWT_ABBR.DAT. Este encabezado debe estar localizado después o por debajo del encabezado [AMINO ACIDS].
+20135=Seleccione OK para continuar solamente con abreviaturas de aminoácidos.
+20140=El fichero de abreviaturas no fue encontrado en el directorio de instalación del programa
+20150=Error cargando/creando fichero de abreviaturas
+20160=Abreviatura ignorada -- Fórmula no válida
+20170=Abreviatura ignorada; la abreviatura esta duplicada
+20180=Abreviatura ignorada; carácter o letra no válido
+20190=Abreviatura ignorada; demasiado larga
+20200=Ignorando línea de datos no correcta
+20210=Se ha reconstruido el fichero elementos químicos a su valor por defecto.
+20220=Masa posiblemente incorrecta para ese elemento químico.
+20230=Desviación posiblemente incorrecta para ese elemento químico
+20250=Línea de datos ignorada; símbolo del elemento no correcto
+20260=El encabezado [ELEMENTS] no se ha encontrado en el fichero MWT_ELEM.DAT. Este encabezado debe estar localizado en el fichero.
+20265=Seleccione OK para continuar con los valores por defecto establecidos para los elementos químicos.
+20270=El fichero de elementos no fue encontrado en el directorio de instalación del programa
+20280=Error cargando/creando fichero de elementos
+20305=Continuando con los valores por defecto.
+20320=Error grabando archivo de elementos
+20330=Error cargando/creando archivo de valores
+20340=Seleccione OK para continuar sin cargar los valores y fórmulas por defecto.
+20345=Si utiliza una unidad (disco) de sólo-lectura, utilice el parámetro /X en la línea de comandos para prevenir este error.
+20350=Error
+20360=Error grabando archivo de opciones por defecto
+20370=Si utiliza una unidad (disco) de sólo-lectura, usted no puede grabar nuevas opciones por defecto.
+20380=Error grabando archivo de valores y fórmulas
+20390=Si utiliza una unidad (disco) de sólo-lectura, usted no puede grabar datos con nuevos valores y fórmulas.
+20400=Error cargando/creando archivo de opciones por defecto
+20410=Seleccione OK para continuar sin cargar los valores por defecto del usuario.
+20440=El fichero de idioma no se ha podido abrir con éxito, quizá tiene un formato de texto incorrecto.
+20450=No es posible cargar los campos de texto específicos del idioma
+20460=El fichero de idioma no se ha podido encontrar en el directorio de instalación del programa
+20470=El fichero solicitado para el cáculo de masa molecular no fue encontrado
+20480=Fichero no encontrado
+20490=Este fichero ya existe. Desea sustituirlo?
+20500=Fichero presente
+20510=Error de lectura/escritura de archivos durante el procesamiento por lotes
+20515=Seleccione OK para abortar el procesamiento por lotes de archivos.
+20520=Error en programa
+20530=Estas líneas del código no deberían haber sido encontradas. Por favor, comuníqueselo al programador.
+20540=Usted no puede editar elementos químicos porque el parámetro /X es utilizado en la línea de comandos.
+20545=Usted no puede modificar abreviaturas porque el parámetro /X es utilizado en la línea de comandos.
+20550=El solver desde porcentajes no puede ser utilizado cuando los corchetes equivalen a paréntesis. Puede cambiar el modo de reconocimiento de corchetes descativando la opción correspondiente dentro del cuadro de diálogo 'Preferencias del programa'.
+20555=Solver desde porcentajes no disponible
+20560=Número máximo de campos para fórmulas alcanzado.
+20570=El campo para la fórmula actual está en blanco.
+20580=Desactive la resolución -solver- desde porcentajes (F11) antes de escribir una nueva fórmula.
+20590=Ha ocurrido un error de desbordamiento de memoria. Por favor, disminuya los valores numéricos y vuelva a calcular.
+20600=Un error ha ocurrido
+20605=Por favor, salga e informe del error al programador. Seleccione 'Sobre MWC' en el menú Ayuda para ver la dirección de correo electrónico disponible.
+20610=Los espacios en blanco no se permiten en fórmulas
+20620=Caracter de texto no válido.
+20630=Imposible copiar a nueva fórmula.
+20650=El campo para la fórmula actual está en blanco.
+20655=El modo solver desde porcentajes está activado (F11 para desactivar).
+20660=Advertencia; la masa del isótopo es seguramente demasiado grande para este elemento
+20662=Advertencia; la masa del isótopo es seguramente demasiado pequeña para este elemento
+20665=vs. un peso atómico medio de
+20670=Advertencia; es imposible que la masa del isótopo sea tan pequeña para este elemento
+20675=protones
+20680=Nota: modo de reconocimiento de fórmulas 'exacto' activado
+20685=Nota: en modo solver desde porcentajes, un corchete izquierdo ([) debe estar precedido por un x
+20690=Nota: corchetes equivalen a paréntesis (opción está activada)
+20700=Uno o más elementos deben ser seleccionados.
+20705=El máximo debe ser mayor que cero.
+20710=El máximo debe ser menor que
+20715=El número mínimo de elementos debe ser igual o mayor que cero.
+20720=El número mínimo de elementos debe ser menor que el número máximo de elementos.
+20725=El número máximo de elementos debe ser menor de 65.025
+20730=Una masa atómica debe ser incluida para los elementos químicos personalizados.
+20735=La masa atómica debe ser mayor que 0 para los elementos personalizados.
+20740=La masa molecular objetivo debe ser tecleada.
+20745=La masa molecular objetivo debe ser mayor que cero.
+20755=Una masa molecular máxima debe ser tecleada.
+20760=La masa molecular máxima debe ser mayor que cero.
+20765=Los porcentajes buscados deben ser tecleados para cada elemento
+20770=Los porcentajes buscados deben ser mayor que cero.
+20775=Los pesos elementales personalizados deben contener solamente números o solamente letras. Si se utilizan letras, deben estar asociadas a un único símbolo elemental o abreviatura válida.
+20780=El peso elemental personalizado esta vacío. Si se utilizan letras, deben estar asociadas a un único símbolo elemental o abreviatura válida.
+20785=Elemento o abreviatura desconocido al personalizar su masa elemental
+20790=Sólo se permiten símbolos químicos elementales o abreviaturas.
+20800=Atención; ninguna abreviatura fue cargada -- El comando no ha tenido ningún efecto.
+
+20900=Error Reading/Writing sequence information file.
+20910=Ions are already present in the ion list. Replace with new ions?
+20920=Replace Existing Ions
+20930=Loading Ion List
+20940=Process aborted
+20945=Aborted
+20950=Normalizing ions
+20960=Normalizing by region
+20965=Sorting by Intensity
+20970=Matching Ions
+20980=The clipboard is empty. No ions to paste.
+20985=No ions
+20990=Pasting ion list
+21000=Determining number of ions in list
+21010=Parsing list
+21020=No valid ions were found on the clipboard. A valid ion list is a list of mass and intensity pairs, separated by commas, tabs, or spaces. One mass/intensity pair should be present per line.
+21030=Error writing data to file
+21040=Set Range
+21050=Start Val
+21055=End Val
+21060=Set X Axis Range
+21065=Set Y Axis Range
+21070=Enter a new Gaussian Representation quality factor. Higher numbers result in smoother Gaussian curves, but slower updates. Valid range is 1 to 50, default is 20.
+21072=Gaussian Representation Quality
+21075=Enter a new plotting approximation factor. Higher numbers result in faster updates, but give a less accurate graphical representation when viewing a wide mass range (zoomed out). Valid range is 1 to 50, default is 10.
+21077=Plotting Approximation Factor
+21080=Resolving Power Specifications
+21090=Resolving Power
+21100=X Value of Specification
+21110=Please enter the approximate number of ticks to label on the axis
+21115=Axis Ticks
+21120=Creating Gaussian Representation
+21130=Preparing plot
+21135=Drawing plot
+21140=Are you sure you want to restore the default plotting options?
+21145=Restore Default Options
+21150=Auto Align Ions
+21155=Maximum Offset
+21160=Offset Increment
+21165=Aligning Ions
+
+21500=All Files
+21510=Text Files
+21515=txt
+21520=Data Files
+21525=csv
+21530=Sequence Files
+21535=seq
+21540=Ion List Files
+21545=txt
+21550=cap
+21555=Capillary Flow Info Files
+
+[CautionStatments]
+; Note: Caution statement keynames are case sensitive; i.e. Bi is different than BI
+; You may add new caution statements if desired; however, you will need to save
+; the file with a name other than Lang_English and change the Language= key
+; since this file is not loaded if the language is English
+22000=Atención
+Bi=Bi significa bismuto; BI significa boro-yodo.
+Bk=Bk significa berkelio; BK significa boro-potasio.
+Bu=Bu significa grupo butílico; BU significa boro-uranio.
+Cd=Cd significa cadmio; CD significa carbono-deuterio.
+Cf=Cf significa californio; CF significa carbono-flúor.
+Co=Co significa cobalto; CO significa carbono-oxígeno.
+Cs=Cs significa cesio; CS significa carbono-sulfuro.
+Cu=Cu significa cobre; CU significa carbono-uranio.
+Dy=Dy significa dysprosio; DY significa el deuterio-itrio.
+Hf=Hf significa hafnio; HF significa hidrógeno-flúor.
+Ho=Ho significa holmio; HO significa hidrógeno-oxígeno.
+In=In significa indio; IN significa yodo-nitrógeno.
+Nb=Nb significa niobio; NB significa nitrógeno-boro.
+Nd=Nd significa neodimio; ND significa nitrógeno-deuterio.
+Ni=Ni significa níquel; NI significa nitrógeno-yodo.
+No=No significa nobelio; NO significa nitrógeno-oxígeno.
+Np=Np significa neptuno; NP significa nitrógeno-fósforo.
+Os=Os significa osmio; OS significa oxígeno-sulfuro.
+Pd=Pd significa paladio; PD significa fósforo-deuterio.
+Ph=Ph significa fósforo, PH significa fósforo-hidrógeno
+Pu=Pu significa plutonio; PU significa fósforo-uranio.
+Py=Py significa pyridine; PY significa fósforo-itrio.
+Sb=Sb significa antimonio; SB significa sulfuro-boro.
+Sc=Sc significa escandio; SC significa sulfuro-carbono.
+Si=Si significa silicio; SI significa sulfuro-yodo.
+Sn=Sn significa estaño; SN significa sulfor-nitrógeno
+TI=TI significa tritio-yodo, Ti significa titanio.
+Yb=Yb significa iterbio; YB significa itrio-boro.
+BPY=BPY significa boro-fósforo-itrio; Bpy significa bipyridine.
+BPy=BPy significa boro-pyridine; Bpy significa bipyridine.
+Bpy=Bpy significa bipyridine.
+Cys=Cys significa cisteina; CYS significa carbono-itrio-sulfuro.
+His=His significa histidine; HIS significa hidrógeno-yodo-sulfuro.
+Hoh=HoH significa holmio-hidrógeno; HOH significa hidrógeno-oxígeno-hidrógeno (agua).
+Hyp=Hyp significa hydroxyproline; HYP significa hidrógeno-itrio-fósforo.
+OAc=OAc significa oxígeno-actinio; Oac significa acetato.
+Oac=Oac significa acetato.
+Pro=Pro significa proline; PrO significa praseodymium-oxígeno.
+PrO=Pro significa proline; PrO significa praseodymium-oxígeno.
+Val=Val significa valine; VAl significa vanadio-aluminio.
+VAl=Val significa valine; VAl significa vanadio-aluminio.
diff --git a/MwtZip/MSFLXGRD.OCX b/MwtZip/MSFLXGRD.OCX
new file mode 100644
index 0000000..c68b64c
Binary files /dev/null and b/MwtZip/MSFLXGRD.OCX differ
diff --git a/MwtZip/MWTWIN.INI b/MwtZip/MWTWIN.INI
new file mode 100644
index 0000000..62eac75
--- /dev/null
+++ b/MwtZip/MWTWIN.INI
@@ -0,0 +1,26 @@
+; Options File for MWTWIN Program (v6.19)
+;
+; DO NOT EDIT -- Select Save Options As Defaults in Preferences under the Options Menu
+;
+View=0
+Convert=0
+Abbrev=1
+StdDev=0
+Caution=1
+Advance=1
+Charge=0
+QuickSwitch=1
+Font=Arial
+FontSize=10
+ExitConfirm=0
+ToolTips=1
+HideInactiveForms=0
+AutoSaveValues=1
+BracketsAsParentheses=0
+AutoCopyCurrentMWT=0
+StartupModule=0
+MaximumFormulasToShow=9::11
+FinderWeightModeWarn=0
+FinderBoundedSearch=0
+Language=English
+LanguageFile=Lang_English.ini
diff --git a/MwtZip/MWT_ABBR.DAT b/MwtZip/MWT_ABBR.DAT
new file mode 100644
index 0000000..56a2416
--- /dev/null
+++ b/MwtZip/MWT_ABBR.DAT
@@ -0,0 +1,64 @@
+; Abbreviations File for MWTWIN program (v6.19)
+;
+; Comments may be added by preceding with a semicolon
+; Two group headings must exist: [AMINO ACIDS] and [ABBREVIATIONS]
+; Abbreviations may be added; simply type the abbreviation and molecular
+; formula under the appropriate column in either section
+; Note: Only the first letter of an abbreviation is allowed to be capitalized
+;
+; The abbreviations in the Amino Acid section are treated as extended level
+; abbreviations: they are only recognized when extended abbreviations are on
+; If this file becomes corrupted, the MWTWIN program will inform the user
+; and ignore incorrect lines
+; If this file becomes deleted, the MWTWIN program will create a new file
+; with the default abbreviations
+;
+; Default Amino Acids are in their ionic form
+; Amino Acid abbreviation names may be up to 6 characters long
+[AMINO ACIDS]
+Ala C3H5NO 0 A ; Alanine
+Arg C6H12N4O 0 R ; Arginine, (unprotonated NH2)
+Asn C4H6N2O2 0 N ; Asparagine
+Asp C4H5NO3 0 D ; Aspartic acid (undissociated COOH)
+Cys C3H5NOS 0 C ; Cysteine (no disulfide link)
+Gla C6H7NO5 0 U ; gamma-Carboxyglutamate
+Gln C5H8N2O2 0 Q ; Glutamine
+Glu C5H7NO3 0 E ; Glutamic acid (undissociated COOH)
+Gly C2H3NO 0 G ; Glycine
+His C6H7N3O 0 H ; Histidine (unprotonated NH)
+Hse C4H7NO2 0 ; Homoserine
+Hyl C6H12N2O2 0 ; Hydroxylysine
+Hyp C5H7NO2 0 ; Hydroxyproline
+Ile C6H11NO 0 I ; Isoleucine (same as Leucine)
+Leu C6H11NO 0 L ; Leucine (same as Isoleucine)
+Lys C6H12N2O 0 K ; Lysine (unprotonated NH2)
+Met C5H9NOS 0 M ; Methionine
+Orn C5H10N2O 0 O ; Ornithine
+Phe C9H9NO 0 F ; Phenylalanine
+Pro C5H7NO 0 P ; Proline
+Pyr C5H5NO2 0 ; Pyroglutamic acid
+Sar C3H5NO 0 ; Sarcosine
+Ser C3H5NO2 0 S ; Serine
+Thr C4H7NO2 0 T ; Threonine
+Trp C11H10N2O 0 W ; Tryptophan
+Tyr C9H9NO2 0 Y ; Tyrosine
+Val C5H9NO 0 V ; Valine
+
+; Normal abbreviation names may be up to 6 characters long
+[ABBREVIATIONS]
+Bpy C10H8N2 0 ; Bipyridine
+Bu C4H9 1 ; Butyl
+D ^2.014H 1 ; Deuterium
+En C2H8N2 0 ; Ethylenediamine
+Et CH3CH2 1 ; Ethyl
+Me CH3 1 ; Methyl
+Ms CH3SOO -1 ; Mesyl
+Oac C2H3O2 -1 ; Acetate
+Otf OSO2CF3 -1 ; Triflate
+Ox C2O4 -2 ; Oxalate
+Ph C6H5 1 ; Phenyl
+Phen C12H8N2 0 ; Phenanthroline
+Py C5H5N 0 ; Pyridine
+Tpp (C4H2N(C6H5C)C4H2N(C6H5C))2 0 ; Tetraphenylporphyrin, mw 612.733
+Ts CH3C6H4SOO -1 ; Tosyl
+Urea H2NCONH2 0 ; Urea
diff --git a/MwtZip/MWT_ELEM.DAT b/MwtZip/MWT_ELEM.DAT
new file mode 100644
index 0000000..52e352e
--- /dev/null
+++ b/MwtZip/MWT_ELEM.DAT
@@ -0,0 +1,128 @@
+; Elements File for MWTWIN program (v6.19)
+;
+; Comments may be added by preceding with a semicolon
+; The heading [ELEMENTWEIGHTTYPE] 1 signifies that Average Elemental Weights are
+; being used while [ELEMENTWEIGHTTYPE] 2 signifies the use of Isotopic Weights
+; and [ELEMENTWEIGHTTYPE] 3 signifies the use of Integer Weights
+; The group heading [ELEMENTS] must exist to signify the start of the elements
+; Elemental values may be changed, but new elements may not be added
+; If you wish to add new elements, simply add them as abbreviations
+; If this file becomes deleted, the MWTWIN program will create a new file
+; with the default values
+; Uncertainties from CRC Handbook of Chemistry and Physics
+; For Radioactive elements, the most stable isotope is NOT used;
+; instead, an average Mol. Weight is used, just like with other elements.
+; Data obtained from the Perma-Chart Science Series periodic table, 1993.
+; Uncertainties from CRC Handoobk of Chemistry and Physics, except for
+; Radioactive elements, where uncertainty was estimated to be .n5 where
+; n represents the number digits after the decimal point but before the last
+; number of the molecular weight.
+; For example, for No, MW = 259.1009 (±0.0005)
+;
+[ELEMENTWEIGHTTYPE] 1
+; The values signify:
+; Weight Uncertainty Charge
+[ELEMENTS]
+H 1.00794 0.00007 1
+He 4.002602 0.000002 0
+Li 6.941 0.002 1
+Be 9.012182 0.000003 2
+B 10.811 0.007 3
+C 12.0107 0.0008 4
+N 14.00674 0.00007 -3
+O 15.9994 0.0003 -2
+F 18.9984032 0.0000005 -1
+Ne 20.1797 0.0006 0
+Na 22.98977 0.000002 1
+Mg 24.305 0.0006 2
+Al 26.981538 0.000002 3
+Si 28.0855 0.0003 4
+P 30.973761 0.000002 -3
+S 32.066 0.006 -2
+Cl 35.4527 0.0009 -1
+Ar 39.948 0.001 0
+K 39.0983 0.0001 1
+Ca 40.078 0.004 2
+Sc 44.95591 0.000008 3
+Ti 47.867 0.001 4
+V 50.9415 0.0001 5
+Cr 51.9961 0.0006 3
+Mn 54.938049 0.000009 2
+Fe 55.845 0.002 3
+Co 58.9332 0.000009 2
+Ni 58.6934 0.0002 2
+Cu 63.546 0.003 2
+Zn 65.39 0.02 2
+Ga 69.723 0.001 3
+Ge 72.61 0.02 4
+As 74.9216 0.00002 -3
+Se 78.96 0.03 -2
+Br 79.904 0.001 -1
+Kr 83.8 0.01 0
+Rb 85.4678 0.0003 1
+Sr 87.62 0.01 2
+Y 88.90585 0.00002 3
+Zr 91.224 0.002 4
+Nb 92.90638 0.00002 5
+Mo 95.94 0.01 6
+Tc 97.9072 0.0005 7
+Ru 101.07 0.02 4
+Rh 102.9055 0.00002 3
+Pd 106.42 0.01 2
+Ag 107.8682 0.0002 1
+Cd 112.411 0.008 2
+In 114.818 0.003 3
+Sn 118.71 0.007 4
+Sb 121.76 0.001 -3
+Te 127.6 0.03 -2
+I 126.90447 0.00003 -1
+Xe 131.29 0.02 0
+Cs 132.90545 0.00002 1
+Ba 137.327 0.007 2
+La 138.9055 0.0002 3
+Ce 140.116 0.001 3
+Pr 140.90765 0.00002 4
+Nd 144.24 0.03 3
+Pm 144.9127 0.0005 3
+Sm 150.36 0.03 3
+Eu 151.964 0.001 3
+Gd 157.25 0.03 3
+Tb 158.92534 0.00002 3
+Dy 162.5 0.03 3
+Ho 164.93032 0.00002 3
+Er 167.26 0.03 3
+Tm 168.93421 0.00002 3
+Yb 173.04 0.03 3
+Lu 174.967 0.001 3
+Hf 178.49 0.02 4
+Ta 180.9479 0.0001 5
+W 183.84 0.01 6
+Re 186.207 0.001 7
+Os 190.23 0.03 4
+Ir 192.217 0.03 4
+Pt 195.078 0.002 4
+Au 196.96655 0.00002 3
+Hg 200.59 0.02 2
+Tl 204.3833 0.0002 1
+Pb 207.2 0.1 2
+Bi 208.98038 0.00002 3
+Po 208.9824 0.0005 4
+At 209.9871 0.0005 -1
+Rn 222.0176 0.0005 0
+Fr 223.0197 0.0005 1
+Ra 226.0254 0.0001 2
+Ac 227.0278 0.00001 3
+Th 232.0381 0.0001 4
+Pa 231.03588 0.00002 5
+U 238.0289 0.0001 6
+Np 237.0482 0.0005 5
+Pu 244.0642 0.0005 4
+Am 243.0614 0.0005 3
+Cm 247.0703 0.0005 3
+Bk 247.0703 0.0005 3
+Cf 251.0796 0.0005 3
+Es 252.083 0.005 3
+Fm 257.0951 0.0005 3
+Md 258.1 0.05 3
+No 259.1009 0.0005 3
+Lr 262.11 0.05 3
diff --git a/MwtZip/MWT_VALU.INI b/MwtZip/MWT_VALU.INI
new file mode 100644
index 0000000..f3541f6
--- /dev/null
+++ b/MwtZip/MWT_VALU.INI
@@ -0,0 +1,977 @@
+; Values File for MWTWIN Program (v6.19)
+;
+; DO NOT EDIT -- Select Save Values and Formulas under the Options Menu
+;
+Formula0=BrCH2(CH2)7CH2Br
+Formula1=FeCl3-6H2O
+Formula2=Co(Bpy)(CO)4
+Formula3=^13C6H6-.1H2O
+Formula4=HGlyLeuTyrOH
+AminoAcidConvertOneLetter=GLY
+AminoAcidConvertThreeLetter=Gly-Leu-Tyr
+AminoAcidConvertSpaceOneLetter=1
+AminoAcidConvertDashThreeLetter=1
+Mole/MassWeightSource=0
+Mole/MassCustomMass=100
+Mole/MassAction=2
+Mole/MassFrom=1
+Mole/MassFromUnits=0
+Mole/MassDensity=1
+Mole/MassToUnits=3
+Mole/MassVolume=100
+Mole/MassVolumeUnits=1
+Mole/MassMolarity=1
+Mole/MassMolarityUnits=0
+Mole/MassDilutionMode=0
+Mole/MassMolarityInitial=10
+Mole/MassMolarityInitialUnits=0
+Mole/MassVolumeInitial=3.0
+Mole/MassVolumeInitialUnits=1
+Mole/MassMolarityFinal=2
+Mole/MassMolarityFinalUnits=0
+Mole/MassVolumeSolvent=12.0
+Mole/MassVolumeSolventUnits=1
+Mole/MassVolumeTotal=15
+Mole/MassVolumeTotalUnits=1
+Mole/MassLinkConcentrations=0
+Mole/MassLinkDilutionVolumeUnits=1
+CapillaryFlowMode=0
+CapillaryFlowComputationType=3
+CapillaryFlowLinkFlowRate=1
+CapillaryFlowLinkLinearVelocity=1
+CapillaryFlowShowPeakBroadeningSave=0
+CapillaryFlowWeightSource=0
+CapillaryFlowCustomMass=100
+CapillaryFlowOpenText0=50
+CapillaryFlowPackedText0=3000
+CapillaryFlowOpenText1=50
+CapillaryFlowPackedText1=50
+CapillaryFlowOpenText2=30
+CapillaryFlowPackedText2=75
+CapillaryFlowOpenText3=0.0089
+CapillaryFlowPackedText3=0.0089
+CapillaryFlowOpenText4=0
+CapillaryFlowPackedText4=5
+CapillaryFlowOpenText5=100
+CapillaryFlowPackedText5=300
+CapillaryFlowOpenText6=22.948184
+CapillaryFlowPackedText6=1
+CapillaryFlowOpenText7=0.4
+CapillaryFlowPackedText7=0.4
+CapillaryFlowOpenText8=1
+CapillaryFlowPackedText8=1
+CapillaryFlowOpenText9=924.070953
+CapillaryFlowPackedText9=100
+CapillaryFlowOpenText10=30
+CapillaryFlowPackedText10=5
+CapillaryFlowOpenText11=2.1788
+CapillaryFlowPackedText11=1
+CapillaryFlowOpenText12=0.000005
+CapillaryFlowPackedText12=0.000005
+CapillaryFlowOpenText13=5
+CapillaryFlowPackedText13=5
+CapillaryFlowOpenText14=50
+CapillaryFlowPackedText14=50
+CapillaryFlowOpenText15=30
+CapillaryFlowPackedText15=30
+CapillaryFlowOpenText16=0
+CapillaryFlowPackedText16=0
+CapillaryFlowOpenCombo0=0
+CapillaryFlowPackedCombo0=0
+CapillaryFlowOpenCombo1=0
+CapillaryFlowPackedCombo1=0
+CapillaryFlowOpenCombo2=0
+CapillaryFlowPackedCombo2=0
+CapillaryFlowOpenCombo3=2
+CapillaryFlowPackedCombo3=2
+CapillaryFlowOpenCombo4=4
+CapillaryFlowPackedCombo4=4
+CapillaryFlowOpenCombo5=2
+CapillaryFlowPackedCombo5=2
+CapillaryFlowOpenCombo6=2
+CapillaryFlowPackedCombo6=2
+CapillaryFlowOpenCombo7=2
+CapillaryFlowPackedCombo7=2
+CapillaryFlowOpenCombo8=2
+CapillaryFlowPackedCombo8=2
+CapillaryFlowOpenCombo9=2
+CapillaryFlowPackedCombo9=2
+CapillaryFlowOpenCombo10=4
+CapillaryFlowPackedCombo10=4
+CapillaryFlowOpenCombo11=5
+CapillaryFlowPackedCombo11=5
+CapillaryFlowOpenCombo12=4
+CapillaryFlowPackedCombo12=4
+CapillaryFlowOpenCombo13=0
+CapillaryFlowPackedCombo13=0
+Calculator=6^3-8.5*3
+FinderAction=0
+FinderMWT=200
+FinderPercentMaxWeight=400
+FinderPPM=0
+FinderWtTolerance=0.05
+FinderPercentTolerance=1
+FinderMaxHits=100
+FinderSortResults=1
+FinderSmartH=1
+FinderFindCharge=0
+FinderFindMtoZ=0
+FinderLimitChargeRange=0
+FinderChargeRangeMin=-4
+FinderChargeRangeMax=4
+FinderFindTargetMtoZ=0
+FinderHighlightText=0
+FinderAutoBoundsSet=1
+FinderSortMode=0
+FinderMin0=0
+FinderMax0=18
+FinderCheckElements0=1
+FinderPercentValue0=Percent
+FinderMin1=0
+FinderMax1=101
+FinderCheckElements1=1
+FinderPercentValue1=Percent
+FinderMin2=0
+FinderMax2=15
+FinderCheckElements2=1
+FinderPercentValue2=Percent
+FinderMin3=0
+FinderMax3=13
+FinderCheckElements3=1
+FinderPercentValue3=Percent
+FinderMin4=0
+FinderMax4=10
+FinderCheckElements4=0
+FinderPercentValue4=Percent
+FinderCustomWeight1=# or Element or Abbrev.
+FinderMin5=0
+FinderMax5=10
+FinderCheckElements5=0
+FinderPercentValue5=Percent
+FinderCustomWeight2=# or Element or Abbrev.
+FinderMin6=0
+FinderMax6=10
+FinderCheckElements6=0
+FinderPercentValue6=Percent
+FinderCustomWeight3=# or Element or Abbrev.
+FinderMin7=0
+FinderMax7=10
+FinderCheckElements7=0
+FinderPercentValue7=Percent
+FinderCustomWeight4=# or Element or Abbrev.
+FinderMin8=0
+FinderMax8=10
+FinderCheckElements8=0
+FinderPercentValue8=Percent
+FinderCustomWeight5=# or Element or Abbrev.
+FinderMin9=0
+FinderMax9=10
+FinderCheckElements9=0
+FinderPercentValue9=Percent
+FinderCustomWeight6=# or Element or Abbrev.
+FragModelNotationMode=1
+FragModelSequence=Arg-His-Pro-Glu-Tyr-Ala-Val
+FragModelNTerminus=0
+FragModelCTerminus=0
+FragModelIonType0=0
+FragModelIonType1=1
+FragModelIonType2=1
+FragModelIonsToModify0=0
+FragModelIonsToModify1=1
+FragModelIonsToModify2=1
+FragModelWaterLoss=1
+FragModelAmmoniaLoss=0
+FragModelDoubleCharge=0
+FragModelDoubleChargeThreshold=8
+FragModelPrecursorIonRemove=1
+FragModelPrecursorIonMass=300
+FragModelPrecursorIonMassWindow=2
+FragModelIonMatchWindow=0.5
+FragModelIonIntensity0=10
+FragModelIonIntensity1=50
+FragModelIonIntensity2=50
+FragModelShoulderIntensity=25
+FragModelNeutralLossIntensity=10
+FragModelGroupIons=0
+FragModelGroupIonsMassWindow=0.5
+FragModelNormalizedIntensity=100
+FragModelNormalizationIonsUseCount=200
+FragModelNormalizationMassRegions=10
+IonPlotType=0
+IonPlotResolution=5000
+IonPlotResolutionXVal=500
+IonPlotGridlinesX=0
+IonPlotGridlinesY=0
+IonPlotTicksX=5
+IonPlotTicksY=5
+IonPlotGaussianQuality=20
+IonPlotApproximationFactor=10
+IonPlotAutoscaleY=1
+IonPlotShowPosition=1
+IonPlotShowLegend=0
+FragModelIonMatchList=763
+112.0853,3
+136.0762,59
+137.0843,5
+139.0817,6
+139.1133,17
+139.377,2
+139.7315,2
+140.0848,5
+141.5006,1
+143.1274,15
+143.5475,1
+144.1294,2
+148.0963,2
+156.1161,4
+157.0959,5
+159.0842,2
+159.1246,34
+160.1297,2
+160.1751,1
+163.8093,6
+169.1121,3
+171.0814,1
+171.1163,7
+175.1257,37
+182.1106,3
+185.1759,5
+186.1721,1
+186.2184,1
+187.111,37
+188.121,6
+196.1191,3
+199.1189,12
+199.1768,2
+202.3497,2
+202.3897,6
+202.4608,2
+202.9548,1
+203.0119,3
+205.1135,2
+207.0992,4
+207.1408,8
+213.1642,4
+218.1487,2
+221.9199,2
+227.1035,31
+227.1788,4
+228.0981,4
+228.1437,4
+233.155,3
+235.0365,1
+235.1248,19
+236.1297,7
+240.1542,3
+245.6539,4
+246.3976,2
+246.6541,68
+246.8809,1
+247.1341,4
+247.1902,11
+249.1758,7
+250.6709,5
+250.7164,7
+251.1959,5
+251.2478,3
+251.6217,2
+251.6747,2
+252.1679,6
+255.6198,1
+258.2047,3
+259.1178,1
+259.1799,3
+260.295,4
+260.5264,2
+260.6527,149
+261.069,1
+261.1432,39
+261.4579,3
+261.6691,5
+262.1266,6
+262.2358,4
+263.0959,2
+263.1416,2
+266.1627,13
+266.2044,6
+266.9036,2
+267.548,2
+267.9639,1
+268.1754,8
+268.6133,1
+269.1628,4
+269.6667,1
+269.7262,2
+271.1963,17
+271.2502,4
+272.1867,2
+275.1514,1
+275.6785,2
+275.7574,1
+277.1639,12
+278.137,6
+286.1738,4
+287.0152,3
+288.2111,63
+288.5215,2
+288.9533,1
+289.1393,3
+289.2121,17
+293.1697,3
+293.6161,2
+293.6732,2
+294.1874,231
+294.455,5
+294.5085,3
+294.6884,14
+294.9955,1
+295.1794,42
+295.2924,2
+295.3462,1
+295.3869,2
+295.447,1
+295.5037,2
+295.9444,1
+296.1693,10
+296.3044,3
+300.1975,21
+300.2907,2
+301.2919,2
+304.7282,2
+306.1841,3
+306.2568,1
+312.2487,6
+319.6728,4
+320.2012,4
+322.2489,2
+327.1851,3
+327.3661,1
+328.1826,68
+328.2633,14
+328.3271,3
+328.6884,49
+328.7545,6
+329.1873,8
+333.1671,8
+333.6007,3
+334.2184,12
+334.2833,1
+334.7221,4
+334.7917,2
+337.7202,3
+339.5072,2
+340.7826,2
+341.0398,2
+341.7773,4
+342.1797,393
+342.3465,3
+342.4303,5
+342.4893,4
+342.5583,7
+342.6834,159
+342.817,13
+343.0197,4
+343.1782,28
+343.4868,4
+343.5865,2
+343.6495,5
+343.7368,36
+343.8218,10
+343.8938,4
+344.0427,2
+344.1109,1
+344.1737,4
+344.258,31
+344.5179,4
+344.5953,4
+344.7082,7
+344.8063,3
+344.9668,5
+345.2133,3
+346.1691,6
+346.7994,2
+346.8672,3
+347.1616,6
+347.3818,4
+349.0909,2
+351.1988,4
+351.2789,1
+351.6955,3
+355.2979,1
+356.1698,3
+356.6293,1
+357.2323,4
+362.1739,13
+362.2378,3
+363.2299,6
+363.3801,1
+363.7023,82
+364.1729,18
+364.2336,11
+364.3133,5
+364.5458,3
+364.6974,3
+365.1807,4
+365.5901,2
+366.2758,4
+366.8056,3
+368.689,13
+369.6983,3
+370.2689,5
+370.3798,2
+371.2562,5
+372.1652,3
+373.11,3
+373.2534,2
+375.1942,4
+376.0613,2
+376.4238,5
+377.0261,6
+377.1432,1
+377.2305,12
+377.4629,5
+377.5285,3
+377.7029,598
+377.9336,5
+377.9883,3
+378.2069,338
+378.5213,10
+378.5701,6
+378.691,51
+378.7713,34
+378.9062,3
+378.9558,1
+379.0303,10
+379.1436,4
+379.2068,21
+379.3916,8
+379.6018,9
+379.7127,3
+379.8116,4
+379.8799,9
+380.3029,2
+380.4071,1
+380.958,4
+382.7159,4
+384.207,5
+384.2823,21
+386.2754,4
+388.5695,2
+390.1915,52
+390.283,4
+391.1819,10
+391.2362,8
+392.1442,3
+392.2137,1
+393.5819,2
+393.9643,2
+394.8687,2
+400.2879,3
+400.4994,4
+400.5706,2
+401.1934,4
+401.3109,371
+401.6982,6
+402.3135,81
+402.4536,5
+402.5192,3
+402.6164,3
+402.7132,1
+402.9335,5
+403.259,12
+403.309,6
+403.3876,3
+403.4753,1
+403.7147,3
+404.2269,4
+404.3108,3
+404.7374,5
+404.8113,1
+405.2131,5
+405.3333,3
+405.6795,2
+407.8732,2
+411.0067,2
+413.0218,1
+413.0892,1
+413.2335,57
+413.3035,25
+413.7328,32
+413.8081,8
+414.2228,5
+414.2828,9
+414.3424,4
+414.4356,2
+414.6094,4
+414.7199,6
+414.87,2
+416.11,3
+418.711,4
+424.4149,2
+425.287,2
+426.2268,2
+426.7227,4
+426.9637,3
+427.2246,74
+427.2997,40
+427.4115,1
+427.7239,68
+427.8436,6
+427.9177,3
+428.0482,2
+428.1411,1
+428.2242,15
+428.3137,17
+428.787,6
+429.6598,3
+430.2758,3
+432.2763,1
+433.2212,6
+435.1302,3
+435.3378,4
+443.235,2
+443.6571,1
+444.9332,3
+445.2844,5
+446.3422,2
+447.2256,2
+448.7895,3
+449.2528,3
+449.5677,1
+450.1993,3
+451.8308,3
+452.2794,3
+452.8574,3
+456.3444,3
+456.815,2
+456.893,1
+457.3382,2
+458.089,2
+460.6348,4
+460.7936,7
+460.8852,4
+461.2248,43
+461.3586,8
+461.7555,134
+462.0425,2
+462.2522,92
+462.4144,5
+462.746,21
+462.8273,5
+463.2587,9
+464.1609,3
+464.2634,1
+469.518,3
+470.3055,3
+470.7576,81
+471.1271,5
+471.2655,46
+471.4061,6
+471.7367,9
+471.8181,6
+472.0988,5
+472.2733,7
+472.5045,1
+472.5667,1
+473.0598,2
+473.6369,1
+474.4301,2
+474.6018,11
+474.6872,10
+474.9321,10
+475.0013,21
+476.3438,3
+477.5691,2
+478.7099,2
+479.9517,4
+480.0665,2
+480.3365,10
+480.4079,2
+480.64,160
+480.8394,3
+480.9711,150
+481.1419,8
+481.295,87
+481.5169,2
+481.6326,26
+481.7563,5
+481.8299,2
+481.979,5
+482.067,2
+482.3113,8
+482.4529,2
+482.7108,8
+482.9548,4
+483.0466,2
+483.1181,4
+483.2962,2
+483.4197,6
+484.2981,4
+485.0859,3
+491.204,1
+491.2662,1
+491.3383,1
+491.7874,2
+491.8846,1
+492.295,20
+492.4422,3
+493.302,5
+493.504,3
+494.313,3
+495.3706,2
+497.7738,4
+498.8301,3
+498.9969,2
+499.2101,3
+499.649,2
+500.226,3
+500.3869,342
+500.56,5
+500.7669,5
+501.0752,2
+501.3755,91
+501.4952,9
+502.2757,5
+502.3503,14
+502.4227,10
+502.5471,4
+502.6361,4
+502.8102,2
+503.4046,5
+505.4753,2
+506.4412,4
+507.7981,3
+511.2679,14
+511.3341,17
+511.4388,2
+511.7908,27
+512.3044,5
+512.5751,3
+519.3084,4
+519.7026,4
+519.8273,2
+520.2967,328
+520.6697,1
+520.7661,3
+520.8824,7
+520.9682,2
+521.2927,94
+521.7892,3
+522.0936,2
+522.2187,5
+522.3113,12
+522.4092,7
+522.7855,1
+523.2501,3
+523.3372,1
+524.1531,2
+524.7791,3
+525.3735,1
+527.2947,8
+528.2895,3
+529.1505,2
+530.6804,2
+530.7861,2
+532.306,9
+533.3033,3
+535.361,3
+552.3618,2
+553.407,2
+554.7569,2
+558.5176,2
+559.6127,1
+560.287,5
+560.4134,3
+561.2498,1
+561.3267,4
+562.8124,2
+563.2944,3
+563.4239,1
+564.8261,6
+564.9099,4
+564.976,2
+565.2759,3
+565.3707,9
+565.5305,2
+566.4214,2
+568.4691,1
+569.3346,4
+569.4058,13
+569.5019,4
+569.5747,1
+569.6475,1
+570.3633,4
+570.4498,16
+571.2965,1
+571.4195,6
+571.4758,3
+571.5784,1
+572.381,3
+572.4486,2
+572.92,4
+573.3981,3
+573.7458,4
+573.8586,67
+573.9612,21
+574.066,3
+574.3539,61
+574.4537,17
+574.5536,2
+574.8405,19
+574.9592,2
+575.3185,11
+575.4207,4
+575.5056,2
+575.5826,1
+575.6589,1
+577.3074,9
+577.4223,3
+578.1526,3
+584.5505,3
+585.3615,11
+585.4314,10
+585.5741,3
+585.6603,7
+585.9116,3
+586.0613,5
+586.388,11
+586.5022,1
+586.5732,2
+586.846,12
+587.4271,1387
+587.7023,8
+587.7939,6
+587.8698,6
+588.0663,5
+588.2092,8
+588.4289,520
+588.6898,10
+588.7769,6
+588.993,12
+589.4146,97
+589.4962,51
+589.6946,13
+589.801,3
+590.3812,16
+590.5562,5
+592.2068,4
+592.8172,1
+593.0849,2
+593.4933,3
+595.6253,2
+596.3392,4
+597.3459,1
+597.4203,3
+597.515,2
+597.9026,1
+598.2836,3
+598.3417,8
+599.1752,2
+603.2936,2
+606.1924,2
+616.592,2
+617.423,1
+624.5602,2
+637.3413,3
+638.3671,3
+639.2586,1
+639.331,1
+639.8571,3
+642.108,1
+647.2784,4
+648.3354,5
+648.4521,2
+650.7113,2
+655.2712,2
+655.3664,30
+656.3695,8
+657.3942,3
+665.3284,4
+668.3688,2
+668.4735,6
+668.6234,1
+669.4628,3
+669.8121,1
+670.5142,3
+670.5972,2
+680.7796,3
+681.3997,1
+681.4736,3
+682.3482,2
+682.4495,5
+683.3481,219
+683.4712,44
+683.6359,6
+684.0644,3
+684.3716,106
+684.5844,6
+684.8958,1
+684.9804,3
+685.3737,14
+685.4988,4
+685.7285,5
+686.0152,7
+686.1675,5
+686.5014,557
+686.9116,8
+687.2289,2
+687.3205,3
+687.4829,171
+687.5939,93
+687.8615,9
+688.3171,3
+688.4927,40
+688.5773,13
+688.6929,9
+689.2798,1
+689.3668,1
+689.4847,4
+689.593,8
+689.8995,4
+690.908,2
+696.3164,2
+696.4634,5
+696.5764,1
+697.5877,2
+699.8672,3
+707.7047,2
+708.2455,1
+709.3156,4
+709.4521,2
+715.4932,1
+723.5035,3
+725.7914,1
+726.4122,90
+727.287,1
+727.3789,21
+727.4848,20
+727.9292,2
+734.0432,2
+736.162,1
+736.3848,13
+736.5123,4
+737.3798,5
+738.4948,3
+739.3513,3
+740.5328,9
+740.6787,2
+747.4741,2
+751.2795,4
+751.5072,2
+752.3605,7
+752.7471,3
+752.9329,6
+753.1516,5
+754.0845,9
+754.4078,773
+754.6768,22
+754.8329,5
+754.9259,3
+755.0079,9
+755.3988,315
+755.5961,32
+755.8419,8
+756.1276,5
+756.2121,3
+756.4058,84
+756.5536,8
+756.6567,1
+756.7365,4
+757.0129,8
+757.1477,5
+757.5342,249
+757.8083,8
+758.149,5
+758.3525,2
+758.5118,61
+758.5903,49
+758.8855,4
+759.4818,18
+759.5482,11
+759.7332,5
+760.4133,3
+760.5503,10
+760.9072,3
+761.6349,5
+762.7632,2
+763.4514,2
+764.3829,1
+764.4747,2
+768.6735,1
+770.4442,3
+785.5863,2
+793.6028,2
+808.385,1
+808.4804,2
+825.4254,18
+825.5293,15
+826.4259,8
+826.5468,8
+827.6287,3
+838.4358,2
+845.1581,1
+853.4627,103
+853.5911,23
+853.6886,16
+854.4817,49
+854.5994,22
+854.7208,4
+855.4445,15
+855.6116,1
+855.7076,1
+856.5129,2
+859.6588,1
+860.5162,2
+902.6061,5
+902.6943,2
+903.626,4
+903.7915,1
+905.4571,2
+913.6252,1
+915.7272,3
+917.6539,2
+920.3547,3
+920.5964,139
+920.7654,36
+920.9797,2
+921.5889,89
+921.7524,38
+922.0116,1
+922.1476,3
+922.4272,17
+922.5228,33
+922.6741,27
+922.817,4
+923.1877,1
+923.5013,29
+923.6208,5
+924.4304,4
+924.6093,6
+932.7939,2
+940.4985,30
+940.5948,8
+940.7292,6
+940.8721,3
+941.397,4
+941.5469,12
+941.7205,6
+1012.576,4
+1039.495,12
+1039.615,6
+1039.692,3
+1039.85,1
+1040.467,6
+1040.583,9
+1049.522,9
+1049.63,14
+1049.709,10
+1050.543,4
+1050.646,7
+1050.765,5
+1051.748,4
+1147.636,3
+1148.107,1
+1152.559,3
+1253.329,1
+FragModelIonMatchListEnd
+FragModelIonAlignment=0
diff --git a/MwtZip/RICHTX32.OCX b/MwtZip/RICHTX32.OCX
new file mode 100644
index 0000000..66771ff
Binary files /dev/null and b/MwtZip/RICHTX32.OCX differ
diff --git a/MwtZip/ReadMe.txt b/MwtZip/ReadMe.txt
new file mode 100644
index 0000000..b8b8499
--- /dev/null
+++ b/MwtZip/ReadMe.txt
@@ -0,0 +1,32 @@
+
+ Molecular Weight Calculator
+
+ This program will calculate the molecular weight and percent
+composition of up to 20 compounds simultaneously. It recognizes
+user-definable abbreviations and all isotopes. It also includes a
+Mole/Mass Converter, Formula Finder, Capillary Flow Modeler, Amino
+Acid Notation Converter, Peptide Sequence Fragmentation Modeler,
+and built-in calculator. Full program documentation is available
+by pressing F1 during program operation. This program is FreeWare
+and may be distributed freely.
+
+ You can manually install the Molecular Weight Calculator for
+9x/NT/00/ME/XP only if you already have the MSVBVM60.Dll file in
+your Windows System directory. Otherwise, please download the file
+with the setup program from:
+ http://www.alchemistmatt.com/mwtwin.html#autoinstall
+
+To manually install, unzip the files into a program directory, for
+example "C:\PROGRAM FILES\MWTWIN". If replacing an older version, you
+do not need to replace the MWTWIN.INI, MWT_VALU.INI, or .DAT files. Do
+not move the MSFLXGRD.OCX, COMDLG32.OCX, RICHTX32.OCX, or RICHED32.DLL
+files to your \Windows\System or \Winnt\System32 directory since
+Windows will give an error message saying they are not registered correctly.
+
+Send E-Mail to AlchemistMatt@Yahoo.Com or Matt@Alchemistmatt.Com
+WWW is at http://www.alchemistmatt.com/
+and http://www.geocities.com/tandm_wy/
+and http://come.to/alchemistmatt/
+
+
+
diff --git a/MwtZip/mwt6_19.zip b/MwtZip/mwt6_19.zip
new file mode 100644
index 0000000..3697eef
Binary files /dev/null and b/MwtZip/mwt6_19.zip differ
diff --git a/MwtZip/mwtwin.chm b/MwtZip/mwtwin.chm
new file mode 100644
index 0000000..9b0965a
Binary files /dev/null and b/MwtZip/mwtwin.chm differ
diff --git a/MwtZip/mwtwin.exe b/MwtZip/mwtwin.exe
new file mode 100644
index 0000000..5a414b8
Binary files /dev/null and b/MwtZip/mwtwin.exe differ
diff --git a/MwtZip/riched32.dll b/MwtZip/riched32.dll
new file mode 100644
index 0000000..b6a7c3f
Binary files /dev/null and b/MwtZip/riched32.dll differ
diff --git a/Mwtwin.vbp b/Mwtwin.vbp
new file mode 100644
index 0000000..46afe1c
--- /dev/null
+++ b/Mwtwin.vbp
@@ -0,0 +1,81 @@
+Type=Exe
+Reference=*\G{ADB880A2-D8FF-11CF-9377-00AA003B7A11}#4.0#0#C:\WINDOWS\system32\hhctrl.ocx#HHCtrl 4.0 Type Library
+Reference=*\G{F935DC20-1CF0-11D0-ADB9-00C04FD58A0B}#1.0#0#C:\WINDOWS\system32\wshom.ocx#Windows Script Host Object Model
+Reference=*\G{C4BE505F-B909-4F29-9F14-365325BDB989}#2c.0#0#..\CWSpectrumDLL\CWSpectrumDll.dll#CWSpectrumDLL
+Reference=*\G{40A1F1BF-ADB0-441E-BF5F-0A5E4A1DDC48}#1.0#0#MwtWinDll\MwtWindll.dll#Molecular Weight Calculator - Dll Version
+Object={5E9E78A0-531B-11CF-91F6-C2863C385E30}#1.0#0; MSFLXGRD.OCX
+Object={3B7C8863-D78F-101B-B9B5-04021C009402}#1.2#0; richtx32.ocx
+Object={F9043C88-F6F2-101A-A3C9-08002B2F49FB}#1.2#0; Comdlg32.ocx
+Form=mwtwin.frm
+Module=MwtWinProcedures; MWTWIN.BAS
+Form=ABOUT.FRM
+Form=FONTCH.FRM
+Form=frmChangeValue.frm
+Form=frmCalculator.frm
+Form=frmFinderModeWarn.frm
+Form=frmFinderOptions.frm
+Form=frmProgramPreferences.frm
+Form=EquationsPackedCapillary.frm
+Form=EquationsOpenTube.frm
+Form=EquationsBroadening.frm
+Form=frmChooseLanguage.frm
+Module=FileIOFunctions; FileIOFunctions.bas
+Form=frmAminoAcidConverter.frm
+Form=frmStrings.frm
+Form=EDITABBR.FRM
+Form=frmCapillaryCalcs.frm
+Form=INTRO.FRM
+Form=MMCONV.FRM
+Module=modSharedVBRoutines; SharedVBRoutines.bas
+Form=SetRange.frm
+Form=frmFragmentationModelling.frm
+Form=frmIonMatchingOptions.frm
+Form=FINDER.FRM
+Form=frmIsotopicAbundance.frm
+Form=frmprogress.frm
+Form=frmEditAbbrevDetails.frm
+Form=Differnc.frm
+Form=EditElem.frm
+Form=frmAminoAcidModifications.frm
+Form=frmEditModSymbolDetails.frm
+Form=frmDtaTxtFileBrowser.frm
+Module=GaussianConversionRoutines; GaussianConversionRoutines.bas
+Form=frmviscosityForMeCN.frm
+IconForm="frmMain"
+Startup="Sub Main"
+HelpFile="D:\MwtWin\mwtwin.chm"
+Title="Molecular Weight Calculator"
+ExeName32="mwtwin.exe"
+Command32=""
+Name="MWTWIN"
+HelpContextID="0"
+Description="Molecular Weight Calculator for Windows, v6.41"
+CompatibleMode="0"
+MajorVer=6
+MinorVer=42
+RevisionVer=227
+AutoIncrementVer=1
+ServerSupportFiles=0
+VersionComments="by Matthew Monroe "
+VersionCompanyName=" "
+VersionLegalCopyright="This program is Freeware, distribute freely."
+VersionProductName="Molecular Weight Calculator for Windows 9x/ME/NT/00/XP"
+CompilationType=0
+OptimizationType=0
+FavorPentiumPro(tm)=0
+CodeViewDebugInfo=0
+NoAliasing=0
+BoundsCheck=0
+OverflowCheck=0
+FlPointCheck=0
+FDIVCheck=0
+UnroundedFP=0
+StartMode=0
+Unattended=0
+Retained=0
+ThreadPerObject=0
+MaxNumberOfThreads=1
+DebugStartupOption=0
+
+[MS Transaction Server]
+AutoRefresh=1
diff --git a/Mwtwin.vbw b/Mwtwin.vbw
new file mode 100644
index 0000000..2429b54
--- /dev/null
+++ b/Mwtwin.vbw
@@ -0,0 +1,35 @@
+frmMain = 77, 74, 885, 585, C, 0, 0, 778, 399, C
+MwtWinProcedures = 83, 45, 472, 524,
+frmAboutBox = 22, 22, 273, 284, C, 50, 10, 818, 658, C
+frmChangeFont = -77, 22, 565, 368, C, 0, 0, 318, 262, C
+frmChangeValue = 44, 44, 686, 390, C, 66, 66, 384, 328, C
+frmCalculator = 0, 0, 318, 262, C, 110, 110, 428, 372, C
+frmFinderModeWarn = 88, 88, 595, 353, C, 44, 19, 541, 376, C
+frmFinderOptions = 132, 132, 606, 428, C, 424, 218, 898, 514, C
+frmProgramPreferences = 88, 88, 510, 384, C, 110, 28, 587, 461, C
+frmEquationsPackedCapillary = 66, 66, 320, 514, C, 22, 36, 599, 484, C
+frmEquationsOpenTube = 44, 44, 693, 414, C, 176, 176, 753, 624, C
+frmEquationsBroadening = 44, 44, 554, 492, C, 22, 22, 563, 512, C
+frmChooseLanguage = 135, 135, 488, 492, C, 110, 110, 759, 480, C
+FileIOFunctions = 154, 154, 803, 524, C
+frmAminoAcidConverter = 66, 66, 569, 436, C, 22, 22, 735, 434, C
+frmStrings = 110, 110, 677, 480, C, 44, 44, 421, 280, C
+frmEditAbbrev = 66, 66, 699, 421, C, 44, 44, 648, 399, C
+frmCapillaryCalcs = 66, 66, 746, 414, C, 0, 0, 604, 355, C
+frmIntro = 0, 0, 658, 368, C, 154, 154, 758, 509, C
+frmMMConvert = 0, 0, 652, 348, C, 81, 54, 685, 409, C
+modSharedVBRoutines = 25, 25, 705, 372, C
+frmSetValue = 88, 88, 799, 416, C, 88, 88, 778, 407, C
+frmFragmentationModelling = 69, 69, 366, 422, C, -165, 120, 416, 486, C
+frmIonMatchOptions = 57, 37, 486, 405, C, 548, 10, 983, 391, C
+frmFinder = 44, 44, 717, 414, C, 22, 22, 695, 392, C
+frmIsotopicDistribution = 110, 110, 510, 480, C, 88, 88, 713, 458, C
+frmProgress = 23, 23, 632, 406, C, 0, 0, 609, 383, C
+frmEditAbbrevDetails = 0, 0, 631, 385, C, 138, 138, 769, 523, C
+frmDiff = 23, 23, 641, 393, C, 46, 46, 720, 436, C
+frmEditElem = 92, 92, 766, 482, C, 115, 115, 789, 505, C
+frmAminoAcidModificationSymbols = 184, 184, 600, 592, C, 92, 92, 747, 500, C
+frmEditModSymbolDetails = 0, 0, 633, 401, C, 184, 184, 817, 585, C
+frmDtaTxtFileBrowser = 22, 24, 566, 463, C, 0, 0, 788, 439, C
+GaussianConversionRoutines = 120, 120, 874, 489,
+frmViscosityForMeCN = 0, 0, 610, 548, C, 88, 116, 698, 664, C
diff --git a/MyGraph.csv b/MyGraph.csv
new file mode 100644
index 0000000..c7156b6
--- /dev/null
+++ b/MyGraph.csv
@@ -0,0 +1,364 @@
+[Data_Series1]
+102.054405212402,-3.60000991821289
+119.064971923828,-9.00002479553223
+120.064971923828,-18.0000495910645
+121.064971923828,-9.00002479553223
+127.087684631348,-3.60000991821289
+154.082046508789,-9.00002479553223
+155.082046508789,-18.0000495910645
+156.082046508789,-9.00002479553223
+189.086441040039,-3.60000991821289
+206.09700012207,-9.00002479553223
+207.09700012207,-18.0000495910645
+208.09700012207,-9.00002479553223
+246.10791015625,-3.60000991821289
+263.118469238281,-9.00002479553223
+264.118469238281,-18.0000495910645
+264.146575927734,-3.60000991821289
+265.118469238281,-9.00002479553223
+291.140960693359,-9.00002479553223
+292.140960693359,-18.0000495910645
+293.140960693359,-9.00002479553223
+347.155578613281,-3.60000991821289
+364.166137695313,-9.00002479553223
+365.166137695313,-18.0000495910645
+365.194274902344,-3.60000991821289
+366.166137695313,-9.00002479553223
+375.178070068359,-3.60000991821289
+392.188629150391,-9.00002479553223
+393.188629150391,-18.0000495910645
+394.188629150391,-9.00002479553223
+418.192687988281,-3.60000991821289
+431.748840332031,-3.60000991821289
+435.203247070313,-9.00002479553223
+436.203247070313,-18.0000495910645
+436.740753173828,-3.60000991821289
+437.203247070313,-9.00002479553223
+444.244995117188,-3.60000991821289
+445.246032714844,-9.00002479553223
+445.746032714844,-18.0000495910645
+446.246032714844,-9.00002479553223
+452.750274658203,-9.00002479553223
+453.250274658203,-18.0000495910645
+453.750274658203,-9.00002479553223
+464.262664794922,-3.60000991821289
+474.246490478516,-3.60000991821289
+491.257049560547,-9.00002479553223
+492.257049560547,-18.0000495910645
+493.257049560547,-9.00002479553223
+495.796325683594,-3.60000991821289
+500.788238525391,-3.60000991821289
+508.766326904297,-3.60000991821289
+509.293518066406,-9.00002479553223
+509.793518066406,-18.0000495910645
+510.293518066406,-9.00002479553223
+517.261108398438,-3.60000991821289
+517.271606445313,-9.00002479553223
+517.771606445313,-18.0000495910645
+518.271606445313,-9.00002479553223
+534.271667480469,-9.00002479553223
+535.271667480469,-18.0000495910645
+536.271667480469,-9.00002479553223
+552.33837890625,-3.60000991821289
+557.330261230469,-3.60000991821289
+565.308288574219,-3.60000991821289
+565.835571289063,-9.00002479553223
+566.335571289063,-18.0000495910645
+566.835571289063,-9.00002479553223
+573.813598632813,-9.00002479553223
+574.313598632813,-18.0000495910645
+574.813598632813,-9.00002479553223
+616.859680175781,-3.60000991821289
+620.36376953125,-3.60000991821289
+621.8515625,-3.60000991821289
+630.347595214844,-3.60000991821289
+630.356872558594,-9.00002479553223
+630.856872558594,-18.0000495910645
+631.356872558594,-9.00002479553223
+643.35888671875,-3.60000991821289
+646.3037109375,-3.60000991821289
+647.358154296875,-9.00002479553223
+648.358154296875,-18.0000495910645
+649.358154296875,-9.00002479553223
+651.864196777344,-9.00002479553223
+652.364196777344,-18.0000495910645
+652.864196777344,-9.00002479553223
+663.314270019531,-9.00002479553223
+664.314270019531,-18.0000495910645
+665.314270019531,-9.00002479553223
+666.393859863281,-3.60000991821289
+671.3857421875,-3.60000991821289
+679.891052246094,-9.00002479553223
+680.391052246094,-18.0000495910645
+680.891052246094,-9.00002479553223
+692.89306640625,-3.60000991821289
+701.398376464844,-9.00002479553223
+701.898376464844,-18.0000495910645
+701.912414550781,-3.60000991821289
+702.398376464844,-9.00002479553223
+706.904296875,-3.60000991821289
+715.409606933594,-9.00002479553223
+715.909606933594,-18.0000495910645
+716.409606933594,-9.00002479553223
+733.447814941406,-3.60000991821289
+743.416931152344,-3.60000991821289
+743.431640625,-3.60000991821289
+751.922241210938,-9.00002479553223
+752.422241210938,-18.0000495910645
+752.436279296875,-3.60000991821289
+752.922241210938,-9.00002479553223
+757.428161621094,-3.60000991821289
+759.387756347656,-3.60000991821289
+760.442199707031,-9.00002479553223
+761.442199707031,-18.0000495910645
+762.442199707031,-9.00002479553223
+765.933471679688,-9.00002479553223
+766.433471679688,-18.0000495910645
+766.933471679688,-9.00002479553223
+776.398315429688,-9.00002479553223
+777.398315429688,-18.0000495910645
+778.398315429688,-9.00002479553223
+780.947021484375,-3.60000991821289
+785.938903808594,-3.60000991821289
+794.444213867188,-9.00002479553223
+794.944213867188,-18.0000495910645
+795.444213867188,-9.00002479553223
+811.946350097656,-3.60000991821289
+820.45166015625,-9.00002479553223
+820.95166015625,-18.0000495910645
+821.45166015625,-9.00002479553223
+824.463012695313,-3.60000991821289
+829.454895019531,-3.60000991821289
+837.960205078125,-9.00002479553223
+838.460205078125,-18.0000495910645
+838.960205078125,-9.00002479553223
+840.457092285156,-3.60000991821289
+848.96240234375,-9.00002479553223
+849.46240234375,-18.0000495910645
+849.96240234375,-9.00002479553223
+862.490417480469,-3.60000991821289
+872.474243164063,-3.60000991821289
+887.482727050781,-3.60000991821289
+888.983764648438,-3.60000991821289
+889.484802246094,-9.00002479553223
+890.484802246094,-18.0000495910645
+891.484802246094,-9.00002479553223
+897.489074707031,-9.00002479553223
+897.989074707031,-18.0000495910645
+898.489074707031,-9.00002479553223
+904.493286132813,-9.00002479553223
+905.493286132813,-18.0000495910645
+906.493286132813,-9.00002479553223
+990.585388183594,-3.60000991821289
+1000.56921386719,-3.60000991821289
+1016.52532958984,-3.60000991821289
+1017.57977294922,-9.00002479553223
+1018.57977294922,-18.0000495910645
+1019.57977294922,-9.00002479553223
+1033.53588867188,-9.00002479553223
+1034.53588867188,-18.0000495910645
+1035.53588867188,-9.00002479553223
+1103.66943359375,-3.60000991821289
+1113.65319824219,-3.60000991821289
+1129.60925292969,-3.60000991821289
+1130.66381835938,-9.00002479553223
+1131.66381835938,-18.0000495910645
+1132.66381835938,-9.00002479553223
+1146.61987304688,-9.00002479553223
+1147.61987304688,-18.0000495910645
+1148.61987304688,-9.00002479553223
+1232.71203613281,-3.60000991821289
+1242.69580078125,-3.60000991821289
+1259.70642089844,-9.00002479553223
+1260.70642089844,-18.0000495910645
+1261.70642089844,-9.00002479553223
+1285.71044921875,-3.60000991821289
+1302.72106933594,-9.00002479553223
+1303.72106933594,-18.0000495910645
+1304.72106933594,-9.00002479553223
+1331.78039550781,-3.60000991821289
+1341.76416015625,-3.60000991821289
+1358.77478027344,-9.00002479553223
+1359.77478027344,-18.0000495910645
+1360.77478027344,-9.00002479553223
+1384.77880859375,-3.60000991821289
+1401.78942871094,-9.00002479553223
+1402.78942871094,-18.0000495910645
+1402.81750488281,-3.60000991821289
+1403.78942871094,-9.00002479553223
+1412.80126953125,-3.60000991821289
+1429.81188964844,-9.00002479553223
+1430.81188964844,-18.0000495910645
+1431.81188964844,-9.00002479553223
+1485.82653808594,-3.60000991821289
+1502.83715820313,-9.00002479553223
+1503.83715820313,-18.0000495910645
+1503.865234375,-3.60000991821289
+1504.83715820313,-9.00002479553223
+1513.84899902344,-3.60000991821289
+1530.85961914063,-9.00002479553223
+1531.85961914063,-18.0000495910645
+1532.85961914063,-9.00002479553223
+1560.88671875,-3.60000991821289
+1570.87048339844,-3.60000991821289
+1587.88110351563,-9.00002479553223
+1588.88110351563,-18.0000495910645
+1589.88110351563,-9.00002479553223
+1622.88537597656,-3.60000991821289
+1639.89599609375,-9.00002479553223
+1640.89599609375,-18.0000495910645
+1641.89599609375,-9.00002479553223
+1647.91870117188,-3.60000991821289
+1657.90246582031,-3.60000991821289
+1674.9130859375,-9.00002479553223
+1675.9130859375,-18.0000495910645
+1676.9130859375,-9.00002479553223
+1679.90686035156,-3.60000991821289
+1696.91748046875,-9.00002479553223
+1697.91748046875,-18.0000495910645
+1698.91748046875,-9.00002479553223
+1776.96020507813,-3.60000991821289
+1793.97082519531,-9.00002479553223
+1794.97082519531,-18.0000495910645
+1795.97082519531,-9.00002479553223
+[PlotOptions_Series1]
+SeriesPlotMode=1
+SeriesLineStyle=0
+SeriesLineWidth=1
+SeriesLineColor=16711680
+SeriesLineToBaseColor=16711680
+SeriesBarFillColor=16711680
+SeriesPointStyle=0
+SeriesPointColor=16711680
+AnnotationFontName=Arial
+AnnotationFontSize=10
+AnnotationFontColor=0
+SeriesLegendCaption=Theoretical
+SeriesOriginalIntensityMaximum=0
+[Annotations_Series1]
+121.065,-18.4720264,0,\FS2\H,y1
+128.0877,-4.0719864,0,\FS4\H,a2
+156.082,-18.4720264,0,\FS6\H,b2
+208.097,-18.4720264,0,\FS10\H,y2
+265.1185,-18.4720264,0,\FS14\H,y3
+265.1466,-4.0719864,0,\FS15\H,a3
+293.141,-18.4720264,0,\FS18\H,b3
+366.1661,-18.4720264,0,\FS22\H,y4
+366.1943,-4.0719864,0,\FS23\H,a4
+394.1886,-18.4720264,0,\FS27\H,b4
+437.2032,-18.4720264,0,\FS32\H,y5
+465.2627,-4.0719864,0,\FS42\H,a5
+493.257,-18.4720264,0,\FS45\H,b5
+536.2717,-18.4720264,0,\FS58\H,y6
+621.3638,-4.0719864,0,\FS70\H,a6
+649.3582,-18.4720264,0,\FS79\H,b6
+665.3143,-18.4720264,0,\FS85\H,y7
+734.4478,-4.0719864,0,\FS101\H,a7
+762.4422,-18.4720264,0,\FS111\H,b7
+778.3983,-18.4720264,0,\FS117\H,y8
+863.4904,-4.0719864,0,\FS137\H,a8
+891.4848,-18.4720264,0,\FS142\H,b8
+906.4933,-18.4720264,0,\FS148\H,y9
+991.5854,-4.0719864,0,\FS150\H,a9
+1019.58,-18.4720264,0,\FS154\H,b9
+1035.536,-18.4720264,0,\FS157\H,y10
+1104.669,-4.0719864,0,\FS159\H,a10
+1132.664,-18.4720264,0,\FS163\H,b10
+1148.62,-18.4720264,0,\FS166\H,y11
+1233.712,-4.0719864,0,\FS168\H,a11
+1261.706,-18.4720264,0,\FS171\H,b11
+1304.721,-18.4720264,0,\FS175\H,y12
+1332.78,-4.0719864,0,\FS177\H,a12
+1360.775,-18.4720264,0,\FS180\H,b12
+1403.789,-18.4720264,0,\FS184\H,y13
+1403.818,-4.0719864,0,\FS185\H,a13
+1431.812,-18.4720264,0,\FS189\H,b13
+1504.837,-18.4720264,0,\FS193\H,y14
+1504.865,-4.0719864,0,\FS194\H,a14
+1532.86,-18.4720264,0,\FS198\H,b14
+1561.887,-4.0719864,0,\FS200\H,a15
+1589.881,-18.4720264,0,\FS203\H,b15
+1641.896,-18.4720264,0,\FS207\H,y15
+1648.919,-4.0719864,0,\FS209\H,a16
+1676.913,-18.4720264,0,\FS212\H,b16
+1698.917,-18.4720264,0,\FS216\H,y16
+1795.971,-18.4720264,0,\FS220\H,y17
+[Data_Series2]
+222.12,9.34
+281.07,91.88
+282.03,62.6
+282.9,30.12
+298.59,9.89
+299.67,15.98
+416.98,12.5
+430.03,9.96
+439.4,16.33
+443.93,10.25
+484.16,18.52
+495.66,13.82
+503.09,15.11
+503.93,93.43
+505.04,46.3
+505.91,20.26
+519.13,17.75
+519.86,100
+520.79,63.4
+521.8,22.13
+[PlotOptions_Series2]
+SeriesPlotMode=1
+SeriesLineStyle=0
+SeriesLineWidth=1
+SeriesLineColor=32768
+SeriesLineToBaseColor=32768
+SeriesBarFillColor=32768
+SeriesPointStyle=0
+SeriesPointColor=32768
+AnnotationFontName=Arial
+AnnotationFontSize=10
+AnnotationFontColor=0
+SeriesLegendCaption=ALSpor_08_LTQ_4-20: Scan 8170
+SeriesOriginalIntensityMaximum=310.4
+[Annotations_Series2]
+519.86,96.4502600040956,0,\FS17\H,TEstedf
+[GlobalPlotOptions]
+Title=
+Subtitle=
+XAxis=
+YAxis=
+LabelFontName=Arial
+LabelFontSize=Arial
+LabelFontColor=0
+PlotBackgroundColor=16777215
+NormalizeOnLoadOrPaste=True
+NormalizationConstant=100
+GridLinesXColorMajor=0
+GridLinesXColorMinor=8421504
+GridLinesYColorMajor=0
+GridLinesYColorMinor=8421504
+GridLinesXVisibleMajor=False
+GridLinesXVisibleMinor=False
+GridLinesYVisibleMajor=False
+GridLinesYVisibleMinor=False
+AnnotationDensityAutoHideCaptions=True
+AnnotationDensityToleranceAutoAdjust=True
+AnnotationDensityToleranceX=109.177755032412
+AnnotationDensityToleranceY=6.81792080498197
+AutoScaleVisibleY=False
+FixMinimumYAtZero=False
+AutoAdjustScalingToIncludeCaptions=True
+PrecisionX=2
+PrecisionY=1
+CursorVisible=True
+CursorSnapToData=False
+CursorColor=0
+CursorPositionX=100
+CursorPositionY=0
+AutoLabelPeaksDisplayXPosition=True
+AutoLabelPeaksDisplayYPosition=False
+AutoLabelPeaksIncludeArrow=False
+AutoLabelPeaksHideInDenseRegions=True
+AutoLabelPeaksCaptionAngle=0
+AutoLabelPeaksIntensityThresholdMinimum=10
+AutoLabelPeaksMinimumIntensityPercentageOfMaximum=0
+AutoLabelPeaksPeakWidthMinimumPoints=5
+AutoLabelPeaksLabelCountMaximum=100
diff --git a/MyMsgBox.frx b/MyMsgBox.frx
new file mode 100644
index 0000000..03ffc39
Binary files /dev/null and b/MyMsgBox.frx differ
diff --git a/Progress.frx b/Progress.frx
new file mode 100644
index 0000000..03ffc39
Binary files /dev/null and b/Progress.frx differ
diff --git a/ReadMe.txt b/ReadMe.txt
new file mode 100644
index 0000000..fef0489
--- /dev/null
+++ b/ReadMe.txt
@@ -0,0 +1,56 @@
+Molecular Weight Calculator
+
+This program can calculate the molecular weight and percent composition
+of chemical formulas and amino acids, providing a graphical user interface to
+edit the formulas and parsing options. It recognizes user-definable
+abbreviations, custom elemental isotopes, and can display up to 20 compounds
+simultaneously. It also includes a Mole/Mass Converter, Formula Finder,
+Capillary Flow Modeller, Amino Acid Notation Converter, Peptide Sequence
+Fragmentation Modeler, Isotopic Distribution Calculator, and built-in
+calculator. Full program documentation is available by pressing F1 during
+program operation.
+
+To install the Molecular Weight Calculator for Windows
+9x/NT/00/ME/XP, run the "Molecular Weight Calculator.msi" file by
+double-clicking on it. The install program should take care of
+copying the files to the correct locations and registering all of
+the components. If replacing an older version, the .INI and .DAT
+files will be replaced. If you have abbreviations you want to save,
+backup the MWT_ABBR.DAT file before installing.
+
+Note: Sometimes when upgrading from a previous version the Lang*.Ini
+and MwtWin.Chm files do not get upgraded to the current version.
+For this reason, if uprgrading, please delete the Lang*.ini and MwtWin.Chm
+files in the Molecular Weight Calculator directory before running the
+"Molecular Weight Calculator.msi" file. I apologize for the
+inconvenience but have not found a way to fix the problem using the
+current version of the Windows Installer. There are new versions of the
+installer available, but I do not want to force users to have to update
+their Windows Installer simply to install this software.
+
+If you do not have the Windows Installer on your machine, the .msi
+file will not run and you must install the Windows Installer (it is
+included by default in Windows 2000 and higher). I did not include the
+Windows Installer as part of this download because it is an additional
+1.4 MB to download. You can download the Windows Installer from Microsoft:
+
+If running Windows 95/98, download
+ http://download.microsoft.com/download/platformsdk/wininst/1.1/W9X/EN-US/InstMsi.exe
+
+If running Windows NT, download
+ http://download.microsoft.com/download/platformsdk/wininst/1.1/NT4/EN-US/InstMsi.exe
+
+Once you have installed the Windows Installer, you should be able
+to run the "Molecular Weight Calculator.msi" setup file.
+
+-------------------------------------------------------------------------------
+Written by Matthew Monroe for the Department of Energy (PNNL, Richland, WA)
+
+E-mail: matthew.monroe@pnl.gov or matt@alchemistmatt.com
+Website: http://ncrr.pnl.gov/ or http://www.sysbio.org/resources/staff/ or
+http://www.alchemistmatt.com/ or http://come.to/alchemistmatt/
+-------------------------------------------------------------------------------
+
+Licensed under the Apache License, Version 2.0; you may not use this file except
+in compliance with the License. You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
diff --git a/ReferenceDocs/Atomic_mass_abundances.pdf b/ReferenceDocs/Atomic_mass_abundances.pdf
new file mode 100644
index 0000000..42a3841
Binary files /dev/null and b/ReferenceDocs/Atomic_mass_abundances.pdf differ
diff --git a/ReferenceDocs/CTerminalModifications.txt b/ReferenceDocs/CTerminalModifications.txt
new file mode 100644
index 0000000..1d05d5f
--- /dev/null
+++ b/ReferenceDocs/CTerminalModifications.txt
@@ -0,0 +1,11 @@
+Free Acid OH OH 17.0073 17.0027
+Amidation NH2 NH2 16.0226 16.0187
+None None 0.0000 0.0000
+Methyl Me CH3 15.0348 15.0235
+Ethyl Et C2H5 29.0617 29.0391
+t-Butyl tBu C4H9 57.1155 57.0704
+Phenyl Ph C6H5 77.1057 77.0391
+Cyclohexyl cHex C6H11 83.1533 83.0861
+Benzyl Bzl C7H7 91.1326 91.0548
+Pentafluorophenyl Pfp C6H5 77.1057 77.0391
+Pentachlorophenyl Pcp C6Cl5 249.3295 246.8443
diff --git a/ReferenceDocs/DilutionCalculations.xls b/ReferenceDocs/DilutionCalculations.xls
new file mode 100644
index 0000000..42c135d
Binary files /dev/null and b/ReferenceDocs/DilutionCalculations.xls differ
diff --git a/ReferenceDocs/DiophantineApproachToIsotopicAbuCalc.pdf b/ReferenceDocs/DiophantineApproachToIsotopicAbuCalc.pdf
new file mode 100644
index 0000000..5761ce9
Binary files /dev/null and b/ReferenceDocs/DiophantineApproachToIsotopicAbuCalc.pdf differ
diff --git a/ReferenceDocs/ErrorStringList.xls b/ReferenceDocs/ErrorStringList.xls
new file mode 100644
index 0000000..4ab475d
Binary files /dev/null and b/ReferenceDocs/ErrorStringList.xls differ
diff --git a/ReferenceDocs/Exact_Mass.html b/ReferenceDocs/Exact_Mass.html
new file mode 100644
index 0000000..52185f6
--- /dev/null
+++ b/ReferenceDocs/Exact_Mass.html
@@ -0,0 +1,158 @@
+
+
+NCSU Mass Spectrometry Facility - Exact Mass
+
+
+
+
+
+
+
+
Exact Mass Calculation
+
+
Note: If the table below appears to be just a string of symbols and numbers, try this page which is a text based version of the same table.
+
+
Premise
+
The calculation of the exact mass of any given compound is simple, but you have to have the right tool for the job. The most important tool to have is a table of exact masses. Any given element has one or more naturally occuring isotopes. Most periodic tables list the mass of an element out to several decimal places, but this is the average mass for that compound, ie. the average of the exact masses of all of the naturally occuring isotopes, weighted by their percent abundance. To obtain the exact mass of a given compound, one must use the exact masses of only the most abundant isotopes for each element present. The table below lists each element and the mass of its most abundant isotope to four decimal places.
+
+
Examples
+
Benzene is a good example compound. It has a nominal mass of 78. If you used a periodic table to calculate its "exact" mass you would get 78.1134. However, the actual exact mass, from the table below, is 78.0468. Given its small size, that is still a fairly sizable difference. For large compounds, especially organometallics, the diferences can be enormous.
+
+
Take, for instance, the zinc compound on our home page, C45H28N4OZn. The "exact" mass from a periodic table would be 706.1324. The actual exact mass is 704.1555. This large difference is mostly due to the fact that zinc has five naturally occuring isotopes. The most abundant weighs 63.9291. This is the mass to use for exact mass calculations. This isotope, however, only has an abundance of 48.6 percent. The other isotopes, while not as abundant, are all larger and bias the weight high, therefore skewing answers based on the average mass.
+
+
Exact Masses : The Table
+
As stated above, the table below contains the mass to use for a given element when calculating a compound's exact mass. These values come from a large table we have here in the lab containing all of the isotopes of the elements and their masses. The elements in bold are the more common ones that we have seen in our labs. If your favorite element of choice isn't bolded, drop me a line and I will try to correct this grevious oversite.
+Last Modified Monday, 29-Dec-97 14:05:48 EST
+System Time Sunday, 22-Mar-98 14:35:17 EST
+The Mass Spectrometry Facility WWW Pages are maintained by Howard Sanford.
+Comments, complaints, congratulations, or conciliatory remarks may be
+sent to : howard@ch9000.chem.ncsu.edu
+
+
+
+
diff --git a/ReferenceDocs/FlowAndBroadeningEquations.doc b/ReferenceDocs/FlowAndBroadeningEquations.doc
new file mode 100644
index 0000000..4a8724c
Binary files /dev/null and b/ReferenceDocs/FlowAndBroadeningEquations.doc differ
diff --git a/ReferenceDocs/InternalModifications.txt b/ReferenceDocs/InternalModifications.txt
new file mode 100644
index 0000000..4df0247
--- /dev/null
+++ b/ReferenceDocs/InternalModifications.txt
@@ -0,0 +1,28 @@
+2-Aminobutyric acid Abu C4H7NO 85.1057 85.0528
+Aminoethylcysteine AEC C5H10N2OS 146.2133 146.0514
+Phosphoserine Pse C3H6NO5P 167.0581 166.9984
+Tyrosine sulphate TyS C9H9NO5S 243.2402 243.0201
+Hydroxylysine Hyl C6H12N2O2 144.1736 144.0899
+N-methyllysine Mly C7H14N2O 142.2010 142.1106
+O-methylglutamic acid Mgl C6H9NO3 143.1424 143.0582
+Galactosamine Gal C6H13NO5 179.1730 179.0794
+N-acetylneuraminic acid Neu C11H19NO9 309.2732 309.1060
+Norleucine Nle C6H11NO 113.1595 113.0841
+Hydroxyproline Hyp C5H7NO2 113.1161 113.0477
+Carboxymethylcysteine Cmc C5H7NO3S 161.1815 161.0147
+4- carboxyglutamic acid Gla C6H7NO5 173.1253 173.0324
+2- Aminoisobutyric acid Aib C4H7NO 85.1057 85.0528
+Cysteic acid CyO C3H5NO4S 151.1430 150.9939
+Dehydroalanine Dha C3H3NO 69.0630 69.0215
+Dehydroamino-2-butyric acid Dhb C4H5NO 83.0898 83.0371
+Isovaline Iva C5H9NO 99.1326 99.0684
+Ornithine Orn C5H10N2O 114.1473 114.0793
+2-Piperidinecarboxylic acid Pip C6H9NO 111.1436 111.0684
+Pyroglutamic acid Pyr C5H5NO2 111.1002 111.0320
+Sarcosine Sar C3H5NO 71.0788 71.0371
+CAM Cysteine CAM C5H8N2O2S 160.1968 160.0306
+Homoserine lactone Hsl C4H5NO 83.0898 83.0371
+Homoserine Hms C4H7NO2 101.1051 101.0477
+Phosphothreonine pTh C4H8NO5P 181.0850 181.0140
+Phosphotyrosine pTy C9H10NO5P 243.1559 243.0297
+Methionine Sulfoxide OxM C5H9NO2S 147.1980 147.0354
diff --git a/ReferenceDocs/IonList.txt b/ReferenceDocs/IonList.txt
new file mode 100644
index 0000000..874fafa
--- /dev/null
+++ b/ReferenceDocs/IonList.txt
@@ -0,0 +1,100 @@
+300.1234 138.5
+302.2468 118.0
+304.3702 97.3
+306.4936 76.4
+308.617 55.3
+310.7404 34.2
+312.8638 13.0
+314.9872 8.3
+317.1106 29.5
+319.234 50.7
+321.3574 71.7
+323.4808 92.7
+325.6042 113.5
+327.7276 134.0
+329.851 154.4
+331.9744 174.4
+334.0978 194.1
+336.2212 213.5
+338.3446 232.5
+340.468 251.1
+342.5914 269.2
+344.7148 286.9
+346.8382 304.0
+348.9616 320.6
+351.085 336.6
+353.2084 352.0
+355.3318 366.7
+357.4552 380.8
+359.5786 394.3
+361.702 407.0
+363.8254 418.9
+365.9488 430.1
+368.0722 440.6
+370.1956 450.2
+372.319 459.0
+374.4424 467.0
+376.5658 474.2
+378.6892 480.5
+380.8126 485.9
+382.936 490.5
+385.0594 494.2
+387.1828 497.0
+389.3062 498.8
+391.4296 499.8
+393.553 499.9
+395.6764 499.1
+397.7998 497.4
+399.9232 494.8
+402.0466 491.3
+404.17 486.9
+406.2934 481.6
+408.4168 475.5
+410.5402 468.5
+412.6636 460.7
+414.787 452.0
+416.9104 442.5
+419.0338 432.2
+421.1572 421.2
+423.2806 409.4
+425.404 396.8
+427.5274 383.5
+429.6508 369.6
+431.7742 354.9
+433.8976 339.7
+436.021 323.8
+438.1444 307.3
+440.2678 290.3
+442.3912 272.7
+444.5146 254.7
+446.638 236.2
+448.7614 217.3
+450.8848 198.0
+453.0082 178.3
+455.1316 158.3
+457.255 138.0
+459.3784 117.5
+461.5018 96.8
+463.6252 75.8
+465.7486 54.8
+467.872 33.6
+469.9954 12.4
+472.1188 8.8
+474.2422 30.0
+476.3656 51.2
+478.489 72.2
+480.6124 93.2
+482.7358 114.0
+484.8592 134.5
+486.9826 154.8
+489.106 174.9
+491.2294 194.6
+493.3528 214.0
+495.4762 233.0
+497.5996 251.6
+499.723 269.7
+501.8464 287.3
+503.9698 304.4
+506.0932 321.0
+508.2166 337.0
+510.34 352.4
diff --git a/ReferenceDocs/Isotopes.xls b/ReferenceDocs/Isotopes.xls
new file mode 100644
index 0000000..4ba462b
Binary files /dev/null and b/ReferenceDocs/Isotopes.xls differ
diff --git a/ReferenceDocs/IsotopicAbundanceCalculationUsingIsoPro.txt b/ReferenceDocs/IsotopicAbundanceCalculationUsingIsoPro.txt
new file mode 100644
index 0000000..7b6fa04
--- /dev/null
+++ b/ReferenceDocs/IsotopicAbundanceCalculationUsingIsoPro.txt
@@ -0,0 +1,25 @@
+******************************************************************************
+From: senko@magnet.fsu.edu (Mike Senko)
+Subject: Re: Isotope pattern software
+Date: 7 Jul 1995 00:36:22 GMT
+Organization: NHMFL
+
+ I wrote an isotope simulator in VB using Yergey's algorithm
+(IJMSIP, 52, 1983, 337-49) a couple of years back. It does all the
+elements (isotope ratios can be modified) and has graphical output to the
+screen and printer. Since it's written in VB, it's not real fast (ie. a
+10 kDa protein takes 15 seconds to calculate the distribution and 20 to
+display on a 486/33), but I'm working on a new version in Delphi that
+should be 20x faster. If you want a copy of the old version, send me a
+note. I make no claims to the accuracy of the algorithm (you get what
+you pay for :), but Yergey was nice enough to give me his VAX Fortran
+code to translate, so it should be safe. All I know is that it matches
+experimental distributions from ESI-FTMS instruments real well.
+ Note: I've not used the WWW distribution calculator myself,
+but I've heard it's results are a little off.
+
+Mike Senko
+senko@magnet.fsu.edu
+
+703. Yergey, JA, A general approach to calculating isotopic distributions for mass spectrometry. International Journal of Mass Spectrometry and
+Ion Physics, 52 337-49 (1983).
\ No newline at end of file
diff --git a/ReferenceDocs/LinearVelocityDemo_EdBouvier.ppt b/ReferenceDocs/LinearVelocityDemo_EdBouvier.ppt
new file mode 100644
index 0000000..429c5d1
Binary files /dev/null and b/ReferenceDocs/LinearVelocityDemo_EdBouvier.ppt differ
diff --git a/ReferenceDocs/LinearVelocityEqs_mm.ppt b/ReferenceDocs/LinearVelocityEqs_mm.ppt
new file mode 100644
index 0000000..d0d8fdb
Binary files /dev/null and b/ReferenceDocs/LinearVelocityEqs_mm.ppt differ
diff --git a/ReferenceDocs/NTerminalModifications.txt b/ReferenceDocs/NTerminalModifications.txt
new file mode 100644
index 0000000..16bd06b
--- /dev/null
+++ b/ReferenceDocs/NTerminalModifications.txt
@@ -0,0 +1,25 @@
+N-Terminal Modifications
+
+Hydrogen H H 1.0079 1.0078
+Pyroglutamic Acid Pyr C5H6NO2 112.1082 112.0399
+N-formylation HCO HCO 29.0183 29.0027
+N-myristoylation N-myr C14H27O 211.3678 211.2062
+N-acetylation CH3CO C2H3O 43.0452 43.0184
+Amidation NH2 NH2 16.0226 16.0187
+None None None 0.0000 0.0000
+t-Butyl But C4H9 57.1155 57.0704
+Acetamidomethyl Acm C3H6ON 72.0868 72.0449
+t-Butoxymethyl Bum C5H1O 87.1417 87.0810
+Benzyl Bzl C7H7 91.1326 91.0548
+tert-Butyloxycarbonyl tBOC C5H9O2 101.1253 101.0603
+4-Methylbenzyl MeBzl C8H9 105.1595 105.0704
+4-Methoxybenzyl MBzl C8H9O 121.1589 121.0653
+Benzyloxycarbonyl Cbz C8H7O2 135.1424 135.0446
+o-Nitrophenylsulphenyl Nps C6H4NO2S 154.1693 153.9963
+tosyl Tos C7H7O2S 155.1974 155.0167
+2,6 Dichlorobenzyl Cl2Bz C7H5Cl2 160.0221 158.9768
+2,4 Dinitrophenyl Dnp C6H3O4N2 167.1009 167.0093
+2,4,6 Trimethoxybenzyl Tmob C10H12O3 180.2035 180.0786
+Fmoc Fmoc C15H1O2 223.2511 223.0759
+Trityl Trt C19H15 243.3281 243.1174
+2,2,5,7,8-Pentamethylchromane Pmc C14H19O3S 267.3691 267.1055
diff --git a/ReferenceDocs/ParseEmpiricalFormula.xls b/ReferenceDocs/ParseEmpiricalFormula.xls
new file mode 100644
index 0000000..274ba8c
Binary files /dev/null and b/ReferenceDocs/ParseEmpiricalFormula.xls differ
diff --git a/ReferenceDocs/PeptideSequenceModifications.xls b/ReferenceDocs/PeptideSequenceModifications.xls
new file mode 100644
index 0000000..d135aa0
Binary files /dev/null and b/ReferenceDocs/PeptideSequenceModifications.xls differ
diff --git a/ReferenceDocs/SequestPatent.doc b/ReferenceDocs/SequestPatent.doc
new file mode 100644
index 0000000..7199c07
Binary files /dev/null and b/ReferenceDocs/SequestPatent.doc differ
diff --git a/ReferenceDocs/SequestPatent_5538897.pdf b/ReferenceDocs/SequestPatent_5538897.pdf
new file mode 100644
index 0000000..9b4cf34
Binary files /dev/null and b/ReferenceDocs/SequestPatent_5538897.pdf differ
diff --git a/ReferenceDocs/ToDo.txt b/ReferenceDocs/ToDo.txt
new file mode 100644
index 0000000..5a324c8
--- /dev/null
+++ b/ReferenceDocs/ToDo.txt
@@ -0,0 +1,3 @@
+ToDo:
+
+Allow user to edit N and C terminus functional groups
diff --git a/ReferenceDocs/ViscosityOfMeCNSolutions.xls b/ReferenceDocs/ViscosityOfMeCNSolutions.xls
new file mode 100644
index 0000000..67e12db
Binary files /dev/null and b/ReferenceDocs/ViscosityOfMeCNSolutions.xls differ
diff --git a/ReferenceDocs/ViscosityOfMeCNSolutions_ac0112622.pdf b/ReferenceDocs/ViscosityOfMeCNSolutions_ac0112622.pdf
new file mode 100644
index 0000000..f05db18
Binary files /dev/null and b/ReferenceDocs/ViscosityOfMeCNSolutions_ac0112622.pdf differ
diff --git a/ReferenceDocs/equations.pdf b/ReferenceDocs/equations.pdf
new file mode 100644
index 0000000..55a708c
Binary files /dev/null and b/ReferenceDocs/equations.pdf differ
diff --git a/ReferenceDocs/exactmas.htm b/ReferenceDocs/exactmas.htm
new file mode 100644
index 0000000..c68d34b
--- /dev/null
+++ b/ReferenceDocs/exactmas.htm
@@ -0,0 +1,198 @@
+
+
+
+
+
+
+Exact Masses and Isotopic Abundance of Elements - Numeric List
+
+
+
+
+
+
+
+
+
+
+
Exact Masses of the Elements and Isotopic Abundances
+
+
Based on the Carbon 12 Standard
+
+
+
+
+The following data was collected from a compillation of data from
+the CRC Handbook and other references. If any errors or corrections
+are noted please advise us
+and we will make the corrections.
+
+Authors not responsible for errors, omissions or inaccuracy of
+the above data. Please notify SIS of any errors or corrections
+in the above data. E-Mail sis@sisweb.com
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ReferenceDocs/invitetojoinyahoogroup.txt b/ReferenceDocs/invitetojoinyahoogroup.txt
new file mode 100644
index 0000000..f5a5b2f
--- /dev/null
+++ b/ReferenceDocs/invitetojoinyahoogroup.txt
@@ -0,0 +1,58 @@
+Hello,
+
+I wanted to let you know that I have created a mailing list to announce updates/changes to my Molecular Weight Calculator. The mailing list, hosted at Yahoo Groups, is a moderated, low volume list. The mailing list home page is at http://groups.yahoo.com/group/molecular-weight-calculator/ while the home page for my software is now at http://www.alchemistmatt.com/mwtwin.html
+
+The latest version of my software is version 6.06, released November 11, 2001. Note that recent versions now support international languages, including Spanish, Portuguese, German, and Russian. I have also enhanced the mole/mass converter to help with dilution calculations.
+
+Regards,
+
+Matthew Monroe
+
+
+Above message sent to the following people on November 29, 2001 at 5:30 pm
+
+AlmutSM@aol.com
+bondabsr@unige.it Francesco Bondavalli
+bricer@mindspring.com E. R. Brice
+burt.tm@pg.com
+Carl.Braybrook@molsci.csiro.au Carl Braybrook
+crevasse@seanet.com
+cumberland@chem.ucsb.edu scott lee cumberland
+cwu@bruker.com Ching Wu
+dpe@fda.net David Evitts
+dstasko@reedgroup.ucr.edu Dan
+emilyyap@ozamiz.com Emily Mae L. Yap
+fluss@bluewin.ch Stefan Flueler
+garciar@cadvision.com Richard Garcia
+j.i.trujillo@worldnet.att.net John Trujillo
+jqian@nrgn.com Qian, Jean
+jsfjr@erols.com Joe
+Koen.Binnemans@chem.kuleuven.ac.be Binnemans Koen
+Lagarto2@aol.com
+lionel@fki.uu.se Dr. Lionel Vayssieres
+livia.ds@tiscalinet.it Livia Della Seta
+m.lorms@tu-bs.de Michael Lorms
+MACBEE2000@aol.com
+marism@apollo.lv SEAR CON
+martins@scripps.edu Martin Sonderegger
+mehrotra@ilsc.com Arun Mehrotra
+michealj@bellsouth.net MICHAEL KOGAN
+Michel_De_Poortere@albemarle.com
+nasaman@revealed.net Bruce Bromley
+nathan_yates@merck.com Yates, Nathan A.
+ntegti@uol.com.br NteGti
+OPK@POLYMIR.VITEBSK.BY Aleksandr V. Dubrowskij
+paul@chela.chemie.uni-bielefeld.de Paul Koegerler
+peache00@hotmail.com D L
+pefeco@redestb.es Pedro Fernández Cortés
+pilloton@casaccia.enea.it
+ponshmoe@bellsouth.net Ponciano Moe
+RHBallard.ClearLake@Celanese.com Ballard, Robert H.
+Roderick.Davis@RP-RORER.COM Davis, Roderick S.
+senko@Finnigan.com Michael W. Senko
+stom@everest.bim.anl.gov Andrey Stomakhin
+tlsaylor@eastman.com Lloyd-Saylor, Teresa
+ubchsv@burgarden.educ.goteborg.se Helena Svedhem
+wnichols@redsuspenders.com Bill Nichols
+yah@mailru.com Yahkind M.I.
+keith_fadgen@waters.com Keith Fadgen
diff --git a/ReferenceDocs/iupac.txt b/ReferenceDocs/iupac.txt
new file mode 100644
index 0000000..f5a213e
--- /dev/null
+++ b/ReferenceDocs/iupac.txt
@@ -0,0 +1,111 @@
+ 1 H Hydrogen 1.00794(7) 1, 2, 3
+ 2 He Helium 4.002602(2) 1, 2
+ 3 Li Lithium 6.941(2) 1, 2, 3, 4
+ 4 Be Beryllium 9.012182(3)
+ 5 B Boron 10.811(7) 1, 2, 3
+ 6 C Carbon 12.0107(8) 1, 2
+ 7 N Nitrogen 14.00674(7) 1, 2
+ 8 O Oxygen 15.9994(3) 1, 2
+ 9 F Fluorine 18.9984032(5)
+ 10 Ne Neon 20.1797(6) 1, 3
+ 11 Na Sodium 22.989770(2)
+ 12 Mg Magnesium 24.3050(6)
+ 13 Al Aluminium 26.981538(2)
+ 14 Si Silicon 28.0855(3) 2
+ 15 P Phosphorus 30.973761(2)
+ 16 S Sulfur 32.066(6) 1, 2
+ 17 Cl Chlorine 35.4527(9) 3
+ 18 Ar Argon 39.948(1) 1, 2
+ 19 K Potassium 39.0983(1) 1
+ 20 Ca Calcium 40.078(4) 1
+ 21 Sc Scandium 44.955910(8)
+ 22 Ti Titanium 47.867(1)
+ 23 V Vanadium 50.9415(1)
+ 24 Cr Chromium 51.9961(6)
+ 25 Mn Manganese 54.938049(9)
+ 26 Fe Iron 55.845(2)
+ 27 Co Cobalt 58.933200(9)
+ 28 Ni Nickel 58.6934(2)
+ 29 Cu Copper 63.546(3) 2
+ 30 Zn Zinc 65.39(2)
+ 31 Ga Gallium 69.723(1)
+ 32 Ge Germanium 72.61(2)
+ 33 As Arsenic 74.92160(2)
+ 34 Se Selenium 78.96(3)
+ 35 Br Bromine 79.904(1)
+ 36 Kr Krypton 83.80(1) 1, 3
+ 37 Rb Rubidium 85.4678(3) 1
+ 38 Sr Strontium 87.62(1) 1, 2
+ 39 Y Yttrium 88.90585(2)
+ 40 Zr Zirconium 91.224(2) 1
+ 41 Nb Niobium 92.90638(2)
+ 42 Mo Molybdenum 95.94(1) 1
+ 43 Tc Technetium [98] 5
+ 44 Ru Ruthenium 101.07(2) 1
+ 45 Rh Rhodium 102.90550(2)
+ 46 Pd Palladium 106.42(1) 1
+ 47 Ag Silver 107.8682(2) 1
+ 48 Cd Cadmium 112.411(8) 1
+ 49 In Indium 114.818(3)
+ 50 Sn Tin 118.710(7) 1
+ 51 Sb Antimony 121.760(1) 1
+ 52 Te Tellurium 127.60(3) 1
+ 53 I Iodine 126.90447(3)
+ 54 Xe Xenon 131.29(2) 1, 3
+ 55 Cs Caesium 132.90545(2)
+ 56 Ba Barium 137.327(7)
+ 57 La Lanthanum 138.9055(2) 1
+ 58 Ce Cerium 140.116(1) 1
+ 59 Pr Praseodymium 140.90765(2)
+ 60 Nd Neodymium 144.24(3) 1
+ 61 Pm Promethium [145] 5
+ 62 Sm Samarium 150.36(3) 1
+ 63 Eu Europium 151.964(1) 1
+ 64 Gd Gadolinium 157.25(3) 1
+ 65 Tb Terbium 158.92534(2)
+ 66 Dy Dysprosium 162.50(3) 1
+ 67 Ho Holmium 164.93032(2)
+ 68 Er Erbium 167.26(3) 1
+ 69 Tm Thulium 168.93421(2)
+ 70 Yb Ytterbium 173.04(3) 1
+ 71 Lu Lutetium 174.967(1) 1
+ 72 Hf Hafnium 178.49(2)
+ 73 Ta Tantalum 180.9479(1)
+ 74 W Tungsten 183.84(1)
+ 75 Re Rhenium 186.207(1)
+ 76 Os Osmium 190.23(3) 1
+ 77 Ir Iridium 192.217(3)
+ 78 Pt Platinum 195.078(2)
+ 79 Au Gold 196.96655(2)
+ 80 Hg Mercury 200.59(2)
+ 81 Tl Thallium 204.3833(2)
+ 82 Pb Lead 207.2(1) 1, 2
+ 83 Bi Bismuth 208.98038(2)
+ 84 Po Polonium [209] 5
+ 85 At Astatine [210] 5
+ 86 Rn Radon [222] 5
+ 87 Fr Francium [223] 5
+ 88 Ra Radium [226] 5
+ 89 Ac Actinium [227] 5
+ 90 Th Thorium 232.0381(1) 1, 5
+ 91 Pa Protactinium 231.03588(2) 5
+ 92 U Uranium 238.0289(1) 1, 3, 5
+ 93 Np Neptunium [237] 5
+ 94 Pu Plutonium [244] 5
+ 95 Am Americium [243] 5
+ 96 Cm Curium [247] 5
+ 97 Bk Berkelium [247] 5
+ 98 Cf Californium [251] 5
+ 99 Es Einsteinium [252] 5
+ 100 Fm Fermium [257] 5
+ 101 Md Mendelevium [258] 5
+ 102 No Nobelium [259] 5
+ 103 Lr Lawrencium [262] 5
+ 104 Rf Rutherfordium [261] 5, 6
+ 105 Db Dubnium [262] 5, 6
+ 106 Sg Seaborgium [263] 5, 6
+ 107 Bh Bohrium [262] 5, 6
+ 108 Hs Hassium [265] 5, 6
+ 109 Mt Meitnerium [266] 5, 6
+ 110 Uun Ununnilium [269] 5, 6
+ 111 Uuu Unununium [272] 5, 6
diff --git a/ReferenceDocs/programdescription.txt b/ReferenceDocs/programdescription.txt
new file mode 100644
index 0000000..bc11412
--- /dev/null
+++ b/ReferenceDocs/programdescription.txt
@@ -0,0 +1,10 @@
+ Short description:
+Molecular Weight Calculator lets you calculate the molecular weight and percent composition of up to 20 compounds simultaneously. Features include a Mole/Mass Converter, a Formula Finder, Amino Acid Notation converter, and the ability to recognize isotopes and user-defined abbreviations. The calculator also includes abbreviation expansion, empirical formula conversion, and a built-in mathematical calculator. All formulas and settings are saved between uses. Now includes support for International languages (Spanish, German, Portuguese, Russian, and English).
+
+
+ Longer description:
+The Molecular Weight Calculator for Windows 9x/NT/00/XP v6.02 will calculate the molecular weight and percent composition of up to 20 compounds simultaneously, while properly displaying numbers as subscripts and superscripts where needed. It can recognize up to 150 user-defined abbreviations, all isotopes, and has average mass, isotopic mass, and nominal integer mass weight modes for elements. The program can handle embedded parentheses, multiple hydrates, and has the unique ability to weight certain parts of a compound. An advanced feature of the program is its ability to solve for 'x' in a compound based on user-specifed percent composition data, for example C6H6-[xH2O].
+
+The program also includes a Mole/Mass converter, a Formula Finder capable of finding all compounds with a specific molecular weight or mass to charge ratio within a given tolerance, a Capillary Flow and Mass Rate Calculator, and an Amino Acid Notation Converter (1 to 3 and 3 to 1 letter). Other features include standard deviations of results, automatic case conversion, recognition of amino acids, abbreviation expansion, conversion to an empirical formula, and a built-in mathematical calculator.
+
+The program now includes support for International languages, currently including files for German, Spanish, Portuguese, Russian, and English. The program includes extensive error checking to verify that formulas entered are valid, and optionally displays caution statements for formulas with unusual element combinations. A full Windows help file is included plus context-sensitive tool tips can be displayed in the program. Lastly, all features and formulas can be automatically or manually saved during program operation then reloaded upon program start.
\ No newline at end of file
diff --git a/ReferenceDocs/simtel_submission_directions.txt b/ReferenceDocs/simtel_submission_directions.txt
new file mode 100644
index 0000000..9c5db16
--- /dev/null
+++ b/ReferenceDocs/simtel_submission_directions.txt
@@ -0,0 +1,167 @@
+Your Username is: [alchemi.yahoo.co]
+Your Password is: [c21hay.iml]
+
+Thank you for contributing to the Simtel.Net Archive.
+
+The Simtel.Net collections are periodically published on CD-ROM.
+If you do not wish to have your package distributed on CD-ROM
+please do not upload it.
+
+You can review our Upload Policy at
+ http://www.simtel.net/uppolicy.html
+
+Please review this policy and keep all your uploads within the scope of the Simtel.Net collection. There are changes from the old Simtel.Net
+policies. ("same name" replacements are now permissible. You may
+include VB runtimes. And more.)
+
+Now that you have this upload account with Simtel.Net, you do not need
+to send any more upload requests for future uploads. Just upload
+directly to us.
+
+
+UPLOADING:
+
+You can upload your files to
+ ftp://uploads.simtel.net.
+
+Some browsers expect you to add your username as part of the access:
+ ftp://user.name@uploads.simtel.net
+and then prompt you for your password once there.
+
+Some (like Netscape) require you to add the path to our incoming
+area:
+ ftp://user.name@uploads.simtel.net/submissions/incoming
+
+Most FTP programs, including WSFTP will require you to enter the host as uploads.simtel.net
+
+If you have difficulties, go to the Uploaders Forum for answers and help. (See the end of this message.)
+
+Once you have logged in (using the above username and password), you
+will be automatically moved to the /submissions/incoming directory.
+Upload BOTH your file and its accompanying PAD .xml (see below) file
+there. Do not create any other folders, do not upload anything else. You can see everyone else's uploads, but you cannot "affect" them in
+any way, only your own. And please, lowercase short filenames only. Anything else WILL delay processing.
+
+This is NOT your web page, NOT your directory. This is a shared area:
+please treat it with respect.
+
+We do NOT accept emailed files under ANY conditions.
+
+
+PADGEN AND THE PAD .xml FILE:
+
+We require ALL SUBMISSIONS to use PADGEN. You can get this program for
+free from http://www.asp-shareware.org/pad/ You will also find details
+on its use. You do not have to join the ASP to get or use the PADGEN
+program.
+
+You will also need to get the Simtel PAD extension, which can be found at this link:
+
+ http://www.simtel.net/simtelxml.zip
+
+Unzip the simtel.htm file and put it in the Padgen directory. This
+file will create a "simtel" tab in the Padgen program that will allow you
+to enter specific information for Simtel file categories. Read the instructions. Then select the lowest platform (MS-DOS, Win3, WinXX) in
+which your program will function, and the most appropriate file category
+for that platform. Complete ONE platform and category only.
+
+Details on using extensions (and other extensions that are available for other shareware sites) can be found at
+
+ http://www.asp-shareware.org/pad/padextensions.asp
+
+When preparing your PAD .xml file, be sure to fill the Author name and Author email fields. Insure your "official" email address, the one you used to submit your submission application to us, the email
+address we're sending this very message to, is in at least ONE of the available PAD .xml email fields. Insure you fill in the short description and at least one long description. Insure you put the SAME filename you're uploading into one of the Filename_* fields. Yes, case matters. Yes, the file extension matters.
+
+Not every field in the entire PAD .xml file need be completed. See our Uploaders Forum for detailed requirements.
+
+Be sure to use the Filename_Previous field if you're replacing one of your files already at Simtel.Net. That will insure file links are reused, old files are removed, and download counts are carried forward.
+
+If you are an Agent and plan to upload for other publishers who do not have upload accounts at Simtel.Net, contact us for special instructions on procedures, correct use of the PAD .xml file, etc.
+
+
+FILENAMES:
+
+Simtel.Net accepts short 8.3 "filename.typ" filenames only. We accept only ".zip" or ".exe" file extensions (and of course the companion ".xml" file type). Anything else will be automatically rejected. No .jar, .htm, .arj, .gz, .sqz, .uue.
+
+Insure at least ONE of the PAD .xml Filename_* fields contains the exact
+filename that you will be uploading to us. Use lowercase only for all
+filenames: any uppercase in filenames will delay your upload's processing. Filenames in the PAD .xml file must include the file
+extension. "wombat" is NOT the filename of the "wombat.zip" file you
+uploaded. "wombat.exe" is NOT the same as "wombat.zip". (This happens
+ALL the time.)
+
+You will need to upload BOTH your .exe/.zip and the companion PAD .xml
+file to our incoming directory. Both files must have the same name
+(i.e. filename.zip [.exe] and filename.xml). We do prefer .zip files, and suggest you include the PAD .xml inside the .zip file so the end user and other distribution sites can get your PAD .xml file. (No, we will NOT go into your .zip to take out the .xml file for our use. Upload it separately.) (No, we will NOT "go out and get" the file to which your uploaded orphan .xml file points. Upload it.)
+
+Understand that the accompanying .xml file is MANDATORY. Our system can not process your file, add it to the file system, and catalog it without the information in that .xml file. You MUST download and include the Simtel.Net PAD extension provided by the simtel.htm file.
+
+You MUST include your upload account's email address in one of the .xml form's email fields or we cannot accept your upload. That email address
+will become part of the file description, will go out in our New Upload Digests, etc. We regret this may make you vulnerable to spammers, but we simply MUST have that email address. We will remove the files and user account of any uploader who fails to maintain that email address. Contact us if your email address changes, and we will direct you on how
+to create a new upload account.
+
+
+UPLOAD PROCESSING:
+
+If you see your files disappear from our incoming area, that means they're being processed (that's good). If you see them renamed (with something like ".BAD" or ".NO" or ".SIM" or ".CAT" or ".PUB"), that's not good. Please go to our Uploaders Forum for details (see
+the end of this message). If you see this problem, you may upload
+a corrected .xml (and/or program file) with the problem(s) fixed.
+Otherwise you'll eventually get an email message describing the
+problem .. and directing you to re-upload everything since we've
+removed all the problem files.
+
+It will take up to 3 days for your file to be processed, and up to another 36 hours for the file to become "visible" on our web site (and available for downloads from the mirror sites). If there is a delay, do NOT email us. It will not make anything work faster.
+Simtel.Net now has an eXpress subscription service, to provide
+priority posting and distribution (at a cost). If interested, email webmaster@simtel.net for details. Or watch our web page for details.
+
+
+FILE LINKS:
+
+When your upload is processed, our system will send you email with two links to your program. The first link will be the "Product Description"
+page which includes the description of your submitted program. The second link will be the "Download" page for your submitted file which
+lists all of the download locations ("mirror sites") for your file.
+
+NOTE: Simtel.Net does NOT allow the linking directly to files in the archive system, to include all of the mirror sites. You and any other
+web site are ONLY authorized to link to one of the URLs provided after
+your file has been processed. Violation of this policy can result in
+all of your files being removed from the system and your upload account
+being permanently disabled.
+
+We may rename your files for more effective system operation or to avoid filename conflicts. Do NOT depend on filenames remaining the same as
+when you uploaded them.
+
+If you link to the HTML page, you can be assured that the download link
+will always work and allow your user to choose the download location
+from around the world that is best for them.
+
+Let us know if you have any questions or comments. Please send it to
+webmaster@simtel.net with the subject of Upload Procedure. And by all means use our web page's Users or Uploaders Forum for any comments or
+discussion.
+
+
+THE SIMTEL.NET FORUM AREA:
+
+We strongly urge you to monitor the Forum area at our home page at
+
+ http://www.simtel.net/wwwthreads/wwwthreads.pl
+
+There is even a special Uploaders Discussion and Info area (the "Uploaders Forum") just for uploaders. There you'll find much
+background information on how the entire system works, common problem
+and error conditions (and their solutions), and more.
+
+As an additional note:
+
+Looking for Web Hosting or eCommerce solutions, or software promotion opportunities? Be sure to check out our Partners page at
+
+ http://www.simtel.net/partners.html
+
+to find out who we use and recommend.
+
+
+Thanks.
+
+Simtel.Net Management
+--
+
+
+This email was sent to: alchemistmatt@yahoo.com
diff --git a/ReferenceDocs/submit.txt b/ReferenceDocs/submit.txt
new file mode 100644
index 0000000..79297a9
--- /dev/null
+++ b/ReferenceDocs/submit.txt
@@ -0,0 +1,149 @@
+August 19, 2002 updates:
+1) Visited Download.cnet.com (http://download.com.com/3000-2054-10012449.html) version listed was 6.12 (April 1, 2002). Logged into upload.cnet.com (http://upload.cnet.com/uploads/devcorner/0-5904195.html) using alchemistmatt@yahoo.com and the usual password.
+
+Updated program to version 6.19, providing links to (Note that old link was still www.unc.edu even though inputted jjorg.chem.unc.edu on March 9, 2002):
+http://jjorg.chem.unc.edu/personal/monroe/download/mwt6_19s.zip
+http://www.geocities.com/alchemistmatt/download/mwt6_19s.zip
+
+2) Visited Simtel.net (http://www.simtel.net/pub/pd/58238.html) version listed was 6.12
+Updated the PAD .xml file (specifying previous filename as mwt6_12s.zip and the new one as mwt6_19s.zip), renamed pad_file.xml to mwt6_19s.xml, and added to the mwt6_19s.zip (as requested by Simtel). Ftp'd to ftp://uploads.simtel.net (login using alchemi.yahoo.co with password c21hay.iml) and uploaded the mwt6_19s.zip and mwt6_19s.xml files.
+
+NEED TO DO
+3) Visit Nonags.com at http://www.nonags.com/sub/index1.html or at http://www.nonags.com/softwform/submit.html
+Matthew Monroe
+matt@alchemistmatt.com
+Molecular Weight Calculator
+Home page url: http://www.alchemistmatt.com/
+File url: http://www.alchemistmatt.com/download/mwt6_19s.zip
+Size: 2.13 Mb
+Version: 6.19
+Category: Calculators - Freeware
+Runs on: All Windows
+
+4) Visited Winsite.com (http://uploads.winsite.com/auth/) Login using alchemistmatt@yahoo.com and usual password. Chose REPLACE existing program to update, specifying version 6.19 and Win 9x/NT/2000/XP, plus language support for German, Spanish, Portuguese, and Russian. Also specified program information URL as http://jjorg.chem.unc.edu/personal/monroe/mwtwin.html
+Note: InfoCard URL is http://www.winsite.com/bin/Info?500000022559
+
+
+March 11, 2002 updates:
+Replaced version 6.11 at www.alchemistmatt.com (jjorg.chem.unc.edu), www.unc.edu, and www.geocities.com with the contents of version 6.12, so only necessary to resubmit to Simtel; however, also updated at Winsite.com since very easy.
+
+Logged into Simtel using directions below -- ftp'd mwt6_12s.zip and mwt6_12s.xml
+
+Logged into Winsite.com using directions below -- changed version to 6.12 and uploaded file using web address http://jjorg.chem.unc.edu/personal/monroe/download/mwt6_12s.zip
+
+
+March 9, 2002 updates:
+
+1) Visited Download.cnet.com (http://download.cnet.com/downloads/0-1635596-100-7505754.html) version listed was 6.04 (October 12, 2001). Logged into upload.cnet.com (http://upload.cnet.com/uploads/devcorner/0-5904195.html) using alchemistmatt@yahoo.com and the usual password.
+
+Updated program to version 6.11, providing links to http://jjorg.chem.unc.edu/personal/monroe/download/mwt6_11s.zip and http://www.geocities.com/tandm_wy/download/mwt6_11s.zip, and changing program home page to http://www.alchemistmatt.com/mwtwin.html
+ Will take 6 to 8 weeks for listing to be updated
+
+1.2) ZDNet upload submissions also point to Download.Cnet.Com
+
+2) Visited Simtel.net (http://www.simtel.net/pub/pd/56419.shtml) version listed was 6.04
+Updated the PAD .xml file (specifying previous filename as mwt6_04s.zip and the new one as mwt6_11s.zip), renamed pad_file.xml to mwt6_11s.xml, and added to the mwt6_11s.zip (as requested by Simtel). Ftp'd to ftp://uploads.simtel.net (login using alchemi.yahoo.co with password c21hay.iml) and uploaded the mwt6_11s.zip and mwt6_11s.xml files.
+
+3) Visit Nonags.com at http://www.nonags.com/sub/index1.html
+Home page url: http://www.alchemistmatt.com/
+File url: http://www.alchemistmatt.com/download/mwt6_11s.zip
+Size: 2.06 Mb
+Version: 6.11
+Category: Calculators - Freeware
+Runs on: All Windows
+
+4) Visited Winsite.com (http://uploads.winsite.com/auth/) Login using alchemistmatt@yahoo.com and usual password. Chose REPLACE existing program to update, specifying version 6.11 and Win 9x/NT/2000/XP, plus language support for German, Spanish, Portuguese, and Russian. Also specified program information URL as http://jjorg.chem.unc.edu/personal/monroe/mwtwin.html
+
+5) Visited Tucows at http://author.tucows.com/ (login using alchemistmatt)
+ Listed version 6.02 as being rejected. Chose add new program (not update v6.02).
+ Used software url: http://jjorg.chem.unc.edu/personal/monroe/download/mwt6_11s.zip
+
+
+October 2001 updates:
+File link: http://www.alchemistmatt.com/download/mwt6_02s.zip
+
+1) Visited Download.cnet.com (was Download.com, Softseek.com, Winfiles.com) and registered (alchemistmatt@yahoo.com & www.alchemistmatt.com). Submission information instructed to log in at:
+ http://upload.cnet.com/uploads/devcorner/0-5904195.html
+Category: Home and Education: Science
+
+Note: 11/2/01: I used the form at http://upload.cnet.com/uploads/submissions/0-5904195.html?tag=txt to submit an update for my software. May or may not work since I then registered soon after.
+
+
+1.2) ZDNet upload submissions also point to Download.Cnet.Com
+
+
+2) Visited Simtel.net at http://www.simtel.net/upload.php to request upload instructions. Received instructions on 10/4/2001 specifying the following
+ Ftp to ftp://uploads.simtel.net
+ Login using alchemi.yahoo.co
+ Pssword is c21hay.iml
+Upload the program file and a PAD .xml program (generated using PadGen)
+
+3) Visit Nonags.com at http://www.nonags.com/sub/index1.html
+File link: http://www.alchemistmatt.com/download/mwt6_02s.zip
+Category: Calculators - Freeware
+
+4) Visited Winsite.com and created an account for alchemistmatt@yahoo.com
+Submitted update information using http://uploads.winsite.com/auth/ (choosing REPLACE existing program)
+
+
+5) Visited Tucows at http://author.tucows.com/ and created an account (alchemistmatt)
+ Submitted application for review. Rejected a few days later. Need to resubmit a future version.
+
+6) Send an annoucement to my Yahoo! Groups mailing list (http://groups.yahoo.com/group/mwtwin)
+
+===========================
+Old Updates:
+
+Submit program to:
+
+ftp://ftp.osc.edu/pub/chemistry/software/MS-WINDOWS95/
+ Upload mwt4_4.exe to the /incoming directory with
+ the accompanying mwt4_4.txt file.
+ Then e-mail ftphelp@osc.edu telling them to post file in
+ correct directory.
+6/18/98: v4.4 submitted
+7/20/98: v4.5 submitted
+
+Submit program to www.simtel.net by uploading to incoming.simtel.net
+ then e-mailing archive@Simtel.Net
+ with a short description of the files you wish to submit and
+ the method you wish to use for uploading (see direc.txt)
+6/18/98: v4.4 submitted
+
+Go to Download.com and submit UNC address and simtel address
+6/15/98: v4.4 information submitted and updated
+
+Go to Upload.com to update the ZD Net information by submitting mwt4_4.zip
+Username: Matthew Monroe, password merlin
+6/18/98: v4.4 submitted
+
+Submit mwt4_4s.exe program to www.winsite.com by using Netscape with the page
+ (submit as filename mwt4_4.exe replaces file mwt4_31.exe):
+ http://uploads.winsite.com/wus/uploadservice.pcgi
+6/18/98: Can't Connect to site
+
+Submit mw4_4s.exe program to softseek.com
+ http://softseek.com/Education_and_Science/Science_and_Engineering/Review_13402_index.html
+ Choose submit update button at bottom, left corner.
+6/15/98: v4.4 submitted and updated
+
+Submit to new place shown in e-mail
+
+
+Download required VB 5 files from:
+
+http://www.simtel.net/simtel.net/win95/dll.html
+ under vb5run.zip
+ (http://www.simtel.net/pub/simtelnet/win95/dll/vb5run.zip)
+
+http://www.sharepaper.com/apps/reviews/q_ufad.html
+ under Visual Basic 5 Runtimes
+ (http://www.sharepaper.com/cgi-local/d.cgi?http://filez.com/cgi/filez.cgi?query=vb5run.zip&doit=Search)
+
+http://www.softseek.com/Utilities/VBRUN_Files/
+ under VB5 Runtime Files
+ (http://www.softseek.com/Utilities/VBRUN_Files/Review_11110_index.html)
+
+http://www.apexsc.com/vb/davem/vbttdl.html
+ under VB 5 Runtime Files
+ (http://www.apexsc.com/vb/ftp/vbtt/vb5run.exe)
diff --git a/ReferenceDocs/weights.wpd b/ReferenceDocs/weights.wpd
new file mode 100644
index 0000000..33bdf2d
Binary files /dev/null and b/ReferenceDocs/weights.wpd differ
diff --git a/RevisionHistory.txt b/RevisionHistory.txt
new file mode 100644
index 0000000..fee12db
--- /dev/null
+++ b/RevisionHistory.txt
@@ -0,0 +1,501 @@
+Revision 1 - DOS version Completed August 6, 1995 (QuickBasic for DOS)
+ Contains the following basic features:
+ - formula weight calculation
+ - percent composition calculation
+ - can handle parentheses, up to 2 sets of embedding
+ - can handle hydrates and other additional compounds
+ - can handle numbers up to 2 digits long
+ - two types of case conversion
+ - help screen
+
+Revision 2.0 - August 8, 1995
+ - Can now handle numbers up to 6 digits long
+ - Can now handle up to 4 sets of embedded parentheses
+ - Now includes ability to handle brackets and partial weights
+ - Now has three types of case conversion
+ - Added expanded help screens
+
+Revision 2.1 - August 9, 1995
+ - Can now show display of current time
+
+Revision 2.2 - August 10, 1995
+ - Added a simple math calculator
+
+Revision 2.21 - August 17, 1995
+ - Contains minor bug fixes.
+
+Revision 2.3 - September 2, 1995
+ - added command line switches to control internal settings
+ - Added standard deviation option
+ - Added recognition Bu for butyl group
+
+Revision 2.4 - December 1, 1995
+ - Added a Percent solver routine.
+ - Combined F11 and F12 std. deviation options into just F12
+ - Contains Screen update bug fixes.
+
+Revision 2.5 - December 7, 1995
+ - Improved speed of the % solver algorithm.
+ - Added recognition of Urea, Ox, Py, En, Tpp, Otf.
+
+Revision 2.55 - December 17, 1995
+ - Added error trapping routines.
+ - Improved handling of exponentially large and small numbers.
+ - Added warning statements for possibly ambiguous abbreviations such as Bpy and Py.
+
+Revision 2.6 - January 16, 1996
+ - Recognizes Amino Acid abbreviations.
+ - Recognizes Deuterium, D abbreviation.
+ - Percent Solver values can now be set for all elements of a formula.
+ - Displays differences between actual and theoretical values at the conclusion of the percent solver routine.
+ - Added CTRL-P option to print results.
+ - Added more error messages/explanations for incorrect user entries.
+
+
+Revision 2.7 - March 1, 1996
+ - Now able to handle isotopes; use the caret (^) symbol.
+ - Now able to calculate powers of numbers in the calculator.
+ - Added more error messages/explanations for incorrect entries.
+ - Included a moderately accurate error handler to check the validity of entered isotopic masses.
+ - Added numerous "caution" statements for possibly erroneous entries: eg. Co vs. CO and Sc vs. SC
+ (This feature may be toggled on and off with CTRL-C)
+ - Improved speed of the % solver algorithm; watch it blaze!
+ - Removed CTRL-P option -- use PRINT-SCREEN or SHIFT-PRINT-SCREEN
+ - Changed the order and layout of the in-program help screens.
+ - Fixed typos in help screens and added two more help screens.
+
+
+Revision 2.8 - May 1, 1996
+ - Now able to handle user-defined abbreviations listed in the MWT_ABBR.DAT file.
+ - Added error checking to prevent duplicate abbreviations or abbreviations duplicating elements.
+ - Added automatic re-creation of the abbreviation file if it is deleted/missing.
+ - Added ability to run without abbreviations if program is run on a write-protected drive.
+ - Added command-line switch (/X) to stop any attempts of reading or creating an abbreviation file (useful on a write-protected drive, like a network drive).
+
+
+Revision 2.85 - September 1, 1996
+ - Now recognizes the MWTPATH environment variable which specifies the location of the MWT_ABBR.DAT file
+
+Revision 2.87 - January 1, 1997
+ - Updated the help file to reflect the latest Windows version of the program.
+
+Revision 3.0 - Windows 3.x version Completed June 10, 1996 (Visual Basic 3.0)
+ - New Windows interface.
+ - Now able to modify elemental values stored in the MWT_ELEM.DAT file.
+ - Added editing and saving of Abbreviations and Elemental values during program operation.
+ - Added ability to save current options as defaults.
+ - Added ability to Copy and Paste information to/from other Windows programs.
+ - Formula length is now unlimited -- formulas can even contain all 103 elements.
+ - Added ability to print results.
+
+
+Revision 3.1 - June 28, 1996
+ - Added ability to change the font used to display formulas and calculated results.
+ - Added Mole/Mass Converter
+ - Added Formula Finder
+ - Added full hypertext help
+
+
+Revision 3.2 - January 1, 1997
+ - Now allows use of abbreviations as custom elements in formula finder.
+ - For Percent Solver, added display of differences between target percentages and obtained percentages.
+ - Changed comment delimiter to be a semicolon in the MWTWIN.INI file and the .DAT files.
+ - Added detection of a mouse click to stop the percent solver and formula finder.
+ - Updated help file with MWT Dos version information.
+ - Corrected bug in display of standard deviation values to display the correct number of decimal places.
+ - Improved editing of abbreviations and elemental values.
+ - Improved formula finder interface.
+
+
+Revision 4.0 - Windows 95 version Completed August 25, 1997 (Visual Basic 5.0)
+ - 32 bit Windows 95 code
+ - Now allows user to turn off confirmation of exiting the program.
+ - Added possibility of using exact isotopic weights, in addition to average elemental weights. Useful for mass spectrometry.
+ - Added context sensitive tool tips to many of the program’s controls and added a setting in the help menu to turn them on or off (the settings can be saved in the MWTWIN.INI file)
+ - Redesigned program help to Windows 95 standards.
+ - Improved dialog box displayed when changing items in grids to include OK, Cancel, and Reset buttons.
+ - Fixed bug that had smart case mode and exact case mode switched around in the Calculate function.
+ - Changed all forms and controls to the standard VB 5.0 3-D style.
+ - Changed program icon and made the edges transparent.
+ - Updated help file with MWT Dos version information.
+ - Updated my E-mail and WWW addresses to UNC.
+
+
+Revision 4.1 - September 2, 1997
+ - Added feature to expand abbreviations to their elemental equivalents.
+ - Fixed bug that wrongly calculated weights and uncertainties for weighting of compounds when abbreviations were involved (i.e. use of brackets, eg. [.1Bpy]).
+ - Fixed bug that did not take abbreviations or isotopes into account when hydrates (dashes) were used (eg. Fe-3Bpy or Fe-6^13CH3)
+ - Enabled error handlers to catch overflow values in various procedures.
+
+
+Revision 4.2 - September 7, 1997
+ - Added feature to convert formulas into their empirical formulas, displaying C first, then H, then the remaining elements alphabetically.
+ - Made the Expand Abbreviations and Convert to Empirical Formula commands instantaneous if exit program confirmation is turned off in Exit Program Options under the Options menu.
+
+
+Revision 4.3 - March 10, 1998
+ - Added feature to allow isotopes to contain decimal values, for example: ^13.02C
+ - Added an indicator of the percent of calculations completed in the formula finder.
+ - Added back in the mathematical expression calculator that was previously present in the MWT for Dos version (see above).
+ - Fixed bug that would not allow single letter elements to be entered in the custom elements boxes of the formula finder routine.
+ - Modified error messages in the formula finder routine to be more clear.
+
+
+Revision 4.31 - March 22, 1998
+ - Fixed error with re-creation of the mwt_elem.dat file if it was deleted from the current directory.
+ - Made minor updates to average and isotopic mass values for elements in accordance with the 1993 IUPAC standards.
+ - Minor changes to help file.
+
+
+
+Revision 4.4 - June 15, 1998
+ - Added parts per million (ppm) mode to formula finder weight tolerance box.
+ - Added tooltip for the copy button in the formula finder.
+ - Added Smart Hydrogen atom feature to the formula finder, limiting the number of hydrogens in found compounds to a realistic number (allows CH5 but not CH6 or CH25, allows NH4 but not NH5, allows H3O but not H4O).
+ - Added option to convert found formulas in formula finder to empirical formulas and chemically alphabetize the results, giving a more logical ordering of found formulas (but slowing find process); sort can be stopped by any keypress or mouse click.
+ - Added option to save current values and formulas so they are automatically loaded the next time the program is started. The values can also be autosaved on exit of the program.
+ - Made format of the difference in mass result (dm=) in formula finder dependent on the standard deviation mode: if "Short" or "Decimal" then dm is displayed in standard notation (0.00314); if "Scientific" then dm is displayed in scientific notation; if "Off" then dm is not displayed.
+ - Modified the tab order of objects in the various windows to be more logical.
+ - Fixed copy commands to insert a new line character properly and to insert tabs instead of spaces between columns.
+ - Fixed a major bug with the /X command line feature that did not load elemental information (symbols and weights) upon startup, thus making the program useless. Amazingly no one reported this to me, so I can only assume no one uses this feature.
+ - Removed all command line switches except /X and /? since the AutoSave and AutoLoad features of the options, formulas, and values eliminates their usefulness.
+ - Updated the MWT_ELEM.DAT and program elements defaults to include the average atomic weights and uncertainties specified by the 1997 IUPAC standards.
+ - Changed the "Possibly Incorrect Uncertainty" caution message (for elemental uncertainties) to display only if uncertainties are different from those built into the program code by 10 times instead of by just 20%
+ - Changed the "Possibly Incorrect Elemental Weight" caution message to display only if different from those built into the program code by 20% instead of just 10%.
+ - Fixed status line from displaying a yellow colored "Ready" after editing elements or abbreviations when a caution statement about an abbreviation in one of the formulas was displayed and replaced.
+ - Numerous updates to Mwtwin.Hlp file
+ - Fixed Edit Elements table and program internal code to handle molecular weights with 16 digit precision rather than just 8.
+ - Made all displayed value formats follow the Standard Deviation Mode in that they are displayed in standard notation, unless Scientific mode is chosen, in which case they are shown in exponential notation. This applies to dm results in the Formula Finder, values in the Mole/Mass Converter, results in the Calculator, and percent solver results.
+
+
+
+Revision 4.5 - July 19, 1998
+ - Added ability of abbreviations to contain isotope references. For example, ^2.014H is used to add Deuterium to the abbreviations list, signifying Hydrogen weighing exactly 2.014 Daltons. Note: the uncertainties for isotopes used in abbreviations will be equivalent to those of the elements used in the abbreviation; for example .00007 for Hydrogen, even if ^2.014H is given as the abbreviation.
+ - Added caution statement for TI being tritium-iodine versus Ti being titanium (although tritium is not included in the abbreviations list, users may add it as ^3.01605H).
+ - Added creation of backup files for MWT_ABBR.DAT and MWT_ELEM.DAT each time the files are changed, saving the old version as MWT_ABBR.BAK and MWT_ELEM.DAT
+ - Added display of percent completed information when sorting results in the Formula Finder.
+ - Changed default deuterium abbreviation to be ^2.014H (rather than simply H2).
+ - Improved speed of sorting algorithm in Formula Finder (now using a Shell sort rather than a recursive QuickSort, which generates too much overhead for large data sets due to the recursion).
+ - Changed code in the Standard Deviation Display subroutine to better handle very large numbers without giving an overflow error.
+ - Added Geocities.Com web address and e-mail address throughout help file and program.
+
+
+Revision 4.6 - January 23, 1999
+ - Added option of entering decimal elemental amounts as X1.5 in addition to [1.5X]. For example, Fe1.5O2.25 instead of [1.5Fe][2.25O]
+ - Added option of entering decimal numbers after dashes. For example C6H6-.5H2O instead of C6H6-[.5H2O]
+ - Added functionality to parse a text file containing formulas and create an output file with the molecular weight of each formula.
+ - Added /F:filename switch that can be used when starting MWTWIN to specify a file to parse automatically, calculating molecular weights for each formula, and writing to filename.out
+ - Fixed bug in "expand to empirical formula" feature that skipped elements with an occurrence of less than 1 in a formula (for example, [.7CH3] would expand to simply H2.1 rather than C.7H2.1
+ - Fixed bug in formula parser that wasn't warning user of decimal numbers with leading zeroes after carets for isotopes, i.e. ^0.5H is not allowed while ^.5H is (though it is unrealistic and the program warns of this). --- This change no longer matters since I've removed the requirement that decimal numbers cannot start with a 0 as in 0.5
+ - Fixed bug in loading saved formulas on program startup that caused a program error if blank formulas were present before the final formula.
+ - Further improved speed of sorting algorithm in formula finder by converting each line to easily sorted code, sorting the code, and arranging the original lines based on how the coded lines sorted.
+ - Removed requirement that decimal numbers be in the format .5 instead of 0.5 Thus, decimal numbers can now be entered as 0.5 or .5
+ - Removed requirement that numbers following parentheses be integers and not decimal numbers. Thus, (CH3)2.5 is now allowed.
+
+
+Revision 4.61 - February 1, 1999
+ - Added new code to correctly recognize the element dysprosium (Dy) when deuterium (D) is defined as an abbreviation. Previously, the program would match D as deuterium and Y as yttrium, with the only possible fix being to delete the deuterium abbreviation. A special-case work around has been added.
+ - Added a caution statement concerning Dy versus DY (dysprosium vs. deuterium-yttrium).
+
+
+Revision 4.62 - February 8, 1999
+ - Added a warning dialog that appears when the Formula Finder is started, but the element weight mode is using average weights. The user can stay in average weight mode or switch to isotopic weight mode. A checkbox is also included to avoid seeing the warning dialog in the future.
+ - Added the option of using Nominal Integer Weights for elements, useful for looking for matches to low resolution mass spectrometry data via the formula finder.
+ - Fixed bug that incorrectly loaded the saved formulas on program start when the view mode was single view.
+ - Completely reworked how the program parses formulas, looking for elements and abbreviations. Now, discrepancies like the Dy vs. DY problem corrected in revision 4.61 will not occur, even if the user creates a new, potentially ambiguous abbreviation. For example, if the user assigns CH3 to the abbreviation A, then types ac in a formula, the program will parse this as Ac, the element actinium. On the other hand, if they type AC, it will correctly parse this as CH3C, while previous versions would not have.
+ - Reworked a large majority of the code to remove nondescriptive variable names like temp, temp$, etc. Also consolidated some of the repetitive sections into single functions, thereby reducing the overall program size.
+
+
+Revision 4.65 - February 16, 1999
+ - Added ability to sort the elements by atomic weight, elemental symbol, or weight uncertainty when editing elements.
+ - Abbreviations can now contain parentheses, for example CH(CH3)3
+ - Abbreviations can also now contain anything a regular formula might contain, except for other abbreviations. Thus, decimal numbers can now be used, plus parentheses, dashes, brackets, etc. Furthermore, abbreviation formulas can be entered lowercase when editing abbreviations, and the program will properly capitalize the abbreviations.
+ - Added a more robust and faster Formula Finder routine, called "Thorough Search". This routine is recursion based, and no longer requires the user to enter maximum and minimum values for the number of each element present. It is faster than the older, "Bounded Search" routine for finding all matches to a given target weight and tolerance. However, I've left the Bounded Search method available in case the user wishes to search for a high molecular weight compound (over approx. 1000 Da) with many possible elements (over approximately four), in which case the user can enter a large minimum element occurrence number to speed up the search.
+ - When the bounded search method is activated, changing the Target Molecular Weight changes the upper bounds on the checked elements. For example, if a target of 100 is entered, the upper bound on carbon will become 100/12=9. Further, if Smart Hydrogen checking is on, the upper bound on H's is only 53 rather than 103 (granted, 53 is still quite large, but is much more reasonable than 103).
+ - When matching Percent Compositions in the Formula Finder routine using the Thorough Search mode, the user no longer must enter maximum and minimum values for the number of each element present, but they now do have to enter a maximum molecular weight of found compounds.
+ - Reworked more of the code, consolidating more functions and adding a recursive aspect to the formula parsing routine so it can now handle an infinite number of levels of embedded parentheses (within available memory, of course).
+
+Revision 5.0 - May 1, 1999
+ - Code recompiled using Visual Basic 6.0 for Windows 95/98/NT.
+ - Formulas are now displayed using RichText Boxes, allowing subscripts, superscripts, and colors to be displayed. I tried doing this with VB 5, but the program crashed continually. Thankfully, the RichTx32.dll that comes with VB 6 is stable.
+ - Drag and drop of both formulas and results in the Formula Finder is now possible, thanks to the built-in functionality of the Rich Text Boxes. Simply highlight text to copy, then drag and drop it to the desired location (either in MwtWin or in another application, like Microsoft Word).
+ - Added Copy Formula as RTF to allow a formula to be copied as its rich text format code. This allows the formula to be pasted into an RTF aware program (like Microsoft Word) and contain the appropriate super and subscripts. This can also be accomplished by dragging the formula from VB and dropping into Word.
+ - When entering abbreviations in the Edit Abbreviations dialog, they are formatted with super and subscripts as the formula is typed.
+ - When loading the Change Formula Font dialog, the progress of loading fonts is now displayed in the status bar.
+
+Revision 5.01 - May 10, 1999
+ - At a user's request, I have added the ability to enter a charge for each element and abbreviation, allowing the overall charge of a formula to be found. This is not useful for compounds with double bonds or rings, since bond order cannot be determined from the empirical formula. However, it is useful in situations where one knows the exact charge of each constituent of a compound, for example in inorganic clusters
+ - Compute Charge has been added to the options menu to display the overall charge of formulas. Hydrogen is assumed to be +1, unless preceded by a non-halogen such as carbon or a metal.
+ - More Formula Finder changes: 1) the charge can now be computed and displayed; 2) this also allows the mass to charge (m/z) ratio to be computed and displayed; 3) the results of a formula finder search can now be sorted by 1 of 4 criteria: formula, charge, molecular weight, and m/z ratio. Furthermore, the width of the Formula Finder window can now be widened to better display the results.
+ - The font size of the formulas can now be changed using the Change Formula Font dialog. This font size also affects the results shown the in the formula finder.
+ - When editing elemental values, uncertainties, and charges, clicking one of the buttons no longer automatically closes the edit box, allowing one to immediately see the new values that appear if any of the buttons are pushed.
+
+Revision 5.02 - May 12, 1999
+ - Includes improvements to the Charge computation algorithm
+
+Revision 5.03 - May 17, 1999
+ - Updated the Calculator feature to use a rich text box, thus allowing powers like 2^2 to be displayed as superscripts.
+ - Added more Charge and mass/charge ratio options in the formula finder, grouping the checkboxes together in an options dialog. The displayed compounds can now be limited to a specific charge range. Users can also search for compounds with a specific m/z (and thus a range of weights and charges).
+ - Fixed program bug that prevented program from calculating formula weights at program start if in Single View mode.
+ - Fixed program bug that incorrectly displayed the current formula at program start if in Single View mode.
+ - Consolidated more code by combining redundant sections into shared subroutines.
+
+Revision 5.04 - May 18, 1999
+ - Improved the speed of m/z searching in the formula finder when using the bounded search mode.
+
+Revision 5.05 - June 6, 1999
+ - Added the option of not automatically adjusting the Min and Max values for elements in the Formula Finder when performing a bounded search (in the Formula Finder options box).
+ - Corrected a major bug that rendered the bounded search in the Formula Finder inoperable if not calculating charges and m/z ratios of formulas.
+
+Revision 5.06 - July 10, 1999
+ - Upgraded components to Service Pack 3 for Visual Basic 6.0
+ - Moved the Sort Mode and Search Mode combo boxes from the formula finder main form to the formula finder options form.
+ - Added option to quickly change the element mode on the program’s main form, called Quick Switch. These changes do not write the new elemental values to disk until exiting the program. When using the quick elemental mode switch, any user defined elemental values are lost.
+ - Fixed bug that failed to color the status line yellow if a caution statement was displayed at program start.
+
+Revision 5.07 - July 14, 1999
+ - Fixed bug that failed to update the Quick Switch Element mode when the Formula Finder finder weight mode warning window changed the weight mode for the user.
+ - Fixed bug in Formula Finder that caused the number and underscore of custom elements to be inadvertently subscripted when displayed in the results box.
+ - Fixed bug that failed to fill in element or abbreviation information the first time Edit Abbreviations or Edit Elements was chosen on the File menu (they filled in the second time).
+ - Changed the Chlorine and Sulfur check boxes in the formula finder to custom element boxes to allow users the possibility of six custom elements or abbreviations.
+ - Moved many of the program options from the Options menu to a preferences dialog box, making it easier to set multiple options at once. Added an option to make the Formula Finder warning mode screen reappear if user had earlier checked the box to make it never appear again.
+ - Added a number of new keyboard shortcuts for menu items; all shortcuts are displayed in the menus.
+ - Added current build of program to the intro screen and about box. This allows me to differentiate between different builds of a current version. Starting at build 35 was an arbitrary choice, made by counting 34 released versions before the current one. There have surely been several 100 builds of the program on my own computer, however.
+
+Revision 5.07b - July 18, 1999
+ - Rolled back to Service Pack 2 (SP2) of Visual Basic for compiling the program due to errors arising when users tried to install the program on Windows 95 computers (specifically, received error with Comdlg32.ocx). It seems that VB6 SP3 is not compatible with the earlier (original?) version of Windows 95, while it works fine on computers with Windows 95b (plus Win 98/NT).
+
+Revision 5.08 - September 16, 1999
+ - Re-updated program to Service Pack 3 (SP3) since the Comdlg32.ocx error did not appear to be widespread.
+ - Updated web addresses to http://www.geocities.com/CapeCanaveral/Lab/9548/ from http://www.geocities.com/CapeCanaveral/Lab/9317/ due to a snafu at Geocities that erased my web pages, forcing me to create a new account (entirely their fault).
+ - Also updated e-mail addresses to AlchemistMatt@Yahoo.com from AlchemistMatt@Geocities.com due to the merger of Geocities with Yahoo.
+ - Made permissible the use of the plus sign (+) in abbreviations (at the request of a user). For example, an abbreviation called H+ or Na+ can now be entered, both in the main window and in the formula finder.
+
+Revision 5.09 - October 10, 1999
+ - By user request, made the curly brackets, { and }, behave as parentheses in formulas. In addition, added the option of allowing regular brackets, [ and ], to also act as parentheses. When regular brackets are treated as parentheses, all Percent Solver options are disabled. Toggle the bracket mode in the Program Preferences Window.
+ - Made regular and curly brackets available in the calculator. There, they behave as parentheses regardless of the bracket mode setting in the Program Preferences Window.
+ - Fixed bug in calculator that superscripted the plus sign and subscripted numbers following the plus sign
+ - Fixed bug that failed to set the standard deviation of a formula to zero when an error is found in the formula.
+ - Since the plus sign was made an allowable part of an abbreviation in version 5.08, I added the underscore (_) to also be allowable, so users can add anions to the abbreviations list.
+ - Fixed bug that failed to correctly set the "Never Show the Formula Finder Weight Mode Warning Dialog" value correctly when the user requested to "Stop Showing the Warning Dialog" option.
+ - Since I was finding it annoying, I made the behavior in the Formula Finder of selecting an entire text field when clicking on it be turned off by default; it may be turned on in the Formula Finder options window.
+ - Added code to correctly identify invalid Ctrl key combinations (like Ctrl+B, Ctrl+D, etc.) and notify the user if pressed.
+
+Revision 5.10 - December 19, 1999
+ - Fixed bug that failed to recognize the last abbreviation (alphabetically) in the extended abbreviations list; Val is the default final extended abbreviation, thus it wasn’t being correctly identified.
+ - Fixed bug that failed to update the Quick Switch Element Mode value on program load when the element mode was not Average weights.
+ - Changed the behavior of the Copy Current Molecular weight command to just copy the weight value when standard deviation mode is set to off
+ - Assigned Ctrl+W to be the shortcut for Copying the current molecular weight.
+
+Revision 5.11 - March 5, 2000
+ - Added a window for performing calculations for open tubular and packed fused silica capillaries used in capillary liquid chromatography.
+ - Also added the ability to perform Mass Rate Calculations, useful for determining amount of sample eluting from an electrospray needle in ESI-MS.
+ - Fixed minor bugs in the Mole/Mass Converter, including failure to display numbers below 1E-6 when short Standard Deviation mode was on.
+ - In addition to informing the user when the program’s .INI or .DAT files are being re-written due to corruption, I now list the name that the corrupted file has been renamed to.
+ - Just for fun, added an "Always on Top" feature to the program, allowing the user to choose to have the main program windows stay on top of other windows.
+ - Converted the help file to HTML help, since this allows me to display sub and superscripts, along with conforming to Microsoft's new help file standards.
+
+Revision 5.12 - June 27, 2000
+ - At a user's request, added the option of Automatically Copying the current formula's molecular weight to the clipboard after each calculation.
+ - In the Capillary Chromatography Calculations window, added the option to determine theoretically the extent to which band broadening will occur under various capillary conditions and dimensions.
+
+Revision 5.2 - September 28, 2000
+ - To tell the truth, I can't recall what changes I made to warrant changing from 5.12 to 5.2 Most likely, I made some minor changes to the Capillary Chromatography Calculation window, including changing the name to Capillary Flow and Mass Rate Calculations.
+
+Revision 5.21 - April 3, 2001
+ - Changed the constant used to compute Volumetric Flow Rate and Linear Velocity in the Capillary Flow and Mass Rate Calculations window to more accurately predict those values. Specifically, changed the constant form 180 to 270 in the following equation:
+ Vol Flow Rate = [Pressure * (diameter of packing)2 * (epsilon)2 * (capillary radius)2 * Pi] / [270 * viscosity * (column length) * (1 - epsilon)2] where epsilon is the interparticle porosity, typically 0.4
+ - In addition, changed the name of the interparticle porosity to epsilon rather than eta, which I had erroneously labeled it as previously.
+
+Revision 5.22 - April 9, 2001
+ - Changed a constant used to compute Volumetric Flow Rate and Linear Velocity in the Capillary Flow and Mass Rate Calculations window back to 180.
+ - Added ability to view the equations used to compute the flow values.
+
+Revision 5.23 - June 18, 2001
+ - Fixed a bug introduced in version 5.22 that caused the linear velocity value for open capillaries to be incorrect.
+
+Revision 6.02 - October 2, 2001
+ - Added a 3 letter to 1 letter amino acid abbreviation conversion utility. The program still requires that peptide sequences be entered using three letter codes for molecular weight determination, but this converter makes it easier to copy and paste values from other peptide handling programs or the web. In addition to the standard 20 amino acids, the converter also recognizes U for Gla (gamma-Carboxyglutamtate).
+ - Added numerous new Amino Acid abbreviations (Gla, Hse, Hyl, Hyp, Orn, and Sar). Only Gla has a corresponding one letter abbreviation, U, since I could not find any literature-wide agreement for one letter abbreviations for the other new amino acids.
+ - Added ability to display more than 7 formulas simultaneously. The maximum is dependent upon your screen resolution. For example, the maximum for 1024x768 is 12 formulas. The total number to show can be set to a value lower than the maximum in the preferences window.
+ - Added support for other (international) languages. The program can now be customized to support any Roman or Cyrillic character based language (German, French, Spanish, Italian, Russian) by creating a Lang_NewLanguage.ini file and loading the file by choosing Language under the Options menu. All text based phrases in the program can be customized, including ToolTip text and error messages.
+ - Related to international language support, changed program to recognize if commas are set to represent decimal points on the user's computer (Regional Options under the Windows Control Panel). If so, replaces all period (.) decimal points with comma (,) decimal points.
+ - Improved usability of the mole/mass converter by adding option to simply enter the mass of the compound. Additionally, provided option for mg/mL type concentrations rather than simply molarities.
+ - Added numerous new units to the Mole/Mass converter, including micromoles, nmol, pmol, fmol, amol, & micrograms.
+ - Added a new option to the Capillary Flow calculator to use a given Dead Time to compute the Volumetric Flow Rate that would give that dead time, modifying the Back Pressure appropriately to give the computed Volumetric Flow Rate.
+ - Modified program to be dual-monitor aware. The program will now properly center itself on the primary monitor.
+ - Fixed behavior of the Percent Solver to properly display the results rather than the target values when completing a computation. The target values are redisplayed when the user re-enters the set table.
+ - Fixed the math calculator to properly handle parentheses (there were some weird bugs going on). Now using a recursive computation algorithm that allows an infinite level of embedded parentheses. Also, removed requirement that the multiplication operator (*) be included between numbers and parentheses, eg. 3(4+2)/(3+2)+(2/3)6 = 7.6 Finally, can now properly raise value of parentheses to a power, eg. 3*(4+2)^2 = 108
+ - Shuffled around a few of the menus, including moving the Formula Finder, the converters, and the calculators to a new menu, the Tools menu.
+ - Code Changes: Removed redundant code in the Capillary Flow Calculator. Changed application load and unload behavior to avoid the use of the End statement. Added code to prevent any sub forms from being unloaded from memory until program is exited completely.
+ - Extensively edited the help file to bring up-to-date with the latest features and new locations of numerous program items.
+ - Bumped up the version number to 6.0 owing to all of the new improvements. Also, using a version of 6.x, the program version now matches the version of Visual Basic used.
+Revision 6.03 - October 3, 2001
+ - Added ability to cut, copy, or paste values from any of the program textboxes. I perform error checking to prevent invalid characters, and was inadvertently blocking Ctrl+X, Ctrl+C, and Ctrl+V
+ - Added units of Bar and Torr (mm Hg) in pressure box of the Capillary Flow Calculator
+ - Fixed bug in Capillary Flow Calculator that prevented Find Back Pressure and Find Inner Diameter from working
+ - Fixed bug in Capillary Flow Calculator that delayed updating all results after clearing an input value to 0 then typing a valid number again.
+
+Revision 6.04 - October 11, 2001
+ - Expanded the functionality of the Mole/Mass converter window to include a Dilution Calculator to handle volume-volume dilution calculations. Note that by setting the final concentration larger than the initial concentration this can also be used to perform calculations involving concentrating a solute by evaporation or sublimation.
+ - Now coloring textboxes of computed quantities yellow to indicate they are a computed result and cannot be changed.
+ - Fixed bug in cut/copy/paste from textboxes that prevented copying computed results in the capillary flow calculator.
+ - Added keyboard shortcut of Ctrl+A to select all of the text (or numbers) in a text box. Does not apply to formulas in the main window since Ctrl+A means to expand abbreviations.
+ - Added a simple undo feature to restore the currently selected formula or text box to the value it had when first entered. Once you have moved to a new control, the value of the old control cannot be restored. I will probably expand the undo system in the future.
+
+Revision 6.05 - October 23, 2001
+ - Fixed Major bug in Formula Finder that prevented users from changing the Target Percent values for Percent Composition Searching. In addition, the Min and Max search values for bounded searches were also broken. I added a new textbox validation routine in version 6.04 and failed to correctly update the functions for the Formula Finder form.
+ - Moved around a few of the controls on the Mole/Mass/Dilution form.
+ - Updated the Lang_Portuguese.Ini and Lang_Spanish.Ini files.
+
+Revision 6.06 - November 11, 2001
+ - Fixed bug with Mole/Mass/Dilution calculator that generated a program error if the window was minimized then restored (unminimized).
+ - Restored behavior of the Mole/Mass/Dilution calculator window to be a fixed size.
+
+Revision 6.10 - January 25, 2002
+ - Added Peptide Sequence Fragmentation Modelling tool, including ability to plot the theoretical mass spectrum of the fragmentation pattern for a given peptide sequence.
+ - The new Fragmentation Modelling Tool also includes ability to paste actual mass spectral data (mass/intensity pairs) so that the predicted ions can be matched to the raw data. The raw data may also be plotted with the predicted fragment ions.
+ - Added option to enter column diameters in inches in the Capillary Flow and Mass Rate Calculations Window.
+ - Modified Formula Finder results list to grow/shrink vertically in addition to horizontally when the window is resized.
+ - Modified Amino Acid Notation Converter to properly handle H at the beginning and OH at the end in the three-letter based sequence input box. In addition, modified to properly reposition and resize controls when window resized.
+ - Changed Ctrl+A to select entire formula since this is the expected behavior for Ctrl+A in Windows applications and Abbreviation Expansion is most likely rarely used.
+ - Fixed bug in main window involving the order of tabbing between controls.
+ - Fixed bug that failed to sum up standard deviation values for all portions of a formula when using parentheses or abbreviations.
+ - Fixed bug that failed to re-calculate the molecular weight or percent composition of formulas in Single View when the formula is modified using Cut/Copy/Paste via Ctrl+X/Ctrl+C/Ctrl+V.
+ - Fixed bug that caused the Percent Solver to give an answer slightly off (less than 0.001%) from the correct answer when the standard deviation mode was turned on.
+ - Major update to the Lang_Spanish.Ini file with corrections contributed by Perez de la Hoz.
+
+Revision 6.11 - March 9, 2002
+ - Fixed bug that failed to save new amino acid abbreviations if the charge state was not specified
+ - Updated Lang_Russian.Ini file (contributed by Michael I. Yahkind)
+
+Revision 6.12 - March 10, 2002
+ - Removed restriction preventing a formula from starting with a number. Now, starting a formula with a number will multiply the following elements (up to the first dash) by the number. Thus, the following are all equivalent ways of entering a formula with 10 fluorine atoms: F10, (F)10, [10F], and 10F
+
+Revision 6.13 - May 7, 2002
+ - Added ability to edit the one letter abbreviations of amino acids
+ - Fixed bug in 3 to 1 letter amino acid notation converter that failed to mark amino acid abbreviations with no equivalent code with an X when the amino acid existed but no 1 letter abbreviation was defined.
+ - Added ability to resize the abbreviation editing window, accompanied by automatic column width expansion.
+ - Changed help ID numbers to show the correct help screen when pressing F1 in the amino acid notation converter window.
+ - Updated Lang_Portuguese.Ini file (contributed by Alexandre R Soares)
+
+Revision 6.14 - May 9, 2002
+ - Fixed bug in abbreviation editor that failed to properly sort the 1 letter abbreviations when adding or removing amino acid abbreviations.
+
+Revision 6.16 - June 8, 2002
+ - Added option to run the Formula Finder in batch analysis mode, reading search values from a file and writing the results to an output file. See the Batch Analysis help page for more information.
+ - Fixed bug in formula finder that re-initialized all of the custom elements to the phrase "# or element or abbrev" after leaving and returning to the form.
+
+Revision 6.17 - July 1, 2002
+ - Added ability to predict the Isotopic Distribution for a given formula, predicting the masses and relative abundances of all possible isotopes. Includes ability to handle explicitly specified elements as part of the formula, in addition to graphing the results.
+
+Revision 6.18 - July 2, 2002
+ - Turned on the error checking in the Isotopic Distribution module that I had forgotten to turn back on.
+ - Updated the help files to discuss Isotopic Distribution.
+ - Now displaying the formula with subscripts and superscripts on the Isotopic Distribution window.
+ - Updated the Isotopic Distribution results display to be more cleanly formatted.
+
+Revision 6.19 - August 12, 2002
+ - Added ability to use custom amino acids in the Peptide Sequence Fragmentation Modeller.
+ - Added the ability to save and load capillary flow settings to/from text files.
+ - Added the option to automatically show one of the program modules at program start (instead of the default program window). Clicking the X on the module window exits the entire program. Choosing Close (from a menu or a button) returns to the main program screen.
+ - Changed default diffusion coefficient in the Capillary Flow and Mass Rate Calculations module to be 5E-6. Also, changed tooltip to state that typical coefficient for small organics is 1E-5 rather than 1E-6.
+ - Fixed bug in amino acid notation convertor that caused the program to crash if the 3 letter sequence was copied to the list of formulas, but the main window was hidden since Hide Inactive Program windows was turned on.
+ - Re-worked the algorithms used to parse and store the user-defined abbreviations and amino acids. If an invalid (or duplicate) abbreviation is present, the user will now be able to see it using Edit | Abbreviations and correct or remove the abbreviation.
+
+Revision 6.20 - October 15, 2002
+ - Modified form layouts to behave properly using the default Windows XP theme (which uses wider borders than previous themes)
+ - Minor updates to the help files, including updating contact information.
+
+Revision 6.21 - November 17, 2002
+ - Added custom language captions for the results box in the Isotopic Distribution window.
+ - Added a new language: Catalan (aka Català)
+
+Revision 6.22 - November 29, 2002
+ - Modified the Set X Range and Set Y Range functions on the Plot window to allow users to set the view range to more than 110% of the current data range. The new allowable limit is up to 1000 times the data range.
+
+Revision 6.25 - Beta 12 completed June 16, 2003
+ - Although the program interface looks very similar, all of the primary computation routines have been moved to an ActiveX DLL file. Doing this allowed me to greatly clean up a lot of the legacy code present in the software.
+ - Additional units have been added to many of the parameters in the Capillary Flow Calculations window.
+ - Additional units have been added to some of the parametesr in the Mole/Mass Converter window.
+ - Abbreviations may now contain other abbreviations. For example, if Ph = C6H5 then you could define Cb = PhCl. This also allows D to be used inside other abbreviations.
+ - The ability to right-click and see the Cut/Copy/Paste etc. options has been added to numerous text boxes throughout the program.
+ - The Peptide Sequence and Fragmentation module has been greatly expanded:
+ - You can now define modification symbols to allow for modified amino acids.
+ - You can now choose the functional group present at the N and C terminus.
+ - Phosphorylation is now an allowable neutral loss.
+ - The fragmentation mass listing now excludes those ions that could not possibly form, based on location in the peptide and whether or not a specific residue can lose water, ammonia, or the phosphate group.
+ - The mass of the peptide, including any modifications, is now displayed on the form, along with the equivalent mass of the M+H mass.
+ - You can convert between M+H and [M+nH]n+ where n is between 1 and 10.
+ - The graphing component has been updated to a professional component. The graph is now much faster and much more powerful, allowing for custom annotations and numerous other features, including the ability to save and load graphs (including all colors, styles, and annotations).
+ - The theoretical fragmentation spectrum can be included on the graph, and any matches with the real data can be included as annotations on the graph.
+ - The peptide sequence and fragmentation module (and the accompanying graph) can correctly read .Dta files (common text-based MS/MS file format).
+ - The Batch Analysis feature has been greatly expanded. Numerous new commands are now present, including the ability to change the standard deviation mode, convert compounds to empirical formulas, and convert amino acid sequences to/from 1 and 3 letter notation.
+ - You can now subtract out elements from a formula using the > symbol:
+ - This feature was added to allow one to quickly find the mass or empirical formula of a compound that has lost one or more elements due to a reaction or a neutral loss in mass spectrometry.
+ - For example: C6H5Cl>HCl means C6H5Cl minus HCl, having a mass equivalent to C6H4
+ - The elements to the right of the > symbol must all be present in the elements to the left of the > symbol (see Element Subtraction for more information).
+ - Changed the /X command line switch to mean "do not write any settings (abbreviations, elements, values) to disk"
+ - Added a new command line switch, /Z, meaning "do not read or write any settings to/from disk"
+
+Revision 6.26 - August 3, 2003
+ - Updated the Isotopic Distribution module to use the new graphing component described above for the Peptide Sequence Fragmentation module
+ - Added the ability to paste a list of ions to compare with the predicted isotopic distribution.
+ - Added error handling routines to the Formula Finder code to reduce the possibility of abrupt program crashes.
+
+Revision 6.27 - October 10, 2003
+ - Fixed bug on the Peptide Sequence and Fragmentation Module that used 1.00000 for the mass of hydrogen rather than 1.00782 when converting between M+H and [M+nH]n+
+
+Revision 6.28 - October 30, 2003
+ - Added option to the graph component to define custom tick starting values and intervals. Use Edit->Zoom Range.
+
+Revision 6.29 - November 23, 2003
+ - Fixed bug involving call to Peptide.SetModificationSymbol in MwtWinDll.Dll that caused the program to crash if the user had the Windows decimal point set to a comma rather than a period, as is common in many countries outside the United States and the UK.
+
+Revision 6.30 - December 3, 2003
+ - Modified the graph control to allow changing the border color and border style (3D or plain)
+
+Revision 6.31 - January 12, 2004
+ - Added new window that allows one to compute solvent viscosity for a mixture of water and acetonitrile (MeCN) given the temperature and percent organic composition. The routine uses the Chen-Horvath equation (see Thompson, JD; Carr, P, Analytical Chemistry, 2002, 74, 4150-4159 or Chen, H; Horvath, CJ, Chromatography A, 1995, 705, 3)
+ - Can also graph the viscosity as a function of percent organic composition for the given temperature.
+
+Revision 6.32 - February 29, 2004
+ - Fixed bug in Capillary Flow Calculator that gave erroneous results if one were to set the particle diameter to 0, then back to a non-zero value when finding column back pressure for packed capillaries.
+ - Now displaying the references to the Chen-Horvath viscosity equation in the program, just below the equation.
+
+Revision 6.33 - March 27, 2004
+ - Updated the MwtWinDll.Dll file to include Xxx as a default amino acid abbreviation, equivalent to C6H12NO (Lysine)
+
+Revision 6.34 - August 14, 2004
+ - Fixed bug in the Peptide Sequence and Fragmentation module that used the monoisotopic mass of hydrogen as the charge carrier rather than using the mass of a proton (which is 0.0005 Da less than the mass of hydrogen). This involved updating MwtWinDll.Dll.
+ - On the Isotopic Distribution module, added the ability to display the masses as m/z values, with charge values greater than 1.
+
+Revision 6.35 - September 12, 2004
+ - Fixed bug in the Mole/Mass/Dilution Calculator that involved the dilution concentrations not updating when the custom mass was changed.
+
+Revision 6.36 - November 16, 2004
+ - Updated the MwtWinDll.Dll file with a few bug fixes involving the peptide parsing class
+
+Revision 6.37 - December 26, 2004
+ - Extended the Batch Calculation engine to support Isotopic Distribution commands. Enable using IsotopicDistribution=On ; Set the charge state using IsotopicDistributionCharge=1
+
+Revision 6.38 - February 18, 2006
+ - Added error handlers to the copy and paste routines
+ - Updated the mass of the most abundant isotope for each element to match the default monoisotopic mass for each element
+ - The elemental masses come from two different sources and the monoisotopic mass was sometimes slightly different than the most abundant isotope's mass; this has been corrected
+ - As part of this update, switched the variables used to store mass values from single to double precision
+
+Revision 6.39 - March 8, 2006
+ - Added option Show Delta Mass on the Formula Finder form
+ - Added new sort option to the Formula Finder: Sort by Abs(Delta Mass)
+ - Fixed bug in the Peptide Sequence and Fragmentation module that caused an array initialization error when no valid residues were defined in the peptide sequence
+ - Fixed control placement bug on the Formula Finder form
+
+Revision 6.40 - May 25, 2006
+ - Fixed bug that caused the program to crash if you maximized the Formula Finder screen
+
+Revision 6.41 - September 21, 2006
+ - Fixed several data synchronization bugs in the capillary flow calculator that caused displayed values to get out of sync with values cached in the DLL. Bug was commonly seen if various input values on the form were set to 0 then set back to a non-zero value.
+
+Revision 6.42 - November 5, 2006
+ - New version of MwtWinDll.dll that fixes charge state interpretation when computing m/z values in the Isotopic Distribution module
diff --git a/SetRange.frm b/SetRange.frm
new file mode 100644
index 0000000..ceede1b
--- /dev/null
+++ b/SetRange.frm
@@ -0,0 +1,146 @@
+VERSION 5.00
+Begin VB.Form frmSetValue
+ BorderStyle = 3 'Fixed Dialog
+ Caption = "Set Value"
+ ClientHeight = 1065
+ ClientLeft = 45
+ ClientTop = 330
+ ClientWidth = 3945
+ ClipControls = 0 'False
+ ControlBox = 0 'False
+ LinkTopic = "Form1"
+ MaxButton = 0 'False
+ MinButton = 0 'False
+ ScaleHeight = 1065
+ ScaleWidth = 3945
+ ShowInTaskbar = 0 'False
+ StartUpPosition = 3 'Windows Default
+ Tag = "14500"
+ Begin VB.TextBox txtEndVal
+ Height = 285
+ Left = 1320
+ TabIndex = 3
+ Text = "5"
+ Top = 600
+ Width = 975
+ End
+ Begin VB.CommandButton cmdCancel
+ Cancel = -1 'True
+ Caption = "&Cancel"
+ Height = 375
+ Left = 2760
+ TabIndex = 5
+ Tag = "4020"
+ Top = 600
+ Width = 1095
+ End
+ Begin VB.CommandButton cmdSet
+ Caption = "&Set"
+ Default = -1 'True
+ Height = 375
+ Left = 2760
+ TabIndex = 4
+ Tag = "14510"
+ Top = 120
+ Width = 1095
+ End
+ Begin VB.TextBox txtStartVal
+ Height = 285
+ Left = 120
+ TabIndex = 1
+ Text = "5"
+ Top = 600
+ Width = 975
+ End
+ Begin VB.Label lblHiddenStatus
+ Caption = "Hidden Status"
+ Height = 255
+ Left = 120
+ TabIndex = 6
+ Top = 960
+ Visible = 0 'False
+ Width = 1335
+ End
+ Begin VB.Label lblEndVal
+ Caption = "End Val"
+ Height = 435
+ Left = 1320
+ TabIndex = 2
+ Top = 120
+ Width = 1215
+ End
+ Begin VB.Label lblStartVal
+ Caption = "Start Val"
+ Height = 435
+ Left = 120
+ TabIndex = 0
+ Top = 120
+ Width = 1035
+ End
+End
+Attribute VB_Name = "frmSetValue"
+Attribute VB_GlobalNameSpace = False
+Attribute VB_Creatable = False
+Attribute VB_PredeclaredId = True
+Attribute VB_Exposed = False
+Option Explicit
+
+Private blnCoerceDataWithinLimits As Boolean
+
+Private mLowerLimit As Double
+Private mUpperLimit As Double
+
+Private localDefaultSeparationValue As Double
+
+Public Sub SetLimits(blbLclCoerceDataWithinLimits As Boolean, Optional dblLowerLimit As Double = 0, Optional dblUpperLimit As Double = 100, Optional dblDefaultSeparationValue As Double = 1)
+ blnCoerceDataWithinLimits = blbLclCoerceDataWithinLimits
+ If blbLclCoerceDataWithinLimits Then
+ mLowerLimit = dblLowerLimit
+ mUpperLimit = dblUpperLimit
+ localDefaultSeparationValue = dblDefaultSeparationValue
+ End If
+End Sub
+
+Private Sub cmdCancel_Click()
+ lblHiddenStatus = "Cancel"
+ Me.Hide
+End Sub
+
+Private Sub cmdSet_Click()
+ ' Must re-validate data since data is not validated if user presses Enter after changing a value
+ If blnCoerceDataWithinLimits Then
+ ValidateDualTextBoxes txtStartVal, txtEndVal, False, CDbl(mLowerLimit), CDbl(mUpperLimit), CDbl(localDefaultSeparationValue)
+ End If
+
+ lblHiddenStatus = "Ok"
+ Me.Hide
+End Sub
+
+Private Sub Form_Load()
+ SizeAndCenterWindow Me, cWindowUpperThird, , , False
+
+ cmdSet.Caption = LookupLanguageCaption(14510, "&Set")
+ cmdCancel.Caption = LookupLanguageCaption(4020, "&Cancel")
+ Me.Caption = LookupLanguageCaption(14500, "Set Value")
+
+End Sub
+
+Private Sub txtEndVal_KeyPress(KeyAscii As Integer)
+ TextBoxKeyPressHandler txtEndVal, KeyAscii, True, True, True, False, False, False, False, False, False, True, True
+End Sub
+
+Private Sub txtEndVal_Validate(Cancel As Boolean)
+ If blnCoerceDataWithinLimits Then
+ ValidateDualTextBoxes txtEndVal, txtEndVal, False, CDbl(mLowerLimit), CDbl(mUpperLimit), CDbl(localDefaultSeparationValue)
+ End If
+End Sub
+
+Private Sub txtStartVal_KeyPress(KeyAscii As Integer)
+ TextBoxKeyPressHandler txtStartVal, KeyAscii, True, True, True, False, False, False, False, False, False, True, True
+End Sub
+
+Private Sub txtStartVal_Validate(Cancel As Boolean)
+ If blnCoerceDataWithinLimits Then
+ ValidateDualTextBoxes txtStartVal, txtEndVal, False, CDbl(mLowerLimit), CDbl(mUpperLimit), CDbl(localDefaultSeparationValue)
+ End If
+End Sub
diff --git a/SetupHelp.txt b/SetupHelp.txt
new file mode 100644
index 0000000..b1a4385
--- /dev/null
+++ b/SetupHelp.txt
@@ -0,0 +1,55 @@
+
+ Molecular Weight Calculator
+
+ This program will calculate the molecular weight and percent
+composition of up to 20 compounds simultaneously. It recognizes
+user-definable abbreviations and all isotopes. It also includes a
+Mole/Mass Converter, Formula Finder, Capillary Flow Modeler, Amino
+Acid Notation Converter, Peptide Sequence Fragmentation Modeler,
+and built-in calculator. Full program documentation is available
+by pressing F1 during program operation. This program is FreeWare
+and may be distributed freely.
+
+ To install the Molecular Weight Calculator for Windows
+9x/NT/00/ME/XP, run the "Molecular Weight Calculator.msi" file by
+double-clicking on it. The install program should take care of
+copying the files to the correct locations and registering all of
+the components. If replacing an older version, the .INI and .DAT
+files will be replaced. If you have abbreviations you want to save,
+backup the MWT_ABBR.DAT file before installing.
+
+ Note: Sometimes when upgrading from a previous version the Lang*.Ini
+and MwtWin.Chm files do not get upgraded to the current version.
+For this reason, if uprgrading, please delete the Lang*.ini and MwtWin.Chm
+files in the Molecular Weight Calculator directory before running the
+"Molecular Weight Calculator.msi" file. I apologize for the
+inconvenience but have not found a way to fix the problem using the
+current version of the Windows Installer. There are new versions of the
+installer available, but I do not want to force users to have to update
+their Windows Installer simply to install my program.
+
+ If you do not have the Windows Installer on your machine, the .msi
+file will not run and you must install the Windows Installer (it is
+included by default in Windows 2000 and higher). I did not include the
+Windows Installer as part of this download because it is an additional
+1.4 MB to download. You can download the Windows Installer from my
+home page:
+ http://www.alchemistmatt.com/mwtwin.html#windowsinstaller
+
+or from Microsoft:
+ If running Windows 95/98, download
+http://download.microsoft.com/download/platformsdk/wininst/1.1/W9X/EN-US/InstMsi.exe
+
+ If running Windows NT, download
+http://download.microsoft.com/download/platformsdk/wininst/1.1/NT4/EN-US/InstMsi.exe
+
+
+Once you have installed the Windows Installer, you should be able
+to run the "Molecular Weight Calculator.msi" setup file.
+
+Send E-Mail to Matt@Alchemistmatt.Com or AlchemistMatt@Yahoo.Com
+WWW is at http://www.alchemistmatt.com/
+and http://www.geocities.com/alchemistmatt/
+and http://come.to/alchemistmatt/
+
+
diff --git a/SharedVBRoutines.bas b/SharedVBRoutines.bas
new file mode 100644
index 0000000..3d5ec8c
--- /dev/null
+++ b/SharedVBRoutines.bas
@@ -0,0 +1,3086 @@
+Attribute VB_Name = "modSharedVBRoutines"
+Option Explicit
+
+'
+' Collection of Visual Basic Functions
+' Written by Matthew Monroe for use in applications
+'
+' First written in Chapel Hill, NC in roughly 2000
+'
+' Last Modified: July 13, 2003
+' Version: 1.59
+
+Public KeyPressAbortProcess As Integer ' Used with frmProgress
+Public glbDecimalSeparator As String ' Used to record whether the . or the , is the decimal point indicator (. in US while , in Europe)
+Private mTextBoxValueSaved As String ' Used to undo changes to a textbox
+
+Private Const FIELD_DELIMETER = ","
+
+' Constants for Centering Windows
+Public Const cWindowExactCenter = 0
+Public Const cWindowUpperThird = 1
+Public Const cWindowLowerThird = 2
+Public Const cWindowMiddleLeft = 3
+Public Const cWindowMiddleRight = 4
+Public Const cWindowTopCenter = 5
+Public Const cWindowBottomCenter = 6
+Public Const cWindowBottomRight = 7
+Public Const cWindowBottomLeft = 8
+Public Const cWindowTopRight = 9
+Public Const cWindowTopLeft = 10
+
+' The following function and constants are used to keep the application window
+' "on top" of other windows
+'
+Public Declare Function SetWindowPos Lib "user32" _
+ (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, _
+ ByVal x As Long, ByVal y As Long, ByVal cx As Long, _
+ ByVal cy As Long, ByVal wFlags As Long) As Long
+
+' Set some constant values (from WIN32API.TXT).
+Private Const conHwndTopmost = -1
+Private Const conHwndNoTopmost = -2
+Private Const conSwpNoActivate = &H10
+Private Const conSwpShowWindow = &H40
+
+'' Used for Internet Access
+''' Used in the GetUrlSource() Function
+''' from http://www.planet-source-code.com/vb/scripts/ShowCode.asp?lngWId=1&txtCodeId=24465
+''Public Declare Function InternetOpen Lib "wininet.dll" Alias "InternetOpenA" (ByVal sAgent As String, ByVal lAccessType As Long, ByVal sProxyName As String, ByVal sProxyBypass As String, ByVal lFlags As Long) As Long
+''Public Declare Function InternetOpenUrl Lib "wininet.dll" Alias "InternetOpenUrlA" (ByVal hInternetSession As Long, ByVal sURL As String, ByVal sHeaders As String, ByVal lHeadersLength As Long, ByVal lFlags As Long, ByVal lContext As Long) As Long
+''Public Declare Function InternetReadFile Lib "wininet.dll" (ByVal hFile As Long, ByVal sBuffer As String, ByVal lNumBytesToRead As Long, lNumberOfBytesRead As Long) As Integer
+''Public Declare Function InternetCloseHandle Lib "wininet.dll" (ByVal hInet As Long) As Integer
+''
+''Public Const IF_FROM_CACHE = &H1000000
+''Public Const IF_MAKE_PERSISTENT = &H2000000
+''Public Const IF_NO_CACHE_WRITE = &H4000000
+''
+''
+'''used for shelling out to the default web browser
+''Public Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hWnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long
+''Public Const conSwNormal = 1
+''
+''Private Const BUFFER_LEN = 2048
+
+
+' Return the handle of a window given its name or class. Pass only one of the parameters,
+' using vbNullString for the other.
+'
+' For example: hwnd = FindWindow(vbNullString, "My Window Caption")
+'
+Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
+Public Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
+Public Declare Function GetParent Lib "user32" (ByVal hwnd As Long) As Long
+Public Declare Function GetActiveWindow Lib "user32" () As Long
+Public Declare Function GetTopWindow Lib "user32" (ByVal hwnd As Long) As Long
+Public Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
+
+' GetWindow() Constants
+Public Const GW_HWNDFIRST = 0
+Public Const GW_HWNDLAST = 1
+Public Const GW_HWNDNEXT = 2
+Public Const GW_HWNDPREV = 3
+Public Const GW_OWNER = 4
+Public Const GW_CHILD = 5
+Public Const GW_MAX = 5
+Public Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, ByVal wCmd As Long) As Long
+
+'
+' More Window Functions
+'
+Public Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
+Public Declare Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" (ByVal hwnd As Long) As Long
+Public Declare Function GetNextWindow Lib "user32" Alias "GetWindow" (ByVal hwnd As Long, ByVal wFlag As Long) As Long
+
+' Functions for finding the size of the desktop
+
+Private Type Rect
+ Left As Long
+ Top As Long
+ Right As Long
+ Bottom As Long
+End Type
+
+Private Type POINTAPI
+ x As Long
+ y As Long
+End Type
+
+Private Type WINDOWPLACEMENT
+ Length As Long
+ flags As Long
+ showCmd As Long
+ ptMinPosition As POINTAPI
+ ptMaxPosition As POINTAPI
+ rcNormalPosition As Rect
+End Type
+
+Private Declare Function GetDesktopWindow Lib "user32" () As Long
+Private Declare Function GetWindowPlacement Lib "user32" (ByVal hwnd As Long, lpwndpl As WINDOWPLACEMENT) As Long
+
+' Other functions
+'
+Private Declare Function GetTempPath Lib "kernel32" Alias "GetTempPathA" (ByVal nBufferLength As Long, ByVal lpBuffer As String) As Long
+Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
+
+' Api Functions
+Public Declare Function GetTickCount Lib "kernel32" () As Long
+
+' Functions for selecting a directory (Function BrowseForFolder)
+
+Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As String) As Long
+Private Declare Function SHBrowseForFolder Lib "shell32" (lpbi As BROWSEINFO) As Long
+Private Declare Function SHGetPathFromIDList Lib "shell32" (ByVal pidList As Long, ByVal lpBuffer As String) As Long
+Private Declare Function lstrcat Lib "kernel32" Alias "lstrcatA" (ByVal lpString1 As String, ByVal lpString2 As String) As Long
+Private Declare Sub CoTaskMemFree Lib "ole32" (ByVal hMem As Long)
+Private Declare Function GetOpenFileName Lib "comdlg32" Alias "GetOpenFileNameA" (pOpenfilename As OPENFILENAME) As Long
+Private Declare Function GetSaveFileName Lib "comdlg32" Alias "GetSaveFileNameA" (pOpenfilename As OPENFILENAME) As Long
+
+Private Type BROWSEINFO
+ hwndOwner As Long
+ pidlRoot As Long
+ pszDisplayName As Long
+ lpszTitle As Long
+ ulFlags As Long
+ lpfnCallback As Long
+ lParam As Long
+ iImage As Long
+End Type
+
+'used with GetOpenFileName function
+Private Type OPENFILENAME
+ lStructSize As Long
+ hwndOwner As Long
+ hInstance As Long
+ lpstrFilter As String
+ lpstrCustomFilter As String
+ nMaxCustFilter As Long
+ nFilterIndex As Long
+ lpstrFile As String
+ nMaxFile As Long
+ lpstrFileTitle As String
+ nMaxFileTitle As Long
+ lpstrInitialDir As String
+ lpstrTitle As String
+ flags As Long
+ nFileOffset As Integer
+ nFileExtension As Integer
+ lpstrDefExt As String
+ lCustData As Long
+ lpfnHook As Long
+ lpTemplateName As String
+End Type
+
+' Possibly, this should be MAX_PATH = 257
+Private Const MAX_PATH = 512
+
+Private Const WM_USER = &H400
+Private Const BFFM_INITIALIZED = 1
+Private Const BFFM_SELCHANGED = 2
+Private Const BFFM_SETSTATUSTEXT = (WM_USER + 100)
+Private Const BFFM_SETSELECTION = (WM_USER + 102)
+
+Private Const BIF_RETURNONLYFSDIRS = &H1
+Private Const BIF_DONTGOBELOWDOMAIN = &H2
+Private Const BIF_STATUSTEXT = &H4
+Private Const BIF_RETURNFSANCESTORS = &H8
+Private Const BIF_EDITBOX = &H10
+Private Const BIF_NEWDIALOGSTYLE = &H20
+Private Const BIF_USENEWUI = &H40
+Private Const BIF_INCLUDECOMPUTERS = &H1000
+Private Const BIF_INCLUDEPRINTERS = &H2000
+Private Const BIF_INCLUDEFILES = &H4000
+
+'OPENFILENAME structure flags constants (used with Open & Save dialogs)
+Private Const OFN_ALLOWMULTISELECT = &H200
+Private Const OFN_CREATEPROMPT = &H2000
+Private Const OFN_ENABLEHOOK = &H20
+Private Const OFN_ENABLETEMPLATE = &H40
+Private Const OFN_ENABLETEMPLATEHANDLE = &H80
+Private Const OFN_EXPLORER = &H80000
+Private Const OFN_EXTENSIONDIFFERENT = &H400
+Private Const OFN_FILEMUSTEXIST = &H1000
+Private Const OFN_HIDEREADONLY = &H4
+Private Const OFN_LONGNAMES = &H200000
+Private Const OFN_NOCHANGEDIR = &H8
+Private Const OFN_NODEREFERENCELINKS = &H100000
+Private Const OFN_NOLONGNAMES = &H40000
+Private Const OFN_NONETWORKBUTTON = &H20000
+Private Const OFN_NOREADONLYRETURN = &H8000
+Private Const OFN_NOTESTFILECREATE = &H10000
+Private Const OFN_NOVALIDATE = &H100
+Private Const OFN_OVERWRITEPROMPT = &H2
+Private Const OFN_PATHMUSTEXIST = &H800
+Private Const OFN_READONLY = &H1
+Private Const OFN_SHAREAWARE = &H4000
+Private Const OFN_SHAREFALLTHROUGH = 2
+Private Const OFN_SHARENOWARN = 1
+Private Const OFN_SHAREWARN = 0
+Private Const OFN_SHOWHELP = &H10
+Private Const OFS_MAXPATHNAME = 512
+
+Private mCurrentDirectory As String ' The last directory selected using BrowseForFolder()
+'
+
+Public Sub AppendToString(ByRef strThisString As String, strAppendText As String, Optional blnAddCarriageReturn As Boolean = False)
+ strThisString = strThisString & strAppendText
+
+ If blnAddCarriageReturn Then
+ strThisString = strThisString & vbCrLf
+ End If
+End Sub
+
+Public Function AssureNonZero(lngNumber As Long) As Long
+ ' Returns a non-zero number, either -1 if lngNumber = 0 or lngNumber if it's nonzero
+ If lngNumber = 0 Then
+ AssureNonZero = -1
+ Else
+ AssureNonZero = lngNumber
+ End If
+End Function
+
+Public Function BrowseForFileOrFolder(ByVal lngOwnderhwnd As Long, Optional ByRef strStartPath As String, Optional ByVal strTitle As String = "Select File", Optional blnReturnFoldersOnly As Boolean = False, Optional strFilterDescription As String = "All") As String
+ ' Returns the path to the selected file or folder
+ ' Returns "" if cancelled
+
+ '=====================================================================================
+ ' Browse for a Folder using SHBrowseForFolder API function with a callback
+ ' function BrowseCallbackProc.
+ '
+ ' This Extends the functionality that was given in the
+ ' MSDN Knowledge Base article Q179497 "HOWTO: Select a Directory
+ ' Without the Common Dialog Control".
+ '
+ ' After reading the MSDN knowledge base article Q179378 "HOWTO: Browse for
+ ' Folders from the Current Directory", I was able to figure out how to add
+ ' a callback function that sets the starting directory and displays the
+ ' currently selected path in the "Browse For Folder" dialog.
+ '
+ ' I used VB 6.0 (SP3) to compile this code. Should work in VB 5.0.
+ ' However, because it uses the AddressOf operator this code will not
+ ' work with versions below 5.0.
+ '
+ ' This code works in Window 95a so I assume it will work with later versions.
+ '
+ ' Stephen Fonnesbeck
+ ' steev@xmission.com
+ ' http://www.xmission.com/~steev
+ ' Feb 20, 2000
+ '
+ '=====================================================================================
+ ' Usage:
+ '
+ ' Dim folder As String
+ ' folder = BrowseForFileOrFolder(Me, "C:\startdir\anywhere", True, "Select a Directory")
+ ' If Len(folder) = 0 Then Exit Sub 'User Selected Cancel
+ '
+ '=====================================================================================
+ '
+ '
+ ' Code extended by Matthew Monroe to also allow selection of files, using an example
+ ' from http://www.thescarms.com/VBasic/DirectoryBrowser.asp
+ '
+
+ Dim lpIDList As Long
+ Dim sBuffer As String
+ Dim tBrowseInfo As BROWSEINFO
+
+ If Len(strStartPath) > 0 Then
+ mCurrentDirectory = strStartPath & vbNullChar
+ End If
+
+ If Len(mCurrentDirectory) = 0 Then mCurrentDirectory = vbNullChar
+
+ With tBrowseInfo
+ .hwndOwner = lngOwnderhwnd
+ .lpszTitle = lstrcat(strTitle, "")
+ .ulFlags = BIF_RETURNONLYFSDIRS Or BIF_DONTGOBELOWDOMAIN Or BIF_STATUSTEXT Or BIF_EDITBOX Or BIF_NEWDIALOGSTYLE Or BIF_USENEWUI
+ If Not blnReturnFoldersOnly Then
+ .ulFlags = .ulFlags Or BIF_INCLUDEFILES
+ End If
+ .lpfnCallback = GetAddressofFunction(AddressOf BrowseCallbackProc) 'get address of function.
+ End With
+
+ lpIDList = SHBrowseForFolder(tBrowseInfo)
+ If (lpIDList) Then
+ sBuffer = Space(MAX_PATH)
+ SHGetPathFromIDList lpIDList, sBuffer
+ sBuffer = Left(sBuffer, InStr(sBuffer, vbNullChar) - 1)
+
+ Call CoTaskMemFree(lpIDList)
+
+ BrowseForFileOrFolder = sBuffer
+ strStartPath = sBuffer
+ Else
+ BrowseForFileOrFolder = ""
+ End If
+
+End Function
+
+' Used with BrowseForFolder
+Private Function BrowseCallbackProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal lp As Long, ByVal pData As Long) As Long
+
+ Dim lpIDList As Long
+ Dim Ret As Long
+ Dim sBuffer As String
+
+ On Error Resume Next 'Sugested by MS to prevent an error from propagating back into the calling process.
+
+ Select Case uMsg
+ Case BFFM_INITIALIZED
+ Call SendMessage(hwnd, BFFM_SETSELECTION, 1, mCurrentDirectory)
+
+ Case BFFM_SELCHANGED
+ sBuffer = Space(MAX_PATH)
+
+ Ret = SHGetPathFromIDList(lp, sBuffer)
+ If Ret = 1 Then
+ Call SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, sBuffer)
+ End If
+
+ End Select
+
+ BrowseCallbackProc = 0
+
+End Function
+
+' This function allows you to assign a function pointer to a vaiable.
+' Used with BrowseForFolder
+Private Function GetAddressofFunction(add As Long) As Long
+ GetAddressofFunction = add
+End Function
+
+Public Function cChkBox(value As Integer) As Boolean
+ ' Converts a checkbox value to true or false
+ If value = vbChecked Then
+ cChkBox = True
+ Else
+ cChkBox = False
+ End If
+End Function
+
+Public Function CLngRoundUp(dblValue As Double) As Long
+ Dim lngNewValue As Long
+ lngNewValue = CLng(dblValue)
+
+ If lngNewValue <> dblValue Then
+ lngNewValue = lngNewValue + 1
+ End If
+
+ CLngRoundUp = lngNewValue
+End Function
+
+Public Function CLngSafe(strValue As String) As Long
+ On Error Resume Next
+ If IsNumeric(strValue) Then
+ CLngSafe = CLng(strValue)
+ End If
+End Function
+
+Public Function CBoolSafe(strValue As String) As Boolean
+ On Error GoTo ReturnFalse
+ CBoolSafe = CBool(Trim(strValue))
+ Exit Function
+ReturnFalse:
+ CBoolSafe = False
+End Function
+
+Public Function CDblSafe(strWork As String) As Double
+ On Error Resume Next
+ If IsNumeric(strWork) Then
+ CDblSafe = CDbl(strWork)
+ End If
+End Function
+
+Public Function CIntSafeDbl(dblWork As Double) As Integer
+ If dblWork <= 32767 And dblWork >= -32767 Then
+ CIntSafeDbl = CInt(dblWork)
+ Else
+ If dblWork < 0 Then
+ CIntSafeDbl = -32767
+ Else
+ CIntSafeDbl = 32767
+ End If
+ End If
+End Function
+
+Public Function CIntSafe(strWork As String) As Integer
+ If IsNumeric(strWork) Then
+ CIntSafe = CIntSafeDbl(CDbl(strWork))
+ ElseIf LCase(strWork) = "true" Then
+ CIntSafe = -1
+ Else
+ CIntSafe = 0
+ End If
+End Function
+
+Public Function Combinatorial(a As Integer, B As Integer) As Single
+ If a > 170 Or B > 170 Then
+ Debug.Print "Cannot compute factorial of a number over 170. Thus, cannot compute the combination."
+ Combinatorial = -1
+ ElseIf a < B Then
+ Debug.Print "First number should be greater than or equal to the second number"
+ Combinatorial = -1
+ Else
+ Combinatorial = Factorial(a) / (Factorial(B) * Factorial(a - B))
+ End If
+End Function
+
+Public Function CompactPathString(ByVal strPathToCompact As String, Optional ByVal lngMaxLength As Long = 40) As String
+ ' Recursive function to shorten strPathToCompact to a maximum length of lngMaxLength
+
+ ' The following is example output
+ ' Note that when drive letters or subdirectories are present, the a minimum length is imposed
+ ' For "C:\My Documents\Readme.txt"
+ ' Minimum string returned= C:\M..\Rea..
+ ' Length for 20 characters= C:\My D..\Readme.txt
+ ' Length for 25 characters= C:\My Docume..\Readme.txt
+ '
+ ' For "C:\My Documents\Word\Business\Finances.doc"
+ ' Minimum string returned= C:\...\B..\Fin..
+ ' Length for 20 characters= C:\...\B..\Finance..
+ ' Length for 25 characters= C:\...\Bus..\Finances.doc
+ ' Length for 32 characters= C:\...\W..\Business\Finances.doc
+ ' Length for 40 characters= C:\My Docum..\Word\Business\Finances.doc
+
+ Dim strPath(4) As String ' 0-based array
+ Dim intPartCount As Integer
+
+ Dim strLeadingChars As String
+ Dim strShortenedPath As String
+
+ Dim lngCharLoc As Long
+ Dim intLoopCount As Integer, intFileNameIndex As Integer
+ Dim lngShortLength As Long, lngOverLength As Long
+ Dim lngLeadingCharsLength As Long
+ Dim intMultiPathCorrection As Integer
+
+ If lngMaxLength < 3 Then lngMaxLength = 3
+
+ ' Determine the name of the first directory following the leading ?:\ or \\
+
+ strPathToCompact = Trim(strPathToCompact)
+
+ If Len(strPathToCompact) <= lngMaxLength Then
+ CompactPathString = strPathToCompact
+ Exit Function
+ End If
+
+ intPartCount = 1
+ If Left(strPathToCompact, 2) = "\\" Then
+ strLeadingChars = "\\"
+ lngCharLoc = InStr(3, strPathToCompact, "\")
+ If lngCharLoc > 0 Then
+ strLeadingChars = "\\" & Mid(strPathToCompact, 3, lngCharLoc - 2)
+ strPath(0) = Mid(strPathToCompact, lngCharLoc + 1)
+ Else
+ strPath(0) = Mid(strPathToCompact, 3)
+ End If
+ ElseIf Left(strPathToCompact, 2) = ".\" Then
+ strLeadingChars = Left(strPathToCompact, 2)
+ strPath(0) = Mid(strPathToCompact, 3)
+ ElseIf Left(strPathToCompact, 3) = "..\" Or Mid(strPathToCompact, 2, 2) = ":\" Then
+ strLeadingChars = Left(strPathToCompact, 3)
+ strPath(0) = Mid(strPathToCompact, 4)
+ Else
+ strPath(0) = strPathToCompact
+ End If
+
+ ' Examine strPath(0) to see if there are 1, 2, or more subdirectories
+ intLoopCount = 0
+ Do
+ lngCharLoc = InStr(strPath(intPartCount - 1), "\")
+ If lngCharLoc > 0 Then
+ strPath(intPartCount) = Mid(strPath(intPartCount - 1), lngCharLoc + 1)
+ strPath(intPartCount - 1) = Left(strPath(intPartCount - 1), lngCharLoc)
+ intPartCount = intPartCount + 1
+ End If
+ intLoopCount = intLoopCount + 1
+ Loop While intLoopCount < 3
+
+ If intPartCount = 1 Then
+ ' No \ found, we're forced to shorten the filename (though if a UNC, then can shorten part of the UNC)
+
+ If Left(strLeadingChars, 2) = "\\" Then
+ lngLeadingCharsLength = Len(strLeadingChars)
+ If lngLeadingCharsLength > 5 Then
+ ' Can shorten the server name as needed
+ lngShortLength = lngMaxLength - Len(strPath(0)) - 3
+ If lngShortLength < lngLeadingCharsLength Then
+ If lngShortLength < 3 Then lngShortLength = 3
+ strLeadingChars = Left(strLeadingChars, lngShortLength) & "..\"
+ End If
+
+ End If
+ End If
+
+ lngShortLength = lngMaxLength - Len(strLeadingChars) - 2
+ If lngShortLength < 3 Then lngShortLength = 3
+ If lngShortLength < Len(strPath(0)) - 2 Then
+ strShortenedPath = strLeadingChars & Left(strPath(0), lngShortLength) & ".."
+ Else
+ strShortenedPath = strLeadingChars & strPath(0)
+ End If
+ Else
+ ' Found one (or more) subdirectories
+
+ ' First check if strPath(1) = "...\"
+ If strPath(0) = "...\" Then
+ intMultiPathCorrection = 4
+ strPath(0) = strPath(1)
+ strPath(1) = strPath(2)
+ strPath(2) = strPath(3)
+ strPath(3) = ""
+ intPartCount = 3
+ Else
+ intMultiPathCorrection = 0
+ End If
+
+ ' Shorten the first to as little as possible
+ ' If not short enough, replace the first with ... and call this function again
+ lngShortLength = lngMaxLength - Len(strLeadingChars) - Len(strPath(3)) - Len(strPath(2)) - Len(strPath(1)) - 3 - intMultiPathCorrection
+ If lngShortLength < 1 And Len(strPath(2)) > 0 Then
+ ' Not short enough, but other subdirectories are present
+ ' Thus, can call this function recursively
+ strShortenedPath = strLeadingChars & "...\" & strPath(1) & strPath(2) & strPath(3)
+ strShortenedPath = CompactPathString(strShortenedPath, lngMaxLength)
+ Else
+ If Left(strLeadingChars, 2) = "\\" Then
+ lngLeadingCharsLength = Len(strLeadingChars)
+ If lngLeadingCharsLength > 5 Then
+ ' Can shorten the server name as needed
+ lngShortLength = lngMaxLength - Len(strPath(3)) - Len(strPath(2)) - Len(strPath(1)) - 7 - intMultiPathCorrection
+ If lngShortLength < lngLeadingCharsLength - 3 Then
+ If lngShortLength < 3 Then lngShortLength = 3
+ strLeadingChars = Left(strLeadingChars, lngShortLength) & "..\"
+ End If
+
+ ' Recompute lngShortLength
+ lngShortLength = lngMaxLength - Len(strLeadingChars) - Len(strPath(3)) - Len(strPath(2)) - Len(strPath(1)) - 3 - intMultiPathCorrection
+ End If
+ End If
+
+ If intMultiPathCorrection > 0 Then
+ strLeadingChars = strLeadingChars & "...\"
+ End If
+
+ If lngShortLength < 1 Then lngShortLength = 1
+ strPath(0) = Left(strPath(0), lngShortLength) & "..\"
+ strShortenedPath = strLeadingChars & strPath(0) & strPath(1) & strPath(2) & strPath(3)
+
+ ' See if still to long
+ ' If it is, then will need to shorten the filename too
+ lngOverLength = Len(strShortenedPath) - lngMaxLength
+ If lngOverLength > 0 Then
+ ' Need to shorten filename too
+ ' Determine which index the filename is in
+ For intFileNameIndex = intPartCount - 1 To 0 Step -1
+ If Len(strPath(intFileNameIndex)) > 0 Then Exit For
+ Next intFileNameIndex
+
+ lngShortLength = Len(strPath(intFileNameIndex)) - lngOverLength - 2
+ If lngShortLength < 4 Then
+ strPath(intFileNameIndex) = Left(strPath(intFileNameIndex), 3) & ".."
+ Else
+ strPath(intFileNameIndex) = Left(strPath(intFileNameIndex), lngShortLength) & ".."
+ End If
+
+ strShortenedPath = strLeadingChars & strPath(0) & strPath(1) & strPath(2) & strPath(3)
+ End If
+
+ End If
+ End If
+
+ CompactPathString = strShortenedPath
+End Function
+
+Public Function TestCompactFileName(strTestString As String)
+ Dim lngIndex As Long
+
+ For lngIndex = 15 To Len(strTestString) + 2
+ Debug.Print Format(lngIndex, "000") & ": " & CompactPathString(strTestString, lngIndex)
+ Next lngIndex
+End Function
+
+Private Function ComputeAverage(ByRef sngArrayZeroBased() As Single, lngArrayCount As Long, Optional ByRef sngMedian As Single, Optional ByRef sngMinimum As Single, Optional ByRef sngMaximum As Single) As Single
+ ' Computes the average and returns it
+ ' Computes other stats and returns them
+
+ Dim lngIndex As Long
+ Dim sngSumForAveraging As Single, lclAverage As Single, lclMedian As Single
+ Dim lclMinimum As Single, lclMaximum As Single
+
+ If lngArrayCount = 0 Then
+ lclAverage = 0
+ lclMedian = 0
+ Else
+ lclMinimum = sngArrayZeroBased(0)
+ lclMaximum = lclMinimum
+
+ sngSumForAveraging = 0
+ For lngIndex = 0 To lngArrayCount - 1
+ sngSumForAveraging = sngSumForAveraging + sngArrayZeroBased(lngIndex)
+
+ If sngArrayZeroBased(lngIndex) < lclMinimum Then
+ lclMinimum = sngArrayZeroBased(lngIndex)
+ End If
+
+ If sngArrayZeroBased(lngIndex) > lclMaximum Then
+ lclMaximum = sngArrayZeroBased(lngIndex)
+ End If
+
+ Next lngIndex
+
+ lclAverage = sngSumForAveraging / lngArrayCount
+
+ lclMedian = ComputeMedian(sngArrayZeroBased(), lngArrayCount)
+ End If
+
+
+ sngMinimum = lclMinimum
+ sngMaximum = lclMaximum
+
+ sngMedian = lclMedian
+ ComputeAverage = lclAverage
+
+End Function
+
+Public Function ComputeMedian(ByRef sngArrayZeroBased() As Single, lngArrayCount As Long, Optional blnRigorousMedianForEvenNumberedDatasets As Boolean = True) As Single
+ ' Finds the median value in sngIniputArrayZeroBased() using the Select() function from Numerical Recipes in C
+ ' Returns the median
+
+ ' If lngArrayCount is Odd, then calls Select, (N+1)/2 for lngElementToSelect
+ ' If lngArrayCount is Even, and blnRigorousMedianForEvenNumberedDatasets is True, or lngArrayCount < 100,
+ ' then calls the select function twice, grabbing element N/2 and N/2 + 1
+ ' Otherwise, if lngArrayCount is Even, but blnRigorousMedianForEvenNumberedDatasets (and lngArrayCount >= 100)
+ ' then simply calls the function one, grabbing element N/2 and using this as an approximate median value
+
+ Dim lngIndex As Long, lngElementToGrab As Long
+ Dim blnEvenCount As Boolean
+ Dim sngInputArrayOneBased() As Single
+ Dim sngMedianValue As Single, sngMedianValueNextLarger As Single
+
+ If lngArrayCount <= 0 Then Exit Function
+
+ If lngArrayCount = 1 Then
+ ComputeMedian = sngArrayZeroBased(0)
+ Exit Function
+ End If
+
+ ' Since the Select function requires the array be one-based, I make a copy of the data in the Zero Based array
+ ' This also prevents sngArrayZeroBased() from being disturbed
+
+ ReDim sngInputArrayOneBased(lngArrayCount)
+
+ For lngIndex = 0 To lngArrayCount - 1
+ sngInputArrayOneBased(lngIndex + 1) = sngArrayZeroBased(lngIndex)
+ Next lngIndex
+
+ If lngArrayCount / 2# = CLng(lngArrayCount / 2#) Then
+ ' lngArrayCount is even
+ blnEvenCount = True
+ Else
+ ' lngArrayCount is odd
+ blnEvenCount = False
+ End If
+
+ If blnEvenCount Then
+ lngElementToGrab = lngArrayCount / 2
+ sngMedianValue = SelectValue(sngInputArrayOneBased(), lngArrayCount, lngElementToGrab)
+
+ If blnRigorousMedianForEvenNumberedDatasets Or lngArrayCount < 100 Then
+ sngMedianValueNextLarger = SelectValue(sngInputArrayOneBased(), lngArrayCount, lngElementToGrab + 1)
+ sngMedianValue = (sngMedianValue + sngMedianValueNextLarger) / 2
+ End If
+ Else
+ lngElementToGrab = (lngArrayCount + 1) / 2
+ sngMedianValue = SelectValue(sngInputArrayOneBased(), lngArrayCount, lngElementToGrab)
+ End If
+
+ ComputeMedian = sngMedianValue
+
+End Function
+
+Public Function ConstructFormatString(ByVal dblThisValue As Double, Optional ByRef intDigitsInFormattedValue As Integer) As String
+ ' Examines dblThisValue and constructs a format string based on its magnitude
+ ' For example, dblThisValue = 1234 will return "0"
+ ' dblThisValue = 2.4323 will return "0.0000"
+ '
+ ' In addition, returns the length of the string representation of dblThisValue
+ ' using the determined format string
+ Dim lngExponentValue As Long, intDigitsInLabel As Integer
+ Dim strWork As String, strFormatString As String
+
+ ' Determine width of label to use and construct formatting string for labels
+ ' First, find the exponent of dblThisValue
+ strWork = Format(dblThisValue, "0E+000")
+ lngExponentValue = CIntSafe(Right(strWork, 4))
+
+ ' Determine number of digits in dblThisValue, rounded according to lngExponentVal
+ If lngExponentValue >= 0 Then
+ intDigitsInLabel = 0
+ strFormatString = "0"
+ Else
+ ' Add 1 for the decimal point
+ intDigitsInLabel = -lngExponentValue + 1
+ strFormatString = "0." & String(-lngExponentValue, "0")
+ End If
+
+ intDigitsInFormattedValue = Len(Format(dblThisValue, strFormatString))
+
+ ConstructFormatString = strFormatString
+End Function
+
+Public Function CountOccurrenceInString(ByVal strStringToSearch As String, ByVal strSearchString As String, Optional ByVal blnCaseSensitive As Boolean = False) As Long
+ ' Counts the number of times strSearchString occurs in strStringToSearch
+
+ Dim lngMatchCount As Long, lngCharLoc As Long
+
+ If Not blnCaseSensitive Then
+ strStringToSearch = LCase(strStringToSearch)
+ strSearchString = LCase(strSearchString)
+ End If
+
+On Error GoTo CountOccurrenceInStringErrorHandler
+
+ If Len(strSearchString) = 0 Or Len(strStringToSearch) = 0 Then
+ lngMatchCount = 0
+ Else
+ lngCharLoc = 1
+ Do
+ lngCharLoc = InStr(lngCharLoc, strStringToSearch, strSearchString)
+ If lngCharLoc > 0 Then
+ lngMatchCount = lngMatchCount + 1
+ lngCharLoc = lngCharLoc + Len(strSearchString)
+ End If
+ Loop While lngCharLoc > 0
+ End If
+
+ CountOccurrenceInString = lngMatchCount
+ Exit Function
+
+CountOccurrenceInStringErrorHandler:
+ Debug.Assert False
+ Debug.Print "Error in CountOccurrenceInString Function: " & Err.Description
+ CountOccurrenceInString = lngMatchCount
+
+End Function
+
+Public Function CountInstancesOfApp(frmThisForm As VB.Form) As Integer
+ Dim lngHWnd As Long, strCaption As String, intInstances As Integer
+ Dim strClassName As String, nRtn As Long, lngMaxCount As Long
+
+ lngMaxCount = 100
+
+ ' See if other copies of the Software are already loaded
+ ' A hidden window bearing the name of the application is loaded for each instance of the app,
+ ' regardless of the caption of frmMain
+ '
+ ' Thus, I can search for all forms with the caption frmThisForm,
+ ' then examine the ClassName of the form.
+ ' Windows explorer folders are class CabinetWClass
+ ' All VB Apps are class ThunderMain (if in VB IDE) or ThunderRT6Main (if compiled to .Exe)
+ ' In addition, if frmMain's caption is App.Title, it will also be found,
+ ' However, it is class ThunderFormDC or ThunderRT6FormDC
+
+ ' Finally, note that I could use App.Previnstance to see if other instances of the Application are running
+ ' However, this only works for other instances with the identical version number
+ ' Thus, I'll use the Window-Handle method shown below.
+
+ On Error GoTo ExitCountInstances
+
+ lngHWnd = frmThisForm.hwnd
+ intInstances = 0
+ Do
+ DoEvents
+ If lngHWnd = 0 Then Exit Do
+ strCaption = GetWindowCaption(lngHWnd)
+
+ If LCase(strCaption) = LCase(App.Title) Then
+ ' Note: Usage of GetClassName from Joe Garrick, at
+ ' http://www.citilink.com/~jgarrick/vbasic/tips/appact.html
+ ' Must fill strClassName with spaces (or nulls) before sending to GetClassName
+ ' All VB Apps are class Thunder, and each app has one window with Thunder and Main
+ ' Windows explorer folders are class CabinetWClass
+
+ strClassName = Space(lngMaxCount)
+ nRtn = GetClassName(lngHWnd, strClassName, lngMaxCount)
+
+' If Len(strCaption) > 0 Then
+' Debug.Print "(" & lngHWnd&; ") " & strCaption & ": "; strClassName
+' End If
+
+ strClassName = Trim(LCase(strClassName))
+ If InStr(strClassName, "thunder") Then
+ If InStr(strClassName, "main") Then
+ intInstances = intInstances + 1
+ End If
+ End If
+ End If
+
+ lngHWnd = GetNextWindow(lngHWnd, 2)
+ Loop
+
+ExitCountInstances:
+ CountInstancesOfApp = intInstances
+End Function
+
+Public Function GetMostRecentTextBoxValue() As String
+ GetMostRecentTextBoxValue = mTextBoxValueSaved
+End Function
+
+Public Function GetTemporaryDir(Optional blnFavorAPI As Boolean = True) As String
+ ' Uses two different methods to get the temporary directory path
+
+ Dim strTempDirViaEnviron As String, strTempDirViaAPI As String
+ Dim strResult As String
+ Dim lngCount As Long
+ Const MAX_LENGTH = 1024
+
+ ' Get temp directory using the Environ() Function
+ strTempDirViaEnviron = Environ("TMP")
+ If Len(strTempDirViaEnviron) = 0 Then
+ strTempDirViaEnviron = Environ("TEMP")
+ End If
+
+ If Len(strTempDirViaEnviron) > 0 Then
+ If Right(strTempDirViaEnviron, 1) <> "\" Then
+ strTempDirViaEnviron = strTempDirViaEnviron & "\"
+ End If
+ End If
+
+ ' Get temp directory using an API call
+ strResult = Space(MAX_LENGTH)
+ lngCount = GetTempPath(MAX_LENGTH, strResult)
+
+ If lngCount > 0 Then
+ If lngCount > Len(strResult) Then
+ strResult = Space(lngCount + 1)
+ lngCount = GetTempPath(MAX_LENGTH, strResult)
+ End If
+ End If
+
+ If lngCount > 0 Then
+ strTempDirViaAPI = Left(strResult, lngCount)
+ Else
+ strTempDirViaAPI = ""
+ End If
+
+ If strTempDirViaAPI = strTempDirViaEnviron Then
+ GetTemporaryDir = strTempDirViaAPI
+ Else
+ If blnFavorAPI Then
+ GetTemporaryDir = strTempDirViaAPI
+ Else
+ GetTemporaryDir = strTempDirViaEnviron
+ End If
+
+ End If
+
+End Function
+
+Private Function GetWindowCaption(lngHWnd As Long) As String
+ Dim strCaption As String, lngLength As Long
+
+ lngLength = GetWindowTextLength(lngHWnd)
+
+ strCaption = String(lngLength, 0&)
+
+ GetWindowText lngHWnd, strCaption, lngLength + 1
+ GetWindowCaption = strCaption
+
+End Function
+
+Public Function CreateFolderByPath(ByVal strFolderPathToCreate As String) As Boolean
+ ' strFolderPathToCreate must have a fully qualified folder path
+ ' For example: C:\Temp\MyFolder
+ ' or \\MyServer\MyShare\NewFolder
+ ' This function will recursively step through the parent folders of the given folder,
+ ' creating them as needed
+ ' Thus, if strFolderPathToCreate = "C:\Temp\SubFolder\Docs\Working" and only C:\Temp exists
+ ' then 3 folders will be created: SubFolder, Docs, and Working
+
+ ' Returns True if the folder already exists or if it is successfully created
+ ' Returns False if an error occurs or if the folder can't be created
+
+ Dim fso As New FileSystemObject
+ Dim strParentFolderPath As String
+ Dim blnSuccess As Boolean
+
+On Error GoTo CreateFolderByPathErrorHandler
+
+ strParentFolderPath = fso.GetParentFolderName(strFolderPathToCreate)
+
+ If Len(strParentFolderPath) = 0 Then Exit Function
+
+ If Not fso.FolderExists(strParentFolderPath) Then
+ blnSuccess = CreateFolderByPath(strParentFolderPath)
+ Else
+ blnSuccess = True
+ End If
+
+ If fso.FolderExists(strParentFolderPath) And blnSuccess Then
+ If Not fso.FolderExists(strFolderPathToCreate) Then
+ On Error Resume Next
+ fso.CreateFolder (strFolderPathToCreate)
+ If Err.Number = 0 Then
+ blnSuccess = True
+ Else
+ Err.Clear
+ blnSuccess = False
+ End If
+ Else
+ ' Desired folder already exists
+ blnSuccess = True
+ End If
+ Else
+ blnSuccess = False
+ End If
+
+ CreateFolderByPath = blnSuccess
+
+ Set fso = Nothing
+ Exit Function
+
+CreateFolderByPathErrorHandler:
+ CreateFolderByPath = False
+
+End Function
+
+Public Function CSngSafe(strValue As String) As Single
+ If IsNumeric(strValue) Then
+ CSngSafe = CSng(strValue)
+ End If
+End Function
+
+Public Function CStrIfNonZero(ByVal dblThisNumber As Double, Optional strAppendString As String = "", Optional intNumDecimalPlacesToRound As Integer = -1, Optional blnEmptyStringForZero As Boolean = True, Optional blnEmptyStringForNegative As Boolean = True) As String
+ Dim strFormattingString As String
+
+ If (blnEmptyStringForZero And dblThisNumber = 0) Then
+ CStrIfNonZero = ""
+ Else
+ If (blnEmptyStringForNegative And dblThisNumber < 0) Then
+ CStrIfNonZero = ""
+ Else
+ If intNumDecimalPlacesToRound = -1 Then
+ CStrIfNonZero = Trim(CStr(dblThisNumber)) & strAppendString
+ Else
+ If intNumDecimalPlacesToRound = 0 Then
+ strFormattingString = "0"
+ Else
+ strFormattingString = "0." & String(intNumDecimalPlacesToRound, "0")
+ End If
+ CStrIfNonZero = Format(dblThisNumber, strFormattingString) & strAppendString
+ End If
+ End If
+ End If
+End Function
+
+' The following subroutines require the presence of the Microsoft Internet Connection Control on a form
+'''Public Function DownloadWebPage(frmICControlForm as VB.Form, strHtmlLink As String, Optional boolUpdateProgressForm As Boolean = False) As String
+''' ' Returns the text of the page at strHtmlLink
+'''
+''' ' This function requires a Microsoft Internet Connection control to be present on the form specified by
+''' ' frmICControlForm
+''' ' In addition, frmProgress must be present in the project
+'''
+''' ' When using this function (in conjunction with the Microsoft URL Control)
+''' ' the browser appears in the web server logs as 'Microsoft URL Control - 6.00.8862'
+'''
+''' If boolUpdateProgressForm Then
+''' frmProgress.UpdateCurrentSubTask "Downloading web page"
+''' End If
+'''
+''' frmICControlForm.Inet1.AccessType = icUseDefault
+''' DownloadWebPage = frmICControlForm.Inet1.OpenURL(strHtmlLink, 0)
+'''
+''' If boolUpdateProgressForm Then
+''' frmProgress.UpdateCurrentSubTask "Done"
+''' End If
+'''End Function
+'''
+'''Public Function DownloadWebPageAsByteArray(frmICControlForm as VB.Form, strHtmlLink As String, Optional boolUpdateProgressForm As Boolean = False) As Variant
+''' ' Returns a byte array of the data at strHtmlLink
+'''
+''' ' This function requires a Microsoft Internet Connection control to be present on the form specified by
+''' ' frmICControlForm
+''' ' In addition, frmProgress must be present in the project
+'''
+''''''' Note: To download a picture to the hard drive use the following code in the sub calling this function
+'''''' Dim ByteArray() As Byte
+''''''
+'''''' ByteArray = DownloadWebPageAsByteArray(frmMain, strHtmlLink, False)
+''''''
+'''''' If UBound(ByteArray()) > 0 Then
+'''''' ' Save the data to disk
+'''''' Open strFilepath For Binary Access Write As #1
+'''''' Put #1, , ByteArray()
+'''''' Close #1
+'''''' End If
+'''''''
+'''
+''' If boolUpdateProgressForm Then
+''' frmProgress.UpdateCurrentSubTask "Downloading web page"
+''' End If
+'''
+''' frmICControlForm.Inet1.AccessType = icUseDefault
+''' DownloadWebPageAsByteArray = frmICControlForm.Inet1.OpenURL(strHtmlLink, icByteArray)
+'''
+''' If boolUpdateProgressForm Then
+''' frmProgress.UpdateCurrentSubTask "Done"
+''' End If
+'''End Function
+
+Public Function DetermineDecimalPoint() As String
+ Dim strTestNumber As String, sglConversionResult As Double
+
+ ' I need to use the On Error Resume Next statement
+ ' Since the Trim(Str(Cdbl(...))) statement causes an error when the
+ ' user's computer is configured for using , for decimal points but not . for the
+ ' thousand's separator (instead, perhaps, using a space for thousands)
+ On Error Resume Next
+
+ ' Determine what locale we're in (. or , for decimal point)
+ strTestNumber = "5,500"
+ sglConversionResult = CDbl(strTestNumber)
+ If sglConversionResult = 5.5 Then
+ ' Use comma as Decimal point
+ DetermineDecimalPoint = ","
+ Else
+ ' Use period as Decimal point
+ DetermineDecimalPoint = "."
+ End If
+
+End Function
+
+Public Function FlattenStringArray(strArrayZeroBased() As String, lngArrayCount As Long, Optional strLineDelimeter As String = vbCrLf, Optional blnShowProgressFormOnLongOperation As Boolean = True, Optional blnIncludeDelimeterAfterFinalItem As Boolean = True) As String
+ ' Flattens the entries in strArrayZeroBased() into a single string, separating each entry by strLineDelimeter
+ ' Uses some recursive tricks to speed up this process vs. simply concatenating all the entries to a single string variable
+
+ Const MIN_PROGRESS_COUNT = 2500
+
+ ' Note: The following must be evenly divisible by 10
+ Const CUMULATIVE_CHUNK_SIZE = 500
+
+ Dim lngFillStringMaxIndex As Long
+ Dim lngSrcIndex As Long
+ Dim blnShowProgress As Boolean
+ Dim FillStringArray() As String
+ Dim FillStringCumulative As String
+
+ lngFillStringMaxIndex = -1
+
+ If lngArrayCount > MIN_PROGRESS_COUNT And blnShowProgressFormOnLongOperation Then blnShowProgress = True
+
+ If blnShowProgress Then frmProgress.InitializeForm "Copying data to clipboard", 0, lngArrayCount, False, False, False
+
+ ReDim FillStringArray(CLng(lngArrayCount / CUMULATIVE_CHUNK_SIZE) + 2)
+
+ For lngSrcIndex = 0 To lngArrayCount - 1
+ If lngSrcIndex Mod CUMULATIVE_CHUNK_SIZE / 10 = 0 Then
+ If lngSrcIndex Mod CUMULATIVE_CHUNK_SIZE = 0 Then
+ lngFillStringMaxIndex = lngFillStringMaxIndex + 1
+ End If
+
+ If blnShowProgress Then
+ frmProgress.UpdateProgressBar lngSrcIndex
+ If KeyPressAbortProcess > 1 Then Exit For
+ End If
+ End If
+
+ FillStringArray(lngFillStringMaxIndex) = FillStringArray(lngFillStringMaxIndex) & strArrayZeroBased(lngSrcIndex) & strLineDelimeter
+
+ Next lngSrcIndex
+
+ If lngFillStringMaxIndex >= 0 And Not blnIncludeDelimeterAfterFinalItem Then
+ FillStringArray(lngFillStringMaxIndex) = Left(FillStringArray(lngFillStringMaxIndex), Len(FillStringArray(lngFillStringMaxIndex)) - Len(strLineDelimeter))
+ End If
+
+ For lngSrcIndex = 0 To lngFillStringMaxIndex
+ FillStringCumulative = FillStringCumulative & FillStringArray(lngSrcIndex)
+ Next lngSrcIndex
+
+ FlattenStringArray = FillStringCumulative
+
+ If blnShowProgress Then frmProgress.HideForm
+
+End Function
+
+Public Function FolderExists(strPath As String) As Boolean
+ Dim fso As New FileSystemObject
+
+ If Len(strPath) > 0 Then
+
+ FolderExists = fso.FolderExists(strPath)
+ Else
+ FolderExists = False
+ End If
+
+ Set fso = Nothing
+End Function
+
+Public Function FormatNumberAsString(ByVal dblNumber As Double, Optional lngMaxLength As Long = 10, Optional lngMaxDigitsOfPrecision As Long = 8, Optional blnUseScientificWhenTooLong As Boolean = True) As String
+
+ Dim strNumberAsText As String
+ Dim strZeroes As String
+
+ If lngMaxDigitsOfPrecision <= 1 Then
+ strZeroes = "0"
+ Else
+ strZeroes = "0." & String(lngMaxDigitsOfPrecision - 1, "0")
+ End If
+
+ dblNumber = CDbl(Format(dblNumber, strZeroes & "E+0"))
+
+ strNumberAsText = CStr(dblNumber)
+
+ If Len(strNumberAsText) > lngMaxLength Then
+ If blnUseScientificWhenTooLong Then
+ If lngMaxLength < 5 Then lngMaxLength = 5
+
+ strZeroes = String(lngMaxLength - 5, "0")
+ strNumberAsText = Format(dblNumber, "0." & strZeroes & "E+0")
+ Else
+ If lngMaxLength < 3 Then lngMaxLength = 3
+ strNumberAsText = Round(dblNumber, lngMaxLength - 2)
+ End If
+ End If
+
+ FormatNumberAsString = strNumberAsText
+
+End Function
+
+Public Function Factorial(Number As Integer) As Double
+ ' Compute the factorial of a number; uses recursion
+ ' Number should be an integer number between 0 and 170
+
+ On Error GoTo FactorialOverflow
+
+ If Number > 170 Then
+ Debug.Print "Cannot compute factorial of a number over 170"
+ Factorial = -1
+ Exit Function
+ End If
+
+ If Number < 0 Then
+ Debug.Print "Cannot compute factorial of a negative number"
+ Factorial = -1
+ Exit Function
+ End If
+
+ If Number = 0 Then
+ Factorial = 1
+ Else
+ Factorial = Number * Factorial(Number - 1)
+ End If
+
+ Exit Function
+
+FactorialOverflow:
+ Debug.Print "Number too large"
+ Factorial = -1
+End Function
+
+'''Public Function FileExists(strFilepath As String, Optional blnIncludeReadOnly As Boolean = True, Optional blnIncludeHidden As Boolean = False) As Boolean
+''' Warning: This function will match both files and folders
+'''
+''' Dim strTestFile As String
+''' Dim intAttributes As Integer
+'''
+''' If Len(strFilepath) = 0 Then
+''' FileExists = False
+''' Exit Function
+''' End If
+'''
+''' If blnIncludeReadOnly Then intAttributes = intAttributes Or vbReadOnly
+''' If blnIncludeHidden Then intAttributes = intAttributes Or vbHidden
+'''
+''' On Error Resume Next
+''' strTestFile = Dir(strFilepath, intAttributes)
+'''
+''' If Len(strTestFile) > 0 Then
+''' FileExists = True
+''' Else
+''' FileExists = False
+''' End If
+'''
+'''End Function
+
+Public Function FileExists(strFilePath As String) As Boolean
+ Dim fso As New FileSystemObject
+
+ If Len(strFilePath) > 0 Then
+ FileExists = fso.FileExists(strFilePath)
+ Else
+ FileExists = False
+ End If
+
+ Set fso = Nothing
+End Function
+
+Public Function FileExtensionForce(ByVal strFilePath As String, ByVal strExtensionToForce As String, Optional ByVal blnReplaceExistingExtension As Boolean = True) As String
+ ' Guarantees that strFilePath has the desired extension
+ ' Returns strFilePath, with the extension appended if it isn't present
+ '
+ ' Example Call: strFilePath = FileExtensionForce("MyTextFile", "txt")
+ ' will return MyTextFile.txt
+ ' Second Example: strFilePath = FileExtensionForce("MyTextFile.txt", "txt")
+ ' will return MyTextFile.txt
+
+ Dim fso As New FileSystemObject
+ Dim strExistingExtension As String
+
+ strExtensionToForce = Trim(strExtensionToForce)
+ If Left(strExtensionToForce, 1) = "." Then strExtensionToForce = Mid(strExtensionToForce, 2)
+
+ strExistingExtension = fso.GetExtensionName(strFilePath)
+ If UCase(strExistingExtension) <> UCase(strExtensionToForce) Then
+ If blnReplaceExistingExtension And Len(strExistingExtension) > 0 Then
+ FileExtensionForce = Left(strFilePath, Len(strFilePath) - Len(strExistingExtension)) & strExtensionToForce
+ Else
+ FileExtensionForce = strFilePath & "." & strExtensionToForce
+ End If
+ Else
+ FileExtensionForce = strFilePath
+ End If
+
+ Set fso = Nothing
+End Function
+
+' Finds a window containg strCaption and returns the handle to the window
+' Returns 0 if no matches
+Public Function FindWindowCaption(ByVal strCaptionToFind As String, Optional ByRef strClassOfMatch As String) As Long
+
+ Dim strCaption As String
+ Dim lngHWnd As Long, nRtn As Long
+ Const lngMaxCount = 32
+
+ lngHWnd = GetTopWindow(0)
+ Do While lngHWnd <> 0
+ strCaption = GetWindowCaption(lngHWnd)
+
+ If InStr(LCase(strCaption), LCase(strCaptionToFind)) Then
+ nRtn = GetClassName(lngHWnd, strClassOfMatch, lngMaxCount)
+ FindWindowCaption = lngHWnd
+ Exit Do
+ End If
+
+ lngHWnd = GetNextWindow(lngHWnd, 2)
+ Loop
+
+End Function
+
+Private Function GetDesktopSize(ByRef lngHeight As Long, ByRef lngWidth As Long, blnUseTwips As Boolean) As Long
+ ' Determines the height and width of the desktop
+ ' Returns values in Twips, if requested
+ ' Returns the width
+ Dim lngHWnd As Long, lngReturn As Long
+ Dim lpWindowPlacement As WINDOWPLACEMENT
+
+ lngHWnd = GetDesktopWindow()
+
+ lngReturn = GetWindowPlacement(lngHWnd, lpWindowPlacement)
+
+ With lpWindowPlacement.rcNormalPosition
+ lngHeight = .Bottom - .Top
+ lngWidth = .Right - .Left
+ End With
+
+ If blnUseTwips Then
+ lngWidth = lngWidth * Screen.TwipsPerPixelX
+ lngHeight = lngHeight * Screen.TwipsPerPixelY
+ End If
+
+ GetDesktopSize = lngWidth
+End Function
+
+Public Function GetClipboardTextSmart(Optional eClipboardContentType As ClipBoardConstants = vbCFText) As String
+ Dim intAttempts As Integer, strClipboardText As String
+ Const cMaxAttempts = 5
+
+ intAttempts = 0
+
+TryAgain:
+ Err.Clear
+ On Error GoTo TryAgain
+
+ intAttempts = intAttempts + 1
+ If intAttempts <= cMaxAttempts Then
+ Sleep 50
+ strClipboardText = Clipboard.GetText(eClipboardContentType)
+ Else
+ strClipboardText = ""
+ MsgBox Err.Description & vbCrLf & "Continuing without retrieving any clipboard text", vbInformation + vbOKOnly
+ End If
+
+ GetClipboardTextSmart = strClipboardText
+
+End Function
+
+''Public Function GetUrlSource(sURL As String, Optional boolUpdateProgressForm As Boolean = False) As String
+'' ' Function from http://www.planet-source-code.com/vb/scripts/ShowCode.asp?lngWId=1&txtCodeId=24465
+''
+'' ' Note: When using this function, the browser appears in the web server logs as the currently installed web browser (typically MSIE 5.x or MSIE 6.x)
+''
+'' Dim sBuffer As String * BUFFER_LEN, iResult As Integer, sData As String
+'' Dim hInternet As Long, hSession As Long, lReturn As Long
+''
+'' If boolUpdateProgressForm Then
+'' frmProgress.UpdateCurrentSubTask "Initializing internal web browser"
+'' End If
+''
+'' 'get the handle of the current internet connection
+'' hSession = InternetOpen("vb wininet", 1, vbNullString, vbNullString, 0)
+''
+'' 'get the handle of the url
+'' If hSession Then
+'' hInternet = InternetOpenUrl(hSession, sURL, vbNullString, 0, IF_NO_CACHE_WRITE, 0)
+'' End If
+''
+'' If boolUpdateProgressForm Then
+'' frmProgress.UpdateCurrentSubTask "Downloading web page"
+'' End If
+''
+'' 'if we have the handle, then start reading the web page
+'' If hInternet Then
+'' 'get the first chunk & buffer it.
+'' iResult = InternetReadFile(hInternet, sBuffer, BUFFER_LEN, lReturn)
+'' sData = sBuffer
+'' 'if there's more data then keep reading it into the buffer
+'' Do While lReturn <> 0
+'' If boolUpdateProgressForm Then
+'' With frmProgress.lblCurrentSubTask
+'' .Caption = .Caption & "."
+'' If Len(.Caption) > 50 Then .Caption = ""
+'' End With
+'' DoEvents
+'' End If
+''
+'' iResult = InternetReadFile(hInternet, sBuffer, BUFFER_LEN, lReturn)
+'' sData = sData + Mid(sBuffer, 1, lReturn)
+'' Loop
+'' End If
+''
+'' 'close the URL
+'' iResult = InternetCloseHandle(hInternet)
+''
+'' If boolUpdateProgressForm Then
+'' frmProgress.UpdateCurrentSubTask "Done"
+'' End If
+''
+'' GetUrlSource = sData
+''End Function
+
+Public Function IsCharacter(TestString As String) As Boolean
+ ' Returns true if the first letter of TestString is a character (i.e. a lowercase or uppercase letter)
+ Dim AsciiValue As Integer
+ If Len(TestString) > 0 Then
+ AsciiValue = Asc(Left(TestString, 1))
+ Select Case AsciiValue
+ Case 65 To 90, 97 To 122
+ IsCharacter = True
+ Case Else
+ IsCharacter = False
+ End Select
+ Else
+ IsCharacter = False
+ End If
+End Function
+
+'for use in a .bas module or class contained in
+'the same project as the form(s) being tested for
+Public Function IsLoaded(FormName As String) As Boolean
+
+ Dim strFormName As String
+ Dim objForm As VB.Form
+
+ strFormName = UCase(FormName)
+
+ For Each objForm In Forms
+ If UCase(objForm.Name) = strFormName Then
+ IsLoaded = True
+ Exit Function
+ End If
+ Next
+
+End Function
+
+Public Function Log10(x As Double) As Double
+ On Error Resume Next
+ Log10 = Log(x) / Log(10#)
+End Function
+
+''''For use in a class contained in an external .dll
+''Public Function IsLoaded(FormName As String, FormCollection As Object) As Boolean
+''
+'' Dim strFormName As String
+'' Dim f as VB.Form
+''
+'' strFormName = ucase(FormName)
+''
+'' On Error Resume Next
+'' For Each f In FormCollection
+'' If ucase(f.Name) = strFormName Then
+'' IsLoaded = True
+'' Exit Function
+'' End If
+'' Next
+''
+''End Function
+
+''
+''Public Sub LaunchDefaultWebBrowser(frmParentForm as VB.Form, strHtmlAddressToView As String)
+'' ' Any valid form can be passed as the parent form
+'' ' Necessary since an hWnd value is required to run ShellExecute
+''
+'' ShellExecute frmParentForm.hWnd, "open", strHtmlAddressToView, vbNullString, vbNullString, conSwNormal
+''End Sub
+
+Public Function MatchAndSplit(ByRef strSearchString As String, strTextBefore As String, strTextAfter As String, Optional boolRemoveTextBeforeAndMatch As Boolean = True) As String
+ ' Looks for strTextBefore in the string
+ ' Next looks for strTextAfter in the string
+ ' Returns the text between strTextBefore and strTextAfter
+ ' If strTextBefore is not found, starts at the beginning of the string
+ ' If strTextAfter is not found, continues to end of string
+
+ ' In addition, can remove strTextBefore and the matching string from strWork, though keeping strTextAfter
+
+ Dim lngMatchIndex As Long, strWork As String, strMatch As String
+
+ strWork = strSearchString
+
+ lngMatchIndex = InStr(strWork, strTextBefore)
+ If lngMatchIndex > 0 Then
+ strWork = Mid(strWork, lngMatchIndex + Len(strTextBefore))
+ End If
+ lngMatchIndex = InStr(strWork, strTextAfter)
+
+ If lngMatchIndex > 0 Then
+ strMatch = Left(strWork, lngMatchIndex - 1)
+ strWork = Mid(strWork, lngMatchIndex)
+ Else
+ strMatch = strWork
+ strWork = ""
+ End If
+
+ If boolRemoveTextBeforeAndMatch Then
+ strSearchString = strWork
+ End If
+
+ MatchAndSplit = strMatch
+End Function
+
+Public Sub ParseAndSortList(strSearchList As String, ByRef strTextArrayZeroBased() As String, ByRef lngTextArrayCount As Long, Optional ByVal strDelimeters As String = ",;", Optional blnSpaceDelimeter As Boolean = True, Optional blnCarriageReturnDelimeter As Boolean = True, Optional blnSortItems As Boolean = True, Optional blnSortItemsAsNumbers As Boolean = False, Optional blnRemoveDuplicates As Boolean = True, Optional ByVal lngMaxParseCount As Long = 1000)
+ ' Breaks apart strSearchList according to the delimeter specifications
+ ' Places the subparts in strTextArrayZeroBased()
+ ' Optionally sorts the items
+ ' Optionally removes duplicate items
+ '
+ '
+ ' Since this sub requires the use of a special, single character to represent
+ ' a carriage return, if strDelimeters = "" and blnSpaceDelimeter = False, but
+ ' blnCarriageReturnDelimeter = True, then we must choose a substitute single
+ ' character delimeter. We've chosen to use Chr(1). Thus, strSearchList should
+ ' not contain Chr(1) in this special case
+
+ Dim strCrLfReplacement As String
+ Dim lngArrayCountBeforeDuplicatesRemoval As Long
+ Dim lngIndex As Long
+
+ If lngMaxParseCount <= 0 Then lngMaxParseCount = 1000000000#
+
+ ' Possibly add a space to strDelimeters
+ If blnSpaceDelimeter Then strDelimeters = strDelimeters & " "
+ If Len(strDelimeters) = 0 And blnCarriageReturnDelimeter Then
+ ' Need to have at least one character in strDelimeters for the Replace() statement below to work
+ ' I'll use Chr(1) since
+ strDelimeters = Chr(1)
+ End If
+
+ If Len(strDelimeters) = 0 Then
+ ' No delimeters
+ ' Place all of the text in strTextArrayZeroBased(0)
+ lngTextArrayCount = 1
+ ReDim strTextArrayZeroBased(0)
+ strTextArrayZeroBased(0) = strSearchList
+ Exit Sub
+ End If
+
+ If blnCarriageReturnDelimeter Then
+ ' To make life easier, replace all of the carriage returns in strSearchList with
+ ' the first delimeter in strDelimeters (stored in strCrLfReplacement)
+ strCrLfReplacement = Left(strDelimeters, 1)
+ strSearchList = Replace(strSearchList, vbCrLf, strCrLfReplacement)
+ End If
+
+ lngTextArrayCount = ParseString(strSearchList, strTextArrayZeroBased(), lngMaxParseCount, strDelimeters, "", False, True, False)
+
+ If lngTextArrayCount >= 1 Then
+ ReDim Preserve strTextArrayZeroBased(0 To lngTextArrayCount - 1)
+
+ If blnSortItems Then
+ ShellSortString strTextArrayZeroBased(), 0, lngTextArrayCount - 1, blnSortItemsAsNumbers
+ End If
+
+ lngArrayCountBeforeDuplicatesRemoval = lngTextArrayCount
+ If blnRemoveDuplicates Then
+ RemoveDuplicates strTextArrayZeroBased(), lngTextArrayCount
+ End If
+ Else
+ lngTextArrayCount = 0
+ ReDim strTextArrayZeroBased(0)
+ End If
+
+End Sub
+
+Public Function ParseString(ByVal strWork As String, ByRef strParsedVals() As String, lngParseTrackMax As Long, Optional strFieldDelimeter As String = FIELD_DELIMETER, Optional strRemaining As String, Optional boolMatchWholeDelimeter As Boolean = True, Optional boolCombineConsecutiveDelimeters As Boolean = False, Optional blnOneBaseArray As Boolean = True) As Long
+ ' Scans strWork, looking for strFieldDelimeter, splitting strWork into a maximum of lngParseTrackMax parts
+ ' and storing the results in strParsedVals()
+ ' Note that strParsedVals() is a 1-based array if blnOneBaseArray = True (which is default)
+
+ ' strFieldDelimeter may be 1 or more characters long. If multiple characters, use
+ ' boolMatchWholeDelimeter = True to treat strFieldDelimeter as just one delimeter
+ ' Use boolMatchWholeDelimeter = False to treat each of the characters in strFieldDelimeter as a delimeter (token)
+ ' When boolCombineConsecutiveDelimeters is true, then consecutive delimeters (like ,,, or two or more spaces) will be treated as just one delimeter
+
+ ' Returns the number of values found
+ ' If there was strParsedVals() gets filled to lngParseTrackMax, then the remaining text is placed in strRemaining
+
+ Const DIM_CHUNK_SIZE = 10
+
+ Dim lngParseTrack As Long, lngMatchIndex As Long
+ Dim lngParseTrackDimCount As Long
+
+ Dim lngIndexOffset As Long
+ Dim lngCharLoc As Long
+
+ If blnOneBaseArray Then
+ lngIndexOffset = 0
+ Else
+ lngIndexOffset = 1
+ End If
+
+ lngParseTrackDimCount = DIM_CHUNK_SIZE
+
+ ' Need to use On Error Resume Next here in case strParsedVals() has a fixed size (i.e. was dimmed at design time)
+ On Error Resume Next
+ ReDim strParsedVals(lngParseTrackDimCount + 1) ' Must add 1 since any remainder is placed in array (following the Do While-Loop)
+ On Error GoTo ParseStringErrorHandler
+
+ lngParseTrack = 0
+ lngMatchIndex = ParseStringFindNextDelimeter(strWork, strFieldDelimeter, boolMatchWholeDelimeter, boolCombineConsecutiveDelimeters)
+ Do While lngMatchIndex > 0 And lngParseTrack < lngParseTrackMax
+ lngParseTrack = lngParseTrack + 1
+ If lngParseTrack >= lngParseTrackDimCount Then
+ lngParseTrackDimCount = lngParseTrackDimCount + DIM_CHUNK_SIZE
+ On Error Resume Next
+ ReDim Preserve strParsedVals(lngParseTrackDimCount + 1) ' Must add 1 since any remainder is placed in array (following the Do While-Loop)
+ On Error GoTo ParseStringErrorHandler
+ End If
+
+ If lngMatchIndex > 1 Then
+ strParsedVals(lngParseTrack - lngIndexOffset) = Left(strWork, lngMatchIndex - 1)
+ Else
+ strParsedVals(lngParseTrack - lngIndexOffset) = ""
+ End If
+
+ If boolMatchWholeDelimeter Then
+ strWork = Mid(strWork, lngMatchIndex + Len(strFieldDelimeter))
+ Else
+ strWork = Mid(strWork, lngMatchIndex + 1)
+ If boolCombineConsecutiveDelimeters Then
+ ' Need to check for, and remove, any delimeters at the end of strParsedVals(lngParseTrack - lngIndexOffset)
+ Do
+ lngCharLoc = ParseStringFindNextDelimeter(strParsedVals(lngParseTrack - lngIndexOffset), strFieldDelimeter, False, True)
+ If lngCharLoc > 0 Then
+ strParsedVals(lngParseTrack - lngIndexOffset) = Left(strParsedVals(lngParseTrack - lngIndexOffset), lngCharLoc - 1) & Mid(strParsedVals(lngParseTrack - lngIndexOffset), lngCharLoc + 1)
+ End If
+ Loop While lngCharLoc > 0
+ End If
+ End If
+ lngMatchIndex = ParseStringFindNextDelimeter(strWork, strFieldDelimeter, boolMatchWholeDelimeter, boolCombineConsecutiveDelimeters)
+ Loop
+
+ If Len(strWork) > 0 Then
+ ' Items still remain; append to strParsedVals() or place in strRemaining
+ If lngParseTrack < lngParseTrackMax Then
+ lngParseTrack = lngParseTrack + 1
+ strParsedVals(lngParseTrack - lngIndexOffset) = strWork
+ Else
+ strRemaining = strWork
+ End If
+ End If
+
+ ParseString = lngParseTrack
+ Exit Function
+
+ParseStringErrorHandler:
+ Debug.Assert False
+ Debug.Print "Error with ParseString: " & Err.Description
+ ParseString = lngParseTrack
+
+End Function
+
+Public Function ParseStringValues(ByVal strWork As String, ByRef intParsedVals() As Integer, intParseTrackMax As Integer, Optional strFieldDelimeter As String = FIELD_DELIMETER, Optional strRemaining As String, Optional boolMatchWholeDelimeter As Boolean = True, Optional boolCombineConsecutiveDelimeters As Boolean = False, Optional blnOneBaseArray As Boolean = True) As Integer
+ ' See ParseString for parameter descriptions
+
+ Dim intParseTrack As Integer
+ Dim intIndex As Integer, intMaxIndexToCopy As Integer
+ Dim strParsedVals() As String
+
+ If intParseTrackMax < 0 Then intParseTrackMax = 0
+ ReDim strParsedVals(intParseTrackMax + 1)
+
+ ' Need to use On Error Resume Next here in case intParsedVals() has a fixed size (i.e. was dimmed at design time)
+ On Error Resume Next
+ ReDim intParsedVals(intParseTrackMax + 1)
+ On Error GoTo ParseStringValuesErrorHandler
+
+ intParseTrack = ParseString(strWork, strParsedVals(), CLng(intParseTrackMax), strFieldDelimeter, strRemaining, boolMatchWholeDelimeter, boolCombineConsecutiveDelimeters, blnOneBaseArray)
+
+ intMaxIndexToCopy = intParseTrackMax
+ If UBound(intParsedVals) < intMaxIndexToCopy Then
+ intMaxIndexToCopy = UBound(intParsedVals)
+ End If
+
+ For intIndex = 0 To intMaxIndexToCopy
+ If IsNumeric(strParsedVals(intIndex)) Then
+ intParsedVals(intIndex) = CInt(strParsedVals(intIndex))
+ Else
+ intParsedVals(intIndex) = 0
+ End If
+ Next intIndex
+
+ ParseStringValues = intParseTrack
+ Exit Function
+
+ParseStringValuesErrorHandler:
+ Debug.Assert False
+ Debug.Print "Error with ParseStringValues: " & Err.Description
+ ParseStringValues = intParseTrack
+
+End Function
+
+Public Function ParseStringValuesDbl(ByVal strWork As String, ByRef dblParsedVals() As Double, intParseTrackMax As Integer, Optional strFieldDelimeter As String = FIELD_DELIMETER, Optional strRemaining As String, Optional boolMatchWholeDelimeter As Boolean = True, Optional boolCombineConsecutiveDelimeters As Boolean = False, Optional blnOneBaseArray As Boolean = True) As Integer
+ ' See ParseStringText
+
+ Dim intParseTrack As Integer
+ Dim intIndex As Integer, intMaxIndexToCopy As Integer
+ Dim strParsedVals() As String
+
+ If intParseTrackMax < 0 Then intParseTrackMax = 0
+ ReDim strParsedVals(intParseTrackMax + 1)
+
+ ' Need to use On Error Resume Next here in case dblParsedVals() has a fixed size (i.e. was dimmed at design time)
+ On Error Resume Next
+ ReDim dblParsedVals(intParseTrackMax + 1)
+ On Error GoTo ParseStringValuesDblErrorHandler
+
+ intParseTrack = ParseString(strWork, strParsedVals(), CLng(intParseTrackMax), strFieldDelimeter, strRemaining, boolMatchWholeDelimeter, boolCombineConsecutiveDelimeters, blnOneBaseArray)
+
+ intMaxIndexToCopy = intParseTrackMax
+ If UBound(dblParsedVals) < intMaxIndexToCopy Then
+ intMaxIndexToCopy = UBound(dblParsedVals)
+ End If
+
+ For intIndex = 0 To intMaxIndexToCopy
+ If IsNumeric(strParsedVals(intIndex)) Then
+ dblParsedVals(intIndex) = CDbl(strParsedVals(intIndex))
+ Else
+ dblParsedVals(intIndex) = 0
+ End If
+ Next intIndex
+
+ ParseStringValuesDbl = intParseTrack
+ Exit Function
+
+ParseStringValuesDblErrorHandler:
+ Debug.Assert False
+ Debug.Print "Error with ParseStringValuesDbl: " & Err.Description
+ ParseStringValuesDbl = intParseTrack
+
+End Function
+
+Public Function ParseStringFindCrlfIndex(ByRef strWork As String, ByRef intDelimeterLength As Integer) As Long
+ ' First looks for vbCrLf in strWork
+ ' Returns index if found, setting intDelimeterLength to 2
+ ' If not found, uses ParseStringFindNextDelimeter to search for just CR or just LF,
+ ' returning location and setting intDelimeterLength to 1
+
+ Dim lngCrLfLoc As Long
+
+ lngCrLfLoc = InStr(strWork, vbCrLf)
+ If lngCrLfLoc = 0 Then
+ ' CrLf not found; look for just Cr or just LF
+ lngCrLfLoc = ParseStringFindNextDelimeter(strWork, vbCrLf, False)
+ intDelimeterLength = 1
+ Else
+ intDelimeterLength = 2
+ End If
+
+ ParseStringFindCrlfIndex = lngCrLfLoc
+End Function
+
+Private Function ParseStringFindNextDelimeter(ByVal strWork As String, strFieldDelimeter As String, Optional boolMatchWholeDelimeter As Boolean = True, Optional boolCombineConsecutiveDelimeters As Boolean = False) As Long
+ ' Scans strWork, looking for next delimeter (token)
+ ' strFieldDelimeter may be 1 or more characters long. If multiple characters, use
+ ' boolMatchWholeDelimeter = True to treat strFieldDelimeter as just one delimeter
+ ' Use boolMatchWholeDelimeter = False to treat each of the characters in strFieldDelimeter as a delimeter (token)
+
+ Dim intFieldDelimeterLength As Integer, intDelimeterIndex As Integer
+ Dim lngMatchIndex As Long, lngSmallestMatchIndex As Long
+ Dim blnDelimeterMatched As Boolean
+
+ intFieldDelimeterLength = Len(strFieldDelimeter)
+
+ If intFieldDelimeterLength = 0 Then
+ lngSmallestMatchIndex = 0
+ Else
+ If boolMatchWholeDelimeter Or intFieldDelimeterLength = 1 Then
+ lngSmallestMatchIndex = InStr(strWork, strFieldDelimeter)
+ Else
+ ' Look for each of the characters in strFieldDelimeter, returning the smallest nonzero index found
+ lngSmallestMatchIndex = 0
+ For intDelimeterIndex = 1 To Len(strFieldDelimeter)
+ lngMatchIndex = InStr(strWork, Mid(strFieldDelimeter, intDelimeterIndex, 1))
+ If lngMatchIndex > 0 Then
+ If lngMatchIndex < lngSmallestMatchIndex Or lngSmallestMatchIndex = 0 Then
+ lngSmallestMatchIndex = lngMatchIndex
+ End If
+ End If
+ Next intDelimeterIndex
+ End If
+
+ ' If boolCombineConsecutiveDelimeters is true, then examine adjacent text for more delimeters, returning location of final delimeter
+ If boolCombineConsecutiveDelimeters Then
+ lngMatchIndex = lngSmallestMatchIndex + 1
+ Do While lngMatchIndex <= Len(strWork)
+ If boolMatchWholeDelimeter Or intFieldDelimeterLength = 1 Then
+ If Mid(strWork, lngMatchIndex, intFieldDelimeterLength) = strFieldDelimeter Then
+ lngMatchIndex = lngMatchIndex + intFieldDelimeterLength
+ Else
+ Exit Do
+ End If
+ Else
+ blnDelimeterMatched = False
+ For intDelimeterIndex = 1 To Len(strFieldDelimeter)
+ If Mid(strWork, lngMatchIndex, 1) = Mid(strFieldDelimeter, intDelimeterIndex, 1) Then
+ blnDelimeterMatched = True
+ Exit For
+ End If
+ Next intDelimeterIndex
+ If blnDelimeterMatched Then
+ lngMatchIndex = lngMatchIndex + 1
+ Else
+ Exit Do
+ End If
+ End If
+ Loop
+ lngSmallestMatchIndex = lngMatchIndex - 1
+ End If
+
+ End If
+
+ ParseStringFindNextDelimeter = lngSmallestMatchIndex
+
+End Function
+
+Public Sub RemoveDuplicates(ByRef strTextArrayZeroBased() As String, ByRef lngArrayCount As Long)
+ Dim lngIndex As Long
+ Dim lngCompareIndex As Long
+ Dim lngShiftIndex As Long
+
+ lngIndex = 0
+ Do While lngIndex < lngArrayCount
+ lngCompareIndex = lngArrayCount - 1
+ Do While lngCompareIndex > lngIndex
+ If strTextArrayZeroBased(lngIndex) = strTextArrayZeroBased(lngCompareIndex) Then
+ ' Remove duplicate item
+ For lngShiftIndex = lngCompareIndex To lngArrayCount - 2
+ strTextArrayZeroBased(lngShiftIndex) = strTextArrayZeroBased(lngShiftIndex + 1)
+ Next lngShiftIndex
+ lngArrayCount = lngArrayCount - 1
+ strTextArrayZeroBased(lngArrayCount) = ""
+ If lngCompareIndex >= lngArrayCount Then Exit Do
+ Else
+ lngCompareIndex = lngCompareIndex - 1
+ End If
+ Loop
+ lngIndex = lngIndex + 1
+ Loop
+
+End Sub
+
+Public Function ReplaceSubString(ByRef strSearchString As String, strTextToFind As String, strTextToReplaceWith As String) As Boolean
+ ' Returns true if a change was made to strSearchString
+
+ Dim lngMatchIndex As Long, intSearchTextLength As Integer, boolReplaced As Boolean
+
+ boolReplaced = False
+ intSearchTextLength = Len(strTextToFind)
+
+ Do
+ lngMatchIndex = InStr(strSearchString, strTextToFind)
+ If lngMatchIndex > 0 Then
+ strSearchString = Left(strSearchString, lngMatchIndex - 1) & strTextToReplaceWith & Mid(strSearchString, lngMatchIndex + intSearchTextLength)
+ boolReplaced = True
+ End If
+ Loop While lngMatchIndex > 0
+
+ ReplaceSubString = boolReplaced
+
+End Function
+
+Public Function RoundToEvenMultiple(ByVal dblValueToRound As Double, ByVal MultipleValue As Double, ByVal blnRoundUp As Boolean) As Double
+ Dim intLoopCount As Integer
+ Dim strWork As String, dblWork As Double
+ Dim lngExponentValue As Long
+
+ ' Find the exponent of MultipleValue
+ strWork = Format(MultipleValue, "0E+000")
+ lngExponentValue = CIntSafe(Right(strWork, 4))
+
+ intLoopCount = 0
+ Do While Trim(Str(dblValueToRound / MultipleValue)) <> Trim(Str(Round(dblValueToRound / MultipleValue, 0)))
+ dblWork = dblValueToRound / 10 ^ (lngExponentValue)
+ dblWork = Format(dblWork, "0")
+ dblWork = dblWork * 10 ^ (lngExponentValue)
+ If blnRoundUp Then
+ If dblWork <= dblValueToRound Then
+ dblWork = dblWork + 10 ^ lngExponentValue
+ End If
+ Else
+ If dblWork >= dblValueToRound Then
+ dblWork = dblWork - 10 ^ lngExponentValue
+ End If
+ End If
+ dblValueToRound = dblWork
+ intLoopCount = intLoopCount + 1
+ If intLoopCount > 500 Then
+' Debug.Assert False
+ Exit Do
+ End If
+ Loop
+
+ RoundToEvenMultiple = dblValueToRound
+End Function
+
+Public Function RoundToMultipleOf10(ByVal dblThisNum As Double, Optional ByRef lngExponentValue As Long) As Double
+ Dim strWork As String, dblWork As Double
+
+ ' Round to nearest 1, 2, or 5 (or multiple of 10 thereof)
+ ' First, find the exponent of dblThisNum
+ strWork = Format(dblThisNum, "0E+000")
+ lngExponentValue = CIntSafe(Right(strWork, 4))
+ dblWork = dblThisNum / 10 ^ lngExponentValue
+ dblWork = CIntSafeDbl(dblWork)
+
+ ' dblWork should now be between 0 and 9
+ Select Case dblWork
+ Case 0, 1: dblThisNum = 1
+ Case 2 To 4: dblThisNum = 2
+ Case Else: dblThisNum = 5
+ End Select
+
+ ' Convert dblThisNum back to the correct magnitude
+ dblThisNum = dblThisNum * 10 ^ lngExponentValue
+
+ RoundToMultipleOf10 = dblThisNum
+End Function
+
+Public Function RoundToNearest(ByVal dblNumberToRound As Double, ByVal lngMultipleToRoundTo As Long, ByVal blnRoundUp As Boolean) As Long
+ ' Rounds a number to the nearest Multiple specified
+ ' If blnRoundUp = True, then always rounds up
+ ' If blnRoundUp = False, then always rounds down
+ Dim lngRoundedNumber As Long
+
+ If lngMultipleToRoundTo = 0 Then lngMultipleToRoundTo = 1
+
+ ' Use Int() to get the floor of the number
+ lngRoundedNumber = Int(dblNumberToRound / CDbl(lngMultipleToRoundTo)) * lngMultipleToRoundTo
+
+ If blnRoundUp And lngRoundedNumber < dblNumberToRound Then
+ lngRoundedNumber = lngRoundedNumber + lngMultipleToRoundTo
+ End If
+ RoundToNearest = lngRoundedNumber
+End Function
+
+Public Function SelectFile(ByVal Ownerhwnd As Long, ByVal sTitle As String, Optional ByRef strStartPath As String = "", Optional blnSaveFile As Boolean = False, Optional strDefaultFileName As String = "", Optional ByVal strFileFilterCodes As String = "All Files (*.*)|*.*|Text Files (*.txt)|*.txt", Optional ByRef intFilterIndexDefault As Integer = 1, Optional blnFileMustExistOnOpen As Boolean = True) As String
+ ' Returns file name if user selects a file (for opening) or enters a valid path (for saving)
+ ' Returns "" if user canceled dialog
+ ' If strStartPath = "", then uses last directory for default directory
+ ' Updates strStartPath to contain the directory of the selected file
+ ' Updates intFilterIndexDefault to have the filter index of the selected file (if a valid file is chosen)
+
+ Dim ofDlg As OPENFILENAME
+ Dim Res As Long
+ Dim Chr0Pos As Integer
+
+ Dim sFilter As String
+ Dim nFilterInd As Integer
+ Dim strSelectedFile As String
+ Dim strSuggestedFileName As String
+
+ If Len(strFileFilterCodes) = 0 Then
+ sFilter = "All Files" & Chr(0) & "*.*"
+ nFilterInd = 1
+ Else
+ sFilter = Replace(strFileFilterCodes, "|", Chr(0))
+ sFilter = sFilter & Chr(0)
+ nFilterInd = intFilterIndexDefault
+ End If
+
+ If Len(strStartPath) > 0 Then
+ mCurrentDirectory = strStartPath & vbNullChar
+ End If
+
+ If Len(mCurrentDirectory) = 0 Then mCurrentDirectory = vbNullChar
+
+ strSuggestedFileName = strDefaultFileName
+
+ ' GetSaveFileName() doesn't like having colons in the suggested filename
+ strSuggestedFileName = Replace(strSuggestedFileName, ":", "")
+
+ With ofDlg
+ .lStructSize = Len(ofDlg)
+ .hwndOwner = Ownerhwnd
+ .hInstance = App.hInstance
+ .lpstrFilter = sFilter
+ .nFilterIndex = nFilterInd
+ If Len(strSuggestedFileName) > 0 Then
+ .lpstrFile = strSuggestedFileName & String(MAX_PATH, 0)
+ Else
+ .lpstrFile = String(MAX_PATH, 0)
+ End If
+ .nMaxFile = Len(.lpstrFile) - 1
+ .lpstrFileTitle = .lpstrFile
+ .nMaxFileTitle = .nMaxFile
+ .lpstrInitialDir = mCurrentDirectory
+ .lpstrTitle = sTitle
+ If blnSaveFile Then
+ .flags = OFN_LONGNAMES Or OFN_OVERWRITEPROMPT Or OFN_HIDEREADONLY
+ Else
+ If blnFileMustExistOnOpen Then
+ .flags = OFN_FILEMUSTEXIST
+ Else
+ .flags = 0
+ End If
+ End If
+ End With
+
+ If blnSaveFile Then
+ Res = GetSaveFileName(ofDlg)
+ Else
+ Res = GetOpenFileName(ofDlg)
+ End If
+
+ ' Give Windows a chance to refresh (i.e., close the dialog)
+ DoEvents
+
+ If Res = 0 Then
+ SelectFile = ""
+ Else
+ Chr0Pos = InStr(1, ofDlg.lpstrFile, Chr(0))
+ If Chr0Pos > 0 Then
+ strSelectedFile = Left(ofDlg.lpstrFile, Chr0Pos - 1)
+ Else
+ strSelectedFile = Trim(ofDlg.lpstrFile)
+ End If
+
+ StripFullPath strSelectedFile, mCurrentDirectory
+ strStartPath = mCurrentDirectory
+ intFilterIndexDefault = ofDlg.nFilterIndex
+
+ SelectFile = strSelectedFile
+ End If
+
+End Function
+
+Private Function SelectValue(ByRef sngInputArrayOneBased() As Single, lngArrayCount As Long, lngElementToSelect As Long) As Single
+ ' Rearranges sngInputArrayZeroBased such that the lngElementToSelect'th element is in sngInputArrayZeroBased(lngElementToSelect)
+ ' Code is from Numerical Recipes In C (Section 8.5, page 375)
+
+ ' Returns the kth smallest value in the array arr[1...n]. The input array will be rearranged
+ ' to have this value in location arr[k], with all smaller elements moved to arr[1..k-1] (in
+ ' arbitrary order) and all larger elements in arr[k+1..n] (also in arbitrary order).
+
+ Dim I As Long, ir As Long, j As Long, l As Long, lngMidPoint As Long
+
+ Dim a As Single
+
+ l = 1
+ ir = lngArrayCount
+
+ ' Loop until the Exit Do statement is reached
+ Do
+
+ If ir <= l + 1 Then
+ If ir = l + 1 And sngInputArrayOneBased(ir) < sngInputArrayOneBased(l) Then
+ SwapSingle sngInputArrayOneBased(l), sngInputArrayOneBased(ir)
+ End If
+ Exit Do
+ Else
+ lngMidPoint = Int((l + ir) / 2)
+ SwapSingle sngInputArrayOneBased(lngMidPoint), sngInputArrayOneBased(l + 1)
+
+ If sngInputArrayOneBased(l) > sngInputArrayOneBased(ir) Then
+ SwapSingle sngInputArrayOneBased(l), sngInputArrayOneBased(ir)
+ End If
+ If sngInputArrayOneBased(l + 1) > sngInputArrayOneBased(ir) Then
+ SwapSingle sngInputArrayOneBased(l + 1), sngInputArrayOneBased(ir)
+ End If
+ If sngInputArrayOneBased(l) > sngInputArrayOneBased(l + 1) Then
+ SwapSingle sngInputArrayOneBased(l), sngInputArrayOneBased(l + 1)
+ End If
+ I = l + 1
+ j = ir
+ a = sngInputArrayOneBased(l + 1)
+
+ Do
+ Do
+ I = I + 1
+ Loop While sngInputArrayOneBased(I) < a
+
+ Do
+ j = j - 1
+ Loop While sngInputArrayOneBased(j) > a
+
+ If j < I Then Exit Do
+
+ SwapSingle sngInputArrayOneBased(I), sngInputArrayOneBased(j)
+ Loop
+ sngInputArrayOneBased(l + 1) = sngInputArrayOneBased(j)
+ sngInputArrayOneBased(j) = a
+ If j >= lngElementToSelect Then ir = j - 1
+ If j <= lngElementToSelect Then l = I
+
+ End If
+ Loop
+
+ SelectValue = sngInputArrayOneBased(lngElementToSelect)
+
+'' Debug.Print "Checking median; should be " & sngInputArrayOneBased(lngElementToSelect)
+'' For j = 1 To lngArrayCount
+'' Debug.Print sngInputArrayOneBased(j)
+'' Next j
+'' Debug.Print ""
+
+End Function
+
+Public Function SetCheckBox(ByRef chkThisCheckBox As VB.CheckBox, blnIsChecked As Boolean)
+ If blnIsChecked Then
+ chkThisCheckBox.value = vbChecked
+ Else
+ chkThisCheckBox.value = vbUnchecked
+ End If
+End Function
+
+Public Sub SetMostRecentTextBoxValue(strNewText As String)
+ mTextBoxValueSaved = strNewText
+End Sub
+
+Public Sub ShellSortLong(ByRef lngArray() As Long, ByVal lngLowIndex As Long, ByVal lngHighIndex As Long)
+ Dim lngCount As Long
+ Dim lngIncrement As Long
+ Dim lngIndex As Long
+ Dim lngIndexCompare As Long
+ Dim lngCompareVal As Long
+
+On Error GoTo ShellSortLongErrorHandler
+
+' sort array[lngLowIndex..lngHighIndex]
+
+ ' compute largest increment
+ lngCount = lngHighIndex - lngLowIndex + 1
+ lngIncrement = 1
+ If (lngCount < 14) Then
+ lngIncrement = 1
+ Else
+ Do While lngIncrement < lngCount
+ lngIncrement = 3 * lngIncrement + 1
+ Loop
+ lngIncrement = lngIncrement \ 3
+ lngIncrement = lngIncrement \ 3
+ End If
+
+ Do While lngIncrement > 0
+ ' sort by insertion in increments of lngIncrement
+ For lngIndex = lngLowIndex + lngIncrement To lngHighIndex
+ lngCompareVal = lngArray(lngIndex)
+ For lngIndexCompare = lngIndex - lngIncrement To lngLowIndex Step -lngIncrement
+ ' Use <= to sort ascending; Use > to sort descending
+ If lngArray(lngIndexCompare) <= lngCompareVal Then Exit For
+ lngArray(lngIndexCompare + lngIncrement) = lngArray(lngIndexCompare)
+ Next lngIndexCompare
+ lngArray(lngIndexCompare + lngIncrement) = lngCompareVal
+ Next lngIndex
+ lngIncrement = lngIncrement \ 3
+ Loop
+
+ Exit Sub
+
+ShellSortLongErrorHandler:
+ Debug.Assert False
+End Sub
+
+' Shell Sort
+Public Sub ShellSortSingle(ByRef sngArray() As Single, ByVal lngLowIndex As Long, ByVal lngHighIndex As Long)
+ Dim lngCount As Long
+ Dim lngIncrement As Long
+ Dim lngIndex As Long
+ Dim lngIndexCompare As Long
+ Dim sngCompareVal As Single
+
+On Error GoTo ShellSortSingleErrorHandler
+
+' sort array[lngLowIndex..lngHighIndex]
+
+ ' compute largest increment
+ lngCount = lngHighIndex - lngLowIndex + 1
+ lngIncrement = 1
+ If (lngCount < 14) Then
+ lngIncrement = 1
+ Else
+ Do While lngIncrement < lngCount
+ lngIncrement = 3 * lngIncrement + 1
+ Loop
+ lngIncrement = lngIncrement \ 3
+ lngIncrement = lngIncrement \ 3
+ End If
+
+ Do While lngIncrement > 0
+ ' sort by insertion in increments of lngIncrement
+ For lngIndex = lngLowIndex + lngIncrement To lngHighIndex
+ sngCompareVal = sngArray(lngIndex)
+ For lngIndexCompare = lngIndex - lngIncrement To lngLowIndex Step -lngIncrement
+ ' Use <= to sort ascending; Use > to sort descending
+ If sngArray(lngIndexCompare) <= sngCompareVal Then Exit For
+ sngArray(lngIndexCompare + lngIncrement) = sngArray(lngIndexCompare)
+ Next lngIndexCompare
+ sngArray(lngIndexCompare + lngIncrement) = sngCompareVal
+ Next lngIndex
+ lngIncrement = lngIncrement \ 3
+ Loop
+
+'' Debug.Assert VerifySort(sngArray(), lngLowIndex, lngHighIndex)
+ Exit Sub
+
+ShellSortSingleErrorHandler:
+ Debug.Assert False
+End Sub
+
+
+' This sub is about 3 times slower than the above ShellSortSingle routine
+Public Sub ShellSortSingleOld(ByRef sngArray() As Single, ByVal lngLowIndex As Long, ByVal lngHighIndex As Long)
+ Dim sngSwap As Single
+
+ ' Sort the list via a shell sort
+ Dim lngMaxRow As Long, lngOffSet As Long, lngLimit As Long, lngSwitch As Long
+ Dim lngRow As Long
+
+ ' Set comparison lngOffset to half the number of records
+ lngMaxRow = lngHighIndex
+ lngOffSet = lngMaxRow \ 2
+
+ ' When just two data points in the array, need to make sure at least one comparison occurs
+ If (lngHighIndex - lngLowIndex - 1) = 2 Then lngOffSet = 1
+
+ Do While lngOffSet > 0 ' Loop until lngOffset gets to zero.
+
+ lngLimit = lngMaxRow - lngOffSet
+ Do
+ lngSwitch = 0 ' Assume no switches at this lngOffset.
+
+ ' Compare elements and Switch ones out of order:
+ For lngRow = lngLowIndex To lngLimit
+ ' Use > to sort ascending, < to sort descending
+ If sngArray(lngRow) > sngArray(lngRow + lngOffSet) Then
+ sngSwap = sngArray(lngRow + lngOffSet)
+ sngArray(lngRow + lngOffSet) = sngArray(lngRow)
+ sngArray(lngRow) = sngSwap
+ lngSwitch = lngRow
+ End If
+ Next lngRow
+
+ ' Sort on next pass only to where last lngSwitch was made:
+ lngLimit = lngSwitch - lngOffSet
+ Loop While lngSwitch
+
+ ' No switches at last lngOffset, try one half as big:
+ lngOffSet = lngOffSet \ 2
+
+ Loop
+End Sub
+
+Public Sub ShellSortString(ByRef strArray() As String, ByVal lngLowIndex As Long, ByVal lngHighIndex As Long, Optional blnSortItemsAsNumbers As Boolean = False)
+ Dim lngCount As Long
+ Dim lngIncrement As Long
+ Dim lngIndex As Long
+ Dim lngIndexCompare As Long
+ Dim strCompareVal As String
+
+On Error GoTo ShellSortStringErrorHandler
+
+ ' sort array[lngLowIndex..lngHighIndex]
+
+ ' compute largest increment
+ lngCount = lngHighIndex - lngLowIndex + 1
+ lngIncrement = 1
+ If (lngCount < 14) Then
+ lngIncrement = 1
+ Else
+ Do While lngIncrement < lngCount
+ lngIncrement = 3 * lngIncrement + 1
+ Loop
+ lngIncrement = lngIncrement \ 3
+ lngIncrement = lngIncrement \ 3
+ End If
+
+ If blnSortItemsAsNumbers Then
+ Do While lngIncrement > 0
+ ' sort by insertion in increments of lngIncrement
+ For lngIndex = lngLowIndex + lngIncrement To lngHighIndex
+ strCompareVal = strArray(lngIndex)
+ For lngIndexCompare = lngIndex - lngIncrement To lngLowIndex Step -lngIncrement
+ ' Use <= to sort ascending; Use > to sort descending
+ If Val(strArray(lngIndexCompare)) <= Val(strCompareVal) Then Exit For
+ strArray(lngIndexCompare + lngIncrement) = strArray(lngIndexCompare)
+ Next lngIndexCompare
+ strArray(lngIndexCompare + lngIncrement) = strCompareVal
+ Next lngIndex
+ lngIncrement = lngIncrement \ 3
+ Loop
+ Else
+ Do While lngIncrement > 0
+ ' sort by insertion in increments of lngIncrement
+ For lngIndex = lngLowIndex + lngIncrement To lngHighIndex
+ strCompareVal = strArray(lngIndex)
+ For lngIndexCompare = lngIndex - lngIncrement To lngLowIndex Step -lngIncrement
+ ' Use <= to sort ascending; Use > to sort descending
+ If strArray(lngIndexCompare) <= strCompareVal Then Exit For
+ strArray(lngIndexCompare + lngIncrement) = strArray(lngIndexCompare)
+ Next lngIndexCompare
+ strArray(lngIndexCompare + lngIncrement) = strCompareVal
+ Next lngIndex
+ lngIncrement = lngIncrement \ 3
+ Loop
+ End If
+
+ Exit Sub
+
+ShellSortStringErrorHandler:
+Debug.Assert False
+
+End Sub
+
+' Quick sort
+Public Sub QuickSort(ByRef sngArray() As Single, ByVal lngLowIndex As Long, ByVal lngHighIndex As Long)
+ ' From http://oopweb.com/Algorithms/Documents/Sman/Volume/s_vsq2.txt
+ Dim lbStack(32) As Long
+ Dim ubStack(32) As Long
+ Dim lngStackPointer As Long ' stack pointer
+ Dim lngCurrentLowerBoundIndex As Long ' current lower-bound
+ Dim lngCurrentUpperBoundIndex As Long ' current upper-bound
+ Dim lngPivotIndex As Long ' index to pivot
+ Dim I As Long
+ Dim j As Long
+ Dim m As Long
+ Dim sngSwapVal As Single ' temp used for exchanges
+
+ lbStack(0) = lngLowIndex
+ ubStack(0) = lngHighIndex
+ lngStackPointer = 0
+ Do While lngStackPointer >= 0
+ lngCurrentLowerBoundIndex = lbStack(lngStackPointer)
+ lngCurrentUpperBoundIndex = ubStack(lngStackPointer)
+
+ Do While (lngCurrentLowerBoundIndex < lngCurrentUpperBoundIndex)
+
+ ' select pivot and exchange with 1st element
+ lngPivotIndex = lngCurrentLowerBoundIndex + (lngCurrentUpperBoundIndex - lngCurrentLowerBoundIndex) \ 2
+
+ ' exchange lngCurrentLowerBoundIndex, lngPivotIndex
+ sngSwapVal = sngArray(lngCurrentLowerBoundIndex)
+ sngArray(lngCurrentLowerBoundIndex) = sngArray(lngPivotIndex)
+ sngArray(lngPivotIndex) = sngSwapVal
+
+ ' partition into two segments
+ I = lngCurrentLowerBoundIndex + 1
+ j = lngCurrentUpperBoundIndex
+ Do
+ Do While I < j
+ If sngArray(lngCurrentLowerBoundIndex) <= sngArray(I) Then Exit Do
+ I = I + 1
+ Loop
+
+ Do While j >= I
+ If sngArray(j) <= sngArray(lngCurrentLowerBoundIndex) Then Exit Do
+ j = j - 1
+ Loop
+
+ If I >= j Then Exit Do
+
+ ' exchange i, j
+ sngSwapVal = sngArray(I)
+ sngArray(I) = sngArray(j)
+ sngArray(j) = sngSwapVal
+
+ j = j - 1
+ I = I + 1
+ Loop
+
+ ' pivot belongs in sngArray[j]
+ ' exchange lngCurrentLowerBoundIndex, j
+ sngSwapVal = sngArray(lngCurrentLowerBoundIndex)
+ sngArray(lngCurrentLowerBoundIndex) = sngArray(j)
+ sngArray(j) = sngSwapVal
+
+ m = j
+
+ ' keep processing smallest segment, and stack largest
+ If m - lngCurrentLowerBoundIndex <= lngCurrentUpperBoundIndex - m Then
+ If m + 1 < lngCurrentUpperBoundIndex Then
+ lbStack(lngStackPointer) = m + 1
+ ubStack(lngStackPointer) = lngCurrentUpperBoundIndex
+ lngStackPointer = lngStackPointer + 1
+ End If
+ lngCurrentUpperBoundIndex = m - 1
+ Else
+ If m - 1 > lngCurrentLowerBoundIndex Then
+ lbStack(lngStackPointer) = lngCurrentLowerBoundIndex
+ ubStack(lngStackPointer) = m - 1
+ lngStackPointer = lngStackPointer + 1
+ End If
+ lngCurrentLowerBoundIndex = m + 1
+ End If
+ Loop
+ lngStackPointer = lngStackPointer - 1
+ Loop
+
+ Debug.Assert VerifySort(sngArray(), lngLowIndex, lngHighIndex)
+End Sub
+
+Public Sub TestSortRoutines()
+ Const DATA_COUNT = 10000
+ Const LOOP_COUNT = 25
+ Const MOD_CHUNK = 1
+ Dim sngTest(DATA_COUNT) As Single, sngArrayToSort(DATA_COUNT) As Single
+ Dim lngRandomNumberSeed As Long
+ Dim lngIndex As Long, lngLoop As Long
+ Dim lngStartTime As Long, lngStopTime As Long
+
+ Debug.Print "Testing Data_Count = " & DATA_COUNT
+ lngRandomNumberSeed = Timer
+
+ ' Call Rnd() with a negative number before calling Randomize() lngRandomNumberSeed in order to
+ ' guarantee that we get the same order of random numbers each time
+ Call Rnd(-1)
+ Randomize lngRandomNumberSeed
+ lngStartTime = GetTickCount()
+ For lngLoop = 0 To LOOP_COUNT - 1
+ If lngLoop Mod MOD_CHUNK = 0 Then Debug.Print ".";
+
+ For lngIndex = 0 To DATA_COUNT - 1
+ sngTest(lngIndex) = Rnd(1)
+ sngArrayToSort(lngIndex) = sngTest(lngIndex)
+ Next lngIndex
+
+ ' Call ShellSort
+ ShellSortSingleOld sngArrayToSort(), 0, DATA_COUNT - 1
+
+ ' Restore sngArrayToSort() to original order
+ For lngIndex = 0 To DATA_COUNT - 1
+ sngArrayToSort(lngIndex) = sngTest(lngIndex)
+ Next lngIndex
+ Next lngLoop
+ lngStopTime = GetTickCount()
+ Debug.Print "ShellSortOld took " & lngStopTime - lngStartTime & " msec total"
+
+
+ Call Rnd(-1)
+ Randomize lngRandomNumberSeed
+ lngStartTime = GetTickCount()
+ For lngLoop = 0 To LOOP_COUNT - 1
+ If lngLoop Mod MOD_CHUNK = 0 Then Debug.Print ".";
+
+ For lngIndex = 0 To DATA_COUNT - 1
+ sngTest(lngIndex) = Rnd(1)
+ sngArrayToSort(lngIndex) = sngTest(lngIndex)
+ Next lngIndex
+
+ ' Call ShellSort
+ ShellSortSingle sngArrayToSort(), 0, DATA_COUNT - 1
+
+ ' Restore sngArrayToSort() to original order
+ For lngIndex = 0 To DATA_COUNT - 1
+ sngArrayToSort(lngIndex) = sngTest(lngIndex)
+ Next lngIndex
+ Next lngLoop
+ lngStopTime = GetTickCount()
+ Debug.Print "ShellSort took " & lngStopTime - lngStartTime & " msec total"
+
+
+ Call Rnd(-1)
+ Randomize lngRandomNumberSeed
+ lngStartTime = GetTickCount()
+ For lngLoop = 0 To LOOP_COUNT - 1
+ If lngLoop Mod MOD_CHUNK = 0 Then Debug.Print ".";
+
+ For lngIndex = 0 To DATA_COUNT - 1
+ sngTest(lngIndex) = Rnd(1)
+ sngArrayToSort(lngIndex) = sngTest(lngIndex)
+ Next lngIndex
+
+ ' Call QuickSort
+ QuickSort sngArrayToSort(), 0, DATA_COUNT - 1
+
+ ' Restore sngArrayToSort() to original order
+ For lngIndex = 0 To DATA_COUNT - 1
+ sngArrayToSort(lngIndex) = sngTest(lngIndex)
+ Next lngIndex
+ Next lngLoop
+ lngStopTime = GetTickCount()
+ Debug.Print "QuickSort took " & lngStopTime - lngStartTime & " msec total"
+
+End Sub
+
+Public Sub SizeAndCenterWindow(frmThisForm As VB.Form, Optional intCenterMode As Integer = 0, Optional lngWindowWidth As Long = -1, Optional lngWindowHeight As Long = -1, Optional boolSizeAndCenterOnlyOncePerProgramSession As Boolean = True, Optional intDualMonitorToUse As Integer = -1)
+ ' Sub revision 1.2
+
+ ' Center Mode uses one of the following:
+ ' Public Const cWindowExactCenter = 0
+ ' Public Const cWindowUpperThird = 1
+ ' Public Const cWindowLowerThird = 2
+ ' Public Const cWindowMiddleLeft = 3
+ ' Public Const cWindowMiddleRight = 4
+ ' Public Const cWindowTopCenter = 5
+ ' Public Const cWindowBottomCenter = 6
+ ' Public Const cWindowBottomRight = 7
+ ' Public Const cWindowBottomLeft = 8
+ ' Public Const cWindowTopRight = 9
+ ' Public Const cWindowTopLeft = 10
+
+ ' This sub routine properly recognizes dual monitors, centering the form to just one monitor
+
+ ' lngWindowWidth and lngWindowHeight are in twips (there are 15 twips in one pixel)
+ ' intDualMonitorToUse can be 0 or 1, signifying the first or second monitor
+ ' boolSizeAndCenterOnlyOncePerProgramSession is useful when the SizeAndCenterWindow sub is called from the Form_Activate sub of a form
+ ' Note: It is suggested that this be set to false if called from Form_Load in case the user closes the form (thus unloading it)
+
+ Const MAX_RESIZE_FORMS_TO_REMEMBER = 100
+ Dim lngWindowAreaWidth As Long, lngWindowAreaHeight As Long, dblAspectRatio As Double
+ Dim lngWorkingAreaWidth As Long, lngWorkingAreaHeight As Long
+ Dim boolDualMonitor As Boolean, boolHorizontalDual As Boolean
+ Dim lngWindowTopToSet As Long, lngWindowLeftToSet As Long
+ Dim frmMainAppForm As VB.Form
+ Static strFormsCentered(MAX_RESIZE_FORMS_TO_REMEMBER) As String ' 0-based array
+ Static intFormsCenteredCount As Integer
+ Dim boolSubCalledPreviously As Boolean, intIndex As Integer
+
+ ' See if the form has already called this sub
+ ' If not, add to strFormsCentered()
+ boolSubCalledPreviously = False
+ For intIndex = 0 To intFormsCenteredCount - 1
+ If strFormsCentered(intIndex) = frmThisForm.Name Then
+ boolSubCalledPreviously = True
+ Exit For
+ End If
+ Next intIndex
+
+ If Not boolSubCalledPreviously Then
+ ' First time sub called this sub
+ ' Add to strFormsCentered()
+ If intFormsCenteredCount < MAX_RESIZE_FORMS_TO_REMEMBER Then
+ intFormsCenteredCount = intFormsCenteredCount + 1
+ strFormsCentered(intFormsCenteredCount - 1) = frmThisForm.Name
+ Else
+ Debug.Assert False
+ End If
+ End If
+
+ ' If form called previously and boolSizeAndCenterOnlyOncePerProgramSessionis true, then exit sub
+ If boolSizeAndCenterOnlyOncePerProgramSession And boolSubCalledPreviously Then
+ Exit Sub
+ End If
+
+ ' Resize Window
+ With frmThisForm
+ .WindowState = vbNormal
+ If lngWindowWidth > 0 Then .Width = lngWindowWidth
+ If lngWindowHeight > 0 Then .Height = lngWindowHeight
+ End With
+
+ ' Assume the first form loaded is the main form
+ ' May need to be customized if ported to other applications
+ Set frmMainAppForm = Forms(0)
+
+ ' Find the desktop area (width and height)
+ lngWindowAreaWidth = Screen.Width
+ lngWindowAreaHeight = Screen.Height
+
+ ' Check the aspect ratio of WindowAreaWidth / WindowAreaHeight
+ If lngWindowAreaHeight > 0 Then
+ dblAspectRatio = lngWindowAreaWidth / lngWindowAreaHeight
+ Else
+ dblAspectRatio = 1.333
+ End If
+
+ ' Typical desktop areas and aspect ratios
+ ' Normal Desktops have aspect ratios of 1.33 or 1.5
+ ' HDTV desktops have an aspect ratio of 1.6 or 1.7
+ ' Horizontal Dual Monitors have an aspect ratio of 2.66 or 2.5
+ ' Vertical Dual Monitors have an aspectr ratio of 0.67 or 0.62
+
+ ' Determine if using dual monitors
+ If dblAspectRatio < 1 Or dblAspectRatio > 2 Then
+ boolDualMonitor = True
+ If dblAspectRatio > 2 Then
+ ' Aspect ratio greater than 2 - using horizontal dual monitors
+ boolHorizontalDual = True
+ lngWorkingAreaWidth = Screen.Width / 2
+ lngWorkingAreaHeight = Screen.Height
+
+ If frmMainAppForm.Left > lngWorkingAreaWidth Then
+ ' Main app window on second monitor
+ ' Set intDualMonitorToUse if not explicitly set
+ If intDualMonitorToUse < 0 Then
+ intDualMonitorToUse = 1
+ End If
+ End If
+ Else
+ ' Aspect ratio must be less than 1 - using vertical dual monitors
+ boolHorizontalDual = False
+ lngWorkingAreaWidth = Screen.Width
+ lngWorkingAreaHeight = Screen.Height / 2
+
+ If frmMainAppForm.Top > lngWorkingAreaHeight Then
+ ' Main app window on second monitor
+ ' Set intDualMonitorToUse if not explicitly set
+ If intDualMonitorToUse < 0 Then
+ intDualMonitorToUse = 1
+ End If
+ End If
+ End If
+ Else
+ ' Aspect ratio between 1 and 2
+ ' Using a single monitor
+ boolDualMonitor = False
+ lngWorkingAreaWidth = Screen.Width
+ lngWorkingAreaHeight = Screen.Height
+ End If
+
+ With frmThisForm
+ ' Position window
+ Select Case intCenterMode
+ Case cWindowUpperThird
+ lngWindowLeftToSet = (lngWorkingAreaWidth - .Width) \ 2
+ lngWindowTopToSet = (lngWorkingAreaHeight - .Height) \ 3
+ Case cWindowLowerThird
+ lngWindowLeftToSet = (lngWorkingAreaWidth - .Width) \ 2
+ lngWindowTopToSet = (lngWorkingAreaHeight - .Height) * 2 \ 3
+ Case cWindowMiddleLeft
+ lngWindowLeftToSet = 0
+ lngWindowTopToSet = (lngWorkingAreaHeight - .Height) \ 2
+ Case cWindowMiddleRight
+ lngWindowLeftToSet = lngWorkingAreaWidth - .Width
+ lngWindowTopToSet = (lngWorkingAreaHeight - .Height) \ 2
+ Case cWindowTopCenter
+ lngWindowLeftToSet = (lngWorkingAreaWidth - .Width) \ 2
+ lngWindowTopToSet = 0
+ Case cWindowBottomCenter
+ lngWindowLeftToSet = (lngWorkingAreaWidth - .Width) \ 2
+ lngWindowTopToSet = lngWorkingAreaHeight - .Height - 500
+ Case cWindowBottomRight
+ lngWindowLeftToSet = lngWorkingAreaWidth - .Width
+ lngWindowTopToSet = lngWorkingAreaHeight - .Height - 500
+ Case cWindowBottomLeft
+ lngWindowLeftToSet = 0
+ lngWindowTopToSet = lngWorkingAreaHeight - .Height - 500
+ Case cWindowTopRight
+ lngWindowLeftToSet = lngWorkingAreaWidth - .Width
+ lngWindowTopToSet = 0
+ Case cWindowTopLeft
+ lngWindowLeftToSet = 0
+ lngWindowTopToSet = 0
+ Case Else ' Includes cWindowExactCenter = 0
+ lngWindowLeftToSet = (lngWorkingAreaWidth - .Width) \ 2
+ lngWindowTopToSet = (lngWorkingAreaHeight - .Height) \ 2
+ End Select
+
+ ' Move to second monitor if explicitly stated or if the main window is already on the second monitor
+ If boolDualMonitor And intDualMonitorToUse > 0 Then
+ ' Place window on second monitor
+ If boolHorizontalDual Then
+ ' Horizontal dual - Shift to the right
+ lngWindowLeftToSet = lngWindowLeftToSet + lngWorkingAreaWidth
+ Else
+ ' Vertical dual - Shift down
+ lngWindowTopToSet = lngWindowTopToSet + lngWorkingAreaHeight
+ End If
+ End If
+
+ ' Actually position the window
+ .Move lngWindowLeftToSet, lngWindowTopToSet
+ End With
+
+End Sub
+
+Public Function SpacePad(strWork As String, intLength As Integer) As String
+ ' Adds spaces to strWork until the length = intLength
+
+ Do While Len(strWork) < intLength
+ strWork = strWork & " "
+ Loop
+ SpacePad = strWork
+End Function
+
+Public Function SpacePadToFront(strWork As String, intLength As Integer) As String
+ ' Adds spaces to the beginning of strWork until the length = intLength
+
+ Do While Len(strWork) < intLength
+ strWork = " " & strWork
+ Loop
+ SpacePadToFront = strWork
+End Function
+
+Public Function StringToNumber(ByVal strWork As String, Optional ByRef intNumLength As Integer, Optional ByRef intErrorCode As Integer, Optional blnAllowMinusSign As Boolean = False, Optional blnAllowPlusSign As Boolean = False, Optional blnAllowESymbol As Boolean = False, Optional blnMultipleDecimalPointIsError As Boolean = True, Optional ByVal strDecimalPointSymbol As String = ".") As Double
+ ' Looks for a number at the start of strWork and returns it if found
+ ' strWork can contain non-numeric characters after the number; only the number will be returned
+ ' intNumLength returns the length of the number, including the decimal point and any negative sign or E symbol
+ ' When blnAllowESymbol = True, then looks for exponential numbers, like 3.23E+04 or 2.48E-084
+ ' If an error is found or no number is present, then 0 is returned and intNumLength is set to 0, and intErrorCode is assigned the error code:
+ ' 0 = No Error
+ ' -1 = No number
+ ' -3 = No number at all or (more likely) no number after decimal point
+ ' -4 = More than one decimal point
+
+ ' Examples:
+ ' 23Text Returns 23 and intNumLength = 2
+ ' 23.432Text Returns 23.432 and intNumLength = 6
+ ' .3Text Returns 0.3 and intNumLength = 2
+ ' 0.3Text Returns 0.3 and intNumLength = 3
+ ' 3Text Returns 3 and intNumLength = 1
+ ' 3.Text Returns 3 and intNumLength = 2
+ ' Text Returns 0 and intNumLength = 0 and intErrorCode = -3
+ ' .Text Returns 0 and intNumLength = 0 and intErrorCode = -3
+ ' 4.23.Text Returns 0 and intNumLength = 0 and intErrorCode = -4 (must have blnMultipleDecimalPointIsError = True)
+ ' -43Text Returns -43 and intNumLength = 2 (must have blnAllowMinusSign = True)
+ ' 32E+48Text Returns 32E+48 and intNumLength = 6 (must have blnAllowESymbol = True)
+
+ Dim strTestChar As String
+ Dim strFoundNum As String, intIndex As Integer, intDecPtCount As Integer
+ Dim blnNumberFound As Boolean, blnESymbolFound As Boolean
+
+ If strDecimalPointSymbol = "" Then
+ strDecimalPointSymbol = DetermineDecimalPoint()
+ End If
+
+ ' Set intNumLength to -1 for now
+ ' If it doesn't get set to 0 (due to an error), it will get set to the
+ ' length of the matched number before exiting the sub
+ intNumLength = -1
+
+ If Len(strWork) > 0 Then
+ strFoundNum = Left(strWork, 1)
+ If IsNumeric(strFoundNum) Then
+ blnNumberFound = True
+ ElseIf strFoundNum = strDecimalPointSymbol Then
+ blnNumberFound = True
+ intDecPtCount = intDecPtCount + 1
+ ElseIf (strFoundNum = "-" And blnAllowMinusSign) Then
+ blnNumberFound = True
+ ElseIf (strFoundNum = "+" And blnAllowPlusSign) Then
+ blnNumberFound = True
+ End If
+ End If
+
+ If blnNumberFound Then
+ ' Start of string is a number or a decimal point, or (if allowed) a negative or plus sign
+ ' Continue looking
+
+ intIndex = 2
+ Do While intIndex <= Len(strWork)
+ strTestChar = Mid(strWork, intIndex, 1)
+ If IsNumeric(strTestChar) Then
+ strFoundNum = strFoundNum & strTestChar
+ ElseIf strTestChar = strDecimalPointSymbol Then
+ intDecPtCount = intDecPtCount + 1
+ If intDecPtCount = 1 Then
+ strFoundNum = strFoundNum & strTestChar
+ Else
+ Exit Do
+ End If
+ ElseIf (UCase(strTestChar) = "E" And blnAllowESymbol) Then
+ ' E symbol found; only add to strFoundNum if followed by a + and a number,
+ ' a - and a number, or another number
+ strTestChar = Mid(strWork, intIndex + 1, 1)
+ If IsNumeric(strTestChar) Then
+ strFoundNum = strFoundNum & "E" & strTestChar
+ intIndex = intIndex + 2
+ blnESymbolFound = True
+ ElseIf strTestChar = "+" Or strTestChar = "-" Then
+ If IsNumeric(Mid(strWork, intIndex + 2, 1)) Then
+ strFoundNum = strFoundNum & "E" & strTestChar & Mid(strWork, intIndex + 2, 1)
+ intIndex = intIndex + 3
+ blnESymbolFound = True
+ End If
+ End If
+
+ If blnESymbolFound Then
+ ' Continue looking for numbers after the E symbol
+ ' However, only allow pure numbers; not + or - or .
+
+ Do While intIndex <= Len(strWork)
+ strTestChar = Mid(strWork, intIndex, 1)
+ If IsNumeric(strTestChar) Then
+ strFoundNum = strFoundNum & strTestChar
+ ElseIf strTestChar = strDecimalPointSymbol Then
+ If blnMultipleDecimalPointIsError Then
+ ' Set this to 2 to force the multiple decimal point error to appear
+ intDecPtCount = 2
+ End If
+ Exit Do
+ Else
+ Exit Do
+ End If
+ intIndex = intIndex + 1
+ Loop
+ End If
+
+ Exit Do
+ Else
+ Exit Do
+ End If
+ intIndex = intIndex + 1
+ Loop
+
+ If intDecPtCount > 1 And blnMultipleDecimalPointIsError Then
+ ' Too many decimal points
+ intNumLength = 0 ' No number found
+ intErrorCode = -4
+ StringToNumber = 0
+ ElseIf Len(strFoundNum) = 0 Or strFoundNum = strDecimalPointSymbol Then
+ ' No number at all or (more likely) no number after decimal point
+ intNumLength = 0 ' No number found
+ intErrorCode = -3
+ StringToNumber = 0
+ Else
+ ' All is fine
+ intNumLength = Len(strFoundNum)
+ intErrorCode = 0
+ StringToNumber = CDblSafe(strFoundNum)
+ End If
+ Else
+ intNumLength = 0 ' No number found
+ intErrorCode = -1
+ StringToNumber = 0
+ End If
+
+End Function
+
+Public Function StripChrZero(ByRef DataString As String) As String
+ Dim intCharLoc As Integer
+
+ intCharLoc = InStr(DataString, Chr(0))
+ If intCharLoc > 0 Then
+ DataString = Left(DataString, intCharLoc - 1)
+ End If
+ StripChrZero = DataString
+
+End Function
+
+Public Function StripFullPath(ByVal strFilePathIn As String, Optional ByRef strStrippedPath As String) As String
+ ' Removes all path info from strFilePathIn, returning just the filename
+ ' The path of the file is returned in strStrippedPath (including the trailing \)
+
+ Dim fso As New FileSystemObject
+
+ strStrippedPath = fso.GetParentFolderName(strFilePathIn)
+ If Right(strStrippedPath, 1) <> "\" And Right(strStrippedPath, 1) <> "/" Then strStrippedPath = strStrippedPath & "\"
+
+ StripFullPath = fso.GetFileName(strFilePathIn)
+
+ Set fso = Nothing
+
+'' Dim intCharLoc As Integer
+''
+'' intCharLoc = InStrRev(strFilePathIn, "\")
+'' If intCharLoc > 0 Then
+'' strStrippedPath = Left(strFilePathIn, intCharLoc)
+'' StripFullPath = Mid(strFilePathIn, intCharLoc + 1)
+'' Else
+'' StripFullPath = strFilePathIn
+'' End If
+
+End Function
+
+Private Sub SwapSingle(ByRef FirstValue As Single, ByRef SecondValue As Single)
+ Dim sngTemp As Single
+ sngTemp = FirstValue
+ FirstValue = SecondValue
+ SecondValue = sngTemp
+End Sub
+
+Public Sub SwapValues(ByRef FirstValue As Variant, ByRef SecondValue As Variant)
+ Dim varTemp As Variant
+ varTemp = FirstValue
+ FirstValue = SecondValue
+ SecondValue = varTemp
+End Sub
+
+Public Sub TextBoxKeyPressHandler(txtThisTextBox As TextBox, ByRef KeyAscii As Integer, Optional AllowNumbers As Boolean = True, Optional AllowDecimalPoint As Boolean = False, Optional AllowNegativeSign As Boolean = False, Optional AllowCharacters As Boolean = False, Optional AllowPlusSign As Boolean = False, Optional AllowUnderscore As Boolean = False, Optional AllowDollarSign As Boolean = False, Optional AllowEmailChars As Boolean = False, Optional AllowSpaces As Boolean = False, Optional AllowECharacter As Boolean = False, Optional boolAllowCutCopyPaste As Boolean = True)
+ ' Note that the AllowECharacter option has been added to allow the
+ ' user to type numbers in scientific notation
+
+ ' Checks KeyAscii to see if it's valid
+ ' If it isn't, it is set to 0
+
+ Select Case KeyAscii
+ Case 1
+ ' Ctrl+A -- Highlight entire text box
+ txtThisTextBox.SelStart = 0
+ txtThisTextBox.SelLength = Len(txtThisTextBox.Text)
+ KeyAscii = 0
+ Case 24, 3, 22
+ ' Cut, copy, paste, or delete was pressed; let the command occur
+ If Not boolAllowCutCopyPaste Then KeyAscii = 0
+ Case 26
+ ' Ctrl+Z = Undo
+ KeyAscii = 0
+ txtThisTextBox.Text = mTextBoxValueSaved
+ Case 8
+ ' Backspace is allowed
+ Case 48 To 57: If Not AllowNumbers Then KeyAscii = 0
+ Case 32: If Not AllowSpaces Then KeyAscii = 0
+ Case 36: If Not AllowDollarSign Then KeyAscii = 0
+ Case 43: If Not AllowPlusSign Then KeyAscii = 0
+ Case 45: If Not AllowNegativeSign Then KeyAscii = 0
+ Case 44, 46:
+ Select Case glbDecimalSeparator
+ Case ","
+ If KeyAscii = 46 Then KeyAscii = 0
+ Case Else ' includes "."
+ If KeyAscii = 44 Then KeyAscii = 0
+ End Select
+ If Not AllowDecimalPoint Then KeyAscii = 0
+ Case 64: If Not AllowEmailChars Then KeyAscii = 0
+ Case 65 To 90, 97 To 122
+ If Not AllowCharacters Then
+ If Not AllowECharacter Then
+ KeyAscii = 0
+ Else
+ If KeyAscii = 69 Or KeyAscii = 101 Then
+ KeyAscii = 69
+ Else
+ KeyAscii = 0
+ End If
+ End If
+ End If
+ Case 95: If Not AllowUnderscore Then KeyAscii = 0
+ Case Else
+ KeyAscii = 0
+ End Select
+
+End Sub
+
+Public Sub TextBoxGotFocusHandler(txtThisTextBox As VB.TextBox, Optional blnSelectAll As Boolean = True)
+ ' Selects the text in the given textbox if blnSelectAll = true
+ ' Stores the current textbox value in mTextBoxValueSaved
+
+ If blnSelectAll Then
+ txtThisTextBox.SelStart = 0
+ txtThisTextBox.SelLength = Len(txtThisTextBox.Text)
+ End If
+
+ SetMostRecentTextBoxValue txtThisTextBox.Text
+End Sub
+
+Public Function TrimFileName(strFilePath As String) As String
+ ' Examines strFilePath, looking from the right for a \
+ ' If found, returns only the portion after \
+ ' Otherwise, returns the enter string
+ Dim lngLastSlashLoc As Long
+ Dim strTrimmedPath As String
+
+ lngLastSlashLoc = InStrRev(strFilePath, "\")
+
+ If lngLastSlashLoc > 0 Then
+ strTrimmedPath = Mid(strFilePath, lngLastSlashLoc + 1)
+ Else
+ strTrimmedPath = strFilePath
+ End If
+
+ TrimFileName = strTrimmedPath
+End Function
+
+Public Sub UnloadAllForms(strCallingFormName As String)
+
+ Dim frmThisForm As VB.Form
+ ' Unload all the other forms
+ For Each frmThisForm In Forms
+ If frmThisForm.Name <> strCallingFormName Then
+ Unload frmThisForm
+ End If
+ Next
+
+ ' If all the other forms did not unload, then the following will be false and
+ ' the program will break. Force the application to end.
+ Debug.Assert Forms.Count = 1
+ If Forms.Count > 1 Then
+ 'End
+ End If
+
+End Sub
+
+Public Function ValidateDualTextBoxes(txtFirstTextBox As TextBox, txtSecondTextBox As TextBox, boolFavorFirstTextBox As Boolean, dblLowerBound As Double, dblUpperBound As Double, Optional dblDefaultSeparationAmount As Double = 1) As Boolean
+
+ ' Makes sure txtFirstTextBox is less than or equal to txtSecondTextBox
+ ' Returns True if all is OK; returns False if one of the textboxes had to be corrected
+
+ Dim blnTextboxUpdated As Boolean
+
+ If dblUpperBound > 0 Then
+ If boolFavorFirstTextBox Then
+ If Val(txtFirstTextBox) > Val(txtSecondTextBox) Then
+ txtSecondTextBox = CStr(Val(txtFirstTextBox) + dblDefaultSeparationAmount)
+ blnTextboxUpdated = True
+ End If
+ Else
+ If Val(txtFirstTextBox) > Val(txtSecondTextBox) Then
+ txtFirstTextBox = CStr(Val(txtSecondTextBox) - dblDefaultSeparationAmount)
+ blnTextboxUpdated = True
+ End If
+ End If
+
+ If Val(txtSecondTextBox) > dblUpperBound Then
+ txtSecondTextBox = Format(dblUpperBound, "0.00")
+ blnTextboxUpdated = True
+ End If
+ If Val(txtFirstTextBox) < dblLowerBound Then
+ txtFirstTextBox = Format(dblLowerBound, "0.00")
+ blnTextboxUpdated = True
+ End If
+
+ If boolFavorFirstTextBox Then
+ blnTextboxUpdated = Not ValidateDualTextBoxes(txtFirstTextBox, txtSecondTextBox, False, dblLowerBound, dblUpperBound)
+ End If
+ End If
+
+ ValidateDualTextBoxes = Not blnTextboxUpdated
+
+End Function
+
+Public Function ValidateTextboxValueLng(txtThisTextControl As TextBox, lngMinimumVal As Long, lngMaximumVal As Long, lngdefaultVal As Long) As Long
+ If Val(txtThisTextControl) < lngMinimumVal Or Val(txtThisTextControl) > lngMaximumVal Or Not IsNumeric(txtThisTextControl) Then
+ txtThisTextControl = Trim(Str(lngdefaultVal))
+ End If
+ ValidateTextboxValueLng = Val(txtThisTextControl)
+End Function
+
+Public Function ValidateTextboxValueDbl(txtThisTextControl As TextBox, dblMinimumVal As Double, dblMaximumVal As Double, dbldefaultVal As Double) As Double
+ If Val(txtThisTextControl) < dblMinimumVal Or Val(txtThisTextControl) > dblMaximumVal Or Not IsNumeric(txtThisTextControl) Then
+ txtThisTextControl = Trim(Str(dbldefaultVal))
+ End If
+ ValidateTextboxValueDbl = Val(txtThisTextControl)
+End Function
+
+Public Function ValidateValueDbl(ByRef dblThisValue As Double, dblMinimumVal As Double, dblMaximumVal As Double, dbldefaultVal As Double) As Double
+ If dblThisValue < dblMinimumVal Or dblThisValue > dblMaximumVal Then
+ dblThisValue = dbldefaultVal
+ End If
+
+ ValidateValueDbl = dblThisValue
+End Function
+
+Public Function ValidateValueLng(ByRef lngThisValue As Long, lngMinimumVal As Long, lngMaximumVal As Long, lngdefaultVal As Long) As Long
+ If lngThisValue < lngMinimumVal Or lngThisValue > lngMaximumVal Then
+ lngThisValue = lngdefaultVal
+ End If
+
+ ValidateValueLng = lngThisValue
+End Function
+
+Private Function VerifySort(sngArray() As Single, lngLowIndex As Long, lngHighIndex As Long) As Boolean
+ Dim blnInOrder As Boolean
+ Dim lngIndex As Long
+
+ blnInOrder = True
+
+ For lngIndex = lngLowIndex To lngHighIndex - 1
+ If sngArray(lngIndex) > sngArray(lngIndex + 1) Then
+ blnInOrder = False
+ Exit For
+ End If
+ Next lngIndex
+
+ VerifySort = blnInOrder
+End Function
+
+Public Sub VerifyValidWindowPos(frmThisForm As VB.Form, Optional lngMinWidth As Long = 500, Optional lngMinHeight As Long = 500, Optional MinVisibleFormArea As Long = 500)
+ ' Make sure the window isn't too small and is visible on the desktop
+
+ Dim lngReturn As Long
+ Dim lngScreenWidth As Long, lngScreenHeight As Long
+
+ lngReturn = GetDesktopSize(lngScreenHeight, lngScreenWidth, True)
+
+ If lngScreenHeight < Screen.Height Then lngScreenHeight = Screen.Height
+ If lngScreenWidth < Screen.Width Then lngScreenWidth = Screen.Width
+
+ On Error GoTo VerifyValidWindowPosErrorHandler
+ With frmThisForm
+ If .WindowState = vbMinimized Then
+ .WindowState = vbNormal
+ End If
+
+ If .Width < lngMinWidth Then .Width = lngMinWidth
+ If .Height < lngMinHeight Then .Height = lngMinHeight
+
+ If .Left > lngScreenWidth - MinVisibleFormArea Or _
+ .Top > lngScreenHeight - MinVisibleFormArea Or _
+ .Left < 0 Or .Top < 0 Then
+ SizeAndCenterWindow frmThisForm, cWindowUpperThird, .Width, .Height, False
+ End If
+ End With
+
+ Exit Sub
+
+VerifyValidWindowPosErrorHandler:
+ ' An error occured
+ ' The form is probably minimized; we'll ignore it
+ Debug.Print "Error occured in VerifyValidWindowPos: " & Err.Description
+
+End Sub
+
+Public Sub WindowStayOnTop(hwnd As Long, boolStayOnTop As Boolean, Optional lngFormPosLeft As Long = 0, Optional lngFormPosTop As Long = 0, Optional lngFormPosWidth As Long = 600, Optional lngFormPosHeight As Long = 500)
+ ' Toggles the behavior of the given window to "stay on top" of all other windows
+ ' The new form sizes (lngFormPosLeft, lngFormPosTop, lngFormPosWidth, lngFormPosHeight)
+ ' are in pixels
+
+ Dim lngTopMostSwitch As Long
+
+ If boolStayOnTop Then
+ ' Turn on the TopMost attribute.
+ lngTopMostSwitch = conHwndTopmost
+ Else
+ ' Turn off the TopMost attribute.
+ lngTopMostSwitch = conHwndNoTopmost
+ End If
+
+ SetWindowPos hwnd, lngTopMostSwitch, lngFormPosLeft, lngFormPosTop, lngFormPosWidth, lngFormPosHeight, conSwpNoActivate Or conSwpShowWindow
+End Sub
+
+Public Function YesNoBox(strMessage As String, strTitle As String) As VbMsgBoxResult
+ ' Displays a Message Box with OK/Cancel buttons (i.e. yes/no)
+ ' uses vbDefaultButton2 to make sure No or Cancel is the default button
+
+ Dim DialogType As Integer
+
+ ' The dialog box should have Yes and No buttons,
+ ' and a question icon.
+ DialogType = vbYesNo + vbQuestion + vbDefaultButton2
+
+ ' Display the dialog box and get user's response.
+ YesNoBox = MsgBox(strMessage, DialogType, strTitle)
+End Function
+
diff --git a/TestSeqForHelpFile.seq b/TestSeqForHelpFile.seq
new file mode 100644
index 0000000..825adc2
--- /dev/null
+++ b/TestSeqForHelpFile.seq
@@ -0,0 +1,61 @@
+; Molecular Weight Calculator Sequence Information File
+FragModelNotationMode=0
+FragModelSequence=YLLR
+FragModelNTerminus=0
+FragModelCTerminus=0
+FragModelIonType0=1
+FragModelIonType1=1
+FragModelIonType2=1
+FragModelIonsToModify0=0
+FragModelIonsToModify1=1
+FragModelIonsToModify2=1
+FragModelWaterLoss=1
+FragModelAmmoniaLoss=0
+FragModelDoubleCharge=0
+FragModelDoubleChargeThreshold=8
+FragModelPrecursorIonRemove=1
+FragModelPrecursorIonMass=480.63
+FragModelPrecursorIonMassWindow=2
+FragModelIonMatchWindow=0.5
+FragModelIonIntensity0=10
+FragModelIonIntensity1=50
+FragModelIonIntensity2=50
+FragModelShoulderIntensity=25
+FragModelNeutralLossIntensity=10
+FragModelGroupIons=0
+FragModelGroupIonsMassWindow=0.5
+FragModelNormalizedIntensity=100
+FragModelNormalizationIonsUseCount=200
+FragModelNormalizationMassRegions=3
+IonPlotType=1
+IonPlotResolution=5000
+IonPlotResolutionXVal=500
+IonPlotGridlinesX=0
+IonPlotGridlinesY=0
+IonPlotTicksX=5
+IonPlotTicksY=5
+IonPlotGaussianQuality=20
+IonPlotApproximationFactor=10
+IonPlotAutoscaleY=1
+IonPlotShowPosition=1
+FragModelIonMatchList=19
+136.08,100
+139.11,28.81
+159.12,57.63
+175.13,62.71
+187.11,62.71
+227.1,13.42
+235.12,8.22
+246.65,29.44
+260.65,64.5
+261.14,16.88
+271.2,7.36
+288.21,27.27
+289.21,7.36
+294.19,100
+379.21,3.51
+384.28,3.51
+390.19,8.7
+401.31,62.04
+402.31,13.54
+FragModelIonMatchListEnd
diff --git a/Unused/MyMsgBox.frm b/Unused/MyMsgBox.frm
new file mode 100644
index 0000000..7e5a6bc
--- /dev/null
+++ b/Unused/MyMsgBox.frm
@@ -0,0 +1,90 @@
+VERSION 5.00
+Begin VB.Form frmMyMsgBox
+ BorderStyle = 3 'Fixed Dialog
+ Caption = "Caption"
+ ClientHeight = 1980
+ ClientLeft = 45
+ ClientTop = 330
+ ClientWidth = 5850
+ Icon = "MyMsgBox.frx":0000
+ LinkTopic = "Form1"
+ MaxButton = 0 'False
+ MinButton = 0 'False
+ ScaleHeight = 1980
+ ScaleWidth = 5850
+ ShowInTaskbar = 0 'False
+ StartUpPosition = 3 'Windows Default
+ Begin VB.CommandButton cmdButton
+ Caption = "Button4"
+ Height = 495
+ HelpContextID = 4002
+ Index = 4
+ Left = 4440
+ TabIndex = 4
+ Tag = "0"
+ Top = 1320
+ Width = 1335
+ End
+ Begin VB.CommandButton cmdButton
+ Caption = "Button3"
+ Height = 495
+ HelpContextID = 4002
+ Index = 3
+ Left = 3000
+ TabIndex = 3
+ Tag = "0"
+ Top = 1320
+ Width = 1335
+ End
+ Begin VB.CommandButton cmdButton
+ Caption = "Button2"
+ Height = 495
+ HelpContextID = 4002
+ Index = 2
+ Left = 1560
+ TabIndex = 2
+ Tag = "0"
+ Top = 1320
+ Width = 1335
+ End
+ Begin VB.CommandButton cmdButton
+ Caption = "Button1"
+ Default = -1 'True
+ Height = 495
+ HelpContextID = 4002
+ Index = 1
+ Left = 120
+ TabIndex = 0
+ Tag = "0"
+ Top = 1320
+ Width = 1335
+ End
+ Begin VB.Label lblMessage
+ Caption = "Message"
+ Height = 975
+ Left = 240
+ TabIndex = 1
+ Top = 120
+ Width = 4095
+ End
+End
+Attribute VB_Name = "frmMyMsgBox"
+Attribute VB_GlobalNameSpace = False
+Attribute VB_Creatable = False
+Attribute VB_PredeclaredId = True
+Attribute VB_Exposed = False
+Option Explicit
+
+Private Sub cmdButton_Click(Index As Integer)
+ Me.Tag = Trim(Str(Index))
+ Me.Hide
+
+End Sub
+
+Private Sub Form_Load()
+ ' Put window in upper center of screen
+ ' Do Not Use SizeAndCenterWindow since the MyMsgBox function repositions this form
+ Me.Width = 4600
+ Me.Height = 2400
+
+End Sub
diff --git a/Unused/Progress.frm b/Unused/Progress.frm
new file mode 100644
index 0000000..6118898
--- /dev/null
+++ b/Unused/Progress.frm
@@ -0,0 +1,270 @@
+VERSION 5.00
+Begin VB.Form frmProgress
+ BorderStyle = 3 'Fixed Dialog
+ Caption = "Progress"
+ ClientHeight = 2580
+ ClientLeft = 45
+ ClientTop = 330
+ ClientWidth = 3105
+ Icon = "Progress.frx":0000
+ KeyPreview = -1 'True
+ LinkTopic = "Form1"
+ MaxButton = 0 'False
+ MinButton = 0 'False
+ ScaleHeight = 2580
+ ScaleWidth = 3105
+ ShowInTaskbar = 0 'False
+ StartUpPosition = 3 'Windows Default
+ Tag = "14700"
+ Begin VB.CommandButton cmdPause
+ Caption = "Click to Pause"
+ Height = 375
+ Left = 480
+ TabIndex = 4
+ Tag = "14710"
+ Top = 1800
+ Width = 1815
+ End
+ Begin VB.Timer tmrDelayTimer
+ Enabled = 0 'False
+ Left = 2400
+ Top = 1680
+ End
+ Begin VB.Shape pbarProgress
+ BackColor = &H80000002&
+ FillColor = &H80000002&
+ FillStyle = 0 'Solid
+ Height = 255
+ Left = 120
+ Top = 1200
+ Width = 1215
+ End
+ Begin VB.Shape pbarBox
+ Height = 255
+ Left = 120
+ Top = 1200
+ Width = 2775
+ End
+ Begin VB.Label lblCurrentSubTask
+ Height = 375
+ Left = 120
+ TabIndex = 3
+ Top = 600
+ Width = 2655
+ End
+ Begin VB.Label lblTimeStats
+ Caption = "Elapsed/remaining time"
+ Height = 255
+ Left = 120
+ TabIndex = 2
+ Top = 1515
+ Width = 3015
+ End
+ Begin VB.Label lblPressEscape
+ Alignment = 2 'Center
+ Caption = "(Press Escape to abort)"
+ Height = 255
+ Left = 120
+ TabIndex = 1
+ Tag = "14730"
+ Top = 2280
+ Width = 2655
+ End
+ Begin VB.Label lblCurrentTask
+ Caption = "Current task"
+ Height = 375
+ Left = 120
+ TabIndex = 0
+ Top = 120
+ Width = 2655
+ End
+End
+Attribute VB_Name = "frmProgress"
+Attribute VB_GlobalNameSpace = False
+Attribute VB_Creatable = False
+Attribute VB_PredeclaredId = True
+Attribute VB_Exposed = False
+Option Explicit
+
+
+Private DelayTimerIntervalCount As Integer
+Private intPauseStatus As Integer
+
+Private lngProgressMin As Long
+Private lngProgressMax As Long
+
+Private Const cUnpaused = 0
+Private Const cRequestPause = 1
+Private Const cPaused = 2
+Private Const cRequestUnpause = 3
+
+Private Sub CheckForPauseUnpause()
+
+ Select Case intPauseStatus
+ Case cRequestPause
+ cmdPause.Caption = LookupLanguageCaption(14720, "Paused")
+ intPauseStatus = cPaused
+ Me.MousePointer = vbNormal
+ Do
+ WasteTime 100
+ DoEvents
+ Loop While intPauseStatus = cPaused
+ intPauseStatus = cUnpaused
+ cmdPause.Caption = LookupLanguageCaption(14710, "Click to Pause")
+ Me.MousePointer = vbHourglass
+ Case cRequestUnpause
+ intPauseStatus = cUnpaused
+ Case Else
+ ' Nothing to pause or unpause
+ End Select
+
+End Sub
+
+Public Sub InitializeForm(CurrentTask As String, ByVal ProgressBarMinNew As Long, ByVal ProgressBarMaxNew As Long, Optional boolShowTimeStats As Boolean = False)
+ If ProgressBarMinNew < 0 Then ProgressBarMinNew = 0
+ If ProgressBarMinNew > ProgressBarMaxNew Then ProgressBarMaxNew = ProgressBarMinNew + 1
+
+ lblCurrentTask.Caption = CurrentTask
+ lblCurrentSubTask = ""
+
+ lngProgressMin = ProgressBarMinNew
+ lngProgressMax = ProgressBarMaxNew
+
+ If lngProgressMin < 0 Then lngProgressMin = 0
+ If lngProgressMax <= lngProgressMin Then lngProgressMax = lngProgressMin + 1
+
+ lblTimeStats.Visible = boolShowTimeStats
+
+ UpdateProgressBar ProgressBarMinNew, True
+
+ KeyPressAbortProcess = 0
+
+ frmProgress.Show
+ frmProgress.MousePointer = vbHourglass
+
+End Sub
+
+Public Sub UpdateProgressBar(ByVal NewValue As Long, Optional ResetStartTime As Boolean = False)
+
+ Static StartTime As Double
+ Static StopTime As Double
+
+ Dim MinutesElapsed As Currency, MinutesTotal As Currency, MinutesRemaining As Currency
+ Dim dblRatioCompleted As Double, lngNewWidth As Long
+
+ If ResetStartTime Then
+ StartTime = Now()
+ End If
+
+ If NewValue < lngProgressMin Then NewValue = lngProgressMin
+ If NewValue > lngProgressMax Then NewValue = lngProgressMax
+
+ If lngProgressMax > 0 Then
+ dblRatioCompleted = (NewValue - lngProgressMin) / lngProgressMax
+ Else
+ dblRatioCompleted = 0
+ End If
+ If dblRatioCompleted < 0 Then dblRatioCompleted = 0
+ If dblRatioCompleted > 1 Then dblRatioCompleted = 1
+ pbarProgress.Width = pbarBox.Width * dblRatioCompleted
+
+ On Error GoTo ExitUpdateProgressBarFunction
+
+ StopTime = Now()
+ MinutesElapsed = (StopTime - StartTime) * 1440
+ If dblRatioCompleted <> 0 Then
+ MinutesTotal = MinutesElapsed / dblRatioCompleted
+ Else
+ MinutesTotal = 0
+ End If
+ MinutesRemaining = MinutesTotal - MinutesElapsed
+ lblTimeStats = Format(MinutesElapsed, "0.00") & " : " & Format(MinutesRemaining, "0.00 ") & LookupLanguageCaption(14740, "min. elapsed/remaining")
+
+ CheckForPauseUnpause
+
+ DoEvents
+
+ExitUpdateProgressBarFunction:
+
+End Sub
+
+Public Sub UpdateCurrentTask(strNewTask As String)
+ lblCurrentTask = strNewTask
+
+ CheckForPauseUnpause
+
+ DoEvents
+End Sub
+
+Public Sub UpdateCurrentSubTask(strNewSubTask As String)
+ lblCurrentSubTask = strNewSubTask
+
+ CheckForPauseUnpause
+
+ DoEvents
+End Sub
+
+Public Sub WasteTime(Optional Milliseconds As Integer = 250)
+ ' Wait the specified number of milliseconds
+
+ Const Default_Interval = 10
+
+ Dim dblStopCount As Double
+
+ With frmProgress
+ DelayTimerIntervalCount = 0
+
+ .tmrDelayTimer.Interval = Default_Interval
+ .tmrDelayTimer.Enabled = True
+
+ dblStopCount = Milliseconds / Default_Interval
+ Do While DelayTimerIntervalCount < dblStopCount
+ DoEvents
+ Loop
+ .tmrDelayTimer.Enabled = False
+
+ End With
+
+End Sub
+
+Private Sub cmdPause_Click()
+ Select Case intPauseStatus
+ Case cUnpaused
+ intPauseStatus = cRequestPause
+ cmdPause.Caption = LookupLanguageCaption(14715, "Preparing to Pause")
+ DoEvents
+ Case cPaused
+ intPauseStatus = cRequestUnpause
+ cmdPause.Caption = LookupLanguageCaption(14725, "Resuming")
+ DoEvents
+ Case Else
+ ' Ignore click
+ End Select
+
+End Sub
+
+Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
+ If KeyCode = vbKeyEscape Then
+ KeyPressAbortProcess = 2
+ KeyCode = 0
+ Shift = 0
+ End If
+End Sub
+
+Private Sub Form_Load()
+
+ ' Put window in exact center of screen
+ SizeAndCenterWindow Me, cWindowExactCenter, 3200, 3000, False
+
+End Sub
+
+
+Private Sub tmrDelayTimer_Timer()
+ Dim IntervalCount As Integer
+
+ DelayTimerIntervalCount = DelayTimerIntervalCount + 1
+
+ If DelayTimerIntervalCount > 32767 Then DelayTimerIntervalCount = -32767
+End Sub
+
+
diff --git a/Unused/frmMenuIDsAndLabels.frm b/Unused/frmMenuIDsAndLabels.frm
new file mode 100644
index 0000000..b0f3b16
--- /dev/null
+++ b/Unused/frmMenuIDsAndLabels.frm
@@ -0,0 +1,22 @@
+VERSION 5.00
+Begin VB.Form frmMenuIDsAndLabels
+ Caption = "Menu ID's And Labels + Amino Acids"
+ ClientHeight = 4665
+ ClientLeft = 60
+ ClientTop = 345
+ ClientWidth = 4260
+ LinkTopic = "Form1"
+ ScaleHeight = 4665
+ ScaleWidth = 4260
+ StartUpPosition = 3 'Windows Default
+End
+Attribute VB_Name = "frmMenuIDsAndLabels"
+Attribute VB_GlobalNameSpace = False
+Attribute VB_Creatable = False
+Attribute VB_PredeclaredId = True
+Attribute VB_Exposed = False
+Option Explicit
+
+Private Sub Form_Load()
+
+End Sub
diff --git a/Unused/frmReportCompounds.frm b/Unused/frmReportCompounds.frm
new file mode 100644
index 0000000..4c3da11
--- /dev/null
+++ b/Unused/frmReportCompounds.frm
@@ -0,0 +1,64 @@
+VERSION 5.00
+Begin VB.Form frmReportCompounds
+ Caption = "Report Compounds"
+ ClientHeight = 3660
+ ClientLeft = 60
+ ClientTop = 345
+ ClientWidth = 4680
+ Icon = "frmReportCompounds.frx":0000
+ LinkTopic = "Form1"
+ ScaleHeight = 3660
+ ScaleWidth = 4680
+ StartUpPosition = 3 'Windows Default
+ Begin VB.CommandButton cmdCopy
+ Caption = "&Copy"
+ Height = 360
+ HelpContextID = 5000
+ Left = 600
+ TabIndex = 2
+ Top = 3120
+ Width = 1035
+ End
+ Begin VB.CommandButton cmdOK
+ Cancel = -1 'True
+ Caption = "&OK"
+ Default = -1 'True
+ Height = 360
+ HelpContextID = 5000
+ Left = 2160
+ TabIndex = 1
+ Top = 3120
+ Width = 1035
+ End
+ Begin VB.ListBox lstCompounds
+ Height = 2400
+ Left = 480
+ TabIndex = 0
+ Top = 360
+ Width = 3135
+ End
+End
+Attribute VB_Name = "frmReportCompounds"
+Attribute VB_GlobalNameSpace = False
+Attribute VB_Creatable = False
+Attribute VB_PredeclaredId = True
+Attribute VB_Exposed = False
+Option Explicit
+
+Private Sub cmdOK_Click()
+ frmReportCompounds.Hide
+End Sub
+
+Private Sub cmdCopy_Click()
+ Dim copytext$, x%
+
+ Clipboard.Clear
+ copytext$ = ""
+ For x = 0 To lstCompounds.ListCount - 1
+ ' MW not found, copy line to clipboard without any tabs
+ copytext$ = copytext$ & Chr$(13) & Chr$(10) & lstCompounds.List(x)
+ If x > 5000 Then Exit For
+ Next x
+ Clipboard.SetText copytext$
+
+End Sub
diff --git a/batch.txt.out b/batch.txt.out
new file mode 100644
index 0000000..3677ebd
--- /dev/null
+++ b/batch.txt.out
@@ -0,0 +1,113 @@
+; Average Weight Mode Enabled
+; Standard deviations will not be displayed
+; Source formula will be displayed with proper capitalization
+FeCl3-6H2O 270.29478
+
+; Abbreviation expansion now On
+EtOac CH3CH2C2H3O2 88.10512
+; Display of source formula is now Off
+CH3CH2C2H3O2 88.10512
+; Will not display the molecular weight (mass) of each formula
+CH3CH2C2H3O2
+
+; Converting formulas to empirical formulas now On
+H12Cl3FeO6
+C4H8O2
+; Display of source formula is now On
+UreaC4(NH2)4Ca C5H12CaN6O
+
+; 3 letter to 1 letter amino acid symbol conversion now On
+GluGlaPheLeu EUFL
+Val-Ile-Arg VIR
+; Will add a space every 10 amino acids
+; Will only show the converted sequence, not the sequence being converted
+EUFLVIRFYM CVEUEUFLVI RFYMCVEU
+
+; 1 letter to 3 letter amino acid symbol conversion now On
+PheLeuGluGluLeuTyrArg
+MetLeuThrSerCysAspGluGluPhe
+; Will show sequence being converted, in addition to the converted sequence
+; Will separate residues with a dash
+FLEELYR Phe-Leu-Glu-Glu-Leu-Tyr-Arg
+
+; Normal Molecular Weight Mode Enabled (other modes turned Off)
+C4N8OH2 178.112
+
+; One letter Amino Acid weight mode: input formulas are assumed to be peptides in one-letter notation
+H-PheLeuGluGluLeuTyrArg-OH 969.09172
+H-MetLeuThrSerCysAspGluGluPhe-OH 1074.18464
+; Display of source formula is now Off
+1074.18464
+
+; Formula Finder Mode Enabled. Search elements/abbreviations: C, H, N, O, Cl, Bpy
+; Isotopic Weight Mode Enabled
+; FF Maximum Hits set to 5
+; FF Tolerance set to 0.05
+; FF Searching: 403.84
+Compounds found: 0
+
+; FF Searching: 300.58
+Compounds found: 0
+
+; FF Tolerance set to 0.02
+; FF Searching: 403.885
+Compounds found: 0
+
+; FF Maximum Hits set to 10
+; FF Searching: 632.43
+Compounds found: 0
+
+
+; Formula Finder Mode Enabled. Search elements/abbreviations: H, N, Br, Li
+; FF Maximum Hits set to 2
+; FF Searching: 389.32
+Compounds found: 0
+
+; Switching back (this comment is in the source file)
+
+NH2 16.0187232
+C6H5Cl 112.007976
+^13C6H5Cl 118.007976
+
+FeCl3-6H2O 270.29478
+
+
+
+; So is this one, along with the 3 blank lines above
+16.02262
+112.5566
+118.4924
+270.29478
+
+; Verbose mode is now on
+; Delimeter now a Space
+; Source formula will be displayed with proper capitalization
+C6H5Cl 112.5566
+
+; Delimeter now ,
+C6H5Cl,112.5566
+
+; Comments found in the source file will not be written to the output file
+
+; Isotopic Distribution calculations now On
+Isotopic Abundances for CH2(CH2)7CH2Br
+ Mass/Charge Fraction Intensity
+ 205.05919 0.4588825 100.00
+ 206.05919 0.0459075 10.00
+ 207.05919 0.4484460 97.73
+ 208.05919 0.0447120 9.74
+ 209.05919 0.0020020 0.44
+ 210.05919 0.0000528 0.01
+ 211.05919 0.0000017 0.00
+
+; Isotopic Distribution charge set to 2
+Isotopic Abundances for CH2(CH2)7CH2Br
+ Mass/Charge Fraction Intensity
+ 103.03329 0.4588825 100.00
+ 103.53329 0.0459075 10.00
+ 104.03329 0.4484460 97.73
+ 104.53329 0.0447120 9.74
+ 105.03329 0.0020020 0.44
+ 105.53329 0.0000528 0.01
+ 106.03329 0.0000017 0.00
+
diff --git a/frmAminoAcidConverter.frm b/frmAminoAcidConverter.frm
new file mode 100644
index 0000000..a860eb1
--- /dev/null
+++ b/frmAminoAcidConverter.frm
@@ -0,0 +1,430 @@
+VERSION 5.00
+Begin VB.Form frmAminoAcidConverter
+ Caption = "Amino Acid Notation Converter"
+ ClientHeight = 4905
+ ClientLeft = 60
+ ClientTop = 345
+ ClientWidth = 8460
+ HelpContextID = 3055
+ Icon = "frmAminoAcidConverter.frx":0000
+ LinkTopic = "Form1"
+ ScaleHeight = 4905
+ ScaleWidth = 8460
+ StartUpPosition = 3 'Windows Default
+ Tag = "6000"
+ Begin VB.ComboBox cboTargetFormula
+ Height = 315
+ Left = 3960
+ Style = 2 'Dropdown List
+ TabIndex = 10
+ ToolTipText = "Units of amount to convert from or use for molarity calculation"
+ Top = 4320
+ Width = 735
+ End
+ Begin VB.CommandButton cmdCopyToFragmentationModeller
+ Caption = "Copy to &Fragmentation Modeller"
+ Height = 720
+ Left = 120
+ TabIndex = 8
+ Tag = "6060"
+ Top = 4080
+ Width = 1335
+ End
+ Begin VB.CheckBox chkSpaceEvery10
+ Caption = "&Add space every 10 residues"
+ Height = 615
+ Left = 120
+ TabIndex = 5
+ Tag = "6080"
+ Top = 840
+ Value = 1 'Checked
+ Width = 1695
+ End
+ Begin VB.CheckBox chkSeparateWithDash
+ Caption = "&Separate residues with dash"
+ Height = 615
+ Left = 120
+ TabIndex = 7
+ Tag = "6090"
+ Top = 3000
+ Value = 1 'Checked
+ Width = 1695
+ End
+ Begin VB.CommandButton cmdCopy3Letter
+ Caption = "&Copy 3 letter sequence to formula:"
+ Height = 720
+ Left = 2040
+ TabIndex = 9
+ Tag = "6050"
+ Top = 4080
+ Width = 1815
+ End
+ Begin VB.TextBox txt1LetterSequence
+ Height = 1245
+ HelpContextID = 3055
+ Left = 1920
+ MultiLine = -1 'True
+ ScrollBars = 2 'Vertical
+ TabIndex = 0
+ Tag = "6030"
+ Text = "frmAminoAcidConverter.frx":08CA
+ ToolTipText = "Enter sequence using 1 letter abbreviations here"
+ Top = 120
+ Width = 6375
+ End
+ Begin VB.TextBox txt3LetterSequence
+ Height = 1845
+ HelpContextID = 3055
+ Left = 1920
+ MultiLine = -1 'True
+ ScrollBars = 2 'Vertical
+ TabIndex = 3
+ Tag = "6040"
+ Text = "frmAminoAcidConverter.frx":08CC
+ ToolTipText = "Enter sequence using 3 letter abbreviations here"
+ Top = 2160
+ Width = 6375
+ End
+ Begin VB.CommandButton cmdConvertTo3Letter
+ Appearance = 0 'Flat
+ Height = 585
+ Left = 3720
+ Picture = "frmAminoAcidConverter.frx":08D0
+ Style = 1 'Graphical
+ TabIndex = 1
+ Top = 1440
+ Width = 495
+ End
+ Begin VB.CommandButton cmdConvertTo1Letter
+ Height = 600
+ Left = 5520
+ Picture = "frmAminoAcidConverter.frx":0D07
+ Style = 1 'Graphical
+ TabIndex = 2
+ Top = 1440
+ Width = 495
+ End
+ Begin VB.CommandButton cmdClose
+ Cancel = -1 'True
+ Caption = "Cl&ose"
+ Height = 480
+ Left = 7080
+ TabIndex = 11
+ Tag = "4000"
+ Top = 4200
+ Width = 1155
+ End
+ Begin VB.Label lbl1Letter
+ Caption = "One letter-based amino acid sequence"
+ Height = 735
+ Left = 120
+ TabIndex = 4
+ Tag = "6010"
+ Top = 120
+ Width = 1575
+ End
+ Begin VB.Label lbl3Letter
+ Caption = "Three letter-based amino acid sequence"
+ Height = 735
+ Left = 120
+ TabIndex = 6
+ Tag = "6020"
+ Top = 2160
+ Width = 1575
+ End
+End
+Attribute VB_Name = "frmAminoAcidConverter"
+Attribute VB_GlobalNameSpace = False
+Attribute VB_Creatable = False
+Attribute VB_PredeclaredId = True
+Attribute VB_Exposed = False
+Option Explicit
+
+' Purpose: Make sure keystrokes in an Amino-acid containing textbox are valid
+Private Sub AminoAcidTextBoxKeyPressHandler(txtThisTextBox As TextBox, KeyAscii As Integer)
+ ' Checks KeyAscii to see if it's valid
+ ' If it isn't, it is set to 0
+
+ If Not objMwtWin.IsModSymbol(Chr(KeyAscii)) Then
+ Select Case KeyAscii
+ Case 1 ' Ctrl+A -- select entire textbox
+ txtThisTextBox.SelStart = 0
+ txtThisTextBox.SelLength = Len(txtThisTextBox.Text)
+ KeyAscii = 0
+ Case 24, 3, 22 ' Cut, Copy, Paste is allowed
+ Case 26
+ ' Ctrl+Z = Undo
+ KeyAscii = 0
+ txtThisTextBox.Text = GetMostRecentTextBoxValue
+ Case 8 ' Backspace key is allowed
+ Case 32 ' Spaces are allowed
+ Case 44, 46: ' Decimal point (. or ,) is allowed (as a separator)
+ Case 65 To 90, 97 To 122 ' Characters are allowed
+ Case Else
+ KeyAscii = 0
+ End Select
+ End If
+
+End Sub
+
+' Purpose: Convert a string of amino acid abbreviations to/from their 3 letter abbreviation
+Private Sub ConvertSequence(bool1LetterTo3Letter As Boolean)
+ ' If bool1LetterTo3Letter = True, then converting 1 letter codes to 3 letter codes
+ ' If bool1LetterTo3Letter = False, then converting 3 letter codes to 1 letter codes
+
+ Dim strWorkingSequence As String
+
+ If bool1LetterTo3Letter Then
+ ' Convert 1 letter symbols to 3 letter symbols
+ strWorkingSequence = txt1LetterSequence.Text
+ If Len(strWorkingSequence) = 0 Then Exit Sub
+
+ objMwtWin.Peptide.SetSequence strWorkingSequence, ntgHydrogen, ctgHydroxyl, False
+
+ txt3LetterSequence = objMwtWin.Peptide.GetSequence(True, False, cChkBox(chkSeparateWithDash), False, True)
+ Else
+ ' Convert 3 letter symbols to 1 letter symbols
+ strWorkingSequence = txt3LetterSequence.Text
+ If Len(strWorkingSequence) = 0 Then Exit Sub
+
+ objMwtWin.Peptide.SetSequence strWorkingSequence
+
+ txt1LetterSequence = objMwtWin.Peptide.GetSequence(False, cChkBox(chkSpaceEvery10), False, False, True)
+ End If
+End Sub
+
+' Purpose: Copy 3 letter sequence to requested formula on frmMain
+Private Sub CopySeqToFormula()
+ Dim intTargetFormulaID As Integer, boolWindowWasHidden As Boolean
+ Dim strSequence As String
+
+ strSequence = txt3LetterSequence.Text
+ If Len(strSequence) = 0 Then Exit Sub
+
+ intTargetFormulaID = cboTargetFormula.ListIndex
+ If intTargetFormulaID < 0 Then intTargetFormulaID = frmMain.GetTopFormulaIndex
+
+ ' Need to make sure the form is shown so that adding a formula will work correctly
+ ' Also necessary to assure the formula gets properly formatted
+ boolWindowWasHidden = False
+ If frmMain.Visible = False Then
+ boolWindowWasHidden = True
+ frmMain.WindowState = vbMinimized
+ frmMain.Visible = True
+ End If
+
+ If intTargetFormulaID > frmMain.GetTopFormulaIndex And _
+ frmMain.GetTopFormulaIndex < gMaxFormulaIndex Then
+ frmMain.AddNewFormulaWrapper
+ End If
+
+ ' Use .SetSequence and .GetSequence to remove any modification symbols that might be present
+ objMwtWin.Peptide.SetSequence strSequence, ntgHydrogen, ctgHydroxyl, True
+ strSequence = objMwtWin.Peptide.GetSequence(True, False, cChkBox(chkSeparateWithDash), False, False)
+
+ If Len(strSequence) = 0 Then
+ MsgBox "Invalid sequence present. Nothing to copy.", vbExclamation + vbOKOnly, "Error"
+ Else
+ frmMain.rtfFormula(intTargetFormulaID).Text = "H" & strSequence & "OH"
+ frmMain.Calculate False, True, True, intTargetFormulaID, False, False, True, 1, True
+
+ If boolWindowWasHidden Then
+ frmMain.Visible = False
+ End If
+ End If
+
+End Sub
+
+' Purpose: Copy 3 letter sequence to the peptide sequence fragmentation modeller
+Private Sub CopySeqToFragmentationModeller()
+ frmFragmentationModelling.cboNotation.ListIndex = 1
+ frmFragmentationModelling.PasteNewSequence txt3LetterSequence, True
+ frmFragmentationModelling.Show
+
+ If frmFragmentationModelling.WindowState <> vbMinimized Then
+ frmFragmentationModelling.txtSequence.SetFocus
+ End If
+
+End Sub
+
+' Purpose: Examines the formulas on frmMain, looking for the first blank one
+Private Sub FindFirstAvailableFormula()
+ ' Returns the highest formula (gMaxFormulaIndex) if all are in use
+
+ Dim intIndex As Integer, intFirstAvailID As Integer
+
+ With frmMain
+ intFirstAvailID = -1
+ For intIndex = 0 To frmMain.GetTopFormulaIndex
+ If .rtfFormula(intIndex).Text = "" Then
+ intFirstAvailID = intIndex
+ Exit For
+ End If
+ Next intIndex
+ If intFirstAvailID < 0 Then
+ If frmMain.GetTopFormulaIndex < gMaxFormulaIndex Then
+ intFirstAvailID = frmMain.GetTopFormulaIndex + 1
+ Else
+ intFirstAvailID = frmMain.GetTopFormulaIndex
+ End If
+ End If
+ End With
+
+ ' Now make sure this formula is highlighted in cboTargetFormula
+ UpdateTargetFormulaCombo intFirstAvailID
+
+End Sub
+
+' Purpose: Resize this form and position and size controls
+Private Sub ResizeForm(Optional boolEnlargeToMinimums As Boolean = False)
+ Dim lngCmdConvertMidpoint As Long
+ Dim boolSkipWidthAdjust As Boolean, boolSkipHeightAdjust As Boolean
+
+ If Me.Width < 6300 Then
+ If Not boolEnlargeToMinimums Then
+ boolSkipWidthAdjust = True
+ Else
+ Me.Width = 6300
+ End If
+ End If
+
+ If Me.Height < 4250 Then
+ If Not boolEnlargeToMinimums Then
+ boolSkipHeightAdjust = True
+ Else
+ Me.Height = 4250
+ End If
+ End If
+
+ txt1LetterSequence.Top = 120
+ If Not boolSkipHeightAdjust Then txt1LetterSequence.Height = Me.ScaleHeight * 0.2 - txt1LetterSequence.Top
+ txt1LetterSequence.Left = 1920
+ If Not boolSkipWidthAdjust Then txt1LetterSequence.Width = Me.ScaleWidth - txt1LetterSequence.Left - 280
+
+ cmdConvertTo3Letter.Top = txt1LetterSequence.Top + txt1LetterSequence.Height + 120
+ cmdConvertTo1Letter.Top = cmdConvertTo3Letter.Top
+
+ lngCmdConvertMidpoint = txt1LetterSequence.Left + 0.5 * txt1LetterSequence.Width
+ cmdConvertTo3Letter.Left = lngCmdConvertMidpoint - cmdConvertTo3Letter.Width - 240
+ cmdConvertTo1Letter.Left = lngCmdConvertMidpoint + 120
+
+ txt3LetterSequence.Top = cmdConvertTo1Letter.Top + cmdConvertTo1Letter.Height + 160
+ If Not boolSkipHeightAdjust Then txt3LetterSequence.Height = Me.ScaleHeight - txt3LetterSequence.Top - 1000
+ txt3LetterSequence.Left = txt1LetterSequence.Left
+ txt3LetterSequence.Width = txt1LetterSequence.Width
+
+ cmdCopy3Letter.Top = txt3LetterSequence.Top + txt3LetterSequence.Height + 120
+ cboTargetFormula.Top = cmdCopy3Letter.Top + 180
+
+ cmdClose.Top = cmdCopy3Letter.Top + 120
+ cmdCopyToFragmentationModeller.Top = cmdCopy3Letter.Top
+
+ lbl1Letter.Top = txt1LetterSequence.Top
+ chkSpaceEvery10.Top = lbl1Letter.Top + 600
+
+ lbl3Letter.Top = txt3LetterSequence.Top
+ chkSeparateWithDash.Top = lbl3Letter.Top + 600
+
+ If Not boolSkipWidthAdjust Then cmdClose.Left = Me.ScaleWidth - cmdClose.Width - 240
+End Sub
+
+' Purpose: Make sure cboTargetFormula has the same number of formulas as are displayed on frmMain
+' (plus 1 extra if frmMain.mTopFormulaIndex < gMaxFormulaIndex)
+' Also, set to the value of the first blank formula (or to frmMain.mTopFormulaIndex + 1 if not maxxed out)
+Private Sub UpdateTargetFormulaCombo(Optional intFormulaIDToHighlight As Integer = -1)
+ Dim intOldFormulaIDHighlighted As Integer, intIndex As Integer
+
+ intOldFormulaIDHighlighted = cboTargetFormula.ListIndex
+ With cboTargetFormula
+ .Clear
+ For intIndex = 0 To frmMain.GetTopFormulaIndex
+ .AddItem CStr(intIndex + 1)
+ Next intIndex
+ If frmMain.GetTopFormulaIndex < gMaxFormulaIndex Then
+ .AddItem CStr(frmMain.GetTopFormulaIndex + 2)
+ End If
+ End With
+
+ If intFormulaIDToHighlight < 0 Then
+ ' Simply make sure cboTargetFormula has the same number of formulas listed as frmMain
+ cboTargetFormula.ListIndex = intOldFormulaIDHighlighted
+ Else
+ If intFormulaIDToHighlight < cboTargetFormula.ListCount Then
+ cboTargetFormula.ListIndex = intFormulaIDToHighlight
+ End If
+ End If
+End Sub
+
+Private Sub chkSeparateWithDash_Click()
+ ConvertSequence True
+End Sub
+
+Private Sub chkSpaceEvery10_Click()
+ ConvertSequence False
+End Sub
+
+Private Sub cmdClose_Click()
+ HideFormShowMain Me
+End Sub
+
+Private Sub cmdConvertTo1Letter_Click()
+ ConvertSequence False
+End Sub
+
+Private Sub cmdConvertTo3Letter_Click()
+ ConvertSequence True
+End Sub
+
+Private Sub cmdCopy3Letter_Click()
+ CopySeqToFormula
+End Sub
+
+Private Sub cmdCopyToFragmentationModeller_Click()
+ CopySeqToFragmentationModeller
+End Sub
+
+Private Sub Form_Activate()
+ PossiblyHideMainWindow
+ FindFirstAvailableFormula
+End Sub
+
+Private Sub Form_Load()
+ SizeAndCenterWindow Me, cWindowUpperThird, 6000, 3500
+ ResizeForm True
+End Sub
+
+Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
+ QueryUnloadFormHandler Me, Cancel, UnloadMode
+End Sub
+
+Private Sub Form_Resize()
+ ResizeForm False
+End Sub
+
+Private Sub txt1LetterSequence_GotFocus()
+ HighlightOnFocus txt1LetterSequence
+End Sub
+
+Private Sub txt1LetterSequence_KeyDown(KeyCode As Integer, Shift As Integer)
+ If KeyCode = vbKeyReturn Then
+ ConvertSequence True
+ End If
+End Sub
+
+Private Sub txt1LetterSequence_KeyPress(KeyAscii As Integer)
+ AminoAcidTextBoxKeyPressHandler txt1LetterSequence, KeyAscii
+End Sub
+
+Private Sub txt3LetterSequence_GotFocus()
+ HighlightOnFocus txt3LetterSequence
+End Sub
+
+Private Sub txt3LetterSequence_KeyDown(KeyCode As Integer, Shift As Integer)
+ If KeyCode = vbKeyReturn Then
+ ConvertSequence False
+ End If
+End Sub
+
+Private Sub txt3LetterSequence_KeyPress(KeyAscii As Integer)
+ AminoAcidTextBoxKeyPressHandler txt3LetterSequence, KeyAscii
+End Sub
diff --git a/frmAminoAcidConverter.frx b/frmAminoAcidConverter.frx
new file mode 100644
index 0000000..35d4b82
Binary files /dev/null and b/frmAminoAcidConverter.frx differ
diff --git a/frmAminoAcidModifications.frm b/frmAminoAcidModifications.frm
new file mode 100644
index 0000000..94b4b8f
--- /dev/null
+++ b/frmAminoAcidModifications.frm
@@ -0,0 +1,593 @@
+VERSION 5.00
+Object = "{5E9E78A0-531B-11CF-91F6-C2863C385E30}#1.0#0"; "MSFLXGRD.OCX"
+Begin VB.Form frmAminoAcidModificationSymbols
+ Caption = "Amino Acid Modification Symbols Editor"
+ ClientHeight = 7095
+ ClientLeft = 60
+ ClientTop = 360
+ ClientWidth = 10080
+ LinkTopic = "Form1"
+ MaxButton = 0 'False
+ ScaleHeight = 7095
+ ScaleWidth = 10080
+ StartUpPosition = 3 'Windows Default
+ Tag = "15500"
+ Begin VB.TextBox txtPhosphorylationSymbol
+ Height = 300
+ Left = 2520
+ TabIndex = 11
+ Text = "*"
+ Top = 2160
+ Width = 855
+ End
+ Begin VB.CommandButton cmdAddToList
+ Appearance = 0 'Flat
+ Caption = "&Add selected to list"
+ Height = 360
+ Left = 6600
+ TabIndex = 6
+ Tag = "15810"
+ Top = 6600
+ Width = 2235
+ End
+ Begin VB.ListBox lstStandardModfications
+ Height = 2985
+ Left = 5880
+ TabIndex = 5
+ Top = 3240
+ Width = 3975
+ End
+ Begin VB.CommandButton cmdOK
+ Caption = "&OK"
+ Height = 360
+ Left = 120
+ TabIndex = 7
+ Tag = "4010"
+ Top = 6600
+ Width = 1035
+ End
+ Begin VB.CommandButton cmdCancel
+ Appearance = 0 'Flat
+ Cancel = -1 'True
+ Caption = "&Cancel"
+ Height = 360
+ Left = 1320
+ TabIndex = 8
+ Tag = "4020"
+ Top = 6600
+ Width = 1035
+ End
+ Begin VB.CommandButton cmdReset
+ Appearance = 0 'Flat
+ Caption = "Reset to &Defaults"
+ Height = 360
+ Left = 2520
+ TabIndex = 9
+ Tag = "15800"
+ ToolTipText = "Resets modification symbols to defaults"
+ Top = 6600
+ Width = 1935
+ End
+ Begin MSFlexGridLib.MSFlexGrid grdModSymbols
+ Height = 3135
+ Left = 120
+ TabIndex = 3
+ Tag = "15600"
+ ToolTipText = "Click to change a modification symbol"
+ Top = 3285
+ Width = 5535
+ _ExtentX = 9763
+ _ExtentY = 5530
+ _Version = 393216
+ Rows = 17
+ Cols = 5
+ FixedCols = 0
+ ScrollBars = 2
+ End
+ Begin VB.Label lblPhosphorylationSymbolComment
+ Height = 255
+ Left = 3600
+ TabIndex = 12
+ Top = 2190
+ Width = 2415
+ End
+ Begin VB.Label lblPhosphorylationSymbol
+ Caption = "Phosphorylation Symbol:"
+ Height = 255
+ Left = 120
+ TabIndex = 10
+ Tag = "15200"
+ Top = 2190
+ Width = 2295
+ End
+ Begin VB.Label lblModificationSymbolHeaderDirections
+ Caption = "Single click to edit or remove. Click in blank row to add."
+ Height = 375
+ Left = 120
+ TabIndex = 2
+ Tag = "15710"
+ Top = 2880
+ Width = 5535
+ End
+ Begin VB.Label lblModificationSymbolHeader
+ Caption = "Modification Symbols Defined"
+ Height = 255
+ Left = 120
+ TabIndex = 1
+ Tag = "15730"
+ Top = 2640
+ Width = 5535
+ End
+ Begin VB.Label Label1
+ Caption = "Standard Modifications"
+ Height = 255
+ Left = 5880
+ TabIndex = 4
+ Tag = "15720"
+ Top = 2880
+ Width = 2655
+ End
+ Begin VB.Label lblExplanation
+ Caption = "Explanation"
+ Height = 1815
+ Left = 120
+ TabIndex = 0
+ Top = 120
+ Width = 9735
+ End
+End
+Attribute VB_Name = "frmAminoAcidModificationSymbols"
+Attribute VB_GlobalNameSpace = False
+Attribute VB_Creatable = False
+Attribute VB_PredeclaredId = True
+Attribute VB_Exposed = False
+Option Explicit
+
+Private Const FORM_WIDTH_MAX = 11000
+Private Const FORM_HEIGHT_MAX = 7500
+
+Private Const MODSYMBOLS_GRID_COL_COUNT = 4
+
+Private Type udtModificationSymbolsType
+ Symbol As String
+ ModificationMass As Double
+ IndicatesPhosphorylation As Boolean
+ Comment As String
+End Type
+
+Private DefaultModSymbols() As udtModificationSymbolsType ' 0-based array
+Private DefaultModSymbolsCount As Long
+
+Private SavedModSymbols() As udtModificationSymbolsType ' 0-based array
+Private SavedModSymbolsCount As Long
+
+Private mValueChanged As Boolean
+Private mDelayUpdate As Boolean
+
+Private Sub AddDefaultModificationSymbol(strSymbol As String, dblMass As Double, blnIndicatesPhosphorylation As Boolean, strComment As String)
+
+ With DefaultModSymbols(DefaultModSymbolsCount)
+ .Symbol = strSymbol
+ .ModificationMass = dblMass
+ .IndicatesPhosphorylation = blnIndicatesPhosphorylation
+ .Comment = strComment
+
+ lstStandardModfications.AddItem .Symbol & ", " & .ModificationMass & ", " & .Comment
+ End With
+ DefaultModSymbolsCount = DefaultModSymbolsCount + 1
+
+End Sub
+Private Sub AddSelectedModificationToList()
+ Dim lngIndex As Long, lngSelectedIndex As Long
+ Dim lngErrorID As Long
+
+ lngSelectedIndex = -1
+ For lngIndex = 0 To lstStandardModfications.ListCount - 1
+ If lstStandardModfications.Selected(lngIndex) Then
+ lngSelectedIndex = lngIndex
+ Exit For
+ End If
+ Next lngIndex
+
+ If lngSelectedIndex >= 0 Then
+ With DefaultModSymbols(lngSelectedIndex)
+ ' The SetModificationSymbol() will update the symbol if it exists,
+ ' or add a new one if it doesn't exist
+ lngErrorID = objMwtWin.Peptide.SetModificationSymbol(.Symbol, .ModificationMass, .IndicatesPhosphorylation, .Comment)
+ Debug.Assert lngErrorID = 0
+ End With
+ End If
+
+ DisplayCurrentModificationSymbols
+End Sub
+
+Private Sub DisplayCurrentModificationSymbols()
+
+ Dim lngIndex As Long, intCurrentRow As Integer, intCurrentCol As Integer
+ Dim lngModSymbolCount As Long
+ Dim strSymbol As String, strComment As String
+ Dim dblMass As Double, blnPhosphorylation As Boolean
+ Dim blnPhosphorylationSymbolFound As Boolean
+ Dim lngError As Long
+
+ If mDelayUpdate Then Exit Sub
+ mDelayUpdate = True
+
+ txtPhosphorylationSymbol = ""
+
+ intCurrentRow = grdModSymbols.Row
+ intCurrentCol = grdModSymbols.Col
+
+ ' Grab the Modification Symbols from objMwtWin and fill the grid
+ ' Place the first phosphorylation symbol found in txtPhosphorylationSymbol
+ lngModSymbolCount = 0
+ For lngIndex = 1 To objMwtWin.Peptide.GetModificationSymbolCount
+
+ lngError = objMwtWin.Peptide.GetModificationSymbol(lngIndex, strSymbol, dblMass, blnPhosphorylation, strComment)
+ Debug.Assert lngError = 0
+
+ If blnPhosphorylation Then
+ If Not blnPhosphorylationSymbolFound Then
+ txtPhosphorylationSymbol = strSymbol
+ blnPhosphorylationSymbolFound = True
+ End If
+ Else
+ With grdModSymbols
+ lngModSymbolCount = lngModSymbolCount + 1
+ ' Enlarge grid if necessary
+ If lngModSymbolCount >= .Rows - 1 Then
+ .Rows = lngModSymbolCount + 2
+ End If
+
+ .TextMatrix(lngModSymbolCount, 0) = lngIndex
+ .TextMatrix(lngModSymbolCount, 1) = strSymbol
+ .TextMatrix(lngModSymbolCount, 2) = Round(dblMass, 6)
+ .TextMatrix(lngModSymbolCount, 3) = strComment
+ End With
+ End If
+ Next lngIndex
+
+ ' Erase remaining cells in grid
+ For lngIndex = lngModSymbolCount + 1 To grdModSymbols.Rows - 1
+ With grdModSymbols
+ .TextMatrix(lngIndex, 0) = ""
+ .TextMatrix(lngIndex, 1) = ""
+ .TextMatrix(lngIndex, 2) = ""
+ .TextMatrix(lngIndex, 3) = ""
+ End With
+ Next lngIndex
+
+ ' Adjust row height of rows in grid
+ For lngIndex = 1 To grdModSymbols.Rows - 1
+ grdModSymbols.RowHeight(lngIndex) = TextHeight("123456789gT") + 60
+ Next lngIndex
+
+ ' Re-position cursor
+ grdModSymbols.Row = intCurrentRow
+ If intCurrentRow - 3 >= 1 Then
+ grdModSymbols.TopRow = intCurrentRow - 3
+ Else
+ grdModSymbols.TopRow = 1
+ End If
+ grdModSymbols.Col = intCurrentCol
+
+ mDelayUpdate = False
+
+End Sub
+
+Private Sub HandleGridClick()
+
+ Dim intCurrentRow As Integer
+ Dim strModSymbolID As String, lngModSymbolID As Long
+ Dim strSymbol As String, strMass As String, strComment As String
+ Dim strNewSymbol As String, strNewMass As String, strNewComment As String
+ Dim lngErrorID As Long
+
+ ' Determine the current row
+ intCurrentRow = grdModSymbols.Row
+
+ If intCurrentRow < 1 Then Exit Sub
+
+ ' Determine which mod symbol the user clicked on
+ strModSymbolID = grdModSymbols.TextMatrix(intCurrentRow, 0)
+
+ If strModSymbolID = "" Then
+ lngModSymbolID = 0
+ Else
+ lngModSymbolID = Val(strModSymbolID)
+ With grdModSymbols
+ strSymbol = .TextMatrix(intCurrentRow, 1)
+ strMass = .TextMatrix(intCurrentRow, 2)
+ strComment = .TextMatrix(intCurrentRow, 3)
+ End With
+ End If
+
+ ' Display the dialog box and get user's response.
+ With frmEditModSymbolDetails
+ .lblHiddenButtonClickStatus = BUTTON_NOT_CLICKED_YET
+ .txtSymbol = strSymbol
+ .txtMass = strMass
+ .txtComment = strComment
+
+ .Show vbModal
+
+ If .lblHiddenButtonClickStatus = BUTTON_NOT_CLICKED_YET Then .lblHiddenButtonClickStatus = BUTTON_CANCEL
+ End With
+
+ If Not frmEditModSymbolDetails.lblHiddenButtonClickStatus = BUTTON_CANCEL Then
+ If frmEditModSymbolDetails.lblHiddenButtonClickStatus = BUTTON_RESET Then
+ ' BUTTON_RESET indicates to remove the mod symbol
+ If IsNumeric(strModSymbolID) Then
+ lngModSymbolID = Val(strModSymbolID)
+
+ lngErrorID = objMwtWin.Peptide.RemoveModificationByID(lngModSymbolID)
+ Debug.Assert lngErrorID = 0
+ End If
+ Else
+ With frmEditModSymbolDetails
+ strNewSymbol = .txtSymbol
+ strNewMass = .txtMass
+ strNewComment = .txtComment
+ End With
+
+ If Len(strNewSymbol) > 0 Then
+ If strNewSymbol <> strSymbol Then
+ ' User changed symbol; need to remove the old entry before adding the new one
+ objMwtWin.Peptide.RemoveModification (strSymbol)
+ End If
+ lngErrorID = objMwtWin.Peptide.SetModificationSymbol(strNewSymbol, CDblSafe(strNewMass), False, strNewComment)
+ Debug.Assert lngErrorID = 0
+ End If
+ End If
+
+ DisplayCurrentModificationSymbols
+ mValueChanged = True
+ End If
+
+End Sub
+
+Public Sub InitializeForm()
+ Dim lngIndex As Long
+ Dim lngErrorID As Long
+
+ SavedModSymbolsCount = objMwtWin.Peptide.GetModificationSymbolCount
+
+ ReDim SavedModSymbols(SavedModSymbolsCount)
+ For lngIndex = 1 To SavedModSymbolsCount
+ ' Note: SavedModSymbols() is 0-based, but the modifications in objMwtWin.Peptide are 1-based
+ With SavedModSymbols(lngIndex - 1)
+ lngErrorID = objMwtWin.Peptide.GetModificationSymbol(lngIndex, .Symbol, .ModificationMass, .IndicatesPhosphorylation, .Comment)
+ Debug.Assert lngErrorID = 0
+ End With
+ Next lngIndex
+
+ DisplayCurrentModificationSymbols
+
+ mValueChanged = False
+End Sub
+
+Private Sub InitializeControls()
+ Dim strMessage As String
+
+ strMessage = LookupLanguageCaption(15550, "Modified residues in an amino acid sequence are notated by placing a modification symbol directly after the residue's 1 letter or 3 letter abbreviation.")
+ strMessage = strMessage & " " & LookupLanguageCaption(15555, "The phosphorylation symbol is defined separately because phosphorylated residues can lose a phosphate group during fragmentation.")
+ strMessage = strMessage & " " & LookupLanguageCaption(15560, "As an example, if the phosphorylation symbol is *, then in the sequence 'GlyLeuTyr*' the tyrosine residue is phosphorylated.")
+ strMessage = strMessage & " " & LookupLanguageCaption(15565, "Allowable symbols for user-defined modifications are") & " ! # $ % & ' * + ? ^ _ ` and ~"
+ strMessage = strMessage & " " & LookupLanguageCaption(15570, "Modification symbols can be more than 1 character long, though it is suggested that you keep them to just 1 character long to make it easier for the parsing routine to correctly parse residues with multiple modifications.")
+ strMessage = strMessage & " " & LookupLanguageCaption(15575, "If a residue has multiple modifications, then simply place the appropriate modification symbols after the residue, for example in 'FLE*#L' the E residue is modified by both the * and # modifications.")
+ strMessage = strMessage & " " & LookupLanguageCaption(15580, "Modification masses can be negative values, as well as positive values.")
+
+ lblExplanation.Caption = strMessage
+
+ With grdModSymbols
+ .ColWidth(0) = 0
+ .Cols = MODSYMBOLS_GRID_COL_COUNT
+ .Rows = 2
+ .Clear
+ .TextMatrix(0, 0) = "ModSymbolID (Hidden)"
+ .TextMatrix(0, 1) = LookupLanguageCaption(15610, "Symbol")
+ .TextMatrix(0, 2) = LookupLanguageCaption(15620, "Mass")
+ .TextMatrix(0, 3) = LookupLanguageCaption(15640, "Comment")
+
+ .ColWidth(0) = 0
+ .ColWidth(1) = 800
+ .ColWidth(2) = 1000
+ .ColWidth(3) = 3400
+
+ .ColAlignment(1) = flexAlignLeftCenter
+ .ColAlignment(2) = flexAlignGeneral
+ .ColAlignment(3) = flexAlignLeftCenter
+
+ .Row = 1
+ .Col = 1
+ End With
+
+ DisplayCurrentModificationSymbols
+
+End Sub
+
+Private Sub InitializeDefaultModSymbols()
+ ' Initialize DefaultModSymbols()
+
+ Dim lngIndex As Long
+ Dim lngReturn As Long
+ Dim strModSymbol As String, dblModMass As Double, blnIndicatesPhosphorylation As Boolean, strComment As String
+
+ Dim objPeptideClass As New MWPeptideClass
+
+ lstStandardModfications.Clear
+ DefaultModSymbolsCount = 0
+ ReDim DefaultModSymbols(objPeptideClass.GetModificationSymbolCount)
+
+ For lngIndex = 1 To objPeptideClass.GetModificationSymbolCount
+ lngReturn = objPeptideClass.GetModificationSymbol(lngIndex, strModSymbol, dblModMass, blnIndicatesPhosphorylation, strComment)
+
+ If Not blnIndicatesPhosphorylation Then
+ AddDefaultModificationSymbol strModSymbol, dblModMass, blnIndicatesPhosphorylation, strComment
+ Else
+ lblPhosphorylationSymbolComment = "[HPO3], " & Round(dblModMass, 3)
+ End If
+ Next lngIndex
+
+ Set objPeptideClass = Nothing
+
+End Sub
+
+Private Sub RemoveAllPhosphorylationSymbols()
+ Dim strSymbol As String
+ Dim lngIndex As Long
+ Dim blnIndicatesPhosphorylation As Boolean
+ Dim lngErrorID As Long
+
+ ' Remove all mod symbols with phosphorylation = True
+ lngIndex = 1
+ Do While lngIndex <= objMwtWin.Peptide.GetModificationSymbolCount
+ lngErrorID = objMwtWin.Peptide.GetModificationSymbol(lngIndex, strSymbol, 0, blnIndicatesPhosphorylation, "")
+ Debug.Assert lngErrorID = 0
+
+ If blnIndicatesPhosphorylation = True Then
+ lngErrorID = objMwtWin.Peptide.RemoveModificationByID(lngIndex)
+ Else
+ lngIndex = lngIndex + 1
+ End If
+ Loop
+
+End Sub
+
+Public Sub ResetModificationSymbolsToDefaults()
+ objMwtWin.Peptide.SetDefaultModificationSymbols
+ mValueChanged = True
+
+ ' Update displayed mod list
+ DisplayCurrentModificationSymbols
+End Sub
+
+Private Sub RestoreSavedModSymbols()
+ Dim lngIndex As Long
+ Dim lngErrorID As Long
+
+ objMwtWin.Peptide.RemoveAllModificationSymbols
+
+ For lngIndex = 1 To SavedModSymbolsCount
+ ' Note: SavedModSymbols() is 0-based, but the modifications in objMwtWin.Peptide are 1-based
+ With SavedModSymbols(lngIndex - 1)
+ lngErrorID = objMwtWin.Peptide.SetModificationSymbol(.Symbol, .ModificationMass, .IndicatesPhosphorylation, .Comment)
+ Debug.Assert lngErrorID = 0
+ End With
+ Next lngIndex
+End Sub
+
+Private Sub ValidateNewPhosphorylationSymbol()
+
+ Const PHOSPHORYLATION_MASS As Double = 79.9663326
+
+ Dim strNewSymbol As String
+ Dim lngModSymbolID As Long
+ Dim lngErrorID As Long
+ Dim eResponse As VbMsgBoxResult
+
+ If mDelayUpdate Then Exit Sub
+
+ strNewSymbol = txtPhosphorylationSymbol
+
+ If Len(strNewSymbol) = 0 Then
+ RemoveAllPhosphorylationSymbols
+ mValueChanged = True
+ Else
+ ' See if any of the current modification symbols match txtPhosphorylationSymbol
+ ' If they do, warn user that they will be removed
+ lngModSymbolID = objMwtWin.Peptide.GetModificationSymbolID(strNewSymbol)
+
+ If lngModSymbolID > 0 Then
+ eResponse = MsgBox(LookupLanguageCaption(15760, "Warning, the new phosphorylation symbol is already being used for another modification. Do you really want to use this symbol for phosphorylation and consequently remove the other definition?"), vbQuestion + vbYesNoCancel + vbDefaultButton3, _
+ LookupLanguageCaption(15765, "Modification Symbol Conflict"))
+ Else
+ eResponse = vbYes
+ End If
+
+ If eResponse = vbYes Then
+ RemoveAllPhosphorylationSymbols
+ lngErrorID = objMwtWin.Peptide.SetModificationSymbol(strNewSymbol, PHOSPHORYLATION_MASS, True, "Phosphorylation")
+ Debug.Assert lngErrorID = 0
+
+ mValueChanged = True = True
+ End If
+ End If
+
+ DisplayCurrentModificationSymbols
+
+End Sub
+
+Private Sub cmdAddToList_Click()
+ AddSelectedModificationToList
+End Sub
+
+Private Sub cmdCancel_Click()
+ Dim eResponse As VbMsgBoxResult
+
+ If mValueChanged Then
+ eResponse = YesNoBox(LookupLanguageCaption(15770, "Are you sure you want to lose all changes?"), _
+ LookupLanguageCaption(15775, "Closing Edit Modification Symbols Window"))
+ If eResponse = vbYes Then
+ RestoreSavedModSymbols
+ Else
+ Exit Sub
+ End If
+ End If
+
+ mValueChanged = False
+ Me.Hide
+End Sub
+
+Private Sub cmdOK_Click()
+ mValueChanged = False
+ Me.Hide
+End Sub
+
+Private Sub cmdReset_Click()
+ ResetModificationSymbolsToDefaults
+End Sub
+
+Private Sub Form_Load()
+ SizeAndCenterWindow Me, cWindowUpperThird, FORM_WIDTH_MAX, FORM_HEIGHT_MAX
+
+ InitializeDefaultModSymbols
+
+ InitializeControls
+End Sub
+
+Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
+ QueryUnloadFormHandler Me, Cancel, UnloadMode
+End Sub
+
+Private Sub Form_Resize()
+
+ On Error Resume Next
+ With Me
+ If .Height > FORM_HEIGHT_MAX Then .Height = FORM_HEIGHT_MAX
+ If .Width > FORM_WIDTH_MAX Then .Width = FORM_WIDTH_MAX
+ End With
+
+End Sub
+
+Private Sub grdModSymbols_Click()
+ HandleGridClick
+End Sub
+
+Private Sub lstStandardModfications_DblClick()
+ AddSelectedModificationToList
+End Sub
+
+Private Sub txtPhosphorylationSymbol_Change()
+ Dim lngSelSave As Long
+
+ With txtPhosphorylationSymbol
+ lngSelSave = .SelStart
+ ValidateNewPhosphorylationSymbol
+ .SelStart = lngSelSave
+ End With
+End Sub
+
+Private Sub txtPhosphorylationSymbol_KeyPress(KeyAscii As Integer)
+ ModSymbolKeyPressHandler txtPhosphorylationSymbol, KeyAscii
+End Sub
diff --git a/frmCalculator.frm b/frmCalculator.frm
new file mode 100644
index 0000000..33dda94
--- /dev/null
+++ b/frmCalculator.frm
@@ -0,0 +1,854 @@
+VERSION 5.00
+Object = "{3B7C8863-D78F-101B-B9B5-04021C009402}#1.2#0"; "richtx32.ocx"
+Begin VB.Form frmCalculator
+ Caption = "Calculator"
+ ClientHeight = 1110
+ ClientLeft = 165
+ ClientTop = 840
+ ClientWidth = 7035
+ Icon = "frmCalculator.frx":0000
+ LinkTopic = "Form1"
+ MaxButton = 0 'False
+ ScaleHeight = 1110
+ ScaleWidth = 7035
+ StartUpPosition = 3 'Windows Default
+ Tag = "6500"
+ Begin VB.TextBox txtStatus
+ Appearance = 0 'Flat
+ BackColor = &H8000000F&
+ BorderStyle = 0 'None
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 9.75
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 240
+ Left = 120
+ Locked = -1 'True
+ TabIndex = 3
+ TabStop = 0 'False
+ Text = "Status"
+ Top = 720
+ Width = 4815
+ End
+ Begin VB.CommandButton cmdOK
+ Cancel = -1 'True
+ Caption = "Cl&ose"
+ Height = 360
+ Left = 5280
+ TabIndex = 2
+ Tag = "4000"
+ Top = 600
+ Width = 1155
+ End
+ Begin VB.CommandButton cmdCalculate
+ Caption = "&Calculate"
+ Default = -1 'True
+ Height = 375
+ Left = 5160
+ TabIndex = 1
+ Tag = "6520"
+ ToolTipText = "Evaluates the current expression"
+ Top = 120
+ Width = 1455
+ End
+ Begin RichTextLib.RichTextBox rtfExpression
+ Height = 495
+ Left = 120
+ TabIndex = 0
+ Tag = "6510"
+ ToolTipText = "Enter a mathematical expression to evaluate here"
+ Top = 120
+ Width = 4815
+ _ExtentX = 8493
+ _ExtentY = 873
+ _Version = 393217
+ Enabled = -1 'True
+ MultiLine = 0 'False
+ TextRTF = $"frmCalculator.frx":08CA
+ End
+ Begin VB.Menu mnuRightClick
+ Caption = "RightClickMenu"
+ Begin VB.Menu mnuRightClickUndo
+ Caption = "&Undo"
+ End
+ Begin VB.Menu mnuRightClickSep1
+ Caption = "-"
+ End
+ Begin VB.Menu mnuRightClickCut
+ Caption = "Cu&t"
+ End
+ Begin VB.Menu mnuRightClickCopy
+ Caption = "&Copy"
+ End
+ Begin VB.Menu mnuRightClickPaste
+ Caption = "&Paste"
+ End
+ Begin VB.Menu mnuRightClickDelete
+ Caption = "&Delete"
+ End
+ Begin VB.Menu mnuRightClickSep2
+ Caption = "-"
+ End
+ Begin VB.Menu mnuRightClickSelectAll
+ Caption = "Select &All"
+ End
+ End
+End
+Attribute VB_Name = "frmCalculator"
+Attribute VB_GlobalNameSpace = False
+Attribute VB_Creatable = False
+Attribute VB_PredeclaredId = True
+Attribute VB_Exposed = False
+Option Explicit
+
+' Form wide globals
+Private strComputationResult As String
+Private boolExpressionChanged As Boolean
+
+Private mCalculatorErrorID As Long
+Private mCalculatorErrorPosition As Long
+Private mDecimalSeparator As String
+
+' Purpose: Hande errors generated by ParseNum
+Private Sub CatchParsenumErrorInCalculator(AdjacentNum As Double, Optional boolInspectingCaret As Boolean = False)
+
+ If AdjacentNum < 0 Then
+ Select Case AdjacentNum
+ Case -1
+ ' Error: No number
+ If boolInspectingCaret Then
+ mCalculatorErrorID = 15 ' LookupMessage(89)
+ Else
+ ' Ignore the missing number
+ End If
+ Case -3
+ ' Error: No number after decimal point
+ ' Return message 'Misplaced number'
+ mCalculatorErrorID = 21 ' LookupMessage(95)
+ Case -4
+ ' Error: More than one decimal point
+ mCalculatorErrorID = 16 ' LookupMessage(90)
+ Case Else
+ ' Error: General number error
+ ' Return message 'Misplaced number'
+ mCalculatorErrorID = 4 ' LookupMessage(78)
+ End Select
+ End If
+
+End Sub
+
+Private Sub CopyRoutinePrivate()
+ ' Copy text from rtfExpression to the clipboard
+
+ Dim strCopyText As String
+
+ strCopyText = rtfExpression.SelText
+
+ RemoveHeightAdjustChar strCopyText
+
+ ' Copy corrected text to Clipboard.
+ Clipboard.Clear
+ Clipboard.SetText strCopyText, vbCFText
+
+End Sub
+
+' Purpose: Take a number to a power
+Private Function DoPower(dblWorkNum As Double, strExpression As String, intIndexOfStartOfFirstNumber As Integer, ByVal intOffsetToSecondNumber As Integer, ByRef intNumSizing As Integer) As Double
+ ' Note: intNumSizing holds the length of the first number when this expression is called
+ ' Later in the expression the length of the second number (and 1 for the caret) is
+ ' added to intNumSizing such that it then holds the length of both numbers and the caret
+
+ Dim intNumSizingFirstNumber As Integer, dblPowerNum As Double
+ Dim intNumSizingSecondNumber As Integer
+
+ ' Need to take sum in parentheses to power before continuing
+ intNumSizingFirstNumber = intNumSizing
+
+ If Mid(strExpression, intIndexOfStartOfFirstNumber + intNumSizingFirstNumber + intOffsetToSecondNumber, 1) = "-" Then
+ ' Ability to handle negative powers
+ dblPowerNum = ParseNum(Mid(strExpression, intIndexOfStartOfFirstNumber + intNumSizingFirstNumber + intOffsetToSecondNumber + 1), intNumSizingSecondNumber)
+ CatchParsenumErrorInCalculator dblPowerNum, True
+ If dblPowerNum >= 0 Then
+ dblPowerNum = -dblPowerNum
+ intNumSizing = intNumSizing + 1
+ End If
+ Else
+ dblPowerNum = ParseNum(Mid(strExpression, intIndexOfStartOfFirstNumber + intNumSizingFirstNumber + intOffsetToSecondNumber), intNumSizingSecondNumber)
+ CatchParsenumErrorInCalculator dblPowerNum, True
+ End If
+
+ If mCalculatorErrorID = 0 Then
+ If dblWorkNum < 0 And dblPowerNum <> CIntSafeDbl(dblPowerNum) Then
+ ' Cannot take a negative number to a decimal power
+ mCalculatorErrorID = 11
+ ElseIf dblWorkNum = 0 Then
+ If dblPowerNum < 0 Then
+ ' Cannot take zero to a negative power
+ mCalculatorErrorID = 12
+ ElseIf dblPowerNum = 0 Then
+ ' Cannot take zero to the zeroth power
+ mCalculatorErrorID = 13
+ End If
+ End If
+ If mCalculatorErrorID = 0 Then
+ ' intNumSizingFirstNumber contains the length of the first number (m in m^n)
+ ' intNumSizing contains the length of the second number (n in m^n)
+ intNumSizing = intNumSizingFirstNumber + intNumSizingSecondNumber + 1
+ DoPower = dblWorkNum ^ dblPowerNum
+ End If
+ End If
+
+ If mCalculatorErrorID <> 0 Then
+ mCalculatorErrorPosition = intIndexOfStartOfFirstNumber + intOffsetToSecondNumber + intNumSizingFirstNumber
+ intIndexOfStartOfFirstNumber = Len(strExpression)
+ End If
+
+End Function
+
+' Purpose: Compute a result based on rtfExpression.Text; display in strComputationResult
+Private Sub InitiateMathCalculate()
+ Dim dblResult As Double
+
+ mCalculatorErrorID = 0
+ If boolExpressionChanged Then
+ dblResult = PerformMath(rtfExpression.Text, 1)
+
+ If frmProgramPreferences.optStdDevType(1).value = True Or Abs(dblResult) >= 10000000# Then
+ ' Use scientific notation
+ strComputationResult = Format(dblResult, "0.###############E+00")
+ Else
+ ' Display result in 0.000 notation rather than exponential
+ If Abs(dblResult) >= 10000# Then
+ ' Display with commas
+ strComputationResult = Format(dblResult, "#,##0.################")
+ Else
+ ' Leave out the commas
+ strComputationResult = Format(dblResult, "#0.###############")
+ End If
+ If Right(strComputationResult, 1) = "." Then
+ strComputationResult = Left(strComputationResult, Len(strComputationResult) - 1)
+ End If
+ End If
+ End If
+
+ If mCalculatorErrorID > 0 Then ' Inform user of error and location
+ txtStatus.ForeColor = QBColor(COLOR_ERR)
+ ' Calculator error codes are 75 to 99
+ txtStatus.Text = LookupMessage(mCalculatorErrorID + 74)
+
+ Form_Resize
+ Else
+ ' Display sum
+ txtStatus.ForeColor = vbWindowText
+ txtStatus.Text = LookupLanguageCaption(6610, "Result ") & " = " & strComputationResult
+ End If
+
+End Sub
+
+' Purpose: Update txtstatus
+Private Sub LabelStatus()
+ If mCalculatorErrorID = 0 Then
+ txtStatus.ForeColor = vbWindowText
+ txtStatus.Text = LookupLanguageCaption(3670, "Ready")
+ End If
+End Sub
+
+' Purpose: Handle keys pressed in rtfExpression
+Private Sub MathTextBoxKeypressHandler(ByRef KeyAscii As Integer)
+
+ Select Case KeyAscii
+ Case 40 To 43, 45, 47 To 57, 91, 93, 94, 123, 125
+ ' Valid Characters are:
+ ' ( and ) are 40 and 41
+ ' [ and ] are 91 and 93
+ ' { and } are 123 and 125
+ ' * is 42
+ ' + is 43
+ ' - is 45
+ ' / is 47
+ ' Numbers are 48 to 57
+ ' ^ is 94
+ boolExpressionChanged = True
+ Case 44, 46
+ Select Case glbDecimalSeparator
+ Case ","
+ If KeyAscii = 46 Then
+ KeyAscii = 0
+ txtStatus.Text = LookupMessage(94)
+ End If
+ Case Else ' includes "."
+ If KeyAscii = 44 Then
+ KeyAscii = 0
+ txtStatus.Text = LookupMessage(93)
+ End If
+ End Select
+ Case 8
+ ' Backspace; it is valid
+ boolExpressionChanged = True
+ Case 9
+ ' Tab; it is valid
+ Case 32
+ ' Space
+ txtStatus.ForeColor = QBColor(COLOR_ERR)
+ txtStatus.Text = LookupMessage(92)
+ KeyAscii = 0
+ Case vbKeyReturn
+ cmdCalculate_Click
+ KeyAscii = 0
+ LabelStatus
+ Case 0
+ ' This is set by Form_KeyDown and should just ignore the entry
+ Case vbKeyEscape
+ ' Ignore the key if it got this far
+ KeyAscii = 0
+ Case 1
+ ' User pressed Ctrl+A (select all)
+ Case 3
+ ' User pressed CTRL+C (copy)
+ CopyRoutine Me, False
+ Case 22
+ ' User pressed CTRL+V (paste)
+ PasteRoutine Me, False
+ Case 24
+ ' User pressed CTRL+X (cut)
+ CutRoutine Me, False
+ Case Else
+ ' All other ASCII characters are invalid
+ txtStatus.ForeColor = QBColor(COLOR_ERR)
+ txtStatus.Text = LookupMessage(620) & " " & Chr$(KeyAscii)
+ KeyAscii = 0
+ End Select
+
+End Sub
+
+Private Function ParseNum(strWork As String, ByRef intNumLength As Integer, Optional blnAllowNegative As Boolean = False) As Double
+ ' Looks for a number and returns it if found
+ ' If an error is found, it returns a negative number for the error code and sets intNumLength = 0
+ ' -1 = No number
+ ' -2 = (unused)
+ ' -3 = No number at all or (more likely) no number after decimal point
+ ' -4 = More than one decimal point
+
+ Dim strWorking As String, strFoundNum As String, intIndex As Integer, intDecPtCount As Integer
+
+ If mDecimalSeparator = "" Then
+ mDecimalSeparator = DetermineDecimalPoint()
+ End If
+
+ ' Set intNumLength to -1 for now
+ ' If it doesn't get set to 0 (due to an error), it will get set to the
+ ' length of the matched number before exiting the sub
+ intNumLength = -1
+
+ If strWork = "" Then strWork = EMPTY_STRINGCHAR
+ If (Asc(Left(strWork, 1)) < 48 Or Asc(Left(strWork, 1)) > 57) And _
+ Left(strWork, 1) <> mDecimalSeparator And _
+ Not (Left(strWork, 1) = "-" And blnAllowNegative = True) Then
+ intNumLength = 0 ' No number found
+ ParseNum = -1
+ Else
+ ' Start of string is a number or a decimal point, or (if allowed) a negative sign
+ For intIndex = 1 To Len(strWork)
+ strWorking = Mid(strWork, intIndex, 1)
+ If IsNumeric(strWorking) Or strWorking = mDecimalSeparator Or _
+ (blnAllowNegative = True And strWorking = "-") Then
+ strFoundNum = strFoundNum & strWorking
+ Else
+ Exit For
+ End If
+ Next intIndex
+
+ If Len(strFoundNum) = 0 Or strFoundNum = mDecimalSeparator Then
+ ' No number at all or (more likely) no number after decimal point
+ strFoundNum = -3
+ intNumLength = 0
+ Else
+ ' Check for more than one decimal point (. or ,)
+ intDecPtCount = 0
+ For intIndex = 1 To Len(strFoundNum)
+ If Mid(strFoundNum, intIndex, 1) = mDecimalSeparator Then intDecPtCount = intDecPtCount + 1
+ Next intIndex
+ If intDecPtCount > 1 Then
+ ' more than one intDecPtCount
+ strFoundNum = -4
+ intNumLength = 0
+ Else
+ ' All is fine
+ End If
+ End If
+
+ If intNumLength < 0 Then intNumLength = Len(strFoundNum)
+ ParseNum = CDblSafe(strFoundNum)
+ End If
+
+End Function
+
+' Purpose: Handle parentheses in strExpression; recursive function
+Private Function ParseParentheses(strExpression As String, strExpressionChars() As String, intCharIndex As Integer, intStartingCharIndex As Integer, intNumSizing As Integer) As Double
+ Dim intExpressionLen As Integer
+ Dim intParenthCount As Integer
+ Dim intSearchIndex As Integer, boolMatchFound As Boolean
+ Dim dblWorkNum As Double
+
+ ' Find matching closing parethesis, then recursively call this sub,
+ ' sending the numbers and operators between the parentheses as the text string
+ ' Will return a numeric result, and can then proceed just like this is a number
+ ' except that we must infer what the operator before the parentheses
+ ' should be if a number precedes the parentheses
+ ' Similary, if a number follows the parentheses, must infer that the operator is a *
+
+ intExpressionLen = Len(strExpression)
+
+ intParenthCount = 1
+ For intSearchIndex = intCharIndex + 1 To intExpressionLen
+ Select Case strExpressionChars(intSearchIndex)
+ Case "("
+ intParenthCount = intParenthCount + 1
+ Case ")"
+ intParenthCount = intParenthCount - 1
+ If intParenthCount = 0 Then
+ ' Found matching closing parenthesis
+ boolMatchFound = True
+ Exit For
+ End If
+ End Select
+ Next intSearchIndex
+
+ If Not boolMatchFound Then
+ ' Closing parenthesis not found
+ mCalculatorErrorID = 2: mCalculatorErrorPosition = intCharIndex + intStartingCharIndex
+ Else
+ If intSearchIndex = intCharIndex + 1 Then
+ ' Nothing in between parentheses; assume 0
+ intNumSizing = 0
+ dblWorkNum = 0
+ Else
+ intNumSizing = intSearchIndex - intCharIndex - 1
+ dblWorkNum = PerformMath(Mid(strExpression, intCharIndex + 1, intNumSizing), intCharIndex + 1)
+ End If
+
+ ' Numsizing holds the entire length of the expression, including the parentheses
+ intNumSizing = intNumSizing + 2
+ End If
+
+ ParseParentheses = dblWorkNum
+End Function
+
+' Purpose: Compute the result for strExpression
+Private Function PerformMath(ByVal strExpression As String, ByVal intStartingCharIndex As Integer) As Double
+ ' ( and ) are 40 and 41
+ ' + is 43
+ ' - is 45
+ ' * is 42
+ ' / is 47
+ ' Numbers are 48 to 57
+ ' . is 46
+ ' ^ is 94
+
+ Dim strOperator(50) As String, bin(50) As Double, dblWorkNum As Double
+ Dim intExpressionLen As Integer ' Expression Length
+ Dim intTrack As Integer, intTrackIndex As Integer, intCharIndex As Integer
+ Dim intNumSizing As Integer
+ Dim boolParenthParsed As Boolean, boolInsertMult As Boolean
+ Dim strWork As String, strWork2 As String, strWork3 As String, strWork4 As String
+ Dim strExpressionChars() As String, strReplaceChar As String
+
+On Error GoTo MathErrorHandler
+
+ If mCalculatorErrorID <> 0 Then
+ PerformMath = 0
+ Exit Function
+ End If
+
+ intTrack = 1
+ bin(1) = 0#
+
+ intExpressionLen = Len(strExpression)
+
+ ' Replace all brackets (straight and curly) with parentheses
+ For intCharIndex = 1 To intExpressionLen
+ Select Case strExpression
+ Case "[", "{": strReplaceChar = "("
+ Case "]", "}": strReplaceChar = ")"
+ Case Else: strReplaceChar = ""
+ End Select
+
+ If strReplaceChar <> "" Then
+ strExpression = Left(strExpression, intCharIndex - 1) & strReplaceChar & Mid(strExpression, intCharIndex + 1)
+ End If
+ Next intCharIndex
+
+ ' Replace all instances of a number followed by () followed by a number,
+ ' or )( together with a * for implicit multiplication
+ intCharIndex = 1
+ Do While intCharIndex < Len(strExpression)
+ strWork = Mid(strExpression, intCharIndex, 1)
+ strWork2 = Mid(strExpression, intCharIndex + 1, 1)
+
+ boolInsertMult = False
+ If (IsNumeric(strWork) Or strWork = ".") And strWork2 = "(" Then
+ boolInsertMult = True
+ ElseIf strWork = ")" Then
+ If IsNumeric(strWork2) Or strWork2 = "." Then
+ boolInsertMult = True
+ ElseIf strWork2 = "(" Then
+ boolInsertMult = True
+ End If
+ End If
+ If boolInsertMult Then
+ strExpression = Left(strExpression, intCharIndex) & "*" & Mid(strExpression, intCharIndex + 1)
+ End If
+ intCharIndex = intCharIndex + 1
+ Loop
+
+ ' Store contents of strExpression in an array
+ intExpressionLen = Len(strExpression)
+ ReDim strExpressionChars(intExpressionLen + 3)
+ For intCharIndex = 1 To intExpressionLen
+ strExpressionChars(intCharIndex) = Mid(strExpression, intCharIndex, 1)
+ Next intCharIndex
+
+ For intCharIndex = 1 To intExpressionLen
+ strWork = strExpressionChars(intCharIndex)
+ strWork2 = strExpressionChars(intCharIndex + 1)
+ strWork3 = strExpressionChars(intCharIndex + 2)
+ strWork4 = strExpressionChars(intCharIndex + 3)
+
+ If strWork = "" Then strWork = EMPTY_STRINGCHAR
+ If strWork2 = "" Then strWork2 = EMPTY_STRINGCHAR
+ If strWork3 = "" Then strWork3 = EMPTY_STRINGCHAR
+ If strWork4 = "" Then strWork4 = EMPTY_STRINGCHAR
+ Select Case Asc(strWork)
+ Case 41 ' ), should not be encountered
+ ' Unmatched closing parenthesis
+ mCalculatorErrorID = 3: mCalculatorErrorPosition = intCharIndex + intStartingCharIndex - 1
+ intCharIndex = intExpressionLen
+ Case 43, 45 ' + -
+ If intCharIndex <> 1 Then
+ ' Pretend close parentheses
+ If intTrack > 1 Then
+ Select Case strOperator(intTrack)
+ Case "+": bin(intTrack - 1) = bin(intTrack - 1) + bin(intTrack)
+ Case "-": bin(intTrack - 1) = bin(intTrack - 1) - bin(intTrack)
+ Case "*": bin(intTrack - 1) = bin(intTrack - 1) * bin(intTrack)
+ Case "/": bin(intTrack - 1) = bin(intTrack - 1) / bin(intTrack)
+ Case Else
+ ' Missing operator error
+ mCalculatorErrorID = 8: mCalculatorErrorPosition = intCharIndex + intStartingCharIndex - 1
+ intCharIndex = intExpressionLen
+ End Select
+ bin(intTrack) = 0#
+ strOperator(intTrack) = ""
+ intTrack = intTrack - 1
+ Else
+ ' intTrack error
+ mCalculatorErrorID = 7: mCalculatorErrorPosition = intCharIndex + intStartingCharIndex - 1
+ intCharIndex = intExpressionLen
+ End If
+ End If
+
+ ' Pretend open parentheses
+ intTrack = intTrack + 1
+ strOperator(intTrack) = strWork
+
+ boolParenthParsed = False
+ If strWork2 = "(" Then
+ dblWorkNum = ParseParentheses(strExpression, strExpressionChars, intCharIndex + 1, intStartingCharIndex, intNumSizing)
+ boolParenthParsed = True
+ Else
+ dblWorkNum = ParseNum(Mid(strExpression, intCharIndex + 1), intNumSizing)
+ CatchParsenumErrorInCalculator dblWorkNum
+ End If
+
+ If mCalculatorErrorID = 0 And strExpressionChars(intCharIndex + 1 + intNumSizing) = "^" Then
+ dblWorkNum = DoPower(dblWorkNum, strExpression, intCharIndex, 2, intNumSizing)
+ End If
+
+ If mCalculatorErrorID = 0 Then
+ If dblWorkNum < 0 And Not boolParenthParsed Then
+ ' Misplaced operator
+ mCalculatorErrorID = 6: mCalculatorErrorPosition = intCharIndex + intStartingCharIndex - 1
+ intCharIndex = intExpressionLen
+ Else
+ bin(intTrack) = bin(intTrack) + dblWorkNum
+ intCharIndex = intCharIndex + intNumSizing
+ End If
+ End If
+ Case 42, 47 ' * /
+ boolParenthParsed = False
+ If strWork2 = "(" Then
+ dblWorkNum = ParseParentheses(strExpression, strExpressionChars, intCharIndex + 1, intStartingCharIndex, intNumSizing)
+ boolParenthParsed = True
+ Else
+ dblWorkNum = ParseNum(Mid(strExpression, intCharIndex + 1), intNumSizing)
+ CatchParsenumErrorInCalculator dblWorkNum
+ End If
+
+ If mCalculatorErrorID = 0 And strExpressionChars(intCharIndex + 1 + intNumSizing) = "^" Then
+ ' Take number to power before multiplying
+ dblWorkNum = DoPower(dblWorkNum, strExpression, intCharIndex, 2, intNumSizing)
+ End If
+
+ If mCalculatorErrorID = 0 Then
+ If dblWorkNum < 0 And Not boolParenthParsed Then
+ ' Misplaced operator
+ mCalculatorErrorID = 6: mCalculatorErrorPosition = intCharIndex + intStartingCharIndex - 1
+ intCharIndex = intExpressionLen
+ Else
+ If strExpressionChars(intCharIndex - 1) = "" Or intCharIndex = 1 Then
+ ' Misplaced operator
+ mCalculatorErrorID = 6: mCalculatorErrorPosition = intCharIndex + intStartingCharIndex - 1
+ intCharIndex = intExpressionLen
+ Else
+ Select Case strWork
+ Case "*": bin(intTrack) = bin(intTrack) * dblWorkNum
+ Case "/": bin(intTrack) = bin(intTrack) / dblWorkNum
+ Case Else
+ End Select
+ intCharIndex = intCharIndex + intNumSizing
+ End If
+ End If
+ End If
+ Case 40, 44, 46, 48 To 57 ' (, . or , and Numbers 0 to 9
+ boolParenthParsed = False
+ If strWork = "(" Then
+ dblWorkNum = ParseParentheses(strExpression, strExpressionChars, intCharIndex, intStartingCharIndex, intNumSizing)
+ boolParenthParsed = True
+ Else
+ dblWorkNum = ParseNum(Mid(strExpression, intCharIndex), intNumSizing)
+ CatchParsenumErrorInCalculator dblWorkNum
+ End If
+
+ If mCalculatorErrorID = 0 And intCharIndex = 1 Then
+ If strExpressionChars(intCharIndex + intNumSizing) = "^" Then
+ dblWorkNum = DoPower(dblWorkNum, strExpression, intCharIndex, 1, intNumSizing)
+ End If
+ If boolParenthParsed Or (mCalculatorErrorID = 0 And dblWorkNum >= 0) Then
+ intTrack = intTrack + 1
+ strOperator(intTrack) = "+"
+ bin(intTrack) = bin(intTrack) + dblWorkNum
+ intCharIndex = intCharIndex + intNumSizing - 1
+ Else
+ ' Misplaced Number
+ If mCalculatorErrorID = 0 Then
+ mCalculatorErrorID = 4: mCalculatorErrorPosition = intCharIndex + intStartingCharIndex - 1
+ intCharIndex = intExpressionLen
+ End If
+ End If
+ Else
+ ' ToDo
+ ' Misplaced number ?!?
+ End If
+ Case 65 To 90, 97 To 122 ' Uppercase A to Z and lowercase a to z
+ ' Should not be present
+ mCalculatorErrorID = 1: mCalculatorErrorPosition = intCharIndex + intStartingCharIndex - 1
+ intCharIndex = intExpressionLen
+ Case 94
+ ' Caret
+ ' Should have been encountered and skipped
+ ' Misplaced operator
+ mCalculatorErrorID = 6: mCalculatorErrorPosition = intCharIndex + intStartingCharIndex - 1
+ intCharIndex = intExpressionLen
+ Case Else
+ End Select
+ If mCalculatorErrorID <> 0 Then Exit For
+ Next intCharIndex
+
+ If intTrack > 1 And mCalculatorErrorID = 0 Then
+ ' Pretend close parentheses
+ For intTrackIndex = intTrack To 2 Step -1
+ Select Case strOperator(intTrackIndex)
+ Case "+": bin(intTrackIndex - 1) = bin(intTrackIndex - 1) + bin(intTrackIndex)
+ Case "-": bin(intTrackIndex - 1) = bin(intTrackIndex - 1) - bin(intTrackIndex)
+ Case "*": bin(intTrackIndex - 1) = bin(intTrackIndex - 1) * bin(intTrackIndex)
+ Case "/": bin(intTrackIndex - 1) = bin(intTrackIndex - 1) / bin(intTrackIndex)
+ Case Else
+ ' Missing operator error
+ mCalculatorErrorID = 8: mCalculatorErrorPosition = intCharIndex + intStartingCharIndex - 1
+ intCharIndex = intExpressionLen
+ End Select
+ bin(intTrackIndex) = 0#
+ strOperator(intTrackIndex) = ""
+ Next intTrackIndex
+ End If
+
+ PerformMath = bin(1)
+
+MathStart:
+ Exit Function
+
+MathErrorHandler:
+ If Err = 11 Then
+ MsgBox LookupMessage(91), vbOKOnly + vbExclamation, LookupMessage(350)
+ Else
+ GeneralErrorHandler "frmCalculator|PerformMath", Err.Number, Err.Description
+ End If
+ Resume MathStart
+
+End Function
+
+' Purpose: Position controls on form
+Private Sub PositionFormControls()
+
+ With txtStatus
+ .Top = 720
+ .Left = 120
+ .Width = 4300
+ End With
+
+ With rtfExpression
+ .Font.Name = objMwtWin.RtfFontName
+ .Font.Size = objMwtWin.RtfFontSize
+ .Top = 120
+ .Left = 120
+ .Width = 2500
+ End With
+
+ cmdCalculate.Top = 120
+ cmdCalculate.Left = 3900
+ cmdOK.Top = 600
+ cmdOK.Left = 3000
+
+End Sub
+
+' Purpose: Resize form
+Private Sub ResizeForm()
+ Dim MinFormWidth As Long
+ Dim boolSkipWidthAdjust As Boolean
+
+ If Me.WindowState = vbNormal Then
+ MinFormWidth = TextWidth(txtStatus.Text) + 2100
+ If Me.Width < MinFormWidth Then boolSkipWidthAdjust = True
+ If Me.Height > 1600 Then Me.Height = 1600
+ End If
+
+ If Me.WindowState <> vbMinimized Then
+ ' Position Objects
+ If Not boolSkipWidthAdjust Then
+ rtfExpression.Width = Me.Width - 1900 ' FormulaSingle text box
+ txtStatus.Width = Me.Width - 1900 ' Status Bar
+ cmdCalculate.Left = Me.Width - cmdCalculate.Width - 175 ' Calculate Button
+ cmdOK.Left = Me.Width - cmdCalculate.Width - 50 ' Close
+ End If
+ End If
+
+End Sub
+
+' Purpose: Format rtfExpression when user changes it
+Private Sub UpdateRTFExpression()
+ Dim intSaveLoc As Integer
+
+ boolExpressionChanged = True
+
+ intSaveLoc = rtfExpression.SelStart
+ rtfExpression.TextRTF = objMwtWin.TextToRTF(rtfExpression.Text, True)
+
+ rtfExpression.SelStart = intSaveLoc
+
+End Sub
+
+Private Sub cmdCalculate_Click()
+ InitiateMathCalculate
+ SetMostRecentTextBoxValue rtfExpression.Text
+End Sub
+
+Private Sub cmdOK_Click()
+ HideFormShowMain Me
+End Sub
+
+Private Sub Form_Activate()
+ ' Put window in center of screen
+ SizeAndCenterWindow Me, cWindowLowerThird, 4500, 1600
+ ResizeForm
+ InitiateMathCalculate
+End Sub
+
+Private Sub Form_Load()
+ mnuRightClick.Visible = False
+ PositionFormControls
+End Sub
+
+Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
+ QueryUnloadFormHandler Me, Cancel, UnloadMode
+End Sub
+
+Private Sub Form_Resize()
+ ResizeForm
+End Sub
+
+Private Sub mnuRightClickCopy_Click()
+ CopyRoutinePrivate
+End Sub
+
+Private Sub mnuRightClickCut_Click()
+ CopyRoutinePrivate
+
+ ' Manually need to clear the selected text
+ rtfExpression.SelText = ""
+End Sub
+
+Private Sub mnuRightClickDelete_Click()
+ rtfExpression.SelText = ""
+End Sub
+
+Private Sub mnuRightClickPaste_Click()
+ Dim strPasteText As String
+
+On Error GoTo RightClickPasteErrorHandler
+
+ ' Place text from Clipboard into active control.
+ If Clipboard.GetFormat(vbCFRTF) Then
+ ' rtf on clipboard
+ strPasteText = GetClipboardTextSmart(vbCFRTF)
+ rtfExpression.SelRTF = strPasteText
+ Else
+ strPasteText = GetClipboardTextSmart()
+ rtfExpression.SelText = strPasteText
+ End If
+
+RightClickPasteErrorHandler:
+ GeneralErrorHandler "frmCalculator|mnuRightClickPaste_Click", Err.Number, Err.Description
+
+End Sub
+
+Private Sub mnuRightClickSelectAll_Click()
+ rtfExpression.SelStart = 0
+ rtfExpression.SelLength = Len(rtfExpression.Text)
+End Sub
+
+Private Sub mnuRightClickUndo_Click()
+ rtfExpression.Text = GetMostRecentTextBoxValue()
+End Sub
+
+Private Sub rtfExpression_Change()
+ UpdateRTFExpression
+End Sub
+
+Private Sub rtfExpression_GotFocus()
+ SetMostRecentTextBoxValue rtfExpression.Text
+End Sub
+
+Private Sub rtfExpression_KeyDown(KeyCode As Integer, Shift As Integer)
+
+ If mCalculatorErrorID <> 0 Then
+ ' Reset error flags, then update status line
+ mCalculatorErrorID = 0:
+ LabelStatus
+ End If
+
+End Sub
+
+Private Sub rtfExpression_KeyPress(KeyAscii As Integer)
+ MathTextBoxKeypressHandler KeyAscii
+End Sub
+
+Private Sub rtfExpression_MouseUp(Button As Integer, Shift As Integer, x As Single, y As Single)
+ If Button = vbRightButton Then
+ ShowPopupRightClickMenu Me, rtfExpression, True
+ End If
+End Sub
diff --git a/frmCalculator.frx b/frmCalculator.frx
new file mode 100644
index 0000000..9dd9466
Binary files /dev/null and b/frmCalculator.frx differ
diff --git a/frmCapillaryCalcs.frm b/frmCapillaryCalcs.frm
new file mode 100644
index 0000000..31209fa
--- /dev/null
+++ b/frmCapillaryCalcs.frm
@@ -0,0 +1,2921 @@
+VERSION 5.00
+Object = "{3B7C8863-D78F-101B-B9B5-04021C009402}#1.2#0"; "richtx32.ocx"
+Begin VB.Form frmCapillaryCalcs
+ Caption = "Capillary Flow and Mass Rate Calculations"
+ ClientHeight = 6600
+ ClientLeft = 540
+ ClientTop = 1680
+ ClientWidth = 10770
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 700
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ ForeColor = &H80000008&
+ HelpContextID = 3070
+ Icon = "frmCapillaryCalcs.frx":0000
+ LinkTopic = "Form1"
+ MaxButton = 0 'False
+ PaletteMode = 1 'UseZOrder
+ ScaleHeight = 6600
+ ScaleWidth = 10770
+ Tag = "7000"
+ Begin VB.CommandButton cmdComputeViscosity
+ Caption = "Compute Water/MeCN Viscosity"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 300
+ Left = 240
+ TabIndex = 30
+ Tag = "7740"
+ Top = 2880
+ Width = 2715
+ End
+ Begin VB.Frame fraBroadening
+ Caption = "Extra Column Broadening Calculations"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 2880
+ Left = 120
+ TabIndex = 48
+ Tag = "7350"
+ Top = 3240
+ Visible = 0 'False
+ Width = 10455
+ Begin VB.ComboBox cboCapValue
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 315
+ Index = 18
+ Left = 9240
+ Style = 2 'Dropdown List
+ TabIndex = 94
+ Tag = "7070"
+ Top = 2040
+ Width = 1095
+ End
+ Begin VB.ComboBox cboCapValue
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 315
+ Index = 17
+ Left = 3720
+ Style = 2 'Dropdown List
+ TabIndex = 93
+ Tag = "7070"
+ Top = 2040
+ Width = 1095
+ End
+ Begin VB.ComboBox cboCapValue
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 315
+ Index = 15
+ Left = 3720
+ Style = 2 'Dropdown List
+ TabIndex = 57
+ Tag = "7035"
+ Top = 1320
+ Width = 1815
+ End
+ Begin VB.ComboBox cboCapValue
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 315
+ Index = 16
+ Left = 3720
+ Style = 2 'Dropdown List
+ TabIndex = 60
+ Tag = "7035"
+ Top = 1680
+ Width = 1815
+ End
+ Begin VB.TextBox txtCapValue
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 285
+ Index = 12
+ Left = 2520
+ TabIndex = 82
+ Text = "0.000001"
+ Top = 840
+ Width = 1095
+ End
+ Begin VB.CommandButton cmdViewBroadeningEquations
+ Caption = "View Equations"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 360
+ Left = 240
+ TabIndex = 81
+ Tag = "7730"
+ Top = 2400
+ Width = 1815
+ End
+ Begin VB.TextBox txtCapValue
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 285
+ Index = 16
+ Left = 8160
+ TabIndex = 71
+ Text = "1"
+ Top = 1320
+ Width = 975
+ End
+ Begin VB.TextBox txtCapValue
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 285
+ Index = 15
+ Left = 2520
+ TabIndex = 62
+ Text = "1"
+ Top = 2040
+ Width = 1095
+ End
+ Begin RichTextLib.RichTextBox rtfBdTemporalVarianceUnit
+ Height = 255
+ Left = 9360
+ TabIndex = 69
+ TabStop = 0 'False
+ Tag = "7550"
+ Top = 960
+ Width = 975
+ _ExtentX = 1720
+ _ExtentY = 450
+ _Version = 393217
+ BackColor = -2147483633
+ BorderStyle = 0
+ Appearance = 0
+ TextRTF = $"frmCapillaryCalcs.frx":08CA
+ BeginProperty Font {0BE35203-8F91-11CE-9DE3-00AA004BB851}
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ End
+ Begin VB.TextBox txtCapValue
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 285
+ Index = 14
+ Left = 2520
+ TabIndex = 59
+ Text = "1"
+ Top = 1680
+ Width = 1095
+ End
+ Begin VB.TextBox txtCapValue
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 285
+ Index = 13
+ Left = 2520
+ TabIndex = 56
+ Text = "1"
+ Top = 1320
+ Width = 1095
+ End
+ Begin VB.ComboBox cboCapValue
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 315
+ Index = 14
+ Left = 3720
+ Style = 2 'Dropdown List
+ TabIndex = 52
+ Tag = "7060"
+ Top = 360
+ Width = 1695
+ End
+ Begin VB.TextBox txtCapValue
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 285
+ Index = 11
+ Left = 2520
+ TabIndex = 51
+ Text = "1"
+ Top = 360
+ Width = 1095
+ End
+ Begin VB.CheckBox chkBdLinkLinearVelocity
+ Caption = "&Link to Above"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = 360
+ TabIndex = 50
+ Tag = "7800"
+ Top = 600
+ Width = 2055
+ End
+ Begin RichTextLib.RichTextBox rtfBdAdditionalVarianceUnit
+ Height = 255
+ Left = 9360
+ TabIndex = 72
+ TabStop = 0 'False
+ Tag = "7550"
+ Top = 1320
+ Width = 975
+ _ExtentX = 1720
+ _ExtentY = 450
+ _Version = 393217
+ BackColor = -2147483633
+ BorderStyle = 0
+ Appearance = 0
+ TextRTF = $"frmCapillaryCalcs.frx":093D
+ BeginProperty Font {0BE35203-8F91-11CE-9DE3-00AA004BB851}
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ End
+ Begin RichTextLib.RichTextBox rtfDiffusionCoefficient
+ Height = 255
+ Left = 3720
+ TabIndex = 54
+ TabStop = 0 'False
+ Tag = "7520"
+ Top = 960
+ Width = 1695
+ _ExtentX = 2990
+ _ExtentY = 450
+ _Version = 393217
+ BackColor = -2147483633
+ BorderStyle = 0
+ Enabled = 0 'False
+ Appearance = 0
+ TextRTF = $"frmCapillaryCalcs.frx":09B0
+ BeginProperty Font {0BE35203-8F91-11CE-9DE3-00AA004BB851}
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ End
+ Begin VB.Label lblDiffusionCoefficient
+ Caption = "Diffusion Coefficient"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = 240
+ TabIndex = 53
+ Tag = "7360"
+ Top = 960
+ Width = 2175
+ End
+ Begin VB.Label lblOptimumLinearVelocityBasis
+ Caption = "(for 5 um particles)"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = 5880
+ TabIndex = 66
+ Tag = "7410"
+ Top = 600
+ Width = 2175
+ End
+ Begin VB.Label lblOptimumLinearVelocity
+ Caption = "1"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = 8160
+ TabIndex = 64
+ Top = 360
+ Width = 975
+ End
+ Begin VB.Label lblOptimumLinearVelocityUnit
+ Caption = "cm/sec"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = 9360
+ TabIndex = 65
+ Tag = "7540"
+ Top = 360
+ Width = 975
+ End
+ Begin VB.Label lblOptimumLinearVelocityLabel
+ Caption = "Optimum Linear Velocity"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = 5760
+ TabIndex = 63
+ Tag = "7400"
+ Top = 360
+ Width = 2295
+ End
+ Begin VB.Label lblBdPercentVarianceIncrease
+ Caption = "0%"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = 8160
+ TabIndex = 76
+ Top = 2400
+ Width = 1095
+ End
+ Begin VB.Label lblBdPercentVarianceIncreaseLabel
+ Caption = "Percent Increase"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = 5760
+ TabIndex = 75
+ Tag = "7450"
+ Top = 2400
+ Width = 2295
+ End
+ Begin VB.Label lblBdResultantPeakWidthLabel
+ Caption = "Resulting Peak Width"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = 5760
+ TabIndex = 73
+ Tag = "7440"
+ Top = 2040
+ Width = 2295
+ End
+ Begin VB.Label lblBdResultantPeakWidth
+ Caption = "1"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = 8160
+ TabIndex = 74
+ Top = 2040
+ Width = 975
+ End
+ Begin VB.Label lblBdAdditionalVarianceLabel
+ Caption = "Additional Variance"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = 5760
+ TabIndex = 70
+ Tag = "7430"
+ Top = 1320
+ Width = 2295
+ End
+ Begin VB.Label lblBdInitialPeakWidth
+ Caption = "Initial Peak Width (at base)"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 375
+ Left = 240
+ TabIndex = 61
+ Tag = "7390"
+ Top = 2040
+ Width = 2175
+ End
+ Begin VB.Label lblBdTemporalVarianceLabel
+ Caption = "Temporal Variance"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = 5760
+ TabIndex = 67
+ Tag = "7420"
+ Top = 960
+ Width = 2295
+ End
+ Begin VB.Label lblBdTemporalVariance
+ Caption = "1"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = 8160
+ TabIndex = 68
+ Top = 960
+ Width = 975
+ End
+ Begin VB.Label lblBdOpenTubeLength
+ Caption = "Open Tube Length"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = 240
+ TabIndex = 55
+ Tag = "7370"
+ Top = 1320
+ Width = 2175
+ End
+ Begin VB.Label lblBdOpenTubeID
+ Caption = "Open Tube I.D."
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = 240
+ TabIndex = 58
+ Tag = "7380"
+ Top = 1680
+ Width = 2175
+ End
+ Begin VB.Label lblBdLinearVelocity
+ Caption = "Linear Velocity"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = 240
+ TabIndex = 49
+ Tag = "7260"
+ Top = 360
+ Width = 2175
+ End
+ End
+ Begin VB.ComboBox cboCapValue
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 315
+ Index = 4
+ Left = 3840
+ Style = 2 'Dropdown List
+ TabIndex = 16
+ Tag = "7035"
+ Top = 2520
+ Width = 1815
+ End
+ Begin VB.ComboBox cboCapValue
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 315
+ Index = 1
+ Left = 3840
+ Style = 2 'Dropdown List
+ TabIndex = 7
+ Tag = "7035"
+ Top = 1440
+ Width = 1815
+ End
+ Begin VB.ComboBox cboCapValue
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 315
+ Index = 2
+ Left = 3840
+ Style = 2 'Dropdown List
+ TabIndex = 10
+ Tag = "7035"
+ Top = 1800
+ Width = 1815
+ End
+ Begin VB.TextBox txtCapValue
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 285
+ Index = 6
+ Left = 8280
+ TabIndex = 80
+ Text = "1"
+ Top = 1800
+ Width = 1095
+ End
+ Begin VB.CommandButton cmdViewEquations
+ Caption = "&View Explanatory Equations"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 600
+ Left = 7440
+ TabIndex = 79
+ Tag = "7710"
+ Top = 120
+ Width = 1815
+ End
+ Begin VB.CommandButton cmdShowPeakBroadening
+ Caption = "Show/Hide &Peak Broadening Calculations"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 600
+ Left = 5160
+ TabIndex = 78
+ Tag = "7700"
+ Top = 120
+ Width = 2115
+ End
+ Begin VB.ComboBox cboCapValue
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 315
+ Index = 8
+ Left = 9480
+ Style = 2 'Dropdown List
+ TabIndex = 27
+ Tag = "7080"
+ Top = 2160
+ Width = 1095
+ End
+ Begin VB.ComboBox cboCapValue
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 315
+ Index = 7
+ Left = 9480
+ Style = 2 'Dropdown List
+ TabIndex = 24
+ Tag = "7070"
+ Top = 1800
+ Width = 1095
+ End
+ Begin VB.ComboBox cboCapValue
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 315
+ Index = 6
+ Left = 9480
+ Style = 2 'Dropdown List
+ TabIndex = 22
+ Tag = "7060"
+ Top = 1440
+ Width = 1095
+ End
+ Begin VB.ComboBox cboCapValue
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 315
+ Index = 5
+ Left = 9480
+ Style = 2 'Dropdown List
+ TabIndex = 19
+ Tag = "7050"
+ Top = 1080
+ Width = 1095
+ End
+ Begin VB.ComboBox cboCapValue
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 315
+ Index = 3
+ Left = 3840
+ Style = 2 'Dropdown List
+ TabIndex = 13
+ Tag = "7040"
+ Top = 2160
+ Width = 1815
+ End
+ Begin VB.ComboBox cboCapValue
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 315
+ Index = 0
+ Left = 3840
+ Style = 2 'Dropdown List
+ TabIndex = 4
+ Tag = "7030"
+ Top = 1080
+ Width = 1815
+ End
+ Begin VB.TextBox txtCapValue
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 285
+ Index = 7
+ Left = 9480
+ TabIndex = 29
+ Text = ".4"
+ Top = 2520
+ Width = 975
+ End
+ Begin VB.TextBox txtCapValue
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 285
+ Index = 5
+ Left = 8280
+ TabIndex = 18
+ Text = "1"
+ Top = 1080
+ Width = 1095
+ End
+ Begin VB.TextBox txtCapValue
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 285
+ Index = 4
+ Left = 2640
+ TabIndex = 15
+ Text = "1"
+ Top = 2520
+ Width = 1095
+ End
+ Begin VB.TextBox txtCapValue
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 285
+ Index = 3
+ Left = 2640
+ TabIndex = 12
+ Text = "1"
+ Top = 2160
+ Width = 1095
+ End
+ Begin VB.TextBox txtCapValue
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 285
+ Index = 2
+ Left = 2640
+ TabIndex = 9
+ Text = "1"
+ Top = 1800
+ Width = 1095
+ End
+ Begin VB.TextBox txtCapValue
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 285
+ Index = 1
+ Left = 2640
+ TabIndex = 6
+ Text = "1"
+ Top = 1440
+ Width = 1095
+ End
+ Begin VB.TextBox txtCapValue
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 285
+ Index = 0
+ Left = 2640
+ TabIndex = 3
+ Text = "1"
+ Top = 1080
+ Width = 1095
+ End
+ Begin VB.ComboBox cboComputationType
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 315
+ Left = 240
+ Style = 2 'Dropdown List
+ TabIndex = 1
+ Tag = "7020"
+ Top = 520
+ Width = 4575
+ End
+ Begin VB.Frame fraMassRate
+ Caption = "Mass Rate Calculations"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 1695
+ Left = 120
+ TabIndex = 31
+ Tag = "7300"
+ Top = 3240
+ Width = 10455
+ Begin VB.ComboBox cboCapValue
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 315
+ Index = 13
+ Left = 9120
+ Style = 2 'Dropdown List
+ TabIndex = 47
+ Tag = "7110"
+ Top = 1320
+ Width = 1215
+ End
+ Begin VB.ComboBox cboCapValue
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 315
+ Index = 12
+ Left = 9120
+ Style = 2 'Dropdown List
+ TabIndex = 44
+ Tag = "7100"
+ Top = 360
+ Width = 1215
+ End
+ Begin VB.ComboBox cboCapValue
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 315
+ Index = 11
+ Left = 3720
+ Style = 2 'Dropdown List
+ TabIndex = 41
+ Tag = "7070"
+ Top = 1320
+ Width = 1695
+ End
+ Begin VB.ComboBox cboCapValue
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 315
+ Index = 10
+ Left = 3720
+ Style = 2 'Dropdown List
+ TabIndex = 38
+ Tag = "7050"
+ Top = 720
+ Width = 1695
+ End
+ Begin VB.ComboBox cboCapValue
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 315
+ Index = 9
+ Left = 3720
+ Style = 2 'Dropdown List
+ TabIndex = 34
+ Tag = "7090"
+ Top = 360
+ Width = 1695
+ End
+ Begin VB.TextBox txtCapValue
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 285
+ Index = 10
+ Left = 2520
+ TabIndex = 40
+ Text = "1"
+ Top = 1320
+ Width = 1095
+ End
+ Begin VB.TextBox txtCapValue
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 285
+ Index = 9
+ Left = 2520
+ TabIndex = 37
+ Text = "1"
+ Top = 720
+ Width = 1095
+ End
+ Begin VB.TextBox txtCapValue
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 285
+ Index = 8
+ Left = 2520
+ TabIndex = 33
+ Text = "1"
+ Top = 360
+ Width = 1095
+ End
+ Begin VB.CheckBox chkMassRateLinkFlowRate
+ Caption = "&Link to Above"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = 360
+ TabIndex = 36
+ Tag = "7800"
+ Top = 960
+ Width = 2055
+ End
+ Begin VB.Label lblMolesInjectedLabel
+ Caption = "Moles Injected"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = 5760
+ TabIndex = 45
+ Tag = "7340"
+ Top = 1320
+ Width = 1935
+ End
+ Begin VB.Label lblMolesInjected
+ Caption = "1"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = 8040
+ TabIndex = 46
+ Top = 1320
+ Width = 1095
+ End
+ Begin VB.Label lblMassFlowRateLabel
+ Caption = "Mass Flow Rate"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = 5760
+ TabIndex = 42
+ Tag = "7330"
+ Top = 360
+ Width = 1935
+ End
+ Begin VB.Label lblMassFlowRate
+ Caption = "1"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = 8040
+ TabIndex = 43
+ Top = 360
+ Width = 1095
+ End
+ Begin VB.Label lblMassRateInjectionTime
+ Caption = "Injection Time"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = 240
+ TabIndex = 39
+ Tag = "7320"
+ Top = 1320
+ Width = 2175
+ End
+ Begin VB.Label lblMassRateVolFlowRate
+ Caption = "Volumetric Flow Rate"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = 240
+ TabIndex = 35
+ Tag = "7250"
+ Top = 720
+ Width = 2175
+ End
+ Begin VB.Label lblMassRateConcentration
+ Caption = "Sample Concentration"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = 240
+ TabIndex = 32
+ Tag = "7310"
+ Top = 360
+ Width = 2175
+ End
+ End
+ Begin VB.ComboBox cboCapillaryType
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 315
+ Left = 240
+ Style = 2 'Dropdown List
+ TabIndex = 0
+ Tag = "7010"
+ ToolTipText = "Toggle between open and packed capillaries"
+ Top = 120
+ Width = 2655
+ End
+ Begin VB.CommandButton cmdOK
+ Cancel = -1 'True
+ Caption = "Cl&ose"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 360
+ Left = 9360
+ TabIndex = 77
+ Tag = "4000"
+ Top = 240
+ Width = 1155
+ End
+ Begin VB.Frame fraWeightSource
+ BorderStyle = 0 'None
+ Caption = "Weight Source"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 1575
+ Left = 240
+ TabIndex = 83
+ Top = 5040
+ Width = 5655
+ Begin VB.OptionButton optWeightSource
+ Caption = "&Use mass of compound in current formula"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ HelpContextID = 4010
+ Index = 0
+ Left = 0
+ TabIndex = 86
+ Tag = "7750"
+ Top = 0
+ Value = -1 'True
+ Width = 5475
+ End
+ Begin VB.OptionButton optWeightSource
+ Caption = "&Enter custom numerical mass"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ HelpContextID = 4010
+ Index = 1
+ Left = 0
+ TabIndex = 85
+ Tag = "7760"
+ Top = 240
+ Width = 5475
+ End
+ Begin VB.TextBox txtCustomMass
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 285
+ Left = 3360
+ TabIndex = 84
+ Tag = "7600"
+ Text = "100"
+ ToolTipText = "Enter custom numerical mass for use in computations"
+ Top = 1200
+ Width = 1575
+ End
+ Begin RichTextLib.RichTextBox rtfCurrentFormula
+ Height = 495
+ Left = 2040
+ TabIndex = 87
+ TabStop = 0 'False
+ Top = 600
+ Width = 3615
+ _ExtentX = 6376
+ _ExtentY = 873
+ _Version = 393217
+ Enabled = 0 'False
+ MultiLine = 0 'False
+ Appearance = 0
+ TextRTF = $"frmCapillaryCalcs.frx":0A26
+ End
+ Begin VB.Label lblMWTValue
+ Caption = "1"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = 960
+ TabIndex = 92
+ Top = 1200
+ Width = 1455
+ End
+ Begin VB.Label lblCustomMassUnits
+ Caption = "g/mole"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = 5040
+ TabIndex = 91
+ Tag = "7570"
+ Top = 1200
+ Width = 1095
+ End
+ Begin VB.Label lblMWT
+ Caption = "MW ="
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = 120
+ TabIndex = 90
+ Tag = "7470"
+ Top = 1200
+ Width = 1335
+ End
+ Begin VB.Label lblFormula
+ Caption = "Current Formula is"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = 120
+ TabIndex = 89
+ Tag = "7460"
+ Top = 720
+ Width = 1815
+ End
+ Begin VB.Label lblCustomMass
+ Caption = "Custom Mass:"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = 2280
+ TabIndex = 88
+ Tag = "7480"
+ Top = 1200
+ Width = 2175
+ End
+ End
+ Begin VB.Label lblVolumeLabel
+ Caption = "Column Volume"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = 5880
+ TabIndex = 25
+ Tag = "7280"
+ Top = 2160
+ Width = 2295
+ End
+ Begin VB.Label lblVolume
+ Caption = "1"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = 8280
+ TabIndex = 26
+ Top = 2160
+ Width = 1095
+ End
+ Begin VB.Label lblDeadTimeLabel
+ Caption = "Column Dead Time"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = 5880
+ TabIndex = 23
+ Tag = "7270"
+ Top = 1800
+ Width = 2415
+ End
+ Begin VB.Label lblLinearVelocity
+ Caption = "1"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = 8280
+ TabIndex = 21
+ Top = 1440
+ Width = 1095
+ End
+ Begin VB.Label lblLinearVelocityLabel
+ Caption = "Linear Velocity"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = 5880
+ TabIndex = 20
+ Tag = "7260"
+ Top = 1440
+ Width = 2295
+ End
+ Begin VB.Label lblFlowRateLabel
+ Caption = "Volumetric Flow Rate"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = 5880
+ TabIndex = 17
+ Tag = "7250"
+ Top = 1080
+ Width = 2295
+ End
+ Begin VB.Label lblPorosity
+ Caption = "Interparticle Porosity (epsilon)"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = 5880
+ TabIndex = 28
+ Tag = "7290"
+ Top = 2520
+ Width = 3495
+ End
+ Begin VB.Label lblParticleDiameter
+ Caption = "Particle Diameter"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = 240
+ TabIndex = 14
+ Tag = "7240"
+ Top = 2520
+ Width = 2295
+ End
+ Begin VB.Label lblViscosity
+ Caption = "Solvent Viscosity"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = 240
+ TabIndex = 11
+ Tag = "7230"
+ Top = 2160
+ Width = 2295
+ End
+ Begin VB.Label lblColumnID
+ Caption = "Column Inner Diameter"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = 240
+ TabIndex = 8
+ Tag = "7220"
+ Top = 1800
+ Width = 2295
+ End
+ Begin VB.Label lblLength
+ Caption = "Column Length"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = 240
+ TabIndex = 5
+ Tag = "7210"
+ Top = 1440
+ Width = 2295
+ End
+ Begin VB.Label lblPressure
+ Caption = "Back Pressure"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = 240
+ TabIndex = 2
+ Tag = "7200"
+ Top = 1080
+ Width = 2295
+ End
+ Begin VB.Menu mnuFile
+ Caption = "&File"
+ Begin VB.Menu mnuLoadCapValues
+ Caption = "&Load Values"
+ End
+ Begin VB.Menu mnuSaveCapValues
+ Caption = "&Save Values"
+ End
+ Begin VB.Menu mnuSep1
+ Caption = "-"
+ End
+ Begin VB.Menu mnuClose
+ Caption = "&Close"
+ End
+ End
+ Begin VB.Menu mnuHelp
+ Caption = "&Help"
+ Begin VB.Menu mnuCapillaryFlowHelp
+ Caption = "&Capillary Flow Calculations"
+ End
+ End
+End
+Attribute VB_Name = "frmCapillaryCalcs"
+Attribute VB_GlobalNameSpace = False
+Attribute VB_Creatable = False
+Attribute VB_PredeclaredId = True
+Attribute VB_Exposed = False
+Option Explicit
+
+' Subs ResizeCapillaryCalcsForm and ShowHideWeightSource in frmCapillaryCalcs
+' use cConcentrationUnitsFirstWeightIndex to determine whether
+' weight-based (mg/mL) or mole-based (Molar) mass units are being used
+Private Const cConcentrationUnitsFirstWeightIndex = 7
+
+Private Enum cptComputationTypeConstants
+ cptBackPressure = 0
+ cptColumnLength = 1
+ cptColumnID = 2
+ cptVolFlowRate = 3
+ cptVolFlowRateUsingDeadTime = 4
+End Enum
+
+' Constants for Combo Boxes on Capillay Calcs form
+Private Enum caCapillaryActionConstants
+ caFindBackPressure = 0
+ caFindColumnLength = 1
+ caFindInnerDiameter = 2
+ caFindVolFlowRateUsingPressure = 3
+ caFindVolFlowUsingDeadTime = 4
+End Enum
+
+Private Const CAPILLARY_CALCS_FORM_INITIAL_WIDTH = 10800
+Private Const CAPILLARY_CALCS_FORM_INITIAL_HEIGHT = 6000
+
+' Note: Other forms access this variable
+Public eMassMode As mmcMassModeConstants
+
+' Form-wide variables
+Private mDefaultCapValuesLoaded As Boolean
+Private mUpdatingCapValues As Boolean
+Private eColumnIDUnitsIndexSaved As ulnUnitsLengthConstants
+
+Private objCapillaryFlow As New MWCapillaryFlowClass
+
+' Purpose: Examines current computation type and checks to see if user (or code)
+' is attempting to modify a text box in which a result will be placed
+' If they (or the code) is, then do not allow any of the auto-update cascade events to fire
+Private Function CheckDoNotModify(eTextBoxID As cctCapCalcTextBoxIDConstants) As Boolean
+
+ Dim blnDoNotModify As Boolean
+
+ Select Case cboComputationType.ListIndex
+ Case caFindBackPressure
+ If eTextBoxID = cctPressure Then blnDoNotModify = True
+ Case caFindColumnLength
+ If eTextBoxID = cctColumnLength Then blnDoNotModify = True
+ Case caFindInnerDiameter
+ If eTextBoxID = cctColumnID Then blnDoNotModify = True
+ Case caFindVolFlowRateUsingPressure
+ If eTextBoxID = cctFlowRate Then blnDoNotModify = True
+ Case caFindVolFlowUsingDeadTime
+ ' Finding Vol. Flow rate and pressure using dead time; do not auto-compute on change
+ If eTextBoxID = cctPressure Or eTextBoxID = cctFlowRate Then blnDoNotModify = True
+ End Select
+
+ CheckDoNotModify = blnDoNotModify
+End Function
+
+' Purpose: Copy flow info from txtFlowRate to txtMassRateVolFlowRate
+Private Sub CopyFlowRate()
+ ' Use a static variable to prevent infinite loops from occurring
+ Static blnCopyingFlowRate As Boolean
+
+ If Not blnCopyingFlowRate Then
+ If cChkBox(chkMassRateLinkFlowRate) Then
+ blnCopyingFlowRate = True
+
+ txtCapValue(cctMassRateVolFlowRate).Text = txtCapValue(cctFlowRate).Text
+ cboCapValue(cccMassRateVolFlowRateUnits).ListIndex = cboCapValue(cccFlowRateUnits).ListIndex
+
+ blnCopyingFlowRate = False
+ End If
+ End If
+End Sub
+
+' Purpose: Copy velocity info from lblLinearVelocity to txtBdLinearVelocity
+Private Sub CopyLinearVelocity()
+ txtCapValue(cctBdLinearVelocity).Text = lblLinearVelocity.Caption
+ cboCapValue(cccBdLinearVelocityUnits).ListIndex = cboCapValue(cccLinearVelocityUnits).ListIndex
+End Sub
+
+' Purpose: Put appropriate labels in RTF boxes (labels change based on language)
+Private Sub FillRTFBoxes()
+ Dim strRtfText As String, strRtfPreString As String, strRtfTwoSquared As String
+ Dim strWorkingCaption As String, strNumerator As String, strDenominator As String
+ Dim intCaretLoc As Integer
+
+ ' Put text in RTF text boxes
+ strRtfPreString = "{\rtf1\ansi\ansicpg1252\deff0\deftab720{\fonttbl{\f0\fswiss MS Sans Serif;}{\f1\froman\fcharset2 Symbol;}{\f2\froman Times New Roman;}{\f3\fswiss MS Sans Serif;}{\f4\froman Times New Roman;}}"
+ strRtfPreString = strRtfPreString & "{\colortbl\red0\green0\blue0;\red255\green255\blue255;}"
+ strRtfPreString = strRtfPreString & "\deflang1033\pard\plain\f0\fs16 "
+ strRtfTwoSquared = "\plain\f0\fs16\up3 2\plain\f0\fs16 "
+
+ strWorkingCaption = LookupLanguageCaption(7520, "cm^2/sec")
+ intCaretLoc = InStr(strWorkingCaption, "^")
+ If InStr(strWorkingCaption, "^") Then
+ strNumerator = Left(strWorkingCaption, intCaretLoc - 1)
+ strDenominator = Mid(strWorkingCaption, intCaretLoc + 2)
+ Else
+ strNumerator = "cm"
+ strDenominator = "/sec"
+ End If
+
+ strRtfText = strRtfPreString & strNumerator & strRtfTwoSquared & strDenominator
+ strRtfText = strRtfText & "\par }"
+ rtfDiffusionCoefficient.TextRTF = strRtfText
+
+ strWorkingCaption = LookupLanguageCaption(7550, "sec^2")
+ intCaretLoc = InStr(strWorkingCaption, "^")
+ If InStr(strWorkingCaption, "^") Then
+ strNumerator = Left(strWorkingCaption, intCaretLoc - 1)
+ Else
+ strNumerator = "sec"
+ End If
+
+ strRtfText = strRtfPreString & strNumerator & strRtfTwoSquared & "\par }"
+ rtfBdTemporalVarianceUnit.TextRTF = strRtfText
+ rtfBdAdditionalVarianceUnit.TextRTF = strRtfText
+
+
+End Sub
+
+Private Sub FindDesiredValue()
+ Dim dblValue As Double, dblNewBackPressure As Double
+
+ Select Case cboComputationType.ListIndex
+ Case cptBackPressure
+ dblValue = objCapillaryFlow.ComputeBackPressure(cboCapValue(cccPressureUnits).ListIndex)
+ FormatTextBox txtCapValue(cctPressure), dblValue
+
+ Case cptColumnLength
+ dblValue = objCapillaryFlow.ComputeColumnLength(cboCapValue(cccColumnLengthUnits).ListIndex)
+ FormatTextBox txtCapValue(cctColumnLength), dblValue
+
+ Case cptColumnID
+ dblValue = objCapillaryFlow.ComputeColumnID(cboCapValue(cccColumnIDUnits).ListIndex)
+ FormatTextBox txtCapValue(cctColumnID), dblValue
+
+ Case cptVolFlowRateUsingDeadTime
+ dblValue = objCapillaryFlow.ComputeVolFlowRateUsingDeadTime(cboCapValue(cccFlowRateUnits).ListIndex, dblNewBackPressure, cboCapValue(cccPressureUnits).ListIndex)
+ FormatTextBox txtCapValue(cctFlowRate), dblValue
+ FormatTextBox txtCapValue(cctPressure), dblNewBackPressure
+
+ Case Else ' Includes cptVolFlowRate
+ dblValue = objCapillaryFlow.ComputeVolFlowRate(cboCapValue(cccFlowRateUnits).ListIndex)
+ FormatTextBox txtCapValue(cctFlowRate), dblValue
+ End Select
+
+ ' Update Linear Velocity (it is auto-computed by any of the above calls to objCapillaryFlow)
+ dblValue = objCapillaryFlow.GetLinearVelocity(cboCapValue(cccLinearVelocityUnits).ListIndex)
+ FormatLabel lblLinearVelocity, dblValue
+
+ ' Update the dead time, unless we computed the flow rate using the dead time
+ If cboComputationType.ListIndex <> cptVolFlowRateUsingDeadTime Then
+ dblValue = objCapillaryFlow.GetDeadTime(cboCapValue(cccDeadTimeUnits).ListIndex)
+ FormatTextBox txtCapValue(cctDeadTime), dblValue
+ End If
+
+ ' Update the column volume
+ dblValue = objCapillaryFlow.GetColumnVolume(cboCapValue(cccVolumeUnits).ListIndex)
+ FormatLabel lblVolume, dblValue
+
+End Sub
+
+Private Sub FindMassRate()
+ Dim dblValue As Double
+
+ If Not mDefaultCapValuesLoaded Then Exit Sub
+
+ ' Note: This automatically calls ComputeMassRateValues which computes
+ ' the Mass Flow Rate and Moles Injected
+ objCapillaryFlow.SetMassRateSampleMass GetWorkingMass()
+
+ dblValue = objCapillaryFlow.GetMassFlowRate(cboCapValue(cccMassFlowRateUnits).ListIndex)
+ FormatLabel lblMassFlowRate, dblValue
+
+ dblValue = objCapillaryFlow.GetMassRateMolesInjected(cboCapValue(cccMassRateMolesInjectedUnits).ListIndex)
+ FormatLabel lblMolesInjected, dblValue
+
+End Sub
+
+Private Sub FindBroadening()
+
+ Dim dblInitialPeakWidthInSec As Double, dblResultantPeakWidthInSec As Double
+ Dim dblPercentIncrease As Double
+ Dim dblValue As Double
+
+ ' Note: This will calculate the temporal variance, in addition to the resultant peak width
+ dblValue = objCapillaryFlow.ComputeExtraColumnBroadeningResultantPeakWidth(cboCapValue(cccBdResultantPeakWidthUnits).ListIndex)
+ FormatLabel lblBdResultantPeakWidth, dblValue
+
+ dblValue = objCapillaryFlow.GetExtraColumnBroadeningTemporalVarianceInSquareSeconds()
+ FormatLabel lblBdTemporalVariance, dblValue
+
+ ' The peak widths were computed above
+ ' Simply retrieve them, using seconds as the unit, and compute the percent increase in the peak width
+ dblInitialPeakWidthInSec = objCapillaryFlow.GetExtraColumnBroadeningInitialPeakWidthAtBase(utmSeconds)
+ dblResultantPeakWidthInSec = objCapillaryFlow.GetExtraColumnBroadeningResultantPeakWidth(utmSeconds)
+
+ If dblInitialPeakWidthInSec <> 0 Then
+ dblPercentIncrease = (dblResultantPeakWidthInSec - dblInitialPeakWidthInSec) / dblInitialPeakWidthInSec * 100
+ Else
+ dblPercentIncrease = 0
+ End If
+
+ lblBdPercentVarianceIncrease.Caption = Format(dblPercentIncrease / 100, "##0.0%")
+
+End Sub
+
+Private Sub FindOptimumLinearVelocity()
+ ' ToDo: Make this update the linear velocity
+
+ Dim dblOptimumLinearVelocity As Double, strCaptionWork As String
+ Dim intNumStartLoc As Integer, intNumEndLoc As Integer, intIndex As Integer
+
+ dblOptimumLinearVelocity = objCapillaryFlow.ComputeOptimumLinearVelocityUsingParticleDiamAndDiffusionCoeff(cboCapValue(cccLinearVelocityUnits).ListIndex)
+
+ FormatLabel lblOptimumLinearVelocity, dblOptimumLinearVelocity
+ lblOptimumLinearVelocityUnit = cboCapValue(cccLinearVelocityUnits).Text
+
+ strCaptionWork = LookupLanguageCaption(7410, "(for 5 um particles)")
+ intNumEndLoc = -1
+ intNumStartLoc = -1
+ For intIndex = 1 To Len(strCaptionWork)
+ If intNumStartLoc <= 0 Then
+ If IsNumeric(Mid(strCaptionWork, intIndex, 1)) Then
+ intNumStartLoc = intIndex
+ End If
+ Else
+ If Not IsNumeric(Mid(strCaptionWork, intIndex, 1)) Then
+ intNumEndLoc = intIndex - 1
+ Exit For
+ End If
+ End If
+ Next intIndex
+
+ With txtCapValue(cctParticleDiamter)
+ If intNumEndLoc > 0 And intNumStartLoc > 0 Then
+ strCaptionWork = Left(strCaptionWork, intNumStartLoc - 1) & Trim(.Text) & _
+ Mid(strCaptionWork, intNumEndLoc + 1)
+ lblOptimumLinearVelocityBasis.Caption = strCaptionWork
+ Else
+ lblOptimumLinearVelocityBasis.Caption = "(for " & Trim(.Text) & " um particles)"
+ End If
+ End With
+
+End Sub
+
+' Purpose: Get working mass from lblMwtValue or txtCustomMass
+Private Function GetWorkingMass() As Double
+ If eMassMode = 0 Then
+ GetWorkingMass = CDblSafe(lblMWTValue.Caption)
+ Else
+ GetWorkingMass = CDblSafe(txtCustomMass.Text)
+ End If
+End Function
+
+' Purpose: Change background color of text boxes to indicate which is being found
+Private Sub HighlightTargetBoxes()
+ Dim ctlThisControl As Control, strControlType As String
+ Dim lngHighlightedColor As Long
+
+ For Each ctlThisControl In Me.Controls
+ strControlType = TypeName(ctlThisControl)
+ If strControlType = "TextBox" Then
+ ctlThisControl.BackColor = QBColor(COLOR_WHITE)
+ End If
+ Next
+
+ ' 7, 10, and 14 are good colors for QBColor()
+ lngHighlightedColor = QBColor(COLOR_COMPUTEDQUANTITY)
+ Select Case cboComputationType.ListIndex
+ Case caFindBackPressure
+ txtCapValue(cctPressure).BackColor = lngHighlightedColor
+ Case caFindColumnLength
+ txtCapValue(cctColumnLength).BackColor = lngHighlightedColor
+ Case caFindInnerDiameter
+ txtCapValue(cctColumnID).BackColor = lngHighlightedColor
+ Case caFindVolFlowRateUsingPressure
+ txtCapValue(cctFlowRate).BackColor = lngHighlightedColor
+ Case caFindVolFlowUsingDeadTime
+ ' Finding Vol. Flow rate and pressure using dead time; do not auto-compute on change
+ txtCapValue(cctPressure).BackColor = lngHighlightedColor
+ txtCapValue(cctFlowRate).BackColor = lngHighlightedColor
+ End Select
+
+ If cboComputationType.ListIndex <> caFindVolFlowUsingDeadTime Then
+ txtCapValue(cctDeadTime).BackColor = lngHighlightedColor
+ End If
+
+End Sub
+
+' Purpose: Load the default capillary form values
+Private Sub LoadCapFormValues()
+ Dim intIndex As Integer
+
+On Error GoTo LoadCapFormValuesErrorHandler
+
+ If Not mDefaultCapValuesLoaded Then Exit Sub
+
+ mUpdatingCapValues = True
+
+ cboComputationType.ListIndex = gCapFlowComputationTypeSave
+ chkMassRateLinkFlowRate.value = gCapFlowLinkMassRateFlowRateSave
+ chkBdLinkLinearVelocity.value = gCapFlowLinkBdLinearVelocitySave
+
+ If gCapFlowShowPeakBroadeningSave = 1 And fraBroadening.Visible = False Then
+ ShowHideBroadeningFrame
+ End If
+
+ If cboCapillaryType.ListIndex = ctOpenTubularCapillary Then
+ ' Open Capillary
+ For intIndex = 0 To CapTextBoxMaxIndex
+ txtCapValue(intIndex).Text = Trim(CStr(OpenCapVals.TextValues(intIndex)))
+ Next intIndex
+
+ For intIndex = 0 To CapComboBoxMaxIndex
+ If OpenCapVals.ComboValues(intIndex) < cboCapValue(intIndex).ListCount Then
+ cboCapValue(intIndex).ListIndex = OpenCapVals.ComboValues(intIndex)
+ End If
+ Next intIndex
+ Else
+ ' Packed Capillary
+ For intIndex = 0 To CapTextBoxMaxIndex
+ txtCapValue(intIndex).Text = Trim(CStr(PackedCapVals.TextValues(intIndex)))
+ Next intIndex
+
+ For intIndex = 0 To CapComboBoxMaxIndex
+ If PackedCapVals.ComboValues(intIndex) < cboCapValue(intIndex).ListCount Then
+ cboCapValue(intIndex).ListIndex = PackedCapVals.ComboValues(intIndex)
+ End If
+ Next intIndex
+
+ End If
+
+ eColumnIDUnitsIndexSaved = cboCapValue(cccColumnIDUnits).ListIndex
+ mUpdatingCapValues = False
+
+ Exit Sub
+
+LoadCapFormValuesErrorHandler:
+ Debug.Print "Error in LoadCapFormValues"
+ Debug.Assert False
+ Resume Next
+End Sub
+
+' Purpose: Populate the combo boxes with the valid choices (language specific)
+Private Sub PopulateComboBoxes()
+ Dim intIndex As Integer
+
+ ' Load Amount types in the Combo Boxes
+
+ PopulateComboBox cboCapillaryType, True, "Open Tubular Capillary|Packed Capillary", 0 '7010
+ PopulateComboBox cboComputationType, True, "Find Back Pressure|Find Column Length|Find Inner Diameter|Find Volumetric Flow rate|Find Flow Rate using Dead Time", 3 '7020
+
+ PopulateComboBox cboCapValue(cccPressureUnits), True, "psi|Pascals|kiloPascals|Atmospheres|Bar|Torr (mm Hg)|dynes/cm^2", 0 '7030
+
+ PopulateComboBox cboCapValue(cccColumnLengthUnits), True, "m|cm|mm|um|inches", 1 '7035
+ PopulateComboBox cboCapValue(cccColumnIDUnits), True, "m|cm|mm|um|inches", 3 '7035
+
+ PopulateComboBox cboCapValue(cccViscosityUnits), True, "Poise [g/(cm-sec)]|centiPoise", 0 '7040
+
+ With cboCapValue(cccParticleDiameterUnits) '7035 Dup
+ For intIndex = 0 To cboCapValue(cccColumnIDUnits).ListCount - 1
+ .AddItem cboCapValue(cccColumnIDUnits).List(intIndex)
+ Next intIndex
+ .ListIndex = cboCapValue(cccColumnIDUnits).ListIndex
+ End With
+
+ PopulateComboBox cboCapValue(cccFlowRateUnits), True, "mL/min|uL/min|nL/min", 2 '7050
+ PopulateComboBox cboCapValue(cccLinearVelocityUnits), True, "cm/hr|mm/hr|cm/min|mm/min|cm/sec|mm/sec", 4 '7060
+ PopulateComboBox cboCapValue(cccDeadTimeUnits), True, "hours|minutes|seconds", 2 '7070
+ PopulateComboBox cboCapValue(cccVolumeUnits), True, "mL|uL|nL|pL", 2 '7080
+
+ ' Note: Subs ResizeCapillaryCalcsForm and ShowHideWeightSource use
+ ' cConcentrationUnitsFirstWeightIndex to determine whether
+ ' weight-based (mg/mL) or mole-based (Molar) mass units are being used
+ ' Be sure to change cConcentrationUnitsFirstWeightIndex if necessary if
+ ' modifying the following units
+ PopulateComboBox cboCapValue(cccMassRateConcentrationUnits), True, "Molar|milliMolar|microMolar|nanoMolar|picoMolar|femtoMolar|attoMolar|mg/mL|ug/mL|ng/mL|ug/uL|ng/uL", 2 '7090
+
+ With cboCapValue(cccMassRateVolFlowRateUnits) ' 7050 Dup
+ For intIndex = 0 To cboCapValue(cccFlowRateUnits).ListCount - 1
+ .AddItem cboCapValue(cccFlowRateUnits).List(intIndex)
+ Next intIndex
+ .ListIndex = cboCapValue(cccFlowRateUnits).ListIndex
+ End With
+
+ With cboCapValue(cccMassRateInjectionTimeUnits) '7070 Dup
+ For intIndex = 0 To cboCapValue(cccDeadTimeUnits).ListCount - 1
+ .AddItem cboCapValue(cccDeadTimeUnits).List(intIndex)
+ Next intIndex
+ .ListIndex = cboCapValue(cccDeadTimeUnits).ListIndex
+ End With
+
+ PopulateComboBox cboCapValue(cccMassFlowRateUnits), True, "pmol/min|fmol/min|amol/min|pmol/sec|fmol/sec|amol/sec", 4 '7100
+ PopulateComboBox cboCapValue(cccMassRateMolesInjectedUnits), True, "Moles|milliMoles|microMoles|nanoMoles|picoMoles|femtoMoles|attoMoles", 5 '7110
+
+ With cboCapValue(cccBdLinearVelocityUnits) '7060 Dup
+ For intIndex = 0 To cboCapValue(cccLinearVelocityUnits).ListCount - 1
+ .AddItem cboCapValue(cccLinearVelocityUnits).List(intIndex)
+ Next intIndex
+ .ListIndex = cboCapValue(cccLinearVelocityUnits).ListIndex
+ End With
+
+ With cboCapValue(cccBdOpenTubeLengthUnits) '7035 Dup
+ For intIndex = 0 To cboCapValue(cccColumnLengthUnits).ListCount - 1
+ .AddItem cboCapValue(cccColumnLengthUnits).List(intIndex)
+ Next intIndex
+ .ListIndex = cboCapValue(cccColumnLengthUnits).ListIndex
+ End With
+
+ With cboCapValue(cccBdOpenTubeIDUnits) '7035 Dup
+ For intIndex = 0 To cboCapValue(cccColumnIDUnits).ListCount - 1
+ .AddItem cboCapValue(cccColumnIDUnits).List(intIndex)
+ Next intIndex
+ .ListIndex = cboCapValue(cccColumnIDUnits).ListIndex
+ End With
+
+ With cboCapValue(cccBdInitialPeakWidthUnits) '7070 Dup
+ For intIndex = 0 To cboCapValue(cccDeadTimeUnits).ListCount - 1
+ .AddItem cboCapValue(cccDeadTimeUnits).List(intIndex)
+ Next intIndex
+ .ListIndex = 2
+ End With
+
+ With cboCapValue(cccBdResultantPeakWidthUnits) '7070 Dup
+ For intIndex = 0 To cboCapValue(cccBdInitialPeakWidthUnits).ListCount - 1
+ .AddItem cboCapValue(cccBdInitialPeakWidthUnits).List(intIndex)
+ Next intIndex
+ .ListIndex = cboCapValue(cccBdInitialPeakWidthUnits).ListIndex
+ End With
+
+End Sub
+
+' Purpose: Position controls on the form
+Private Sub PositionFormControls()
+ Dim RowSpacing As Integer, LabelAdjust As Integer
+ RowSpacing = 360
+ LabelAdjust = 30
+
+ mDefaultCapValuesLoaded = False
+
+ fraBroadening.Visible = False
+ fraWeightSource.Visible = False
+
+ cboCapillaryType.Top = 160
+ cboCapillaryType.Left = 240
+ cboComputationType.Top = 520
+ cboComputationType.Left = cboCapillaryType.Left
+
+ cmdShowPeakBroadening.Top = cboCapillaryType.Top - 40
+ cmdShowPeakBroadening.Left = 5160
+
+ cmdViewEquations.Top = cmdViewEquations.Top
+ cmdViewEquations.Left = 7440
+
+ cmdOK.Top = 240
+ cmdOK.Left = 9360
+
+ lblPressure.Top = 1080
+ lblPressure.Left = cboCapillaryType.Left
+ txtCapValue(cctPressure).Top = lblPressure.Top - LabelAdjust
+ txtCapValue(cctPressure).Left = 2640
+ cboCapValue(cccPressureUnits).Top = lblPressure.Top - LabelAdjust
+ cboCapValue(cccPressureUnits).Left = 3840
+
+ lblLength.Top = lblPressure.Top + RowSpacing * 1
+ lblLength.Left = cboCapillaryType.Left
+ txtCapValue(cctColumnLength).Top = lblLength.Top - LabelAdjust
+ txtCapValue(cctColumnLength).Left = txtCapValue(cctPressure).Left
+ cboCapValue(cccColumnLengthUnits).Top = lblLength.Top - LabelAdjust
+ cboCapValue(cccColumnLengthUnits).Left = cboCapValue(cccPressureUnits).Left
+
+ lblColumnID.Top = lblPressure.Top + RowSpacing * 2
+ lblColumnID.Left = cboCapillaryType.Left
+ txtCapValue(cctColumnID).Top = lblColumnID.Top - LabelAdjust
+ txtCapValue(cctColumnID).Left = txtCapValue(cctPressure).Left
+ cboCapValue(cccColumnIDUnits).Top = lblColumnID.Top - LabelAdjust
+ cboCapValue(cccColumnIDUnits).Left = cboCapValue(cccPressureUnits).Left
+
+ lblViscosity.Top = lblPressure.Top + RowSpacing * 3
+ lblViscosity.Left = cboCapillaryType.Left
+ txtCapValue(cctViscosity).Top = lblViscosity.Top - LabelAdjust
+ txtCapValue(cctViscosity).Left = txtCapValue(cctPressure).Left
+ cboCapValue(cccViscosityUnits).Top = lblViscosity.Top - LabelAdjust
+ cboCapValue(cccViscosityUnits).Left = cboCapValue(cccPressureUnits).Left
+
+ lblParticleDiameter.Top = lblPressure.Top + RowSpacing * 4
+ lblParticleDiameter.Left = cboCapillaryType.Left
+ txtCapValue(cctParticleDiamter).Top = lblParticleDiameter.Top - LabelAdjust
+ txtCapValue(cctParticleDiamter).Left = txtCapValue(cctPressure).Left
+ cboCapValue(cccParticleDiameterUnits).Top = lblParticleDiameter.Top - LabelAdjust
+ cboCapValue(cccParticleDiameterUnits).Left = cboCapValue(cccPressureUnits).Left
+
+ lblFlowRateLabel.Top = lblPressure.Top
+ lblFlowRateLabel.Left = 5880
+ txtCapValue(cctFlowRate).Top = lblFlowRateLabel.Top - LabelAdjust
+ txtCapValue(cctFlowRate).Left = 8280
+ cboCapValue(cccFlowRateUnits).Top = lblFlowRateLabel.Top - LabelAdjust
+ cboCapValue(cccFlowRateUnits).Left = 9480
+
+ lblLinearVelocityLabel.Top = lblFlowRateLabel.Top + RowSpacing
+ lblLinearVelocityLabel.Left = lblFlowRateLabel.Left
+ lblLinearVelocity.Top = lblLinearVelocityLabel.Top
+ lblLinearVelocity.Left = txtCapValue(cctFlowRate).Left + 40
+ cboCapValue(cccLinearVelocityUnits).Top = lblLinearVelocityLabel.Top - LabelAdjust
+ cboCapValue(cccLinearVelocityUnits).Left = cboCapValue(cccFlowRateUnits).Left
+
+ lblDeadTimeLabel.Top = lblFlowRateLabel.Top + RowSpacing * 2
+ lblDeadTimeLabel.Left = lblFlowRateLabel.Left
+ txtCapValue(cctDeadTime).Top = lblDeadTimeLabel.Top - LabelAdjust
+ txtCapValue(cctDeadTime).Left = txtCapValue(cctFlowRate).Left
+ cboCapValue(cccDeadTimeUnits).Top = lblDeadTimeLabel.Top - LabelAdjust
+ cboCapValue(cccDeadTimeUnits).Left = cboCapValue(cccFlowRateUnits).Left
+
+ lblVolumeLabel.Top = lblFlowRateLabel.Top + RowSpacing * 3
+ lblVolumeLabel.Left = lblFlowRateLabel.Left
+ lblVolume.Top = lblVolumeLabel.Top
+ lblVolume.Left = txtCapValue(cctFlowRate).Left + 40
+ cboCapValue(cccVolumeUnits).Top = lblVolumeLabel.Top - LabelAdjust
+ cboCapValue(cccVolumeUnits).Left = cboCapValue(cccFlowRateUnits).Left
+
+ lblPorosity.Top = lblFlowRateLabel.Top + RowSpacing * 4
+ lblPorosity.Left = lblFlowRateLabel.Left
+ txtCapValue(cctPorosity).Top = lblPorosity.Top - LabelAdjust
+ txtCapValue(cctPorosity).Left = cboCapValue(cccFlowRateUnits).Left
+
+ cmdComputeViscosity.Top = lblPressure.Top + RowSpacing * 5
+ cmdComputeViscosity.Left = 240
+
+ fraMassRate.Top = cmdComputeViscosity.Top + cmdComputeViscosity.Height + 140
+ fraMassRate.Left = 120
+
+ lblMassRateConcentration.Top = 300
+ lblMassRateConcentration.Left = 240
+ txtCapValue(cctMassRateConcentration).Top = lblMassRateConcentration.Top - LabelAdjust
+ txtCapValue(cctMassRateConcentration).Left = 2520
+ cboCapValue(cccMassRateConcentrationUnits).Top = lblMassRateConcentration.Top - LabelAdjust
+ cboCapValue(cccMassRateConcentrationUnits).Left = 3720
+
+ lblMassRateVolFlowRate.Top = lblMassRateConcentration.Top + RowSpacing
+ lblMassRateVolFlowRate.Left = lblMassRateConcentration.Left
+ txtCapValue(cctMassRateVolFlowRate).Top = lblMassRateVolFlowRate.Top + 80
+ txtCapValue(cctMassRateVolFlowRate).Left = txtCapValue(cctMassRateConcentration).Left
+ cboCapValue(cccMassRateVolFlowRateUnits).Top = txtCapValue(cctMassRateVolFlowRate).Top
+ cboCapValue(cccMassRateVolFlowRateUnits).Left = cboCapValue(cccMassRateConcentrationUnits).Left
+ chkMassRateLinkFlowRate.Top = lblMassRateVolFlowRate.Top + 240
+ chkMassRateLinkFlowRate.Left = lblMassRateConcentration.Left + 240
+
+ lblMassRateInjectionTime.Top = lblMassRateVolFlowRate.Top + 600
+ lblMassRateInjectionTime.Left = lblMassRateConcentration.Left
+ txtCapValue(cctMassRateInjectionTime).Top = lblMassRateInjectionTime.Top - LabelAdjust
+ txtCapValue(cctMassRateInjectionTime).Left = txtCapValue(cctMassRateConcentration).Left
+ cboCapValue(cccMassRateInjectionTimeUnits).Top = lblMassRateInjectionTime.Top - LabelAdjust
+ cboCapValue(cccMassRateInjectionTimeUnits).Left = cboCapValue(cccMassRateConcentrationUnits).Left
+
+ lblMassFlowRateLabel.Top = lblMassRateConcentration.Top
+ lblMassFlowRateLabel.Left = 5760
+ lblMassFlowRate.Top = lblMassFlowRateLabel.Top
+ lblMassFlowRate.Left = 8040
+ cboCapValue(cccMassFlowRateUnits).Top = lblMassFlowRateLabel.Top - LabelAdjust
+ cboCapValue(cccMassFlowRateUnits).Left = 9200
+
+ lblMolesInjectedLabel.Top = lblMassRateInjectionTime.Top
+ lblMolesInjectedLabel.Left = lblMassFlowRateLabel.Left
+ lblMolesInjected.Top = lblMolesInjectedLabel.Top
+ lblMolesInjected.Left = lblMassFlowRate.Left
+ cboCapValue(cccMassRateMolesInjectedUnits).Top = lblMolesInjectedLabel.Top - LabelAdjust
+ cboCapValue(cccMassRateMolesInjectedUnits).Left = cboCapValue(cccMassFlowRateUnits).Left
+
+ fraBroadening.Top = fraMassRate.Top
+ fraBroadening.Left = fraMassRate.Left
+
+ lblBdLinearVelocity.Top = lblMassRateConcentration.Top
+ lblBdLinearVelocity.Left = lblMassRateConcentration.Left
+ txtCapValue(cctBdLinearVelocity).Top = lblBdLinearVelocity.Top + 80
+ txtCapValue(cctBdLinearVelocity).Left = txtCapValue(cctMassRateConcentration).Left
+ cboCapValue(cccBdLinearVelocityUnits).Top = txtCapValue(cctBdLinearVelocity).Top
+ cboCapValue(cccBdLinearVelocityUnits).Left = cboCapValue(cccMassRateConcentrationUnits).Left
+ chkBdLinkLinearVelocity.Top = lblBdLinearVelocity.Top + 240
+ chkBdLinkLinearVelocity.Left = lblBdLinearVelocity.Left + 240
+
+ lblDiffusionCoefficient.Top = lblBdLinearVelocity.Top + 600
+ lblDiffusionCoefficient.Left = lblBdLinearVelocity.Left
+ txtCapValue(cctBdDiffusionCoefficient).Top = lblDiffusionCoefficient.Top - LabelAdjust
+ txtCapValue(cctBdDiffusionCoefficient).Left = txtCapValue(cctBdLinearVelocity).Left
+ rtfDiffusionCoefficient.Top = lblDiffusionCoefficient.Top - LabelAdjust
+ rtfDiffusionCoefficient.Left = cboCapValue(cccBdLinearVelocityUnits).Left
+
+ lblBdOpenTubeLength.Top = lblDiffusionCoefficient.Top + RowSpacing
+ lblBdOpenTubeLength.Left = lblBdLinearVelocity.Left
+ txtCapValue(cctBdOpenTubeLength).Top = lblBdOpenTubeLength.Top - LabelAdjust
+ txtCapValue(cctBdOpenTubeLength).Left = txtCapValue(cctBdLinearVelocity).Left
+ cboCapValue(cccBdOpenTubeLengthUnits).Top = lblBdOpenTubeLength.Top - LabelAdjust
+ cboCapValue(cccBdOpenTubeLengthUnits).Left = cboCapValue(cccBdLinearVelocityUnits).Left
+
+ lblBdOpenTubeID.Top = lblBdOpenTubeLength.Top + RowSpacing
+ lblBdOpenTubeID.Left = lblBdLinearVelocity.Left
+ txtCapValue(cctBdOpenTubeID).Top = lblBdOpenTubeID.Top - LabelAdjust
+ txtCapValue(cctBdOpenTubeID).Left = txtCapValue(cctBdLinearVelocity).Left
+ cboCapValue(cccBdOpenTubeIDUnits).Top = lblBdOpenTubeID.Top - LabelAdjust
+ cboCapValue(cccBdOpenTubeIDUnits).Left = cboCapValue(cccBdLinearVelocityUnits).Left
+
+ lblBdInitialPeakWidth.Top = lblBdOpenTubeLength.Top + RowSpacing * 2
+ lblBdInitialPeakWidth.Left = lblBdLinearVelocity.Left
+ txtCapValue(cctBdInitialPeakWidth).Top = lblBdInitialPeakWidth.Top - LabelAdjust
+ txtCapValue(cctBdInitialPeakWidth).Left = txtCapValue(cctBdLinearVelocity).Left
+ cboCapValue(cccBdInitialPeakWidthUnits).Top = lblBdInitialPeakWidth.Top - LabelAdjust
+ cboCapValue(cccBdInitialPeakWidthUnits).Left = cboCapValue(cccBdLinearVelocityUnits).Left
+
+ lblOptimumLinearVelocityLabel.Top = lblBdLinearVelocity.Top
+ lblOptimumLinearVelocityLabel.Left = lblMassFlowRateLabel.Left
+ lblOptimumLinearVelocity.Top = lblOptimumLinearVelocityLabel.Top
+ lblOptimumLinearVelocity.Left = 8160
+ lblOptimumLinearVelocityUnit.Top = lblOptimumLinearVelocityLabel.Top
+ lblOptimumLinearVelocityUnit.Left = 9360
+ lblOptimumLinearVelocityBasis.Top = chkBdLinkLinearVelocity.Top
+ lblOptimumLinearVelocityBasis.Left = lblOptimumLinearVelocityLabel.Left + 100
+
+ lblBdTemporalVarianceLabel.Top = lblDiffusionCoefficient.Top
+ lblBdTemporalVarianceLabel.Left = lblOptimumLinearVelocityLabel.Left
+ lblBdTemporalVariance.Top = lblBdTemporalVarianceLabel.Top
+ lblBdTemporalVariance.Left = lblOptimumLinearVelocity.Left
+ rtfBdTemporalVarianceUnit.Top = lblBdTemporalVarianceLabel.Top - LabelAdjust
+ rtfBdTemporalVarianceUnit.Left = lblOptimumLinearVelocityUnit.Left
+
+ lblBdAdditionalVarianceLabel.Top = lblBdTemporalVarianceLabel.Top + RowSpacing
+ lblBdAdditionalVarianceLabel.Left = lblBdTemporalVarianceLabel.Left
+ txtCapValue(cctBdAdditionalVariance).Top = lblBdAdditionalVarianceLabel.Top - LabelAdjust
+ txtCapValue(cctBdAdditionalVariance).Left = lblBdTemporalVariance.Left
+ rtfBdAdditionalVarianceUnit.Top = txtCapValue(cctBdAdditionalVariance).Top
+ rtfBdAdditionalVarianceUnit.Left = rtfBdTemporalVarianceUnit.Left
+
+ lblBdResultantPeakWidthLabel.Top = lblBdOpenTubeID.Top
+ lblBdResultantPeakWidthLabel.Left = lblBdTemporalVarianceLabel.Left
+ lblBdResultantPeakWidth.Top = lblBdResultantPeakWidthLabel.Top
+ lblBdResultantPeakWidth.Left = lblBdTemporalVariance.Left
+ cboCapValue(cccBdResultantPeakWidthUnits).Top = lblBdResultantPeakWidthLabel.Top - LabelAdjust
+ cboCapValue(cccBdResultantPeakWidthUnits).Left = rtfBdTemporalVarianceUnit.Left - 120
+
+ lblBdPercentVarianceIncreaseLabel.Top = lblBdInitialPeakWidth.Top
+ lblBdPercentVarianceIncreaseLabel.Left = lblBdTemporalVarianceLabel.Left
+ lblBdPercentVarianceIncrease.Top = lblBdPercentVarianceIncreaseLabel.Top
+ lblBdPercentVarianceIncrease.Left = lblBdTemporalVariance.Left
+
+ fraWeightSource.Top = fraMassRate.Top + fraMassRate.Height + 100
+ fraWeightSource.Left = 600
+ PositionWeightSourceframeControls Me
+
+End Sub
+
+' Purpose: Resize form
+Private Sub ResizeCapillaryCalcsForm(boolResizeToDefaultHeight As Boolean)
+ Dim lngHeightToSet As Long
+
+ If fraBroadening.Visible = True Then
+ lngHeightToSet = CAPILLARY_CALCS_FORM_INITIAL_HEIGHT + 1150
+ Else
+ If cboCapValue(cccMassRateConcentrationUnits).ListIndex >= cConcentrationUnitsFirstWeightIndex Then
+ ' Weight-based mass rate units
+ lngHeightToSet = CAPILLARY_CALCS_FORM_INITIAL_HEIGHT + 1400
+ Else
+ ' Mole-based mass rate units
+ lngHeightToSet = CAPILLARY_CALCS_FORM_INITIAL_HEIGHT
+ End If
+ End If
+
+ If Me.WindowState = vbNormal Then
+ If Me.Width > CAPILLARY_CALCS_FORM_INITIAL_WIDTH Then
+ Me.Width = CAPILLARY_CALCS_FORM_INITIAL_WIDTH
+ End If
+
+ If boolResizeToDefaultHeight Then
+ Me.Height = lngHeightToSet
+ Else
+ If Me.Height > lngHeightToSet Then
+ Me.Height = lngHeightToSet
+ End If
+ End If
+ End If
+
+End Sub
+
+' Purpose: Saved changed combo values to OpenCapValues or PackedCapValues
+Private Sub SaveChangedComboValue(cboThisComboBox As ComboBox, Index As Integer)
+
+ If Not mDefaultCapValuesLoaded Then Exit Sub
+
+ If cboThisComboBox.Name = cboComputationType.Name Then
+ gCapFlowComputationTypeSave = cboThisComboBox.ListIndex
+ Else
+ If cboCapillaryType.ListIndex = ctOpenTubularCapillary Then
+ ' Open Capillary
+ OpenCapVals.ComboValues(Index) = cboThisComboBox.ListIndex
+ Else
+ ' Packed Capillary
+ PackedCapVals.ComboValues(Index) = cboThisComboBox.ListIndex
+ End If
+ End If
+
+End Sub
+
+' Purpose: Save the value in OpenCapVals or PackedCapVals to allow for easy switching between open and packed capillaries
+Private Sub SaveChangedTextValue(Index As Integer)
+
+ If mUpdatingCapValues Or Not mDefaultCapValuesLoaded Then Exit Sub
+
+ On Error Resume Next
+
+ If cboCapillaryType.ListIndex = ctOpenTubularCapillary Then
+ ' Open Capillary
+ OpenCapVals.TextValues(Index) = CDblSafe(txtCapValue(Index).Text)
+ Else
+ ' Packed Capillary
+ PackedCapVals.TextValues(Index) = CDblSafe(txtCapValue(Index).Text)
+ End If
+
+End Sub
+
+Private Sub ShowHideBroadeningFrame()
+ With cmdShowPeakBroadening
+ If fraBroadening.Visible = False Then
+ fraBroadening.Visible = True
+ gCapFlowShowPeakBroadeningSave = 1
+ Else
+ fraBroadening.Visible = False
+ gCapFlowShowPeakBroadeningSave = 0
+ End If
+ End With
+
+ ShowHideWeightSource
+ ResizeCapillaryCalcsForm True
+
+End Sub
+
+' Purpose: Displays fraWeightSource if the concentration units involve mass (e.g. g
+Private Sub ShowHideWeightSource()
+ If cboCapValue(cccMassRateConcentrationUnits).ListIndex >= cConcentrationUnitsFirstWeightIndex And _
+ fraBroadening.Visible = False Then
+ fraWeightSource.Visible = True
+ Else
+ fraWeightSource.Visible = False
+ End If
+ ResizeCapillaryCalcsForm True
+
+End Sub
+
+Private Sub SynchronizeValueWithDll(eTextBoxID As cctCapCalcTextBoxIDConstants)
+ Dim dblNewValue As Double
+
+ If CheckDoNotModify(eTextBoxID) Then Exit Sub
+
+ ' Update value in objCapillaryFlow
+ dblNewValue = CDblSafe(txtCapValue(eTextBoxID))
+
+ Select Case eTextBoxID
+ Case cctPressure: objCapillaryFlow.SetBackPressure dblNewValue, cboCapValue(cccPressureUnits).ListIndex
+ Case cctColumnLength: objCapillaryFlow.SetColumnLength dblNewValue, cboCapValue(cccColumnLengthUnits).ListIndex
+ Case cctColumnID: objCapillaryFlow.SetColumnID dblNewValue, cboCapValue(cccColumnIDUnits).ListIndex
+ Case cctViscosity: objCapillaryFlow.SetSolventViscosity dblNewValue, cboCapValue(cccViscosityUnits).ListIndex
+ Case cctParticleDiamter: objCapillaryFlow.SetParticleDiameter dblNewValue, cboCapValue(cccParticleDiameterUnits).ListIndex
+ Case cctFlowRate: objCapillaryFlow.SetVolFlowRate dblNewValue, cboCapValue(cccFlowRateUnits).ListIndex
+ Case cctDeadTime: objCapillaryFlow.SetDeadTime dblNewValue, cboCapValue(cccDeadTimeUnits).ListIndex
+ Case cctPorosity: objCapillaryFlow.SetInterparticlePorosity dblNewValue
+ Case cctMassRateConcentration: objCapillaryFlow.SetMassRateConcentration dblNewValue, cboCapValue(cccMassRateConcentrationUnits).ListIndex
+ Case cctMassRateVolFlowRate: objCapillaryFlow.SetMassRateVolFlowRate dblNewValue, cboCapValue(cccMassRateVolFlowRateUnits).ListIndex
+ Case cctMassRateInjectionTime: objCapillaryFlow.SetMassRateInjectionTime dblNewValue, cboCapValue(cccMassRateInjectionTimeUnits).ListIndex
+ Case cctBdLinearVelocity: objCapillaryFlow.SetExtraColumnBroadeningLinearVelocity dblNewValue, cboCapValue(cccBdLinearVelocityUnits).ListIndex
+ Case cctBdDiffusionCoefficient: objCapillaryFlow.SetExtraColumnBroadeningDiffusionCoefficient dblNewValue, udcCmSquaredPerSec
+ Case cctBdOpenTubeLength: objCapillaryFlow.SetExtraColumnBroadeningOpenTubeLength dblNewValue, cboCapValue(cccBdOpenTubeLengthUnits).ListIndex
+ Case cctBdOpenTubeID: objCapillaryFlow.SetExtraColumnBroadeningOpenTubeID dblNewValue, cboCapValue(cccBdOpenTubeIDUnits).ListIndex
+ Case cctBdInitialPeakWidth: objCapillaryFlow.SetExtraColumnBroadeningInitialPeakWidthAtBase dblNewValue, cboCapValue(cccBdInitialPeakWidthUnits).ListIndex
+ Case cctBdAdditionalVariance: objCapillaryFlow.SetExtraColumnBroadeningAdditionalVariance dblNewValue
+ Case Else
+ ' This shouldn't happen
+ Debug.Assert False
+ End Select
+
+End Sub
+
+' Switch capillary types
+Public Sub UpdateCapillaryType()
+
+ Dim blnShowControls As Boolean
+
+ On Error GoTo CCErrorHandler
+
+ Select Case cboCapillaryType.ListIndex
+ Case ctOpenTubularCapillary
+ ' Set Packed Capillary Fields to be invisible
+ blnShowControls = False
+ objCapillaryFlow.SetCapillaryType ctOpenTubularCapillary
+ Case Else
+ ' Set Packed Capillary Fields to be visible
+ blnShowControls = True
+ objCapillaryFlow.SetCapillaryType ctPackedCapillary
+ End Select
+
+ lblParticleDiameter.Visible = blnShowControls
+ txtCapValue(cctParticleDiamter).Visible = blnShowControls
+ cboCapValue(cccParticleDiameterUnits).Visible = blnShowControls
+
+ lblPorosity.Visible = blnShowControls
+ txtCapValue(cctPorosity).Visible = blnShowControls
+
+ LoadCapFormValues
+ CopyFlowRate
+ FindDesiredValue
+
+CCStart:
+ 'This code skips the error handler
+ Exit Sub
+
+CCErrorHandler:
+ GeneralErrorHandler "CapillaryCalcs|cboCapillarType_Click", Err.Number, Err.Description
+ Resume CCStart
+
+End Sub
+
+Private Sub cboCapillaryType_Click()
+ UpdateCapillaryType
+End Sub
+
+Private Sub cboCapValue_Click(Index As Integer)
+ Dim eCurrentUnits As ulnUnitsLengthConstants
+ Dim eNewUnits As ulnUnitsLengthConstants
+ Dim dblNewColumnID As Double
+
+ Select Case Index
+ Case cccPressureUnits: SynchronizeValueWithDll cctPressure
+ Case cccColumnLengthUnits: SynchronizeValueWithDll cctColumnLength
+ Case cccColumnIDUnits: SynchronizeValueWithDll cctColumnID
+ Case cccViscosityUnits: SynchronizeValueWithDll cctViscosity
+ Case cccParticleDiameterUnits: SynchronizeValueWithDll cctParticleDiamter
+ Case cccFlowRateUnits: SynchronizeValueWithDll cctFlowRate
+ Case cccLinearVelocityUnits ' Nothing needs to be updated in the Dll
+ Case cccDeadTimeUnits: SynchronizeValueWithDll cctDeadTime
+ Case cccVolumeUnits ' Nothing needs to be updated in the Dll
+ Case cccMassRateConcentrationUnits: SynchronizeValueWithDll cctMassRateConcentration
+ Case cccMassRateVolFlowRateUnits: SynchronizeValueWithDll cctMassRateVolFlowRate
+ Case cccMassRateInjectionTimeUnits: SynchronizeValueWithDll cctMassRateInjectionTime
+ Case cccMassFlowRateUnits ' Nothing needs to be updated in the Dll
+ Case cccMassRateMolesInjectedUnits ' Nothing needs to be updated in the Dll
+ Case cccBdLinearVelocityUnits: SynchronizeValueWithDll cctBdLinearVelocity
+ Case cccBdOpenTubeLengthUnits: SynchronizeValueWithDll cctBdOpenTubeLength
+ Case cccBdOpenTubeIDUnits: SynchronizeValueWithDll cctBdOpenTubeID
+ Case cccBdInitialPeakWidthUnits: SynchronizeValueWithDll cctBdInitialPeakWidth
+ Case cccBdResultantPeakWidthUnits ' Nothing needs to be updated in the Dll
+ Case Else
+ ' This shouldn't happen
+ Debug.Assert False
+ End Select
+
+ If Index = cccColumnIDUnits And Not mUpdatingCapValues Then
+ ' Change the units from um to inches or back (if required)
+ If cboCapValue(Index).ListIndex <> eColumnIDUnitsIndexSaved And mDefaultCapValuesLoaded Then
+ eCurrentUnits = eColumnIDUnitsIndexSaved
+ eNewUnits = cboCapValue(Index).ListIndex
+
+ dblNewColumnID = objCapillaryFlow.ConvertLength(txtCapValue(cctColumnID).Text, eCurrentUnits, eNewUnits)
+ If eNewUnits = ulnInches Then
+ txtCapValue(cctColumnID).Text = Format(dblNewColumnID, "0.000000")
+ Else
+ If dblNewColumnID < 0.01 Then
+ txtCapValue(cctColumnID).Text = Format(dblNewColumnID, "0.000E+00")
+ Else
+ txtCapValue(cctColumnID).Text = Format(dblNewColumnID, "0.000")
+ End If
+ End If
+ End If
+ eColumnIDUnitsIndexSaved = cboCapValue(Index).ListIndex
+ End If
+
+ If Index <= cccVolumeUnits Then
+ If Index = cccFlowRateUnits And cChkBox(chkMassRateLinkFlowRate) Then
+ CopyFlowRate
+ FindDesiredValue
+ FindMassRate
+ FindBroadening
+ Else
+ FindDesiredValue
+ End If
+ ElseIf Index <= cccMassRateMolesInjectedUnits Then
+ FindMassRate
+ Else
+ If Index = cccBdLinearVelocityUnits Then
+ If cChkBox(chkBdLinkLinearVelocity) Then CopyLinearVelocity
+ End If
+ FindBroadening
+ End If
+
+ If Index = cccLinearVelocityUnits Then
+ FindOptimumLinearVelocity
+ End If
+
+ If Index = cccMassRateConcentrationUnits Then
+ ShowHideWeightSource
+ End If
+
+ SaveChangedComboValue cboCapValue(Index), Index
+
+End Sub
+
+Private Sub cboCapValue_KeyDown(Index As Integer, KeyCode As Integer, Shift As Integer)
+ Dim Cancel As Boolean
+ cboCapValue_Validate Index, Cancel
+
+End Sub
+
+Private Sub cboCapValue_Validate(Index As Integer, Cancel As Boolean)
+ If Index = cccMassRateVolFlowRateUnits Then
+ CopyFlowRate
+ FindMassRate
+ ElseIf Index = cccBdLinearVelocityUnits Then
+ If cChkBox(chkBdLinkLinearVelocity) Then CopyLinearVelocity
+ FindBroadening
+ End If
+End Sub
+
+Private Sub cboComputationType_Click()
+ HighlightTargetBoxes
+ CopyFlowRate
+ FindDesiredValue
+ SaveChangedComboValue cboComputationType, 0
+End Sub
+
+Private Sub chkBdLinkLinearVelocity_Click()
+ If cChkBox(chkBdLinkLinearVelocity) Then CopyLinearVelocity
+ FindBroadening
+ gCapFlowLinkBdLinearVelocitySave = chkBdLinkLinearVelocity.value
+
+End Sub
+
+Private Sub chkMassRateLinkFlowRate_Click()
+ CopyFlowRate
+ FindMassRate
+ gCapFlowLinkMassRateFlowRateSave = chkMassRateLinkFlowRate.value
+End Sub
+
+Private Sub cmdComputeViscosity_Click()
+ frmViscosityForMeCN.Show
+End Sub
+
+Private Sub cmdOK_Click()
+ HideFormShowMain Me
+End Sub
+
+Private Sub cmdShowPeakBroadening_Click()
+ ShowHideBroadeningFrame
+End Sub
+
+Private Sub cmdViewBroadeningEquations_Click()
+ frmEquationsBroadening.Show vbModal
+End Sub
+
+Private Sub cmdViewEquations_Click()
+ If cboCapillaryType.ListIndex = ctPackedCapillary Then
+ ' Packed Capillary
+ frmEquationsPackedCapillary.Show vbModal
+ Else
+ ' Open Capillary
+ frmEquationsOpenTube.Show vbModal
+ End If
+
+End Sub
+
+Private Sub Form_Activate()
+ SizeAndCenterWindow Me, cWindowTopCenter, CAPILLARY_CALCS_FORM_INITIAL_WIDTH, CAPILLARY_CALCS_FORM_INITIAL_HEIGHT
+
+ DisplayCurrentFormulaOnSubForm Me
+
+ UpdateCapillaryType
+ CopyFlowRate
+ FindDesiredValue
+ FindMassRate
+ FindBroadening
+
+ PossiblyHideMainWindow
+
+ FillRTFBoxes
+End Sub
+
+Private Sub Form_Load()
+
+ ' Turn off auto-compute
+ objCapillaryFlow.SetAutoComputeEnabled False
+
+ PositionFormControls
+
+ PopulateComboBoxes
+
+ ' Make sure appropriate Weight Source box is shown
+ ' Note: also calls ResizeCapillaryCalcsForm
+ ShowHideWeightSource
+
+ ' Also make sure correct mass input controls are shown
+ ShowHideMassInputControlsGlobal Me
+
+ mDefaultCapValuesLoaded = True
+ UpdateCapillaryType
+
+End Sub
+
+Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
+ QueryUnloadFormHandler Me, Cancel, UnloadMode
+End Sub
+
+Private Sub Form_Resize()
+ ResizeCapillaryCalcsForm False
+End Sub
+
+Private Sub Form_Unload(Cancel As Integer)
+ Set objCapillaryFlow = Nothing
+End Sub
+
+Private Sub lblLinearVelocity_Change()
+ If cChkBox(chkBdLinkLinearVelocity) Then
+ CopyLinearVelocity
+ FindBroadening
+ End If
+End Sub
+
+Private Sub lblMWT_Change()
+ FindDesiredValue
+End Sub
+
+Private Sub mnuCapillaryFlowHelp_Click()
+ ShowHelpPage hwnd, 3070
+End Sub
+
+Private Sub mnuClose_Click()
+ HideFormShowMain Me
+End Sub
+
+Private Sub mnuLoadCapValues_Click()
+ LoadCapillaryFlowInfo
+
+ ' Update controls to correct values
+ LoadCapFormValues
+ FindDesiredValue
+
+End Sub
+
+Private Sub mnuSaveCapValues_Click()
+ SaveCapillaryFlowInfo
+
+End Sub
+
+Private Sub optWeightSource_Click(Index As Integer)
+ ShowHideMassInputControlsGlobal Me
+ FindMassRate
+End Sub
+
+Private Sub txtCapValue_Change(Index As Integer)
+
+ SaveChangedTextValue Index
+ If CheckDoNotModify(CInt(Index)) Then Exit Sub
+
+ SynchronizeValueWithDll CInt(Index)
+
+ If Index <= cctPorosity Then
+ CopyFlowRate
+ FindDesiredValue
+ If cboComputationType.ListIndex = caFindVolFlowRateUsingPressure Or cboComputationType.ListIndex = caFindVolFlowUsingDeadTime Then
+ CopyFlowRate
+ End If
+ ElseIf Index <= cctMassRateInjectionTime Then
+ If Index = cctMassRateVolFlowRate And cChkBox(chkMassRateLinkFlowRate) Then
+ CopyFlowRate
+ FindDesiredValue
+ End If
+ FindMassRate
+ Else
+ If Index = cctBdLinearVelocity And cChkBox(chkBdLinkLinearVelocity) Then
+ CopyLinearVelocity
+ FindDesiredValue
+ End If
+ FindBroadening
+ End If
+
+ If Index = cctParticleDiamter Or Index = cctBdDiffusionCoefficient Then
+ FindOptimumLinearVelocity
+ End If
+
+End Sub
+
+Private Sub txtCapValue_GotFocus(Index As Integer)
+ HighlightOnFocus txtCapValue(Index)
+
+End Sub
+
+Private Sub txtCapValue_KeyPress(Index As Integer, KeyAscii As Integer)
+
+ If CheckDoNotModify(CInt(Index)) Then
+ ' Check for Ctrl+C (copy) and Ctrl+A (select all)
+ If KeyAscii <> 3 And KeyAscii <> 1 Then
+ KeyAscii = 0
+ Exit Sub
+ End If
+ End If
+
+ TextBoxKeyPressHandler txtCapValue(Index), KeyAscii, True, True, True, False, True, False, False, False, False, True
+End Sub
+
+Private Sub txtCustomMass_Change()
+ FindMassRate
+End Sub
+
+Private Sub txtCustomMass_GotFocus()
+ HighlightOnFocus txtCustomMass
+
+End Sub
+
+Private Sub txtCustomMass_KeyPress(KeyAscii As Integer)
+ TextBoxKeyPressHandler txtCustomMass, KeyAscii, True, True, True, False, True, False, False, False, False, True
+End Sub
diff --git a/frmCapillaryCalcs.frx b/frmCapillaryCalcs.frx
new file mode 100644
index 0000000..5a7b78e
Binary files /dev/null and b/frmCapillaryCalcs.frx differ
diff --git a/frmChangeValue.frm b/frmChangeValue.frm
new file mode 100644
index 0000000..287a759
--- /dev/null
+++ b/frmChangeValue.frm
@@ -0,0 +1,149 @@
+VERSION 5.00
+Object = "{3B7C8863-D78F-101B-B9B5-04021C009402}#1.2#0"; "Richtx32.ocx"
+Begin VB.Form frmChangeValue
+ BorderStyle = 3 'Fixed Dialog
+ Caption = "Change Value"
+ ClientHeight = 1980
+ ClientLeft = 45
+ ClientTop = 330
+ ClientWidth = 4545
+ ControlBox = 0 'False
+ Icon = "frmChangeValue.frx":0000
+ LinkTopic = "Form1"
+ MaxButton = 0 'False
+ MinButton = 0 'False
+ ScaleHeight = 1980
+ ScaleWidth = 4545
+ ShowInTaskbar = 0 'False
+ StartUpPosition = 3 'Windows Default
+ Tag = "8200"
+ Begin RichTextLib.RichTextBox rtfValue
+ Height = 495
+ Left = 120
+ TabIndex = 1
+ Top = 1440
+ Width = 3015
+ _ExtentX = 5318
+ _ExtentY = 873
+ _Version = 393217
+ MultiLine = 0 'False
+ TextRTF = $"frmChangeValue.frx":08CA
+ End
+ Begin VB.TextBox txtValue
+ Height = 375
+ Left = 120
+ TabIndex = 5
+ Text = "Text1"
+ Top = 1440
+ Width = 3015
+ End
+ Begin VB.CommandButton cmdReset
+ Caption = "&Reset to Default"
+ Height = 495
+ Left = 3360
+ TabIndex = 4
+ Tag = "8210"
+ Top = 1080
+ Width = 1095
+ End
+ Begin VB.CommandButton cmdCancel
+ Cancel = -1 'True
+ Caption = "&Cancel"
+ Height = 375
+ Left = 3360
+ TabIndex = 3
+ Tag = "4020"
+ Top = 600
+ Width = 1095
+ End
+ Begin VB.CommandButton cmdOK
+ Caption = "&OK"
+ Default = -1 'True
+ Height = 375
+ Left = 3360
+ TabIndex = 2
+ Tag = "4010"
+ Top = 120
+ Width = 1095
+ End
+ Begin VB.Label lblHiddenButtonClickStatus
+ Caption = "-1"
+ Height = 255
+ Left = 3480
+ TabIndex = 6
+ Top = 1680
+ Visible = 0 'False
+ Width = 855
+ End
+ Begin VB.Label lblInstructions
+ Caption = "Directions."
+ Height = 1215
+ Left = 120
+ TabIndex = 0
+ Top = 120
+ Width = 3015
+ End
+End
+Attribute VB_Name = "frmChangeValue"
+Attribute VB_GlobalNameSpace = False
+Attribute VB_Creatable = False
+Attribute VB_PredeclaredId = True
+Attribute VB_Exposed = False
+Option Explicit
+
+Private Sub cmdCancel_Click()
+ lblHiddenButtonClickStatus = BUTTON_CANCEL
+ frmChangeValue.Hide
+
+End Sub
+
+Private Sub cmdOK_Click()
+ lblHiddenButtonClickStatus = BUTTON_OK
+ frmChangeValue.Hide
+
+End Sub
+
+Private Sub cmdReset_Click()
+ lblHiddenButtonClickStatus = BUTTON_RESET
+ frmChangeValue.Hide
+
+End Sub
+
+Private Sub Form_Activate()
+ ' Put window in center of screen
+ SizeAndCenterWindow Me, cWindowExactCenter, 4600, 2400
+
+ If txtValue.Visible = True Then
+ With txtValue
+ .SetFocus
+ .SelStart = 0
+ .SelLength = Len(.Text)
+ End With
+ Else
+ With rtfValue
+ .SetFocus
+ .SelStart = 0
+ .SelLength = Len(.Text)
+ End With
+ End If
+
+End Sub
+
+Private Sub Form_Load()
+ Me.Caption = LookupLanguageCaption(8200, "Change Value")
+ CmdOK.Caption = LookupLanguageCaption(4010, "&Ok")
+ cmdCancel.Caption = LookupLanguageCaption(4020, "&Cancel")
+End Sub
+
+Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
+ QueryUnloadFormHandler Me, Cancel, UnloadMode
+End Sub
+
+Private Sub rtfValue_Change()
+ Dim saveloc As Integer
+
+ saveloc = rtfValue.SelStart
+ rtfValue.TextRTF = objMwtWin.TextToRTF(rtfValue.Text)
+ rtfValue.SelStart = saveloc
+
+End Sub
diff --git a/frmChangeValue.frx b/frmChangeValue.frx
new file mode 100644
index 0000000..9dd9466
Binary files /dev/null and b/frmChangeValue.frx differ
diff --git a/frmChooseLanguage.frm b/frmChooseLanguage.frm
new file mode 100644
index 0000000..616a166
--- /dev/null
+++ b/frmChooseLanguage.frm
@@ -0,0 +1,199 @@
+VERSION 5.00
+Begin VB.Form frmChooseLanguage
+ Caption = "Choose Language"
+ ClientHeight = 3345
+ ClientLeft = 60
+ ClientTop = 345
+ ClientWidth = 4725
+ ControlBox = 0 'False
+ HelpContextID = 4003
+ LinkTopic = "Form1"
+ LockControls = -1 'True
+ MaxButton = 0 'False
+ ScaleHeight = 3345
+ ScaleWidth = 4725
+ StartUpPosition = 3 'Windows Default
+ Tag = "8400"
+ Begin VB.ListBox lstAvailableLanguages
+ Height = 1620
+ Left = 120
+ TabIndex = 2
+ Top = 1080
+ Width = 4215
+ End
+ Begin VB.CommandButton CmdOK
+ Caption = "&OK"
+ Default = -1 'True
+ Height = 360
+ Left = 960
+ TabIndex = 3
+ Tag = "4010"
+ Top = 2880
+ Width = 1035
+ End
+ Begin VB.CommandButton cmdCancel
+ Appearance = 0 'Flat
+ Cancel = -1 'True
+ Caption = "&Cancel"
+ Height = 360
+ Left = 2280
+ TabIndex = 4
+ Tag = "4020"
+ Top = 2880
+ Width = 1035
+ End
+ Begin VB.Label lblNoLanguageFiles
+ Caption = "No language files are available. Visit the author's homepage to download alternate languages."
+ Height = 735
+ Left = 360
+ TabIndex = 1
+ Tag = "8420"
+ Top = 240
+ Width = 4215
+ End
+ Begin VB.Label lblChooseLanguage
+ Caption = "Available languages are shown below. Please choose the language you wish to use."
+ Height = 735
+ Left = 120
+ TabIndex = 0
+ Tag = "8410"
+ Top = 120
+ Width = 4215
+ End
+End
+Attribute VB_Name = "frmChooseLanguage"
+Attribute VB_GlobalNameSpace = False
+Attribute VB_Creatable = False
+Attribute VB_PredeclaredId = True
+Attribute VB_Exposed = False
+Option Explicit
+
+' Form-wide global variables
+Private intLanguageFilesFound As Integer
+Private strLanguageFileInfo(MAX_LANGUAGE_FILE_COUNT, 2) As String
+
+Private Sub PositionFormControls()
+ Me.Caption = LookupLanguageCaption(8400, "Choose Language")
+ cmdOK.Caption = LookupLanguageCaption(4010, "&Ok")
+ cmdCancel.Caption = LookupLanguageCaption(4020, "&Cancel")
+
+ lblChooseLanguage.Top = 120
+ lblChooseLanguage.Left = 120
+ lblChooseLanguage.Caption = LookupLanguageCaption(8410, "Available languages are shown below. Please choose the language you wish to use.")
+
+ lblNoLanguageFiles.Top = lblChooseLanguage.Top
+ lblNoLanguageFiles.Left = lblChooseLanguage.Left
+ lblNoLanguageFiles.Caption = LookupLanguageCaption(8420, "No language files are available. Visit the author's homepage to download alternate languages.")
+
+ lstAvailableLanguages.Top = 1080
+ lstAvailableLanguages.Left = 120
+
+End Sub
+
+Private Sub cmdCancel_Click()
+ Me.Hide
+End Sub
+
+Private Sub cmdOK_Click()
+ Dim boolSuccess As Boolean
+
+ If lblNoLanguageFiles.Visible = False Then
+ ' If chosen language is different than current language, then load new language
+ If lstAvailableLanguages.List(lstAvailableLanguages.ListIndex) <> gCurrentLanguage Then
+ ' Change mouse pointer to hourglass
+ MousePointer = vbHourglass
+
+ boolSuccess = LoadLanguageSettings(strLanguageFileInfo(lstAvailableLanguages.ListIndex, 0), strLanguageFileInfo(lstAvailableLanguages.ListIndex, 1))
+ If boolSuccess Then
+ SaveSingleDefaultOption "Language", gCurrentLanguage
+ SaveSingleDefaultOption "LanguageFile", gCurrentLanguageFileName
+ frmMain.lblStatus.ForeColor = vbWindowText
+ frmMain.lblStatus.Caption = LookupLanguageCaption(3850, "New default language saved.")
+ End If
+
+ ' Change mouse pointer back to normal
+ MousePointer = vbDefault
+
+ End If
+ End If
+ Me.Hide
+
+End Sub
+
+Private Sub Form_Activate()
+ ' ReQuery gCurrentPath for Lang*.Ini
+ ' Open each one and look for Language=
+ ' If Language= exists, display Language value in lstLanguages
+ ' Compare to gCurrentLanguage and highlight line with current language if set
+
+ ' If no language files are found, hide lblChooseLanguage and show lblNoLanguageFiles
+
+ ' User can choose language, and press OK or Cancel
+
+ Dim strLanguageFileSearchPath As String, strInputFilePath As String
+ Dim strLanguageFileMatch As String, strLineIn As String
+ Dim strLanguageName As String, intIndex As Integer
+ Dim InFileNum As Integer
+
+ ' Position Window
+ SizeAndCenterWindow Me, cWindowUpperThird, 4850, 3850
+
+ lblChooseLanguage.Visible = True
+ lblNoLanguageFiles.Visible = False
+
+ strLanguageFileSearchPath = BuildPath(gCurrentPath, "Lang*.Ini")
+
+ intLanguageFilesFound = 0
+ strLanguageFileMatch = Dir(strLanguageFileSearchPath)
+ Do While Len(strLanguageFileMatch) > 0
+ strInputFilePath = BuildPath(gCurrentPath, strLanguageFileMatch)
+
+ InFileNum = FreeFile()
+ Open strInputFilePath For Input As #InFileNum
+ Do While Not EOF(InFileNum)
+ Line Input #InFileNum, strLineIn
+ If LCase(Left(strLineIn, 9)) = "language=" Then
+ strLanguageName = Mid(strLineIn, 10)
+ If Len(strLanguageName) > 0 Then
+ intLanguageFilesFound = intLanguageFilesFound + 1
+ strLanguageFileInfo(intLanguageFilesFound - 1, 0) = strLanguageFileMatch
+ strLanguageFileInfo(intLanguageFilesFound - 1, 1) = strLanguageName
+ Exit Do
+ End If
+ End If
+ Loop
+ Close #InFileNum
+ If intLanguageFilesFound >= MAX_LANGUAGE_FILE_COUNT Then Exit Do
+ strLanguageFileMatch = Dir
+ Loop
+
+ If intLanguageFilesFound = 0 Then
+ lblChooseLanguage.Visible = False
+ lblNoLanguageFiles.Visible = True
+
+ Else
+ ' Populate List Box
+ lstAvailableLanguages.Clear
+ For intIndex = 0 To intLanguageFilesFound - 1
+ lstAvailableLanguages.AddItem strLanguageFileInfo(intIndex, 1)
+ If LCase(gCurrentLanguage) = LCase(strLanguageFileInfo(intIndex, 1)) Then
+ lstAvailableLanguages.ListIndex = intIndex
+ End If
+ Next intIndex
+ End If
+
+End Sub
+
+Private Sub Form_Load()
+
+ PositionFormControls
+
+End Sub
+
+Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
+ QueryUnloadFormHandler Me, Cancel, UnloadMode
+End Sub
+
+Private Sub lstAvailableLanguages_DblClick()
+ cmdOK_Click
+End Sub
diff --git a/frmDtaTxtFileBrowser.frm b/frmDtaTxtFileBrowser.frm
new file mode 100644
index 0000000..74fba02
--- /dev/null
+++ b/frmDtaTxtFileBrowser.frm
@@ -0,0 +1,475 @@
+VERSION 5.00
+Begin VB.Form frmDtaTxtFileBrowser
+ BorderStyle = 3 'Fixed Dialog
+ Caption = "_Dta.Txt File Browser"
+ ClientHeight = 1320
+ ClientLeft = 45
+ ClientTop = 360
+ ClientWidth = 10515
+ KeyPreview = -1 'True
+ LinkTopic = "Form1"
+ MaxButton = 0 'False
+ MinButton = 0 'False
+ ScaleHeight = 1320
+ ScaleWidth = 10515
+ ShowInTaskbar = 0 'False
+ StartUpPosition = 3 'Windows Default
+ Tag = "16000"
+ Begin VB.CommandButton cmdJumpToScan
+ Cancel = -1 'True
+ Caption = "&Jump to scan"
+ Height = 360
+ Left = 7560
+ TabIndex = 10
+ Tag = "16100"
+ ToolTipText = "Shortcut is Ctrl+J"
+ Top = 720
+ Width = 1275
+ End
+ Begin VB.CheckBox chkWindowStayOnTop
+ Caption = "&Keep Window On Top"
+ Height = 495
+ Left = 9000
+ TabIndex = 11
+ Tag = "16110"
+ Top = 120
+ Width = 1455
+ End
+ Begin VB.CommandButton cmdOK
+ Caption = "Cl&ose"
+ Height = 360
+ Left = 7560
+ TabIndex = 9
+ Tag = "4000"
+ Top = 240
+ Width = 1275
+ End
+ Begin VB.Frame fraDTATextOptions
+ Height = 1095
+ Left = 120
+ TabIndex = 0
+ Top = 120
+ Width = 7215
+ Begin VB.TextBox txtParentIonCharge
+ Height = 285
+ Left = 5400
+ Locked = -1 'True
+ TabIndex = 8
+ Top = 660
+ Width = 1455
+ End
+ Begin VB.TextBox txtParentIonMass
+ Height = 285
+ Left = 5400
+ Locked = -1 'True
+ TabIndex = 4
+ Top = 240
+ Width = 1455
+ End
+ Begin VB.ComboBox cboDTAScanNumber
+ Height = 315
+ Left = 1920
+ Style = 2 'Dropdown List
+ TabIndex = 2
+ Top = 240
+ Width = 1455
+ End
+ Begin VB.Label lblParentIonCharge
+ Caption = "Parent Ion Charge"
+ Height = 255
+ Left = 3600
+ TabIndex = 7
+ Tag = "16080"
+ Top = 660
+ Width = 1575
+ End
+ Begin VB.Label lblParentIonMH
+ Caption = "Parent Ion MH+"
+ Height = 255
+ Left = 3600
+ TabIndex = 3
+ Tag = "16070"
+ Top = 240
+ Width = 1575
+ End
+ Begin VB.Label lblScanNumberEndLabel
+ Caption = "Scan Number End"
+ Height = 255
+ Left = 120
+ TabIndex = 5
+ Tag = "16060"
+ Top = 660
+ Width = 1575
+ End
+ Begin VB.Label lblScanNumberEnd
+ Caption = "End Scan Number"
+ Height = 255
+ Left = 1920
+ TabIndex = 6
+ Top = 660
+ Width = 1455
+ End
+ Begin VB.Label lblDTAScanNumber
+ Caption = "Scan Number Start"
+ Height = 255
+ Left = 120
+ TabIndex = 1
+ Tag = "16050"
+ Top = 240
+ Width = 1575
+ End
+ End
+End
+Attribute VB_Name = "frmDtaTxtFileBrowser"
+Attribute VB_GlobalNameSpace = False
+Attribute VB_Creatable = False
+Attribute VB_PredeclaredId = True
+Attribute VB_Exposed = False
+Option Explicit
+
+Private Type udtSpectraType
+ ScanNumberStart As Long
+ ScanNumberEnd As Long
+ ParentIon As Double
+ ParentIonCharge As Integer
+ DataCount As Long
+ XVals() As Double
+ YVals() As Double
+End Type
+
+Private Type udtDtaTxtDataType
+ Initialized As Boolean
+ SpectraCount As Long
+ Spectra() As udtSpectraType
+ DtaTxtFilePath As String
+End Type
+
+Private mDtaTxtData As udtDtaTxtDataType
+
+Public Function GetDataInitializedState() As Boolean
+ GetDataInitializedState = mDtaTxtData.Initialized
+End Function
+
+Public Sub JumpToScanNumber(Optional ByRef lngScanNumber As Long = 0)
+ ' If lngScanNumber is greater than 0, then jumps directly to the given scan number
+ ' Otherwise, shows an Input box to allow the user to type a scan number
+ ' The scan number entered by the user is returned ByRef in lngScanNumber
+
+ Dim strFirstScan As String, strLastScan As String
+ Dim strScanNumber As String
+ Dim lngIndex As Long
+ Dim blnMatched As Boolean
+
+ If cboDTAScanNumber.ListCount < 1 Then
+ If lngScanNumber = 0 Then MsgBox "The scan list is empty; no scans to jump to.", vbInformation + vbOKOnly, "No Scans in Memory"
+ Exit Sub
+ End If
+
+ If lngScanNumber <= 0 Then
+ strFirstScan = cboDTAScanNumber.List(0)
+ strLastScan = cboDTAScanNumber.List(cboDTAScanNumber.ListCount - 1)
+
+ strScanNumber = InputBox("Enter the scan number to jump to (" & strFirstScan & " to " & strLastScan & "): ", "Jump to Scan", cboDTAScanNumber)
+ If IsNumeric(strScanNumber) Then
+ lngScanNumber = CLngSafe(strScanNumber)
+
+ With cboDTAScanNumber
+ If CLngSafe(.List(0)) > lngScanNumber Then
+ .ListIndex = 0
+ Else
+ For lngIndex = 0 To .ListCount - 1
+ If CLngSafe(.List(lngIndex)) >= lngScanNumber Then
+ .ListIndex = lngIndex
+ blnMatched = True
+ Exit For
+ End If
+ Next lngIndex
+
+ If Not blnMatched Then .ListIndex = .ListCount - 1
+ End If
+ End With
+
+ End If
+ End If
+End Sub
+
+Public Sub ReadDtaTxtFile(strFilePath As String)
+
+ Dim InFileNum As Integer
+ Dim lngDtaTxtSpectraDimCount As Long
+
+ Dim lngTotalByteCount As Long, lngTotalBytesRead As Long
+ Dim lngCurrentLineNumber As Long
+ Dim intParseCount As Integer, intIndex As Integer
+ Dim strParsedVals() As String
+ Dim lngDataDimCount As Long
+ Dim lngIndex As Long
+
+ Dim strLineIn As String
+ Dim blnSkipNextRead As Boolean
+ Dim lngScanNumberStart As Long
+ Dim lngScanNumberEnd As Long
+ Dim intChargeFromHeader As Integer
+ Dim dblParentIonMass As Double
+ Dim intChargeFromParentIon As Integer
+ Dim blnSkipThisScan As Boolean
+
+ Const SCAN_DELIMETER = "="
+
+On Error GoTo ReadDtaTxtFileErrorHandler
+
+ ' Initialize mDtaTxtData
+ With mDtaTxtData
+ .Initialized = True
+ .SpectraCount = 0
+ .DtaTxtFilePath = strFilePath
+ lngDtaTxtSpectraDimCount = 1000
+ ReDim .Spectra(lngDtaTxtSpectraDimCount)
+ End With
+
+ ' Make sure the file exists
+ If Not FileExists(strFilePath) Then
+ mDtaTxtData.Initialized = False
+ Exit Sub
+ End If
+
+ InFileNum = FreeFile()
+ Open strFilePath For Input As #InFileNum
+ lngTotalByteCount = FileLen(strFilePath)
+
+ frmProgress.InitializeForm "Reading _Dta.Txt file", 0, lngTotalByteCount, True, False, True
+
+ lngTotalBytesRead = 0
+ lngCurrentLineNumber = 0
+ Do While Not EOF(InFileNum)
+ If blnSkipNextRead Then
+ blnSkipNextRead = False
+ Else
+ Line Input #InFileNum, strLineIn
+ strLineIn = Trim(strLineIn)
+ End If
+
+ lngCurrentLineNumber = lngCurrentLineNumber + 1
+ lngTotalBytesRead = lngTotalBytesRead + Len(strLineIn) + 2 ' Add 2 bytes to account for CrLf at end of line
+
+ If lngCurrentLineNumber Mod 1000 = 0 Then
+ ' Only update the progress bar every 250 lines
+ frmProgress.UpdateProgressBar lngTotalBytesRead
+ If KeyPressAbortProcess > 1 Then Exit Do
+ End If
+
+ If Left(strLineIn, 1) = SCAN_DELIMETER Then
+ ' Header line found
+ ' Determine scan range and assigned charge
+ lngScanNumberStart = 0
+ lngScanNumberEnd = 0
+ intChargeFromHeader = 0
+ dblParentIonMass = 0
+ intChargeFromParentIon = 0
+
+ intParseCount = ParseString(strLineIn, strParsedVals(), 15, "." & Chr(34) & " ", "", False, False, False)
+
+ ' Find the enry in strParsedVals() that contains dta
+ For intIndex = intParseCount - 1 To 0 Step -1
+ If LCase(strParsedVals(intIndex)) = "dta" Then
+ If intIndex >= 3 Then
+ Debug.Assert intIndex = 6
+
+ lngScanNumberStart = CLngSafe(strParsedVals(intIndex - 3))
+ lngScanNumberEnd = CLngSafe(strParsedVals(intIndex - 2))
+ intChargeFromHeader = CLngSafe(strParsedVals(intIndex - 1))
+ End If
+ Exit For
+ End If
+ Next intIndex
+
+ ' Read next line to get Parent ion (as M+H) and charge
+ Line Input #InFileNum, strLineIn
+ lngCurrentLineNumber = lngCurrentLineNumber + 1
+ lngTotalBytesRead = lngTotalBytesRead + Len(strLineIn) + 2 ' Add 2 bytes to account for CrLf at end of line
+
+ intParseCount = ParseString(strLineIn, strParsedVals(), 3, " ", "", True, True, False)
+
+ If intParseCount >= 2 Then
+ dblParentIonMass = CDblSafe(strParsedVals(0))
+ intChargeFromParentIon = CIntSafe(strParsedVals(1))
+ If intChargeFromParentIon <> intChargeFromHeader Then
+ intChargeFromHeader = intChargeFromParentIon
+ End If
+ End If
+
+ With mDtaTxtData
+ ' Check if this scan has the same values for lngScanNumberStart and lngScanNumberEnd as the previous one
+ blnSkipThisScan = False
+ If .SpectraCount > 0 Then
+ With .Spectra(.SpectraCount - 1)
+ If .ScanNumberStart = lngScanNumberStart And .ScanNumberEnd = lngScanNumberEnd Then
+ blnSkipThisScan = True
+ End If
+ End With
+ End If
+
+ If blnSkipThisScan Then
+ ' Skip all of the lines for this scan by continuing to read data until a line
+ ' a line is found that doesn't start with a number
+ blnSkipNextRead = False
+ Do While Not EOF(InFileNum)
+ Line Input #InFileNum, strLineIn
+ strLineIn = Trim(strLineIn)
+ If Not IsNumeric(Left(strLineIn, 1)) Then
+ blnSkipNextRead = True
+ Exit Do
+ Else
+ lngCurrentLineNumber = lngCurrentLineNumber + 1
+ lngTotalBytesRead = lngTotalBytesRead + Len(strLineIn) + 2 ' Add 2 bytes to account for CrLf at end of line
+ End If
+ Loop
+ Else
+ .SpectraCount = .SpectraCount + 1
+ If .SpectraCount >= lngDtaTxtSpectraDimCount Then
+ lngDtaTxtSpectraDimCount = lngDtaTxtSpectraDimCount + 1000
+ ReDim Preserve .Spectra(lngDtaTxtSpectraDimCount)
+ End If
+
+ With .Spectra(.SpectraCount - 1)
+ .ParentIon = dblParentIonMass
+ .ParentIonCharge = intChargeFromHeader
+ .ScanNumberStart = lngScanNumberStart
+ .ScanNumberEnd = lngScanNumberEnd
+ .DataCount = 0
+ lngDataDimCount = 0
+ ReDim .XVals(lngDataDimCount)
+ ReDim .YVals(lngDataDimCount)
+ End With
+ End If
+ End With
+ ElseIf IsNumeric(Left(strLineIn, 1)) Then
+ ' Add to the most recent scan's data
+
+ intParseCount = ParseString(strLineIn, strParsedVals(), 3, " ", "", True, True, False)
+ If intParseCount >= 2 Then
+ With mDtaTxtData
+ If .SpectraCount > 0 Then
+ With .Spectra(.SpectraCount - 1)
+ .XVals(.DataCount) = Val(strParsedVals(0))
+ .YVals(.DataCount) = Val(strParsedVals(1))
+ .DataCount = .DataCount + 1
+
+ If .DataCount >= lngDataDimCount Then
+ lngDataDimCount = lngDataDimCount + 100
+ ReDim Preserve .XVals(lngDataDimCount)
+ ReDim Preserve .YVals(lngDataDimCount)
+ End If
+ End With
+ End If
+ End With
+ End If
+ End If
+
+ Loop
+
+ Close #InFileNum
+
+ With mDtaTxtData
+ cboDTAScanNumber.Clear
+ If .SpectraCount > 0 Then
+ For lngIndex = 0 To .SpectraCount - 1
+ cboDTAScanNumber.AddItem .Spectra(lngIndex).ScanNumberStart
+ Next lngIndex
+
+ cboDTAScanNumber.ListIndex = 0
+
+ .Initialized = True
+ Me.Show
+ Else
+ .Initialized = False
+ Me.Hide
+ End If
+ End With
+
+ frmProgress.HideForm
+ Exit Sub
+
+ReadDtaTxtFileErrorHandler:
+ MsgBox "Error reading input file " & strFilePath & vbCrLf & Err.Description & vbCrLf & "Aborting.", vbExclamation + vbOKOnly, "Error"
+ frmProgress.HideForm
+
+End Sub
+
+Private Sub ShowDtaTextSpectrum()
+ Dim lngSelectedIndex As Long
+
+ If cboDTAScanNumber.ListIndex < 0 Then Exit Sub
+
+ lngSelectedIndex = cboDTAScanNumber.ListIndex
+
+ With mDtaTxtData
+ If .Initialized Then
+ With .Spectra(lngSelectedIndex)
+ frmFragmentationModelling.SetIonMatchList .XVals(), .YVals(), .DataCount, mDtaTxtData.DtaTxtFilePath, .ScanNumberStart, .ScanNumberEnd, .ParentIon, .ParentIonCharge
+
+ txtParentIonMass = .ParentIon
+ txtParentIonCharge = .ParentIonCharge
+ lblScanNumberEnd = .ScanNumberEnd
+ End With
+ End If
+ End With
+
+ On Error Resume Next
+
+ cboDTAScanNumber.SetFocus
+
+End Sub
+
+Public Sub ToggleAlwaysOnTop(blnStayOnTop As Boolean)
+
+ Static blnUpdating As Boolean
+
+ If blnUpdating Then Exit Sub
+
+ Me.ScaleMode = vbTwips
+
+ WindowStayOnTop Me.hwnd, blnStayOnTop, Me.ScaleX(Me.Left, vbTwips, vbPixels), Me.ScaleY(Me.Top, vbTwips, vbPixels), Me.ScaleX(Me.Width, vbTwips, vbPixels), Me.ScaleY(Me.Height, vbTwips, vbPixels)
+
+ blnUpdating = True
+ SetCheckBox chkWindowStayOnTop, blnStayOnTop
+ blnUpdating = False
+
+End Sub
+
+Private Sub cboDTAScanNumber_Click()
+ ShowDtaTextSpectrum
+End Sub
+
+Private Sub chkWindowStayOnTop_Click()
+ ToggleAlwaysOnTop cChkBox(chkWindowStayOnTop)
+End Sub
+
+Private Sub cmdJumpToScan_Click()
+ JumpToScanNumber
+End Sub
+
+Private Sub cmdOK_Click()
+ Me.Hide
+End Sub
+
+Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
+ If Shift Or vbCtrlMask Then
+ If KeyCode = vbKeyJ Then
+ JumpToScanNumber
+ End If
+ End If
+End Sub
+
+Private Sub Form_Load()
+ ToggleAlwaysOnTop False
+
+ SizeAndCenterWindow Me, cWindowBottomCenter, 10600, 1725
+
+ lblScanNumberEnd.Left = cboDTAScanNumber.Left + 60
+End Sub
+
+Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
+ QueryUnloadFormHandler Me, Cancel, UnloadMode
+End Sub
+
diff --git a/frmEditAbbrevDetails.frm b/frmEditAbbrevDetails.frm
new file mode 100644
index 0000000..516fa4d
--- /dev/null
+++ b/frmEditAbbrevDetails.frm
@@ -0,0 +1,240 @@
+VERSION 5.00
+Object = "{3B7C8863-D78F-101B-B9B5-04021C009402}#1.2#0"; "richtx32.ocx"
+Begin VB.Form frmEditAbbrevDetails
+ BorderStyle = 3 'Fixed Dialog
+ Caption = "Editing Abbreviations"
+ ClientHeight = 3870
+ ClientLeft = 45
+ ClientTop = 345
+ ClientWidth = 6255
+ ControlBox = 0 'False
+ LinkTopic = "Form1"
+ MaxButton = 0 'False
+ MinButton = 0 'False
+ ScaleHeight = 3870
+ ScaleWidth = 6255
+ ShowInTaskbar = 0 'False
+ StartUpPosition = 3 'Windows Default
+ Tag = "9000"
+ Begin VB.TextBox txtComment
+ Height = 405
+ Left = 1560
+ TabIndex = 10
+ Top = 3240
+ Width = 4455
+ End
+ Begin VB.TextBox txtOneLetterSymbol
+ Height = 405
+ Left = 1560
+ TabIndex = 8
+ Top = 2760
+ Width = 1815
+ End
+ Begin VB.TextBox txtCharge
+ Height = 405
+ Left = 1560
+ TabIndex = 6
+ Top = 2280
+ Width = 735
+ End
+ Begin VB.TextBox txtSymbol
+ Height = 405
+ Left = 1560
+ TabIndex = 2
+ Top = 1200
+ Width = 1815
+ End
+ Begin VB.CommandButton cmdOK
+ Caption = "&OK"
+ Default = -1 'True
+ Height = 375
+ Left = 4800
+ TabIndex = 11
+ Tag = "4010"
+ Top = 120
+ Width = 1095
+ End
+ Begin VB.CommandButton cmdCancel
+ Cancel = -1 'True
+ Caption = "&Cancel"
+ Height = 375
+ Left = 4800
+ TabIndex = 12
+ Tag = "4020"
+ Top = 600
+ Width = 1095
+ End
+ Begin VB.CommandButton cmdRemove
+ Caption = "&Remove"
+ Height = 495
+ Left = 4800
+ TabIndex = 13
+ Tag = "9020"
+ Top = 1080
+ Width = 1095
+ End
+ Begin RichTextLib.RichTextBox rtfFormula
+ Height = 495
+ Left = 1560
+ TabIndex = 4
+ Top = 1680
+ Width = 3015
+ _ExtentX = 5318
+ _ExtentY = 873
+ _Version = 393217
+ Enabled = -1 'True
+ MultiLine = 0 'False
+ TextRTF = $"frmEditAbbrevDetails.frx":0000
+ End
+ Begin VB.Label lblComment
+ Caption = "Commen&t"
+ Height = 255
+ Left = 120
+ TabIndex = 9
+ Tag = "9195"
+ Top = 3270
+ Width = 1350
+ End
+ Begin VB.Label lblOneLetterSymbol
+ Caption = "&1 Letter"
+ Height = 255
+ Left = 120
+ TabIndex = 7
+ Tag = "9190"
+ Top = 2790
+ Width = 1350
+ End
+ Begin VB.Label lblCharge
+ Caption = "Char&ge"
+ Height = 255
+ Left = 120
+ TabIndex = 5
+ Tag = "9150"
+ Top = 2280
+ Width = 1350
+ End
+ Begin VB.Label lblFormula
+ Caption = "&Formula"
+ Height = 255
+ Left = 120
+ TabIndex = 3
+ Tag = "9160"
+ Top = 1800
+ Width = 1350
+ End
+ Begin VB.Label lblSymbol
+ Caption = "&Symbol"
+ Height = 255
+ Left = 120
+ TabIndex = 1
+ Tag = "9145"
+ Top = 1230
+ Width = 1350
+ End
+ Begin VB.Label lblInstructions
+ Caption = "Directions."
+ Height = 975
+ Left = 120
+ TabIndex = 0
+ Top = 120
+ Width = 4455
+ End
+ Begin VB.Label lblHiddenButtonClickStatus
+ Caption = "-1"
+ Height = 255
+ Left = 4920
+ TabIndex = 14
+ Top = 1920
+ Visible = 0 'False
+ Width = 855
+ End
+End
+Attribute VB_Name = "frmEditAbbrevDetails"
+Attribute VB_GlobalNameSpace = False
+Attribute VB_Creatable = False
+Attribute VB_PredeclaredId = True
+Attribute VB_Exposed = False
+Option Explicit
+
+
+Private Sub cmdCancel_Click()
+ lblHiddenButtonClickStatus = BUTTON_CANCEL
+ frmEditAbbrevDetails.Hide
+
+End Sub
+
+Private Sub cmdOK_Click()
+ lblHiddenButtonClickStatus = BUTTON_OK
+ frmEditAbbrevDetails.Hide
+
+End Sub
+
+Private Sub cmdRemove_Click()
+ lblHiddenButtonClickStatus = BUTTON_RESET
+ frmEditAbbrevDetails.Hide
+
+End Sub
+
+Private Sub Form_Activate()
+ ' Put window in center of screen
+ SizeAndCenterWindow Me, cWindowExactCenter, 6350, 4250
+
+End Sub
+
+Private Sub Form_Load()
+ Me.Caption = LookupLanguageCaption(9000, "Editing Abbreviations")
+ cmdOK.Caption = LookupLanguageCaption(4010, "&Ok")
+ cmdCancel.Caption = LookupLanguageCaption(4020, "&Cancel")
+ cmdRemove.Caption = LookupLanguageCaption(9020, "&Remove")
+End Sub
+
+Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
+ QueryUnloadFormHandler Me, Cancel, UnloadMode
+End Sub
+
+Private Sub rtfFormula_Change()
+ Dim saveloc As Integer
+
+ saveloc = rtfFormula.SelStart
+ rtfFormula.TextRTF = objMwtWin.TextToRTF(rtfFormula.Text)
+ rtfFormula.SelStart = saveloc
+
+End Sub
+
+Private Sub rtfFormula_GotFocus()
+ SetMostRecentTextBoxValue rtfFormula.Text
+End Sub
+
+Private Sub rtfFormula_KeyPress(KeyAscii As Integer)
+ RTFBoxKeyPressHandler Me, rtfFormula, KeyAscii, False
+End Sub
+
+Private Sub txtCharge_Change()
+ HighlightOnFocus txtCharge
+End Sub
+
+Private Sub txtCharge_KeyPress(KeyAscii As Integer)
+ TextBoxKeyPressHandler txtCharge, KeyAscii, True, True, True, False, True
+End Sub
+
+Private Sub txtOneLetterSymbol_Change()
+ HighlightOnFocus txtOneLetterSymbol
+End Sub
+
+Private Sub txtOneLetterSymbol_KeyPress(KeyAscii As Integer)
+ TextBoxKeyPressHandler txtOneLetterSymbol, KeyAscii, False, False, False, True
+End Sub
+
+Private Sub txtOneLetterSymbol_Validate(Cancel As Boolean)
+ If Len(txtOneLetterSymbol) > 1 Then
+ txtOneLetterSymbol = Left(txtOneLetterSymbol, 1)
+ End If
+End Sub
+
+Private Sub txtSymbol_GotFocus()
+ HighlightOnFocus txtSymbol
+End Sub
+
+Private Sub txtSymbol_KeyPress(KeyAscii As Integer)
+ TextBoxKeyPressHandler txtSymbol, KeyAscii, False, False, False, True
+End Sub
diff --git a/frmEditAbbrevDetails.frx b/frmEditAbbrevDetails.frx
new file mode 100644
index 0000000..8ebef8e
Binary files /dev/null and b/frmEditAbbrevDetails.frx differ
diff --git a/frmEditModSymbolDetails.frm b/frmEditModSymbolDetails.frm
new file mode 100644
index 0000000..e60465c
--- /dev/null
+++ b/frmEditModSymbolDetails.frm
@@ -0,0 +1,178 @@
+VERSION 5.00
+Begin VB.Form frmEditModSymbolDetails
+ BorderStyle = 3 'Fixed Dialog
+ Caption = "Amino Acid Modification Symbols Editor"
+ ClientHeight = 2670
+ ClientLeft = 45
+ ClientTop = 345
+ ClientWidth = 6210
+ ControlBox = 0 'False
+ LinkTopic = "Form1"
+ MaxButton = 0 'False
+ MinButton = 0 'False
+ ScaleHeight = 2670
+ ScaleWidth = 6210
+ ShowInTaskbar = 0 'False
+ StartUpPosition = 3 'Windows Default
+ Tag = "15500"
+ Begin VB.TextBox txtComment
+ Height = 315
+ Left = 1560
+ TabIndex = 6
+ Top = 2160
+ Width = 4455
+ End
+ Begin VB.TextBox txtMass
+ Height = 315
+ Left = 1560
+ TabIndex = 4
+ Top = 1680
+ Width = 1815
+ End
+ Begin VB.TextBox txtSymbol
+ Height = 315
+ Left = 1560
+ TabIndex = 2
+ Top = 1200
+ Width = 1815
+ End
+ Begin VB.CommandButton cmdOK
+ Caption = "&OK"
+ Default = -1 'True
+ Height = 375
+ Left = 4920
+ TabIndex = 7
+ Tag = "4010"
+ Top = 120
+ Width = 1095
+ End
+ Begin VB.CommandButton cmdCancel
+ Cancel = -1 'True
+ Caption = "&Cancel"
+ Height = 375
+ Left = 4920
+ TabIndex = 8
+ Tag = "4020"
+ Top = 600
+ Width = 1095
+ End
+ Begin VB.CommandButton cmdRemove
+ Caption = "&Remove"
+ Height = 495
+ Left = 4920
+ TabIndex = 9
+ Tag = "9020"
+ Top = 1080
+ Width = 1095
+ End
+ Begin VB.Label lblComment
+ Caption = "Commen&t"
+ Height = 255
+ Left = 120
+ TabIndex = 5
+ Tag = "15140"
+ Top = 2190
+ Width = 1350
+ End
+ Begin VB.Label lblMass
+ Caption = "&Mass"
+ Height = 255
+ Left = 120
+ TabIndex = 3
+ Tag = "15120"
+ Top = 1680
+ Width = 1350
+ End
+ Begin VB.Label lblSymbol
+ Caption = "&Symbol"
+ Height = 255
+ Left = 120
+ TabIndex = 1
+ Tag = "15110"
+ Top = 1230
+ Width = 1350
+ End
+ Begin VB.Label lblInstructions
+ Caption = "Directions."
+ Height = 975
+ Left = 120
+ TabIndex = 0
+ Tag = "15250"
+ Top = 120
+ Width = 4575
+ End
+ Begin VB.Label lblHiddenButtonClickStatus
+ Caption = "-1"
+ Height = 255
+ Left = 5040
+ TabIndex = 10
+ Top = 1800
+ Visible = 0 'False
+ Width = 855
+ End
+End
+Attribute VB_Name = "frmEditModSymbolDetails"
+Attribute VB_GlobalNameSpace = False
+Attribute VB_Creatable = False
+Attribute VB_PredeclaredId = True
+Attribute VB_Exposed = False
+Option Explicit
+
+Private Sub cmdCancel_Click()
+ lblHiddenButtonClickStatus = BUTTON_CANCEL
+ frmEditModSymbolDetails.Hide
+
+End Sub
+
+Private Sub cmdOK_Click()
+ lblHiddenButtonClickStatus = BUTTON_OK
+ frmEditModSymbolDetails.Hide
+End Sub
+
+Private Sub cmdRemove_Click()
+ lblHiddenButtonClickStatus = BUTTON_RESET
+ frmEditModSymbolDetails.Hide
+End Sub
+
+Private Sub Form_Activate()
+ ' Put window in center of screen
+ SizeAndCenterWindow Me, cWindowExactCenter, 6300, 3050
+End Sub
+
+Private Sub Form_Load()
+ Me.Caption = LookupLanguageCaption(9000, "Amino Acid Modification Symbols Editor")
+
+ CmdOK.Caption = LookupLanguageCaption(4010, "&Ok")
+ cmdCancel.Caption = LookupLanguageCaption(4020, "&Cancel")
+ cmdRemove.Caption = LookupLanguageCaption(9020, "&Remove")
+
+ lblInstructions.Caption = LookupLanguageCaption(15750, "The amino acid symbol modification will be updated with the parameters below. Select Remove to delete the modification symbol or Cancel to ignore any changes.")
+End Sub
+
+Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
+ QueryUnloadFormHandler Me, Cancel, UnloadMode
+End Sub
+
+Private Sub txtComment_KeyPress(KeyAscii As Integer)
+ ' Note: I'm purposely not using TextBoxKeyPressHandler for the Comment since I want to allow the user to type anything in the comment box
+End Sub
+
+Private Sub txtMass_Change()
+ HighlightOnFocus txtMass
+End Sub
+
+Private Sub txtMass_GotFocus()
+ HighlightOnFocus txtMass
+End Sub
+
+Private Sub txtMass_KeyPress(KeyAscii As Integer)
+ TextBoxKeyPressHandler txtMass, KeyAscii, True, True, True, False, True
+End Sub
+
+Private Sub txtSymbol_GotFocus()
+ HighlightOnFocus txtSymbol
+End Sub
+
+Private Sub txtSymbol_KeyPress(KeyAscii As Integer)
+ ModSymbolKeyPressHandler txtSymbol, KeyAscii
+End Sub
diff --git a/frmFinderOptions.frm b/frmFinderOptions.frm
new file mode 100644
index 0000000..6f3ac94
--- /dev/null
+++ b/frmFinderOptions.frm
@@ -0,0 +1,425 @@
+VERSION 5.00
+Begin VB.Form frmFinderOptions
+ BorderStyle = 3 'Fixed Dialog
+ Caption = "Finder Options"
+ ClientHeight = 3075
+ ClientLeft = 45
+ ClientTop = 330
+ ClientWidth = 5955
+ HelpContextID = 3050
+ Icon = "frmFinderOptions.frx":0000
+ LinkTopic = "Form1"
+ MaxButton = 0 'False
+ MinButton = 0 'False
+ ScaleHeight = 3075
+ ScaleWidth = 5955
+ ShowInTaskbar = 0 'False
+ StartUpPosition = 3 'Windows Default
+ Tag = "10800"
+ Begin VB.ComboBox cboSearchType
+ Height = 315
+ Left = 120
+ Style = 2 'Dropdown List
+ TabIndex = 10
+ Tag = "10840"
+ ToolTipText = "Choose converting between different amounts or molarity calculation in a solvent"
+ Top = 2640
+ Width = 2295
+ End
+ Begin VB.ComboBox cboSortResults
+ Height = 315
+ Left = 120
+ Style = 2 'Dropdown List
+ TabIndex = 9
+ Tag = "10850"
+ ToolTipText = "Resorts the results the list."
+ Top = 2160
+ Width = 2295
+ End
+ Begin VB.CheckBox chkVerifyHydrogens
+ Caption = "&Smart H atoms"
+ Height = 255
+ Left = 2040
+ TabIndex = 8
+ Tag = "10950"
+ Top = 1680
+ Value = 1 'Checked
+ Width = 2415
+ End
+ Begin VB.CheckBox chkSort
+ Caption = "So&rt Results"
+ Height = 255
+ Left = 120
+ TabIndex = 7
+ Tag = "10940"
+ Top = 1680
+ Value = 1 'Checked
+ Width = 1815
+ End
+ Begin VB.CheckBox chkAutoSetBounds
+ Caption = "&Automatically adjust Min and Max in bounded search."
+ Height = 615
+ Left = 2880
+ TabIndex = 11
+ Tag = "10960"
+ Top = 2160
+ Value = 1 'Checked
+ Width = 2415
+ End
+ Begin VB.TextBox txtChargeMax
+ Height = 285
+ Left = 5280
+ TabIndex = 4
+ Tag = "10830"
+ Text = "4"
+ ToolTipText = "Maximum charge to limit compounds to"
+ Top = 960
+ Width = 375
+ End
+ Begin VB.TextBox txtChargeMin
+ Height = 285
+ Left = 4560
+ TabIndex = 3
+ Tag = "10820"
+ Text = "-4"
+ ToolTipText = "Minimum charge to limit compounds to"
+ Top = 960
+ Width = 375
+ End
+ Begin VB.CheckBox chkLimitChargeRange
+ Caption = "Limit Charge &Range"
+ Height = 255
+ Left = 2040
+ TabIndex = 2
+ Tag = "10910"
+ Top = 960
+ Width = 2415
+ End
+ Begin VB.CheckBox chkFindTargetMtoZ
+ Caption = "Find &Target m/z"
+ Height = 255
+ Left = 2040
+ TabIndex = 6
+ Tag = "10930"
+ Top = 1320
+ Width = 2415
+ End
+ Begin VB.CheckBox chkFindCharge
+ Caption = "Find &Charge"
+ Height = 255
+ Left = 120
+ TabIndex = 1
+ Tag = "10900"
+ Top = 960
+ Width = 1815
+ End
+ Begin VB.CheckBox chkFindMtoZ
+ Caption = "Find m/&z"
+ Height = 255
+ Left = 120
+ TabIndex = 5
+ Tag = "10920"
+ Top = 1320
+ Width = 1815
+ End
+ Begin VB.CommandButton cmdOK
+ Cancel = -1 'True
+ Caption = "&OK"
+ Default = -1 'True
+ Height = 480
+ Left = 4560
+ TabIndex = 0
+ Tag = "4010"
+ Top = 120
+ Width = 1095
+ End
+ Begin VB.Label lblMax
+ Caption = "Max"
+ Height = 255
+ Left = 5280
+ TabIndex = 14
+ Tag = "10070"
+ Top = 720
+ Width = 735
+ End
+ Begin VB.Label lblMin
+ Caption = "Min"
+ Height = 255
+ Left = 4560
+ TabIndex = 13
+ Tag = "10060"
+ Top = 720
+ Width = 615
+ End
+ Begin VB.Label lblInstructions
+ Caption = "Use the checkboxes to select various options for the Formula Finder."
+ Height = 615
+ Left = 120
+ TabIndex = 12
+ Tag = "10810"
+ Top = 120
+ Width = 3135
+ End
+End
+Attribute VB_Name = "frmFinderOptions"
+Attribute VB_GlobalNameSpace = False
+Attribute VB_Creatable = False
+Attribute VB_PredeclaredId = True
+Attribute VB_Exposed = False
+Option Explicit
+
+Private mSortModeMapCount As Integer
+Private mSortModeMap() As smcFinderResultsSortModeConstants
+
+Public Function LookupResultsSortModeTypeByIndex(intListIndex As Integer) As smcFinderResultsSortModeConstants
+ If intListIndex < 0 Or intListIndex > mSortModeMapCount - 1 Then
+ LookupResultsSortModeTypeByIndex = smcSortByFormula
+ Else
+ LookupResultsSortModeTypeByIndex = mSortModeMap(intListIndex)
+ End If
+End Function
+
+Private Sub PositionFormControls()
+
+ ReDim mSortModeMap(5)
+
+ PopulateComboBox cboSearchType, True, "Thorough Search|Bounded Search", 0 ' 10840
+
+ frmFinderOptions.cboSortResults.ListIndex = 0
+
+ txtChargeMin.Visible = False
+ txtChargeMax.Visible = False
+ lblMin.Visible = False
+ lblMax.Visible = False
+ chkFindTargetMtoZ.Enabled = False
+ chkVerifyHydrogens.Enabled = False
+
+End Sub
+
+Public Sub UpdateCheckBoxes()
+ Dim blnShowControl As Boolean
+ Dim intListIndexSave As Integer
+
+ If cChkBox(chkFindCharge) Then
+ blnShowControl = True
+ Else
+ blnShowControl = False
+ chkFindMtoZ.value = vbUnchecked
+ chkLimitChargeRange.value = vbUnchecked
+ End If
+
+ ' Show or hide the FindMtoZ and LimitChargeRange buttons depending on FindCharge's value
+ If frmFinder.optType(0).value = True Then
+ chkFindMtoZ.Enabled = blnShowControl
+ Else
+ chkFindMtoZ.Enabled = False
+ chkFindMtoZ.value = vbUnchecked
+ End If
+ chkLimitChargeRange.Enabled = blnShowControl
+
+ If blnShowControl = True And cChkBox(chkLimitChargeRange) Then
+ blnShowControl = True
+ Else
+ blnShowControl = False
+ End If
+
+ ' If FindCharge is checked and LimitChargeRange is checked then show the Min and Max labels and boxes
+ txtChargeMin.Visible = blnShowControl
+ txtChargeMax.Visible = blnShowControl
+ lblMin.Visible = blnShowControl
+ lblMax.Visible = blnShowControl
+
+ ' If LimitChargeRange is checked and FindMtoZ is checked then show FindTargetMtoZ
+ If blnShowControl = True And cChkBox(chkFindMtoZ) Then
+ chkFindTargetMtoZ.Enabled = True
+ Else
+ chkFindTargetMtoZ.Enabled = False
+ chkFindTargetMtoZ.value = vbUnchecked
+ End If
+
+ ' If SortResults is checked, then show sort mode
+ If cChkBox(chkSort) Then
+ cboSortResults.Enabled = True
+ Else
+ cboSortResults.Enabled = False
+ End If
+
+ ' If cboSearchMode is bounded search, then show the auto adjust min and max checkbox
+ If cboSearchType.ListIndex = 1 Then
+ chkAutoSetBounds.Enabled = True
+ Else
+ chkAutoSetBounds.Enabled = False
+ End If
+
+ ' Set the lblMWT Caption based on the FindMtoZ box
+ If cChkBox(chkFindTargetMtoZ) Then
+ frmFinder.lblMWT.Caption = LookupLanguageCaption(10870, "Mass/Charge Ratio of Target") & ":"
+ Else
+ frmFinder.lblMWT.Caption = LookupLanguageCaption(10875, "Molecular Weight of Target") & ":"
+ End If
+
+ ' Update the values in the sorttype combo box
+ With cboSortResults
+ intListIndexSave = .ListIndex
+ .Clear
+ End With
+
+ ' Clear mSortModeMap
+ mSortModeMapCount = 0
+ ReDim mSortModeMap(6)
+
+ ' Add items to sort box
+ AddSortResultsItem LookupLanguageCaption(10850, "Sort by Formula"), smcSortByFormula
+
+ If cChkBox(chkFindCharge) Then
+ AddSortResultsItem LookupLanguageCaption(10855, "Sort by Charge"), smcSortByCharge
+ End If
+
+ AddSortResultsItem LookupLanguageCaption(10860, "Sort by MWT"), smcSortByMWT
+
+ If cChkBox(chkFindMtoZ) Then
+ AddSortResultsItem LookupLanguageCaption(10865, "Sort by m/z"), smcSortByMZ
+ End If
+
+ AddSortResultsItem LookupLanguageCaption(10867, "Sort by Abs(Delta Mass)"), smcSortByDeltaMass
+
+ If intListIndexSave < cboSortResults.ListCount Then
+ cboSortResults.ListIndex = intListIndexSave
+ Else
+ cboSortResults.ListIndex = 0
+ End If
+
+End Sub
+
+Private Sub AddSortResultsItem(strItemName, eSortMode As smcFinderResultsSortModeConstants)
+ cboSortResults.AddItem strItemName
+
+ If mSortModeMapCount >= mSortModeMapCount Then
+ ReDim Preserve mSortModeMap(UBound(mSortModeMap) * 2)
+ End If
+
+ mSortModeMap(mSortModeMapCount) = eSortMode
+ mSortModeMapCount = mSortModeMapCount + 1
+
+End Sub
+
+Private Sub cboSearchType_Click()
+ Dim blnBoundedSearch As Boolean, intIndex As Integer
+
+ UpdateCheckBoxes
+
+ If cboSearchType.ListIndex = 0 Then
+ ' Thorough search, so hide the bounds boxes
+ blnBoundedSearch = False
+ Else
+ ' Bounded search, so show the bounds boxes
+ blnBoundedSearch = True
+ End If
+
+ With frmFinder
+ ' Show/hide bounds boxes as needed
+ For intIndex = 0 To 9
+ If cChkBox(.chkElements(intIndex)) Then
+ .txtMin(intIndex).Visible = blnBoundedSearch
+ .txtMax(intIndex).Visible = blnBoundedSearch
+ Else
+ .txtMin(intIndex).Visible = False
+ .txtMax(intIndex).Visible = False
+ .txtPercent(intIndex).Visible = False
+ End If
+ Next intIndex
+
+ If blnBoundedSearch Then
+ ' Show labels as needed
+ For intIndex = 0 To 9
+ If cChkBox(.chkElements(intIndex)) Then Exit For
+ Next intIndex
+ If intIndex < 10 Then
+ ' At least one checked, show labels
+ .lblMin.Visible = True
+ .lblMax.Visible = True
+ End If
+ Else
+ .lblMin.Visible = False
+ .lblMax.Visible = False
+ End If
+
+ .ResizeForm
+ End With
+End Sub
+
+Private Sub chkFindCharge_Click()
+ UpdateCheckBoxes
+End Sub
+
+Private Sub chkFindMtoZ_Click()
+ UpdateCheckBoxes
+
+End Sub
+
+Private Sub chkFindTargetMtoZ_Click()
+ UpdateCheckBoxes
+End Sub
+
+Private Sub chkLimitChargeRange_Click()
+ chkLimitChargeRange_Validate False
+
+End Sub
+
+Private Sub chkLimitChargeRange_Validate(Cancel As Boolean)
+ UpdateCheckBoxes
+End Sub
+
+Private Sub chkSort_Click()
+ UpdateCheckBoxes
+End Sub
+
+Private Sub cmdOK_Click()
+ frmFinderOptions.Hide
+End Sub
+
+Private Sub Form_Activate()
+ ' Put window in center of screen (and upper third vertically)
+ SizeAndCenterWindow Me, cWindowUpperThird, 6050, 3600
+
+ UpdateCheckBoxes
+End Sub
+
+Private Sub Form_Click()
+ UpdateCheckBoxes
+End Sub
+
+Private Sub Form_Load()
+ PositionFormControls
+End Sub
+
+Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
+ QueryUnloadFormHandler Me, Cancel, UnloadMode
+End Sub
+
+Private Sub txtChargeMax_GotFocus()
+ HighlightOnFocus txtChargeMax
+
+End Sub
+
+Private Sub txtChargeMax_KeyPress(KeyAscii As Integer)
+ TextBoxKeyPressHandler txtChargeMax, KeyAscii, True, False, True
+End Sub
+
+Private Sub txtChargeMax_Validate(Cancel As Boolean)
+ ' Make sure the value is reasonable
+ ValidateDualTextBoxes txtChargeMin, txtChargeMax, False, -20, 20, 1
+End Sub
+
+Private Sub txtChargeMin_GotFocus()
+ HighlightOnFocus txtChargeMin
+End Sub
+
+Private Sub txtChargeMin_KeyPress(KeyAscii As Integer)
+ TextBoxKeyPressHandler txtChargeMin, KeyAscii, True, False, True
+End Sub
+
+Private Sub txtChargeMin_Validate(Cancel As Boolean)
+ ' Make sure the value is reasonable
+ ValidateDualTextBoxes txtChargeMin, txtChargeMax, True, -20, 20, 1
+End Sub
diff --git a/frmFinderOptions.frx b/frmFinderOptions.frx
new file mode 100644
index 0000000..03ffc39
Binary files /dev/null and b/frmFinderOptions.frx differ
diff --git a/frmFragmentationModelling.frm b/frmFragmentationModelling.frm
new file mode 100644
index 0000000..e0dff5f
--- /dev/null
+++ b/frmFragmentationModelling.frm
@@ -0,0 +1,3871 @@
+VERSION 5.00
+Object = "{5E9E78A0-531B-11CF-91F6-C2863C385E30}#1.0#0"; "MSFLXGRD.OCX"
+Begin VB.Form frmFragmentationModelling
+ Caption = "Peptide Sequence Fragmentation Modelling"
+ ClientHeight = 9525
+ ClientLeft = 165
+ ClientTop = 840
+ ClientWidth = 10110
+ HelpContextID = 3080
+ Icon = "frmFragmentationModelling.frx":0000
+ KeyPreview = -1 'True
+ LinkTopic = "Form1"
+ ScaleHeight = 9525
+ ScaleWidth = 10110
+ StartUpPosition = 3 'Windows Default
+ Tag = "12000"
+ Begin VB.CommandButton cmdMatchIons
+ Caption = "&Match Ions"
+ Height = 345
+ Left = 7200
+ TabIndex = 2
+ Tag = "12020"
+ Top = 240
+ Width = 1515
+ End
+ Begin VB.Frame fraMassInfo
+ Caption = "Mass Information"
+ Height = 935
+ Left = 2640
+ TabIndex = 4
+ Tag = "12410"
+ Top = 720
+ Width = 7275
+ Begin VB.OptionButton optElementMode
+ Caption = "Average"
+ Height = 255
+ HelpContextID = 4053
+ Index = 0
+ Left = 5640
+ TabIndex = 53
+ Tag = "12425"
+ Top = 360
+ Value = -1 'True
+ Width = 1395
+ End
+ Begin VB.OptionButton optElementMode
+ Caption = "Isotopic"
+ Height = 255
+ HelpContextID = 4053
+ Index = 1
+ Left = 5640
+ TabIndex = 52
+ Tag = "12430"
+ Top = 600
+ Width = 1395
+ End
+ Begin VB.TextBox txtMWT
+ Appearance = 0 'Flat
+ BackColor = &H8000000F&
+ BorderStyle = 0 'None
+ Height = 255
+ Left = 120
+ Locked = -1 'True
+ TabIndex = 51
+ Text = "MW="
+ Top = 240
+ Width = 2175
+ End
+ Begin VB.TextBox txtMHAlt
+ Height = 285
+ Left = 3720
+ TabIndex = 9
+ Text = "500"
+ Top = 560
+ Width = 1335
+ End
+ Begin VB.ComboBox cboMHAlternate
+ Height = 315
+ Left = 2400
+ Style = 2 'Dropdown List
+ TabIndex = 8
+ Top = 540
+ Width = 1215
+ End
+ Begin VB.TextBox txtMH
+ Height = 285
+ Left = 3720
+ TabIndex = 6
+ Text = "500"
+ Top = 240
+ Width = 1335
+ End
+ Begin VB.Label lblElementMode
+ Caption = "Element Mode"
+ Height = 225
+ Left = 5640
+ TabIndex = 54
+ Tag = "12420"
+ Top = 120
+ Width = 1455
+ End
+ Begin VB.Label lblMHAltDa
+ Caption = "Da"
+ Height = 255
+ Left = 5160
+ TabIndex = 10
+ Tag = "12350"
+ Top = 585
+ Width = 375
+ End
+ Begin VB.Label lblMHDa
+ Caption = "Da"
+ Height = 255
+ Left = 5160
+ TabIndex = 7
+ Tag = "12350"
+ Top = 255
+ Width = 375
+ End
+ Begin VB.Label lblMH
+ Caption = "[M+H]1+"
+ Height = 255
+ Left = 2400
+ TabIndex = 5
+ Top = 260
+ Width = 855
+ End
+ End
+ Begin MSFlexGridLib.MSFlexGrid grdIonList
+ Height = 6375
+ Left = 7080
+ TabIndex = 44
+ Top = 1800
+ Width = 1935
+ _ExtentX = 3413
+ _ExtentY = 11245
+ _Version = 393216
+ Cols = 3
+ FixedCols = 0
+ End
+ Begin VB.Frame fraIonStats
+ Caption = "Ion Statistics"
+ Height = 1935
+ Left = 3960
+ TabIndex = 45
+ Tag = "12360"
+ Top = 6360
+ Width = 3015
+ Begin VB.Label lblScore
+ BorderStyle = 1 'Fixed Single
+ Height = 255
+ Left = 120
+ TabIndex = 50
+ Top = 1640
+ Width = 2655
+ End
+ Begin VB.Label lblMatchCount
+ BorderStyle = 1 'Fixed Single
+ Height = 255
+ Left = 120
+ TabIndex = 49
+ Top = 1400
+ Width = 2655
+ End
+ Begin VB.Label lblBinAndToleranceCounts
+ BorderStyle = 1 'Fixed Single
+ Height = 615
+ Left = 120
+ TabIndex = 48
+ Top = 440
+ Width = 2655
+ End
+ Begin VB.Label lblPrecursorStatus
+ BorderStyle = 1 'Fixed Single
+ Height = 375
+ Left = 120
+ TabIndex = 47
+ Top = 1040
+ Width = 2655
+ End
+ Begin VB.Label lblIonLoadedCount
+ BorderStyle = 1 'Fixed Single
+ Height = 255
+ Left = 120
+ TabIndex = 46
+ Top = 200
+ Width = 2655
+ End
+ End
+ Begin VB.Frame fraIonMatching
+ Caption = "Ion Match Options"
+ Height = 1935
+ Left = 60
+ TabIndex = 29
+ Tag = "12300"
+ Top = 6360
+ Width = 3735
+ Begin VB.TextBox txtAlignment
+ Height = 285
+ Left = 2280
+ TabIndex = 41
+ Tag = "12060"
+ Text = "0"
+ Top = 1560
+ Width = 735
+ End
+ Begin VB.CheckBox chkRemovePrecursorIon
+ Caption = "&Remove Precursor Ion"
+ Height = 255
+ Left = 120
+ TabIndex = 30
+ Tag = "12310"
+ Top = 240
+ Value = 1 'Checked
+ Width = 3375
+ End
+ Begin VB.TextBox txtPrecursorMassWindow
+ Height = 285
+ Left = 2280
+ TabIndex = 35
+ Text = "2"
+ Top = 840
+ Width = 735
+ End
+ Begin VB.TextBox txtIonMatchingWindow
+ Height = 285
+ Left = 2280
+ TabIndex = 38
+ Text = ".5"
+ Top = 1200
+ Width = 735
+ End
+ Begin VB.TextBox txtPrecursorIonMass
+ Height = 285
+ Left = 2280
+ TabIndex = 32
+ Text = "500"
+ Top = 500
+ Width = 735
+ End
+ Begin VB.Label lblAlignment
+ Caption = "Alignment &Offset"
+ Height = 255
+ Left = 120
+ TabIndex = 40
+ Tag = "12355"
+ Top = 1580
+ Width = 2175
+ End
+ Begin VB.Label lblDaltons
+ Caption = "Da"
+ Height = 255
+ Index = 3
+ Left = 3120
+ TabIndex = 42
+ Tag = "12350"
+ Top = 1580
+ Width = 495
+ End
+ Begin VB.Label lblDaltons
+ Caption = "Da"
+ Height = 255
+ Index = 2
+ Left = 3120
+ TabIndex = 39
+ Tag = "12350"
+ Top = 1220
+ Width = 495
+ End
+ Begin VB.Label lblDaltons
+ Caption = "Da"
+ Height = 255
+ Index = 1
+ Left = 3120
+ TabIndex = 36
+ Tag = "12350"
+ Top = 860
+ Width = 495
+ End
+ Begin VB.Label lblPrecursorMassWindow
+ Caption = "Mass Window"
+ Height = 255
+ Left = 480
+ TabIndex = 34
+ Tag = "12330"
+ Top = 860
+ Width = 1815
+ End
+ Begin VB.Label lblDaltons
+ Caption = "Da"
+ Height = 255
+ Index = 0
+ Left = 3120
+ TabIndex = 33
+ Tag = "12350"
+ Top = 520
+ Width = 495
+ End
+ Begin VB.Label lblIonMatchingWindow
+ Caption = "&Ion Matching Window"
+ Height = 255
+ Left = 120
+ TabIndex = 37
+ Tag = "12340"
+ Top = 1220
+ Width = 2175
+ End
+ Begin VB.Label lblPrecursorIonMass
+ Caption = "Ion Mass"
+ Height = 255
+ Left = 480
+ TabIndex = 31
+ Tag = "12320"
+ Top = 520
+ Width = 1695
+ End
+ End
+ Begin VB.Frame fraCharge
+ Caption = "Charge Options"
+ Height = 975
+ Left = 60
+ TabIndex = 25
+ Tag = "12260"
+ Top = 5280
+ Width = 2415
+ Begin VB.CheckBox chkDoubleCharge
+ Caption = "&2+ charged ions"
+ Height = 255
+ Left = 135
+ TabIndex = 26
+ Tag = "12270"
+ Top = 240
+ Width = 2055
+ End
+ Begin VB.ComboBox cboDoubleCharge
+ Height = 315
+ Left = 1215
+ Style = 2 'Dropdown List
+ TabIndex = 28
+ Tag = "12285"
+ ToolTipText = "The 2+ m/z value will be computed for ions above this m/z"
+ Top = 600
+ Width = 1095
+ End
+ Begin VB.Label lblDoubleCharge
+ Alignment = 1 'Right Justify
+ Caption = "Threshold"
+ Height = 255
+ Left = 120
+ TabIndex = 27
+ Tag = "12280"
+ Top = 600
+ Width = 1020
+ End
+ End
+ Begin VB.Frame fraTerminii
+ Caption = "N and C Terminus"
+ Height = 1255
+ Left = 60
+ TabIndex = 11
+ Tag = "12150"
+ Top = 1680
+ Width = 2415
+ Begin VB.ComboBox cboCTerminus
+ Height = 315
+ Left = 600
+ Style = 2 'Dropdown List
+ TabIndex = 15
+ Tag = "12190"
+ Top = 800
+ Width = 1575
+ End
+ Begin VB.ComboBox cboNTerminus
+ Height = 315
+ Left = 600
+ Style = 2 'Dropdown List
+ TabIndex = 13
+ Tag = "12180"
+ Top = 320
+ Width = 1575
+ End
+ Begin VB.Label lblCTerminus
+ Caption = "&C"
+ Height = 255
+ Left = 120
+ TabIndex = 14
+ Tag = "12170"
+ Top = 840
+ Width = 300
+ End
+ Begin VB.Label lblNTerminus
+ Caption = "&N"
+ Height = 255
+ Left = 120
+ TabIndex = 12
+ Tag = "12160"
+ Top = 360
+ Width = 300
+ End
+ End
+ Begin VB.Frame fraNeutralLosses
+ Caption = "Neutral Losses"
+ Height = 1005
+ Left = 60
+ TabIndex = 20
+ Tag = "12230"
+ Top = 4200
+ Width = 2415
+ Begin VB.CheckBox chkPhosphateLoss
+ Caption = "Loss of PO4"
+ Height = 255
+ Left = 600
+ TabIndex = 24
+ Tag = "12255"
+ Top = 680
+ Width = 1695
+ End
+ Begin VB.ListBox lstIonsToModify
+ Height = 645
+ ItemData = "frmFragmentationModelling.frx":08CA
+ Left = 120
+ List = "frmFragmentationModelling.frx":08D7
+ MultiSelect = 1 'Simple
+ TabIndex = 21
+ Tag = "12235"
+ ToolTipText = "Choose ions to which losses will be applied"
+ Top = 240
+ Width = 375
+ End
+ Begin VB.CheckBox chkAmmoniaLoss
+ Caption = "Loss of NH3"
+ Height = 255
+ Left = 600
+ TabIndex = 23
+ Tag = "12250"
+ Top = 440
+ Width = 1695
+ End
+ Begin VB.CheckBox chkWaterLoss
+ Caption = "Loss of H2O"
+ Height = 255
+ Left = 600
+ TabIndex = 22
+ Tag = "12240"
+ Top = 200
+ Value = 1 'Checked
+ Width = 1695
+ End
+ End
+ Begin VB.Frame fraIonTypes
+ Caption = "Ion Types"
+ Height = 1095
+ Left = 60
+ TabIndex = 16
+ Tag = "12200"
+ Top = 3000
+ Width = 2415
+ Begin VB.CheckBox chkIonType
+ Caption = "&Y Ions"
+ Height = 255
+ Index = 2
+ Left = 120
+ TabIndex = 19
+ Tag = "12220"
+ Top = 720
+ Value = 1 'Checked
+ Width = 2130
+ End
+ Begin VB.CheckBox chkIonType
+ Caption = "&B Ions"
+ Height = 255
+ Index = 1
+ Left = 120
+ TabIndex = 18
+ Tag = "12215"
+ Top = 480
+ Value = 1 'Checked
+ Width = 2175
+ End
+ Begin VB.CheckBox chkIonType
+ Caption = "&A Ions"
+ Height = 255
+ Index = 0
+ Left = 120
+ TabIndex = 17
+ Tag = "12210"
+ Top = 240
+ Width = 2175
+ End
+ End
+ Begin MSFlexGridLib.MSFlexGrid grdFragMasses
+ Height = 4455
+ Left = 2640
+ TabIndex = 43
+ Top = 1800
+ Width = 4335
+ _ExtentX = 7646
+ _ExtentY = 7858
+ _Version = 393216
+ FixedCols = 0
+ End
+ Begin VB.ComboBox cboNotation
+ Height = 315
+ Left = 120
+ Style = 2 'Dropdown List
+ TabIndex = 3
+ Tag = "12010"
+ ToolTipText = "Amino acid sequence notation type"
+ Top = 840
+ Width = 2295
+ End
+ Begin VB.TextBox txtSequence
+ Height = 555
+ Left = 1440
+ MultiLine = -1 'True
+ ScrollBars = 2 'Vertical
+ TabIndex = 1
+ Tag = "12050"
+ ToolTipText = "Enter amino acid sequence here"
+ Top = 120
+ Width = 5535
+ End
+ Begin VB.Label lblSequence
+ Caption = "&Sequence:"
+ Height = 255
+ Left = 60
+ TabIndex = 0
+ Tag = "12100"
+ Top = 180
+ Width = 1335
+ End
+ Begin VB.Menu mnuFile
+ Caption = "&File"
+ Begin VB.Menu mnuLoadSequenceInfo
+ Caption = "&Load Sequence Info"
+ Shortcut = ^L
+ End
+ Begin VB.Menu mnuSaveSequenceInfo
+ Caption = "&Save Sequence Info"
+ Shortcut = ^S
+ End
+ Begin VB.Menu mnuFileSep1
+ Caption = "-"
+ End
+ Begin VB.Menu mnuLoadIonList
+ Caption = "Load List of &Ions or .Dta file to Match"
+ Shortcut = ^D
+ End
+ Begin VB.Menu mnuFileSep2
+ Caption = "-"
+ End
+ Begin VB.Menu mnuClose
+ Caption = "&Close"
+ End
+ End
+ Begin VB.Menu mnuEdit
+ Caption = "&Edit"
+ Begin VB.Menu mnuCopyPredictedIons
+ Caption = "&Copy Predicted Ions"
+ End
+ Begin VB.Menu mnuCopyPredictedIonsAsRTF
+ Caption = "Copy Predicted Ions as &RTF"
+ Shortcut = ^R
+ End
+ Begin VB.Menu mnuCopyPredictedIonsAsHtml
+ Caption = "Copy Predicted Ions as &Html"
+ End
+ Begin VB.Menu mnuEditSep1
+ Caption = "-"
+ End
+ Begin VB.Menu mnuCopySequenceMW
+ Caption = "Copy Sequence Molecular &Weight"
+ Shortcut = ^W
+ End
+ Begin VB.Menu mnuEditSep2
+ Caption = "-"
+ End
+ Begin VB.Menu mnuPasteIonList
+ Caption = "&Paste List of Ions to Match"
+ End
+ Begin VB.Menu mnuClearMatchIonList
+ Caption = "Clear Match Ion &List"
+ Enabled = 0 'False
+ End
+ End
+ Begin VB.Menu mnuView
+ Caption = "&View"
+ Begin VB.Menu mnuViewMatchIonList
+ Caption = "List of &Ions to Match"
+ Shortcut = ^I
+ End
+ Begin VB.Menu mnuViewSep1
+ Caption = "-"
+ End
+ Begin VB.Menu mnuShowMassSpectrum
+ Caption = "&Mass Spectrum"
+ Shortcut = ^M
+ End
+ Begin VB.Menu mnuUpdateSpectrum
+ Caption = "&Update Spectrum on Change"
+ Shortcut = ^U
+ End
+ Begin VB.Menu mnuViewDtaTxtSep
+ Caption = "-"
+ End
+ Begin VB.Menu mnuViewDtaTxtBrowser
+ Caption = "&Dta.Txt File Browser"
+ End
+ End
+ Begin VB.Menu mnuTools
+ Caption = "&Tools"
+ Begin VB.Menu mnuIonMatchListOptions
+ Caption = "Ion Match List &Options"
+ Shortcut = ^O
+ End
+ Begin VB.Menu mnuEditModificationSymbols
+ Caption = "Edit Residue &Modification Symbols"
+ Shortcut = ^E
+ End
+ Begin VB.Menu mnuToolsSep1
+ Caption = "-"
+ End
+ Begin VB.Menu mnuAutoAlign
+ Caption = "&Automatically Align Ions to Match"
+ End
+ End
+ Begin VB.Menu mnuHelp
+ Caption = "&Help"
+ Begin VB.Menu mnuFragmentationModellingHelp
+ Caption = "&Fragmentation Modelling"
+ End
+ End
+ Begin VB.Menu mnuIonMatchListRightClick
+ Caption = "IonMatchListRightClickMenu"
+ Begin VB.Menu mnuIonMatchListRightClickCopy
+ Caption = "&Copy Selected Ions"
+ End
+ Begin VB.Menu mniIonMatchListRightClickPaste
+ Caption = "&Paste List of Ions to Match"
+ End
+ Begin VB.Menu mnuIonMatchListRightClickDeleteAll
+ Caption = "&Delete All (Clear list)"
+ End
+ Begin VB.Menu mnuIonMatchListRightClickSep1
+ Caption = "-"
+ End
+ Begin VB.Menu mnuIonMatchListRightClickSelectAll
+ Caption = "Select &All"
+ End
+ End
+End
+Attribute VB_Name = "frmFragmentationModelling"
+Attribute VB_GlobalNameSpace = False
+Attribute VB_Creatable = False
+Attribute VB_PredeclaredId = True
+Attribute VB_Exposed = False
+Option Explicit
+
+Private Const TOTAL_POSSIBLE_ION_TYPES = 3
+Private Const MAX_CHARGE_STATE = 2
+Private Const MAX_MODIFICATIONS = 6 ' Maximum number of modifications for a single residue
+Private Const SHOULDER_ION_PREFIX = "Shoulder-"
+
+Private Const ANNOTATION_FONT_SIZE = 10
+Private Const MAX_SERIES_COUNT = 32
+
+' The following values are now given by the itIonTypeConstants enumerated type
+'Const itAIon = 0
+'Const itBIon = 1
+'Const itYIon = 2
+
+Private Const MAX_BIN_COUNT = 50000
+Private Const ION_SEPARATION_TOLERANCE_TO_AUTO_ENABLE_BINNING = 0.2
+
+Const ION_LIST_COL_COUNT = 3
+Private Enum ilgIonListGridConstants
+ ilgMass = 0
+ ilgIntensity = 1
+ ilgSymbolMatch = 2
+End Enum
+
+Const ION_LIST_ARRAY_MAXINDEX_2D = 2
+Private Enum ilaIonListArrayConstants
+ ilaMass = 0
+ ilaIntensity = 1
+ ilaNormalizedIntensity = 2
+End Enum
+
+Private Type udtGridLocationType
+ Row As Long
+ Col As Long
+End Type
+
+' The udtResidueMatchedType type is used to record if the given ion type of the
+' given charge was matched in sub MatchIons
+' For example, if the b ion for residue 2 is seen singly charged, then
+' .IonType(itBIon, 1) = True
+Private Type udtResidueMatchedType
+ IonHit(TOTAL_POSSIBLE_ION_TYPES, MAX_CHARGE_STATE) As Boolean
+End Type
+
+Private Type udtIonMatchListDetailsType
+ Caption As String
+ OriginalMaximumIntensity As Double
+End Type
+
+Private dblImmoniumMassDifference As Double ' CO minus H = 26.9871
+
+Private dblHistidineFW As Double ' 110
+Private dblPhenylalanineFW As Double ' 120
+Private dblTyrosineFW As Double ' 136
+
+Private mFormActivatedByUser As Boolean ' Set true the first time the user activates the form; always true from then on
+ ' Used to prevent plotting the mass spectrum until after the user has activated the fragmentation match form at least once
+
+Private mFragMatchSettingsChanged As Boolean
+
+' FragSpectrumDetails() contains detailed information on the fragmentation spectrum data, sorted by mass
+' FragSpectrumGridLocs() contains the row and column indices in grdFragMasses that the values in FragSpectrumDetails() are displayed at
+' Both contain an equal number of data points, given by FragSpectrumIonCount
+Private FragSpectrumIonCount As Long
+Private FragSpectrumDetails() As udtFragmentationSpectrumDataType ' 0-based array, ranging from 0 to FragSpectrumIonCount-1
+
+Private FragSpectrumGridLocs() As udtGridLocationType
+
+Private CRCForPredictedSpectrumSaved As Double ' Used to determine if the values in PredictedSpectrum() have changed
+Private CRCForIonListSaved As Double ' Used to determine if the values in grdIonList() have changed
+
+Private mAutoAligning As Boolean ' Set to True when auto-aligning (determining the best offset)
+Private dblAlignmentScore As Double ' The score computed for a match
+Private lngAlignmentMatchCount As Long ' # of matches for the current alignment
+
+Private IonMatchList() As Double ' List of ions to match to those in FragSpectrumDetails()
+ ' 2D array, 1-based in the first dimension but uses columns 0, 1, and 2
+ ' Column 0 is the mass, column 1 the raw intensity, column 2 is the normalized intensity (or -1 if not used)
+Private IonMatchListCount As Long
+Private mIonMatchListDetails As udtIonMatchListDetailsType
+
+Private BinnedData() As Double ' Binned version of IonMatchList()
+ ' 2D array, 1-based in the first dimension but uses columns 0, 1, and 2
+ ' Column 0 is the mass, column 1 the raw intensity, column 2 is the normalized intensity (or -1 if not used)
+Private BinnedDataCount As Long ' When BinnedDataCount = 0, not using BinnedData. If non-zero, then we are using binned data
+
+Private mDelayUpdate As Boolean
+Private mNeedToZoomOutFull As Boolean
+
+Private udtNewFragmentationSpectrumOptions As udtFragmentationSpectrumOptionsType
+
+Private WithEvents objSpectrum As CWSpectrumDLL.Spectrum
+Attribute objSpectrum.VB_VarHelpID = -1
+'
+
+Private Sub AddIonPairToIonList(strThisLine As String, lngPointsLoaded As Long, blnAllowCommaDelimeter As Boolean, dblMinMass As Double, dblMaxMass As Double)
+ Dim strLeftChar As String, strDelimeterList As String
+ Dim dblParsedVals(3) As Double ' 1-based array
+ Dim intParseValCount As Integer
+
+ ' Only parse if the first letter (trimmed) is a number (may start with - or +)
+ strLeftChar = Left(strThisLine, 1)
+ If IsNumeric(strLeftChar) Or strLeftChar = "-" Or strLeftChar = "+" Then
+
+ ' Construct Delimeter List: Contains a space, Tab, and possibly comma
+ strDelimeterList = " " & vbTab & vbCr & vbLf
+ If blnAllowCommaDelimeter Then
+ strDelimeterList = strDelimeterList & ","
+ End If
+
+ intParseValCount = ParseStringValuesDbl(strThisLine, dblParsedVals(), 2, strDelimeterList, , False, False, True)
+
+ If intParseValCount >= 2 Then
+
+ If dblParsedVals(1) <> 0 And dblParsedVals(2) <> 0 Then
+ lngPointsLoaded = lngPointsLoaded + 1
+
+ AppendXYPair IonMatchList(), IonMatchListCount, dblParsedVals(1), dblParsedVals(2), True
+
+ If dblParsedVals(1) < dblMinMass Then dblMinMass = dblParsedVals(1)
+ If dblParsedVals(1) > dblMaxMass Then dblMaxMass = dblParsedVals(1)
+ End If
+ End If
+ End If
+
+End Sub
+
+Private Function AddSpectrumLabels(lngDataCount As Long, dblXVals() As Double, dblYVals() As Double, strDataLabels() As String, intSeriesNumber As Integer) As Long
+ ' Returns the number of labels added
+ ' Note that strDataLabels() should be 0-based
+
+ Dim lngIndex As Long, lngCharIndex As Long, lngLabelsAdded As Long
+ Dim strNewCaption As String, strFirstChar As String
+ Dim blnShowCaption As Boolean, blnShowAllCaptions As Boolean
+
+ If Not (cChkBox(frmIonMatchOptions.chkFragSpecLabelMainIons) Or cChkBox(frmIonMatchOptions.chkFragSpecLabelOtherIons)) Then
+ AddSpectrumLabels = 0
+ Exit Function
+ End If
+ lngLabelsAdded = 0
+
+ With objSpectrum
+
+ .SetAnnotationFontSize intSeriesNumber, ANNOTATION_FONT_SIZE, True
+ .SetAnnotationDensityToleranceAutoAdjust True ' Could use ToleranceX = 0.9
+
+ If cChkBox(frmIonMatchOptions.chkFragSpecLabelMainIons) And cChkBox(frmIonMatchOptions.chkFragSpecLabelOtherIons) Then
+ blnShowAllCaptions = True
+ Else
+ blnShowAllCaptions = False
+ End If
+
+ For lngIndex = 0 To lngDataCount - 1
+ If Len(strDataLabels(lngIndex)) > 0 Then
+
+ strNewCaption = strDataLabels(lngIndex)
+
+ If blnShowAllCaptions Then
+ blnShowCaption = True
+ Else
+ strFirstChar = LCase(Left(strNewCaption, 1))
+
+ ' See if this is a primary ion label; i.e. a1, b1, y1, a2, b2, y2, etc.
+ blnShowCaption = True
+ If strFirstChar = "a" Or strFirstChar = "b" Or strFirstChar = "y" Then
+ lngCharIndex = 2
+ Do While lngCharIndex <= Len(strNewCaption)
+ If Not IsNumeric(Mid(strNewCaption, lngCharIndex, 1)) Then
+ blnShowCaption = False
+ Exit Do
+ End If
+ lngCharIndex = lngCharIndex + 1
+ Loop
+
+ If blnShowCaption Then
+ ' This is a primary ion label
+ ' Examine chkFragSpecLabelMainIons
+ blnShowCaption = cChkBox(frmIonMatchOptions.chkFragSpecLabelMainIons)
+ Else
+ blnShowCaption = cChkBox(frmIonMatchOptions.chkFragSpecLabelOtherIons)
+ End If
+ Else
+ blnShowCaption = cChkBox(frmIonMatchOptions.chkFragSpecLabelOtherIons)
+ End If
+ End If
+
+ ' Do not show captions for shoulder ions
+ If InStr(strNewCaption, "Shoulder-") > 0 Then blnShowCaption = False
+
+ If blnShowCaption Then
+
+ .SetAnnotation False, dblXVals(lngIndex) + 1, dblYVals(lngIndex), strNewCaption, 0, intSeriesNumber, asmFixedToSingleDataPoint, lngIndex, False, False, False, True, 0, True
+
+ lngLabelsAdded = lngLabelsAdded + 1
+ End If
+ End If
+ Next lngIndex
+
+ End With
+
+ AddSpectrumLabels = lngLabelsAdded
+
+End Function
+
+Public Sub AlignmentOffsetValidate()
+
+ If IsNumeric(txtAlignment) Then
+ FillIonMatchGridWrapper
+ UpdateMassesGridAndSpectrumWrapper
+ End If
+
+End Sub
+
+Private Sub AppendXYPair(ByRef ThisSpectrum() As Double, ThisSpectrumCount As Long, dblXData As Double, dblYData As Double, Optional blnIncludeZeroXValue As Boolean = False)
+ ' ThisSpectrum() is a 2D array, 1-based in the first column and 0-based in the second column
+ ' Note: Will not add data if dblXData = 0 and blnIncludeZeroXValue = False
+
+ Dim lngDimCount As Long, lngIndex As Long
+ Dim dblSpectrumCopy() As Double ' 2D array, 1-based in the first dimension, 0 to 2 in the second dimension
+
+ If dblXData = 0 And Not blnIncludeZeroXValue Then
+ Exit Sub
+ End If
+
+ lngDimCount = UBound(ThisSpectrum(), 1)
+
+ If ThisSpectrumCount >= lngDimCount Then
+ ' Need to increase the space in ThisSpectrum()
+ Debug.Assert False
+
+ ' However, can't use Redim Preserve since ThisSpectrum() is a 2D array
+ ReDim dblSpectrumCopy(lngDimCount + 10, 0 To ION_LIST_ARRAY_MAXINDEX_2D)
+ For lngIndex = 0 To lngDimCount
+ dblSpectrumCopy(lngIndex, ilaMass) = ThisSpectrum(lngIndex, ilaMass)
+ dblSpectrumCopy(lngIndex, ilaIntensity) = ThisSpectrum(lngIndex, ilaIntensity)
+ dblSpectrumCopy(lngIndex, ilaNormalizedIntensity) = ThisSpectrum(lngIndex, ilaNormalizedIntensity)
+ Next lngIndex
+
+ ' Now that dblSpectrumCopy() has been populated, we can perform a bulk array copy using the following
+ ThisSpectrum() = dblSpectrumCopy()
+
+ End If
+
+ ThisSpectrumCount = ThisSpectrumCount + 1
+ ThisSpectrum(ThisSpectrumCount, ilaMass) = dblXData
+ ThisSpectrum(ThisSpectrumCount, ilaIntensity) = dblYData
+
+End Sub
+
+Private Sub AutoAlignMatchIonList()
+ Dim dblMaxOffset As Double, dblOffsetIncrement As Double
+ Dim lngIterationsCompleted As Long, lngPredictedIterationCount As Long
+ Dim dblBestScore As Double, dblBestScoreOffset As Double, dblAdditionalBestScoreOffset As Double
+ Dim dblCurrentOffset As Double, dblOffsetEnd As Double
+ Dim lngSequentialDuplicates As Long
+ Dim blnUpdateSpectrumSaved As Boolean
+
+ With frmSetValue
+ .Caption = LookupMessage(1150)
+ .lblStartVal.Caption = LookupMessage(1155)
+ .txtStartVal = "10"
+ .lblEndVal.Caption = LookupMessage(1160)
+ .txtEndVal = 0.1
+
+ .SetLimits False
+
+ .Show vbModal
+ End With
+
+ If UCase(frmSetValue.lblHiddenStatus) <> "OK" Then Exit Sub
+
+ ' Auto Align the Ion Match List
+ With frmSetValue
+ If IsNumeric(.txtStartVal) Then
+ dblMaxOffset = Abs(CDbl(.txtStartVal))
+ Else
+ dblMaxOffset = 10
+ End If
+
+ If dblMaxOffset < 0.5 Or dblMaxOffset > 1000 Then dblMaxOffset = 10
+
+ If IsNumeric(.txtEndVal) Then
+ dblOffsetIncrement = Abs(CDbl(.txtEndVal))
+ Else
+ dblOffsetIncrement = 0.1
+ End If
+ dblOffsetIncrement = Round(dblOffsetIncrement, 3)
+ If dblOffsetIncrement < 0.001 Or dblOffsetIncrement > 10 Then dblOffsetIncrement = 0.1
+ End With
+
+ ' Determine the predicted iteration count
+ lngPredictedIterationCount = dblMaxOffset * 2 / dblOffsetIncrement
+
+ If lngPredictedIterationCount > 10000 Then
+ ' Over 1000 predicted iterations
+ ' Raise dblOffsetIncrement so that lngPredictedIterationCount = 10000
+ lngPredictedIterationCount = 10000
+ dblOffsetIncrement = dblMaxOffset * 2 / lngPredictedIterationCount
+ End If
+
+ ' Disable automatic plot updating
+ blnUpdateSpectrumSaved = mnuUpdateSpectrum.Checked
+ mnuUpdateSpectrum.Checked = False
+
+ ' Hide grdIonList and grdFragMasses
+ grdIonList.Visible = False
+ grdFragMasses.Visible = False
+
+ ' Turn on mAutoAligning
+ mAutoAligning = True
+
+ ' Show the Progress form
+ frmProgress.InitializeForm LookupMessage(1165), 0, lngPredictedIterationCount, True
+ frmProgress.ToggleAlwaysOnTop True
+
+ dblCurrentOffset = -dblMaxOffset
+ dblOffsetEnd = dblMaxOffset
+
+ lngSequentialDuplicates = 0
+ lngIterationsCompleted = 0
+ Do While dblCurrentOffset < dblOffsetEnd
+ ' Assigning dblCurrentOffset to txtAlignment does not trigger the _Validate function
+ txtAlignment = dblCurrentOffset
+
+ ' Must set mFragMatchSettingsChanged to True each time before re-matching
+ mFragMatchSettingsChanged = True
+
+ ' Update the masses of the match ions
+ FillIonMatchGridWrapper
+
+ ' Remove cell coloring from grdFragMasses
+ FlexGridRemoveHighlighting grdFragMasses, 1, grdFragMasses.Cols - 2
+
+ ' Perform the match
+ MatchIons
+
+ ' See if new dblMatchScore is better than previous
+ ' If so, save new offset as best offset
+ If dblAlignmentScore >= dblBestScore Then
+ If dblAlignmentScore > dblBestScore Then
+ dblBestScore = dblAlignmentScore
+ dblBestScoreOffset = dblCurrentOffset
+ ' Update Stats since new best
+ UpdateMatchCountAndScoreWork lngAlignmentMatchCount, dblAlignmentScore
+
+ ' Set lngSequentialDuplicates
+ lngSequentialDuplicates = 1
+ ' Reset dblAdditionalBestScoreOffset
+ dblAdditionalBestScoreOffset = dblCurrentOffset
+ Else
+ If dblCurrentOffset - dblOffsetIncrement * 1.51 < dblAdditionalBestScoreOffset Then
+ dblAdditionalBestScoreOffset = dblCurrentOffset
+ lngSequentialDuplicates = lngSequentialDuplicates + 1
+ End If
+ End If
+ End If
+
+ ' Update Iterations counter
+ lngIterationsCompleted = lngIterationsCompleted + 1
+ If lngIterationsCompleted Mod 5 = 0 Then
+ frmProgress.UpdateProgressBar lngIterationsCompleted
+ If KeyPressAbortProcess > 1 Then
+ Exit Do
+ End If
+ End If
+
+ ' Computer new offset
+ dblCurrentOffset = Round(dblCurrentOffset + dblOffsetIncrement, 3)
+
+ Loop
+ KeyPressAbortProcess = 0
+
+ If lngSequentialDuplicates > 1 Then
+ ' More than one offset in a row gave the same score
+ ' dblBestScoreOffset is the first score that matched while dblAdditionalBestScoreOffset is the last
+ dblBestScoreOffset = dblBestScoreOffset + Abs((dblAdditionalBestScoreOffset - dblBestScoreOffset)) / 2
+ End If
+
+' MsgBox "Best offset is " & dblBestScoreOffset & " (" & lngSequentialDuplicates & " duplicates)", vbInformation + vbOKOnly, "Alignment Results"
+
+ ' Hide the progress form
+ frmProgress.HideForm
+
+ ' Turn off mAutoAligning
+ mAutoAligning = False
+
+ ' Store best match in txtAlignment
+ ' Does not trigger any match routines, so must manually call
+ txtAlignment = dblBestScoreOffset
+
+ UpdateIonMatchListWrapper
+
+ ' Re-enable mnuUpdateSpectrum
+ mnuUpdateSpectrum.Checked = blnUpdateSpectrumSaved
+
+ ' Unhide grdIonList
+ grdIonList.Visible = True
+
+End Sub
+
+Private Sub BinIonMatchList()
+
+ Const BIN_MEMBER_COUNT_INDEX = 2
+
+ Dim lngIndex As Long, lngBinNumber As Long
+ Dim lngValuesToPopulate As Long
+ Dim lclBinnedData() As Double ' Binned version of IonMatchList()
+ ' 2D array, 1-based in the first dimension but uses columns 0, 1, and 2
+ ' Column 0 is the mass, column 1 the raw intensity, column 2 is the normalized intensity (or -1 if not used)
+ ' Note, though, that I actually use column 3 to record the number of ions in each bin
+
+ Dim lclBinnedDataCount As Long ' When lclBinnedDataCount = 0, not using lclBinnedData. If non-zero, then we are using binned data
+
+ Dim dblMassMinimum As Double, dblMassMaximum As Double
+ Dim dblBinWindow As Double
+
+ ' Exit sub if user has turned off binning
+ If Not cChkBox(frmIonMatchOptions.chkGroupSimilarIons) Or IonMatchListCount = 0 Then
+ BinnedDataCount = 0
+ ReDim BinnedData(1, 0 To ION_LIST_ARRAY_MAXINDEX_2D)
+ Exit Sub
+ End If
+
+ With frmIonMatchOptions
+ dblBinWindow = .txtGroupIonMassWindow
+ If dblBinWindow < 0 Or dblBinWindow > 100 Then
+ dblBinWindow = 0.5
+ End If
+ End With
+
+ If dblBinWindow = 0 Then
+ ' Window is 0, do not attempt to bin data
+ Exit Sub
+ End If
+
+ ' Find the Mass Limits
+ FindMassLimits IonMatchList(), IonMatchListCount, dblMassMinimum, dblMassMaximum
+
+ ' Determine the total number of bins, limiting to MAX_BIN_COUNT if necessary
+ lclBinnedDataCount = CLngRoundUp((dblMassMaximum - dblMassMinimum) / dblBinWindow)
+ If lclBinnedDataCount > MAX_BIN_COUNT Then
+ lclBinnedDataCount = MAX_BIN_COUNT
+ dblBinWindow = (dblMassMaximum - dblMassMinimum) / lclBinnedDataCount
+ End If
+
+ ' Initialize lclBinnedData()
+ ReDim lclBinnedData(lclBinnedDataCount + 1, 3) ' 1-based array in the first dimension
+ ' For 2nd dimension, column 0 is mass, column 1 is intensity
+ ' and column 2 is # of data points assigned to bin
+ ' An explanation on the binning process:
+ ' For each mass in IonMatchList() the appropriate bin number is calculated
+ ' If the bin is empty, the ion's mass and intensity are assigned to the bin (,0) and (,1)
+ ' and a 1 is placed in cell lclBinnedData(lngBinNumber,2)
+ ' If the bin already has a value in it, the new mass is added to the current mass
+ ' and cell (,2) is incremented by 1
+ ' Additionally, the intensities are compared and the higher intensity is assigned to cell (,1)
+ ' When all done binning, the values in cell (,0) are divided by the value in (,2) to get an
+ ' averag mass value for all of the masses assigned to the bin
+
+ ' Step through IonMatchList() and assign data to appropriate bin
+ For lngIndex = 1 To IonMatchListCount
+ lngBinNumber = MassToBinNumber(IonMatchList(lngIndex, ilaMass), dblMassMinimum, dblBinWindow)
+ If lclBinnedData(lngBinNumber, ilaMass) = 0 Then
+ ' No ions assigned to this bin yet; assign mass and intensity
+ lclBinnedData(lngBinNumber, ilaMass) = IonMatchList(lngIndex, ilaMass)
+ lclBinnedData(lngBinNumber, ilaIntensity) = IonMatchList(lngIndex, ilaIntensity)
+ lclBinnedData(lngBinNumber, BIN_MEMBER_COUNT_INDEX) = 1
+ Else
+ lclBinnedData(lngBinNumber, ilaMass) = lclBinnedData(lngBinNumber, ilaMass) + IonMatchList(lngIndex, ilaMass)
+ If IonMatchList(lngIndex, ilaIntensity) > lclBinnedData(lngBinNumber, ilaIntensity) Then
+ lclBinnedData(lngBinNumber, ilaIntensity) = IonMatchList(lngIndex, ilaIntensity)
+ End If
+ lclBinnedData(lngBinNumber, BIN_MEMBER_COUNT_INDEX) = lclBinnedData(lngBinNumber, BIN_MEMBER_COUNT_INDEX) + 1
+ End If
+ Next lngIndex
+
+ ' Step through lclBinnedData() and compute the correct mass
+ ' Additionally, determine the number of bins with actual data in them
+ lngValuesToPopulate = 0
+ For lngBinNumber = 1 To lclBinnedDataCount
+ If lclBinnedData(lngBinNumber, BIN_MEMBER_COUNT_INDEX) > 0 Then
+ lngValuesToPopulate = lngValuesToPopulate + 1
+ lclBinnedData(lngBinNumber, ilaMass) = lclBinnedData(lngBinNumber, ilaMass) / lclBinnedData(lngBinNumber, BIN_MEMBER_COUNT_INDEX)
+ End If
+ Next lngBinNumber
+
+ ' Copy data from lclBinnedData() to BinnedData()
+ ' Only copy non-zero values
+ BinnedDataCount = lngValuesToPopulate
+
+
+ ' Redimension BinnedData() based on lngValuesToPopulate
+ ReDim BinnedData(BinnedDataCount + 1, 0 To ION_LIST_ARRAY_MAXINDEX_2D) ' 1-based array in the first dimension
+ ' For 2nd dimension, column 0 is mass, column 1 is intensity
+ ' and column 2 is the normalized intensity
+
+ ' Load data into BinnedData()
+ lngIndex = 0
+ For lngBinNumber = 1 To lclBinnedDataCount
+ If lclBinnedData(lngBinNumber, BIN_MEMBER_COUNT_INDEX) > 0 Then
+ lngIndex = lngIndex + 1
+ BinnedData(lngIndex, ilaMass) = lclBinnedData(lngBinNumber, ilaMass)
+ BinnedData(lngIndex, ilaIntensity) = lclBinnedData(lngBinNumber, ilaIntensity)
+ BinnedData(lngIndex, ilaNormalizedIntensity) = BinnedData(lngIndex, ilaIntensity)
+ End If
+ Next lngBinNumber
+
+End Sub
+
+Private Sub CheckSequenceTerminii()
+ ' If 3 letter codes are enabled, then checks to see if the sequence begins with H and ends with OH
+ ' If so, makes sure the first three letters are not an amino acid
+ ' If they're not, removes the H and OH and sets cboNTerminus and cboCTerminus accordingly
+
+ Dim strCleanSequence As String
+ Dim lngAbbrevID As Long, strSymbol As String
+ Dim blnIsAminoAcid As Boolean
+
+ mDelayUpdate = True
+
+ If Len(txtSequence) > 0 And Get3LetterCodeState = True Then
+ If UCase(Left(txtSequence, 1)) = "H" Then
+ If UCase(Right(txtSequence, 2)) = "OH" Then
+ If IsCharacter(Mid(txtSequence, 2, 1)) And IsCharacter(Mid(txtSequence, 3, 1)) Then
+ lngAbbrevID = objMwtWin.GetAbbreviationID(Left(txtSequence, 3))
+ If lngAbbrevID > 0 Then
+ ' Matched an abbreviation; is it an amino acid?
+ objMwtWin.GetAbbreviation lngAbbrevID, strSymbol, "", 0, blnIsAminoAcid
+ If Not blnIsAminoAcid Then
+ ' Matched an abbreviation, but it's not an amino acid
+ lngAbbrevID = 0
+ End If
+ End If
+ Else
+ lngAbbrevID = 0
+ End If
+
+ If lngAbbrevID = 0 Then
+ ' The first three characters do not represent a 3 letter amino acid code
+ ' Remove the H and OH
+ strCleanSequence = Mid(txtSequence, 2, Len(txtSequence) - 3)
+ If Left(strCleanSequence, 1) = "-" Then strCleanSequence = Mid(strCleanSequence, 2)
+ If Right(strCleanSequence, 1) = "-" Then strCleanSequence = Left(strCleanSequence, Len(strCleanSequence) - 1)
+ txtSequence = strCleanSequence
+
+ cboNTerminus.ListIndex = ntgHydrogen
+ cboCTerminus.ListIndex = ctgHydroxyl
+ End If
+ End If
+ End If
+ End If
+
+ mDelayUpdate = False
+
+End Sub
+
+Private Sub ConvertSequenceMH(blnFavorMH As Boolean)
+ ' When blnFavorMH = True then computes MHAlt using MH
+ ' Otherwise, computes MH using MHAlt
+
+ Static blnWorking As Boolean
+ Dim dblMH As Double, dblMHAlt As Double, intCharge As Integer
+
+ If blnWorking Then Exit Sub
+ blnWorking = True
+
+ intCharge = cboMHAlternate.ListIndex + 1
+ If intCharge < 1 Then intCharge = 1
+
+ If blnFavorMH Then
+ dblMH = CDblSafe(txtMH)
+ If dblMH > 0 Then
+ dblMHAlt = objMwtWin.ConvoluteMass(dblMH, 1, intCharge)
+ Else
+ dblMHAlt = 0
+ End If
+ txtMHAlt = Round(dblMHAlt, 6)
+ Else
+ dblMHAlt = CDblSafe(txtMHAlt)
+ If dblMHAlt > 0 Then
+ dblMH = objMwtWin.ConvoluteMass(dblMHAlt, intCharge, 1)
+ Else
+ dblMH = 0
+ End If
+ txtMH = Round(dblMH, 6)
+ End If
+
+ blnWorking = False
+
+End Sub
+
+Private Sub CopyFragGridInfo(grdThisGrid As MSFlexGrid, Optional eCopyMode As gcmGridCopyModeConstants = gcmText, Optional intRowStart As Integer = -1, Optional intRowEnd As Integer = -1, Optional intColStart As Integer = -1, Optional intColEnd As Integer = -1)
+ ' intCopyMode can be 0 = text, 1 = RTF, or 2 = Html
+
+ If grdThisGrid.Rows > 1 Then
+ If intRowStart < 0 Then intRowStart = 0
+ If intRowEnd < 0 Then intRowEnd = grdThisGrid.Rows - 1
+ If intColStart < 0 Then intColStart = 0
+ If intColEnd < 0 Then intColEnd = grdThisGrid.Cols - 1
+
+ FlexGridCopyInfo Me, grdThisGrid, eCopyMode, intRowStart, intRowEnd, intColStart, intColEnd
+ End If
+
+End Sub
+
+Private Sub CopySequenceMW()
+ Dim strWork As String
+
+ strWork = Trim(objMwtWin.Peptide.GetPeptideMass())
+
+ Clipboard.SetText strWork, vbCFText
+
+End Sub
+
+Public Sub DisplaySpectra()
+ Dim lngIndex As Long
+
+ Static blnSeriesPlotModeInitialized(MAX_SERIES_COUNT) As Boolean
+
+ Dim PredictedSpectrumCRC As Double
+ Dim dblMassTimesIntensity As Double
+ Dim blnUpdateFragSpectrum As Boolean, blnUpdateIonListSpectrum As Boolean
+ Dim blnAllowResumeNextErrorHandling As Boolean
+ Dim blnEmphasizeProlineIons As Boolean
+
+ Dim dblXVals() As Double ' 0-based array
+ Dim dblYVals() As Double ' 0-based array
+ Dim strDataLabels() As String ' 0-based array
+ Dim lngDataCount As Long
+ Dim intSeriesNumber As Integer
+
+ Dim blnShowAnnotations As Boolean, blnRemoveExistingAnnotations As Boolean
+ Dim blnCursorVisibilitySaved As Boolean
+ Dim blnAutoHideCaptionsSaved As Boolean
+
+ If Not mFormActivatedByUser Then Exit Sub
+
+On Error GoTo DisplaySpectraErrorHandler
+ blnAllowResumeNextErrorHandling = True
+
+ ' Compute a CRC value for the current PredictedSpectrum() array and compare to the previously computed value
+ PredictedSpectrumCRC = 0
+ For lngIndex = 0 To FragSpectrumIonCount - 1
+ dblMassTimesIntensity = Abs((lngIndex + 1) * FragSpectrumDetails(lngIndex).Mass * FragSpectrumDetails(lngIndex).Intensity)
+ If dblMassTimesIntensity > 0 Then
+ PredictedSpectrumCRC = PredictedSpectrumCRC + Log(dblMassTimesIntensity)
+ End If
+ Next lngIndex
+
+ ' If the new CRC is different than the old one then re-plot the spectrun
+ If PredictedSpectrumCRC <> CRCForPredictedSpectrumSaved Then
+ CRCForPredictedSpectrumSaved = PredictedSpectrumCRC
+ blnUpdateFragSpectrum = True
+ End If
+
+ ' Also compute a CRC value for the ions in grdIonList and compare to the previously computed value
+ PredictedSpectrumCRC = 0
+ With grdIonList
+ lngDataCount = .Rows - 1
+ For lngIndex = 1 To lngDataCount
+ dblMassTimesIntensity = Abs(lngIndex * .TextMatrix(lngIndex, ilgMass) * .TextMatrix(lngIndex, ilgIntensity))
+ If dblMassTimesIntensity > 0 Then
+ PredictedSpectrumCRC = PredictedSpectrumCRC + Log(dblMassTimesIntensity)
+ End If
+ Next lngIndex
+ End With
+
+ ' If the new CRC is different than the old one then re-plot the spectrun
+ If PredictedSpectrumCRC <> CRCForIonListSaved Then
+ CRCForIonListSaved = PredictedSpectrumCRC
+ blnUpdateIonListSpectrum = True
+ End If
+
+ If Not (blnUpdateFragSpectrum Or blnUpdateIonListSpectrum) Then
+ Exit Sub
+ End If
+
+ blnAllowResumeNextErrorHandling = False
+
+ objSpectrum.ShowSpectrum
+
+ ' Hide the Cursor and disable auto-hiding of annotations
+ blnCursorVisibilitySaved = objSpectrum.GetCursorVisibility()
+ If blnCursorVisibilitySaved Then objSpectrum.SetCursorVisible False
+
+ blnAutoHideCaptionsSaved = objSpectrum.GetAnnotationDensityAutoHideCaptions()
+ If blnAutoHideCaptionsSaved Then objSpectrum.SetAnnotationDensityAutoHideCaptions False, False
+
+ blnEmphasizeProlineIons = cChkBox(frmIonMatchOptions.chkFragSpecEmphasizeProlineYIons)
+
+ lngDataCount = FragSpectrumIonCount
+ If lngDataCount > 0 Then
+ ReDim dblXVals(0 To lngDataCount - 1)
+ ReDim dblYVals(0 To lngDataCount - 1)
+ ReDim strDataLabels(0 To lngDataCount - 1)
+ Else
+ ReDim dblXVals(0)
+ ReDim dblYVals(0)
+ ReDim strDataLabels(0)
+ End If
+
+ ' Now fill dblXVals(), dblYVals(), and strDataLabels()
+ For lngIndex = 0 To lngDataCount - 1
+ With FragSpectrumDetails(lngIndex)
+ dblXVals(lngIndex) = .Mass
+ dblYVals(lngIndex) = .Intensity
+ strDataLabels(lngIndex) = .Symbol
+
+ If blnEmphasizeProlineIons Then
+ ' Adjust the intensity of all of the peaks to 90% of their original value
+ ' Do not adjust the intensity for any proline y ions, thus leaving them at the original intensity
+ If LCase(.SymbolGeneric) = "y" Then
+ If .SourceResidueSymbol3Letter = "Pro" Then
+ ' Leave the intensity untouched
+ Else
+ dblYVals(lngIndex) = dblYVals(lngIndex) * 0.9
+ End If
+ Else
+ dblYVals(lngIndex) = dblYVals(lngIndex) * 0.9
+ End If
+ End If
+ End With
+ Next lngIndex
+
+ ' Display the values in the mass spectrum
+ ' Only label the predicted spectrum if it is plotted inverted or if grdIonList.Rows() <=1
+ intSeriesNumber = 1
+ blnShowAnnotations = (cChkBox(frmIonMatchOptions.chkPlotSpectrumInverted) Or grdIonList.Rows <= 1)
+ blnRemoveExistingAnnotations = True
+ DisplaySpectraWork objSpectrum, intSeriesNumber, lngDataCount, dblXVals(), dblYVals(), strDataLabels(), True, "Theoretical", blnSeriesPlotModeInitialized(), 0, blnShowAnnotations, blnRemoveExistingAnnotations
+
+ ' Also plot ions in grdIonList() if present
+ If grdIonList.Rows > 1 Then
+ With grdIonList
+ lngDataCount = .Rows - 1
+ ReDim dblXVals(0 To lngDataCount - 1)
+ ReDim dblYVals(0 To lngDataCount - 1)
+ ReDim strDataLabels(0 To lngDataCount - 1)
+
+ For lngIndex = 1 To lngDataCount
+ dblXVals(lngIndex - 1) = .TextMatrix(lngIndex, ilgMass)
+ dblYVals(lngIndex - 1) = .TextMatrix(lngIndex, ilgIntensity)
+ strDataLabels(lngIndex - 1) = .TextMatrix(lngIndex, ilgSymbolMatch)
+ Next lngIndex
+ End With
+
+ ' Display the values in the mass spectrum
+ intSeriesNumber = 2
+ blnShowAnnotations = True
+ blnRemoveExistingAnnotations = Not cChkBox(frmIonMatchOptions.chkAutoLabelMass) ' Do not remove existing annotations if Auto-Label Mass is True
+ DisplaySpectraWork objSpectrum, intSeriesNumber, lngDataCount, dblXVals(), dblYVals(), strDataLabels(), False, mIonMatchListDetails.Caption, blnSeriesPlotModeInitialized(), mIonMatchListDetails.OriginalMaximumIntensity, blnShowAnnotations, blnRemoveExistingAnnotations
+ End If
+
+ ' The following will change the active series number to 2 if data was present in grdIonList
+ ' Otherwise, it will be set to 1
+ objSpectrum.SetSpectrumFormCurrentSeriesNumber intSeriesNumber
+
+ With objSpectrum
+ If mNeedToZoomOutFull Then
+ .ZoomOutFull
+ mNeedToZoomOutFull = False
+ End If
+
+ .SetCursorPosition 100, 0
+
+ ' Auto-hiding of captions was disabled above; re-enable if necessary
+ .SetAnnotationDensityAutoHideCaptions blnAutoHideCaptionsSaved
+
+ ' The cursor was hidden above; re-show it if necessary
+ If blnCursorVisibilitySaved Then
+ .SetCursorVisible True
+ End If
+
+ ' Make sure the tick spacing is set to the default
+ .SetCustomTicksXAxis 0, 0, True
+ .SetCustomTicksYAxis 0, 0, True
+
+ .ShowSpectrum
+ End With
+
+ ' Return the focus back to this form (if possible)
+ On Error Resume Next
+ Me.SetFocus
+ Exit Sub
+
+DisplaySpectraErrorHandler:
+ If blnAllowResumeNextErrorHandling Then
+ ' Something is probably wrong with the CRC computation routines
+ Debug.Assert False
+ Resume Next
+ Else
+ GeneralErrorHandler "frmFragmentationModelling|DisplaySpectra", Err.Number, Err.Description
+ End If
+
+End Sub
+
+Private Sub DisplaySpectraWork(objThisCWSpectrum As CWSpectrumDLL.Spectrum, intSeriesNumber As Integer, lngDataCount As Long, dblXVals() As Double, dblYVals() As Double, strDataLabels() As String, blnFragmentationData As Boolean, strLegendCaption As String, ByRef blnSeriesPlotModeInitialized() As Boolean, Optional dblOriginalMaximumIntensity As Double = 0, Optional blnDisplayAnnotations As Boolean = True, Optional blnRemoveExistingAnnotations As Boolean = True)
+
+ Dim udtAutoLabelPeaksSettings As udtAutoLabelPeaksOptionsType
+
+ With objThisCWSpectrum
+ If .GetSeriesCount() < intSeriesNumber Then
+ .SetSeriesCount intSeriesNumber
+ End If
+
+ If Not blnSeriesPlotModeInitialized(intSeriesNumber) Then
+ .SetSeriesPlotMode intSeriesNumber, pmStickToZero, False
+ blnSeriesPlotModeInitialized(intSeriesNumber) = True
+ End If
+
+ If lngDataCount <= 0 Then
+ .ClearData intSeriesNumber
+ Else
+ .SetDataXvsY intSeriesNumber, dblXVals(), dblYVals(), lngDataCount, strLegendCaption, dblOriginalMaximumIntensity
+
+ If blnFragmentationData Then
+ ' Fragmentation MS data
+ .SetSeriesColor intSeriesNumber, frmIonMatchOptions.lblFragSpectrumColor.BackColor
+ Else
+ ' Normal data
+ .SetSeriesColor intSeriesNumber, frmIonMatchOptions.lblMatchingIonDataColor.BackColor
+ If cChkBox(frmIonMatchOptions.chkAutoLabelMass) Then
+ udtAutoLabelPeaksSettings = .GetAutoLabelPeaksOptions()
+
+ .AutoLabelPeaks intSeriesNumber, udtAutoLabelPeaksSettings.DisplayXPos, udtAutoLabelPeaksSettings.DisplayYPos, udtAutoLabelPeaksSettings.CaptionAngle, udtAutoLabelPeaksSettings.IncludeArrow, udtAutoLabelPeaksSettings.HideInDenseRegions, udtAutoLabelPeaksSettings.PeakLabelCountMaximum, False, True
+ End If
+ End If
+
+ If blnDisplayAnnotations Then
+ If blnRemoveExistingAnnotations Then
+ objSpectrum.RemoveAnnotationsForSeries intSeriesNumber
+ End If
+
+ AddSpectrumLabels lngDataCount, dblXVals(), dblYVals(), strDataLabels(), intSeriesNumber
+ End If
+ End If
+ End With
+
+End Sub
+
+Private Sub DisplayPredictedIonMasses()
+ ' Call objMwtWin to get the predicted fragmentation spectrum masses and intensities
+ ' Use this data to populate grdFragMasses
+
+ Dim strColumnHeaders() As String
+ Dim lngColCount As Long
+
+ Dim lngIonIndex As Long
+ Dim lngResidueIndex As Long, lngResidueCount As Long
+ Dim strSymbol As String, strSymbol1Letter As String
+ Dim dblResidueMass As Double
+
+ Dim blnIsModified As Boolean
+ Dim lngModIDs() As Long
+ Dim intModCount As Integer, intModIndex As Integer
+ Dim strModSymbol As String, strModSymbolForThisResidue As String
+
+ Dim blnUse3LetterSymbol As Boolean
+ Dim lngErrorID As Long
+ Dim lngColIndex As Long, lngSeqColIndex As Long
+ Dim lngThisRow As Long
+ Dim strSymbolGeneric As String
+
+On Error GoTo DisplayPredictedIonMassesErrorHandler
+
+ UpdateFragmentationSpectrumOptions
+
+ ' The GetFragmentationMasses() function computes the masses, intensities, and symbols for the given sequence
+ FragSpectrumIonCount = objMwtWin.Peptide.GetFragmentationMasses(FragSpectrumDetails())
+
+ ' Initialize (and clear) grdFragMasses
+ grdFragMasses.Visible = False
+ lngSeqColIndex = InitializeFragMassGrid(strColumnHeaders(), lngColCount)
+
+ ' Now populate grdFragMasses with the data
+ lngResidueCount = objMwtWin.Peptide.GetResidueCount
+ blnUse3LetterSymbol = Get3LetterCodeState()
+ For lngResidueIndex = 1 To lngResidueCount
+
+ lngErrorID = objMwtWin.Peptide.GetResidue(lngResidueIndex, strSymbol, dblResidueMass, blnIsModified, intModCount)
+
+ strModSymbolForThisResidue = ""
+ If blnIsModified Then
+ ' I really shouldn't have to ReDim lngModIDs here, but the Dll is refusing to do it, thus generating an error
+ ReDim lngModIDs(MAX_MODIFICATIONS)
+
+ intModCount = objMwtWin.Peptide.GetResidueModificationIDs(lngResidueIndex, lngModIDs())
+
+ For intModIndex = 1 To intModCount
+ objMwtWin.Peptide.GetModificationSymbol lngModIDs(intModIndex), strModSymbol, 0, 0, ""
+ strModSymbolForThisResidue = strModSymbolForThisResidue & strModSymbol
+ Next intModIndex
+ End If
+
+ Debug.Assert lngErrorID = 0
+
+ ' Add a new row to grdFragMasses
+ With grdFragMasses
+ .Rows = .Rows + 1
+ lngThisRow = .Rows - 1
+
+ ' Add residue number to first column
+ .TextMatrix(lngThisRow, 0) = lngResidueIndex
+
+ ' Add reverse residue number to last column
+ .TextMatrix(lngThisRow, .Cols - 1) = lngResidueCount - lngResidueIndex + 1
+
+ ' Add the immonium ion to the second column
+ .TextMatrix(lngThisRow, 1) = CStrIfNonZero(objMwtWin.Peptide.ComputeImmoniumMass(dblResidueMass), "", 2)
+
+ ' Add the residue symbol
+ If blnUse3LetterSymbol Then
+ .TextMatrix(lngThisRow, lngSeqColIndex) = strSymbol & strModSymbolForThisResidue
+ Else
+ strSymbol1Letter = objMwtWin.GetAminoAcidSymbolConversion(strSymbol, False)
+ If Len(strSymbol1Letter) = 0 Then strSymbol1Letter = strSymbol
+ If strSymbol1Letter = "Xxx" Then strSymbol1Letter = "X"
+ .TextMatrix(lngThisRow, lngSeqColIndex) = strSymbol1Letter & strModSymbolForThisResidue
+ End If
+ End With
+
+ Next lngResidueIndex
+ grdFragMasses.Visible = True
+
+ ' Initialize FragSpectrumGridLocs()
+ ReDim FragSpectrumGridLocs(FragSpectrumIonCount)
+
+ ' Finally, step through FragSpectrumDetails and populate grdFragMasses with the ion masses
+ ' Shoulder ion masses are not displayed, but FragSpectrumGridLocs is updated with the associated primary ion
+ For lngIonIndex = 0 To FragSpectrumIonCount - 1
+ With FragSpectrumDetails(lngIonIndex)
+ ' Can start at column 2 since column 0 is # and column 1 is Immon.
+ ' Can stop at grdFragMasses.Cols - 2 since the final column is #
+
+ strSymbolGeneric = .SymbolGeneric
+ If .IsShoulderIon Then
+ strSymbolGeneric = Replace(strSymbolGeneric, SHOULDER_ION_PREFIX, "")
+ End If
+
+ For lngColIndex = 2 To grdFragMasses.Cols - 2
+ If grdFragMasses.TextMatrix(0, lngColIndex) = strSymbolGeneric Then
+ ' Add the mass of this ion to the appropriate row in this column
+ If .SourceResidueNumber < grdFragMasses.Rows Then
+ If Not .IsShoulderIon Then
+ ' Only display if not a Shoulder Ion
+ grdFragMasses.TextMatrix(.SourceResidueNumber, lngColIndex) = CStrIfNonZero(.Mass, "", 2)
+ End If
+
+ ' Update FragSpectrumGridLocs() with the Row Index and Column Index
+ FragSpectrumGridLocs(lngIonIndex).Row = .SourceResidueNumber
+ FragSpectrumGridLocs(lngIonIndex).Col = lngColIndex
+ Else
+ ' Invalid residue number; this is unexpected
+ Debug.Assert False
+ End If
+ End If
+ Next lngColIndex
+ End With
+ Next lngIonIndex
+
+ Exit Sub
+
+DisplayPredictedIonMassesErrorHandler:
+ GeneralErrorHandler "frmFragmentationModelling|DisplayPredictedIonMasses", Err.Number, Err.Description
+
+End Sub
+
+
+Private Sub EnableDisableControls()
+ Dim boolRemovePrecursorIon As Boolean
+
+ cboDoubleCharge.Enabled = cChkBox(chkDoubleCharge)
+ lblDoubleCharge.Enabled = cboDoubleCharge.Enabled
+
+ boolRemovePrecursorIon = cChkBox(chkRemovePrecursorIon)
+ lblPrecursorIonMass.Enabled = boolRemovePrecursorIon
+ txtPrecursorIonMass.Enabled = boolRemovePrecursorIon
+ lblPrecursorMassWindow.Enabled = boolRemovePrecursorIon
+ txtPrecursorMassWindow.Enabled = boolRemovePrecursorIon
+ lblDaltons(0).Enabled = boolRemovePrecursorIon
+ lblDaltons(1).Enabled = boolRemovePrecursorIon
+
+End Sub
+
+Private Sub InitializeDummyData(intDataType As Integer)
+ ' intDataType can be 0: continuous sine wave
+ ' 1: stick data (only 20 points)
+ ' 2: stick data (1000's of points, mostly zero, with a few spikes)
+
+ Dim ThisXYDataSet As usrXYDataSet
+ Dim lngIndex As Long, sngOffset As Single
+
+ Const PI = 3.14159265359
+ Const DegToRadiansMultiplier = PI / 180 / 10
+
+ Randomize Timer
+
+ Select Case intDataType
+ Case 1
+ With ThisXYDataSet
+ .XYDataListCount = 14
+ ReDim .XYDataList(.XYDataListCount)
+ .XYDataList(1).XVal = 154
+ .XYDataList(1).YVal = 79
+ .XYDataList(2).XVal = 154.51
+ .XYDataList(2).YVal = 25
+ .XYDataList(3).XVal = 154.95
+ .XYDataList(3).YVal = 15
+ .XYDataList(4).XVal = 280.2
+ .XYDataList(4).YVal = 60
+ .XYDataList(5).XVal = 281.15
+ .XYDataList(5).YVal = 20
+ .XYDataList(6).XVal = 282.201
+ .XYDataList(6).YVal = 10
+ .XYDataList(7).XVal = 312
+ .XYDataList(7).YVal = 23
+ .XYDataList(8).XVal = 312.332
+ .XYDataList(8).YVal = 5
+ .XYDataList(9).XVal = 312.661
+ .XYDataList(9).YVal = 2
+ .XYDataList(10).XVal = 500
+ .XYDataList(10).YVal = 10
+ .XYDataList(11).XVal = 589
+ .XYDataList(11).YVal = 102
+ .XYDataList(12).XVal = 589.247
+ .XYDataList(12).YVal = 72.3
+ .XYDataList(13).XVal = 589.523
+ .XYDataList(13).YVal = 50.7
+ .XYDataList(14).XVal = 589.78
+ .XYDataList(14).YVal = 30
+ End With
+ Case 2
+ With ThisXYDataSet
+ .XYDataListCount = 50000
+ ReDim .XYDataList(.XYDataListCount)
+ For lngIndex = 1 To .XYDataListCount
+ .XYDataList(lngIndex).XVal = 100 + lngIndex / 500
+ If lngIndex Mod 5000 = 0 Then
+ .XYDataList(lngIndex).YVal = Rnd(1) * .XYDataListCount / 200 * Rnd(1)
+ ElseIf lngIndex Mod 3000 = 0 Then
+ .XYDataList(lngIndex).YVal = Rnd(1) * .XYDataListCount / 650 * Rnd(1)
+ Else
+ .XYDataList(lngIndex).YVal = Rnd(1) * 3
+ End If
+ Next lngIndex
+ End With
+ Case Else
+ With ThisXYDataSet
+ .XYDataListCount = 360! * 100!
+
+ ReDim .XYDataList(.XYDataListCount)
+ sngOffset = 10
+ For lngIndex = 1 To .XYDataListCount
+ If lngIndex Mod 5050 = 0 Then
+ sngOffset = Rnd(1) + 10
+ End If
+ .XYDataList(lngIndex).XVal = CDbl(lngIndex) / 1000 - 5
+ .XYDataList(lngIndex).YVal = sngOffset - Abs((lngIndex - .XYDataListCount / 2)) / 10000 + Sin(DegToRadiansMultiplier * lngIndex) * Cos(DegToRadiansMultiplier * lngIndex / 2) * 1.29967878493163
+ Next lngIndex
+ End With
+ End Select
+
+ ' Fill Ion IonMatchList
+ InitializeIonMatchList ThisXYDataSet.XYDataListCount
+
+ With ThisXYDataSet
+ For lngIndex = 1 To .XYDataListCount
+ IonMatchList(lngIndex, ilaMass) = .XYDataList(lngIndex).XVal
+ IonMatchList(lngIndex, ilaIntensity) = .XYDataList(lngIndex).YVal
+ Next lngIndex
+ IonMatchListCount = .XYDataListCount
+ End With
+
+ UpdateIonMatchListWrapper
+
+End Sub
+
+Private Sub InitializeIonListGrid()
+
+ With grdIonList
+ .Clear
+ .Rows = 1
+ .Cols = ION_LIST_COL_COUNT
+ .TextMatrix(0, ilgMass) = LookupLanguageCaption(12550, "Mass")
+ .TextMatrix(0, ilgIntensity) = LookupLanguageCaption(12560, "Intensity")
+ .TextMatrix(0, ilgSymbolMatch) = LookupLanguageCaption(12570, "Symbol")
+
+ .ColWidth(ilgMass) = 900
+ .ColWidth(ilgIntensity) = 1000
+ .ColWidth(ilgSymbolMatch) = 1000
+ .ColAlignment(ilgMass) = flexAlignRightCenter
+ .ColAlignment(ilgIntensity) = flexAlignRightCenter
+ .ColAlignment(ilgSymbolMatch) = flexAlignCenterCenter
+ End With
+End Sub
+
+Private Function InitializeFragMassGrid(strColumnHeaders() As String, lngColCount As Long) As Long
+ ' Initializes grdFragMasses using the headers in strColumnHeaders() and the widths in lngColumnWidths()
+ ' Returns the column number that will hold the residue symbol (lngSeqColIndex)
+ ' this column is located just before the first y ion column
+
+ Dim lngColumnWidths() As Long
+ Dim lngColIndex As Long
+ Dim lngSeqColIndex As Long
+ Dim lngIonIndex As Long, lngIndexCompare As Long
+ Dim blnMatched As Boolean, blnSeqColumnAdded As Boolean
+
+ Dim strYIonSymbol As String
+ Dim strColumnHeadersToAdd() As String
+ Dim lngColHeadersToAddCount As Long
+ Dim lngColHeadersToAddDimCount As Long
+
+On Error GoTo InitializeFragMassGridErrorHandler
+
+ lngColHeadersToAddCount = 0
+ lngColHeadersToAddDimCount = 10
+ ReDim strColumnHeadersToAdd(lngColHeadersToAddDimCount)
+
+ ' Examine FragSpectrumDetails().Symbol to make a list of the possible ion types present
+ For lngIonIndex = 0 To FragSpectrumIonCount - 1
+ With FragSpectrumDetails(lngIonIndex)
+ If Not .IsShoulderIon Then
+ blnMatched = False
+ For lngIndexCompare = 0 To lngColHeadersToAddCount - 1
+ If strColumnHeadersToAdd(lngIndexCompare) = .SymbolGeneric Then
+ blnMatched = True
+ Exit For
+ End If
+ Next lngIndexCompare
+
+ If Not blnMatched Then
+ strColumnHeadersToAdd(lngColHeadersToAddCount) = .SymbolGeneric
+
+ ' Increment lngColHeadersToAddCount and reserve more memory if needed
+ lngColHeadersToAddCount = lngColHeadersToAddCount + 1
+ If lngColHeadersToAddCount >= lngColHeadersToAddDimCount Then
+ lngColHeadersToAddDimCount = lngColHeadersToAddDimCount + 10
+ ReDim Preserve strColumnHeadersToAdd(lngColHeadersToAddDimCount)
+ End If
+ End If
+ End If
+ End With
+ Next lngIonIndex
+
+ ' There are at a minimum 4 columns (#, Immon., Seq., and #)
+ ' We'll start with # and Immon.
+ ReDim strColumnHeaders(4 + lngColHeadersToAddCount)
+ ReDim lngColumnWidths(4 + lngColHeadersToAddCount)
+
+ lngColCount = 2
+ strColumnHeaders(0) = LookupLanguageCaption(12500, "#")
+ strColumnHeaders(1) = LookupLanguageCaption(12510, "Immon.")
+
+ lngColumnWidths(0) = 400
+ lngColumnWidths(1) = 700
+
+ strYIonSymbol = objMwtWin.Peptide.LookupIonTypeString(itYIon)
+
+ If lngColHeadersToAddCount > 0 Then
+ ' Sort strColumnHeadersToAdd() alphabetically (a, b, then y)
+ ShellSortString strColumnHeadersToAdd(), 0, lngColHeadersToAddCount - 1
+
+ ' Append the items in strColumnHeadersToAdd() to strColumnHeaders
+ For lngColIndex = 0 To lngColHeadersToAddCount - 1
+ If lngColIndex < lngColHeadersToAddCount And Not blnSeqColumnAdded Then
+ ' Check if this column is the first y-ion column
+ If Left(strColumnHeadersToAdd(lngColIndex), 1) = strYIonSymbol Then
+ strColumnHeaders(lngColCount) = LookupLanguageCaption(12520, "Seq.")
+ lngSeqColIndex = lngColCount
+ lngColCount = lngColCount + 1
+ blnSeqColumnAdded = True
+ End If
+ End If
+
+ strColumnHeaders(lngColCount) = strColumnHeadersToAdd(lngColIndex)
+ lngColumnWidths(lngColCount) = 800
+ lngColCount = lngColCount + 1
+
+ Next lngColIndex
+
+ End If
+
+ ' If the sequence column still wasn't added, then add it now
+ If Not blnSeqColumnAdded Then
+ strColumnHeaders(lngColCount) = LookupLanguageCaption(12520, "Seq.")
+ lngSeqColIndex = lngColCount
+ lngColCount = lngColCount + 1
+ End If
+ lngColumnWidths(lngSeqColIndex) = 600
+
+ ' The final column is a duplicate of the zeroth column
+ strColumnHeaders(lngColCount) = strColumnHeaders(0)
+ lngColumnWidths(lngColCount) = lngColumnWidths(0)
+ lngColCount = lngColCount + 1
+
+ ' Now populate the grid
+ With grdFragMasses
+ .Clear
+ .Rows = 1
+ .Cols = lngColCount
+
+ For lngColIndex = 0 To lngColCount - 1
+ .TextMatrix(0, lngColIndex) = strColumnHeaders(lngColIndex)
+ .ColWidth(lngColIndex) = lngColumnWidths(lngColIndex)
+ .ColAlignment(lngColIndex) = flexAlignCenterCenter
+ Next lngColIndex
+
+ End With
+
+ InitializeFragMassGrid = lngSeqColIndex
+ Exit Function
+
+InitializeFragMassGridErrorHandler:
+ GeneralErrorHandler "frmFragmentationModelling|InitializeFragMassGrid", Err.Number, Err.Description
+
+End Function
+
+Private Sub InitializeIonMatchList(ByVal lngNumberPoints As Long)
+ ' Redimension array (erasing old values) using size lngNumberPoints
+
+ IonMatchListCount = 0
+ ReDim IonMatchList(lngNumberPoints, 0 To ION_LIST_ARRAY_MAXINDEX_2D) ' 1-based array in the first dimension, uses columns 0, 1, and 2 in the 2nd dimension
+
+ UpdateIonLoadStats True
+
+End Sub
+
+Private Sub FillIonMatchGridWrapper()
+ If BinnedDataCount > 0 Then
+ FillIonMatchGrid BinnedData(), BinnedDataCount
+ Else
+ FillIonMatchGrid IonMatchList(), IonMatchListCount
+ End If
+End Sub
+
+Private Sub FillIonMatchGrid(ThisIonList() As Double, ThisIonListCount As Long)
+ ' ThisIonList is a 2D array, 1-based in the first dimension but uses columns 0, 1, and 2
+ ' Column 0 is the mass, column 1 the raw intensity, column 2 is the normalized intensity (or -1 if not used)
+
+ Dim lngIndex As Long, lngValuesToPopulate As Long, dblAlignmentValue As Double
+
+ InitializeIonListGrid
+
+ lngValuesToPopulate = 0
+ For lngIndex = 1 To ThisIonListCount
+ If ThisIonList(lngIndex, ilaNormalizedIntensity) >= 0 Then
+ lngValuesToPopulate = lngValuesToPopulate + 1
+ End If
+ Next lngIndex
+
+ ' The Alignment Value is added to the masses of all ions
+ dblAlignmentValue = CDblSafe(txtAlignment)
+
+ With grdIonList
+ .Rows = lngValuesToPopulate + 1
+ lngValuesToPopulate = 0
+ For lngIndex = 1 To ThisIonListCount
+ If ThisIonList(lngIndex, ilaNormalizedIntensity) >= 0 Then
+ lngValuesToPopulate = lngValuesToPopulate + 1
+ .TextMatrix(lngValuesToPopulate, ilgMass) = Format(ThisIonList(lngIndex, ilaMass) + dblAlignmentValue, "#0.00")
+ .TextMatrix(lngValuesToPopulate, ilgIntensity) = Format(ThisIonList(lngIndex, ilaNormalizedIntensity), "#0.00")
+ .TextMatrix(lngValuesToPopulate, ilgSymbolMatch) = ""
+ End If
+ Next lngIndex
+ End With
+End Sub
+
+Private Sub FindMassLimits(ThisIonMatchList() As Double, ThisIonMatchListCount As Long, dblMassMinimum As Double, dblMassMaximum As Double)
+ Dim lngIndex As Long, dblMassValue As Double
+
+ ' Determine the smallest and largest ion mass (m/z)
+ dblMassMinimum = HighestValueForDoubleDataType
+ dblMassMaximum = LowestValueForDoubleDataType
+ For lngIndex = 1 To ThisIonMatchListCount
+ dblMassValue = ThisIonMatchList(lngIndex, ilaMass)
+ If dblMassValue > dblMassMaximum Then dblMassMaximum = dblMassValue
+ If dblMassValue < dblMassMinimum Then dblMassMinimum = dblMassValue
+ Next lngIndex
+
+End Sub
+
+Private Sub FlexGridKeyPressHandler(frmThisForm As VB.Form, grdThisGrid As MSFlexGrid, KeyCode As Integer, Shift As Integer, Optional lngMaxColumnToSelect As Long = -1)
+ If KeyCode = vbKeyC And (Shift And vbCtrlMask) Then
+ ' Ctrl+C
+ FlexGridCopyInfo frmThisForm, grdThisGrid, gcmText
+ ElseIf KeyCode = vbKeyA And (Shift And vbCtrlMask) Then
+ ' Ctrl+A
+ FlexGridSelectEntireGrid grdThisGrid, lngMaxColumnToSelect
+ End If
+End Sub
+
+Private Sub FlexGridRemoveHighlighting(grdThisGrid As MSFlexGrid, lngStartCol As Long, lngEndCol As Long)
+ Dim lngRow As Long, lngCol As Long
+
+ With grdThisGrid
+ For lngRow = 1 To .Rows - 1
+ .Row = lngRow
+ For lngCol = lngStartCol To lngEndCol
+ .Col = lngCol
+ .CellBackColor = 0
+ Next lngCol
+ Next lngRow
+ End With
+End Sub
+
+Private Sub FlexGridSelectEntireGrid(grdThisGrid As MSFlexGrid, Optional lngMaxColumnToSelect As Long = -1)
+ ' Select entire grid
+ With grdThisGrid
+ If .Rows > 1 Then
+ .Row = 1
+ .Col = 0
+ .RowSel = .Rows - 1
+ If lngMaxColumnToSelect = -1 Then lngMaxColumnToSelect = .Cols - 1
+
+ If lngMaxColumnToSelect >= 0 And lngMaxColumnToSelect < .Cols Then
+ .ColSel = lngMaxColumnToSelect
+ Else
+ If .Cols > 1 Then
+ .ColSel = 1
+ Else
+ .ColSel = 0
+ End If
+ End If
+ End If
+ End With
+
+End Sub
+
+Private Function Get3LetterCodeState() As Boolean
+ ' Returns true if the user wants 3 letter sequence residue symbols
+
+ If cboNotation.ListIndex = 0 Then
+ Get3LetterCodeState = False
+ Else
+ Get3LetterCodeState = True
+ End If
+
+End Function
+
+Private Function GetCTerminusState() As ctgCTerminusGroupConstants
+ Dim lngListIndex As Long
+
+ lngListIndex = cboCTerminus.ListIndex
+
+ If lngListIndex >= ctgHydroxyl And lngListIndex <= ctgNone Then
+ GetCTerminusState = lngListIndex
+ Else
+ GetCTerminusState = ctgNone
+ End If
+
+End Function
+
+Public Function GetIonMatchList(ByRef ThisIonMatchList() As Double, ByRef strIonMatchListCaption As String) As Long
+ ' Returns the IonMatchList() since it is a private variable
+
+ Dim lngRow As Long, lngCol As Long
+
+ ReDim ThisIonMatchList(IonMatchListCount, 3)
+
+ ' IonMatchList() is 1 based in the first dimension and 0-based in the second, using columns 0, 1, and 2
+ For lngRow = 1 To IonMatchListCount
+ For lngCol = 0 To 2
+ ThisIonMatchList(lngRow, lngCol) = IonMatchList(lngRow, lngCol)
+ Next lngCol
+ Next lngRow
+
+ strIonMatchListCaption = mIonMatchListDetails.Caption
+
+ GetIonMatchList = IonMatchListCount
+End Function
+
+
+Private Function GetNTerminusState() As ntgNTerminusGroupConstants
+ Dim lngListIndex As Long
+
+ lngListIndex = cboNTerminus.ListIndex
+
+ If lngListIndex >= ntgHydrogen And lngListIndex <= ntgNone Then
+ GetNTerminusState = lngListIndex
+ Else
+ GetNTerminusState = ctgNone
+ End If
+
+End Function
+
+Private Sub IonMatchListClear()
+ InitializeIonMatchList 0
+ InitializeIonListGrid
+End Sub
+
+Public Sub LoadCWSpectrumOptions(strSequenceFilePath As String)
+ objSpectrum.LoadDataFromDisk strSequenceFilePath, False, True
+End Sub
+
+Public Function LoadIonListToMatch(Optional SeqFileNum As Integer = 0, Optional IonMatchListCountInFile As Long) As Boolean
+ ' Loads Fragmentation Modelling sequence info from a file
+
+ ' If SeqFileNum is not given (and thus 0), the user is prompted for the file from which to read the ion list
+ ' Otherwise, a .Seq file is already open and the ion list in the file needs to be read
+ '
+ ' Returns true if a file is selected and one or more ions are read
+
+ ' Can also read data from a .Dta file, in which case the parent ion will be properly recorded
+ ' Finally, if the user chooses a _Dta.Txt file, then frmDtaTxtFileBrowser is called
+
+ Static intFilterIndexSaved As Integer
+ Dim strIonListFilename As String, strMessage As String
+ Dim strLineIn As String, lngValuesToPopulate As Long
+ Dim blnAllowCommaDelimeter As Boolean
+ Dim IonListFileNum As Integer, lngPointsLoaded As Long
+ Dim dblMinMass As Double, dblMaxMass As Double
+ Dim lngCharLoc As Long
+ Dim blnLoadingDTAFile As Boolean
+ Dim blnSkippedParentIon As Boolean
+ Dim strFilter As String
+
+ If SeqFileNum = 0 Then
+ ' Display the File Open dialog box.
+
+ ' 1500 = All Files
+ ' 1540 = Ion List Files, 1545 = .txt
+ strFilter = LookupMessage(1540) & " (*." & LookupMessage(1545) & ")|*." & LookupMessage(1545) & "|DTA Files (*.dta)|*.dta|" & "Concatenated DTA files (*dta.txt)|*dta.txt|" & LookupMessage(1500) & " (*.*)|*.*"
+ If intFilterIndexSaved = 0 Then intFilterIndexSaved = 1
+ strIonListFilename = SelectFile(frmFragmentationModelling.hwnd, "Select File", gLastFileOpenSaveFolder, False, "", strFilter, intFilterIndexSaved)
+ If Len(strIonListFilename) = 0 Then
+ ' No file selected (or other error)
+ LoadIonListToMatch = True
+ Exit Function
+ End If
+ Else
+ If IonMatchListCountInFile < 1 Then
+ LoadIonListToMatch = False
+ Exit Function
+ End If
+ End If
+
+ If LCase(Right(strIonListFilename, 8)) = "_dta.txt" Then
+ ' User chose a concatenated _dta.txt file, call frmDtaTxtFileBrowser instead
+ ' This filetype is specific to PNNL and the Smith group
+ frmDtaTxtFileBrowser.ReadDtaTxtFile strIonListFilename
+ SetDtaTxtFileBrowserMenuVisibility frmDtaTxtFileBrowser.GetDataInitializedState()
+ LoadIonListToMatch = True
+ Exit Function
+ End If
+
+ On Error GoTo LoadIonListProblem
+
+ ' Determine if commas are used for the decimal point in this locale
+ If DetermineDecimalPoint() = "," Then
+ blnAllowCommaDelimeter = False
+ Else
+ blnAllowCommaDelimeter = True
+ End If
+
+ If SeqFileNum = 0 Then
+ ' Length of the progress bar is an estimate
+ frmProgress.InitializeForm LookupMessage(930), 0, 4
+ frmProgress.ToggleAlwaysOnTop True
+
+ ' Open the file for input
+ IonListFileNum = FreeFile()
+ Open strIonListFilename For Input As #IonListFileNum
+
+ ' First Determine number of data points in file
+ ' Necessary since the IonMatchList() array is multi-dimensional and cannot be redimensioned without erasing old values
+ lngValuesToPopulate = 0
+ Do While Not EOF(IonListFileNum)
+ Line Input #IonListFileNum, strLineIn
+
+ If Len(strLineIn) > 0 Then
+ lngValuesToPopulate = lngValuesToPopulate + 1
+ End If
+ Loop
+ Close #IonListFileNum
+
+ frmProgress.InitializeForm LookupMessage(930), 0, lngValuesToPopulate
+ Else
+ lngValuesToPopulate = IonMatchListCountInFile
+ End If
+
+ ' Initialize the IonMatchList() Array
+ InitializeIonMatchList lngValuesToPopulate
+ lngPointsLoaded = 0
+
+ dblMaxMass = LowestValueForDoubleDataType
+ dblMinMass = HighestValueForDoubleDataType
+
+ If SeqFileNum = 0 Then
+ ' Now re-open the file and import the data
+ IonListFileNum = FreeFile
+ Open strIonListFilename For Input As #IonListFileNum
+
+ If LCase(Right(strIonListFilename, 4)) = ".dta" Then
+ ' User chose a .Dta file
+ ' Need to set the following to True
+ blnLoadingDTAFile = True
+ End If
+ Else
+ IonListFileNum = SeqFileNum
+ End If
+
+ Do While Not EOF(IonListFileNum)
+ If lngPointsLoaded Mod 250 = 0 And SeqFileNum = 0 Then
+ frmProgress.UpdateProgressBar lngPointsLoaded
+ If KeyPressAbortProcess > 1 Then Exit Do
+ End If
+
+ Line Input #IonListFileNum, strLineIn
+ strLineIn = Trim(strLineIn)
+
+ If blnLoadingDTAFile And Not blnSkippedParentIon Then
+ If Len(strLineIn) > 0 Then
+ If IsNumeric(Left(strLineIn, 1)) Then
+ ' Skip the first set of data since it is the parent ion (MH) and charge
+ lngCharLoc = InStr(strLineIn, " ")
+ If lngCharLoc > 0 Then
+ strLineIn = Left(strLineIn, lngCharLoc - 1)
+ txtPrecursorIonMass = strLineIn
+ End If
+ blnSkippedParentIon = True
+ strLineIn = ""
+ End If
+ End If
+ End If
+
+ If Len(strLineIn) > 0 Then
+ If UCase(Left(strLineIn, 4)) = "FRAG" Then Exit Do
+ AddIonPairToIonList strLineIn, lngPointsLoaded, blnAllowCommaDelimeter, dblMinMass, dblMaxMass
+ End If
+ Loop
+
+ If SeqFileNum = 0 Then Close #IonListFileNum
+
+ If KeyPressAbortProcess = 0 And lngPointsLoaded > 0 Then
+ LoadIonListToMatch = True
+
+ If Abs((dblMaxMass - dblMinMass) / lngPointsLoaded) < ION_SEPARATION_TOLERANCE_TO_AUTO_ENABLE_BINNING Then
+ ' Average spacing between ions is less than 0.2 Da, turn on binning
+ frmIonMatchOptions.chkGroupSimilarIons.value = vbChecked
+ frmIonMatchOptions.txtGroupIonMassWindow.Text = "0.2"
+ End If
+
+ ' Reset the alignment offset
+ txtAlignment = "0"
+ Else
+ If SeqFileNum = 0 And lngPointsLoaded > 0 Then
+ MsgBox LookupMessage(940), vbInformation + vbOKOnly, LookupMessage(945)
+ End If
+ LoadIonListToMatch = False
+ End If
+
+ If SeqFileNum = 0 Then frmProgress.HideForm
+
+ Exit Function
+
+LoadIonListProblem:
+ If SeqFileNum = 0 Then Close
+ strMessage = LookupMessage(900) & ": " & strIonListFilename
+ strMessage = strMessage & vbCrLf & Err.Description
+ MsgBox strMessage, vbOKOnly + vbExclamation, LookupMessage(350)
+
+End Function
+
+Private Function MassToBinNumber(ThisMass As Double, StartMass As Double, MassResolution As Double) As Long
+ Dim WorkingMass As Double
+
+ ' First subtract StartMass from ThisMass
+ ' For example, if StartMass is 500 and ThisMass is 500.28, then WorkingMass = 0.28
+ ' Or, if StartMass is 500 and ThisMass is 530.83, then WorkingMass = 30.83
+ WorkingMass = ThisMass - StartMass
+
+ ' Now, dividing WorkingMass by MassResolution and rounding to nearest integer
+ ' actually gives the bin
+ ' For example, given WorkingMass = 0.28 and MassResolution = 0.1, Bin = CLng(2.8) + 1 = 4
+ ' Or, given WorkingMass = 30.83 and MassResolution = 0.1, Bin = CLng(308.3) + 1 = 309
+ MassToBinNumber = CLng(WorkingMass / MassResolution) + 1
+
+End Function
+
+Private Sub MatchIons()
+ ' For each of the ions in FragSpectrumDetails(), look in IonMatchList() to see
+ ' if any of the ions is within tolerance
+ ' If it is, change the background color of the corresponding cell in grdFragMasses accordingly
+
+ Dim lngIonIndex As Long, lngResidueIndex As Long
+ Dim lngRowIndex As Long
+ Dim eIonType As itIonTypeConstants
+ Dim intChargeIndex As Integer
+ Dim lngCellBackColor As Long
+ Dim dblMatchTolerance As Double
+ Dim dblFragmentMass As Double
+ Dim lngIndexInIonListGrid As Long
+
+ Dim udtResidueMatched() As udtResidueMatchedType
+ Dim lngResidueCount As Long
+
+ ' Variables for computing match score
+ Dim dblScore As Double
+ Dim lngMatchCount As Long ' Number of ions in user data matching a predicted ion
+ Dim dblIntensitySum As Double ' Sum of the intensities for all matching ions (normalized intensity in user data)
+ Dim dblBeta As Double ' Incremented by 0.075 for each successive b ion and also each successive y ion
+ Dim dblRho As Double ' Adjustment for presence of standard immonium ions:
+ ' Looks for 110, 120, and 136 m/z in user data (His, Phe, and Tyr immonium ions)
+ ' If m/z is present, examines sequence being matched. If corresponding amino acid is present,
+ ' increments rho by 0.15. If amino acid is absent, decrements rho by 0.15. No change if m/z is not found in user data
+
+
+ If grdIonList.Rows <= 1 Or FragSpectrumIonCount < 1 Then Exit Sub
+
+ If Not mFragMatchSettingsChanged Then Exit Sub
+
+ mFragMatchSettingsChanged = False
+
+ If Not (grdIonList.Visible Or mAutoAligning) Then Exit Sub
+
+ dblMatchTolerance = Val(txtIonMatchingWindow)
+ If dblMatchTolerance < 0 Or dblMatchTolerance > 100 Then
+ dblMatchTolerance = 0.5
+ End If
+
+ If Not mAutoAligning Then Me.MousePointer = vbHourglass
+
+ ' Initialize variables used to compute score
+ lngMatchCount = 0
+ dblIntensitySum = 0
+ dblBeta = 0
+ dblRho = 0
+
+ ' Initialize udtResidueMatched()
+ lngResidueCount = objMwtWin.Peptide.GetResidueCount
+ ReDim udtResidueMatched(lngResidueCount)
+
+ ' Hide grdFragMasses and grdIonList to prevent screen updates
+ ' from slowing down the computer during matching
+ grdFragMasses.Visible = False
+ grdIonList.Visible = False
+
+ ' Remove all background coloring from grdIonList
+ FlexGridRemoveHighlighting grdIonList, 0, ION_LIST_COL_COUNT - 1
+
+ ' Clear the ilgSymbolMatch column in grdIonList
+ With grdIonList
+ For lngRowIndex = 1 To .Rows - 1
+ .TextMatrix(lngRowIndex, ilgSymbolMatch) = ""
+ Next lngRowIndex
+ End With
+
+ lngMatchCount = 0
+ For lngIonIndex = 0 To FragSpectrumIonCount - 1
+ With FragSpectrumDetails(lngIonIndex)
+ If .Mass > 0 Then
+ lngIndexInIonListGrid = SearchForIonInIonListGrid(.Mass, dblMatchTolerance)
+
+ If lngIndexInIonListGrid >= 0 Then
+ lngMatchCount = lngMatchCount + 1
+
+ grdFragMasses.Row = FragSpectrumGridLocs(lngIonIndex).Row
+ grdFragMasses.Col = FragSpectrumGridLocs(lngIonIndex).Col
+ If .IsShoulderIon Then
+ lngCellBackColor = &H80FFFF ' Light Yellow
+
+ ' Only change to yellow if currently white
+ If grdFragMasses.CellBackColor = 0 Then
+ grdFragMasses.CellBackColor = lngCellBackColor
+ End If
+ Else
+ lngCellBackColor = vbCyan
+ grdFragMasses.CellBackColor = lngCellBackColor
+ End If
+
+ dblIntensitySum = dblIntensitySum + Abs(.Intensity)
+
+ ' Display the symbol of the match in the ilgSymbolMatch column
+ grdIonList.TextMatrix(lngIndexInIonListGrid, ilgSymbolMatch) = .Symbol
+
+ ' Also, color the corresponding row in grdIonList
+ ' Fill in order of 2, 1, 0 so cursor ends up in 0'th column
+ grdIonList.Row = lngIndexInIonListGrid
+ grdIonList.Col = ilgSymbolMatch: grdIonList.CellBackColor = lngCellBackColor
+ grdIonList.Col = ilgIntensity: grdIonList.CellBackColor = lngCellBackColor
+ grdIonList.Col = ilgMass: grdIonList.CellBackColor = lngCellBackColor
+
+ ' Lastly, update udtResidueMatched()
+ udtResidueMatched(.SourceResidueNumber).IonHit(.IonType, .Charge) = True
+ End If
+
+ End If
+ End With
+ Next lngIonIndex
+
+ ' Now examine udtResidueMatched() to determine dblBeta
+ ' Beta is incremented by 0.075 for each successive b, b++, y, or y++ ion
+ For eIonType = itBIon To itYIon
+ For intChargeIndex = 1 To 2
+ For lngResidueIndex = 0 To lngResidueCount - 2
+ If udtResidueMatched(lngResidueIndex).IonHit(eIonType, intChargeIndex) Then
+ If udtResidueMatched(lngResidueIndex + 1).IonHit(eIonType, intChargeIndex) Then
+ dblBeta = dblBeta + 0.075
+ End If
+ End If
+ Next lngResidueIndex
+ Next intChargeIndex
+ Next eIonType
+
+ ' Finally, examine grdIonList to look for important immonium ions, adjusting rho as needed
+
+ ' Look for Histidine (110)
+ dblFragmentMass = dblHistidineFW - dblImmoniumMassDifference
+ If Not WithinTolerance(110, dblFragmentMass, 2) Then dblFragmentMass = 110
+ MatchIonAdjustRho dblRho, dblFragmentMass, dblMatchTolerance, "His"
+
+ ' Look for Phenylalanine (120)
+ dblFragmentMass = dblPhenylalanineFW - dblImmoniumMassDifference
+ If Not WithinTolerance(120, dblFragmentMass, 2) Then dblFragmentMass = 120
+ MatchIonAdjustRho dblRho, dblFragmentMass, dblMatchTolerance, "Phe"
+
+ ' Look for Tyrosine (136)
+ dblFragmentMass = dblTyrosineFW - dblImmoniumMassDifference
+ If Not WithinTolerance(136, dblFragmentMass, 2) Then dblFragmentMass = 136
+ MatchIonAdjustRho dblRho, dblFragmentMass, dblMatchTolerance, "Tyr"
+
+ ' Compute the score
+ If FragSpectrumIonCount > 0 Then
+ ' Compute Match Score
+ ' ToDo: whether 1 - dblRho or 1 + dblRho is correct
+ dblScore = dblIntensitySum * lngMatchCount * (1 + dblBeta) * (1 + dblRho) / FragSpectrumIonCount
+ Else
+ dblScore = 0
+ End If
+
+ If Not mAutoAligning Then
+ grdFragMasses.Visible = True
+ grdIonList.Visible = True
+
+ UpdateMatchCountAndScoreWork lngMatchCount, dblScore
+ Else
+ lngAlignmentMatchCount = lngMatchCount
+ dblAlignmentScore = dblScore
+ End If
+
+ If Not mAutoAligning Then Me.MousePointer = vbDefault
+
+End Sub
+
+Private Function MatchIonAdjustRho(ByRef dblRho As Double, dblFragmentMass As Double, dblMatchTolerance As Double, strResidue3LetterSymbol As String) As Long
+ ' Returns -1 if no match
+ ' Otherwise, returns the row index of the match in grdIonList
+
+ Dim lngIndexInIonListGrid As Long
+ Dim lngResidueIndex As Long
+
+ lngIndexInIonListGrid = SearchForIonInIonListGrid(dblFragmentMass, dblMatchTolerance)
+
+ ' Only adjust rho if intensity of ion in grdIonList is greater than 40% of the
+ ' maximum intensity used for normalizing
+
+ If lngIndexInIonListGrid >= 0 Then
+
+ If Val(grdIonList.TextMatrix(lngIndexInIonListGrid, ilgIntensity)) >= 0.4 * Val(frmIonMatchOptions.txtNormalizedIntensity) Then
+
+ ' See if residue exists in target sequence
+ If objMwtWin.Peptide.GetResidueCountSpecificResidue(strResidue3LetterSymbol, True) > 0 Then
+ ' Immonium mass found and residue is present in sequence
+ ' Increase Rho by 0.15
+ dblRho = dblRho + 0.15
+
+ For lngResidueIndex = 1 To objMwtWin.Peptide.GetResidueCount
+ If objMwtWin.Peptide.GetResidueSymbolOnly(lngResidueIndex) = strResidue3LetterSymbol Then
+ ' Color given cell in grdFragMasses
+ With grdFragMasses
+ .Row = lngResidueIndex
+ .Col = 1
+ .CellBackColor = vbCyan
+ End With
+ End If
+ Next lngResidueIndex
+
+ ' Also color cell in grdIonList
+ With grdIonList
+ .Row = lngIndexInIonListGrid
+ .Col = ilgSymbolMatch
+ .CellBackColor = vbCyan
+ .Col = ilgIntensity
+ .CellBackColor = vbCyan
+ .Col = ilgMass
+ .CellBackColor = vbCyan
+
+ End With
+ Else
+ ' Immonium mass found, but residue was not present in sequence
+ ' Decrease Rho by 0.15
+ dblRho = dblRho - 0.15
+
+ ' Color cell in grdIonList red
+ With grdIonList
+ .Row = lngIndexInIonListGrid
+ .Col = ilgSymbolMatch
+ .CellBackColor = &HC0C0FF ' Light Red
+ .Col = ilgIntensity
+ .CellBackColor = &HC0C0FF ' Light Red
+ .Col = ilgMass
+ .CellBackColor = &HC0C0FF ' Light Red
+ End With
+
+ ' Set lngIndexInIonListGrid to -1
+ lngIndexInIonListGrid = -1
+ End If
+ Else
+ lngIndexInIonListGrid = -1
+ End If
+ End If
+End Function
+
+Private Sub NormalizeIonMatchListWrapper()
+ Dim dblOriginalMaximumIntensity As Double
+
+ If BinnedDataCount > 0 Then
+ NormalizeIonMatchList BinnedData(), BinnedDataCount, dblOriginalMaximumIntensity
+ Else
+ NormalizeIonMatchList IonMatchList(), IonMatchListCount, dblOriginalMaximumIntensity
+ mIonMatchListDetails.OriginalMaximumIntensity = dblOriginalMaximumIntensity
+ End If
+End Sub
+
+Private Sub NormalizeIonMatchList(ThisIonList() As Double, ThisIonListCount As Long, ByRef dblOriginalMaximumIntensity As Double)
+ Dim lngIndex As Long, lngRegionIndex As Long
+ Dim lngStopIndex As Long
+ Dim lngIonPointerArray() As Long, lngPointerArrayCount As Long
+ Dim dblMassRegionIndices() As Double ' 2D Array (1-based in the 1st dimension and 0-based in the second)
+ ' First dimension is mass value of window edge, 2nd dimension is index in ThisIonList() that starts this window
+ Dim intMassRegionCount As Integer, intMassRegionTrack As Integer
+ Dim lngTopMostValuesToUse As Long
+ Dim dblMassValue As Double
+ Dim dblMassMinimum As Double, dblMassMaximum As Double
+ Dim dblMassRegionWidth As Double
+ Dim dblMaximumIntensity As Double
+ Dim dblNormalizedIntensity As Double
+ Dim boolRemovePrecursorIon As Boolean
+ Dim dblPrecursorIonMass As Double, dblPrecursorIonMassWindow As Double
+ Dim boolPrecursorRemoved As Boolean
+ Dim blnShowProgress As Boolean
+
+ If ThisIonListCount > 3000 Then blnShowProgress = True
+ dblOriginalMaximumIntensity = 0
+ If ThisIonListCount = 0 Then Exit Sub
+
+ If blnShowProgress Then
+ frmProgress.InitializeForm LookupMessage(950), 0, 4
+ frmProgress.ToggleAlwaysOnTop True
+ End If
+
+ ' Fill tolerance variables
+ If IsNumeric(txtPrecursorIonMass) Then
+ dblPrecursorIonMass = Val(txtPrecursorIonMass)
+ Else
+ dblPrecursorIonMass = 0
+ End If
+
+ boolRemovePrecursorIon = cChkBox(chkRemovePrecursorIon)
+ dblPrecursorIonMassWindow = txtPrecursorMassWindow
+ If dblPrecursorIonMassWindow < 0 Or dblPrecursorIonMassWindow > 100 Then
+ dblPrecursorIonMassWindow = 2
+ End If
+
+ With frmIonMatchOptions
+
+ intMassRegionCount = .txtMassRegions
+ If intMassRegionCount < 1 Or intMassRegionCount > 1000 Then
+ intMassRegionCount = 1
+ End If
+
+ lngTopMostValuesToUse = .txtIonCountToUse
+ If lngTopMostValuesToUse < 10 Or lngTopMostValuesToUse > 32000 Then
+ lngTopMostValuesToUse = 200
+ End If
+
+ dblNormalizedIntensity = .txtNormalizedIntensity
+ If dblNormalizedIntensity < 1 Or dblNormalizedIntensity > 32000 Then
+ dblNormalizedIntensity = 100
+ End If
+ End With
+
+ ' Initialize the Pointer Array
+ lngPointerArrayCount = ThisIonListCount
+ ReDim lngIonPointerArray(lngPointerArrayCount)
+ For lngIndex = 1 To lngPointerArrayCount
+ lngIonPointerArray(lngIndex) = lngIndex
+ Next lngIndex
+
+ ' Find the Mass Limits
+ FindMassLimits ThisIonList(), ThisIonListCount, dblMassMinimum, dblMassMaximum
+
+ ' Initialize dblMassRegionIndices()
+ ReDim dblMassRegionIndices(intMassRegionCount + 1, 2)
+ dblMassRegionWidth = (dblMassMaximum - dblMassMinimum) / intMassRegionCount
+
+ For lngIndex = 1 To intMassRegionCount
+ dblMassRegionIndices(lngIndex, 0) = dblMassMinimum + (lngIndex - 1) * dblMassRegionWidth
+ Next lngIndex
+
+ dblMassRegionIndices(1, 1) = 1
+ intMassRegionTrack = 2
+ dblMassRegionIndices(intMassRegionCount + 1, 0) = ThisIonList(ThisIonListCount, 0)
+ dblMassRegionIndices(intMassRegionCount + 1, 1) = ThisIonListCount
+
+ ' Initialize the 3rd column of ThisIonList() by setting to the actual intensity
+ ' unless within tolerance from the PrecursorIonMass, in which case the intensity is set to -1
+ ' At the same time, determine the index of the start of each mass region
+ dblMassMinimum = HighestValueForDoubleDataType
+ dblMassMaximum = LowestValueForDoubleDataType
+ For lngIndex = 1 To ThisIonListCount
+ dblMassValue = ThisIonList(lngIndex, ilaMass)
+ ThisIonList(lngIndex, ilaNormalizedIntensity) = ThisIonList(lngIndex, ilaIntensity)
+ If dblPrecursorIonMass > 0 And boolRemovePrecursorIon Then
+ If WithinTolerance(dblMassValue, dblPrecursorIonMass, dblPrecursorIonMassWindow) Then
+ ThisIonList(lngIndex, ilaNormalizedIntensity) = -1
+ boolPrecursorRemoved = True
+ End If
+ End If
+
+ If intMassRegionTrack <= intMassRegionCount Then
+ If dblMassValue >= dblMassRegionIndices(intMassRegionTrack, 0) Then
+ dblMassRegionIndices(intMassRegionTrack, 1) = lngIndex
+ intMassRegionTrack = intMassRegionTrack + 1
+ End If
+ End If
+ Next lngIndex
+
+ ' Update lblPrecursorStatus
+ If boolPrecursorRemoved Then
+ lblPrecursorStatus.Caption = LookupLanguageCaption(12390, "Precursor removed") & ": " & Trim(CStr(Round(dblPrecursorIonMass, 0))) & "±" & Format(dblPrecursorIonMassWindow, "0.0")
+ Else
+ If boolRemovePrecursorIon Then
+ lblPrecursorStatus.Caption = LookupLanguageCaption(12385, "Precursor not found")
+ Else
+ lblPrecursorStatus.Caption = LookupLanguageCaption(12395, "Precursor not removed")
+ End If
+ End If
+
+ lngPointerArrayCount = ThisIonListCount
+
+ ' Next, sort the ions by intensity (descending)
+ ShellSortIonList ThisIonList(), lngIonPointerArray(), 1, lngPointerArrayCount, ilaNormalizedIntensity, blnShowProgress
+
+ ' Next, set the intensities of ions below the top-most ion count to -1 (so that they'll be ignored
+ ' If lngTopMostValuesToUse > lngPointerArrayCount then nothing is set to -1
+ For lngIndex = lngTopMostValuesToUse + 1 To lngPointerArrayCount
+ ThisIonList(lngIonPointerArray(lngIndex), ilaNormalizedIntensity) = -1
+ Next lngIndex
+
+ If blnShowProgress Then
+ frmProgress.InitializeForm LookupMessage(950), 0, 4
+ frmProgress.UpdateProgressBar 2
+ frmProgress.UpdateCurrentSubTask LookupMessage(960)
+ End If
+
+ ' Next, normalize the intensities in each mass region
+ ' For each region, find the maximum intensity
+ ' Then normalize intensities in given region to maximum intensity
+ For lngRegionIndex = 1 To intMassRegionCount
+ dblMaximumIntensity = LowestValueForDoubleDataType
+ For lngIndex = dblMassRegionIndices(lngRegionIndex, 1) To dblMassRegionIndices(lngRegionIndex + 1, 1)
+ If ThisIonList(lngIndex, ilaNormalizedIntensity) > dblMaximumIntensity Then dblMaximumIntensity = ThisIonList(lngIndex, ilaNormalizedIntensity)
+ Next lngIndex
+ If dblMaximumIntensity <= 0 Then
+ ' All ions in this region were below tolerance
+ dblMaximumIntensity = 1
+ Else
+ If dblMaximumIntensity > dblOriginalMaximumIntensity Then
+ dblOriginalMaximumIntensity = dblMaximumIntensity
+ End If
+ End If
+ ' Finally, step through list, normalizing intensities if > 0
+ lngStopIndex = dblMassRegionIndices(lngRegionIndex + 1, 1) - 1
+ If lngRegionIndex = intMassRegionCount Then
+ lngStopIndex = lngStopIndex + 1
+ End If
+ For lngIndex = dblMassRegionIndices(lngRegionIndex, 1) To lngStopIndex
+ If ThisIonList(lngIndex, ilaNormalizedIntensity) > 0 Then
+ ' Round Intensity to 3 decimal places
+ ThisIonList(lngIndex, ilaNormalizedIntensity) = Round(ThisIonList(lngIndex, ilaNormalizedIntensity) / dblMaximumIntensity * dblNormalizedIntensity, 3)
+ End If
+ Next lngIndex
+ Next lngRegionIndex
+
+ FillIonMatchGridWrapper
+
+ If blnShowProgress Then
+ frmProgress.InitializeForm LookupMessage(950), 0, 4
+ frmProgress.UpdateProgressBar 3
+ frmProgress.UpdateCurrentSubTask LookupMessage(970)
+ End If
+
+ UpdateMassesGridAndSpectrumWrapper
+
+ If KeyPressAbortProcess > 1 Then
+ MsgBox LookupMessage(940), vbInformation + vbOKOnly, LookupMessage(945)
+ End If
+
+ frmProgress.HideForm
+End Sub
+
+Private Sub PasteIonMatchList()
+ Dim strIonList As String, strLineWork As String
+ Dim lngPointsLoaded As Long, blnAllowCommaDelimeter As Boolean
+ Dim lngCrLfLoc As Long, lngValuesToPopulate As Long
+ Dim lngIndex As Long, lngStartIndex As Long
+ Dim dblMinMass As Double, dblMaxMass As Double
+ Dim strDelimeter As String, intDelimeterLength As Integer
+
+On Error GoTo PasteIonMatchListErrorHandler
+
+ ' Warn user about replacing data
+ If Not QueryExistingIonsInList() Then Exit Sub
+
+ ' Grab text from clipboard
+ strIonList = GetClipboardTextSmart()
+
+ If Len(strIonList) = 0 Then
+ MsgBox LookupMessage(980), vbInformation + vbOKOnly, LookupMessage(985)
+ Exit Sub
+ End If
+
+ ' Determine if commas are used for the decimal point in this locale
+ If DetermineDecimalPoint() = "," Then
+ blnAllowCommaDelimeter = False
+ Else
+ blnAllowCommaDelimeter = True
+ End If
+
+ frmProgress.InitializeForm LookupMessage(990), 0, Len(strIonList)
+ frmProgress.ToggleAlwaysOnTop True
+ frmProgress.UpdateCurrentSubTask LookupMessage(1000)
+ lngPointsLoaded = 0
+
+ ' First Determine number of data points in strIonList
+ ' Necessary since the IonMatchList() array is multi-dimensional and cannot be redimensioned without erasing old values
+
+ ' First look for the first occurrence of a valid delimeter
+ lngCrLfLoc = ParseStringFindCrlfIndex(strIonList, intDelimeterLength)
+
+ If lngCrLfLoc > 0 Then
+ ' Record the first character of the delimeter (if vbCrLf, then recording vbCr), otherwise, recording just vbCr or just vbLf)
+ strDelimeter = Mid(strIonList, lngCrLfLoc, 1)
+
+ ' Now determine the number of occurrences of the delimeter
+ lngValuesToPopulate = 0
+ For lngIndex = 1 To Len(strIonList)
+ If lngIndex Mod 500 = 0 Then
+ frmProgress.UpdateProgressBar lngIndex
+ If KeyPressAbortProcess > 1 Then Exit For
+ End If
+
+ If Mid(strIonList, lngIndex, 1) = strDelimeter Then
+ lngValuesToPopulate = lngValuesToPopulate + 1
+ End If
+ Next lngIndex
+
+ If lngValuesToPopulate > 1 And KeyPressAbortProcess = 0 Then
+ ' Update frmProgress to use the correct progress bar size
+ frmProgress.InitializeForm LookupMessage(990), 0, lngValuesToPopulate
+ frmProgress.UpdateCurrentSubTask LookupMessage(1010)
+ End If
+
+ ' Initialize IonMatchList
+ InitializeIonMatchList lngValuesToPopulate
+ lngPointsLoaded = 0
+
+ dblMaxMass = LowestValueForDoubleDataType
+ dblMinMass = HighestValueForDoubleDataType
+
+ ' Actually parse the data
+ ' I process the list using the Mid() function since this is the fastest method
+ ' However, Mid() becomes slower when the index value reaches 1000 or more (roughly)
+ ' so I discard already-parsed data from strIonList every 1000 characters (approximately)
+ Do While Len(strIonList) > 0
+ lngStartIndex = 1
+ For lngIndex = 1 To Len(strIonList)
+ If lngIndex Mod 100 = 0 Then
+ frmProgress.UpdateProgressBar lngPointsLoaded
+ If KeyPressAbortProcess > 1 Then Exit For
+ End If
+
+ If Mid(strIonList, lngIndex, 1) = strDelimeter Then
+ strLineWork = Mid(strIonList, lngStartIndex, lngIndex - 1)
+
+ If Len(strLineWork) > 0 Then
+ AddIonPairToIonList strLineWork, lngPointsLoaded, blnAllowCommaDelimeter, dblMinMass, dblMaxMass
+ End If
+
+ lngStartIndex = lngIndex + intDelimeterLength
+ lngIndex = lngIndex + intDelimeterLength - 1
+
+ If lngIndex > 1000 Then
+ ' Reduce the size of strIonList since the Mid() function gets slower with longer strings
+ strIonList = Mid(strIonList, lngIndex + 1)
+ lngIndex = 1
+ Exit For
+ End If
+ End If
+ Next lngIndex
+ If lngIndex > Len(strIonList) Then Exit Do
+ Loop
+ End If
+
+ If lngPointsLoaded > 0 And KeyPressAbortProcess = 0 Then
+ If Abs((dblMaxMass - dblMinMass) / lngPointsLoaded) < ION_SEPARATION_TOLERANCE_TO_AUTO_ENABLE_BINNING Then
+ ' Average spacing between ions is less than 0.2 Da, turn on binning
+ frmIonMatchOptions.chkGroupSimilarIons.value = vbChecked
+ End If
+
+ ' Reset the alignment offset
+ txtAlignment = "0"
+
+ UpdateIonMatchListWrapper
+ frmProgress.HideForm
+ Else
+ frmProgress.HideForm
+ If KeyPressAbortProcess = 0 Then
+ MsgBox LookupMessage(1020), vbInformation + vbOKOnly, LookupMessage(985)
+ Else
+ MsgBox LookupMessage(940), vbInformation + vbOKOnly, LookupMessage(945)
+ End If
+ End If
+
+ Exit Sub
+
+PasteIonMatchListErrorHandler:
+ frmProgress.HideForm
+ GeneralErrorHandler "frmFragmentationModelling|ParseIonMatchList", Err.Number, Err.Description
+
+End Sub
+
+Public Sub PasteNewSequence(ByVal strNewSequence As String, bln3LetterCode As Boolean)
+
+ ' Validate strNewSequence
+ objMwtWin.Peptide.SetSequence strNewSequence, , , bln3LetterCode
+
+ txtSequence = objMwtWin.Peptide.GetSequence(bln3LetterCode)
+
+End Sub
+
+Private Sub PeptideSequenceKeyPressHandler(txtThisTextBox As TextBox, KeyAscii As Integer)
+ ' Checks KeyAscii to see if it's valid
+ ' If it isn't, it is set to 0
+
+ If Not objMwtWin.IsModSymbol(Chr(KeyAscii)) Then
+ Select Case KeyAscii
+ Case 1 ' Ctrl+A -- select entire textbox
+ txtThisTextBox.SelStart = 0
+ txtThisTextBox.SelLength = Len(txtThisTextBox.Text)
+ KeyAscii = 0
+ Case 24, 3, 22 ' Cut, Copy, Paste is allowed
+ Case 26
+ ' Ctrl+Z = Undo
+ KeyAscii = 0
+ txtThisTextBox.Text = GetMostRecentTextBoxValue()
+ Case 8 ' Backspace key is allowed
+ Case 48 To 57 ' Numbers are not allowed ' ToDo: Possibly allow them for side-chains
+ KeyAscii = 0
+ Case 32 ' Spaces are allowed
+ Case 40 To 41 ' Parentheses are not allowed ' ToDo: Possibly allow them for side-chains
+ KeyAscii = 0
+ Case 43: ' Plus sign is not allowed
+ KeyAscii = 0
+ Case 45: ' Negative sign is allowed
+ Case 44, 46: ' Decimal point (. or ,) is allowed
+ Case 65 To 90, 97 To 122 ' Characters are allowed
+ Case 95: ' Underscore is not allowed
+ KeyAscii = 0
+ Case Else
+ KeyAscii = 0
+ End Select
+ End If
+
+End Sub
+
+Private Sub PopulateComboBoxes()
+
+ Dim intIndex As Integer
+
+ On Error GoTo PopulateComboBoxesErrorHandler
+
+ PopulateComboBox cboNotation, True, "1 letter notation|3 letter notation", 1
+
+ With cboDoubleCharge
+ For intIndex = 1 To 16
+ .AddItem CIntSafeDbl((intIndex - 1) * 100)
+ Next intIndex
+ .ListIndex = 8
+ End With
+
+ PopulateComboBox cboNTerminus, True, "H (hydrogen)|HH+ (protonated)|C2OH3 (acetyl)|C5O2NH6 (pyroglu)|CONH2 (carbamyl)|C7H6NS (PTC)|(none)", 0
+
+ PopulateComboBox cboCTerminus, True, "OH (hydroxyl)|NH2 (amide)|(none)", 0
+
+ With lstIonsToModify
+ .Clear
+ .AddItem UCase(LookupLanguageCaption(12600, "a"))
+ .AddItem UCase(LookupLanguageCaption(12610, "b"))
+ .AddItem UCase(LookupLanguageCaption(12620, "y"))
+ .Selected(0) = False
+ .Selected(1) = True
+ .Selected(2) = True
+ End With
+
+ With cboMHAlternate
+ .Clear
+ .AddItem "[M+H]1+"
+ For intIndex = 2 To 9
+ .AddItem "[M+" & Trim(intIndex) & "H]" & Trim(intIndex) & "+"
+ Next intIndex
+ .ListIndex = 1 ' Charge of 2+
+ End With
+ Exit Sub
+
+PopulateComboBoxesErrorHandler:
+ GeneralErrorHandler "frmFragmentationModelling|PopulateComboBoxes", Err.Number, Err.Description
+
+End Sub
+
+Private Sub PositionControls()
+ Dim lngTopAdjust As Long, blnIonMatchListShown As Boolean
+ Dim lngPreferredTop As Long, lngMinimumTop As Long
+ Dim lngPreferredHeight As Long
+ Dim lngPreferredWidth As Long
+ Dim blnSkipWidthAdjust As Boolean, blnSkipHeightAdjust As Boolean
+
+ If Me.WindowState = vbMinimized Then Exit Sub
+
+ blnIonMatchListShown = grdIonList.Visible
+ If Me.Height < 6500 And Not blnIonMatchListShown Then
+ lngTopAdjust = 0
+ Else
+ lngTopAdjust = 340
+ End If
+
+ If Me.Height < 2660 + lngTopAdjust Then
+ 'Me.Height = 2660 + lngTopAdjust
+ ' Do not position any controls; form too small
+ blnSkipHeightAdjust = True
+ End If
+
+ If blnIonMatchListShown Then
+ lngPreferredWidth = 8000
+ Else
+ lngPreferredWidth = 6700
+ End If
+
+ If Me.Width < lngPreferredWidth Then
+ 'Me.Width = 6700
+ ' Do not position any controls; form too small
+ blnSkipWidthAdjust = True
+ End If
+
+ lblSequence.Top = 180
+ lblSequence.Left = 60
+ txtSequence.Top = 120
+ txtSequence.Left = 1440
+ If Not blnSkipWidthAdjust Then txtSequence.Width = Me.Width - txtSequence.Left - cmdMatchIons.Width - 340
+ txtSequence.Height = 315 + lngTopAdjust
+
+ If Not blnSkipWidthAdjust Then
+ cmdMatchIons.Left = txtSequence.Left + txtSequence.Width + 120
+ End If
+
+ If Not blnSkipHeightAdjust Then
+ cmdMatchIons.Top = txtSequence.Top + (txtSequence.Height / 2) - (cmdMatchIons.Height / 2)
+ End If
+
+ With fraMassInfo
+ .Top = 460 + lngTopAdjust
+ .Left = 2640
+ End With
+ lngTopAdjust = lngTopAdjust + fraMassInfo.Height
+
+ cboNotation.Top = fraMassInfo.Top + 120
+ cboNotation.Left = 120
+
+ lblMH.Left = cboMHAlternate.Left + 60
+
+ With grdIonList
+ .Top = fraMassInfo.Top + fraMassInfo.Height + 100
+ lngPreferredWidth = 2280
+ If Me.Width > 10000 Then
+ lngPreferredWidth = lngPreferredWidth + (Me.Width - 10000) / 4
+ If lngPreferredWidth > 3270 Then lngPreferredWidth = 3270
+ End If
+
+ .Width = lngPreferredWidth
+ If Not blnSkipWidthAdjust Then .Left = Me.Width - .Width - 225
+ If Not blnSkipHeightAdjust Then .Height = Me.Height - .Top - 900
+ End With
+
+ fraTerminii.Top = grdIonList.Top
+ fraTerminii.Left = 60
+
+ fraIonTypes.Top = fraTerminii.Top + fraTerminii.Height + 80
+ fraIonTypes.Left = fraTerminii.Left
+
+ fraNeutralLosses.Top = fraIonTypes.Top + fraIonTypes.Height + 80
+ fraNeutralLosses.Left = fraTerminii.Left
+
+ fraCharge.Top = fraNeutralLosses.Top + fraNeutralLosses.Height + 80
+ fraCharge.Left = fraTerminii.Left
+
+ ' Preferred top for fraIonMatching
+ lngPreferredTop = Me.Height - fraIonMatching.Height - 860
+ lngMinimumTop = fraCharge.Top + fraCharge.Height + 80
+ If lngPreferredTop < lngMinimumTop Then lngPreferredTop = lngMinimumTop
+
+ With fraIonMatching
+ If Not blnSkipHeightAdjust Then .Top = lngPreferredTop
+ .Left = fraTerminii.Left
+ End With
+
+ With fraIonStats
+ .Top = fraIonMatching.Top
+ .Left = fraIonMatching.Left + fraIonMatching.Width + 90
+ lngPreferredWidth = fraIonMatching.Width
+ If .Left + lngPreferredWidth > grdIonList.Left - 80 Then
+ lngPreferredWidth = grdIonList.Left - 80 - .Left
+ If lngPreferredWidth < 1500 Then
+ lngPreferredWidth = 1500
+ End If
+ End If
+ .Width = lngPreferredWidth
+
+ ' Remove the border (I keep it on in the design window so I can see where the labels are
+ lblIonLoadedCount.BorderStyle = 0
+ lblBinAndToleranceCounts.BorderStyle = 0
+ lblPrecursorStatus.BorderStyle = 0
+ lblMatchCount.BorderStyle = 0
+ lblScore.BorderStyle = 0
+
+ lblIonLoadedCount.Width = lngPreferredWidth - 250
+ lblBinAndToleranceCounts.Width = lblIonLoadedCount.Width
+ lblPrecursorStatus.Width = lblIonLoadedCount.Width
+ lblMatchCount.Width = lblIonLoadedCount.Width
+ lblScore.Width = lblIonLoadedCount.Width
+ End With
+
+ With grdFragMasses
+ .Left = fraMassInfo.Left
+ .Top = grdIonList.Top
+
+ ' Preferred height for grdFragMasses
+ lngPreferredHeight = grdIonList.Height
+ If blnIonMatchListShown Then
+ If .Top + lngPreferredHeight + 80 > lngPreferredTop Then
+ lngPreferredHeight = fraIonMatching.Top - .Top - 80
+ End If
+ End If
+
+ If Not blnSkipWidthAdjust Then
+ If grdIonList.Visible Then
+ .Width = Me.Width - .Left - 220 - grdIonList.Width - 90
+ Else
+ .Width = Me.Width - .Left - 220
+ End If
+ End If
+ .Height = lngPreferredHeight
+ End With
+
+ mnuIonMatchListRightClick.Visible = False
+
+End Sub
+
+Private Function QueryExistingIonsInList() As Boolean
+ Dim strMessage As String, eResponse As VbMsgBoxResult
+
+ If grdIonList.Rows > 1 Then
+ strMessage = LookupMessage(910)
+ eResponse = MsgBox(strMessage, vbQuestion + vbYesNoCancel + vbDefaultButton3, LookupMessage(920))
+ If eResponse = vbYes Then
+ QueryExistingIonsInList = True
+ Else
+ QueryExistingIonsInList = False
+ End If
+ Else
+ QueryExistingIonsInList = True
+ End If
+
+End Function
+
+Public Sub ResetCWSpectrumOptions()
+ objSpectrum.ResetOptionsToDefaults True, True, 2, pmStickToZero
+End Sub
+
+Public Sub ResetPredictedSpectrumCRC()
+ CRCForIonListSaved = 0
+ CRCForPredictedSpectrumSaved = 0
+End Sub
+
+Public Sub SaveCWSpectrumOptions(strSequenceFilePath As String)
+On Error GoTo SaveCWSpectrumOptionsErrorHandler
+
+ objSpectrum.SaveDataToDisk strSequenceFilePath, True, ",", False, True
+ Exit Sub
+
+SaveCWSpectrumOptionsErrorHandler:
+ Debug.Assert False
+ GeneralErrorHandler "frmFragmentationModelling|SaveDataToDisk", Err.Number, Err.Description
+End Sub
+
+Private Function SearchForIonInIonListGrid(ByVal dblMassToFind As Double, ByVal dblMatchTolerance As Double) As Long
+ ' Returns -1 if no match
+ ' Otherwise, returns the row index of the match in grdIonList
+
+ Dim lngIonIndex As Long, boolIonMassMatched As Boolean
+ Dim dblCompareMass As Double
+
+ boolIonMassMatched = False
+ For lngIonIndex = 1 To grdIonList.Rows - 1
+ dblCompareMass = grdIonList.TextMatrix(lngIonIndex, ilgMass)
+ If WithinTolerance(dblMassToFind, dblCompareMass, dblMatchTolerance) Then
+ boolIonMassMatched = True
+ Exit For
+ End If
+ Next lngIonIndex
+
+ If boolIonMassMatched Then
+ SearchForIonInIonListGrid = lngIonIndex
+ Else
+ SearchForIonInIonListGrid = -1
+ End If
+End Function
+
+Private Sub SetDtaTxtFileBrowserMenuVisibility(blnShowMenu As Boolean)
+ mnuViewDtaTxtSep.Visible = blnShowMenu
+ mnuViewDtaTxtBrowser.Visible = blnShowMenu
+End Sub
+
+Public Sub SetIonMatchList(dblXVals() As Double, dblYVals() As Double, lngDataCount As Long, strSourceFilePath As String, lngScanNumberStart As Long, lngScanNumberEnd As Long, ByVal dblParentIon As Double, intParentIonCharge As Integer, Optional blnAllowAutoBinningDetermination As Boolean = True)
+ ' Set the ion match list values via code
+ ' dblXVals() and dblYVals() should be 0-based
+
+ Dim lngIndex As Long
+ Dim dblMinMass As Double, dblMaxMass As Double
+ Dim strCaption As String, strPrecursorIonMH As String
+ Dim fso As New FileSystemObject
+
+ ' Initialize IonMatchList
+ InitializeIonMatchList lngDataCount
+
+ dblMinMass = HighestValueForDoubleDataType
+ dblMaxMass = LowestValueForDoubleDataType
+
+ For lngIndex = 0 To lngDataCount - 1
+ AppendXYPair IonMatchList(), IonMatchListCount, dblXVals(lngIndex), dblYVals(lngIndex), True
+
+ If dblXVals(lngIndex) < dblMinMass Then dblMinMass = dblXVals(lngIndex)
+ If dblXVals(lngIndex) > dblMaxMass Then dblMaxMass = dblXVals(lngIndex)
+ Next lngIndex
+
+ If lngDataCount > 0 Then
+ If Abs((dblMaxMass - dblMinMass) / lngDataCount) < ION_SEPARATION_TOLERANCE_TO_AUTO_ENABLE_BINNING Then
+ ' Average spacing between ions is less than 0.2 Da, turn on binning
+ frmIonMatchOptions.chkGroupSimilarIons.value = vbChecked
+ End If
+
+ ' Reset the alignment offset
+ txtAlignment = "0"
+
+ ' Note that the Parent Ion mass in a .Dta file is the MH mass, and is thus already 1+
+ strPrecursorIonMH = FormatNumberAsString(Round(dblParentIon, 2), 10, 8)
+
+ strCaption = CompactPathString(fso.GetFileName(strSourceFilePath), 20)
+ If Right(strCaption, 2) = ".." Then strCaption = Left(strCaption, Len(strCaption) - 2)
+
+ strCaption = strCaption & ": Scan " & Trim(lngScanNumberStart)
+ If lngScanNumberEnd <> lngScanNumberStart Then
+ strCaption = strCaption & "-" & Trim(lngScanNumberEnd)
+ End If
+
+ mIonMatchListDetails.Caption = strCaption
+
+ txtPrecursorIonMass = strPrecursorIonMH
+
+ UpdateIonMatchListWrapper
+
+ End If
+
+ Set fso = Nothing
+
+End Sub
+
+Public Sub SetIonMatchListCaption(strNewCaption As String)
+ mIonMatchListDetails.Caption = strNewCaption
+End Sub
+
+Private Sub SetIonMatchListVisibility(blnShowList As Boolean)
+ mnuViewMatchIonList.Checked = blnShowList
+
+ grdIonList.Visible = blnShowList
+ mnuClearMatchIonList.Enabled = blnShowList
+ fraIonMatching.Visible = blnShowList
+ fraIonStats.Visible = blnShowList
+ cmdMatchIons.Visible = blnShowList
+
+ If Me.WindowState = vbNormal And blnShowList Then
+ If Me.Width < 9000 Then Me.Width = 9000
+ End If
+
+ PositionControls
+ UpdateMassesGridAndSpectrumWrapper
+
+End Sub
+
+Public Sub SetFragMatchSettingsChanged()
+ mFragMatchSettingsChanged = True
+End Sub
+
+Public Sub SetNeedToZoomOutFull(blnEnable As Boolean)
+ mNeedToZoomOutFull = blnEnable
+End Sub
+
+Public Sub SetUpdateSpectrumMode(blnUpdateOnChange As Boolean)
+ mnuUpdateSpectrum.Checked = blnUpdateOnChange
+End Sub
+
+Private Sub ShellSortIonList(ByRef ThisIonMatchList() As Double, lngPointerArray() As Long, ByVal lngLowIndex As Long, ByVal lngHighIndex As Long, intColIndexToSortOn As Integer, blnUpdateProgressForm As Boolean)
+ ' Sorts the PointerArray to ThisIonMatchList() using column intColIndexToSortOn
+ ' Note that ThisIonMatchList() is a 2D array, 1-based in the first dimension but uses columns 0, 1, and 2
+
+ Dim lngCount As Long
+ Dim lngIncrement As Long
+ Dim lngIndex As Long
+ Dim lngIndexCompare As Long
+ Dim lngPointerSaved As Long
+ Dim dblCompareVal As Double
+
+ ' sort array[lngLowIndex..lngHighIndex]
+
+ ' compute largest increment
+ lngCount = lngHighIndex - lngLowIndex + 1
+ lngIncrement = 1
+ If (lngCount < 14) Then
+ lngIncrement = 1
+ Else
+ Do While lngIncrement < lngCount
+ lngIncrement = 3 * lngIncrement + 1
+ Loop
+ lngIncrement = lngIncrement \ 3
+ lngIncrement = lngIncrement \ 3
+ End If
+
+ Do While lngIncrement > 0
+ ' sort by insertion in increments of lngIncrement
+ For lngIndex = lngLowIndex + lngIncrement To lngHighIndex
+ lngPointerSaved = lngPointerArray(lngIndex)
+ dblCompareVal = ThisIonMatchList(lngPointerSaved, intColIndexToSortOn)
+ For lngIndexCompare = lngIndex - lngIncrement To lngLowIndex Step -lngIncrement
+ ' Use <= to sort ascending; Use > to sort descending
+ If ThisIonMatchList(lngPointerArray(lngIndexCompare), intColIndexToSortOn) > dblCompareVal Then Exit For
+ lngPointerArray(lngIndexCompare + lngIncrement) = lngPointerArray(lngIndexCompare)
+ Next lngIndexCompare
+ lngPointerArray(lngIndexCompare + lngIncrement) = lngPointerSaved
+ Next lngIndex
+ lngIncrement = lngIncrement \ 3
+ Loop
+
+End Sub
+
+Public Sub ShowAutoLabelPeaksOptions()
+ objSpectrum.ShowAutoLabelPeaksDialog
+End Sub
+
+Private Sub UpdateFragmentationSpectrumOptions()
+
+ Dim intIonIndex As Integer
+ Dim blnModifyIon As Boolean
+ Dim sngDivisorForInversion As Single
+ Dim intLastGoodLineNumber As Integer
+
+On Error GoTo UpdateFragmentationSpectrumOptionsHandler
+ intLastGoodLineNumber = 2568
+
+ If objMwtWin.Peptide Is Nothing Then Exit Sub
+
+ intLastGoodLineNumber = 2572
+ ' Initialize to the current values
+ udtNewFragmentationSpectrumOptions = objMwtWin.Peptide.GetFragmentationSpectrumOptions
+
+ intLastGoodLineNumber = 2576
+ With udtNewFragmentationSpectrumOptions
+ intLastGoodLineNumber = 2578
+ .DoubleChargeIonsShow = cChkBox(chkDoubleCharge)
+ If cboDoubleCharge.ListIndex >= 0 And cboDoubleCharge.ListCount > 0 Then
+ .DoubleChargeIonsThreshold = cboDoubleCharge.List(cboDoubleCharge.ListIndex)
+ End If
+
+ intLastGoodLineNumber = 2584
+ For intIonIndex = 0 To TOTAL_POSSIBLE_ION_TYPES - 1
+ .IonTypeOptions(intIonIndex).ShowIon = cChkBox(chkIonType(intIonIndex))
+ Next intIonIndex
+
+ intLastGoodLineNumber = 2589
+ For intIonIndex = 0 To TOTAL_POSSIBLE_ION_TYPES - 1
+ blnModifyIon = lstIonsToModify.Selected(intIonIndex)
+
+ .IonTypeOptions(intIonIndex).NeutralLossWater = blnModifyIon And cChkBox(chkWaterLoss)
+ .IonTypeOptions(intIonIndex).NeutralLossAmmonia = blnModifyIon And cChkBox(chkAmmoniaLoss)
+ .IonTypeOptions(intIonIndex).NeutralLossPhosphate = blnModifyIon And cChkBox(chkPhosphateLoss)
+
+ Next intIonIndex
+
+ ' Note: A ions can have ammonia and phosphate loss, but not water loss, so always set this to false
+ .IonTypeOptions(itAIon).NeutralLossWater = False
+
+ intLastGoodLineNumber = 2602
+ For intIonIndex = 0 To TOTAL_POSSIBLE_ION_TYPES - 1
+ .IntensityOptions.IonType(intIonIndex) = Val(frmIonMatchOptions.txtIonIntensity(intIonIndex))
+ Next intIonIndex
+ .IntensityOptions.BYIonShoulder = frmIonMatchOptions.txtBYIonShoulders
+ .IntensityOptions.NeutralLoss = frmIonMatchOptions.txtNeutralLosses
+
+ intLastGoodLineNumber = 2609
+ If cChkBox(frmIonMatchOptions.chkPlotSpectrumInverted) Then
+ If cChkBox(frmIonMatchOptions.chkFragSpecEmphasizeProlineYIons) Then
+ sngDivisorForInversion = 2.5
+ Else
+ sngDivisorForInversion = 2.77777
+ End If
+
+ For intIonIndex = 0 To TOTAL_POSSIBLE_ION_TYPES - 1
+ .IntensityOptions.IonType(intIonIndex) = -Abs(.IntensityOptions.IonType(intIonIndex)) / sngDivisorForInversion
+ Next intIonIndex
+ .IntensityOptions.BYIonShoulder = -Abs(.IntensityOptions.BYIonShoulder) / sngDivisorForInversion
+ .IntensityOptions.NeutralLoss = -Abs(.IntensityOptions.NeutralLoss) / sngDivisorForInversion
+ End If
+
+ End With
+
+ intLastGoodLineNumber = 2626
+ objMwtWin.Peptide.SetFragmentationSpectrumOptions udtNewFragmentationSpectrumOptions
+ Exit Sub
+
+UpdateFragmentationSpectrumOptionsHandler:
+ GeneralErrorHandler "frmFragmentationModelling|UpdateFragmentationSpectrumOptions", Err.Number, "Last good line number = " & Trim(intLastGoodLineNumber) & vbCrLf & Err.Description
+
+End Sub
+
+Private Sub UpdateIonLoadStats(Optional boolClearStats As Boolean = False)
+ Dim lngWithinTolerance As Long, sngPercentage As Single
+ Dim strLoaded As String, strRemaining As String
+ Dim strWithinTolerance As String
+ Dim strMessage As String
+
+ strLoaded = LookupLanguageCaption(12370, "Loaded") & ": "
+ strRemaining = LookupLanguageCaption(12375, "Remaining after binning") & ": "
+ strWithinTolerance = LookupLanguageCaption(12380, "Within tolerance") & ": "
+
+ lblIonLoadedCount.Caption = strLoaded & CStr(IonMatchListCount)
+
+ If boolClearStats Then
+ lblBinAndToleranceCounts.Caption = ""
+ lblPrecursorStatus.Caption = ""
+ lblMatchCount.Caption = ""
+ lblScore.Caption = ""
+ Else
+ lngWithinTolerance = grdIonList.Rows - 1
+ If BinnedDataCount > 0 Then
+ strMessage = strRemaining & CStr(BinnedDataCount) & vbCrLf
+ sngPercentage = lngWithinTolerance / BinnedDataCount * 100
+ Else
+ If IonMatchListCount > 0 Then
+ sngPercentage = lngWithinTolerance / IonMatchListCount * 100
+ Else
+ sngPercentage = 0
+ End If
+ End If
+ strMessage = strMessage & strWithinTolerance & CStr(lngWithinTolerance) & " (" & Format(sngPercentage, "#0.0") & "%)"
+ lblBinAndToleranceCounts = strMessage
+ End If
+
+End Sub
+
+Public Sub UpdateIonMatchListWrapper()
+ Dim blnUpdateMassSpectrumSaved As Boolean
+
+ blnUpdateMassSpectrumSaved = mnuUpdateSpectrum.Checked
+ If blnUpdateMassSpectrumSaved Then mnuUpdateSpectrum.Checked = False
+
+ ' The following calls UpdateMassesGridAndSpectrumWrapper
+ SetIonMatchListVisibility True
+ BinIonMatchList
+
+ If blnUpdateMassSpectrumSaved Then mnuUpdateSpectrum.Checked = True
+
+ ' The following sub calls UpdateMassesGridAndSpectrumWrapper, which calls the MatchIons sub
+ NormalizeIonMatchListWrapper
+
+ UpdateIonLoadStats
+
+End Sub
+
+Private Sub UpdateMassesGridAndSpectrumWrapper()
+
+ ' Set the Settings Changed Bit
+ SetFragMatchSettingsChanged
+
+ ' Display predicted ions & intensities in grid
+ DisplayPredictedIonMasses
+ MatchIons
+
+ ' Call UpdatePredictedFragSpectrum if necessary
+ If mnuUpdateSpectrum.Checked Then
+ DisplaySpectra
+ End If
+End Sub
+
+Private Sub UpdateMatchCountAndScoreWork(lngMatchCount As Long, dblMatchScore As Double)
+ lblMatchCount = LookupLanguageCaption(12400, "Matches") & ": " & CStr(lngMatchCount)
+ lblScore = LookupLanguageCaption(12405, "Score") & ": " & Format(dblMatchScore, "0.0")
+End Sub
+
+Private Sub UpdatePredictedFragMasses()
+ ' Determines the masses of the expected ions for the given sequence
+
+ Dim dblSequenceMass As Double
+
+ If mDelayUpdate Then Exit Sub
+
+ If Len(txtSequence) > 100 Then Me.MousePointer = vbHourglass
+
+ objMwtWin.Peptide.SetSequence txtSequence, GetNTerminusState(), GetCTerminusState(), Get3LetterCodeState()
+
+ If objMwtWin.Peptide.GetResidueCount > 0 Then
+ dblSequenceMass = objMwtWin.Peptide.GetPeptideMass()
+ If dblSequenceMass = 0 Then
+ txtMH = 0
+ Else
+ If cboNTerminus.ListIndex = ntgHydrogenPlusProton Then
+ ' Don't need to add a proton
+ txtMH = Round(dblSequenceMass, 6)
+ Else
+ txtMH = Round(dblSequenceMass + objMwtWin.GetChargeCarrierMass, 6)
+ End If
+ End If
+ Else
+ dblSequenceMass = 0
+ txtMH = "0"
+ End If
+
+ txtMWT = LookupLanguageCaption(4040, "MW") & " = " & Round(dblSequenceMass, 6)
+
+ UpdateMassesGridAndSpectrumWrapper
+
+ If Len(txtSequence) > 100 Then Me.MousePointer = vbDefault
+End Sub
+
+Private Sub UpdateStandardMasses()
+
+ dblHistidineFW = objMwtWin.ComputeMass("His")
+ dblPhenylalanineFW = objMwtWin.ComputeMass("Phe")
+ dblTyrosineFW = objMwtWin.ComputeMass("Tyr")
+ dblImmoniumMassDifference = objMwtWin.ComputeMass("CO") - objMwtWin.ComputeMass("H")
+
+ UpdatePredictedFragMasses
+End Sub
+
+Private Function WithinTolerance(ThisNumber As Double, CompareNumber As Double, ThisTolerance As Double) As Boolean
+ If Abs(ThisNumber - CompareNumber) <= ThisTolerance Then
+ WithinTolerance = True
+ Else
+ WithinTolerance = False
+ End If
+End Function
+
+Private Sub cboCTerminus_Click()
+ UpdatePredictedFragMasses
+End Sub
+
+Private Sub cboDoubleCharge_Click()
+ UpdatePredictedFragMasses
+End Sub
+
+Private Sub cboMHAlternate_Click()
+ ConvertSequenceMH True
+End Sub
+
+Private Sub cboNotation_Click()
+ UpdatePredictedFragMasses
+End Sub
+
+Private Sub cboNTerminus_Click()
+ UpdatePredictedFragMasses
+End Sub
+
+Private Sub chkAmmoniaLoss_Click()
+ UpdateMassesGridAndSpectrumWrapper
+End Sub
+
+Private Sub chkDoubleCharge_Click()
+ EnableDisableControls
+ UpdateMassesGridAndSpectrumWrapper
+End Sub
+
+Private Sub chkPhosphateLoss_Click()
+ UpdateMassesGridAndSpectrumWrapper
+End Sub
+
+Private Sub chkRemovePrecursorIon_Click()
+ EnableDisableControls
+ UpdateIonMatchListWrapper
+End Sub
+
+Private Sub chkWaterLoss_Click()
+ UpdateMassesGridAndSpectrumWrapper
+End Sub
+
+Private Sub chkIonType_Click(Index As Integer)
+ UpdateMassesGridAndSpectrumWrapper
+End Sub
+
+Private Sub cmdMatchIons_Click()
+ MatchIons
+End Sub
+
+Private Sub Form_Activate()
+ Dim lclFragMatchSettingsChanged As Boolean
+
+ PossiblyHideMainWindow
+
+ lclFragMatchSettingsChanged = mFragMatchSettingsChanged
+ mFormActivatedByUser = True
+
+ Select Case objMwtWin.GetElementMode
+ Case emAverageMass
+ optElementMode(0).value = True
+ Case emIsotopicMass
+ optElementMode(1).value = True
+ Case Else
+ objMwtWin.SetElementMode emIsotopicMass
+ optElementMode(1).value = True
+ End Select
+
+ UpdateStandardMasses
+ UpdateIonLoadStats
+
+ If lclFragMatchSettingsChanged And IonMatchListCount > 0 Then
+ ' Does this code ever get reached?
+ Debug.Assert False
+ UpdateIonMatchListWrapper
+ End If
+
+End Sub
+
+Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
+ If KeyCode = vbKeyEscape Then
+ mnuClose_Click
+ End If
+
+End Sub
+
+Private Sub Form_Load()
+
+On Error GoTo FormLoadErrorHandler
+
+ If objSpectrum Is Nothing Then
+ Set objSpectrum = New CWSpectrumDLL.Spectrum
+ End If
+ With objSpectrum
+ .SetSeriesCount 2
+ .SetSeriesPlotMode 1, pmStickToZero, True
+ End With
+ mNeedToZoomOutFull = True
+
+ SetDtaTxtFileBrowserMenuVisibility False
+ SetIonMatchListVisibility False
+
+ PopulateComboBoxes
+
+ ' Note that PositionControls gets called when the form is resized with the following command
+ ' Must call SetIonMatchListVisibility before calling this sub
+ SizeAndCenterWindow Me, cWindowTopLeft, 12000, 9250
+
+ EnableDisableControls
+
+ UpdateStandardMasses
+
+ InitializeIonMatchList 0
+
+ InitializeIonListGrid
+ UpdateMassesGridAndSpectrumWrapper
+
+ Exit Sub
+
+FormLoadErrorHandler:
+ GeneralErrorHandler "frmFragmentationModelling|Form_Load", Err.Number, Err.Description
+
+End Sub
+
+Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
+ QueryUnloadFormHandler Me, Cancel, UnloadMode
+End Sub
+
+Private Sub Form_Resize()
+ PositionControls
+End Sub
+
+Private Sub Form_Unload(Cancel As Integer)
+ Set objSpectrum = Nothing
+End Sub
+
+Private Sub grdFragMasses_KeyDown(KeyCode As Integer, Shift As Integer)
+ FlexGridKeyPressHandler Me, grdFragMasses, KeyCode, Shift
+End Sub
+
+Private Sub grdIonList_KeyDown(KeyCode As Integer, Shift As Integer)
+ If KeyCode = vbKeyV And (Shift And vbCtrlMask) Then
+ PasteIonMatchList
+ Else
+ FlexGridKeyPressHandler Me, grdIonList, KeyCode, Shift
+ End If
+
+End Sub
+
+Private Sub grdIonList_MouseUp(Button As Integer, Shift As Integer, x As Single, y As Single)
+ If Button = vbRightButton Then
+ Me.PopupMenu mnuIonMatchListRightClick
+ End If
+End Sub
+
+Private Sub lblIonMatchingWindow_Click()
+ Static ClickTrack As Integer, eResponse As VbMsgBoxResult
+
+ ClickTrack = ClickTrack + 1
+
+ If ClickTrack = 3 Then
+ ClickTrack = 0
+ eResponse = MsgBox("Initialize with Dummy Data?", vbQuestion + vbYesNoCancel, "Initialize")
+ If eResponse = vbYes Then InitializeDummyData 2
+ End If
+End Sub
+
+Private Sub lstIonsToModify_Click()
+ UpdateMassesGridAndSpectrumWrapper
+End Sub
+
+Private Sub mniIonMatchListRightClickPaste_Click()
+ PasteIonMatchList
+End Sub
+
+Private Sub mnuAutoAlign_Click()
+ AutoAlignMatchIonList
+End Sub
+
+Private Sub mnuClearMatchIonList_Click()
+ IonMatchListClear
+End Sub
+
+Private Sub mnuClose_Click()
+ HideFormShowMain Me
+End Sub
+
+Private Sub mnuCopySequenceMW_Click()
+ CopySequenceMW
+End Sub
+
+Private Sub mnuCopyPredictedIons_Click()
+ CopyFragGridInfo grdFragMasses, gcmText
+End Sub
+
+Private Sub mnuCopyPredictedIonsAsRTF_Click()
+ CopyFragGridInfo grdFragMasses, gcmRTF
+End Sub
+
+Private Sub mnuCopyPredictedIonsAsHtml_Click()
+ CopyFragGridInfo grdFragMasses, gcmHTML
+End Sub
+
+Private Sub mnuEditModificationSymbols_Click()
+ frmAminoAcidModificationSymbols.InitializeForm
+ frmAminoAcidModificationSymbols.Show vbModal
+ UpdatePredictedFragMasses
+End Sub
+
+Private Sub mnuFragmentationModellingHelp_Click()
+ ShowHelpPage hwnd, 3080
+
+End Sub
+
+Private Sub mnuIonMatchListOptions_Click()
+ frmIonMatchOptions.Show vbModeless
+End Sub
+
+Private Sub mnuIonMatchListRightClickCopy_Click()
+ ' Equivalent to pressing Ctrl+C
+ FlexGridCopyInfo Me, grdIonList, gcmText
+End Sub
+
+Private Sub mnuIonMatchListRightClickDeleteAll_Click()
+ IonMatchListClear
+End Sub
+
+Private Sub mnuIonMatchListRightClickSelectAll_Click()
+ ' Equivalent to pressing Ctrl+A
+ FlexGridSelectEntireGrid grdIonList
+End Sub
+
+Private Sub mnuLoadIonList_Click()
+ Dim blnSuccess As Boolean
+
+''' ' Warn user about replacing data
+''' If Not QueryExistingIonsInList() Then Exit Sub
+
+ blnSuccess = LoadIonListToMatch()
+
+ If blnSuccess Then
+ UpdateIonMatchListWrapper
+ Else
+ If Err.Number <> 32755 Then
+ MsgBox LookupMessage(1020), vbInformation + vbOKOnly, LookupMessage(985)
+ End If
+ End If
+
+End Sub
+
+Private Sub mnuLoadSequenceInfo_Click()
+ LoadSequenceInfo
+End Sub
+
+Private Sub mnuPasteIonList_Click()
+ PasteIonMatchList
+End Sub
+
+Private Sub mnuSaveSequenceInfo_Click()
+ SaveSequenceInfo IonMatchList(), IonMatchListCount, mIonMatchListDetails.Caption
+End Sub
+
+Private Sub mnuShowMassSpectrum_Click()
+ SetUpdateSpectrumMode True
+
+ UpdateMassesGridAndSpectrumWrapper
+
+ objSpectrum.ShowSpectrum
+End Sub
+
+Private Sub mnuViewDtaTxtBrowser_Click()
+ If frmDtaTxtFileBrowser.GetDataInitializedState() Then
+ frmDtaTxtFileBrowser.Show
+ End If
+End Sub
+
+Private Sub mnuViewMatchIonList_Click()
+ SetIonMatchListVisibility (Not mnuViewMatchIonList.Checked)
+End Sub
+
+Private Sub mnuUpdateSpectrum_Click()
+ SetUpdateSpectrumMode Not mnuUpdateSpectrum.Checked
+ UpdateMassesGridAndSpectrumWrapper
+End Sub
+
+Private Sub objSpectrum_SpectrumFormRequestClose()
+ ' The SpectrumForm was closed (actually, most likely just hidden)
+ ' If we wanted to do anything special, we could do it here
+End Sub
+
+Private Sub optElementMode_Click(Index As Integer)
+ ' Elementweightmode = 1 means average weights, 2 means isotopic, and 3 means integer
+ Dim eNewWeightMode As emElementModeConstants
+
+ eNewWeightMode = Index + 1
+
+ If eNewWeightMode <> objMwtWin.GetElementMode Then
+ SwitchWeightMode eNewWeightMode, True, False
+
+ UpdateStandardMasses
+ UpdateIonLoadStats
+
+ If mFragMatchSettingsChanged And IonMatchListCount > 0 Then
+ ' Does this code ever get reached?
+ Debug.Assert False
+ UpdateIonMatchListWrapper
+ End If
+ End If
+
+End Sub
+
+Private Sub txtAlignment_KeyDown(KeyCode As Integer, Shift As Integer)
+ If KeyCode = 13 And Not mAutoAligning Then
+ AlignmentOffsetValidate
+ End If
+End Sub
+
+Private Sub txtAlignment_KeyPress(KeyAscii As Integer)
+ TextBoxKeyPressHandler txtAlignment, KeyAscii, True, True, True, False, True, False, False, False, False, True
+End Sub
+
+Private Sub txtAlignment_Validate(Cancel As Boolean)
+ If Val(GetMostRecentTextBoxValue) <> Val(txtAlignment) Then
+ If Not mAutoAligning Then
+ AlignmentOffsetValidate
+ End If
+ End If
+End Sub
+
+Private Sub txtIonMatchingWindow_GotFocus()
+ HighlightOnFocus txtIonMatchingWindow
+End Sub
+
+Private Sub txtIonMatchingWindow_KeyDown(KeyCode As Integer, Shift As Integer)
+ If KeyCode = 13 Then UpdateIonMatchListWrapper
+End Sub
+
+Private Sub txtIonMatchingWindow_KeyPress(KeyAscii As Integer)
+ TextBoxKeyPressHandler txtIonMatchingWindow, KeyAscii, True, True, False
+End Sub
+
+Private Sub txtIonMatchingWindow_Validate(Cancel As Boolean)
+ ValidateTextboxValueDbl txtIonMatchingWindow, 0, 100, 0.5
+
+ If Val(GetMostRecentTextBoxValue) <> Val(txtIonMatchingWindow) Then UpdateIonMatchListWrapper
+
+End Sub
+
+Private Sub txtMH_Change()
+ ConvertSequenceMH True
+End Sub
+
+Private Sub txtMH_KeyPress(KeyAscii As Integer)
+ TextBoxKeyPressHandler txtMH, KeyAscii, True, True, True, False, True, False, False, False, False, True, True
+End Sub
+
+Private Sub txtMH_Validate(Cancel As Boolean)
+ If IsNumeric(txtMH) Then
+ If CDblSafe(txtMH) < 0 Then txtMH = "0"
+ End If
+End Sub
+
+Private Sub txtMHAlt_Change()
+ ConvertSequenceMH False
+End Sub
+
+Private Sub txtMHAlt_KeyPress(KeyAscii As Integer)
+ TextBoxKeyPressHandler txtMHAlt, KeyAscii, True, True, True, False, True, False, False, False, False, True, True
+End Sub
+
+Private Sub txtMHAlt_Validate(Cancel As Boolean)
+ If IsNumeric(txtMH) Then
+ If CDblSafe(txtMH) < 0 Then txtMH = "0"
+ End If
+End Sub
+
+Private Sub txtPrecursorIonMass_GotFocus()
+ HighlightOnFocus txtPrecursorIonMass
+End Sub
+
+Private Sub txtPrecursorIonMass_KeyDown(KeyCode As Integer, Shift As Integer)
+ If KeyCode = 13 Then UpdateIonMatchListWrapper
+End Sub
+
+Private Sub txtPrecursorIonMass_KeyPress(KeyAscii As Integer)
+ TextBoxKeyPressHandler txtPrecursorIonMass, KeyAscii, True, True, False
+End Sub
+
+Private Sub txtPrecursorIonMass_Validate(Cancel As Boolean)
+ ValidateTextboxValueDbl txtPrecursorIonMass, 0, 32000, 500
+
+ If Val(GetMostRecentTextBoxValue) <> Val(txtPrecursorIonMass) Then UpdateIonMatchListWrapper
+
+End Sub
+
+Private Sub txtPrecursorMassWindow_GotFocus()
+ HighlightOnFocus txtPrecursorMassWindow
+End Sub
+
+Private Sub txtPrecursorMassWindow_KeyDown(KeyCode As Integer, Shift As Integer)
+ If KeyCode = 13 Then UpdateIonMatchListWrapper
+End Sub
+
+Private Sub txtPrecursorMassWindow_KeyPress(KeyAscii As Integer)
+ TextBoxKeyPressHandler txtPrecursorMassWindow, KeyAscii, True, True
+End Sub
+
+Private Sub txtPrecursorMassWindow_Validate(Cancel As Boolean)
+ ValidateTextboxValueDbl txtPrecursorMassWindow, 0, 100, 2
+
+ If Val(GetMostRecentTextBoxValue) <> Val(txtPrecursorMassWindow) Then UpdateIonMatchListWrapper
+
+End Sub
+
+Private Sub txtSequence_Change()
+ If mDelayUpdate Then Exit Sub
+
+ CheckSequenceTerminii
+
+ UpdatePredictedFragMasses
+End Sub
+
+Private Sub txtSequence_GotFocus()
+ HighlightOnFocus txtSequence
+End Sub
+
+Private Sub txtSequence_KeyDown(KeyCode As Integer, Shift As Integer)
+ Dim strText As String
+
+ If Shift And vbCtrlMask Then
+ If KeyCode = vbKeyC Then
+ ' Ctrl+C was used
+ ' For some reason automatic handling of Ctrl+C isn't working with txtSequence
+ ' Thus, manually copy to clipboard
+
+ strText = Mid(txtSequence.Text, txtSequence.SelStart + 1, txtSequence.SelLength)
+ Clipboard.SetText strText, vbCFText
+ End If
+ End If
+End Sub
+
+Private Sub txtSequence_KeyPress(KeyAscii As Integer)
+ PeptideSequenceKeyPressHandler txtSequence, KeyAscii
+End Sub
diff --git a/frmFragmentationModelling.frx b/frmFragmentationModelling.frx
new file mode 100644
index 0000000..e54721b
Binary files /dev/null and b/frmFragmentationModelling.frx differ
diff --git a/frmIonMatchingOptions.frm b/frmIonMatchingOptions.frm
new file mode 100644
index 0000000..80db580
--- /dev/null
+++ b/frmIonMatchingOptions.frm
@@ -0,0 +1,624 @@
+VERSION 5.00
+Begin VB.Form frmIonMatchOptions
+ BorderStyle = 3 'Fixed Dialog
+ Caption = "Ion Matching Options"
+ ClientHeight = 6960
+ ClientLeft = 45
+ ClientTop = 330
+ ClientWidth = 8250
+ HelpContextID = 3085
+ Icon = "frmIonMatchingOptions.frx":0000
+ LinkTopic = "Form1"
+ MaxButton = 0 'False
+ MinButton = 0 'False
+ ScaleHeight = 6960
+ ScaleWidth = 8250
+ ShowInTaskbar = 0 'False
+ StartUpPosition = 3 'Windows Default
+ Tag = "14000"
+ Begin VB.Frame fraPlottingOptions
+ Caption = "Spectrum Plotting Options"
+ Height = 1935
+ Left = 3960
+ TabIndex = 26
+ Tag = "14240"
+ Top = 4920
+ Width = 4215
+ Begin VB.CommandButton cmdEditAutoLabelPeaksOptions
+ Caption = "Edit Auto-Label Options"
+ Height = 360
+ Left = 960
+ TabIndex = 37
+ Tag = "14020"
+ Top = 1440
+ Width = 2115
+ End
+ Begin VB.CheckBox chkAutoLabelMass
+ Caption = "Auto-Label Peaks on Matching Ion Spectrum"
+ Height = 255
+ Left = 240
+ TabIndex = 36
+ Tag = "14270"
+ Top = 1080
+ Width = 3495
+ End
+ Begin VB.CheckBox chkPlotSpectrumInverted
+ Caption = "Plot Fragmentation Spectrum Inverted"
+ Height = 255
+ Left = 240
+ TabIndex = 27
+ Tag = "14260"
+ Top = 840
+ Width = 3495
+ End
+ Begin VB.Label lblMatchingIonDataColorLabel
+ BackStyle = 0 'Transparent
+ Caption = "Matching Ion Data Color"
+ Height = 255
+ Left = 240
+ TabIndex = 30
+ Tag = "14255"
+ Top = 525
+ Width = 2775
+ End
+ Begin VB.Label lblMatchingIonDataColor
+ BackColor = &H0000C000&
+ BorderStyle = 1 'Fixed Single
+ Height = 255
+ Left = 3120
+ TabIndex = 31
+ Tag = "14257"
+ ToolTipText = "Click to change"
+ Top = 525
+ Width = 375
+ End
+ Begin VB.Label lblFragSpectrumColorLabel
+ BackStyle = 0 'Transparent
+ Caption = "Fragmentation Data Color"
+ Height = 255
+ Left = 240
+ TabIndex = 28
+ Tag = "14250"
+ Top = 240
+ Width = 2775
+ End
+ Begin VB.Label lblFragSpectrumColor
+ BackColor = &H00FF0000&
+ BorderStyle = 1 'Fixed Single
+ Height = 255
+ Left = 3120
+ TabIndex = 29
+ Tag = "14257"
+ ToolTipText = "Click to change"
+ Top = 240
+ Width = 375
+ End
+ End
+ Begin VB.Frame fraFragSpecLabels
+ Caption = "Frgamentation Spectrum Labels"
+ Height = 1095
+ Left = 120
+ TabIndex = 22
+ Tag = "14200"
+ Top = 4920
+ Width = 3735
+ Begin VB.CheckBox chkFragSpecEmphasizeProlineYIons
+ Caption = "Emphasize Proline y ions"
+ Height = 255
+ Left = 120
+ TabIndex = 25
+ Tag = "14230"
+ Top = 720
+ Width = 3495
+ End
+ Begin VB.CheckBox chkFragSpecLabelOtherIons
+ Caption = "Label neutral loss ions"
+ Height = 255
+ Left = 120
+ TabIndex = 24
+ Tag = "14220"
+ Top = 480
+ Width = 3495
+ End
+ Begin VB.CheckBox chkFragSpecLabelMainIons
+ Caption = "Label main ions (a, b, y)"
+ Height = 255
+ Left = 120
+ TabIndex = 23
+ Tag = "14210"
+ Top = 240
+ Value = 1 'Checked
+ Width = 3495
+ End
+ End
+ Begin VB.CommandButton cmdResetToDefaults
+ Caption = "&Reset to Defaults"
+ Height = 480
+ Left = 480
+ TabIndex = 34
+ Tag = "14010"
+ Top = 6120
+ Width = 1275
+ End
+ Begin VB.CommandButton cmdOK
+ Cancel = -1 'True
+ Caption = "Cl&ose"
+ Height = 480
+ Left = 2160
+ TabIndex = 35
+ Tag = "4000"
+ Top = 6120
+ Width = 1155
+ End
+ Begin VB.Frame fraNormalization
+ Caption = "Normalization Options for Imported Data"
+ Height = 2295
+ Left = 120
+ TabIndex = 0
+ Tag = "14100"
+ Top = 120
+ Width = 3735
+ Begin VB.TextBox txtGroupIonMassWindow
+ Height = 285
+ Left = 2280
+ TabIndex = 3
+ Text = "0.5"
+ Top = 540
+ Width = 735
+ End
+ Begin VB.CheckBox chkGroupSimilarIons
+ Caption = "&Group Similar Ions (Bin Data)"
+ Height = 255
+ Left = 120
+ TabIndex = 1
+ Tag = "14110"
+ Top = 240
+ Width = 3375
+ End
+ Begin VB.TextBox txtMassRegions
+ Height = 285
+ Left = 2760
+ TabIndex = 8
+ Text = "1"
+ Top = 1440
+ Width = 800
+ End
+ Begin VB.TextBox txtIonCountToUse
+ Height = 285
+ Left = 2760
+ TabIndex = 6
+ Text = "200"
+ Top = 1080
+ Width = 800
+ End
+ Begin VB.TextBox txtNormalizedIntensity
+ Height = 285
+ Left = 2760
+ TabIndex = 10
+ Text = "100"
+ Top = 1800
+ Width = 800
+ End
+ Begin VB.Label lblGroupSimilarIons
+ Caption = "Mass Window"
+ Height = 255
+ Left = 480
+ TabIndex = 2
+ Tag = "14115"
+ Top = 570
+ Width = 1815
+ End
+ Begin VB.Label lblMassRegions
+ Caption = "Mass region subdivisions"
+ Height = 255
+ Left = 120
+ TabIndex = 7
+ Tag = "14140"
+ Top = 1440
+ Width = 2655
+ End
+ Begin VB.Label lblIonCountToUse
+ Caption = "Number of Ions to Use"
+ Height = 255
+ Left = 120
+ TabIndex = 5
+ Tag = "14130"
+ Top = 1080
+ Width = 2655
+ End
+ Begin VB.Label lblNormalizedIntensity
+ Caption = "Normalized Intensity"
+ Height = 255
+ Left = 120
+ TabIndex = 9
+ Tag = "14120"
+ Top = 1800
+ Width = 2655
+ End
+ Begin VB.Label lblGroupSimilarIonsUnits
+ Caption = "Da"
+ Height = 255
+ Left = 3120
+ TabIndex = 4
+ Tag = "12350"
+ Top = 600
+ Width = 495
+ End
+ End
+ Begin VB.Frame fraIonIntensities
+ Caption = "Ion Intensities of Predicted Ions"
+ Height = 2295
+ Left = 120
+ TabIndex = 11
+ Tag = "14150"
+ Top = 2520
+ Width = 3735
+ Begin VB.TextBox txtIonIntensity
+ Height = 285
+ Index = 0
+ Left = 2760
+ TabIndex = 13
+ Text = "10"
+ Top = 360
+ Width = 800
+ End
+ Begin VB.TextBox txtNeutralLosses
+ Height = 285
+ Left = 2760
+ TabIndex = 21
+ Text = "10"
+ Top = 1800
+ Width = 800
+ End
+ Begin VB.TextBox txtBYIonShoulders
+ Height = 285
+ Left = 2760
+ TabIndex = 19
+ Text = "25"
+ Top = 1440
+ Width = 800
+ End
+ Begin VB.TextBox txtIonIntensity
+ Height = 285
+ Index = 2
+ Left = 2760
+ TabIndex = 17
+ Text = "50"
+ Top = 1080
+ Width = 800
+ End
+ Begin VB.TextBox txtIonIntensity
+ Height = 285
+ Index = 1
+ Left = 2760
+ TabIndex = 15
+ Text = "50"
+ Top = 720
+ Width = 800
+ End
+ Begin VB.Label lblIonIntensity
+ Caption = "A Ion Intensity"
+ Height = 255
+ Index = 0
+ Left = 120
+ TabIndex = 12
+ Tag = "14160"
+ Top = 360
+ Width = 2660
+ End
+ Begin VB.Label lblNeutralLosses
+ Caption = "Neutral Losses"
+ Height = 255
+ Left = 120
+ TabIndex = 20
+ Tag = "14190"
+ Top = 1800
+ Width = 2660
+ End
+ Begin VB.Label lblBYIonShoulders
+ Caption = "B/Y Ion shoulders"
+ Height = 255
+ Left = 120
+ TabIndex = 18
+ Tag = "14180"
+ Top = 1440
+ Width = 2660
+ End
+ Begin VB.Label lblIonIntensity
+ Caption = "Y Ion Intensity"
+ Height = 255
+ Index = 2
+ Left = 120
+ TabIndex = 16
+ Tag = "14170"
+ Top = 1080
+ Width = 2660
+ End
+ Begin VB.Label lblIonIntensity
+ Caption = "B Ion Intensity"
+ Height = 255
+ Index = 1
+ Left = 120
+ TabIndex = 14
+ Tag = "14165"
+ Top = 720
+ Width = 2660
+ End
+ End
+ Begin VB.Label lblPredictedIntensityExplanation
+ Caption = $"frmIonMatchingOptions.frx":08CA
+ Height = 2055
+ Left = 4080
+ TabIndex = 33
+ Top = 2640
+ Width = 3975
+ End
+ Begin VB.Label lblNormalizationExplanation
+ Caption = $"frmIonMatchingOptions.frx":0A49
+ Height = 2175
+ Left = 4080
+ TabIndex = 32
+ Top = 240
+ Width = 3975
+ End
+End
+Attribute VB_Name = "frmIonMatchOptions"
+Attribute VB_GlobalNameSpace = False
+Attribute VB_Creatable = False
+Attribute VB_PredeclaredId = True
+Attribute VB_Exposed = False
+Option Explicit
+
+Private Sub EnableDisableControls()
+ Dim boolGroupIons As Boolean
+
+On Error GoTo EnableDisableControlsErrorHandler
+
+ boolGroupIons = cChkBox(chkGroupSimilarIons.value)
+ lblGroupSimilarIons.Enabled = boolGroupIons
+ txtGroupIonMassWindow.Enabled = boolGroupIons
+ lblGroupSimilarIonsUnits.Enabled = boolGroupIons
+
+ Exit Sub
+
+EnableDisableControlsErrorHandler:
+ GeneralErrorHandler "frmIonMatchOptions|EnableDisableControls", Err.Number, Err.Description
+
+End Sub
+
+Public Sub SetDefaultValues()
+ txtIonIntensity(0) = "10"
+ txtIonIntensity(1) = "50"
+ txtIonIntensity(2) = "50"
+ txtBYIonShoulders = "25"
+ txtNeutralLosses = "10"
+
+ With frmFragmentationModelling
+ .cboDoubleCharge.ListIndex = 8
+ .chkRemovePrecursorIon.value = vbChecked
+ .txtPrecursorMassWindow = "2"
+ .txtIonMatchingWindow = "0.5"
+ End With
+ chkGroupSimilarIons.value = vbUnchecked
+ txtGroupIonMassWindow = "0.5"
+ txtNormalizedIntensity = "100"
+ txtIonCountToUse = "200"
+ txtMassRegions = "1"
+
+ chkFragSpecLabelMainIons.value = vbChecked
+ chkFragSpecLabelOtherIons.value = vbUnchecked
+ chkFragSpecEmphasizeProlineYIons.value = vbUnchecked
+
+ chkPlotSpectrumInverted.value = vbChecked
+ chkAutoLabelMass = vbUnchecked
+
+ lblFragSpectrumColor.BackColor = RGB(0, 0, 255)
+ lblMatchingIonDataColor.BackColor = RGB(0, 128, 0)
+
+End Sub
+
+Private Sub chkFragSpecEmphasizeProlineYIons_Click()
+ frmFragmentationModelling.ResetPredictedSpectrumCRC
+ frmFragmentationModelling.DisplaySpectra
+
+ On Error Resume Next
+ chkFragSpecEmphasizeProlineYIons.SetFocus
+End Sub
+
+Private Sub chkFragSpecLabelMainIons_Click()
+ frmFragmentationModelling.ResetPredictedSpectrumCRC
+ frmFragmentationModelling.DisplaySpectra
+
+ On Error Resume Next
+ chkFragSpecLabelMainIons.SetFocus
+End Sub
+
+Private Sub chkFragSpecLabelOtherIons_Click()
+ frmFragmentationModelling.ResetPredictedSpectrumCRC
+ frmFragmentationModelling.DisplaySpectra
+
+ On Error Resume Next
+ chkFragSpecLabelOtherIons.SetFocus
+End Sub
+
+Private Sub chkGroupSimilarIons_Click()
+ EnableDisableControls
+ frmFragmentationModelling.UpdateIonMatchListWrapper
+End Sub
+
+Private Sub chkPlotSpectrumInverted_Click()
+ frmFragmentationModelling.ResetPredictedSpectrumCRC
+ frmFragmentationModelling.SetNeedToZoomOutFull True
+ frmFragmentationModelling.UpdateIonMatchListWrapper
+
+ On Error Resume Next
+ chkPlotSpectrumInverted.SetFocus
+
+End Sub
+
+Private Sub cmdEditAutoLabelPeaksOptions_Click()
+ frmFragmentationModelling.ShowAutoLabelPeaksOptions
+End Sub
+
+Private Sub cmdOK_Click()
+ Me.Hide
+End Sub
+
+Private Sub cmdResetToDefaults_Click()
+ SetDefaultValues
+End Sub
+
+Private Sub Form_Activate()
+ Dim strMessage As String
+
+ strMessage = LookupLanguageCaption(14050, "When a list of ions is imported into the program, ions of similar mass may optionally be grouped together via a binning process to reduce the total number of data points. Next, ions around the precursor ion may be removed.")
+ strMessage = strMessage & LookupLanguageCaption(14055, " Then, the intensities are normalized to the given maximum intensity and ordered by decreasing intensity. The top-most ions (number of ions to use) are divided into distinct mass regions and the ions in each region again normalized.")
+ lblNormalizationExplanation.Caption = strMessage
+
+ strMessage = LookupLanguageCaption(14060, "The masses of the predicted ions for a given peptide sequence are easily computed. However, intensity values must also be assigned to the masses.")
+ strMessage = strMessage & LookupLanguageCaption(14065, " The B and Y ions are typically assigned the same intensity while the A ion is typically 5 times less intense. Shoulder ions (masses ± 1 Da from the B and Y ions) can be added, in addition to including neutral losses (H2O, NH3, and PO4).")
+ lblPredictedIntensityExplanation.Caption = strMessage
+End Sub
+
+Private Sub Form_Load()
+
+ On Error GoTo IonMatchOptionsErrorHandler
+
+ SizeAndCenterWindow Me, cWindowTopCenter, 8350, 7360
+
+ EnableDisableControls
+
+ Exit Sub
+
+IonMatchOptionsErrorHandler:
+ GeneralErrorHandler "frmIonMatchOptions|Form_Load", Err.Number, Err.Description
+
+End Sub
+
+Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
+ QueryUnloadFormHandler Me, Cancel, UnloadMode
+End Sub
+
+Private Sub lblFragSpectrumColor_Click()
+ SelectCustomColor Me, lblFragSpectrumColor
+End Sub
+
+Private Sub lblMatchingIonDataColor_Click()
+ SelectCustomColor Me, lblMatchingIonDataColor
+End Sub
+
+Private Sub txtBYIonShoulders_GotFocus()
+ HighlightOnFocus txtBYIonShoulders
+End Sub
+
+Private Sub txtBYIonShoulders_KeyPress(KeyAscii As Integer)
+ TextBoxKeyPressHandler txtBYIonShoulders, KeyAscii, True
+End Sub
+
+Private Sub txtBYIonShoulders_Validate(Cancel As Boolean)
+ ValidateTextboxValueDbl txtBYIonShoulders, 0, 32000, 25
+End Sub
+
+Private Sub txtGroupIonMassWindow_GotFocus()
+ HighlightOnFocus txtGroupIonMassWindow
+End Sub
+
+Private Sub txtGroupIonMassWindow_KeyDown(KeyCode As Integer, Shift As Integer)
+ If KeyCode = 13 Then frmFragmentationModelling.UpdateIonMatchListWrapper
+End Sub
+
+Private Sub txtGroupIonMassWindow_KeyPress(KeyAscii As Integer)
+ TextBoxKeyPressHandler txtGroupIonMassWindow, KeyAscii, True, True, False
+End Sub
+
+Private Sub txtGroupIonMassWindow_Validate(Cancel As Boolean)
+ ValidateTextboxValueDbl txtGroupIonMassWindow, 0, 100, 0.5
+ If Val(GetMostRecentTextBoxValue) <> Val(txtGroupIonMassWindow) Then frmFragmentationModelling.UpdateIonMatchListWrapper
+End Sub
+
+Private Sub txtIonCountToUse_GotFocus()
+ HighlightOnFocus txtIonCountToUse
+End Sub
+
+Private Sub txtIonCountToUse_KeyDown(KeyCode As Integer, Shift As Integer)
+ If KeyCode = 13 Then frmFragmentationModelling.UpdateIonMatchListWrapper
+End Sub
+
+Private Sub txtIonCountToUse_KeyPress(KeyAscii As Integer)
+ TextBoxKeyPressHandler txtIonCountToUse, KeyAscii, True
+ frmFragmentationModelling.SetFragMatchSettingsChanged
+End Sub
+
+Private Sub txtIonCountToUse_Validate(Cancel As Boolean)
+ ValidateTextboxValueDbl txtIonCountToUse, 10, 32000, 200
+ If Val(GetMostRecentTextBoxValue) <> Val(txtIonCountToUse) Then frmFragmentationModelling.UpdateIonMatchListWrapper
+End Sub
+
+Private Sub txtIonIntensity_GotFocus(Index As Integer)
+ HighlightOnFocus txtIonIntensity(Index)
+End Sub
+
+Private Sub txtIonIntensity_KeyPress(Index As Integer, KeyAscii As Integer)
+ TextBoxKeyPressHandler txtIonIntensity(Index), KeyAscii, True
+End Sub
+
+Private Sub txtIonIntensity_Validate(Index As Integer, Cancel As Boolean)
+ Dim dblDefaultIntensity As Double
+
+ If Index = 0 Then
+ dblDefaultIntensity = 10
+ Else
+ dblDefaultIntensity = 50
+ End If
+
+ ValidateTextboxValueDbl txtIonIntensity(Index), 0, 32000, dblDefaultIntensity
+
+End Sub
+
+Private Sub txtMassRegions_GotFocus()
+ HighlightOnFocus txtMassRegions
+End Sub
+
+Private Sub txtMassRegions_KeyDown(KeyCode As Integer, Shift As Integer)
+ If KeyCode = 13 Then frmFragmentationModelling.UpdateIonMatchListWrapper
+End Sub
+
+Private Sub txtMassRegions_KeyPress(KeyAscii As Integer)
+ TextBoxKeyPressHandler txtMassRegions, KeyAscii, True
+ frmFragmentationModelling.SetFragMatchSettingsChanged
+End Sub
+
+Private Sub txtMassRegions_Validate(Cancel As Boolean)
+ ValidateTextboxValueDbl txtMassRegions, 0, 1000, 1
+ If Val(GetMostRecentTextBoxValue) <> Val(txtMassRegions) Then frmFragmentationModelling.UpdateIonMatchListWrapper
+End Sub
+
+Private Sub txtNeutralLosses_GotFocus()
+ HighlightOnFocus txtNeutralLosses
+End Sub
+
+Private Sub txtNeutralLosses_KeyPress(KeyAscii As Integer)
+ TextBoxKeyPressHandler txtNeutralLosses, KeyAscii, True
+End Sub
+
+Private Sub txtNeutralLosses_Validate(Cancel As Boolean)
+ ValidateTextboxValueDbl txtNeutralLosses, 0, 32000, 10
+End Sub
+
+Private Sub txtNormalizedIntensity_GotFocus()
+ HighlightOnFocus txtNormalizedIntensity
+End Sub
+
+Private Sub txtNormalizedIntensity_KeyDown(KeyCode As Integer, Shift As Integer)
+ If KeyCode = 13 Then frmFragmentationModelling.UpdateIonMatchListWrapper
+End Sub
+
+Private Sub txtNormalizedIntensity_KeyPress(KeyAscii As Integer)
+ TextBoxKeyPressHandler txtNormalizedIntensity, KeyAscii, True
+ frmFragmentationModelling.SetFragMatchSettingsChanged
+End Sub
+
+Private Sub txtNormalizedIntensity_Validate(Cancel As Boolean)
+ ValidateTextboxValueDbl txtNormalizedIntensity, 0, 32000, 100
+ If Val(GetMostRecentTextBoxValue) <> Val(txtNormalizedIntensity) Then frmFragmentationModelling.UpdateIonMatchListWrapper
+End Sub
diff --git a/frmIonMatchingOptions.frx b/frmIonMatchingOptions.frx
new file mode 100644
index 0000000..c138121
Binary files /dev/null and b/frmIonMatchingOptions.frx differ
diff --git a/frmIsotopicAbundance.frm b/frmIsotopicAbundance.frm
new file mode 100644
index 0000000..86bfa6d
--- /dev/null
+++ b/frmIsotopicAbundance.frm
@@ -0,0 +1,1223 @@
+VERSION 5.00
+Object = "{3B7C8863-D78F-101B-B9B5-04021C009402}#1.2#0"; "richtx32.ocx"
+Begin VB.Form frmIsotopicDistribution
+ Caption = "Isotopic Distribution"
+ ClientHeight = 5205
+ ClientLeft = 60
+ ClientTop = 345
+ ClientWidth = 10830
+ HelpContextID = 3100
+ Icon = "frmIsotopicAbundance.frx":0000
+ LinkTopic = "Form1"
+ ScaleHeight = 5205
+ ScaleWidth = 10830
+ StartUpPosition = 3 'Windows Default
+ Tag = "15000"
+ Begin VB.TextBox txtChargeState
+ Height = 285
+ Left = 4920
+ TabIndex = 7
+ Text = "1"
+ Top = 915
+ Width = 615
+ End
+ Begin VB.Frame fraIonComparisonList
+ Caption = "Comparison List"
+ Height = 2175
+ Left = 5640
+ TabIndex = 22
+ Tag = "15195"
+ Top = 2880
+ Width = 4575
+ Begin VB.CheckBox chkComparisonListNormalize
+ Caption = "Normalize pasted ion list"
+ Height = 255
+ Left = 120
+ TabIndex = 31
+ Tag = "15105"
+ Top = 1000
+ Value = 1 'Checked
+ Width = 2295
+ End
+ Begin VB.CommandButton cmdComparisonListClear
+ Caption = "Clear list"
+ Height = 375
+ Left = 2880
+ TabIndex = 28
+ Tag = "15165"
+ Top = 1320
+ Width = 1455
+ End
+ Begin VB.CommandButton cmdComparisonListPaste
+ Caption = "Paste list of ions to plot"
+ Height = 375
+ Left = 120
+ TabIndex = 27
+ Tag = "15160"
+ Top = 1320
+ Width = 2535
+ End
+ Begin VB.ComboBox cboComparisonListPlotType
+ Height = 315
+ Left = 2040
+ Style = 2 'Dropdown List
+ TabIndex = 26
+ Tag = "15140"
+ Top = 630
+ Width = 2295
+ End
+ Begin VB.Label lblComparisonListDataPoints
+ Caption = "0"
+ Height = 255
+ Left = 2640
+ TabIndex = 30
+ Top = 1800
+ Width = 615
+ End
+ Begin VB.Label lblComparisonListDataPointsLabel
+ Caption = "Comparison list data points:"
+ Height = 255
+ Left = 120
+ TabIndex = 29
+ Tag = "15170"
+ Top = 1800
+ Width = 2415
+ End
+ Begin VB.Label lblComparisonListPlotColorLabel
+ BackStyle = 0 'Transparent
+ Caption = "Plot Data Color"
+ Height = 255
+ Left = 120
+ TabIndex = 23
+ Tag = "15120"
+ Top = 300
+ Width = 1935
+ End
+ Begin VB.Label lblComparisonListPlotColor
+ BackColor = &H000000FF&
+ BorderStyle = 1 'Fixed Single
+ Height = 255
+ Left = 2040
+ TabIndex = 24
+ Tag = "15125"
+ ToolTipText = "Click to change"
+ Top = 300
+ Width = 375
+ End
+ Begin VB.Label lblComparisonListPlotType
+ BackStyle = 0 'Transparent
+ Caption = "Plot Type"
+ Height = 255
+ Left = 120
+ TabIndex = 25
+ Tag = "15130"
+ Top = 660
+ Width = 1935
+ End
+ End
+ Begin VB.Frame fraPlotOptions
+ Caption = "Options"
+ Height = 2655
+ Left = 5640
+ TabIndex = 9
+ Tag = "15190"
+ Top = 120
+ Width = 4575
+ Begin VB.TextBox txtEffectiveResolutionMass
+ Height = 300
+ Left = 3000
+ TabIndex = 19
+ Text = "1000"
+ Top = 1770
+ Width = 855
+ End
+ Begin VB.TextBox txtEffectiveResolution
+ Height = 300
+ Left = 3000
+ TabIndex = 17
+ Text = "5000"
+ Top = 1440
+ Width = 855
+ End
+ Begin VB.TextBox txtGaussianQualityFactor
+ Height = 300
+ Left = 3000
+ TabIndex = 21
+ Text = "50"
+ Top = 2190
+ Width = 855
+ End
+ Begin VB.ComboBox cboPlotType
+ Height = 315
+ Left = 2040
+ Style = 2 'Dropdown List
+ TabIndex = 15
+ Tag = "15140"
+ Top = 960
+ Width = 2295
+ End
+ Begin VB.CheckBox chkPlotResults
+ Caption = "&Plot Results"
+ Height = 255
+ Left = 120
+ TabIndex = 10
+ Tag = "15100"
+ Top = 300
+ Value = 1 'Checked
+ Width = 1695
+ End
+ Begin VB.CheckBox chkAutoLabelPeaks
+ Caption = "&Auto-Label Peaks"
+ Height = 255
+ Left = 2040
+ TabIndex = 11
+ Tag = "15105"
+ Top = 300
+ Width = 2295
+ End
+ Begin VB.Label lblEffectiveResolutionMass
+ BackStyle = 0 'Transparent
+ Caption = "Effective Resolution M/Z"
+ Height = 255
+ Left = 120
+ TabIndex = 18
+ Tag = "15130"
+ Top = 1800
+ Width = 2655
+ End
+ Begin VB.Label lblEffectiveResolution
+ BackStyle = 0 'Transparent
+ Caption = "Effective Resolution"
+ Height = 255
+ Left = 120
+ TabIndex = 16
+ Tag = "15130"
+ Top = 1470
+ Width = 2655
+ End
+ Begin VB.Label lblGaussianQualityFactor
+ BackStyle = 0 'Transparent
+ Caption = "Gaussian Quality Factor"
+ Height = 255
+ Left = 120
+ TabIndex = 20
+ Tag = "15130"
+ Top = 2220
+ Width = 2655
+ End
+ Begin VB.Label lblPlotType
+ BackStyle = 0 'Transparent
+ Caption = "Plot Type"
+ Height = 255
+ Left = 120
+ TabIndex = 14
+ Tag = "15130"
+ Top = 990
+ Width = 1935
+ End
+ Begin VB.Label lblPlotColor
+ BackColor = &H00FF0000&
+ BorderStyle = 1 'Fixed Single
+ Height = 255
+ Left = 2040
+ TabIndex = 13
+ Tag = "15125"
+ ToolTipText = "Click to change"
+ Top = 630
+ Width = 375
+ End
+ Begin VB.Label lblPlotColorLabel
+ BackStyle = 0 'Transparent
+ Caption = "Plot Data Color"
+ Height = 255
+ Left = 120
+ TabIndex = 12
+ Tag = "15120"
+ Top = 630
+ Width = 1935
+ End
+ End
+ Begin VB.CommandButton cmdCopy
+ Caption = "Cop&y"
+ Height = 375
+ Left = 1320
+ TabIndex = 3
+ Tag = "10340"
+ Top = 840
+ Width = 1095
+ End
+ Begin RichTextLib.RichTextBox rtfFormula
+ Height = 495
+ Left = 1560
+ TabIndex = 1
+ Tag = "5050"
+ ToolTipText = "Type the molecular formula here."
+ Top = 120
+ Width = 3015
+ _ExtentX = 5318
+ _ExtentY = 873
+ _Version = 393217
+ MultiLine = 0 'False
+ TextRTF = $"frmIsotopicAbundance.frx":08CA
+ BeginProperty Font {0BE35203-8F91-11CE-9DE3-00AA004BB851}
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 700
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ End
+ Begin VB.TextBox txtResults
+ BeginProperty Font
+ Name = "Courier"
+ Size = 9.75
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 3255
+ Left = 120
+ Locked = -1 'True
+ MultiLine = -1 'True
+ ScrollBars = 2 'Vertical
+ TabIndex = 8
+ Tag = "15150"
+ ToolTipText = "Isotopic distribution results"
+ Top = 1680
+ Width = 5415
+ End
+ Begin VB.CommandButton cmdCompute
+ Caption = "&Compute"
+ Default = -1 'True
+ Height = 375
+ Left = 120
+ TabIndex = 2
+ Tag = "15110"
+ Top = 840
+ Width = 1095
+ End
+ Begin VB.CommandButton cmdClose
+ Cancel = -1 'True
+ Caption = "Cl&ose"
+ Height = 375
+ Left = 2520
+ TabIndex = 4
+ Tag = "4000"
+ Top = 840
+ Width = 1095
+ End
+ Begin VB.Label lblChargeState
+ Alignment = 1 'Right Justify
+ Caption = "C&harge state:"
+ Height = 255
+ Left = 3480
+ TabIndex = 6
+ Tag = "15070"
+ Top = 930
+ Width = 1335
+ End
+ Begin VB.Label lblResults
+ Caption = "Results:"
+ Height = 255
+ Left = 120
+ TabIndex = 5
+ Tag = "15060"
+ Top = 1320
+ Width = 1455
+ End
+ Begin VB.Label lblFormula
+ Caption = "&Formula:"
+ Height = 255
+ Left = 120
+ TabIndex = 0
+ Tag = "15050"
+ Top = 240
+ Width = 1455
+ End
+End
+Attribute VB_Name = "frmIsotopicDistribution"
+Attribute VB_GlobalNameSpace = False
+Attribute VB_Creatable = False
+Attribute VB_PredeclaredId = True
+Attribute VB_Exposed = False
+Option Explicit
+
+Private WithEvents objSpectrum As CWSpectrumDLL.Spectrum
+Attribute objSpectrum.VB_VarHelpID = -1
+
+Private Const MAX_SERIES_COUNT = 2
+Private Const GAUSSIAN_CONVERSION_DATACOUNT_WARNING_THRESHOLD = 1000
+
+Private Enum ipmIsotopicPlotModeConstants
+ ipmSticksToZero = 0
+ ipmGaussian = 1
+ ipmContinuousData = 2 ' Used for raw, uncentered data
+End Enum
+
+Private Enum lcwfLastControlWithFocusConstants
+ lcwfFormula = 0
+ lcwfEffectiveResolution = 1
+ lcwfEffectiveResolutionMass = 2
+ lcwfGaussianQualityFactor = 3
+ lcwfChargeState = 4
+End Enum
+
+Private ConvolutedMSDataCount As Long
+Private ConvolutedMSData2D() As Double ' 1-based array (since it is 1-based in the Dll)
+
+Private ComparisonListDataCount As Long
+Private ComparisonListXVals() As Double ' 0-based array
+Private ComparisonListYVals() As Double ' 0-based array
+
+Private CRCForPredictedSpectrumSaved As Double
+Private CRCForComparisonIonListSaved As Double
+Private mNeedToZoomOutFull As Boolean
+
+Private mLastControlWithFocus As lcwfLastControlWithFocusConstants
+
+Private mFormActivatedByUser As Boolean ' Set true the first time the user activates the form; always true from then on
+ ' Used to prevent plotting the mass spectrum until after the user has activated the isotopic distribution form at least once
+
+Private mUserWarnedLargeDataSetForGaussianConversion As Boolean
+Private mDelayUpdatingPlot As Boolean
+
+Private Sub ComparisonIonListClear()
+ ComparisonListDataCount = 0
+ ReDim ComparisonListXVals(0)
+ ReDim ComparisonListYVals(0)
+ UpdateComparisonListStatus
+
+ PlotIsotopicDistribution
+
+End Sub
+
+Private Sub ComparisonIonListPaste()
+
+ Dim strIonList As String, strLineWork As String
+ Dim blnAllowCommaDelimeter As Boolean
+ Dim lngCrLfLoc As Long, lngValuesToPopulate As Long
+ Dim lngIndex As Long, lngStartIndex As Long
+ Dim strDelimeter As String, intDelimeterLength As Integer
+
+ Dim strLeftChar As String, strDelimeterList As String
+ Dim dblParsedVals() As Double ' 0-based array
+ Dim intParseValCount As Integer
+ Dim dblMaximumIntensity As Double
+
+On Error GoTo ComparisonIonListPasteErrorHandler
+
+'' ' Warn user about replacing data
+'' If Not QueryExistingIonsInList() Then Exit Sub
+
+ ' Grab text from clipboard
+ strIonList = GetClipboardTextSmart()
+
+ If Len(strIonList) = 0 Then
+ MsgBox LookupMessage(980), vbInformation + vbOKOnly, LookupMessage(985)
+ Exit Sub
+ End If
+
+ ' Determine if commas are used for the decimal point in this locale
+ If DetermineDecimalPoint() = "," Then
+ blnAllowCommaDelimeter = False
+ Else
+ blnAllowCommaDelimeter = True
+ End If
+
+ frmProgress.InitializeForm LookupMessage(990), 0, Len(strIonList)
+ frmProgress.ToggleAlwaysOnTop True
+ frmProgress.UpdateCurrentSubTask LookupMessage(1000)
+
+ ' First Determine number of data points in strIonList
+ ' This isn't necessary (while it is necessary in frmFragmentationModelling.PasteIonMatchList),
+ ' but it doesn't take that much time and allows this code to be nearly identical to the frmFragmentationModelling code
+
+ ' First look for the first occurrence of a valid delimeter
+ lngCrLfLoc = ParseStringFindCrlfIndex(strIonList, intDelimeterLength)
+
+ If lngCrLfLoc > 0 Then
+ ' Record the first character of the delimeter (if vbCrLf, then recording vbCr), otherwise, recording just vbCr or just vbLf)
+ strDelimeter = Mid(strIonList, lngCrLfLoc, 1)
+
+ ' Now determine the number of occurrences of the delimeter
+ lngValuesToPopulate = 0
+ For lngIndex = 1 To Len(strIonList)
+ If lngIndex Mod 500 = 0 Then
+ frmProgress.UpdateProgressBar lngIndex
+ If KeyPressAbortProcess > 1 Then Exit For
+ End If
+
+ If Mid(strIonList, lngIndex, 1) = strDelimeter Then
+ lngValuesToPopulate = lngValuesToPopulate + 1
+ End If
+ Next lngIndex
+
+ If lngValuesToPopulate > 1 And KeyPressAbortProcess = 0 Then
+ ' Update frmProgress to use the correct progress bar size
+ frmProgress.InitializeForm LookupMessage(990), 0, lngValuesToPopulate
+ frmProgress.UpdateCurrentSubTask LookupMessage(1010)
+ End If
+
+ ' Initialize IonMatchList
+ ComparisonListDataCount = 0
+ ReDim ComparisonListXVals(lngValuesToPopulate)
+ ReDim ComparisonListYVals(lngValuesToPopulate)
+
+ ' Construct Delimeter List: Contains a space, Tab, and possibly comma
+ strDelimeterList = " " & vbTab & vbCr & vbLf
+ If blnAllowCommaDelimeter Then
+ strDelimeterList = strDelimeterList & ","
+ End If
+
+ ' Initialize dblMaximumIntensity
+ dblMaximumIntensity = LowestValueForDoubleDataType
+
+ ' Actually parse the data
+ ' I process the list using the Mid() function since this is the fastest method
+ ' However, Mid() becomes slower when the index value reaches 1000 or more (roughly)
+ ' so I discard already-parsed data from strIonList every 1000 characters (approximately)
+ Do While Len(strIonList) > 0
+ lngStartIndex = 1
+ For lngIndex = 1 To Len(strIonList)
+ If lngIndex Mod 100 = 0 Then
+ frmProgress.UpdateProgressBar ComparisonListDataCount
+ If KeyPressAbortProcess > 1 Then Exit For
+ End If
+
+ If Mid(strIonList, lngIndex, 1) = strDelimeter Then
+ strLineWork = Mid(strIonList, lngStartIndex, lngIndex - 1)
+
+ If Len(strLineWork) > 0 Then
+
+ ' Only parse if the first letter (trimmed) is a number (may start with - or +)
+ strLeftChar = Left(strLineWork, 1)
+ If IsNumeric(strLeftChar) Or strLeftChar = "-" Or strLeftChar = "+" Then
+ intParseValCount = ParseStringValuesDbl(strLineWork, dblParsedVals(), 2, strDelimeterList, , False, False, False)
+
+ If intParseValCount >= 2 Then
+ If dblParsedVals(0) <> 0 And dblParsedVals(0) <> 0 Then
+ If dblParsedVals(1) > dblMaximumIntensity Then
+ dblMaximumIntensity = dblParsedVals(1)
+ End If
+
+ ComparisonListXVals(ComparisonListDataCount) = dblParsedVals(0)
+ ComparisonListYVals(ComparisonListDataCount) = dblParsedVals(1)
+ ComparisonListDataCount = ComparisonListDataCount + 1
+
+
+ If ComparisonListDataCount > lngValuesToPopulate Then
+ ' This shouldn't happen
+ Debug.Assert False
+ Exit Do
+ End If
+ End If
+ End If
+ End If
+
+ End If
+
+ lngStartIndex = lngIndex + intDelimeterLength
+ lngIndex = lngIndex + intDelimeterLength - 1
+
+ If lngIndex > 1000 Then
+ ' Reduce the size of strIonList since the Mid() function gets slower with longer strings
+ strIonList = Mid(strIonList, lngIndex + 1)
+ lngIndex = 1
+ Exit For
+ End If
+ End If
+ Next lngIndex
+ If lngIndex > Len(strIonList) Then Exit Do
+ Loop
+ End If
+
+ frmProgress.HideForm
+ If ComparisonListDataCount > 0 And KeyPressAbortProcess = 0 Then
+
+ If dblMaximumIntensity <> 0 And cChkBox(chkComparisonListNormalize) Then
+ ' Normalize the Comparison ion list to 100
+ For lngIndex = 0 To ComparisonListDataCount - 1
+ ComparisonListYVals(lngIndex) = ComparisonListYVals(lngIndex) / dblMaximumIntensity * 100
+ Next lngIndex
+ End If
+
+ PlotIsotopicDistribution False
+ Else
+ If KeyPressAbortProcess = 0 Then
+ MsgBox LookupMessage(1020), vbInformation + vbOKOnly, LookupMessage(985)
+ Else
+ MsgBox LookupMessage(940), vbInformation + vbOKOnly, LookupMessage(945)
+ End If
+ End If
+
+ UpdateComparisonListStatus
+
+ Exit Sub
+
+ComparisonIonListPasteErrorHandler:
+ frmProgress.HideForm
+ UpdateComparisonListStatus
+ GeneralErrorHandler "frmIsotopicDistribution|ComparisonIonListPaste", Err.Number, Err.Description
+
+End Sub
+
+Private Sub CopyResults()
+
+ Clipboard.Clear
+ Clipboard.SetText txtResults, vbCFText
+
+End Sub
+
+Public Sub EnableDisablePlotUpdates(blnDisableUpdating As Boolean)
+ mDelayUpdatingPlot = blnDisableUpdating
+ If Not blnDisableUpdating Then
+ PlotIsotopicDistribution True
+ End If
+End Sub
+
+Private Sub PlotIsotopicDistribution(Optional blnIgnoreCRC As Boolean = False)
+ Dim lngIndex As Long
+
+ Static blnSeriesPlotModeInitialized(MAX_SERIES_COUNT) As Boolean
+ Static blnUpdatingPlot As Boolean
+
+ Dim PredictedSpectrumCRC As Double
+ Dim dblMassTimesIntensity As Double
+ Dim blnUpdatePlot As Boolean
+ Dim blnAllowResumeNextErrorHandling As Boolean
+
+ Dim dblXVals() As Double ' 0-based array
+ Dim dblYVals() As Double ' 0-based array
+ Dim lngDataCount As Long
+
+ Dim intSeriesNumber As Integer
+ Dim strLegendCaption As String
+ Dim eIsoPlotMode As ipmIsotopicPlotModeConstants
+ Dim lngPlotColor As Long
+
+ Dim eResponse As VbMsgBoxResult
+ Dim strMessage As String
+ Dim blnCursorVisibilitySaved As Boolean
+ Dim blnAutoHideCaptionsSaved As Boolean
+
+ If Not mFormActivatedByUser Or mDelayUpdatingPlot Then Exit Sub
+
+On Error GoTo PlotIsotopicDistributionErrorHandler
+
+ blnAllowResumeNextErrorHandling = True
+
+ ' Compute a CRC value for the current PredictedSpectrum() array and compare to the previously computed value
+ PredictedSpectrumCRC = 0
+ For lngIndex = 1 To ConvolutedMSDataCount
+ dblMassTimesIntensity = Abs((lngIndex) * ConvolutedMSData2D(lngIndex, 0) * ConvolutedMSData2D(lngIndex, 1))
+ If dblMassTimesIntensity > 0 Then
+ PredictedSpectrumCRC = PredictedSpectrumCRC + Log(dblMassTimesIntensity)
+ End If
+ Next lngIndex
+
+ ' If the new CRC is different than the old one then re-plot the spectrun
+ If PredictedSpectrumCRC <> CRCForPredictedSpectrumSaved Then
+ CRCForPredictedSpectrumSaved = PredictedSpectrumCRC
+ blnUpdatePlot = True
+ End If
+
+ ' Also compute a CRC value for the Comparison Ion List and compare to the previously computed value
+ PredictedSpectrumCRC = 0
+ For lngIndex = 0 To ComparisonListDataCount - 1
+ dblMassTimesIntensity = Abs(lngIndex * ComparisonListXVals(lngIndex) * ComparisonListYVals(lngIndex))
+ If dblMassTimesIntensity > 0 Then
+ PredictedSpectrumCRC = PredictedSpectrumCRC + Log(dblMassTimesIntensity)
+ End If
+ Next lngIndex
+
+ ' If the new CRC is different than the old one then re-plot the spectrun
+ If PredictedSpectrumCRC <> CRCForComparisonIonListSaved Then
+ CRCForComparisonIonListSaved = PredictedSpectrumCRC
+ blnUpdatePlot = True
+ End If
+
+ If blnIgnoreCRC Then blnUpdatePlot = True
+
+ If Not blnUpdatePlot Then
+ Exit Sub
+ End If
+
+ If blnUpdatingPlot Then Exit Sub
+ blnUpdatingPlot = True
+
+ blnAllowResumeNextErrorHandling = False
+
+ objSpectrum.ShowSpectrum
+
+ ' Hide the Cursor and disable auto-hiding of annotations
+ blnCursorVisibilitySaved = objSpectrum.GetCursorVisibility()
+ If blnCursorVisibilitySaved Then objSpectrum.SetCursorVisible False
+
+ blnAutoHideCaptionsSaved = objSpectrum.GetAnnotationDensityAutoHideCaptions()
+ If blnAutoHideCaptionsSaved Then objSpectrum.SetAnnotationDensityAutoHideCaptions False, False
+
+ If ConvolutedMSDataCount > 0 Then
+ lngDataCount = ConvolutedMSDataCount
+ ReDim dblXVals(0 To lngDataCount - 1)
+ ReDim dblYVals(0 To lngDataCount - 1)
+
+ ' Now fill dblXVals() and dblYVals()
+ ' ConvolutedMSData2D() is 1-based, but dblXVals() and dblYVals() are 0-based
+ For lngIndex = 1 To lngDataCount
+ dblXVals(lngIndex - 1) = ConvolutedMSData2D(lngIndex, 0)
+ dblYVals(lngIndex - 1) = ConvolutedMSData2D(lngIndex, 1)
+ Next lngIndex
+ Else
+ lngDataCount = 0
+ End If
+
+ ' First plot the theoretical isotopic distribution
+ intSeriesNumber = 1
+ strLegendCaption = rtfFormula.Text
+ eIsoPlotMode = cboPlotType.ListIndex
+ lngPlotColor = lblPlotColor.BackColor
+ PlotIsotopicDistributionWork objSpectrum, intSeriesNumber, lngDataCount, dblXVals(), dblYVals(), strLegendCaption, blnSeriesPlotModeInitialized(), eIsoPlotMode, lngPlotColor
+
+ ' Now plot the comparison ion list (will clear series 2 if list is empty)
+ intSeriesNumber = 2
+ strLegendCaption = "Comparison List"
+ eIsoPlotMode = cboComparisonListPlotType.ListIndex
+ lngPlotColor = lblComparisonListPlotColor.BackColor
+
+ ' Need to copy the data from CaprisonListXVals() to dblXVals() since the Gaussian conversion operation changes the array
+ If ComparisonListDataCount > 0 Then
+ lngDataCount = ComparisonListDataCount
+ ReDim dblXVals(0 To UBound(ComparisonListXVals()))
+ dblXVals() = ComparisonListXVals()
+ dblYVals() = ComparisonListYVals()
+ Else
+ lngDataCount = 0
+ End If
+
+ ' Check for large number of data points when Gaussian mode is enabled
+ If eIsoPlotMode = ipmGaussian And lngDataCount > GAUSSIAN_CONVERSION_DATACOUNT_WARNING_THRESHOLD Then
+ If Not mUserWarnedLargeDataSetForGaussianConversion Then
+ strMessage = LookupLanguageCaption(15300, "Warning, the ion comparison list contains a large number of data points. Do you really want to convert each point to a Gaussian curve?")
+ eResponse = MsgBox(strMessage, vbQuestion + vbYesNoCancel + vbDefaultButton2, LookupLanguageCaption(15305, "Large Data Point Count"))
+
+ If eResponse = vbYes Then
+ mUserWarnedLargeDataSetForGaussianConversion = True
+ ElseIf eResponse = vbCancel Then
+ lngDataCount = 0
+ Else
+ ' Switch to Continuous Data mode
+ eIsoPlotMode = ipmContinuousData
+ cboComparisonListPlotType.ListIndex = eIsoPlotMode
+ End If
+ End If
+ End If
+
+ PlotIsotopicDistributionWork objSpectrum, intSeriesNumber, lngDataCount, dblXVals(), dblYVals(), strLegendCaption, blnSeriesPlotModeInitialized(), eIsoPlotMode, lngPlotColor
+
+ With objSpectrum
+ If mNeedToZoomOutFull Then
+ .ZoomOutFull
+ mNeedToZoomOutFull = False
+ End If
+
+ .SetCursorPosition 100, 0
+
+ ' Auto-hiding of captions was disabled above; re-enable if necessary
+ .SetAnnotationDensityAutoHideCaptions blnAutoHideCaptionsSaved
+
+ ' The cursor was hidden above; re-show it if necessary
+ If blnCursorVisibilitySaved Then
+ .SetCursorVisible True
+ End If
+
+ .SetSpectrumFormCurrentSeriesNumber 1
+
+ .ShowSpectrum
+ End With
+
+ ' Return the focus back to this form (if possible)
+ On Error Resume Next
+ Select Case mLastControlWithFocus
+ Case lcwfFormula
+ rtfFormula.SetFocus
+ Case lcwfEffectiveResolution
+ txtEffectiveResolution.SetFocus
+ Case lcwfEffectiveResolutionMass
+ txtEffectiveResolutionMass.SetFocus
+ Case lcwfGaussianQualityFactor
+ txtGaussianQualityFactor.SetFocus
+ Case lcwfChargeState
+ txtChargeState.SetFocus
+ Case Else
+ Me.SetFocus
+ End Select
+
+ blnUpdatingPlot = False
+
+ Exit Sub
+
+PlotIsotopicDistributionErrorHandler:
+ If blnAllowResumeNextErrorHandling Then
+ ' Something is probably wrong with the CRC computation routines
+ Debug.Assert False
+ Resume Next
+ Else
+ GeneralErrorHandler "frmIsotopicDistribution|PlotIsotopicDistribution", Err.Number, Err.Description
+ End If
+ blnUpdatingPlot = False
+
+End Sub
+
+Private Sub PlotIsotopicDistributionWork(objThisCWSpectrum As CWSpectrumDLL.Spectrum, intSeriesNumber As Integer, lngDataCount As Long, dblXVals() As Double, dblYVals() As Double, strLegendCaption As String, blnSeriesPlotModeInitialized() As Boolean, eIsoPlotMode As ipmIsotopicPlotModeConstants, lngPlotColor As Long)
+
+ Dim lngResolution As Long, lngResolutionMass As Long
+ Dim lngQualityFactor As Long
+
+ Dim udtAutoLabelPeaksSettings As udtAutoLabelPeaksOptionsType
+ Dim dblMinimum As Double, dblMaximum As Double
+ Dim ePlotMode As pmPlotModeConstants
+
+On Error GoTo PlotIsotopicDistributionWorkErrorHandler
+
+ If eIsoPlotMode = ipmGaussian Then
+ lngResolution = CLngSafe(txtEffectiveResolution)
+ lngResolutionMass = CLngSafe(txtEffectiveResolutionMass)
+ lngQualityFactor = CIntSafe(txtGaussianQualityFactor)
+
+ ValidateValueLng lngResolution, 1, 1000000000#, 5000
+ ValidateValueLng lngQualityFactor, 1, 75, 50
+ ValidateValueLng lngResolutionMass, 1, 1000000000#, 1000
+
+ ' Note that dblXVals() and dblYVals() will be replaced with Gaussian representations of the peaks by the following function
+ ConvertStickDataToGaussian2DArray Me, dblXVals(), dblYVals(), lngDataCount, lngResolution, lngResolutionMass, CInt(lngQualityFactor)
+ End If
+
+ If eIsoPlotMode = ipmSticksToZero Then
+ ePlotMode = pmStickToZero
+ Else
+ ePlotMode = pmLines
+ End If
+
+ With objThisCWSpectrum
+ If .GetSeriesCount() < intSeriesNumber Then
+ .SetSeriesCount intSeriesNumber
+ End If
+
+ If Not blnSeriesPlotModeInitialized(intSeriesNumber) Then
+ .SetSeriesPlotMode intSeriesNumber, pmStickToZero, False
+ blnSeriesPlotModeInitialized(intSeriesNumber) = True
+ End If
+
+ .ClearData intSeriesNumber
+ If lngDataCount > 0 Then
+ ' Normal data
+ .SetSeriesColor intSeriesNumber, lngPlotColor
+
+ .SetDataXvsY intSeriesNumber, dblXVals(), dblYVals(), lngDataCount, strLegendCaption
+
+ .SetSeriesPlotMode intSeriesNumber, ePlotMode, False
+
+ If cChkBox(chkAutoLabelPeaks) Then
+ udtAutoLabelPeaksSettings = .GetAutoLabelPeaksOptions()
+
+ udtAutoLabelPeaksSettings.DisplayXPos = True
+ udtAutoLabelPeaksSettings.IsContinuousData = (ePlotMode = pmLines)
+
+ .SetAutoLabelPeaksOptions udtAutoLabelPeaksSettings
+ .AutoLabelPeaks intSeriesNumber, udtAutoLabelPeaksSettings.DisplayXPos, udtAutoLabelPeaksSettings.DisplayYPos, udtAutoLabelPeaksSettings.CaptionAngle, udtAutoLabelPeaksSettings.IncludeArrow, udtAutoLabelPeaksSettings.HideInDenseRegions, udtAutoLabelPeaksSettings.PeakLabelCountMaximum
+ End If
+
+ .SetSpectrumFormCurrentSeriesNumber intSeriesNumber
+
+ .GetRangeX dblMinimum, dblMaximum
+
+ If dblXVals(0) < dblMinimum Or dblXVals(0) > dblMaximum Then mNeedToZoomOutFull = True
+ If dblXVals(lngDataCount - 1) < dblMinimum Or dblXVals(lngDataCount - 1) > dblMaximum Then mNeedToZoomOutFull = True
+ End If
+ End With
+
+ Exit Sub
+
+PlotIsotopicDistributionWorkErrorHandler:
+ GeneralErrorHandler "frmIsotopicDistribution|PlotIsotopicDistributionWork", Err.Number, Err.Description
+
+End Sub
+
+Private Sub PositionFormControls()
+ Dim lngPreferredValue As Long
+
+On Error GoTo PositionFormControlsErrorHandler
+
+ With fraPlotOptions
+ lngPreferredValue = Me.ScaleWidth - .Width - 120
+ If lngPreferredValue < 5500 Then lngPreferredValue = 5500
+ .Left = lngPreferredValue
+ End With
+
+ fraIonComparisonList.Left = fraPlotOptions.Left
+
+ rtfFormula.Width = fraPlotOptions.Left - rtfFormula.Left - 120
+
+ With txtResults
+ .Top = lblResults.Top + 360
+ .Left = 120
+
+ lngPreferredValue = fraPlotOptions.Left - .Left - 120
+ If lngPreferredValue < 2000 Then
+ ' This shouldn't happen
+ Debug.Assert False
+ lngPreferredValue = 2000
+ End If
+ .Width = lngPreferredValue
+
+ lngPreferredValue = Me.ScaleHeight - .Top - 120
+ If lngPreferredValue < 1000 Then lngPreferredValue = 1000
+ .Height = lngPreferredValue
+ End With
+
+ lngPreferredValue = txtResults.Left + txtResults.Width - txtChargeState.Width
+ If lngPreferredValue < lblResults.Left + lblResults.Width + lblChargeState.Width Then
+ lngPreferredValue = lblResults.Left + lblResults.Width + lblChargeState.Width
+ End If
+ txtChargeState.Left = lngPreferredValue
+ lblChargeState.Left = txtChargeState.Left - lblChargeState.Width - 60
+
+ Exit Sub
+
+PositionFormControlsErrorHandler:
+ Debug.Assert False
+ Resume Next
+
+End Sub
+
+Private Function QueryExistingIonsInList() As Boolean
+ Dim strMessage As String, eResponse As VbMsgBoxResult
+
+ If ComparisonListDataCount > 0 Then
+ strMessage = LookupMessage(910)
+ eResponse = MsgBox(strMessage, vbQuestion + vbYesNoCancel + vbDefaultButton3, LookupMessage(920))
+ If eResponse = vbYes Then
+ QueryExistingIonsInList = True
+ Else
+ QueryExistingIonsInList = False
+ End If
+ Else
+ QueryExistingIonsInList = True
+ End If
+
+End Function
+
+Public Sub ResetCWSpectrumOptions()
+ If cboComparisonListPlotType.ListIndex = ipmGaussian Then
+ objSpectrum.ResetOptionsToDefaults True, True, 2, pmLines
+ Else
+ objSpectrum.ResetOptionsToDefaults True, True, 2, pmStickToZero
+ End If
+End Sub
+
+Private Sub ResetPredictedSpectrumCRC()
+ CRCForPredictedSpectrumSaved = 0
+End Sub
+
+Public Sub SetFormActivated()
+ mFormActivatedByUser = True
+End Sub
+
+Public Sub SetNeedToZoomOutFull(blnEnable As Boolean)
+ mNeedToZoomOutFull = blnEnable
+End Sub
+
+Public Sub StartIsotopicDistributionCalcs(blnSetFocusOnTextbox As Boolean, Optional blnSetFocusOnChargeTextbox As Boolean = False)
+ Dim strResults As String, lngErrorID As Long
+ Dim strFormula As String
+ Dim strHeaderIsotopicAbundace As String, strHeaderMass As String
+ Dim strHeaderFraction As String, strHeaderIntensity As String
+ Dim lngCursorPos As Long
+
+ Dim intChargeState As Integer
+
+On Error GoTo StartIsotopicDistributionCalcsErrorHandler
+
+ strFormula = rtfFormula.Text
+ lngCursorPos = rtfFormula.SelStart
+
+ If Len(Trim(strFormula)) = 0 Then Exit Sub
+
+ RemoveHeightAdjustChar strFormula
+
+ Me.MousePointer = vbHourglass
+
+ If IsNumeric(txtChargeState) Then
+ intChargeState = Val(txtChargeState)
+ If intChargeState < 0 Then intChargeState = 1
+ If intChargeState >= 10000 Then intChargeState = 10000
+ Else
+ intChargeState = 1
+ End If
+
+ strHeaderIsotopicAbundace = LookupLanguageCaption(15200, "Isotopic Abundances for")
+ If intChargeState = 0 Then
+ strHeaderMass = LookupLanguageCaption(15215, "Neutral Mass")
+ Else
+ strHeaderMass = LookupLanguageCaption(15210, "Mass/Charge")
+ End If
+
+ strHeaderFraction = LookupLanguageCaption(15220, "Fraction")
+ strHeaderIntensity = LookupLanguageCaption(15230, "Intensity")
+
+ ' Make sure we're using isotopic masses
+ SwitchWeightMode emIsotopicMass
+
+ ' Note: strFormula is passed ByRef
+ lngErrorID = objMwtWin.ComputeIsotopicAbundances(strFormula, intChargeState, strResults, ConvolutedMSData2D(), ConvolutedMSDataCount, strHeaderIsotopicAbundace, strHeaderMass, strHeaderFraction, strHeaderIntensity)
+
+ If lngErrorID = 0 Then
+ ' Update rtfFormula with the capitalized formula
+ rtfFormula = strFormula
+
+ If cChkBox(chkPlotResults.value) Then
+ PlotIsotopicDistribution
+ End If
+ ElseIf lngErrorID <> -1 Then
+ MsgBox LookupMessage(lngErrorID), vbOKOnly + vbExclamation, LookupMessage(350)
+ End If
+
+ txtResults = strResults
+ txtResults.Font = "Courier"
+
+ rtfFormula = strFormula
+ If lngCursorPos <= Len(strFormula) Then
+ rtfFormula.SelStart = lngCursorPos
+ End If
+
+ Me.MousePointer = vbNormal
+
+ If blnSetFocusOnTextbox Then
+ rtfFormula.SetFocus
+ ElseIf blnSetFocusOnChargeTextbox Then
+ txtChargeState.SetFocus
+ End If
+
+ Exit Sub
+
+StartIsotopicDistributionCalcsErrorHandler:
+ GeneralErrorHandler "frmIsotopicDistribution|StartIsotopicDistributionCalcs", Err.Number, Err.Description
+
+End Sub
+
+Private Sub UpdateComparisonListStatus()
+ lblComparisonListDataPoints = Trim(ComparisonListDataCount)
+End Sub
+
+Private Sub cboComparisonListPlotType_Click()
+ PlotIsotopicDistribution True
+End Sub
+
+Private Sub cboPlotType_Click()
+ PlotIsotopicDistribution True
+End Sub
+
+Private Sub chkAutoLabelPeaks_Click()
+ PlotIsotopicDistribution True
+End Sub
+
+Private Sub chkPlotResults_Click()
+ If cChkBox(chkPlotResults) Then PlotIsotopicDistribution True
+End Sub
+
+Private Sub cmdClose_Click()
+ HideFormShowMain Me
+End Sub
+
+Private Sub cmdComparisonListClear_Click()
+ ComparisonIonListClear
+End Sub
+
+Private Sub cmdComparisonListPaste_Click()
+ ComparisonIonListPaste
+End Sub
+
+Private Sub cmdCompute_Click()
+ StartIsotopicDistributionCalcs True
+End Sub
+
+Private Sub cmdCopy_Click()
+ CopyResults
+End Sub
+
+Private Sub cmdShowPlot_Click()
+ objSpectrum.ShowSpectrum
+End Sub
+
+Private Sub Form_Activate()
+ PossiblyHideMainWindow
+
+ mFormActivatedByUser = True
+
+End Sub
+
+Private Sub Form_Load()
+
+ SizeAndCenterWindow Me, cWindowTopCenter, 11000, 5650
+
+ If objSpectrum Is Nothing Then
+ Set objSpectrum = New CWSpectrumDLL.Spectrum
+ End If
+
+ With objSpectrum
+ .SetSeriesCount 2
+ .SetSeriesPlotMode 1, pmLines, True
+ End With
+ mNeedToZoomOutFull = True
+
+ mDelayUpdatingPlot = False
+
+ ConvolutedMSDataCount = 0
+ ReDim ConvolutedMSData(0)
+
+ ComparisonListDataCount = 0
+ ReDim ComparisonListXVals(0)
+ ReDim ComparisonListYVals(0)
+
+ PopulateComboBox cboPlotType, True, "Sticks to Zero|Gaussian Peaks", ipmGaussian ' 15140
+ PopulateComboBox cboComparisonListPlotType, True, "Sticks to Zero|Gaussian Peaks|Lines Between Points", ipmSticksToZero ' 15145
+
+ txtChargeState = "1"
+
+ txtResults.Text = ""
+ txtResults.Font = "Courier"
+
+ PositionFormControls
+
+End Sub
+
+Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
+ QueryUnloadFormHandler Me, Cancel, UnloadMode
+End Sub
+
+Private Sub Form_Resize()
+ PositionFormControls
+End Sub
+
+Private Sub lblComparisonListPlotColor_Click()
+ SelectCustomColor Me, lblComparisonListPlotColor
+ PlotIsotopicDistribution True
+End Sub
+
+Private Sub lblPlotColor_Click()
+ SelectCustomColor Me, lblPlotColor
+ PlotIsotopicDistribution True
+End Sub
+
+Private Sub objSpectrum_SpectrumFormRequestClose()
+ ' The SpectrumForm was closed (actually, most likely just hidden)
+ ' If we wanted to do anything special, we could do it here
+End Sub
+
+Private Sub rtfFormula_Change()
+ Dim saveloc As Integer
+
+ saveloc = rtfFormula.SelStart
+
+ rtfFormula.TextRTF = objMwtWin.TextToRTF(rtfFormula.Text)
+ rtfFormula.SelStart = saveloc
+
+End Sub
+
+Private Sub rtfFormula_GotFocus()
+ SetMostRecentTextBoxValue rtfFormula.Text
+ mLastControlWithFocus = lcwfFormula
+End Sub
+
+Private Sub rtfFormula_KeyPress(KeyAscii As Integer)
+
+ If KeyAscii = vbKeyReturn Then
+ StartIsotopicDistributionCalcs True
+ KeyAscii = 0
+ End If
+
+ ' Check the validity of the key using RTFBoxKeyPressHandler
+ If KeyAscii <> 0 Then RTFBoxKeyPressHandler Me, rtfFormula, KeyAscii, False
+
+End Sub
+
+Private Sub txtChargeState_GotFocus()
+ HighlightOnFocus txtChargeState
+ mLastControlWithFocus = lcwfChargeState
+End Sub
+
+Private Sub txtChargeState_KeyPress(KeyAscii As Integer)
+ TextBoxKeyPressHandler txtChargeState, KeyAscii, True, False
+End Sub
+
+Private Sub txtChargeState_LostFocus()
+ ValidateTextboxValueLng txtChargeState, 0, 10000, 1
+ If txtChargeState <> GetMostRecentTextBoxValue() Then
+ StartIsotopicDistributionCalcs False, True
+ End If
+End Sub
+
+Private Sub txtEffectiveResolution_GotFocus()
+ HighlightOnFocus txtEffectiveResolution
+ mLastControlWithFocus = lcwfEffectiveResolution
+End Sub
+
+Private Sub txtEffectiveResolution_KeyPress(KeyAscii As Integer)
+ TextBoxKeyPressHandler txtEffectiveResolution, KeyAscii, True, False
+End Sub
+
+Private Sub txtEffectiveResolution_LostFocus()
+ ValidateTextboxValueLng txtEffectiveResolution, 1, 1000000000#, 5000
+ If txtEffectiveResolution <> GetMostRecentTextBoxValue() Then PlotIsotopicDistribution True
+End Sub
+
+Private Sub txtEffectiveResolutionMass_GotFocus()
+ HighlightOnFocus txtEffectiveResolutionMass
+ mLastControlWithFocus = lcwfEffectiveResolutionMass
+End Sub
+
+Private Sub txtEffectiveResolutionMass_KeyPress(KeyAscii As Integer)
+ TextBoxKeyPressHandler txtEffectiveResolutionMass, KeyAscii, True, False
+End Sub
+
+Private Sub txtEffectiveResolutionMass_LostFocus()
+ ValidateTextboxValueLng txtEffectiveResolutionMass, 1, 1000000000#, 1000
+ If txtEffectiveResolutionMass <> GetMostRecentTextBoxValue() Then PlotIsotopicDistribution True
+End Sub
+
+Private Sub txtGaussianQualityFactor_GotFocus()
+ HighlightOnFocus txtGaussianQualityFactor
+ mLastControlWithFocus = lcwfGaussianQualityFactor
+End Sub
+
+Private Sub txtGaussianQualityFactor_KeyPress(KeyAscii As Integer)
+ TextBoxKeyPressHandler txtGaussianQualityFactor, KeyAscii, True, False
+End Sub
+
+Private Sub txtGaussianQualityFactor_LostFocus()
+ ValidateTextboxValueLng txtGaussianQualityFactor, 1, 75, 50
+ If txtGaussianQualityFactor <> GetMostRecentTextBoxValue() Then PlotIsotopicDistribution True
+End Sub
+
+Private Sub txtResults_KeyPress(KeyAscii As Integer)
+
+ Select Case KeyAscii
+ Case 1 ' Ctrl+A -- select entire textbox
+ txtResults.SelStart = 0
+ txtResults.SelLength = Len(txtResults.Text)
+ KeyAscii = 0
+ Case 3 ' Copy is allowed
+ Case 24, 3, 22 ' Cut and Paste are not allowed
+ KeyAscii = 0
+ Case 26 ' Ctrl+Z = Undo is not allowed
+ KeyAscii = 0
+ Case Else
+ KeyAscii = 0
+ End Select
+
+End Sub
+
diff --git a/frmIsotopicAbundance.frx b/frmIsotopicAbundance.frx
new file mode 100644
index 0000000..5a50854
Binary files /dev/null and b/frmIsotopicAbundance.frx differ
diff --git a/frmProgramPreferences.frm b/frmProgramPreferences.frm
new file mode 100644
index 0000000..da21005
--- /dev/null
+++ b/frmProgramPreferences.frm
@@ -0,0 +1,839 @@
+VERSION 5.00
+Begin VB.Form frmProgramPreferences
+ BorderStyle = 3 'Fixed Dialog
+ Caption = "Molecular Weight Calculator Preferences"
+ ClientHeight = 6705
+ ClientLeft = 45
+ ClientTop = 330
+ ClientWidth = 9975
+ HelpContextID = 4006
+ Icon = "frmProgramPreferences.frx":0000
+ KeyPreview = -1 'True
+ LinkTopic = "Form1"
+ MaxButton = 0 'False
+ MinButton = 0 'False
+ ScaleHeight = 6705
+ ScaleWidth = 9975
+ ShowInTaskbar = 0 'False
+ StartUpPosition = 3 'Windows Default
+ Tag = "11500"
+ Begin VB.CommandButton cmdCancel
+ Cancel = -1 'True
+ Caption = "&Cancel"
+ Height = 480
+ HelpContextID = 4006
+ Left = 6120
+ TabIndex = 38
+ Tag = "4020"
+ Top = 6000
+ Width = 1095
+ End
+ Begin VB.Frame fraFormulaEntry
+ BorderStyle = 0 'None
+ Caption = "Formula Entry Options"
+ Height = 5775
+ Left = 120
+ TabIndex = 41
+ Top = 120
+ Width = 9735
+ Begin VB.ComboBox cboStartupModule
+ Height = 315
+ Left = 4680
+ Style = 2 'Dropdown List
+ TabIndex = 33
+ Tag = "11895"
+ ToolTipText = "Module to show when the program starts"
+ Top = 4920
+ Width = 4095
+ End
+ Begin VB.ComboBox cboMaximumFormulasToShow
+ Height = 315
+ Left = 240
+ Style = 2 'Dropdown List
+ TabIndex = 17
+ Tag = "11880"
+ ToolTipText = $"frmProgramPreferences.frx":08CA
+ Top = 5280
+ Width = 735
+ End
+ Begin VB.CheckBox chkShowCaution
+ Caption = "Show Caution Statements (F7)"
+ Height = 255
+ Left = 4680
+ TabIndex = 28
+ Tag = "11830"
+ Top = 3240
+ Value = 1 'Checked
+ Width = 4935
+ End
+ Begin VB.CheckBox chkShowQuickSwitch
+ Caption = "Show Element Mode &Quick Switch"
+ Height = 255
+ Left = 4680
+ TabIndex = 29
+ Tag = "11840"
+ Top = 3600
+ Value = 1 'Checked
+ Width = 4935
+ End
+ Begin VB.CheckBox chkShowToolTips
+ Caption = "Show Tool Tips"
+ Height = 255
+ Left = 4680
+ TabIndex = 30
+ Tag = "11850"
+ Top = 3960
+ Value = 1 'Checked
+ Width = 3975
+ End
+ Begin VB.CheckBox chkHideInactiveForms
+ Caption = "&Hide inactive program windows"
+ Height = 255
+ Left = 4680
+ TabIndex = 34
+ Tag = "11870"
+ Top = 5325
+ Width = 4935
+ End
+ Begin VB.CheckBox chkHighlightTextFields
+ Caption = "Highlight Text Fields when Selected"
+ Height = 255
+ Left = 4680
+ TabIndex = 31
+ Tag = "11860"
+ Top = 4320
+ Width = 4935
+ End
+ Begin VB.CheckBox chkAutosaveValues
+ Caption = "&Autosave options, values, and formulas on exit"
+ Height = 255
+ Left = 4680
+ TabIndex = 27
+ Tag = "11820"
+ Top = 2880
+ Width = 4935
+ End
+ Begin VB.Frame fraExitProgramOptions
+ Caption = "Exit Program Options"
+ Height = 1335
+ Left = 4560
+ TabIndex = 22
+ Tag = "11550"
+ Top = 1440
+ Width = 5055
+ Begin VB.OptionButton optExitConfirmation
+ Caption = "Ignore escape key and do not confirm exit"
+ Height = 255
+ Index = 3
+ Left = 240
+ TabIndex = 26
+ Tag = "11715"
+ Top = 960
+ Width = 4755
+ End
+ Begin VB.OptionButton optExitConfirmation
+ Caption = "Ignore escape key but confirm exit"
+ Height = 255
+ Index = 2
+ Left = 240
+ TabIndex = 25
+ Tag = "11710"
+ Top = 720
+ Width = 4755
+ End
+ Begin VB.OptionButton optExitConfirmation
+ Caption = "Exit on Escape without confirmation"
+ Height = 255
+ Index = 1
+ Left = 240
+ TabIndex = 24
+ Tag = "11705"
+ Top = 480
+ Width = 4755
+ End
+ Begin VB.OptionButton optExitConfirmation
+ Caption = "Exit on Escape with confirmation"
+ Height = 255
+ Index = 0
+ Left = 240
+ TabIndex = 23
+ Tag = "11700"
+ Top = 240
+ Value = -1 'True
+ Width = 4755
+ End
+ End
+ Begin VB.Frame fraFormulaFinderWeightModeWarning
+ Caption = "Advanced Tools Weight Mode Options"
+ Height = 1335
+ Left = 4560
+ TabIndex = 19
+ Tag = "11540"
+ Top = 0
+ Width = 5055
+ Begin VB.CheckBox chkAlwaysSwitchToIsotopic
+ Caption = "Always switch to &Isotopic Mode automatically"
+ Height = 495
+ Left = 240
+ TabIndex = 20
+ Tag = "11800"
+ Top = 240
+ Width = 4575
+ End
+ Begin VB.CheckBox chkNeverShowFormulaFinderWarning
+ Caption = "&Never show the weight mode warning dialog"
+ Height = 495
+ Left = 240
+ TabIndex = 21
+ Tag = "11810"
+ Top = 720
+ Width = 4695
+ End
+ End
+ Begin VB.Frame fraStandardDeviation
+ Caption = "Standard Deviation Mode (F12)"
+ Height = 1335
+ Left = 120
+ TabIndex = 8
+ Tag = "11530"
+ Top = 2400
+ Width = 3975
+ Begin VB.OptionButton optStdDevType
+ Caption = "Decimal"
+ Height = 255
+ Index = 2
+ Left = 240
+ TabIndex = 11
+ Tag = "11690"
+ Top = 720
+ Width = 3315
+ End
+ Begin VB.OptionButton optStdDevType
+ Caption = "Scientific"
+ Height = 255
+ Index = 1
+ Left = 240
+ TabIndex = 10
+ Tag = "11685"
+ Top = 480
+ Width = 3435
+ End
+ Begin VB.OptionButton optStdDevType
+ Caption = "Short"
+ Height = 255
+ Index = 0
+ Left = 240
+ TabIndex = 9
+ Tag = "11680"
+ Top = 240
+ Value = -1 'True
+ Width = 3555
+ End
+ Begin VB.OptionButton optStdDevType
+ Caption = "Off"
+ Height = 255
+ Index = 3
+ Left = 240
+ TabIndex = 12
+ Tag = "11695"
+ Top = 960
+ Width = 3435
+ End
+ End
+ Begin VB.Frame fraCaseRecognition
+ Caption = "Case Recognition Mode (F4)"
+ Height = 1095
+ Left = 120
+ TabIndex = 4
+ Tag = "11520"
+ Top = 1200
+ Width = 3975
+ Begin VB.OptionButton optConvertType
+ Caption = "Convert Case Up"
+ Height = 255
+ Index = 0
+ Left = 240
+ TabIndex = 5
+ Tag = "11665"
+ Top = 240
+ Value = -1 'True
+ Width = 3555
+ End
+ Begin VB.OptionButton optConvertType
+ Caption = "Exact Case"
+ Height = 255
+ Index = 1
+ Left = 240
+ TabIndex = 6
+ Tag = "11670"
+ Top = 480
+ Width = 3555
+ End
+ Begin VB.OptionButton optConvertType
+ Caption = "Smart Case"
+ Height = 255
+ Index = 2
+ Left = 240
+ TabIndex = 7
+ Tag = "11675"
+ Top = 720
+ Width = 3555
+ End
+ End
+ Begin VB.Frame fraAbbreviations
+ Caption = "Abbreviation Mode (F3)"
+ Height = 1095
+ Left = 120
+ TabIndex = 0
+ Tag = "11510"
+ Top = 0
+ Width = 3975
+ Begin VB.OptionButton optAbbrevType
+ Caption = "Off"
+ Height = 255
+ Index = 2
+ Left = 240
+ TabIndex = 3
+ Tag = "11660"
+ Top = 720
+ Width = 3555
+ End
+ Begin VB.OptionButton optAbbrevType
+ Caption = "Normal + Amino Acids"
+ Height = 255
+ Index = 1
+ Left = 240
+ TabIndex = 2
+ Tag = "11655"
+ Top = 480
+ Width = 3555
+ End
+ Begin VB.OptionButton optAbbrevType
+ Caption = "Normal"
+ Height = 255
+ Index = 0
+ Left = 240
+ TabIndex = 1
+ Tag = "11650"
+ Top = 240
+ Value = -1 'True
+ Width = 3555
+ End
+ End
+ Begin VB.CheckBox chkComputeCharge
+ Caption = "Compute Char&ge"
+ Height = 255
+ Left = 240
+ TabIndex = 16
+ Tag = "11780"
+ Top = 4920
+ Width = 4455
+ End
+ Begin VB.CheckBox chkBracketsAsParentheses
+ Caption = "Treat &Brackets as Parentheses"
+ Height = 255
+ Left = 240
+ TabIndex = 14
+ Tag = "11760"
+ Top = 4200
+ Width = 4455
+ End
+ Begin VB.CheckBox chkAutoCopyCurrentMWT
+ Caption = "A&uto Copy Current Molecular Weight (Ctrl+U)"
+ Height = 255
+ Left = 240
+ TabIndex = 15
+ Tag = "11770"
+ Top = 4560
+ Width = 4455
+ End
+ Begin VB.CheckBox chkAdvanceOnCalculate
+ Caption = "Ad&vance on Calculate (F9)"
+ Height = 255
+ Left = 240
+ TabIndex = 13
+ Tag = "11750"
+ Top = 3840
+ Width = 4455
+ End
+ Begin VB.Label lblStartupModule
+ Caption = "Module to show at startup"
+ Height = 255
+ Left = 4680
+ TabIndex = 32
+ Tag = "11890"
+ Top = 4680
+ Width = 4095
+ End
+ Begin VB.Label lblMaximumFormulasToShow
+ Caption = "Maximum number of formulas to display"
+ Height = 255
+ Left = 1080
+ TabIndex = 18
+ Tag = "11885"
+ Top = 5325
+ Width = 3615
+ End
+ End
+ Begin VB.CommandButton cmdRestoreOptions
+ Caption = "&Restore default options"
+ Height = 615
+ Left = 1800
+ TabIndex = 36
+ Tag = "11610"
+ Top = 6000
+ Width = 1335
+ End
+ Begin VB.CommandButton cmdSaveOptions
+ Caption = "&Save options as defaults"
+ Height = 615
+ Left = 360
+ TabIndex = 35
+ Tag = "11600"
+ Top = 6000
+ Width = 1215
+ End
+ Begin VB.CommandButton cmdOK
+ Caption = "Cl&ose"
+ Default = -1 'True
+ Height = 480
+ Left = 4800
+ TabIndex = 37
+ Tag = "4000"
+ Top = 6000
+ Width = 1095
+ End
+ Begin VB.Label lblHiddenDefaultsLoadedStatus
+ Caption = "Hidden Defaults Loaded Status"
+ Height = 255
+ Left = 7800
+ TabIndex = 40
+ Top = 6240
+ Visible = 0 'False
+ Width = 2655
+ End
+ Begin VB.Label lblHiddenFormStatus
+ Caption = "Hidden Form Loaded Status"
+ Height = 255
+ Left = 7800
+ TabIndex = 39
+ Top = 6000
+ Visible = 0 'False
+ Width = 2055
+ End
+End
+Attribute VB_Name = "frmProgramPreferences"
+Attribute VB_GlobalNameSpace = False
+Attribute VB_Creatable = False
+Attribute VB_PredeclaredId = True
+Attribute VB_Exposed = False
+Option Explicit
+
+Private Const STDDEV_INDEX_OFF = 3
+
+Private lclAbbreviationMode As Integer, lclCaseRecognitionMode As Integer
+Private lclStandardDeviationMode As Integer, lclExitProgramOption As Integer
+Private lclShowCaution As Integer, lclComputeCharge As Integer
+Private lclAdvanceOnCalculate As Integer, lclQuickSwitch As Integer
+Private lclAutoSaveValues As Integer, lclAlwaysSwitchToIsotopicMode As Integer
+Private lclHideInactiveForms As Integer, lclStartupModule As Integer
+Private lclBracketsAsParentheses As Integer, lclAutoCopyCurrentMWT As Integer
+Private lclNeverShowFFWarning As Integer, lclShowTooltips As Integer
+Private lclHighlightTextFields As Integer, lclMaximumFormulasToShow As Integer
+
+Private Sub PopulateComboBoxes()
+ Dim intIndex As Integer, intMaximumFormulaIndexToAllow As Integer
+ Const intMinimumFormulaIndexToAllow = 2
+
+ intMaximumFormulaIndexToAllow = DetermineMaxAllowableFormulaIndex()
+ With cboMaximumFormulasToShow
+ .Clear
+ For intIndex = 0 To intMaximumFormulaIndexToAllow - intMinimumFormulaIndexToAllow
+ .AddItem CStr(intIndex + intMinimumFormulaIndexToAllow + 1)
+ Next intIndex
+ .ListIndex = .ListCount - 1
+ End With
+
+ UpdateDynamicComboBox
+End Sub
+
+Private Sub RestorePreviousOptions()
+ optAbbrevType(lclAbbreviationMode).value = True
+ optConvertType(lclCaseRecognitionMode).value = True
+ optStdDevType(lclStandardDeviationMode).value = True
+ optExitConfirmation(lclExitProgramOption).value = True
+
+ chkAlwaysSwitchToIsotopic = lclAlwaysSwitchToIsotopicMode
+ chkNeverShowFormulaFinderWarning = lclNeverShowFFWarning
+
+ chkAdvanceOnCalculate = lclAdvanceOnCalculate
+ chkBracketsAsParentheses = lclBracketsAsParentheses
+ chkAutoCopyCurrentMWT = lclAutoCopyCurrentMWT
+ chkComputeCharge = lclComputeCharge
+
+ chkAutosaveValues = lclAutoSaveValues
+ chkShowCaution = lclShowCaution
+ chkShowQuickSwitch = lclQuickSwitch
+ chkShowToolTips = lclShowTooltips
+ chkHighlightTextFields = lclHighlightTextFields
+ chkHideInactiveForms = lclHideInactiveForms
+ cboStartupModule.ListIndex = lclStartupModule
+ cboMaximumFormulasToShow.ListIndex = lclMaximumFormulasToShow
+
+End Sub
+
+Private Sub PositionFormControls()
+ Dim intCheckBoxSpacing As Integer
+
+ intCheckBoxSpacing = 360
+
+ fraFormulaEntry.Top = 120
+ fraFormulaEntry.Left = 120
+
+ fraAbbreviations.Top = 0
+ fraAbbreviations.Left = 120
+
+ fraCaseRecognition.Top = 1200
+ fraCaseRecognition.Left = fraAbbreviations.Left
+
+ fraStandardDeviation.Top = 2400
+ fraStandardDeviation.Left = fraAbbreviations.Left
+
+ fraFormulaFinderWeightModeWarning.Top = fraAbbreviations.Top
+ fraFormulaFinderWeightModeWarning.Left = 4560
+
+ fraExitProgramOptions.Top = 1440
+ fraExitProgramOptions.Left = fraFormulaFinderWeightModeWarning.Left
+
+ chkAdvanceOnCalculate.Top = 3840
+ chkAdvanceOnCalculate.Left = 240
+ chkBracketsAsParentheses.Top = chkAdvanceOnCalculate.Top + intCheckBoxSpacing * 1
+ chkBracketsAsParentheses.Left = chkAdvanceOnCalculate.Left
+ chkAutoCopyCurrentMWT.Top = chkAdvanceOnCalculate.Top + intCheckBoxSpacing * 2
+ chkAutoCopyCurrentMWT.Left = chkAdvanceOnCalculate.Left
+ chkComputeCharge.Top = chkAdvanceOnCalculate.Top + intCheckBoxSpacing * 3
+ chkComputeCharge.Left = chkAdvanceOnCalculate.Left
+
+ cboMaximumFormulasToShow.Top = 5280
+ cboMaximumFormulasToShow.Left = chkAdvanceOnCalculate.Left
+ lblMaximumFormulasToShow.Top = 5325
+ lblMaximumFormulasToShow.Left = 1080
+
+ chkAutosaveValues.Top = 2880
+ chkAutosaveValues.Left = 4680
+ chkShowCaution.Top = chkAutosaveValues.Top + intCheckBoxSpacing * 1
+ chkShowCaution.Left = chkAutosaveValues.Left
+ chkShowQuickSwitch.Top = chkAutosaveValues.Top + intCheckBoxSpacing * 2
+ chkShowQuickSwitch.Left = chkAutosaveValues.Left
+ chkShowToolTips.Top = chkAutosaveValues.Top + intCheckBoxSpacing * 3
+ chkShowToolTips.Left = chkAutosaveValues.Left
+ chkHighlightTextFields.Top = chkAutosaveValues.Top + intCheckBoxSpacing * 4
+ chkHighlightTextFields.Left = chkAutosaveValues.Left
+
+ lblStartupModule.Top = 4680
+ lblStartupModule.Left = chkAutosaveValues.Left
+ cboStartupModule.Top = 4920
+ cboStartupModule.Left = chkAutosaveValues.Left
+
+ chkHideInactiveForms.Top = 5325
+ chkHideInactiveForms.Left = chkAutosaveValues.Left
+
+ cmdSaveOptions.Top = 5970
+ cmdSaveOptions.Left = 360
+ cmdRestoreOptions.Top = cmdSaveOptions.Top
+ cmdRestoreOptions.Left = 1800
+
+ CmdOK.Top = 6050
+ CmdOK.Left = 4800
+ cmdCancel.Top = CmdOK.Top
+ cmdCancel.Left = 6120
+
+End Sub
+
+Private Sub SaveCurrentOptions()
+ Dim intIndex As Integer
+
+ For intIndex = 0 To 2
+ If optAbbrevType(intIndex).value = True Then
+ lclAbbreviationMode = intIndex
+ End If
+ Next intIndex
+
+ For intIndex = 0 To 2
+ If optConvertType(intIndex).value = True Then
+ lclCaseRecognitionMode = intIndex
+ End If
+ Next intIndex
+
+ For intIndex = 0 To 3
+ If optStdDevType(intIndex).value = True Then
+ lclStandardDeviationMode = intIndex
+ End If
+ Next intIndex
+
+ For intIndex = 0 To 3
+ If optExitConfirmation(intIndex).value = True Then
+ lclExitProgramOption = intIndex
+ End If
+ Next intIndex
+
+ lclAlwaysSwitchToIsotopicMode = chkAlwaysSwitchToIsotopic
+ lclNeverShowFFWarning = chkNeverShowFormulaFinderWarning
+
+ lclAdvanceOnCalculate = chkAdvanceOnCalculate
+ lclBracketsAsParentheses = chkBracketsAsParentheses
+ lclAutoCopyCurrentMWT = chkAutoCopyCurrentMWT
+ lclComputeCharge = chkComputeCharge
+
+ lclAutoSaveValues = chkAutosaveValues
+ lclShowCaution = chkShowCaution
+ lclQuickSwitch = chkShowQuickSwitch
+ lclShowTooltips = chkShowToolTips
+ lclHighlightTextFields = chkHighlightTextFields
+ lclHideInactiveForms = chkHideInactiveForms
+ lclStartupModule = cboStartupModule.ListIndex
+ lclMaximumFormulasToShow = cboMaximumFormulasToShow.ListIndex
+
+End Sub
+
+Public Sub SwapCheck(ThisCheckBoxControl As CheckBox)
+
+ With ThisCheckBoxControl
+ If .value = vbUnchecked Then
+ .value = vbChecked
+ Else
+ .value = vbUnchecked
+ End If
+ End With
+End Sub
+
+Private Sub cboMaximumFormulasToShow_Validate(Cancel As Boolean)
+ Dim intDesiredMaxIndex As Integer
+
+ intDesiredMaxIndex = Val(cboMaximumFormulasToShow.List(cboMaximumFormulasToShow.ListIndex)) - 1
+
+ If intDesiredMaxIndex = gMaxFormulaIndex Then Exit Sub
+
+ ' Only chage intDesiredMaxIndex if the new, desired index is larger than the current value
+ ' Reason: it is easy to load new objects, but more difficult to unload them
+ If intDesiredMaxIndex > frmMain.GetTopFormulaIndex Then
+ gMaxFormulaIndex = intDesiredMaxIndex
+ End If
+
+ SaveSingleDefaultOption "MaximumFormulasToShow", FormatMaximumFormulasToShowString(intDesiredMaxIndex)
+
+End Sub
+
+Private Sub UpdateDynamicComboBox()
+ PopulateComboBox cboStartupModule, True, LookupLanguageCaption(11898, "Main Window|Formula Finder|Capillary Flow Calculator|Mole/Mass Converter|Peptide Sequence Fragmentation Modeller|Amino Acid Notation Converter|Isotopic Distribution Modeller")
+
+ If cboStartupModule.ListIndex < 0 Then cboStartupModule.ListIndex = 0
+
+End Sub
+
+Private Sub chkAlwaysSwitchToIsotopic_Click()
+ If cChkBox(chkAlwaysSwitchToIsotopic) Then
+ chkNeverShowFormulaFinderWarning.value = vbChecked
+ chkNeverShowFormulaFinderWarning.Enabled = False
+ Else
+ chkNeverShowFormulaFinderWarning.value = vbUnchecked
+ chkNeverShowFormulaFinderWarning.Enabled = True
+ End If
+
+End Sub
+
+Private Sub chkAutoSaveValues_Click()
+ Dim strValueToSave As String
+
+ If cChkBox(chkAutosaveValues) Then
+ strValueToSave = "1"
+ Else
+ strValueToSave = "0"
+ End If
+
+ SaveSingleDefaultOption "AutoSaveValues", strValueToSave
+ frmMain.lblStatus.ForeColor = vbWindowText
+ frmMain.lblStatus.Caption = LookupLanguageCaption(11900, "Autosave values option saved.")
+
+End Sub
+
+Private Sub chkBracketsAsParentheses_Click()
+ objMwtWin.BracketsTreatedAsParentheses = cChkBox(chkBracketsAsParentheses)
+
+End Sub
+
+Private Sub chkShowQuickSwitch_Click()
+
+ frmMain.ShowHideQuickSwitch chkShowQuickSwitch.value
+
+ frmMain.ResizeFormMain True
+
+End Sub
+
+Private Sub chkShowToolTips_Click()
+ SwitchTips cChkBox(chkShowToolTips)
+
+End Sub
+
+Private Sub cmdCancel_Click()
+ RestorePreviousOptions
+ frmProgramPreferences.Hide
+ lblHiddenFormStatus = "Cancelled"
+
+End Sub
+
+Private Sub cmdOK_Click()
+ frmProgramPreferences.Hide
+ lblHiddenFormStatus = "Hidden"
+End Sub
+
+Private Sub cmdRestoreOptions_Click()
+ LoadDefaultOptions True
+
+ frmMain.lblStatus.ForeColor = vbWindowText
+ frmMain.lblStatus.Caption = LookupLanguageCaption(11910, "Default options restored.")
+
+ If frmProgramPreferences.Visible = True Then
+ frmProgramPreferences.cmdSaveOptions.SetFocus
+ End If
+
+End Sub
+
+Private Sub cmdSaveOptions_Click()
+ SaveDefaultOptions
+End Sub
+
+Private Sub Form_Activate()
+
+ SizeAndCenterWindow Me, cWindowUpperThird, 10000, 7100
+
+ If lblHiddenFormStatus <> "Saved" Then
+ SaveCurrentOptions
+ lblHiddenFormStatus = "Saved"
+ End If
+
+ UpdateDynamicComboBox
+
+End Sub
+
+Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
+ Dim NewValue As Integer
+
+ Select Case KeyCode
+ Case vbKeyF1
+ ' Windows Help command
+ Case vbKeyF2
+ ' Copy current formula
+ Case vbKeyF3
+ ' Change abbreviation recognition mode
+ If optAbbrevType(0).value = True Then
+ optAbbrevType(1).value = True
+ ElseIf optAbbrevType(1).value = True Then
+ optAbbrevType(2).value = True
+ Else
+ optAbbrevType(0).value = True
+ End If
+ frmMain.LabelStatus
+ Case vbKeyF4
+ ' Change Case Mode
+ If optConvertType(0).value = True Then
+ optConvertType(1).value = True
+ ElseIf optConvertType(1).value = True Then
+ optConvertType(2).value = True
+ Else
+ optConvertType(0).value = True
+ End If
+ frmMain.LabelStatus
+ Case vbKeyF7
+ ' Change caution mode
+ SwapCheck chkShowCaution
+ frmMain.LabelStatus
+ Case vbKeyF9
+ ' Change advance mode
+ SwapCheck chkAdvanceOnCalculate
+ frmMain.LabelStatus
+ Case vbKeyF12
+ ' Change standard deviation mode
+ If optStdDevType(0).value = True Then
+ optStdDevType(1).value = True
+ NewValue = 1
+ ElseIf optStdDevType(1).value = True Then
+ optStdDevType(2).value = True
+ NewValue = 2
+ ElseIf optStdDevType(2).value = True Then
+ optStdDevType(3).value = True
+ NewValue = 3
+ Else
+ optStdDevType(0).value = True
+ NewValue = 0
+ End If
+ frmMain.LabelStatus
+ frmProgramPreferences.optStdDevType(NewValue).SetFocus
+
+ Case Else
+ If KeyCode = vbKeyU And (Shift And vbCtrlMask) Then ' And them in case alt or shift was also accidentally pressed
+ If chkAutoCopyCurrentMWT = 1 Then
+ chkAutoCopyCurrentMWT = 0
+ Else
+ chkAutoCopyCurrentMWT = 1
+ End If
+ KeyCode = 0: Shift = 0
+ Else
+ ' Let the key pass
+ End If
+ End Select
+
+End Sub
+
+Private Sub Form_Load()
+
+ PositionFormControls
+ PopulateComboBoxes
+
+End Sub
+
+Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
+ QueryUnloadFormHandler Me, Cancel, UnloadMode
+End Sub
+
+Private Sub optAbbrevType_Click(Index As Integer)
+
+ If frmMain.lblHiddenFormStatus <> "Loading" Then
+ With frmMain.lblStatus
+ .ForeColor = QBColor(COLOR_WARN)
+ .Caption = LookupMessage(800)
+ gBlnStatusCaution = True
+ End With
+ objMwtWin.AbbreviationRecognitionMode = Index
+ End If
+
+End Sub
+
+Private Sub optConvertType_Click(Index As Integer)
+ objMwtWin.CaseConversionMode = Index
+End Sub
+
+Private Sub optExitConfirmation_Click(Index As Integer)
+ ' Reset dynamic menu captions
+ ' Call AppendShortcutKeysToMenuCaptions, which reset all menu captions
+ AppendShortcutKeysToMenuCaptions
+End Sub
+
+Private Sub optStdDevType_Click(Index As Integer)
+
+ objMwtWin.StdDevMode = Index
+
+ If Index = STDDEV_INDEX_OFF Then
+ gBlnShowStdDevWithMass = False
+ Else
+ gBlnShowStdDevWithMass = True
+ End If
+
+ frmMain.Calculate True, True, True, 0, False, False, True
+
+ If frmProgramPreferences.Visible = True Then
+ frmProgramPreferences.optStdDevType(Index).SetFocus
+ End If
+
+End Sub
+
diff --git a/frmProgramPreferences.frx b/frmProgramPreferences.frx
new file mode 100644
index 0000000..c49c8aa
Binary files /dev/null and b/frmProgramPreferences.frx differ
diff --git a/frmReportCompounds.frx b/frmReportCompounds.frx
new file mode 100644
index 0000000..03ffc39
Binary files /dev/null and b/frmReportCompounds.frx differ
diff --git a/frmStrings.frm b/frmStrings.frm
new file mode 100644
index 0000000..d7cb0a5
--- /dev/null
+++ b/frmStrings.frm
@@ -0,0 +1,81 @@
+VERSION 5.00
+Object = "{5E9E78A0-531B-11CF-91F6-C2863C385E30}#1.0#0"; "MSFLXGRD.OCX"
+Begin VB.Form frmStrings
+ Caption = "String Reference Tables"
+ ClientHeight = 4905
+ ClientLeft = 60
+ ClientTop = 345
+ ClientWidth = 6495
+ LinkTopic = "Form1"
+ MaxButton = 0 'False
+ MinButton = 0 'False
+ ScaleHeight = 4905
+ ScaleWidth = 6495
+ StartUpPosition = 3 'Windows Default
+ Begin VB.CommandButton cmdHide
+ Cancel = -1 'True
+ Caption = "&Hide"
+ Default = -1 'True
+ Height = 360
+ Left = 120
+ TabIndex = 2
+ ToolTipText = "Accepts changes made to abbreviations"
+ Top = 4440
+ Width = 1035
+ End
+ Begin MSFlexGridLib.MSFlexGrid grdLanguageStrings
+ Height = 2055
+ Left = 120
+ TabIndex = 0
+ Top = 120
+ Width = 4215
+ _ExtentX = 7435
+ _ExtentY = 3625
+ _Version = 393216
+ FixedRows = 0
+ FixedCols = 0
+ AllowUserResizing= 1
+ End
+ Begin MSFlexGridLib.MSFlexGrid grdMenuInfo
+ Height = 2055
+ Left = 120
+ TabIndex = 1
+ Top = 2280
+ Width = 6135
+ _ExtentX = 10821
+ _ExtentY = 3625
+ _Version = 393216
+ FixedRows = 0
+ FixedCols = 0
+ AllowUserResizing= 1
+ End
+ Begin MSFlexGridLib.MSFlexGrid grdLanguageStringsCrossRef
+ Height = 2055
+ Left = 4440
+ TabIndex = 3
+ Top = 120
+ Width = 1815
+ _ExtentX = 3201
+ _ExtentY = 3625
+ _Version = 393216
+ Rows = 1
+ FixedRows = 0
+ FixedCols = 0
+ AllowUserResizing= 1
+ End
+End
+Attribute VB_Name = "frmStrings"
+Attribute VB_GlobalNameSpace = False
+Attribute VB_Creatable = False
+Attribute VB_PredeclaredId = True
+Attribute VB_Exposed = False
+Option Explicit
+
+Private Sub cmdHide_Click()
+ Me.Hide
+
+End Sub
+
+Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
+ QueryUnloadFormHandler Me, Cancel, UnloadMode
+End Sub
diff --git a/frmfindermodewarn.frm b/frmfindermodewarn.frm
new file mode 100644
index 0000000..6dd5942
--- /dev/null
+++ b/frmfindermodewarn.frm
@@ -0,0 +1,171 @@
+VERSION 5.00
+Begin VB.Form frmFinderModeWarn
+ BorderStyle = 3 'Fixed Dialog
+ Caption = "Formula Finder"
+ ClientHeight = 4725
+ ClientLeft = 45
+ ClientTop = 330
+ ClientWidth = 6705
+ HelpContextID = 3045
+ Icon = "frmFinderModeWarn.frx":0000
+ KeyPreview = -1 'True
+ LinkTopic = "Form1"
+ MaxButton = 0 'False
+ MinButton = 0 'False
+ ScaleHeight = 4725
+ ScaleWidth = 6705
+ ShowInTaskbar = 0 'False
+ StartUpPosition = 3 'Windows Default
+ Tag = "10000"
+ Begin VB.OptionButton optWeightChoice
+ Caption = "Continue using &Average Weights."
+ Height = 255
+ Index = 2
+ Left = 480
+ TabIndex = 3
+ Tag = "9770"
+ Top = 3600
+ Width = 5655
+ End
+ Begin VB.OptionButton optWeightChoice
+ Caption = "Always automatically switch to Isotopic &Weight mode."
+ Height = 255
+ Index = 1
+ Left = 480
+ TabIndex = 2
+ Tag = "9760"
+ Top = 3240
+ Width = 5655
+ End
+ Begin VB.OptionButton optWeightChoice
+ Caption = "Switch to &Isotopic Weight mode now."
+ Height = 255
+ Index = 0
+ Left = 480
+ TabIndex = 1
+ Tag = "9750"
+ Top = 2880
+ Value = -1 'True
+ Width = 5655
+ End
+ Begin VB.CheckBox chkShowAgain
+ Caption = "&Stop showing this warning dialog."
+ Height = 375
+ Left = 480
+ TabIndex = 4
+ Tag = "9780"
+ Top = 4080
+ Width = 3855
+ End
+ Begin VB.CommandButton cmdOK
+ Caption = "&Continue"
+ Default = -1 'True
+ Height = 480
+ Left = 5040
+ TabIndex = 5
+ Tag = "9720"
+ Top = 4080
+ Width = 1095
+ End
+ Begin VB.Label lblInstructions2
+ Caption = "Would you like to:"
+ Height = 255
+ Left = 120
+ TabIndex = 6
+ Tag = "9703"
+ Top = 2520
+ Width = 3375
+ End
+ Begin VB.Label lblInstructions
+ Caption = "Instructions"
+ Height = 2175
+ Left = 120
+ TabIndex = 0
+ Top = 120
+ Width = 6495
+ End
+End
+Attribute VB_Name = "frmFinderModeWarn"
+Attribute VB_GlobalNameSpace = False
+Attribute VB_Creatable = False
+Attribute VB_PredeclaredId = True
+Attribute VB_Exposed = False
+Option Explicit
+
+Private intStopShowing As Integer
+
+Public Sub DisplayInstructions(Optional blnlShowFormulaFinder As Boolean = True)
+ Dim strMessage As String, strWindowCaption As String
+
+ If blnlShowFormulaFinder Then
+ ' Load correct text into strMessage
+ strMessage = LookupLanguageCaption(9700, "The typical use of the Formula Finder feature is for when the monoisotopic mass (weight) of a compound is known (typically determined by Mass Spectrometry) and potential matching compounds are to be searched for.")
+ strMessage = strMessage & vbCrLf & " "
+ strMessage = strMessage & LookupLanguageCaption(9701, "For example, a mass of 16.0312984 Daltons is measured for a compound containing Carbon and Hydrogen, and the possible empirical formula is desired. Performing the search, with a weight tolerance of 5000 ppm results in three compounds, H2N, CH4, and O. Within 500 ppm only CH4 matches, which is the correct match.")
+ strMessage = strMessage & vbCrLf & " "
+
+ ' Set the proper window caption
+ strWindowCaption = LookupLanguageCaption(10000, "Formula Finder")
+ Else
+ strMessage = LookupLanguageCaption(9705, "The typical use of the Fragmentation Modelling feature is for predicting the masses expected to be observed with a Mass Spectrometer when a peptide is ionized, enters the instrument, and fragments along the peptide backbone.")
+ strMessage = strMessage & vbCrLf & " "
+ strMessage = strMessage & LookupLanguageCaption(9706, "The peptide typically fragments at each amide bond. For example, the peptide Gly-Leu-Tyr will form the fragments Gly-Leu, Leu-Tyr, Gly, Leu, and Tyr. Additionally, the cleavage of the amide bond can occur at differing locations, resulting in varying weights.")
+ strMessage = strMessage & vbCrLf & " "
+ strWindowCaption = LookupLanguageCaption(12000, "Peptide Sequence Fragmentation Modelling")
+ End If
+
+ strMessage = strMessage & LookupLanguageCaption(9702, "To correctly use this feature, the program must be set to Isotopic Weight mode. This can be done manually by choosing Edit Elements Table under the File menu, or the program can automatically switch to this mode for you.")
+
+ lblInstructions.Caption = strMessage
+ lblInstructions2.Caption = LookupLanguageCaption(9703, "Would you like to:")
+
+ frmFinderModeWarn.Caption = strWindowCaption
+End Sub
+
+Private Sub cmdOK_Click()
+ frmFinderModeWarn.Hide
+
+End Sub
+
+Private Sub Form_Activate()
+
+ ' Put window in center of screen
+ SizeAndCenterWindow Me, cWindowUpperThird, 7500
+
+ intStopShowing = chkShowAgain.value
+End Sub
+
+Private Sub Form_GotFocus()
+ optWeightChoice(0).SetFocus
+
+End Sub
+
+Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
+ If KeyCode = vbKeyEscape Then
+ optWeightChoice(0).value = True
+ chkShowAgain.value = False
+ cmdOK_Click
+ End If
+End Sub
+
+Private Sub Form_Load()
+
+ intStopShowing = chkShowAgain.value
+
+ ' Set the first option as the default choice
+ optWeightChoice(0).value = True
+
+End Sub
+
+Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
+ QueryUnloadFormHandler Me, Cancel, UnloadMode
+End Sub
+
+Private Sub optWeightChoice_Click(Index As Integer)
+ If Index = 1 Then
+ chkShowAgain.value = 1
+ Else
+ chkShowAgain.value = intStopShowing
+ End If
+
+End Sub
diff --git a/frmfindermodewarn.frx b/frmfindermodewarn.frx
new file mode 100644
index 0000000..03ffc39
Binary files /dev/null and b/frmfindermodewarn.frx differ
diff --git a/frmprogress.frm b/frmprogress.frm
new file mode 100644
index 0000000..1821e4d
--- /dev/null
+++ b/frmprogress.frm
@@ -0,0 +1,552 @@
+VERSION 5.00
+Begin VB.Form frmProgress
+ BorderStyle = 3 'Fixed Dialog
+ Caption = "Progress"
+ ClientHeight = 2385
+ ClientLeft = 45
+ ClientTop = 360
+ ClientWidth = 7350
+ KeyPreview = -1 'True
+ LinkTopic = "Form1"
+ MaxButton = 0 'False
+ MinButton = 0 'False
+ ScaleHeight = 2385
+ ScaleWidth = 7350
+ ShowInTaskbar = 0 'False
+ StartUpPosition = 3 'Windows Default
+ Tag = "14700"
+ Begin VB.Frame fraControls
+ BorderStyle = 0 'None
+ Caption = "Frame1"
+ Height = 735
+ Left = 3840
+ TabIndex = 5
+ Top = 1560
+ Width = 2415
+ Begin VB.CommandButton cmdPause
+ Caption = "Click to Pause"
+ Height = 375
+ Left = 360
+ TabIndex = 6
+ Tag = "14710"
+ Top = 0
+ Width = 1815
+ End
+ Begin VB.Label lblPressEscape
+ Alignment = 2 'Center
+ Caption = "(Press Escape to abort)"
+ Height = 255
+ Left = 0
+ TabIndex = 7
+ Tag = "14730"
+ Top = 480
+ Width = 2655
+ End
+ End
+ Begin VB.Shape pbarSubProgressBox
+ Height = 255
+ Left = 120
+ Top = 960
+ Width = 2775
+ End
+ Begin VB.Shape pbarSubProgress
+ BackColor = &H80000002&
+ FillColor = &H80000002&
+ FillStyle = 0 'Solid
+ Height = 255
+ Left = 120
+ Top = 960
+ Width = 1215
+ End
+ Begin VB.Shape pbarProgressBox
+ Height = 255
+ Left = 120
+ Top = 120
+ Width = 2775
+ End
+ Begin VB.Shape pbarProgress
+ BackColor = &H80000002&
+ FillColor = &H80000002&
+ FillStyle = 0 'Solid
+ Height = 255
+ Left = 120
+ Top = 120
+ Width = 1215
+ End
+ Begin VB.Label lblSubtaskProgress
+ Alignment = 2 'Center
+ Caption = "Current Task Progress"
+ Height = 255
+ Left = 120
+ TabIndex = 1
+ Tag = "14730"
+ Top = 1350
+ Width = 2655
+ End
+ Begin VB.Label lblOverallProgress
+ Alignment = 2 'Center
+ Caption = "Overall Progress"
+ Height = 255
+ Left = 120
+ TabIndex = 0
+ Tag = "14730"
+ Top = 510
+ Width = 2655
+ End
+ Begin VB.Label lblCurrentSubTask
+ Height = 735
+ Left = 3120
+ TabIndex = 4
+ Top = 720
+ Width = 4095
+ End
+ Begin VB.Label lblTimeStats
+ Caption = "Elapsed/remaining time"
+ Height = 255
+ Left = 240
+ TabIndex = 2
+ Top = 1800
+ Width = 3015
+ End
+ Begin VB.Label lblCurrentTask
+ Caption = "Current task"
+ Height = 495
+ Left = 3120
+ TabIndex = 3
+ Top = 120
+ Width = 4095
+ End
+End
+Attribute VB_Name = "frmProgress"
+Attribute VB_GlobalNameSpace = False
+Attribute VB_Creatable = False
+Attribute VB_PredeclaredId = True
+Attribute VB_Exposed = False
+Option Explicit
+
+' Written by Matthew Monroe for use in applications
+' First written in Chapel Hill, NC in roughly 2000
+'
+' Last Modified: July 24, 2003
+
+Private ePauseStatus As ppProgressPauseConstants
+
+Private lngProgressMin As Long
+Private lngProgressMax As Long
+Private dblLatestProgressBarValue As Double
+
+Private lngSubTaskProgressMin As Long
+Private lngSubTaskProgressMax As Long
+Private dblLatestSubTaskProgressBarValue As Double
+
+Private mblnWorking As Boolean
+Private mTextMinutesElapsedRemaining As String
+Private mTextPreparingToPause As String
+Private mTextResuming As String
+Private mTextClickToPause As String
+Private mTextPaused As String
+Private mTextPressEscapeToAbort As String
+Private mLastQueryUnloadTickCount As Long
+
+Private Enum ppProgressPauseConstants
+ ppUnpaused = 0
+ ppRequestPause
+ ppPaused
+ ppRequestUnpause
+End Enum
+
+Private Sub CheckForPauseUnpause()
+
+ Select Case ePauseStatus
+ Case ppRequestPause
+ cmdPause.Caption = mTextPaused
+ ePauseStatus = ppPaused
+ Me.MousePointer = vbNormal
+ Do
+ Sleep 100
+ DoEvents
+ Loop While ePauseStatus = ppPaused
+ ePauseStatus = ppUnpaused
+ cmdPause.Caption = mTextClickToPause
+ Me.MousePointer = vbHourglass
+ Case ppRequestUnpause
+ ePauseStatus = ppUnpaused
+ cmdPause.Caption = mTextClickToPause
+ Case Else
+ ' Nothing to pause or unpause
+ End Select
+
+End Sub
+
+Public Function GetElapsedTime() As Single
+ ' Examines lblTimeStats to find the last recorded elapsed time
+
+ Dim intColonLoc As Integer
+
+ intColonLoc = InStr(lblTimeStats, ":")
+
+ If intColonLoc > 0 Then
+ GetElapsedTime = Val(Left(lblTimeStats, intColonLoc - 1))
+ End If
+
+End Function
+
+Public Function GetProgressBarValue(ByRef lngMinimum As Long, ByRef lngMaximum As Long) As Double
+ ' Returns the current value of the progress bar, plus the Min and Max, returning them ByRef
+ lngMinimum = lngProgressMin
+ lngMaximum = lngProgressMax
+
+ GetProgressBarValue = dblLatestProgressBarValue
+End Function
+
+Public Function GetSubTaskProgressBarValue(ByRef lngMinimum As Long, ByRef lngMaximum As Long) As Double
+ ' Returns the current value of the subtask progress bar, plus the Min and Max, returning them ByRef
+ lngMinimum = lngSubTaskProgressMin
+ lngMaximum = lngSubTaskProgressMax
+
+ GetSubTaskProgressBarValue = dblLatestSubTaskProgressBarValue
+End Function
+
+Public Sub HideForm(Optional blnResetKeyPressAbortProcess As Boolean = True)
+
+ If blnResetKeyPressAbortProcess Then KeyPressAbortProcess = 0
+
+ frmProgress.MousePointer = vbNormal
+
+ mblnWorking = False
+
+ ' The following On Error is necessary in case a modal window is displayed
+ ' Also necessary since a call to .Hide when a form is already hidden generates an error
+ On Error Resume Next
+ frmProgress.Hide
+
+End Sub
+
+Public Sub InitializeSubtask(CurrentSubTask As String, SubTaskProgressBarMinNew As Long, SubTaskProgressBarMaxNew As Long)
+ lngSubTaskProgressMin = SubTaskProgressBarMinNew
+ lngSubTaskProgressMax = SubTaskProgressBarMaxNew
+
+ If lngSubTaskProgressMin > lngSubTaskProgressMax Then
+ ' Swap them
+ SwapValues lngSubTaskProgressMin, lngSubTaskProgressMax
+ End If
+
+ If lngSubTaskProgressMin < 0 Then lngSubTaskProgressMin = 0
+ If lngSubTaskProgressMin > lngSubTaskProgressMax Then lngSubTaskProgressMax = lngSubTaskProgressMin + 1
+ If lngSubTaskProgressMax < 1 Then lngSubTaskProgressMax = 1
+
+On Error GoTo InitializeSubtaskErrorHandler
+
+ UpdateCurrentSubTask CurrentSubTask
+
+ UpdateSubtaskProgressBar lngSubTaskProgressMin
+
+ mblnWorking = True
+
+ Exit Sub
+
+InitializeSubtaskErrorHandler:
+ MsgBox "An error occurred while initializing the sub-progress bar: " & vbCrLf & Err.Description, vbInformation + vbOKOnly, "Error"
+ Resume Next
+
+End Sub
+
+Public Sub InitializeForm(CurrentTask As String, OverallProgressBarMinNew As Long, OverallProgressBarMaxNew As Long, Optional blnShowTimeStats As Boolean = False, Optional blnShowSubTaskProgress As Boolean = False, Optional blnShowPauseButton As Boolean = True, Optional frmObjOwnerForm As Form)
+ lngProgressMin = OverallProgressBarMinNew
+ lngProgressMax = OverallProgressBarMaxNew
+
+ If lngProgressMin > lngProgressMax Then
+ ' Swap them
+ SwapValues lngProgressMin, lngProgressMax
+ End If
+
+ If lngProgressMin < 0 Then lngProgressMin = 0
+ If lngProgressMin > lngProgressMax Then lngProgressMax = lngProgressMin + 1
+ If lngProgressMax < 1 Then lngProgressMax = 1
+
+ lngSubTaskProgressMin = 0
+ lngSubTaskProgressMax = 1
+ pbarSubProgress.Width = 0
+
+On Error GoTo InitializeFormErrorHandler
+
+ UpdateCurrentTask CurrentTask
+ lblCurrentSubTask = ""
+
+ lblTimeStats.Visible = blnShowTimeStats
+
+ pbarSubProgress.Visible = blnShowSubTaskProgress
+ pbarSubProgressBox.Visible = blnShowSubTaskProgress
+ lblSubtaskProgress.Visible = blnShowSubTaskProgress
+
+ If blnShowSubTaskProgress Then
+ lblTimeStats.Top = 1800
+ fraControls.Top = 1650
+ fraControls.Left = 3840
+ Me.Height = 2800
+ Else
+ lblTimeStats.Top = 800
+ fraControls.Top = 1190
+ fraControls.Left = 240
+ Me.Height = 2350
+ End If
+
+ cmdPause.Visible = blnShowPauseButton
+ If ppPaused Then
+ ePauseStatus = ppRequestUnpause
+ CheckForPauseUnpause
+ End If
+
+ UpdateProgressBar lngProgressMin, True
+
+ KeyPressAbortProcess = 0
+ mLastQueryUnloadTickCount = 0
+ mblnWorking = True
+
+ If frmObjOwnerForm Is Nothing Then
+ frmProgress.Show vbModeless
+ Else
+ frmProgress.Show vbModeless, frmObjOwnerForm
+ End If
+
+ frmProgress.MousePointer = vbHourglass
+
+ Exit Sub
+
+InitializeFormErrorHandler:
+ If Err.Number = 401 Then
+ ' Tried to show frmProgress when a modal form is shown; this isn't allowed
+ ' Probably cannot use frmProgress in the calling routine
+ Debug.Assert False
+ Resume Next
+ Else
+ MsgBox "An error occurred while initializing the progress bar: " & vbCrLf & Err.Description, vbInformation + vbOKOnly, "Error"
+ Resume Next
+ End If
+
+End Sub
+
+Public Sub MoveToBottomCenter()
+ SizeAndCenterWindow Me, cWindowBottomCenter, -1, -1, False
+End Sub
+
+Public Function TaskInProgress() As Boolean
+ ' Returns True if the Progress form is currently displayed
+ ' Returns False otherwise
+
+ TaskInProgress = mblnWorking
+End Function
+
+Public Sub ToggleAlwaysOnTop(blnStayOnTop As Boolean)
+ Static blnCurrentlyOnTop As Boolean
+
+ If blnCurrentlyOnTop = blnStayOnTop Then Exit Sub
+
+ Me.ScaleMode = vbTwips
+
+ WindowStayOnTop Me.hWnd, blnStayOnTop, Me.ScaleX(Me.Left, vbTwips, vbPixels), Me.ScaleY(Me.Top, vbTwips, vbPixels), Me.ScaleX(Me.Width, vbTwips, vbPixels), Me.ScaleY(Me.Height, vbTwips, vbPixels)
+
+ blnCurrentlyOnTop = blnStayOnTop
+End Sub
+
+Public Sub UpdateProgressBar(ByVal NewValue As Double, Optional ResetStartTime As Boolean = False)
+
+ Static StartTime As Double
+ Static StopTime As Double
+
+ Dim MinutesElapsed As Double, MinutesTotal As Double, MinutesRemaining As Double
+ Dim dblRatioCompleted As Double
+
+ If ResetStartTime Then
+ StartTime = Now()
+ End If
+
+ dblRatioCompleted = SetProgressBarValue(NewValue, False)
+
+ StopTime = Now()
+ MinutesElapsed = (StopTime - StartTime) * 1440
+ If dblRatioCompleted <> 0 Then
+ MinutesTotal = MinutesElapsed / dblRatioCompleted
+ Else
+ MinutesTotal = 0
+ End If
+ MinutesRemaining = MinutesTotal - MinutesElapsed
+ lblTimeStats = Format(MinutesElapsed, "0.00") & " : " & Format(MinutesRemaining, "0.00 ") & mTextMinutesElapsedRemaining
+
+ CheckForPauseUnpause
+
+ DoEvents
+
+End Sub
+
+Public Sub SetStandardCaptionText(Optional ByVal strMinutesElapsedRemaining As String = "min. elapsed/remaining", Optional ByVal strPreparingToPause As String = "Preparing to Pause", Optional ByVal strResuming As String = "Resuming", Optional ByVal strClickToPause As String = "Click to Pause", Optional ByVal strPaused As String = "Paused", Optional ByVal strPressEscapeToAbort As String = "(Press Escape to abort)")
+ mTextMinutesElapsedRemaining = strMinutesElapsedRemaining
+ mTextPreparingToPause = strPreparingToPause
+ mTextResuming = strResuming
+ mTextClickToPause = strClickToPause
+ mTextPaused = strPaused
+ mTextPressEscapeToAbort = strPressEscapeToAbort
+
+ lblPressEscape.Caption = mTextPressEscapeToAbort
+End Sub
+
+Private Function SetProgressBarValue(ByRef dblNewValue As Double, Optional blnIncrementalUpdate As Boolean = False) As Double
+ ' Updates the value of the Progress bar based on dblNewValue, adjusting if necessary
+ ' Returns the % completed ratio
+ ' If blnIncrementalUpdate is true, then does not update dblLatestProgressBarValue
+
+ Dim dblRatioCompleted As Double
+
+ If dblNewValue < lngProgressMin Then dblNewValue = lngProgressMin
+ If dblNewValue > lngProgressMax Then dblNewValue = lngProgressMax
+
+ If lngProgressMax > lngProgressMin Then
+ dblRatioCompleted = (dblNewValue - lngProgressMin) / (lngProgressMax - lngProgressMin)
+ Else
+ dblRatioCompleted = 0
+ End If
+ If dblRatioCompleted < 0 Then dblRatioCompleted = 0
+ If dblRatioCompleted > 1 Then dblRatioCompleted = 1
+
+On Error GoTo ExitSetProgressBar
+
+ pbarProgress.Width = pbarProgressBox.Width * dblRatioCompleted
+
+ If Not blnIncrementalUpdate Then
+ dblLatestProgressBarValue = dblNewValue
+ End If
+
+ SetProgressBarValue = dblRatioCompleted
+
+ExitSetProgressBar:
+
+End Function
+
+Public Sub UpdateSubtaskProgressBar(ByVal dblNewValue As Double, Optional ByVal blnFractionallyIncreaseOverallProgressValue As Boolean = True)
+ Dim dblPartialIncrementToAdd As Double, dblNewTotalProgressValue As Double
+ Dim dblRatioCompleted As Double
+ Dim lngSubtaskProgressBarLength As Long
+
+ If dblNewValue < lngSubTaskProgressMin Then dblNewValue = lngSubTaskProgressMin
+ If dblNewValue > lngSubTaskProgressMax Then dblNewValue = lngSubTaskProgressMax
+
+ dblLatestSubTaskProgressBarValue = dblNewValue
+
+ If lngSubTaskProgressMax > 0 Then
+ dblRatioCompleted = (dblNewValue - lngSubTaskProgressMin) / lngSubTaskProgressMax
+ Else
+ dblRatioCompleted = 0
+ End If
+ If dblRatioCompleted < 0 Then dblRatioCompleted = 0
+ If dblRatioCompleted > 1 Then dblRatioCompleted = 1
+
+ On Error GoTo ExitUpdateSubProgressBarFunction
+
+ pbarSubProgress.Width = pbarSubProgressBox.Width * dblRatioCompleted
+
+ lngSubtaskProgressBarLength = lngSubTaskProgressMax - lngSubTaskProgressMin
+ If lngSubtaskProgressBarLength > 0 And blnFractionallyIncreaseOverallProgressValue Then
+ dblPartialIncrementToAdd = (dblNewValue - lngSubTaskProgressMin) / CDbl(lngSubtaskProgressBarLength)
+
+ dblNewTotalProgressValue = dblLatestProgressBarValue + dblPartialIncrementToAdd
+ If dblNewTotalProgressValue > dblLatestProgressBarValue Then
+ SetProgressBarValue dblNewTotalProgressValue, True
+ End If
+ End If
+
+ CheckForPauseUnpause
+
+ DoEvents
+
+ExitUpdateSubProgressBarFunction:
+
+End Sub
+
+Public Sub UpdateCurrentTask(strNewTask As String)
+ lblCurrentTask = strNewTask
+
+ CheckForPauseUnpause
+
+ DoEvents
+End Sub
+
+Public Sub UpdateCurrentSubTask(strNewSubTask As String)
+ lblCurrentSubTask = strNewSubTask
+
+ CheckForPauseUnpause
+
+ DoEvents
+End Sub
+
+Public Sub WasteTime(Optional Milliseconds As Integer = 250)
+ ' Wait the specified number of milliseconds
+
+ ' Use of the Sleep API call is more efficient than using a VB timer since it results in 0% processor usage
+ Sleep Milliseconds
+
+End Sub
+
+Private Sub cmdPause_Click()
+ Select Case ePauseStatus
+ Case ppUnpaused
+ ePauseStatus = ppRequestPause
+ cmdPause.Caption = mTextPreparingToPause
+ DoEvents
+ Case ppPaused
+ ePauseStatus = ppRequestUnpause
+ cmdPause.Caption = mTextResuming
+ DoEvents
+ Case Else
+ ' Ignore click
+ End Select
+
+End Sub
+
+Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
+ If KeyCode = vbKeyEscape Then
+ KeyPressAbortProcess = 2
+ KeyCode = 0
+ Shift = 0
+
+ ' Move the form to the bottom center of the screen to avoid having the msgbox popup under the form
+ MoveToBottomCenter
+ End If
+End Sub
+
+Private Sub Form_Load()
+
+ ' Put window in exact center of screen
+ SizeAndCenterWindow Me, cWindowLowerThird, 7450, 2800, False
+
+ SetStandardCaptionText
+
+ mblnWorking = False
+
+End Sub
+
+Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
+ Dim eResponse As VbMsgBoxResult
+ Dim lngCurrentTickCount As Long
+
+ If UnloadMode = vbFormControlMenu Then
+ ' If at least 20 seconds has elapsed since the last time the user tried
+ ' to close the form, then query whether they really want to do this
+ lngCurrentTickCount = GetTickCount()
+ If Abs(lngCurrentTickCount - mLastQueryUnloadTickCount) >= 20000 Then
+ ' Move the form to the bottom center of the screen to avoid having the msgbox popup under the form
+ Me.MoveToBottomCenter
+
+ eResponse = MsgBox("It appears that a task is currently in progress. Do you really want to close the progress window? If yes, this will cancel the currently running task.", vbQuestion + vbYesNo + vbDefaultButton2, "Cancel Task")
+ If eResponse = vbYes Then
+ ' Set KeyPressAbortProcess to 2 so that the program will cancel the task gracefully, and (hopefully) hide the progress window
+ KeyPressAbortProcess = 2
+ Else
+ ' User said no; set lngCurrentTickCount to 0 to guarantee MsgBox will reoccur if user clicks again
+ lngCurrentTickCount = 0
+ End If
+
+ Cancel = 1
+ End If
+ mLastQueryUnloadTickCount = lngCurrentTickCount
+ End If
+End Sub
diff --git a/frmprogress.frx b/frmprogress.frx
new file mode 100644
index 0000000..03ffc39
Binary files /dev/null and b/frmprogress.frx differ
diff --git a/frmviscosityForMeCN.frm b/frmviscosityForMeCN.frm
new file mode 100644
index 0000000..dafdcaa
--- /dev/null
+++ b/frmviscosityForMeCN.frm
@@ -0,0 +1,363 @@
+VERSION 5.00
+Begin VB.Form frmViscosityForMeCN
+ BorderStyle = 3 'Fixed Dialog
+ Caption = "Viscosity for Water/Acetonitrile Mixture"
+ ClientHeight = 3840
+ ClientLeft = 45
+ ClientTop = 435
+ ClientWidth = 9360
+ LinkTopic = "Form1"
+ MaxButton = 0 'False
+ MinButton = 0 'False
+ ScaleHeight = 3840
+ ScaleWidth = 9360
+ ShowInTaskbar = 0 'False
+ StartUpPosition = 3 'Windows Default
+ Begin VB.CommandButton cmdClose
+ Cancel = -1 'True
+ Caption = "Cl&ose"
+ Height = 360
+ Left = 7920
+ TabIndex = 13
+ Tag = "4000"
+ Top = 1440
+ Width = 1155
+ End
+ Begin VB.CommandButton cmdDefaults
+ Caption = "Defaults"
+ Height = 360
+ Left = 5880
+ TabIndex = 12
+ Tag = "16670"
+ Top = 1440
+ Width = 1800
+ End
+ Begin VB.PictureBox picChenHorvathEquation
+ Height = 990
+ Left = 120
+ Picture = "frmviscosityForMeCN.frx":0000
+ ScaleHeight = 930
+ ScaleWidth = 9075
+ TabIndex = 15
+ Top = 2160
+ Width = 9135
+ End
+ Begin VB.CommandButton cmdPlot
+ Caption = "Show Viscosity Plot"
+ Height = 360
+ Left = 5880
+ TabIndex = 11
+ Tag = "16660"
+ Top = 960
+ Width = 1800
+ End
+ Begin VB.CommandButton cmdCopyViscosity
+ Caption = "Copy Viscosity"
+ Default = -1 'True
+ Height = 360
+ Left = 5880
+ TabIndex = 10
+ Tag = "16650"
+ Top = 480
+ Width = 1800
+ End
+ Begin VB.TextBox txtViscosity
+ Height = 285
+ Left = 2520
+ Locked = -1 'True
+ TabIndex = 8
+ Text = "1"
+ Top = 1440
+ Width = 1095
+ End
+ Begin VB.ComboBox cboViscosityUnits
+ Height = 315
+ Left = 3720
+ Style = 2 'Dropdown List
+ TabIndex = 9
+ Tag = "7040"
+ Top = 1440
+ Width = 1815
+ End
+ Begin VB.TextBox txtPercentAcetonitrile
+ Height = 285
+ Left = 2520
+ TabIndex = 2
+ Tag = "16600"
+ Text = "20"
+ Top = 720
+ Width = 615
+ End
+ Begin VB.TextBox txtTemperature
+ Height = 285
+ Left = 2520
+ TabIndex = 5
+ Text = "25"
+ Top = 1080
+ Width = 1095
+ End
+ Begin VB.ComboBox cboTemperatureUnits
+ Height = 315
+ Left = 3720
+ Style = 2 'Dropdown List
+ TabIndex = 6
+ Tag = "16510"
+ Top = 1080
+ Width = 1815
+ End
+ Begin VB.Label lblReference
+ Caption = "Chen, H; Horvath, CJ. J. Chromatography A, 1995, 705, 3"
+ Height = 255
+ Index = 1
+ Left = 240
+ TabIndex = 17
+ Top = 3480
+ Width = 6135
+ End
+ Begin VB.Label lblReference
+ Caption = "Thompson, JD; Carr, P. Analytical Chemistry, 2002, 74, 4150-4159."
+ Height = 255
+ Index = 0
+ Left = 240
+ TabIndex = 16
+ Top = 3240
+ Width = 6135
+ End
+ Begin VB.Label lblChenHorvath
+ Caption = "Chen-Horvath Equation"
+ Height = 255
+ Left = 120
+ TabIndex = 14
+ Tag = "16580"
+ Top = 1920
+ Width = 1935
+ End
+ Begin VB.Label lblDirections
+ Caption = "Enter the percent acetonitrile and temperature and the theoretical viscosity will be computed."
+ Height = 495
+ Left = 120
+ TabIndex = 0
+ Tag = "16550"
+ Top = 120
+ Width = 4095
+ End
+ Begin VB.Label lblViscosity
+ Caption = "Solvent Viscosity"
+ Height = 255
+ Left = 120
+ TabIndex = 7
+ Tag = "7230"
+ Top = 1470
+ Width = 2295
+ End
+ Begin VB.Label lblPercentAcetonitrileUnits
+ Caption = "%"
+ Height = 255
+ Left = 3240
+ TabIndex = 3
+ Top = 750
+ Width = 255
+ End
+ Begin VB.Label lblPercentOrganic
+ Caption = "Percent Acetonitrile"
+ Height = 255
+ Left = 120
+ TabIndex = 1
+ Tag = "16560"
+ Top = 750
+ Width = 2295
+ End
+ Begin VB.Label lblTemperature
+ Caption = "Temperature"
+ Height = 255
+ Left = 120
+ TabIndex = 4
+ Tag = "16570"
+ Top = 1110
+ Width = 2295
+ End
+End
+Attribute VB_Name = "frmViscosityForMeCN"
+Attribute VB_GlobalNameSpace = False
+Attribute VB_Creatable = False
+Attribute VB_PredeclaredId = True
+Attribute VB_Exposed = False
+Option Explicit
+
+Private mUpdating As Boolean
+Private mFormLoaded As Boolean
+
+Private objViscosityPlot As CWSpectrumDLL.Spectrum
+
+Private Sub ComputeViscosity()
+
+ Dim eTemperatureUnits As utpUnitsTemperatureConstants
+ Dim eViscosityUnits As uviUnitsViscosityConstants
+
+ Dim dblTemperature As Double
+ Dim dblPercentAcetonitrile As Double
+ Dim dblViscosity As Double
+
+ dblPercentAcetonitrile = CDblSafe(txtPercentAcetonitrile)
+ dblTemperature = CDblSafe(txtTemperature)
+ eTemperatureUnits = cboTemperatureUnits.ListIndex
+ eViscosityUnits = cboViscosityUnits.ListIndex
+
+ dblViscosity = Rnd(1) * 10
+ dblViscosity = objMwtWin.CapFlow.ComputeMeCNViscosity(dblPercentAcetonitrile, dblTemperature, eTemperatureUnits, eViscosityUnits)
+
+ txtViscosity = Round(dblViscosity, 6)
+
+ UpdateViscosityPlot
+End Sub
+
+Private Sub CopyViscosityToCapillaryFlowForm()
+ If IsNumeric(txtViscosity) Then
+ frmCapillaryCalcs.cboCapValue(cccViscosityUnits).ListIndex = cboViscosityUnits.ListIndex
+ frmCapillaryCalcs.txtCapValue(cctViscosity) = txtViscosity
+ End If
+End Sub
+
+Private Sub PlotViscosityVsTemperature()
+ If objViscosityPlot Is Nothing Then
+ Set objViscosityPlot = New CWSpectrumDLL.Spectrum
+ objViscosityPlot.SetCursorVisible False
+ End If
+ objViscosityPlot.ShowSpectrum
+ UpdateViscosityPlot
+End Sub
+
+Public Sub SetDefaultValues()
+ mUpdating = True
+ txtTemperature = "25"
+ cboTemperatureUnits.ListIndex = utpCelsius
+
+ txtPercentAcetonitrile = "20"
+ cboViscosityUnits.ListIndex = uviPoise
+
+ mUpdating = False
+ ComputeViscosity
+
+End Sub
+
+Public Sub SetViscosityValues(strViscosity As String, intViscosityUnits As Integer)
+
+ txtViscosity = strViscosity
+ If intViscosityUnits >= 0 And intViscosityUnits < cboViscosityUnits.ListCount Then
+ cboViscosityUnits.ListIndex = intViscosityUnits
+ End If
+
+End Sub
+
+Private Sub UpdateViscosityPlot()
+
+ Const START_X As Long = 0
+ Const END_X As Long = 100
+ Const DELTA_X As Long = 1
+
+ Dim lngIndex As Long
+
+ Dim lngDataCount As Long
+ Dim dblYValues() As Double
+
+ Dim eTemperatureUnits As utpUnitsTemperatureConstants
+ Dim dblTemperature As Double
+
+ If Not objViscosityPlot Is Nothing Then
+
+ lngDataCount = (END_X - START_X + 1) * DELTA_X
+ ReDim dblYValues(lngDataCount - 1)
+
+ dblTemperature = CDblSafe(txtTemperature)
+ eTemperatureUnits = cboTemperatureUnits.ListIndex
+
+ For lngIndex = START_X To END_X Step DELTA_X
+ dblYValues(lngIndex) = objMwtWin.CapFlow.ComputeMeCNViscosity(CDbl(lngIndex), dblTemperature, eTemperatureUnits, cboViscosityUnits.ListIndex)
+ Next lngIndex
+
+ objViscosityPlot.SetSeriesPlotMode 1, pmLines, True
+ objViscosityPlot.SetDataYOnly 1, dblYValues(), lngDataCount, START_X, DELTA_X, LookupLanguageCaption(16600, "Viscosity")
+ objViscosityPlot.SetLabelXAxis LookupLanguageCaption(16610, "Percent Acetonitrile")
+ objViscosityPlot.SetLabelYAxis LookupLanguageCaption(16600, "Viscosity") & " (" & cboViscosityUnits.Text & ")"
+
+ objViscosityPlot.SetDisplayPrecisionX 0
+ If cboViscosityUnits.ListIndex = uviPoise Then
+ objViscosityPlot.SetDisplayPrecisionY 4
+ Else
+ objViscosityPlot.SetDisplayPrecisionY 2
+ End If
+
+ End If
+End Sub
+
+Private Sub PopulateComboBoxes()
+
+ PopulateComboBox cboTemperatureUnits, True, "Celsius|Kelvin|Fahrenheit", 0 '7120
+ PopulateComboBox cboViscosityUnits, True, "Poise [g/(cm-sec)]|centiPoise", 0 '7040
+
+End Sub
+
+Private Sub cboTemperatureUnits_Click()
+ ComputeViscosity
+End Sub
+
+Private Sub cboViscosityUnits_Click()
+ ComputeViscosity
+End Sub
+
+Private Sub cmdClose_Click()
+ Me.Hide
+End Sub
+
+Private Sub cmdCopyViscosity_Click()
+ CopyViscosityToCapillaryFlowForm
+End Sub
+
+Private Sub cmdDefaults_Click()
+ SetDefaultValues
+End Sub
+
+Private Sub cmdPlot_Click()
+ PlotViscosityVsTemperature
+End Sub
+
+Private Sub Form_Load()
+ PopulateComboBoxes
+ mFormLoaded = True
+End Sub
+
+Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
+ QueryUnloadFormHandler Me, Cancel, UnloadMode
+End Sub
+
+Private Sub txtPercentAcetonitrile_Change()
+ ComputeViscosity
+End Sub
+
+Private Sub txtPercentAcetonitrile_GotFocus()
+ HighlightOnFocus txtPercentAcetonitrile
+End Sub
+
+Private Sub txtPercentAcetonitrile_KeyPress(KeyAscii As Integer)
+ TextBoxKeyPressHandler txtPercentAcetonitrile, KeyAscii, True, True
+End Sub
+
+Private Sub txtPercentAcetonitrile_LostFocus()
+ ValidateTextboxValueDbl txtPercentAcetonitrile, 0, 100, 50
+End Sub
+
+Private Sub txtTemperature_Change()
+ ComputeViscosity
+End Sub
+
+Private Sub txtTemperature_GotFocus()
+ HighlightOnFocus txtTemperature
+End Sub
+
+Private Sub txtTemperature_KeyPress(KeyAscii As Integer)
+ TextBoxKeyPressHandler txtTemperature, KeyAscii, True, True, True
+End Sub
+
+Private Sub txtTemperature_LostFocus()
+ ValidateTextboxValueDbl txtTemperature, -500, 10000, 25
+End Sub
diff --git a/frmviscosityForMeCN.frx b/frmviscosityForMeCN.frx
new file mode 100644
index 0000000..8dec7fc
Binary files /dev/null and b/frmviscosityForMeCN.frx differ
diff --git a/html/Abbreviations.htm b/html/Abbreviations.htm
new file mode 100644
index 0000000..ecbf58d
--- /dev/null
+++ b/html/Abbreviations.htm
@@ -0,0 +1,14 @@
+
+
+
+To use an abbreviation, simply type it as you would type any element. Use the F3 key (or the options on the Program Preferences Window) to cycle through the three abbreviation recognition modes: Normal recognition, Amino Acid (Extended) recognition, and No Recognition. The MWT_ABBR.DAT file contains the default abbreviations included with the program. Besides using the default abbreviations, you can edit the abbreviationsto add your own. Lastly, you can expand the abbreviations into their elemental compositions.
+
+
diff --git a/html/AdvanceOnCalculate.htm b/html/AdvanceOnCalculate.htm
new file mode 100644
index 0000000..e5314bc
--- /dev/null
+++ b/html/AdvanceOnCalculate.htm
@@ -0,0 +1,14 @@
+
+
+
+
+Advance on Calculate
+
+
+
+The Advance on Calculate feature sets whether or not a new formula is created in Multi View mode when the Calculate button or the Enter key is pressed.
The Amino Acid Converter can be used to convert sequences of amino acid residues between 1 and 3 letter notation. I added this feature because the main program window only supports 3 letter amino acid abbreviations, but sequences obtained via web searches of sequence databases are typically in one letter notation. Use the arrow buttons to convert either direction.
+
+
When converting a sequence, if a 1 letter abbreviation is not recognized then 'Xxx' will be shown it its place in the 3 letter window. Conversely, if a 3 letter sequence is not recognized, then 'X' will be shown in its place. Only amino acid abbreviations may be entered for conversion -- do not include the initial H or OH in the 3 letter abbreviation.
+
+
The sequence shown in the 3 letter textbox can be copied to the main program window using the "Copy 3 letter sequence" button. When copying, an H is added to the beginning of the sequence and an OH to the end. This is necessary to obtain the correct molecular weight of the peptide chain.
+
+
Use the dropdown box to select which formula to copy the sequence to. The default formula number is set to one more than the highest formula number that exists in the main window, unless the maximum number of formulas already exists, in which case it is set to the highest number.
+
+I am a graduate of the University of North Carolina chemistry program, specializing in proteomics and bioinformatics while working with Dr. James Jorgenson. My areas of expertise include analytical instrumentation design and automation, microcolumn liquid chromatography, and mass spectrometry, in addition to software design using both Visual Basic and LabView. I am currently working with Dr. Richard D. Smith at Pacific Northwest National Laboratory in Richland, WA. I have been programming since 1986 when I learned BASIC on an Apple //c (with 128 KB of Ram and no hard disk). Since then, I have updated to GW-Basic, then QuickBasic v4.5 and QuickBasic v7.1 for DOS, Visual Basic 3.0 for Windows, Visual Basic 5.0 for Windows 95, and now Visual Basic 6.0. I have experience with C and C++ programming but predominantly use VB due to the ease and simplicity with which software can be written.
+
+When the option to Automatically Copy the Current Formula's Molecular Weight After each Calculation is turned on, the molecular weight value of the currently selected formula will be automatically copied to the clipboard after each calculation (initiated by pressing Enter, clicking the calculate button, or moving to a different formula with the arrow keys). Note that only the molecular weight value is copied, regardless of the Standard Deviation Mode. The shortcut key for toggling this option is Ctrl+U
+When the autosave option is checked, all options, values, and formulas will be saved upon program exit. This feature is on by default and is useful for exiting the program then restarting it later with the same formulas loaded. This can also be useful if you would like to set the values in the Formula Finder and/or Mole/Mass Converter to your own defaults. Values will not be saved to disk if /X or /Z was used at the command line.
+The program is available via the web at http://www.alchemistmatt.com/ and http://ncrr.pnl.gov/software/ The installation zip file (for example mwt6_39.zip) contains MSVBVM60.DLL and a full installation program, utilizing the Windows MSI Installer.
+For Radioactive elements, the most stable isotope is NOT used in average weights mode; instead, the weight of the most common isotope is used. See the isotopes section for the method of indicating an exact isotopic mass. Data originally obtained from the Perma-Chart Science Series Chemical Periodic Table, 1993; ISBN 1-55080-063-9, then updated using the 1997 IUPAC standard atomic weights and uncertainties found in Pure Appl. Chem., 68, 2339-2359 (1996); 69, 2471-2473 (1997).
+
+Uncertainties come from CRC Handbook of Chemistry and Physics, except for Radioactive elements, where uncertainty was estimated to be .n5 where n represents the number of digits after the decimal point but before the last number of the molecular weight. For example, for Nobelium, MW = 259.1009 (±0.0005)
+The Mathematics behind the Isotopic Extremes error handler
+
+When a user types in an isotopic mass (eg. ^13C for carbon-13), the program checks to see if the isotope is a reasonable value. Obviously, ^5C (carbon-5) would be unreasonable because any compound with 6 protons (i.e. carbon) must have a minimum weight of 6. However, upon examining the Table of Isotopes in the CRC Handbook of Chemistry and Physics, I found that very few compounds have zero neutrons (and thus an atomic weight equal to the number of protons in the element). Therefore, I examined the table and used MS Excel to create a graph of the highest and lowest isotopic masses for every element (shown below). I then determined two fit-lines that encompassed all the data points -- one for the upper extreme and one for the lower extreme.
+
+
+
+Since most isotopic masses occur somewhere around the value twice the atomic number (Z) of the element, I chose to work with the value:
+
+x = isotope_value - Z*2
+
+ where isotope_value is the value present after the caret (^) in the formula.
+
+The curve that describes the upper limit of these x values is:
+
+max_x = INTEGER(0.63*Z + 6)
+
+where max_x is the maximum allowable x value before a warning is issued.
+
+The curve that describes the lower limit of these x values is:
+
+min_x = INTEGER(0.008*Z² - 0.4*Z - 6)
+
+where min_x is the minimum allowable x value before a warning is issued. The results were converted to integers to aid in program design.
+
+Finally, because the min_x value is too low for some of the lighter elements, I included a test to make sure that isotope_value was at least as large as Z, or else a warning was again issued to the user. The method is an approximate test on the isotope value, and is designed to catch the outrageous isotopic masses. It does not catch the borderline ones since that would have increased the program size and memory usage by too much.
+
+Examples:
+
+For Carbon:
+
+^13C has z = 6, x = 1, max_x = 9 and min_x = -9
+
+Because x < 9 and x > -9 and x > 6, no warning is issued.
+
+(The average atomic weight of carbon is 12.011)
+
+^25C has z = 6, x = 10, max_x = 9 and min_x = -9
+
+Because x > 9, a warning that 25 is probably too large is given.
+
+In reality, the heaviest known carbon isotope is carbon-16.
+
+^5C has z = 6, x = -7, max_x = 9 and min_x = -9
+
+Although x < 9 and x > -9, x is less than 6 so a warning is again issued.
+
+In reality, the lightest known carbon isotope is carbon-9.
+
+For Silver:
+
+^100Ag has z = 47, x = 6, max_x = 35 and min_x = -8
+
+Because x < 35 and x > -8 and x > 47, no warning is issued.
+
+(The average atomic weight of silver is 107.87)
+
+^130Ag has z = 47, x = 36, max_x = 35 and min_x = -8
+
+Because x > 35, a warning that 130 is probably too large is given.
+
+In reality, the heaviest known silver isotope is silver-122.
+
+^85Ag has z = 47, x = -9, max_x = 35 and min_x = -8
+
+Because x < -8 a warning that 85 is probably too small is given.
+
+In reality, the lightest known silver isotope is carbon-96.
+
+The above calculations show, as mentioned above, that this method catches the outrageous isotopic masses but does not catch the borderline cases. Furthermore, it should also be evident that this method is more accurate for the heavier elements, a consequence of the unusual isotopic behavior of the lighter elements.
Percent Composition and Standard Deviation calculations
+
+The Mathematics behind the Molecular Weight, Percent
+
+Composition and Standard Deviation Calculations
+
+(Concept from Molar Mass program by Christopher King at Eastern Oregon State College).
+
+For Addition:
+
+In general: For f = x + y - z, the standard deviation of f, sf, is equal to Sqrt[(sx)2 + (sy)2 + (sz)2], which is in words, the std. dev. of f is equal to the square root of the sum of the squares of the std. deviations of each term in the original sum.
+
+Applied to the Molecular Weight of a molecule:
+
+MW = ax + by + cz + ..., where a is the number of atoms of weight x, b is the number of atoms of weight y, etc. The Std. Dev. of MW, smw = Sqrt[a(sx)2 + b(sy)2 + ...]
+
+NOTE: The reason the equation uses a(sx)2 is that if the terms were added up consecutively 'a' times for the same element, we would have (sx)2 + (sx)2 + (sx)2 etc. up to 'a' times, which combines to be a(sx)2
+In general: For f = x*y/z, the standard deviation of f, sf is equal to f*Sqrt[(sx / x)2 + (sy / y)2 + (sz / z)2], which is in words, the std. dev. of f is equal to f times the square root of the sum of squares of the quotients of the std. deviations of each term divided by each term itself.
+
+Applied to the Percent Composition of a molecule:
+
+%Comp = (a*x/MW)*100, where a is the number of atoms of weight x and MW is the total molecular weight of the molecule. The Std. Dev. of %Comp, s%c = %c*Sqrt[(sa/a)2 + (sx/x)2 + (smw/mw)2]. But, since a is a finite number, its sa = 0, so the formula becomes: s%c = %c*Sqrt[(sx / x)2 + (smw / mw)2].
+
+For example, for chlorobenzene, C6H5Cl:
+
+%Comp of Carbon = 6*12.011/112.5584*100 = 64.02543%
+The Mathematics behind the Percent Solver routine
+
+For determining the closest fit between multiple target values and actually calculated data, the value of the following formula is minimized: diff = Sum[(actual%value_i - target%value_i)2], which in words is the summation of the square of the ith calculated percentage value minus the ith target value. The minimum value of this formula should be obtained when all actual values are closest to their target values.
+A colleague of mine requested this feature for the purpose of trying to figure out if a compound he had synthesized and sent off for elemental analysis had a little bit of water in it (hadn't been completely dried), as in C6H6-[.1H2O], to see if the theoretical percent composition data would better match the actual lab results.
+
+NOTE: The percent solver feature will perform this operation for you.
+
+In earlier versions, decimal numbers could only be used after brackets and not after closing parentheses or after a dash, however this restriction has now been removed. Therefore, the above example could have also been entered as (Na).2Cl or Na.2Cl or even Cl-.2Na
+
+If you would like brackets, [ and ], to be treated like regular parentheses, you can change this option in the Program Preferences Window. However, when brackets are being treated as parentheses, all percent solver features will be disabled.
+Molecular weights of compounds (formulas) listed in a text file can be computed and written to an output file. The Formula Finder can be also be run in batch analysis mode using appropriate Batch Analysis Commands (see below). In addition, amino acid sequences can be converted from 1 to 3 letter notation (or from 3 to 1 letter notation).
+
+
Initiate batch analysis mode by either choosing "Calculate weights" from under the File menu and selecting the file, or by using the /F:filename switch at the command line. The input file must be a text file with each line containing a single molecular formula, an amino acid sequence, a numeric mass to use for the formula finder, a batch analysis command (see below), or a comment (beginning with a ; or ').
+
+
Batch Molecular Weight Computation
+
+
The default mode for batch analysis is molecular weight computation. To use this mode, the text file need only contain a single, valid molecular formula on each line. Each formula's molecular weight will be computed, and the results written to the output file (see below for filename). The output file will contain the original formula, plus its molecular weight, separated by a Tab (configurable using DELIMETER=). By default, the standard deviation is included, formatted depending on the current setting for the standard deviation mode. Whether or not to include the standard deviation, in addition to its format, can be customized using STDDEVMODE=. If there is an error in the formula, the error will be listed in the output file. If a FF= Batch Command was issued earlier in the file, a MW= command can be used to switch back to Molecular Weight Computation mode (see the example input file below).
+
+
The Batch Analysis Command WEIGHTMODE={AVERAGE|ISOTOPIC|INTEGER} can be used to set the weight mode for computations. For example, to switch to isotopic mode use WEIGHTMODE=ISOTOPIC and to switch back to average mode use WEIGHTMODE=AVERAGE. You can suppress the display of the source formula using MWSHOWSOURCEFORMULA=OFF. You can suppress the display of the formula's mass using SHOWMASS=OFF. This is useful if you simply wish to convert formulas to their empirical formula (using EMPIRICAL=ON).
+
+
If you need to compute the mass of peptides listed in 1-letter notation, you can use ONELETTERPEPTIDEWEIGHTMODE=ON. The default prefix and suffix groups for the peptides are H and OH, though this can be changed with PEPTIDEWEIGHTMODEPEPTIDEPREFIX and PEPTIDEWEIGHTMODEPEPTIDESUFFIX. To compute the mass of peptides listed in 3-letter notation, simply use the default MW= molecular weight computation mode. However, note that 3-letter abbreviation peptide formulas must explicitly include the H and OH in the formula to obtain the correct mass. For example, GlyLeuTyr will return a mass of 333.38234, while HGLyLeuTyrOH (or H-GlyLeuTyr-OH) will return the correct mass of 351.39762 (in average mass mode).
+
+
+
Batch Formula Finder Mode
+
In order to enter formula finder mode you must place the command FF= on a line in the input text file. You may also optionally specify which elements to use for the formula finder searching by listing them on the same line as the FF= command, separated by commas (if not specified, the previously enabled elements will be used). The Batch Analysis commands MAXHITS=num and TOLERANCE=num can be used to specify the maximum number of hits or the search tolerance. If either of these commands is omitted, the values currently set in the Molecular Weight Calculator Formula Finder window will be used.
+
+
Once formula finder mode has been enabled (using FF=), a list of numeric values to match elemental combinations to can be given, with each value listed on its own line. For each value, a list of matching empirical formulas will be determined, and the results written to the output file. The MAXHITS= or TOLERANCE= command can be given at any time in the list in order to change one of the values. Additionally, the FF= command can be re-issued with a new list of search elements to use. Finally, the MW= command can be used to switch back to Molecular Weight Computation Mode.
+
+
+
Batch Amino Acid Notation Conversion Mode
+
The third mode for batch analysis is amino acid sequence notation conversion. Use AACONVERT3TO1=ON for 3 letter to 1 letter conversion, or AACONVERT1TO3=ON for the reverse. After this, each line will be treated as a sequence and converted as desired. By default the source sequence is outputted, followed by the converted sequence. To prevent output of the source sequence, use the command AASHOWSEQUENCEBEINGCONVERTED=OFF
+
+
+
Isotopic Distribution Mode
+
The fourth mode for batch analysis is computation of isotopic distributions for a given formula. Enable using ISOTOPICDISTRIBUTION=ON. After this, each line containing a valid formula will have its isotopic distribution computed and written to the output file. Optionally, set the charge state to use for m/z calculations using ISOTOPICDISTRIBUTIONCHARGE=num, where num is an integer greater than 0.
+
+
+
Output File and Automation
+
+
The output filename will be the input filename, plus the extension ".out". For example, if the input file is "formulas.txt", the output file will be "formulas.txt.out". If the /F:filename switch is used on the command line, the Molecular Calculator program will exit upon completion of processing the input file. Additionally, you can specify an alternate output filename using the /O:outfile switch. Use the /Y switch to suppress the "Are you sure you want to replace?" dialog box from appearing when an existing output file is found.
+
+
+To process a number of files at once, simply create a batch file (.BAT) containing lines to call the Molecular Weight calculator program and process each file. For example, you could create GO.BAT containing the lines:
+Then, run GO.BAT and the files will be processed.
+
+
Batch Analysis Command Summary
+
Values in brackets [] are optional (do not use the brackets). Words in curly brackes {} are a list of potential words; choose just one of the words and do not use the curly brackes or comma. num is a valid number
+
+
Command and options
Explanation
Default
+
MW=
Enable Normal Molecular Weight Computation mode
+
+
WEIGHTMODE={AVERAGE|ISOTOPIC|INTEGER}
Weight mode to use.
The weight mode in effect the last time the program was run (or the current weight mode if the program is running).
+
+
STDDEVMODE={SHORT|SCIENTIFIC|DECIMAL|OFF}
The standard deviation mode, defining how to format the standard deviation of each element's weight
The standard deviation mode in effect the last time the program was run (or the current standard deviation mode if the program is running).
+
+
MWSHOWSOURCEFORMULA={ON|OFF}
When ON, will output the source formula, followed by either the molecular weight, the empirical formula, or the formula with expanded abbreviations, separating the two with the currently defined delimeter.
ON
+
+
CAPITALIZED={ON|OFF}
If ON, will output the source formula properly capitalized. For example, c6h6 would be outputted as C6H6. Default is OFF.
OFF
+
+
EMPIRICAL={ON|OFF}
If ON, will convert the source formula to its empirical formula and output the result. If MWSHOWSOURCEFORMULA=ON, will show the source formula before the empirical formula, separating with the currently defined delimeter. Unless SHOWMASS=OFF, the molecular weight will also be outputted.
OFF
+
+
EXPANDABBREVIATIONS={ON|OFF}
If ON, will expand the abbreviations in the source formula to their elemental equivalent, and output the result. If MWSHOWSOURCEFORMULA=ON, will show the source formula before the resultant formula, separating with the currently defined delimeter. Unless SHOWMASS=OFF, the molecular weight will also be outputted.
OFF
+
+
SHOWMASS={ON|OFF}
When ON, will output the mass of each formula encountered in normal weight computation mode.
ON
+
+
ONELETTERPEPTIDEWEIGHTMODE={ON|OFF}
When ON, will treat the input formulas as peptides in 1-letter notation. The default peptide prefix is H and default peptide suffix is OH. Use PEPTIDEWEIGHTMODEPEPTIDEPREFIX and PEPTIDEWEIGHTMODEPEPTIDESUFFIX to change the default prefix and suffix. Note that this mode is not appropriate for computing masses of peptides in 3-letter notation. Those peptide masses can be computed using the Normal Molecular Weight Computation (MW=) mode.
OFF
+
+
PEPTIDEWEIGHTMODEPEPTIDEPREFIX={custom formula}
Use this to set a custom prefix formula for peptide masses computed when ONELETTERPEPTIDEWEIGHTMODE=ON.
H
+
+
PEPTIDEWEIGHTMODEPEPTIDESUFFIX={custom formula}
Use this to set a custom suffix formula for peptide masses.
The delimeter to use to separate the source formula and the computed mass, or the source sequence and the converted sequence. Use one of the standard <> commands (for example DELIMETER=<TAB>) or provide a custom symbol (for example DELIMETER=, to set the delimeter to a comma)
<TAB>
+
+
AACONVERT3TO1={ON|OFF}
When ON, will treat each line as a set of 3 letter amino acid abbreviations, and will output the equivalent 1 letter sequence.
OFF
+
+
AACONVERT1TO3={ON|OFF}
When ON, will treat each line as a set of 1 letter amino acid abbreviations, and will output the equivalent 3 letter sequence.
OFF
+
+
AASPACEEVERY10={ON|OFF}
When ON, will add a space every 10 residues in the output sequence.
OFF
+
AA1TO3USEDASH={ON|OFF}
When ON, will separate each residue with a dash (only applicable for 1 to 3 letter conversion).
OFF
+
+
AASHOWSEQUENCEBEINGCONVERTED={ON|OFF}
When ON, will output the source sequence, followed by the converted sequence, separated the currently defined delimeter. It is useful to set this option to OFF if you are converting long sequences.
ON
+
+
FF=[Element1[,Element2][,...]]
Enable Formula Finder mode. Optionally provide a comma-separated list of elements or abbreviations to search for.
If no list of elements is supplied after the equals sign, then the options last used for the formula finder will be used.
+
+
MAXHITS=num
Define the maximum number of formula finder hits
+
+
TOLERANCE=num
Set the formula finder search tolerance
+
+
ISOTOPICDISTRIBUTION={ON|OFF}
When ON, will write out the isotopic distribution for any line containing a valid formula.
+
+
ISOTOPICDISTRIBUTIONCHARGE=num
Define the charge state to use for computing m/z values in Isotopic Distribution mode.
+
+
; Comment
Insert a comment by starting a line with a semicolon or an apostrophe. You cannot add a comment on the same line as a Batch Analysis Command or any other text to be used for computation.
+
+
ECHOCOMMENTS={ON|OFF}
When ON, will write any blank lines and comment lines found in the source file to the output file.
OFF
+
+
VERBOSEMODE={ON|OFF}
When ON, will write a comment to the output file each time a command is found in the source file. Error messages will be written to the output file regardless of the VERBOSEMODE setting.
+; Set weight mode
+WEIGHTMODE=AVERAGE
+
+; Set Standard Deviation mode
+STDDEVMODE=OFF
+
+; Return capitalized (formatted) formulas
+CAPITALIZED=ON
+
+fecl3-6h2o
+
+; Expand abbreviations
+EXPANDABBREVIATIONS=ON
+
+etoac
+
+; Don't display the source formula
+MWSHOWSOURCEFORMULA=OFF
+etoac
+
+; Don't display the weight
+SHOWWEIGHT=OFF
+etoac
+
+; Convert to empirical formula
+; Note: no need to use EXPANDABBREVIATIONS=OFF
+EMPIRICAL=ON
+
+fecl3-6h2o
+etoac
+
+; Re-enable display of the source formula
+MWSHOWSOURCEFORMULA=ON
+UreaC4(NH2)4Ca
+
+; Convert amino acid sequence from 1 letter to 3 letter sequence
+AACONVERT3TO1=ON
+
+GluGlaPheLeu
+Val-Ile-Arg
+
+AASPACEEVERY10=ON
+; For really long sequences, can disable display of the source sequence
+AASHOWSEQUENCEBEINGCONVERTED=OFF
+GluGlaPheLeuVAlIleArgPheTyrMetCysValGluGlaGluGlaPheLeuVAlIleArgPheTyrMetCysValGluGla
+
+AACONVERT1TO3=ON
+FLEELYR
+MLTSCDEEF
+
+AASHOWSEQUENCEBEINGCONVERTED=ON
+AA1TO3USEDASH=ON
+FLEELYR
+
+; To re-enable plain molecular weight computation, use MW=
+; Note: this will also disable EMPIRICAL= and EXPANDABBREVIATIONS=
+; Further, it will automatically re-enable SHOWWEIGHT
+MW=
+
+C4N8OH2
+
+; Compute the mass of peptides given in 1-letter notation
+ONELETTERPEPTIDEWEIGHTMODE=ON
+
+FLEELYR
+MLTSCDEEF
+
+; Don't show the source formula when computing the peptide's mass
+MWSHOWSOURCEFORMULA=OFF
+
+MLTSCDEEF
+
+; Enable formula finder mode using FF=, specifying the elements to use in searching
+; Can also specify weight mode, maximum number of hits, and tolerance
+FF=C,H,N,O,Cl,Bpy
+WEIGHTMODE=ISOTOPIC
+MAXHITS=5
+TOLERANCE=0.05
+403.84
+300.58
+
+; The tolerance can be changed
+TOLERANCE=0.02
+403.885
+
+; The maximum number of hits can be changed
+MAXHITS=10
+632.43
+
+; The search elements can be changed
+FF=N,Br,H,Li
+MAXHITS=2
+389.32
+
+; Can disable verbose output
+VERBOSEMODE=OFF
+; Additionally, could enable echo of comments
+ECHOCOMMENTS=ON
+; Switching back (this comment is in the source file)
+
+MW=
+MWSHOWSOURCEFORMULA=ON
+NH2
+C6H5Cl
+^13C6H5Cl
+
+WEIGHTMODE=AVERAGE
+FeCl3-6H2O
+
+
+
+; So is this one, along with the 3 blank lines above
+MWSHOWSOURCEFORMULA=OFF
+NH2
+C6H5Cl
+^13C6H5Cl
+FeCl3-6H2O
+
+VERBOSEMODE=ON
+DELIMETER=<SPACE>
+CAPITALIZED=on
+c6h5cl
+
+DELIMETER=,
+c6h5cl
+
+ECHOCOMMENTS=OFF
+
+; Enable Isotopic Distribution Mode
+ISOTOPICDISTRIBUTION=ON
+; Simply enter a formula to obtain the isotopic distribution
+CH2(CH2)7CH2Br
+
+; Change the charge state with the following command
+ISOTOPICDISTRIBUTIONCHARGE=2
+CH2(CH2)7CH2Br
+
+
+
+
Resultant Output File
+
+; Average Weight Mode Enabled
+; Standard deviations will not be displayed
+; Source formula will be displayed with proper capitalization
+FeCl3-6H2O 270.29478
+
+; Abbreviation expansion now On
+EtOac CH3CH2C2H3O2 88.10512
+; Display of source formula is now Off
+CH3CH2C2H3O2 88.10512
+; Will not display the molecular weight (mass) of each formula
+CH3CH2C2H3O2
+
+; Converting formulas to empirical formulas now On
+H12Cl3FeO6
+C4H8O2
+; Display of source formula is now On
+UreaC4(NH2)4Ca C5H12CaN6O
+
+; 3 letter to 1 letter amino acid symbol conversion now On
+GluGlaPheLeu EUFL
+Val-Ile-Arg VIR
+; Will add a space every 10 amino acids
+; Will only show the converted sequence, not the sequence being converted
+EUFLVIRFYM CVEUEUFLVI RFYMCVEU
+
+; 1 letter to 3 letter amino acid symbol conversion now On
+PheLeuGluGluLeuTyrArg
+MetLeuThrSerCysAspGluGluPhe
+; Will show sequence being converted, in addition to the converted sequence
+; Will separate residues with a dash
+FLEELYR Phe-Leu-Glu-Glu-Leu-Tyr-Arg
+
+; Normal Molecular Weight Mode Enabled (other modes turned Off)
+C4N8OH2 178.112
+
+; One letter Amino Acid weight mode: input formulas are assumed to be peptides in one-letter notation
+H-PheLeuGluGluLeuTyrArg-OH 969.09172
+H-MetLeuThrSerCysAspGluGluPhe-OH 1074.18464
+; Display of source formula is now Off
+1074.18464
+
+; Formula Finder Mode Enabled. Search elements/abbreviations: C, H, N, O, Cl, Bpy
+; Isotopic Weight Mode Enabled
+; FF Maximum Hits set to 5
+; FF Tolerance set to 0.05
+; FF Searching: 403.84
+Compounds found: 5
+C2BpyCl6N MW=403.8849368 dm=0.0449368
+C5H6Cl8N3O MW=403.8019086 dm=-0.0380914
+C6H6Cl8NO2 MW=403.7906756 dm=-0.0493244
+C6H8Cl8N2O MW=403.8144838 dm=-0.0255162
+C7H8Cl8O2 MW=403.8032508 dm=-0.0367492
+
+; FF Searching: 300.58
+Compounds found: 0
+
+; FF Tolerance set to 0.02
+; FF Searching: 403.885
+Compounds found: 5
+CH7Cl7N10 MW=403.8674832 dm=-0.0175168
+C2BpyCl6N MW=403.8849368 dm=-0.0000632
+C2H9Cl7N9 MW=403.8800584 dm=-0.0049416
+C3H2BpyCl6 MW=403.897512 dm=0.012512
+C3H9Cl7N7O MW=403.8688254 dm=-0.0161746
+
+; FF Maximum Hits set to 10
+; FF Searching: 632.43
+Compounds found: 10
+CH24Bpy3N8O MW=632.413531800001 dm=-0.0164682
+C2H26Bpy3N7O MW=632.426107000001 dm=-0.003893
+C3H26Bpy3N5O2 MW=632.414874000001 dm=-0.015126
+C4H28Bpy3N4O2 MW=632.427449200001 dm=-0.0025508
+C5H28Bpy3N2O3 MW=632.416216200001 dm=-0.0137838
+C5H30Bpy3N3O2 MW=632.440024400001 dm=0.0100244
+C6H30Bpy3NO3 MW=632.428791400001 dm=-0.0012086
+C7H31Bpy3ClN MW=632.420724000002 dm=-0.009276
+C7H32Bpy3O3 MW=632.441366600002 dm=0.0113666
+C8H33Bpy3Cl MW=632.433299200002 dm=0.0032992
+
+
+; Formula Finder Mode Enabled. Search elements/abbreviations: H, N, Br, Li
+; FF Maximum Hits set to 2
+; FF Searching: 389.32
+Compounds found: 2
+H47Br3Li11N2 MW=389.3049672 dm=-0.0150328
+H47Br3Li13N MW=389.3339032 dm=0.0139032
+
+; Switching back (this comment is in the source file)
+
+NH2 16.0187232
+C6H5Cl 112.007976
+^13C6H5Cl 118.007976
+
+FeCl3-6H2O 270.29478
+
+
+
+; So is this one, along with the 3 blank lines above
+16.02262
+112.5566
+118.4924
+270.29478
+
+; Verbose mode is now on
+; Delimeter now a Space
+; Source formula will be displayed with proper capitalization
+C6H5Cl 112.5566
+
+; Delimeter now ,
+C6H5Cl,112.5566
+
+; Comments found in the source file will not be written to the output file
+
+; Isotopic Distribution calculations now On
+Isotopic Abundances for CH2(CH2)7CH2Br
+ Mass/Charge Fraction Intensity
+ 205.05919 0.4588825 100.00
+ 206.05919 0.0459075 10.00
+ 207.05919 0.4484460 97.73
+ 208.05919 0.0447120 9.74
+ 209.05919 0.0020020 0.44
+ 210.05919 0.0000528 0.01
+ 211.05919 0.0000017 0.00
+
+; Isotopic Distribution charge set to 2
+Isotopic Abundances for CH2(CH2)7CH2Br
+ Mass/Charge Fraction Intensity
+ 103.03329 0.4588825 100.00
+ 103.53329 0.0459075 10.00
+ 104.03329 0.4484460 97.73
+ 104.53329 0.0447120 9.74
+ 105.03329 0.0020020 0.44
+ 105.53329 0.0000528 0.01
+ 106.03329 0.0000017 0.00
+
+The Molecular Weight Calculator now includes the built-in math calculator that was present in the Dos Version. This is a simple calculator where you can enter expressions to evaluate. Valid operators are +, -, *, and / for addition, subtraction, multiplication, and division, plus ^ for raising a number to a power. The calculator also supports the use of parentheses, including assuming multiplication for numbers directly before or after parentheses, for example 3(4+3) means 3*(4+3).
+
+
The calculator follows operator precedence rules appropriately, computing the results of expressions in parentheses, then raising numbers to a power, followed by multiplication and division, then addition and subtraction. Simply enter the expression, then press the calculate button (or press enter) to compute the result. You can leave the math calculator window open while switching to any other window.
+
+
+Examples:
+
+
+
+Expression
+
+Result
+
+Note
+
+
+
+8+7/3
+
+10.3333
+
+7/3 is performed, then the result added to 8
+
+
+
+3.14159*.03^2
+
+2.8274E-3
+
+which is the same as 0.0028274
+
+
+
+50.4382*8.5/.001-45*23+87
+
+427776.7
+
+
+
+
+
+6(5-2/5)^3
+
+584.016
+
+Computes 5-2/5, then cubes, then takes times 6
+
+
+
+
diff --git a/html/CapillaryCalculations.htm b/html/CapillaryCalculations.htm
new file mode 100644
index 0000000..5fa1642
--- /dev/null
+++ b/html/CapillaryCalculations.htm
@@ -0,0 +1,101 @@
+
+
+
+
+Capillary Flow and Mass Rate Calculations
+
+
+
This window can be used to predict the flow rate of liquid in both open tubular and packed capillaries (aka columns). Capillaries are small tubes used in liquid chromatography, capillary electrophoresis, and other analytical chemistry fields. It is useful to be able to compute the expected linear velocity and volumetric flow rate of liquid through capillaries. The flow rate will change based on the applied pressure, the length of the capillary, the inner diameter of the capillary, and the solvent viscosity (typically 0.0089 poise). Each of these values may be changed on the page, using various units, and the correct flow rate will be computed. Choose the "View Explanatory Equations" tab to see the equations used.
+
+
When a capillary is filled with small particles, it is termed a "packed capillary". The addition of the particles results in a decreasing of the flow rate. To see the equations used under these conditions, change to Packed Capillary mode (the upper left dropdown box) and choose "View Explanatory Equations". When dealing with packing particles, you need to enter the particle diameter, and the interparticle porosity (epsilon), a "fudge factor" that accounts for the percentage of the capillary that becomes filled by the particles, thus impeding flow. A typical value for epsilon is 0.4
+
+
In addition to predicting volumetric flow rate, you can also determine what pressure, column length, or column inner diameter will be needed to give a desired volumetric flow rate. Lastly, you can enter an observed dead time (the time for solvent to travel the entire length of the column) and the program will determine what volumetric flow rate and back pressure will result in the given dead time. Use the second dropdown box on the upper left to change the computation mode.
+
+
The following table illustrates which values are used to calculate which result in the various modes. U means a User-entered value, and Calc means a calculated value. In the program (and below), text boxes highlighted in yellow are the values that the program will be computing for you, and thus, cannot be manually changed.
+
The Capillary Flow Calculator can assist in determining the Mass Flow Rate of a compound in the column and the moles of a compound injected onto a column. The Mass Flow Rate is simply the number of moles of a compound that pass by a given point on the column in one second. When injecting a "plug" of sample onto a column using a pressure-based injection, the total moles of compound injected can be computed by entering the sample concentration, flow rate, and injection time.
+
+
The concentration can be entered as a Molarity, or as a mg/mL type concentration. When using mg/mL, the program needs to know the molecular of the compound. You can either use the molecular weight of the currently selected formula in the main program window, or enter a custom numerical mass.
+
By pressing the "Show/Hide Peak Broadening" button, you can toggle between seeing the Mass Flow Rate calculations and the Extra Column Broadening Calculations controls. In chromatography, injected compounds migrate or travel through a column with a given peak width, meaning they occupy a certain portion of the column. As they travel, the peak width tends to get wider or broaden. The Extra Column Broadening Calculations can be used to compute how much the peak width will change as the compound flows through an open tube.
+
+
To use, enter a Liner Velocity, or "Link" to the linear velocity computed above. A typical diffusion coefficient is 1E-6, or 0.000001 Enter the tube length, inner diameter (I.D.) and the initial peak width. The temporal variance (variance in time) is then computed and the resulting peak width determined. The percent increase of the peak width is also shown.
+
+
If the compound travels through multiple open tubes of varying inner diameters, the overall peak broadening can still be computed because temporal variances are additive. Thus, for two tubes, you can enter the values for the first tube to find the temporal variance. Now enter the computed variance in the Additional Variance textbox and enter the values for the second tube. The variance in the Additional Variance box will be added to that in the Temporal Variance box and the overall resulting peak width determined. Click the View Equations button to see the supporting equations.
+Use the F4 key to toggle the case recognition mode for the analysis of a formula. Available modes:
+
+
+
+
Exact Case Mode
+
Elements must be properly capitalized for the program to recognize them. Only the first letter of abbreviations are capitalized.
+
+
+
Smart Case Mode
+
Elements can be typed in lower case or upper case and the program will make an educated guess as to what the elements are. For example, nacl would be interpreted as sodium chloride. However, the line will be left displayed the way it was typed in.
+
+
+
Convert Case Up Mode
+
The program will convert a line to proper notation after it has analyzed the line. In the above example, the program would redisplay the formula as NaCl. Another example, c6h6cl, would become C6H5Cl for chlorobenzene.
+
+
+When caution mode is set to on, the program will warn the user when a formula is possibly mistyped, typically by warning when a character combination could be interpreted as either an inorganic element or two organic elements. For example, 'Co means cobalt, while CO means carbon monoxide'
+
+
diff --git a/html/CommandLineSwitches.htm b/html/CommandLineSwitches.htm
new file mode 100644
index 0000000..fb48a55
--- /dev/null
+++ b/html/CommandLineSwitches.htm
@@ -0,0 +1,35 @@
+
+
+
+
+Command Line Switches
+
+
+
+The program now includes a charge computation algorithm. This has been added predominantly for use in the Formula Finder, but I've included one for use with regular formulas too. The charges for each element can be edited in the Edit elements window while the charges for the abbreviations can be edited in the Edit Abbreviations window.
+
+The method in which charge is computed is different for formulas in the Main Window and the Formula Finder window. This is because formulas in the Formula Finder are simply empirical formulas while those in the Main Window are assumed to be typed as their structure would look. For example, when parentheses are used in the Main Window, a charge correction is employed. Also, hydrogen must be treated specially. In the Main Window the charge of hydrogen is assumed to be +1. This is done so that H2O will have a charge of 2 times 1 minus 2 = 0. However, if the element preceding a hydrogen atom is not a halide (for example, it is carbon, silicon, or any metal), then the charge on hydrogen will be assumed to be -1. Thus, CH3 has an overall charge of 4 minus 3 = 1 and CH4 has a charge of 0.
+
+In the Formula Finder, the charge must be determined simply given an empirical formula. For this reason, a number of assumptions are made. First, all carbon atoms are assumed to be linked by single bonds. If you know you'll have aromatic compounds, then make an abbreviation for C6 and give it a charge of +6. Note that Ph is already the abbreviation for C6H5 (the phenyl group) and it has been given a charge of +1. The second assumption is that Hydrogen is +1. However, if carbon is present, all hydrogens are assumed to be -1. Lastly, if nitrogen is present, the charge is adjusted to assume that each nitrogen takes the place of one hydrogen on a carbon, then any hydrogens that remain must belong to nitrogen, and thus must be positive. With this in mind, the overall charge is further corrected.
+
+Some examples:
+
+
+
+Structural Formula
+
+Charge in Main Window
+
+Empirical Formula
+
+Charge in Formula Finder
+
+
+
+CH3CH2CH2CH2Cl
+
+0
+
+C4H9Cl
+
+0
+
+
+
+ClCH2C(CH3)2CH2
+
+1+
+
+C5H10Cl
+
+1+
+
+
+
+CH3CH2CH(NH2)CH2NH2
+
+0
+
+C4H12N2
+
+0
+
+
+
+CH3CH2C(ClNH3)CH3
+
+1+
+
+C4H11ClN
+
+1-
+
+
+
+CH3CH2CH2CH2NH2Cl
+
+1-
+
+C4H11ClN
+
+1-
+
+
+
+CH3CH2COOH
+
+0
+
+C3H6O2
+
+2-
+
+
+
+CH3CH2CHOO
+
+2-
+
+C3H6O2
+
+2-
+
+
+
+C6H5Cl
+
+8+
+
+C6H5Cl
+
+8+
+
+
+
+PhCl
+
+0
+
+PhCl
+
+0
+
+
+
+Note: Entering an empirical formula with Nitrogen into the main window will give an erroneous charge since all of the hydrogens will be assumed to belong to carbon and thus be -1 charge. The C4H11ClN empirical formula gives different charges in the Main Window depending on the structural order, while it always gives 1- for the empirical formula. Similarly, C3H6O2 always gives 2- for the overall charge, while the charge can vary in the Main Window. You can enter Ph in the Formula Finder using one of the custom element checkboxes.
+
+
diff --git a/html/CopyCurrent.htm b/html/CopyCurrent.htm
new file mode 100644
index 0000000..ed3263d
--- /dev/null
+++ b/html/CopyCurrent.htm
@@ -0,0 +1,17 @@
+
+
+
+
+Copy current weight or percent composition.
+
+
+
+Copy Current Molecular Weight copies the molecular weight to the clipboard so that it may be pasted into other programs. If the Standard Deviation Mode is set to off, only the weight will be copied. Otherwise, the entire molecular weight string (including MW = and the standard deviation value) will be copied. Similarly, Copy Percent Composition data will copy the data to the clipboard (only available during Single View Mode).
+
+
Note that when the option to automatically copy the current formula's molecular weight to the clipboard after each calculation is turned on, only the formula's value is copied to the clipboard, regardless of the Standard Deviation Mode.
+The copy as RTF command copies the current formula in rich text format, allowing the formula to be pasted into an RTF aware application, for example Microsoft Word. This allows the superscript and subscript codes to be preserved when the formula is pasted into the application.
+The Cut, Copy, Paste, and Delete options may be used to copy formulas to other formulas in the program or to other programs. These options will only work if the cursor is on a text input box. Furthermore, text must be selected for cut, copy, or delete to work.
+
For all other text boxes in the program, use Ctrl+X, Ctrl+C, and Ctrl+V for Cut, Copy, and Paste. In addition, you may use Ctrl+A to select all of the text in the currently active text box. See also the complete list of keyboard shortcuts.
+
+Dashes are used to add hydrates to a compound. For example, FeCl3-6H2O means ferric chloride with 6 water molecules attached. As shown, an integer can follow the dash, though it's not required (in which case 1 is assumed to follow the dash). In fact, the dash can be used many times to add multiple hydrates onto a compound (if you have the desire). Also, other molecules besides hydrates can be added. For example (fictional compound) C6H6-H2O-2ZnHgMg-U would be benzene + water + 2*(zinc+mercury+magnesium) + uranium for a total molecular weight of 914.73. Decimal numbers can also be entered after a dash to add fractional parts of hydrates or other compounds, for example FeCl3-2.5H2O
+Note: The amino acids are listed as (NH)CH(CO)R (missing an H and an OH) as if they had formed peptide bonds and were in a protein. Be sure to add an H to the first amino acid and an OH to the last amino acid when you type in a complete peptide or protein (for the neutral form).
+
+For example: H-Gly-Ala-Phe-OH is a neutral peptide chain with three amino acids. The zwitterionic (dipolar) form of the peptide would be represented as H2-Gly-Ala-Phe-O though the molecular weight would be the same.
+
+The following is a list of the default abbreviations included with this program. Be aware that BPY is Boron-Phosphorus-Yttrium while Bpy is bipyridine:
+Note 1: 2,2'-Bipyridine is also known as 2,2'-Dipyridyl
+
+
+Note 2: It is suggested that D be used for deuterium rather than ^2H since most deuterium used in the laboratory is of weight 2.014 rather than exactly 2, which is the weight ^2H would calculate as.
+
+
+Note 3: Tpp is (C4H2N(C6H5C)C4H2N(C6H5C))2 and is assumed to be bound to a metal. Thus, solid, pure Tpp would be notated H2Tpp to add back the two hydrogens that leave upon complex formation. Tpp is also known as 5,10,15,20-Tetraphenyl-21H,23H-porphine.
+Press the F2 key to copy a formula to a blank line (valid in both Multi and Single View modes). The program will search for a blank line on all formula lines, and put the copy on that line. If no line is blank, it will copy the formula to a new line, unless the maximum number of formulas already exist. Also note that the program will not copy a blank line to a new blank line.
+1) Abbreviation names may contain up to six characters. Only letters are allowed in abbreviation names, though the final character may now be a plus sign (+) or underscore (_) if desired; for example, Na+ and Cl_ are now allowable (this allows cations and anions to be defined as abbreviations).
+
+2) Only the first letter of an abbreviation is allowed to be capitalized.
+
+3) The definition for an abbreviation may contain any combination of elements, parentheses, and isotopes.
+
+4) Abbreviations can now contain other abbreviations. If a circular loop is found wherein Abbreviation A references Abbreviation B, which references Abbreviation A, then an error message will be displayed.
+
+5) Up to 100 normal abbreviations and 50 extended abbreviations are allowed.
+
Editing Abbreviations Using the Built-in Editor
+
+The easiest way to edit the abbreviations is to select Edit Abbreviations under the File Menu. The above conventions apply to any new or modified abbreviations. While editing the abbreviations, use the arrow keys to move around, then press Enter or click on the value to change it. After changing the value, press OK to accept it or Cancel to cancel changes. Clicking on Remove or Erasing the value in the Change Value window and pressing OK will erase the abbreviation or value. Any lines containing one or more blank columns will be erased from the MWT_ABBR.DAT file. Pressing Cancel in the Editing Abbreviations window will cancel the most recent changes by simply reloading the MWT_ABBR.DAT file. Select Reset to Defaults in the Editing Abbreviations screen to reset the abbreviations to their default names and formulas.
+
+If the MWT_ABBR.DAT file becomes corrupted, the MWT program will inform the user and ignore incorrect lines. If the file becomes deleted, the MWT program will create a new file with the default abbreviations. Thus, you can erase the .DAT files or select Restore to Defaults to restore the default abbreviations.
+
+Editing Abbreviations Using a Text Editor
+
+You can also edit the abbreviations directly in the MWT_ABBR file via a text editor. The following conventions must be followed:
+
+1) Comments may be added by preceding the comment with an apostrophe.
+
+2) Two group headings must exist: [AMINO ACIDS] and [ABBREVIATIONS]
+
+3) Abbreviations consist of the abbreviation and molecular formula under the appropriate column in either section.
+
+4) Only the first letter of an abbreviation is allowed to be capitalized.
+
+5) The abbreviations in the Amino Acid section are treated as extended level abbreviations -- they are only recognized when extended abbreviations are on.
+
+
Abbreviation Matching Order and Selectivity
+
+One quirky aspect of abbreviation recognition is that the first abbreviation of a user entered formula that is matched to the available abbreviations (during program operation) is the abbreviation that will be used -- furthermore, extended abbreviations are matched first if they are turned on.
+
+For example, say the user types in the formula phen2-meph. If only normal abbreviations are turned on, the program will match phen to Phen and not to Ph and En since Phen appears first in the MWT_ABBR.DAT file. To force the Ph and En abbreviations, type PhEn2-MePh. However, if extended abbreviations have been activated (by pressing F3), the formula phen2-meph will be translated to PheN2-MePh and nothing else, since the program will match Phe to the amino acid phenylalanine, leaving the n to be interpreted as nitrogen. Numerous methods exist to avoid this specific problem:
+
+1) Properly capitalize formulas while typing them in
+
+2) Don't use extended abbreviations
+
+3) Erase the Phe amino acid
+
+4) Place the Phen abbreviation in the amino acid section ABOVE the Phe abbreviation, so that the program tries to match Phen before Phe.
+
+This example should serve as a model for how to handle possible future abbreviation conflicts. This example should also illustrate that if the Phen abbreviation is placed anywhere below the Ph or En abbreviations in the MWT_ABBR.DAT file, it will be IMPOSSIBLE for the program to recognize it, since it will match Ph or En or both before even encountering Phen.
+The file MWT_ELEM.DAT contains a listing of all the elements and their uncertainties (errors in their weights). This file may be edited via a text editor or by selecting Edit Elements Table under the File menu. Only elemental weights and uncertainties may be changed, not element names. To edit a value, use the arrow keys to move around, then press Enter or click on the value to change it. After changing the value, press OK to accept it or Cancel to cancel changes. Clicking on Reset will reset the value to the default value built into the program code. New elements can only be added by entering them as abbreviations. See the abbreviations section for a description of how to edit abbreviations. Select Reset to Defaults in the Editing Elements window to reset the elements to their default average atomic weight values.
+
+By default, the elemental weights are based on the elements’ average atomic weights in nature. By clicking on the Isotopic Weights button, you can set the elements’ weights to the isotopic weight of the most common isotope of each element, typically used in analysis of high resolution mass spectrometry results. This change will also affect the percent composition results to reflect the elements’ isotopic weights appropriately. Typically, you will want to use the elements’ average weights, which can be set by either clicking Use Average Weights or Reset To Defaults.
+
+The third option for elemental weights is to use the nominal integer weight of the most common isotope, chosen via the Nominal Integer Weight button. This is useful for analyzing low resolution mass spectrometry results. For example, a fragment peak is seen at 40 Daltons, and possible matches are desired. First choose to use Nominal Integer Weights in the edit elements window, then go to the Formula Finder, type in 40 for the target weight, 0 for the tolerance, and select potential elements the fragment might contain, for example C, H, N, O, S, and Cl. Click on calculate and the program will come up with 4 matches: CN2, C2H2N, C2O, and C3H4.
+The quick switch buttons allow you to quickly switch between average weights, isotopic weights, and nominal integer value isotope weights, discussed further in the Editing Elements topic. When switching element types using Quick Switch, the new element values are loaded into memory directly from the program code and not from disk; thus, user-defined elemental weights cannot be used with Quick Switch. The element mode selected by Quick Switch on the main window also affects the element mode used by the Formula Finder. On program exit, the current element mode is saved to disk so that it is again selected when the program is restarted.
+
+If you wish to hide the Quick Switch buttons (for example, too make the window smaller) you can uncheck the Show Element Mode Quick Switch box in the Program Preferences Window.
+
+
diff --git a/html/ElementSubtraction.htm b/html/ElementSubtraction.htm
new file mode 100644
index 0000000..5b3f9d2
--- /dev/null
+++ b/html/ElementSubtraction.htm
@@ -0,0 +1,34 @@
+
+
+
+
+Element Subtraction Using the > Symbol
+
+
+
+Element Subtraction was added to allow one to quickly find the mass or empirical formula of a compound that has lost one or more elements due to a reaction or a neutral loss in mass spectrometry. For example:
+
C6H5Cl>HCl means C6H5Cl minus HCl, having a mass of 76.0959 Da (average mass), equivalent to C6H4
+
+
The elements to the right of the > symbol must all be present in the elements to the left of the > symbol, otherwise an error will occur. Furthermore, the number of atoms of a given element listed to the right of the > symbol cannot be greater than the number of atoms of the element to the left of the > symbol. Thus, the following formulas will result in an error:
+
+
+
C6H5Cl>HBr
since Br is not present in C6H5Cl
+
C6H5Cl>HCl2
since only one Cl atom is present in C6H5Cl
+
+
+
If you include multiple > symbols in a formula, then the order of operation is right-to-left. For example:
+
C6H5Cl3>H3Cl2>HCl
+will first be converted to
+C6H5Cl3>H2Cl
+and then to
+C6H3Cl2
+
+
The mass of C6H3Cl2 is 145.99342 Da (average mass), and consequently this is the mass returned for C6H5Cl3>H3Cl2>HCl If you choose Convert To Empirical Formula, then the empirical formula returned is C6H3Cl2
+
+
Abbreviations may contain formulas having > symbols in them. Thus, if the abbreviation J is defined to be C6H5Cl>HCl (mass 76.0959 Da), then the formula H2J will have a mass of 78.11184 Da. If you choose Expand Abbreviations for the formula H2J, then the formula will be replaced with H2C6H5Cl>HCl. However, if the original formula is J2 and you choose Expand Abbreviations, then we cannot simply replace J2 with (C6H5Cl>HCl)2 since that is an invalid formula. Consequently, J is first converted to its empirical formula, giving (C6H4)2 This same situation applies if J is in the middle of a formula. For example, H2JO2 will be converted to H2C6H4O2 when choosing Expand Abbreviations, or to C6H6O2 when choosing Convert to Empirical Formula.
+
+
+
diff --git a/html/EmpiricalFormula.htm b/html/EmpiricalFormula.htm
new file mode 100644
index 0000000..f67aeca
--- /dev/null
+++ b/html/EmpiricalFormula.htm
@@ -0,0 +1,16 @@
+
+
+
+Choose convert to empirical formula to convert the current formula to its empirical formula, showing the number of carbon atoms first, then hydrogen, then the remaining atoms alphabetically. For example, FeCl3-6H2O would convert to H12Cl3FeO6 and HOC6H4Cl would convert to C6H5ClO.
+
+
A confirmation dialog box will appear if "Exit on Escape with confirmation" or "Ignore escape key but confirm exit" is checked in Exit Program Options under the Options menu, otherwise, the command is instantaneous and cannot be undone.
+Once the program starts, you may enter a molecule's formula on the numbered line. Calculate the weight of a formula by pressing the ENTER key or clicking the Calculate button. In Multi View mode, this will create a new blank line for a new formula (unless the Advance on Calculate option is set to No). This is useful for comparing molecular weights of multiple compounds. The maximum number of formulas to show is adjustable, allowing you to prevent the window from growing to fill the screen.
+
+Move among the lines using the UP and DOWN arrow keys or the TAB and SHIFT-TAB keys. Pressing ENTER on line 'n' when line 'n+1' already has a formula will simply move the cursor to line n+1. A formula can consist of elements, element subscripts, parentheses, dashes (-) for hydrates followed by numbers to separate parts of a compound (NOT subtract them), and brackets for weighting parts of a compound.
+
+The Element Mode Quick Switch can be used to quickly change the element mode between average, isotopic, and integer modes.
+
+
+See the examples for a wide variety of example formulas.
+
+NOTE: For Radioactive elements, the most stable isotope is NOT used; Instead, an average Molecular Weight is used, just like with other elements. See the isotopes section for the method of indicating an isotopic mass. Data originally obtained from the Perma-Chart Science Series Chemical Periodic Table, 1993; ISBN 1-55080-063-9, then updated using the 1997 IUPAC standard atomic weights and uncertainties found in Pure Appl. Chem., 68, 2339-2359 (1996); 69, 2471-2473 (1997).
+
+
diff --git a/html/EraseAllFormulas.htm b/html/EraseAllFormulas.htm
new file mode 100644
index 0000000..b5391c2
--- /dev/null
+++ b/html/EraseAllFormulas.htm
@@ -0,0 +1,14 @@
+
+
+
+
+Erase all formulas.
+
+
+
+Press the F6 key to erase the current formula. The program will prompt you for confirmation. In Single View mode this will leave you with a blank line. Again, the other formulas (if present) can be viewed using the UP and DOWN arrow keys.
+The program will display error messages in red on the status line when an incorrect entry is inputted. The error message will disappear when a key is pressed. Any actual program errors (errors with the code) should be trapped by an error trapping routine, though I have tried to beta-test the program as much as possible with every situation I can think of. Please send me a note if you encounter any unhandled error.
+
+The program will also display numerous caution messages for possibly erroneous entries. This feature may be toggled on and off with F7.
+
+
diff --git a/html/ExamplesOfFormulas.htm b/html/ExamplesOfFormulas.htm
new file mode 100644
index 0000000..fe721e1
--- /dev/null
+++ b/html/ExamplesOfFormulas.htm
@@ -0,0 +1,138 @@
+
+
+
+
+Examples of Formulas
+
+
+
+Only one fifth of a sodium atom exists for each chlorine atom (shows use of brackets)
+
+
+
+
+Na.2Cl
+
+Same as previous example, but without brackets.
+
+
+
+
+C6H6-[xH2O]
+
+Benzene with an unknown amount of water, denoted by the x. Use with percent solver calculations.
+
+
+
+
HGlyLeuTyrOH
+
+
A peptide containing three residues (amino acids). Note that an H must added to the beginning and an OH to the end to obtain the correct molecular weight.
+
+
+
+
+
+
C6H5Cl>HCl
+
+
Example of Element Subtraction: One atom of H and one atom of Cl are removed from C6H5Cl to give C6H4.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/html/ExitProgram.htm b/html/ExitProgram.htm
new file mode 100644
index 0000000..4759af1
--- /dev/null
+++ b/html/ExitProgram.htm
@@ -0,0 +1,15 @@
+
+
+
+
+Exiting the Program
+
+
+
+
+Allows you to exit the program. Depending upon the Exit Program Options, the Escape Key (Esc) may be used as a shortcut for exiting the program, and a confirmation dialog might be shown.
+The various Exit Program Options allow you to choose whether or not the escape key (Esc) causes the program to end and whether or not exiting the program brings up the exit confirmation dialog box.
+Choose expand abbreviations from the edit menu to expand the abbreviations in the current formula to their elemental equivalents. For example, expanding PhOH gives C6H5OH. Parentheses will be inserted for clarity if necessary, for example FeBpy3 expands to Fe(C10H8N2)3 since FeC10H8N23 would be incorrect. A confirmation dialog box will appear if "Exit on Escape with confirmation" or "Ignore escape key but confirm exit" is checked in Exit Program Options under the Options menu, otherwise, the command is instantaneous and cannot be undone.
+
+
diff --git a/html/FormulaFinder.htm b/html/FormulaFinder.htm
new file mode 100644
index 0000000..7b86941
--- /dev/null
+++ b/html/FormulaFinder.htm
@@ -0,0 +1,71 @@
+
+
+
+
+Formula Finder
+
+
+
+The Formula Finder can be used to find empirical formulas of compounds that have a specific molecular weight or specific percent composition data. This is useful for finding possible compounds based on data, simply the reverse of what the main program does.
+
Matching Molecular Weights
+
+ For finding compounds based on molecular weight:
+
+
+Select the Match Molecular Weight radio button
+
+Check desired elements
+
+Type a weight in the Molecular Weight of Target Compound box.
+
+Set the weight tolerance to an acceptable value.
+
+Select calculate.
+
+
Setting Parameters
+
+The tolerance defines what range of compounds to match. For example, typing 78 in the weight box and .1 in the tolerance box will find compounds whose weights lie between 77.9 and 78.1. The tolerance can also be specified in Parts per Million (Ppm) by checking the Ppm Mode option. Setting a tolerance in parts per million will change the difference in mass results (dm=) to also be shown in parts per million.
+
+You specify which elements a compound contains by clicking the boxes next to the element names. If Bounded Searching is on (see below), the Min and Max boxes appear once an element is selected. These boxes specify the minimum and maximum number of times the element may appear in the empirical formula of the compounds. For Thorough Searching the minimum and maximum are automatically determined based on the target weight and the weight of the elements.
+
The Custom1_, Custom2_, etc. boxes are used to enter custom elements or abbreviations besides the ones listed. Clicking one of the Custom boxes brings up the typical Min and Max boxes, plus a box where you may type a weight for the custom element, an elemental symbol for one of the valid elements (eg. Fe, Pb, Na), or a valid abbreviation (eg. Me, Ph, Bpy).
+
Calculating and Displaying Results
+
+Selecting calculate will instruct the program to find all of the compounds that match the specifications. If you used a custom element and typed a weight for it, it will be notated in the results list by C1_, C2_, C3_, etc. This is so that C2_5 can represent five custom 2 atoms, while C2 represents two carbon atoms. If an elemental symbol such as Fe or Na was entered for a custom element, the program will use that symbol in the results list.
+
+The results list shows the found compounds, their molecular weights, and their difference in mass from the target value, denoted "dm". The format of the dm number is dependent on the Standard Deviation Mode selected under the options menu: standard notation for Short and Decimal modes, exponential notation for Scientific mode, while dm= is not displayed if Standard Deviations are turned off.
+
Other Options
+
+You can limit the maximum number of compounds found by changing the number in the Max Hits box. Double clicking or pressing Enter on any of the lines in the results box will show the entire line. This is useful if the formula is too long to display in the box. You can stop the Formula Finder during calculations by pressing a key or clicking the mouse.
+
+Additional Formula Finder options can be selected by choosing the Formula Finder Options button. The Find Charge option tells the program to calculate the charge of the compounds that match the search parameters. You can then limit the displayed compounds to those within a desired charge range if desired.
+
+In addition, the mass to charge (m/z) ratio of compounds can be computed. When selected, this allows you to enter a target m/z value rather than a target molecular weight to search for.
+
+The Smart Hydrogen feature is useful for limiting the number of found compounds. This feature causes compounds with an unreasonably high number of hydrogens to not be shown. For example, CH5 is acceptable, while CH6 is not. Also, NH4 is acceptable, but NH5 is not.
+
+The Sort Results option is on by default. This will sort the resultant compound list in a chemically logical order, placing CH6 before C2H6 and C2H6 before C10H6. Although useful, this process may take some time for lists of over 200 compounds, so be patient or turn off the feature. The process can be stopped by pressing any key or clicking the mouse.
+
+
Thorough Searching is the default (and usually faster) algorithm for the Formula Finder. It involves recursively finding all of the combinations of the selected elements and checking the mass of each combination to see if it matches the target molecular weight. When trying to match a very large molecular weight (e.g. 5000 Da or more), then thorough searching may actually take too long. In this case, you can choose Bounded Searching and use the Min and Max boxes to set a reasonable range of occurrences of each element to check for.
+
+
+
+You can minimize the Formula Finder window (by clicking on the underscore just left of the X button in the upper right of the window) while it performs its calculations and it will continue to calculate in the background. This is useful in case you have a very large calculation to perform and you want to use other windows applications or other parts of the Molecular Weight Calculator program while the calculations are performed.
+
+
Matching Percent Compositions
+
+For finding compounds based on percent compositions, select the Match Percent Compositions radio button. Now, selecting specific elements will show a Percent box, along with the Min and Max boxes. In this box you should type the percent of the compound that is the element. Type the percentages as numbers between 0 and 100 and do not type a percent sign (the program won't let you). If you use an abbreviation in a custom element box while Matching Percent Compositions, realize that the percentage you type in for the abbreviation will be for the percent of the compound that is that abbreviation.
+
+Similar to the molecular weight tolerance, the percent tolerance specifies the percent range that the element may have, so that setting carbon's percent to 56 with a tolerance of 2 will match compounds that are between 54% and 58%. Again, to see the entire line of results that don't fit in the list box, just double click on the line or press Enter.
+
+
Copying Results
+
+Click the Copy button to copy the results of the Formula Finder search in plain text format. The formulas, computed weights, and computed differences are separated by tabs allowing the results to be pasted into Excel and correctly fill the cells. The Copy as RTF button allows you to copy the results, preserving the subscripts in the formulas. This allows you to paste the results in an RTF aware program like Microsoft Word, and the subscripts will show up correctly. Lastly, you can select some or all of the lines in the results box and drag and drop the data (hold down the control key to copy it; simply dragging actually removes the highlighted text from the results box).
+
+
Isotopic Distribution
+
+
The Isotopic Distribution of any of the formulas in the results list can be computed by placing your cursor on the desired results line and choosing the Display Iso Abundance button (or by pressing Ctrl+D). The plot of the abundances will appear and the cursor will be placed back on the original line in the results box, allowing for easy comparison of several compounds. Although the Isotopic Distribution window is not shown, the distribution results are present in the window. Simply open the window by choosing Tools | Isotopic Distribution Modelling from the main program window.
+
+
diff --git a/html/FormulaFinderWarn.htm b/html/FormulaFinderWarn.htm
new file mode 100644
index 0000000..59b31f7
--- /dev/null
+++ b/html/FormulaFinderWarn.htm
@@ -0,0 +1,17 @@
+
+
+
+
+Weight Mode
+
+
+
Weight Mode Warning Screen
+
+When loading the Formula Finder or Peptide Sequence Fragmentation Modelling module while using Average Atomic Weights, the weight mode warning screen will appear to warn the user that these tools are most often used when a precise mass of a compound is determined via mass spectrometry. This is usually performed using Isotopic Weights, so the program warns of this and gives the user the option to switch to isotopic weights this time only, always switch to isotopic weights, or continue using Average Weights. A checkbox is also present in case the user wants to stop the warning dialog from appearing again. If the checkbox is selected, whatever option is currently selected will become the default option.
+The Change Formula Font option allows you to set the font used to display the formulas and calculated results. The font is saved when Save Options as Defaults is selected or when the Autosave feature is turned on.
This option can be used to reduce clutter of windows on the screen. When enabled, the main program window will be hidden when you open select one of the tools on the Tools Menu (except for the Math Calculator). Close the sub window to return to the main program window.
When this option is enabled, the contents of each text field will be selected when the field is chosen. This makes it easy to change the value of the entire field.
+After downloading the zipped file (for example mwt6_39.zip), install by unzipping and running the "Molecular Weight Calculator.msi" file (double-click to run). If you do not have the Windows Installer on your machine, the .msi file will not run and you must install the Windows Installer (it is included by default in Windows 2000 and higher).
+
+You can download the Windows Installer from Microsoft:
+
+The install program should take care of copying the files to the correct
+locations and registering all of the components. If replacing an older version, the .INI and .DAT
+files will be replaced. If you have abbreviations you want to save, backup the MWT_ABBR.DAT file before installing.
+
The program now includes support for international languages. Language information files for Spanish, German, Portuguese, and Russian are included with the program. To switch to a new language, select Choose Language from the Options Menu and choose the new language. In addition, the program examines your International Locale settings to determine if your decimal point is a period or a comma.
+
+
All text phrases in the program, including menus, labels, dropdown boxes, and messages can be translated into any Roman or Cyrillic based language by creating a new Lang.Ini file for your desired language. First, copy the Lang_English.Ini
+file to a new file and name it based on your language. For example, the Spanish version is Lang_Spanish.ini
+
+
Each text phrase or control caption is identified by a unique number. You can edit your new .Ini file to translate all of the English phrases to your desired language. Note that the program examines all of the Lang*.ini files in the program directory to create the list of available languages, obtaining the name of the language from the key Language= See the text at the start of the Lang_English.ini file for additional instructions
+
+
+
If you do create a Lang.Ini file for a language not included with the distribution of this program, please e-mail it to me so that I may distribute it with the next version. Even if you only translate some of the phrases (with the menus being most important) I would definitely appreciate receiving a copy of the file.
+
+
+
+
diff --git a/html/IonMatchListOptions.htm b/html/IonMatchListOptions.htm
new file mode 100644
index 0000000..427a192
--- /dev/null
+++ b/html/IonMatchListOptions.htm
@@ -0,0 +1,14 @@
+
+
+
+
+Ion Match List Options
+
+
+
Use the Ion Match Options window to specify the binning and normalization parameters used when parsing a list of ions loaded for matching to predicted fragmentation masses. Additionally, the arbitrary intensities assigned to a, b, and y ions, b/y ion shoulders, and neutral loss ions can be defined here. See the discussion on Ion Matching and Scoring for descriptions of how the parameters affect matching and scoring.
+
+
+
diff --git a/html/IonPlot.htm b/html/IonPlot.htm
new file mode 100644
index 0000000..aac06c1
--- /dev/null
+++ b/html/IonPlot.htm
@@ -0,0 +1,30 @@
+
+
+
The ion plot window can be used to visualize the expected mass spectrum for the predicted fragmentation ions. In addition, the location of actual ions loaded for matching can be compared to the predicted ion locations. The data on the plot can be exported in either graphical or text form (File and Edit menus). This same plotting window is used to display Isotopic Distribution plots. The plot is highly configurable and is much faster than the original plotting routine provided with the Molecular Weight Calculator.
+
+
Zooming, Panning, Scaling, and moving the Cursor
+
To zoom in, simply drag the mouse on the plot. The Mouse Action mode defines the type of zoom that will occur. In Zoom X mode, the plot expands the X axis, but autoscales the Y axis. The reverse behavior can be achieved using Zoom Y mode. Zoom Box mode allows one to draw a box on the graph and expand the given region. To show the entire plot, choose Options | Zoom Out to show All, or press Ctrl+A.
+
+
To slide the graph left/right or up/down (also known as panning), change to the Pan Graph or Pan Along X mode. To view the entire plot, click Zoom out, or press Ctrl+A. You can specify an X or Y range to view by choosing Edit->Set Zoom Range. The Y axis can also be automatically scaled as you zoom in or out by clicking Options and making sure Autoscale Visible Y is checked. Additionally, you can enable Fix Minimum Y at Zero so that the Y axis ranges from 0 to the maximum of any peaks in the current view. Both autoscaling and fixing the minimum Y at zero are useful for simplifying zooming into regions of the plot without requiring you to highlight an entire peak vertically prior to zooming. When either mode is enabled, it is best to set the Mouse Action to Zoom X.
+
+
+
The Mouse Action mode can be temporarily changed by pressing and holding the A, C, P, or Z key: A enables Move Annotation mode, C enables Move Cursor mode, P enables Pan mode, and Z enables Zoom mode. To view the cursor, click the Options button and make sure Show Cursor is checked. If Snap to Data is checked, the cursor can only be positioned on top of a data point; otherwise, the cursor can be positioned anywhere. To move the cursor, enable Cursor mode (by changing the Mouse Action mode or by pressing C), then drag the cursor to a new location. The current coordinates of the cursor, in addition to the current coordinates of the mouse, are displayed at the bottom of the plot. The digits of precision in the coordinates can be adjusted by clicking the Options button.
+
+
+
Plot Options and Annotations
+
Various formatting options can be modified using Edit->Edit Plot Styles and Colors. Various captions can be set. X and Y Axis gridlines may be displayed on the plot. The plot mode can be changed. The point and line colors and styles can be changed. Finally, the annotation font, size, and color can be customized.
+
+
Annotations are automatically added to the plot by the Peptide Sequence Fragmentation Module. In addition, you can add a custom annotation by double-clicking on the plot. The Snap Mode determines whether the annotation is bound to a specific series and/or specific data point, or is freely floating. Annotations can contain custom text, or can display the X and/or Y value of the nearest point. An arrow can be displayed showing which point the annotation is bound to. Finally, if Hide in Crowded Regions is enabled for the annotation, and if Auto Hide Captions is enabled (click Options, check Auto Hide Captions), then captions will be hidden in areas of the plot where numerous captions are present. The caption bound to the point with the highest intensity is give the highest preference for displaying. The Annotation Density Options can be used to define which annotations to show and/or hide.
+
+Isotopes may be entered in the form ^xY where x is the isotopic mass of the isotope and Y is the name of the element. For example, ^13C is carbon-13 and ^59Fe is iron-59. The program will check to make sure that the isotopic mass entered is a reasonable value for the particular element that it is associated with (see the isotope math section). The caret symbol (^) may be entered before any element in a formula, not just at the beginning. For example, C6H5^18OH is oxygen-18 labeled phenol. It has molecular weight 96.114 instead of 94.113 You can also enter decimal number for isotopes. For example ^78.918Br is Bromine 79 with a specific isotopic mass
+
+The isotopic mass entered is also used when figuring the percent composition of a compound. Thus, C6H6 is 92.258% carbon and 7.7421% hydrogen while ^13C6H6 is 92.8045% carbon and 7.1955% hydrogen. Isotopic masses may not be entered for abbreviations. For example, ^166Bpy is invalid. I considered allowing this, so that 166 would be used for the weight of Bpy (rather than 156.187), but I decided that the percent composition calculations would then be invalid since the program would not know which elements in the abbreviation were contributing to the extra (or less) weight of the abbreviation. Therefore, for carbon-13 labeled Bpy, for example, simply type ^13C10H8N2 instead of ^166Bpy.
+
+NOTE: It is suggested that D be used for deuterium rather than ^2H since most deuterium used in the laboratory is of weight 2.0159 rather than exactly 2, which is the weight ^2H would calculate as.
+
+NOTE: For Radioactive elements, the most stable isotope is NOT used; Instead, an average Molecular Weight is used, just like with other elements. Data originally obtained from the Perma-Chart Science Series Chemical Periodic Table, 1993; ISBN 1-55080-063-9, then updated using the 1997 IUPAC standard atomic weights and uncertainties found in Pure Appl. Chem., 68, 2339-2359 (1996); 69, 2471-2473 (1997).
+
+
diff --git a/html/IsotopicDistribution.htm b/html/IsotopicDistribution.htm
new file mode 100644
index 0000000..73aa4a2
--- /dev/null
+++ b/html/IsotopicDistribution.htm
@@ -0,0 +1,88 @@
+
+
+
+
+Isotopic Distribution
+
+
+
The Isotopic Distribution module allows you to predict the masses and abundances of the isotopes for a given formula. This information is useful for comparison to observed mass spectrometry data in helping to predict the number of atoms of a given element in the formula. The abundances are calculated by knowing the observed natural abundance of each element in the formula, and convoluting these natural abundances to predict the isotopic abundances. When you start the module by choosing Isotopic Distribution from the Tools menu, the currently selected formula is copied to the Isotopic Distribution form. You can also type or paste a new formula in the formula box. Whenever computing isotopic distributions the weight mode will be automatically changed to Isotopic weights; this cannot be changed.
+
+
As an example, the molecule C6H5Cl weighs 112.00797 Da. Its isotopic distribution is:
+
+
Mass
Fraction
Intensity
Potential Combinations of Atoms
+
112.00797
0.7098995
100.00
12C61H535Cl
+
113.00797
0.0466010
6.56
12C513C 1H535Cl
12C61H42H 35Cl
+
114.00797
0.2281708
32.14
12C413C21H5
12C61H32H235Cl
12C61H537Cl
+
115.00797
0.0149130
2.10
...
+
116.00797
0.0004092
0.06
...
+
117.00797
0.0000060
0.00
...
+
+
+
This means that 70.98995% = 71% of the compound will contain six 12C atoms, five 1H atoms, and one 35Cl atom. However, it is also possible that one of the six carbon atoms could be Carbon-13, which would increase the weight of the compound by one Da. It is equally possible that one of the five Hydrogen atoms could be Hydrogen-2, also increasing the weight by 1 Da. The probability of either of these happening is 4.66%, as shown by the above table. I have also shown the three possible compounds that would result in a 114.00797 Da compound. The program does not list all of the possible combinations of atoms; I have added those to the above table to illustrate the concept.
+
+
By checking the Plot Results box, the distribution will be plotted. The plot will update faster if you use Options | Plot Type | Sticks to Zero (left plot below). However, you can see the effect of the mass spectrometer's resolution on the ability to see the isotopes by changing the Plot Type to Gaussian Peaks in the Isotopic Distribution window. The plot will change depending on the effective resolution and corresponding m/z you have defined (see below for details). See the Plotting Help for more information on configuring the plot, zooming and out, and panning the plot view.
+
+
You can copy the results to the clipboard by clicking the Copy button or by selecting the results box, pressing Ctrl+A to select all, and Ctrl+C to copy. Since the values are separated by tabs, you can paste the data directly into Microsoft Excel and it will be properly placed into adjacent cells.
+
+
+
+
+
+
Resolution for Gaussian Peak plotting
+
The width of the Gaussian peaks can be modified by specifying the effective resolution and effective resolution m/z. The higher the resolution, the sharper the Gaussian peak. Typically, Quadrupole instruments have resolutions between 500 and 5000. Time of Flight (including Q-Tof) instruments have resolutions of 5000 to 30,000. Fourier Transform ICR (FT-ICR) instruments have resolutions ranging from 50,000 to 1,000,000.
+
+
Resolution in mass spectrometry is technically only valid at a single given mass, since it is computed by dividing the mass by the smallest spacing between two masses that can be discerned (m ÷ ΔM). For this reason, you must also specify an m/z at which the resolution applies. At lower resolutions, the Gaussian representation of adjacent peaks may begin to blend together, a phenomenon commonly seen on lower resolution instruments. The following four pictures illustrate the plot produced for the same four masses at four different resolutions.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Ion Comparison List
+
+
You can compare the predicted isotopic distribution to another spectrum by copying the spectrum to the clipboard, then clicking the Paste List of Ions to Plot button. The format of the ion list should be a list of mass (m/z) and intensity pairs, separated by a space, tab, or comma, with each mass/intensity pair on a separate line. If the data consists of discrete masses (centered data), then set the Plot Type to Sticks to Zero or Gaussian Peaks. In the case of Gaussian peaks, each of the masses will be converted to a gaussian peak, using the specified options. If the data consists of high resolution, raw data (continuum data), then set the Plot Type to Lines Between Points. If more than 1000 masses are pasted, and the Plot Type is changed to Gaussian Peaks, a warning message will be shown the first time the Gaussian Peaks mode is selected. This is done to prevent you from accidentally choosing the Gaussian Peaks mode with continuum data. The pasted list can optionally be normalized to 100. Additionally, the plot color for the comparison list can be customized.
+
+
+
+
+
+
+
+
Additional Information
+
+
In addition to entering a formula on the Isotopic Distribution window, you can place your cursor on a formula line in the main Molecular Weight Calculator window and choose Tools | Show Isotopic Distribution for Current Formula (or press Ctrl+D). This will compute the distribution and plot it, but not show the Isotopic Distribution window. Finally, while using the Formula Finder, you can view the isotopic distribution of any of the formulas in the results list by placing your cursor on the results line and choosing the Display Iso Abundance button (or by pressing Ctrl+D).
+
+
It is allowable to have explicitly defined Isotopes present in a formula (for example ^13C6). Since an explicitly defined isotope has just one mass, it has no "distribution". Thus, the result is to simply increase the observed weight of the formula by the mass of the isotope. For example, C6H6 weighs 78.04695 Da and has 4 possible isotopes. Adding one Carbon-13 to give C6H6^13C simply shifts the mass up by 13 to 91.04695, still giving 4 possible isotopes. However, ^13C6H6, with all Carbon-13 atoms weighs 84.04695 (6 Da more than 78.04695) and only has 2 isotopes, those contributed by Hydrogen-1 and Hydrogen-2.
+
+
Due to the above behavior for explicitly defined isotopes, the abbreviation D, for deuterium, must be replaced with its explicitly defined equivalent, ^2.014H prior to computation. This will be done automatically for you if you enter a formula containing deuterium.
+
+
+
Background
+
Two papers useful for learning about the computation of isotopic abundance distributions are:
+
Yergey, J.A., International Journal of Mass Spectrometry and Ion Physics, 1983, 52, 337-349.
+
+
+
+
Other Available Software
+
IsoPro 3.0, written by Mike Senko, can also be used to compute isotopic distributions and abundances. The software is faster than my implementation and can handle larger compounds (more atoms, more combined elements) than mine can. Finally, it also shows very detailed molecular weights of each isotope. If you need more precise isotopic distribution computations than provided with my software, I suggest downloading IsoPro and trying it out. Download from http://members.aol.com/msmssoft
+
I will point out, in my defense, that my software is easier to use, the plotting window is easier to zoom in and out of, and the Molecular Weight Calculator is freeware. Further, from the testing that I have performed, the abundances and masses computed with my software vs. IsoPro are very similar.
+
The maximum number of formulas that can be displayed at a given time is determined by your current screen resolution. You may set the maximum to a lower number to prevent the main program window from filling the screen. Recall that a new formula is added when the Enter key is pressed in the bottom-most formula, or when the New Formula button is clicked.
+
+
The program keeps track of the screen resolution used when the program was previously run. If the detected resolution is different than that used previously, the maximum number of formulas to display will be set to the maximum allowable for the new resolution minus 2, unless in 640x480 mode where it will be set to 7.
+With the help menu you can see an overview of the program, search the index for a specific topic, or view an about box listing information about the program and the author.
+
+Additionally, the Show Tool Tips command can be used to turn off or on the display of tool tips on various controls throughout the program. Tool tips are pop-up tips that appear when you point at a control with the mouse pointer without moving (or clicking) for one second. I have placed these tips throughout the program at places where I think they will be useful in helping users learn about the various features of the program.
+
+
For example, if you hold the mouse over the status line at the bottom of the main screen, a tool tip will appear telling you that you can "Double click the status line to expand it" and thus see the entire line in case part of it gets cut off. You can remove the check mark from beside Show Tool Tips by selecting the menu item, causing the tool tips to no longer be displayed throughout the program.
+The Mole/Mass Converter is useful for performing common chemical calculations concerning the interconversion of mass, moles, and molarity. You have the option of using the mass of the compound in the current formula or entering a custom numerical mass.
+
+
The Dilution Calculator helps determine concentrations and volumes to perform the specified dilution or achieve a desired concentration (via evaporation or sublimation, for example).
+
+In the converter window, the first two lines are used for simple conversion between mass and moles or one unit of mass and other units of mass.
+
+
+Select Convert Amounts from the dropdown combo box
+
+Type the starting number
+
+Select the correct units for the starting and computed numbers
+
+The program will perform the conversion for you.
+
+
+When volume units are selected, a density box will appear so that the program can correctly convert mL of a liquid to moles of the liquid (for example). Note that pounds and ounces conversions are based on the avoirdupois system, commonly used in the U.S. (1 pound = 16 ounces = 0.454 kg).
+
+When Find Concentration is chosen in the dropdown combo box, two other boxes appear which can be used to perform three common molarity-related operations:
+
+
+By typing a weight or volume in the top box and entering a volume in the second box, you can select the Find Concentration button to calculate the resultant concentration of a solution of the corresponding volume containing the specific amount of the compound.
+
+Conversely, after entering a concentration and a volume, you can select the Find Amount button to find the amount of substance required to make a solution of the corresponding volume and concentration.
+
+Finally, after entering an amount and a concentration, you can find the volume of solvent required to satisfy the amount and concentration requirements by selecting the Find Volume button.
+
+
+
In Find Concentration mode, the behavior of the units dropdown boxes has been improved to automatically recompute the corresponding value (amount/volume/concentration) when you change units. However, if you enter a new value then immediately change the corresponding units, the value will not be automatically updated, since you most likely want to use that specific value/unit combination.
+
+
+
+Note: I have chosen to only allow the g/mL unit for density; if anyone can suggest other common units I will implement them in a future version of the program.
Diluting a stock solution (starting solution) involves adding solvent to a given volume (aliquot) of the stock solution to lower the concentration of the solute (the compound dissolved in the solution). Conversely, concentrating a solution involves removing some of the solvent (by boiling, evaporating, or sublimation) resulting in an increase of the concentration of the solute. The dilution calculator can assist you in determining what types of volume changes are required to accomplish the desired dilution or concentration. Alternatively, it can assist in determining how the concentration of the solute will change for a given set of volumes.
+
+
The standard equation for determing change in concentration between an initial and final solution is:
+ M1V1 = M2V2
+where M1 is the concentration of the solute in the initial (stock) solution, M2 is the concentration of the solute in the final solution, V1 is the volume (aliquot) of initial (stock) solution used to make the final solution, and V2 is the total volume of the final solution. In making a dilution, one must determine the volume of solvent (Vs) to mix with the aliquot of stock solution (V1). This can easily be computed using:
+ Vs = V2 - V1
+With these equations in mind, I have included four types of computational modes in the dilution calculator. The text boxes highlighted in yellow are the values that the program will be computing for you, and thus, cannot be manually changed.
+
+
+
+
Find Required Dilution Volumes
+ In this mode you enter an Initial and Final solute concentration, in addition to a desired Total Solution Volume.
+
+
If the Final concentration is less than the Initial concentration, the program will compute the Volume of Stock solution and Volume of Diluting Solvent to mix to perform the specified dilution.
+
If the Final concentration is larger than the Initial concentration then nothing can be logically computed, so the volume boxes are cleared.
+
+
+
+
Find Required Total Volume
+ In this mode you enter an Initial and Final solute concentration, in addition to the Volume of Stock solution to use.
+
+
If the Final concentration is less than the Initial concentration, the program will compute the Total Final Volume and Volume of Diluting Solvent necessary to perform the specified dilution.
+
If the Final concentration is larger than the Initial concentration then the progrm will compute the Total Final Volume that the Volume of Stock solution must be reduced to in order to achieve the specified increase in concentration.
+
+
+
+
Find Final Concentration
+ In this mode you enter an Initial solute concentration, Volume of Stock solution (V1), and Total Final Volume (V2).
+
+
If the Total Final Volume is greater than the Volume of Stock solution, then the Volume of Diluting Solvent is automatically computed by subtracting V2 - V1, afterwhich the Final Concentration is computed.
+
However, you also have the option of entering a Total Final Volume less than the Volume of Stock solution. In this case, you are performing a concentration and no Diluting Solvent is added; thus the box is cleared. The Final Concentration is then computed using V2 and V1.
+
+
+
+
Find Initial Concentration
+ This mode is identical to the Find Final Concentration mode, except that the Initial Concentration is now being computed.
+
+
As with the above mode, the Volume of Diluting Solvent is computed if the Total Final Volume is greater than the Volume of Stock solution, afterwhich the Initial Concentration is computed.
+
Otherwise, the volume of Diluting Solvent is cleared and the Initial Concentration is computed using V2 and V1.
+
+
+
+
Two checkbox options appear when the Dilution Calculator is activated. The first, Link Initial Dilution Concentration and Convert Amounts Concentration, will keep the values and units of these two concentrations the same if either one changes. The second checkbox, Link Dilution Volume Units, simply keeps all of the units in the Dilution Calculator identical. You will want to turn this off when you are diluting a solution by several orders of magnitude, thus requiring a very small Volume of Stock Solution and much larger volume of Diluting Solvnet.
+
+Multi View Mode is useful for comparing several formulas and their molecular weights simultaneously (the maximum number of formulas is dependent upon screen resolution and may be adjusted). See Entering Formulas for information on formula conventions. You must switch to Single View mode to see percent composition data.
+
+
diff --git a/html/MultipleProgramInstances.htm b/html/MultipleProgramInstances.htm
new file mode 100644
index 0000000..cabf178
--- /dev/null
+++ b/html/MultipleProgramInstances.htm
@@ -0,0 +1,16 @@
+
+
+
+
+Multiple Instances of the Program
+
+
+
Multiple Instances of the Program
+
+
If the Molecular Weight Calculator is running and you accidentally (or intentionally) try to run it again, a warning dialog will appear warning you that another copy (instance) is already running. Choose yes to start another copy, or no to cancel.
+
+
+If you do have multiple copies running, and AutoSave Options is enabled, then each instance will write its formulas, options, and values to disk when exited. If each of the instances points to the same executable file (MwtWin.exe), then the values for the instance closed last will overwrite any values saved by the previous instances.
+The program is available via the web at http://www.alchemistmatt.com/ and http://ncrr.pnl.gov/software/ The installation zip file (for example mwt6_38.zip) contains MSVBVM60.DLL and a full installation program, utilizing the Windows MSI Installer.
+Molecular weights of compounds (formulas) listed in a text file can be computed and written to an output file. The Formula Finder can be also be run in batch analysis mode using appropriate Batch Analysis Commands (see below). In addition, amino acid sequences can be converted from 1 to 3 letter notation (or from 3 to 1 letter notation).
+
+
Initiate batch analysis mode by either choosing "Calculate weights" from under the File menu and selecting the file, or by using the /F:filename switch at the command line. The input file must be a text file with each line containing a single molecular formula, an amino acid sequence, a numeric mass to use for the formula finder, a batch analysis command (see below), or a comment (beginning with a ; or ').
+
+
Batch Molecular Weight Computation
+
+
The default mode for batch analysis is molecular weight computation. To use this mode, the text file need only contain a single, valid molecular formula on each line. Each formula's molecular weight will be computed, and the results written to the output file (see below for filename). The output file will contain the original formula, plus its molecular weight, separated by a Tab (configurable using DELIMETER=). By default, the standard deviation is included, formatted depending on the current setting for the standard deviation mode. Whether or not to include the standard deviation, in addition to its format, can be customized using STDDEVMODE=. If there is an error in the formula, the error will be listed in the output file. If a FF= Batch Command was issued earlier in the file, a MW= command can be used to switch back to Molecular Weight Computation mode (see the example input file below).
+
+
The Batch Analysis Command WEIGHTMODE={AVERAGE|ISOTOPIC|INTEGER} can be used to set the weight mode for computations. For example, to switch to isotopic mode use WEIGHTMODE=ISOTOPIC and to switch back to average mode use WEIGHTMODE=AVERAGE. You can suppress the display of the source formula using MWSHOWSOURCEFORMULA=OFF. You can suppress the display of the formula's mass using SHOWMASS=OFF. This is useful if you simply wish to convert formulas to their empirical formula (using EMPIRICAL=ON).
+
+
If you need to compute the mass of peptides listed in 1-letter notation, you can use ONELETTERPEPTIDEWEIGHTMODE=ON. The default prefix and suffix groups for the peptides are H and OH, though this can be changed with PEPTIDEWEIGHTMODEPEPTIDEPREFIX and PEPTIDEWEIGHTMODEPEPTIDESUFFIX. To compute the mass of peptides listed in 3-letter notation, simply use the default MW= molecular weight computation mode. However, note that 3-letter abbreviation peptide formulas must explicitly include the H and OH in the formula to obtain the correct mass. For example, GlyLeuTyr will return a mass of 333.38234, while HGLyLeuTyrOH (or H-GlyLeuTyr-OH) will return the correct mass of 351.39762 (in average mass mode).
+
+
+
Batch Formula Finder Mode
+
In order to enter formula finder mode you must place the command FF= on a line in the input text file. You may also optionally specify which elements to use for the formula finder searching by listing them on the same line as the FF= command, separated by commas (if not specified, the previously enabled elements will be used). The Batch Analysis commands MAXHITS=num and TOLERANCE=num can be used to specify the maximum number of hits or the search tolerance. If either of these commands is omitted, the values currently set in the Molecular Weight Calculator Formula Finder window will be used.
+
+
Once formula finder mode has been enabled (using FF=), a list of numeric values to match elemental combinations to can be given, with each value listed on its own line. For each value, a list of matching empirical formulas will be determined, and the results written to the output file. The MAXHITS= or TOLERANCE= command can be given at any time in the list in order to change one of the values. Additionally, the FF= command can be re-issued with a new list of search elements to use. Finally, the MW= command can be used to switch back to Molecular Weight Computation Mode.
+
+
+
Batch Amino Acid Notation Conversion Mode
+
The third mode for batch analysis is amino acid sequence notation conversion. Use AACONVERT3TO1=ON for 3 letter to 1 letter conversion, or AACONVERT1TO3=ON for the reverse. After this, each line will be treated as a sequence and converted as desired. By default the source sequence is outputted, followed by the converted sequence. To prevent output of the source sequence, use the command AASHOWSEQUENCEBEINGCONVERTED=OFF
+
+
+
Isotopic Distribution Mode
+
The fourth mode for batch analysis is computation of isotopic distributions for a given formula. Enable using ISOTOPICDISTRIBUTION=ON. After this, each line containing a valid formula will have its isotopic distribution computed and written to the output file. Optionally, set the charge state to use for m/z calculations using ISOTOPICDISTRIBUTIONCHARGE=num, where num is an integer greater than 0.
+
+
+
Output File and Automation
+
+
The output filename will be the input filename, plus the extension ".out". For example, if the input file is "formulas.txt", the output file will be "formulas.txt.out". If the /F:filename switch is used on the command line, the Molecular Calculator program will exit upon completion of processing the input file. Additionally, you can specify an alternate output filename using the /O:outfile switch. Use the /Y switch to suppress the "Are you sure you want to replace?" dialog box from appearing when an existing output file is found.
+
+
+To process a number of files at once, simply create a batch file (.BAT) containing lines to call the Molecular Weight calculator program and process each file. For example, you could create GO.BAT containing the lines:
+Then, run GO.BAT and the files will be processed.
+
+
Batch Analysis Command Summary
+
Values in brackets [] are optional (do not use the brackets). Words in curly brackes {} are a list of potential words; choose just one of the words and do not use the curly brackes or comma. num is a valid number
+
+
Command and options
Explanation
Default
+
MW=
Enable Normal Molecular Weight Computation mode
+
+
WEIGHTMODE={AVERAGE|ISOTOPIC|INTEGER}
Weight mode to use.
The weight mode in effect the last time the program was run (or the current weight mode if the program is running).
+
+
STDDEVMODE={SHORT|SCIENTIFIC|DECIMAL|OFF}
The standard deviation mode, defining how to format the standard deviation of each element's weight
The standard deviation mode in effect the last time the program was run (or the current standard deviation mode if the program is running).
+
+
MWSHOWSOURCEFORMULA={ON|OFF}
When ON, will output the source formula, followed by either the molecular weight, the empirical formula, or the formula with expanded abbreviations, separating the two with the currently defined delimeter.
ON
+
+
CAPITALIZED={ON|OFF}
If ON, will output the source formula properly capitalized. For example, c6h6 would be outputted as C6H6. Default is OFF.
OFF
+
+
EMPIRICAL={ON|OFF}
If ON, will convert the source formula to its empirical formula and output the result. If MWSHOWSOURCEFORMULA=ON, will show the source formula before the empirical formula, separating with the currently defined delimeter. Unless SHOWMASS=OFF, the molecular weight will also be outputted.
OFF
+
+
EXPANDABBREVIATIONS={ON|OFF}
If ON, will expand the abbreviations in the source formula to their elemental equivalent, and output the result. If MWSHOWSOURCEFORMULA=ON, will show the source formula before the resultant formula, separating with the currently defined delimeter. Unless SHOWMASS=OFF, the molecular weight will also be outputted.
OFF
+
+
SHOWMASS={ON|OFF}
When ON, will output the mass of each formula encountered in normal weight computation mode.
ON
+
+
ONELETTERPEPTIDEWEIGHTMODE={ON|OFF}
When ON, will treat the input formulas as peptides in 1-letter notation. The default peptide prefix is H and default peptide suffix is OH. Use PEPTIDEWEIGHTMODEPEPTIDEPREFIX and PEPTIDEWEIGHTMODEPEPTIDESUFFIX to change the default prefix and suffix. Note that this mode is not appropriate for computing masses of peptides in 3-letter notation. Those peptide masses can be computed using the Normal Molecular Weight Computation (MW=) mode.
OFF
+
+
PEPTIDEWEIGHTMODEPEPTIDEPREFIX={custom formula}
Use this to set a custom prefix formula for peptide masses computed when ONELETTERPEPTIDEWEIGHTMODE=ON.
H
+
+
PEPTIDEWEIGHTMODEPEPTIDESUFFIX={custom formula}
Use this to set a custom suffix formula for peptide masses.
The delimeter to use to separate the source formula and the computed mass, or the source sequence and the converted sequence. Use one of the standard <> commands (for example DELIMETER=<TAB>) or provide a custom symbol (for example DELIMETER=, to set the delimeter to a comma)
<TAB>
+
+
AACONVERT3TO1={ON|OFF}
When ON, will treat each line as a set of 3 letter amino acid abbreviations, and will output the equivalent 1 letter sequence.
OFF
+
+
AACONVERT1TO3={ON|OFF}
When ON, will treat each line as a set of 1 letter amino acid abbreviations, and will output the equivalent 3 letter sequence.
OFF
+
+
AASPACEEVERY10={ON|OFF}
When ON, will add a space every 10 residues in the output sequence.
OFF
+
AA1TO3USEDASH={ON|OFF}
When ON, will separate each residue with a dash (only applicable for 1 to 3 letter conversion).
OFF
+
+
AASHOWSEQUENCEBEINGCONVERTED={ON|OFF}
When ON, will output the source sequence, followed by the converted sequence, separated the currently defined delimeter. It is useful to set this option to OFF if you are converting long sequences.
ON
+
+
FF=[Element1[,Element2][,...]]
Enable Formula Finder mode. Optionally provide a comma-separated list of elements or abbreviations to search for.
If no list of elements is supplied after the equals sign, then the options last used for the formula finder will be used.
+
+
MAXHITS=num
Define the maximum number of formula finder hits
+
+
TOLERANCE=num
Set the formula finder search tolerance
+
+
ISOTOPICDISTRIBUTION={ON|OFF}
When ON, will write out the isotopic distribution for any line containing a valid formula.
+
+
ISOTOPICDISTRIBUTIONCHARGE=num
Define the charge state to use for computing m/z values in Isotopic Distribution mode.
+
+
; Comment
Insert a comment by starting a line with a semicolon or an apostrophe. You cannot add a comment on the same line as a Batch Analysis Command or any other text to be used for computation.
+
+
ECHOCOMMENTS={ON|OFF}
When ON, will write any blank lines and comment lines found in the source file to the output file.
OFF
+
+
VERBOSEMODE={ON|OFF}
When ON, will write a comment to the output file each time a command is found in the source file. Error messages will be written to the output file regardless of the VERBOSEMODE setting.
+; Set weight mode
+WEIGHTMODE=AVERAGE
+
+; Set Standard Deviation mode
+STDDEVMODE=OFF
+
+; Return capitalized (formatted) formulas
+CAPITALIZED=ON
+
+fecl3-6h2o
+
+; Expand abbreviations
+EXPANDABBREVIATIONS=ON
+
+etoac
+
+; Don't display the source formula
+MWSHOWSOURCEFORMULA=OFF
+etoac
+
+; Don't display the weight
+SHOWWEIGHT=OFF
+etoac
+
+; Convert to empirical formula
+; Note: no need to use EXPANDABBREVIATIONS=OFF
+EMPIRICAL=ON
+
+fecl3-6h2o
+etoac
+
+; Re-enable display of the source formula
+MWSHOWSOURCEFORMULA=ON
+UreaC4(NH2)4Ca
+
+; Convert amino acid sequence from 1 letter to 3 letter sequence
+AACONVERT3TO1=ON
+
+GluGlaPheLeu
+Val-Ile-Arg
+
+AASPACEEVERY10=ON
+; For really long sequences, can disable display of the source sequence
+AASHOWSEQUENCEBEINGCONVERTED=OFF
+GluGlaPheLeuVAlIleArgPheTyrMetCysValGluGlaGluGlaPheLeuVAlIleArgPheTyrMetCysValGluGla
+
+AACONVERT1TO3=ON
+FLEELYR
+MLTSCDEEF
+
+AASHOWSEQUENCEBEINGCONVERTED=ON
+AA1TO3USEDASH=ON
+FLEELYR
+
+; To re-enable plain molecular weight computation, use MW=
+; Note: this will also disable EMPIRICAL= and EXPANDABBREVIATIONS=
+; Further, it will automatically re-enable SHOWWEIGHT
+MW=
+
+C4N8OH2
+
+; Compute the mass of peptides given in 1-letter notation
+ONELETTERPEPTIDEWEIGHTMODE=ON
+
+FLEELYR
+MLTSCDEEF
+
+; Don't show the source formula when computing the peptide's mass
+MWSHOWSOURCEFORMULA=OFF
+
+MLTSCDEEF
+
+; Enable formula finder mode using FF=, specifying the elements to use in searching
+; Can also specify weight mode, maximum number of hits, and tolerance
+FF=C,H,N,O,Cl,Bpy
+WEIGHTMODE=ISOTOPIC
+MAXHITS=5
+TOLERANCE=0.05
+403.84
+300.58
+
+; The tolerance can be changed
+TOLERANCE=0.02
+403.885
+
+; The maximum number of hits can be changed
+MAXHITS=10
+632.43
+
+; The search elements can be changed
+FF=N,Br,H,Li
+MAXHITS=2
+389.32
+
+; Can disable verbose output
+VERBOSEMODE=OFF
+; Additionally, could enable echo of comments
+ECHOCOMMENTS=ON
+; Switching back (this comment is in the source file)
+
+MW=
+MWSHOWSOURCEFORMULA=ON
+NH2
+C6H5Cl
+^13C6H5Cl
+
+WEIGHTMODE=AVERAGE
+FeCl3-6H2O
+
+
+
+; So is this one, along with the 3 blank lines above
+MWSHOWSOURCEFORMULA=OFF
+NH2
+C6H5Cl
+^13C6H5Cl
+FeCl3-6H2O
+
+VERBOSEMODE=ON
+DELIMETER=<SPACE>
+CAPITALIZED=on
+c6h5cl
+
+DELIMETER=,
+c6h5cl
+
+ECHOCOMMENTS=OFF
+
+; Enable Isotopic Distribution Mode
+ISOTOPICDISTRIBUTION=ON
+; Simply enter a formula to obtain the isotopic distribution
+CH2(CH2)7CH2Br
+
+; Change the charge state with the following command
+ISOTOPICDISTRIBUTIONCHARGE=2
+CH2(CH2)7CH2Br
+
+
+
+
Resultant Output File
+
+; Average Weight Mode Enabled
+; Standard deviations will not be displayed
+; Source formula will be displayed with proper capitalization
+FeCl3-6H2O 270.29478
+
+; Abbreviation expansion now On
+EtOac CH3CH2C2H3O2 88.10512
+; Display of source formula is now Off
+CH3CH2C2H3O2 88.10512
+; Will not display the molecular weight (mass) of each formula
+CH3CH2C2H3O2
+
+; Converting formulas to empirical formulas now On
+H12Cl3FeO6
+C4H8O2
+; Display of source formula is now On
+UreaC4(NH2)4Ca C5H12CaN6O
+
+; 3 letter to 1 letter amino acid symbol conversion now On
+GluGlaPheLeu EUFL
+Val-Ile-Arg VIR
+; Will add a space every 10 amino acids
+; Will only show the converted sequence, not the sequence being converted
+EUFLVIRFYM CVEUEUFLVI RFYMCVEU
+
+; 1 letter to 3 letter amino acid symbol conversion now On
+PheLeuGluGluLeuTyrArg
+MetLeuThrSerCysAspGluGluPhe
+; Will show sequence being converted, in addition to the converted sequence
+; Will separate residues with a dash
+FLEELYR Phe-Leu-Glu-Glu-Leu-Tyr-Arg
+
+; Normal Molecular Weight Mode Enabled (other modes turned Off)
+C4N8OH2 178.112
+
+; One letter Amino Acid weight mode: input formulas are assumed to be peptides in one-letter notation
+H-PheLeuGluGluLeuTyrArg-OH 969.09172
+H-MetLeuThrSerCysAspGluGluPhe-OH 1074.18464
+; Display of source formula is now Off
+1074.18464
+
+; Formula Finder Mode Enabled. Search elements/abbreviations: C, H, N, O, Cl, Bpy
+; Isotopic Weight Mode Enabled
+; FF Maximum Hits set to 5
+; FF Tolerance set to 0.05
+; FF Searching: 403.84
+Compounds found: 5
+C2BpyCl6N MW=403.8849368 dm=0.0449368
+C5H6Cl8N3O MW=403.8019086 dm=-0.0380914
+C6H6Cl8NO2 MW=403.7906756 dm=-0.0493244
+C6H8Cl8N2O MW=403.8144838 dm=-0.0255162
+C7H8Cl8O2 MW=403.8032508 dm=-0.0367492
+
+; FF Searching: 300.58
+Compounds found: 0
+
+; FF Tolerance set to 0.02
+; FF Searching: 403.885
+Compounds found: 5
+CH7Cl7N10 MW=403.8674832 dm=-0.0175168
+C2BpyCl6N MW=403.8849368 dm=-0.0000632
+C2H9Cl7N9 MW=403.8800584 dm=-0.0049416
+C3H2BpyCl6 MW=403.897512 dm=0.012512
+C3H9Cl7N7O MW=403.8688254 dm=-0.0161746
+
+; FF Maximum Hits set to 10
+; FF Searching: 632.43
+Compounds found: 10
+CH24Bpy3N8O MW=632.413531800001 dm=-0.0164682
+C2H26Bpy3N7O MW=632.426107000001 dm=-0.003893
+C3H26Bpy3N5O2 MW=632.414874000001 dm=-0.015126
+C4H28Bpy3N4O2 MW=632.427449200001 dm=-0.0025508
+C5H28Bpy3N2O3 MW=632.416216200001 dm=-0.0137838
+C5H30Bpy3N3O2 MW=632.440024400001 dm=0.0100244
+C6H30Bpy3NO3 MW=632.428791400001 dm=-0.0012086
+C7H31Bpy3ClN MW=632.420724000002 dm=-0.009276
+C7H32Bpy3O3 MW=632.441366600002 dm=0.0113666
+C8H33Bpy3Cl MW=632.433299200002 dm=0.0032992
+
+
+; Formula Finder Mode Enabled. Search elements/abbreviations: H, N, Br, Li
+; FF Maximum Hits set to 2
+; FF Searching: 389.32
+Compounds found: 2
+H47Br3Li11N2 MW=389.3049672 dm=-0.0150328
+H47Br3Li13N MW=389.3339032 dm=0.0139032
+
+; Switching back (this comment is in the source file)
+
+NH2 16.0187232
+C6H5Cl 112.007976
+^13C6H5Cl 118.007976
+
+FeCl3-6H2O 270.29478
+
+
+
+; So is this one, along with the 3 blank lines above
+16.02262
+112.5566
+118.4924
+270.29478
+
+; Verbose mode is now on
+; Delimeter now a Space
+; Source formula will be displayed with proper capitalization
+C6H5Cl 112.5566
+
+; Delimeter now ,
+C6H5Cl,112.5566
+
+; Comments found in the source file will not be written to the output file
+
+; Isotopic Distribution calculations now On
+Isotopic Abundances for CH2(CH2)7CH2Br
+ Mass/Charge Fraction Intensity
+ 205.05919 0.4588825 100.00
+ 206.05919 0.0459075 10.00
+ 207.05919 0.4484460 97.73
+ 208.05919 0.0447120 9.74
+ 209.05919 0.0020020 0.44
+ 210.05919 0.0000528 0.01
+ 211.05919 0.0000017 0.00
+
+; Isotopic Distribution charge set to 2
+Isotopic Abundances for CH2(CH2)7CH2Br
+ Mass/Charge Fraction Intensity
+ 103.03329 0.4588825 100.00
+ 103.53329 0.0459075 10.00
+ 104.03329 0.4484460 97.73
+ 104.53329 0.0447120 9.74
+ 105.03329 0.0020020 0.44
+ 105.53329 0.0000528 0.01
+ 106.03329 0.0000017 0.00
+
+1) Abbreviation names may contain up to six characters. Only letters are allowed in abbreviation names, though the final character may now be a plus sign (+) or underscore (_) if desired; for example, Na+ and Cl_ are now allowable (this allows cations and anions to be defined as abbreviations).
+
+2) Only the first letter of an abbreviation is allowed to be capitalized.
+
+3) The definition for an abbreviation may contain any combination of elements, parentheses, and isotopes.
+
+4) Abbreviations can now contain other abbreviations. If a circular loop is found wherein Abbreviation A references Abbreviation B, which references Abbreviation A, then an error message will be displayed.
+
+5) Up to 100 normal abbreviations and 50 extended abbreviations are allowed.
+
Editing Abbreviations Using the Built-in Editor
+
+The easiest way to edit the abbreviations is to select Edit Abbreviations under the File Menu. The above conventions apply to any new or modified abbreviations. While editing the abbreviations, use the arrow keys to move around, then press Enter or click on the value to change it. After changing the value, press OK to accept it or Cancel to cancel changes. Clicking on Remove or Erasing the value in the Change Value window and pressing OK will erase the abbreviation or value. Any lines containing one or more blank columns will be erased from the MWT_ABBR.DAT file. Pressing Cancel in the Editing Abbreviations window will cancel the most recent changes by simply reloading the MWT_ABBR.DAT file. Select Reset to Defaults in the Editing Abbreviations screen to reset the abbreviations to their default names and formulas.
+
+If the MWT_ABBR.DAT file becomes corrupted, the MWT program will inform the user and ignore incorrect lines. If the file becomes deleted, the MWT program will create a new file with the default abbreviations. Thus, you can erase the .DAT files or select Restore to Defaults to restore the default abbreviations.
+
+Editing Abbreviations Using a Text Editor
+
+You can also edit the abbreviations directly in the MWT_ABBR file via a text editor. The following conventions must be followed:
+
+1) Comments may be added by preceding the comment with an apostrophe.
+
+2) Two group headings must exist: [AMINO ACIDS] and [ABBREVIATIONS]
+
+3) Abbreviations consist of the abbreviation and molecular formula under the appropriate column in either section.
+
+4) Only the first letter of an abbreviation is allowed to be capitalized.
+
+5) The abbreviations in the Amino Acid section are treated as extended level abbreviations -- they are only recognized when extended abbreviations are on.
+
+
Abbreviation Matching Order and Selectivity
+
+One quirky aspect of abbreviation recognition is that the first abbreviation of a user entered formula that is matched to the available abbreviations (during program operation) is the abbreviation that will be used -- furthermore, extended abbreviations are matched first if they are turned on.
+
+For example, say the user types in the formula phen2-meph. If only normal abbreviations are turned on, the program will match phen to Phen and not to Ph and En since Phen appears first in the MWT_ABBR.DAT file. To force the Ph and En abbreviations, type PhEn2-MePh. However, if extended abbreviations have been activated (by pressing F3), the formula phen2-meph will be translated to PheN2-MePh and nothing else, since the program will match Phe to the amino acid phenylalanine, leaving the n to be interpreted as nitrogen. Numerous methods exist to avoid this specific problem:
+
+1) Properly capitalize formulas while typing them in
+
+2) Don't use extended abbreviations
+
+3) Erase the Phe amino acid
+
+4) Place the Phen abbreviation in the amino acid section ABOVE the Phe abbreviation, so that the program tries to match Phen before Phe.
+
+This example should serve as a model for how to handle possible future abbreviation conflicts. This example should also illustrate that if the Phen abbreviation is placed anywhere below the Ph or En abbreviations in the MWT_ABBR.DAT file, it will be IMPOSSIBLE for the program to recognize it, since it will match Ph or En or both before even encountering Phen.
+Element Subtraction was added to allow one to quickly find the mass or empirical formula of a compound that has lost one or more elements due to a reaction or a neutral loss in mass spectrometry. For example:
+
C6H5Cl>HCl means C6H5Cl minus HCl, having a mass of 76.0959 Da (average mass), equivalent to C6H4
+
+
The elements to the right of the > symbol must all be present in the elements to the left of the > symbol, otherwise an error will occur. Furthermore, the number of atoms of a given element listed to the right of the > symbol cannot be greater than the number of atoms of the element to the left of the > symbol. Thus, the following formulas will result in an error:
+
+
+
C6H5Cl>HBr
since Br is not present in C6H5Cl
+
C6H5Cl>HCl2
since only one Cl atom is present in C6H5Cl
+
+
+
If you include multiple > symbols in a formula, then the order of operation is right-to-left. For example:
+
C6H5Cl3>H3Cl2>HCl
+will first be converted to
+C6H5Cl3>H2Cl
+and then to
+C6H3Cl2
+
+
The mass of C6H3Cl2 is 145.99342 Da (average mass), and consequently this is the mass returned for C6H5Cl3>H3Cl2>HCl If you choose Convert To Empirical Formula, then the empirical formula returned is C6H3Cl2
+
+
Abbreviations may contain formulas having > symbols in them. Thus, if the abbreviation J is defined to be C6H5Cl>HCl (mass 76.0959 Da), then the formula H2J will have a mass of 78.11184 Da. If you choose Expand Abbreviations for the formula H2J, then the formula will be replaced with H2C6H5Cl>HCl. However, if the original formula is J2 and you choose Expand Abbreviations, then we cannot simply replace J2 with (C6H5Cl>HCl)2 since that is an invalid formula. Consequently, J is first converted to its empirical formula, giving (C6H4)2 This same situation applies if J is in the middle of a formula. For example, H2JO2 will be converted to H2C6H4O2 when choosing Expand Abbreviations, or to C6H6O2 when choosing Convert to Empirical Formula.
+
+
+Only one fifth of a sodium atom exists for each chlorine atom (shows use of brackets)
+
+
+
+
+Na.2Cl
+
+Same as previous example, but without brackets.
+
+
+
+
+C6H6-[xH2O]
+
+Benzene with an unknown amount of water, denoted by the x. Use with percent solver calculations.
+
+
+
+
HGlyLeuTyrOH
+
+
A peptide containing three residues (amino acids). Note that an H must added to the beginning and an OH to the end to obtain the correct molecular weight.
+
+
+
+
+
+
C6H5Cl>HCl
+
+
Example of Element Subtraction: One atom of H and one atom of Cl are removed from C6H5Cl to give C6H4.
+
+After downloading the zipped file (for example mwt6_38.zip), install by unzipping and running the "Molecular Weight Calculator.msi" file (double-click to run). If you do not have the Windows Installer on your machine, the .msi file will not run and you must install the Windows Installer (it is included by default in Windows 2000 and higher).
+
+You can download the Windows Installer from my home page at:
+
+The install program should take care of copying the files to the correct
+locations and registering all of the components. If replacing an older version, the .INI and .DAT
+files will be replaced. If you have abbreviations you want to save, backup the MWT_ABBR.DAT file before installing.
+
+
+
diff --git a/html/MwtHelp/Overview.htm b/html/MwtHelp/Overview.htm
new file mode 100644
index 0000000..cd851d6
--- /dev/null
+++ b/html/MwtHelp/Overview.htm
@@ -0,0 +1,151 @@
+
+
+
+
+Overview of Features
+
+
+
Overview of Features
+
+ Click the contents button to see a list of available help topics.
+ (may need to click the Show button at the upper left)
+
+
+
Tools
+
+Mole/Mass/Dilution Converter for easily interconverting moles and mass, for computing molarity or concentration given an amount and volume, and for performing dilution calculations.
+
+Formula Finder for finding potential empirical formulas for a given molecular weight or for a given set of percent composition data. Includes a Smart Hydrogen feature to limit the number of hydrogen atoms in found compounds to a reasonable number.
+
+Amino Acid Notation Converter to convert between 3 letter and 1 letter abbreviations for amino acids (converts both ways).
+
+Peptide Sequence Fragmentation Modelling module to predict the ion masses expected from fragmentation of a peptide in the collision cell of a mass spectrometer. Actual experimental data may also be matched to a theoretical peptide sequence.
+
+Capillary Calculations module for performing typical flow, mass-rate, and band broadening calculations in open and packed capillary columns, commonly used in capillary liquid chromatography
+
+Isotopic Distribution module for predicting the masses and abundances of the isotopes for a given formula, useful for comparison to observed mass spectrometry results
+
+
Built-in mathematical calculator that follows mathematical precedence rules.
+For example, CH3(CH2)3CH3 is equivalent to CH3CH2CH2CH2CH3
+
+
+
+
+
+Can also handle decimal numbers following parentheses.
+
+For example, (Fe2O3).5 is equivalent to FeO1.5
+
+
+
+
+Hydrates or other appended compounds are allowed.
+
+For example, FeCl3-6H2O or FeCl3-2.5H2O
+
+
+
+
+
+Can also begin a formula with a number.
+
+For example, 4FeCl3-6H2O is equivalent to (FeCl3)4-6H2O
+
+
+
+
+
+User-definable abbreviations Default abbreviations are included for common parts of compounds, including amino acids. See full list.
+
+For example, PhCl = C6H5Cl and
+HOAc = CH3COOH.
+
+
+
+
+Smart Case Conversion The program will automatically convert lowercase letters to uppercase where appropriate for ease of entering a formula. Exact case matching and non-conversion are also available.
+
+
+
+Isotopes are recognized using the following notation:
+
+^13C is Carbon-13
+C6H5^18OH is heavy-oxygen (Oxygen-18) labeled phenol
+^78.918Br is Bromine 79 with a specific isotopic mass
+
+Feature of weighting parts of a compound relative to the other parts. For example:
+
+[.2Na]Cl would have a weight of 0.2*22.989768+35.4527=40.0507
+NaCl-.5H2O would have a weight of 22.989768+35.4527+0.5*(2*1.00794+15.9994)=67.4501
+
+
+
+
+
+Feature of Element Subtraction to return the mass of a formula, minus one or more elements. For example:
+
+C6H5Cl>HCl means C6H5Cl minus HCl, having a mass of 76.0959 Da (average mass), equivalent to C6H4
+
+
+
+
+The overall Charge on a compound can be estimated. The program sums up the default charges for each element and for each abbreviation to give the total charge for a formula. Hydrogens are treated as +1 when preceded by a halogen and -1 when preceded by other elements (including carbon and all metals).
+
+Percent Solver mode for finding the value of "x" in a compound that satisfies user-specified percent composition requirements.
+
+
+International (foreign language) text phrases may be loaded for all labels and messages in the program. Current languages included are Spanish, German, Portuguese, and Russian. You can make your own language-specific caption file by simply editing a text file.
+Edit and save elemental values while program is running. Further, default elemental weights can be set for the elements' average atomic weights, isotopic weight of the most common isotope, or nominal integer weight of the most common isotope.
+
+Accuracy of the final digit of the molecular wt. and percent composition.
+
+Capability of saving options as defaults and automatic loading of the saved options upon program start.
+Ability to process and compute molecular weights for compounds listed in an input text file. Can also run the Formula Finder in batch mode using a text file. Specify the file by choosing calculate weights from file menu or using the /F:filename switch at command line.
+Revision History for the Molecular Weight Calculator program
+by Matthew Monroe
+
+
+ Revision 1 - DOS version Completed August 6, 1995 (QuickBasic for DOS)
+ Contains the following basic features:
+
+
+
formula weight calculation
+
+
+
percent composition calculation
+
+
+
can handle parentheses, up to 2 sets of embedding
+
+
+
can handle hydrates and other additional compounds
+
+
+
can handle numbers up to 2 digits long
+
+
+
two types of case conversion
+
+
+
help screen
+
+
+
+
+Revision 2.0 - Completed August 8, 1995
+
+
Can now handle numbers up to 6 digits long
+
+
+
Can now handle up to 4 sets of embedded parentheses
+
+
+
Now includes ability to handle brackets and partial weights
+
+
+
Now has three types of case conversion
+
+
+
Added expanded help screens
+
+
+
+
+Revision 2.1 - Completed August 9, 1995
+
+
Can now show display of current time
+
+
+
+
+Revision 2.2 - Completed August 10, 1995
+
+
Added a simple math calculator
+
+
+
+
+Revision 2.21 - Completed August 17, 1995
+
+
+ Contains minor bug fixes.
+
+
+
+
+Revision 2.3 - Completed September 2, 1995
+
+
added command line switches to control internal settings
+
+
+
Added standard deviation option
+
+
+
Added recognition Bu for butyl group
+
+
+
+
+Revision 2.4 - Completed December 1, 1995
+
+
Added a Percent solver routine.
+
+
+
Combined F11 and F12 std. deviation options into just F12
+
+
+
Contains Screen update bug fixes.
+
+
+
+
+Revision 2.5 - Completed December 7, 1995
+
+
Improved speed of the % solver algorithm.
+
+
+
Added recognition of Urea, Ox, Py, En, Tpp, Otf.
+
+
+
+
+Revision 2.55 - Completed December 17, 1995
+
+
Added error trapping routines.
+
+
+
Improved handling of exponentially large and small numbers.
+
+
+
Added warning statements for possibly ambiguous abbreviations such as Bpy and Py.
+
+
+
+
+Revision 2.6 - Completed January 16, 1996
+
+
Recognizes Amino Acid abbreviations.
+
+
+
+ Recognizes Deuterium, D abbreviation.
+
+
+
+ Percent Solver values can now be set for all elements of a formula.
+
+
+
+ Displays differences between actual and theoretical values at the conclusion of the percent solver routine.
+
+
+
+ Added CTRL-P option to print results.
+
+
+
+ Added more error messages/explanations for incorrect user entries.
+
+
+
+
+
+Revision 2.7 - Completed March 1, 1996
+
+
Now able to handle isotopes; use the caret (^) symbol.
+
+
+
+ Now able to calculate powers of numbers in the calculator.
+
+
+
+ Added more error messages/explanations for incorrect entries.
+
+
+
+ Included a moderately accurate error handler to check the validity of entered isotopic masses.
+
+
+
+ Added numerous "caution" statements for possibly erroneous entries: eg. Co vs. CO and Sc vs. SC
+ (This feature may be toggled on and off with CTRL-C)
+
+
+
+ Improved speed of the % solver algorithm; watch it blaze!
+
+
+
+ Removed CTRL-P option -- use PRINT-SCREEN or SHIFT-PRINT-SCREEN
+
+
+
+ Changed the order and layout of the in-program help screens.
+
+
+
+ Fixed typos in help screens and added two more help screens.
+
+
+
+
+
+Revision 2.8 - Completed May 1, 1996
+
+
Now able to handle user-defined abbreviations listed in the MWT_ABBR.DAT file.
+
+
+
+ Added error checking to prevent duplicate abbreviations or abbreviations duplicating elements.
+
+
+
+ Added automatic re-creation of the abbreviation file if it is deleted/missing.
+
+
+
+ Added ability to run without abbreviations if program is run on a write-protected drive.
+
+
+
+ Added command-line switch (/X) to stop any attempts of reading or creating an abbreviation file (useful on a write-protected drive, like a network drive).
+
+
+
+
+
+Revision 2.85 - Completed September 1, 1996
+
+
Now recognizes the MWTPATH environment variable which specifies the location of the MWT_ABBR.DAT file
+
+
+
+
+Revision 2.87 - Completed January 1, 1997
+
+
+ Updated the help file to reflect the latest Windows version of the program.
+
+
+
+
+
+Revision 3.0 - Windows 3.x version Completed June 10, 1996 (Visual Basic 3.0)
+
+
+ New Windows interface.
+
+
+
+ Now able to modify elemental values stored in the MWT_ELEM.DAT file.
+
+
+
+ Added editing and saving of Abbreviations and Elemental values during program operation.
+
+
+
+ Added ability to save current options as defaults.
+
+
+
+ Added ability to Copy and Paste information to/from other Windows programs.
+
+
+
+ Formula length is now unlimited -- formulas can even contain all 103 elements.
+
+
+
+ Added ability to print results.
+
+
+
+
+
+Revision 3.1 - Completed June 28, 1996
+
+
Added ability to change the font used to display formulas and calculated results.
+
+
+
+ Added Mole/Mass Converter
+
+
+
+ Added Formula Finder
+
+
+
+ Added full hypertext help
+
+
+
+
+
+Revision 3.2 - Completed January 1, 1997
+
+
+ Now allows use of abbreviations as custom elements in formula finder.
+
+
+
+ For Percent Solver, added display of differences between target percentages and obtained percentages.
+
+
+
+ Changed comment delimiter to be a semicolon in the MWTWIN.INI file and the .DAT files.
+
+
+
+ Added detection of a mouse click to stop the percent solver and formula finder.
+
+
+
+ Updated help file with MWT Dos version information.
+
+
+
+ Corrected bug in display of standard deviation values to display the correct number of decimal places.
+
+
+
+ Improved editing of abbreviations and elemental values.
+
+
+
+ Improved formula finder interface.
+
+
+
+
+
+Revision 4.0 - Windows 95 version Completed August 25, 1997 (Visual Basic 5.0)
+
+
32 bit Windows 95 code
+
+
+ Now allows user to turn off confirmation of exiting the program.
+
+
+
+ Added possibility of using exact isotopic weights, in addition to average elemental weights. Useful for mass spectrometry.
+
+
+
+ Added context sensitive tool tips to many of the program’s controls and added a setting in the help menu to turn them on or off (the settings can be saved in the MWTWIN.INI file)
+
+
+
+ Redesigned program help to Windows 95 standards.
+
+
+
+ Improved dialog box displayed when changing items in grids to include OK, Cancel, and Reset buttons.
+
+
+
+ Fixed bug that had smart case mode and exact case mode switched around in the Calculate function.
+
+
+
+ Changed all forms and controls to the standard VB 5.0 3-D style.
+
+
+
+ Changed program icon and made the edges transparent.
+
+
+
+ Updated help file with MWT Dos version information.
+
+
+
+ Updated my E-mail and WWW addresses to UNC.
+
+
+
+
+
+Revision 4.1 - Completed September 2, 1997
+
+
+ Added feature to expand abbreviations to their elemental equivalents.
+
+
+
+ Fixed bug that wrongly calculated weights and uncertainties for weighting of compounds when abbreviations were involved (i.e. use of brackets, eg. [.1Bpy]).
+
+
+
+ Fixed bug that did not take abbreviations or isotopes into account when hydrates (dashes) were used (eg. Fe-3Bpy or Fe-6^13CH3)
+
+
+
+ Enabled error handlers to catch overflow values in various procedures.
+
+
+
+
+
+Revision 4.2 - Completed September 7, 1997
+
+
+ Added feature to convert formulas into their empirical formulas, displaying C first, then H, then the remaining elements alphabetically.
+
+
+
+ Made the Expand Abbreviations and Convert to Empirical Formula commands instantaneous if exit program confirmation is turned off in Exit Program Options under the Options menu.
+
+
+
+
+
+Revision 4.3 - Completed March 10, 1998
+
+
+ Added feature to allow isotopes to contain decimal values, for example: ^13.02C
+
+
+
+ Added an indicator of the percent of calculations completed in the formula finder.
+
+
+
+ Added back in the mathematical expression calculator that was previously present in the MWT for Dos version (see above).
+
+
+
+ Fixed bug that would not allow single letter elements to be entered in the custom elements boxes of the formula finder routine.
+
+
+
+ Modified error messages in the formula finder routine to be more clear.
+
+
+
+
+
+
Revision 4.31 - Completed March 22, 1998
+
+
+ Fixed error with re-creation of the mwt_elem.dat file if it was deleted from the current directory.
+
+
+
+ Made minor updates to average and isotopic mass values for elements in accordance with the 1993 IUPAC standards.
+
+
+
+ Minor changes to help file.
+
+
+
+
+
+
+Revision 4.4 - Completed June 15, 1998
+
+
+ Added parts per million (ppm) mode to formula finder weight tolerance box.
+
+
+
+ Added tooltip for the copy button in the formula finder.
+
+
+
+ Added Smart Hydrogen atom feature to the formula finder, limiting the number of hydrogens in found compounds to a realistic number (allows CH5 but not CH6 or CH25, allows NH4 but not NH5, allows H3O but not H4O).
+
+
+
+ Added option to convert found formulas in formula finder to empirical formulas and chemically alphabetize the results, giving a more logical ordering of found formulas (but slowing find process); sort can be stopped by any keypress or mouse click.
+
+
+
+ Added option to save current values and formulas so they are automatically loaded the next time the program is started. The values can also be autosaved on exit of the program.
+
+
+
+
+ Made format of the difference in mass result (dm=) in formula finder dependent on the standard deviation mode: if "Short" or "Decimal" then dm is displayed in standard notation (0.00314); if "Scientific" then dm is displayed in scientific notation; if "Off" then dm is not displayed.
+
+
+
+ Modified the tab order of objects in the various windows to be more logical.
+
+
+
+ Fixed copy commands to insert a new line character properly and to insert tabs instead of spaces between columns.
+
+
+
+ Fixed a major bug with the /X command line feature that did not load elemental information (symbols and weights) upon startup, thus making the program useless. Amazingly no one reported this to me, so I can only assume no one uses this feature.
+
+
+
+ Removed all command line switches except /X and /? since the AutoSave and AutoLoad features of the options, formulas, and values eliminates their usefulness.
+
+
+
+ Updated the MWT_ELEM.DAT and program elements defaults to include the average atomic weights and uncertainties specified by the 1997 IUPAC standards.
+
+
+
+ Changed the "Possibly Incorrect Uncertainty" caution message (for elemental uncertainties) to display only if uncertainties are different from those built into the program code by 10 times instead of by just 20%
+
+
+
+ Changed the "Possibly Incorrect Elemental Weight" caution message to display only if different from those built into the program code by 20% instead of just 10%.
+
+
+
+ Fixed status line from displaying a yellow colored "Ready" after editing elements or abbreviations when a caution statement about an abbreviation in one of the formulas was displayed and replaced.
+
+
+
+ Numerous updates to Mwtwin.Hlp file
+
+
+
+ Fixed Edit Elements table and program internal code to handle molecular weights with 16 digit precision rather than just 8.
+
+
+
+ Made all displayed value formats follow the Standard Deviation Mode in that they are displayed in standard notation, unless Scientific mode is chosen, in which case they are shown in exponential notation. This applies to dm results in the Formula Finder, values in the Mole/Mass Converter, results in the Calculator, and percent solver results.
+
+
+
+
+
+
+Revision 4.5 - Completed July 19, 1998
+
+
+ Added ability of abbreviations to contain isotope references. For example, ^2.014H is used to add Deuterium to the abbreviations list, signifying Hydrogen weighing exactly 2.014 Daltons. Note: the uncertainties for isotopes used in abbreviations will be equivalent to those of the elements used in the abbreviation; for example .00007 for Hydrogen, even if ^2.014H is given as the abbreviation.
+
+
+
+ Added caution statement for TI being tritium-iodine versus Ti being titanium (although tritium is not included in the abbreviations list, users may add it as ^3.01605H).
+
+
+
+ Added creation of backup files for MWT_ABBR.DAT and MWT_ELEM.DAT each time the files are changed, saving the old version as MWT_ABBR.BAK and MWT_ELEM.DAT
+
+
+
+ Added display of percent completed information when sorting results in the Formula Finder.
+
+
+
+ Changed default deuterium abbreviation to be ^2.014H (rather than simply H2).
+
+
+
+ Improved speed of sorting algorithm in Formula Finder (now using a Shell sort rather than a recursive QuickSort, which generates too much overhead for large data sets due to the recursion).
+
+
+
+ Changed code in the Standard Deviation Display subroutine to better handle very large numbers without giving an overflow error.
+
+
+
+ Added Geocities.Com web address and e-mail address throughout help file and program.
+
+
+
+
+
+Revision 4.6 - Completed January 23, 1999
+
+
+ Added option of entering decimal elemental amounts as X1.5 in addition to [1.5X]. For example, Fe1.5O2.25 instead of [1.5Fe][2.25O]
+
+
+
+ Added option of entering decimal numbers after dashes. For example C6H6-.5H2O instead of C6H6-[.5H2O]
+
+
+
+ Added functionality to parse a text file containing formulas and create an output file with the molecular weight of each formula.
+
+
+
+ Added /F:filename switch that can be used when starting MWTWIN to specify a file to parse automatically, calculating molecular weights for each formula, and writing to filename.out
+
+
+
+ Fixed bug in "expand to empirical formula" feature that skipped elements with an occurrence of less than 1 in a formula (for example, [.7CH3] would expand to simply H2.1 rather than C.7H2.1
+
+
+
+ Fixed bug in formula parser that wasn't warning user of decimal numbers with leading zeroes after carets for isotopes, i.e. ^0.5H is not allowed while ^.5H is (though it is unrealistic and the program warns of this). --- This change no longer matters since I've removed the requirement that decimal numbers cannot start with a 0 as in 0.5
+
+
+
+ Fixed bug in loading saved formulas on program startup that caused a program error if blank formulas were present before the final formula.
+
+
+
+ Further improved speed of sorting algorithm in formula finder by converting each line to easily sorted code, sorting the code, and arranging the original lines based on how the coded lines sorted.
+
+
+
+ Removed requirement that decimal numbers be in the format .5 instead of 0.5 Thus, decimal numbers can now be entered as 0.5 or .5
+
+
+
+ Removed requirement that numbers following parentheses be integers and not decimal numbers. Thus, (CH3)2.5 is now allowed.
+
+
+
+
+
+Revision 4.61 - Completed February 1, 1999
+
+
+ Added new code to correctly recognize the element dysprosium (Dy) when deuterium (D) is defined as an abbreviation. Previously, the program would match D as deuterium and Y as yttrium, with the only possible fix being to delete the deuterium abbreviation. A special-case work around has been added.
+
+
+
+ Added a caution statement concerning Dy versus DY (dysprosium vs. deuterium-yttrium).
+
+
+
+
+
+Revision 4.62 - Completed February 8, 1999
+
+
+ Added a warning dialog that appears when the Formula Finder is started, but the element weight mode is using average weights. The user can stay in average weight mode or switch to isotopic weight mode. A checkbox is also included to avoid seeing the warning dialog in the future.
+
+
+
+ Added the option of using Nominal Integer Weights for elements, useful for looking for matches to low resolution mass spectrometry data via the formula finder.
+
+
+
+ Fixed bug that incorrectly loaded the saved formulas on program start when the view mode was single view.
+
+
+
+ Completely reworked how the program parses formulas, looking for elements and abbreviations. Now, discrepancies like the Dy vs. DY problem corrected in revision 4.61 will not occur, even if the user creates a new, potentially ambiguous abbreviation. For example, if the user assigns CH3 to the abbreviation A, then types ac in a formula, the program will parse this as Ac, the element actinium. On the other hand, if they type AC, it will correctly parse this as CH3C, while previous versions would not have.
+
+
+
+ Reworked a large majority of the code to remove nondescriptive variable names like temp, temp$, etc. Also consolidated some of the repetitive sections into single functions, thereby reducing the overall program size.
+
+
+
+
+
+Revision 4.65 - Completed February 16, 1999
+
+
+ Added ability to sort the elements by atomic weight, elemental symbol, or weight uncertainty when editing elements.
+
+
+
+ Abbreviations can now contain parentheses, for example CH(CH3)3
+
+
+
+ Abbreviations can also now contain anything a regular formula might contain, except for other abbreviations. Thus, decimal numbers can now be used, plus parentheses, dashes, brackets, etc. Furthermore, abbreviation formulas can be entered lowercase when editing abbreviations, and the program will properly capitalize the abbreviations.
+
+
+
+ Added a more robust and faster Formula Finder routine, called "Thorough Search". This routine is recursion based, and no longer requires the user to enter maximum and minimum values for the number of each element present. It is faster than the older, "Bounded Search" routine for finding all matches to a given target weight and tolerance. However, I've left the Bounded Search method available in case the user wishes to search for a high molecular weight compound (over approx. 1000 Da) with many possible elements (over approximately four), in which case the user can enter a large minimum element occurrence number to speed up the search.
+
+
+
+ When the bounded search method is activated, changing the Target Molecular Weight changes the upper bounds on the checked elements. For example, if a target of 100 is entered, the upper bound on carbon will become 100/12=9. Further, if Smart Hydrogen checking is on, the upper bound on H's is only 53 rather than 103 (granted, 53 is still quite large, but is much more reasonable than 103).
+
+
+
+ When matching Percent Compositions in the Formula Finder routine using the Thorough Search mode, the user no longer must enter maximum and minimum values for the number of each element present, but they now do have to enter a maximum molecular weight of found compounds.
+
+
+
+ Reworked more of the code, consolidating more functions and adding a recursive aspect to the formula parsing routine so it can now handle an infinite number of levels of embedded parentheses (within available memory, of course).
+
+
+
+
+Revision 5.0 - Completed May 1, 1999
+
+
+ Code recompiled using Visual Basic 6.0 for Windows 95/98/NT.
+
+
+
+ Formulas are now displayed using RichText Boxes, allowing subscripts, superscripts, and colors to be displayed. I tried doing this with VB 5, but the program crashed continually. Thankfully, the RichTx32.dll that comes with VB 6 is stable.
+
+
+
+ Drag and drop of both formulas and results in the Formula Finder is now possible, thanks to the built-in functionality of the Rich Text Boxes. Simply highlight text to copy, then drag and drop it to the desired location (either in MwtWin or in another application, like Microsoft Word).
+
+
+
+ Added Copy Formula as RTF to allow a formula to be copied as its rich text format code. This allows the formula to be pasted into an RTF aware program (like Microsoft Word) and contain the appropriate super and subscripts. This can also be accomplished by dragging the formula from VB and dropping into Word.
+
+
+
+ When entering abbreviations in the Edit Abbreviations dialog, they are formatted with super and subscripts as the formula is typed.
+
+
+
+ When loading the Change Formula Font dialog, the progress of loading fonts is now displayed in the status bar.
+
+
+
+
+Revision 5.01 - Completed May 10, 1999
+
+
+ At a user's request, I have added the ability to enter a charge for each element and abbreviation, allowing the overall charge of a formula to be found. This is not useful for compounds with double bonds or rings, since bond order cannot be determined from the empirical formula. However, it is useful in situations where one knows the exact charge of each constituent of a compound, for example in inorganic clusters
+
+
+
+ Compute Charge has been added to the options menu to display the overall charge of formulas. Hydrogen is assumed to be +1, unless preceded by a non-halogen such as carbon or a metal.
+
+
+
+ More Formula Finder changes: 1) the charge can now be computed and displayed; 2) this also allows the mass to charge (m/z) ratio to be computed and displayed; 3) the results of a formula finder search can now be sorted by 1 of 4 criteria: formula, charge, molecular weight, and m/z ratio. Furthermore, the width of the Formula Finder window can now be widened to better display the results.
+
+
+
+ The font size of the formulas can now be changed using the Change Formula Font dialog. This font size also affects the results shown the in the formula finder.
+
+
+
+ When editing elemental values, uncertainties, and charges, clicking one of the buttons no longer automatically closes the edit box, allowing one to immediately see the new values that appear if any of the buttons are pushed.
+
+
+
+
+
Revision 5.02 - Completed May 12, 1999
+
+
+ Includes improvements to the Charge computation algorithm, as detailed in the charge section.
+
+
+
+
+
Revision 5.03 - Completed May 17, 1999
+
+
+ Updated the Calculator feature to use a rich text box, thus allowing powers like 2^2 to be displayed as superscripts.
+
+
+
Added more Charge and mass/charge ratio options in the formula finder, grouping the checkboxes together in an options dialog. The displayed compounds can now be limited to a specific charge range. Users can also search for compounds with a specific m/z (and thus a range of weights and charges).
+
+
+
Fixed program bug that prevented program from calculating formula weights at program start if in Single View mode.
+
+
+
Fixed program bug that incorrectly displayed the current formula at program start if in Single View mode.
+
+
+
Consolidated more code by combining redundant sections into shared subroutines.
+
+
+
+
+
Revision 5.04 - Completed May 18, 1999
+
+
+ Improved the speed of m/z searching in the formula finder when using the bounded search mode.
+
+
+
+
+
Revision 5.05 - Completed June 6, 1999
+
+
+ Added the option of not automatically adjusting the Min and Max values for elements in the Formula Finder when performing a bounded search (in the Formula Finder options box).
+
+
+
Corrected a major bug that rendered the bounded search in the Formula Finder inoperable if not calculating charges and m/z ratios of formulas.
+
+
+
+
+
Revision 5.06 - Completed July 10, 1999
+
+
+ Upgraded components to Service Pack 3 for Visual Basic 6.0
+
+
+
Moved the Sort Mode and Search Mode combo boxes from the formula finder main form to the formula finder options form.
+
+
+
Added option to quickly change the element mode on the program’s main form, called Quick Switch. These changes do not write the new elemental values to disk until exiting the program. When using the quick elemental mode switch, any user defined elemental values are lost.
+
+
+
Fixed bug that failed to color the status line yellow if a caution statement was displayed at program start.
+
+
+
+
+
Revision 5.07 - Completed July 14, 1999
+
+
Fixed bug that failed to update the Quick Switch Element mode when the Formula Finder finder weight mode warning window changed the weight mode for the user.
+
+
+
Fixed bug in Formula Finder that caused the number and underscore of custom elements to be inadvertently subscripted when displayed in the results box.
+
+
+
Fixed bug that failed to fill in element or abbreviation information the first time Edit Abbreviations or Edit Elements was chosen on the File menu (they filled in the second time).
+
+
+
Changed the Chlorine and Sulfur check boxes in the formula finder to custom element boxes to allow users the possibility of six custom elements or abbreviations.
+
+
+
Moved many of the program options from the Options menu to a preferences dialog box, making it easier to set multiple options at once. Added an option to make the Formula Finder warning mode screen reappear if user had earlier checked the box to make it never appear again.
+
+
+
Added a number of new keyboard shortcuts for menu items; all shortcuts are displayed in the menus.
+
+
+
Added current build of program to the intro screen and about box. This allows me to differentiate between different builds of a current version. Starting at build 35 was an arbitrary choice, made by counting 34 released versions before the current one. There have surely been several 100 builds of the program on my own computer, however.
+
+
+
+
+
Revision 5.07b - Completed July 18, 1999
+
+
Rolled back to Service Pack 2 (SP2) of Visual Basic for compiling the program due to errors arising when users tried to install the program on Windows 95 computers (specifically, received error with Comdlg32.ocx). It seems that VB6 SP3 is not compatible with the earlier (original?) version of Windows 95, while it works fine on computers with Windows 95b (plus Win 98/NT).
+
+
+
+
+
Revision 5.08 - Completed September 16, 1999
+
+
Re-updated program to Service Pack 3 (SP3) since the Comdlg32.ocx error did not appear to be widespread.
+
+
+
Updated web addresses to http://www.geocities.com/CapeCanaveral/Lab/9548/ from http://www.geocities.com/CapeCanaveral/Lab/9317/ due to a snafu at Geocities that erased my web pages, forcing me to create a new account (entirely their fault).
+
+
+
Also updated e-mail addresses to AlchemistMatt@Yahoo.com from AlchemistMatt@Geocities.com due to the merger of Geocities with Yahoo.
+
+
+
Made permissible the use of the plus sign (+) in abbreviations (at the request of a user). For example, an abbreviation called H+ or Na+ can now be entered, both in the main window and in the formula finder.
+
+
+
+
+
Revision 5.09 - Completed October 10, 1999
+
+
By user request, made the curly brackets, { and }, behave as parentheses in formulas. In addition, added the option of allowing regular brackets, [ and ], to also act as parentheses. When regular brackets are treated as parentheses, all Percent Solver options are disabled. Toggle the bracket mode in the Program Preferences Window.
+
+
+
Made regular and curly brackets available in the calculator. There, they behave as parentheses regardless of the bracket mode setting in the Program Preferences Window.
+
+
+
Fixed bug in calculator that superscripted the plus sign and subscripted numbers following the plus sign
+
+
+
Fixed bug that failed to set the standard deviation of a formula to zero when an error is found in the formula.
+
+
+
Since the plus sign was made an allowable part of an abbreviation in version 5.08, I added the underscore (_) to also be allowable, so users can add anions to the abbreviations list.
+
+
+
Fixed bug that failed to correctly set the "Never Show the Formula Finder Weight Mode Warning Dialog" value correctly when the user requested to "Stop Showing the Warning Dialog" option.
+
+
+
Since I was finding it annoying, I made the behavior in the Formula Finder of selecting an entire text field when clicking on it be turned off by default; it may be turned on in the Formula Finder options window.
+
+
+
Added code to correctly identify invalid Ctrl key combinations (like Ctrl+B, Ctrl+D, etc.) and notify the user if pressed.
+
+
+
+
+
Revision 5.10 - Completed December 19, 1999
+
+
Fixed bug that failed to recognize the last abbreviation (alphabetically) in the extended abbreviations list; Val is the default final extended abbreviation, thus it wasn’t being correctly identified.
+
+
+
Fixed bug that failed to update the Quick Switch Element Mode value on program load when the element mode was not Average weights.
+
+
+
Changed the behavior of the Copy Current Molecular weight command to just copy the weight value when standard deviation mode is set to off
+
+
+
Assigned Ctrl+W to be the shortcut for Copying the current molecular weight.
+
+
+
+
+
Revision 5.11 - Completed March 5, 2000
+
+
Added a window for performing calculations for open tubular and packed fused silica capillaries used in capillary liquid chromatography.
+
+
+
Also added the ability to perform Mass Rate Calculations, useful for determining amount of sample eluting from an electrospray needle in ESI-MS.
+
+
+
Fixed minor bugs in the Mole/Mass Converter, including failure to display numbers below 1E-6 when short Standard Deviation mode was on.
+
+
+
In addition to informing the user when the program’s .INI or .DAT files are being re-written due to corruption, I now list the name that the corrupted file has been renamed to.
+
+
+
Just for fun, added an "Always on Top" feature to the program, allowing the user to choose to have the main program windows stay on top of other windows.
+
+
+
Converted the help file to HTML help, since this allows me to display sub and superscripts, along with conforming to Microsoft's new help file standards.
+
+
+
+
+
Revision 5.12 - Completed June 27, 2000
+
+
At a user's request, added the option of Automatically Copying the current formula's molecular weight to the clipboard after each calculation.
+
+
+
In the Capillary Chromatography Calculations window, added the option to determine theoretically the extent to which band broadening will occur under various capillary conditions and dimensions.
+
+
+
+
+
Revision 5.2 - Completed September 28, 2000
+
+
To tell the truth, I can't recall what changes I made to warrant changing from 5.12 to 5.2 Most likely, I made some minor changes to the Capillary Chromatography Calculation window, including changing the name to Capillary Flow and Mass Rate Calculations.
+
+
+
+
+
Revision 5.21 - Completed April 3, 2001
+
+
Changed the constant used to compute Volumetric Flow Rate and Linear Velocity in the Capillary Flow and Mass Rate Calculations window to more accurately predict those values. Specifically, changed the constant form 180 to 270 in the following equation:
+ Vol Flow Rate = [Pressure * (diameter of packing)2 * (epsilon)2 * (capillary radius)2 * Pi] / [270 * viscosity * (column length) * (1 - epsilon)2] where epsilon is the interparticle porosity, typically 0.4
+
+
+
In addition, changed the name of the interparticle porosity to epsilon rather than eta, which I had erroneously labeled it as previously.
+
+
+
+
+
Revision 5.22 - Completed April 9, 2001
+
+
Changed a constant used to compute Volumetric Flow Rate and Linear Velocity in the Capillary Flow and Mass Rate Calculations window back to 180.
+
+
+
Added ability to view the equations used to compute the flow values.
+
+
+
+
+
Revision 5.23 - Completed June 18, 2001
+
+
Fixed a bug introduced in version 5.22 that caused the linear velocity value for open capillaries to be incorrect.
+
+
+
+
+
Revision 6.02 - Completed October 2, 2001
+
+
Added a 3 letter to 1 letter amino acid abbreviation conversion utility. The program still requires that peptide sequences be entered using three letter codes for molecular weight determination, but this converter makes it easier to copy and paste values from other peptide handling programs or the web. In addition to the standard 20 amino acids, the converter also recognizes U for Gla (gamma-Carboxyglutamtate).
+
+
+
Added numerous new Amino Acid abbreviations (Gla, Hse, Hyl, Hyp, Orn, and Sar). Only Gla has a corresponding one letter abbreviation, U, since I could not find any literature-wide agreement for one letter abbreviations for the other new amino acids.
+
+
+
Added ability to display more than 7 formulas simultaneously. The maximum is dependent upon your screen resolution. For example, the maximum for 1024x768 is 12 formulas. The total number to show can be set to a value lower than the maximum in the preferences window.
+
+
+
Added support for other (international) languages. The program can now be customized to support any Roman or Cyrillic character based language (German, French, Spanish, Italian, Russian) by creating a Lang_NewLanguage.ini file and loading the file by choosing Language under the Options menu. All text based phrases in the program can be customized, including ToolTip text and error messages.
+
+
+
Related to international language support, changed program to recognize if commas are set to represent decimal points on the user's computer (Regional Options under the Windows Control Panel). If so, replaces all period (.) decimal points with comma (,) decimal points.
+
+
+
Improved usability of the mole/mass converter by adding option to simply enter the mass of the compound. Additionally, provided option for mg/mL type concentrations rather than simply molarities.
+
+
+
Added numerous new units to the Mole/Mass converter, including micromoles, nmol, pmol, fmol, amol, & micrograms.
+
+
+
Added a new option to the Capillary Flow calculator to use a given Dead Time to compute the Volumetric Flow Rate that would give that dead time, modifying the Back Pressure appropriately to give the computed Volumetric Flow Rate.
+
+
+
Modified program to be dual-monitor aware. The program will now properly center itself on the primary monitor.
+
+
+
Fixed behavior of the Percent Solver to properly display the results rather than the target values when completing a computation. The target values are redisplayed when the user re-enters the set table.
+
+
+
Fixed the math calculator to properly handle parentheses (there were some weird bugs going on). Now using a recursive computation algorithm that allows an infinite level of embedded parentheses. Also, removed requirement that the multiplication operator (*) be included between numbers and parentheses, eg. 3(4+2)/(3+2)+(2/3)6 = 7.6 Finally, can now properly raise value of parentheses to a power, eg. 3*(4+2)^2 = 108
+
+
+
Shuffled around a few of the menus, including moving the Formula Finder, the converters, and the calculators to a new menu, the Tools menu.
+
+
+
Code Changes: Removed redundant code in the Capillary Flow Calculator. Changed application load and unload behavior to avoid the use of the End statement. Added code to prevent any sub forms from being unloaded from memory until program is exited completely.
+
+
+
Extensively edited the help file to bring up-to-date with the latest features and new locations of numerous program items.
+
+
+
Bumped up the version number to 6.0 owing to all of the new improvements. Also, using a version of 6.x, the program version now matches the version of Visual Basic used.
+
+
+
+
Revision 6.03 - Completed October 3, 2001
+
+
Added ability to cut, copy, or paste values from any of the program textboxes. I perform error checking to prevent invalid characters, and was inadvertently blocking Ctrl+X, Ctrl+C, and Ctrl+V
+
+
+
Added units of Bar and Torr (mm Hg) in pressure box of the Capillary Flow Calculator
+
+
+
Fixed bug in Capillary Flow Calculator that prevented Find Back Pressure and Find Inner Diameter from working
+
+
+
Fixed bug in Capillary Flow Calculator that delayed updating all results after clearing an input value to 0 then typing a valid number again.
+
+
+
+
+
Revision 6.04 - Completed October 11, 2001
+
+
Expanded the functionality of the Mole/Mass converter window to include a Dilution Calculator to handle volume-volume dilution calculations. Note that by setting the final concentration larger than the initial concentration this can also be used to perform calculations involving concentrating a solute by evaporation or sublimation.
+
+
+
Now coloring textboxes of computed quantities yellow to indicate they are a computed result and cannot be changed.
+
+
+
Fixed bug in cut/copy/paste from textboxes that prevented copying computed results in the capillary flow calculator.
+
+
+
Added keyboard shortcut of Ctrl+A to select all of the text (or numbers) in a text box. Does not apply to formulas in the main window since Ctrl+A means to expand abbreviations.
+
+
Added a simple undo feature to restore the currently selected formula or text box to the value it had when first entered. Once you have moved to a new control, the value of the old control cannot be restored. I will probably expand the undo system in the future.
+
+
+
Revision 6.05 - Completed October 23, 2001
+
+
Fixed Major bug in Formula Finder that prevented users from changing the Target Percent values for Percent Composition Searching. In addition, the Min and Max search values for bounded searches were also broken. I added a new textbox validation routine in version 6.04 and failed to correctly update the functions for the Formula Finder form.
+
+
+
Moved around a few of the controls on the Mole/Mass/Dilution form.
+
+
+
Updated the Lang_Portuguese.Ini and Lang_Spanish.Ini files.
+
+
+
+
Revision 6.06 - Completed November 11, 2001
+
+
Fixed bug with Mole/Mass/Dilution calculator that generated a program error if the window was minimized then restored (unminimized).
+
+
+
Restored behavior of the Mole/Mass/Dilution calculator window to be a fixed size.
+
+
+
+
Revision 6.10 - Completed January 25, 2002
+
+
Added Peptide Sequence Fragmentation Modelling tool, including ability to plot the theoretical mass spectrum of the fragmentation pattern for a given peptide sequence.
+
+
+
The new Fragmentation Modelling Tool also includes ability to paste actual mass spectral data (mass/intensity pairs) so that the predicted ions can be matched to the raw data. The raw data may also be plotted with the predicted fragment ions.
+
+
+
Added option to enter column diameters in inches in the Capillary Flow and Mass Rate Calculations Window.
+
+
+
Modified Formula Finder results list to grow/shrink vertically in addition to horizontally when the window is resized.
+
+
+
Modified Amino Acid Notation Converter to properly handle H at the beginning and OH at the end in the three-letter based sequence input box. In addition, modified to properly reposition and resize controls when window resized.
+
+
+
Changed Ctrl+A to select entire formula since this is the expected behavior for Ctrl+A in Windows applications and Abbreviation Expansion is most likely rarely used.
+
+
+
Fixed bug in main window involving the order of tabbing between controls.
+
+
+
Fixed bug that failed to sum up standard deviation values for all portions of a formula when using parentheses or abbreviations.
+
+
+
Fixed bug that failed to re-calculate the molecular weight or percent composition of formulas in Single View when the formula is modified using Cut/Copy/Paste via Ctrl+X/Ctrl+C/Ctrl+V.
+
+
+
Fixed bug that caused the Percent Solver to give an answer slightly off (less than 0.001%) from the correct answer when the standard deviation mode was turned on.
+
+
+
Major update to the Lang_Spanish.Ini file with corrections contributed by Perez de la Hoz.
+
+
+
+
+
Revision 6.11 - Completed March 9, 2002
+
+
Fixed bug that failed to save new amino acid abbreviations if the charge state was not specified
+
+
+
Updated Lang_Russian.Ini file (contributed by Michael I. Yahkind)
+
+
+
+
Revision 6.12 - Completed March 10, 2002
+
+
Removed restriction preventing a formula from starting with a number. Now, starting a formula with a number will multiply the following elements (up to the first dash) by the number. Thus, the following are all equivalent ways of entering a formula with 10 fluorine atoms: F10, (F)10, [10F], and 10F
+
+
+
+
Revision 6.13 - Completed May 7, 2002
+
+
Added ability to edit the one letter abbreviations of amino acids
+
+
+
Fixed bug in 3 to 1 letter amino acid notation converter that failed to mark amino acid abbreviations with no equivalent code with an X when the amino acid existed but no 1 letter abbreviation was defined.
+
+
+
Added ability to resize the abbreviation editing window, accompanied by automatic column width expansion.
+
+
+
Changed help ID numbers to show the correct help screen when pressing F1 in the amino acid notation converter window.
+
+
+
Updated Lang_Portuguese.Ini file (contributed by Alexandre R Soares)
+
+
+
Revision 6.14 - Completed May 9, 2002
+
+
Fixed bug in abbreviation editor that failed to properly sort the 1 letter abbreviations when adding or removing amino acid abbreviations.
+
+
+
+
Revision 6.16 - Completed June 8, 2002
+
+
Added option to run the Formula Finder in batch analysis mode, reading search values from a file and writing the results to an output file. See the Batch Analysis help page for more information.
+
+
Fixed bug in formula finder that re-initialized all of the custom elements to the phrase "# or element or abbrev" after leaving and returning to the form.
+
+
+
+
Revision 6.17 - Completed July 1, 2002
+
+
Added ability to predict the Isotopic Distribution for a given formula, predicting the masses and relative abundances of all possible isotopes. Includes ability to handle explicitly specified elements as part of the formula, in addition to graphing the results.
+
+
+
+
Revision 6.18 - Completed July 2, 2002
+
+
Turned on the error checking in the Isotopic Distribution module that I had forgotten to turn back on.
+
Updated the help files to discuss Isotopic Distribution.
+
Now displaying the formula with subscripts and superscripts on the Isotopic Distribution window.
+
Updated the Isotopic Distribution results display to be more cleanly formatted.
+
+
+
Revision 6.19 - Completed August 12, 2002
+
+
Added ability to use custom amino acids in the Peptide Sequence Fragmentation Modeller.
+
Added the ability to save and load capillary flow settings to/from text files.
+
Added the option to automatically show one of the program modules at program start (instead of the default program window). Clicking the X on the module window exits the entire program. Choosing Close (from a menu or a button) returns to the main program screen.
+
Changed default diffusion coefficient in the Capillary Flow and Mass Rate Calculations module to be 5E-6. Also, changed tooltip to state that typical coefficient for small organics is 1E-5 rather than 1E-6.
+
Fixed bug in amino acid notation convertor that caused the program to crash if the 3 letter sequence was copied to the list of formulas, but the main window was hidden since Hide Inactive Program windows was turned on.
+
Re-worked the algorithms used to parse and store the user-defined abbreviations and amino acids. If an invalid (or duplicate) abbreviation is present, the user will now be able to see it using Edit | Abbreviations and correct or remove the abbreviation.
+
+
+
Revision 6.20 - Completed October 15, 2002
+
+
Modified form layouts to behave properly using the default Windows XP theme (which uses wider borders than previous themes)
+
Minor updates to the help files, including updating contact information.
+
+
+
Revision 6.21 - Completed November 17, 2002
+
+
Added custom language captions for the results box in the Isotopic Distribution window.
+
Added a new language: Catalan (aka Català)
+
+
+
Revision 6.22 - Completed November 29, 2002
+
+
Modified the Set X Range and Set Y Range functions on the Plot window to allow users to set the view range to more than 110% of the current data range. The new allowable limit is up to 1000 times the data range.
+
+
+
Revision 6.25 - Beta 12 completed June 16, 2003
+
+
Although the program interface looks very similar, all of the primary computation routines have been moved to an ActiveX DLL file. Doing this allowed me to greatly clean up a lot of the legacy code present in the software.
+
Additional units have been added to many of the parameters in the Capillary Flow Calculations window.
+
Additional units have been added to some of the parametesr in the Mole/Mass Converter window.
+
Abbreviations may now contain other abbreviations. For example, if Ph = C6H5 then you could define Cb = PhCl. This also allows D to be used inside other abbreviations.
+
The ability to right-click and see the Cut/Copy/Paste etc. options has been added to numerous text boxes throughout the program.
+
The Peptide Sequence and Fragmentation module has been greatly expanded:
+
+
You can now define modification symbols to allow for modified amino acids.
+
You can now choose the functional group present at the N and C terminus.
+
Phosphorylation is now an allowable neutral loss.
+
The fragmentation mass listing now excludes those ions that could not possibly form, based on location in the peptide and whether or not a specific residue can lose water, ammonia, or the phosphate group.
+
The mass of the peptide, including any modifications, is now displayed on the form, along with the equivalent mass of the M+H mass.
+
You can convert between M+H and [M+nH]n+ where n is between 1 and 10.
+
The graphing component has been updated to a professional component. The graph is now much faster and much more powerful, allowing for custom annotations and numerous other features, including the ability to save and load graphs (including all colors, styles, and annotations).
+
The theoretical fragmentation spectrum can be included on the graph, and any matches with the real data can be included as annotations on the graph.
+
The peptide sequence and fragmentation module (and the accompanying graph) can correctly read .Dta files (common text-based MS/MS file format).
+
+
The Batch Analysis feature has been greatly expanded. Numerous new commands are now present, including the ability to change the standard deviation mode, convert compounds to empirical formulas, and convert amino acid sequences to/from 1 and 3 letter notation.
+
You can now subtract out elements from a formula using the > symbol:
+
+
This feature was added to allow one to quickly find the mass or empirical formula of a compound that has lost one or more elements due to a reaction or a neutral loss in mass spectrometry.
+
For example: C6H5Cl>HCl means C6H5Cl minus HCl, having a mass equivalent to C6H4
+
The elements to the right of the > symbol must all be present in the elements to the left of the > symbol (see Element Subtraction for more information).
+
+
Changed the /X command line switch to mean "do not write any settings (abbreviations, elements, values) to disk"
+
Added a new command line switch, /Z, meaning "do not read or write any settings to/from disk"
+
+
+
Revision 6.26 - Completed August 3, 2003
+
+
Updated the Isotopic Distribution module to use the new graphing component described above for the Peptide Sequence Fragmentation module
+
Added the ability to paste a list of ions to compare with the predicted isotopic distribution.
+
Added error handling routines to the Formula Finder code to reduce the possibility of abrupt program crashes.
+
+
+
Revision 6.27 - Completed October 10, 2003
+
+
Fixed bug on the Peptide Sequence and Fragmentation Module that used 1.00000 for the mass of hydrogen rather than 1.00782 when converting between M+H and [M+nH]n+
+
+
+
Revision 6.28 - Completed October 30, 2003
+
+
Added option to the graph component to define custom tick starting values and intervals. Use Edit->Zoom Range.
+
+
+
Revision 6.29 - Completed November 23, 2003
+
+
Fixed bug involving call to Peptide.SetModificationSymbol in MwtWinDll.Dll that caused the program to crash if the user had the Windows decimal point set to a comma rather than a period, as is common in many countries outside the United States and the UK.
+
+
+
Revision 6.30 - Completed December 3, 2003
+
+
Modified the graph control to allow changing the border color and border style (3D or plain)
+
+
+
Revision 6.31 - Completed January 12, 2004
+
+
Added new window that allows one to compute solvent viscosity for a mixture of water and acetonitrile (MeCN) given the temperature and percent organic composition. The routine uses the Chen-Horvath equation (see Thompson, JD; Carr, P, Analytical Chemistry, 2002, 74, 4150-4159 or Chen, H; Horvath, CJ, Chromatography A, 1995, 705, 3)
+
Can also graph the viscosity as a function of percent organic composition for the given temperature.
+
+
+
Revision 6.32 - Completed February 29, 2004
+
+
Fixed bug in Capillary Flow Calculator that gave erroneous results if one were to set the particle diameter to 0, then back to a non-zero value when finding column back pressure for packed capillaries.
+
Now displaying the references to the Chen-Horvath viscosity equation in the program, just below the equation.
+
+
+
Revision 6.33 - Completed March 27, 2004
+
+
Updated the MwtWinDll.Dll file to include Xxx as a default amino acid abbreviation, equivalent to C6H12NO (Lysine)
+
+
+
Revision 6.34 - Completed August 14, 2004
+
+
Fixed bug in the Peptide Sequence and Fragmentation module that used the monoisotopic mass of hydrogen as the charge carrier rather than using the mass of a proton (which is 0.0005 Da less than the mass of hydrogen). This involved updating MwtWinDll.Dll.
+
On the Isotopic Distribution module, added the ability to display the masses as m/z values, with charge values greater than 1.
+
+
+
Revision 6.35 - Completed September 12, 2004
+
+
Fixed bug in the Mole/Mass/Dilution Calculator that involved the dilution concentrations not updating when the custom mass was changed.
+
+
+
Revision 6.36 - Completed November 16, 2004
+
+
Updated the MwtWinDll.Dll file with a few bug fixes involving the peptide parsing class
+
+
+
Revision 6.37 - Completed December 26, 2004
+
+
Extended the Batch Calculation engine to support Isotopic Distribution commands. Enable using IsotopicDistribution=On ; Set the charge state using IsotopicDistributionCharge=1
+
+
+
Revision 6.38 - Completed February 18, 2006
+
+
Added error handlers to the copy and paste routines
+
Updated the mass of the most abundant isotope for each element to match the default monoisotopic mass for each element
+
+
The elemental masses come from two different sources and the monoisotopic mass was sometimes slightly different than the most abundant isotope's mass; this has been corrected
+
As part of this update, switched the variables used to store mass values from single to double precision
+
+
diff --git a/html/NewFormula.htm b/html/NewFormula.htm
new file mode 100644
index 0000000..25857d5
--- /dev/null
+++ b/html/NewFormula.htm
@@ -0,0 +1,15 @@
+
+
+
+
+New Formula Button
+
+
+
New Formula Button
+
Location: Main Program Window
+
+
+The New Formula Button (Alt-N) creates a new blank formula line provided the current formula is not blank. This is useful when Advance on Calculate is turned off and in Single View mode since the ENTER key does not create a new line in these cases.
+
+
+
diff --git a/html/Overview.htm b/html/Overview.htm
new file mode 100644
index 0000000..54e770e
--- /dev/null
+++ b/html/Overview.htm
@@ -0,0 +1,150 @@
+
+
+
+
+Overview of Features
+
+
+
Overview of Features
+
+ Click the contents button to see a list of available help topics.
+ (may need to click the Show button at the upper left)
+
+
+
Tools
+
+Mole/Mass/Dilution Converter for easily interconverting moles and mass, for computing molarity or concentration given an amount and volume, and for performing dilution calculations.
+
+Formula Finder for finding potential empirical formulas for a given molecular weight or for a given set of percent composition data. Includes a Smart Hydrogen feature to limit the number of hydrogen atoms in found compounds to a reasonable number.
+
+Amino Acid Notation Converter to convert between 3 letter and 1 letter abbreviations for amino acids (converts both ways).
+
+Peptide Sequence Fragmentation Modelling module to predict the ion masses expected from fragmentation of a peptide in the collision cell of a mass spectrometer. Actual experimental data may also be matched to a theoretical peptide sequence.
+
+Capillary Calculations module for performing typical flow, mass-rate, and band broadening calculations in open and packed capillary columns, commonly used in capillary liquid chromatography
+
+Isotopic Distribution module for predicting the masses and abundances of the isotopes for a given formula, useful for comparison to observed mass spectrometry results
+
+
Built-in mathematical calculator that follows mathematical precedence rules.
+For example, CH3(CH2)3CH3 is equivalent to CH3CH2CH2CH2CH3
+
+
+
+
+
+Can also handle decimal numbers following parentheses.
+
+For example, (Fe2O3).5 is equivalent to FeO1.5
+
+
+
+
+Hydrates or other appended compounds are allowed.
+
+For example, FeCl3-6H2O or FeCl3-2.5H2O
+
+
+
+
+
+Can also begin a formula with a number.
+
+For example, 4FeCl3-6H2O is equivalent to (FeCl3)4-6H2O
+
+
+
+
+
+User-definable abbreviations Default abbreviations are included for common parts of compounds, including amino acids. See full list.
+
+For example, PhCl = C6H5Cl and
+HOAc = CH3COOH.
+
+
+
+
+Smart Case Conversion The program will automatically convert lowercase letters to uppercase where appropriate for ease of entering a formula. Exact case matching and non-conversion are also available.
+
+
+
+Isotopes are recognized using the following notation:
+
+^13C is Carbon-13
+C6H5^18OH is heavy-oxygen (Oxygen-18) labeled phenol
+^78.918Br is Bromine 79 with a specific isotopic mass
+
+Feature of weighting parts of a compound relative to the other parts. For example:
+
+[.2Na]Cl would have a weight of 0.2*22.989768+35.4527=40.0507
+NaCl-.5H2O would have a weight of 22.989768+35.4527+0.5*(2*1.00794+15.9994)=67.4501
+
+
+
+
+
+Feature of Element Subtraction to return the mass of a formula, minus one or more elements. For example:
+
+C6H5Cl>HCl means C6H5Cl minus HCl, having a mass of 76.0959 Da (average mass), equivalent to C6H4
+
+
+
+
+The overall Charge on a compound can be estimated. The program sums up the default charges for each element and for each abbreviation to give the total charge for a formula. Hydrogens are treated as +1 when preceded by a halogen and -1 when preceded by other elements (including carbon and all metals).
+
+Percent Solver mode for finding the value of "x" in a compound that satisfies user-specified percent composition requirements.
+
+
+International (foreign language) text phrases may be loaded for all labels and messages in the program. Current languages included are Spanish, German, Portuguese, and Russian. You can make your own language-specific caption file by simply editing a text file.
+Edit and save elemental values while program is running. Further, default elemental weights can be set for the elements' average atomic weights, isotopic weight of the most common isotope, or nominal integer weight of the most common isotope.
+
+Accuracy of the final digit of the molecular wt. and percent composition.
+
+Capability of saving options as defaults and automatic loading of the saved options upon program start.
+Ability to process and compute molecular weights for compounds listed in an input text file. Can also run the Formula Finder in batch mode using a text file. Specify the file by choosing calculate weights from file menu or using the /F:filename switch at command line.
+Parentheses are used to repeat parts of a compound. For example, C6(COOH)6 has 12 carbon atoms, 12 oxygen atoms, and 6 hydrogen atoms while CH(C(CH3)3)3 is a carbon atom with three C(CH3)3 groups attached and a hydrogen atom attached.
+
+
+The program supports any number of layers of embedded parentheses. Furthermore, curly brackets, { and }, are treated as parentheses, while regular brackets, [ and ], can be treated as parentheses if desired (see the Program Preferences Window).
+Note: Percent Solver Mode is disabled if the "Treat Brackets as Parentheses" option is selected in the Program Preferences screen.
+
+
+The Percent Solver Mode is enabled using the View Menu or using the ShortCut Keys The F11, PAGE UP or PAGE DOWN. Percent solver mode is useful for entering target percent composition values and solving for the best value of "x" in a formula to satisfy these values. The equation for determining the best value for x is found in the calculations section of this help file.
+
+
+To set the target percent composition values, use the PAGE UP, PAGE DOWN, and arrow keys to move among the percent compositions shown, then press Enter or click on a percent to type in the target values for the solver to aim for. Select OK to accept the value, cancel to cancel any changes, or Reset to un-target the percent.
+
+
+Before the solver can work, you need to place an x in the formula, directly after a bracket. For example, "C6H6-[xH2O]" is useful for calculating the amount of water in a benzene sample, provided elemental analysis data is available. The formula must be in bracketed form for the solver to work. If you have the formula "NaClx", where you wish to find the number of chlorine atoms based on data, simply retype the formula in the form "Na[xCl]" for the percent solver to be able to interpret the it. When at least one target percent is entered and an x is present after a bracket in the formula, you may navigate the cursor to the formula line then press ENTER or click on the Calculate Button to begin solving.
+
+The program will indicate the progress of its calculations. Press any key or click the mouse during the calculations to stop them before they are completed. The computer should stop calculating once it gets the same answer four times in a row, which should be to approximately four or five decimal places.
+
+After the calculations are complete, a window will appear which shows the obtained percentages, target percentages, and differences between these numbers. This is useful for seeing how well the x value works for matching the target percentages. Use the Copy button to copy the data to the clipboard. Closing the box with the close button returns you to the main program. Press the F11 key again to exit percent solver mode.
+
+NOTE: If the program is not in Percent Solver mode, but an x is present in the formula after a bracket, the program will calculate the molecular weight based on x equaling one.
The fragmentation modelling tool can be used to predict the potential ions observed when a peptide is fragmented in the collision cell of a tandem mass spectrometer or quadrupole ion trap. In a collision cell, adjustment of various instrumental voltages imparts additional kinetic energy onto ions entering the cell, resulting in fragmentation at certain bonds of the ion.
+
+
Background
+
Fragmentation of peptides (amino acid chains) typically occurs along the peptide backbone. Each residue of the peptide chain successively fragments off, both in the N->C and C->N direction. The location that the fragmentation occurs, and the nature of the ion remaining results in various ions, a, b, c and x, y, or z ions. The most commonly observed ions are a, b, and y ions. The following diagram illustrates the formation of b and y ions during the fragmentation of a three residue peptide chain.
+
+
+
+
+
+
The Peptide Sequence Fragmentation Modelling tool can be used to tabulate all of the potential ion fragment masses that could be observed for a given peptide. Optional modifications can be applied, including the loss of an ammonium or hydroxyl ion.
+
+
Importing Ions
+
Actual ion data can be imported into the program so that ion matching can be performed. You can import a list of ions to match from a text file by choosing Load List of Ions to Match from the File menu. Alternatively, you can copy the list of ions to the clipboard, then choose Paste List of Ions to Match from the Edit Menu. If the ion list is already visible, you can click on the ion list and press Ctrl+V to paste a new ion list. The format of the ion list should be a list of mass (m/z) and intensity pairs, separated by a space, tab, or comma, with each mass/intensity pair on a separate line. If your software has the ability of deconvoluting the spectrum to transform 2+ and 3+ ions to their 1+ representation, it is advisable that you do this prior to importing the ion list into the Molecular Weight Calculator.
+
+
Binning
+
In order to decrease the total number of ions to be matched, the ions being imported can be binned (grouped together) when they are imported. This process involves comparing adjacent ions to see if their m/z difference is below a threshold. If it is, the two (or more) ions are combined to just one ion having an m/z value equal to the average of all the m/z values within tolerance of the given bin. The largest intensity of the combined ions is used for the intensity of the binned ion. The following table illustrates a small portion of an ion list before and after binning. Note that if the average spacing between the m/z values of the ions in the list you import is less than 0.2 Da, then binning of the ions to 0.5 Da is automatically enabled. You may manually enable binning, along with setting the binning parameters using the Ion Match List Options window.
+
+
+
+
Original Data
+
+
After Binning (Window = 0.5 Da)
+
+
+
m/z
+
Intensity
+
+
m/z
+
Intensity
+
+
+
+
+
+
585.9116
+
+
+
586.0613
+
+
+
+
+
+
+
3
+
+
+
5
+
+
+
+
585.9865
+
5
+
+
+
+
+
+
586.3880
+
+
+
586.5022
+
+
+
586.5732
+
+
+
+
+
+
+
11
+
+
+
1
+
+
+
2
+
+
+
+
586.4878
+
11
+
+
+
586.8460
+
12
+
586.8460
+
12
+
+
+
+
+
+
587.4271
+
+
+
587.7023
+
+
+
+
+
+
+
1387
+
+
+
8
+
+
+
+
587.5647
+
1387
+
+
+
+
+
+
587.7939
+
+
+
587.8698
+
+
+
588.0663
+
+
+
588.2092
+
+
+
+
+
+
+
6
+
+
+
6
+
+
+
5
+
+
+
8
+
+
+
+
587.9848
+
8
+
+
+
+
+
+
588.4289
+
+
+
588.6898
+
+
+
+
+
+
+
520
+
+
+
10
+
+
+
+
588.5594
+
520
+
+
+
+
+
+
588.7769
+
+
+
588.9930
+
+
+
+
+
+
+
6
+
+
+
12
+
+
+
+
588.8850
+
12
+
+
+
+
Precursor Removal and Normalization
+
Once the list of ions has been imported into the program, the precursor ion may optionally be removed (if present). The mass of the precursor ion to search for and mass window (tolerance) to match it are specified in the Ion Match Options frame of the Peptide Sequence Fragmentation Modelling window.
+
+
The ion list is next normalized to keep only the most intense ions and to allow a match score to be computed when matching ions. Normalization involves first sorting the list by decreasing intensity and only keeping the top-most ions (defined by Number of Ions to Use). Next, the list of ions actually being used is subdivided into mass regions (typically 10 regions). The ions in each mass region are normalized to the most intense ion in the given region, and all ions are normalized to a uniform maximum value, typically 100. Normalization parameters can be modified using the Ion Match List Options window
+
+
The following table illustrates a raw ion list, the list after choosing just the top 10 ions, and the list after dividing into 3 regions and normalizing each region. Note that unlike the example table above, this list was not binned.
+
+
+
+
Original Data
+
+ Top 10 ions
+ Three Subdivisions
+
+
+
+
m/z
+
Intensity
+
m/z
+
Raw Intensity
+
+
Normalized
+ Intensity
+
+
+
+
585.9116
+
3
+
586.388
+
11
+
0.8
+
+
+
586.0613
+
5
+
586.846
+
12
+
0.9
+
+
+
586.388
+
11
+
587.4271
+
1387
+
100
+
+
+
586.5022
+
1
+
587.7023
+
8
+
100
+
+
+
586.5732
+
2
+
587.7939
+
6
+
75
+
+
+
586.846
+
12
+
587.8698
+
6
+
75
+
+
+
587.4271
+
1387
+
588.2092
+
8
+
100
+
+
+
587.7023
+
8
+
588.4289
+
520
+
100
+
+
+
587.7939
+
6
+
588.6898
+
10
+
1.9
+
+
+
587.8698
+
6
+
588.993
+
12
+
2.3
+
+
+
588.0663
+
5
+
+
+
+
588.2092
+
8
+
+
+
588.4289
+
520
+
+
+
588.6898
+
10
+
+
+
588.7769
+
6
+
+
+
588.993
+
12
+
+
+
+
Ion Matching
+
When normalization is complete, the ion masses remaining in the ion list are compared to the masses predicted for the fragmentation products of the peptide chain. If a match is found within the specified tolerance, then the ion is highlighted both in the peptide fragmentation table and in the ion matching list. The following table explains the colors used for highlighting ions.
+
+
+
+
Color
+
Explanation
+
+
+
Cyan
+
+
The ion is present (within tolerance) in both the ion match list and the predicted fragmentation ion table.
+
+
+
+
+
Yellow
+
+
The ion in the match list was matched to a shoulder ion in the predicted fragmentation ion table.
+
+
+
+
+
Light Red
+
+
An ion was present at 110, 120, or 136 m/z in the match list with a normalized score of 40% of the max or greater, but histidine, phenylalanine, or tyrosine was not one of the residues in the peptide chain. See the discussion on rho (ρ) in the scoring algorithm below.
+
+
+
+
+
+
Ion match statistics are provided, including the number of ions loaded, the number remaining after binning (if applicable), the number within tolerance, whether or not the precursor was found and removed, and the number of matching ions.
A match score is also computed. The higher the score, the better the match. The matching score was modeled after the score used in the Sequest search algorithm developed by John Yates and Jimmy Eng (United States Patent 5,538,897; July 23, 1996). The match score was developed to provide a means for comparing the quality of match of potential peptide sequences against a given mass spectrum. The score is included in this program to allow you to compare the quality of a match for various spectra you might manually inspect using the fragmentation modelling routine. This program is not meant as a replacement for Sequest and will not automatically search a database to find the best matching sequence for a given spectrum.
+
+
In order to make the match score more meaningful, the predicted fragmentation ions are assigned arbitrary intensities based on the ion type. The default values are 50 counts for the b and y ions, 10 counts for the a ions, and 10 counts for any neutral losses selected. In addition, shoulder ions can be added for the b and y ions. Shoulder ions are simply ions added at ±1 Da for each b or y ion, since actual data often contains shoulder ions around the b and y ion peaks. An intensity of 25 counts is assigned to shoulder ions. The default intensities can be modified using the Ion Match List Options window.
In the equation im is the sum of the intensities of each of the matches and (ni) is the count of the matches. 1+β is a correction factor to increase the score when successive y or b ions are found. β is initially zero, but is increased by 0.075 for each sequential y ion and each sequential b ion matched. Similarly, ρ is a correction factor to increase or decrease the score for the occurrence of certain immonium ions. The immonium ions of histidine (110), phenylalanine (120), and tyrosine (136) are commonly observed in fragmentation spectra. These ions are searched for in the normalized ion list, and if a match is found and its intensity is 40% or greater of the maximum intensity, then the given peptide chain is examined to look for the corresponding residue.
+
+
For example, if an ion at 120 m/z has an intensity of 60 out of a maximum of 100, then the peptide sequence is examined. If phenylalanine (Phe or F) is present, then rho is increased by 0.15 If Phe is not found, then rho is decreased by 0.15 If the 120 m/z ion was not found, rho is left unchanged. Following this procedure, rho can range anywhere from -0.45 to 0.45 Note, that in the original patent the equation used (1-ρ) rather than (1+ρ). I believe this to be an error since one would want a higher match score if the immonium ion is found and is present in the sequence of interest. The following table illustrates how a sample sequence would be scored.
+
+
+
+
+
+
+
#
+
Immon.
+
a
+
b
+
b*
+
Seq.
+
y
+
y*
+
#
+
+
+
1
+
136.08
+
136.08
+
164.07
+
147.07
+
Y
+
564.35
+
547.35
+
4
+
+
+
2
+
86.1
+
249.16
+
277.16
+
260.15
+
L
+
401.29
+
384.28
+
3
+
+
+
3
+
86.1
+
362.25
+
390.24
+
373.24
+
L
+
288.2
+
271.2
+
2
+
+
+
4
+
129.12
+
518.35
+
546.34
+
529.34
+
R
+
175.12
+
158.12
+
1
+
+
+
+
+
+
+
Mass
+
Intensity
+
+
+
136.18
+
100.00
+
+
+
139.11
+
28.81
+
+
+
159.12
+
57.63
+
+
+
164.82
+
32.43
+
+
+
175.13
+
62.71
+
+
+
187.11
+
62.71
+
+
+
227.10
+
13.42
+
+
+
235.12
+
8.22
+
+
+
246.65
+
29.44
+
+
+
260.65
+
64.50
+
+
+
261.14
+
16.88
+
+
+
271.2
+
7.36
+
+
+
288.21
+
27.27
+
+
+
289.21
+
7.36
+
+
+
294.19
+
100.00
+
+
+
379.21
+
5.66
+
+
+
384.28
+
5.66
+
+
+
390.19
+
14.02
+
+
+
401.31
+
100.00
+
+
+
402.31
+
21.82
+
+
+
+
+
+
+
Computation of score, parsing left to right, top to bottom;
+ a ions are 10 counts, b and y are 50 counts, b/y shoulders are 25,
+ neutral loss ions are 10 counts
+
Σ im = a + b + b* + y + y* + b + y + y* + y
+ Σ im = 10+25+10+50+10+50+50+10+50
+ Σ im = 265
+
ni = 9
+
β = 0.075 + 0.075 = 0.15
+ (since three y ions in a row)
+
ρ = 0.15
+ (since 136.18 found and Y is in fact present)
+
The predicted masses from fragmentation of the peptide sequence may be plotted by choosing View | Predicted mass spectrum. If a list of ions to match is present, those ions will also be plotted. If "Update Spectrum on Change" is enabled (Tools menu) then any changes to the loaded ions or predicted fragmentation ions will cause the plot to be updated. For more information, see the Ion Plot Window
+
+
Aligning
+
The Alignment Offset value can be used to shift the m/z value of all of the ions in the match list to correct for a slightly miscalibrated instrument or to account for a post-translational modification that has changed the overall mass of the peptide whose ions are in the match list. In addition to manually entering an offset value, you can have the program automatically search for the offset value that gives the best match score by choosing Tools | Automatically align Ions to Match.
+
+
This process involves incrementing through all of the possible alignment values over a given range with a given increment value. For example, if you enter a maximum offset of 20 and an offset increment of 0.1, the program will test 400 different offset values ranging from -20 to 20 to see which one gives the best match score. If one or more sequential offset values give the same match score, the average of the offset values is kept. For example, if 0.6, 0.7, and 0.8 all give a match score of 423, then offset value displayed when completed is 0.7 A progress indicator is shown which displays the time elapsed and the estimated time to completion. In addition, the current offset value being tested is displayed, along with the statistics for the best matching offset value (not shown until the process is completed, or aborted by pressing escape).
+
+The results can be printed by selecting Print Results from the File Menu or clicking the Print button in the Formula Finder. In Multi View Mode, the formulas and their molecular weights will be printed. In Single View Mode, the current formula and its percent composition results will be printed. In the Formula Finder, the formulas in the results box will be printed.
+
+
diff --git a/html/ProgramOptions.htm b/html/ProgramOptions.htm
new file mode 100644
index 0000000..3de3775
--- /dev/null
+++ b/html/ProgramOptions.htm
@@ -0,0 +1,51 @@
+
+
+
+
+Change Program Preferences
+
+
+
+In this screen you can set various options that affect how the program behaves while parsing formulas, when using the Formula Finder, and when exiting the program. These options take effect as soon as they are selected, and the options window can be kept open while typing formulas to explore what effect each option has. To cancel any changes made since first opening the options window, press the Cancel button. Otherwise, press the Close button to close the window. The shortcut key for viewing the Program Preferences Window is Ctrl+O
+Revision History for the Molecular Weight Calculator program
+by Matthew Monroe
+
+
+ Revision 1 - DOS version Completed August 6, 1995 (QuickBasic for DOS)
+ Contains the following basic features:
+
+
+
formula weight calculation
+
+
+
percent composition calculation
+
+
+
can handle parentheses, up to 2 sets of embedding
+
+
+
can handle hydrates and other additional compounds
+
+
+
can handle numbers up to 2 digits long
+
+
+
two types of case conversion
+
+
+
help screen
+
+
+
+
+Revision 2.0 - Completed August 8, 1995
+
+
Can now handle numbers up to 6 digits long
+
+
+
Can now handle up to 4 sets of embedded parentheses
+
+
+
Now includes ability to handle brackets and partial weights
+
+
+
Now has three types of case conversion
+
+
+
Added expanded help screens
+
+
+
+
+Revision 2.1 - Completed August 9, 1995
+
+
Can now show display of current time
+
+
+
+
+Revision 2.2 - Completed August 10, 1995
+
+
Added a simple math calculator
+
+
+
+
+Revision 2.21 - Completed August 17, 1995
+
+
+ Contains minor bug fixes.
+
+
+
+
+Revision 2.3 - Completed September 2, 1995
+
+
added command line switches to control internal settings
+
+
+
Added standard deviation option
+
+
+
Added recognition Bu for butyl group
+
+
+
+
+Revision 2.4 - Completed December 1, 1995
+
+
Added a Percent solver routine.
+
+
+
Combined F11 and F12 std. deviation options into just F12
+
+
+
Contains Screen update bug fixes.
+
+
+
+
+Revision 2.5 - Completed December 7, 1995
+
+
Improved speed of the % solver algorithm.
+
+
+
Added recognition of Urea, Ox, Py, En, Tpp, Otf.
+
+
+
+
+Revision 2.55 - Completed December 17, 1995
+
+
Added error trapping routines.
+
+
+
Improved handling of exponentially large and small numbers.
+
+
+
Added warning statements for possibly ambiguous abbreviations such as Bpy and Py.
+
+
+
+
+Revision 2.6 - Completed January 16, 1996
+
+
Recognizes Amino Acid abbreviations.
+
+
+
+ Recognizes Deuterium, D abbreviation.
+
+
+
+ Percent Solver values can now be set for all elements of a formula.
+
+
+
+ Displays differences between actual and theoretical values at the conclusion of the percent solver routine.
+
+
+
+ Added CTRL-P option to print results.
+
+
+
+ Added more error messages/explanations for incorrect user entries.
+
+
+
+
+
+Revision 2.7 - Completed March 1, 1996
+
+
Now able to handle isotopes; use the caret (^) symbol.
+
+
+
+ Now able to calculate powers of numbers in the calculator.
+
+
+
+ Added more error messages/explanations for incorrect entries.
+
+
+
+ Included a moderately accurate error handler to check the validity of entered isotopic masses.
+
+
+
+ Added numerous "caution" statements for possibly erroneous entries: eg. Co vs. CO and Sc vs. SC
+ (This feature may be toggled on and off with CTRL-C)
+
+
+
+ Improved speed of the % solver algorithm; watch it blaze!
+
+
+
+ Removed CTRL-P option -- use PRINT-SCREEN or SHIFT-PRINT-SCREEN
+
+
+
+ Changed the order and layout of the in-program help screens.
+
+
+
+ Fixed typos in help screens and added two more help screens.
+
+
+
+
+
+Revision 2.8 - Completed May 1, 1996
+
+
Now able to handle user-defined abbreviations listed in the MWT_ABBR.DAT file.
+
+
+
+ Added error checking to prevent duplicate abbreviations or abbreviations duplicating elements.
+
+
+
+ Added automatic re-creation of the abbreviation file if it is deleted/missing.
+
+
+
+ Added ability to run without abbreviations if program is run on a write-protected drive.
+
+
+
+ Added command-line switch (/X) to stop any attempts of reading or creating an abbreviation file (useful on a write-protected drive, like a network drive).
+
+
+
+
+
+Revision 2.85 - Completed September 1, 1996
+
+
Now recognizes the MWTPATH environment variable which specifies the location of the MWT_ABBR.DAT file
+
+
+
+
+Revision 2.87 - Completed January 1, 1997
+
+
+ Updated the help file to reflect the latest Windows version of the program.
+
+
+
+
+
+Revision 3.0 - Windows 3.x version Completed June 10, 1996 (Visual Basic 3.0)
+
+
+ New Windows interface.
+
+
+
+ Now able to modify elemental values stored in the MWT_ELEM.DAT file.
+
+
+
+ Added editing and saving of Abbreviations and Elemental values during program operation.
+
+
+
+ Added ability to save current options as defaults.
+
+
+
+ Added ability to Copy and Paste information to/from other Windows programs.
+
+
+
+ Formula length is now unlimited -- formulas can even contain all 103 elements.
+
+
+
+ Added ability to print results.
+
+
+
+
+
+Revision 3.1 - Completed June 28, 1996
+
+
Added ability to change the font used to display formulas and calculated results.
+
+
+
+ Added Mole/Mass Converter
+
+
+
+ Added Formula Finder
+
+
+
+ Added full hypertext help
+
+
+
+
+
+Revision 3.2 - Completed January 1, 1997
+
+
+ Now allows use of abbreviations as custom elements in formula finder.
+
+
+
+ For Percent Solver, added display of differences between target percentages and obtained percentages.
+
+
+
+ Changed comment delimiter to be a semicolon in the MWTWIN.INI file and the .DAT files.
+
+
+
+ Added detection of a mouse click to stop the percent solver and formula finder.
+
+
+
+ Updated help file with MWT Dos version information.
+
+
+
+ Corrected bug in display of standard deviation values to display the correct number of decimal places.
+
+
+
+ Improved editing of abbreviations and elemental values.
+
+
+
+ Improved formula finder interface.
+
+
+
+
+
+Revision 4.0 - Windows 95 version Completed August 25, 1997 (Visual Basic 5.0)
+
+
32 bit Windows 95 code
+
+
+ Now allows user to turn off confirmation of exiting the program.
+
+
+
+ Added possibility of using exact isotopic weights, in addition to average elemental weights. Useful for mass spectrometry.
+
+
+
+ Added context sensitive tool tips to many of the program’s controls and added a setting in the help menu to turn them on or off (the settings can be saved in the MWTWIN.INI file)
+
+
+
+ Redesigned program help to Windows 95 standards.
+
+
+
+ Improved dialog box displayed when changing items in grids to include OK, Cancel, and Reset buttons.
+
+
+
+ Fixed bug that had smart case mode and exact case mode switched around in the Calculate function.
+
+
+
+ Changed all forms and controls to the standard VB 5.0 3-D style.
+
+
+
+ Changed program icon and made the edges transparent.
+
+
+
+ Updated help file with MWT Dos version information.
+
+
+
+ Updated my E-mail and WWW addresses to UNC.
+
+
+
+
+
+Revision 4.1 - Completed September 2, 1997
+
+
+ Added feature to expand abbreviations to their elemental equivalents.
+
+
+
+ Fixed bug that wrongly calculated weights and uncertainties for weighting of compounds when abbreviations were involved (i.e. use of brackets, eg. [.1Bpy]).
+
+
+
+ Fixed bug that did not take abbreviations or isotopes into account when hydrates (dashes) were used (eg. Fe-3Bpy or Fe-6^13CH3)
+
+
+
+ Enabled error handlers to catch overflow values in various procedures.
+
+
+
+
+
+Revision 4.2 - Completed September 7, 1997
+
+
+ Added feature to convert formulas into their empirical formulas, displaying C first, then H, then the remaining elements alphabetically.
+
+
+
+ Made the Expand Abbreviations and Convert to Empirical Formula commands instantaneous if exit program confirmation is turned off in Exit Program Options under the Options menu.
+
+
+
+
+
+Revision 4.3 - Completed March 10, 1998
+
+
+ Added feature to allow isotopes to contain decimal values, for example: ^13.02C
+
+
+
+ Added an indicator of the percent of calculations completed in the formula finder.
+
+
+
+ Added back in the mathematical expression calculator that was previously present in the MWT for Dos version (see above).
+
+
+
+ Fixed bug that would not allow single letter elements to be entered in the custom elements boxes of the formula finder routine.
+
+
+
+ Modified error messages in the formula finder routine to be more clear.
+
+
+
+
+
+
Revision 4.31 - Completed March 22, 1998
+
+
+ Fixed error with re-creation of the mwt_elem.dat file if it was deleted from the current directory.
+
+
+
+ Made minor updates to average and isotopic mass values for elements in accordance with the 1993 IUPAC standards.
+
+
+
+ Minor changes to help file.
+
+
+
+
+
+
+Revision 4.4 - Completed June 15, 1998
+
+
+ Added parts per million (ppm) mode to formula finder weight tolerance box.
+
+
+
+ Added tooltip for the copy button in the formula finder.
+
+
+
+ Added Smart Hydrogen atom feature to the formula finder, limiting the number of hydrogens in found compounds to a realistic number (allows CH5 but not CH6 or CH25, allows NH4 but not NH5, allows H3O but not H4O).
+
+
+
+ Added option to convert found formulas in formula finder to empirical formulas and chemically alphabetize the results, giving a more logical ordering of found formulas (but slowing find process); sort can be stopped by any keypress or mouse click.
+
+
+
+ Added option to save current values and formulas so they are automatically loaded the next time the program is started. The values can also be autosaved on exit of the program.
+
+
+
+
+ Made format of the difference in mass result (dm=) in formula finder dependent on the standard deviation mode: if "Short" or "Decimal" then dm is displayed in standard notation (0.00314); if "Scientific" then dm is displayed in scientific notation; if "Off" then dm is not displayed.
+
+
+
+ Modified the tab order of objects in the various windows to be more logical.
+
+
+
+ Fixed copy commands to insert a new line character properly and to insert tabs instead of spaces between columns.
+
+
+
+ Fixed a major bug with the /X command line feature that did not load elemental information (symbols and weights) upon startup, thus making the program useless. Amazingly no one reported this to me, so I can only assume no one uses this feature.
+
+
+
+ Removed all command line switches except /X and /? since the AutoSave and AutoLoad features of the options, formulas, and values eliminates their usefulness.
+
+
+
+ Updated the MWT_ELEM.DAT and program elements defaults to include the average atomic weights and uncertainties specified by the 1997 IUPAC standards.
+
+
+
+ Changed the "Possibly Incorrect Uncertainty" caution message (for elemental uncertainties) to display only if uncertainties are different from those built into the program code by 10 times instead of by just 20%
+
+
+
+ Changed the "Possibly Incorrect Elemental Weight" caution message to display only if different from those built into the program code by 20% instead of just 10%.
+
+
+
+ Fixed status line from displaying a yellow colored "Ready" after editing elements or abbreviations when a caution statement about an abbreviation in one of the formulas was displayed and replaced.
+
+
+
+ Numerous updates to Mwtwin.Hlp file
+
+
+
+ Fixed Edit Elements table and program internal code to handle molecular weights with 16 digit precision rather than just 8.
+
+
+
+ Made all displayed value formats follow the Standard Deviation Mode in that they are displayed in standard notation, unless Scientific mode is chosen, in which case they are shown in exponential notation. This applies to dm results in the Formula Finder, values in the Mole/Mass Converter, results in the Calculator, and percent solver results.
+
+
+
+
+
+
+Revision 4.5 - Completed July 19, 1998
+
+
+ Added ability of abbreviations to contain isotope references. For example, ^2.014H is used to add Deuterium to the abbreviations list, signifying Hydrogen weighing exactly 2.014 Daltons. Note: the uncertainties for isotopes used in abbreviations will be equivalent to those of the elements used in the abbreviation; for example .00007 for Hydrogen, even if ^2.014H is given as the abbreviation.
+
+
+
+ Added caution statement for TI being tritium-iodine versus Ti being titanium (although tritium is not included in the abbreviations list, users may add it as ^3.01605H).
+
+
+
+ Added creation of backup files for MWT_ABBR.DAT and MWT_ELEM.DAT each time the files are changed, saving the old version as MWT_ABBR.BAK and MWT_ELEM.DAT
+
+
+
+ Added display of percent completed information when sorting results in the Formula Finder.
+
+
+
+ Changed default deuterium abbreviation to be ^2.014H (rather than simply H2).
+
+
+
+ Improved speed of sorting algorithm in Formula Finder (now using a Shell sort rather than a recursive QuickSort, which generates too much overhead for large data sets due to the recursion).
+
+
+
+ Changed code in the Standard Deviation Display subroutine to better handle very large numbers without giving an overflow error.
+
+
+
+ Added Geocities.Com web address and e-mail address throughout help file and program.
+
+
+
+
+
+Revision 4.6 - Completed January 23, 1999
+
+
+ Added option of entering decimal elemental amounts as X1.5 in addition to [1.5X]. For example, Fe1.5O2.25 instead of [1.5Fe][2.25O]
+
+
+
+ Added option of entering decimal numbers after dashes. For example C6H6-.5H2O instead of C6H6-[.5H2O]
+
+
+
+ Added functionality to parse a text file containing formulas and create an output file with the molecular weight of each formula.
+
+
+
+ Added /F:filename switch that can be used when starting MWTWIN to specify a file to parse automatically, calculating molecular weights for each formula, and writing to filename.out
+
+
+
+ Fixed bug in "expand to empirical formula" feature that skipped elements with an occurrence of less than 1 in a formula (for example, [.7CH3] would expand to simply H2.1 rather than C.7H2.1
+
+
+
+ Fixed bug in formula parser that wasn't warning user of decimal numbers with leading zeroes after carets for isotopes, i.e. ^0.5H is not allowed while ^.5H is (though it is unrealistic and the program warns of this). --- This change no longer matters since I've removed the requirement that decimal numbers cannot start with a 0 as in 0.5
+
+
+
+ Fixed bug in loading saved formulas on program startup that caused a program error if blank formulas were present before the final formula.
+
+
+
+ Further improved speed of sorting algorithm in formula finder by converting each line to easily sorted code, sorting the code, and arranging the original lines based on how the coded lines sorted.
+
+
+
+ Removed requirement that decimal numbers be in the format .5 instead of 0.5 Thus, decimal numbers can now be entered as 0.5 or .5
+
+
+
+ Removed requirement that numbers following parentheses be integers and not decimal numbers. Thus, (CH3)2.5 is now allowed.
+
+
+
+
+
+Revision 4.61 - Completed February 1, 1999
+
+
+ Added new code to correctly recognize the element dysprosium (Dy) when deuterium (D) is defined as an abbreviation. Previously, the program would match D as deuterium and Y as yttrium, with the only possible fix being to delete the deuterium abbreviation. A special-case work around has been added.
+
+
+
+ Added a caution statement concerning Dy versus DY (dysprosium vs. deuterium-yttrium).
+
+
+
+
+
+Revision 4.62 - Completed February 8, 1999
+
+
+ Added a warning dialog that appears when the Formula Finder is started, but the element weight mode is using average weights. The user can stay in average weight mode or switch to isotopic weight mode. A checkbox is also included to avoid seeing the warning dialog in the future.
+
+
+
+ Added the option of using Nominal Integer Weights for elements, useful for looking for matches to low resolution mass spectrometry data via the formula finder.
+
+
+
+ Fixed bug that incorrectly loaded the saved formulas on program start when the view mode was single view.
+
+
+
+ Completely reworked how the program parses formulas, looking for elements and abbreviations. Now, discrepancies like the Dy vs. DY problem corrected in revision 4.61 will not occur, even if the user creates a new, potentially ambiguous abbreviation. For example, if the user assigns CH3 to the abbreviation A, then types ac in a formula, the program will parse this as Ac, the element actinium. On the other hand, if they type AC, it will correctly parse this as CH3C, while previous versions would not have.
+
+
+
+ Reworked a large majority of the code to remove nondescriptive variable names like temp, temp$, etc. Also consolidated some of the repetitive sections into single functions, thereby reducing the overall program size.
+
+
+
+
+
+Revision 4.65 - Completed February 16, 1999
+
+
+ Added ability to sort the elements by atomic weight, elemental symbol, or weight uncertainty when editing elements.
+
+
+
+ Abbreviations can now contain parentheses, for example CH(CH3)3
+
+
+
+ Abbreviations can also now contain anything a regular formula might contain, except for other abbreviations. Thus, decimal numbers can now be used, plus parentheses, dashes, brackets, etc. Furthermore, abbreviation formulas can be entered lowercase when editing abbreviations, and the program will properly capitalize the abbreviations.
+
+
+
+ Added a more robust and faster Formula Finder routine, called "Thorough Search". This routine is recursion based, and no longer requires the user to enter maximum and minimum values for the number of each element present. It is faster than the older, "Bounded Search" routine for finding all matches to a given target weight and tolerance. However, I've left the Bounded Search method available in case the user wishes to search for a high molecular weight compound (over approx. 1000 Da) with many possible elements (over approximately four), in which case the user can enter a large minimum element occurrence number to speed up the search.
+
+
+
+ When the bounded search method is activated, changing the Target Molecular Weight changes the upper bounds on the checked elements. For example, if a target of 100 is entered, the upper bound on carbon will become 100/12=9. Further, if Smart Hydrogen checking is on, the upper bound on H's is only 53 rather than 103 (granted, 53 is still quite large, but is much more reasonable than 103).
+
+
+
+ When matching Percent Compositions in the Formula Finder routine using the Thorough Search mode, the user no longer must enter maximum and minimum values for the number of each element present, but they now do have to enter a maximum molecular weight of found compounds.
+
+
+
+ Reworked more of the code, consolidating more functions and adding a recursive aspect to the formula parsing routine so it can now handle an infinite number of levels of embedded parentheses (within available memory, of course).
+
+
+
+
+Revision 5.0 - Completed May 1, 1999
+
+
+ Code recompiled using Visual Basic 6.0 for Windows 95/98/NT.
+
+
+
+ Formulas are now displayed using RichText Boxes, allowing subscripts, superscripts, and colors to be displayed. I tried doing this with VB 5, but the program crashed continually. Thankfully, the RichTx32.dll that comes with VB 6 is stable.
+
+
+
+ Drag and drop of both formulas and results in the Formula Finder is now possible, thanks to the built-in functionality of the Rich Text Boxes. Simply highlight text to copy, then drag and drop it to the desired location (either in MwtWin or in another application, like Microsoft Word).
+
+
+
+ Added Copy Formula as RTF to allow a formula to be copied as its rich text format code. This allows the formula to be pasted into an RTF aware program (like Microsoft Word) and contain the appropriate super and subscripts. This can also be accomplished by dragging the formula from VB and dropping into Word.
+
+
+
+ When entering abbreviations in the Edit Abbreviations dialog, they are formatted with super and subscripts as the formula is typed.
+
+
+
+ When loading the Change Formula Font dialog, the progress of loading fonts is now displayed in the status bar.
+
+
+
+
+Revision 5.01 - Completed May 10, 1999
+
+
+ At a user's request, I have added the ability to enter a charge for each element and abbreviation, allowing the overall charge of a formula to be found. This is not useful for compounds with double bonds or rings, since bond order cannot be determined from the empirical formula. However, it is useful in situations where one knows the exact charge of each constituent of a compound, for example in inorganic clusters
+
+
+
+ Compute Charge has been added to the options menu to display the overall charge of formulas. Hydrogen is assumed to be +1, unless preceded by a non-halogen such as carbon or a metal.
+
+
+
+ More Formula Finder changes: 1) the charge can now be computed and displayed; 2) this also allows the mass to charge (m/z) ratio to be computed and displayed; 3) the results of a formula finder search can now be sorted by 1 of 4 criteria: formula, charge, molecular weight, and m/z ratio. Furthermore, the width of the Formula Finder window can now be widened to better display the results.
+
+
+
+ The font size of the formulas can now be changed using the Change Formula Font dialog. This font size also affects the results shown the in the formula finder.
+
+
+
+ When editing elemental values, uncertainties, and charges, clicking one of the buttons no longer automatically closes the edit box, allowing one to immediately see the new values that appear if any of the buttons are pushed.
+
+
+
+
+
Revision 5.02 - Completed May 12, 1999
+
+
+ Includes improvements to the Charge computation algorithm, as detailed in the charge section.
+
+
+
+
+
Revision 5.03 - Completed May 17, 1999
+
+
+ Updated the Calculator feature to use a rich text box, thus allowing powers like 2^2 to be displayed as superscripts.
+
+
+
Added more Charge and mass/charge ratio options in the formula finder, grouping the checkboxes together in an options dialog. The displayed compounds can now be limited to a specific charge range. Users can also search for compounds with a specific m/z (and thus a range of weights and charges).
+
+
+
Fixed program bug that prevented program from calculating formula weights at program start if in Single View mode.
+
+
+
Fixed program bug that incorrectly displayed the current formula at program start if in Single View mode.
+
+
+
Consolidated more code by combining redundant sections into shared subroutines.
+
+
+
+
+
Revision 5.04 - Completed May 18, 1999
+
+
+ Improved the speed of m/z searching in the formula finder when using the bounded search mode.
+
+
+
+
+
Revision 5.05 - Completed June 6, 1999
+
+
+ Added the option of not automatically adjusting the Min and Max values for elements in the Formula Finder when performing a bounded search (in the Formula Finder options box).
+
+
+
Corrected a major bug that rendered the bounded search in the Formula Finder inoperable if not calculating charges and m/z ratios of formulas.
+
+
+
+
+
Revision 5.06 - Completed July 10, 1999
+
+
+ Upgraded components to Service Pack 3 for Visual Basic 6.0
+
+
+
Moved the Sort Mode and Search Mode combo boxes from the formula finder main form to the formula finder options form.
+
+
+
Added option to quickly change the element mode on the program’s main form, called Quick Switch. These changes do not write the new elemental values to disk until exiting the program. When using the quick elemental mode switch, any user defined elemental values are lost.
+
+
+
Fixed bug that failed to color the status line yellow if a caution statement was displayed at program start.
+
+
+
+
+
Revision 5.07 - Completed July 14, 1999
+
+
Fixed bug that failed to update the Quick Switch Element mode when the Formula Finder finder weight mode warning window changed the weight mode for the user.
+
+
+
Fixed bug in Formula Finder that caused the number and underscore of custom elements to be inadvertently subscripted when displayed in the results box.
+
+
+
Fixed bug that failed to fill in element or abbreviation information the first time Edit Abbreviations or Edit Elements was chosen on the File menu (they filled in the second time).
+
+
+
Changed the Chlorine and Sulfur check boxes in the formula finder to custom element boxes to allow users the possibility of six custom elements or abbreviations.
+
+
+
Moved many of the program options from the Options menu to a preferences dialog box, making it easier to set multiple options at once. Added an option to make the Formula Finder warning mode screen reappear if user had earlier checked the box to make it never appear again.
+
+
+
Added a number of new keyboard shortcuts for menu items; all shortcuts are displayed in the menus.
+
+
+
Added current build of program to the intro screen and about box. This allows me to differentiate between different builds of a current version. Starting at build 35 was an arbitrary choice, made by counting 34 released versions before the current one. There have surely been several 100 builds of the program on my own computer, however.
+
+
+
+
+
Revision 5.07b - Completed July 18, 1999
+
+
Rolled back to Service Pack 2 (SP2) of Visual Basic for compiling the program due to errors arising when users tried to install the program on Windows 95 computers (specifically, received error with Comdlg32.ocx). It seems that VB6 SP3 is not compatible with the earlier (original?) version of Windows 95, while it works fine on computers with Windows 95b (plus Win 98/NT).
+
+
+
+
+
Revision 5.08 - Completed September 16, 1999
+
+
Re-updated program to Service Pack 3 (SP3) since the Comdlg32.ocx error did not appear to be widespread.
+
+
+
Updated web addresses to http://www.geocities.com/CapeCanaveral/Lab/9548/ from http://www.geocities.com/CapeCanaveral/Lab/9317/ due to a snafu at Geocities that erased my web pages, forcing me to create a new account (entirely their fault).
+
+
+
Also updated e-mail addresses to AlchemistMatt@Yahoo.com from AlchemistMatt@Geocities.com due to the merger of Geocities with Yahoo.
+
+
+
Made permissible the use of the plus sign (+) in abbreviations (at the request of a user). For example, an abbreviation called H+ or Na+ can now be entered, both in the main window and in the formula finder.
+
+
+
+
+
Revision 5.09 - Completed October 10, 1999
+
+
By user request, made the curly brackets, { and }, behave as parentheses in formulas. In addition, added the option of allowing regular brackets, [ and ], to also act as parentheses. When regular brackets are treated as parentheses, all Percent Solver options are disabled. Toggle the bracket mode in the Program Preferences Window.
+
+
+
Made regular and curly brackets available in the calculator. There, they behave as parentheses regardless of the bracket mode setting in the Program Preferences Window.
+
+
+
Fixed bug in calculator that superscripted the plus sign and subscripted numbers following the plus sign
+
+
+
Fixed bug that failed to set the standard deviation of a formula to zero when an error is found in the formula.
+
+
+
Since the plus sign was made an allowable part of an abbreviation in version 5.08, I added the underscore (_) to also be allowable, so users can add anions to the abbreviations list.
+
+
+
Fixed bug that failed to correctly set the "Never Show the Formula Finder Weight Mode Warning Dialog" value correctly when the user requested to "Stop Showing the Warning Dialog" option.
+
+
+
Since I was finding it annoying, I made the behavior in the Formula Finder of selecting an entire text field when clicking on it be turned off by default; it may be turned on in the Formula Finder options window.
+
+
+
Added code to correctly identify invalid Ctrl key combinations (like Ctrl+B, Ctrl+D, etc.) and notify the user if pressed.
+
+
+
+
+
Revision 5.10 - Completed December 19, 1999
+
+
Fixed bug that failed to recognize the last abbreviation (alphabetically) in the extended abbreviations list; Val is the default final extended abbreviation, thus it wasn’t being correctly identified.
+
+
+
Fixed bug that failed to update the Quick Switch Element Mode value on program load when the element mode was not Average weights.
+
+
+
Changed the behavior of the Copy Current Molecular weight command to just copy the weight value when standard deviation mode is set to off
+
+
+
Assigned Ctrl+W to be the shortcut for Copying the current molecular weight.
+
+
+
+
+
Revision 5.11 - Completed March 5, 2000
+
+
Added a window for performing calculations for open tubular and packed fused silica capillaries used in capillary liquid chromatography.
+
+
+
Also added the ability to perform Mass Rate Calculations, useful for determining amount of sample eluting from an electrospray needle in ESI-MS.
+
+
+
Fixed minor bugs in the Mole/Mass Converter, including failure to display numbers below 1E-6 when short Standard Deviation mode was on.
+
+
+
In addition to informing the user when the program’s .INI or .DAT files are being re-written due to corruption, I now list the name that the corrupted file has been renamed to.
+
+
+
Just for fun, added an "Always on Top" feature to the program, allowing the user to choose to have the main program windows stay on top of other windows.
+
+
+
Converted the help file to HTML help, since this allows me to display sub and superscripts, along with conforming to Microsoft's new help file standards.
+
+
+
+
+
Revision 5.12 - Completed June 27, 2000
+
+
At a user's request, added the option of Automatically Copying the current formula's molecular weight to the clipboard after each calculation.
+
+
+
In the Capillary Chromatography Calculations window, added the option to determine theoretically the extent to which band broadening will occur under various capillary conditions and dimensions.
+
+
+
+
+
Revision 5.2 - Completed September 28, 2000
+
+
To tell the truth, I can't recall what changes I made to warrant changing from 5.12 to 5.2 Most likely, I made some minor changes to the Capillary Chromatography Calculation window, including changing the name to Capillary Flow and Mass Rate Calculations.
+
+
+
+
+
Revision 5.21 - Completed April 3, 2001
+
+
Changed the constant used to compute Volumetric Flow Rate and Linear Velocity in the Capillary Flow and Mass Rate Calculations window to more accurately predict those values. Specifically, changed the constant form 180 to 270 in the following equation:
+ Vol Flow Rate = [Pressure * (diameter of packing)2 * (epsilon)2 * (capillary radius)2 * Pi] / [270 * viscosity * (column length) * (1 - epsilon)2] where epsilon is the interparticle porosity, typically 0.4
+
+
+
In addition, changed the name of the interparticle porosity to epsilon rather than eta, which I had erroneously labeled it as previously.
+
+
+
+
+
Revision 5.22 - Completed April 9, 2001
+
+
Changed a constant used to compute Volumetric Flow Rate and Linear Velocity in the Capillary Flow and Mass Rate Calculations window back to 180.
+
+
+
Added ability to view the equations used to compute the flow values.
+
+
+
+
+
Revision 5.23 - Completed June 18, 2001
+
+
Fixed a bug introduced in version 5.22 that caused the linear velocity value for open capillaries to be incorrect.
+
+
+
+
+
Revision 6.02 - Completed October 2, 2001
+
+
Added a 3 letter to 1 letter amino acid abbreviation conversion utility. The program still requires that peptide sequences be entered using three letter codes for molecular weight determination, but this converter makes it easier to copy and paste values from other peptide handling programs or the web. In addition to the standard 20 amino acids, the converter also recognizes U for Gla (gamma-Carboxyglutamtate).
+
+
+
Added numerous new Amino Acid abbreviations (Gla, Hse, Hyl, Hyp, Orn, and Sar). Only Gla has a corresponding one letter abbreviation, U, since I could not find any literature-wide agreement for one letter abbreviations for the other new amino acids.
+
+
+
Added ability to display more than 7 formulas simultaneously. The maximum is dependent upon your screen resolution. For example, the maximum for 1024x768 is 12 formulas. The total number to show can be set to a value lower than the maximum in the preferences window.
+
+
+
Added support for other (international) languages. The program can now be customized to support any Roman or Cyrillic character based language (German, French, Spanish, Italian, Russian) by creating a Lang_NewLanguage.ini file and loading the file by choosing Language under the Options menu. All text based phrases in the program can be customized, including ToolTip text and error messages.
+
+
+
Related to international language support, changed program to recognize if commas are set to represent decimal points on the user's computer (Regional Options under the Windows Control Panel). If so, replaces all period (.) decimal points with comma (,) decimal points.
+
+
+
Improved usability of the mole/mass converter by adding option to simply enter the mass of the compound. Additionally, provided option for mg/mL type concentrations rather than simply molarities.
+
+
+
Added numerous new units to the Mole/Mass converter, including micromoles, nmol, pmol, fmol, amol, & micrograms.
+
+
+
Added a new option to the Capillary Flow calculator to use a given Dead Time to compute the Volumetric Flow Rate that would give that dead time, modifying the Back Pressure appropriately to give the computed Volumetric Flow Rate.
+
+
+
Modified program to be dual-monitor aware. The program will now properly center itself on the primary monitor.
+
+
+
Fixed behavior of the Percent Solver to properly display the results rather than the target values when completing a computation. The target values are redisplayed when the user re-enters the set table.
+
+
+
Fixed the math calculator to properly handle parentheses (there were some weird bugs going on). Now using a recursive computation algorithm that allows an infinite level of embedded parentheses. Also, removed requirement that the multiplication operator (*) be included between numbers and parentheses, eg. 3(4+2)/(3+2)+(2/3)6 = 7.6 Finally, can now properly raise value of parentheses to a power, eg. 3*(4+2)^2 = 108
+
+
+
Shuffled around a few of the menus, including moving the Formula Finder, the converters, and the calculators to a new menu, the Tools menu.
+
+
+
Code Changes: Removed redundant code in the Capillary Flow Calculator. Changed application load and unload behavior to avoid the use of the End statement. Added code to prevent any sub forms from being unloaded from memory until program is exited completely.
+
+
+
Extensively edited the help file to bring up-to-date with the latest features and new locations of numerous program items.
+
+
+
Bumped up the version number to 6.0 owing to all of the new improvements. Also, using a version of 6.x, the program version now matches the version of Visual Basic used.
+
+
+
+
Revision 6.03 - Completed October 3, 2001
+
+
Added ability to cut, copy, or paste values from any of the program textboxes. I perform error checking to prevent invalid characters, and was inadvertently blocking Ctrl+X, Ctrl+C, and Ctrl+V
+
+
+
Added units of Bar and Torr (mm Hg) in pressure box of the Capillary Flow Calculator
+
+
+
Fixed bug in Capillary Flow Calculator that prevented Find Back Pressure and Find Inner Diameter from working
+
+
+
Fixed bug in Capillary Flow Calculator that delayed updating all results after clearing an input value to 0 then typing a valid number again.
+
+
+
+
+
Revision 6.04 - Completed October 11, 2001
+
+
Expanded the functionality of the Mole/Mass converter window to include a Dilution Calculator to handle volume-volume dilution calculations. Note that by setting the final concentration larger than the initial concentration this can also be used to perform calculations involving concentrating a solute by evaporation or sublimation.
+
+
+
Now coloring textboxes of computed quantities yellow to indicate they are a computed result and cannot be changed.
+
+
+
Fixed bug in cut/copy/paste from textboxes that prevented copying computed results in the capillary flow calculator.
+
+
+
Added keyboard shortcut of Ctrl+A to select all of the text (or numbers) in a text box. Does not apply to formulas in the main window since Ctrl+A means to expand abbreviations.
+
+
Added a simple undo feature to restore the currently selected formula or text box to the value it had when first entered. Once you have moved to a new control, the value of the old control cannot be restored. I will probably expand the undo system in the future.
+
+
+
Revision 6.05 - Completed October 23, 2001
+
+
Fixed Major bug in Formula Finder that prevented users from changing the Target Percent values for Percent Composition Searching. In addition, the Min and Max search values for bounded searches were also broken. I added a new textbox validation routine in version 6.04 and failed to correctly update the functions for the Formula Finder form.
+
+
+
Moved around a few of the controls on the Mole/Mass/Dilution form.
+
+
+
Updated the Lang_Portuguese.Ini and Lang_Spanish.Ini files.
+
+
+
+
Revision 6.06 - Completed November 11, 2001
+
+
Fixed bug with Mole/Mass/Dilution calculator that generated a program error if the window was minimized then restored (unminimized).
+
+
+
Restored behavior of the Mole/Mass/Dilution calculator window to be a fixed size.
+
+
+
+
Revision 6.10 - Completed January 25, 2002
+
+
Added Peptide Sequence Fragmentation Modelling tool, including ability to plot the theoretical mass spectrum of the fragmentation pattern for a given peptide sequence.
+
+
+
The new Fragmentation Modelling Tool also includes ability to paste actual mass spectral data (mass/intensity pairs) so that the predicted ions can be matched to the raw data. The raw data may also be plotted with the predicted fragment ions.
+
+
+
Added option to enter column diameters in inches in the Capillary Flow and Mass Rate Calculations Window.
+
+
+
Modified Formula Finder results list to grow/shrink vertically in addition to horizontally when the window is resized.
+
+
+
Modified Amino Acid Notation Converter to properly handle H at the beginning and OH at the end in the three-letter based sequence input box. In addition, modified to properly reposition and resize controls when window resized.
+
+
+
Changed Ctrl+A to select entire formula since this is the expected behavior for Ctrl+A in Windows applications and Abbreviation Expansion is most likely rarely used.
+
+
+
Fixed bug in main window involving the order of tabbing between controls.
+
+
+
Fixed bug that failed to sum up standard deviation values for all portions of a formula when using parentheses or abbreviations.
+
+
+
Fixed bug that failed to re-calculate the molecular weight or percent composition of formulas in Single View when the formula is modified using Cut/Copy/Paste via Ctrl+X/Ctrl+C/Ctrl+V.
+
+
+
Fixed bug that caused the Percent Solver to give an answer slightly off (less than 0.001%) from the correct answer when the standard deviation mode was turned on.
+
+
+
Major update to the Lang_Spanish.Ini file with corrections contributed by Perez de la Hoz.
+
+
+
+
+
Revision 6.11 - Completed March 9, 2002
+
+
Fixed bug that failed to save new amino acid abbreviations if the charge state was not specified
+
+
+
Updated Lang_Russian.Ini file (contributed by Michael I. Yahkind)
+
+
+
+
Revision 6.12 - Completed March 10, 2002
+
+
Removed restriction preventing a formula from starting with a number. Now, starting a formula with a number will multiply the following elements (up to the first dash) by the number. Thus, the following are all equivalent ways of entering a formula with 10 fluorine atoms: F10, (F)10, [10F], and 10F
+
+
+
+
Revision 6.13 - Completed May 7, 2002
+
+
Added ability to edit the one letter abbreviations of amino acids
+
+
+
Fixed bug in 3 to 1 letter amino acid notation converter that failed to mark amino acid abbreviations with no equivalent code with an X when the amino acid existed but no 1 letter abbreviation was defined.
+
+
+
Added ability to resize the abbreviation editing window, accompanied by automatic column width expansion.
+
+
+
Changed help ID numbers to show the correct help screen when pressing F1 in the amino acid notation converter window.
+
+
+
Updated Lang_Portuguese.Ini file (contributed by Alexandre R Soares)
+
+
+
Revision 6.14 - Completed May 9, 2002
+
+
Fixed bug in abbreviation editor that failed to properly sort the 1 letter abbreviations when adding or removing amino acid abbreviations.
+
+
+
+
Revision 6.16 - Completed June 8, 2002
+
+
Added option to run the Formula Finder in batch analysis mode, reading search values from a file and writing the results to an output file. See the Batch Analysis help page for more information.
+
+
Fixed bug in formula finder that re-initialized all of the custom elements to the phrase "# or element or abbrev" after leaving and returning to the form.
+
+
+
+
Revision 6.17 - Completed July 1, 2002
+
+
Added ability to predict the Isotopic Distribution for a given formula, predicting the masses and relative abundances of all possible isotopes. Includes ability to handle explicitly specified elements as part of the formula, in addition to graphing the results.
+
+
+
+
Revision 6.18 - Completed July 2, 2002
+
+
Turned on the error checking in the Isotopic Distribution module that I had forgotten to turn back on.
+
Updated the help files to discuss Isotopic Distribution.
+
Now displaying the formula with subscripts and superscripts on the Isotopic Distribution window.
+
Updated the Isotopic Distribution results display to be more cleanly formatted.
+
+
+
Revision 6.19 - Completed August 12, 2002
+
+
Added ability to use custom amino acids in the Peptide Sequence Fragmentation Modeller.
+
Added the ability to save and load capillary flow settings to/from text files.
+
Added the option to automatically show one of the program modules at program start (instead of the default program window). Clicking the X on the module window exits the entire program. Choosing Close (from a menu or a button) returns to the main program screen.
+
Changed default diffusion coefficient in the Capillary Flow and Mass Rate Calculations module to be 5E-6. Also, changed tooltip to state that typical coefficient for small organics is 1E-5 rather than 1E-6.
+
Fixed bug in amino acid notation convertor that caused the program to crash if the 3 letter sequence was copied to the list of formulas, but the main window was hidden since Hide Inactive Program windows was turned on.
+
Re-worked the algorithms used to parse and store the user-defined abbreviations and amino acids. If an invalid (or duplicate) abbreviation is present, the user will now be able to see it using Edit | Abbreviations and correct or remove the abbreviation.
+
+
+
Revision 6.20 - Completed October 15, 2002
+
+
Modified form layouts to behave properly using the default Windows XP theme (which uses wider borders than previous themes)
+
Minor updates to the help files, including updating contact information.
+
+
+
Revision 6.21 - Completed November 17, 2002
+
+
Added custom language captions for the results box in the Isotopic Distribution window.
+
Added a new language: Catalan (aka Català)
+
+
+
Revision 6.22 - Completed November 29, 2002
+
+
Modified the Set X Range and Set Y Range functions on the Plot window to allow users to set the view range to more than 110% of the current data range. The new allowable limit is up to 1000 times the data range.
+
+
+
Revision 6.25 - Beta 12 completed June 16, 2003
+
+
Although the program interface looks very similar, all of the primary computation routines have been moved to an ActiveX DLL file. Doing this allowed me to greatly clean up a lot of the legacy code present in the software.
+
Additional units have been added to many of the parameters in the Capillary Flow Calculations window.
+
Additional units have been added to some of the parametesr in the Mole/Mass Converter window.
+
Abbreviations may now contain other abbreviations. For example, if Ph = C6H5 then you could define Cb = PhCl. This also allows D to be used inside other abbreviations.
+
The ability to right-click and see the Cut/Copy/Paste etc. options has been added to numerous text boxes throughout the program.
+
The Peptide Sequence and Fragmentation module has been greatly expanded:
+
+
You can now define modification symbols to allow for modified amino acids.
+
You can now choose the functional group present at the N and C terminus.
+
Phosphorylation is now an allowable neutral loss.
+
The fragmentation mass listing now excludes those ions that could not possibly form, based on location in the peptide and whether or not a specific residue can lose water, ammonia, or the phosphate group.
+
The mass of the peptide, including any modifications, is now displayed on the form, along with the equivalent mass of the M+H mass.
+
You can convert between M+H and [M+nH]n+ where n is between 1 and 10.
+
The graphing component has been updated to a professional component. The graph is now much faster and much more powerful, allowing for custom annotations and numerous other features, including the ability to save and load graphs (including all colors, styles, and annotations).
+
The theoretical fragmentation spectrum can be included on the graph, and any matches with the real data can be included as annotations on the graph.
+
The peptide sequence and fragmentation module (and the accompanying graph) can correctly read .Dta files (common text-based MS/MS file format).
+
+
The Batch Analysis feature has been greatly expanded. Numerous new commands are now present, including the ability to change the standard deviation mode, convert compounds to empirical formulas, and convert amino acid sequences to/from 1 and 3 letter notation.
+
You can now subtract out elements from a formula using the > symbol:
+
+
This feature was added to allow one to quickly find the mass or empirical formula of a compound that has lost one or more elements due to a reaction or a neutral loss in mass spectrometry.
+
For example: C6H5Cl>HCl means C6H5Cl minus HCl, having a mass equivalent to C6H4
+
The elements to the right of the > symbol must all be present in the elements to the left of the > symbol (see Element Subtraction for more information).
+
+
Changed the /X command line switch to mean "do not write any settings (abbreviations, elements, values) to disk"
+
Added a new command line switch, /Z, meaning "do not read or write any settings to/from disk"
+
+
+
Revision 6.26 - Completed August 3, 2003
+
+
Updated the Isotopic Distribution module to use the new graphing component described above for the Peptide Sequence Fragmentation module
+
Added the ability to paste a list of ions to compare with the predicted isotopic distribution.
+
Added error handling routines to the Formula Finder code to reduce the possibility of abrupt program crashes.
+
+
+
Revision 6.27 - Completed October 10, 2003
+
+
Fixed bug on the Peptide Sequence and Fragmentation Module that used 1.00000 for the mass of hydrogen rather than 1.00782 when converting between M+H and [M+nH]n+
+
+
+
Revision 6.28 - Completed October 30, 2003
+
+
Added option to the graph component to define custom tick starting values and intervals. Use Edit->Zoom Range.
+
+
+
Revision 6.29 - Completed November 23, 2003
+
+
Fixed bug involving call to Peptide.SetModificationSymbol in MwtWinDll.Dll that caused the program to crash if the user had the Windows decimal point set to a comma rather than a period, as is common in many countries outside the United States and the UK.
+
+
+
Revision 6.30 - Completed December 3, 2003
+
+
Modified the graph control to allow changing the border color and border style (3D or plain)
+
+
+
Revision 6.31 - Completed January 12, 2004
+
+
Added new window that allows one to compute solvent viscosity for a mixture of water and acetonitrile (MeCN) given the temperature and percent organic composition. The routine uses the Chen-Horvath equation (see Thompson, JD; Carr, P, Analytical Chemistry, 2002, 74, 4150-4159 or Chen, H; Horvath, CJ, Chromatography A, 1995, 705, 3)
+
Can also graph the viscosity as a function of percent organic composition for the given temperature.
+
+
+
Revision 6.32 - Completed February 29, 2004
+
+
Fixed bug in Capillary Flow Calculator that gave erroneous results if one were to set the particle diameter to 0, then back to a non-zero value when finding column back pressure for packed capillaries.
+
Now displaying the references to the Chen-Horvath viscosity equation in the program, just below the equation.
+
+
+
Revision 6.33 - Completed March 27, 2004
+
+
Updated the MwtWinDll.Dll file to include Xxx as a default amino acid abbreviation, equivalent to C6H12NO (Lysine)
+
+
+
Revision 6.34 - Completed August 14, 2004
+
+
Fixed bug in the Peptide Sequence and Fragmentation module that used the monoisotopic mass of hydrogen as the charge carrier rather than using the mass of a proton (which is 0.0005 Da less than the mass of hydrogen). This involved updating MwtWinDll.Dll.
+
On the Isotopic Distribution module, added the ability to display the masses as m/z values, with charge values greater than 1.
+
+
+
Revision 6.35 - Completed September 12, 2004
+
+
Fixed bug in the Mole/Mass/Dilution Calculator that involved the dilution concentrations not updating when the custom mass was changed.
+
+
+
Revision 6.36 - Completed November 16, 2004
+
+
Updated the MwtWinDll.Dll file with a few bug fixes involving the peptide parsing class
+
+
+
Revision 6.37 - Completed December 26, 2004
+
+
Extended the Batch Calculation engine to support Isotopic Distribution commands. Enable using IsotopicDistribution=On ; Set the charge state using IsotopicDistributionCharge=1
+
+
+
Revision 6.38 - Completed February 18, 2006
+
+
Added error handlers to the copy and paste routines
+
Updated the mass of the most abundant isotope for each element to match the default monoisotopic mass for each element
+
+
The elemental masses come from two different sources and the monoisotopic mass was sometimes slightly different than the most abundant isotope's mass; this has been corrected
+
As part of this update, switched the variables used to store mass values from single to double precision
+
+
+
+
Revision 6.39 - Completed March 8, 2006
+
+
Added option Show Delta Mass on the Formula Finder form
+
Added new sort option to the Formula Finder: Sort by Abs(Delta Mass)
+
Fixed bug in the Peptide Sequence and Fragmentation module that caused an array initialization error when no valid residues were defined in the peptide sequence
+
Fixed control placement bug on the Formula Finder form
+
+
+
Revision 6.40 - Completed May 25, 2006
+
+
Fixed bug that caused the program to crash if you maximized the Formula Finder screen
+
+
+
Revision 6.41 - Completed September 21, 2006
+
+
Fixed several data synchronization bugs in the capillary flow calculator that caused displayed values to get out of sync with values cached in the DLL. Bug was commonly seen if various input values on the form were set to 0 then set back to a non-zero value.
+Choose Save Options as Defaults to save the current options to the MWTWIN.INI file or Restore Default Options to set the all the options to their respective defaults (though the MWTWIN.INI file is not automatically written). You can also turn on the Autosave feature to have results saved automatically upon program exit.
+
+
diff --git a/html/SaveRestoreValues.htm b/html/SaveRestoreValues.htm
new file mode 100644
index 0000000..82803e5
--- /dev/null
+++ b/html/SaveRestoreValues.htm
@@ -0,0 +1,14 @@
+
+
+
+
+Values and Formulas Save Options
+
+
+
+These options save or load the current Values and Formulas in the MWT_VALU.INI file. This is useful for saving the current formulas and setting the values in the Formula Finder and/or Mole/Mass Converter to your own defaults. Then, when the program is next loaded, the saved formulas and values will be loaded. The Autosave feature can be used to save the options automatically.
+You can see the percent composition of the compounds by pressing the F8 key. Although only one formula is shown at a time, the other formulas are kept in memory and can be cycled through using the UP and DOWN keys without switching back to Multi View Mode. In Single View Mode the formulas can still be completely modified. The ENTER key or Calculate Button will calculate a formula's molecular weight and percent composition. However, in Single View Mode, pressing the ENTER key or clicking the Calculate Button will keep the same formula visible; only the UP and DOWN arrow keys will move to a new formula in Single View Mode. Use the new formula button to create a new formula.
+
+
diff --git a/html/StartupModule.htm b/html/StartupModule.htm
new file mode 100644
index 0000000..2c2701c
--- /dev/null
+++ b/html/StartupModule.htm
@@ -0,0 +1,14 @@
+
+
+
+
+Module to show at startup
+
+
+
This option can be used automatically display one of the modules when the program starts, instead of displaying the main program window. When an alternate module is chosen, the Hide Inactive Program Windows and Exit On Escape Without Confirmation options are automatically enabled (though they may be changed afterward). When an alternate startup module is enabled, the program can be quickly closed by clicking the X on the upper-right corner of the window. Choose the Close button or the Close menu item in the default module to see the main program window (and thus also to change the startup module).
+
+
+
diff --git a/html/StayOnTop.htm b/html/StayOnTop.htm
new file mode 100644
index 0000000..f49db24
--- /dev/null
+++ b/html/StayOnTop.htm
@@ -0,0 +1,13 @@
+
+
+
+
+Stay On Top
+
+
+
When the Stay on Top menu item is checked, the main window of the Molecular Weight Calculator will remain on top of all other Windows at all times. Other windows in the program will behavior normally. Select the menu item to toggle.
Each time you move the cursor to a new formula or any textbox, the program records the text or number in the textbox. If you decide while editing the formula or text box that you wish to revert to the stored value, you can press Ctrl+Z to Undo the change. Once you have moved to a separate formula or another textbox, you can no longer revert the change made to the first formula or text box.
+
+
+
diff --git a/images/DeadTimeAndVolumeOpen.gif b/images/DeadTimeAndVolumeOpen.gif
new file mode 100644
index 0000000..b58fcd4
Binary files /dev/null and b/images/DeadTimeAndVolumeOpen.gif differ
diff --git a/images/DeadTimeAndVolumePacked.gif b/images/DeadTimeAndVolumePacked.gif
new file mode 100644
index 0000000..0149074
Binary files /dev/null and b/images/DeadTimeAndVolumePacked.gif differ
diff --git a/images/DownArrow.gif b/images/DownArrow.gif
new file mode 100644
index 0000000..e33e82f
Binary files /dev/null and b/images/DownArrow.gif differ
diff --git a/images/ExtraColumnBroadeningEquations.gif b/images/ExtraColumnBroadeningEquations.gif
new file mode 100644
index 0000000..b18f92a
Binary files /dev/null and b/images/ExtraColumnBroadeningEquations.gif differ
diff --git a/images/IonFragmentation.gif b/images/IonFragmentation.gif
new file mode 100644
index 0000000..fb03162
Binary files /dev/null and b/images/IonFragmentation.gif differ
diff --git a/images/LinearVelocityDescription.gif b/images/LinearVelocityDescription.gif
new file mode 100644
index 0000000..f13cc57
Binary files /dev/null and b/images/LinearVelocityDescription.gif differ
diff --git a/images/LinearVelocityDescriptionOpen.gif b/images/LinearVelocityDescriptionOpen.gif
new file mode 100644
index 0000000..65ac065
Binary files /dev/null and b/images/LinearVelocityDescriptionOpen.gif differ
diff --git a/images/LinearVelocityEquation.gif b/images/LinearVelocityEquation.gif
new file mode 100644
index 0000000..c91da39
Binary files /dev/null and b/images/LinearVelocityEquation.gif differ
diff --git a/images/LinearVelocityEquationOpen.gif b/images/LinearVelocityEquationOpen.gif
new file mode 100644
index 0000000..77d508f
Binary files /dev/null and b/images/LinearVelocityEquationOpen.gif differ
diff --git a/images/MolecularWeightCalculatorLogo.jpg b/images/MolecularWeightCalculatorLogo.jpg
new file mode 100644
index 0000000..7cc3896
Binary files /dev/null and b/images/MolecularWeightCalculatorLogo.jpg differ
diff --git a/images/MwtAminoAcidNotation.gif b/images/MwtAminoAcidNotation.gif
new file mode 100644
index 0000000..d2ee1d8
Binary files /dev/null and b/images/MwtAminoAcidNotation.gif differ
diff --git a/images/MwtCapillaryFlowCalculator.gif b/images/MwtCapillaryFlowCalculator.gif
new file mode 100644
index 0000000..67f1641
Binary files /dev/null and b/images/MwtCapillaryFlowCalculator.gif differ
diff --git a/images/MwtEditAbbreviations.gif b/images/MwtEditAbbreviations.gif
new file mode 100644
index 0000000..79e6793
Binary files /dev/null and b/images/MwtEditAbbreviations.gif differ
diff --git a/images/MwtFormulaFinder.gif b/images/MwtFormulaFinder.gif
new file mode 100644
index 0000000..248b235
Binary files /dev/null and b/images/MwtFormulaFinder.gif differ
diff --git a/images/MwtInGerman.gif b/images/MwtInGerman.gif
new file mode 100644
index 0000000..c0d8e43
Binary files /dev/null and b/images/MwtInGerman.gif differ
diff --git a/images/MwtIonPlot1.gif b/images/MwtIonPlot1.gif
new file mode 100644
index 0000000..55ddefe
Binary files /dev/null and b/images/MwtIonPlot1.gif differ
diff --git a/images/MwtIonPlot2.gif b/images/MwtIonPlot2.gif
new file mode 100644
index 0000000..7129af5
Binary files /dev/null and b/images/MwtIonPlot2.gif differ
diff --git a/images/MwtIsoAbundance1.gif b/images/MwtIsoAbundance1.gif
new file mode 100644
index 0000000..7a61835
Binary files /dev/null and b/images/MwtIsoAbundance1.gif differ
diff --git a/images/MwtIsoAbundance2.gif b/images/MwtIsoAbundance2.gif
new file mode 100644
index 0000000..dae68a5
Binary files /dev/null and b/images/MwtIsoAbundance2.gif differ
diff --git a/images/MwtIsoAbundance3.gif b/images/MwtIsoAbundance3.gif
new file mode 100644
index 0000000..0ca84c0
Binary files /dev/null and b/images/MwtIsoAbundance3.gif differ
diff --git a/images/MwtIsoAbundance4.gif b/images/MwtIsoAbundance4.gif
new file mode 100644
index 0000000..5737782
Binary files /dev/null and b/images/MwtIsoAbundance4.gif differ
diff --git a/images/MwtMainScreen.gif b/images/MwtMainScreen.gif
new file mode 100644
index 0000000..1c213d5
Binary files /dev/null and b/images/MwtMainScreen.gif differ
diff --git a/images/MwtMoleMassConverter.gif b/images/MwtMoleMassConverter.gif
new file mode 100644
index 0000000..911ac75
Binary files /dev/null and b/images/MwtMoleMassConverter.gif differ
diff --git a/images/MwtPeptideFrag.gif b/images/MwtPeptideFrag.gif
new file mode 100644
index 0000000..362b49b
Binary files /dev/null and b/images/MwtPeptideFrag.gif differ
diff --git a/images/MwtPercentComposition.gif b/images/MwtPercentComposition.gif
new file mode 100644
index 0000000..96caf2e
Binary files /dev/null and b/images/MwtPercentComposition.gif differ
diff --git a/images/MwtPercentSolver.gif b/images/MwtPercentSolver.gif
new file mode 100644
index 0000000..9ec9b87
Binary files /dev/null and b/images/MwtPercentSolver.gif differ
diff --git a/images/MwtWinIcon.gif b/images/MwtWinIcon.gif
new file mode 100644
index 0000000..96657d6
Binary files /dev/null and b/images/MwtWinIcon.gif differ
diff --git a/images/Old/MwtIsoAbundance.gif b/images/Old/MwtIsoAbundance.gif
new file mode 100644
index 0000000..c574db4
Binary files /dev/null and b/images/Old/MwtIsoAbundance.gif differ
diff --git a/images/Old/MwtIsoAbundance2.gif b/images/Old/MwtIsoAbundance2.gif
new file mode 100644
index 0000000..7b607b1
Binary files /dev/null and b/images/Old/MwtIsoAbundance2.gif differ
diff --git a/images/Old/MwtIsoAbundance3.gif b/images/Old/MwtIsoAbundance3.gif
new file mode 100644
index 0000000..d557cc8
Binary files /dev/null and b/images/Old/MwtIsoAbundance3.gif differ
diff --git a/images/Old/ResolutionComparison1000.gif b/images/Old/ResolutionComparison1000.gif
new file mode 100644
index 0000000..18f9a56
Binary files /dev/null and b/images/Old/ResolutionComparison1000.gif differ
diff --git a/images/Old/ResolutionComparison1500.gif b/images/Old/ResolutionComparison1500.gif
new file mode 100644
index 0000000..71f2570
Binary files /dev/null and b/images/Old/ResolutionComparison1500.gif differ
diff --git a/images/Old/ResolutionComparison5000.gif b/images/Old/ResolutionComparison5000.gif
new file mode 100644
index 0000000..5934abe
Binary files /dev/null and b/images/Old/ResolutionComparison5000.gif differ
diff --git a/images/Old/ResolutionComparison750.gif b/images/Old/ResolutionComparison750.gif
new file mode 100644
index 0000000..16c75eb
Binary files /dev/null and b/images/Old/ResolutionComparison750.gif differ
diff --git a/images/OldLogo.gif b/images/OldLogo.gif
new file mode 100644
index 0000000..74408ca
Binary files /dev/null and b/images/OldLogo.gif differ
diff --git a/images/PostTranslationMods.gif b/images/PostTranslationMods.gif
new file mode 100644
index 0000000..59d0b05
Binary files /dev/null and b/images/PostTranslationMods.gif differ
diff --git a/images/ResolutionComparison1000.gif b/images/ResolutionComparison1000.gif
new file mode 100644
index 0000000..82e5775
Binary files /dev/null and b/images/ResolutionComparison1000.gif differ
diff --git a/images/ResolutionComparison500.gif b/images/ResolutionComparison500.gif
new file mode 100644
index 0000000..585160b
Binary files /dev/null and b/images/ResolutionComparison500.gif differ
diff --git a/images/ResolutionComparison5000.gif b/images/ResolutionComparison5000.gif
new file mode 100644
index 0000000..1ae6002
Binary files /dev/null and b/images/ResolutionComparison5000.gif differ
diff --git a/images/ResolutionComparison750.gif b/images/ResolutionComparison750.gif
new file mode 100644
index 0000000..4437218
Binary files /dev/null and b/images/ResolutionComparison750.gif differ
diff --git a/images/SourceDocs/IonFragmentation.ppt b/images/SourceDocs/IonFragmentation.ppt
new file mode 100644
index 0000000..95e8b51
Binary files /dev/null and b/images/SourceDocs/IonFragmentation.ppt differ
diff --git a/images/SourceDocs/MolecularWeightCalculatorLogo.CNV b/images/SourceDocs/MolecularWeightCalculatorLogo.CNV
new file mode 100644
index 0000000..d1c5b1f
Binary files /dev/null and b/images/SourceDocs/MolecularWeightCalculatorLogo.CNV differ
diff --git a/images/SourceDocs/isotopes.bmp b/images/SourceDocs/isotopes.bmp
new file mode 100644
index 0000000..773e859
Binary files /dev/null and b/images/SourceDocs/isotopes.bmp differ
diff --git a/images/UpArrow.gif b/images/UpArrow.gif
new file mode 100644
index 0000000..2e3aa2d
Binary files /dev/null and b/images/UpArrow.gif differ
diff --git a/images/VolFlowRateEquationOpen.gif b/images/VolFlowRateEquationOpen.gif
new file mode 100644
index 0000000..245e616
Binary files /dev/null and b/images/VolFlowRateEquationOpen.gif differ
diff --git a/images/VolFlowRateEquations.gif b/images/VolFlowRateEquations.gif
new file mode 100644
index 0000000..19cf965
Binary files /dev/null and b/images/VolFlowRateEquations.gif differ
diff --git a/images/WhiteBitmap.bmp b/images/WhiteBitmap.bmp
new file mode 100644
index 0000000..2300a14
Binary files /dev/null and b/images/WhiteBitmap.bmp differ
diff --git a/images/isotopes.gif b/images/isotopes.gif
new file mode 100644
index 0000000..5e8514e
Binary files /dev/null and b/images/isotopes.gif differ
diff --git a/images/monroe_address.gif b/images/monroe_address.gif
new file mode 100644
index 0000000..16de2c0
Binary files /dev/null and b/images/monroe_address.gif differ
diff --git a/images/mwtwin.bmp b/images/mwtwin.bmp
new file mode 100644
index 0000000..77174f7
Binary files /dev/null and b/images/mwtwin.bmp differ
diff --git a/images/mwtwin.gif b/images/mwtwin.gif
new file mode 100644
index 0000000..e4ace15
Binary files /dev/null and b/images/mwtwin.gif differ
diff --git a/images/mwtwin2.bmp b/images/mwtwin2.bmp
new file mode 100644
index 0000000..128c4b0
Binary files /dev/null and b/images/mwtwin2.bmp differ
diff --git a/lang_catalan.ini b/lang_catalan.ini
new file mode 100644
index 0000000..46ddd54
--- /dev/null
+++ b/lang_catalan.ini
@@ -0,0 +1,1107 @@
+; Language customization file for the Molecular Weight Calculator program by Matthew Monroe
+; Contact at alchemistmatt@yahoo.com and http://come.to/alchemistmatt/ or http://www.alchemistmatt.com/
+;
+; When customizing the phrases in this file, the ampersand symbol (&) signifies a
+; keyboard shortcut. For example, the default value for key 1000 is &File. When
+; running the program, the F in File will be underlined and the user may press Alt-F
+; to access the File menu (in addition to clicking on the file menu)
+; To improve usability of the program, please try to include the & symbol in menu items
+; and buttons. Note, however, that if two controls on the same form have the same &
+; shortcut, they will not respond to the alt key in the usual way.
+;
+; In this file, items surround by brackets [] are section headers -- the program ignores them
+; when parsing the file. The key values (1000, 1010, 1020, etc.) should not be changed, with
+; the exception that new caution statements may be added at the end of the file.
+; Lines beginning with a semicolon (;) are also ignored since they are treated as comments
+; However, you should not place a ; at the end of a line with an actual key and caption.
+;
+; Keys with multiple values separated by a vertical line (|) represent multiple items loaded
+; into a ComboBox control. When translating to other languages, you must keep the same number
+; of items in the list, or program functionality will be lost. For example, key 7070 contains
+; hours|minutes|seconds Thus, hours, minutes, and seconds will be loaded into a control, from
+; which the user may select one of them. In Spanish, you would use 7070=horas|segundos|minutos
+;
+; If you create a new .Ini file for a foreign language and would like it posted on my
+; web page, simply e-mail it to me.
+
+; Catalan version -- by Antoni Escalas
+; Barcelona (Catalonia), Spain
+; For Molecular Weight Calculator v6.x
+
+[Language]
+Language=Català
+
+[frmMain Menus]
+; Menu Items
+1000=&Fitxer
+1010=Edita la &taula d'elements
+1020=Edita les &abreviatures
+1030=&Calcula masses des d'un fitxer de text
+1040=Im&primeix els resultats
+1050=&Surt
+1500=&Edita
+1505=&Undo
+1510=Re&talla
+1520=&Copia
+1530=En&ganxa
+1540=&Suprimeix
+1545=Select &All
+1550=Copia la fórmula actual com a &RTF
+1560=Copia la massa &molecular actual
+1570=Copia les dades de composició en tant &per cent
+1580=Duplica la &fórmula actual
+1590=Esborr&a totes les fórmules
+1600=Esborra la fórmula actual
+1610=E&xpandeix les abreviatures
+1620=C&onverteix a fórmula empírica
+2000=&Visualitza
+2010=Vista &múltiple
+2020=&Vista simple
+2030=Calculadora de &percentatges
+2040=&Desactiva
+2050=&Activa
+2500=&Eines
+2510=Conversor de &mols/massa/dilució
+2520=Buscador de &fórmules
+2530=Conversor de la notació dels &aminoàcids
+2533=Modelització de la fragmentació de la seqüència de &pèptids
+2536=Modelització de la distribució &isotòpica
+2538=Mostra la &distribució isotòpica per a la fórmula actual
+2540=Calculadora &matemàtica
+2550=Calculadora per al flux cap&il·lar
+3000=&Opcions
+3010=Trieu &idioma [Language]
+3020=Canvia les &preferències del programa
+3030=Canvia el tipus de lletra de les &fórmules
+3040=Sempre &visible
+3050=&Desa i restableix els valors per defecte
+3060=&Restableix els valors i les fórmules per defecte
+3070=Desa ara els &valors i les fórmules
+3500=&Ajuda
+3510=Visió general del &programa
+3530=&Mostra els consells sobre les eines
+3540=&Quant al MWT
+
+[frmMain Status Messages and Verification Messages]
+3600=La línia completa és:
+3605=Línia completa
+3610=Esteu segur que voleu convertir la fórmula actual en la seva fórmula empírica?
+3615=Converteix a fórmula empírica
+3620=Esteu segur que voleu esborrar la fórmula actual?
+3625=Esborra la fórmula actual
+3630=Esteu segur que voleu expandir les abreviatures de la fórmula actual en els seus equivalents elementals?
+3635=Expandeix les abreviatures
+3640=Restablir els valors per defecte esborrarà les fórmules actuals. Esteu segur que ho voleu fer?
+3645=Restablint els valors i les fórmules
+3650=Definiu el percentatge objectiu de la calculadora de percentatges. Seleccioneu Restablir per alliberar aquest valor or Cancel·lar per ignorar tots els canvis.
+3660=Feu servir Av Pàg/Re Pàg o les fletxes Amunt/Avall per moure els percentatges (F11 fa sortir del mode Calculadora de percentatges).
+3665=Premeu la tecla de retorn per canviar a percentatge (F11 fa sortir del mode Calculadora de percentatges).
+3670=Preparat
+3700=Calculant, premeu qualsevol tecla o cliqueu el ratolí per aturar.
+3710=x és
+3720=Valor calculat
+3730=Objectiu
+3740=Diferència respecte de l'objectiu
+3750=Càlcul de % activat
+3760=Resultats de la Calculadora de masses moleculars
+3770=Els valors per defecte i les fórmules han estat restaurats.
+3780=Esteu segur que voleu esborrar totes les fórmules?
+3785=Esborra totes les fórmules
+3790=Esteu segur que voleu sortir?
+3795=Sortint del programa
+3800=S'estan carregant les abreviatures
+3810=S'estan carregant els elements
+3820=(s'estant utilitzant masses atòmiques mitjanes)
+3830=(s'estan usant masses atòmiques isotòpiques)
+3840=(s'estan usant masses atòmiques enteres)
+3850=S'ha desat el nou idioma per defecte.
+
+[Phrases common throughout application]
+4000=&Tanca
+4010=&D'acord
+4020=&Cancel·la
+4030=&Surt
+; The following is the abbreviation for Molecular Weight
+; It must be exactly two letters long
+4040=MW
+4050=Atenció
+4060=Yes
+4065=No
+
+[frmMain]
+; Form Caption
+4900=Calculadora de masses moleculars
+; Labels
+5000=Fórmula
+5010=Canvi ràpid entre modes d'element
+5020=&Mitjana
+5021=Utilitza les masses mitjanes dels elements
+5030=&Isotòpica
+5031=Utilitza l'isòtop més comú
+5040=En&tera
+5041=Utilitza la massa nominal entera de l'isòtop més comú
+; TextBoxes
+5051=Teclegeu la fórmula molecular aquí
+; Buttons
+5100=&Calcula
+5101=Determina la massa molecular de la fórmula actual
+5110=&Nova fórmula
+5111=Afegeix una nova fórmula en blanc a la llista
+5116=Mostra una nova fórmula en blanc
+; Grid control
+5201=Cliqueu per definir o redefinir el valor desitjat
+; Status control
+5301=feu doble clic sobre la línia d'estat per expandir-la
+5350=El Molecular Weight Calculator ja s'està executant. Esteu segur que en voleu iniciar una altra còpia?
+5355=Ja s'està executant
+
+[frmAboutBox]
+5500=About MWT
+5510=MWT és programari lliure; distribuïu-lo lliurement
+
+[frmIntro]
+5700=S'està carregant
+
+[frmAminoAcidConverter]
+; Form Caption
+6000=Conversor de la notació dels aminoàcids
+; Labels
+6010=Seqüència d'aminoàcids basada en una sola lletra
+6020=Seqüència d'aminoàcids basada en tres lletres
+; TextBoxes
+6031=Introduïu aquí la seqüència fent servir abreviatures d'1 lletra
+6041=Introduïu aquí la seqüència fent servir abreviatures de 3 lletres
+; Buttons
+6050=&Copia la seqüència de 3 lletres com a fórmula:
+6060=Copia al modelador de &fragmentació
+; CheckBoxes
+6080=&Afegeix un espai cada 10 residus
+6090=&Separa els residus amb un guionet
+
+[frmCalculator]
+; Form caption
+6500=Calculadora
+; Textbox
+6511=Introduïu una expressió matemàtica a calcular
+; Buttons
+6520=&Calcula
+6521=Calcula l'expressió actual
+; Status control
+6610=Resultat
+
+[frmCapillaryCalcs]
+; Form Caption
+7000=Càlculs del flux capil·lar i del flux màssic
+; Combo Boxes
+7010=Capil·lar tubular obert|Capil·lar reblit
+7011=Commuta entre capil·lars oberts i reblits.
+7020=Calcula la pressió a l'entrada de la columna|Calcula la llargada de columna|Calcula el diàmetre interior|Calcula el cabal volumètric|Calcula el cabal volumètric a partir del temps mort
+7030=psi|Pascals|Quilopascals|Atmosferes|Bar|Torr (mm Hg)|dynes/cm^2
+7035=m|cm|mm|um|Polzades
+7040=Poise [g/(cm-s)]
+7050=mL/min|uL/min|nL/min
+7060=cm/h|mm/h|cm/min|mm/min|cm/s|mm/s
+7070=hores|minuts|segons
+7080=mL|uL|nL|pL
+7090=Molar|Mil·limolar|Micromolar|Nanomolar|Picomolar|Femtomolar|Atomolar|mg/dL|mg/mL|ug/mL|ng/mL|ug/uL|ng/uL
+7100=pmol/min|fmol/min|amol/min|pmol/s|fmol/s|amol/s
+7110=Mols|Mil·limols|Micromols|Nanomols|Picomols|Femtomoles|Atomols
+; Labels and frames
+7200=Contrapressió
+7210=Llargada de columna
+7220=Diàmetre interior de la columna
+7230=Viscositat del dissolvent
+7240=Diàmetre de partícula
+7250=Cabal volumètric
+7260=Velocitat lineal
+7270=Temps mort de la columna
+7280=Volum de la columna
+7290=Porositat interparticular (èpsilon)
+7300=Calcul del flux màssic
+7310=Concentració de la mostra
+7320=Temps d'injecció
+7330=Flux màssic
+7340=Mols injectats
+7350=Calculs addicionals per a l'eixamplament de la columna
+7360=Coefficient de difusió
+7370=Llargada del tub obert
+7380=Diàmetre interior del tub obert
+7390=Amplada inicial de pic (a la base)
+7400=Velocitat lineal òptima
+7410=(per a partícules de 5 um)
+7420=Variància temporal
+7430=Variància addicional
+7440=Amplada resultant de pic
+7450=Augment percentual
+7460=La fórmula actual és
+7480=Personalitzeu la massa
+7500=cm
+7510=um
+7520=cm^2/sec
+7530=sec
+7540=cm/sec
+7550=sec^2
+7560=sec
+7570=g/mole
+; TextBoxes
+7601=Introduïu la massa numèrica personalitzada a utilitzar en els càlculs
+; Buttons
+7700=Mostra/oculta els càlculs d'eixamplament de &pic
+7710=&Visualitza les equacions explicatives
+7730=Visualitza les equacions
+; Option Buttons
+7750=&Utilitza la massa del compost en la fórmula actual
+7760=Ut&ilitza la massa numèrica personalitzada
+; CheckBoxes
+7800=Pren el cabal de dalt
+; ToolTips
+7851=Un valor típic de la viscositat és 0,0089 poise
+7861=Un valor típic de la porositat és 0,4
+7871=Un coeficient de difusió típic per a compostos orgànics petits és 0,00001, és a dir, 1E-5; Un valor típic per a un pèptid és 0,000005, és a dir, 5E-6
+; Menus
+7900=&Carrega els valors
+7910=&Desa els valors
+7950=&Càlculs de flux capil·lar
+
+[frmChangeFont]
+; Form Caption
+8000=Canvia el tipus de lletra de les fórmules
+; Combo Boxes
+; Labels
+8060=Canvia el tipus de lletra de les fórmules a:
+8070=Mida:
+; Buttons
+
+[frmChangeValue]
+; Form Caption
+8200=Canvia el valor
+; Buttons
+8210=&Restableix els valors per defecte
+
+[frmChangeLanguage]
+8400=Tria l'idioma
+; Labels
+8410=El idiomes disponibles es mostren tot seguit. Escolliu l'idioma que voleu utilitzar.
+8420=No hi ha cap fitxer d'idioma disponible. Visiteu la web de l'autor per descarregar altres idiomes.
+
+[frmDiff]
+8600=Diferències de la calculadora de percentatges
+8610=&Copia
+8611=Copia els resultats als porta-retalls
+
+[frmEditAbbrev]
+9000=Edita les abreviatures
+; Buttons
+9010=&Restableix els valors per defecte
+9011=Restableix les abreviatures als valors per defecte del programa
+9020=&Suprimeix
+; Messages
+9050=S'ha arribat al màxim
+9060=Atenció, només es permeten 500 abreviatures.
+9090=L'abreviatura o fórmula molecular es canviarà al valor que teclegeu. Seleccioneu Suprimeix per suprimir l'abreviatura o Cancel·lar per ignorar tots els canvis.
+9100=Esteu segur que voleu perdre tots els canvis?
+9105=S'està tancant la finestra d'edició d'abreviatures
+9110=Esteu segur que voleu restablir les abreviatures als seus valors per defecte
+9115=Restableix els valors per defecte
+9120=Warning, test usage of the new/updated abbreviation did not give the same mass as the formula for the abbreviation. This probably indicates a problem with the abbreviation's formula.
+;Table Tool Tip
+9140=
+9141=Cliqueu per canviar una abreviatura
+9145=Symbol
+; Table Column Titles
+9150=Càrrega
+9160=Fórmula molecular
+9170=Abrev. normal
+9180=Nom d'aminoàcid
+9190=1 lletra
+9195=Comment
+
+[frmEditElem]
+9200=Edita els elements
+; Buttons
+9210=&Restableix els valors per defecte
+9211=Restableix les masses elementals com a les seves masses mitjanes
+9220=&Restableix
+9230=Utilitza masses atòmiques mitj&anes
+9231=Fixa totes les masses dels elements en el seu valor mitjà trobat a la natura
+9240=Utilitza la massa de l'&isòtop més comú
+9241=Fixa totes les masses elementals en la massa de l'isòtop més comú de l'element (per a espectrometria de masses d'alta resolució)
+9245=Fes servir la massa entera &nominal
+9246=Fixa les masses elementals en la massa entera nominal de l'isòtop més comú de l'element (per a espectrometria de masses de baixa resolució)
+; Messages
+9250=La massa elemental o la incertesa es canviaran al valor que teclegeu. Selecciconeu Restablir per restablir el valor per defecte or Cancel·la per ignorar els canvis.
+9260=Esteu segur que voleu restablir tots els valors en les seves masses elementals mitjanes?
+9265=Canvia a masses mitjanes
+9270=Esteu segur que voleu restablir tots els valors en les seves masses elementals isotòpiques?
+9275=Canvia a masses isotòpiques
+9280=Esteu segur que voleu restablir tots els valors en les seves masses enteres?
+9285=Canvia a masses enteres
+9290=Esteu segur que voleu restablir tots els valors en els valors elementals per defecte (masses mitjanes)?
+9295=Restableix els valors per defecte
+9300=Si s'executa no es pot anul·lar.
+9310=Esteu segur que voleu perdre tots els canvis?
+9315=S'està tancant la taula d'elements.
+;Table Tool Tip
+9340=
+9341=Cliqueu per canviar la massa o l'incertesa d'un element
+;Table Column Titles
+9350=Element
+9360=Massa
+9370=Incertesa
+; Combo boxes
+9380=Símbol de l'element|Nombre atòmic|Incertesa|Càrrega
+9390=Ordena els elements per:
+
+[frmEquationsBroadening]
+9500=Equacions de l'eixamplament extracolumnar
+
+[frmEquationsOpenTube]
+9550=Equacions del flux en un tub obert
+
+[frmEquationsPackedCapillary]
+9600=Equacions del flux en un capil·lar reblit
+
+[frmFinderModeWarn]
+; Instructions Label
+9700=L'ús típic de buscador de fórmules és quan la massa (pes) monoisotòpica d'un compost és coneguda (determinada típicament per espectrometria de masses) i cal cercar possibles compostos que s'hi ajustin.
+9701=Per exemple, es mesura una massa de 16.0312984 Dalton per a un compost que conté carboni i hidrogen, i es busca la possible fórmula empírica. Efectuant la cerca, amb una tolerància de massa de 5000 ppm, s'obtenen tres compostos, H2N, CH4 i O. Amb 500 ppm només el CH4 s'hi ajusta, que és la solució correcta.
+9702=Per utilitzar correctament aquesta característica, el programa s'ha de posar en el mode de massa isotòpica. Això es pot fer triant manualment Edita la taula d'elements, al menú de Fitxer, o bé el programa pot commutar automàticament a aquest mode.
+9703=Voldríeu:
+9705=L'ús típic de la modelització de la fragmentació és per predir les masses que s'espera trobar amb un espectròmetre de masses quan un pèptid entra a l'instrument, es ionitza i es fragmenta al llarg de cadena del pèptid.
+9706=El pèptid normalment es fragmenta a cada enllaç amido. Per exemple, el pèptid Gly-Leu-Tyr formarà els fragments Gly-Leu, Leu-Tyr, Gly, Leu, i Tyr. A més, el trencament de l'enllaç amido es pot presentar a diferents ubicacions, donant lloc a diverses masses.
+; Buttons
+9720=&Continua
+; Option Buttons
+9750=Commuta al mode de massa &isotòpica ara.
+9760=Canvia sempre automàticament al mode de massa isotòpica.
+9770=Segueix usant masses &mitjanes.
+; CheckBoxes
+9780=&Deixa de mostrar aquesta finestra d'advertiment.
+
+[frmFinder]
+10000=Buscador de fórmules
+; Labels
+10010=Seleccioneu els elements adequats o afegiu-hi els vostres, introduïu una massa molecular o la composició percentual, i llavors seleccioneu Calcula per trobar els compostos que s'ajusten a les especificacions.
+10020=Massa molecular de la fórmula:
+10030=Massa molecular de l'objectiu:
+10040=Tolerància de massa molecular:
+10050=Tolerància percentual:
+10060=Mín
+10070=Màx
+10080=Element
+10090=Percent.
+10100=Màxim de resultats
+10105=Massa atòmica
+; Percent completed status messages
+10110=% acabat
+10115=S'està ordenant
+10120=S'està cercant
+10125=S'està treballant
+10130=Acabat
+10135=compostos
+10140=S'ha interromput l'ordenació
+10145=S'han interromput els càlculs
+10150=S'està formatant
+10155=Fet
+10160=S'ha avortat el formatatge
+; Listboxes & Textboxes
+10201=Feu doble clic sobre qualsevol línia per expandir-la
+10221=Quantitat del compost objectiu que pot provenir de la massa objectiu
+10231=Quantitat de la composició percentual que pot provenir del percentatge objectiu
+10241=Nombre màxim d'objectius a trobar
+10251=Nombre mínim d'àtoms en el compost objectiu
+10256=Nombre màxim d'àtoms en el compost objectiu
+10260=Percentatge
+10261=Composició percentual del compost objectiu que és
+10270=nombre o element o abrev.
+10271=Teclegeu una massa per a l'element personalitzat, un símbol d'element o una abreviatura
+; Note the following is 'dm' in English, standing for 'delta mass' or the mass difference
+; of the given result's mass versus the target mass
+10280=dm
+; Note the following is 'ppm' in English, standing for 'parts per million'
+10285=ppm
+; Buttons
+10300=Opcions del busc&ador
+10301=Drecera: Ctrl+O
+10310=&Calcula
+10311=Troba els compostos que s'ajusten als paràmetres especificats
+10320=Imprimei&x
+10330=Copia com a RT&F
+10331=Copia els resultats al porta-retalls en format de Rich Text
+10340=Cop&ia
+10341=Copia els resultats al porta-retalls
+10345=&Mostra distrib. isotòpica
+10346=Mostra la distribució isotòpica del compost actualment seleccionat (ctrl+D)
+; Option Buttons
+10350=Ajusta la &massa molecular
+10360=Ajusta la composició &percentual
+; CheckBoxes
+10370=Mode de ppm
+10380=Show Delta Mass
+10381=Note: Delta mass notation will change as the standard deviation mode is changed (F12 in the main window)
+; Elements (and Custom element phrase)
+10400=Carboni
+10405=Hidrogen
+10410=Nitrogen
+10415=Oxigen
+10420=Personalitzat
+; Messages
+; Note that 10455 is also used with the Abort button
+10450=Heu premut una tecla.
+10455=Avorta
+10460=Heu clicat amb el ratolí fora de la finestra de resultats.
+10465=S'està aturant el formatatge
+10470=S'està aturant l'ordenació.
+10480=La suma de composicions percentuals no és el 100%
+10485=Voleu continuar amb els càlculs?
+10490=No es pot calcular
+10500=Heu premut una tecla.
+10505=Heu clicat amb el ratolí fora de la finestra de resultats.
+10510=S'estant aturant els càlculs.
+10515=S'ha arribat al nombre màxim de resultats.
+10520=Màxim de resultats
+10530=Compostos trobats
+; Note: the following is used when displaying the results of a percent composition
+; search in the formula finder. A synonym for 'has' would be 'contains' or 'is composed of'
+10535=conté
+10540=S'ha produït un error de memòria. Probablement la llista de resultats és plena. Es mostren els resultats fins aquest punt.
+10545=Sense memòria
+10550=La finestra de resultats és buida.
+10555=No hi ha res a copiar
+10560=No hi ha res a imprimir
+10565=Esteu segur que voleu imprimir els resultats actuals?
+10570=S'està imprimint
+
+[frmFinderOptions]
+10800=Opcions del buscador
+; Labels
+10810=Utilitzeu els quadres de verificació per seleccionar les diverses opcions del buscador de fórmules.
+; Textboxes & Comboboxes
+10821=Càrrega mínima dels compostos
+10831=Càrrega màxima dels compostos
+10840=Cerca directa|Cerca restringida
+10841=La cerca directa troba tots els compostos coincidents. La cerca amb restriccions troba els compostos dins un interval de massa atòmica (la cerca directa sol ser més ràpida).
+10850=Ordena per fórmula
+10851=Mètode d'ordenació dels resultats. Recalculeu per reordenar.
+10855=Ordeneu per càrrega
+10860=Ordeneu per MW
+10865=Ordeneu per m/z
+10870=Relació massa/càrrega del compost objectiu
+10875=Massa molecular del compost objectiu
+; CheckBoxes
+10900=Calcula la &càrrega
+10901=Calcula la càrrega global de cada compost trobat
+10910=Limita l'interval de cà&rrega
+10911=Limita els compostos que mostra a un interval específic de càrrega
+10920=Calcula m/&z
+10921=Calcula la relació massa/càrrega per a cada compost trobat
+10930=Troba m/z objectiu
+10931=Troba els compostos amb valors d'm/z equivalents al compost objectiu
+10940=O&rdena els resultats
+10941=Converteix els resultats a fórmules empíriques i ordena-les
+10950=Àtom&s d'H intel·ligents
+10951=Limita el nombre d'àtoms d'hidrogen en els compostos trobats a un valor raonable
+10960=Ajusta &automàticament mín. i màx. en la cerca restringida.
+10961=Ajusta automàticament els valors màx. i mín. a un interval vàlid per a la massa objectiu donada
+
+[frmMMconvert]
+11000=Conversor de mols/massa i calculadora de dilucions
+; Combo Boxes
+11010=Converteix quantitats|Calcula concentracions|Càlcul de dilucions
+11011=Fa la conversió entre diferents quantitats de compost o realitza càlculs relacionats amb la molaritat
+11020=Mols|Mil·limols|Micromols|Nanomols|Picomols|Femtomols|Atomols|Quilograms|Grams|Mil·ligrams|Micrograms|Lliures|Unces|Litres|Decilitres|Mil·lilitres|Microlitres|Nanolitres|Picolitres|Galons|Quarts de galó|Pintes
+11021=Unitats de la quantitat a convertir
+11026=Unitats de la quantitat a utilitzar per al càlcul de la concentració
+11030=Litres|Decilitres|Mil·lilitres|Microlitres|Nanolitres|Picolitres|Galons|Quarts de galó|Pintes
+11031=Unitats de volum
+11041=Unitats de la quantitat convertida
+11051=Unitats de concentració
+; Labels
+11080=g/mL
+; Textboxes
+11101=Quantitat de compost a convertir
+11106=Quantitat de compost a dissoldre en el dissolvent
+11111=Densitat del compost
+11121=Volum de dissolvent en què es dissol el compost
+11131=Concentració de compost en el dissolvent
+; Buttons
+11150=Calcula la qu&antitat
+11151=Calcula la quantitat utilitzant el volum i la concentració
+11160=Calcula el &volum
+11161=Calcula el volum utilitzant la quantitat i la concentració
+11170=Calcula la &concentració
+11171=Calcula la concentració utilitzant la quantitat i el volum
+
+; Dilution-related controls
+11200=Càlculs de dilucions
+11205=Càlculs d'evaporació o de sublimació
+11210=Calcula els volums de dilució requerits|Calcula el volum total requerit|Calcula la concentració final|Calcula la concentració inicial
+11211=Quantitat a determinar en el càlcul de dilucions
+11220=En&llaça la concentració inicial de la dilució amb la concentració del conversor de quantitats
+11221=Copia la concentració calculada en el conversor sobre la concentració inicial per a la dilució i viceversa, si una de les dues canvia
+11230=Enllaça les unitats dels volums de dilució
+11231=Sincronitza les unitats del volum de solució mare, del volum de dissolvent i del volum total final
+; Dilution related labels and textbox tooltips
+11250=Concentració &inicial
+11256=Concentració de solut a la solució mare
+11260=Volum de &solució mare
+11266=Volum (alíquota) a prendre de solució mare quan es faci la dilució
+11270=Concentració &final
+11276=Concentració de solut a la solució final després de diluir
+11280=Volum de dissolvent utilitzat en la &dilució
+11286=Volum de dissolvent a mesclar amb la solució mare (alíquota) presa per fer la dilució
+11290=Volum &total final
+11296=Volum total de solució final obtinguda mesclant la solució mare i el dissolvent de dilució
+
+[frmProgramPreferences]
+11500=Preferències de la calculadora de masses moleculars
+; Frame labels
+11510=Mode d'abreviació (F3)
+11520=Reconeixement de majúscules/minúscules (F4)
+11530=Mode de la desviació estàndard (F12)
+11540=Opcions de massa atòmica per a eines avançades
+11550=Opcions de sortida del programa
+; Buttons
+11600=&Desa opcions com a valors per defecte
+11610=&Restableix les opcions per defecte
+; Option Buttons
+11650=Normal
+11651=Reconeix les abreviatures normals però no les dels aminoàcids
+11655=Normal + aminoàcids
+11656=Reconeix les abreviatures normals i els aminoàcids
+11660=Desactivat
+11661=Ignora totes les abreviatures
+11665=Converteix a majúscules
+11666=Converteix correctament les fórmules a majúscules en analitzar-se
+11670=Majúscules/minúscules exactes
+11671=Exigeix a l'usuari que teclegi les fórmules amb majúscules/minúscules correctes
+11675=Majúscules/minúscules intel·ligents
+11676=Interpreta correctament les fórmules en minúscules i no les passa a majúscules
+11680=Curt
+11681=Mostra les desviacions estàndard en forma abreujada
+11685=Científic
+11686=Mostra les desviacions estàndard en notació científica
+11690=Decimal
+11691=Mostra les desviacions estàndard en forma decimal llarga
+11695=Desactivat
+11696=No mostra les desviacions estàndard
+11700=Surt amb confirmació en prémer la tecla d'escapada
+11701=Determina si la tecla d'escapada fa sortir del programa i si cal confirmar la sortida del programa
+11705=Surt sense confirmació en prémer la tecla d'escapada
+11710=Ignora la tecla d'escapada però confirma la sortida
+11715=Ignora la tecla d'escapada i no confirmis la sortida
+; CheckBoxes
+11750=A&vança en prémer Calcula (F9)
+11751=Es mou a una nova línia de fórmula després de calcular la massa d'una fórmula
+11760=Tracta els &claudàtors com a parèntesis
+11761=Tracta els claudàtors, [i], com a parèntesis en lloc de marcadors de la calculadora de percentatges
+11770=Copia a&utomàticament la massa molecular actual (Ctrl+U)
+11771=Copia automàticament al porta-retalls la massa molecular de la fórmula seleccionada després de cada càlcul
+11780=Calcula la càrre&ga
+11781=Calcula la càrrega dels compostos (regles molt bàsiques, no pot fer la correcció per a dobles o triples enllaços, etc...)
+11800=Canvia sempre automàticament al mode &isotòpic
+11801=Canvia automàticament a masses isotòpiques en obrir el buscador de fórmules o el mòdul de fragmentació de pèptids
+11810=&No mostris mai la finestra d'advertència del mode de massa
+11811=No preguntis mai sobre el mode de massa actual quan obris el buscador de fórmules o el mòdul de fragmentació de pèptids
+11820=Desa &automàticament opcions, valors i fórmules en sortir
+11821=Desa automàticament les opcions, els valors i les fórmules en sortir del programa
+11830=Mostra les frases d'advertència (F7)
+11831=Adverteix quan hi ha possibles confusions d'elements a les fórmules (com Co i CO)
+11840=Mostra el canvi ràpid entre els modes d'elements
+11841=Mostra l'opció de canviar ràpidament entre modes de massa elemental
+11850=Mostra el consells referents a les eines
+11851=Mostra missatges curts quan el ratolí passa sobre certs botons i àrees
+11860=Ressalta els camps de text quan siguin seleccionats
+11861=Ressalta el camp de text complet quan t'hi desplacis
+11870=&Oculta les finestres inactives del programa
+11871=Oculta la finestra principal del programa en utilitzar el buscador de fórmules, el calculador de mols/masses, etc...
+11881=Tria un nombre més petit per evitar que la finestra de fórmules ocupi tota la pantalla. Si es disminueix, cal sortir i reiniciar el programa per tal que tingui efecte. El màxim depèn de la resolució de pantalla.
+11885=Nombre màxim de fórmules a mostrar
+11890=Mòdul a mostrar a l'inici
+11896=Mòdul a mostrar quan el programa s'inicia
+11898=Finestra principal|Buscador de fórmules|Calculadora de flux capil·lar|Conversor de mols/masses|Modelització de la fragmentació de seqüències de pèptids|Conversió de notacions d'aminoàcids|Modelització de la distribució isotòpica
+
+; Messages
+11900=S'han desat les opcions de desament automàtic
+11910=S'han restablert les opcions per defecte
+11920=S'han desat els valors i les fórmules.
+11925=NO s'han desat els valors i les fórmules perquè /X s'ha utilitzat l'opció de línia de comandes
+11930=S'han desat les opcions per defecte
+11935=NO s'han desat les opcions per defecte perquè /X s'ha utilitzat l'opció de línia de comandes
+
+[frmFragmentationModelling]
+12000=Modelització de la fragmentació de seqüències de pèptids
+; General Combo Boxes
+12010=Notació d'1 lletra|Notació de 3 lletres
+12011=Tipus de notació de seqüències d'aminoàcids
+12020=&Compara els ions
+; Textboxes
+12051=Introdueix aquí la seqüència d'aminoàcids
+12061=Desplaça en la quantitat indicada els ions carregats, per tal de fer la correcció per modificacions posttranslacionals.
+; Frames, labels, and checkboxes
+12100=Seqüència:
+12150=N i C terminals
+12160=&N
+12170=&C
+12180=H (hydrogen)|HH+ (protonated)|C2OH3 (acetyl)|C5O2NH6 (pyroglu)|CONH2 (carbamyl)|C7H6NS (PTC)|(none)
+12190=OH (hydroxyl)|NH2 (amide)|(bare)
+12200=Tipus d'ions
+12210=Ions &A
+12215=Ions &B
+12220=Ions &Y
+12230=Pèrdues neutres
+12236=Tria els ions als què s'aplicaran les pèrdues
+12240=Pèrdua d'H2O
+12250=Pèrdua d'NH3
+12255=Loss of PO4
+12260=Opcions de càrrega
+12270=Ions carregats &2+
+12280=&Llindar
+12286=El valor m/z per als ions 2+ es calcularà per als ions per damunt d'aquesta m/z
+12300=Opcions de comparació d'ions
+12310=&Elimina l'ió precursor
+12320=Massa de l'ió
+12330=Finestra de masses
+12340=&Finestra de comparació d'ions
+12350=Da
+12355=Desplaçament d'alinea&ció
+12360=Estadístiques dels ions
+12370=Carregats
+12375=Restants després d'agrupar-los
+12380=Dins de la tolerància
+12385=No s'ha trobat el precursor
+12390=S'ha eliminat el precursor
+12395=No s'ha eliminat el precursor
+12400=Coincidències
+12405=Puntuació
+12410=Mass Information
+12420=Element Mode
+12425=Average
+12430=Isotopic
+
+; Column titles in grids
+; Note: # means 'number', Immon. means 'immonium', and Seq. means 'sequence'
+12500=Nre.
+12510=Imoni
+12520=Seq.
+12550=Massa
+12560=Intensitat
+12570=Symbol
+
+; Menu Items
+12800=Carrega la informació de &la seqüència
+12810=De&sa la informació de la seqüència
+12820=Carrega la llista d'&ions a comparar
+12830=Tanc&a
+12840=&Copia els ions predits
+12850=Copia els ions predits com a &RTF
+12855=Copia els ions predits com a HTML
+12860=Enganxa la llista d'ions a com¶r
+12865=Copy Sequence Molecular &Weight
+12870=Neteja la &llista d'ions a comparar
+12880=Llista d'&ions a comparar
+12900=Espectre de &masses
+12910=Act&ualitza els espectres en haver-hi canvis
+12915=&Dta.Txt File Browser
+12920=&Opcions de la llista d'ions a comparar
+12925=Edit Residue &Modification Symbols
+12930=&Alinea automàticament els ions a comparar
+12940=Modelització de la &fragmentació
+12950=&Copy Selected Ions
+12960=&Delete All (Clear list)
+
+[frmMsPlot]
+13000=Gràfica
+; The following is an abbreviation for the word 'Location'
+13010=Ubic
+
+; Legend Items
+13030=Ions predits
+13035=Ions carregats
+
+; Menu Items
+13100=&Exporta les dades
+13150=&Tipus de gràfica
+13160=&Histograma
+13170=Pics &gaussians
+13180=Estableix la &resolució efectiva
+13190=Graella de l'eix X
+13200=Graella de l'eix Y
+13210=Marques a e&tiquetar (aprox.)
+13220=Eix &X
+13230=Eix &Y
+13235=&Qualitat dels gràfica (afecta la velocitat)
+13240=Qualitat de la representació &gaussiana
+13245=Factor d'&aproximació
+13250=Defineix l'interval de l'eix &X
+13260=Defineix l'interval de l'eix &Y
+13270=Eix Y amb escala &automàtica
+13280=&Fixa la Y mínima a zero
+13290=Redueix el zoom al valor previ
+13295=Ctrl+Z o botó dret
+13300=Redueix el zoom per mostrar-ho tot
+13310=Mode de &cursor
+13315=Espai activa Desplaça
+13320=&Zoom
+13330=&Desplaça
+13340=Mo&stra la posició actual
+13342=Mostra la &llegenda
+13345=Restableix les opcions per &defecte
+13350=Quadre de &zoom
+13360=Ampl&ia el zoom
+13365=Botó esquerre
+13370=Augmenta el zoom horitzontal
+13380=Augmenta el zoom vertical
+13390=Redueix el z&oom
+13400=Redueix el zoom horitzontal
+13410=Redueix el zoom vertical
+
+[frmIonMatchOptions]
+14000=Opcions de comparació d'ions
+; Buttons
+14010=&Restableix val. per defecte
+14020=Edit Auto-Label Options
+
+; Explanations
+14050=Quan una llista d'ions s'importa dins el programa, els ions de masses semblants poden ser agrupats mitjançant un procés d'agrupament per tal de reduir el nombre total de punts de dades. Tot seguit, es poden eliminar els ions entorn de l'ió precursor.
+14055=Llavors, les intensitats es normalitzen a una intensitat màxima donada i s'ordenen per intensitat decreixent. Els ions principals (el nombre d'ions a utilitzar) es divideixen en diferents regions de masses i es tornen a normalitzar.
+14060=Les masses dels ions predits per a una seqüència de pèptids donada es calculen fàcilment. Tanmateix, també cal assignar els valors d'intensitat a les masses.
+14065=Als ions B i Y se'ls assigna normalment la mateixa intensitat, mentre que l'ió A és normalment 5 vegades menys intens. S'hi poden afegir els ions-estrep (masses ± 1 Da dels ions A i Y), a més d'incloure-hi les pèrdues neutres (H2O i NH3).
+
+; Frames, labels, and checkboxes
+14100=Opcions de normalització per a dades importades
+14110=A&grupa els ions semblants (agrupa dades)
+14115=Finestra de masses
+14120=Intensitat normalitzada
+14130=Nombre d'ions a utilitzar
+14140=Subdivisions de regions de masses
+14150=Intensitat iònica dels ions predits
+14160=Intensitat dels ions A
+14165=Intensitat dels ions B
+14170=Intensitat dels ions Y
+14180=Estreps dels ions B/Y
+14190=Pèrdues neutres
+14200=Frgamentation Spectrum Labels
+14210=Label main ions (a, b, y)
+14220=Label neutral loss ions
+14230=Emphasize Proline y ions
+14240=Spectrum Plotting Options
+14250=Fragmentation Data Color
+14255=Matching Ion Data Color
+14258=Click to change
+14260=Plot Fragmentation Spectrum Inverted
+14270=Auto-Label Peaks on Matching Ion Spectrum
+
+[frmSetValue]
+14500=Defineix el valor
+14510=&Defineix
+14520=&Inicia
+
+[frmProgress]
+14700=Progrés
+14710=Pausa
+14715=S'està preparant la pausa
+14720=Està en pausa
+14725=Reprenent
+14730=(Premeu ESC per avortar)
+14740=min. transcorreguts/restants
+
+[frmIsotopicDistibution]
+15000=Distribució isotòpica
+; Frames, labels, and checkboxes
+15050=Fórmula:
+15060=Resultats:
+15070=Càrrega:
+15100=&Histograma
+15105=&Auto-Label Peaks
+15110=&Calcula
+15120=Plot Data Color
+15126=Click to change
+15130=Plot Type
+15140=Sticks to Zero|Gaussian Peaks
+15145=Sticks to Zero|Gaussian Peaks|Lines Between Points
+15151=Resultats de la distribució isotòpica
+15160=Paste list of ions to compare
+15165=Clear List
+15170=Comparison list data points:
+15190=Options
+15195=Comparison List
+; Column headers in the results box
+15200=Abundàncies isotòpiques del
+15210=Massa/Càrrega
+15215=Neutral Mass
+15220=Fracció
+15230=Intensitat
+15300=Warning, the ion comparison list contains a large number of data points. Do you really want to convert each point to a Gaussian curve?
+15305=Large Data Point Count
+
+[frmAminoAcidModificationSymbols]
+15500=Amino Acid Modification Symbols Editor
+;Directions
+15550=Modified residues in an amino acid sequence are notated by placing a modification symbol directly after the residue's 1 letter or 3 letter abbreviation.
+15555=The phosphorylation symbol is defined separately because phosphorylated residues can lose a phosphate group during fragmentation.
+15560=As an example, if the phosphorylation symbol is *, then in the sequence 'GlyLeuTyr*' the tyrosine residue is phosphorylated.
+15565=Allowable symbols for user-defined modifications are
+15570=Modification symbols can be more than 1 character long, though it is suggested that you keep them to just 1 character long to make it easier for the parsing routine to correctly parse residues with multiple modifications.
+15575=If a residue has multiple modifications, then simply place the appropriate modification symbols after the residue, for example in 'FLE*#L' the E residue is modified by both the * and # modifications.
+15580=Modification masses can be negative values, as well as positive values.
+;Table Tool Tip
+15600=
+15601=Click to change a modification symbol
+; Table column headers
+15610=Symbol
+15620=Mass
+15640=Comment
+; Labels
+15700=Modification Symbols Defined
+15710=Single click to edit or remove. Click in blank row to add.
+15720=Standard Modifications
+15730=Phosphorylation Symbol:
+; Messages
+15750=The amino acid symbol modification will be updated with the parameters below. Select Remove to delete the modification symbol or Cancel to ignore any changes.
+15760=Warning, the new phosphorylation symbol is already being used for another modification. Do you really want to use this symbol for phosphorylation and consequently remove the other definition?
+15765=Modification Symbol Conflict
+15770=Are you sure you want to lose all changes?
+15775=Closing Edit Modification Symbols Window
+; Buttons
+15800=&Reset to Defaults
+15801=Resets modification symbols to defaults
+15810=&Add selected to list
+
+[frmDtaTxtFileBrowser]
+16000=_Dta.Txt File Browser
+; Labels
+16050=Scan Number Start
+16060=Scan Number End
+16070=Parent Ion MH+
+16080=Parent Ion Charge
+; Buttons
+16100=&Jump to scan
+16101=Shortcut is Ctrl+J
+16110=&Keep Window On Top
+
+[ErrorAndStatusMessages]
+20001=Element desconegut
+20003=Falta un parèntesi dret
+20004=Parèntesis desaparellats
+20005=No hi pot haver un 0 directament després d'un element o un guionet
+20006=Nombre massa llarg o bé només pot anar darrera [, -, ), o circumflex (^)
+20007=Nombre massa llarg
+20011=Els nombres han d'anar darrera un claudàtor esquerre, no darrera un claudàtor dret (a no ser que s'hagi activat l'opció 'tractar claudàtors com a parèntesis)
+20012=Hi ha d'haver un nombre darrera un claudàtor i/o el punt decimal
+20013=Falta un claudàtor dret, ]
+20014=Nombre mal col·locat; només hauria d'anar darrera un element, [,) , -, o circumflex (^)
+20015=Claudàtor desaparellat
+20016=No es poden gestionar claudàtors imbricats ni claudàtors dins hidrats múltiples (a no ser que s'hagi activat l'opció 'tractar claudàtors com a parèntesis)
+20018=Element desconegut
+20020=Hi ha d'haver un nombre de massa isotòpica després del circumflex (^)
+20022=Hi ha d'haver un element després de la massa isotòpica que segueix al circumflex (^)
+20023=No es permeten masses isotòpiques negatives després del circumflex (^)
+20024=No es permeten masses isotòpiques per a abreviatures
+20025=Hi ha d'haver un element després del primer coeficient del guionet
+20026=No es permeten masses isotòpiques per a abreviatures; D és una abreviatura
+20027=Els nombres no poden tenir més d'un punt decimal
+20028=Circular abbreviation reference; can't have an abbreviation referencing a second abbreviation that depends upon the first one
+20030=Invalid formula subtraction; one or more atoms (or too many atoms) in the right-hand formula are missing (or less abundant) in the left-hand formula
+20050=El valor objectiu és més gran que el 100%, un valor impossible
+20075=No es permeten lletres en la línia de la calculadora
+20076=Manca un parèntesi dret
+20077=Parèntesis desaparellats
+20078=Nombre mal col·locat; o nombre massa gran, massa petit o massa llarg
+20080=Operador mal col·locat
+20081=Una variable de seguiment és més petita o igual que 1; notifiqueu-ho al programador
+20082=Falta un operador
+20085=No es poden elevar nombres negatius a una potència decimal
+20086=No es pot elevar el zero a una potència negativa
+20087=No es pot elevar el zero a la potència zero
+20089=Hi ha d'haver un sol número positiu i negatiu després d'un circumflex (^)
+20090=Els nombres no poden tenir més d'un punt decimal
+20091=Heu provat de dividir un nombre per zero. Corregiu el problema i recalculeu.
+20092=No es permeten espais en les expressions matemàtiques
+20093=Useu el punt com a caràcter decimal
+20094=Useu una coma com a caràcter decimal
+20095=Hi ha d'haver un nombre després d'un punt decimal
+20100=Error en desar el fitxer d'abreviatures
+20110=S'ha tornat a crear el fitxer d'abreviatures
+20115=El fitxer antic s'ha reanomenat
+20120=No s'ha trobat l'encapçalament [AMINO ACIDS] dins el fitxer MWT_ABBR.DAT. Aquest encapçalament ha d'estar ubicat abans/per damunt l'encapçalament [ABBREVIATIONS].
+20130=No s'ha trobat l'encapçalament [ABBREVIATIONS] dins el fitxer MWT_ABBR.DAT. Aquest encapçalament ha d'estar ubicat abans/per damunt l'encapçalament [AMINO ACIDS].
+20135=Seleccioneu D'acord per continuar només amb abreviatures d'aminoàcids.
+20140=No s'ha trobat el fitxer d'abreviatures en el directori del programa
+20150=Error carregant/creant el fitxer d'abreviatures
+20160=S'ignora l'abreviatura -- Fórmula invàlida
+20170=S'ignora l'abreviatura duplicada
+20180=S'ignora l'abreviatura; caràcter invàlid
+20190=S'ignora l'abreviatura; massa llarga
+20200=S'ignora una línia invàlida
+20210=S'ha tornat a crear el fitxer d'elements per defecte
+20220=Possible massa incorrecta per a un element
+20230=Possible incertesa incorrecta per a un element
+20250=S'ignora la línia; símbol invàlid d'element
+20260=No s'ha trobat l'encapçalament [ELEMENTS] dins el fitxer MWT_ELEM.DAT. Aquest encapçalament ha d'estar ubicat dins el fitxer.
+20265=Seleccioneu D'acord per continuar amb els valors per defecte dels elements.
+20270=No s'ha trobat el fitxer d'elements dins el directori del programa
+20280=Error carregant/creant el fitxer d'elements
+20305=Es continua amb les llegendes per defecte.
+20320=Error desant el fitxer d'elements
+20330=Error carregant/desant el fitxer de valors
+20340=Seleccioneu D'acord per continuar sense carregar els valors per defecte ni les fórmules.
+20345=Si utilitzeu una unitat de només lectura, feu servir l'opció /X des de la línia de comandes per tal d'evitar aquest error.
+20350=Error
+20360=Error desant el fitxer d'opcions per defecte
+20380=Error desant el fitxer de valors i fórmules
+20400=Error carregant/creant el fitxer d'opcions per defecte
+20410=Seleccioneu D'acord per continuar carregant els valors per defecte de l'usuari.
+20440=El fitxer d'idioma no s'ha pogut obrir correctament o estava formatat incorrectament.
+20450=No es poden carregar les llegendes específiques de l'idioma
+20460=No s'ha pogut trobar el fitxer d'idioma en el directori del programa
+20470=No s'ha trobat el fitxer requerit per processar la massa molecular
+20480=No s'ha trobat el fitxer
+20490=Aquest fitxer ja existeix. El voleu substituir?
+20500=El fitxer existeix
+20510=Error llegint/escrivint el fitxer de processament per lots
+20515=Seleccioneu D'acord per avortar el fitxer de processament per lots.
+20520=Error dins el programa
+20530=No s'haurien d'haver trobat aquestes línies de codi. Notifiqueu-ho al programador.
+20550=No es pot utilitzar la calculadora de percentatges quan els claudàtors són tractats com a parèntesis. Podeu canviar el mode de reconeixement de claudàtors triant Canvia les preferències del programa, des del menú d'opcions.
+20555=La calculadora de percentatges no està disponible.
+20560=Existeix un nombre màxim de fórmules.
+20570=La fórmula actual està en blanc.
+20580=Desactiveu la calculadora de percentatges.
+20590=S'ha produït un sobreeiximent. Reduïu la mida dels nombres i recalculeu.
+20600=S'ha produït un error
+20605=Sortiu del programa i informeu-ne sisplau el programador. Seleccioneu Quant a, del menú d'ajuda per veure'n l'adreça electrònica.
+20610=No es permeten espais dins les fórmules.
+20620=Caràcter no vàlid
+20630=No es pot copiar a una nova fórmula.
+20650=La fórmula actual està en blanc.
+20655=La calculadora està activada (F11 per sortir del mode).
+20660=Atenció, la massa isotòpica és probablement massa gran per a l'element
+20662=Atenció, la massa isotòpica és probablement petita gran per a l'element
+20665=enfront de la massa atòmica mitjana del
+20670=Atenció, la massa isotòpica mitjana no pot ser Einstellungen
+; Frame labels
+11510=Wahl der Erkennungsart von Abkürzungen (F3):
+11520=Wahl der Interpretationsart der Schreibweise (F4):
+11530=Wahl der Standard-Abweichung (F12):
+11540=Wahl des Atomgewicht-Modus beim Formel-Finder:
+11550=Beendigungsart des Programms
+; Buttons
+11600=&Einstellungen abspeichern
+11610=&Zurücksetzen
+; Option Buttons
+11650=Typische
+11651=Alle Abkürzungen ausser Aminosäuren erkennen
+11655=Aminosäuren + Typische
+11656=Alle Abkürzungen inklusive Aminosäuren erkennen
+11660=Ausschalten
+11661=Keine Abkürzungen erkennen
+11665=Klein- in Grossbuchstaben umwandeln
+11666=Gross/Kleinschreibung während des Einlesens der Formel wenn nötig anpassen
+11670=Exakte Gross/Kleinschreibung
+11671=Erfordert vom Benutzer die Eingabe der Formeln in korrekter Gross/Kleinschreibung
+11675=Automatische Erkennung
+11676=Kann beliebig geschriebene Formeln erkennen, ohne die Gross/Kleinschreibung anzupassen
+11680=Kurz
+11681=Die Anzeige der Standard-Abweichung wird auf vier Dezimalstellen gerundet
+11685=Wissenschaftlich
+11686=Die Standard-Abweichung wird in wissenschaftlicher Notation angezeigt
+11690=Dezimal
+11691=Die Standard-Abweichung wird mit allen verfügbaren Dezimalstellen angezeigt
+11695=Ausschalten
+11696=Die Standard-Abweichung wird nicht angezeigt (nur ganzzahlige Ergebnisse)
+11700=Bei Verlassen Escape-Taste zulassen, Bestätigung verlangen
+11701=Ermittelt, ob das Programm mittels Escape-Taste verlassen werden darf, und ob eine Bestätigung dafür verlangt werden soll
+11705=Escape-Taste zulassen, keine Bestätigung verlangen
+11710=Escape-Taste ignorieren; gegen Bestätigung beenden
+11715=Escape-Taste ignorieren; ohne Bestätigung beenden
+; CheckBoxes
+11750=&Nach Kalkulation weiterfahren (F9)
+11751=Nach der Berechnung eines Formelgewichtes zusätzliche neue Eingabelinie einrichten
+11760=&Betrachte Eckige Klammern als Runde Klammern
+11761=Behandle Eckige Klammern [ und ] als Runde Klammern, und nicht als Statthalter für den %-Ermittler
+11770=&Aktuelles Molekulargewicht automatisch kopieren (Ctrl+U)
+11771=Kopiere das Molekulargewicht der selektierten Formel nach der Kalkulation automatisch in die Zwischenablage
+11780=Berechne die &Ladung
+11781=Berechne die Ladung von Verbindungen (sehr rudimentär, kann keine Doppel- oder Dreifachbindungen etc erkennen)
+11800=Au&tomatisches Umschalten in den Isotopenreinen Gewichtsmodus
+11801=Schalte automatisch um zu isotopischen Atomgewichten, sobald der Formel-Finder gestartet wird
+11810=&Formel-Finder Gewichtsmodus-Warndialog auschalten
+11811=Zeige nie den Warnhinweis auf den aktuellen Gewichtsmodus beim Starten des Formel-Finders
+11820=A&m Ende automatisch Optionen, Werte, Formeln abspeichern
+11821=Beim Verlassen des Programms automatisch alle Einstellungen, Werte, und Formeln abspeichern
+11830=Zeige &Warn-Hinweise in der Statuszeile (F7)
+11831=Vorsicht vor Verwechslungen bei bestimmten Buchstaben-Kombinationen in der Formeleingabe (etwa Co gegen CO)
+11840=Zeige &den Atomgewicht-Schnellumschalter
+11841=Anzeige eines Schnellumschalters für die drei Atomgewichts-Modi unter der Formel-Eingabe
+11850=&Hinweise einblenden
+11851=Anzeige kurzer Hilfe-Texte beim Ueberfahren der Bedienelemente und Eingabefelder mit der Maus
+11860=A&ngewählte Textfelder hervorheben
+11861=Hebt das ganze Textfeld hervor, wenn es angewählt (mit der Maus angefahren) wird
+11870=&Verstecke inaktive Programmfenster
+11871=Verstecke das Hauptprogrammfenster, wenn Werkzeugfenster gestartet werden (zB Formel-Finder, Mol/Masse-Kalkulator, etc.)
+11881=Wählen Sie eine kleinere Zahl, falls das Formelfenster den Bildschirm zu sehr füllt. Nach Verminderung der Zahl muss das Programm neu gestartet werden. Die Maximalzahl hängt von der Bildschirmauflösung ab.
+11885=Maximalzahl anzeigbare Formeln.
+11890=Module to show at startup
+11896=Module to show when the program starts
+11898=Main Window|Formula Finder|Capillary Flow Calculator|Mole/Mass Converter|Peptide Seq Fragmentation Modeller|Amino Acid Notation Converter|Isotopic Distribution Modeller
+
+; Messages
+11900=Autosave Option für die Einstellungen gespeichert.
+11910=Auf Voreinstellungen zurückgesetzt.
+11920=Werte und Formeln gespeichert.
+11925=Werte und Formeln NICHT gespeichert, weil /x Kommandozeilen-Parameter aktiv.
+11930=Eingestellte Optionen gespeichert.
+11935=Eingestellte Optionen NICHT gespeichert, weil /x Kommandozeilen-Parameter aktiv.
+
+[frmFragmentationModelling]
+12000=Peptide Sequence Fragmentation Modelling
+; General Combo Boxes
+12010=1 letter notation|3 letter notation
+12011=Amino acid sequence notation type
+12020=&Match Ions
+; Textboxes
+12051=Enter amino acid sequence here
+12061=Shifts the loaded ions to be matched by the given amount to correct for post-translational modifications.
+; Frames, labels, and checkboxes
+12100=Sequence:
+12150=N and C Terminus
+12160=&N
+12170=&C
+12180=H (hydrogen)|HH+ (protonated)|C2OH3 (acetyl)|C5O2NH6 (pyroglu)|CONH2 (carbamyl)|C7H6NS (PTC)|(none)
+12190=OH (hydroxyl)|NH2 (amide)|(bare)
+12200=Ion Types
+12210=&A Ions
+12215=&B Ions
+12220=&Y Ions
+12230=Neutral Losses
+12236=Choose ions to which losses will be applied
+12240=Loss of H2O
+12250=Loss of NH3
+12255=Loss of PO4
+12260=Charge Options
+12270=&2+ charged ions
+12280=&Threshold
+12286=The 2+ m/z value will be computed for ions above this m/z
+12300=Ion Match Options
+12310=&Remove Precursor Ion
+12320=Ion Mass
+12330=Mass Window
+12340=&Ion Matching Window
+12350=Da
+12355=Alignment &Offset
+12360=Ion Statistics
+12370=Loaded
+12375=Remaining after binning
+12380=Within tolerance
+12385=Precursor not found
+12390=Precursor removed
+12395=Precursor not removed
+12400=Matches
+12405=Score
+12410=Mass Information
+12420=Element Mode
+12425=Average
+12430=Isotopic
+
+; Column titles in grids
+; Note: # means 'number', Immon. means 'immonium', and Seq. means 'sequence'
+12500=#
+12510=Immon.
+12520=Seq.
+12550=Mass
+12560=Intensity
+12570=Symbol
+
+; Menu Items
+12800=&Load Sequence Info
+12810=&Save Sequence Info
+12820=Load List of &Ions or .Dta file to Match
+12830=&Close
+12840=&Copy Predicted Ions
+12850=Copy Predicted Ions as &RTF
+12855=Copy Predicted Ions as Html
+12860=&Paste List of Ions to Match
+12865=Copy Sequence Molecular &Weight
+12870=Clear Match Ion &List
+12880=List of &Ions to Match
+12900=&Mass Spectrum
+12910=&Update Spectrum on Change
+12915=&Dta.Txt File Browser
+12920=Ion Match List &Options
+12925=Edit Residue &Modification Symbols
+12930=&Automatically Align Ions to Match
+12940=&Fragmentation Modelling
+12950=&Copy Selected Ions
+12960=&Delete All (Clear list)
+
+[frmMsPlot]
+13000=Plot
+; The following is an abbreviation for the word 'Location'
+13010=Loc
+
+; Legend Items
+13030=Predicted Ions
+13035=Loaded Ions
+
+; Menu Items
+13100=&Export Data
+13150=&Plot Type
+13160=&Sticks To Zero
+13170=&Gaussian Peaks
+13180=Set Effective &Resolution
+13190=X Axis Gridlines
+13200=Y Axis Gridlines
+13210=&Ticks to label (approx.)
+13220=&X Axis
+13230=&Y Axis
+13235=Plot &Quality (affects speed)
+13240=&Gaussian Representation Quality
+13245=&Approximation Factor
+13250=Set &X Range
+13260=Set &Y Range
+13270=&Autoscale Y Axis
+13280=&Fix mimimum Y at zero
+13290=&Zoom Out to Previous
+13295=Ctrl+Z or Right Click
+13300=Zoom Out to Show All
+13310=&Cursor Mode
+13315=Space Enables Move
+13320=&Zoom
+13330=&Move
+13340=&Show Current Position
+13342=Show &Legend
+13345=Reset to &Default Options
+13350=&Zoom Box
+13360=Zoom &In
+13365=Left Click
+13370=Zoom In Horizontal
+13380=Zoom In Vertical
+13390=Zoom &Out
+13400=Zoom Out Horizontal
+13410=Zoom Out Vertical
+
+[frmIonMatchOptions]
+14000=Ion Matching Options
+; Buttons
+14010=&Reset to Defaults
+14020=Edit Auto-Label Options
+
+; Explanations
+14050=When a list of ions is imported into the program, ions of similar mass may optionally be grouped together via a binning process to reduce the total number of data points. Next, ions around the precursor ion may be removed.
+14055=Then, the intensities are normalized to the given maximum intensity and ordered by decreasing intensity. The top-most ions (number of ions to use) are divided into distinct mass regions and the ions in each region again normalized.
+14060=The masses of the predicted ions for a given peptide sequence are easily computed. However, intensity values must also be assigned to the masses.
+14065=The B and Y ions are typically assigned the same intensity while the A ion is typically 5 times less intense. Shoulder ions (masses ± 1 Da from the B and Y ions) can be added, in addition to including neutral losses (H2O and NH3).
+
+; Frames, labels, and checkboxes
+14100=Normalization Options for Imported Data
+14110=&Group Similar Ions (Bin Data)
+14115=Mass Window
+14120=Normalized Intensity
+14130=Number of Ions to Use
+14140=Mass region subdivisions
+14150=Ion Intensities of Predicted Ions
+14160=A Ion Intensity
+14165=B Ion Intensity
+14170=Y Ion Intensity
+14180=B/Y Ion Shoulders
+14190=Neutral Losses
+14200=Frgamentation Spectrum Labels
+14210=Label main ions (a, b, y)
+14220=Label neutral loss ions
+14230=Emphasize Proline y ions
+14240=Spectrum Plotting Options
+14250=Fragmentation Data Color
+14255=Matching Ion Data Color
+14258=Click to change
+14260=Plot Fragmentation Spectrum Inverted
+14270=Auto-Label Peaks on Matching Ion Spectrum
+
+[frmSetValue]
+14500=Set Value
+14510=&Set
+14520=&Start
+
+[frmProgress]
+14700=Progress
+14710=Click to Pause
+14715=Preparing to Pause
+14720=Paused
+14725=Resuming
+14730=(Press Escape to abort)
+14740=min. elapsed/remaining
+
+[frmIsotopicDistibution]
+15000=Isotopic Distribution
+; Frames, labels, and checkboxes
+15050=Formula:
+15060=Results:
+15070=Ladung:
+15100=&Plot Results
+15105=&Auto-Label Peaks
+15110=&Compute
+15120=Plot Data Color
+15126=Click to change
+15130=Plot Type
+15140=Sticks to Zero|Gaussian Peaks
+15145=Sticks to Zero|Gaussian Peaks|Lines Between Points
+15151=Isotopic distribution results
+15160=Paste list of ions to compare
+15165=Clear List
+15170=Comparison list data points:
+15190=Options
+15195=Comparison List
+; Column headers in the results box
+15200=Isotopic Abundances for
+15210=Mass/Charge
+15215=Neutral Mass
+15220=Fraction
+15230=Intensity
+15300=Warning, the ion comparison list contains a large number of data points. Do you really want to convert each point to a Gaussian curve?
+15305=Large Data Point Count
+
+[frmAminoAcidModificationSymbols]
+15500=Amino Acid Modification Symbols Editor
+;Directions
+15550=Modified residues in an amino acid sequence are notated by placing a modification symbol directly after the residue's 1 letter or 3 letter abbreviation.
+15555=The phosphorylation symbol is defined separately because phosphorylated residues can lose a phosphate group during fragmentation.
+15560=As an example, if the phosphorylation symbol is *, then in the sequence 'GlyLeuTyr*' the tyrosine residue is phosphorylated.
+15565=Allowable symbols for user-defined modifications are
+15570=Modification symbols can be more than 1 character long, though it is suggested that you keep them to just 1 character long to make it easier for the parsing routine to correctly parse residues with multiple modifications.
+15575=If a residue has multiple modifications, then simply place the appropriate modification symbols after the residue, for example in 'FLE*#L' the E residue is modified by both the * and # modifications.
+15580=Modification masses can be negative values, as well as positive values.
+;Table Tool Tip
+15600=
+15601=Click to change a modification symbol
+; Table column headers
+15610=Symbol
+15620=Mass
+15640=Comment
+; Labels
+15700=Modification Symbols Defined
+15710=Single click to edit or remove. Click in blank row to add.
+15720=Standard Modifications
+15730=Phosphorylation Symbol:
+; Messages
+15750=The amino acid symbol modification will be updated with the parameters below. Select Remove to delete the modification symbol or Cancel to ignore any changes.
+15760=Warning, the new phosphorylation symbol is already being used for another modification. Do you really want to use this symbol for phosphorylation and consequently remove the other definition?
+15765=Modification Symbol Conflict
+15770=Are you sure you want to lose all changes?
+15775=Closing Edit Modification Symbols Window
+; Buttons
+15800=&Reset to Defaults
+15801=Resets modification symbols to defaults
+15810=&Add selected to list
+
+[frmDtaTxtFileBrowser]
+16000=_Dta.Txt File Browser
+; Labels
+16050=Scan Number Start
+16060=Scan Number End
+16070=Parent Ion MH+
+16080=Parent Ion Charge
+; Buttons
+16100=&Jump to scan
+16101=Shortcut is Ctrl+J
+16110=&Keep Window On Top
+
+[ErrorAndStatusMessages]
+20001=Unbekanntes Element
+20003=Fehlende Abschlussklammern
+20004=Klammern ohne Entsprechung gefunden
+20005=Null (0) direkt nach Abschlussklammer, Element oder Bindestrich (-) nicht erlaubt
+20006=Eingegebene Zahl zu gross oder nur nach [, -, ), oder ^ (Kapitälchen) erlaubt
+20007=Eingegebene Zahl zu gross
+20011=Zahlen sollten auf linke eckige Klammern folgen, nicht auf rechte eckige Klammern (ausser 'Betrachte eckige als runde Klammern' ist eingeschaltet)
+20012=Nach jeder eckigen Klammer und/oder einem Dezimalpunkt muss eine Zahl folgen
+20013=Eckige Abschlussklammer (]) fehlt
+20014=Falsch platzierte Zahl; sollte immer nach einem Element, [, ), -, oder Kapitälchen (^) stehen
+20015=Eckige Klammer ohne Gegenstück
+20016=Verschachtelte eckige Klammern oder eckige Klammern innerhalb von Mehrfach-Hydraten nicht erlaubt (ausser 'Betrachte eckige als runde Klammern' ist eingeschaltet)
+20018=Unbekanntes Element
+20020=Nach einem Kapitälchen (^) muss die Massenzahl eines Isotops folgen
+20022=Einem Kapitälchen (^), gefolgt von einer isotopischen Massenzahl, muss wiederum ein Element folgen
+20023=Nach einem Kapitälchen (^) sind negative isotopische Massenzahlen nicht erlaubt
+20024=Isotopische Massenzahlen für Abkürzungen sind nicht erlaubt
+20025=Nach einem Koeffizient, der einen Bindestrich anführt, muss ein Element folgen
+20026=Bei Abkürzungen sind isotopische Massen nicht erlaubt; D ist eine Abkürzung
+20027=Zahlen können nur einen einzigen Dezimalpunkt enthalten
+20028=Circular abbreviation reference; can't have an abbreviation referencing a second abbreviation that depends upon the first one
+20030=Invalid formula subtraction; one or more atoms (or too many atoms) in the right-hand formula are missing (or less abundant) in the left-hand formula
+20050=Ziel-Wert ist grösser als 100%, unmöglich bei Zusammensetzungen
+20075=In der Taschenrechner-Eingabe sind keine Buchstaben erlaubt
+20076=Runde Abschlussklammer fehlt
+20077=Runde Klammern ohne Gegenstück
+20078=Zahl am falschen Ort, zu gross, zu klein, oder zu lang
+20080=Operator-Zeichen am falschen Ort
+20081=Track-Variable ist kleiner oder gleich 1; Programmfehler; bitte Programm-Autor benachrichtigen
+20082=Fehlendes Operator-Zeichen.
+20085=Negative Zahlen hoch eine Dezimalzahl sind nicht erlaubt
+20086=Null hoch eine negative Zahl ist nicht möglich
+20087=Null in der nullten Potenz ist nicht möglich
+20089=Nach einem Kapitälchen (^) muss eine einzige positive oder negative Zahl folgen
+20090=Zahlen können nur einen einzigen Dezimalpunkt enthalten
+20091=Division durch Null nicht erlaubt. Fehler korrigieren und nochmals probieren
+20092=Leerschläge (Abstandszeichen) sind in mathematischen Ausdrücken nicht erlaubt
+20093=Verwende Punkt zur Anzeige von Dezimalstellen
+20094=Verwende Komma zur Anzeige von Dezimalstellen
+20095=Nach dem Dezimalpunkt muss eine Zahl folgen
+20100=Fehler beim Speichern der Abkürzungs-Datei MWT_ABBR.DAT
+20110=Die voreingestellte Abkürzungs-Datei wurde neu erzeugt.
+20115=Die vorherige Datei wurde umbenannt.
+20120=Kopfzeile [AMINO ACIDS] nicht gefunden in der Datei MWT_ABBR.DAT. Diese Kopfzeile muss VOR der Kopfzeile [ABBREVIATIONS] stehen.
+20130=Kopfzeile [ABBREVIATIONS] nicht gefunden in der Datei MWT_ABBR.DAT. Diese Kopfzeile muss VOR der Kopfzeile [AMINO ACIDS] stehen.
+20135='OK' drücken, um nur mit den Aminosäuren-Abkürzungen weiterzumachen.
+20140=Abkürzungsdatei im Verzeichnis des Programms nicht gefunden.
+20150=Fehler beim Laden/Erzeugen der Abkürzungs-Datei
+20160=Ignoriere Abkürzung -- Formel ist ungültig
+20170=Ignoriere Duplizierte Abkürzung
+20180=Ignoriere Abkürzung; Ungültiges Zeichen
+20190=Ignoriere Abkürzung; zu lang
+20200=Ignoriere ungültige Zeile
+20210=Die voreingestellte Elementen-Datei wurde neu erzeugt.
+20220=Element hat möglicherweise inkorrektes Atomgewicht gesetzt
+20230=Element hat möglicherweise inkorrekte Unschärfe gesetzt
+20250=Ignoriere Zeile; Ungültiges Element-Symbol
+20260=Kopfzeile [ELEMENTS] nicht gefunden in der Datei MWT_ELEM.DAT. Datei muss diese Kopfzeile enthalten.
+20265='OK' drücken, um nur mit voreingestellten Element-Werten weiterzufahren.
+20270=Die Elementendatei im Ordner des Programms nicht gefunden.
+20280=Fehler beim Laden/Erzeugen der Elementen-Datei
+20305=Fahre mit der voreingestellten Sprache weiter.
+20320=Fehler beim Speichern der Elementen-Datei
+20330=Fehler beim Laden/Erzeugen der Werte-Datei
+20340='OK' drücken, um weiterzufahren, ohne die voreingestellten Werte und Formeln zu laden.
+20345=Falls Sie ein schreibgeschütztes Medium benutzen, sollten Sie auf der Kommando-Zeile den /X Schalter setzen, um diesen Fehler zu vermeiden.
+20350=Fehler
+20360=Fehler beim Speichern der Programmvoreinstellungen-Datei
+20380=Fehler beim Speichern der Werte- und Formeln-Datei (MWT_NUM.DAT)
+20400=Fehler beim Laden/Erzeugen der Programm-Initialisierungs-Datei
+20410='OK' drücken, um weiterzufahren, ohne die benutzerseitigen Voreinstellungen zu laden.
+20440=Die sprachspezifische Initialisierungs-Datei konnte nicht geöffnet werden, oder hat ein falsches Format
+20450=Eine sprachspezifische Initialisierung konnte nicht geladen werden
+20460=Eine sprachspezifische Initialisierungs-Datei wurde nicht gefunden im Verzeichnis des Programms
+20470=Die Quell-Datei zur Berechnung von Molekulargewichten wurde nicht gefunden
+20480=Datei nicht gefunden
+20490=Die Datei existiert bereits. Ueberschreiben?
+20500=Die Datei existiert
+20510=Fehler beim Lesen/Schreiben von Dateien zur automatischen Bearbeitung
+20515='OK' drücken, um die automatische Dateibearbeitung zu beenden
+20520=Programmfehler
+20530=Das Programm ist in einen verbotenen Zustand geraten. Bitte benachrichtigen Sie den Programm-Autor.
+20550=Der %-Ermittler kann nicht benützt werden, wenn eckige Klammern als runde behandelt werden. In den Programmeinstellungen kann die Klammer-Erkennung umgeschaltet werden.
+20555=Der %-Ermittler ist nicht benützbar
+20560=Die Zahl der Felder für die Formel-Eingabe ist beschränkt.
+20570=Die aktuelle Formel-Eingabe ist leer.
+20580=Schalten Sie den %-Ermittler (F11) aus, bevor Sie eine neue Formel erzeugen.
+20590=Ein Ueberlauf-Fehler ist aufgetreten. Bitte Zahlen verkleinern und Berechnung nochmals starten.
+20600=Ein Fehler ist aufgetreten
+20605=Bitte beenden Sie das Programm und melden Sie den Fehler dem Programm-Autor. Die Email-Adresse ist im Fenster 'Ueber den Molekulargewicht-Kalkulator' angegeben.
+20610=Innerhalb einer Formel sind keine Leerschläge (Abstandszeichen) erlaubt
+20620=Ungültiges Zeichen
+20630=Kopieren in eine neue Formel-Eingabe nicht möglich.
+20650=Die aktuelle Formel ist leer.
+20655=Der %-Ermittler ist eingeschaltet (mit F11 ausschalten).
+20660=Warnung, die isotopische Massenzahl ist vermutlich zu gross für das Element
+20662=Warnung, die isotopische Massenzahl ist vermutlich zu klein für das Element
+20665=vs avg atomic wt of
+20670=Warnung, isotopische Massenzahl ist unmöglich klein für das Element
+20675=Protonen
+20680=Notiz: Exakte Gross/Kleinschreibung eingeschaltet
+20685=Notiz: Für %-Ermittler muss eine linke eckige Klammer, gefolgt von einem x in der Formel stehen
+20690=Notiz: Eckige werden als runde Klammern behandelt
+20700=One or more elements must be checked.
+20705=Maximum hits must be greater than 0.
+20710=Maximum hits must be less than
+20715=Minimum number of elements must be 0 or greater.
+20720=Minimum number of elements must be less than maximum number of elements.
+20725=Maximum number of elements must be less than 65,025
+20730=Bei selbstdefinierten Elementen muss ein Atomgewicht eingegeben werden.
+20735=Bei selbstdefinierten Elementen muss das Atomgewicht grösser als Null sein.
+20740=Das gesuchte Molekulargewicht muss eingegeben werden.
+20745=Das gesuchte Molekulargewicht muss grösser als Null sein.
+20755=Ein maximales Molekulargewicht muss eingegeben werden.
+20760=Das maximale Molekulargewicht muss grösser als Null sein.
+20765=Der gesuchte Anteil des Elements muss eingegeben werden
+20770=Der gesuchte Anteil des Elements muss grösser als Null sein.
+20775=Custom elemental weights must contain only numbers or only letters. If letters are used, they must be for a single valid elemental symbol or abbreviation.
+20780=Custom elemental weight is empty. If letters are used, they must be for a single valid elemental symbol or abbreviation.
+20785=Unbekanntes Element-Symbol, Atom-Nummer oder Abkürzung bei einem selbstdefinierten Element.
+20790=Nur ein einziges Element-Symbol oder eine einzige Abkürzung sind erlaubt.
+20800=Vorsicht, es wurden keine Abkürzungen geladen - die Anweisung hat keinen Effekt.
+20805=Cannot handle fractional numbers of atoms
+
+20900=Error Reading/Writing sequence information file.
+20910=Ions are already present in the ion list. Replace with new ions?
+20920=Replace Existing Ions
+20930=Loading Ion List
+20940=Process aborted
+20945=Aborted
+20950=Normalizing ions
+20960=Normalizing by region
+20965=Sorting by Intensity
+20970=Matching Ions
+20980=The clipboard is empty. No ions to paste.
+20985=No ions
+20990=Pasting ion list
+21000=Determining number of ions in list
+21010=Parsing list
+21020=No valid ions were found on the clipboard. A valid ion list is a list of mass and intensity pairs, separated by commas, tabs, or spaces. One mass/intensity pair should be present per line.
+21030=Error writing data to file
+21040=Set Range
+21050=Start Val
+21055=End Val
+21060=Set X Axis Range
+21065=Set Y Axis Range
+21070=Enter a new Gaussian Representation quality factor. Higher numbers result in smoother Gaussian curves, but slower updates. Valid range is 1 to 50, default is 20.
+21072=Gaussian Representation Quality
+21075=Enter a new plotting approximation factor. Higher numbers result in faster updates, but give a less accurate graphical representation when viewing a wide mass range (zoomed out). Valid range is 1 to 50, default is 10.
+21077=Plotting Approximation Factor
+21080=Resolving Power Specifications
+21090=Resolving Power
+21100=X Value of Specification
+21110=Please enter the approximate number of ticks to label on the axis
+21115=Axis Ticks
+21120=Creating Gaussian Representation
+21130=Preparing plot
+21135=Drawing plot
+21140=Are you sure you want to restore the default plotting options?
+21145=Restore Default Options
+21150=Auto Align Ions
+21155=Maximum Offset
+21160=Offset Increment
+21165=Aligning Ions
+
+21500=All Files
+21510=Text Files
+21515=txt
+21520=Data Files
+21525=csv
+21530=Sequence Files
+21535=seq
+21540=Ion List Files
+21545=txt
+21550=cap
+21555=Capillary Flow Info Files
+
+[CautionStatments]
+; Note: Caution statement keynames are case sensitive; i.e. Bi is different than BI
+; You may add new caution statements if desired; however, you will need to save
+; the file with a name other than Lang_English and change the Language= key
+; since this file is not loaded if the language is English
+22000=Vorsicht
+Bi=Mit Bi ist Wismut gemeint; mit BI ist Bor-Jod gemeint.
+Bk=Mit Bk ist Berkelium gemeint; mit BK ist Bor-Kalium gemeint.
+Bu=Mit Bu ist Butyl- gemeint; mit BU ist Bor-Uran gemeint.
+Cd=Mit Cd ist Kadmium gemeint; mit CD ist Kohlenstoff-Deuterium gemeint.
+Cf=Mit Cf ist Californium gemeint; mit CF ist Kohlenstoff-Fluor gemeint.
+Co=Mit Co ist Kobalt gemeint; mit CO ist Kohlenstoff-Sauerstoff gemeint.
+Cs=Mit Cs ist Cäsium gemeint; mit CS ist Kohlenstoff-Schwefel gemeint.
+Cu=Mit Cu ist Kupfer gemeint; mit CU ist Kohlenstoff-Uran gemeint.
+Dy=Mit Dy ist Dysprosium gemeint; mit DY ist Deuterium-Yttrium gemeint.
+Hf=Mit Hf ist Hafnium gemeint; mit HF ist Wasserstoff-Fluor gemeint.
+Ho=Mit Ho ist Holmium gemeint; mit HO ist Wasserstoff-Sauerstoff gemeint.
+In=Mit In ist Indium gemeint; mit IN ist Jod-Stickstoff gemeint.
+Nb=Mit Nb ist Niob gemeint; mit NB ist Stickstoff-Bor gemeint.
+Nd=Mit Nd ist Neodym gemeint; mit ND ist Stickstoff-Deuterium gemeint.
+Ni=Mit Ni ist Nickel gemeint; mit NI ist Stickstoff-Jod gemeint.
+No=Mit No ist Nobelium gemeint; mit NO ist Stickstoff-Sauerstoff gemeint.
+Np=Mit Np ist Neptunium gemeint; mit NP ist Stickstoff-Phosphor gemeint.
+Os=Mit Os ist Osmium gemeint; mit OS ist Sauerstoff-Schwefel gemeint.
+Pd=Mit Pd ist Palladium gemeint; mit PD ist Phosphor-Deuterium gemeint.
+Ph=Mit Ph ist Phenyl- gemeint, mit PH ist Phosphor-Stickstoff gemeint.
+Pu=Mit Pu ist Plutonium gemeint; mit PU ist Phosphor-Uran gemeint.
+Py=Mit Py ist Pyridin gemeint; mit PY ist Phosphor-Yttrium gemeint.
+Sb=Mit Sb ist Antimon gemeint; mit SB ist Schwefel-Bor gemeint.
+Sc=Mit Sc ist Scandium gemeint; mit SC ist Schwefel-Kohlenstoff gemeint.
+Si=Mit Si ist Silizium gemeint; mit SI ist Schwefel-Jod gemeint.
+Sn=Mit Sn ist Zinn gemeint; mit SN ist Schwefel-Stickstoff gemeint.
+TI=Mit TI ist Tritium-Jod gemeint, mit Ti ist Titan gemeint.
+Yb=Mit Yb ist Ytterbium gemeint; mit YB ist Yttrium-Bor gemeint.
+BPY=Mit BPY ist Bor-Phosphor-Yttrium gemeint; mit Bpy ist Bipyridin gemeint.
+BPy=Mit BPy ist Bor-Pyridin gemeint; mit Bpy ist Bipyridin gemeint.
+Bpy=Mit Bpy ist Bipyridin gemeint.
+Cys=Mit Cys ist Cystein gemeint; mit CYS ist Kohlenstoff-Yttrium-Schwefel gemeint.
+His=Mit His ist Histidin gemeint; mit HIS ist Wassrstoff-Jod-Schwefel gemeint.
+Hoh=Mit HoH ist Holmium-Wasserstoff gemeint; mit HOH ist Wasserstoff-Sauerstoff-Wasserstoff (aka-Wasser) gemeint.
+Hyp=Mit Hyp ist Hydroxyprolin gemeint; mit HYP ist Wasserstoff-Yttrium-Phosphor gemeint.
+OAc=Mit OAc ist Sauerstoff-Actinium gemeint; mit Oac ist Acetat gemeint.
+Oac=Mit Oac ist Acetat gemeint.
+Pro=Mit Pro ist Prolin gemeint; mit PrO ist Praseodym-Sauerstoff gemeint.
+PrO=Mit Pro ist Proline gemeint; mit PrO ist Praseodym-Sauerstoff gemeint.
+Val=Mit Val ist Valin gemeint; mit VAl ist Vanadium-Aluminium gemeint.
+VAl=Mit Val ist Valin gemeint; mit VAl ist Vanadium-Aluminium gemeint.
diff --git a/lang_portuguese.ini b/lang_portuguese.ini
new file mode 100644
index 0000000..83b51d7
--- /dev/null
+++ b/lang_portuguese.ini
@@ -0,0 +1,1107 @@
+; Language customization file for the Molecular Weight Calculator program by Matthew Monroe
+; Contact at alchemistmatt@yahoo.com and http://come.to/alchemistmatt/ or http://www.alchemistmatt.com/
+;
+; When customizing the phrases in this file, the ampersand symbol (&) signifies a
+; keyboard shortcut. For example, the default value for key 1000 is &File. When
+; running the program, the F in File will be underlined and the user may press Alt-F
+; to access the File menu (in addition to clicking on the file menu)
+; To improve usability of the program, please try to include the & symbol in menu items
+; and buttons. Note, however, that if two controls on the same form have the same &
+; shortcut, they will not respond to the alt key in the usual way.
+;
+; In this file, items surround by brackets [] are section headers -- the program ignores them
+; when parsing the file. The key values (1000, 1010, 1020, etc.) should not be changed, with
+; the exception that new caution statements may be added at the end of the file.
+; Lines beginning with a semicolon (;) are also ignored since they are treated as comments
+; However, you should not place a ; at the end of a line with an actual key and caption.
+;
+; Keys with multiple values separated by a vertical line (|) represent multiple items loaded
+; into a ComboBox control. When translating to other languages, you must keep the same number
+; of items in the list, or program functionality will be lost. For example, key 7070 contains
+; hours|minutes|seconds Thus, hours, minutes, and seconds will be loaded into a control, from
+; which the user may select one of them. In Spanish, you would use 7070=horas|segundos|minutos
+;
+; If you create a new .Ini file for a foreign language and would like it posted on my
+; web page, simply e-mail it to me.
+
+; Portuguese translation generously provided by Alexandre R Soares; http://geocities.yahoo.com.br/ntegti
+
+
+[Language]
+Language=Português
+
+
+[frmMain Menus]
+; Menu Items
+1000=&Arquivo
+1010=Editar &Tabela de Elementos
+1020=Editar &Abreviaturas
+1030=&Calcular massas em arquivo texto
+1040=Im&primir
+1050=&Sair
+1500=&Editar
+1505=&Undo
+1510=&Recortar
+1520=&Copiar
+1530=&Colar
+1540=&Limpar
+1545=Select &All
+1550=Copiar Fórmula como &RTF
+1560=Copiar Massa Molecular
+1570=Copiar Composição P&ercentual
+1580=Duplicar &Fórmula
+1590=Apagar T&udo
+1600=Apagar Fórmula
+1610=E&xpandir Abreviaturas
+1620=Converter para Fórmula &Empírica
+2000=&Ver
+2010=Ver &Tudo
+2020=Visão &Simples
+2030=Resolver &Percentual
+2040=&Desliga
+2050=&Liga
+2500=&Ferramentas
+2510=Cálculos &Mol/Massa/Solução
+2520=Encontre &Fórmula
+2530=Conversor &Aminoácido
+2533=Modelagem de Seqüência de &Peptídio
+2536=Modelagem de Distribuição &Isotópica
+2538=Show Isotopic &Distribution for Current Formula
+2540=&Calculadora
+2550=Calculadora de Fluxo Cap&ilar
+3000=&Opções
+3010=Escolher &Idioma (Language)
+3020=Alterar &Preferências
+3030=Al&terar Fonte
+3040=Manter no &Topo
+3050=&Salvar e Restaurar Padrão
+3060=&Restaurar Padrão e Fórmulas
+3070=Salvar &Valores e Fórmulas Agora
+3500=Aj&uda
+3510=&Visão Geral
+3530=&Mostrar Dicas
+3540=&Sobre MWT
+
+[frmMain Status Messages and Verification Messages]
+3600=A linha completa é
+3605=Zooming
+3610=Tem certeza que deseja converter essa fórmula em empírica?
+3615=Converter em Fórmula Empírica
+3620=Tem certeza que deseja apagar essa fórmula?
+3625=Apagar a Fórmula
+3630=Tem certeza que deseja expandir as abreviaturas dessa fórmula para seus equivalentes elementais?
+3635=Expandir Abreviaturas
+3640=Restaurar padrão e fórmulas eliminará as fórmulas atuais. Tem certeza que deseja fazê-lo?
+3645=Restaurar Valores e Fórmulas
+3650=Modifique a porcentagem indicada para o elemento no Percent Solver. Selecione Restaurar para desmarcar a porcentagem ou Cancelar para ignorar alterações.
+3660=Use Page Up/Down ou setas para mover (F11 sai do modo Percent Solver).
+3665=Pressione Enter ou Clique para alterar a percentagem (F11 sai do modo Percent Solver).
+3670=Pronto
+3700=Calculando, prima qualquer tecla ou clique no mouse para parar.
+3710=x é
+3720=Valor Calculado
+3730=Procurado
+3740=Diferença para o Indicado
+3750=% Solver Ativado
+3760=Resultados do MWT
+3770=Valores e fórmulas padrão restaurados.
+3780=Tem certeza que deseja apagar todas as fórmulas?
+3785=Apagar todas as Fórmulas
+3790=Tem certeza que deseja sair?
+3795=Sair do Programa
+3800=Carregando Abreviaturas
+3810=Carregando Elementos
+3820=(usando massas atômicas médias)
+3830=(usando massas isotópicas elementais)
+3840=(usando massas isotópicas inteiras)
+3850=Alteração de idioma salva.
+
+[Phrases common throughout application]
+4000=&Fechar
+4010=&Ok
+4020=&Cancelar
+4030=Sa&ir
+; The following is the abbreviation for Molecular Weight
+; It must be exactly two letters long
+4040=MM
+4050=Aviso
+4060=Yes
+4065=No
+
+[frmMain]
+; Form Caption
+4900=Molecular Weight Calculator
+; Labels
+5000=Fórmula
+5010=Modo de Massa
+5020=&Média
+5021=Usar massas médias dos elementos
+5030=&Isotópico
+5031=Usar massa do isótopo mais comum
+5040=In&teiro
+5041=Usar massa inteira do isótopo mais comum
+; TextBoxes
+5051=Escreva a fórmula molecular aqui
+; Buttons
+5100=&Calcular
+5101=Determina a massa molecular da fórmula
+5110=&Nova Fórmula
+5111=Adiciona nova fórmula à lista
+5116=Mostra nova fórmula
+; Grid control
+5201=Clique para estabelecer ou restabelecer um valor alvo
+; Status control
+5301=Duplo clique para expandir linha de status
+5350=MWT já está sendo usado. Tem certeza que deseja abrir outra cópia?
+5355=Em uso
+
+[frmAboutBox]
+5500=Sobre MWT
+5510=Esse programa é Freeware; distribuição livre
+
+[frmIntro]
+5700=Carregando
+
+[frmAminoAcidConverter]
+; Form Caption
+6000=Registro de Conversão de Aminoácido
+; Labels
+6010=Seqüência de Aminoácidos com uma letra
+6020=Seqüência de Aminoácidos com três letras
+; TextBoxes
+6031=Entre aqui a seqüência usando abreviaturas com 1 letra
+6041=Entre aqui a seqüência usando abreviaturas com 3 letras
+; Buttons
+6050=&Copiar seqüência de 3 letras para fórmula:
+6060=Copiar para &Fragmentation Modeller
+; CheckBoxes
+6080=&Adicionar espaço a cada 10 resíduos
+6090=&Separar resíduos usando traços
+
+[frmCalculator]
+; Form caption
+6500=Calculadora
+; Textbox
+6511=Entre aqui uma expressão matemática para avaliar
+; Buttons
+6520=&Calcular
+6521=Avaliar a expressão atual
+; Status control
+6610=Resultado
+
+[frmCapillaryCalcs]
+; Form Caption
+7000=Cálculo de Fluxo Capilar e Fração de Massa
+; Combo Boxes
+7010=Abrir Capilaridade Tubular|Capilaridade Fechada
+7011=Alternar entre capilaridade aberta e fechada.
+7020=Encontrar Pressão de Fundo|Comprimento da Coluna|Encontrar Diâmetro Interno|Encontrar Taxa de Fluxo Volumétrico|Encontrar Taxa de Fluxo usando Tempo Morto
+7030=psi|Pascals|quiloPascals|Atmosferas|Bar|Torr (mmHg)|dynes/cm^2
+7035=m|cm|mm|um|pol
+7040=Poise [g/(cm-s)]
+7050=mL/min|uL/min|nL/min
+7060=cm/h|mm/h|cm/min|mm/min|cm/s|mm/s
+7070=horas|minutos|segundos
+7080=mL|uL|nL|pL
+7090=Mol/L|miliMol/L|microMol/L|nanoMol/L|picoMol/L|fentoMol/L|atoMol/L|mg/dL|mg/mL|ug/mL|ng/mL|ug/uL|ng/uL
+7100=pmol/min|fmol/min|amol/min|pmol/s|fmol/s|amol/s
+7110=Mols|miliMols|microMols|nanoMols|picoMols|fentoMols|atoMols
+; Labels and frames
+7200=Pressão de Fundo
+7210=Comprimento da Coluna
+7220=Diâmetro Interno da Coluna
+7230=Viscosidade do Solvente
+7240=Diâmetro da Partícula
+7250=Taxa de Fluxo Volumétrico
+7260=Velocidade Linear
+7270=Tempo Morto da Coluna
+7280=Volume da Coluna
+7290=Porosidade Interparticular (epsilon)
+7300=Cálculos de Taxa de Massa
+7310=Concentração da Amostra
+7320=Tempo de Injeção
+7330=Taxa de Fluxo de Massa
+7340=Mols Injetados
+7350=Extra Column Broadening Calculations
+7360=Coeficiente de Difusão
+7370=Comprimento do Tubo Aberto
+7380=Tubo Aberto Diâmetro Interno
+7390=Largura Inicial do Pico (na base)
+7400=Velocidade Linear Ótima
+7410=(para partículas de 5 um)
+7420=Variança de Tempo
+7430=Variança Adicional
+7440=Resulting Peak Width
+7450=Incremento Porcentual
+7460=Fórmula Atual
+7480=Massa Molar
+7500=cm
+7510=um
+7520=cm^2/s
+7530=s
+7540=cm/s
+7550=s^2
+7560=s
+7570=g/mol
+; TextBoxes
+7601=Escreva a massa desejada para fazer os cálculos
+; Buttons
+7700=Mostrar/Ocultar Peak Broadening Calculations
+7710=&Ver Equações Explanatórias
+7730=Ver Equações
+; Option Buttons
+7750=&Usar massa molar da fórmula atual
+7760=&Empregar outro valor de massa molar
+; CheckBoxes
+7800=&Link para Cima
+; ToolTips
+7851=Valor típico de viscosidade é 0,0089 poise
+7861=Valor típico de porosidade é 0,4
+7871=Coeficiente de difusão típico para compostos orgânicos pequenos é 0,000001, i.e., 1E-6;; Typical value for peptides is 0,00005, i.e. 5E-5
+; Menus
+7900=&Load Values
+7910=&Save Values
+7950=&Capillary Flow Calculations
+
+[frmChangeFont]
+; Form Caption
+8000=Alterar Fonte
+; Combo Boxes
+; Labels
+8060=Alterar Fonte para:
+8070=Tamanho:
+; Buttons
+
+[frmChangeValue]
+; Form Caption
+8200=Alterar Valor
+; Buttons
+8210=&Alterar para Padrão
+
+[frmChangeLanguage]
+8400=Escolher Idioma
+; Labels
+8410=Os idiomas disponíveis são mostrados abaixo. Por favor, escolha o idioma que deseja usar.
+8420=Arquivos de idioma não disponíveis. Visite a homepage do autor para download de outros idiomas.
+
+[frmDiff]
+8600=Percent Solver Differences
+8610=&Copiar
+8611=Copiar resultados para o clipboard
+
+[frmEditAbbrev]
+9000=Editar Abreviaturas
+; Buttons
+9010=&Alterar para Padrão
+9011=Reestabelecer padrão de abreviaturas
+9020=&Remover
+; Messages
+9050=Máximo encontrado
+9060=Desculpe-me, são permitidas até 500 abreviaturas.
+9090=A abreviatura ou fórmula molecular será alterada para a que você digitar. Selecione Remover para deletar a abreviatura ou Cancelar para ignorar qualquer alteração.
+9100=Tem certeza que deseja perder todas as alterações?
+9105=Fechando Caixa de Edição de Abreviaturas
+9110=Tem certeza que deseja restaurar para as abreviaturas padrão?
+9115=Restaurar para padrão
+9120=Warning, test usage of the new/updated abbreviation did not give the same mass as the formula for the abbreviation. This probably indicates a problem with the abbreviation's formula.
+;Table Tool Tip
+9140=
+9141=Clique para fazer alteração
+9145=Symbol
+; Table Column Titles
+9150=Carga
+9160=Fórmula Molecular
+9170=Abrev. Normal
+9180=Nome do Aminoácido
+9190=1 letra
+9195=Comment
+
+[frmEditElem]
+9200=Editar Elementos
+; Buttons
+9210=&Restaurar Padrões
+9211=Restaurar massas para seus valores médios
+9220=&Restaurar
+9230=Usar Massas &Atômicas Médias
+9231=Altera todas as massas para valores médios encontrados na natureza
+9240=Usar massas do &Isótopo mais comum
+9241=Altera todas as massas para valor do isótopo mais comum (para alta resolução de espectrometria de massa)
+9245=Usar massa inteira &Nominal
+9246=Ajusta todas as massas elementais para a massa inteira nominal do isótopo mais comum do elemento (para espectroscopia de massa de baixa resolução)
+; Messages
+9250=A massa ou incerteza será substituída pelo valor digitado. Selecione Restaurar ou coloque em valor-padrão ou Cancelar para ignorar qualquer alteração.
+9260=Tem certeza que deseja alterar todos os valores para Massa elemental média?
+9265=Alterar para Massa Média
+9270=Tem certeza que deseja alterar todos os valores para Massa elemental isotópica?
+9275=Alterar para Massa Isotópica
+9280=Tem certeza que deseja alterar todos os valores para Massa Inteira?
+9285=Alterar para Massa Inteira
+9290=Tem certeza que deseja alterar todos os valores para valores padrão (Massa média)?
+9295=Alterar para padrão
+9300=Se executado, não poderá ser cancelado.
+9310=Tem certeza que deseja perder todasas alterações?
+9315=Fechando Caixa de Edição de Elementos
+;Table Tool Tip
+9340=
+9341=Clique para modificar a massa do elemento ou incerteza
+;Table Column Titles
+9350=Elemento
+9360=Massa
+9370=Incerteza
+; Combo boxes
+9380=Símbolo|Número Atômico|Incerteza|Carga
+9390=Classificar por:
+
+[frmEquationsBroadening]
+9500=Equações de Largura da Coluna Extra
+
+[frmEquationsOpenTube]
+9550=Equações para fluxo em um tubo aberto
+
+[frmEquationsPackedCapillary]
+9600=Equações para fluxo em capilaridade fechada
+
+[frmFinderModeWarn]
+; Instructions Label
+9700= Use o Formula Finder para encontrar a provável fórmula de um composto de massa monoisotópica conhecida (determinada tipicamente por Espectroscopia de Massa).
+9701=Por exemplo, para encontrar uma possível fórmula empírica de um composto formado por C e H cuja massa seja de 16,0312984 daltons. Ao executar a busca com uma tolerância de massa de 5000 ppm resulta em 3 compostos: H2N, CH4, e O. Se escolher 500 ppm, somente CH4 combinará, que é o composto apropriado.
+9702=Para conseguir corretamente esta resposta, o programa deve ser ajustado para o modo Massa Isotópica. Isto pode ser feito manualmente ao Editar a Tabela de Elementos (menu Arquivo), ou comutar automaticamente a esta modalidade (marque uma opção abaixo).
+9703=Você gostaria de:
+9705=O Fragmentation Modelling serve para predizer massas que devem ser encontradas no Espectrômetro de Massa quando se ioniza um peptídio, entra no instrumento, e fragmentos se juntam à cadeia principal do peptídio (peptide backbone).
+9706=O peptídio normalmente se fragmentas em cada ligação de amida. Por exemplo, o peptídio Gly-Leu-Tyr formará os fragmentos Gly-Leu, Leu-Tyr, Gly, Leu, e Tyr. Adicionalmente, a clivagem da ligação amida pode ocorrer em diferentes locais, resultando em variações de massa.
+; Buttons
+9720=&Continuar
+; Option Buttons
+9750=Alternar agora para Modo Massa &Isotópica.
+9760=Sempre alternar automaticamente para modo Massas Isotópicas.
+9770=Continuar usando Massas Médi&as.
+; CheckBoxes
+9780=Não mo&strar mais esta caixa de diálogo.
+
+[frmFinder]
+10000=Formula Finder
+; Labels
+10010=Selecione entre os elementos C, H, N e O ou adicione outros. A busca é feita por massa molecular ou composições percentuais. Clique em Calcular para encontrar os compostos.
+10020=Maior Massa da Fórmula:
+10030=Massa Molecular Indicada:
+10040=Tolerância da Massa:
+10050=% de Tolerância:
+10060=Mín
+10070=Máx
+10080=Elemento
+10090=%
+10100=Limite
+10105=Massa Atômica
+; Percent completed status messages
+10110=% Realizado
+10115=Escolhendo
+10120=Procurando
+10125=Trabalhando
+10130=Completado
+10135=compostos
+10140=Escolha Interrompida
+10145=Cálculos Interrompidos
+10150=Formatando
+10155=Feito
+10160=Formatação abortada
+; Listboxes & Textboxes
+10201=Duplo clique em qualquer linha para expandi-la
+10221=Faixa de tolerância na massa indicada
+10231=Quantidade possível de composições percentuais com a porcentagem indicada
+10241=Número máximo de compostos a procurar
+10251=Número mínimo de átomos no composto
+10256=Número máximo de átomos no composto
+10260=%
+10261=Composição porcentual de
+10270=# ou Elemento ou Abreviatura
+10271=Escreva uma massa para o elemento, um símbolo, ou uma abreviatura
+; Note the following is 'dm' in English, standing for 'delta mass' or the mass difference
+; of the given result's mass versus the target mass
+10280=dm
+; Note the following is 'ppm' in English, standing for 'parts per million'
+10285=ppm
+; Buttons
+10300=Opções do Formul&a Finder
+10301=Atalho: Ctrl+O
+10310=&Calcular
+10311=Encontre os compostos dentro dos parâmetros especificados
+10320=Im&primir ...
+10330=Copiar como RT&F
+10331=Copiar resultados para clipboard no formato RTF
+10340=Cop&iar
+10341=Copiar resultados para clipboard
+10345=&Display Iso Abundance
+10346=Display the Isotopic Distribution of the currently selected compound (Ctrl+D)
+; Option Buttons
+10350=Coincidir Massa &Molecular
+10360=Coincidir Composições &Porcentuais
+; CheckBoxes
+10370=Modo Ppm
+10380=Show Delta Mass
+10381=Note: Delta mass notation will change as the standard deviation mode is changed (F12 in the main window)
+; Elements (and Custom element phrase)
+10400=Carbono
+10405=Hidrogênio
+10410=Nitrogênio
+10415=Oxigênio
+10420=Escolha
+; Messages
+; Note that 10455 is also used with the Abort button
+10450=Uma tecla foi pressionada.
+10455=Abortar
+10460=O mouse foi clicado fora da caixa de resultados.
+10465=Interrompendo formatação.
+10470=Interrompendo escolha.
+10480=A soma das composições percentuais não é 100%.
+10485=Continuar calculando?
+10490=Não é possível calcular
+10500=Uma tecla foi pressionada.
+10505=O mouse foi clicado fora da caixa de resultados.
+10510=Interrompendo cálculos.
+10515=O Número máximo foi encontrado.
+10520=Máximo
+10530=Compostos encontrados
+; Note: the following is used when displaying the results of a percent composition
+; search in the formula finder. A synonym for 'has' would be 'contains' or 'is composed of'
+10535=contém
+10540=Ocorreu um erro de memória. A lista de resultados está provavelmente cheia.
+10545=Falta de Memória
+10550=A caixa de resultados está vazia.
+10555=Nada a copiar
+10560=Nada a imprimir
+10565=Tem certeza que deseja imprimir o(s) resultado(s)?
+10570=Imprimindo
+
+[frmFinderOptions]
+10800=Opções do Finder
+; Labels
+10810=Selecione os itens das várias opções do Formula Finder.
+; Textboxes & Comboboxes
+10821=Carga mínima a limitar compostos
+10831=Carga máxima a limitar compostos
+10840=Busca Completa |Busca Restrita
+10841=Uma busca completa encontra todos os compostos, enquanto uma busca restrita encontra compostos dentro de uma escala atômica específica (completa é geralmente mais rápida).
+10850=Ordenar por Fórmula
+10851=Método para ordenar resultados. Calcular de novo para reordenar.
+10855=Ordenar por Carga
+10860=Ordenar por MM
+10865=Ordenar por m/z
+10870=Razão Massa/Carga Indicada
+10875=Massa Molecular Indicada
+; CheckBoxes
+10900=Encontrar &Carga
+10901=Computar a carga global de cada composto encontrado
+10910=Faixa Limite de Ca&rga
+10911=Limitar exibição de compostos à faixa específica de carga
+10920=Encontrar m/&z
+10921=Computar a massa para razão de carga de cada composto encontrado
+10930=Encontrar m/z &Indicado
+10931=Encontrar compostos com valores m/z equivalentes ao indicado
+10940=O&rdenar Resultados
+10941=Converter resultados para fórmulas empíricas e ordená-las
+10950=&Regular átomos de H
+10951=Elimina fórmulas com número exagerado de átomos de hidrogênio
+10960=&Ajustar automaticamente Mín e Máx ao ligante procurado.
+10961=Ajusta automaticamente valores Mín e Máx procurados para uma faixa válida de massa dada
+
+[frmMMconvert]
+11000=Cálculos Mol/Massa/Solução
+; Combo Boxes
+11010=Converter Quantidades|Encontrar Concentração|Diluição
+11011=Cálculos de concentração ou cálculos e conversões de grandezas
+11020=Mols|miliMols|microMols|nanoMols|picoMols|fentoMols|atoMols|Quilogramas|Gramas|Miligramas|Microgramas|Libras|Onças|Litros|Decilitros|Mililitros|Microlitros|Nanolitros|Picolitros|Galões|Quarts|Pints
+11021=Unidade a ser convertida
+11026=Unidade a usar no cálculo de concentração
+11030=Litros|Decilitros|Mililitros|Microlitros|Nanolitros|Picolitros|Galões|Quarts|Pints
+11031=Unidade de volume
+11041=Unidade da grandeza a calcular
+11051=Unidade de concentração
+; Labels
+11080=g/mL
+; Textboxes
+11101=Quantidade, volume ou massa de composto
+11106=Quantidade, volume ou massa de soluto
+11111=Densidade da substância
+11121=Volume da solução
+11131=Concentração de soluto
+; Buttons
+11150=Encontrar &Quantidade
+11151=Calcula quantidade, volume ou massa usando volume e concentração
+11160=Encontrar &Volume
+11161=Calcula volume usando a quantidade e concentração
+11170=Encontrar &Concentração
+11171=Calcula concentração usando quantidade e volume
+
+; Dilution-related controls
+11200=Problemas de Diluição
+11205=Problemas de Evaporação ou Sublimação
+11210=Encontrar Volumes Necessários|Encontrar Volume Total|Encontrar Concentração Final|Encontrar Concentração Inicial
+11211=Escolha o que deseja calcular
+11220=&Vincular Concentração Calculada e Concentração Initial (Diluição)
+11221=Usa o mesmo valor para Concentração Calculada e Concentração Inicial
+11230=Vincular Unidades de Volume
+11231=Usa as mesmas unidades de Volume para Solução inicial, Solvente, e Volume Total Final
+; Dilution related labels and textbox tooltips
+11250=Concentração &Inicial
+11256=Concentração de soluto na solução inicial
+11260=Volume da Solução &Inicial
+11266=Volume (alíquota) da solução inicial necessária para a diluição
+11270=Concentração &Final
+11276=Concentração de soluto na solução final após diluição
+11280=Volume de Solvente usado na &Diluição
+11286=Volume de solvente a misturar com a alíquota da solução inicial
+11290=Volume &Total Final
+11296=Volume total da solução final após diluição com solvente
+
+[frmProgramPreferences]
+11500=Preferências do MWT
+; Frame labels
+11510=Modo Abreviatura (F3)
+11520=Modo Case Recognition (F4)
+11530=Modo Desvio-Padrão (F12)
+11540=Opções do Formula Finder
+11550=Opções para Sair do Programa
+; Buttons
+11600=&Salvar opções como padrão
+11610=&Restaurar opções padrão
+; Option Buttons
+11650=Normal
+11651=Reconhecer abreviaturas normais, mas não Aminoácidos
+11655=Normal + Aminoácidos
+11656=Reconhecer abreviaturas normais e Aminoácidos
+11660=Desabilitado
+11661=Ignorar todas abreviaturas
+11665=Conversor para Maiúsculas
+11666=Põe fórmulas em maiúsculas corretamente
+11670=Case Exato
+11671=Requer que o usuário escreva as fórmulas com maiúsculas e minúsculas corretas
+11675=Smart Case
+11676=Interpreta fórmulas em letras minúsculas sem alterá-las para maiúsculas
+11680=Curto
+11681=Mostrar Desvios-Padrão de forma abreviada
+11685=Científico
+11686=Mostrar Desvios-Padrão em notação científica
+11690=Decimal
+11691=Mostrar Desvios-Padrão na forma decimal longa
+11695=Desabilitado
+11696=Não mostrar desvios-padrão
+11700=Usa Esc para sair com confirmação
+11701=Determine se a tecla Esc será usada para sair do programa exibindo janela de confirmação
+11705=Usa Esc para sair sem confirmação
+11710=Ignora Esc mas confirma saída
+11715=Ignora Esc e não confirma saída
+; CheckBoxes
+11750=A&vança após Calcular (F9)
+11751=Muda para nova fórmula após calcular a massa.
+11760=Usa &Colchetes como Parênteses
+11761=Usa colchetes, [ e ], como parênteses (não usar com Percent Solver)
+11770=Copia a&utomaticamente Massa Molecular Atual (Ctrl+U)
+11771=Automaticamente copia o valor de massa molecular da fórmula selecionada para o clipboard após cada cálculo
+11780=Considera Car&ga
+11781=Considera carga dos compostos (regras básicas, não consegue corrigir ligações duplas ou triplas, etc.)
+11800=Sempre troca para Modo &Isotópico automaticamente
+11801=Alterna para Massa Isotópica ao entrar em Formula Finder
+11810=&Nunca mostra o aviso de modo Formula Finder
+11811=Nunca avisa sobre modo de massa atual quando entra em Formula Finder
+11820=Salva &Automaticamente opções, valores, e fórmulas ao sair
+11821=Automaticaticamente salva opções, valores, e fórmulas ao sair do programa
+11830=Apresenta Frases de Alerta (F7)
+11831=Alerta possíveis confusões na escrita de fórmulas (como Co em vez de CO)
+11840=Mostra Modo de Massa
+11841=Permite alternar rapidamente o modo de massa (média, isotópica, inteiro)
+11850=Mostra Dicas
+11851=Mostra mensagens curtas de ajuda quando o mouse passa sobre alguns botões e áreas
+11860=Destaca campos de texto quando selecionado
+11861=Destaca o campo de texto completo quando move para ele
+11870=&Oculta janelas de programas inativos
+11871=Oculta a janela principal do programa quando usa o Formula Finder, Calculadora Mol/Massa, etc.
+11881=Escolha o menor número para evitar que a janela de fórmulas encha a tela. O máximo depende da configuração da tela. Pode ser necessário reiniciar o programa.
+11885=Número máximo de fórmulas a exibir
+11890=Module to show at startup
+11896=Module to show when the program starts
+11898=Main Window|Formula Finder|Capillary Flow Calculator|Mole/Mass Converter|Peptide Seq Fragmentation Modeller|Amino Acid Notation Converter|Isotopic Distribution Modeller
+
+; Messages
+11900=Salva automaticamente valores de opções salvas.
+11910=Opções padrão restauradas.
+11920=Valores e fórmulas salvas.
+11925=Valores e fórmulas NÃO foram salvos pois foi usado o comando /X.
+11930=Opções default salvas.
+11935=Opções default NÃO foram salvos pois foi usado o comando /X.
+
+[frmFragmentationModelling]
+12000=Modelagem de Seqüência de Peptídio
+; General Combo Boxes
+12010=notação 1 letra|notação 3 letras
+12011=Tipo de notação para seqüência de aminoácido
+12020=&Encontre Íons
+; Textboxes
+12051=Escreva a seqüência de aminoácido aqui
+12061=Shifts the loaded ions to be matched by the given amount to correct for post-translational modifications.
+; Frames, labels, and checkboxes
+12100=Seqüência:
+12150=Terminação N e C
+12160=&N
+12170=&C
+12180=H (hydrogen)|HH+ (protonated)|C2OH3 (acetyl)|C5O2NH6 (pyroglu)|CONH2 (carbamyl)|C7H6NS (PTC)|(none)
+12190=OH (hydroxyl)|NH2 (amide)|(bare)
+12200=Tipos de Íon
+12210=&A Íons
+12215=&B Íons
+12220=&Y Íons
+12230=Perda Neutra
+12236=Escolha os íons cuja cuja perda será aplicada
+12240=Perda de H2O
+12250=Perda de NH3
+12255=Loss of PO4
+12260=Opções de Carga
+12270=Íons de carga &2+
+12280=&Mínimo
+12286=O valor m/z 2+ será computado pelos íons acima desse m/z
+12300=Opções para o Íon
+12310=&Remove Íon Precursor
+12320=Massa do Íon
+12330=Faixa de Massa
+12340=&Ion Matching Window
+12350=Da
+12355=Alinhamento &Offset
+12360=Estatísticas do Íon
+12370=Carregado
+12375=Remaining after binning
+12380=Faixa de tolerância
+12385=Precursor não encontrado
+12390=Precursor removido
+12395=Precursor não removido
+12400=Encontrados
+12405=Escore
+12410=Mass Information
+12420=Element Mode
+12425=Average
+12430=Isotopic
+
+; Column titles in grids
+; Note: # means 'number', Immon. means 'immonium', and Seq. means 'sequence'
+12500=#
+12510=Immon.
+12520=Seq.
+12550=Massa
+12560=Intensidade
+12570=Symbol
+
+; Menu Items
+12800=&Abrir Seqüência Info
+12810=&Salvar Seqüência Info
+12820=Abrir Lista de &Íons a Encontrar
+12830=&Fechar
+12840=&Copiar Íons Previstos
+12850=Copiar Íons Previstos como &RTF
+12855=Copiar Íons Previstos como Html
+12860=Co&lar Lista de Íons para Encontrar
+12865=Copy Sequence Molecular &Weight
+12870=Limpar &Lista de Íons a Encontrar
+12880=Lista de &Ions a Encontar
+12900=Espectro de &Massa
+12910=A&tualizar Espectro na Alteração
+12915=&Dta.Txt File Browser
+12920=Ion Match List &Options
+12925=Edit Residue &Modification Symbols
+12930=&Alinhamento Automático de Íons
+12940=Modelagem de &Fragmentos
+12950=&Copy Selected Ions
+12960=&Delete All (Clear list)
+
+[frmMsPlot]
+13000=Plot
+; The following is an abbreviation for the word 'Location'
+13010=Loc
+
+; Legend Items
+13030=Íons Previstos
+13035=Íons Carregados
+
+; Menu Items
+13100=&Exportar Dados
+13150=Tipo de &Gráfico
+13160=&Sticks To Zero
+13170=Picos &Gaussianos
+13180=Set Effective &Resolution
+13190=Linhas de Grade Eixo X
+13200=Linhas de Grade Eixo Y
+13210=&Marcar para etiqueta (aprox.)
+13220=Eixo &X
+13230=Eixo &Y
+13235=&Qualidade do Gráfico (afeta velocidade)
+13240=Qualidade da Representação &Gaussiana
+13245=Fator de &Aproximação
+13250=Determinar &X
+13260=Determinar &Y
+13270=&Autoescalar Eixo Y
+13280=&Corrigir mínimo Y em zero
+13290=&Reduzir para Anterior
+13295=Ctrl+Z ou Clique Direito
+13300=Reduzir para Exibir Tudo
+13310=Modo do &Cursor
+13315=Space Enables Move
+13320=&Zoom
+13330=&Mover
+13340=&Mostrar Posição Atual
+13342=Mostrar &Legenda
+13345=Restaurar Opções &Padrão
+13350=&Zoom Box
+13360=&Ampliar
+13365=Clique Esquerdo
+13370=Ampliar Horizontal
+13380=Ampliar Vertical
+13390=&Reduzir
+13400=Reduzir Horizontal
+13410=Reduzir Vertical
+
+[frmIonMatchOptions]
+14000=Opções de Busca de Íon
+; Buttons
+14010=&Alterar para Padrão
+14020=Edit Auto-Label Options
+
+; Explanations
+14050=Quando uma lista de íons é importada para o programa, íons de massa similar podem ser opcionalmente agrupados para reduzir o número total de pontos. Íons que cercam o íon precursor podem ser removidos.
+14055=Então, as intensidades são normalizadas para a máxima intensidade dada e colocadas em ordem decrescente de intensidade. Os íons "top-most" (número de íons a usar) são divididos em diferentes regiões de massa e os íons em cada região são novamente normalizados.
+14060=As massas dos íons previstos para uma dada seqüência de peptídios são facilmente computadas. Contudo, valores de intensidade também podem ser indicadas por massas.
+14065=Os íons B e Y são tipicamente de mesma intensidade enquanto o íon A é tipicamente 5 vezes menos intenso. Íons "shoulder" (massas ± 1 Da dos íons B e Y) podem ser adicionados, além de incluir perdas neutras (H2O e NH3).
+
+; Frames, labels, and checkboxes
+14100=Opções de Normalização para Dados Importados
+14110=&Group Similar Ions (Bin Data)
+14115=Faixa de Massa
+14120=Intensidade Normalizada
+14130=Número de Íons a Usar
+14140=Subdivisões de Região de Massa
+14150=Ion Intensities of Predicted Ions
+14160=Intensidade Íon A
+14165=Intensidade Íon B
+14170=Intensidade Íon Y
+14180=B/Y Ion Shoulders
+14190=Neutral Losses
+14200=Frgamentation Spectrum Labels
+14210=Label main ions (a, b, y)
+14220=Label neutral loss ions
+14230=Emphasize Proline y ions
+14240=Spectrum Plotting Options
+14250=Fragmentation Data Color
+14255=Matching Ion Data Color
+14258=Click to change
+14260=Plot Fragmentation Spectrum Inverted
+14270=Auto-Label Peaks on Matching Ion Spectrum
+
+[frmSetValue]
+14500=Determinar Valor
+14510=&Determinar
+14520=&Iniciar
+
+[frmProgress]
+14700=Progresso
+14710=Clique para Pausa
+14715=Preparando Pausa
+14720=Em pausa
+14725=Resuming
+14730=(Use Esc para interromper)
+14740=min. elapsed/remaining
+
+[frmIsotopicDistibution]
+15000=Isotopic Distribution
+; Frames, labels, and checkboxes
+15050=Formula:
+15060=Results:
+15070=Carga:
+15100=&Plot Results
+15105=&Auto-Label Peaks
+15110=&Compute
+15120=Plot Data Color
+15126=Click to change
+15130=Plot Type
+15140=Sticks to Zero|Gaussian Peaks
+15145=Sticks to Zero|Gaussian Peaks|Lines Between Points
+15151=Isotopic distribution results
+15160=Paste list of ions to compare
+15165=Clear List
+15170=Comparison list data points:
+15190=Options
+15195=Comparison List
+; Column headers in the results box
+15200=Isotopic Abundances for
+15210=Mass/Charge
+15215=Neutral Mass
+15220=Fraction
+15230=Intensity
+15300=Warning, the ion comparison list contains a large number of data points. Do you really want to convert each point to a Gaussian curve?
+15305=Large Data Point Count
+
+[frmAminoAcidModificationSymbols]
+15500=Amino Acid Modification Symbols Editor
+;Directions
+15550=Modified residues in an amino acid sequence are notated by placing a modification symbol directly after the residue's 1 letter or 3 letter abbreviation.
+15555=The phosphorylation symbol is defined separately because phosphorylated residues can lose a phosphate group during fragmentation.
+15560=As an example, if the phosphorylation symbol is *, then in the sequence 'GlyLeuTyr*' the tyrosine residue is phosphorylated.
+15565=Allowable symbols for user-defined modifications are
+15570=Modification symbols can be more than 1 character long, though it is suggested that you keep them to just 1 character long to make it easier for the parsing routine to correctly parse residues with multiple modifications.
+15575=If a residue has multiple modifications, then simply place the appropriate modification symbols after the residue, for example in 'FLE*#L' the E residue is modified by both the * and # modifications.
+15580=Modification masses can be negative values, as well as positive values.
+;Table Tool Tip
+15600=
+15601=Click to change a modification symbol
+; Table column headers
+15610=Symbol
+15620=Mass
+15640=Comment
+; Labels
+15700=Modification Symbols Defined
+15710=Single click to edit or remove. Click in blank row to add.
+15720=Standard Modifications
+15730=Phosphorylation Symbol:
+; Messages
+15750=The amino acid symbol modification will be updated with the parameters below. Select Remove to delete the modification symbol or Cancel to ignore any changes.
+15760=Warning, the new phosphorylation symbol is already being used for another modification. Do you really want to use this symbol for phosphorylation and consequently remove the other definition?
+15765=Modification Symbol Conflict
+15770=Are you sure you want to lose all changes?
+15775=Closing Edit Modification Symbols Window
+; Buttons
+15800=&Reset to Defaults
+15801=Resets modification symbols to defaults
+15810=&Add selected to list
+
+[frmDtaTxtFileBrowser]
+16000=_Dta.Txt File Browser
+; Labels
+16050=Scan Number Start
+16060=Scan Number End
+16070=Parent Ion MH+
+16080=Parent Ion Charge
+; Buttons
+16100=&Jump to scan
+16101=Shortcut is Ctrl+J
+16110=&Keep Window On Top
+
+[ErrorAndStatusMessages]
+20001=Elemento desconhecido
+20003=Falta fechar parênteses
+20004=Parênteses desencontrados
+20005=Não deve ter um 0 logo após fechar elemento ou -
+20006=Número muito grande ou colocar somente após [, -, ), ou circunflexo (^)
+20007=Número muito grande
+20011=Números deveriam estar à esquerda de colchetes, não à direita (a menos que esteja no modo 'tratar colchetes' como parênteses)
+20012=Um número deve estar presente após um colchete e/ou após a vírgula decimal
+20013=Falta fechar colchete, ]
+20014=Número mal colocado; deveria estar apenas após um elemento, [, ), -, ou circunflexo, ^
+20015=Colchete não encontrado
+20016=Não pode nested brackets or brackets inside múltiplos hidratos (a menos que esteja no modo 'tratar colchetes' como parênteses)
+20018=Elemento desconhecido
+20020=Deve colocar número de massa do isótopo seguido de circunflexo (^)
+20022=Um elemento deve estar presente após a massa isotópica após o circunflexo (^)
+20023=Massas de isótopo negativas não são permitidas após circunflexo (^)
+20024=Massas isotópicas não são permitidas para abreviaturas
+20025=Um elemento deve estar presente após o leading coeficiente of the dash
+20026=Massas Isotópicas não são permitidas para abreviaturas; D é uma abreviatura
+20027=Números não podem conter mais que uma vírgula decimal
+20028=Circular abbreviation reference; can't have an abbreviation referencing a second abbreviation that depends upon the first one
+20030=Invalid formula subtraction; one or more atoms (or too many atoms) in the right-hand formula are missing (or less abundant) in the left-hand formula
+20050=Valor Indicado é maior que 100%, valor impossível.
+20075=Letras não são permitidas na linha da calculadora
+20076=Falta fechar parênteses
+20077=Parênteses não encontrado
+20078=Número mal colocado; ou número muito grande, muito pequeno, ou muito longo
+20080=Operador mal colocado
+20081=Faixa variável é menor que ou igual a 1; bug no programa; por favor notifique o programador
+20082=Faltando operador.
+20085=Não é possível usar números negativos para potência decimal
+20086=Não é possível usar zero para potência decimal
+20087=Não é possível usar zero para elevar à zeroésima potência
+20089=Um npumero positivo ou negativo deve estar presente após o circunflexo (^)
+20090=Números não podem conter mais que uma vírgula decimal
+20091=Você tentou dividir um número por zero. Por favor corrija o problema e recalcule.
+20092=Não são permitidos espaços em expressões matemáticas
+20093=Use ponto para decimais
+20094=Use vírgula para decimais
+20095=Deve ser colocado um algarismo após a vírgula
+20100=Erro ao salvar arquivo de abreviaturas
+20110=O arquivo de abreviaturas foi modificado.
+20115=O arquivo anterior foi renomeado
+20120=[AMINOÁCIDOS] cabeçalho não encontrado no arquivo MWT_ABBR.DAT . Ele deveria estar antes/acima do cabeçalho [ABBREVIATIONS].
+20130=[ABBREVIATURAS] cabeçalho não encontrado no arquivo MWT_ABBR.DAT. Ele deveria estar antes/acima do cabeçalho [AMINOÁCIDOS].
+20135=Selecione OK para continuar somente com abreviaturas de Aminoácidos.
+20140=O arquivo de abreviaturas não foi encontrado na pasta do programa
+20150=Erro ao Carregar/Criar Arquivo de Abreviatura
+20160=Ignorando Abreviatura -- Fórmula Inválida
+20170=Ignorando Abreviatura Repetida
+20180=Ignorando Abreviatura; Caracter Inválido
+20190=Ignorando Abreviatura; muito comprido
+20200=Ignorando linha inválida
+20210=O arquivo contendo os elementos foi modificado.
+20220=Massa possivelmente incorreta
+20230=Incerteza possivelmente incorreta
+20250=Ignorando Linha; Símbolo de Elemento Invélido
+20260=[ELEMENTOS] cabeçalho não encontrado no arquivo MWT_ELEM.DAT . Ele deveria estar neste arquivo.
+20265=Selecione OK para continuar com valores padrão.
+20270=O arquivo de elementos não foi encontrado na pasta do programa.
+20280=Erro ao Carregar/Criar Arquivo de Elementos
+20305=Continuar com captions padrão.
+20320=Erro ao Salvar Arquivo de Elementos
+20330=Erro ao Carregar/Criar no Arquivo de Valores
+20340=Selecione OK para continuar a carregar Valores e Fórmulas Padrão.
+20345=Ao usar drive de leitura (Read-Only), use /X na linha de comando para evitar esse erro.
+20350=Erro
+20360=Erro ao Salvar no Arquivo Opções Padrão
+20380=Erro ao Salvar no Arquivo de Valores e Fórmulas
+20400=Erro ao Carregar/Criar no Arquivo de Opções Padrão
+20410=Selecione OK para continuar sem carregar Padrões do Usuário.
+20440=O arquivo de idioma não pode ser aberto corretamente ou foi formatado incorretamente.
+20450=Impossível carregar idioma especificado
+20460=O arquivo de idioma não foi encontrado na pasta (diretório) do programa.
+20470=O arquivo necessário para processar massa molecular não foi encontrado
+20480=Arquivo Não Encontrado
+20490=Este arquivo já existe. Substituí-lo?
+20500=Arquivo Existente
+20510=Erro ao Ler/Escrever arquivos de processamento batch
+20515=Selecione OK para abortar processamento de arquivo batch.
+20520=Erro no programa
+20530=These line code should not have been encountered. Please notify programmer.
+20550=Percent solver não pode ser usado quando colchetes são tratados como parênteses. Você pode modificar esse modo escolhendo Alterar Preferências no menu Opções.
+20555=Percent Solver não Disponível
+20560=Não é possível trabalhar com mais fórmulas.
+20570=Fórmula em branco.
+20580=Desabilite Percent Solver (F11) antes de criar uma fórmula nova.
+20590=Ocorreu um erro de overflow. Por favor reduza o tamanho dos números e recalcule.
+20600=Ocorreu um erro
+20605=Por favor, saia do programa e relate o erro ao programador. Selecione About MWT... no menu Ajuda para ver o endereço eletrônico (e-mail).
+20610=Espaços não são permitidos em fórmulas
+20620=Caracter Inválido
+20630=Não é possível copiar para nova fórmula.
+20650=Fórmula em branco.
+20655=O modo Percent Solver está habilitado (F11 para sair do modo).
+20660=Atenção, provavelmente a massa isotópica está muito grande para o elemento
+20662=Atenção, provavelmente a massa isotópica está muito pequena para o elemento
+20665=vs massa atômica média de
+20670=Atenção, a massa isotópica está exageradamente pequena para o elemento
+20675=prótons
+20680=Nota: Modo Exact Case está habilitado
+20685=Nota: para % Solver, um colchete esquerdo deve preceder um x
+20690=Nota: colchetes estão sendo tratados como parênteses
+20700=Um ou mais elementos devem ser verificados.
+20705=Maximum hits must be greater than 0.
+20710=Maximum hits deve ser menor que
+20715=Número mínimo de elementos deve ser 0 ou maior.
+20720=Número mínimo de elementos deve ser número máximo de elementos.
+20725=Número máximo de elementos deve ser menor que 65.025
+20730=Uma massa atômica deve ser colocada para elementos customizados.
+20735=Massa Atômica deve ser maior que 0 para elementos customizados.
+20740=Massa molecular deve ser fornecida.
+20745=Massa molecular deve ser maior que 0.
+20755=O máximo para a massa molecular deve ser fornecido.
+20760=O máximo para a massa molecular deve ser maior que 0.
+20765=A porcentagem de cada elemento deve ser fornecida
+20770=A porcentagem deve ser maior que 0.
+20775=As massas customizadas devem conter somente números ou somente letras. Se forem usadas letras, elas devem ser para um símbolo válido ou abreviatura.
+20780=Massa elemental customizada está vazia. Se forem usadas letras, elas devem ser para um símbolo válido ou abreviatura.
+20785=Elemento desconhecido ou abreviatura para massa elemental customizada
+20790=Somente símbolos de elementos ou abreviaturas são permitidas.
+20800=Cuidado, abreviaturas não foram carregadas -- Comando sem efeito.
+20805=Cannot handle fractional numbers of atoms
+
+20900=Error Reading/Writing sequence information file.
+20910=Ions are already present in the ion list. Replace with new ions?
+20920=Subsutituir Íons Existentes
+20930=Carregando Lista de Íons
+20940=Processo interrompido
+20945=Abortado
+20950=Normalizando íons
+20960=Normalizando por região
+20965=Classificando por Intensidade
+20970=Encontrando Íons
+20980=O clipboard está vazio. Sem íons para colar.
+20985=Sem íons
+20990=Colando lista de íon
+21000=Determinando número de íons na lista
+21010=Parsing list
+21020=Não foram encontrados íons válidos no clipboard. Uma lista de íon válida é uma lista de massa intensidade aos pares, separados por vírgula, tabs, ou espaços. Deve ser colocado somente um par massa/intensidade por linha.
+21030=Erro ao gravar dados para arquivo
+21040=Set Range
+21050=Inciar Val
+21055=Finalizar Val
+21060=Set X Axis Range
+21065=Set Y Axis Range
+21070=Enter a new Gaussian Representation quality factor. Higher numbers result in smoother Gaussian curves, but slower updates. Valid range is 1 to 50, default is 20.
+21072=Gaussian Representation Quality
+21075=Enter a new plotting approximation factor. Higher numbers result in faster updates, but give a less accurate graphical representation when viewing a wide mass range (zoomed out). Valid range is 1 to 50, default is 10.
+21077=Plotting Approximation Factor
+21080=Resolving Power Specifications
+21090=Resolving Power
+21100=X Value of Specification
+21110=Please enter the approximate number of ticks to label on the axis
+21115=Axis Ticks
+21120=Creating Gaussian Representation
+21130=Preparing plot
+21135=Desenhando
+21140=Tem certeza que deseja restaurar as opções padrão?
+21145=Restaurar Opções Padrão
+21150=Alinhar Íons
+21155=Máximo Offset
+21160=Incremento Offset
+21165=Alinhando Íons
+
+21500=Todos Arquivos
+21510=Arquivos Texto
+21515=txt
+21520=Arquivos de Dados
+21525=csv
+21530=Arquivos de Seqüência
+21535=seq
+21540=Arquivos Lista de Íon
+21545=txt
+21550=cap
+21555=Capillary Flow Info Files
+
+[CautionStatments]
+; Note: Caution statement keynames are case sensitive; i.e. Bi is different than BI
+; You may add new caution statements if desired; however, you will need to save
+; the file with a name other than Lang_English and change the Language= key
+; since this file is not loaded if the language is English
+22000=Aviso
+Bi=Bi quer dizer bismuto; BI quer dizer boro-iodo.
+Bk=Bk quer dizer berquélio; BK quer dizer boro-potássio.
+Bu=Bu quer dizer o grupo butil; BU quer dizer boro-urânio.
+Cd=Cd quer dizer cádmio; CD quer dizer carbono-deutério.
+Cf=Cf quer dizer califórnio; CF quer dizer carbono-flúor.
+Co=Co quer dizer cobalto; CO quer dizer carbono-oxigênio.
+Cs=Cs quer dizer césio; CS quer dizer carbono-enxofre.
+Cu=Cu quer dizer cobre; CU quer dizer carbono-urânio.
+Dy=Dy quer dizer disprósio; DY quer dizer deutério-ítrio.
+Hf=Hf quer dizer hafnio; HF quer dizer hidrogênio-flúor.
+Ho=Ho quer dizer hólmio; HO quer dizer hidrogênio-oxigênio.
+In=In quer dizer índio; IN quer dizer iodo-nitrogênio.
+Nb=Nb quer dizer nióbio; NB quer dizer nitrogênio-boro.
+Nd=Nd quer dizer neodímio; ND quer dizer nitrogênio-deutério.
+Ni=Ni quer dizer níquel; NI quer dizer nitrogênio-iodo.
+No=No quer dizer nobélio; NO quer dizer nitrogênio-oxigênio.
+Np=Np quer dizer neptúnio; NP quer dizer nitrogênio-fósforo.
+Os=Os quer dizer ósmio; OS quer dizer oxigênio-enxofre.
+Pd=Pd quer dizer paládio; PD quer dizer fósforo-deutério.
+Ph=Ph quer dizer fenil, PH quer dizer fósforo-hidrogênio.
+Pu=Pu quer dizer plutônio; PU quer dizer fósforo-urânio.
+Py=Py quer dizer piridina; PY quer dizer fósforo-ítrio.
+Sb=Sb quer dizer antimônio; SB quer dizer enxofre-boro.
+Sc=Sc quer dizer escândio; SC quer dizer enxofre-carbono.
+Si=Si quer dizer silício; SI quer dizer enxofre-iodo.
+Sn=Sn quer dizer estanho; SN quer dizer sulfor-nitrogênio.
+TI=TI quer dizer trítio-iodo, Ti quer dizer titânio.
+Yb=Yb quer dizer itérbio; YB quer dizer ítrio-boro.
+BPY=BPY quer dizer boro-fósforo-ítrio; Bpy quer dizer bipiridina.
+BPy=BPy quer dizer boro-piridina; Bpy quer dizer bipiridina.
+Bpy=Bpy quer dizer bipiridina.
+Cys=Cys quer dizer cisteína; CYS quer dizer carbono-ítrio-enxofre.
+His=His quer dizer histidina; HIS quer dizer hidrogênio-iodo-enxofre.
+Hoh=HoH quer dizer hólmio-hidrogênio; HOH quer dizer hidrogênio-oxigênio-hidrogênio (água).
+Hyp=Hyp quer dizer hidroxiprolina; HYP quer dizer hidrogênio-ítrio-fósforo.
+OAc=OAc quer dizer oxigênio-actínio; Oac quer dizer acetato.
+Oac=Oac quer dizer acetato.
+Pro=Pro quer dizer prolina; PrO quer dizer praseodímio-oxigênio.
+PrO=Pro quer dizer prolina; PrO quer dizer praseodímio-oxigênio.
+Val=Val quer dizer valina; VAl quer dizer vanádio-alumínio.
+VAl=Val quer dizer valina; VAl quer dizer vanádio-alumínio.
diff --git a/lang_russian.ini b/lang_russian.ini
new file mode 100644
index 0000000..5e5c2a3
--- /dev/null
+++ b/lang_russian.ini
@@ -0,0 +1,1107 @@
+; Language customization file for the Molecular Weight Calculator program by Matthew Monroe
+; Contact at alchemistmatt@yahoo.com and http://come.to/alchemistmatt/ or http://www.alchemistmatt.com/
+;
+; When customizing the phrases in this file, the ampersand symbol (&) signifies a
+; keyboard shortcut. For example, the default value for key 1000 is &File. When
+; running the program, the F in File will be underlined and the user may press Alt-F
+; to access the File menu (in addition to clicking on the file menu)
+; To improve usability of the program, please try to include the & symbol in menu items
+; and buttons. Note, however, that if two controls on the same form have the same &
+; shortcut, they will not respond to the alt key in the usual way.
+;
+; In this file, items surround by brackets [] are section headers -- the program ignores them
+; when parsing the file. The key values (1000, 1010, 1020, etc.) should not be changed, with
+; the exception that new caution statements may be added at the end of the file.
+; Lines beginning with a semicolon (;) are also ignored since they are treated as comments
+; However, you should not place a ; at the end of a line with an actual key and caption.
+;
+; Keys with multiple values separated by a vertical line (|) represent multiple items loaded
+; into a ComboBox control. When translating to other languages, you must keep the same number
+; of items in the list, or program functionality will be lost. For example, key 7070 contains
+; hours|minutes|seconds Thus, hours, minutes, and seconds will be loaded into a control, from
+; which the user may select one of them. In Spanish, you would use 7070=horas|segundos|minutos
+;
+; If you create a new .Ini file for a foreign language and would like it posted on my
+; web page, simply e-mail it to me.
+;
+;
+; Translation to Russian - Ïåðåâîä íà ðóññêèé:
+; Michael I. Yahkind - yah@mailru.com - ßõêèíä Ìèõàèë Èëüè÷
+
+[Language]
+Language=Russian
+
+[frmMain Menus]
+; Menu Items
+1000=&Ôàéë
+1010=Ïðàâèòü òàáëèöó &ýëåìåíòîâ
+1020=Ïðàâèòü &àááðåâèàòóðû
+1030=&Âû÷èñëèòü ìàññû äëÿ òåêñòîâîãî ôàéëà
+1040=&Ïå÷àòü ðåçóëüòàòîâ
+1050=Â&ûõîä
+1500=&Ïðàâêà
+1505=&Undo
+1510=&Âûðåçàòü
+1520=&Êîïèðîâàòü
+1530=Â&ñòàâèòü
+1540=&Óäàëèòü
+1545=Select &All
+1550=Ê&îïèðîâàòü òåêóùóþ ôîðìóëó êàê RTF
+1560=Êîïèðîâàòü òåêóùóþ &ìîëåêóëÿðíóþ ìàññó
+1570=Êîïèðîâàòü äàííûå &ïðîöåíòíîãî ñîñòàâà
+1580=Ó&äâîèòü òåêóùóþ ôîðìóëó
+1590=Ñ&òåðåòü âñå ôîðìóëû
+1600=Ñòåðåòü òåêóùóþ &ôîðìóëó
+1610=Ðàñêðûòü &àááðåâèàòóðû
+1620=Ïðåîáðàçîâàòü â &ýìïèðè÷åñêóþ ôîðìóëó
+2000=&Âèä
+2010=&Ìíîãî ôîðìóë
+2020=&Îäíà ôîðìóëà
+2030=&Âû÷èñëèòåëü ïðîöåíòîâ
+2040=&Íåò
+2050=&Äà
+2500=Ñ&ðåäñòâà
+2510=Êîíâåðòåð &ìîëåé/ìàññû è êàëüêóëÿòîð ðàçâåäåíèÿ
+2520=&Èñêàòåëü ôîðìóë
+2530=Êîíâåðòåð îáîçíà÷åíèé &àìèíîêèñëîò
+2533=Ìîäåëèðîâàíèå &ôðàãìåíòàöèè ïåïòèäîâ
+2536=Ìîäåëèðîâàíèå èçîòîïíîãî &ðàñïðåäåëåíèÿ
+2538=Show Isotopic &Distribution for Current Formula
+2540=Ìàòåìàòè÷åñêèé &êàëüêóëÿòîð
+2550=Êàëüêóëÿòîð &ïîòîêîâ äëÿ êàïèëëÿðà
+3000=&Îïöèè
+3010=Âûáðàòü &ÿçûê (Choose Language)
+3020=Ñìåíèòü &ïàðàìåòðû ïðîãðàììû
+3030=Ñìåíèòü &øðèôò ôîðìóë
+3040=Ïî&âåðõ âñåõ îêîí
+3050=&Ñîõðàíèòü/âîññòàíîâèòü çíà÷åíèÿ ïî óìîë÷àíèþ
+3060=&Âîññòàíîâèòü çíà÷åíèÿ è ôîðìóëû ïî óìîë÷àíèþ
+3070=Ñîõðàíèòü &òåêóùèå çíà÷åíèÿ è ôîðìóëû
+3500=Ïî&ìîùü
+3510=&Îáçîð ïðîãðàììû
+3530=Ïîêàçûâàòü &âñïëûâàþùèå ïîäñêàçêè
+3540=Î &ïðîãðàììå MWT
+
+[frmMain Status Messages and Verification Messages]
+3600=Ýòà ñòðîêà:
+3605=Óâåëè÷åíèå
+3610=Âû óâåðåíû, ÷òî õîòèòå ïðåîáðàçîâàòü òåêóùóþ ôîðìóëó â ýìïèðè÷åñêóþ?
+3615=Ïðåîáðàçîâàòü â ýìïèðè÷åñêóþ ôîðìóëó
+3620=Âû óâåðåíû, ÷òî õîòèòå ñòåðåòü òåêóùóþ ôîðìóëó?
+3625=Ñòåðåòü òåêóùóþ ôîðìóëó
+3630=Âû óâåðåíû, ÷òî õîòèòå ðàñêðûòü àááðåâèàòóðû â òåêóùåé ôîðìóëå è çàìåíèòü èõ íà ýêâèâàëåíòû èç ýëåìåíòîâ?
+3635=Ðàñêðûòü àááðåâèàòóðû
+3640=Âîññòàíîâëåíèå çíà÷åíèé è ôîðìóë ïî óìîë÷àíèþ ñîòðåò òåêóùèå ôîðìóëû. Âû óâåðåíû, ÷òî õîòèòå ñäåëàòü ýòî?
+3645=Âîññòàíîâèòü çíà÷åíèÿ è ôîðìóëû ïî óìîë÷àíèþ
+3650=Ââåñòè çàäàííîå ïðîöåíòíîå ñîäåðæàíèå ýòîãî ýëåìåíòà. Ñáðîñ äëÿ âîññòàíîâëåíèÿ âû÷èñëåííîãî çíà÷åíèÿ, Îòìåíà - äëÿ îòìåíû èçìåíåíèé.
+3660=Êëàâèøè ñòðåëîê, PgUp/Dn - ïåðåõîäû (F11 - âûõîä èç Âû÷èñëèòåëÿ %%).
+3665=Ùåë÷îê èëè Enter äëÿ èçìåíåíèÿ çíà÷åíèÿ (F11 - âûõîä èç Âû÷èñëèòåëÿ %%).
+3670=Ãîòîâî
+3700=Âû÷èñëåíèÿ, ùåë÷îê ìûøè èëè ëþáàÿ êëàâèøà äëÿ îñòàíîâêè.
+3710=x =
+3720=Âû÷èñëåííîå çíà÷åíèå
+3730=Çàäàííîå çíà÷åíèå
+3740=Ðàçíîñòü ñ çàäàííûì
+3750=Âû÷èñëèòåëü %% âêë.
+3760=Ðåçóëüòàòû MWT Êàëüêóëÿòîðà ìîëåêóëÿðíûõ ìàññ
+3770=Çíà÷åíèÿ è ôîðìóëû ïî óìîë÷àíèþ âîññòàíîâëåíû.
+3780=Âû óâåðåíû, ÷òî õîòèòå ñòåðåòü âñå ôîðìóëû?
+3785=Ñòåðåòü âñå ôîðìóëû
+3790=Âû óâåðåíû, ÷òî õîòèòå âûéòè?
+3795=Âûõîä èç ïðîãðàììû
+3800=Çàãðóçêà àááðåâèàòóð
+3810=Çàãðóçêà ýëåìåíòîâ
+3820=(èñïîëüçóþòñÿ ñðåäíèå àòîìíûå ìàññû)
+3830=(èñïîëüçóþòñÿ ìàññû èçîòîïîâ)
+3840=(èñïîëüçóþòñÿ öåëûå ìàññû èçîòîïîâ)
+3850=Èñïîëüçîâàíèå íîâîãî ÿçûêà ñîõðàíåíî.
+
+[Phrases common throughout application]
+4000=&Çàêðûòü
+4010=&Äà
+4020=&Îòìåíà
+4030=Â&ûõîä
+; The following is the abbreviation for Molecular Weight
+; It must be exactly two letters long
+4040=MM
+4050=Âíèìàíèå
+4060=Yes
+4065=No
+
+[frmMain]
+; Form Caption
+4900=MWT Êàëüêóëÿòîð ìîëåêóëÿðíûõ ìàññ
+; Labels
+5000=Ôîðìóëà
+5010=Ðåæèì ìàññ ýëåìåíòîâ
+5020=&Ñðåäíèå
+5021=Èñïîëüçîâàòü ñðåäíèå àòîìíûå ìàññû ýëåìåíòîâ
+5030=&Èçîòîïíûå
+5031=Èñïîëüçîâàòü ìàññû íàèáîëåå ðàñïðîñòðàíåííûõ èçîòîïîâ
+5040=&Öåëûå
+5041=Èñïîëüçîâàòü öåëî÷èñëåííûå ìàññû íàèáîëåå ðàñïðîñòðàíåííûõ èçîòîïîâ
+; TextBoxes
+5051=Çäåñü ââîäÿò ôîðìóëó ìîëåêóëû
+; Buttons
+5100=Âû&÷èñëèòü
+5101=Îïðåäåëèòü ìîëåêóëÿðíóþ ìàññó äëÿ òåêóùåé ôîðìóëû
+5110=&Íîâàÿ ôîðìóëà
+5111=Äîáàâèòü ê ñïèñêó íîâóþ, ÷èñòóþ ñòðîêó äëÿ ôîðìóëû
+5116=Ñîçäàòü íîâóþ, ÷èñòóþ ñòðîêó äëÿ ôîðìóëû
+; Grid control
+5201=Ùåë÷îê äëÿ ââîäà èëè ñáðîñà çàäàííîãî çíà÷åíèÿ
+; Status control
+5301=Äâîéíîé ùåë÷îê ïî ñòðîêå ñîñòîÿíèÿ óâåëè÷èâàåò åå (èñïîëüçîâàòü äëÿ äëèííûõ ñîîáùåíèé)
+5350=MWT Êàëüêóëÿòîð ìîëåêóëÿðíûõ ìàññ óæå çàïóùåí. Âû óâåðåíû, ÷òî õîòèòå çàïóñòèòü íîâóþ êîïèþ?
+5355=Óæå çàïóùåí
+
+[frmAboutBox]
+5500=Î ïðîãðàììå MWT
+5510=Ýòà ïðîãðàììà Freeware, ò.å. áåñïëàòíàÿ
+
+[frmIntro]
+5700=Çàãðóçêà
+
+[frmAminoAcidConverter]
+; Form Caption
+6000=Êîíâåðòåð îáîçíà÷åíèé àìèíîêèñëîò
+; Labels
+6010=Íàáîð àìèíîêèñëîò â 1-áóêâåííîì îáîçíà÷åíèè
+6020=Íàáîð àìèíîêèñëîò â 3-áóêâåííîì îáîçíà÷åíèè
+; TextBoxes
+6031=Çäåñü ââîäÿò íàáîð àìèíîêèñëîò, èñïîëüçóÿ 1-áóêâåííûå îáîçíà÷åíèÿ
+6041=Çäåñü ââîäÿò íàáîð àìèíîêèñëîò, èñïîëüçóÿ 3-áóêâåííûå îáîçíà÷åíèÿ
+; Buttons
+6050=&Êîïèðîâàòü íàáîð àìèíîêèñëîò â ôîðìóëó:
+6060=Êîïèðîâàòü â Ìîäåëèðîâàíèå &ôðàãìåíòàöèè
+; CheckBoxes
+6080=&Äîáàâëÿòü ïðîáåë ïîñëå 10 îñòàòêîâ
+6090=&Ðàçäåëÿòü îñòàòêè òèðå
+
+[frmCalculator]
+; Form Caption
+6500=Êàëüêóëÿòîð
+; Textbox
+6511=Çäåñü ââîäÿò ìàòåìàòè÷åñêîå âûðàæåíèå äëÿ âû÷èñëåíèÿ
+; Buttons
+6520=Âû&÷èñëèòü
+6521=Âû÷èñëèòü òåêóùåå âûðàæåíèå
+; Status control
+6610=Ðåçóëüòàò
+
+[frmCapillaryCalcs]
+; Form Caption
+7000=Âû÷èñëåíèå îáúåìíîé è ìàññîâîé ñêîðîñòè äëÿ êàïèëëÿðà
+; Combo Boxes
+7010=Ïóñòîé òðóá÷àòûé êàïèëëÿð|Çàïîëíåííûé êàïèëëÿð
+7011=Ïåðåêëþ÷åíèå ìåæäó ïóñòûì è çàïîëíåííûì êàïèëëÿðîì
+7020=Íàéòè ïàäåíèå äàâëåíèÿ|Íàéòè äëèíó êîëîíêè|Íàéòè âíóòðåííèé äèàìåòð|Íàéòè îáúåìíóþ ñêîðîñòü ïîäà÷è|Íàéòè ñêîðîñòü ïîäà÷è, èñïîëüçóÿ "ìåðòâîå âðåìÿ"
+7030=ôóíòû/êâ.äþéì|Ïàñêàëè|êèëîÏàñêàëè|àòìîñôåðû|áàðû (àò)|òîððû (ìì Hg)|dynes/ñì^2
+7035=ì|ñì|ìì|ìêì|äþéìû
+7040=Ïóàçû [ã/(ñì-ñåê)]
+7050=ìë/ìèí|ìêë/ìèí|íë/ìèí
+7060=ñì/÷àñ|ìì/÷àñ|ñì/ìèí|ìì/ìèí|ñì/ñåê|ìì/ñåê
+7070=÷àñû|ìèíóòû|ñåêóíäû
+7080=ìë|ìêë|íë|ïë
+7090=ìîëü/ë|ìèëëèìîëü/ë|ìèêðîìîëü/ë|íàíîìîëü/ë|ïèêîìîëü/ë|ôåìòîìîëü/ë|àòòîìîëü/ë|mg/dL|ìã/ìë|ìêã/ìë|íã/ìë|ìêã/ìêë|íã/ìêë
+7100=ïìîëü/ìèí|ôìîëü/ìèí|àìîëü/ìèí|ïìîëü/ñåê|ôìîëü/ñåê|àìîëü/ñåê
+7110=ìîëü|ììîëü|ìêìîëü|íìîëü|ïìîëü|ôìîëü|àìîëü
+; Labels and frames
+7200=Ïàäåíèå äàâëåíèÿ
+7210=Äëèíà êîëîíêè
+7220=Âíóòðåííèé äèàìåòð êîëîíêè
+7230=Âÿçêîñòü ðàñòâîðèòåëÿ
+7240=Äèàìåòð ÷àñòèö
+7250=Îáúåìíàÿ ñêîðîñòü ïîäà÷è
+7260=Ëèíåéíàÿ ñêîðîñòü
+7270="Ìåðòâîå âðåìÿ" êîëîíêè
+7280=Îáúåì êîëîíêè
+7290=Ïîðèñòîñòü ìåæäó ÷àñòèöàìè (ýïñèëîí)
+7300=Âû÷èñëåíèå ìàññîâîé ñêîðîñòè
+7310=Êîíöåíòðàöèÿ ïðîáû
+7320=Âðåìÿ âêàëûâàíèÿ
+7330=Ìàññîâàÿ ñêîðîñòü ïîäà÷è
+7340=Âêîëîòî ìîëåé
+7350=Âû÷èñëåíèå ðàñøèðåíèÿ ïèêà âíå êîëîíêè
+7360=Êîýôôèöèåíò äèôôóçèè
+7370=Äëèíà ïóñòîé òðóáêè
+7380=Âíóòðåííèé äèàìåòð òðóáêè
+7390=Íà÷àëüíàÿ øèðèíà ïèêà (êàê îñíîâà)
+7400=Îïòèìàëüíàÿ ñêîðîñòü
+7410=(äëÿ ÷àñòèö 5 ìêì)
+7420=Îòêëîíåíèå âðåìåíè
+7430=Äîïîëíèòåëüíîå îòêëîíåíèå
+7440=Ðåçóëüòèðóþùàÿ øèðèíà ïèêà
+7450=Ïðîöåíò óâåëè÷åíèÿ
+7460=Ôîðìóëà
+7480=MM =
+7500=ñì
+7510=ìêì
+7520=ñì^2/ñåê
+7530=ñåê
+7540=ñì/ñåê
+7550=ñåê^2
+7560=ñåê
+7570=ã/ìîëü
+; TextBoxes
+7601=Çäåñü ââîäÿò ìîëåêóëÿðíóþ ìàññó äëÿ èñïîëüçîâàíèÿ â âû÷èñëåíèÿõ
+; Buttons
+7700=Ïîêàçàòü/Ñêðûòü âû&÷èñëåíèå ðàñøèðåíèÿ ïèêà
+7710=&Ïîêàçàòü ïîÿñíÿþùèå óðàâíåíèÿ
+7730=Ïîêàçàòü &óðàâíåíèÿ
+; Option Buttons
+7750=&Èñïîëüçîâàòü ìîëåêóëÿðíóþ ìàññó ñîåäèíåíèÿ òåêóùåé ôîðìóëû
+7760=&Ââåñòè ìîëåêóëÿðíóþ ìàññó
+; CheckBoxes
+7800=&Ñâÿçü ñ ïðåäûäóùèì
+; ToolTips
+7851=Îáû÷íîå çíà÷åíèå âÿçêîñòè 0,0089 Ïóàç
+7861=Îáû÷íîå çíà÷åíèå ïîðèñòîñòè 0,4
+7871=Îáû÷íûé êîýôôèöèåíò äèôôóçèè äëÿ íåáîëüøèõ îðãàíè÷åñêèõ ñîåäèíåíèé 0,000001, ò.å. 1E-6; äëÿ ïåïòèäîâ 0,00005, ò.å. 5E-5
+; Menus
+7900=&Load Values
+7910=&Save Values
+7950=&Capillary Flow Calculations
+
+[frmChangeFont]
+; Form Caption
+8000=Ñìåíèòü øðèôò ôîðìóë
+; Combo Boxes
+; Labels
+8060=Ñìåíèòü øðèôò ôîðìóë íà [ðåêîìåíäóåòñÿ MS Sans Serif]:
+8070=Ðàçìåð:
+; Buttons
+
+[frmChangeValue]
+; Form Caption
+8200=Èçìåíèòü çíà÷åíèå
+; Buttons
+8210=&Âîññòàíîâèòü ïî óìîë÷àíèþ
+
+[frmChangeLanguage]
+8400=Âûáðàòü ÿçûê (Choose Language)
+; Labels
+8410=Äîñòóïíûå ÿçûêè äàíû íèæå. Âûáåðèòå ÿçûê, êîòîðûé Âû õîòèòå èñïîëüçîâàòü. Available languages are shown below. Choose the language you wish to use.
+8420=No language files are available. Visit the author's homepage to download alternate languages.
+
+[frmDiff]
+8600=Ðàçíîñòè Âû÷èñëèòåëÿ ïðîöåíòîâ
+8610=&Êîïèðîâàòü
+8611=Êîïèðîâàòü ðåçóëüòàòû â áóôåð
+
+[frmEditAbbrev]
+9000=Ïðàâêà àááðåâèàòóð
+; Buttons
+9010=&Âîññòàíîâèòü ïî óìîë÷àíèþ
+9011=Âîññòàíîâèòü àááðåâèàòóðû, èñïîëüçóåìûå ïðîãðàììîé ïî óìîë÷àíèþ
+9020=&Óäàëèòü
+; Messages
+9050=Äîñòèãíóò ìàêñèìóì
+9060=Ñîæàëåþ, äîïóñòèìî òîëüêî 500 àááðåâèàòóð.
+9090=Àááðåâèàòóðà/ôîðìóëà áóäóò èçìåíåíû íà ââåäåííîå çíà÷åíèå. Âûáåðèòå Óäàëèòü äëÿ óäàëåíèÿ çíà÷åíèÿ, èëè Îòìåíà äëÿ îòìåíû èçìåíåíèé.
+9100=Âû óâåðåíû, ÷òî õîòèòå îòìåíèòü âñå èçìåíåíèÿ?
+9105=Çàêðûòèå êîðîáêè ïðàâêè àááðåâèàòóð
+9110=Âû óâåðåíû, ÷òî õîòèòå âîññòàíîâèòü àááðåâèàòóðû, èñïîëüçóåìûå ïðîãðàììîé ïî óìîë÷àíèþ?
+9115=Âîññòàíîâèòü àááðåâèàòóðû ïî óìîë÷àíèþ
+9120=Warning, test usage of the new/updated abbreviation did not give the same mass as the formula for the abbreviation. This probably indicates a problem with the abbreviation's formula.
+;Table Tool Tip
+9140=
+9141=Ùåë÷îê äëÿ èçìåíåíèÿ çíà÷åíèÿ
+9145=Symbol
+; Table Column Titles
+9150=Çàðÿä
+9160=Ôîðìóëà
+9170=Îáû÷íàÿ àááðåâèàò.
+9180=Àìèíîêèñëîòà
+9190=1-áóêâåííûå
+9195=Comment
+
+[frmEditElem]
+9200=Ïðàâêà ýëåìåíòîâ
+; Buttons
+9210=&Âîññòàíîâèòü ïî óìîë÷àíèþ
+9211=Äëÿ âñåõ ýëåìåíòîâ âîññòàíîâèòü èõ ñðåäíèå àòîìíûå ìàññû, íàéäåííûå â ïðèðîäå
+9220=&Ñáðîñ
+9230=Èñïîëüçîâàòü &ñðåäíèå àòîìíûå ìàññû
+9231=Äëÿ âñåõ ýëåìåíòîâ âîññòàíîâèòü èõ ñðåäíèå àòîìíûå ìàññû, íàéäåííûå â ïðèðîäå
+9240=Èñïîëüçîâàòü ìàññû &èçîòîïîâ
+9241=Äëÿ âñåõ ýëåìåíòîâ âîññòàíîâèòü ìàññû èõ íàèáîëåå ðàñïðîñòðàíåííûõ èçîòîïîâ (äëÿ ìàññ-ñïåêòðîìåòðèè âûñîêîãî ðàçðåøåíèÿ)
+9245=Èñïîëüçîâàòü &öåëûå ìàññû èçîòîïîâ
+9246=Äëÿ âñåõ ýëåìåíòîâ âîññòàíîâèòü öåëî÷èñëåííûå ìàññû èõ íàèáîëåå ðàñïðîñòðàíåííûõ èçîòîïîâ (äëÿ ìàññ-ñïåêòðîìåòðèè íèçêîãî ðàçðåøåíèÿ)
+; Messages
+9250=Ìàññà/ïîãðåøíîñòü áóäóò èçìåíåíû íà ââåäåííîå çíà÷åíèå. Âûáåðèòå Ñáðîñ äëÿ çíà÷åíèÿ ïî óìîë÷àíèþ, èëè Îòìåíà äëÿ îòìåíû èçìåíåíèé.
+9260=Âû óâåðåíû, ÷òî õîòèòå âîññòàíîâèòü ñðåäíèå àòîìíûå ìàññû äëÿ âñåõ ýëåìåíòîâ?
+9265=Èñïîëüçîâàòü ñðåäíèå àòîìíûå ìàññû
+9270=Âû óâåðåíû, ÷òî õîòèòå âîññòàíîâèòü ìàññû íàèáîëåå ðàñïðîñòðàíåííûõ èçîòîïîâ äëÿ âñåõ ýëåìåíòîâ?
+9275=Èñïîëüçîâàòü ìàññû èçîòîïîâ
+9280=Âû óâåðåíû, ÷òî õîòèòå âîññòàíîâèòü öåëî÷èñëåííûå ìàññû íàèáîëåå ðàñïðîñòðàíåííûõ èçîòîïîâ äëÿ âñåõ ýëåìåíòîâ?
+9285=Èñïîëüçîâàòü öåëûå ìàññû èçîòîïîâ
+9290=Âû óâåðåíû, ÷òî õîòèòå âîññòàíîâèòü ìàññû, èñïîëüçóåìûå ïî óìîë÷àíèþ (ñðåäíèå àòîìíûå ìàññû), äëÿ âñåõ ýëåìåíòîâ?
+9295=Âîññòàíîâèòü ìàññû ïî óìîë÷àíèþ
+9300=Åñëè ñäåëàòü ýòî, îòìåíà íåâîçìîæíà.
+9310=Âû óâåðåíû, ÷òî õîòèòå îòìåíèòü âñå èçìåíåíèÿ?
+9315=Çàêðûòèå êîðîáêè ïðàâêè ýëåìåíòîâ
+;Table Tool Tip
+9340=
+9341=Ùåë÷îê äëÿ èçìåíåíèÿ çíà÷åíèÿ
+;Table Column Titles
+9350=Ýëåìåíò
+9360=Ìàññà
+9370=Ïîãðåøíîñòü
+; Combo boxes
+9380=Ñèìâîë ýëåìåíòà|Àòîìíûé íîìåð|Ïîãðåøíîñòü|Çàðÿä
+9390=Ñîðòèðîâàòü ýëåìåíòû ïî:
+
+[frmEquationsBroadening]
+9500=Óðàâíåíèÿ ðàñøèðåíèÿ ïèêà âíå êîëîíêè Extra-column broadening equations
+
+[frmEquationsOpenTube]
+9550=Óðàâíåíèÿ ïîòîêà â ïóñòîì êàïèëëÿðå Equations for flow in an open tube
+
+[frmEquationsPackedCapillary]
+9600=Óðàâíåíèÿ ïîòîêà â çàïîëíåííîì êàïèëëÿðå Equations for flow in a packed capillary
+
+[frmFinderModeWarn]
+; Instructions Label
+9700= Îáû÷íîå èñïîëüçîâàíèå Èñêàòåëÿ ôîðìóë - êîãäà èçâåñòíà ìîíîèçîòîïíàÿ ìàññà ñîåäèíåíèÿ (åå îáû÷íî îïðåäåëÿþò ìàññ-ñïåêòðîìåòðèåé) è íóæíî íàéòè ñîåäèíåíèÿ, ïîòåíöèàëüíî ñîîòâåòñòâóþùèå ýòîé ìàññå.
+9701=Íàïðèìåð, äëÿ ñîåäèíåíèÿ, êîòîðîå ìîæåò ñîäåðæàòü C,H,N,O, íàéäåíà ìàññà 16,0312984 Äàëüòîí, è íóæíû âîçìîæíûå ýìïèðè÷åñêèå ôîðìóëû. Ïîèñê ñ îòêëîíåíèåì äëÿ ìàññû 5000 ÷.í.ì. äàåò H2N, CH4 è O, ñ îòêëîíåíèåì 500 ÷.í.ì. - òîëüêî CH4, ÷òî ÿâëÿåòñÿ ïðàâèëüíûì îòâåòîì.
+9702=×òîáû ïðàâèëüíî èñïîëüçîâàòü ýòî ñðåäñòâî, ïðîãðàììà äîëæíà íàõîäèòüñÿ â ðåæèìå Èçîòîïíûõ ìàññ ýëåìåíòîâ. Ýòî ìîæíî ñäåëàòü, âûáðàâ Ïðàâèòü òàáëèöó ýëåìåíòîâ â ìåíþ Ôàéë, èëè â ãëàâíîì îêíå, èëè çäåñü, èëè ïðîãðàììà ìîæåò ïåðåõîäèòü â ýòîò ðåæèì àâòîìàòè÷åñêè.
+9703=×òî Âû õîòèòå:
+9705= Îáû÷íîå èñïîëüçîâàíèå Ìîäåëèðîâàíèÿ ôðàãìåíòàöèè - ïðåäñêàçàíèå ìàññ ôðàãìåíòîâ, êîòîðûå áóäóò íàáëþäàòüñÿ ïðè ìàññ-ñïåêòðîìåòðèè ïåïòèäà, êîãäà åãî èîíèçèðóþò, ââîäÿò â ïðèáîð è ïðîèñõîäèò åãî ôðàãìåíòàöèÿ ïî îñíîâíîé öåïè.
+9706=Ôðàãìåíòàöèÿ ïåïòèäîâ îáû÷íî èäåò ïî àìèäíûì ñâÿçÿì. Íàïðèìåð ïåïòèä Gly-Leu-Tyr áóäåò äàâàòü ôðàãìåíòû Gly-Leu, Leu-Tyr, Gly, Leu è Tyr. Êðîìå òîãî, ðàñùåïëåíèå àìèäíûõ ñâÿçåé ìîæåò ïðîèñõîäèòü â ðàçëè÷íûõ ìåñòàõ, è ýòî ïðèâîäèò ê ðàçíûì ìàññàì ôðàãìåíòîâ.
+; Buttons
+9720=&Ïðîäîëæèòü
+; Option Buttons
+9750=Ïåðåéòè ñåé÷àñ â ðåæèì &Èçîòîïíûõ ìàññ ýëåìåíòîâ.
+9760=Âñåãäà &àâòîìàòè÷åñêè ïåðåõîäèòü â ðåæèì Èçîòîïíûõ ìàññ.
+9770=Ïðîäîëæèòü, èñïîëüçóÿ ðåæèì &Ñðåäíèõ ìàññ ýëåìåíòîâ.
+; CheckBoxes
+9780=Ïðåêðàòèòü ïîêàçûâàòü ýòî &îêíî.
+
+[frmFinder]
+10000=Èñêàòåëü ôîðìóë
+; Labels
+10010=Âûáèðàþò íóæíûå ýëåìåíòû, ââîäÿò ìîëåêóëÿðíóþ ìàññó èëè ïðîöåíòíûé ñîñòàâ, çàòåì íàæèìàþò Âû÷èñëèòü, ÷òîáû íàéòè ñîåäèíåíèÿ, ñîîòâåòñòâóþùèå çàäàíèþ.
+10020=Ìàêñèìàëüíàÿ ìàññà ñîåäèíåíèÿ:
+10030=Çàäàííàÿ ìîëåêóëÿðíàÿ ìàññà:
+10040=Îòêëîíåíèå äëÿ ìàññû:
+10050=Îòêëîíåíèå äëÿ ïðîöåíòîâ:
+10060=Ìèí
+10070=Ìàêñ
+10080=Ýëåìåíòû
+10090=%%
+10100=Ìàêñ.÷èñëî ôîðìóë
+10105=Àòîìíàÿ ìàññà
+; Percent completed status messages
+10110=% âûïîëíåíî
+10115=Ñîðòèðîâêà
+10120=Ïîèñê
+10125=Ðàáîòà
+10130=Âûïîëíåíî
+10135=ñîåäèíåíèé
+10140=Ñîðòèðîâêà ïðåðâàíà
+10145=Âû÷èñëåíèÿ ïðåðâàíû
+10150=Ôîðìàò
+10155=Ñäåëàíî
+10160=Ôîðìàò ïðåðâàí
+; Listboxes & Textboxes
+10201=Äâîéíîé ùåë÷îê ïî ëþáîé ñòðîêå óâåëè÷èâàåò åå (èñïîëüçîâàòü äëÿ äëèííûõ ñòðîê)
+10221=Âåëè÷èíà, íà êîòîðóþ ìîëåêóëÿðíàÿ ìàññà íàéäåííîãî ñîåäèíåíèÿ ìîæåò îòêëîíÿòüñÿ îò çàäàííîé
+10231=Âåëè÷èíà, íà êîòîðóþ ïðîöåíòíûå ñîäåðæàíèÿ ýëåìåíòîâ â íàéäåííîì ñîåäèíåíèè ìîãóò îòêëîíÿòüñÿ îò çàäàííûõ
+10241=Ìàêñèìàëüíîå ÷èñëî íàéäåííûõ ñîåäèíåíèé
+10251=Ìèíèìàëüíîå ÷èñëî àòîìîâ â íàéäåííîì ñîåäèíåíèè
+10256=Ìàêñèìàëüíîå ÷èñëî àòîìîâ â íàéäåííîì ñîåäèíåíèè
+10260=%
+10261=Çàäàííîå ïðîöåíòíîå ñîäåðæàíèå ýëåìåíòà
+10270=Ý
+10271=Çäåñü ââîäÿò àòîìíóþ ìàññó ýòîãî ýëåìåíòà, èëè ñèìâîë ýëåìåíòà, èëè àááðåâèàòóðó
+; Note the following is 'dm' in English, standing for 'delta mass' or the mass difference
+; of the given result's mass versus the target mass
+10280=dM
+; Note the following is 'ppm' in English, standing for 'parts per million'
+10285=ppm
+; Buttons
+10300=&Îïöèè Èñêàòåëÿ ôîðìóë
+10301=Ãîðÿ÷àÿ êëàâèøà: Ctrl+O
+10310=Âû&÷èñëèòü
+10311=Íàéòè ñîåäèíåíèÿ, ñîîòâåòñòâóþùèå çàäàííûì ïàðàìåòðàì
+10320=&Ïå÷àòü ...
+10330=Êîïè&ðîâàòü êàê RTF
+10331=Êîïèðîâàòü ðåçóëüòàòû â áóôåð â ôîðìàòå RTF
+10340=&Êîïèðîâàòü
+10341=Êîïèðîâàòü ðåçóëüòàòû â áóôåð
+10345=&Display Iso Abundance
+10346=Display the Isotopic Distribution of the currently selected compound (Ctrl+D)
+; Option Buttons
+10350=Ïî &ìîëåêóëÿðíîé ìàññå
+10360=Ïî ïðîöåíòíîìó &ñîñòàâó
+; CheckBoxes
+10370=÷.í.ì. (ppm)
+10380=Show Delta Mass
+10381=Note: Delta mass notation will change as the standard deviation mode is changed (F12 in the main window)
+; Elements (and Custom element phrase)
+10400=Óãëåðîä
+10405=Âîäîðîä
+10410=Àçîò
+10415=Êèñëîðîä
+10420=Äðóãîé
+; Messages
+; Note that 10455 is also used with the Abort button
+10450=Íàæàòà êëàâèøà.
+10455=Îòìåíà
+10460=Ùåë÷îê ìûøè âíå êîðîáêè ðåçóëüòàòîâ.
+10465=Îñòàíîâêà ôîðìàòà.
+10470=Îñòàíîâêà ñîðòèðîâêè.
+10480=Ñóììà ïðîöåíòíûõ ñîäåðæàíèé íå ðàâíà 100%.
+10485=Ïðîäîëæèòü âû÷èñëåíèÿ?
+10490=Íåâîçìîæíî âû÷èñëèòü
+10500=Íàæàòà êëàâèøà.
+10505=Ùåë÷îê ìûøè âíå êîðîáêè ðåçóëüòàòîâ.
+10510=Îñòàíîâêà âû÷èñëåíèé.
+10515=Äîñòèãíóòî ìàêñèìàëüíîå ÷èñëî íàéäåííûõ ñîåäèíåíèé.
+10520=Ìàêñèìàëüíîå ÷èñëî ôîðìóë
+10530=Íàéäåíî ñîåäèíåíèé
+; Note: the following is used when displaying the results of a percent composition
+; search in the Formula Finder. A synonym for 'has' would be 'contains' or 'is composed of'
+10535=
+10540=Îøèáêà ïàìÿòè. Ñïèñîê ðåçóëüòàòîâ, âåðîÿòíî, ïîëîí. Ðåçóëüòàòû ïîêàçàíû.
+10545=Íåõâàòêà ïàìÿòè
+10550=Êîðîáêà ðåçóëüòàòîâ ïóñòà.
+10555=Íå÷åãî êîïèðîâàòü
+10560=Íå÷åãî ïå÷àòàòü
+10565=Âû óâåðåíû, ÷òî õîòèòå ðàñïå÷àòàòü òåêóùèå ðåçóëüòàòû?
+10570=Ïå÷àòü
+
+[frmFinderOptions]
+10800=Îïöèè Èñêàòåëÿ ôîðìóë
+; Labels
+10810=Èñïîëüçîâàòü ïåðåêëþ÷àòåëè äëÿ âûáîðà ðàçëè÷íûõ îïöèé Èñêàòåëÿ ôîðìóë.
+; Textboxes & Comboboxes
+10821=Ìèíèìàëüíûé çàðÿä, îãðàíè÷èâàþùèé íàéäåííûå ñîåäèíåíèÿ
+10831=Ìàêñèìàëüíûé çàðÿä, îãðàíè÷èâàþùèé íàéäåííûå ñîåäèíåíèÿ
+10840=Ïîëíûé ïîèñê|Îãðàíè÷åííûé ïîèñê
+10841=Ïîëíûé ïîèñê íàõîäèò âñå ñîîòâåòñòâóþùèå ñîåäèíåíèÿ, à îãðàíè÷åííûé - ñîåäèíåíèÿ â çàäàííîì èíòåðâàëå àòîìîâ (ïîëíûé îáû÷íî áûñòðåå)
+10850=Ñîðòèðîâêà ïî ôîðìóëå
+10851=Ìåòîä ñîðòèðîâêè ðåçóëüòàòîâ, ñëåäóåò ïîâòîðèòü âû÷èñëåíèÿ äëÿ íîâîé ñîðòèðîâêè
+10855=Ñîðòèðîâêà ïî çàðÿäó
+10860=Ñîðòèðîâêà ïî MM
+10865=Ñîðòèðîâêà ïî m/z
+10870=Çàäàííîå îòíîøåíèå ìàññà/çàðÿä
+10875=Çàäàííàÿ ìîëåêóëÿðíàÿ ìàññà
+; CheckBoxes
+10900=Âû÷èñëèòü &çàðÿä
+10901=Âû÷èñëèòü îáùèé çàðÿä äëÿ êàæäîãî íàéäåííîãî ñîåäèíåíèÿ
+10910=&Èíòåðâàë çàðÿäîâ
+10911=Îãðàíè÷èòü íàéäåííûå ñîåäèíåíèÿ çàäàííûì èíòåðâàëîì çàðÿäîâ
+10920=&Âû÷èñëèòü m/z
+10921=Âû÷èñëèòü îòíîøåíèå ìàññà/çàðÿä äëÿ êàæäîãî íàéäåííîãî ñîåäèíåíèÿ
+10930=&Íàéòè çàäàííîå m/z
+10931=Íàéòè ñîåäèíåíèÿ ñ îòíîøåíèåì ìàññà/çàðÿä, ðàâíûì çàäàííîìó
+10940=&Ñîðòèðîâêà
+10941=Ïðåâðàòèòü ðåçóëüòàòû â ýìïèðè÷åñêèå ôîðìóëû è îòñîðòèðîâàòü èõ
+10950=&Îãðàíè÷åíèå àòîìîâ H
+10951=Îãðàíè÷èòü êîëè÷åñòâî àòîìîâ âîäîðîäà â íàéäåííûõ ñîåäèíåíèÿõ ðåàëüíûì ÷èñëîì
+10960=&Àâòîìàòè÷åñêè óñòàíàâëèâàòü Ìèí è Ìàêñ ïðè îãðàíè÷åííîì ïîèñêå
+10961=Àâòîìàòè÷åñêè óñòàíàâëèâàòü çíà÷åíèÿ ìèíèìóìà è ìàêñèìóìà àòîìîâ ïðè îãðàíè÷åííîì ïîèñêå íà ðåàëüíûé äëÿ çàäàííîé ìàññû èíòåðâàë
+
+[frmMMconvert]
+11000=Êîíâåðòåð ìîëåé/ìàññû è êàëüêóëÿòîð ðàçâåäåíèÿ
+; Combo Boxes
+11010=Ïðåîáðàçîâàòü êîëè÷åñòâî|Íàéòè êîíöåíòðàöèþ|Âû÷èñëèòü ðàçâåäåíèå
+11011=Ïðåîáðàçîâàíèå ìåæäó ðàçëè÷íûìè åäèíèöàìè èçìåðåíèÿ êîëè÷åñòâà, èëè âû÷èñëåíèå êîíöåíòðàöèè ñîåäèíåíèÿ, à òàêæå âû÷èñëåíèå ðàçâåäåíèÿ
+11020=ìîëè|ìèëëèìîëè|ìèêðîìîëè|íàíîìîëè|ïèêîìîëè|ôåìòîìîëè|àòòîìîëè|êèëîãðàììû|ãðàììû|ìèëëèãðàììû|ìèêðîãðàììû|ôóíòû|óíöèè|ëèòðû|deciliters|ìèëëèëèòðû|ìèêðîëèòðû|íàíîëèòðû|ïèêîëèòðû|ãàëëîíû|êâàðòû|ïèíòû
+11021=Èñõîäíàÿ åäèíèöà èçìåðåíèÿ êîëè÷åñòâà
+11026=Åäèíèöà èçìåðåíèÿ êîëè÷åñòâà
+11030=ëèòðû|deciliters|ìèëëèëèòðû|ìèêðîëèòðû|íàíîëèòðû|ïèêîëèòðû|ãàëëîíû|êâàðòû|ïèíòû
+11031=Åäèíèöà èçìåðåíèÿ îáúåìà
+11041=Êîíå÷íàÿ åäèíèöà èçìåðåíèÿ êîëè÷åñòâà
+11051=Åäèíèöà èçìåðåíèÿ êîíöåíòðàöèè
+; Labels
+11080=ã/ìë
+; Textboxes
+11101=Êîëè÷åñòâî ñîåäèíåíèÿ â èñõîäíûõ åäèíèöàõ
+11106=Êîëè÷åñòâî ñîåäèíåíèÿ, ðàñòâîðåííîãî â ðàñòâîðèòåëå
+11111=Ïëîòíîñòü ñîåäèíåíèÿ
+11121=Îáúåì ðàñòâîðèòåëÿ, â êîòîðîì ðàñòâîðåíî ñîåäèíåíèå
+11131=Êîíöåíòðàöèÿ ñîåäèíåíèÿ â ðàñòâîðèòåëå
+; Buttons
+11150=Âû÷èñëèòü &êîëè÷åñòâî
+11151=Âû÷èñëèòü êîëè÷åñòâî ñîåäèíåíèÿ, èñïîëüçóÿ îáúåì è êîíöåíòðàöèþ
+11160=Âû÷èñëèòü &îáúåì
+11161=Âû÷èñëèòü îáúåì ðàñòâîðèòåëÿ, èñïîëüçóÿ êîëè÷åñòâî è êîíöåíòðàöèþ
+11170=Âû÷èñëèòü êîí&öåíòðàöèþ
+11171=Âû÷èñëèòü êîíöåíòðàöèþ ñîåäèíåíèÿ, èñïîëüçóÿ êîëè÷åñòâî è îáúåì
+
+; Dilution-related controls
+11200=Âû÷èñëåíèå ðàçâåäåíèÿ
+11205=Âû÷èñëåíèå èñïàðåíèÿ èëè ñóáëèìàöèè
+11210=Íàéòè îáúåìû ðàñòâîðà/ðàñòâîðèòåëÿ|Íàéòè îáùèé êîíå÷íûé îáúåì|Íàéòè êîíå÷íóþ êîíöåíòðàöèþ|Íàéòè èñõîäíóþ êîíöåíòðàöèþ
+11211=Âåëè÷èíà, êîòîðóþ íóæíî íàéòè ïðè âû÷èñëåíèè ðàçâåäåíèÿ
+11220=&Ñâÿçàòü èñõîäíóþ êîíöåíòðàöèþ ñ ðàñ÷åòíîé êîíöåíòðàöèåé
+11221=Êîïèðîâàòü ðàñ÷åòíóþ êîíöåíòðàöèþ èç âû÷èñëåíèÿ êîíöåíòðàöèè â èñõîäíóþ êîíöåíòðàöèþ äëÿ ðàçâåäåíèÿ (è íàîáîðîò ïðè èçìåíåíèè ïîñëåäíåé)
+11230=Ñâÿçàòü &åäèíèöû èçìåðåíèÿ îáúåìà
+11231=Èñïîëüçîâàòü îäèíàêîâûå åäèíèöû èçìåðåíèÿ äëÿ îáúåìà èñõîäíîãî ðàñòâîðà, îáúåìà ðàñòâîðèòåëÿ è îáùåãî êîíå÷íîãî îáúåìà
+; Dilution related labels and textbox tooltips
+11250=Èñ&õîäíàÿ êîíöåíòðàöèÿ
+11256=Êîíöåíòðàöèÿ ðàñòâîðåííîãî âåùåñòâà â èñõîäíîì ðàñòâîðå
+11260=Îá&úåì èñõîäíîãî ðàñòâîðà
+11266=Îáúåì (àëèêâîòà) èñõîäíîãî ðàñòâîðà, âçÿòûé äëÿ ðàçâåäåíèÿ
+11270=Êî&íå÷íàÿ êîíöåíòðàöèÿ
+11276=Êîíöåíòðàöèÿ ðàñòâîðåííîãî âåùåñòâà â êîíå÷íîì ðàñòâîðå ïîñëå ðàçâåäåíèÿ
+11280=Îáúåì &äîáàâëåííîãî ðàñòâîðèòåëÿ
+11286=Îáúåì ðàñòâîðèòåëÿ, äîáàâëåííûé ê îáúåìó (àëèêâîòå) èñõîäíîãî ðàñòâîðà
+11290=Îá&ùèé êîíå÷íûé îáúåì
+11296=Îáùèé îáúåì êîíå÷íîãî ðàñòâîðà ïîñëå ñìåøèâàíèÿ èñõîäíîãî ðàñòâîðà è äîáàâëåííîãî ðàñòâîðèòåëÿ
+
+[frmProgramPreferences]
+11500=Ïàðàìåòðû ïðîãðàììû MWT
+; Frame labels
+11510=Ðåæèì àááðåâèàòóð (F3)
+11520=Ðåæèì ðàñïîçíàâàíèÿ ðåãèñòðà (F4)
+11530=Ðåæèì ñòàíäàðòíûõ ïîãðåøíîñòåé (F12)
+11540=Îïöèè ðåæèìà ìàññ ýëåìåíòîâ äëÿ äîïîëíèòåëüíûõ ñðåäñòâ
+11550=Îïöèè âûõîäà èç ïðîãðàììû
+; Buttons
+11600=&Ñîõðàíèòü ïàðàìåòðû
+11610=&Âîññòàíîâèòü ïàðàìåòðû ïî óìîë÷àíèþ
+; Option Buttons
+11650=Îáû÷íûå
+11651=Ðàñïîçíàâàòü îáû÷íûå àááðåâèàòóðû, íî íå àááðåâèàòóðû àìèíîêèñëîò
+11655=Îáû÷íûå + Àìèíîêèñëîòû
+11656=Ðàñïîçíàâàòü îáû÷íûå àááðåâèàòóðû è àááðåâèàòóðû àìèíîêèñëîò
+11660=Íåò
+11661=Èãíîðèðîâàòü âñå àááðåâèàòóðû
+11665=Ïðåîáðàçîâàíèå â âåðõíèé ðåãèñòð
+11666=Ôîðìóëû ïðàâèëüíî ïðåîáðàçóþòñÿ â âåðõíèé ðåãèñòð ïðè àíàëèçå
+11670=Òî÷íîå ñîáëþäåíèå ðåãèñòðà
+11671=Ôîðìóëû íåîáõîäèìî ââîäèòü ñ ïðàâèëüíûì ñîáëþäåíèåì âåðõíåãî ðåãèñòðà
+11675=Ïðîèçâîëüíûé ðåãèñòð
+11676=Ïðè ââîäå ôîðìóë â íèæíåì ðåãèñòðå îíè ïðàâèëüíî âîñïðèíèìàþòñÿ áåç ïðåîáðàçîâàíèÿ â âåðõíèé ðåãèñòð
+11680=Ñîêðàùåííûå
+11681=Ïîêàçûâàòü ñòàíäàðòíûå ïîãðåøíîñòè â ñîêðàùåííîé ôîðìå
+11685=Ýêñïîíåíöèàëüíûå
+11686=Ïîêàçûâàòü ñòàíäàðòíûå ïîãðåøíîñòè â ýêñïîíåíöèàëüíîé ôîðìå
+11690=Äåñÿòè÷íûå
+11691=Ïîêàçûâàòü ñòàíäàðòíûå ïîãðåøíîñòè â ôîðìå äåñÿòè÷íîé äðîáè
+11695=Íåò
+11696=Íå ïîêàçûâàòü ñòàíäàðòíûå ïîãðåøíîñòè
+11700=Âûõîä ñ ïîäòâåðæäåíèåì, òàêæå ïî êëàâèøå Esc
+11701=Îïðåäåëÿåò, áóäåò ëè çàïðîñ íà ïîäòâåðæäåíèå ïðè âûõîäå èç ïðîãðàììû è âîçìîæåí ëè âûõîä ïî êëàâèøå Esc
+11705=Âûõîä áåç ïîäòâåðæäåíèÿ, òàêæå ïî êëàâèøå Esc
+11710=Âûõîä ñ ïîäòâåðæäåíèåì, êëàâèøà Esc íå èñïîëüçóåòñÿ
+11715=Âûõîä áåç ïîäòâåðæäåíèÿ, êëàâèøà Esc íå èñïîëüçóåòñÿ
+; CheckBoxes
+11750=&Ïåðåìåùåíèå âïåðåä ïðè âû÷èñëåíèÿõ (F9)
+11751=Ïåðåìåùàòü êóðñîð íà ëèíèþ ñëåäóþùåé ôîðìóëû ïîñëå âû÷èñëåíèÿ ìîëåêóëÿðíîé ìàññû òåêóùåé ôîðìóëû
+11760=Îáðàáàòûâàòü &êâàäðàòíûå ñêîáêè êàê êðóãëûå
+11761=Îáðàáàòûâàòü êâàäðàòíûå ñêîáêè, [ è ], êàê êðóãëûå, à íå êàê "çàïîëíèòåëè" Âû÷èñëèòåëÿ ïðîöåíòîâ
+11770=Àâòîêîïèðîâàíèå &ìîëåêóëÿðíîé ìàññû (Ctrl+U)
+11771=Àâòîìàòè÷åñêè êîïèðîâàòü ìîëåêóëÿðíóþ ìàññó âûáðàííîé ôîðìóëû â áóôåð ïîñëå êàæäîãî âû÷èñëåíèÿ
+11780=Âû&÷èñëÿòü çàðÿä
+11781=Âû÷èñëÿòü çàðÿä ñîåäèíåíèé (î÷åíü óïðîùåííûå ïðàâèëà, íå ó÷èòûâàþòñÿ äâîéíûå è òðîéíûå ñâÿçè è äð.)
+11800=Âñåãäà àâòîìàòè÷åñêè ïåðåõîäèòü â ðåæèì &Èçîòîïíûõ ìàññ ýëåìåíòîâ
+11801=Âñåãäà àâòîìàòè÷åñêè ïåðåõîäèòü â ðåæèì Èçîòîïíûõ ìàññ ýëåìåíòîâ ïðè âêëþ÷åíèè Èñêàòåëÿ ôîðìóë èëè Ìîäåëèðîâàíèÿ ôðàãìåíòàöèè
+11810=&Íèêîãäà íå ïîêàçûâàòü ïðåäóïðåäèòåëüíîå îêíî î ðåæèìå ìàññ ýëåìåíòîâ
+11811=Íèêîãäà íå ïîêàçûâàòü ïðåäóïðåäèòåëüíîå îêíî î òåêóùåì ðåæèìå ìàññ ýëåìåíòîâ ïðè âêëþ÷åíèè Èñêàòåëÿ ôîðìóë èëè Ìîäåëèðîâàíèÿ ôðàãìåíòàöèè
+11820=&Àâòîñîõðàíåíèå ïàðàìåòðîâ, çíà÷åíèé, ôîðìóë ïðè âûõîäå
+11821=Àâòîìàòè÷åñêè ñîõðàíÿòü ïàðàìåòðû, çíà÷åíèÿ è ôîðìóëû ïðè âûõîäå èç ïðîãðàììû
+11830=Ïîêàçûâàòü ïðåä&óïðåæäåíèÿ (F7)
+11831=Ïîêàçûâàòü ïðåäóïðåæäåíèÿ, êîãäà â ôîðìóëå âîçìîæíà íåîäíîçíà÷íàÿ êîìáèíàöèÿ ñèìâîëîâ (íàïðèìåð Co è CO)
+11840=Ïîêàçûâàòü ïåðåêëþ÷àòåëü &Ðåæèì ìàññ ýëåìåíòîâ
+11841= ãëàâíîì îêíå ïîêàçûâàòü ïåðåêëþ÷àòåëü äëÿ áûñòðîé ñìåíû ðåæèìîâ ìàññ ýëåìåíòîâ
+11850=Ïîêàç&ûâàòü âñïëûâàþùèå ïîäñêàçêè
+11851=Ïîêàçûâàòü êîðîòêèå ñîîáùåíèÿ-ïîäñêàçêè òîãäà, êîãäà ìûøü ïðîõîäèò íàä íåêîòîðûìè êíîïêàìè è çîíàìè
+11860=Âû&äåëåíèå ïîëÿ ââîäà ïðè âûáîðå
+11861=Âñå ïîëå ââîäà âûäåëÿåòñÿ ïðè ïåðåìåùåíèè ê íåìó êóðñîðà èëè ïðè ùåë÷êå ìûøüþ (íå äëÿ âñåõ ïîëåé)
+11870=Ñêðûâàòü íåàêòèâíîå &ãëàâíîå îêíî ïðîãðàììû
+11871=Ñêðûâàòü ãëàâíîå îêíî ïðîãðàììû ïðè èñïîëüçîâàíèè Èñêàòåëÿ ôîðìóë, Êîíâåðòåðà ìîëåé/ìàññû è ò.ï.
+11881=Óìåíüøèòü ÷èñëî, ÷òîáû îêíî ôîðìóë íå çàïîëíÿëî ýêðàí, ïîñëå ýòîãî çàêðûòü è ïåðåçàïóñòèòü ïðîãðàììó. Ìàêñèìóì çàâèñèò îò ðàçðåøåíèÿ ýêðàíà.
+11885=Ìàêñèìàëüíîå ÷èñëî ôîðìóë íà ýêðàíå
+11890=Module to show at startup
+11896=Module to show when the program starts
+11898=Main Window|Formula Finder|Capillary Flow Calculator|Mole/Mass Converter|Peptide Seq Fragmentation Modeller|Amino Acid Notation Converter|Isotopic Distribution Modeller
+
+; Messages
+11900=Çíà÷åíèÿ è ïàðàìåòðû àâòîìàòè÷åñêè ñîõðàíåíû.
+11910=Ïàðàìåòðû ïî óìîë÷àíèþ âîññòàíîâëåíû.
+11920=Çíà÷åíèÿ è ôîðìóëû ñîõðàíåíû.
+11925=Çíà÷åíèÿ è ôîðìóëû ÍÅ ñîõðàíåíû, ïîñêîëüêó èñïîëüçóåòñÿ ïàðàìåòð /X â êîìàíäíîé ñòðîêå.
+11930=Ïàðàìåòðû ñîõðàíåíû.
+11935=Ïàðàìåòðû ÍÅ ñîõðàíåíû, ïîñêîëüêó èñïîëüçóåòñÿ ïàðàìåòð /X â êîìàíäíîé ñòðîêå..
+
+[frmFragmentationModelling]
+12000=Ìîäåëèðîâàíèå ôðàãìåíòàöèè ïåïòèäîâ
+; General Combo Boxes
+12010=1-áóêâåííûå îáîçíà÷åíèÿ|3-áóêâåííûå îáîçíà÷åíèÿ
+12011=Òèï îáîçíà÷åíèé àìèíîêèñëîò
+12020=Ïîäáîð &èîíîâ
+; Textboxes
+12051=Çäåñü ââîäÿò íàáîð àìèíîêèñëîò
+12061=Ñìåùåíèå íà äàííóþ âåëè÷èíó ìàññ çàãðóæåííûõ èîíîâ äëÿ ïîäáîðà ñ öåëüþ êîððåêòèðîâêè îòêëîíåíèé ìàññ-ñïåêòðà
+; Frames, labels, and checkboxes
+12100=Íàáîð:
+12150=Òåðìèíàëüíûå N è C
+12160=&N
+12170=&C
+12180=H (hydrogen)|HH+ (protonated)|C2OH3 (acetyl)|C5O2NH6 (pyroglu)|CONH2 (carbamyl)|C7H6NS (PTC)|(none)
+12190=OH (hydroxyl)|NH2 (amide)|(bare)
+12200=Òèïû èîíîâ
+12210=&A èîíû
+12215=&B èîíû
+12220=&Y èîíû
+12230=Íåéòðàëüíûå ïîòåðè
+12236=Çäåñü âûáèðàþò èîíû, ê êîòîðûì îòíîñÿòñÿ ïîòåðè
+12240=Ïîòåðÿ H2O
+12250=Ïîòåðÿ NH3
+12255=Ïîòåðÿ PO4
+12260=Îïöèè çàðÿäà
+12270=Èîíû ñ &çàðÿäîì 2+
+12280=Ïîðî&ã
+12286=Äëÿ èîíîâ ñ m/z âûøå ýòîãî ïîðîãà áóäóò âû÷èñëÿòüñÿ çíà÷åíèÿ 2+ m/z
+12300=Îïöèè ïîäáîðà èîíîâ
+12310=&Óäàëÿòü èîí-ïðåäøåñòâåííèê
+12320=Ìàññà èîíà
+12330=Äîïóñê äëÿ ìàññû
+12340=&Äîïóñê äëÿ ïîäáîðà èîíà
+12350=Ä
+12355=&Êîððåêòèðîâêà
+12360=Ñòàòèñòèêà èîíîâ
+12370=Çàãðóæåíî
+12375=Îñòàëîñü ïîñëå ñáîðà
+12380=Â ïðåäåëàõ äîïóñêà
+12385=Ïðåäøåñòâåííèê íå íàéäåí
+12390=Ïðåäøåñòâåííèê óäàëåí
+12395=Ïðåäøåñòâåííèê íå óäàëåí
+12400=Ïîäîáðàíî èîíîâ
+12405=Îöåíêà
+12410=Mass Information
+12420=Element Mode
+12425=Average
+12430=Isotopic
+
+; Column titles in grids
+; Note: # means 'number', Immon. means 'immonium', and Seq. means 'sequence'
+12500=#
+12510=Èììîí.
+12520=Íàáîð
+12550=Ìàññà
+12560=Èíòåíñèâí.
+12570=Symbol
+
+; Menu Items
+12800=Çàãðóçèòü èíôîðìàöèþ î &íàáîðå
+12810=&Ñîõðàíèòü èíôîðìàöèþ î íàáîðå
+12820=Çàãðóçèòü ñïèñîê &èîíîâ äëÿ ïîäáîðà
+12830=&Çàêðûòü
+12840=&Êîïèðîâàòü ïðåäñêàçàííûå èîíû
+12850=Ê&îïèðîâàòü ïðåäñêàçàííûå èîíû êàê RTF
+12855=Êî&ïèðîâàòü ïðåäñêàçàííûå èîíû êàê Html
+12860=&Âñòàâèòü ñïèñîê èîíîâ äëÿ ïîäáîðà
+12865=Copy Sequence Molecular &Weight
+12870=Î÷èñòèòü &ñïèñîê èîíîâ äëÿ ïîäáîðà
+12880=&Ñïèñîê èîíîâ äëÿ ïîäáîðà
+12900=Ïðåäñêàçàííûé &ìàññ-ñïåêòð
+12910=&Îáíîâëÿòü ìàññ-ñïåêòð ïðè èçìåíåíèÿõ
+12915=&Dta.Txt File Browser
+12920=&Îïöèè ñïèñêà èîíîâ äëÿ ïîäáîðà
+12925=Edit Residue &Modification Symbols
+12930=&Àâòîìàòè÷åñêàÿ êîððåêòèðîâêà èîíîâ äëÿ ïîäáîðà
+12940=&Ìîäåëèðîâàíèå ôðàãìåíòàöèè
+12950=&Copy Selected Ions
+12960=&Delete All (Clear list)
+
+[frmMsPlot]
+13000=Ãðàôèê - Ìàññ-ñïåêòð
+; The following is an abbreviation for the word 'Location'
+13010=Ïîç.
+
+; Legend Items
+13030=Ïðåäñêàçàííûå èîíû
+13035=Çàãðóæåííûå èîíû
+
+; Menu Items
+13100=&Ýêñïîðò äàííûõ
+13150=&Òèï ãðàôèêà
+13160=&Ïðîñòûå ïèêè (óõîäÿùèå ê íóëþ)
+13170=&Ãàóññîâû ïèêè
+13180=Óñòàíîâèòü ýôôåêòèâíîå &ðàçðåøåíèå
+13190=Ëèíèè ñåòêè ïî îñè X
+13200=Ëèíèè ñåòêè ïî îñè Y
+13210=Îòìåòêè ñ &÷èñëàìè (ïðèáëèæåííî)
+13220=Ïî îñè &X
+13230=Ïî îñè &Y
+13235=&Êà÷åñòâî ãðàôèêà (âëèÿåò íà ñêîðîñòü)
+13240=Êà÷åñòâî &Ãàóññîâà ïðåäñòàâëåíèÿ
+13245=Êîýôôèöèåíò &àïïðîêñèìàöèè
+13250=Óñòàíîâèòü èíòåðâàë ïî îñè &X
+13260=Óñòàíîâèòü èíòåðâàë ïî îñè &Y
+13270=&Àâòîìàñøòàáèðîâàíèå ïî îñè Y
+13280=&Ôèêñèðîâàòü ìèíèìóì ïî îñè Y â íóëå
+13290=&Óìåíüøèòü äî ïðåäøåñòâóþùåãî
+13295=Ctrl+Z èëè ïðàâàÿ êíîïêà ìûøè
+13300=Óìåíüøèòü, ÷òîáû ïîêàçàòü &âñå
+13310=Ðåæèì êóðñîðà &ìûøè
+13315=Ïðîáåë ïîçâîëÿåò ñäâèíóòü
+13320=&Âûäåëèòü êîðîáêó äëÿ óâåëè÷åíèÿ/óìåíüøåíèÿ
+13330=&Ñäâèíóòü ãðàôèê
+13340=&Ïîêàçàòü òåêóùóþ ïîçèöèþ
+13342=Ïîêàçàòü &ëåãåíäó
+13345=Âîññòàíîâèòü &îïöèè ïî óìîë÷àíèþ
+13350=&Óâåëè÷èòü/óìåíüøèòü êîðîáêó
+13360=Ó&âåëè÷èòü
+13365=Ëåâàÿ êíîïêà ìûøè
+13370=Óâåëè÷èòü ïî ãîðèçîíòàëè
+13380=Óâåëè÷èòü ïî âåðòèêàëè
+13390=Ó&ìåíüøèòü
+13400=Óìåíüøèòü ïî ãîðèçîíòàëè
+13410=Óìåíüøèòü ïî âåðòèêàëè
+
+[frmIonMatchOptions]
+14000=Îïöèè ñïèñêà èîíîâ äëÿ ïîäáîðà
+; Buttons
+14010=&Âîññòàíîâèòü ïî óìîë÷àíèþ
+14020=Edit Auto-Label Options
+
+; Explanations
+14050=Êîãäà â ïðîãðàììó èìïîðòèðóþò ñïèñîê èîíîâ, èîíû ñ áëèçêèìè ìàññàìè ìîæíî îáúåäèíèòü âìåñòå ïðè ïîìîùè ïðîöåññà ñáîðà, ÷òîáû óìåíüøèòü îáùåå ÷èñëî òî÷åê äàííûõ. Ïîòîì èîíû îêîëî èîíà-ïðåäøåñòâåííèêà ìîæíî óäàëèòü.
+14055= Çàòåì èíòåíñèâíîñòè èîíîâ íîðìàëèçóþòñÿ ïî çàäàííîé èíòåíñèâíîñòè è îíè ðàñïîëàãàþòñÿ ïî óìåíüøåíèþ èíòåíñèâíîñòè. Èîíû ñ íàèáîëüøåé èíòåíñèâíîñòüþ (äî ÷èñëà èñïîëüçóåìûõ èîíîâ) äåëÿòñÿ íà îòäåëüíûå ãðóïïû ïî ìàññå è èîíû â êàæäîé ãðóïïå âíîâü íîðìàëèçóþòñÿ.
+14060=Íåòðóäíî âû÷èñëèòü ìàññû ïðåäñêàçàííûõ èîíîâ äëÿ äàííîãî ïåïòèäà. Îäíàêî ìàññàì òàêæå íóæíî íàçíà÷èòü çíà÷åíèÿ èíòåíñèâíîñòåé.
+14065= Èîíàì B è Y îáû÷íî íàçíà÷àþò îäèíàêîâóþ èíòåíñèâíîñòü, òîãäà êàê èîí A îáû÷íî èìååò èíòåíñèâíîñòü â 5 ðàç ìåíüøå. Ìîæíî äîáàâèòü "ïëå÷åâûå" èîíû (ñ ìàññàìè +/- 1 Ä îò ìàññû èîíîâ B è Y), à òàêæå ó÷åñòü íåéòðàëüíûå ïîòåðè (H2O è NH3).
+
+; Frames, labels, and checkboxes
+14100=Îïöèè íîðìàëèçàöèè ïðè èìïîðòå äàííûõ
+14110=&Îáúåäèíåíèå èîíîâ (Ñáîð äàííûõ)
+14115=Äîïóñê äëÿ ìàññû
+14120=Íîðìàëèçîâàííàÿ èíòåíñèâíîñòü
+14130=×èñëî èñïîëüçóåìûõ èîíîâ
+14140=Ãðóïï ïî ìàññå
+14150=Èíòåíñèâíîñòè ïðåäñêàçàííûõ èîíîâ
+14160=Èíòåíñèâíîñòü èîíà A
+14165=Èíòåíñèâíîñòü èîíà B
+14170=Èíòåíñèâíîñòü èîíà Y
+14180="Ïëå÷åâûå" èîíû äëÿ èîíîâ B/Y
+14190=Íåéòðàëüíûå ïîòåðè
+14200=Frgamentation Spectrum Labels
+14210=Label main ions (a, b, y)
+14220=Label neutral loss ions
+14230=Emphasize Proline y ions
+14240=Spectrum Plotting Options
+14250=Fragmentation Data Color
+14255=Matching Ion Data Color
+14258=Click to change
+14260=Plot Fragmentation Spectrum Inverted
+14270=Auto-Label Peaks on Matching Ion Spectrum
+
+[frmSetValue]
+14500=Óñòàíîâèòü çíà÷åíèå
+14510=&Óñòàíîâèòü
+14520=&Çàïóñê
+
+[frmProgress]
+14700=Ïðîöåññ
+14710=Ùåë÷îê äëÿ ïàóçû
+14715=Ïîäãîòîâêà ê ïàóçå
+14720=Ïàóçà
+14725=Âîçîáíîâëåíèå
+14730=(Íàæàòü Esc äëÿ îòìåíû)
+14740=ìèí. ïðîøëî/îñòàëîñü
+
+[frmIsotopicDistibution]
+15000=Isotopic Distribution
+; Frames, labels, and checkboxes
+15050=Formula:
+15060=Results:
+15070=Çàðÿä:
+15100=&Plot Results
+15105=&Auto-Label Peaks
+15110=&Compute
+15120=Plot Data Color
+15126=Click to change
+15130=Plot Type
+15140=Sticks to Zero|Gaussian Peaks
+15145=Sticks to Zero|Gaussian Peaks|Lines Between Points
+15151=Isotopic distribution results
+15160=Paste list of ions to compare
+15165=Clear List
+15170=Comparison list data points:
+15190=Options
+15195=Comparison List
+; Column headers in the results box
+15200=Isotopic Abundances for
+15210=Mass/Charge
+15215=Neutral Mass
+15220=Fraction
+15230=Intensity
+15300=Warning, the ion comparison list contains a large number of data points. Do you really want to convert each point to a Gaussian curve?
+15305=Large Data Point Count
+
+[frmAminoAcidModificationSymbols]
+15500=Amino Acid Modification Symbols Editor
+;Directions
+15550=Modified residues in an amino acid sequence are notated by placing a modification symbol directly after the residue's 1 letter or 3 letter abbreviation.
+15555=The phosphorylation symbol is defined separately because phosphorylated residues can lose a phosphate group during fragmentation.
+15560=As an example, if the phosphorylation symbol is *, then in the sequence 'GlyLeuTyr*' the tyrosine residue is phosphorylated.
+15565=Allowable symbols for user-defined modifications are
+15570=Modification symbols can be more than 1 character long, though it is suggested that you keep them to just 1 character long to make it easier for the parsing routine to correctly parse residues with multiple modifications.
+15575=If a residue has multiple modifications, then simply place the appropriate modification symbols after the residue, for example in 'FLE*#L' the E residue is modified by both the * and # modifications.
+15580=Modification masses can be negative values, as well as positive values.
+;Table Tool Tip
+15600=
+15601=Click to change a modification symbol
+; Table column headers
+15610=Symbol
+15620=Mass
+15640=Comment
+; Labels
+15700=Modification Symbols Defined
+15710=Single click to edit or remove. Click in blank row to add.
+15720=Standard Modifications
+15730=Phosphorylation Symbol:
+; Messages
+15750=The amino acid symbol modification will be updated with the parameters below. Select Remove to delete the modification symbol or Cancel to ignore any changes.
+15760=Warning, the new phosphorylation symbol is already being used for another modification. Do you really want to use this symbol for phosphorylation and consequently remove the other definition?
+15765=Modification Symbol Conflict
+15770=Are you sure you want to lose all changes?
+15775=Closing Edit Modification Symbols Window
+; Buttons
+15800=&Reset to Defaults
+15801=Resets modification symbols to defaults
+15810=&Add selected to list
+
+[frmDtaTxtFileBrowser]
+16000=_Dta.Txt File Browser
+; Labels
+16050=Scan Number Start
+16060=Scan Number End
+16070=Parent Ion MH+
+16080=Parent Ion Charge
+; Buttons
+16100=&Jump to scan
+16101=Shortcut is Ctrl+J
+16110=&Keep Window On Top
+
+[ErrorAndStatusMessages]
+20001=Íåèçâåñòíûé ýëåìåíò
+20003=Íå çàêðûòû êðóãëûå ñêîáêè
+20004=Íåñîîòâåòñòâèå êðóãëûõ ñêîáîê
+20005=Íåëüçÿ èñïîëüçîâàòü 0 ñðàçó ïîñëå ñèìâîëà ýëåìåíòà èëè -
+20006=×èñëî ñëèøêîì âåëèêî èëè äîëæíî áûòü òîëüêî ïîñëå [, ), - èëè ^
+20007=×èñëî ñëèøêîì âåëèêî
+20011=×èñëà äîëæíû ñòîÿòü çà ëåâûìè [, à íå çà ïðàâûìè ]
+20012=Ïîñëå ëåâîé [ èëè äåñÿòè÷íîé çàïÿòîé äîëæíî áûòü ÷èñëî
+20013=Íå çàêðûòû êâàäðàòíûå ñêîáêè
+20014=×èñëî ìîæåò áûòü òîëüêî ïîñëå ñèìâîëà ýëåìåíòà, [, ), - èëè ^
+20015=Íåñîîòâåòñòâèå êâàäðàòíûõ ñêîáîê
+20016=Íåëüçÿ èñïîëüçîâàòü âëîæåííûå [] èëè [] âíóòðè ïîëèãèäðàòîâ
+20018=Íåèçâåñòíûé ýëåìåíò
+20020=Ïîñëå ^ äîëæíî áûòü ÷èñëî - ìàññà èçîòîïà
+20022=Ïîñëå ìàññû èçîòîïà (÷èñëî ïîñëå ^) äîëæåí áûòü ñèìâîë ýëåìåíòà
+20023=Ìàññà èçîòîïà ïîñëå ^ íå ìîæåò áûòü îòðèöàòåëüíîé
+20024=Äëÿ àááðåâèàòóð ìàññû èçîòîïîâ íå èñïîëüçóþòñÿ
+20025=Ïîñëå ìíîæèòåëÿ (÷èñëî ïîñëå -) äîëæåí áûòü ñèìâîë ýëåìåíòà
+20026=Äëÿ àááðåâèàòóð ìàññû èçîòîïîâ íå èñïîëüçóþòñÿ; D - àááðåâèàòóðà
+20027=×èñëî íå ìîæåò ñîäåðæàòü áîëåå îäíîé äåñÿòè÷íîé çàïÿòîé
+20028=Circular abbreviation reference; can't have an abbreviation referencing a second abbreviation that depends upon the first one
+20030=Invalid formula subtraction; one or more atoms (or too many atoms) in the right-hand formula are missing (or less abundant) in the left-hand formula
+20050=Çàäàííîå çíà÷åíèå áîëåå 100% íåäîïóñòèìî.
+20075=Â ñòðîêå êàëüêóëÿòîðà íåëüçÿ èñïîëüçîâàòü áóêâû
+20076=Íå çàêðûòû êðóãëûå ñêîáêè
+20077=Íåñîîòâåòñòâèå êðóãëûõ ñêîáîê
+20078=×èñëî íå íà ìåñòå, ëèáî ñëèøêîì áîëüøîå/ìàëîå/äëèííîå
+20080=Îïåðàòîð íå íà ìåñòå
+20081=Ïåðåìåííàÿ òðåêà (track variable) ìåíåå èëè ðàâíà 1; äåôåêò ïðîãðàììû. Ïðîøó ñîîáùèòü ïðîãðàììèñòó.
+20082=Ïðîïóùåí îïåðàòîð.
+20085=Íåëüçÿ âîçâåñòè îòðèöàòåëüíîå ÷èñëî â äðîáíóþ ñòåïåíü
+20086=Íåëüçÿ âîçâåñòè íîëü â îòðèöàòåëüíóþ ñòåïåíü
+20087=Íåëüçÿ âîçâåñòè íîëü â íóëåâóþ ñòåïåíü
+20089=Ïîñëå ^ äîëæíî áûòü îäíî ÷èñëî (ìîæíî îòðèöàòåëüíîå)
+20090=×èñëî íå ìîæåò ñîäåðæàòü áîëåå îäíîé äåñÿòè÷íîé çàïÿòîé
+20091=Ïîïûòêà ïîäåëèòü ÷èñëî íà íîëü. Ñëåäóåò èñïðàâèòü âûðàæåíèå è ïîâòîðèòü âû÷èñëåíèÿ.
+20092= ìàòåìàòè÷åñêèõ âûðàæåíèÿõ ïðîáåëû íåäîïóñòèìû
+20093=Òî÷êà ÿâëÿåòñÿ äåñÿòè÷íûì ñèìâîëîì
+20094=Çàïÿòàÿ ÿâëÿåòñÿ äåñÿòè÷íûì ñèìâîëîì
+20095=Ïîñëå äåñÿòè÷íîé çàïÿòîé äîëæíà áûòü öèôðà
+20100=Îøèáêà ñîõðàíåíèÿ ôàéëà àááðåâèàòóð
+20110=Çàíîâî ñîçäàí ôàéë àááðåâèàòóð, èñïîëüçóåìûõ ïðîãðàììîé ïî óìîë÷àíèþ.
+20115=Ñòàðûé ôàéë ïåðåèìåíîâàí â
+20120=Â ôàéëå àááðåâèàòóð íå íàéäåí çàãîëîâîê [AMINO ACIDS]. Îí äîëæåí áûòü âûøå çàãîëîâêà [ABBREVIATIONS].
+20130=Â ôàéëå àááðåâèàòóð íå íàéäåí çàãîëîâîê [ABBREVIATIONS]. Îí äîëæåí áûòü íèæå çàãîëîâêà [AMINO ACIDS].
+20135=Íàæàòü Äà, ÷òîáû ïðîäîëæèòü òîëüêî ñ àááðåâèàòóðàìè àìèíîêèñëîò.
+20140=Ôàéë àááðåâèàòóð íå íàéäåí â êàòàëîãå ïðîãðàììû
+20150=Îøèáêà çàãðóçêè/ñîçäàíèÿ ôàéëà àááðåâèàòóð
+20160=Àááðåâèàòóðà èãíîðèðóåòñÿ; íåâåðíàÿ ôîðìóëà
+20170=Èãíîðèðóåòñÿ óäâîåííàÿ àááðåâèàòóðà
+20180=Àááðåâèàòóðà èãíîðèðóåòñÿ; íåâåðíûé ñèìâîë
+20190=Àááðåâèàòóðà èãíîðèðóåòñÿ; ñëèøêîì äëèííàÿ
+20200=Èãíîðèðóåòñÿ íåâåðíàÿ ñòðîêà
+20210=Çàíîâî ñîçäàí ôàéë ýëåìåíòîâ, èñïîëüçóåìûõ ïðîãðàììîé.
+20220=Âîçìîæíî íåâåðíàÿ ìàññà ýëåìåíòà
+20230=Âîçìîæíî íåâåðíàÿ ïîãðåøíîñòü äëÿ ýëåìåíòà
+20250=Ñòðîêà èãíîðèðóåòñÿ; íåâåðíûé ñèìâîë ýëåìåíòà
+20260=Â ôàéëå ýëåìåíòîâ íå íàéäåí çàãîëîâîê [ELEMENTS]. Îí äîëæåí áûòü â ôàéëå.
+20265=Íàæàòü Äà, ÷òîáû ïðîäîëæèòü ñ ìàññàìè ýëåìåíòîâ ïî óìîë÷àíèþ.
+20270=Ôàéë ýëåìåíòîâ íå íàéäåí â êàòàëîãå ïðîãðàììû
+20280=Îøèáêà çàãðóçêè/ñîçäàíèÿ ôàéëà ýëåìåíòîâ
+20305=Ïðîäîëæèòü ñ èñïîëüçóåìûì ðàíåå ôàéëîì òåêñòîâ.
+20320=Îøèáêà ñîõðàíåíèÿ ôàéëà ýëåìåíòîâ
+20330=Îøèáêà çàãðóçêè/ñîçäàíèÿ ôàéëà çíà÷åíèé è ôîðìóë
+20340=Íàæàòü Äà, ÷òîáû ïðîäîëæèòü áåç çàãðóçêè çíà÷åíèé è ôîðìóë.
+20345=Äëÿ óñòðîéñòâ "Òîëüêî äëÿ ÷òåíèÿ", ÷òîáû ïðåäîòâðàòèòü ýòó îøèáêó, èñïîëüçóþò ïàðàìåòð /X â êîìàíäíîé ñòðîêå.
+20350=Îøèáêà
+20360=Îøèáêà ñîõðàíåíèÿ ôàéëà ïàðàìåòðîâ
+20380=Îøèáêà ñîõðàíåíèÿ ôàéëà çíà÷åíèé è ôîðìóë
+20400=Îøèáêà çàãðóçêè/ñîçäàíèÿ ôàéëà ïàðàìåòðîâ
+20410=Íàæàòü Äà, ÷òîáû ïðîäîëæèòü áåç çàãðóçêè ïàðàìåòðîâ ïîëüçîâàòåëÿ.
+20440=Íåâîçìîæíî îòêðûòü ôàéë òåêñòîâ äëÿ äàííîãî ÿçûêà èëè îí èìååò íåïðàâèëüíûé ôîðìàò.
+20450=Íåâîçìîæíî çàãðóçèòü òåêñòû äëÿ äàííîãî ÿçûêà
+20460=Ôàéë òåêñòîâ äëÿ äàííîãî ÿçûêà íå íàéäåí â êàòàëîãå ïðîãðàììû
+20470=Íå íàéäåí ôàéë, íåîáõîäèìûé äëÿ âû÷èñëåíèÿ ìîëåêóëÿðíîé ìàññû
+20480=Ôàéë íå íàéäåí
+20490=Òàêîé ôàéë óæå ñóùåñòâóåò. Çàìåíèòü åãî?
+20500=Ôàéë ñóùåñòâóåò
+20510=Îøèáêà ÷òåíèÿ/çàïèñè ôàéëîâ äëÿ ïàêåòíîé îáðàáîòêè
+20515=Íàæàòü Äà äëÿ îòìåíû ïàêåòíîé îáðàáîòêè ôàéëîâ.
+20520=Îøèáêà â ïðîãðàììå
+20530=Ýòè ñòðîêè êîäà íå äîëæíû âñòðå÷àòüñÿ. Ïðîøó ñîîáùèòü ïðîãðàììèñòó.
+20550=Íåëüçÿ èñïîëüçîâàòü Âû÷èñëèòåëü ïðîöåíòîâ, êîãäà âêëþ÷åí ïàðàìåòð "Îáðàáàòûâàòü êâàäðàòíûå ñêîáêè êàê êðóãëûå". Ýòîò ïàðàìåòð ìîæíî èçìåíèòü, âûáðàâ Ñìåíèòü ïàðàìåòðû ïðîãðàììû â ìåíþ Îïöèè.
+20555=Âû÷èñëèòåëü ïðîöåíòîâ íåäîñòóïåí
+20560=Äîñòèãíóòî ìàêñèìàëüíîå êîëè÷åñòâî ñòðîê äëÿ ôîðìóë.
+20570=Òåêóùàÿ ôîðìóëà íå çàïîëíåíà.
+20580=Îòêëþ÷àþò Âû÷èñëèòåëü ïðîöåíòîâ (F11) ïåðåä ñîçäàíèåì íîâîé ñòðîêè äëÿ ôîðìóëû.
+20590=Îøèáêà ïåðåïîëíåíèÿ. Ñëåäóåò óìåíüøèòü ðàçìåð ÷èñëà è ïîâòîðèòü âû÷èñëåíèÿ.
+20600=Îøèáêà
+20605=Ïðîøó âûéòè èç ïðîãðàììû è ñîîáùèòü îá îøèáêå ïðîãðàììèñòó. E-mail - ñì. Î ïðîãðàììå MWT â ìåíþ Ïîìîùü.
+20610=Ïðîáåëû â ôîðìóëàõ íå äîïóñêàþòñÿ
+20620=Íåâåðíûé ñèìâîë
+20630=Íåâîçìîæíî êîïèðîâàòü â íîâóþ ôîðìóëó.
+20650=Òåêóùàÿ ôîðìóëà íå çàïîëíåíà.
+20655=Âêëþ÷åí Âû÷èñëèòåëü ïðîöåíòîâ (F11 äëÿ âûõîäà).
+20660=Âíèìàíèå, ìàññà èçîòîïà, âåðîÿòíî, ñëèøêîì âåëèêà äëÿ ýëåìåíòà
+20662=Âíèìàíèå, ìàññà èçîòîïà, âåðîÿòíî, ñëèøêîì ìàëà äëÿ ýëåìåíòà
+20665=ïðîòèâ ñðåäíåé AM
+20670=Âíèìàíèå, ìàññà èçîòîïà íåäîïóñòèìî ìàëà äëÿ ýëåìåíòà
+20675=ïðîòîí(à,îâ)
+20680=Âíèìàíèå: Âêëþ÷åí ðåæèì Òî÷íîå ñîáëþäåíèå ðåãèñòðà
+20685=Âíèìàíèå: äëÿ Âû÷èñëèòåëÿ ïðîöåíòîâ [ äîëæíà áûòü ïåðåä x
+20690=Âíèìàíèå: Êâàäðàòíûå ñêîáêè îáðàáàòûâàþòñÿ êàê êðóãëûå
+20700=Íåîáõîäèìî îòìåòèòü îäèí èëè íåñêîëüêî ýëåìåíòîâ.
+20705=Ìàêñèìàëüíîå ÷èñëî ôîðìóë äîëæíî áûòü áîëüøå 0.
+20710=Ìàêñèìàëüíîå ÷èñëî ôîðìóë äîëæíî áûòü ìåíüøå
+20715=Ìèíèìàëüíîå ÷èñëî àòîìîâ äîëæíî áûòü 0 èëè áîëüøå.
+20720=Ìèíèìàëüíîå ÷èñëî àòîìîâ äîëæíî áûòü ìåíüøå ìàêñèìàëüíîãî.
+20725=Ìàêñèìàëüíîå ÷èñëî àòîìîâ äîëæíî áûòü ìåíüøå 65 025
+20730=Äëÿ Äðóãîãî ýëåìåíòà íóæíî ââåñòè àòîìíóþ ìàññó.
+20735=Àòîìíàÿ ìàññà äëÿ Äðóãîãî ýëåìåíòà äîëæíà áûòü áîëüøå 0.
+20740=Íóæíî ââåñòè çàäàííóþ ìîëåêóëÿðíóþ ìàññó.
+20745=Çàäàííàÿ ìîëåêóëÿðíàÿ ìàññà äîëæíà áûòü áîëüøå 0.
+20755=Íóæíî ââåñòè ìàêñèìàëüíóþ ìîëåêóëÿðíóþ ìàññó ñîåäèíåíèÿ.
+20760=Ìàêñèìàëüíàÿ ìîëåêóëÿðíàÿ ìàññà ñîåäèíåíèÿ äîëæíà áûòü áîëüøå 0.
+20765=Íóæíî ââåñòè çàäàííîå ïðîöåíòíîå ñîäåðæàíèå äëÿ ýëåìåíòà
+20770=Çàäàííîå ïðîöåíòíîå ñîäåðæàíèå äîëæíî áûòü áîëüøå 0.
+20775= ïîëå Àòîìíàÿ ìàññà äëÿ Äðóãîãî ýëåìåíòà íóæíî ââîäèòü ëèáî òîëüêî ÷èñëî (ìàññó), ëèáî òîëüêî áóêâû. Åñëè èñïîëüçóþòñÿ áóêâû, îíè äîëæíû áûòü ñèìâîëîì îäíîãî ýëåìåíòà èëè îäíîé àááðåâèàòóðîé.
+20780=Íå çàïîëíåíî ïîëå Àòîìíàÿ ìàññà äëÿ Äðóãîãî ýëåìåíòà. Åñëè èñïîëüçóþòñÿ áóêâû, îíè äîëæíû áûòü ñèìâîëîì îäíîãî ýëåìåíòà èëè îäíîé àááðåâèàòóðîé.
+20785=Íåèçâåñòíûé ñèìâîë ýëåìåíòà èëè àááðåâèàòóðà â ïîëå Àòîìíàÿ ìàññà äëÿ Äðóãîãî ýëåìåíòà
+20790=Ìîæíî ââåñòè ñèìâîë òîëüêî îäíîãî ýëåìåíòà èëè îäíó àááðåâèàòóðó.
+20800=Âíèìàíèå, àááðåâèàòóðû íå çàãðóæåíû - Êîìàíäà íå âûïîëíÿåòñÿ.
+20805=Cannot handle fractional numbers of atoms
+
+20900=Îøèáêà ÷òåíèÿ/çàïèñè ôàéëà èíôîðìàöèè î íàáîðå.
+20910=Â ñïèñêå èîíîâ óæå åñòü èîíû. Çàìåíèòü èõ íîâûìè èîíàìè?
+20920=Çàìåíèòü ñóùåñòâóþùèå èîíû
+20930=Çàãðóçêà ñïèñêà èîíîâ
+20940=Ïðîöåññ ïðåðâàí
+20945=Îòìåíà
+20950=Íîðìàëèçàöèÿ èîíîâ
+20960=Íîðìàëèçàöèÿ ïî ãðóïïàì
+20965=Ñîðòèðîâêà ïî èíòåíñèâíîñòè
+20970=Ïîäáîð èîíîâ
+20980=Áóôåð îáìåíà ïóñò. Íåò èîíîâ äëÿ âñòàâêè.
+20985=Íåò èîíîâ
+20990=Âñòàâêà ñïèñêà èîíîâ
+21000=Îïðåäåëåíèå ÷èñëà èîíîâ â ñïèñêå
+21010=Àíàëèç ñïèñêà
+21020=Â áóôåðå îáìåíà íåò ïðàâèëüíîãî ñïèñêà èîíîâ. Ïðàâèëüíûé ñïèñîê èîíîâ - ýòî ñïèñîê èç ïàð ìàññ è èíòåíñèâíîñòåé. Íà êàæäîé ñòðîêå äîëæíà áûòü îäíà ïàðà ìàññà/èíòåíñèâíîñòü, êîòîðûå îòäåëåíû äðóã îò äðóãà çàïÿòîé, ñèìâîëîì òàáóëÿöèè èëè ïðîáåëîì.
+21030=Îøèáêà çàïèñè äàííûõ â ôàéë
+21040=Óñòàíîâèòü èíòåðâàë
+21050=Íà÷àëî
+21055=Êîíåö
+21060=Óñòàíîâèòü èíòåðâàë ïî îñè X
+21065=Óñòàíîâèòü èíòåðâàë ïî îñè Y
+21070=Ââåäèòå íîâûé êîýôôèöèåíò êà÷åñòâà Ãàóññîâà ïðåäñòàâëåíèÿ. ×åì îí âûøå, òåì ïëàâíåå Ãàóññîâû êðèâûå, íî ìåäëåííåå îáíîâëåíèÿ. Èíòåðâàë îò 1 äî 50, ïî óìîë÷àíèþ 20
+21072=Êà÷åñòâî Ãàóññîâà ïðåäñòàâëåíèÿ
+21075=Ââåäèòå íîâûé êîýôôèöèåíò àïïðîêñèìàöèè ãðàôèêà. ×åì îí âûøå, òåì áûñòðåå îáíîâëåíèÿ, íî ìåíåå òî÷íû ãðàôè÷åñêèå ïðåäñòàâëåíèÿ ïðè ïðîñìîòðå øèðîêîãî èíòåðâàëà ìàññ (ïðè óìåíüøåíèè). Èíòåðâàë îò 1 äî 50, ïî óìîë÷àíèþ 10
+21077=Êîýôôèöèåíò àïïðîêñèìàöèè ãðàôèêà
+21080=Ñïåöèôèêàöèè ðàçðåøåíèÿ
+21090=Ðàçðåøåíèå
+21100=Ìàññà X äëÿ ðàçðåøåíèÿ
+21110=Ââåäèòå ïðèáëèæåííîå êîëè÷åñòâî îòìåòîê ñ ÷èñëàìè ïî îñè
+21115=Îòìåòêè ñ ÷èñëàìè ïî îñè
+21120=Ñîçäàíèå Ãàóññîâà ïðåäñòàâëåíèÿ
+21130=Ïîäãîòîâêà ãðàôèêà
+21135=Ðèñîâàíèå ãðàôèêà
+21140=Âû óâåðåíû, ÷òî õîòèòå âîññòàíîâèòü îïöèè ïî óìîë÷àíèþ äëÿ ïîñòðîåíèÿ ãðàôèêà?
+21145=Âîññòàíîâèòü îïöèè ïî óìîë÷àíèþ
+21150=Àâòîìàòè÷åñêàÿ êîððåêòèðîâêà èîíîâ
+21155=Ìàêñèìóì ñìåùåíèÿ
+21160=Øàã ñìåùåíèÿ
+21165=Êîððåêòèðîâêà èîíîâ
+
+21500=Âñå ôàéëû
+21510=Òåêñòîâûå ôàéëû
+21515=txt
+21520=Ôàéëû äàííûõ
+21525=csv
+21530=Ôàéëû íàáîðîâ
+21535=seq
+21540=Ôàéëû ñïèñêîâ èîíîâ
+21545=txt
+21550=cap
+21555=Capillary Flow Info Files
+
+[CautionStatments]
+; Note: Caution statement keynames are case sensitive; i.e. Bi is different than BI
+; You may add new caution statements if desired; however, you will need to save
+; the file with a name other than Lang_English and change the Language= key
+; since this file is not loaded if the language is English
+22000=Âíèìàíèå
+Bi=Bi çíà÷èò âèñìóò; BI çíà÷èò áîð-éîä.
+Bk=Bk çíà÷èò áåðêëèé; BK çíà÷èò áîð-êàëèé.
+Bu=Bu çíà÷èò áóòèë; BU çíà÷èò áîð-óðàí.
+Cd=Cd çíà÷èò êàäìèé; CD çíà÷èò óãëåðîä-äåéòåðèé.
+Cf=Cf çíà÷èò êàëèôîðíèé; CF çíà÷èò óãëåðîä-ôòîð.
+Co=Co çíà÷èò êîáàëüò; CO çíà÷èò óãëåðîä-êèñëîðîä.
+Cs=Cs çíà÷èò öåçèé; CS çíà÷èò óãëåðîä-ñåðà.
+Cu=Cu çíà÷èò ìåäü; CU çíà÷èò óãëåðîä-óðàí.
+Dy=Dy çíà÷èò äèñïðîçèé; DY çíà÷èò äåéòåðèé-èòòðèé.
+Hf=Hf çíà÷èò ãàôíèé; HF çíà÷èò âîäîðîä-ôòîð.
+Ho=Ho çíà÷èò ãîëüìèé; HO çíà÷èò âîäîðîä-êèñëîðîä.
+In=In çíà÷èò èíäèé; IN çíà÷èò éîä-àçîò.
+Nb=Nb çíà÷èò íèîáèé; NB çíà÷èò àçîò-áîð.
+Nd=Nd çíà÷èò íåîäèì; ND çíà÷èò àçîò-äåéòåðèé.
+Ni=Ni çíà÷èò íèêåëü; NI çíà÷èò àçîò-éîä.
+No=No çíà÷èò íîáåëèé; NO çíà÷èò àçîò-êèñëîðîä.
+Np=Np çíà÷èò íåïòóíèé; NP çíà÷èò àçîò-ôîñôîð.
+Os=Os çíà÷èò îñìèé; OS çíà÷èò êèñëîðîä-ñåðà.
+Pd=Pd çíà÷èò ïàëëàäèé; PD çíà÷èò ôîñôîð-äåéòåðèé.
+Ph=Ph çíà÷èò ôåíèë, PH çíà÷èò ôîñôîð-âîäîðîä.
+Pu=Pu çíà÷èò ïëóòîíèé; PU çíà÷èò ôîñôîð-óðàí.
+Py=Py çíà÷èò ïèðèäèí; PY çíà÷èò ôîñôîð-èòòðèé.
+Sb=Sb çíà÷èò ñóðüìà; SB çíà÷èò ñåðà-áîð.
+Sc=Sc çíà÷èò ñêàíäèé; SC çíà÷èò ñåðà-óãëåðîä.
+Si=Si çíà÷èò êðåìíèé; SI çíà÷èò ñåðà-éîä.
+Sn=Sn çíà÷èò îëîâî; SN çíà÷èò ñåðà-àçîò.
+Ti=TI çíà÷èò òðèòèé-éîä; Ti çíà÷èò òèòàí.
+Yb=Yb çíà÷èò èòòåðáèé; YB çíà÷èò èòòðèé-áîð.
+BPY=BPY çíà÷èò áîð-ôîñôîð-èòòðèé; Bpy çíà÷èò áèïèðèäèí.
+BPy=BPy çíà÷èò áîð-ïèðèäèí; Bpy çíà÷èò áèïèðèäèí.
+Bpy=Bpy çíà÷èò áèïèðèäèí.
+Cys=Cys çíà÷èò öèñòåèí; CYS çíà÷èò óãëåðîä-èòòðèé-ñåðà.
+His=His çíà÷èò ãèñòèäèí; HIS çíà÷èò âîäîðîä-éîä-ñåðà.
+Hoh=HoH çíà÷èò ãîëüìèé-âîäîðîä; HOH çíà÷èò âîäîðîä-êèñëîðîä-âîäîðîä (ò.å. âîäà).
+Hyp=Hyp çíà÷èò ãèäðîêñèïðîëèí; HYP çíà÷èò âîäîðîä-èòòðèé-ôîñôîð.
+OAc=OAc çíà÷èò êèñëîðîä-àêòèíèé; Oac çíà÷èò àöåòàò.
+Oac=Oac çíà÷èò àöåòàò.
+Pro=Pro çíà÷èò ïðîëèí; PrO çíà÷èò ïðàçåîäèì-êèñëîðîä.
+PrO=Pro çíà÷èò ïðîëèí; PrO çíà÷èò ïðàçåîäèì-êèñëîðîä.
+Val=Val çíà÷èò âàëèí; VAl çíà÷èò âàíàäèé-àëþìèíèé.
+VAl=Val çíà÷èò âàëèí; VAl çíà÷èò âàíàäèé-àëþìèíèé.
diff --git a/lang_spanish.ini b/lang_spanish.ini
new file mode 100644
index 0000000..a0d0255
--- /dev/null
+++ b/lang_spanish.ini
@@ -0,0 +1,1107 @@
+; Language customization file for the Molecular Weight Calculator program by Matthew Monroe
+; Contact at alchemistmatt@yahoo.com and http://come.to/alchemistmatt/ or http://www.alchemistmatt.com/
+;
+; When customizing the phrases in this file, the ampersand symbol (&) signifies a
+; keyboard shortcut. For example, the default value for key 1000 is &File. When
+; running the program, the F in File will be underlined and the user may press Alt-F
+; to access the File menu (in addition to clicking on the file menu)
+; To improve usability of the program, please try to include the & symbol in menu items
+; and buttons. Note, however, that if two controls on the same form have the same &
+; shortcut, they will not respond to the alt key in the usual way.
+;
+; In this file, items surround by brackets [] are section headers -- the program ignores them
+; when parsing the file. The key values (1000, 1010, 1020, etc.) should not be changed, with
+; the exception that new caution statements may be added at the end of the file.
+; Lines beginning with a semicolon (;) are also ignored since they are treated as comments
+; However, you should not place a ; at the end of a line with an actual key and caption.
+;
+; Keys with multiple values separated by a vertical line (|) represent multiple items loaded
+; into a ComboBox control. When translating to other languages, you must keep the same number
+; of items in the list, or program functionality will be lost. For example, key 7070 contains
+; hours|minutes|seconds Thus, hours, minutes, and seconds will be loaded into a control, from
+; which the user may select one of them. In Spanish, you would use 7070=horas|segundos|minutos
+;
+; If you create a new .Ini file for a foreign language and would like it posted on my
+; web page, simply e-mail it to me.
+;
+; Spanish translation initially by Matthew Monroe and Alexandre R Soares (http://br.geocities.com/ntegti)
+; Improved by Perez de la Hoz (epdlh1@mundofree.com)
+
+[Language]
+Language=Spanish
+
+
+[frmMain Menus]
+; Menu Items
+1000=&Archivo
+1010=Editar Tabla de &Elementos
+1020=Editar &Abreviaturas
+1030=Calcular Masa Desde Valores en &Fichero
+1040=&Imprimir
+1050=&Salir
+1500=&Edición
+1505=&Undo
+1510=Cortar
+1520=&Copiar
+1530=&Pegar
+1540=&Suprimir
+1545=Select &All
+1550=Copiar formula en &RTF
+1560=Copiar &masa molecular
+1570=Copiar &valores porcentuales
+1580=&Duplicar fórmula actual
+1590=Borrar todas las &fórmulas
+1600=Borrar fórmula actual
+1610=Expandir &abreviaturas
+1620=Convertir a fórmula &empírica
+2000=&Ver
+2010=Ver &Todo
+2020=Ver &Una
+2030=Resolver desde &Porcetajes
+2040=&Desactivado
+2050=&Activado
+2500=&Herramientas
+2510=Convertidor de Dilución &Mol/Masa
+2520=Buscador de &Fórmulas
+2530=Convertidor de Nomenclatura de &Aminoacidos
+2533=&Peptide Sequence Fragmentation Modelling
+2536=&Isotopic Distribution Modelling
+2538=Show Isotopic &Distribution for Current Formula
+2540=Ca&lculadora
+2550=Calculador de Flujo &Capilar
+3000=&Opciones
+3010=Eligir &Idioma (Choose language)
+3020=&Preferencias del Programa
+3030=Cambiar &Fuente
+3040=Mantener &Activo
+3050=&Guardar o Restaurar
+3060=&Cargar Valores y Fórmulas por Defecto
+3070=&Guardar Valores y Fórmulas Actuales
+3500=A&yuda
+3510=&Descripción del Programa
+3530=Ver &Etiquetas
+3540=&Sobre Molecular Weight Calculator
+
+[frmMain Status Messages and Verification Messages]
+3600=La linea completa es
+3605=Zooming
+3610=Esta seguro de que desea convertir fórmula actual a empírica?
+3615=Convertir a formula empírica
+3620=Esta seguro de que desea borrar la fórmula?
+3625=Borrar Fórmula
+3630=Seguro que desea expandir las abreviaturas de la fórmula actual a sus equivalentes elementales?
+3635=Expandir abreviaturas
+3640=Se restablecen los valores y fórmulas por defecto, borrándose las fórmulas actuales. Seguro que desea hacer esto?
+3645=Restablecer valores y fórmulas
+3650=Fije el porcentaje objetivo de este elemento a un valor dado. Seleccione Borrar para reajustar el porcentaje o bien seleccione Cancelar para ignorar cualquier cambio.
+3660=Utilice las flechas de paginación Up/Down o Left/Right para moverse por los valores (F11 da salida del modo solver de porcentajes).
+3665=Haga clic sobre celda para cambiar un porcentaje (F11 da salida del modo solver de porcentajes).
+3670=Listo
+3700=Calculando; pulse una tecla o haga clic para interrumpir.
+3710=x es
+3720=Valor calculado
+3730=Target (objetivo)
+3740=Diferencia con el target
+3750=% Solver activado
+3760=Resultados de Molecular Weight Calculator
+3770=Valores y fórmulas por defecto restaurados.
+3780=Está seguro de que desea borrar todas las fórmulas?
+3785=Borrar todas las fórmulas
+3790=Seguro que desea salir?
+3795=Salir del programa
+3800=Cargando abreviaturas
+3810=Cargando elementos
+3820=(usando masas atómicas medias ponderadas)
+3830=(usando masas del isótopo mayoritario de los elementos)
+3840=(usando masas del isótopo mayoritario en número entero)
+3850=Nuevo idioma salvado
+
+[Phrases common throughout application]
+4000=Ce&rrar
+4010=&OK
+4020=&Cancelar
+4030=&Salir
+; The following is the abbreviation for Molecular Weight
+; It must be exactly two letters long
+4040=MW
+4050=Cuidado
+4060=Yes
+4065=No
+
+[frmMain]
+; Form Caption
+4900=Molecular Weight Calculator
+; Labels
+5000=Fórmula
+5010=Modo masa media de elementos
+5020=&Media
+5021=Utilizando masa media de los elementos
+5030=&Isótopo
+5031=Usando la masa del isótopo mayoritario en cada elemento
+5040=&Entero
+5041=Usando masa nominal entera del isótopo mayoritario
+; TextBoxes
+5051=Escriba aquí la fórmula molecular
+; Buttons
+5100=&Calcular
+5101=Determinar la masa molecular de la fórmula actual
+5110=&Nueva Fórmula
+5111=Agrega un nueva fórmula a la lista
+5116=Visualizar una nueva fórmula
+; Grid control
+5201=Teclear para fijar o borrar el valor objetivo
+; Status control
+5301=Teclear doble click en la línea para ampliarla
+5350=MWC ya se está ejecutando. Abrir otro nuevo MWC?
+5355=MWC todavía esta en uso
+
+[frmAboutBox]
+5500=Acerca de MWC
+5510=Este programa es freeware; distribuyalo libremente
+
+[frmIntro]
+5700=Inicializando
+
+[frmAminoAcidConverter]
+; Form Caption
+6000=Convertidor de Nomenclatura de Aminoácidos
+; Labels
+6010=Secuencia de aminoácido de una letra
+6020=Secuencia de aminoácido de tres letras
+; TextBoxes
+6031=Introducir secuencia de abrevación usando 1 letra aquí
+6041=Introducir secuencia de abrevación usando 3 letras aquí
+; Buttons
+6050=&Copiar Secuencia de Tres Letras a Cuadro de Fórmula:
+6060=Copy to &Fragmentation Modeller
+; CheckBoxes
+6080=&Añadir espacio cada 10 residuos
+6090=Residuos &separados por guión
+
+[frmCalculator]
+; Form caption
+6500=Calculadora
+; Textbox
+6511=Escriba la expresión matemática a evaluar aquí
+; Buttons
+6520=&Calcular
+6521=Evalua la actual expresión
+; Status control
+6610=Resultado
+
+[frmCapillaryCalcs]
+; Form Caption
+7000=Cálculos de Flujo Capilar y Velocidad Másica
+; Combo Boxes
+7010=Tubo capilar abierto|Red capilar
+7011=Cambiar entre tubo capilar abierto y red capilar.
+7020=Calcular presión final|Calcular longitud de columna|Calcular diámetro interior|Calcular caudal volumétrico|Calcular caudal usando tiempo muerto
+7030=psi|Pascales|kilo-Pascales|atmósferas|bares|Torr (mm Hg)|dynes/cm^2
+7035=m|cm|mm|micro-m|inches
+7040=Poise [g/(cm*s)]
+7050=mililitro/min|microlitro/min|nanolitro/min
+7060=cm/h|mm/h|cm/min|mm/min|cm/s|mm/s
+7070=horas|minutos|segundos
+7080=mililitro|microlitro|nanolitro|picolitro
+7090=mol/litro|mili-mol/litro|micro-mol/litro|nano-mol/litro|pico-mol/litro|femto-mol/litro|atto-mol/litro|mg/decilitro|mg/mililitro|microgramo/mililitro|nanogramo/mililitro|microgramo/microlitro|nanogramo/microlitro
+7100=pico-mol/min|femto-mol/min|atto-mol/min|pico-mol/s|femto-mol/s|atto-mol/s
+7110=moles|mili-moles|micro-moles|nano-moles|pico-moles|femto-moles|atto-moles
+; Labels and frames
+7200=Presión final
+7210=Longitud de columna
+7220=Diámetro interior columna
+7230=Viscosidad del disolvente
+7240=Diámetro de partícula
+7250=Caudal volumétrico
+7260=Velocidad lineal
+7270=Tiempo muerto de columna
+7280=Volumen de columna
+7290=Porosidad de partícula (epsilon)
+7300=Cálculos de velocidad másica
+7310=Concentración de muestra
+7320=Tiempo de inyección
+7330=Velocidad caudal másico
+7340=Moles inyectados
+7350=Cálculos por ensanchamiento de columna
+7360=Coeficiente de difusión
+7370=Longitud tubo abierto
+7380=Diámetro interior tubo abierto
+7390=Anchura máxima inicial (en base)
+7400=Velocidad lineal óptima
+7410=(en partículas de 5 micro-m)
+7420=Variación de tiempo
+7430=Variación adicional
+7440=Máxima anchura resultante
+7450=Incremento porcentual
+7460=La fórmula actual es
+7480=Masa personalizada
+7500=cm
+7510=um
+7520=cm^2/sec
+7530=sec
+7540=cm/sec
+7550=sec^2
+7560=sec
+7570=g/mole
+; TextBoxes
+7601=Introduzca el número de masa molecular (g/mol) personalizado para utilizar en los cálculos
+; Buttons
+7700=Mostrar/Ocultar Cálculos de Máximo &Ensanchamiento
+7710=&Mirar Textos Explicativos de Ecuaciones
+7730=Mirar Ecuaciones
+; Option Buttons
+7750=&Utilizar la masa del compuesto de la fórmula actual
+7760=Introducir masa molecular &personalizada
+; CheckBoxes
+7800=&Asociar con datos prev.
+; ToolTips
+7851=Un valor típico de viscosidad es 0,0089 poises
+7861=Un valor típico de porosidad es 0,4
+7871=Un coeficiente de difusión típico es 0,000001, es decir 1E-6; Coeficient típico por peptides es 0,00005, es decir 5E-5
+; Menus
+7900=&Load Values
+7910=&Save Values
+7950=&Capillary Flow Calculations
+
+[frmChangeFont]
+; Form Caption
+8000=Cambiar la fuente de la fórmula a:
+; Combo Boxes
+; Labels
+8060=Cambiar la fuente a:
+8070=Tamaño:
+; Buttons
+
+[frmChangeValue]
+; Form Caption
+8200=Cambiar valor
+; Buttons
+8210=&Volver a valores por defecto
+
+[frmChangeLanguage]
+8400=Eligir idioma
+; Labels
+8410=Los idiomas disponibles se muestran abajo. Elija por favor el idioma que usted desea utilizar.
+8420=Si no hay ficheros con el idioma por usted deseado. Visite la Homepage del autor para descargar idiomas alternos.
+
+[frmDiff]
+8600=Diferencia porcentuales de Solver
+8610=&Copiar
+8611=Copiar los resultados al portapapeles
+
+[frmEditAbbrev]
+9000=Editar Abreviaturas
+; Buttons
+9010=&Cargar Abreviaturas por Defecto
+9011=Se borran todas las abreviaturas y se cargan las establecidas por defecto
+9020=&Borrar
+; Messages
+9050=Máximo alcanzado
+9060=Desgraciadamente sólo se permite una lista de 500 abreviaturas.
+9090=La abreviatura o fórmula molecular será cambiada por el valor que usted introduzca. Seleccione Borrar para suprimir la abreviatura o Cancelar para ignorar cualquier cambio.
+9100=Esta seguro que desea perder todas las modificaciones realizadas?
+9105=Cerrando ventana de edición de abreviaturas
+9110=Esta seguro que desea borrar las abreviaturas y cargar las abreviaturas establecidas por defecto?
+9115=Cargar valores por defecto
+9120=Warning, test usage of the new/updated abbreviation did not give the same mass as the formula for the abbreviation. This probably indicates a problem with the abbreviation's formula.
+;Table Tool Tip
+9140=
+9141=Haga click para cambiar una abreviatura, fórmula y/o carga eléctrica
+9145=Symbol
+; Table Column Titles
+9150=Carga Eléctrica
+9160=Fórmula Molecular
+9170=Abreviatura Normal
+9180=Nombre Aminoácido
+9190=Una letra
+9195=Comment
+
+[frmEditElem]
+9200=Editor de Tabla de Elementos
+; Buttons
+9210=&Cargar Valores por Defecto
+9211=Asigna a las masas elementales los pesos isotópicos medios
+9220=&Borrar
+9230=Usar Masas Isotópicas &Medias
+9231=Fija todas las masas elementales a sus pesos medios encontrados en la naturaleza
+9240=Usar Masa del &Isótopo Mayoritario
+9241=Fija todas las masas elementales a la masa del isótopo más común en la naturaleza del elemento en cuestión (para espectrometría de alta resolución)
+9245=Usar Masa Isotópica Nominal &Entera
+9246=Fija todas las masas elementales a la masa nominal entera del isótopo más común en la naturaleza del elemento en cuestión (para espectrometría de baja resolución)
+; Messages
+9250=La masa elemental y/o su desviación será cambiada al valor que usted introduzca. Seleccione Borrar para volver al valor por defecto o Cancelar para ignorar cualquier cambio.
+9260=Esta seguro que desea borrar todos los valores actuales y cargar los valores de masas medias elementales establecidas por defecto?
+9265=Cambiar a las masas medias elementales
+9270=Esta seguro que desea reajustar todos los valores a masas elementales de isótopo mayoritario?
+9275=Cambiar a las masas isotópicas mayoritarias
+9280=Esta seguro que desea reajustar todos los valores a masas elementales de isótopo mayoritario en número entero?
+9285=Cambiar a las masas enteras nominales isotópicas mayoritarias
+9290=Esta seguro que desea reajustar todos los valores a masas elementales establecidas por defecto (masas medias)?
+9295=Cargar Valores por Defecto
+9300=De ser ejecutado, luego no podrá ser cancelado.
+9310=Esta seguro que desea perder todos los cambios realizados?
+9315=Cerrando la ventana del editor de tabla de elementos
+;Table Tool Tip
+9340=
+9341=Haga click para cambiar la masa, carga y/o desviación de un elemento
+;Table Column Titles
+9350=Elemento
+9360=Masa
+9370=Desviación
+; Combo boxes
+9380=Símbolo|Número atómico|Desviación|Carga eléctrica
+9390=Clasificar elementos por:
+
+[frmEquationsBroadening]
+9500=Ecuaciones de Ensanchamiento Adicional de Columna
+
+[frmEquationsOpenTube]
+9550=Ecuaciones de Flujo en Tubo Abierto
+
+[frmEquationsPackedCapillary]
+9600=Ecuaciones de Flujo en Red Capilar
+
+[frmFinderModeWarn]
+; Instructions Label
+9700=El uso típico del buscador de fórmulas resulta cuando la masa monoisotópica de un compuesto es conocida (determinada típicamente por espectrometría de masas) y el compuesto que corresponde con el potencial indicado debe ser buscado.
+9701=Por ejemplo; una masa de 16,0312984 Daltons es medida para una molécula que contiene carbono e hidrógeno, y se desea saber su fórmula empírica posible. Realizando la búsqueda, con una tolerancia del peso de 5.000 ppm los resultados son tres: H2N, CH4, y O. Dentro de 500 ppm solamente se obtiene CH4 que corresponde con el emparejamiento correcto.
+9702=Para alcanzar esta respuesta, el programa se debe fijar en modo Masas Isotópicas Mayoritarias. Esto se puede hacer manualmente o bien el programa puede hacerlo automáticamente.
+9703=Elección:
+9705=The typical use of the Fragmentation Modelling feature is for predicting the masses expected to be observed with a Mass Spectrometer when a peptide is ionized, enters the instrument, and fragments along the peptide backbone.
+9706=The peptide typically fragments at each amide bond. For example, the peptide Gly-Leu-Tyr will form the fragments Gly-Leu, Leu-Tyr, Gly, Leu, and Tyr. Additionally, the cleavage of the amide bond can occur at differing locations, resulting in varying weights.
+; Buttons
+9720=Continuar
+; Option Buttons
+9750=Cambiar al modo Masas &Isotópicas Mayoritarias.
+9760=Cambiar siempre &Automáticamente al modo Masas Isotópicas Mayoritarias.
+9770=Continuar usando Masas Isotópicas &Medias.
+; CheckBoxes
+9780=No &volver a mostrar más este diálogo
+
+[frmFinder]
+10000=Buscador de Fórmulas
+; Labels
+10010=Seleccione los elementos apropiados o agregue otros, introduzca un peso molecular o las composiciones porcentuales en los elementos, entonces pulse Calcular para encontrar los compuestos que corresponden con las especificaciones marcadas.
+10020=Masa máxima de la fórmula:
+10030=Masa molecular objetivo:
+10040=Tolerancia de masa:
+10050=Porcentaje de tolerancia:
+10060=Min.
+10070=Max.
+10080=Elemento
+10090=%
+10100=Nº máx de resultados
+10105=Peso atómico
+; Percent completed status messages
+10110=% terminado
+10115=Ordenando
+10120=Buscando
+10125=Ocupado
+10130=Finalizado
+10135=Compuestos
+10140=Ordenación interrumpida
+10145=Cálculos interrumpidos
+10150=Formateando
+10155=Hecho
+10160=Formato abortado
+; Listboxes & Textboxes
+10201=Haga doble click sobre cualquier línea para ampliarla
+10221=Cantidad de la masa del compuesto que proceda de la masa buscada u objetivo
+10231=Cantidad de porcentaje elemental que proceda del porcentaje buscado u objetivo
+10241=Número máximo de soluciones del compuesto a encontrar.
+10251=Número mínimo de átomos del compuesto a buscar
+10256=Número máximo de átomos del compuesto a buscar
+10260=Porcentaje
+10261=El porcentaje del elemento en la molécula objetivo es
+10270=Masa
+10271=Escriba una masa y una abreviatura, símbolo o marca para ese elemento
+; Note the following is 'dm' in English, standing for 'delta mass' or the mass difference
+; of the given result's mass versus the target mass
+10280=delta mass
+; Note the following is 'ppm' in English, standing for 'parts per million'
+10285=ppm
+; Buttons
+10300=&Opciones del Buscador
+10301=Atajo: Ctrl+O
+10310=&Buscar
+10311=Encuentra los compuestos que corresponden a los parámetros especificados
+10320=&Imprimir
+10330=Copiar &RTF
+10331=Copiar resultados al portapapeles en formato Rich Text Format
+10340=&Copiar
+10341=Copiar resultados al portapapeles
+10345=&Display Iso Abundance
+10346=Display the Isotopic Distribution of the currently selected compound (Ctrl+D)
+; Option Buttons
+10350=Buscar por Masa &Molecular
+10360=Buscar por Composición &Porcentual
+; CheckBoxes
+10370=Modo ppm
+10380=Show Delta Mass
+10381=Note: Delta mass notation will change as the standard deviation mode is changed (F12 in the main window)
+; Elements (and Custom element phrase)
+10400=Carbono
+10405=Hidrógeno
+10410=Nitrógeno
+10415=Oxígeno
+10420=Otro
+; Messages
+; Note that 10455 is also used with the Abort button
+10450=Un tecla fue presionada
+10455=Abortar
+10460=El ratón ha hecho click fuera de la ventana de resultados.
+10465=Parar el formato.
+10470=Parar clasificación.
+10480=La suma de los valores porcentuales no es igual a 100%.
+10485=Continuar con el cálculo?
+10490=No se puede calcular
+10500=Un tecla fue presionada.
+10505=El ratón ha hecho click fuera de la ventana de resultados.
+10510=Busqueda detenida.
+10515=El número máximo de soluciones ha sido alcanzado.
+10520=Número max de soluciones
+10530=Compuestos encontrados
+; Note: the following is used when displaying the results of a percent composition
+; search in the formula finder. A synonym for 'has' would be 'contains' or 'is composed of'
+10535=contiene
+10540=Ha ocurrido un error en la memoria. La lista de los soluciones probablemente este llena. Las soluciones encontradas hasta ahora son las indicadas.
+10545=Fuera de memoria.
+10550=El rectángulo de soluciones está vacío.
+10555=Nada que copiar.
+10560=Nada que imprimir.
+10565=Esta seguro que desea imprimir el resultado actual?
+10570=Imprimir
+
+[frmFinderOptions]
+10800=Opciones del Buscador
+; Labels
+10810=Marque las celdillas para activar las opciones del buscador del fórmulas.
+; Textboxes & Comboboxes
+10821=Límite carga mínima del compuesto
+10831=Límite carga máxima del compuesto
+10840=Búsqueda completa|Búsqueda limitada
+10841=Una búsqueda completa encuentra todos los compuestos que se ajusten mientras que una búsqueda limitada encuentra compuestos dentro de un rango atómico específico.
+10850=Clasificación de fórmulas
+10851=Métodos para clasificar resultados, recalcular o reclasificar.
+10855=Ordenar por carga
+10860=Ordenar por MWC
+10865=Ordenar por m/z
+10870=Relación masa/carga de la objetivo
+10875=Masa molecular objetivo
+; CheckBoxes
+10900=Encontrar &Carga
+10901=Calcular la carga media de cada uno de los elementos encontrados
+10910=&Rango de la Carga Límite
+10911=Límite de compuestos visualizados para un rango de carga específico
+10920=Encontrar m/&z
+10921=Calcular ratio m/z para cada compuesto encontrado
+10930=Buscar &Objetivo m/z
+10931=Buscar compuestos con valores de m/z equivalentes al objetivo
+10940=Or&denar Resultado:
+10941=Convertir resultados a fórmulas empíricas y ordenarlos
+10950=Átomos de H2 &Inteligentes
+10951=Limitar el número de átomos de hidrógeno en cada compuesto a un número realista
+10960=Ajustar &Automáticamente el mín y el máx en búsqueda limitada
+10961=Ajustar automáticamente los valores del mín y el máx de búsqueda a un rango válido para que encuentre la masa objetivo
+
+[frmMMconvert]
+11000=Conversor de Mol y Masa
+; Combo Boxes
+11010=Conversor de cantidades|Calcular concentración|Calcular dilución
+11011=Realiza conversiones con diferentes cantidades de compuesto o ejecuta cálculos de molaridad
+11020=moles|mili-moles|micro-moles|nano-moles|pico-moles|femto-moles|atto-moles|kilogramos|gramos|miligramos|microgramos|Libras|onzas|litros|decilitros|mililitros|microlitros|nanolitros|picolitro|Galones|cuartos|Pintas
+11021=Unidades origen desde donde convertir la cantidad
+11026=Unidades de cantidad a utilizar para el cálculo de la concentración
+11030=litros|decilitros|mililitros|microlitros|nanolitros|picolitros|Galones|cuartos|Pintas
+11031=Unidades del volumen
+11041=Unidades destino a donde convertir la cantidad
+11051=Unidades de concentración
+; Labels
+11080=g/ml
+; Textboxes
+11101=Cantidad a convertir del compuesto
+11106=Cantidad de compuesto que se disolverá en disolvente
+11111=Densidad del compuesto
+11121=El volumen de disolvente en que el compuesto se disuelve
+11131=Concentración del compuesto en la disolución
+; Buttons
+11150=Calcular Canti&dad
+11151=Calcula la cantidad de soluto usando el volumen y la concentración de la disolución
+11160=Calcular &Volumen
+11161=Calcula el volumen de disolución usando la cantidad de soluto y la concentración de la disolución
+11170=Calcular &Concentración
+11171=Calcula la concentración de la disolución usando la cantidad de soluto y el volumen de disolución
+
+; Dilution-related controls
+11200=Cálculos de dilución
+11205=Cálculos de evaporación o sublimación
+11210=Calcular volumen de dilución requerido|Calcular volumen total requerido|Encontrar concentración final|Encontrar concentración inicial
+11211=Cantidad a encontrar para cálculos de dilución
+11220=&Asociar resultado conversión como concentración inicial para dilución
+11221=Copia el resultado del conversor de cantidades como concentración inicial para las diluciones y viceversa si se hacen cambios
+11230=Unidades &homogéneas en la dilución
+11231=Homogeneización de las unidades de volumen soluto, disolvente acuoso y el volumen total final de la dilución
+; Dilution related labels and textbox tooltips
+11250=Concentración &Inicial
+11256=Concentración de la disolución de partida
+11260=Volu&men de concentración inicial
+11266=Volume de la disolución de partida antes de iniciar la dilución con agua destilada (pura)
+11270=Concentración &Final
+11276=Concentración final de soluto al terminar la dilución
+11280=Volumen de dilución re&querido
+11286=Volumen de agua destilada requerido para añadir a la disolución inicial en el proceso de dilución
+11290=Volumen final &Total
+11296=Volumen final de la disolución resultante después de la dilución
+
+[frmProgramPreferences]
+11500=Preferencias de Molecular Weight Calculator
+; Frame labels
+11510=Modo de reconocimiento de abreviaturas (F3)
+11520=Modo de reconocimiento de fórmulas (F4)
+11530=Modo desviación standar (F12)
+11540=Opciones del Buscador de Fórmulas
+11550=Opciones de salida de programa
+; Buttons
+11600=Grabar Opciones como &Defecto
+11610=Cargar &Opciones por Defecto
+; Option Buttons
+11650=Normal
+11651=Reconoce abreviaturas normales, pero no los aminoácidos
+11655=Normal + Aminoácidos
+11656=Reconoce abreviaturas normales y los aminoácidos
+11660=Desconectado
+11661=Ignora todas las abreviaturas
+11665=Por aproximación
+11666=Tantea la nomenclatura de las fórmulas mientras analiza
+11670=Exacto
+11671=Requiere usar fórmulas con nomenclatura exacta
+11675=Inteligente
+11676=Interpreta las fórmulas, y no las capitaliza
+11680=Abreviado
+11681=Visualización abreviada de las desviaciones standar
+11685=Científico
+11686=Visualización en notación científica de las desviaciones standar
+11690=Decimal
+11691=Visualización en forma decimal larga de las desviaciones standar
+11695=Desactivado
+11696=No visualiza las desviaciones standar
+11700=Salir del programa con ESC y luego confirmar salida
+11701=Establecer si la tecla ESCAPE es capaz de cerrar el programa y por otro lado si se exige confirmación a la salida o no
+11705=Salir del programa con ESC sin confirmar salida
+11710=Anulada ESC, pero confirmar salida de programa
+11715=Anulada ESC, y no confirmar salida de programa
+; CheckBoxes
+11750=Activar a&vance automático después de calcular
+11751=Movimiento a una nueva línea de fórmula después de calcular la masa de la fórmula anterior
+11760=Corchetes equivalen a &Paréntesis
+11761=Considerar los corchetes ( [...] ) como paréntesis, y no como ubicadores de porcentajes calculados
+11770=Copiar a&utomaticamente el peso molecular
+11771=Copia automáticamente el valor del peso molecular de la fórmula seleccionada al portapapeles después de cada cálculo
+11780=Cálcular car&ga
+11781=Cálcula la carga eléctrica de los compuestos (lo hace con reglas muy básicas, no pueden corregir anomalías por doble o triple enlace)
+11800=Cambiar automáticamente al modo &sótopo mayoritario
+11801=Cambia automáticamente a masas isotópicas al entrar en el Buscador Fórmulas
+11810=No mostrar &nunca diálogo de advertencia sobre modo de masa al entrar en Buscador
+11811=Activarlo implica que nunca se mostrará el cuadro de advertencia sobre modo de masa al entrar en el Buscador del Fórmulas
+11820=Salvar &automáticamente opciones, valores y fórmulas al salir
+11821=Salva automáticamente opciones, valores y fórmulas seleccionadas en el programa cada vez que se sale
+11830=Mostrar avisos de confusión en la nomenclatura
+11831=Advierte cuando las combinaciones elementales dan posiblemente origen a confusión en fórmulas (como el Co contra el CO)
+11840=Mostrar cambio rápido del modo &másico de elementos
+11841=Muestra el cuadro de opciones que permite cambiar rapidamente los modos másicos de los elementos
+11850=Mostrar etiquetas (tips)
+11851=Muestra brevemente mensajes de ayuda cuando el ratón se sitúa sobre ciertos botones o áreas operativas del programa
+11860=Resaltar campo de texto cuando esta seleccionado
+11861=Resalta la totalidad del campo de texto al moverse sobre él
+11870=Minimizar automáticamente las ventanas &inactivas del programa
+11871=Oculta la ventana principal del programa al usar el convertidor de mol/masa, el buscador de fórmulas ... etc.
+11881=Elija un número más pequeño para evitar que la ventana principal llene la pantalla. Si lo baja, debe salir y reinicializar de nuevo el programa. El número máximo aconsejado dependerá de la resolución en pantalla.
+11885=Número máximo de fórmulas a mostrar
+11890=Module to show at startup
+11896=Module to show when the program starts
+11898=Main Window|Formula Finder|Capillary Flow Calculator|Mole/Mass Converter|Peptide Seq Fragmentation Modeller|Amino Acid Notation Converter|Isotopic Distribution Modeller
+
+; Messages
+11900=Opción de grabación automática de valores salvada.
+11910=Opciones por defecto restauradas.
+11920=Valores y fórmulas grabados.
+11925=Valores y fórmulas NO salvadas ya que la línea de comando / X fue utilizada.
+11930=Opciones por defecto grabadas.
+11935=Opciones por defecto NO salvadas ya que la línea de comando / X fue utilizada.
+
+[frmFragmentationModelling]
+12000=Peptide Sequence Fragmentation Modelling
+; General Combo Boxes
+12010=1 letter notation|3 letter notation
+12011=Amino acid sequence notation type
+12020=&Match Ions
+; Textboxes
+12051=Enter amino acid sequence here
+12061=Shifts the loaded ions to be matched by the given amount to correct for post-translational modifications.
+; Frames, labels, and checkboxes
+12100=Sequence:
+12150=N and C Terminus
+12160=&N
+12170=&C
+12180=H (hydrogen)|HH+ (protonated)|C2OH3 (acetyl)|C5O2NH6 (pyroglu)|CONH2 (carbamyl)|C7H6NS (PTC)|(none)
+12190=OH (hydroxyl)|NH2 (amide)|(bare)
+12200=Ion Types
+12210=&A Ions
+12215=&B Ions
+12220=&Y Ions
+12230=Neutral Losses
+12236=Choose ions to which losses will be applied
+12240=Loss of H2O
+12250=Loss of NH3
+12255=Loss of PO4
+12260=Charge Options
+12270=&2+ charged ions
+12280=&Threshold
+12286=The 2+ m/z value will be computed for ions above this m/z
+12300=Ion Match Options
+12310=&Remove Precursor Ion
+12320=Ion Mass
+12330=Mass Window
+12340=&Ion Matching Window
+12350=Da
+12355=Alignment &Offset
+12360=Ion Statistics
+12370=Loaded
+12375=Remaining after binning
+12380=Within tolerance
+12385=Precursor not found
+12390=Precursor removed
+12395=Precursor not removed
+12400=Matches
+12405=Score
+12410=Mass Information
+12420=Element Mode
+12425=Average
+12430=Isotopic
+
+; Column titles in grids
+; Note: # means 'number', Immon. means 'immonium', and Seq. means 'sequence'
+12500=#
+12510=Immon.
+12520=Seq.
+12550=Mass
+12560=Intensity
+12570=Symbol
+
+; Menu Items
+12800=&Load Sequence Info
+12810=&Save Sequence Info
+12820=Load List of &Ions or .Dta file to Match
+12830=&Close
+12840=&Copy Predicted Ions
+12850=Copy Predicted Ions as &RTF
+12855=Copy Predicted Ions as Html
+12860=&Paste List of Ions to Match
+12865=Copy Sequence Molecular &Weight
+12870=Clear Match Ion &List
+12880=List of &Ions to Match
+12900=&Mass Spectrum
+12910=&Update Spectrum on Change
+12915=&Dta.Txt File Browser
+12920=Ion Match List &Options
+12925=Edit Residue &Modification Symbols
+12930=&Automatically Align Ions to Match
+12940=&Fragmentation Modelling
+12950=&Copy Selected Ions
+12960=&Delete All (Clear list)
+
+[frmMsPlot]
+13000=Plot
+; The following is an abbreviation for the word 'Location'
+13010=Loc
+
+; Legend Items
+13030=Predicted Ions
+13035=Loaded Ions
+
+; Menu Items
+13100=&Export Data
+13150=&Plot Type
+13160=&Sticks To Zero
+13170=&Gaussian Peaks
+13180=Set Effective &Resolution
+13190=X Axis Gridlines
+13200=Y Axis Gridlines
+13210=&Ticks to label (approx.)
+13220=&X Axis
+13230=&Y Axis
+13235=Plot &Quality (affects speed)
+13240=&Gaussian Representation Quality
+13245=&Approximation Factor
+13250=Set &X Range
+13260=Set &Y Range
+13270=&Autoscale Y Axis
+13280=&Fix mimimum Y at zero
+13290=&Zoom Out to Previous
+13295=Ctrl+Z or Right Click
+13300=Zoom Out to Show All
+13310=&Cursor Mode
+13315=Space Enables Move
+13320=&Zoom
+13330=&Move
+13340=&Show Current Position
+13342=Show &Legend
+13345=Reset to &Default Options
+13350=&Zoom Box
+13360=Zoom &In
+13365=Left Click
+13370=Zoom In Horizontal
+13380=Zoom In Vertical
+13390=Zoom &Out
+13400=Zoom Out Horizontal
+13410=Zoom Out Vertical
+
+[frmIonMatchOptions]
+14000=Ion Matching Options
+; Buttons
+14010=&Reset to Defaults
+14020=Edit Auto-Label Options
+
+; Explanations
+14050=When a list of ions is imported into the program, ions of similar mass may optionally be grouped together via a binning process to reduce the total number of data points. Next, ions around the precursor ion may be removed.
+14055=Then, the intensities are normalized to the given maximum intensity and ordered by decreasing intensity. The top-most ions (number of ions to use) are divided into distinct mass regions and the ions in each region again normalized.
+14060=The masses of the predicted ions for a given peptide sequence are easily computed. However, intensity values must also be assigned to the masses.
+14065=The B and Y ions are typically assigned the same intensity while the A ion is typically 5 times less intense. Shoulder ions (masses ± 1 Da from the B and Y ions) can be added, in addition to including neutral losses (H2O and NH3).
+
+; Frames, labels, and checkboxes
+14100=Normalization Options for Imported Data
+14110=&Group Similar Ions (Bin Data)
+14115=Mass Window
+14120=Normalized Intensity
+14130=Number of Ions to Use
+14140=Mass region subdivisions
+14150=Ion Intensities of Predicted Ions
+14160=A Ion Intensity
+14165=B Ion Intensity
+14170=Y Ion Intensity
+14180=B/Y Ion Shoulders
+14190=Neutral Losses
+14200=Frgamentation Spectrum Labels
+14210=Label main ions (a, b, y)
+14220=Label neutral loss ions
+14230=Emphasize Proline y ions
+14240=Spectrum Plotting Options
+14250=Fragmentation Data Color
+14255=Matching Ion Data Color
+14258=Click to change
+14260=Plot Fragmentation Spectrum Inverted
+14270=Auto-Label Peaks on Matching Ion Spectrum
+
+[frmSetValue]
+14500=Set Value
+14510=&Set
+14520=&Start
+
+[frmProgress]
+14700=Progress
+14710=Click to Pause
+14715=Preparing to Pause
+14720=Paused
+14725=Resuming
+14730=(Press Escape to abort)
+14740=min. elapsed/remaining
+
+[frmIsotopicDistibution]
+15000=Isotopic Distribution
+; Frames, labels, and checkboxes
+15050=Formula:
+15060=Results:
+15070=Carga Eléctrica:
+15100=&Plot Results
+15105=&Auto-Label Peaks
+15110=&Compute
+15120=Plot Data Color
+15126=Click to change
+15130=Plot Type
+15140=Sticks to Zero|Gaussian Peaks
+15145=Sticks to Zero|Gaussian Peaks|Lines Between Points
+15151=Isotopic distribution results
+15160=Paste list of ions to compare
+15165=Clear List
+15170=Comparison list data points:
+15190=Options
+15195=Comparison List
+; Column headers in the results box
+15200=Isotopic Abundances for
+15210=Mass/Charge
+15215=Neutral Mass
+15220=Fraction
+15230=Intensity
+15300=Warning, the ion comparison list contains a large number of data points. Do you really want to convert each point to a Gaussian curve?
+15305=Large Data Point Count
+
+[frmAminoAcidModificationSymbols]
+15500=Amino Acid Modification Symbols Editor
+;Directions
+15550=Modified residues in an amino acid sequence are notated by placing a modification symbol directly after the residue's 1 letter or 3 letter abbreviation.
+15555=The phosphorylation symbol is defined separately because phosphorylated residues can lose a phosphate group during fragmentation.
+15560=As an example, if the phosphorylation symbol is *, then in the sequence 'GlyLeuTyr*' the tyrosine residue is phosphorylated.
+15565=Allowable symbols for user-defined modifications are
+15570=Modification symbols can be more than 1 character long, though it is suggested that you keep them to just 1 character long to make it easier for the parsing routine to correctly parse residues with multiple modifications.
+15575=If a residue has multiple modifications, then simply place the appropriate modification symbols after the residue, for example in 'FLE*#L' the E residue is modified by both the * and # modifications.
+15580=Modification masses can be negative values, as well as positive values.
+;Table Tool Tip
+15600=
+15601=Click to change a modification symbol
+; Table column headers
+15610=Symbol
+15620=Mass
+15640=Comment
+; Labels
+15700=Modification Symbols Defined
+15710=Single click to edit or remove. Click in blank row to add.
+15720=Standard Modifications
+15730=Phosphorylation Symbol:
+; Messages
+15750=The amino acid symbol modification will be updated with the parameters below. Select Remove to delete the modification symbol or Cancel to ignore any changes.
+15760=Warning, the new phosphorylation symbol is already being used for another modification. Do you really want to use this symbol for phosphorylation and consequently remove the other definition?
+15765=Modification Symbol Conflict
+15770=Are you sure you want to lose all changes?
+15775=Closing Edit Modification Symbols Window
+; Buttons
+15800=&Reset to Defaults
+15801=Resets modification symbols to defaults
+15810=&Add selected to list
+
+[frmDtaTxtFileBrowser]
+16000=_Dta.Txt File Browser
+; Labels
+16050=Scan Number Start
+16060=Scan Number End
+16070=Parent Ion MH+
+16080=Parent Ion Charge
+; Buttons
+16100=&Jump to scan
+16101=Shortcut is Ctrl+J
+16110=&Keep Window On Top
+
+[ErrorAndStatusMessages]
+20001=Elemento químico desconocido
+20003=Error; falta cerrar paréntesis
+20004=Incongruencia de paréntesis
+20005=No puede haber un 0 (cero) después de un elemento o guión ( - )
+20006=Numero demasiado grande o bien debería estar después de guión ( - ) o del signo de potencia (^)
+20007=Número demasiado grande
+20011=Los números deben preceder a corchete abierto ([), no a corchete cerrado (]) (a menos que 'corchetes equivalen a paréntesis' este activo)
+20012=Un número debe estar presente después de un corchete y/o después de la coma
+20013=Falta corchete de cierre (])
+20014=Número mal colocado; debería estar detrás de un elemento químico, [, ), -, o el signo de potenciación (^)
+20015=Incongruencia de corchete
+20016=No puede anidar corchetes o jerarquizar corchetes dentro de hidratos múltiples (a menos que 'corchetes equivalen a paréntesis' este activo)
+20018=Elemento químico desconocido
+20020=Debe haber un número de masa isotópica a continuación del signo de potenciación (^)
+20022=Hay un cero después del signo de potenciación (^); una masa isotópica nula no se permite
+20023=Masas isotópicas negativas no se permiten después del signo de potenciación (^)
+20024=Las masas isotópicas no se permiten como abreviaturas
+20025=Un elemento debe estar presente después del guión del coeficiente principal
+20026=Las masas isotópicas no se permiten como abreviaturas; D es una abreviatura
+20027=Los números fraccionarios no pueden contener más de una coma
+20028=Circular abbreviation reference; can't have an abbreviation referencing a second abbreviation that depends upon the first one
+20030=Invalid formula subtraction; one or more atoms (or too many atoms) in the right-hand formula are missing (or less abundant) in the left-hand formula
+20050=El valor de objetivo es mayor que 100%, un valor imposible.
+20075=Las letras no se permiten en la línea de operaciones de la calculadora
+20076=Falta cerrar paréntesis
+20077=Incongruencia de paréntesis
+20078=Número erroneo; o demasiado grande, o demasiado pequeño, o demasiado largo
+20080=Operador mal colocado
+20081=La variable comando es menor o igual a 1; fallo en funcionamiento del programa (program bug); por favor, notifiquelo al programador
+20082=Falta operador.
+20085=No puede haber números negativos en una potencia
+20086=No puede tener cero una potencia
+20087=No puede tener cero una potencia
+20089=Un único número positivo o negativo debe ir después de un signo de potenciación (^)
+20090=Los números fraccionarios no pueden contener más de una coma
+20091=Usted intentó dividir un número por cero. Por favor, solucione el problema y recalcule.
+20092=Los espacios en blanco no se permiten en las expresiones matemáticas
+20093=Utilice una coma como punto decimal
+20094=Utilice una coma como punto decimal
+20095=Algún número debe estar presente después de una coma
+20100=Error grabando fichero de abreviaturas
+20110=Se ha reconstruido el fichero abreviaturas a su valor por defecto.
+20115=Se ha cambiado el nombre al fichero antiguo
+20120=El encabezado [AMINO ACIDS] no se ha encontrado en el fichero MWT_ABBR.DAT. Este encabezado dede estar localizado antes o por encima del encabezado [ABBREVIATIONS].
+20130=El encabezado [ABBREVIATIONS] no se ha encontrado en el fichero MWT_ABBR.DAT. Este encabezado debe estar localizado después o por debajo del encabezado [AMINO ACIDS].
+20135=Seleccione OK para continuar solamente con abreviaturas de aminoácidos.
+20140=El fichero de abreviaturas no fue encontrado en el directorio de instalación del programa
+20150=Error cargando/creando fichero de abreviaturas
+20160=Abreviatura ignorada -- Fórmula no válida
+20170=Abreviatura ignorada; la abreviatura esta duplicada
+20180=Abreviatura ignorada; carácter o letra no válido
+20190=Abreviatura ignorada; demasiado larga
+20200=Ignorando línea de datos no correcta
+20210=Se ha reconstruido el fichero elementos químicos a su valor por defecto.
+20220=Masa posiblemente incorrecta para ese elemento químico.
+20230=Desviación posiblemente incorrecta para ese elemento químico
+20250=Línea de datos ignorada; símbolo del elemento no correcto
+20260=El encabezado [ELEMENTS] no se ha encontrado en el fichero MWT_ELEM.DAT. Este encabezado debe estar localizado en el fichero.
+20265=Seleccione OK para continuar con los valores por defecto establecidos para los elementos químicos.
+20270=El fichero de elementos no fue encontrado en el directorio de instalación del programa
+20280=Error cargando/creando fichero de elementos
+20305=Continuando con los valores por defecto.
+20320=Error grabando archivo de elementos
+20330=Error cargando/creando archivo de valores
+20340=Seleccione OK para continuar sin cargar los valores y fórmulas por defecto.
+20345=Si utiliza una unidad (disco) de sólo-lectura, utilice el parámetro /X en la línea de comandos para prevenir este error.
+20350=Error
+20360=Error grabando archivo de opciones por defecto
+20380=Error grabando archivo de valores y fórmulas
+20400=Error cargando/creando archivo de opciones por defecto
+20410=Seleccione OK para continuar sin cargar los valores por defecto del usuario.
+20440=El fichero de idioma no se ha podido abrir con éxito, quizá tiene un formato de texto incorrecto.
+20450=No es posible cargar los campos de texto específicos del idioma
+20460=El fichero de idioma no se ha podido encontrar en el directorio de instalación del programa
+20470=El fichero solicitado para el cáculo de masa molecular no fue encontrado
+20480=Fichero no encontrado
+20490=Este fichero ya existe. Desea sustituirlo?
+20500=Fichero presente
+20510=Error de lectura/escritura de archivos durante el procesamiento por lotes
+20515=Seleccione OK para abortar el procesamiento por lotes de archivos.
+20520=Error en programa
+20530=Estas líneas del código no deberían haber sido encontradas. Por favor, comuníqueselo al programador.
+20550=El solver desde porcentajes no puede ser utilizado cuando los corchetes equivalen a paréntesis. Puede cambiar el modo de reconocimiento de corchetes descativando la opción correspondiente dentro del cuadro de diálogo 'Preferencias del programa'.
+20555=Solver desde porcentajes no disponible
+20560=Número máximo de campos para fórmulas alcanzado.
+20570=El campo para la fórmula actual está en blanco.
+20580=Desactive la resolución -solver- desde porcentajes (F11) antes de escribir una nueva fórmula.
+20590=Ha ocurrido un error de desbordamiento de memoria. Por favor, disminuya los valores numéricos y vuelva a calcular.
+20600=Un error ha ocurrido
+20605=Por favor, salga e informe del error al programador. Seleccione 'Sobre MWC' en el menú Ayuda para ver la dirección de correo electrónico disponible.
+20610=Los espacios en blanco no se permiten en fórmulas
+20620=Caracter de texto no válido.
+20630=Imposible copiar a nueva fórmula.
+20650=El campo para la fórmula actual está en blanco.
+20655=El modo solver desde porcentajes está activado (F11 para desactivar).
+20660=Advertencia; la masa del isótopo es seguramente demasiado grande para este elemento
+20662=Advertencia; la masa del isótopo es seguramente demasiado pequeña para este elemento
+20665=vs. un peso atómico medio de
+20670=Advertencia; es imposible que la masa del isótopo sea tan pequeña para este elemento
+20675=protones
+20680=Nota: modo de reconocimiento de fórmulas 'exacto' activado
+20685=Nota: en modo solver desde porcentajes, un corchete izquierdo ([) debe estar precedido por un x
+20690=Nota: corchetes equivalen a paréntesis (opción está activada)
+20700=Uno o más elementos deben ser seleccionados.
+20705=El máximo debe ser mayor que cero.
+20710=El máximo debe ser menor que
+20715=El número mínimo de elementos debe ser igual o mayor que cero.
+20720=El número mínimo de elementos debe ser menor que el número máximo de elementos.
+20725=El número máximo de elementos debe ser menor de 65.025
+20730=Una masa atómica debe ser incluida para los elementos químicos personalizados.
+20735=La masa atómica debe ser mayor que 0 para los elementos personalizados.
+20740=La masa molecular objetivo debe ser tecleada.
+20745=La masa molecular objetivo debe ser mayor que cero.
+20755=Una masa molecular máxima debe ser tecleada.
+20760=La masa molecular máxima debe ser mayor que cero.
+20765=Los porcentajes buscados deben ser tecleados para cada elemento
+20770=Los porcentajes buscados deben ser mayor que cero.
+20775=Los pesos elementales personalizados deben contener solamente números o solamente letras. Si se utilizan letras, deben estar asociadas a un único símbolo elemental o abreviatura válida.
+20780=El peso elemental personalizado esta vacío. Si se utilizan letras, deben estar asociadas a un único símbolo elemental o abreviatura válida.
+20785=Elemento o abreviatura desconocido al personalizar su masa elemental
+20790=Sólo se permiten símbolos químicos elementales o abreviaturas.
+20800=Atención; ninguna abreviatura fue cargada -- El comando no ha tenido ningún efecto.
+20805=Cannot handle fractional numbers of atoms
+
+20900=Error Reading/Writing sequence information file.
+20910=Ions are already present in the ion list. Replace with new ions?
+20920=Replace Existing Ions
+20930=Loading Ion List
+20940=Process aborted
+20945=Aborted
+20950=Normalizing ions
+20960=Normalizing by region
+20965=Sorting by Intensity
+20970=Matching Ions
+20980=The clipboard is empty. No ions to paste.
+20985=No ions
+20990=Pasting ion list
+21000=Determining number of ions in list
+21010=Parsing list
+21020=No valid ions were found on the clipboard. A valid ion list is a list of mass and intensity pairs, separated by commas, tabs, or spaces. One mass/intensity pair should be present per line.
+21030=Error writing data to file
+21040=Set Range
+21050=Start Val
+21055=End Val
+21060=Set X Axis Range
+21065=Set Y Axis Range
+21070=Enter a new Gaussian Representation quality factor. Higher numbers result in smoother Gaussian curves, but slower updates. Valid range is 1 to 50, default is 20.
+21072=Gaussian Representation Quality
+21075=Enter a new plotting approximation factor. Higher numbers result in faster updates, but give a less accurate graphical representation when viewing a wide mass range (zoomed out). Valid range is 1 to 50, default is 10.
+21077=Plotting Approximation Factor
+21080=Resolving Power Specifications
+21090=Resolving Power
+21100=X Value of Specification
+21110=Please enter the approximate number of ticks to label on the axis
+21115=Axis Ticks
+21120=Creating Gaussian Representation
+21130=Preparing plot
+21135=Drawing plot
+21140=Are you sure you want to restore the default plotting options?
+21145=Restore Default Options
+21150=Auto Align Ions
+21155=Maximum Offset
+21160=Offset Increment
+21165=Aligning Ions
+
+21500=All Files
+21510=Text Files
+21515=txt
+21520=Data Files
+21525=csv
+21530=Sequence Files
+21535=seq
+21540=Ion List Files
+21545=txt
+21550=cap
+21555=Capillary Flow Info Files
+
+[CautionStatments]
+; Note: Caution statement keynames are case sensitive; i.e. Bi is different than BI
+; You may add new caution statements if desired; however, you will need to save
+; the file with a name other than Lang_English and change the Language= key
+; since this file is not loaded if the language is English
+22000=Atención
+Bi=Bi significa bismuto; BI significa boro-yodo.
+Bk=Bk significa berkelio; BK significa boro-potasio.
+Bu=Bu significa grupo butílico; BU significa boro-uranio.
+Cd=Cd significa cadmio; CD significa carbono-deuterio.
+Cf=Cf significa californio; CF significa carbono-flúor.
+Co=Co significa cobalto; CO significa carbono-oxígeno.
+Cs=Cs significa cesio; CS significa carbono-sulfuro.
+Cu=Cu significa cobre; CU significa carbono-uranio.
+Dy=Dy significa dysprosio; DY significa el deuterio-itrio.
+Hf=Hf significa hafnio; HF significa hidrógeno-flúor.
+Ho=Ho significa holmio; HO significa hidrógeno-oxígeno.
+In=In significa indio; IN significa yodo-nitrógeno.
+Nb=Nb significa niobio; NB significa nitrógeno-boro.
+Nd=Nd significa neodimio; ND significa nitrógeno-deuterio.
+Ni=Ni significa níquel; NI significa nitrógeno-yodo.
+No=No significa nobelio; NO significa nitrógeno-oxígeno.
+Np=Np significa neptuno; NP significa nitrógeno-fósforo.
+Os=Os significa osmio; OS significa oxígeno-sulfuro.
+Pd=Pd significa paladio; PD significa fósforo-deuterio.
+Ph=Ph significa fósforo, PH significa fósforo-hidrógeno
+Pu=Pu significa plutonio; PU significa fósforo-uranio.
+Py=Py significa pyridine; PY significa fósforo-itrio.
+Sb=Sb significa antimonio; SB significa sulfuro-boro.
+Sc=Sc significa escandio; SC significa sulfuro-carbono.
+Si=Si significa silicio; SI significa sulfuro-yodo.
+Sn=Sn significa estaño; SN significa sulfor-nitrógeno
+TI=TI significa tritio-yodo, Ti significa titanio.
+Yb=Yb significa iterbio; YB significa itrio-boro.
+BPY=BPY significa boro-fósforo-itrio; Bpy significa bipyridine.
+BPy=BPy significa boro-pyridine; Bpy significa bipyridine.
+Bpy=Bpy significa bipyridine.
+Cys=Cys significa cisteina; CYS significa carbono-itrio-sulfuro.
+His=His significa histidine; HIS significa hidrógeno-yodo-sulfuro.
+Hoh=HoH significa holmio-hidrógeno; HOH significa hidrógeno-oxígeno-hidrógeno (agua).
+Hyp=Hyp significa hydroxyproline; HYP significa hidrógeno-itrio-fósforo.
+OAc=OAc significa oxígeno-actinio; Oac significa acetato.
+Oac=Oac significa acetato.
+Pro=Pro significa proline; PrO significa praseodymium-oxígeno.
+PrO=Pro significa proline; PrO significa praseodymium-oxígeno.
+Val=Val significa valine; VAl significa vanadio-aluminio.
+VAl=Val significa valine; VAl significa vanadio-aluminio.
diff --git a/lang_turkish.ini b/lang_turkish.ini
new file mode 100644
index 0000000..973bb77
--- /dev/null
+++ b/lang_turkish.ini
@@ -0,0 +1,1107 @@
+; Language customization file for the Molecular Weight Calculator program by Matthew Monroe
+; Contact at alchemistmatt@yahoo.com and http://come.to/alchemistmatt/ or http://www.alchemistmatt.com/
+;
+; When customizing the phrases in this file, the ampersand symbol (&) signifies a
+; keyboard shortcut. For example, the default value for key 1000 is &File. When
+; running the program, the F in File will be underlined and the user may press Alt-F
+; to access the File menu (in addition to clicking on the file menu)
+; To improve usability of the program, please try to include the & symbol in menu items
+; and buttons. Note, however, that if two controls on the same form have the same &
+; shortcut, they will not respond to the alt key in the usual way.
+;
+; In this file, items surround by brackets [] are section headers -- the program ignores them
+; when parsing the file. The key values (1000, 1010, 1020, etc.) should not be changed, with
+; the exception that new caution statements may be added at the end of the file.
+; Lines beginning with a semicolon (;) are also ignored since they are treated as comments
+; However, you should not place a ; at the end of a line with an actual key and caption.
+;
+; Keys with multiple values separated by a vertical line (|) represent multiple items loaded
+; into a ComboBox control. When translating to other languages, you must keep the same number
+; of items in the list, or program functionality will be lost. For example, key 7070 contains
+; hours|minutes|seconds Thus, hours, minutes, and seconds will be loaded into a control, from
+; which the user may select one of them. In Spanish, you would use 7070=horas|segundos|minutos
+;
+; If you create a new .Ini file for a foreign language and would like it posted on my
+; web page, simply e-mail it to me.
+
+; Turkish version -- by Ramazan Kocabas
+; For Molecular Weight Calculator v6.0
+
+[Language]
+Language=Turkish
+
+
+[frmMain Menus]
+; Menu Items
+1000=Dosya
+1010=Elementler Tablosunu Düzenle
+1020=Kýsaltmalarý Düzenle
+1030=Aðýrlýklarý text dosyasýndan hesapla
+1040=Sonuçlarý yaz
+1050=Kapat
+1500=Düzen
+1505=&Undo
+1510=Kes
+1520=Kopyala
+1530=Yapýþtýr
+1540=Sil
+1545=Select &All
+1550=Geçerli Formülü Text Olarak Kopyala
+1560=Geçerli Formülün Molekül Aðýrlýðýný Kopyala
+1570=Bileþim Verileri Yüzdesini Kopyala
+1580=Geçerli Formülün Kopyasýný Ekle
+1590=Bütün Formülleri Sil
+1600=Geçerli Formülü Sil
+1610=Kýsaltmalarý Aç
+1620=Kimyasal Formülünü Göster
+2000=Görünüm
+2010=Çok Sayýda Formül
+2020=Tek Formül
+2030=Yüzde Çözünürlük
+2040=Kapalý
+2050=Açýk
+2500=Araçlar
+2510=Mol - Kütle Çevrimi ve Dilüsyon Hesaplarý
+2520=Formül Bulucu
+2530=Amino Asitlerin Rakamsal Çevrimi
+2533=Peptide Sequence Fragmentation Modelling
+2536=Izotopik Daðýlým Modeli
+2538=Geçerli Formül Ýçin Ýzotopik Daðýlýmý Göster
+2540=Hesap Makinesi
+2550=Kapiller Elektroforez - Kapiller Akýþ Hesaplarý
+3000=Seçenekler
+3010=Dil Tercihleri
+3020=Program Tercihlerini Deðiþtir
+3030=Formül Yazý Tipini Deðiþtir
+3040=Üstte Kal
+3050=Varsayýlan Deðerlere Geri Dön veya Kaydet
+3060=Varsayýlan Deðer ve Formüllerin Aslýna Dön
+3070=Mevcut Formüller ve Deðerleri Þimdi Kaydet
+3500=Yardým
+3510=Programa Genel Bakýþ
+3530=Araç Seçeneklerini Göster
+3540=Program Hakkýnda
+
+[frmMain Status Messages and Verification Messages]
+3600=The entire line is
+3605=Zooming
+3610=Bu formülü kimyasal formüle çevirmek istediðinize emin misiniz?
+3615=Kimyasal Formüle Çevir
+3620=Geçerli formülü silmek istediðinize emin misiniz?
+3625=Geçerli Formülü Sil
+3630=Bu formülün kýsaltmalarýný elemental eþdeðerlerinin aslýna çevirmek istediðinize emin misiniz?
+3635=Kýsaltmalarý Aç
+3640=Varsayýlan Formül ve Deðerlerin Aslýna Dönmek Geçerli Formülleri Temizleyecek ! Aslýna Dönülsün mü?
+3645=Formül ve Deðerleri Aslýna Getir
+3650=Set the Percent Solver target percentage of this element to a percentage. Select Reset to un-target the percentage or Cancel to ignore any changes.
+3660=Use Page Up/Down or Up/Down arrows to move to the percents (F11 exits Percent Solver mode).
+3665=Press Enter or Click to change a percentage (F11 exits Percent Solver Mode).
+3670=Hazýr
+3700=Hesaplanýyor... Durdurmak için herhangi bir tuþa basýn veya fareyi týklatýn.
+3710=x is
+3720=Hesaplanan Deðer
+3730=Hedef
+3740=Hedeften Farklý
+3750=% Çözünürlük Açýk
+3760=Hesaplanan Molekül Aðýrlýk Sonuçlarý
+3770=Formüller ve Deðerleri Varsayýlan Þekline Geri Al
+3780=Bütün formülleri silmek istediðinize emin misiniz?
+3785=Bütün formülleri sil
+3790=Kapatmak istediðinize emin misiniz?
+3795=Program kapatýlýyor
+3800=Kýsaltmalar yükleniyor
+3810=Elementler yükleniyor
+3820=(ortalama atom aðýrlýðýný kullanarak)
+3830=(izotopik elemental aðýrlýklarý kullanarak)
+3840=(Ýzotopik aðýrlýklarýn tam sayý deðerlerini kullanarak)
+3850=Seçtiðiniz Dil Varsayýlan Olarak Kaydedildi
+
+[Phrases common throughout application]
+4000=Kapat
+4010=Tamam
+4020=Ýptal
+4030=Çýkýþ
+; The following is the abbreviation for Molecular Weight
+; It must be exactly two letters long
+4040=MW
+4050=Dikkat
+4060=Yes
+4065=No
+
+[frmMain]
+; Form Caption
+4900=Molecular Weight Calculator - TÜRKÇE - RAMAZAN KOCABAÞ
+; Labels
+5000=Formül
+5010=Element Aðýrlýðýnýn Hesaplama Tarzý
+5020=Ortalama
+5021=Elementlerin Ortalama Aðýrlýklarý Kullanýlýr
+5030=Ýzotopik
+5031=Elementin En Yaygýn Bulunan Ýzotopunun Aðýrlýðý Kullanýlýr
+5040=Tam Sayý
+5041=En Yaygýn Ýzotopun Ýtibari Aðýrlýðýný Tam Sayý Olarak Gösterir
+; TextBoxes
+5051=Moleküler Formülü Buraya Yazýn
+; Buttons
+5100=Hesapla
+5101=Geçerli Formülün Molekül Aðýrlýðýný Hesaplar
+5110=Yeni Formül
+5111=Formül Yazmak Ýçin Yeni Bir Pencere Açar
+5116=Yeni Bir Boþ Formül Penceresi Gösterir
+; Grid control
+5201=Bir Hedefe Gitmek veya Geri Dönmek Ýçin Týklayýn
+; Status control
+5301=Daha Geniþ Bir Pencerede Görmek Ýçin Çift Týklayýn
+5350=Molecular Weight Calculator henüz çalýþýyor. Baþka bir kopyasýný baþlatmak istediðinize emin misiniz?
+5355=Zaten Çalýþýyor
+
+[frmAboutBox]
+5500=MWT Hakkýnda
+5510=Türkçe'ye Çeviren : Ramazan KOCABAÞ - 19.03.2003
+
+[frmIntro]
+5700=Yükleniyor - TÜRKÇE'ye çeviren RAMAZAN KOCABAÞ
+
+[frmAminoAcidConverter]
+; Form Caption
+6000=Amino Acid Notation Converter
+; Labels
+6010=One letter-based amino acid sequence
+6020=Three letter-based amino acid sequence
+; TextBoxes
+6031=Enter sequence using 1 letter abbreviations here
+6041=Enter sequence using 3 letter abbreviations here
+; Buttons
+6050=&Copy 3 letter sequence to formula:
+6060=Copy to &Fragmentation Modeller
+; CheckBoxes
+6080=&Add space every 10 residues
+6090=&Separate residues with dash
+
+[frmCalculator]
+; Form caption
+6500=Hesap Makinesi
+; Textbox
+6511=Hesaplama Ýçin Matematiksel Bir Veri Girin
+; Buttons
+6520=Hesapla
+6521=Matematiksel Ýþlemin Sonucunu Gösterir
+; Status control
+6610=Sunuç
+
+[frmCapillaryCalcs]
+; Form Caption
+7000=Capillary Flow and Mass Rate Calculations
+; Combo Boxes
+7010=Open Tubular Capillary|Packed Capillary
+7011=Toggle between open and packed capillaries.
+7020=Find Back Pressure|Find Column Length|Find Inner Diameter|Find Volumetric Flow rate|Find Flow Rate using Dead Time
+7030=psi|Pascals|kiloPascals|Atmospheres|Bar|Torr (mm Hg)|dynes/cm^2
+7035=m|cm|mm|um|inches
+7040=Poise [g/(cm-sec)]
+7050=mL/min|uL/min|nL/min
+7060=cm/hr|mm/hr|cm/min|mm/min|cm/sec|mm/sec
+7070=hours|minutes|seconds
+7080=mL|uL|nL|pL
+7090=Molar|milliMolar|microMolar|nanoMolar|picoMolar|femtoMolar|attoMolar|mg/dL|mg/mL|ug/mL|ng/mL|ug/uL|ng/uL
+7100=pmol/min|fmol/min|amol/min|pmol/sec|fmol/sec|amol/sec
+7110=Moles|milliMoles|microMoles|nanoMoles|picoMoles|femtoMoles|attoMoles
+; Labels and frames
+7200=Back Pressure
+7210=Column Length
+7220=Column Inner Diameter
+7230=Solvent Viscosity
+7240=Particle Diameter
+7250=Volumetric Flow Rate
+7260=Linear Velocity
+7270=Column Dead Time
+7280=Column Volume
+7290=Interparticle Porosity (epsilon)
+7300=Mass Rate Calculations
+7310=Sample Concentration
+7320=Injection Time
+7330=Mass Flow Rate
+7340=Moles Injected
+7350=Extra Column Broadening Calculations
+7360=Diffusion Coefficient
+7370=Open Tube Length
+7380=Open Tube I.D.
+7390=Initial Peak Width
+7400=Optimum Linear Velocity
+7410=(for 5 um particles)
+7420=Temporal Variance
+7430=Additional Variance
+7440=Resulting Peak Width
+7450=Percent Increase
+7460=Geçerli Formül :
+7480=Atom Aðýrlýðý
+7500=cm
+7510=um
+7520=cm^2/sec
+7530=sec
+7540=cm/sec
+7550=sec^2
+7560=sec
+7570=g/mole
+; TextBoxes
+7601=Enter custom numerical mass for use in computations
+; Buttons
+7700=Show/Hide &Peak Broadening Calculations
+7710=&View Explanatory Equations
+7730=View Equations
+; Option Buttons
+7750=Geçerli Formüldeki Bileþiðin Atom Aðýrlýðýný Kullan
+7760=Atom Aðýrlýðýný Kendim Yazacaðým
+; CheckBoxes
+7800=&Link to Above
+; ToolTips
+7851=Typical viscosity value is 0.0089 poise
+7861=Typical porosity value is 0.4
+7871=Typical diffusion coefficient for small organics is 0.00001, i.e. 1E-5; Typical value for peptides is 0.000005, i.e. 5E-6
+; Menus
+7900=&Load Values
+7910=&Save Values
+7950=&Capillary Flow Calculations
+
+[frmChangeFont]
+; Form Caption
+8000=Formül Yazý Tipini Deðiþtir
+; Combo Boxes
+; Labels
+8060=Formül Yazý Tipini Aþaðýdan Seçiniz...
+8070=Boyut :
+; Buttons
+
+[frmChangeValue]
+; Form Caption
+8200=Deðeri Deðiþtir
+; Buttons
+8210=&Varsayýlana Dön
+
+[frmChangeLanguage]
+8400=Dil Tercihleri
+; Labels
+8410=Dil tercihleri aþaðýda görülmektedir. Kullanmak istediðiniz dili seçiniz.
+8420=Bu dil kullanýlamýyor. Farklý bir dil için programýn web sayfasýný ziyaret ediniz.
+
+[frmDiff]
+8600=Percent Solver Differences
+8610=&Copy
+8611=Copies the results to the clipboard
+
+[frmEditAbbrev]
+9000=Kýsaltmalarý Düzenle
+; Buttons
+9010=Aslýna Çevir
+9011=Kýsaltmalarý Program Varsayýlanlarýna Geri Getirir
+9020=Çýkar
+; Messages
+9050=Maksimuma Ulaþtý
+9060=Üzgünüm ! Sadece 500 kýsaltmasý girebilmektedir.
+9090=Kýsaltma veya Moleküler Formül sizin yazdýðýnýz þekilde deðiþecek. Kýsaltmayý silmek için " Çýkar " tuþunu, deðiþiklikleri iptal etmek için " Ýptal " tuþunu seçiniz.
+9100=Yapýlan Bitin Deðiþiklikler Kaybolacak, Emin misiniz?
+9105=Closing Edit Abbreviations Box
+9110=Varsayýlan Kýsaltmalara Dönmek Ýstediðinize Emin misiniz?
+9115=Aslýna Döndür
+9120=Warning, test usage of the new/updated abbreviation did not give the same mass as the formula for the abbreviation. This probably indicates a problem with the abbreviation's formula.
+;Table Tool Tip
+9140=
+9141=Bir Kýsaltmayý Deðiþtirmek Ýçin Týklayýn
+9145=Symbol
+; Table Column Titles
+9150=Yük
+9160=Moleküler Formül
+9170=Normal Kýsaltma
+9180=Amino Asit Adý
+9190=1 Harf
+9195=Comment
+
+[frmEditElem]
+9200=Elementler Tablosunu Düzenle
+; Buttons
+9210=Aslýna Dön
+9211=Resets elemental weights to their average weights
+9220=Reset
+9230=Otalama Atom Aðýrlýðýný Kullan
+9231=Sets all elemental weights to their average weights found in nature
+9240=En Yaygýn Ýzotopun Aðýrlýðýný Kullan
+9241=Sets all elemental weights to the weight of the element's most common isotope (for high resolution mass spectrometry)
+9245=Ýtibari Aðýrlýðýn Tam Sayý Deðerini Kullan
+9246=Sets all elemental weights to the nominal integer weight of the element's most common isotope (for low resolution mass spectrometry)
+; Messages
+9250=The elemental weight or uncertainty will be changed to the value you type. Select Reset to reset to the default value or Cancel to ignore any changes.
+9260=Are you sure you want to reset all the values to their average elemental weights?
+9265=Change to Average Weights
+9270=Are you sure you want to reset all the values to their isotopic elemental weights?
+9275=Change to Isotopic Weights
+9280=Are you sure you want to reset all the values to their integer weights?
+9285=Change to Integer Weights
+9290=Are you sure you want to reset all the values to the default Elemental values (average weights)?
+9295=Varsayýlanlara Dön
+9300=If executed, this cannot be canceled.
+9310=Are you sure you want to lose all changes?
+9315=Closing Edit Elements Box
+;Table Tool Tip
+9340=
+9341=Bir Elementin Aðýrlýðýný veya Belirsizliðini Deðiþtirmek Ýçin Týklayýn
+;Table Column Titles
+9350=Element
+9360=Aðýrlýk
+9370=Belirsizlik
+; Combo boxes
+9380=Element Sembolü|Atom Numarasý|Belirsizlik|Yük
+9390=Elementleri Sýrala :
+
+[frmEquationsBroadening]
+9500=Extra-column broadening equations
+
+[frmEquationsOpenTube]
+9550=Equations for flow in an open tube
+
+[frmEquationsPackedCapillary]
+9600=Equations for flow in a packed capillary
+
+[frmFinderModeWarn]
+; Instructions Label
+9700=The typical use of the Formula Finder feature is for when the monoisotopic mass (weight) of a compound is known (typically determined by Mass Spectrometry) and potential matching compounds are to be searched for.
+9701=For example, a mass of 16.0312984 Daltons is measured for a compound containing Carbon and Hydrogen, and the possible empirical formula is desired. Performing the search, with a weight tolerance of 5000 ppm results in three compounds, H2N, CH4, and O. Within 500 ppm only CH4 matches, which is the correct match.
+9702=To correctly achieve use this feature, the program must be set to Isotopic Weight mode. This can be done manually by choosing Edit Elements Table under the File menu, or the program can automatically switch to this mode for you.
+9703=Would you like to:
+9705=The typical use of the Fragmentation Modelling feature is for predicting the masses expected to be observed with a Mass Spectrometer when a peptide is ionized, enters the instrument, and fragments along the peptide backbone.
+9706=The peptide typically fragments at each amide bond. For example, the peptide Gly-Leu-Tyr will form the fragments Gly-Leu, Leu-Tyr, Gly, Leu, and Tyr. Additionally, the cleavage of the amide bond can occur at differing locations, resulting in varying weights.
+; Buttons
+9720=&Continue
+; Option Buttons
+9750=Switch to &Isotopic Weight mode now.
+9760=Always automatically switch to Isotopic &Weight mode.
+9770=Continue using &Average Weights.
+; CheckBoxes
+9780=&Stop showing this warning dialog.
+
+[frmFinder]
+10000=Formula Finder
+; Labels
+10010=Select appropriate elements or add your own, enter a molecular weight or percent compositions, then select calculate to find compounds that match the specifications.
+10020=Maximum Weight of Formula:
+10030=Molecular Weight of Target:
+10040=Weight Tolerance:
+10050=Percent Tolerance:
+10060=Min
+10070=Max
+10080=Element
+10090=Percent
+10100=Max Hits
+10105=Atomic Wt.
+; Percent completed status messages
+10110=% Completed
+10115=Sorting
+10120=Searching
+10125=Working
+10130=Completed
+10135=compounds
+10140=Sorting Interrupted
+10145=Calculations Interrupted
+10150=Formatting
+10155=Done
+10160=Formatting aborted
+; Listboxes & Textboxes
+10201=Double click any line to expand it
+10221=Amount that target compound's weight can be from the target weight
+10231=Amount that elemental percent compositions can be from the target percentage
+10241=Maximum number of target compounds to find
+10251=Minimum number of atoms in target compound
+10256=Maximum number of atoms in target compound
+10260=Percent
+10261=Percent composition of target compound that is
+10270=# or Element or Abbrev.
+10271=Type a weight for the custom element, an elemental symbol, or an abbreviation
+; Note the following is 'dm' in English, standing for 'delta mass' or the mass difference
+; of the given result's mass versus the target mass
+10280=dm
+; Note the following is 'ppm' in English, standing for 'parts per million'
+10285=ppm
+; Buttons
+10300=Formul&a Finder Options
+10301=Shortcut: Ctrl+O
+10310=&Calculate
+10311=Find the compounds that match the specified parameters
+10320=Prin&t ...
+10330=Copy as RT&F
+10331=Copy results to clipboard in Rich Text Format
+10340=Cop&y
+10341=Copy results to clipboard
+10345=&Display Iso Abundance
+10346=Display the Isotopic Distribution of the currently selected compound (Ctrl+D)
+; Option Buttons
+10350=Match &Molecular Weight
+10360=Match &Percent Compositions
+; CheckBoxes
+10370=Ppm Mode
+10380=Show Delta Mass
+10381=Note: Delta mass notation will change as the standard deviation mode is changed (F12 in the main window)
+; Elements (and Custom element phrase)
+10400=Carbon
+10405=Hydrogen
+10410=Nitrogen
+10415=Oxygen
+10420=Custom
+; Messages
+; Note that 10455 is also used with the Abort button
+10450=A key was pressed.
+10455=Abort
+10460=The mouse was clicked outside the results box.
+10465=Stopping formatting.
+10470=Stopping sort.
+10480=The sum of the percent compositions is not 100%.
+10485=Continue with calculation?
+10490=Cannot Calculate
+10500=A key was pressed.
+10505=The mouse was clicked outside the results box.
+10510=Stopping calculations.
+10515=The maximum number of hits has been reached.
+10520=Maximum Hits
+10530=Compounds found
+; Note: the following is used when displaying the results of a percent composition
+; search in the formula finder. A synonym for 'has' would be 'contains' or 'is composed of'
+10535=has
+10540=A memory error has occurred. The results list is probably full. Results so far are shown.
+10545=Out of Memory
+10550=The results box is empty.
+10555=Nothing to Copy
+10560=Nothing to Print
+10565=Are you sure you want to print the current result(s)?
+10570=Printing
+
+[frmFinderOptions]
+10800=Finder Options
+; Labels
+10810=Use the checkboxes to select various options for the Formula Finder.
+; Textboxes & Comboboxes
+10821=Minimum charge to limit compounds to
+10831=Maximum charge to limit compounds to
+10840=Thorough Search|Bounded Search
+10841=A thorough search finds all matching compounds while a bounded search finds compounds within a specific atomic range (thorough is usually faster).
+10850=Sort by Formula
+10851=Method to sort results. Re-calculate to re-sort.
+10855=Sort by Charge
+10860=Sort by MWT
+10865=Sort by m/z
+10870=Mass/Charge Ratio of Target
+10875=Molecular Weight of Target
+; CheckBoxes
+10900=Find &Charge
+10901=Compute the overall charge of each compound found
+10910=Limit Charge &Range
+10911=Limit the displayed compounds to a specific charge range
+10920=Find m/&z
+10921=Compute the mass to charge ratio for each compound found
+10930=Find &Target m/z
+10931=Find compounds with m/z values equivalent to the target
+10940=So&rt Results
+10941=Convert results to empirical formulas and sort them
+10950=&Smart H atoms
+10951=Limit number of hydrogen atoms in found compounds to a realistic number
+10960=&Automatically adjust Min and Max in bounded search.
+10961=Automatically adjust the Min and Max search values to a valid range for the given target weight
+
+[frmMMconvert]
+11000=Mol - Kütle Çevrimi ve Dilüsyon Hesaplarý
+; Combo Boxes
+11010=Miktar Çevirme|Konsantrasyon Hesabý|Dilüsyon Hesaplarý
+11011=Perform conversions between different amounts of compound or perform molarity-related calculations
+11020=Moles|Millimoles|microMoles|nanoMoles|picoMoles|femtoMoles|attoMoles|Kilograms|Grams|Milligrams|Micrograms|Pounds|Ounces|Liters|Deciliters|Milliliters|Microliters|Nanoliters|Picoliters|Gallons|Quarts|Pints
+11021=Units of amount to convert from
+11026=Units of amount to use for concentration calculation
+11030=Liters|Deciliters|Milliliters|Microliters|Nanoliters|Picoliters|Gallons|Quarts|Pints
+11031=Units of volume
+11041=Units of amount to convert to
+11051=Units of concentration
+; Labels
+11080=g/mL
+; Textboxes
+11101=Amount of compound to convert from
+11106=Amount of compound to be dissolved in solvent
+11111=Density of the compound
+11121=Volume of solvent the compound is dissolved in
+11131=Concentration of compound in the solvent
+; Buttons
+11150=Find &Amount
+11151=Calculate the amount using the volume and concentration
+11160=Find &Volume
+11161=Calculate the volume using the amount and concentration
+11170=Find &Concentration
+11171=Calculate the concentration using the amount and volume
+
+; Dilution-related controls
+11200=Dilution Calculations
+11205=Evaporation or Sublimation Calculations
+11210=Find Required Dilution Volumes|Find Required Total Volume|Find Final Concentration|Find Initial Concentration
+11211=Quantity to find for dilution calculations
+11220=&Link Initial Dilution Concentration and Convert Amounts Concentration
+11221=Copy the Computed Concentration for converting amounts to the Initial Concentration for dilutions and vice versa if either changes
+11230=Link Dilution Volume Units
+11231=Synchronize the units for the Volume of Stock, Volume of Solvent, and Final Total Volume
+; Dilution related labels and textbox tooltips
+11250=&Initial Concentration
+11256=Concentration of solute in stock solution
+11260=Volume of &Stock Solution
+11266=Volume (aliquot) of stock solution to remove when performing dilution
+11270=&Final Concentration
+11276=Concentration of solute in final solution following dilution
+11280=Volume of Solvent used for &Dilution
+11286=Volume of solvent to mix with the stock solution (aliquot) removed for dilution
+11290=&Total Final Volume
+11296=Total volume of the final solution following mixing of stock and diluting solvent
+
+[frmProgramPreferences]
+11500=Molecular Weight Calculator Preferences
+; Frame labels
+11510=Abbreviation Mode (F3)
+11520=Case Recognition Mode (F4)
+11530=Standard Deviation Mode (F12)
+11540=Advanced Tools Weight Mode Options
+11550=Exit Program Options
+; Buttons
+11600=&Save options as defaults
+11610=&Restore default options
+; Option Buttons
+11650=Normal
+11651=Recognize normal abbreviations, but not amino acids
+11655=Normal + Amino Acids
+11656=Recognize normal abbreviations and amino acids
+11660=Off
+11661=Ignore all abbreviations
+11665=Convert Case Up
+11666=Correctly capitalize formulas while parsing
+11670=Exact Case
+11671=Require user to type formulas with correct capitalization
+11675=Smart Case
+11676=Interpret lowercase formulas, and do not capitalize them
+11680=Short
+11681=Display standard deviations in abbreviated form
+11685=Scientific
+11686=Display standard deviations in scientific notation
+11690=Decimal
+11691=Display standard deviations in long decimal form
+11695=Off
+11696=Do not display standard deviations
+11700=Exit on Escape with confirmation
+11701=Determines if the escape key exits program and whether to confirm program exit
+11705=Exit on Escape without confirmation
+11710=Ignore escape key but confirm exit
+11715=Ignore escape key and do not confirm exit
+; CheckBoxes
+11750=Ad&vance on Calculate (F9)
+11751=Move to a new formula line after calculating a formula's weight
+11760=Treat &Brackets as Parentheses
+11761=Treat brackets, [ and ], as parentheses, rather than as percent solver placeholders
+11770=A&uto Copy Current Molecular Weight (Ctrl+U)
+11771=Automatically copy the selected formula's molecular weight value to the clipboard after each calculation
+11780=Compute Char&ge
+11781=Compute charge of compounds (very basic rules, cannot correct for double or triple bonds, etc.)
+11800=Always switch to &Isotopic Mode automatically
+11801=Switch to isotopic weights automatically upon entering the formula finder or peptide fragmentation module
+11810=&Never show the weight mode warning dialog
+11811=Never prompt about current weight mode when entering the formula finder or peptide fragmentation module
+11820=&Autosave options, values, and formulas on exit
+11821=Automatically save options, values, and formulas on program exit
+11830=Show Caution Statements (F7)
+11831=Caution when possibly confusing elemental combinations are in formulas (like Co vs. CO)
+11840=Show Element Mode &Quick Switch
+11841=Show option to quickly change elemental weight modes
+11850=Show Tool Tips
+11851=Show short help messages when mouse passes over certain buttons and areas
+11860=Highlight Text Fields when Selected
+11861=Highlight the entire text field when moving to it
+11870=&Hide inactive program windows
+11871=Hide the main program window when using the Formula Finder, Mole/Mass calculator, etc.
+11881=Choose a smaller number to prevent the formula window from filling the screen. If lowering, must exit and restart program before takes effect. Maximum is dependent upon screen resolution.
+11885=En Fazla 9 Formül Yazýlabilir
+11890=Module to show at startup
+11896=Module to show when the program starts
+11898=Main Window|Formula Finder|Capillary Flow Calculator|Mole/Mass Converter|Peptide Sequence Fragmentation Modeller|Amino Acid Notation Converter|Isotopic Distribution Modeller
+
+; Messages
+11900=Autosave values option saved.
+11910=Default options restored.
+11920=Values and formulas saved.
+11925=Values and formulas NOT saved since /X command line option was used.
+11930=Default options saved.
+11935=Default options NOT saved since /X command line option was used.
+
+[frmFragmentationModelling]
+12000=Peptide Sequence Fragmentation Modelling
+; General Combo Boxes
+12010=1 letter notation|3 letter notation
+12011=Amino acid sequence notation type
+12020=&Match Ions
+; Textboxes
+12051=Enter amino acid sequence here
+12061=Shifts the loaded ions to be matched by the given amount to correct for post-translational modifications.
+; Frames, labels, and checkboxes
+12100=Sequence:
+12150=N and C Terminus
+12160=&N
+12170=&C
+12180=H (hydrogen)|HH+ (protonated)|C2OH3 (acetyl)|C5O2NH6 (pyroglu)|CONH2 (carbamyl)|C7H6NS (PTC)|(none)
+12190=OH (hydroxyl)|NH2 (amide)|(bare)
+12200=Ion Types
+12210=&A Ions
+12215=&B Ions
+12220=&Y Ions
+12230=Neutral Losses
+12236=Choose ions to which losses will be applied
+12240=Loss of H2O
+12250=Loss of NH3
+12255=Loss of PO4
+12260=Charge Options
+12270=&2+ charged ions
+12280=&Threshold
+12286=The 2+ m/z value will be computed for ions above this m/z
+12300=Ion Match Options
+12310=&Remove Precursor Ion
+12320=Ion Mass
+12330=Mass Window
+12340=&Ion Matching Window
+12350=Da
+12355=Alignment &Offset
+12360=Ion Statistics
+12370=Loaded
+12375=Remaining after binning
+12380=Within tolerance
+12385=Precursor not found
+12390=Precursor removed
+12395=Precursor not removed
+12400=Matches
+12405=Score
+12410=Mass Information
+12420=Element Mode
+12425=Average
+12430=Isotopic
+
+; Column titles in grids
+; Note: # means 'number', Immon. means 'immonium', and Seq. means 'sequence'
+12500=#
+12510=Immon.
+12520=Seq.
+12550=Mass
+12560=Intensity
+12570=Symbol
+
+; Menu Items
+12800=&Load Sequence Info
+12810=&Save Sequence Info
+12820=Load List of &Ions or .Dta file to Match
+12830=&Close
+12840=&Copy Predicted Ions
+12850=Copy Predicted Ions as &RTF
+12855=Copy Predicted Ions as Html
+12860=&Paste List of Ions to Match
+12865=Copy Sequence Molecular &Weight
+12870=Clear Match Ion &List
+12880=List of &Ions to Match
+12900=&Mass Spectrum
+12910=&Update Spectrum on Change
+12915=&Dta.Txt File Browser
+12920=Ion Match List &Options
+12925=Edit Residue &Modification Symbols
+12930=&Automatically Align Ions to Match
+12940=&Fragmentation Modelling
+12950=&Copy Selected Ions
+12960=&Delete All (Clear list)
+
+[frmMsPlot]
+13000=Plot
+; The following is an abbreviation for the word 'Location'
+13010=Loc
+
+; Legend Items
+13030=Predicted Ions
+13035=Loaded Ions
+
+; Menu Items
+13100=&Export Data
+13150=&Plot Type
+13160=&Sticks To Zero
+13170=&Gaussian Peaks
+13180=Set Effective &Resolution
+13190=X Axis Gridlines
+13200=Y Axis Gridlines
+13210=&Ticks to label (approx.)
+13220=&X Axis
+13230=&Y Axis
+13235=Plot &Quality (affects speed)
+13240=&Gaussian Representation Quality
+13245=&Approximation Factor
+13250=Set &X Range
+13260=Set &Y Range
+13270=&Autoscale Y Axis
+13280=&Fix mimimum Y at zero
+13290=&Zoom Out to Previous
+13295=Ctrl+Z or Right Click
+13300=Zoom Out to Show All
+13310=&Cursor Mode
+13315=Space Enables Move
+13320=&Zoom
+13330=&Move
+13340=&Show Current Position
+13342=Show &Legend
+13345=Reset to &Default Options
+13350=&Zoom Box
+13360=Zoom &In
+13365=Left Click
+13370=Zoom In Horizontal
+13380=Zoom In Vertical
+13390=Zoom &Out
+13400=Zoom Out Horizontal
+13410=Zoom Out Vertical
+
+[frmIonMatchOptions]
+14000=Ion Matching Options
+; Buttons
+14010=Varsayýlanlara Dön
+14020=Edit Auto-Label Options
+
+; Explanations
+14050=When a list of ions is imported into the program, ions of similar mass may optionally be grouped together via a binning process to reduce the total number of data points. Next, ions around the precursor ion may be removed.
+14055=Then, the intensities are normalized to the given maximum intensity and ordered by decreasing intensity. The top-most ions (number of ions to use) are divided into distinct mass regions and the ions in each region again normalized.
+14060=The masses of the predicted ions for a given peptide sequence are easily computed. However, intensity values must also be assigned to the masses.
+14065=The B and Y ions are typically assigned the same intensity while the A ion is typically 5 times less intense. Shoulder ions (masses ± 1 Da from the B and Y ions) can be added, in addition to including neutral losses (H2O and NH3).
+
+; Frames, labels, and checkboxes
+14100=Normalization Options for Imported Data
+14110=&Group Similar Ions (Bin Data)
+14115=Mass Window
+14120=Normalized Intensity
+14130=Number of Ions to Use
+14140=Mass region subdivisions
+14150=Ion Intensities of Predicted Ions
+14160=A Ion Intensity
+14165=B Ion Intensity
+14170=Y Ion Intensity
+14180=B/Y Ion Shoulders
+14190=Neutral Losses
+14200=Frgamentation Spectrum Labels
+14210=Label main ions (a, b, y)
+14220=Label neutral loss ions
+14230=Emphasize Proline y ions
+14240=Spectrum Plotting Options
+14250=Fragmentation Data Color
+14255=Matching Ion Data Color
+14258=Click to change
+14260=Plot Fragmentation Spectrum Inverted
+14270=Auto-Label Peaks on Matching Ion Spectrum
+
+[frmSetValue]
+14500=Set Value
+14510=&Set
+14520=&Start
+
+[frmProgress]
+14700=Progress
+14710=Click to Pause
+14715=Preparing to Pause
+14720=Paused
+14725=Resuming
+14730=(Press Escape to abort)
+14740=min. elapsed/remaining
+
+[frmIsotopicDistibution]
+15000=Isotopic Distribution
+; Frames, labels, and checkboxes
+15050=Formül:
+15060=Sonuçlar:
+15070=Yük:
+15100=Ýþaretli Sonuçlar
+15105=&Auto-Label Peaks
+15110=Hesapla
+15120=Plot Data Color
+15126=Click to change
+15130=Plot Type
+15140=Sticks to Zero|Gaussian Peaks
+15145=Sticks to Zero|Gaussian Peaks|Lines Between Points
+15151=Ýzotopik Daðýlým Sonuçlarý
+15160=Paste list of ions to compare
+15165=Clear List
+15170=Comparison list data points:
+15190=Options
+15195=Comparison List
+; Column headers in the results box
+15200=Isotopic Abundances for
+15210=Mass/Charge
+15215=Neutral Mass
+15220=Fraction
+15230=Intensity
+15300=Warning, the ion comparison list contains a large number of data points. Do you really want to convert each point to a Gaussian curve?
+15305=Large Data Point Count
+
+[frmAminoAcidModificationSymbols]
+15500=Amino Acid Modification Symbols Editor
+;Directions
+15550=Modified residues in an amino acid sequence are notated by placing a modification symbol directly after the residue's 1 letter or 3 letter abbreviation.
+15555=The phosphorylation symbol is defined separately because phosphorylated residues can lose a phosphate group during fragmentation.
+15560=As an example, if the phosphorylation symbol is *, then in the sequence 'GlyLeuTyr*' the tyrosine residue is phosphorylated.
+15565=Allowable symbols for user-defined modifications are
+15570=Modification symbols can be more than 1 character long, though it is suggested that you keep them to just 1 character long to make it easier for the parsing routine to correctly parse residues with multiple modifications.
+15575=If a residue has multiple modifications, then simply place the appropriate modification symbols after the residue, for example in 'FLE*#L' the E residue is modified by both the * and # modifications.
+15580=Modification masses can be negative values, as well as positive values.
+;Table Tool Tip
+15600=
+15601=Click to change a modification symbol
+; Table column headers
+15610=Symbol
+15620=Mass
+15640=Comment
+; Labels
+15700=Modification Symbols Defined
+15710=Single click to edit or remove. Click in blank row to add.
+15720=Standard Modifications
+15730=Phosphorylation Symbol:
+; Messages
+15750=The amino acid symbol modification will be updated with the parameters below. Select Remove to delete the modification symbol or Cancel to ignore any changes.
+15760=Warning, the new phosphorylation symbol is already being used for another modification. Do you really want to use this symbol for phosphorylation and consequently remove the other definition?
+15765=Modification Symbol Conflict
+15770=Are you sure you want to lose all changes?
+15775=Closing Edit Modification Symbols Window
+; Buttons
+15800=&Reset to Defaults
+15801=Resets modification symbols to defaults
+15810=&Add selected to list
+
+[frmDtaTxtFileBrowser]
+16000=_Dta.Txt File Browser
+; Labels
+16050=Scan Number Start
+16060=Scan Number End
+16070=Parent Ion MH+
+16080=Parent Ion Charge
+; Buttons
+16100=&Jump to scan
+16101=Shortcut is Ctrl+J
+16110=&Keep Window On Top
+
+[ErrorAndStatusMessages]
+20001=Bilinmeyen Element
+20003=Missing closing parentheses
+20004=Unmatched parentheses
+20005=Cannot have a 0 directly after an element or dash (-)
+20006=Number too large or must only be after [, -, ), or caret (^)
+20007=Sayý Çok Büyük
+20011=Numbers should follow left brackets, not right brackets (unless 'treat brackets' as parentheses is on)
+20012=A number must be present after a bracket and/or after the decimal point
+20013=Missing closing bracket, ]
+20014=Misplaced number; should only be after an element, [, ), -, or caret (^)
+20015=Unmatched bracket
+20016=Cannot handle nested brackets or brackets inside multiple hydrates (unless 'treat brackets as parentheses' is on)
+20018=Bilinmeyen Element
+20020=There must be an isotopic mass number following the caret (^)
+20022=An element must be present after the isotopic mass after the caret (^)
+20023=Negative isotopic masses are not allowed after the caret (^)
+20024=Isotopic masses are not allowed for abbreviations
+20025=An element must be present after the leading coefficient of the dash
+20026=Isotopic masses are not allowed for abbreviations; D is an abbreviation
+20027=Numbers cannot contain more than one decimal point
+20028=Circular abbreviation reference; can't have an abbreviation referencing a second abbreviation that depends upon the first one
+20030=Invalid formula subtraction; one or more atoms (or too many atoms) in the right-hand formula are missing (or less abundant) in the left-hand formula
+20050=Target value is greater than 100%, an impossible value.
+20075=Letters are not allowed in the calculator line
+20076=Missing closing parenthesis
+20077=Unmatched parentheses
+20078=Misplaced number; or number too large, too small, or too long
+20080=Misplaced operator
+20081=Track variable is less than or equal to 1; program bug; please notify programmer
+20082=Missing operator.
+20085=Cannot take negative numbers to a decimal power
+20086=Cannot take zero to a negative power
+20087=Cannot take zero to the zeroth power
+20089=A single positive or negative number must be present after a caret (^)
+20090=Numbers cannot contain more than one decimal point
+20091=You tried to divide a number by zero. Please correct the problem and recalculate.
+20092=Spaces are not allowed in mathematical expressions
+20093=Use a period for a decimal point
+20094=Use a comma for a decimal point
+20095=A number must be present after a decimal point
+20100=Error Saving Abbreviation File
+20110=The default abbreviation file has been re-created.
+20115=The old file has been renamed
+20120=[AMINO ACIDS] heading not found in MWT_ABBR.DAT file. This heading must be located before/above the [ABBREVIATIONS] heading.
+20130=[ABBREVIATIONS] heading not found in MWT_ABBR.DAT file. This heading must be located before/above the [AMINO ACIDS] heading.
+20135=Select OK to continue with amino acids abbreviations only.
+20140=The Abbreviations File was not found in the program directory
+20150=Error Loading/Creating Abbreviation File
+20160=Kýsaltma Bilinmiyor -- Geçersiz Formül
+20170=Ignoring Duplicate Abbreviation
+20180=Ignoring Abbreviation; Invalid Character
+20190=Ignoring Abbreviation; too long
+20200=Ignoring Invalid Line
+20210=The default elements file has been re-created.
+20220=Possibly incorrect weight for element
+20230=Possibly incorrect uncertainty for element
+20250=Ignoring Line; Invalid Element Symbol
+20260=[ELEMENTS] heading not found in MWT_ELEM.DAT file. This heading must be located in the file.
+20265=Select OK to continue with default Element values.
+20270=Elementler Dosyasý Program Klasöründe Bulunamadý
+20280=Elementler Dosyasýnýn Yüklenmesinde veya Yazýlmasýnda Hata Var
+20305=Continuing with default captions.
+20320=Elementler Dosyasýnýn Kaydýnda Hata Var
+20330=Deðerler Dosyasýnýn Yüklenmesinde veya Yazýlmasýnda Hata Var
+20340=Select OK to continue without loading default Values and Formulas.
+20345=If using a Read-Only drive, use the /X switch at the command line to prevent this error.
+20350=Hata
+20360=Error Saving Default Options File
+20380=Error Saving Values and Formulas File
+20400=Error Loading/Creating Default Options File
+20410=Select OK to continue without loading User Defaults.
+20440=The language file could not be successfully opened or was formatted incorrectly.
+20450=Unable to load language-specific captions
+20460=The language file could not be found in the program directory
+20470=The file requested for molecular weight processing was not found
+20480=Dosya Bulunmadý
+20490=Bu dosya zaten var. Deðiþtirilsin mi?
+20500=Dosya Mevcut
+20510=Error Reading/Writing files for batch processing
+20515=Select OK to abort batch file processing.
+20520=Programda Hata
+20530=These lines of code should not have been encountered. Please notify programmer.
+20550=Percent solver cannot be used when brackets are being treated as parentheses. You can change the bracket recognition mode by choosing Change Program Preferences under the Options menu.
+20555=Percent Solver not Available
+20560=En Fazla 9 Formül Yazýlabilir
+20570=Formül Yazýlabilecek Boþ Bir Alan Zaten Var
+20580=Turn off Percent Solver (F11) before creating a new formula.
+20590=An overflow error has occured. Please reduce number sizes and recalculate.
+20600=Bir Hata Görüldü
+20605=Please exit the program and report the error to the programmer. Select About from the Help menu to see the E-mail address.
+20610=Spaces are not allowed in formulas
+20620=Geçersiz Karakter :
+20630=Yeni Formül Ýçin Kopya Yapýlamadý.
+20650=Formül Yazýlabilecek Boþ Bir Alan Zaten Var
+20655=Percent Solver mode is on (F11 to exit mode).
+20660=Warning, isotopic mass is probably too large for element
+20662=Warning, isotopic mass is probably too small for element
+20665=vs avg atomic wt of
+20670=Warning, isotopic mass is impossibly small for element
+20675=protons
+20680=Not: Böyle bir kayýt yok, Yazdýklarýnýzý kontrol ediniz
+20685=Note: for % Solver, a left bracket must precede an x
+20690=Note: brackets are being treated as parentheses
+20700=One or more elements must be checked.
+20705=Maximum hits must be greater than 0.
+20710=Maximum hits must be less than
+20715=Minimum number of elements must be 0 or greater.
+20720=Minimum number of elements must be less than maximum number of elements.
+20725=Maximum number of elements must be less than 65,025
+20730=An atomic weight must be entered for custom elements.
+20735=Atomic Weight must be greater than 0 for custom elements.
+20740=Target molecular weight must be entered.
+20745=Target molecular weight must be greater than 0.
+20755=A maximum molecular weight must be entered.
+20760=Maximum molecular weight must be greater than 0.
+20765=Target percentages must be entered for element
+20770=Target percentage must be greater than 0.
+20775=Custom elemental weights must contain only numbers or only letters. If letters are used, they must be for a single valid elemental symbol or abbreviation.
+20780=Custom elemental weight is empty. If letters are used, they must be for a single valid elemental symbol or abbreviation.
+20785=Unknown element or abbreviation for custom elemental weight
+20790=Only single elemental symbols or abbreviations are allowed.
+20800=Caution, no abbreviations were loaded -- Command has no effect.
+20805=Cannot handle fractional numbers of atoms
+
+20900=Error Reading/Writing sequence information file.
+20910=Ions are already present in the ion list. Replace with new ions?
+20920=Replace Existing Ions
+20930=Loading Ion List
+20940=Process aborted
+20945=Aborted
+20950=Normalizing ions
+20960=Normalizing by region
+20965=Sorting by Intensity
+20970=Matching Ions
+20980=The clipboard is empty. No ions to paste.
+20985=No ions
+20990=Pasting ion list
+21000=Determining number of ions in list
+21010=Parsing list
+21020=No valid ions were found on the clipboard. A valid ion list is a list of mass and intensity pairs, separated by commas, tabs, or spaces. One mass/intensity pair should be present per line.
+21030=Error writing data to file
+21040=Set Range
+21050=Start Val
+21055=End Val
+21060=Set X Axis Range
+21065=Set Y Axis Range
+21070=Enter a new Gaussian Representation quality factor. Higher numbers result in smoother Gaussian curves, but slower updates. Valid range is 1 to 50, default is 20.
+21072=Gaussian Representation Quality
+21075=Enter a new plotting approximation factor. Higher numbers result in faster updates, but give a less accurate graphical representation when viewing a wide mass range (zoomed out). Valid range is 1 to 50, default is 10.
+21077=Plotting Approximation Factor
+21080=Resolving Power Specifications
+21090=Resolving Power
+21100=X Value of Specification
+21110=Please enter the approximate number of ticks to label on the axis
+21115=Axis Ticks
+21120=Creating Gaussian Representation
+21130=Preparing plot
+21135=Drawing plot
+21140=Are you sure you want to restore the default plotting options?
+21145=Restore Default Options
+21150=Auto Align Ions
+21155=Maximum Offset
+21160=Offset Increment
+21165=Aligning Ions
+
+21500=All Files
+21510=Text Files
+21515=txt
+21520=Data Files
+21525=csv
+21530=Sequence Files
+21535=seq
+21540=Ion List Files
+21545=txt
+21550=cap
+21555=Capillary Flow Info Files
+
+[CautionStatments]
+; Note: Caution statement keynames are case sensitive; i.e. Bi is different than BI
+; You may add new caution statements if desired; however, you will need to save
+; the file with a name other than Lang_English and change the Language= key
+; since this file is not loaded if the language is English
+22000=Dikkat
+Bi=Bi = bismuth; BI = boron-iodine.
+Bk=Bk = berkelium; BK = boron-potassium.
+Bu=Bu = the butyl group; BU = boron-uranium.
+Cd=Cd = cadmium; CD = carbon-deuterium.
+Cf=Cf = californium; CF = carbon-fluorine.
+Co=Co = cobalt; CO = carbon-oxygen.
+Cs=Cs = cesium; CS = carbon-sulfur.
+Cu=Cu = copper; CU = carbon-uranium.
+Dy=Dy = dysprosium; DY = deuterium-yttrium.
+Hf=Hf = hafnium; HF = hydrogen-fluorine.
+Ho=Ho = holmium; HO = hydrogen-oxygen.
+In=In = indium; IN = iodine-nitrogen.
+Nb=Nb = niobium; NB = nitrogen-boron.
+Nd=Nd = neodymium; ND = nitrogen-deuterium.
+Ni=Ni = nickel; NI = nitrogen-iodine.
+No=No = nobelium; NO = nitrogen-oxygen.
+Np=Np = neptunium; NP = nitrogen-phosphorus.
+Os=Os = osmium; OS = oxygen-sulfur.
+Pd=Pd = palladium; PD = phosphorus-deuterium.
+Ph=Ph = phenyl, PH = phosphorus-hydrogen.
+Pu=Pu = plutonium; PU = phosphorus-uranium.
+Py=Py = pyridine; PY = phosphorus-yttrium.
+Sb=Sb = antimony; SB = sulfor-boron.
+Sc=Sc = scandium; SC = sulfur-carbon.
+Si=Si = silicon; SI = sulfur-iodine.
+Sn=Sn = tin; SN = sulfor-nitrogen.
+TI=TI = tritium-iodine, Ti = titanium.
+Yb=Yb = ytterbium; YB = yttrium-boron.
+BPY=BPY = boron-phosphorus-yttrium; Bpy = bipyridine.
+BPy=BPy = boron-pyridine; Bpy = bipyridine.
+Bpy=Bpy = bipyridine.
+Cys=Cys = cysteine; CYS = carbon-yttrium-sulfur.
+His=His = histidine; HIS = hydrogen-iodine-sulfur.
+Hoh=HoH = holmium-hydrogen; HOH = hydrogen-oxygen-hydrogen (aka water).
+Hyp=Hyp = hydroxyproline; HYP = hydrogen-yttrium-phosphorus.
+OAc=OAc = oxygen-actinium; Oac = acetate.
+Oac=Oac = acetate.
+Pro=Pro = proline; PrO = praseodymium-oxygen.
+PrO=Pro = proline; PrO = praseodymium-oxygen.
+Val=Val = valine; VAl = vanadium-aluminum.
+VAl=Val = valine; VAl = vanadium-aluminum.
diff --git a/msplot.frm b/msplot.frm
new file mode 100644
index 0000000..4a4f498
--- /dev/null
+++ b/msplot.frm
@@ -0,0 +1,2034 @@
+VERSION 5.00
+Begin VB.Form frmMsPlot
+ Caption = "Plot"
+ ClientHeight = 5460
+ ClientLeft = 165
+ ClientTop = 795
+ ClientWidth = 7665
+ HelpContextID = 3090
+ Icon = "msplot.frx":0000
+ KeyPreview = -1 'True
+ LinkTopic = "Form1"
+ ScaleHeight = 5460
+ ScaleWidth = 7665
+ StartUpPosition = 3 'Windows Default
+ Tag = "13000"
+ Begin VB.Frame fraLegend
+ BorderStyle = 0 'None
+ Height = 225
+ Left = 0
+ TabIndex = 2
+ Top = 0
+ Width = 4695
+ Begin VB.Line linLegend
+ Index = 0
+ Visible = 0 'False
+ X1 = 360
+ X2 = 120
+ Y1 = 120
+ Y2 = 120
+ End
+ Begin VB.Label lblLegend
+ Caption = "Series 1"
+ Height = 195
+ Index = 0
+ Left = 480
+ TabIndex = 4
+ Top = 20
+ Width = 1815
+ End
+ Begin VB.Line linLegend
+ Index = 1
+ Visible = 0 'False
+ X1 = 2640
+ X2 = 2400
+ Y1 = 120
+ Y2 = 120
+ End
+ Begin VB.Label lblLegend
+ Caption = "Series 2"
+ Height = 195
+ Index = 1
+ Left = 2760
+ TabIndex = 3
+ Top = 20
+ Width = 1815
+ End
+ End
+ Begin VB.Frame fraPlot
+ BorderStyle = 0 'None
+ Height = 2985
+ Left = 120
+ TabIndex = 0
+ Top = 600
+ Width = 4785
+ Begin VB.Timer tmrUpdatePlot
+ Interval = 100
+ Left = 4320
+ Top = 0
+ End
+ Begin VB.Shape shpZoomBox
+ BorderColor = &H000000FF&
+ BorderStyle = 4 'Dash-Dot
+ Height = 855
+ Left = 120
+ Top = 360
+ Width = 855
+ End
+ Begin VB.Line linData
+ Index = 1
+ Visible = 0 'False
+ X1 = 2160
+ X2 = 2160
+ Y1 = 600
+ Y2 = 1080
+ End
+ Begin VB.Line linTickMajor
+ DrawMode = 9 'Not Mask Pen
+ Index = 1
+ Visible = 0 'False
+ X1 = 840
+ X2 = 840
+ Y1 = 240
+ Y2 = 720
+ End
+ Begin VB.Line linXAxis
+ Visible = 0 'False
+ X1 = 1320
+ X2 = 600
+ Y1 = 720
+ Y2 = 720
+ End
+ Begin VB.Line linYAxis
+ Visible = 0 'False
+ X1 = 600
+ X2 = 600
+ Y1 = 720
+ Y2 = 120
+ End
+ Begin VB.Label lblTick
+ BackStyle = 0 'Transparent
+ Caption = "123.45"
+ Height = 200
+ Index = 1
+ Left = 720
+ TabIndex = 1
+ Top = 840
+ Visible = 0 'False
+ Width = 500
+ End
+ Begin VB.Line linTickMinor
+ DrawMode = 9 'Not Mask Pen
+ Index = 1
+ Visible = 0 'False
+ X1 = 960
+ X2 = 960
+ Y1 = 480
+ Y2 = 720
+ End
+ Begin VB.Line linGridline
+ BorderColor = &H00008000&
+ BorderStyle = 3 'Dot
+ DrawMode = 9 'Not Mask Pen
+ Index = 1
+ Visible = 0 'False
+ X1 = 720
+ X2 = 720
+ Y1 = 240
+ Y2 = 720
+ End
+ End
+ Begin VB.Label lblCurrentPos
+ Caption = "Loc: 0,0"
+ Height = 225
+ Left = 5280
+ TabIndex = 5
+ Top = 0
+ Width = 2115
+ End
+ Begin VB.Menu mnuFile
+ Caption = "&File"
+ Begin VB.Menu mnuExportData
+ Caption = "&Export Data..."
+ End
+ Begin VB.Menu mnuFileSepBar1
+ Caption = "-"
+ End
+ Begin VB.Menu mnuClose
+ Caption = "&Close"
+ End
+ End
+ Begin VB.Menu mnuOptions
+ Caption = "&Options"
+ Begin VB.Menu mnuPlotType
+ Caption = "&Plot Type"
+ Begin VB.Menu mnuPlotTypeSticksToZero
+ Caption = "&Sticks to Zero"
+ End
+ Begin VB.Menu mnuPlotTypeGaussianPeaks
+ Caption = "&Gaussian Peaks"
+ Checked = -1 'True
+ End
+ End
+ Begin VB.Menu mnuSetResolution
+ Caption = "Set Effective &Resolution..."
+ End
+ Begin VB.Menu mnuOptionsSepBar6
+ Caption = "-"
+ End
+ Begin VB.Menu mnuGridLinesXAxis
+ Caption = "X Axis Gridlines"
+ Shortcut = ^X
+ End
+ Begin VB.Menu mnuGridLinesYAxis
+ Caption = "Y Axis Gridlines"
+ Shortcut = ^Y
+ End
+ Begin VB.Menu mnuTicks
+ Caption = "&Ticks to label (approx.)"
+ Begin VB.Menu mnuTicksXAxis
+ Caption = "&X Axis..."
+ End
+ Begin VB.Menu mnuTicksYAxis
+ Caption = "&Y Axis..."
+ End
+ End
+ Begin VB.Menu mnuPlotQuality
+ Caption = "&Plot Quality (affects speed)"
+ Begin VB.Menu mnuGaussianQuality
+ Caption = "&Gaussian Representation Quality"
+ End
+ Begin VB.Menu mnuApproximationFactor
+ Caption = "&Approximation Factor"
+ End
+ End
+ Begin VB.Menu mnuOptionsSepBar4
+ Caption = "-"
+ End
+ Begin VB.Menu mnuSetRangeX
+ Caption = "Set &X Range..."
+ End
+ Begin VB.Menu mnuSetRangeY
+ Caption = "Set &Y Range..."
+ End
+ Begin VB.Menu mnuAutoScaleYAxis
+ Caption = "&Autoscale Y Axis"
+ Checked = -1 'True
+ Shortcut = ^F
+ End
+ Begin VB.Menu mnuFixMinimumYAtZero
+ Caption = "&Fix mimimum Y at zero"
+ End
+ Begin VB.Menu mnuOptionsSepBar5
+ Caption = "-"
+ End
+ Begin VB.Menu mnuZoomOutToPrevious
+ Caption = "&Zoom Out to Previous"
+ End
+ Begin VB.Menu mnuZoomOutFullScale
+ Caption = "Zoom Out to Show All"
+ Shortcut = ^A
+ End
+ Begin VB.Menu mnuOptionsSepBar1
+ Caption = "-"
+ End
+ Begin VB.Menu mnuCursorMode
+ Caption = "&Cursor Mode"
+ Begin VB.Menu mnuCursorModeZoom
+ Caption = "&Zoom"
+ Checked = -1 'True
+ End
+ Begin VB.Menu mnuCursorModeMove
+ Caption = "&Move"
+ End
+ End
+ Begin VB.Menu mnuShowCurrentPosition
+ Caption = "&Show Current Position"
+ Checked = -1 'True
+ Shortcut = ^P
+ End
+ Begin VB.Menu mnuShowLegend
+ Caption = "Show &Legend"
+ Shortcut = ^L
+ End
+ Begin VB.Menu mnuOptionsSepBar3
+ Caption = "-"
+ End
+ Begin VB.Menu mnuResetToDefaults
+ Caption = "Reset to &Default Options"
+ End
+ End
+ Begin VB.Menu mnuZoomOptions
+ Caption = "&Zoom Box"
+ Begin VB.Menu mnuZoomIn
+ Caption = "Zoom &In"
+ End
+ Begin VB.Menu mnuZoomInHorizontal
+ Caption = "Zoom In Horizontal"
+ End
+ Begin VB.Menu mnuZoomInVertical
+ Caption = "Zoom In Vertical"
+ End
+ Begin VB.Menu mnuZoomSepBar2
+ Caption = "-"
+ End
+ Begin VB.Menu mnuZoomOut
+ Caption = "Zoom &Out"
+ End
+ Begin VB.Menu mnuZoomOutHorizontal
+ Caption = "Zoom Out Horizontal"
+ End
+ Begin VB.Menu mnuZoomOutVertical
+ Caption = "Zoom Out Vertical"
+ End
+ End
+End
+Attribute VB_Name = "frmMsPlot"
+Attribute VB_GlobalNameSpace = False
+Attribute VB_Creatable = False
+Attribute VB_PredeclaredId = True
+Attribute VB_Exposed = False
+Option Explicit
+
+Private Type usrRect
+ x1 As Long
+ y1 As Long
+ x2 As Long
+ y2 As Long
+End Type
+
+Private Type usrScalingRangeValues
+ PlotRangeStretchVal As Double
+ StartVal As Double
+ EndVal As Double
+ LowerLimit As Double
+ UpperLimit As Double
+End Type
+
+Private ZoomBoxCoords As usrRect
+Private PlotOptions As usrPlotDataOptions
+
+Private blnSlidingGraph As Boolean
+Private PlotRangeAtMoveStart As usrPlotRange
+Private blnResizingWindow As Boolean
+Private blnDrawingZoomBox As Boolean, blnZoomBoxDrawn As Boolean
+
+Private intDataSetLoadedCount As Integer ' Count of the number of data sets loaded (originally 0); 1 if 1 data set (index 0 of LoadedXYData), 2 if 2 data sets, etc.
+Private LoadedXYData(MAX_DATA_SETS) As usrXYDataSet ' The data to plot; 0-based array, using indices 0 and 1 since MAX_DATA_SETS = 1; However, .XYDataList() is 1=based
+Private InitialStickData(MAX_DATA_SETS) As usrXYDataSet ' 0-based array: If the user submits Stick Data (discrete data points) and requests that the sticks be converted
+ ' to a Gaussian representation, then the original, unmodified data is stored here
+
+Private TicksElapsedSinceStart As Long ' Actually increments 10 times per second rather than 1000 per second since tmrUpdatePlot.Interval = 100
+Private TickCountToUpdateAt As Long
+
+Private blnDelayUpdate As Boolean ' When true, the plot will not update
+Private blnUpdatePosition As Boolean
+Private CurrentPosX As Double, CurrentPosY As Double
+
+Private Const PLOT_RANGE_HISTORY_COUNT = 20
+Private PlotRangeHistory(PLOT_RANGE_HISTORY_COUNT, MAX_DATA_SETS) As usrPlotRange ' Keeps track of the last 5 plot ranges displayed to allow for undoing
+
+Private Sub EnableDisableZoomMenus(boolEnableMenus As Boolean)
+
+ mnuZoomOptions.Visible = boolEnableMenus
+
+End Sub
+
+Public Sub SetDelayUpdate(blnTurnOnDelay As Boolean, Optional blnZoomOutCompletely As Boolean = True)
+ blnDelayUpdate = blnTurnOnDelay
+
+ If Not blnTurnOnDelay And frmMsPlot.Visible = True Then
+ If blnZoomOutCompletely Then
+ ZoomOut blnZoomOutCompletely
+ Else
+ UpdatePlot True
+ End If
+ End If
+End Sub
+
+Private Sub DetermineCurrentScalingRange(ThisAxisScaling As usrPlotRangeAxis, TheseDataLimits As usrPlotRangeAxis, CurrentScalingRange As usrScalingRangeValues, Optional sngStretchValMultiplier As Single = 0.1)
+
+ With CurrentScalingRange
+ .PlotRangeStretchVal = (TheseDataLimits.ValEnd.Val - TheseDataLimits.ValStart.Val) * sngStretchValMultiplier
+
+ .StartVal = ThisAxisScaling.ValStart.Val - ThisAxisScaling.ValNegativeValueCorrectionOffset
+ .EndVal = ThisAxisScaling.ValEnd.Val - ThisAxisScaling.ValNegativeValueCorrectionOffset
+ .LowerLimit = TheseDataLimits.ValStart.Val - .PlotRangeStretchVal
+ .UpperLimit = TheseDataLimits.ValEnd.Val + .PlotRangeStretchVal
+ End With
+
+End Sub
+
+Private Sub EnableDisableExportDataMenu()
+ Dim intDataSetIndex As Integer, boolDataPresent As Boolean
+
+ boolDataPresent = False
+
+ For intDataSetIndex = 0 To intDataSetLoadedCount - 1
+ If LoadedXYData(intDataSetIndex).XYDataListCount > 0 Then
+ boolDataPresent = True
+ Exit For
+ End If
+ Next intDataSetIndex
+
+ mnuExportData.Enabled = boolDataPresent
+
+End Sub
+
+Private Sub EnableDisableMenuCheckmarks()
+ Dim boolLinesBetweenPoints As Boolean
+
+ With PlotOptions
+ boolLinesBetweenPoints = (.PlotTypeCode = cPlotTypeGaussian)
+ mnuPlotTypeSticksToZero.Checked = Not boolLinesBetweenPoints
+ mnuPlotTypeGaussianPeaks.Checked = boolLinesBetweenPoints
+ mnuGridLinesXAxis.Checked = .XAxis.ShowGridLinesMajor
+ mnuGridLinesYAxis.Checked = .YAxis.ShowGridLinesMajor
+ mnuAutoScaleYAxis.Checked = .AutoScaleY
+
+ mnuFixMinimumYAtZero.Checked = .FixYAxisMinimumAtZero
+ mnuFixMinimumYAtZero.Enabled = Not mnuAutoScaleYAxis.Checked
+
+ mnuSetResolution.Enabled = boolLinesBetweenPoints
+ mnuSetRangeY.Enabled = Not (mnuAutoScaleYAxis.Checked)
+ End With
+
+End Sub
+
+Public Sub ExportData()
+ Dim lngIndex As Long, strFilePath As String, strOutput As String
+ Dim intDataSetIndex As Integer, lngMaxDataListCount As Long
+ Dim OutFileNum As Integer
+
+ On Error GoTo WriteProblem
+
+ ' 1520 = Data Files, 1525 = .csv
+ strFilePath = SelectFile(frmMsPlot.hwnd, "Save File", gLastFileOpenSaveFolder, True, "", ConstructFileDialogFilterMask(LookupMessage(1520), LookupMessage(1525)), 1)
+ If Len(strFilePath) = 0 Then
+ ' No file selected (or other error)
+ Exit Sub
+ End If
+
+ OutFileNum = FreeFile()
+ Open strFilePath For Output As #OutFileNum
+
+ If intDataSetLoadedCount > 1 Then
+ strOutput = ""
+ For intDataSetIndex = 0 To intDataSetLoadedCount - 1
+ strOutput = strOutput & "Data Set " & Trim(CStr(intDataSetIndex + 1)) & " X" & "," & "Data Set " & Trim(CStr(intDataSetIndex + 1)) & " Y"
+ If intDataSetIndex < intDataSetLoadedCount - 1 Then strOutput = strOutput & ","
+ Next intDataSetIndex
+ Print #OutFileNum, strOutput
+ End If
+
+ ' Determine maximum .XyDataListCount value
+ lngMaxDataListCount = 0
+ For intDataSetIndex = 0 To intDataSetLoadedCount - 1
+ If LoadedXYData(intDataSetIndex).XYDataListCount > lngMaxDataListCount Then
+ lngMaxDataListCount = LoadedXYData(intDataSetIndex).XYDataListCount
+ End If
+ Next intDataSetIndex
+
+ For lngIndex = 1 To lngMaxDataListCount
+ strOutput = ""
+ For intDataSetIndex = 0 To intDataSetLoadedCount - 1
+ If lngIndex <= LoadedXYData(intDataSetIndex).XYDataListCount Then
+ With LoadedXYData(intDataSetIndex).XYDataList(lngIndex)
+ strOutput = strOutput & .XVal & "," & .YVal
+ End With
+ Else
+ strOutput = strOutput & ","
+ End If
+ If intDataSetIndex < intDataSetLoadedCount - 1 Then strOutput = strOutput & ","
+ Next intDataSetIndex
+ Print #OutFileNum, strOutput
+ Next lngIndex
+
+ Close #OutFileNum
+
+ Exit Sub
+
+WriteProblem:
+ MsgBox LookupMessage(1030) & ": " & strFilePath
+
+End Sub
+
+Private Function FixUpCoordinates(TheseCoords As usrRect) As usrRect
+ Dim FixedCoords As usrRect
+
+ FixedCoords = TheseCoords
+
+ With FixedCoords
+ If .x1 > .x2 Then
+ SwapValues .x1, .x2
+ End If
+ If .y1 < .y2 Then
+ SwapValues .y1, .y2
+ End If
+ End With
+
+ FixUpCoordinates = FixedCoords
+
+End Function
+
+Private Sub HidePlotForm()
+ frmFragmentationModelling.SetUpdateSpectrumMode False
+ HideFormShowMain Me
+End Sub
+Private Sub HideZoomBox(Button As Integer, boolPerformZoom As Boolean)
+
+ EnableDisableZoomMenus False
+ blnZoomBoxDrawn = False
+ blnDrawingZoomBox = False
+
+ If shpZoomBox.Visible = False Then
+ Exit Sub
+ End If
+
+ shpZoomBox.Visible = False
+
+ If Button = vbLeftButton Then
+ If boolPerformZoom Then
+ PerformZoom
+ End If
+ End If
+
+End Sub
+
+Private Sub InitializeDummyData(intDataType As Integer)
+ ' intDataType can be 0: continuous sine wave
+ ' 1: stick data (only 20 points)
+ ' 2: stick data (1000's of points, mostly zero, with a few spikes)
+
+ Dim ThisXYDataSet As usrXYDataSet
+ Dim x As Long, sngOffset As Single
+
+ Const PI = 3.14159265359
+ Const DegToRadiansMultiplier = PI / 180 / 10
+
+ Randomize Timer
+
+ Select Case intDataType
+ Case 1
+ With ThisXYDataSet
+ .XYDataListCount = 14
+ ReDim .XYDataList(.XYDataListCount)
+ .XYDataList(1).XVal = 154
+ .XYDataList(1).YVal = 79
+ .XYDataList(2).XVal = 154.51
+ .XYDataList(2).YVal = 25
+ .XYDataList(3).XVal = 154.95
+ .XYDataList(3).YVal = 15
+ .XYDataList(4).XVal = 280.2
+ .XYDataList(4).YVal = 60
+ .XYDataList(5).XVal = 281.15
+ .XYDataList(5).YVal = 20
+ .XYDataList(6).XVal = 282.201
+ .XYDataList(6).YVal = 10
+ .XYDataList(7).XVal = 312
+ .XYDataList(7).YVal = 23
+ .XYDataList(8).XVal = 312.332
+ .XYDataList(8).YVal = 5
+ .XYDataList(9).XVal = 312.661
+ .XYDataList(9).YVal = 2
+ .XYDataList(10).XVal = 500
+ .XYDataList(10).YVal = 10
+ .XYDataList(11).XVal = 589
+ .XYDataList(11).YVal = 102
+ .XYDataList(12).XVal = 589.247
+ .XYDataList(12).YVal = 72.3
+ .XYDataList(13).XVal = 589.523
+ .XYDataList(13).YVal = 50.7
+ .XYDataList(14).XVal = 589.78
+ .XYDataList(14).YVal = 30
+ End With
+ SetXYData ThisXYDataSet, True, True
+ Case 2
+ With ThisXYDataSet
+ .XYDataListCount = 50000
+ ReDim .XYDataList(.XYDataListCount)
+ For x = 1 To .XYDataListCount
+ .XYDataList(x).XVal = 100 + x / 500
+ If x Mod 5000 = 0 Then
+ .XYDataList(x).YVal = Rnd(1) * .XYDataListCount / 200 * Rnd(1)
+ ElseIf x Mod 3000 = 0 Then
+ .XYDataList(x).YVal = Rnd(1) * .XYDataListCount / 650 * Rnd(1)
+ Else
+ .XYDataList(x).YVal = Rnd(1) * 3
+ End If
+ Next x
+ End With
+ SetXYData ThisXYDataSet, True, False
+ Case Else
+ With ThisXYDataSet
+ .XYDataListCount = 360! * 100!
+
+ ReDim .XYDataList(.XYDataListCount)
+ sngOffset = 10
+ For x = 1 To .XYDataListCount
+ If x Mod 5050 = 0 Then
+ sngOffset = Rnd(1) + 10
+ End If
+ .XYDataList(x).XVal = CDbl(x) / 1000 - 5
+ .XYDataList(x).YVal = sngOffset - Abs((x - .XYDataListCount / 2)) / 10000 + Sin(DegToRadiansMultiplier * x) * Cos(DegToRadiansMultiplier * x / 2) * 1.29967878493163
+ Next x
+ End With
+ SetXYData ThisXYDataSet, False, False
+ End Select
+
+ PlotOptions.IndexToHighlight = ThisXYDataSet.XYDataListCount / 2
+
+ ZoomOut True
+
+End Sub
+
+Private Sub InitializeZoomOrMove(Button As Integer, x As Single, y As Single)
+ If Button = vbLeftButton Then
+ With ZoomBoxCoords
+ .x1 = x
+ .y1 = y
+ .x2 = .x1
+ .y2 = .y1
+ End With
+
+ If mnuCursorModeZoom.Checked Then
+ ' Zooming
+ ' Begin drawing zoom/move box
+ shpZoomBox.Visible = True
+ blnZoomBoxDrawn = False
+ EnableDisableZoomMenus False
+ RedrawZoomBox
+ Else
+ ' Moving (dragging) plot
+ ' Will still update the zoom/move box to keep track of how far dragged
+ ' but will not draw the box
+ shpZoomBox.Visible = False
+ blnDrawingZoomBox = False
+ blnSlidingGraph = True
+ PlotRangeAtMoveStart = PlotRangeHistory(1, 0)
+ End If
+
+ Else
+ If shpZoomBox.Visible = True Then
+ ' User clicked outside of zoom box (not left button), hide it
+ HideZoomBox Button, False
+ Else
+ If Button = vbRightButton Then
+ ZoomOut False
+ End If
+ End If
+ End If
+
+End Sub
+
+Private Sub RespondZoomModeClick(Button As Integer, x As Single, y As Single)
+ ' The Zoom Box is visible and the user clicked inside the box
+ ' Handle the click differently depending on the location and the button
+
+ If IsZoomBoxLargeEnough(ZoomBoxCoords) Then
+ If Button = vbLeftButton Then
+ ' Left click inside box: Remove zoom/move box and zoom
+ HideZoomBox Button, True
+ ElseIf Button = vbRightButton Then
+ ' Right click inside box: Show zoom menu
+ PopupMenu mnuZoomOptions, vbPopupMenuLeftAlign
+ End If
+ Else
+ ' Clicked inside box but it's too small
+ HideZoomBox Button, False
+ SetCursorIcon
+
+ If Button = vbLeftButton Then
+ ' Left click outside box: Start a new zoom box
+ InitializeZoomOrMove Button, x, y
+ End If
+ End If
+
+End Sub
+
+Private Sub ResetMousePointer(Optional Button As Integer = 0)
+ If Button = 0 And Me.MousePointer <> vbDefault Then Me.MousePointer = vbDefault
+End Sub
+
+Private Sub ResizeZoomBox(Button As Integer, x As Single, y As Single)
+ ' For both zooming and moving, resizes the Zoom Box
+
+ ' If zooming, then redraw the box
+ If shpZoomBox.Visible = True And Button = vbLeftButton Then
+ ' Resize zoom/move box
+ ZoomBoxCoords.x2 = x
+ ZoomBoxCoords.y2 = y
+
+ RedrawZoomBox
+ End If
+
+ ' If moving, then call the PerformMove sub to initiate a move
+ If mnuCursorModeMove.Checked And Button = vbLeftButton Then
+ ' Resize zoom/move box
+ ZoomBoxCoords.x2 = x
+ ZoomBoxCoords.y2 = y
+
+ ' Moving plot
+ PerformMove
+ End If
+
+End Sub
+
+Public Sub SetAutoscaleY(boolEnable As Boolean)
+
+ If boolEnable Then
+ ' Auto Scale just turned on - replot
+ PlotOptions.AutoScaleY = True
+
+ ' Call SetFixMinimumYAtZero in order to properly set .FixYAxisMinimumAtZero
+ SetFixMinimumYAtZero PlotOptions.FixYAxisMinimumAtZero
+
+ UpdatePlot
+ Else
+ ' Auto Scale just turned off
+ PlotOptions.AutoScaleY = True
+ UpdatePlot
+ PlotOptions.AutoScaleY = False
+ End If
+ EnableDisableMenuCheckmarks
+
+End Sub
+
+Private Sub SetCursorIcon(Optional x As Single = 0, Optional y As Single = 0)
+ If mnuCursorModeMove.Checked Then
+ ' Move mode
+ ' Me.MouseIcon = imgMouseHand
+ ' Me.MousePointer = vbCustom
+ Me.MousePointer = vbSizeAll
+ Else
+ ' Zoom Mode
+ If blnZoomBoxDrawn Then
+ If IsClickInBox(x, y, ZoomBoxCoords) Then
+ If Me.MousePointer <> vbArrowQuestion Then
+ If IsZoomBoxLargeEnough(ZoomBoxCoords) Then
+' Me.MouseIcon = imgMouseMagnify
+' Me.MousePointer = vbCustom
+ 'Me.MousePointer = vbArrowQuestion
+ Me.MousePointer = vbUpArrow
+ End If
+ End If
+ Else
+ Me.MousePointer = vbCrosshair
+ End If
+ Else
+ Me.MousePointer = vbCrosshair
+ End If
+ End If
+ EnableDisableMenuCheckmarks
+End Sub
+
+Public Sub SetCursorMode(boolMoveMode As Boolean)
+
+ mnuCursorModeZoom.Checked = Not boolMoveMode
+ mnuCursorModeMove.Checked = boolMoveMode
+
+ SetCursorIcon
+
+End Sub
+
+Public Sub SetFixMinimumYAtZero(boolEnable As Boolean)
+ With PlotOptions
+ ' If sticks to zero plot and autoscaling then fix Y axis minimum at zero
+ If .PlotTypeCode = cPlotTypeSticks And .AutoScaleY Then
+ .FixYAxisMinimumAtZero = True
+ Else
+ .FixYAxisMinimumAtZero = boolEnable
+ End If
+ End With
+
+ EnableDisableMenuCheckmarks
+
+ UpdatePlot True
+
+End Sub
+
+Public Sub SetGridlinesXAxis(boolEnable As Boolean)
+ PlotOptions.XAxis.ShowGridLinesMajor = boolEnable
+ UpdatePlot False
+ EnableDisableMenuCheckmarks
+End Sub
+
+Public Sub SetGridlinesYAxis(boolEnable As Boolean)
+ PlotOptions.YAxis.ShowGridLinesMajor = boolEnable
+ UpdatePlot False
+ EnableDisableMenuCheckmarks
+End Sub
+
+Public Sub SetLegendVisibility(blnShowLegend As Boolean)
+ mnuShowLegend.Checked = blnShowLegend
+ fraLegend.Visible = blnShowLegend
+
+ fraPlot.Visible = False
+
+ PositionControls
+ UpdatePlot False
+
+ fraPlot.Visible = True
+End Sub
+
+Public Sub SetNewRange(blnXAxis As Boolean, boolPromptUserForValues As Boolean, Optional dblNewStartVal As Double = 0, Optional dblNewEndVal As Double = 0)
+ Dim CurrentScalingRange As usrScalingRangeValues, ThisDataSetScalingRange As usrScalingRangeValues
+ Dim dblDefaultSeparationValue As Double
+ Dim intDataSetIndex As Integer
+ Dim strFormatString As String
+
+ For intDataSetIndex = 0 To intDataSetLoadedCount - 1
+ If blnXAxis Then
+ DetermineCurrentScalingRange PlotOptions.Scaling.x, PlotOptions.DataLimits(intDataSetIndex).x, ThisDataSetScalingRange, 1000
+ Else
+ DetermineCurrentScalingRange PlotOptions.Scaling.y, PlotOptions.DataLimits(intDataSetIndex).y, ThisDataSetScalingRange, 1000
+ End If
+ If intDataSetIndex = 0 Then
+ CurrentScalingRange = ThisDataSetScalingRange
+ Else
+ With CurrentScalingRange
+ If ThisDataSetScalingRange.LowerLimit < .LowerLimit Then
+ .LowerLimit = ThisDataSetScalingRange.LowerLimit
+ End If
+ If ThisDataSetScalingRange.UpperLimit > .UpperLimit Then
+ .UpperLimit = ThisDataSetScalingRange.UpperLimit
+ End If
+ If ThisDataSetScalingRange.StartVal < .StartVal Then
+ .StartVal = ThisDataSetScalingRange.StartVal
+ End If
+ If ThisDataSetScalingRange.EndVal > .EndVal Then
+ .EndVal = ThisDataSetScalingRange.EndVal
+ End If
+ End With
+ End If
+ Next intDataSetIndex
+
+ With CurrentScalingRange
+ If .StartVal = 0 And .EndVal = 0 Then
+ .StartVal = .LowerLimit
+ .EndVal = .UpperLimit
+ End If
+ End With
+
+ If boolPromptUserForValues Or (dblNewStartVal = 0 And dblNewEndVal = 0) Then
+
+ With PlotRangeHistory(1, 0)
+ If blnXAxis Then
+ strFormatString = ConstructFormatString(Abs(.x.ValEnd.Val - .x.ValStart.Val) / 100)
+ Else
+ strFormatString = ConstructFormatString(Abs(.y.ValEnd.Val - .y.ValStart.Val) / 100)
+ End If
+ End With
+
+ With CurrentScalingRange
+ .StartVal = Format(.StartVal, strFormatString)
+ .EndVal = Format(.EndVal, strFormatString)
+ End With
+
+ With frmSetValue
+ .Caption = LookupMessage(1040)
+ .lblStartVal.Caption = LookupMessage(1050)
+ .txtStartVal = CurrentScalingRange.StartVal
+ .lblEndVal.Caption = LookupMessage(1055)
+ .txtEndVal = CurrentScalingRange.EndVal
+
+ ' Round dblDefaultSeparationValue to nearest 1, 2, or 5 (or multiple of 10 thereof)
+ dblDefaultSeparationValue = RoundToMultipleOf10((CurrentScalingRange.EndVal - CurrentScalingRange.StartVal) / 10)
+
+ .SetLimits True, CurrentScalingRange.LowerLimit, CurrentScalingRange.UpperLimit, dblDefaultSeparationValue
+
+ If blnXAxis Then
+ .Caption = LookupMessage(1060)
+ Else
+ .Caption = LookupMessage(1065)
+ End If
+
+ .Show vbModal
+ End With
+
+ If UCase(frmSetValue.lblHiddenStatus) <> "OK" Then Exit Sub
+
+ ' Set New Range
+ With frmSetValue
+ If IsNumeric(.txtStartVal) Then dblNewStartVal = CDbl(.txtStartVal)
+ If IsNumeric(.txtEndVal) Then dblNewEndVal = CDbl(.txtEndVal)
+ End With
+ End If
+
+ ' Set new scaling value for all loaded data sets
+ If blnXAxis Then
+ PlotOptions.Scaling.x.ValStart.Val = dblNewStartVal
+ PlotOptions.Scaling.x.ValEnd.Val = dblNewEndVal
+ Else
+ PlotOptions.Scaling.y.ValStart.Val = dblNewStartVal
+ PlotOptions.Scaling.y.ValEnd.Val = dblNewEndVal
+ End If
+
+ UpdatePlot True
+
+End Sub
+
+Public Sub SetXYDataVia2DArray(NewXYData() As Double, NewXYDataCount As Long, intDataSetIndexToUse As Integer, boolTreatDataAsDiscretePoints As Boolean, Optional blnZoomOutCompletely As Boolean = True)
+ ' Assumes NewXYData() is a 2D array with 2 columns
+ ' Further, assumes NewXYData() is a 1-based array in the first dimension but 0-based in the second
+
+ Dim ThisXYDataSet As usrXYDataSet, lngIndex As Long
+ Dim boolConvertStickDataToGaussianRepresentation As Boolean
+
+ If intDataSetIndexToUse < 0 Then
+ MsgBox "Invalid data set number. Must be between 0 and " & Trim(Str(MAX_DATA_SETS - 1)) & " Assuming value of 0", vbExclamation + vbOKOnly, "Error"
+ intDataSetIndexToUse = 0
+ ElseIf intDataSetIndexToUse > MAX_DATA_SETS - 1 Then
+ MsgBox "Invalid data set number. Must be between 0 and " & Trim(Str(MAX_DATA_SETS - 1)) & " Assuming value of " & Trim(Str(MAX_DATA_SETS - 1)), vbExclamation + vbOKOnly, "Error"
+ intDataSetIndexToUse = MAX_DATA_SETS - 1
+ End If
+
+ With ThisXYDataSet
+ .XYDataListCount = NewXYDataCount
+ .XYDataListCountDimmed = NewXYDataCount + 1
+ ReDim .XYDataList(.XYDataListCountDimmed)
+
+ For lngIndex = 1 To NewXYDataCount
+ .XYDataList(lngIndex).XVal = NewXYData(lngIndex, 0)
+ .XYDataList(lngIndex).YVal = NewXYData(lngIndex, 1)
+ Next lngIndex
+ End With
+
+ boolConvertStickDataToGaussianRepresentation = (PlotOptions.PlotTypeCode = cPlotTypeGaussian)
+ SetXYData ThisXYDataSet, boolTreatDataAsDiscretePoints, intDataSetIndexToUse, boolConvertStickDataToGaussianRepresentation, blnZoomOutCompletely
+
+End Sub
+
+Private Sub SetXYData(NewXYData As usrXYDataSet, boolTreatDataAsDiscretePoints As Boolean, intDataSetIndexToUse As Integer, Optional boolConvertStickDataToGaussianRepresentation As Boolean = False, Optional blnZoomOutCompletely As Boolean = True)
+ ' intDataSetIndexToUse can be 0 up to MAX_DATA_SETS, indicating which data set to use
+ Dim XYDataPointerArray() As Long, XYDataPointerArrayCount As Long
+ Dim intDataSetIndex As Integer, lngIndex As Long
+ Dim dblCompareVal As Double
+
+ If intDataSetIndexToUse < 0 Then
+ MsgBox "Invalid data set number. Must be between 0 and " & Trim(Str(MAX_DATA_SETS - 1)) & " Assuming value of 0", vbExclamation + vbOKOnly, "Error"
+ intDataSetIndexToUse = 0
+ ElseIf intDataSetIndexToUse > MAX_DATA_SETS - 1 Then
+ MsgBox "Invalid data set number. Must be between 0 and " & Trim(Str(MAX_DATA_SETS - 1)) & " Assuming value of " & Trim(Str(MAX_DATA_SETS - 1)), vbExclamation + vbOKOnly, "Error"
+ intDataSetIndexToUse = MAX_DATA_SETS - 1
+ End If
+
+ ' Reset .DataLimits
+ With PlotOptions.DataLimits(intDataSetIndexToUse)
+ .x.ValStart.Val = 0
+ .y.ValEnd.Val = 0
+ .y.ValStart.Val = 0
+ .y.ValEnd.Val = 0
+ End With
+
+ If intDataSetIndexToUse > intDataSetLoadedCount - 1 Then
+ ' The number of data sets loaded must be at least intDataSetIndexToUse + 1
+ intDataSetLoadedCount = intDataSetIndexToUse + 1
+ End If
+
+ ' Sort a Pointer Array to NewXYData, then store in order in InitialStickData or LoadedXYData
+ ' First, initialize XYDataPointerArray
+ XYDataPointerArrayCount = NewXYData.XYDataListCount
+ ReDim XYDataPointerArray(XYDataPointerArrayCount + 1)
+ For lngIndex = 1 To XYDataPointerArrayCount
+ XYDataPointerArray(lngIndex) = lngIndex
+ Next lngIndex
+
+ ' Now sort
+ Me.MousePointer = vbHourglass
+ ShellSortXYData NewXYData.XYDataList(), XYDataPointerArray(), 1, XYDataPointerArrayCount
+ Me.MousePointer = vbDefault
+
+ If boolTreatDataAsDiscretePoints Then
+ ' Copy from NewXYData into InitialStickData()
+ ReDim InitialStickData(intDataSetIndexToUse).XYDataList(XYDataPointerArrayCount + 1)
+ For lngIndex = 1 To XYDataPointerArrayCount
+ InitialStickData(intDataSetIndexToUse).XYDataList(lngIndex) = NewXYData.XYDataList(XYDataPointerArray(lngIndex))
+ Next lngIndex
+ InitialStickData(intDataSetIndexToUse).XYDataListCount = XYDataPointerArrayCount
+
+ ' Load New Data into LoadedXYData; accomplished using SetPlotType provided
+ ' InitialStickData(intDataSetIndex).XYDataListCount > 0
+ SetPlotType boolConvertStickDataToGaussianRepresentation, False
+ Else
+ InitialStickData(intDataSetIndexToUse).XYDataListCount = 0
+
+ ' Copy from NewXYData into LoadedXYData()
+ ReDim LoadedXYData(intDataSetIndexToUse).XYDataList(XYDataPointerArrayCount + 1)
+ For lngIndex = 1 To XYDataPointerArrayCount
+ LoadedXYData(intDataSetIndexToUse).XYDataList(lngIndex) = NewXYData.XYDataList(XYDataPointerArray(lngIndex))
+ Next lngIndex
+ LoadedXYData(intDataSetIndexToUse).XYDataListCount = XYDataPointerArrayCount
+
+ SetPlotType True, False
+ End If
+
+ If blnZoomOutCompletely Then
+ With PlotOptions
+ .Scaling = .DataLimits(0)
+
+ ' Check other data sets to see if data limits are outside limits in .Scaling
+ For intDataSetIndex = 1 To intDataSetLoadedCount - 1
+ dblCompareVal = .DataLimits(intDataSetIndexToUse).x.ValStart.Val
+ If dblCompareVal < .Scaling.x.ValStart.Val Then
+ .Scaling.x.ValStart.Val = dblCompareVal
+ End If
+
+ dblCompareVal = .DataLimits(intDataSetIndexToUse).x.ValEnd.Val
+ If dblCompareVal < .Scaling.x.ValEnd.Val Then
+ .Scaling.x.ValEnd.Val = dblCompareVal
+ End If
+
+ dblCompareVal = .DataLimits(intDataSetIndexToUse).y.ValStart.Val
+ If dblCompareVal > .Scaling.y.ValStart.Val Then
+ .Scaling.y.ValStart.Val = dblCompareVal
+ End If
+
+ dblCompareVal = .DataLimits(intDataSetIndexToUse).y.ValEnd.Val
+ If dblCompareVal > .Scaling.y.ValEnd.Val Then
+ .Scaling.y.ValEnd.Val = dblCompareVal
+ End If
+ Next intDataSetIndex
+
+ End With
+
+ End If
+
+ ' Reset the blnLongOperationsRequired bit
+ PlotOptions.blnLongOperationsRequired = False
+
+ ' Erase all data in PlotRangeHistory()
+ ' Since this array is dimensioned using the const PLOT_RANGE_HISTORY_COUNT and MAX_DATA_SETS, it
+ ' does not need to be re-dimensioned after erasing
+ Erase PlotRangeHistory()
+
+ RefreshPlot blnZoomOutCompletely
+
+''' LoadDataIntoDynaPlot LoadedXYData(intDataSetIndexToUse), intDataSetIndexToUse
+
+End Sub
+
+'''Private Sub LoadDataIntoDynaPlot(ThisXYData As usrXYDataSet, intDataSetIndexToUse As Integer)
+'''
+''' Dim XData() As Double, YData() As Double
+''' Dim lngIndex As Long
+'''
+''' ' No longer using DynaPlot, exit sub
+''' Exit Sub
+'''
+''' If ThisXYData.XYDataListCount = 0 Then Exit Sub
+'''
+''' With ThisXYData
+'''
+''' ReDim XData(.XYDataListCount)
+''' ReDim YData(.XYDataListCount)
+'''
+''' For lngIndex = 1 To .XYDataListCount
+''' XData(lngIndex) = .XYDataList(lngIndex).XVal
+''' YData(lngIndex) = .XYDataList(lngIndex).YVal
+''' Next lngIndex
+'''
+''' End With
+'''
+'''''' If dynMSPlot.DataCurves.count < intDataSetIndexToUse + 1 Then
+'''''' ' Load data into dynPlot
+'''''' dynMSPlot.DataCurves.AddVB "Set " & intDataSetIndexToUse + 1, XData(), YData(), False
+'''''' Else
+'''''' dynMSPlot.DataCurves.Item(intDataSetIndexToUse).Curve.UpdateDataVB XData(), YData()
+'''''' End If
+'''
+'''End Sub
+
+Public Sub SetGaussianQuality(Optional intQualityFactor As Integer = -1)
+ Dim strResponse As String, intNewQualityFactor As Integer
+ Dim intDataSetIndex As Integer
+
+ If intQualityFactor < 0 Then
+ strResponse = InputBox(LookupMessage(1070) & ":", LookupMessage(1072), PlotOptions.GaussianConversion.QualityFactor)
+ Else
+ strResponse = Trim(CStr(intQualityFactor))
+ End If
+
+ If IsNumeric(strResponse) Then
+ intNewQualityFactor = CIntSafe(strResponse)
+
+ If intNewQualityFactor < 1 Or intNewQualityFactor > 50 Then
+ intNewQualityFactor = 20
+ End If
+
+ PlotOptions.GaussianConversion.QualityFactor = intNewQualityFactor
+ End If
+
+ ' The gaussian representation will be updated to reflect the new settings in SetPlotType
+ SetPlotType CBool(PlotOptions.PlotTypeCode = cPlotTypeGaussian)
+
+End Sub
+
+Public Sub SetPlotApproximationFactor(Optional intApproximationFactor As Integer = -1)
+ Dim strResponse As String, intNewFactor As Integer
+
+ If intApproximationFactor < 0 Then
+ strResponse = InputBox(LookupMessage(1075) & ":", LookupMessage(1077), PlotOptions.ApproximationFactor)
+ Else
+ strResponse = Trim(CStr(intApproximationFactor))
+ End If
+
+ If IsNumeric(strResponse) Then
+ intNewFactor = CIntSafe(strResponse)
+
+ If intNewFactor < 1 Or intNewFactor > 50 Then
+ intNewFactor = 10
+ End If
+
+ PlotOptions.ApproximationFactor = intNewFactor
+ End If
+
+ UpdatePlot False
+
+End Sub
+
+Private Sub InitializePlotOptions()
+
+ SetLegendVisibility False
+
+ With PlotOptions
+ .PlotTypeCode = cPlotTypeSticks
+ .AutoScaleY = True
+ .ApproximationFactor = 10
+
+ .XAxis.Show = True
+ .XAxis.MajorTicksToShow = 5
+ .XAxis.MinorTickMinimumPixelSep = 100
+ .XAxis.ShowMinorTicks = True
+ .XAxis.ShowGridLinesMajor = False
+
+ .YAxis.Show = True
+ .YAxis.MajorTicksToShow = 5
+ .YAxis.MinorTickMinimumPixelSep = 100
+ .YAxis.ShowMinorTicks = True
+ .YAxis.ShowGridLinesMajor = False
+
+ .GaussianConversion.ResolvingPower = 5000
+ .GaussianConversion.XValueOfSpecification = 500
+ .GaussianConversion.QualityFactor = 20
+
+ .HighlightColor = vbRed
+ End With
+
+ Dim intIndex As Integer
+ For intIndex = 0 To 1
+ linLegend(intIndex).BorderColor = GetPlotSeriesColor(intIndex)
+ linLegend(intIndex).Visible = True
+ Next intIndex
+
+ lblLegend(0) = LookupLanguageCaption(13030, "Predicted Ions")
+ lblLegend(1) = LookupLanguageCaption(13035, "Loaded Ions")
+
+ SetCursorMode False
+ SetShowCursorPosition True
+ SetLegendVisibility False
+
+End Sub
+
+Public Sub SetPlotType(boolLinesBetweenPoints As Boolean, Optional boolUpdatePlot As Boolean = True)
+ Dim intDataSetIndex As Integer
+
+ If boolLinesBetweenPoints Then
+ PlotOptions.PlotTypeCode = cPlotTypeGaussian
+ SetFixMinimumYAtZero False
+ Else
+ PlotOptions.PlotTypeCode = cPlotTypeSticks
+ SetFixMinimumYAtZero True
+ End If
+
+ mnuPlotQuality.Enabled = boolLinesBetweenPoints
+
+ For intDataSetIndex = 0 To intDataSetLoadedCount - 1
+
+ ' Reset .DataLimits
+ With PlotOptions.DataLimits(intDataSetIndex)
+ .x.ValStart.Val = 0
+ .y.ValEnd.Val = 0
+ .y.ValStart.Val = 0
+ .y.ValEnd.Val = 0
+ End With
+
+ If InitialStickData(intDataSetIndex).XYDataListCount > 0 Then
+ ' Stick data is present; need to take action
+ If boolLinesBetweenPoints Then
+ LoadedXYData(intDataSetIndex) = ConvertStickDataToGaussian(Me, InitialStickData(intDataSetIndex), PlotOptions, intDataSetIndex)
+ Else
+ LoadedXYData(intDataSetIndex) = InitialStickData(intDataSetIndex)
+ End If
+ Else
+ ' Clear data in LoadedXYData()
+ LoadedXYData(intDataSetIndex).XYDataListCount = 0
+ End If
+ Next intDataSetIndex
+
+ If boolUpdatePlot Then UpdatePlot False
+
+ EnableDisableMenuCheckmarks
+
+End Sub
+
+Public Sub SetResolution(Optional lngNewResolvingPower As Long = -1, Optional dblNewXValResLocation As Double = 500)
+ Dim strResponse As String
+
+ If lngNewResolvingPower < 1 Then
+ With frmSetValue
+ .Caption = LookupMessage(1080)
+ .lblStartVal.Caption = LookupMessage(1090)
+ .txtStartVal = PlotOptions.GaussianConversion.ResolvingPower
+ .lblEndVal.Caption = LookupMessage(1100)
+ .txtEndVal = PlotOptions.GaussianConversion.XValueOfSpecification
+
+ .SetLimits False
+
+ .Show vbModal
+ End With
+
+ If UCase(frmSetValue.lblHiddenStatus) <> "OK" Then Exit Sub
+
+ ' Set New Range
+ With frmSetValue
+ If IsNumeric(.txtStartVal) Then
+ lngNewResolvingPower = CLng(.txtStartVal)
+ Else
+ lngNewResolvingPower = 5000
+ End If
+ If IsNumeric(.txtEndVal) Then
+ dblNewXValResLocation = CDbl(.txtEndVal)
+ Else
+ dblNewXValResLocation = 500
+ End If
+ End With
+
+ End If
+
+ If lngNewResolvingPower < 1 Or lngNewResolvingPower > 1E+38 Then
+ lngNewResolvingPower = 5000
+ End If
+
+ If dblNewXValResLocation < 1 Or dblNewXValResLocation > 1E+38 Then
+ dblNewXValResLocation = 500
+ End If
+
+ PlotOptions.GaussianConversion.ResolvingPower = lngNewResolvingPower
+ PlotOptions.GaussianConversion.XValueOfSpecification = dblNewXValResLocation
+
+ ' Must recreate Gaussian representation (if Gaussian mode is on)
+ SetPlotType CBool(PlotOptions.PlotTypeCode), True
+
+End Sub
+
+Public Sub SetShowCursorPosition(boolEnable As Boolean)
+ mnuShowCurrentPosition.Checked = boolEnable
+ lblCurrentPos.Visible = boolEnable
+ fraPlot.Visible = False
+
+ PositionControls
+ UpdatePlot False
+
+ fraPlot.Visible = True
+End Sub
+
+Private Sub AxisTickCountUpdateByUser(blnXAxis As Boolean, intCurrentTickCount As Integer)
+ Dim strAxisLetter As String
+ Dim strResponse As String, intNewTickCount As Integer
+
+ If blnXAxis Then
+ strAxisLetter = "X"
+ Else
+ strAxisLetter = "Y"
+ End If
+
+ If intCurrentTickCount < 2 Or intCurrentTickCount > 30 Then intCurrentTickCount = 5
+
+ strResponse = InputBox(LookupMessage(1110) & " (" & strAxisLetter & ", 2 - 30):", LookupMessage(1115), intCurrentTickCount)
+
+ If IsNumeric(strResponse) Then
+ intNewTickCount = CIntSafe(strResponse)
+ AxisTickCountUpdate blnXAxis, intNewTickCount
+ End If
+
+ UpdatePlot False
+
+End Sub
+
+Public Sub AxisTickCountUpdate(blnXAxis As Boolean, intNewTickCount As Integer)
+ If intNewTickCount < 2 Or intNewTickCount > 30 Then intNewTickCount = 5
+
+ If blnXAxis Then
+ PlotOptions.XAxis.MajorTicksToShow = intNewTickCount
+ Else
+ PlotOptions.YAxis.MajorTicksToShow = intNewTickCount
+ End If
+End Sub
+
+Private Sub UpdateCurrentPos()
+ Dim XValue As Double, YValue As Double
+ Dim strNewString As String
+ Dim strFormatStringX As String, strFormatStringY As String
+
+ If mnuShowCurrentPosition.Checked Then
+ With PlotRangeHistory(1, 0)
+ XValue = XYPosToValue(CLng(CurrentPosX), .x)
+ YValue = XYPosToValue(CLng(CurrentPosY), .y)
+ strNewString = ConstructFormatString(Abs(.x.ValEnd.Val - .x.ValStart.Val) / 100)
+ strFormatStringX = strNewString
+
+ strNewString = ConstructFormatString(Abs(.y.ValEnd.Val - .y.ValStart.Val) / 100)
+ strFormatStringY = strNewString
+ End With
+
+ lblCurrentPos = LookupLanguageCaption(13010, "Loc") & ": " & Format(XValue, strFormatStringX) & ", " & Format(YValue, strFormatStringY)
+ End If
+
+ blnUpdatePosition = False
+End Sub
+
+Private Sub UpdatePlot(Optional boolUpdateHistory As Boolean = True)
+ Dim MostRecentPlotRange(MAX_DATA_SETS) As usrPlotRange, intHistoryIndex As Integer
+ Dim intDataSetIndex As Integer
+
+ If blnDelayUpdate Then Exit Sub
+
+ With PlotOptions
+ .PlotTop = 100
+ .PlotLeft = 300
+ .PlotWidth = fraPlot.Width - .PlotLeft - 0
+ .PlotHeight = fraPlot.Height - .PlotTop - 700
+ If .PlotHeight < 500 Then .PlotHeight = 500
+ End With
+
+ For intDataSetIndex = 0 To intDataSetLoadedCount - 1
+ MostRecentPlotRange(intDataSetIndex) = PlotRangeHistory(1, intDataSetIndex)
+ Next intDataSetIndex
+
+ ' Hide fraPlot so that it updates faster
+ fraPlot.Visible = False
+
+ ' Perform the actual update
+ DrawPlot Me, PlotOptions, LoadedXYData(), MostRecentPlotRange(), intDataSetLoadedCount
+
+ ' Show fraPlot
+ fraPlot.Visible = True
+
+ If boolUpdateHistory Then
+ ' Update the plot range history
+ For intHistoryIndex = PLOT_RANGE_HISTORY_COUNT To 2 Step -1
+ For intDataSetIndex = 0 To intDataSetLoadedCount - 1
+ PlotRangeHistory(intHistoryIndex, intDataSetIndex) = PlotRangeHistory(intHistoryIndex - 1, intDataSetIndex)
+ Next intDataSetIndex
+ Next intHistoryIndex
+ End If
+
+ If Me.MousePointer = vbHourglass Then Me.MousePointer = vbDefault
+
+ For intDataSetIndex = 0 To intDataSetLoadedCount - 1
+ PlotRangeHistory(1, intDataSetIndex) = MostRecentPlotRange(intDataSetIndex)
+ Next intDataSetIndex
+End Sub
+
+Private Sub UpdatePlotWhenIdle()
+ Dim boolUpdateHistory As Boolean
+
+ If TickCountToUpdateAt < TicksElapsedSinceStart Then
+ ' Update the plot, but don't update the history if sliding
+ If blnSlidingGraph Or blnResizingWindow Then
+ boolUpdateHistory = False
+ Else
+ boolUpdateHistory = True
+ End If
+ UpdatePlot boolUpdateHistory
+
+ TickCountToUpdateAt = 0
+ blnResizingWindow = False
+ End If
+
+End Sub
+
+Private Sub ZoomInHorizontal()
+ ' Zoom in along the horizontal axis but
+ ' Do not change the vertical range
+
+ FixUpCoordinates ZoomBoxCoords
+ With ZoomBoxCoords
+ .y1 = PlotRangeHistory(1, 0).y.ValEnd.Pos
+ .y2 = PlotRangeHistory(1, 0).y.ValStart.Pos
+ End With
+
+ HideZoomBox vbLeftButton, True
+
+End Sub
+
+Private Sub ZoomInVertical()
+ ' Zoom in along the horizontal axis but
+ ' Do not change the vertical range
+
+ FixUpCoordinates ZoomBoxCoords
+ With ZoomBoxCoords
+ .x1 = PlotRangeHistory(1, 0).x.ValStart.Pos
+ .x2 = PlotRangeHistory(1, 0).x.ValEnd.Pos
+ End With
+
+ HideZoomBox vbLeftButton, True
+
+End Sub
+
+Private Sub ZoomOut(ByVal blnZoomOutCompletely As Boolean)
+ Dim intHistoryIndex As Integer, lngIndex As Long, intDataSetIndex As Integer
+ Dim dblCompareXVal As Double, dblMinXVal As Double, dblMaxXVal As Double
+ Dim dblPlotRangeStretchVal As Double
+ Dim boolAutoScaleSaved As Boolean
+
+ If Not blnZoomOutCompletely Then
+ ' See if any previous PlotRange data exists in the history
+ ' If not then set blnZoomOutCompletely to True
+ With PlotRangeHistory(2, 0)
+ If .x.ValStart.Pos = 0 And .x.ValEnd.Pos = 0 And .x.ValStart.Pos = 0 And .x.ValEnd.Pos = 0 Then
+ ' Most recent saved zoom range is all zeroes -- not usable
+ blnZoomOutCompletely = True
+ End If
+ End With
+ End If
+
+ If blnZoomOutCompletely Then
+
+ With PlotOptions
+ boolAutoScaleSaved = .AutoScaleY
+
+ ' Override the AutoScaleY option and turn on ZoomOutFull
+ .ZoomOutFull = True
+ .AutoScaleY = True
+
+ ' Initialize .Scaling.x.ValStart.Val and .Scaling.y.ValStart.Val
+ ' Examine all loaded data sets to determine minimum and maximum XVal
+ For intDataSetIndex = 0 To intDataSetLoadedCount - 1
+ If LoadedXYData(intDataSetIndex).XYDataListCount > 0 Then
+ ' Data in LoadedXYData is not necessarily sorted by mass
+ ' Must step through data to determine minimum and maximum XVal
+ If dblMinXVal = 0 Then
+ dblMinXVal = LoadedXYData(intDataSetIndex).XYDataList(1).XVal
+ End If
+ If dblMaxXVal = 0 Then
+ dblMaxXVal = LoadedXYData(intDataSetIndex).XYDataList(LoadedXYData(intDataSetIndex).XYDataListCount).XVal
+ End If
+
+ For lngIndex = 1 To LoadedXYData(intDataSetIndex).XYDataListCount
+ dblCompareXVal = LoadedXYData(intDataSetIndex).XYDataList(lngIndex).XVal
+ If dblCompareXVal < dblMinXVal Then dblMinXVal = dblCompareXVal
+ If dblCompareXVal > dblMaxXVal Then dblMaxXVal = dblCompareXVal
+ Next lngIndex
+
+ End If
+ Next intDataSetIndex
+
+ .Scaling.x.ValStart.Val = dblMinXVal
+ .Scaling.x.ValEnd.Val = dblMaxXVal
+
+ ' Stretch the limits of the plot by 5% of the total range
+ dblPlotRangeStretchVal = (.Scaling.x.ValEnd.Val - .Scaling.x.ValStart.Val) * 0.05
+ .Scaling.x.ValEnd.Val = .Scaling.x.ValEnd.Val + dblPlotRangeStretchVal
+ .Scaling.x.ValStart.Val = .Scaling.x.ValStart.Val - dblPlotRangeStretchVal
+
+ End With
+
+ ' Update the plot
+ UpdatePlot
+
+ ' Reset .AutoScaleY and turn off .ZoomOutFull
+ PlotOptions.AutoScaleY = boolAutoScaleSaved
+ PlotOptions.ZoomOutFull = False
+ Else
+ ' Zoom to previous range
+ PlotOptions.Scaling = PlotRangeHistory(2, 0)
+
+ UpdatePlot False
+
+ ' Update the plot range history
+ For intHistoryIndex = 2 To PLOT_RANGE_HISTORY_COUNT - 1
+ For intDataSetIndex = 0 To intDataSetLoadedCount - 1
+ PlotRangeHistory(intHistoryIndex, intDataSetIndex) = PlotRangeHistory(intHistoryIndex + 1, intDataSetIndex)
+ Next intDataSetIndex
+ Next intHistoryIndex
+
+ End If
+
+End Sub
+
+Private Sub ZoomShrink(boolFixHorizontal As Boolean, boolFixVertical As Boolean)
+ ' Zoom out, but not completely
+
+ Dim lngViewRangePosX As Long, lngViewRangePosY As Long
+ Dim lngBoxSizeX As Double, lngBoxSizeY As Double
+ Dim lngPosCorrectionFactorX As Long, lngPosCorrectionFactorY As Long
+ Dim TheseCoords As usrRect
+
+ With PlotRangeHistory(1, 0)
+ lngViewRangePosX = .x.ValEnd.Pos - .x.ValStart.Pos
+ lngViewRangePosY = .y.ValEnd.Pos - .y.ValStart.Pos
+ End With
+
+ If lngViewRangePosX = 0 Or lngViewRangePosY = 0 Then Exit Sub
+
+ TheseCoords = ZoomBoxCoords
+ FixUpCoordinates TheseCoords
+ With TheseCoords
+ lngBoxSizeX = Abs(.x2 - .x1)
+ lngBoxSizeY = Abs(.y2 - .y1)
+ If boolFixVertical Then
+ .x1 = PlotRangeHistory(1, 0).x.ValStart.Pos
+ .x2 = PlotRangeHistory(1, 0).x.ValEnd.Pos
+ Else
+ If lngBoxSizeX > 0 Then
+ lngPosCorrectionFactorX = (CLng(lngViewRangePosX * CDbl(lngViewRangePosX) / CDbl(lngBoxSizeX))) / 2
+ .x1 = .x1 - lngPosCorrectionFactorX
+ .x2 = .x2 + lngPosCorrectionFactorX
+ End If
+ End If
+ If boolFixHorizontal Then
+ .y1 = PlotRangeHistory(1, 0).y.ValEnd.Pos
+ .y2 = PlotRangeHistory(1, 0).y.ValStart.Pos
+ Else
+ If lngBoxSizeY > 0 Then
+ lngPosCorrectionFactorY = (CLng(lngViewRangePosY * CDbl(lngViewRangePosY) / CDbl(lngBoxSizeY))) / 2
+ .y1 = .y1 - lngPosCorrectionFactorY
+ .y2 = .y2 + lngPosCorrectionFactorY
+ End If
+ End If
+ End With
+
+ If lngBoxSizeX > 0 And lngBoxSizeY > 0 Then
+ ZoomBoxCoords = TheseCoords
+ HideZoomBox vbLeftButton, True
+ Else
+ HideZoomBox vbLeftButton, False
+ End If
+
+End Sub
+
+Private Function IsClickInBox(x As Single, y As Single, TheseZoomBoxCoords As usrRect) As Boolean
+ Dim FixedCoords As usrRect
+
+ ' Determine if click was inside or outside of zoom box
+ FixedCoords = FixUpCoordinates(TheseZoomBoxCoords)
+
+ With FixedCoords
+ If x >= .x1 And x <= .x2 And _
+ y >= .y2 And y <= .y1 Then
+ IsClickInBox = True
+ Else
+ IsClickInBox = False
+ End If
+ End With
+
+End Function
+
+Private Function IsZoomBoxLargeEnough(TheseCoords As usrRect) As Boolean
+
+ With TheseCoords
+ ' Don't zoom if box size is less than 150 by 150 twips
+ If Abs(.x2 - .x1) >= 150 And Abs(.y2 - .y1) >= 150 Then
+ IsZoomBoxLargeEnough = True
+ Else
+ IsZoomBoxLargeEnough = False
+ End If
+ End With
+
+End Function
+
+Private Sub PerformMove()
+
+ Dim TheseCoords As usrRect
+ Dim intDataSetIndex As Integer
+ Dim dblCompareVal As Double, dblMinDefinedXVal As Double, dblMaxDefinedXVal As Double
+ Dim DeltaXVal As Double, DeltaYVal As Double
+ Dim dblMinAllowableXVal As Double, dblMaxAllowableXVal As Double, MaximumRange As Double
+
+ TheseCoords = ZoomBoxCoords
+
+ With PlotRangeAtMoveStart
+ DeltaXVal = XYPosToValue(TheseCoords.x2, .x) - XYPosToValue(TheseCoords.x1, .x)
+ DeltaYVal = XYPosToValue(TheseCoords.y2, .y) - XYPosToValue(TheseCoords.y1, .y)
+ End With
+
+ PlotOptions.ZoomOutFull = False
+ With PlotOptions
+ ' First determine minimum and maximum defined x values for all loaded data sets
+ dblMinDefinedXVal = .DataLimits(0).x.ValStart.Val
+ dblMaxDefinedXVal = .DataLimits(0).x.ValEnd.Val
+ For intDataSetIndex = 1 To intDataSetLoadedCount - 1
+ dblCompareVal = .DataLimits(intDataSetIndex).x.ValStart.Val
+ If dblCompareVal < dblMinDefinedXVal Then dblMinDefinedXVal = dblCompareVal
+
+ dblCompareVal = .DataLimits(intDataSetIndex).x.ValEnd.Val
+ If dblCompareVal > dblMaxDefinedXVal Then dblMaxDefinedXVal = dblCompareVal
+ Next intDataSetIndex
+
+ MaximumRange = dblMaxDefinedXVal - dblMinDefinedXVal
+ .Scaling.x.ValStart.Val = PlotRangeAtMoveStart.x.ValStart.Val - DeltaXVal
+ dblMinAllowableXVal = dblMinDefinedXVal - MaximumRange / 10
+ If .Scaling.x.ValStart.Val < dblMinAllowableXVal Then
+ .Scaling.x.ValStart.Val = dblMinAllowableXVal
+ .Scaling.x.ValEnd.Val = .Scaling.x.ValStart.Val + (PlotRangeAtMoveStart.x.ValEnd.Val - PlotRangeAtMoveStart.x.ValStart.Val)
+ Else
+ .Scaling.x.ValEnd.Val = PlotRangeAtMoveStart.x.ValEnd.Val - DeltaXVal
+ End If
+
+ dblMaxAllowableXVal = dblMaxDefinedXVal + MaximumRange / 10
+ If .Scaling.x.ValEnd.Val > dblMaxAllowableXVal Then
+ .Scaling.x.ValEnd.Val = dblMaxAllowableXVal
+ .Scaling.x.ValStart.Val = .Scaling.x.ValEnd.Val - (PlotRangeAtMoveStart.x.ValEnd.Val - PlotRangeAtMoveStart.x.ValStart.Val)
+ End If
+ .Scaling.y.ValStart.Val = PlotRangeAtMoveStart.y.ValStart.Val - DeltaYVal
+ .Scaling.y.ValEnd.Val = PlotRangeAtMoveStart.y.ValEnd.Val - DeltaYVal
+
+ End With
+
+ ' By setting TickCountToUpdateAt to a nonzero value (>= TicksElapsedSinceStart), the
+ ' move will be performed when TicksElapsedSinceStart reaches TickCountToUpdateAt
+ TickCountToUpdateAt = TicksElapsedSinceStart
+End Sub
+
+Private Sub PerformZoom()
+ Dim TheseCoords As usrRect
+ Dim PlotRangeSaved As usrPlotRange
+
+ ' Use the numbers stored in PlotRangeSaved to update the PlotOptions with the desired zoom range
+ PlotRangeSaved = PlotRangeHistory(1, 0) ' The most recent plot range
+
+ TheseCoords = FixUpCoordinates(ZoomBoxCoords)
+
+ If IsZoomBoxLargeEnough(TheseCoords) Then
+ PlotOptions.ZoomOutFull = False
+ With PlotOptions.Scaling
+ .x.ValStart.Val = XYPosToValue(TheseCoords.x1, PlotRangeSaved.x)
+ .x.ValEnd.Val = XYPosToValue(TheseCoords.x2, PlotRangeSaved.x)
+ .y.ValStart.Val = XYPosToValue(TheseCoords.y1, PlotRangeSaved.y)
+ .y.ValEnd.Val = XYPosToValue(TheseCoords.y2, PlotRangeSaved.y)
+ End With
+
+ UpdatePlot
+
+ End If
+
+End Sub
+
+Private Sub PositionControls()
+ Dim PlotHeight As Long
+ Dim lngSuggestedPos As Long, lngMinimumPos As Long
+
+ With fraLegend
+ .Top = 0
+ .Left = 720
+ .Width = 4700
+ .Height = 225
+ .BorderStyle = 0
+ End With
+
+ lblCurrentPos.Top = 0
+
+ lngSuggestedPos = Me.Width - lblCurrentPos.Width - 50
+ If fraLegend.Visible Then
+ lngMinimumPos = fraLegend.Left + fraLegend.Width + 50
+ Else
+ lngMinimumPos = 120
+ End If
+ If lngSuggestedPos < lngMinimumPos Then
+ lngSuggestedPos = lngMinimumPos
+ End If
+
+ lblCurrentPos.Left = lngSuggestedPos
+
+ With fraPlot
+ .Left = 50
+ .Width = Me.Width - 300
+
+ PlotHeight = Me.Height - 700
+ lngSuggestedPos = 0
+ If fraLegend.Visible Or lblCurrentPos.Visible Then
+ lngSuggestedPos = lngSuggestedPos + fraLegend.Height
+ PlotHeight = PlotHeight - fraLegend.Height + 45
+ Else
+ lngSuggestedPos = 50
+ End If
+ .Top = lngSuggestedPos
+
+ If PlotHeight < 1 Then PlotHeight = 1
+ .Height = PlotHeight
+
+''' dynMSPlot.Left = .Left
+''' dynMSPlot.top = .top
+''' dynMSPlot.Width = .Width
+''' dynMSPlot.Height = .Height
+
+ End With
+
+
+End Sub
+
+Private Sub RedrawZoomBox()
+ Dim TheseCoords As usrRect
+
+ TheseCoords = ZoomBoxCoords
+
+ With TheseCoords
+ If .x1 > .x2 Then
+ SwapValues .x1, .x2
+ End If
+ If .y1 > .y2 Then
+ SwapValues .y1, .y2
+ End If
+
+ End With
+
+ ' When the box size gets large enough, turn on blnDrawingZoomBox
+ If IsZoomBoxLargeEnough(TheseCoords) Then
+ blnDrawingZoomBox = True
+ End If
+
+ With shpZoomBox
+ .Left = TheseCoords.x1
+ .Top = TheseCoords.y1
+ .Width = TheseCoords.x2 - TheseCoords.x1
+ .Height = TheseCoords.y2 - TheseCoords.y1
+ End With
+
+End Sub
+
+Public Sub RefreshPlot(Optional blnZoomOutCompletely As Boolean = True)
+ If blnZoomOutCompletely Then
+ ZoomOut blnZoomOutCompletely
+ Else
+ UpdatePlot False
+ End If
+End Sub
+
+Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
+ If KeyCode = 32 Then
+ SetCursorMode True
+ SetCursorIcon
+ ElseIf KeyCode = vbKeyEscape Then
+ mnuClose_Click
+ ElseIf KeyCode = 90 And (Shift And vbCtrlMask) Then
+ ' Ctrl+Z
+ ZoomOut False
+ End If
+
+End Sub
+Private Sub Form_KeyUp(KeyCode As Integer, Shift As Integer)
+ If KeyCode = 32 Then
+ SetCursorMode False
+ SetCursorIcon
+ End If
+End Sub
+
+Private Sub Form_Load()
+ SizeAndCenterWindow Me, cWindowBottomRight, 8000, 7000, True
+
+ tmrUpdatePlot.Interval = 100
+
+ InitializePlotOptions
+
+ shpZoomBox.Visible = False
+
+ EnableDisableMenuCheckmarks
+ EnableDisableZoomMenus False
+
+End Sub
+
+Private Sub Form_MouseMove(Button As Integer, Shift As Integer, x As Single, y As Single)
+ ResetMousePointer Button
+End Sub
+
+Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
+ If UnloadMode = vbFormControlMenu Then
+ Cancel = True
+ HidePlotForm
+ End If
+End Sub
+
+Private Sub Form_Resize()
+ PositionControls
+ If Me.WindowState <> vbMinimized Then
+ TickCountToUpdateAt = TicksElapsedSinceStart + 1
+ blnResizingWindow = True
+ End If
+End Sub
+
+Public Function GetPlotType() As Integer
+ GetPlotType = PlotOptions.PlotTypeCode
+End Function
+
+Public Function GetResolution() As Long
+ GetResolution = PlotOptions.GaussianConversion.ResolvingPower
+End Function
+
+Public Function GetResolutionXVal() As Double
+ GetResolutionXVal = PlotOptions.GaussianConversion.XValueOfSpecification
+End Function
+
+Public Function GetGridlinesStatus(blnXAxis As Boolean) As Boolean
+ If blnXAxis Then
+ GetGridlinesStatus = PlotOptions.XAxis.ShowGridLinesMajor
+ Else
+ GetGridlinesStatus = PlotOptions.YAxis.ShowGridLinesMajor
+ End If
+End Function
+
+Public Function GetAxisTickCount(blnXAxis As Boolean) As Integer
+ If blnXAxis Then
+ GetAxisTickCount = PlotOptions.XAxis.MajorTicksToShow
+ Else
+ GetAxisTickCount = PlotOptions.YAxis.MajorTicksToShow
+ End If
+End Function
+
+Public Function GetGaussianQualityFactor() As Integer
+ GetGaussianQualityFactor = PlotOptions.GaussianConversion.QualityFactor
+End Function
+
+Public Function GetPlotApproximationFactor() As Integer
+ GetPlotApproximationFactor = PlotOptions.ApproximationFactor
+End Function
+Public Function GetAutoscaleYStatus() As Boolean
+ GetAutoscaleYStatus = PlotOptions.AutoScaleY
+End Function
+
+Public Function GetPositionDisplayStatus() As Boolean
+ GetPositionDisplayStatus = blnUpdatePosition
+End Function
+
+Private Sub fraPlot_MouseDown(Button As Integer, Shift As Integer, x As Single, y As Single)
+
+ Dim boolClickInsideBox As Boolean
+ boolClickInsideBox = IsClickInBox(x, y, ZoomBoxCoords)
+
+ If Not shpZoomBox.Visible Or Not boolClickInsideBox Then
+ InitializeZoomOrMove Button, x, y
+ Else
+ ' The Zoom Box is visible
+ ' The click is also handled in Sub fraPlot_MouseUp since it is more customary to handle clicks with _MouseUp events
+ If blnZoomBoxDrawn = True Then
+ RespondZoomModeClick Button, x, y
+ End If
+ End If
+End Sub
+
+Private Sub fraPlot_MouseMove(Button As Integer, Shift As Integer, x As Single, y As Single)
+ If Button = 0 Then
+ SetCursorIcon x, y
+ End If
+
+ ResizeZoomBox Button, x, y
+
+ blnUpdatePosition = True
+ CurrentPosX = x
+ CurrentPosY = y
+
+End Sub
+
+Private Sub fraPlot_MouseUp(Button As Integer, Shift As Integer, x As Single, y As Single)
+ Dim intHistoryIndex As Integer, intDataSetIndex As Integer
+
+ If mnuCursorModeZoom.Checked Then
+ ' Zooming, the box is shown at the size the user chose
+ ' Handle the click differently depending on the location and the button
+
+ If blnZoomBoxDrawn = True Then
+ ' Do nothing
+ ElseIf blnDrawingZoomBox Then
+ blnZoomBoxDrawn = True
+ EnableDisableZoomMenus IsZoomBoxLargeEnough(ZoomBoxCoords)
+ End If
+ Else
+ ' Moving plot
+ ' Turn off blnSlidingGraph
+ blnSlidingGraph = False
+
+ ' Set TickCountToUpdateAt back to 0 so no more udpates occur
+ TickCountToUpdateAt = 0
+
+ ' Update the plot one more time so new view gets saved to history
+ UpdatePlot True
+
+ ' For some reason the history still has two copies of the most recent view
+ ' Remove one of them
+ For intHistoryIndex = 2 To PLOT_RANGE_HISTORY_COUNT - 1
+ For intDataSetIndex = 1 To intDataSetLoadedCount - 1
+ PlotRangeHistory(intHistoryIndex, intDataSetIndex) = PlotRangeHistory(intHistoryIndex + 1, intDataSetIndex)
+ Next intDataSetIndex
+ Next intHistoryIndex
+ End If
+
+End Sub
+
+Private Sub mnuApproximationFactor_Click()
+ SetPlotApproximationFactor
+End Sub
+
+Private Sub mnuAutoScaleYAxis_Click()
+ SetAutoscaleY Not mnuAutoScaleYAxis.Checked
+End Sub
+
+Private Sub mnuClose_Click()
+ HidePlotForm
+End Sub
+
+Private Sub mnuCursorModeMove_Click()
+ SetCursorMode True
+End Sub
+
+Private Sub mnuCursorModeZoom_Click()
+ SetCursorMode False
+End Sub
+
+Private Sub mnuExportData_Click()
+ ExportData
+End Sub
+
+Private Sub mnuFile_Click()
+ ' EnableDisable mnuExportData
+
+ EnableDisableExportDataMenu
+End Sub
+
+Private Sub mnuFixMinimumYAtZero_Click()
+ SetFixMinimumYAtZero Not mnuFixMinimumYAtZero.Checked
+End Sub
+
+Private Sub mnuGaussianQuality_Click()
+ SetGaussianQuality
+End Sub
+
+Private Sub mnuGridLinesXAxis_Click()
+ SetGridlinesXAxis Not mnuGridLinesXAxis.Checked
+End Sub
+
+Private Sub mnuGridLinesYAxis_Click()
+ SetGridlinesYAxis Not mnuGridLinesYAxis.Checked
+End Sub
+
+Private Sub mnuOptions_Click()
+ EnableDisableMenuCheckmarks
+End Sub
+
+Private Sub mnuPlotTypeGaussianPeaks_Click()
+ SetPlotType True
+End Sub
+
+Private Sub mnuPlotTypeSticksToZero_Click()
+ SetPlotType False
+End Sub
+
+Private Sub mnuResetToDefaults_Click()
+ Dim eResponse As VbMsgBoxResult
+
+ eResponse = MsgBox(LookupMessage(1140), vbYesNoCancel + vbDefaultButton2 + vbQuestion, LookupMessage(1145))
+
+ If eResponse = vbYes Then
+ InitializePlotOptions
+ SetPlotType CBool(PlotOptions.PlotTypeCode), False
+ ZoomOut True
+ End If
+End Sub
+
+Private Sub mnuSetRangeX_Click()
+ SetNewRange True, False
+End Sub
+
+Private Sub mnuSetRangeY_Click()
+ SetNewRange False, True
+End Sub
+
+Private Sub mnuSetResolution_Click()
+ SetResolution
+End Sub
+
+Private Sub mnuShowCurrentPosition_Click()
+ SetShowCursorPosition Not mnuShowCurrentPosition.Checked
+End Sub
+
+Private Sub mnuShowLegend_Click()
+ SetLegendVisibility Not mnuShowLegend.Checked
+End Sub
+
+'''Private Sub mnuShowDynaPlot_Click()
+''' mnuShowDynaPlot.Checked = Not mnuShowDynaPlot.Checked
+'''
+''' fraPlot.Visible = Not mnuShowDynaPlot.Checked
+''' dynMSPlot.Visible = mnuShowDynaPlot.Checked
+'''End Sub
+'''
+'''Private Sub dynMSPlot_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
+''' If Button <> vbLeftButton Then
+''' ' Zoom out to previous zoom
+''' 'dynMSPlot.Scale.ZoomOut
+''' dynMSPlot.Action.CallActionFunction acZOOMOUT
+''' End If
+'''End Sub
+'''
+'''Private Sub dynMSPlot_Zoomed(ByVal XLeft As Double, ByVal XRight As Double, ByVal YBottom As Double, ByVal YTop As Double)
+'''
+''' With dynMSPlot.Scale
+''' .XLeft = XLeft
+''' .XRight = XRight
+''' .YBottom = 0
+''' .YTop = 100
+''' End With
+'''
+'''End Sub
+
+Private Sub mnuTicksXAxis_Click()
+ AxisTickCountUpdateByUser True, PlotOptions.XAxis.MajorTicksToShow
+End Sub
+
+Private Sub mnuTicksYAxis_Click()
+ AxisTickCountUpdateByUser False, PlotOptions.YAxis.MajorTicksToShow
+End Sub
+
+Private Sub mnuZoomIn_Click()
+ HideZoomBox vbLeftButton, True
+End Sub
+
+Private Sub mnuZoomInHorizontal_Click()
+ ZoomInHorizontal
+End Sub
+
+Private Sub mnuZoomInVertical_Click()
+ ZoomInVertical
+End Sub
+
+Private Sub mnuZoomOut_Click()
+ ZoomShrink False, False
+End Sub
+
+Private Sub mnuZoomOutFullScale_Click()
+ ZoomOut True
+End Sub
+
+Private Sub mnuZoomOutHorizontal_Click()
+ ZoomShrink True, False
+End Sub
+
+Private Sub mnuZoomOutToPrevious_Click()
+ ZoomOut False
+End Sub
+
+Private Sub mnuZoomOutVertical_Click()
+ ZoomShrink False, True
+End Sub
+
+Private Sub tmrUpdatePlot_Timer()
+ ' Note: the internal for the timer is 100 msec
+
+ TicksElapsedSinceStart = TicksElapsedSinceStart + 1
+ If TickCountToUpdateAt > 0 Then
+ UpdatePlotWhenIdle
+ End If
+
+ If blnUpdatePosition Then UpdateCurrentPos
+End Sub
+
diff --git a/msplot.frx b/msplot.frx
new file mode 100644
index 0000000..03ffc39
Binary files /dev/null and b/msplot.frx differ
diff --git a/mwt_abbr.dtt b/mwt_abbr.dtt
new file mode 100644
index 0000000..a3a5662
--- /dev/null
+++ b/mwt_abbr.dtt
@@ -0,0 +1,65 @@
+; Abbreviations File for MWTWIN program (v6.41)
+;
+; Comments may be added by preceding with a semicolon
+; Two group headings must exist: [AMINO ACIDS] and [ABBREVIATIONS]
+; Abbreviations may be added; simply type the abbreviation and molecular
+; formula under the appropriate column in either section
+; Note: Only the first letter of an abbreviation is allowed to be capitalized
+;
+; The abbreviations in the Amino Acid section are treated as extended level
+; abbreviations: they are only recognized when extended abbreviations are on
+; If this file becomes corrupted, the MWTWIN program will inform the user
+; and ignore incorrect lines
+; If this file becomes deleted, the MWTWIN program will create a new file
+; with the default abbreviations
+;
+; Default Amino Acids are in their ionic form
+; Amino Acid abbreviation names may be up to 6 characters long
+[AMINO ACIDS]
+Ala C3H5NO 0 A ; Alanine
+Arg C6H12N4O 0 R ; Arginine, (unprotonated NH2)
+Asn C4H6N2O2 0 N ; Asparagine
+Asp C4H5NO3 0 D ; Aspartic acid (undissociated COOH)
+Cys C3H5NOS 0 C ; Cysteine (no disulfide link)
+Gla C6H7NO5 0 U ; gamma-Carboxyglutamate
+Gln C5H8N2O2 0 Q ; Glutamine
+Glu C5H7NO3 0 E ; Glutamic acid (undissociated COOH)
+Gly C2H3NO 0 G ; Glycine
+His C6H7N3O 0 H ; Histidine (unprotonated NH)
+Hse C4H7NO2 0 ; Homoserine
+Hyl C6H12N2O2 0 ; Hydroxylysine
+Hyp C5H7NO2 0 ; Hydroxyproline
+Ile C6H11NO 0 I ; Isoleucine
+Leu C6H11NO 0 L ; Leucine
+Lys C6H12N2O 0 K ; Lysine (unprotonated NH2)
+Met C5H9NOS 0 M ; Methionine
+Orn C5H10N2O 0 O ; Ornithine
+Phe C9H9NO 0 F ; Phenylalanine
+Pro C5H7NO 0 P ; Proline
+Pyr C5H5NO2 0 ; Pyroglutamic acid
+Sar C3H5NO 0 ; Sarcosine
+Ser C3H5NO2 0 S ; Serine
+Thr C4H7NO2 0 T ; Threonine
+Trp C11H10N2O 0 W ; Tryptophan
+Tyr C9H9NO2 0 Y ; Tyrosine
+Val C5H9NO 0 V ; Valine
+Xxx C6H12N2O 0 X ; Unknown
+
+; Normal abbreviation names may be up to 6 characters long
+[ABBREVIATIONS]
+Bpy C10H8N2 0 ; Bipyridine
+Bu C4H9 1 ; Butyl
+D ^2.014H 1 ; Deuterium
+En C2H8N2 0 ; Ethylenediamine
+Et CH3CH2 1 ; Ethyl
+Me CH3 1 ; Methyl
+Ms CH3SOO -1 ; Mesyl
+Oac C2H3O2 -1 ; Acetate
+Otf OSO2CF3 -1 ; Triflate
+Ox C2O4 -2 ; Oxalate
+Ph C6H5 1 ; Phenyl
+Phen C12H8N2 0 ; Phenanthroline
+Py C5H5N 0 ; Pyridine
+Tpp (C4H2N(C6H5C)C4H2N(C6H5C))2 0 ; Tetraphenylporphyrin, mw 612.733
+Ts CH3C6H4SOO -1 ; Tosyl
+Urea H2NCONH2 0 ; Urea
diff --git a/mwt_elem.dat b/mwt_elem.dat
new file mode 100644
index 0000000..95daad2
--- /dev/null
+++ b/mwt_elem.dat
@@ -0,0 +1,128 @@
+; Elements File for MWTWIN program (v6.42)
+;
+; Comments may be added by preceding with a semicolon
+; The heading [ELEMENTWEIGHTTYPE] 1 signifies that Average Elemental Weights are
+; being used while [ELEMENTWEIGHTTYPE] 2 signifies the use of Isotopic Weights
+; and [ELEMENTWEIGHTTYPE] 3 signifies the use of Integer Weights
+; The group heading [ELEMENTS] must exist to signify the start of the elements
+; Elemental values may be changed, but new elements may not be added
+; If you wish to add new elements, simply add them as abbreviations
+; If this file becomes deleted, the MWTWIN program will create a new file
+; with the default values
+; Uncertainties from CRC Handbook of Chemistry and Physics
+; For Radioactive elements, the most stable isotope is NOT used;
+; instead, an average Mol. Weight is used, just like with other elements.
+; Data obtained from the Perma-Chart Science Series periodic table, 1993.
+; Uncertainties from CRC Handoobk of Chemistry and Physics, except for
+; Radioactive elements, where uncertainty was estimated to be .n5 where
+; n represents the number digits after the decimal point but before the last
+; number of the molecular weight.
+; For example, for No, MW = 259.1009 (±0.0005)
+;
+[ELEMENTWEIGHTTYPE] 2
+; The values signify:
+; Weight Uncertainty Charge
+[ELEMENTS]
+H 1.0078246 0 1
+He 4.0026029 0 0
+Li 7.016005 0 1
+Be 9.012183 0 2
+B 11.009305 0 3
+C 12 0 4
+N 14.003074 0 -3
+O 15.994915 0 -2
+F 18.9984032 0 -1
+Ne 19.992439 0 0
+Na 22.98977 0 1
+Mg 23.98505 0 2
+Al 26.981541 0 3
+Si 27.976928 0 4
+P 30.973763 0 -3
+S 31.972072 0 -2
+Cl 34.968853 0 -1
+Ar 39.962383 0 0
+K 38.963708 0 1
+Ca 39.962591 0 2
+Sc 44.955914 0 3
+Ti 47.947947 0 4
+V 50.943963 0 5
+Cr 51.94051 0 3
+Mn 54.938046 0 2
+Fe 55.934939 0 3
+Co 58.933198 0 2
+Ni 57.935347 0 2
+Cu 62.929599 0 2
+Zn 63.929145 0 2
+Ga 68.925581 0 3
+Ge 71.92208 0 4
+As 74.921596 0 -3
+Se 79.916521 0 -2
+Br 78.918336 0 -1
+Kr 83.911506 0 0
+Rb 84.9118 0 1
+Sr 87.905625 0 2
+Y 88.905856 0 3
+Zr 89.904708 0 4
+Nb 92.906378 0 5
+Mo 97.905405 0 6
+Tc 98 0 7
+Ru 101.90434 0 4
+Rh 102.905503 0 3
+Pd 105.903475 0 2
+Ag 106.905095 0 1
+Cd 113.903361 0 2
+In 114.903875 0 3
+Sn 119.902199 0 4
+Sb 120.903824 0 -3
+Te 129.906229 0 -2
+I 126.904477 0 -1
+Xe 131.904148 0 0
+Cs 132.905433 0 1
+Ba 137.905236 0 2
+La 138.906355 0 3
+Ce 139.905442 0 3
+Pr 140.907657 0 4
+Nd 141.907731 0 3
+Pm 145 0 3
+Sm 151.919741 0 3
+Eu 152.921243 0 3
+Gd 157.924111 0 3
+Tb 158.92535 0 3
+Dy 163.929183 0 3
+Ho 164.930332 0 3
+Er 165.930305 0 3
+Tm 168.934225 0 3
+Yb 173.938873 0 3
+Lu 174.940785 0 3
+Hf 179.946561 0 4
+Ta 180.948014 0 5
+W 183.950953 0 6
+Re 186.955765 0 7
+Os 191.960603 0 4
+Ir 192.962942 0 4
+Pt 194.964785 0 4
+Au 196.96656 0 3
+Hg 201.970632 0 2
+Tl 204.97441 0 1
+Pb 207.976641 0 2
+Bi 208.980388 0 3
+Po 209 0 4
+At 210 0 -1
+Rn 222 0 0
+Fr 223 0 1
+Ra 227 0 2
+Ac 227 0 3
+Th 232.038054 0 4
+Pa 231 0 5
+U 238.050786 0 6
+Np 237 0 5
+Pu 244 0 4
+Am 243 0 3
+Cm 247 0 3
+Bk 247 0 3
+Cf 251 0 3
+Es 252 0 3
+Fm 257 0 3
+Md 258 0 3
+No 269 0 3
+Lr 260 0 3
diff --git a/mwt_elem.dtt b/mwt_elem.dtt
new file mode 100644
index 0000000..39aeae6
--- /dev/null
+++ b/mwt_elem.dtt
@@ -0,0 +1,128 @@
+; Elements File for MWTWIN program (v6.41)
+;
+; Comments may be added by preceding with a semicolon
+; The heading [ELEMENTWEIGHTTYPE] 1 signifies that Average Elemental Weights are
+; being used while [ELEMENTWEIGHTTYPE] 2 signifies the use of Isotopic Weights
+; and [ELEMENTWEIGHTTYPE] 3 signifies the use of Integer Weights
+; The group heading [ELEMENTS] must exist to signify the start of the elements
+; Elemental values may be changed, but new elements may not be added
+; If you wish to add new elements, simply add them as abbreviations
+; If this file becomes deleted, the MWTWIN program will create a new file
+; with the default values
+; Uncertainties from CRC Handbook of Chemistry and Physics
+; For Radioactive elements, the most stable isotope is NOT used;
+; instead, an average Mol. Weight is used, just like with other elements.
+; Data obtained from the Perma-Chart Science Series periodic table, 1993.
+; Uncertainties from CRC Handoobk of Chemistry and Physics, except for
+; Radioactive elements, where uncertainty was estimated to be .n5 where
+; n represents the number digits after the decimal point but before the last
+; number of the molecular weight.
+; For example, for No, MW = 259.1009 (±0.0005)
+;
+[ELEMENTWEIGHTTYPE] 1
+; The values signify:
+; Weight Uncertainty Charge
+[ELEMENTS]
+H 1.00794 0.00007 1
+He 4.002602 0.000002 0
+Li 6.941 0.002 1
+Be 9.012182 0.000003 2
+B 10.811 0.007 3
+C 12.0107 0.0008 4
+N 14.00674 0.00007 -3
+O 15.9994 0.0003 -2
+F 18.9984032 0.0000005 -1
+Ne 20.1797 0.0006 0
+Na 22.98977 0.000002 1
+Mg 24.305 0.0006 2
+Al 26.981538 0.000002 3
+Si 28.0855 0.0003 4
+P 30.973761 0.000002 -3
+S 32.066 0.006 -2
+Cl 35.4527 0.0009 -1
+Ar 39.948 0.001 0
+K 39.0983 0.0001 1
+Ca 40.078 0.004 2
+Sc 44.95591 0.000008 3
+Ti 47.867 0.001 4
+V 50.9415 0.0001 5
+Cr 51.9961 0.0006 3
+Mn 54.938049 0.000009 2
+Fe 55.845 0.002 3
+Co 58.9332 0.000009 2
+Ni 58.6934 0.0002 2
+Cu 63.546 0.003 2
+Zn 65.39 0.02 2
+Ga 69.723 0.001 3
+Ge 72.61 0.02 4
+As 74.9216 0.00002 -3
+Se 78.96 0.03 -2
+Br 79.904 0.001 -1
+Kr 83.8 0.01 0
+Rb 85.4678 0.0003 1
+Sr 87.62 0.01 2
+Y 88.90585 0.00002 3
+Zr 91.224 0.002 4
+Nb 92.90638 0.00002 5
+Mo 95.94 0.01 6
+Tc 97.9072 0.0005 7
+Ru 101.07 0.02 4
+Rh 102.9055 0.00002 3
+Pd 106.42 0.01 2
+Ag 107.8682 0.0002 1
+Cd 112.411 0.008 2
+In 114.818 0.003 3
+Sn 118.71 0.007 4
+Sb 121.76 0.001 -3
+Te 127.6 0.03 -2
+I 126.90447 0.00003 -1
+Xe 131.29 0.02 0
+Cs 132.90545 0.00002 1
+Ba 137.327 0.007 2
+La 138.9055 0.0002 3
+Ce 140.116 0.001 3
+Pr 140.90765 0.00002 4
+Nd 144.24 0.03 3
+Pm 144.9127 0.0005 3
+Sm 150.36 0.03 3
+Eu 151.964 0.001 3
+Gd 157.25 0.03 3
+Tb 158.92534 0.00002 3
+Dy 162.5 0.03 3
+Ho 164.93032 0.00002 3
+Er 167.26 0.03 3
+Tm 168.93421 0.00002 3
+Yb 173.04 0.03 3
+Lu 174.967 0.001 3
+Hf 178.49 0.02 4
+Ta 180.9479 0.0001 5
+W 183.84 0.01 6
+Re 186.207 0.001 7
+Os 190.23 0.03 4
+Ir 192.217 0.03 4
+Pt 195.078 0.002 4
+Au 196.96655 0.00002 3
+Hg 200.59 0.02 2
+Tl 204.3833 0.0002 1
+Pb 207.2 0.1 2
+Bi 208.98038 0.00002 3
+Po 208.9824 0.0005 4
+At 209.9871 0.0005 -1
+Rn 222.0176 0.0005 0
+Fr 223.0197 0.0005 1
+Ra 226.0254 0.0001 2
+Ac 227.0278 0.00001 3
+Th 232.0381 0.0001 4
+Pa 231.03588 0.00002 5
+U 238.0289 0.0001 6
+Np 237.0482 0.0005 5
+Pu 244.0642 0.0005 4
+Am 243.0614 0.0005 3
+Cm 247.0703 0.0005 3
+Bk 247.0703 0.0005 3
+Cf 251.0796 0.0005 3
+Es 252.083 0.005 3
+Fm 257.0951 0.0005 3
+Md 258.1 0.05 3
+No 259.1009 0.0005 3
+Lr 262.11 0.05 3
diff --git a/mwt_valu.ini b/mwt_valu.ini
new file mode 100644
index 0000000..b8c925e
--- /dev/null
+++ b/mwt_valu.ini
@@ -0,0 +1,950 @@
+; Values File for MWTWIN Program (v6.42)
+;
+; File Automatically Created -- Select Save Values and Formulas under the Options Menu
+;
+Formula0=BrCH2(CH2)7CH2Br
+Formula1=FeCl3-6H2O
+Formula2=Co(Bpy)(CO)4
+Formula3=^13C6H6-.1H2O
+Formula4=HGlyLeuTyrOH
+Formula5=BrCH2(CH2)7CH2Br>CH8
+AminoAcidConvertOneLetter=GLY
+AminoAcidConvertThreeLetter=Gly-Leu-Tyr
+AminoAcidConvertSpaceOneLetter=1
+AminoAcidConvertDashThreeLetter=1
+Mole/MassWeightSource=0
+Mole/MassCustomMass=100
+Mole/MassAction=2
+Mole/MassFrom=1
+Mole/MassFromUnits=0
+Mole/MassDensity=1
+Mole/MassToUnits=8
+Mole/MassVolume=100
+Mole/MassVolumeUnits=2
+Mole/MassMolarity=10.0
+Mole/MassMolarityUnits=0
+Mole/MassDilutionMode=0
+Mole/MassMolarityInitial=10
+Mole/MassMolarityInitialUnits=0
+Mole/MassVolumeInitial=3.0
+Mole/MassVolumeInitialUnits=2
+Mole/MassMolarityFinal=2
+Mole/MassMolarityFinalUnits=0
+Mole/MassVolumeSolvent=12.0
+Mole/MassVolumeSolventUnits=2
+Mole/MassVolumeTotal=15
+Mole/MassVolumeTotalUnits=2
+Mole/MassLinkConcentrations=0
+Mole/MassLinkDilutionVolumeUnits=1
+CapillaryFlowFileFormatVersion=2
+CapillaryFlowMode=0
+CapillaryFlowComputationType=3
+CapillaryFlowLinkFlowRate=1
+CapillaryFlowLinkLinearVelocity=1
+CapillaryFlowShowPeakBroadeningSave=0
+CapillaryFlowWeightSource=0
+CapillaryFlowCustomMass=100
+CapillaryFlowOpenText0=50
+CapillaryFlowPackedText0=3000
+CapillaryFlowOpenText1=50
+CapillaryFlowPackedText1=50
+CapillaryFlowOpenText2=30
+CapillaryFlowPackedText2=75
+CapillaryFlowOpenText3=0.0089
+CapillaryFlowPackedText3=0.0089
+CapillaryFlowOpenText4=5
+CapillaryFlowPackedText4=5
+CapillaryFlowOpenText5=100
+CapillaryFlowPackedText5=100
+CapillaryFlowOpenText6=1
+CapillaryFlowPackedText6=1
+CapillaryFlowOpenText7=0.4
+CapillaryFlowPackedText7=0.4
+CapillaryFlowOpenText8=1
+CapillaryFlowPackedText8=1
+CapillaryFlowOpenText9=100
+CapillaryFlowPackedText9=100
+CapillaryFlowOpenText10=30
+CapillaryFlowPackedText10=30
+CapillaryFlowOpenText11=1
+CapillaryFlowPackedText11=1
+CapillaryFlowOpenText12=0.000005
+CapillaryFlowPackedText12=0.000005
+CapillaryFlowOpenText13=5
+CapillaryFlowPackedText13=5
+CapillaryFlowOpenText14=50
+CapillaryFlowPackedText14=50
+CapillaryFlowOpenText15=30
+CapillaryFlowPackedText15=30
+CapillaryFlowOpenText16=0
+CapillaryFlowPackedText16=0
+CapillaryFlowOpenCombo0=0
+CapillaryFlowPackedCombo0=0
+CapillaryFlowOpenCombo1=1
+CapillaryFlowPackedCombo1=1
+CapillaryFlowOpenCombo2=3
+CapillaryFlowPackedCombo2=3
+CapillaryFlowOpenCombo3=0
+CapillaryFlowPackedCombo3=0
+CapillaryFlowOpenCombo4=3
+CapillaryFlowPackedCombo4=3
+CapillaryFlowOpenCombo5=2
+CapillaryFlowPackedCombo5=2
+CapillaryFlowOpenCombo6=4
+CapillaryFlowPackedCombo6=4
+CapillaryFlowOpenCombo7=2
+CapillaryFlowPackedCombo7=2
+CapillaryFlowOpenCombo8=2
+CapillaryFlowPackedCombo8=2
+CapillaryFlowOpenCombo9=2
+CapillaryFlowPackedCombo9=2
+CapillaryFlowOpenCombo10=2
+CapillaryFlowPackedCombo10=2
+CapillaryFlowOpenCombo11=2
+CapillaryFlowPackedCombo11=2
+CapillaryFlowOpenCombo12=4
+CapillaryFlowPackedCombo12=4
+CapillaryFlowOpenCombo13=5
+CapillaryFlowPackedCombo13=5
+CapillaryFlowOpenCombo14=4
+CapillaryFlowPackedCombo14=4
+CapillaryFlowOpenCombo15=1
+CapillaryFlowPackedCombo15=1
+CapillaryFlowOpenCombo16=3
+CapillaryFlowPackedCombo16=3
+CapillaryFlowOpenCombo17=2
+CapillaryFlowPackedCombo17=2
+CapillaryFlowOpenCombo18=2
+CapillaryFlowPackedCombo18=2
+ViscosityMeCNPercentAcetontrile=20
+ViscosityMeCNTemperature=25
+ViscosityMeCNTemperatureUnits=0
+Calculator=6^3-8.5*3
+IonPlotColor=16711680
+IonPlotShowPlot=1
+IonPlotType=1
+IonPlotResolution=5000
+IonPlotResolutionMass=1000
+IonPlotGaussianQuality=50
+IonComparisonPlotColor=255
+IonComparisonPlotType=0
+IonComparisonPlotNormalize=1
+FinderAction=0
+FinderMWT=200
+FinderPercentMaxWeight=400
+FinderPPM=0
+FinderShowDeltaMass=1
+FinderWtTolerance=0.05
+FinderPercentTolerance=1
+FinderMaxHits=100
+FinderSortResults=1
+FinderSmartH=1
+FinderFindCharge=0
+FinderFindMtoZ=0
+FinderLimitChargeRange=0
+FinderChargeRangeMin=-4
+FinderChargeRangeMax=4
+FinderFindTargetMtoZ=0
+FinderHighlightText=0
+FinderAutoBoundsSet=1
+FinderSortMode=0
+FinderMin0=0
+FinderMax0=10
+FinderCheckElements0=1
+FinderPercentValue0=Percent
+FinderMin1=0
+FinderMax1=10
+FinderCheckElements1=1
+FinderPercentValue1=Percent
+FinderMin2=0
+FinderMax2=10
+FinderCheckElements2=1
+FinderPercentValue2=Percent
+FinderMin3=0
+FinderMax3=10
+FinderCheckElements3=1
+FinderPercentValue3=Percent
+FinderMin4=0
+FinderMax4=10
+FinderCheckElements4=0
+FinderPercentValue4=Percent
+FinderCustomWeight1=# or Element or Abbrev.
+FinderMin5=0
+FinderMax5=10
+FinderCheckElements5=0
+FinderPercentValue5=Percent
+FinderCustomWeight2=# or Element or Abbrev.
+FinderMin6=0
+FinderMax6=10
+FinderCheckElements6=0
+FinderPercentValue6=Percent
+FinderCustomWeight3=# or Element or Abbrev.
+FinderMin7=0
+FinderMax7=10
+FinderCheckElements7=0
+FinderPercentValue7=Percent
+FinderCustomWeight4=# or Element or Abbrev.
+FinderMin8=0
+FinderMax8=10
+FinderCheckElements8=0
+FinderPercentValue8=Percent
+FinderCustomWeight5=# or Element or Abbrev.
+FinderMin9=0
+FinderMax9=10
+FinderCheckElements9=0
+FinderPercentValue9=Percent
+FinderCustomWeight6=# or Element or Abbrev.
+FragModelModificationSymbolsCount=10
+FragModelModificationSymbol1=*,79.9663326,True,Phosphorylation [HPO3]
+FragModelModificationSymbol2=+,14.01565,False,Methylation [CH2]
+FragModelModificationSymbol3=@,15.99492,False,Oxidation [O]
+FragModelModificationSymbol4=!,57.02146,False,Carbamidomethylation [C2H3NO]
+FragModelModificationSymbol5=&,58.00548,False,Carboxymethylation [CH2CO2]
+FragModelModificationSymbol6=#,71.03711,False,Acrylamide [CHCH2CONH2]
+FragModelModificationSymbol7=$,227.127,False,Cleavable ICAT [(^12C10)H17N3O3]
+FragModelModificationSymbol8=%,236.127,False,Cleavable ICAT [(^13C9)(^12C)H17N3O3]
+FragModelModificationSymbol9=~,442.225,False,ICAT D0 [C20H34N4O5S]
+FragModelModificationSymbol10=`,450.274,False,ICAT D8 [C20H26D8N4O5S]
+FragModelNotationMode=1
+FragModelSequence=Arg-His-Pro-Glu-Tyr-Ala-Val
+FragModelNTerminus=0
+FragModelCTerminus=0
+FragModelIonType0=0
+FragModelIonType1=1
+FragModelIonType2=1
+FragModelIonsToModify0=0
+FragModelIonsToModify1=1
+FragModelIonsToModify2=1
+FragModelWaterLoss=1
+FragModelAmmoniaLoss=0
+FragModelPhosphateLoss=0
+FragModelDoubleCharge=0
+FragModelDoubleChargeThreshold=8
+FragModelPrecursorIonRemove=1
+FragModelPrecursorIonMass=300
+FragModelPrecursorIonMassWindow=2
+FragModelIonMatchWindow=0.5
+FragModelIonIntensity0=10
+FragModelIonIntensity1=50
+FragModelIonIntensity2=50
+FragModelShoulderIntensity=25
+FragModelNeutralLossIntensity=10
+FragModelGroupIons=0
+FragModelGroupIonsMassWindow=.5
+FragModelNormalizedIntensity=100
+FragModelNormalizationIonsUseCount=200
+FragModelNormalizationMassRegions=1
+FragModelLabelMainIons=1
+FragModelLabelOtherIons=0
+FragModelEmphasizeProlineYIons=0
+FragModelPlotPredictedSpectrumInverted=1
+FragModelAutoLabelMass=0
+FragModelFragSpectrumColor=16711680
+FragModelMatchingIonDataColor=32768
+FragModelIonMatchList=637
+379.461,6
+380.339,1.2
+384.326,2.9
+389.005,7.8
+411.377,3.1
+414.084,2.7
+437.125,6.5
+460.34,6.9
+462.034,2.8
+472.466,23.4
+478.512,8.3
+481.635,3.9
+500.2,7.9
+507.284,2.7
+508.232,10.1
+521.179,1.4
+530.629,2.2
+534.312,18.4
+539.964,3.8
+541.164,4.2
+543.388,7.2
+545.858,2.3
+549.199,9.7
+554.196,6.8
+561.151,3.8
+562.317,2.5
+565.096,7.1
+566.305,8.1
+567.031,9.4
+568.379,1.7
+570.055,4.6
+571.17,11.1
+576.61,13.8
+582.438,9
+586.32,19.5
+590.33,5.8
+601.675,2.7
+603.215,12.5
+611.299,2.7
+613.391,7.7
+615.37,2.7
+617.419,13.3
+618.294,4.8
+620.439,8.9
+622.059,3.5
+627.106,2
+650.276,3.1
+657.377,3.5
+661.3,12
+680.892,7.5
+682.203,5.8
+683.548,13.1
+685.302,6.7
+697.146,8.1
+697.948,3.2
+706.225,19.4
+707.906,11.1
+711.2,14.5
+727.823,4.8
+732.249,3.5
+734.557,11.1
+737.084,10.3
+746.159,2.7
+748.313,30.4
+757.809,4.8
+760.14,6.1
+761.4,22.1
+769.285,19.6
+770.036,7.4
+771.12,18
+774.113,20.2
+776.248,15.6
+781.326,10.4
+782.236,16.6
+784.55,21.3
+785.355,7.2
+791.449,16.8
+795.524,10.3
+797.897,23.3
+802.239,4.2
+806.178,9
+807.325,5.9
+808.151,28
+810.506,17.6
+812.404,9.9
+814.347,14.9
+823.687,9.1
+827.2,18.4
+828.495,30.1
+830.456,7.4
+843.74,6.8
+845.378,25.6
+846.124,8.3
+850.279,3.2
+857.077,3.8
+860.066,9.2
+861.488,6.5
+862.229,10.5
+863.078,4.4
+863.694,17.1
+864.537,3.4
+865.37,29
+866.245,2.9
+866.961,5
+867.685,18
+869.123,9.5
+871.775,23.1
+873.595,33
+875.707,15.5
+877.188,8.6
+878.644,40.1
+879.973,24.3
+884.381,12.1
+886.129,4.1
+889.206,23.3
+892.502,5.8
+898.276,6
+898.927,16.5
+900.03,14.9
+909.412,27
+910.736,14.3
+912.761,5.4
+918.955,7.1
+921.403,9.3
+926.314,4.4
+927.264,44.7
+931.4,14
+935.755,38.2
+936.443,115.8
+937.157,28.8
+938.027,22.2
+941.158,10.1
+943.544,11
+944.188,7.1
+948.636,10.5
+949.992,24.9
+953.302,21.2
+954.427,4.4
+955.785,18.5
+956.486,19.9
+957.483,3.3
+958.353,1.8
+960.501,27.3
+963.173,9.4
+964.142,22.2
+965.36,6.2
+968.71,2.3
+972.337,18.3
+977.187,7.9
+977.883,31.1
+979.576,2.3
+981.127,16.5
+982.614,28.6
+985.816,5.4
+987.76,2.7
+988.615,33.4
+989.659,1.4
+991.94,7.3
+997.515,9.1
+998.981,4.4
+1006.169,29.1
+1010.57,37
+1011.619,8.7
+1012.56,16.6
+1013.532,2.3
+1014.498,14.6
+1015.608,15.3
+1019.642,10
+1021.028,41.7
+1022.413,9.2
+1023.351,5.5
+1027.299,33.5
+1028.18,30.7
+1029.408,38.6
+1030.477,7.8
+1036.909,37.6
+1039.308,8.1
+1040.937,11.2
+1044.367,12.5
+1045.892,39.2
+1050.997,37.2
+1051.764,12.1
+1052.551,6.8
+1054.741,35.6
+1063.992,5.6
+1066.194,78.2
+1067.027,17.5
+1067.858,8.2
+1073.451,14.9
+1079.227,25.6
+1079.99,8.4
+1082.4,16.5
+1084.332,2
+1086.278,22.7
+1089.943,5.9
+1093.599,9.8
+1095.441,18.3
+1098.684,19.2
+1100.082,36.8
+1101.255,39.7
+1102.073,36.5
+1104.673,21.7
+1105.894,39.8
+1107.651,81.8
+1108.383,5.1
+1110.158,34.4
+1112.243,8.9
+1113.991,31.6
+1114.941,21.8
+1117.156,37.9
+1118.251,13.7
+1119.673,13.6
+1121.348,7.2
+1123.233,10.2
+1127.54,43.5
+1128.585,21.7
+1129.482,19.5
+1130.406,51.5
+1131.208,4.5
+1132.497,5.8
+1133.583,6.7
+1134.654,30.1
+1137.003,28.5
+1137.673,13.1
+1138.498,47.4
+1139.625,6.8
+1140.367,23.8
+1141.502,22.6
+1142.81,40.5
+1144.252,51.2
+1145.315,4.5
+1147.506,29.2
+1148.341,32.5
+1151.129,126.4
+1152.22,60.4
+1152.823,14.7
+1154.932,31
+1162.154,49
+1164.805,76.8
+1166.633,47.6
+1167.393,26.2
+1171.333,25
+1172.483,37.4
+1175.112,2.9
+1176.211,11.2
+1178.166,19
+1184.656,69.2
+1187.041,11.2
+1188.91,4.9
+1189.981,16.8
+1191.568,56.8
+1192.313,39.5
+1194.053,97.9
+1198.711,14.1
+1200.49,46.3
+1201.23,87.7
+1203.361,35.4
+1204.856,31.6
+1205.686,15.6
+1208.25,162.5
+1209.074,105.6
+1210.19,27.5
+1211.234,95.1
+1212.46,20.1
+1213.107,6.3
+1214.067,17.5
+1215.322,31.3
+1216.301,61.7
+1217.571,2.3
+1219.321,22
+1220.489,66.3
+1221.754,27
+1224.069,89.6
+1225.273,30.7
+1227.152,52.9
+1228.536,91.2
+1229.343,42.7
+1231.135,98.6
+1232.771,60.1
+1233.689,24.2
+1234.882,31.4
+1235.614,8.8
+1237.141,127.1
+1237.827,4.4
+1238.749,13
+1240.373,34.6
+1241.888,103.3
+1242.591,16.9
+1243.577,44.3
+1245.452,9.8
+1246.217,46.5
+1247.278,78
+1247.923,116.4
+1248.606,32.7
+1251.051,89.4
+1252.053,70.9
+1253.464,33.1
+1254.479,6.9
+1255.237,59.6
+1257.995,26.8
+1258.606,11.3
+1259.428,35.9
+1260.38,8.7
+1261.228,12.7
+1261.916,28.4
+1263.386,139.8
+1264.383,107.9
+1265.479,59.8
+1266.553,34
+1268.225,19.6
+1293.355,43.3
+1295.413,7.2
+1296.031,4
+1296.665,6.3
+1301.846,13.4
+1307.085,3.1
+1308.874,1.7
+1313.282,9.5
+1315.804,172
+1316.719,6.9
+1319.764,79.3
+1321.402,7.2
+1322.577,22.7
+1324.4,65.6
+1327.032,22.2
+1330.641,37
+1334.25,7
+1338.436,102.5
+1339.314,55.7
+1340.176,29.1
+1343.637,88.2
+1345.073,44.8
+1346.231,211.3
+1348.111,36.6
+1348.961,36.9
+1350.008,17.9
+1351.19,103.6
+1352.408,35.3
+1353.43,14.2
+1354.406,27.6
+1357.8,114
+1360.742,9.2
+1361.683,65.7
+1364.713,56.9
+1366.008,138
+1366.94,148.6
+1368.956,3.8
+1369.623,49.2
+1371.214,44.1
+1371.996,9.7
+1373.184,32.9
+1374.701,51.1
+1375.658,19.1
+1376.811,78.7
+1377.861,58.7
+1379.2,23
+1380.332,9
+1381.758,54.9
+1382.655,9.4
+1385.597,3.5
+1388.394,34
+1389.752,23.4
+1394.69,57.8
+1396.199,87.4
+1398.121,24.5
+1399.263,50.7
+1399.986,39.5
+1400.976,22.2
+1401.658,19.8
+1404.554,4.7
+1406.023,149.8
+1407.653,102.3
+1408.662,122.2
+1410.262,9.1
+1412.521,55.2
+1413.722,28
+1414.519,7.4
+1415.885,46.8
+1416.529,68.8
+1417.396,43.8
+1418.646,15.6
+1419.44,19.9
+1420.465,37.1
+1421.18,15.6
+1421.781,11.7
+1425.811,66.4
+1426.508,21.9
+1427.809,100.8
+1428.738,40.9
+1429.699,38.1
+1430.719,149.2
+1431.797,17.1
+1433.272,44.9
+1434.431,19.6
+1435.499,3.7
+1436.441,157.8
+1437.197,10.1
+1438.124,44.7
+1439.672,34.1
+1440.665,21
+1443.418,95.4
+1445.228,1.9
+1452.395,64.6
+1453.295,6.1
+1457.18,56.3
+1457.937,14.4
+1461.855,59.9
+1462.94,56.6
+1465.69,66.5
+1467.527,3.1
+1468.586,46.6
+1469.345,7.4
+1471.001,10.1
+1471.636,26.3
+1472.641,4.9
+1474.849,37.1
+1476.141,18.8
+1477.515,27.1
+1478.308,24
+1479.975,69.4
+1480.648,1.6
+1482.259,44.5
+1483.001,11.9
+1485.136,105.5
+1485.775,34
+1487.783,45.4
+1488.809,24.7
+1489.921,17.7
+1490.549,26.3
+1491.54,14.1
+1492.506,33.6
+1495.197,17.3
+1497.236,89.7
+1499.61,22.2
+1501.811,4.1
+1503.396,5.3
+1506.86,62.9
+1507.815,26.3
+1509.434,8.5
+1510.356,73.2
+1511.509,23.9
+1512.637,4.4
+1513.458,43.5
+1514.126,49.2
+1515.093,14.2
+1516.977,116.6
+1517.984,101.5
+1518.663,2
+1519.405,14.7
+1521.016,71.6
+1522.858,55.3
+1523.861,22.3
+1530.29,22.9
+1532.912,14.9
+1533.566,4.7
+1534.514,4
+1536.546,43.2
+1540.464,35.4
+1541.603,34.5
+1542.626,70.3
+1543.92,23.6
+1547.329,33.5
+1548.741,1.8
+1550.543,37.9
+1552.905,208.3
+1554.226,189.6
+1555.085,75.2
+1555.735,1.7
+1557.289,29.8
+1559.157,324.6
+1559.952,107.5
+1560.63,24.8
+1561.873,47.9
+1564.207,32
+1566.253,16.2
+1570.567,71.9
+1574.427,87.7
+1575.359,18.2
+1576.878,10.9
+1578.463,27.1
+1579.13,18.7
+1585.852,27.3
+1586.662,14.1
+1587.379,5.2
+1588.339,42.1
+1589.874,9.1
+1591.224,51.8
+1591.911,36.4
+1592.852,1.8
+1593.993,18.1
+1599.533,19.1
+1600.61,3.4
+1603.868,22
+1607.7,35.2
+1608.997,46
+1609.724,14.5
+1612.595,25.5
+1614.184,38.3
+1615.699,21.4
+1617.191,5.8
+1621.281,9.5
+1622.297,10
+1623.798,12.5
+1625.681,9.9
+1627.395,91.3
+1628.626,12.3
+1629.541,46.3
+1631.565,28.9
+1632.856,25.7
+1635.644,62.6
+1636.626,18.5
+1637.368,5.4
+1638.403,10.8
+1639.443,10
+1641.071,138.9
+1642.24,43.3
+1643.216,25.1
+1645.007,56.8
+1645.741,6.7
+1646.584,14.5
+1647.69,20.6
+1649.052,10.8
+1650.903,15.4
+1652.112,6.8
+1652.983,26.7
+1655.4,5
+1657.846,12.2
+1660.164,48.9
+1661.677,9.7
+1668.584,81.2
+1669.305,4
+1671.813,11.1
+1673.349,3.8
+1674.4,2
+1677.662,18.3
+1680.044,33.1
+1681.242,10.9
+1683.692,8.4
+1684.381,27.5
+1685.214,10.7
+1686.462,29
+1687.508,4
+1691.522,14.7
+1692.641,26.8
+1696.366,52.5
+1697.557,16.6
+1701.681,10.7
+1703.762,54.7
+1704.699,28
+1706.526,43.6
+1709.564,38.9
+1710.894,10.8
+1712.526,34.4
+1713.199,23.2
+1714.573,14.4
+1716.483,22.7
+1721.385,11.8
+1722.673,35.4
+1723.455,25.4
+1724.685,20.4
+1725.61,6.2
+1729.942,28.7
+1732.083,30.6
+1733.53,50.2
+1734.614,16.2
+1738.318,12.7
+1739.396,14.5
+1742.212,15.2
+1742.843,5.2
+1743.916,10.3
+1745.901,12.1
+1747.494,6.9
+1750.433,25.8
+1754.032,5.9
+1755.026,11.5
+1757.642,29.6
+1758.323,3.1
+1763.382,16
+1769.582,8.3
+1771.219,14.2
+1773.064,4.5
+1776.647,2.2
+1782.317,21.7
+1786.912,19.8
+1793.615,25.1
+1795.543,7.2
+1796.843,1.4
+1798.764,12.9
+1800.335,2.7
+1802.575,17.4
+1813.584,15.1
+1814.362,6
+1817.63,30.6
+1821.513,15.7
+1823.36,42.8
+1824.44,16.3
+1827.192,16.4
+1828.6,27.1
+1829.759,12
+1832.786,40.6
+1836.984,92.8
+1837.818,13.8
+1840.404,17.8
+1841.535,6.7
+1848.037,25.9
+1848.717,3.8
+1850.918,2
+1852.771,8.4
+1853.778,7.8
+1854.645,26.5
+1857.714,21.1
+1862.614,11.2
+1871.483,53.1
+1874.175,18.6
+1874.981,15.3
+1877.145,6
+1879.476,23.2
+1894.793,19.1
+1895.553,5.4
+1897.367,7.7
+1898.021,1.2
+1906.242,14.3
+1914.824,4.1
+1919.659,3.5
+1924.77,36.3
+1937.047,20.7
+1939.232,18.3
+1942.525,9.2
+1943.27,6.3
+1948.095,13.3
+1951.771,25.6
+1961.532,9.5
+1967.624,9.9
+1969.254,7.2
+1971.767,6.8
+1987.625,23
+1990.602,4.4
+FragModelIonMatchListEnd
+FragModelIonMatchListCaption=CaM_S5_005_060925_: Scan 11275
+FragModelIonAlignment=0
+[PlotOptions_Series1]
+SeriesPlotMode=1
+SeriesLineStyle=0
+SeriesLineWidth=1
+SeriesLineColor=255
+SeriesLineToBaseColor=255
+SeriesBarFillColor=255
+SeriesPointStyle=0
+SeriesPointColor=255
+AnnotationFontName=Arial
+AnnotationFontSize=10
+AnnotationFontColor=0
+[PlotOptions_Series2]
+SeriesPlotMode=1
+SeriesLineStyle=0
+SeriesLineWidth=1
+SeriesLineColor=40960
+SeriesLineToBaseColor=40960
+SeriesBarFillColor=40960
+SeriesPointStyle=0
+SeriesPointColor=40960
+AnnotationFontName=Arial
+AnnotationFontSize=10
+AnnotationFontColor=0
+[GlobalPlotOptions]
+Title=
+Subtitle=
+XAxis=
+YAxis=
+LabelFontName=Arial
+LabelFontSize=Arial
+LabelFontColor=0
+PlotBackgroundColor=16777215
+NormalizeOnLoadOrPaste=True
+NormalizationConstant=100
+GridLinesXColorMajor=0
+GridLinesXColorMinor=8421504
+GridLinesYColorMajor=0
+GridLinesYColorMinor=8421504
+GridLinesXVisibleMajor=False
+GridLinesXVisibleMinor=False
+GridLinesYVisibleMajor=False
+GridLinesYVisibleMinor=False
+AnnotationDensityAutoHideCaptions=True
+AnnotationDensityToleranceAutoAdjust=True
+AnnotationDensityToleranceX=0.562291337199086
+AnnotationDensityToleranceY=0.5420054200542
+AutoScaleVisibleY=False
+FixMinimumYAtZero=False
+AutoAdjustScalingToIncludeCaptions=True
+PrecisionX=2
+PrecisionY=1
+CursorVisible=True
+CursorSnapToData=False
+CursorColor=0
+CursorPositionX=0
+CursorPositionY=0
+AutoLabelPeaksDisplayXPosition=True
+AutoLabelPeaksDisplayYPosition=False
+AutoLabelPeaksIncludeArrow=False
+AutoLabelPeaksHideInDenseRegions=True
+AutoLabelPeaksCaptionAngle=0
+AutoLabelPeaksIntensityThresholdMinimum=10
+AutoLabelPeaksMinimumIntensityPercentageOfMaximum=0
+AutoLabelPeaksPeakWidthMinimumPoints=5
+AutoLabelPeaksLabelCountMaximum=100
diff --git a/mwt_valu.inn b/mwt_valu.inn
new file mode 100644
index 0000000..fbabcca
--- /dev/null
+++ b/mwt_valu.inn
@@ -0,0 +1,1076 @@
+; Values File for MWTWIN Program (v6.41)
+;
+; File Automatically Created -- Select Save Values and Formulas under the Options Menu
+;
+Formula0=BrCH2(CH2)7CH2Br
+Formula1=FeCl3-6H2O
+Formula2=Co(Bpy)(CO)4
+Formula3=^13C6H6-.1H2O
+Formula4=HGlyLeuTyrOH
+Formula5=BrCH2(CH2)7CH2Br>CH8
+AminoAcidConvertOneLetter=GLY
+AminoAcidConvertThreeLetter=Gly-Leu-Tyr
+AminoAcidConvertSpaceOneLetter=1
+AminoAcidConvertDashThreeLetter=1
+Mole/MassWeightSource=0
+Mole/MassCustomMass=100
+Mole/MassAction=2
+Mole/MassFrom=1
+Mole/MassFromUnits=0
+Mole/MassDensity=1
+Mole/MassToUnits=8
+Mole/MassVolume=100
+Mole/MassVolumeUnits=2
+Mole/MassMolarity=10.0
+Mole/MassMolarityUnits=0
+Mole/MassDilutionMode=0
+Mole/MassMolarityInitial=10
+Mole/MassMolarityInitialUnits=0
+Mole/MassVolumeInitial=3.0
+Mole/MassVolumeInitialUnits=2
+Mole/MassMolarityFinal=2
+Mole/MassMolarityFinalUnits=0
+Mole/MassVolumeSolvent=12.0
+Mole/MassVolumeSolventUnits=2
+Mole/MassVolumeTotal=15
+Mole/MassVolumeTotalUnits=2
+Mole/MassLinkConcentrations=0
+Mole/MassLinkDilutionVolumeUnits=1
+CapillaryFlowFileFormatVersion=2
+CapillaryFlowMode=0
+CapillaryFlowComputationType=3
+CapillaryFlowLinkFlowRate=1
+CapillaryFlowLinkLinearVelocity=1
+CapillaryFlowShowPeakBroadeningSave=0
+CapillaryFlowWeightSource=0
+CapillaryFlowCustomMass=100
+CapillaryFlowOpenText0=50
+CapillaryFlowPackedText0=3000
+CapillaryFlowOpenText1=50
+CapillaryFlowPackedText1=50
+CapillaryFlowOpenText2=30
+CapillaryFlowPackedText2=75
+CapillaryFlowOpenText3=0.0089
+CapillaryFlowPackedText3=0.0089
+CapillaryFlowOpenText4=5
+CapillaryFlowPackedText4=5
+CapillaryFlowOpenText5=100
+CapillaryFlowPackedText5=100
+CapillaryFlowOpenText6=1
+CapillaryFlowPackedText6=1
+CapillaryFlowOpenText7=0.4
+CapillaryFlowPackedText7=0.4
+CapillaryFlowOpenText8=1
+CapillaryFlowPackedText8=1
+CapillaryFlowOpenText9=924.07
+CapillaryFlowPackedText9=100
+CapillaryFlowOpenText10=30
+CapillaryFlowPackedText10=30
+CapillaryFlowOpenText11=1
+CapillaryFlowPackedText11=1
+CapillaryFlowOpenText12=0.000005
+CapillaryFlowPackedText12=0.000005
+CapillaryFlowOpenText13=5
+CapillaryFlowPackedText13=5
+CapillaryFlowOpenText14=50
+CapillaryFlowPackedText14=50
+CapillaryFlowOpenText15=30
+CapillaryFlowPackedText15=30
+CapillaryFlowOpenText16=0
+CapillaryFlowPackedText16=0
+CapillaryFlowOpenCombo0=0
+CapillaryFlowPackedCombo0=0
+CapillaryFlowOpenCombo1=1
+CapillaryFlowPackedCombo1=1
+CapillaryFlowOpenCombo2=3
+CapillaryFlowPackedCombo2=3
+CapillaryFlowOpenCombo3=0
+CapillaryFlowPackedCombo3=0
+CapillaryFlowOpenCombo4=3
+CapillaryFlowPackedCombo4=3
+CapillaryFlowOpenCombo5=2
+CapillaryFlowPackedCombo5=2
+CapillaryFlowOpenCombo6=4
+CapillaryFlowPackedCombo6=4
+CapillaryFlowOpenCombo7=2
+CapillaryFlowPackedCombo7=2
+CapillaryFlowOpenCombo8=2
+CapillaryFlowPackedCombo8=2
+CapillaryFlowOpenCombo9=2
+CapillaryFlowPackedCombo9=2
+CapillaryFlowOpenCombo10=2
+CapillaryFlowPackedCombo10=2
+CapillaryFlowOpenCombo11=2
+CapillaryFlowPackedCombo11=2
+CapillaryFlowOpenCombo12=4
+CapillaryFlowPackedCombo12=4
+CapillaryFlowOpenCombo13=5
+CapillaryFlowPackedCombo13=5
+CapillaryFlowOpenCombo14=4
+CapillaryFlowPackedCombo14=4
+CapillaryFlowOpenCombo15=1
+CapillaryFlowPackedCombo15=1
+CapillaryFlowOpenCombo16=3
+CapillaryFlowPackedCombo16=3
+CapillaryFlowOpenCombo17=2
+CapillaryFlowPackedCombo17=2
+CapillaryFlowOpenCombo18=2
+CapillaryFlowPackedCombo18=2
+ViscosityMeCNPercentAcetontrile=20
+ViscosityMeCNTemperature=25
+ViscosityMeCNTemperatureUnits=0
+Calculator=6^3-8.5*3
+IonPlotColor=16711680
+IonPlotShowPlot=1
+IonPlotType=1
+IonPlotResolution=5000
+IonPlotResolutionMass=1000
+IonPlotGaussianQuality=50
+IonComparisonPlotColor=255
+IonComparisonPlotType=0
+IonComparisonPlotNormalize=1
+FinderAction=0
+FinderMWT=200
+FinderPercentMaxWeight=400
+FinderPPM=0
+FinderShowDeltaMass=1
+FinderWtTolerance=0.05
+FinderPercentTolerance=1
+FinderMaxHits=100
+FinderSortResults=1
+FinderSmartH=1
+FinderFindCharge=0
+FinderFindMtoZ=0
+FinderLimitChargeRange=0
+FinderChargeRangeMin=-4
+FinderChargeRangeMax=4
+FinderFindTargetMtoZ=0
+FinderHighlightText=0
+FinderAutoBoundsSet=1
+FinderSortMode=0
+FinderMin0=0
+FinderMax0=10
+FinderCheckElements0=1
+FinderPercentValue0=Percent
+FinderMin1=0
+FinderMax1=10
+FinderCheckElements1=1
+FinderPercentValue1=Percent
+FinderMin2=0
+FinderMax2=10
+FinderCheckElements2=1
+FinderPercentValue2=Percent
+FinderMin3=0
+FinderMax3=10
+FinderCheckElements3=1
+FinderPercentValue3=Percent
+FinderMin4=0
+FinderMax4=10
+FinderCheckElements4=0
+FinderPercentValue4=Percent
+FinderCustomWeight1=# or Element or Abbrev.
+FinderMin5=0
+FinderMax5=10
+FinderCheckElements5=0
+FinderPercentValue5=Percent
+FinderCustomWeight2=# or Element or Abbrev.
+FinderMin6=0
+FinderMax6=10
+FinderCheckElements6=0
+FinderPercentValue6=Percent
+FinderCustomWeight3=# or Element or Abbrev.
+FinderMin7=0
+FinderMax7=10
+FinderCheckElements7=0
+FinderPercentValue7=Percent
+FinderCustomWeight4=# or Element or Abbrev.
+FinderMin8=0
+FinderMax8=10
+FinderCheckElements8=0
+FinderPercentValue8=Percent
+FinderCustomWeight5=# or Element or Abbrev.
+FinderMin9=0
+FinderMax9=10
+FinderCheckElements9=0
+FinderPercentValue9=Percent
+FinderCustomWeight6=# or Element or Abbrev.
+FragModelModificationSymbolsCount=10
+FragModelModificationSymbol1=*,79.9663326,True,Phosphorylation [HPO3]
+FragModelModificationSymbol2=+,14.01565,False,Methylation [CH2]
+FragModelModificationSymbol3=@,15.99492,False,Oxidation [O]
+FragModelModificationSymbol4=!,57.02146,False,Carbamidomethylation [C2H3NO]
+FragModelModificationSymbol5=&,58.00548,False,Carboxymethylation [CH2CO2]
+FragModelModificationSymbol6=#,71.03711,False,Acrylamide [CHCH2CONH2]
+FragModelModificationSymbol7=$,227.127,False,Cleavable ICAT [(^12C10)H17N3O3]
+FragModelModificationSymbol8=%,236.127,False,Cleavable ICAT [(^13C9)(^12C)H17N3O3]
+FragModelModificationSymbol9=~,442.225,False,ICAT D0 [C20H34N4O5S]
+FragModelModificationSymbol10=`,450.274,False,ICAT D8 [C20H26D8N4O5S]
+FragModelNotationMode=1
+FragModelSequence=Arg-His-Pro-Glu-Tyr-Ala-Val
+FragModelNTerminus=0
+FragModelCTerminus=0
+FragModelIonType0=0
+FragModelIonType1=1
+FragModelIonType2=1
+FragModelIonsToModify0=0
+FragModelIonsToModify1=1
+FragModelIonsToModify2=1
+FragModelWaterLoss=1
+FragModelAmmoniaLoss=0
+FragModelPhosphateLoss=0
+FragModelDoubleCharge=0
+FragModelDoubleChargeThreshold=8
+FragModelPrecursorIonRemove=1
+FragModelPrecursorIonMass=300
+FragModelPrecursorIonMassWindow=2
+FragModelIonMatchWindow=0.5
+FragModelIonIntensity0=10
+FragModelIonIntensity1=50
+FragModelIonIntensity2=50
+FragModelShoulderIntensity=25
+FragModelNeutralLossIntensity=10
+FragModelGroupIons=0
+FragModelGroupIonsMassWindow=.5
+FragModelNormalizedIntensity=100
+FragModelNormalizationIonsUseCount=200
+FragModelNormalizationMassRegions=1
+FragModelLabelMainIons=1
+FragModelLabelOtherIons=0
+FragModelEmphasizeProlineYIons=0
+FragModelPlotPredictedSpectrumInverted=1
+FragModelAutoLabelMass=0
+FragModelFragSpectrumColor=16711680
+FragModelMatchingIonDataColor=32768
+FragModelIonMatchList=763
+112.0853,3
+136.0762,59
+137.0843,5
+139.0817,6
+139.1133,17
+139.377,2
+139.7315,2
+140.0848,5
+141.5006,1
+143.1274,15
+143.5475,1
+144.1294,2
+148.0963,2
+156.1161,4
+157.0959,5
+159.0842,2
+159.1246,34
+160.1297,2
+160.1751,1
+163.8093,6
+169.1121,3
+171.0814,1
+171.1163,7
+175.1257,37
+182.1106,3
+185.1759,5
+186.1721,1
+186.2184,1
+187.111,37
+188.121,6
+196.1191,3
+199.1189,12
+199.1768,2
+202.3497,2
+202.3897,6
+202.4608,2
+202.9548,1
+203.0119,3
+205.1135,2
+207.0992,4
+207.1408,8
+213.1642,4
+218.1487,2
+221.9199,2
+227.1035,31
+227.1788,4
+228.0981,4
+228.1437,4
+233.155,3
+235.0365,1
+235.1248,19
+236.1297,7
+240.1542,3
+245.6539,4
+246.3976,2
+246.6541,68
+246.8809,1
+247.1341,4
+247.1902,11
+249.1758,7
+250.6709,5
+250.7164,7
+251.1959,5
+251.2478,3
+251.6217,2
+251.6747,2
+252.1679,6
+255.6198,1
+258.2047,3
+259.1178,1
+259.1799,3
+260.295,4
+260.5264,2
+260.6527,149
+261.069,1
+261.1432,39
+261.4579,3
+261.6691,5
+262.1266,6
+262.2358,4
+263.0959,2
+263.1416,2
+266.1627,13
+266.2044,6
+266.9036,2
+267.548,2
+267.9639,1
+268.1754,8
+268.6133,1
+269.1628,4
+269.6667,1
+269.7262,2
+271.1963,17
+271.2502,4
+272.1867,2
+275.1514,1
+275.6785,2
+275.7574,1
+277.1639,12
+278.137,6
+286.1738,4
+287.0152,3
+288.2111,63
+288.5215,2
+288.9533,1
+289.1393,3
+289.2121,17
+293.1697,3
+293.6161,2
+293.6732,2
+294.1874,231
+294.455,5
+294.5085,3
+294.6884,14
+294.9955,1
+295.1794,42
+295.2924,2
+295.3462,1
+295.3869,2
+295.447,1
+295.5037,2
+295.9444,1
+296.1693,10
+296.3044,3
+300.1975,21
+300.2907,2
+301.2919,2
+304.7282,2
+306.1841,3
+306.2568,1
+312.2487,6
+319.6728,4
+320.2012,4
+322.2489,2
+327.1851,3
+327.3661,1
+328.1826,68
+328.2633,14
+328.3271,3
+328.6884,49
+328.7545,6
+329.1873,8
+333.1671,8
+333.6007,3
+334.2184,12
+334.2833,1
+334.7221,4
+334.7917,2
+337.7202,3
+339.5072,2
+340.7826,2
+341.0398,2
+341.7773,4
+342.1797,393
+342.3465,3
+342.4303,5
+342.4893,4
+342.5583,7
+342.6834,159
+342.817,13
+343.0197,4
+343.1782,28
+343.4868,4
+343.5865,2
+343.6495,5
+343.7368,36
+343.8218,10
+343.8938,4
+344.0427,2
+344.1109,1
+344.1737,4
+344.258,31
+344.5179,4
+344.5953,4
+344.7082,7
+344.8063,3
+344.9668,5
+345.2133,3
+346.1691,6
+346.7994,2
+346.8672,3
+347.1616,6
+347.3818,4
+349.0909,2
+351.1988,4
+351.2789,1
+351.6955,3
+355.2979,1
+356.1698,3
+356.6293,1
+357.2323,4
+362.1739,13
+362.2378,3
+363.2299,6
+363.3801,1
+363.7023,82
+364.1729,18
+364.2336,11
+364.3133,5
+364.5458,3
+364.6974,3
+365.1807,4
+365.5901,2
+366.2758,4
+366.8056,3
+368.689,13
+369.6983,3
+370.2689,5
+370.3798,2
+371.2562,5
+372.1652,3
+373.11,3
+373.2534,2
+375.1942,4
+376.0613,2
+376.4238,5
+377.0261,6
+377.1432,1
+377.2305,12
+377.4629,5
+377.5285,3
+377.7029,598
+377.9336,5
+377.9883,3
+378.2069,338
+378.5213,10
+378.5701,6
+378.691,51
+378.7713,34
+378.9062,3
+378.9558,1
+379.0303,10
+379.1436,4
+379.2068,21
+379.3916,8
+379.6018,9
+379.7127,3
+379.8116,4
+379.8799,9
+380.3029,2
+380.4071,1
+380.958,4
+382.7159,4
+384.207,5
+384.2823,21
+386.2754,4
+388.5695,2
+390.1915,52
+390.283,4
+391.1819,10
+391.2362,8
+392.1442,3
+392.2137,1
+393.5819,2
+393.9643,2
+394.8687,2
+400.2879,3
+400.4994,4
+400.5706,2
+401.1934,4
+401.3109,371
+401.6982,6
+402.3135,81
+402.4536,5
+402.5192,3
+402.6164,3
+402.7132,1
+402.9335,5
+403.259,12
+403.309,6
+403.3876,3
+403.4753,1
+403.7147,3
+404.2269,4
+404.3108,3
+404.7374,5
+404.8113,1
+405.2131,5
+405.3333,3
+405.6795,2
+407.8732,2
+411.0067,2
+413.0218,1
+413.0892,1
+413.2335,57
+413.3035,25
+413.7328,32
+413.8081,8
+414.2228,5
+414.2828,9
+414.3424,4
+414.4356,2
+414.6094,4
+414.7199,6
+414.87,2
+416.11,3
+418.711,4
+424.4149,2
+425.287,2
+426.2268,2
+426.7227,4
+426.9637,3
+427.2246,74
+427.2997,40
+427.4115,1
+427.7239,68
+427.8436,6
+427.9177,3
+428.0482,2
+428.1411,1
+428.2242,15
+428.3137,17
+428.787,6
+429.6598,3
+430.2758,3
+432.2763,1
+433.2212,6
+435.1302,3
+435.3378,4
+443.235,2
+443.6571,1
+444.9332,3
+445.2844,5
+446.3422,2
+447.2256,2
+448.7895,3
+449.2528,3
+449.5677,1
+450.1993,3
+451.8308,3
+452.2794,3
+452.8574,3
+456.3444,3
+456.815,2
+456.893,1
+457.3382,2
+458.089,2
+460.6348,4
+460.7936,7
+460.8852,4
+461.2248,43
+461.3586,8
+461.7555,134
+462.0425,2
+462.2522,92
+462.4144,5
+462.746,21
+462.8273,5
+463.2587,9
+464.1609,3
+464.2634,1
+469.518,3
+470.3055,3
+470.7576,81
+471.1271,5
+471.2655,46
+471.4061,6
+471.7367,9
+471.8181,6
+472.0988,5
+472.2733,7
+472.5045,1
+472.5667,1
+473.0598,2
+473.6369,1
+474.4301,2
+474.6018,11
+474.6872,10
+474.9321,10
+475.0013,21
+476.3438,3
+477.5691,2
+478.7099,2
+479.9517,4
+480.0665,2
+480.3365,10
+480.4079,2
+480.64,160
+480.8394,3
+480.9711,150
+481.1419,8
+481.295,87
+481.5169,2
+481.6326,26
+481.7563,5
+481.8299,2
+481.979,5
+482.067,2
+482.3113,8
+482.4529,2
+482.7108,8
+482.9548,4
+483.0466,2
+483.1181,4
+483.2962,2
+483.4197,6
+484.2981,4
+485.0859,3
+491.204,1
+491.2662,1
+491.3383,1
+491.7874,2
+491.8846,1
+492.295,20
+492.4422,3
+493.302,5
+493.504,3
+494.313,3
+495.3706,2
+497.7738,4
+498.8301,3
+498.9969,2
+499.2101,3
+499.649,2
+500.226,3
+500.3869,342
+500.56,5
+500.7669,5
+501.0752,2
+501.3755,91
+501.4952,9
+502.2757,5
+502.3503,14
+502.4227,10
+502.5471,4
+502.6361,4
+502.8102,2
+503.4046,5
+505.4753,2
+506.4412,4
+507.7981,3
+511.2679,14
+511.3341,17
+511.4388,2
+511.7908,27
+512.3044,5
+512.5751,3
+519.3084,4
+519.7026,4
+519.8273,2
+520.2967,328
+520.6697,1
+520.7661,3
+520.8824,7
+520.9682,2
+521.2927,94
+521.7892,3
+522.0936,2
+522.2187,5
+522.3113,12
+522.4092,7
+522.7855,1
+523.2501,3
+523.3372,1
+524.1531,2
+524.7791,3
+525.3735,1
+527.2947,8
+528.2895,3
+529.1505,2
+530.6804,2
+530.7861,2
+532.306,9
+533.3033,3
+535.361,3
+552.3618,2
+553.407,2
+554.7569,2
+558.5176,2
+559.6127,1
+560.287,5
+560.4134,3
+561.2498,1
+561.3267,4
+562.8124,2
+563.2944,3
+563.4239,1
+564.8261,6
+564.9099,4
+564.976,2
+565.2759,3
+565.3707,9
+565.5305,2
+566.4214,2
+568.4691,1
+569.3346,4
+569.4058,13
+569.5019,4
+569.5747,1
+569.6475,1
+570.3633,4
+570.4498,16
+571.2965,1
+571.4195,6
+571.4758,3
+571.5784,1
+572.381,3
+572.4486,2
+572.92,4
+573.3981,3
+573.7458,4
+573.8586,67
+573.9612,21
+574.066,3
+574.3539,61
+574.4537,17
+574.5536,2
+574.8405,19
+574.9592,2
+575.3185,11
+575.4207,4
+575.5056,2
+575.5826,1
+575.6589,1
+577.3074,9
+577.4223,3
+578.1526,3
+584.5505,3
+585.3615,11
+585.4314,10
+585.5741,3
+585.6603,7
+585.9116,3
+586.0613,5
+586.388,11
+586.5022,1
+586.5732,2
+586.846,12
+587.4271,1387
+587.7023,8
+587.7939,6
+587.8698,6
+588.0663,5
+588.2092,8
+588.4289,520
+588.6898,10
+588.7769,6
+588.993,12
+589.4146,97
+589.4962,51
+589.6946,13
+589.801,3
+590.3812,16
+590.5562,5
+592.2068,4
+592.8172,1
+593.0849,2
+593.4933,3
+595.6253,2
+596.3392,4
+597.3459,1
+597.4203,3
+597.515,2
+597.9026,1
+598.2836,3
+598.3417,8
+599.1752,2
+603.2936,2
+606.1924,2
+616.592,2
+617.423,1
+624.5602,2
+637.3413,3
+638.3671,3
+639.2586,1
+639.331,1
+639.8571,3
+642.108,1
+647.2784,4
+648.3354,5
+648.4521,2
+650.7113,2
+655.2712,2
+655.3664,30
+656.3695,8
+657.3942,3
+665.3284,4
+668.3688,2
+668.4735,6
+668.6234,1
+669.4628,3
+669.8121,1
+670.5142,3
+670.5972,2
+680.7796,3
+681.3997,1
+681.4736,3
+682.3482,2
+682.4495,5
+683.3481,219
+683.4712,44
+683.6359,6
+684.0644,3
+684.3716,106
+684.5844,6
+684.8958,1
+684.9804,3
+685.3737,14
+685.4988,4
+685.7285,5
+686.0152,7
+686.1675,5
+686.5014,557
+686.9116,8
+687.2289,2
+687.3205,3
+687.4829,171
+687.5939,93
+687.8615,9
+688.3171,3
+688.4927,40
+688.5773,13
+688.6929,9
+689.2798,1
+689.3668,1
+689.4847,4
+689.593,8
+689.8995,4
+690.908,2
+696.3164,2
+696.4634,5
+696.5764,1
+697.5877,2
+699.8672,3
+707.7047,2
+708.2455,1
+709.3156,4
+709.4521,2
+715.4932,1
+723.5035,3
+725.7914,1
+726.4122,90
+727.287,1
+727.3789,21
+727.4848,20
+727.9292,2
+734.0432,2
+736.162,1
+736.3848,13
+736.5123,4
+737.3798,5
+738.4948,3
+739.3513,3
+740.5328,9
+740.6787,2
+747.4741,2
+751.2795,4
+751.5072,2
+752.3605,7
+752.7471,3
+752.9329,6
+753.1516,5
+754.0845,9
+754.4078,773
+754.6768,22
+754.8329,5
+754.9259,3
+755.0079,9
+755.3988,315
+755.5961,32
+755.8419,8
+756.1276,5
+756.2121,3
+756.4058,84
+756.5536,8
+756.6567,1
+756.7365,4
+757.0129,8
+757.1477,5
+757.5342,249
+757.8083,8
+758.149,5
+758.3525,2
+758.5118,61
+758.5903,49
+758.8855,4
+759.4818,18
+759.5482,11
+759.7332,5
+760.4133,3
+760.5503,10
+760.9072,3
+761.6349,5
+762.7632,2
+763.4514,2
+764.3829,1
+764.4747,2
+768.6735,1
+770.4442,3
+785.5863,2
+793.6028,2
+808.385,1
+808.4804,2
+825.4254,18
+825.5293,15
+826.4259,8
+826.5468,8
+827.6287,3
+838.4358,2
+845.1581,1
+853.4627,103
+853.5911,23
+853.6886,16
+854.4817,49
+854.5994,22
+854.7208,4
+855.4445,15
+855.6116,1
+855.7076,1
+856.5129,2
+859.6588,1
+860.5162,2
+902.6061,5
+902.6943,2
+903.626,4
+903.7915,1
+905.4571,2
+913.6252,1
+915.7272,3
+917.6539,2
+920.3547,3
+920.5964,139
+920.7654,36
+920.9797,2
+921.5889,89
+921.7524,38
+922.0116,1
+922.1476,3
+922.4272,17
+922.5228,33
+922.6741,27
+922.817,4
+923.1877,1
+923.5013,29
+923.6208,5
+924.4304,4
+924.6093,6
+932.7939,2
+940.4985,30
+940.5948,8
+940.7292,6
+940.8721,3
+941.397,4
+941.5469,12
+941.7205,6
+1012.576,4
+1039.495,12
+1039.615,6
+1039.692,3
+1039.85,1
+1040.467,6
+1040.583,9
+1049.522,9
+1049.63,14
+1049.709,10
+1050.543,4
+1050.646,7
+1050.765,5
+1051.748,4
+1147.636,3
+1148.107,1
+1152.559,3
+1253.329,1
+FragModelIonMatchListEnd
+FragModelIonMatchListCaption=
+FragModelIonAlignment=0
+[PlotOptions_Series1]
+SeriesPlotMode=1
+SeriesLineStyle=0
+SeriesLineWidth=1
+SeriesLineColor=255
+SeriesLineToBaseColor=255
+SeriesBarFillColor=255
+SeriesPointStyle=0
+SeriesPointColor=255
+AnnotationFontName=Arial
+AnnotationFontSize=10
+AnnotationFontColor=0
+[PlotOptions_Series2]
+SeriesPlotMode=1
+SeriesLineStyle=0
+SeriesLineWidth=1
+SeriesLineColor=40960
+SeriesLineToBaseColor=40960
+SeriesBarFillColor=40960
+SeriesPointStyle=0
+SeriesPointColor=40960
+AnnotationFontName=Arial
+AnnotationFontSize=10
+AnnotationFontColor=0
+[GlobalPlotOptions]
+Title=
+Subtitle=
+XAxis=
+YAxis=
+LabelFontName=Arial
+LabelFontSize=Arial
+LabelFontColor=0
+PlotBackgroundColor=16777215
+NormalizeOnLoadOrPaste=True
+NormalizationConstant=100
+GridLinesXColorMajor=0
+GridLinesXColorMinor=8421504
+GridLinesYColorMajor=0
+GridLinesYColorMinor=8421504
+GridLinesXVisibleMajor=False
+GridLinesXVisibleMinor=False
+GridLinesYVisibleMajor=False
+GridLinesYVisibleMinor=False
+AnnotationDensityAutoHideCaptions=True
+AnnotationDensityToleranceAutoAdjust=True
+AnnotationDensityToleranceX=0.562291337199086
+AnnotationDensityToleranceY=0.5420054200542
+AutoScaleVisibleY=False
+FixMinimumYAtZero=False
+AutoAdjustScalingToIncludeCaptions=True
+PrecisionX=2
+PrecisionY=1
+CursorVisible=True
+CursorSnapToData=False
+CursorColor=0
+CursorPositionX=0
+CursorPositionY=0
+AutoLabelPeaksDisplayXPosition=True
+AutoLabelPeaksDisplayYPosition=False
+AutoLabelPeaksIncludeArrow=False
+AutoLabelPeaksHideInDenseRegions=True
+AutoLabelPeaksCaptionAngle=0
+AutoLabelPeaksIntensityThresholdMinimum=10
+AutoLabelPeaksMinimumIntensityPercentageOfMaximum=0
+AutoLabelPeaksPeakWidthMinimumPoints=5
+AutoLabelPeaksLabelCountMaximum=100
diff --git a/mwtwin.DEP b/mwtwin.DEP
new file mode 100644
index 0000000..acbb38a
--- /dev/null
+++ b/mwtwin.DEP
@@ -0,0 +1,26 @@
+[Version]
+Version=5.7.0.41
+
+[mwtwin.exe <0009>]
+Dest=$(AppPath)
+Date=9/16/99
+Time=22:23
+Version=5.7.0.41
+CABFilename=mwtwin.CAB
+CABINFFile=mwtwin.INF
+Uses1=MSVBVM60.DLL
+Uses2=OLEAUT32.DLL
+Uses3=olepro32.dll
+Uses4=ASYCFILT.DLL
+Uses5=STDOLE2.TLB
+Uses6=COMCAT.DLL
+Uses7=MSFLXGRD.OCX
+Uses8=COMDLG32.OCX
+Uses9=RICHTX32.OCX
+Uses10=mwtwin.hlp
+Uses11=mwtwin.ini
+Uses12=MWT_ABBR.dat
+Uses13=mwt_elem.dat
+Uses14=mwt_valu.ini
+Uses15=mwtwin.cnt
+Uses16=readme.txt
diff --git a/mwtwin.chm b/mwtwin.chm
new file mode 100644
index 0000000..5ab7a62
Binary files /dev/null and b/mwtwin.chm differ
diff --git a/mwtwin.exe b/mwtwin.exe
new file mode 100644
index 0000000..3c9abc3
Binary files /dev/null and b/mwtwin.exe differ
diff --git a/mwtwin.frm b/mwtwin.frm
new file mode 100644
index 0000000..548bfe7
--- /dev/null
+++ b/mwtwin.frm
@@ -0,0 +1,3582 @@
+VERSION 5.00
+Object = "{5E9E78A0-531B-11CF-91F6-C2863C385E30}#1.0#0"; "msflxgrd.ocx"
+Object = "{3B7C8863-D78F-101B-B9B5-04021C009402}#1.2#0"; "richtx32.ocx"
+Object = "{F9043C88-F6F2-101A-A3C9-08002B2F49FB}#1.2#0"; "comdlg32.ocx"
+Begin VB.Form frmMain
+ AutoRedraw = -1 'True
+ Caption = "Molecular Weight Calculator"
+ ClientHeight = 5460
+ ClientLeft = 1890
+ ClientTop = 1890
+ ClientWidth = 6270
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 700
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ ForeColor = &H80000008&
+ HelpContextID = 600
+ Icon = "mwtwin.frx":0000
+ KeyPreview = -1 'True
+ LinkTopic = "Form1"
+ PaletteMode = 1 'UseZOrder
+ ScaleHeight = 5460
+ ScaleWidth = 6270
+ Tag = "4900"
+ Begin MSComDlg.CommonDialog CommonDialog1
+ Left = 5280
+ Top = 3240
+ _ExtentX = 847
+ _ExtentY = 847
+ _Version = 393216
+ End
+ Begin VB.OptionButton optElementMode
+ Caption = "Inte&ger"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ HelpContextID = 4053
+ Index = 2
+ Left = 4680
+ TabIndex = 13
+ Tag = "5040"
+ Top = 2640
+ Width = 1395
+ End
+ Begin VB.OptionButton optElementMode
+ Caption = "&Isotopic"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ HelpContextID = 4053
+ Index = 1
+ Left = 4680
+ TabIndex = 12
+ Tag = "5030"
+ Top = 2400
+ Width = 1395
+ End
+ Begin VB.OptionButton optElementMode
+ Caption = "&Average"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ HelpContextID = 4053
+ Index = 0
+ Left = 4680
+ TabIndex = 11
+ Tag = "5020"
+ Top = 2160
+ Value = -1 'True
+ Width = 1395
+ End
+ Begin VB.Frame fraSingle
+ Height = 3975
+ Left = 120
+ TabIndex = 4
+ Top = 1200
+ Visible = 0 'False
+ Width = 4095
+ Begin MSFlexGridLib.MSFlexGrid grdPC
+ Height = 2775
+ Left = 240
+ TabIndex = 8
+ Tag = "5200"
+ ToolTipText = "Click to set or reset a target value"
+ Top = 960
+ Width = 3495
+ _ExtentX = 6165
+ _ExtentY = 4895
+ _Version = 393216
+ Rows = 11
+ FixedRows = 0
+ FixedCols = 0
+ ScrollBars = 0
+ End
+ Begin RichTextLib.RichTextBox rtfFormulaSingle
+ Height = 495
+ Left = 1080
+ TabIndex = 10
+ Tag = "5050"
+ ToolTipText = "5150"
+ Top = 240
+ Width = 2655
+ _ExtentX = 4683
+ _ExtentY = 873
+ _Version = 393217
+ MultiLine = 0 'False
+ TextRTF = $"mwtwin.frx":08CA
+ BeginProperty Font {0BE35203-8F91-11CE-9DE3-00AA004BB851}
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 700
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ End
+ Begin VB.TextBox txtMWTSingle
+ Appearance = 0 'Flat
+ BackColor = &H8000000F&
+ BorderStyle = 0 'None
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 9.75
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = 960
+ Locked = -1 'True
+ TabIndex = 17
+ TabStop = 0 'False
+ Text = "MW="
+ Top = 700
+ Width = 3015
+ End
+ Begin VB.Label lblFormulaSingle
+ Caption = "Formula 1:"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 375
+ Left = 120
+ TabIndex = 6
+ Top = 240
+ Width = 900
+ End
+ End
+ Begin VB.Frame fraMulti
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 975
+ Left = 120
+ TabIndex = 2
+ Top = 120
+ Width = 4215
+ Begin RichTextLib.RichTextBox rtfFormula
+ Height = 495
+ Index = 0
+ Left = 960
+ TabIndex = 9
+ Tag = "5050"
+ ToolTipText = "Type the molecular formula here."
+ Top = 240
+ Width = 2775
+ _ExtentX = 4895
+ _ExtentY = 873
+ _Version = 393217
+ MultiLine = 0 'False
+ TextRTF = $"mwtwin.frx":094E
+ BeginProperty Font {0BE35203-8F91-11CE-9DE3-00AA004BB851}
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 700
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ End
+ Begin VB.TextBox txtMWT
+ Appearance = 0 'Flat
+ BackColor = &H8000000F&
+ BorderStyle = 0 'None
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 9.75
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Index = 0
+ Left = 960
+ Locked = -1 'True
+ TabIndex = 16
+ TabStop = 0 'False
+ Text = "MW="
+ Top = 700
+ Width = 3015
+ End
+ Begin VB.Label lblFormula
+ Caption = "Formula 1:"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 375
+ Index = 0
+ Left = 120
+ TabIndex = 3
+ Top = 240
+ Width = 900
+ End
+ End
+ Begin VB.CommandButton cmdNewFormula
+ Caption = "&New Formula"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 375
+ Left = 4560
+ TabIndex = 1
+ TabStop = 0 'False
+ Tag = "5110"
+ ToolTipText = "Adds a new formula to the list"
+ Top = 720
+ Width = 1575
+ End
+ Begin VB.CommandButton cmdCalculate
+ Caption = "&Calculate"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 375
+ Left = 4560
+ TabIndex = 0
+ TabStop = 0 'False
+ Tag = "5100"
+ ToolTipText = "Determines the molecular weight of the current formula"
+ Top = 240
+ Width = 1575
+ End
+ Begin VB.Label lblStatus
+ BorderStyle = 1 'Fixed Single
+ Caption = "Ready"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = -1440
+ TabIndex = 5
+ ToolTipText = "Double click the status line to expand it"
+ Top = 4800
+ Width = 8295
+ End
+ Begin VB.Label lblHiddenFormStatus
+ Caption = "Unloaded"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 255
+ Left = 5040
+ TabIndex = 15
+ Top = 4200
+ Visible = 0 'False
+ Width = 735
+ End
+ Begin VB.Label lblQuickSwitch
+ Caption = "Quick Switch Element Mode"
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 495
+ Left = 4680
+ TabIndex = 14
+ Tag = "5010"
+ Top = 1560
+ Width = 1455
+ End
+ Begin VB.Label lblValueForX
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 8.25
+ Charset = 0
+ Weight = 400
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ Height = 375
+ Left = 4440
+ TabIndex = 7
+ Top = 1200
+ Width = 1695
+ End
+ Begin VB.Menu mnuFile
+ Caption = "&File"
+ HelpContextID = 1000
+ Begin VB.Menu mnuEditElements
+ Caption = "Edit &Elements Table"
+ HelpContextID = 1010
+ End
+ Begin VB.Menu mnuEditAbbrev
+ Caption = "Edit &Abbreviations"
+ HelpContextID = 1020
+ End
+ Begin VB.Menu mnuCalculateFile
+ Caption = "&Calculate weights from text file"
+ HelpContextID = 1005
+ End
+ Begin VB.Menu mnuBar1
+ Caption = "-"
+ End
+ Begin VB.Menu mnuPrint
+ Caption = "&Print Results"
+ HelpContextID = 1030
+ End
+ Begin VB.Menu mnuBar2
+ Caption = "-"
+ End
+ Begin VB.Menu mnuExit
+ Caption = "E&xit"
+ HelpContextID = 1040
+ End
+ End
+ Begin VB.Menu mnuEdit
+ Caption = "&Edit"
+ HelpContextID = 2000
+ Begin VB.Menu mnuCut
+ Caption = "Cu&t"
+ HelpContextID = 2010
+ End
+ Begin VB.Menu mnuCopy
+ Caption = "&Copy"
+ HelpContextID = 2010
+ End
+ Begin VB.Menu mnuPaste
+ Caption = "&Paste"
+ HelpContextID = 2010
+ End
+ Begin VB.Menu mnuDelete
+ Caption = "&Delete"
+ HelpContextID = 2010
+ End
+ Begin VB.Menu mnuCopyRTF
+ Caption = "Copy Current Formula as &RTF"
+ HelpContextID = 2030
+ Shortcut = ^R
+ End
+ Begin VB.Menu mnuBar3
+ Caption = "-"
+ End
+ Begin VB.Menu mnuCopyMWT
+ Caption = "Copy Current &Molecular Weight"
+ HelpContextID = 2040
+ Shortcut = ^W
+ End
+ Begin VB.Menu mnuCopyPC
+ Caption = "Copy P&ercent Composition Data"
+ HelpContextID = 2040
+ End
+ Begin VB.Menu mnuBar4
+ Caption = "-"
+ End
+ Begin VB.Menu mnuCopyCurrent
+ Caption = "Duplicate Current &Formula"
+ HelpContextID = 2050
+ Shortcut = {F2}
+ End
+ Begin VB.Menu mnuEraseAll
+ Caption = "Erase &All Formulas"
+ HelpContextID = 2060
+ Shortcut = {F5}
+ End
+ Begin VB.Menu mnuEraseCurrent
+ Caption = "Erase Current Formula"
+ HelpContextID = 2070
+ Shortcut = {F6}
+ End
+ Begin VB.Menu mnuBar9
+ Caption = "-"
+ End
+ Begin VB.Menu mnuExpandAbbrev
+ Caption = "E&xpand Abbreviations"
+ HelpContextID = 2080
+ End
+ Begin VB.Menu mnuEmpirical
+ Caption = "Convert to Empirical F&ormula"
+ HelpContextID = 2090
+ End
+ End
+ Begin VB.Menu mnuView
+ Caption = "&View"
+ HelpContextID = 3000
+ Begin VB.Menu mnuViewType
+ Caption = "&Muti View"
+ Checked = -1 'True
+ HelpContextID = 3010
+ Index = 0
+ End
+ Begin VB.Menu mnuViewType
+ Caption = "&Single View"
+ HelpContextID = 3020
+ Index = 1
+ End
+ Begin VB.Menu mnuBar5
+ Caption = "-"
+ End
+ Begin VB.Menu mnuPercentSolver
+ Caption = "&Percent Solver"
+ HelpContextID = 3030
+ Begin VB.Menu mnuPercentType
+ Caption = "O&ff"
+ Checked = -1 'True
+ HelpContextID = 3030
+ Index = 0
+ End
+ Begin VB.Menu mnuPercentType
+ Caption = "&On"
+ HelpContextID = 3030
+ Index = 1
+ End
+ End
+ End
+ Begin VB.Menu mnuTools
+ Caption = "&Tools"
+ HelpContextID = 3035
+ Begin VB.Menu mnuMMConvert
+ Caption = "&Mole/Mass Converter"
+ HelpContextID = 3040
+ Shortcut = ^M
+ End
+ Begin VB.Menu mnuFinder
+ Caption = "&Formula Finder"
+ HelpContextID = 3050
+ Shortcut = ^F
+ End
+ Begin VB.Menu mnuAminoAcidNotationConverter
+ Caption = "&Amino Acid Notation Converter"
+ HelpContextID = 3055
+ Shortcut = ^N
+ End
+ Begin VB.Menu mnuBar13
+ Caption = "-"
+ End
+ Begin VB.Menu mnuPeptideSequenceFragmentation
+ Caption = "&Peptide Sequence Fragmentation Modelling"
+ HelpContextID = 3080
+ Shortcut = ^P
+ End
+ Begin VB.Menu mnuIsotopicDistribution
+ Caption = "&Isotopic Distribution Modelling"
+ HelpContextID = 3100
+ Shortcut = ^I
+ End
+ Begin VB.Menu mnuDisplayIsotopicDistribution
+ Caption = "Show Isotopic &Distribution for Current Formula"
+ HelpContextID = 3100
+ Shortcut = ^D
+ End
+ Begin VB.Menu mnuBar11
+ Caption = "-"
+ End
+ Begin VB.Menu mnuCalculator
+ Caption = "Math &Calculator"
+ HelpContextID = 3060
+ Shortcut = ^L
+ End
+ Begin VB.Menu mnuCapillaryFlow
+ Caption = "Capillar&y Flow Calculator"
+ HelpContextID = 3070
+ Shortcut = ^Y
+ End
+ End
+ Begin VB.Menu mnuOptions
+ Caption = "&Options"
+ HelpContextID = 4000
+ Begin VB.Menu mnuChooseLanguage
+ Caption = "Choose &Language"
+ HelpContextID = 4003
+ End
+ Begin VB.Menu mnuProgramOptions
+ Caption = "Change Program &Preferences"
+ HelpContextID = 4006
+ Shortcut = ^O
+ End
+ Begin VB.Menu mnuChangeFont
+ Caption = "Change &Formula Font"
+ HelpContextID = 4060
+ Shortcut = ^T
+ End
+ Begin VB.Menu mnuStayOnTop
+ Caption = "Stay on &Top"
+ HelpContextID = 4065
+ Shortcut = ^S
+ End
+ Begin VB.Menu mnuBar10
+ Caption = "-"
+ HelpContextID = 4080
+ End
+ Begin VB.Menu mnuDefaultsOptions
+ Caption = "&Save and Restore Default Values"
+ HelpContextID = 4080
+ Begin VB.Menu mnuRestoreValues
+ Caption = "&Restore Default Values and Formulas"
+ HelpContextID = 4080
+ End
+ Begin VB.Menu mnuSaveValues
+ Caption = "Save &Values and Formulas Now"
+ HelpContextID = 4080
+ End
+ End
+ End
+ Begin VB.Menu mnuHelp
+ Caption = "&Help"
+ HelpContextID = 5000
+ Begin VB.Menu mnuOverview
+ Caption = "&Program Overview"
+ HelpContextID = 5000
+ End
+ Begin VB.Menu mnuShowTips
+ Caption = "&Show Tool Tips"
+ Checked = -1 'True
+ HelpContextID = 5000
+ End
+ Begin VB.Menu mnuBar7
+ Caption = "-"
+ End
+ Begin VB.Menu mnuAbout
+ Caption = "&About MWT"
+ HelpContextID = 6000
+ End
+ End
+ Begin VB.Menu mnuRightClick
+ Caption = "RightClickMenu"
+ Begin VB.Menu mnuRightClickUndo
+ Caption = "&Undo"
+ End
+ Begin VB.Menu mnuRightClickSep1
+ Caption = "-"
+ End
+ Begin VB.Menu mnuRightClickCut
+ Caption = "Cu&t"
+ End
+ Begin VB.Menu mnuRightClickCopy
+ Caption = "&Copy"
+ End
+ Begin VB.Menu mnuRightClickPaste
+ Caption = "&Paste"
+ End
+ Begin VB.Menu mnuRightClickDelete
+ Caption = "&Delete"
+ End
+ Begin VB.Menu mnuRightClickSep2
+ Caption = "-"
+ End
+ Begin VB.Menu mnuRightClickSelectAll
+ Caption = "Select &All"
+ End
+ End
+End
+Attribute VB_Name = "frmMain"
+Attribute VB_GlobalNameSpace = False
+Attribute VB_Creatable = False
+Attribute VB_PredeclaredId = True
+Attribute VB_Exposed = False
+Option Explicit
+
+Private Const PCT_SOLVER_INITIAL_DIVISION_COUNT = 10
+Private Const FORMULA_OFFSET_AMOUNT = 750 ' Distance to adjust screen when adding new formulas
+
+Private Const FORMULA_HIGHLIGHTED = "Highlighted"
+Private Const FORM_STAY_ON_TOP_NEWLY_ENABLED = "StayOnTopEnabled"
+Private Const MAIN_HEIGHT = 3950 ' Minimum height for the form
+Private Const MAIN_HEIGHT_SINGLE = 5400
+
+Private Type udtPercentSolverParametersType
+ SolverOn As Boolean
+ SolverWorking As Boolean
+ XVal As Double
+ SolverCounter As Long
+ blnMaxReached As Boolean
+ DivisionCount As Integer
+ IterationStopValue As Integer
+ StdDevModeEnabledSaved As Boolean
+
+ BestXVal As Double ' The x value that gave the lowest residual sum
+ BestXSumResiduals As Double ' The sum of the residuals when using BestXVal
+
+End Type
+
+Private Type udtMultiLineErrorDescriptionType
+ ErrorID As Long ' Contains the error number (used in the LookupMessage function). In addition, if a program error occurs, ErrorParams.ErrorID = -10
+ ErrorLine As Integer
+ ErrorPosition As Integer
+ ErrorCharacter As String
+End Type
+
+Private Type udtPCompGridValuesType
+ Text As String
+ value As Double
+ Goal As Double
+ Locked As Boolean
+End Type
+
+Private Type udtPctCompValuesType
+ GridCell(MAX_ELEMENT_INDEX) As udtPCompGridValuesType
+ TotalElements As Integer ' Total number of elements whose percent composition values are shown
+ LockedValuesCount As Integer ' The total number of locked percent composition values
+End Type
+
+
+' General Form-Wide Variables
+Private mBlnBatchProcess As Boolean
+Private mBatchProcessFilename As String
+Private mBatchProcessOutfile As String
+Private mBatchProcessOverwrite As Boolean
+Private mPctCompValues(MAX_FORMULAS) As udtPctCompValuesType ' 0-based array
+
+Private mViewMode As vmdViewModeConstants
+Private mCurrentFormulaIndex As Integer ' The current formula line (0 through mTopFormulaIndex)
+Private mTopFormulaIndex As Integer ' Ranges from 0 to mTopFormulaIndex; Number of formulas is mTopFormulaIndex + 1
+Private mStdDevModSaved As Integer
+Private mKeyPressAbortPctSolver As Integer
+Private mCurrentFormWidth As Integer, mCurrentFormHeight As Integer
+
+Private mUsingPCGrid As Boolean
+Private mIgnoreNextGotFocus As Boolean
+Private mDifferencesFormShown As Boolean
+Private mPercentCompositionGridRowCount As Integer
+
+Private mErrorParams As udtMultiLineErrorDescriptionType
+
+Private PctSolverParams As udtPercentSolverParametersType
+
+Public Function AddNewFormulaWrapper(Optional blnForceAddition As Boolean = False) As Boolean
+ ' Returns True if a new formula was added or a blank line was found and selected; false otherwise
+
+ Dim intIndex As Integer
+ Dim blnSuccess As Boolean
+
+On Error GoTo AddNewFormulaWrapperErrorHandler
+
+ ' Only call this function if the form is visible, otherwise, things can go wrong
+ Debug.Assert Me.Visible
+
+ If rtfFormulaSingle.Text = "" And Not blnForceAddition Then
+ ' Current formula is already blank
+ RaiseLabelStatusError 570
+ blnSuccess = False
+ Else
+ If mViewMode = vmdMultiView Then
+ ' Multi view
+ If Not blnForceAddition Then
+ ' Search for a blank line; move to it if found
+ For intIndex = 0 To mTopFormulaIndex
+ If rtfFormula(intIndex).Text = "" Then
+ ' The .SetFocus event can cause an error if a form is shown modally
+ ' Must use Resume Next error handling to avoid an error
+ On Error Resume Next
+ rtfFormula(intIndex).SetFocus
+ blnSuccess = True
+ Exit Function
+ End If
+ Next intIndex
+ End If
+
+ ' Actually add the new formula
+ If AddNewFormulaWork(True) Then
+ ' The .SetFocus event can cause an error if a form is shown modally
+ ' Must use Resume Next error handling to avoid an error
+ On Error Resume Next
+ rtfFormula(mCurrentFormulaIndex).SetFocus
+ blnSuccess = True
+ Else
+ blnSuccess = False
+ End If
+ Else
+ ' Single view
+ If PctSolverParams.SolverOn Then
+ ' Percent solver is on; must turn off before adding new formula
+ RaiseLabelStatusError 580
+ blnSuccess = False
+ Else
+ If Not blnForceAddition Then
+ ' Look for a blank formula; if found, display it
+ ' Otherwise, add a new one
+ For intIndex = 0 To mTopFormulaIndex
+ If rtfFormula(intIndex).Text = "" Then
+ mCurrentFormulaIndex = intIndex
+ rtfFormulaSingle.Text = rtfFormula(mCurrentFormulaIndex).Text
+ lblFormulaSingle.Caption = ConstructFormulaLabel(mCurrentFormulaIndex)
+ txtMWTSingle.Text = txtMWT(mCurrentFormulaIndex).Text
+ If txtMWTSingle.Text <> "" Then
+ txtMWTSingle.Visible = True
+ Else
+ txtMWTSingle.Visible = False
+ End If
+ LabelStatus
+ Calculate True
+ rtfFormulaSingle.SetFocus
+ blnSuccess = True
+ Exit Function
+ End If
+ Next intIndex
+ End If
+
+ ' Add a new formula
+ If AddNewFormulaWork(False) Then
+ rtfFormulaSingle.SetFocus
+ blnSuccess = True
+ Else
+ blnSuccess = False
+ End If
+ End If
+ End If
+ End If
+
+ AddNewFormulaWrapper = blnSuccess
+ Exit Function
+
+AddNewFormulaWrapperErrorHandler:
+ Debug.Assert False
+ GeneralErrorHandler "frmMain|AddNewFormulaWrapper", Err.Number, Err.Description
+
+End Function
+
+Private Function AddNewFormulaWork(boolMultiView As Boolean) As Boolean
+ ' Returns true if new formula actually added
+
+On Error GoTo AddNewFormulaWorkErrorHandler
+
+ ' Check if mTopFormulaIndex is < gMaxFormulaIndex
+ If mTopFormulaIndex >= gMaxFormulaIndex Then
+ ' Already have max formula fields, can't add more
+ RaiseLabelStatusError 560
+ AddNewFormulaWork = False
+ Exit Function
+ End If
+
+ mTopFormulaIndex = mTopFormulaIndex + 1 ' Increment field count.
+ mCurrentFormulaIndex = mTopFormulaIndex
+
+ ' Create new Formula Text Field
+ Load rtfFormula(mTopFormulaIndex)
+
+ ' Set new Text Field under previous field.
+ With rtfFormula(mTopFormulaIndex)
+ .Top = rtfFormula(mTopFormulaIndex - 1).Top + FORMULA_OFFSET_AMOUNT
+ .TabIndex = mTopFormulaIndex
+ .Text = ""
+ End With
+ cmdCalculate.TabIndex = mTopFormulaIndex + 1
+ cmdNewFormula.TabIndex = mTopFormulaIndex + 2
+ optElementMode(0).TabIndex = mTopFormulaIndex + 3
+ optElementMode(1).TabIndex = mTopFormulaIndex + 4
+ optElementMode(2).TabIndex = mTopFormulaIndex + 5
+
+ If cChkBox(frmProgramPreferences.chkShowToolTips) Then
+ rtfFormula(mTopFormulaIndex).ToolTipText = LookupToolTipLanguageCaption(5050, "Type the molecular formula here")
+ End If
+
+ ' Create new Formula Label Field
+ Load lblFormula(mTopFormulaIndex)
+
+ ' Set new Text Field under previous field.
+ lblFormula(mTopFormulaIndex).Top = lblFormula(mTopFormulaIndex - 1).Top + FORMULA_OFFSET_AMOUNT
+ lblFormula(mTopFormulaIndex).Caption = ConstructFormulaLabel(mTopFormulaIndex)
+ lblFormulaSingle.Caption = lblFormula(mTopFormulaIndex).Caption
+
+ ' Create new Molecular Weight Text Field
+ Load txtMWT(mTopFormulaIndex)
+
+ ' Set new Field under previous field.
+ txtMWT(mTopFormulaIndex).Top = txtMWT(mTopFormulaIndex - 1).Top + FORMULA_OFFSET_AMOUNT
+ txtMWT(mTopFormulaIndex).Text = ""
+ If txtMWTSingle.Text <> "" Then txtMWTSingle.Visible = True Else txtMWTSingle.Visible = False
+
+ ' Make appropriate new fields visible
+ rtfFormula(mTopFormulaIndex).Visible = True
+ lblFormula(mTopFormulaIndex).Visible = True
+ txtMWT(mTopFormulaIndex).Visible = False
+
+ ' Change window heights and set focus
+ fraMulti.Height = fraMulti.Height + FORMULA_OFFSET_AMOUNT
+ If boolMultiView Then
+ With frmMain
+ If .WindowState = vbNormal Then
+ ResizeFormMain True
+ If .Height + .Top > Screen.Height Then
+ .Top = 0
+ End If
+ End If
+ End With
+ Else
+ rtfFormulaSingle.Text = rtfFormula(mCurrentFormulaIndex).Text
+ lblFormulaSingle.Caption = ConstructFormulaLabel(mCurrentFormulaIndex)
+ txtMWTSingle.Text = txtMWT(mCurrentFormulaIndex).Text
+ If txtMWTSingle.Text <> "" Then
+ txtMWTSingle.Visible = True
+ Else
+ txtMWTSingle.Visible = False
+ End If
+ End If
+
+ ' Make sure txtMWT is not a tab stop
+ txtMWT(mTopFormulaIndex).TabStop = False
+
+ AddNewFormulaWork = True
+ Exit Function
+
+AddNewFormulaWorkErrorHandler:
+ Debug.Assert False
+ GeneralErrorHandler "frmMain|AddNewFormulaWork", Err.Number, Err.Description
+
+End Function
+
+Private Sub AddToDiffForm(strAdd As String, intLabelIndex As Integer)
+
+ Select Case intLabelIndex
+ Case 1
+ frmDiff.lblDiff1.Caption = frmDiff.lblDiff1.Caption & vbCrLf & strAdd
+ Case 2
+ frmDiff.lblDiff2.Caption = frmDiff.lblDiff2.Caption & vbCrLf & strAdd
+ Case Else
+ frmDiff.lblDiff3.Caption = frmDiff.lblDiff3.Caption & vbCrLf & strAdd
+ End Select
+
+End Sub
+
+Public Function Calculate(blnProcessAllFormulas As Boolean, Optional blnUpdateControls As Boolean = True, Optional blnStayOnCurrentFormula As Boolean = False, Optional intSingleFormulaToProcess As Integer = 0, Optional blnConvertToEmpirical As Boolean = False, Optional blnExpandAbbreviations As Boolean = False, Optional blnForceRecalculation As Boolean = False, Optional dblValueForX As Double = 1#, Optional blnSetFocusToFormula As Boolean = True) As Long
+ ' Re-calculate the molecular weight and percent composition values
+ ' for some or all of the formulas
+ ' If blnConvertToEmpirical = True then convert to empirical formulas
+ ' If blnExpandAbbreviations = True then expand abbreviations to their elemental equivalents
+
+ ' Returns 0 if success; the error ID if an error
+
+ Dim intFormulaIndex As Integer, intCurrentFormulaIndexSave As Integer
+ Dim intIndexStart As Integer, intIndexEnd As Integer
+ Dim intElementIndex As Integer
+ Dim intGridInUseCount As Integer
+ Dim lngError As Long
+ Dim strNewFormula As String, strMWTText As String
+ Dim strCautionStatement As String
+ Dim strStatus As String
+
+ If blnProcessAllFormulas Then
+ intIndexStart = 0
+ intIndexEnd = mTopFormulaIndex
+ Else
+ intIndexStart = intSingleFormulaToProcess
+ intIndexEnd = intSingleFormulaToProcess
+ End If
+
+On Error GoTo CalculateErrorHandler
+
+ gBlnErrorPresent = False
+ mErrorParams.ErrorID = 0
+ mErrorParams.ErrorLine = -1
+ mErrorParams.ErrorPosition = -1
+ mErrorParams.ErrorCharacter = ""
+
+ intCurrentFormulaIndexSave = mCurrentFormulaIndex
+ For intFormulaIndex = intIndexStart To intIndexEnd
+
+ If Len(Trim(rtfFormula(intFormulaIndex).Text)) = 0 Then
+ ' Formula is blank
+ objCompounds(intFormulaIndex).SetFormula ""
+
+ ' Set txtMWT().Text to "" and hide
+ txtMWT(intFormulaIndex).Text = ""
+ txtMWT(intFormulaIndex).Visible = False
+ Else
+ If rtfFormula(intFormulaIndex).Tag = FORMULA_CHANGED Or _
+ blnForceRecalculation Or _
+ blnConvertToEmpirical Or _
+ blnExpandAbbreviations Then
+
+ With objCompounds(intFormulaIndex)
+ .ValueForX = dblValueForX
+ ' Note: Setting the formula automatically computes the mass
+ lngError = .SetFormula(rtfFormula(intFormulaIndex).Text)
+
+ strCautionStatement = .CautionDescription
+ If Len(strCautionStatement) > 0 And cChkBox(frmProgramPreferences.chkShowCaution) Then
+ With lblStatus
+ .Caption = LookupLanguageCaption(22000, "Caution") & ", " & strCautionStatement
+ gBlnStatusCaution = True
+ .ForeColor = QBColor(COLOR_WARN)
+ End With
+ End If
+ End With
+
+ If blnConvertToEmpirical Then
+ ' Note that Converting to the empirical formula automatically expands abbreviations to their empirical formulas
+ strNewFormula = objCompounds(intFormulaIndex).ConvertToEmpirical
+ Debug.Assert objCompounds(intFormulaIndex).FormulaCapitalized = strNewFormula
+ ElseIf blnExpandAbbreviations Then
+ strNewFormula = objCompounds(intFormulaIndex).ExpandAbbreviations
+ Debug.Assert objCompounds(intFormulaIndex).FormulaCapitalized = strNewFormula
+ End If
+
+ ' Update formula to formatted version
+ rtfFormula(intFormulaIndex).TextRTF = objMwtWin.TextToRTF(objCompounds(intFormulaIndex).FormulaCapitalized)
+
+ Debug.Assert objMwtWin.ErrorID = lngError
+
+ If objMwtWin.ErrorID = 0 Then
+ ' No error
+ ' Reset .Tag
+ rtfFormula(intFormulaIndex).Tag = ""
+ rtfFormulaSingle.Tag = ""
+
+ If blnUpdateControls Then
+ ' Refresh screen
+ If Not gBlnShowStdDevWithMass Then
+ ' Standard Deviation Mode is Off
+ strMWTText = CStr(objCompounds(intFormulaIndex).Mass(False))
+ Else
+ strMWTText = objCompounds(intFormulaIndex).MassAndStdDevString(False)
+ End If
+
+ strMWTText = ConstructMWEqualsCaption & strMWTText
+
+ If cChkBox(frmProgramPreferences.chkComputeCharge) Then
+ strMWTText = strMWTText & " " & _
+ LookupLanguageCaption(9150, "Charge") & " = " & _
+ ChargeValueToString(objCompounds(intFormulaIndex).Charge)
+ End If
+
+ txtMWT(intFormulaIndex).Text = strMWTText
+ txtMWT(intFormulaIndex).Visible = True
+
+ If intFormulaIndex = intCurrentFormulaIndexSave Then
+ txtMWTSingle.Text = strMWTText
+ txtMWTSingle.Visible = True
+ End If
+
+ End If
+
+ Else
+ ' Error occurred
+ If lngError <> 0 And mErrorParams.ErrorID = 0 Then
+ With mErrorParams
+ .ErrorID = objMwtWin.ErrorID
+ .ErrorLine = intFormulaIndex
+ .ErrorPosition = objMwtWin.ErrorPosition
+ .ErrorCharacter = objMwtWin.ErrorCharacter
+ End With
+ End If
+
+ ' Hide txtMWT
+ If mViewMode = vmdMultiView Then
+ txtMWT(intFormulaIndex).Visible = False
+ Else
+ txtMWTSingle.Visible = False
+ End If
+ End If
+
+ End If
+ End If
+
+ Next intFormulaIndex
+
+ If mViewMode = vmdSingleView Then
+ ' Need to display percent composition values
+ ' Further, if PctSolver is running, then need to compute additional values
+
+ With mPctCompValues(mCurrentFormulaIndex)
+ .TotalElements = objCompounds(mCurrentFormulaIndex).GetUsedElementCount
+ For intElementIndex = 1 To objMwtWin.GetElementCount
+ If objCompounds(mCurrentFormulaIndex).ElementPresent(intElementIndex) Then
+ intGridInUseCount = intGridInUseCount + 1
+ .GridCell(intGridInUseCount).Text = objCompounds(mCurrentFormulaIndex).GetPercentCompositionForElementAsString(intElementIndex, gBlnShowStdDevWithMass)
+ .GridCell(intGridInUseCount).value = objCompounds(mCurrentFormulaIndex).GetPercentCompositionForElement(intElementIndex)
+ End If
+ Next intElementIndex
+ End With
+
+ If objCompounds(mCurrentFormulaIndex).Mass(False) > 0 Then
+ ' Only proceed with percent solver computations if a non-zero mass
+
+ If mErrorParams.ErrorID = 0 And PctSolverParams.SolverOn Then
+ mErrorParams.ErrorID = PerformPercentSolverCalculations(mCurrentFormulaIndex)
+ If mErrorParams.ErrorID <> 0 Then
+ With mErrorParams
+ .ErrorLine = mCurrentFormulaIndex
+ .ErrorPosition = objMwtWin.ErrorPosition
+ .ErrorCharacter = objMwtWin.ErrorCharacter
+ End With
+ End If
+ End If
+ Else
+ If rtfFormula(mCurrentFormulaIndex).Text = "" Then
+ If Not PctSolverParams.SolverOn Then
+ lblValueForX.Caption = ""
+ lblValueForX.Visible = False
+ Else
+ lblValueForX.ForeColor = vbWindowText
+ lblValueForX.Caption = LookupLanguageCaption(3750, "% Solver On")
+ lblValueForX.Visible = True
+ End If
+ End If
+ End If
+
+ If blnUpdateControls Then
+ If mErrorParams.ErrorID = 0 Then
+ UpdateGrid grdPC, mCurrentFormulaIndex
+ Else
+ grdPC.Clear
+ End If
+ End If
+
+ End If
+
+ ' May need to copy the formula from rtfFormula() to rtfFormulaSingle
+ rtfFormulaSingle.Text = rtfFormula(mCurrentFormulaIndex).Text
+ txtMWTSingle.Text = txtMWT(mCurrentFormulaIndex).Text
+
+ If mErrorParams.ErrorID <> 0 Then ' Inform user of error and location
+ lblStatus.ForeColor = QBColor(COLOR_ERR)
+ strStatus = LookupMessage(mErrorParams.ErrorID)
+ If Len(mErrorParams.ErrorCharacter) > 0 Then
+ strStatus = strStatus & ": " & mErrorParams.ErrorCharacter
+ End If
+ lblStatus.Caption = strStatus
+ gBlnErrorPresent = True
+ If mErrorParams.ErrorLine >= 0 And mErrorParams.ErrorPosition >= 0 Then
+ RTFHighlightCharacter mErrorParams.ErrorLine, mErrorParams.ErrorPosition
+ End If
+
+ ResizeFormMain False, False
+ Else
+ ' No error
+
+ ' Also, copy current molecular weight value to clipboard if Auto Copy is turned on
+ If cChkBox(frmProgramPreferences.chkAutoCopyCurrentMWT) Then
+ CopyCurrentMWT True
+ End If
+ End If
+
+ ' See if an x is present after a bracket in the current formula
+ ' If yes, update lblValueForX to indicate the x value
+ ' Otherwise, hide lblValueForX
+ If objCompounds(mCurrentFormulaIndex).XIsPresentAfterBracket Then
+ lblValueForX.ForeColor = QBColor(COLOR_SOLVER)
+ lblValueForX.Caption = LookupLanguageCaption(3710, "x is") & " " & Format(dblValueForX, "#0.0######")
+ lblValueForX.Visible = True
+ Else
+ lblValueForX.Visible = False
+ End If
+
+ ' Position Cursor
+ If rtfFormula(mCurrentFormulaIndex).Tag = "" And _
+ rtfFormula(mCurrentFormulaIndex).Text <> "" And _
+ blnUpdateControls Then
+ If mViewMode = vmdMultiView Then
+ If blnProcessAllFormulas And Not blnStayOnCurrentFormula And _
+ cChkBox(frmProgramPreferences.chkAdvanceOnCalculate) Then
+ If mCurrentFormulaIndex = mTopFormulaIndex And mTopFormulaIndex <> gMaxFormulaIndex Then
+ AddNewFormulaWrapper
+ Else
+ mCurrentFormulaIndex = mCurrentFormulaIndex + 1
+ If mCurrentFormulaIndex > mTopFormulaIndex Then
+ ' This should never happen
+ Debug.Assert False
+ mCurrentFormulaIndex = mTopFormulaIndex
+ End If
+ End If
+ End If
+ End If
+
+ If frmMain.Visible And blnUpdateControls And blnSetFocusToFormula Then
+ SetFocusToFormulaByIndex mCurrentFormulaIndex
+ End If
+ End If
+
+ Calculate = mErrorParams.ErrorID
+
+ Exit Function
+
+CalculateErrorHandler:
+ GeneralErrorHandler "frmMain|CalculateMultiLine", Err.Number, Err.Description
+
+End Function
+
+Private Sub ClearGrid(ThisGrid As MSFlexGrid)
+ Dim elementi As Integer
+
+ With mPctCompValues(mCurrentFormulaIndex)
+ For elementi = 1 To objMwtWin.GetElementCount
+ .GridCell(elementi).Text = ""
+ .GridCell(elementi).value = 0
+ Next elementi
+ End With
+
+ UpdateGrid ThisGrid, mCurrentFormulaIndex
+
+End Sub
+
+Private Sub ConvertToEmpirical()
+ ' Expand abbreviations of current formula into their elemental representations
+ ' Then, rearrange elements to be in the order carbon, then hydrogen, then
+ ' the rest alphabetically
+
+ Dim eResponse As VbMsgBoxResult
+
+ ' Display the dialog box and get user's response.
+ If (frmProgramPreferences.optExitConfirmation(exmEscapeKeyConfirmExit).value = True Or frmProgramPreferences.optExitConfirmation(exmIgnoreEscapeKeyConfirmExit).value = True) Then
+ eResponse = YesNoBox(LookupLanguageCaption(3610, "Are you sure you want to convert the current formula into its empirical formula?"), _
+ LookupLanguageCaption(3615, "Convert to Empirical Formula"))
+ Else
+ eResponse = vbYes
+ End If
+
+ ' Evaluate the user's response.
+ If eResponse = vbYes Then
+ Calculate False, True, True, mCurrentFormulaIndex, True
+ End If
+
+End Sub
+
+Private Sub DisplayIsotopicDistribution(intFormulaIndexToDisplay As Integer)
+ If intFormulaIndexToDisplay <= frmMain.GetTopFormulaIndex Then
+ frmIsotopicDistribution.rtfFormula.Text = frmMain.rtfFormula(intFormulaIndexToDisplay).Text
+ frmIsotopicDistribution.Show
+ frmIsotopicDistribution.StartIsotopicDistributionCalcs True
+ End If
+End Sub
+
+Private Sub DuplicateCurrentFormula()
+ ' Copy current formula to new line or existing blank line
+
+ Dim blnFound As Boolean, intIndex As Integer, strCopyText As String
+
+ ' Only do this if Percent Solver Mode is not on
+ If Not PctSolverParams.SolverOn Then
+ If rtfFormula(mCurrentFormulaIndex).Text <> "" Then
+ ' Proceed only if the line is not blank
+ strCopyText = rtfFormula(mCurrentFormulaIndex).Text
+ RemoveHeightAdjustChar strCopyText
+
+ ' Search for an empty formula line
+ For intIndex = 0 To mTopFormulaIndex
+ If rtfFormula(intIndex).Text = "" Then
+ blnFound = True
+ Exit For
+ End If
+ Next intIndex
+
+ If Not blnFound Then
+ ' No empty lines
+ If mTopFormulaIndex < gMaxFormulaIndex Then
+ ' Add new formula and copy to end
+ If AddNewFormulaWrapper() = True Then
+ mCurrentFormulaIndex = mTopFormulaIndex
+ rtfFormula(mTopFormulaIndex).Text = strCopyText
+ End If
+ Else
+ lblStatus.ForeColor = QBColor(COLOR_ERR)
+ lblStatus.Caption = LookupMessage(630) & " " & LookupMessage(560)
+ End If
+ Else
+ ' Copy to blank formula
+ mCurrentFormulaIndex = intIndex
+ rtfFormula(intIndex).Text = strCopyText
+ End If
+
+ If mViewMode = vmdSingleView Then
+ rtfFormulaSingle.SetFocus
+ rtfFormulaSingle.Text = rtfFormula(mCurrentFormulaIndex).Text
+ lblFormulaSingle.Caption = ConstructFormulaLabel(mCurrentFormulaIndex)
+ txtMWTSingle.Text = txtMWT(mCurrentFormulaIndex).Text
+ If txtMWTSingle.Text <> "" Then
+ txtMWTSingle.Visible = True
+ Else
+ txtMWTSingle.Visible = False
+ End If
+ End If
+
+ ' Make sure the .Tag = FORMULA_CHANGED to assure the calculation occurs
+ rtfFormula(mCurrentFormulaIndex).Tag = FORMULA_CHANGED
+ Calculate True, True, True
+
+ LabelStatus
+ Else
+ lblStatus.ForeColor = QBColor(COLOR_ERR)
+ lblStatus.Caption = LookupMessage(630) & " " & LookupMessage(640)
+ End If
+ Else
+ lblStatus.ForeColor = QBColor(COLOR_ERR)
+ lblStatus.Caption = LookupMessage(630) & " " & LookupMessage(655)
+ End If
+
+End Sub
+
+Private Sub CopyPC()
+ Dim strCopyText As String, intIndex As Integer
+ Dim strPctCompositions(MAX_ELEMENT_INDEX) As String
+ Clipboard.Clear
+
+ strCopyText = ""
+ With objCompounds(mCurrentFormulaIndex)
+ .GetPercentCompositionForAllElements strPctCompositions()
+
+ For intIndex = 1 To objMwtWin.GetElementCount
+ If Len(strPctCompositions(intIndex)) > 0 Then
+ strCopyText = strCopyText & objMwtWin.GetElementSymbol(intIndex) & ": " & strPctCompositions(intIndex) & vbCrLf
+ End If
+ Next intIndex
+ End With
+
+ Clipboard.SetText strCopyText, vbCFText
+
+End Sub
+
+Private Sub CopyRTF()
+ Clipboard.Clear
+
+ rtfFormula(mCurrentFormulaIndex).SelStart = 0
+ rtfFormula(mCurrentFormulaIndex).SelLength = Len(rtfFormula(mCurrentFormulaIndex).Text)
+
+ Clipboard.SetText RemoveRTFHeightAdjust(rtfFormula(mCurrentFormulaIndex).SelRTF), vbCFRTF
+ rtfFormula(mCurrentFormulaIndex).SelLength = 0
+
+End Sub
+
+Public Sub ShowIsoDistributionModeller()
+
+ Dim strFormula As String
+
+ strFormula = rtfFormula(mCurrentFormulaIndex).Text
+
+ RemoveHeightAdjustChar strFormula
+
+ frmIsotopicDistribution.rtfFormula = strFormula
+ frmIsotopicDistribution.Show
+End Sub
+
+Private Sub EditAbbreviations()
+ frmEditAbbrev.ResetValChangedToFalse
+ frmEditAbbrev.Show vbModal
+ RecalculateAllFormulas
+
+ ' Clear lblLoadStatus so it doesn't accumulate messages over time
+ frmIntro.lblLoadStatus.Caption = ""
+End Sub
+
+Private Sub EditElements()
+ frmEditElem.ResetValChangedToFalse
+ frmEditElem.Show vbModal
+ RecalculateAllFormulas
+
+ ' Clear lblLoadStatus so it doesn't accumulate messages over time
+ frmIntro.lblLoadStatus.Caption = ""
+End Sub
+
+Private Sub EditMenuCheck()
+ Dim intIndex As Integer
+
+ If TypeOf Screen.ActiveControl Is RichTextBox Or TypeOf Screen.ActiveControl Is TextBox Then
+ mnuCut.Enabled = True
+ mnuCopy.Enabled = True
+ If Clipboard.GetFormat(vbCFText) Or Clipboard.GetFormat(vbCFRTF) Then
+ mnuPaste.Enabled = True
+ Else
+ mnuPaste.Enabled = False
+ End If
+ mnuDelete.Enabled = True
+ mnuCopyRTF.Enabled = True
+ Else
+ mnuCut.Enabled = False
+ mnuCopy.Enabled = False
+ mnuPaste.Enabled = False
+ mnuDelete.Enabled = False
+ mnuCopyRTF.Enabled = False
+ End If
+
+ If rtfFormula(mCurrentFormulaIndex).Text = "" Then
+ mnuEraseCurrent.Enabled = False
+ mnuCopyCurrent.Enabled = False
+ mnuExpandAbbrev.Enabled = False
+ mnuEmpirical.Enabled = False
+ Else
+ mnuEraseCurrent.Enabled = True
+ mnuCopyCurrent.Enabled = True
+ mnuExpandAbbrev.Enabled = True
+ mnuEmpirical.Enabled = True
+ End If
+
+
+ mnuExpandAbbrev.Caption = AppendEllipsesToSingleMenu(mnuExpandAbbrev.Caption, True)
+ mnuEmpirical.Caption = AppendEllipsesToSingleMenu(mnuEmpirical.Caption, True)
+ mnuEmpirical.Caption = AppendShortcutKeyToSingleMenu(mnuEmpirical.Caption, "Ctrl+E")
+
+ If txtMWT(mCurrentFormulaIndex).Visible = False Then
+ mnuCopyMWT.Enabled = False
+ Else
+ mnuCopyMWT.Enabled = True
+ End If
+
+ For intIndex = 0 To mTopFormulaIndex
+ If rtfFormula(intIndex).Text <> "" Then Exit For
+ Next intIndex
+
+ If intIndex = mTopFormulaIndex + 1 Then
+ mnuEraseAll.Enabled = False
+ Else
+ mnuEraseAll.Enabled = True
+ End If
+
+ If mViewMode = vmdSingleView Then
+ mnuCopyPC.Enabled = True
+ Else
+ mnuCopyPC.Enabled = False
+ End If
+End Sub
+
+Private Sub FormWideKeyDownHandler(ByRef KeyCode As Integer, ByRef Shift As Integer)
+
+ If mKeyPressAbortPctSolver = 1 Then
+ ' Key pressed, so end calculations
+ mKeyPressAbortPctSolver = 2
+ KeyCode = 0
+ Shift = 0
+ Else
+ If mKeyPressAbortPctSolver = 3 Then
+ UpdateGrid grdPC, mCurrentFormulaIndex
+ End If
+ End If
+
+ If (KeyCode = vbKeyF4 And (Shift And vbAltMask)) Then ' And them in case ctrl or shift was also accidentally pressed
+ ' Exit program via exit subroutine
+ KeyCode = 0
+ Shift = 0
+ ExitProgram
+ ElseIf KeyCode = vbKeyEscape Then
+ If frmProgramPreferences.optExitConfirmation(exmEscapeKeyConfirmExit).value = True Or frmProgramPreferences.optExitConfirmation(exmEscapeKeyDoNotConfirmExit).value = True Then
+ ' If Esc key is activated, exit program via exit subroutine
+ ExitProgram
+ Else
+ ' Call ExitProgram subroutine to avoid an error, but don't exit
+ End If
+ ElseIf KeyCode = vbKeyE And (Shift And vbCtrlMask) Then ' And them in case alt or shift was also accidentally pressed
+ mnuEmpirical_Click
+ KeyCode = 0: Shift = 0
+ ElseIf KeyCode = vbKeyU And (Shift And vbCtrlMask) Then ' And them in case alt or shift was also accidentally pressed
+ With frmProgramPreferences
+ If .chkAutoCopyCurrentMWT = 1 Then
+ .chkAutoCopyCurrentMWT = 0
+ Else
+ .chkAutoCopyCurrentMWT = 1
+ End If
+ End With
+ KeyCode = 0: Shift = 0
+ Else
+ Select Case KeyCode
+ Case vbKeyF1
+ ' Windows Help command
+ Case vbKeyF2
+ ' Copy current formula
+ Case vbKeyF3
+ ' Change abbreviation recognition mode
+ With frmProgramPreferences
+ If .optAbbrevType(0).value = True Then
+ .optAbbrevType(1).value = True
+ ElseIf .optAbbrevType(1).value = True Then
+ .optAbbrevType(2).value = True
+ Else
+ .optAbbrevType(0).value = True
+ End If
+ End With
+ LabelStatus
+ Case vbKeyF4
+ ' Change Case Mode
+ With frmProgramPreferences
+ If .optConvertType(0).value = True Then
+ .optConvertType(1).value = True
+ ElseIf .optConvertType(1).value = True Then
+ .optConvertType(2).value = True
+ Else
+ .optConvertType(0).value = True
+ End If
+ End With
+ LabelStatus
+ Case vbKeyF5
+ ' Erase all formulas
+ Case vbKeyF6
+ ' Erase current formula
+ Case vbKeyF7
+ ' Change caution mode
+ frmProgramPreferences.SwapCheck frmProgramPreferences.chkShowCaution
+ LabelStatus
+ Case vbKeyF8
+ ' Switch views
+ If mViewMode = vmdMultiView Then
+ SetViewMode vmdSingleView
+ Else
+ SetViewMode vmdMultiView
+ End If
+ Case vbKeyF9
+ frmProgramPreferences.SwapCheck frmProgramPreferences.chkAdvanceOnCalculate
+ LabelStatus
+ Case vbKeyF10
+ ' Reserved by windows for selecting the menus
+ Case vbKeyF11
+ ' Toggle Percent Solver
+ If Not PctSolverParams.SolverOn Then
+ TogglePercentComposition 1
+ Else
+ TogglePercentComposition 0
+ End If
+ frmMain.SetFocus
+ LabelStatus
+ Case vbKeyF12
+ ' Change standard deviation mode
+ With frmProgramPreferences
+ If .optStdDevType(0).value = True Then
+ .optStdDevType(1).value = True
+ ElseIf .optStdDevType(1).value = True Then
+ .optStdDevType(2).value = True
+ ElseIf .optStdDevType(2).value = True Then
+ .optStdDevType(3).value = True
+ Else
+ .optStdDevType(0).value = True
+ End If
+ End With
+ LabelStatus
+ Case vbKeyReturn
+ ' Ignore It
+ Case Else
+ LabelStatus
+ End Select
+ End If
+
+End Sub
+
+Public Sub SetFocusToFormulaByIndex(Optional intFormulaIndex As Integer = 0)
+ Dim eViewModeSaved As vmdViewModeConstants
+
+ ' This is necessary in case a modal form is display when this sub is called
+ On Error Resume Next
+
+ eViewModeSaved = frmMain.GetViewMode
+ If eViewModeSaved = vmdSingleView Then
+ SetViewMode vmdMultiView
+ End If
+
+ mCurrentFormulaIndex = intFormulaIndex
+ frmMain.rtfFormula(intFormulaIndex).SetFocus
+
+ If eViewModeSaved = vmdSingleView Then
+ SetViewMode vmdSingleView
+ frmMain.rtfFormulaSingle.SetFocus
+ End If
+
+End Sub
+
+Public Sub SetUsingPCGridFalse()
+ mUsingPCGrid = False
+End Sub
+
+Public Sub SetViewMode(eViewMode As vmdViewModeConstants)
+ Dim blnMultiMode As Boolean
+
+ If PctSolverParams.SolverOn And eViewMode = vmdMultiView Then
+ TogglePercentComposition psmPercentSolverOff
+ End If
+
+ If eViewMode = vmdMultiView Then blnMultiMode = True
+ mViewMode = eViewMode
+
+ mnuViewType(vmdMultiView).Checked = blnMultiMode
+ mnuViewType(vmdSingleView).Checked = Not blnMultiMode
+
+ fraMulti.Visible = blnMultiMode
+ fraSingle.Visible = Not blnMultiMode
+
+ If blnMultiMode Then
+ If frmMain.Visible = True Then rtfFormula(mCurrentFormulaIndex).SetFocus
+ Calculate True, True, True
+ Else
+ rtfFormulaSingle.TextRTF = rtfFormula(mCurrentFormulaIndex).TextRTF
+ txtMWTSingle.Text = txtMWT(mCurrentFormulaIndex).Text
+ lblFormulaSingle.Caption = lblFormula(mCurrentFormulaIndex).Caption
+
+ If frmMain.Visible = True Then rtfFormulaSingle.SetFocus
+
+ Calculate True, True, True
+ If txtMWTSingle.Text = "" Then ClearGrid grdPC
+ End If
+
+ If cChkBox(frmProgramPreferences.chkShowToolTips) Then
+ cmdNewFormula.ToolTipText = ConstructAddFormulaToolTip
+ End If
+
+ ResizeFormMain True
+
+End Sub
+
+Public Sub ShowAminoAcidNotationModule()
+ frmAminoAcidConverter.Show
+End Sub
+
+Public Sub ShowCapillaryFlowModule()
+ frmCapillaryCalcs.Show
+End Sub
+
+Public Sub ShowFormulaFinder()
+ ShowWeightModeWarningDialog True
+End Sub
+
+Public Sub ShowMoleMassConverter()
+ If rtfFormula(mCurrentFormulaIndex).Text = "" Or objMwtWin.ErrorID <> 0 Then
+ frmMMConvert.optWeightSource(1).value = True
+ End If
+
+ frmMMConvert.Show
+
+End Sub
+
+Public Sub ShowPeptideSequenceModeller()
+ ShowWeightModeWarningDialog False
+End Sub
+
+Private Sub ShowProgramOptions()
+ frmProgramPreferences.lblHiddenFormStatus = "Shown"
+ frmProgramPreferences.Show
+
+End Sub
+
+Private Sub ShowWeightModeWarningDialog(blnShow As Boolean)
+ ' If blnShow is True then the Formula Finder warning and Formula Finder
+ ' window are shown.
+
+ ' If blnShow is False then the Fragmentation Modelling window is shown
+
+ If objMwtWin.GetElementMode = emAverageMass Then
+ ' using average weights, check to warn or not
+ If cChkBox(frmProgramPreferences.chkNeverShowFormulaFinderWarning) And _
+ Not cChkBox(frmProgramPreferences.chkAlwaysSwitchToIsotopic) Then
+ ' Never warn, just leave alone
+ ElseIf cChkBox(frmProgramPreferences.chkAlwaysSwitchToIsotopic) Then
+ ' Always quick switch to isotopic weights
+ SwitchWeightMode emIsotopicMass
+ Else ' Includes case 0 specifically
+ ' If not done yet, warn user of weight-type situation, and request future action
+ ' First display the proper instructions; must do this before displaying the form modally
+ frmFinderModeWarn.DisplayInstructions blnShow
+
+ ' Now display the form (modally)
+ frmFinderModeWarn.Show vbModal
+
+ ' Examine the status of the options
+ If frmFinderModeWarn.optWeightChoice(0).value = True Or frmFinderModeWarn.optWeightChoice(1).value = True Then
+ ' Quick Switch to isotopic weights now
+ SwitchWeightMode emIsotopicMass
+ End If
+
+ ' Examine the status of the ShowAgain checkbox
+ If cChkBox(frmFinderModeWarn.chkShowAgain) Then
+ ' Don't show form again
+ With frmProgramPreferences
+ If frmFinderModeWarn.optWeightChoice(1).value = True Then
+ ' Switched to isotopic weights this time and should every time
+ .chkAlwaysSwitchToIsotopic = vbChecked ' This also checks Never show
+ Else
+ ' Stop showing this form and never automatically switch
+ .chkAlwaysSwitchToIsotopic = vbUnchecked
+ .chkNeverShowFormulaFinderWarning = vbChecked
+ End If
+ End With
+ End If
+ End If
+ End If
+
+ If blnShow Then
+ frmFinder.Show
+ Else
+ frmFragmentationModelling.Show
+ End If
+
+End Sub
+
+Public Sub EraseAllFormulas(Optional boolPromptForErase As Boolean = True)
+ Dim eResponse As VbMsgBoxResult
+ Dim intIndex As Integer
+
+ ' Erase all formulas
+ If boolPromptForErase = True Then
+ ' Display the dialog box and get user's Response.
+ eResponse = YesNoBox(LookupLanguageCaption(3780, "Are you sure you want to erase all the formulas?"), _
+ LookupLanguageCaption(3785, "Erase all Formulas"))
+ Else
+ eResponse = vbYes
+ End If
+
+ ' Evaluate the user's Response.
+ If eResponse = vbYes Then
+ With frmMain
+ For intIndex = 0 To frmMain.GetTopFormulaIndex
+ .rtfFormula(intIndex).Text = ""
+ .txtMWT(intIndex).Text = ""
+ .txtMWT(intIndex).Visible = False
+ Next intIndex
+ .rtfFormulaSingle.Text = ""
+ .txtMWTSingle.Text = ""
+ .txtMWTSingle.Visible = False
+ .SetFocusToFormulaByIndex
+
+ Debug.Assert frmMain.GetCurrentFormulaIndex = 0
+
+ .SetUsingPCGridFalse
+
+ .Calculate True
+ .LabelStatus
+ End With
+ End If
+
+End Sub
+
+Private Sub EraseCurrentFormula()
+ ' Erase current formula (F6)
+ Dim eResponse As VbMsgBoxResult
+
+ ' Display the dialog box and get user's response.
+ eResponse = YesNoBox(LookupLanguageCaption(3620, "Are you sure you want to erase the current formula?"), _
+ LookupLanguageCaption(3625, "Erase Current Formula"))
+
+ ' Evaluate the user's response.
+ If eResponse = vbYes Then
+ rtfFormula(mCurrentFormulaIndex).Text = ""
+
+ txtMWT(mCurrentFormulaIndex).Text = ""
+ txtMWT(mCurrentFormulaIndex).Visible = False
+
+ PctSolverParams.SolverOn = False ' Turn off % Solver
+ mUsingPCGrid = False
+
+ Calculate True
+ End If
+ LabelStatus
+
+End Sub
+
+Private Sub ExpandAbbreviations()
+ ' Expand abbreviations of the current formula into their elemental representations
+
+ Dim eResponse As VbMsgBoxResult
+
+ ' Display the dialog box and get user's response.
+ If (frmProgramPreferences.optExitConfirmation(exmEscapeKeyConfirmExit).value = True Or frmProgramPreferences.optExitConfirmation(exmIgnoreEscapeKeyConfirmExit).value = True) Then
+ eResponse = YesNoBox(LookupLanguageCaption(3630, "Are you sure you want to expand the abbreviations of the current formula to their elemental equivalents?"), _
+ LookupLanguageCaption(3635, "Expand Abbreviations"))
+ Else
+ eResponse = vbYes
+ End If
+
+ ' Evaluate the user's response.
+ If eResponse = vbYes Then
+ 'ExpandAbbreviations
+
+ Calculate False, True, True, mCurrentFormulaIndex, False, True
+
+ If objMwtWin.ErrorID = 0 Then
+ LabelStatus
+ Else
+ ' Do nothing; error message is being displayed
+ End If
+ End If
+
+End Sub
+
+Private Sub FormulaKeyDownHandler(ByRef KeyCode As Integer, ByRef Shift As Integer)
+ Dim blnErrorPresent As Boolean
+
+ If objMwtWin.ErrorID <> 0 Or gBlnErrorPresent Then
+ blnErrorPresent = True
+ ' Position insertion point on line of error
+ If mViewMode = vmdMultiView Then
+ rtfFormula(mCurrentFormulaIndex).SetFocus
+ Else
+ rtfFormulaSingle.SetFocus
+ End If
+ objMwtWin.ClearError
+ gBlnErrorPresent = False: gBlnStatusCaution = False
+ mErrorParams.ErrorLine = -1
+ mErrorParams.ErrorPosition = -1
+ mErrorParams.ErrorCharacter = ""
+ LabelStatus
+ End If
+
+ If (KeyCode = vbKeyDown Or KeyCode = vbKeyUp) And Not blnErrorPresent Then
+ If KeyCode = vbKeyUp Then
+ ' Up Arrow
+ mCurrentFormulaIndex = mCurrentFormulaIndex - 1
+ If mCurrentFormulaIndex < 0 Then mCurrentFormulaIndex = mTopFormulaIndex
+ End If
+
+ If KeyCode = vbKeyDown Then
+ ' Down Arrow
+ mCurrentFormulaIndex = mCurrentFormulaIndex + 1
+ If mCurrentFormulaIndex > mTopFormulaIndex Then mCurrentFormulaIndex = 0
+ End If
+
+ KeyCode = 0
+ Shift = 0
+ SetFocusToFormulaByIndex mCurrentFormulaIndex
+
+ rtfFormulaSingle.Text = rtfFormula(mCurrentFormulaIndex).Text
+ lblFormulaSingle.Caption = ConstructFormulaLabel(mCurrentFormulaIndex)
+ txtMWTSingle.Text = txtMWT(mCurrentFormulaIndex).Text
+ If Len(txtMWTSingle.Text) = 0 Then
+ txtMWTSingle.Visible = False
+ Else
+ txtMWTSingle.Visible = True
+ End If
+ LabelStatus
+
+ If mViewMode = vmdSingleView Then
+ Calculate False, True, True
+ Else
+ Calculate True, True, True
+ End If
+ End If
+
+ Select Case KeyCode
+ Case 9
+ If (Shift And vbCtrlMask) <> 0 Then
+ ' Do not allow Ctrl+Tab
+ KeyCode = 0
+ Shift = 0
+ End If
+ Case 33
+ SetViewMode vmdSingleView
+ If PctSolverParams.SolverOn Then
+ ' Page Up
+ With grdPC
+ .Row = 10
+ .SetFocus
+ .Tag = True
+ End With
+ LabelStatus
+ End If
+ Case 34
+ SetViewMode vmdSingleView
+ If PctSolverParams.SolverOn Then
+ ' Page Down
+ With grdPC
+ .Row = 0
+ .SetFocus
+ .Tag = True
+ End With
+ LabelStatus
+ End If
+ End Select
+End Sub
+
+Private Sub FormulaKeyPressHandler(ThisRTFTextBox As RichTextBox, KeyAscii As Integer)
+ Dim intSelStartSaved As Integer
+
+ If gBlnStatusCaution And objMwtWin.ErrorID = 0 Then
+ gBlnStatusCaution = False
+ If KeyAscii <> 0 Then LabelStatus
+ End If
+
+ If PctSolverParams.SolverOn And mDifferencesFormShown Then
+ With PctSolverParams
+ mDifferencesFormShown = False
+ .SolverWorking = True
+
+ Debug.Assert gBlnShowStdDevWithMass = .StdDevModeEnabledSaved
+
+ .XVal = .BestXVal
+ rtfFormula(mCurrentFormulaIndex).Tag = "Changed"
+ intSelStartSaved = rtfFormulaSingle.SelStart
+
+ Calculate False, True, True, mCurrentFormulaIndex, False, False, True, .XVal
+
+ rtfFormulaSingle.SelStart = intSelStartSaved
+ .SolverWorking = False
+ End With
+ End If
+
+ ' These are special-case keypress events that are not handled by RTFBoxKeyPressHandler
+ Select Case KeyAscii
+ Case 40 To 41, 43, 45, 48 To 57, 62, 65 To 90, 91, 93, 94, 95, 97 To 122, 123, 125
+ ' Valid Characters (see RTFBoxKeyPressHandler for details)
+ rtfFormula(mCurrentFormulaIndex).Tag = FORMULA_CHANGED
+ Case 8
+ ' Backspace; it is valid
+ rtfFormula(mCurrentFormulaIndex).Tag = FORMULA_CHANGED
+ Case vbKeyReturn
+ InitiateCalculate
+ KeyAscii = 0
+ End Select
+
+ ' Check the validity of the key using RTFBoxKeyPressHandler
+ If KeyAscii <> 0 Then RTFBoxKeyPressHandler Me, ThisRTFTextBox, KeyAscii, True
+
+End Sub
+
+Public Function GetCurrentFormulaIndex() As Integer
+ GetCurrentFormulaIndex = mCurrentFormulaIndex
+End Function
+
+Public Function GetTopFormulaIndex() As Integer
+ GetTopFormulaIndex = mTopFormulaIndex
+End Function
+
+Public Function GetViewMode() As vmdViewModeConstants
+ GetViewMode = mViewMode
+End Function
+
+Private Sub InitiateCalculate()
+ Dim lngErrorID As Long
+
+ If Not PctSolverParams.SolverOn Then
+ ' Change mouse pointer to hourglass
+ Me.MousePointer = vbHourglass
+
+ lngErrorID = Calculate(True)
+
+ ' Change mouse pointer to default
+ Me.MousePointer = vbDefault
+
+ If Len(rtfFormula(mCurrentFormulaIndex).Text) = 0 Then
+ If mViewMode = vmdMultiView Then
+ txtMWT(mCurrentFormulaIndex).Visible = False
+ txtMWT(mCurrentFormulaIndex).Text = ""
+ Else
+ txtMWTSingle.Visible = False
+ txtMWTSingle.Text = ""
+ End If
+ End If
+ Else
+ InitiatePercentSolver
+
+ 'The following is necessary to prevent grdPC from being updated just after .InitiatePercentSolver() finishes
+ mIgnoreNextGotFocus = True
+
+ End If
+
+ ' Update the status line
+ LabelStatus lngErrorID
+
+End Sub
+
+Private Sub InitializeFormWideVariables()
+
+ ' Set default Public variable values
+ mTopFormulaIndex = 0 ' Number of formulas fields displayed
+ mCurrentFormulaIndex = 0 ' Current Formula number
+
+ mCurrentFormulaIndex = 0 ' Current Forumla
+
+ mPercentCompositionGridRowCount = 11
+
+End Sub
+
+Private Sub InitiatePercentSolver()
+ ' Solve for the optimum value for x in a formula such that the
+ ' computed percent composition values match those entered by the user
+
+ Const REPEAT_COUNT_STOP_VAL = 3
+
+ Dim intXCharLoc As Integer
+ Dim blnXPresent As Boolean
+ Dim lngErrorID As Long
+
+ Dim dblXValMinimum As Double, dblXValMaximum As Double
+ Dim dblXValPreviousMax As Double, dblStepSize As Double
+ Dim dblWork As Double
+ Dim intRepeatCount As Integer, intIndex As Integer
+ Dim intColonLoc As Integer
+
+ If PctSolverParams.SolverWorking Then Exit Sub
+
+ ' Make sure an x is present after a bracket in the formula
+ intXCharLoc = InStr(rtfFormula(mCurrentFormulaIndex).Text, "[")
+ If intXCharLoc > 0 And LCase(Mid(rtfFormula(mCurrentFormulaIndex).Text, intXCharLoc + 1, 1)) = "x" Then
+ blnXPresent = True
+ End If
+
+ If Not blnXPresent Or mPctCompValues(mCurrentFormulaIndex).LockedValuesCount = 0 Then
+ ' Either x is not present in the formula after a bracket or no values locked
+ ' Calculate normally
+ mKeyPressAbortPctSolver = 2
+ Calculate True
+ Else
+ ' Percent Solver Routine
+ dblXValMinimum = 0 ' Current minimum x value
+ dblXValMaximum = 1000 ' Current maximum x value
+ mKeyPressAbortPctSolver = 1
+ intRepeatCount = 0
+
+ With PctSolverParams
+ .SolverWorking = True
+ .DivisionCount = PCT_SOLVER_INITIAL_DIVISION_COUNT
+ .blnMaxReached = False
+ .StdDevModeEnabledSaved = gBlnShowStdDevWithMass
+ .BestXSumResiduals = 10 ^ 30 ' Set .BestXSumResiduals to a really big number
+ End With
+
+ lblStatus.ForeColor = QBColor(COLOR_CALC)
+ lblStatus.Caption = " " & LookupLanguageCaption(3700, "Calculating, press any key or click the mouse to stop.")
+
+ ' Change mouse pointer to hourglass
+ Me.MousePointer = vbHourglass
+ Do
+ dblXValPreviousMax = dblXValMaximum
+ PctSolverParams.SolverCounter = -1
+ dblStepSize = ((dblXValMaximum - dblXValMinimum) / PctSolverParams.DivisionCount)
+ If dblStepSize = 0 Then dblStepSize = -1
+ PctSolverParams.IterationStopValue = PctSolverParams.DivisionCount + 1
+
+ For dblWork = dblXValMinimum To dblXValMaximum Step dblStepSize
+ DoEvents
+ If mKeyPressAbortPctSolver <> 1 Then Exit Do
+ PctSolverParams.SolverCounter = PctSolverParams.SolverCounter + 1
+ PctSolverParams.XVal = dblWork
+
+ If PctSolverParams.SolverCounter = PctSolverParams.DivisionCount / 2 Then
+ ' Update the current x value half way through the iterations
+ lngErrorID = Calculate(False, True, True, mCurrentFormulaIndex, False, False, True, PctSolverParams.XVal)
+ Else
+ lngErrorID = Calculate(False, False, True, mCurrentFormulaIndex, False, False, True, PctSolverParams.XVal)
+ End If
+ If lngErrorID <> 0 Then Exit Do
+ If PctSolverParams.SolverCounter > PctSolverParams.IterationStopValue Then Exit For
+ Next dblWork
+
+ If Not PctSolverParams.blnMaxReached And PctSolverParams.BestXVal = dblXValMaximum Then
+ ' The best X Val was dblXValMaximum, and we haven't yet found the maximum,
+ ' so set the step size to the previous maximum (essentially zooming out the search)
+ dblStepSize = dblXValPreviousMax
+ Else
+ ' The best X val was less than dblXValMaximum, so set blnMaxReached to True
+ ' The best X val must be within dblStepSize of .BestXVal
+ PctSolverParams.blnMaxReached = True
+ End If
+
+ dblXValMinimum = PctSolverParams.BestXVal - dblStepSize
+ dblXValMaximum = PctSolverParams.BestXVal + dblStepSize
+ If dblXValMinimum < 0 Then dblXValMinimum = 0
+ If dblXValMaximum > 1E+19 Then mKeyPressAbortPctSolver = 0
+
+ If Format(dblXValMaximum, "0.0000000E+00") = Format(dblXValPreviousMax, "0.0000000E+00") Then
+ intRepeatCount = intRepeatCount + 1
+ With PctSolverParams
+ ' If a value is repeated, then test 10x, 50x, or 100 times more values on the next iteration
+ Select Case intRepeatCount
+ Case 1
+ If .DivisionCount < PCT_SOLVER_INITIAL_DIVISION_COUNT * 10 Then .DivisionCount = PCT_SOLVER_INITIAL_DIVISION_COUNT * 10
+ Case 2
+ If .DivisionCount < PCT_SOLVER_INITIAL_DIVISION_COUNT * 50 Then .DivisionCount = PCT_SOLVER_INITIAL_DIVISION_COUNT * 50
+ Case 3
+ If .DivisionCount < PCT_SOLVER_INITIAL_DIVISION_COUNT * 100 Then .DivisionCount = PCT_SOLVER_INITIAL_DIVISION_COUNT * 100
+ Case Else
+ ' Leave .DivisionCount unchanged
+ End Select
+ End With
+ End If
+ If intRepeatCount = REPEAT_COUNT_STOP_VAL Or dblStepSize = 0 Then mKeyPressAbortPctSolver = 0
+ Loop
+ mKeyPressAbortPctSolver = 2
+
+ ' Change mouse pointer to default
+ MousePointer = vbDefault
+
+ If lngErrorID = 0 Then
+ PctSolverParams.XVal = PctSolverParams.BestXVal
+ rtfFormula(mCurrentFormulaIndex).Tag = "Changed"
+ lngErrorID = Calculate(False, True, True, mCurrentFormulaIndex, False, False, True, PctSolverParams.XVal)
+ Debug.Assert lngErrorID = 0
+
+ lblValueForX.ForeColor = QBColor(COLOR_SOLVER)
+ lblValueForX.Caption = LookupLanguageCaption(3710, "x is") & " " & Format(PctSolverParams.BestXVal, "#0.0######")
+
+ With frmDiff
+ .lblDiff1.Caption = ""
+ .lblDiff2.Caption = ""
+ .lblDiff3.Caption = ""
+ End With
+
+ ' Print differences
+ AddToDiffForm LookupLanguageCaption(3720, "Calculated Value"), 1
+ AddToDiffForm LookupLanguageCaption(3730, "Target"), 2
+ AddToDiffForm LookupLanguageCaption(3740, "Difference from Target"), 3
+
+ For intIndex = 1 To mPctCompValues(mCurrentFormulaIndex).TotalElements
+ With mPctCompValues(mCurrentFormulaIndex).GridCell(intIndex)
+ ' Check Locking Status
+ If .Locked Then
+ ' The element is locked
+ intColonLoc = InStr(.Text, ":")
+ AddToDiffForm Left(.Text, intColonLoc) & " " & Format(.value, "##0.0######"), 1
+ AddToDiffForm CStr(.Goal), 2
+ AddToDiffForm Format(.value - .Goal, "##0.0######"), 3
+ End If
+ End With
+ Next intIndex
+ If frmDiff.WindowState = vbMinimized Then frmDiff.WindowState = vbNormal
+ frmDiff.Show
+ mDifferencesFormShown = True
+
+ LabelStatus
+ Else
+ ' Error present. Error position was not highlighted because solver was equal to 1
+ If rtfFormulaSingle.Tag = "Highlighted" Then
+ PctSolverParams.SolverWorking = False
+ rtfFormulaSingle.Tag = ""
+ UpdateAndFormatFormulaSingle
+ End If
+ End If
+
+ gBlnShowStdDevWithMass = PctSolverParams.StdDevModeEnabledSaved
+ PctSolverParams.SolverWorking = False
+ End If
+
+End Sub
+
+
+Public Sub LabelStatus(Optional lngLocallyCaughtErrorID As Long = 0)
+
+ If objMwtWin.ErrorID = 0 And lngLocallyCaughtErrorID = 0 And Not gBlnStatusCaution And Not gBlnErrorPresent Then
+ If mUsingPCGrid = False Then
+ If PctSolverParams.SolverOn Then
+ lblStatus.ForeColor = QBColor(COLOR_DIREC)
+ lblStatus.Caption = LookupLanguageCaption(3660, "Use Page Up/Down or Up/Down arrows to move to the percents (F11 exits Percent Solver mode).")
+ End If
+ Else
+ If PctSolverParams.SolverOn Then
+ ' Percent Solver is On
+ lblStatus.ForeColor = QBColor(COLOR_DIREC)
+ lblStatus.Caption = LookupLanguageCaption(3665, "Press Enter or Click to change a percentage (F11 exits Percent Solver Mode).")
+ End If
+ End If
+ End If
+
+ If gBlnStatusCaution = True Then
+ gBlnStatusCaution = False
+ Else
+ If Not PctSolverParams.SolverOn And objMwtWin.ErrorID = 0 And lngLocallyCaughtErrorID = 0 Then
+ lblStatus.ForeColor = vbWindowText
+ lblStatus.Caption = LookupLanguageCaption(3670, "Ready")
+ Select Case objMwtWin.GetElementMode()
+ Case emIsotopicMass
+ lblStatus.Caption = lblStatus.Caption & " " & LookupLanguageCaption(3830, "(using isotopic elemental weights)")
+ Case emIntegerMass
+ lblStatus.Caption = lblStatus.Caption & " " & LookupLanguageCaption(3840, "(using integer isotopic weights)")
+ Case Else ' The default, using average atomic weights
+ ' Don't append anything; just show Ready
+ End Select
+ End If
+ End If
+
+End Sub
+
+Private Function ParseCommandLine(blnPreParseCommandLine As Boolean) As Boolean
+ ' Parses the command line
+ ' Returns true if /?, /Help, or an invalid argument was used at the command line
+ ' If blnPreParseCommandLine = True, then only checks for /X, /Z, or /D and does not
+ ' perform batch analysis
+
+ ' Declare local variables
+ Dim strArguments(15) As String
+ Dim strMessage As String, strWork As String, strCommandLine As String
+ Dim intMaxArgs As Integer, intNumArgs As Integer, intStatus As Integer, intIndex As Integer
+ Dim boolInAnArgument As Boolean
+
+ strCommandLine = Command()
+ intNumArgs = 0
+ If strCommandLine <> "" Then
+ intMaxArgs = 15
+ For intIndex = 1 To Len(strCommandLine)
+ strWork = Mid(strCommandLine, intIndex, 1)
+ ' Test for character being a blank or a tab.
+ If strWork <> " " And strWork <> vbTab Then
+ ' Neither blank nor tab. Test if we're already inside an argument.
+ If Not boolInAnArgument Then
+ ' Found the start of a new argument.
+ ' Test for too many arguments.
+ If intNumArgs = intMaxArgs Then Exit For
+ intNumArgs = intNumArgs + 1
+ boolInAnArgument = True
+ End If
+ ' Add the character to the current argument.
+ strArguments(intNumArgs) = strArguments(intNumArgs) + strWork
+ Else
+ ' Found a blank or a tab.
+ ' Set "Not in an argument" flag to FALSE.
+ boolInAnArgument = False
+ End If
+ Next intIndex
+
+ For intIndex = 1 To intNumArgs
+ strWork = strArguments(intIndex)
+ If Left(strWork, 1) = "/" Or Left(strWork, 1) = "-" Then strWork = Mid(strWork, 2)
+
+ intStatus = 0
+ Select Case UCase(Left(strWork, 1))
+ Case "F"
+ mBlnBatchProcess = True
+ If Mid(strWork, 2, 1) = ":" Then
+ mBatchProcessFilename = Mid(strWork, 3)
+ Else
+ mBatchProcessFilename = Mid(strWork, 2)
+ End If
+ Case "O"
+ If Mid(strWork, 2, 1) = ":" Then
+ mBatchProcessOutfile = Mid(strWork, 3)
+ Else
+ mBatchProcessOutfile = Mid(strWork, 2)
+ End If
+ Case "Y"
+ mBatchProcessOverwrite = True
+ Case "X"
+ gBlnWriteFilesOnDrive = False
+ Case "Z"
+ gBlnAccessFilesOnDrive = False
+ gBlnWriteFilesOnDrive = False
+ Case "D"
+ If UCase(strWork) = "DEBUG" Then
+ ' Ignore it; user is debugging software
+ Else
+ intStatus = 2
+ End If
+ Case "?", "h", "H"
+ If Not blnPreParseCommandLine Then intStatus = 2
+ Case Else
+ If Not blnPreParseCommandLine Then intStatus = 1
+ End Select
+
+ If intStatus <> 0 Then
+ strMessage = vbCrLf
+ If (Left(strWork, 1) = "?" Or Left(strWork, 1) = "H") And intStatus = 2 Then
+ strMessage = strMessage & vbCrLf & "Command line options."
+ Else
+ strMessage = strMessage & vbCrLf & "Incorrect options for command line: " & strCommandLine
+ strMessage = strMessage + vbCrLf
+ End If
+ strMessage = strMessage & vbCrLf & "Syntax: MWTWIN [/F:filename] [/O:outfile] [/Y] [/X] [/?]"
+ strMessage = strMessage + vbCrLf
+ strMessage = strMessage & vbCrLf & "Available options are:"
+ strMessage = strMessage & vbCrLf & "/F:filename to start MWTWIN in batch mode, calculating weights for compounds in filename, writing"
+ strMessage = strMessage & vbCrLf & " results to filename.out, and exiting"
+ strMessage = strMessage & vbCrLf & "/O:outfile to specify the name of the output file for batch mode"
+ strMessage = strMessage & vbCrLf & "/Y to overwrite outfile without prompting the user"
+ strMessage = strMessage & vbCrLf & "/X to prevent MWTWIN from attempting to write abbreviation, element, or default value files"
+ strMessage = strMessage & vbCrLf & "/Z to prevent MWTWIN from attempting to read or write abbreviations/elements/values files"
+ '
+ ' Secret option: /Debug to show debug prompts
+ '
+ strMessage = strMessage & vbCrLf & "/? or /Help to display this screen."
+ strMessage = strMessage + vbCrLf
+ strMessage = strMessage & vbCrLf & "See MWTWIN.CHM for more help."
+ strMessage = strMessage & vbCrLf & "Program by Matthew Monroe. Send E-Mail to Matt@alchemistmatt.com or AlchemistMatt@Yahoo.com"
+ strMessage = strMessage & vbCrLf & "WWW - http://www.alchemistmatt.com/ and http://www.come.to/alchemistmatt"
+ strMessage = strMessage + vbCrLf
+ strMessage = strMessage & vbCrLf & "This program is Freeware; distribute freely."
+
+ frmIntro.cmdExit.Visible = True
+ frmIntro.cmdOK.Visible = False
+ frmIntro.cmdExit.Default = False
+ frmIntro.cmdExit.Cancel = True
+
+ frmIntro.lblLoadStatus.Visible = True
+ frmIntro.lblLoadStatus.Caption = strMessage
+ frmIntro.MousePointer = vbDefault
+ End If
+ Next intIndex
+ End If
+
+ If intStatus <> 0 Then
+ ParseCommandLine = True
+ Else
+ ParseCommandLine = False
+ End If
+
+End Function
+
+Private Sub PercentCompGridClickHandler()
+ ' The grid was clicked
+ Const DISPLAY_PRECISION = 5
+
+ Dim strMessage As String
+ Dim intDereferencedIndex As Integer, strDefaultValue As String
+
+ If mKeyPressAbortPctSolver = 1 Then
+ ' Key pressed, so end calculations
+ mKeyPressAbortPctSolver = 2
+ End If
+
+ If cChkBox(frmProgramPreferences.chkBracketsAsParentheses) Then
+ MsgBox LookupMessage(550), vbOKOnly + vbInformation, LookupMessage(555)
+ Exit Sub
+ End If
+
+ If grdPC.Text <> "" Then
+ If grdPC.Text <> "" And Not PctSolverParams.SolverOn Then
+ TogglePercentComposition psmPercentSolverOn
+ End If
+
+ ' The message of the dialog box.
+ strMessage = LookupLanguageCaption(3650, "Set the Percent Solver target percentage of this element to a percentage. Select Reset to un-target the percentage or Cancel to ignore any changes.")
+
+ ' Display the dialog box and get user's response.
+ With frmChangeValue
+ .cmdReset.Caption = LookupLanguageCaption(9220, "&Reset")
+ .lblHiddenButtonClickStatus = BUTTON_NOT_CLICKED_YET
+ .lblInstructions.Caption = strMessage
+ .rtfValue.Visible = False
+ .txtValue.Visible = True
+ End With
+
+ intDereferencedIndex = (grdPC.Row + 1) + mPercentCompositionGridRowCount * (grdPC.Col)
+ ' Display the dialog box and get user's response.
+
+ With mPctCompValues(mCurrentFormulaIndex).GridCell(intDereferencedIndex)
+ If .Locked Then
+ strDefaultValue = Trim(CStr(.Goal))
+ Else
+ strDefaultValue = Trim(CStr(Round(.value, DISPLAY_PRECISION)))
+ End If
+ End With
+ frmChangeValue.txtValue = strDefaultValue
+
+ frmChangeValue.Show vbModal
+
+ If frmChangeValue.lblHiddenButtonClickStatus = BUTTON_NOT_CLICKED_YET Then frmChangeValue.lblHiddenButtonClickStatus = BUTTON_CANCEL
+
+ If Not frmChangeValue.lblHiddenButtonClickStatus = BUTTON_CANCEL Then
+ With mPctCompValues(mCurrentFormulaIndex)
+ If frmChangeValue.lblHiddenButtonClickStatus = BUTTON_RESET Then
+ If .GridCell(intDereferencedIndex).Locked Then
+ .GridCell(intDereferencedIndex).Locked = False
+ .LockedValuesCount = .LockedValuesCount - 1
+ End If
+ .GridCell(intDereferencedIndex).Goal = 0
+ Else
+ ' Lock intDereferencedIndex
+ If Trim(frmChangeValue.txtValue) <> Trim(CStr(Round(.GridCell(intDereferencedIndex).value, DISPLAY_PRECISION))) And frmChangeValue.txtValue <> "" Then
+ If Not .GridCell(intDereferencedIndex).Locked Then
+ .GridCell(intDereferencedIndex).Locked = True
+ .LockedValuesCount = .LockedValuesCount + 1
+ End If
+ .GridCell(intDereferencedIndex).Goal = CDblSafe(frmChangeValue.txtValue)
+ End If
+ End If
+ End With
+ UpdateGrid grdPC, mCurrentFormulaIndex
+ End If
+ End If
+End Sub
+
+Private Function PerformPercentSolverCalculations(intFormulaIndex As Integer) As Long
+ ' Returns 0 if success; Error number if error
+
+ Dim dblSumResidualsSquared As Double
+ Dim blnAtLeastOneLockedValue As Boolean
+ Dim intPCompLineIndex As Integer
+ Dim lngErrorID As Long
+
+ ' % Solver Calculations
+ dblSumResidualsSquared = 0
+ blnAtLeastOneLockedValue = False
+ For intPCompLineIndex = 1 To mPctCompValues(intFormulaIndex).TotalElements
+ With mPctCompValues(intFormulaIndex).GridCell(intPCompLineIndex)
+ If .Locked Then
+ ' Percent has been locked by user
+ blnAtLeastOneLockedValue = True
+ If .Goal > 100 Then
+ lngErrorID = 50
+ ' Set intPCompLineIndex = max value so for loop gets exitted
+ ' Cannot use an Exit For statement because inside a With statement
+ intPCompLineIndex = mPctCompValues(intFormulaIndex).TotalElements
+ Else
+ ' dblSumResidualsSquared is a sum of the residuals squared
+ ' The fit is minimized when dblSumResidualsSquared is minimized
+ dblSumResidualsSquared = dblSumResidualsSquared + (.value - .Goal) ^ 2
+ End If
+ End If
+ End With
+ Next intPCompLineIndex
+
+ If blnAtLeastOneLockedValue Then
+ If dblSumResidualsSquared <= PctSolverParams.BestXSumResiduals Then
+ PctSolverParams.BestXVal = PctSolverParams.XVal ' The x value to give this best result
+ PctSolverParams.BestXSumResiduals = dblSumResidualsSquared ' The best result for the given x value
+ End If
+ End If
+
+ If lngErrorID <> 0 Then ' Inform user of error and location
+ RaiseLabelStatusError lngErrorID
+ ResizeFormMain
+ End If
+
+ PerformPercentSolverCalculations = lngErrorID
+End Function
+
+Private Sub PositionFormControls()
+ ' Position Objects
+ lblStatus.Left = 0 ' Toolbar, remaining locs set in Resize Procedure
+
+ With fraMulti
+ .Left = 120 ' Multi Frame
+ .Top = 50
+ .Height = 1025
+ End With
+ With lblFormula(0)
+ .Left = 120 ' Formula Label
+ .Top = 350
+ End With
+ With rtfFormula(0)
+ .Left = 1080 ' Formula 1 text box
+ .Top = 240
+ .ZOrder 0
+ End With
+ With txtMWT(0)
+ .Left = 1080 ' MW= Label
+ .Top = 725
+ End With
+ With fraSingle
+ .Left = 120 ' Single Frame
+ .Top = 50
+ .Height = 4200
+ End With
+ With lblFormulaSingle
+ .Left = 120 ' Formula Label
+ .Top = lblFormula(0).Top
+ End With
+ With rtfFormulaSingle
+ .Left = 1080 ' Formula text box
+ .Top = 240
+ End With
+ With txtMWTSingle
+ .Left = 1080 ' MW Label
+ .Top = 725
+ End With
+ With grdPC
+ .Top = lblFormulaSingle.Top + 725
+ .Left = lblFormulaSingle.Left
+ '.HighLight = False
+ End With
+ cmdCalculate.Top = 150 ' Calculate button
+ cmdNewFormula.Top = 600 ' NewFormula button
+
+ With lblValueForX
+ .Top = 1050
+ .Visible = False
+ .Caption = ""
+ End With
+
+ mnuRightClick.Visible = False
+
+End Sub
+
+Private Sub PrintResults()
+ Dim intIndex As Integer
+
+ With CommonDialog1
+ .CancelError = True
+ .flags = &H8 + &H4 + &H100000 'cdlPDNoPageNums + cdlPDNoSelection + cdlPDHidePrintToFile
+ On Error Resume Next
+ .ShowPrinter
+ End With
+
+ If Err.Number <> 0 Then
+ ' No file selected from the Open File dialog box.
+ Exit Sub
+ End If
+
+ If mViewMode = vmdMultiView Then
+ ' Multi Mode
+ Printer.Print LookupLanguageCaption(3760, "Molecular Weight Calculator Results")
+ Printer.Print ""
+ For intIndex = 0 To mTopFormulaIndex
+ Printer.Print lblFormula(intIndex + 1).Caption; Tab(15); rtfFormula(intIndex).Text
+ Printer.Print Tab(15); txtMWT(intIndex).Text
+ Printer.Print ""
+ Next intIndex
+ Else
+ ' Single Mode
+ Printer.Print lblFormula(mCurrentFormulaIndex + 1).Caption; ":"; Tab(15); rtfFormulaSingle.Text
+ Printer.Print Tab(15); txtMWTSingle.Text
+ Printer.Print ""
+ For intIndex = 1 To mPctCompValues(mCurrentFormulaIndex).TotalElements
+ Printer.Print mPctCompValues(mCurrentFormulaIndex).GridCell(intIndex).Text
+ Next intIndex
+ End If
+
+ Printer.EndDoc
+
+End Sub
+
+Public Sub ResizeFormMain(Optional blnEnlargeToMinimums As Boolean = False, Optional blnUpdateGridPC As Boolean = True)
+ Dim intIndex As Integer, minWidth As Single, minHeight As Single
+ Dim lngPreferredTop As Long, lngMinimumTop As Long, lngCompareVal As Long
+ Dim blnAllowingShrinking As Boolean, blnWidthsAdjusted As Boolean
+ Dim lngDesiredValue As Long
+
+On Error GoTo ResizeFormMainErrorHandler
+
+ If Me.WindowState = vbMinimized Then Exit Sub
+
+ Me.ScaleMode = vbTwips
+ blnAllowingShrinking = True
+
+ With frmMain
+ If .WindowState = vbNormal Then
+ If mnuStayOnTop.Tag = FORM_STAY_ON_TOP_NEWLY_ENABLED And minWidth < mCurrentFormWidth Then
+ minWidth = mCurrentFormWidth
+ End If
+ If mViewMode = vmdMultiView Then
+ If minWidth < 5000 Then minWidth = 5000
+ Else
+ If minWidth < 6300 Then minWidth = 6300
+ End If
+
+ If .Width < minWidth Then
+ If blnEnlargeToMinimums Then
+ .Width = minWidth
+ Else
+ blnAllowingShrinking = False
+ End If
+ End If
+
+ If mViewMode = vmdMultiView Then
+ minHeight = MAIN_HEIGHT + mTopFormulaIndex * FORMULA_OFFSET_AMOUNT - 1500
+ Else
+ minHeight = MAIN_HEIGHT_SINGLE
+ End If
+
+ If frmProgramPreferences.lblHiddenDefaultsLoadedStatus = "DefaultsLoaded" Then
+ If minHeight < MAIN_HEIGHT And cChkBox(frmProgramPreferences.chkShowQuickSwitch) Then
+ minHeight = MAIN_HEIGHT
+ End If
+ End If
+
+ If mnuStayOnTop.Tag = FORM_STAY_ON_TOP_NEWLY_ENABLED And minHeight < mCurrentFormHeight Then
+ minHeight = mCurrentFormHeight
+ End If
+
+ If .Height < minHeight Then
+ If blnEnlargeToMinimums Then
+ .Height = minHeight
+ End If
+ End If
+
+ If .Width > Screen.Width Then
+ .Width = Screen.Width
+ End If
+ End If
+ End With
+ mnuStayOnTop.Tag = ""
+
+ If frmMain.WindowState <> vbMinimized Then
+ lngDesiredValue = frmMain.ScaleWidth - cmdCalculate.Width - 500
+ If mViewMode = vmdMultiView Then
+ ' Position Objects in Multi View
+ If blnAllowingShrinking Or fraMulti.Width < lngDesiredValue Then
+ blnWidthsAdjusted = True
+ fraMulti.Width = lngDesiredValue
+ For intIndex = 0 To mTopFormulaIndex
+ rtfFormula(intIndex).Width = fraMulti.Width - 1200 ' Formula intIndex text box
+ txtMWT(intIndex).Width = rtfFormula(intIndex).Width
+ Next intIndex
+ End If
+ Else
+ ' Position Objects in Single View
+ If blnAllowingShrinking Or fraSingle.Width < lngDesiredValue Then
+ blnWidthsAdjusted = True
+ fraSingle.Width = lngDesiredValue
+ rtfFormulaSingle.Width = fraSingle.Width - 1200 ' FormulaSingle text box
+ txtMWTSingle.Width = rtfFormulaSingle.Width
+ End If
+ End If
+
+ If blnUpdateGridPC Then
+ UpdateGrid grdPC, mCurrentFormulaIndex
+ End If
+
+ lngPreferredTop = frmMain.ScaleHeight - lblStatus.Height
+ If mViewMode = vmdMultiView Then
+ lngMinimumTop = fraMulti.Top + fraMulti.Height + 60
+ If optElementMode(2).Visible Then
+ lngCompareVal = optElementMode(2).Top + optElementMode(2).Height
+ If lngMinimumTop < lngCompareVal Then
+ lngMinimumTop = lngCompareVal
+ End If
+ End If
+ Else
+ lngMinimumTop = fraSingle.Top + fraSingle.Height + 60
+ End If
+
+ If lngPreferredTop < lngMinimumTop Then lngPreferredTop = lngMinimumTop
+ lblStatus.Top = lngPreferredTop
+ If lblStatus.Width < minWidth Then
+ lblStatus.Width = minWidth
+ Else
+ lblStatus.Width = Me.ScaleWidth
+ End If
+
+ If blnAllowingShrinking Or blnWidthsAdjusted Then
+ With frmMain
+ lblStatus.Width = .ScaleWidth ' Status Bar
+ lblStatus.Width = .ScaleWidth ' Status Bar
+ cmdCalculate.Left = .Width - cmdCalculate.Width - 350 ' Calculate Button
+ cmdNewFormula.Left = cmdCalculate.Left ' New Formula Button
+ lblValueForX.Left = cmdCalculate.Left
+ lblQuickSwitch.Left = .Width - cmdCalculate.Width - 250
+ End With
+
+ For intIndex = 0 To 2
+ optElementMode(intIndex).Left = lblQuickSwitch.Left
+ Next intIndex
+ End If
+ End If
+
+ Exit Sub
+
+ResizeFormMainErrorHandler:
+ Debug.Assert False
+ GeneralErrorHandler "frmMain|ResizeFormMain", Err.Number, Err.Description
+
+End Sub
+
+Private Sub RestoreDefaultValues()
+ Dim eResponse As VbMsgBoxResult
+
+ ' Display the dialog box and get user's response.
+ eResponse = MsgBox(LookupLanguageCaption(3640, "Restoring the default values and formulas will clear the current formulas. Are you sure you want to do this?"), vbYesNo + vbQuestion + vbDefaultButton2, _
+ LookupLanguageCaption(3645, "Restoring Values and Formulas"))
+
+ If eResponse = vbYes Then
+ ' Change cursor to be on formula 1
+ SetFocusToFormulaByIndex 0
+
+ EraseAllFormulas False
+ SwitchWeightMode emAverageMass
+
+ LoadValuesAndFormulas True
+
+ lblStatus.ForeColor = vbWindowText
+ lblStatus.Caption = LookupLanguageCaption(3770, "Default values and formulas restored.")
+ Calculate True
+ End If
+
+End Sub
+
+Private Sub RTFHighlightCharacter(intWorkLine As Integer, intWorkCharLoc As Integer)
+
+ Dim strOriginalText As String, strNewText As String
+
+ If mViewMode = vmdMultiView Then
+ strOriginalText = rtfFormula(intWorkLine).Text
+
+ ' Mark the error place with a % sign
+ strNewText = Left(strOriginalText, intWorkCharLoc - 1) & "%" & Mid(strOriginalText, intWorkCharLoc)
+ If Right(strNewText, 1) = " " Then strNewText = Left(strNewText, Len(strNewText) - 1)
+ rtfFormula(intWorkLine).Text = strNewText
+ rtfFormula(intWorkLine).Tag = FORMULA_HIGHLIGHTED
+ Else
+ strOriginalText = rtfFormulaSingle.Text
+
+ ' Mark the error place with a % sign
+ strNewText = Left(strOriginalText, intWorkCharLoc - 1) & "%" & Mid(strOriginalText, intWorkCharLoc)
+ If Right(strNewText, 1) = " " Then strNewText = Left(strNewText, Len(strNewText) - 1)
+ rtfFormulaSingle.Text = strNewText
+ rtfFormulaSingle.Tag = FORMULA_HIGHLIGHTED
+ End If
+End Sub
+
+Public Sub ShowHideQuickSwitch(blnShowControl As Boolean)
+ Dim intIndex As Integer, eElementWeightType As emElementModeConstants
+
+ lblQuickSwitch.Visible = blnShowControl
+
+ For intIndex = 0 To 2
+ optElementMode(intIndex).Visible = blnShowControl
+ Next intIndex
+
+ eElementWeightType = objMwtWin.GetElementMode()
+
+ If eElementWeightType > 0 And _
+ (optElementMode(0).value = True And eElementWeightType <> emAverageMass Or _
+ optElementMode(1).value = True And eElementWeightType <> emIsotopicMass Or _
+ optElementMode(2).value = True And eElementWeightType <> emIntegerMass) Then
+ optElementMode(eElementWeightType - 1).value = True
+ End If
+
+End Sub
+
+Private Sub TogglePercentComposition(ePercentSolverMode As psmPercentSolverModeConstants)
+ Dim intIndex As Integer
+
+ If mnuPercentType(psmPercentSolverOff).Checked = True And _
+ ePercentSolverMode = psmPercentSolverOn Then
+ ' Turn Percent Solver On (if not on yet)
+ If Not cChkBox(frmProgramPreferences.chkBracketsAsParentheses) Then
+ PctSolverParams.SolverOn = True
+
+ PctSolverParams.XVal = 1
+ PctSolverParams.BestXVal = 1
+
+ SetViewMode vmdSingleView
+ lblValueForX.Visible = True
+ lblValueForX.ForeColor = vbWindowText
+ lblValueForX.Caption = LookupLanguageCaption(3750, "% Solver On")
+ For intIndex = 0 To 3
+ If frmProgramPreferences.optStdDevType(intIndex).value = True Then
+ mStdDevModSaved = intIndex
+ Exit For
+ End If
+ Next intIndex
+
+ If mStdDevModSaved = 1 Or mStdDevModSaved = 2 Then
+ frmProgramPreferences.optStdDevType(0).value = True
+ End If
+
+ cmdNewFormula.Enabled = False
+ Else
+ MsgBox LookupMessage(550), vbOKOnly + vbInformation, LookupMessage(555)
+ End If
+ Else
+ If ePercentSolverMode = psmPercentSolverOff Then
+ ' Turn Percent Solver Off
+ PctSolverParams.SolverOn = False
+
+ lblValueForX.Visible = False
+ lblValueForX.Caption = ""
+ frmProgramPreferences.optStdDevType(mStdDevModSaved).value = True
+ End If
+ cmdNewFormula.Enabled = True
+ End If
+
+ mnuPercentType(psmPercentSolverOff).Checked = Not PctSolverParams.SolverOn
+ mnuPercentType(psmPercentSolverOn).Checked = PctSolverParams.SolverOn
+
+ LabelStatus
+
+End Sub
+
+Private Sub ToggleStayOnTop()
+
+ ' Add or remove the check mark from the menu.
+ mnuStayOnTop.Checked = Not mnuStayOnTop.Checked
+
+ With frmMain
+ mCurrentFormWidth = .Width
+ mCurrentFormHeight = .Height
+ End With
+
+ mnuStayOnTop.Tag = FORM_STAY_ON_TOP_NEWLY_ENABLED
+
+ Me.ScaleMode = vbTwips
+
+ WindowStayOnTop Me.hwnd, mnuStayOnTop.Checked, Me.ScaleX(Me.Left, vbTwips, vbPixels), Me.ScaleY(Me.Top, vbTwips, vbPixels), Me.ScaleX(Me.Width, vbTwips, vbPixels), Me.ScaleY(Me.Height, vbTwips, vbPixels)
+
+End Sub
+
+Public Sub UpdateAndFormatFormula(Index As Integer, Optional blnForceUpdate As Boolean = False)
+ Dim lngSaveLoc As Integer
+
+ If mViewMode = vmdMultiView Or blnForceUpdate Then
+ ' Only format if the multi-view frame is visible
+
+ If rtfFormula(Index).Tag = FORMULA_HIGHLIGHTED Then
+ rtfFormula(Index).Tag = FORMULA_CHANGED
+ Else
+ lngSaveLoc = rtfFormula(Index).SelStart
+
+ If blnForceUpdate And mViewMode = vmdSingleView Then
+ fraSingle.Visible = False
+ fraMulti.Visible = True
+ End If
+
+ If mErrorParams.ErrorID <> 0 Then
+ rtfFormula(Index).TextRTF = objMwtWin.TextToRTF(rtfFormula(Index).Text, False, True, True, mErrorParams.ErrorID)
+ Else
+ rtfFormula(Index).TextRTF = objMwtWin.TextToRTF(rtfFormula(Index).Text, False, True)
+ End If
+ rtfFormula(Index).SelStart = lngSaveLoc
+
+ If blnForceUpdate And mViewMode = vmdSingleView Then
+ fraSingle.Visible = True
+ fraMulti.Visible = False
+ End If
+
+ If rtfFormula(Index).Tag = "" Then
+ ' Only set as changed if it's blank
+ ' Must preserve recalc and highlighted tags
+ rtfFormula(Index).Tag = FORMULA_CHANGED
+ End If
+ End If
+ If mViewMode = vmdMultiView Then
+ rtfFormulaSingle.TextRTF = rtfFormula(Index).TextRTF
+ End If
+ End If
+
+End Sub
+
+Private Sub UpdateAndFormatFormulaSingle()
+ Dim intSaveLoc As Integer
+ Static blnUpdating As Boolean
+
+ If blnUpdating Then Exit Sub
+ blnUpdating = True
+
+ If mViewMode = vmdSingleView Then
+ ' Only format if the single-view frame is visible
+ If rtfFormulaSingle.Tag = FORMULA_HIGHLIGHTED Then
+ rtfFormulaSingle.Tag = FORMULA_CHANGED
+ rtfFormula(mCurrentFormulaIndex).Tag = FORMULA_CHANGED
+ Else
+ intSaveLoc = rtfFormulaSingle.SelStart
+
+ rtfFormulaSingle.TextRTF = objMwtWin.TextToRTF(rtfFormulaSingle.Text)
+ rtfFormulaSingle.SelStart = intSaveLoc
+
+ If rtfFormulaSingle.Tag = "" Then
+ ' Only set as changed if it's blank
+ ' Must preserve recalc and highlighted tags
+ rtfFormulaSingle.Tag = FORMULA_CHANGED
+ rtfFormula(mCurrentFormulaIndex).Tag = FORMULA_CHANGED
+ End If
+ End If
+ rtfFormula(mCurrentFormulaIndex).TextRTF = rtfFormulaSingle.TextRTF
+ End If
+
+ blnUpdating = False
+
+End Sub
+
+Private Sub UpdateGrid(ThisGrid As MSFlexGrid, intFormulaIndex As Integer)
+
+ Dim intIndex As Integer, intCurrentRow As Integer, intCurrentColumn As Integer
+ Dim intColsNeeded As Integer
+ Dim intRowSaved As Integer, intColumnSaved As Integer
+ Dim lngWidthForTwoColumns As Long, lngWidthIncrement As Long
+ Dim intCharLoc As Integer
+ Dim lngDesiredValue As Long
+ Dim strNewText As String
+
+ ' First, set grid size and rows, then guess at number of columns
+
+ With fraSingle
+ lngDesiredValue = Me.ScaleHeight - fraSingle.Top - lblStatus.Height - 120
+ If lngDesiredValue < 3000 Then lngDesiredValue = 3000
+ .Height = lngDesiredValue
+ End With
+
+ With ThisGrid
+ .Visible = False
+ .Width = rtfFormulaSingle.Width + lblFormulaSingle.Width
+
+ lngDesiredValue = fraSingle.Height - .Top - 360
+ If lngDesiredValue < 0 Then lngDesiredValue = 0
+ .Height = lngDesiredValue
+
+ mPercentCompositionGridRowCount = .Height / .RowHeight(0) - 1
+ If mPercentCompositionGridRowCount < 5 Then mPercentCompositionGridRowCount = 5
+ .Rows = mPercentCompositionGridRowCount
+
+ intRowSaved = .Row
+ intColumnSaved = .Col
+
+ If Not gBlnShowStdDevWithMass Or objMwtWin.StdDevMode = smShort Then
+ lngWidthForTwoColumns = 6000
+ lngWidthIncrement = 2000
+ Else
+ lngWidthForTwoColumns = 7000
+ lngWidthIncrement = 2500
+ End If
+
+ If .Width < lngWidthForTwoColumns Then
+ .Cols = 2
+ Else
+ .Cols = RoundToNearest(.Width / lngWidthIncrement, 1, False)
+ End If
+
+ For intIndex = 0 To .Cols - 1
+ Select Case .Cols
+ Case 2
+ .ColWidth(intIndex) = (.Width - 120) / (.Cols) ' 30 twips is gridline width and/or height
+ Case 3
+ .ColWidth(intIndex) = (.Width - 40) / (.Cols) ' 30 twips is gridline width and/or height
+ Case Else
+ .ColWidth(intIndex) = (.Width - 40) / (.Cols) ' 30 twips is gridline width and/or height
+ End Select
+ Next intIndex
+
+ .ScrollBars = flexScrollBarHorizontal
+
+ ' Now, enlarge grid if necessary
+ intColsNeeded = CIntSafe(mPctCompValues(intFormulaIndex).TotalElements / mPercentCompositionGridRowCount)
+ If mPctCompValues(intFormulaIndex).TotalElements Mod mPercentCompositionGridRowCount > 0 Then
+ intColsNeeded = intColsNeeded + 1
+ End If
+ If intColsNeeded > .Cols Then
+ .Cols = intColsNeeded
+ ' FrmMain.Width
+ For intIndex = 1 To .Cols - 1
+ .ColWidth(intIndex) = .ColWidth(0)
+ Next intIndex
+ .Height = (TextHeight("123456789gT") + 33) * (.Rows + 1) + 255 ' 255 is Scroll Bar Height
+ Else
+ .Height = (TextHeight("123456789gT") + 33) * (.Rows + 1)
+ End If
+
+ .LeftCol = 0
+ .TopRow = 0
+
+ ' Update mKeyPressAbortPctSolver if necessary
+ If mKeyPressAbortPctSolver = 3 Then mKeyPressAbortPctSolver = 0
+ If mKeyPressAbortPctSolver = 2 Then mKeyPressAbortPctSolver = 3
+
+ End With
+
+ ' Finally, copy the data in .GridCell().Text into the grid
+ intCurrentRow = 0
+ intCurrentColumn = 0
+ For intIndex = 1 To mPctCompValues(intFormulaIndex).TotalElements
+ With mPctCompValues(intFormulaIndex).GridCell(intIndex)
+ If .Locked And PctSolverParams.SolverOn And mKeyPressAbortPctSolver = 0 Then
+ intCharLoc = InStr(.Text, ":")
+ If intCharLoc > 0 Then
+ strNewText = SpacePad(Left(.Text, intCharLoc), 4) & CStr(.Goal)
+ Else
+ ' Colon not found; this is unexpected
+ Debug.Assert False
+ strNewText = SpacePad(Left(.Text, 3), 4) & CStr(.Goal)
+ End If
+ Else
+ strNewText = .Text
+ End If
+ ThisGrid.TextMatrix(intCurrentRow, intCurrentColumn) = strNewText
+ End With
+
+ intCurrentRow = intCurrentRow + 1
+ If intCurrentRow = ThisGrid.Rows Then
+ intCurrentRow = 0
+ intCurrentColumn = intCurrentColumn + 1
+ End If
+ Next intIndex
+
+ With grdPC
+ ' Erase remaining cells
+ For intIndex = mPctCompValues(intFormulaIndex).TotalElements + 1 To .Rows * .Cols
+ .TextMatrix(intCurrentRow, intCurrentColumn) = ""
+ intCurrentRow = intCurrentRow + 1
+ If intCurrentRow = ThisGrid.Rows Then
+ If intCurrentColumn <> .Cols - 1 Then
+ intCurrentRow = 0
+ intCurrentColumn = intCurrentColumn + 1
+ Else
+ ' Last cell reached, for loop will exit on next intIndex
+ ' Just keep cell in same spot
+ End If
+ End If
+ Next intIndex
+
+ ' Show the grid again
+ .Visible = True
+
+ ' Re-position cursor
+ If intRowSaved >= .Rows Then intRowSaved = 0
+ If intColumnSaved >= .Cols Then intColumnSaved = 0
+
+ .Row = intRowSaved
+ .Col = intColumnSaved
+
+ End With
+
+End Sub
+
+Private Sub cmdCalculate_Click()
+ InitiateCalculate
+End Sub
+
+Private Sub cmdNewFormula_Click()
+ AddNewFormulaWrapper
+End Sub
+
+Private Sub Form_Click()
+ If mKeyPressAbortPctSolver = 1 Then
+ ' Key pressed, so end calculations
+ mKeyPressAbortPctSolver = 2
+ End If
+End Sub
+
+Private Sub Form_Deactivate()
+ If Not mIgnoreNextGotFocus Then
+ Calculate True, True, True, 0, False, False, False, 1, False
+ End If
+End Sub
+
+Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
+ ' Since KeyPreview is true for frmMain, the Form_Keydown event gets called before the
+ ' control_keydown event
+ ' Useful for catching F1 and Ctrl+A keys
+
+ FormWideKeyDownHandler KeyCode, Shift
+' lblStatus.Caption = lblStatus.Caption & " " & Str(keycode) ' Useful for finding a key's Keycode
+
+End Sub
+
+Private Sub Form_Load()
+
+ Dim eResponse As VbMsgBoxResult
+ Dim blnSuccess As Boolean
+ Dim blnShowDebugPrompts As Boolean
+ Dim lngErrorID As Long, blnProceedWithLoad As Boolean
+ Dim intInstances As Integer
+
+ On Error GoTo ErrorHandler
+
+ ' Uncomment the following to Debug
+ If InStr(UCase(Command()), "/DEBUG") Then
+ eResponse = MsgBox("Track load progress?", vbYesNo + vbDefaultButton2, "Track Progress")
+ If eResponse = vbYes Then blnShowDebugPrompts = True
+ End If
+
+ If blnShowDebugPrompts Then MsgBox "Initialize globals"
+ InitializeFormWideVariables
+ InitializeGlobalVariables blnShowDebugPrompts
+
+ ' Set frmMain.lblHiddenFormStatus to "Loading"
+ ' Used by Functions to prevent certain tasks from occuring while program is loading
+ frmMain.lblHiddenFormStatus = "Loading"
+
+ If blnShowDebugPrompts Then MsgBox "Show intro form"
+ frmIntro.Show
+ frmIntro.MousePointer = vbHourglass
+ DoEvents
+
+ If blnShowDebugPrompts Then MsgBox "Set default options"
+ ' Load default options and set default menu checkmarks
+ SetDefaultOptions
+
+ If blnShowDebugPrompts Then MsgBox "Set default values and formulas"
+ SetDefaultValuesAndFormulas False, blnShowDebugPrompts
+
+ If blnShowDebugPrompts Then MsgBox "Load string constants"
+ ' Load String Constants into MSFlexGrids on frmStrings
+ MemoryLoadAllStringConstants
+
+ If blnShowDebugPrompts Then MsgBox "Size and center App"
+ ' Put app in center of screen horizontally, and upper fourth vertically
+ SizeAndCenterWindow Me, cWindowUpperThird, 6300, MAIN_HEIGHT
+
+ If blnShowDebugPrompts Then MsgBox "Position controls"
+ ' Position frmMain controls
+ PositionFormControls
+
+ If blnShowDebugPrompts Then MsgBox "Pre-Parse command line"
+ ' Preliminarily parse the command line
+ ParseCommandLine True
+
+ If blnShowDebugPrompts Then MsgBox "Load forms FinderModeWarn and IonMatchOptions"
+ ' Load various forms that need to be loaded (but not shown) so Language-specific
+ ' captions can be set
+ Load frmFinderModeWarn
+ Load frmIonMatchOptions
+ Load frmDtaTxtFileBrowser
+
+ frmFinderModeWarn.Visible = False
+ frmIonMatchOptions.Visible = False
+ frmDtaTxtFileBrowser.Visible = False
+ DoEvents
+
+ If blnShowDebugPrompts Then MsgBox "Load program options from disk"
+ ' Load Default Program Options (from disk, or memory if not found)
+ LoadDefaultOptions False, blnShowDebugPrompts
+
+ ' If gCurrentLanguage is not English, then attempt to load correct
+ ' language file
+ If LCase(gCurrentLanguageFileName) <> LCase(DEFAULT_LANGUAGE_FILENAME) Then
+ If blnShowDebugPrompts Then MsgBox "Load language file from " & gCurrentLanguageFileName
+ blnSuccess = LoadLanguageSettings(gCurrentLanguageFileName, gCurrentLanguage)
+ If Not blnSuccess Then
+ ' If alternate langauge file could not be loaded, then revert to English
+ gCurrentLanguageFileName = DEFAULT_LANGUAGE_FILENAME
+ gCurrentLanguage = "English"
+ SaveSingleDefaultOption "Language", gCurrentLanguage
+ SaveSingleDefaultOption "LanguageFile", gCurrentLanguageFileName
+ End If
+ Else
+ ' Set blnSuccess to False to assure Menu items get loaded from memory
+ blnSuccess = False
+ End If
+
+ If blnShowDebugPrompts Then MsgBox "Reset menu captions"
+ If Not blnSuccess Then
+ ResetMenuCaptions True
+ End If
+
+ ' Now that Language Information has been loaded, check if other copies
+ ' of the Molecular Weight Calculator are running. If they are, prompt user
+ ' about continuing
+
+ ' Assume OK to proceed
+ blnProceedWithLoad = True
+ intInstances = CountInstancesOfApp(Me)
+ If intInstances > 1 Then
+ eResponse = YesNoBox(LookupLanguageCaption(5350, "The Molecular Weight Calculator is already running. Are you sure you want to start another copy?"), LookupLanguageCaption(5355, "Already Running"))
+ If eResponse <> vbYes Then blnProceedWithLoad = False
+ End If
+
+ If Not blnProceedWithLoad Then
+ ' Exit program, but do not save values or default options
+ gNonSaveExitApp = True
+ Else
+ If blnShowDebugPrompts Then MsgBox "Parse command line"
+ ' Modify defaults based on command line
+ gCommandLineInstructionsDisplayed = ParseCommandLine(False)
+
+ If gCommandLineInstructionsDisplayed Then
+ ' Also set gNonSaveExitApp to true so frmMain won't auto unload, allowing user
+ ' To read message on frmIntro
+ gNonSaveExitApp = True
+ Else
+ If blnShowDebugPrompts Then MsgBox "Set weight mode"
+ SwitchWeightMode emAverageMass
+
+ ' Load elements from disk
+ LoadElements 0, True
+
+ ' Now that elements are loaded, need to populate grid on Edit Elements form with elements
+ frmEditElem.PopulateGrid
+
+ If blnShowDebugPrompts Then MsgBox "Load abbreviations from disk"
+ ' Load all abbreviations (from disk, or memory if not found)
+ LoadAbbreviations False
+
+ ' Show the main form even if gBlnLoadStatusOK = False
+ frmMain.Show
+
+ If mBlnBatchProcess Then
+ BatchProcessTextFile mBatchProcessFilename, mBatchProcessOutfile, mBatchProcessOverwrite
+ 'lblStatus.Caption = "Completed processing " & mBatchProcessFilename
+ End
+ End If
+
+ If blnShowDebugPrompts Then MsgBox "Load default values from disk"
+ ' Load Default Values (from disk or memory)
+ LoadValuesAndFormulas False
+
+ mCurrentFormulaIndex = 0
+ lblFormulaSingle.Caption = lblFormula(mCurrentFormulaIndex).Caption
+
+ ' Set frmMain.lblHiddenFormStatus to "Done Loading"
+ frmMain.lblHiddenFormStatus = "Done Loading"
+
+ ' This info is used by the Form_Resize event
+ frmProgramPreferences.lblHiddenDefaultsLoadedStatus = "DefaultsLoaded"
+ ResizeFormMain True
+
+ If blnShowDebugPrompts Then MsgBox "ReCalculate"
+
+ ' ReCalculate
+ lngErrorID = Calculate(True)
+
+ ' Fill in Status message
+ LabelStatus lngErrorID
+
+ ' Reset mouse pointer
+ frmIntro.MousePointer = vbDefault
+
+ ' Hide Intro box if no problems
+ If gBlnLoadStatusOK Then
+ If blnShowDebugPrompts Then MsgBox "Unload intro form"
+ Unload frmIntro
+
+ ' Set focus to rtfFormula(0) only if gBlnLoadStatusOK = True
+ SetFocusToFormulaByIndex
+ End If
+
+ ' Display default form if request by user (and not Main form)
+ ShowDefaultFormAtLoad
+
+ If blnShowDebugPrompts Then MsgBox "Done Loading"
+ End If
+ End If
+
+ProgStart:
+ Exit Sub
+
+ErrorHandler:
+ Close
+ GeneralErrorHandler "frmMain|Form_Load", Err.Number, Err.Description
+ Resume ProgStart
+
+End Sub
+
+Private Sub Form_Resize()
+ ResizeFormMain
+End Sub
+
+Private Sub Form_Unload(Cancel As Integer)
+ Dim intIndex As Integer
+
+ ' Set the following two variables to 2 to stop the Formula finder and Pct Solver (if running)
+ gKeyPressAbortFormulaFinder = 2
+ mKeyPressAbortPctSolver = 2
+
+ If cChkBox(frmProgramPreferences.chkAutosaveValues) And Not gNonSaveExitApp Then
+ SaveDefaultOptions
+ SaveValuesAndFormulas
+ If objMwtWin.GetElementMode <> gElementWeightTypeInFile Then
+ ' User quick switched the elementweight type, but it hasn't been saved
+ ' Save it Now
+ SaveElements
+ End If
+ End If
+
+ ' frmStrings and frmSetValue Refuse to unload using the code in UnloadAllForms
+ ' Manually unload if loaded
+ If IsLoaded("frmSetValue") Then Unload frmSetValue
+ If IsLoaded("frmStrings") Then Unload frmStrings
+
+ ' Unload the objCompounds()
+ For intIndex = 0 To MAX_FORMULAS
+ Set objCompounds(intIndex) = Nothing
+ Next intIndex
+
+ ' Unload the objMwtWin class
+ Set objMwtWin = Nothing
+
+ UnloadAllForms Me.Name
+
+ End
+
+End Sub
+
+Private Sub fraSingle_Click()
+ If mKeyPressAbortPctSolver = 1 Then
+ ' Key pressed, so end calculations
+ mKeyPressAbortPctSolver = 2
+ End If
+
+End Sub
+
+Private Sub grdPC_GotFocus()
+ mUsingPCGrid = True
+End Sub
+
+Private Sub grdPC_KeyDown(KeyCode As Integer, Shift As Integer)
+
+ If mKeyPressAbortPctSolver = 1 Then
+ ' Key pressed, so end calculations
+ mKeyPressAbortPctSolver = 2
+ End If
+
+ Select Case KeyCode
+ Case vbKeyReturn
+ grdPC_Click
+ Case vbKeyPageUp, vbKeyUp
+ ' Page Up and up arrow
+ If grdPC.Row = 0 Then
+ rtfFormulaSingle.SetFocus
+ mUsingPCGrid = False
+ LabelStatus
+ End If
+ Case vbKeyPageDown, vbKeyDown
+ ' Page Down and down arrow
+ If grdPC.Row = 10 Then
+ rtfFormulaSingle.SetFocus
+ mUsingPCGrid = False
+ LabelStatus
+ End If
+ End Select
+
+End Sub
+
+Private Sub grdPC_LostFocus()
+ mUsingPCGrid = False
+End Sub
+
+Private Sub lblFormulaSingle_Click()
+ If mKeyPressAbortPctSolver = 1 Then
+ ' Key pressed, so end calculations
+ mKeyPressAbortPctSolver = 2
+ End If
+End Sub
+
+Private Sub txtMWT_Change(Index As Integer)
+ txtMWTSingle.Text = txtMWT(Index).Text
+End Sub
+
+Private Sub txtMWTSingle_Click()
+ If mKeyPressAbortPctSolver = 1 Then
+ ' Key pressed, so end calculations
+ mKeyPressAbortPctSolver = 2
+ End If
+End Sub
+
+Private Sub lblStatus_Click()
+ If mKeyPressAbortPctSolver = 1 Then
+ ' Key pressed, so end calculations
+ mKeyPressAbortPctSolver = 2
+ End If
+End Sub
+
+Private Sub lblStatus_DblClick()
+ ZoomLine lblStatus.Caption
+End Sub
+
+Private Sub lblValueForX_Click()
+ If mKeyPressAbortPctSolver = 1 Then
+ ' Key pressed, so end calculations
+ mKeyPressAbortPctSolver = 2
+ End If
+End Sub
+
+Private Sub mnuAbout_Click()
+ frmAboutBox.Show vbModal
+End Sub
+
+Private Sub mnuAminoAcidNotationConverter_Click()
+ ShowAminoAcidNotationModule
+End Sub
+
+Private Sub mnuChooseLanguage_Click()
+ frmChooseLanguage.Show
+End Sub
+
+Private Sub mnuIsotopicDistribution_Click()
+ ShowIsoDistributionModeller
+End Sub
+
+Private Sub mnuPeptideSequenceFragmentation_Click()
+ ShowPeptideSequenceModeller
+End Sub
+
+Private Sub mnuDisplayIsotopicDistribution_Click()
+ DisplayIsotopicDistribution mCurrentFormulaIndex
+End Sub
+
+Private Sub mnuCalculateFile_Click()
+ ' Call the BatchProcessing subroutine
+ BatchProcessTextFile
+End Sub
+
+Private Sub mnuCalculator_Click()
+ frmCalculator.Show
+End Sub
+
+Private Sub mnuCapillaryFlow_Click()
+ ShowCapillaryFlowModule
+End Sub
+
+Private Sub mnuChangeFont_Click()
+
+ frmChangeFont.Show
+
+End Sub
+
+Private Sub mnuCopy_Click()
+ CopyRoutine Me, True
+End Sub
+
+Private Sub mnuCopyCurrent_Click()
+ DuplicateCurrentFormula
+End Sub
+
+Private Sub mnuCopyMWT_Click()
+ CopyCurrentMWT False
+End Sub
+
+Private Sub mnuCopyPC_Click()
+ CopyPC
+End Sub
+
+Private Sub mnuCopyRTF_Click()
+ CopyRTF
+End Sub
+
+Private Sub mnuCut_Click()
+ CutRoutine Me, True
+End Sub
+
+Private Sub mnuDelete_Click()
+ ' Delete selected text.
+ frmMain.ActiveControl.SelText = ""
+End Sub
+
+Private Sub mnuEdit_Click()
+ EditMenuCheck
+End Sub
+
+Private Sub mnuEditAbbrev_Click()
+ EditAbbreviations
+End Sub
+
+Private Sub mnuEditElements_Click()
+ EditElements
+End Sub
+
+Private Sub mnuEmpirical_Click()
+ ConvertToEmpirical
+End Sub
+
+Private Sub mnuEraseAll_Click()
+ EraseAllFormulas True
+End Sub
+
+Private Sub mnuEraseCurrent_Click()
+ EraseCurrentFormula
+End Sub
+
+Private Sub mnuExit_Click()
+ ExitProgram
+End Sub
+
+Private Sub mnuExpandAbbrev_Click()
+ ExpandAbbreviations
+End Sub
+
+Private Sub mnuFinder_Click()
+ ShowFormulaFinder
+End Sub
+
+Private Sub mnuMMConvert_Click()
+ ShowMoleMassConverter
+End Sub
+
+Private Sub mnuOverview_Click()
+ On Error GoTo ErrHandler
+
+ 'hWnd is a Long defined elsewhere to be the window handle
+ 'that will be the parent to the help window.
+ Dim hwndHelp As Long
+
+ 'The return value is the window handle of the created help window.
+ hwndHelp = HtmlHelp(hwnd, App.HelpFile, HH_DISPLAY_TOPIC, 0)
+
+ Exit Sub
+
+ErrHandler:
+ ' User pressed cancel button
+ Exit Sub
+
+End Sub
+
+Private Sub mnuPaste_Click()
+ PasteRoutine Me, True
+End Sub
+
+Private Sub mnuPercentType_Click(Index As Integer)
+ If Index = psmPercentSolverOn Then
+ TogglePercentComposition psmPercentSolverOn
+ Else
+ TogglePercentComposition psmPercentSolverOff
+ End If
+End Sub
+
+Private Sub mnuPrint_Click()
+ PrintResults
+End Sub
+
+Private Sub ToggleToolTips()
+ frmProgramPreferences.SwapCheck frmProgramPreferences.chkShowToolTips
+End Sub
+
+Private Sub mnuProgramOptions_Click()
+ ShowProgramOptions
+End Sub
+
+Private Sub mnuRestoreValues_Click()
+ RestoreDefaultValues
+End Sub
+
+Private Sub mnuRightClickCopy_Click()
+ CopyRoutine Me, True
+End Sub
+
+Private Sub mnuRightClickCut_Click()
+ CutRoutine Me, True
+End Sub
+
+Private Sub mnuRightClickDelete_Click()
+ frmMain.ActiveControl.SelText = ""
+End Sub
+
+Private Sub mnuRightClickPaste_Click()
+ PasteRoutine Me, True
+End Sub
+
+Private Sub mnuRightClickSelectAll_Click()
+ frmMain.ActiveControl.SelStart = 0
+ frmMain.ActiveControl.SelLength = Len(frmMain.ActiveControl.Text)
+End Sub
+
+Private Sub mnuRightClickUndo_Click()
+ If TypeOf frmMain.ActiveControl Is RichTextBox Or _
+ TypeOf frmMain.ActiveControl Is VB.TextBox Then
+ frmMain.ActiveControl.Text = GetMostRecentTextBoxValue()
+ End If
+End Sub
+
+Private Sub mnuSaveValues_Click()
+ SaveValuesAndFormulas
+End Sub
+
+Private Sub mnuShowTips_Click()
+ ToggleToolTips
+End Sub
+
+Private Sub mnuStayOnTop_Click()
+ ToggleStayOnTop
+End Sub
+
+Private Sub mnuViewType_Click(Index As Integer)
+ If Index = vmdSingleView Then
+ SetViewMode vmdSingleView
+ Else
+ SetViewMode vmdMultiView
+ End If
+
+End Sub
+
+Private Sub grdPC_Click()
+ PercentCompGridClickHandler
+End Sub
+
+Private Sub optElementMode_Click(Index As Integer)
+ ' Elementweightmode = 1 means average weights, 2 means isotopic, and 3 means integer
+ Dim eNewWeightMode As emElementModeConstants
+
+ eNewWeightMode = Index + 1
+
+ If eNewWeightMode <> objMwtWin.GetElementMode Then
+ SwitchWeightMode eNewWeightMode
+ End If
+
+End Sub
+
+Private Sub rtfFormula_Change(Index As Integer)
+ UpdateAndFormatFormula Index
+End Sub
+
+Private Sub rtfFormula_GotFocus(Index As Integer)
+ lblFormulaSingle.Caption = ConstructFormulaLabel(Index)
+ mCurrentFormulaIndex = Index
+ SetMostRecentTextBoxValue rtfFormula(Index).Text
+End Sub
+
+Private Sub rtfFormula_KeyDown(Index As Integer, KeyCode As Integer, Shift As Integer)
+ ' Look for arrow keys or Enter key
+ FormulaKeyDownHandler KeyCode, Shift
+End Sub
+
+Private Sub rtfFormula_KeyPress(Index As Integer, KeyAscii As Integer)
+ ' Make sure the key is valid
+ FormulaKeyPressHandler rtfFormula(Index), KeyAscii
+End Sub
+
+Private Sub rtfFormula_MouseUp(Index As Integer, Button As Integer, Shift As Integer, x As Single, y As Single)
+ If Button = vbRightButton Then
+ ShowPopupRightClickMenu Me, rtfFormula(Index), True
+ End If
+End Sub
+
+Private Sub rtfFormulaSingle_Change()
+ UpdateAndFormatFormulaSingle
+End Sub
+
+Private Sub rtfFormulaSingle_Click()
+ If mKeyPressAbortPctSolver = 1 Then
+ ' Key pressed, so end calculations
+ mKeyPressAbortPctSolver = 2
+ End If
+End Sub
+
+Private Sub rtfFormulaSingle_GotFocus()
+ If Not mIgnoreNextGotFocus Then
+ If Not gBlnErrorPresent Then
+ UpdateGrid grdPC, mCurrentFormulaIndex
+ End If
+
+ ' The .SetFocus event can cause an error if a form is shown modally
+ ' Must use Resume Next error handling to avoid an error
+ On Error Resume Next
+ rtfFormulaSingle.SetFocus
+ On Error GoTo 0
+
+ SetMostRecentTextBoxValue rtfFormulaSingle.Text
+ Else
+ mIgnoreNextGotFocus = False
+ End If
+End Sub
+
+Private Sub rtfFormulaSingle_KeyDown(KeyCode As Integer, Shift As Integer)
+ FormulaKeyDownHandler KeyCode, Shift
+End Sub
+
+Private Sub rtfFormulaSingle_KeyPress(KeyAscii As Integer)
+ FormulaKeyPressHandler rtfFormulaSingle, KeyAscii
+End Sub
diff --git a/mwtwin.frx b/mwtwin.frx
new file mode 100644
index 0000000..94746c3
Binary files /dev/null and b/mwtwin.frx differ
diff --git a/mwtwin.hhc b/mwtwin.hhc
new file mode 100644
index 0000000..af76d2b
--- /dev/null
+++ b/mwtwin.hhc
@@ -0,0 +1,360 @@
+
+
+
+
+
+
+