From 4c84494f3540feddba9c45bc3d9197a45a804ba0 Mon Sep 17 00:00:00 2001 From: Laura Mendoza Date: Mon, 28 Oct 2019 17:44:44 +0100 Subject: [PATCH 01/16] [doc] adding contributing guidelines --- doc/source/contributing.rst | 12 ++++++++++++ doc/source/index.rst | 1 + doc/source/tofu.data.rst | 8 ++++++++ doc/source/tofu.rst | 1 + examples/tutorials/plot_basic_tutorial.py | 14 +++++++------- 5 files changed, 29 insertions(+), 7 deletions(-) create mode 100644 doc/source/contributing.rst diff --git a/doc/source/contributing.rst b/doc/source/contributing.rst new file mode 100644 index 000000000..ac8543664 --- /dev/null +++ b/doc/source/contributing.rst @@ -0,0 +1,12 @@ +Contributing +============ + +Bug reports, requests, ideas +---------------------------- + +If you found a bug in **tofu**, or if you a suggestion, the best is to open +an issue directly on our `github page `_. +If you are opening an issue related to a bug found, please specify the version +of **tofu** you are using, any configuration information that might be helpful +for us to create your issue, a minimal example to recreate the bug (if possible), +and the log files or errors you might have got. diff --git a/doc/source/index.rst b/doc/source/index.rst index 943865847..0a3be6232 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -57,6 +57,7 @@ Contents: :maxdepth: 1 How to install tofu + How to contribute All tutorials and examples * How to create / handle a diagnostic geometry diff --git a/doc/source/tofu.data.rst b/doc/source/tofu.data.rst index a294cb363..8f0f4f2cf 100644 --- a/doc/source/tofu.data.rst +++ b/doc/source/tofu.data.rst @@ -20,6 +20,14 @@ tofu.data.\_core module :undoc-members: :show-inheritance: +tofu.data.\_core\_new module +---------------------------- + +.. automodule:: tofu.data._core_new + :members: + :undoc-members: + :show-inheritance: + tofu.data.\_def module ---------------------- diff --git a/doc/source/tofu.rst b/doc/source/tofu.rst index 0ad09fb31..9e8466a9d 100644 --- a/doc/source/tofu.rst +++ b/doc/source/tofu.rst @@ -10,6 +10,7 @@ Subpackages tofu.dumpro tofu.dust tofu.geom + tofu.tests Submodules ---------- diff --git a/examples/tutorials/plot_basic_tutorial.py b/examples/tutorials/plot_basic_tutorial.py index 14b2b4a85..df12320e7 100644 --- a/examples/tutorials/plot_basic_tutorial.py +++ b/examples/tutorials/plot_basic_tutorial.py @@ -5,9 +5,8 @@ This is a tutorial that aims to get a new user a little familiar with tofu's structure. """ -import matplotlib import matplotlib.pyplot as plt -matplotlib.use('Qt5Agg') +import numpy as np ############################################################################### # We start by loading `tofu`. You might see some warnings at this stage since @@ -18,8 +17,9 @@ ############################################################################### # We can now create our first configuration. -# In `tofu` speak, a configuration is the geometry of the device and its structures. -# `tofu` provides pre-defined ones for your to try, so we're going to do just that: +# In `tofu` speak, a configuration is the geometry of the device and its +# structures. `tofu` provides pre-defined ones for your to try, so we're going +# to do just that: configB2 = tf.geom.utils.create_config("B2") @@ -29,9 +29,8 @@ configB2.plot() ############################################################################### -# Since `tofu` is all about tomography, let's create a 1D camera and plot its output. - -import numpy as np +# Since `tofu` is all about tomography, let's create a 1D camera and plot its +# output. cam1d = tf.geom.utils.create_CamLOS1D( config=configB2, @@ -44,6 +43,7 @@ Exp="", Diag="", ) +plt.clf() # interactive plot cam1d.plot_touch() From 5d5955eb9bff0b0f8acd3bdbd1645c147eb2cf90 Mon Sep 17 00:00:00 2001 From: Laura Mendoza Date: Tue, 29 Oct 2019 11:38:00 +0100 Subject: [PATCH 02/16] [bug] fixed conad packaging fail for py2 + blacked --- benchmarks/calc_signal_benchmark.py | 432 ++++++++++++++++++---------- 1 file changed, 273 insertions(+), 159 deletions(-) diff --git a/benchmarks/calc_signal_benchmark.py b/benchmarks/calc_signal_benchmark.py index 14e6b89b1..093791881 100644 --- a/benchmarks/calc_signal_benchmark.py +++ b/benchmarks/calc_signal_benchmark.py @@ -1,34 +1,37 @@ #!/usr/bin/env python +# Python 2 and 3 compatibility +from __future__ import print_function + # Built-in import os import sys import argparse # Common +import socket +import getpass import datetime as dtm import numpy as np import matplotlib.pyplot as plt -from mpl_toolkits.mplot3d import Axes3D -import socket -import getpass # tofu # test if in a tofu git repo _HERE = os.path.abspath(os.path.dirname(__file__)) istofugit = False heresplit = _HERE.split(os.path.sep) -if 'benchmarks' in heresplit: - ind = heresplit[::-1].index('benchmarks') - pp = os.path.sep + os.path.join(*heresplit[:-ind-1]) +if "benchmarks" in heresplit: + ind = heresplit[::-1].index("benchmarks") + pp = os.path.sep + os.path.join(*heresplit[: -ind - 1]) lf = os.listdir(pp) - if '.git' in lf and 'tofu' in lf: + if ".git" in lf and "tofu" in lf: istofugit = True if istofugit: # Make sure we load the corresponding tofu - sys.path.insert(1,pp) + sys.path.insert(1, pp) import tofu as tf + _ = sys.path.pop(1) else: import tofu as tf @@ -50,29 +53,33 @@ _DRES = abs(_LRES[1] - _LRES[0]) _DLOS = abs(_LLOS[1] - _LLOS[0]) _DT = abs(_LT[1] - _LT[0]) -_RES = np.logspace(_LRES[0], _LRES[1], _LRES[2]*_DRES + _DRES + 1 , - base=10) -_NLOS = np.round(np.logspace(_LLOS[0], _LLOS[1], _LLOS[2]*_DLOS + _DLOS + 1, - base=10)) -_NT = np.round(np.logspace(_LT[0], _LT[1], _LT[2]*_DT + _DT + 1, base=10)) +_RES = np.logspace(_LRES[0], _LRES[1], _LRES[2] * _DRES + _DRES + 1, base=10) +_NUMTOT = _LLOS[2] * _DLOS + _DLOS + 1 +_NLOS = np.round(np.logspace(_LLOS[0], _LLOS[1], _NUMTOT, base=10)) +_NT = np.round(np.logspace(_LT[0], _LT[1], _LT[2] * _DT + _DT + 1, base=10)) _SHOT = 54178 -_IDS = ['core_profiles', 'equilibrium', 'core_sources'] -_QUANT = 'core_profiles.1dne' -_REF1D = 'core_profiles.1drhotn' -_REF2D = 'equilibrium.2drhotn' -_DALGO = {'ref-sum':{'newcalc':False}, - 'calls-sum': {'newcalc':True, 'minimize':'calls', 'method':'sum'}, - # 'calls-simps': {'newcalc':True, 'minimize':'calls', 'method':'simps'}, - # 'calls-romb': {'newcalc':True, 'minimize':'calls', 'method':'romb'}, - 'hybrid-sum': {'newcalc':True, 'minimize':'hybrid', 'method':'sum'}, - # 'hybrid-simps': {'newcalc':True, 'minimize':'hybrid', 'method':'simps'}, - # 'hybrid-romb': {'newcalc':True, 'minimize':'hybrid', 'method':'romb'}, - 'memory-sum': {'newcalc':True, 'minimize':'memory', 'method':'sum'}, - # 'memory-simps': {'newcalc':True, 'minimize':'memory', 'method':'simps'}, - # 'memory-romb': {'newcalc':True, 'minimize':'memory', 'method':'romb'}, - } -_DCAM = {'P':[3.4,0.,0.], 'F':0.1, 'D12':0.1, - 'angs':[1.05*np.pi, np.pi/4, np.pi/4]} +_IDS = ["core_profiles", "equilibrium", "core_sources"] +_QUANT = "core_profiles.1dne" +_REF1D = "core_profiles.1drhotn" +_REF2D = "equilibrium.2drhotn" +_DALGO = { + "ref-sum": {"newcalc": False}, + "calls-sum": {"newcalc": True, "minimize": "calls", "method": "sum"}, + # 'calls-simps': {'newcalc':True, 'minimize':'calls', 'method':'simps'}, + # 'calls-romb': {'newcalc':True, 'minimize':'calls', 'method':'romb'}, + "hybrid-sum": {"newcalc": True, "minimize": "hybrid", "method": "sum"}, + # 'hybrid-simps': {'newcalc':True, 'minimize':'hybrid', 'method':'simps'}, + # 'hybrid-romb': {'newcalc':True, 'minimize':'hybrid', 'method':'romb'}, + "memory-sum": {"newcalc": True, "minimize": "memory", "method": "sum"}, + # 'memory-simps': {'newcalc':True, 'minimize':'memory', 'method':'simps'}, + # 'memory-romb': {'newcalc':True, 'minimize':'memory', 'method':'romb'}, +} +_DCAM = { + "P": [3.4, 0.0, 0.0], + "F": 0.1, + "D12": 0.1, + "angs": [1.05 * np.pi, np.pi / 4, np.pi / 4], +} _PATH = _HERE _FUNC = True @@ -80,35 +87,57 @@ _SAVE = True _PLOT = False -_FS = (14,10) -_DMARGIN = {'left':0.05, 'right':0.95, - 'bottom':0.05, 'top':0.95, - 'wspace':0.1, 'hspace':0.1} - +_FS = (14, 10) +_DMARGIN = { + "left": 0.05, + "right": 0.95, + "bottom": 0.05, + "top": 0.95, + "wspace": 0.1, + "hspace": 0.1, +} ################### # Emissivity ################### + def emiss(pts, t=None, vect=None): - r, z = np.hypot(pts[0,:],pts[1,:]), pts[2,:] - e = np.exp(-(r-2.4)**2/0.2**2 - z**2/0.2**2) + r, z = np.hypot(pts[0, :], pts[1, :]), pts[2, :] + e = np.exp(-(r - 2.4) ** 2 / 0.2 ** 2 - z ** 2 / 0.2 ** 2) if t is not None: - e = np.cos(np.atleast_1d(t))[:,None] * e[None,:] + e = np.cos(np.atleast_1d(t))[:, None] * e[None, :] return e + ################### # Main function ################### -def benchmark(config=None, func=_FUNC, plasma=None, shot=None, ids=None, - quant=None, ref1d=None, ref2d=None, - res=None, nlos=None, nt=None, t=None, - dalgo=None, nrep=None, txtfile=None, - path=None, name=None, nameappend=None, - plot=_PLOT, save=_SAVE): +def benchmark( + config=None, + func=_FUNC, + plasma=None, + shot=None, + ids=None, + quant=None, + ref1d=None, + ref2d=None, + res=None, + nlos=None, + nt=None, + t=None, + dalgo=None, + nrep=None, + txtfile=None, + path=None, + name=None, + nameappend=None, + plot=_PLOT, + save=_SAVE, +): # -------------- # Prepare inputs @@ -135,7 +164,7 @@ def benchmark(config=None, func=_FUNC, plasma=None, shot=None, ids=None, if t is None: if nt is None: nt = _NT - lt = [np.linspace(0,100,ntt) for ntt in nt] + lt = [np.linspace(0, 100, ntt) for ntt in nt] else: lt = [np.atleast_1d(t).ravel()] nnt = len(lt) @@ -143,14 +172,18 @@ def benchmark(config=None, func=_FUNC, plasma=None, shot=None, ids=None, if path is None: path = _PATH if name is None: - lvar = [('nalgo',nalgo), ('nnlos',nnlos), - ('nres',nres), ('nnt',nnt), - ('Host',socket.gethostname()), ('USR',getpass.getuser())] - name = 'benchmark_LOScalcsignal_' - name += '_'.join(['%s%s'%(nn,vv) - for nn,vv in lvar]) + lvar = [ + ("nalgo", nalgo), + ("nnlos", nnlos), + ("nres", nres), + ("nnt", nnt), + ("Host", socket.gethostname()), + ("USR", getpass.getuser()), + ] + name = "benchmark_LOScalcsignal_" + name += "_".join(["%s%s" % (nn, vv) for nn, vv in lvar]) if nameappend is not None: - name += '_'+nameappend + name += "_" + nameappend # printing file stdout = False @@ -158,21 +191,20 @@ def benchmark(config=None, func=_FUNC, plasma=None, shot=None, ids=None, txtfile = sys.stdout stdout = True elif type(txtfile) is str: - txtfile = open(os.path.join(path,txtfile), 'w') + txtfile = open(os.path.join(path, txtfile), "w") elif txtfile is True: - txtfile = open(os.path.join(path,name+'.txt'), 'w') - msg = "\ntofu %s loaded from:\n %s\n"%(tfversion,tforigin) + txtfile = open(os.path.join(path, name + ".txt"), "w") + msg = "\ntofu %s loaded from:\n %s\n" % (tfversion, tforigin) print(msg, file=txtfile) - # config if config is None: - config = 'B2' + config = "B2" if type(config) is str: config = tf.geom.utils.create_config(config) # func vs plasma - if func == True: + if func is True: func = emiss elif func is None: if plasma is None: @@ -189,7 +221,7 @@ def benchmark(config=None, func=_FUNC, plasma=None, shot=None, ids=None, ref1d = _REF1D ref2d = _REF2D - #--------------- + # --------------- # Prepare output # data @@ -198,95 +230,135 @@ def benchmark(config=None, func=_FUNC, plasma=None, shot=None, ids=None, memerr = np.zeros((nalgo, nnlos, nres, nnt), dtype=bool) win = np.zeros((nnlos, nres, nnt), dtype=int) - #--------------- + # --------------- # Prepare saving params if save: - pfe = os.path.join(path,name+'.npz') - lk = ['tforigin', 'tfversion', 't_std', 'nnt', 'lt', 'nalgo', 'nres', - 'name', 'path', 'save', 'plot', 'nrep', 'dalgo', 't', 'nt', - 'res', 'ref2d', 'ref1d', 'quant', 'ids', 'shot', - 'win', 't_av', 'nnlos', 'nlos', 'ncase', 'lalgo'] - - #------------ + pfe = os.path.join(path, name + ".npz") + lk = [ + "tforigin", + "tfversion", + "t_std", + "nnt", + "lt", + "nalgo", + "nres", + "name", + "path", + "save", + "plot", + "nrep", + "dalgo", + "t", + "nt", + "res", + "ref2d", + "ref1d", + "quant", + "ids", + "shot", + "win", + "t_av", + "nnlos", + "nlos", + "ncase", + "lalgo", + ] + + # ------------ # Start loop - names = np.array([['%s los = %s'%(lalgo[ii],int(nlos[jj])) - for jj in range(nnlos)] - for ii in range(nalgo)]) + names = np.array( + [ + ["%s los = %s" % (lalgo[ii], int(nlos[jj])) for jj in range(nnlos)] + for ii in range(nalgo) + ] + ) lennames = np.max(np.char.str_len(names)) - msg = "\n###################################"*2 + msg = "\n###################################" * 2 msg += "\nBenchmark about to be run with:" msg += "\n-------------------------------\n\n" - msg += "lalgo = %s\n"%str(lalgo) - msg += "nlos = %s\n"%str(nlos) - msg += "res = %s\n"%str(res) - msg += "nt = %s\n"%str(nt) - msg += "rep = %s\n\n"%str(nrep) - msg += " algo:".ljust(lennames) + ' times:' + msg += "lalgo = %s\n" % str(lalgo) + msg += "nlos = %s\n" % str(nlos) + msg += "res = %s\n" % str(res) + msg += "nt = %s\n" % str(nt) + msg += "rep = %s\n\n" % str(nrep) + msg += " algo:".ljust(lennames) + " times:" print(msg, file=txtfile) err0 = None for ii in range(nalgo): - print('', file=txtfile, flush=True) + print("", file=txtfile, flush=True) for jj in range(nnlos): - cam = tf.geom.utils.create_CamLOS1D(N12=nlos[jj], - config=config, - Name=str(names[ii,jj]), Exp='dummy', - Diag='Dummy', - **_DCAM) - msg = " %s"%(names[ii,jj].ljust(lennames)) + cam = tf.geom.utils.create_CamLOS1D( + N12=nlos[jj], + config=config, + Name=str(names[ii, jj]), + Exp="dummy", + Diag="Dummy", + **_DCAM + ) + msg = " %s" % (names[ii, jj].ljust(lennames)) print(msg, file=txtfile, flush=True) for ll in range(nres): - msg = " res %s/%s"%(ll+1, nres) + msg = " res %s/%s" % (ll + 1, nres) for tt in range(nnt): dt = np.zeros((nrep,)) for rr in range(nrep): if stdout: - msgi = "\r" + msg + " nt %s/%s rep %s/%s"%(tt+1,nnt,rr+1,nrep) - print(msgi, end='', file=txtfile, flush=True) + msgi = ( + "\r" + msg + " nt %s/%s rep %s/%s" + % (tt + 1, nnt, rr + 1, nrep) + ) + print(msgi, end="", file=txtfile, flush=True) try: if func is None: t0 = dtm.datetime.now() - _ = cam.calc_signal_from_Plasma2D(plasma, - quant=quant, - ref1d=ref1d, - ref2d=ref2d, - res=res[ll], - resMode='abs', - plot=False, - t = lt[tt], - **dalgo[lalgo[ii]]) - dt[rr] = (dtm.datetime.now()-t0).total_seconds() + _ = cam.calc_signal_from_Plasma2D( + plasma, + quant=quant, + ref1d=ref1d, + ref2d=ref2d, + res=res[ll], + resMode="abs", + plot=False, + t=lt[tt], + **dalgo[lalgo[ii]] + ) + tm_now = dtm.datetime.now() + dt[rr] = (tm_now - t0).total_seconds() else: t0 = dtm.datetime.now() - _ = cam.calc_signal(func, res=res[ll], - resMode='abs', plot=False, - t = lt[tt], - **dalgo[lalgo[ii]]) - dt[rr] = (dtm.datetime.now()-t0).total_seconds() - except MemoryError as err: + _ = cam.calc_signal( + func, + res=res[ll], + resMode="abs", + plot=False, + t=lt[tt], + **dalgo[lalgo[ii]] + ) + tm_now = dtm.datetime.now() + dt[rr] = (tm_now - t0).total_seconds() + except MemoryError: dt[rr] = -1 - memerr[ii,jj,ll,tt] = True + memerr[ii, jj, ll, tt] = True except Exception as err: if err0 is None: err0 = err - t_av[ii,jj,ll,tt] = np.mean(dt) - t_std[ii,jj,ll,tt] = np.std(dt) + t_av[ii, jj, ll, tt] = np.mean(dt) + t_std[ii, jj, ll, tt] = np.std(dt) - msgi = msg + ': %s'%str(t_av[ii,jj,ll,:]) + msgi = msg + ": %s" % str(t_av[ii, jj, ll, :]) if stdout: - msgi = '\r'+msgi + msgi = "\r" + msgi print(msgi, file=txtfile, flush=True) if save: - out = {kk:vv for kk,vv in locals().items() if kk in lk} + out = {kk: vv for kk, vv in locals().items() if kk in lk} np.savez(pfe, **out) print(" (saved)", file=txtfile) - - t_av[memerr] = np.nan win = np.nanargmin(t_av, axis=0) ncase = win.size @@ -295,37 +367,46 @@ def benchmark(config=None, func=_FUNC, plasma=None, shot=None, ids=None, ln = np.max([len(aa) for aa in lalgo]) msg = "\n --------------------\n --- Synthesis ---" msg += "\n\n Speed score:\n " - msg += "\n ".join(["%s : %s"%(lalgo[ii].ljust(ln), - 100.*np.sum(win==ii)/ncase) +' %' - for ii in range(nalgo)]) + msg += "\n ".join( + ["%s : %s" % (lalgo[ii].ljust(ln), + 100.0 * np.sum(win == ii) / ncase) + " %" + for ii in range(nalgo) + ] + ) winname = np.char.rjust(np.asarray(lalgo)[win], ln) - lsblocks = ['nlos = %s'%str(nlos[jj]) + "\n " - + "\n ".join([('res %s/%s '%(ll,nres) - + str(winname[jj,ll,:])) - for ll in range(nres)]) - for jj in range(nnlos)] - msg += "\n" + "\n " + "\n ".join(lsblocks) - + lsblocks = [ + "nlos = %s" % str(nlos[jj]) + "\n \n ".join( + [ + ("res %s/%s " % (ll, nres) + str(winname[jj, ll, :])) + for ll in range(nres) + ] + ) + for jj in range(nnlos) + ] + msg += "\n" + "\n " + "\n ".join(lsblocks) msg += "\n\n Memory score:\n " - msg += "\n ".join(["%s : %s"%(lalgo[ii].ljust(ln), - 100.*np.sum(t_av[ii,...]>=0)/ncase) + ' %' - for ii in range(nalgo)]) + msg += "\n ".join( + [ + "%s : %s" + % (lalgo[ii].ljust(ln), + 100.0 * np.sum(t_av[ii, ...] >= 0) / ncase) + " %" + for ii in range(nalgo) + ] + ) print(msg, file=txtfile) - if err0 is not None: raise err0 - #------------- + # ------------- # Plot / save - if save: - out = {kk:vv for kk,vv in locals().items() if kk in lk} + out = {kk: vv for kk, vv in locals().items() if kk in lk} np.savez(pfe, **out) - print('Saved in:\n %s'%pfe, file=txtfile) + print("Saved in:\n %s" % pfe, file=txtfile) if plot: try: @@ -337,7 +418,6 @@ def benchmark(config=None, func=_FUNC, plasma=None, shot=None, ids=None, return out - ################### # Plotting ################### @@ -358,9 +438,8 @@ def plot_benchmark(fname=None, fs=None, dmargin=None, **kwdargs): if dmargin is None: dmargin = _DMARGIN - indok = out['t_av'] >= 0. - vmin, vmax = np.nanmin(out['t_av'][indok]), np.nanmax(out['t_av'][indok]) - + # indok = out["t_av"] >= 0.0 + # vmin, vmax = np.nanmin(out["t_av"][indok]), np.nanmax(out["t_av"][indok]) # Plotting # -------------- @@ -370,46 +449,81 @@ def plot_benchmark(fname=None, fs=None, dmargin=None, **kwdargs): # ax1 = # ax2 = # ax3 = - ax0 = fig.add_axes([0.1,0.1,0.8,0.8]) + ax0 = fig.add_axes([0.1, 0.1, 0.8, 0.8]) - ax0.scatter(out['nlos'], out['res'], out['nt'], - c=out['t_av'][0,...], s=8, marker='o') + ax0.scatter( + out["nlos"], + out["res"], + out["nt"], + c=out["t_av"][0, ...], + s=8, + marker="o" + ) return - ################### # Bash interface ################### -if __name__ == '__main__': +if __name__ == "__main__": # Parse input arguments - msg = \ - """ Launch benchmark for _GG.LOS_calc_signal + msg = """ Launch benchmark for _GG.LOS_calc_signal This is a bash wrapper around the function benchmark() """ - parser = argparse.ArgumentParser(description = msg) - - parser.add_argument('-f', '--func', type=bool, - help='emissivity function', required=False, default=_FUNC) - parser.add_argument('-tf', '--txtfile', type=bool, - help='write to txt file ?', required=False, - default=_TXTFILE) - parser.add_argument('-na', '--nameappend', type=str, - help='str to be appended to the name', required=False, - default=None) - parser.add_argument('-s', '--save', type=bool, - help='save results ?', required=False, - default=_SAVE) - parser.add_argument('-p', '--plot', type=bool, - help='plot results ?', required=False, - default=_PLOT) - parser.add_argument('-pa', '--path', type=str, - help='path where to save results', required=False, - default=_PATH) + parser = argparse.ArgumentParser(description=msg) + + parser.add_argument( + "-f", + "--func", + type=bool, + help="emissivity function", + required=False, + default=_FUNC, + ) + parser.add_argument( + "-tf", + "--txtfile", + type=bool, + help="write to txt file ?", + required=False, + default=_TXTFILE, + ) + parser.add_argument( + "-na", + "--nameappend", + type=str, + help="str to be appended to the name", + required=False, + default=None, + ) + parser.add_argument( + "-s", + "--save", + type=bool, + help="save results ?", + required=False, + default=_SAVE + ) + parser.add_argument( + "-p", + "--plot", + type=bool, + help="plot results ?", + required=False, + default=_PLOT + ) + parser.add_argument( + "-pa", + "--path", + type=str, + help="path where to save results", + required=False, + default=_PATH, + ) args = parser.parse_args() From 8acadd8b48ccd213946b0527d2e8e8308f745126 Mon Sep 17 00:00:00 2001 From: Laura Mendoza Date: Tue, 29 Oct 2019 15:23:12 +0100 Subject: [PATCH 03/16] [travis] wait 30 mins --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b780c961b..4cfadfc8a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,7 @@ before_install: - ldd --version - gcc --version - export START=$(pwd) -install: +install: travis_wait 30 mvn install - if [[ "$TRAVIS_PYTHON_VERSION" == "2.7" ]]; then wget https://repo.continuum.io/miniconda/Miniconda2-latest-Linux-x86_64.sh -O miniconda.sh; export VADD="py27"; else wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh; export VADD="py36"; fi From 69392e513542499c4b73837b47eed97c14c97171 Mon Sep 17 00:00:00 2001 From: Laura Mendoza Date: Tue, 29 Oct 2019 17:58:23 +0100 Subject: [PATCH 04/16] [doc] uupdate --- doc/source/contributing.rst | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/doc/source/contributing.rst b/doc/source/contributing.rst index ac8543664..4ee4c7dc4 100644 --- a/doc/source/contributing.rst +++ b/doc/source/contributing.rst @@ -1,12 +1,22 @@ Contributing ============ + Bug reports, requests, ideas ----------------------------- +"""""""""""""""""""""""""""" If you found a bug in **tofu**, or if you a suggestion, the best is to open an issue directly on our `github page `_. If you are opening an issue related to a bug found, please specify the version of **tofu** you are using, any configuration information that might be helpful -for us to create your issue, a minimal example to recreate the bug (if possible), -and the log files or errors you might have got. +for us to create your issue, a minimal example to recreate the bug (if +possible), and the log files or errors you might have got. + + +How to add your contribution +"""""""""""""""""""""""""""" + +First of all, you can check the instruction on how to install_ **tofu** +in developper mode. + +.. _devmode: installation.html From 47b563cd49a9bf7c6eff86a0061e2da27efa4e35 Mon Sep 17 00:00:00 2001 From: "Laura S. Mendoza" Date: Wed, 30 Oct 2019 21:33:39 +0100 Subject: [PATCH 05/16] [doc] update in installation and contributing sections --- doc/source/contributing.rst | 64 +++++++++++++++++-------------- doc/source/images/pep8speaks.png | Bin 0 -> 34684 bytes doc/source/images/travis.png | Bin 0 -> 20642 bytes doc/source/installation.rst | 5 +-- 4 files changed, 38 insertions(+), 31 deletions(-) create mode 100644 doc/source/images/pep8speaks.png create mode 100644 doc/source/images/travis.png diff --git a/doc/source/contributing.rst b/doc/source/contributing.rst index 99b6a893e..d49cafd61 100644 --- a/doc/source/contributing.rst +++ b/doc/source/contributing.rst @@ -1,36 +1,12 @@ -Contributing -============ - - -Bug reports, requests, ideas -"""""""""""""""""""""""""""" - -If you found a bug in **tofu**, or if you a suggestion, the best is to open -an issue directly on our `github page `_. -If you are opening an issue related to a bug found, please specify the version -of **tofu** you are using, any configuration information that might be helpful -for us to create your issue, a minimal example to recreate the bug (if -possible), and the log files or errors you might have got. - - -How to add your contribution -"""""""""""""""""""""""""""" - -First of all, you can check the instruction on how to install_ **tofu** -in developper mode. - -.. _devmode: installation.html -======= - Contribute to tofu ================== -You found a bug, or you want to add something to the library ? This +You found a bug, or you want to add something to the library? This tutorial will show you how to get the repository and the first steps to contribute to the project. Bug reports and suggestions -""""""""""""""""""""""""""" +---------------------------- If you found a bug in **tofu**, or if you have a suggestion, the best is to open an issue directly on our `github page `_. @@ -41,7 +17,11 @@ information that might be helpful to us (OS, server, how you installed files or errors you might have got. -Getting started + +Developping in the code +----------------------- + +The basic tools """"""""""""""" There are many tools and concepts to get familiar with when contributing @@ -111,7 +91,13 @@ If you wish to contribute, but don't know where to start, check `our open issues `__. You can also read `this tutorial `__, -on how to contribute to a github project. Before modifying the code, you +on how to contribute to a github project. + + +Git branches and pull requests +"""""""""""""""""""""""""""""" + +Before modifying the code, you should create a new branch (based on the *devel* branch) and switch to it. :: @@ -126,3 +112,25 @@ Now you can open a pull request in our `github page `__, from your branch, ``theNameOfYourBranch`` to ``devel``. We will review it, comment it, and accept it. + + + +Continuous integration +"""""""""""""""""""""" + +For each pull request (PR) on github, there will be a series of tests run to +make sure the modifications introduced to the library did not introduce any +errors. If all tests pass, you should see something like the image below. + +.. image:: images/travis.png + +If there is an error (red cross instead of green check) it can be either that +your code is breaking the normal functionning of the code, or (less probably) +that there is a bug in the unit tests. Please try and understand what went wrong. +If you cannot find the problem, you can ask for help by commenting on the PR. +Additionally to the unit tests, we have integrated pep8speaks_, a bot that will +check your coding style. + +.. _pep8speaks: https://pep8speaks.com/ + +.. image:: images/pep8speaks.png diff --git a/doc/source/images/pep8speaks.png b/doc/source/images/pep8speaks.png new file mode 100644 index 0000000000000000000000000000000000000000..9c868082f9464254fffec7f39bfc9467526c706e GIT binary patch literal 34684 zcmc$_WmFzPx2V~;OM)c9EfCz@AxLm{cXxLuSg_!3FZ$x{65QRL;O@?l@7z0f?piay zX8KR}s;=s)uIk?M>|J4UGGZu*IEVlMp!^X3t^fd#`v3qz3J>{Sa`t9O3jlCi9!hFX z3i_@@b`G{C=2pf;PVRQbM8S%z8osbqr4|HS{sH{NkCE^$!2)ZFxCzSzV0i`Mn^!^+X%8~&Fpkj=qU ze0)d$-PQ3cY6}WKSH4$y^|RF*-`>S?;NkqS`|I(&P15UfAm22|fntMez5?!HUWAV2 zP2c2dP2pwz?1HuHK_izHJeS6YO&%u^s~!3FoC3~|i%9BXw5M^!)?l8`%1gYXyz4xU z`Z=Zg{V%GK+)$=%zw1+r-(~PK{mGe9161W{P3C%1+|KmH%TtBX@2r#c!TVPpTepU) z=SzksN0V1N#_@IIUF|t~f%!-0ul&oKiM$;lt}@q-x7@kEEYN4#Ki{_9KeM8y&b7cA zf4%V`q`P(;eDFaL|FmMGyAIVraZ#Q=J=lGhc~)pNOwB&V8clJuyl`;lzO&)EW;-bT zy+nLXp-F$b{w@5guk`X-nCl^$qb;m5fy&kETgNy*zS~$c`d@0Zor_HLE$LxxE7&|w z12ymINB^2uU@uGRLFDFA$m`-bi(Ar{@1yKrX|tRo+}m}Vkq6_tkI?6T6(HEvVTG}T zQT$e!$bV0U-g?E&Kz75+OH?fx>0I+))OTz>3+IoIyYn{;v>duNwrWlC(=m1IV;W$N z%C@rDG0FPS&z4h{U&~LK5~=-=M;nWlPP#bd5`n5=(5x&Ju+YXW9XJf>`0 zeV^Hv@PW*_5k=xwtw*cRmO6&)+wE9mi}`&7qpBw~ndseyq}kuZNTMBghoH1FyQB=2 zRc*gMP9VVY@kXI1a$hF9QnAM6#8{zdTSh@ECu3p!Hq!7KAax#xV5z}D7z8E9pE}8} z*v&{GiZ#YSD{ykmWVs=R#uLR9aaOyvTPrWZg<#2RRpyfvTg9zyS6L_+GQFTVJZ8jggA$=H;+P^o;>G03 zvS@I7yy7~<%N4lHh22?1VO3wZv}7GSY*`dFZb_}*XwOP3Uh^Pyt0m&AL9!w zY}P^x_jizDuQ0O;Jqr}jdoOC5P+{?P#}U9CG`SNz(xs;9k`{#~GC$>P!PcScvynS& zamzLd75N=s>G#yBoC~Z;L4Utl=QHeDOcs)0esr1C!Nd{@{I0DLrGwTcnq(!8hN?{Q^CBUND?=kaBBf#`5k&`5(KnNV=N(w-s;u<6P9Tvd;o7mS z^%JLMCWjPkJQ~nzzZ~_m_bEbzx={p2Psu4Dp+~ay3zkL(8G9oJf^Uy$IL%Y^R%M2l zE|5Yi>aQHRO11J3jIhO7rLyTVw(By&6_lQ?VLp};J+%dV|GYi728^`Vlu_yZIoowB z(>XuM7mN~M!e^k4?%@d;w?k5rI?2S?3j6KT>l?dpHNuza?g_6nhxawgv&@Huioj$- zPe2hTuQ$iZmNd`0B@uO@5~(KDdXGc4$7zXf3G0X=TsYyl-K0xtjAmX-{4!|VTbm{u zDh;Rk<#c0Wi8Zh7NimyIfF=EtrNG{x5Hd4lab8RTbdGHtG$W&vRR;yO@=|z9p@{5G zC?q8Uq^*GbCE#L)Q#+wAoDtEj@U878hB|TPH;gnX>X0G|`pybx(!)0owHukxv+;EC zI`)t4ze#FNPaS{G2da~>peVZ;sS#%)aUaPK9l+nfb$@Q+!DOb27m|{}nlW70#?_P` zA>Q5?nFy};oRVrgFyvh9J4(Cvk2ydmsYU%t`wN8fBY<5&G^+~X>&GG8G@h-E#__$q&_V*mvM6S0XRiMSk74LBguJ$JqWr!g>pDvvGL^V4vEIOrA*jy+C=iasL z95>}1i?MC?y42byje0=>sHa-FotX(AU~9C;QZm#s(gQduoO>`bFORhp~SVaEOz zk_DNrv**7>y;(O}P+R1P5!e{la4M93p^v&o+;P09pQL`vzj}ac5c+k#*Fgh*I{0|V zRQ;~>p&W&ND8a+SFK^0j000s2;yBdb-Ja7(0_C??$W&lxkbrCde1oloI zkw|9(6}E^-u|{3}f&s0D{W|-^)?A`S!j=S9jzRDiq}m5>7%TNMngo%r-{P{#B$CMn z?%*QeQ_y327p^?rG(PXHd7ie#59*&vDHWHNLO}xnTH{}Up;Nr05K0i9I4H)dgclzW z`gfJfVE>ObQ-cRt9C{kMQC*pjT|5-uKy@4>4uA*p1l`np7?$(Lu zy*c_J^qIq!!fm4vP3-4uxkaV&VIUb+82Yp zA3iE#|Eq$3Nk>8V?-?HbdRqbi`YP}bL;5$U->~3ijS?^zTw1EA{C@OWA^aN}{v>{w zq_(!Uv^2_(I3T;Eq$DRtuyDF1NBjLIe4Al2sr`qDUZI?r{_R;Me$zYFqSDgosVN0T z#iJ0=hxZ3x(;ZwYr!_Zo#gU1SOlI(RSIffvHCZbHgRvrdwO8r>^}WWsYTpv3MB;w2 z6@311Ws!3(QYU_|MHDOE{J;0J9X>pqREG>JoM3(_AXhjxRgut6_M=*pu6d(>{NG5= ze$&ZnDJd(LQoFzDNc$|kH4V{h^Y@CqjdT#9!;^jdk)-2FS+Q|+eX#0$L;BvJ=*d}Q zOXwz=b?$v;r%p-@CuH-4%2db?ZWQhamkJs^Kg`a~-k^!QssN)2s^?#)G_*7LwB?%| z2KX7=8#8Xw6<0D*q5rMN_l(5GqN1XKm2waWmWt{{EOJ7gRiW+Cpf6mlr4M_WEG@ z@X!J~VzyMZB0L1{?9xhuhbRpZ&fuiK$FyE!6R`$6Q;renq;Qao1Ic1T0&I)JyHK!ulRTgHh z>rX*_JsSmun5ydC>&sJ52+Hul!2WtiM@UFtJcaD(YD>Qn6E!vU7i3Xm;{qkBukb>0 zipn~kS>?JJFPCxh;6b^iP;a$n3k!>nVc)-D9v&Xf&CV*TsCGW6`3;i^^7VS ziQ6lK)m$(}x#RHZqHrvT0A#JP)k(nSeS#xDEi>DTz^^^?*?cL`zCA&04#V524#k5D zIY`cQxso>jQN&qJ&#yN|P#Tw3FD5=u*r%(l=L5wh;;FSpO|F>1k>1wjA%WFwB712`0}BhQePa-7b8wAZmi56KZ(mU< zbJ9r~xw@tX9}n+zt&KWC;=${+(;q5}$6Y~QUfIJRZFZ^wg2YV@}kJ6jqJ#!`*!`CBFp7meBDebi4? z>$zPDsUw=<^^1mKzYRC0@Y9(#BQ|#VkX1^RfQKC4lJRsFS^c=9xC)2*1NP$wC9Vw;nJgzGDl5BPe=b3@+vw>v0qu>yIk( zNrCWuxRiyqZCA#X4P6TnHH92)*$gm;c+ zTfoPbx_@R-fCMxo2()n6S1Aw5zK4=)UZuO@2Chsv)g~S=`6$?5g+B>KzM6q<| zEq7MlO$C6seqWKy$L%@c92ehGMi=y~0ptZ1cVL!MrVRtER(gg%f^YU@_?Rz?AbI(@@r~73@?_J=A7e~g@}amR|rdX@a^mpBx>)x-9dhRj$?C$)I^poW133wmI7i$hpU0FsWb_`z3(CvQDKksf~ zd(TD#m%%i7e`<2wQG?H%BCq6;lMCAeBUWTU`n6DugL1WM3-W6=)E$Dodlhi@5%1 zLSC>J)yJ>}E4B=ov+2U|cM0d<;80svH#;+9VQC4W*Xajwce={V&Q8dn*O|fXiieMn z5U~HprlHHIER7NXhHc7tw-tnb$T0p8x*!Dx7I_yvT&I1$F7^UeB_w*uZ&%GPu76(E z?o!z1&L;~nOl`C7|AMAXR7t1rz;$%SJ9rtVAFa)9y7uh}X_IgLDJNs+Ueb5Lvu&~G zo`2>|&vy2bS|!vEvHk>o0{n97iuHT2AEcoG0q5PU20fz<8aPKTKmP{XgU!-siLjkR zu*EQpqc&$M09%gab?S|qpuw>k1O;^BY_bKQ083D`$Ywm;XursT{nWH-0~qO2TI*xd zhrJWvf6iMc#bZIFC70^4q+yuA)GmXXM&fXy^zugLolIrv{RR@-g zfL*R+D8H^qn1VaDH7nNn=EOX0oQ{eiJ{J~c18&#vS4*Wf8EwUk_EE-1p6qT)HA z!J=T)w{nq`QUOI{jSdlfOlG$~Apkvw)dnJ0*$;qUzQ7m@tA_{o*3-QZrJu@R_g|fK z6MWCS*yBiv*P$UwTI&b0^yZL0wFWfGWnp;d63MW^dbYFK3UvJYgY)$i&K_$pWV_nJ zmRJOFpq2Gn%kSismrvSU$&E!NC5HzG5CYoT_<>z|RcZ$Z2T*XRGjnq`kB-jw=bKGU zO?7p3gi)!9F%)#H!$niYbRKbHdBy8(o(;MkJ}-|q@#176A|mgN@Oa$pe*6fluXj0H zYddgi4i1J%8m6VEuP7>FU}Q9Bww#=wrmfhxqRw);ux>&wm2G(HcsmR+sD}amW~d`vr0sE^)a_bl_ybBaB_xF4S+|D;5)J37#1j5J|7PkEjl%#NMd zW{kX!oz)C{>=S62B)pIEq<8U@dOZ?BmUeRg3bXm-dsm{%&y;VL`cQ&gk&N^h56dD& znsHUd59gP3|J{J0+Wh8wO$R~?*V6|=4jN!WkJYMh8lsk!701`i$EmJLmbF8RXoEm4 zc6y@hJ4xK3DgxjHAyC+1v)xi!rpaGC#7E^V#Gb*BZQlSP9Le%+-3G=zj4}3;1DS9u z)Sd?WxF#Y!IZt&87LjFBaJ5hKE4)~gSnuLIVdBnPe3By3?**s{xF|eWF(yf}p6j=v zZwIFAZG=EF7e^(kZ->dUXT3_#30`_=O6_shNC`lIW#6?>TxI^~NBmez0{E5mV@}UJ z$4yQ5%O29#@$B)tqo$iwB#(U_WG@L~{`0(Yc2Q7J!DQ!*a+5HeD909perWaZhRya; zeC}!@GwrMScHa)ZDahx?D!zKJySGgzbBo7rJoSgo*Gdr%FZ0Z556%eewKAGKu6H;GB6*X*KcNBz%aT51 zWo>=bQQVPN(C%YsXb2;GII>c(V_|W@qo{~(q$T|c3b~5uD|{uBe<_RsEruxt22jnh zZ9xz{NWOy!K?nFHtMYjsAjy#C*y3*iFz* z%z59oW^}#4(91b=zg1kRbEtyUQ)O&reeP=%$xtJGX2cXfu`S9A5V7Y0Bild zQ!nMKrnS|I+>5Qze(X`4KPetKG&+k_>uG=y0J!>1V#p3F;JmhLNxTc29swXV(Q(ek z?s2c8HZpxU6l1)aPYs>J@cR|n4;N)xv0#U4BboS=p6{hkRZXnkV$BQfuNv;tv0mE} z?;1dr4r$?G)&Fs&fY0)a-pVC5P0&P|S-a58wfDX3(_x4EeT?QC@&{mHsWmCZxqoh# zH-*32*_n_}X}_m?tY5qA&DPt3LxaQ;O%?l3uY_ch2s_98y@d*PM$8~s}Js@>D`Yt~CTB(i_*fyu(llaR_F z)MtHE00>5a8|%&&2yDOZ|B6=P4@Lmww4I{G=FjHc(OfJKam}yZXv;45Rp07g7;eNr zT5oBECb~;`4pm1zNtFNPgB*UGxfc`+gNLo7(#CP!Fq3&ZNHdAjYw(}|k4cSAR%$Hk zy0j?WsJ=OVRcB!`OKac+{B|lVNf7V>KRzqyy?xsx-)-z$!X|-FKz1_`YYM+zZC+^w zxU^zt-4NHe*~4`TzF$?{i?6Yg|G)6c$ zR-8}ix_Lp(Xen4k&GPr#Kh=NWnUZ+_{uPV$O5ftC`bvw$5-!i+6FyXcKq{)Lg*gSv zg$UO=B`-J9<}5gJUV5vzQ}fdW(=+!8vg<|I)Mpi9%;7bTLCt5hUUtC@4wS%*+d@e z?mD>dy4tTkqco80WMQy_;2b9Um6OoDDsHud-a9!y&_rgZct(itO}=ZEbkAXtj!?sS z%hV;Avk7N~+wqe92oBzdJcw&CZ98R)(vJZVPP9x4M?iqLQiltIxy| z+z#YV5Ls_TyyQ%h-=VUhS`S#-y2M?EoMuYLwHe-*P3$u+?&ZA~aL;6C{IWMz_qtR` z3k|q=wO3W?Yu-QrQYkEq&xPL7pOkjq7C>|z|8X{pl@OiJzbk2!zUAxQJjp=uzoVyw zhe^kbT;}o?H8*RWw(MDz#NK>xC`DZ<{IZSCK$Sa~4I_Q9w1>RnG-xhG#fSg<6YI-9 z3tiD>i{F(m980|k7G~CDBmNE>3II3_bNWw{%D#MP&QZvuooDYhDcB9nv~{NXUYInHPdq!TiPbAknm(h2o{_Y%MER|FGR9`JQtUmGM7Q(IfIX3Ctp8s zF0yHb%+}t#cE9W_D)N6-m1J?27M0T7u)Nhkno(A#gTKFDC|(a}kXR7bDtw6Ki2IWZ z1+=|PU*m+Un|YFPn{uU^S(u?RfV^@ch-aKRgke|5MqC`6DnDCgrZ|i3^4-{0G%(k2 z3V)+-cfn7fdz=qQ70>?|rWP0H{dXyXlpKu%qYrv!ePp=`txs7Cjxc8I&E|PzfT>jZ zM?Z+_vDga#+Z2j&PQz4QPz;J|h6@Z=-C2#YMk&=OWnmhcc_W{qGp*ANKY`~9_`=Zg zgOKgd{tB%s6Gb^afw$KXY4&thQ!A@R2ldXLP~)x~IH7uLy`w`X#~|$%C8c-9b7>5I z*P{OSDs=)wWw_b7h)!JKzi`G*5Z=72Lxtnb%~(O0UqA3rHDjeI4cgawOqam``F93) zgukTd!Exdx1R#Qz`yfMh_!{hY?O=Fx=+@YT$LRqHuvMUFFt{f6ZiEa|VF$v|CUaX} zEfE164%b1UX_9xQv=b<*TH=hwkW?KeURe~c)31v=KL|$?#L1uqi%MJ`PFNRR-|($$ zre?uJ`7yayrD*w+q0)~A<-#3f;*4%7jQu`Or7`pcmUn*}-N)_OyArV80gQSFYojQc z2E+V#?yP~_J9!}$lP$6|n=xfrtr*5gdM7GzWbR&TH&c!Y0o9uzo0mG+yE9Xvn~EQ< zB>$noIlnla$sgZ6q0M@gvt^B=!$Sbb(sk!%emWb$Lt{@Oc&L2y(9UcG{N5cQi2^`Q zLnXf$+^clfbKLvqKYZCE?VTYeeT=_CJe^%XFtD;3_`+mX_Owr+PHZuSABF^o7buv6 ze+!yA^&rY){8y*0QtU5BWh^*RqIvI3@cnS^sryHe;oIVyZ?Y2lfBy$u+vYxD+x(-* zL2Kyb|KZ9CILVFwz_Ymdf8)#lv%=~lhtu6tLuG!UumHR>wKPhUMQl-F-urceE028@ z0axR{8^l3!gqr;*CN71~pma7LiQK=?W~GJ(Z*GieJx zExds#THTl94{?iY6HCSF=>RaF$Qg|^YWYFpnk21DSksr2UK)Z3V|Q7GU+ucjekY`n ztE_SE)d7oAle}et+eXTF8-9u2GNN=iQImIq0dN``K+4@?%aZdH8;3dCiueHlUBM!^ zqlKQyfy+B0p7g`s1uIMYYzvNOtDr2$yI;5#%nx$*(;*}H7;F16r@sTid15$zkj$^- zA6(A0g4XUkvyXXSOoX74)ni5j{5z@!SyG zJ6Zav;w>+dp|;vN^SBFENB$Ok?;Ww7C+hvB^^VyR8vxuNALq9;YX8uZ1 zxZ)_j)%UKYT@yqGh{UzduAm$pcN$RN!zx{;H9i3O*)(@6?Ki`ppq^F|V*y|UAuSK` z1Rfyjg|z7#=N3++Gt7FM9Z%1tTaKNJbmVNpVo*W@vPrn};Qj1*Teg@Lc>zGjM&-+N z-&nOauL>lhlthcuSk9F3$0StEzJ;_eOrULLr`w;-VeI@3Mf=M)lFw?w_}QZGhUJCP z#b#(H)6?Wuoi3~Ve4_5*4H7ob=Aj~%Si~Pzr{+NIb;7n3^6OtAi`oqK2ZAg6ezGbc zMqU*Hv`odUJOB_7dF=Wt*m6g6Yl_d$*@G$Y4Ko}9nU_zKs}Gr~8nc+wHfb+1D*`;H z#m5-U6uR$J(fcEKf|&{S-S8R(^bS*4pWokfuUf^GD46WCy_8ybI`BgWW^m51uFWt> zuZ32_JYS4=fOi(Xi;aby2@+snVrp24^YoUG@_J2-B?kl;aD8C_6HwRI%rL}Y3YO2V z2d47kf_k{G#4u^$;Rhf_Q#U)gp{B+Cv)H(9!om9js}H{v5xE81n!j?S93ZM3(~2s7tYWTbAci_F43>2TGYo z)dS`{2J9=du&{}>Et(dU1)8ACA0~cPxF>y7of>v>%pvzYu=r}7S#xRN3w-p!Yfdp% zwF@OLe(fvQ^i$_SB_}pk2RQBIfUVouV2a!vN88+m{N-L;w>i>4+GZ{jj6y4Bc~!_PfnU zQJ<^^SBgUP@W`b!T}W!$J(%>{!M;u^-OVCMAou2`F|AM9GY%3GzM6;ol|&>-&_qbv z4I{TsxF(io`v)D=1-%K>I@h^hmaBUy(^j;P==X-w1^@F5BZC1WxI37_2;I_b5{vqi zfc-un)pQ*OD;p&kz{uMEX3dk%sqNU(svAmBN&U8NIDEI1*H0$6Y z4ZFea^{V?8^-ZbmcXcf@B|1u5=z-iIXU8^C4vy%w7P`x8uKC?zx``5@l2}`dqNvIE zu$+Eq1*r=XeFk{gz!*mY_Ual|GUn-F02p}wZM8cPT!T;aq~X1#^E*=#XKASh0@G93 zA-km4zq^Nizo8YRZA4)88%se+p<*#sR2^zIlASesBLCaMUk^k)D$Ke%#_a~S z=BRtB;tRE1k+C}4pX$3vp@*|wRW)^0HPC|BB%b}V2htGQuS1LW&QyyovYJt9EgGR? zoD55;bL@N#1KGJ12&{2Q)+ZnVN}Zc5ugAzATskiZ%Xd!oEesNf-@l%eH9YBWO~oav zsto;Q^TxVNm1*mR+oSyjU9mCXxaWJzKD>6=!1d$yi8-Zh%+(yv(7|q}sR$*0b48&8 zf00(#-srK5&;h=oVm{I!;kACoRGMn@^(K{a#M09ztVstpL`Je5Zxns)=kU~xR@34# zCg3CnUa47W7a_=Ouw0`!8aGyA0Baqiz_@>M9Zw_pt$^NOZi$BmNEpnOMO$g?(Q&u< zn8H>%Bj~FyU1Z;cK>~i^K?UuC9Uz3L^!}Dg_jy#`ZN>HC@P%wYZF_gU13sTf%AMCL z%h$^yg&}MhAjDx?Nz3QE+2H_6KYbsxr;w1G86*M_(?(5{KX4pTnanH?*Um7${K={D zU@j#cDs;#T4UZGo)h0^*@G)a>)HI*OK4X21=`8DRq=t;>Zf9%uOCM6;ct76aF-@de z&DoNrVt3}_)dA~Vq&)7&3Y*#_?m*5b-)~pXr}xp!QdlR7lZ!Wd9F`<+jqdK_O8Uv` zhtLoJd|cuf(jdzd3D4#I8fRo)&K@p>go$a??u&;BXXxg|>P>`y`n+WlE2Pomqq}B} z)Qjx*ci9N}fqSf>c{#^9m`SW%9yf0uaj@lSx&5aVD6l0sQdh-D46j|V@rh%ATS`iQ z+x_aw8O&)~$mO%XM+zOb%l zoc5#nZdCY7ZwcWNTN&!?&-|}E_BHgyk+|v_2^QJlhaCUwt-6wtlBIsM;HT-YP~BmQmTPk411x% zjT0YK8i2WDBjHOqcOH|fIycKYB|T?wztg=NON7*V{T?ji-~LJg3P@z;aoXpES~~_P z?BvhF4lrnu{4UkT!cvU-CfjUEXsNob#P5Aw{poz*qH<{Gguv=}h}Lx6?%r%IWh{gl zO$tBMJwh(EHIx})4rs~I(Fv7wn3m{VZ9aEfz#?8K8+bov(I>E17^Dvll_02;Kq*t(SG>m${TzyRO_1R0h+X|pyj|1K3L(g3${UtD7Q z-LZf^vgyqly)y(GVfA+%wRZbdei0-MV`Vx*An^|DdslH#lavK|5=;dp1_F$W>(?_L z=0aeA&f!ub8lIJtQFT3n&t6k0^m`zj2WGPtyQ{s^lYtTOs?*j4K4Ao4A8M~9XqS|Ay`oRYNZT<&A*o{>;|125op57W03kK2z11Ju-6PAPt>ZR`GK zxs&EoJh30v)X)FLtMxz(G)mExwyJ*9Pk1)c-DR43V##ZBA^IM*WxT!VEyH~>SR zcO9wlE1I^8B!hOY-}E#gNGrsW^{21bL|KdG%LdM5Sy{6K9YX3U^U^ zF0aUL#92MT4$#0iS0d(2&r7~=kwH`rQpDmQ(Fk^U7^mnqPYWMpKfgf?|b4G;|R?T*}4~F~cqG;5SrW+w{_;qvYyK z{znak>F5$v8&UqH5(sgK!y(&5)aFGm)0?yU6ra&V#gZ@0k1lWR4Q#&`wV?o_$Qy+= zRvlUEHPPh8+RjRK_tWEa6ZVk&vd0QW+@wMgZtiFi-5~*73Q0)6{t5u}H4QNH zKB*Ek*9k-K9C5GZgaESl_|_aoqiVNWNh;&2*q4{);DOGC8T9P@b~F(YV<4u^acd(( z`YFK(8zOmenTZ}`{I+%DYZ_I?f1bQwXBHCA2@(98R_KVGm^^LNgt<7NP|vK-{Bxt~ z5q!`=GUZ5jS^j?OaqSU%dBMeCSjBAvi^WQX`>*e7Y8`lhIIQXdgD{&;=5awpzgv_8 zA+Je5(%m=r1~IuYB3!^}RBG9kH%w1MjZL~OCHTvSOigGL_pd=wzSC_5!Y8!JdrQY< zQcR-R-%2;V+k8q3+9>l*{)o&Cu*;iW>#U|D2~;i|?@~Wj*o?tc`K4W49mZtKRYc(a z9fch3Thoe(Q70>E%(OkV0>c5fE`2%0DUcL41m=9b;V^Q7HzihVA_eLXdbf4PJp@6* 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 literal 0 HcmV?d00001 diff --git a/doc/source/images/travis.png b/doc/source/images/travis.png new file mode 100644 index 0000000000000000000000000000000000000000..a85c75b39a8b80dfebb1df978f7eb0e0213ff299 GIT binary patch literal 20642 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 @@ -128,7 +128,7 @@ To install tofu as a developer, we recommend using the conda ecosystem (Minicond - Move to where you would like to install your local copy of ToFu ``$ cd some_path`` - ``$ git clone https://github.com/ToFuProject/tofu.git`` (make sure you remember the path where you are installing, if you want to install it - into your home repository, just make sure to ``cd ~`` before the + into your home repository, just make sure to ``$ cd ~`` before the ``git clone...``) - Move to the "cloned" tofu directory that has been created by the git clone command: ``cd ~/tofu`` @@ -142,4 +142,3 @@ To install tofu as a developer, we recommend using the conda ecosystem (Minicond tofu Cython extensions and install it into your conda environment while you can still modify the source files in the current repository.` - Make sure tofu tests are running by typing ``nosetests`` - From d927dbcc26b5391a3152e1aa3c7457580ef6c54f Mon Sep 17 00:00:00 2001 From: "Laura S. Mendoza" Date: Wed, 30 Oct 2019 22:00:12 +0100 Subject: [PATCH 06/16] [bugfix] pyplot was not being detected --- examples/tutorials/plot_basic_tutorial.py | 3 ++- tofu/__init__.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/tutorials/plot_basic_tutorial.py b/examples/tutorials/plot_basic_tutorial.py index bf8ba3b3f..5f4a63265 100644 --- a/examples/tutorials/plot_basic_tutorial.py +++ b/examples/tutorials/plot_basic_tutorial.py @@ -14,7 +14,7 @@ matplotlib.use('Qt5Agg') except ImportError: matplotlib.use(matplotlib.rcParams['backend']) -import matplotlib.pyplot as plt +import matplotlib.pyplot ############################################################################### # We start by loading `tofu`. You might see some warnings at this stage since @@ -23,6 +23,7 @@ import tofu as tf + ############################################################################### # We can now create our first configuration. # In `tofu` speak, a configuration is the geometry of the device and its diff --git a/tofu/__init__.py b/tofu/__init__.py index 8ffba0a2d..27793e90e 100644 --- a/tofu/__init__.py +++ b/tofu/__init__.py @@ -59,7 +59,7 @@ from .version import __version__ # For tests without display with nosetests -if not 'matplotlib.pyplot' in sys.modules: +if not 'matplotlib.pyplot' in sys.modules.keys(): import matplotlib matplotlib.use('agg') del matplotlib From ad54bbabfca73a2be716b252d5819e664acf791b Mon Sep 17 00:00:00 2001 From: Laura Mendoza Date: Fri, 15 Nov 2019 14:13:56 +0100 Subject: [PATCH 07/16] [merge] added new example: custom emissivity --- doc/source/conf.py | 2 ++ doc/source/index.rst | 9 +++++++-- examples/tutorials/plot_custom_emissivity.py | 1 + 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/doc/source/conf.py b/doc/source/conf.py index 82930885f..0a58fd4a0 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -14,6 +14,7 @@ import sys import tofu as tf import sphinx_bootstrap_theme +from sphinx_gallery.sorting import FileNameSortKey # Getting tofu version tf_version = tf.__version__[:3] @@ -354,6 +355,7 @@ sphinx_gallery_conf = { "examples_dirs": "../../examples", # path to your example scripts "gallery_dirs": "auto_examples", # path to save gallery generated output + "within_subsection_order": FileNameSortKey, } diff --git a/doc/source/index.rst b/doc/source/index.rst index d89f72370..5e91e9b20 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -36,15 +36,20 @@ interactive plots.