Ejemplo n.º 1
0
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
Ejemplo n.º 2
0
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.")