def reduce(self, iterator, collector):
        """
        :param iterator:
        :param collector:
        :return:
        """
        # group tiles by band
        band_to_tiles = defaultdict(set)
        for tile in iterator:
            band_to_tiles[tile._band].add(tile)

        # iterate over bands in order
        bands = sorted(band_to_tiles.keys())
        orig_not_null_counter = 0
        inside_counter = 0
        known_counter = 0
        for b in bands:
            result = Tile()
            # Initialize content with -9999
            result._content = bytearray(self.xSize * self.ySize * 2)
            for i in range(0, len(result._content), 2):
                result._content[i] = NOVAL[0]
                result._content[i+1] = NOVAL[1]

            # iterate over tiles for current band
            updated = False
            for t in band_to_tiles[b]:
                if not updated:
                    result.update(self.leftUpper, self.rightLower, self.xSize,
                                  self.ySize, b, t._pathRow, t._aquisitionDate,
                                  t._xPixelWidth, t._yPixelWidth)
                    updated = True

                # iterate over tile content 2 bytes per iteration
                for i in range(0, len(t._content), 2):
                    if t._content[i:i+2] != NOVAL:
                        orig_not_null_counter += 1

                    # check coordinates of current pixel
                    px_coord_lat, px_coord_lon = t.get_coordinate(i)
                    if (self.leftUpperLat >= px_coord_lat and
                            px_coord_lat >= self.rightLowerLat and
                            self.leftUpperLon <= px_coord_lon and
                            px_coord_lon <= self.rightLowerLon):
                        # get index in result tile for current pixel
                        index = int(result.get_content_index_from_coordinate((px_coord_lat, px_coord_lon)))
                        if index >= 0 and index < len(result._content):
                            inside_counter += 1
                            px_value = t._content[i:i+2]
                            if px_value != NOVAL:
                                known_counter += 1
                            result._content[index] = px_value[0]
                            result._content[index+1] = px_value[1]

                collector.collect(result)

        print("inside", inside_counter)
        print("known_counter", known_counter)
        print("orig not null", orig_not_null_counter)
    def deserialize(self):
        tile = Tile()
        isAckDate = self._boolSerializer.deserialize()
        if isAckDate > 0:
            tile._aquisitionDate = self._stringSerializer.deserialize()

        tile._band = self._intSerializer.deserialize()

        tile._leftUpperLon = self._doubleSerializer.deserialize()
        tile._leftUpperLat = self._doubleSerializer.deserialize()
        tile._rightLowerLon = self._doubleSerializer.deserialize()
        tile._rightLowerLat = self._doubleSerializer.deserialize()

        isPathRow = self._boolSerializer.deserialize()
        if isPathRow > 0:
            tile._pathRow = self._stringSerializer.deserialize()

        tile._height = self._intSerializer.deserialize()
        tile._width = self._intSerializer.deserialize()

        tile._xPixelWidth = self._doubleSerializer.deserialize()
        tile._yPixelWidth = self._doubleSerializer.deserialize()

        hasContent = self._boolSerializer.deserialize()
        if hasContent > 0:
            tile._content = self._bytesSerializer.deserialize()

        return tile