igs-slm 0.1.0b0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (447) hide show
  1. igs_slm-0.1.0b0.dist-info/LICENSE +21 -0
  2. igs_slm-0.1.0b0.dist-info/METADATA +151 -0
  3. igs_slm-0.1.0b0.dist-info/RECORD +447 -0
  4. igs_slm-0.1.0b0.dist-info/WHEEL +4 -0
  5. igs_slm-0.1.0b0.dist-info/entry_points.txt +3 -0
  6. igs_tools/__init__.py +0 -0
  7. igs_tools/connection.py +88 -0
  8. igs_tools/defines/__init__.py +8 -0
  9. igs_tools/defines/constellation.py +21 -0
  10. igs_tools/defines/data_center.py +75 -0
  11. igs_tools/defines/rinex.py +49 -0
  12. igs_tools/directory.py +247 -0
  13. igs_tools/utils.py +66 -0
  14. slm/__init__.py +21 -0
  15. slm/admin.py +674 -0
  16. slm/api/edit/__init__.py +0 -0
  17. slm/api/edit/serializers.py +316 -0
  18. slm/api/edit/views.py +1632 -0
  19. slm/api/fields.py +89 -0
  20. slm/api/filter.py +504 -0
  21. slm/api/pagination.py +55 -0
  22. slm/api/permissions.py +65 -0
  23. slm/api/public/__init__.py +0 -0
  24. slm/api/public/serializers.py +249 -0
  25. slm/api/public/views.py +606 -0
  26. slm/api/serializers.py +132 -0
  27. slm/api/views.py +148 -0
  28. slm/apps.py +323 -0
  29. slm/authentication.py +198 -0
  30. slm/bin/__init__.py +0 -0
  31. slm/bin/startproject.py +262 -0
  32. slm/bin/templates/{{ project_dir }}/pyproject.toml +35 -0
  33. slm/bin/templates/{{ project_dir }}/sites/__init__.py +0 -0
  34. slm/bin/templates/{{ project_dir }}/sites/{{ site }}/__init__.py +0 -0
  35. slm/bin/templates/{{ project_dir }}/sites/{{ site }}/base.py +15 -0
  36. slm/bin/templates/{{ project_dir }}/sites/{{ site }}/develop/__init__.py +56 -0
  37. slm/bin/templates/{{ project_dir }}/sites/{{ site }}/develop/local.py +4 -0
  38. slm/bin/templates/{{ project_dir }}/sites/{{ site }}/develop/wsgi.py +16 -0
  39. slm/bin/templates/{{ project_dir }}/sites/{{ site }}/manage.py +34 -0
  40. slm/bin/templates/{{ project_dir }}/sites/{{ site }}/production/__init__.py +61 -0
  41. slm/bin/templates/{{ project_dir }}/sites/{{ site }}/production/wsgi.py +16 -0
  42. slm/bin/templates/{{ project_dir }}/sites/{{ site }}/urls.py +7 -0
  43. slm/bin/templates/{{ project_dir }}/sites/{{ site }}/validation.py +11 -0
  44. slm/bin/templates/{{ project_dir }}/{{ extension_app }}/__init__.py +0 -0
  45. slm/bin/templates/{{ project_dir }}/{{ extension_app }}/admin.py +5 -0
  46. slm/bin/templates/{{ project_dir }}/{{ extension_app }}/apps.py +14 -0
  47. slm/bin/templates/{{ project_dir }}/{{ extension_app }}/management/__init__.py +0 -0
  48. slm/bin/templates/{{ project_dir }}/{{ extension_app }}/management/commands/__init__.py +0 -0
  49. slm/bin/templates/{{ project_dir }}/{{ extension_app }}/management/commands/import_archive.py +64 -0
  50. slm/bin/templates/{{ project_dir }}/{{ extension_app }}/migrations/__init__.py +0 -0
  51. slm/bin/templates/{{ project_dir }}/{{ extension_app }}/models.py +6 -0
  52. slm/bin/templates/{{ project_dir }}/{{ extension_app }}/templates/slm/base.html +8 -0
  53. slm/bin/templates/{{ project_dir }}/{{ extension_app }}/urls.py +10 -0
  54. slm/bin/templates/{{ project_dir }}/{{ extension_app }}/views.py +5 -0
  55. slm/defines/AlertLevel.py +24 -0
  56. slm/defines/AntennaCalibration.py +25 -0
  57. slm/defines/AntennaFeatures.py +27 -0
  58. slm/defines/AntennaReferencePoint.py +22 -0
  59. slm/defines/Aspiration.py +13 -0
  60. slm/defines/CardinalDirection.py +19 -0
  61. slm/defines/CollocationStatus.py +12 -0
  62. slm/defines/EquipmentState.py +22 -0
  63. slm/defines/FlagSeverity.py +14 -0
  64. slm/defines/FractureSpacing.py +15 -0
  65. slm/defines/FrequencyStandardType.py +15 -0
  66. slm/defines/GeodesyMLVersion.py +48 -0
  67. slm/defines/ISOCountry.py +1194 -0
  68. slm/defines/Instrumentation.py +19 -0
  69. slm/defines/LogEntryType.py +30 -0
  70. slm/defines/SLMFileType.py +18 -0
  71. slm/defines/SiteFileUploadStatus.py +61 -0
  72. slm/defines/SiteLogFormat.py +49 -0
  73. slm/defines/SiteLogStatus.py +78 -0
  74. slm/defines/TectonicPlates.py +28 -0
  75. slm/defines/__init__.py +46 -0
  76. slm/forms.py +1126 -0
  77. slm/jinja2/slm/sitelog/ascii_9char.log +346 -0
  78. slm/jinja2/slm/sitelog/legacy.log +346 -0
  79. slm/jinja2/slm/sitelog/xsd/0.4/collocationInformation.xml +12 -0
  80. slm/jinja2/slm/sitelog/xsd/0.4/condition.xml +12 -0
  81. slm/jinja2/slm/sitelog/xsd/0.4/contact.xml +52 -0
  82. slm/jinja2/slm/sitelog/xsd/0.4/formInformation.xml +5 -0
  83. slm/jinja2/slm/sitelog/xsd/0.4/frequencyStandard.xml +12 -0
  84. slm/jinja2/slm/sitelog/xsd/0.4/gnssAntenna.xml +16 -0
  85. slm/jinja2/slm/sitelog/xsd/0.4/gnssReceiver.xml +11 -0
  86. slm/jinja2/slm/sitelog/xsd/0.4/humiditySensor.xml +13 -0
  87. slm/jinja2/slm/sitelog/xsd/0.4/localEpisodicEffect.xml +10 -0
  88. slm/jinja2/slm/sitelog/xsd/0.4/moreInformation.xml +22 -0
  89. slm/jinja2/slm/sitelog/xsd/0.4/multipathSource.xml +10 -0
  90. slm/jinja2/slm/sitelog/xsd/0.4/otherInstrumentation.xml +5 -0
  91. slm/jinja2/slm/sitelog/xsd/0.4/pressureSensor.xml +12 -0
  92. slm/jinja2/slm/sitelog/xsd/0.4/radioInterference.xml +11 -0
  93. slm/jinja2/slm/sitelog/xsd/0.4/sensor.xml +16 -0
  94. slm/jinja2/slm/sitelog/xsd/0.4/signalObstruction.xml +10 -0
  95. slm/jinja2/slm/sitelog/xsd/0.4/siteIdentification.xml +22 -0
  96. slm/jinja2/slm/sitelog/xsd/0.4/siteLocation.xml +21 -0
  97. slm/jinja2/slm/sitelog/xsd/0.4/surveyedLocalTie.xml +20 -0
  98. slm/jinja2/slm/sitelog/xsd/0.4/temperatureSensor.xml +13 -0
  99. slm/jinja2/slm/sitelog/xsd/0.4/waterVaporSensor.xml +11 -0
  100. slm/jinja2/slm/sitelog/xsd/0.5/document.xml +10 -0
  101. slm/jinja2/slm/sitelog/xsd/geodesyml_0.4.xml +99 -0
  102. slm/jinja2/slm/sitelog/xsd/geodesyml_0.5.xml +112 -0
  103. slm/management/__init__.py +0 -0
  104. slm/management/commands/__init__.py +53 -0
  105. slm/management/commands/build_index.py +96 -0
  106. slm/management/commands/generate_sinex.py +675 -0
  107. slm/management/commands/head_from_index.py +541 -0
  108. slm/management/commands/import_archive.py +908 -0
  109. slm/management/commands/import_equipment.py +351 -0
  110. slm/management/commands/set_site.py +56 -0
  111. slm/management/commands/sitelog.py +144 -0
  112. slm/management/commands/synchronize.py +60 -0
  113. slm/management/commands/update_data_availability.py +167 -0
  114. slm/management/commands/validate_db.py +186 -0
  115. slm/management/commands/validate_gml.py +73 -0
  116. slm/map/__init__.py +1 -0
  117. slm/map/admin.py +5 -0
  118. slm/map/api/__init__.py +0 -0
  119. slm/map/api/edit/__init__.py +0 -0
  120. slm/map/api/edit/serializers.py +28 -0
  121. slm/map/api/edit/views.py +46 -0
  122. slm/map/api/public/__init__.py +0 -0
  123. slm/map/api/public/serializers.py +29 -0
  124. slm/map/api/public/views.py +64 -0
  125. slm/map/apps.py +7 -0
  126. slm/map/defines.py +53 -0
  127. slm/map/migrations/0001_initial.py +115 -0
  128. slm/map/migrations/__init__.py +0 -0
  129. slm/map/models.py +63 -0
  130. slm/map/static/slm/css/map.css +86 -0
  131. slm/map/static/slm/js/map.js +159 -0
  132. slm/map/templates/slm/map.html +374 -0
  133. slm/map/templates/slm/station/base.html +11 -0
  134. slm/map/templates/slm/station/edit.html +10 -0
  135. slm/map/templates/slm/top_nav.html +17 -0
  136. slm/map/templatetags/__init__.py +0 -0
  137. slm/map/templatetags/slm_map.py +18 -0
  138. slm/map/urls.py +25 -0
  139. slm/map/views.py +36 -0
  140. slm/middleware.py +29 -0
  141. slm/migrations/0001_alter_siteantenna_marker_enu_alter_sitelocation_llh_and_more.py +47 -0
  142. slm/migrations/0001_initial.py +4826 -0
  143. slm/migrations/0002_alter_dataavailability_site.py +22 -0
  144. slm/migrations/0003_remove_logentry_slm_logentr_site_lo_7a2af7_idx_and_more.py +80 -0
  145. slm/migrations/0004_alter_logentry_timestamp_and_more.py +25 -0
  146. slm/migrations/0005_alter_logentry_options_alter_logentry_section_and_more.py +46 -0
  147. slm/migrations/0006_alter_logentry_options_alter_logentry_index_together.py +24 -0
  148. slm/migrations/0007_alter_dataavailability_rate.py +23 -0
  149. slm/migrations/0008_alter_archiveindex_options_and_more.py +64 -0
  150. slm/migrations/0009_alter_archiveindex_end.py +21 -0
  151. slm/migrations/0010_alter_dataavailability_rinex_version_and_more.py +844 -0
  152. slm/migrations/0011_alter_siteidentification_fracture_spacing.py +33 -0
  153. slm/migrations/0012_alter_logentry_type.py +36 -0
  154. slm/migrations/0013_unpublishedfilesalert.py +48 -0
  155. slm/migrations/0014_sitelogpublished.py +48 -0
  156. slm/migrations/0015_alter_siteantenna_options_and_more.py +181 -0
  157. slm/migrations/0016_alter_antenna_description_alter_radome_description_and_more.py +42 -0
  158. slm/migrations/0017_alter_logentry_unique_together_and_more.py +54 -0
  159. slm/migrations/0018_afix_deleted.py +34 -0
  160. slm/migrations/0018_alter_siteantenna_options_and_more.py +244 -0
  161. slm/migrations/0019_remove_siteantenna_marker_enu_siteantenna_marker_une_and_more.py +101 -0
  162. slm/migrations/0020_alter_manufacturer_options.py +16 -0
  163. slm/migrations/0021_alter_siteform_report_type.py +23 -0
  164. slm/migrations/0022_rename_antcal_antenna_radome_slm_antcal_antenna_20827a_idx_and_more.py +297 -0
  165. slm/migrations/0023_archivedsitelog_gml_version_and_more.py +55 -0
  166. slm/migrations/0024_alter_agency_name_alter_agency_shortname.py +24 -0
  167. slm/migrations/0025_alter_archivedsitelog_log_format_and_more.py +61 -0
  168. slm/migrations/0026_alter_archivedsitelog_log_format_and_more.py +61 -0
  169. slm/migrations/0027_importalert_file_contents_importalert_findings_and_more.py +41 -0
  170. slm/migrations/0028_antenna_replaced_manufacturer_url_radome_replaced_and_more.py +46 -0
  171. slm/migrations/0029_manufacturer_full_name.py +17 -0
  172. slm/migrations/0030_alter_antenna_state_alter_radome_state_and_more.py +43 -0
  173. slm/migrations/__init__.py +0 -0
  174. slm/migrations/load_satellitesystems.py +27 -0
  175. slm/models/__init__.py +118 -0
  176. slm/models/about.py +14 -0
  177. slm/models/alerts.py +1204 -0
  178. slm/models/data.py +58 -0
  179. slm/models/equipment.py +229 -0
  180. slm/models/help.py +14 -0
  181. slm/models/index.py +428 -0
  182. slm/models/sitelog.py +4279 -0
  183. slm/models/system.py +723 -0
  184. slm/models/user.py +304 -0
  185. slm/parsing/__init__.py +786 -0
  186. slm/parsing/legacy/__init__.py +4 -0
  187. slm/parsing/legacy/binding.py +817 -0
  188. slm/parsing/legacy/parser.py +377 -0
  189. slm/parsing/xsd/__init__.py +34 -0
  190. slm/parsing/xsd/binding.py +86 -0
  191. slm/parsing/xsd/geodesyml/0.4/commonTypes.xsd +133 -0
  192. slm/parsing/xsd/geodesyml/0.4/contact.xsd +29 -0
  193. slm/parsing/xsd/geodesyml/0.4/dataStreams.xsd +129 -0
  194. slm/parsing/xsd/geodesyml/0.4/document.xsd +64 -0
  195. slm/parsing/xsd/geodesyml/0.4/equipment.xsd +427 -0
  196. slm/parsing/xsd/geodesyml/0.4/fieldMeasurement.xsd +170 -0
  197. slm/parsing/xsd/geodesyml/0.4/geodesyML.xsd +71 -0
  198. slm/parsing/xsd/geodesyml/0.4/geodeticEquipment.xsd +343 -0
  199. slm/parsing/xsd/geodesyml/0.4/geodeticMonument.xsd +147 -0
  200. slm/parsing/xsd/geodesyml/0.4/lineage.xsd +614 -0
  201. slm/parsing/xsd/geodesyml/0.4/localInterferences.xsd +131 -0
  202. slm/parsing/xsd/geodesyml/0.4/measurement.xsd +473 -0
  203. slm/parsing/xsd/geodesyml/0.4/monumentInfo.xsd +251 -0
  204. slm/parsing/xsd/geodesyml/0.4/observationSystem.xsd +429 -0
  205. slm/parsing/xsd/geodesyml/0.4/project.xsd +38 -0
  206. slm/parsing/xsd/geodesyml/0.4/quality.xsd +176 -0
  207. slm/parsing/xsd/geodesyml/0.4/referenceFrame.xsd +194 -0
  208. slm/parsing/xsd/geodesyml/0.4/siteLog.xsd +71 -0
  209. slm/parsing/xsd/geodesyml/0.5/commonTypes.xsd +133 -0
  210. slm/parsing/xsd/geodesyml/0.5/contact.xsd +29 -0
  211. slm/parsing/xsd/geodesyml/0.5/dataStreams.xsd +129 -0
  212. slm/parsing/xsd/geodesyml/0.5/document.xsd +64 -0
  213. slm/parsing/xsd/geodesyml/0.5/equipment.xsd +427 -0
  214. slm/parsing/xsd/geodesyml/0.5/fieldMeasurement.xsd +170 -0
  215. slm/parsing/xsd/geodesyml/0.5/geodesyML.xsd +71 -0
  216. slm/parsing/xsd/geodesyml/0.5/geodeticEquipment.xsd +343 -0
  217. slm/parsing/xsd/geodesyml/0.5/geodeticMonument.xsd +147 -0
  218. slm/parsing/xsd/geodesyml/0.5/lineage.xsd +614 -0
  219. slm/parsing/xsd/geodesyml/0.5/localInterferences.xsd +131 -0
  220. slm/parsing/xsd/geodesyml/0.5/measurement.xsd +473 -0
  221. slm/parsing/xsd/geodesyml/0.5/monumentInfo.xsd +306 -0
  222. slm/parsing/xsd/geodesyml/0.5/observationSystem.xsd +429 -0
  223. slm/parsing/xsd/geodesyml/0.5/project.xsd +38 -0
  224. slm/parsing/xsd/geodesyml/0.5/quality.xsd +176 -0
  225. slm/parsing/xsd/geodesyml/0.5/referenceFrame.xsd +194 -0
  226. slm/parsing/xsd/geodesyml/0.5/siteLog.xsd +73 -0
  227. slm/parsing/xsd/parser.py +116 -0
  228. slm/parsing/xsd/resolver.py +28 -0
  229. slm/receivers/__init__.py +11 -0
  230. slm/receivers/alerts.py +87 -0
  231. slm/receivers/cleanup.py +41 -0
  232. slm/receivers/event_loggers.py +175 -0
  233. slm/receivers/index.py +67 -0
  234. slm/settings/__init__.py +55 -0
  235. slm/settings/auth.py +15 -0
  236. slm/settings/ckeditor.py +14 -0
  237. slm/settings/debug.py +47 -0
  238. slm/settings/internationalization.py +12 -0
  239. slm/settings/logging.py +113 -0
  240. slm/settings/platform/__init__.py +0 -0
  241. slm/settings/platform/darwin.py +10 -0
  242. slm/settings/rest.py +21 -0
  243. slm/settings/root.py +152 -0
  244. slm/settings/routines.py +43 -0
  245. slm/settings/secrets.py +37 -0
  246. slm/settings/security.py +5 -0
  247. slm/settings/slm.py +188 -0
  248. slm/settings/static_templates.py +53 -0
  249. slm/settings/templates.py +29 -0
  250. slm/settings/uploads.py +8 -0
  251. slm/settings/urls.py +126 -0
  252. slm/settings/validation.py +196 -0
  253. slm/signals.py +250 -0
  254. slm/singleton.py +49 -0
  255. slm/static/rest_framework/css/bootstrap-tweaks.css +204 -0
  256. slm/static/rest_framework/css/bootstrap.min.css +7 -0
  257. slm/static/rest_framework/css/bootstrap.min.css.map +1 -0
  258. slm/static/rest_framework/css/default.css +82 -0
  259. slm/static/rest_framework/css/prettify.css +30 -0
  260. slm/static/rest_framework/docs/css/base.css +344 -0
  261. slm/static/rest_framework/docs/css/highlight.css +125 -0
  262. slm/static/rest_framework/docs/css/jquery.json-view.min.css +11 -0
  263. slm/static/rest_framework/docs/img/favicon.ico +0 -0
  264. slm/static/rest_framework/docs/img/grid.png +0 -0
  265. slm/static/rest_framework/docs/js/api.js +321 -0
  266. slm/static/rest_framework/docs/js/highlight.pack.js +2 -0
  267. slm/static/rest_framework/docs/js/jquery.json-view.min.js +7 -0
  268. slm/static/rest_framework/img/grid.png +0 -0
  269. slm/static/rest_framework/js/ajax-form.js +127 -0
  270. slm/static/rest_framework/js/bootstrap.bundle.min.js +7 -0
  271. slm/static/rest_framework/js/bootstrap.bundle.min.js.map +1 -0
  272. slm/static/rest_framework/js/bootstrap.min.js.map +1 -0
  273. slm/static/rest_framework/js/coreapi-0.1.1.js +2043 -0
  274. slm/static/rest_framework/js/csrf.js +52 -0
  275. slm/static/rest_framework/js/default.js +47 -0
  276. slm/static/rest_framework/js/jquery-3.5.1.min.js +2 -0
  277. slm/static/rest_framework/js/prettify-min.js +28 -0
  278. slm/static/slm/css/admin.css +3 -0
  279. slm/static/slm/css/defines.css +82 -0
  280. slm/static/slm/css/forms.css +1 -0
  281. slm/static/slm/css/style.css +1004 -0
  282. slm/static/slm/img/email-branding.png +0 -0
  283. slm/static/slm/img/favicon.ico +0 -0
  284. slm/static/slm/img/login-bg.jpg +0 -0
  285. slm/static/slm/img/slm-logo.svg +4 -0
  286. slm/static/slm/js/autocomplete.js +341 -0
  287. slm/static/slm/js/enums.js +322 -0
  288. slm/static/slm/js/fileIcons.js +30 -0
  289. slm/static/slm/js/form.js +404 -0
  290. slm/static/slm/js/formWidget.js +23 -0
  291. slm/static/slm/js/persistable.js +33 -0
  292. slm/static/slm/js/slm.js +1028 -0
  293. slm/static/slm/js/time24.js +212 -0
  294. slm/static_templates/slm/css/defines.css +26 -0
  295. slm/static_templates/slm/js/enums.js +28 -0
  296. slm/static_templates/slm/js/fileIcons.js +16 -0
  297. slm/static_templates/slm/js/urls.js +5 -0
  298. slm/templates/account/base.html +20 -0
  299. slm/templates/account/email/base.html +43 -0
  300. slm/templates/account/email/base_message.txt +7 -0
  301. slm/templates/account/email/email_confirmation_message.html +16 -0
  302. slm/templates/account/email/email_confirmation_message.txt +7 -0
  303. slm/templates/account/email/email_confirmation_signup_message.html +1 -0
  304. slm/templates/account/email/email_confirmation_signup_message.txt +1 -0
  305. slm/templates/account/email/email_confirmation_signup_subject.txt +1 -0
  306. slm/templates/account/email/email_confirmation_subject.txt +4 -0
  307. slm/templates/account/email/password_reset_key_message.html +28 -0
  308. slm/templates/account/email/password_reset_key_message.txt +9 -0
  309. slm/templates/account/email/password_reset_key_subject.txt +4 -0
  310. slm/templates/account/email/unknown_account_message.html +25 -0
  311. slm/templates/account/email/unknown_account_message.txt +12 -0
  312. slm/templates/account/email/unknown_account_subject.txt +4 -0
  313. slm/templates/account/login.html +67 -0
  314. slm/templates/account/logout.html +38 -0
  315. slm/templates/account/password_change.html +48 -0
  316. slm/templates/account/password_reset.html +51 -0
  317. slm/templates/account/password_reset_done.html +20 -0
  318. slm/templates/account/password_reset_from_key.html +52 -0
  319. slm/templates/account/password_reset_from_key_done.html +17 -0
  320. slm/templates/admin/base.html +7 -0
  321. slm/templates/messages.html +8 -0
  322. slm/templates/rest_framework/README +16 -0
  323. slm/templates/rest_framework/admin/detail.html +10 -0
  324. slm/templates/rest_framework/admin/dict_value.html +11 -0
  325. slm/templates/rest_framework/admin/list.html +32 -0
  326. slm/templates/rest_framework/admin/list_value.html +11 -0
  327. slm/templates/rest_framework/admin/simple_list_value.html +2 -0
  328. slm/templates/rest_framework/admin.html +282 -0
  329. slm/templates/rest_framework/api.html +3 -0
  330. slm/templates/rest_framework/base.html +334 -0
  331. slm/templates/rest_framework/docs/auth/basic.html +42 -0
  332. slm/templates/rest_framework/docs/auth/session.html +40 -0
  333. slm/templates/rest_framework/docs/auth/token.html +41 -0
  334. slm/templates/rest_framework/docs/document.html +37 -0
  335. slm/templates/rest_framework/docs/error.html +71 -0
  336. slm/templates/rest_framework/docs/index.html +55 -0
  337. slm/templates/rest_framework/docs/interact.html +57 -0
  338. slm/templates/rest_framework/docs/langs/javascript-intro.html +5 -0
  339. slm/templates/rest_framework/docs/langs/javascript.html +15 -0
  340. slm/templates/rest_framework/docs/langs/python-intro.html +3 -0
  341. slm/templates/rest_framework/docs/langs/python.html +13 -0
  342. slm/templates/rest_framework/docs/langs/shell-intro.html +3 -0
  343. slm/templates/rest_framework/docs/langs/shell.html +6 -0
  344. slm/templates/rest_framework/docs/link.html +113 -0
  345. slm/templates/rest_framework/docs/sidebar.html +78 -0
  346. slm/templates/rest_framework/filters/base.html +16 -0
  347. slm/templates/rest_framework/filters/ordering.html +17 -0
  348. slm/templates/rest_framework/filters/search.html +13 -0
  349. slm/templates/rest_framework/horizontal/checkbox.html +23 -0
  350. slm/templates/rest_framework/horizontal/checkbox_multiple.html +32 -0
  351. slm/templates/rest_framework/horizontal/dict_field.html +11 -0
  352. slm/templates/rest_framework/horizontal/fieldset.html +16 -0
  353. slm/templates/rest_framework/horizontal/form.html +6 -0
  354. slm/templates/rest_framework/horizontal/input.html +21 -0
  355. slm/templates/rest_framework/horizontal/list_field.html +11 -0
  356. slm/templates/rest_framework/horizontal/list_fieldset.html +13 -0
  357. slm/templates/rest_framework/horizontal/radio.html +42 -0
  358. slm/templates/rest_framework/horizontal/select.html +36 -0
  359. slm/templates/rest_framework/horizontal/select_multiple.html +38 -0
  360. slm/templates/rest_framework/horizontal/textarea.html +21 -0
  361. slm/templates/rest_framework/inline/checkbox.html +8 -0
  362. slm/templates/rest_framework/inline/checkbox_multiple.html +14 -0
  363. slm/templates/rest_framework/inline/dict_field.html +9 -0
  364. slm/templates/rest_framework/inline/fieldset.html +6 -0
  365. slm/templates/rest_framework/inline/form.html +8 -0
  366. slm/templates/rest_framework/inline/input.html +9 -0
  367. slm/templates/rest_framework/inline/list_field.html +9 -0
  368. slm/templates/rest_framework/inline/list_fieldset.html +3 -0
  369. slm/templates/rest_framework/inline/radio.html +25 -0
  370. slm/templates/rest_framework/inline/select.html +24 -0
  371. slm/templates/rest_framework/inline/select_multiple.html +25 -0
  372. slm/templates/rest_framework/inline/textarea.html +9 -0
  373. slm/templates/rest_framework/login.html +3 -0
  374. slm/templates/rest_framework/login_base.html +65 -0
  375. slm/templates/rest_framework/pagination/numbers.html +47 -0
  376. slm/templates/rest_framework/pagination/previous_and_next.html +21 -0
  377. slm/templates/rest_framework/raw_data_form.html +11 -0
  378. slm/templates/rest_framework/schema.js +3 -0
  379. slm/templates/rest_framework/vertical/checkbox.html +16 -0
  380. slm/templates/rest_framework/vertical/checkbox_multiple.html +30 -0
  381. slm/templates/rest_framework/vertical/dict_field.html +7 -0
  382. slm/templates/rest_framework/vertical/fieldset.html +13 -0
  383. slm/templates/rest_framework/vertical/form.html +6 -0
  384. slm/templates/rest_framework/vertical/input.html +17 -0
  385. slm/templates/rest_framework/vertical/list_field.html +7 -0
  386. slm/templates/rest_framework/vertical/list_fieldset.html +7 -0
  387. slm/templates/rest_framework/vertical/radio.html +40 -0
  388. slm/templates/rest_framework/vertical/select.html +34 -0
  389. slm/templates/rest_framework/vertical/select_multiple.html +31 -0
  390. slm/templates/rest_framework/vertical/textarea.html +17 -0
  391. slm/templates/slm/about.html +21 -0
  392. slm/templates/slm/alerts/alert.html +15 -0
  393. slm/templates/slm/alerts/geodesymlinvalid.html +8 -0
  394. slm/templates/slm/alerts/importalert.html +10 -0
  395. slm/templates/slm/alerts.html +18 -0
  396. slm/templates/slm/auth_menu.html +41 -0
  397. slm/templates/slm/base.html +195 -0
  398. slm/templates/slm/emails/alert_issued.html +31 -0
  399. slm/templates/slm/emails/alert_issued.txt +9 -0
  400. slm/templates/slm/emails/base.html +6 -0
  401. slm/templates/slm/emails/changes_rejected.txt +7 -0
  402. slm/templates/slm/emails/review_requested.txt +7 -0
  403. slm/templates/slm/forms/widgets/auto_complete.html +21 -0
  404. slm/templates/slm/forms/widgets/auto_complete_multiple.html +18 -0
  405. slm/templates/slm/forms/widgets/checkbox_multiple.html +6 -0
  406. slm/templates/slm/forms/widgets/inline_multi.html +1 -0
  407. slm/templates/slm/forms/widgets/splitdatetime.html +14 -0
  408. slm/templates/slm/forms/widgets/time24.html +37 -0
  409. slm/templates/slm/help.html +54 -0
  410. slm/templates/slm/messages.html +13 -0
  411. slm/templates/slm/new_site.html +88 -0
  412. slm/templates/slm/profile.html +57 -0
  413. slm/templates/slm/register.html +40 -0
  414. slm/templates/slm/reports/file_log.html +43 -0
  415. slm/templates/slm/reports/head_log.html +23 -0
  416. slm/templates/slm/reports/head_report.html +55 -0
  417. slm/templates/slm/reports/index_log.html +23 -0
  418. slm/templates/slm/reports/index_report.html +71 -0
  419. slm/templates/slm/station/alert.html +8 -0
  420. slm/templates/slm/station/alerts.html +19 -0
  421. slm/templates/slm/station/base.html +104 -0
  422. slm/templates/slm/station/download.html +87 -0
  423. slm/templates/slm/station/edit.html +283 -0
  424. slm/templates/slm/station/form.html +110 -0
  425. slm/templates/slm/station/log.html +18 -0
  426. slm/templates/slm/station/review.html +461 -0
  427. slm/templates/slm/station/upload.html +295 -0
  428. slm/templates/slm/station/uploads/attachment.html +20 -0
  429. slm/templates/slm/station/uploads/geodesyml.html +1 -0
  430. slm/templates/slm/station/uploads/image.html +27 -0
  431. slm/templates/slm/station/uploads/json.html +0 -0
  432. slm/templates/slm/station/uploads/legacy.html +77 -0
  433. slm/templates/slm/top_nav.html +14 -0
  434. slm/templates/slm/user_activity.html +16 -0
  435. slm/templates/slm/widgets/alert_scroll.html +135 -0
  436. slm/templates/slm/widgets/filelist.html +258 -0
  437. slm/templates/slm/widgets/legend.html +12 -0
  438. slm/templates/slm/widgets/log_scroll.html +88 -0
  439. slm/templates/slm/widgets/stationlist.html +233 -0
  440. slm/templatetags/__init__.py +0 -0
  441. slm/templatetags/jinja2.py +9 -0
  442. slm/templatetags/slm.py +459 -0
  443. slm/urls.py +148 -0
  444. slm/utils.py +299 -0
  445. slm/validators.py +297 -0
  446. slm/views.py +654 -0
  447. slm/widgets.py +134 -0
@@ -0,0 +1,675 @@
1
+ """
2
+ Generates a SINEX_ file from the current published database state.
3
+
4
+ The default antex file used is https://files.igs.org/pub/station/general/igs20.atx.gz
5
+ """
6
+
7
+ import html
8
+ import re
9
+ import typing as t
10
+ import zlib
11
+ from collections import defaultdict
12
+ from datetime import datetime
13
+ from pathlib import Path
14
+
15
+ import requests
16
+ from django.core.management import CommandError
17
+ from django.db.models import Prefetch
18
+ from django.utils.translation import gettext as _
19
+ from django_typer.management import TyperCommand, model_parser_completer
20
+ from typer import Argument, Option
21
+ from typing_extensions import Annotated
22
+
23
+ from slm.defines import ISOCountry
24
+ from slm.models import Network, Site, SiteAntenna, SiteReceiver
25
+ from slm.utils import dddmmss_ss_parts, xyz2llh
26
+
27
+ DEFAULT_ANTEX = "https://files.igs.org/pub/station/general/igs20.atx.gz"
28
+
29
+
30
+ def rec_dd():
31
+ return defaultdict(rec_dd)
32
+
33
+
34
+ def sinex_time(time):
35
+ if time is None:
36
+ return "00:000:00000"
37
+ return (
38
+ f'{time.strftime("%y:%j")}:'
39
+ f"{time.hour * 60 * 60 + time.minute * 60 + time.second:05.0f}"
40
+ )
41
+
42
+
43
+ def date2YYdoy(date):
44
+ if date == "" or "CCYY" in date:
45
+ return 0, 0, 0
46
+
47
+ hour = minute = _sec = int(0)
48
+ m = re.match(
49
+ r"(\d\d\d\d)-(\d\d)-(\d\d)((\s|T)(\d\d):(\d\d)(Z|\d\d.\d\d\d\d\d)?)?", date
50
+ )
51
+ if m:
52
+ year = int(m.group(1))
53
+ mo = int(m.group(2))
54
+ day = int(m.group(3))
55
+ if m.group(4):
56
+ hour = int(m.group(6))
57
+ minute = int(m.group(7))
58
+ if m.group(8):
59
+ if m.group(8) == "Z":
60
+ _sec = 0
61
+ else:
62
+ _sec = float(m.group(9))
63
+
64
+ second = hour * 60 * 60 + minute * 60 + _sec
65
+
66
+ _date = "%4d-%02d-%02d %02d:%02d" % (year, mo, day, hour, minute)
67
+ dateObj = datetime.strptime(_date, "%Y-%m-%d %H:%M")
68
+ _y, _doy = dateObj.strftime("%y %j").split()
69
+
70
+ return int(_y), int(_doy), int(second)
71
+
72
+
73
+ class Command(TyperCommand):
74
+ help = _("Generate the sinex files for each station.")
75
+
76
+ used_antennas: set
77
+ sinex_code: str = ""
78
+ siteAnt: dict
79
+ atx: dict
80
+ sat_phase_center: dict
81
+
82
+ suppressed_base_arguments = {
83
+ *TyperCommand.suppressed_base_arguments,
84
+ "version",
85
+ "pythonpath",
86
+ "settings",
87
+ "skip-checks",
88
+ }
89
+ requires_migrations_checks = False
90
+ requires_system_checks = []
91
+
92
+ def handle(
93
+ self,
94
+ destination: Annotated[
95
+ t.Optional[Path],
96
+ Argument(
97
+ dir_okay=False,
98
+ help=_(
99
+ "The destination to write the sinex file to, if none "
100
+ "provided will print to stdout."
101
+ ),
102
+ ),
103
+ ] = None,
104
+ antex_file: Annotated[
105
+ str, Option(help=_("The antex file to use."))
106
+ ] = DEFAULT_ANTEX,
107
+ include_networks: Annotated[
108
+ t.Optional[t.List[Network]],
109
+ Option(
110
+ **model_parser_completer(
111
+ Network, lookup_field="name", case_insensitive=True
112
+ ),
113
+ help=_("Include non-public sites in the given networks."),
114
+ ),
115
+ ] = None,
116
+ include_former: Annotated[
117
+ bool,
118
+ Option("--include-former", help=_("Include former sites in the list.")),
119
+ ] = False,
120
+ ):
121
+ self.sinex_code = ""
122
+ self.siteAnt = rec_dd()
123
+ self.atx = rec_dd()
124
+ self.sat_phase_center = rec_dd()
125
+
126
+ sites = Site.objects.all().order_by("name")
127
+ sites = sites.public() if include_former else sites.active()
128
+ if include_networks:
129
+ sites |= sites.filter(networks__in=include_networks)
130
+
131
+ sites = sites.distinct()
132
+
133
+ self.used_antennas = set(
134
+ [
135
+ "%-16s%-4s" % (ant[0], ant[1])
136
+ for ant in SiteAntenna.objects.filter(site__in=sites)
137
+ .order_by("antenna_type")
138
+ .values_list("antenna_type__model", "radome_type__model")
139
+ .distinct("antenna_type__model", "radome_type__model")
140
+ ]
141
+ )
142
+
143
+ self.build_antex_index(antex_file)
144
+
145
+ output = self.stdout
146
+ if destination:
147
+ output = open(destination, "w")
148
+
149
+ # write header
150
+ for line in self.header(antex_file):
151
+ output.write(f"{line}\n")
152
+
153
+ # write SITE/ID section
154
+ for line in self.site_ids(sites):
155
+ output.write(f"{line}\n")
156
+
157
+ # write SITE/RECEIVER section
158
+ for line in self.site_receivers(sites):
159
+ output.write(f"{line}\n")
160
+
161
+ # write SITE/ANTENNA section
162
+ for line in self.site_antennas(sites):
163
+ output.write(f"{line}\n")
164
+
165
+ # write GPS/PHASECENTER section
166
+ for line in self.gps_phase_center():
167
+ output.write(f"{line}\n")
168
+
169
+ # write GAL/PHASECENTER section
170
+ for line in self.gal_phase_center():
171
+ output.write(f"{line}\n")
172
+
173
+ # write SITE/ECCENTRICITY
174
+ for line in self.site_eccentricity(sites):
175
+ output.write(f"{line}\n")
176
+
177
+ # write SATELLITE/ID
178
+ for line in self.satellite_ids():
179
+ output.write(f"{line}\n")
180
+
181
+ # write +SATELLITE/PHASE_CENTER
182
+ for line in self.satellite_phase_centers():
183
+ output.write(f"{line}\n")
184
+
185
+ # close out the file
186
+ for line in self.footer():
187
+ output.write(f"{line}\n")
188
+
189
+ if destination:
190
+ output.close()
191
+
192
+ def header(self, antex_file):
193
+ now = datetime.now()
194
+ now_date = "%04d-%02d-%02dT%02d:%02d:%02d" % (
195
+ now.year,
196
+ now.month,
197
+ now.day,
198
+ now.hour,
199
+ now.minute,
200
+ now.second,
201
+ )
202
+ now_year, now_jday, now_seconds = date2YYdoy(now_date)
203
+
204
+ yield (
205
+ "%%=SNX 2.02 IGS %02d:%03d:%05d IGS 00:000:00000 00:000:00000 P "
206
+ "00000 0" % (now_year, now_jday, now_seconds)
207
+ )
208
+ yield "+FILE/REFERENCE"
209
+ yield " DESCRIPTION IGS Central Bureau"
210
+ yield " OUTPUT historical sinex header file"
211
+ yield " CONTACT cb@igs.org"
212
+ yield " SOFTWARE SLM2SNX"
213
+ yield " HARDWARE x86_64 Linux | AWS Cloud"
214
+ yield f" INPUT SiteLog Manager, {self.sinex_code.lower()}.atx"
215
+ yield "-FILE/REFERENCE"
216
+ yield "+FILE/COMMENT"
217
+ yield " This file is generated daily from all current IGS site logs in"
218
+ yield " https://files.igs.org/pub/station/log/"
219
+ yield (
220
+ " Phase center offsets are a function of antenna type, using as "
221
+ "reference"
222
+ )
223
+ yield f' {antex_file.rstrip(".gz")}'
224
+ yield "-FILE/COMMENT"
225
+ yield "+INPUT/ACKNOWLEDGMENTS"
226
+ yield " IGS International GNSS Service"
227
+ yield "-INPUT/ACKNOWLEDGMENTS"
228
+
229
+ def footer(self):
230
+ yield "%ENDSNX"
231
+
232
+ def site_ids(self, sites):
233
+ sites = sites.with_location_fields().with_identification_fields()
234
+ yield "+SITE/ID"
235
+ yield (
236
+ "*CODE PT __DOMES__ T _STATION DESCRIPTION__ _LONGITUDE_ "
237
+ "_LATITUDE__ HEIGHT_"
238
+ )
239
+ for site in sites:
240
+ ctry = html.unescape(
241
+ (
242
+ site.country.short_name
243
+ if isinstance(site.country, ISOCountry)
244
+ else site.country
245
+ )
246
+ )
247
+ llh = xyz2llh(site.xyz.coords)
248
+ location = html.unescape(
249
+ f"{site.city or site.state}"
250
+ f'{"," if site.city or site.state else ""}{ctry}'
251
+ )[:21]
252
+ lat_deg, lat_min, lat_sec = dddmmss_ss_parts(llh[0])
253
+
254
+ if lat_deg is None:
255
+ continue
256
+
257
+ # is sinex longitude 0-360 or -180 to 180?
258
+ lon_deg, lon_min, lon_sec = dddmmss_ss_parts(
259
+ llh[1] if llh[1] > 0 else llh[1] + 360
260
+ )
261
+
262
+ yield (
263
+ f" {site.four_id.lower()} A "
264
+ f"{site.iers_domes_number:>9} P "
265
+ f"{location:<21} {lon_deg:3d} {lon_min:2d} "
266
+ f"{lon_sec:>4.1f} {lat_deg:3d} {lat_min:2d} "
267
+ f"{lat_sec:>4.1f} {llh[2]:>7.1f}"
268
+ )
269
+ yield "-SITE/ID"
270
+
271
+ def site_receivers(self, sites):
272
+ yield "+SITE/RECEIVER"
273
+ yield (
274
+ "*CODE PT SOLN T _DATA START_ __DATA_END__ ___RECEIVER_TYPE____ "
275
+ "_S/N_ _FIRMWARE__"
276
+ )
277
+
278
+ for site in sites.prefetch_related(
279
+ Prefetch(
280
+ "sitereceiver_set",
281
+ queryset=SiteReceiver.objects.published()
282
+ .prefetch_related("receiver_type")
283
+ .order_by("installed"),
284
+ )
285
+ ):
286
+ for receiver in site.sitereceiver_set.all():
287
+ yield (
288
+ f" {site.four_id.lower()} A ---- P "
289
+ f"{sinex_time(receiver.installed):<12.12} "
290
+ f"{sinex_time(receiver.removed):<12.12} "
291
+ f"{receiver.receiver_type.model:<20.20} "
292
+ f"{receiver.serial_number:<5.5} {receiver.firmware:<11.11}"
293
+ )
294
+ yield "-SITE/RECEIVER"
295
+
296
+ def site_antennas(self, sites):
297
+ yield "+SITE/ANTENNA"
298
+ yield (
299
+ "*CODE PT SOLN T _DATA START_ __DATA_END__ ____ANTENNA_TYPE____ "
300
+ "_S/N_ _DAZ"
301
+ )
302
+ for site in sites.prefetch_related(
303
+ Prefetch(
304
+ "siteantenna_set",
305
+ queryset=SiteAntenna.objects.published()
306
+ .prefetch_related("antenna_type", "radome_type")
307
+ .order_by("installed"),
308
+ )
309
+ ):
310
+ for antenna in site.siteantenna_set.all():
311
+ yield (
312
+ f" {site.four_id.lower()} A ---- P "
313
+ f"{sinex_time(antenna.installed):<12.12} "
314
+ f"{sinex_time(antenna.removed):<12.12} "
315
+ f"{antenna.antenna_type.model:<15.15} "
316
+ f"{antenna.radome_type.model:4.4} "
317
+ f"{antenna.serial_number:<5.5} "
318
+ f"{antenna.alignment if antenna.alignment else 0.0:>4.0f}"
319
+ )
320
+ # todo: add antenna offset defaulting to zero if its unknown?
321
+ # seems wrong
322
+ yield "-SITE/ANTENNA"
323
+
324
+ def gps_phase_center(self):
325
+ yield "+SITE/GPS_PHASE_CENTER"
326
+ yield (
327
+ "*ANTENNA_NAME____DOME S_NO_ __UP__ NORTH_ _EAST_ __UP__ NORTH_ "
328
+ "_EAST_ ANT_MODEL_"
329
+ )
330
+ for ant in sorted(self.siteAnt):
331
+ if "G02" in self.siteAnt[ant]:
332
+ yield (
333
+ f' {ant:20} ----- {self.siteAnt[ant]["G01"]["up"]:6.6} '
334
+ f'{self.siteAnt[ant]["G01"]["north"]:6.6} '
335
+ f'{self.siteAnt[ant]["G01"]["east"]:6.6} '
336
+ f'{self.siteAnt[ant]["G02"]["up"]:6.6} '
337
+ f'{self.siteAnt[ant]["G02"]["north"]:6.6} '
338
+ f'{self.siteAnt[ant]["G02"]["east"]:6.6} {self.sinex_code:10.10}'
339
+ )
340
+ else:
341
+ yield (
342
+ f' {ant:20} ----- {self.siteAnt[ant]["G01"]["up"]:6.6} '
343
+ f'{self.siteAnt[ant]["G01"]["north"]:6.6} '
344
+ f'{self.siteAnt[ant]["G01"]["east"]:6.6} ------ ------ ------ '
345
+ f"{self.sinex_code:10.10}"
346
+ )
347
+ yield "-SITE/GPS_PHASE_CENTER"
348
+
349
+ def gal_phase_center(self):
350
+ yield "+SITE/GAL_PHASE_CENTER"
351
+ yield (
352
+ "*ANTENNA_NAME____DOME S_NO_ __UP__ NORTH_ _EAST_ __UP__ NORTH_ "
353
+ "_EAST_ ANT_MODEL_"
354
+ )
355
+ for ant in sorted(self.siteAnt):
356
+ if "E01" in self.siteAnt[ant]:
357
+ _e01 = (
358
+ f'{self.siteAnt[ant]["E01"]["up"]:6.6} '
359
+ f'{self.siteAnt[ant]["E01"]["north"]:6.6} '
360
+ f'{self.siteAnt[ant]["E01"]["east"]:6.6}'
361
+ )
362
+ else:
363
+ _e01 = "------ ------ ------"
364
+ if "E05" in self.siteAnt[ant]:
365
+ _e05 = (
366
+ f'{self.siteAnt[ant]["E05"]["up"]:6.6} '
367
+ f'{self.siteAnt[ant]["E05"]["north"]:6.6} '
368
+ f'{self.siteAnt[ant]["E05"]["east"]:6.6}'
369
+ )
370
+ else:
371
+ _e05 = "------ ------ ------"
372
+ yield f" {ant} ---- {_e01} {_e05} {self.sinex_code:10s}"
373
+
374
+ if "E06" in self.siteAnt[ant]:
375
+ _e06 = (
376
+ f'{self.siteAnt[ant]["E06"]["up"]:6.6} '
377
+ f'{self.siteAnt[ant]["E06"]["north"]:6.6} '
378
+ f'{self.siteAnt[ant]["E06"]["east"]:6.6}'
379
+ )
380
+ else:
381
+ _e06 = "------ ------ ------"
382
+ if "E07" in self.siteAnt[ant]:
383
+ _e07 = (
384
+ f'{self.siteAnt[ant]["E07"]["up"]:6.6} '
385
+ f'{self.siteAnt[ant]["E07"]["north"]:6.6} '
386
+ f'{self.siteAnt[ant]["E07"]["east"]:6.6}'
387
+ )
388
+ else:
389
+ _e07 = "------ ------ ------"
390
+ yield f" {ant} ---- {_e06} {_e07} {self.sinex_code:10s}"
391
+
392
+ if "E08" in self.siteAnt[ant]:
393
+ _e08 = (
394
+ f'{self.siteAnt[ant]["E08"]["up"]:6.6} '
395
+ f'{self.siteAnt[ant]["E08"]["north"]:6.6} '
396
+ f'{self.siteAnt[ant]["E08"]["east"]:6.6}'
397
+ )
398
+ else:
399
+ _e08 = "------ ------ ------"
400
+
401
+ yield f" {ant} ---- {_e08} ------ ------ ------ {self.sinex_code:10s}"
402
+ yield "-SITE/GAL_PHASE_CENTER"
403
+
404
+ def site_eccentricity(self, sites):
405
+ yield "+SITE/ECCENTRICITY"
406
+ yield (
407
+ "*CODE PT SOLN T _DATA START_ __DATA_END__ REF __DX_U__ __DX_N__ "
408
+ "__DX_E__"
409
+ )
410
+ for site in sites.prefetch_related(
411
+ Prefetch(
412
+ "siteantenna_set",
413
+ queryset=SiteAntenna.objects.published().order_by("installed"),
414
+ )
415
+ ):
416
+ for antenna in site.siteantenna_set.all():
417
+ yield (
418
+ f" {site.four_id.lower():4.4} A ---- P "
419
+ f"{sinex_time(antenna.installed):12.12} "
420
+ f"{sinex_time(antenna.removed):12.12} UNE "
421
+ f"{antenna.marker_une[0]:8.4f} "
422
+ f"{antenna.marker_une[1]:8.4f} "
423
+ f"{antenna.marker_une[2]:8.4f}"
424
+ )
425
+ yield "-SITE/ECCENTRICITY"
426
+
427
+ def satellite_ids(self):
428
+ yield "+SATELLITE/ID"
429
+ yield ("*CNNN PN COSPARID_ T _START_DATE_ __END_DATE__ " "____ANTENNA_TYPE____")
430
+ for sat in sorted(self.atx):
431
+ for startDate in self.atx[sat]:
432
+ yield (
433
+ f' {sat:.4s} {self.atx[sat][startDate]["prn"]:.2s} '
434
+ f'{self.atx[sat][startDate]["cospar_id"]:.9s} P '
435
+ f'{startDate:.12s} {self.atx[sat][startDate]["endDate"]:.12s} '
436
+ f'{self.atx[sat][startDate]["name"]:.20s}'
437
+ )
438
+ yield "-SATELLITE/ID"
439
+
440
+ def satellite_phase_centers(self):
441
+ yield "+SATELLITE/PHASE_CENTER"
442
+ yield ("*CNNN F __UP__ NORTH_ _EAST_ F __UP__ NORTH_ _EAST_ " "SINEXCODE_ V M")
443
+ for sat in sorted(self.sat_phase_center):
444
+ if sat.startswith("G"):
445
+ yield (
446
+ f' {sat:4.4} 1 {self.sat_phase_center[sat]["G01"]["up"]:6.6} '
447
+ f'{self.sat_phase_center[sat]["G01"]["north"]:6.6} '
448
+ f'{self.sat_phase_center[sat]["G01"]["east"]:6.6} 2 '
449
+ f'{self.sat_phase_center[sat]["G02"]["up"]:6.6} '
450
+ f'{self.sat_phase_center[sat]["G02"]["north"]:6.6} '
451
+ f'{self.sat_phase_center[sat]["G02"]["east"]:6.6} '
452
+ f"{self.sinex_code:10.10} A E"
453
+ )
454
+ try:
455
+ yield (
456
+ f" {sat:4.4} 5 "
457
+ f'{self.sat_phase_center[sat]["G05"]["up"]:6.6} '
458
+ f'{self.sat_phase_center[sat]["G05"]["north"]:6.6} '
459
+ f'{self.sat_phase_center[sat]["G05"]["east"]:6.6} - ------ '
460
+ f"------ ------ {self.sinex_code:10.10} A E"
461
+ )
462
+ except Exception:
463
+ pass
464
+
465
+ if sat.startswith("R"):
466
+ yield (
467
+ f' {sat:4.4} 1 {self.sat_phase_center[sat]["R01"]["up"]:6.6} '
468
+ f'{self.sat_phase_center[sat]["R01"]["north"]:6.6} '
469
+ f'{self.sat_phase_center[sat]["R01"]["east"]:6.6} 2 '
470
+ f'{self.sat_phase_center[sat]["R02"]["up"]:6.6} '
471
+ f'{self.sat_phase_center[sat]["R02"]["north"]:6.6} '
472
+ f'{self.sat_phase_center[sat]["R02"]["east"]:6.6} '
473
+ f"{self.sinex_code:10.10} A E"
474
+ )
475
+
476
+ if sat.startswith("E"):
477
+ yield (
478
+ f' {sat:4.4} 1 {self.sat_phase_center[sat]["E01"]["up"]:6.6} '
479
+ f'{self.sat_phase_center[sat]["E01"]["north"]:6.6} '
480
+ f'{self.sat_phase_center[sat]["E01"]["east"]:6.6} 5 '
481
+ f'{self.sat_phase_center[sat]["E05"]["up"]:6.6} '
482
+ f'{self.sat_phase_center[sat]["E05"]["north"]:6.6} '
483
+ f'{self.sat_phase_center[sat]["E05"]["east"]:6.6} '
484
+ f"{self.sinex_code:10.10} A E"
485
+ )
486
+ yield (
487
+ f' {sat:4.4} 6 {self.sat_phase_center[sat]["E06"]["up"]:6.6} '
488
+ f'{self.sat_phase_center[sat]["E06"]["north"]:6.6} '
489
+ f'{self.sat_phase_center[sat]["E06"]["east"]:6.6} 7 '
490
+ f'{self.sat_phase_center[sat]["E07"]["up"]:6.6} '
491
+ f'{self.sat_phase_center[sat]["E07"]["north"]:6.6} '
492
+ f'{self.sat_phase_center[sat]["E07"]["east"]:6.6} '
493
+ f"{self.sinex_code:10.10} A E"
494
+ )
495
+ yield (
496
+ f" {sat:4.4} 8 "
497
+ f'{self.sat_phase_center[sat]["E08"]["up"]:6.6} '
498
+ f'{self.sat_phase_center[sat]["E08"]["north"]:6.6} '
499
+ f'{self.sat_phase_center[sat]["E08"]["east"]:6.6} - ------ '
500
+ f"------ ------ {self.sinex_code:10.10} A E"
501
+ )
502
+ yield "-SATELLITE/PHASE_CENTER"
503
+
504
+ def build_antex_index(self, antex_file):
505
+ """
506
+ Streams the antex file from files.igs.org and builds an index off of
507
+ it.
508
+
509
+ :param antex_file: The url to the antex file to use, may be gzipped or
510
+ uncompressed.
511
+ """
512
+
513
+ def process_line(
514
+ line,
515
+ prn=None,
516
+ svn=None,
517
+ name=None,
518
+ cospar_id=None,
519
+ north=None,
520
+ east=None,
521
+ up=None,
522
+ atxStartDate=None,
523
+ atxEndDate=None,
524
+ sat_num=None,
525
+ ):
526
+ if "TYPE / SERIAL NO" in line:
527
+ name = line[0:20].rstrip()
528
+ prn = line[21:23]
529
+ svn = line[40:44]
530
+ cospar_id = line[50:59]
531
+ atxEndDate = "00:000:00000"
532
+
533
+ if "SINEX CODE" in line[60:]:
534
+ self.sinex_code = line[:10]
535
+
536
+ if "VALID FROM" in line:
537
+ year, month, day, hour, minute, second = line[0:60].split()
538
+ yy, doy, sec = date2YYdoy(
539
+ "%04d-%02d-%02d %02d:%02d:%02d"
540
+ % (
541
+ int(year),
542
+ int(month),
543
+ int(day),
544
+ int(hour),
545
+ int(minute),
546
+ int(float(second)),
547
+ )
548
+ )
549
+ atxStartDate = "%02d:%03d:%05d" % (int(yy), int(doy), int(sec))
550
+
551
+ if "VALID UNTIL" in line:
552
+ year, month, day, hour, minute, second = line[0:60].split()
553
+ yy, doy, sec = date2YYdoy(
554
+ "%04d-%02d-%02d %02d:%02d:%02d"
555
+ % (
556
+ int(year),
557
+ int(month),
558
+ int(day),
559
+ int(hour),
560
+ int(minute),
561
+ int(float(second)),
562
+ )
563
+ )
564
+ atxEndDate = "%02d:%03d:%05d" % (int(yy), int(doy), int(sec))
565
+
566
+ if "START OF FREQUENCY" in line[60:]:
567
+ sat_num = line[0:59].split()
568
+
569
+ if "NORTH / EAST / UP" in line[60:]:
570
+ north, east, up = line[0:60].split()
571
+ north = float(north) / 1000
572
+ east = float(east) / 1000
573
+ up = float(up) / 1000
574
+
575
+ if prn.isspace():
576
+ if name in self.used_antennas:
577
+ if north < 0:
578
+ self.siteAnt[name][sat_num[0]]["north"] = re.sub(
579
+ "-0.", "-.", "%6.4f" % north
580
+ )
581
+ else:
582
+ self.siteAnt[name][sat_num[0]]["north"] = str(
583
+ "%6.4f" % north
584
+ )
585
+ if east < 0:
586
+ self.siteAnt[name][sat_num[0]]["east"] = re.sub(
587
+ "-0.", "-.", "%6.4f" % east
588
+ )
589
+ else:
590
+ self.siteAnt[name][sat_num[0]]["east"] = str("%6.4f" % east)
591
+ if up < 0:
592
+ self.siteAnt[name][sat_num[0]]["up"] = re.sub(
593
+ "-0.", "-.", "%6.4f" % up
594
+ )
595
+ else:
596
+ self.siteAnt[name][sat_num[0]]["up"] = str("%6.4f" % up)
597
+
598
+ # self.siteAnt[name][sat_num[0]]["north"] = re.sub("0.", ".", str(north), 1)
599
+ # self.siteAnt[name][sat_num[0]]["east"] = re.sub("0.", ".", str(east), 1)
600
+ # self.siteAnt[name][sat_num[0]]["up"] = re.sub("0.", ".", str(up), 1)
601
+ else:
602
+ # satAnt
603
+ self.atx[svn][atxStartDate]["endDate"] = atxEndDate
604
+ self.atx[svn][atxStartDate]["svn"] = svn
605
+ self.atx[svn][atxStartDate]["prn"] = prn
606
+ self.atx[svn][atxStartDate]["north"] = north
607
+ self.atx[svn][atxStartDate]["east"] = east
608
+ self.atx[svn][atxStartDate]["up"] = up
609
+ self.atx[svn][atxStartDate]["cospar_id"] = cospar_id
610
+ self.atx[svn][atxStartDate]["name"] = name
611
+
612
+ if north < 0:
613
+ self.sat_phase_center[svn][sat_num[0]]["north"] = re.sub(
614
+ "-0.", "-.", "%6.4f" % north
615
+ )
616
+ else:
617
+ self.sat_phase_center[svn][sat_num[0]]["north"] = str(
618
+ "%6.4f" % north
619
+ )
620
+ if east < 0:
621
+ self.sat_phase_center[svn][sat_num[0]]["east"] = re.sub(
622
+ "-0.", "-.", "%6.4f" % east
623
+ )
624
+ else:
625
+ self.sat_phase_center[svn][sat_num[0]]["east"] = str(
626
+ "%6.4f" % east
627
+ )
628
+ if up < 0:
629
+ self.sat_phase_center[svn][sat_num[0]]["up"] = re.sub(
630
+ "-0.", "-.", "%6.4f" % up
631
+ )
632
+ else:
633
+ self.sat_phase_center[svn][sat_num[0]]["up"] = str("%6.4f" % up)
634
+
635
+ if "END OF ANTENNA" in line:
636
+ return []
637
+ return [
638
+ prn,
639
+ svn,
640
+ name,
641
+ cospar_id,
642
+ north,
643
+ east,
644
+ up,
645
+ atxStartDate,
646
+ atxEndDate,
647
+ sat_num,
648
+ ]
649
+
650
+ resp = requests.get(antex_file, stream=True)
651
+ if resp.status_code < 300:
652
+ last = ""
653
+ decomp = None
654
+ if resp.headers["content-type"].endswith("gzip"):
655
+ decomp = zlib.decompressobj(16 + zlib.MAX_WBITS)
656
+
657
+ params = []
658
+ for chunk in resp.iter_content(chunk_size=4096):
659
+ if not chunk:
660
+ if last:
661
+ process_line(last, *params)
662
+ if decomp:
663
+ chunk = decomp.decompress(chunk)
664
+
665
+ chunk = chunk.decode("utf-8")
666
+ lines = chunk.split("\n")
667
+ lines[0] = last + lines[0]
668
+ last = lines[-1]
669
+ for line in lines[0:-1]:
670
+ params = process_line(line, *params)
671
+ else:
672
+ raise CommandError(
673
+ f"Unable to fetch antex file ({antex_file}):"
674
+ f"{resp.status_code} {resp.reason}"
675
+ )