'''
This file includes 
- the class MS1-feature used to store a record from a .kronik file
- a routine to load a .kronik file
'''

class MS1Feature: 
    def __init__(self, fields):
        '''
        Depending on the version of Kronik, the number of fields will be 
        14 or 17 (The filename field should be included)
        '''
        field_names = ["filename", "first_scan", "last_scan", "num_scans", \
                "charge", "monoisotopic_mass", "base_isotope_peak", \
                "best_intensity", "summed_intensity", "first_rt", \
                "last_rt", "best_rt", "best_correl", "modifications"] 
        field_types = [str, int, int, int, int, float, float, float, \
                float, float, float, float, float, str]
        indices = range(len(field_types))
        for fname, ftype, i in zip(field_names, field_types, indices):
            self.__dict__[fname] = ftype(fields[i])
        if len(fields) == 17:
            self.fwhm = float(fields[14])
            self.four_sigmas = float(fields[15])
            self.r2 = float(fields[16])
        else:
            self.fwhm = None
            self.four_sigmas = None
            self.r2 = None

    def __str__(self):
        to_format = "{}\t"*13
        to_str = to_format.\
                format(self.first_scan, self.last_scan, self.num_scans, \
                self.charge, self.monoisotopic_mass, self.base_isotope_peak, \
                self.best_intensity, self.summed_intensity, self.first_rt, \
                self.last_rt, self.best_rt, self.best_correl, \
                self.modifications.strip()) 
        if self.fwhm != None:            
            to_str += "\t{}\t{}\t{}".format(self.fwhm, self.four_sigmas, \
            self.r2)
        return to_str
    
    def __eq__(self, other, epsilon=1e-3):
        return self.filename == other.filename \
                and self.first_scan == other.first_scan and \
                self.last_scan == other.last_scan and \
                self.num_scans == other.num_scans and \
                self.charge == other.charge and \
                abs(self.monoisotopic_mass-other.monoisotopic_mass) < epsilon and \
                abs(self.base_isotope_peak-other.base_isotope_peak) < epsilon and \
                abs(self.best_intensity-other.best_intensity) < epsilon and \
                abs(self.summed_intensity-other.summed_intensity) < epsilon and \
                self.first_rt == other.first_rt and \
                self.last_rt == other.last_rt and \
                self.best_rt == other.best_rt and \
                self.best_correl == other.best_correl and \
                self.modifications == other.modifications
           

class KronikIO:
    @staticmethod
    def load_kronik_file(filename, verbosity=2):
        '''
        Load a file generated by kronik and return a list of MS1Feature objects
        '''        
        if verbosity > 2:
            print "\nLoading {}...".format(filename)
        lines = open(filename, "r").readlines()[1:]
        ms1_features = []
        for l in lines: 
            tmp_fields = l.split("\t")
            if len(tmp_fields) != 14:
                fields = ["-"] + tmp_fields
            else:
                fields = tmp_fields
            ms1_features.append(MS1Feature(fields))
        if verbosity > 2:        
            print "{} features were loaded.".format(len(ms1_features)) 
        return ms1_features
  
