|
1 | 1 | ;;; Collection of utils. |
2 | 2 |
|
3 | 3 | ;;(require [hy.contrib.walk [let]]) |
4 | | -(import sys copy math os re) |
| 4 | +(import sys copy math os re [importlib [reload]]) |
5 | 5 |
|
6 | 6 | ;; when passing kwargs to another function like pl.plot, the dictionary should |
7 | 7 | ;; be like {'option value}, not {:option value}. |
|
23 | 23 | (defn symbol [string] (HySymbol string)) |
24 | 24 |
|
25 | 25 | (defmacro/g! svifn [&rest args] |
26 | | - "setv if none" |
27 | 26 | `(do ~@(map (fn [e] |
28 | 27 | `(if (none? ~(first e)) (setv ~(first e) ~(last e)))) |
29 | 28 | (zip (cut args 0 (len args) 2) |
|
81 | 80 | `(print (.format ~@args) :end "" :file ~fid)) |
82 | 81 |
|
83 | 82 | (defmacro prc [sym] |
84 | | - `(prf ~(+ (name sym) " {}") ~sym)) |
| 83 | + `(print ~sym "|" (eval (read-str ~sym)))) |
85 | 84 |
|
86 | 85 | (defmacro mapply [func &rest args] |
87 | 86 | "Apply func. Works for keyword args, unlike apply. (Probably broken in many |
|
149 | 148 | (setv last? (= ~g!i ~g!last)) |
150 | 149 | ~@body))) |
151 | 150 |
|
152 | | -;; Use this instead of macroexpand to get output stripped of the Hy object |
153 | | -;; ctors. |
154 | | -(defn ppme [quoted-form] |
155 | | - (sv sym-dict {} b (Box) b.sym-num 0 |
156 | | - b.after-open True) |
157 | | - (defn sym [e] |
158 | | - (unless (in e sym-dict) |
159 | | - (assoc sym-dict e (.format "sym-{:d}" b.sym-num)) |
160 | | - (inc! b.sym-num)) |
161 | | - (get sym-dict e)) |
162 | | - (defn prl [e ldelim rdelim] |
163 | | - (prfno "{:s}" (+ (if b.after-open "" " ") ldelim)) |
164 | | - (sv b.after-open True) |
165 | | - (for [li e] (rec li)) |
166 | | - (prfno "{:s}" rdelim)) |
167 | | - (defn atom? [e] |
168 | | - (in "quote" (first e))) |
169 | | - (defn rec [e] |
170 | | - (setv t (type e)) |
171 | | - (case/in t |
172 | | - [[hy.models.HyFloat HyInteger] (print (+ " " (str e)) :end "")] |
173 | | - [[HyExpression] |
174 | | - (if (atom? e) |
175 | | - (for [li e] (rec li)) |
176 | | - (prl e "(" ")"))] |
177 | | - [[HyList] (prl e "[" "]")] |
178 | | - [[HyString] (print (.format " \"{:s}\"" e) :end "")] |
179 | | - [:else |
180 | | - (unless b.after-open (print " " :end "")) |
181 | | - (sv b.after-open False) |
182 | | - (cond [(in "keyform" e) |
183 | | - (print (sym e) :end "")] |
184 | | - [(in "quote" e) |
185 | | - (print "'" :end "") |
186 | | - (sv b.after-open True)] |
187 | | - [:else (print e :end "")])])) |
188 | | - (setv h (macroexpand quoted-form)) |
189 | | - (print h) |
190 | | - (rec h) |
191 | | - (print)) |
192 | | - |
193 | 151 | (defclass Box [] |
194 | 152 | "A box to hold values to be written in closures." |
195 | 153 | (defn --repr-- [me] |
|
357 | 315 | (/ (sum (map (fn [e] (** (- e mu) 2)) coll)) |
358 | 316 | (len coll))) |
359 | 317 |
|
| 318 | +(defn cumsum [coll] |
| 319 | + (setv c (list (copy.deepcopy coll))) |
| 320 | + (for [i (range 1 (len c))] (+= (get c i) (nth c (dec i)))) |
| 321 | + c) |
| 322 | + |
360 | 323 | (defn cross-prod [x y] |
361 | 324 | (defn one [i0 i1] |
362 | 325 | (- (* (get x i0) (get y i1)) (* (get x i1) (get y i0)))) |
|
397 | 360 | (except [e Exception] |
398 | 361 | (print ln)))) |
399 | 362 |
|
400 | | -(defn ooa [y &optional [xfac 2] [x None]] |
| 363 | +(defn calc-ooa [y &optional [xfac 2] [x None]] |
| 364 | + (defn bad [e] (or (npy.isnan e) (npy.isinf e))) |
401 | 365 | (setv r []) |
402 | 366 | (for [i (range (dec (len y)))] |
| 367 | + (when (or (bad (nth y i)) (bad (nth y (inc i)))) |
| 368 | + (prf "calc-ooa: i {} y(i) {} y(i+1) {}" i (nth y i) (nth y (inc i)))) |
403 | 369 | (.append r (/ (- (math.log (get y i)) (math.log (get y (inc i)))) |
404 | 370 | (if x |
405 | | - (- (math.log (get x i)) (math.log (get x (inc i)))) |
| 371 | + (- (math.log (get x (inc i))) (math.log (get x i))) |
406 | 372 | (math.log xfac))))) |
407 | 373 | r) |
408 | 374 |
|
409 | | -(defn ooa-from-file [fname fieldno &optional anchor] |
| 375 | +(defn ooa-from-file [fname xanchor xfldno yanchor yfldno] |
410 | 376 | "Read text from file fname, optionally scan for lines beginning with anchor, |
411 | 377 | and read symbol fieldno, starting from 0. Return a list of OOAs." |
412 | 378 | (sv txt (.split (readall fname) "\n") |
413 | | - errs []) |
| 379 | + x [] y []) |
414 | 380 | (for [ln txt] |
415 | | - (unless (none? anchor) |
416 | | - (when (or (< (len ln) (len anchor)) |
417 | | - (!= anchor (cut ln 0 (len anchor)))) |
418 | | - (continue))) |
419 | | - (.append errs (float (get (.split ln) fieldno)))) |
420 | | - (, errs (ooa errs))) |
| 381 | + (cond [(and (>= (len ln) (len xanchor)) |
| 382 | + (= xanchor (cut ln 0 (len xanchor)))) |
| 383 | + (.append x (float (get (.split ln) xfldno)))] |
| 384 | + [(and (>= (len ln) (len yanchor)) |
| 385 | + (= yanchor (cut ln 0 (len yanchor)))) |
| 386 | + (.append y (float (get (.split ln) yfldno)))])) |
| 387 | + (, x y (ooa y :x x))) |
| 388 | + |
| 389 | +(defn sypd [procs calls time &optional [calls-per-day 48]] |
| 390 | + (/ (/ calls procs calls-per-day 365) |
| 391 | + (/ time (* 24 3600)))) |
421 | 392 |
|
422 | 393 | (defn single? [coll] |
423 | 394 | (or (not (coll? coll)) |
|
521 | 492 | (do |
522 | 493 | (import [numpy :as npy] ctypes) |
523 | 494 |
|
| 495 | + (defmacro getc [vs i] `(get ~vs (, (s-all) ~i))) |
| 496 | + |
524 | 497 | (defn array-range [&rest args] |
525 | | - (npy.array (list (apply range args)) :dtype int)) |
| 498 | + (npy.array (list (range #*args)) :dtype int)) |
526 | 499 |
|
527 | 500 | (defn array-if-not [A &optional [dtype float]] |
528 | 501 | (unless (= (type A) npy.ndarray) |
|
540 | 513 | (defn ones-row-vec [n] (npy.ones (, 1 (pod-or-len n)))) |
541 | 514 | (defn ones-col-vec [n] (npy.ones (, (pod-or-len n) 1))) |
542 | 515 |
|
| 516 | + (defn xy->XY [x y] |
| 517 | + (, (npy.dot (col-vec (npy.ones (len y))) (row-vec x)) |
| 518 | + (npy.dot (col-vec y) (row-vec (npy.ones (len x)))))) |
| 519 | + |
543 | 520 | (defn sort-with-p [ai] |
544 | 521 | "Return sorted ai and permutation array. Each entry of a must have the same |
545 | 522 | type." |
|
651 | 628 |
|
652 | 629 | (defn antidiag [v] |
653 | 630 | (get (npy.diag (get (npy.array v) (s-all-rev))) (s-all-rev))) |
| 631 | + |
| 632 | + (defn get-row-2norms [vs] |
| 633 | + (assert (and (= (len vs.shape) 2))) |
| 634 | + (sv nrm (second vs.shape) |
| 635 | + den 0) |
| 636 | + (for [i (range nrm)] |
| 637 | + (+= den (** (getc vs i) 2))) |
| 638 | + (sv den (npy.sqrt den)) |
| 639 | + den) |
| 640 | + |
| 641 | + (defn scale-rows! [scale vs] |
| 642 | + (assert (and (< (len scale.shape) 2) |
| 643 | + (= (len scale) (len vs)) |
| 644 | + (= (len vs.shape) 2))) |
| 645 | + (sv dim (second vs.shape)) |
| 646 | + (for [i (range dim)] |
| 647 | + (sv (getc vs i) (* scale (getc vs i)))) |
| 648 | + vs) |
| 649 | + |
| 650 | + (defn normalize-rows! [vs] |
| 651 | + (scale-rows! (/ (get-row-2norms vs)) vs)) |
| 652 | + |
654 | 653 | ) |
655 | 654 | (except [] |
656 | 655 | (do |
|
663 | 662 | (do |
664 | 663 | (import matplotlib [matplotlib.pyplot :as pl]) |
665 | 664 |
|
666 | | - (defn my-grid [&optional ls zorder] |
667 | | - (svifn ls "-" zorder -1) |
668 | | - (pl.grid True :lw 0.5 :ls ls :color (, 0.8 0.8 0.8) :zorder zorder |
| 665 | + (defn my-grid [&optional ls] |
| 666 | + (svifn ls "-") |
| 667 | + (pl.grid True :lw 0.5 :ls ls :color (, 0.8 0.8 0.8) :zorder -1 |
669 | 668 | :which "both") |
670 | 669 | (.set_axisbelow (pl.gca) True)) |
671 | 670 |
|
|
753 | 752 |
|
754 | 753 | (defn make-reference-slope-triangle [x-span y-span slope pattern |
755 | 754 | &optional [kwargs-plot None] |
756 | | - [kwargs-text None] |
757 | | - [opposite None]] |
| 755 | + [kwargs-text None]] |
758 | 756 | (assert (= 2 (len x-span))) |
759 | 757 | (assert (= 2 (len y-span))) |
760 | 758 | (svifn kwargs-plot {}) |
761 | 759 | (svifn kwargs-text {}) |
762 | | - (svifn opposite False) |
763 | 760 | (sv (, x0 x1) x-span (, y0 y1) y-span |
764 | | - dx (- x1 x0) dy (- y1 y0)) |
765 | | - (if opposite |
766 | | - (do (sv x [x0 x1 x1 x0] |
767 | | - y [y1 y1 y0 y1])) |
768 | | - (do (sv x [x0 x1 x0 x0] |
769 | | - y [y0 y0 y1 y0]))) |
| 761 | + dx (- x1 x0) dy (- y1 y0) |
| 762 | + x [x0 x1 x0 x0] y [y0 y0 y1 y0]) |
770 | 763 | (pl.plot #*[x y pattern] #**kwargs-plot) |
771 | | - (when opposite |
772 | | - (if (none? kwargs-text) (sv kwargs-text {})) |
773 | | - (assoc kwargs-text "horizontalalignment" "right" "verticalalignment" "top")) |
774 | | - (pl.text #*[(if opposite (- x1 (* 0.1 dx)) (+ x0 (* 0.1 dx))) |
775 | | - (if opposite (- y1 (* 0.1 dy)) (+ y0 (* 0.1 dy))) (str slope)] |
| 764 | + (pl.text #*[(+ x0 (* 0.1 dx)) (+ y0 (* 0.1 dy)) (str slope)] |
776 | 765 | #**kwargs-text)) |
777 | 766 |
|
778 | | - ) (except [] )) |
| 767 | + (defn frame-init [] |
| 768 | + (pl.show :block False)) |
| 769 | + (defn frame-flip [U &optional [clim None] [pause 0.05]] |
| 770 | + (pl.clf) |
| 771 | + (pl.imshow U :interpolation "none" :origin "lower") |
| 772 | + (unless (none? clim) |
| 773 | + (pl.clim clim)) |
| 774 | + (pl.tight-layout) |
| 775 | + (pl.pause pause)) |
779 | 776 |
|
780 | | -;;; More extensive unit tests. |
781 | | -(if-main |
782 | | - (expect |
783 | | - (case/eq 'hi |
784 | | - ('hit 'nope) |
785 | | - ('hi 'bark 'yep)) |
786 | | - 'yep) |
787 | | - (expect |
788 | | - (case/in 'hello |
789 | | - ['(bye hello) 'nope] |
790 | | - ('(hi) 'yep) |
791 | | - ('(4) 'another-nope)) |
792 | | - 'nope) |
793 | | - (expect |
794 | | - (case/in 'hi |
795 | | - ('(bye hello) 'nope) |
796 | | - ('(hi) 'yep) |
797 | | - ('(4) 'another-nope)) |
798 | | - 'yep) |
799 | | - (expect |
800 | | - (case/in 'hi |
801 | | - ('(bye hello) 'nope) |
802 | | - ('hi 'yep) |
803 | | - ('(4) 'another-nope)) |
804 | | - 'yep) |
805 | | - (expect |
806 | | - (case/test in 'hi |
807 | | - ('(bye hello) 'nope) |
808 | | - ('hi 'yep) |
809 | | - ('(4) 'another-nope)) |
810 | | - 'yep) |
811 | | - (expect (case/eq 4 [5 'bye] [4 'hi]) |
812 | | - 'hi) |
813 | | - (expect |
814 | | - (case/in 'hi |
815 | | - ('(bye hello) 'nope)) |
816 | | - None) |
817 | | - (expect |
818 | | - (case/in 'hi |
819 | | - ('(bye hello) 'nope) |
820 | | - (:else 'woot)) |
821 | | - 'woot) |
822 | | - (expect |
823 | | - (sdo (setv key 'hi) |
824 | | - (case/in key |
825 | | - ('(bye hello) 'nope) |
826 | | - ([key] 'yup))) |
827 | | - 'yup) |
828 | | - |
829 | | - (expect |
830 | | - (do |
831 | | - (sv a None b 4 c "hi" d None) |
832 | | - (svifn a "hi" b 3 c "bye") |
833 | | - (and (= a "hi") (= b 4) (= c "hi") (none? d)))) |
834 | | - (expect |
835 | | - (do |
836 | | - (sv a None) |
837 | | - (svifn a "hi") |
838 | | - (= a "hi"))) |
839 | | - (expect |
840 | | - (do |
841 | | - (sv a 5) |
842 | | - (svifn a "hi") |
843 | | - (= a 5))) |
844 | | - |
845 | | - (expect |
846 | | - (do (sv a 1 b "hi" c 'd) |
847 | | - (svb (ab 1) (bb "hi") (cb 'd)) |
848 | | - (and (= a ab) (= b bb) (= c cb)))) |
849 | | - |
850 | | - (when-inp ["test-pretty-print"] |
851 | | - (ppme '(case/in 'hi |
852 | | - (['hi 'bye] 'hi) |
853 | | - ('[foo] (for [d dinos] |
854 | | - (print (.format "{:s} goes {:d}" |
855 | | - d.name d.sound)))) |
856 | | - ('[bar] |
857 | | - (defn axis-tight-pad [&optional [pad 0.05] [mult False] |
858 | | - [foo 3]] |
859 | | - (pl.axis "tight") |
860 | | - (setv xl (pl.xlim) yl (pl.ylim)) |
861 | | - (pl.xlim (pad-lim xl pad mult)) |
862 | | - (pl.ylim (pad-lim yl pad mult))) |
863 | | - (axis-tight-pad))))) |
864 | | - |
865 | | - (when-inp ["ooa-from-file" {:fname str :anchor str :fieldno int}] |
866 | | - (sv (, errs ooas) (ooa-from-file fname fieldno :anchor anchor)) |
867 | | - (for [i (range (len errs))] |
868 | | - (prf "{:10.3e} {}" (get errs i) |
869 | | - (if (zero? i) " n/a" (.format "{:6.3f}" (get ooas (dec i))))))) |
870 | | -) |
| 777 | + ) (except [] )) |
0 commit comments