We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Build filename parser utility function
It would be useful to have a function in the `utils.py` module that returned the individual elements of a given filename, for example:

```python
from jwql.utils.utils import parse_filename
filename_dict = parse_filename('jw94015001001_02102_00001_nrcb1_uncal.fits')
```

where `filename_dict` is:

```
{
    'program_id' : '94015',
    'observation' : '001',
    'visit' : '001',
    'visit_group' : '02',
    'parallel_seq_id' : '1',
    'activity' : '02',
    'exposure_id' : '00001',
    'detector' : 'nrcb1',
    'suffix' : 'uncal'
}
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `jwql/utils/utils.py`
Content:
```
1 """Various utility functions for the jwql project.
2 
3 Authors
4 -------
5 
6     Matthew Bourque
7 
8 Use
9 ---
10 
11     This module can be imported as such:
12 
13     >>> import utils
14     settings = get_config()
15 """
16 
17 import json
18 
19 
20 def get_config():
21     """Return a dictionary that holds the contents of the jwql config
22     file.
23 
24     Returns
25     -------
26     settings : dict
27         A dictionary that holds the contents of the config file.
28     """
29 
30     with open('config.json', 'r') as config_file:
31         settings = json.load(config_file)
32 
33     return settings
34
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/jwql/utils/utils.py b/jwql/utils/utils.py
--- a/jwql/utils/utils.py
+++ b/jwql/utils/utils.py
@@ -3,7 +3,8 @@
 Authors
 -------
 
-    Matthew Bourque
+    - Matthew Bourque
+    - Lauren Chambers
 
 Use
 ---
@@ -12,9 +13,19 @@
 
     >>> import utils
     settings = get_config()
+
+References
+----------
+
+    Filename parser modifed from Joe Hunkeler:
+    https://gist.github.com/jhunkeler/f08783ca2da7bfd1f8e9ee1d207da5ff
 """
 
 import json
+import os
+import re
+
+__location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__)))
 
 
 def get_config():
@@ -27,7 +38,50 @@
         A dictionary that holds the contents of the config file.
     """
 
-    with open('config.json', 'r') as config_file:
+    with open(os.path.join(__location__, 'config.json'), 'r') as config_file:
         settings = json.load(config_file)
 
     return settings
+
+
+def filename_parser(filename):
+    """Return a dictionary that contains the properties of a given
+    JWST file (e.g. program ID, visit number, detector, etc.)
+
+    Parameters
+    ----------
+    filename : str
+        Path or name of JWST file to parse
+
+    Returns
+    -------
+    filename_dict : dict
+        Collection of file properties
+
+    Raises
+    ------
+    ValueError
+        When the provided file does not follow naming conventions
+    """
+    filename = os.path.basename(filename)
+
+    elements = \
+        re.compile(r"[a-z]+"
+                   "(?P<program_id>\d{5})"
+                   "(?P<observation>\d{3})"
+                   "(?P<visit>\d{3})"
+                   "_(?P<visit_group>\d{2})"
+                   "(?P<parallel_seq_id>\d{1})"
+                   "(?P<activity>\d{2})"
+                   "_(?P<exposure_id>\d+)"
+                   "_(?P<detector>\w+)"
+                   "_(?P<suffix>\w+).*")
+
+    jwst_file = elements.match(filename)
+
+    if jwst_file is not None:
+        filename_dict = jwst_file.groupdict()
+    else:
+        raise ValueError('Provided file {} does not follow JWST naming conventions (jw<PPPPP><OOO><VVV>_<GGSAA>_<EEEEE>_<detector>_<suffix>.fits)'.format(filename))
+
+    return filename_dict

{"golden_diff": "diff --git a/jwql/utils/utils.py b/jwql/utils/utils.py\n--- a/jwql/utils/utils.py\n+++ b/jwql/utils/utils.py\n@@ -3,7 +3,8 @@\n Authors\n -------\n \n-    Matthew Bourque\n+    - Matthew Bourque\n+    - Lauren Chambers\n \n Use\n ---\n@@ -12,9 +13,19 @@\n \n     >>> import utils\n     settings = get_config()\n+\n+References\n+----------\n+\n+    Filename parser modifed from Joe Hunkeler:\n+    https://gist.github.com/jhunkeler/f08783ca2da7bfd1f8e9ee1d207da5ff\n \"\"\"\n \n import json\n+import os\n+import re\n+\n+__location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__)))\n \n \n def get_config():\n@@ -27,7 +38,50 @@\n         A dictionary that holds the contents of the config file.\n     \"\"\"\n \n-    with open('config.json', 'r') as config_file:\n+    with open(os.path.join(__location__, 'config.json'), 'r') as config_file:\n         settings = json.load(config_file)\n \n     return settings\n+\n+\n+def filename_parser(filename):\n+    \"\"\"Return a dictionary that contains the properties of a given\n+    JWST file (e.g. program ID, visit number, detector, etc.)\n+\n+    Parameters\n+    ----------\n+    filename : str\n+        Path or name of JWST file to parse\n+\n+    Returns\n+    -------\n+    filename_dict : dict\n+        Collection of file properties\n+\n+    Raises\n+    ------\n+    ValueError\n+        When the provided file does not follow naming conventions\n+    \"\"\"\n+    filename = os.path.basename(filename)\n+\n+    elements = \\\n+        re.compile(r\"[a-z]+\"\n+                   \"(?P<program_id>\\d{5})\"\n+                   \"(?P<observation>\\d{3})\"\n+                   \"(?P<visit>\\d{3})\"\n+                   \"_(?P<visit_group>\\d{2})\"\n+                   \"(?P<parallel_seq_id>\\d{1})\"\n+                   \"(?P<activity>\\d{2})\"\n+                   \"_(?P<exposure_id>\\d+)\"\n+                   \"_(?P<detector>\\w+)\"\n+                   \"_(?P<suffix>\\w+).*\")\n+\n+    jwst_file = elements.match(filename)\n+\n+    if jwst_file is not None:\n+        filename_dict = jwst_file.groupdict()\n+    else:\n+        raise ValueError('Provided file {} does not follow JWST naming conventions (jw<PPPPP><OOO><VVV>_<GGSAA>_<EEEEE>_<detector>_<suffix>.fits)'.format(filename))\n+\n+    return filename_dict\n", "issue": "Build filename parser utility function\nIt would be useful to have a function in the `utils.py` module that returned the individual elements of a given filename, for example:\r\n\r\n```python\r\nfrom jwql.utils.utils import parse_filename\r\nfilename_dict = parse_filename('jw94015001001_02102_00001_nrcb1_uncal.fits')\r\n```\r\n\r\nwhere `filename_dict` is:\r\n\r\n```\r\n{\r\n    'program_id' : '94015',\r\n    'observation' : '001',\r\n    'visit' : '001',\r\n    'visit_group' : '02',\r\n    'parallel_seq_id' : '1',\r\n    'activity' : '02',\r\n    'exposure_id' : '00001',\r\n    'detector' : 'nrcb1',\r\n    'suffix' : 'uncal'\r\n}\r\n```\n", "before_files": [{"content": "\"\"\"Various utility functions for the jwql project.\n\nAuthors\n-------\n\n    Matthew Bourque\n\nUse\n---\n\n    This module can be imported as such:\n\n    >>> import utils\n    settings = get_config()\n\"\"\"\n\nimport json\n\n\ndef get_config():\n    \"\"\"Return a dictionary that holds the contents of the jwql config\n    file.\n\n    Returns\n    -------\n    settings : dict\n        A dictionary that holds the contents of the config file.\n    \"\"\"\n\n    with open('config.json', 'r') as config_file:\n        settings = json.load(config_file)\n\n    return settings\n", "path": "jwql/utils/utils.py"}], "after_files": [{"content": "\"\"\"Various utility functions for the jwql project.\n\nAuthors\n-------\n\n    - Matthew Bourque\n    - Lauren Chambers\n\nUse\n---\n\n    This module can be imported as such:\n\n    >>> import utils\n    settings = get_config()\n\nReferences\n----------\n\n    Filename parser modifed from Joe Hunkeler:\n    https://gist.github.com/jhunkeler/f08783ca2da7bfd1f8e9ee1d207da5ff\n\"\"\"\n\nimport json\nimport os\nimport re\n\n__location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__)))\n\n\ndef get_config():\n    \"\"\"Return a dictionary that holds the contents of the jwql config\n    file.\n\n    Returns\n    -------\n    settings : dict\n        A dictionary that holds the contents of the config file.\n    \"\"\"\n\n    with open(os.path.join(__location__, 'config.json'), 'r') as config_file:\n        settings = json.load(config_file)\n\n    return settings\n\n\ndef filename_parser(filename):\n    \"\"\"Return a dictionary that contains the properties of a given\n    JWST file (e.g. program ID, visit number, detector, etc.)\n\n    Parameters\n    ----------\n    filename : str\n        Path or name of JWST file to parse\n\n    Returns\n    -------\n    filename_dict : dict\n        Collection of file properties\n\n    Raises\n    ------\n    ValueError\n        When the provided file does not follow naming conventions\n    \"\"\"\n    filename = os.path.basename(filename)\n\n    elements = \\\n        re.compile(r\"[a-z]+\"\n                   \"(?P<program_id>\\d{5})\"\n                   \"(?P<observation>\\d{3})\"\n                   \"(?P<visit>\\d{3})\"\n                   \"_(?P<visit_group>\\d{2})\"\n                   \"(?P<parallel_seq_id>\\d{1})\"\n                   \"(?P<activity>\\d{2})\"\n                   \"_(?P<exposure_id>\\d+)\"\n                   \"_(?P<detector>\\w+)\"\n                   \"_(?P<suffix>\\w+).*\")\n\n    jwst_file = elements.match(filename)\n\n    if jwst_file is not None:\n        filename_dict = jwst_file.groupdict()\n    else:\n        raise ValueError('Provided file {} does not follow JWST naming conventions (jw<PPPPP><OOO><VVV>_<GGSAA>_<EEEEE>_<detector>_<suffix>.fits)'.format(filename))\n\n    return filename_dict\n", "path": "jwql/utils/utils.py"}]}