# Path: loom/util.py
# class LoomError(Exception):
#     pass
# 
# Path: loom/util.py
# def parallel_map(fun, args):
#     if not isinstance(args, list):
#         args = list(args)
#     is_daemon = multiprocessing.current_process().daemon
#     if THREADS == 1 or len(args) < 2 or is_daemon:
#         print 'Running {} in this thread'.format(fun.__name__)
#         return map(fun, args)
#     else:
#         print 'Running {} in {:d} threads'.format(fun.__name__, THREADS)
#         pool = multiprocessing.Pool(THREADS)
#         fun_args = [(fun, arg) for arg in args]
#         return pool.map(print_trace, fun_args, chunksize=1)


import os
import numpy
import pymetis
import pymetis._internal  # HACK to avoid errors finding .so files in path
import loom.store
from itertools import izip
from collections import defaultdict
from collections import namedtuple
from distributions.io.stream import json_dump
from distributions.io.stream import open_compressed
from loom.schema_pb2 import CrossCat
from loom.cFormat import assignment_stream_load
from loom.util import LoomError
from loom.util import parallel_map
#   may be used to endorse or promote products derived from this
#   software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


METIS_ARGS_TEMPFILE = 'temp.metis_args.json'

Row = namedtuple('Row', ['row_id', 'group_id', 'confidence'])


def collate(pairs):
    groups = defaultdict(lambda: [])
    for key, value in pairs:
        groups[key].append(value)
    return groups.values()


def group(root, feature_name, parallel=False):
    paths = loom.store.get_paths(root, sample_count=None)

# Path: loom/util.py
# class LoomError(Exception):
#     pass
# 
# Path: loom/util.py
# def parallel_map(fun, args):
#     if not isinstance(args, list):
#         args = list(args)
#     is_daemon = multiprocessing.current_process().daemon
#     if THREADS == 1 or len(args) < 2 or is_daemon:
#         print 'Running {} in this thread'.format(fun.__name__)
#         return map(fun, args)
#     else:
#         print 'Running {} in {:d} threads'.format(fun.__name__, THREADS)
#         pool = multiprocessing.Pool(THREADS)
#         fun_args = [(fun, arg) for arg in args]
#         return pool.map(print_trace, fun_args, chunksize=1)


# Path: loom/group.py
import os
import numpy
import pymetis
import pymetis._internal  # HACK to avoid errors finding .so files in path
import loom.store
from itertools import izip
from collections import defaultdict
from collections import namedtuple
from distributions.io.stream import json_dump
from distributions.io.stream import open_compressed
from loom.schema_pb2 import CrossCat
from loom.cFormat import assignment_stream_load
from loom.util import LoomError
from loom.util import parallel_map

#   may be used to endorse or promote products derived from this
#   software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


METIS_ARGS_TEMPFILE = 'temp.metis_args.json'

Row = namedtuple('Row', ['row_id', 'group_id', 'confidence'])


def collate(pairs):
    groups = defaultdict(lambda: [])
    for key, value in pairs:
        groups[key].append(value)
    return groups.values()


def group(root, feature_name, parallel=False):
    paths = loom.store.get_paths(root, sample_count=None)

    map_ = parallel_map if parallel else map