Commits
Takeshi Nakazato authored and Ville Suoranta committed 53c82146ccb Merge
27 27 | import os |
28 28 | import re |
29 29 | import shutil |
30 30 | import unittest |
31 31 | |
32 32 | import numpy as np |
33 33 | |
34 34 | from casatasks import applycal, casalog, gencal, sdatmcor |
35 35 | from casatasks.private.sdutil import (convert_antenna_spec_autocorr, |
36 36 | get_antenna_selection_include_autocorr, |
37 - | table_manager) |
37 + | table_manager, table_selector) |
38 38 | import casatasks.private.task_sdatmcor as sdatmcor_impl |
39 39 | from casatools import calibrater, ctsys |
40 40 | from casatools import ms as mstool |
41 41 | from casatools import quanta |
42 42 | |
43 43 | ctsys_resolve = ctsys.resolve |
44 44 | |
45 45 | # hold omp_get_num_threads value when this file is imported |
46 46 | OMP_NUM_THREADS_INITIAL = casalog.ompGetNumThreads() |
47 47 | |
644 644 | casalog.post( |
645 645 | f'OMP_NUM_THREAD_VALUES: initial: {OMP_NUM_THREADS_INITIAL} (returned by get_omp_num_threads), ' |
646 646 | f'at test start time: {omp_num_threads_org}, expected: {num_threads_expected}, ' |
647 647 | f'last set in logfile: {num_threads_log}') |
648 648 | self.assertEqual(num_threads_expected, num_threads_log) |
649 649 | |
650 650 | # check output MS |
651 651 | self.check_result({19: True, 23: True}) |
652 652 | |
653 653 | |
654 + | def set_data_to_zero(infile: str, spw: int) -> np.ndarray: |
655 + | """Set ON_SOURCE CORRECTED_DATA to zero for given spw. |
656 + | |
657 + | This is implemented by TaQL and is intended to do the |
658 + | same with the following code snippet. |
659 + | |
660 + | ms.open(infile) |
661 + | ms.msselect( |
662 + | {'spw': str(spw), 'scanintent': 'OBSERVE_TARGET#ON_SOURCE'}, |
663 + | onlyparse=True |
664 + | ) |
665 + | msidx = ms.msselectedindices() |
666 + | ms.close() |
667 + | ddid = msidx['spwdd'][0] |
668 + | stateid = list(msidx['stateid']) |
669 + | taql = f'DATA_DESC_ID == {ddid} && STATE_ID IN {stateid}' |
670 + | |
671 + | with table_selector(infile, taql=taql, nomodify=False) as tb: |
672 + | cdata = tb.getcol('CORRECTED_DATA') |
673 + | cdata[::] = 0 |
674 + | tb.putcol(colname, cdata) |
675 + | return cdata |
676 + | |
677 + | Args: |
678 + | infile: Input MS name |
679 + | spw: Spectral window Id |
680 + | |
681 + | Returns: |
682 + | Data array manipulated by this function |
683 + | """ |
684 + | with table_manager(infile) as tb: |
685 + | taql_string = f''' |
686 + | USING STYLE PYTHON |
687 + | UPDATE "{infile}" SET CORRECTED_DATA = 0 |
688 + | WHERE |
689 + | DATA_DESC_ID IN |
690 + | [SELECT ROWID() FROM ::DATA_DESCRIPTION WHERE SPECTRAL_WINDOW_ID == {spw}] |
691 + | && STATE_ID IN |
692 + | [SELECT ROWID() FROM ::STATE WHERE OBS_MODE ~ m/^OBSERVE_TARGET#ON_SOURCE/] |
693 + | ''' |
694 + | t = tb.taql(taql_string) |
695 + | cdata = t.getcol('CORRECTED_DATA') |
696 + | t.close() |
697 + | return cdata.real |
698 + | |
699 + | |
700 + | class test_sdatmcor_smoothing(unittest.TestCase): |
701 + | datapath = 'measurementset/almasd' |
702 + | infile = 'X59ca_sel.ms' |
703 + | outfile = infile + '.atmcor' |
704 + | |
705 + | def setUp(self): |
706 + | smart_remove(self.infile) |
707 + | smart_remove(self.outfile) |
708 + | datapath_to_ms = ctsys_resolve(os.path.join(self.datapath, self.infile)) |
709 + | shutil.copytree(datapath_to_ms, self.infile) |
710 + | |
711 + | def tearDown(self): |
712 + | smart_remove(self.infile) |
713 + | smart_remove(self.outfile) |
714 + | |
715 + | def _get_data(self, ms_name, spw): |
716 + | with table_selector(ms_name, f'DATA_DESC_ID=={spw}') as tb: |
717 + | data = tb.getcol('DATA').real |
718 + | |
719 + | return data |
720 + | |
721 + | def test_mitigation(self): |
722 + | """Test if mitigation for boundary effect of convolution works.""" |
723 + | # Set data zero to get correction factor |
724 + | # In sdatmcor, correction factor is subtracted from the data |
725 + | # so we can get correction factor if we set data all zero |
726 + | # (output_data = 0 - correction_factor). |
727 + | zero_data = set_data_to_zero(self.infile, spw=17) |
728 + | self.assertTrue(np.all(zero_data == 0)) |
729 + | |
730 + | # Apply correction with smoothing |
731 + | sdatmcor( |
732 + | infile=self.infile, |
733 + | outfile=self.outfile, |
734 + | spw='17,19', |
735 + | intent='OBSERVE_TARGET#ON_SOURCE', |
736 + | datacolumn='corrected', |
737 + | gainfactor={17: 41.49, 19: 41.48}, |
738 + | dtem_dh=-5.6, |
739 + | h0=2.0, |
740 + | atmtype=1 |
741 + | ) |
742 + | |
743 + | # Resulting data should be -correction_factor. Only check spectral |
744 + | # data for spw 17 since it is severely suffered from the boundary |
745 + | # effect. If mitigation didn't work, there will be steep increase |
746 + | # or decrease at edge channels. In that case, the slope should be |
747 + | # order of magnitude larger. |
748 + | correction_factor_spw17 = self._get_data(self.outfile, spw=17) |
749 + | average_factor_per_pol = correction_factor_spw17.mean(axis=2) |
750 + | # average derivative excluding edge channels |
751 + | delta = average_factor_per_pol[:, 1:] - average_factor_per_pol[:, :-1] |
752 + | average_delta = delta[:, 10:-10].mean() |
753 + | threshold = abs(average_delta) * 10 |
754 + | for ipol in range(correction_factor_spw17.shape[0]): |
755 + | print(f'Examining pol {ipol}') |
756 + | edge_delta = np.abs(delta[ipol, [0, -1]]) |
757 + | print('edge_delta', edge_delta) |
758 + | print(f'threshold = {threshold}') |
759 + | self.assertTrue( |
760 + | np.all(edge_delta < threshold), |
761 + | msg=f'Mitigation did not work for pol {ipol}' |
762 + | ) |
763 + | |
764 + | |
654 765 | class ATMParamTest(unittest.TestCase): |
655 766 | def _param_test_template(self, valid_test_cases, |
656 767 | invalid_user_input, user_default, task_default, unit=''): |
657 768 | # internal error |
658 769 | wrong_task_default = 'NG' |
659 770 | with self.assertRaises(RuntimeError): |
660 771 | param, is_customized = sdatmcor_impl.parse_atm_params( |
661 772 | '', |
662 773 | user_default, |
663 774 | wrong_task_default |