diff --git a/.readthedocs.yaml b/.readthedocs.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..c6cdcc1b671547b04ebcc11cc93d6aefeda5b752
--- /dev/null
+++ b/.readthedocs.yaml
@@ -0,0 +1,19 @@
+version: 2
+
+build:
+  os: "ubuntu-22.04"
+  tools:
+    python: "3.11"
+
+sphinx:
+  configuration: docs/source/conf.py
+  fail_on_warning: false
+  
+formats:
+  - pdf
+  
+python:
+  install:
+    - requirements: docs/requirements.txt
+    - method: pip
+      path: .
diff --git a/config/cluster.py b/config/cluster.py
index 9a60872f55e30e96ebdaf1fdf0ef4495dc740071..96cffd303bdaede50016e6cfc12899640d70ff0a 100755
--- a/config/cluster.py
+++ b/config/cluster.py
@@ -42,35 +42,38 @@ slurm_cfg               python dictionary, containing options of SLURM
                             'cfg_update = {"nodes": "2"}'
 """
 
+
 cluster = utils.ClusterConfig(exp)
-cluster.name = 'srvx1'
-cluster.max_nproc = 6
-cluster.use_slurm = False
+cluster.name = 'jet'
+cluster.max_nproc = 12
+cluster.use_slurm = True
+cluster.size_jobarray = 40
 
 # binaries
-cluster.python = '/users/staff/lkugler/miniconda3/bin/python'
-cluster.python_verif = '/users/staff/lkugler/miniconda3/bin/python'
-cluster.ncks = '/home/swd/spack/opt/spack/linux-rhel8-skylake_avx512/gcc-8.5.0/nco-5.0.1-ntu44aoxlvwtr2tsrobfr4lht7cpvccf/bin/ncks'
-cluster.ideal = '' #/jetfs/home/lkugler/bin/ideal-v4.3_v1.22.exe'
-cluster.wrfexe = '' #/jetfs/home/lkugler/bin/wrf-v4.3_v1.22.exe'
+cluster.python = '/jetfs/home/lkugler/miniconda3/envs/DART/bin/python'
+cluster.python_verif = '/jetfs/home/lkugler/miniconda3/envs/enstools/bin/python'
+cluster.ncks = '/jetfs/spack/opt/spack/linux-rhel8-skylake_avx512/intel-20.0.2/nco-4.9.3-dhlqiyog7howjmaleyfhm6lkt7ra37xf/bin/ncks'
+cluster.ideal = '/jetfs/home/lkugler/bin/ideal-v4.3_v1.22.exe'
+cluster.wrfexe = '/jetfs/home/lkugler/bin/wrf-v4.3_v1.22.exe'
 cluster.container = ''
 
 # paths for data output
-cluster.wrf_rundir_base = '/users/staff/lkugler/AdvDA23/run_WRF/'  # path for temporary files
-cluster.dart_rundir_base = '/users/staff/lkugler/AdvDA23/run_DART/'  # path for temporary files
-cluster.archive_base = '/mnt/jetfs/scratch/lkugler/data/sim_archive/'
+cluster.wrf_rundir_base = '/jetfs/home/lkugler/data/run_WRF/'  # path for temporary files
+cluster.dart_rundir_base = '/jetfs/home/lkugler/data/run_DART/'  # path for temporary files
+cluster.archive_base = '/jetfs/home/lkugler/data/sim_archive/'
 
 # paths used as input
-cluster.srcdir = '/users/staff/lkugler/AdvDA23/DART/WRF-4.3/run'
-cluster.dart_srcdir = '/users/staff/lkugler/AdvDA23/DART/models/wrf/work'
-cluster.rttov_srcdir = '/users/staff/lkugler/AdvDA23/RTTOV13/rtcoef_rttov13/'
-cluster.scriptsdir = '/users/staff/lkugler/AdvDA23/DART-WRF/dartwrf/'
-cluster.geo_em = '/mnt/jetfs/scratch/lkugler/data/geo_em.d01.nc'
+cluster.srcdir = '/jetfs/home/lkugler/data/compile/WRF-4.3/run'
+cluster.dart_srcdir = '/jetfs/home/lkugler/data/compile/DART/DART-10.5.3/models/wrf/work'
+cluster.rttov_srcdir = '/jetfs/home/lkugler/data/compile/RTTOV13/rtcoef_rttov13/'
+cluster.scriptsdir = '/jetfs/home/lkugler/DART-WRF/dartwrf/'
 
-# templates/run scripts
+# other inputs
+cluster.geo_em = '/jetfs/home/lkugler/data/geo_em.d01.nc'
+cluster.obs_impact_filename = cluster.scriptsdir+'/../templates/impactfactor_T.txt'
 cluster.namelist = cluster.scriptsdir+'/../templates/namelist.input'
-cluster.run_WRF = cluster.scriptsdir+'/run_ens.jet.sh'
+cluster.run_WRF = '/jetfs/home/lkugler/DART-WRF/dartwrf/run_ens.jet.sh'
 
-cluster.slurm_cfg = {"account": "lkugler", "partition": "compute",
+cluster.slurm_cfg = {"account": "lkugler", "partition": "compute", #"nodelist": "jet07",
                  "ntasks": "1", "ntasks-per-core": "1", "mem": "50G",
                  "mail-type": "FAIL", "mail-user": "lukas.kugler@univie.ac.at"}
diff --git a/cycled_exp.py b/cycled_exp.py
index 15610299abfdca6c9df575efedfad5bc75e9cc8c..f365b1bdc14305fb4021527a534bda181e5e7df3 100755
--- a/cycled_exp.py
+++ b/cycled_exp.py
@@ -63,7 +63,7 @@ if __name__ == "__main__":
         # How long shall we integrate?
         timedelta_integrate = timedelta_btw_assim
         output_restart_interval = timedelta_btw_assim.total_seconds()/60
-        if time == last_assim_time: #this_forecast_init.minute in [0,]:  # longer forecast every full hour
+        if time == last_assim_time:  # this_forecast_init.minute in [0,]:  # longer forecast every full hour
             timedelta_integrate = forecast_until - last_assim_time  # dt.timedelta(hours=4)
             output_restart_interval = 9999  # no restart file after last assim
 
@@ -74,7 +74,7 @@ if __name__ == "__main__":
                     depends_on=id)
         
         # as we have WRF output, we can use own exp path as prior
-        prior_path_exp = cluster.archivedir       
+        prior_path_exp = w.cluster.archivedir       
 
         id_sat = w.create_satimages(time, depends_on=id)
         
diff --git a/dartwrf/assim_synth_obs.py b/dartwrf/assim_synth_obs.py
index 2b57fadbfb40ee55c56aae5b852c77f053fab4bb..460375e2d8a8004af46fb9f6dd77f5367d264e8b 100755
--- a/dartwrf/assim_synth_obs.py
+++ b/dartwrf/assim_synth_obs.py
@@ -3,7 +3,7 @@ import time as time_module
 import datetime as dt
 import numpy as np
 
-from dartwrf.utils import symlink, copy, sed_inplace, append_file, mkdir, try_remove, print, shell
+from dartwrf.utils import symlink, copy, sed_inplace, append_file, mkdir, try_remove, print, shell, write_txt
 from dartwrf.obs import error_models as err
 import dartwrf.create_obsseq as osq
 from dartwrf import wrfout_add_geo
@@ -141,13 +141,6 @@ def prepare_prior_ensemble(assim_time, prior_init_time, prior_valid_time, prior_
     os.system("rm -rf " + cluster.dartrundir + "/perfect_output_*")
     os.system("rm -rf " + cluster.dartrundir + "/obs_seq.fina*")
 
-
-def write_txt(lines, fpath):
-    try_remove(fpath)
-    with open(fpath, "w") as file:
-        for line in lines:
-            file.write(line+'\n')
-
 def write_list_of_inputfiles_prior():
      files = []
      for iens in range(1, exp.n_ens+1):
@@ -236,13 +229,13 @@ def archive_filteroutput(time):
 def get_parametrized_error(obscfg, osf_prior):
     """Calculate the parametrized error for an ObsConfig (one obs type)
 
-    Args
-        obscfg (object):                configuration of observations
-        osf_prior (obsseq.ObsRecord):   contains truth and prior values from obs_seq.final
+    Args:
+        obscfg (object): Configuration of observations
+        osf_prior (obsseq.ObsRecord): Contains truth and prior values from obs_seq.final
                                         (output of ./final in evaluate-mode (no posterior))
 
-    Returns
-        np.array            observation error std-dev for assimilation
+    Returns:
+        np.array: observation error std-dev for assimilation
     """
     Hx_prior = osf_prior.get_prior_Hx().T
     Hx_truth = osf_prior.get_truth_Hx()
@@ -263,8 +256,7 @@ def set_obserr_assimilate_in_obsseqout(oso, osf_prior, outfile="./obs_seq.out"):
     """"Overwrite existing variance values in obs_seq.out files
     
     Args:
-        oso (ObsSeq) :  python representation of obs_seq.out file, 
-                        will be modified and written to file
+        oso (ObsSeq): python representation of obs_seq.out file, will be modified and written to file
         osf_prior (ObsSeq): python representation of obs_seq.final (output of filter in evaluate-mode without posterior)
                             contains prior values; used for parameterized errors
 
diff --git a/dartwrf/config b/dartwrf/config
new file mode 120000
index 0000000000000000000000000000000000000000..4088526854d4f1d637653a0436624cdcf75dceb9
--- /dev/null
+++ b/dartwrf/config
@@ -0,0 +1 @@
+../config/
\ No newline at end of file
diff --git a/dartwrf/create_obsseq.py b/dartwrf/create_obsseq.py
index df2a84725773b34dcf153127aa795925debd5216..d014f0564b0413d305708ae5817a796b86b6e7eb 100755
--- a/dartwrf/create_obsseq.py
+++ b/dartwrf/create_obsseq.py
@@ -174,21 +174,21 @@ kind
 
 
 def create_obs_seq_in(time_dt, list_obscfg, 
-                             output_path=cluster.dartrundir+'/obs_seq.in'):
+                      output_path=cluster.dartrundir+'/obs_seq.in'):
     """Create obs_seq.in with multiple obs types in one file
 
     Args:
         time_dt (dt.datetime): time of observation
-        list_obscfg (list of dict) :    configuration for observation types
-            must have keys: 
-                - n_obs (int) : number of observations (must be a square of an integer: 4, 9, 1000, ...)
-                - obs_locations (str or tuple) in ['square_array_from_domaincenter', 'square_array_evenly_on_grid', ] 
-                                                or list of (lat, lon) coordinate tuples, in degrees north/east
-                - error_generate (float)
-                - error_assimilate (float or False) : False -> parameterized
-                - cov_loc_radius_km (float)
-
-        obs_errors (np.array): contains observation errors, one for each observation
+        list_obscfg (list of dict): configuration for observation types
+
+    Note:
+        `list_obscfg` must have these keys: 
+            - n_obs (int) : number of observations (must be a square of an integer: 4, 9, 1000, ...)
+            - obs_locations (str or tuple) in ['square_array_from_domaincenter', 'square_array_evenly_on_grid', ] 
+                                            or list of (lat, lon) coordinate tuples, in degrees north/east
+            - error_generate (np.array)
+            - error_assimilate (np.array or False) : False -> parameterized
+            - cov_loc_radius_km (float)
     """
     print('creating obs_seq.in:')
     time_dt = add_timezone_UTC(time_dt)
diff --git a/docs/requirements.txt b/docs/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..c1f3f786afa1423075cce9f90ea11647d335c6ad
--- /dev/null
+++ b/docs/requirements.txt
@@ -0,0 +1,4 @@
+sphinx>=6
+pysolar==0.10.0
+docopt
+nbsphinx
diff --git a/docs/source/.readthedocs.yaml b/docs/source/.readthedocs.yaml
deleted file mode 100644
index 58557268f5f6b2df9f328b7db29541abf3ce7a59..0000000000000000000000000000000000000000
--- a/docs/source/.readthedocs.yaml
+++ /dev/null
@@ -1,19 +0,0 @@
-version: 1
-
-build:
-  os: "ubuntu-20.04"
-  tools:
-    python: "3.10"
-
-sphinx:
-  fail_on_warning: true
-  
-formats:
-  - pdf
-  - epub
-  
-python:
-  # Install our python package before building the docs
-  install:
-    - method: pip
-      path: .
diff --git a/docs/source/conf.py b/docs/source/conf.py
index 9af02837a4558b11ce3cdff96c74516c8daf1df8..673128efa9e14de1d9091624975b651fdc2a0736 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -11,7 +11,10 @@ author = 'Lukas Kugler'
 release = '2023.2.21'
 
 # -- General configuration
-sys.path.insert(0, os.path.abspath('../../'))
+sys.path.insert(0, os.path.abspath('.'))
+sys.path.insert(0, os.path.abspath('../'))
+
+master_doc = 'index'
 
 extensions = [
     'sphinx.ext.duration',
diff --git a/docs/source/index.rst b/docs/source/index.rst
index c08bb094d713f2aeeba59f6107a7927894c3c26e..282d53b1981bab76a8af373faf6898a4d823a89a 100644
--- a/docs/source/index.rst
+++ b/docs/source/index.rst
@@ -18,7 +18,7 @@ DART-WRF is available at `github.com/lkugler/DART-WRF <https://github.com/lkugle
 Other helpful resources
 -----------------------
 
-**DART documentation** `[docs.ucar.edu] <https://docs.dart.ucar.edu/en/latest/README.html>`_
+**DART documentation** `[here] <https://docs.dart.ucar.edu/en/latest/README.html>`_
 **WRF user guide** `[here] <http://www2.mmm.ucar.edu/wrf/users/docs/user_guide_v4/v4.2/WRFUsersGuide_v42.pdf>`_
 
 
@@ -31,9 +31,10 @@ Other helpful resources
    :maxdepth: 2
    :caption: Tutorials:
 
-   tutorial1
-   tutorial2
-   tutorial3
+   notebooks/tutorial1
+   notebooks/tutorial2
+   notebooks/tutorial3
+
 
 API
 ===
diff --git a/docs/source/tutorial1.ipynb b/docs/source/notebooks/tutorial1.ipynb
similarity index 100%
rename from docs/source/tutorial1.ipynb
rename to docs/source/notebooks/tutorial1.ipynb
diff --git a/docs/source/tutorial2.ipynb b/docs/source/notebooks/tutorial2.ipynb
similarity index 100%
rename from docs/source/tutorial2.ipynb
rename to docs/source/notebooks/tutorial2.ipynb
diff --git a/docs/source/tutorial3.ipynb b/docs/source/notebooks/tutorial3.ipynb
similarity index 100%
rename from docs/source/tutorial3.ipynb
rename to docs/source/notebooks/tutorial3.ipynb
diff --git a/requirements.txt b/requirements.txt
deleted file mode 100644
index 86afc0b69de74f6c1fd2de122e9a6c447805628a..0000000000000000000000000000000000000000
--- a/requirements.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-pysolar==1.10.0
-docopt
-nbsphinx>=0.8.6