import inspect
import os
import tempfile
import unittest
import Numeric

from compClust.mlx import datasets
import compClust.gui.DataManager as DataManager

class DataManagerTestCases(unittest.TestCase):
  def setUp(self):
    self.datadir = os.path.split(inspect.getsourcefile(DataManagerTestCases))[0]
    self.chodir = os.path.join(self.datadir, "../Examples/ChoCellCycling")

    self.cache_dir = os.path.join(tempfile.gettempdir(), "testcache")
    self.shelf_name = os.path.join(tempfile.gettempdir(), "testshelf")
    self.shelf_id_name = os.path.join(tempfile.gettempdir(), "testshelfid")
    self.labelings = [
      ('cho', os.path.join(self.chodir,'ChoClassification.rlab'), True, None),
      ('em', os.path.join(self.chodir, 'EM.rlab'), True, None),
      ('common', os.path.join(self.chodir, 'CommonNames.rlab'), True, None),
      ('orfs', os.path.join(self.chodir, 'ORFs.rlab'), True, "http://somesite.com/orf=%s"),
      ('times', os.path.join(self.chodir, 'times.clab'), False, None)]

  def tearDown(self):
    pass
    #os.rmdir(self.cache_dir)
    if os.path.isfile(self.shelf_name):
      os.remove(self.shelf_name)
    if os.path.isfile(self.shelf_id_name):
      os.remove(self.shelf_id_name)
    
  def loadCho(self):
    """Load cho dataset into a datamanager
    """
    ds = DataManager.DataSource()
    ds.source = os.path.join(self.chodir, 'ChoCycling.dat')
    dm = DataManager.DataManager(self.cache_dir, self.shelf_name, self.shelf_id_name)
    dm.append(ds)
    return (dm, ds)

  def attachChoLabels(self, ds):
    """Attach labelings to cho dataset"""
    for name, path, isrow, url in self.labelings:
      ds.add_labeling(name, path, isrow, url)
    
  def testDataManager(self):
    """Add a dataset to the datamanager, and make sure we can get it back
    """
    dm, ds = self.loadCho()
    self.failUnless(ds == dm[ds], "lookup ds by initial dataset")
    self.failUnless(ds == dm[ds.id], "lookup ds by id")

    self.attachChoLabels(ds)
    
    browse = dm.browse_list()
    self.failUnless(len(browse) == 1)
    self.failUnless(len(browse[0][2]) == len(self.labelings))

    cho_labeling = ds.dataset.getLabeling("cho")
    self.failUnless(ds.get_labeling_by_name("cho") == cho_labeling )
    self.failUnless(ds.get_labeling_by_name(cho_labeling) == cho_labeling)
    self.failUnless(ds.get_labeling_by_name("lasdjflka") == None)

  def testDataManagerPrimarySecondary(self):
    """Test to see if we can attach labelingsources as primary & secondary
    labels.
    """
    dm, cho = self.loadCho()
    self.attachChoLabels(cho)

    # lookup by labelingsource name
    cho.primary = "orfs"
    self.failUnless(cho.primary == cho.get_labeling_source('orfs'))
    
    # lookup by labelingsource
    secondary = cho.get_labeling_source('common')
    cho.secondary = secondary
    self.failUnless(cho.secondary == secondary)

  def testPersistentDataManager(self):
    """Save dataset
    """
    # construct datamanager
    dm, cho = self.loadCho()
    cho_id = cho.id
    simple_dataset = datasets.Dataset(os.path.join(self.datadir,"dataset.txt"))
    simple = DataManager.DataSource(simple_dataset)
    simple_id = simple.id
    dm.append(simple)

    for ds_id, ds_name, ds_labelings, isloaded in dm.browse_list():
      self.failUnless(isloaded == True, "%s should be loaded" % (ds_name))

    # save stuff
    dm.persist(cho_id)
    dm.persist(simple_id)
    self.failUnless(len(dm.browse_list()) == 2, "Saving created another entry")

    dm.unload(cho_id)
    dm.unload(simple_id)
    self.failUnless(len(dm.browse_list()) != 2, 
                    "Did you turn on persistance, persistance breaks clusterings")
    # FIXME: When persistence works, there should be two entries
    #"should find saved entries")
    # skip the rest of the persistance tests until we figure out how 
    # to make it work correctly without breaking clustering
    # (the breakage happens because the dataset that has the new labeling 
    # attached to it is no longer the same one after the dataset is
    # reloaded from the perstance manager
    return 
    
    for ds_id, ds_name, ds_labelings, isloaded in dm.browse_list():
      self.failUnless(isloaded == False, "%s was still loaded" % (ds_name))

    simple_loaded = dm[simple_id]
    equal_vector = simple.dataset.getData() == simple_loaded.dataset.getData()
    self.failUnless(not Numeric.alltrue(equal_vector),"couldn't reload dataset properly")

    dm.delete(cho_id)
    dm.delete(simple_id)

  def testNonStringLabels(self):
    """Make sure that we can handle labels that aren't strings
    """
    from compClust.score.ConfusionMatrix2 import ConfusionMatrix
    def make_ordering(clustering):
      row_labels = clustering.getLabelByRows()
      order = [(row_labels.count(x), x) for x in clustering.getLabels() ]
      order.sort()
      order = [ x[1] for x in order ]
      order.reverse()
      return order
      
    dm, chosource = self.loadCho()
    chods = chosource.dataset
    self.attachChoLabels(chosource)
    cho_clustering = chods.getLabeling('cho')
    em_clustering = chods.getLabeling('em')

    l1Order = make_ordering(cho_clustering)
    l2Order = make_ordering(em_clustering)
    
    clusterOrders = [l1Order, l2Order]
    cm = ConfusionMatrix([cho_clustering, em_clustering], clusterOrders=clusterOrders)
    
    # this is a labeling of confusion matrix coord
    cm_labeling = cm.getConfusionLabeling()

    # can we get the labeling back?
    self.failUnless(cm_labeling==chods.getLabeling(cm_labeling.getName()))
    # can we get it back if we string it?
    self.failUnless(cm_labeling==chods.getLabeling(str(cm_labeling.getName())))
    
def suite(**kw):
 suite = unittest.makeSuite(DataManagerTestCases,'test')
 return suite

if __name__ == "__main__":
  unittest.main(defaultTest="suite")

