From 52c25ef5e891abd0a12ee1808362c70e1b3126b6 Mon Sep 17 00:00:00 2001
From: Tue Herlau <tuhe@dtu.dk>
Date: Wed, 24 Mar 2021 22:24:42 +0100
Subject: [PATCH] Update with new norm test and easier pre-computed test
 building

---
 unitgrade/__init__.py                         |   9 +++-
 unitgrade/__pycache__/__init__.cpython-38.pyc | Bin 1125 -> 1369 bytes
 .../__pycache__/unitgrade.cpython-38.pyc      | Bin 13332 -> 13887 bytes
 .../unitgrade_helpers.cpython-38.pyc          | Bin 6555 -> 6604 bytes
 unitgrade/unitgrade.py                        |  45 +++++++++++++++---
 unitgrade/unitgrade_helpers.py                |  12 ++---
 unitgrade/version.py                          |   2 +-
 7 files changed, 53 insertions(+), 15 deletions(-)

diff --git a/unitgrade/__init__.py b/unitgrade/__init__.py
index 605eedf..f590541 100644
--- a/unitgrade/__init__.py
+++ b/unitgrade/__init__.py
@@ -23,8 +23,13 @@ def cache_read(file_name):
     import compress_pickle # Import here because if you import in top the __version__ tag will fail.
     # file_name = cn_(file_name) if cache_prefix else file_name
     if os.path.exists(file_name):
-        with open(file_name, 'rb') as f:
-            return compress_pickle.load(f, compression="lzma")
+        try:
+            with open(file_name, 'rb') as f:
+                return compress_pickle.load(f, compression="lzma")
+        except Exception as e:
+            print("Tried to load a bad pickle file at", file_name)
+            print("If the file appears to be automatically generated, you can try to delete it, otherwise download a new version")
+            print(e)
             # return pickle.load(f)
     else:
         return None
diff --git a/unitgrade/__pycache__/__init__.cpython-38.pyc b/unitgrade/__pycache__/__init__.cpython-38.pyc
index dc097231ab1cc676f96b6e553c3f3a9d29cccfee..1e78fe7d5e0b0725357397a89d63a7266b1f0aa7 100644
GIT binary patch
delta 646
zcmaFLag&QLl$V!_fq{YH;IGhxa@LJ}HjIo>lf4<M_}Lg37^0X`@@_Gvtz;+?o_vKd
zol$hM4U@4VI|Bnl5eJ9>>C|K_5&*G<;e^QK2~4t1Vhjun$&4VQp_qk%fdQn!nSp_!
zxQ~H>A%!u8A%~%sv4k;;X#sN$!$QWQwko3%mKuf>re>yoxyf&tr0T;Nf*ArCf*2wg
z!Wjy?SQtv!vbl<y7#V7r85yeNO4w6aYZ#iD7#T{~Q`njrL39l>hz@5kWk_MDWv*k6
zV2ETW?22H>V@Y8MW&mMLcE2K!%c7Wyl8QjiDq>||V5m|GDauSuQ7Fk*$jMJkQAkus
zN=&I&D9B9C&Pi2B%gjktNGz$!^-NPJ$$;?-3Q`k`ia}bEQWX+QOY(CQOEQxab8;#b
z(o^$NixNvxQ*;z6^Gg+y6Y~^GiYh@$Q&MwMOHvgwOLP?SOEOZ6$}@{o6;krc^Ptw|
zrIss{r4|)u=I3eFa}<Fhq6jt2i+C9r7;dqE)ZgNCtw>HSD9OyvE8<~bV9;cNL<d-x
z5J(wgY7tW0fJC^G6O%Ji<BL)gQ$Vp)ECPxlMh+$(MkYocMm0tOMlMDUMj7TJDTc|D
zm}A1hmWzVo7o@yM3S@?GX<lYYdQoCZsvewGBn?s{10rNWgdB*F2N4P&0^tfUOJuSu
Ii##Jg03hv=hyVZp

delta 379
zcmcb~^^}7zl$V!_fq{Wx&$OU~WR{J5HjIq7CVMkh@v}29Fx+BF$-BjvwvwSpbn+F(
zbVl*XHcZBf91IK$MVugln}LBrld(t;#1@4UVv{E@$vQ|dFfb%Df{cb@W(EcZkX6nM
z3=G9y3=9k@j42E`47H3Uj9E+zm}?joG8Q?Nu+%W5Ff}vv%S?XHBvl{G5Xcb35W$eg
zlEM(o0K%HAenlWtZ!r}m6|sQqWCb~btqA1aB2=dp@qzrnl9Qj9qR9+#C0LaRNE?!S
zL8`ct6O%Ji<BL)gQ^Y_H1i6%fn~{TwhmnU-iMdF6aw|)$2H1RYkam#wiliAB7@~wr
i^D;})ixN{(_28_@{H#)<iXe3eYrrhA$(F40j9dW6P(%p;

diff --git a/unitgrade/__pycache__/unitgrade.cpython-38.pyc b/unitgrade/__pycache__/unitgrade.cpython-38.pyc
index 5601367584ffb2dd33f99e057b47d73958c6bf42..be8062ad9576348beec485019d587f4c0f1b248f 100644
GIT binary patch
delta 2762
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

delta 2208
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
Haqs{DkJbi*

diff --git a/unitgrade/__pycache__/unitgrade_helpers.cpython-38.pyc b/unitgrade/__pycache__/unitgrade_helpers.cpython-38.pyc
index d7f1dcc24f9053facd9ab6146edd241ac30a3ca1..e83dce19af0550bd9e960167059ea3b304191b28 100644
GIT binary patch
delta 1051
zcmbPje8!kJl$V!_fq{V`DJLvp<wo9{tb9BS3=G^13=GZ;3=G9qlfSS&a~E15Tq3kU
zWFf;s#uP3|hAh!qt`gQPwgqA}Tniaf7*e=fnIsufc*GfMxxwP%HQWmsComS7l?bHp
zHZw9ZlnA8o)o^d-XWz#t`jU}>f#K!f|NsA2amJ??C8nh66;w_>%aO=h#cXG1H`#+z
zn^9tN3FkfaTWqNnnZ+f=nmo7Iic$;mi%N=Q7#J9e<UoWnh)`f)V7N88kjsiaiZwkg
zGbeTOYA#(ylgT%^wD_4s7$q3_7&#cZ7&#b=947N|zhaD@{F6IZFcRc5HjuBGgc!LP
zi@YY6^T;vEOrFMbjIm*IEN?oa+2o_Vj*JGA+4+L`AJoV%kX^{Y$WS7eCBHynay*~7
zzTyI<65a*83mIzUBp6bp7BbZ;mT;s<mnf$&)(DlT)JQfnN-#7ti7=$dh%=O^PF~6<
z&!{%}D4(KoMu~WhOqN8AQi^CVQ>}cSS_wyuQi=jZXNsZ(Ly5{{PJZor^%~Y1wi@;t
z<{HivrC!z;rdrinwHnzPwHnnLl@iq&nJkTF#u}L{t`y}tY&B9f(l!hwn66T<;hMl)
zq=o7OuwO82tx<-#S)3t-fAVI2QGUA=l{}^t)mr5m<rJ9`)ydcSJsDR`RustORH@Md
zsV-5OJXzo=ziJIbmPj+BI75mC*thM1`xw(Ey9wRl3uRzn&}1wE#Z^d=>tqArP;N(1
zyg7jg=gAX<#Y{sO7#N~h0vv;btGKkZv=rPNJ$+nVG}(%f6oO)zHM1l&x3~xtcSRwS
zZwohw1b_{{#avucq{&p|0x~jga=u6oW7On3BIS%BlS4$kxFI%y<f1396g6WEo%}#l
zO6L}Hab@u>w&IeM{L+$JtZ6x=#TiBJU~7u<OY>50G3O>$6#0U*#ZMLzQ)4Rfn(QYg
z%V;?{N6g$T0wgXAB0yQEC<EjJp2Xth%*^<t#Js%JqFanfQJg6y@x>)YnR)3&aUi9(
zlW&SCFgi~DC1%MOI@v^ANgm{tTkOfDMMbH3B}E{IMzNL@rzRKQVk$2#a-Li&uEA(C
zd7ij9TOugIZkoJX+)0&@jfszuhe?1@h>;DPwt1M?7)6-07(uiQ6C0xdlN#e>1&IPt
ykavohKvpw@h)fVsI(eyt8CxZYnK${NgdcZ2i0J?#ye3;oMzJe%a4;}3{09KrWeY(7

delta 1003
zcmX?OJlmKzl$V!_fq{Xcc6v~P=SJR}tbE)I3=AOb%)r1<tTFiu>oZe<6s~4QMurlh
z1;Qml3q%$&EM!dKmSo5ht>r2aNZ~1A&0<?1R>QTBF@+(8x0OkfA%#zzVY4FpKE}yk
zI1;5^GBPkQR59Dx*}eSx|Ns9g&iM4A#FSLMg38HJoZ5`yliN7&F==v7&f}6{jGEld
zWi|N>moB5h<X>D`+>9JdB8+m39E?SFla0AwF-A_7<H;2a2f2+6<ZdP*MlQx8kI8d*
z<QRn}@8&tiST?zdH=R*u@+)3PMzzU0e8H^OYUCHlPVVCq_m^8BU&6b9cOgTKoCHIP
z)Iz3O#S)Gb=@Nw$#u}j##Tv<GMhS*yCJ}}d8F7XZr5eR%MsbD|S#bui_c>DJYJ^0<
z>>9BenRw;NU-%T2<4VM9WU?e`lu|@{nQG<p)JiyNlu{HRW~L}gFq9}xw&2&USE*sG
zVXI-UVXom!QR-!lVX9TFRjZM$QL9m{Q7KWXk;zhRW~`CP;!07T!&W0zBW=S_g6UrM
z8m<Y<MG7DvEo5M1C{fE&U!VbIVc1%u4D*dRLkj=oNBpAvCMha;Oew0h$~DR<G9^lr
z*#tZp7fcQi$mCS4(E_P1QJj28;3>aS4MUa)*zX#kaG1PJa35pJ<WiwKe8CJ144RBZ
z$_xw)Aw|xU<Ap=H?HL#tiX1?M<K+FqVx~b13=B~$0gl1JRa{zHS_*ECo<6QFnruZ#
z3K<v}Zn0*Tq~;bEf#R|#Xfl^bgNPs4@LSBqB}JM{MNS|iV<yiN$zi-TnOn4+F=%qL
zs24ZHCXig@<Qt-9jKP!n#iS&PT){>b<(KBA++xm6tSIsZDT$pNDyAlOi@CV6_!e7n
zNlJcc$t~8joYLZqB9F<nVzP`DlV^*Wn}vbY%7O?`W++Mr`G6;}I5{&jJ}EITFSY0v
zV^S1nN=bZiNl|8AdQl8Wsr6(IaRo;E$(rJpjKPzW#g*hiUb)4dTv}9=npXl2k|@@a
z;?(5gTTJD}MUIn~h-)xfO+G6w&K3_!z#AsN5_eK&Vq@ZC<Y5wE6k=p!<Y44sVq+9x
z)&kQqOl*t-OlnM%10@PXK^`n(0$I!qA~HZk$>eJiW^6SeX6|GmNk8sb5YrAscudZg
OjAB>h;9y{6_zwWM4*Sah

diff --git a/unitgrade/unitgrade.py b/unitgrade/unitgrade.py
index e57ccbc..e100673 100644
--- a/unitgrade/unitgrade.py
+++ b/unitgrade/unitgrade.py
@@ -94,6 +94,17 @@ class QItem(unittest.TestCase):
         if self.title is None:
             self.title = self.name
 
+    def assertNorm(self, computed, expected, tol=None):
+        if tol == None:
+            tol = self.tol
+        diff = np.abs( (np.asarray(computed).flat- np.asarray(expected)).flat )
+        nrm = np.sum( diff ** 2)
+
+        if nrm > tol:
+            print(f"Not equal within tolerance {tol}; norm of difference was {nrm}")
+            print(f"Element-wise differences {diff.tolist()}")
+            self.assertEqual(computed, expected, msg=f"Not equal within tolerance {tol}")
+
     def assertL2(self, computed, expected, tol=None):
         if tol == None:
             tol = self.tol
@@ -332,24 +343,46 @@ class ActiveProgress():
         self.t = t
         self._running = False
         self.title = title
+        self.dt = 0.1
+
+        self.n = int(np.round(self.t / self.dt))
+        # self.pbar = tqdm.tqdm(total=self.n)
+
+
         if start:
             self.start()
 
     def start(self):
         self._running = True
-        self.thread = threading.Thread(target=self.run, args=(10,))
+        self.thread = threading.Thread(target=self.run)
         self.thread.start()
 
     def terminate(self):
+
+
         self._running = False
         self.thread.join()
+        if hasattr(self, 'pbar') and self.pbar is not None:
+            self.pbar.update(1)
+            self.pbar.close()
+            self.pbar=None
+
         sys.stdout.flush()
 
-    def run(self, n):
-        dt = 0.1
+    def run(self):
+        self.pbar = tqdm.tqdm(total=self.n, file=sys.stdout, position=0, leave=False, desc=self.title, ncols=100,
+                              bar_format='{l_bar}{bar}| [{elapsed}<{remaining}]')  # , unit_scale=dt, unit='seconds'):
 
-        n = int(np.round(self.t/dt))
-        for _ in tqdm.tqdm(range(n), file=sys.stdout, position=0, leave=False, desc=self.title, ncols=100, bar_format='{l_bar}{bar}| [{elapsed}<{remaining}]'): #, unit_scale=dt, unit='seconds'):
+        for _ in range(self.n-1): # Don't terminate completely; leave bar at 99% done until terminate.
             if not self._running:
+                self.pbar.close()
+                self.pbar = None
                 break
-            time.sleep(dt)
\ No newline at end of file
+
+            time.sleep(self.dt)
+            self.pbar.update(1)
+
+        # if self.pbar is not None:
+        #     self.pbar.close()
+        #     self.pbar = None
+        # for _ in tqdm.tqdm(range(n), file=sys.stdout, position=0, leave=False, desc=self.title, ncols=100, bar_format='{l_bar}{bar}| [{elapsed}<{remaining}]'): #, unit_scale=dt, unit='seconds'):
diff --git a/unitgrade/unitgrade_helpers.py b/unitgrade/unitgrade_helpers.py
index 5edd3ee..c73c496 100644
--- a/unitgrade/unitgrade_helpers.py
+++ b/unitgrade/unitgrade_helpers.py
@@ -76,11 +76,13 @@ def evaluate_report_student(report, question=None, qitem=None, unmute=None, pass
         table = table_data
         print(tabulate(table))
         print(" ")
-    print("Note your results have not yet been registered. \nTo register your results, please run the file:")
 
     fr = inspect.getouterframes(inspect.currentframe())[1].filename
-    print(">>>", os.path.basename(fr)[:-3] + "_grade.py")
-    print("In the same manner as you ran this file.")
+    gfile = os.path.basename(fr)[:-3] + "_grade.py"
+    if os.path.exists(gfile):
+        print("Note your results have not yet been registered. \nTo register your results, please run the file:")
+        print(">>>", gfile)
+        print("In the same manner as you ran this file.")
     return results
 
 
@@ -133,7 +135,6 @@ def evaluate_report(report, question=None, qitem=None, passall=False, verbose=Fa
                 start = time.time()
 
                 cc = None
-
                 if show_progress_bar:
                     # cc.start()
                     cc = ActiveProgress(t=q.estimated_time, title=q_title_print)
@@ -143,12 +144,12 @@ def evaluate_report(report, question=None, qitem=None, passall=False, verbose=Fa
                     q.init() # Initialize the question. Useful for sharing resources.
                 if show_progress_bar:
                     cc.terminate()
+                    sys.stdout.flush()
                     print(q_title_print, end="")
 
                 q.has_called_init_ = True
                 q_time =np.round(  time.time()-start, 2)
 
-
                 print(" "* max(0,nL - len(q_title_print) ) + " (" + str(q_time) + " seconds)") # if q.name in report.payloads else "")
                 print("=" * nL)
 
@@ -159,7 +160,6 @@ def evaluate_report(report, question=None, qitem=None, passall=False, verbose=Fa
                 cc = ActiveProgress(t=item.estimated_time, title=item_title_print)
             else:
                 print(item_title_print + ( '.'*max(0, nL-4-len(ss)) ), end="")
-
             hidden = issubclass(item.__class__, Hidden)
             # if not hidden:
             #     print(ss, end="")
diff --git a/unitgrade/version.py b/unitgrade/version.py
index acf3be3..51e0a06 100644
--- a/unitgrade/version.py
+++ b/unitgrade/version.py
@@ -1 +1 @@
-__version__ = "0.1.3"
\ No newline at end of file
+__version__ = "0.1.4"
\ No newline at end of file
-- 
GitLab