├── images └── lorikeet │ ├── zoom_in.png │ ├── zoom_out.png │ ├── header_scan.png │ ├── header_text.png │ ├── slider_handle.png │ ├── header_lorikeet.png │ └── lorikeet_text_small.png ├── original_image_files ├── lorikeet.ai └── lorikeet.psd ├── test ├── index.html └── test.js ├── LICENSE ├── css ├── lorikeet.css └── jquery-ui-1.13.0.slider.min.css ├── js ├── aminoacid.js ├── ion.js ├── jquery.flot.selection.js ├── excanvas.min.js ├── jquery-ui-1.13.0.slider.min.js └── peptide.js ├── html ├── example_itraq2.html ├── example_use_neutral_loss.html ├── example_itraq.html ├── example_use.html └── example_user_reporter_ions.html └── README /images/lorikeet/zoom_in.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UWPR/Lorikeet/HEAD/images/lorikeet/zoom_in.png -------------------------------------------------------------------------------- /images/lorikeet/zoom_out.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UWPR/Lorikeet/HEAD/images/lorikeet/zoom_out.png -------------------------------------------------------------------------------- /images/lorikeet/header_scan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UWPR/Lorikeet/HEAD/images/lorikeet/header_scan.png -------------------------------------------------------------------------------- /images/lorikeet/header_text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UWPR/Lorikeet/HEAD/images/lorikeet/header_text.png -------------------------------------------------------------------------------- /original_image_files/lorikeet.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UWPR/Lorikeet/HEAD/original_image_files/lorikeet.ai -------------------------------------------------------------------------------- /images/lorikeet/slider_handle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UWPR/Lorikeet/HEAD/images/lorikeet/slider_handle.png -------------------------------------------------------------------------------- /original_image_files/lorikeet.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UWPR/Lorikeet/HEAD/original_image_files/lorikeet.psd -------------------------------------------------------------------------------- /images/lorikeet/header_lorikeet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UWPR/Lorikeet/HEAD/images/lorikeet/header_lorikeet.png -------------------------------------------------------------------------------- /images/lorikeet/lorikeet_text_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UWPR/Lorikeet/HEAD/images/lorikeet/lorikeet_text_small.png -------------------------------------------------------------------------------- /test/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Unit Tests 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 University of Washington 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /css/lorikeet.css: -------------------------------------------------------------------------------- 1 | /*$LastChangedDate$*/ 2 | /*$LastChangedBy$*/ 3 | /*$LastChangedRevision$*/ 4 | 5 | @media print { 6 | .noprint { 7 | display:none; 8 | } 9 | } 10 | 11 | div.lorikeet { 12 | width:100%; 13 | background-color: #FFFFFF; 14 | color: #000000; 15 | font-family: "Trebuchet MS",Arial,sans-serif; 16 | font-size: 10pt; 17 | font-style: normal; 18 | margin: 0; 19 | padding: 0; 20 | } 21 | 22 | div.lorikeet div.bar { 23 | background-color:#F5F5DC; 24 | color:black; 25 | } 26 | div.lorikeet td { 27 | background-color:#FFFFEF; 28 | border:1px solid black; 29 | padding: 5px; 30 | } 31 | 32 | div.lorikeet td.optionCell { 33 | background-color: white; 34 | border: 1px dotted #666666; 35 | padding: 5px; 36 | margin:5px; 37 | } 38 | 39 | div.lorikeet .link { 40 | text-decoration: underline; 41 | cursor:pointer; 42 | color:sienna; 43 | } 44 | div.lorikeet .font_small { 45 | font-size: 8pt; 46 | } 47 | div.lorikeet .zoom_out_link { 48 | background-image: url('../images/lorikeet/zoom_out.png'); 49 | background-repeat: no-repeat; 50 | width:20px; 51 | height:20px; 52 | cursor:pointer; 53 | } 54 | div.lorikeet .zoom_in_link { 55 | background-image: url('../images/lorikeet/zoom_in.png'); 56 | background-repeat: no-repeat; 57 | width:20px; 58 | height:20px; 59 | cursor:pointer; 60 | } 61 | 62 | 63 | /* THE FOLLOWING STYLES ARE FOR THE TABLE DISPLAYING THE SEQUENCE AND FRAGMENT ION MASS */ 64 | div.lorikeet .ionTable { 65 | border-collapse:collapse; 66 | border-color:#DDDDDD; 67 | } 68 | div.lorikeet .ionTable th { 69 | background-color:#BDB76B; 70 | border: 1px solid #666666; 71 | } 72 | div.lorikeet .ionTable td { 73 | border: 1px solid #666666; 74 | text-align: center; 75 | background-color:#FFFFFF; 76 | font-size: 8pt; 77 | } 78 | 79 | /* style for a cell containing a residue from the sequence */ 80 | div.lorikeet .ionTable td.seq { 81 | font-weight: bold; 82 | background-color:#BDB76B; 83 | } 84 | 85 | /* style for cell containing a modified residue */ 86 | div.lorikeet .ionTable td.modified{ 87 | background-color:gold; 88 | } 89 | 90 | /* style for cell containing the fragment indices */ 91 | div.lorikeet .ionTable td.numCell { 92 | background-color:#F5F5DC; 93 | color:#777777; 94 | } 95 | 96 | 97 | /* style for cell containing a fragment m/z that matches a peak in the scan */ 98 | div.lorikeet .ionTable td.matchIon { 99 | font-weight:bold; 100 | opacity:0.8; 101 | filter: alpha(opacity=80); /*For IE*/ 102 | -moz-opacity:0.8; /*Old Mozilla browsers*/ 103 | color:white; 104 | } 105 | 106 | 107 | /* THE FOLLOWING STYLES ARE FOR THE TABLE DISPLAYING VARIABLE MODIFICATIONS */ 108 | div.lorikeet .varModsTable { 109 | border-collapse:collapse; 110 | } 111 | 112 | div.lorikeet .varModsTable td { 113 | border: 0px; 114 | text-align: left; 115 | font-size: 10pt; 116 | padding: 1px 5px 1px 0px; 117 | } -------------------------------------------------------------------------------- /js/aminoacid.js: -------------------------------------------------------------------------------- 1 | // $LastChangedDate$ 2 | // $LastChangedBy$ 3 | // $LastChangedRevision$ 4 | 5 | function AminoAcid(aaCode, aaShortName, aaName, monoMass, avgMass) { 6 | this.code = aaCode; 7 | this.shortName = aaShortName; 8 | this.name = aaName; 9 | this.mono = monoMass; 10 | this.avg = avgMass; 11 | 12 | this.get = _getAA; 13 | } 14 | 15 | AminoAcid.A = new AminoAcid ("A", "Ala", "Alanine", 71.037113805, 71.0779); 16 | AminoAcid.R = new AminoAcid ("R", "Arg", "Arginine", 156.101111050, 156.18568); 17 | AminoAcid.N = new AminoAcid ("N", "Asn", "Asparagine", 114.042927470, 114.10264); 18 | AminoAcid.D = new AminoAcid ("D", "Asp", "Aspartic Acid", 115.026943065, 115.0874); 19 | AminoAcid.C = new AminoAcid ("C", "Cys", "Cysteine", 103.009184505, 103.1429); 20 | AminoAcid.E = new AminoAcid ("E", "Glu", "Glutamine", 129.042593135, 129.11398); 21 | AminoAcid.Q = new AminoAcid ("Q", "Gln", "Glutamic Acid", 128.058577540, 128.12922); 22 | AminoAcid.G = new AminoAcid ("G", "Gly", "Glycine", 57.021463735, 57.05132); 23 | AminoAcid.H = new AminoAcid ("H", "His", "Histidine", 137.058911875, 137.13928); 24 | AminoAcid.I = new AminoAcid ("I", "Ile", "Isoleucine", 113.084064015, 113.15764); 25 | AminoAcid.L = new AminoAcid ("L", "Leu", "Leucine", 113.084064015, 113.15764); 26 | AminoAcid.K = new AminoAcid ("K", "Lys", "Lysine", 128.094963050, 128.17228); 27 | AminoAcid.M = new AminoAcid ("M", "Met", "Methionine", 131.040484645, 131.19606); 28 | AminoAcid.F = new AminoAcid ("F", "Phe", "Phenylalanine", 147.068413945, 147.17386); 29 | AminoAcid.P = new AminoAcid ("P", "Pro", "Proline", 97.052763875, 97.11518); 30 | AminoAcid.S = new AminoAcid ("S", "Ser", "Serine", 87.032028435, 87.0773); 31 | AminoAcid.T = new AminoAcid ("T", "Thr", "Threonine", 101.047678505, 101.10388); 32 | AminoAcid.W = new AminoAcid ("W", "Trp", "Tryptophan", 186.079312980, 186.2099); 33 | AminoAcid.Y = new AminoAcid ("Y", "Tyr", "Tyrosine", 163.063328575, 163.17326); 34 | AminoAcid.V = new AminoAcid ("V", "Val", "Valine", 99.068413945, 99.13106); 35 | 36 | 37 | AminoAcid.aa = []; 38 | AminoAcid.aa["A"] = AminoAcid.A; 39 | AminoAcid.aa["R"] = AminoAcid.R; 40 | AminoAcid.aa["N"] = AminoAcid.N; 41 | AminoAcid.aa["D"] = AminoAcid.D; 42 | AminoAcid.aa["C"] = AminoAcid.C; 43 | AminoAcid.aa["E"] = AminoAcid.E; 44 | AminoAcid.aa["Q"] = AminoAcid.Q; 45 | AminoAcid.aa["G"] = AminoAcid.G; 46 | AminoAcid.aa["H"] = AminoAcid.H; 47 | AminoAcid.aa["I"] = AminoAcid.I; 48 | AminoAcid.aa["L"] = AminoAcid.L; 49 | AminoAcid.aa["K"] = AminoAcid.K; 50 | AminoAcid.aa["M"] = AminoAcid.M; 51 | AminoAcid.aa["F"] = AminoAcid.F; 52 | AminoAcid.aa["P"] = AminoAcid.P; 53 | AminoAcid.aa["S"] = AminoAcid.S; 54 | AminoAcid.aa["T"] = AminoAcid.T; 55 | AminoAcid.aa["W"] = AminoAcid.W; 56 | AminoAcid.aa["Y"] = AminoAcid.Y; 57 | AminoAcid.aa["V"] = AminoAcid.V; 58 | 59 | AminoAcid.get = _getAA; 60 | 61 | function _getAA(aaCode) { 62 | if(AminoAcid.aa[aaCode]) 63 | return AminoAcid.aa[aaCode]; 64 | else 65 | return new AminoAcid(aaCode, aaCode, 0.0, 0.0); 66 | } 67 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | // aminoacid.js tests 2 | test("AminoAcid properties", function() { 3 | var aaM = AminoAcid.get("M"); 4 | equal(aaM.name, "Methionine"); 5 | equal(aaM.shortName, "Met"); 6 | equal(aaM.mono, 131.040484645); 7 | equal(aaM.avg, 131.19606); 8 | equal(aaM.code, "M"); 9 | }); 10 | 11 | test("Invalid AminoAcid", function() { 12 | var aaInvalid = AminoAcid.get("B"); 13 | equal(aaInvalid.code, "B"); 14 | equal(aaInvalid.shortName, "B"); 15 | }); 16 | 17 | // peptide.js tests 18 | var UNMODIFIED_TEST_PEPTIDE = new Peptide("AGCDE", [], [], 0.0, 0.0); 19 | var STATIC_TEST_MODIFICATION = new Modification(AminoAcid.get("C"), 57.0); 20 | var STATIC_MODIFIED_PEPTIDE = new Peptide("AGCDE", [STATIC_TEST_MODIFICATION], [], 0.0, 0.0); 21 | var VARIABLE_TEST_MODIFICATION = new VariableModification(3, 57.0, AminoAcid.get("C")); 22 | var VARIABLE_MODFIFIED_PEPTIDE = new Peptide("AGCDE", [], [VARIABLE_TEST_MODIFICATION], 0.0, 0.0); 23 | var TEST_N_TERM_MODIFICATION = 12.0; 24 | var TEST_C_TERM_MODIFICATION = 15.0; 25 | var TERMINAL_MODIFIED_PEPTIDE = new Peptide("AGCDE", [], [], TEST_N_TERM_MODIFICATION, TEST_C_TERM_MODIFICATION); 26 | 27 | test("Modification properties", function() { 28 | equal(STATIC_TEST_MODIFICATION.aa.code, "C"); 29 | equal(STATIC_TEST_MODIFICATION.modMass, 57.0); 30 | }); 31 | 32 | test("VariableModification properties", function() { 33 | equal(VARIABLE_TEST_MODIFICATION.aa.code, "C"); 34 | equal(VARIABLE_TEST_MODIFICATION.position, 3); 35 | equal(VARIABLE_TEST_MODIFICATION.modMass, 57.0); 36 | }) 37 | 38 | test("getSeqMass for simple peptide", function() { 39 | var peptide = UNMODIFIED_TEST_PEPTIDE; 40 | var mass1 = peptide.getSeqMassMono(1, "n"); 41 | equal(mass1, AminoAcid.get("A").mono); 42 | var mass2 = peptide.getSeqMassAvg(3, "c"); 43 | equal(mass2, AminoAcid.get("D").avg + AminoAcid.get("E").avg); 44 | }); 45 | 46 | test("getSeqMass for peptide with static modification", function() { 47 | var peptide = STATIC_MODIFIED_PEPTIDE; 48 | // subsequence without modification 49 | var mass1 = peptide.getSeqMassMono(2, "n"); 50 | equal(mass1, AminoAcid.get("A").mono + AminoAcid.get("G").mono); 51 | // subsequence with modification 52 | var mass2 = peptide.getSeqMassMono(3, "n"); 53 | equal(mass2, AminoAcid.get("A").mono + AminoAcid.get("G").mono + AminoAcid.get("C").mono + 57.0); 54 | }); 55 | 56 | test("getSeqMass for peptide with var modification", function() { 57 | var peptide = VARIABLE_MODFIFIED_PEPTIDE; 58 | var mass = peptide.getSeqMassAvg(3, "n"); 59 | equal(mass, AminoAcid.get("A").avg + AminoAcid.get("G").avg + AminoAcid.get("C").avg + 57.0); 60 | }); 61 | 62 | test("getSeqMass for peptide with terminal modfications", function() { 63 | var peptide = TERMINAL_MODIFIED_PEPTIDE; 64 | var mass1 = peptide.getSeqMassMono(1, "n"); 65 | equal(mass1, AminoAcid.get("A").mono + TEST_N_TERM_MODIFICATION); 66 | var mass2 = peptide.getSeqMassAvg(4, "c"); 67 | equal(mass2, AminoAcid.get("E").avg + TEST_C_TERM_MODIFICATION); 68 | }); 69 | 70 | test("getNeutralMassMono for peptide with terminal modifications", function() { 71 | var mass = VARIABLE_MODFIFIED_PEPTIDE.getNeutralMassMono(); 72 | var expectedMass = AminoAcid.get("A").mono + 73 | AminoAcid.get("G").mono + 74 | AminoAcid.get("C").mono + 75 | 57.0 + 76 | AminoAcid.get("D").mono + 77 | AminoAcid.get("E").mono + 78 | Ion.MASS_H_1 + 79 | Ion.MASS_O_16 + Ion.MASS_H_1; 80 | equal(mass, expectedMass); 81 | }); 82 | 83 | test("getNeutralMassAvg for peptide with variable modifications", function() { 84 | var mass = TERMINAL_MODIFIED_PEPTIDE.getNeutralMassAvg(); 85 | var expectedMass = AminoAcid.get("A").avg + 86 | AminoAcid.get("G").avg + 87 | AminoAcid.get("C").avg + 88 | AminoAcid.get("D").avg + 89 | AminoAcid.get("E").avg + 90 | TEST_N_TERM_MODIFICATION + 91 | TEST_C_TERM_MODIFICATION + 92 | Ion.MASS_H + 93 | Ion.MASS_O + Ion.MASS_H; 94 | equal(mass, expectedMass); 95 | }); 96 | 97 | // ion.js tests 98 | test("Ion properties", function() { 99 | var bIon = Ion.get("b", 2); 100 | equal(bIon.charge, 2); 101 | equal(bIon.type, "b"); 102 | equal(bIon.term, "n"); 103 | equal(bIon.label, "b2+"); 104 | }); 105 | 106 | test("getSeriesIon for b", function() { 107 | var bIon = Ion.get("b", 3); 108 | var seriesIonB = Ion.getSeriesIon(bIon, UNMODIFIED_TEST_PEPTIDE, 2, "mono"); 109 | equal(seriesIonB.charge, 3); 110 | equal(seriesIonB.term, "n"); 111 | var mass = AminoAcid.get("A").mono + 112 | AminoAcid.get("G").mono; 113 | var mz = (mass + (3 * Ion.MASS_PROTON) ) / 3; 114 | equal(seriesIonB.mz, mz); 115 | }); 116 | 117 | test("getSeriesIon for y", function() { 118 | var yIon = Ion.get("y", 1); 119 | var seriesIonY = Ion.getSeriesIon(yIon, UNMODIFIED_TEST_PEPTIDE, 2, "avg"); 120 | equal(seriesIonY.charge, 1); 121 | equal(seriesIonY.term, "c"); 122 | var mass = AminoAcid.get("C").avg + 123 | AminoAcid.get("D").avg + 124 | AminoAcid.get("E").avg + 125 | 2 * Ion.MASS_H + Ion.MASS_O; 126 | var mz = (mass + (1 * Ion.MASS_PROTON) ) / 1; 127 | }); 128 | 129 | test("getWaterLossMz", function() { 130 | function example() { 131 | this.mz = 100.0; 132 | this.charge = 2; 133 | return this; 134 | } 135 | var neutralMass = (100.0 * 2) - (2 * Ion.MASS_PROTON); 136 | var mass = neutralMass - (Ion.MASS_H * 2 + Ion.MASS_O); 137 | var expectedMz = (mass + (2 * Ion.MASS_PROTON)) / 2 138 | var waterLoss = NeutralLoss.WaterLoss(); 139 | var lossCombination = new LossCombination(); 140 | lossCombination.addLoss(waterLoss); 141 | equal(Ion.getIonMzWithLoss(example(), lossCombination, 'avg'), expectedMz); 142 | }); 143 | 144 | test("getAmmoniaLossMz", function() { 145 | function example() { 146 | this.mz = 50.0; 147 | this.charge = 3; 148 | return this; 149 | } 150 | var neutralMass = (50.0 * 3) - (3 * Ion.MASS_PROTON); 151 | var mass = neutralMass - (Ion.MASS_H * 3 + Ion.MASS_N); 152 | var expectedMz = (mass + (3 * Ion.MASS_PROTON)) / 3; 153 | var ammoniaLoss = NeutralLoss.AmmoniaLoss(); 154 | var lossCombination = new LossCombination(); 155 | lossCombination.addLoss(ammoniaLoss); 156 | equal(Ion.getIonMzWithLoss(example(), lossCombination, 'avg'), expectedMz); 157 | }); 158 | 159 | -------------------------------------------------------------------------------- /html/example_itraq2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | COMET/Lorikeet Spectrum Viewer 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | To label reporter ions such as iTRAQ and TMT, set labelReporters to true in the options. 24 |
labelReporters: true
25 |
26 |
27 | This example is from PeptideAtlas 28 |
29 | 30 |
31 | 32 | 217 | 218 |
219 |
220 | 221 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Lorikeet Reference 2 | ===================================== 3 | 4 | Lorikeet is a JQuery plugin to render MS/MS spectra annotated with fragment ions. 5 | The spectrum is interactive with zoom capabilities, selection of fragment types, 6 | switching annotations on and off etc. The plugin can, optionally, also render a MS1 7 | spectrum below the MS/MS spectrum, with options to highlight the precursor peak 8 | for the MS/MS scan, as well as any other precursor peaks. 9 | 10 | 11 | Files required for the plugin to work: 12 | 1. specview.js -- this file has the plugin's rendering functions 13 | 2. aminoacid.js 14 | 3. ion.js 15 | 4. peptide.js 16 | 5. jquery.flot.js -- this is a modified version of the flot (http://code.google.com/p/flot/) 17 | plotting library for JQuery. It is base off of subversion revision 263. 18 | 6. jquery.flot.selection.js -- part of the flot package. This is also from revision 263. 19 | 20 | 21 | Other Dependencies: 22 | 1. JQuery core library (tested with version 3.5.1) 23 | 2. JQuery UI library (tested with version 1.13.0. Lorikeet uses only the slider widget) 24 | 25 | A NOTE ABOUT Internet Explorer 26 | --------------------------------------- 27 | The flot JQuery plugin makes use of the canvas element of HTML5. This element is not 28 | supported in the current versions of IE. It should be supported in IE9. 29 | For the viewer to work on IE the ExplorerCanvas script has to be included in the page. 30 | This script brings the canvas functionality to IE. 31 | 32 | <%-- Only load the excanvas.min.js if it is IE 8 or lower. IE 8 does not support HTML5 so this is a way to have HTML5 canvas support --%> 33 | 34 | 35 | 36 | 37 | Examples: 38 | --------------------------------------- 39 | Please see the following examples of using the Lorikeet plugin in a html page: 40 | 1. example_use.html -- MS/MS spectrum only 41 | 2. example_use2.html -- MS/MS and MS1 spectra 42 | 43 | 44 | Stylesheet: 45 | --------------------------------------- 46 | The stylesheet lorikeet.css contains the necessary styling for the Lorikeet plugin. 47 | jquery-ui-1.13.0.slider.min.css contains the JQuery UI Slider specific CSS 48 | 49 | 50 | Usage: 51 | --------------------------------------- 52 | The following fragment has to be included in the HTML file where the viewer should be 53 | displayed. The id of the div can be any id that is unique on the page. 54 |
55 | 56 | The following fragment has to be included in a script element on the page. This is 57 | typically included in the window.onload function. $("#lorikeet") is the JQuery way 58 | of referring to a DOM element with the id "lorikeet". 59 | $("#lorikeet").specview(options); 60 | 61 | 62 | API Documentation: 63 | --------------------------------------- 64 | Lorikeet has only a single method that renders the viewer! 65 | 66 | specview(options) 67 | 68 | options is a set of key/value pairs that configure and provide data to the viewer. 69 | 70 | Options: 71 | { 72 | "sequence": null, 73 | "staticMods": [], 74 | "variableMods": [], 75 | "ntermMod": 0, // additional mass to be added to the n-term 76 | "ctermMod": 0, // additional mass to be added to the c-term 77 | "peaks": [], 78 | "massError": 0.5, 79 | "scanNum": null, 80 | "fileName": null, 81 | "charge": null, 82 | "precursorMz": null, 83 | "ms1peaks": null, 84 | "ms1scanLabel": null, 85 | "precursorPeaks": null, 86 | "precursorPeakClickFn": null, 87 | "zoomMs1": false, 88 | "width": 750, // width of the ms/ms plot 89 | "height": 450, // height of the ms/ms plot 90 | "extraPeakSeries": [], 91 | "showIonTable": true, 92 | "showViewingOptions": true, 93 | "showOptionsTable": true, 94 | "showSequenceInfo": true, 95 | "labelImmoniumIons": true, 96 | "labelPrecursorPeak": true, 97 | "labelReporters": false, 98 | "showMassErrorPlot": false, 99 | "massErrorPlotDefaultUnit": 'Da' 100 | } 101 | 102 | The required options(key/value pairs) are: 103 | ------------------------------------------ 104 | 1. sequence: the sequence of the peptide 105 | 2. peaks: an array of peaks in the MS/MS scan. 106 | Example: [ [602.17,209860.34], [691.67,33731.58],[871.42,236841.11],[888.50,1005389.56] ] 107 | 108 | Other options (not required): 109 | ---------------------------- 110 | 1. charge: The charge of the precursor. This information is displayed at the top of the scan. 111 | 2. precursorMz: The m/z of the precursor. This information is displayed at the top of the scan. 112 | This value is required for labeling the precursor peak in the MS1 scan if 113 | it is rendered, and also marking the precursor peak in the MS/MS scan. 114 | 3. scanNum: The scan number of the MS/MS scan. This information is displayed at the top of the scan. 115 | 4. fileName: Name of the file that contains the MS/MS scan. This information is displayed at the top of the scan. 116 | 5. staticMods: An array of static modifications. Each modification is a set of key/value pairs. 117 | Example: [{"modMass":57.0,"aminoAcid":"C"}]; 118 | 4. variableMods: An array of variable modifications. Each modification is a set of key/value pairs. 119 | Example: [ {index: 14, modMass: 16.0, aminoAcid: 'M'} ] // index is the index (1-based) 120 | // of the modification in the sequence. 121 | 5. ntermMod: additional mass to be added to the N-terminus. 122 | 6. ctermMod: additional mass to be added to the C-terminus. 123 | 7. massError: mass tolerance used for labeling peaks in the MS/MS scan. 124 | 8. ms1Peaks: peaks in the MS1 scan. Format is the same as the "peaks" option. 125 | 9. precursorPeaks: Any precursor peaks in the MS1 scan that will be highlighted. 126 | Same format is the same as the "peaks" option. 127 | 10. zoomMs1: If the value is "true" the MS1 scan, upon initialization, is zoomed around the peak 128 | that is the closest match to the "precursorMz" option. Default is "false". 129 | 11. ms1scanLabel: Label for the MS1 scan. 130 | 12. precursorPeakClickFn: This is the function that will be called when a precursor peak is clicked. 131 | 13. width: width of the MS/MS plot area. Default is 750. 132 | 14. height: height of the MS/MS plot area. Default is 450. 133 | 15. extraPeakSeries: An array of user defined peak series. Each series should be a set of key value pairs. 134 | Example: {data: [[10.0,2.0],[20.0,3.0]], color: "#00aa00",labelType: 'mz',labels: ['one','two']} 135 | "labelType" should not be used if custom labels are provided as value to the "labels" key. 136 | If "labelType" is 'mz', custom labels are ignored. 137 | 16. showIonTable: Show a table with theoretical fragment ion masses to the right of the annotated MS/MS scan. 138 | Default is true. 139 | 17. showViewingOptions: Show zooming and other options at the bottom of the MS/MS scan. Default is true. 140 | 18. showOptionsTable: Show a table with all the available options to the left of the annotated MS/MS scan. 141 | Default is true. 142 | 19. showSequenceInfo: Show sequence, m/z, filename, scan number, charge etc. at the top of the MS/MS scan. 143 | Default is true. 144 | 20. labelImmoniumIons: Label immonium ions in the MS/MS scan. Default is true. 145 | Example file: example_precursor_immonium.html 146 | 21. labelPrecursorPeaks: Label precursor ion if found in the MS/MS scan. Default is true. 147 | Example file: example_precursor_immonium.html 148 | 22. labelReporters: Label reporter ions such as iTRAQ and TMT. Default is false. 149 | Example file: example_itraq.html 150 | 23. showMassErrorPlot: Display a plot showing the mass errors for annoated peaks. Default is false. 151 | Example file: example_mass_error_plot.html 152 | 24. massErrorPlotDefaultUnit: Unit for mass error plot. Default is 'Da'. Set to 'ppm' to see mass error in 153 | parts per million. 154 | } 155 | 156 | -------------------------------------------------------------------------------- /js/ion.js: -------------------------------------------------------------------------------- 1 | // $LastChangedDate$ 2 | // $LastChangedBy$ 3 | // $LastChangedRevision$ 4 | 5 | function Ion (t, color, charge, terminus) { 6 | this.type = t; 7 | this.color = color; 8 | this.charge = charge; 9 | this.label = this.type; 10 | if(this.charge > 1) 11 | this.label += charge; 12 | this.label += "+"; 13 | this.term = terminus; 14 | } 15 | 16 | // Source: http://en.wikipedia.org/wiki/Web_colors 17 | 18 | // charge +1 19 | Ion.A_1 = new Ion("a", "#008000", 1, "n"); // green 20 | Ion.B_1 = new Ion("b", "#0000ff", 1, "n"); // blue 21 | Ion.C_1 = new Ion("c", "#008B8B", 1, "n"); // dark cyan 22 | Ion.X_1 = new Ion("x", "#4B0082", 1, "c"); // indigo 23 | Ion.Y_1 = new Ion("y", "#ff0000", 1, "c"); // red 24 | Ion.Z_1 = new Ion("z", "#FF8C00", 1, "c"); // dark orange 25 | 26 | // charge +2 27 | Ion.A_2 = new Ion("a", "#2E8B57", 2, "n"); // sea green 28 | Ion.B_2 = new Ion("b", "#4169E1", 2, "n"); // royal blue 29 | Ion.C_2 = new Ion("c", "#20B2AA", 2, "n"); // light sea green 30 | Ion.X_2 = new Ion("x", "#800080", 2, "c"); // purple 31 | Ion.Y_2 = new Ion("y", "#FA8072", 2, "c"); // salmon 32 | Ion.Z_2 = new Ion("z", "#FFA500", 2, "c"); // orange 33 | 34 | // charge +3 35 | Ion.A_3 = new Ion("a", "#9ACD32", 3, "n"); // yellow green 36 | Ion.B_3 = new Ion("b", "#00BFFF", 3, "n"); // deep sky blue 37 | Ion.C_3 = new Ion("c", "#66CDAA", 3, "n"); // medium aquamarine 38 | Ion.X_3 = new Ion("x", "#9932CC", 3, "c"); // dark orchid 39 | Ion.Y_3 = new Ion("y", "#FFA07A", 3, "c"); // light salmon 40 | Ion.Z_3 = new Ion("z", "#FFD700", 3, "c"); // gold 41 | 42 | var _ions = []; 43 | _ions["a"] = []; 44 | _ions["a"][1] = Ion.A_1; 45 | _ions["a"][2] = Ion.A_2; 46 | _ions["a"][3] = Ion.A_3; 47 | _ions["b"] = []; 48 | _ions["b"][1] = Ion.B_1; 49 | _ions["b"][2] = Ion.B_2; 50 | _ions["b"][3] = Ion.B_3; 51 | _ions["c"] = []; 52 | _ions["c"][1] = Ion.C_1; 53 | _ions["c"][2] = Ion.C_2; 54 | _ions["c"][3] = Ion.C_3; 55 | _ions["x"] = []; 56 | _ions["x"][1] = Ion.X_1; 57 | _ions["x"][2] = Ion.X_2; 58 | _ions["x"][3] = Ion.X_3; 59 | _ions["y"] = []; 60 | _ions["y"][1] = Ion.Y_1; 61 | _ions["y"][2] = Ion.Y_2; 62 | _ions["y"][3] = Ion.Y_3; 63 | _ions["z"] = []; 64 | _ions["z"][1] = Ion.Z_1; 65 | _ions["z"][2] = Ion.Z_2; 66 | _ions["z"][3] = Ion.Z_3; 67 | 68 | Ion.get = function _getIon(type, charge) { 69 | 70 | return _ions[type][charge]; 71 | } 72 | 73 | Ion.getSeriesColor = function _getSeriesColor(ion) { 74 | 75 | return _ions[ion.type][ion.charge].color; 76 | } 77 | 78 | 79 | //----------------------------------------------------------------------------- 80 | // Ion Series 81 | //----------------------------------------------------------------------------- 82 | var MASS_H_1 = 1.00782503207; // H(1) Source: http://en.wikipedia.org/wiki/Isotopes_of_hydrogen 83 | var MASS_C_12 = 12.0; // C(12) Source: http://en.wikipedia.org/wiki/Isotopes_of_carbon 84 | var MASS_C_13 = 13.0033548378; // C(13) Source: http://en.wikipedia.org/wiki/Isotopes_of_carbon 85 | var MASS_N_14 = 14.0030740048; // N(14) Source: http://en.wikipedia.org/wiki/Isotopes_of_nitrogen 86 | var MASS_N_15 = 15.0001088982; // N(15) Source: http://en.wikipedia.org/wiki/Isotopes_of_nitrogen 87 | var MASS_O_16 = 15.99491461956; // O(16) Source: http://en.wikipedia.org/wiki/Isotopes_of_oxygen 88 | var MASS_O_18 = 17.9991610; // O(18) Source: http://en.wikipedia.org/wiki/Isotopes_of_oxygen 89 | var MASS_P_31 = 30.97376163; // P(31) Source: http://en.wikipedia.org/wiki/Isotopes_of_phosphorus 90 | 91 | // average masses 92 | var MASS_H = 1.00794; // Source: http://www.unimod.org/masses.html 93 | var MASS_C = 12.0107; // Source: http://en.wikipedia.org/wiki/Isotopes_of_carbon 94 | var MASS_N = 14.0067; // Source: http://en.wikipedia.org/wiki/Isotopes_of_nitrogen 95 | var MASS_O = 15.9994; // Source: http://en.wikipedia.org/wiki/Isotopes_of_oxygen 96 | var MASS_P = 30.9738; // Source: http://en.wikipedia.org/wiki/Isotopes_of_phosphorus 97 | 98 | var MASS_PROTON = 1.007276; 99 | 100 | Ion.MASS_PROTON = MASS_PROTON; 101 | Ion.MASS_H = MASS_H; 102 | Ion.MASS_C = MASS_C; 103 | Ion.MASS_N = MASS_N; 104 | Ion.MASS_O = MASS_O; 105 | Ion.MASS_P = MASS_P; 106 | 107 | Ion.MASS_H_1 = MASS_H_1; 108 | Ion.MASS_C_12 = MASS_C_12; 109 | Ion.MASS_C_13 = MASS_C_13; 110 | Ion.MASS_N_14 = MASS_N_14; 111 | Ion.MASS_N_15 = MASS_N_15; 112 | Ion.MASS_O_16 = MASS_O_16; 113 | Ion.MASS_O_18 = MASS_O_18; 114 | Ion.MASS_P_31 = MASS_P_31; 115 | 116 | // massType can be "mono" or "avg" 117 | Ion.getSeriesIon = function _getSeriesIon(ion, peptide, idxInSeq, massType) { 118 | if(ion.type == "a") 119 | return new Ion_A (peptide, idxInSeq, ion.charge, massType); 120 | if(ion.type == "b") 121 | return new Ion_B (peptide, idxInSeq, ion.charge, massType); 122 | if(ion.type == "c") 123 | return new Ion_C (peptide, idxInSeq, ion.charge, massType); 124 | if(ion.type == "x") 125 | return new Ion_X (peptide, idxInSeq, ion.charge, massType); 126 | if(ion.type == "y") 127 | return new Ion_Y (peptide, idxInSeq, ion.charge, massType); 128 | if(ion.type == "z") 129 | return new Ion_Z (peptide, idxInSeq, ion.charge, massType); 130 | } 131 | 132 | function _makeIonLabel(type, index, charge) { 133 | var label = type+""+index; 134 | for(var i = 1; i <= charge; i+=1) 135 | label += "+"; 136 | return label; 137 | } 138 | 139 | function _getMz(neutralMass, charge) { 140 | return ( neutralMass + (charge * MASS_PROTON) ) / charge; 141 | } 142 | 143 | Ion.AmmoniaLossMass_mono = MASS_H_1 * 3 + MASS_N_14; 144 | Ion.AmmoniaLossMass_avg = MASS_H * 3 + MASS_N; 145 | 146 | Ion.WaterLossMass_mono = MASS_H_1 * 2 + MASS_O_16; 147 | Ion.WaterLossMass_avg = MASS_H * 2 + MASS_O; 148 | 149 | Ion.PhosphoLossMass_mono = MASS_H_1 * 3 + MASS_P_31 + MASS_O_16 * 4; 150 | Ion.PhosphoLossMass_avg = MASS_H * 3 + MASS_P + MASS_O * 4; 151 | 152 | function _getIonMzWithLoss(sion, neutralLosses, massType) { 153 | var neutralMass = (sion.mz * sion.charge) - (sion.charge * MASS_PROTON); 154 | var lossMass = 0; 155 | if(neutralLosses) 156 | { 157 | if(massType == 'mono') lossMass += neutralLosses.getTotalLossMass('mono'); 158 | else if(massType == 'avg') lossMass += neutralLosses.getTotalLossMass('avg'); 159 | } 160 | return _getMz((neutralMass - lossMass), sion.charge); 161 | } 162 | 163 | Ion.getMz = _getMz; 164 | Ion.getIonMzWithLoss = _getIonMzWithLoss; 165 | 166 | function Ion_A (peptide, endIdxPlusOne, charge, massType) { 167 | // Neutral mass: [N]+[M]-CHO ; N = mass of neutral N terminal group 168 | var mass = 0; 169 | if(massType == "mono") 170 | mass = peptide.getSeqMassMono(endIdxPlusOne, "n") - (MASS_C_12 + MASS_O_16); 171 | else if(massType == "avg") 172 | mass = peptide.getSeqMassAvg(endIdxPlusOne, "n") - (MASS_C + MASS_O); 173 | this.charge = charge; 174 | this.mz = _getMz(mass, charge); 175 | this.fragmentIndex = endIdxPlusOne; 176 | this.label = _makeIonLabel("a",this.fragmentIndex, charge); 177 | this.match = false; 178 | this.term = "n"; 179 | return this; 180 | } 181 | 182 | function Ion_B (peptide, endIdxPlusOne, charge, massType) { 183 | // Neutral mass: [N]+[M]-H ; N = mass of neutral N terminal group 184 | var mass = 0; 185 | if(massType == "mono") 186 | mass = peptide.getSeqMassMono(endIdxPlusOne, "n"); 187 | else if(massType == "avg") 188 | mass = peptide.getSeqMassAvg(endIdxPlusOne, "n"); 189 | this.charge = charge; 190 | this.mz = _getMz(mass, charge); 191 | this.fragmentIndex = endIdxPlusOne; 192 | this.label = _makeIonLabel("b", this.fragmentIndex, charge); 193 | this.match = false; 194 | this.term = "n"; 195 | return this; 196 | } 197 | 198 | function Ion_C (peptide, endIdxPlusOne, charge, massType) { 199 | // Neutral mass: [N]+[M]+NH2 ; N = mass of neutral N terminal group 200 | var mass = 0; 201 | if(massType == "mono") 202 | mass = peptide.getSeqMassMono(endIdxPlusOne, "n") + MASS_H_1 + (MASS_N_14 + 2*MASS_H_1); 203 | else if(massType == "avg") 204 | mass = peptide.getSeqMassAvg(endIdxPlusOne, "n") + MASS_H + (MASS_N + 2*MASS_H); 205 | this.charge = charge; 206 | this.mz = _getMz(mass, charge); 207 | this.fragmentIndex = endIdxPlusOne; 208 | this.label = _makeIonLabel("c", this.fragmentIndex, charge); 209 | this.match = false; 210 | this.term = "n"; 211 | return this; 212 | } 213 | 214 | function Ion_X (peptide, startIdx, charge, massType) { 215 | // Neutral mass = [C]+[M]+CO-H ; C = mass of neutral C-terminal group (OH) 216 | var mass = 0; 217 | if(massType == "mono") 218 | mass = peptide.getSeqMassMono(startIdx, "c") + 2*MASS_O_16 + MASS_C_12; 219 | else if(massType == "avg") 220 | mass = peptide.getSeqMassAvg(startIdx, "c") + 2*MASS_O + MASS_C; 221 | this.charge = charge; 222 | this.mz = _getMz(mass, charge); 223 | this.fragmentIndex = peptide.sequence().length - startIdx; 224 | this.label = _makeIonLabel("x", this.fragmentIndex, charge); 225 | this.match = false; 226 | this.term = "c"; 227 | return this; 228 | } 229 | 230 | function Ion_Y (peptide, startIdx, charge, massType) { 231 | // Neutral mass = [C]+[M]+H ; C = mass of neutral C-terminal group (OH) 232 | var mass = 0; 233 | if(massType == "mono") 234 | mass = peptide.getSeqMassMono(startIdx, "c") + 2*MASS_H_1 + MASS_O_16; 235 | else if(massType == "avg") 236 | mass = peptide.getSeqMassAvg(startIdx, "c") + 2*MASS_H + MASS_O; 237 | this.charge = charge; 238 | this.mz = _getMz(mass, charge); 239 | this.fragmentIndex = peptide.sequence().length - startIdx; 240 | this.label = _makeIonLabel("y", this.fragmentIndex, charge); 241 | this.match = false; 242 | this.term = "c"; 243 | return this; 244 | } 245 | 246 | function Ion_Z (peptide, startIdx, charge, massType) { 247 | // Neutral mass = [C]+[M]-NH2 ; C = mass of neutral C-terminal group (OH) 248 | // We're really printing Z-dot ions so we add an H to make it OH+[M]-NH2 +H = [M]+O-N 249 | var mass = 0; 250 | if(massType == "mono") 251 | mass = peptide.getSeqMassMono(startIdx, "c") + MASS_O_16 - MASS_N_14; 252 | else if(massType == "avg") 253 | mass = peptide.getSeqMassAvg(startIdx, "c") + MASS_O - MASS_N; 254 | this.charge = charge; 255 | this.mz = _getMz(mass, charge); 256 | this.fragmentIndex = peptide.sequence().length - startIdx; 257 | this.label = _makeIonLabel("z", this.fragmentIndex, charge); 258 | this.match = false; 259 | this.term = "c"; 260 | return this; 261 | } 262 | -------------------------------------------------------------------------------- /html/example_use_neutral_loss.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Lorikeet Spectrum Viewer 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |

Lorikeet Plugin Example

27 | 28 |
29 | Lorikeet can display custom neutral losses and multiple neutral losses per amino acid. 30 |
31 | The default is to have one neutral loss per amino acid, but you can set it to a higher number with the 32 | following option: 33 |
34 |
 35 |         maxNeutralLossCount: 2
 36 |     
37 | Custom potential losses at a residue can be specified in the modification options, as the losses array. 38 |
39 |
 40 |         staticMods: [
 41 |                         {
 42 |                             "modMass":0.0,
 43 |                             "aminoAcid":"K",
 44 |                              losses: [{monoLossMass:17.026, avgLossMass:17.03, formula: 'NH3'}]
 45 |                         }
 46 |                     ]
 47 |         variableMods: [
 48 |                         {
 49 |                             index: 6,
 50 |                             modMass: 80.0,
 51 |                             aminoAcid: 'S',
 52 |                             losses: [{monoLossMass: 97.976895625, avgLossMass: 97.995181, formula: 'H3PO4'}]
 53 |                         }
 54 |                     ]
 55 |     
56 |
57 | 58 | 59 | 60 |
Neutral Loss Spectrum
61 |
62 | 63 | 386 | 387 | 388 | 389 | -------------------------------------------------------------------------------- /js/jquery.flot.selection.js: -------------------------------------------------------------------------------- 1 | /* Flot plugin for selecting regions of a plot. 2 | 3 | Copyright (c) 2007-2014 IOLA and Ole Laursen. 4 | Licensed under the MIT license. 5 | 6 | The plugin supports these options: 7 | 8 | selection: { 9 | mode: null or "x" or "y" or "xy", 10 | color: color, 11 | shape: "round" or "miter" or "bevel", 12 | minSize: number of pixels 13 | } 14 | 15 | Selection support is enabled by setting the mode to one of "x", "y" or "xy". 16 | In "x" mode, the user will only be able to specify the x range, similarly for 17 | "y" mode. For "xy", the selection becomes a rectangle where both ranges can be 18 | specified. "color" is color of the selection (if you need to change the color 19 | later on, you can get to it with plot.getOptions().selection.color). "shape" 20 | is the shape of the corners of the selection. 21 | 22 | "minSize" is the minimum size a selection can be in pixels. This value can 23 | be customized to determine the smallest size a selection can be and still 24 | have the selection rectangle be displayed. When customizing this value, the 25 | fact that it refers to pixels, not axis units must be taken into account. 26 | Thus, for example, if there is a bar graph in time mode with BarWidth set to 1 27 | minute, setting "minSize" to 1 will not make the minimum selection size 1 28 | minute, but rather 1 pixel. Note also that setting "minSize" to 0 will prevent 29 | "plotunselected" events from being fired when the user clicks the mouse without 30 | dragging. 31 | 32 | When selection support is enabled, a "plotselected" event will be emitted on 33 | the DOM element you passed into the plot function. The event handler gets a 34 | parameter with the ranges selected on the axes, like this: 35 | 36 | placeholder.bind( "plotselected", function( event, ranges ) { 37 | alert("You selected " + ranges.xaxis.from + " to " + ranges.xaxis.to) 38 | // similar for yaxis - with multiple axes, the extra ones are in 39 | // x2axis, x3axis, ... 40 | }); 41 | 42 | The "plotselected" event is only fired when the user has finished making the 43 | selection. A "plotselecting" event is fired during the process with the same 44 | parameters as the "plotselected" event, in case you want to know what's 45 | happening while it's happening, 46 | 47 | A "plotunselected" event with no arguments is emitted when the user clicks the 48 | mouse to remove the selection. As stated above, setting "minSize" to 0 will 49 | destroy this behavior. 50 | 51 | The plugin allso adds the following methods to the plot object: 52 | 53 | - setSelection( ranges, preventEvent ) 54 | 55 | Set the selection rectangle. The passed in ranges is on the same form as 56 | returned in the "plotselected" event. If the selection mode is "x", you 57 | should put in either an xaxis range, if the mode is "y" you need to put in 58 | an yaxis range and both xaxis and yaxis if the selection mode is "xy", like 59 | this: 60 | 61 | setSelection({ xaxis: { from: 0, to: 10 }, yaxis: { from: 40, to: 60 } }); 62 | 63 | setSelection will trigger the "plotselected" event when called. If you don't 64 | want that to happen, e.g. if you're inside a "plotselected" handler, pass 65 | true as the second parameter. If you are using multiple axes, you can 66 | specify the ranges on any of those, e.g. as x2axis/x3axis/... instead of 67 | xaxis, the plugin picks the first one it sees. 68 | 69 | - clearSelection( preventEvent ) 70 | 71 | Clear the selection rectangle. Pass in true to avoid getting a 72 | "plotunselected" event. 73 | 74 | - getSelection() 75 | 76 | Returns the current selection in the same format as the "plotselected" 77 | event. If there's currently no selection, the function returns null. 78 | 79 | */ 80 | 81 | (function ($) { 82 | function init(plot) { 83 | var selection = { 84 | first: { x: -1, y: -1}, second: { x: -1, y: -1}, 85 | show: false, 86 | active: false 87 | }; 88 | 89 | // FIXME: The drag handling implemented here should be 90 | // abstracted out, there's some similar code from a library in 91 | // the navigation plugin, this should be massaged a bit to fit 92 | // the Flot cases here better and reused. Doing this would 93 | // make this plugin much slimmer. 94 | var savedhandlers = {}; 95 | 96 | var mouseUpHandler = null; 97 | 98 | function onMouseMove(e) { 99 | if (selection.active) { 100 | updateSelection(e); 101 | 102 | plot.getPlaceholder().trigger("plotselecting", [ getSelection() ]); 103 | } 104 | } 105 | 106 | function onMouseDown(e) { 107 | if (e.which != 1) // only accept left-click 108 | return; 109 | 110 | // cancel out any text selections 111 | document.body.focus(); 112 | 113 | // prevent text selection and drag in old-school browsers 114 | if (document.onselectstart !== undefined && savedhandlers.onselectstart == null) { 115 | savedhandlers.onselectstart = document.onselectstart; 116 | document.onselectstart = function () { return false; }; 117 | } 118 | if (document.ondrag !== undefined && savedhandlers.ondrag == null) { 119 | savedhandlers.ondrag = document.ondrag; 120 | document.ondrag = function () { return false; }; 121 | } 122 | 123 | setSelectionPos(selection.first, e); 124 | 125 | selection.active = true; 126 | 127 | // this is a bit silly, but we have to use a closure to be 128 | // able to whack the same handler again 129 | mouseUpHandler = function (e) { onMouseUp(e); }; 130 | 131 | $(document).one("mouseup", mouseUpHandler); 132 | } 133 | 134 | function onMouseUp(e) { 135 | mouseUpHandler = null; 136 | 137 | // revert drag stuff for old-school browsers 138 | if (document.onselectstart !== undefined) 139 | document.onselectstart = savedhandlers.onselectstart; 140 | if (document.ondrag !== undefined) 141 | document.ondrag = savedhandlers.ondrag; 142 | 143 | // no more dragging 144 | selection.active = false; 145 | updateSelection(e); 146 | 147 | if (selectionIsSane()) 148 | triggerSelectedEvent(); 149 | else { 150 | // this counts as a clear 151 | plot.getPlaceholder().trigger("plotunselected", [ ]); 152 | plot.getPlaceholder().trigger("plotselecting", [ null ]); 153 | } 154 | 155 | return false; 156 | } 157 | 158 | function getSelection() { 159 | if (!selectionIsSane()) 160 | return null; 161 | 162 | if (!selection.show) return null; 163 | 164 | var r = {}, c1 = selection.first, c2 = selection.second; 165 | $.each(plot.getAxes(), function (name, axis) { 166 | if (axis.used) { 167 | var p1 = axis.c2p(c1[axis.direction]), p2 = axis.c2p(c2[axis.direction]); 168 | r[name] = { from: Math.min(p1, p2), to: Math.max(p1, p2) }; 169 | } 170 | }); 171 | return r; 172 | } 173 | 174 | function triggerSelectedEvent() { 175 | var r = getSelection(); 176 | 177 | plot.getPlaceholder().trigger("plotselected", [ r ]); 178 | 179 | // backwards-compat stuff, to be removed in future 180 | if (r.xaxis && r.yaxis) 181 | plot.getPlaceholder().trigger("selected", [ { x1: r.xaxis.from, y1: r.yaxis.from, x2: r.xaxis.to, y2: r.yaxis.to } ]); 182 | } 183 | 184 | function clamp(min, value, max) { 185 | return value < min ? min: (value > max ? max: value); 186 | } 187 | 188 | function setSelectionPos(pos, e) { 189 | var o = plot.getOptions(); 190 | var offset = plot.getPlaceholder().offset(); 191 | var plotOffset = plot.getPlotOffset(); 192 | pos.x = clamp(0, e.pageX - offset.left - plotOffset.left, plot.width()); 193 | pos.y = clamp(0, e.pageY - offset.top - plotOffset.top, plot.height()); 194 | 195 | if (o.selection.mode == "y") 196 | pos.x = pos == selection.first ? 0 : plot.width(); 197 | 198 | if (o.selection.mode == "x") 199 | pos.y = pos == selection.first ? 0 : plot.height(); 200 | } 201 | 202 | function updateSelection(pos) { 203 | if (pos.pageX == null) 204 | return; 205 | 206 | setSelectionPos(selection.second, pos); 207 | if (selectionIsSane()) { 208 | selection.show = true; 209 | plot.triggerRedrawOverlay(); 210 | } 211 | else 212 | clearSelection(true); 213 | } 214 | 215 | function clearSelection(preventEvent) { 216 | if (selection.show) { 217 | selection.show = false; 218 | plot.triggerRedrawOverlay(); 219 | if (!preventEvent) 220 | plot.getPlaceholder().trigger("plotunselected", [ ]); 221 | } 222 | } 223 | 224 | // function taken from markings support in Flot 225 | function extractRange(ranges, coord) { 226 | var axis, from, to, key, axes = plot.getAxes(); 227 | 228 | for (var k in axes) { 229 | axis = axes[k]; 230 | if (axis.direction == coord) { 231 | key = coord + axis.n + "axis"; 232 | if (!ranges[key] && axis.n == 1) 233 | key = coord + "axis"; // support x1axis as xaxis 234 | if (ranges[key]) { 235 | from = ranges[key].from; 236 | to = ranges[key].to; 237 | break; 238 | } 239 | } 240 | } 241 | 242 | // backwards-compat stuff - to be removed in future 243 | if (!ranges[key]) { 244 | axis = coord == "x" ? plot.getXAxes()[0] : plot.getYAxes()[0]; 245 | from = ranges[coord + "1"]; 246 | to = ranges[coord + "2"]; 247 | } 248 | 249 | // auto-reverse as an added bonus 250 | if (from != null && to != null && from > to) { 251 | var tmp = from; 252 | from = to; 253 | to = tmp; 254 | } 255 | 256 | return { from: from, to: to, axis: axis }; 257 | } 258 | 259 | function setSelection(ranges, preventEvent) { 260 | var axis, range, o = plot.getOptions(); 261 | 262 | if (o.selection.mode == "y") { 263 | selection.first.x = 0; 264 | selection.second.x = plot.width(); 265 | } 266 | else { 267 | range = extractRange(ranges, "x"); 268 | 269 | selection.first.x = range.axis.p2c(range.from); 270 | selection.second.x = range.axis.p2c(range.to); 271 | } 272 | 273 | if (o.selection.mode == "x") { 274 | selection.first.y = 0; 275 | selection.second.y = plot.height(); 276 | } 277 | else { 278 | range = extractRange(ranges, "y"); 279 | 280 | selection.first.y = range.axis.p2c(range.from); 281 | selection.second.y = range.axis.p2c(range.to); 282 | } 283 | 284 | selection.show = true; 285 | plot.triggerRedrawOverlay(); 286 | if (!preventEvent && selectionIsSane()) 287 | triggerSelectedEvent(); 288 | } 289 | 290 | function selectionIsSane() { 291 | var minSize = plot.getOptions().selection.minSize; 292 | return Math.abs(selection.second.x - selection.first.x) >= minSize && 293 | Math.abs(selection.second.y - selection.first.y) >= minSize; 294 | } 295 | 296 | plot.clearSelection = clearSelection; 297 | plot.setSelection = setSelection; 298 | plot.getSelection = getSelection; 299 | 300 | plot.hooks.bindEvents.push(function(plot, eventHolder) { 301 | var o = plot.getOptions(); 302 | if (o.selection.mode != null) { 303 | eventHolder.mousemove(onMouseMove); 304 | eventHolder.mousedown(onMouseDown); 305 | } 306 | }); 307 | 308 | 309 | plot.hooks.drawOverlay.push(function (plot, ctx) { 310 | // draw selection 311 | if (selection.show && selectionIsSane()) { 312 | var plotOffset = plot.getPlotOffset(); 313 | var o = plot.getOptions(); 314 | 315 | ctx.save(); 316 | ctx.translate(plotOffset.left, plotOffset.top); 317 | 318 | var c = $.color.parse(o.selection.color); 319 | 320 | ctx.strokeStyle = c.scale('a', 0.8).toString(); 321 | ctx.lineWidth = 1; 322 | ctx.lineJoin = o.selection.shape; 323 | ctx.fillStyle = c.scale('a', 0.4).toString(); 324 | 325 | var x = Math.min(selection.first.x, selection.second.x) + 0.5, 326 | y = Math.min(selection.first.y, selection.second.y) + 0.5, 327 | w = Math.abs(selection.second.x - selection.first.x) - 1, 328 | h = Math.abs(selection.second.y - selection.first.y) - 1; 329 | 330 | ctx.fillRect(x, y, w, h); 331 | ctx.strokeRect(x, y, w, h); 332 | 333 | ctx.restore(); 334 | } 335 | }); 336 | 337 | plot.hooks.shutdown.push(function (plot, eventHolder) { 338 | eventHolder.unbind("mousemove", onMouseMove); 339 | eventHolder.unbind("mousedown", onMouseDown); 340 | 341 | if (mouseUpHandler) 342 | $(document).unbind("mouseup", mouseUpHandler); 343 | }); 344 | 345 | } 346 | 347 | $.plot.plugins.push({ 348 | init: init, 349 | options: { 350 | selection: { 351 | mode: null, // one of null, "x", "y" or "xy" 352 | color: "#e8cfac", 353 | shape: "round", // one of "round", "miter", or "bevel" 354 | minSize: 5 // minimum number of pixels 355 | } 356 | }, 357 | name: 'selection', 358 | version: '1.1' 359 | }); 360 | })(jQuery); 361 | -------------------------------------------------------------------------------- /css/jquery-ui-1.13.0.slider.min.css: -------------------------------------------------------------------------------- 1 | /*! jQuery UI - v1.13.0 - 2021-12-22 2 | * http://jqueryui.com 3 | * Includes: core.css, slider.css, theme.css 4 | * To view and modify this theme, visit http://jqueryui.com/themeroller/?scope=&folderName=base&cornerRadiusShadow=8px&offsetLeftShadow=0px&offsetTopShadow=0px&thicknessShadow=5px&opacityShadow=30&bgImgOpacityShadow=0&bgTextureShadow=flat&bgColorShadow=666666&opacityOverlay=30&bgImgOpacityOverlay=0&bgTextureOverlay=flat&bgColorOverlay=aaaaaa&iconColorError=cc0000&fcError=5f3f3f&borderColorError=f1a899&bgTextureError=flat&bgColorError=fddfdf&iconColorHighlight=777620&fcHighlight=777620&borderColorHighlight=dad55e&bgTextureHighlight=flat&bgColorHighlight=fffa90&iconColorActive=ffffff&fcActive=ffffff&borderColorActive=003eff&bgTextureActive=flat&bgColorActive=007fff&iconColorHover=555555&fcHover=2b2b2b&borderColorHover=cccccc&bgTextureHover=flat&bgColorHover=ededed&iconColorDefault=777777&fcDefault=454545&borderColorDefault=c5c5c5&bgTextureDefault=flat&bgColorDefault=f6f6f6&iconColorContent=444444&fcContent=333333&borderColorContent=dddddd&bgTextureContent=flat&bgColorContent=ffffff&iconColorHeader=444444&fcHeader=333333&borderColorHeader=dddddd&bgTextureHeader=flat&bgColorHeader=e9e9e9&cornerRadius=3px&fwDefault=normal&fsDefault=1em&ffDefault=Arial%2CHelvetica%2Csans-serif 5 | * Copyright jQuery Foundation and other contributors; Licensed MIT */ 6 | 7 | .ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;-ms-filter:"alpha(opacity=0)"}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important;pointer-events:none}.ui-icon{display:inline-block;vertical-align:middle;margin-top:-.25em;position:relative;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-icon-block{left:50%;margin-left:-8px;display:block}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:pointer;-ms-touch-action:none;touch-action:none}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider.ui-state-disabled .ui-slider-handle,.ui-slider.ui-state-disabled .ui-slider-range{filter:inherit}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}.ui-widget{font-family:Arial,Helvetica,sans-serif;font-size:1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Arial,Helvetica,sans-serif;font-size:1em}.ui-widget.ui-widget-content{border:1px solid #c5c5c5}.ui-widget-content{border:1px solid #ddd;background:#fff;color:#333}.ui-widget-content a{color:#333}.ui-widget-header{border:1px solid #ddd;background:#e9e9e9;color:#333;font-weight:bold}.ui-widget-header a{color:#333}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default,.ui-button,html .ui-button.ui-state-disabled:hover,html .ui-button.ui-state-disabled:active{border:1px solid #c5c5c5;background:#f6f6f6;font-weight:normal;color:#454545}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited,a.ui-button,a:link.ui-button,a:visited.ui-button,.ui-button{color:#454545;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus,.ui-button:hover,.ui-button:focus{border:1px solid #ccc;background:#ededed;font-weight:normal;color:#2b2b2b}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited,.ui-state-focus a,.ui-state-focus a:hover,.ui-state-focus a:link,.ui-state-focus a:visited,a.ui-button:hover,a.ui-button:focus{color:#2b2b2b;text-decoration:none}.ui-visual-focus{box-shadow:0 0 3px 1px rgb(94,158,214)}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active,a.ui-button:active,.ui-button:active,.ui-button.ui-state-active:hover{border:1px solid #003eff;background:#007fff;font-weight:normal;color:#fff}.ui-icon-background,.ui-state-active .ui-icon-background{border:#003eff;background-color:#fff}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#fff;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #dad55e;background:#fffa90;color:#777620}.ui-state-checked{border:1px solid #dad55e;background:#fffa90}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#777620}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #f1a899;background:#fddfdf;color:#5f3f3f}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#5f3f3f}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#5f3f3f}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;-ms-filter:"alpha(opacity=70)";font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;-ms-filter:"alpha(opacity=35)";background-image:none}.ui-state-disabled .ui-icon{-ms-filter:"alpha(opacity=35)"}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url("images/ui-icons_444444_256x240.png")}.ui-widget-header .ui-icon{background-image:url("images/ui-icons_444444_256x240.png")}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon,.ui-button:hover .ui-icon,.ui-button:focus .ui-icon{background-image:url("images/ui-icons_555555_256x240.png")}.ui-state-active .ui-icon,.ui-button:active .ui-icon{background-image:url("images/ui-icons_ffffff_256x240.png")}.ui-state-highlight .ui-icon,.ui-button .ui-state-highlight.ui-icon{background-image:url("images/ui-icons_777620_256x240.png")}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url("images/ui-icons_cc0000_256x240.png")}.ui-button .ui-icon{background-image:url("images/ui-icons_777777_256x240.png")}.ui-icon-blank.ui-icon-blank.ui-icon-blank{background-image:none}.ui-icon-caret-1-n{background-position:0 0}.ui-icon-caret-1-ne{background-position:-16px 0}.ui-icon-caret-1-e{background-position:-32px 0}.ui-icon-caret-1-se{background-position:-48px 0}.ui-icon-caret-1-s{background-position:-65px 0}.ui-icon-caret-1-sw{background-position:-80px 0}.ui-icon-caret-1-w{background-position:-96px 0}.ui-icon-caret-1-nw{background-position:-112px 0}.ui-icon-caret-2-n-s{background-position:-128px 0}.ui-icon-caret-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-65px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-65px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:1px -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:3px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:3px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:3px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:3px}.ui-widget-overlay{background:#aaa;opacity:.3;-ms-filter:Alpha(Opacity=30)}.ui-widget-shadow{-webkit-box-shadow:0 0 5px #666;box-shadow:0 0 5px #666} -------------------------------------------------------------------------------- /html/example_itraq.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | COMET/Lorikeet Spectrum Viewer 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | To label reporter ions such as iTRAQ and TMT, set labelReporters to true in the options. 24 |
labelReporters: true
25 |
26 | 27 |
28 | 29 | 576 | 577 |
578 |
579 | 580 | -------------------------------------------------------------------------------- /js/excanvas.min.js: -------------------------------------------------------------------------------- 1 | if(!document.createElement("canvas").getContext){(function(){var z=Math;var K=z.round;var J=z.sin;var U=z.cos;var b=z.abs;var k=z.sqrt;var D=10;var F=D/2;function T(){return this.context_||(this.context_=new W(this))}var O=Array.prototype.slice;function G(i,j,m){var Z=O.call(arguments,2);return function(){return i.apply(j,Z.concat(O.call(arguments)))}}function AD(Z){return String(Z).replace(/&/g,"&").replace(/"/g,""")}function r(i){if(!i.namespaces.g_vml_){i.namespaces.add("g_vml_","urn:schemas-microsoft-com:vml","#default#VML")}if(!i.namespaces.g_o_){i.namespaces.add("g_o_","urn:schemas-microsoft-com:office:office","#default#VML")}if(!i.styleSheets.ex_canvas_){var Z=i.createStyleSheet();Z.owningElement.id="ex_canvas_";Z.cssText="canvas{display:inline-block;overflow:hidden;text-align:left;width:300px;height:150px}"}}r(document);var E={init:function(Z){if(/MSIE/.test(navigator.userAgent)&&!window.opera){var i=Z||document;i.createElement("canvas");i.attachEvent("onreadystatechange",G(this.init_,this,i))}},init_:function(m){var j=m.getElementsByTagName("canvas");for(var Z=0;Z1){j--}if(6*j<1){return i+(Z-i)*6*j}else{if(2*j<1){return Z}else{if(3*j<2){return i+(Z-i)*(2/3-j)*6}else{return i}}}}function Y(Z){var AE,p=1;Z=String(Z);if(Z.charAt(0)=="#"){AE=Z}else{if(/^rgb/.test(Z)){var m=g(Z);var AE="#",AF;for(var j=0;j<3;j++){if(m[j].indexOf("%")!=-1){AF=Math.floor(C(m[j])*255)}else{AF=Number(m[j])}AE+=I[N(AF,0,255)]}p=m[3]}else{if(/^hsl/.test(Z)){var m=g(Z);AE=c(m);p=m[3]}else{AE=B[Z]||Z}}}return{color:AE,alpha:p}}var L={style:"normal",variant:"normal",weight:"normal",size:10,family:"sans-serif"};var f={};function X(Z){if(f[Z]){return f[Z]}var m=document.createElement("div");var j=m.style;try{j.font=Z}catch(i){}return f[Z]={style:j.fontStyle||L.style,variant:j.fontVariant||L.variant,weight:j.fontWeight||L.weight,size:j.fontSize||L.size,family:j.fontFamily||L.family}}function P(j,i){var Z={};for(var AF in j){Z[AF]=j[AF]}var AE=parseFloat(i.currentStyle.fontSize),m=parseFloat(j.size);if(typeof j.size=="number"){Z.size=j.size}else{if(j.size.indexOf("px")!=-1){Z.size=m}else{if(j.size.indexOf("em")!=-1){Z.size=AE*m}else{if(j.size.indexOf("%")!=-1){Z.size=(AE/100)*m}else{if(j.size.indexOf("pt")!=-1){Z.size=m/0.75}else{Z.size=AE}}}}}Z.size*=0.981;return Z}function AA(Z){return Z.style+" "+Z.variant+" "+Z.weight+" "+Z.size+"px "+Z.family}function t(Z){switch(Z){case"butt":return"flat";case"round":return"round";case"square":default:return"square"}}function W(i){this.m_=V();this.mStack_=[];this.aStack_=[];this.currentPath_=[];this.strokeStyle="#000";this.fillStyle="#000";this.lineWidth=1;this.lineJoin="miter";this.lineCap="butt";this.miterLimit=D*1;this.globalAlpha=1;this.font="10px sans-serif";this.textAlign="left";this.textBaseline="alphabetic";this.canvas=i;var Z=i.ownerDocument.createElement("div");Z.style.width=i.clientWidth+"px";Z.style.height=i.clientHeight+"px";Z.style.overflow="hidden";Z.style.position="absolute";i.appendChild(Z);this.element_=Z;this.arcScaleX_=1;this.arcScaleY_=1;this.lineScale_=1}var M=W.prototype;M.clearRect=function(){if(this.textMeasureEl_){this.textMeasureEl_.removeNode(true);this.textMeasureEl_=null}this.element_.innerHTML=""};M.beginPath=function(){this.currentPath_=[]};M.moveTo=function(i,Z){var j=this.getCoords_(i,Z);this.currentPath_.push({type:"moveTo",x:j.x,y:j.y});this.currentX_=j.x;this.currentY_=j.y};M.lineTo=function(i,Z){var j=this.getCoords_(i,Z);this.currentPath_.push({type:"lineTo",x:j.x,y:j.y});this.currentX_=j.x;this.currentY_=j.y};M.bezierCurveTo=function(j,i,AI,AH,AG,AE){var Z=this.getCoords_(AG,AE);var AF=this.getCoords_(j,i);var m=this.getCoords_(AI,AH);e(this,AF,m,Z)};function e(Z,m,j,i){Z.currentPath_.push({type:"bezierCurveTo",cp1x:m.x,cp1y:m.y,cp2x:j.x,cp2y:j.y,x:i.x,y:i.y});Z.currentX_=i.x;Z.currentY_=i.y}M.quadraticCurveTo=function(AG,j,i,Z){var AF=this.getCoords_(AG,j);var AE=this.getCoords_(i,Z);var AH={x:this.currentX_+2/3*(AF.x-this.currentX_),y:this.currentY_+2/3*(AF.y-this.currentY_)};var m={x:AH.x+(AE.x-this.currentX_)/3,y:AH.y+(AE.y-this.currentY_)/3};e(this,AH,m,AE)};M.arc=function(AJ,AH,AI,AE,i,j){AI*=D;var AN=j?"at":"wa";var AK=AJ+U(AE)*AI-F;var AM=AH+J(AE)*AI-F;var Z=AJ+U(i)*AI-F;var AL=AH+J(i)*AI-F;if(AK==Z&&!j){AK+=0.125}var m=this.getCoords_(AJ,AH);var AG=this.getCoords_(AK,AM);var AF=this.getCoords_(Z,AL);this.currentPath_.push({type:AN,x:m.x,y:m.y,radius:AI,xStart:AG.x,yStart:AG.y,xEnd:AF.x,yEnd:AF.y})};M.rect=function(j,i,Z,m){this.moveTo(j,i);this.lineTo(j+Z,i);this.lineTo(j+Z,i+m);this.lineTo(j,i+m);this.closePath()};M.strokeRect=function(j,i,Z,m){var p=this.currentPath_;this.beginPath();this.moveTo(j,i);this.lineTo(j+Z,i);this.lineTo(j+Z,i+m);this.lineTo(j,i+m);this.closePath();this.stroke();this.currentPath_=p};M.fillRect=function(j,i,Z,m){var p=this.currentPath_;this.beginPath();this.moveTo(j,i);this.lineTo(j+Z,i);this.lineTo(j+Z,i+m);this.lineTo(j,i+m);this.closePath();this.fill();this.currentPath_=p};M.createLinearGradient=function(i,m,Z,j){var p=new v("gradient");p.x0_=i;p.y0_=m;p.x1_=Z;p.y1_=j;return p};M.createRadialGradient=function(m,AE,j,i,p,Z){var AF=new v("gradientradial");AF.x0_=m;AF.y0_=AE;AF.r0_=j;AF.x1_=i;AF.y1_=p;AF.r1_=Z;return AF};M.drawImage=function(AO,j){var AH,AF,AJ,AV,AM,AK,AQ,AX;var AI=AO.runtimeStyle.width;var AN=AO.runtimeStyle.height;AO.runtimeStyle.width="auto";AO.runtimeStyle.height="auto";var AG=AO.width;var AT=AO.height;AO.runtimeStyle.width=AI;AO.runtimeStyle.height=AN;if(arguments.length==3){AH=arguments[1];AF=arguments[2];AM=AK=0;AQ=AJ=AG;AX=AV=AT}else{if(arguments.length==5){AH=arguments[1];AF=arguments[2];AJ=arguments[3];AV=arguments[4];AM=AK=0;AQ=AG;AX=AT}else{if(arguments.length==9){AM=arguments[1];AK=arguments[2];AQ=arguments[3];AX=arguments[4];AH=arguments[5];AF=arguments[6];AJ=arguments[7];AV=arguments[8]}else{throw Error("Invalid number of arguments")}}}var AW=this.getCoords_(AH,AF);var m=AQ/2;var i=AX/2;var AU=[];var Z=10;var AE=10;AU.push(" ','","");this.element_.insertAdjacentHTML("BeforeEnd",AU.join(""))};M.stroke=function(AM){var m=10;var AN=10;var AE=5000;var AG={x:null,y:null};var AL={x:null,y:null};for(var AH=0;AHAL.x){AL.x=Z.x}if(AG.y==null||Z.yAL.y){AL.y=Z.y}}}AK.push(' ">');if(!AM){R(this,AK)}else{a(this,AK,AG,AL)}AK.push("");this.element_.insertAdjacentHTML("beforeEnd",AK.join(""))}};function R(j,AE){var i=Y(j.strokeStyle);var m=i.color;var p=i.alpha*j.globalAlpha;var Z=j.lineScale_*j.lineWidth;if(Z<1){p*=Z}AE.push("')}function a(AO,AG,Ah,AP){var AH=AO.fillStyle;var AY=AO.arcScaleX_;var AX=AO.arcScaleY_;var Z=AP.x-Ah.x;var m=AP.y-Ah.y;if(AH instanceof v){var AL=0;var Ac={x:0,y:0};var AU=0;var AK=1;if(AH.type_=="gradient"){var AJ=AH.x0_/AY;var j=AH.y0_/AX;var AI=AH.x1_/AY;var Aj=AH.y1_/AX;var Ag=AO.getCoords_(AJ,j);var Af=AO.getCoords_(AI,Aj);var AE=Af.x-Ag.x;var p=Af.y-Ag.y;AL=Math.atan2(AE,p)*180/Math.PI;if(AL<0){AL+=360}if(AL<0.000001){AL=0}}else{var Ag=AO.getCoords_(AH.x0_,AH.y0_);Ac={x:(Ag.x-Ah.x)/Z,y:(Ag.y-Ah.y)/m};Z/=AY*D;m/=AX*D;var Aa=z.max(Z,m);AU=2*AH.r0_/Aa;AK=2*AH.r1_/Aa-AU}var AS=AH.colors_;AS.sort(function(Ak,i){return Ak.offset-i.offset});var AN=AS.length;var AR=AS[0].color;var AQ=AS[AN-1].color;var AW=AS[0].alpha*AO.globalAlpha;var AV=AS[AN-1].alpha*AO.globalAlpha;var Ab=[];for(var Ae=0;Ae')}else{if(AH instanceof u){if(Z&&m){var AF=-Ah.x;var AZ=-Ah.y;AG.push("')}}else{var Ai=Y(AO.fillStyle);var AT=Ai.color;var Ad=Ai.alpha*AO.globalAlpha;AG.push('')}}}M.fill=function(){this.stroke(true)};M.closePath=function(){this.currentPath_.push({type:"close"})};M.getCoords_=function(j,i){var Z=this.m_;return{x:D*(j*Z[0][0]+i*Z[1][0]+Z[2][0])-F,y:D*(j*Z[0][1]+i*Z[1][1]+Z[2][1])-F}};M.save=function(){var Z={};Q(this,Z);this.aStack_.push(Z);this.mStack_.push(this.m_);this.m_=d(V(),this.m_)};M.restore=function(){if(this.aStack_.length){Q(this.aStack_.pop(),this);this.m_=this.mStack_.pop()}};function H(Z){return isFinite(Z[0][0])&&isFinite(Z[0][1])&&isFinite(Z[1][0])&&isFinite(Z[1][1])&&isFinite(Z[2][0])&&isFinite(Z[2][1])}function y(i,Z,j){if(!H(Z)){return }i.m_=Z;if(j){var p=Z[0][0]*Z[1][1]-Z[0][1]*Z[1][0];i.lineScale_=k(b(p))}}M.translate=function(j,i){var Z=[[1,0,0],[0,1,0],[j,i,1]];y(this,d(Z,this.m_),false)};M.rotate=function(i){var m=U(i);var j=J(i);var Z=[[m,j,0],[-j,m,0],[0,0,1]];y(this,d(Z,this.m_),false)};M.scale=function(j,i){this.arcScaleX_*=j;this.arcScaleY_*=i;var Z=[[j,0,0],[0,i,0],[0,0,1]];y(this,d(Z,this.m_),true)};M.transform=function(p,m,AF,AE,i,Z){var j=[[p,m,0],[AF,AE,0],[i,Z,1]];y(this,d(j,this.m_),true)};M.setTransform=function(AE,p,AG,AF,j,i){var Z=[[AE,p,0],[AG,AF,0],[j,i,1]];y(this,Z,true)};M.drawText_=function(AK,AI,AH,AN,AG){var AM=this.m_,AQ=1000,i=0,AP=AQ,AF={x:0,y:0},AE=[];var Z=P(X(this.font),this.element_);var j=AA(Z);var AR=this.element_.currentStyle;var p=this.textAlign.toLowerCase();switch(p){case"left":case"center":case"right":break;case"end":p=AR.direction=="ltr"?"right":"left";break;case"start":p=AR.direction=="rtl"?"right":"left";break;default:p="left"}switch(this.textBaseline){case"hanging":case"top":AF.y=Z.size/1.75;break;case"middle":break;default:case null:case"alphabetic":case"ideographic":case"bottom":AF.y=-Z.size/2.25;break}switch(p){case"right":i=AQ;AP=0.05;break;case"center":i=AP=AQ/2;break}var AO=this.getCoords_(AI+AF.x,AH+AF.y);AE.push('');if(AG){R(this,AE)}else{a(this,AE,{x:-i,y:0},{x:AP,y:Z.size})}var AL=AM[0][0].toFixed(3)+","+AM[1][0].toFixed(3)+","+AM[0][1].toFixed(3)+","+AM[1][1].toFixed(3)+",0,0";var AJ=K(AO.x/D)+","+K(AO.y/D);AE.push('','','');this.element_.insertAdjacentHTML("beforeEnd",AE.join(""))};M.fillText=function(j,Z,m,i){this.drawText_(j,Z,m,i,false)};M.strokeText=function(j,Z,m,i){this.drawText_(j,Z,m,i,true)};M.measureText=function(j){if(!this.textMeasureEl_){var Z='';this.element_.insertAdjacentHTML("beforeEnd",Z);this.textMeasureEl_=this.element_.lastChild}var i=this.element_.ownerDocument;this.textMeasureEl_.innerHTML="";this.textMeasureEl_.style.font=this.font;this.textMeasureEl_.appendChild(i.createTextNode(j));return{width:this.textMeasureEl_.offsetWidth}};M.clip=function(){};M.arcTo=function(){};M.createPattern=function(i,Z){return new u(i,Z)};function v(Z){this.type_=Z;this.x0_=0;this.y0_=0;this.r0_=0;this.x1_=0;this.y1_=0;this.r1_=0;this.colors_=[]}v.prototype.addColorStop=function(i,Z){Z=Y(Z);this.colors_.push({offset:i,color:Z.color,alpha:Z.alpha})};function u(i,Z){q(i);switch(Z){case"repeat":case null:case"":this.repetition_="repeat";break;case"repeat-x":case"repeat-y":case"no-repeat":this.repetition_=Z;break;default:n("SYNTAX_ERR")}this.src_=i.src;this.width_=i.width;this.height_=i.height}function n(Z){throw new o(Z)}function q(Z){if(!Z||Z.nodeType!=1||Z.tagName!="IMG"){n("TYPE_MISMATCH_ERR")}if(Z.readyState!="complete"){n("INVALID_STATE_ERR")}}function o(Z){this.code=this[Z];this.message=Z+": DOM Exception "+this.code}var x=o.prototype=new Error;x.INDEX_SIZE_ERR=1;x.DOMSTRING_SIZE_ERR=2;x.HIERARCHY_REQUEST_ERR=3;x.WRONG_DOCUMENT_ERR=4;x.INVALID_CHARACTER_ERR=5;x.NO_DATA_ALLOWED_ERR=6;x.NO_MODIFICATION_ALLOWED_ERR=7;x.NOT_FOUND_ERR=8;x.NOT_SUPPORTED_ERR=9;x.INUSE_ATTRIBUTE_ERR=10;x.INVALID_STATE_ERR=11;x.SYNTAX_ERR=12;x.INVALID_MODIFICATION_ERR=13;x.NAMESPACE_ERR=14;x.INVALID_ACCESS_ERR=15;x.VALIDATION_ERR=16;x.TYPE_MISMATCH_ERR=17;G_vmlCanvasManager=E;CanvasRenderingContext2D=W;CanvasGradient=v;CanvasPattern=u;DOMException=o})()}; -------------------------------------------------------------------------------- /js/jquery-ui-1.13.0.slider.min.js: -------------------------------------------------------------------------------- 1 | /*! jQuery UI - v1.13.0 - 2021-12-22 2 | * http://jqueryui.com 3 | * Includes: widget.js, keycode.js, widgets/mouse.js, widgets/slider.js 4 | * Copyright jQuery Foundation and other contributors; Licensed MIT */ 5 | 6 | !function(e){"use strict";"function"==typeof define&&define.amd?define(["jquery"],e):e(jQuery)}(function(l){"use strict";l.ui=l.ui||{};l.ui.version="1.13.0";var n,i=0,o=Array.prototype.hasOwnProperty,h=Array.prototype.slice;l.cleanData=(n=l.cleanData,function(e){for(var t,i,s=0;null!=(i=e[s]);s++)(t=l._data(i,"events"))&&t.remove&&l(i).triggerHandler("remove");n(e)}),l.widget=function(e,i,t){var s,n,a,o={},h=e.split(".")[0],r=h+"-"+(e=e.split(".")[1]);return t||(t=i,i=l.Widget),Array.isArray(t)&&(t=l.extend.apply(null,[{}].concat(t))),l.expr.pseudos[r.toLowerCase()]=function(e){return!!l.data(e,r)},l[h]=l[h]||{},s=l[h][e],n=l[h][e]=function(e,t){if(!this._createWidget)return new n(e,t);arguments.length&&this._createWidget(e,t)},l.extend(n,s,{version:t.version,_proto:l.extend({},t),_childConstructors:[]}),(a=new i).options=l.widget.extend({},a.options),l.each(t,function(t,s){function n(){return i.prototype[t].apply(this,arguments)}function a(e){return i.prototype[t].apply(this,e)}o[t]="function"==typeof s?function(){var e,t=this._super,i=this._superApply;return this._super=n,this._superApply=a,e=s.apply(this,arguments),this._super=t,this._superApply=i,e}:s}),n.prototype=l.widget.extend(a,{widgetEventPrefix:s&&a.widgetEventPrefix||e},o,{constructor:n,namespace:h,widgetName:e,widgetFullName:r}),s?(l.each(s._childConstructors,function(e,t){var i=t.prototype;l.widget(i.namespace+"."+i.widgetName,n,t._proto)}),delete s._childConstructors):i._childConstructors.push(n),l.widget.bridge(e,n),n},l.widget.extend=function(e){for(var t,i,s=h.call(arguments,1),n=0,a=s.length;n",options:{classes:{},disabled:!1,create:null},_createWidget:function(e,t){t=l(t||this.defaultElement||this)[0],this.element=l(t),this.uuid=i++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=l(),this.hoverable=l(),this.focusable=l(),this.classesElementLookup={},t!==this&&(l.data(t,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===t&&this.destroy()}}),this.document=l(t.style?t.ownerDocument:t.document||t),this.window=l(this.document[0].defaultView||this.document[0].parentWindow)),this.options=l.widget.extend({},this.options,this._getCreateOptions(),e),this._create(),this.options.disabled&&this._setOptionDisabled(this.options.disabled),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:function(){return{}},_getCreateEventData:l.noop,_create:l.noop,_init:l.noop,destroy:function(){var i=this;this._destroy(),l.each(this.classesElementLookup,function(e,t){i._removeClass(t,e)}),this.element.off(this.eventNamespace).removeData(this.widgetFullName),this.widget().off(this.eventNamespace).removeAttr("aria-disabled"),this.bindings.off(this.eventNamespace)},_destroy:l.noop,widget:function(){return this.element},option:function(e,t){var i,s,n,a=e;if(0===arguments.length)return l.widget.extend({},this.options);if("string"==typeof e)if(a={},e=(i=e.split(".")).shift(),i.length){for(s=a[e]=l.widget.extend({},this.options[e]),n=0;n=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}}),l.widget("ui.slider",l.ui.mouse,{version:"1.13.0",widgetEventPrefix:"slide",options:{animate:!1,classes:{"ui-slider":"ui-corner-all","ui-slider-handle":"ui-corner-all","ui-slider-range":"ui-corner-all ui-widget-header"},distance:0,max:100,min:0,orientation:"horizontal",range:!1,step:1,value:0,values:null,change:null,slide:null,start:null,stop:null},numPages:5,_create:function(){this._keySliding=!1,this._mouseSliding=!1,this._animateOff=!0,this._handleIndex=null,this._detectOrientation(),this._mouseInit(),this._calculateNewMax(),this._addClass("ui-slider ui-slider-"+this.orientation,"ui-widget ui-widget-content"),this._refresh(),this._animateOff=!1},_refresh:function(){this._createRange(),this._createHandles(),this._setupEvents(),this._refreshValue()},_createHandles:function(){var e,t=this.options,i=this.element.find(".ui-slider-handle"),s=[],n=t.values&&t.values.length||1;for(i.length>n&&(i.slice(n).remove(),i=i.slice(0,n)),e=i.length;e");this.handles=i.add(l(s.join("")).appendTo(this.element)),this._addClass(this.handles,"ui-slider-handle","ui-state-default"),this.handle=this.handles.eq(0),this.handles.each(function(e){l(this).data("ui-slider-handle-index",e).attr("tabIndex",0)})},_createRange:function(){var e=this.options;e.range?(!0===e.range&&(e.values?e.values.length&&2!==e.values.length?e.values=[e.values[0],e.values[0]]:Array.isArray(e.values)&&(e.values=e.values.slice(0)):e.values=[this._valueMin(),this._valueMin()]),this.range&&this.range.length?(this._removeClass(this.range,"ui-slider-range-min ui-slider-range-max"),this.range.css({left:"",bottom:""})):(this.range=l("
").appendTo(this.element),this._addClass(this.range,"ui-slider-range")),"min"!==e.range&&"max"!==e.range||this._addClass(this.range,"ui-slider-range-"+e.range)):(this.range&&this.range.remove(),this.range=null)},_setupEvents:function(){this._off(this.handles),this._on(this.handles,this._handleEvents),this._hoverable(this.handles),this._focusable(this.handles)},_destroy:function(){this.handles.remove(),this.range&&this.range.remove(),this._mouseDestroy()},_mouseCapture:function(e){var i,s,n,a,t,o,h=this,r=this.options;return!r.disabled&&(this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()},this.elementOffset=this.element.offset(),o={x:e.pageX,y:e.pageY},i=this._normValueFromMouse(o),s=this._valueMax()-this._valueMin()+1,this.handles.each(function(e){var t=Math.abs(i-h.values(e));(t=this._valueMax())return this._valueMax();var t=0=t&&(e+=0this.options.max&&(e-=i),this.max=parseFloat(e.toFixed(this._precision()))},_precision:function(){var e=this._precisionOf(this.options.step);return e=null!==this.options.min?Math.max(e,this._precisionOf(this.options.min)):e},_precisionOf:function(e){var t=e.toString(),e=t.indexOf(".");return-1===e?0:t.length-e-1},_valueMin:function(){return this.options.min},_valueMax:function(){return this.max},_refreshRange:function(e){"vertical"===e&&this.range.css({width:"",left:""}),"horizontal"===e&&this.range.css({height:"",bottom:""})},_refreshValue:function(){var t,i,e,s,n,a=this.options.range,o=this.options,h=this,r=!this._animateOff&&o.animate,u={};this._hasMultipleValues()?this.handles.each(function(e){i=(h.values(e)-h._valueMin())/(h._valueMax()-h._valueMin())*100,u["horizontal"===h.orientation?"left":"bottom"]=i+"%",l(this).stop(1,1)[r?"animate":"css"](u,o.animate),!0===h.options.range&&("horizontal"===h.orientation?(0===e&&h.range.stop(1,1)[r?"animate":"css"]({left:i+"%"},o.animate),1===e&&h.range[r?"animate":"css"]({width:i-t+"%"},{queue:!1,duration:o.animate})):(0===e&&h.range.stop(1,1)[r?"animate":"css"]({bottom:i+"%"},o.animate),1===e&&h.range[r?"animate":"css"]({height:i-t+"%"},{queue:!1,duration:o.animate}))),t=i}):(e=this.value(),s=this._valueMin(),n=this._valueMax(),i=n!==s?(e-s)/(n-s)*100:0,u["horizontal"===this.orientation?"left":"bottom"]=i+"%",this.handle.stop(1,1)[r?"animate":"css"](u,o.animate),"min"===a&&"horizontal"===this.orientation&&this.range.stop(1,1)[r?"animate":"css"]({width:i+"%"},o.animate),"max"===a&&"horizontal"===this.orientation&&this.range.stop(1,1)[r?"animate":"css"]({width:100-i+"%"},o.animate),"min"===a&&"vertical"===this.orientation&&this.range.stop(1,1)[r?"animate":"css"]({height:i+"%"},o.animate),"max"===a&&"vertical"===this.orientation&&this.range.stop(1,1)[r?"animate":"css"]({height:100-i+"%"},o.animate))},_handleEvents:{keydown:function(e){var t,i,s,n=l(e.target).data("ui-slider-handle-index");switch(e.keyCode){case l.ui.keyCode.HOME:case l.ui.keyCode.END:case l.ui.keyCode.PAGE_UP:case l.ui.keyCode.PAGE_DOWN:case l.ui.keyCode.UP:case l.ui.keyCode.RIGHT:case l.ui.keyCode.DOWN:case l.ui.keyCode.LEFT:if(e.preventDefault(),!this._keySliding&&(this._keySliding=!0,this._addClass(l(e.target),null,"ui-state-active"),!1===this._start(e,n)))return}switch(s=this.options.step,t=i=this._hasMultipleValues()?this.values(n):this.value(),e.keyCode){case l.ui.keyCode.HOME:i=this._valueMin();break;case l.ui.keyCode.END:i=this._valueMax();break;case l.ui.keyCode.PAGE_UP:i=this._trimAlignValue(t+(this._valueMax()-this._valueMin())/this.numPages);break;case l.ui.keyCode.PAGE_DOWN:i=this._trimAlignValue(t-(this._valueMax()-this._valueMin())/this.numPages);break;case l.ui.keyCode.UP:case l.ui.keyCode.RIGHT:if(t===this._valueMax())return;i=this._trimAlignValue(t+s);break;case l.ui.keyCode.DOWN:case l.ui.keyCode.LEFT:if(t===this._valueMin())return;i=this._trimAlignValue(t-s)}this._slide(e,n,i)},keyup:function(e){var t=l(e.target).data("ui-slider-handle-index");this._keySliding&&(this._keySliding=!1,this._stop(e,t),this._change(e,t),this._removeClass(l(e.target),null,"ui-state-active"))}}})}); -------------------------------------------------------------------------------- /html/example_use.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Lorikeet Spectrum Viewer 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |

Lorikeet Plugin Example

27 | 28 | 29 |
30 | 31 | 795 | 796 | 797 | 798 | -------------------------------------------------------------------------------- /js/peptide.js: -------------------------------------------------------------------------------- 1 | // $LastChangedDate$ 2 | // $LastChangedBy$ 3 | // $LastChangedRevision$ 4 | 5 | // ----------------------------------------------------------------------------- 6 | // Peptide sequence and modifications 7 | // ----------------------------------------------------------------------------- 8 | function Peptide(seq, staticModifications, varModifications, ntermModification, ctermModification, maxNeutralLossCount) { 9 | 10 | var sequence = seq; 11 | if(!sequence) { 12 | sequence = ""; 13 | } 14 | 15 | var ntermMod = ntermModification; 16 | var ctermMod = ctermModification; 17 | var staticMods = []; 18 | var varMods = []; 19 | var potentialLosses_custom = {}; 20 | var potentialLosses_lorikeet = {}; 21 | var potentialLossesAtIndex = []; 22 | var nterm_totalLossOptions = []; 23 | var cterm_totalLossOptions = []; 24 | var maxNeutralLossCount = maxNeutralLossCount; 25 | 26 | var debug = false; 27 | 28 | _initNeutralLosses(); 29 | _initStaticMods(); 30 | _initVarMods(); 31 | // calculate the total loss options at each index using only custom neutral losses. 32 | _calculateTotalLossOptions(null, maxNeutralLossCount); 33 | 34 | 35 | //---------------------------------------------------------------------------------------- 36 | //---------------------------------------------------------------------------------------- 37 | this.sequence = function () { 38 | return sequence; 39 | } 40 | 41 | this.varMods = function() { 42 | return varMods; 43 | } 44 | 45 | // index: index in the seq. 46 | // If this is a N-term sequence we will sum up the mass of the amino acids in the sequence up-to index (exclusive). 47 | // If this is a C-term sequence we will sum up the mass of the amino acids in the sequence starting from index (inclusive) 48 | // modification masses are added 49 | this.getSeqMassMono = function _seqMassMono(index, term) { 50 | return _getSeqMass(index, term, "mono"); 51 | } 52 | 53 | // index: index in the seq. 54 | // If this is a N-term sequence we will sum up the mass of the amino acids in the sequence up-to index (exclusive). 55 | // If this is a C-term sequence we will sum up the mass of the amino acids in the sequence starting from index (inclusive) 56 | // modification masses are added 57 | this.getSeqMassAvg = function _seqMassAvg(index, term) { 58 | return _getSeqMass(index, term, "avg"); 59 | } 60 | 61 | // Returns the monoisotopic neutral mass of the peptide; modifications added. N-term H and C-term OH are added 62 | this.getNeutralMassMono = function _massNeutralMono() { 63 | 64 | var mass = 0; 65 | var aa_obj = new AminoAcid(); 66 | if(sequence) { 67 | for(var i = 0; i < sequence.length; i++) { 68 | var aa = aa_obj.get(sequence.charAt(i)); 69 | mass += aa.mono; 70 | } 71 | } 72 | 73 | mass = _addTerminalModMass(mass, "n"); 74 | mass = _addTerminalModMass(mass, "c"); 75 | mass = _addResidueModMasses(mass, sequence.length, "n"); 76 | // add N-terminal H 77 | mass = mass + Ion.MASS_H_1; 78 | // add C-terminal OH 79 | mass = mass + Ion.MASS_O_16 + Ion.MASS_H_1; 80 | 81 | return mass; 82 | } 83 | 84 | //Returns the avg neutral mass of the peptide; modifications added. N-term H and C-term OH are added 85 | this.getNeutralMassAvg = function _massNeutralAvg() { 86 | 87 | var mass = 0; 88 | var aa_obj = new AminoAcid(); 89 | if(sequence) { 90 | for(var i = 0; i < sequence.length; i++) { 91 | var aa = aa_obj.get(sequence.charAt(i)); 92 | mass += aa.avg; 93 | } 94 | } 95 | 96 | mass = _addTerminalModMass(mass, "n"); 97 | mass = _addTerminalModMass(mass, "c"); 98 | mass = _addResidueModMasses(mass, sequence.length, "n"); 99 | // add N-terminal H 100 | mass = mass + Ion.MASS_H; 101 | // add C-terminal OH 102 | mass = mass + Ion.MASS_O + Ion.MASS_H; 103 | 104 | return mass; 105 | } 106 | 107 | this.getPotentialLosses = function _getPotentialLosses(sion) 108 | { 109 | var term = sion.term; 110 | var fragmentIndex = sion.fragmentIndex; 111 | if(term == 'n') 112 | { 113 | return nterm_totalLossOptions[fragmentIndex - 1]; 114 | } 115 | if(term == 'c') 116 | { 117 | return cterm_totalLossOptions[sequence.length - fragmentIndex]; 118 | } 119 | } 120 | 121 | this.customPotentialLosses = potentialLosses_custom; 122 | this.lorikeetPotentialLosses = potentialLosses_lorikeet; 123 | this.getLossForLabel = function _getLossForLabel(lossLabel) 124 | { 125 | var loss = potentialLosses_custom[lossLabel]; 126 | if(loss) return loss; 127 | loss = potentialLosses_lorikeet[lossLabel]; 128 | if(loss) return loss; 129 | } 130 | this.recalculateLossOptions = function _recalculate(selectedLossOptions, maxLossCount) 131 | { 132 | _calculateTotalLossOptions(selectedLossOptions, maxLossCount); 133 | } 134 | 135 | //---------------------------------------------------------------------------------------- 136 | //---------------------------------------------------------------------------------------- 137 | 138 | function _initStaticMods() 139 | { 140 | if(staticModifications) { 141 | for(var i = 0; i < staticModifications.length; i += 1) { 142 | var mod = staticModifications[i]; 143 | staticMods[mod.aa.code] = mod; 144 | } 145 | 146 | for(var i = 0; i < sequence.length; i += 1) { 147 | var mod = staticMods[sequence.charAt(i)]; 148 | if(mod && mod.losses) { 149 | for(var j = 0; j < mod.losses.length; j++) { 150 | _addCustomLoss(i, mod.losses[j]); 151 | } 152 | } 153 | } 154 | } 155 | } 156 | 157 | function _initVarMods() 158 | { 159 | if(varModifications) { 160 | for(var i = 0; i < varModifications.length; i += 1) { 161 | var mod = varModifications[i]; 162 | if(mod) { 163 | varMods[mod.position] = mod; 164 | 165 | if(mod.losses) { 166 | for(var j = 0; j < mod.losses.length; j++) { 167 | var modIndex_0based = mod.position - 1; // mod.position is a 1-based index 168 | _addCustomLoss(modIndex_0based, mod.losses[j]); 169 | } 170 | } 171 | } 172 | } 173 | } 174 | } 175 | 176 | function _addCustomLoss(index, loss) 177 | { 178 | // Example: {avgLossMass: "97.995", monoLossMass: "97.977", formula: "H3PO4"} 179 | if(loss && loss.avgLossMass && loss.avgLossMass > 0.0 && loss.monoLossMass && loss.monoLossMass > 0.0) 180 | { 181 | var neutralLoss = new NeutralLoss(loss.monoLossMass, loss.avgLossMass, loss.formula, loss.label); 182 | potentialLossesAtIndex[index].push(neutralLoss); 183 | potentialLosses_custom[neutralLoss.label()] = neutralLoss; 184 | } 185 | } 186 | 187 | function _initNeutralLosses() 188 | { 189 | for(var i = 0; i < sequence.length; i++) { 190 | potentialLossesAtIndex[i] = []; // potential neutral loss possibilities at an index in the peptide sequence 191 | } 192 | 193 | var ammoniaLoss = NeutralLoss.AmmoniaLoss(); 194 | var waterLoss = NeutralLoss.WaterLoss(); 195 | var phosphoLoss = NeutralLoss.PhosphoLoss(); 196 | potentialLosses_lorikeet[ammoniaLoss.label()] = ammoniaLoss; 197 | potentialLosses_lorikeet[waterLoss.label()] = waterLoss; 198 | potentialLosses_lorikeet[phosphoLoss.label()] = phosphoLoss; 199 | 200 | for(var i = 0; i < sequence.length; i += 1) 201 | { 202 | var aa = sequence.charAt(i); 203 | if(aa == 'K' || aa == 'R' || aa == 'Q' || aa == 'N') 204 | { 205 | potentialLossesAtIndex[i].push(ammoniaLoss); 206 | } 207 | if (aa == 'S' || aa == 'T' || aa == 'E' || aa == 'D') 208 | { 209 | potentialLossesAtIndex[i].push(waterLoss); 210 | } 211 | if (aa == 'S' || aa == 'T' || aa == 'Y') 212 | { 213 | potentialLossesAtIndex[i].push(phosphoLoss); 214 | } 215 | } 216 | } 217 | 218 | function _calculateTotalLossOptions(selectedLosses, maxLossCount) 219 | { 220 | if(!maxLossCount) 221 | maxLossCount = 1; 222 | 223 | 224 | var selectedLossLabels = {}; 225 | if(!selectedLosses) 226 | { 227 | for(var lossLabel in potentialLosses_custom) 228 | { 229 | selectedLossLabels[lossLabel] = true; 230 | } 231 | } 232 | else 233 | { 234 | for(var i = 0; i < selectedLosses.length; i += 1) 235 | { 236 | if(selectedLosses[i]) 237 | { 238 | selectedLossLabels[selectedLosses[i].label()] = true; 239 | } 240 | } 241 | } 242 | _initNeutralLossArrays(maxLossCount); 243 | _calculateTotalLossOptionsForTerm('n', selectedLossLabels, maxLossCount); 244 | _calculateTotalLossOptionsForTerm('c', selectedLossLabels, maxLossCount); 245 | 246 | if(debug) 247 | { 248 | _printPotentialLosses(); 249 | _printNeutralLossCombinations(); 250 | } 251 | } 252 | 253 | function _initNeutralLossArrays(maxLossCount) 254 | { 255 | for(var i = 0; i < sequence.length; i += 1) 256 | { 257 | nterm_totalLossOptions[i] = []; 258 | cterm_totalLossOptions[i] = []; 259 | for(var j = 0; j <= maxLossCount; j += 1) 260 | { 261 | nterm_totalLossOptions[i][j] = []; 262 | cterm_totalLossOptions[i][j] = []; 263 | } 264 | } 265 | } 266 | 267 | function _calculateTotalLossOptionsForTerm(term, selectedLossLabels, maxLossCount) 268 | { 269 | if(term == 'n') 270 | { 271 | for(var i = 0; i < sequence.length; i += 1) { 272 | _calculate(i, 0, 1, selectedLossLabels, nterm_totalLossOptions, maxLossCount); 273 | } 274 | } 275 | if(term == 'c') 276 | { 277 | var s = sequence.length - 1; 278 | for(var i = s; i >= 0; i -= 1) { 279 | _calculate(i, s, -1, selectedLossLabels, cterm_totalLossOptions, maxLossCount); 280 | } 281 | } 282 | } 283 | 284 | // totalLossOptionsArray[i] = lossOptions at index i in sequence. 285 | // totalLossOptionsArray[i][j] = LossCombinationList with j losses at index i in the sequence. 286 | // Each LossCombinationList contains an array of possible LossCombinations of j losses; 287 | function _calculate(i, s, incr, selectedLossLabels, totalLossOptionsArray, maxLossCount) { 288 | 289 | var lossOptions = potentialLossesAtIndex[i]; 290 | var validLossOptions = []; 291 | for (var l = 0; l < lossOptions.length; l += 1) { // these are the potential losses at index i in the sequence. 292 | var loss = lossOptions[l]; 293 | if(!(loss.label() in selectedLossLabels)) 294 | continue; 295 | else 296 | validLossOptions.push(loss); 297 | } 298 | 299 | if(validLossOptions.length == 0) 300 | { 301 | if (i != s) 302 | { 303 | totalLossOptionsArray[i] = totalLossOptionsArray[i - incr]; 304 | } 305 | else 306 | { 307 | for(var j = 1; j <= maxLossCount; j += 1) 308 | { 309 | totalLossOptionsArray[i][j] = new LossCombinationList(j); 310 | } 311 | } 312 | return; 313 | } 314 | 315 | var loss_options_at_i = []; 316 | totalLossOptionsArray[i] = loss_options_at_i; 317 | if(i == s) 318 | { 319 | for(j = 1; j <= maxLossCount; j += 1) 320 | { 321 | loss_options_at_i[j] = new LossCombinationList(j); 322 | } 323 | } 324 | else 325 | { 326 | var loss_options_before_i = totalLossOptionsArray[i - incr]; 327 | for(j = 1; j <= maxLossCount; j += 1) 328 | { 329 | loss_options_at_i[j] = LossCombinationList.copyLossCombinationList(loss_options_before_i[j]); 330 | } 331 | } 332 | 333 | for(var l = 0; l < validLossOptions.length; l += 1) 334 | { 335 | var loss = validLossOptions[l]; 336 | 337 | // iterate in reverse order so that we don't add the loss 338 | // in each iteration. 339 | for(var j = maxLossCount; j >= 1; j -= 1) 340 | { 341 | if(j == 1) 342 | { 343 | var loss_combi_list_at_j = loss_options_at_i[j]; 344 | var loss_combi = new LossCombination(); 345 | loss_combi.addLoss(loss); 346 | loss_combi_list_at_j.addLossCombination(loss_combi); 347 | } 348 | else 349 | { 350 | var loss_combi_list_at_jminus1 = loss_options_at_i[j-1]; 351 | var loss_combi_list_at_j = LossCombinationList.copyLossCombinationList(loss_combi_list_at_jminus1); 352 | loss_options_at_i[j] = loss_combi_list_at_j; 353 | for(var k = 0; k < loss_combi_list_at_j.lossCombinationCount(); k += 1) 354 | { 355 | loss_combi_list_at_j.getLossCombination(k).addLoss(loss); 356 | } 357 | } 358 | } 359 | } 360 | } 361 | 362 | function _getMassesWithLoss(lossOptions, mass) { 363 | var massesWithLoss = []; 364 | var j = 0; 365 | for (var i = 0; i < lossOptions.length; i += 1) { 366 | var loss = lossOptions[i]; 367 | if (loss > 0.0) { 368 | var massWithLoss = mass - loss; 369 | massesWithLoss[j] = {mass:massWithLoss, loss:loss}; 370 | j++; 371 | } 372 | } 373 | return massesWithLoss; 374 | } 375 | 376 | function _addResidueModMasses(seqMass, index, term) { 377 | 378 | var mass = seqMass; 379 | var slice = new _Slice(index, term); 380 | for( var i = slice.from; i < slice.to; i += 1) { 381 | // add any static modifications 382 | var mod = staticMods[sequence.charAt(i)]; 383 | if(mod) { 384 | mass += mod.modMass; 385 | } 386 | // add any variable modifications 387 | mod = varMods[i+1]; // varMods index in the sequence is 1-based 388 | if(mod) { 389 | mass += mod.modMass; 390 | } 391 | } 392 | 393 | return mass; 394 | } 395 | 396 | function _getSeqMass(index, term, massType) { 397 | 398 | var mass = 0; 399 | var aa_obj = new AminoAcid(); 400 | if(sequence) { 401 | var slice = new _Slice(index, term); 402 | for( var i = slice.from; i < slice.to; i += 1) { 403 | var aa = aa_obj.get(sequence[i]); 404 | mass += aa[massType]; 405 | } 406 | } 407 | 408 | mass = _addTerminalModMass(mass, term); 409 | mass = _addResidueModMasses(mass, index, term); 410 | return mass; 411 | } 412 | 413 | function _addTerminalModMass(seqMass, term) { 414 | 415 | var mass = seqMass; 416 | // add any terminal modifications 417 | if(term == "n" && ntermMod) 418 | mass += ntermMod; 419 | if(term == "c" && ctermMod) 420 | mass += ctermMod; 421 | 422 | return mass; 423 | } 424 | 425 | function _Slice(index, term) { 426 | if(term == "n") { 427 | this.from = 0; 428 | this.to = index; 429 | } 430 | if(term == "c") { 431 | this.from = index; 432 | this.to = sequence.length; 433 | } 434 | } 435 | 436 | function _printNeutralLossCombinations() { 437 | 438 | for(var i = 1; i < sequence.length; i += 1) 439 | { 440 | var subseq = sequence.substring(0, i); 441 | var lossOpts = nterm_totalLossOptions[i]; 442 | _log(subseq + " -- "); 443 | for(var j = 1; j < lossOpts.length; j += 1) 444 | { 445 | _log(" -- "+j); 446 | var lossesAt_j = lossOpts[j]; 447 | var count = lossesAt_j.lossCombinationCount(); 448 | for (var k = 0; k < count; k += 1) 449 | { 450 | var lossCombo = lossesAt_j.getLossCombination(k); 451 | _log("---- " + lossCombo.getLabels()); 452 | } 453 | } 454 | } 455 | 456 | for(var i = sequence.length - 1; i >= 0; i -= 1) 457 | { 458 | var subseq = sequence.substring(i, sequence.length); 459 | var lossOpts = cterm_totalLossOptions[i]; 460 | _log(subseq + " -- "); 461 | for(var j = 1; j < lossOpts.length; j += 1) 462 | { 463 | _log(" -- "+j); 464 | var lossesAt_j = lossOpts[j]; 465 | var count = lossesAt_j.lossCombinationCount(); 466 | for (var k = 0; k < count; k += 1) 467 | { 468 | var lossCombo = lossesAt_j.getLossCombination(k); 469 | _log("---- " + lossCombo.getLabels()); 470 | } 471 | } 472 | } 473 | } 474 | 475 | function _printPotentialLosses() { 476 | for (var i = 0; i < potentialLossesAtIndex.length; i += 1) { 477 | var losses = potentialLossesAtIndex[i]; 478 | if (losses.length > 0) 479 | _log("Potential Losses at " + i + " " + sequence.charAt(i)); 480 | for (var j = 0; j < losses.length; j++) { 481 | var loss = losses[j]; 482 | _log(loss.monoLossMass + ", " + loss.avgLossMass + ", " + loss.formula + ", " + loss.label()); 483 | } 484 | } 485 | } 486 | 487 | function _log(message) 488 | { 489 | if(debug) 490 | console.log(message); 491 | } 492 | } 493 | 494 | 495 | //----------------------------------------------------------------------------- 496 | // Modification 497 | //----------------------------------------------------------------------------- 498 | function Modification(aminoAcid, mass, losses) { 499 | this.aa = aminoAcid; 500 | this.modMass = mass; 501 | this.losses = losses; 502 | } 503 | 504 | function VariableModification(pos, mass, aminoAcid, losses) { 505 | this.position = parseInt(pos); 506 | this.aa = aminoAcid; 507 | this.modMass = mass; 508 | this.losses = losses; 509 | } 510 | //----------------------------------------------------------------------------- 511 | // Neutral loss 512 | //----------------------------------------------------------------------------- 513 | function NeutralLoss(lossMassMono, lossMassAvg, formula, label) 514 | { 515 | this.monoLossMass = lossMassMono; 516 | if(!this.monoLossMass) 517 | this.monoLossMass = 0.0; 518 | this.avgLossMass = lossMassAvg; 519 | if(!this.avgLossMass) 520 | this.avgLossMass = 0.0; 521 | this.formula = formula; 522 | this.userLabel = label; 523 | var _htmlLabel; 524 | 525 | this.longLabel = function _getLongLabel() 526 | { 527 | if(formula) 528 | { 529 | return formula + " ("+this.label()+")"; 530 | } 531 | else 532 | { 533 | return this.label; 534 | } 535 | } 536 | 537 | this.label = function _getLabel() 538 | { 539 | if(this.userLabel) return this.userLabel; 540 | return "-"+Math.round(this.monoLossMass); 541 | } 542 | 543 | this.htmlLabel = function _getHtmlLabel() 544 | { 545 | if(_htmlLabel) 546 | return _htmlLabel; 547 | 548 | _htmlLabel = ""; 549 | // html += H2O (o) 550 | if(formula) 551 | { 552 | for (var i = 0; i < formula.length; i++) 553 | { 554 | var charAt = formula.charAt(i); 555 | if(!isNaN(charAt)) 556 | { 557 | _htmlLabel += ''+charAt+''; 558 | } 559 | else 560 | { 561 | _htmlLabel += charAt; 562 | } 563 | } 564 | _htmlLabel += " ("; 565 | } 566 | _htmlLabel += ''+this.label()+''; 567 | if(formula) 568 | { 569 | _htmlLabel += ")"; 570 | } 571 | 572 | return _htmlLabel; 573 | } 574 | } 575 | 576 | NeutralLoss.AmmoniaLoss = function _getAmmoniaLoss() 577 | { 578 | return new NeutralLoss(Ion.AmmoniaLossMass_mono, Ion.AmmoniaLossMass_avg, "NH3", "*"); 579 | } 580 | NeutralLoss.WaterLoss = function _getWaterLoss() 581 | { 582 | return new NeutralLoss(Ion.WaterLossMass_mono, Ion.WaterLossMass_avg, "H2O", "o"); 583 | } 584 | NeutralLoss.PhosphoLoss = function _getPhosphoLoss() 585 | { 586 | return new NeutralLoss(Ion.PhosphoLossMass_mono, Ion.PhosphoLossMass_avg, "H3PO4", "p"); 587 | } 588 | 589 | function LossCombination() 590 | { 591 | this.losses = []; 592 | 593 | this.addLoss = function _addLoss(loss) 594 | { 595 | this.losses.push(loss); 596 | } 597 | 598 | this.getLabels = function _getLabels() 599 | { 600 | var label = ""; 601 | for(var l = 0; l < this.losses.length; l += 1) 602 | { 603 | label += ", "+this.losses[l].label(); 604 | } 605 | return label; 606 | } 607 | 608 | this.getLabel = function _getLabel() 609 | { 610 | if(this.losses.length == 1) 611 | { 612 | return " " + this.losses[0].label(); 613 | } 614 | else 615 | { 616 | var lossMass = 0; 617 | for(var i = 0; i < this.losses.length; i += 1) 618 | { 619 | lossMass += this.losses[i].monoLossMass; 620 | } 621 | return " -" + Math.round(lossMass); 622 | } 623 | } 624 | 625 | this.getTotalLossMass = function _getTotalLossMass(massType) 626 | { 627 | var totalLoss = 0; 628 | for(var l = 0; l < this.losses.length; l += 1) 629 | { 630 | if(massType == 'mono') 631 | { 632 | totalLoss += this.losses[l].monoLossMass; 633 | } 634 | else if(massType == 'avg') 635 | { 636 | totalLoss += this.losses[l].avgLossMass; 637 | } 638 | } 639 | return totalLoss; 640 | } 641 | } 642 | 643 | LossCombination.copyLossCombination = function _copyLossCombination(originalLossCombination) 644 | { 645 | var newLossCombination = new LossCombination(); 646 | var losses = originalLossCombination.losses; 647 | for(var l = 0; l < losses.length; l += 1) 648 | { 649 | newLossCombination.addLoss(losses[l]); 650 | } 651 | return newLossCombination; 652 | } 653 | 654 | function LossCombinationList(numLosses) 655 | { 656 | this.numLosses = numLosses; 657 | this.lossCombinations = []; 658 | 659 | this.lossCombinationCount = function _getLossCombinationCount() 660 | { 661 | return this.lossCombinations.length; 662 | } 663 | 664 | this.addLossCombination = function _addLossCombination(lossCombination) 665 | { 666 | var found = false; 667 | 668 | for(var l = 0; l < this.lossCombinationCount(); l += 1) 669 | { 670 | if(this.lossCombinations[l].getTotalLossMass('mono') == lossCombination.getTotalLossMass('mono')) 671 | { 672 | found = true; 673 | } 674 | } 675 | if(!found) 676 | { 677 | this.lossCombinations.push(lossCombination); 678 | } 679 | } 680 | 681 | this.getLossCombination = function _getLossCombinationAtIndex(index) 682 | { 683 | if(index >= 0 && index < this.lossCombinationCount()) 684 | { 685 | return this.lossCombinations[index]; 686 | } 687 | } 688 | } 689 | LossCombinationList.copyLossCombinationList = function _copyLossCombinationList(originalList) 690 | { 691 | var newLossCombinationList = new LossCombinationList(originalList.numLosses); 692 | var count = originalList.lossCombinationCount(); 693 | for(var l = 0; l < count; l += 1) 694 | { 695 | var originalLossCombination = originalList.getLossCombination(l); 696 | var lossCombination = LossCombination.copyLossCombination(originalLossCombination); 697 | newLossCombinationList.addLossCombination(lossCombination); 698 | } 699 | return newLossCombinationList; 700 | } 701 | 702 | 703 | 704 | -------------------------------------------------------------------------------- /html/example_user_reporter_ions.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Lorikeet Spectrum Viewer 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |

Lorikeet Plugin Example

27 | 28 |
29 | The userReporterIons option allows you to find and label specific peaks in the MS2 30 | spectrum based on their expected m/z value. In the example below, 498.24 and 1608.54 were 31 | passed in as reporter ion masses using the following option: 32 |
33 |
34 |
userReporterIons:[498.24, 1608.54]
35 |
36 | 37 | 38 |
39 | 40 | 805 | 806 | 807 | 808 | --------------------------------------------------------------------------------