Repository: soar-telescope/goodman_focus

Issue:
disable plot by default
plotting should be optional since not always anyone wants it.

Discussion:

Patch:
diff --git a/CHANGES.rst b/CHANGES.rst
index f3b2832..b896220 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -1,5 +1,5 @@
-0.1.4 (Not released yet)
-========================
+0.2.0
+=====
 
 - Added messages when no file matches the `--obstype` value, by default is
   `FOCUS` [#9]
@@ -11,6 +11,9 @@
   several issues. For instance `--debug` was unusable, and also there were
   duplicated log entries for the file handler when used as a library in other
   application. [#10]
+- Replaced the use of the function `get_args` by using arguments on class
+  instantiation instead
+- Created name for modes [#11]
 
 0.1.3
 =====
diff --git a/goodman_focus/goodman_focus.py b/goodman_focus/goodman_focus.py
index f8b1316..25853ce 100644
--- a/goodman_focus/goodman_focus.py
+++ b/goodman_focus/goodman_focus.py
@@ -4,6 +4,7 @@ import matplotlib.pyplot as plt
 import numpy as np
 import os
 import pandas
+import re
 import sys
 
 from astropy.stats import sigma_clip
@@ -18,6 +19,7 @@ import logging.config
 
 LOG_FORMAT = '[%(asctime)s][%(levelname)s]: %(message)s'
 LOG_LEVEL = logging.INFO
+# LOG_LEVEL = logging.CRITICAL
 
 DATE_FORMAT = '%H:%M:%S'
 
@@ -65,6 +67,12 @@ def get_args(arguments=None):
                         help='Model to use in fitting the features in order to'
                              'obtain the FWHM for each of them')
 
+    parser.add_argument('--plot-results',
+                        action='store_true',
+                        dest='plot_results',
+                        help='Show a plot when it finishes the focus '
+                             'calculation')
+
     parser.add_argument('--debug',
                         action='store_true',
                         dest='debug',
@@ -72,14 +80,6 @@ def get_args(arguments=None):
 
     args = parser.parse_args(args=arguments)
 
-    if not os.path.isdir(args.data_path):
-        log.error("Data location {} does not exist".format(args.data_path))
-        sys.exit(0)
-    elif len(glob.glob(os.path.join(args.data_path, args.file_pattern))) == 0:
-        log.error("There are no files matching \"{}\" in the folder \"{}\""
-                  "".format(args.file_pattern, args.data_path))
-        sys.exit(0)
-
     return args
 
 
@@ -271,15 +271,28 @@ class GoodmanFocus(object):
                 'OBSTYPE',
                 'ROI']
 
-    def __init__(self, arguments=None):
-        self.args = get_args(arguments=arguments)
+    def __init__(self,
+                 data_path=os.getcwd(),
+                 file_pattern="*.fits",
+                 obstype="FOCUS",
+                 features_model='gaussian',
+                 plot_results=False,
+                 debug=False):
+
+        self.data_path = data_path
+        self.file_pattern = file_pattern
+        self.obstype = obstype
+        self.features_model = features_model
+        self.plot_results = plot_results
+        self.debug = debug
+
         self.log = logging.getLogger(__name__)
-        if self.args.debug:
+        if self.debug:
             self.log.setLevel(level=logging.DEBUG)
 
-        if self.args.features_model == 'gaussian':
+        if self.features_model == 'gaussian':
             self.feature_model = models.Gaussian1D()
-        elif self.args.features_model == 'moffat':
+        elif self.features_model == 'moffat':
             self.feature_model = models.Moffat1D()
 
         self.__ccd = None
@@ -291,16 +304,26 @@ class GoodmanFocus(object):
         self.fitter = fitting.LevMarLSQFitter()
         self.linear_fitter = fitting.LinearLSQFitter()
 
-        if os.path.isdir(self.args.data_path):
-            self.full_path = self.args.data_path
+        if os.path.isdir(self.data_path):
+            self.full_path = self.data_path
+            if not os.listdir(self.full_path):
+                self.log.critical("Directory is empty")
+                sys.exit(0)
+            # print(glob.glob(os.path.join(self.full_path, self.file_pattern)))
+            elif not glob.glob(os.path.join(self.full_path, self.file_pattern)):
+                self.log.critical('Directory {} does not containe files '
+                                  'matching the pattern {}'
+                                  ''.format(self.full_path, self.file_pattern))
+                sys.exit(0)
         else:
-            sys.exit("No such directory")
+            self.log.critical("No such directory")
+            sys.exit(0)
 
         _ifc = ImageFileCollection(self.full_path, keywords=self.keywords)
 
         self.ifc = _ifc.summary.to_pandas()
         self.log.debug("Found {} FITS files".format(self.ifc.shape[0]))
-        self.ifc = self.ifc[(self.ifc['OBSTYPE'] == self.args.obstype)]
+        self.ifc = self.ifc[(self.ifc['OBSTYPE'] == self.obstype)]
         if self.ifc.shape[0] != 0:
             self.log.debug("Found {} FITS files with OBSTYPE = FOCUS".format(
                 self.ifc.shape[0]))
@@ -348,22 +371,24 @@ class GoodmanFocus(object):
         if value is not None:
             self._fwhm = value
 
-
     def __call__(self, *args, **kwargs):
         for focus_group in self.focus_groups:
-            # print(focus_group)
+            mode_name = self._get_mode_name(focus_group)
 
             focus_dataframe = self.get_focus_data(group=focus_group)
 
             self._fit(df=focus_dataframe)
-            self.log.info("Best Focus for {} is {}".format(self.file_name,
-                                                           self.__best_focus))
-            if True:   # pragma: no cover
+            self.log.info("Best Focus for mode {} is {}".format(
+                mode_name,
+                self.__best_focus))
+            if self.plot_results:   # pragma: no cover
                 # TODO (simon): Do properly using matplotlib or pandas alone
                 # fig = plt.subplots()
                 focus_dataframe.plot(x='focus', y='fwhm', marker='x')
-                plt.axvline(self.__best_focus)
-                plt.title("Best Focus: {}".format(self.__best_focus))
+                plt.axvline(self.__best_focus, color='k', label='Best Focus')
+                plt.title("Best Focus:\n{} {:.3f}".format(
+                    mode_name,
+                    self.__best_focus))
                 focus_list = focus_dataframe['focus'].tolist()
                 new_x_axis = np.linspace(focus_list[0], focus_list[-1], 1000)
                 plt.plot(new_x_axis,
@@ -391,6 +416,24 @@ class GoodmanFocus(object):
 
         return self.__best_focus
 
+    @staticmethod
+    def _get_mode_name(group):
+        unique_values = group.drop_duplicates(
+            subset=['INSTCONF', 'FILTER', 'FILTER2', 'WAVMODE'], keep='first')
+
+        if unique_values['WAVMODE'].values == ['Imaging']:
+            mode_name = 'IM_{}_{}'.format(
+                unique_values['INSTCONF'].values[0],
+                unique_values['FILTER'].values[0])
+        else:
+            mode_name = 'SP_{}_{}_{}'.format(
+                unique_values['INSTCONF'].values[0],
+                unique_values['WAVMODE'].values[0],
+                unique_values['FILTER2'].values[0])
+        mode_name = re.sub('[<> ]', '', mode_name)
+        # mode_name = re.sub('[- ]', '_', mode_name)
+        return mode_name
+
     def get_focus_data(self, group):
         """Collects all the relevant data for finding best focus
 
@@ -416,7 +459,7 @@ class GoodmanFocus(object):
             peaks, values, x_axis,  profile = get_peaks(
                 ccd=self.__ccd,
                 file_name=self.file_name,
-                plots=self.args.debug)
+                plots=self.debug)
 
             self.fwhm = get_fwhm(peaks=peaks,
                                  values=values,
@@ -450,13 +493,16 @@ def run_goodman_focus(args=None):   # pragma: no cover
         args (list): (optional) a list of arguments and respective values.
 
     """
-
-    goodman_focus = GoodmanFocus(arguments=args)
+    args = get_args(arguments=args)
+    goodman_focus = GoodmanFocus(data_path=args.data_path,
+                                 file_pattern=args.file_pattern,
+                                 obstype=args.obstype,
+                                 features_model=args.features_model,
+                                 plot_results=args.plot_results,
+                                 debug=args.debug)
     goodman_focus()
 
 
 if __name__ == '__main__':   # pragma: no cover
     # full_path = '/user/simon/data/soar/work/focus2'
-    get_focus = GoodmanFocus()
-    get_focus()
-
+    run_goodman_focus()
diff --git a/goodman_focus/version.py b/goodman_focus/version.py
index 0e285e2..4e02b70 100644
--- a/goodman_focus/version.py
+++ b/goodman_focus/version.py
@@ -1,2 +1,2 @@
 # This is an automatic generated file please do not edit
-__version__ = '0.1.4.dev1'
\ No newline at end of file
+__version__ = '0.2.0'
\ No newline at end of file
diff --git a/setup.cfg b/setup.cfg
index e364ba8..b01f1cd 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -32,4 +32,4 @@ install_requires =
     sphinx>=2.1.2
 
 # version should be PEP440 compatible (http://www.python.org/dev/peps/pep-0440)
-version = 0.1.4.dev1
+version = 0.2.0


Test patch:
diff --git a/goodman_focus/tests/test_goodman_focus.py b/goodman_focus/tests/test_goodman_focus.py
index 73c162b..a611a7a 100644
--- a/goodman_focus/tests/test_goodman_focus.py
+++ b/goodman_focus/tests/test_goodman_focus.py
@@ -9,12 +9,34 @@ from unittest import TestCase, skip
 from ccdproc import CCDData
 
 from ..goodman_focus import GoodmanFocus
-from ..goodman_focus import get_peaks, get_fwhm
+from ..goodman_focus import get_args, get_peaks, get_fwhm
 
 import matplotlib.pyplot as plt
 
 logging.disable(logging.CRITICAL)
 
+
+class ArgumentTests(TestCase):
+
+    def setUp(self):
+        self.arg_list = ['--data-path', os.getcwd(),
+                         '--file-pattern', '*.myfile',
+                         '--obstype', 'ANY',
+                         '--features-model', 'moffat',
+                         '--plot-results',
+                         '--debug']
+
+    def test_get_args_default(self):
+        args = get_args(arguments=self.arg_list)
+        self.assertEqual(args.__class__.__name__, 'Namespace')
+        self.assertEqual(args.data_path, os.getcwd())
+        self.assertEqual(args.file_pattern, '*.myfile')
+        self.assertEqual(args.obstype, 'ANY')
+        self.assertEqual(args.features_model, 'moffat')
+        self.assertTrue(args.plot_results)
+        self.assertTrue(args.debug)
+
+
 class GetPeaksTest(TestCase):
 
     def setUp(self):
@@ -143,7 +165,7 @@ class GoodmanFocusTests(TestCase):
             focus_data,
             columns=['file', 'fwhm', 'focus'])
 
-        self.goodman_focus = GoodmanFocus(arguments=arguments)
+        self.goodman_focus = GoodmanFocus()
 
     def test_get_focus_data(self):
 
@@ -163,21 +185,49 @@ class GoodmanFocusTests(TestCase):
         self.goodman_focus()
         self.assertIsNotNone(self.goodman_focus.fwhm)
 
+    def test__call__Moffat1D(self):
+        self.goodman_focus = GoodmanFocus(features_model='moffat')
+        self.goodman_focus()
+        self.assertIsNotNone(self.goodman_focus.fwhm)
+
     def tearDown(self):
         for _file in self.file_list:
             os.unlink(_file)
 
 
-class DirectoryAndFilesTest(TestCase):
+class SpectroscopicModeNameTests(TestCase):
 
     def setUp(self):
-        self.arguments = [
-            '--data-path', os.path.join(os.getcwd(), 'nonexisting'),
-            '--file-pattern', '*.fits',
-            '--obstype', 'FOCUS',
-            '--features-model', 'gaussian']
+        self.data = {'file': ['file_{}.fits'.format(i + 1) for i in range(5)],
+                     'INSTCONF': ['Blue'] * 5,
+                     'FILTER': ['FILTER-X'] * 5,
+                     'FILTER2': ['NO FILTER'] * 5,
+                     'WAVMODE': ['Imaging'] * 5}
+
+
+    def test_imaging_mode(self):
+        df = pandas.DataFrame(self.data)
+        expected_name = 'IM_Blue_FILTER-X'
+        mode_name = GoodmanFocus._get_mode_name(group=df)
+        self.assertEqual(mode_name, expected_name)
+
+    def test_spectroscopy_mode(self):
+        self.data['WAVMODE'] = ['400  z1'] * 5
+        df = pandas.DataFrame(self.data)
+
+        expected_name = 'SP_Blue_400z1_NOFILTER'
+
+        mode_name = GoodmanFocus._get_mode_name(group=df)
+
+        self.assertEqual(mode_name, expected_name)
 
+
+
+class DirectoryAndFilesTest(TestCase):
+
+    def setUp(self):
         os.mkdir(os.path.join(os.getcwd(), 'test_dir_empty'))
+        os.mkdir(os.path.join(os.getcwd(), 'test_dir_no_matching_files'))
         os.mkdir(os.path.join(os.getcwd(), 'test_dir_no_focus'))
         for i in range(3):
             ccd = CCDData(data=np.ones((100, 100)),
@@ -203,19 +253,37 @@ class DirectoryAndFilesTest(TestCase):
     def test_directory_does_not_exists(self):
 
         # goodman_focus = GoodmanFocus(arguments=arguments)
-        self.assertRaises(SystemExit, GoodmanFocus, self.arguments)
+        path_non_existing = os.path.join(os.getcwd(), 'non-existing')
+        self.assertRaises(SystemExit, GoodmanFocus, path_non_existing)
 
     def test_directory_exists_but_empty(self):
-        self.arguments[1] = os.path.join(os.getcwd(), 'test_dir_empty')
-        self.assertRaises(SystemExit, GoodmanFocus, self.arguments)
+        empty_path = os.path.join(os.getcwd(), 'test_dir_empty')
+        self.assertRaises(SystemExit, GoodmanFocus, empty_path)
 
-    def test_no_focus_files(self):
-        self.arguments[1] = os.path.join(os.getcwd(), 'test_dir_no_focus')
-        self.assertRaises(SystemExit, GoodmanFocus, self.arguments)
+    def test_directory_not_empty_and_no_matching_files(self):
+        path = os.path.join(os.getcwd(), 'test_dir_no_matching_files')
 
+        open(os.path.join(path, 'sample_file.txt'), 'a').close()
+
+        self.assertRaises(SystemExit, GoodmanFocus, path)
+
+    def test_no_focus_files(self):
+        path_no_focus_files = os.path.join(os.getcwd(), 'test_dir_no_focus')
+        self.assertRaises(SystemExit, GoodmanFocus, path_no_focus_files)
 
     def tearDown(self):
-        os.rmdir(os.path.join(os.getcwd(), 'test_dir_empty'))
+
         for _file in os.listdir(os.path.join(os.getcwd(), 'test_dir_no_focus')):
             os.unlink(os.path.join(os.getcwd(), 'test_dir_no_focus', _file))
+
+        for _file in os.listdir(os.path.join(
+                os.getcwd(),
+                'test_dir_no_matching_files')):
+
+            os.unlink(os.path.join(os.getcwd(),
+                                   'test_dir_no_matching_files',
+                                   _file))
+
+        os.rmdir(os.path.join(os.getcwd(), 'test_dir_empty'))
         os.rmdir(os.path.join(os.getcwd(), 'test_dir_no_focus'))
+        os.rmdir(os.path.join(os.getcwd(), 'test_dir_no_matching_files'))