"""
Quantiphyse - Tests for supervoxel clustering widget

Copyright (c) 2013-2020 University of Oxford

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
import unittest 

import numpy as np

from quantiphyse.processes import Process
from quantiphyse.test import WidgetTest, ProcessTest

from .widgets import PerfSlicWidget

NUM_SV = 4
NAME = "test_sv"
NUM_PCA = 3
SIGMA = 0.5
COMP = 0.2

class PerfSlicWidgetTest(WidgetTest):

    def widget_class(self):
        return PerfSlicWidget

    def testNoData(self):
        """ User clicks the generate buttons with no data"""
        self.harmless_click(self.w.gen_btn)

    def test3dData(self):
        self.ivm.add(self.data_3d, grid=self.grid, name="data_3d")
        self.w.ovl.setCurrentIndex(0)
        self.processEvents()
        self.assertFalse(self.w.n_comp.spin.isVisible())

        self.w.compactness.spin.setValue(COMP)
        self.w.sigma.spin.setValue(SIGMA)
        self.w.n_supervoxels.spin.setValue(NUM_SV)
        self.w.output_name.setText(NAME)

        self.harmless_click(self.w.gen_btn)
        self.processEvents()

        self.assertTrue(NAME in self.ivm.rois)
        self.assertEquals(self.ivm.current_roi.name, NAME)
        # Don't check regions as we know this doesn't work. Really you shouldn't be running
        # supervoxels without an ROI, we are just checking it handles it gracefully if you do
        #self.assertEquals(len(self.ivm.rois[NAME].regions, NUM_SV)
        self.assertFalse(self.error)

    def test3dDataMask(self):
        self.ivm.add(self.mask, grid=self.grid, name="mask", roi=True)
        self.w.ovl.setCurrentIndex(0)
        self.test3dData()
        self.assertEquals(len(self.ivm.rois[NAME].regions), NUM_SV)
        # Supervoxel value is always zero outside the ROI
        sv = self.ivm.rois[NAME].raw()
        self.assertTrue(np.all(sv[self.mask == 0] == 0))
        self.assertFalse(self.error)

    def test4dData(self):
        self.ivm.add(self.data_4d, grid=self.grid, name="data_4d")
        self.w.ovl.setCurrentIndex(0)
        self.w.roi.setCurrentIndex(0)
        self.processEvents()
        self.assertTrue(self.w.n_comp.spin.isEnabled())

        self.w.compactness.spin.setValue(COMP)
        self.w.n_comp.spin.setValue(NUM_PCA)
        self.w.sigma.spin.setValue(SIGMA)
        self.w.n_supervoxels.spin.setValue(NUM_SV)
        self.w.output_name.setText(NAME)

        self.harmless_click(self.w.gen_btn)
        self.processEvents()

        self.assertTrue(NAME in self.ivm.rois)
        self.assertEquals(self.ivm.current_roi.name, NAME)
        # Don't check regions as we know this doesn't work. Really you shouldn't be running
        # supervoxels without an ROI, we are just checking it handles it gracefully if you do
        #self.assertEquals(len(self.ivm.rois[NAME].regions, NUM_SV)
        self.assertFalse(self.error)

    def test4dDataMask(self):
        self.ivm.add(self.mask, grid=self.grid, name="mask", roi=True)
        self.w.ovl.setCurrentIndex(0)
        self.w.roi.setCurrentIndex(0)
        self.test4dData()
        self.assertEquals(len(self.ivm.rois[NAME].regions), NUM_SV)
        # Supervoxel value is always zero outside the ROI
        sv = self.ivm.rois[NAME].raw()
        self.assertTrue(np.all(sv[self.mask == 0] == 0))
        self.assertFalse(self.error)

class SupervoxelsProcessTest(ProcessTest):

    def test3d(self):
        yaml = """
  - Supervoxels:
      data: data_3d
      output-name: sv_3d
      compactness: 0.01
      n-supervoxels: 20
"""
        self.run_yaml(yaml)
        self.assertEqual(self.status, Process.SUCCEEDED)
        self.assertTrue("sv_3d" in self.ivm.rois)

    def test4d(self):
        yaml = """

  - Supervoxels:
      data: data_4d
      output-name: sv_4d
      n-components: 3
      compactness: 0.02
      n-supervoxels: 30
"""
        self.run_yaml(yaml)
        self.assertEqual(self.status, Process.SUCCEEDED)
        self.assertTrue("sv_4d" in self.ivm.rois)

if __name__ == '__main__':
    unittest.main()
