def get_hdul(fits_name, mode='readonly', checksum=True): # Written by Ema 05.03.2020 r"""Wrapper for astropy `fits.open`. It checks if the file exists and in case returns its HDUList. Args: fits_name (str): fits file name mode (str): Open mode for the file. Possibilities are: `readonly’, `update`, `append`, `denywrite`, or `ostream` checksum (bool): If True, verifies that both `DATASUM` and `CHECKSUM` card values (when present in the HDU header) match the header and data of all HDU’s in the file. Updates to a file that already has a checksum will preserve and update the existing checksums unless this argument is given a value of `remove`, in which case the `CHECKSUM` and `DATASUM` values are not checked, and are removed when saving changes to the file Returns: hdul: list-like collection of HDU objects """ if not checks.fits_file_is_valid(fits_name): msgs.error('Fits file not valid') return None else: hdul = fits.open(fits_name, mode=mode, checksum=checksum) msgs.info('The fits file {} contains {} HDUs'.format( fits_name, len(hdul))) msgs.info('Summary:') hdul.info() return hdul
def make_list_of_fits_files(args_input, verify_fits=False) -> list: r"""Cleaning an input list of fits files Args: args_input (list): input list of fits files that will be checked (usually is coming from `parse_arguments()` in a macro) verify_fits (bool): if set to `True`, it will verify that the fits file is complaint to the FITS standard Returns: list: list containing all the valid fits files given in input """ list_of_fits_files = [] if not isinstance(args_input, list): args_input_files: list = [args_input] else: args_input_files: list = args_input for args_input_file in args_input_files: if checks.fits_file_is_valid(args_input_file, overwrite=False, verify_fits=verify_fits): list_of_fits_files.append(args_input_file) else: msgs.warning('{} excluded because not a valid fits file'.format(args_input_file)) if len(list_of_fits_files) == 0: msgs.error('No valid fits files present') return list_of_fits_files
def contours_from_gw_bayestar(file_name, credible_level=50.): r"""Given a bayestar.fits.gz HEALPix maps of a GW superevent it extracts contours at the given `credible_level` This is a wrapper around `ligo_skymap_contour`. The different contours are then counterclockwise oriented to be compatible with TAP and ASP queries. Args: file_name (str): Name of HEALPix maps credible_level (float): Probability level at which contours are returned Returns: list: [RA,Dec] list defining the contours location. These are counter-clockwise oriented as seen on the sky from inside the sphere. The length of contours represent the number of not connected regions identified. """ # Some checks assert isinstance(file_name, (str, np.str)), '{} is not a valid string'.format(file_name) if not checks.fits_file_is_valid(file_name): msgs.error('{} not a valid fits file'.format(file_name)) assert isinstance(credible_level, (int, float, np.int, np.float)), '`credible_level` is not a float or an int' # Create temporary file where to store output from ligo_skymap_contour contour_tmp_file = '.' + file_name + '.tmp.json' if path.isfile(contour_tmp_file): remove(contour_tmp_file) # Use ligo_skymap_contour to compute contours ligo_skymap_contour(args=[file_name, '--output', contour_tmp_file, '--contour', str(credible_level)]) # Parse the content of the resulting json file into a dict with open(contour_tmp_file, 'r') as json_file: json_data = json_file.read() contours_dict = json.loads(json_data) json_file.close() # cleaning up remove(contour_tmp_file) # Parse the resulting json to obtain a list of coordinates defining the vertices of the contours of each peak # contours is a list, each element of which contains the vertices of one contour encircling the desired significance contours = contours_dict['features'][0]['geometry']['coordinates'] # Make sure that the orientation of the polygons on the sky is the correct one for the TAP queries, # i.e. counter-clockwise as seen on the sky from inside the sphere. for iii, contour in enumerate(contours): contours[iii] = _ensure_orientation(contour) # Quick summary: if len(contours) > 0: msgs.info('Extracted the contours for {} regions at {} credible level'.format(len(contours), credible_level)) else: msgs.info('No contours extracted at {} credible level'.format(credible_level)) contours = None return contours
def header_from_fits_file(fits_name, which_hdu=0): # Written by Ema 05.03.2020 r"""Load an header with the information from a fits file Args: fits_name (`str`): fits file name which_hdu (`numpy.int`): select from which HDU you are getting the header. Default = 0 Returns: header (`hdu.header`): the header corresponding to `which_hdu` from `fits_name` """ assert isinstance(which_hdu, (int, np.int_)), 'which_hdu must be an int' if not checks.fits_file_is_valid(fits_name): msgs.error('Fits file not valid') else: header = fits.getheader(fits_name, which_hdu) return header
def show_contours_from_gw_bayestar(file_name, contours=None, cmap='cylon', contours_color='C3', show_figure=True, save_figure=None, matplotlib_backend=None): r"""Show sky credibility from the input healpix map and plot the contours created with `contours_from_gw_bayestar` Args: file_name (`str`): Fits files containing the HEALPix mask you would like to show. contours (`list`): cmap: contours_color: show_figure (`bool`): save_figure (`str` or `None`): matplotlib_backend: Returns: """ # Some checks assert isinstance(file_name, (str, np.str)), '{} is not a valid string'.format(file_name) if not checks.fits_file_is_valid(file_name): msgs.error('{} not a valid fits file'.format(file_name)) if contours is None: msgs.warning("No contours defined, showing `credible_level=50` contours") plot_contours = contours_from_gw_bayestar(file_name, credible_level=50.) else: plot_contours = contours # ToDo find a more elegant solution for this. # ligo.skymap.tool.ligo_skymap_contour introduces problems with the matplotlib backend. This i a workaround to # get it running. importlib.reload(matplotlib) from matplotlib import pyplot as plt if matplotlib_backend is None: matplotlib.use(STARTING_MATPLOTLIB_BACKEND) try: # check if the script runs on a notebook. # https://stackoverflow.com/questions/23883394/detect-if-python-script-is-run-from-an-ipython-shell-or # -run-from # -the-command-li __IPYTHON__ except NameError: # Try to get a working gui # https://stackoverflow.com/questions/39026653/programmatically-choose-correct-backend-for-matplotlib-on # -mac-os-x gui_env = matplotlib.rcsetup.all_backends for gui in gui_env: try: matplotlib.use(gui, force=True) break except: continue else: matplotlib.use('nbAgg') else: if matplotlib_backend in matplotlib.rcsetup.all_backends: matplotlib.use(matplotlib_backend) else: msgs.error('{} is not a valid `matplolib` backend'.format(matplotlib_backend)) # Read map and get object name map_data, map_header = healpy.read_map(file_name, h=True, verbose=False, dtype=None) object_name_list = [value for name, value in map_header if name == 'OBJECT'] if len(object_name_list) > 0: object_name = object_name_list[0] else: object_name = 'GW event - {}'.format(file_name) # start the plot # ToDo fix matplotlibe error """ plt.figure(figsize=(10., 7.)) ax = plt.axes([0.1, 0.1, 0.9, 0.9], projection='astro degrees mollweide') ax.grid(True) ax.imshow_hpx(map_data, cmap=cmap, visible=True, zorder=1) ax.text(0.15, 0.95, object_name, horizontalalignment='center', verticalalignment='center', transform=ax.transAxes, bbox=dict(facecolor='orange', alpha=0.8), fontsize=24) # Convert the contour vertex coordinates from world to pixels and draw the contours w = wcs.WCS(ax.header) # Split a contour if two neighboring pixels are more distant than 10 degrees in RA split_step = (10 * (ax.get_xlim()[1] - ax.get_xlim()[0]) / 360.) for contour_world in plot_contours: contour_pix = w.wcs_world2pix(contour_world, 0) x_contours, y_contours = _array_split(contour_pix, split_step) for x_contour, y_contour in zip(x_contours, y_contours): ax.plot(x_contour, y_contour, linewidth=2.5, color=contours_color, zorder=5) # , marker='o') if save_figure is not None: plt.savefig(save_figure, dpi=200., format='pdf', bbox_inches='tight') if show_figure: plt.show() plt.close() """ # Bringing back the previously used matplotlib backend matplotlib.use(STARTING_MATPLOTLIB_BACKEND)
return parser.parse_args() EXAMPLES = r""" Example: fix_sinfoni.py input_fits.fits fix_sinfoni.py input_fits.fits -out _cleaned -cal ABSOLUTE """ if __name__ == '__main__': args = parse_arguments() # File_names input_fits_files = [] for file_name in args.input_fits: if not checks.fits_file_is_valid(file_name): msgs.warning( 'File {} is not a valid fits file. Skipping the procedure'. format(file_name)) elif len(fitsfiles.get_hdul(file_name)) > 1: msgs.warning( '{} cube already processed? Skipping the procedure'.format( file_name)) else: input_fits_files.append(file_name) if len(input_fits_files) == 0: msgs.error('No valid file to process') # output if args.output is not None: overwrite = False