diff --git a/gwinc/__init__.py b/gwinc/__init__.py
index 640ed7365f593773a5f24691b2b2f909c42c943c..7eba9f33439778f425d295e8c67337f023fd4986 100644
--- a/gwinc/__init__.py
+++ b/gwinc/__init__.py
@@ -1,5 +1,5 @@
 from .ifo import available_ifos, load_ifo
-from .struct import load_struct
+from .struct import Struct
 from .precomp import precompIFO
 from .plot import plot_noise
 from .io import load_hdf5, save_hdf5
diff --git a/gwinc/ifo/__init__.py b/gwinc/ifo/__init__.py
index a51ff4a2c365f6edc51021dfd932534666c1081a..8d83b853beb51356b67e976cd2f8bc14c0c2bd78 100644
--- a/gwinc/ifo/__init__.py
+++ b/gwinc/ifo/__init__.py
@@ -1,7 +1,7 @@
 import os
 import logging
 
-from ..struct import load_struct, STRUCT_EXT
+from ..struct import Struct
 from ..util import load_module
 
 
@@ -28,8 +28,8 @@ def load_ifo(name_or_path):
     Named IFOs should correspond to one of the IFOs available in the
     gwinc package (see gwinc.available_ifos()).  If a path is provided
     it should either be a budget package (directory) or module (ending
-    in .py), or an IFO struct (see gwinc.load_struct()).  In the
-    latter case the base aLIGO budget definition will be used.
+    in .py), or an IFO struct (see gwinc.Struct).  In the latter case
+    the base aLIGO budget definition will be used.
 
     Returns primary Budget class, ifo structure, frequency array, and
     plot style dictionary, with the last three being None if they are
@@ -42,9 +42,9 @@ def load_ifo(name_or_path):
         path = name_or_path.rstrip('/')
         bname, ext = os.path.splitext(os.path.basename(path))
 
-        if ext in STRUCT_EXT:
+        if ext in Struct.STRUCT_EXT:
             logging.info("loading struct {}...".format(path))
-            ifo = load_struct(path)
+            ifo = Struct.from_file(path)
             bname = 'aLIGO'
             modname = 'gwinc.ifo.aLIGO'
             logging.info("loading budget {}...".format(modname))
@@ -69,7 +69,7 @@ def load_ifo(name_or_path):
     ifo = getattr(mod, 'IFO', ifo)
     ifopath = os.path.join(modpath, 'ifo.yaml')
     if not ifo and ifopath:
-        ifo = load_struct(ifopath)
+        ifo = Struct.from_file(ifopath)
     freq = getattr(mod, 'FREQ', None)
     plot_style = getattr(mod, 'PLOT_STYLE', PLOT_STYLE)
 
diff --git a/gwinc/struct.py b/gwinc/struct.py
index 819b70e479a257d8f54ec5d8e792d6e102e06295..3b767a664b4479f2ad759efb20b5f96c6ed9e801 100644
--- a/gwinc/struct.py
+++ b/gwinc/struct.py
@@ -57,6 +57,9 @@ class Struct(object):
 
     """
 
+    STRUCT_EXT = ['.yaml', '.yml', '.mat', '.m']
+    """accepted extension types for struct files"""
+
     # FIXME: There should be a way to allow setting nested struct
     # attributes, e.g.:
     #
@@ -328,10 +331,33 @@ class Struct(object):
     def from_file(cls, path):
         """Load Struct from .yaml or MATLAB .mat file.
 
-        File type will be determined by extension.
+        Accepted file types are .yaml, .mat, or .m.
+
+        For .m files, the file is expected to include either an object
+        or function that corresponds to the basename of the file.  The
+        MATLAB engine will be invoked to execute the .m code and
+        extract the resultant IFO data.
+
+        If `path` is a tuple, all elements will be joined ala
+        os.path.join, with the first element resolved to it's absolute
+        dirname.  This is useful for loading package-relative files
+        with e.g.:
+
+          Struct.from_file((__file__, 'myifo.yaml'))
 
         """
-        (root, ext) = os.path.splitext(path)
+        if type(path) == tuple:
+            path = os.path.join(os.path.abspath(os.path.dirname(path[0])), *path[1:])
+        base, ext = os.path.splitext(path)
+
+        if ext == '.m':
+            from ..gwinc_matlab import Matlab
+            matlab = Matlab()
+            matlab.addpath(os.path.dirname(path))
+            func_name = os.path.basename(base)
+            matlab.eval("ifo = {};".format(func_name), nargout=0)
+            ifo = matlab.extract('ifo')
+            return Struct.from_matstruct(ifo)
 
         with open(path, 'r') as f:
             if ext in ['.yaml', '.yml']:
@@ -341,31 +367,3 @@ class Struct(object):
                 return cls.from_matstruct(s)
             else:
                 raise IOError("Unknown file type: {}".format(ext))
-
-
-def load_struct(path):
-    """Load struct from YAML or MATLAB file.
-
-    Files may be either .yaml, .mat or .m.  For .m files, the file is
-    expected to include either an object or function that corresponds
-    to the basename of the file.  The MATLAB engine will be invoked to
-    execute the .m code and extract the resultant IFO data.
-
-    """
-    root, ext = os.path.splitext(path)
-
-    if ext == '.m':
-        from ..gwinc_matlab import Matlab
-        matlab = Matlab()
-        matlab.addpath(os.path.dirname(path))
-        func_name = os.path.basename(root)
-        matlab.eval("ifo = {};".format(func_name), nargout=0)
-        ifo = matlab.extract('ifo')
-        return Struct.from_matstruct(ifo)
-
-    else:
-        return Struct.from_file(path)
-
-
-# accepted extension types for struct files
-STRUCT_EXT = ['.yaml', '.yml', '.mat', '.m']