PK!ISSheater/__init__.pyfrom .heater import make_heatmap __version__ = "0.0.1" __all__ = ["make_heatmap"] PK!Q!pheater/__main__.pyimport argparse import csv import sys from .heater import make_heatmap def parse_args(): parser = argparse.ArgumentParser(description="Create a heatmap on top of a base image.") parser.add_argument( "background_file", type=argparse.FileType(mode="rb"), help="the image to use as a background", ) parser.add_argument( "coords_file", type=argparse.FileType(mode="r"), help="a CSV of x and y positions", ) parser.add_argument( "output_file", type=argparse.FileType(mode="wb"), help="the name of the output file", ) return parser.parse_args() def main(): args = parse_args() points = [(int(x), int(y)) for x, y in csv.reader(args.coords_file)] heatmap = make_heatmap(args.background_file, points) heatmap.save(args.output_file) return 0 if __name__ == "__main__": sys.exit(main()) PK!P;ߕheater/heater.pyfrom typing import BinaryIO, List, Tuple, Union import numpy import pkg_resources from matplotlib.colors import LinearSegmentedColormap from PIL import Image def _make_color_map(image: Image) -> LinearSegmentedColormap: image = image.resize((256, image.height)) colors = (image.getpixel((x, 0)) for x in range(256)) colors = [[c / 255 for c in color] for color in colors] return LinearSegmentedColormap.from_list("from_image", colors) DOT_IMAGE = Image.open(pkg_resources.resource_filename("heater.resources", "dot.png")) SCALE_IMAGE = Image.open(pkg_resources.resource_filename("heater.resources", "scale.png")) SCALE_COLOR_MAP = _make_color_map(SCALE_IMAGE) def make_heatmap( background_file: Union[str, BinaryIO], points: List[Tuple[int, int]], point_diameter: float = 50, point_weight: float = 0.1, opacity: float = 0.65, ) -> Image: """Generate a heatmap. """ background = Image.open(background_file) greymap = _make_greymap(background.width, background.height, points, point_diameter, point_weight) heatmap = _change_opacity(_colorize(greymap), opacity) return Image.alpha_composite(background.convert("RGBA"), heatmap) def _colorize(greymap: Image) -> Image: return Image.fromarray(SCALE_COLOR_MAP(numpy.array(greymap), bytes=True)) def _make_greymap( width: int, height: int, points: List[Tuple[int, int]], point_diameter: float = 50, point_weight: float = 0.1, ) -> Image: heatmap = Image.new("L", [width, height], color=255) point = _make_dot(point_diameter, point_weight) for x, y in points: position = [ int(x - point_diameter / 2), int(y - point_diameter / 2), ] heatmap.paste(point, position, mask=point) return heatmap def _make_dot(diameter: float, opacity: float) -> Image: dot = DOT_IMAGE.copy().resize([diameter, diameter], resample=Image.ANTIALIAS) return _change_opacity(dot, opacity) def _change_opacity(image: Image, opacity: float) -> Image: image_alpha = image.split()[3] image.putalpha(image_alpha.point(lambda p: int(p * opacity))) return image PK!heater/resources/__init__.pyPK!eqllllheater/resources/dot.pngPNG  IHDR|EbKGD pHYs  tIME ,gtEXtCommentCreated with GIMPW IDATx8L#ٚ[Rr"WMv'@$u޾e;9ױo9#v;?bco_9Lzƻ> ;ɽm=c֎]6ޖ`qnKluo{@vXY_ ls5@~Vl{S\lu@ fOca[٦Pl%%4vs.rJp,7 7HP~c|*@=z;&~s2ٜ@ܝ޾3ᷪB2VA/LHvs:UlF~{ 1K8W2#U½f(m@>AEva|`76AX y,|͟rVgqo+ l2gTP_x+qpp_F IMg`y.S\^ptC]6GX9UJrpp_pea~g Ľm>:;w,V7qpp$+-ag"7wg vVզV,Ss] }=N{jZ~R;U [ }-Ȟf:vUIV* VY_>>n3777f vfUAqp#ݓXj]<9ɪaA*p5vYj'Ua[[nn`6Z*hRJ3͕7 7YJ{_Yt/[g({[NTi ŧdyJ}: lRz+~ՑO,=cU@0 HU`޽>}rv^rWg;_w ҭW`Pd^aJL XXVDMlkt:8: |מ>:+ʞ828auX V5+ Om++ X jZ Cp_ B/DŽ>E^@0 Rܧ,UX>c~% 3leTnXq2ιj 3,}0J ~#A.C1 ;}b>`6: hVpyJr+ۥ .s+#Qi*Z9:*U"S76 7`Gg7]!2S!v<y@u}0B ij5XQ-WR+H g*\ /@ʪܝdgk[vqaoT^˂K:POn3j`W**SM*̾p> j:mniGgZ@ @S9h0P΀̜nȹs( @cV[2Q$B; Kt$U ؑ0rURne:vGHV VvPo7 ڕdVGzD_'WDeay`) \YY3Dvf]"O7 O`*[I)vV@XJiu :7 ?evZ3Y"}׳eFaw|7*6r_BAtnƹspt2n:A\sPof@K7WW0B /]*0A>Cne و[b |&G:ⷂХ\@\Yn~87yY)k5jPyo5@IoEUɂ1 Bs=ߧBA4>UV ƪ4jm 7 !3UP<. L^fU{L%8S50+`:W`E%jf P?]A1@2TO,:!fYDyCumY`[ew% 7+ٟ߯P*4f:Ù0@ O`vU®Xy}VR|5*RJ`".:v] \i+u8jx@- rnV'+sX*έjN Wl~? ~nh$;,dT @XMne37 ? *P}o5(V\Ju1᧪™i0U@MtC;WU蹔`WB}e '(?*tU݆ᗀpC^}s#:j 58kЙLif;y9 0 ®4NVtY9A7D- q*UwtLk.Haqi3A*gXV \i] [u*`t tCY4Qpu\}f\ʪªDx@ U`xGY XxR;X=A}BheAN V}7 aGp̓!ةf[PTXٶ\ n_5uD>j+FvCnX=2tSv@ѝ.QB5 Yҡ `uO@K k=RVaDIEVvAUFf`J"#aؕG贗s;ߧ{=stf>H^hO%DC}> ]Πd VODmPr(U@XbV \֨:BwX{(U~]nUZUpwF)PTԢ~2i t?3 gð J׺@i#HWXsE+TU Îgbq};S@Zjs7w?t>):ߴnn^pY12wW|a$OD"Dm Xp ؽ,SE*BǺ kݪ:.eb2jvDV Vqr 8ju.֭آ(«אהQ9rlf?Rpw}͡ rIsJ58 B,`XYԭa(P#أk{+ARVm*֨c j2~7gn3E]>Ls>138E޻zM;?_ ~:^*m63hDf#G;(s1k:ezU*?^>Atĕ(]Y0DS(#*%wg^ع&֎S;F bV.ee;bי,giD>b^50bT,a6-UB}]a*T*g V$;!|mv̆EWu%w1q}~gΰ#`7][:KC唔10d`醠s6*0eDyyc]0T2VY%~ـvi6ϥW 5U3`5ꘓR# gSW<Kp.E ;7%jyF~D:YfTA f]%;!x^WI\;s7 W/dl3X}"k*ьJ1L.D5f*Lda5zvqqF\m!`d vn uAnTgJ4ΤS su 2U5՚ UvkF%*ukQժd:ȑRtd,QUf Hyr.U 6ceTl-* W rLW*EBR~LyuR?C!)ދ :`Irυ~S0X2+Xc٨SwR!KC)*) CEt^y{*GXݩϽj*"ŒbFaz"e ڱ" ? nT-f |`Q~#[#k*3hUVD[EZnW"EF\eth}nH *(ZnUWef՝]fk`q%ʤEdT Ks8IGPB8,аzU "LUK)ީ:)X"Xy$5mda#wjϥ}EBŠJTTaԞ:c;\D=Ѭ<1HGDTh|hpdF KfARGD%fKe2 *dR{Pv%3V GcFt %MTa~x10db֬;ǐLU`5N a+`j*QQl4b: ;;cT>JsF`\t+DJ%0kT]y**V]hD)=`a^1IU< ;Q=Q#H>$!S+6#CuIl*̮GX3jŘ  g-;L*UG0dCͤN)wPA4Y;7y'cI:GŽk jx Qu00`QJoEȲFFw_ w0d~/${w\@OVб0oD@ zaTaE> eel);Z5j4:q`D-{:\h0L' U۔EBPQ(ªkAņe-9D:}*0S0"9B"5JUW`RqU0T=c^HfݣTa¼`~(i_$ߋx!ceS'"9¬| `DC|3D V%֔bUj0 T0D? ~=*Ug X$SvPE#F(  YWV;[7!P \itJUZxg5aV[B3 2VEtE+(1s~̜ }g.UHkiaHvTsY|1e>OFVDf,*^^w6]hK$^l"(2ŷO#8-Rj)QnUcz QVਤD(! Wf#G⹬#G(һ .ߝ< E$p*98 DBi*PWWjE-jkkJёnB|A%0%M?a"54p&"g8U#6` D֫\+DoNwvlP݊wPꊲj0@凂U~ hT(,R*ΰy*TV? j5tz"X(3uDg@ |(Sm{/3qaFpL0j_FW CfHy>EGVB#*tUlљj I+e웁 ^(DVFGgteܮTݻu)='G@Bd_dC5pf*أ4gPbe5(|T{%ѫһQ$jA k{K%HE`Xa"EhQ  "{ jVca,s5 #il D_f|;5ǬA&R#@"2G3EjkE (B6>US!QfS b"s?hQE2KJ|(^s*mzOE*D4-Ap+AT"SRXF!^ DU*R(2UH};U@1] (ߤ|T$/EؤWp5UR*E4{6e[ fC>=}4* "U\ k]nNEj w O{&wڤ̳S =J!1E]}y;`*B@S AE}Fx8:, y_u~\a\(»-ه_#5_"0KR*Ě;eB>n5Xn1T>/"[RUNEx7r#FT`a\(=f~(At1'\?`]P# UXn*E)hnͨA"^;4F +Fpu@lQ=LݨeوQ ZT|+5xW\v% *uL=gX yGF 6gB3W@/RwEQ5x;"* (d2RBuW=mC*ԠU[CtN@O0maTOਾ;{43U_XSA@7]Q*˕5Za*cTGMn52C7[%V$g%TL%P|L(<&UZh&TaV:  q&㯨*+}ؤ+Q0<-YE`. G@t_8١( N,'%4#BT)HԠZ- { QW`ڡ Վn;NMBlѫB>w`weUϖK(cV SK>Eй՟R{+@#H?ިCK$ #TtA[.5N@_B*"^#tYQXYi]]Yerj(`,ӓx-dRUʊ39!{T5\kCG*k fA f,ˬ&13jԱ]"_;@Zm"ިE4HwJM`(s&g0٨#xkf,X5ZiVv:ZjThe5t(Ce@ZuWUGFjآ5*C|lT)o>/JSgqjֱjh _WTsj2Jcd!XSxw}U@t)Bd"v' UkidpUBQ(FupC=[/E#\I9OQV@FL'vDPtՔ+8M]{|j{/ZWjh:fnPQ,@^sVXUA3( gw.n\f%e d,Qtr =MQGQ?e:r+àF*B+dR *j0Zhv\.20$п2A$M@qؠU2Lٴ 5bp^EVUU:ժNFGYVXpڞGz@s6YUX<7ش!+?H~Uj;}c&w̚#F3s2יH^f(a,RF>}1xCʼ1.D=]cE]E3١jE-gnbGVWSQ&27x%Dء D{&UJ9QȕQCtlfTEyhZHf`6ee2Ŷ3Ov!r"Hk4gA\f:]b-Av bSlь%:u׳ ֮fo "z^TV%G8zsy0t'+J +!a(g5S>؛,s0u@JlCWC2a0QQWtOCui ,ٕ%ߝIGmQ:6lN$U@IheW9`F"֝zcQ-ʸaTS% ] +lQF!"P:+Bu~2ztTUwPtsdf*Q4jYm&c A$һ_spQ lRnd˩10t(/f ;= NA T!Z$PE w3u9:gfq7wsQ(`ƤSdaJ{]R!R"QTTJR(*(sJy!pThD#DcpH)BOCP+t|/L\ z#K:hDF]kEvc_d~2w{6P./}[(0ef&*6i)b0Q\AuأuJ@-qeUhXjCT["A+wiw9WK'D3eKuA6žL:Zt0eY[a20gxFQ4. ʆW縫2B0@A2tT?cE Rw)t4FҌjP+(yuJEUGUKNMEh5F5x P0Duv\ l2xbmVD6b9էD>(Сt hĦ hw¶W:} JcL@ET<\|LcF avhuvQÈY&5]bud4n"q "3B9Si 0h9EXoQ8\uD lr%7RJٚ 2LUEk˴oknDRT2l4؀H4nvd.ۄ*Eɰ#]fi-6=;VQf`qEU֌f뤨Fَ^ ?R>Jp=0^l#F/S y%R]1@/2ssH'kdl2 V:?X v< AFwB Plʹ-Dj@2GkUl2&(3ߪ۠:F b@2 [ kAƫ#uD1oA.]z?U5k: Ls}MvP;V8Y Bjr|5stTeTd@7N?+:wRs C5k] wN>+j\zj$#PA`tgN)P1g+` >M[ /ˌ6vGs ¯AՆ<+V.kݩg]1ӮAI9b ,a ½mqŝRXL17mo{hਪ3mmo{Amo{mo{ۛo; şmpo{r&uޜg!mAB]߳0*zΉso{ prr (!dה^x`΂3m3 6R͜6^_r/\<;H@:y4?/3J;=dN̨~oAr2GLz;0[wM&P}#E|':0Ǩ`@wSh{(! ̄?iT>C;cFhvX? YM(̹u6];' ضLjtmnZĄ9ؗ8ZMt?8ِxĜF'Y،5j{#Gq^>g tNsvV PcV)jhG :R3 xP|c[ 9! U<azQ7ծXgѩ)xF0xƂP4Ʈ8Uca44XFu}ڠ:JQ2:]uF/×X±Y%PJ4c2Tim]?7ULmxf7\a$nLZ``>3T0A:;1knm1P_m֩RFU3{J4/ێe+rrFU,+c+PT@eԝyЂrQHíW{&F*@ՠUdQfQViw^Gv6X0mevP8kf܊Y*ϺlE²&8kMEF]j̬wVcdHUVwT ROC{EUb?G+hG3<;I|չ#y^c^ww;y΋92(aQ ]IRc]YLu9p$ ;3#0ȵ7qڻu@^p\+c T뙁>Q5S&H W,rv(‘8Lpya;>W0:uw΃ADT (7r V*Hd*kVWH0G!Ȗ(DPIty v"P`v~@ƌlOACF;lP!ʜ`6oOZf-F_}VF sRͬCX_a?0ӭOQUl۫Υݩw@YwPGYEBZ8͍jU`"D`t:bR|kD%#tS213<=c,G(S4c"DQ5# {u=v^ĪAG_p&#MZ?) X%z7?JąC Tj(@unQ2<.H&bQ}QeX@Q`E3i5 Q)\ض+u"C(m?<+vu8l2pɬ=zu$h TX'w tv(`5O %HP㚰0jGPVNlP.`2qN0g'qH@Uh#{wP9.z&H4~L؀*UY ڢMR {8K).OCYd/A@/K~NCz+uA@(Gyxx]j'V)0D)@D mQvy352>3DJ9m)Q?rXd.!@xs`Ak2kݏkTU*۠*U@@)Tz<#??(RDVؑH?F8ILHE;RwUPFwhVqln nρ5ء}8W! Mک#u7E C$& PgCVau- 8fѥQ5x)<ݜ(o0)0ת;f< ݐ(10D`wW FsU2R(Tءlh4 f]٢߈ZWP6(' "?;Ԯ$zvJ ^G@U0p4p5HȹPD2 tBP*ͨA62MTـVhtUD"t5\%&cw:*dD w} |%UF23R]B<b{~/ (A6mBYr}B[9Z~u9󲑦w!v(b.R&=O`,RF٠yf tdyxd٢Un> tDn+y? Qv2d <00אGQO`Ŕ8lҺS*EhVEJ;#2RZ+ V5UgP0kwEGI Qfl!a$J-v6>(Š|B%DW5|%61 |١0'TͰ*pleZHFcyBU ,o4s!`{$UlϧA5GbR&2t$;'2 rB=[C9-R+5:_=zw>%e0_bf{DQ*13:a=V$gT"Sb:*(ʐQdGG |QewWG^ Z.(ehA:!,'cQ6L<un3*T\0(YEa4D21#8N |2TplcD73@@-=u'Ɵ]B TG,vT<E7dh~l39z fGخЩ.u0*eA#[m큭/2|Qc$Ϊ]uvZjآδ nMGm+}=%&+i2}a,RE'Y%mGUֲuG yI&Ef`uE]iYHMWO# tW\ؤ':RXB2٠5N!+M2WȒWZ*bVٞQkvѵG3X$Qp?k~O2*ڙ0!!TIG)j^_7\Egm !>.п>yX;,5=+zwdīHd tA= j0Qu  RI%BaY DQ5肠W; QtJ< AEe #gNՑGQSLY S`?أ6m(36)f;Mئ**QU"ʰ٠ 3A/(`.Q#EX-ragGQ9ΰviSU:3PQ DS,_"rvQdY v) S7#Pd1Y[T\#YLQf̚hUtT}4iCF sۏ vW3uC"ECFטg<{#Hwew%:̨5(,Y ɪ@V U٢e.]jdf"$|]]eQgf9.PQz"Z"%lL}֨bY=箲E YhJLDR3iY2Va#u^Ubf DhRQB곕u"vآB PXVQ4#qPtn'\єl/Q;*[I Q0st]QӪZUA2ŵKlш8AG#@yU"0sTp50k2F;;D D&XdJ&w%"PQ.5xVij0ȪBEf+PU(C bIFlhޤJ"GBWRF(Q+/ePuP̔TCkyBw纒=z;fc64By?gbG&X&8zW *(AF ^U.!3s (2EmJށMRDJ9"T_s7*0kj*js*l23z]Թ/;Parf3R F9kQDitEB0UJԪ 7]0E6|"Ds:QyDg0L6XU A2A'=;$A8E`F`VB|2uר0Y]23Uk`;`)8mOT.qͬ U* 8+ڰ ȫ ՖŽ\CPG:`6btF =X'4+mvlU4U-퀑ϡG]vԜ2g' R*XI r DYtE5 ݪpU읪QY5GtNS*dE8z3+!_BЭwUp 8 )?&̽*0D"U.fAQ&F8c+;!! 9:]ffaVIuU(Ntj{4 U8R~YEXA I\*J5pu!|hY>;P(SAPF^Tlbڹ5a:l.U6ˬG.RNѓ0ߡP`eF("9 V$WSc RٚL- BU T$gBDΰIX Hf$Ȍ|Ȩ\'󽳪a?7# v(WR*p&٩PUU *DPMUpZj'{@V 4l)WSŸmy{D vB|#c:M֦ͬ6b]e@8Q%(FQ꺄Q EyEE܃N5)tG;Tr4 jQݷZ Fh>![pU# NUs1@"BAN:TXСK< :,nAwtd3U`Xm gZi22\,5$soPwp*BEZ,xPNkgYٵ h*B=-]cg!:Х˃dX>Q"J8HQ8hDV"PZ$w0/=k̼"3a-}᧪P3TQv [}O!wTxH4CI*ѧ]X,llvq;{ ~ݖhӠ'<Wǿ8  n"F~W44h%>3aR}_XLj,lAY@ށ9k;@9C. Cj.yx30x?x|//p41cM;OKU.Gh1¨B"0sC#8MljCe˨CDԠ{=.Nw (DTU~U(B8*c*u0T@aΜ+D:%]bZ\엙Cd:S|]]^QHR,&Uu+ (26)#GE2]ѧB5  t(Dt_^3'lq_EG ﶘK jDEH3ޜ #7%F#'jU ]U~*D: V ^sYoQ q ԉ*BCEgJ blt0:7(@6H]:MU}[YV 9cVYbdeT,pD9S,`P5Uu.5F:C:TGݩC50RlC(@V I+p cvI&䷳ q*]vޖlѬXS˭UXcT+[wQ(Ceʒ^ʵϼF{g`sH ;e7EԎd4+\s#%\ vlTΨR+O޳ifwe2!U dX[ae~j{Ef3(oG5HU+48ZGpEN4TrP[Mf%Jx)PUrUxRtʠUC<K!+dYcOnt-J*8^sQ.+!GG_k%\*={tB_U`UD̀Sf`8dE GE_ጹ.wRX$;d:ZQ{T+GϹD32˩; gZdaUb9,T/Ϋ*jTU̿* =5(BEv[˨, C(B6͂XdYP2tDGjY3D婫+ڨSUv蜧S܌5< OB+,ePU.T [}F7 u c`"pdfE,# }N*C)ԥA0Vu8KiPc WHP]U"U,j]ͬʹB:2 Qh5R2wgV@9-QW|ʖ,Y0t)<'T{ԑH52bՂWf iE.b{WA,Ѯ VP Ì ~碰T`XiT@PiNƅRة*rY]*Q׾Ye6MuZ}n:Qu= N{Ty 3 jT5^Jk*`RU OD՜*20tΨJ`WPRLERkVг@(XȾ #Gة WHUxu;]6IvpdөFY *XU ـsϑf:F}VD$;Y 쀡* W\Ub(v jk]Q}!~R[YmYgkv@uA+°:43Ǥ QG#80E)j-VvbqvBU ,5h[S,R|J0 C+LE6k"D#G\FU;ڝD buuԜ!t,NBv H/DViU=q=j_)P+a8:l U@D㚢D"CU fQ=fhOWY>"u*TzԹ{*mDZvI]  K~i'2ǰ5đ6MQh-IC΀2\©6EړwCfjNDr+@ivpEډnUPQYXUL< "dƂ3Y^D8AWp%'*p6 3PeAᑢa#Pt3 i'|%aEE C(Oؘ" k%E(XuMj+p$f,Ιh+fN7 WWFQhf{4yݘz7!vZjeV!8joK[ 0QdRd9f=VM@QNr *v Q!c5x\"C]&e;7]oH 5@r0` UA=Jow6¶U%B*°{]p|0 s#`9e%kji t}zL'yh%g0xm](4f*uj 3jwQ9e:Q$Zt/";#EJ\RQQYAYBF̄ጼCUK;A6ft-Bwb&eՀkEgA[}>UNI$΂lݪSaM`oVu23oI v6j"T %`مݠ\%8rAXCV)Vx CeNSPe8, әV)EJ-{]mz)K 0t00~*LFߡu; IDATsS-*%JL2HB#@Gl7 Q Au!0LW! JQnA֨c}9T#rsZ*:Y{ V'JN`m 3gZAVVa7g >a8+Uw.}æS(Ѣ,QrJDFYK+~EUtW\\ V-[ Ch$zg5(sgS#e:-f QV}>t)Ìc3O7U%*zղCh+O8WPsW\1 a ]U0.}XUY`(hho`#HYig>N[9? YO~%W]&c8''~!@-t Vn\ 380uTZѡ5m©)`(:i0U!y':*=G`rqԀUfj0TxO`=YfERY<.u͡V٪F+2S:@{gAН&l *V^ᆝ[%iٜ?3 f+*[iVhiϏᆡh8sqihx8f"+5O#DWB%fz]gTΨ|evY|I 7c{ +hp+Wȧ x3Fj'(EV V¸|3 <O!YPUzf\R7kc`hR܊inffj &: ^cF,Ps׻ITU7_BrUda̾Ď q~N/T!5GW<+R">.Mi fԞUgwEPVqW,;+A11OaX  l+tpUs0fKUqCA8*d>Rj"ٙT/Aw!Nj\zq5VstǫvˤA8 XdO?0ܵF?ZCy?i>NmvuUf?Oa`jt)@ 􁰪*s{V > ' d0lg Tpp>8kS8+fH6O!Wp#[ y @T;jV`'Gn~9Wa׹2PBi<v 7Y (X Z]mfM W݆0_YzUgXQ YЫSnCS@$"j0+1 ,g tgX`ةU[s82$V(î`jPV[m~]0{UbPT x4>{3x&ޯ^ nT]< @A uX"^ 3SաkBRdAm_T>Kٙ`:uZt*ħZ; YE7 0tkg1?Qg:וgVQ6] *e9 jʷNg;wDUj$ ! | ]@O;T^f BIu$耷z̆20tuUy@Gz'T]sUTCΈ̕Vxȟ ì:1Cbj;rujJ93`)*pCAV脢K?\WЌK]@  Hfա 4jIoX] ]p ©LQ]sF]dgUq'7i8j0Bsn5R=XVA 0l {yQ%>[n~$ j٠֨OKT`T ΀bzqw3#Ko  zuTQ+@[2XuUb|bJoppðXVkf5{5ƕW 75P h{lzoО ¯T+[\>mkT9_VV[>N׽zۡZ v*Q[nkhQ_>쟠Wb> 7'􎇷% M 0\OS|;HYNX d]F],Pt9s_Oyu-67gJE6^*g:kT7{0 E5nO(Kgopw{[::gcdE] a@삢v''ςoyo ðSa{r HXI}wCppoJ@m~[{8'ߕ7#sppo E Ϭkte8c }0{rUF;Kugpw{@c݊ܓ0V\Yf>gV upCppo_*uSF=jlح0J:8lTmpw{@xmmbŢgKtǗ'UYUmNuo_p:rV9?z+oRՔe3eg|pw{Y{6t.zޕAv.~A;νm >cN{V;̽m('%w}^wg<@~{ rz6vڀ}s뱷ŷgL9IENDB`PK!'2}  heater/resources/scale.pngPNG  IHDRRG$c1bKGD pHYsaa?itIME  #$~IDATxٮ$GDI-<*I3zd -9/Yr׿*~[^Sp阋{{d}~ c{[ùYu ;/|c?뇎E1x$:1~g<=sP|9įFdFdDTC"Yyۗ2ݽ>vfc,>y|_bcU/Ko}Yst 9}?ՏVǹ^~.\5'|Α9-s=^J\yx?uƞƹi/qG.j6ֹyVk4(/wvž~)""0R {~g&Ӊۼ432|gjLKi$C\̉;kPƜ:F2̀2ֻ;46enl>}U;:Lf*jMnM$p QQ׺5=3n }ؙa/F 5Nϼ[g:QMxY':#q{s_ryIHWxr&=}ܫ(SK)5.g%ePUhsecXU}DƧkݍ7#ؘu~ߘc]m'2 >Rc2,\.׹H!'^+Qi:>.1L6kkyDL 7*ϜuRuK6`NFj5S~x0RgS |elb^'e&t;Nq ̿LLm4A'TMaBdؙV~jB-UX\>5xJ4*x&Fј)Oq;f+r^Bn Ofl~݋OMc,N=kMn$}Hvdź *#]Dji~:9H8i/_hfrJPPWJҘ5."fs3:T^}GA)P݊8`2S}41MZQ9n3ӄN6""{Ϫ"^W9HܹR5cܽst sAD -1 qj8-;$Im6&ŭļ#:kXgm\I`D(3d[lg7iJצzoJx>"<-)6[uSùmD7I" \#_g4)᩺du1:j)=W8;IDoMOmݺ3%Zù6&Mpn>i1bܮ8;vڷ^S- ʳmɫRL?Ǯ˔4Ebޕ-nӱTr2IedMlߘN7QQDSn(gi}op }'Í"f+h3-r֝(?́ju͸+@9ڈOQ63vH "R$r8*uF\pSd2b!26su3GD|\NL)D :*]Ĵ'Tgq*lֶ{1x^#v9?N|Mt_ض V݇7"&$N;)TnStI.:5:aNJX&bq8fꢤ1R Nh&5!pǓyWVSU"OZfz-+JkyͺNi0SMP2֠-Ymzqyoo[]t[8]AHlD>ίDU`ݹǢ9r5*#"1,e4 5cNs(j=].15yR<9jOZsv0R "LVI'>N 'Sߛ%9<}^Xuc5NsO)D?NuS5&Ӧ39ʘX>s,8ݢJo^> )QܚSNĹFcv'7ٹn-tQE Sk"0.9tNM93y028"ӞzCzk2)cm}~ss2 #PH(cz8=qt%q1R-7Z&23)Bb4 YCWPnCw:7S`[dm NƁkJLRNwl~h'y.m.篖~WViOMj Mi&S>Ect)7J !lB/wE3uQ)$N&VN~폈EoΣRȟܸiKa̷L΋69 8Uj_c_[JXS 0oKI|05*V֝HUKhed0 ޳2+')Z19C^TWGjϹc[z]TxVp Ν?N} %\$C|ޭ2U㾯$od#{blݾDcV8-z0Ntũ=2=?5qm3.e0R&+('63eex8uO_Uڊ29Uw{0o9̙|[1R-[cd'hWйQTS(֭%`uk>ٙS ݑ[ }.NU{tTͯ[xڿ:^9eƳ=nx/V0-O-~i|^pz~!~:R뱹4|+Ļ{=)̺izcO8fy]v7k|aOp̕[(^k8F:pS\FHn*wi)#Xz'hm{Xˋ}RND%yԽ9ucTit52R7ƊsDŽ$N**BEL]X)բqqЙ J`;*#T ڮCK:{fO5Jqj~d^TyC!yJq?js>9؉]{SmX= |Gb2bNX B5_oDZXrqZb S`Λ2*{23tZK:=]<Twsop*3MpR''n3u9Gq7i:5>sw9KN+ΏcȸYԩVHPQ9S͞)w:nۊ\]ͻ23H'tp}:p;siG$tvNfŦތ{*ri[+YN(H'M>uT~T7u4c>)7*ǽ5g)F5? Í;ΐqĪ.EnM4j̎)B¯Qv^1:cDdצh#u۴co;MM{fײIs|jdtF 5QTm ̶ձ*늵 uIn[x#.'#Dn:Ǥ0?j1**{^W=DdLBO>97chu8͙=CxŦ0iE;&'~j243/4 NDk9) CX)C̻5vZ&>'y9^eU[j8ީ[ '~a]1L' y}*1/Q ݵtT%0yqVpIRKY2IȫNUݘߴ1ǰל̛7ĺ;0R P8 ]#xmA֍P:ǜRG6zsmgMQk5I}Fl.WSq`'MfN)/M5om+nwĹkO"EvQQ"! WvNăS6&ĭ=Ԛو0M)M$ȞNImŜQs߽泩ZqIRu;"Rw ][x(uuKwڷ p+m} GЦ0KbfvUl16ٍusZǰ^GuI7y>k֫kT4#2˜s]^)WpM7C-.!67ku #aNFtzۖ=5.cO&dF=wFR^~';l7_)ӯJ4*t)je2uN:Nmu;(scs?s*C(k6֍y/]s_8w {oJَ9MW[P=&xV'cT}W؋s٫ F epG9u7eIuqogx]-cK(sv_} )VR,)Qץt5!JM!4W e߉fPC%ƶmgTdȴ\}:k\1_wk Ԟ0Q˹yΦ{ޞtjaB1<&AϔD_glR)NP ƅSX;t*|F ]SZ!'ըSSwnqϝ!uSuZ913k})2l'F #j:a{:O^ޗz/I1ok,tID8:iar;%9|fFw2 TT𘞟ĝݟ)smq묧oHSm9 !uSg6"Y}fSOr2{T)! m .qrjGKE 9s֓Qca[RJ%Z2qql$Ҹ&MBu"QseMg cuTbathc8mC]\ɛ4ų}ƻyt;6E]7{[~-xJUqA}\Q;ՕNG@N5*TclNp6o:Ũ椆tupRʩ&Ivlr0kך -y0KNF $ sCEIT!pIv/ԎtOt9BN콛1]n8;jb~gȭ28yEb?>c)soNp')5 ̣@B2ZprrL)+X0]d4ۗO8[s‡ X)vst$JÿɊ+M" S:@ul:w+T+4=z Gl| :N؀\ɗh+8jBwK^Sk-/!ov0 (8HQmlyQwE~VXICY;v"5.|ar=8YX9SZ] yXg'L#F0Գ|p``qkT"1*#rnYysrZ\ڸ^)DH|N`}Xqnm9Nsir읏rGoPK!Hmpheater-0.0.1.dist-info/RECORDuI@pYl8,ˠ8(QYA_CBeR&wz$i㸨.g͓c4'=X0,8t (svl'04̀qF'L/4x+F#d\`Ϊ?'S8 +9 hp9NTW݅JY HsO˵ PEVmFؿVJ06`UIͥ]YRqUnTIk^m}(9\3s;z8UU(sBUdYr%qLrk(Bf?ғQm߅~H%PoeR%7ɃY^/cbӴ'R]-ZPp~r4~5 !) ۚ9t@3@T{QJ[YvNqh?z?펃Խqo?PK!ISSheater/__init__.pyPK!Q!pheater/__main__.pyPK!P;ߕCheater/heater.pyPK! heater/resources/__init__.pyPK!eqllll@ heater/resources/dot.pngPK!'2}  yheater/resources/scale.pngPK!HǎASS&heater-0.0.1.dist-info/WHEELPK!H 4heater-0.0.1.dist-info/METADATAPK!Hmp$heater-0.0.1.dist-info/RECORDPK x