deblend-sofia-detections 0.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,61 @@
1
+ # -*- coding: future_fstrings -*-
2
+
3
+ try:
4
+ from importlib.metadata import version
5
+ except ImportError:
6
+ # Try backported to PY<37 `importlib_resources`.
7
+ # For Py<3.9 files is not available
8
+ from importlib_metadata import version
9
+
10
+ import os
11
+ import subprocess
12
+
13
+ def report_version():
14
+ # Distutils standard way to do version numbering
15
+ try:
16
+ __version__ = version("deblend_sofia_detections")
17
+ except:
18
+ __version__ = "devel"
19
+
20
+ # perhaps we are in a github with tags; in that case return describe
21
+ path = os.path.dirname(os.path.abspath(__file__))
22
+ try:
23
+ # work round possible unavailability of git -C
24
+ result = subprocess.check_output(
25
+ 'cd %s; git describe --tags' % path, shell=True, stderr=subprocess.STDOUT).rstrip().decode()
26
+ except subprocess.CalledProcessError:
27
+ result = None
28
+ if result != None and 'fatal' not in result:
29
+ # will succeed if tags exist
30
+ return result
31
+ else:
32
+ # perhaps we are in a github without tags? Cook something up if so
33
+ try:
34
+ result = subprocess.check_output(
35
+ 'cd %s; git rev-parse --short HEAD' % path, shell=True, stderr=subprocess.STDOUT).rstrip().decode()
36
+ except subprocess.CalledProcessError:
37
+ result = None
38
+ if result != None and 'fatal' not in result:
39
+ return __version__+'-'+result
40
+ else:
41
+ # we are probably in an installed version
42
+ return __version__
43
+
44
+ def report_branch():
45
+ path = os.path.dirname(os.path.abspath(__file__))
46
+ result = None
47
+ try:
48
+ branches = subprocess.check_output(\
49
+ 'cd %s; git branch' % path, shell=True, stderr=subprocess.STDOUT).rstrip().decode().split()
50
+ for i,line in enumerate(branches):
51
+ if line == '*':
52
+ result=branches[i+1]
53
+ break
54
+ except subprocess.CalledProcessError:
55
+ result= None
56
+ return result
57
+
58
+ __version__ = report_version()
59
+ __branch__ = report_branch()
60
+
61
+ #set_logger_values()
File without changes
@@ -0,0 +1,98 @@
1
+ # -*- coding: future_fstrings -*-
2
+ #Functions that look for optical image
3
+
4
+ from deblend_sofia_detections.deblending.image_manipulation import cut_optical
5
+ from deblend_sofia_detections.support.errors import DownloadError
6
+ from astropy import units as u
7
+ from astropy.io import fits
8
+ from astroquery.skyview import SkyView
9
+ from astropy.coordinates import SkyCoord
10
+ from astropy.wcs import WCS
11
+
12
+ import os
13
+ import warnings
14
+ import numpy as np
15
+
16
+
17
+
18
+ def download_full_FOV_optical(cfg):
19
+ SkyView.URL = 'https://skyview.gsfc.nasa.gov/current/cgi/basicform.pl'
20
+ if cfg.general.verbose:
21
+ print(f'Quering the Sky Survey')
22
+ if not os.path.isdir(f'{cfg.internal.ancillary_directory}/'):
23
+ os.system(f'mkdir {cfg.internal.ancillary_directory}/')
24
+ #First we open the moment header 0 to get the extend of the field
25
+ with warnings.catch_warnings():
26
+ warnings.simplefilter("ignore")
27
+ mom0_header = fits.getheader(f'{cfg.internal.sofia_directory}/{cfg.internal.sofia_basename}_mom0.fits')
28
+ mom0_wcs = WCS(mom0_header).celestial
29
+ #set the size of the image
30
+ size = np.nanmax([abs(mom0_header['NAXIS1']*mom0_header['CDELT1'])*60.,
31
+ abs(mom0_header['NAXIS2']*mom0_header['CDELT2'])*60.,])
32
+ size_quantity= u.Quantity(size,u.arcmin)
33
+ #get_image_list seems to guess at the pixel size let's fix it to 3 arcsec
34
+ beam = mom0_header['BMAJ'] * u.deg
35
+ optical_pixel_scale = beam.to(u.arcsec).value/cfg.general.optical_pixel_scale * u.arcsec
36
+ #If the resolution of our optical images is greater than 5 the deblending becomes hairy
37
+ if optical_pixel_scale > 4.*u.arcsec:
38
+ optical_pixel_scale = 4. * u.arcsec
39
+ size_pixels = (size_quantity.to(u.arcsec).value/optical_pixel_scale.value).astype(int)
40
+ #obtain the central coordinates
41
+ ra,dec = mom0_wcs.wcs_pix2world(mom0_header['NAXIS1']/2., mom0_header['NAXIS2']/2.,1.)
42
+ obj_coords = SkyCoord(ra= ra* u.degree, dec= dec * u.degree, frame='fk5')
43
+
44
+
45
+ if not cfg.input.manual_optical_image[0] is None:
46
+ if cfg.general.verbose:
47
+ print(f'Checking manual input')
48
+ for identifier in cfg.general.manual_optical_image:
49
+ if os.path.isfile(identifier):
50
+ print(f'Found manual optical image: {identifier}')
51
+ manual_path,manual_file = os.path.split(identifier)
52
+ if manual_path == '':
53
+ manual_path = './'
54
+ cutout = cut_optical(mom0_header,mom0_wcs,\
55
+ manual_path,
56
+ manual_file)
57
+
58
+ cutout_hdr = cutout.wcs.to_header()
59
+ cutout_hdr['COMMENT'] = f'The original file was {identifier}'
60
+ fits.writeto(f'{cfg.internal.ancillary_directory}/moment0_full_DSS.fits',cutout.data,cutout_hdr,overwrite=True)
61
+
62
+ return
63
+
64
+
65
+ if cfg.general.verbose:
66
+ print(f'''Obtaining the actual image list with the following parameters:
67
+ object coordinates: {obj_coords.to_string('hmsdms')},
68
+ radius: {size_quantity},
69
+ pixels: {size_pixels},''')
70
+ #SkyView.clear_cache()
71
+ sky_view_list = SkyView.get_image_list(position=obj_coords,
72
+ radius = size_quantity,
73
+ coordinates = "J2000",
74
+ pixels = size_pixels,
75
+ cache=True,
76
+ #survey=['WISE 3.4'])
77
+ #survey=['2MASS-K'])
78
+ survey=['DSS2 Red'])
79
+
80
+ if cfg.general.verbose:
81
+ print(f'''Obtained {len(sky_view_list)} images from SkyView
82
+ {sky_view_list}
83
+ ''')
84
+ for path in sky_view_list:
85
+ if cfg.general.verbose:
86
+ print(f'''Starting the download for {cfg.internal.data_cube}.
87
+ This can take a while.''')
88
+ filename = path.split("/")[-1]
89
+ os.system('wget '+path)
90
+ if os.path.isfile(filename):
91
+ print("Successfully downloaded the image")
92
+ os.system(f'mv {filename} {cfg.internal.ancillary_directory}/moment0_full_DSS.fits')
93
+ else:
94
+ print("Failed to obtain the image from SkyView")
95
+ raise DownloadError(f'''Failed to download the image from SkyView: {path}
96
+ Check your internet connection and the SkyView service status.
97
+ Note that redownloading the exact same image may fail if it has recently been removed from the SkyView archive.
98
+ ''')
@@ -0,0 +1,304 @@
1
+ from deblend_sofia_detections.support.errors import InputError
2
+ from deblend_sofia_detections.support.table_functions import check_table_length,\
3
+ read_manual_table, combine_tables, copy_table_header
4
+ from deblend_sofia_detections.support.support_functions import convertRADEC,\
5
+ isquantity, get_nan_for_dtype,calculate_projected_distance
6
+
7
+ from astropy.coordinates import SkyCoord
8
+ from astropy.io import fits
9
+ from astropy.table import QTable, Column
10
+
11
+ from astroquery.ipac.ned import Ned
12
+
13
+ import astropy.units as u
14
+ import copy
15
+ import numpy as np
16
+ import time
17
+
18
+ Ned.TIMEOUT = 3600
19
+
20
+ def find_NED_counterpart(cfg,source,header_info, sysrange = None,\
21
+ weights = [1.,1.,1.],weight_min_area = False ):
22
+ requested_columns=['Object Name','RA','DEC','Velocity','Type',\
23
+ 'Magnitude and Filter','Distance']
24
+
25
+ coordinates = [source['ra'].unmasked,source['dec'].unmasked]
26
+ #coordinates, radius
27
+ #[source['ra'],source['dec'],source['v_sofia']],\
28
+ # beam_size[0]/2.
29
+
30
+ co = SkyCoord(ra=coordinates[0], dec=coordinates[1], frame='fk5')
31
+
32
+ # Setup a search table in ned
33
+ vsys, radius = set_search_radius(cfg,source,header_info,sysrange,
34
+ counterpart_region=cfg.general.counterpart_region)
35
+ if cfg.general.verbose:
36
+ print("Querying NED")
37
+ print(f'Search a radius {radius.to(u.arcmin)} around {", ".join(convertRADEC(*[x.value for x in coordinates[:2]]))}')
38
+ # get the NED table
39
+ try:
40
+ internet_table = Ned.query_region(co, radius=radius, equinox='J2000.0')
41
+ except:
42
+ time.sleep(10)
43
+ try:
44
+ internet_table = Ned.query_region(co, radius=radius, equinox='J2000.0')
45
+ except Exception as e:
46
+ raise InputError(f'Could not query NED, error {e}')
47
+ # as astropy is the dumbest project ever they can not be consistant so
48
+ # we have to correct the units for RA and DEg
49
+ internet_table['RA'].unit=u.deg
50
+ internet_table['DEC'].unit=u.deg
51
+ # Astropy is so stupid that it does not provide a QTable from the query
52
+ # so we have to do this as well.
53
+ result_table = QTable()
54
+ for x in requested_columns:
55
+ if x in internet_table.colnames:
56
+ tmp_column= internet_table[x]
57
+ tmp_column[tmp_column.mask] = float('NaN')
58
+
59
+ result_table[x] = Column(tmp_column,\
60
+ unit=internet_table[x].unit)
61
+ else:
62
+ result_table[x] = Column([None for x in range(check_table_length(internet_table))])
63
+
64
+
65
+ #select out the galaxies
66
+ objects_to_select = ['G','GPAIR','GTRPL']
67
+ rows = [True if x.upper() in objects_to_select else False for x in result_table['Type']]
68
+ search_table = result_table[rows]
69
+
70
+ # if we have set a range of velocities we mask all that that are outside the range
71
+ if not sysrange is None:
72
+ rows = [True if vsys-sysrange < x < vsys+sysrange else False for x in search_table['Velocity']]
73
+ search_table = search_table[rows]
74
+ else:
75
+ # if we do not have a velocity range we have to make sure that we take the None as float
76
+ search_table['Velocity'] = [float('NaN') if x is None else x for x in search_table['Velocity']]
77
+
78
+ if check_table_length(search_table) > 0:
79
+ if not isquantity(search_table['Velocity']):
80
+ search_table['Velocity'].unit = u.km/u.s
81
+ else:
82
+ if search_table['Velocity'].unit != u.km/u.s:
83
+ try:
84
+ search_table['Velocity'] = [x.to(u.km/u.s).value for x in search_table['Velocity']]
85
+ search_table['Velocity'].unit = u.km/u.s
86
+ except:
87
+ raise InputError(f'the NED counterpart for {source["Name"]} has a weird unit {search_table["Velocity"].unit}')
88
+
89
+ # first sort on distance, we always do this cause else we do not get the Spatial and combined columns
90
+ search_table = sort_on_distance(search_table, coordinates,vsys)
91
+ if len(search_table) > 1:
92
+ # then pick NGC/UGC/ESO/M matches
93
+ search_table = sort_by_name(search_table)
94
+
95
+ if check_table_length(search_table) > 0:
96
+ name = search_table['Object Name'][0]
97
+ if ':' in name:
98
+ search_table['Object Name'][0] = name.split(':')[0]
99
+ if search_table['Velocity Diff'].unit != u.km/u.s:
100
+ print(search_table)
101
+ print(f'Velocity Diff unit is {search_table["Velocity Diff"].unit}')
102
+
103
+ return search_table
104
+
105
+
106
+ def find_manual_counterpart(cfg,source,header_info, sysrange=None):
107
+ if cfg.input.manual_input_tables[0] is None:
108
+ return QTable()
109
+ manual_table = read_manual_table(cfg)
110
+ coordinates = [source['sofia_ra'][0],source['sofia_dec'][0]]
111
+ vsys, radius = set_search_radius(cfg,source,header_info,sysrange,
112
+ counterpart_region=cfg.general.counterpart_region)
113
+ search_table = sort_on_distance(manual_table, coordinates,vsys)
114
+ if cfg.general.verbose:
115
+ print(f'Searching for manual counterpart for {source["sofia_id"][0]}')
116
+ print(f'Search a radius {radius.to(u.arcsec)} around {", ".join(convertRADEC(coordinates[0].value,coordinates[1].value))}')
117
+ print(f' The nearest target is {search_table["Name"][0]} at a distance of {search_table["Spatial Diff"][0].to(u.arcsec)}')
118
+ print(f'And the velocity difference is {search_table["Velocity Diff"][0].to(u.km/u.s)} to vsys {vsys.to(u.km/u.s)}')
119
+
120
+ # if we have set a range of velocities we mask all that that are outside the range
121
+ if search_table['Spatial Diff'][0] > 2.*radius.to(u.arcsec) or\
122
+ search_table['Velocity Diff'][0] > sysrange:
123
+ search_table = QTable()
124
+ return search_table
125
+
126
+
127
+
128
+
129
+ def search_counter_part(cfg,source,sofia_directory= './',
130
+ basename=None,query ='NED',insource=None):
131
+ '''Look for the optical counterpart of the source'''
132
+ try:
133
+ inid = source['id']
134
+ except:
135
+ inid = source['sofia_id'][0]
136
+ if cfg.general.verbose:
137
+ print(f'Searching in {query} to find a counterpart for {basename} with id {inid}')
138
+
139
+ input_dir = f'{sofia_directory}/{basename}_cubelets'
140
+ cube = fits.open(f'{input_dir}/{basename}_{inid}_cube.fits',\
141
+ output_verify='warn')
142
+ header_info= {'BMAJ':float(cube[0].header['BMAJ'])*u.deg,
143
+ 'pixelsize': float(np.mean([abs(cube[0].header['CDELT1']),\
144
+ abs(cube[0].header['CDELT1'])]))\
145
+ *u.deg\
146
+ }
147
+
148
+ # first try a spectroscopic match
149
+ if query.upper() == 'NED':
150
+ spectroscopic_table = find_NED_counterpart(cfg,source, header_info,\
151
+ sysrange=150.*u.km/u.s)
152
+ search_id = 'NED'
153
+ pref =''
154
+ elif query.upper() == 'MANUAL':
155
+ spectroscopic_table = find_manual_counterpart(cfg,source, header_info,
156
+ sysrange=150.*u.km/u.s)
157
+ search_id = 'Manual'
158
+ pref = 'sofia_'
159
+ confirmed = True
160
+
161
+ if check_table_length(spectroscopic_table) > 0:
162
+ new_table = spectroscopic_table
163
+ else:
164
+ if cfg.general.verbose:
165
+ print(f'We found no match within the velocity range, picking the closest object without velocity')
166
+ if query.upper() == 'NED':
167
+ possible_table = find_NED_counterpart(cfg,source, header_info)
168
+ if query.upper() == 'MANUAL':
169
+ possible_table = QTable()
170
+ new_table = possible_table
171
+ confirmed = False
172
+ #We don't need the searching rows
173
+ #false_table = True
174
+ #if query.upper() == 'NED':
175
+ # false_table = False
176
+ if check_table_length(new_table) > 0: # and false_table:
177
+ new_table=new_table[0:1]
178
+ final_row = combine_tables(new_table,source,column_indicators=[search_id,insource])
179
+ final_row[f'{search_id}_spectroscopic'] = confirmed
180
+ else:
181
+ if cfg.general.verbose:
182
+ print(f'We found no {search_id} counterpart for {source[pref+"id"]}')
183
+ if query.upper() == 'NED':
184
+ requested_columns = ['Object Name','RA','DEC','Velocity','Type',\
185
+ 'Magnitude and Filter','Distance','Spatial Diff','Velocity Diff',\
186
+ 'Combined Diff']
187
+ requested_dtypes = ['U30',float,float,float,object,object,object,float,float,float]
188
+ requested_units = [None,u.deg,u.deg,u.km/u.s,None,None,None,u.deg,u.km/u.s,None]
189
+ elif query.upper() == 'MANUAL':
190
+ manual_table = read_manual_table(cfg,need_velocity=False)
191
+ # Add the difference columns
192
+ add_units = [u.deg, u.km/u.s, u.dimensionless_unscaled]
193
+ for i,col in enumerate(['Spatial Diff','Velocity Diff','Combined Diff']):
194
+ if col not in manual_table.colnames:
195
+ manual_table.add_column(np.nan,name=col)
196
+ manual_table[col].unit = add_units[i]
197
+ requested_columns = []
198
+ requested_dtypes = []
199
+ requested_units = []
200
+ for col in manual_table.colnames:
201
+ requested_columns.append(col)
202
+ requested_dtypes.append(manual_table[col].dtype)
203
+ requested_units.append(manual_table[col].unit)
204
+ requested_values = []
205
+ for dt in requested_dtypes:
206
+ requested_values.append(get_nan_for_dtype(dt))
207
+ dummy_table = QTable(names=requested_columns \
208
+ ,dtype=requested_dtypes,units = requested_units)
209
+ dummy_table.add_row(requested_values)
210
+ final_row = combine_tables(dummy_table,source,column_indicators=[search_id,insource])
211
+ final_row[f'{search_id}_spectroscopic'] = False
212
+
213
+ return final_row
214
+
215
+
216
+ def set_search_radius(cfg,source,header_info,sysrange=None,
217
+ counterpart_region = 'Beam'):
218
+ vsys = None
219
+ pref = ''
220
+ for col in source.colnames:
221
+ if 'sofia_' in col.lower():
222
+ pref = 'sofia_'
223
+ if not sysrange is None:
224
+ vsys = source[pref+'v_sofia'].to(u.km/u.s) #systemic in km/s
225
+
226
+ if counterpart_region.lower() in ['beam']:
227
+ radius = header_info['BMAJ']/2.
228
+ elif counterpart_region.lower() in ['3beam']:
229
+ radius = header_info['BMAJ']*3./2.
230
+ elif counterpart_region.lower() in ['box']:
231
+ radius = np.max([source[pref+'x'].value-source[pref+'x_min'].value,\
232
+ source[pref+'x_max'].value-source[pref+'x'].value,
233
+ source[pref+'y'].value-source[pref+'y_min'].value,
234
+ source[pref+'y_max'].value-source[pref+'y'].value
235
+ ])*header_info['pixelsize']
236
+ else:
237
+ raise InputError(f'We dont know what to do with {counterpart_region} for counterpart_region')
238
+ return vsys, radius
239
+
240
+
241
+
242
+ ''' Sort our table based on catalogue name'''
243
+ def sort_by_name(table):
244
+ #print(table)
245
+ # The order we prefer things in
246
+ preferred_order = [['NGC'], ['UGC','ESO'], ['M']]
247
+ new_table = copy_table_header( table,)
248
+
249
+ # add the rows to our table based on the preferred order
250
+ for names in preferred_order:
251
+ for row in table:
252
+ row_name = row['Object Name']
253
+ for identifier in names:
254
+ if row_name[:len(identifier)].upper() == identifier:
255
+ if len(identifier) == 1:
256
+ if not row_name[len(identifier):].isdigit():
257
+ continue
258
+ new_table.add_row(row)
259
+ #Attach all final objects that did not have a preffered order
260
+ selected_objects = [x['Object Name'] for x in new_table]
261
+ for row in table:
262
+ if row['Object Name'] not in selected_objects:
263
+ new_table.add_row(row)
264
+
265
+ return new_table
266
+
267
+ '''Sort the table by distance'''
268
+ def sort_on_distance(table_in,coordinates,vsys,weights = [1.,1.],print_in=False):
269
+ # this stupid table is not ordered so get names, types ra and dec and sort on distance
270
+ for x in table_in.colnames:
271
+ if x.lower() in ['spatial_diff','velocity_diff', 'combined_diff']:
272
+ raise InputError(f'Column {x} is not allowed in the table, please rename it')
273
+ if print_in:
274
+ print(f'Before sorting: {table_in}')
275
+ print(f'This the table type {type(table_in)}')
276
+ table = copy.deepcopy(table_in)
277
+ table['Spatial Diff'] = [calculate_projected_distance([x,\
278
+ y],coordinates,no_PA = True).value for x,y in zip(\
279
+ table['RA'],table['DEC'])]* u.deg
280
+ if not vsys is None:
281
+ velocities = table['Velocity'].to(u.km/u.s)
282
+ if isquantity(velocities):
283
+ velocities = velocities.value
284
+ if isquantity(vsys):
285
+ vsys = vsys.to(u.km/u.s).value
286
+ table['Velocity Diff'] = [float(abs(vsys-z)/weights[1])\
287
+ for z in velocities] * u.km/u.s
288
+ table['Combined Diff']= [float(np.sqrt(x.value**2+y.to(u.arcsec).value**2)) for x,y in\
289
+ zip(table['Velocity Diff'],table['Spatial Diff'])] * u.dimensionless_unscaled
290
+
291
+ table.sort('Combined Diff')
292
+
293
+ else:
294
+
295
+ table['Velocity Diff'] = [float('NaN') for x in table['Spatial Diff']]\
296
+ * u.km/u.s
297
+ table['Combined Diff'] = [float('NaN') for x in table['Spatial Diff']]\
298
+ * u.dimensionless_unscaled
299
+ table.sort('Spatial Diff')
300
+ if print_in:
301
+ print(f'After sorting: {table}')
302
+
303
+ return table
304
+
File without changes
@@ -0,0 +1,51 @@
1
+ # OmegaConf setups
2
+
3
+ from dataclasses import dataclass, field
4
+ from omegaconf import OmegaConf,MISSING
5
+ from typing import List, Optional
6
+
7
+ import os
8
+ import psutil
9
+
10
+
11
+ @dataclass
12
+ class Input:
13
+ sofia_parameters: str = 'sofia_input.par' #Give full pathe else expected in the run directory
14
+ manual_input_tables: List = field(default_factory=lambda: [None])
15
+ # If True we will update the manual input table with the information found online
16
+ manual_optical_image: List = field(default_factory=lambda: [None])
17
+
18
+ @dataclass
19
+ class General:
20
+ verbose: bool = True
21
+ try:
22
+ ncpu: int = len(psutil.Process().cpu_affinity())
23
+ except AttributeError:
24
+ ncpu: int = psutil.cpu_count()
25
+ multiprocessing: bool = True
26
+ optical_pixel_scale: float = 5. # Amount of optical pixels that should cover a beam
27
+ counterpart_region: str = 'Beam'
28
+
29
+
30
+ @dataclass
31
+ class Internal:
32
+ ancillary_directory: str = MISSING
33
+ data_cube: str = MISSING
34
+ data_directory: str = MISSING
35
+ run_directory: str = MISSING
36
+ sofia_catalogue: str = MISSING
37
+ sofia_directory: str = MISSING
38
+ sofia_parameter_file: str = MISSING
39
+ sofia_basename: str = MISSING
40
+
41
+ #font_file: str = "/usr/share/fonts/truetype/msttcorefonts/Times_New_Roman.ttf"
42
+
43
+ @dataclass
44
+ class defaults:
45
+ print_examples: bool = False
46
+ configuration_file: Optional[str] = None
47
+ input: Input = field(default_factory = Input)
48
+ general: General = field(default_factory = General)
49
+ internal: Internal = field(default_factory = Internal)
50
+
51
+
@@ -0,0 +1,110 @@
1
+ from deblend_sofia_detections.config.config import defaults
2
+ from deblend_sofia_detections.support.errors import InputError
3
+ from deblend_sofia_detections.support.system_functions import create_directory
4
+ from deblend_sofia_detections.deblending.sofia_functions import load_sofia_input_file
5
+ from omegaconf import OmegaConf
6
+
7
+ import os
8
+ import psutil
9
+ import sys
10
+ import deblend_sofia_detections
11
+ try:
12
+ from importlib.resources import files as import_pack_files
13
+ except ImportError:
14
+ # Try backported to PY<37 `importlib_resources`.
15
+ # For Py<3.9 files is not available
16
+ from importlib_resources import files as import_pack_files
17
+
18
+
19
+ def setup_config(argv):
20
+ if '-v' in argv or '--version' in argv:
21
+ print(f"This is version {deblend_sofia_detections.__version__} of the program.")
22
+ sys.exit()
23
+
24
+ if '-h' in argv or '--help' in argv:
25
+ print('''
26
+ Use package_name in this way:
27
+
28
+ All config parameters can be set directly from the command line by setting the correct parameters, e.g:
29
+ create_package_name def_file=cube.fits error_generator=tirshaker
30
+ ''')
31
+ sys.exit()
32
+
33
+
34
+ cfg = OmegaConf.structured(defaults)
35
+ if cfg.general.ncpu == psutil.cpu_count():
36
+ cfg.general.ncpu -= 1
37
+ inputconf = OmegaConf.from_cli(argv)
38
+ cfg_input = OmegaConf.merge(cfg,inputconf)
39
+
40
+ if cfg_input.print_examples:
41
+ default_name = f'{__name__.split(".")[0]}_default.yml'
42
+ masked_copy = OmegaConf.masked_copy(cfg,\
43
+ ['input','general'])
44
+
45
+ with open(default_name,'w') as default_write:
46
+ default_write.write(OmegaConf.to_yaml(masked_copy))
47
+ print(f'''We have printed the file {default_name} in {os.getcwd()}.
48
+ Exiting {__name__.split(".")[0]}.''')
49
+ my_resources = import_pack_files('deblend_sofia_detections.template')
50
+ data = (my_resources / 'sofia_template.par').read_bytes()
51
+ with open('sofia_template.par','w+b') as default_write:
52
+ default_write.write(data)
53
+ print(f'''We have printed the file sofia_template.par in {os.getcwd()}.
54
+ ''')
55
+ sys.exit()
56
+
57
+
58
+ if cfg_input.configuration_file:
59
+ succes = False
60
+ while not succes:
61
+ try:
62
+ yaml_config = OmegaConf.load(cfg_input.configuration_file)
63
+ #merge yml file with defaults
64
+ cfg = OmegaConf.merge(cfg,yaml_config)
65
+ succes = True
66
+ except FileNotFoundError:
67
+ cfg_input.configuration_file = input(f'''
68
+ You have provided a config file ({cfg_input.configuration_file}) but it can't be found.
69
+ If you want to provide a config file please give the correct name.
70
+ Else press CTRL-C to abort.
71
+ configuration_file = ''')
72
+ cfg = OmegaConf.merge(cfg,inputconf)
73
+
74
+ #open the input parameter file to obtain the data cube and output locations
75
+ cfg = read_parameter_input(cfg)
76
+
77
+ cfg = directory_check(cfg)
78
+ return cfg
79
+
80
+
81
+ def directory_check(cfg):
82
+
83
+ for test_dir in [cfg.internal.data_directory, cfg.internal.sofia_directory, cfg.internal.run_directory]:
84
+ if not os.path.isdir(test_dir):
85
+ raise InputError(f'''The directory {test_dir} does not exist.''')
86
+ return cfg
87
+
88
+
89
+ def read_parameter_input(cfg):
90
+ cfg.internal.run_directory = os.getcwd()
91
+ parameters = load_sofia_input_file(cfg.input.sofia_parameters)
92
+ input_pathname,parameter_file = os.path.split(cfg.input.sofia_parameters)
93
+ cfg.internal.sofia_parameter_file = parameter_file
94
+ if input_pathname == '' or input_pathname[0] != '/':
95
+ input_pathname = os.path.join(os.getcwd(),input_pathname)
96
+ data_path,data_file = os.path.split(parameters['input.data'])
97
+ if data_path == '' or data_path[0] != '/':
98
+ cfg.internal.data_directory = f'{input_pathname}{data_path}'
99
+ else:
100
+ cfg.internal.data_directory = data_path
101
+ cfg.internal.ancillary_directory = f'{cfg.internal.data_directory}/ancillary_data'
102
+ cfg.internal.data_cube = data_file
103
+ cfg.internal.sofia_basename = parameters['output.filename']
104
+ if cfg.internal.sofia_basename == '':
105
+ cfg.internal.sofia_basename = os.path.splitext(data_file)[0]
106
+ cfg.internal.sofia_directory = parameters['output.directory']
107
+ if cfg.internal.sofia_directory == '' or cfg.internal.sofia_directory[0] != '/':
108
+ cfg.internal.sofia_directory = os.path.join(input_pathname,cfg.internal.sofia_directory)
109
+
110
+ return cfg
File without changes