From 66efd3dea9482a69681be33b05e9ed442a6c0578 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de>
Date: Tue, 11 Apr 2023 18:18:03 +0200
Subject: [PATCH 1/5] purge devtools: rm line counting tools

---
 devtools/linecount/baloc/__init__.py          |   3 -
 devtools/linecount/baloc/file_types.py        | 122 -----------------
 devtools/linecount/baloc/history_collector.py | 128 ------------------
 devtools/linecount/baloc/history_plot.py      |  63 ---------
 devtools/linecount/lines_of_code.py           |  58 --------
 5 files changed, 374 deletions(-)
 delete mode 100644 devtools/linecount/baloc/__init__.py
 delete mode 100644 devtools/linecount/baloc/file_types.py
 delete mode 100644 devtools/linecount/baloc/history_collector.py
 delete mode 100644 devtools/linecount/baloc/history_plot.py
 delete mode 100755 devtools/linecount/lines_of_code.py

diff --git a/devtools/linecount/baloc/__init__.py b/devtools/linecount/baloc/__init__.py
deleted file mode 100644
index c8a9d7cc449..00000000000
--- a/devtools/linecount/baloc/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from .file_types import *
-from .history_collector import *
-from .history_plot import *
diff --git a/devtools/linecount/baloc/file_types.py b/devtools/linecount/baloc/file_types.py
deleted file mode 100644
index 9a86fccbd53..00000000000
--- a/devtools/linecount/baloc/file_types.py
+++ /dev/null
@@ -1,122 +0,0 @@
-"""
-Contains machinery to convert BornAgain filename to the type of the content
-"""
-
-class FileTypes:
-    """
-    Enumerator class to hold file types
-    """
-    CORE, FTEST, UTEST, PYCODE, MACROS, GUI, PYAPI, THIRD, UNDEF, TOTAL = range(10)
-    descr=["Core", "Functional Tests", "Unit Tests", "*.py", "macros", "GUI", "PythonAPI", "Third", "Undef"]
-    @staticmethod
-    def loc_for_type():
-        result = []
-        for i in range(FileTypes.TOTAL):
-            result.append(0)
-        return result
-
-
-def filePython(x):
-    if ".py" in x and not ".pypp." in x: return True
-    return False
-
-
-def fileCpp(x):
-    if ".h" in x or ".cpp" in x: return True
-    return False
-
-
-def dirCore(x):
-    # if "/Core/Algorithms" in x: return True
-    # if "/Core/FormFactors" in x: return True
-    # if "/Core/Samples" in x: return True
-    # if "/Core/StandardSamples" in x: return True
-    # if "/Core/Tools" in x: return True
-    # if "/Core/Fitting" in x: return True
-    # if "/Core/inc" in x: return True
-    # if "/Core/src" in x: return True
-    # if "/Core/InputOutput" in x: return True
-    # if "/Core/Geometry" in x: return True
-    # if "/Fit/Factory" in x: return True
-    # if "/Fit/FitKernel" in x: return True
-    # if "/Fit/StandardFits" in x: return True
-    # if "/Core/Geometry" in x: return True
-    if "/Core/" in x: return True
-    if "/Fit/" in x: return True
-
-    return False
-
-
-def dirPyAPI(x):
-    if "/Core/PythonAPI" in x: return True
-    if "/Fit/PythonAPI" in x: return True
-    return False
-
-
-def dirFuncTest(x):
-    # if "/App/" in x: return True
-    if "/Tests/Functional" in x: return True
-    if "/Tests/PerformanceTests" in x: return True
-    if "/Tests/FunctionalTests/TestCore" in x: return True
-    if "/Tests/FunctionalTests/TestFit" in x: return True
-    if "/Tests/FunctionalTests/TestPyCore" in x: return True
-    if "/Tests/FunctionalTests/TestPyFit" in x: return True
-    if "/Core/TestMachinery" in x: return True
-    return False
-
-
-def dirGUI(x):
-    if "/GUI/coregui" in x  and not "widgetbox" in x and not "qttools" in x: return True
-    if "/GUI/main" in x: return True
-    if "/AppGUI/coregui" in x: return True
-    if "/BASuite" in x: return True
-    return False
-
-
-def dirThirdParty(x):
-    if "/ThirdParty" in x: return True
-    return False
-
-
-def dirSkip(x):
-    if "/pub/core" in x: return True
-    return False
-
-
-def dirUnitTests(x):
-    if "/UnitTests/" in x: return True
-    if "/Tests/UnitTests/TestCore/" in x: return True
-    if "/Tests/UnitTests/TestFit/" in x: return True
-    if "/Tests/UnitTests/" in x: return True
-    return False
-
-
-def filetype(x):
-    """
-    Returns type of file
-    """
-    result = FileTypes.UNDEF
-
-    if dirSkip(x):
-        return result
-
-    if dirPyAPI(x):
-        result = FileTypes.PYAPI
-
-    elif dirThirdParty(x):
-        result = FileTypes.THIRD
-
-    elif (fileCpp(x) or filePython(x)) and dirFuncTest(x):
-        result = FileTypes.FTEST
-
-    elif fileCpp(x) and dirCore(x):
-        result = FileTypes.CORE
-
-    elif dirUnitTests(x):
-        result = FileTypes.UTEST
-
-    elif dirGUI(x):
-        result = FileTypes.GUI
-
-    return result
-
diff --git a/devtools/linecount/baloc/history_collector.py b/devtools/linecount/baloc/history_collector.py
deleted file mode 100644
index 8ac42f65e6d..00000000000
--- a/devtools/linecount/baloc/history_collector.py
+++ /dev/null
@@ -1,128 +0,0 @@
-"""
-Process gitlog and create a file with number of lines of code.
-"""
-from datetime import datetime
-from .file_types import FileTypes, filetype
-import re
-from email.utils import parsedate
-import subprocess
-
-
-def gitlog():
-    """
-    Execute gitlog command and make generator over lines in the log
-    """
-    p = subprocess.Popen(['git', 'log', 'develop', '--reverse', '-p'], stdout=subprocess.PIPE)
-    for line in iter(p.stdout.readline, b''):
-        decoded = line.decode('latin1')
-        if decoded and len(decoded):
-            yield decoded.strip()
-
-
-class Commit:
-    """
-    Contains commit info and accumulated number of lines of code (file type dependent).
-    """
-    def __init__(self):
-        self.date = datetime.today()
-        self.added_lines = 0
-        self.removed_lines = 0
-        self.loc_for_type = FileTypes.loc_for_type()
-        self.hsh = None
-        self.who = None
-        self.cmt = None
-
-    def increment_loc(self, file_type):
-        self.loc_for_type[file_type] += 1
-        self.added_lines += 1
-
-    def decrement_loc(self, file_type):
-        self.loc_for_type[file_type] -= 1
-        self.removed_lines += 1
-
-
-class DayHistory:
-    """
-    Number of lines added or deleted for given day.
-    """
-    def __init__(self, date, locs):
-        self.date = date
-        self.loc_for_type = locs
-
-
-class HistoryCollector:
-    def __init__(self):
-        self.last_commit = Commit()
-        self.data = []
-        self.locs = 0
-        self.fc = 0
-        self.file_type_ppp = FileTypes.UNDEF
-        self.file_type_mmm = FileTypes.UNDEF
-        self.start_date = datetime(2012, 4, 1)
-        self.days_history = {}  # DayHistory vs. number of days since beginning of coding
-
-    def pop(self):
-        if not self.last_commit.added_lines:
-            return
-        pstr="%s %8u %5s %5s %7s %s"%(self.last_commit.date, self.locs, '+' + str(self.last_commit.added_lines), '-' + str(self.last_commit.removed_lines), self.last_commit.hsh, self.last_commit.who)
-        print(pstr)
-        delta = (self.last_commit.date - self.start_date).days
-        self.days_history[delta] = DayHistory(self.last_commit.date, self.last_commit.loc_for_type)
-
-        tmp = list(self.last_commit.loc_for_type)
-        self.last_commit = Commit()
-        self.last_commit.loc_for_type = tmp
-
-    def run(self):
-        nnn = 0
-        for x in gitlog():
-            nnn += 1
-            if x.startswith('commit'):
-                self.pop()
-                self.last_commit.hsh = x[7:14]
-
-            if x.startswith('Author'):
-                self.last_commit.who = x.replace("Author: ", '').replace('\n', '')
-                self.last_commit.who = re.sub(">.*", "", self.last_commit.who)
-                self.last_commit.who = re.sub(".*<", "", self.last_commit.who)
-
-            if x.startswith('Date'):
-                self.fc = 1
-                self.last_commit.date = datetime(*parsedate(x[5:])[:7])
-
-            if self.fc == 2:
-                self.last_commit.cmt = x[:-1]
-                self.fc = 0
-
-            if self.fc == 1:
-                if len(x) == 1:
-                    self.fc = 2
-
-            if x.startswith('+++'):
-                self.file_type_ppp = filetype(x)
-
-            if x.startswith('---'):
-                self.file_type_mmm = filetype(x)
-
-            if x.startswith('+') and not x.startswith('+++'):
-                self.last_commit.increment_loc(self.file_type_ppp)
-                if self.file_type_ppp <FileTypes.PYAPI:
-                    self.locs += 1
-
-            if x.startswith('-') and not x.startswith('---'):
-                self.last_commit.decrement_loc(self.file_type_mmm)
-                if self.file_type_mmm < FileTypes.PYAPI:
-                    self.locs -= 1
-
-            # if nnn>1000000:
-            #     break
-
-        self.pop()
-
-    def save_report(self, filename):
-        print("Saving report in {0}".format(filename))
-        with open(filename, 'w') as the_file:
-            for key in self.days_history:
-                dayhist = self.days_history[key]
-                pstr = "%s %s \n" % (str(dayhist.date), ' '.join(str(e) for e in dayhist.loc_for_type))
-                the_file.write(pstr)
diff --git a/devtools/linecount/baloc/history_plot.py b/devtools/linecount/baloc/history_plot.py
deleted file mode 100644
index 73eabfc5792..00000000000
--- a/devtools/linecount/baloc/history_plot.py
+++ /dev/null
@@ -1,63 +0,0 @@
-import matplotlib.pyplot as plt
-import seaborn as sns
-from datetime import datetime
-from .file_types import FileTypes, filetype
-
-
-selected_file_type = [FileTypes.CORE, FileTypes.FTEST, FileTypes.UTEST, FileTypes.GUI, FileTypes.PYAPI]
-
-
-def read_history(filename):
-    xvals = []  # Time
-    ydata = {}  # id of file type .vs. LOC .vs. time
-    for x in selected_file_type:
-        ydata[x] = []
-
-    print("Reading file {0}".format(filename))
-    with open(filename, 'r') as the_file:
-        for line in the_file:
-            parts = line.strip().split()
-            date = datetime.strptime(parts[0] + " " + parts[1], '%Y-%m-%d %H:%M:%S')
-            xvals.append(date)
-            for x in selected_file_type:
-                ydata[x].append(int(parts[2+x]))
-
-    yvals = []
-    descr = []
-    for key in ydata:
-        descr.append(FileTypes.descr[key])
-        yvals.append(ydata[key])
-
-    # printing summary of LOC
-    for x in range(0, len(yvals)):
-        print("{:18} : {:10}".format(descr[x], yvals[x][-1]))
-
-    return xvals, yvals, descr
-
-
-def history_plot(filename):
-    xvals, yvals, descr = read_history(filename)
-
-    # figure size
-    my_dpi = 96
-    plt.figure(figsize=(1600*1.2 / my_dpi, 900*1.2 / my_dpi), dpi=my_dpi)
-    plt.style.use('seaborn-bright')
-
-    # making stackplot
-    plt.stackplot(xvals, yvals)
-    pal = ["#3399ff", "#ffcc00", "#ff0000", "#0033ff", "#999999"]
-    plt.stackplot(xvals, yvals, labels=descr, colors=pal)
-
-    # styling axes and grid
-    plt.grid(color='gray', linestyle='dashed')
-    ax = plt.gca()
-    ax.set_axisbelow(True)
-    plt.ylim(0.0, 220e+03)
-    plt.tick_params(axis='both', which='major', labelsize=14)
-
-    # making inverse legend
-    handles, labels = ax.get_legend_handles_labels()
-    ax.legend(handles[::-1], labels[::-1], loc='upper left', prop={'size': 18})
-
-    # saving plot
-    plt.savefig('lines_of_code.png', dpi=my_dpi, bbox_inches='tight')
diff --git a/devtools/linecount/lines_of_code.py b/devtools/linecount/lines_of_code.py
deleted file mode 100755
index 2366fa6f5a4..00000000000
--- a/devtools/linecount/lines_of_code.py
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/usr/bin/env python3
-"""
-Creates picture with number of lines of code.
-Usage: python3 lines_of_code.py
-
-The command should be executed in the directory where lines_of_code.py is located
-(i.e. in <BornAgain>/devtools/linecount)
-"""
-import sys
-if sys.version_info < (3, 0):
-    exit("Requires python3, exiting ...")
-import os
-from baloc import HistoryCollector
-from baloc import history_plot
-import matplotlib.pyplot as plt
-
-
-gitlog_filename = "gitlog.tmp"
-
-
-def process_loc_number(targetfolder="../..", gitlog=gitlog_filename):
-    prevfolder = os.getcwd()
-    os.chdir(targetfolder)
-
-    collector = HistoryCollector()
-    collector.run()
-    collector.save_report(os.path.join(prevfolder, gitlog))
-
-    os.chdir(prevfolder)
-
-
-def plot_loc_number(gitlog=gitlog_filename):
-    history_plot(gitlog)
-    plt.show()
-
-
-if __name__ == '__main__':
-    print('-' * 80)
-    print("Generating picture for number of lines of code")
-    print('-' * 80)
-    print(" ")
-    print("Possible options:")
-    print("[0] - Generate {0} and picture.".format(gitlog_filename))
-    print("[1] - Generate only {0}.".format(gitlog_filename))
-    print("[2] - Generate picture using existing {0}.".format(gitlog_filename))
-    print("[3] - Exit")
-
-    var = int(input("Enter your choice [0]: ") or "0")
-
-    if var == 0:
-        process_loc_number()
-        plot_loc_number()
-    elif var == 1:
-        process_loc_number()
-    elif var == 2:
-        plot_loc_number()
-    else:
-        exit("Good bye")
-- 
GitLab


From 06c790a1be052e12f78daa09013330f182541641 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de>
Date: Tue, 11 Apr 2023 18:21:56 +0200
Subject: [PATCH 2/5] devtools: script names uniformly with hyphen

---
 Tests/Suite/Persist/Check.cpp                           | 4 ++--
 devtools/view/{plot_diff_int.py => plot-diff.py}        | 0
 devtools/view/{plot_int.py => plot-int.py}              | 0
 devtools/view/{plot_numpy_array.py => plot-np-array.py} | 0
 4 files changed, 2 insertions(+), 2 deletions(-)
 rename devtools/view/{plot_diff_int.py => plot-diff.py} (100%)
 rename devtools/view/{plot_int.py => plot-int.py} (100%)
 rename devtools/view/{plot_numpy_array.py => plot-np-array.py} (100%)

diff --git a/Tests/Suite/Persist/Check.cpp b/Tests/Suite/Persist/Check.cpp
index 7a40ca9d0b2..4c09ffd4b9f 100644
--- a/Tests/Suite/Persist/Check.cpp
+++ b/Tests/Suite/Persist/Check.cpp
@@ -61,9 +61,9 @@ bool checkSimulation(const std::string& name, ISimulation& direct_simulation, co
         BaseUtils::Filesystem::jointPath(BATesting::TestOutDir_Suite(), name + ".int.gz");
     IOFactory::writeDatafield(*result_data, out_fname);
     std::cout << "Notes:\n- to visualize an intensity map, use " << BABuild::srcDir()
-              << "/devtools/view/plot_int.py\n"
+              << "/devtools/view/plot-int.py\n"
               << "- to plot a difference image, use " << BABuild::srcDir()
-              << "/devtools/view/plot_diff_int.py\n"
+              << "/devtools/view/plot-diff.py\n"
               << "- if the new simulation result\n"
               << "    " << out_fname << "\n"
               << "  is correct, then move it to the reference directory\n"
diff --git a/devtools/view/plot_diff_int.py b/devtools/view/plot-diff.py
similarity index 100%
rename from devtools/view/plot_diff_int.py
rename to devtools/view/plot-diff.py
diff --git a/devtools/view/plot_int.py b/devtools/view/plot-int.py
similarity index 100%
rename from devtools/view/plot_int.py
rename to devtools/view/plot-int.py
diff --git a/devtools/view/plot_numpy_array.py b/devtools/view/plot-np-array.py
similarity index 100%
rename from devtools/view/plot_numpy_array.py
rename to devtools/view/plot-np-array.py
-- 
GitLab


From 866e9134cbaf98842c45dab4f2590006632c0a01 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de>
Date: Tue, 11 Apr 2023 18:23:52 +0200
Subject: [PATCH 3/5] devtools: rm MPI scripts

---
 devtools/mpi/pytests/mpi_cpp_test.py |  76 --------------------
 devtools/mpi/pytests/mpi_test.py     | 103 ---------------------------
 devtools/mpi/pytests/version.py      |   2 -
 devtools/mpi/supermuc.sh             |  17 -----
 4 files changed, 198 deletions(-)
 delete mode 100644 devtools/mpi/pytests/mpi_cpp_test.py
 delete mode 100644 devtools/mpi/pytests/mpi_test.py
 delete mode 100644 devtools/mpi/pytests/version.py
 delete mode 100644 devtools/mpi/supermuc.sh

diff --git a/devtools/mpi/pytests/mpi_cpp_test.py b/devtools/mpi/pytests/mpi_cpp_test.py
deleted file mode 100644
index ccc8774a3d5..00000000000
--- a/devtools/mpi/pytests/mpi_cpp_test.py
+++ /dev/null
@@ -1,76 +0,0 @@
-# Mixture of cylinders and prisms without interference
-
-from mpi4py import MPI # this line has to be first
-import numpy
-import matplotlib
-import pylab
-from libBornAgainCore import *
-
-comm = MPI.COMM_WORLD
-world_size = comm.Get_size()
-world_rank = comm.Get_rank()
-
-
-def get_sample():
-    """
-    Build and return the sample representing cylinders and pyramids on top of
-    substrate without interference.
-    """
-    # defining materials
-    m_air = HomogeneousMaterial("Air", 0.0, 0.0)
-    m_substrate = HomogeneousMaterial("Substrate", 6e-6, 2e-8)
-    m_particle = HomogeneousMaterial("Particle", 6e-4, 2e-8)
-
-    # collection of particles
-    cylinder_ff = FormFactorCylinder(5*nanometer, 5*nanometer)
-    cylinder = Particle(m_particle, cylinder_ff)
-    prism_ff = FormFactorPrism3(10*nanometer, 5*nanometer)
-    prism = Particle(m_particle, prism_ff)
-    particle_layout = ParticleLayout()
-    particle_layout.addParticle(cylinder, 0.5)
-    particle_layout.addParticle(prism, 0.5)
-
-    # air layer with particles and substrate form multi layer
-    air_layer = Layer(m_air)
-    air_layer.addLayout(particle_layout)
-    substrate_layer = Layer(m_substrate)
-    multi_layer = MultiLayer()
-    multi_layer.addLayer(air_layer)
-    multi_layer.addLayer(substrate_layer)
-    return multi_layer
-
-
-def get_simulation():
-    """
-    Create and return GISAS simulation with beam and detector defined
-    """
-    simulation = GISASSimulation()
-    simulation.setDetectorParameters(100, -1.0*degree, 1.0*degree, 100, 0.0*degree, 2.0*degree)
-    simulation.setBeamParameters(1.0*angstrom, 0.2*degree, 0.0*degree)
-    sample = get_sample()
-    simulation.setSample(sample)
-
-    return simulation
-
-
-def run_simulation():
-    """
-    Run simulation and plot results
-    """
-    simulation = get_simulation()
-
-    if(world_size == 1):
-        print("Not an MPI environment, run with 'mpirun -n 4 python ompi_sim_example.py'")
-        exit(0)
-
-    simulation.runMPISimulation()
-
-    if(world_rank == 0):
-        sumresult = simulation.result().array()
-        print(sumresult)
-        # pylab.imshow(sumresult + 1, norm=matplotlib.colors.LogNorm(), extent=[-1.0, 1.0, 0, 2.0])
-        # pylab.show()
-
-
-if __name__ == '__main__':
-    run_simulation()
diff --git a/devtools/mpi/pytests/mpi_test.py b/devtools/mpi/pytests/mpi_test.py
deleted file mode 100644
index 367c46d41a7..00000000000
--- a/devtools/mpi/pytests/mpi_test.py
+++ /dev/null
@@ -1,103 +0,0 @@
-# Mixture of cylinders and prisms without interference (IsGISAXS example ex-1)
-
-from mpi4py import MPI # this line has to be first
-import numpy
-import matplotlib
-import pylab
-from libBornAgainCore import *
-
-comm = MPI.COMM_WORLD
-world_size = comm.Get_size()
-world_rank = comm.Get_rank()
-
-
-def get_sample():
-    """
-    Build and return the sample representing cylinders and pyramids on top of
-    substrate without interference.
-    """
-    # defining materials
-    m_air = HomogeneousMaterial("Air", 0.0, 0.0)
-    m_substrate = HomogeneousMaterial("Substrate", 6e-6, 2e-8)
-    m_particle = HomogeneousMaterial("Particle", 6e-4, 2e-8)
-
-    # collection of particles
-    cylinder_ff = FormFactorCylinder(5*nanometer, 5*nanometer)
-    cylinder = Particle(m_particle, cylinder_ff)
-    prism_ff = FormFactorPrism3(10*nanometer, 5*nanometer)
-    prism = Particle(m_particle, prism_ff)
-    particle_layout = ParticleLayout()
-    particle_layout.addParticle(cylinder, 0.5)
-    particle_layout.addParticle(prism, 0.5)
-
-    # air layer with particles and substrate form multi layer
-    air_layer = Layer(m_air)
-    air_layer.addLayout(particle_layout)
-    substrate_layer = Layer(m_substrate)
-    multi_layer = MultiLayer()
-    multi_layer.addLayer(air_layer)
-    multi_layer.addLayer(substrate_layer)
-    return multi_layer
-
-
-def get_simulation():
-    """
-    Create and return GISAXS simulation with beam and detector defined
-    """
-    simulation = GISASSimulation()
-    simulation.setDetectorParameters(100, -1.0*degree, 1.0*degree, 100, 0.0*degree, 2.0*degree)
-    simulation.setBeamParameters(1.0*angstrom, 0.2*degree, 0.0*degree)
-    sample = get_sample()
-    simulation.setSample(sample)
-
-    return simulation
-
-
-def run_simulation():
-    """
-    Run simulation and plot results
-    """
-    simulation = get_simulation()
-
-    if(world_size == 1):
-        print("Not a MPI environment, run with 'mpirun -n 4 python ompi_sim_example.py'")
-        exit(0)
-
-    if(world_rank != 0):
-        options = simulation.getOptions()
-        thread_info = ThreadInfo()
-        thread_info.n_threads = options.getNumberOfThreads()
-        thread_info.n_batches = world_size - 1
-        thread_info.current_batch = world_rank - 1
-        options.setThreadInfo(thread_info)
-        simulation.setOptions(options)
-        print("preparing to run ", thread_info.n_batches, thread_info.current_batch)
-        simulation.runSimulation()
-        print("preparing to send")
-        comm.Send(simulation.result().array(), 0)
-
-    if(world_rank == 0):
-        sumresult = simulation.result().array()
-        print(sumresult)
-        sumresult = numpy.zeros(sumresult.shape)
-        print(sumresult)
-
-        print("preparing to receive")
-        for i_proc in range(1, world_size):
-            print("  ... receiving", i_proc)
-            result = numpy.zeros(sumresult.shape)
-            comm.Recv(result, i_proc)
-            sumresult += result
-        print(sumresult)
-
-    if(world_rank == 0):
-        print(sumresult)
-        # pylab.imshow(sumresult + 1, norm=matplotlib.colors.LogNorm(), extent=[-1.0, 1.0, 0, 2.0])
-        # pylab.show()
-
-
-if __name__ == '__main__':
-    run_simulation()
-
-
-
diff --git a/devtools/mpi/pytests/version.py b/devtools/mpi/pytests/version.py
deleted file mode 100644
index 261a6512c03..00000000000
--- a/devtools/mpi/pytests/version.py
+++ /dev/null
@@ -1,2 +0,0 @@
-import sys
-print(sys.version)
diff --git a/devtools/mpi/supermuc.sh b/devtools/mpi/supermuc.sh
deleted file mode 100644
index ce93ec8cdb5..00000000000
--- a/devtools/mpi/supermuc.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-# Setup for BornAgain compilation at SuperMUC LRZ cluster
-
-
-module load git
-module load gcc/4.7
-module load cmake/2.8
-module load fftw/mpi/3.3
-module load gsl
-#module load python/2.7_anaconda
-
-export LD_LIBRARY_PATH=/home/hpc/pr87me/di29sok/software/boost_1_55_0.gcc47/lib:$LD_LIBRARY_PATH
-
-export FFTW3=$FFTW_BASE
-export GSL_DIR=$GSL_BASE
-export BOOST_ROOT=/home/hpc/pr87me/di29sok/software/boost_1_55_0.gcc47
-
-
-- 
GitLab


From e42cc010278df81bb1c1c6e3a1bb0580d8843d81 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de>
Date: Tue, 11 Apr 2023 18:24:44 +0200
Subject: [PATCH 4/5] devtools: update README

---
 devtools/README.md | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/devtools/README.md b/devtools/README.md
index bdfb625a80e..19f7ec8d2fa 100644
--- a/devtools/README.md
+++ b/devtools/README.md
@@ -1,4 +1 @@
-Various tools for BornAgain developers.
-
-Note that this directory receives only little, and irregular, attention.
-Much of the material is outdated or obsolete.
+Various tools for BornAgain maintainers.
-- 
GitLab


From 3f2f83102b1e433a5e7fd2a435202a01e9b99f11 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de>
Date: Tue, 11 Apr 2023 18:25:08 +0200
Subject: [PATCH 5/5] devtools: rm outdated architecture analyses

---
 devtools/architecture/DepthProbe.md           |  32 -----
 devtools/architecture/Lattice.md              |  21 ---
 .../architecture/ParameterDistribution.md     | 117 ----------------
 devtools/architecture/Scattering.md           | 126 ------------------
 4 files changed, 296 deletions(-)
 delete mode 100644 devtools/architecture/DepthProbe.md
 delete mode 100644 devtools/architecture/Lattice.md
 delete mode 100644 devtools/architecture/ParameterDistribution.md
 delete mode 100644 devtools/architecture/Scattering.md

diff --git a/devtools/architecture/DepthProbe.md b/devtools/architecture/DepthProbe.md
deleted file mode 100644
index 2ee5e194979..00000000000
--- a/devtools/architecture/DepthProbe.md
+++ /dev/null
@@ -1,32 +0,0 @@
-## How does BornAgain compute depth profiles
-
-Analysis of BornAgain v1.19.0
-
-### Simulation computes an incoherent sum
-
-We consider a simulation handled by class `DepthProbeSimulation < ISimulation`
-(where `<` indicates inheritance).
-
-The function `ISimulation::runSimulation`
-- calls `ISimulation::prepareSimulation`, which
-    - does nothing of interest, except for sample builders
-- loops over parameter combinations, thereby performing an incoherent summation:
-  - for each parameter set, `runSingleSimulation`;
-- calls `DepthProbeSimulation::moveDataFromCache` to collect results.
-  - also calls `transferResultsToIntensityMap`, which does nothing except for `OffSpecSimulation`.
-
-`ISimulation::runSingleSimulation` handles the multithreaded parallel computation
-for batches of detector pixels (`SimulationElement`s). It
-- uses `DepthProbeSimulation::generateSingleThreadedComputation`
-    to create instances of `DepthProbeComputation < IComputation`;
-- for each instance, runs `IComputation.run`;
-- calls `ISimulation2D::normalize`;
-- calls `ISimulation2D::addBackgroundIntensity`.
-
-The `IComputation` constructor creates the member `ProcessedSample m_processed_sample`.
-
-The `DepthProbeComputation` constructor
-    sets the member `DepthProbeComputationTerm m_computation_term`
-    using `ProcessedSample` ...?...
-
-`DepthProbeComputationTerm::compute` computes intensities for all z at one alpha_i.
diff --git a/devtools/architecture/Lattice.md b/devtools/architecture/Lattice.md
deleted file mode 100644
index 8c6d38792c4..00000000000
--- a/devtools/architecture/Lattice.md
+++ /dev/null
@@ -1,21 +0,0 @@
-## Lattices
-
-Typical sample construction with a 3d lattice:
-```
-    lattice = ba.FCCLattice(30*nm).transformed(rot.getTransform3D())
-    peak_shape = ba.MisesFisherGaussPeakShape(peak_intensity, peak_width, zenith, kappa, kappa2)
-    iff = ba.InterferenceFunction3DLattice(lattice)
-    iff.setPositionVariance(1.)
-    iff.setPeakShape(peak_shape)
-
-    layout = ba.ParticleLayout()
-    layout.addParticle(particle)
-    layout.setTotalParticleSurfaceDensity(.01)
-    layout.setInterferenceFunction(iff)
-    layout.setWeight(1.0)
-
-    vacuum_layer = ba.Layer(m_vacuum)
-    vacuum_layer.addLayout(layout)
-```
-
-`bake::FCCLattice` returns a `Lattice3d` with an fcc primitive cell.
diff --git a/devtools/architecture/ParameterDistribution.md b/devtools/architecture/ParameterDistribution.md
deleted file mode 100644
index 1c774260c98..00000000000
--- a/devtools/architecture/ParameterDistribution.md
+++ /dev/null
@@ -1,117 +0,0 @@
-## Parameter distributions
-
-Analysis of BornAgain develop, per 3dec20.
-
-It seems there are two different ways for handling parameter distributions,
-the one specifically for particle distributions, the other one more generic.
-
-### Particle distribution
-
-#### Typical use
-
-Typical use of parameter distributions is described in
-`Examples/Python/sim01_Particles/CylindersWithSizeDistribution.py`:
-```
-def get_sample():
-    # Define materials and form factor ...
-
-    # Define particles
-    particle = ba.Particle(material_Particle, ff)
-
-    # Define particles with parameter following a distribution
-    distr_1 = ba.DistributionGaussian(5.0*nm, 1.0*nm)
-    par_distr_1 = ba.ParameterDistribution(
-        "/Particle/Cylinder/Radius", distr_1, 100, 2.0)
-    particle_distrib = ba.ParticleDistribution(particle, par_distr_1)
-
-    # Define particle layouts
-    layout = ba.ParticleLayout()
-    layout.addParticle(particle_distrib, 1.0)
-
-    # Define layers
-    layer = ba.Layer(material_Vacuum)
-    layer.addLayout(layout)
-
-    # Define sample
-    sample = ba.MultiLayer()
-    sample.addLayer(layer)
-
-    return sample
-
-
-def get_simulation():
-    simulation = ba.ScatteringSimulation()
-    simulation.setDetectorParameters(200, 0.0*deg, 2.0*deg, 200, 0.0*deg, 2.0*deg)
-    simulation.setBeamParameters(1.0*angstrom, 0.2*deg, 0.0*deg)
-    return simulation
-
-
-def run_simulation():
-    simulation = get_simulation()
-    simulation.setSample(get_sample())
-    simulation.runSimulation()
-    return simulation.result()
-```
-
-#### What goes on behind the scenes?
-
-Class hierarchy:
-```
-IParametricComponent
-- INode
-  - ISampleNode
-    - IAbstractParticle
-      - ParticleDistribution (final)
-      - IParticle
-        - Particle (final)
-        - CoreAndShell (final)
-        ... (all final)
-- ISampleBuilder
-- DistributionHandler (final)
-- ParameterDistribution (final)
-```
-
-As we see from the `CylindersWithSizeDistribution` example,
-a `ParticleDistribution` is bound to a `ParticleLayout`.
-The drawing of `IParticle`s from the distribution happens here:
-
-```
-SafePointerVector<IParticle> ParticleLayout::particles() const {
-    SafePointerVector<IParticle> particle_vector;
-    for (const auto* particle : m_particles) {
-        if (const auto* p_part_distr = dynamic_cast<const ParticleDistribution*>(particle)) {
-            SafePointerVector<IParticle> generated_particles = p_part_distr->generateParticles();
-            for (const IParticle* particle : generated_particles)
-                particle_vector.push_back(particle->clone());
-        } else if (const auto* p_iparticle = dynamic_cast<const IParticle*>(particle)) {
-            particle_vector.push_back(p_iparticle->clone());
-        }
-    }
-    return particle_vector;
-}
-```
-
-### Generic distribution handler
-
-This mechanism acts almost on top of the simulation model hierarchy.
-
-`ISimulation` has member `DistributionHandler m_distribution_handler`.
-It is modified through `ISimulation::addParameterDistribution`.
-This function is called explicitly by some standard simulations and Python scripts
-(e.g. `sim03_Structures/Interference2DLatticeSumOfRotated.py`),
-but not in the above simple example.
-
-
-```
-void ISimulation::runSimulation() {
-    ...
-    size_t param_combinations = m_distribution_handler.getTotalNumberOfSamples();
-    std::unique_ptr<ParameterPool> param_pool(createParameterTree());
-    for (size_t index = 0; index < param_combinations; ++index) {
-        double weight = m_distribution_handler.setParameterValues(param_pool.get(), index);
-        runSingleSimulation(batch_start, batch_size, weight);
-    }
-    m_distribution_handler.setParameterToMeans(param_pool.get());
-    ...
-}
-```
diff --git a/devtools/architecture/Scattering.md b/devtools/architecture/Scattering.md
deleted file mode 100644
index ca15543a9f9..00000000000
--- a/devtools/architecture/Scattering.md
+++ /dev/null
@@ -1,126 +0,0 @@
-## How does BornAgain compute scattering?
-
-Analysis of BornAgain develop
-- per 18nov20, after merge of https://github.com/scgmlz/BornAgain/pull/1105
-- partly checked and improved 24jun21
-
-### Run parallel simulations
-
-We consider a GISAS simulation, handled by class `ScatteringSimulation < ISimulation2D < ISimulation`
-(where `<` indicates inheritance).
-
-The function `ScatteringSimulation::runSimulation`
-- calls `ISimulation::prepareSimulation`;
-  - calls `Instrument::initDetector`,
-  - calls `ISimulation2D::prepareSimulation`
-    - calls `ISimulation::prepareSimulation`
-      - does nothing of interest, except for sample builders
-    - calls `IDetector2D::createContext`
-- loops over parameter combinations, thereby performing an incoherent summation:
-  - for each parameter set, `runSingleSimulation`;
-- calls `ISimulation2D::moveDataFromCache` to collect results.
-  - also calls `transferResultsToIntensityMap`, which does nothing except for `OffSpecSimulation`.
-
-`ScatteringSimulation::prepareSimulation` seems to be mostly concerned with `SampleBuilder`s.
-
-`ISimulation::runSingleSimulation` handles the multithreaded parallel computation
-for batches of detector pixels (`SimulationElement`s). It
-- uses `ISimulation2D::generateSingleThreadedComputation`
-    to create instances of `DWBAComputation < IComputation`;
-- for each instance, runs `IComputation.run`;
-- calls `ISimulation2D::normalize`;
-- calls `ISimulation2D::addBackgroundIntensity`.
-
-The `IComputation` constructor creates the member `up<ProcessedSample> m_processed_sample`
-  by calling the c'tor `ProcessedSample(sample, sim_options, forcePolarized)`
-
-The `DWBAComputation` constructor
-populates the member `DWBASingleComputation m_single_computation`:
-- For each `ProcessedLayout` in `m_processed_sample->layouts()`,
-    the vector `DWBASingleComputation::m_layout_comps`
-      is given a `new ParticleLayoutComputation` member;
-- if `m_processed_sample->hasRoughness()`,
-    then `DWBASingleComputation::m_roughness_comp`
-      points to a `new RoughMultiLayerComputation`.
-
-`IComputation::run` calls `DWBAComputation::runProtected`,
-  which for each `SimulationElement` in the batch calls `m_single_computation.compute`.
-
-### Compute scattering as incoherent sum
-
-`DWBASingleComputation::compute(SimulationElement& ele)`
-Computes Fresnel coefficients (`Fluxes`),
-  and transfers them to `ele`.
-  They will be used at the very end of the call following call chains
-  - in `ComputeDWBA::computeFF` for scattering from particles
-
-Then it performs an incoherent summation
-  by calling functions `compute(ele)`
-    that increment `ele.m_intensity`.
-This is done
-- from each `ProcessedLayout`,
-- from each rough interface,
-- from transmission(?) and specular reflection.
-
-### Scattering from a particle layout
-
-The `ParticleLayoutComputation` constructor
-points the member `m_interference_function_strategy`
-  to a `new DecouplingApproximationStrategy`,
-unless we are simulating a radial paracrystal,
-  for which the `SSCApproximationStrategy` is used.
-
-`ParticleLayoutComputation::compute`
-  increments `SimulationElement::m_intensity`
-    by a scattering intensity times the `ProcessedLayout::surfaceDensity()`.
-The intensity is computed by `IInterferenceFunctionStrategy::evaluate`.
-Except for Monte-Carlo integration,
-  this wraps just one call to `IInterferenceFunctionStrategy::evaluateSinglePoint`.
-For unpolarized scattering, and except for radial paracrystals,
-  the next call goes to `DecouplingApproximationStrategy::scalarCalculation`.
-
-`DecouplingApproximationStrategy::scalarCalculation`
-  performs a coherent and an incoherent summation
-    over scattering amplitudes `ff`
-      obtained by calling `FormFactorCoherentSum::summedFF`
-        on members of `ProcessedLayout::formFactorList()`.
-The mixed sum is sum
-
-> |ff|^2 + |sum ff|^2 * (coherence_factor - 1)
-
-where coherence_factor is computed by `IInterferenceFunction::evaluate`.
-
-Except for superlattices, there is no "inner" structure,
-and therefore `IInterferenceFunction::evaluate` just wraps `IInterferenceFunction::iff_no_inner`,
-so that
-
-> coherence_factor = DWfactor(q) * (iff_without_dw(q) * outer_iff - 1) + 1.
-
-By default, outer_iff = 1, so that
-
-> coherence_factor = DWfactor(q) * (iff_without_dw - 1) + 1.
-
-For the simplest of all interference functions,
-`InterferenceFunctionNone::iff_without_dw` just returns 1, so that
-
-> coherence_factor = 1.
-
-### Computing the particle formfactor
-
-`FormFactorCoherentSum::summedFF` returns the sum over `FormFactorCoherentPart::coherentFF`.
-
-`FormFactorCoherentPart::coherentFF` makes use of `SimulationElement::fresnelMap`
-to compute `in` and `out` coefficients.
-
-`FormFactorCoherentPart` wraps an `IComputeFF` and additionally holds
-member `m_layer_index`
-that is set by `FormFactorCoherentPart::setSpecularInfo`.
-This information is forwarded by calling `IComputeFF::setSpecularInfo`,
-which does nothing, unless overridden in `ComputeDWBA`.
-
-After this preparation, `ComputeDWBA::computeFF`
-computes the coherent sum over the four DWBA terms.
-Each of them uses the scattering amplitude from `IFormFactor::evaluate`,
-which is pure virtual, overridden by `IFormFactorBorn::evaluate`,
-which calls `IFormFactorBorn::evaluate_for_q`,
-which is pure virtual, overriden by shape-specific classes like `FormFactorSphere`.
-- 
GitLab