diff --git a/Changelog b/Changelog index 86c19e47..fe5923c9 100644 --- a/Changelog +++ b/Changelog @@ -2,4 +2,6 @@ ### Changed ### Fixed -- Pipeline functions were restored. \ No newline at end of file +- Pipeline functions were restored. +- Ion Purity calculation was fixed, and now supports msconvert 3.20 +- Fixed file discovery for filtering on Windows \ No newline at end of file diff --git a/Makefile b/Makefile index bfa2ba4b..46721863 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ BINARY = philosopher VERSION = $(shell date +%Y%m%d) BUILD = $(shell date +%Y%m%d%H%M) -TAG = v3.2.5 +TAG = v3.2.6 LDFLAGS = -ldflags "-w -s -X main.version=${TAG} -X main.build=${BUILD}" diff --git a/cmd/labelquant.go b/cmd/labelquant.go index 2213fd40..f14202cd 100644 --- a/cmd/labelquant.go +++ b/cmd/labelquant.go @@ -32,9 +32,7 @@ var labelquantCmd = &cobra.Command{ msg.InputNotFound(errors.New("You need to specify the experiment Plex"), "fatal") } - // hardcoded tmt for now msg.Executing("Isobaric-label quantification ", Version) - //m.Quantify.Brand = "tmt" if strings.EqualFold(strings.ToLower(m.Quantify.Format), "mzml") { m.Quantify.Format = "mzML" diff --git a/lib/aba/pep.go b/lib/aba/pep.go index 861e1474..b13e91c0 100644 --- a/lib/aba/pep.go +++ b/lib/aba/pep.go @@ -47,27 +47,36 @@ func peptideLevelAbacus(m met.Data, args []string) { var labels DataSetLabelNames labels.LabelName = make(map[string]string) - // collect interact full file names files, _ := ioutil.ReadDir(i) + + // collect interact full file names for _, f := range files { if strings.Contains(f.Name(), "pep.xml") { interactFile := fmt.Sprintf("%s%s%s", i, string(filepath.Separator), f.Name()) absPath, _ := filepath.Abs(interactFile) xmlFiles = append(xmlFiles, absPath) } - } + if strings.Contains(f.Name(), "annotation") { + var annot = fmt.Sprintf("%s%s%s", i, string(filepath.Separator), f.Name()) + labels.Name = annot - var annot = fmt.Sprintf("%s%sannotation.txt", i, string(filepath.Separator)) - if strings.Contains(i, string(filepath.Separator)) { - i = strings.Replace(i, string(filepath.Separator), "", -1) - labels.Name = i - } else { - labels.Name = i + if len(m.Quantify.Annot) > 0 { + labels.LabelName = getLabelNames(annot) + } + } } - if len(m.Quantify.Annot) > 0 { - labels.LabelName = getLabelNames(annot) - } + // var annot = fmt.Sprintf("%s%sannotation.txt", i, string(filepath.Separator)) + // if strings.Contains(i, string(filepath.Separator)) { + // i = strings.Replace(i, string(filepath.Separator), "", -1) + // labels.Name = i + // } else { + // labels.Name = i + // } + + // if len(m.Quantify.Annot) > 0 { + // labels.LabelName = getLabelNames(annot) + // } // collect project names prjName := i diff --git a/lib/aba/pro.go b/lib/aba/pro.go index 91c3b7ae..e7180121 100644 --- a/lib/aba/pro.go +++ b/lib/aba/pro.go @@ -63,19 +63,27 @@ func proteinLevelAbacus(m met.Data, args []string) { absPath, _ := filepath.Abs(interactFile) xmlFiles = append(xmlFiles, absPath) } - } + if strings.Contains(f.Name(), "annotation") { + var annot = fmt.Sprintf("%s%s%s", i, string(filepath.Separator), f.Name()) + labels.Name = annot - var annot = fmt.Sprintf("%s%sannotation.txt", i, string(filepath.Separator)) - if strings.Contains(i, string(filepath.Separator)) { - i = strings.Replace(i, string(filepath.Separator), "", -1) - labels.Name = i - } else { - labels.Name = i + if len(m.Quantify.Annot) > 0 { + labels.LabelName = getLabelNames(annot) + } + } } - if len(m.Quantify.Annot) > 0 { - labels.LabelName = getLabelNames(annot) - } + // var annot = fmt.Sprintf("%s%sannotation.txt", i, string(filepath.Separator)) + // if strings.Contains(i, string(filepath.Separator)) { + // i = strings.Replace(i, string(filepath.Separator), "", -1) + // labels.Name = i + // } else { + // labels.Name = i + // } + + // if len(m.Quantify.Annot) > 0 { + // labels.LabelName = getLabelNames(annot) + // } // collect project names prjName := i diff --git a/lib/fil/fil.go b/lib/fil/fil.go index bba5f0ec..cc284204 100644 --- a/lib/fil/fil.go +++ b/lib/fil/fil.go @@ -200,7 +200,7 @@ func readPepXMLInput(xmlFile, decoyTag, temp string, models bool, calibratedMass fileCheckList = append(fileCheckList, xmlFile) files[xmlFile] = 0 } else { - glob := fmt.Sprintf("%s/*pep.xml", xmlFile) + glob := fmt.Sprintf("%s%s*pep.xml", xmlFile, string(filepath.Separator)) list, _ := filepath.Glob(glob) if len(list) == 0 { diff --git a/lib/mzn/mzn.go b/lib/mzn/mzn.go index 87e24046..b0ee45af 100644 --- a/lib/mzn/mzn.go +++ b/lib/mzn/mzn.go @@ -13,8 +13,9 @@ import ( "philosopher/lib/msg" - "github.com/sirupsen/logrus" "philosopher/lib/psi" + + "github.com/sirupsen/logrus" ) // MsData top struct @@ -46,8 +47,9 @@ type Precursor struct { ParentScan string ChargeState int SelectedIon float64 + SelectedIonIntensity float64 TargetIon float64 - PeakIntensity float64 + TargetIonIntensity float64 IsolationWindowLowerOffset float64 IsolationWindowUpperOffset float64 } @@ -228,7 +230,7 @@ func processSpectrum(mzSpec psi.Spectrum) Spectrum { if e != nil { msg.CastFloatToString(e, "fatal") } - spec.Precursor.PeakIntensity = val + spec.Precursor.SelectedIonIntensity = val } } } diff --git a/lib/mzn/mzn_test.go b/lib/mzn/mzn_test.go index 2340ef76..497b0247 100644 --- a/lib/mzn/mzn_test.go +++ b/lib/mzn/mzn_test.go @@ -100,8 +100,8 @@ func TestMS2Spectra(t *testing.T) { t.Errorf("Spectrum target ion is incorrect, got %f, want %f", spec.Precursor.TargetIon, 391.2) } - if spec.Precursor.PeakIntensity != 3.58558525e+06 { - t.Errorf("Spectrum precursor intensity is incorrect, got %f, want %f", spec.Precursor.PeakIntensity, 3.58558525e+06) + if spec.Precursor.SelectedIonIntensity != 3.58558525e+06 { + t.Errorf("Spectrum precursor intensity is incorrect, got %f, want %f", spec.Precursor.SelectedIonIntensity, 3.58558525e+06) } if spec.Precursor.IsolationWindowLowerOffset != 0.34999999404 { diff --git a/lib/qua/iso.go b/lib/qua/iso.go index e24a160b..49c77fad 100644 --- a/lib/qua/iso.go +++ b/lib/qua/iso.go @@ -24,6 +24,9 @@ func calculateIonPurity(d, f string, mz mzn.MsData, evi []rep.PSMEvidence) []rep var indexedMS1 = make(map[string]mzn.Spectrum) var indexedMS2 = make(map[string]mzn.Spectrum) + var MS1Peaks = make(map[string][]float64) + var MS1Int = make(map[string][]float64) + for i := range mz.Spectra { if mz.Spectra[i].Level == "1" { @@ -39,6 +42,9 @@ func calculateIonPurity(d, f string, mz mzn.MsData, evi []rep.PSMEvidence) []rep indexedMS1[paddedScan] = mz.Spectra[i] + MS1Peaks[paddedScan] = mz.Spectra[i].Mz.DecodedStream + MS1Int[paddedScan] = mz.Spectra[i].Intensity.DecodedStream + } else if mz.Spectra[i].Level == "2" { if mz.Spectra[i].Precursor.IsolationWindowLowerOffset == 0 && mz.Spectra[i].Precursor.IsolationWindowUpperOffset == 0 { @@ -63,10 +69,17 @@ func calculateIonPurity(d, f string, mz mzn.MsData, evi []rep.PSMEvidence) []rep mz.Spectra[i].Precursor.ParentIndex = paddedPI mz.Spectra[i].Precursor.ParentScan = paddedPS - indexedMS2[paddedScan] = mz.Spectra[i] + stream := MS1Peaks[paddedPS] - } + for j := range stream { + if stream[j] >= (mz.Spectra[i].Precursor.TargetIon-mz.Spectra[i].Precursor.IsolationWindowLowerOffset) && stream[j] <= (mz.Spectra[i].Precursor.TargetIon+mz.Spectra[i].Precursor.IsolationWindowUpperOffset) { + mz.Spectra[i].Precursor.TargetIonIntensity = MS1Int[mz.Spectra[i].Precursor.ParentScan][j] + break + } + } + indexedMS2[paddedScan] = mz.Spectra[i] + } } for i := range evi { @@ -98,14 +111,16 @@ func calculateIonPurity(d, f string, mz mzn.MsData, evi []rep.PSMEvidence) []rep var isotopePackage = make(map[float64]float64) - isotopePackage[v2.Precursor.TargetIon] = v2.Precursor.PeakIntensity - isotopesInt := v2.Precursor.PeakIntensity + isotopePackage[v2.Precursor.TargetIon] = v2.Precursor.TargetIonIntensity + isotopesInt := v2.Precursor.TargetIonIntensity for k, v := range ions { for _, m := range mzRatio { if math.Abs(v2.Precursor.TargetIon-k) <= (m+0.02) && math.Abs(v2.Precursor.TargetIon-k) >= (m-0.02) { - isotopePackage[k] = v - isotopesInt += v + if v != v2.Precursor.TargetIonIntensity { + isotopePackage[k] = v + isotopesInt += v + } break } } @@ -117,11 +132,7 @@ func calculateIonPurity(d, f string, mz mzn.MsData, evi []rep.PSMEvidence) []rep evi[i].Purity = uti.Round((isotopesInt / isolationWindowSummedInt), 5, 2) } - if evi[i].Purity > 1 { - evi[i].Purity = 1 - } } - } return evi diff --git a/lib/qua/lfq.go b/lib/qua/lfq.go index 89414398..84eb4c31 100644 --- a/lib/qua/lfq.go +++ b/lib/qua/lfq.go @@ -8,16 +8,16 @@ import ( "sort" "strings" + "philosopher/lib/bio" "philosopher/lib/msg" + "philosopher/lib/uti" - "philosopher/lib/bio" "philosopher/lib/mzn" "philosopher/lib/rep" "github.com/sirupsen/logrus" ) -// // peakIntensity collects PSM intensities from the apex peak func peakIntensity(evi rep.Evidence, dir, format string, rTWin, pTWin, tol float64, isIso bool) rep.Evidence { logrus.Info("Indexing PSM information") @@ -31,8 +31,10 @@ func peakIntensity(evi rep.Evidence, dir, format string, rTWin, pTWin, tol float var retentionTime = make(map[string]float64) var intensity = make(map[string]float64) - for _, i := range evi.PSM { + var charges = make(map[string]int) + // collect attributes from PSM + for _, i := range evi.PSM { partName := strings.Split(i.Spectrum, ".") sourceMap[partName[0]] = 0 spectra[partName[0]] = append(spectra[partName[0]], i.Spectrum) @@ -42,13 +44,15 @@ func peakIntensity(evi rep.Evidence, dir, format string, rTWin, pTWin, tol float minRT[i.Spectrum] = (i.RetentionTime / 60) - rTWin maxRT[i.Spectrum] = (i.RetentionTime / 60) + rTWin retentionTime[i.Spectrum] = i.RetentionTime + + charges[i.Spectrum] = int(i.AssumedCharge) } + // get a sorted list of spectrum names var sourceMapList []string for source := range sourceMap { sourceMapList = append(sourceMapList, source) } - sort.Strings(sourceMapList) logrus.Info("Reading spectra and tracing peaks") @@ -59,7 +63,8 @@ func peakIntensity(evi rep.Evidence, dir, format string, rTWin, pTWin, tol float fileName := fmt.Sprintf("%s%s%s.mzML", dir, string(filepath.Separator), s) - mz.Read(fileName, false, true, true) + // load MS1, ignore MS2 and MS3 + mz.Read(fileName, false, false, true) for i := range mz.Spectra { if mz.Spectra[i].Level == "1" { @@ -68,6 +73,7 @@ func peakIntensity(evi rep.Evidence, dir, format string, rTWin, pTWin, tol float spectrum := fmt.Sprintf("%s.%05s.%05s.%d", s, mz.Spectra[i].Scan, mz.Spectra[i].Scan, mz.Spectra[i].Precursor.ChargeState) _, ok := mzMap[spectrum] if ok { + // update the MZ with the desired Precursor value from mzML if isIso == true { mzMap[spectrum] = mz.Spectra[i].Precursor.TargetIon } else { @@ -81,12 +87,21 @@ func peakIntensity(evi rep.Evidence, dir, format string, rTWin, pTWin, tol float if ok { for _, j := range v { - //var measured = make(map[float64]float64) - //var retrieved bool - measured, retrieved := xic(mz.Spectra, minRT[j], maxRT[j], ppmPrecision[j], mzMap[j]) + // if j == "20180209_03_TP_1A.03130.03130.2#interact.pep.xml" { + // fmt.Println(measured) + // } + if retrieved == true { + + // create the list of mz differences for each peak + var mzRatio []float64 + for k := 1; k <= 6; k++ { + r := float64(k) * (float64(1) / float64(charges[j])) + mzRatio = append(mzRatio, uti.ToFixed(r, 2)) + } + var timeW = retentionTime[j] / 60 var topI = 0.0 @@ -102,7 +117,6 @@ func peakIntensity(evi rep.Evidence, dir, format string, rTWin, pTWin, tol float } } } - } for i := range evi.PSM { diff --git a/lib/qua/qua.go b/lib/qua/qua.go index d037da40..15f8d50a 100644 --- a/lib/qua/qua.go +++ b/lib/qua/qua.go @@ -122,7 +122,6 @@ func RunIsobaricLabelQuantification(p met.Quantify, mods bool) met.Quantify { psmMap[j.Spectrum] = psm } } - //mappedPurity = nil for _, j := range mappedPSM { v, ok := psmMap[j.Spectrum] @@ -132,7 +131,6 @@ func RunIsobaricLabelQuantification(p met.Quantify, mods bool) met.Quantify { psmMap[j.Spectrum] = psm } } - //mappedPSM = nil } diff --git a/lib/rep/rep.go b/lib/rep/rep.go index a43fcace..d01a7543 100644 --- a/lib/rep/rep.go +++ b/lib/rep/rep.go @@ -401,11 +401,9 @@ func Run(m met.Data) { // get the labels from the annotation file if len(m.Quantify.Annot) > 0 { - if len(m.Quantify.Annot) > 0 { - annotfile := fmt.Sprintf(".%sannotation.txt", string(filepath.Separator)) - annotfile, _ = filepath.Abs(annotfile) - labels = uti.GetLabelNames(annotfile) - } + annotfile := fmt.Sprintf(".%sannotation.txt", string(filepath.Separator)) + annotfile, _ = filepath.Abs(annotfile) + labels = uti.GetLabelNames(annotfile) } logrus.Info("Creating reports") diff --git a/lib/uti/uti.go b/lib/uti/uti.go index 8a48652c..3aff7a6a 100644 --- a/lib/uti/uti.go +++ b/lib/uti/uti.go @@ -3,8 +3,10 @@ package uti import ( "bufio" + "fmt" "math" "os" + "path/filepath" "philosopher/lib/msg" "regexp" "strconv" @@ -110,3 +112,15 @@ func GetLabelNames(annot string) map[string]string { return labels } + +// FindFile locates a file based on a name pattern +func FindFile(targetDir string, pattern string) string { + + match, e := filepath.Glob(targetDir + string(filepath.Separator) + pattern) + + if e != nil { + fmt.Println(e) + } + + return match[0] +}