diff --git a/wetb/dlc/high_level.py b/wetb/dlc/high_level.py
index ea6421676cc5ce86d1488b444859c8f1d0c62215..d405e3504c3aa77bf3d6e8d449e3665d3cce18b5 100644
--- a/wetb/dlc/high_level.py
+++ b/wetb/dlc/high_level.py
@@ -12,17 +12,26 @@ import functools
 
 from wetb.hawc2.sel_file import SelFile
 from wetb.functions.caching import cache_function
+from collections import OrderedDict
 HOURS_PR_20YEAR = 20 * 365 * 24
 
 def Weibull(u, k, start, stop, step):
     C = 2 * u / np.sqrt(np.pi)
     cdf = lambda x :-np.exp(-(x / C) ** k)
+
     return {wsp:-cdf(wsp - step / 2) + cdf(wsp + step / 2) for wsp in np.arange(start, stop + step, step)}
 
+def Weibull2(u, k, wsp_lst):
+    C = 2 * u / np.sqrt(np.pi)
+    cdf = lambda x :-np.exp(-(x / C) ** k)
+    edges = np.r_[wsp_lst[0] - (wsp_lst[1] - wsp_lst[0]) / 2, (wsp_lst[1:] + wsp_lst[:-1]) / 2, wsp_lst[-1] + (wsp_lst[-1] - wsp_lst[-2]) / 2]
+    return [-cdf(e1) + cdf(e2) for wsp, e1, e2 in zip(wsp_lst, edges[:-1], edges[1:])]
+
 
 class DLCHighLevel(object):
-    def __init__(self, filename):
+    def __init__(self, filename, fail_on_resfile_not_found=False):
         self.filename = filename
+        self.fail_on_resfile_not_found = fail_on_resfile_not_found
         wb = xlrd.open_workbook(self.filename)
 
         # Variables
@@ -38,9 +47,21 @@ class DLCHighLevel(object):
         #DLC sheet
         sheet = wb.sheet_by_name("DLC")
         self.dlc_df = pd.DataFrame({sheet.cell(0, col_index).value.lower(): [sheet.cell(row_index, col_index).value for row_index in range(2, sheet.nrows) if sheet.cell(row_index, 0).value != ""] for col_index in range(sheet.ncols)})
-        for k in ['name', 'load', 'wsp', 'wdir', 'dlc_dist', 'wsp_dist', 'wdir_dist']:
+        for k in ['load', 'dlc_dist', 'wsp_dist']:
             assert k.lower() in self.dlc_df.keys(), "DLC sheet must have a '%s' column" % k
-        self.dlc_df['name'] = [n.lower().replace("dlc", "") for n in self.dlc_df['name']]
+        self.dist_value_keys = [('dlc_dist', 'dlc'), ('wsp_dist', 'wsp')]
+        self.dist_value_keys.extend([(k, k.replace("_dist", "")) for k in self.dlc_df.keys() if k.endswith("_dist") and k not in ('dlc_dist', 'wsp_dist')])
+        for i, (dk, vk) in enumerate(self.dist_value_keys):
+            try:
+                assert vk in self.dlc_df.keys(), "DLC sheet must have a '%s'-column when having a '%s'-column" % (vk, dk)
+            except AssertionError as e:
+                if vk == "dlc" and 'name' in self.dlc_df.keys():
+                    columns = list(self.dlc_df.columns)
+                    columns[columns.index('name')] = 'dlc'
+                    self.dlc_df.columns = columns
+                else:
+                    raise e
+            self.dlc_df[vk] = [str(n).lower().replace(vk, "") for n in self.dlc_df[vk]]
         if 'psf' not in self.dlc_df:
             self.dlc_df['psf'] = 1
 
@@ -85,36 +106,90 @@ class DLCHighLevel(object):
         wdir = get_lst(dlc_row['wdir'])
         return wsp, wdir
 
+    def distribution(self, value_key, dist_key, row):
+        values = self.dlc_df[value_key][row]
+        if ":" in values:
+            start, step, stop = [float(eval(v, globals(), self.__dict__)) for v in values.lower().split(":")]
+            values = np.arange(start, stop + step, step)
+        else:
+            values = [(eval(v, globals(), self.__dict__)) for v in str(values).lower().replace("/", ",").split(",")]
+
+        dist = self.dlc_df[dist_key][row]
+        if str(dist).lower() == "weibull" or str(dist).lower() == "rayleigh":
+            dist = Weibull2(self.vref * .2, 2, values)
+        else:
+            def fmt(v):
+                if "#" in str(v):
+                    return v
+                else:
+                    if v == "":
+                        return 0
+                    else:
+                        return float(v) / 100
+            dist = [fmt(v) for v in str(self.dlc_df[dist_key][row]).replace("/", ",").split(",")]
+        assert len(values) == len(dist), "Number of %s-values (%d)!= number of %s-values(%d)" % (value_key, len(values), dist_key, len(dist))
+        return OrderedDict(zip(map(self.format_tag_value, values), dist))
+
     def fatigue_distribution(self):
         fatigue_dist = {}
-        data = self.dlc_df  #[[sheet.cell(row_index, col_index).value for row_index in range(1, sheet.nrows)] for col_index in range(sheet.ncols)]
-        for i, load in enumerate(data['load']):
-            if "F" in str(load).upper():
-                dlc = data['name'][i].lower().replace("dlc", "")
-                def fmt(v):
-                    if "#" in str(v):
-                        return v
-                    else:
-                        if v == "":
-                            return 0
-                        else:
-                            return float(v) / 100
-                dlc_dist = fmt(data['dlc_dist'][i])
-                wsp_dist = data['wsp_dist'][i]
-                wsp = data['wsp'][i]
-                if wsp_dist.lower() == "weibull" or wsp_dist.lower() == "rayleigh":
-                    start, step, stop = [float(eval(v, globals(), self.__dict__)) for v in wsp.lower().split(":")]
-                    wsp_dist = Weibull(self.vref * .2, 2, start, stop, step)
-                else:
-                    wsp = [(eval(v, globals(), self.__dict__)) for v in str(wsp).lower().replace("/", ",").split(",")]
-                    wsp_dist = [fmt(v) for v in str(wsp_dist).lower().replace("/", ",").split(",")]
-                    assert len(wsp) == len(wsp_dist), "\nWsp: %s\nWsp_dist: %s" % (wsp , wsp_dist)
-                    wsp_dist = {k:v  for k, v in zip(wsp, wsp_dist)}
-                wdir_dist = [float(v) for v in str(data['wdir_dist'][i]).replace("/", ",").split(",")]
-                wdir = [float(v) for v in str(data['wdir'][i]).replace("/", ",").split(",")]
-                fatigue_dist[dlc] = (dlc_dist, wsp_dist, {k:v / 100 for k, v in zip(wdir, wdir_dist)})
+        for row, load in enumerate(self.dlc_df['load']):
+            if "F" not in str(load).upper():
+                continue
+            dlc = self.dlc_df[self.dist_value_keys[0][1]][row]
+            fatigue_dist[str(dlc)] = [self.distribution(value_key, dist_key, row) for dist_key, value_key in self.dist_value_keys]
         return fatigue_dist
 
+
+
+    def files_dict(self):
+        if not hasattr(self, "res_folder") or self.res_folder == "":
+            files = glob.glob(os.path.join(self.res_path, "*.sel")) + glob.glob(os.path.join(self.res_path, "*/*.sel"))
+        else:
+            files = []
+            fatigue_dlcs = self.dlc_df[['F' in str(l).upper() for l in self.dlc_df['load']]]['dlc']
+            for dlc_id in fatigue_dlcs:
+                dlc_id = str(dlc_id)
+                if "%" in self.res_folder:
+                    folder = self.res_folder % dlc_id
+                else:
+                    folder = self.res_folder
+                files.extend(glob.glob(os.path.join(self.res_path , folder, "*.sel")))
+        keys = list(zip(*self.dist_value_keys))[1]
+        fmt = self.format_tag_value
+        tags = [[fmt(tag.replace(key, "")) for tag, key in zip(os.path.basename(f).split("_"), keys)] for f in files]
+        dlc_tags = list(zip(*tags))[0]
+        files_dict = {dlc_tag:{} for dlc_tag in dlc_tags}
+        for tag_row, f in zip(tags, files):
+            d = files_dict[tag_row[0]]
+            for tag in tag_row[1:]:
+                if tag not in d:
+                    d[tag] = {}
+                d = d[tag]
+            if 'files' not in d:
+                d['files'] = []
+            d['files'].append(f)
+        return files_dict
+
+    def format_tag_value(self, v):
+        try:
+            if int(float(v)) == float(v):
+                return int(float(v))
+            return float(v)
+        except ValueError:
+            return v
+
+    def probability(self, props, f, files):
+        total_prop = 1
+        for prop in props[::-1]:
+            if str(prop).startswith("#"):
+                duration = SelFile(f).duration
+                prop = float(prop[1:]) * duration / (60 * 60 * 24 * 365)
+                return prop * total_prop
+            else:
+                total_prop *= prop
+        return total_prop
+
+
     def file_hour_lst(self):
         """Create a list of (filename, hours_pr_year) that can be used as input for LifeTimeEqLoad
 
@@ -127,39 +202,58 @@ class DLCHighLevel(object):
         """
 
         fh_lst = []
-        dlc_dict = self.fatigue_distribution()
-        for dlc_id in sorted(dlc_dict.keys()):
-            dlc_dist, wsp_dict, wdir_dict = dlc_dict[dlc_id]
-            for wsp in sorted(wsp_dict.keys()):
-                wsp_dist = wsp_dict[wsp]
-                for wdir in sorted(wdir_dict.keys()):
-                    wdir_dist = wdir_dict[wdir]
-                    if not hasattr(self, "res_folder"):
-                        folder = ""
-                    elif "%" in self.res_folder:
-                        folder = self.res_folder % dlc_id
+        dist_dict = self.fatigue_distribution()
+        files_dict = self.files_dict()
+
+
+
+        for dlc_id in sorted(dist_dict.keys()):
+            dlc_id = str(dlc_id)
+
+            fmt = self.format_tag_value
+            def tag_prop_lst(dist_lst):
+                if len(dist_lst) == 0:
+                    return [[]]
+                return [[(fmt(tag), prop)] + tl for tl in tag_prop_lst(dist_lst[1:]) for tag, prop in dist_lst[0].items()]
+
+            def files_from_tags(self, f_dict, tags):
+                if len(tags) == 0:
+                    return f_dict['files']
+                try:
+                    return files_from_tags(self, f_dict[tags[0]], tags[1:])
+                except KeyError:
+                    if self.dist_value_keys[-len(tags)][1] == "wdir":
+                        try:
+                            return files_from_tags(self, f_dict[tags[0] % 360], tags[1:])
+                        except:
+                            pass
+                    raise
+
+            for tag_props in (tag_prop_lst(dist_dict[dlc_id])):
+                tags, props = zip(*tag_props)
+                try:
+                    files = (files_from_tags(self, files_dict, tags))
+                except KeyError:
+                    if self.fail_on_resfile_not_found:
+                        raise FileNotFoundError("Result files for %s not found" % (", ".join(["%s='%s'" % (dv[1], t) for dv, t in zip(self.dist_value_keys, tags)])))
                     else:
-                        folder = self.res_folder
-                    files = glob.glob(os.path.join(self.res_path , folder, "dlc%s_wsp%02d_wdir%03d*.sel" % (dlc_id, wsp, wdir % 360)))
-                    for f in sorted(files):
-                        if "#" in str(dlc_dist):
-                            duration = SelFile(f).duration
-                            dlc_dist = float(dlc_dist[1:]) * duration / (60 * 60 * 24 * 365)
-                        if "#" in str(wsp_dist):
-                            total = sum([float(v[1:]) for v in wsp_dict.values()])
-                            wsp_dist = float(wsp_dist[1:]) / total
-                        f_prob = dlc_dist * wsp_dist * wdir_dist / len(files)
-                        f_hours_pr_20year = HOURS_PR_20YEAR * f_prob
+                        continue
+                if files:
+                    f_prob = self.probability(props, files[0], files) / len(files)
+                    f_hours_pr_20year = HOURS_PR_20YEAR * f_prob
+                    for f in files:
                         fh_lst.append((f, f_hours_pr_20year))
         return fh_lst
 
+
+
     def dlc_lst(self, load='all'):
-        dlc_lst = np.array(self.dlc_df['name'])[np.array([load == 'all' or load.lower() in d.lower() for d in self.dlc_df['load']])]
+        dlc_lst = np.array(self.dlc_df['dlc'])[np.array([load == 'all' or load.lower() in d.lower() for d in self.dlc_df['load']])]
         return [v.lower().replace('dlc', '') for v in dlc_lst]
 
     @cache_function
     def psf(self):
-        return {dlc.lower().replace('dlc', ''): float((psf, 1)[psf == ""]) for dlc, psf in zip(self.dlc_df['name'], self.dlc_df['psf']) if dlc != ""}
+        return {dlc: float((psf, 1)[psf == ""]) for dlc, psf in zip(self.dlc_df['dlc'], self.dlc_df['psf']) if dlc != ""}
 
 if __name__ == "__main__":
     dlc_hl = DLCHighLevel(r'X:\NREL5MW\dlc.xlsx')
diff --git a/wetb/dlc/tests/test_high_level.py b/wetb/dlc/tests/test_high_level.py
index ea1be643e72ec13520835dce2d67c7078a8b9811..7148cd90a6970e6dd258fe20dda41cfb85f3c401 100644
--- a/wetb/dlc/tests/test_high_level.py
+++ b/wetb/dlc/tests/test_high_level.py
@@ -27,7 +27,7 @@ class TestDLCHighLevel(unittest.TestCase):
 
     def test_fatigue_distribution_pct(self):
         dlc, wsp, wdir = self.dlc_hl.fatigue_distribution()['12']
-        self.assertEqual(dlc, 0.975)
+        self.assertEqual(dlc[12], 0.975)
         self.assertEqual(min(wsp.keys()), 4)
         self.assertEqual(max(wsp.keys()), 26)
         self.assertEqual(wsp[4], 0.11002961306549919)
@@ -66,6 +66,9 @@ class TestDLCHighLevel(unittest.TestCase):
         for k in ['name', 'nr', 'description', 'unit', 'statistic', 'ultimate', 'fatigue', 'm', 'neql', 'bearingdamage', 'mindistance', 'maxdistance', 'extremeload']:
             self.assertTrue(k in self.dlc_hl.sensor_info().keys(), k)
 
+    def test_fail_on_res_not_fount(self):
+        self.dlc_hl = DLCHighLevel('test_files/DLC_test.xlsx', fail_on_resfile_not_found=True)
+        self.assertRaisesRegex(FileNotFoundError, "Result files for dlc='12', wsp='6', wdir='-10' not found")