
    C.i                     z    d Z dZddlZddlZddlZddlmZ d Z	d Z
d Z G d d	e          Z G d
 d          ZdS )z A Parallelised Implementation of K-D Trees

Code extended from http://folk.uio.no/sturlamo/python/multiprocessing-tutorial.pdf
zAjay Thampi    N)cKDTreec                 N    t          j        |                                           S )z_
    Function that converts a shared memory array (multiprocessing.Array) to a numpy array
    )np
frombufferget_obj)shmem_arrays    c/home/louicyp/clawd-clean/.venv-aircash/lib/python3.11/site-packages/reverse_geocoder/cKDTree_MP.pyshmem_as_nparrayr
      s      =,,..///    c                 |   	 t          |                              ||f          }t          |                              ||f          }t          |                              ||	f          }t          |                              ||	f          }t          ||          }| D ]~}|                    ||ddf         |	|
||          \  }}|j        d         }|j        d         }|                    |d          |                    |d          c||ddf<   ||ddf<   dS #  |xj        dz  c_        Y dS xY w)zi
    Function that parallelly queries the K-D tree based on chunks of data returned by the scheduler
    leafsizeN)kepspdistance_upper_boundr      )r
   reshaper   queryshapevalue)	schedulerdatandatandimr   xnxdir   r   r   dubierr_data_x_d_ikdtreesd_outi_outm_dm_is                           r	   _pqueryr,      sT   
 &&..t}==a  (("d44a  (("a11a  (("a11222 	N 	NA!<<1aaa4A3!Z]<^^LE5+a.C+a.C!&sA!6!6c18M8MBq!!!tHbAAAhh		N 	N


a




s   D"D& &D;c                  L    	 t          j                    S # t          $ r Y dS w xY w)z
    Function to get the number of CPUs / cores. This is used to determine the number of processes to spawn.
    Default (if not implemented) = 2
       )mp	cpu_countNotImplementedError r   r	   num_cpusr3   &   s5    
|~~   qqs    
##c                   >     e Zd ZdZd fd	Zdddej        fdZ xZS )	
cKDTree_MPz) 
    The parallelised cKDTree class
       c                 \   t          j        |          }|j        \  }}t          j        t
          j        ||z            | _        t          | j                  	                    ||f          }||ddddf<   || _
        t          t          |                               ||           dS )zX Class Instantiation
        Arguments are based on scipy.spatial.cKDTree class
        Nr   )r   arrayr   r/   Arrayctypesc_double
shmem_datar
   r   	_leafsizesuperr5   __init__)self	data_listr   r   nmr"   	__class__s          r	   r?   zcKDTree_MP.__init__4   s     x	""z1(6?AaC88 11991a&AAaaad!j$(((BBBBBr   r   r   r.   c                 *   t          j        |          }|j        \  }}t          j        t
          j        ||z            }	t          j        t
          j        ||z            }
t          j        t
          j        ||z            }t          |	                              ||f          }t          |
                              ||f          }t          |          }|dk    r|                    ||f          }||ddddf<   t                      }t          ||          }t          j        t
          j        d          }|| j        | j        | j        | j        |	||
||||||ffdt#          |          D             }|D ]}|                                 |D ]}|                                 |j        dk    rt+          d|j        z            |                                |                    t0                                                    fS )z;
        Function to parallelly query the K-D Tree
        r   Nr   c                 F    g | ]}t          j        t                     S ))targetargs)r/   Processr,   ).0_
query_argss     r	   
<listcomp>z%cKDTree_MP.pquery.<locals>.<listcomp>`   s(    SSS
'
;;;SSSr   z%d errors in worker processes)r   r8   r   r/   r9   r:   r;   r
   r   r3   	SchedulerValuec_intr<   rB   rC   r   rangestartjoinr   RuntimeErrorcopyastypeint)r@   x_listr   r   r   r   r   r   mxshmem_xshmem_dshmem_ir#   r$   r%   nprocsr   r!   poolrL   s                      @r	   pqueryzcKDTree_MP.pqueryB   s   
 HVB(6?BrE22(6?BqD11(6?BqD11g&&..Bx88g&&..Aw77g&&66RG$$B111aaa4b&))	xa((otvtvt}r7Ga!5	

 TSSSU6]]SSS  AqwwyyyyAqvvxxxx:??>$*MNNNwwyy"))C..--////r   )r6   )	__name__
__module____qualname____doc__r?   r   infr_   __classcell__)rD   s   @r	   r5   r5   0   so         C C C C C C  !a1$&F$0 $0 $0 $0 $0 $0 $0 $0r   r5   c                   *    e Zd ZdZd Zd Zd Zd ZdS )rN   z
    Scheduler that returns chunks of data to be queries on the K-D Tree.
    The number of chunks is determined by the number of processes.
    c                     t          j        t          j        |          | _        t          j        t          j        d          | _        t          j                    | _        ||z  }|dk    r|n|}|| _        d S )Nr   r.   )	r/   RawValuer:   rP   _ndata_startLock_lock_chunk)r@   r   r]   	min_chunks       r	   r?   zScheduler.__init__m   s^    k&,66k&,22WYY
VO	&!^^EE	r   c                     | S )Nr2   )r@   s    r	   __iter__zScheduler.__iter__u   s    r   c                    | j                                          | j        j        }| j        j        }| j        }|rh||k    r|}||z   }d| j        _        n%|}||z   }||z
  | j        _        ||z   | j        _        | j                                          t          ||          S | j                                          t          Nr   	rl   acquireri   r   rj   rm   releasesliceStopIterationr@   r   rR   chunk_s0_s1s         r	   nextzScheduler.nextx       
!! 	 u}}em$%!!em$)EM!$)EM!J   c??"J   r   c                    | j                                          | j        j        }| j        j        }| j        }|rh||k    r|}||z   }d| j        _        n%|}||z   }||z
  | j        _        ||z   | j        _        | j                                          t          ||          S | j                                          t          rr   rs   rx   s         r	   __next__zScheduler.__next__   r}   r   N)r`   ra   rb   rc   r?   rp   r|   r   r2   r   r	   rN   rN   h   sZ                     *         r   rN   )rc   
__author__numpyr   multiprocessingr/   r:   scipy.spatialr   r
   r,   r3   r5   rN   r2   r   r	   <module>r      s     
          ! ! ! ! ! !0 0 0  *  60 60 60 60 60 60 60 60p8  8  8  8  8  8  8  8  8  8 r   