diff --git "a/IMPETOM-Cl\303\255nico/ImpetomC.py" "b/IMPETOM-Cl\303\255nico/ImpetomC.py"
new file mode 100644
index 0000000000000000000000000000000000000000..4d7873cd56f4cfc64465fd998e98c1339a13bea8
--- /dev/null
+++ "b/IMPETOM-Cl\303\255nico/ImpetomC.py"
@@ -0,0 +1,394 @@
+import threading
+import time
+from datetime import date, datetime
+import numpy as np
+import re
+from pyeit.eit import jac
+from pyeit.eit.interp2d import sim2pts
+
+from Archivos import Archivos
+from Arduino import Arduino
+from ImagenesDicom import ImagenesDicom
+import os
+from ImpetomCError import ImpetomCError
+from ImpetomCElectrodeError import ImpetomCElectrodeError
+import matplotlib.pyplot as plt
+
+#modulos de pyeit
+import pyeit.mesh as mesh
+from pyeit.eit.fem import Forward
+from pyeit.eit.utils import eit_scan_lines
+from pyeit.mesh.shape import thorax,circle
+
+flag_InstanceStudy = True
+
+class ImpetomC:
+    """
+    Permite manejar todas las funcionalidades de la aplicación ImpetomC
+
+        - Generación y guardado de la imagen tomográfica en formato dicom
+        - Conexión del arduino ImpetomC al puerto serie
+
+    """
+
+    #Parametros para las imagenes reconstruidas
+    cmap=plt.cm.RdYlBu # color para las imagenes generadas
+    shape = "thorax"
+    lamb=0.01
+
+    #vectores de datos
+    datos = np.zeros(208) # Variable para el manejo de los datos de entrada desde Arduino ImpetomC
+    archiVH = Archivos("homo_py.txt")# vector homogéneo por defecto. Puede cambiarse utilizando la función actualizarVectorDeDatosHomogeneo
+    vHomogeneo = archiVH.leerArchivo()
+
+    #Variables para el manejo del dispositivo ImpetomC
+    ard = None # se actualiza con startUp() o __arduinoConnect()
+    arduinoComunicationError = None # Variable para manejar el error de que se desconecte el Arduino de la pc mientras adquiere datos
+
+    # Variables globales utilizadas para el manejo de problemas asosciados a los electrodos
+    voltajesElevados = 0
+    voltajesElevadosSeguidos = 0
+    tiraMedidaElevada = 0
+
+    #Parámetros del sistema
+    rootDir=os.path.dirname(os.path.abspath("ImpetomC.py")).replace("ImpetomC.py","")  #Ubicación del directorio donde se guardaran las imágenes generadas
+    today = date.today().strftime("%b-%d-%Y")
+
+    #Establecimiento de los parámetros de la imagen dicom
+    imgDicom = ImagenesDicom(p=0.3,lamb=lamb,file_path_jpg= os.path.join(rootDir, "IMG.jpg"),today=today,rootDir=rootDir, shape=shape)
+
+
+    @classmethod
+    def startUp(cls):
+        """
+        Esta función permite hacer el start up de la aplicación. Utilizarla para dar inicio a la aplicación
+
+        :exception ImpetomCError: Devuelve una excepción en caso de encontrar problemas con la conexión a el dispositivo Arduino
+        """
+
+        cls.__arduinoConnect()
+
+    @classmethod
+    def __arduinoConnect(cls):
+        """
+        Permite establecer la conexión con el Arduino con el software de ImpetomC
+
+        :exception ImpetomCError: Devuelve una excepción con el mensaje correspondiente
+        """
+
+        cls.ard = Arduino(baudrate = 9600, timeout = 0.1,vThreshold = 4.0) #para cambiar el valor del threshold de voltaje cambiar vThreshold
+        cls.arduinoComunicationError = None
+
+
+    @classmethod
+    def reset(cls):
+        """
+        Este método permite realizar el reseteo de la aplicacion, devolviendo la aplicacion a sus valores por defecto
+        """
+
+        cls.datos = np.zeros(208)
+        cls.ard.cerrarPuertoSerie()
+        archiVH = Archivos("homo_py.txt")  # vector homogéneo por defecto. Puede cambiarse utilizando la función actualizarVectorDeDatosHomogeneo
+        cls.vHomogeneo = archiVH.leerArchivo()
+        cls.startUp()
+
+    @classmethod
+    def actualizarVectorDeDatosHomogeneo(cls):
+        """
+        Permite volver a cargar el vector de datos homogeneo en modo reconstrucción para un mejor detalle del vector
+        """
+
+        cls.ard.cambiarModoDeOperacion("Reconstruccion")
+        datosRecalibrados, ve, fa, vS, ta = cls.ard.obtenerMedidas()
+        archiCalibrar = Archivos("datos_calibrar.txt")
+        archiCalibrar.escribirArchivo(datosRecalibrados)
+        cls.vHomogeneo = archiCalibrar.leerArchivo()
+
+
+    @classmethod
+    def __verificarParametrosParaImagen(cls,mode,shape,vmax,vmin,screenWidth,p,sclEnable):
+        """
+            Permite verificar que los parámetros de entrada para la reconstrucción tomográfica sean correctos
+
+            :param mode: Tipo string, debe contener la palabra "reconstruccion" o "setup"
+            :param shape: Tipo String, debe contener la palabra "thorax" o "circle"
+            :param vmax: Tipo float, máximo valor para la escala de la imagen
+            :param vmin: Tipo float, mínimo valor para la escala de la imagen
+            :param screenWidth: Tipo Int, ancho de la pantalla del usuario
+            :param p: Parámetro para la reconstrucción con JAC, se recomienda que el valor esté en 0.1 y 0.9
+            :param SclEnable: Debe ser un booleano. True para utilizar los valores vmax y vmin y false para no utilizarlos
+
+            :returns: **meshDensity** - Retorna la densidad de mesh a utilizar, esto depende de el modo de trabajo de la aplicación y el shape utilizado
+
+                      **retShape** - Retorna un shape reconocible por las funcionalidades de pyEIT
+
+            :exception ImpetomCError: Devuelve una excepción con el mensaje de error correspondiente
+        """
+
+        mode=mode.lower()
+        if mode == "reconstruccion": # Determino el mesh density
+            meshDensity= 0.045
+        elif mode == "setup":
+            if shape == "thorax":  # Determino mesh de setup según modelo
+                meshDensity = 0.07
+
+            elif shape == "circle":
+                meshDensity = 0.1
+            else:
+                raise ImpetomCError("Forma para la reconstrucción inválida, debe ser \"Thorax\" o \"Circle\"")
+        else:
+            raise ImpetomCError("Modo de reconstrucción inválido. Debe ser \"Reconstruccion\" o \"Setup\"")
+
+        shape=shape.lower()
+        if shape == "thorax": # Determino la forma de la reconstrucción
+            retShape=thorax
+
+        elif shape == "circle":
+            retShape = circle
+
+        else:
+            raise ImpetomCError("Forma para la reconstrucción inválida, debe ser \"Thorax\" o \"Circle\"")
+
+        if type(vmax) != float  or type(vmin) != float or type(screenWidth) != int or type(p) != float  or type(sclEnable) != bool:
+            raise ImpetomCError("vmax, vmin, p deben ser floats , screenWidth debe ser un int y sclEnable un bool")
+        elif  screenWidth <= 0 or p <=0 :
+            raise ImpetomCError("screenWidth y p deben ser mayores que 0")
+        return [meshDensity,retShape]
+
+    @classmethod
+    def __obtenerimagen(cls,vectorDatos,SclEnable,vmax,vmin,shape,mode,p,screenWidth):
+        """
+           Pemite generar una imágen tomográfica a partir de un vector de datos, entre otros parámetros
+
+           :param vectorDatos: Vector de 208 valores de tensión para reconstruir la imágen tomográfica
+           :param SclEnable: Debe ser un booleano. True para utilizar los valores vmax y vmin y false para no utilizarlos
+           :param vmax: Máximo valor para la escala de la imagen
+           :param vmin: Mínimo valor para la escala de la imagen
+           :param shape: Forma de la reconstrucción "thorax" o "circle"
+           :param mode: Modo en el que fueron tomadas las medidas de vectorDatos ("reconstruccion" o "setup")
+           :param p: Parámetro para la reconstrucción con JAC, se recomienda que el valor esté entre 0.1 y 0.9
+           :param screenWidth: Ancho de la pantalla del usuario
+
+           :exception ImpetomCError: Devuelve una excepción con el mensaje de error correspondiente
+        """
+
+        meshDensity, correctShape = cls.__verificarParametrosParaImagen(sclEnable=SclEnable,vmax=vmax,vmin=vmin,shape=shape,mode=mode,p=p,screenWidth=screenWidth)
+        mesh_obj, el_pos = mesh.create(16, h0=meshDensity, fd=correctShape)
+        pts = mesh_obj["node"]
+        tri = mesh_obj["element"]
+        x, y = pts[:, 0], pts[:, 1]
+
+        if shape == "circle":
+            el_pos = el_pos + 12  # Electrodo 1 en las "6" del reloj
+            for i in range(4, 16):
+                el_pos[i] = el_pos[i] - 16
+
+        el_dist, step = 1, 1
+        ex_mat = eit_scan_lines(16, el_dist)
+        eit = jac.JAC(mesh_obj, el_pos, ex_mat=ex_mat, step=step, perm=1.0, parser="fmmu")
+        eit.setup(p=p, lamb=cls.lamb, method="kotre")
+
+        ds_n = eit.solve(vectorDatos, cls.vHomogeneo, normalize=True)
+        ds = sim2pts(pts, tri, np.real(ds_n))
+
+        fig, ax = plt.subplots(1, 1, constrained_layout=True)
+        fig.set_size_inches(7, 5)
+
+        if (SclEnable):
+            im = ax.tripcolor(x, y, tri, ds, shading="flat", cmap= cls.cmap, vmax=vmax, vmin=vmin)
+        else:
+            im = ax.tripcolor(x, y, tri, ds, shading="flat", cmap=cls.cmap)
+
+        if shape == "thorax": # Electrodos Thorax
+            for i, e in enumerate(el_pos):
+                if i <= 4:
+                    ax.annotate(str(i + 1), xy=(x[e] - 0.05, y[e] - 0.05), color="w")
+                elif i <= 7:
+                    ax.annotate(str(i + 1), xy=(x[e] - 0.04, y[e]), color="w")
+                else:
+                    if i <= 11:
+                        ax.annotate(str(i + 1), xy=(x[e], y[e]), color="w")
+                    else:
+                        ax.annotate(str(i + 1), xy=(x[e], y[e] - 0.05), color="w")
+        elif shape == "circle": # Electrodos Circle
+            for i, e in enumerate(el_pos):
+                if 1 <= i <= 7:
+                    if i <= 3:
+                        ax.annotate(str(i + 1), xy=(x[e] - 0.05, y[e] - 0.05), color="w")
+                    else:
+                        ax.annotate(str(i + 1), xy=(x[e] - 0.05, y[e]), color="w")
+                elif i >= 14:
+                    ax.annotate(str(i + 1), xy=(x[e] + 0.04, y[e] - 0.05), color="w")
+                elif i == 0:
+                    ax.annotate(str(i + 1), xy=(x[e], y[e] - 0.05), color="w")
+                else:
+                    ax.annotate(str(i + 1), xy=(x[e], y[e]), color="w")
+
+        ax.axis("off")
+        cbar = fig.colorbar(im)
+        cbar_yticks = plt.getp(cbar.ax.axes, 'yticklabels')
+        plt.setp(cbar_yticks, color='w')
+        ax.set_aspect("equal")
+        fig.patch.set_facecolor('black')
+        fig.savefig('IMG.jpg', dpi=(100/1200)*screenWidth)
+        plt.close(fig)
+
+    @classmethod
+    def generarImagenTomografica(cls,mode,shape,screenWidth,sclEnable,vmax,vmin,p,frecuenciaDDS):
+        """
+        Permite generar la imagen tomográfica y la guarda en la raíz del proyecto como IMG.jpg
+
+        :param mode: Modo en el que debe operar el dispositivo ImpetomC
+        :param shape: Forma de la reconstrucción "thorax" o "circle"
+        :param screenWidth: Ancho de la pantalla del usuario
+        :param SclEnable: Debe ser un booleano. True para utilizar los valores vmax y vmin y false para no utilizarlos
+        :param vmax: Máximo valor para la escala de la imagen
+        :param vmin: Mínimo valor para la escala de la imagen
+        :param p: Parámetro para la reconstrucción con JAC, se recomienda que el valor este en 0.1 y 0.9
+        :param frecuenciaDDS: Valor de frecuencia a la que debera operar el DDS del dispositvo ImpetomC
+        
+        :exception ImpetomCElectrodeError: Devuelve una excepción con una mensaje que indica el problema detectado con los electrodos
+        :exception ImpetomCError: Devuelve una excepción con un mensaje de error por errores distintos al anterior
+        """
+
+        global voltajesElevados, voltajesElevadosSeguidos, tiraMedidaElevada
+        if(type(frecuenciaDDS) != str):
+            raise ImpetomCError("La frecuencia del dds debe ser un String")
+        if cls.datos[0] == 0: #Verifico si es la primera vez que se ejecuta la aplicación o si el dispositivo se desconectó
+            cls.__tomarMedidasParaImagen(mode, frecuenciaDDS)
+            threading.Thread(target=cls.__tomarMedidasParaImagen(mode,frecuenciaDDS)).start()
+            cls.__obtenerimagen(vectorDatos=cls.datos,screenWidth=screenWidth,SclEnable=sclEnable,vmax=vmax,vmin=vmin,p=p,shape=shape,mode=mode)
+
+            if voltajesElevados >= 26 and voltajesElevadosSeguidos >= 13:
+                if tiraMedidaElevada[0] != 0:
+                    imprimir_ele = []
+                    for dato in tiraMedidaElevada:
+                        if dato != 0:
+                            imprimir_ele.append(int(dato))
+                    raise ImpetomCElectrodeError("Se detectó un falso contacto en al menos un electrodo. Revise los electrodos " + str(imprimir_ele))
+            elif voltajesElevados > 64:
+                raise ImpetomCElectrodeError("Se detectaron varios electrodos con tensiones elevadas, se recomienda regular la ganancia del dispositivo.",regularGanancia=True)
+            elif voltajesElevados <= 13:
+                raise ImpetomCElectrodeError("Se detectaron varios electrodos con tensiones bajas, se recomienda regular la ganancia del dispositivo.", regularGanancia=True)
+        elif cls.arduinoComunicationError == None: # verifico que no se haya desconectado el dispositivo durante la adquisición
+            threading.Thread(target=cls.__tomarMedidasParaImagen(mode,frecuenciaDDS)).start()
+            tiImagen=time.time()
+            cls.__obtenerimagen(vectorDatos=cls.datos,screenWidth=screenWidth,SclEnable=sclEnable,vmax=vmax,vmin=vmin,p=p,shape=shape,mode=mode)
+            tfImagen=time.time()
+            if voltajesElevados >= 26 and voltajesElevadosSeguidos >= 13:
+                if tiraMedidaElevada[0] != 0:
+                    imprimir_ele = []
+                    for dato in tiraMedidaElevada:
+                        if dato != 0:
+                            imprimir_ele.append(int(dato))
+                    raise ImpetomCElectrodeError("Se detectó un falso contacto en al menos un electrodo. Revise los electrodos " + str(imprimir_ele))
+            elif voltajesElevados > 64:
+                raise ImpetomCElectrodeError(msg="Se detectaron varios electrodos con tensiones elevadas, se recomienda regular la ganancia del dispositivo.",regularGanancia=True)
+            elif voltajesElevados <= 13:
+                raise ImpetomCElectrodeError(msg="Se detectaron varios electrodos con tensiones bajas, se recomienda regular la ganancia del dispositivo.",regularGanancia=True)
+        elif cls.arduinoComunicationError != None:# Si se desconectó el dispositivo durante la adquisición
+            cls.datos= np.zeros(208) #Reinicio el vector de datos
+            cls.ard.datos=np.zeros(208)
+            raise ImpetomCError(cls.arduinoComunicationError)
+
+    @classmethod
+    def __tomarMedidasParaImagen(cls,mode,frecuenciaDDS):
+        """
+        Utiliza al objeto arduino generado para comunicarse con este y obtener las medidas de tension necesarias para realizar la reconstruccion tomográfica del paciente.
+        Las medidas obtenidos son guardadas en la variable datos
+
+        :param mode: Modo de operación para el dispositvo ImpetomC
+        :param frecuenciaDDS: Frecuencia de operación para el dispositvo DDS
+
+        """
+
+        global arduinoComunicationError,voltajesElevados, voltajesElevadosSeguidos,tiraMedidaElevada
+        cls.ard.cambiarModoDeOperacion(mode)
+        cls.ard.cambiarFrecuenciaDDS(frecuenciaDDS)
+        try:
+           tidatos = time.time()
+           cls.datos,voltajesElevados,frecuenciaArd,voltajesElevadosSeguidos,tiraMedidaElevada= cls.ard.obtenerMedidas()
+           archi = Archivos("img.txt")
+           archi.escribirArchivo(cls.datos)
+           tfdatos = time.time()
+           cls.arduinoComunicationError = None
+        except ImpetomCError as e:# Escribo el msj de error en arduinoComunicationError
+           cls.arduinoComunicationError = str(e)
+
+    @classmethod
+    def __verificarParametrosParaHistoriaClinica(cls,pacientName,pacientCi,p,birthDate,sex,medida,medidaZ,shape,mode):
+        """
+            Permite verificar que los parámetros de entrada para la reconstrucción tomográfica sean correctos
+
+            :parameter pacientName: Tipo string, no debe estar vacío
+            :param pacientCi: Tipo String, no debe estar vacío y ser una cadena de números
+            :param p: Tipo float, debe ser mayor que 0
+            :param birthDate: Debe ser un String válido a convertir a fecha en el formato dd-mm-yyyy
+            :param sex: Tipo String, debe ser "M", "F" o "Otro"
+            :param medida: Medida de la circunferencia del thorax del paciente
+            :param medidaZ: Altura aproximada donde está colocado el cinturón de electrodos. El cero se marca desde la apófisis del esternón
+            :param shape: Forma de la reconstrucción "thorax" o "circle"
+
+            :exception ImpetomCError: Devuelve una excepción con el mensaje de error correspondiente
+        """
+
+        if(type(pacientName) != str or len(pacientName) <=1 ):
+            raise ImpetomCError("El nombre debe ser un string y no debe estar vacío")
+        if(type(pacientCi) != str or not re.match('^[0-9]*$',pacientCi)):
+            raise ImpetomCError("La CI solo puede contener números")
+        if (type(p)!=float or p <= 0):
+            raise ImpetomCError("p debe ser un float y mayor que 0")
+        if (type(medida) != str or not re.match('^[0-9]*$', medida)):
+            if type(medida) == int and int(medida) < 0 :# explcitamente me fijo si el numero es positivo
+                raise ImpetomCError("La medida de la circuferencia del tórax solo puede contener números positivos")
+            elif type(medida )!= int:
+                raise ImpetomCError("La medida de la circuferencia del tórax solo puede contener números")
+        if (type(medidaZ) != str or not re.match('^[0-9]*$', medidaZ.strip("-"))):
+            if type(medidaZ) != int:
+                raise ImpetomCError("La medida de la altura de colocación del cinturón debe ser un número entero")
+
+        mode=mode.lower()
+        if type(mode) != str:
+            raise ImpetomCError("El atributo Mode debe ser un string")
+        elif mode != "reconstruccion" and mode != "setup":
+            raise ImpetomCError("Modo de reconstrucción inválido. Debe ser \"Reconstruccion\" o \"Setup\"")
+        shape=shape.lower()
+        if shape != "thorax" and shape != "circle":
+            raise ImpetomCError("Forma para la reconstrucción inválida, debe ser \"Thorax\" o \"Circle\"")
+        try:
+            patBirthDate = datetime.strptime(birthDate, "%Y%m%d")
+        except ValueError:
+            raise ImpetomCError("La fecha de nacimiento no es válida")
+        sex=sex.lower()
+        if (sex != "m" and sex != "f" and sex!="otro"):
+            raise ImpetomCError ("El sexo del paciente debe ser M, F u Otro")
+
+    @classmethod
+    def guardarImagenEnHistoriaClinica(cls,pacientName,pacientCi,p,pacBirthDate,pacSex, medida, shape, medidaZ,mode):
+        """
+        Permite el guardado de las imágenes obtenidas en la carpeta correspondiente a la historia clónica del paciente, solamente cuando el dispositivo se encuentra en modo Reconstrucción
+
+        :param pacientName: Nombre del paciente
+        :param pacientCi: Ci del paciente
+        :param p: valor de p utilizado durante la reconstrucción
+        :param birthDate: Fecha de nacimiento del paciente
+        :param pacSex: Sexo biologico del paciente
+        :param medida: Medida de la circunferencia del thorax del paciente
+        :param shape: Forma de la reconstrucción "thorax" o "circle"
+        :param medidaZ: Altura aproximada donde está colocado el cinturón de electrodos. El cero se marca desde la apófisis del esternón
+        :param mode: Modo de trabajo del dispositivo. Puede ser "Reconstruccion" o "Setup". Solo guarda imágenes con formato Dicom en caso de estar en modo "Reconstruccion"
+        """
+
+        cls.__verificarParametrosParaHistoriaClinica(pacientName,pacientCi,p,pacBirthDate,pacSex,medida,medidaZ,shape,mode)
+        medida=int(medida)
+        medidaZ=int(medidaZ)
+        dir_dcm = "\\Pacients_Data\\" + pacientName.strip('\n') + "_" + pacientCi.strip('\n') + "\\" + cls.today
+
+        try:  # intento crear la capeta donde se guardaran las imágenes tomográficas del paciente
+            os.makedirs(cls.rootDir + dir_dcm)
+        except OSError:  # en caso de que el directorio exista no importa
+            pass
+        finally:  # guardo la imagen en la carpeta del paciente con un nombre que depende de la hora, minutos y segundos
+            mode = mode.lower()
+            if mode == "reconstruccion":
+                cls.imgDicom.generarImagenDicom(pacientName, pacientCi, pacSex, pacBirthDate, p, cls.lamb, cls.today, medida, shape, medidaZ)