def test_chart_with_wcs(): """test cartographer.chart""" helpers.setup(with_data=True) out_dir = helpers.TEST_PATH title = "test" map_layer_names = "test_layer" marker_file_names = "test_marker" wcs = WCS(os.path.join(out_dir, "test_image.fits")) columns = "a,b,c" with open(os.path.join(out_dir, f"{marker_file_names}.columns"), "w") as f: f.write(columns) list( map( lambda r: os.makedirs( os.path.join(out_dir, map_layer_names, str(r))), range(2), )) os.mkdir(os.path.join(out_dir, "js")) os.mkdir(os.path.join(out_dir, "css")) c.chart( out_dir, title, [map_layer_names], [marker_file_names], wcs, float("inf"), [100, 100], ) # inject current version in to test_index.html version = helpers.get_version() raw_path = os.path.join(out_dir, "test_index_wcs.html") with open(raw_path, "r") as f: converted = list( map(lambda l: l.replace("VERSION", version), f.readlines())) with open(raw_path, "w") as f: f.writelines(converted) actual_html = os.path.join(out_dir, "index.html") expected_html = os.path.join(out_dir, "test_index_wcs.html") files_match = filecmp.cmp(expected_html, actual_html) helpers.tear_down() assert files_match
def files_to_map( files: List[str], out_dir: str = ".", min_zoom: int = 0, title: str = "FitsMap", task_procs: int = 0, procs_per_task: int = 0, catalog_delim: str = ",", cat_wcs_fits_file: str = None, max_catalog_zoom: int = -1, tile_size: Tuple[int, int] = [256, 256], image_engine: str = IMG_ENGINE_MPL, norm_kwargs: dict = {}, rows_per_column: int = np.inf, prefer_xy: bool = False, ) -> None: """Converts a list of files into a LeafletJS map. Args: files (List[str]): List of files to convert into a map, can include image files (.fits, .png, .jpg) and catalog files (.cat) out_dir (str): Directory to place the genreated web page and associated subdirectories min_zoom (int): The minimum zoom to create tiles for. The default value is 0, but if it can be helpful to set it to a value greater than zero if your running out of memory as the lowest zoom images can be the most memory intensive. title (str): The title to placed on the webpage task_procs (int): The number of tasks to run in parallel procs_per_task (int): The number of tiles to process in parallel catalog_delim (str): The delimited for catalog (.cat) files. Deault is whitespace. cat_wcs_fits_file (str): A fits file that has the WCS that will be used to map ra and dec coordinates from the catalog files to x and y coordinates in the map max_catalog_zoom (int): The zoom level to stop clustering on, the default is the max zoom level of the image. For images with a high source density, setting this higher than the max zoom will help with performance. tile_size (Tuple[int, int]): The tile size for the leaflet map. Currently only [256, 256] is supported. image_engine (str): The method that converts the image data into image tiles. The default is convert.IMG_ENGINE_MPL (matplotlib) the other option is convert.IMG_ENGINE_PIL (pillow). Pillow can render FITS files but doesn't do any scaling. Pillow may be more performant for only PNG images. norm_kwargs (dict): Optional normalization keyword arguments passed to `astropy.visualization.simple_norm`. The default is linear scaling using min/max values. See documentation for more information: https://docs.astropy.org/en/stable/api/astropy.visualization.mpl_normalize.simple_norm.html rows_per_column (int): If converting a catalog, the number of items in have in each column of the marker popup. By default produces all values in a single column. Setting this value can make it easier to work with catalogs that have a lot of values for each object. Returns: None """ if len(files) == 0: raise ValueError("No files provided `files` is an empty list") unlocatable_files = list(filterfalse(os.path.exists, files)) if len(unlocatable_files) > 0: raise FileNotFoundError(unlocatable_files) if not os.path.exists(out_dir): os.makedirs(out_dir) if "js" not in os.listdir(out_dir): os.mkdir(os.path.join(out_dir, "js")) if "css" not in os.listdir(out_dir): os.mkdir(os.path.join(out_dir, "css")) img_f_kwargs = dict( tile_size=tile_size, min_zoom=min_zoom, image_engine=image_engine, out_dir=out_dir, mp_procs=procs_per_task, norm_kwargs=norm_kwargs, ) img_files = filter_on_extension(files, IMG_FORMATS) img_layer_names = list(map(get_map_layer_name, img_files)) img_job_f = partial(tile_img, **img_f_kwargs) cat_files = filter_on_extension(files, CAT_FORMAT) cat_layer_names = list(map(get_map_layer_name, cat_files)) max_x, max_y = utils.peek_image_info(img_files) max_dim = max(max_x, max_y) if len(cat_files) > 0: # get highlevel image info for catalogging function max_zoom = int(np.log2(2**np.ceil(np.log2(max_dim)) / tile_size[0])) max_dim = 2**max_zoom * tile_size[0] if max_catalog_zoom == -1: max_zoom = int(np.log2(2**np.ceil(np.log2(max_dim)) / tile_size[0])) else: max_zoom = max_catalog_zoom cat_job_f = partial( tile_markers, cat_wcs_fits_file, out_dir, catalog_delim, procs_per_task, prefer_xy, min_zoom, max_zoom, tile_size[0], max_dim, max_dim, ) else: cat_job_f = None pbar_locations = count(0) img_tasks = zip(repeat(img_job_f), zip(img_files, pbar_locations)) cat_tasks = zip(repeat(cat_job_f), zip(cat_files, pbar_locations)) tasks = chain(img_tasks, cat_tasks) if task_procs: q = JoinableQueue() any(map(lambda t: q.put(t), tasks)) workers = [ Process(target=async_worker, args=[q]) for _ in range(task_procs) ] [w.start() for w in workers] # can use any-map if this returns None q.join() else: any(map(lambda func_args: func_args[0](*func_args[1]), tasks)) ns = "\n" * (next(pbar_locations) - 1) print(ns + "Building index.html") if cat_wcs_fits_file is not None: cat_wcs = WCS(cat_wcs_fits_file) else: cat_wcs = None cartographer.chart( out_dir, title, img_layer_names, cat_layer_names, cat_wcs, rows_per_column, (max_x, max_y), ) print("Done.")