Programa para el cálculo de los coeficientes de un modelo de apuntado para un telescopio. Leonel Gutiérrez Octubre, 2005 1. Introducción Generalmente, cuando se instala un telescopio, su alineación no es perfecta. Esta falta de alineación se traduce siempre en errores, tanto en el apuntado como en el seguimiento de los objetos estelares con el telescopio. Por tanto, en un telescopio profesional es necesario alinearlo de la mejor manera posible, moviendo la montura del telescopio hasta que los errores se reducen al mínimo. Esta tarea se ha realizado ya en los telescopios del Observatorio Astronómico Nacional en San Pedro Mártir. Sin embargo, aún en esas circunstancias, quedan errores residuales muy difíciles de corregir mecánicamente, por lo que es necesario contar con un modelo que permita corregir previamente las coordenadas para conseguir un óptimo apuntado del telescopio. Aunque aquí nos referiremos sólo a los telescopios con montura ecuatorial, la idea también se aplica a otros tipos de monturas. Actualmente, los telescopios del Observatorio Astronómico Nacional en San Pedro Mártir cuentan con un modelo que hace un ajuste en base a polinomios. Sin embargo, debido a diversos factores como el hecho de que la distribución de cargas del telescopio no sea constante en el tiempo, pues están sujetos a cambios de instrumentos, es necesario recalcular con cierta frecuencia los coeficientes del modelo para optimizar la precisión de apuntado de telescopio. Pero esto requiere de un método de fácil implementación que permita el cálculo de los coeficientes por parte del personal técnico del Observatorio, a fin de contar siempre con el mejor modelo de apuntado. En este trabajo se describe un modelo de ajuste trigonométrico y, se propone un programa con el que se ha conseguido encontrar los coeficientes para la corrección de los errores de alineación al polo, falta de perpendicularidad de los ejes, flexiones mecánicas y falta de alineación del eje óptico. El programa está escrito en Fortran y hace uso de las nuevas características del Fortran 95, lo que permite hacer una gran cantidad de cálculos de manera muy simple. Existe también una versión para IDL y en breve estará lista una versión del programa en Fortran77. El caso que se presenta como ejemplo usa datos que corresponden al telescopio de 1 m de diámetro del OAN en Tonantzintla, pero el método puede aplicarse directamente a cualquier tipo de telescopios con montura ecuatorial. Aplicando el modelo de correcciones a una base de datos de errores de apuntado, los errores rms se han reducido en Declinación de 49.8” a 8.9” y en Ángulo Horario de 99.7” a 30.1”. 2. Entendiendo el problema Un objeto en el cielo se identifica por sus coordenadas: ascensión recta y declinación (AR/Dec o α/δ). Las declinaciones se miden hacia el norte y hacia el sur del ecuador celeste, mientras que la ascensión recta se mide hacia el este del equinoccio (la intersección entre el ecuador celeste y la eclíptica, siendo esta última el plano de la órbita de la Tierra alrededor del Sol). Pero, conocer AR y Dec no es el final de la historia. Hay una serie de correcciones y transformaciones astronómicas para hacer antes de estar listos para apuntar el telescopio. Luego, es necesario traducir estas coordenadas a otras coordenadas que sirvan para mover el telescopio. Pero en un telescopio ecuatorial (ver figuras 1, 2 y 3) la situación es, en teoría, simple, ya que si el eje polar del telescopio es paralelo al eje polar de la Tierra, la declinación del telescopio coincide con la declinación celeste; el otro eje del telescopio, denominado ángulo horario (AH) y medido hacia el este y el oeste del meridiano, se relaciona con la ascensión recta mediante la ecuación AR = TS – AH, donde TS es el tiempo sideral local (el tiempo sideral local corre un poco mas rápido que el tiempo regular, de tal manera que se adelanta casi 4 minutos diarios). Figura 1. Dos tipos de monturas ecuatoriales simétricas. Figura 2. Dos tipos de monturas ecuatoriales asiméticas. Pero el problema no ha terminado. Aunque ya tenemos las coordenadas del telescopio y estamos listos para moverlo, hemos olvidado que vivimos en un planeta que gira y se balancea, que vemos a través de una atmósfera y que el telescopio no es una máquina perfecta. Todos estos factores han de tomarse en cuenta antes de apuntar el telescopio. La secuencia de cálculos y ajustes que debemos hacer se muestra en la figura 4. Figura 3. Telescopio de 2.1m de SPM. Su montura es ecuatorial de yugo (simétrica). Los tres pasos principales son: pasar de coordenadas medias a aparentes, de aparentes a observadas y de observadas a instrumentales. El primer paso corrige el hecho de que el eje de la Tierra y, por tanto, el ecuador celeste están en constante movimiento debido a la precesión y a la nutación, así como el hecho de que nuestro movimiento alrededor del Sol hace que las estrellas parezcan desplazarse debido a la aberración anual. La transformación de aparentes a observadas se debe a la rotación de la Tierra, a la ubicación geográfica del telescopio y a la refracción atmosférica. El último paso consiste en corregir las imperfecciones instrumentales del telescopio. Figura 4. Diagrama que muestra la secuencia de las correcciones. Las primeras trasformaciones se realizan con ecuaciones que se aplican de igual manera en cualquier telescopio y no dependen de la construcción del mismo. Sin embargo, la última es una transformación única para cada telescopio, pues sólo depende de sus propias características. La precesión del polo terrestre alrededor del polo de la eclíptica, junto con una inclinación gradual de la eclíptica, es la componente de largo plazo de un movimiento complejo causado por los efectos gravitacionales de los miembros del Sistema Solar sobre la Tierra que gira. El periodo de este movimiento es de 26000 años y produce cambios de hasta 50 segundos de arco por año en las coordenadas de las estrellas. El “cabeceo” residual del eje terrestre, que tiene un período de 18.6 años, es la nutación y afecta el apuntado del telescopio en el orden de los 10 segundos de arco. La aberración anual es culpable de hasta 20 segundos de error en el apuntado de un telescopio. Luego, dado que el telescopio está en la Tierra y dentro de la atmósfera, es necesario hacer las otras correcciones para lo cual es necesario conocer la latitud, la longitud y altura sobre el nivel del mar del sitio donde está el observatorio, así como la presión y la temperatura ambiente y el tiempo exacto. Los errores que pueden cometerse por el efecto de la refracción son hasta del orden de 1 minuto de arco para una elevación de 45º al nivel del mar. Todas estas correcciones proporcionan las coordenadas observadas, que, si todo fuera perfecto, nos permitiría ver la estrella perfectamente centrada en el telescopio. Pero el telescopio es real y, por tanto, sus codificadores pueden tener un ligero desplazamiento en sus lecturas, puede haber un ligero juego en los engranes (backlash), sus ejes pueden no ser perfectamente perpendiculares y el eje polar del telescopio puede no estar apuntando exactamente al polo. Corregir físicamente estas imperfecciones puede ser una tarea larga y costosa, por lo que en ocasiones es mejor aceptarlas y tenerlas en cuenta al calcular las coordenadas del objeto. 3. El modelo de apuntado En una montura ecuatorial, estas imperfecciones causan un efecto que puede modelarse mediante seis términos puramente geométricos, complementados con tres debidos a flexiones (Wallace y Tritton,1975; Trueblood y Genet, 1998; Wallace, 2001). En la tabla 1 se muestran estos términos. Los términos HI y DI son simplemente errores de inicialización en las lecturas de las coordenadas instrumentales y pueden calcularse con un apuntado inicial del telescopio. El término CO describe qué tan precisa es la alineación entre el eje mecánico del telescopio y el eje óptico y si el instrumento de detección está bien alineado (la componente que afecta a declinación no depende del ángulo, por lo que queda integrada en DI). El término NP depende de qué tan lejos del ángulo recto está el eje de declinación con respecto al eje polar. Término Descripción Δh Δδ HI Error constante de posición HI DI Error constante de posición CO Error de colimación CO*secδ NP δ y el eje polar no perpendiculares NP*tanδ PV Efecto en elevación de la no coincidencia con el polo PV*senh*tanδ PV*cosh PH Efecto perpendicular a PV -PH*cosh*tanδ PH*senh FT Flexión del tubo FT*cosφ*senh*senδ FT*(cosφ*cosh*senδsenφ*cosδ) FY Flexión del yugo FD Flexión del eje de declinación DI FY*cosh -FD*(cosφ*cosh+ senφ*tanδ) Tabla 1. Términos que afectan en una montura ecuatorial. h y δ son el ángulo horario y la declinación y φ es la latitud del observatorio. Los términos PH y PV describen qué tan apartado está el eje polar del eje verdadero en la dirección horizontal en el caso de PH y en la vertical para PV. FT describe cuánto cae el telescopio al acercarse más a una posición horizontal. FY es la flexión del yugo (o tenedor) y FD es un término de flexiones para el eje de declinación, que sólo se aplica en el caso de los telescopios como los de montura alemana, en la que el eje de declinación no está soportado en ambos extremos. Además de estos términos, generalmente existen términos menores que presentan un comportamiento periódico, causados por defectos de maquinado y de alineación de los diferentes ejes y acoplamientos, que generalmente son de magnitud menor. Estos no se incluyen en el modelo aquí descrito. En la Tabla 1, cada uno de los coeficientes es en general un ángulo pequeño, usualmente del orden de segundos de arco. Las fórmulas para corregir cada uno de los ejes están dadas por la suma de los elementos en sus respectivas columnas. Así, despreciando el término FD, las fórmulas de corrección para el modelo de apuntado son: Δh = HI + CO*secδ + NP*tanδ - PH*cosh*tanδ + PV*senh*tanδ + FT*cosφ*senh*senδ Δδ = DI + PH*senh + (PV+FY)*cosh + FT*(cosφ*cosh*senδ-senφ*cosδ) Aplicando este modelo puede mejorarse notablemente el apuntado del telescopio. 4. ¿Cómo encontrar los coeficientes? Encontrar los coeficientes del modelo no es una tarea fácil (excepto por HI y DI). Además, los coeficientes varían ligeramente con el tiempo y un modelo no puede durar toda la vida: la fatiga de los elementos del telescopio y el esquema instrumental provocarán ligeras variaciones en los coeficientes de flexión, el desplazamiento del eje óptico durante los procesos de mantenimiento provocarán una variación en el coeficiente CO y los asentamientos del suelo provocarán variaciones en la alineación del eje polar del telescopio. Esto hace que deban calcularse los coeficientes con cierta periodicidad. Por esta razón, se ha creado el programa encuentra_modelo. Este programa ha sido escrito en Fortran, usando las nuevas implementaciones incorporadas en el Fortran 95 y se debe usar en ambiente Linux. También es importante que se encuentre instalada una versión del Gnuplot. Existe también una versión para IDL. Para usarlo, es necesario apuntar el telescopio a diferentes estrellas brillantes en el cielo, cuyas coordenadas observadas hayan sido previamente calculadas. Es importante incluir diferentes posiciones en el cielo, anotando la corrección manual que haya tenido que hacerse, tanto en ángulo horario como en declinación. Los datos deben tabularse en un archivo de texto de la siguiente manera: AH dAH Dec dDec donde AH y Dec son el ángulo horario (en horas con respecto al meridiano) y la declinación (en grados) de las coordenadas calculadas del objeto y dAH y dDec son las correcciones que tuvieron que hacerse para centrar el objeto en el telescopio, dadas en segundos de arco. Por ejemplo: -2.473 -33 -16.686 -50.2 -1.799 42 22.515 16.0 (AH) (dAH) (Dec) (dDec) Es importante incluir el mayor número de puntos en la muestra para garantizar un mejor ajuste del modelo. Se recomiendan unos 40 puntos, para tener del orden de 10 en cada cuadrante del cielo. 5. Descripción del programa A este texto se anexa en el Apéndice A un listado del programa en Fortran y en el Apéndice B el correspondiente listado de la versión para IDL. El programa escrito en Fortran funciona de la siguiente manera: a) Busca el archivo con los datos. El programa solicita al usuario que proporcione el nombre del archivo (el que se ha usado para hacer las pruebas se llama ‘epos.txt’). b) Solicita al usuario la latitud del lugar en grados. c) Cuenta cuántas líneas no vacías tiene el archivo, a fin de alojar en memoria un array suficientemente grande para contener los datos. Los elementos de este array son de tipo derivado y contienen cuatro elementos de tipo real: AH, Dec, dAH y dDec. d) Grafica los errores dDec contra dAH para que el usuario tenga una idea de la magnitud de los errores. e) Calcula el término cosφ*cosh*senδ-senφ*cosδ y ajusta la recta tomando como eje vertical a dDec. La pendiente encontrada corresponde al termino FT. Presenta al usuario los datos (pendiente, ordenada al origen y correlación del ajuste), quien puede aceptar o no la corrección. f) Una vez corregidos los errores por este término, se calcula el término cosh y repite el proceso anterior. Esto da como resultado la suma de los términos PV y FY. Nuevamente, pregunta al usuario si acepta la corrección. g) Corrige los errores, si así lo ha decidido el usuario, y calcula el término senh. Al repetir el proceso se tiene el término PH. De esta manera se han encontrado ya los coeficientes que corrigen declinación. h) Grafica, llamando al “gnuplot”, los datos mostrando cómo estaban distribuidos los datos durante los ajustes. i) Incorpora los términos calculados (FT y PH) y corrige los errores en ángulo horario. Revisa si existe algún posible backlash en el mecanismo y lo corrige. j) Calcula el término senh*tanδ y ajusta de nuevo una recta, tomando ahora como eje vertical a dAH. La pendiente del ajuste es ahora PV. Esto permite discriminar ya también el término FY, pues sólo se conocía la suma PV+FY. k) Si el usuario acepta la corrección, se corrigen los errores y se calcula ahora el término tanδ. Esto permite encontrar el término NP. l) Finalmente, calcula el término secδ y encuentra el término CO. m) Grafica ahora los datos de ángulo horario mostrando cómo estaban distribuidos durante los ajustes. También muestra los errores corregidos graficando nuevamente dDec contra dAH y presenta los valores de los coeficientes encontrados. El programa escrito para IDL funciona de manera parecida, con algunas pequeñas variantes: a) El programa recibe como argumentos lel nombre del archive con los datos, la latitud del observatorio y un arreglo de “unos” y “ceros” que indican qué correcciones se harán. Por ejemplo: ENCUENTRA_MODELO, archivo="epos.txt", latitud=19.5, corrige=[1,1,1,0,1,0,1] indica que se harán las correcciones correspondientes a PH, PV, FT, NP y BL y que no se aplicarán las correcciones por el término combinado PV_FY ni la de colimación óptica. El orden es: PH, PV, FT, PV_FY, NP, CO, BL La ausencia de este arreglo en el argumento hará que se calculen todas las correcciones. De hecho, se recomienda habilitar todas las correcciones en una primera ejecución y determinar de allí los términos que pueden o deben omitirse. La latitud deberá darse en grados. b) Busca el archivo con los datos. c) Grafica los errores dDec contra dAH para que el usuario tenga una idea de la magnitud de los errores. d) Calcula el término cosφ*cosh*senδ-senφ*cosδ y ajusta la recta tomando como eje vertical a dDec. La pendiente encontrada corresponde al termino FT. e) Una vez corregidos los errores por este término, se calcula el término cosh y repite el proceso anterior. Esto da como resultado la suma de los términos PV y FY. f) Corrige los errores, si así lo ha decidido el usuario con los valores del argumeno, y calcula el término senh. Al repetir el proceso se tiene el término PH. De esta manera se han encontrado ya los coeficientes que corrigen declinación. g) Grafica los datos usando las propias utilerías de IDL, mostrando cómo estaban distribuidos durante los ajustes. h) Incorpora los términos calculados (FT y PH) y corrige los errores en ángulo horario. Revisa si existe algún posible backlash en el mecanismo y lo corrige. i) Calcula el término senh*tanδ y ajusta de nuevo una recta, tomando ahora como eje vertical a dAH. La pendiente del ajuste es ahora PV. Esto permite discriminar ya también el término FY, pues sólo se conocía la suma PV+FY. j) Se corrigen los errores y se calcula ahora el término tanδ. Esto permite encontrar el término NP. k) Finalmente, calcula el término secδ y encuentra el término CO. l) Grafica ahora los datos de ángulo horario mostrando cómo estaban distribuidos durante los ajustes. También muestra los errores corregidos graficando nuevamente dDec contra dAH y presenta los valores de los coeficientes encontrados. Los términos HI y DI encontrados durante este ajuste no deben ser definitivos, ya que dependen del proceso de inicialización al empezar una sesión de observación. Estos valores deben recalcularse cada vez que se inicia una sesión de observación, apuntando una estrella después de haber aplicado el modelo calculado. El error en este primer apuntado corresponde directamente a los términos HI y DI. Si se desea, pueden apuntarse varias estrellas y promediar los errores encontrados. Pero este hecho puede obviarse en los telescopios del OAN en SPM, pues el sistema de control de los telescopios calcula estos términos cuando se corrigen las coordenadas después del primer apuntado. Los coeficientes encontrados pueden sustituirse ahora en las fórmulas de la sección 3 para hacer las correcciones a las coordenadas. Para obtener mejores resultados de este modelo trigonométrico, en el caso de los telescopios del OAN en San Pedro Mártir, se sugiere inhibir el modelo polinomial que actualmente corrige los errores mecánicos de apuntado, calcular los coeficientes del modelo trigonométrico y, después de aplicarlo, recalcular el modelo polinomial, pues con este último pueden modelarse los demás errores residuales (errores de los acoplamientos de los codificadores, errores de los engranes, etc.) que prácticamente no cambian con el tiempo. 6. Resultados Para probar el algoritmo, hemos aplicado el programa a una base de datos con errores de apuntado del telescopio del Observatorio Astronómico Nacional en Tonantzintla y hemos encontrado los siguientes coeficientes para el modelo (en este caso se usó descartaron las correcciones para CO y para el término combinado PV_FY: Término Valor en segundos de arco Offset en AH HI 9.328 Offset en Dec DI 9.550 Error de colimación CO 0.000 Falta de perpendicularidad NP 67.520 Error horizontal en el polo PH -17.693 Error horizontal en el polo PV -117.582 Flexión del tubo FT 137.124 Flexión del yugo FY 117.582 Backlash en AH BL 171.394 Estos valores permiten disminuir el valor rms de los errores desde 99.7” y 49.8” para AH y Dec, respectivamente, hasta 30.1” y 8.9”. En las figuras 5, 6, 7 y 8 se reproducen las gráficas entregadas por el programa. El código de ambas versiones del programa presentadas aquí se encuentra en la dirección: http://www.astrosen.unam.mx/~leonel/progs/modelo/ Figura 4. Gráfica con los errores de Dec y de AH, antes de ser corregidos. Los aparentes 2 grupos de datos se deben al error por juego mecánico (backlash). Figura 5. Gráfica de los errores de la figura 5 después de ser corregidos. Nótese la escala de los ejes. Figura 6. Gráficas de los errores de Declinación durante el proceso de corrección. Figura 7. Gráfica de los errores en Ángulo Horario durante el proceso de corrección. Nótese el escalón en la primera gráfica al pasar por cero en AH debido al backlash. 7. Referencias 1. Wallace, P. T, y Tritton, K. P., 1979, MNRAS, 189, 115. 2. Trueblood, M. y Genet, R. M., Telescope Control, Willman-Bell, Inc., Richmond, Virginia, USA, 1998. 3. Wallace, P., “Telescope Pointing”, http://www.tpsoft.demon.co.uk/pointing.htm (2001). Apéndice A. Listado del programa en Fortran95 ! Listado del programa !******************************************************************************************! ! Programa 'encuentra_modelo' elaborado por Leonel Gutierrez ! ! Este programa lee un archivo con una serie de datos que muestran los errores de ! apuntado de un telescopio con montura ecuatorial y calcula los coeficientes de ! un modelo trigonometrico para corregir dicho apuntado. ! !******************************************************************************************! ! ! Lo que sigue es un modulo con los elementos necesarios para el programa ! Contiene las siguientes funciones y subrutinas ! ! 1) ! Funcion para contar los renglones del archivo ! function cuantas_lineas(archivo) result(cuantas) ! ! 2) ! Subrutina para traer todos los elementos a sus lugares en el arreglo ! subroutine trae_lineas(archivo, arreglo) ! ! 3) ! Subrutina para guardar en un archivo provisional los datos a graficar ! subroutine guarda_lineas(archivo, matriz) ! ! 4) ! Subrutina para ajustar por minimos cuadrados una recta a una distribucion. Calcula ! ! la pendiente, la ordenada al origen y la correlacion ! subroutine ajusta_recta(x, y, m, b, corr) ! ! 5) ! Funcion que calcula el valor rms de un vector. ! function calcula_rms(x) ! ! 6) ! Subrutina que prepara el archivo que se le va a entregar al 'gnuplot' ! subroutine prepara_archivo_de_grafica() ! ! 7) ! Subrutina que agrega las diferentes graficas al archivo que usara el 'gnuplot'. ! ! Podemos poner hasta 4 graficas en una ventana. (El 'gnuplot' permite muchas ! ! mas, pero en este programa nos hemos limitado a 4.) ! subroutine agrega_grafica(x, y, sx, sy, posx, posy, etiqueta, archivo_prov) ! ! 8) ! ! ! 9) ! ! !10) ! ! !11) ! ! Subrutina que inicia una grafica llamando al 'gnuplot' subroutine inicia_grafica() ! Subrutina que grafica los errores de Declinacion contra los de AH subroutine grafica_errores(etiqueta) ! Subrutina que calcula los coeficientes del modelo usando los errores de Declinacion subroutine encuentra_coeficientes_dec() ! Subrutina que calcula los demas coeficientes del modelo usando los errores de AH subroutine encuentra_coeficientes_ah() module utilerias ! variables y constantes para usarse en el modulo integer, parameter character(len = 256) integer :: dp = selected_real_kind(8,30) ! La clase de doble precision :: linea ! define una cadena para ir leyendo el archivo :: ioss ! variable para almacenar los errores del READ ! Voy a poner los reales de doble precision para no tener problemas de redondeo ! en las funciones trigonometricas real(kind=dp), parameter :: pi = acos(-1.) real(kind=dp), parameter :: gra_rad = pi/180. ! Factor multiplicativo para convertir ! grados en radianes real(kind=dp), parameter :: horas_rad = gra_rad*15.0 ! Factor multiplicativo para convertir ! horas de cielo en radianes integer :: d1, d2, d3,d4 ! dummies real(kind=dp), dimension(4) :: correlacion ! para guardar las correlaciones real(kind=dp), dimension(4) :: m ! las pendientes real(kind=dp), dimension(4) :: b ! y las ordenadas character(len=10) :: resp ! para los dialogos real(kind=dp) real(kind=dp) real(kind=dp) real(kind=dp) real(kind=dp) real(kind=dp) real(kind=dp) real(kind=dp) :: :: :: :: :: :: :: :: PH PV FT FY NP CO PV_FY DAF = = = = = = = = 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ! ! ! ! ! ! ! ! ! Error horizontal en el polo Error vertical en el polo Flexiones del tubo Flexiones del yugo Falta de perpendicularidad Colimacion Flexiones del yugo + error vertical en polo Flexiones del eje de declinacion; No se aplica en este caso real(kind=dp) real(kind=dp) real(kind=dp) :: BL :: HI :: DI = 0.0 = 0.0 = 0.0 real(kind=dp) real(kind=dp) real(kind=dp) :: phi :: senphi :: cosphi ! Error de backlash ! Offset inicial en AH ! Offset inicial en Dec = 19.5*gra_rad ! La latitud del observatorio ! Esto es el seno de la latitud ! Esto es el coseno de la latitud ! variables derivadas type coordenadas real(kind=dp) real(kind=dp) real(kind=dp) real(kind=dp) end type coordenadas :: AH :: Dec :: dAH :: dDec ! Angulo horario del telescopio ! Declinacion ! Error en AH ! Error en Dec ! variables globales ! En este arreglo pongo todos los datos del archivo type(coordenadas), dimension(:), allocatable :: arreglo ! ! ! ! ! ! Esta es una matriz de n x 9 donde pondremos los ejes a graficar; las columnas quedaran asignadas como sigue: 1) para el eje x 2) para los errores antes de corregirse; estos se graficaran en el eje y En las demas columnas se pondran los mismos errores conforme se les vaya aplicando las correcciones real(kind=dp), dimension(:,:), allocatable :: matriz integer :: ii ! un indice contains !***************************************************! ! Funcion para contar los renglones no vacios del archivo. Esto permite reservar el numero de lugares ! necesario para los arreglos usados en el programa. Basicamente son 'arreglo' y 'matriz', asi como ! algunos vectores auxiliares dentro de las subrutinas ! function cuantas_lineas(archivo) result(cuantas) character(*), intent(in) :: archivo integer :: cuantas logical :: existe ! variable para verificar que el archivo existe inquire(FILE = archivo, EXIST = existe) cuantas = 0 if (existe) then open (unit=1,file=archivo,status='old') i = 0 do read(1,'(a)',IOSTAT=ioss) linea if(IOSS == 0) then if(len_trim(linea) > 0) i = i + 1 else exit endif enddo cuantas = i close(1) else print*,"No existe el archivo" end if end function cuantas_lineas !***************************************************! ! Subrutina que lee todos los renglones del archivo de entrada y pone todos los elementos en ! sus lugares correspondientes en el arreglo. ! Subroutine trae_lineas(archivo, arreglo) character(*), intent(in) :: archivo type(coordenadas), dimension(*) :: arreglo logical :: existe ! variable para verificar que el archivo existe inquire(FILE = archivo, EXIST = existe) if (existe) then open (unit=1,file=archivo,status='old') i = 1 do read(1,'(a)',IOSTAT=ioss) linea if(IOSS == 0) then if(len_trim(linea) > 0) then read(linea,*), arreglo(i)%AH, arreglo(i)%dAH, & arreglo(i)%Dec, arreglo(i)%dDec i = i + 1 endif else exit endif end do close(1) else print*,"No existe el archivo" end if end Subroutine trae_lineas !***************************************************! ! Esta subrutina guarda la matriz en un archivo provisional para que sea de alli donde tome el 'gnuplot' los ! datos a graficar. El archivo provisional no se borrar al terminar el programa, a fin de que el usuario ! pueda tener los datos como referencia. El archivo para graficar los errores de Declinacion en cada etapa ! de la correccion, quedan guardados en el archivo 'prov.txt'; los de AH quedan en 'prov_ah.txt'; los errores ! ya corregidos por el modelo quedan en 'prov_i.txt'. Al reiniciarse el programa, los archivos se sobreescriben. ! Subroutine guarda_lineas(archivo, matriz) character(*), intent(in) :: archivo real(kind=dp), dimension(:,:), intent(in) :: matriz integer n = size(matriz,1) :: n open (unit=1,file=archivo,status='replace') i = 1 do write(1,'(9(f10.5,3X))',IOSTAT=ioss) matriz(i,1), matriz(i,2), matriz(i,3), matriz(i,4), & matriz(i,5), matriz(i,6), matriz(i,7), matriz(i,8), matriz(i,9) if(IOSS == 0) then i = i + 1 if (i == n) exit else exit endif end do close(1) end Subroutine guarda_lineas !***************************************************! ! Esta subrutina ajusta una recta usando el metodo de minimos cuadrados ! subroutine ajusta_recta(x, y, m, b, corr) real(kind = dp), dimension(:), intent(in) :: x real(kind = dp), dimension(:), intent(in) :: y real(kind = dp), intent(out) :: m real(kind = dp), intent(out) :: b real(kind = dp), intent(out) :: corr real, dimension(:), allocatable integer :: n :: va, vb, vc ! vectores auxiliares ! tamanio de x o y ! variables para calcular la estadistica real(kind = dp) :: sumax, sumay, sumaxy, sumax2, & cociente, varx, vary, covxy, Xm, Ym ! Procedemos con los minimos cuadrados canonicos n = size(x) allocate(va(n)) allocate(vb(n)) allocate(vc(n)) sumay sumax va sumax2 va sumaxy cociente b m ! Aqui calculamos el tamanio del arreglo ! Reserva n lugares para va, vb y vc = = = = = = = sum(y) ! Suma de todos los elementos en y sum(x) ! Suma de todos los elementos en x x*x sum(va) ! Suma de todas las x^2 x*y sum(va) ! Suma de todas los elementos cruzados n*sumax2 - sumax*sumax ! La ordenada al origen = (sumay*sumax2-sumax*sumaxy)/cociente ! La pendiente = (n*sumaxy-sumax*sumay)/cociente ! Vamos a sacar ahora la correlacion Xm = sumax/n ! La media de x Ym = sumay/n ! La media de y va vb = x - Xm = y - Ym ! Calcula los errores en x ! Calcula los errores en y vc = vb*vb sumay2 vc = sum(vc) = va*va sumax2 vc sumaxy = sum(vc) = va*vb = sum(vc) varx vary covxy corr = = = = ! Calcula el vector de los cuadrados de las ! diferencias en y ! Aqui la suma de todo ese vector ! Calcula el vector de los cuadrados de las ! diferencias en x ! Aqui la suma de todo ese vector ! Calcula el vector de los productos cruzados ! Aqui la suma de todo ese vector sumax2/n ! La varianza en x sumay2/n ! La varianza en y sumaxy/n ! La covarianza covxy/(sqrt(varx*vary)) ! Finalmente ya tenemos el coeficiente de correlacion ! Libera la memoria deallocate(va) deallocate(vb) deallocate(vc) end subroutine ajusta_recta !***************************************************! ! Esta funcion calcula el valor rms de un vector. En este caso, se trata de un ! vector de errores ! function calcula_rms(x) result(rms) real(kind = dp), dimension(:), intent(in) :: x real(kind = dp) :: rms real, dimension(:), allocatable integer :: n :: va, vb, vc ! vectores auxiliares ! tamanio de x o y ! variables para calcular la estadistica real(kind = dp) :: sumax, sumax2, varx, Xm, Ym n = size(x) ! Aqui calculamos el tamanio del arreglo allocate(va(n)) ! Vamos a calcular el RMS sumax = sum(x) Xm = sumax/n va = x - Xm va = va*va ! Reserva n lugares para va ! ! ! ! ! Suma de todos los elementos en x La media de x Calcula los errores en x Calcula el vector de los cuadrados de las diferencias en sumax2 = sum(va) varx rms = sumax2/n = sqrt(varx) deallocate(va) end function calcula_rms ! Aqui la suma de todo ese vector ! La varianza en x ! ! Finalmente ya tenemos el coeficiente de correlacion ! Libera la memoria !***************************************************! ! Esta subrutina prepara el archivo que luego se le entregara al 'gnuplot' para hacer las ! graficas ! subroutine prepara_archivo_de_grafica() open (unit=3,file="pp.prg",status='replace') write(3,'(A)') "set origin 0,0" write(3,'(A)') "set size 1,1" write(3,'(A)') "set multiplot" close(3) end subroutine prepara_archivo_de_grafica !***************************************************! ! Esta subrutina ordena al sistema que arranque el 'gnuplot' usando el archivo 'pp.prg' ! como archivo de lotes para hacer las graficas ! subroutine inicia_grafica() character(len = 25) :: salida salida = "gnuplot -persist pp.prg" call system(salida) end subroutine inicia_grafica !***************************************************! ! Esta subrutina agrega al archivo 'pp.prg' los mandos necesarios para insertar una grafica en ! la ventana del 'gnuplot' ! subroutine agrega_grafica(x, y, sx, sy, posx, posy, etiqueta, archivo_prov) ! 'x' es el numero de columna que se usara en el eje x; lo mismo con 'y' ! 'sx' es la etiqueta que ira en el eje x; lo mismo con y integer, intent(in) :: x, y character(len = *), intent(in) :: sx, sy ! etiquetas para la grafica integer, intent(in) :: posx, posy ! pueden valer 0 y 1, para ! indicar en que cuadrante se van a poner ! 'archivo_prov' es donde se han puesto los datos a graficar character(len = *), intent(in) :: etiqueta character(len = *), intent(in) :: archivo_prov integer :: mx, my, mmx, mmy ! Calcula los valores maximos y minimos mx = floor(minval(matriz(:,x))) my = floor(minval(matriz(:,y))) mmx = ceiling(maxval(matriz(:,x))) mmy = ceiling(maxval(matriz(:,y))) ! para poner los max y min open (unit=3,file="pp.prg",status='old', position='append') write(3,'(A12,I4,A1,I4,A1)') "set xrange [", mx, ":", mmx, "]" write(3,'(A12,I4,A1,I4,A1)') "set yrange [", my, ":", mmy, "]" write(3,'(A)') "set size 0.5,0.5" write(3,'(A,F3.2,A1,F3.2)') "set origin ", 0.5*posx,",", 0.5*posy write(3,'(A12,A)') "set xlabel ", sx write(3,'(A12,A)') "set ylabel ", sy write(3,'(A6,A,A7,I2,A1,I2,A3,A)') "plot '",archivo_prov, "' using ", x, ":", y, " t ",etiqueta close(3) end Subroutine agrega_grafica !***************************************************! ! Esta subrutina grafica los errores de Declinacion contra los errores de Angulo horario para que el ! usuario tenga una idea de la magnitud de los errores. Se llama al inicio del programa y al final ! para poder comparar los errores iniciales contra los finales ! subroutine grafica_errores(etiqueta, rmsdec, rmsah) character(len = *), intent(in) :: etiqueta real, intent(out) :: rmsdec, rmsah integer :: mx, my, mmx, mmy matriz(:,1) = arreglo%dDec matriz(:,2) = arreglo%dAH ! Calcula los valores maximos y minimos mx = floor(minval(matriz(:,1))) my = floor(minval(matriz(:,2))) mmx = ceiling(maxval(matriz(:,1))) mmy = ceiling(maxval(matriz(:,2))) ! para poner los max y min rmsdec = calcula_rms(matriz(:,1)) rmsah = calcula_rms(matriz(:,2)) call guarda_lineas("prov_i.txt", matriz) open (unit=3,file="pp.prg",status='replace') write(3,'(A)') "set origin 0,0" write(3,'(A)') "set size 1,1" write(3,'(A12,I4,A1,I4,A1)') "set xrange [", mx, ":", mmx, "]" write(3,'(A12,I4,A1,I4,A1)') "set yrange [", my, ":", mmy, "]" write(3,'(A,F5.1,A)') "set xlabel 'dDec: ", rmsdec, " rms'" write(3,'(A,F5.1,A)') "set ylabel 'dAH: ", rmsah, " rms'" write(3,'(A,A)') "plot 'prov_i.txt' using 1:2 t ", etiqueta close(3) call inicia_grafica() end subroutine grafica_errores !***************************************************! ! Esta subrutina se encarga de hacer los calculos necesarios para encontrar los coeficientes del ! modelo de correccion correspondientes a Declinacion. Solicita al usuario la confirmacion de ! las correcciones. El usuario debe decidir si se hacen las correcciones o no, en funcion de la ! informacion presentada, en particular la correlacion del ajuste ! subroutine encuentra_coeficientes_dec() ! Pone en la primera columna los errores en declinacion antes de ninguna correccion integer :: tam, kk matriz(:,1) = arreglo%dDec ! En la segunda columna pone el termino de flexiones del tubo; en los calculos, va ! multiplicando a Dec, que esta dada en grados, por el termino 'gra_rad' para ponerla ! en radianes y a AH, que esta en horas, por 'horas_rad' matriz(:,2) = -senphi*cos(arreglo%Dec*gra_rad) + & cosphi*sin(arreglo%Dec*gra_rad)*cos(arreglo%AH*horas_rad); !!!!! Primer ajuste (para el termino FT) !!!!! ! Calcula la mejor recta que se ajusta a esta distribucion call ajusta_recta(matriz(:,2), matriz(:,1), m(1), b(1), correlacion(1)) ! Imprime los valores de m, b y la correlacion para que el usuario decida si se ! aplica la correccion write(*,'(A,3F14.6)') " Flexiones del tubo: m, b y corr=", m(1), b(1), correlacion(1) ! Pregunta si aplica la correccion write(*,'(/a)', advance = "no") "Aplico esta correccion (s,n)? " read(*,*) resp if(resp == "s") then ! Corrige los errores usando la recta encontrada arreglo%dDec = arreglo%dDec-( m(1)*matriz(:,2) + b(1) ); FT = m(1) DI = DI + b(1) endif ! En la tercera columna de la matriz pone los errores con esta primera correccion; si no hubo ! correccion se dejan como estaban pero se ponen en esa columna para poder graficarlos matriz(:,3) = arreglo%dDec ! En la cuarta columna pone el termino de flexiones del yugo + alineacion vertical al polo matriz(:,4) = cos(arreglo%AH*horas_rad); !!!!! Segundo ajuste (para el termino PV_FY) !!!!! ! Calcula la mejor recta que se ajusta a esta distribucion call ajusta_recta(matriz(:,4), matriz(:,3), m(1), b(1), correlacion(1)) write(*,'(A,3F14.6)') " Flexiones del yugo y no alin. vertical: m, b y corr=", m(1), b(1), correlacion(1) ! De nuevo, dejamos que el usuario decida write(*,'(/a)', advance = "no") "Aplico esta correccion (s,n)? " read(*,*) resp if(resp == "s") then ! Corrige los errores usando la recta encontrada arreglo%dDec = arreglo%dDec-( m(1)*matriz(:,4) + b(1) ); PV_FY = m(1) DI = DI + b(1) endif ! En la columna 5 de la matriz pone los errores para ser graficados despues matriz(:,5) = arreglo%dDec ! Y en la columna 6 pone el termino de alineacion horizontal al polo matriz(:,6) = sin(arreglo%AH*horas_rad) !!!!! Tercer ajuste (termino PH) !!!!! ! Calcula la mejor recta que se ajusta a esta distribucion call ajusta_recta(matriz(:,6), matriz(:,5), m(1), b(1), correlacion(1)) write(*,'(A,3F14.6)') " No alin. horiz.: m, b y corr=", m(1), b(1), correlacion(1) ! Igual. Dejamos que el usuario decida write(*,'(/a)', advance = "no") "Aplico esta correccion (s,n)? " read(*,*) resp if(resp == "s") then ! Corrige los errores usando la recta encontrada arreglo%dDec = arreglo%dDec-( m(1)*matriz(:,6) + b(1) ); PH = m(1) DI = DI + b(1) endif ! En la columna 7 de la matriz pone los errores para ser graficados despues matriz(:,7) = arreglo%dDec ! Aqui los datos estan acomodados como sigue: ! Col 1 | 2 | 3 | 4 | 5 | 6 | 7 ! ! --------------------------------------------------------------! ! dDec | FT | dDec_FT | PV_FY | dDec_PV_FY | PH | dDec_PH ! call guarda_lineas("prov.txt", matriz) call call call call call call prepara_archivo_de_grafica() agrega_grafica(2,1,'"FT"', '"dDec"', 0, agrega_grafica(4,3,'"PV+FY"', '"dDec"', agrega_grafica(6,5,'"PH"', '"dDec"', 0, agrega_grafica(2,7,'"FT"', '"dDec"', 1, inicia_grafica() 1,'"Flexiones del tubo"', "prov.txt") 1, 1,'"Flex. yugo + No alin. vert."', "prov.txt") 0,'"No alin. horiz."', "prov.txt") 0,'"Errores corregidos vs. FT"', "prov.txt") tam = size(matriz(:,7)) do kk = 1, tam if( matriz(kk,7) < -30) then write(*,*) "El valor es: ",matriz(kk,7), "con kk = ", k endif enddo end subroutine encuentra_coeficientes_dec !***************************************************! ! Como en el caso de Declinacion, esta subrutina se encarga de hacer los calculos necesarios para ! encontrar los coeficientes del modelo de correccion correspondientes al Angulo Horario. Tambien ! solicita al usuario la confirmacion de las correcciones, para que sea el usuario el que decida ! si se hacen las correcciones o no. ! subroutine encuentra_coeficientes_ah() real :: media_mas, media_menos integer :: cuantos_mas integer :: cuantos_menos media = 0.0 cuantos_mas = 0 cuantos_menos = 0 media_mas media_menos cuantos_mas cuantos_menos media_mas media_menos = = = = = = sum(arreglo%dAH, mask = arreglo%AH > 0) sum(arreglo%dAH, mask = arreglo%AH <= 0) count(arreglo%AH > 0) count(arreglo%AH <= 0) media_mas/cuantos_mas media_menos/cuantos_menos ! Pone en la primera columna los errores en AH antes de ninguna correccion matriz(:,1) = arreglo%dAH ! Pone en la columna 9 AH para graficar despues matriz(:,9) = arreglo%AH ! Pregunta si aplica la correccion write(*,'(/a,F6.1,/a)', advance = "no") "Encontre un error de backlash de ", media_mas-media_menos, & "Aplico esta correccion (s,n)? " read(*,*) resp if(resp == "s") then ! Corrige los errores restando el backlash a los del lado positivo where(arreglo%AH > 0) arreglo%dAH = arreglo%dAH - (media_mas - media_menos) BL = (media_mas - media_menos) endif ! Ahora corrige con los coeficientes que ya conoce arreglo%dAH = arreglo%dAH - FT*cosphi*sin(arreglo%AH*horas_rad)*sin(arreglo%Dec*gra_rad) arreglo%dAH = arreglo%dAH + PH*cos(arreglo%AH*horas_rad)*tan(arreglo%Dec*gra_rad) ! Pone en la segunda columna los errores en AH despues de las correcciones conocidas matriz(:,2) = arreglo%dAH ! En la tercera columna pone el termino de falta de alineacion vertical matriz(:,3) = tan(arreglo%Dec*gra_rad)*sin(arreglo%AH*horas_rad); ! Limita los valores pues la tangente puede hacerse muy grande where(matriz(:,3) > 1000) matriz(:,3) = 1000 where(matriz(:,3) < -1000) matriz(:,3) = -1000 ! Calcula la mejor recta que se ajusta a esta distribucion call ajusta_recta(matriz(:,3), matriz(:,2), m(1), b(1), correlacion(1)) write(*,'(A,3F14.6)') " No alineacion vertical: m, b y corr=", m(1), b(1), correlacion(1) ! Pregunta si aplica la correccion write(*,'(/a)', advance = "no") "Aplico esta correccion (s,n)? " read(*,*) resp if(resp == "s") then ! Corrige los errores usando la recta encontrada arreglo%dAH = arreglo%dAH-( m(1)*matriz(:,3) + b(1) ); PV = m(1) HI = HI + b(1) endif ! En la cuarta columna pone los errores con la correccion anterior matriz(:,4) = arreglo%dAH ! En la quinta columna pone el termino de falta de perpendicularidad matriz(:,5) = tan(arreglo%Dec*gra_rad); ! Tambien limitamos los valores de la tangente where(matriz(:,5) > 1000) matriz(:,5) = 1000 where(matriz(:,5) < -1000) matriz(:,5) = -1000 ! Calcula la mejor recta que se ajusta a esta distribucion call ajusta_recta(matriz(:,5), matriz(:,4), m(1), b(1), correlacion(1)) write(*,'(A,3F14.6)') " No perpendicularidad: m, b y corr=", m(1), b(1), correlacion(1) ! Pregunta si aplica la correccion write(*,'(/a)', advance = "no") "Aplico esta correccion (s,n)? " read(*,*) resp if(resp == "s") then ! Corrige los errores usando la recta encontrada arreglo%dAH = arreglo%dAH-( m(1)*matriz(:,5) + b(1) ); NP = m(1) HI = HI + b(1) endif ! En la columna 6 pone los errores con la correccion anterior matriz(:,6) = arreglo%dAH ! En la columna 7 pone el termino de falta de colimacion matriz(:,7) = 1.0/cos(arreglo%Dec*gra_rad); where(matriz(:,7) > 1000) matriz(:,7) = 1000 where(matriz(:,7) < -1000) matriz(:,7) = -1000 ! Calcula la mejor recta que se ajusta a esta distribucion call ajusta_recta(matriz(:,7), matriz(:,6), m(1), b(1), correlacion(1)) write(*,'(A,3F14.6)') " Colimacion: m, b y corr=", m(1), b(1), correlacion(1) ! Pregunta si aplica la correccion write(*,'(/a)', advance = "no") "Aplico esta correccion (s,n)? " read(*,*) resp if(resp == "s") then ! Corrige los errores usando la recta encontrada arreglo%dAH = arreglo%dAH-( m(1)*matriz(:,7) + b(1) ) CO = m(1) HI = HI + b(1) endif ! En la columna 8 pone los errores con todas las correcciones matriz(:,8) = arreglo%dAH ! Aqui los datos estan acomodados como sigue: ! Col 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 ! ! ---------------------------------------------------------------------------! ! dAH | dAH_ | PV | dAH_PV | NP | dAH_PV_NP | CO | dAH_PV_NP_CO | AH ! call guarda_lineas("prov_ah.txt", matriz) call call call call call call prepara_archivo_de_grafica() agrega_grafica(9,1,'"AH"', '"dAH"', agrega_grafica(3,2,'"PV"', '"dAH"', agrega_grafica(5,4,'"NP"', '"dAH"', agrega_grafica(7,6,'"CO"', '"dAH"', inicia_grafica() end subroutine encuentra_coeficientes_ah end module utilerias 0, 1, 0, 1, 1,'"Errores iniciales"', "prov_ah.txt") 1,'"Alineacion vertical"', "prov_ah.txt") 0,'"Falta de perpendicularidad"', "prov_ah.txt") 0,'"Falta de colimacion"', "prov_ah.txt") !*************************************************************! ! Empieza el programa ! !*************************************************************! Program calcula_modelo ! Trate de poner lo mas posible en subrutinas en el modulo a fin de hacer el programa ! mas compacto. use utilerias ! En este modulo estan las subrutinas implicit none character(len=40) :: archivo integer :: n_lineas real :: rmsdec, rmsah, rmsdec_ant, rmsah_ant, dummy ! ! Para el nombre del archivo que ! contiene los datos ! Numero de lineas en el archivo Primero pide al usuario el nombre del archivo con los datos write(unit=*, fmt='(a)', advance="no") "Teclea el nombre del archivo con los datos: " read(*,*) archivo ! do Pide al usuario la latitude del observatorio y verifica que sea un numero razonable write(unit=*, fmt='(/a,f4.1,a)', advance="no") "Dame la latitud del observatorio en grados (", phi/gra_rad, "): " read(*,*) dummy if(dummy > -80.0 .and. dummy < 80.0) exit enddo phi senphi cosphi ! ! = dummy*gra_rad = sin(phi) = cos(phi) ! la convierte en radianes ! Esto es el seno de la latitud ! Esto es el coseno de la latitud Luego calcula el numero de renglones del archivo para definir los arreglos n_lineas = cuantas_lineas(archivo) ! Verifica que exista y revisa cuantas lineas ! con datos tiene print*, "Hay", n_lineas, "lineas validas" ! Si no hay lineas validas, termina el proceso if(n_lineas == 0) return allocate(arreglo(n_lineas)) allocate(matriz(n_lineas,9)) ! Acomoda el arreglo de n_lineas ! Acomoda la matriz donde pondra ! los datos a graficar call trae_lineas(archivo, arreglo) ! Trae todos los datos y los pone en 'arreglo' ! Luego verifica que AH este entre -12 y 12 where(arreglo%AH > 12.0) arreglo%AH = arreglo%AH-24.0; call grafica_errores('"Errores iniciales"', rmsdec_ant, rmsah_ant) ! Aqui llama a una subrutina que calcula los coeficientes de correccion para la ! Declinacion call encuentra_coeficientes_dec() ! Luego llama a otra subrutina para calcular los coeficientes de correccion para ! el Angulo Horario call encuentra_coeficientes_ah() call grafica_errores('"Errores finales"', rmsdec, rmsah) ! Muestra los coeficientes calculados write(*,'(/A)') "Los coeficientes calculados son:" write(*,'(/A,F8.3)') " (Alineacion horizontal) - PH: ", PH write(*,'(A,F8.3)') " (Alineacion vertical) - PV: ", PV write(*,'(A,F8.3)') " (Flexion del tubo) - FT: ", FT write(*,'(A,F8.3)') " (Flexion del yugo) - FY: ", PV_FY - PV write(*,'(A,F8.3)') "(Falta de perpendicularidad) - NP: ", NP write(*,'(A,F8.3)') " (Error de colimacion) - CO: ", CO write(*,'(A,F8.3)') " (Backlash en AH) - BL: ", BL write(*,'(A,F8.3)') " (Offset en AH) - HI: ", HI write(*,'(A,F8.3)') " (Offset en Dec) - DI: ", DI write(*,'(/A)') "Con esta correccion se han bajado del errores RMS como sigue:" write(*,'(A,F5.1,A,F5.1,A)') " AH: de ", rmsah_ant, " a ", rmsah, " (arcsec)" write(*,'(A,F5.1,A,F5.1,A)') "Dec: de ", rmsdec_ant, " a ", rmsdec, " (arcsec)" ! Pregunta si cerramos los graficos write(*,'(/a)', advance = "no") "Cierro los graficos (s,n)? " read(*,*) resp if(resp == "s") then call system("killall gnuplot_x11") ! Cierra todas las ventanas con gnuplot endif deallocate(arreglo) deallocate(matriz) End Program calcula_modelo !************************************************************************ Apéndice B. Listado del programa en IDL FUNCTION rms, vector media = mean(vector) va = vector - media return, sqrt(mean(va*va)) END PRO encuentra_modelo, ARCHIVO=archivo, LATITUD=latitud, CORRIGE=corrige ;********************************************************************************** ; Programa 'encuentra_modelo.pro' elaborado por Leonel Gutierrez . ; ; Este programa lee un archivo con una serie de datos que muestran ; los errores de apuntado de un telescopio con montura ecuatorial ; y calcula los coeficientes de un modelo trigonometrico para corregir ; dicho apuntado. ;********************************************************************************** ; sintaxis: ENCUENTRA_MODELO, archivo="epos.txt", latitud=19.5, corrige=[1,1,1,0,1,0,1] if (NOT keyword_set(ARCHIVO)) then archivo="epos.txt" if (NOT keyword_set(LATITUD)) then latitud=19.5 if (NOT keyword_set(CORRIGE)) then begin corrigePH=1 corrigePV=1 corrigeFT=1 corrigePV_FY=1 corrigeNP=1 corrigeCO=1 corrigeBL=1 endif else begin if n_elements(corrige) ne 7 then begin print, "Corrige debe tener 7 elementos en el orden [PH,PV,FT,PV_FY,NP,CO,BL]." print, "Poner 1 en la correccion que se desea y 0 en la que no." return endif corrigePH=corrige(0) corrigePV=corrige(1) corrigeFT=corrige(2) corrigePV_FY=corrige(3) corrigeNP=corrige(4) corrigeCO=corrige(5) corrigeBL=corrige(6) endelse ;Trae los datos del archivo readcol,archivo,f='(f,f,f,f)', ah, dah, dec, ddec ; Inicia una ventana para desplegar las graficas window, 1, xsi=300,ysi=300,retain=2, title="Errores iniciales" white = !D.N_COLORS-1 !P.color = 0 !p.background = white ; Desplegara solo una grafica !p.multi = [0,1,1,0,0] sx = "dDec (rms=" +string(rms(dDec),f='(f6.2)') + ")" sy = "dAH (rms=" +string(rms(dAH),f='(f6.2)') + ")" plot,ddec,dah,psym=4,symsize=0.5,xtitle=sx, ytitle=sy print, "rms de dAH y dDec (antes): ", rms(dAH), rms(dDec) ; Mi definicion de PI pi=acos(-1) ; Pone la latitud y calculas el seno y el coseno phi=latitud senphi = sin(phi*pi/180.0) cosphi = cos(phi*pi/180.0) ; Inicia otra ventana para desplegar el proceso de correccion en declinacion window, 2, xsi=600,ysi=600,retain=2, title="Correcciones en declinacion" ; Desplegara 4 graficas !p.multi = [0,2,2,0,0] ; Para calcular el termino correspondiente a las flexiones del tubo term1 = -senphi*cos(dec*pi/180.0) + cosphi*sin(dec*pi/180.0)*cos(ah*15*pi/180.0) ; Grafica los errores plot,term1,ddec,psym=4,symsize=0.5,xtitle='FT', ytitle='dDec' xyouts, 120,260+300,"Flexiones del tubo", /device ; Ajusta una recta y calcula FT params = fltarr(2) params = linfit(term1,ddec) DI = params(0) FT = 0.0 if corrigeFT then begin FT = params(1) ; Corrige los errores ddec = ddec - (FT*term1 + DI) endif ; Para corregir las flexiones del yugo y la falta de alineacion vertical term2 = cos(ah*15*pi/180.0) plot, term2,ddec,psym=4,symsize=0.5,xtitle='PV+FY', ytitle='dDec' xyouts, 120+300,260+300,"Flex. yugo + alin. vert.", /device ; Ajusta una recta y calcula PV_FY params = linfit(term2,ddec) DI = params(0) + DI PV_FY = 0.0 if (corrigePV_FY) then begin PV_FY = params(1) ; Corrige los errores ddec = ddec-(PV_FY*term2 + params(0)) endif ; Para corregir la falta de alineacion horizontal term3 = sin(ah*15*pi/180.0) plot, term3,ddec,psym=4,symsize=0.5,xtitle='PH', ytitle='dDec' xyouts, 120,260,"Alin. horizontal", /device ; Ajusta una recta y calcula FT params = linfit(term3,ddec) DI = params(0) + DI PH = 0.0 if (corrigePH) then begin PH = params(1) ; Corrige los errores ddec = ddec-(PH*term3 + params(0)) endif ; Grafica los errores en declinacion una vez corregidos plot,term1,ddec,psym=4,symsize=0.5,xtitle='FT', ytitle='dDec' xyouts, 120+300,260,"Errores corregidos en Dec", /device ; Inicia otra ventana para desplegar el proceso de correccion en AH window, 3, xsi=600,ysi=600,retain=2, title="Correcciones en AH" ; Grafica los errores plot,AH,dAH,psym=4,symsize=0.5,xtitle='AH', ytitle='dAH' xyouts, 120,260+300,"Errores iniciales", /device ; Para calcular el Backlash, calcula la media de los errores donde AH > 0 crit = where(ah>0) mediamas = mean(dAh(crit)) ; Luego calcula la media del lado negativo crit1 = where(ah<0) mediamenos = mean(dAh(crit1)) ; Calcula el backlash BL = mediamas - mediamenos if (corrigeBL) then begin ; Lo resta a los del lado positivo dah(crit) = dah(crit) - BL endif ; Corrige los errores en AH con los terminos que ya se conocen dah=dah-FT*cosphi*sin(ah*15*pi/180.0)*sin(dec*pi/180.0) dah = dah + PH*cos(ah*15*pi/180.0)*tan(dec*pi/180.0) ; Para corregir por falta de alineacion vertical term4 = sin(ah*15*pi/180.0)*tan(dec*pi/180.0) plot, term4,dah,psym=4, symsize=0.5,xtitle='PV', ytitle='dDec' xyouts, 120+300,260+300,"Alineacion vertical", /device ; Ajusta una recta y calcula PV params = linfit(term4,dAH) HI = params(0) PV = 0.0 if (corrigePV) then begin PV = params(1) ; Corrige los errores dAH = dAH-(PV*term4 + params(0)) endif ; Para corregir por perpendicularidad term5 = tan(dec*pi/180.0) plot, term5,dah,psym=4, symsize=0.5,xtitle='NP', ytitle='dDec' xyouts, 120,260,"Perpendicularidad", /device ; Ajusta una recta y calcula NP params = linfit(term5,dAH) HI = HI + params(0) NP = 0.0 if (corrigeNP) then begin NP = params(1) ; Corrige los errores dAH = dAH-(NP*term5 + params(0)) endif ; Para corregir por falta de colimacion term6 = 1.0/cos(dec*pi/180.0) plot, term6,dah,psym=4, symsize=0.5,xtitle='CO', ytitle='dDec' xyouts, 120+300,260,"Falta de colimacion", /device ; Ajusta una recta y calcula CO params = linfit(term6,dAH) HI = HI + params(0) CO = 0.0 if (corrigeCO) then begin CO = params(1) ; Corrige los errores dAH = dAH-(CO*term6 + params(0)) endif ; Inicia otra ventana para desplegar la grafica final window, 4, xsi=300,ysi=300,retain=2, title="Errores corregidos" ; Desplegara solo una grafica !p.multi = [0,1,1,0,0] sx = "dDec (rms=" +string(rms(dDec),f='(f6.2)') + ")" sy = "dAH (rms=" +string(rms(dAH),f='(f6.2)') + ")" plot,ddec,dah,psym=4,symsize=0.5,xtitle=sx, ytitle=sy print, print, print, print, print, print, print, print, print, " (Alineacion horizontal) " (Alineacion vertical) " (Flexiones del tubo) " (Flexiones del yugo) "(Falta de perpendicularidad) " (Error de colimacion) " (Backlash en AH) " (Offset en AH) " (Offset en Dec) - PH: PV: FT: FY: NP: CO: BL: HI: DI: ", ", ", ", ", ", ", ", ", PH PV FT PV_FY - PV NP CO BL HI DI print, "rms de dAH y dDec (despues): ", rms(dAH), rms(dDec) END