diff --git a/__pycache__/__init__.cpython-311.pyc b/__pycache__/__init__.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..3e608de1cf2f35d94fdefd09865be67c4102cb94
Binary files /dev/null and b/__pycache__/__init__.cpython-311.pyc differ
diff --git a/data_analysis/__pycache__/polytec.cpython-311.pyc b/data_analysis/__pycache__/polytec.cpython-311.pyc
index 73a020fb97a3e957c37c8dd16413850b27606a8b..42401fe229eb692bc2a4604732c59ce14e61e056 100644
Binary files a/data_analysis/__pycache__/polytec.cpython-311.pyc and b/data_analysis/__pycache__/polytec.cpython-311.pyc differ
diff --git a/data_analysis/__pycache__/raman.cpython-311.pyc b/data_analysis/__pycache__/raman.cpython-311.pyc
index 54cf895f506e106fa1499701befc98cefa359aae..69a7818923583c091407edf9bd9b0be13dbc68a3 100644
Binary files a/data_analysis/__pycache__/raman.cpython-311.pyc and b/data_analysis/__pycache__/raman.cpython-311.pyc differ
diff --git a/data_analysis/archive/Code/__pycache__/Dektak.cpython-311.pyc b/data_analysis/archive/Code/__pycache__/Dektak.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..0acbeeba1192951d0a90a914bf7323e7519ab4d9
Binary files /dev/null and b/data_analysis/archive/Code/__pycache__/Dektak.cpython-311.pyc differ
diff --git a/data_analysis/archive/Code/__pycache__/DesCar.cpython-311.pyc b/data_analysis/archive/Code/__pycache__/DesCar.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..82f97ced0fd99ce8dd447308052e402631cb10d5
Binary files /dev/null and b/data_analysis/archive/Code/__pycache__/DesCar.cpython-311.pyc differ
diff --git a/data_analysis/archive/Code/__pycache__/Intro.cpython-311.pyc b/data_analysis/archive/Code/__pycache__/Intro.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..d0c41c2ebe333944ae0a5fd7a8b47a1076700581
Binary files /dev/null and b/data_analysis/archive/Code/__pycache__/Intro.cpython-311.pyc differ
diff --git a/data_analysis/archive/Code/__pycache__/StressEstimation.cpython-311.pyc b/data_analysis/archive/Code/__pycache__/StressEstimation.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..980d0d205185242caf2fe5c636a9823ebbba487c
Binary files /dev/null and b/data_analysis/archive/Code/__pycache__/StressEstimation.cpython-311.pyc differ
diff --git a/data_analysis/archive/Code/__pycache__/basicDataModifier.cpython-311.pyc b/data_analysis/archive/Code/__pycache__/basicDataModifier.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..850be715ac6a387de3b73b7fbb029d1c66bacf44
Binary files /dev/null and b/data_analysis/archive/Code/__pycache__/basicDataModifier.cpython-311.pyc differ
diff --git a/data_analysis/archive/Code/__pycache__/comsol.cpython-311.pyc b/data_analysis/archive/Code/__pycache__/comsol.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..2cbe699641d081116b91f4e0e2da5a8943986cc8
Binary files /dev/null and b/data_analysis/archive/Code/__pycache__/comsol.cpython-311.pyc differ
diff --git a/data_analysis/archive/Code/__pycache__/extractionIV.cpython-311.pyc b/data_analysis/archive/Code/__pycache__/extractionIV.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..ddd14c259c27dffc157378506a4fb7169414938b
Binary files /dev/null and b/data_analysis/archive/Code/__pycache__/extractionIV.cpython-311.pyc differ
diff --git a/data_analysis/archive/Code/__pycache__/filePath.cpython-311.pyc b/data_analysis/archive/Code/__pycache__/filePath.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..111082e5eb8669257cd2928f846039a64aab1816
Binary files /dev/null and b/data_analysis/archive/Code/__pycache__/filePath.cpython-311.pyc differ
diff --git a/data_analysis/archive/Code/__pycache__/interpolate.cpython-311.pyc b/data_analysis/archive/Code/__pycache__/interpolate.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..77c1700e221be0de1c38e2b7d177ee77a44bae65
Binary files /dev/null and b/data_analysis/archive/Code/__pycache__/interpolate.cpython-311.pyc differ
diff --git a/data_analysis/archive/Code/__pycache__/machines.cpython-311.pyc b/data_analysis/archive/Code/__pycache__/machines.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..073f9977d58746e96e0b3a5f756801aeeac202f0
Binary files /dev/null and b/data_analysis/archive/Code/__pycache__/machines.cpython-311.pyc differ
diff --git a/data_analysis/archive/Code/__pycache__/material.cpython-311.pyc b/data_analysis/archive/Code/__pycache__/material.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..b1eb382851bb1259b13347add1300e3d54d9e3e2
Binary files /dev/null and b/data_analysis/archive/Code/__pycache__/material.cpython-311.pyc differ
diff --git a/data_analysis/archive/Code/__pycache__/plotGeneral.cpython-311.pyc b/data_analysis/archive/Code/__pycache__/plotGeneral.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..4c87cf938ad3bd5def531fe566e280e602944246
Binary files /dev/null and b/data_analysis/archive/Code/__pycache__/plotGeneral.cpython-311.pyc differ
diff --git a/data_analysis/archive/Code/__pycache__/plotPolytek.cpython-311.pyc b/data_analysis/archive/Code/__pycache__/plotPolytek.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..dc352a9d844054d2e708545b2e089e4257500c69
Binary files /dev/null and b/data_analysis/archive/Code/__pycache__/plotPolytek.cpython-311.pyc differ
diff --git a/data_analysis/archive/Code/__pycache__/plotRaman.cpython-311.pyc b/data_analysis/archive/Code/__pycache__/plotRaman.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..cabd158626e2463f1fd9c93afaa47a5c28520822
Binary files /dev/null and b/data_analysis/archive/Code/__pycache__/plotRaman.cpython-311.pyc differ
diff --git a/data_analysis/archive/Code/__pycache__/siliconPeakRemover.cpython-311.pyc b/data_analysis/archive/Code/__pycache__/siliconPeakRemover.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..eaa45ca669a0be8c8ffb4fa34cb11cebdcdf74fd
Binary files /dev/null and b/data_analysis/archive/Code/__pycache__/siliconPeakRemover.cpython-311.pyc differ
diff --git a/data_analysis/examples/__pycache__/diode_analysis.cpython-311.pyc b/data_analysis/examples/__pycache__/diode_analysis.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..3177f8db70fdafaf39febb29cb05e0574b3168fe
Binary files /dev/null and b/data_analysis/examples/__pycache__/diode_analysis.cpython-311.pyc differ
diff --git a/data_analysis/examples/__pycache__/diode_modeling.cpython-311.pyc b/data_analysis/examples/__pycache__/diode_modeling.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..ceb2fada0240ad133479c545e3d5d047299c9849
Binary files /dev/null and b/data_analysis/examples/__pycache__/diode_modeling.cpython-311.pyc differ
diff --git a/data_analysis/examples/__pycache__/mos_transistor_analysis.cpython-311.pyc b/data_analysis/examples/__pycache__/mos_transistor_analysis.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..123e41b532dfd884e82691db3c346743b91c21ff
Binary files /dev/null and b/data_analysis/examples/__pycache__/mos_transistor_analysis.cpython-311.pyc differ
diff --git a/data_analysis/examples/__pycache__/mos_transistor_modeling.cpython-311.pyc b/data_analysis/examples/__pycache__/mos_transistor_modeling.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..442a4a769d6ec6ace8bf0fbecf2fc09520967654
Binary files /dev/null and b/data_analysis/examples/__pycache__/mos_transistor_modeling.cpython-311.pyc differ
diff --git a/data_analysis/examples/__pycache__/piezoresistive_effect_silicon.cpython-311.pyc b/data_analysis/examples/__pycache__/piezoresistive_effect_silicon.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..5547136d274518073296a8497d031354c405f82b
Binary files /dev/null and b/data_analysis/examples/__pycache__/piezoresistive_effect_silicon.cpython-311.pyc differ
diff --git a/data_analysis/examples/polytec_membrane/__pycache__/membrane_deflection.cpython-311.pyc b/data_analysis/examples/polytec_membrane/__pycache__/membrane_deflection.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..ff8f933e94786392e7d389f175c5754f13baae0f
Binary files /dev/null and b/data_analysis/examples/polytec_membrane/__pycache__/membrane_deflection.cpython-311.pyc differ
diff --git a/data_analysis/examples/raman_silicon/__pycache__/raman_phonon_deformation_potential.cpython-311.pyc b/data_analysis/examples/raman_silicon/__pycache__/raman_phonon_deformation_potential.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..8484e63959f27c02485b0e6e071e655f4b5d7670
Binary files /dev/null and b/data_analysis/examples/raman_silicon/__pycache__/raman_phonon_deformation_potential.cpython-311.pyc differ
diff --git a/data_analysis/examples/raman_silicon/__pycache__/raman_strain_silicon.cpython-311.pyc b/data_analysis/examples/raman_silicon/__pycache__/raman_strain_silicon.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..496cc3b51c3d4ef49481d33bc56f756e9670d3e4
Binary files /dev/null and b/data_analysis/examples/raman_silicon/__pycache__/raman_strain_silicon.cpython-311.pyc differ
diff --git a/data_analysis/examples/transfer_matrix_method/__pycache__/absorption_in_silicon_layer.cpython-311.pyc b/data_analysis/examples/transfer_matrix_method/__pycache__/absorption_in_silicon_layer.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..64da49a2435f51decbaf0fffdf93af2d6f5c68f2
Binary files /dev/null and b/data_analysis/examples/transfer_matrix_method/__pycache__/absorption_in_silicon_layer.cpython-311.pyc differ
diff --git a/equipment_control/__pycache__/cm110.cpython-311.pyc b/equipment_control/__pycache__/cm110.cpython-311.pyc
index 1553e0925545cc597fbb0e31ac92af776f35abc7..7f342932363852b57def946b8a3c3c6d170e9a16 100644
Binary files a/equipment_control/__pycache__/cm110.cpython-311.pyc and b/equipment_control/__pycache__/cm110.cpython-311.pyc differ
diff --git a/equipment_control/__pycache__/dmm.cpython-311.pyc b/equipment_control/__pycache__/dmm.cpython-311.pyc
index 84320a1ca1f6ef1565659367e52e192a271cd3f3..ca150904e8bba2a913ffb496d08c6af51996f526 100644
Binary files a/equipment_control/__pycache__/dmm.cpython-311.pyc and b/equipment_control/__pycache__/dmm.cpython-311.pyc differ
diff --git a/equipment_control/__pycache__/equipment.cpython-311.pyc b/equipment_control/__pycache__/equipment.cpython-311.pyc
index ccc66f67e0f1cff8171944478d0dc59abed12789..8c3e2d012676b1b68f718197d53e93f131a1284c 100644
Binary files a/equipment_control/__pycache__/equipment.cpython-311.pyc and b/equipment_control/__pycache__/equipment.cpython-311.pyc differ
diff --git a/equipment_control/__pycache__/hp4145.cpython-311.pyc b/equipment_control/__pycache__/hp4145.cpython-311.pyc
index dfc03a98e1bb6f4e1aab97330c3c072f6662cf7c..4616a19aab81d7d6e33732f76f0f6049a447a558 100644
Binary files a/equipment_control/__pycache__/hp4145.cpython-311.pyc and b/equipment_control/__pycache__/hp4145.cpython-311.pyc differ
diff --git a/equipment_control/__pycache__/k2400.cpython-311.pyc b/equipment_control/__pycache__/k2400.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..071fa26554929bd8dbf7af184bbe0574a3233314
Binary files /dev/null and b/equipment_control/__pycache__/k2400.cpython-311.pyc differ
diff --git a/equipment_control/__pycache__/k2450.cpython-311.pyc b/equipment_control/__pycache__/k2450.cpython-311.pyc
index 4ada50c438bcb1a1c83e32da6e9062b025e7e93d..4b8d64f652331334388e22c02307d8eab5127f32 100644
Binary files a/equipment_control/__pycache__/k2450.cpython-311.pyc and b/equipment_control/__pycache__/k2450.cpython-311.pyc differ
diff --git a/equipment_control/__pycache__/k4200.cpython-311.pyc b/equipment_control/__pycache__/k4200.cpython-311.pyc
index a7bcbb2bba58af1122ba628d6589d291c2e97780..2fc9db57e2b78fbc2449c5b2e37190e07fc316b8 100644
Binary files a/equipment_control/__pycache__/k4200.cpython-311.pyc and b/equipment_control/__pycache__/k4200.cpython-311.pyc differ
diff --git a/equipment_control/__pycache__/kal100.cpython-311.pyc b/equipment_control/__pycache__/kal100.cpython-311.pyc
index 84492bed45d4149ecd557d603aae5fefaeb2d078..a8b6437d2017320dde73cc5f122fd687eb615dc9 100644
Binary files a/equipment_control/__pycache__/kal100.cpython-311.pyc and b/equipment_control/__pycache__/kal100.cpython-311.pyc differ
diff --git a/equipment_control/__pycache__/sh242.cpython-311.pyc b/equipment_control/__pycache__/sh242.cpython-311.pyc
index e9411676ca7dcea379714dff50028f355ee80256..663c1a71fafac352be69e96e936f5228e3ee91bf 100644
Binary files a/equipment_control/__pycache__/sh242.cpython-311.pyc and b/equipment_control/__pycache__/sh242.cpython-311.pyc differ
diff --git a/equipment_control/examples/single_equipment/__pycache__/cm110_script.cpython-311.pyc b/equipment_control/examples/single_equipment/__pycache__/cm110_script.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..7d764951d452777d12cc7ae1510816e0dd22beef
Binary files /dev/null and b/equipment_control/examples/single_equipment/__pycache__/cm110_script.cpython-311.pyc differ
diff --git a/equipment_control/examples/single_equipment/__pycache__/dmm_script.cpython-311.pyc b/equipment_control/examples/single_equipment/__pycache__/dmm_script.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..411a01aa84ab47c583b75cb51447bc4892b85b67
Binary files /dev/null and b/equipment_control/examples/single_equipment/__pycache__/dmm_script.cpython-311.pyc differ
diff --git a/equipment_control/examples/single_equipment/__pycache__/hp4145_script.cpython-311.pyc b/equipment_control/examples/single_equipment/__pycache__/hp4145_script.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..51c2abe095ecb76e5851afb8047b61bc1a02f1df
Binary files /dev/null and b/equipment_control/examples/single_equipment/__pycache__/hp4145_script.cpython-311.pyc differ
diff --git a/equipment_control/examples/single_equipment/__pycache__/k2400_script.cpython-311.pyc b/equipment_control/examples/single_equipment/__pycache__/k2400_script.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..3bcfe693d3345c161d420d26eedddd1eb7f3ea59
Binary files /dev/null and b/equipment_control/examples/single_equipment/__pycache__/k2400_script.cpython-311.pyc differ
diff --git a/equipment_control/examples/single_equipment/__pycache__/k2450_script.cpython-311.pyc b/equipment_control/examples/single_equipment/__pycache__/k2450_script.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..668a88fa8c6e7823a8a881ae437f21e80e5ec4da
Binary files /dev/null and b/equipment_control/examples/single_equipment/__pycache__/k2450_script.cpython-311.pyc differ
diff --git a/equipment_control/examples/single_equipment/__pycache__/k4200_script.cpython-311.pyc b/equipment_control/examples/single_equipment/__pycache__/k4200_script.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..563f0ce946b804cc28ec6005cfd774aa9c3e551c
Binary files /dev/null and b/equipment_control/examples/single_equipment/__pycache__/k4200_script.cpython-311.pyc differ
diff --git a/equipment_control/examples/single_equipment/__pycache__/kal100_script.cpython-311.pyc b/equipment_control/examples/single_equipment/__pycache__/kal100_script.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..55ef067869643a4241f34ea49581eede00661b09
Binary files /dev/null and b/equipment_control/examples/single_equipment/__pycache__/kal100_script.cpython-311.pyc differ
diff --git a/equipment_control/examples/single_equipment/__pycache__/sh242_script.cpython-311.pyc b/equipment_control/examples/single_equipment/__pycache__/sh242_script.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..eb2c6c50ec71b5c59da4ffcfbc6aff8c1bb2a47c
Binary files /dev/null and b/equipment_control/examples/single_equipment/__pycache__/sh242_script.cpython-311.pyc differ
diff --git a/equipment_control/example/single_equipment/cm110_script.py b/equipment_control/examples/single_equipment/cm110_script.py
similarity index 100%
rename from equipment_control/example/single_equipment/cm110_script.py
rename to equipment_control/examples/single_equipment/cm110_script.py
diff --git a/equipment_control/example/single_equipment/dmm_script.py b/equipment_control/examples/single_equipment/dmm_script.py
similarity index 100%
rename from equipment_control/example/single_equipment/dmm_script.py
rename to equipment_control/examples/single_equipment/dmm_script.py
diff --git a/equipment_control/example/single_equipment/hp4145_script.py b/equipment_control/examples/single_equipment/hp4145_script.py
similarity index 100%
rename from equipment_control/example/single_equipment/hp4145_script.py
rename to equipment_control/examples/single_equipment/hp4145_script.py
diff --git a/equipment_control/example/single_equipment/k2400_script.py b/equipment_control/examples/single_equipment/k2400_script.py
similarity index 100%
rename from equipment_control/example/single_equipment/k2400_script.py
rename to equipment_control/examples/single_equipment/k2400_script.py
diff --git a/equipment_control/example/single_equipment/k2450_script.py b/equipment_control/examples/single_equipment/k2450_script.py
similarity index 100%
rename from equipment_control/example/single_equipment/k2450_script.py
rename to equipment_control/examples/single_equipment/k2450_script.py
diff --git a/equipment_control/example/single_equipment/k4200_script.py b/equipment_control/examples/single_equipment/k4200_script.py
similarity index 100%
rename from equipment_control/example/single_equipment/k4200_script.py
rename to equipment_control/examples/single_equipment/k4200_script.py
diff --git a/equipment_control/example/single_equipment/kal100_script.py b/equipment_control/examples/single_equipment/kal100_script.py
similarity index 100%
rename from equipment_control/example/single_equipment/kal100_script.py
rename to equipment_control/examples/single_equipment/kal100_script.py
diff --git a/equipment_control/example/single_equipment/sh242_script.py b/equipment_control/examples/single_equipment/sh242_script.py
similarity index 100%
rename from equipment_control/example/single_equipment/sh242_script.py
rename to equipment_control/examples/single_equipment/sh242_script.py
diff --git a/equipment_control/example/single_equipment/temp.txt b/equipment_control/examples/single_equipment/temp.txt
similarity index 100%
rename from equipment_control/example/single_equipment/temp.txt
rename to equipment_control/examples/single_equipment/temp.txt
diff --git a/html/data_analysis/data_processing.html b/html/data_analysis/data_processing.html
new file mode 100644
index 0000000000000000000000000000000000000000..3388cd88ebe8b0ed2175125d9406c081208c0243
--- /dev/null
+++ b/html/data_analysis/data_processing.html
@@ -0,0 +1,533 @@
+<!doctype html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
+<meta name="generator" content="pdoc3 0.11.6">
+<title>dopes.data_analysis.data_processing API documentation</title>
+<meta name="description" content="">
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/typography.min.css" integrity="sha512-Y1DYSb995BAfxobCkKepB1BqJJTPrOp3zPL74AWFugHHmmdcvO+C48WLrUOlhGMc0QG7AE3f7gmvvcrmX2fDoA==" crossorigin>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css" crossorigin>
+<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:1.5em;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:2em 0 .50em 0}h3{font-size:1.4em;margin:1.6em 0 .7em 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .2s ease-in-out}a:visited{color:#503}a:hover{color:#b62}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900;font-weight:bold}pre code{font-size:.8em;line-height:1.4em;padding:1em;display:block}code{background:#f3f3f3;font-family:"DejaVu Sans Mono",monospace;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source > summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible;min-width:max-content}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em 1em;margin:1em 0}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
+<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul ul{padding-left:1em}.toc > ul > li{margin-top:.5em}}</style>
+<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
+<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js" integrity="sha512-D9gUyxqja7hBtkWpPWGt9wfbfaMGVt9gnyCvYa+jojwwPHLCzUm5i8rpk7vD7wNee9bA35eYIjobYPaQuKS1MQ==" crossorigin></script>
+<script>window.addEventListener('DOMContentLoaded', () => {
+hljs.configure({languages: ['bash', 'css', 'diff', 'graphql', 'ini', 'javascript', 'json', 'plaintext', 'python', 'python-repl', 'rust', 'shell', 'sql', 'typescript', 'xml', 'yaml']});
+hljs.highlightAll();
+/* Collapse source docstrings */
+setTimeout(() => {
+[...document.querySelectorAll('.hljs.language-python > .hljs-string')]
+.filter(el => el.innerHTML.length > 200 && ['"""', "'''"].includes(el.innerHTML.substring(0, 3)))
+.forEach(el => {
+let d = document.createElement('details');
+d.classList.add('hljs-string');
+d.innerHTML = '<summary>"""</summary>' + el.innerHTML.substring(3);
+el.replaceWith(d);
+});
+}, 100);
+})</script>
+</head>
+<body>
+<main>
+<article id="content">
+<header>
+<h1 class="title">Module <code>dopes.data_analysis.data_processing</code></h1>
+</header>
+<section id="section-intro">
+</section>
+<section>
+</section>
+<section>
+</section>
+<section>
+<h2 class="section-title" id="header-functions">Functions</h2>
+<dl>
+<dt id="dopes.data_analysis.data_processing.finite_difference"><code class="name flex">
+<span>def <span class="ident">finite_difference</span></span>(<span>x, h, order, accuracy=2, kind='central')</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def finite_difference(x,h,order,accuracy=2,kind=&#34;central&#34;):
+    &#34;&#34;&#34; Function to calculate the coefficient to calculate a finite difference for derivative calculation
+        
+        args:
+            - x (array): the 1D array for which to calculate the finite difference. The size of the array should be higher than the size of the stencil given by 2 * |_ (order + 1) / 2 _| - 1 + 2 * |_ accuracy / 2_|
+            - h (scalar): the step size for an uniform grid spacing between each finite difference interval
+            - order (integer): the order of the derivation
+            - accuracy (integer): related to the number of points taken for the finite difference. see https://en.wikipedia.org/wiki/Finite_difference_coefficient
+            - kind (string): the type of finite difference calculated. For now, only &#34;central&#34; finite difference is implemented.
+    
+        return:
+            - results (numpy array): an array with the results of the calculation of the finite difference
+            - x_results (numpy array): an array with the x value with the central value for each calculation of the finite difference
+    &#34;&#34;&#34;  
+    if kind==&#34;central&#34;:
+        n_stencil=int(2*np.floor((order+1)/2)-1+2*np.floor(accuracy/2))
+        
+        stencil=range(-int(np.floor(n_stencil/2)),int(np.floor(n_stencil/2))+1)
+        
+    
+    coeff=finite_difference_coeff(stencil,order)/h**order
+    
+    Nx=len(x)
+    matrix_coeff=np.zeros((Nx-accuracy-order+1,Nx))
+    for i in range(Nx-accuracy-order+1):
+        matrix_coeff[i,i:n_stencil+i]=coeff[:,0]
+        
+    results=matrix_coeff @ x
+    # x_results=x[int((n_stencil-1)/2):-int((n_stencil-1)/2)]
+    return results</code></pre>
+</details>
+<div class="desc"><p>Function to calculate the coefficient to calculate a finite difference for derivative calculation</p>
+<p>args:
+- x (array): the 1D array for which to calculate the finite difference. The size of the array should be higher than the size of the stencil given by 2 * |<em> (order + 1) / 2 </em>| - 1 + 2 * |<em> accuracy / 2</em>|
+- h (scalar): the step size for an uniform grid spacing between each finite difference interval
+- order (integer): the order of the derivation
+- accuracy (integer): related to the number of points taken for the finite difference. see <a href="https://en.wikipedia.org/wiki/Finite_difference_coefficient">https://en.wikipedia.org/wiki/Finite_difference_coefficient</a>
+- kind (string): the type of finite difference calculated. For now, only "central" finite difference is implemented.</p>
+<p>return:
+- results (numpy array): an array with the results of the calculation of the finite difference
+- x_results (numpy array): an array with the x value with the central value for each calculation of the finite difference</p></div>
+</dd>
+<dt id="dopes.data_analysis.data_processing.finite_difference_coeff"><code class="name flex">
+<span>def <span class="ident">finite_difference_coeff</span></span>(<span>stencil, order)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def finite_difference_coeff(stencil,order):
+    &#34;&#34;&#34; Function to calculate the coefficient to calculate a finite difference for derivative calculation
+        https://en.wikipedia.org/wiki/Finite_difference_coefficient
+        
+        args:
+            - stencil (list of integer): the node point for the calculation of each derivation point. The size of the stencil depends on the accuracy and the order of the derivation. For central difference, the length of the stencil is odd and symetric around 0.
+            - order (integer): the order of the derivation
+    
+        return:
+            - coeff (numpy array): a column array of the coefficients to be used to calculate the finite difference
+    &#34;&#34;&#34;  
+    N=len(stencil)
+    stencil_matrix=np.zeros((N,N))
+    for i in range(N):
+        stencil_matrix[i]=np.array(stencil)**i
+    delta=np.zeros((N,1))
+    delta[order,0]= math.factorial(order)
+
+    coeff=np.linalg.inv(stencil_matrix) @ delta
+    return coeff</code></pre>
+</details>
+<div class="desc"><p>Function to calculate the coefficient to calculate a finite difference for derivative calculation
+<a href="https://en.wikipedia.org/wiki/Finite_difference_coefficient">https://en.wikipedia.org/wiki/Finite_difference_coefficient</a></p>
+<p>args:
+- stencil (list of integer): the node point for the calculation of each derivation point. The size of the stencil depends on the accuracy and the order of the derivation. For central difference, the length of the stencil is odd and symetric around 0.
+- order (integer): the order of the derivation</p>
+<p>return:
+- coeff (numpy array): a column array of the coefficients to be used to calculate the finite difference</p></div>
+</dd>
+<dt id="dopes.data_analysis.data_processing.fit_gaussian"><code class="name flex">
+<span>def <span class="ident">fit_gaussian</span></span>(<span>x, y, xmin=None, xmax=None, x0=0, A=1, W=1)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def fit_gaussian(x,y,xmin=None,xmax=None,x0=0,A=1,W=1):
+    &#34;&#34;&#34; Function to fit the data with a Lorentzian function 
+    
+        args:
+            - x (array_like) : a 1D input array.
+            - y (array_like) : a 1D  input array with the same dimension of x.
+            - xmin (scalar) : a scalar or array of values to set the minimum value of the data range on which the Gaussian is calculated. 
+            - xmax (scalar) : a scalar or array of values to set the maximum value of the data range on which the Gaussian is calculated. .
+            - x0 (scalar) : the starting position of the Gaussian function for the fit
+            - A (scalar) : the starting amplitude of the Gaussian function for the fit
+            - W (scalar) : the starting full width at half maximum (FWHM) of the Gaussian function for the fit
+        return:
+            - a tuple (parameter_dictionary, data_gaussian) with the a dictionary containing the fitting parameters (&#34;position&#34;, &#34;amplitude&#34; and &#34;width&#34;) and the corresponding Gaussian function evaluated in x.
+    &#34;&#34;&#34;
+    if (xmin is None) and (xmax is None):
+        x_fit=x
+        y_fit=y
+    else:
+        index=(x&gt;=xmin) &amp; (x&lt;=xmax) 
+        x_fit=x[index]
+        y_fit=y[index]
+
+    p_gaussian=curve_fit(gaussian, x_fit, y_fit, p0=[x0,A,W])[0]
+    return {&#34;position&#34;:p_gaussian[0],&#34;width&#34;:p_gaussian[1],&#34;amplitude&#34;:p_gaussian[2]}, gaussian(x,*p_gaussian)</code></pre>
+</details>
+<div class="desc"><p>Function to fit the data with a Lorentzian function </p>
+<p>args:
+- x (array_like) : a 1D input array.
+- y (array_like) : a 1D
+input array with the same dimension of x.
+- xmin (scalar) : a scalar or array of values to set the minimum value of the data range on which the Gaussian is calculated.
+- xmax (scalar) : a scalar or array of values to set the maximum value of the data range on which the Gaussian is calculated. .
+- x0 (scalar) : the starting position of the Gaussian function for the fit
+- A (scalar) : the starting amplitude of the Gaussian function for the fit
+- W (scalar) : the starting full width at half maximum (FWHM) of the Gaussian function for the fit
+return:
+- a tuple (parameter_dictionary, data_gaussian) with the a dictionary containing the fitting parameters ("position", "amplitude" and "width") and the corresponding Gaussian function evaluated in x.</p></div>
+</dd>
+<dt id="dopes.data_analysis.data_processing.fit_lorentzian"><code class="name flex">
+<span>def <span class="ident">fit_lorentzian</span></span>(<span>x, y, xmin=None, xmax=None, x0=520.7, A0=1, W0=3)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def fit_lorentzian(x,y,xmin=None,xmax=None,x0=520.7,A0=1,W0=3):
+    &#34;&#34;&#34; Function to fit the data with a Lorentzian function 
+    
+        args:
+            - x (array_like) : a 1D input array.
+            - y (array_like) : a 1D  input array with the same dimension of x.
+            - xmin (scalar) : a scalar or array of values to set the minimum value of the data range on which the Lorentzian is calculated. 
+            - xmax (scalar) : a scalar or array of values to set the maximum value of the data range on which the Lorentzian is calculated. .
+            - x0 (scalar) : the starting position of the Lorentzian function for the fit
+            - A (scalar) : the starting amplitude of the Lorentzian function for the fit
+            - W (scalar) : the starting full width at half maximum (FWHM) of the Lorentzian function for the fit
+        return:
+            - a tuple (parameter_dictionary, data_lorentzian) with the a dictionary containing the fitting parameters (&#34;position&#34;, &#34;amplitude&#34; and &#34;width&#34;) and the corresponding Lorentzian function evaluated in x.
+    &#34;&#34;&#34;
+    if (xmin is None) and (xmax is None):
+        x_fit=x
+        y_fit=y
+    else:
+        index=(x&gt;=xmin) &amp; (x&lt;=xmax) 
+        x_fit=x[index]
+        y_fit=y[index]
+    p_lorentzian=curve_fit(lorentzian, x_fit, y_fit, p0=[x0,A0,W0])[0]
+    return {&#34;position&#34;:p_lorentzian[0],&#34;amplitude&#34;:p_lorentzian[1],&#34;width&#34;:p_lorentzian[2]}, lorentzian(x,*p_lorentzian)</code></pre>
+</details>
+<div class="desc"><p>Function to fit the data with a Lorentzian function </p>
+<p>args:
+- x (array_like) : a 1D input array.
+- y (array_like) : a 1D
+input array with the same dimension of x.
+- xmin (scalar) : a scalar or array of values to set the minimum value of the data range on which the Lorentzian is calculated.
+- xmax (scalar) : a scalar or array of values to set the maximum value of the data range on which the Lorentzian is calculated. .
+- x0 (scalar) : the starting position of the Lorentzian function for the fit
+- A (scalar) : the starting amplitude of the Lorentzian function for the fit
+- W (scalar) : the starting full width at half maximum (FWHM) of the Lorentzian function for the fit
+return:
+- a tuple (parameter_dictionary, data_lorentzian) with the a dictionary containing the fitting parameters ("position", "amplitude" and "width") and the corresponding Lorentzian function evaluated in x.</p></div>
+</dd>
+<dt id="dopes.data_analysis.data_processing.fit_lorentzian_2peaks"><code class="name flex">
+<span>def <span class="ident">fit_lorentzian_2peaks</span></span>(<span>x, y, xmin=None, xmax=None, x0=(520, 520.7), A0=(1, 1), W0=(3, 3))</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def fit_lorentzian_2peaks(x,y,xmin=None,xmax=None,x0=(520,520.7),A0=(1,1),W0=(3,3)):
+    &#34;&#34;&#34; Function to fit the data with a Lorentzian function 
+    
+        args:
+            - x (array_like) : a 1D input array.
+            - y (array_like) : a 1D  input array with the same dimension of x.
+            - xmin (scalar) : a scalar or array of values to set the minimum value of the data range on which the Lorentzian is calculated. 
+            - xmax (scalar) : a scalar or array of values to set the maximum value of the data range on which the Lorentzian is calculated. .
+            - x0 (tuple) : the two starting position of the double Lorentzian function for the fit
+            - A (tuple) : the two starting amplitude of the double Lorentzian function for the fit
+            - W (tuple) : the two starting full width at half maximum (FWHM) of the double Lorentzian function for the fit
+        return:
+            - a tuple (parameter_dictionary, data_lorentzian) with the a dictionary containing the fitting parameters (&#34;position&#34;, &#34;amplitude&#34; and &#34;width&#34;) and the corresponding double Lorentzian function evaluated in x.
+        &#34;&#34;&#34;
+    if (xmin is None) and (xmax is None):
+        x_fit=x
+        y_fit=y
+    else:
+        index=(x&gt;=xmin) &amp; (x&lt;=xmax) 
+        x_fit=x[index]
+        y_fit=y[index]
+    p_lorentzian=curve_fit(lorentzian2, x_fit, y_fit, p0=np.reshape([x0,A0,W0],newshape=6))[0]
+    return {&#34;position&#34;:p_lorentzian[:2],&#34;amplitude&#34;:p_lorentzian[2:4],&#34;width&#34;:p_lorentzian[4:]}, lorentzian(x,*p_lorentzian)</code></pre>
+</details>
+<div class="desc"><p>Function to fit the data with a Lorentzian function </p>
+<p>args:
+- x (array_like) : a 1D input array.
+- y (array_like) : a 1D
+input array with the same dimension of x.
+- xmin (scalar) : a scalar or array of values to set the minimum value of the data range on which the Lorentzian is calculated.
+- xmax (scalar) : a scalar or array of values to set the maximum value of the data range on which the Lorentzian is calculated. .
+- x0 (tuple) : the two starting position of the double Lorentzian function for the fit
+- A (tuple) : the two starting amplitude of the double Lorentzian function for the fit
+- W (tuple) : the two starting full width at half maximum (FWHM) of the double Lorentzian function for the fit
+return:
+- a tuple (parameter_dictionary, data_lorentzian) with the a dictionary containing the fitting parameters ("position", "amplitude" and "width") and the corresponding double Lorentzian function evaluated in x.</p></div>
+</dd>
+<dt id="dopes.data_analysis.data_processing.gaussian"><code class="name flex">
+<span>def <span class="ident">gaussian</span></span>(<span>x, x0, A, W)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def gaussian(x, x0, A, W):
+    &#34;&#34;&#34; Faussian function 
+    
+        args:
+            - x (array_like) : a 1D input array.
+            - x0 (scalar) : the position of the Gaussian function
+            - A (scalar) : the amplitude of the Lorentzian function
+            - W (scalar) : the full width at half maximum (FWHM) of the Lorentzian function
+        return:
+            - an array of the same dimension od x
+    &#34;&#34;&#34; 
+    return A*np.exp(-np.power(x - x0, 2.) / (2 * np.power(W, 2.))) / (W * np.sqrt(2*np.pi))</code></pre>
+</details>
+<div class="desc"><p>Faussian function </p>
+<p>args:
+- x (array_like) : a 1D input array.
+- x0 (scalar) : the position of the Gaussian function
+- A (scalar) : the amplitude of the Lorentzian function
+- W (scalar) : the full width at half maximum (FWHM) of the Lorentzian function
+return:
+- an array of the same dimension od x</p></div>
+</dd>
+<dt id="dopes.data_analysis.data_processing.interpolate"><code class="name flex">
+<span>def <span class="ident">interpolate</span></span>(<span>x, y, x_interp, kind='cubic')</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def interpolate(x,y,x_interp,kind=&#34;cubic&#34;):
+    &#34;&#34;&#34; Function to interpolate an 1-D array
+    
+        args:
+            - x (array_like) : a 1-D array of real values.
+            - y (array_like) : a 1-D array of real values of the same dimension of x.
+            - x_interp (array_like) : a 1-D array of real values of the any dimension but with all values include between the max and min value of x.
+            - kind (string or integer) : Specifies the kind of interpolation as a string specifying the order of the spline interpolator to use. The string has to be one of ‘linear’, ‘nearest’, ‘nearest-up’, ‘zero’, ‘slinear’, ‘quadratic’, ‘cubic’, ‘previous’, or ‘next’. 
+        return:
+            - an array the same size as x_interp containing the interpolated result.
+    &#34;&#34;&#34;    
+    f=interp1d(x, y,kind=kind)    
+    return f(x_interp)</code></pre>
+</details>
+<div class="desc"><p>Function to interpolate an 1-D array</p>
+<p>args:
+- x (array_like) : a 1-D array of real values.
+- y (array_like) : a 1-D array of real values of the same dimension of x.
+- x_interp (array_like) : a 1-D array of real values of the any dimension but with all values include between the max and min value of x.
+- kind (string or integer) : Specifies the kind of interpolation as a string specifying the order of the spline interpolator to use. The string has to be one of ‘linear’, ‘nearest’, ‘nearest-up’, ‘zero’, ‘slinear’, ‘quadratic’, ‘cubic’, ‘previous’, or ‘next’.
+return:
+- an array the same size as x_interp containing the interpolated result.</p></div>
+</dd>
+<dt id="dopes.data_analysis.data_processing.lorentzian"><code class="name flex">
+<span>def <span class="ident">lorentzian</span></span>(<span>x, x0, A, W)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def lorentzian(x,x0,A,W):
+    &#34;&#34;&#34; Lorentzian function 
+    
+        args:
+            - x (array_like) : a 1D input array.
+            - x0 (scalar) : the position of the Lorentzian function
+            - A (scalar) : the amplitude of the Lorentzian function
+            - W (scalar) : the full width at half maximum (FWHM) of the Lorentzian function
+        return:
+            - an array of the same dimension as x
+    &#34;&#34;&#34; 
+    return A/(1+((x-x0)/(W/2))**2)</code></pre>
+</details>
+<div class="desc"><p>Lorentzian function </p>
+<p>args:
+- x (array_like) : a 1D input array.
+- x0 (scalar) : the position of the Lorentzian function
+- A (scalar) : the amplitude of the Lorentzian function
+- W (scalar) : the full width at half maximum (FWHM) of the Lorentzian function
+return:
+- an array of the same dimension as x</p></div>
+</dd>
+<dt id="dopes.data_analysis.data_processing.lorentzian2"><code class="name flex">
+<span>def <span class="ident">lorentzian2</span></span>(<span>x, x0, x01, A, A1, W, W1)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def lorentzian2(x,x0,x01,A,A1,W,W1):
+    &#34;&#34;&#34; Function with the sum of two Lorentzian 
+    
+        args:
+            - x (array_like) : a 1D input array.
+            - x01 (scalar) : the position of the first Lorentzian function
+            - A1 (scalar) : the amplitude of the first Lorentzian function
+            - W1 (scalar) : the full width at half maximum (FWHM) of the first Lorentzian function
+            - x02 (scalar) : the position of the second Lorentzian function
+            - A2 (scalar) : the amplitude of the second Lorentzian function
+            - W2 (scalar) : the full width at half maximum (FWHM) of the second Lorentzian function
+        return:
+            - an array of the same dimension as x
+    &#34;&#34;&#34; 
+    return A/(1+((x-x0)/(W/2))**2)+A1/(1+((x-x01)/(W1/2))**2)</code></pre>
+</details>
+<div class="desc"><p>Function with the sum of two Lorentzian </p>
+<p>args:
+- x (array_like) : a 1D input array.
+- x01 (scalar) : the position of the first Lorentzian function
+- A1 (scalar) : the amplitude of the first Lorentzian function
+- W1 (scalar) : the full width at half maximum (FWHM) of the first Lorentzian function
+- x02 (scalar) : the position of the second Lorentzian function
+- A2 (scalar) : the amplitude of the second Lorentzian function
+- W2 (scalar) : the full width at half maximum (FWHM) of the second Lorentzian function
+return:
+- an array of the same dimension as x</p></div>
+</dd>
+<dt id="dopes.data_analysis.data_processing.moving_median"><code class="name flex">
+<span>def <span class="ident">moving_median</span></span>(<span>x, window_length=3)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def moving_median(x,window_length=3):
+    &#34;&#34;&#34; Function to perform a median filter on a array
+    
+        args:
+            - x (array_like) : the input array.
+            - window_length (scalar) : size of the median filter window.    
+        return:
+            - an array the same size as input containing the median filtered result.
+    &#34;&#34;&#34;
+    return signal.medfilt(x,window_length)</code></pre>
+</details>
+<div class="desc"><p>Function to perform a median filter on a array</p>
+<p>args:
+- x (array_like) : the input array.
+- window_length (scalar) : size of the median filter window.
+<br>
+return:
+- an array the same size as input containing the median filtered result.</p></div>
+</dd>
+<dt id="dopes.data_analysis.data_processing.remove_baseline"><code class="name flex">
+<span>def <span class="ident">remove_baseline</span></span>(<span>x, y, xmin_baseline, xmax_baseline, polyorder=2)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def remove_baseline(x,y,xmin_baseline,xmax_baseline,polyorder=2):
+    &#34;&#34;&#34; Function to remove the baseline a 1-D array
+    
+        args:
+            - x (array_like) : a 1D input array.
+            - y (array_like) : a 1D  input array with the same dimension of x.
+            - xmin_baseline (scalar or array) : a scalar or array of values to set the minimum value of the data ranges on which the baseline is calculated. Several windows can be specified by specifying an array of values
+            - xmax_baseline (scalar or array) : a scalar or array of values to set the maximum value of the data ranges on which the baseline is calculated. Several windows can be specified by specifying an array of values.
+            - polyorder (scalar) : the order of the polynome to calculate the baseline    
+        return:
+            - a tuple (corrected_data, baseline) with the corrected data and the baseline calculated.
+    &#34;&#34;&#34;       
+    if isinstance(xmin_baseline,(int,float)):
+        xmin_baseline=[xmin_baseline]
+        xmax_baseline=[xmax_baseline]
+        
+    index=[False]*len(x)
+    for i in range(len(xmin_baseline)):
+        index = index | ((x&gt;=xmin_baseline[i]) &amp; (x&lt;=xmax_baseline[i]) )
+    p=np.polyfit(x[index],y[index],deg=polyorder)
+    baseline=np.polyval(p,x)
+    return y-baseline, baseline</code></pre>
+</details>
+<div class="desc"><p>Function to remove the baseline a 1-D array</p>
+<p>args:
+- x (array_like) : a 1D input array.
+- y (array_like) : a 1D
+input array with the same dimension of x.
+- xmin_baseline (scalar or array) : a scalar or array of values to set the minimum value of the data ranges on which the baseline is calculated. Several windows can be specified by specifying an array of values
+- xmax_baseline (scalar or array) : a scalar or array of values to set the maximum value of the data ranges on which the baseline is calculated. Several windows can be specified by specifying an array of values.
+- polyorder (scalar) : the order of the polynome to calculate the baseline
+<br>
+return:
+- a tuple (corrected_data, baseline) with the corrected data and the baseline calculated.</p></div>
+</dd>
+<dt id="dopes.data_analysis.data_processing.smooth"><code class="name flex">
+<span>def <span class="ident">smooth</span></span>(<span>x, window_length=11, polyorder=2)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def smooth(x, window_length=11, polyorder=2):
+    &#34;&#34;&#34; Function to smooth an array by applying a Savitzky-Golay filter
+    
+        args:
+            - x (array_like) : the data to be filtered.
+            - window_length (scalar) : the length of the filter window.
+            - polyorder (scalar) : the order of the polynomial used to fit the samples. polyorder must be less than window_length.   
+        return:
+            - an array the same size as input containing the filtered result.
+    &#34;&#34;&#34;    
+    return signal.savgol_filter(x,window_length,polyorder)</code></pre>
+</details>
+<div class="desc"><p>Function to smooth an array by applying a Savitzky-Golay filter</p>
+<p>args:
+- x (array_like) : the data to be filtered.
+- window_length (scalar) : the length of the filter window.
+- polyorder (scalar) : the order of the polynomial used to fit the samples. polyorder must be less than window_length. <br>
+return:
+- an array the same size as input containing the filtered result.</p></div>
+</dd>
+</dl>
+</section>
+<section>
+</section>
+</article>
+<nav id="sidebar">
+<div class="toc">
+<ul></ul>
+</div>
+<ul id="index">
+<li><h3>Super-module</h3>
+<ul>
+<li><code><a title="dopes.data_analysis" href="index.html">dopes.data_analysis</a></code></li>
+</ul>
+</li>
+<li><h3><a href="#header-functions">Functions</a></h3>
+<ul class="">
+<li><code><a title="dopes.data_analysis.data_processing.finite_difference" href="#dopes.data_analysis.data_processing.finite_difference">finite_difference</a></code></li>
+<li><code><a title="dopes.data_analysis.data_processing.finite_difference_coeff" href="#dopes.data_analysis.data_processing.finite_difference_coeff">finite_difference_coeff</a></code></li>
+<li><code><a title="dopes.data_analysis.data_processing.fit_gaussian" href="#dopes.data_analysis.data_processing.fit_gaussian">fit_gaussian</a></code></li>
+<li><code><a title="dopes.data_analysis.data_processing.fit_lorentzian" href="#dopes.data_analysis.data_processing.fit_lorentzian">fit_lorentzian</a></code></li>
+<li><code><a title="dopes.data_analysis.data_processing.fit_lorentzian_2peaks" href="#dopes.data_analysis.data_processing.fit_lorentzian_2peaks">fit_lorentzian_2peaks</a></code></li>
+<li><code><a title="dopes.data_analysis.data_processing.gaussian" href="#dopes.data_analysis.data_processing.gaussian">gaussian</a></code></li>
+<li><code><a title="dopes.data_analysis.data_processing.interpolate" href="#dopes.data_analysis.data_processing.interpolate">interpolate</a></code></li>
+<li><code><a title="dopes.data_analysis.data_processing.lorentzian" href="#dopes.data_analysis.data_processing.lorentzian">lorentzian</a></code></li>
+<li><code><a title="dopes.data_analysis.data_processing.lorentzian2" href="#dopes.data_analysis.data_processing.lorentzian2">lorentzian2</a></code></li>
+<li><code><a title="dopes.data_analysis.data_processing.moving_median" href="#dopes.data_analysis.data_processing.moving_median">moving_median</a></code></li>
+<li><code><a title="dopes.data_analysis.data_processing.remove_baseline" href="#dopes.data_analysis.data_processing.remove_baseline">remove_baseline</a></code></li>
+<li><code><a title="dopes.data_analysis.data_processing.smooth" href="#dopes.data_analysis.data_processing.smooth">smooth</a></code></li>
+</ul>
+</li>
+</ul>
+</nav>
+</main>
+<footer id="footer">
+<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
+</footer>
+</body>
+</html>
diff --git a/html/data_analysis/diode.html b/html/data_analysis/diode.html
new file mode 100644
index 0000000000000000000000000000000000000000..d25a64333cc875a0d07a5d258f46b96121513d89
--- /dev/null
+++ b/html/data_analysis/diode.html
@@ -0,0 +1,353 @@
+<!doctype html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
+<meta name="generator" content="pdoc3 0.11.6">
+<title>dopes.data_analysis.diode API documentation</title>
+<meta name="description" content="">
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/typography.min.css" integrity="sha512-Y1DYSb995BAfxobCkKepB1BqJJTPrOp3zPL74AWFugHHmmdcvO+C48WLrUOlhGMc0QG7AE3f7gmvvcrmX2fDoA==" crossorigin>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css" crossorigin>
+<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:1.5em;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:2em 0 .50em 0}h3{font-size:1.4em;margin:1.6em 0 .7em 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .2s ease-in-out}a:visited{color:#503}a:hover{color:#b62}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900;font-weight:bold}pre code{font-size:.8em;line-height:1.4em;padding:1em;display:block}code{background:#f3f3f3;font-family:"DejaVu Sans Mono",monospace;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source > summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible;min-width:max-content}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em 1em;margin:1em 0}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
+<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul ul{padding-left:1em}.toc > ul > li{margin-top:.5em}}</style>
+<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
+<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js" integrity="sha512-D9gUyxqja7hBtkWpPWGt9wfbfaMGVt9gnyCvYa+jojwwPHLCzUm5i8rpk7vD7wNee9bA35eYIjobYPaQuKS1MQ==" crossorigin></script>
+<script>window.addEventListener('DOMContentLoaded', () => {
+hljs.configure({languages: ['bash', 'css', 'diff', 'graphql', 'ini', 'javascript', 'json', 'plaintext', 'python', 'python-repl', 'rust', 'shell', 'sql', 'typescript', 'xml', 'yaml']});
+hljs.highlightAll();
+/* Collapse source docstrings */
+setTimeout(() => {
+[...document.querySelectorAll('.hljs.language-python > .hljs-string')]
+.filter(el => el.innerHTML.length > 200 && ['"""', "'''"].includes(el.innerHTML.substring(0, 3)))
+.forEach(el => {
+let d = document.createElement('details');
+d.classList.add('hljs-string');
+d.innerHTML = '<summary>"""</summary>' + el.innerHTML.substring(3);
+el.replaceWith(d);
+});
+}, 100);
+})</script>
+</head>
+<body>
+<main>
+<article id="content">
+<header>
+<h1 class="title">Module <code>dopes.data_analysis.diode</code></h1>
+</header>
+<section id="section-intro">
+</section>
+<section>
+</section>
+<section>
+</section>
+<section>
+<h2 class="section-title" id="header-functions">Functions</h2>
+<dl>
+<dt id="dopes.data_analysis.diode.depletion_length"><code class="name flex">
+<span>def <span class="ident">depletion_length</span></span>(<span>doping_in, doping_out, Vbias=0, temp=300)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def depletion_length(doping_in, doping_out, Vbias=0,temp=300):
+    &#34;&#34;&#34; Function to calculate the depletion length in a pn junction
+        
+        args:
+            - doping_in (scalar): the doping in the region for which the depletion length has to be calculated
+            - doping_out (scalar): the doping in the adjacent region for which the depletion length has to be calculated
+            - Vbias (scalar): the bias voltage of the pn junction
+            - temp (scalar): the temperature
+                
+        return:
+            - a scalar with the depletion length calculated in one region
+    &#34;&#34;&#34; 
+    
+    kB = 1.38e-23 # J/K
+    q = 1.602e-19 # C
+    epsilon_0 = 8.8542e-12 # F/m
+    epsilon_si = 11.7
+    
+    phi_0 = kB * temp / q * np.log(doping_in * doping_out / sc.intrinsic_concentration(temp)**2 )
+    return np.sqrt(2 * epsilon_si * epsilon_0 / q * doping_out / doping_in / (doping_in + doping_out) * (phi_0 - Vbias))</code></pre>
+</details>
+<div class="desc"><p>Function to calculate the depletion length in a pn junction</p>
+<p>args:
+- doping_in (scalar): the doping in the region for which the depletion length has to be calculated
+- doping_out (scalar): the doping in the adjacent region for which the depletion length has to be calculated
+- Vbias (scalar): the bias voltage of the pn junction
+- temp (scalar): the temperature</p>
+<p>return:
+- a scalar with the depletion length calculated in one region</p></div>
+</dd>
+<dt id="dopes.data_analysis.diode.ideal_diode"><code class="name flex">
+<span>def <span class="ident">ideal_diode</span></span>(<span>Vbias, Is, n=1, temp=300)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def ideal_diode(Vbias,Is,n=1, temp=300):
+  
+    &#34;&#34;&#34; Function to calculate the current in an ideal diode 
+        
+        args:
+            - Vbias (scalar or sequence): the bias voltage of the diode
+            - Is (scalar): the saturation current of the diode
+            - n (scalar): the ideality factor of the diode, 1 for radiative recombination, 2 for SRH recombination
+            - temp (scalar): the temperature
+                
+        return:
+            - a scalar or sequence with same dimension as Vbias
+    &#34;&#34;&#34; 
+    
+    kB = 1.38e-23 # J/K
+    q = 1.602e-19 # C
+
+    return Is * (np.exp(q * Vbias / (n * kB * temp)) -1 )</code></pre>
+</details>
+<div class="desc"><p>Function to calculate the current in an ideal diode </p>
+<p>args:
+- Vbias (scalar or sequence): the bias voltage of the diode
+- Is (scalar): the saturation current of the diode
+- n (scalar): the ideality factor of the diode, 1 for radiative recombination, 2 for SRH recombination
+- temp (scalar): the temperature</p>
+<p>return:
+- a scalar or sequence with same dimension as Vbias</p></div>
+</dd>
+<dt id="dopes.data_analysis.diode.j_radiative"><code class="name flex">
+<span>def <span class="ident">j_radiative</span></span>(<span>Vbias, mu_n, mu_p, tau_n, tau_p, ND, NA, ln, lp, temp=300)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def j_radiative(Vbias,mu_n,mu_p,tau_n,tau_p,ND,NA,ln,lp,temp=300):
+    &#34;&#34;&#34; Function to calculate the radial contribution to the current density in a silicon pn junction
+        
+        args:
+            - Vbias (scalar): the bias voltage of the pn junction
+            - mu_n (scalar): the mobility of the electrons
+            - mu_p (scalar): the mobility of the holes
+            - tau_n (scalar): the lifetime of the electrons
+            - tau_p (scalar): the lifetime of the holes
+            - ND (scalar): the donor doping concentration in the n region 
+            - NA (scalar): the acceptor doping concentraion in the p region 
+            - ln (scalar): the length of the cathode (n-doped region)
+            - lp (scalar): the length of the anode (p-doped region)
+            - temp (scalar): the temperature
+
+        return:
+            - a scalar with the radiative current density calculated 
+    &#34;&#34;&#34;  
+    b_rad = 4.76e-15 # cm3/s - low-impurity value entre 1 et 10
+
+    kB = 1.38e-23 # J/K
+    q = 1.602e-19 # C
+
+    Dn = kB * temp / q * mu_n
+    Dp = kB * temp / q * mu_p
+    
+    Ln = np.sqrt( Dn * tau_n )
+    Lp = np.sqrt( Dp * tau_p )
+    
+    ld_n = depletion_length(ND, NA, Vbias)
+    ld_p = depletion_length(NA, ND, Vbias)
+    
+    ni = sc.intrinsic_concentration(temp)
+    n_p0=ni**2/NA
+    p_n0=ni**2/ND
+        
+    coeff_radial = Dn * n_p0 / Ln / np.tanh( (lp-ld_p) / Ln ) + Dp * p_n0 / Lp / np.tanh( (ln-ld_n) / Lp ) + ni**2 *b_rad* (ld_p + ld_n)
+    
+    
+    return q * ( coeff_radial * (np.exp(q * Vbias/ ( kB * temp)) - 1 ) )</code></pre>
+</details>
+<div class="desc"><p>Function to calculate the radial contribution to the current density in a silicon pn junction</p>
+<p>args:
+- Vbias (scalar): the bias voltage of the pn junction
+- mu_n (scalar): the mobility of the electrons
+- mu_p (scalar): the mobility of the holes
+- tau_n (scalar): the lifetime of the electrons
+- tau_p (scalar): the lifetime of the holes
+- ND (scalar): the donor doping concentration in the n region
+- NA (scalar): the acceptor doping concentraion in the p region
+- ln (scalar): the length of the cathode (n-doped region)
+- lp (scalar): the length of the anode (p-doped region)
+- temp (scalar): the temperature</p>
+<p>return:
+- a scalar with the radiative current density calculated</p></div>
+</dd>
+<dt id="dopes.data_analysis.diode.j_srh"><code class="name flex">
+<span>def <span class="ident">j_srh</span></span>(<span>Vbias, ND, NA, tau=1e-07, temp=300)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def j_srh(Vbias,ND,NA,tau=1e-7,temp=300):
+    &#34;&#34;&#34; Function to calculate the Shockley-Read-Hall contribution to the current density in a pn junction
+        
+        args:
+            - Vbias (scalar): the bias voltage of the pn junction
+            - ND (scalar): the donor doping concentration in the n region 
+            - NA (scalar): the acceptor doping concentraion in the p region 
+            - tau (scalar): the global lifetime associated to the SRH mechanism
+            - temp (scalar): the temperature
+
+        return:
+            - a scalar with the SRH current density calculated 
+    &#34;&#34;&#34;  
+    kB = 1.38e-23 # J/K
+    q = 1.602e-19 # C
+
+    ld_n = depletion_length(ND, NA, Vbias)
+    ld_p = depletion_length(NA, ND, Vbias)
+    ni = sc.intrinsic_concentration(temp)
+    x=(ld_p + ld_n) # approximation by considering only the depletion region without diffusion mechanism, gives an upper limit as the effective length is always below
+    
+    coeff_SRH = q * ni * x / (2 * tau)
+    
+    return ( coeff_SRH * (np.exp(q * Vbias/ (2 * kB * temp)) - 1 ) )</code></pre>
+</details>
+<div class="desc"><p>Function to calculate the Shockley-Read-Hall contribution to the current density in a pn junction</p>
+<p>args:
+- Vbias (scalar): the bias voltage of the pn junction
+- ND (scalar): the donor doping concentration in the n region
+- NA (scalar): the acceptor doping concentraion in the p region
+- tau (scalar): the global lifetime associated to the SRH mechanism
+- temp (scalar): the temperature</p>
+<p>return:
+- a scalar with the SRH current density calculated</p></div>
+</dd>
+<dt id="dopes.data_analysis.diode.two_diodes"><code class="name flex">
+<span>def <span class="ident">two_diodes</span></span>(<span>Vbias, Is1, Is2, n1=1, n2=2, temp=300)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def two_diodes(Vbias,Is1,Is2,n1=1,n2=2, temp=300):
+    &#34;&#34;&#34; Function to calculate the current for a two diodes model 
+        
+        args:
+            - Vbias (scalar or sequence): the bias voltage of the diode
+            - Is1 (scalar): the saturation current of the first diode
+            - Is2 (scalar): the saturation current of the second diode
+            - n1 (scalar): the ideality factor of the first diode, 1 for radiative recombination, 2 for SRH recombination
+            - n1 (scalar): the ideality factor of the second diode, 1 for radiative recombination, 2 for SRH recombination
+            - temp (scalar): the temperature
+                
+        return:
+            - a scalar or sequence with same dimension as Vbias
+    &#34;&#34;&#34; 
+    kB = 1.38e-23 # J/K
+    q = 1.602e-19 # C
+
+    return Is1 * (np.exp( q * Vbias / (n1 * kB * temp)) -1 ) + Is2 * (np.exp( q * Vbias / (n2 * kB * temp)) -1 )</code></pre>
+</details>
+<div class="desc"><p>Function to calculate the current for a two diodes model </p>
+<p>args:
+- Vbias (scalar or sequence): the bias voltage of the diode
+- Is1 (scalar): the saturation current of the first diode
+- Is2 (scalar): the saturation current of the second diode
+- n1 (scalar): the ideality factor of the first diode, 1 for radiative recombination, 2 for SRH recombination
+- n1 (scalar): the ideality factor of the second diode, 1 for radiative recombination, 2 for SRH recombination
+- temp (scalar): the temperature</p>
+<p>return:
+- a scalar or sequence with same dimension as Vbias</p></div>
+</dd>
+<dt id="dopes.data_analysis.diode.two_diodes_with_resistances"><code class="name flex">
+<span>def <span class="ident">two_diodes_with_resistances</span></span>(<span>Vbias, Is1, Is2, n1=1, n2=2, temp=300, Rs=0, Rsh=inf)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def two_diodes_with_resistances(Vbias,Is1,Is2,n1=1,n2=2, temp=300, Rs=0, Rsh=float(&#34;inf&#34;)):
+    &#34;&#34;&#34; Function to calculate the current for a two diodes model by taking into account the series and shunt resistances
+        
+        args:
+            - Vbias (scalar or sequence): the bias voltage of the diode
+            - Is1 (scalar): the saturation current of the first diode
+            - Is2 (scalar): the saturation current of the second diode
+            - n1 (scalar): the ideality factor of the first diode, 1 for radiative recombination, 2 for SRH recombination
+            - n1 (scalar): the ideality factor of the second diode, 1 for radiative recombination, 2 for SRH recombination
+            - temp (scalar): the temperature
+            - Rs (scalar): the serie resistance 
+            - Rsh (scalar): the shunt resistance 
+                
+        return:
+            - a scalar or sequence with same dimension as Vbias
+    &#34;&#34;&#34; 
+    
+    kB = 1.38e-23 # J/K
+    q = 1.602e-19 # C
+    
+
+    if isinstance(Vbias, (int,float)):
+        # x0=np.min((two_diodes(Vbias,Is1,Is2,n1,n2, temp),Vbias/Rs))
+        I = fsolve(lambda x:Is1 * (np.exp( q * (Vbias - Rs * x) / (n1 * kB * temp)) -1 ) + Is2 * (np.exp( q * (Vbias - Rs * x) / (n2 * kB * temp)) -1 ) + (Vbias - Rs * x ) / Rsh - x,x0=0)
+    else:
+        I=np.zeros(len(Vbias))
+        i=0
+        i=0
+        for v in Vbias:
+            # x0=np.min((two_diodes(v,Is1,Is2,n1,n2, temp),v/Rs))
+            I[i] = fsolve(lambda x : Is1 * (np.exp( q * (v - Rs * x) / (n1 * kB * temp)) -1 ) + Is2 * (np.exp( q * (v - Rs * x) / (n2 * kB * temp)) -1 ) + (v - Rs * x ) / Rsh - x,x0=0)
+            i+=1
+    return I</code></pre>
+</details>
+<div class="desc"><p>Function to calculate the current for a two diodes model by taking into account the series and shunt resistances</p>
+<p>args:
+- Vbias (scalar or sequence): the bias voltage of the diode
+- Is1 (scalar): the saturation current of the first diode
+- Is2 (scalar): the saturation current of the second diode
+- n1 (scalar): the ideality factor of the first diode, 1 for radiative recombination, 2 for SRH recombination
+- n1 (scalar): the ideality factor of the second diode, 1 for radiative recombination, 2 for SRH recombination
+- temp (scalar): the temperature
+- Rs (scalar): the serie resistance
+- Rsh (scalar): the shunt resistance </p>
+<p>return:
+- a scalar or sequence with same dimension as Vbias</p></div>
+</dd>
+</dl>
+</section>
+<section>
+</section>
+</article>
+<nav id="sidebar">
+<div class="toc">
+<ul></ul>
+</div>
+<ul id="index">
+<li><h3>Super-module</h3>
+<ul>
+<li><code><a title="dopes.data_analysis" href="index.html">dopes.data_analysis</a></code></li>
+</ul>
+</li>
+<li><h3><a href="#header-functions">Functions</a></h3>
+<ul class="">
+<li><code><a title="dopes.data_analysis.diode.depletion_length" href="#dopes.data_analysis.diode.depletion_length">depletion_length</a></code></li>
+<li><code><a title="dopes.data_analysis.diode.ideal_diode" href="#dopes.data_analysis.diode.ideal_diode">ideal_diode</a></code></li>
+<li><code><a title="dopes.data_analysis.diode.j_radiative" href="#dopes.data_analysis.diode.j_radiative">j_radiative</a></code></li>
+<li><code><a title="dopes.data_analysis.diode.j_srh" href="#dopes.data_analysis.diode.j_srh">j_srh</a></code></li>
+<li><code><a title="dopes.data_analysis.diode.two_diodes" href="#dopes.data_analysis.diode.two_diodes">two_diodes</a></code></li>
+<li><code><a title="dopes.data_analysis.diode.two_diodes_with_resistances" href="#dopes.data_analysis.diode.two_diodes_with_resistances">two_diodes_with_resistances</a></code></li>
+</ul>
+</li>
+</ul>
+</nav>
+</main>
+<footer id="footer">
+<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
+</footer>
+</body>
+</html>
diff --git a/html/data_analysis/file_handling.html b/html/data_analysis/file_handling.html
new file mode 100644
index 0000000000000000000000000000000000000000..f3a121ebad08f7f41fff181be7d2785e6a3c7501
--- /dev/null
+++ b/html/data_analysis/file_handling.html
@@ -0,0 +1,189 @@
+<!doctype html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
+<meta name="generator" content="pdoc3 0.11.6">
+<title>dopes.data_analysis.file_handling API documentation</title>
+<meta name="description" content="">
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/typography.min.css" integrity="sha512-Y1DYSb995BAfxobCkKepB1BqJJTPrOp3zPL74AWFugHHmmdcvO+C48WLrUOlhGMc0QG7AE3f7gmvvcrmX2fDoA==" crossorigin>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css" crossorigin>
+<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:1.5em;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:2em 0 .50em 0}h3{font-size:1.4em;margin:1.6em 0 .7em 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .2s ease-in-out}a:visited{color:#503}a:hover{color:#b62}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900;font-weight:bold}pre code{font-size:.8em;line-height:1.4em;padding:1em;display:block}code{background:#f3f3f3;font-family:"DejaVu Sans Mono",monospace;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source > summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible;min-width:max-content}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em 1em;margin:1em 0}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
+<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul ul{padding-left:1em}.toc > ul > li{margin-top:.5em}}</style>
+<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
+<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js" integrity="sha512-D9gUyxqja7hBtkWpPWGt9wfbfaMGVt9gnyCvYa+jojwwPHLCzUm5i8rpk7vD7wNee9bA35eYIjobYPaQuKS1MQ==" crossorigin></script>
+<script>window.addEventListener('DOMContentLoaded', () => {
+hljs.configure({languages: ['bash', 'css', 'diff', 'graphql', 'ini', 'javascript', 'json', 'plaintext', 'python', 'python-repl', 'rust', 'shell', 'sql', 'typescript', 'xml', 'yaml']});
+hljs.highlightAll();
+/* Collapse source docstrings */
+setTimeout(() => {
+[...document.querySelectorAll('.hljs.language-python > .hljs-string')]
+.filter(el => el.innerHTML.length > 200 && ['"""', "'''"].includes(el.innerHTML.substring(0, 3)))
+.forEach(el => {
+let d = document.createElement('details');
+d.classList.add('hljs-string');
+d.innerHTML = '<summary>"""</summary>' + el.innerHTML.substring(3);
+el.replaceWith(d);
+});
+}, 100);
+})</script>
+</head>
+<body>
+<main>
+<article id="content">
+<header>
+<h1 class="title">Module <code>dopes.data_analysis.file_handling</code></h1>
+</header>
+<section id="section-intro">
+</section>
+<section>
+</section>
+<section>
+</section>
+<section>
+<h2 class="section-title" id="header-functions">Functions</h2>
+<dl>
+<dt id="dopes.data_analysis.file_handling.read_file"><code class="name flex">
+<span>def <span class="ident">read_file</span></span>(<span>file_path,<br>comments='#',<br>delimiter=',',<br>skip_header=0,<br>skip_footer=0,<br>max_rows=None,<br>usecols=None,<br>deletechars=&quot; !#$%&amp;&#x27;()*+, /:;&lt;=&gt;?@[\\]^{|}~&quot;)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def read_file(file_path,comments=comments,delimiter=delimiter, skip_header=skip_header,skip_footer=skip_footer,
+                    max_rows=max_rows,usecols=usecols, deletechars=deletechars):
+    &#34;&#34;&#34; Function to read data from a file
+    
+        args:
+            - file_path (string) : file, filename, list, or generator to read.
+            - comments (char) : the character used to indicate the start of a comment.
+            - delimiter (char) : the string used to separate values.
+            - skip_header (integer or sequence) : the number of lines to skip at the beginning of the file.
+            - skip_footer (integer or sequence) : the number of lines to skip at the end of the file.
+            - max_rows (integer) : the maximum number of rows to read. Must not be used with skip_footer at the same time.
+            - usecols (sequence) : which columns to read, with 0 being the first. For example, usecols = (1, 4, 5) will extract the 2nd, 5th and 6th columns.
+            - deletechars (string) : a string combining invalid characters that must be deleted from the names.
+    
+        return:
+            - data (numpy array): numpy array of the data read from the file
+    &#34;&#34;&#34;          
+    data=np.genfromtxt(file_path,comments=comments,delimiter=delimiter,
+                        skip_header=skip_header,skip_footer=skip_footer,
+                        max_rows=max_rows,usecols=usecols, deletechars=deletechars)
+    
+    return data</code></pre>
+</details>
+<div class="desc"><p>Function to read data from a file</p>
+<p>args:
+- file_path (string) : file, filename, list, or generator to read.
+- comments (char) : the character used to indicate the start of a comment.
+- delimiter (char) : the string used to separate values.
+- skip_header (integer or sequence) : the number of lines to skip at the beginning of the file.
+- skip_footer (integer or sequence) : the number of lines to skip at the end of the file.
+- max_rows (integer) : the maximum number of rows to read. Must not be used with skip_footer at the same time.
+- usecols (sequence) : which columns to read, with 0 being the first. For example, usecols = (1, 4, 5) will extract the 2nd, 5th and 6th columns.
+- deletechars (string) : a string combining invalid characters that must be deleted from the names.</p>
+<p>return:
+- data (numpy array): numpy array of the data read from the file</p></div>
+</dd>
+<dt id="dopes.data_analysis.file_handling.write_in_file"><code class="name flex">
+<span>def <span class="ident">write_in_file</span></span>(<span>file_path, data, delimiter=',', overwrite=False, header=None, date=True, comment='#')</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def write_in_file(file_path,data,delimiter=&#34;,&#34;,overwrite=False,header=None,date=True, comment=&#34;#&#34;):
+    &#34;&#34;&#34; Function to write data in a file
+    
+        args:
+            - file_path (string) : path for the data file, including the filename with its extension
+            - data (scalar, list or array) : the data to be written in the file
+            - delimiter (char) : the delimiter to separate the column of the data
+            - overwrite (boolean) : if True overwrite the existing file if any, if False, append the data to the existing file if any
+            - header (string) : header to be written before the data
+            - date (boolean) : date to be written at the beginning of the file
+            - comment (char) : char to be written before the header and date to indicate non-data lines
+    
+    &#34;&#34;&#34;        
+    if file_path.split(&#34;.&#34;)[-1]==&#34;csv&#34;:
+        delimiter=&#34;,&#34;
+        
+    # Create file and header
+    if overwrite:
+        f = open(file_path, &#34;w&#34;)
+    else:
+        f = open(file_path, &#34;a&#34;)
+        
+    if date:
+        f.write(&#34;%s %s\n&#34;%(comment,datetime.datetime.now().strftime(&#34;%c&#34;)))
+    
+    if isinstance(header, str):
+        for line in header.split(&#34;\n&#34;):
+            f.write(comment+&#34; &#34;+line+&#34;\n&#34;)
+
+    
+    shape=np.shape(data)
+    if len(shape)==0:
+        f.write(&#34;%.6E\n&#34;%(data))
+    elif len(shape)==1:
+        for i in range(shape[0]):
+            if i==0:
+                f.write(&#34;%.6E&#34;%(data[i]))
+            else:
+                f.write(&#34;%s%.6E&#34;%(delimiter,data[i]))
+
+        f.write(&#34;\n&#34;)
+
+    elif len(shape)==2:
+        for i in range(shape[0]):
+            for j in range(shape[1]):
+                if j==0:
+                    f.write(&#34;%.6E&#34;%(data[i,j]))
+                else:
+                    f.write(&#34;%s%.6E&#34;%(delimiter,data[i,j]))
+            f.write(&#34;\n&#34;)                
+    f.close()</code></pre>
+</details>
+<div class="desc"><p>Function to write data in a file</p>
+<p>args:
+- file_path (string) : path for the data file, including the filename with its extension
+- data (scalar, list or array) : the data to be written in the file
+- delimiter (char) : the delimiter to separate the column of the data
+- overwrite (boolean) : if True overwrite the existing file if any, if False, append the data to the existing file if any
+- header (string) : header to be written before the data
+- date (boolean) : date to be written at the beginning of the file
+- comment (char) : char to be written before the header and date to indicate non-data lines</p></div>
+</dd>
+</dl>
+</section>
+<section>
+</section>
+</article>
+<nav id="sidebar">
+<div class="toc">
+<ul></ul>
+</div>
+<ul id="index">
+<li><h3>Super-module</h3>
+<ul>
+<li><code><a title="dopes.data_analysis" href="index.html">dopes.data_analysis</a></code></li>
+</ul>
+</li>
+<li><h3><a href="#header-functions">Functions</a></h3>
+<ul class="">
+<li><code><a title="dopes.data_analysis.file_handling.read_file" href="#dopes.data_analysis.file_handling.read_file">read_file</a></code></li>
+<li><code><a title="dopes.data_analysis.file_handling.write_in_file" href="#dopes.data_analysis.file_handling.write_in_file">write_in_file</a></code></li>
+</ul>
+</li>
+</ul>
+</nav>
+</main>
+<footer id="footer">
+<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
+</footer>
+</body>
+</html>
diff --git a/html/data_analysis/index.html b/html/data_analysis/index.html
new file mode 100644
index 0000000000000000000000000000000000000000..17a467d58d69af33d42c29274b9c51d946d044d0
--- /dev/null
+++ b/html/data_analysis/index.html
@@ -0,0 +1,113 @@
+<!doctype html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
+<meta name="generator" content="pdoc3 0.11.6">
+<title>dopes.data_analysis API documentation</title>
+<meta name="description" content="">
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/typography.min.css" integrity="sha512-Y1DYSb995BAfxobCkKepB1BqJJTPrOp3zPL74AWFugHHmmdcvO+C48WLrUOlhGMc0QG7AE3f7gmvvcrmX2fDoA==" crossorigin>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css" crossorigin>
+<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:1.5em;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:2em 0 .50em 0}h3{font-size:1.4em;margin:1.6em 0 .7em 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .2s ease-in-out}a:visited{color:#503}a:hover{color:#b62}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900;font-weight:bold}pre code{font-size:.8em;line-height:1.4em;padding:1em;display:block}code{background:#f3f3f3;font-family:"DejaVu Sans Mono",monospace;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source > summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible;min-width:max-content}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em 1em;margin:1em 0}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
+<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul ul{padding-left:1em}.toc > ul > li{margin-top:.5em}}</style>
+<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
+<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js" integrity="sha512-D9gUyxqja7hBtkWpPWGt9wfbfaMGVt9gnyCvYa+jojwwPHLCzUm5i8rpk7vD7wNee9bA35eYIjobYPaQuKS1MQ==" crossorigin></script>
+<script>window.addEventListener('DOMContentLoaded', () => {
+hljs.configure({languages: ['bash', 'css', 'diff', 'graphql', 'ini', 'javascript', 'json', 'plaintext', 'python', 'python-repl', 'rust', 'shell', 'sql', 'typescript', 'xml', 'yaml']});
+hljs.highlightAll();
+/* Collapse source docstrings */
+setTimeout(() => {
+[...document.querySelectorAll('.hljs.language-python > .hljs-string')]
+.filter(el => el.innerHTML.length > 200 && ['"""', "'''"].includes(el.innerHTML.substring(0, 3)))
+.forEach(el => {
+let d = document.createElement('details');
+d.classList.add('hljs-string');
+d.innerHTML = '<summary>"""</summary>' + el.innerHTML.substring(3);
+el.replaceWith(d);
+});
+}, 100);
+})</script>
+</head>
+<body>
+<main>
+<article id="content">
+<header>
+<h1 class="title">Namespace <code>dopes.data_analysis</code></h1>
+</header>
+<section id="section-intro">
+</section>
+<section>
+<h2 class="section-title" id="header-submodules">Sub-modules</h2>
+<dl>
+<dt><code class="name"><a title="dopes.data_analysis.data_processing" href="data_processing.html">dopes.data_analysis.data_processing</a></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt><code class="name"><a title="dopes.data_analysis.diode" href="diode.html">dopes.data_analysis.diode</a></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt><code class="name"><a title="dopes.data_analysis.file_handling" href="file_handling.html">dopes.data_analysis.file_handling</a></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt><code class="name"><a title="dopes.data_analysis.mechanics" href="mechanics.html">dopes.data_analysis.mechanics</a></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt><code class="name"><a title="dopes.data_analysis.polytec" href="polytec.html">dopes.data_analysis.polytec</a></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt><code class="name"><a title="dopes.data_analysis.raman" href="raman.html">dopes.data_analysis.raman</a></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt><code class="name"><a title="dopes.data_analysis.semiconductor" href="semiconductor.html">dopes.data_analysis.semiconductor</a></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt><code class="name"><a title="dopes.data_analysis.transistor" href="transistor.html">dopes.data_analysis.transistor</a></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+</dl>
+</section>
+<section>
+</section>
+<section>
+</section>
+<section>
+</section>
+</article>
+<nav id="sidebar">
+<div class="toc">
+<ul></ul>
+</div>
+<ul id="index">
+<li><h3>Super-module</h3>
+<ul>
+<li><code><a title="dopes" href="../index.html">dopes</a></code></li>
+</ul>
+</li>
+<li><h3><a href="#header-submodules">Sub-modules</a></h3>
+<ul>
+<li><code><a title="dopes.data_analysis.data_processing" href="data_processing.html">dopes.data_analysis.data_processing</a></code></li>
+<li><code><a title="dopes.data_analysis.diode" href="diode.html">dopes.data_analysis.diode</a></code></li>
+<li><code><a title="dopes.data_analysis.file_handling" href="file_handling.html">dopes.data_analysis.file_handling</a></code></li>
+<li><code><a title="dopes.data_analysis.mechanics" href="mechanics.html">dopes.data_analysis.mechanics</a></code></li>
+<li><code><a title="dopes.data_analysis.polytec" href="polytec.html">dopes.data_analysis.polytec</a></code></li>
+<li><code><a title="dopes.data_analysis.raman" href="raman.html">dopes.data_analysis.raman</a></code></li>
+<li><code><a title="dopes.data_analysis.semiconductor" href="semiconductor.html">dopes.data_analysis.semiconductor</a></code></li>
+<li><code><a title="dopes.data_analysis.transistor" href="transistor.html">dopes.data_analysis.transistor</a></code></li>
+</ul>
+</li>
+</ul>
+</nav>
+</main>
+<footer id="footer">
+<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
+</footer>
+</body>
+</html>
diff --git a/html/data_analysis/mechanics.html b/html/data_analysis/mechanics.html
new file mode 100644
index 0000000000000000000000000000000000000000..f7af10783eda34d4c15e5b750924cc4bb65db4fe
--- /dev/null
+++ b/html/data_analysis/mechanics.html
@@ -0,0 +1,608 @@
+<!doctype html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
+<meta name="generator" content="pdoc3 0.11.6">
+<title>dopes.data_analysis.mechanics API documentation</title>
+<meta name="description" content="">
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/typography.min.css" integrity="sha512-Y1DYSb995BAfxobCkKepB1BqJJTPrOp3zPL74AWFugHHmmdcvO+C48WLrUOlhGMc0QG7AE3f7gmvvcrmX2fDoA==" crossorigin>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css" crossorigin>
+<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:1.5em;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:2em 0 .50em 0}h3{font-size:1.4em;margin:1.6em 0 .7em 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .2s ease-in-out}a:visited{color:#503}a:hover{color:#b62}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900;font-weight:bold}pre code{font-size:.8em;line-height:1.4em;padding:1em;display:block}code{background:#f3f3f3;font-family:"DejaVu Sans Mono",monospace;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source > summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible;min-width:max-content}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em 1em;margin:1em 0}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
+<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul ul{padding-left:1em}.toc > ul > li{margin-top:.5em}}</style>
+<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
+<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js" integrity="sha512-D9gUyxqja7hBtkWpPWGt9wfbfaMGVt9gnyCvYa+jojwwPHLCzUm5i8rpk7vD7wNee9bA35eYIjobYPaQuKS1MQ==" crossorigin></script>
+<script>window.addEventListener('DOMContentLoaded', () => {
+hljs.configure({languages: ['bash', 'css', 'diff', 'graphql', 'ini', 'javascript', 'json', 'plaintext', 'python', 'python-repl', 'rust', 'shell', 'sql', 'typescript', 'xml', 'yaml']});
+hljs.highlightAll();
+/* Collapse source docstrings */
+setTimeout(() => {
+[...document.querySelectorAll('.hljs.language-python > .hljs-string')]
+.filter(el => el.innerHTML.length > 200 && ['"""', "'''"].includes(el.innerHTML.substring(0, 3)))
+.forEach(el => {
+let d = document.createElement('details');
+d.classList.add('hljs-string');
+d.innerHTML = '<summary>"""</summary>' + el.innerHTML.substring(3);
+el.replaceWith(d);
+});
+}, 100);
+})</script>
+</head>
+<body>
+<main>
+<article id="content">
+<header>
+<h1 class="title">Module <code>dopes.data_analysis.mechanics</code></h1>
+</header>
+<section id="section-intro">
+</section>
+<section>
+</section>
+<section>
+</section>
+<section>
+<h2 class="section-title" id="header-functions">Functions</h2>
+<dl>
+<dt id="dopes.data_analysis.mechanics.strain_from_stress"><code class="name flex">
+<span>def <span class="ident">strain_from_stress</span></span>(<span>stress_tensor, c11=165.77, c12=63.93, c44=79.62)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def strain_from_stress(stress_tensor,c11= 165.77,c12= 63.93,c44 = 79.62):
+    &#34;&#34;&#34; Function to calculate the strain in silicon from a stress tensor 
+    
+        args:
+            - stress_tensor (numpy array): the stress tensor for which the stress should be calculated. The voigt notation should be used with a 1 x 6 vector but the function can handle  3 x 3 matrix but only take the upper half in this case.
+            - c11, c12 and c44 (scalar): the coefficient of the compliance matrix in GPa
+            
+        return:
+            - strain_tensor (numpy array): the strain tensor calculated of dimension 1 x 6 using the voigt notation
+    &#34;&#34;&#34;  
+    
+    stress_voigt=np.zeros((6,1))
+    stress_shape=np.shape(stress_tensor)
+    
+    if len(stress_shape)==2:
+        if stress_shape[0]==3 and stress_shape[1]==3:
+            stress_voigt[0]=stress_tensor[0,0]
+            stress_voigt[1]=stress_tensor[1,1]
+            stress_voigt[2]=stress_tensor[2,2]
+            stress_voigt[3]=stress_tensor[1,2]
+            stress_voigt[4]=stress_tensor[0,2]
+            stress_voigt[5]=stress_tensor[0,1]
+        if stress_shape[0]==1 and stress_shape[1]==6:
+            stress_voigt=stress_tensor
+    else:
+        stress_voigt=np.transpose(np.array([stress_tensor]))
+    
+    compliance_tensor=np.array([[c11,c12,c12,0,0,0],
+                                [c12,c11,c12,0,0,0],
+                                [c12,c12,c11,0,0,0],
+                                [0,0,0,c44,0,0],
+                                [0,0,0,0,c44,0],
+                                [0,0,0,0,0,c44]])
+    
+    strain_tensor=np.linalg.inv(compliance_tensor) @ stress_tensor
+    return strain_tensor</code></pre>
+</details>
+<div class="desc"><p>Function to calculate the strain in silicon from a stress tensor </p>
+<p>args:
+- stress_tensor (numpy array): the stress tensor for which the stress should be calculated. The voigt notation should be used with a 1 x 6 vector but the function can handle
+3 x 3 matrix but only take the upper half in this case.
+- c11, c12 and c44 (scalar): the coefficient of the compliance matrix in GPa</p>
+<p>return:
+- strain_tensor (numpy array): the strain tensor calculated of dimension 1 x 6 using the voigt notation</p></div>
+</dd>
+<dt id="dopes.data_analysis.mechanics.straintensor"><code class="name flex">
+<span>def <span class="ident">straintensor</span></span>(<span>strain_type,<br>strain_direction,<br>N=11,<br>emin=-0.05,<br>emax=0.05,<br>c11=165.77,<br>c12=63.93,<br>c44=79.62,<br>poisson=True)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def straintensor(strain_type,strain_direction,N=11,emin=-0.05,emax=0.05,c11=165.77,c12=63.93,c44=79.62, poisson=True):
+    
+    &#34;&#34;&#34; Function to calculate the strain tensor for various strain type and direction
+    
+        args:
+            - strain_type (string): the type of strain. Choice between uniaxial (&#34;uni&#34;), biaxial (&#34;bi&#34;), shear (&#34;shear&#34;) and hydrostatic (&#34;hydro&#34;).
+            - strain_direction (string): the crystal direction and orientation of the strain. Choice between [001], [110] and [111]. For uniaxial strain, the principal strain is oriented along strain_direction while the principal stresses are perpendicular for biaxial strain.
+            - N (int): the number of strain tensor calculated linearly between emin and emax
+            - emin (scalar): the minimal value for the principal strain direction
+            - emax (scalar): the maximal value for the principal strain direction
+            - c11, c12 and c44 (scalar): the coefficient of the compliance matrix in GPa
+            - poisson (boolean): if True, take into account the poisson effect to calculate the strain tensor
+            
+        return:
+            - strain_tensor (numpy array): array of dimensions ( 3 x 3 x N ) with the strain tensors calculated
+    &#34;&#34;&#34;  
+    
+    strain_tensor=np.zeros((3,3,N))
+    
+    eps=np.linspace(emin,emax,N)
+    
+    # Initiation
+    uniepsilon001=np.zeros((3,3,N))
+    uniepsilon110=np.zeros((3,3,N))
+    uniepsilon111=np.zeros((3,3,N))
+    biepsilon001=np.zeros((3,3,N))
+    biepsilon110=np.zeros((3,3,N))
+    biepsilon111=np.zeros((3,3,N))
+    shear001=np.zeros((3,3,N))
+    shear110=np.zeros((3,3,N))
+    shear111=np.zeros((3,3,N))
+    hydro=np.zeros((3,3,N))    
+    # Matrix computation
+    # Uniaxial
+    if poisson:
+      uniepar001=-c12/(c11+c12)*eps
+    else:
+      uniepar001=0
+    
+    uniepsilon001[0][0]=uniepar001
+    uniepsilon001[0][1]=np.zeros(N)
+    uniepsilon001[0][2]=np.zeros(N)
+    uniepsilon001[1][0]=np.zeros(N)
+    uniepsilon001[1][1]=uniepar001
+    uniepsilon001[1][2]=np.zeros(N)
+    uniepsilon001[2][0]=np.zeros(N)
+    uniepsilon001[2][1]=np.zeros(N)
+    uniepsilon001[2][2]=eps
+
+    if poisson:    
+      uniepar110=- ( 4*c12*c44 ) / ( 2*c11*c44+(c11+2*c12)*(c11-c12) )*eps 
+    else:
+      uniepar110=0
+    
+    uniepsilon110[0][0]=0.5*(eps+uniepar110)
+    uniepsilon110[0][1]=0.5*(eps-uniepar110)
+    uniepsilon110[0][2]=np.zeros(N)
+    uniepsilon110[1][0]=0.5*(eps-uniepar110)
+    uniepsilon110[1][1]=0.5*(eps+uniepar110)
+    uniepsilon110[1][2]=np.zeros(N)
+    uniepsilon110[2][0]=np.zeros(N)
+    uniepsilon110[2][1]=np.zeros(N)
+    uniepsilon110[2][2]=uniepar110
+
+    if poisson:     
+      uniepar111 = - (c11 + 2*c12 - 2*c44) / (c11 + 2*c12 + 2*c44)*eps
+    else:
+      uniepar111 = 0
+      
+    uniepsilon111[0][0] = (eps + 2*uniepar111) / 3
+    uniepsilon111[0][1] = (eps - uniepar111) / 3
+    uniepsilon111[0][2] = (eps - uniepar111) / 3
+    uniepsilon111[1][0] = (eps - uniepar111) / 3
+    uniepsilon111[1][1] = (eps + 2*uniepar111) / 3
+    uniepsilon111[1][2] = (eps - uniepar111) / 3
+    uniepsilon111[2][0] = (eps - uniepar111) / 3
+    uniepsilon111[2][1] = (eps - uniepar111) / 3
+    uniepsilon111[2][2] = (eps + 2*uniepar111) / 3
+    
+    # Biaxial
+    if poisson:
+      bieper001 = -2 * c12 / c11 * eps        
+    else:
+      bieper001=0
+          
+    biepsilon001[0][0] = eps
+    biepsilon001[0][1] = np.zeros(N)
+    biepsilon001[0][2] = np.zeros(N)
+    biepsilon001[1][0] = np.zeros(N)
+    biepsilon001[1][1] = eps
+    biepsilon001[1][2] = np.zeros(N)
+    biepsilon001[2][0] = np.zeros(N)
+    biepsilon001[2][1] = np.zeros(N)
+    biepsilon001[2][2] = bieper001
+
+    if poisson:     
+      bieper110 = -(c11+3*c12-2*c44)/(c11+c12+2*c44)*eps
+    else:
+      bieper110 = 0
+    
+    biepsilon110[0][0] = 0.5*(bieper110+eps)
+    biepsilon110[0][1] = 0.5*(bieper110-eps)
+    biepsilon110[0][2] = np.zeros(N)
+    biepsilon110[1][2] = np.zeros(N)
+    biepsilon110[1][1] = 0.5*(bieper110+eps)
+    biepsilon110[1][0] = 0.5*(bieper110-eps)
+    biepsilon110[2][0] = np.zeros(N)
+    biepsilon110[2][1] = np.zeros(N)
+    biepsilon110[2][2] = eps
+    
+    if poisson:     
+      bieper111 = -2*(c11+2*c12-2*c44)/(c11+2*c12+4*c44)* eps
+    else:
+      bieper111=0
+    biepsilon111[0][0] = (bieper111+2*eps)/3 
+    biepsilon111[0][1] = (bieper111-eps)/3 
+    biepsilon111[0][2] = (bieper111-eps)/3 
+    biepsilon111[1][0] = (bieper111-eps)/3 
+    biepsilon111[1][1] = (bieper111+2*eps)/3 
+    biepsilon111[1][2] = (bieper111-eps)/3 
+    biepsilon111[2][0] = (bieper111-eps)/3 
+    biepsilon111[2][1] = (bieper111-eps)/3 
+    biepsilon111[2][2] = (bieper111+2*eps)/3
+
+    # Shear
+
+    shear001[0][2] = eps
+    shear001[2][0] = eps
+
+    shear110[0][2] = eps/np.sqrt(2)
+    shear110[2][0] = eps/np.sqrt(2)
+    shear110[1][2] = eps/np.sqrt(2)
+    shear110[2][2] = eps/np.sqrt(2)
+
+    shear111[0][1] = eps/np.sqrt(3)
+    shear111[0][2] = eps/np.sqrt(3)
+    shear111[1][0] = eps/np.sqrt(3)
+    shear111[1][2] = eps/np.sqrt(3)
+    shear111[2][0] = eps/np.sqrt(3)
+    shear111[2][1] = eps/np.sqrt(3)
+
+    # hydro
+
+    hydro[0][0] = eps/3
+    hydro[1][1] = eps/3
+    hydro[2][2] = eps/3
+    if (strain_type == &#34;uniaxial&#34;) or (strain_type == &#34;uni&#34;):
+        if strain_direction == &#34;001&#34;:
+            strain_tensor=uniepsilon001
+        elif strain_direction == &#34;110&#34;:
+            strain_tensor=uniepsilon110         
+        elif strain_direction == &#34;111&#34;:
+            strain_tensor=uniepsilon111      
+    elif (strain_type == &#34;biaxial&#34;) or (strain_type == &#34;bi&#34;):
+        if strain_direction == &#34;001&#34;:
+            strain_tensor=biepsilon001
+        elif strain_direction == &#34;110&#34;:
+            strain_tensor=biepsilon110         
+        elif strain_direction == &#34;111&#34;:
+            strain_tensor=biepsilon111
+    elif strain_type == &#34;shear&#34;:
+        if strain_direction == &#34;001&#34;:
+            strain_tensor=shear001
+        elif strain_direction == &#34;110&#34;:
+            strain_tensor=shear110         
+        elif strain_direction == &#34;111&#34;:
+            strain_tensor=shear111
+    elif (strain_type ==&#34;hydro&#34;) or (strain_type ==&#34;hydrostatic&#34;) :
+            strain_tensor = hydro
+      
+            
+    return strain_tensor</code></pre>
+</details>
+<div class="desc"><p>Function to calculate the strain tensor for various strain type and direction</p>
+<p>args:
+- strain_type (string): the type of strain. Choice between uniaxial ("uni"), biaxial ("bi"), shear ("shear") and hydrostatic ("hydro").
+- strain_direction (string): the crystal direction and orientation of the strain. Choice between [001], [110] and [111]. For uniaxial strain, the principal strain is oriented along strain_direction while the principal stresses are perpendicular for biaxial strain.
+- N (int): the number of strain tensor calculated linearly between emin and emax
+- emin (scalar): the minimal value for the principal strain direction
+- emax (scalar): the maximal value for the principal strain direction
+- c11, c12 and c44 (scalar): the coefficient of the compliance matrix in GPa
+- poisson (boolean): if True, take into account the poisson effect to calculate the strain tensor</p>
+<p>return:
+- strain_tensor (numpy array): array of dimensions ( 3 x 3 x N ) with the strain tensors calculated</p></div>
+</dd>
+<dt id="dopes.data_analysis.mechanics.straintensor_scalar"><code class="name flex">
+<span>def <span class="ident">straintensor_scalar</span></span>(<span>strain_type, strain_direction, eps=0, c11=16.577, c12=6.393, c44=7.962, poisson=True)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def straintensor_scalar(strain_type,strain_direction,eps=0,c11=16.577,c12=6.393,c44=7.962,poisson=True):
+    
+    &#34;&#34;&#34; Function to calculate the strain tensor for various strain type and direction
+    
+        args:
+            - strain_type (string): the type of strain. Choice between uniaxial (&#34;uni&#34;), biaxial (&#34;bi&#34;), shear (&#34;shear&#34;) and hydrostatic (&#34;hydro&#34;).
+            - strain_direction (string): the crystal direction and orientation of the strain. Choice between [001], [110] and [111]. For uniaxial strain, the principal strain is oriented along strain_direction while the principal stresses are perpendicular for biaxial strain.
+            - eps (scalar): the value of strain in the principal strain direction
+            - c11, c12 and c44 (scalar): the coefficient of the compliance matrix in GPa
+            - poisson (boolean): if True, take into account the poisson effect to calculate the strain tensor
+            
+        return:
+            - strain_tensor (numpy array): array of dimensions ( 3 x 3 ) with the strain tensor calculated
+    &#34;&#34;&#34;  
+    
+    strain_tensor=np.zeros((3,3))
+    
+    
+    # Initiation
+    uniepsilon001=np.zeros((3,3))
+    uniepsilon110=np.zeros((3,3))
+    uniepsilon111=np.zeros((3,3))
+    biepsilon001=np.zeros((3,3))
+    biepsilon110=np.zeros((3,3))
+    biepsilon111=np.zeros((3,3))
+    shear001=np.zeros((3,3))
+    shear110=np.zeros((3,3))
+    shear111=np.zeros((3,3))
+    hydro=np.zeros((3,3))    
+    # Matrix computation
+    # Uniaxial
+    if poisson:
+      uniepar001=-c12/(c11+c12)*eps
+    else:
+      uniepar001=0
+      
+    uniepsilon001[0][0]=uniepar001
+    uniepsilon001[0][1]=0
+    uniepsilon001[0][2]=0
+    uniepsilon001[1][0]=0
+    uniepsilon001[1][1]=uniepar001
+    uniepsilon001[1][2]=0
+    uniepsilon001[2][0]=0
+    uniepsilon001[2][1]=0
+    uniepsilon001[2][2]=eps
+
+    if poisson:
+      uniepar110=- ( 4*c12*c44 ) / ( 2*c11*c44+(c11+2*c12)*(c11-c12) )*eps 
+    else:
+      uniepar110=0
+          
+
+    uniepsilon110[0][0]=0.5*(eps+uniepar110)
+    uniepsilon110[0][1]=0.5*(eps-uniepar110)
+    uniepsilon110[0][2]=0
+    uniepsilon110[1][0]=0.5*(eps-uniepar110)
+    uniepsilon110[1][1]=0.5*(eps+uniepar110)
+    uniepsilon110[1][2]=0
+    uniepsilon110[2][0]=0
+    uniepsilon110[2][1]=0
+    uniepsilon110[2][2]=uniepar110
+    
+    if poisson:
+      uniepar111 = - (c11 + 2*c12 - 2*c44) / (c11 + 2*c12 + 2*c44)*eps 
+    else:
+      uniepar111=0    
+
+    uniepsilon111[0][0] = (eps + 2*uniepar111) / 3
+    uniepsilon111[0][1] = (eps - uniepar111) / 3
+    uniepsilon111[0][2] = (eps - uniepar111) / 3
+    uniepsilon111[1][0] = (eps - uniepar111) / 3
+    uniepsilon111[1][1] = (eps + 2*uniepar111) / 3
+    uniepsilon111[1][2] = (eps - uniepar111) / 3
+    uniepsilon111[2][0] = (eps - uniepar111) / 3
+    uniepsilon111[2][1] = (eps - uniepar111) / 3
+    uniepsilon111[2][2] = (eps + 2*uniepar111) / 3
+    
+    # Biaxial
+    if poisson:
+      bieper001 = -2 * c12 / c11 * eps
+    else:
+      bieper001=0      
+    
+    
+
+    biepsilon001[0][0] = eps
+    biepsilon001[0][1] = 0
+    biepsilon001[0][2] = 0
+    biepsilon001[1][0] = 0
+    biepsilon001[1][1] = eps
+    biepsilon001[1][2] = 0
+    biepsilon001[2][0] = 0
+    biepsilon001[2][1] = 0
+    biepsilon001[2][2] = bieper001
+    
+    if poisson:
+      bieper110 = -(c11+3*c12-2*c44)/(c11+c12+2*c44)*eps
+    else:
+      bieper110=0      
+        
+    
+    biepsilon110[0][0] = 0.5*(bieper110+eps)
+    biepsilon110[0][1] = 0.5*(bieper110-eps)
+    biepsilon110[0][2] = 0
+    biepsilon110[1][2] = 0
+    biepsilon110[1][1] = 0.5*(bieper110+eps)
+    biepsilon110[1][0] = 0.5*(bieper110-eps)
+    biepsilon110[2][0] = 0
+    biepsilon110[2][1] = 0
+    biepsilon110[2][2] = eps
+
+    if poisson:
+      bieper111 = -2*(c11+2*c12-2*c44)/(c11+2*c12+4*c44)* eps
+    else:
+      bieper111=0     
+          
+    
+    biepsilon111[0][0] = (bieper111+2*eps)/3 
+    biepsilon111[0][1] = (bieper111-eps)/3 
+    biepsilon111[0][2] = (bieper111-eps)/3 
+    biepsilon111[1][0] = (bieper111-eps)/3 
+    biepsilon111[1][1] = (bieper111+2*eps)/3 
+    biepsilon111[1][2] = (bieper111-eps)/3 
+    biepsilon111[2][0] = (bieper111-eps)/3 
+    biepsilon111[2][1] = (bieper111-eps)/3 
+    biepsilon111[2][2] = (bieper111+2*eps)/3
+
+    # Shear
+
+    shear001[0][2] = eps
+    shear001[2][0] = eps
+
+    shear110[0][2] = eps/np.sqrt(2)
+    shear110[2][0] = eps/np.sqrt(2)
+    shear110[1][2] = eps/np.sqrt(2)
+    shear110[2][2] = eps/np.sqrt(2)
+
+    shear111[0][1] = eps/np.sqrt(3)
+    shear111[0][2] = eps/np.sqrt(3)
+    shear111[1][0] = eps/np.sqrt(3)
+    shear111[1][2] = eps/np.sqrt(3)
+    shear111[2][0] = eps/np.sqrt(3)
+    shear111[2][1] = eps/np.sqrt(3)
+
+    # hydro
+
+    hydro[0][0] = eps/3
+    hydro[1][1] = eps/3
+    hydro[2][2] = eps/3
+    if (strain_type == &#34;uniaxial&#34;) or (strain_type == &#34;uni&#34;):
+        if strain_direction == &#34;001&#34;:
+            strain_tensor=uniepsilon001
+        elif strain_direction == &#34;110&#34;:
+            strain_tensor=uniepsilon110         
+        elif strain_direction == &#34;111&#34;:
+            strain_tensor=uniepsilon111      
+    elif (strain_type == &#34;biaxial&#34;) or (strain_type == &#34;bi&#34;):
+        if strain_direction == &#34;001&#34;:
+            strain_tensor=biepsilon001
+        elif strain_direction == &#34;110&#34;:
+            strain_tensor=biepsilon110         
+        elif strain_direction == &#34;111&#34;:
+            strain_tensor=biepsilon111
+    elif strain_type == &#34;shear&#34;:
+        if strain_direction == &#34;001&#34;:
+            strain_tensor=shear001
+        elif strain_direction == &#34;110&#34;:
+            strain_tensor=shear110         
+        elif strain_direction == &#34;111&#34;:
+            strain_tensor=shear111
+    elif (strain_type ==&#34;hydro&#34;) or (strain_type ==&#34;hydrostatic&#34;) :
+            strain_tensor = hydro
+      
+            
+    return strain_tensor</code></pre>
+</details>
+<div class="desc"><p>Function to calculate the strain tensor for various strain type and direction</p>
+<p>args:
+- strain_type (string): the type of strain. Choice between uniaxial ("uni"), biaxial ("bi"), shear ("shear") and hydrostatic ("hydro").
+- strain_direction (string): the crystal direction and orientation of the strain. Choice between [001], [110] and [111]. For uniaxial strain, the principal strain is oriented along strain_direction while the principal stresses are perpendicular for biaxial strain.
+- eps (scalar): the value of strain in the principal strain direction
+- c11, c12 and c44 (scalar): the coefficient of the compliance matrix in GPa
+- poisson (boolean): if True, take into account the poisson effect to calculate the strain tensor</p>
+<p>return:
+- strain_tensor (numpy array): array of dimensions ( 3 x 3 ) with the strain tensor calculated</p></div>
+</dd>
+<dt id="dopes.data_analysis.mechanics.stress_from_strain"><code class="name flex">
+<span>def <span class="ident">stress_from_strain</span></span>(<span>strain_tensor, c11=165.77, c12=63.93, c44=79.62)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def stress_from_strain(strain_tensor,c11= 165.77,c12= 63.93,c44 = 79.62):
+    &#34;&#34;&#34; Function to calculate the stress in silicon from a strain tensor 
+    
+        args:
+            - strain_tensor (numpy array): the strain tensor for which the stress should be calculated. The voigt notation should be used with a 1 x 6 vector but the function can handle  3 x 3 matrix but only take the upper half in this case.
+            - c11, c12 and c44 (scalar): the coefficient of the compliance matrix in GPa
+            
+        return:
+            - stress_tensor (numpy array): the stress tensor calculated of dimension 1 x 6 using the voigt notation
+    &#34;&#34;&#34;  
+    
+    strain_voigt=np.zeros((6,1))
+    strain_shape=np.shape(strain_tensor)
+    
+    if len(strain_shape)==2:
+        if strain_shape[0]==3 and strain_shape[1]==3:
+            strain_voigt[0]=strain_tensor[0,0]
+            strain_voigt[1]=strain_tensor[1,1]
+            strain_voigt[2]=strain_tensor[2,2]
+            strain_voigt[3]=strain_tensor[1,2]
+            strain_voigt[4]=strain_tensor[0,2]
+            strain_voigt[5]=strain_tensor[0,1]
+        if strain_shape[0]==1 and strain_shape[1]==6:
+            strain_voigt=strain_tensor
+    else:
+        strain_voigt=np.transpose(np.array([strain_tensor]))
+    
+    compliance_tensor=np.array([[c11,c12,c12,0,0,0],
+                                [c12,c11,c12,0,0,0],
+                                [c12,c12,c11,0,0,0],
+                                [0,0,0,c44,0,0],
+                                [0,0,0,0,c44,0],
+                                [0,0,0,0,0,c44]])
+    
+    stress_tensor=compliance_tensor @ strain_voigt
+    return stress_tensor</code></pre>
+</details>
+<div class="desc"><p>Function to calculate the stress in silicon from a strain tensor </p>
+<p>args:
+- strain_tensor (numpy array): the strain tensor for which the stress should be calculated. The voigt notation should be used with a 1 x 6 vector but the function can handle
+3 x 3 matrix but only take the upper half in this case.
+- c11, c12 and c44 (scalar): the coefficient of the compliance matrix in GPa</p>
+<p>return:
+- stress_tensor (numpy array): the stress tensor calculated of dimension 1 x 6 using the voigt notation</p></div>
+</dd>
+<dt id="dopes.data_analysis.mechanics.voigt_to_matrix"><code class="name flex">
+<span>def <span class="ident">voigt_to_matrix</span></span>(<span>voigt_vector)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def voigt_to_matrix(voigt_vector):
+    &#34;&#34;&#34; Function to convert a vector in Voigt notation to a matrix 
+    
+        args:
+            - voigt_vector (numpy array): 1D vector with 6 elements
+            
+        return:
+            - matrix (numpy array): 2D matrix with 3 x 3 elements
+    &#34;&#34;&#34;  
+    matrix=np.zeros((3,3))
+    
+    matrix[0,0]=voigt_vector[0]
+    matrix[1,1]=voigt_vector[1]
+    matrix[2,2]=voigt_vector[2]
+    matrix[1,2]=voigt_vector[3]
+    matrix[2,1]=voigt_vector[3]
+    matrix[0,2]=voigt_vector[4]
+    matrix[2,0]=voigt_vector[4]
+    matrix[0,1]=voigt_vector[5]
+    matrix[1,0]=voigt_vector[5]
+    
+    return matrix</code></pre>
+</details>
+<div class="desc"><p>Function to convert a vector in Voigt notation to a matrix </p>
+<p>args:
+- voigt_vector (numpy array): 1D vector with 6 elements</p>
+<p>return:
+- matrix (numpy array): 2D matrix with 3 x 3 elements</p></div>
+</dd>
+</dl>
+</section>
+<section>
+</section>
+</article>
+<nav id="sidebar">
+<div class="toc">
+<ul></ul>
+</div>
+<ul id="index">
+<li><h3>Super-module</h3>
+<ul>
+<li><code><a title="dopes.data_analysis" href="index.html">dopes.data_analysis</a></code></li>
+</ul>
+</li>
+<li><h3><a href="#header-functions">Functions</a></h3>
+<ul class="">
+<li><code><a title="dopes.data_analysis.mechanics.strain_from_stress" href="#dopes.data_analysis.mechanics.strain_from_stress">strain_from_stress</a></code></li>
+<li><code><a title="dopes.data_analysis.mechanics.straintensor" href="#dopes.data_analysis.mechanics.straintensor">straintensor</a></code></li>
+<li><code><a title="dopes.data_analysis.mechanics.straintensor_scalar" href="#dopes.data_analysis.mechanics.straintensor_scalar">straintensor_scalar</a></code></li>
+<li><code><a title="dopes.data_analysis.mechanics.stress_from_strain" href="#dopes.data_analysis.mechanics.stress_from_strain">stress_from_strain</a></code></li>
+<li><code><a title="dopes.data_analysis.mechanics.voigt_to_matrix" href="#dopes.data_analysis.mechanics.voigt_to_matrix">voigt_to_matrix</a></code></li>
+</ul>
+</li>
+</ul>
+</nav>
+</main>
+<footer id="footer">
+<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
+</footer>
+</body>
+</html>
diff --git a/html/data_analysis/polytec.html b/html/data_analysis/polytec.html
new file mode 100644
index 0000000000000000000000000000000000000000..d1d7f2be346d374e90348f50e26dbd627b5b6112
--- /dev/null
+++ b/html/data_analysis/polytec.html
@@ -0,0 +1,431 @@
+<!doctype html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
+<meta name="generator" content="pdoc3 0.11.6">
+<title>dopes.data_analysis.polytec API documentation</title>
+<meta name="description" content="">
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/typography.min.css" integrity="sha512-Y1DYSb995BAfxobCkKepB1BqJJTPrOp3zPL74AWFugHHmmdcvO+C48WLrUOlhGMc0QG7AE3f7gmvvcrmX2fDoA==" crossorigin>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css" crossorigin>
+<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:1.5em;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:2em 0 .50em 0}h3{font-size:1.4em;margin:1.6em 0 .7em 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .2s ease-in-out}a:visited{color:#503}a:hover{color:#b62}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900;font-weight:bold}pre code{font-size:.8em;line-height:1.4em;padding:1em;display:block}code{background:#f3f3f3;font-family:"DejaVu Sans Mono",monospace;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source > summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible;min-width:max-content}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em 1em;margin:1em 0}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
+<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul ul{padding-left:1em}.toc > ul > li{margin-top:.5em}}</style>
+<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
+<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js" integrity="sha512-D9gUyxqja7hBtkWpPWGt9wfbfaMGVt9gnyCvYa+jojwwPHLCzUm5i8rpk7vD7wNee9bA35eYIjobYPaQuKS1MQ==" crossorigin></script>
+<script>window.addEventListener('DOMContentLoaded', () => {
+hljs.configure({languages: ['bash', 'css', 'diff', 'graphql', 'ini', 'javascript', 'json', 'plaintext', 'python', 'python-repl', 'rust', 'shell', 'sql', 'typescript', 'xml', 'yaml']});
+hljs.highlightAll();
+/* Collapse source docstrings */
+setTimeout(() => {
+[...document.querySelectorAll('.hljs.language-python > .hljs-string')]
+.filter(el => el.innerHTML.length > 200 && ['"""', "'''"].includes(el.innerHTML.substring(0, 3)))
+.forEach(el => {
+let d = document.createElement('details');
+d.classList.add('hljs-string');
+d.innerHTML = '<summary>"""</summary>' + el.innerHTML.substring(3);
+el.replaceWith(d);
+});
+}, 100);
+})</script>
+</head>
+<body>
+<main>
+<article id="content">
+<header>
+<h1 class="title">Module <code>dopes.data_analysis.polytec</code></h1>
+</header>
+<section id="section-intro">
+</section>
+<section>
+</section>
+<section>
+</section>
+<section>
+<h2 class="section-title" id="header-functions">Functions</h2>
+<dl>
+<dt id="dopes.data_analysis.polytec.find_max"><code class="name flex">
+<span>def <span class="ident">find_max</span></span>(<span>x, y, z, kind='maximum', height=None, width=None)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def find_max(x,y,z,kind=&#34;maximum&#34;,height=None,width=None):
+    &#34;&#34;&#34; Function to find maximal values
+    
+        args:
+            - x, y (array) : 1D array for the x and y position of the pixel 
+            - z (array) : 1D array with the values at position (x,y) and with the same dimension as x and y
+            - kind (string) : the method to determine the maximum. &#34;maximum&#34; only takes the max value of the z array while &#34;peaks&#34; is looking for the maximal peak. This last method is more robust with regards to outlier. The minimum height and width can be specified.
+            - height (None, scalar or 2-element sequence) : required height of peaks. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required height.
+            - width (None, scalar or 2-element sequence) : required width of peaks in samples. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required width.
+        
+        return:
+            - x_max,y_max,z_max : three elements with the x, y position of the maximum value of the z array
+    &#34;&#34;&#34;
+    if kind==&#34;maximum&#34;:
+        index=np.nanargmax(z)
+        x_max=x[index]
+        y_max=y[index]
+        z_max=z[index]
+        
+    elif kind == &#34;peaks&#34;:
+        n_interp=int(np.sqrt(len(z)))
+        X,Y,Z=medfilt_2D(x,y,z,n_interp)
+
+
+        if height is None:
+            height = np.nanmax(Z[:,int(n_interp/2)])*0.1
+        if width is None:
+            width = n_interp/np.nanmax(x)*0.1
+        
+        param_peaks=find_peaks(Z[:,int(n_interp/2)],height=height,width=width)
+        peak_x=param_peaks[0][np.nanargmax(param_peaks[1][&#34;peak_heights&#34;])]
+
+        param_peaks=find_peaks(Z[peak_x],height=height,width=width)
+        peak_y=param_peaks[0][np.nanargmax(param_peaks[1][&#34;peak_heights&#34;])]
+        peak_height=np.nanmax(param_peaks[1][&#34;peak_heights&#34;])
+        
+        x_max=X[peak_x,peak_y]
+        y_max=Y[peak_x,peak_y]
+        z_max=peak_height     
+
+    
+    return x_max,y_max,z_max</code></pre>
+</details>
+<div class="desc"><p>Function to find maximal values</p>
+<p>args:
+- x, y (array) : 1D array for the x and y position of the pixel
+- z (array) : 1D array with the values at position (x,y) and with the same dimension as x and y
+- kind (string) : the method to determine the maximum. "maximum" only takes the max value of the z array while "peaks" is looking for the maximal peak. This last method is more robust with regards to outlier. The minimum height and width can be specified.
+- height (None, scalar or 2-element sequence) : required height of peaks. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required height.
+- width (None, scalar or 2-element sequence) : required width of peaks in samples. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required width.</p>
+<p>return:
+- x_max,y_max,z_max : three elements with the x, y position of the maximum value of the z array</p></div>
+</dd>
+<dt id="dopes.data_analysis.polytec.medfilt_2D"><code class="name flex">
+<span>def <span class="ident">medfilt_2D</span></span>(<span>x, y, z, kernel_size=9, n_interp=None)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def medfilt_2D(x,y,z,kernel_size=9,n_interp=None):
+    &#34;&#34;&#34; Function to convert unstructured 1D data (three vectors) in 2D grid for which the z values have been filtered with a 2D median filter to remove the outliers
+    
+        args:
+            - x, y (array) : 1D array for the x and y position of the pixel 
+            - z (array) : 1D array with with the values at position (x,y), and with the same dimension as x and y
+            - kernel_size (int) : size of the median filter window.    
+            - n_interp (int) : the number of points for the dimensions of the interpolation along x and y. if None, n_interp is set as the square root of the dimension of the z array
+                
+        return:
+            - X,Y,Z : three meshgrids of the same dimension (n_interp x n_interp) with the x,y coordinates and the z values filtered. The X and Y grid are linearly spaced from the minimal and maximal valeus of x and y, respectively.
+            
+    &#34;&#34;&#34;
+
+    X, Y, Z_interp = unstructured_to_regular(x,y,z,n_interp)
+    Z_med = medfilt2d(Z_interp,kernel_size)
+    
+    return X,Y,Z_med</code></pre>
+</details>
+<div class="desc"><p>Function to convert unstructured 1D data (three vectors) in 2D grid for which the z values have been filtered with a 2D median filter to remove the outliers</p>
+<p>args:
+- x, y (array) : 1D array for the x and y position of the pixel
+- z (array) : 1D array with with the values at position (x,y), and with the same dimension as x and y
+- kernel_size (int) : size of the median filter window.
+<br>
+- n_interp (int) : the number of points for the dimensions of the interpolation along x and y. if None, n_interp is set as the square root of the dimension of the z array</p>
+<p>return:
+- X,Y,Z : three meshgrids of the same dimension (n_interp x n_interp) with the x,y coordinates and the z values filtered. The X and Y grid are linearly spaced from the minimal and maximal valeus of x and y, respectively.</p></div>
+</dd>
+<dt id="dopes.data_analysis.polytec.plot_1D_line_from_file"><code class="name flex">
+<span>def <span class="ident">plot_1D_line_from_file</span></span>(<span>file_path,<br>unit_mult=(1, 1),<br>use_lines=None,<br>ax=None,<br>color_list=None,<br>ls_list=None,<br>marker_list=None,<br>**plot_kwargs)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def plot_1D_line_from_file(file_path,unit_mult=(1,1),use_lines=None,ax=None,color_list=None,ls_list=None,marker_list=None,**plot_kwargs):
+    &#34;&#34;&#34; Function to plot a line data from a file
+    
+        args:
+            - file_path (string) : the file to read
+            - unit_mult (array) : array of three scalar to multiply the data of the x, y and z vector.
+            - use_lines (array) : list of lines to be plotted. Be careful that the number of column in the file is usually twice the number of lines (as each line has an x and z vector).
+            - ax (list of two Axes) : the axes of the subplot in which plotting the map and the color bar next to it
+            - color_list, ls_list, marker_list (array) : list of color, linestyle and marker to be used for the data lines found in the files. If the length of the list is smaller than the number of data lines, the last component is kept for the last data lines. 
+            - plot_kwargs : this method also takes any keyword argument for the Axes.plot() function
+        return:
+            -fig, ax, data : the figure with its axe and the data array read from the file. If ax is provided, only data is returned
+    &#34;&#34;&#34;    
+    if use_lines is not None:
+        index=np.transpose(np.array([use_lines])) @ (2 * np.ones((1,2*len(use_lines))))+ np.array([[0,1]*len(use_lines)])
+        use_col=[int(i) for i in index[0]]
+    else:
+        use_col=None
+        
+    data=np.genfromtxt(file_path,skip_header=2,delimiter=&#34;\t&#34;,usecols=use_col)
+    n_lines=int(len(data[0])/2)
+    
+    if ax is None:
+        fig,ax=plt.subplots(dpi=200)
+        
+        ax.set_xlabel(&#34;d (mm)&#34;)
+        ax.set_ylabel(&#34;z (mm)&#34;)
+    if use_lines is None:
+        lines_to_plot=range(n_lines)
+    else:
+        lines_to_plot=range(len(use_lines))
+
+
+    for i in lines_to_plot:
+        d_lines=data[:,2*i]*unit_mult[0]
+        z_lines=proc.moving_median(data[:,2*i+1],9)*unit_mult[1]
+        if color_list is not None:
+            plot_kwargs[&#34;color&#34;]=color_list[np.min((i,len(color_list)-1))]
+        if ls_list is not None:
+            plot_kwargs[&#34;ls&#34;]=ls_list[np.min((i,len(ls_list)-1))]     
+            plot_kwargs.pop(&#34;linestyle&#34;,None)    
+            
+        if marker_list is not None:
+            plot_kwargs[&#34;marker&#34;]=marker_list[np.min((i,len(marker_list)-1))] 
+
+        
+        ax.plot(d_lines,z_lines,**plot_kwargs)
+
+    if ax is None:        
+        return fig,ax, data
+    else:
+        return data</code></pre>
+</details>
+<div class="desc"><p>Function to plot a line data from a file</p>
+<p>args:
+- file_path (string) : the file to read
+- unit_mult (array) : array of three scalar to multiply the data of the x, y and z vector.
+- use_lines (array) : list of lines to be plotted. Be careful that the number of column in the file is usually twice the number of lines (as each line has an x and z vector).
+- ax (list of two Axes) : the axes of the subplot in which plotting the map and the color bar next to it
+- color_list, ls_list, marker_list (array) : list of color, linestyle and marker to be used for the data lines found in the files. If the length of the list is smaller than the number of data lines, the last component is kept for the last data lines.
+- plot_kwargs : this method also takes any keyword argument for the Axes.plot() function
+return:
+-fig, ax, data : the figure with its axe and the data array read from the file. If ax is provided, only data is returned</p></div>
+</dd>
+<dt id="dopes.data_analysis.polytec.plot_map"><code class="name flex">
+<span>def <span class="ident">plot_map</span></span>(<span>x,<br>y,<br>z,<br>ax=None,<br>vmin=None,<br>vmax=None,<br>cmap='coolwarm',<br>medfilt=True,<br>kernel_size=9,<br>n_interp=None,<br>**contour_kwargs)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def plot_map(x,y,z,ax=None,vmin=None,vmax=None,cmap=&#34;coolwarm&#34;,medfilt=True,kernel_size=9,n_interp=None, **contour_kwargs):
+    &#34;&#34;&#34; Function to plot a 2D map from unstructured 1D data (three vectors)
+    
+        args:
+            - x, y (array) : 1D array for the x and y position of the pixel 
+            - z (array) : 1D array with with the values at position (x,y), and with the same dimension as x and y
+            - ax (list of two Axes) : the axes of the subplot in which plotting the map and the color bar next to it
+            - vmin, vmax (scalar) : define the data range that the colormap covers. By default, the colormap covers the complete value range of the supplied data. If vmin or vmax are not given, the default color scaling is based on levels.
+            - cmap (str or Colormap) : the Colormap instance or registered colormap name used to map scalar data to colors.
+            - medfilt (boolean) : if True apply a median filter on the data by interpolating it on a n_interp x n_interp grid
+            - kernel_size (int) : size of the median filter window.    
+            - n_interp (int) : the number of points for the dimensions of the interpolation along x and y. if None, n_interp is set as the square root of the dimension of the z array
+            - contour_kwargs : this method also takes any keyword argument for the Axes.contourf() and axes.tricontourf()
+        return:
+            -fig, ax_map, ax_bar : the figure with the 2D map axe (ax_map) and the axe with the color bar (ax_bar)
+            
+    &#34;&#34;&#34;
+    if vmin==None:
+        vmin=0
+
+    if ax==None:
+        fig,ax=plt.subplots(1,2,gridspec_kw={&#34;wspace&#34;:0.1,&#34;width_ratios&#34;:[5,0.2]})
+    ax[0].set_xlabel(&#34;x (mm)&#34;)
+    ax[0].set_ylabel(&#34;y (mm)&#34;)
+  
+    if medfilt:
+        X,Y,Z=medfilt_2D(x,y,z,kernel_size,n_interp)
+        if vmax==None:
+            vmax=np.ceil(np.nanmax(Z)*1e3)/1e3
+        ax[0].contourf(X, Y, Z, vmin=vmin, vmax=vmax,cmap=cmap,**contour_kwargs)
+
+    else:
+        if vmax==None:
+            vmax=np.ceil(np.nanmax(z)*1e3)/1e3
+
+        ax[0].tricontourf(x, y, z, vmin=vmin, vmax=vmax,cmap=cmap, **contour_kwargs)
+        
+    fig.colorbar(mpl.cm.ScalarMappable(norm = mpl.colors.Normalize(vmin=vmin, vmax=vmax), cmap=cmap), 
+                     orientation=&#39;vertical&#39;, label=&#34;Deflection (µm)&#34;,cax=ax[1])
+
+    ax_map=ax[0]
+    ax_bar=ax[1]
+    
+    return fig, ax_map, ax_bar</code></pre>
+</details>
+<div class="desc"><p>Function to plot a 2D map from unstructured 1D data (three vectors)</p>
+<p>args:
+- x, y (array) : 1D array for the x and y position of the pixel
+- z (array) : 1D array with with the values at position (x,y), and with the same dimension as x and y
+- ax (list of two Axes) : the axes of the subplot in which plotting the map and the color bar next to it
+- vmin, vmax (scalar) : define the data range that the colormap covers. By default, the colormap covers the complete value range of the supplied data. If vmin or vmax are not given, the default color scaling is based on levels.
+- cmap (str or Colormap) : the Colormap instance or registered colormap name used to map scalar data to colors.
+- medfilt (boolean) : if True apply a median filter on the data by interpolating it on a n_interp x n_interp grid
+- kernel_size (int) : size of the median filter window.
+<br>
+- n_interp (int) : the number of points for the dimensions of the interpolation along x and y. if None, n_interp is set as the square root of the dimension of the z array
+- contour_kwargs : this method also takes any keyword argument for the Axes.contourf() and axes.tricontourf()
+return:
+-fig, ax_map, ax_bar : the figure with the 2D map axe (ax_map) and the axe with the color bar (ax_bar)</p></div>
+</dd>
+<dt id="dopes.data_analysis.polytec.plot_map_from_file"><code class="name flex">
+<span>def <span class="ident">plot_map_from_file</span></span>(<span>file_path,<br>n_step=1,<br>unit_mult=(1, 1, 1),<br>ax=None,<br>vmin=None,<br>vmax=None,<br>cmap='coolwarm',<br>medfilt=True,<br>kernel_size=9,<br>n_interp=None,<br>**contour_kwargs)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def plot_map_from_file(file_path,n_step=1,unit_mult=(1,1,1),ax=None,vmin=None,vmax=None,cmap=&#34;coolwarm&#34;,medfilt=True,kernel_size=9,n_interp=None, **contour_kwargs):
+    &#34;&#34;&#34; Function to plot a 2D map from a file of unstructured 1D data (three vectors x,y and z)
+    
+        args:
+            - file_path (string) : the file to read
+            - n_step (int) : reduce the number of point to be plotted by taking one point each n_point index of the x, y ,z vectors
+            - unit_mult (array) : array of three scalar to multiply the data of the x, y and z vector.
+            - ax (list of two Axes) : the axes of the subplot in which plotting the map and the color bar next to it
+            - vmin, vmax (scalar) : define the data range that the colormap covers. By default, the colormap covers the complete value range of the supplied data. If vmin or vmax are not given, the default color scaling is based on levels.
+            - cmap (string or Colormap) : the Colormap instance or registered colormap name used to map scalar data to colors.
+            - medfilt (boolean) : if True apply a median filter on the data by interpolating it on a n_interp x n_interp grid
+            - kernel_size (int) : size of the median filter window.    
+            - n_interp (int) : the number of points for the dimensions of the interpolation along x and y. if None, n_interp is set as the square root of the dimension of the z array
+            - contour_kwargs : this method also takes any keyword argument for the Axes.contourf() and axes.tricontourf()
+        return:
+            -fig, ax_map, ax_bar : the figure with the 2D map axe (ax_map) and the axe with the color bar (ax_bar)
+    &#34;&#34;&#34;    
+    n_step=10
+    data=np.genfromtxt(file_path)
+    x=data[::n_step,0] * unit_mult[0]
+    y=data[::n_step,1] * unit_mult[1]
+    z=data[::n_step,2] * unit_mult[2]
+
+
+    if vmin==None:
+        vmin=0
+
+    if ax==None:
+        fig,ax=plt.subplots(1,2,gridspec_kw={&#34;wspace&#34;:0.1,&#34;width_ratios&#34;:[5,0.2]})
+        ax[0].set_xlabel(&#34;x (mm)&#34;)
+        ax[0].set_ylabel(&#34;y (mm)&#34;)
+      
+    if medfilt:
+        X,Y,Z=medfilt_2D(x,y,z,kernel_size,n_interp)
+        if vmax==None:
+            vmax=np.ceil(np.nanmax(Z)*1e3)/1e3
+        ax[0].contourf(X, Y, Z, vmin=vmin, vmax=vmax,cmap=cmap,**contour_kwargs)
+
+    else:
+        if vmax==None:
+            vmax=np.ceil(np.nanmax(z)*1e3)/1e3
+
+        ax[0].tricontourf(x, y, z, vmin=vmin, vmax=vmax,cmap=cmap, **contour_kwargs)
+        
+    fig.colorbar(mpl.cm.ScalarMappable(norm = mpl.colors.Normalize(vmin=vmin, vmax=vmax), cmap=cmap), 
+                     orientation=&#39;vertical&#39;, label=&#34;Deflection (µm)&#34;,cax=ax[1])
+
+    ax_map=ax[0]
+    ax_bar=ax[1]
+    
+    return fig, ax_map, ax_bar</code></pre>
+</details>
+<div class="desc"><p>Function to plot a 2D map from a file of unstructured 1D data (three vectors x,y and z)</p>
+<p>args:
+- file_path (string) : the file to read
+- n_step (int) : reduce the number of point to be plotted by taking one point each n_point index of the x, y ,z vectors
+- unit_mult (array) : array of three scalar to multiply the data of the x, y and z vector.
+- ax (list of two Axes) : the axes of the subplot in which plotting the map and the color bar next to it
+- vmin, vmax (scalar) : define the data range that the colormap covers. By default, the colormap covers the complete value range of the supplied data. If vmin or vmax are not given, the default color scaling is based on levels.
+- cmap (string or Colormap) : the Colormap instance or registered colormap name used to map scalar data to colors.
+- medfilt (boolean) : if True apply a median filter on the data by interpolating it on a n_interp x n_interp grid
+- kernel_size (int) : size of the median filter window.
+<br>
+- n_interp (int) : the number of points for the dimensions of the interpolation along x and y. if None, n_interp is set as the square root of the dimension of the z array
+- contour_kwargs : this method also takes any keyword argument for the Axes.contourf() and axes.tricontourf()
+return:
+-fig, ax_map, ax_bar : the figure with the 2D map axe (ax_map) and the axe with the color bar (ax_bar)</p></div>
+</dd>
+<dt id="dopes.data_analysis.polytec.unstructured_to_regular"><code class="name flex">
+<span>def <span class="ident">unstructured_to_regular</span></span>(<span>x, y, z, n_interp=None)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def unstructured_to_regular(x,y,z,n_interp=None):
+    &#34;&#34;&#34; Function to convert unstructured 1D data (three vectors) in 2D grid
+    
+        args:
+            - x, y (array) : 1D array for the x and y position of the pixel 
+            - z (array) : 1D array with with the values at position (x,y), and with the same dimension as x and y
+            - n_interp (int) : the number of points for the dimensions of the interpolation along x and y. if None, n_interp is set as the square root of the dimension of the z array
+                
+        return:
+            - X,Y,Z : three meshgrids of the same dimension (n_interp x n_interp) with the x,y coordinates and the z values interpolated. The X and Y grid are linearly spaced from the minimal and maximal valeus of x and y, respectively.
+            
+    &#34;&#34;&#34;
+    if n_interp==None:
+        n_interp=int(np.sqrt(len(z)))
+        
+    x_interp = np.linspace(min(x), max(x),n_interp)
+    y_interp = np.linspace(min(y), max(y),n_interp)
+    X, Y = np.meshgrid(x_interp, y_interp)  # 2D grid for interpolation
+    Z=griddata(list(zip(x, y)), z, (X, Y), method=&#39;linear&#39;)
+
+    return X,Y,Z</code></pre>
+</details>
+<div class="desc"><p>Function to convert unstructured 1D data (three vectors) in 2D grid</p>
+<p>args:
+- x, y (array) : 1D array for the x and y position of the pixel
+- z (array) : 1D array with with the values at position (x,y), and with the same dimension as x and y
+- n_interp (int) : the number of points for the dimensions of the interpolation along x and y. if None, n_interp is set as the square root of the dimension of the z array</p>
+<p>return:
+- X,Y,Z : three meshgrids of the same dimension (n_interp x n_interp) with the x,y coordinates and the z values interpolated. The X and Y grid are linearly spaced from the minimal and maximal valeus of x and y, respectively.</p></div>
+</dd>
+</dl>
+</section>
+<section>
+</section>
+</article>
+<nav id="sidebar">
+<div class="toc">
+<ul></ul>
+</div>
+<ul id="index">
+<li><h3>Super-module</h3>
+<ul>
+<li><code><a title="dopes.data_analysis" href="index.html">dopes.data_analysis</a></code></li>
+</ul>
+</li>
+<li><h3><a href="#header-functions">Functions</a></h3>
+<ul class="">
+<li><code><a title="dopes.data_analysis.polytec.find_max" href="#dopes.data_analysis.polytec.find_max">find_max</a></code></li>
+<li><code><a title="dopes.data_analysis.polytec.medfilt_2D" href="#dopes.data_analysis.polytec.medfilt_2D">medfilt_2D</a></code></li>
+<li><code><a title="dopes.data_analysis.polytec.plot_1D_line_from_file" href="#dopes.data_analysis.polytec.plot_1D_line_from_file">plot_1D_line_from_file</a></code></li>
+<li><code><a title="dopes.data_analysis.polytec.plot_map" href="#dopes.data_analysis.polytec.plot_map">plot_map</a></code></li>
+<li><code><a title="dopes.data_analysis.polytec.plot_map_from_file" href="#dopes.data_analysis.polytec.plot_map_from_file">plot_map_from_file</a></code></li>
+<li><code><a title="dopes.data_analysis.polytec.unstructured_to_regular" href="#dopes.data_analysis.polytec.unstructured_to_regular">unstructured_to_regular</a></code></li>
+</ul>
+</li>
+</ul>
+</nav>
+</main>
+<footer id="footer">
+<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
+</footer>
+</body>
+</html>
diff --git a/html/data_analysis/raman.html b/html/data_analysis/raman.html
new file mode 100644
index 0000000000000000000000000000000000000000..8474e8f5ba3008ea07be6e38003ef9b3ca22b1cd
--- /dev/null
+++ b/html/data_analysis/raman.html
@@ -0,0 +1,407 @@
+<!doctype html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
+<meta name="generator" content="pdoc3 0.11.6">
+<title>dopes.data_analysis.raman API documentation</title>
+<meta name="description" content="">
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/typography.min.css" integrity="sha512-Y1DYSb995BAfxobCkKepB1BqJJTPrOp3zPL74AWFugHHmmdcvO+C48WLrUOlhGMc0QG7AE3f7gmvvcrmX2fDoA==" crossorigin>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css" crossorigin>
+<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:1.5em;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:2em 0 .50em 0}h3{font-size:1.4em;margin:1.6em 0 .7em 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .2s ease-in-out}a:visited{color:#503}a:hover{color:#b62}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900;font-weight:bold}pre code{font-size:.8em;line-height:1.4em;padding:1em;display:block}code{background:#f3f3f3;font-family:"DejaVu Sans Mono",monospace;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source > summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible;min-width:max-content}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em 1em;margin:1em 0}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
+<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul ul{padding-left:1em}.toc > ul > li{margin-top:.5em}}</style>
+<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
+<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js" integrity="sha512-D9gUyxqja7hBtkWpPWGt9wfbfaMGVt9gnyCvYa+jojwwPHLCzUm5i8rpk7vD7wNee9bA35eYIjobYPaQuKS1MQ==" crossorigin></script>
+<script>window.addEventListener('DOMContentLoaded', () => {
+hljs.configure({languages: ['bash', 'css', 'diff', 'graphql', 'ini', 'javascript', 'json', 'plaintext', 'python', 'python-repl', 'rust', 'shell', 'sql', 'typescript', 'xml', 'yaml']});
+hljs.highlightAll();
+/* Collapse source docstrings */
+setTimeout(() => {
+[...document.querySelectorAll('.hljs.language-python > .hljs-string')]
+.filter(el => el.innerHTML.length > 200 && ['"""', "'''"].includes(el.innerHTML.substring(0, 3)))
+.forEach(el => {
+let d = document.createElement('details');
+d.classList.add('hljs-string');
+d.innerHTML = '<summary>"""</summary>' + el.innerHTML.substring(3);
+el.replaceWith(d);
+});
+}, 100);
+})</script>
+</head>
+<body>
+<main>
+<article id="content">
+<header>
+<h1 class="title">Module <code>dopes.data_analysis.raman</code></h1>
+</header>
+<section id="section-intro">
+</section>
+<section>
+</section>
+<section>
+</section>
+<section>
+<h2 class="section-title" id="header-functions">Functions</h2>
+<dl>
+<dt id="dopes.data_analysis.raman.find_peaks"><code class="name flex">
+<span>def <span class="ident">find_peaks</span></span>(<span>x, y, height=None, threshold=None, distance=None, width=None)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def find_peaks(x,y,height=None, threshold=None, distance=None, width=None):
+    &#34;&#34;&#34; Function to find peaks in the Raman spectrum. Be careful that the method is not a fit put a peak detection.
+    
+        args:
+            - x (array) : an array 
+            - y (array) : the signal with peaks with the same dimension as x
+            - height (None, scalar or 2-element sequence) : required height of peaks. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required height.
+            - threshold (None, scalar or 2-element sequence) : required threshold of peaks, the vertical distance to its neighboring samples. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required threshold.
+            - distance (scalar) : Required minimal horizontal distance in samples between neighbouring peaks. The distance should be higher than the step between two adjacents points from x. Smaller peaks are removed first until the condition is fulfilled for all remaining peaks.
+            - width (None, scalar or 2-element sequence) : required width of peaks in samples. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required width.
+        
+        return:
+            - (positions, heights, widths) : an array of three elements with the positions, the heights and the widths of the peaks
+    &#34;&#34;&#34;
+    peaks_properties={}
+    dx=(np.max(x)-np.max(y))/len(x)
+    
+    if distance is not None:
+        distance_index=int(np.round(distance/dx))
+    else:
+        distance_index=None
+    
+    peaks_index,prop=scipy.signal.find_peaks(y,height=height, threshold=threshold, distance=distance_index, width=width)
+    if height is not None:
+        peaks_properties[&#34;peak_heights&#34;]=prop[&#34;peak_heights&#34;]
+    else:
+        peaks_properties[&#34;peak_heights&#34;]=y[peaks_index]
+        
+    if width is not None:
+        peaks_properties[&#34;widths&#34;]=prop[&#34;widths&#34;]
+    else:
+        peaks_properties[&#34;widths&#34;]=scipy.signal.peak_widths(y,peaks_index)[0]
+    
+    
+    return x[peaks_index],peaks_properties[&#34;peak_heights&#34;],peaks_properties[&#34;widths&#34;]</code></pre>
+</details>
+<div class="desc"><p>Function to find peaks in the Raman spectrum. Be careful that the method is not a fit put a peak detection.</p>
+<p>args:
+- x (array) : an array
+- y (array) : the signal with peaks with the same dimension as x
+- height (None, scalar or 2-element sequence) : required height of peaks. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required height.
+- threshold (None, scalar or 2-element sequence) : required threshold of peaks, the vertical distance to its neighboring samples. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required threshold.
+- distance (scalar) : Required minimal horizontal distance in samples between neighbouring peaks. The distance should be higher than the step between two adjacents points from x. Smaller peaks are removed first until the condition is fulfilled for all remaining peaks.
+- width (None, scalar or 2-element sequence) : required width of peaks in samples. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required width.</p>
+<p>return:
+- (positions, heights, widths) : an array of three elements with the positions, the heights and the widths of the peaks</p></div>
+</dd>
+<dt id="dopes.data_analysis.raman.find_peaks_from_file"><code class="name flex">
+<span>def <span class="ident">find_peaks_from_file</span></span>(<span>file_path, height=None, threshold=None, distance=None, width=None)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def find_peaks_from_file(file_path,height=None, threshold=None, distance=None, width=None):
+    &#34;&#34;&#34; Function to find peaks in the Raman spectrum. Be careful that the method is not a fit put a peak detection.
+    
+        args:
+            - x (array) : an array 
+            - y (array) : the signal with peaks with the same dimension as x
+            - height (None, scalar or 2-element sequence) : required height of peaks. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required height.
+            - threshold (None, scalar or 2-element sequence) : required threshold of peaks, the vertical distance to its neighboring samples. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required threshold.
+            - distance (scalar) : Required minimal horizontal distance in samples between neighbouring peaks. The distance should be higher than the step between two adjacents points from x. Smaller peaks are removed first until the condition is fulfilled for all remaining peaks.
+            - width (None, scalar or 2-element sequence) : required width of peaks in samples. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required width.
+        
+        return:
+            - (positions, heights, widths) : an array of three elements with the positions, the heights and the widths of the peaks
+    &#34;&#34;&#34;
+    data=file_handling.read_file(file_path,comments=&#34;#&#34;,delimiter=None)
+    x=data[:,0]
+    y=data[:,1]
+
+    return find_peaks(x,y,height, threshold, distance, width)</code></pre>
+</details>
+<div class="desc"><p>Function to find peaks in the Raman spectrum. Be careful that the method is not a fit put a peak detection.</p>
+<p>args:
+- x (array) : an array
+- y (array) : the signal with peaks with the same dimension as x
+- height (None, scalar or 2-element sequence) : required height of peaks. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required height.
+- threshold (None, scalar or 2-element sequence) : required threshold of peaks, the vertical distance to its neighboring samples. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required threshold.
+- distance (scalar) : Required minimal horizontal distance in samples between neighbouring peaks. The distance should be higher than the step between two adjacents points from x. Smaller peaks are removed first until the condition is fulfilled for all remaining peaks.
+- width (None, scalar or 2-element sequence) : required width of peaks in samples. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required width.</p>
+<p>return:
+- (positions, heights, widths) : an array of three elements with the positions, the heights and the widths of the peaks</p></div>
+</dd>
+<dt id="dopes.data_analysis.raman.phonon_deformation_silicon"><code class="name flex">
+<span>def <span class="ident">phonon_deformation_silicon</span></span>(<span>strain_matrix, p, q, r, sort=False, w0=None)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def phonon_deformation_silicon(strain_matrix,p,q,r,sort=False,w0=None):
+    &#34;&#34;&#34; Function to calculate the Raman shift from an arbitrary strain tensor using Phonon Deformation Potential (PDP) theory
+    
+        args:
+            - strain_matrix (3x3 matrix) : the strain tensor
+            - p (scalar) : the first phonon deformation potential    
+            - q (scalar) : the second phonon deformation potential.    
+            - r (scalar) : the third phonon deformation potential  
+            - sort (boolean) : if true, sort the phonon modes from lowest to highest energy
+            - w0 (scalar) : reference energy at zero strain, 520.7 cm-1 for silicon
+        return:
+            - an array of three elements with the energy of the three phonon modes (LO, TO1, and TO2).
+    &#34;&#34;&#34;
+    if w0==None:
+        w0=520.7 # in cm-1
+        
+    p=p*w0**2
+    q=q*w0**2
+    r=r*w0**2
+    exx=strain_matrix[0,0]
+    eyy=strain_matrix[1,1]
+    ezz=strain_matrix[2,2]
+    eyz=strain_matrix[1,2]
+    exz=strain_matrix[0,2]
+    exy=strain_matrix[0,1]
+    ezy=strain_matrix[2,1]
+    ezx=strain_matrix[2,0]
+    eyx=strain_matrix[1,0]
+    P=np.array([[p*exx+q*(eyy+ezz),2*r*exy,2*r*exz],
+                [2*r*eyx,p*eyy+q*(ezz+exx),2*r*eyz],
+                [2*r*ezx,2*r*ezy,p*ezz+q*(eyy+exx)]])
+    det=np.linalg.det(P)
+    tr=np.trace(P)
+    tr2=np.trace(P.dot(P))
+    
+    if sort : 
+        lamb=np.sort(np.roots([1,-tr,-0.5*(tr2-tr**2),-det]))
+        
+    else :
+        lamb=np.roots([1,-tr,-0.5*(tr2-tr**2),-det])
+    return np.sqrt(lamb+w0**2)</code></pre>
+</details>
+<div class="desc"><p>Function to calculate the Raman shift from an arbitrary strain tensor using Phonon Deformation Potential (PDP) theory</p>
+<p>args:
+- strain_matrix (3x3 matrix) : the strain tensor
+- p (scalar) : the first phonon deformation potential
+<br>
+- q (scalar) : the second phonon deformation potential.
+<br>
+- r (scalar) : the third phonon deformation potential<br>
+- sort (boolean) : if true, sort the phonon modes from lowest to highest energy
+- w0 (scalar) : reference energy at zero strain, 520.7 cm-1 for silicon
+return:
+- an array of three elements with the energy of the three phonon modes (LO, TO1, and TO2).</p></div>
+</dd>
+<dt id="dopes.data_analysis.raman.plot_from_file"><code class="name flex">
+<span>def <span class="ident">plot_from_file</span></span>(<span>file_path,<br>ax=None,<br>with_peaks=False,<br>with_peaks_label=False,<br>height=None,<br>threshold=None,<br>distance=None,<br>width=None,<br>**plot_kwargs)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def plot_from_file(file_path,ax=None,with_peaks=False,with_peaks_label=False,height=None, threshold=None, distance=None, width=None,**plot_kwargs):
+    &#34;&#34;&#34; Function to plot the Raman spectrum with the peaks indicated
+    
+        args:
+            - file_path (string) : the file to read
+            - ax (Axes) : the axes of the subplot in which plotting the Raman signal and peaks
+            - with_peaks (boolean) : if True, find the peaks in the spectrum and show them on the graph. Be careful that the method is not a fit put a peak detection.
+            - with_peaks_label (boolean) : if True, write the value of the peaks above each of them
+            - height (None, scalar or 2-element sequence) : required height of peaks. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required height.
+            - threshold (None, scalar or 2-element sequence) : required threshold of peaks, the vertical distance to its neighboring samples. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required threshold.
+            - distance (scalar) : Required minimal horizontal distance in samples between neighbouring peaks. The distance should be higher than the step between two adjacents points from x. Smaller peaks are removed first until the condition is fulfilled for all remaining peaks.
+            - width (None, scalar or 2-element sequence) : required width of peaks in samples. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required width.
+            - **plot_kwargs : this method also takes any keyword argument for the Axes.plot() function such as linewidth, linestyle, marker, markersize, color, markeredgecolor, zorder, alpha, label, clip_on, ...
+            
+        return:
+            - fig, ax : the Figure and Axes object created if None is specified for ax
+    &#34;&#34;&#34;
+    
+    data=file_handling.read_file(file_path,comments=&#34;#&#34;,delimiter=None)
+    x=data[:,0]
+    y=data[:,1]
+    
+    if ax==None:
+        fig=plt.figure()
+        ax_data=fig.add_subplot()
+    else:
+        ax_data=ax
+        
+    if with_peaks:
+        plot_with_peaks(x,y,ax=ax_data,height=height, threshold=threshold, distance=distance, width=width,with_peaks_label=with_peaks_label,**plot_kwargs)
+    else:
+        ax_data.plot(x,y,**plot_kwargs)
+        
+    if ax==None:
+        return fig, ax_data</code></pre>
+</details>
+<div class="desc"><p>Function to plot the Raman spectrum with the peaks indicated</p>
+<p>args:
+- file_path (string) : the file to read
+- ax (Axes) : the axes of the subplot in which plotting the Raman signal and peaks
+- with_peaks (boolean) : if True, find the peaks in the spectrum and show them on the graph. Be careful that the method is not a fit put a peak detection.
+- with_peaks_label (boolean) : if True, write the value of the peaks above each of them
+- height (None, scalar or 2-element sequence) : required height of peaks. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required height.
+- threshold (None, scalar or 2-element sequence) : required threshold of peaks, the vertical distance to its neighboring samples. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required threshold.
+- distance (scalar) : Required minimal horizontal distance in samples between neighbouring peaks. The distance should be higher than the step between two adjacents points from x. Smaller peaks are removed first until the condition is fulfilled for all remaining peaks.
+- width (None, scalar or 2-element sequence) : required width of peaks in samples. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required width.
+- **plot_kwargs : this method also takes any keyword argument for the Axes.plot() function such as linewidth, linestyle, marker, markersize, color, markeredgecolor, zorder, alpha, label, clip_on, &hellip;</p>
+<p>return:
+- fig, ax : the Figure and Axes object created if None is specified for ax</p></div>
+</dd>
+<dt id="dopes.data_analysis.raman.plot_from_multiple_files"><code class="name flex">
+<span>def <span class="ident">plot_from_multiple_files</span></span>(<span>file_paths,<br>with_peaks=False,<br>with_peaks_label=False,<br>height=None,<br>threshold=None,<br>distance=None,<br>width=None,<br>sharey=False,<br>ylabel=None,<br>**plot_kwargs)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def plot_from_multiple_files(file_paths,with_peaks=False,with_peaks_label=False,height=None, threshold=None, distance=None, width=None,sharey=False,ylabel=None,**plot_kwargs):
+    
+    &#34;&#34;&#34; Function to plot the Raman spectrum with the peaks indicated
+    
+        args:
+            - file_paths (list of string) : lis of the names for the files to read
+            - ax (Axes) : the axes of the subplot in which plotting the Raman signal and peaks
+            - with_peaks (boolean) : if True, find the peaks in the spectrum and show them on the graph. Be careful that the method is not a fit put a peak detection.
+            - with_peaks_label (boolean) : if True, write the value of the peaks above each of them
+            - height (None, scalar or 2-element sequence) : required height of peaks. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required height.
+            - threshold (None, scalar or 2-element sequence) : required threshold of peaks, the vertical distance to its neighboring samples. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required threshold.
+            - distance (scalar) : Required minimal horizontal distance in samples between neighbouring peaks. The distance should be higher than the step between two adjacents points from x. Smaller peaks are removed first until the condition is fulfilled for all remaining peaks.
+            - width (None, scalar or 2-element sequence) : required width of peaks in samples. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required width.
+            - **plot_kwargs : this method also takes any keyword argument for the Axes.plot() function such as linewidth, linestyle, marker, markersize, color, markeredgecolor, zorder, alpha, label, clip_on, ...
+            
+        return:
+            - fig, ax : the Figure and a list with the axes object created
+    &#34;&#34;&#34;
+    
+    n_plot=len(file_paths)
+    fig,ax=plt.subplots(n_plot,1,sharex=True,sharey=sharey,figsize=(5,n_plot*2))
+    
+    for i in range(n_plot):
+        ax[-i-1].spines.right.set_visible(False)
+        ax[-i-1].spines.top.set_visible(False)
+        if ylabel is not None:
+            ax[-i-1].set_ylabel(ylabel)
+        # if i != 0:
+        #     ax[-i-1].xticklabels.bottom.set_visible(False)
+        plot_from_file(file_paths[i],ax=ax[-i-1],with_peaks=with_peaks,with_peaks_label=with_peaks_label,height=height, threshold=threshold, distance=distance, width=width,**plot_kwargs)
+        
+    return fig, ax</code></pre>
+</details>
+<div class="desc"><p>Function to plot the Raman spectrum with the peaks indicated</p>
+<p>args:
+- file_paths (list of string) : lis of the names for the files to read
+- ax (Axes) : the axes of the subplot in which plotting the Raman signal and peaks
+- with_peaks (boolean) : if True, find the peaks in the spectrum and show them on the graph. Be careful that the method is not a fit put a peak detection.
+- with_peaks_label (boolean) : if True, write the value of the peaks above each of them
+- height (None, scalar or 2-element sequence) : required height of peaks. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required height.
+- threshold (None, scalar or 2-element sequence) : required threshold of peaks, the vertical distance to its neighboring samples. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required threshold.
+- distance (scalar) : Required minimal horizontal distance in samples between neighbouring peaks. The distance should be higher than the step between two adjacents points from x. Smaller peaks are removed first until the condition is fulfilled for all remaining peaks.
+- width (None, scalar or 2-element sequence) : required width of peaks in samples. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required width.
+- **plot_kwargs : this method also takes any keyword argument for the Axes.plot() function such as linewidth, linestyle, marker, markersize, color, markeredgecolor, zorder, alpha, label, clip_on, &hellip;</p>
+<p>return:
+- fig, ax : the Figure and a list with the axes object created</p></div>
+</dd>
+<dt id="dopes.data_analysis.raman.plot_with_peaks"><code class="name flex">
+<span>def <span class="ident">plot_with_peaks</span></span>(<span>x,<br>y,<br>ax=None,<br>height=None,<br>threshold=None,<br>distance=None,<br>width=None,<br>with_peaks_label=False,<br>**plot_kwargs)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def plot_with_peaks(x,y,ax=None,height=None, threshold=None, distance=None, width=None,with_peaks_label=False,**plot_kwargs):
+    &#34;&#34;&#34; Function to plot the Raman spectrum with the peaks indicated.  Be careful that the method is not a fit put a peak detection.
+    
+        args:
+            - x (array) : an array for the energy of the Raman spectrum
+            - y (array) : the Raman signal with peaks with the same dimension as x
+            - ax (Axes) : the axes of the subplot in which plotting the Raman signal and peaks
+            - height (None, scalar or 2-element sequence) : required height of peaks. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required height.
+            - threshold (None, scalar or 2-element sequence) : required threshold of peaks, the vertical distance to its neighboring samples. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required threshold.
+            - distance (scalar) : Required minimal horizontal distance in samples between neighbouring peaks. The distance should be higher than the step between two adjacents points from x. Smaller peaks are removed first until the condition is fulfilled for all remaining peaks.
+            - width (None, scalar or 2-element sequence) : required width of peaks in samples. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required width.
+            - with_peaks_label (boolean) : if True, write the value of the peaks above each of them
+            - **plot_kwargs : this method also takes any keyword argument for the Axes.plot() function such as linewidth, linestyle, marker, markersize, color, markeredgecolor, zorder, alpha, label, clip_on, ...
+            
+        return:
+            - fig, ax : the Figure and Axes object created if None is specified for ax
+    &#34;&#34;&#34;
+    
+    if ax==None:
+        fig=plt.figure()
+        ax_data=fig.add_subplot()
+    else:
+        ax_data=ax
+    
+    ax_data.plot(x,y,**plot_kwargs)
+    position, heights, width=find_peaks(x,y,height=height, threshold=threshold, distance=distance, width=width)
+    
+    ax_data.plot(position,heights,marker=&#34;.&#34;,ls=&#34;&#34;,color=&#34;k&#34;)
+    for i in range(len(heights)):
+        ax_data.plot([position[i],position[i]],[0,heights[i]],marker=&#34;&#34;,ls=&#34;--&#34;,color=&#34;k&#34;)
+        if with_peaks_label:
+            ax_data.text(position[i],1.1*heights[i],&#34;%.2f&#34;%position[i],ha=&#34;center&#34;,va=&#34;bottom&#34;,rotation=&#34;vertical&#34;)
+    if ax==None:
+        return fig, ax_data</code></pre>
+</details>
+<div class="desc"><p>Function to plot the Raman spectrum with the peaks indicated.
+Be careful that the method is not a fit put a peak detection.</p>
+<p>args:
+- x (array) : an array for the energy of the Raman spectrum
+- y (array) : the Raman signal with peaks with the same dimension as x
+- ax (Axes) : the axes of the subplot in which plotting the Raman signal and peaks
+- height (None, scalar or 2-element sequence) : required height of peaks. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required height.
+- threshold (None, scalar or 2-element sequence) : required threshold of peaks, the vertical distance to its neighboring samples. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required threshold.
+- distance (scalar) : Required minimal horizontal distance in samples between neighbouring peaks. The distance should be higher than the step between two adjacents points from x. Smaller peaks are removed first until the condition is fulfilled for all remaining peaks.
+- width (None, scalar or 2-element sequence) : required width of peaks in samples. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required width.
+- with_peaks_label (boolean) : if True, write the value of the peaks above each of them
+- **plot_kwargs : this method also takes any keyword argument for the Axes.plot() function such as linewidth, linestyle, marker, markersize, color, markeredgecolor, zorder, alpha, label, clip_on, &hellip;</p>
+<p>return:
+- fig, ax : the Figure and Axes object created if None is specified for ax</p></div>
+</dd>
+</dl>
+</section>
+<section>
+</section>
+</article>
+<nav id="sidebar">
+<div class="toc">
+<ul></ul>
+</div>
+<ul id="index">
+<li><h3>Super-module</h3>
+<ul>
+<li><code><a title="dopes.data_analysis" href="index.html">dopes.data_analysis</a></code></li>
+</ul>
+</li>
+<li><h3><a href="#header-functions">Functions</a></h3>
+<ul class="">
+<li><code><a title="dopes.data_analysis.raman.find_peaks" href="#dopes.data_analysis.raman.find_peaks">find_peaks</a></code></li>
+<li><code><a title="dopes.data_analysis.raman.find_peaks_from_file" href="#dopes.data_analysis.raman.find_peaks_from_file">find_peaks_from_file</a></code></li>
+<li><code><a title="dopes.data_analysis.raman.phonon_deformation_silicon" href="#dopes.data_analysis.raman.phonon_deformation_silicon">phonon_deformation_silicon</a></code></li>
+<li><code><a title="dopes.data_analysis.raman.plot_from_file" href="#dopes.data_analysis.raman.plot_from_file">plot_from_file</a></code></li>
+<li><code><a title="dopes.data_analysis.raman.plot_from_multiple_files" href="#dopes.data_analysis.raman.plot_from_multiple_files">plot_from_multiple_files</a></code></li>
+<li><code><a title="dopes.data_analysis.raman.plot_with_peaks" href="#dopes.data_analysis.raman.plot_with_peaks">plot_with_peaks</a></code></li>
+</ul>
+</li>
+</ul>
+</nav>
+</main>
+<footer id="footer">
+<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
+</footer>
+</body>
+</html>
diff --git a/html/data_analysis/semiconductor.html b/html/data_analysis/semiconductor.html
new file mode 100644
index 0000000000000000000000000000000000000000..dee3e227ccb28e49fb72af9442513670e7c750ac
--- /dev/null
+++ b/html/data_analysis/semiconductor.html
@@ -0,0 +1,393 @@
+<!doctype html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
+<meta name="generator" content="pdoc3 0.11.6">
+<title>dopes.data_analysis.semiconductor API documentation</title>
+<meta name="description" content="">
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/typography.min.css" integrity="sha512-Y1DYSb995BAfxobCkKepB1BqJJTPrOp3zPL74AWFugHHmmdcvO+C48WLrUOlhGMc0QG7AE3f7gmvvcrmX2fDoA==" crossorigin>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css" crossorigin>
+<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:1.5em;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:2em 0 .50em 0}h3{font-size:1.4em;margin:1.6em 0 .7em 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .2s ease-in-out}a:visited{color:#503}a:hover{color:#b62}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900;font-weight:bold}pre code{font-size:.8em;line-height:1.4em;padding:1em;display:block}code{background:#f3f3f3;font-family:"DejaVu Sans Mono",monospace;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source > summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible;min-width:max-content}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em 1em;margin:1em 0}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
+<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul ul{padding-left:1em}.toc > ul > li{margin-top:.5em}}</style>
+<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
+<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js" integrity="sha512-D9gUyxqja7hBtkWpPWGt9wfbfaMGVt9gnyCvYa+jojwwPHLCzUm5i8rpk7vD7wNee9bA35eYIjobYPaQuKS1MQ==" crossorigin></script>
+<script>window.addEventListener('DOMContentLoaded', () => {
+hljs.configure({languages: ['bash', 'css', 'diff', 'graphql', 'ini', 'javascript', 'json', 'plaintext', 'python', 'python-repl', 'rust', 'shell', 'sql', 'typescript', 'xml', 'yaml']});
+hljs.highlightAll();
+/* Collapse source docstrings */
+setTimeout(() => {
+[...document.querySelectorAll('.hljs.language-python > .hljs-string')]
+.filter(el => el.innerHTML.length > 200 && ['"""', "'''"].includes(el.innerHTML.substring(0, 3)))
+.forEach(el => {
+let d = document.createElement('details');
+d.classList.add('hljs-string');
+d.innerHTML = '<summary>"""</summary>' + el.innerHTML.substring(3);
+el.replaceWith(d);
+});
+}, 100);
+})</script>
+</head>
+<body>
+<main>
+<article id="content">
+<header>
+<h1 class="title">Module <code>dopes.data_analysis.semiconductor</code></h1>
+</header>
+<section id="section-intro">
+</section>
+<section>
+</section>
+<section>
+</section>
+<section>
+<h2 class="section-title" id="header-functions">Functions</h2>
+<dl>
+<dt id="dopes.data_analysis.semiconductor.intrinsic_concentration"><code class="name flex">
+<span>def <span class="ident">intrinsic_concentration</span></span>(<span>temp)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def intrinsic_concentration(temp):
+    &#34;&#34;&#34; Function to calculate the intrinsic concentration of silicon from K. Misiakos and Tsamakis, D., “Accurate measurements of the silicon intrinsic carrier density from 78 to 340 K”, Journal of Applied Physics, vol. 74, no. 5, p. 3293, 1993.
+    
+        args:
+            - temp (scalar): the temperature 
+            
+        return:
+            - ni (scalar): the intrinsic concentration in silicon
+    &#34;&#34;&#34;  
+    
+    return 5.29e19 * (temp/300)**2.54 * np.exp(-6726/temp)</code></pre>
+</details>
+<div class="desc"><p>Function to calculate the intrinsic concentration of silicon from K. Misiakos and Tsamakis, D., “Accurate measurements of the silicon intrinsic carrier density from 78 to 340 K”, Journal of Applied Physics, vol. 74, no. 5, p. 3293, 1993.</p>
+<p>args:
+- temp (scalar): the temperature </p>
+<p>return:
+- ni (scalar): the intrinsic concentration in silicon</p></div>
+</dd>
+<dt id="dopes.data_analysis.semiconductor.mobility_impurity"><code class="name flex">
+<span>def <span class="ident">mobility_impurity</span></span>(<span>mu_0, carrier='n', Ni=1000000000000000.0, temp=300, dopant='phosphorus')</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def mobility_impurity(mu_0,carrier=&#34;n&#34;,Ni=1e15,temp=300, dopant=&#34;phosphorus&#34;):
+    &#34;&#34;&#34; Function to calculate the silicon mobility according to Masetti relation (1983)
+    
+        args:
+            - carrier (string): &#34;n&#34; for electrons, &#34;p&#34; for holes
+            - temp (scalar): the temperature 
+            - Ni (scalar): the impurity cencentration in cm-3
+            - dopant (string): the type of n-type dopant. &#34;phosphorus&#34; or &#34;arsenic&#34;
+            
+        return:
+            - mu_LI (scalar): the electron or hole mobility with the impurity scattering taken into account
+    &#34;&#34;&#34;  
+    
+    # Values are taken from Masetti et al. (1983)
+    if dopant==&#34;phosphorus&#34;:
+        param_300_n={&#34;mu_min&#34;:68.5,&#34;Cref&#34;:9.20e16,&#34;alpha&#34;:0.711} 
+        correction_n={&#34;mu_min&#34;:56.1,&#34;Cref&#34;:3.41e20,&#34;alpha&#34;:1.98} 
+        # mu_0=1414
+    elif dopant==&#34;arsenic&#34;:
+        param_300_n={&#34;mu_min&#34;:52.2,&#34;Cref&#34;:9.68e16,&#34;alpha&#34;:0.680} 
+        correction_n={&#34;mu_min&#34;:43.4,&#34;Cref&#34;:3.43e20,&#34;alpha&#34;:2.00} 
+        # mu_0=1417
+
+    param_300_p={&#34;mu_min&#34;:44.9,&#34;Cref&#34;:22.3e16,&#34;alpha&#34;:0.72}
+    correction_p={&#34;mu_min&#34;:29.0,&#34;Cref&#34;:6.1e20,&#34;alpha&#34;:2.0}
+    
+    expon_temp={&#34;mu_min&#34;:-0.45,&#34;Cref&#34;:3.2,&#34;alpha&#34;:0.065}
+     
+    if carrier==&#34;n&#34;:
+        param_300=param_300_n
+        correction=correction_n[&#34;mu_min&#34;]/(1+(correction_n[&#34;Cref&#34;]/Ni)**correction_n[&#34;alpha&#34;])
+    else:
+        param_300=param_300_p
+        correction=correction_p[&#34;mu_min&#34;]/(1+(correction_p[&#34;Cref&#34;]/Ni)**correction_p[&#34;alpha&#34;])
+        # mu_0=470.5
+
+
+    mu_min=param_300[&#34;mu_min&#34;]*(temp/300)**expon_temp[&#34;mu_min&#34;]
+    Cref=param_300[&#34;Cref&#34;]*(temp/300)**expon_temp[&#34;Cref&#34;]
+    alpha=param_300[&#34;alpha&#34;]*(temp/300)**expon_temp[&#34;alpha&#34;]
+    
+    mu_LI=mu_min+(mu_0-mu_min) / ( 1 + ( Ni / Cref )**alpha )-correction
+    
+    return mu_LI</code></pre>
+</details>
+<div class="desc"><p>Function to calculate the silicon mobility according to Masetti relation (1983)</p>
+<p>args:
+- carrier (string): "n" for electrons, "p" for holes
+- temp (scalar): the temperature
+- Ni (scalar): the impurity cencentration in cm-3
+- dopant (string): the type of n-type dopant. "phosphorus" or "arsenic"</p>
+<p>return:
+- mu_LI (scalar): the electron or hole mobility with the impurity scattering taken into account</p></div>
+</dd>
+<dt id="dopes.data_analysis.semiconductor.piezo_ratio_temperature"><code class="name flex">
+<span>def <span class="ident">piezo_ratio_temperature</span></span>(<span>temp, carrier='n')</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def piezo_ratio_temperature(temp,carrier=&#34;n&#34;):
+    &#34;&#34;&#34; Function to calculate the correcting ratio due to temperature variations for the piezoresistive coefficients. The data are taken from Kanda (1982) between 200 K and 400K.
+        The correction is refered to the 300K coefficients. The new piezoresistive coefficients can be calculated by piezo_coefficient(temp) = ratio * piezo_coefficient(300K)
+        
+        args:
+            - temp (scalar or sequence): the temperatures for which the correting ratio has to be calculated
+            - carrier (string): &#34;n&#34; for electrons, &#34;p&#34; for holes
+                
+        return:
+            - a scalar or sequence with the same dimension as temp with the correcting ratio
+    &#34;&#34;&#34;  
+
+    temp_kanda1982=np.linspace(125, -75,9)+273
+    dpi_kanda1982_n=np.array([0.7547318611987381,0.8067823343848579,0.8611987381703468,0.9298107255520504,1.0007886435331228,1.0977917981072554,1.2113564668769716,1.3438485804416402,1.5165615141955835])
+    dpi_kanda1982_p=np.array([0.7523342983957861,0.8037360206464299,0.8598127702627387,0.922894558591104,0.995324258126102,1.0934548187864221,1.205601887444947,1.3411219494071012,1.5093457676819353])
+    
+    fn=interp.interp1d(temp_kanda1982,dpi_kanda1982_n,kind=&#34;linear&#34;,fill_value=&#34;extrapolate&#34; )
+    fp=interp.interp1d(temp_kanda1982,dpi_kanda1982_p,kind=&#34;linear&#34;,fill_value=&#34;extrapolate&#34; )
+
+    if carrier==&#34;n&#34;:
+        return fn(temp)
+    elif carrier ==&#34;p&#34;:
+        return fp(temp)
+    else:
+        return 0</code></pre>
+</details>
+<div class="desc"><p>Function to calculate the correcting ratio due to temperature variations for the piezoresistive coefficients. The data are taken from Kanda (1982) between 200 K and 400K.
+The correction is refered to the 300K coefficients. The new piezoresistive coefficients can be calculated by piezo_coefficient(temp) = ratio * piezo_coefficient(300K)</p>
+<p>args:
+- temp (scalar or sequence): the temperatures for which the correting ratio has to be calculated
+- carrier (string): "n" for electrons, "p" for holes</p>
+<p>return:
+- a scalar or sequence with the same dimension as temp with the correcting ratio</p></div>
+</dd>
+<dt id="dopes.data_analysis.semiconductor.piezoresistivity_strain"><code class="name flex">
+<span>def <span class="ident">piezoresistivity_strain</span></span>(<span>strain_tensor, pi11, pi12, pi44)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def piezoresistivity_strain(strain_tensor, pi11, pi12, pi44):
+    &#34;&#34;&#34; Function to calculate the relative change due to stress in silicon
+        
+        args:
+            - stress_tensor (numpy array): the stress tensor for which the stress should be calculated. The voigt notation should be used with a 1 x 6 vector but the function can handle  3 x 3 matrix but only take the upper half in this case.
+            - pi11, pi12 and pi44 (scalar): piezoresistive coefficients used to calculate the variations in the relative resistivity. 
+              Values from Smith (1954) are pi11 = -1022 TPa-1, pi12 = 534 TPa-1 and pi44 = -136 TPa-1 for the electrons,
+              and pi11 = 66 TPa-1, pi12 = -11 TPa-1 and pi44 = 1381 TPa-1 for the holes.
+                
+        return:
+            - an 1 x 6 tensor using the Voigt notation with the relative variation of the resistivity.
+    &#34;&#34;&#34;  
+
+    piezo_tensor=np.array([[pi11,pi12,pi12,0,0,0],
+                                [pi12,pi11,pi12,0,0,0],
+                                [pi12,pi12,pi11,0,0,0],
+                                [0,0,0,pi44,0,0],
+                                [0,0,0,0,pi44,0],
+                                [0,0,0,0,0,pi44]])
+    
+    stress_tensor= mec.stress_from_strain(strain_tensor)
+    
+    return piezo_tensor @ stress_tensor</code></pre>
+</details>
+<div class="desc"><p>Function to calculate the relative change due to stress in silicon</p>
+<p>args:
+- stress_tensor (numpy array): the stress tensor for which the stress should be calculated. The voigt notation should be used with a 1 x 6 vector but the function can handle
+3 x 3 matrix but only take the upper half in this case.
+- pi11, pi12 and pi44 (scalar): piezoresistive coefficients used to calculate the variations in the relative resistivity.
+Values from Smith (1954) are pi11 = -1022 TPa-1, pi12 = 534 TPa-1 and pi44 = -136 TPa-1 for the electrons,
+and pi11 = 66 TPa-1, pi12 = -11 TPa-1 and pi44 = 1381 TPa-1 for the holes.</p>
+<p>return:
+- an 1 x 6 tensor using the Voigt notation with the relative variation of the resistivity.</p></div>
+</dd>
+<dt id="dopes.data_analysis.semiconductor.piezoresistivity_stress"><code class="name flex">
+<span>def <span class="ident">piezoresistivity_stress</span></span>(<span>stress_tensor, pi11, pi12, pi44)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def piezoresistivity_stress(stress_tensor, pi11, pi12, pi44):
+    &#34;&#34;&#34; Function to calculate the relative change due to stress in silicon
+        
+        args:
+            - stress_tensor (numpy array): the stress tensor for which the stress should be calculated. The voigt notation should be used with a 1 x 6 vector but the function can handle  3 x 3 matrix but only take the upper half in this case.
+            - pi11, pi12 and pi44 (scalar): piezoresistive coefficients used to calculate the variations in the relative resistivity. 
+              Values from Smith (1954) are pi11 = -1022 TPa-1, pi12 = 534 TPa-1 and pi44 = -136 TPa-1 for the electrons,
+              and pi11 = 66 TPa-1, pi12 = -11 TPa-1 and pi44 = 1381 TPa-1 for the holes.
+                
+        return:
+            - an 1 x 6 tensor using the Voigt notation with the relative variation of the resistivity.
+    &#34;&#34;&#34;  
+    
+    stress_voigt=np.zeros((6,1))
+    stress_shape=np.shape(stress_tensor)
+    
+    if len(stress_shape)==2:
+        if stress_shape[0]==3 and stress_shape[1]==3:
+            stress_voigt[0]=stress_tensor[0,0]
+            stress_voigt[1]=stress_tensor[1,1]
+            stress_voigt[2]=stress_tensor[2,2]
+            stress_voigt[3]=stress_tensor[1,2]
+            stress_voigt[4]=stress_tensor[0,2]
+            stress_voigt[5]=stress_tensor[0,1]
+        if stress_shape[0]==1 and stress_shape[1]==6:
+            stress_voigt=stress_tensor
+    else:
+        stress_voigt=np.array([stress_tensor])
+    
+    piezo_tensor=np.array([[pi11,pi12,pi12,0,0,0],
+                                [pi12,pi11,pi12,0,0,0],
+                                [pi12,pi12,pi11,0,0,0],
+                                [0,0,0,pi44,0,0],
+                                [0,0,0,0,pi44,0],
+                                [0,0,0,0,0,pi44]])
+    
+    return piezo_tensor @ stress_voigt</code></pre>
+</details>
+<div class="desc"><p>Function to calculate the relative change due to stress in silicon</p>
+<p>args:
+- stress_tensor (numpy array): the stress tensor for which the stress should be calculated. The voigt notation should be used with a 1 x 6 vector but the function can handle
+3 x 3 matrix but only take the upper half in this case.
+- pi11, pi12 and pi44 (scalar): piezoresistive coefficients used to calculate the variations in the relative resistivity.
+Values from Smith (1954) are pi11 = -1022 TPa-1, pi12 = 534 TPa-1 and pi44 = -136 TPa-1 for the electrons,
+and pi11 = 66 TPa-1, pi12 = -11 TPa-1 and pi44 = 1381 TPa-1 for the holes.</p>
+<p>return:
+- an 1 x 6 tensor using the Voigt notation with the relative variation of the resistivity.</p></div>
+</dd>
+<dt id="dopes.data_analysis.semiconductor.tau_srh"><code class="name flex">
+<span>def <span class="ident">tau_srh</span></span>(<span>Ni, tau_0=5e-05, Nc=5e+16, A=1, B=1, C=0, E=0)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def tau_srh(Ni, tau_0=5e-5,  Nc=5e16, A=1, B=1, C=0, E=0):
+    &#34;&#34;&#34; Function to calculate the SRH lifetime of silicon. The default parameters, similar for electron and hole, are those from D&#39;Avanzo, D. C., Vanzi, M., Dutton, R. W.: One-Dimensional Semiconductor Device Analysis
+        (SEDAN). Report G-201-5, Stanford University, 1979.
+        
+        args:
+            - Ni (scalar): the impurity density in the material 
+            - tau_0 (scalar): intial value for the lifetime 
+            - Nc (scalar): the critical impurity level 
+            - A, B, C and D (scalar): the coefficient for the model 
+            
+        return:
+            - the SRH lifetime in silicon
+    &#34;&#34;&#34;  
+    
+    return tau_0/(A+B*(Ni/Nc)+C*(Ni/Nc)**E)</code></pre>
+</details>
+<div class="desc"><p>Function to calculate the SRH lifetime of silicon. The default parameters, similar for electron and hole, are those from D'Avanzo, D. C., Vanzi, M., Dutton, R. W.: One-Dimensional Semiconductor Device Analysis
+(SEDAN). Report G-201-5, Stanford University, 1979.</p>
+<p>args:
+- Ni (scalar): the impurity density in the material
+- tau_0 (scalar): intial value for the lifetime
+- Nc (scalar): the critical impurity level
+- A, B, C and D (scalar): the coefficient for the model </p>
+<p>return:
+- the SRH lifetime in silicon</p></div>
+</dd>
+<dt id="dopes.data_analysis.semiconductor.tau_trap"><code class="name flex">
+<span>def <span class="ident">tau_trap</span></span>(<span>tau_n, tau_p, NA, ND, Etrap=0.56, Eg=1.12, temp=300)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def tau_trap(tau_n, tau_p, NA, ND, Etrap=0.56,Eg=1.12, temp=300):
+    &#34;&#34;&#34; Function to calculate the lifetime of silicon due to a trap.
+        
+        args:
+            - tau_n and tau_p (scalar): the life time of the electron and hole due to the trap density. 
+              The lifetime can be calculated by tau_n = 1 / (sigma_n * v_th * Nt ) where sigma_n is the capture cross section, vth is the thermal velocity and Nt is the trap density. 
+              Typical values for the thermal velocities are 2.3e7 and 1.65e7 cm/s for the electrons and holes, respectively. 
+              Typical value for the capture cross section is 1e-15 cm² for a neutral defect. 
+              Typical value for the trap density is 1e12 cm-3 for a neutral defect.  
+            - NA and ND (scalar): the acceptor and donor density of the pn junction 
+            - Etrap (scalar): the trap level referred to the maximum of the valence band 
+            - Eg (scalar): the bandgap of the material 
+            - temp (scalar): the temperature 
+            
+        return:
+            - the trap lifetime 
+    &#34;&#34;&#34;  
+    kB = 1.38e-23 # J/K
+    q = 1.602e-19 # C
+    
+    nieff=intrinsic_concentration(temp)
+    
+    n_0 = nieff**2 / NA
+    p_0 = nieff**2 / ND
+    n1 = nieff * np.exp(- q * (Eg - Etrap) / (kB*temp))
+    p1 = nieff * np.exp(- q * Etrap / (kB*temp))
+    
+    return (tau_p * (n_0 + n1) + tau_n * (p_0 + p1)) / (p_0 + n_0)</code></pre>
+</details>
+<div class="desc"><p>Function to calculate the lifetime of silicon due to a trap.</p>
+<p>args:
+- tau_n and tau_p (scalar): the life time of the electron and hole due to the trap density.
+The lifetime can be calculated by tau_n = 1 / (sigma_n * v_th * Nt ) where sigma_n is the capture cross section, vth is the thermal velocity and Nt is the trap density.
+Typical values for the thermal velocities are 2.3e7 and 1.65e7 cm/s for the electrons and holes, respectively.
+Typical value for the capture cross section is 1e-15 cm² for a neutral defect.
+Typical value for the trap density is 1e12 cm-3 for a neutral defect.<br>
+- NA and ND (scalar): the acceptor and donor density of the pn junction
+- Etrap (scalar): the trap level referred to the maximum of the valence band
+- Eg (scalar): the bandgap of the material
+- temp (scalar): the temperature </p>
+<p>return:
+- the trap lifetime</p></div>
+</dd>
+</dl>
+</section>
+<section>
+</section>
+</article>
+<nav id="sidebar">
+<div class="toc">
+<ul></ul>
+</div>
+<ul id="index">
+<li><h3>Super-module</h3>
+<ul>
+<li><code><a title="dopes.data_analysis" href="index.html">dopes.data_analysis</a></code></li>
+</ul>
+</li>
+<li><h3><a href="#header-functions">Functions</a></h3>
+<ul class="">
+<li><code><a title="dopes.data_analysis.semiconductor.intrinsic_concentration" href="#dopes.data_analysis.semiconductor.intrinsic_concentration">intrinsic_concentration</a></code></li>
+<li><code><a title="dopes.data_analysis.semiconductor.mobility_impurity" href="#dopes.data_analysis.semiconductor.mobility_impurity">mobility_impurity</a></code></li>
+<li><code><a title="dopes.data_analysis.semiconductor.piezo_ratio_temperature" href="#dopes.data_analysis.semiconductor.piezo_ratio_temperature">piezo_ratio_temperature</a></code></li>
+<li><code><a title="dopes.data_analysis.semiconductor.piezoresistivity_strain" href="#dopes.data_analysis.semiconductor.piezoresistivity_strain">piezoresistivity_strain</a></code></li>
+<li><code><a title="dopes.data_analysis.semiconductor.piezoresistivity_stress" href="#dopes.data_analysis.semiconductor.piezoresistivity_stress">piezoresistivity_stress</a></code></li>
+<li><code><a title="dopes.data_analysis.semiconductor.tau_srh" href="#dopes.data_analysis.semiconductor.tau_srh">tau_srh</a></code></li>
+<li><code><a title="dopes.data_analysis.semiconductor.tau_trap" href="#dopes.data_analysis.semiconductor.tau_trap">tau_trap</a></code></li>
+</ul>
+</li>
+</ul>
+</nav>
+</main>
+<footer id="footer">
+<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
+</footer>
+</body>
+</html>
diff --git a/html/data_analysis/transistor.html b/html/data_analysis/transistor.html
new file mode 100644
index 0000000000000000000000000000000000000000..78dd2286b37f377018b56bf5e0aa311835270ea5
--- /dev/null
+++ b/html/data_analysis/transistor.html
@@ -0,0 +1,217 @@
+<!doctype html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
+<meta name="generator" content="pdoc3 0.11.6">
+<title>dopes.data_analysis.transistor API documentation</title>
+<meta name="description" content="">
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/typography.min.css" integrity="sha512-Y1DYSb995BAfxobCkKepB1BqJJTPrOp3zPL74AWFugHHmmdcvO+C48WLrUOlhGMc0QG7AE3f7gmvvcrmX2fDoA==" crossorigin>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css" crossorigin>
+<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:1.5em;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:2em 0 .50em 0}h3{font-size:1.4em;margin:1.6em 0 .7em 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .2s ease-in-out}a:visited{color:#503}a:hover{color:#b62}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900;font-weight:bold}pre code{font-size:.8em;line-height:1.4em;padding:1em;display:block}code{background:#f3f3f3;font-family:"DejaVu Sans Mono",monospace;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source > summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible;min-width:max-content}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em 1em;margin:1em 0}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
+<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul ul{padding-left:1em}.toc > ul > li{margin-top:.5em}}</style>
+<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
+<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js" integrity="sha512-D9gUyxqja7hBtkWpPWGt9wfbfaMGVt9gnyCvYa+jojwwPHLCzUm5i8rpk7vD7wNee9bA35eYIjobYPaQuKS1MQ==" crossorigin></script>
+<script>window.addEventListener('DOMContentLoaded', () => {
+hljs.configure({languages: ['bash', 'css', 'diff', 'graphql', 'ini', 'javascript', 'json', 'plaintext', 'python', 'python-repl', 'rust', 'shell', 'sql', 'typescript', 'xml', 'yaml']});
+hljs.highlightAll();
+/* Collapse source docstrings */
+setTimeout(() => {
+[...document.querySelectorAll('.hljs.language-python > .hljs-string')]
+.filter(el => el.innerHTML.length > 200 && ['"""', "'''"].includes(el.innerHTML.substring(0, 3)))
+.forEach(el => {
+let d = document.createElement('details');
+d.classList.add('hljs-string');
+d.innerHTML = '<summary>"""</summary>' + el.innerHTML.substring(3);
+el.replaceWith(d);
+});
+}, 100);
+})</script>
+</head>
+<body>
+<main>
+<article id="content">
+<header>
+<h1 class="title">Module <code>dopes.data_analysis.transistor</code></h1>
+</header>
+<section id="section-intro">
+</section>
+<section>
+</section>
+<section>
+</section>
+<section>
+<h2 class="section-title" id="header-functions">Functions</h2>
+<dl>
+<dt id="dopes.data_analysis.transistor.mos_transistor_current"><code class="name flex">
+<span>def <span class="ident">mos_transistor_current</span></span>(<span>vg, vd, vs=0, vth=0.8, k=0.0001, vea=50, theta=0, mos_type='nmos', early=True)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def mos_transistor_current(vg,vd,vs=0,vth=0.8,k=1e-4,vea=50,theta=0,mos_type=&#34;nmos&#34;,early=True):
+    &#34;&#34;&#34; Function to calculate the current in a MOS transistor:
+            cutoff (vgs &lt; vth) : ids = 0
+            triode (vgs - vth &gt;= vds) : ids = k * ( (vgs-vth) * vds - vds**2/2) * (1+(vds)/vea)
+            saturation (vgs - vth &lt; vds)  : ids = k/2 * ( (vgs-vth)**2) * (1+(vds)/vea)
+        with k = &#34;mobility&#34; * &#34;oxide capacitance&#34; * &#34;width&#34; / &#34;length&#34; where the oxide capacitance is given by the ratio between the permittivity and the oxide thickness, i.e., Cox = epsilon_r * epsilon_0 / t_ox
+        The mobility degradation is taken into account by replacing k by k / (1 + theta * (vgs - vth)) in the current equation.
+        
+        args:
+            - vg (scalar or sequence): gate voltage of the transistor. Maximum one parameter among vg, vd and vs can be a sequence.
+            - vd (scala or sequence): drain voltage of the transistor. Maximum one parameter among vg, vd and vs can be a sequence.
+            - vs (scalar or sequence): source voltage of the transistor. Maximum one parameter among vg, vd and vs can be a sequence.
+            - vth (scalar): threshold voltage of the transistor
+            - k (scalar): the gain factor of the transistor
+            - vea (scalar) : early voltage of the transistor
+            - theta (scalar) : mobility degradation factor
+            
+        return:
+            - a scalar or sequence with the value of current calculated
+    &#34;&#34;&#34;  
+    
+    if mos_type==&#34;nmos&#34;:
+        vth=abs(vth)
+        vds=vd-vs
+        vgs=vg-vs
+    if mos_type==&#34;pmos&#34;:
+        vth=abs(vth)
+        vds=vs-vd
+        vgs=vs-vg
+    
+    
+    index_cutoff=(vgs&lt;=vth)
+    index_saturation=(vgs-vth&lt;vds)
+    
+    # if vgs&lt;vth:
+    #     mode=&#34;cutoff&#34;
+    # elif vgs-vth&lt;vds:
+    #     mode=&#34;triode&#34;
+    # elif vgs-vth&gt;=vds:
+    #     mode=&#34;saturation&#34;
+
+    k_theta=k/(1+theta*(vgs-vth))
+
+    jd=k_theta*((vgs-vth)*(vds)-(vds)**2/2)
+
+    
+    if not isinstance(vgs, (int,float)): # vgs is a list  
+        jd[index_saturation]=k_theta[index_saturation]/2*(vgs[index_saturation]-vth)**2 
+        jd[index_cutoff]=0
+    else: # vgs is not a list
+        if not isinstance(vds, (int,float)): # vds is a list
+            jd[index_saturation]=k_theta/2*(vgs-vth)**2 * np.ones(len(vds[index_saturation]))
+            if vgs&lt;=vth:
+                jd=np.zeros(len(vds))
+        else: # vds is not a list
+            if vgs&lt;=vth:
+                jd=0 
+            elif (vgs-vth&lt;vds):
+                jd=k_theta/2*(vgs-vth)**2 
+                
+    if early:
+        jd=jd*(1+(vds)/vea)                
+    
+    return jd</code></pre>
+</details>
+<div class="desc"><p>Function to calculate the current in a MOS transistor:
+cutoff (vgs &lt; vth) : ids = 0
+triode (vgs - vth &gt;= vds) : ids = k * ( (vgs-vth) * vds - vds<strong>2/2) * (1+(vds)/vea)
+saturation (vgs - vth &lt; vds)
+: ids = k/2 * ( (vgs-vth)</strong>2) * (1+(vds)/vea)
+with k = "mobility" * "oxide capacitance" * "width" / "length" where the oxide capacitance is given by the ratio between the permittivity and the oxide thickness, i.e., Cox = epsilon_r * epsilon_0 / t_ox
+The mobility degradation is taken into account by replacing k by k / (1 + theta * (vgs - vth)) in the current equation.</p>
+<p>args:
+- vg (scalar or sequence): gate voltage of the transistor. Maximum one parameter among vg, vd and vs can be a sequence.
+- vd (scala or sequence): drain voltage of the transistor. Maximum one parameter among vg, vd and vs can be a sequence.
+- vs (scalar or sequence): source voltage of the transistor. Maximum one parameter among vg, vd and vs can be a sequence.
+- vth (scalar): threshold voltage of the transistor
+- k (scalar): the gain factor of the transistor
+- vea (scalar) : early voltage of the transistor
+- theta (scalar) : mobility degradation factor</p>
+<p>return:
+- a scalar or sequence with the value of current calculated</p></div>
+</dd>
+<dt id="dopes.data_analysis.transistor.threshold_voltage_extraction"><code class="name flex">
+<span>def <span class="ident">threshold_voltage_extraction</span></span>(<span>ids, vgs, accuracy=4)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def threshold_voltage_extraction(ids,vgs,accuracy=4): 
+    &#34;&#34;&#34; Function to find the threshold voltage of a transistor defined as the voltage where the transconductance gm is maximum, i.e., when the first derivative of the current is maximum or when the second derivative is zero.
+        The method is based on the second-derivative method from Wong HS, White MH, Krutsick TJ, Booth RV. &#34;Modeling of transconductance degradation and extraction of threshold voltage in thin oxide MOSFET’s.&#34; Solid-State Electron (1987).
+        The transistor should be put in linear region (VDS &lt;= VGS-Vth), i.e., with low VDS bias.
+        The implementation is based on central finite difference to limit the impact of noise for the determination of the threshold voltage.
+        The numerical derivative is done on accuracy + 1 points, but accuracy should be even
+        
+        args:
+            - ids (scalar): the source to drain current of the transistor (nmos or pmos)
+            - vgs (scalar): the voltage between the gate and the source of the transistor (nmos or pmos) 
+            - accuracy (integer): related to the number of points taken for the finite difference. For central finite difference, the number of points for a first order derivation is accuracy + 1 but accuracy should be even to guarantee a centered interval.
+            
+        return:
+            - a tuple of two scalars with the threshold voltage found and the transconductance value found at this voltage
+    &#34;&#34;&#34;  
+
+    v_step=np.mean(vgs[1:]-vgs[:-1])
+    gm=proc.finite_difference(ids, v_step,order=1,accuracy=accuracy)
+    
+    dn=len(vgs)-len(gm)
+    f = interp.InterpolatedUnivariateSpline(vgs[int(dn/2):-int(dn/2)], gm, k=4)
+    
+    cr_pts = f.derivative().roots()
+    cr_pts = np.append(cr_pts, (vgs[int(dn/2)], vgs[-int(dn/2)]))  # also check the endpoints of the interval
+    cr_vals = f(cr_pts)
+    max_index = np.argmax(cr_vals)
+    vth=cr_pts[max_index]
+    gm_max=cr_vals[max_index]
+    
+    return vth, gm_max</code></pre>
+</details>
+<div class="desc"><p>Function to find the threshold voltage of a transistor defined as the voltage where the transconductance gm is maximum, i.e., when the first derivative of the current is maximum or when the second derivative is zero.
+The method is based on the second-derivative method from Wong HS, White MH, Krutsick TJ, Booth RV. "Modeling of transconductance degradation and extraction of threshold voltage in thin oxide MOSFET’s." Solid-State Electron (1987).
+The transistor should be put in linear region (VDS &lt;= VGS-Vth), i.e., with low VDS bias.
+The implementation is based on central finite difference to limit the impact of noise for the determination of the threshold voltage.
+The numerical derivative is done on accuracy + 1 points, but accuracy should be even</p>
+<p>args:
+- ids (scalar): the source to drain current of the transistor (nmos or pmos)
+- vgs (scalar): the voltage between the gate and the source of the transistor (nmos or pmos)
+- accuracy (integer): related to the number of points taken for the finite difference. For central finite difference, the number of points for a first order derivation is accuracy + 1 but accuracy should be even to guarantee a centered interval.</p>
+<p>return:
+- a tuple of two scalars with the threshold voltage found and the transconductance value found at this voltage</p></div>
+</dd>
+</dl>
+</section>
+<section>
+</section>
+</article>
+<nav id="sidebar">
+<div class="toc">
+<ul></ul>
+</div>
+<ul id="index">
+<li><h3>Super-module</h3>
+<ul>
+<li><code><a title="dopes.data_analysis" href="index.html">dopes.data_analysis</a></code></li>
+</ul>
+</li>
+<li><h3><a href="#header-functions">Functions</a></h3>
+<ul class="">
+<li><code><a title="dopes.data_analysis.transistor.mos_transistor_current" href="#dopes.data_analysis.transistor.mos_transistor_current">mos_transistor_current</a></code></li>
+<li><code><a title="dopes.data_analysis.transistor.threshold_voltage_extraction" href="#dopes.data_analysis.transistor.threshold_voltage_extraction">threshold_voltage_extraction</a></code></li>
+</ul>
+</li>
+</ul>
+</nav>
+</main>
+<footer id="footer">
+<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
+</footer>
+</body>
+</html>
diff --git a/html/equipment_control/cm110.html b/html/equipment_control/cm110.html
new file mode 100644
index 0000000000000000000000000000000000000000..270853070658cf643f1ed0bb36c48bc13b9aee6c
--- /dev/null
+++ b/html/equipment_control/cm110.html
@@ -0,0 +1,268 @@
+<!doctype html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
+<meta name="generator" content="pdoc3 0.11.6">
+<title>dopes.equipment_control.cm110 API documentation</title>
+<meta name="description" content="">
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/typography.min.css" integrity="sha512-Y1DYSb995BAfxobCkKepB1BqJJTPrOp3zPL74AWFugHHmmdcvO+C48WLrUOlhGMc0QG7AE3f7gmvvcrmX2fDoA==" crossorigin>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css" crossorigin>
+<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:1.5em;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:2em 0 .50em 0}h3{font-size:1.4em;margin:1.6em 0 .7em 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .2s ease-in-out}a:visited{color:#503}a:hover{color:#b62}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900;font-weight:bold}pre code{font-size:.8em;line-height:1.4em;padding:1em;display:block}code{background:#f3f3f3;font-family:"DejaVu Sans Mono",monospace;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source > summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible;min-width:max-content}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em 1em;margin:1em 0}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
+<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul ul{padding-left:1em}.toc > ul > li{margin-top:.5em}}</style>
+<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
+<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js" integrity="sha512-D9gUyxqja7hBtkWpPWGt9wfbfaMGVt9gnyCvYa+jojwwPHLCzUm5i8rpk7vD7wNee9bA35eYIjobYPaQuKS1MQ==" crossorigin></script>
+<script>window.addEventListener('DOMContentLoaded', () => {
+hljs.configure({languages: ['bash', 'css', 'diff', 'graphql', 'ini', 'javascript', 'json', 'plaintext', 'python', 'python-repl', 'rust', 'shell', 'sql', 'typescript', 'xml', 'yaml']});
+hljs.highlightAll();
+/* Collapse source docstrings */
+setTimeout(() => {
+[...document.querySelectorAll('.hljs.language-python > .hljs-string')]
+.filter(el => el.innerHTML.length > 200 && ['"""', "'''"].includes(el.innerHTML.substring(0, 3)))
+.forEach(el => {
+let d = document.createElement('details');
+d.classList.add('hljs-string');
+d.innerHTML = '<summary>"""</summary>' + el.innerHTML.substring(3);
+el.replaceWith(d);
+});
+}, 100);
+})</script>
+</head>
+<body>
+<main>
+<article id="content">
+<header>
+<h1 class="title">Module <code>dopes.equipment_control.cm110</code></h1>
+</header>
+<section id="section-intro">
+</section>
+<section>
+</section>
+<section>
+</section>
+<section>
+</section>
+<section>
+<h2 class="section-title" id="header-classes">Classes</h2>
+<dl>
+<dt id="dopes.equipment_control.cm110.cm110"><code class="flex name class">
+<span>class <span class="ident">cm110</span></span>
+<span>(</span><span>port)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">class cm110(equipment.equipment):
+    
+    &#34;&#34;&#34;Class to control CM110 monochromator&#34;&#34;&#34;
+    model=&#34;CM110&#34;
+    company=&#34;Spectral Product&#34;
+    url=&#34;https://www.spectralproducts.com/CM110&#34;
+
+    def __init__(self,port):
+        &#34;&#34;&#34; Function called when an instance of the class is created
+        
+            args:
+                - port (string) : the computer port to which the equipment is connected        
+        &#34;&#34;&#34;
+        self.serial_resource = serial.Serial(
+            port=port,
+            baudrate=9600,
+            parity=serial.PARITY_NONE,
+            stopbits=serial.STOPBITS_ONE,
+            bytesize=serial.EIGHTBITS
+        )
+
+
+    def initialize(self,grating_number=1,waiting_time=30):
+        &#34;&#34;&#34; Function to initialize the CM110
+        
+            args:
+                - grating_number (int) : select the grating (Grating 1 : AG2400-00240-303 (2400 G/mm and 180 nm - 680 nm) and Grating 2 : AG1200-00750-303 (1200 G/mm and 480 nm - 1500 nm))
+                - waiting_time (int) : waiting time in seconds after changing the grating and reset to the initial position
+                
+        &#34;&#34;&#34;
+        reset=[255,255,255] 
+        
+        self.serial_resource.write(serial.to_bytes([26,grating_number]))
+        time.sleep(waiting_time)
+        self.serial_resource.write(serial.to_bytes(reset))
+        time.sleep(waiting_time)
+        
+    def set_wavelength(self, wavelength,waiting_time=5):
+        &#34;&#34;&#34; Function to set the wavelength of the monochromator
+        
+            args:
+                - wavelength (scalar) : targeted wavelength in nm
+                - waiting_time : waiting time in seconds to let the grating of the monochromator reach the targeted wavelength
+        &#34;&#34;&#34;
+        set_position = [16,int((wavelength-wavelength%256)/256),wavelength%256] # Goto Position : 1000 -&gt; 0x3E8 -&gt; 3 and 232 
+        self.serial_resource.write(serial.to_bytes(set_position))
+        time.sleep(waiting_time)
+        
+    def select_grating(self, grating_number,waiting_time=30):
+        &#34;&#34;&#34; Function to select the gratin
+                - grating_number (int) : select the grating (Grating 1 : AG2400-00240-303 (2400 G/mm and 180 nm - 680 nm) and Grating 2 : AG1200-00750-303 (1200 G/mm and 480 nm - 1500 nm))
+                - waiting_time (int) : waiting time in seconds after changing the grating and reset to the initial position 
+        &#34;&#34;&#34;
+        self.serial_resource.write(serial.to_bytes([26,grating_number]))
+        time.sleep(waiting_time)
+
+    def close_connection(self):
+        &#34;&#34;&#34; Function to close the  serial connection with the equipment &#34;&#34;&#34;
+        self.serial_resource.close()</code></pre>
+</details>
+<div class="desc"><p>Class to control CM110 monochromator</p>
+<p>Function called when an instance of the class is created</p>
+<p>args:
+- port (string) : the computer port to which the equipment is connected</p></div>
+<h3>Ancestors</h3>
+<ul class="hlist">
+<li>equipment_control.equipment.equipment</li>
+</ul>
+<h3>Class variables</h3>
+<dl>
+<dt id="dopes.equipment_control.cm110.cm110.company"><code class="name">var <span class="ident">company</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="dopes.equipment_control.cm110.cm110.model"><code class="name">var <span class="ident">model</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="dopes.equipment_control.cm110.cm110.url"><code class="name">var <span class="ident">url</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+</dl>
+<h3>Methods</h3>
+<dl>
+<dt id="dopes.equipment_control.cm110.cm110.close_connection"><code class="name flex">
+<span>def <span class="ident">close_connection</span></span>(<span>self)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def close_connection(self):
+    &#34;&#34;&#34; Function to close the  serial connection with the equipment &#34;&#34;&#34;
+    self.serial_resource.close()</code></pre>
+</details>
+<div class="desc"><p>Function to close the
+serial connection with the equipment</p></div>
+</dd>
+<dt id="dopes.equipment_control.cm110.cm110.initialize"><code class="name flex">
+<span>def <span class="ident">initialize</span></span>(<span>self, grating_number=1, waiting_time=30)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def initialize(self,grating_number=1,waiting_time=30):
+    &#34;&#34;&#34; Function to initialize the CM110
+    
+        args:
+            - grating_number (int) : select the grating (Grating 1 : AG2400-00240-303 (2400 G/mm and 180 nm - 680 nm) and Grating 2 : AG1200-00750-303 (1200 G/mm and 480 nm - 1500 nm))
+            - waiting_time (int) : waiting time in seconds after changing the grating and reset to the initial position
+            
+    &#34;&#34;&#34;
+    reset=[255,255,255] 
+    
+    self.serial_resource.write(serial.to_bytes([26,grating_number]))
+    time.sleep(waiting_time)
+    self.serial_resource.write(serial.to_bytes(reset))
+    time.sleep(waiting_time)</code></pre>
+</details>
+<div class="desc"><p>Function to initialize the CM110</p>
+<p>args:
+- grating_number (int) : select the grating (Grating 1 : AG2400-00240-303 (2400 G/mm and 180 nm - 680 nm) and Grating 2 : AG1200-00750-303 (1200 G/mm and 480 nm - 1500 nm))
+- waiting_time (int) : waiting time in seconds after changing the grating and reset to the initial position</p></div>
+</dd>
+<dt id="dopes.equipment_control.cm110.cm110.select_grating"><code class="name flex">
+<span>def <span class="ident">select_grating</span></span>(<span>self, grating_number, waiting_time=30)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def select_grating(self, grating_number,waiting_time=30):
+    &#34;&#34;&#34; Function to select the gratin
+            - grating_number (int) : select the grating (Grating 1 : AG2400-00240-303 (2400 G/mm and 180 nm - 680 nm) and Grating 2 : AG1200-00750-303 (1200 G/mm and 480 nm - 1500 nm))
+            - waiting_time (int) : waiting time in seconds after changing the grating and reset to the initial position 
+    &#34;&#34;&#34;
+    self.serial_resource.write(serial.to_bytes([26,grating_number]))
+    time.sleep(waiting_time)</code></pre>
+</details>
+<div class="desc"><p>Function to select the gratin
+- grating_number (int) : select the grating (Grating 1 : AG2400-00240-303 (2400 G/mm and 180 nm - 680 nm) and Grating 2 : AG1200-00750-303 (1200 G/mm and 480 nm - 1500 nm))
+- waiting_time (int) : waiting time in seconds after changing the grating and reset to the initial position</p></div>
+</dd>
+<dt id="dopes.equipment_control.cm110.cm110.set_wavelength"><code class="name flex">
+<span>def <span class="ident">set_wavelength</span></span>(<span>self, wavelength, waiting_time=5)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def set_wavelength(self, wavelength,waiting_time=5):
+    &#34;&#34;&#34; Function to set the wavelength of the monochromator
+    
+        args:
+            - wavelength (scalar) : targeted wavelength in nm
+            - waiting_time : waiting time in seconds to let the grating of the monochromator reach the targeted wavelength
+    &#34;&#34;&#34;
+    set_position = [16,int((wavelength-wavelength%256)/256),wavelength%256] # Goto Position : 1000 -&gt; 0x3E8 -&gt; 3 and 232 
+    self.serial_resource.write(serial.to_bytes(set_position))
+    time.sleep(waiting_time)</code></pre>
+</details>
+<div class="desc"><p>Function to set the wavelength of the monochromator</p>
+<p>args:
+- wavelength (scalar) : targeted wavelength in nm
+- waiting_time : waiting time in seconds to let the grating of the monochromator reach the targeted wavelength</p></div>
+</dd>
+</dl>
+</dd>
+</dl>
+</section>
+</article>
+<nav id="sidebar">
+<div class="toc">
+<ul></ul>
+</div>
+<ul id="index">
+<li><h3>Super-module</h3>
+<ul>
+<li><code><a title="dopes.equipment_control" href="index.html">dopes.equipment_control</a></code></li>
+</ul>
+</li>
+<li><h3><a href="#header-classes">Classes</a></h3>
+<ul>
+<li>
+<h4><code><a title="dopes.equipment_control.cm110.cm110" href="#dopes.equipment_control.cm110.cm110">cm110</a></code></h4>
+<ul class="two-column">
+<li><code><a title="dopes.equipment_control.cm110.cm110.close_connection" href="#dopes.equipment_control.cm110.cm110.close_connection">close_connection</a></code></li>
+<li><code><a title="dopes.equipment_control.cm110.cm110.company" href="#dopes.equipment_control.cm110.cm110.company">company</a></code></li>
+<li><code><a title="dopes.equipment_control.cm110.cm110.initialize" href="#dopes.equipment_control.cm110.cm110.initialize">initialize</a></code></li>
+<li><code><a title="dopes.equipment_control.cm110.cm110.model" href="#dopes.equipment_control.cm110.cm110.model">model</a></code></li>
+<li><code><a title="dopes.equipment_control.cm110.cm110.select_grating" href="#dopes.equipment_control.cm110.cm110.select_grating">select_grating</a></code></li>
+<li><code><a title="dopes.equipment_control.cm110.cm110.set_wavelength" href="#dopes.equipment_control.cm110.cm110.set_wavelength">set_wavelength</a></code></li>
+<li><code><a title="dopes.equipment_control.cm110.cm110.url" href="#dopes.equipment_control.cm110.cm110.url">url</a></code></li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+</nav>
+</main>
+<footer id="footer">
+<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
+</footer>
+</body>
+</html>
diff --git a/html/equipment_control/dmm.html b/html/equipment_control/dmm.html
new file mode 100644
index 0000000000000000000000000000000000000000..666586f8f0bcc498db6d5c4d876aaecfaf13e485
--- /dev/null
+++ b/html/equipment_control/dmm.html
@@ -0,0 +1,321 @@
+<!doctype html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
+<meta name="generator" content="pdoc3 0.11.6">
+<title>dopes.equipment_control.dmm API documentation</title>
+<meta name="description" content="">
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/typography.min.css" integrity="sha512-Y1DYSb995BAfxobCkKepB1BqJJTPrOp3zPL74AWFugHHmmdcvO+C48WLrUOlhGMc0QG7AE3f7gmvvcrmX2fDoA==" crossorigin>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css" crossorigin>
+<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:1.5em;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:2em 0 .50em 0}h3{font-size:1.4em;margin:1.6em 0 .7em 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .2s ease-in-out}a:visited{color:#503}a:hover{color:#b62}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900;font-weight:bold}pre code{font-size:.8em;line-height:1.4em;padding:1em;display:block}code{background:#f3f3f3;font-family:"DejaVu Sans Mono",monospace;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source > summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible;min-width:max-content}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em 1em;margin:1em 0}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
+<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul ul{padding-left:1em}.toc > ul > li{margin-top:.5em}}</style>
+<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
+<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js" integrity="sha512-D9gUyxqja7hBtkWpPWGt9wfbfaMGVt9gnyCvYa+jojwwPHLCzUm5i8rpk7vD7wNee9bA35eYIjobYPaQuKS1MQ==" crossorigin></script>
+<script>window.addEventListener('DOMContentLoaded', () => {
+hljs.configure({languages: ['bash', 'css', 'diff', 'graphql', 'ini', 'javascript', 'json', 'plaintext', 'python', 'python-repl', 'rust', 'shell', 'sql', 'typescript', 'xml', 'yaml']});
+hljs.highlightAll();
+/* Collapse source docstrings */
+setTimeout(() => {
+[...document.querySelectorAll('.hljs.language-python > .hljs-string')]
+.filter(el => el.innerHTML.length > 200 && ['"""', "'''"].includes(el.innerHTML.substring(0, 3)))
+.forEach(el => {
+let d = document.createElement('details');
+d.classList.add('hljs-string');
+d.innerHTML = '<summary>"""</summary>' + el.innerHTML.substring(3);
+el.replaceWith(d);
+});
+}, 100);
+})</script>
+</head>
+<body>
+<main>
+<article id="content">
+<header>
+<h1 class="title">Module <code>dopes.equipment_control.dmm</code></h1>
+</header>
+<section id="section-intro">
+</section>
+<section>
+</section>
+<section>
+</section>
+<section>
+</section>
+<section>
+<h2 class="section-title" id="header-classes">Classes</h2>
+<dl>
+<dt id="dopes.equipment_control.dmm.dmm"><code class="flex name class">
+<span>class <span class="ident">dmm</span></span>
+<span>(</span><span>address, rm=None, timeout=10000.0)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">class dmm(equipment.equipment):
+    
+    &#34;&#34;&#34;Class to control digital multimeter&#34;&#34;&#34;
+    model=&#34;DMM7510, DMM6500 or K2000&#34;
+    company=&#34;Keithley&#34;
+    url=&#34;https://www.tek.com/en/products/keithley/benchtop-digital-multimeter&#34;
+
+    def initialize(self, mode, autozero=True, nplc=1,timeout=10e3,digits=6,continuous_trigger=False,disp_enable=True,k2000=False):
+        
+        &#34;&#34;&#34; Function to initialize the K2400 SMU  with the desired settings
+        
+            args:
+                - mode (string) : measurement mode of the multimeter (&#34;current&#34;, &#34;voltage&#34;, &#34;resistance&#34; or &#34;4 wires&#34;)
+                - autozero (boolean) : if true, enable autozero of the SMU
+                - nplc (scalar) : set NPLC to set the integration time for the measurement. For a NPLC of 1, the integration period would be 1/50 (for 50Hz line power) which is 20 msec
+                - digits (int) : display resolution in number of bits
+                - continuous_trigger (boolean) : if true, the display of the equipment does not freeze after a measurement. When disabled, the instrument operates at a higher speed
+                - disp_enable (boolean) : if true, enable the front panel display circuitry. When disabled, the instrument operates at a higher speed
+                - k2000 (boolean) : if true send instruction formatted for k2000 multimeter, otherwise send instruction for more recent multimeter such as DMM6500 and DMM7510
+        &#34;&#34;&#34;
+        
+
+        self.continuous_trigger=continuous_trigger
+        self.k2000=k2000
+        self.pyvisa_resource.write(&#34;*RST&#34;)
+        # self.set_connection_parameter_dic({&#34;write_termination&#34;:&#39;\r\n&#39;,&#34;read_termination&#34;:&#39;\r\n&#39;,&#34;send_end&#34;:True})
+
+        mode_name={&#34;voltage&#34;:&#34;VOLT&#34;, &#34;current&#34;:&#34;CURR&#34;, &#34;resistance&#34;:&#34;RES&#34;, &#34;4wires&#34;:&#34;FRES&#34;, &#34;4 wires&#34;:&#34;FRES&#34;}        
+
+        self.pyvisa_resource.write(&#34;:SENS:FUNC &#39;%s&#39;&#34;%mode_name[mode])           
+
+        self.pyvisa_resource.write(&#34;:SENS:%s:RANG:AUTO ON&#34;%mode_name[mode])     # set automatic range
+
+
+        if k2000:
+            self.pyvisa_resource.write(&#34;:SENS:%s:DIG %d&#34;%(mode_name[mode],digits))    
+            if disp_enable:
+                self.pyvisa_resource.write(&#34;:DISP:ENAB ON&#34;)     # This command is used to enable and disable the front panel display circuitry. When disabled, the instrument operates at a higher speed.
+            else:
+                 self.pyvisa_resource.write(&#34;:DISP:ENAB OFF&#34;)
+
+            if continuous_trigger:
+                self.pyvisa_resource.write(&#34;INIT:CONT ON&#34;)     # able continuous triggering
+            else:
+                self.pyvisa_resource.write(&#34;INIT:CONT OFF&#34;)     
+
+        else:
+            if disp_enable:
+                self.pyvisa_resource.write(&#34;:DISP:LIGHT:STAT ON100&#34;)     # This command is used to enable and disable the front panel display circuitry. When disabled, the instrument operates at a higher speed.
+            else:
+                 self.pyvisa_resource.write(&#34;:DISP:LIGHT:STAT OFF&#34;)
+
+            self.pyvisa_resource.write(&#34;:DISP:%s:DIG %d&#34;%(mode_name[mode],digits))   
+            self.pyvisa_resource.write(&#34;:SENS:%s:NPLC %d&#34;%(mode_name[mode],nplc))           # set NPLC. For a PLC of 1, the integration period would be 1/50 (for 50Hz line power) which is 20 msec
+           
+            if autozero:
+                self.pyvisa_resource.write(&#34;:%s:AZER ON&#34;%mode_name[mode])          # enable auto-zero
+            else:
+                self.pyvisa_resource.write(&#34;:%s:AZER OFF&#34;%mode_name[mode])
+
+            if continuous_trigger:
+                self.pyvisa_resource.write(&#34;TRIG:CONT REST&#34;)     # able continuous triggering
+            else:
+                self.pyvisa_resource.write(&#34;TRIG:CONT OFF&#34;)
+
+    def read_single(self):
+        &#34;&#34;&#34; Function to read a single measurement data. The output is turn off at the end of the measurement only if continuous_trigger and output_state have been initialized as false and off
+        
+            return:
+                - data (float) : float with the value of the measurement
+        &#34;&#34;&#34;
+        
+        if self.k2000:
+            if self.continuous_trigger:
+                data=self.pyvisa_resource.query(&#34;FETCH?&#34;)
+            else:
+                data=self.pyvisa_resource.query(&#34;READ?&#34;)
+        else:
+            if self.continuous_trigger:
+                self.pyvisa_resource.write(&#34;TRIG:CONT OFF&#34;)
+                time.sleep(0.1)
+                data=float(self.pyvisa_resource.query(&#34;MEAS?&#34;))
+                self.pyvisa_resource.write(&#34;TRIG:CONT REST&#34;)
+            else:
+                data=float(self.pyvisa_resource.query(&#34;MEAS?&#34;))
+
+        return data</code></pre>
+</details>
+<div class="desc"><p>Class to control digital multimeter</p>
+<p>Function called when an instance of the class is created</p>
+<p>args:
+- address (string) : the address of the equipment to be connected
+- rm (pyvisa object) : the pyvisa resource manager used to set the communication with the equipment
+- timeout (scalar) : the timeout set for the communication with the equipment</p></div>
+<h3>Ancestors</h3>
+<ul class="hlist">
+<li>equipment_control.equipment.equipment</li>
+</ul>
+<h3>Class variables</h3>
+<dl>
+<dt id="dopes.equipment_control.dmm.dmm.company"><code class="name">var <span class="ident">company</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="dopes.equipment_control.dmm.dmm.model"><code class="name">var <span class="ident">model</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="dopes.equipment_control.dmm.dmm.url"><code class="name">var <span class="ident">url</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+</dl>
+<h3>Methods</h3>
+<dl>
+<dt id="dopes.equipment_control.dmm.dmm.initialize"><code class="name flex">
+<span>def <span class="ident">initialize</span></span>(<span>self,<br>mode,<br>autozero=True,<br>nplc=1,<br>timeout=10000.0,<br>digits=6,<br>continuous_trigger=False,<br>disp_enable=True,<br>k2000=False)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def initialize(self, mode, autozero=True, nplc=1,timeout=10e3,digits=6,continuous_trigger=False,disp_enable=True,k2000=False):
+    
+    &#34;&#34;&#34; Function to initialize the K2400 SMU  with the desired settings
+    
+        args:
+            - mode (string) : measurement mode of the multimeter (&#34;current&#34;, &#34;voltage&#34;, &#34;resistance&#34; or &#34;4 wires&#34;)
+            - autozero (boolean) : if true, enable autozero of the SMU
+            - nplc (scalar) : set NPLC to set the integration time for the measurement. For a NPLC of 1, the integration period would be 1/50 (for 50Hz line power) which is 20 msec
+            - digits (int) : display resolution in number of bits
+            - continuous_trigger (boolean) : if true, the display of the equipment does not freeze after a measurement. When disabled, the instrument operates at a higher speed
+            - disp_enable (boolean) : if true, enable the front panel display circuitry. When disabled, the instrument operates at a higher speed
+            - k2000 (boolean) : if true send instruction formatted for k2000 multimeter, otherwise send instruction for more recent multimeter such as DMM6500 and DMM7510
+    &#34;&#34;&#34;
+    
+
+    self.continuous_trigger=continuous_trigger
+    self.k2000=k2000
+    self.pyvisa_resource.write(&#34;*RST&#34;)
+    # self.set_connection_parameter_dic({&#34;write_termination&#34;:&#39;\r\n&#39;,&#34;read_termination&#34;:&#39;\r\n&#39;,&#34;send_end&#34;:True})
+
+    mode_name={&#34;voltage&#34;:&#34;VOLT&#34;, &#34;current&#34;:&#34;CURR&#34;, &#34;resistance&#34;:&#34;RES&#34;, &#34;4wires&#34;:&#34;FRES&#34;, &#34;4 wires&#34;:&#34;FRES&#34;}        
+
+    self.pyvisa_resource.write(&#34;:SENS:FUNC &#39;%s&#39;&#34;%mode_name[mode])           
+
+    self.pyvisa_resource.write(&#34;:SENS:%s:RANG:AUTO ON&#34;%mode_name[mode])     # set automatic range
+
+
+    if k2000:
+        self.pyvisa_resource.write(&#34;:SENS:%s:DIG %d&#34;%(mode_name[mode],digits))    
+        if disp_enable:
+            self.pyvisa_resource.write(&#34;:DISP:ENAB ON&#34;)     # This command is used to enable and disable the front panel display circuitry. When disabled, the instrument operates at a higher speed.
+        else:
+             self.pyvisa_resource.write(&#34;:DISP:ENAB OFF&#34;)
+
+        if continuous_trigger:
+            self.pyvisa_resource.write(&#34;INIT:CONT ON&#34;)     # able continuous triggering
+        else:
+            self.pyvisa_resource.write(&#34;INIT:CONT OFF&#34;)     
+
+    else:
+        if disp_enable:
+            self.pyvisa_resource.write(&#34;:DISP:LIGHT:STAT ON100&#34;)     # This command is used to enable and disable the front panel display circuitry. When disabled, the instrument operates at a higher speed.
+        else:
+             self.pyvisa_resource.write(&#34;:DISP:LIGHT:STAT OFF&#34;)
+
+        self.pyvisa_resource.write(&#34;:DISP:%s:DIG %d&#34;%(mode_name[mode],digits))   
+        self.pyvisa_resource.write(&#34;:SENS:%s:NPLC %d&#34;%(mode_name[mode],nplc))           # set NPLC. For a PLC of 1, the integration period would be 1/50 (for 50Hz line power) which is 20 msec
+       
+        if autozero:
+            self.pyvisa_resource.write(&#34;:%s:AZER ON&#34;%mode_name[mode])          # enable auto-zero
+        else:
+            self.pyvisa_resource.write(&#34;:%s:AZER OFF&#34;%mode_name[mode])
+
+        if continuous_trigger:
+            self.pyvisa_resource.write(&#34;TRIG:CONT REST&#34;)     # able continuous triggering
+        else:
+            self.pyvisa_resource.write(&#34;TRIG:CONT OFF&#34;)</code></pre>
+</details>
+<div class="desc"><p>Function to initialize the K2400 SMU
+with the desired settings</p>
+<p>args:
+- mode (string) : measurement mode of the multimeter ("current", "voltage", "resistance" or "4 wires")
+- autozero (boolean) : if true, enable autozero of the SMU
+- nplc (scalar) : set NPLC to set the integration time for the measurement. For a NPLC of 1, the integration period would be 1/50 (for 50Hz line power) which is 20 msec
+- digits (int) : display resolution in number of bits
+- continuous_trigger (boolean) : if true, the display of the equipment does not freeze after a measurement. When disabled, the instrument operates at a higher speed
+- disp_enable (boolean) : if true, enable the front panel display circuitry. When disabled, the instrument operates at a higher speed
+- k2000 (boolean) : if true send instruction formatted for k2000 multimeter, otherwise send instruction for more recent multimeter such as DMM6500 and DMM7510</p></div>
+</dd>
+<dt id="dopes.equipment_control.dmm.dmm.read_single"><code class="name flex">
+<span>def <span class="ident">read_single</span></span>(<span>self)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def read_single(self):
+    &#34;&#34;&#34; Function to read a single measurement data. The output is turn off at the end of the measurement only if continuous_trigger and output_state have been initialized as false and off
+    
+        return:
+            - data (float) : float with the value of the measurement
+    &#34;&#34;&#34;
+    
+    if self.k2000:
+        if self.continuous_trigger:
+            data=self.pyvisa_resource.query(&#34;FETCH?&#34;)
+        else:
+            data=self.pyvisa_resource.query(&#34;READ?&#34;)
+    else:
+        if self.continuous_trigger:
+            self.pyvisa_resource.write(&#34;TRIG:CONT OFF&#34;)
+            time.sleep(0.1)
+            data=float(self.pyvisa_resource.query(&#34;MEAS?&#34;))
+            self.pyvisa_resource.write(&#34;TRIG:CONT REST&#34;)
+        else:
+            data=float(self.pyvisa_resource.query(&#34;MEAS?&#34;))
+
+    return data</code></pre>
+</details>
+<div class="desc"><p>Function to read a single measurement data. The output is turn off at the end of the measurement only if continuous_trigger and output_state have been initialized as false and off</p>
+<p>return:
+- data (float) : float with the value of the measurement</p></div>
+</dd>
+</dl>
+</dd>
+</dl>
+</section>
+</article>
+<nav id="sidebar">
+<div class="toc">
+<ul></ul>
+</div>
+<ul id="index">
+<li><h3>Super-module</h3>
+<ul>
+<li><code><a title="dopes.equipment_control" href="index.html">dopes.equipment_control</a></code></li>
+</ul>
+</li>
+<li><h3><a href="#header-classes">Classes</a></h3>
+<ul>
+<li>
+<h4><code><a title="dopes.equipment_control.dmm.dmm" href="#dopes.equipment_control.dmm.dmm">dmm</a></code></h4>
+<ul class="">
+<li><code><a title="dopes.equipment_control.dmm.dmm.company" href="#dopes.equipment_control.dmm.dmm.company">company</a></code></li>
+<li><code><a title="dopes.equipment_control.dmm.dmm.initialize" href="#dopes.equipment_control.dmm.dmm.initialize">initialize</a></code></li>
+<li><code><a title="dopes.equipment_control.dmm.dmm.model" href="#dopes.equipment_control.dmm.dmm.model">model</a></code></li>
+<li><code><a title="dopes.equipment_control.dmm.dmm.read_single" href="#dopes.equipment_control.dmm.dmm.read_single">read_single</a></code></li>
+<li><code><a title="dopes.equipment_control.dmm.dmm.url" href="#dopes.equipment_control.dmm.dmm.url">url</a></code></li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+</nav>
+</main>
+<footer id="footer">
+<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
+</footer>
+</body>
+</html>
diff --git a/html/equipment_control/equipment.html b/html/equipment_control/equipment.html
new file mode 100644
index 0000000000000000000000000000000000000000..974f59773f928c794cb0162b0b7e1ab6f49d4830
--- /dev/null
+++ b/html/equipment_control/equipment.html
@@ -0,0 +1,399 @@
+<!doctype html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
+<meta name="generator" content="pdoc3 0.11.6">
+<title>dopes.equipment_control.equipment API documentation</title>
+<meta name="description" content="">
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/typography.min.css" integrity="sha512-Y1DYSb995BAfxobCkKepB1BqJJTPrOp3zPL74AWFugHHmmdcvO+C48WLrUOlhGMc0QG7AE3f7gmvvcrmX2fDoA==" crossorigin>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css" crossorigin>
+<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:1.5em;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:2em 0 .50em 0}h3{font-size:1.4em;margin:1.6em 0 .7em 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .2s ease-in-out}a:visited{color:#503}a:hover{color:#b62}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900;font-weight:bold}pre code{font-size:.8em;line-height:1.4em;padding:1em;display:block}code{background:#f3f3f3;font-family:"DejaVu Sans Mono",monospace;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source > summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible;min-width:max-content}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em 1em;margin:1em 0}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
+<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul ul{padding-left:1em}.toc > ul > li{margin-top:.5em}}</style>
+<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
+<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js" integrity="sha512-D9gUyxqja7hBtkWpPWGt9wfbfaMGVt9gnyCvYa+jojwwPHLCzUm5i8rpk7vD7wNee9bA35eYIjobYPaQuKS1MQ==" crossorigin></script>
+<script>window.addEventListener('DOMContentLoaded', () => {
+hljs.configure({languages: ['bash', 'css', 'diff', 'graphql', 'ini', 'javascript', 'json', 'plaintext', 'python', 'python-repl', 'rust', 'shell', 'sql', 'typescript', 'xml', 'yaml']});
+hljs.highlightAll();
+/* Collapse source docstrings */
+setTimeout(() => {
+[...document.querySelectorAll('.hljs.language-python > .hljs-string')]
+.filter(el => el.innerHTML.length > 200 && ['"""', "'''"].includes(el.innerHTML.substring(0, 3)))
+.forEach(el => {
+let d = document.createElement('details');
+d.classList.add('hljs-string');
+d.innerHTML = '<summary>"""</summary>' + el.innerHTML.substring(3);
+el.replaceWith(d);
+});
+}, 100);
+})</script>
+</head>
+<body>
+<main>
+<article id="content">
+<header>
+<h1 class="title">Module <code>dopes.equipment_control.equipment</code></h1>
+</header>
+<section id="section-intro">
+</section>
+<section>
+</section>
+<section>
+</section>
+<section>
+<h2 class="section-title" id="header-functions">Functions</h2>
+<dl>
+<dt id="dopes.equipment_control.equipment.available_connections"><code class="name flex">
+<span>def <span class="ident">available_connections</span></span>(<span>rm=None)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def available_connections(rm=None):
+    &#34;&#34;&#34; Function that return the list of resource connected to the computer &#34;&#34;&#34;
+    if rm==None:
+        rm = pyvisa.ResourceManager()    
+    return rm.list_resources()</code></pre>
+</details>
+<div class="desc"><p>Function that return the list of resource connected to the computer</p></div>
+</dd>
+<dt id="dopes.equipment_control.equipment.resource_manager"><code class="name flex">
+<span>def <span class="ident">resource_manager</span></span>(<span>)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def resource_manager():
+    &#34;&#34;&#34; Function that return a pyvisa resource manager to deal with resources connected to the computer &#34;&#34;&#34;
+
+    rm = pyvisa.ResourceManager()
+    return rm</code></pre>
+</details>
+<div class="desc"><p>Function that return a pyvisa resource manager to deal with resources connected to the computer</p></div>
+</dd>
+</dl>
+</section>
+<section>
+<h2 class="section-title" id="header-classes">Classes</h2>
+<dl>
+<dt id="dopes.equipment_control.equipment.equipment"><code class="flex name class">
+<span>class <span class="ident">equipment</span></span>
+<span>(</span><span>address, rm=None, timeout=10000.0)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">class equipment():
+
+    &#34;&#34;&#34; Parent class for all the equipment classes.&#34;&#34;&#34;
+    
+        
+    def __init__(self,address,rm=None,timeout=10e3):
+        &#34;&#34;&#34; Function called when an instance of the class is created
+        
+            args:
+                - address (string) : the address of the equipment to be connected
+                - rm (pyvisa object) : the pyvisa resource manager used to set the communication with the equipment
+                - timeout (scalar) : the timeout set for the communication with the equipment
+        
+        &#34;&#34;&#34;
+
+        if rm==None:
+            rm = pyvisa.ResourceManager()
+        self.pyvisa_resource = rm.open_resource(address)
+        self.set_connection_parameter(&#34;timeout&#34;,timeout)
+        
+    def set_connection_parameter(self,key,value):
+        &#34;&#34;&#34; Function to change a parameter of the communication with the equipment
+        
+            args:
+                - key (string) : the parameter to be modifier 
+                - value (scalar) : the value for the parameter
+        
+        &#34;&#34;&#34;
+        key_list=[&#34;timeout&#34;,&#34;write_termination&#34;,&#34;read_termination&#34;,&#34;send_end&#34;,&#34;baud_rate&#34;]
+        if key==&#34;timeout&#34;:
+            self.pyvisa_resource.timeout=value
+        elif key==&#34;write_termination&#34;:
+            self.pyvisa_resource.write_termination=value
+        elif key==&#34;read_termination&#34;:
+            self.pyvisa_resource.read_termination=value                    
+        elif key==&#34;send_end&#34;:
+            self.pyvisa_resource.send_end=value
+        elif key==&#34;baud_rate&#34;:
+            self.pyvisa_resource.baud_rate =value
+        else:
+            print(&#34;Parameter not valid. Valid parameter are %s&#34;%key_list)
+        
+            
+    def set_connection_parameter_dic(self,connection_parameter):
+        &#34;&#34;&#34; Function to change a parameter of the communication with the equipment
+        
+            args:
+                - connection_parameter (dictionary) = dictionary with key and value to be sent to function set_connection_parameter(key,value)
+        
+        &#34;&#34;&#34;
+        if isinstance(connection_parameter, dict):
+            for key, value in connection_parameter.items():
+                self.set_connection_parameter(key,value)
+        else:
+            print(&#34;Please provide a dictionnary as argument.&#34;)
+        
+        
+    def close_connection(self):
+        &#34;&#34;&#34; Function to close the connection with an equipment &#34;&#34;&#34;
+        self.pyvisa_resource.close()
+
+    def write_in_file(self,file_path,data,delimiter=&#34;,&#34;,overwrite=False,header=None,date=True, comment=&#34;#&#34;):
+        &#34;&#34;&#34; Function to write data in a file
+        
+            args:
+                - file_path (string) : path for the data file, including the filename with its extension
+                - data (scalar, list or array) : the data to be written in the file
+                - delimiter (char) : the delimiter to separate the column of the data
+                - overwrite (boolean) : if True overwrite the existing file if any, if False, append the data to the existing file if any
+                - header (string) : header to be written before the data
+                - date (boolean) : date to be written at the beginning of the file
+                - comment (char) : char to be written before the header and date to indicate non-data lines
+        
+        &#34;&#34;&#34;        
+        if file_path.split(&#34;.&#34;)[-1]==&#34;csv&#34;:
+            delimiter=&#34;,&#34;
+            
+        # Create file and header
+        if overwrite:
+            f = open(file_path, &#34;w&#34;)
+        else:
+            f = open(file_path, &#34;a&#34;)
+            
+        if date:
+            f.write(&#34;%s %s\n&#34;%(comment,datetime.datetime.now().strftime(&#34;%c&#34;)))
+        
+        if isinstance(header, str):
+            for line in header.split(&#34;\n&#34;):
+                f.write(comment+&#34; &#34;+line+&#34;\n&#34;)
+
+        
+        shape=np.shape(data)
+        if len(shape)==0:
+            f.write(&#34;%.6E\n&#34;%(data))
+        elif len(shape)==1:
+            for i in range(shape[0]):
+                if i==0:
+                    f.write(&#34;%.6E&#34;%(data[i]))
+                else:
+                    f.write(&#34;%s%.6E&#34;%(delimiter,data[i]))
+
+            f.write(&#34;\n&#34;)
+
+        elif len(shape)==2:
+            for i in range(shape[0]):
+                for j in range(shape[1]):
+                    if j==0:
+                        f.write(&#34;%.6E&#34;%(data[i,j]))
+                    else:
+                        f.write(&#34;%s%.6E&#34;%(delimiter,data[i,j]))
+                f.write(&#34;\n&#34;)                
+        f.close()</code></pre>
+</details>
+<div class="desc"><p>Parent class for all the equipment classes.</p>
+<p>Function called when an instance of the class is created</p>
+<p>args:
+- address (string) : the address of the equipment to be connected
+- rm (pyvisa object) : the pyvisa resource manager used to set the communication with the equipment
+- timeout (scalar) : the timeout set for the communication with the equipment</p></div>
+<h3>Methods</h3>
+<dl>
+<dt id="dopes.equipment_control.equipment.equipment.close_connection"><code class="name flex">
+<span>def <span class="ident">close_connection</span></span>(<span>self)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def close_connection(self):
+    &#34;&#34;&#34; Function to close the connection with an equipment &#34;&#34;&#34;
+    self.pyvisa_resource.close()</code></pre>
+</details>
+<div class="desc"><p>Function to close the connection with an equipment</p></div>
+</dd>
+<dt id="dopes.equipment_control.equipment.equipment.set_connection_parameter"><code class="name flex">
+<span>def <span class="ident">set_connection_parameter</span></span>(<span>self, key, value)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def set_connection_parameter(self,key,value):
+    &#34;&#34;&#34; Function to change a parameter of the communication with the equipment
+    
+        args:
+            - key (string) : the parameter to be modifier 
+            - value (scalar) : the value for the parameter
+    
+    &#34;&#34;&#34;
+    key_list=[&#34;timeout&#34;,&#34;write_termination&#34;,&#34;read_termination&#34;,&#34;send_end&#34;,&#34;baud_rate&#34;]
+    if key==&#34;timeout&#34;:
+        self.pyvisa_resource.timeout=value
+    elif key==&#34;write_termination&#34;:
+        self.pyvisa_resource.write_termination=value
+    elif key==&#34;read_termination&#34;:
+        self.pyvisa_resource.read_termination=value                    
+    elif key==&#34;send_end&#34;:
+        self.pyvisa_resource.send_end=value
+    elif key==&#34;baud_rate&#34;:
+        self.pyvisa_resource.baud_rate =value
+    else:
+        print(&#34;Parameter not valid. Valid parameter are %s&#34;%key_list)</code></pre>
+</details>
+<div class="desc"><p>Function to change a parameter of the communication with the equipment</p>
+<p>args:
+- key (string) : the parameter to be modifier
+- value (scalar) : the value for the parameter</p></div>
+</dd>
+<dt id="dopes.equipment_control.equipment.equipment.set_connection_parameter_dic"><code class="name flex">
+<span>def <span class="ident">set_connection_parameter_dic</span></span>(<span>self, connection_parameter)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def set_connection_parameter_dic(self,connection_parameter):
+    &#34;&#34;&#34; Function to change a parameter of the communication with the equipment
+    
+        args:
+            - connection_parameter (dictionary) = dictionary with key and value to be sent to function set_connection_parameter(key,value)
+    
+    &#34;&#34;&#34;
+    if isinstance(connection_parameter, dict):
+        for key, value in connection_parameter.items():
+            self.set_connection_parameter(key,value)
+    else:
+        print(&#34;Please provide a dictionnary as argument.&#34;)</code></pre>
+</details>
+<div class="desc"><p>Function to change a parameter of the communication with the equipment</p>
+<p>args:
+- connection_parameter (dictionary) = dictionary with key and value to be sent to function set_connection_parameter(key,value)</p></div>
+</dd>
+<dt id="dopes.equipment_control.equipment.equipment.write_in_file"><code class="name flex">
+<span>def <span class="ident">write_in_file</span></span>(<span>self,<br>file_path,<br>data,<br>delimiter=',',<br>overwrite=False,<br>header=None,<br>date=True,<br>comment='#')</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def write_in_file(self,file_path,data,delimiter=&#34;,&#34;,overwrite=False,header=None,date=True, comment=&#34;#&#34;):
+    &#34;&#34;&#34; Function to write data in a file
+    
+        args:
+            - file_path (string) : path for the data file, including the filename with its extension
+            - data (scalar, list or array) : the data to be written in the file
+            - delimiter (char) : the delimiter to separate the column of the data
+            - overwrite (boolean) : if True overwrite the existing file if any, if False, append the data to the existing file if any
+            - header (string) : header to be written before the data
+            - date (boolean) : date to be written at the beginning of the file
+            - comment (char) : char to be written before the header and date to indicate non-data lines
+    
+    &#34;&#34;&#34;        
+    if file_path.split(&#34;.&#34;)[-1]==&#34;csv&#34;:
+        delimiter=&#34;,&#34;
+        
+    # Create file and header
+    if overwrite:
+        f = open(file_path, &#34;w&#34;)
+    else:
+        f = open(file_path, &#34;a&#34;)
+        
+    if date:
+        f.write(&#34;%s %s\n&#34;%(comment,datetime.datetime.now().strftime(&#34;%c&#34;)))
+    
+    if isinstance(header, str):
+        for line in header.split(&#34;\n&#34;):
+            f.write(comment+&#34; &#34;+line+&#34;\n&#34;)
+
+    
+    shape=np.shape(data)
+    if len(shape)==0:
+        f.write(&#34;%.6E\n&#34;%(data))
+    elif len(shape)==1:
+        for i in range(shape[0]):
+            if i==0:
+                f.write(&#34;%.6E&#34;%(data[i]))
+            else:
+                f.write(&#34;%s%.6E&#34;%(delimiter,data[i]))
+
+        f.write(&#34;\n&#34;)
+
+    elif len(shape)==2:
+        for i in range(shape[0]):
+            for j in range(shape[1]):
+                if j==0:
+                    f.write(&#34;%.6E&#34;%(data[i,j]))
+                else:
+                    f.write(&#34;%s%.6E&#34;%(delimiter,data[i,j]))
+            f.write(&#34;\n&#34;)                
+    f.close()</code></pre>
+</details>
+<div class="desc"><p>Function to write data in a file</p>
+<p>args:
+- file_path (string) : path for the data file, including the filename with its extension
+- data (scalar, list or array) : the data to be written in the file
+- delimiter (char) : the delimiter to separate the column of the data
+- overwrite (boolean) : if True overwrite the existing file if any, if False, append the data to the existing file if any
+- header (string) : header to be written before the data
+- date (boolean) : date to be written at the beginning of the file
+- comment (char) : char to be written before the header and date to indicate non-data lines</p></div>
+</dd>
+</dl>
+</dd>
+</dl>
+</section>
+</article>
+<nav id="sidebar">
+<div class="toc">
+<ul></ul>
+</div>
+<ul id="index">
+<li><h3>Super-module</h3>
+<ul>
+<li><code><a title="dopes.equipment_control" href="index.html">dopes.equipment_control</a></code></li>
+</ul>
+</li>
+<li><h3><a href="#header-functions">Functions</a></h3>
+<ul class="">
+<li><code><a title="dopes.equipment_control.equipment.available_connections" href="#dopes.equipment_control.equipment.available_connections">available_connections</a></code></li>
+<li><code><a title="dopes.equipment_control.equipment.resource_manager" href="#dopes.equipment_control.equipment.resource_manager">resource_manager</a></code></li>
+</ul>
+</li>
+<li><h3><a href="#header-classes">Classes</a></h3>
+<ul>
+<li>
+<h4><code><a title="dopes.equipment_control.equipment.equipment" href="#dopes.equipment_control.equipment.equipment">equipment</a></code></h4>
+<ul class="">
+<li><code><a title="dopes.equipment_control.equipment.equipment.close_connection" href="#dopes.equipment_control.equipment.equipment.close_connection">close_connection</a></code></li>
+<li><code><a title="dopes.equipment_control.equipment.equipment.set_connection_parameter" href="#dopes.equipment_control.equipment.equipment.set_connection_parameter">set_connection_parameter</a></code></li>
+<li><code><a title="dopes.equipment_control.equipment.equipment.set_connection_parameter_dic" href="#dopes.equipment_control.equipment.equipment.set_connection_parameter_dic">set_connection_parameter_dic</a></code></li>
+<li><code><a title="dopes.equipment_control.equipment.equipment.write_in_file" href="#dopes.equipment_control.equipment.equipment.write_in_file">write_in_file</a></code></li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+</nav>
+</main>
+<footer id="footer">
+<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
+</footer>
+</body>
+</html>
diff --git a/html/equipment_control/hp4145.html b/html/equipment_control/hp4145.html
new file mode 100644
index 0000000000000000000000000000000000000000..feada1b0e02a5f12ec98da4846226cf5079dbb59
--- /dev/null
+++ b/html/equipment_control/hp4145.html
@@ -0,0 +1,551 @@
+<!doctype html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
+<meta name="generator" content="pdoc3 0.11.6">
+<title>dopes.equipment_control.hp4145 API documentation</title>
+<meta name="description" content="">
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/typography.min.css" integrity="sha512-Y1DYSb995BAfxobCkKepB1BqJJTPrOp3zPL74AWFugHHmmdcvO+C48WLrUOlhGMc0QG7AE3f7gmvvcrmX2fDoA==" crossorigin>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css" crossorigin>
+<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:1.5em;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:2em 0 .50em 0}h3{font-size:1.4em;margin:1.6em 0 .7em 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .2s ease-in-out}a:visited{color:#503}a:hover{color:#b62}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900;font-weight:bold}pre code{font-size:.8em;line-height:1.4em;padding:1em;display:block}code{background:#f3f3f3;font-family:"DejaVu Sans Mono",monospace;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source > summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible;min-width:max-content}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em 1em;margin:1em 0}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
+<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul ul{padding-left:1em}.toc > ul > li{margin-top:.5em}}</style>
+<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
+<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js" integrity="sha512-D9gUyxqja7hBtkWpPWGt9wfbfaMGVt9gnyCvYa+jojwwPHLCzUm5i8rpk7vD7wNee9bA35eYIjobYPaQuKS1MQ==" crossorigin></script>
+<script>window.addEventListener('DOMContentLoaded', () => {
+hljs.configure({languages: ['bash', 'css', 'diff', 'graphql', 'ini', 'javascript', 'json', 'plaintext', 'python', 'python-repl', 'rust', 'shell', 'sql', 'typescript', 'xml', 'yaml']});
+hljs.highlightAll();
+/* Collapse source docstrings */
+setTimeout(() => {
+[...document.querySelectorAll('.hljs.language-python > .hljs-string')]
+.filter(el => el.innerHTML.length > 200 && ['"""', "'''"].includes(el.innerHTML.substring(0, 3)))
+.forEach(el => {
+let d = document.createElement('details');
+d.classList.add('hljs-string');
+d.innerHTML = '<summary>"""</summary>' + el.innerHTML.substring(3);
+el.replaceWith(d);
+});
+}, 100);
+})</script>
+</head>
+<body>
+<main>
+<article id="content">
+<header>
+<h1 class="title">Module <code>dopes.equipment_control.hp4145</code></h1>
+</header>
+<section id="section-intro">
+</section>
+<section>
+</section>
+<section>
+</section>
+<section>
+</section>
+<section>
+<h2 class="section-title" id="header-classes">Classes</h2>
+<dl>
+<dt id="dopes.equipment_control.hp4145.hp4145"><code class="flex name class">
+<span>class <span class="ident">hp4145</span></span>
+<span>(</span><span>address, rm=None, timeout=10000.0)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">class hp4145(equipment.equipment):
+    
+    &#34;&#34;&#34;Class to control HP4145 semiconductor analyzer&#34;&#34;&#34;
+    
+    model=&#34;HP4145&#34;
+    company=&#34;Keysight&#34;
+    url=&#34;https://www.keysight.com/dk/en/assets/9018-07935/service-manuals/9018-07935.pdf&#34;
+    
+    def initialize(self, smu_type={&#34;SMU1&#34;:&#34;voltage&#34;,&#34;SMU2&#34;:&#34;voltage&#34;,&#34;SMU3&#34;:&#34;common&#34;,&#34;SMU4&#34;:&#34;common&#34;}, 
+                   smu_used={&#34;SMU1&#34;:&#34;on&#34;,&#34;SMU2&#34;:&#34;on&#34;,&#34;SMU3&#34;:&#34;on&#34;,&#34;SMU4&#34;:&#34;on&#34;}, 
+                   smu_master=1,smu_bias={&#34;SMU1&#34;:0,&#34;SMU2&#34;:0,&#34;SMU3&#34;:0,&#34;SMU4&#34;:0},
+                   smu_compliance={&#34;SMU1&#34;:1e-6,&#34;SMU2&#34;:1e-6,&#34;SMU3&#34;:1e-6,&#34;SMU4&#34;:1e-6},
+                   sweep_param={&#34;start&#34;:0,&#34;stop&#34;:0,&#34;step&#34;:0},sweep_type=&#34;linear&#34;,
+                   integration_mode=&#34;S&#34;,delay_time=0,hold_time=0):
+        
+        
+        &#34;&#34;&#34; Function to initialize the HP4145 equipment with the desired settings
+        
+            args:
+                - smu_type (dictionary) : dictionary indicated for each SMU (&#34;SMU1&#34;,&#34;SMU2&#34;,&#34;SMU3&#34; and &#34;SMU4&#34;) the bias type (&#34;voltage&#34;, &#34;current&#34; or &#34;common&#34;)
+                - smu_used (dictionary) : dictionary indicated for each SMU (&#34;SMU1&#34;,&#34;SMU2&#34;,&#34;SMU3&#34; and &#34;SMU4&#34;) if active or not (&#34;on&#34; or &#34;off&#34;)
+                - smu_master (int) : integer to indicate which SMU performs the sweep
+                - smu_bias (dictionary) : dictionary indicated for each SMU (&#34;SMU1&#34;,&#34;SMU2&#34;,&#34;SMU3&#34; and &#34;SMU4&#34;) the bias point (scalar)
+                - smu_compliance (dictionary) : dictionary indicated for each SMU (&#34;SMU1&#34;,&#34;SMU2&#34;,&#34;SMU3&#34; and &#34;SMU4&#34;) the compliance (scalar)
+                - sweep_param (dictionary) : dictionary indicated the starting bias (&#34;start&#34;), the stoping bias (&#34;stop&#34;) and step (&#34;step&#34;) of the sweep
+                - sweep_type (string) : string to indicate linear (&#34;linear&#34;) sweep or logarithmic (&#34;log&#34;) sweep
+                - integration_mode (string) : set the integration time parameter (&#34;S&#34; for short, &#34;M&#34; for medium and &#34;L&#34; for long)
+                - delay_time (scalar) : the time to wait between when the output voltage is set and when the measurement is made in a sweep
+                - hold_time (scalar) : hold time that delays the start of a sweep
+        &#34;&#34;&#34;
+        
+        self.smu_type=smu_type
+        self.sweep_type=sweep_type
+        self.smu_used=smu_used
+        self.smu_master=smu_master
+        self.sweep_param=sweep_param
+        self.smu_compliance=smu_compliance
+        self.smu_bias=smu_bias
+        self.integration_mode=integration_mode
+        self.delay_time=delay_time
+        self.hold_time=hold_time
+        
+        index_measurement_type={&#34;sweep&#34;:1, &#34;constant&#34;:3}
+        index_smu_type={&#34;voltage&#34;:1, &#34;current&#34;:2, &#34;common&#34;:3}
+        integration_dictionnary={&#34;S&#34;:&#34;IT1&#34;,&#34;M&#34;:&#34;IT2&#34;,&#34;L&#34;:&#34;IT3&#34;}
+        try:
+            self.pyvisa_resource.write(&#34;BC&#34;) # clear all buffer.
+            self.pyvisa_resource.write(&#34;DR1&#34;) # This command enables or disables service request for data ready when communications is set to GPIB.
+            self.pyvisa_resource.write(&#34;EC 1&#34;) # This command sets the condition to exit the test if compliance is reached.
+            
+                
+            self.pyvisa_resource.write(&#34;DE&#34;) # DE: Accesses SMU channel definition page.
+            
+            self.pyvisa_resource.write(&#34;CH%d, &#39;V%d&#39;, &#39;I%d&#39;, %d, %d&#34;%(smu_master,smu_master,smu_master,index_smu_type[smu_type[&#34;SMU%d&#34;%smu_master]],index_measurement_type[&#34;sweep&#34;])) # 1/2/3: voltage/current/Common 1/2/3: VAR1/VAR2/constant
+            
+            for smu_index in range(4):
+                if (smu_index+1!=smu_master) and smu_used[&#34;SMU%d&#34;%(smu_index+1)]==&#34;off&#34;:
+                    self.pyvisa_resource.write(&#34;CH%d&#34;%(smu_index+1)) 
+                elif (smu_index+1!=smu_master) and smu_used[&#34;SMU%d&#34;%(smu_index+1)]==&#34;on&#34;:
+                    self.pyvisa_resource.write(&#34;CH%d, &#39;V%d&#39;, &#39;I%d&#39;, %d, %d&#34;%(smu_index+1,smu_index+1,smu_index+1,index_smu_type[smu_type[&#34;SMU%d&#34;%(smu_index+1)]],index_measurement_type[&#34;constant&#34;])) 
+
+            self.pyvisa_resource.write(&#34;SS&#34;)# Accesses source setup page
+            if smu_type[&#34;SMU%d&#34;%smu_master]==&#34;voltage&#34;:
+                if sweep_type==&#34;linear&#34;:
+                    self.pyvisa_resource.write(&#34;VR1, %.6E, %.6E, %.6E, %.6E&#34;%(sweep_param[&#34;start&#34;],sweep_param[&#34;stop&#34;],sweep_param[&#34;step&#34;],smu_compliance[&#34;SMU%d&#34;%smu_master])) # VR1 for linear sweep of VAR1 source function, vmin, vmax,vstep, compliance
+                elif sweep_type==&#34;log&#34;:
+                    self.pyvisa_resource.write(&#34;VR2, %.6E, %.6E, %.6E&#34;%(sweep_param[&#34;start&#34;],sweep_param[&#34;stop&#34;],smu_compliance[&#34;SMU%d&#34;%smu_master])) # VR2 for log sweep of VAR1 source function, vmin, vmax, compliance
+            elif smu_type[&#34;SMU%d&#34;%smu_master]==&#34;current&#34;:
+                if sweep_type==&#34;linear&#34;:
+                    self.pyvisa_resource.write(&#34;IR1, %.6E, %.6E, %.6E, %.6E&#34;%(sweep_param[&#34;start&#34;],sweep_param[&#34;stop&#34;],sweep_param[&#34;step&#34;],smu_compliance[&#34;SMU%d&#34;%smu_master])) # IR1 for linear sweep of VAR1 source function, vmin, vmax,vstep, compliance
+                elif sweep_type==&#34;log&#34;:
+                    self.pyvisa_resource.write(&#34;IR2, %.6E, %.6E, %.6E&#34;%(sweep_param[&#34;start&#34;],sweep_param[&#34;stop&#34;],smu_compliance[&#34;SMU%d&#34;%smu_master])) # IR2 for log sweep of VAR1 source function, vmin, vmax, compliance
+            
+            for smu_index in range(4):
+                if (smu_index+1!=smu_master) and smu_used[&#34;SMU%d&#34;%(smu_index+1)]==&#34;on&#34;:
+                    if smu_type[&#34;SMU%d&#34;%(smu_index+1)]==&#34;voltage&#34;:
+                        self.pyvisa_resource.write(&#34;VC%d, %.2f, %.6E&#34;%(smu_index+1,smu_bias[&#34;SMU%d&#34;%(smu_index+1)],smu_compliance[&#34;SMU%d&#34;%(smu_index+1)]))
+                    elif smu_type[&#34;SMU%d&#34;%(smu_index+1)]==&#34;current&#34;:
+                        self.pyvisa_resource.write(&#34;IC%d, %.2f, %.6E&#34;%(smu_index+1,smu_bias[&#34;SMU%d&#34;%(smu_index+1)],smu_compliance[&#34;SMU%d&#34;%(smu_index+1)]))
+            self.pyvisa_resource.write(&#34;HT %f&#34;%hold_time) # Sets a hold time that delays the start of a sweep
+            self.pyvisa_resource.write(&#34;DT %f&#34;%delay_time) # delay time: Sets the time to wait between when the output voltage is set and when the measurement is made in a sweep.
+            self.pyvisa_resource.write(integration_dictionnary[integration_mode]) # integration time, IT1/IT2/IT3 : short/medium/long
+
+            self.pyvisa_resource.write(&#34;SM&#34;)
+            self.pyvisa_resource.write(&#34;DM2&#34;) # set the data display in list mode
+            
+            list_display=&#34;&#34;
+            for smu_index in range(4):
+                if self.smu_used[&#34;SMU%d&#34;%(smu_index+1)]==&#34;on&#34;:
+                    if self.smu_type[&#34;SMU%d&#34;%(smu_index+1)]==&#34;voltage&#34;:
+                        list_display+=&#34;,&#39;%s%d&#39;&#34;%(&#34;I&#34;,smu_index+1)
+                    elif self.smu_type[&#34;SMU%d&#34;%(smu_index+1)]==&#34;current&#34;:
+                        list_display+=&#34;,&#39;%s%d&#39;&#34;%(&#34;V&#34;,smu_index+1)
+                        
+            self.pyvisa_resource.write(&#34;LI %s&#34;%list_display[1:])
+        except pyvisa.VisaIOError:
+            print(&#34;/!\ VisaIOError : timeout expired&#34;)
+            self.pyvisa_resource.close()
+            
+    def launch_measurements(self,activate_segmentation=True):
+        
+        &#34;&#34;&#34; Function to launch the measurement and return the data (in array shape) and the header (string) depending on the measurement configuration
+        
+            args:
+                - activate_segmentation (boolean) :if True the total number of measurements is subdivide in smaller set of measurments to avoid a connection lost with the equipment. The longer the integration time, the smaller the subdivision segment
+            return:
+                - data (array) : array with the measurement data
+                - header (string) : string with the description of the data column &#34;Vx&#34; or &#34;Ix&#34; for voltage or current measured from SMUx.
+            
+        &#34;&#34;&#34;        
+        number_channel=0
+        for smu_index in range(4):
+            if self.smu_used[&#34;SMU%d&#34;%(smu_index+1)]==&#34;on&#34;:
+                number_channel+=1
+
+        
+        if self.integration_mode==&#34;S&#34;:
+            Nmax=50
+        elif self.integration_mode==&#34;M&#34;:
+            Nmax=30
+        elif self.integration_mode==&#34;L&#34;:
+            Nmax=10
+            
+            
+            
+        sweep_list=np.round(np.arange(self.sweep_param[&#34;start&#34;],self.sweep_param[&#34;stop&#34;]+self.sweep_param[&#34;step&#34;],self.sweep_param[&#34;step&#34;]),6)
+        N_v=len(sweep_list)
+        data=np.zeros((N_v,number_channel+1))
+        data[:,0]=sweep_list
+        j=0
+
+        if activate_segmentation:
+            iteration=int(N_v/Nmax)+1
+            index=0
+            while iteration&gt;0:
+                sweep_start=sweep_list[index]
+                if index+Nmax&gt;N_v:
+                    sweep_end=sweep_list[-1]
+                else:
+                    sweep_end=sweep_list[index+Nmax-1]
+                
+                if self.smu_type[&#34;SMU%d&#34;%self.smu_master]==&#34;voltage&#34;:
+                    if self.sweep_type==&#34;linear&#34;:
+                        self.pyvisa_resource.write(&#34;VR1, %.6E, %.6E, %.6E, %.6E&#34;%(sweep_start,sweep_end,self.sweep_param[&#34;step&#34;],self.smu_compliance[&#34;SMU%d&#34;%self.smu_master])) # VR1 for linear sweep of VAR1 source function, vmin, vmax,vstep, compliance
+                elif self.smu_type[&#34;SMU%d&#34;%self.smu_master]==&#34;current&#34;:
+                    if self.sweep_type==&#34;linear&#34;:
+                        self.pyvisa_resource.write(&#34;IR1, %.6E, %.6E, %.6E, %.6E&#34;%(sweep_start,sweep_end,self.sweep_param[&#34;step&#34;],self.smu_compliance[&#34;SMU%d&#34;%self.smu_master])) # IR1 for linear sweep of VAR1 source function, vmin, vmax,vstep, compliance
+
+                self.pyvisa_resource.write(&#34;SS&#34;)
+                if self.smu_type[&#34;SMU%d&#34;%(self.smu_master)]==&#34;voltage&#34;:
+                    self.pyvisa_resource.write(&#34;VR1, %.6E, %.6E, %.6E, %.6E&#34;%(sweep_start,sweep_end,self.sweep_param[&#34;step&#34;],self.smu_compliance[&#34;SMU%d&#34;%self.smu_master])) # VR1 for linear sweep of VAR1 source function, vmin, vmax,vstep, compliance
+                elif self.smu_type[&#34;SMU%d&#34;%(self.smu_master)]==&#34;current&#34;:
+                    self.pyvisa_resource.write(&#34;IR1, %.6E, %.6E, %.6E, %.6E&#34;%(sweep_start,sweep_end,self.sweep_param[&#34;step&#34;],self.smu_compliance[&#34;SMU%d&#34;%self.smu_master])) # VR1 for linear sweep of VAR1 source function, vmin, vmax,vstep, compliance
+    
+                self.pyvisa_resource.write(&#34;MD&#34;) # This command controls measurements.
+                self.pyvisa_resource.write(&#34;ME1&#34;) # Run a single trigger test and store readings in a cleared buffer: 1
+                
+                i=0
+                for smu_index in range(4):
+                    if self.smu_used[&#34;SMU%d&#34;%(smu_index+1)]==&#34;on&#34;:
+                        i+=1
+                        if self.smu_type[&#34;SMU%d&#34;%(smu_index+1)]==&#34;voltage&#34;:
+                            data_list=self.pyvisa_resource.query(&#34;DO &#39;I%d&#39;&#34;%(smu_index+1))# Read measurements
+                        elif self.smu_type[&#34;SMU%d&#34;%(smu_index+1)]==&#34;current&#34;:
+                            data_list=self.pyvisa_resource.query(&#34;DO &#39;V%d&#39;&#34;%(smu_index+1))# Read measurements
+                        j=0
+                        for  data_i in data_list.split(&#34;,&#34;):
+                            data[index+j,i]=float(data_i[1:])
+                            j+=1
+                            
+                index+=Nmax
+                iteration-=1  
+        else:
+            
+            self.pyvisa_resource.write(&#34;MD&#34;) # This command controls measurements.
+            self.pyvisa_resource.write(&#34;ME1&#34;) # Run a single trigger test and store readings in a cleared buffer: 1
+            time.sleep(10)
+            i=0
+            for smu_index in range(4):
+                if self.smu_used[&#34;SMU%d&#34;%(smu_index+1)]==&#34;on&#34;:
+                    i+=1
+                    if self.smu_type[&#34;SMU%d&#34;%(smu_index+1)]==&#34;voltage&#34;:
+                        data_list=self.pyvisa_resource.query(&#34;DO &#39;I%d&#39;&#34;%(smu_index+1))# Read measurements
+                    elif self.smu_type[&#34;SMU%d&#34;%(smu_index+1)]==&#34;current&#34;:
+                        data_list=self.pyvisa_resource.query(&#34;DO &#39;V%d&#39;&#34;%(smu_index+1))# Read measurements
+                    
+                    j=0
+                    for  data_j in data_list.split(&#34;,&#34;):
+                        data[j,i]=float(data_j[1:])
+                        j+=1
+            
+
+        header=&#34;%s%d&#34;%(self.smu_type[&#34;SMU%d&#34;%self.smu_master][0].upper(),self.smu_master)
+        for smu_index in range(4):
+            if self.smu_used[&#34;SMU%d&#34;%(smu_index+1)]==&#34;on&#34;:
+                if self.smu_type[&#34;SMU%d&#34;%(smu_index+1)]==&#34;voltage&#34;:
+                    header+=&#34;, %s%d&#34;%(&#34;I&#34;,smu_index+1)
+                elif self.smu_type[&#34;SMU%d&#34;%(smu_index+1)]==&#34;current&#34;:
+                    header+=&#34;, %s%d&#34;%(&#34;V&#34;,smu_index+1)
+        return data, header</code></pre>
+</details>
+<div class="desc"><p>Class to control HP4145 semiconductor analyzer</p>
+<p>Function called when an instance of the class is created</p>
+<p>args:
+- address (string) : the address of the equipment to be connected
+- rm (pyvisa object) : the pyvisa resource manager used to set the communication with the equipment
+- timeout (scalar) : the timeout set for the communication with the equipment</p></div>
+<h3>Ancestors</h3>
+<ul class="hlist">
+<li>equipment_control.equipment.equipment</li>
+</ul>
+<h3>Class variables</h3>
+<dl>
+<dt id="dopes.equipment_control.hp4145.hp4145.company"><code class="name">var <span class="ident">company</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="dopes.equipment_control.hp4145.hp4145.model"><code class="name">var <span class="ident">model</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="dopes.equipment_control.hp4145.hp4145.url"><code class="name">var <span class="ident">url</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+</dl>
+<h3>Methods</h3>
+<dl>
+<dt id="dopes.equipment_control.hp4145.hp4145.initialize"><code class="name flex">
+<span>def <span class="ident">initialize</span></span>(<span>self,<br>smu_type={'SMU1': 'voltage', 'SMU2': 'voltage', 'SMU3': 'common', 'SMU4': 'common'},<br>smu_used={'SMU1': 'on', 'SMU2': 'on', 'SMU3': 'on', 'SMU4': 'on'},<br>smu_master=1,<br>smu_bias={'SMU1': 0, 'SMU2': 0, 'SMU3': 0, 'SMU4': 0},<br>smu_compliance={'SMU1': 1e-06, 'SMU2': 1e-06, 'SMU3': 1e-06, 'SMU4': 1e-06},<br>sweep_param={'start': 0, 'stop': 0, 'step': 0},<br>sweep_type='linear',<br>integration_mode='S',<br>delay_time=0,<br>hold_time=0)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def initialize(self, smu_type={&#34;SMU1&#34;:&#34;voltage&#34;,&#34;SMU2&#34;:&#34;voltage&#34;,&#34;SMU3&#34;:&#34;common&#34;,&#34;SMU4&#34;:&#34;common&#34;}, 
+               smu_used={&#34;SMU1&#34;:&#34;on&#34;,&#34;SMU2&#34;:&#34;on&#34;,&#34;SMU3&#34;:&#34;on&#34;,&#34;SMU4&#34;:&#34;on&#34;}, 
+               smu_master=1,smu_bias={&#34;SMU1&#34;:0,&#34;SMU2&#34;:0,&#34;SMU3&#34;:0,&#34;SMU4&#34;:0},
+               smu_compliance={&#34;SMU1&#34;:1e-6,&#34;SMU2&#34;:1e-6,&#34;SMU3&#34;:1e-6,&#34;SMU4&#34;:1e-6},
+               sweep_param={&#34;start&#34;:0,&#34;stop&#34;:0,&#34;step&#34;:0},sweep_type=&#34;linear&#34;,
+               integration_mode=&#34;S&#34;,delay_time=0,hold_time=0):
+    
+    
+    &#34;&#34;&#34; Function to initialize the HP4145 equipment with the desired settings
+    
+        args:
+            - smu_type (dictionary) : dictionary indicated for each SMU (&#34;SMU1&#34;,&#34;SMU2&#34;,&#34;SMU3&#34; and &#34;SMU4&#34;) the bias type (&#34;voltage&#34;, &#34;current&#34; or &#34;common&#34;)
+            - smu_used (dictionary) : dictionary indicated for each SMU (&#34;SMU1&#34;,&#34;SMU2&#34;,&#34;SMU3&#34; and &#34;SMU4&#34;) if active or not (&#34;on&#34; or &#34;off&#34;)
+            - smu_master (int) : integer to indicate which SMU performs the sweep
+            - smu_bias (dictionary) : dictionary indicated for each SMU (&#34;SMU1&#34;,&#34;SMU2&#34;,&#34;SMU3&#34; and &#34;SMU4&#34;) the bias point (scalar)
+            - smu_compliance (dictionary) : dictionary indicated for each SMU (&#34;SMU1&#34;,&#34;SMU2&#34;,&#34;SMU3&#34; and &#34;SMU4&#34;) the compliance (scalar)
+            - sweep_param (dictionary) : dictionary indicated the starting bias (&#34;start&#34;), the stoping bias (&#34;stop&#34;) and step (&#34;step&#34;) of the sweep
+            - sweep_type (string) : string to indicate linear (&#34;linear&#34;) sweep or logarithmic (&#34;log&#34;) sweep
+            - integration_mode (string) : set the integration time parameter (&#34;S&#34; for short, &#34;M&#34; for medium and &#34;L&#34; for long)
+            - delay_time (scalar) : the time to wait between when the output voltage is set and when the measurement is made in a sweep
+            - hold_time (scalar) : hold time that delays the start of a sweep
+    &#34;&#34;&#34;
+    
+    self.smu_type=smu_type
+    self.sweep_type=sweep_type
+    self.smu_used=smu_used
+    self.smu_master=smu_master
+    self.sweep_param=sweep_param
+    self.smu_compliance=smu_compliance
+    self.smu_bias=smu_bias
+    self.integration_mode=integration_mode
+    self.delay_time=delay_time
+    self.hold_time=hold_time
+    
+    index_measurement_type={&#34;sweep&#34;:1, &#34;constant&#34;:3}
+    index_smu_type={&#34;voltage&#34;:1, &#34;current&#34;:2, &#34;common&#34;:3}
+    integration_dictionnary={&#34;S&#34;:&#34;IT1&#34;,&#34;M&#34;:&#34;IT2&#34;,&#34;L&#34;:&#34;IT3&#34;}
+    try:
+        self.pyvisa_resource.write(&#34;BC&#34;) # clear all buffer.
+        self.pyvisa_resource.write(&#34;DR1&#34;) # This command enables or disables service request for data ready when communications is set to GPIB.
+        self.pyvisa_resource.write(&#34;EC 1&#34;) # This command sets the condition to exit the test if compliance is reached.
+        
+            
+        self.pyvisa_resource.write(&#34;DE&#34;) # DE: Accesses SMU channel definition page.
+        
+        self.pyvisa_resource.write(&#34;CH%d, &#39;V%d&#39;, &#39;I%d&#39;, %d, %d&#34;%(smu_master,smu_master,smu_master,index_smu_type[smu_type[&#34;SMU%d&#34;%smu_master]],index_measurement_type[&#34;sweep&#34;])) # 1/2/3: voltage/current/Common 1/2/3: VAR1/VAR2/constant
+        
+        for smu_index in range(4):
+            if (smu_index+1!=smu_master) and smu_used[&#34;SMU%d&#34;%(smu_index+1)]==&#34;off&#34;:
+                self.pyvisa_resource.write(&#34;CH%d&#34;%(smu_index+1)) 
+            elif (smu_index+1!=smu_master) and smu_used[&#34;SMU%d&#34;%(smu_index+1)]==&#34;on&#34;:
+                self.pyvisa_resource.write(&#34;CH%d, &#39;V%d&#39;, &#39;I%d&#39;, %d, %d&#34;%(smu_index+1,smu_index+1,smu_index+1,index_smu_type[smu_type[&#34;SMU%d&#34;%(smu_index+1)]],index_measurement_type[&#34;constant&#34;])) 
+
+        self.pyvisa_resource.write(&#34;SS&#34;)# Accesses source setup page
+        if smu_type[&#34;SMU%d&#34;%smu_master]==&#34;voltage&#34;:
+            if sweep_type==&#34;linear&#34;:
+                self.pyvisa_resource.write(&#34;VR1, %.6E, %.6E, %.6E, %.6E&#34;%(sweep_param[&#34;start&#34;],sweep_param[&#34;stop&#34;],sweep_param[&#34;step&#34;],smu_compliance[&#34;SMU%d&#34;%smu_master])) # VR1 for linear sweep of VAR1 source function, vmin, vmax,vstep, compliance
+            elif sweep_type==&#34;log&#34;:
+                self.pyvisa_resource.write(&#34;VR2, %.6E, %.6E, %.6E&#34;%(sweep_param[&#34;start&#34;],sweep_param[&#34;stop&#34;],smu_compliance[&#34;SMU%d&#34;%smu_master])) # VR2 for log sweep of VAR1 source function, vmin, vmax, compliance
+        elif smu_type[&#34;SMU%d&#34;%smu_master]==&#34;current&#34;:
+            if sweep_type==&#34;linear&#34;:
+                self.pyvisa_resource.write(&#34;IR1, %.6E, %.6E, %.6E, %.6E&#34;%(sweep_param[&#34;start&#34;],sweep_param[&#34;stop&#34;],sweep_param[&#34;step&#34;],smu_compliance[&#34;SMU%d&#34;%smu_master])) # IR1 for linear sweep of VAR1 source function, vmin, vmax,vstep, compliance
+            elif sweep_type==&#34;log&#34;:
+                self.pyvisa_resource.write(&#34;IR2, %.6E, %.6E, %.6E&#34;%(sweep_param[&#34;start&#34;],sweep_param[&#34;stop&#34;],smu_compliance[&#34;SMU%d&#34;%smu_master])) # IR2 for log sweep of VAR1 source function, vmin, vmax, compliance
+        
+        for smu_index in range(4):
+            if (smu_index+1!=smu_master) and smu_used[&#34;SMU%d&#34;%(smu_index+1)]==&#34;on&#34;:
+                if smu_type[&#34;SMU%d&#34;%(smu_index+1)]==&#34;voltage&#34;:
+                    self.pyvisa_resource.write(&#34;VC%d, %.2f, %.6E&#34;%(smu_index+1,smu_bias[&#34;SMU%d&#34;%(smu_index+1)],smu_compliance[&#34;SMU%d&#34;%(smu_index+1)]))
+                elif smu_type[&#34;SMU%d&#34;%(smu_index+1)]==&#34;current&#34;:
+                    self.pyvisa_resource.write(&#34;IC%d, %.2f, %.6E&#34;%(smu_index+1,smu_bias[&#34;SMU%d&#34;%(smu_index+1)],smu_compliance[&#34;SMU%d&#34;%(smu_index+1)]))
+        self.pyvisa_resource.write(&#34;HT %f&#34;%hold_time) # Sets a hold time that delays the start of a sweep
+        self.pyvisa_resource.write(&#34;DT %f&#34;%delay_time) # delay time: Sets the time to wait between when the output voltage is set and when the measurement is made in a sweep.
+        self.pyvisa_resource.write(integration_dictionnary[integration_mode]) # integration time, IT1/IT2/IT3 : short/medium/long
+
+        self.pyvisa_resource.write(&#34;SM&#34;)
+        self.pyvisa_resource.write(&#34;DM2&#34;) # set the data display in list mode
+        
+        list_display=&#34;&#34;
+        for smu_index in range(4):
+            if self.smu_used[&#34;SMU%d&#34;%(smu_index+1)]==&#34;on&#34;:
+                if self.smu_type[&#34;SMU%d&#34;%(smu_index+1)]==&#34;voltage&#34;:
+                    list_display+=&#34;,&#39;%s%d&#39;&#34;%(&#34;I&#34;,smu_index+1)
+                elif self.smu_type[&#34;SMU%d&#34;%(smu_index+1)]==&#34;current&#34;:
+                    list_display+=&#34;,&#39;%s%d&#39;&#34;%(&#34;V&#34;,smu_index+1)
+                    
+        self.pyvisa_resource.write(&#34;LI %s&#34;%list_display[1:])
+    except pyvisa.VisaIOError:
+        print(&#34;/!\ VisaIOError : timeout expired&#34;)
+        self.pyvisa_resource.close()</code></pre>
+</details>
+<div class="desc"><p>Function to initialize the HP4145 equipment with the desired settings</p>
+<p>args:
+- smu_type (dictionary) : dictionary indicated for each SMU ("SMU1","SMU2","SMU3" and "SMU4") the bias type ("voltage", "current" or "common")
+- smu_used (dictionary) : dictionary indicated for each SMU ("SMU1","SMU2","SMU3" and "SMU4") if active or not ("on" or "off")
+- smu_master (int) : integer to indicate which SMU performs the sweep
+- smu_bias (dictionary) : dictionary indicated for each SMU ("SMU1","SMU2","SMU3" and "SMU4") the bias point (scalar)
+- smu_compliance (dictionary) : dictionary indicated for each SMU ("SMU1","SMU2","SMU3" and "SMU4") the compliance (scalar)
+- sweep_param (dictionary) : dictionary indicated the starting bias ("start"), the stoping bias ("stop") and step ("step") of the sweep
+- sweep_type (string) : string to indicate linear ("linear") sweep or logarithmic ("log") sweep
+- integration_mode (string) : set the integration time parameter ("S" for short, "M" for medium and "L" for long)
+- delay_time (scalar) : the time to wait between when the output voltage is set and when the measurement is made in a sweep
+- hold_time (scalar) : hold time that delays the start of a sweep</p></div>
+</dd>
+<dt id="dopes.equipment_control.hp4145.hp4145.launch_measurements"><code class="name flex">
+<span>def <span class="ident">launch_measurements</span></span>(<span>self, activate_segmentation=True)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def launch_measurements(self,activate_segmentation=True):
+    
+    &#34;&#34;&#34; Function to launch the measurement and return the data (in array shape) and the header (string) depending on the measurement configuration
+    
+        args:
+            - activate_segmentation (boolean) :if True the total number of measurements is subdivide in smaller set of measurments to avoid a connection lost with the equipment. The longer the integration time, the smaller the subdivision segment
+        return:
+            - data (array) : array with the measurement data
+            - header (string) : string with the description of the data column &#34;Vx&#34; or &#34;Ix&#34; for voltage or current measured from SMUx.
+        
+    &#34;&#34;&#34;        
+    number_channel=0
+    for smu_index in range(4):
+        if self.smu_used[&#34;SMU%d&#34;%(smu_index+1)]==&#34;on&#34;:
+            number_channel+=1
+
+    
+    if self.integration_mode==&#34;S&#34;:
+        Nmax=50
+    elif self.integration_mode==&#34;M&#34;:
+        Nmax=30
+    elif self.integration_mode==&#34;L&#34;:
+        Nmax=10
+        
+        
+        
+    sweep_list=np.round(np.arange(self.sweep_param[&#34;start&#34;],self.sweep_param[&#34;stop&#34;]+self.sweep_param[&#34;step&#34;],self.sweep_param[&#34;step&#34;]),6)
+    N_v=len(sweep_list)
+    data=np.zeros((N_v,number_channel+1))
+    data[:,0]=sweep_list
+    j=0
+
+    if activate_segmentation:
+        iteration=int(N_v/Nmax)+1
+        index=0
+        while iteration&gt;0:
+            sweep_start=sweep_list[index]
+            if index+Nmax&gt;N_v:
+                sweep_end=sweep_list[-1]
+            else:
+                sweep_end=sweep_list[index+Nmax-1]
+            
+            if self.smu_type[&#34;SMU%d&#34;%self.smu_master]==&#34;voltage&#34;:
+                if self.sweep_type==&#34;linear&#34;:
+                    self.pyvisa_resource.write(&#34;VR1, %.6E, %.6E, %.6E, %.6E&#34;%(sweep_start,sweep_end,self.sweep_param[&#34;step&#34;],self.smu_compliance[&#34;SMU%d&#34;%self.smu_master])) # VR1 for linear sweep of VAR1 source function, vmin, vmax,vstep, compliance
+            elif self.smu_type[&#34;SMU%d&#34;%self.smu_master]==&#34;current&#34;:
+                if self.sweep_type==&#34;linear&#34;:
+                    self.pyvisa_resource.write(&#34;IR1, %.6E, %.6E, %.6E, %.6E&#34;%(sweep_start,sweep_end,self.sweep_param[&#34;step&#34;],self.smu_compliance[&#34;SMU%d&#34;%self.smu_master])) # IR1 for linear sweep of VAR1 source function, vmin, vmax,vstep, compliance
+
+            self.pyvisa_resource.write(&#34;SS&#34;)
+            if self.smu_type[&#34;SMU%d&#34;%(self.smu_master)]==&#34;voltage&#34;:
+                self.pyvisa_resource.write(&#34;VR1, %.6E, %.6E, %.6E, %.6E&#34;%(sweep_start,sweep_end,self.sweep_param[&#34;step&#34;],self.smu_compliance[&#34;SMU%d&#34;%self.smu_master])) # VR1 for linear sweep of VAR1 source function, vmin, vmax,vstep, compliance
+            elif self.smu_type[&#34;SMU%d&#34;%(self.smu_master)]==&#34;current&#34;:
+                self.pyvisa_resource.write(&#34;IR1, %.6E, %.6E, %.6E, %.6E&#34;%(sweep_start,sweep_end,self.sweep_param[&#34;step&#34;],self.smu_compliance[&#34;SMU%d&#34;%self.smu_master])) # VR1 for linear sweep of VAR1 source function, vmin, vmax,vstep, compliance
+
+            self.pyvisa_resource.write(&#34;MD&#34;) # This command controls measurements.
+            self.pyvisa_resource.write(&#34;ME1&#34;) # Run a single trigger test and store readings in a cleared buffer: 1
+            
+            i=0
+            for smu_index in range(4):
+                if self.smu_used[&#34;SMU%d&#34;%(smu_index+1)]==&#34;on&#34;:
+                    i+=1
+                    if self.smu_type[&#34;SMU%d&#34;%(smu_index+1)]==&#34;voltage&#34;:
+                        data_list=self.pyvisa_resource.query(&#34;DO &#39;I%d&#39;&#34;%(smu_index+1))# Read measurements
+                    elif self.smu_type[&#34;SMU%d&#34;%(smu_index+1)]==&#34;current&#34;:
+                        data_list=self.pyvisa_resource.query(&#34;DO &#39;V%d&#39;&#34;%(smu_index+1))# Read measurements
+                    j=0
+                    for  data_i in data_list.split(&#34;,&#34;):
+                        data[index+j,i]=float(data_i[1:])
+                        j+=1
+                        
+            index+=Nmax
+            iteration-=1  
+    else:
+        
+        self.pyvisa_resource.write(&#34;MD&#34;) # This command controls measurements.
+        self.pyvisa_resource.write(&#34;ME1&#34;) # Run a single trigger test and store readings in a cleared buffer: 1
+        time.sleep(10)
+        i=0
+        for smu_index in range(4):
+            if self.smu_used[&#34;SMU%d&#34;%(smu_index+1)]==&#34;on&#34;:
+                i+=1
+                if self.smu_type[&#34;SMU%d&#34;%(smu_index+1)]==&#34;voltage&#34;:
+                    data_list=self.pyvisa_resource.query(&#34;DO &#39;I%d&#39;&#34;%(smu_index+1))# Read measurements
+                elif self.smu_type[&#34;SMU%d&#34;%(smu_index+1)]==&#34;current&#34;:
+                    data_list=self.pyvisa_resource.query(&#34;DO &#39;V%d&#39;&#34;%(smu_index+1))# Read measurements
+                
+                j=0
+                for  data_j in data_list.split(&#34;,&#34;):
+                    data[j,i]=float(data_j[1:])
+                    j+=1
+        
+
+    header=&#34;%s%d&#34;%(self.smu_type[&#34;SMU%d&#34;%self.smu_master][0].upper(),self.smu_master)
+    for smu_index in range(4):
+        if self.smu_used[&#34;SMU%d&#34;%(smu_index+1)]==&#34;on&#34;:
+            if self.smu_type[&#34;SMU%d&#34;%(smu_index+1)]==&#34;voltage&#34;:
+                header+=&#34;, %s%d&#34;%(&#34;I&#34;,smu_index+1)
+            elif self.smu_type[&#34;SMU%d&#34;%(smu_index+1)]==&#34;current&#34;:
+                header+=&#34;, %s%d&#34;%(&#34;V&#34;,smu_index+1)
+    return data, header</code></pre>
+</details>
+<div class="desc"><p>Function to launch the measurement and return the data (in array shape) and the header (string) depending on the measurement configuration</p>
+<p>args:
+- activate_segmentation (boolean) :if True the total number of measurements is subdivide in smaller set of measurments to avoid a connection lost with the equipment. The longer the integration time, the smaller the subdivision segment
+return:
+- data (array) : array with the measurement data
+- header (string) : string with the description of the data column "Vx" or "Ix" for voltage or current measured from SMUx.</p></div>
+</dd>
+</dl>
+</dd>
+</dl>
+</section>
+</article>
+<nav id="sidebar">
+<div class="toc">
+<ul></ul>
+</div>
+<ul id="index">
+<li><h3>Super-module</h3>
+<ul>
+<li><code><a title="dopes.equipment_control" href="index.html">dopes.equipment_control</a></code></li>
+</ul>
+</li>
+<li><h3><a href="#header-classes">Classes</a></h3>
+<ul>
+<li>
+<h4><code><a title="dopes.equipment_control.hp4145.hp4145" href="#dopes.equipment_control.hp4145.hp4145">hp4145</a></code></h4>
+<ul class="">
+<li><code><a title="dopes.equipment_control.hp4145.hp4145.company" href="#dopes.equipment_control.hp4145.hp4145.company">company</a></code></li>
+<li><code><a title="dopes.equipment_control.hp4145.hp4145.initialize" href="#dopes.equipment_control.hp4145.hp4145.initialize">initialize</a></code></li>
+<li><code><a title="dopes.equipment_control.hp4145.hp4145.launch_measurements" href="#dopes.equipment_control.hp4145.hp4145.launch_measurements">launch_measurements</a></code></li>
+<li><code><a title="dopes.equipment_control.hp4145.hp4145.model" href="#dopes.equipment_control.hp4145.hp4145.model">model</a></code></li>
+<li><code><a title="dopes.equipment_control.hp4145.hp4145.url" href="#dopes.equipment_control.hp4145.hp4145.url">url</a></code></li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+</nav>
+</main>
+<footer id="footer">
+<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
+</footer>
+</body>
+</html>
diff --git a/html/equipment_control/index.html b/html/equipment_control/index.html
new file mode 100644
index 0000000000000000000000000000000000000000..2bebcb2d355d09ddf78c20753c0578c2eeff46d8
--- /dev/null
+++ b/html/equipment_control/index.html
@@ -0,0 +1,118 @@
+<!doctype html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
+<meta name="generator" content="pdoc3 0.11.6">
+<title>dopes.equipment_control API documentation</title>
+<meta name="description" content="">
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/typography.min.css" integrity="sha512-Y1DYSb995BAfxobCkKepB1BqJJTPrOp3zPL74AWFugHHmmdcvO+C48WLrUOlhGMc0QG7AE3f7gmvvcrmX2fDoA==" crossorigin>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css" crossorigin>
+<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:1.5em;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:2em 0 .50em 0}h3{font-size:1.4em;margin:1.6em 0 .7em 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .2s ease-in-out}a:visited{color:#503}a:hover{color:#b62}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900;font-weight:bold}pre code{font-size:.8em;line-height:1.4em;padding:1em;display:block}code{background:#f3f3f3;font-family:"DejaVu Sans Mono",monospace;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source > summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible;min-width:max-content}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em 1em;margin:1em 0}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
+<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul ul{padding-left:1em}.toc > ul > li{margin-top:.5em}}</style>
+<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
+<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js" integrity="sha512-D9gUyxqja7hBtkWpPWGt9wfbfaMGVt9gnyCvYa+jojwwPHLCzUm5i8rpk7vD7wNee9bA35eYIjobYPaQuKS1MQ==" crossorigin></script>
+<script>window.addEventListener('DOMContentLoaded', () => {
+hljs.configure({languages: ['bash', 'css', 'diff', 'graphql', 'ini', 'javascript', 'json', 'plaintext', 'python', 'python-repl', 'rust', 'shell', 'sql', 'typescript', 'xml', 'yaml']});
+hljs.highlightAll();
+/* Collapse source docstrings */
+setTimeout(() => {
+[...document.querySelectorAll('.hljs.language-python > .hljs-string')]
+.filter(el => el.innerHTML.length > 200 && ['"""', "'''"].includes(el.innerHTML.substring(0, 3)))
+.forEach(el => {
+let d = document.createElement('details');
+d.classList.add('hljs-string');
+d.innerHTML = '<summary>"""</summary>' + el.innerHTML.substring(3);
+el.replaceWith(d);
+});
+}, 100);
+})</script>
+</head>
+<body>
+<main>
+<article id="content">
+<header>
+<h1 class="title">Namespace <code>dopes.equipment_control</code></h1>
+</header>
+<section id="section-intro">
+</section>
+<section>
+<h2 class="section-title" id="header-submodules">Sub-modules</h2>
+<dl>
+<dt><code class="name"><a title="dopes.equipment_control.cm110" href="cm110.html">dopes.equipment_control.cm110</a></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt><code class="name"><a title="dopes.equipment_control.dmm" href="dmm.html">dopes.equipment_control.dmm</a></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt><code class="name"><a title="dopes.equipment_control.equipment" href="equipment.html">dopes.equipment_control.equipment</a></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt><code class="name"><a title="dopes.equipment_control.hp4145" href="hp4145.html">dopes.equipment_control.hp4145</a></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt><code class="name"><a title="dopes.equipment_control.k2400" href="k2400.html">dopes.equipment_control.k2400</a></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt><code class="name"><a title="dopes.equipment_control.k2450" href="k2450.html">dopes.equipment_control.k2450</a></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt><code class="name"><a title="dopes.equipment_control.k4200" href="k4200.html">dopes.equipment_control.k4200</a></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt><code class="name"><a title="dopes.equipment_control.kal100" href="kal100.html">dopes.equipment_control.kal100</a></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt><code class="name"><a title="dopes.equipment_control.sh242" href="sh242.html">dopes.equipment_control.sh242</a></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+</dl>
+</section>
+<section>
+</section>
+<section>
+</section>
+<section>
+</section>
+</article>
+<nav id="sidebar">
+<div class="toc">
+<ul></ul>
+</div>
+<ul id="index">
+<li><h3>Super-module</h3>
+<ul>
+<li><code><a title="dopes" href="../index.html">dopes</a></code></li>
+</ul>
+</li>
+<li><h3><a href="#header-submodules">Sub-modules</a></h3>
+<ul>
+<li><code><a title="dopes.equipment_control.cm110" href="cm110.html">dopes.equipment_control.cm110</a></code></li>
+<li><code><a title="dopes.equipment_control.dmm" href="dmm.html">dopes.equipment_control.dmm</a></code></li>
+<li><code><a title="dopes.equipment_control.equipment" href="equipment.html">dopes.equipment_control.equipment</a></code></li>
+<li><code><a title="dopes.equipment_control.hp4145" href="hp4145.html">dopes.equipment_control.hp4145</a></code></li>
+<li><code><a title="dopes.equipment_control.k2400" href="k2400.html">dopes.equipment_control.k2400</a></code></li>
+<li><code><a title="dopes.equipment_control.k2450" href="k2450.html">dopes.equipment_control.k2450</a></code></li>
+<li><code><a title="dopes.equipment_control.k4200" href="k4200.html">dopes.equipment_control.k4200</a></code></li>
+<li><code><a title="dopes.equipment_control.kal100" href="kal100.html">dopes.equipment_control.kal100</a></code></li>
+<li><code><a title="dopes.equipment_control.sh242" href="sh242.html">dopes.equipment_control.sh242</a></code></li>
+</ul>
+</li>
+</ul>
+</nav>
+</main>
+<footer id="footer">
+<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
+</footer>
+</body>
+</html>
diff --git a/html/equipment_control/k2400.html b/html/equipment_control/k2400.html
new file mode 100644
index 0000000000000000000000000000000000000000..00929f601f21c499507e91e56cce423c5a3458d1
--- /dev/null
+++ b/html/equipment_control/k2400.html
@@ -0,0 +1,414 @@
+<!doctype html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
+<meta name="generator" content="pdoc3 0.11.6">
+<title>dopes.equipment_control.k2400 API documentation</title>
+<meta name="description" content="">
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/typography.min.css" integrity="sha512-Y1DYSb995BAfxobCkKepB1BqJJTPrOp3zPL74AWFugHHmmdcvO+C48WLrUOlhGMc0QG7AE3f7gmvvcrmX2fDoA==" crossorigin>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css" crossorigin>
+<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:1.5em;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:2em 0 .50em 0}h3{font-size:1.4em;margin:1.6em 0 .7em 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .2s ease-in-out}a:visited{color:#503}a:hover{color:#b62}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900;font-weight:bold}pre code{font-size:.8em;line-height:1.4em;padding:1em;display:block}code{background:#f3f3f3;font-family:"DejaVu Sans Mono",monospace;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source > summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible;min-width:max-content}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em 1em;margin:1em 0}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
+<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul ul{padding-left:1em}.toc > ul > li{margin-top:.5em}}</style>
+<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
+<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js" integrity="sha512-D9gUyxqja7hBtkWpPWGt9wfbfaMGVt9gnyCvYa+jojwwPHLCzUm5i8rpk7vD7wNee9bA35eYIjobYPaQuKS1MQ==" crossorigin></script>
+<script>window.addEventListener('DOMContentLoaded', () => {
+hljs.configure({languages: ['bash', 'css', 'diff', 'graphql', 'ini', 'javascript', 'json', 'plaintext', 'python', 'python-repl', 'rust', 'shell', 'sql', 'typescript', 'xml', 'yaml']});
+hljs.highlightAll();
+/* Collapse source docstrings */
+setTimeout(() => {
+[...document.querySelectorAll('.hljs.language-python > .hljs-string')]
+.filter(el => el.innerHTML.length > 200 && ['"""', "'''"].includes(el.innerHTML.substring(0, 3)))
+.forEach(el => {
+let d = document.createElement('details');
+d.classList.add('hljs-string');
+d.innerHTML = '<summary>"""</summary>' + el.innerHTML.substring(3);
+el.replaceWith(d);
+});
+}, 100);
+})</script>
+</head>
+<body>
+<main>
+<article id="content">
+<header>
+<h1 class="title">Module <code>dopes.equipment_control.k2400</code></h1>
+</header>
+<section id="section-intro">
+</section>
+<section>
+</section>
+<section>
+</section>
+<section>
+</section>
+<section>
+<h2 class="section-title" id="header-classes">Classes</h2>
+<dl>
+<dt id="dopes.equipment_control.k2400.k2400"><code class="flex name class">
+<span>class <span class="ident">k2400</span></span>
+<span>(</span><span>address, rm=None, timeout=10000.0)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">class k2400(equipment.equipment):
+    
+    &#34;&#34;&#34;Class to control K2400 SMU&#34;&#34;&#34;
+    model=&#34;K2400&#34;
+    company=&#34;Keithley&#34;
+    url=&#34;https://www.tek.com/en/products/keithley/digital-multimeter/dmm7510&#34;
+
+
+    def initialize(self, source_mode,measurement_mode, compliance, autozero=True, nplc=1,digits=6,continuous_trigger=False,disp_enable=True):
+        &#34;&#34;&#34; Function to initialize the K2400 SMU  with the desired settings
+        
+            args:
+                - source_mode (string) : source mode of the SMU (&#34;current&#34; or &#34;voltage&#34;)
+                - measurement_mode (string) : measurement mode of the SMU (&#34;current&#34;, &#34;voltage&#34; or &#34;resistance&#34;)
+                - compliance (scalar) : compliance of the source
+                - autozero (boolean) : if true, enable autozero of the SMU
+                - nplc (scalar) : set NPLC to set the integration time for the measurement. For a NPLC of 1, the integration period would be 1/50 (for 50Hz line power) which is 20 msec
+                - digits (int) : display resolution in number of bits
+                - continuous_trigger (boolean) : if true, the display of the equipment does not freeze after a measurement. When disabled, the instrument operates at a higher speed
+                - disp_enable (boolean) : if true, enable the front panel display circuitry. When disabled, the instrument operates at a higher speed
+        &#34;&#34;&#34;
+        mode_name={&#34;voltage&#34;:&#34;VOLT&#34;, &#34;current&#34;:&#34;CURR&#34;, &#34;resistance&#34;:&#34;RES&#34;}        
+        self.output_state=&#34;OFF&#34;
+        self.pyvisa_resource.write(&#34;*RST&#34;)
+        self.source_mode=source_mode
+        self.continuous_trigger=continuous_trigger
+        
+        if source_mode==&#34;voltage&#34;:
+            self.pyvisa_resource.write(&#34;:SOUR:FUNC VOLT&#34;)   
+            self.pyvisa_resource.write(&#34;:SENS:CURR:PROT %E&#34;%compliance)     # set automatic range
+
+        if source_mode==&#34;current&#34;:
+            self.pyvisa_resource.write(&#34;:SOUR:FUNC CURR&#34;)   
+            self.pyvisa_resource.write(&#34;:SENS:VOLT:PROT %E&#34;%compliance)     # set automatic range
+
+
+
+        if measurement_mode==&#34;voltage&#34;:
+            self.pyvisa_resource.write(&#34;:SENS:FUNC &#39;VOLT&#39;&#34;)   
+            self.pyvisa_resource.write(&#34;:SENS:VOLT:RANG:AUTO ON&#34;)     # set automatic range
+
+        elif measurement_mode==&#34;current&#34;:
+            self.pyvisa_resource.write(&#34;:SENS:FUNC &#39;CURR&#39;&#34;)   
+            self.pyvisa_resource.write(&#34;:SENS:CURR:RANG:AUTO ON&#34;)     # set automatic range
+
+        elif measurement_mode==&#34;resistance&#34;:
+            self.pyvisa_resource.write(&#34;:SENS:FUNC &#39;RES&#39;&#34;) 
+            self.pyvisa_resource.write(&#34;:SENS:RES:RANG:AUTO ON&#34;)     # set automatic range
+            
+                   
+        self.pyvisa_resource.write(&#34;:DISP:DIG %d&#34;%digits)     # Query largest allowable display resolution
+        if disp_enable:
+            self.pyvisa_resource.write(&#34;:DISP:ENAB ON&#34;)     # This command is used to enable and disable the front panel display circuitry. When disabled, the instrument operates at a higher speed.
+        else:
+            self.pyvisa_resource.write(&#34;:DISP:ENAB OFF&#34;)     
+
+            
+        if autozero:
+            self.pyvisa_resource.write(&#34;:SYST:AZER:STAT ON&#34;)          # enable auto-zero
+        else:
+            self.pyvisa_resource.write(&#34;:SYST:AZER:STAT OFF&#34;)
+        
+
+        self.pyvisa_resource.write(&#34;:SENS:%s:NPLC %d&#34;%(mode_name[measurement_mode],nplc))           # set NPLC. For a PLC of 1, the integration period would be 1/50 (for 50Hz line power) which is 20 msec
+        self.pyvisa_resource.write(&#34;:FORM:ELEM %s&#34;%mode_name[measurement_mode])
+        
+        if continuous_trigger:
+            self.pyvisa_resource.write(&#34;:ARM:SOUR TIMer&#34;)
+            self.pyvisa_resource.write(&#34;:ARM:TIMer 0.001&#34;) # minimal timer is 1 ms
+            self.pyvisa_resource.write(&#34;:ARM:COUNT INF&#34;)
+        else:
+            self.pyvisa_resource.write(&#34;:ARM:SOUR IMMediate&#34;)
+
+    def read_single(self):
+        
+        &#34;&#34;&#34; Function to read a single measurement data. The output is turn off at the end of the measurement only if continuous_trigger and output_state have been initialized as false and off
+        
+            return:
+                - data (float) : float with the value of the measurement
+        &#34;&#34;&#34;
+        self.pyvisa_resource.write(&#34;:OUTP ON&#34;)
+
+        if self.continuous_trigger:
+            self.pyvisa_resource.write(&#34;:ABORt&#34;)
+            self.pyvisa_resource.write(&#34;:ARM:COUNT 1&#34;)
+            data=float(self.pyvisa_resource.query(&#34;:READ?&#34;))
+            self.pyvisa_resource.write(&#34;:ARM:COUNT INF&#34;)
+            self.pyvisa_resource.write(&#34;:INIT&#34;)
+            
+        else:
+            data=float(self.pyvisa_resource.query(&#34;READ?&#34;))
+            self.pyvisa_resource.write(&#34;:OUTP %s&#34;%self.output_state)
+
+
+        return data
+    
+    def set_source(self,value):
+                
+        &#34;&#34;&#34; Function to set the source bias
+        
+            args:
+                - value (scalar) : value of the bias point
+        &#34;&#34;&#34;
+        if self.source_mode==&#34;current&#34;:
+            self.pyvisa_resource.write(&#34;:SOUR:CURR %.2E&#34;%value)           #set output voltage
+        elif self.source_mode==&#34;voltage&#34;:
+            self.pyvisa_resource.write(&#34;:SOUR:VOLT %.2E&#34;%value)           #set output voltage
+
+
+    def set_output(self,output_state=&#34;ON&#34;):
+                        
+        &#34;&#34;&#34; Function to set the state of the outpute 
+        
+            args:
+                - output_state (string) : &#34;ON&#34; and &#34;OFF&#34; to turn the output on or off
+        &#34;&#34;&#34;
+        self.output_state=output_state
+
+        self.pyvisa_resource.write(&#34;:OUTP %s&#34;%output_state)
+        if self.continuous_trigger:
+            self.pyvisa_resource.write(&#34;:INIT&#34;)</code></pre>
+</details>
+<div class="desc"><p>Class to control K2400 SMU</p>
+<p>Function called when an instance of the class is created</p>
+<p>args:
+- address (string) : the address of the equipment to be connected
+- rm (pyvisa object) : the pyvisa resource manager used to set the communication with the equipment
+- timeout (scalar) : the timeout set for the communication with the equipment</p></div>
+<h3>Ancestors</h3>
+<ul class="hlist">
+<li>equipment_control.equipment.equipment</li>
+</ul>
+<h3>Class variables</h3>
+<dl>
+<dt id="dopes.equipment_control.k2400.k2400.company"><code class="name">var <span class="ident">company</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="dopes.equipment_control.k2400.k2400.model"><code class="name">var <span class="ident">model</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="dopes.equipment_control.k2400.k2400.url"><code class="name">var <span class="ident">url</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+</dl>
+<h3>Methods</h3>
+<dl>
+<dt id="dopes.equipment_control.k2400.k2400.initialize"><code class="name flex">
+<span>def <span class="ident">initialize</span></span>(<span>self,<br>source_mode,<br>measurement_mode,<br>compliance,<br>autozero=True,<br>nplc=1,<br>digits=6,<br>continuous_trigger=False,<br>disp_enable=True)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def initialize(self, source_mode,measurement_mode, compliance, autozero=True, nplc=1,digits=6,continuous_trigger=False,disp_enable=True):
+    &#34;&#34;&#34; Function to initialize the K2400 SMU  with the desired settings
+    
+        args:
+            - source_mode (string) : source mode of the SMU (&#34;current&#34; or &#34;voltage&#34;)
+            - measurement_mode (string) : measurement mode of the SMU (&#34;current&#34;, &#34;voltage&#34; or &#34;resistance&#34;)
+            - compliance (scalar) : compliance of the source
+            - autozero (boolean) : if true, enable autozero of the SMU
+            - nplc (scalar) : set NPLC to set the integration time for the measurement. For a NPLC of 1, the integration period would be 1/50 (for 50Hz line power) which is 20 msec
+            - digits (int) : display resolution in number of bits
+            - continuous_trigger (boolean) : if true, the display of the equipment does not freeze after a measurement. When disabled, the instrument operates at a higher speed
+            - disp_enable (boolean) : if true, enable the front panel display circuitry. When disabled, the instrument operates at a higher speed
+    &#34;&#34;&#34;
+    mode_name={&#34;voltage&#34;:&#34;VOLT&#34;, &#34;current&#34;:&#34;CURR&#34;, &#34;resistance&#34;:&#34;RES&#34;}        
+    self.output_state=&#34;OFF&#34;
+    self.pyvisa_resource.write(&#34;*RST&#34;)
+    self.source_mode=source_mode
+    self.continuous_trigger=continuous_trigger
+    
+    if source_mode==&#34;voltage&#34;:
+        self.pyvisa_resource.write(&#34;:SOUR:FUNC VOLT&#34;)   
+        self.pyvisa_resource.write(&#34;:SENS:CURR:PROT %E&#34;%compliance)     # set automatic range
+
+    if source_mode==&#34;current&#34;:
+        self.pyvisa_resource.write(&#34;:SOUR:FUNC CURR&#34;)   
+        self.pyvisa_resource.write(&#34;:SENS:VOLT:PROT %E&#34;%compliance)     # set automatic range
+
+
+
+    if measurement_mode==&#34;voltage&#34;:
+        self.pyvisa_resource.write(&#34;:SENS:FUNC &#39;VOLT&#39;&#34;)   
+        self.pyvisa_resource.write(&#34;:SENS:VOLT:RANG:AUTO ON&#34;)     # set automatic range
+
+    elif measurement_mode==&#34;current&#34;:
+        self.pyvisa_resource.write(&#34;:SENS:FUNC &#39;CURR&#39;&#34;)   
+        self.pyvisa_resource.write(&#34;:SENS:CURR:RANG:AUTO ON&#34;)     # set automatic range
+
+    elif measurement_mode==&#34;resistance&#34;:
+        self.pyvisa_resource.write(&#34;:SENS:FUNC &#39;RES&#39;&#34;) 
+        self.pyvisa_resource.write(&#34;:SENS:RES:RANG:AUTO ON&#34;)     # set automatic range
+        
+               
+    self.pyvisa_resource.write(&#34;:DISP:DIG %d&#34;%digits)     # Query largest allowable display resolution
+    if disp_enable:
+        self.pyvisa_resource.write(&#34;:DISP:ENAB ON&#34;)     # This command is used to enable and disable the front panel display circuitry. When disabled, the instrument operates at a higher speed.
+    else:
+        self.pyvisa_resource.write(&#34;:DISP:ENAB OFF&#34;)     
+
+        
+    if autozero:
+        self.pyvisa_resource.write(&#34;:SYST:AZER:STAT ON&#34;)          # enable auto-zero
+    else:
+        self.pyvisa_resource.write(&#34;:SYST:AZER:STAT OFF&#34;)
+    
+
+    self.pyvisa_resource.write(&#34;:SENS:%s:NPLC %d&#34;%(mode_name[measurement_mode],nplc))           # set NPLC. For a PLC of 1, the integration period would be 1/50 (for 50Hz line power) which is 20 msec
+    self.pyvisa_resource.write(&#34;:FORM:ELEM %s&#34;%mode_name[measurement_mode])
+    
+    if continuous_trigger:
+        self.pyvisa_resource.write(&#34;:ARM:SOUR TIMer&#34;)
+        self.pyvisa_resource.write(&#34;:ARM:TIMer 0.001&#34;) # minimal timer is 1 ms
+        self.pyvisa_resource.write(&#34;:ARM:COUNT INF&#34;)
+    else:
+        self.pyvisa_resource.write(&#34;:ARM:SOUR IMMediate&#34;)</code></pre>
+</details>
+<div class="desc"><p>Function to initialize the K2400 SMU
+with the desired settings</p>
+<p>args:
+- source_mode (string) : source mode of the SMU ("current" or "voltage")
+- measurement_mode (string) : measurement mode of the SMU ("current", "voltage" or "resistance")
+- compliance (scalar) : compliance of the source
+- autozero (boolean) : if true, enable autozero of the SMU
+- nplc (scalar) : set NPLC to set the integration time for the measurement. For a NPLC of 1, the integration period would be 1/50 (for 50Hz line power) which is 20 msec
+- digits (int) : display resolution in number of bits
+- continuous_trigger (boolean) : if true, the display of the equipment does not freeze after a measurement. When disabled, the instrument operates at a higher speed
+- disp_enable (boolean) : if true, enable the front panel display circuitry. When disabled, the instrument operates at a higher speed</p></div>
+</dd>
+<dt id="dopes.equipment_control.k2400.k2400.read_single"><code class="name flex">
+<span>def <span class="ident">read_single</span></span>(<span>self)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def read_single(self):
+    
+    &#34;&#34;&#34; Function to read a single measurement data. The output is turn off at the end of the measurement only if continuous_trigger and output_state have been initialized as false and off
+    
+        return:
+            - data (float) : float with the value of the measurement
+    &#34;&#34;&#34;
+    self.pyvisa_resource.write(&#34;:OUTP ON&#34;)
+
+    if self.continuous_trigger:
+        self.pyvisa_resource.write(&#34;:ABORt&#34;)
+        self.pyvisa_resource.write(&#34;:ARM:COUNT 1&#34;)
+        data=float(self.pyvisa_resource.query(&#34;:READ?&#34;))
+        self.pyvisa_resource.write(&#34;:ARM:COUNT INF&#34;)
+        self.pyvisa_resource.write(&#34;:INIT&#34;)
+        
+    else:
+        data=float(self.pyvisa_resource.query(&#34;READ?&#34;))
+        self.pyvisa_resource.write(&#34;:OUTP %s&#34;%self.output_state)
+
+
+    return data</code></pre>
+</details>
+<div class="desc"><p>Function to read a single measurement data. The output is turn off at the end of the measurement only if continuous_trigger and output_state have been initialized as false and off</p>
+<p>return:
+- data (float) : float with the value of the measurement</p></div>
+</dd>
+<dt id="dopes.equipment_control.k2400.k2400.set_output"><code class="name flex">
+<span>def <span class="ident">set_output</span></span>(<span>self, output_state='ON')</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def set_output(self,output_state=&#34;ON&#34;):
+                    
+    &#34;&#34;&#34; Function to set the state of the outpute 
+    
+        args:
+            - output_state (string) : &#34;ON&#34; and &#34;OFF&#34; to turn the output on or off
+    &#34;&#34;&#34;
+    self.output_state=output_state
+
+    self.pyvisa_resource.write(&#34;:OUTP %s&#34;%output_state)
+    if self.continuous_trigger:
+        self.pyvisa_resource.write(&#34;:INIT&#34;)</code></pre>
+</details>
+<div class="desc"><p>Function to set the state of the outpute </p>
+<p>args:
+- output_state (string) : "ON" and "OFF" to turn the output on or off</p></div>
+</dd>
+<dt id="dopes.equipment_control.k2400.k2400.set_source"><code class="name flex">
+<span>def <span class="ident">set_source</span></span>(<span>self, value)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def set_source(self,value):
+            
+    &#34;&#34;&#34; Function to set the source bias
+    
+        args:
+            - value (scalar) : value of the bias point
+    &#34;&#34;&#34;
+    if self.source_mode==&#34;current&#34;:
+        self.pyvisa_resource.write(&#34;:SOUR:CURR %.2E&#34;%value)           #set output voltage
+    elif self.source_mode==&#34;voltage&#34;:
+        self.pyvisa_resource.write(&#34;:SOUR:VOLT %.2E&#34;%value)           #set output voltage</code></pre>
+</details>
+<div class="desc"><p>Function to set the source bias</p>
+<p>args:
+- value (scalar) : value of the bias point</p></div>
+</dd>
+</dl>
+</dd>
+</dl>
+</section>
+</article>
+<nav id="sidebar">
+<div class="toc">
+<ul></ul>
+</div>
+<ul id="index">
+<li><h3>Super-module</h3>
+<ul>
+<li><code><a title="dopes.equipment_control" href="index.html">dopes.equipment_control</a></code></li>
+</ul>
+</li>
+<li><h3><a href="#header-classes">Classes</a></h3>
+<ul>
+<li>
+<h4><code><a title="dopes.equipment_control.k2400.k2400" href="#dopes.equipment_control.k2400.k2400">k2400</a></code></h4>
+<ul class="two-column">
+<li><code><a title="dopes.equipment_control.k2400.k2400.company" href="#dopes.equipment_control.k2400.k2400.company">company</a></code></li>
+<li><code><a title="dopes.equipment_control.k2400.k2400.initialize" href="#dopes.equipment_control.k2400.k2400.initialize">initialize</a></code></li>
+<li><code><a title="dopes.equipment_control.k2400.k2400.model" href="#dopes.equipment_control.k2400.k2400.model">model</a></code></li>
+<li><code><a title="dopes.equipment_control.k2400.k2400.read_single" href="#dopes.equipment_control.k2400.k2400.read_single">read_single</a></code></li>
+<li><code><a title="dopes.equipment_control.k2400.k2400.set_output" href="#dopes.equipment_control.k2400.k2400.set_output">set_output</a></code></li>
+<li><code><a title="dopes.equipment_control.k2400.k2400.set_source" href="#dopes.equipment_control.k2400.k2400.set_source">set_source</a></code></li>
+<li><code><a title="dopes.equipment_control.k2400.k2400.url" href="#dopes.equipment_control.k2400.k2400.url">url</a></code></li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+</nav>
+</main>
+<footer id="footer">
+<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
+</footer>
+</body>
+</html>
diff --git a/html/equipment_control/k2450.html b/html/equipment_control/k2450.html
new file mode 100644
index 0000000000000000000000000000000000000000..6e35bb5b41b968438b330ace7fc7236d8cd98b5f
--- /dev/null
+++ b/html/equipment_control/k2450.html
@@ -0,0 +1,398 @@
+<!doctype html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
+<meta name="generator" content="pdoc3 0.11.6">
+<title>dopes.equipment_control.k2450 API documentation</title>
+<meta name="description" content="">
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/typography.min.css" integrity="sha512-Y1DYSb995BAfxobCkKepB1BqJJTPrOp3zPL74AWFugHHmmdcvO+C48WLrUOlhGMc0QG7AE3f7gmvvcrmX2fDoA==" crossorigin>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css" crossorigin>
+<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:1.5em;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:2em 0 .50em 0}h3{font-size:1.4em;margin:1.6em 0 .7em 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .2s ease-in-out}a:visited{color:#503}a:hover{color:#b62}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900;font-weight:bold}pre code{font-size:.8em;line-height:1.4em;padding:1em;display:block}code{background:#f3f3f3;font-family:"DejaVu Sans Mono",monospace;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source > summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible;min-width:max-content}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em 1em;margin:1em 0}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
+<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul ul{padding-left:1em}.toc > ul > li{margin-top:.5em}}</style>
+<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
+<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js" integrity="sha512-D9gUyxqja7hBtkWpPWGt9wfbfaMGVt9gnyCvYa+jojwwPHLCzUm5i8rpk7vD7wNee9bA35eYIjobYPaQuKS1MQ==" crossorigin></script>
+<script>window.addEventListener('DOMContentLoaded', () => {
+hljs.configure({languages: ['bash', 'css', 'diff', 'graphql', 'ini', 'javascript', 'json', 'plaintext', 'python', 'python-repl', 'rust', 'shell', 'sql', 'typescript', 'xml', 'yaml']});
+hljs.highlightAll();
+/* Collapse source docstrings */
+setTimeout(() => {
+[...document.querySelectorAll('.hljs.language-python > .hljs-string')]
+.filter(el => el.innerHTML.length > 200 && ['"""', "'''"].includes(el.innerHTML.substring(0, 3)))
+.forEach(el => {
+let d = document.createElement('details');
+d.classList.add('hljs-string');
+d.innerHTML = '<summary>"""</summary>' + el.innerHTML.substring(3);
+el.replaceWith(d);
+});
+}, 100);
+})</script>
+</head>
+<body>
+<main>
+<article id="content">
+<header>
+<h1 class="title">Module <code>dopes.equipment_control.k2450</code></h1>
+</header>
+<section id="section-intro">
+</section>
+<section>
+</section>
+<section>
+</section>
+<section>
+</section>
+<section>
+<h2 class="section-title" id="header-classes">Classes</h2>
+<dl>
+<dt id="dopes.equipment_control.k2450.k2450"><code class="flex name class">
+<span>class <span class="ident">k2450</span></span>
+<span>(</span><span>address, rm=None, timeout=10000.0)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">class k2450(equipment.equipment):
+    
+    &#34;&#34;&#34;Class to control k2450 SMU&#34;&#34;&#34;
+    model=&#34;K2400 or K2450&#34;
+    company=&#34;Keithley&#34;
+    url=&#34;https://www.tek.com/en/products/keithley/digital-multimeter/dmm7510&#34;
+
+
+    def initialize(self, source_mode,measurement_mode, compliance, autozero=True, nplc=1,digits=6,continuous_trigger=False,disp_enable=True):
+        
+        &#34;&#34;&#34; Function to initialize the K2400 SMU  with the desired settings
+        
+            args:
+                - source_mode (string) : source mode of the SMU (&#34;current&#34; or &#34;voltage&#34;)
+                - measurement_mode (string) : measurement mode of the SMU (&#34;current&#34;, &#34;voltage&#34; or &#34;resistance&#34;)
+                - compliance (scalar) : compliance of the source
+                - autozero (boolean) : if true, enable autozero of the SMU
+                - nplc (scalar) : set NPLC to set the integration time for the measurement. For a NPLC of 1, the integration period would be 1/50 (for 50Hz line power) which is 20 msec
+                - digits (int) : display resolution in number of bits
+                - continuous_trigger (boolean) : if true, the display of the equipment does not freeze after a measurement. When disabled, the instrument operates at a higher speed
+                - disp_enable (boolean) : if true, enable the front panel display circuitry. When disabled, the instrument operates at a higher speed
+        &#34;&#34;&#34;
+        mode_name={&#34;voltage&#34;:&#34;VOLT&#34;, &#34;current&#34;:&#34;CURR&#34;, &#34;resistance&#34;:&#34;RES&#34;}        
+        self.output_state=&#34;OFF&#34;
+        self.pyvisa_resource.write(&#34;*RST&#34;)
+        self.source_mode=source_mode
+        self.continuous_trigger=continuous_trigger
+        
+        if source_mode==&#34;voltage&#34;:
+            self.pyvisa_resource.write(&#34;:SOUR:FUNC VOLT&#34;)   
+            self.pyvisa_resource.write(&#34;:SOUR:VOLT:ILIM %E&#34;%compliance)     # set compliance
+
+        if source_mode==&#34;current&#34;:
+            self.pyvisa_resource.write(&#34;:SOUR:FUNC CURR&#34;)   
+            self.pyvisa_resource.write(&#34;:SOUR:CURR:VLIM %E&#34;%compliance)     # set compliance
+
+
+        if measurement_mode==&#34;voltage&#34;:
+            self.pyvisa_resource.write(&#34;:SENS:FUNC &#39;VOLT&#39;&#34;)   
+            self.pyvisa_resource.write(&#34;:SENS:VOLT:RANG:AUTO ON&#34;)     # set automatic range
+
+        elif measurement_mode==&#34;current&#34;:
+            self.pyvisa_resource.write(&#34;:SENS:FUNC &#39;CURR&#39;&#34;)   
+            self.pyvisa_resource.write(&#34;:SENS:CURR:RANG:AUTO ON&#34;)     # set automatic range
+
+        elif measurement_mode==&#34;resistance&#34;:
+            self.pyvisa_resource.write(&#34;:SENS:FUNC &#39;RES&#39;&#34;) 
+            self.pyvisa_resource.write(&#34;:SENS:RES:RANG:AUTO ON&#34;)     # set automatic range
+
+            
+        self.pyvisa_resource.write(&#34;:DISP:%s:DIG %d&#34;%(mode_name[measurement_mode],digits))   
+        self.pyvisa_resource.write(&#34;:SENS:%s:NPLC %d&#34;%(mode_name[measurement_mode],nplc))           # set NPLC. For a PLC of 1, the integration period would be 1/50 (for 50Hz line power) which is 20 msec
+
+        if disp_enable:
+            self.pyvisa_resource.write(&#34;:DISP:LIGHT:STAT ON100&#34;)     # This command is used to enable and disable the front panel display circuitry. When disabled, the instrument operates at a higher speed.
+        else:
+             self.pyvisa_resource.write(&#34;:DISP:LIGHT:STAT OFF&#34;)     # This command is used to enable and disable the front panel display circuitry. When disabled, the instrument operates at a higher speed.
+             
+        if autozero:
+            self.pyvisa_resource.write(&#34;:SENS:%s:AZER ON&#34;%mode_name[measurement_mode])          # enable auto-zero
+        else:
+            self.pyvisa_resource.write(&#34;:SENS:%s:AZER OFF&#34;%mode_name[measurement_mode])
+
+
+
+        if continuous_trigger:
+            self.pyvisa_resource.write(&#34;:TRIG:LOAD &#39;LoopUntilEvent&#39;, DISP, 0&#34;)     # able continuous triggering
+
+        else:
+            self.pyvisa_resource.write(&#34;TRIG:CONT OFF&#34;)
+
+
+          
+    def read_single(self):
+        &#34;&#34;&#34; Function to read a single measurement data. The output is turn off at the end of the measurement only if continuous_trigger and output_state have been initialized as false and off
+        
+            return:
+                - data (float) : float with the value of the measurement
+        &#34;&#34;&#34;
+        self.pyvisa_resource.write(&#34;:OUTP ON&#34;)
+
+        if self.continuous_trigger:
+            self.pyvisa_resource.write(&#34;:ABORt&#34;)    
+            data=float(self.pyvisa_resource.query(&#34;MEAS?&#34;))
+            self.pyvisa_resource.write(&#34;:TRIG:LOAD &#39;LoopUntilEvent&#39;, DISP, 0&#34;)     # able continuous triggering
+            self.pyvisa_resource.write(&#34;:INIT&#34;)     
+        else:
+            data=float(self.pyvisa_resource.query(&#34;MEAS?&#34;))
+            self.pyvisa_resource.write(&#34;:OUTP %s&#34;%self.output_state)
+
+        return data
+    
+    def set_source(self,value):
+        &#34;&#34;&#34; Function to set the source bias
+        
+            args:
+                - value (scalar) : value of the bias point
+        &#34;&#34;&#34;
+        if self.source_mode==&#34;current&#34;:
+            self.pyvisa_resource.write(&#34;:SOUR:CURR %E&#34;%value)           #set output current
+        elif self.source_mode==&#34;voltage&#34;:
+            self.pyvisa_resource.write(&#34;:SOUR:VOLT %E&#34;%value)           #set output voltage
+
+
+    def set_output(self,output_state=&#34;ON&#34;):
+        &#34;&#34;&#34; Function to set the state of the outpute 
+        
+            args:
+                - output_state (string) : &#34;ON&#34; and &#34;OFF&#34; to turn the output on or off
+        &#34;&#34;&#34;
+        self.output_state=output_state
+        self.pyvisa_resource.write(&#34;:OUTP %s&#34;%output_state)
+        if self.continuous_trigger:
+            self.pyvisa_resource.write(&#34;:INIT&#34;)</code></pre>
+</details>
+<div class="desc"><p>Class to control k2450 SMU</p>
+<p>Function called when an instance of the class is created</p>
+<p>args:
+- address (string) : the address of the equipment to be connected
+- rm (pyvisa object) : the pyvisa resource manager used to set the communication with the equipment
+- timeout (scalar) : the timeout set for the communication with the equipment</p></div>
+<h3>Ancestors</h3>
+<ul class="hlist">
+<li>equipment_control.equipment.equipment</li>
+</ul>
+<h3>Class variables</h3>
+<dl>
+<dt id="dopes.equipment_control.k2450.k2450.company"><code class="name">var <span class="ident">company</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="dopes.equipment_control.k2450.k2450.model"><code class="name">var <span class="ident">model</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="dopes.equipment_control.k2450.k2450.url"><code class="name">var <span class="ident">url</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+</dl>
+<h3>Methods</h3>
+<dl>
+<dt id="dopes.equipment_control.k2450.k2450.initialize"><code class="name flex">
+<span>def <span class="ident">initialize</span></span>(<span>self,<br>source_mode,<br>measurement_mode,<br>compliance,<br>autozero=True,<br>nplc=1,<br>digits=6,<br>continuous_trigger=False,<br>disp_enable=True)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def initialize(self, source_mode,measurement_mode, compliance, autozero=True, nplc=1,digits=6,continuous_trigger=False,disp_enable=True):
+    
+    &#34;&#34;&#34; Function to initialize the K2400 SMU  with the desired settings
+    
+        args:
+            - source_mode (string) : source mode of the SMU (&#34;current&#34; or &#34;voltage&#34;)
+            - measurement_mode (string) : measurement mode of the SMU (&#34;current&#34;, &#34;voltage&#34; or &#34;resistance&#34;)
+            - compliance (scalar) : compliance of the source
+            - autozero (boolean) : if true, enable autozero of the SMU
+            - nplc (scalar) : set NPLC to set the integration time for the measurement. For a NPLC of 1, the integration period would be 1/50 (for 50Hz line power) which is 20 msec
+            - digits (int) : display resolution in number of bits
+            - continuous_trigger (boolean) : if true, the display of the equipment does not freeze after a measurement. When disabled, the instrument operates at a higher speed
+            - disp_enable (boolean) : if true, enable the front panel display circuitry. When disabled, the instrument operates at a higher speed
+    &#34;&#34;&#34;
+    mode_name={&#34;voltage&#34;:&#34;VOLT&#34;, &#34;current&#34;:&#34;CURR&#34;, &#34;resistance&#34;:&#34;RES&#34;}        
+    self.output_state=&#34;OFF&#34;
+    self.pyvisa_resource.write(&#34;*RST&#34;)
+    self.source_mode=source_mode
+    self.continuous_trigger=continuous_trigger
+    
+    if source_mode==&#34;voltage&#34;:
+        self.pyvisa_resource.write(&#34;:SOUR:FUNC VOLT&#34;)   
+        self.pyvisa_resource.write(&#34;:SOUR:VOLT:ILIM %E&#34;%compliance)     # set compliance
+
+    if source_mode==&#34;current&#34;:
+        self.pyvisa_resource.write(&#34;:SOUR:FUNC CURR&#34;)   
+        self.pyvisa_resource.write(&#34;:SOUR:CURR:VLIM %E&#34;%compliance)     # set compliance
+
+
+    if measurement_mode==&#34;voltage&#34;:
+        self.pyvisa_resource.write(&#34;:SENS:FUNC &#39;VOLT&#39;&#34;)   
+        self.pyvisa_resource.write(&#34;:SENS:VOLT:RANG:AUTO ON&#34;)     # set automatic range
+
+    elif measurement_mode==&#34;current&#34;:
+        self.pyvisa_resource.write(&#34;:SENS:FUNC &#39;CURR&#39;&#34;)   
+        self.pyvisa_resource.write(&#34;:SENS:CURR:RANG:AUTO ON&#34;)     # set automatic range
+
+    elif measurement_mode==&#34;resistance&#34;:
+        self.pyvisa_resource.write(&#34;:SENS:FUNC &#39;RES&#39;&#34;) 
+        self.pyvisa_resource.write(&#34;:SENS:RES:RANG:AUTO ON&#34;)     # set automatic range
+
+        
+    self.pyvisa_resource.write(&#34;:DISP:%s:DIG %d&#34;%(mode_name[measurement_mode],digits))   
+    self.pyvisa_resource.write(&#34;:SENS:%s:NPLC %d&#34;%(mode_name[measurement_mode],nplc))           # set NPLC. For a PLC of 1, the integration period would be 1/50 (for 50Hz line power) which is 20 msec
+
+    if disp_enable:
+        self.pyvisa_resource.write(&#34;:DISP:LIGHT:STAT ON100&#34;)     # This command is used to enable and disable the front panel display circuitry. When disabled, the instrument operates at a higher speed.
+    else:
+         self.pyvisa_resource.write(&#34;:DISP:LIGHT:STAT OFF&#34;)     # This command is used to enable and disable the front panel display circuitry. When disabled, the instrument operates at a higher speed.
+         
+    if autozero:
+        self.pyvisa_resource.write(&#34;:SENS:%s:AZER ON&#34;%mode_name[measurement_mode])          # enable auto-zero
+    else:
+        self.pyvisa_resource.write(&#34;:SENS:%s:AZER OFF&#34;%mode_name[measurement_mode])
+
+
+
+    if continuous_trigger:
+        self.pyvisa_resource.write(&#34;:TRIG:LOAD &#39;LoopUntilEvent&#39;, DISP, 0&#34;)     # able continuous triggering
+
+    else:
+        self.pyvisa_resource.write(&#34;TRIG:CONT OFF&#34;)</code></pre>
+</details>
+<div class="desc"><p>Function to initialize the K2400 SMU
+with the desired settings</p>
+<p>args:
+- source_mode (string) : source mode of the SMU ("current" or "voltage")
+- measurement_mode (string) : measurement mode of the SMU ("current", "voltage" or "resistance")
+- compliance (scalar) : compliance of the source
+- autozero (boolean) : if true, enable autozero of the SMU
+- nplc (scalar) : set NPLC to set the integration time for the measurement. For a NPLC of 1, the integration period would be 1/50 (for 50Hz line power) which is 20 msec
+- digits (int) : display resolution in number of bits
+- continuous_trigger (boolean) : if true, the display of the equipment does not freeze after a measurement. When disabled, the instrument operates at a higher speed
+- disp_enable (boolean) : if true, enable the front panel display circuitry. When disabled, the instrument operates at a higher speed</p></div>
+</dd>
+<dt id="dopes.equipment_control.k2450.k2450.read_single"><code class="name flex">
+<span>def <span class="ident">read_single</span></span>(<span>self)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def read_single(self):
+    &#34;&#34;&#34; Function to read a single measurement data. The output is turn off at the end of the measurement only if continuous_trigger and output_state have been initialized as false and off
+    
+        return:
+            - data (float) : float with the value of the measurement
+    &#34;&#34;&#34;
+    self.pyvisa_resource.write(&#34;:OUTP ON&#34;)
+
+    if self.continuous_trigger:
+        self.pyvisa_resource.write(&#34;:ABORt&#34;)    
+        data=float(self.pyvisa_resource.query(&#34;MEAS?&#34;))
+        self.pyvisa_resource.write(&#34;:TRIG:LOAD &#39;LoopUntilEvent&#39;, DISP, 0&#34;)     # able continuous triggering
+        self.pyvisa_resource.write(&#34;:INIT&#34;)     
+    else:
+        data=float(self.pyvisa_resource.query(&#34;MEAS?&#34;))
+        self.pyvisa_resource.write(&#34;:OUTP %s&#34;%self.output_state)
+
+    return data</code></pre>
+</details>
+<div class="desc"><p>Function to read a single measurement data. The output is turn off at the end of the measurement only if continuous_trigger and output_state have been initialized as false and off</p>
+<p>return:
+- data (float) : float with the value of the measurement</p></div>
+</dd>
+<dt id="dopes.equipment_control.k2450.k2450.set_output"><code class="name flex">
+<span>def <span class="ident">set_output</span></span>(<span>self, output_state='ON')</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def set_output(self,output_state=&#34;ON&#34;):
+    &#34;&#34;&#34; Function to set the state of the outpute 
+    
+        args:
+            - output_state (string) : &#34;ON&#34; and &#34;OFF&#34; to turn the output on or off
+    &#34;&#34;&#34;
+    self.output_state=output_state
+    self.pyvisa_resource.write(&#34;:OUTP %s&#34;%output_state)
+    if self.continuous_trigger:
+        self.pyvisa_resource.write(&#34;:INIT&#34;)</code></pre>
+</details>
+<div class="desc"><p>Function to set the state of the outpute </p>
+<p>args:
+- output_state (string) : "ON" and "OFF" to turn the output on or off</p></div>
+</dd>
+<dt id="dopes.equipment_control.k2450.k2450.set_source"><code class="name flex">
+<span>def <span class="ident">set_source</span></span>(<span>self, value)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def set_source(self,value):
+    &#34;&#34;&#34; Function to set the source bias
+    
+        args:
+            - value (scalar) : value of the bias point
+    &#34;&#34;&#34;
+    if self.source_mode==&#34;current&#34;:
+        self.pyvisa_resource.write(&#34;:SOUR:CURR %E&#34;%value)           #set output current
+    elif self.source_mode==&#34;voltage&#34;:
+        self.pyvisa_resource.write(&#34;:SOUR:VOLT %E&#34;%value)           #set output voltage</code></pre>
+</details>
+<div class="desc"><p>Function to set the source bias</p>
+<p>args:
+- value (scalar) : value of the bias point</p></div>
+</dd>
+</dl>
+</dd>
+</dl>
+</section>
+</article>
+<nav id="sidebar">
+<div class="toc">
+<ul></ul>
+</div>
+<ul id="index">
+<li><h3>Super-module</h3>
+<ul>
+<li><code><a title="dopes.equipment_control" href="index.html">dopes.equipment_control</a></code></li>
+</ul>
+</li>
+<li><h3><a href="#header-classes">Classes</a></h3>
+<ul>
+<li>
+<h4><code><a title="dopes.equipment_control.k2450.k2450" href="#dopes.equipment_control.k2450.k2450">k2450</a></code></h4>
+<ul class="two-column">
+<li><code><a title="dopes.equipment_control.k2450.k2450.company" href="#dopes.equipment_control.k2450.k2450.company">company</a></code></li>
+<li><code><a title="dopes.equipment_control.k2450.k2450.initialize" href="#dopes.equipment_control.k2450.k2450.initialize">initialize</a></code></li>
+<li><code><a title="dopes.equipment_control.k2450.k2450.model" href="#dopes.equipment_control.k2450.k2450.model">model</a></code></li>
+<li><code><a title="dopes.equipment_control.k2450.k2450.read_single" href="#dopes.equipment_control.k2450.k2450.read_single">read_single</a></code></li>
+<li><code><a title="dopes.equipment_control.k2450.k2450.set_output" href="#dopes.equipment_control.k2450.k2450.set_output">set_output</a></code></li>
+<li><code><a title="dopes.equipment_control.k2450.k2450.set_source" href="#dopes.equipment_control.k2450.k2450.set_source">set_source</a></code></li>
+<li><code><a title="dopes.equipment_control.k2450.k2450.url" href="#dopes.equipment_control.k2450.k2450.url">url</a></code></li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+</nav>
+</main>
+<footer id="footer">
+<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
+</footer>
+</body>
+</html>
diff --git a/html/equipment_control/k4200.html b/html/equipment_control/k4200.html
new file mode 100644
index 0000000000000000000000000000000000000000..8dbf9f4b3f165d6f0308aa74b785380af9b2645a
--- /dev/null
+++ b/html/equipment_control/k4200.html
@@ -0,0 +1,443 @@
+<!doctype html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
+<meta name="generator" content="pdoc3 0.11.6">
+<title>dopes.equipment_control.k4200 API documentation</title>
+<meta name="description" content="">
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/typography.min.css" integrity="sha512-Y1DYSb995BAfxobCkKepB1BqJJTPrOp3zPL74AWFugHHmmdcvO+C48WLrUOlhGMc0QG7AE3f7gmvvcrmX2fDoA==" crossorigin>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css" crossorigin>
+<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:1.5em;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:2em 0 .50em 0}h3{font-size:1.4em;margin:1.6em 0 .7em 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .2s ease-in-out}a:visited{color:#503}a:hover{color:#b62}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900;font-weight:bold}pre code{font-size:.8em;line-height:1.4em;padding:1em;display:block}code{background:#f3f3f3;font-family:"DejaVu Sans Mono",monospace;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source > summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible;min-width:max-content}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em 1em;margin:1em 0}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
+<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul ul{padding-left:1em}.toc > ul > li{margin-top:.5em}}</style>
+<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
+<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js" integrity="sha512-D9gUyxqja7hBtkWpPWGt9wfbfaMGVt9gnyCvYa+jojwwPHLCzUm5i8rpk7vD7wNee9bA35eYIjobYPaQuKS1MQ==" crossorigin></script>
+<script>window.addEventListener('DOMContentLoaded', () => {
+hljs.configure({languages: ['bash', 'css', 'diff', 'graphql', 'ini', 'javascript', 'json', 'plaintext', 'python', 'python-repl', 'rust', 'shell', 'sql', 'typescript', 'xml', 'yaml']});
+hljs.highlightAll();
+/* Collapse source docstrings */
+setTimeout(() => {
+[...document.querySelectorAll('.hljs.language-python > .hljs-string')]
+.filter(el => el.innerHTML.length > 200 && ['"""', "'''"].includes(el.innerHTML.substring(0, 3)))
+.forEach(el => {
+let d = document.createElement('details');
+d.classList.add('hljs-string');
+d.innerHTML = '<summary>"""</summary>' + el.innerHTML.substring(3);
+el.replaceWith(d);
+});
+}, 100);
+})</script>
+</head>
+<body>
+<main>
+<article id="content">
+<header>
+<h1 class="title">Module <code>dopes.equipment_control.k4200</code></h1>
+</header>
+<section id="section-intro">
+</section>
+<section>
+</section>
+<section>
+</section>
+<section>
+</section>
+<section>
+<h2 class="section-title" id="header-classes">Classes</h2>
+<dl>
+<dt id="dopes.equipment_control.k4200.k4200"><code class="flex name class">
+<span>class <span class="ident">k4200</span></span>
+<span>(</span><span>address, rm=None, timeout=10000.0)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">class k4200(equipment.equipment):
+    
+    &#34;&#34;&#34;Class to control K4200 semiconductor analyzer&#34;&#34;&#34;
+    model=&#34;K4200&#34;
+    company=&#34;Keysight&#34;
+    url=&#34;https://www.tek.com/en/products/keithley/4200a-scs-parameter-analyzer&#34;
+    
+    def initialize(self, smu_type={&#34;SMU1&#34;:&#34;voltage&#34;,&#34;SMU2&#34;:&#34;voltage&#34;,&#34;SMU3&#34;:&#34;common&#34;,&#34;SMU4&#34;:&#34;common&#34;}, 
+                   smu_used={&#34;SMU1&#34;:&#34;on&#34;,&#34;SMU2&#34;:&#34;on&#34;,&#34;SMU3&#34;:&#34;on&#34;,&#34;SMU4&#34;:&#34;on&#34;}, 
+                   smu_master=1,smu_bias={&#34;SMU1&#34;:0,&#34;SMU2&#34;:0,&#34;SMU3&#34;:0,&#34;SMU4&#34;:0},
+                   smu_compliance={&#34;SMU1&#34;:1e-6,&#34;SMU2&#34;:1e-6,&#34;SMU3&#34;:1e-6,&#34;SMU4&#34;:1e-6},
+                   sweep_param={&#34;start&#34;:0,&#34;stop&#34;:0,&#34;step&#34;:0}, sweep_type=&#34;linear&#34;,
+                   integration_mode=&#34;S&#34;,delay_time=0,hold_time=0):
+        
+        
+        
+        &#34;&#34;&#34; Function to initialize the K4200 equipment with the desired settings
+        
+            args:
+                - smu_type (dictionary) : dictionary indicated for each SMU (&#34;SMU1&#34;,&#34;SMU2&#34;,&#34;SMU3&#34; and &#34;SMU4&#34;) the bias type (&#34;voltage&#34;, &#34;current&#34; or &#34;common&#34;)
+                - smu_used (dictionary) : dictionary indicated for each SMU (&#34;SMU1&#34;,&#34;SMU2&#34;,&#34;SMU3&#34; and &#34;SMU4&#34;) if active or not (&#34;on&#34; or &#34;off&#34;)
+                - smu_master (int) : integer to indicate which SMU performs the sweep
+                - smu_bias (dictionary) : dictionary indicated for each SMU (&#34;SMU1&#34;,&#34;SMU2&#34;,&#34;SMU3&#34; and &#34;SMU4&#34;) the bias point (scalar)
+                - smu_compliance (dictionary) : dictionary indicated for each SMU (&#34;SMU1&#34;,&#34;SMU2&#34;,&#34;SMU3&#34; and &#34;SMU4&#34;) the compliance (scalar)
+                - sweep_param (dictionary) : dictionary indicated the starting bias (&#34;start&#34;), the stoping bias (&#34;stop&#34;) and step (&#34;step&#34;) of the sweep
+                - sweep_type (string) : string to indicate linear (&#34;linear&#34;) sweep or logarithmic (&#34;log&#34;) sweep
+                - integration_mode (string) : set the integration time parameter (&#34;S&#34; for short, &#34;M&#34; for medium and &#34;L&#34; for long)
+                - delay_time (scalar) : the time to wait between when the output voltage is set and when the measurement is made in a sweep
+                - hold_time (scalar) : hold time that delays the start of a sweep
+        &#34;&#34;&#34;
+        self.smu_type=smu_type
+        self.sweep_type=sweep_type
+        self.smu_used=smu_used
+        self.smu_master=smu_master
+        self.sweep_param=sweep_param
+        self.smu_compliance=smu_compliance
+        self.smu_bias=smu_bias
+        self.integration_mode=integration_mode
+        self.delay_time=delay_time
+        self.hold_time=hold_time
+        
+        index_measurement_type={&#34;sweep&#34;:1, &#34;constant&#34;:3}
+        index_smu_type={&#34;voltage&#34;:1, &#34;current&#34;:2, &#34;common&#34;:3}
+        integration_dictionnary={&#34;S&#34;:&#34;IT1&#34;,&#34;M&#34;:&#34;IT2&#34;,&#34;L&#34;:&#34;IT3&#34;}
+
+        try:
+            self.pyvisa_resource.write(&#34;BC&#34;) # clear all buffer.
+            self.pyvisa_resource.write(&#34;DR1&#34;) # This command enables or disables service request for data ready when communications is set to GPIB.
+            self.pyvisa_resource.write(&#34;EC 1&#34;) # This command sets the condition to exit the test if compliance is reached.
+            
+                
+            self.pyvisa_resource.write(&#34;DE&#34;) # DE: Accesses SMU channel definition page.
+            
+            self.pyvisa_resource.write(&#34;CH%d, &#39;V%d&#39;, &#39;I%d&#39;, %d, %d&#34;%(smu_master,smu_master,smu_master,index_smu_type[smu_type[&#34;SMU%d&#34;%smu_master]],index_measurement_type[&#34;sweep&#34;])) # 1/2/3: voltage/current/Common 1/2/3: VAR1/VAR2/constant
+            
+            for smu_index in range(4):
+                if (smu_index+1!=smu_master) and smu_used[&#34;SMU%d&#34;%(smu_index+1)]==&#34;off&#34;:
+                    self.pyvisa_resource.write(&#34;CH%d&#34;%(smu_index+1)) 
+                elif (smu_index+1!=smu_master) and smu_used[&#34;SMU%d&#34;%(smu_index+1)]==&#34;on&#34;:
+                    self.pyvisa_resource.write(&#34;CH%d, &#39;V%d&#39;, &#39;I%d&#39;, %d, %d&#34;%(smu_index+1,smu_index+1,smu_index+1,index_smu_type[smu_type[&#34;SMU%d&#34;%(smu_index+1)]],index_measurement_type[&#34;constant&#34;])) 
+
+            self.pyvisa_resource.write(&#34;SS&#34;)# Accesses source setup page
+            if smu_type[&#34;SMU%d&#34;%smu_master]==&#34;voltage&#34;:
+                if sweep_type==&#34;linear&#34;:
+                    self.pyvisa_resource.write(&#34;VR1, %.6E, %.6E, %.6E, %.6E&#34;%(sweep_param[&#34;start&#34;],sweep_param[&#34;stop&#34;],sweep_param[&#34;step&#34;],smu_compliance[&#34;SMU%d&#34;%smu_master])) # VR1 for linear sweep of VAR1 source function, vmin, vmax,vstep, compliance
+                elif sweep_type==&#34;log&#34;:
+                    self.pyvisa_resource.write(&#34;VR2, %.6E, %.6E, %.6E&#34;%(sweep_param[&#34;start&#34;],sweep_param[&#34;stop&#34;],smu_compliance[&#34;SMU%d&#34;%smu_master])) # VR2 for log sweep of VAR1 source function, vmin, vmax, compliance
+            elif smu_type[&#34;SMU%d&#34;%smu_master]==&#34;current&#34;:
+                if sweep_type==&#34;linear&#34;:
+                    self.pyvisa_resource.write(&#34;IR1, %.6E, %.6E, %.6E, %.6E&#34;%(sweep_param[&#34;start&#34;],sweep_param[&#34;stop&#34;],sweep_param[&#34;step&#34;],smu_compliance[&#34;SMU%d&#34;%smu_master])) # IR1 for linear sweep of VAR1 source function, vmin, vmax,vstep, compliance
+                elif sweep_type==&#34;log&#34;:
+                    self.pyvisa_resource.write(&#34;IR2, %.6E, %.6E, %.6E&#34;%(sweep_param[&#34;start&#34;],sweep_param[&#34;stop&#34;],smu_compliance[&#34;SMU%d&#34;%smu_master])) # IR2 for log sweep of VAR1 source function, vmin, vmax, compliance
+            
+            for smu_index in range(4):
+                if (smu_index+1!=smu_master) and smu_used[&#34;SMU%d&#34;%(smu_index+1)]==&#34;on&#34;:
+                    if smu_type[&#34;SMU%d&#34;%(smu_index+1)]==&#34;voltage&#34;:
+                        self.pyvisa_resource.write(&#34;VC%d, %.2f, %.6E&#34;%(smu_index+1,smu_bias[&#34;SMU%d&#34;%(smu_index+1)],smu_compliance[&#34;SMU%d&#34;%(smu_index+1)]))
+                    elif smu_type[&#34;SMU%d&#34;%(smu_index+1)]==&#34;current&#34;:
+                        self.pyvisa_resource.write(&#34;IC%d, %.2f, %.6E&#34;%(smu_index+1,smu_bias[&#34;SMU%d&#34;%(smu_index+1)],smu_compliance[&#34;SMU%d&#34;%(smu_index+1)]))
+
+            self.pyvisa_resource.write(&#34;HT %f&#34;%hold_time) # Sets a hold time that delays the start of a sweep
+            self.pyvisa_resource.write(&#34;DT %f&#34;%delay_time) # delay time: Sets the time to wait between when the output voltage is set and when the measurement is made in a sweep.
+            self.pyvisa_resource.write(integration_dictionnary[integration_mode]) # integration time, IT1/IT2/IT3 : short/medium/long
+
+
+            self.pyvisa_resource.write(&#34;SM&#34;)
+            self.pyvisa_resource.write(&#34;DM2&#34;)
+            list_display=&#34;&#34;
+            for smu_index in range(4):
+                if self.smu_used[&#34;SMU%d&#34;%(smu_index+1)]==&#34;on&#34;:
+                    if self.smu_type[&#34;SMU%d&#34;%(smu_index+1)]==&#34;voltage&#34;:
+                        list_display+=&#34;,&#39;%s%d&#39;&#34;%(&#34;I&#34;,smu_index+1)
+                    elif self.smu_type[&#34;SMU%d&#34;%(smu_index+1)]==&#34;current&#34;:
+                        list_display+=&#34;,&#39;%s%d&#39;&#34;%(&#34;V&#34;,smu_index+1)
+                        
+            self.pyvisa_resource.write(&#34;LI %s&#34;%list_display[1:])
+        except pyvisa.VisaIOError:
+            print(&#34;/!\ VisaIOError : timeout expired&#34;)
+            self.pyvisa_resource.close()
+        
+    
+    def launch_measurements(self):
+        &#34;&#34;&#34; Function that launch the measurement and return the data (in array shape) and the header (string) depending on the measurement configuration
+        
+            return:
+                - data (array) : array with the measurement data
+                - header (string) : string with the description of the data column &#34;Vx&#34; or &#34;Ix&#34; for voltage or current measured from SMUx.
+        &#34;&#34;&#34;            
+        number_channel=0
+        for smu_index in range(4):
+            if self.smu_used[&#34;SMU%d&#34;%(smu_index+1)]==&#34;on&#34;:
+                number_channel+=1
+        sweep_list=np.round(np.arange(self.sweep_param[&#34;start&#34;],self.sweep_param[&#34;stop&#34;]+self.sweep_param[&#34;step&#34;],self.sweep_param[&#34;step&#34;]),6)
+        N_sweep=len(sweep_list)
+        data=np.zeros((N_sweep,number_channel+1))
+        data[:,0]=sweep_list
+
+        
+        self.pyvisa_resource.write(&#34;MD&#34;) # This command controls measurements.
+        self.pyvisa_resource.write(&#34;ME1&#34;) # Run a single trigger test and store readings in a cleared buffer: 1
+        time.sleep(1)
+        j=0               
+        while (j&lt;N_sweep):
+            if self.smu_type[&#34;SMU%d&#34;%(self.smu_master)]==&#34;voltage&#34;:
+                data_master=np.float32(self.pyvisa_resource.query(&#34;RD &#39;I%d&#39;, %d&#34;%(self.smu_master,j+1)))
+            elif self.smu_type[&#34;SMU%d&#34;%(self.smu_master)]==&#34;current&#34;:
+                data_master=np.float32(self.pyvisa_resource.query(&#34;RD &#39;V%d&#39;, %d&#34;%(self.smu_master,j+1)))
+            if (data_master!=0.):
+                i=0
+                for smu_index in range(4):
+                    if self.smu_used[&#34;SMU%d&#34;%(smu_index+1)]==&#34;on&#34;:
+                        i+=1
+                        if self.smu_type[&#34;SMU%d&#34;%(smu_index+1)]==&#34;voltage&#34;:
+                            data[j,i]=np.float32(self.pyvisa_resource.query(&#34;RD &#39;I%d&#39;, %d&#34;%(smu_index+1,j+1)))# Read measurements
+                        elif self.smu_type[&#34;SMU%d&#34;%(smu_index+1)]==&#34;current&#34;:
+                            data[j,i]=np.float32(self.pyvisa_resource.query(&#34;RD &#39;V%d&#39;, %d&#34;%(smu_index+1,j+1)))# Read measurements
+                            
+                j+=1
+            time.sleep(0.1)
+        header=&#34;%s%d&#34;%(self.smu_type[&#34;SMU%d&#34;%self.smu_master][0].upper(),self.smu_master)
+        for smu_index in range(4):
+            if self.smu_used[&#34;SMU%d&#34;%(smu_index+1)]==&#34;on&#34;:
+                if self.smu_type[&#34;SMU%d&#34;%(smu_index+1)]==&#34;voltage&#34;:
+                    header+=&#34;, %s%d&#34;%(&#34;I&#34;,smu_index+1)
+                elif self.smu_type[&#34;SMU%d&#34;%(smu_index+1)]==&#34;current&#34;:
+                    header+=&#34;, %s%d&#34;%(&#34;V&#34;,smu_index+1)
+        return data, header</code></pre>
+</details>
+<div class="desc"><p>Class to control K4200 semiconductor analyzer</p>
+<p>Function called when an instance of the class is created</p>
+<p>args:
+- address (string) : the address of the equipment to be connected
+- rm (pyvisa object) : the pyvisa resource manager used to set the communication with the equipment
+- timeout (scalar) : the timeout set for the communication with the equipment</p></div>
+<h3>Ancestors</h3>
+<ul class="hlist">
+<li>equipment_control.equipment.equipment</li>
+</ul>
+<h3>Class variables</h3>
+<dl>
+<dt id="dopes.equipment_control.k4200.k4200.company"><code class="name">var <span class="ident">company</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="dopes.equipment_control.k4200.k4200.model"><code class="name">var <span class="ident">model</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="dopes.equipment_control.k4200.k4200.url"><code class="name">var <span class="ident">url</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+</dl>
+<h3>Methods</h3>
+<dl>
+<dt id="dopes.equipment_control.k4200.k4200.initialize"><code class="name flex">
+<span>def <span class="ident">initialize</span></span>(<span>self,<br>smu_type={'SMU1': 'voltage', 'SMU2': 'voltage', 'SMU3': 'common', 'SMU4': 'common'},<br>smu_used={'SMU1': 'on', 'SMU2': 'on', 'SMU3': 'on', 'SMU4': 'on'},<br>smu_master=1,<br>smu_bias={'SMU1': 0, 'SMU2': 0, 'SMU3': 0, 'SMU4': 0},<br>smu_compliance={'SMU1': 1e-06, 'SMU2': 1e-06, 'SMU3': 1e-06, 'SMU4': 1e-06},<br>sweep_param={'start': 0, 'stop': 0, 'step': 0},<br>sweep_type='linear',<br>integration_mode='S',<br>delay_time=0,<br>hold_time=0)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def initialize(self, smu_type={&#34;SMU1&#34;:&#34;voltage&#34;,&#34;SMU2&#34;:&#34;voltage&#34;,&#34;SMU3&#34;:&#34;common&#34;,&#34;SMU4&#34;:&#34;common&#34;}, 
+               smu_used={&#34;SMU1&#34;:&#34;on&#34;,&#34;SMU2&#34;:&#34;on&#34;,&#34;SMU3&#34;:&#34;on&#34;,&#34;SMU4&#34;:&#34;on&#34;}, 
+               smu_master=1,smu_bias={&#34;SMU1&#34;:0,&#34;SMU2&#34;:0,&#34;SMU3&#34;:0,&#34;SMU4&#34;:0},
+               smu_compliance={&#34;SMU1&#34;:1e-6,&#34;SMU2&#34;:1e-6,&#34;SMU3&#34;:1e-6,&#34;SMU4&#34;:1e-6},
+               sweep_param={&#34;start&#34;:0,&#34;stop&#34;:0,&#34;step&#34;:0}, sweep_type=&#34;linear&#34;,
+               integration_mode=&#34;S&#34;,delay_time=0,hold_time=0):
+    
+    
+    
+    &#34;&#34;&#34; Function to initialize the K4200 equipment with the desired settings
+    
+        args:
+            - smu_type (dictionary) : dictionary indicated for each SMU (&#34;SMU1&#34;,&#34;SMU2&#34;,&#34;SMU3&#34; and &#34;SMU4&#34;) the bias type (&#34;voltage&#34;, &#34;current&#34; or &#34;common&#34;)
+            - smu_used (dictionary) : dictionary indicated for each SMU (&#34;SMU1&#34;,&#34;SMU2&#34;,&#34;SMU3&#34; and &#34;SMU4&#34;) if active or not (&#34;on&#34; or &#34;off&#34;)
+            - smu_master (int) : integer to indicate which SMU performs the sweep
+            - smu_bias (dictionary) : dictionary indicated for each SMU (&#34;SMU1&#34;,&#34;SMU2&#34;,&#34;SMU3&#34; and &#34;SMU4&#34;) the bias point (scalar)
+            - smu_compliance (dictionary) : dictionary indicated for each SMU (&#34;SMU1&#34;,&#34;SMU2&#34;,&#34;SMU3&#34; and &#34;SMU4&#34;) the compliance (scalar)
+            - sweep_param (dictionary) : dictionary indicated the starting bias (&#34;start&#34;), the stoping bias (&#34;stop&#34;) and step (&#34;step&#34;) of the sweep
+            - sweep_type (string) : string to indicate linear (&#34;linear&#34;) sweep or logarithmic (&#34;log&#34;) sweep
+            - integration_mode (string) : set the integration time parameter (&#34;S&#34; for short, &#34;M&#34; for medium and &#34;L&#34; for long)
+            - delay_time (scalar) : the time to wait between when the output voltage is set and when the measurement is made in a sweep
+            - hold_time (scalar) : hold time that delays the start of a sweep
+    &#34;&#34;&#34;
+    self.smu_type=smu_type
+    self.sweep_type=sweep_type
+    self.smu_used=smu_used
+    self.smu_master=smu_master
+    self.sweep_param=sweep_param
+    self.smu_compliance=smu_compliance
+    self.smu_bias=smu_bias
+    self.integration_mode=integration_mode
+    self.delay_time=delay_time
+    self.hold_time=hold_time
+    
+    index_measurement_type={&#34;sweep&#34;:1, &#34;constant&#34;:3}
+    index_smu_type={&#34;voltage&#34;:1, &#34;current&#34;:2, &#34;common&#34;:3}
+    integration_dictionnary={&#34;S&#34;:&#34;IT1&#34;,&#34;M&#34;:&#34;IT2&#34;,&#34;L&#34;:&#34;IT3&#34;}
+
+    try:
+        self.pyvisa_resource.write(&#34;BC&#34;) # clear all buffer.
+        self.pyvisa_resource.write(&#34;DR1&#34;) # This command enables or disables service request for data ready when communications is set to GPIB.
+        self.pyvisa_resource.write(&#34;EC 1&#34;) # This command sets the condition to exit the test if compliance is reached.
+        
+            
+        self.pyvisa_resource.write(&#34;DE&#34;) # DE: Accesses SMU channel definition page.
+        
+        self.pyvisa_resource.write(&#34;CH%d, &#39;V%d&#39;, &#39;I%d&#39;, %d, %d&#34;%(smu_master,smu_master,smu_master,index_smu_type[smu_type[&#34;SMU%d&#34;%smu_master]],index_measurement_type[&#34;sweep&#34;])) # 1/2/3: voltage/current/Common 1/2/3: VAR1/VAR2/constant
+        
+        for smu_index in range(4):
+            if (smu_index+1!=smu_master) and smu_used[&#34;SMU%d&#34;%(smu_index+1)]==&#34;off&#34;:
+                self.pyvisa_resource.write(&#34;CH%d&#34;%(smu_index+1)) 
+            elif (smu_index+1!=smu_master) and smu_used[&#34;SMU%d&#34;%(smu_index+1)]==&#34;on&#34;:
+                self.pyvisa_resource.write(&#34;CH%d, &#39;V%d&#39;, &#39;I%d&#39;, %d, %d&#34;%(smu_index+1,smu_index+1,smu_index+1,index_smu_type[smu_type[&#34;SMU%d&#34;%(smu_index+1)]],index_measurement_type[&#34;constant&#34;])) 
+
+        self.pyvisa_resource.write(&#34;SS&#34;)# Accesses source setup page
+        if smu_type[&#34;SMU%d&#34;%smu_master]==&#34;voltage&#34;:
+            if sweep_type==&#34;linear&#34;:
+                self.pyvisa_resource.write(&#34;VR1, %.6E, %.6E, %.6E, %.6E&#34;%(sweep_param[&#34;start&#34;],sweep_param[&#34;stop&#34;],sweep_param[&#34;step&#34;],smu_compliance[&#34;SMU%d&#34;%smu_master])) # VR1 for linear sweep of VAR1 source function, vmin, vmax,vstep, compliance
+            elif sweep_type==&#34;log&#34;:
+                self.pyvisa_resource.write(&#34;VR2, %.6E, %.6E, %.6E&#34;%(sweep_param[&#34;start&#34;],sweep_param[&#34;stop&#34;],smu_compliance[&#34;SMU%d&#34;%smu_master])) # VR2 for log sweep of VAR1 source function, vmin, vmax, compliance
+        elif smu_type[&#34;SMU%d&#34;%smu_master]==&#34;current&#34;:
+            if sweep_type==&#34;linear&#34;:
+                self.pyvisa_resource.write(&#34;IR1, %.6E, %.6E, %.6E, %.6E&#34;%(sweep_param[&#34;start&#34;],sweep_param[&#34;stop&#34;],sweep_param[&#34;step&#34;],smu_compliance[&#34;SMU%d&#34;%smu_master])) # IR1 for linear sweep of VAR1 source function, vmin, vmax,vstep, compliance
+            elif sweep_type==&#34;log&#34;:
+                self.pyvisa_resource.write(&#34;IR2, %.6E, %.6E, %.6E&#34;%(sweep_param[&#34;start&#34;],sweep_param[&#34;stop&#34;],smu_compliance[&#34;SMU%d&#34;%smu_master])) # IR2 for log sweep of VAR1 source function, vmin, vmax, compliance
+        
+        for smu_index in range(4):
+            if (smu_index+1!=smu_master) and smu_used[&#34;SMU%d&#34;%(smu_index+1)]==&#34;on&#34;:
+                if smu_type[&#34;SMU%d&#34;%(smu_index+1)]==&#34;voltage&#34;:
+                    self.pyvisa_resource.write(&#34;VC%d, %.2f, %.6E&#34;%(smu_index+1,smu_bias[&#34;SMU%d&#34;%(smu_index+1)],smu_compliance[&#34;SMU%d&#34;%(smu_index+1)]))
+                elif smu_type[&#34;SMU%d&#34;%(smu_index+1)]==&#34;current&#34;:
+                    self.pyvisa_resource.write(&#34;IC%d, %.2f, %.6E&#34;%(smu_index+1,smu_bias[&#34;SMU%d&#34;%(smu_index+1)],smu_compliance[&#34;SMU%d&#34;%(smu_index+1)]))
+
+        self.pyvisa_resource.write(&#34;HT %f&#34;%hold_time) # Sets a hold time that delays the start of a sweep
+        self.pyvisa_resource.write(&#34;DT %f&#34;%delay_time) # delay time: Sets the time to wait between when the output voltage is set and when the measurement is made in a sweep.
+        self.pyvisa_resource.write(integration_dictionnary[integration_mode]) # integration time, IT1/IT2/IT3 : short/medium/long
+
+
+        self.pyvisa_resource.write(&#34;SM&#34;)
+        self.pyvisa_resource.write(&#34;DM2&#34;)
+        list_display=&#34;&#34;
+        for smu_index in range(4):
+            if self.smu_used[&#34;SMU%d&#34;%(smu_index+1)]==&#34;on&#34;:
+                if self.smu_type[&#34;SMU%d&#34;%(smu_index+1)]==&#34;voltage&#34;:
+                    list_display+=&#34;,&#39;%s%d&#39;&#34;%(&#34;I&#34;,smu_index+1)
+                elif self.smu_type[&#34;SMU%d&#34;%(smu_index+1)]==&#34;current&#34;:
+                    list_display+=&#34;,&#39;%s%d&#39;&#34;%(&#34;V&#34;,smu_index+1)
+                    
+        self.pyvisa_resource.write(&#34;LI %s&#34;%list_display[1:])
+    except pyvisa.VisaIOError:
+        print(&#34;/!\ VisaIOError : timeout expired&#34;)
+        self.pyvisa_resource.close()</code></pre>
+</details>
+<div class="desc"><p>Function to initialize the K4200 equipment with the desired settings</p>
+<p>args:
+- smu_type (dictionary) : dictionary indicated for each SMU ("SMU1","SMU2","SMU3" and "SMU4") the bias type ("voltage", "current" or "common")
+- smu_used (dictionary) : dictionary indicated for each SMU ("SMU1","SMU2","SMU3" and "SMU4") if active or not ("on" or "off")
+- smu_master (int) : integer to indicate which SMU performs the sweep
+- smu_bias (dictionary) : dictionary indicated for each SMU ("SMU1","SMU2","SMU3" and "SMU4") the bias point (scalar)
+- smu_compliance (dictionary) : dictionary indicated for each SMU ("SMU1","SMU2","SMU3" and "SMU4") the compliance (scalar)
+- sweep_param (dictionary) : dictionary indicated the starting bias ("start"), the stoping bias ("stop") and step ("step") of the sweep
+- sweep_type (string) : string to indicate linear ("linear") sweep or logarithmic ("log") sweep
+- integration_mode (string) : set the integration time parameter ("S" for short, "M" for medium and "L" for long)
+- delay_time (scalar) : the time to wait between when the output voltage is set and when the measurement is made in a sweep
+- hold_time (scalar) : hold time that delays the start of a sweep</p></div>
+</dd>
+<dt id="dopes.equipment_control.k4200.k4200.launch_measurements"><code class="name flex">
+<span>def <span class="ident">launch_measurements</span></span>(<span>self)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def launch_measurements(self):
+    &#34;&#34;&#34; Function that launch the measurement and return the data (in array shape) and the header (string) depending on the measurement configuration
+    
+        return:
+            - data (array) : array with the measurement data
+            - header (string) : string with the description of the data column &#34;Vx&#34; or &#34;Ix&#34; for voltage or current measured from SMUx.
+    &#34;&#34;&#34;            
+    number_channel=0
+    for smu_index in range(4):
+        if self.smu_used[&#34;SMU%d&#34;%(smu_index+1)]==&#34;on&#34;:
+            number_channel+=1
+    sweep_list=np.round(np.arange(self.sweep_param[&#34;start&#34;],self.sweep_param[&#34;stop&#34;]+self.sweep_param[&#34;step&#34;],self.sweep_param[&#34;step&#34;]),6)
+    N_sweep=len(sweep_list)
+    data=np.zeros((N_sweep,number_channel+1))
+    data[:,0]=sweep_list
+
+    
+    self.pyvisa_resource.write(&#34;MD&#34;) # This command controls measurements.
+    self.pyvisa_resource.write(&#34;ME1&#34;) # Run a single trigger test and store readings in a cleared buffer: 1
+    time.sleep(1)
+    j=0               
+    while (j&lt;N_sweep):
+        if self.smu_type[&#34;SMU%d&#34;%(self.smu_master)]==&#34;voltage&#34;:
+            data_master=np.float32(self.pyvisa_resource.query(&#34;RD &#39;I%d&#39;, %d&#34;%(self.smu_master,j+1)))
+        elif self.smu_type[&#34;SMU%d&#34;%(self.smu_master)]==&#34;current&#34;:
+            data_master=np.float32(self.pyvisa_resource.query(&#34;RD &#39;V%d&#39;, %d&#34;%(self.smu_master,j+1)))
+        if (data_master!=0.):
+            i=0
+            for smu_index in range(4):
+                if self.smu_used[&#34;SMU%d&#34;%(smu_index+1)]==&#34;on&#34;:
+                    i+=1
+                    if self.smu_type[&#34;SMU%d&#34;%(smu_index+1)]==&#34;voltage&#34;:
+                        data[j,i]=np.float32(self.pyvisa_resource.query(&#34;RD &#39;I%d&#39;, %d&#34;%(smu_index+1,j+1)))# Read measurements
+                    elif self.smu_type[&#34;SMU%d&#34;%(smu_index+1)]==&#34;current&#34;:
+                        data[j,i]=np.float32(self.pyvisa_resource.query(&#34;RD &#39;V%d&#39;, %d&#34;%(smu_index+1,j+1)))# Read measurements
+                        
+            j+=1
+        time.sleep(0.1)
+    header=&#34;%s%d&#34;%(self.smu_type[&#34;SMU%d&#34;%self.smu_master][0].upper(),self.smu_master)
+    for smu_index in range(4):
+        if self.smu_used[&#34;SMU%d&#34;%(smu_index+1)]==&#34;on&#34;:
+            if self.smu_type[&#34;SMU%d&#34;%(smu_index+1)]==&#34;voltage&#34;:
+                header+=&#34;, %s%d&#34;%(&#34;I&#34;,smu_index+1)
+            elif self.smu_type[&#34;SMU%d&#34;%(smu_index+1)]==&#34;current&#34;:
+                header+=&#34;, %s%d&#34;%(&#34;V&#34;,smu_index+1)
+    return data, header</code></pre>
+</details>
+<div class="desc"><p>Function that launch the measurement and return the data (in array shape) and the header (string) depending on the measurement configuration</p>
+<p>return:
+- data (array) : array with the measurement data
+- header (string) : string with the description of the data column "Vx" or "Ix" for voltage or current measured from SMUx.</p></div>
+</dd>
+</dl>
+</dd>
+</dl>
+</section>
+</article>
+<nav id="sidebar">
+<div class="toc">
+<ul></ul>
+</div>
+<ul id="index">
+<li><h3>Super-module</h3>
+<ul>
+<li><code><a title="dopes.equipment_control" href="index.html">dopes.equipment_control</a></code></li>
+</ul>
+</li>
+<li><h3><a href="#header-classes">Classes</a></h3>
+<ul>
+<li>
+<h4><code><a title="dopes.equipment_control.k4200.k4200" href="#dopes.equipment_control.k4200.k4200">k4200</a></code></h4>
+<ul class="">
+<li><code><a title="dopes.equipment_control.k4200.k4200.company" href="#dopes.equipment_control.k4200.k4200.company">company</a></code></li>
+<li><code><a title="dopes.equipment_control.k4200.k4200.initialize" href="#dopes.equipment_control.k4200.k4200.initialize">initialize</a></code></li>
+<li><code><a title="dopes.equipment_control.k4200.k4200.launch_measurements" href="#dopes.equipment_control.k4200.k4200.launch_measurements">launch_measurements</a></code></li>
+<li><code><a title="dopes.equipment_control.k4200.k4200.model" href="#dopes.equipment_control.k4200.k4200.model">model</a></code></li>
+<li><code><a title="dopes.equipment_control.k4200.k4200.url" href="#dopes.equipment_control.k4200.k4200.url">url</a></code></li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+</nav>
+</main>
+<footer id="footer">
+<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
+</footer>
+</body>
+</html>
diff --git a/html/equipment_control/kal100.html b/html/equipment_control/kal100.html
new file mode 100644
index 0000000000000000000000000000000000000000..9263b770117aa3baa9fffe1def3e84f11f9361de
--- /dev/null
+++ b/html/equipment_control/kal100.html
@@ -0,0 +1,288 @@
+<!doctype html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
+<meta name="generator" content="pdoc3 0.11.6">
+<title>dopes.equipment_control.kal100 API documentation</title>
+<meta name="description" content="">
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/typography.min.css" integrity="sha512-Y1DYSb995BAfxobCkKepB1BqJJTPrOp3zPL74AWFugHHmmdcvO+C48WLrUOlhGMc0QG7AE3f7gmvvcrmX2fDoA==" crossorigin>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css" crossorigin>
+<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:1.5em;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:2em 0 .50em 0}h3{font-size:1.4em;margin:1.6em 0 .7em 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .2s ease-in-out}a:visited{color:#503}a:hover{color:#b62}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900;font-weight:bold}pre code{font-size:.8em;line-height:1.4em;padding:1em;display:block}code{background:#f3f3f3;font-family:"DejaVu Sans Mono",monospace;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source > summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible;min-width:max-content}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em 1em;margin:1em 0}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
+<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul ul{padding-left:1em}.toc > ul > li{margin-top:.5em}}</style>
+<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
+<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js" integrity="sha512-D9gUyxqja7hBtkWpPWGt9wfbfaMGVt9gnyCvYa+jojwwPHLCzUm5i8rpk7vD7wNee9bA35eYIjobYPaQuKS1MQ==" crossorigin></script>
+<script>window.addEventListener('DOMContentLoaded', () => {
+hljs.configure({languages: ['bash', 'css', 'diff', 'graphql', 'ini', 'javascript', 'json', 'plaintext', 'python', 'python-repl', 'rust', 'shell', 'sql', 'typescript', 'xml', 'yaml']});
+hljs.highlightAll();
+/* Collapse source docstrings */
+setTimeout(() => {
+[...document.querySelectorAll('.hljs.language-python > .hljs-string')]
+.filter(el => el.innerHTML.length > 200 && ['"""', "'''"].includes(el.innerHTML.substring(0, 3)))
+.forEach(el => {
+let d = document.createElement('details');
+d.classList.add('hljs-string');
+d.innerHTML = '<summary>"""</summary>' + el.innerHTML.substring(3);
+el.replaceWith(d);
+});
+}, 100);
+})</script>
+</head>
+<body>
+<main>
+<article id="content">
+<header>
+<h1 class="title">Module <code>dopes.equipment_control.kal100</code></h1>
+</header>
+<section id="section-intro">
+</section>
+<section>
+</section>
+<section>
+</section>
+<section>
+</section>
+<section>
+<h2 class="section-title" id="header-classes">Classes</h2>
+<dl>
+<dt id="dopes.equipment_control.kal100.kal100"><code class="flex name class">
+<span>class <span class="ident">kal100</span></span>
+<span>(</span><span>port)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">class kal100(equipment.equipment):
+    
+    &#34;&#34;&#34;Class to control KAL100 pressure system&#34;&#34;&#34;
+    model=&#34;KAL100&#34;
+    company=&#34;halstrup-walcher&#34;
+    url=&#34;https://www.halstrup-walcher.de/en/products/KAL100.php&#34;
+
+    def __init__(self,port):
+        &#34;&#34;&#34; Function called when an instance of the class is created
+        
+            args:
+                - port (string) : the computer port to which the equipment is connected        
+        &#34;&#34;&#34;
+        self.serial_resource = serial.Serial(
+            port=port,
+            baudrate=9600,
+            parity=serial.PARITY_NONE,
+            stopbits=serial.STOPBITS_ONE,
+            bytesize=serial.EIGHTBITS,
+            timeout=10
+        )
+
+    def initialize(self,units=&#34;kPa&#34;,percentage=100, mode_operation=&#34;MS&#34;, mode_input=&#34;positive&#34;,zero_adjust=True):    
+        &#34;&#34;&#34; Function to initialize the KAL100
+        
+            args:
+                - units (string) : &#34;Pa&#34;, &#34;kPa&#34; or &#34;hPa&#34;
+                - percentage (int) : pressure fixed at &#34;percentage&#34; of the targeted value
+                - mode_operation (string) :  mode test (&#34;MT&#34;), mode zeroing (&#34;MZ&#34;), mode target value (&#34;MS&#34;), mode pressure measurement (&#34;MP&#34;)
+                - mode_input (string) : Positive P-input (&#34;positive&#34;), Negative P-input (&#34;negative&#34;), Differential pressure measurement  (&#34;differential&#34;)
+                
+        &#34;&#34;&#34;
+        units_dic={&#34;kPa&#34;:0,&#34;Pa&#34;:1,&#34;hPa&#34;:2}
+        mode_dic={&#34;positive&#34;:&#34;MI0&#34;,&#34;negative&#34;:&#34;MI1&#34;,&#34;differential&#34;:&#34;MI2&#34;}
+
+        self.units=units
+        # self.serial_resource.write(str.encode(&#34;&gt;PD%d\n&#34;%units_dic[units]))
+        # self.serial_resource.read_until(b&#39;\r&#39;)
+        self.serial_resource.write(str.encode(&#34;&gt;PE%d\n&#34;%units_dic[units]))
+        self.serial_resource.read_until(b&#39;\r&#39;)
+        self.serial_resource.write(str.encode(&#34;&gt;PP%d\n&#34;%percentage)) # percentage of the target 
+        self.serial_resource.read_until(b&#39;\r&#39;)
+
+        self.serial_resource.write(str.encode(&#34;%s\n&#34;%mode_dic[mode_input])) # MI0: Positive P-input, MI1: Negative P-input, MI2: Differential pressure measurement 
+        self.serial_resource.read_until(b&#39;\r&#39;)
+
+        if zero_adjust:
+            self.serial_resource.write(str.encode(&#34;MZ\n&#34;)) # mode zeroing
+            self.serial_resource.read_until(b&#39;\r&#39;)
+            time.sleep(10)
+        self.serial_resource.write(str.encode(&#34;%s\n&#34;%mode_operation)) #MT: mode test, MZ: mode zeroing, MS: mode target value, MP: mode pressure measurement 
+        self.serial_resource.read_until(b&#39;\r&#39;)
+        
+        if mode_operation==&#34;MS&#34;:
+            self.serial_resource.write(str.encode(&#34;&gt;PS%3.5f\n&#34;%0))
+            self.serial_resource.read_until(b&#39;\r&#39;)
+            
+    def set_pressure(self,pressure):
+        &#34;&#34;&#34; Function to set pressure level of the KAL100
+        
+            args:
+                - pressure (scalar) : targeted pressure
+        &#34;&#34;&#34;
+        units_mult={&#34;kPa&#34;:10,&#34;Pa&#34;:1e-3,&#34;hPa&#34;:1}
+
+        self.serial_resource.write(str.encode(&#34;MS\n&#34;))
+        self.serial_resource.read_until(b&#39;\r&#39;)
+        self.serial_resource.write(str.encode(&#34;&gt;PS%3.5f\n&#34;%(pressure*units_mult[self.units])))
+        # self.serial_resource.write(str.encode(&#34;&gt;PS%3.5f\n&#34;%(pressure)))
+        self.serial_resource.read_until(b&#39;\r&#39;)
+            
+    def close_connection(self):
+        &#34;&#34;&#34; Function to close the  serial connection with the equipment &#34;&#34;&#34;
+        self.serial_resource.close()</code></pre>
+</details>
+<div class="desc"><p>Class to control KAL100 pressure system</p>
+<p>Function called when an instance of the class is created</p>
+<p>args:
+- port (string) : the computer port to which the equipment is connected</p></div>
+<h3>Ancestors</h3>
+<ul class="hlist">
+<li>equipment_control.equipment.equipment</li>
+</ul>
+<h3>Class variables</h3>
+<dl>
+<dt id="dopes.equipment_control.kal100.kal100.company"><code class="name">var <span class="ident">company</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="dopes.equipment_control.kal100.kal100.model"><code class="name">var <span class="ident">model</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="dopes.equipment_control.kal100.kal100.url"><code class="name">var <span class="ident">url</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+</dl>
+<h3>Methods</h3>
+<dl>
+<dt id="dopes.equipment_control.kal100.kal100.close_connection"><code class="name flex">
+<span>def <span class="ident">close_connection</span></span>(<span>self)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def close_connection(self):
+    &#34;&#34;&#34; Function to close the  serial connection with the equipment &#34;&#34;&#34;
+    self.serial_resource.close()</code></pre>
+</details>
+<div class="desc"><p>Function to close the
+serial connection with the equipment</p></div>
+</dd>
+<dt id="dopes.equipment_control.kal100.kal100.initialize"><code class="name flex">
+<span>def <span class="ident">initialize</span></span>(<span>self,<br>units='kPa',<br>percentage=100,<br>mode_operation='MS',<br>mode_input='positive',<br>zero_adjust=True)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def initialize(self,units=&#34;kPa&#34;,percentage=100, mode_operation=&#34;MS&#34;, mode_input=&#34;positive&#34;,zero_adjust=True):    
+    &#34;&#34;&#34; Function to initialize the KAL100
+    
+        args:
+            - units (string) : &#34;Pa&#34;, &#34;kPa&#34; or &#34;hPa&#34;
+            - percentage (int) : pressure fixed at &#34;percentage&#34; of the targeted value
+            - mode_operation (string) :  mode test (&#34;MT&#34;), mode zeroing (&#34;MZ&#34;), mode target value (&#34;MS&#34;), mode pressure measurement (&#34;MP&#34;)
+            - mode_input (string) : Positive P-input (&#34;positive&#34;), Negative P-input (&#34;negative&#34;), Differential pressure measurement  (&#34;differential&#34;)
+            
+    &#34;&#34;&#34;
+    units_dic={&#34;kPa&#34;:0,&#34;Pa&#34;:1,&#34;hPa&#34;:2}
+    mode_dic={&#34;positive&#34;:&#34;MI0&#34;,&#34;negative&#34;:&#34;MI1&#34;,&#34;differential&#34;:&#34;MI2&#34;}
+
+    self.units=units
+    # self.serial_resource.write(str.encode(&#34;&gt;PD%d\n&#34;%units_dic[units]))
+    # self.serial_resource.read_until(b&#39;\r&#39;)
+    self.serial_resource.write(str.encode(&#34;&gt;PE%d\n&#34;%units_dic[units]))
+    self.serial_resource.read_until(b&#39;\r&#39;)
+    self.serial_resource.write(str.encode(&#34;&gt;PP%d\n&#34;%percentage)) # percentage of the target 
+    self.serial_resource.read_until(b&#39;\r&#39;)
+
+    self.serial_resource.write(str.encode(&#34;%s\n&#34;%mode_dic[mode_input])) # MI0: Positive P-input, MI1: Negative P-input, MI2: Differential pressure measurement 
+    self.serial_resource.read_until(b&#39;\r&#39;)
+
+    if zero_adjust:
+        self.serial_resource.write(str.encode(&#34;MZ\n&#34;)) # mode zeroing
+        self.serial_resource.read_until(b&#39;\r&#39;)
+        time.sleep(10)
+    self.serial_resource.write(str.encode(&#34;%s\n&#34;%mode_operation)) #MT: mode test, MZ: mode zeroing, MS: mode target value, MP: mode pressure measurement 
+    self.serial_resource.read_until(b&#39;\r&#39;)
+    
+    if mode_operation==&#34;MS&#34;:
+        self.serial_resource.write(str.encode(&#34;&gt;PS%3.5f\n&#34;%0))
+        self.serial_resource.read_until(b&#39;\r&#39;)</code></pre>
+</details>
+<div class="desc"><p>Function to initialize the KAL100</p>
+<p>args:
+- units (string) : "Pa", "kPa" or "hPa"
+- percentage (int) : pressure fixed at "percentage" of the targeted value
+- mode_operation (string) :
+mode test ("MT"), mode zeroing ("MZ"), mode target value ("MS"), mode pressure measurement ("MP")
+- mode_input (string) : Positive P-input ("positive"), Negative P-input ("negative"), Differential pressure measurement
+("differential")</p></div>
+</dd>
+<dt id="dopes.equipment_control.kal100.kal100.set_pressure"><code class="name flex">
+<span>def <span class="ident">set_pressure</span></span>(<span>self, pressure)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def set_pressure(self,pressure):
+    &#34;&#34;&#34; Function to set pressure level of the KAL100
+    
+        args:
+            - pressure (scalar) : targeted pressure
+    &#34;&#34;&#34;
+    units_mult={&#34;kPa&#34;:10,&#34;Pa&#34;:1e-3,&#34;hPa&#34;:1}
+
+    self.serial_resource.write(str.encode(&#34;MS\n&#34;))
+    self.serial_resource.read_until(b&#39;\r&#39;)
+    self.serial_resource.write(str.encode(&#34;&gt;PS%3.5f\n&#34;%(pressure*units_mult[self.units])))
+    # self.serial_resource.write(str.encode(&#34;&gt;PS%3.5f\n&#34;%(pressure)))
+    self.serial_resource.read_until(b&#39;\r&#39;)</code></pre>
+</details>
+<div class="desc"><p>Function to set pressure level of the KAL100</p>
+<p>args:
+- pressure (scalar) : targeted pressure</p></div>
+</dd>
+</dl>
+</dd>
+</dl>
+</section>
+</article>
+<nav id="sidebar">
+<div class="toc">
+<ul></ul>
+</div>
+<ul id="index">
+<li><h3>Super-module</h3>
+<ul>
+<li><code><a title="dopes.equipment_control" href="index.html">dopes.equipment_control</a></code></li>
+</ul>
+</li>
+<li><h3><a href="#header-classes">Classes</a></h3>
+<ul>
+<li>
+<h4><code><a title="dopes.equipment_control.kal100.kal100" href="#dopes.equipment_control.kal100.kal100">kal100</a></code></h4>
+<ul class="two-column">
+<li><code><a title="dopes.equipment_control.kal100.kal100.close_connection" href="#dopes.equipment_control.kal100.kal100.close_connection">close_connection</a></code></li>
+<li><code><a title="dopes.equipment_control.kal100.kal100.company" href="#dopes.equipment_control.kal100.kal100.company">company</a></code></li>
+<li><code><a title="dopes.equipment_control.kal100.kal100.initialize" href="#dopes.equipment_control.kal100.kal100.initialize">initialize</a></code></li>
+<li><code><a title="dopes.equipment_control.kal100.kal100.model" href="#dopes.equipment_control.kal100.kal100.model">model</a></code></li>
+<li><code><a title="dopes.equipment_control.kal100.kal100.set_pressure" href="#dopes.equipment_control.kal100.kal100.set_pressure">set_pressure</a></code></li>
+<li><code><a title="dopes.equipment_control.kal100.kal100.url" href="#dopes.equipment_control.kal100.kal100.url">url</a></code></li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+</nav>
+</main>
+<footer id="footer">
+<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
+</footer>
+</body>
+</html>
diff --git a/html/equipment_control/sh242.html b/html/equipment_control/sh242.html
new file mode 100644
index 0000000000000000000000000000000000000000..eb8fd3d45a30302ebbddcc5872c3661024209148
--- /dev/null
+++ b/html/equipment_control/sh242.html
@@ -0,0 +1,471 @@
+<!doctype html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
+<meta name="generator" content="pdoc3 0.11.6">
+<title>dopes.equipment_control.sh242 API documentation</title>
+<meta name="description" content="">
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/typography.min.css" integrity="sha512-Y1DYSb995BAfxobCkKepB1BqJJTPrOp3zPL74AWFugHHmmdcvO+C48WLrUOlhGMc0QG7AE3f7gmvvcrmX2fDoA==" crossorigin>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css" crossorigin>
+<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:1.5em;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:2em 0 .50em 0}h3{font-size:1.4em;margin:1.6em 0 .7em 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .2s ease-in-out}a:visited{color:#503}a:hover{color:#b62}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900;font-weight:bold}pre code{font-size:.8em;line-height:1.4em;padding:1em;display:block}code{background:#f3f3f3;font-family:"DejaVu Sans Mono",monospace;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source > summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible;min-width:max-content}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em 1em;margin:1em 0}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
+<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul ul{padding-left:1em}.toc > ul > li{margin-top:.5em}}</style>
+<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
+<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js" integrity="sha512-D9gUyxqja7hBtkWpPWGt9wfbfaMGVt9gnyCvYa+jojwwPHLCzUm5i8rpk7vD7wNee9bA35eYIjobYPaQuKS1MQ==" crossorigin></script>
+<script>window.addEventListener('DOMContentLoaded', () => {
+hljs.configure({languages: ['bash', 'css', 'diff', 'graphql', 'ini', 'javascript', 'json', 'plaintext', 'python', 'python-repl', 'rust', 'shell', 'sql', 'typescript', 'xml', 'yaml']});
+hljs.highlightAll();
+/* Collapse source docstrings */
+setTimeout(() => {
+[...document.querySelectorAll('.hljs.language-python > .hljs-string')]
+.filter(el => el.innerHTML.length > 200 && ['"""', "'''"].includes(el.innerHTML.substring(0, 3)))
+.forEach(el => {
+let d = document.createElement('details');
+d.classList.add('hljs-string');
+d.innerHTML = '<summary>"""</summary>' + el.innerHTML.substring(3);
+el.replaceWith(d);
+});
+}, 100);
+})</script>
+</head>
+<body>
+<main>
+<article id="content">
+<header>
+<h1 class="title">Module <code>dopes.equipment_control.sh242</code></h1>
+</header>
+<section id="section-intro">
+</section>
+<section>
+</section>
+<section>
+</section>
+<section>
+</section>
+<section>
+<h2 class="section-title" id="header-classes">Classes</h2>
+<dl>
+<dt id="dopes.equipment_control.sh242.sh242"><code class="flex name class">
+<span>class <span class="ident">sh242</span></span>
+<span>(</span><span>address, rm=None, timeout=10000.0)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">class sh242(equipment.equipment):
+    
+    &#34;&#34;&#34;Class to control SH242 climatic chamber&#34;&#34;&#34;
+    model=&#34;SH242&#34;
+    company=&#34;ESPEC&#34;
+    url=&#34;https://espec.com/na/products/model/sh_242&#34;       
+
+
+    def initialize(self,temperature=True, humidity=False,temperature_dic={&#34;upper&#34;:125,&#34;lower&#34;:-45,&#34;set&#34;:20},humidity_dic={&#34;upper&#34;:100,&#34;lower&#34;:0,&#34;set&#34;:55}):
+        &#34;&#34;&#34; Function to initialize the SH242
+        
+            args:
+                - temperature (boolean) : if True, activate the temperature control
+                - humidity (boolean) : if True, activate the humidity control
+                - temperature_dic (dictionary) : dictionnary with the upper (&#34;upper&#34;) and lower (&#34;lower&#34;) alarm and the initial set point (&#34;set&#34;) for the temperature
+                - humidity_dic (dictionary) : dictionnary with the upper (&#34;upper&#34;) and lower (&#34;lower&#34;) alarm and the initial set point (&#34;set&#34;) for the humidity
+        &#34;&#34;&#34;
+
+        self.set_connection_parameter_dic({&#34;write_termination&#34;:&#39;\r\n&#39;,&#34;read_termination&#34;:&#39;\r\n&#39;,&#34;send_end&#34;:True})
+
+        self.pyvisa_resource.write(&#39;POWER, ON&#39;)
+        time.sleep(1)
+        self.pyvisa_resource.read()
+        self.pyvisa_resource.write(&#39;POWER, CONSTANT&#39;)
+        time.sleep(10)
+        self.pyvisa_resource.read()
+
+        if temperature:
+            self.pyvisa_resource.write(&#34;TEMP, L%.2f&#34;%temperature_dic[&#34;upper&#34;])  #Changes the temperature lower absolute alarm value in constant setup
+            time.sleep(1)
+            self.pyvisa_resource.read()
+            self.pyvisa_resource.write(&#34;TEMP, H%.2f&#34;%temperature_dic[&#34;lower&#34;]) #Changes the temperature upper absolute alarm value in constant setup
+            time.sleep(1)
+            self.pyvisa_resource.read()
+            self.pyvisa_resource.write(&#34;TEMP, S%.2f&#34;%temperature_dic[&#34;set&#34;]) #Changes the temperature set point in constant setup
+            time.sleep(1)
+            self.pyvisa_resource.read()
+        else:
+            self.pyvisa_resource.write(&#34;TEMP, SOFF&#34;) # disable temperature
+            time.sleep(1)
+            self.pyvisa_resource.read()
+            
+
+        if humidity:
+            self.pyvisa_resource.write(&#34;HUMI, L%.2f&#34;%humidity_dic[&#34;upper&#34;])  #Changes the temperature lower absolute alarm value in constant setup
+            time.sleep(1)
+            self.pyvisa_resource.read()
+            self.pyvisa_resource.write(&#34;HUMI, H%.2f&#34;%humidity_dic[&#34;lower&#34;]) #Changes the temperature upper absolute alarm value in constant setup
+            time.sleep(1)
+            self.pyvisa_resource.read()
+            self.pyvisa_resource.write(&#34;HUMI, S%.2f&#34;%humidity_dic[&#34;set&#34;]) #Changes the temperature set point in constant setup
+            time.sleep(1)
+            self.pyvisa_resource.read()
+        else:
+            self.pyvisa_resource.write(&#34;HUMI, SOFF&#34;) # disable temperature
+            time.sleep(1)
+            self.pyvisa_resource.read()
+            
+    def read_temperature(self):
+        &#34;&#34;&#34; Function to read the temperature of the climatic chamber
+        
+            return:
+                - temperature (scalar) : temperature of the chamber
+        &#34;&#34;&#34;
+
+        self.pyvisa_resource.write(&#39;TEMP?&#39;)
+        time.sleep(0.5)
+        temperature=self.pyvisa_resource.read()
+        return temperature
+    
+    def read_humidity(self):
+        &#34;&#34;&#34; Function to read the humidity of the climatic chamber
+        
+            return:
+                - humidity (scalar) : humidity of the chamber
+        &#34;&#34;&#34;
+        self.pyvisa_resource.write(&#39;HUMI?&#39;)
+        time.sleep(0.5)
+        humidity=self.pyvisa_resource.read()
+        return humidity
+    
+    
+    def set_temperature(self,temperature,waiting_time=0,wait_for_stabilization=False,stabilization_tolerance=0.1,stabilization_number=10):
+        &#34;&#34;&#34; Function to set the temperature of the climatic chamber
+        
+            return:
+                - temperature (scalar) : targeted temperature of the chamber
+                - waiting_time (scalar) : time in seconds to wait before after changing the temperature target. If a waiting for the stabilization is required, the waiting time happens before.
+                - wait_for_stabilization (boolean) : if True, the function wait that the chamber has stabilized within &#34;stabilization_tolerance&#34; over &#34;stabilization_number&#34; cycles of 5 seconds
+                - stabilization_tolerance (scalar) : the tolerance in °C to consider the temperature of the chamber close enough to the targeted temperature
+                - stabilization_number (int) : number of cycles to be checked to consider the temperature as stabilized
+        &#34;&#34;&#34;
+        self.pyvisa_resource.write(&#34;TEMP, S%.2f&#34;%temperature) #Changes the temperature set point in constant setup
+        time.sleep(1)
+        self.pyvisa_resource.read()
+        time.sleep(waiting_time)
+        
+        if wait_for_stabilization:
+            temperature_stabilized=False
+            stabilization_count=0
+            
+            while temperature_stabilized==False:
+                self.pyvisa_resource.write(&#34;TEMP?&#34;) 
+                time.sleep(5)
+                temperature_read=np.round(float(self.pyvisa_resource.read().split(&#34;,&#34;)[0]),1)
+                if abs(temperature_read-temperature)&lt;stabilization_tolerance:
+                    stabilization_count+=1
+                    if stabilization_count==stabilization_number:
+                        temperature_stabilized=True
+                    else:
+                        stabilization_count=0
+        
+
+    def set_humidity(self,humidity,waiting_time=0,wait_for_stabilization=False,stabilization_tolerance=0.5,stabilization_number=1):
+        &#34;&#34;&#34; Function to set the humidity of the climatic chamber
+        
+            return:
+                - humidity (scalar) : targeted humidity of the chamber
+                - waiting_time (scalar) : time in seconds to wait before after changing the humidity target. If a waiting for the stabilization is required, the waiting time happens before.
+                - wait_for_stabilization (boolean) : if True, the function wait that the chamber has stabilized within &#34;stabilization_tolerance&#34; over &#34;stabilization_number&#34; cycles of 5 seconds
+                - stabilization_tolerance (scalar) : the tolerance in % to consider the humidity of the chamber close enough to the targeted humidity
+                - stabilization_number (int) : number of cycles to be checked to consider the humidity as stabilized
+        &#34;&#34;&#34;
+        self.pyvisa_resource.write(&#34;HUMI, S%.2f&#34;%humidity) #Changes the temperature set point in constant setup
+        time.sleep(1)
+        self.pyvisa_resource.read()
+        time.sleep(waiting_time)
+        
+        if wait_for_stabilization:
+            humidity_stabilized=False
+            stabilization_count=0
+            
+            while humidity_stabilized==False:
+                self.pyvisa_resource.write(&#34;HUMI?&#34;) 
+                time.sleep(5)
+                humidity_read=np.round(float(self.pyvisa_resource.read().split(&#34;,&#34;)[0]),1)
+                if abs(humidity_read-humidity)&lt;stabilization_tolerance:
+                    stabilization_count+=1
+                    if stabilization_count==stabilization_number:
+                        humidity_stabilized=True
+                else:
+                    stabilization_count=0</code></pre>
+</details>
+<div class="desc"><p>Class to control SH242 climatic chamber</p>
+<p>Function called when an instance of the class is created</p>
+<p>args:
+- address (string) : the address of the equipment to be connected
+- rm (pyvisa object) : the pyvisa resource manager used to set the communication with the equipment
+- timeout (scalar) : the timeout set for the communication with the equipment</p></div>
+<h3>Ancestors</h3>
+<ul class="hlist">
+<li>equipment_control.equipment.equipment</li>
+</ul>
+<h3>Class variables</h3>
+<dl>
+<dt id="dopes.equipment_control.sh242.sh242.company"><code class="name">var <span class="ident">company</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="dopes.equipment_control.sh242.sh242.model"><code class="name">var <span class="ident">model</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="dopes.equipment_control.sh242.sh242.url"><code class="name">var <span class="ident">url</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+</dl>
+<h3>Methods</h3>
+<dl>
+<dt id="dopes.equipment_control.sh242.sh242.initialize"><code class="name flex">
+<span>def <span class="ident">initialize</span></span>(<span>self,<br>temperature=True,<br>humidity=False,<br>temperature_dic={'upper': 125, 'lower': -45, 'set': 20},<br>humidity_dic={'upper': 100, 'lower': 0, 'set': 55})</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def initialize(self,temperature=True, humidity=False,temperature_dic={&#34;upper&#34;:125,&#34;lower&#34;:-45,&#34;set&#34;:20},humidity_dic={&#34;upper&#34;:100,&#34;lower&#34;:0,&#34;set&#34;:55}):
+    &#34;&#34;&#34; Function to initialize the SH242
+    
+        args:
+            - temperature (boolean) : if True, activate the temperature control
+            - humidity (boolean) : if True, activate the humidity control
+            - temperature_dic (dictionary) : dictionnary with the upper (&#34;upper&#34;) and lower (&#34;lower&#34;) alarm and the initial set point (&#34;set&#34;) for the temperature
+            - humidity_dic (dictionary) : dictionnary with the upper (&#34;upper&#34;) and lower (&#34;lower&#34;) alarm and the initial set point (&#34;set&#34;) for the humidity
+    &#34;&#34;&#34;
+
+    self.set_connection_parameter_dic({&#34;write_termination&#34;:&#39;\r\n&#39;,&#34;read_termination&#34;:&#39;\r\n&#39;,&#34;send_end&#34;:True})
+
+    self.pyvisa_resource.write(&#39;POWER, ON&#39;)
+    time.sleep(1)
+    self.pyvisa_resource.read()
+    self.pyvisa_resource.write(&#39;POWER, CONSTANT&#39;)
+    time.sleep(10)
+    self.pyvisa_resource.read()
+
+    if temperature:
+        self.pyvisa_resource.write(&#34;TEMP, L%.2f&#34;%temperature_dic[&#34;upper&#34;])  #Changes the temperature lower absolute alarm value in constant setup
+        time.sleep(1)
+        self.pyvisa_resource.read()
+        self.pyvisa_resource.write(&#34;TEMP, H%.2f&#34;%temperature_dic[&#34;lower&#34;]) #Changes the temperature upper absolute alarm value in constant setup
+        time.sleep(1)
+        self.pyvisa_resource.read()
+        self.pyvisa_resource.write(&#34;TEMP, S%.2f&#34;%temperature_dic[&#34;set&#34;]) #Changes the temperature set point in constant setup
+        time.sleep(1)
+        self.pyvisa_resource.read()
+    else:
+        self.pyvisa_resource.write(&#34;TEMP, SOFF&#34;) # disable temperature
+        time.sleep(1)
+        self.pyvisa_resource.read()
+        
+
+    if humidity:
+        self.pyvisa_resource.write(&#34;HUMI, L%.2f&#34;%humidity_dic[&#34;upper&#34;])  #Changes the temperature lower absolute alarm value in constant setup
+        time.sleep(1)
+        self.pyvisa_resource.read()
+        self.pyvisa_resource.write(&#34;HUMI, H%.2f&#34;%humidity_dic[&#34;lower&#34;]) #Changes the temperature upper absolute alarm value in constant setup
+        time.sleep(1)
+        self.pyvisa_resource.read()
+        self.pyvisa_resource.write(&#34;HUMI, S%.2f&#34;%humidity_dic[&#34;set&#34;]) #Changes the temperature set point in constant setup
+        time.sleep(1)
+        self.pyvisa_resource.read()
+    else:
+        self.pyvisa_resource.write(&#34;HUMI, SOFF&#34;) # disable temperature
+        time.sleep(1)
+        self.pyvisa_resource.read()</code></pre>
+</details>
+<div class="desc"><p>Function to initialize the SH242</p>
+<p>args:
+- temperature (boolean) : if True, activate the temperature control
+- humidity (boolean) : if True, activate the humidity control
+- temperature_dic (dictionary) : dictionnary with the upper ("upper") and lower ("lower") alarm and the initial set point ("set") for the temperature
+- humidity_dic (dictionary) : dictionnary with the upper ("upper") and lower ("lower") alarm and the initial set point ("set") for the humidity</p></div>
+</dd>
+<dt id="dopes.equipment_control.sh242.sh242.read_humidity"><code class="name flex">
+<span>def <span class="ident">read_humidity</span></span>(<span>self)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def read_humidity(self):
+    &#34;&#34;&#34; Function to read the humidity of the climatic chamber
+    
+        return:
+            - humidity (scalar) : humidity of the chamber
+    &#34;&#34;&#34;
+    self.pyvisa_resource.write(&#39;HUMI?&#39;)
+    time.sleep(0.5)
+    humidity=self.pyvisa_resource.read()
+    return humidity</code></pre>
+</details>
+<div class="desc"><p>Function to read the humidity of the climatic chamber</p>
+<p>return:
+- humidity (scalar) : humidity of the chamber</p></div>
+</dd>
+<dt id="dopes.equipment_control.sh242.sh242.read_temperature"><code class="name flex">
+<span>def <span class="ident">read_temperature</span></span>(<span>self)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def read_temperature(self):
+    &#34;&#34;&#34; Function to read the temperature of the climatic chamber
+    
+        return:
+            - temperature (scalar) : temperature of the chamber
+    &#34;&#34;&#34;
+
+    self.pyvisa_resource.write(&#39;TEMP?&#39;)
+    time.sleep(0.5)
+    temperature=self.pyvisa_resource.read()
+    return temperature</code></pre>
+</details>
+<div class="desc"><p>Function to read the temperature of the climatic chamber</p>
+<p>return:
+- temperature (scalar) : temperature of the chamber</p></div>
+</dd>
+<dt id="dopes.equipment_control.sh242.sh242.set_humidity"><code class="name flex">
+<span>def <span class="ident">set_humidity</span></span>(<span>self,<br>humidity,<br>waiting_time=0,<br>wait_for_stabilization=False,<br>stabilization_tolerance=0.5,<br>stabilization_number=1)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def set_humidity(self,humidity,waiting_time=0,wait_for_stabilization=False,stabilization_tolerance=0.5,stabilization_number=1):
+    &#34;&#34;&#34; Function to set the humidity of the climatic chamber
+    
+        return:
+            - humidity (scalar) : targeted humidity of the chamber
+            - waiting_time (scalar) : time in seconds to wait before after changing the humidity target. If a waiting for the stabilization is required, the waiting time happens before.
+            - wait_for_stabilization (boolean) : if True, the function wait that the chamber has stabilized within &#34;stabilization_tolerance&#34; over &#34;stabilization_number&#34; cycles of 5 seconds
+            - stabilization_tolerance (scalar) : the tolerance in % to consider the humidity of the chamber close enough to the targeted humidity
+            - stabilization_number (int) : number of cycles to be checked to consider the humidity as stabilized
+    &#34;&#34;&#34;
+    self.pyvisa_resource.write(&#34;HUMI, S%.2f&#34;%humidity) #Changes the temperature set point in constant setup
+    time.sleep(1)
+    self.pyvisa_resource.read()
+    time.sleep(waiting_time)
+    
+    if wait_for_stabilization:
+        humidity_stabilized=False
+        stabilization_count=0
+        
+        while humidity_stabilized==False:
+            self.pyvisa_resource.write(&#34;HUMI?&#34;) 
+            time.sleep(5)
+            humidity_read=np.round(float(self.pyvisa_resource.read().split(&#34;,&#34;)[0]),1)
+            if abs(humidity_read-humidity)&lt;stabilization_tolerance:
+                stabilization_count+=1
+                if stabilization_count==stabilization_number:
+                    humidity_stabilized=True
+            else:
+                stabilization_count=0</code></pre>
+</details>
+<div class="desc"><p>Function to set the humidity of the climatic chamber</p>
+<p>return:
+- humidity (scalar) : targeted humidity of the chamber
+- waiting_time (scalar) : time in seconds to wait before after changing the humidity target. If a waiting for the stabilization is required, the waiting time happens before.
+- wait_for_stabilization (boolean) : if True, the function wait that the chamber has stabilized within "stabilization_tolerance" over "stabilization_number" cycles of 5 seconds
+- stabilization_tolerance (scalar) : the tolerance in % to consider the humidity of the chamber close enough to the targeted humidity
+- stabilization_number (int) : number of cycles to be checked to consider the humidity as stabilized</p></div>
+</dd>
+<dt id="dopes.equipment_control.sh242.sh242.set_temperature"><code class="name flex">
+<span>def <span class="ident">set_temperature</span></span>(<span>self,<br>temperature,<br>waiting_time=0,<br>wait_for_stabilization=False,<br>stabilization_tolerance=0.1,<br>stabilization_number=10)</span>
+</code></dt>
+<dd>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def set_temperature(self,temperature,waiting_time=0,wait_for_stabilization=False,stabilization_tolerance=0.1,stabilization_number=10):
+    &#34;&#34;&#34; Function to set the temperature of the climatic chamber
+    
+        return:
+            - temperature (scalar) : targeted temperature of the chamber
+            - waiting_time (scalar) : time in seconds to wait before after changing the temperature target. If a waiting for the stabilization is required, the waiting time happens before.
+            - wait_for_stabilization (boolean) : if True, the function wait that the chamber has stabilized within &#34;stabilization_tolerance&#34; over &#34;stabilization_number&#34; cycles of 5 seconds
+            - stabilization_tolerance (scalar) : the tolerance in °C to consider the temperature of the chamber close enough to the targeted temperature
+            - stabilization_number (int) : number of cycles to be checked to consider the temperature as stabilized
+    &#34;&#34;&#34;
+    self.pyvisa_resource.write(&#34;TEMP, S%.2f&#34;%temperature) #Changes the temperature set point in constant setup
+    time.sleep(1)
+    self.pyvisa_resource.read()
+    time.sleep(waiting_time)
+    
+    if wait_for_stabilization:
+        temperature_stabilized=False
+        stabilization_count=0
+        
+        while temperature_stabilized==False:
+            self.pyvisa_resource.write(&#34;TEMP?&#34;) 
+            time.sleep(5)
+            temperature_read=np.round(float(self.pyvisa_resource.read().split(&#34;,&#34;)[0]),1)
+            if abs(temperature_read-temperature)&lt;stabilization_tolerance:
+                stabilization_count+=1
+                if stabilization_count==stabilization_number:
+                    temperature_stabilized=True
+                else:
+                    stabilization_count=0</code></pre>
+</details>
+<div class="desc"><p>Function to set the temperature of the climatic chamber</p>
+<p>return:
+- temperature (scalar) : targeted temperature of the chamber
+- waiting_time (scalar) : time in seconds to wait before after changing the temperature target. If a waiting for the stabilization is required, the waiting time happens before.
+- wait_for_stabilization (boolean) : if True, the function wait that the chamber has stabilized within "stabilization_tolerance" over "stabilization_number" cycles of 5 seconds
+- stabilization_tolerance (scalar) : the tolerance in °C to consider the temperature of the chamber close enough to the targeted temperature
+- stabilization_number (int) : number of cycles to be checked to consider the temperature as stabilized</p></div>
+</dd>
+</dl>
+</dd>
+</dl>
+</section>
+</article>
+<nav id="sidebar">
+<div class="toc">
+<ul></ul>
+</div>
+<ul id="index">
+<li><h3>Super-module</h3>
+<ul>
+<li><code><a title="dopes.equipment_control" href="index.html">dopes.equipment_control</a></code></li>
+</ul>
+</li>
+<li><h3><a href="#header-classes">Classes</a></h3>
+<ul>
+<li>
+<h4><code><a title="dopes.equipment_control.sh242.sh242" href="#dopes.equipment_control.sh242.sh242">sh242</a></code></h4>
+<ul class="two-column">
+<li><code><a title="dopes.equipment_control.sh242.sh242.company" href="#dopes.equipment_control.sh242.sh242.company">company</a></code></li>
+<li><code><a title="dopes.equipment_control.sh242.sh242.initialize" href="#dopes.equipment_control.sh242.sh242.initialize">initialize</a></code></li>
+<li><code><a title="dopes.equipment_control.sh242.sh242.model" href="#dopes.equipment_control.sh242.sh242.model">model</a></code></li>
+<li><code><a title="dopes.equipment_control.sh242.sh242.read_humidity" href="#dopes.equipment_control.sh242.sh242.read_humidity">read_humidity</a></code></li>
+<li><code><a title="dopes.equipment_control.sh242.sh242.read_temperature" href="#dopes.equipment_control.sh242.sh242.read_temperature">read_temperature</a></code></li>
+<li><code><a title="dopes.equipment_control.sh242.sh242.set_humidity" href="#dopes.equipment_control.sh242.sh242.set_humidity">set_humidity</a></code></li>
+<li><code><a title="dopes.equipment_control.sh242.sh242.set_temperature" href="#dopes.equipment_control.sh242.sh242.set_temperature">set_temperature</a></code></li>
+<li><code><a title="dopes.equipment_control.sh242.sh242.url" href="#dopes.equipment_control.sh242.sh242.url">url</a></code></li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+</nav>
+</main>
+<footer id="footer">
+<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
+</footer>
+</body>
+</html>
diff --git a/html/index.html b/html/index.html
new file mode 100644
index 0000000000000000000000000000000000000000..ad75f34cea5dfc64e621b380402a2bbe6f080914
--- /dev/null
+++ b/html/index.html
@@ -0,0 +1,78 @@
+<!doctype html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
+<meta name="generator" content="pdoc3 0.11.6">
+<title>dopes API documentation</title>
+<meta name="description" content="">
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/typography.min.css" integrity="sha512-Y1DYSb995BAfxobCkKepB1BqJJTPrOp3zPL74AWFugHHmmdcvO+C48WLrUOlhGMc0QG7AE3f7gmvvcrmX2fDoA==" crossorigin>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css" crossorigin>
+<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:1.5em;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:2em 0 .50em 0}h3{font-size:1.4em;margin:1.6em 0 .7em 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .2s ease-in-out}a:visited{color:#503}a:hover{color:#b62}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900;font-weight:bold}pre code{font-size:.8em;line-height:1.4em;padding:1em;display:block}code{background:#f3f3f3;font-family:"DejaVu Sans Mono",monospace;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source > summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible;min-width:max-content}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em 1em;margin:1em 0}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
+<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul ul{padding-left:1em}.toc > ul > li{margin-top:.5em}}</style>
+<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
+<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js" integrity="sha512-D9gUyxqja7hBtkWpPWGt9wfbfaMGVt9gnyCvYa+jojwwPHLCzUm5i8rpk7vD7wNee9bA35eYIjobYPaQuKS1MQ==" crossorigin></script>
+<script>window.addEventListener('DOMContentLoaded', () => {
+hljs.configure({languages: ['bash', 'css', 'diff', 'graphql', 'ini', 'javascript', 'json', 'plaintext', 'python', 'python-repl', 'rust', 'shell', 'sql', 'typescript', 'xml', 'yaml']});
+hljs.highlightAll();
+/* Collapse source docstrings */
+setTimeout(() => {
+[...document.querySelectorAll('.hljs.language-python > .hljs-string')]
+.filter(el => el.innerHTML.length > 200 && ['"""', "'''"].includes(el.innerHTML.substring(0, 3)))
+.forEach(el => {
+let d = document.createElement('details');
+d.classList.add('hljs-string');
+d.innerHTML = '<summary>"""</summary>' + el.innerHTML.substring(3);
+el.replaceWith(d);
+});
+}, 100);
+})</script>
+</head>
+<body>
+<main>
+<article id="content">
+<header>
+<h1 class="title">Package <code>dopes</code></h1>
+</header>
+<section id="section-intro">
+</section>
+<section>
+<h2 class="section-title" id="header-submodules">Sub-modules</h2>
+<dl>
+<dt><code class="name"><a title="dopes.data_analysis" href="data_analysis/index.html">dopes.data_analysis</a></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt><code class="name"><a title="dopes.equipment_control" href="equipment_control/index.html">dopes.equipment_control</a></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+</dl>
+</section>
+<section>
+</section>
+<section>
+</section>
+<section>
+</section>
+</article>
+<nav id="sidebar">
+<div class="toc">
+<ul></ul>
+</div>
+<ul id="index">
+<li><h3><a href="#header-submodules">Sub-modules</a></h3>
+<ul>
+<li><code><a title="dopes.data_analysis" href="data_analysis/index.html">dopes.data_analysis</a></code></li>
+<li><code><a title="dopes.equipment_control" href="equipment_control/index.html">dopes.equipment_control</a></code></li>
+</ul>
+</li>
+</ul>
+</nav>
+</main>
+<footer id="footer">
+<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
+</footer>
+</body>
+</html>
diff --git a/presentation.pptx b/presentation.pptx
new file mode 100644
index 0000000000000000000000000000000000000000..051dfa21e69d5590e89dbbda97545a78f18abb36
Binary files /dev/null and b/presentation.pptx differ