# Path: seal/lib/mr/hadoop_event_monitor.py
# class HadoopEventMonitor(EventMonitor):
#     """
#     Event monitor implementation to log information through the
#     Hadoop context.
#     """
#     def __init__(self, event_class, logger, ctx):
#         """
#         Parameters:
#         event_class:  the category in which all counters will be created.
#         logger:  logger object to use
#         ctx:  Hadoop context
#         """
#         self.event_class = event_class
#         self.logger = logger
#         self.ctx = ctx
#         self.__start_times = {}
#         self.__counters = {}
# 
#     def __get_counter(self, name, timing=False):
#         if not self.__counters.has_key(name):
#             if timing:
#                 self.add_counter(name, "TIME_" + name.upper() + " (ms)")
#             else:
#                 self.add_counter(name, name.upper())
#         return self.__counters[name]
# 
#     def __get_timing_counter(self, name):
#         return self.__get_counter(name, timing=True)
# 
#     def start(self, s):
#         self.__start_times[s] = time.time()
# 
#     def stop(self, s, write_status=True):
#         delta = time.time() - self.__start_times[s]
#         self.ctx.incrementCounter(self.__get_timing_counter(s), int(delta/TIME_TICK))
#         if write_status:
#             status = "done with %s (%.3f s)" % (s, delta)
#             self.ctx.setStatus(status)
#             self.log_info(status)
# 
#     def stop_batch(self, s, offset, n):
#         delta = time.time() - self.__start_times[s]
#         self.ctx.incrementCounter(self.__get_timing_counter(s), int(delta/TIME_TICK))
#         status = "done with %s (offset=%d, n=%d) (%.3f s)" % (s, offset, n, delta)
#         self.ctx.setStatus(status)
#         self.log_info(status)
# 
#     def count(self, name, value=1):
#         self.ctx.incrementCounter(self.__get_counter(name), value)
# 
#     def has_counter(self, name):
#         return self.__counters.has_key(name)
# 
#     def add_counter(self, name, display_name=None):
#         if self.__counters.has_key(name):
#             raise ValueError("counter '%s' is already defined" % name)
#         self.__counters[name] = self.ctx.getCounter(self.event_class, display_name if display_name else name.upper())
# 
#     #################################
#     # logging methods
#     #################################
#     def new_status(self, status_msg):
#         self.ctx.setStatus(status_msg)
#         self.log_debug(status_msg)
# 
#     def log_debug(self, *args):
#         self.logger.debug(*args)
# 
#     def log_info(self, *args):
#         self.logger.info(*args)
# 
#     def log_warning(self, *args):
#         self.logger.warning(*args)
# 
#     def log_error(self, *args):
#         self.logger.error(*args)
# 
#     def log_critical(self, *args):
#         self.logger.critical(*args)
# 
# Path: seal/lib/mr/emit_sam_link.py
# class EmitSamLink(HitProcessorChainLink):
#     def __init__(self, context, event_monitor, next_link = None):
#         super(EmitSamLink, self).__init__(next_link)
#         self.ctx = context
#         self.output_formatter = SamFormatter(strip_pe_tag=True)
#         self.event_monitor = event_monitor
# 
#     def process(self, original, pair):
#         for hit in pair:
#             if hit:
#                 k, v = self.output_formatter.format(hit).split("\t", 1)
#                 self.ctx.emit(str(k), str(v))
#                 self.event_monitor.count("emitted sam records", 1)
# 
#         super(EmitSamLink, self).process(original, pair) # forward pair to next element in chain


import logging
import seal.lib.io.protobuf_mapping as protobuf_mapping
import seal.lib.deprecation_utils as deprecation_utils
import seal.seqal as seqal
from pydoop.pipes import Reducer
from pydoop.utils import jc_configure, jc_configure_bool
from seal.lib.mr.hadoop_event_monitor import HadoopEventMonitor
from seal.lib.mr.emit_sam_link import EmitSamLink
        # with_pairs => implies we have proper pairs for the key position,
        # so all lone fragments are to be discarded as duplicates.
        #
        # not with_pairs => we have no proper pairs for the key position.
        # Duplicates will be selected by quality."""
        if with_pairs:
            # all fragments are duplicates
            self.event_monitor.count("duplicate fragments", len(self.__unpaired))
            if not self.discard_duplicates:
                for dup in self.__unpaired: # for each unpaired fragment
                    dup[0].set_duplicate(True)
                    self.__output_sink.process(dup)
        else:
            fragments = dict()
            for m, _ in self.__unpaired: # for each unpaired fragment
                k = get_mapping_key(m)
                if fragments.has_key(k):
                    if get_map_score(fragments[k]) < get_map_score(m):
                        dup = fragments[k]
                        fragments[k] = m
                    else:
                        dup = m
                    self.event_monitor.count("duplicate fragments")
                    if not self.discard_duplicates:
                        dup.set_duplicate(True)
                        self.__output_sink.process((dup,None))
                else:
                    fragments[k] = m
            # now emit the remaining fragments
            self.event_monitor.count("rmdup unique fragments", len(fragments))

# Path: seal/lib/mr/hadoop_event_monitor.py
# class HadoopEventMonitor(EventMonitor):
#     """
#     Event monitor implementation to log information through the
#     Hadoop context.
#     """
#     def __init__(self, event_class, logger, ctx):
#         """
#         Parameters:
#         event_class:  the category in which all counters will be created.
#         logger:  logger object to use
#         ctx:  Hadoop context
#         """
#         self.event_class = event_class
#         self.logger = logger
#         self.ctx = ctx
#         self.__start_times = {}
#         self.__counters = {}
# 
#     def __get_counter(self, name, timing=False):
#         if not self.__counters.has_key(name):
#             if timing:
#                 self.add_counter(name, "TIME_" + name.upper() + " (ms)")
#             else:
#                 self.add_counter(name, name.upper())
#         return self.__counters[name]
# 
#     def __get_timing_counter(self, name):
#         return self.__get_counter(name, timing=True)
# 
#     def start(self, s):
#         self.__start_times[s] = time.time()
# 
#     def stop(self, s, write_status=True):
#         delta = time.time() - self.__start_times[s]
#         self.ctx.incrementCounter(self.__get_timing_counter(s), int(delta/TIME_TICK))
#         if write_status:
#             status = "done with %s (%.3f s)" % (s, delta)
#             self.ctx.setStatus(status)
#             self.log_info(status)
# 
#     def stop_batch(self, s, offset, n):
#         delta = time.time() - self.__start_times[s]
#         self.ctx.incrementCounter(self.__get_timing_counter(s), int(delta/TIME_TICK))
#         status = "done with %s (offset=%d, n=%d) (%.3f s)" % (s, offset, n, delta)
#         self.ctx.setStatus(status)
#         self.log_info(status)
# 
#     def count(self, name, value=1):
#         self.ctx.incrementCounter(self.__get_counter(name), value)
# 
#     def has_counter(self, name):
#         return self.__counters.has_key(name)
# 
#     def add_counter(self, name, display_name=None):
#         if self.__counters.has_key(name):
#             raise ValueError("counter '%s' is already defined" % name)
#         self.__counters[name] = self.ctx.getCounter(self.event_class, display_name if display_name else name.upper())
# 
#     #################################
#     # logging methods
#     #################################
#     def new_status(self, status_msg):
#         self.ctx.setStatus(status_msg)
#         self.log_debug(status_msg)
# 
#     def log_debug(self, *args):
#         self.logger.debug(*args)
# 
#     def log_info(self, *args):
#         self.logger.info(*args)
# 
#     def log_warning(self, *args):
#         self.logger.warning(*args)
# 
#     def log_error(self, *args):
#         self.logger.error(*args)
# 
#     def log_critical(self, *args):
#         self.logger.critical(*args)
# 
# Path: seal/lib/mr/emit_sam_link.py
# class EmitSamLink(HitProcessorChainLink):
#     def __init__(self, context, event_monitor, next_link = None):
#         super(EmitSamLink, self).__init__(next_link)
#         self.ctx = context
#         self.output_formatter = SamFormatter(strip_pe_tag=True)
#         self.event_monitor = event_monitor
# 
#     def process(self, original, pair):
#         for hit in pair:
#             if hit:
#                 k, v = self.output_formatter.format(hit).split("\t", 1)
#                 self.ctx.emit(str(k), str(v))
#                 self.event_monitor.count("emitted sam records", 1)
# 
#         super(EmitSamLink, self).process(original, pair) # forward pair to next element in chain


# Path: seal/seqal/reducer.py
import logging
import seal.lib.io.protobuf_mapping as protobuf_mapping
import seal.lib.deprecation_utils as deprecation_utils
import seal.seqal as seqal
from pydoop.pipes import Reducer
from pydoop.utils import jc_configure, jc_configure_bool
from seal.lib.mr.hadoop_event_monitor import HadoopEventMonitor
from seal.lib.mr.emit_sam_link import EmitSamLink

        # with_pairs => implies we have proper pairs for the key position,
        # so all lone fragments are to be discarded as duplicates.
        #
        # not with_pairs => we have no proper pairs for the key position.
        # Duplicates will be selected by quality."""
        if with_pairs:
            # all fragments are duplicates
            self.event_monitor.count("duplicate fragments", len(self.__unpaired))
            if not self.discard_duplicates:
                for dup in self.__unpaired: # for each unpaired fragment
                    dup[0].set_duplicate(True)
                    self.__output_sink.process(dup)
        else:
            fragments = dict()
            for m, _ in self.__unpaired: # for each unpaired fragment
                k = get_mapping_key(m)
                if fragments.has_key(k):
                    if get_map_score(fragments[k]) < get_map_score(m):
                        dup = fragments[k]
                        fragments[k] = m
                    else:
                        dup = m
                    self.event_monitor.count("duplicate fragments")
                    if not self.discard_duplicates:
                        dup.set_duplicate(True)
                        self.__output_sink.process((dup,None))
                else:
                    fragments[k] = m
            # now emit the remaining fragments
            self.event_monitor.count("rmdup unique fragments", len(fragments))

            for m in fragments.itervalues():