U
    e^                    @   s   d Z ddlZddlZddlZddlZddlmZ ddlZddlZddl	Z	ddl
ZddlmZ dejd< dd Zdd	d
Zdd Zdd ZdddZdddZdddZdddZdddZdd d!Zd"d# Zd$d% Zdd'd(Zd)d* Zd+d, Zdd-d.Zd/d0 Z de!e!e!e"d2d3d4Z#de!e"e!e"d5d6d7Z$dd8d9Z%dd;d<Z&de!e"e!e"d5d=d>Z'de!e!e!e"d?d@dAZ(dBdC Z)dDdE Z*dFdG Z+dHdI Z,ddJdKZ-dLdM Z.ddNdOZ/ddPdQZ0e,dRddSddTdUfdVdWZ1ddYdZZ2e,dRddSfd[d\Z3dd]d^Z4d_d` Z5ddadbZ6ddcddZ7ddedfZ8ddgdhZ9ddidjZ:ddkdlZ;ddmdnZ<doddpi i fdqdrZ=ddsdtZ>ddwdxZ?dydz Z@d{d|d}d&gi i fd~dZAdddZBdddZCdddZDdddZEdddZFdddZGdd ZHdddZIdddZJdddZKddddgfddZLdS )z
The source code is adapted from https://github.com/aliaksandr960/segment-anything-eo. Credit to the author Aliaksandr Hancharenka.
    N)tqdmzAPI-KEYZGOOGLE_MAPS_API_KEYc                  C   s   ddl } d| jkrdS dS dS )z8Tests if the code is being executed within Google Colab.r   Ngoogle.colabTF)sysmodules)r    r   P/home/ankuromar296_gmail_com/.local/lib/python3.8/site-packages/samgeo/common.pyis_colab   s    
r   Tc                 C   sd   t | trX| dr"tj| } ntj| } tj| }tj|sT|rTt	| | S t
ddS )a  Gets the absolute file path.

    Args:
        file_path (str): The path to the file.
        make_dirs (bool, optional): Whether to create the directory if it does not exist. Defaults to True.

    Raises:
        FileNotFoundError: If the directory could not be found.
        TypeError: If the input directory path is not a string.

    Returns:
        str: The absolute path to the file.
    ~z(The provided file path must be a string.N)
isinstancestr
startswithospath
expanduserabspathdirnameexistsmakedirs	TypeError)	file_pathZ	make_dirsZfile_dirr   r   r   check_file_path   s    


r   c                 C   sL   ddl }ddl}| ds"d|  } t| }tj| | |  }|S )zReturns a temporary file path.

    Args:
        extension (str): The file extension.

    Returns:
        str: The temporary file path.
    r   N.)	tempfileuuidr   r   uuid4r   r   join
gettempdir)	extensionr   r   Zfile_idr   r   r   r   temp_file_path<   s    

r   c                 C   s4   t | tr0| dr0d| kr0| dddd} | S )z|Get the raw URL for a GitHub file.

    Args:
        url (str): The GitHub URL.
    Returns:
        str: The raw URL.
    zhttps://github.com/Zblobz
github.comzraw.githubusercontent.comzblob/ )r
   r   r   replace)urlr   r   r   github_raw_urlQ   s     r"   Fc                 C   s  ddl }zddl}W n tk
r2   td Y dS X |dkr\t| tr\| dr\tj	| }tj
tj|}tj|st| t| trtjtj
|r|st| d tj
|S t| } d| krd}|| |||||||||	
}|
r|dr||d	v}|s td
 |rptjtj	|d }tj||}tj|sdt| || n|tj| W 5 Q R X tj
|S )ap  Download a file from URL, including Google Drive shared URL.

    Args:
        url (str, optional): Google Drive URL is also supported. Defaults to None.
        output (str, optional): Output filename. Default is basename of URL.
        quiet (bool, optional): Suppress terminal output. Default is False.
        proxy (str, optional): Proxy. Defaults to None.
        speed (float, optional): Download byte size per second (e.g., 256KB/s = 256 * 1024). Defaults to None.
        use_cookies (bool, optional): Flag to use cookies. Defaults to True.
        verify (bool | str, optional): Either a bool, in which case it controls whether the server's TLS certificate is verified, or a string,
            in which case it must be a path to a CA bundle to use. Default is True.. Defaults to True.
        id (str, optional): Google Drive's file ID. Defaults to None.
        fuzzy (bool, optional): Fuzzy extraction of Google Drive's file Id. Defaults to False.
        resume (bool, optional): Resume the download from existing tmp file if possible. Defaults to False.
        unzip (bool, optional): Unzip the file. Defaults to True.
        overwrite (bool, optional): Overwrite the file if it already exists. Defaults to False.
        subfolder (bool, optional): Create a subfolder with the same name as the file. Defaults to False.

    Returns:
        str: The output file path.
    r   NzWThe gdown package is required for this function. Use `pip install gdown` to install it.httpzC already exists. Skip downloading. Set overwrite=True to overwrite.z https://drive.google.com/file/d/Tz.ziprzExtracting files...)zipfilegdownImportErrorprintr
   r   r   r   r   basenamer   r   r   r   r"   downloadendswithZipFilesplitextr   
extractall)r!   outputquietproxyspeedZuse_cookiesverifyidZfuzzyresumeZunzip	overwriteZ	subfolderr%   r&   out_dirZzip_refr)   r   r   r   download_file`   s^    $

         
r8   vit_hc                 C   s   |s$dddddddddd}n&d	d
ddddddddddd}| |krlt d|  dd| |dkrtjdtjd}tj|||  d }tj|std|  d ||  d }t	|| |S )a  Download the SAM model checkpoint.

    Args:
        model_type (str, optional): The model type. Can be one of ['vit_h', 'vit_l', 'vit_b'].
            Defaults to 'vit_h'. See https://bit.ly/3VrpxUh for more details.
        checkpoint_dir (str, optional): The checkpoint_dir directory. Defaults to None, "~/.cache/torch/hub/checkpoints".
        hq (bool, optional): Whether to use HQ-SAM model (https://github.com/SysCV/sam-hq). Defaults to False.
    sam_vit_h_4b8939.pthDhttps://dl.fbaipublicfiles.com/segment_anything/sam_vit_h_4b8939.pth)namer!   sam_vit_l_0b3195.pthDhttps://dl.fbaipublicfiles.com/segment_anything/sam_vit_l_0b3195.pthsam_vit_b_01ec64.pthDhttps://dl.fbaipublicfiles.com/segment_anything/sam_vit_b_01ec64.pth)r9   vit_lvit_bzsam_hq_vit_h.pthzRhttps://drive.google.com/file/d/1qobFYrI4eyIANfBSmYcGuWRaSIXfMOQ8/view?usp=sharingzsam_hq_vit_l.pthzRhttps://drive.google.com/file/d/1Uk17tDKX1YAKas5knI4y9ZJCo0lRVL0G/view?usp=sharingzsam_hq_vit_b.pthzRhttps://drive.google.com/file/d/11yExZLOve38kRZPfRx_MRxfIAKmfMY47/view?usp=sharingzsam_hq_vit_tiny.pthzDhttps://huggingface.co/lkeab/hq-sam/resolve/main/sam_hq_vit_tiny.pth)r9   rA   rB   Zvit_tinyzInvalid model_type: z. It must be one of z, NZ
TORCH_HOMEz~/.cache/torch/hub/checkpointsr<   zModel checkpoint for z not found.r!   )

ValueErrorr   r   environgetr   r   r   r(   r8   )Z
model_typeZcheckpoint_dirZhqZmodel_types
checkpointr!   r   r   r   download_checkpoint   sN    
 

rG   c                 K   s`   dddd}t | tr&| |kr&||  } | dkr6|d } |dkrJtj| }t| |fd|i|S )a  Download a checkpoint from URL. It can be one of the following: sam_vit_h_4b8939.pth, sam_vit_l_0b3195.pth, sam_vit_b_01ec64.pth.

    Args:
        url (str, optional): The checkpoint URL. Defaults to None.
        output (str, optional): The output file path. Defaults to None.
        overwrite (bool, optional): Overwrite the file if it already exists. Defaults to False.

    Returns:
        str: The output file path.
    r;   r>   r@   )r:   r=   r?   Nr:   r6   )r
   r   r   r   r)   r8   )r!   r/   r6   kwargsZcheckpointsr   r   r   download_checkpoint_legacy   s    rI   deflatec                 K   s   zddl m} ddlm} W n tk
r8   tdY nX | ds`t| } tj	| s`t
d|dkr| dstj| d d }n
td	d
}t|}||}|| ||f| dS )a  Converts an image to a COG file.

    Args:
        source (str): A dataset path, URL or rasterio.io.DatasetReader object.
        dst_path (str, optional): An output dataset path or or PathLike object. Defaults to None.
        profile (str, optional): COG profile. More at https://cogeotiff.github.io/rio-cogeo/profile. Defaults to "deflate".

    Raises:
        ImportError: If rio-cogeo is not installed.
        FileNotFoundError: If the source file could not be found.
    r   )cog_translate)cog_profileszThe rio-cogeo package is not installed. Please install it with `pip install rio-cogeo` or `conda install rio-cogeo -c conda-forge`.r#   z+The provided input file could not be found.Nz_cog.tif.tif)r   )Zrio_cogeo.cogeorK   Zrio_cogeo.profilesrL   r'   r   r   r   r   r   FileNotFoundErrorr-   r   rE   )sourceZdst_pathprofilerH   rK   rL   Zdst_profiler   r   r   image_to_cog  s$    




rQ   	EPSG:4326nearestc                 K   s@  ddl }ddlm}m}m}	 t|tr0t|	|}tj	
| } tj	
|}tj	tj	|snttj	| |j| f|}
||
j||
j|
jf|
j \}}}|
j }|||||d |j|df|N}td|
jd D ]6}|f ||
|||||
j|
j|||d| qW 5 Q R X W 5 Q R X |r<t|| dS )a  Reprojects an image.

    Args:
        image (str): The input image filepath.
        output (str): The output image filepath.
        dst_crs (str, optional): The destination CRS. Defaults to "EPSG:4326".
        resampling (Resampling, optional): The resampling method. Defaults to "nearest".
        to_cog (bool, optional): Whether to convert the output image to a Cloud Optimized GeoTIFF. Defaults to True.
        **kwargs: Additional keyword arguments to pass to rasterio.open.

    r   N)calculate_default_transform	reproject
Resampling)crs	transformwidthheightw   )rO   destinationZsrc_transformsrc_crsZdst_transformdst_crs
resampling)rasterioZrasterio.warprT   rU   rV   r
   r   getattrr   r   r   r   r   r   openrW   rY   rZ   boundsmetacopyupdaterangecountbandrX   rQ   )imager/   r_   r`   to_cogrH   ZriorT   rU   rV   srcrX   rY   rZ   dstir   r   r   rU   :  sP    

   
	

rU   OpenStreetMap	EPSG:3857c
                    s  ddl }ddl
ddlddlddlddlddlm zddlm	m
} W n tk
rl   tdY nX zddl}| W n$ tk
r   ddl}| Y nX |s|j| rtd|  d dS dd	d
ddd}t }t|tr,| |kr
||  }n ||kr|| }n|dr4ntdfdd}t|trht|dkrh|\}}}}ntd|dkr|dkrtdn|dk	r|dk	rtd|dk	r||}d d_  | }|d |  fddfdddd 
fddd d! fd"d#	d)	fd%d&	}zZ|||||||| |	f|
}|rx|W S | d'krt | | ||d( n|rt!| |  W n, t"k
r } zt"|W 5 d}~X Y nX dS )*a  Download TMS tiles and convert them to a GeoTIFF. The source is adapted from https://github.com/gumblex/tms2geotiff.
        Credits to the GitHub user @gumblex.

    Args:
        output (str): The output GeoTIFF file.
        bbox (list): The bounding box [minx, miny, maxx, maxy], e.g., [-122.5216, 37.733, -122.3661, 37.8095]
        zoom (int, optional): The map zoom level. Defaults to None.
        resolution (float, optional): The resolution in meters. Defaults to None.
        source (str, optional): The tile source. It can be one of the following: "OPENSTREETMAP", "ROADMAP",
            "SATELLITE", "TERRAIN", "HYBRID", or an HTTP URL. Defaults to "OpenStreetMap".
        crs (str, optional): The output CRS. Defaults to "EPSG:3857".
        to_cog (bool, optional): Convert to Cloud Optimized GeoTIFF. Defaults to False.
        return_image (bool, optional): Return the image as PIL.Image. Defaults to False.
        overwrite (bool, optional): Overwrite the output file if it already exists. Defaults to False.
        quiet (bool, optional): Suppress output. Defaults to False.
        **kwargs: Additional arguments to pass to gdal.GetDriverByName("GTiff").Create().

    r   NImage)gdalosrz7GDAL is not installed. Install it with pip install GDALzThe output file z6 already exists. Use `overwrite=True` to overwrite it.z.https://tile.openstreetmap.org/{z}/{x}/{y}.pngz2https://mt1.google.com/vt/lyrs=m&x={x}&y={y}&z={z}z2https://mt1.google.com/vt/lyrs=s&x={x}&y={y}&z={z}z2https://mt1.google.com/vt/lyrs=p&x={x}&y={y}&z={z}z2https://mt1.google.com/vt/lyrs=y&x={x}&y={y}&z={z})ZOPENSTREETMAPZROADMAP	SATELLITEZTERRAINZHYBRIDr#   z\source must be one of "OpenStreetMap", "ROADMAP", "SATELLITE", "TERRAIN", "HYBRID", or a URLc                    s   d}  ||  }t|S )zd
        Convert map resolution in meters to zoom level for Web Mercator (EPSG:3857) tiles.
        g|EA)log2int)
resolutionZinitial_resolutionZ
zoom_levelmathr   r   resolution_to_zoom_level  s    z0tms_to_geotiff.<locals>.resolution_to_zoom_level   zNbbox must be a list of 4 coordinates in the format of [xmin, ymin, xmax, ymax]z*Either zoom or resolution must be providedz.Only one of zoom or resolution can be providedg   @TXAi  c              	      s8    |  } d| d    }||fS )N-   g       @)radianslogtan)latlonxtileytile)EARTH_EQUATORIAL_RADIUSr{   r   r   from4326_to3857  s     z'tms_to_geotiff.<locals>.from4326_to3857c                    sZ     | }d| }|d d | }d  |d |   j  d | }||fS )N      ih  r\   )r   r   r   cospi)r   r   zoomZlat_rnr   r   rz   r   r   deg2num  s
    
0ztms_to_geotiff.<locals>.deg2numc                 S   sd   |   }t|dkrTt|dkr0|d dkr0dS |d d D ]}|dkr< dS q<dS |d dkS d S )N   )r   r   TFr   )
getextremalen)imZextremaextr   r   r   is_empty  s    z tms_to_geotiff.<locals>.is_emptyc                    s  |d kr| S   |}|jdkr*dnd}|j}| d kr|d |d< |d |d<  ||d |d |d   |d |d |d   f}n| }t|d |d  }	t|d |d  }
|d |	 |d |
 f}|dkr||| n*|j|kr||}|s||| |  |S )NRGBRGBAr   r\   r   r   )	rc   BytesIOmodesizenewabsZpasteconvertclose)bigim	base_sizetile	corner_xybboxr   r   r   ZnewimZdxZdyZxy0)rs   ior   r   r   
paste_tile  s0     .


z"tms_to_geotiff.<locals>.paste_tilec                 S   s   ||d  }||d  }t |d | }	t |d | }
t |d ||  }t |d ||  }| |	|
|	| |
| f}|jdkr| d dkr|d}|   |S )Nr   r\   r   r   )   r   r   )roundcropr   r   r   r   )r   r   r   x0y0x1y1ZxfracZyfracZx2y2ZimgwZimghZretimr   r   r   finish_picture!  s    
z&tms_to_geotiff.<locals>.finish_picturec                    sf   d}z j | dd}W q@W q tk
r<   |d8 }|s8 Y qX q|jdkrNd S |jsXd S |  |jS )Nr   <   )timeoutr\   i  )rE   	Exceptionstatus_codecontentraise_for_status)r!   retryr$   )SESSIONr   r   get_tile.  s    

z tms_to_geotiff.<locals>.get_tileFc           %         s  |||\}	}
|||\}}t |	|g\}	}t |
|g\}
}tt|	|t|
|}t|}g }jd}|D ]&\}}|	|
| j|||d q|	|
||f}d }ddg}tt||dD ]J\}\}}
||| ||}|stdt|tt| d|  qW 5 Q R X |s^td ||||	|
||}t| }d}d	|krd
dddg|d	< |j||jd |jd |jf|}||\}}||\}} t|| |jd  }!t| | |jd  }"|t|||!dt|| d|" f |  t|D ]L}#	j||#dd}$|$|jd |jd f}$||#d }#|# |$ qD|!  |std|  |S )N   )zxy   r\   zDownloaded image /zSaving GeoTIFF. Please wait...GTiffoptionsCOMPRESS=DEFLATEzPREDICTOR=2zZLEVEL=9z	TILED=YESr   u8)dtypezImage saved to )"sortedtupleproductrh   floorceilr   futuresThreadPoolExecutorappendsubmitformat	enumeratezipresultr(   r   zfillZgetbandsGetDriverByNameCreater   ZGDT_Byter   SetGeoTransformminmaxSetProjectionarrayZgetdatareshapeGetRasterBand
WriteArrayZ
FlushCache)%rO   lat0lon0lat1lon1r   filenamer0   rH   r   r   r   r   ZcornersZtotalnumr   executorr   r   r   r   r   kfutr   imgZimgbandsdriverZgtiffZxp0Zyp0Zxp1Zyp1ZpwidthZpheightrj   r   )WKT_3857
concurrentr   r   r   rt   r   	itertoolsr{   numpyr   r   r   	draw_tile?  sz    $ 

$
z!tms_to_geotiff.<locals>.draw_tilerq   )rl   )F)#r   r   r{   r   concurrent.futuresr   PILrs   osgeort   ru   r'   httpxZClientrequestsSessionr   r   r(   get_basemapsr
   r   upperr   rC   listr   ZMAX_IMAGE_PIXELSZUseExceptionsZSpatialReferenceZImportFromEPSGZExportToWktrU   rQ   r   )r/   r   r   ry   rO   rW   rl   return_imager6   r0   rH   r   ru   r   r   Z	xyz_tilesbasemapsr|   ZwestZsouthZeastZnorthZweb_mercatorr   rk   er   )r   rs   r   r   r   r   r   r   rt   r   r   r   r   r{   r   r   r   tms_to_geotiffs  s     





 "E       r   c              
   C   s(   t | }|jW  5 Q R  S Q R X d S N)ra   rc   rP   src_fprm   r   r   r   get_profile  s    r   c              
   C   s(   t | }|jW  5 Q R  S Q R X d S r   )ra   rc   rW   r   r   r   r   get_crs  s    r   r\   c                 C   sd   ddl m} t | D}|j||ddddddd}tj|}||j |W  5 Q R  S Q R X d S )Nr   featuresr\   TFr   )bidxZsamplingrj   Zas_maskZwith_nodataZ
geographic	precision)	ra   r   rc   Zdataset_featuresgpdGeoDataFramefrom_featuresset_crsrW   )r   r   r   rm   gdfr   r   r   get_features  s    
r  c                 C   s   t jj| ||f S r   )ra   rX   Zfrom_bounds)Zgeo_boxrY   rZ   r   r   r   set_transform  s    r  c                 K   s&   t jj||fddi|}|| |S )aQ  Transform coordinates from one CRS to another.

    Args:
        x (float): The x coordinate.
        y (float): The y coordinate.
        src_crs (str): The source CRS, e.g., "EPSG:4326".
        dst_crs (str): The destination CRS, e.g., "EPSG:3857".

    Returns:
        dict: The transformed coordinates in the format of (x, y)
    Z	always_xyT)pyprojZTransformerZfrom_crsrX   )r   r   r^   r_   rH   Ztransformerr   r   r   transform_coords  s     r  c                 K   s@   |  dst| } tj| f|}|dkr.|jS |j|dd dS )zConverts a vector file to a geojson file.

    Args:
        filename (str): The vector file path.
        output (str, optional): The output geojson file path. Defaults to None.

    Returns:
        dict: The geojson dictionary.
    r#   NGeoJSONr   )r   r8   r   	read_fileZ__geo_interface__to_file)r   r/   rH   r  r   r   r   vector_to_geojson  s    
r  c                 K   s4   t j| f|}|j }|dkr&|jS d| S dS )zGets the CRS of a vector file.

    Args:
        filename (str): The vector file path.

    Returns:
        str: The CRS of the vector file.
    NzEPSG:)r   r  rW   to_epsg)r   rH   r  Zepsgr   r   r   get_vector_crs  s
    	
r  	epsg:4326)geojsonr^   r_   returnc                 C   s   ddl }ddl}|d t| tr.|| } tj| dd}|jj	}dd |D }||krt
dd |D d	d |D ||}d
d t|d |d D }|S )a  Converts a geojson file or a dictionary of feature collection to a list of centroid coordinates.

    Args:
        geojson (str | dict): The geojson file path or a dictionary of feature collection.
        src_crs (str, optional): The source CRS. Defaults to "epsg:4326".
        dst_crs (str, optional): The destination CRS. Defaults to "epsg:4326".

    Returns:
        list: A list of centroid coordinates in the format of [[x1, y1], [x2, y2], ...]
    r   Nignorer	  r
  c                 S   s   g | ]}|j |jgqS r   r   r   .0pointr   r   r   
<listcomp>  s     z%geojson_to_coords.<locals>.<listcomp>c                 S   s   g | ]}|d  qS r   r   r  r   r   r   r   r    s     c                 S   s   g | ]}|d  qS r\   r   r  r   r   r   r    s     c                 S   s   g | ]\}}||gqS r   r   r  r   r   r   r   r   r  
  s     r\   )jsonwarningsfilterwarningsr
   dictdumpsr   r  geometrycentroidr  r   )r  r^   r_   r  r  r  	centroidsZcentroid_listr   r   r   geojson_to_coords  s"    


r%  )r   coords	coord_crsr  c           
   	      s   t |tjr| }t| \}}t| N}|j|j ||j	krZt
||||j	f|\}}tjj|j||f|\}}W 5 Q R X dd t||D }	 fdd|	D }	t|	dkrtd nt|	t|k rtd |	S )a  Converts a list of coordinates to pixel coordinates, i.e., (col, row) coordinates.

    Args:
        src_fp: The source raster file path.
        coords: A list of coordinates in the format of [[x1, y1], [x2, y2], ...]
        coord_crs: The coordinate CRS of the input coordinates. Defaults to "epsg:4326".
        **kwargs: Additional keyword arguments to pass to rasterio.transform.rowcol.

    Returns:
        A list of pixel coordinates in the format of [[x1, y1], [x2, y2], ...]
    c                 S   s   g | ]\}}||gqS r   r   )r  colrowr   r   r   r  &  s     z coords_to_xy.<locals>.<listcomp>c                    s8   g | ]0\}}|d kr|d kr|k r| k r||gqS r  r   r  rZ   rY   r   r   r  (  s        r   !No valid pixel coordinates found./Some coordinates are out of the image boundary.)r
   npndarraytolistr   ra   rc   rY   rZ   rW   r  rX   rowcolr   r(   )
r   r&  r'  rH   xsysrm   rowscolsr   r   r*  r   coords_to_xy  s$    
$
r5  c                    sZ   ddl m   fdd| D }tjd|i|d}||}|dk	rR|j|f| n|S dS )a9  
    Convert a list of bounding box coordinates to vector data.

    Args:
        coords (list): A list of bounding box coordinates in the format [[left, top, right, bottom], [left, top, right, bottom], ...].
        src_crs (int or str): The EPSG code or proj4 string representing the source coordinate reference system (CRS) of the input coordinates.
        dst_crs (int or str, optional): The EPSG code or proj4 string representing the destination CRS to reproject the data (default is "EPSG:4326").
        output (str or None, optional): The full file path (including the directory and filename without the extension) where the vector data should be saved.
                                       If None (default), the function returns the GeoDataFrame without saving it to a file.
        **kwargs: Additional keyword arguments to pass to geopandas.GeoDataFrame.to_file() when saving the vector data.

    Returns:
        geopandas.GeoDataFrame or None: The GeoDataFrame with the converted vector data if output is None, otherwise None if the data is saved to a file.
    r   boxc                    s   g | ]} | qS r   r   )r  coordr6  r   r   r  F  s     z#boxes_to_vector.<locals>.<listcomp>r"  )rW   N)Zshapely.geometryr7  r   r  to_crsr  )r&  r^   r_   r/   rH   polygonsr  Zgdf_reprojectedr   r6  r   boxes_to_vector3  s    
r;  centerc              	      s   |dk	rRg }g }|D ]<}	| |	d  | |	d  | |	d  | |	d  q|dksb|dkrjtdt| *}
tjj|
j||||f|\ |
j}W 5 Q R X |dkrdd t D S  fd	dtdt	 dD }|dk	rt
|||| n|S dS )
a  Converts a list of (row, col) coordinates to (x, y) coordinates.

    Args:
        src_fp (str): The source raster file path.
        rows (list, optional): A list of row coordinates. Defaults to None.
        cols (list, optional): A list of col coordinates. Defaults to None.
        boxes (list, optional): A list of (row, col) coordinates in the format of [[left, top, right, bottom], [left, top, right, bottom], ...]
        zs: zs (list or float, optional): Height associated with coordinates. Primarily used for RPC based coordinate transformations.
        offset (str, optional): Determines if the returned coordinates are for the center of the pixel or for a corner.
        output (str, optional): The output vector file path. Defaults to None.
        dst_crs (str, optional): The destination CRS. Defaults to "EPSG:4326".
        **kwargs: Additional keyword arguments to pass to rasterio.transform.xy.

    Returns:
        A list of (x, y) coordinates.
    Nr\   r   r   r   zrows and cols must be provided.c                 S   s   g | ]\}}||gqS r   r   r  r   r   r   r    s     z rowcol_to_xy.<locals>.<listcomp>c                    s0   g | ](} | |d    |d   | gqS r  r   r  ro   r1  r2  r   r   r    s     )r   rC   ra   rc   rX   ZxyrW   r   rh   r   r;  )r   r3  r4  ZboxesZzsoffsetr/   r_   rH   r7  rm   r^   r   r   r>  r   rowcol_to_xyT  s&     r@  c              	   K   sP  t |tr>t|}|jjj }|jdk	rRd|j	  }nt |t
jrR| }t |trddl}||}tj|dd}|jjj }nt |tstdt |d ts|g}g }t| }|j}	|j}
|D ]}|\}}}}||jkrft||||jf|\}}t||||jf|\}}tjj|j||f|\}}tjj|j||f|\}}|||||g q|||||g qW 5 Q R X g }|D ]t}|\}}}}|dkr|dkr|dkr|dkr||	k r||
k r||	k r||
k r|||||g qt|dkrtd dS t|dkr2|d S t|t|k rLtd	 |S )
a  Converts a list of coordinates to pixel coordinates, i.e., (col, row) coordinates.
        Note that map bbox coords is [minx, miny, maxx, maxy] from bottomleft to topright
        While rasterio bbox coords is [minx, max, maxx, min] from topleft to bottomright

    Args:
        src_fp (str): The source raster file path.
        coords (list): A list of coordinates in the format of [[minx, miny, maxx, maxy], [minx, miny, maxx, maxy], ...]
        coord_crs (str, optional): The coordinate CRS of the input coordinates. Defaults to "epsg:4326".

    Returns:
        list: A list of pixel coordinates in the format of [[minx, maxy, maxx, miny], ...] from top left to bottom right.
    Nzepsg:r   r	  r
  z%coords must be a list of coordinates.r+  r\   r,  )r
   r   r   r  r"  rd   valuesr/  rW   r  r-  r.  r   r  r!  r   rC   ra   rc   rY   rZ   r  rX   r0  r   r   r(   )r   r&  r'  rH   r  r  r  Z
new_coordsrm   rY   rZ   r8  ZminxZminyZmaxxZmaxyZrows1Zcols1Zrows2Zcols2r   r   r   r   
bbox_to_xy  s    





    rB  )r   r  r'  r  c              	   K   s8   t | }|j}W 5 Q R X t|||}t| ||f|S )a  Converts a geojson file or a dictionary of feature collection to a list of pixel coordinates.

    Args:
        src_fp: The source raster file path.
        geojson: The geojson file path or a dictionary of feature collection.
        coord_crs: The coordinate CRS of the input coordinates. Defaults to "epsg:4326".
        **kwargs: Additional keyword arguments to pass to rasterio.transform.rowcol.

    Returns:
        A list of pixel coordinates in the format of [[x1, y1], [x2, y2], ...]
    )ra   rc   rW   r%  r5  )r   r  r'  rH   rm   r^   r&  r   r   r   geojson_to_xy  s    rC  c              	   C   sR   t | >}t j|j||\}}tt|t|t|t|g}W 5 Q R X |S r   )ra   rc   rX   r0  r-  r   r   r   )r   r1  r2  rm   r3  r4  r7  r   r   r   get_pixel_coords  s    ,rD  c                 C   s   |  | d S r   )r  )r  dst_fpr   r   r   write_features  s    rF  c           	   	   C   st   | ddd tj| df|J}t|jdkr>|tjdf }t|jd D ]}||| |d  qLW 5 Q R X d S )	Nr   0)r   nodatar[   r   .r   r\   )	rg   ra   rc   r   shaper-  Znewaxisrh   write)	rE  Zdst_arrrP   rY   rZ   rX   rW   rn   ro   r   r   r   write_raster  s    rK  c                 C   s    | d ddf } t | d} | S )Nr   .)r\   r   r   )r-  Z	transpose)blockr   r   r   
chw_to_hwc  s    rM  c                 C   s   | d|f  tj} | S )N.)astyper-  uint8)rL  Zchannelr   r   r   	hwc_to_hw  s    rP  c                 C   s   || }}g }|d|  }|d|  }	t | | |D ]^}
t | ||D ]J}t|||	 | }t||
| |  }|||
||	||g||ggd qFq4|S )Nr   )r   r   rZ   rY   rd   )rh   r   r   )raster_hraster_wsample_hsample_wboundhr[   blocksrZ   rY   r   r   Zright_x_boundZbottom_y_boundr   r   r   calculate_sample_grid  s"    
	rX  c                 K   s$   | j ||| f||| ffd|dS )NT)windowZ	boundlessZ
fill_value)read)rm   r   r   rZ   rY   rH  rH   r   r   r   
read_block4  s
      r[  c                 C   s   |r||d d |j d |d d  |d d |j d |d d  f }||d d 7 }||d d 7 }||d d  |d d  }||d d  |d d  }| j|d||| f||| ffd d S )Nr   r\   )rY  )rI  rJ  )rn   Zrasterr   r   rZ   rY   rd   r   r   r   write_block:  s    
 
 r\  )   r]     )r   r   r   c
              
   K   s"  t | }|j}|d |d  }}|\}}|}|}t|||||d}d|d< d|d< |d k	rnt|tj}t j|df|}t|D ]}t|f|}||}|j	d d	 }|d k	rt
j||t
jd
}||f|||	d|
}|d k	rt
j||t
jd
}t||f| qW 5 Q R X W 5 Q R X d S )NrZ   rY   )rQ  rR  rS  rT  rU  r\   ri   rO  r   r[   r   )interpolation)
foregrounderosion_kernelmask_multiplier)ra   rc   rP   rX  r-  ZonesrO  r   r[  rI  cv2resizeZINTER_LINEARZINTER_NEARESTr\  )r   rE  funcdata_to_rgbsample_sizesample_resizerU  r`  ra  rb  rH   rm   rP   ZrhrwshswZ	resize_hwZsample_gridrn   br$   Zuint8_rgb_inZ	orig_sizeZuin8_outr   r   r   tiff_to_tiffG  sX            rm    ro  c                 C   sz   t  d}td| \}}||  |j}t  ,}	|	j}
t||
|t|||d t	|
}W 5 Q R X W 5 Q R X |d S )NrM   rf  rg  rh  rU  .r   )
r   NamedTemporaryFilerc  ZimencoderJ  tobytesr<   rm  rM  imread)rk   re  rg  rh  rU  Zsrc_tmpfilesrl  r   dst_tmpfilerE  r   r   r   r   image_to_image  s"    


rw  c           	   
   C   sB   t  ,}|j}t| ||||||d t|}W 5 Q R X |d S )Nrp  rq  )r   rr  r<   rm  rc  rt  )	r   re  rf  rg  rh  rU  rv  rE  r   r   r   r   tiff_to_image  s    

rx  c              	      sp   ddl m} t | (}| }|dk}|j|||jd}W 5 Q R X dd |D } d k	rl fdd|D }|S )Nr   r   maskrX   c                 S   s   g | ]\}}t j|qS r   shapelyr"  rI  )r  rI  _r   r   r   r    s     z"tiff_to_shapes.<locals>.<listcomp>c                    s   g | ]}|j  d qS )Z	tolerance)simplify)r  rI  simplify_tolerancer   r   r    s     )ra   r   rc   rZ  shapesrX   )	tiff_pathr  r   rm   rj   rz  r  r   r   r  r   tiff_to_shapes  s    r  c           
   	   K   s0   ||||g}t ||f|d | dddd|}	|	S )NFT)r   ry   rO   rl   r   r0   )r   )
rO   r   r   r   r   r   r   rH   r   rk   r   r   r   r     s    	r   c              	   K   s   ddl m} t | (}| }|dk}|j|||jd}	W 5 Q R X dd |	D }
|dk	rx|
D ]}|d j|d|d< q^tj	|
}|j
dk	r|j|j
d	d
 |dk	r||}|j|f| dS )aI  Vectorize a raster dataset.

    Args:
        source (str): The path to the tiff file.
        output (str): The path to the vector file.
        simplify_tolerance (float, optional): The maximum allowed geometry displacement.
            The higher this value, the smaller the number of vertices in the resulting geometry.
    r   r   ry  c                 S   s&   g | ]\}}t j|d |idqS )value)r"  
propertiesr{  )r  rI  r  r   r   r   r    s   z$raster_to_vector.<locals>.<listcomp>Nr"  r~  T)rW   inplace)ra   r   rc   rZ  r  rX   r  r   r  r  rW   r  r9  r  )rO   r/   r  r_   rH   r   rm   rj   rz  r  fcro   r  r   r   r   raster_to_vector  s"    	

r  c                 K   s,   | ds|d7 }t| |fd|i| dS )aR  Convert a tiff file to a gpkg file.

    Args:
        tiff_path (str): The path to the tiff file.
        output (str): The path to the gpkg file.
        simplify_tolerance (float, optional): The maximum allowed geometry displacement.
            The higher this value, the smaller the number of vertices in the resulting geometry.
    .gpkgr  Nr+   r  r  r/   r  rH   r   r   r   raster_to_gpkg  s    

r  c                 K   s,   | ds|d7 }t| |fd|i| dS )aR  Convert a tiff file to a shapefile.

    Args:
        tiff_path (str): The path to the tiff file.
        output (str): The path to the shapefile.
        simplify_tolerance (float, optional): The maximum allowed geometry displacement.
            The higher this value, the smaller the number of vertices in the resulting geometry.
    z.shpr  Nr  r  r   r   r   raster_to_shp  s    

r  c                 K   s,   | ds|d7 }t| |fd|i| dS )aX  Convert a tiff file to a GeoJSON file.

    Args:
        tiff_path (str): The path to the tiff file.
        output (str): The path to the GeoJSON file.
        simplify_tolerance (float, optional): The maximum allowed geometry displacement.
            The higher this value, the smaller the number of vertices in the resulting geometry.
    z.geojsonr  Nr  r  r   r   r   raster_to_geojson  s    

r  c           	   	   C   s   ddl }ddlm} dd }i }| D ]}z<|d }|||}||| r^| rTqf|||< n|||< W q( tk
r   |D ]@}|| d }|||}||| r| rq|||< q||||< q|Y q(X q(|t| }|S )zReturns a dictionary of xyz services.

    Args:
        free_only (bool, optional): Whether to return only free xyz tile services that do not require an access token. Defaults to True.

    Returns:
        dict: A dictionary of xyz services.
    r   Nc                 S   s"   | }| dD ]}t||}q|S )Nr   )splitrb   )varparamtempZ	sub_paramr   r   r   _unpack_sub_parameters0  s    z,get_xyz_dict.<locals>._unpack_sub_parametersr<   )	collectionsZxyzservices.providers	providersrA  Zrequires_tokenr   OrderedDictr   items)		free_onlyr  Zxyzr  xyz_dictitemr<   r   Zsub_itemr   r   r   get_xyz_dict$  s0    	



r  c                 C   s:   i }t | d}|D ]"}|| j}||  }|||< q|S )zReturns a dictionary of xyz basemaps.

    Args:
        free_only (bool, optional): Whether to return only free xyz tile services that do not require an access token. Defaults to True.

    Returns:
        dict: A dictionary of xyz basemaps.
    )r  )r  r<   Z	build_url)r  r   r  r  r<   r!   r   r   r   r   S  s    



r   c              	   K   sB  ddl m} t| tr:tj| r:t| } t	| tj
} |dr&|dk	r&t| }|j}|j}	|dkrv|j}W 5 Q R X t| }
t| }|dkr |
dkr|dkrtj}nj|
dkr|dkrtj}nR|
dkr|dkrtj}n:|
dkr|d	krtj}n"|
d
kr|dkrtj}ntj}| |} | jdkrZd| jd | jd d| j||	d}n4| jdkrd| jd | jd | jd | j||	d}|dk	r||d< ntdtj|df|d}| jdkr|| d nD| jdkrt | jd D ](}|| dddd|f |d  qW 5 Q R X n|!| }|j"|f| dS )aN  Save a NumPy array as a GeoTIFF using the projection information from an existing GeoTIFF file.

    Args:
        array (np.ndarray): The NumPy array to be saved as a GeoTIFF.
        output (str): The path to the output image.
        source (str, optional): The path to an existing GeoTIFF file with map projection information. Defaults to None.
        dtype (np.dtype, optional): The data type of the output array. Defaults to None.
        compress (str, optional): The compression method. Can be one of the following: "deflate", "lzw", "packbits", "jpeg". Defaults to "deflate".
    r   rr   rM   Nr\   r   i   i  i i  r   r   )r   rZ   rY   ri   r   rW   rX   r   compresszArray must be 2D or 3D.r[   )#r   rs   r
   r   r   r   r   rc  rt  cvtColorCOLOR_BGR2RGBr+   ra   rc   rW   rX   compressionr-  r   r   float32rO  Zint8Zuint16Zint16Zfloat64rN  ndimrI  r   rC   rJ  rh   Z	fromarraysave)r   r/   rO   r   r  rH   rs   rm   rW   rX   Z	min_valueZ	max_valuemetadatarn   ro   r   r   r   r   array_to_imageg  sl    




	


2
r     
   offc                 K   s   t | trP| drt| } tj| s8td|  dt	| } t
| tj} tjf d|i| tj| fd|i| t| tjf | d S )Nr#   Input path  does not exist.figsizecmap)r
   r   r   r8   r   r   r   rC   rc  rt  r  r  pltfigureimshowaxisshow)rO   r  r  r  Zfig_argsZ	show_argsrH   r   r   r   
show_image  s    



r  c                 C   s~   t  }|r0tjtjdtdggdd}ntddddg}| jdd  \}}| ||d	|d	d	d
 }|| d S )Nr   g333333?r   r  g?g?g      ?r\   r   )	r  gcar-  Zconcatenaterandomr   rI  r   r  )rz  Zrandom_coloraxcolorrV  r[   Z
mask_imager   r   r   	show_mask  s    $r  w  onc              	   K   s  t | trP| drt| } tj| s8td|  dt	| } t
| tj} tj|d t|  t }	||dk }
||dk }|	j|
d d df |
d d df dd|d	d
d |	j|d d df |d d df dd|d	d
d |d k	rt| t| t  d S )Nr#   r  r  r  r\   r   green*whiteg      ?)r  markerru  	edgecolorZ	linewidthred)r
   r   r   r8   r   r   r   rC   rc  rt  r  r  r  r  r  r  Zscattertitler  r  )rk   r&  labelsZmarker_sizer  r  r  rz  rH   r  Z
pos_pointsZ
neg_pointsr   r   r   show_points  sD    



		

r  c              
   C   s`   t  }| d | d  }}| d | d  | d | d   }}|t j||f||dddd d S )Nr   r\   r   r   r  )r   r   r   r   )r  Z	facecolorZlw)r  r  Z	add_patchZ	Rectangle)r7  r  r   r   r[   rV  r   r   r   show_box  s    "r        ?ZTkAggr  c                    s<  ddl }ddl}ddlm}	 d|jkr6d}td dS || t| trx| 	dr\t
| } tj| sxtd|  dt|tr|	drt
|}tj|std| dt| }
t|}tjd	d
d|id\ \}}|j|
f|}|j|fd|i| fdd}|	j|ddd
|d}|| t  dS )a]  Overlays two images using a slider to control the opacity of the top image.

    Args:
        image1 (str | np.ndarray): The first input image at the bottom represented as a NumPy array or the path to the image.
        image2 (_type_): The second input image on top represented as a NumPy array or the path to the image.
        alpha (float, optional): The alpha value of the top image. Defaults to 0.5.
        backend (str, optional): The backend of the matplotlib plot. Defaults to "TkAgg".
        height_ratios (list, optional): The height ratios of the two subplots. Defaults to [10, 1].
        show_args1 (dict, optional): The keyword arguments to pass to the imshow() function for the first image. Defaults to {}.
        show_args2 (dict, optional): The keyword arguments to pass to the imshow() function for the second image. Defaults to {}.

    r   Nr   inlinezgThe TkAgg backend is not supported in Google Colab. The overlay_images function will not work on Colab.r#   r  r  r   r\   height_ratios)Zgridspec_kwalphac                    s    |   j  d S r   )Z	set_alphaZcanvasZ	draw_idle)r  Zfigimg1r   r   rg   S  s    
zoverlay_images.<locals>.update)r  labelZvalminZvalmaxZvalinit)r   
matplotlibZmatplotlib.widgetswidgetsr   r(   Zuser
   r   r   r8   r   r   r   rC   r  rt  Zsubplotsr  ZSliderZ
on_changedr  )Zimage1Zimage2r  backendr  Z
show_args1Z
show_args2r   r  Z	mpwidgetsr   r   Zax0Zax1Zimg0rg   Zslider0r   r  r   overlay_images  s:    








r  c           
      K   sX  t | trB| drt| } tj| s8td|  dt	| } t |tr|dr^t|}tj|sztd| dt	|}| j
tjkr| d tj} |j
tjkr|d tj}| j
|j
kr|| j
}t| |jd |jd f} d| }tj| |||df|}	|r t|	|| |rPtj|d t|	 t| t  n|	S dS )	at  
    Blends two images together using the addWeighted function from the OpenCV library.

    Args:
        img1 (numpy.ndarray): The first input image on top represented as a NumPy array.
        img2 (numpy.ndarray): The second input image at the bottom represented as a NumPy array.
        alpha (float): The weighting factor for the first image in the blend. By default, this is set to 0.5.
        output (str, optional): The path to the output image. Defaults to False.
        show (bool, optional): Whether to display the blended image. Defaults to True.
        figsize (tuple, optional): The size of the figure. Defaults to (12, 10).
        axis (str, optional): The axis of the figure. Defaults to "off".
        **kwargs: Additional keyword arguments to pass to the cv2.addWeighted() function.

    Returns:
        numpy.ndarray: The blended image as a NumPy array.
    r#   r  r  r   r\   r   r  N)r
   r   r   r8   r   r   r   rC   rc  rt  r   r-  r  rN  rO  rd  rI  ZaddWeightedr  r  r  r  r  r  )
r  Zimg2r  r/   r  r  r  rH   betaZ	blend_imgr   r   r   blend_images_  s:    








r  c           
   
   K   s   ddl }z| dkrt } d}d}t||f| tj| d}t }t| |ddkrdd}nd}t| t| |s|	| zt
| W n   Y nX td	 W n* tk
r }	 zt|	W 5 d}	~	X Y nX dS )
a_  Updates the package from the GitHub repository without the need to use pip or conda.

    Args:
        out_dir (str, optional): The output directory. Defaults to None.
        keep (bool, optional): Whether to keep the downloaded package. Defaults to False.
        **kwargs: Additional keyword arguments to pass to the download_file() function.
    r   NzJhttps://github.com/opengeos/segment-geospatial/archive/refs/heads/main.zipzsegment-geospatial-main.zipzsegment-geospatial-mainpipzpip3 install .zpip install .zPackage updated successfully.)shutilr   getcwdr8   r   r   chdirwhichsystemrmtreeremover(   r   )
r7   ZkeeprH   r  r!   r   Zpkg_dirZwork_dircmdr   r   r   r   update_package  s2    	



r  rv   c                    s  z@ddl ddl}ddl}ddlddl}ddlddlm  W n tk
r\   tdY nX dkrn|	 |j
f d|i|	ddi	_	j|dd	 z	jjd
d W n   Y nX g 	_g 	_j	jddj	jdd	 	 	_	_d}d}	d}
ddi}jdddjdd|
ddjddddjdd|
ddjddd djdd|
ddjdd!d"djdd|
ddjddgd#d|j||
d$d%jdd&d|jd'|
d$d(jdd)d|jd'|
d$d(jd*ddj|
d+d,jd-ddd.jd/ddd.|	j_|	j_|	j_jd0dd1d2ddj||
d$|d3jdd4jd5|
d$|d6jdd7d8jd9|
d$|d:ggjgjd;d+d<g}	fd=d>} |d? j!j||
|d@d< g_" |g_" g_"|j#dAdBgdC}	fdDdE
 	
fdFdG} |d?  |d? fdHdI}|$| fdJdK} |d? 	fdLdM} |d? 	fdNdO}	%| 	fdPdQ} |d? 	fdRdS 	fdTdU} |d? 	f
dVdW} |d? j&dXdY}	'| |	_(	S )ZaC  Display the SAM Map GUI.

    Args:
        sam (SamGeo):
        basemap (str, optional): The basemap to use. Defaults to "SATELLITE".
        repeat_mode (bool, optional): Whether to use the repeat mode for the draw control. Defaults to True.
        out_dir (str, optional): The output directory. Defaults to None.

    r   NFileChooserKThe sam_map function requires the leafmap package. Please install it first.repeat_modecursor	crosshairFr  rs   
layer_name
Foreground)Zlayersr<   
Background280px90px0px 0px 0px 4pxdescription_widthinitialTToolbargear28pxrY   rZ   paddingr  tooltipiconlayoutClose the tooltimesprimaryrZ   rY   r  r  r  r  button_styler  zLoad foreground pointsplus-circlezLoad background pointsminus-circlezClass Type:rY   r  )r   descriptiondisabledstyler  zForeground #:Z135px)r  r  r  r  r  zBackground #:Segmentr  r  r  r  r  Saver  r  r  ResetzMask opacity:r\   r  r  r   r   r  readoutcontinuous_updater  r  
Regularize130pxr  r  r  r  Color#ffff00140pxZconciser  r  r  r  0px 4px 0px 4pxr  c                    s,   | d r(  d}|d k	r(|jjd d S )Nr   Masksopacity)
find_layerinteractr  changeZ
mask_layermopacity_sliderr   r   opacity_changedv  s    
z$sam_map_gui.<locals>.opacity_changedr  rY   r  	max_width
mouseenter
mouseleaverO   Zwatched_eventsc                    s   | j d k	r`zt| j }|j}dd |D }|D ]}jrt rlj|d |d fdddd}n&j|d |d gjddd	d
d}j	
| j| tj_q<jr<t rj|d |d fdddd}n&j|d |d gjddd	d
d}j
| j| tj _q<W n, tk
r^ } zt| W 5 d }~X Y nX jjkrj td d_d_W 5 Q R X d S )Nc                 S   s   g | ]}|j |jgqS r   r  r  r   r   r   r    s     z8sam_map_gui.<locals>.marker_callback.<locals>.<listcomp>r\   r   r   r  locationradiusr  Z
fill_colorr  darkredr<   Zmarker_colorZ
icon_colorr(  r  r  r   marker_controlF)selectedr   r  r#  r  r   CircleMarkerMarkerAwesomeIconfg_layeradd
fg_markersr   r   bg_layer
bg_markersr   r(   r-  controlsremove_controldelattr)chooserr  r$  r&  r8  r  r   )bg_countfg_count
ipyleafletr  minus_buttonr/   plus_buttonr   r   marker_callback  sh    
z$sam_map_gui.<locals>.marker_callbackc                    s   | d rjt jd} t  |jddd}d|_ddd	g|_| j|d
d}	| |_
n,tdrj
jkrj
 j
  d S )Nr   SANDBOX_PATH454pxrY   )r   sandbox_pathr  Tz*.shpz	*.geojsonz*.gpkgtoprightZwidgetpositionr-  )r   rD   rE   r  Layoutuse_dir_iconsfilter_patternregister_callbackWidgetControladd_controlr-  hasattrr7  r8  r   )r  rD  filechooserr-  )r  r=  r  r@  r  r   r   marker_button_click  s&    

 
z(sam_map_gui.<locals>.marker_button_clickc                    sB   | d dkrg_ n&| d dkr>js>g_ d_d _d S Ntyper$  r%  Fchildrenr  eventclose_buttontoolbar_buttontoolbar_footertoolbar_headertoolbar_widgetr   r   handle_toolbar_event  s    z)sam_map_gui.<locals>.handle_toolbar_eventc                    s,   | d rd _ g_n j s(g_d S Nr   Fr  rT  r  rW  r   r   toolbar_btn_click  s
    z&sam_map_gui.<locals>.toolbar_btn_clickc                    s2   | d r.d_  j jkr&  j   d S r^  r  toolbar_controlr7  r8  r   r`  r  rY  r\  r   r   close_btn_click  s
    z$sam_map_gui.<locals>.close_btn_clickc               
      s"  z|  ddkr|  d}jdkrt rBjt|dddd}nj|jddd	d
d}| j	| t
j_ndjdkrt rjt|dddd}nj|jddd	d
d}| j	| t
j _W n6 ttfk
r } ztd|  W 5 d }~X Y nX d S )NrR  Zclickcoordinatesr  r   r  r'  r  r*  r+  r,  r  r  r   z Error handling map interaction: )rE   r  r   r/  r   r0  r1  r3  r4  r   r   r6  r   KeyErrorr(   )rH   Zlatlonr  r   )r;  r5  r<  r2  r=  r  radio_buttonsr   r   handle_map_interaction  sV    




z+sam_map_gui.<locals>.handle_map_interactionc           
         s  | d rd_    tjdkrJtd d_ W 5 Q R  d S z~dd jD }dd jD }|| }dgt| dgt|  }d	t  d
}tj	|}j
||d|d dd k	rވd dd k	 rd tdr8tjjr8ztj W n   Y nX znj|ddj ddd j r|d
d}|d
d}t|| t|| d j i}j|d|d dd W n   Y nX   d_ |_W n2 tk
r }	 zd_ t|	 W 5 d }	~	X Y nX W 5 Q R X d S )Nr   Fr   z#Please add some foreground markers.c                 S   s    g | ]}|j d  |j d gqS r\   r   r(  r  r  r   r   r   r  A  s   z=sam_map_gui.<locals>.segment_button_click.<locals>.<listcomp>c                 S   s    g | ]}|j d  |j d gqS rj  rk  rl  r   r   r   r  E  s   r\   Zmasks_rM   rR   )point_coordspoint_labelsZ	point_crsr/   r  Regularizedprediction_fpZBlues)rH  r  r  r  zoom_to_layerr  
_rect.gpkgr  r  r  Z	info_moderq  )r  clear_outputr   r4  r(   r6  random_stringr   r   r   predictr  remove_layerrN  r   rp  r  
add_rasterr    r  
regularize
add_vectorr   )
r  	fg_points	bg_pointsrm  rn  r   vector
vector_recvector_styler   )colorpickerr  r   r7   r/   rectangularsamsegment_buttonr   r   segment_button_click5  s    
	




z)sam_map_gui.<locals>.segment_button_clickc                    s
   | j d k	rz| j }j| |dd}t|| jrX|dd}t|| dd  jD }dd  jD }t	||dd t	||dd W n* t
k
r } zt| W 5 d }~X Y nX t d	r j jkr  j t d	 d
_W 5 Q R X d S )NrM   r  rr  c                 S   s    g | ]}|j d  |j d gqS rj  rk  rl  r   r   r   r    s   z=sam_map_gui.<locals>.filechooser_callback.<locals>.<listcomp>c                 S   s    g | ]}|j d  |j d gqS rj  rk  rl  r   r   r   r    s   z_fg_markers.geojsonz_bg_markers.geojsonsave_controlF)r.  rf   rp  r    r  r  ry  r4  r6  coords_to_geojsonr   r(   rN  r  r7  r8  r9  )r:  r   r}  r~  r{  r|  r   r  r/   r  r  save_buttonr  r   r   filechooser_callback  s<    


 
 

z)sam_map_gui.<locals>.filechooser_callbackc              	      s   | d rxd t jd} t  d|jddd}d|_dg|_| j|d	d
}	| |_
W 5 Q R X n,tdrj
jkrj
 td d S )Nr   rA  z	masks.tifrB  rC  r   r   rD  r  T*.tifrE  rF  r  )r   rD   rE   r  rH  rI  rJ  rK  rL  rM  r  rN  r7  r8  r9  r  rD  rO  r  r  r  r=  r  r/   r  r   r   save_button_click  s*    

 
z&sam_map_gui.<locals>.save_button_clickc                    s   | d rd	_ d_ d_ d_ d_   zd dd k	r^d   tdrd _g _g _j	
  j
  d_ d _ ztj W n   Y nX W n   Y nX d S )	Nr   Fr  r  r  ro  r4  r   )r  rt  rw  r  clear_drawingsrN  Z	user_roisr4  r6  r2  Zclear_layersr5  r   r  rp  r`  )
r;  r  r<  r  r   r/   r  reset_buttonr  r  r   r   reset_button_click  s4    



z'sam_map_gui.<locals>.reset_button_clickrE  rF  ))r  r   leafmapr=  	ipyevents
ipywidgetsipyfilechooserr  r'   r   Mapdefault_styleadd_basemaprx  rO   r4  r6  Z
LayerGroupr3  r2  r5  ToggleButtonrH  ZRadioButtonsZIntTextr  rY   FloatSliderCheckboxColorPickerVBoxHBoxobserveOutputrT  Eventon_dom_eventZon_interactionrL  rM  rc  )r  basemapr  r7   rH   r   r  r  widget_widthbutton_widthr  r  Zbuttonsr!  toolbar_eventrP  r]  ra  re  ri  r  r  r  rc  r   )r  r;  r5  rX  r  r<  r2  r  r=  r  r@  r>  r   r7   r/   r?  rh  r  r  r  r  r  r  rY  rZ  r[  r\  r  r   sam_map_gui  sj   





    
  
 ;	
0
N$ 
r     c                    s4   ddl ddl}|j d fddt| D S )zGenerates a random string of fixed length.

    Args:
        string_length (int, optional): Fixed length. Defaults to 3.

    Returns:
        str: A random string
    r   Nr   c                 3   s   | ]}  V  qd S r   )choicer=  lettersr  r   r   	<genexpr>  s     z random_string.<locals>.<genexpr>)r  stringascii_lowercaser   rh   )Zstring_lengthr  r   r  r   ru    s    	ru  c              	   C   s   ddl }t| dkrdS dg d}| D ]$}dd|di d}|d	 | q&||}|dk	rt|d
}|| W 5 Q R X n|S dS )a  Convert a list of coordinates (lon, lat) to a GeoJSON string or file.

    Args:
        coords (list): A list of coordinates (lon, lat).
        output (str, optional): The output file path. Defaults to None.

    Returns:
        dict: A GeoJSON dictionary.
    r   NZFeatureCollection)rR  r   ZFeatureZPoint)rR  rf  )rR  r"  r  r   r[   )r  r   r   r!  rc   rJ  )r&  r/   r  Zfeature_collectionr8  featureZgeojson_strfr   r   r   r    s    

r  r   r   r   r   r   r   r   c                    s   t tr(drttnt tjr6ntdg g  fdd}t	d t
d| td td t  fS )a  Show a canvas to collect foreground and background points.

    Args:
        image (str | np.ndarray): The input image.
        fg_color (tuple, optional): The color for the foreground points. Defaults to (0, 255, 0).
        bg_color (tuple, optional): The color for the background points. Defaults to (0, 0, 255).
        radius (int, optional): The radius of the points. Defaults to 5.

    Returns:
        tuple: A tuple of two lists of foreground and background points.
    r#   z+Input image must be a URL or a NumPy array.c                    sz   | t jkr<||f t ||fd t d n:| t jkrv||f t ||f d t d d S )Nr   rs   )rc  ZEVENT_LBUTTONDOWNr   circler  ZEVENT_RBUTTONDOWN)rV  r   r   bg_colorfg_colorrk   Zleft_clicksr)  Zright_clicksr   r   get_mouse_coordinates:	  s    

z*show_canvas.<locals>.get_mouse_coordinatesrs   r   )r
   r   r   r8   rc  rt  r-  r.  rC   ZnamedWindowZsetMouseCallbackr  ZwaitKeyZdestroyAllWindows)rk   r  r  r)  r  r   r  r   show_canvas	  s     



r  c                 C   s   ddl }t| tr| g}|D ]v} | dr4d|  } d|  }|j| |jd}|j }|dkrr|	 dk	rrq|rRt
|d  qR|  qdS )	zInstall a Python package.

    Args:
        package (str | list): The package name or a GitHub URL or a list of package names or GitHub URLs.
    r   Nzhttps://github.comzgit+zpip install )stdout    zutf-8)
subprocessr
   r   r   Popenr  PIPEr  readlinepollr(   decodestripwait)packager  packagescommandprocessr/   r   r   r   install_packagea	  s    




r        ?viridisc                    s  zLddl ddl}ddl}	ddlddl}
ddlddlm} ddlm	  W n t
k
rh   t
dY nX 	dkrz| 	|	jf |ddi_j|dd zjjd	d
 W n   Y nX d}d}d}ddi}jdddjdddddjddddjdddddjd|j||ddjddd |d!ddj||d|d"	jd#dd d!|ddj||d|d$	jd%| ||j||dd&jd'dd |ddj||d|d(fd)d*}|d+ jdd,jd-|d|d.jdd/d0jd1|d|d2jd3ddj|d4d5jd6ddd7jd8ddd7|j_|j_|j_jj|||d9d:
 g_ gjgjdd4d:
g_ g_|
j d;d<gd=}fd>d?}|!| fd@dA}|d+ fdBdC}|d+ 	
fdDdE}|d+ 
fdFdG 
fdHdI}|d+ 
f
dJdK}|d+ j"dLdM}#| |_$S )NzDisplay the SAM Map GUI.

    Args:
        sam (SamGeo):
        basemap (str, optional): The basemap to use. Defaults to "SATELLITE".
        out_dir (str, optional): The output directory. Defaults to None.

    r   Nr  r  r  r  Fr  rs   r  r  r  r  r  r  Tr  r  r  r  r  r  r  r  r  r  r  zText prompt:r  )r  r  r  zBox threshold:r\   g{Gz?)	r  r   r   r  stepr  r  r  r  zText threshold:)	r  r   r   r  r  r  r  r  r  zPalette:)r  r   r  r  r  zOpacity:r  c                    s8   | d r4t  dr4  j}|d k	r4|jjd d S )Nr   r  r  )rN  r  r  r  r  r  r  r   r   r!  	  s
    
z%text_sam_gui.<locals>.opacity_changedr  r  r  r  r  r  r  r  r  r  r  r  r	  r
  r"  r  r$  r%  r&  c                    sB   | d dkrg_ n&| d dkr>js>g_ d_d _d S rQ  rS  rU  rW  r   r   r]  9
  s    z*text_sam_gui.<locals>.handle_toolbar_eventc                    s,   | d rd _ g_n j s(g_d S r^  r_  r`  rW  r   r   ra  D
  s
    z'text_sam_gui.<locals>.toolbar_btn_clickc                    s2   | d r.d_  j jkr&  j   d S r^  rb  r`  rd  r   r   re  N
  s
    z%text_sam_gui.<locals>.close_btn_clickc                    s  | d rd	_    t
j dkr:td njd krPtd ntd 
j dd}tj| dt	  d	}znj
j
j  j j |d
 |_|d k	rĈ| | dd k	r| d W n4 tk
r$ } z  t| W 5 d }~X Y nX tj|rzj||j j ddd |_j r|d	d}|d	d}t|| t|| dj i}j|| d|d dd   W n, tk
r } zt| W 5 d }~X Y nX W 5 Q R X d S )Nr   Fr   z!Please enter a text prompt first.z!Please run sam.set_image() first.zSegmenting... r}  rM   )r/   Z_rectz Regularized)r  paletter  rH  rq  r  rr  r  rs  )r  rt  r   r(   rO   r    r   r   r   ru  rv  r/   r  rw  r   r   rx  r  r  ry  rz  )r  r  r   r   r}  r~  r  )
box_slidercmap_dropdownr  r  r   r7   r/   r  r  r  text_prompttext_sliderr   r   r  W
  sr    

 


z*text_sam_gui.<locals>.segment_button_clickc                    s    | j d k	rzJ| j }j| |dd}t|| jrX|dd}t|| W n* tk
r } zt| W 5 d }~X Y nX t	 dr j
 jkr  j
 t d d_W 5 Q R X d S )NrM   r  rr  r  F)r.  rf   r/   r    r  r  ry  r   r(   rN  r  r7  r8  r9  )r:  r   r}  r~  r   r  r   r   r  
  s     


z*text_sam_gui.<locals>.filechooser_callbackc              	      s   | d r    tds*td nftjd} t j d|jddd}d	|_	d
g|_
| j|dd}| |_W 5 Q R X n,tdrȈjjkrȈj td d S )Nr   r  z&Please click the Segment button first.rA  rM   rB  rC  r  Tr  rE  rF  r  )rt  rN  r(   r   rD   rE   r  r  rH  rI  rJ  rK  rL  rM  r  r7  r8  r9  r  r  r   r   r  
  s0    




 
z'text_sam_gui.<locals>.save_button_clickc                    s   | d rd_ d_ d_ d_ d _ d	_ d_ d_   z8tdrnjd k	rnj   W n   Y nX d S )Nr   Fr  r  r  r   r  )r  rt  rN  r  r  rw  r  r`  )
r  r  r  r   r/   r  r  r  r  r  r   r   r  
  s     z(text_sam_gui.<locals>.reset_button_clickrE  rF  )%r  r   r  r=  r  r  Zleafmap.colormapsZ	colormapsr  r  r'   r   r  r  r  rx  rO   r  rH  Textr  ZDropdownZlist_colormapsr  r  r  r  rY   r  r  rT  r  r  r  rL  rM  rc  )r  r  r7   Zbox_thresholdZtext_thresholdr  r  rH   r   r  r  cmr  r  r  r  r!  r  r]  ra  re  r  r  r  rc  r   )r  r  rX  r  r  r  r=  r  r   r7   r/   r  r  r  r  r  r  r  r  rY  rZ  r[  r\  r  r   text_sam_gui	  sJ   


      


 	
"= 
r  c                 K   s   t | trt| }nt | tjr(| }ntd|jdd }tj||jdddd}|dk	rn|j	|d	d
 |dk	r|j
|f| n|S dS )a  Regularize a polygon GeoDataFrame.

    Args:
        source (str | gpd.GeoDataFrame): The input file path or a GeoDataFrame.
        output (str, optional): The output file path. Defaults to None.


    Returns:
        gpd.GeoDataFrame: The output GeoDataFrame.
    z7The input source must be a GeoDataFrame or a file path.c                 S   s   | j S r   )Zminimum_rotated_rectangle)Zgeomr   r   r   <lambda>
  r  zregularize.<locals>.<lambda>r"  r\   r  )r"  dataNT)r  )r
   r   r   r  r  rC   r"  applyZdropr9  r  )rO   r/   rW   rH   r  r:  r   r   r   r   ry  
  s    
ry  r   c                 C   s  zddl m} W n tk
r,   tdY nX t| tr^| dr^| dd }t| | |} || }t	j
|s~t	| t|tr|}|}nt|tr|d }|d }|j}	|j}
|	| ||  t|	| ||  dk }|
| ||  t|
| ||  dk }| }t|D ]l}t|D ]Z}|||  }|||  }t|| |	}t|| |
}||d kr|t|| d}||d krt|| d}|| }|| }| d| d	| d
}|d}|||||j|dj}|d ||d   |d d|d ||d   d|d f}|| ||  t|jD ]<}||d }||d }|||||}|| q>d}q&qd}dS )a  Split a raster into tiles.

    Args:
        filename (str): The path or http URL to the raster file.
        out_dir (str): The path to the output directory.
        tile_size (int | tuple, optional): The size of the tiles. Can be an integer or a tuple of (width, height). Defaults to 256.
        overlap (int, optional): The number of pixels to overlap between tiles. Defaults to 0.

    Raises:
        ImportError: Raised if GDAL is not installed.
    r   rt   ZGDAL is required to use this function. Install it with `conda install gdal -c conda-forge`r#   r   r   r\   z/tile_r}  rM   r   r   r   N)r   rt   r'   r
   r   r   r  r8   ZOpenr   r   r   r   rx   r   ZRasterXSizeZRasterYSizeZGetGeoTransformrh   r   r   r   r   ZRasterCountr   ZDataTyper   r   ZGetProjectionZReadAsArrayr   )r   r7   Z	tile_sizeoverlaprt   r/   ZdsZ
tile_widthZtile_heightrY   rZ   Znum_tiles_xZnum_tiles_yZgeotransformro   jZx_minZy_minZx_maxZy_maxZoutput_filer   Ztile_dsZtile_geotransformr   rj   Z	tile_bandZ	tile_datar   r   r   split_raster  s    












r  r  r   r   c           	      C   sb   ddl }zddlm} W n tk
r4   tdY nX | tj| |}|j|||||d dS )a^  Merge a directory of rasters into a single raster.

    Args:
        input_dir (str): The path to the input directory.
        output (str): The path to the output raster.
        input_pattern (str, optional): The pattern to match the input files. Defaults to "*.tif".
        output_format (str, optional): The output format. Defaults to "GTiff".
        output_nodata (float, optional): The output nodata value. Defaults to None.
        output_options (list, optional): A list of output options. Defaults to ["COMPRESS=DEFLATE"].

    Raises:
        ImportError: Raised if GDAL is not installed.
    r   Nr  r  )r   Z	dstNodatar   )globr   rt   r'   r   r   r   ZWarp)	Z	input_dirr/   Zinput_patternZoutput_formatZoutput_nodataZoutput_optionsr  rt   Zinput_filesr   r   r   merge_rasterss  s    
r  )T)NNFNNTTNFFTFF)r9   NF)NNF)NrJ   )rR   rS   T)NNrp   rq   FFFF)r\   )N)r  r  )r  )rR   N)NNNNr<  NrR   )r  )r  )r   )r   )N)rn  Nr^  )N)NN)N)N)N)T)T)NNrJ   )F)r  r  r  NN)r  FTr  r  )NF)rv   TN)r  )N)r  r  r   )rv   Nr  r  r  r  )NrR   )r   r   )M__doc__r   r   rc  r   r-  r   r|  r  ra   Z	geopandasr   Zmatplotlib.pyplotZpyplotr  rD   r   r   r   r"   r8   rG   rI   rQ   rU   r   r   r   r  r  r  r  r  r   r   r%  r5  r;  r@  rB  rC  rD  rF  rK  rM  rP  rX  r[  r\  rm  rw  rx  r  r   r  r  r  r  r  r   r  r  r  r  r  r  r  r  r  ru  r  r  r  r  ry  r  r  r   r   r   r   <module>   sd  


             
W
?

(     
<        
  !

     $   %
#       
9   \   	



?



#



/
     
Z    

     
2
I     
H
-
    

%
B!      
  f

u