Source code for pywicta.denoising.tailcut

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# Copyright (c) 2016 Jérémie DECOCK (http://www.jdhp.org)

# This script is provided under the terms and conditions of the MIT license:
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

"""
Denoise FITS and PNG images with the tailcut algorithm.

Example usages:
  ./denoising_with_tailcut.py -h
  ./denoising_with_tailcut.py -T 0.5 -t 0.1 ./test.fits
  ./denoising_with_tailcut.py -T 0.5 -t 0.1 ./test.fits
  ipython3 -- ./denoising_with_tailcut.py -t 0.0001 -s ./test.fits

This snippet requires Numpy, Matplotlib and PIL/Pillow Python libraries.
"""

import argparse

from pywicta.denoising.abstract_cleaning_algorithm import AbstractCleaningAlgorithm

from pywicta.io import geometry_converter

from pywi.image.pixel_clusters import kill_isolated_pixels as scipy_kill_isolated_pixels
from pywi.image.pixel_clusters import kill_isolated_pixels_stats
from pywi.image.pixel_clusters import number_of_islands

from ctapipe.image.cleaning import tailcuts_clean

[docs]class Tailcut(AbstractCleaningAlgorithm): def __init__(self): super(Tailcut, self).__init__() self.label = "Tailcut" # Name to show in plots
[docs] def clean_image(self, input_img, high_threshold=10., low_threshold=8., kill_isolated_pixels=False, verbose=False, cam_id=None, output_data_dict=None, **kwargs): """Apply ctapipe's tail-cut image cleaning on ``. """ if cam_id is None: raise Exception("cam_id have to be defined") # TODO # 2D ARRAY (FITS IMAGE) TO CTAPIPE IMAGE ############### geom_1d = geometry_converter.get_geom1d(cam_id) img_1d = geometry_converter.image_2d_to_1d(input_img, cam_id) # APPLY TAILCUT CLEANING ############################## mask = tailcuts_clean(geom_1d, img_1d, picture_thresh=high_threshold, boundary_thresh=low_threshold) img_1d[mask == False] = 0 # CTAPIPE IMAGE TO 2D ARRAY (FITS IMAGE) ############### cleaned_img_2d = geometry_converter.image_1d_to_2d(img_1d, cam_id) # KILL ISOLATED PIXELS ################################# img_cleaned_islands_delta_pe, img_cleaned_islands_delta_abs_pe, img_cleaned_islands_delta_num_pixels = kill_isolated_pixels_stats(cleaned_img_2d) img_cleaned_num_islands = number_of_islands(cleaned_img_2d) if output_data_dict is not None: output_data_dict["img_cleaned_islands_delta_pe"] = img_cleaned_islands_delta_pe output_data_dict["img_cleaned_islands_delta_abs_pe"] = img_cleaned_islands_delta_abs_pe output_data_dict["img_cleaned_islands_delta_num_pixels"] = img_cleaned_islands_delta_num_pixels output_data_dict["img_cleaned_num_islands"] = img_cleaned_num_islands if kill_isolated_pixels: if verbose: print("Kill isolated pixels") cleaned_img_2d = scipy_kill_isolated_pixels(cleaned_img_2d)
return cleaned_img_2d def main(): # PARSE OPTIONS ########################################################### parser = argparse.ArgumentParser(description="Denoise FITS images with the tailcut algorithm.") parser.add_argument("--high-threshold", "-T", type=float, default=0, metavar="FLOAT", help="The 'high' threshold value") parser.add_argument("--low-threshold", "-t", type=float, default=0, metavar="FLOAT", help="The 'low' threshold value") parser.add_argument("--kill-isolated-pixels", action="store_true", help="Suppress isolated pixels in the support (scipy implementation)") # COMMON OPTIONS parser.add_argument("--verbose", "-v", action="store_true", help="Verbose mode") parser.add_argument("--debug", action="store_true", help="Debug mode") parser.add_argument("--max-images", type=int, metavar="INTEGER", help="The maximum number of images to process") parser.add_argument("--telid", type=int, metavar="INTEGER", help="Only process images from the specified telescope") parser.add_argument("--eventid", type=int, metavar="INTEGER", help="Only process images from the specified event") parser.add_argument("--camid", metavar="STRING", help="Only process images from the specified camera") parser.add_argument("--benchmark", "-b", metavar="STRING", help="The benchmark method to use to assess the algorithm for the" "given images") parser.add_argument("--label", "-l", default=None, metavar="STRING", help="The label attached to the produced results") parser.add_argument("--plot", action="store_true", help="Plot images") parser.add_argument("--saveplot", default=None, metavar="FILE", help="The output file where to save plotted images") parser.add_argument("--output", "-o", default=None, metavar="FILE", help="The output file path (JSON)") parser.add_argument("fileargs", nargs="+", metavar="FILE", help="The files image to process (FITS)." "If fileargs is a directory," "all FITS files it contains are processed.") args = parser.parse_args() high_threshold = args.high_threshold low_threshold = args.low_threshold kill_isolated_pixels = args.kill_isolated_pixels verbose = args.verbose debug = args.debug max_images = args.max_images tel_id = args.telid event_id = args.eventid cam_id = args.camid benchmark_method = args.benchmark label = args.label plot = args.plot saveplot = args.saveplot input_file_or_dir_path_list = args.fileargs if args.output is None: output_file_path = "score_tailcut_benchmark_{}.json".format(benchmark_method) else: output_file_path = args.output cleaning_function_params = { "high_threshold": high_threshold, "low_threshold": low_threshold, "kill_isolated_pixels": kill_isolated_pixels, "verbose": verbose } cleaning_algorithm = Tailcut() if verbose: cleaning_algorithm.verbose = True if label is not None: cleaning_algorithm.label = label output_dict = cleaning_algorithm.run(cleaning_function_params, input_file_or_dir_path_list, benchmark_method, output_file_path, plot=plot, saveplot=saveplot, max_num_img=max_images, tel_id=tel_id, event_id=event_id, cam_id=cam_id, debug=debug) if __name__ == "__main__": main()