Commit 55ae73d410663e52d3632f3d1c550cab84ddf5ae

Authored by Alain Klotz
1 parent ad2b1e4a
Exists in master

Ameliorations WCS

.gitignore
1 1 __pycache__
2   -de421.bsp
3 2 photometrie1.txt
4 3 requirements.txt
5 4 build
... ...
resources/solar_system/de421.bsp 0 → 100644
No preview for this file type
src/guitastro/.gitignore 0 → 100644
... ... @@ -0,0 +1 @@
  1 +de421.bsp
... ...
src/guitastro/ephemeris.py
... ... @@ -1980,10 +1980,10 @@ if __name__ == "__main__":
1980 1980  
1981 1981 if example == 16:
1982 1982 """
1983   - Load a matrix file generated by PyROS
  1983 + Load a matrix file schedule generated by PyROS
1984 1984 """
1985 1985 eph = Ephemeris()
1986   - fname = r"C:\srv\develop\pyros_soft\pyros\data\sequence\P001\20230831\scheduler_schedule.txt"
  1986 + fname = r"C:\srv\develop\pyros_soft\DATA\PRODUCTS\TESTS\LONGSTORE\sequences\P001\20230925\scheduler_schedule.txt"
1987 1987 eph.skdl_plot_schedule(fname)
1988 1988  
1989 1989  
... ...
src/guitastro/wcs.py
... ... @@ -800,6 +800,134 @@ class Wcs(WcsException, GuitastroTools):
800 800 self.wcs2skyfield(naxis1, naxis2)
801 801 return self._skyfield;
802 802  
  803 + def skyfield2fov(self, skyfield:dict) ->tuple:
  804 + """ Compute the image field of view profected on R.A., Dec. from a skyfield.
  805 +
  806 + Args:
  807 + skyfield: Input values.
  808 +
  809 + Returns:
  810 + Two elements defining the field of view:
  811 +
  812 + * fovra: (float) Field of view along Right Ascension (unit degrees)
  813 + * fovdec: (float) Field of view along Declination (unit degrees)
  814 + """
  815 + cd11 = math.degrees(skyfield["cd11rad"])
  816 + cd12 = math.degrees(skyfield["cd12rad"])
  817 + cd21 = math.degrees(skyfield["cd21rad"])
  818 + cd22 = math.degrees(skyfield["cd22rad"])
  819 + naxis1 = skyfield["naxis1"]
  820 + naxis2 = skyfield["naxis2"]
  821 + cdelt1, cdelt2, crota2 = self.cd2cdelt(cd11, cd12, cd21, cd22)
  822 + crota2r = math.radians(crota2)
  823 + cosrota = math.cos(crota2r)
  824 + sinrota = math.sin(crota2r)
  825 + fov1 = cdelt1*naxis1
  826 + fov2 = cdelt2*naxis2
  827 + fovra = abs(fov1*cosrota) + abs(fov2*sinrota)
  828 + fovdec = abs(fov1*sinrota) + abs(fov2*cosrota)
  829 + return fovra, fovdec
  830 +
  831 + def is_skyfield_in_radecfov(self, ra:float, dec:float, fovra:float, fovdec:float, coscrval1:float, sincrval1: float, coscrval2:float, sincrval2: float) ->bool:
  832 + """Check if (ra,dec) target is perhaps inside a skyfields.
  833 +
  834 + Skyfield is defined by 12 elements.
  835 + Four of them are required as input of this method: coscrval1, sincrval1, coscrval2, sincrval2.
  836 + (ra, dec) target must be related to the same equinox than crval1, crval2 coordinates.
  837 + The code of this method can be adapted in programs that manage a SQL database.
  838 + The algorithm is rapid but not rigourous.
  839 + The goal is to exclude skyfields well outside the field of view.
  840 + Before using is_skyfield_in_radecfov() use skyfield2fov().
  841 + After using is_skyfield_in_radecfov() use skyfields2indexes().
  842 +
  843 + Args:
  844 + ra: Right ascension (degrees) of the target
  845 + dec: Declination (degrees) of the target
  846 + fov: Field of view (degrees) of the images stored in skyfield
  847 + coscrval1: cosinus of the CRVAL1 coordinate (degrees) of the skyfield
  848 + sincrval1: sinus of the CRVAL1 coordinate (degrees) of the skyfield
  849 + coscrval2: cosinus of the CRVAL2 coordinate (degrees) of the skyfield
  850 + sincrval2: sinus of the CRVAL2 coordinate (degrees) of the skyfield
  851 +
  852 + Returns:
  853 + Bolean value is True if the target should be inside the field of view.
  854 + """
  855 + decr = math.radians(dec)
  856 + fovracos = fovra/math.cos(decr)
  857 + if fovracos > 180:
  858 + fovracos = 180
  859 + # --- ra
  860 + rar = math.radians(ra+fovracos/2)
  861 + cosrap= math.cos(rar)
  862 + sinrap= math.sin(rar)
  863 + rar = math.radians(ra-fovracos/2)
  864 + cosram= math.cos(rar)
  865 + sinram= math.sin(rar)
  866 + if cosrap < cosram:
  867 + cosrap , cosram = cosram , cosrap
  868 + if sinrap < sinram:
  869 + sinrap , sinram = sinram , sinrap
  870 + if sinram < 0 and sinrap >= 0:
  871 + if cosram > 0:
  872 + cosrap = 1
  873 + else:
  874 + cosrap = -1
  875 + if cosram < 0 and cosrap >= 0:
  876 + if sinram > 0:
  877 + sinrap = 1
  878 + else:
  879 + sinrap = -1
  880 + # --- dec
  881 + decr = math.radians(dec+fovdec/2)
  882 + cosdecp= math.cos(decr)
  883 + sindecp= math.sin(decr)
  884 + decr = math.radians(dec-fovdec/2)
  885 + cosdecm= math.cos(decr)
  886 + sindecm= math.sin(decr)
  887 + # --- re-arange min, max
  888 + if cosdecp < cosdecm:
  889 + cosdecp , cosdecm = cosdecm , cosdecp
  890 + if sindecp < sindecm:
  891 + sindecp , sindecm = sindecm , sindecp
  892 + if sindecm < 0 and sindecp >= 0:
  893 + if cosdecm > 0:
  894 + cosdecp = 1
  895 + else:
  896 + cosdecp = -1
  897 + if cosdecm < 0 and cosdecp >= 0:
  898 + if sindecm > 0:
  899 + sindecp = 1
  900 + else:
  901 + sindecp = -1
  902 + # --- SQL request
  903 + # sql_query = "WHERE"
  904 + # sql_query += f" `coscrval1` >= {cosram}"
  905 + # sql_query += f" AND `coscrval1` <= {cosrap}"
  906 + # sql_query += f" AND `sincrval1` >= {sinram}"
  907 + # sql_query += f" AND `sincrval1` <= {sinrap}"
  908 + # sql_query += f" AND `coscrval2` >= {cosdecm}"
  909 + # sql_query += f" AND `coscrval2` <= {cosdecp}"
  910 + # sql_query += f" AND `sincrval2` >= {sindecm}"
  911 + # sql_query += f" AND `sincrval2` <= {sindecp}"
  912 + # --- test is true only if 4 crval* are inside the limits
  913 + if coscrval1 < cosram:
  914 + return False
  915 + if coscrval1 > cosrap:
  916 + return False
  917 + if sincrval1 < sinram:
  918 + return False
  919 + if sincrval1 > sinrap:
  920 + return False
  921 + if coscrval2 < cosdecm:
  922 + return False
  923 + if coscrval2 > cosdecp:
  924 + return False
  925 + if sincrval2 < sindecm:
  926 + return False
  927 + if sincrval2 > sindecp:
  928 + return False
  929 + return True
  930 +
803 931 def skyfields2indexes(self, ra:float, dec:float, skyfields:list):
804 932 """Check if (ra,dec) is inside a list of skyfields.
805 933  
... ... @@ -846,7 +974,7 @@ class Wcs(WcsException, GuitastroTools):
846 974 cd22 = skyfield["cd22rad"]
847 975 crp1 = skyfield["crpix1"]
848 976 crp2 = skyfield["crpix2"]
849   - naxis1 = skyfield["naxis2"]
  977 + naxis1 = skyfield["naxis1"]
850 978 naxis2 = skyfield["naxis2"]
851 979 ccca = cc*ca # cos(dec)*cos(ra) * cos(ra0)
852 980 cssa = cs*sa # cos(dec)*sin(ra) * sin(ra0)
... ... @@ -878,8 +1006,8 @@ class Wcs(WcsException, GuitastroTools):
878 1006  
879 1007 if __name__ == "__main__":
880 1008  
881   - default = 3
882   - example = input(f"Select the example (0 to 3) ({default}) ")
  1009 + default = 4
  1010 + example = input(f"Select the example (0 to 4) ({default}) ")
883 1011 try:
884 1012 example = int(example)
885 1013 except:
... ... @@ -912,14 +1040,57 @@ if __name__ == &quot;__main__&quot;:
912 1040  
913 1041 if example == 3:
914 1042 """
915   - Use of skyfield
  1043 + Use of skyfields2indexes
916 1044 """
917 1045 skyfields = []
918 1046 wcs = Wcs()
919   - wcs.optic(512, 512, "6h00m", "+30d", 9, 9, 1, 0)
  1047 + wcs.optic(512, 512, "8h00m", "+34d", 9, 9, 1, 0)
920 1048 skyfield = wcs.skyfield_get(1024, 1024)
921 1049 skyfields.append(skyfield)
922   - wcs.optic(512, 512, "8h00m", "+34d", 9, 9, 1, 0)
  1050 + wcs.optic(512, 512, "6h00m", "+30d", 9, 9, 1, 0)
923 1051 skyfield = wcs.skyfield_get(1024, 1024)
924 1052 skyfields.append(skyfield)
925 1053 indexes = wcs.skyfields2indexes(90.2, 30.04, skyfields)
  1054 + for index in indexes:
  1055 + i, x, y = index
  1056 + ra, dec = wcs.xy2radec(x, y)
  1057 + print(f"Target {i} position in the image {x=:.2f} {y=:.2f}. R.A.={ra:.2f} Dec.={dec:.2f}")
  1058 +
  1059 + if example == 4:
  1060 + """
  1061 + Use of is_skyfield_in_radecfov
  1062 + """
  1063 + wcs = Wcs()
  1064 + # - Skyfield definition for the test
  1065 + wcs.optic(512, 512, "0h00m", "+31d", 9, 9, 1, 0)
  1066 + skyfield = wcs.skyfield_get(1024, 1024)
  1067 + fovra, fovdec = wcs.skyfield2fov(skyfield)
  1068 + print("=== Skyfield characteristics:")
  1069 + print(f"Image field of view {fovra:.2f} x {fovdec:.2f} degrees")
  1070 + crval1 = wcs.getval('CRVAL1')[0]
  1071 + crval2 = wcs.getval('CRVAL2')[0]
  1072 + print(f"Image center R.A.={crval1:.2f} Dec.={crval2:.2f} degrees")
  1073 + # - Get the four elements
  1074 + coscrval1 = skyfield['coscrval1']
  1075 + sincrval1 = skyfield['sincrval1']
  1076 + coscrval2 = skyfield['coscrval2']
  1077 + sincrval2 = skyfield['sincrval2']
  1078 + # - Target to check if inside the image defined by skyfield
  1079 + print("=== Target characteristics:")
  1080 + ra = 0.3
  1081 + dec = 31.22
  1082 + res = wcs.is_skyfield_in_radecfov(ra, dec, fovra, fovdec, coscrval1, sincrval1, coscrval2, sincrval2)
  1083 + resp = f"Target R.A.={ra:.2f} Dec.={dec:.2f} is "
  1084 + if res:
  1085 + resp += "inside the image."
  1086 + else:
  1087 + resp += "outside the image."
  1088 + print(f"{resp}")
  1089 + if res:
  1090 + skyfields = []
  1091 + skyfields.append(skyfield)
  1092 + indexes = wcs.skyfields2indexes(ra, dec, skyfields)
  1093 + for index in indexes:
  1094 + i, x, y = index
  1095 + print(f"Target position in the image {x=:.2f} {y=:.2f}")
  1096 +
... ...