rL iDMdZddlZddlZddlZddlZddlZddlmZddlZddl Z ddl Z ddl m Z m Z ddlZddlZddlZddlmZddlZddlmZddlmZej2eZgdZd Zd Zd Zd!d Z Gd de!Z"GddZ#Gdde#Z$Gdde#Z%Gdde%Z&dZ'iZ(e'e&Z)dZ*dZ+dZ,ejZdZ.dZ/dZ0dZ1d"dZ2d Z3y)#z( Utilities for comparing image results. N)Path)TemporaryDirectory TemporaryFile)Image)cbook)ImageComparisonFailure) calculate_rmscomparable_formatscompare_imagescXtjj|\}}|d||S)zQ Make a new filename by inserting *purpose* before the file's extension. -)ospathsplitext)fnamepurposebaseexts `/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/matplotlib/testing/compare.pymake_test_filenamers1  'ID#V1WIcU ##chttjd}|jdd|S)N test_cacheT)parentsexist_ok)rmpl get_cachedirmkdir) cache_dirs r_get_cache_pathr &s-S%%'6I OOD4O0 rc(ttSN)strr rr get_cache_dirr%,s  !!rcxtjd}t|d5} |j|}|sn|j |& dddt |j dk(rV|j ttjdjjd|jSt |j dk(rF|j ttjdjjd|jS#1swYxYw) NF)usedforsecurityrbz.pdfgszutf-8.svginkscape) hashlibsha256openreadupdatersuffixr#r_get_executable_infoversionencode hexdigest)r block_sizer-fddatas r get_file_hashr90s ^^E 2F dD  R77:&D MM$     DzF" c#2248@@AHHQR     d  f $ c#22:>FFGNNwWX      s (D00D9c eZdZy)_ConverterErrorN)__name__ __module__ __qualname__r$rrr;r;Asrr;ceZdZdZdZdZy) _ConvertercPd|_tj|jyr")_procatexitregister__del__)selfs r__init__z_Converter.__init__Fs  %rcT|jr|jj|jjtd|jj|jj |jj gD]}|jd|_yyr")rBkillwaitfilterstdinstdoutstderrclose)rFstreams rrEz_Converter.__del__Ns :: JJOO  JJOO   (8(8(, (9(9(, (9(9(;<   DJ rct} |jjjd}|s't t j t||j||j|r t|S|)z!Read until the prompt is reached.) bytearrayrBrMr/r;rfsdecodebytesextendendswith)rF terminatorbufcs r _read_untilz_Converter._read_untilXsgk !!&&q)A%bkk%*&=>> JJqM||J'Sz! rN)r<r=r>rGrEr[r$rrr@r@Es& "rr@ceZdZdZy) _GSConverterc|jsmtjtjdj ddddgtj tj |_ |jdd }|jjjd ||zd z||zd z|jjj|jd}|jdr|jdnd}|stj j#|sj|rt%|ddnd }|jjjd|zt'||zj)t+j,dy#t$r!}td|jd dd}~wwxYw)Nr)z -dNOSAFERz -dNOPAUSEz -dEPSCropz-sDEVICE=png16m)rLrMs GSzFailed to start Ghostscript: rctj|jddjddjddS)N\s\\(s\()s\))rfsencodereplace)names rencode_and_escapez0_GSConverter.__call__..encode_and_escapeqs7KK%WUG,WT6*WT6* ,rs<< /OutputFile (s) >> setpagedevice (s ) run flush )GSrg>rspop rd)rB subprocessPopenrr2 executablePIPEr[r;OSErrorargsrLwriteflushrWrrexistsintrdecodesysgetfilesystemencoding)rForigdesterferrstack stack_sizes r__call__z_GSConverter.__call__eszz#))))$/::k;8IK!oojoo ?DJ  X  ) ,  % &% & % &    /0*-,,v*>  &C t,,1U3BZqJ JJ   " "8j#8 9(u$$S%>%>%@)LN N -'# X @ LMSWW Xs)F G (GG N)r<r=r>r}r$rrr]r]ds!Nrr]c$eZdZdZfdZxZS) _SVGConverterctjdjjdk}|rdnd}t |ds9t |_tj|j |j|jr|jj6|jz|jj`td|jj|jj|jjgD]}|j!it"j$d|j j&d}t)}t+j,|rgdndd gt*j.t*j.|||j j& |_ ||j_ |j1|t9|j j&t#j:d } t9|j j&t#j:d} | j=t9|j?|jjjE|rdnd|jjjG |j1|t#jT| tAjV| |y#t2$r!}t5d |j6d z|d}~wwxYw#t4$rtAjB|| YwxYw#t2$rz}|jjjId tK|jjjMjOtQjRd|d}~wwxYw)Nr+rRs >s> _tmpdir)DISPLAYINKSCAPE_PROFILE_DIR)r+z --without-gui--shellr)rLrMrNenvcwdz/Failed to start Inkscape in interactive mode: rsf.svgsf.pngsf.svg --export-png=f.png s;file-open:f.svg;export-filename:f.png;export-do;file-close rd),rr2r3majorhasattrrrweakreffinalizerErBpollrKrLrMrNrOrenvironrerrjrkrmr[r;rnrorrT symlink_toresolveshutilcopyfilerprqseekrr/rtrurvremovemove) rFrwrx old_inkscaperXrPrrNrz inkscape_orig inkscape_dests rr}z_SVGConverter.__call__s// ;CCIIAM +V tY'-/DL   T\\4<< 8 ::??$0zz%$**//*;*G$TDJJ,<,<,0JJ,=,=,0JJ,=,=,?@#FLLN# ** (, (9(9 C#_F#))=L> O A5N??Ocpt|t|dr|jj yy)Nr)superrErrcleanup)rF __class__s rrEz_SVGConverter.__del__s,  4 # LL " $r)r<r=r>r}rE __classcell__rs@rrrsE)N##rrc"eZdZdZfdZxZS) _SVGWithMatplotlibFontsConverterz A SVG converter which explicitly adds the fonts shipped by Matplotlib to Inkspace's font search path, to better support `svg.fonttype = "none"` (which is in particular used by certain mathtext tests). ct|dsVt|_tjt j dt|jjdt|)||S)Nrz fonts/ttffonts) rrrrcopytreer_get_data_pathrrerr})rFrwrxrs rr}z)_SVGWithMatplotlibFontsConverter.__call__sVtY'-/DL OOE00= !2!2G< >wd++r)r<r=r>__doc__r}rrs@rrrs ,,rrc tjdtxtd<td< tjdt td<y#tj$rY=wxYw#tj$rYywxYw)Nr)pdfepsr+svg)rr2r] converterExecutableNotFoundErrorrr$rr_update_converterrs=   &/;n< %9U++   ,)? %  & &    & &   s"AA2A/.A/2BBcdgtS)z Return the list of file formats that `.compare_images` can compare on this system. Returns ------- list of str E.g. ``['png', 'pdf', 'svg', 'eps']``. png)rr$rrr r s  I rct|}|jst|d|jddtvr#ddl}|j d|jd|j|jd|jdddz }|jr6|jj|jjkr|r tnd}|ntt|}|||jzz }|jr7tjd |t!j"||t%|Stjd |t|jdd}|jd k(r,|j'} t)j*d | rt,}||||,tjd |t!j"|t%|S)a Convert the named file to png; return the name of the created file. If *cache* is True, the result of the conversion is cached in `matplotlib.get_cachedir() + '/test_cache/'`. The caching is based on a hash of the exact contents of the input file. Old cache entries are automatically deleted as needed to keep the size of the cache capped to twice the size of all baseline images. z does not existrRNrzDon't know how to convert z files to png_z.pngz"For %s: reusing cached conversion.zFor %s: converting to png.r*z9style="[^"]*font(|-size|-weight|-family|-variant|-style):z"For %s: caching conversion result.)rrrrnr1rpytestskipparentstemstatst_mtimer '_register_conversion_cache_cleaner_oncer9_logdebugrrr# read_textresearch$_svg_with_matplotlib_fonts_converter) filenamecacherrnewpathr hash_value cached_pathconvertcontentss rrr s >D ;;=o.// {{12i' 0 ]KLkktyyk4;;qr?*;4@@G >> w||~669M9MM).O%D  3 5&t,J#zGNN'BCK!!# ?J W57|# /:DKKO, ;;& ~~'H yy M?g  JJ;X F OOG[ 1 w<rcJtdttjjj dD}d|z}t jt5tj dDcic]}||jc}tdjD}tfdd}||kDr8|j}||jz}|j||kDr8dddycc}w#1swYyxYw) Nc3PK|]}|jj ywr")rst_size).0rs r z*_clean_conversion_cache..Ks&O  Os$&z**/baseline_images/**/**c34K|]}|jywr")r)rrs rrz*_clean_conversion_cache..UsF$Fsc"|jSr")st_atime)r cache_stats rz)_clean_conversion_cache..WsD)9)B)BrT)keyreverse)sumrr__file__rglobr _lock_pathr rvaluessortedpoprunlink)baseline_images_sizemax_cache_sizer cache_sizepaths_by_atimers @r_clean_conversion_cacherHsO&--223LMOO --N   /+ , *9*;*@*@*EG"&D$))+ G F*2C2C2EFF  B>)!%%'D *T*22 2J KKM>)  G  s&DDA0DDD"c6tjtyr")rCrDrr$rrrr_s OO+,rc|dddk(r{|dddk(rs|j\}}}|j\}}} |t|dz |dz z t|dz |dz zt|dz |dz z t|dz |dz zf}||fS)Nirrr)shapers) actual_path actual_image expected_pathexpected_imageawahadeweheds r crop_to_samerds2bU"}R';u'D!'' B#)) B#CQa$8 FR!VO:%!"q&26/23rAvQ3GG%HI  ''rc|j|jk7r%td|jd|jtj||z j t dzj S)zR Calculate the per-pixel errors, then compute the root mean square error. (Image sizes do not match expected size: actual size r)rrnpsqrtastypefloatmean)rrs rr r osy|111$6~7K7K6LM'--. 01 1 77^l2::5AQFLLN OOrctj|}|jdk7s|jdddk(r|j d}t j |S)NRGBArRGB)rr.mode getextremarrasarray)rimgs r _load_imagersR **T C xx6S^^-a03s:kk%  ::c?rc tj|}tjj|st d|dtj |j dk(rt d|dtj|}tjj|std|d|jdd}|d k7rt|d }t|d }t|}t|}t||||\}}t|d }|dkrtj||ry |jtj }|jtj }t#||}||kry t%|||t'|t)|t)|t)||} |s3gd} dj+| D cgc]} | j,di| c} } | Scc} w)a+ Compare two "image" files checking differences within a tolerance. The two given filenames may point to files which are convertible to PNG via the `.converter` dictionary. The underlying RMS is calculated with the `.calculate_rms` function. Parameters ---------- expected : str The filename of the expected image. actual : str The filename of the actual image. tol : float The tolerance (a color value difference, where 255 is the maximal difference). The test fails if the average pixel difference is greater than this value. in_decorator : bool Determines the output format. If called from image_comparison decorator, this should be True. (default=False) Returns ------- None or dict or str Return *None* if the images are equal within the given tolerance. If the images differ, the return value depends on *in_decorator*. If *in_decorator* is true, a dict with the following entries is returned: - *rms*: The RMS of the image difference. - *expected*: The filename of the expected image. - *actual*: The filename of the actual image. - *diff_image*: The filename of the difference image. - *tol*: The comparison tolerance. Otherwise, a human-readable multi-line string representation of this information is returned. Examples -------- :: img1 = "./baseline/plot.png" img2 = "./output/plot.png" compare_images(img1, img2, 0.001) z Output image z does not exist.rzOutput image file z is empty.zBaseline image .rirT)rz failed-diffN)rmsexpectedactualdifftol)z!Error: Image files did not match.zRMS Value: {rms}zExpected: {expected}zActual: {actual}zDifference: {diff}zTolerance: {tol}z r$)rfspathrrr Exceptionrrrnsplitrrrrr array_equalrint16r save_diff_imagedictr#joinformat) rrr in_decorator extensionrr diff_imagerresultstemplatelines rr r sbYYv F 77>>& !-x/?@AA wwv!#,VHJ?@@yy"H 77>>( #|3CDEEs#B'IEt,840!*Nv&L#/ h$8 L.$FM:J ax >>., 7$**2884N&&rxx0L  5C czHfj1sS]f+C OFG 0 ++(K${t{{5W5KL NLsG9c`t|}t|}t||||\}}tj|t}tj|t}|j |j k7r%t d|j d|j tj||z }|dz}tj|ddjtj}|j ddk(r d|ddddd f<tj|j|d y) z Parameters ---------- expected : str File path of expected image. actual : str File path of actual image. output : str File path to save difference image to. rr rrrNrr)r)rrrarrayrrrabsclipruint8r fromarraysave)rroutputrrabs_diffs rr r s!*Nv&L#/ h$8 L.XXne4N88L%0L|111$6~7K7K6LM'--. 01 1vvn|34H NHwwxC(//9H~~aAAq OOH""6%"8r)i)F)4rrC functoolsr,loggingrpathlibrrrjrutempfilerrrrnumpyrPILr matplotlibrrmatplotlib.testing.exceptionsr getLoggerr<r__all__rr r%r9rr;r@r]rrrrrr rrrrrr rr r r$rrr+s    6 @w" C$ "" i "">"N:"NJK#JK#\ ,} , +"  'G'I$ ;|. --( P eP9r