
    Ngd                    :   d dl mZ d dlmZmZmZmZmZmZm	Z	 d dl
Zd dlmZmZ d dlmZ d dlmZ d dlmZ d dlmZmZ d d	lmZ d d
lmZ d dlmZmZmZm Z  d dl!m"Z" d dl#m$Z$m%Z% d dl&m'Z' d dl(m)Z) erd dlm*Z* d dl+m,Z, dZ-dZ.	 	 dbdcdZ/ e)d          	 	 ddded             Z0d! Z1e.fdfd$Z2e.fdgd'Z3d(e.fdhd+Z4d(e.fdhd,Z5 e)d          did2            Z6djd4Z7 e)d          	 dkdld7            Z8dmd;Z9dnd@Z:dodHZ;dpdKZ<dqdNZ=drdSZ>dsdWZ?dtdZZ@dud]ZAdvd_ZBdwdaZCdS )x    )annotations)TYPE_CHECKINGAnyBinaryIOListOptionalUnioncastN)LTChar	LTTextBox)	PDFObjRef)open_filename)	Rectangle)
PixelSpace
PointSpace)CoordinatesMetadata)remove_control_characters)extract_image_objectsextract_text_objectsopen_pdfminer_pages_generatorrect_to_bbox)
env_config)SORT_MODE_BASICSource)sort_text_regions)requires_dependencies)
TextRegion)DocumentLayoutg{Gz?       filenamestrdpiintreturn+tuple[List[List['TextRegion']], List[List]]c                    t          | d          5 }t          t          |          }t          ||          \  }}||fcd d d            S # 1 swxY w Y   d S )Nrb)filer$   )r   r
   r   process_data_with_pdfminer)r"   r$   fpextracted_layoutlayouts_linkss        p/var/www/html/ai-engine/env/lib/python3.11/site-packages/unstructured/partition/pdf_image/pdfminer_processing.pyprocess_file_with_pdfminerr0   #   s     
x	&	& /"(B*D+
 +
 +
'-  ./ / / / / / / / / / / / / / / / / /s   -AAAunstructured_inferencer*    Optional[Union[bytes, BinaryIO]]c           
       % ddl m}m} g }g }|dz  %t          t	          |                     D ]\  }\  }}|j        |j        }
}	g }g }g }t          |	|
          }|j        rt          |j        |
||          }t          j        }g }|D ]}t          |j        |
          \  }}}}||||f}t          |          dk    rbt          |t                     rMt#          ||||          }t%          ||
          \  }}|D ]%}|                    t)          ||                     &t+          |d          rt-          |          }|D ]s}|                                }t1          g t          |j        |
          %|t2          j        |R  }|j        %|j        j        dk    r|                    |           t/t9          |          }|D ]_} t1          g t          | j        |
          %dt2          j        |R  }|j        %|j        j        dk    r|                    |           `%fd|D             }!t;          |t          j                  }"t;          |t          j                  }#g |"|#}$tA          |$tB                    }$tA          |$          }$|                    |$           |                    |!           ||fS )zzLoads the image and word objects from a pdf using pdfplumber and the image renderings of the
    pdf pages using pdf2imager   )EmbeddedTextRegionImageTextRegionH   )widthheightget_textNc                f    g | ]-}fd |d         D             |d         |d         |d         d.S )c                    g | ]}|z  S  r<   ).0xcoefs     r/   
<listcomp>z9process_data_with_pdfminer.<locals>.<listcomp>.<listcomp>{   s    <<<aT<<<    bboxtexturistart_index)rB   rC   urlrE   r<   )r=   metadatar?   s     r/   r@   z.process_data_with_pdfminer.<locals>.<listcomp>y   se     
 
 
  =<<<8F+;<<< ('6	 
 
 
rA   )")unstructured_inference.inference.elementsr4   r5   	enumerater   r7   r8   r   annotsget_urisr   PDF_ANNOTATION_THRESHOLDr   rB   len
isinstancer    check_annotations_within_elementget_words_from_objappendmap_bbox_and_indexhasattrr   r9   _create_text_regionr   PDFMINERarear   remove_duplicate_elements#EMBEDDED_TEXT_SAME_REGION_THRESHOLD$EMBEDDED_IMAGE_SAME_REGION_THRESHOLDr   r   )&r*   r$   r4   r5   layoutsr.   page_numberpagepage_layoutr7   r8   text_layoutimage_layoutannotation_listcoordinate_systemannotation_thresholdurls_metadataobjx1y1x2y2rB   annotations_within_element_wordsannotinner_text_objects	inner_obj_texttext_regioninner_image_objectsimg_objlinksclean_text_layoutclean_image_layoutlayoutr?   s&                                        @r/   r+   r+   0   s          
 GM8D,56STX6Y6Y,Z,Z Q$ Q$((dK#);+=v&
 
 
 ; 	\&t{F<M{[[O)B.0 '	9 '	9C)#(F;;NBBB#D?##a''JsI,F,F'-M#(	. .* .c6::57 K KE!(();E5)I)IJJJJsJ'' 9%9#%>%>"!3 
8 
8I%..00E"5 #%inf==## # 	#
 +# # #K #'38H8MPQ8Q8Q#**;777
8 '<C&@&@#2 	9 	9G"5 #%glF;;## # 	#
 (# # #K #'38H8MPQ8Q8Q$++K888	9
 
 
 
 *
 
 
 6G
 
 7*I
 
 ;$:'9: #6?;; #6**vU####M!!rA   c                P    |                     | |z  ||z  ||z  ||z  ||          S )zECreates a text region of the specified class with scaled coordinates.)rC   source)from_coords)re   rf   rg   rh   r?   rC   rx   region_classs           r/   rT   rT      sA    ##
T	
T	
T	
T	 $   rA   round_to
np.ndarrayc                    t          j        t          |           dft           j                  }t	          |           D ]&\  }}|j        |j        |j        |j        g||ddf<   '|	                    |          S )z.convert a list of boxes's coords into np array   )dtypeN)
npzerosrM   float32rI   re   rf   rg   rh   round)bboxesr{   coordsirB   s        r/   get_coords_from_bboxesr      sv     Xs6{{A&bj999FV$$ < <4$'47;q!!!t<<!!!rA   coords1coords2c           
        t          j        | dd          \  }}}}t          j        |dd          \  }}}	}
t          j        t          j        |t          j        |	                    t          j        |t          j        |                    z
  dz   d          t          j        t          j        |t          j        |
                    t          j        |t          j        |                    z
  dz   d          z  }||z
  dz   ||z
  dz   z  }|	|z
  dz   |
|z
  dz   z  }|                    |          |                    |          |                    |          fS )zHcompute intersection area and own areas for two groups of bounding boxesr~      axisr   )r   splitmaximumminimum	transposer   )r   r   r{   x11y11x12y12x21y21x22y22
inter_area	boxa_area	boxb_areas                 r/   $areas_of_boxes_and_intersection_arear      sH    '11555Cc3'11555Cc3	Cc**	+	+bjbl3>O>O.P.P	PST	TWX 

BJsBL$5$566CVYIZIZ9[9[[^__bcddeJ sQ39q=1IsQ39q=1IH%%yx'@'@)//RZB[B[[[rA         ?	thresholdfloatc                    t          | |          }t          ||          }t          |||          \  }}}|t          j        |t                    z  |k    ||j        k    z  S )zacompute if each element from bboxes1 is almost a subregion of one or more elements in
    bboxes2r{   r   r   r   r   EPSILON_AREAT)	bboxes1bboxes2r   r{   r   r   r   r   r   s	            r/   &bboxes1_is_almost_subregion_of_bboxes2r      sy    
 %Wx@@@G$Wx@@@G'K8( ( ($J	9 I|<<<yHY[  rA   c                    t          | |          }t          |||          \  }}}|t          j        t          ||j        z   |z
            z  |k    S )z#compute iou for a group of elementsr   r   )r   r   r{   r   r   r   r   s          r/   boxes_self_iour      sa    #FX>>>F'K( ( ($J	9 L)ik2IJ2VWWW[dddrA   inferred_document_layout'DocumentLayout'r-   List[List['TextRegion']]hi_res_model_namec                   ddl m} ddlm} | j        }t          t          ||                    D ]\  }\  }}|j        }	|j        }
|
	                    d          }|
	                    d          }||f}i }t          |j        |          rd|j        j        vrddd} |d|	||d	|}t          t          t          d
         |          t                     }g }|D ]Y}|j         t%          t          d
|          |          }n|j        }t'          |          |_        |                    |           Z||j        dd<   | S )z1Merge an inferred layout with an extracted layoutr   )+merge_inferred_layout_with_extracted_layout)UnstructuredDetectronONNXModelr7   r8   R_50r   )same_region_thresholdsubregion_threshold)inferred_layoutr-   page_image_sizer   N)rp   pdf_objectsr<   ).unstructured_inference.inference.layoutelementr   ,unstructured_inference.models.detectron2onnxr   pagesrI   zipelementsimage_metadatagetrN   detection_model
model_pathr   r
   r   r   rC    aggregate_embedded_text_by_blockr   rQ   )r   r-   r   "merge_inferred_with_extracted_pager   inferred_pagesr   inferred_pageextracted_page_layoutr   r   wh
image_sizethreshold_kwargsmerged_layoutr   	layout_elrC   s                      r/   $merge_inferred_with_extracted_layoutr      s         \[[[[[-3N5>N,--6 6 '- '-11M0 (0&5w''x((V
 }46TUU	Zm;FFF9<UXYY:: 
+2&
 
 	
 
 *$tL/A=*Q*QSbcc& 		' 		'I~%7 $\9 = = 5  
 !~6t<<INOOI&&&&$,qqq!!##rA   documentc                   | j         D ]}d |j        D             }g }i d}t          |j                  D ]?\  }}|j        t          j        k    r|                    |j                   ||<   |dz  }@t          ||t          j
                                      d          dk    fdt          |j                  D             |_        | S )zClean pdfminer elements from inside tables.

    This function removes elements sourced from PDFMiner that are subregions within table elements.
    c                F    g | ]}|j         t          j        k    |j        S r<   )rx   r   rU   rB   )r=   es     r/   r@   z1clean_pdfminer_inner_elements.<locals>.<listcomp>  s*    %c%c%cqxSYSbGbGbafGbGbGbrA   r   r   r   c                >    g | ]\  }}|vs|                  |S r<   r<   )r=   r   r   element_to_subregion_map&is_element_subregion_of_other_elementss      r/   r@   z1clean_pdfminer_inner_elements.<locals>.<listcomp>.  sI     
 
 
1222=>VWX>YZ 3  322rA   )r   r   rI   rx   r   rU   rQ   rB   r   r   -EMBEDDED_TEXT_AGGREGATION_SUBREGION_THRESHOLDsum)	r   r\   non_pdfminer_element_boxeselement_boxessubregion_indicer   elementr   r   s	          @@r/   clean_pdfminer_inner_elementsr     s     
 
%c%cdm%c%c%c"#% #DM22 	" 	"JAw~00  ...*:$Q'! 3*H  cqckk 	/
 
 
 
 
!$-00
 
 
 OrA   r   list['TextRegion']c                $   g }t          |           D ]\  }}|                    |j                    t          ||          }g }t          |           D ]<\  }}|||dz   df                                         r'|                    |           =|S )zMRemoves duplicate text elements extracted by PDFMiner from a document layout.r   N)rI   rQ   rB   r   any)r   r   r   r   r   ioufiltered_elementss          r/   rW   rW   :  s     F)) $ $
7gl####

+
+C)) * *
7q!a%''z?   	  ))))rA   rp   'TextRegion'r   c                    t          d |D             | j        gt          j                                      d          d                    fdt          |          D                       }|S )zgExtracts the text aggregated from the elements of the given layout that lie within the given
    block.c                    g | ]	}|j         
S r<   rB   )r=   rd   s     r/   r@   z4aggregate_embedded_text_by_block.<locals>.<listcomp>X  s    )))c)))rA   r   r    c                B    g | ]\  }}|         |j         |j         S r<   )rC   )r=   r   rd   masks      r/   r@   z4aggregate_embedded_text_by_block.<locals>.<listcomp>]  s1    ]]]&!StAw]SVS[]SX]]]rA   )r   rB   r   r   r   joinrI   )rp   r   rC   r   s      @r/   r   r   P  s{     2))[)))		@  
cqckk	 	 88]]]]Ik,B,B]]]^^DKrA   
page_linkslistregionr   c                x     d  D             }t          ||g          } fdt          |          D             }|S )Nc                F    g | ]}t          |                    d            S r   )r   r   )r=   links     r/   r@   z(get_links_in_element.<locals>.<listcomp>c  s)    HHHTItxx//0HHHrA   c                    g | ]e\  }}t          |          |                             d           |                             d          |                             d          dfS )rC   rF   rE   )rC   rF   rE   )r   r   )r=   idxresultr   s      r/   r@   z(get_links_in_element.<locals>.<listcomp>e  s        Cv;;sO''//c?&&u--%c?..}==	
 	
  rA   )r   rI   )r   r   links_bboxesresultsrs   s   `    r/   get_links_in_elementr   a  s`    HHZHHHL4\F8LLG    %W--  E LrA   rJ   PDFObjRef | list[PDFObjRef]r8   ra   PixelSpace | PointSpacer[   list[dict[str, Any]]c                    t          | t                    rt          | |||          S |                                 }|g S t          ||||          S )a  
    Extracts URI annotations from a single or a list of PDF object references on a specific page.
    The type of annots (list or not) depends on the pdf formatting. The function detectes the type
    of annots and then pass on to get_uris_from_annots function as a list.

    Args:
        annots (PDFObjRef | list[PDFObjRef]): A single or a list of PDF object references
            representing annotations on the page.
        height (float): The height of the page in the specified coordinate system.
        coordinate_system (PixelSpace | PointSpace): The coordinate system used to represent
            the annotations' coordinates.
        page_number (int): The page number from which to extract annotations.

    Returns:
        list[dict]: A list of dictionaries, each containing information about a URI annotation,
        including its coordinates, bounding box, type, URI link, and page number.
    )rN   r   get_uris_from_annotsresolve)rJ   r8   ra   r[   resolved_annotss        r/   rK   rK   r  s[    . &$ T#FF4E{SSSnn&&O	9JKXXXrA   list[PDFObjRef]int | floatc           	        g }| D ]}t          |          }t          |t                    s(|                    dd          }|r(t          |t                    st          |          dk    ri|                    dd          }|r(t          |t                    st          |          dk    rt          ||          \  }	}
}}|	|
f|	|f||f||
ff}t          ||          }d|vrt          |d                   }t          |t                    sd}d|v r0t          |d         t                    st          |d                   }d}	 |d	k    r5t          t          |d
                             	                    d          }|dk    r5t          t          |d                             	                    d          }n# t          $ r Y nw xY w|                    ||	|
||f|||d           |S )a  
    Extracts URI annotations from a list of PDF object references.

    Args:
        annots (list[PDFObjRef]): A list of PDF object references representing annotations on
            a page.
        height (int | float): The height of the page in the specified coordinate system.
        coordinate_system (PixelSpace | PointSpace): The coordinate system used to represent
            the annotations' coordinates.
        page_number (int): The page number from which to extract annotations.

    Returns:
        list[dict]: A list of dictionaries, each containing information about a URI annotation,
        including its coordinates, bounding box, type, URI link, and page number.
    SubtypeNz/'Link'Rectr~   )pointssystemASz/'URI'URIzutf-8z/'GoTo'D)coordinatesrB   typerD   r[   )try_resolverN   dictr   r   r#   rM   r   r   decode	ExceptionrQ   )rJ   r8   ra   r[   r`   
annotationannotation_dictsubtyperectre   rf   rg   rh   r   coordinates_metadatauri_dicturi_typerD   s                     r/   r   r     sJ   * O -
 -

%j11/400 	!%%i66 	*Wi88 	CLLI<U<U""6400 	z$	22 	c$ii1nn%dF33BBr(RHr2hR92$ 
  
  

 o%%s344(D)) 	(??:hsmY#G#G?8C=))H	8##!+huo">">??FFwOO9$$!+hsm"<"<==DDWMM 	 	 	D	 	3RR( * 	
 	
 	
 	
 s   A6G
GGrl   r   c                P    	 |                                  S # t          $ r | cY S w xY w)z
    Attempt to resolve a PDF object reference. If successful, returns the resolved object;
    otherwise, returns the original reference.
    )r   r  )rl   s    r/   r  r    s9    
}}   s    %%r`   element_bbox!tuple[float, float, float, float]rb   c                    g }| D ]W}|d         |k    rIt          |d                   }|r2t          ||d                   |z  |k    r|                    |           X|S )a  
    Filter annotations that are within or highly overlap with a specified element on a page.

    Args:
        annotation_list (list[dict[str,Any]]): A list of dictionaries, each containing information
            about an annotation.
        element_bbox (tuple[float, float, float, float]): The bounding box coordinates of the
            specified element in the bbox format (x1, y1, x2, y2).
        page_number (int): The page number to which the annotations and element belong.
        annotation_threshold (float, optional): The threshold value (between 0.0 and 1.0)
            that determines the minimum overlap required for an annotation to be considered
            within the element. Default is 0.9.

    Returns:
        list[dict[str,Any]]: A list of dictionaries containing information about annotations
        that are within or highly overlap with the specified element on the given page, based on
        the specified threshold.
    r[   rB   )calculate_bbox_areacalculate_intersection_arearQ   )r`   r  r[   rb   ri   r  annotation_bbox_sizes          r/   rO   rO     s    0 "$% > >
m$33#6z&7I#J#J # >+L*V:LMMPdd&' ' +11*===%%rA   rd   r   )tuple[list[LTChar], list[dict[str, Any]]]c           	         g }g }d}| D ]}d}d\  }}}	}
d}t          |          D ]P\  }}t          |t                    r|                    |           |                                }|r4|                                s |                    ||||	|
f|d           d}{|s|                                }|rK|                                |k    r3|                                }|                    ||||	|
f|d           d}t          |          dk    r(||z   }|j        }||j	        z
  }
|j
        }	||j        z
  }n|j
        }	||j	        z
  }
||z  }1|                    ||||	|
f|d           d}R|t          |          z  }||fS )a|  
    Extracts characters and word bounding boxes from a PDF text element.

    Args:
        obj (LTTextBox): The PDF text element from which to extract characters and words.
        height (float): The height of the page in the specified coordinate system.

    Returns:
        tuple[list[LTChar], list[dict[str,Any]]]: A tuple containing two lists:
            - list[LTChar]: A list of LTChar objects representing individual characters.
            - list[dict[str,Any]]]: A list of dictionaries, each containing information about
                a word, including its text, bounding box, and start index in the element's text.
    r   r    )NNNN)rC   rB   rE   )rI   rN   r   rQ   r9   stripisalnumrM   x0y0re   rf   )rd   r8   
charactersrk   text_len	text_linewordre   rf   rg   rh   rE   index	charactercharr  s                   r/   rP   rP     s   " JEH +# +#	/BB )) 4 4 &	 &	E9)V,, %!!),,, ))++ 

 LL!%BB/?P[\\   D  -"llnnG DLLNNg55"llnnGLL!%BB/?P[\\   Dt99>>"*U"2K"B),.B"B),.BB"B),.B!BB+;KXX   C	NN"urA   rk   dict[str, Any]c                "   t          |           dk    rd|d<   d|d<   |S t          j        |d         d         t          j        d | D                       z
  dz  |d         d	         t          j        d
 | D                       z
  dz  z             }t          j        |d         d         t          j        d | D                       z
  dz  |d         d         t          j        d | D                       z
  dz  z             }t	          |          }t	          |          }d}||k    r-t          ||d	z             D ]}|dz  }|| |         d         z  }n| |         d         }|                                |d<   | |         d         |d<   |S )aq  
    Maps a bounding box annotation to the corresponding text and start index within a list of words.

    Args:
        words (list[dict[str,Any]]): A list of dictionaries, each containing information about
            a word, including its text, bounding box, and start index.
        annot (dict[str,Any]): The annotation dictionary to be mapped, which will be updated with
        "text" and "start_index" fields.

    Returns:
        dict: The updated annotation dictionary with "text" representing the mapped text and
            "start_index" representing the start index of the mapped text in the list of words.
    r   r    rC   rE   rB   c                *    g | ]}|d          d         S )rB   r   r<   r=   r#  s     r/   r@   z&map_bbox_and_index.<locals>.<listcomp>^       %H%H%H$d6l1o%H%H%HrA      r   c                *    g | ]}|d          d         S )rB   r   r<   r+  s     r/   r@   z&map_bbox_and_index.<locals>.<listcomp>_       'J'J'JDVQ'J'J'JrA   c                *    g | ]}|d          d         S )rB   r-  r<   r+  s     r/   r@   z&map_bbox_and_index.<locals>.<listcomp>b  r,  rA      c                *    g | ]}|d          d         S )rB   r1  r<   r+  s     r/   r@   z&map_bbox_and_index.<locals>.<listcomp>c  r/  rA   r   )rM   r   sqrtarray
try_argminranger  )rk   rl   distance_from_bbox_startdistance_from_bbox_endclosest_startclosest_endrC   rj   s           r/   rR   rR   K  s    5zzQf!m!w	vq	BH%H%H%%H%H%HII	IaO=bh'J'JE'J'J'JKKKPQ
Q	R     W	vq	BH%H%H%%H%H%HII	IaO=bh'J'JE'J'J'JKKKPQ
Q	R  788M344K Dm##}kAo66 	% 	%ACKDE!HV$$DD	% ]#F+JJLLE&M />E-LrA   bbox1bbox2c                    | \  }}}}|\  }}}}	t          ||          }
t          ||          }t          ||          }t          ||	          }|
|k     r||k     rt          |
|||f          }|S dS )a  
    Calculate the area of intersection between two bounding boxes.

    Args:
        bbox1 (tuple[float, float, float, float]): The coordinates of the first bounding box
            in the format (x1, y1, x2, y2).
        bbox2 (tuple[float, float, float, float]): The coordinates of the second bounding box
            in the format (x1, y1, x2, y2).

    Returns:
        float: The area of intersection between the two bounding boxes. If there is no
        intersection, the function returns 0.0.
    g        )maxminr  )r;  r<  x1_1y1_1x2_1y2_1x1_2y1_2x2_2y2_2x_intersectiony_intersectionx2_intersectiony2_intersectionintersection_areas                  r/   r  r  v  s    " #D$d"D$dt__Nt__N$ooO$ooO''N_,L,L/^_oN
 
 ! srA   rB   c                *    | \  }}}}||z
  ||z
  z  }|S )a(  
    Calculate the area of a bounding box.

    Args:
        bbox (tuple[float, float, float, float]): The coordinates of the bounding box
            in the format (x1, y1, x2, y2).

    Returns:
        float: The area of the bounding box, computed as the product of its width and height.
    r<   )rB   re   rf   rg   rh   rV   s         r/   r  r    s(     NBBGR DKrA   r4  c                h    	 t          t          j        |                     S # t          $ r Y dS w xY w)a;  
    Attempt to find the index of the minimum value in a NumPy array.

    Args:
        array (np.ndarray): The NumPy array in which to find the minimum value's index.

    Returns:
        int: The index of the minimum value in the array. If the array is empty or an
        IndexError occurs, it returns -1.
    r)  )r%   r   argmin
IndexError)r4  s    r/   r5  r5    sA    29U##$$$   rrs    # 
11)r    r!   )r"   r#   r$   r%   r&   r'   )Nr!   )r*   r2   r$   r%   r&   r'   )r{   r%   r&   r|   )r   r|   r   r|   r{   r%   )r   r   r{   r%   r&   r|   )r   r   r-   r   r   r#   r&   r   )r   r   r&   r   )r   )r   r   r   r   r&   r   )rp   r   r   r   r&   r#   )r   r   r   r   r&   r   )
rJ   r   r8   r   ra   r   r[   r%   r&   r   )
rJ   r   r8   r   ra   r   r[   r%   r&   r   )rl   r   )
r`   r   r  r  r[   r%   rb   r   r&   r   )rd   r   r8   r   r&   r  )rk   r   rl   r'  )r;  r  r<  r  r&   r   )rB   r  r&   r   )r4  r|   r&   r%   )D
__future__r   typingr   r   r   r   r   r	   r
   numpyr   pdfminer.layoutr   r   pdfminer.pdftypesr   pdfminer.utilsr   rH   r   "unstructured.documents.coordinatesr   r   unstructured.documents.elementsr   0unstructured.partition.pdf_image.pdf_image_utilsr   /unstructured.partition.pdf_image.pdfminer_utilsr   r   r   r   #unstructured.partition.utils.configr   &unstructured.partition.utils.constantsr   r   $unstructured.partition.utils.sortingr   unstructured.utilsr   r   'unstructured_inference.inference.layoutr   r   DEFAULT_ROUNDr0   r+   rT   r   r   r   r   r   r   rW   r   r   rK   r   r  rO   rP   rR   r  r  r5  r<   rA   r/   <module>ra     s   " " " " " " L L L L L L L L L L L L L L L L L L     - - - - - - - - ' ' ' ' ' ' ( ( ( ( ( ( ? ? ? ? ? ? E E E E E E E E ? ? ? ? ? ? V V V V V V            ; : : : : : J J J J J J J J B B B B B B 4 4 4 4 4 4 GDDDDDDFFFFFF  
/ 
/ 
/ 
/ 
/ /00-1b" b" b" b" 10b"J	 	 	 4A " " " " " ?L\ \ \ \ \" *-m    " /2= e e e e e /006$ 6$ 6$ 106$r$ $ $ $N /00     10*   "   "Y Y Y Y>D D D DN   !& !& !& !&HA A A AH( ( ( (V   D         rA   