Source code for spike.Orbitrap

#!/usr/bin/env python 
# encoding: utf-8

"""
This file implements all the tools for handling Orbitrap data-sets

To use it :

import Orbitrap
d = Orbitrap.OrbiData(...)    # There are several possible initialisation : empty, from file
play with d

d will allows all NPKData methods, plus a few specific ones.

alternatively, use an importer :
from File.(Importer_name) import Import_1D
d = Import_1D("filename)")


Created by Marc-Andre' on 2014-09
Copyright (c) 2014 IGBMC. All rights reserved.
"""

from __future__ import print_function
import math
import unittest
import numpy as np
from .File.HDF5File import HDF5File
from spike import NPKData
from spike import FTMS
from .NPKError import NPKError


FREQ0 = 1E7
REF_FREQ = 1887533.975611561     # Ad Hoc values for   REF_FREQ / REF_MASS
REF_MASS = 715.3122

[docs]class OrbiAxis(FTMS.FTMSAxis): """ hold information for one Orbitrap axis used internally """ def __init__(self, itype=0, currentunit="points", size=1024, specwidth=1E6, offsetfreq=0.0, left_point = 0.0, highmass=10000.0, calibA=0.0, calibB=1E14, calibC=0.0): """ all parameters from Axis, plus specwidth highest frequency, offsetfreq carrier frequency in heterodyn or lowest frequency if acquisition does not contains 0.0, calibA, calibB, calibC : calibration constant, allowing 1 2 or 3 parameters calibration. set to zero if unused correspond to Bruker parameter ML1 ML2 ML3 for FTICR correspond to Thermo parameter 'Source Coeff1', 'Source Coeff2', 'Source Coeff3' for Orbitrap highmass highest physical m/z of interest left_point coordinates of first data point; usually 0.0 after Fourier Transform; may be different after extraction currentunit default unit used for display and zoom, possible values for unit are "points" "m/z" conversion methods work on numpy arrays as well """ super(OrbiAxis, self).__init__(itype=itype, currentunit=currentunit, size=size, specwidth=specwidth, offsetfreq=offsetfreq, left_point=left_point, highmass=highmass, calibA=calibA, calibB=calibB, calibC=calibC) self.Orbitrap = "Orbitrap" self.calibA = calibA self.calibB = calibB self.calibC = calibC self.attributes.insert(0,"Orbitrap") # updates storable attributes self.attributes.insert(0,"calibA") # updates storable attributes self.attributes.insert(0,"calibB") # updates storable attributes self.attributes.insert(0,"calibC") # updates storable attributes #-------------------------------------------------------------------------------
[docs] def report(self): "high level reporting" if self.itype == 0: # Real return "Orbitrap axis at %f kHz, %d real points, from mz = %8.3f to m/z = %8.3f M/DeltaM (M=400) = %.0f"% \ (self.specwidth/1000, self.size, self.lowmass, self.highmass, 400.0/self.deltamz(400.)) else: # Complex return "Orbitrap axis at %f kHz, %d complex pairs, from mz = %8.3f to m/z = %8.3f M/DeltaM (M=400) = %.0f"% \ (self.specwidth/1000, self.size/2, self.lowmass, self.highmass, 400.0/self.deltamz(400.))
#-------------------------------------------------------------------------------
[docs] def htomz(self, value): """ return m/z (mz) from Hertz value (h) """ # m/z = A + B/f^2 + C/f^4 v = np.maximum(value,0.1) # protect from divide by 0 return self.calibA + self.calibB/(v**2) + self.calibC/(v**4)
[docs] def mztoh(self, value): """ return Hz value (h) from m/z (mz) """ v = np.maximum(value,0.1) # protect from divide by 0 Delta = self.calibB**2 - 4*self.calibC*(self.calibA - v) f2 = (-self.calibB - np.sqrt(Delta)) / (2*(self.calibA - v)) return np.sqrt(f2)
#-------------------------------------------------------------------------------
[docs]class OrbiData(FTMS.FTMSData): """ subclass of FTMS.FTMSData, meant for handling Orbitrap data doc to be written ... """ # print "in Orbitrap" def __init__(self, dim=1, shape=None, mode="memory", buffer=None, name=None, debug=0): self.axis1 = OrbiAxis() # this creates an OrbiAxis so that pylint does not complain - will be overwritten if dim == 2: raise Exception("2D Orbitrap is not physcally defined (yet ?)") if name: if name.endswith(".msh5"): # try loading .msh5 file if debug>0: print("reading msh5") H = HDF5File(name,"r") H.load(mode=mode) # load into memory by default ! super(OrbiData, self).__init__(buffer=H.data.buffer, debug=debug) NPKData.copyaxes(H.data, self) # and deep copy all axes from file self.name = name self.hdf5file = H else: raise Exception("Filename should have a .msh5 extension") else: if debug>0: print("calling super") super(OrbiData, self).__init__(dim=dim, shape=shape, buffer = buffer, name = name, debug=debug) for i in range(self.dim): axis = self.axes(i+1) setattr(self, "axis%d"%(i+1), OrbiAxis(size=axis.size, itype=0) ) if debug>1: print(self.report())
#-------------------------------------------------------------------------------
[docs]class Orbi_Tests(unittest.TestCase):
[docs] def setUp(self): self.verbose = 1 # verbose > 0 switches messages on
[docs] def announce(self): if self.verbose >0: print("\n========",self.shortDescription(),'===============')
[docs] def test_atob(self): "testing unit conversion functions" self.announce() Oaxis = OrbiAxis(size = 1000, specwidth = 1667000, itype = 0, currentunit = "points", calibB=344.0974*(419620.0**2), highmass = 2000.0) self.assertAlmostEqual(Oaxis.itoh(0), 0) self.assertAlmostEqual(Oaxis.itoh(Oaxis.size), Oaxis.specwidth) # last point is size-1 !!! self.assertAlmostEqual(Oaxis.itomz(1023)/Oaxis.deltamz(Oaxis.itomz(1023)), 1023./2, places = 2) # delta_m / m is 1/size at highest mass - before extraction self.assertAlmostEqual(123**2*Oaxis.itomz(123), 321**2*Oaxis.itomz(321)) # verify that f*m/z is constant ! self.assertAlmostEqual(123*Oaxis.mztoi(123)**2, 321*Oaxis.mztoi(321)**2) # verify that f*m/z is constant ! for i in (1,2): print(Oaxis.report()) print(Oaxis._report()) # low level report for x in (1.0, 301.0, Oaxis.size-20.0, Oaxis.size-1.0): # last point is size-1 !!! print("point at index %d is at freq %f, m/z %f"%(x, Oaxis.itoh(x), Oaxis.itomz(x))) self.assertAlmostEqual(Oaxis.mztoi(Oaxis.itomz(x)), x) self.assertAlmostEqual(Oaxis.itoh(Oaxis.htoi(x)), x) Oaxis.extract([300,Oaxis.size-20])
#------------------------------------------------------------------------------- if __name__ == '__main__': unittest.main()