libaditya 0.3.4__py2.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 (131) hide show
  1. libaditya/__init__.py +46 -0
  2. libaditya/_version.py +29 -0
  3. libaditya/calc/__init__.py +9 -0
  4. libaditya/calc/api.py +30 -0
  5. libaditya/calc/avasthas.py +346 -0
  6. libaditya/calc/docs/jaimini-get-arch.md +95 -0
  7. libaditya/calc/hellenistic.py +37 -0
  8. libaditya/calc/jaimini.py +335 -0
  9. libaditya/calc/jaimini_get.py +240 -0
  10. libaditya/calc/kala.py +73 -0
  11. libaditya/calc/panchanga.py +422 -0
  12. libaditya/calc/rashi.py +612 -0
  13. libaditya/calc/returns.py +50 -0
  14. libaditya/calc/swe_functions.py +118 -0
  15. libaditya/calc/varga.py +287 -0
  16. libaditya/calc/vimshottari.py +431 -0
  17. libaditya/cards/__init__.py +5 -0
  18. libaditya/cards/card.py +90 -0
  19. libaditya/cards/cards_constants.py +115 -0
  20. libaditya/cards/cards_of_truth.py +323 -0
  21. libaditya/cards/cot.py +142 -0
  22. libaditya/cards/deck.py +52 -0
  23. libaditya/charts/__init__.py +6 -0
  24. libaditya/charts/api.py +36 -0
  25. libaditya/charts/bodygraph.py +80 -0
  26. libaditya/charts/chart.py +286 -0
  27. libaditya/charts/jaimini.py +83 -0
  28. libaditya/charts/tajika.py +36 -0
  29. libaditya/constants.py +1776 -0
  30. libaditya/draw/__init__.py +20 -0
  31. libaditya/draw/draw_bodygraph.py +489 -0
  32. libaditya/draw/draw_sbc.py +712 -0
  33. libaditya/draw/themes/default-theme.hd +53 -0
  34. libaditya/ephe/ast0/se00010s.se1 +0 -0
  35. libaditya/ephe/seas_00.se1 +0 -0
  36. libaditya/ephe/seas_06.se1 +0 -0
  37. libaditya/ephe/seas_12.se1 +0 -0
  38. libaditya/ephe/seas_18.se1 +0 -0
  39. libaditya/ephe/seas_24.se1 +0 -0
  40. libaditya/ephe/seas_30.se1 +0 -0
  41. libaditya/ephe/seas_36.se1 +0 -0
  42. libaditya/ephe/seas_42.se1 +0 -0
  43. libaditya/ephe/seas_48.se1 +0 -0
  44. libaditya/ephe/seasm06.se1 +0 -0
  45. libaditya/ephe/seasm12.se1 +0 -0
  46. libaditya/ephe/seasm18.se1 +0 -0
  47. libaditya/ephe/seasm24.se1 +0 -0
  48. libaditya/ephe/seasm30.se1 +0 -0
  49. libaditya/ephe/seasm36.se1 +0 -0
  50. libaditya/ephe/seasm42.se1 +0 -0
  51. libaditya/ephe/seasm48.se1 +0 -0
  52. libaditya/ephe/seasm54.se1 +0 -0
  53. libaditya/ephe/sefstars.txt +4245 -0
  54. libaditya/ephe/semo_00.se1 +0 -0
  55. libaditya/ephe/semo_06.se1 +0 -0
  56. libaditya/ephe/semo_12.se1 +0 -0
  57. libaditya/ephe/semo_18.se1 +0 -0
  58. libaditya/ephe/semo_24.se1 +0 -0
  59. libaditya/ephe/semo_30.se1 +0 -0
  60. libaditya/ephe/semo_36.se1 +0 -0
  61. libaditya/ephe/semo_42.se1 +0 -0
  62. libaditya/ephe/semo_48.se1 +0 -0
  63. libaditya/ephe/semom06.se1 +0 -0
  64. libaditya/ephe/semom12.se1 +0 -0
  65. libaditya/ephe/semom18.se1 +0 -0
  66. libaditya/ephe/semom24.se1 +0 -0
  67. libaditya/ephe/semom30.se1 +0 -0
  68. libaditya/ephe/semom36.se1 +0 -0
  69. libaditya/ephe/semom42.se1 +0 -0
  70. libaditya/ephe/semom48.se1 +0 -0
  71. libaditya/ephe/semom54.se1 +0 -0
  72. libaditya/ephe/sepl_00.se1 +0 -0
  73. libaditya/ephe/sepl_06.se1 +0 -0
  74. libaditya/ephe/sepl_12.se1 +0 -0
  75. libaditya/ephe/sepl_18.se1 +0 -0
  76. libaditya/ephe/sepl_24.se1 +0 -0
  77. libaditya/ephe/sepl_30.se1 +0 -0
  78. libaditya/ephe/sepl_36.se1 +0 -0
  79. libaditya/ephe/sepl_42.se1 +0 -0
  80. libaditya/ephe/sepl_48.se1 +0 -0
  81. libaditya/ephe/seplm06.se1 +0 -0
  82. libaditya/ephe/seplm12.se1 +0 -0
  83. libaditya/ephe/seplm18.se1 +0 -0
  84. libaditya/ephe/seplm24.se1 +0 -0
  85. libaditya/ephe/seplm30.se1 +0 -0
  86. libaditya/ephe/seplm36.se1 +0 -0
  87. libaditya/ephe/seplm42.se1 +0 -0
  88. libaditya/ephe/seplm48.se1 +0 -0
  89. libaditya/ephe/seplm54.se1 +0 -0
  90. libaditya/hd/__init__.py +8 -0
  91. libaditya/hd/calc.py +55 -0
  92. libaditya/hd/constants.py +127 -0
  93. libaditya/hd/longitude.py +271 -0
  94. libaditya/objects/__init__.py +19 -0
  95. libaditya/objects/celestial_object.py +206 -0
  96. libaditya/objects/context.py +133 -0
  97. libaditya/objects/cusps.py +259 -0
  98. libaditya/objects/julian_day.py +265 -0
  99. libaditya/objects/location.py +167 -0
  100. libaditya/objects/longitude.py +987 -0
  101. libaditya/objects/nakshatras.py +285 -0
  102. libaditya/objects/planets.py +2059 -0
  103. libaditya/objects/shadbala.py +398 -0
  104. libaditya/objects/signs.py +690 -0
  105. libaditya/objects/swe_functions.py +75 -0
  106. libaditya/print_functions.py +548 -0
  107. libaditya/read.py +665 -0
  108. libaditya/stars/__init__.py +4 -0
  109. libaditya/stars/fixed_star.py +216 -0
  110. libaditya/stars/make_swe_stars.py +407 -0
  111. libaditya/stars/star-sign-boundaries +44 -0
  112. libaditya/stars/stellarium/__init__.py +6 -0
  113. libaditya/stars/stellarium/remote_control/__init__.py +22 -0
  114. libaditya/stars/stellarium/remote_control/location.py +82 -0
  115. libaditya/stars/stellarium/remote_control/locationsearch.py +35 -0
  116. libaditya/stars/stellarium/remote_control/main.py +165 -0
  117. libaditya/stars/stellarium/remote_control/objects.py +63 -0
  118. libaditya/stars/stellarium/remote_control/scripts.py +81 -0
  119. libaditya/stars/stellarium/remote_control/simbad.py +20 -0
  120. libaditya/stars/stellarium/remote_control/stelaction.py +31 -0
  121. libaditya/stars/stellarium/remote_control/stelproperty.py +30 -0
  122. libaditya/stars/stellarium/remote_control/view.py +85 -0
  123. libaditya/stars/stellarium/stellarium.py +92 -0
  124. libaditya/stars/the_stars.py +522 -0
  125. libaditya/stars/utilities.py +539 -0
  126. libaditya/utils.py +431 -0
  127. libaditya/write.py +67 -0
  128. libaditya-0.3.4.dist-info/METADATA +588 -0
  129. libaditya-0.3.4.dist-info/RECORD +131 -0
  130. libaditya-0.3.4.dist-info/WHEEL +5 -0
  131. libaditya-0.3.4.dist-info/licenses/LICENSE +661 -0
@@ -0,0 +1,539 @@
1
+ # This file is part of libaditya.
2
+ #
3
+ # Copyright (c) 2025 Josh Harper <humanhaven@substack.com>
4
+ #
5
+ # libaditya is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU Affero General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # libaditya is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU Affero General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU Affero General Public License
16
+ # along with libaditya. If not, see <https://www.gnu.org/licenses/>.
17
+
18
+ from libaditya import constants as const
19
+
20
+ def read_swe_ids():
21
+ with open(const.stars_file,"r") as infd:
22
+ lines = infd.readlines()
23
+
24
+ ids=[]
25
+ for line in lines:
26
+ if line.startswith("#"):
27
+ continue
28
+ ids.append(line.split(",")[1])
29
+ return ids
30
+
31
+ def parse_simbad_ascii_response(response: str):
32
+ """
33
+ response is the http_response itself
34
+ """
35
+ lines = response.split("\n")
36
+ #import pdb; pdb.set_trace()
37
+ magV = None
38
+ parallax = None
39
+ hipid = "no hip id"
40
+ name = ""
41
+ nomen_name = ",noMen"
42
+ for n,line in enumerate(lines):
43
+ if n > 28:
44
+ # find HIP id so we can return it first as well
45
+ for n in range(28,50):
46
+ if n >= len(lines):
47
+ break
48
+ if "HIP" in lines[n]:
49
+ line = lines[n].split()
50
+ for i,element in enumerate(line):
51
+ if element == "HIP":
52
+ hipid = element+" "+line[i+1]
53
+ if "NAME" in lines[n]:
54
+ line = lines[n].split()
55
+ for i,element in enumerate(line):
56
+ if element == "NAME":
57
+ name = line[i+1]
58
+ break
59
+ match n:
60
+ case 2:
61
+ trad_name = str(line)
62
+ case 5:
63
+ names = line.split(" ")
64
+ # try to guess the ,noMen name
65
+ nomen_name = ","+names[2]+names[3]
66
+ case 7:
67
+ # icrs coordinates
68
+ icrs = line.split(" ")
69
+ ra_hour = icrs[1]
70
+ ra_minute = icrs[2]
71
+ ra_sec = icrs[3]
72
+ dec_degree = icrs[5]
73
+ dec_minute = icrs[6]
74
+ dec_sec = icrs[7]
75
+ case 11:
76
+ pm = line.split(" ")
77
+ pmra = pm[2]
78
+ pmde = pm[3]
79
+ case 13:
80
+ rad_vel = line.split(" ")
81
+ rad_vel = rad_vel[2]
82
+ case 12:
83
+ para = line.split(" ")
84
+ parallax = para[1]
85
+ if "Flux V" in line:
86
+ flux = line.split(" ")
87
+ magV = flux[3]
88
+ if not magV:
89
+ magV = 0
90
+ try:
91
+ return [hipid,name],trad_name,nomen_name,ra_hour,ra_minute,ra_sec,dec_degree,dec_minute,dec_sec,pmra,pmde,rad_vel,parallax,magV
92
+ except:
93
+ return response
94
+
95
+ def swe_make_star(names=[""]) -> str:
96
+ """
97
+ make an entry for ephe/sefstars.txt to add star "name" to that file, and thus to swe
98
+ returns a list [sefstars.txt_entry,simbad_response_str]
99
+ """
100
+ import urllib
101
+ from string import Template
102
+ simbad_query = Template("https://simbad.cds.unistra.fr/simbad/sim-id?Ident=$swe_id&NbIdent=1&Radius=2&Radius.unit=arcmin&submit=submit%20id&output.format=ASCII")
103
+ swe_star_entry = Template("$trad_name,$nomen_name,ICRS,$ra_hour,$ra_minute,$ra_sec,$dec_degree,$dec_minute,$dec_sec,$pmra,$pmde,$rad_vel,$parallax,$magnitude_V")
104
+ if not isinstance(names,list):
105
+ names=[names]
106
+ ret = []
107
+ for name in names:
108
+ name = name.replace(" ","+")
109
+ the_bytes = urllib.request.urlopen(simbad_query.substitute(swe_id=name))
110
+ ascii = the_bytes.read().decode()
111
+ # lines=the_bytes.read().decode().split("\n")
112
+ # for n,line in enumerate(lines):
113
+ # print(n,line)
114
+ # now parse bytes into all the variables needs for swe_star_entry
115
+ response = parse_simbad_ascii_response(ascii)
116
+ try:
117
+ ids,trad_name,nomen_name,ra_hour,ra_minute,ra_sec,dec_degree,dec_minute,dec_sec,pmra,pmde,rad_vel,parallax,magV = response
118
+ except:
119
+ print("Error: \n")
120
+ print(response)
121
+ return
122
+ id_line = f"#0# {nomen_name.replace(",","")}, "
123
+ id_line += str(ids[1]+", "+ids[0]+"\n")
124
+ ret.append(id_line)
125
+ ret.append(f"{nomen_to_long_form(nomen_name)}{nomen_name},ICRS,{ra_hour},{ra_minute},{ra_sec},{dec_degree},{dec_minute},{dec_sec},{pmra},{pmde},{rad_vel},{parallax},{magV}\n")
126
+ return ret, ascii
127
+
128
+
129
+ def swe_write_stars(names=[""],outfile=""):
130
+ """
131
+ take a list of objects ids, names
132
+ write out to a file their entries for ephe/sefstars.txt
133
+
134
+ TODO: update to do multi-line output with each name
135
+ """
136
+ lines=[]
137
+ for name in names:
138
+ returns, ascii=swe_make_star(name)
139
+ # print(f"sws: {returns[0]=} {returns[1]=}")
140
+ lines.append(returns[0])
141
+ lines.append(returns[1])
142
+ # print(f"{lines=}")
143
+ with open(outfile,"a") as fd:
144
+ fd.writelines(lines)
145
+ return
146
+
147
+ def swe_star_to_python(swe_star: str) -> str:
148
+ """
149
+ take a star line from ephe/sefstars.txt and produce a python object that inherits from FixedStar
150
+ this is written in a .py file that can then be loaded, and we can use any of these stars then by name
151
+ e.g., stars.the_stars.Fomalhaut(context)
152
+
153
+ swe_star is like this:
154
+
155
+ #0# swe_id, Common Name, HIP ID
156
+ Galactic Center,SgrA*,ICRS,17,45,40.03599,-29,00,28.1699,-2.755718425, -5.547, 0.0,0.125,999.99, 0, 0
157
+
158
+ (traditional/common) name,(,noMen) nomenclature name, equinox, ra_hour, ra_minute, ra_second, dec_degree, dec_minute, dec_second,
159
+ ra of proper motion, dec of proper motion, radial velocity in km/s, annual parallax in .0001"", magnitude_V
160
+ an example of what this produces:
161
+
162
+ class GalacticCenter(FixedStar): # ,SgrA*
163
+
164
+ def __init__(self, context = EphContext()):
165
+ super().__init__(swe_id = ",SgrA*", context=context)
166
+
167
+ for new stars, this is the template I am trying to use:
168
+
169
+ #0# alfAur, Capella, HIP 24608
170
+ Alpha Auriga,alfAur,ICRS,05,16,41.35871,+45,59,52.7693,75.25,-426.89,29.19,76.20,0.08
171
+
172
+ class AlphaAuriga(FixedStar): # ,alfAur
173
+
174
+ def __init__(self, context = EphContext()):
175
+ super().__init__(swe_id = ",alfAur", context=context, swe_string="Alpha Auriga,alfAur,ICRS,05,16,41.35871,+45,59,52.7693,75.25,-426.89,29.19,76.20,0.08")
176
+ self._other_names = ["Capella", "HIP 24608"]
177
+
178
+ Capella = AlphaAuriga
179
+
180
+ now, TheStars(context)["alfAur"] will return AlphaAuriga()
181
+ but you can also do stars.the_stars.Capella(context)
182
+
183
+ """
184
+ lines=swe_star.split("\n")
185
+ # since swe_star[1] has a \n at the end, lines will have 3 elements, the last being ""
186
+ names = lines[0]
187
+ names_split = names.split(",")
188
+ common_names = []
189
+ hip_name = ""
190
+ # the swe_id, aka ",nomen" name
191
+ id_swe_id = ","+names_split[0].split()[1]
192
+ # dont need the first one anymore
193
+ names_split = names_split[1:]
194
+ for name in names_split:
195
+ name=name.strip()
196
+ if "HIP" in name:
197
+ hip_name = f"{name.strip()}"
198
+ if not "Messier" in names and not name.startswith("VC") and not name.startswith("NGC") and not name.startswith("HR") and not name.startswith("HD"):
199
+ # get all the common names
200
+ common_names.append(f"{name.strip()}")
201
+ other_names = common_names
202
+ if hip_name:
203
+ other_names = common_names + [hip_name]
204
+
205
+ swe_line = lines[1]
206
+ swe_split = lines[1].split(",")
207
+
208
+ long_form_name = swe_split[0].replace(" ","")
209
+ star_swe_id = ","+swe_split[1]
210
+
211
+ if id_swe_id != star_swe_id:
212
+ print(f"Error swe_ids do not match: {id_swe_id} != {star_swe_id}\nLines out of order")
213
+ return
214
+
215
+ other_classes=""
216
+ for common_name in common_names:
217
+ other_classes += f"{common_name.replace(" ","")} = {long_form_name}\n"
218
+ other_classes += "\n\n"
219
+
220
+ if other_names is not None:
221
+ tmp = []
222
+ for name in other_names:
223
+ if name in tmp:
224
+ continue
225
+ if name == "" or name == '""':
226
+ continue
227
+ tmp.append(name.replace("'",""))
228
+ other_names = tmp
229
+
230
+ ret=[]
231
+ ret.append(f"class {long_form_name}(FixedStar): # {id_swe_id}\n")
232
+ ret.append("\n")
233
+ ret.append(f" def __init__(self, context = EphContext()):\n")
234
+ ret.append(f" super().__init__(swe_id = \"{star_swe_id}\", context=context, swe_string=\"{swe_line}\")\n")
235
+ ret.append(f" self._other_names = {other_names}\n\n")
236
+ ret.append(other_classes)
237
+ return "".join(ret)
238
+
239
+ def swe_stars_to_py(infile,outfile):
240
+ """
241
+ take an input
242
+ """
243
+ with open(infile, "r") as infd:
244
+ swe_stars = infd.readlines()
245
+
246
+ with open(outfile, "a") as outfd:
247
+ n = 0
248
+ while n < len(swe_stars):
249
+ # if line is blank
250
+ if not swe_stars[n]:
251
+ n+=1
252
+ continue
253
+ # if line has info for the next line
254
+ if "#" in swe_stars[n] and "#0#" not in swe_stars[n]:
255
+ n+=1
256
+ continue
257
+ star = swe_stars[n]
258
+ n+=1
259
+ if "#0#" in star:
260
+ star += swe_stars[n]
261
+ n+=1
262
+ outfd.write(swe_star_to_python(star))
263
+
264
+ def convert_sefstars_first_pass(infile,outfile):
265
+ """
266
+ convert ephe/sefstars.txt to a different format
267
+ i already manually changed all 2-letter greek abbreviations to 3-letter abbreviations manually
268
+ so that is accounted for in this function
269
+ """
270
+ with open(infile, "r") as infd:
271
+ inlines = infd.readlines()
272
+
273
+ outlines = []
274
+ for inline in inlines:
275
+ if inline.startswith("#"):
276
+ outlines.append(inline)
277
+ continue
278
+ star = inline.split(",")
279
+ trad_name = star[0]
280
+ nomen_name = star[1].replace("-","0")
281
+ star[1] = nomen_name
282
+ long_form_name = nomen_to_long_form(nomen_name)
283
+ star[0]=long_form_name
284
+ outlines.append(f"#0# {nomen_name}, {trad_name}\n")
285
+ outlines.append(",".join(star).strip()+"\n")
286
+
287
+ with open(outfile,"a") as outfd:
288
+ outfd.writelines(outlines)
289
+
290
+
291
+ def nomen_to_long_form(nomen: str):
292
+ """
293
+ turn a nomenclature name into a long form version of itself
294
+ nomenclature names, any of these designations:
295
+ Bayer, Falmsteed, HIP, NGC, HD, HR, M (Messer Object)
296
+ greek is lowercase greek letter, will use upper case in English
297
+ Latin is genitive of Latin constellation name
298
+ e.g., alfTau, Alpha Tauri, α Tauri
299
+ """
300
+ if nomen[0] == ",":
301
+ nomen = nomen[1:]
302
+ if nomen[0].isnumeric():
303
+ # this means it is Flamsteed
304
+ # easiest to do this first
305
+ number=""
306
+ n=0
307
+ while nomen[n].isnumeric():
308
+ number+=nomen[n]
309
+ n+=1
310
+ constellation=""
311
+ while n < len(nomen):
312
+ constellation+=nomen[n]
313
+ n+=1
314
+ return const.star_names_short_to_long["constellations"][constellation]+number
315
+ # check if this is a "special constellation"
316
+ # not really constellations, but fill the same place in the nomen name, so are treated the same for this purpose
317
+ special_constellations = ["VC","HD","HR","HIP","NGC"]
318
+ # doesnt include "M" because that throws off other checks
319
+ special = None
320
+ for constellation in special_constellations:
321
+ number=""
322
+ if constellation in nomen.upper() or (nomen.upper().startswith("M") and "mu." not in nomen):
323
+ # if one of these special tags is here, special will show us that it is
324
+ if nomen.upper().startswith("M"):
325
+ special = "M"
326
+ number = nomen[1:]
327
+ else:
328
+ special = constellation
329
+ # the rest of the string except the "constellation" names
330
+ number = nomen[(len(special)):]
331
+ break
332
+ if number != "":
333
+ return const.star_names_short_to_long["constellations"][special]+f" {number.strip()}"
334
+ if number == "":
335
+ if special == "VC":
336
+ return const.star_names_short_to_long["constellations"][special]
337
+ # now assume it is a Bayer designation
338
+ # some in the original sefstars.txt have a hyphen "-" in the name
339
+ # replace that with 0
340
+ # first three letters are the greek
341
+ greek = nomen[:3]
342
+ # last three are the Latin constellation
343
+ latin = nomen[3:]
344
+ # sometimes there are two stars with the same name basically, one is, e.g., gam01Sgr, the other, gam02Sgr
345
+ # this will be Gamma Sagittarii 1 and Gamma Sagittarii 2
346
+ number = ""
347
+ if latin[:2].isnumeric():
348
+ number = latin[:2]
349
+ latin = latin[2:]
350
+ if not greek.islower():
351
+ return nomen
352
+ if number:
353
+ return const.star_names_short_to_long["greek"][greek]+" "+const.star_names_short_to_long["constellations"][latin]+f" {number}"
354
+ return const.star_names_short_to_long["greek"][greek]+" "+const.star_names_short_to_long["constellations"][latin]
355
+
356
+ # convert_sefstars_second_pass
357
+ def swe_consolidate_sefstars(infile,outfile):
358
+ """
359
+ right now, sefstars.txt has some stars line that are the same, e.g.,:
360
+ Alpha Tauri,alfTau,ICRS,04,35,55.23907,+16,30,33.4885,63.45,-188.94,54.398,48.94,0.86
361
+ appears three times
362
+ the info line above it, starting with #0#, is different in each case
363
+ so this function consolidates all of the names in the info line above just one entrance for each star/object
364
+ consolidates what it reads from infile, writes to outfile
365
+ """
366
+ with open(infile,"r") as infd:
367
+ lines = infd.readlines()
368
+
369
+ # two-passes
370
+ # one to put all info into dictionary
371
+ # but i want all actual comment lines to remain more or less in the same place
372
+ # the second read pass will also write out simultaneously
373
+
374
+ # populate the dictionary of star information
375
+ # stars_info = {
376
+ # "noMen": [swe_line,other_name,other_name,...]
377
+ # }
378
+ stars_info = swe_populate_stars(lines)
379
+
380
+ with open(infile,"r") as infd:
381
+ lines = infd.readlines()
382
+
383
+ written = []
384
+ outlines = []
385
+
386
+ n=0
387
+ for n in range(0,len(lines)):
388
+ line=lines[n]
389
+ if line.startswith("#") and not line.startswith("#0#"):
390
+ outlines.append(line)
391
+ continue
392
+ if line.startswith("#0#"):
393
+ info_line = line
394
+ n+=1
395
+ star_line = lines[n]
396
+ # ready for the next loop
397
+ n+=1
398
+ # info_line = "#0# alfTau, Alpha Taurus, Aldebaran, HIP 21421"
399
+ info_line = info_line.split(",")
400
+ # indicator and nomen are in the first element of info_line
401
+ # we want the other name, so remove the nomen name from the list
402
+ nomen = info_line[0].split()[1]
403
+ if nomen in written:
404
+ continue
405
+ written.append(nomen)
406
+ info_to_write = f"#0# {nomen}"
407
+ # stars_info[nomen] is a list [swe_star_entry,other_name,other_name,...]
408
+ swe_star = stars_info[nomen][0]
409
+ for n in range(1,len(stars_info[nomen])):
410
+ info_to_write += f", {stars_info[nomen][n]}"
411
+ outlines.append(info_to_write)
412
+ outlines.append(swe_star)
413
+ with open(outfile,"a") as outfd:
414
+ outfd.writelines(outlines)
415
+
416
+
417
+ def swe_populate_stars(lines):
418
+ """
419
+ lines are the lines that have been read from sefstars.txt
420
+
421
+ populate the dictionary of star information
422
+ stars_info = {
423
+ "noMen": [swe_line,other_name,other_name,...]
424
+ }
425
+ """
426
+ stars_info = {}
427
+
428
+ n=0
429
+ for n in range(0,len(lines)):
430
+ line=lines[n]
431
+ if line.startswith("#") and not line.startswith("#0#"):
432
+ # a comment only
433
+ n+=1
434
+ continue
435
+ if line.startswith("#0#"):
436
+ info_line = line
437
+ n+=1
438
+ star_line = lines[n]
439
+ # ready for the next loop
440
+ n+=1
441
+ # info_line = "#0# alfTau, Alpha Taurus, Aldebaran, HIP 21421"
442
+ info_line = info_line.split(",")
443
+ # indicator and nomen are in the first element of info_line
444
+ # we want the other name, so remove the nomen name from the list
445
+ nomen = info_line[0].split()[1]
446
+ info_line = info_line[1:]
447
+ if nomen in stars_info.keys():
448
+ # this entry is already here, so we only want to add new names if there are any
449
+ for name in info_line:
450
+ if name in stars_info[nomen]:
451
+ continue
452
+ else:
453
+ stars_info[nomen].append(name.strip())
454
+ continue
455
+ entry=[]
456
+ if nomen != star_line.split(",")[1]:
457
+ print(f"Error, lines out of order...\n{info_line=}\n{star_line=}")
458
+ entry.append(star_line)
459
+ for name in info_line:
460
+ entry.append(name.strip())
461
+ stars_info[nomen] = entry
462
+ return stars_info
463
+
464
+ def swe_write_multiline_sefstars(infile,outfile):
465
+ """
466
+ take a sefstars.txt that has two entries per star, i.e.,:
467
+ #0# noMen, other_name, other_name, ...
468
+ long_form_nomen,nomen,frame,ra_hour,...
469
+
470
+ and output a sefstars.txt that has the same info line as well as one entry for each name
471
+ #0# noMen, other_name, other_name, ...
472
+ nomen,nomen,frame,ra_hour,...
473
+ long_form_nomen,nomen,frame,ra_hour,...
474
+ other_name,nomen,frame,ra_hour,...
475
+
476
+
477
+ #0# alfCMa, Alpha Canis Major, Sirius, HIP 32349
478
+ alfCMa,alfCMa,ICRS,06,45,08.91728,-16,42,58.0171,-546.01,-1223.07,-5.50,379.21,-1.46
479
+ Alpha Canis Majoris,alfCMa,ICRS,06,45,08.91728,-16,42,58.0171,-546.01,-1223.07,-5.50,379.21,-1.46
480
+ Alpha Canis Major,alfCMa,ICRS,06,45,08.91728,-16,42,58.0171,-546.01,-1223.07,-5.50,379.21,-1.46
481
+ Sirius,alfCMa,ICRS,06,45,08.91728,-16,42,58.0171,-546.01,-1223.07,-5.50,379.21,-1.46
482
+ HIP 32349,alfCMa,ICRS,06,45,08.91728,-16,42,58.0171,-546.01,-1223.07,-5.50,379.21,-1.46
483
+ ...
484
+
485
+ will try to make the first other_name be the "traditional" name if its has one
486
+ this may not always work exactly as hoped
487
+ """
488
+ with open(infile) as infd:
489
+ inlines=infd.readlines()
490
+
491
+
492
+ # need to perserve comments and order, so we will do this with a manual n-based while loop
493
+
494
+ # so we need to write out the original info line
495
+ # we need to write out the original swe_string
496
+ # all in the following order
497
+ # as well as the same swe_string with these as the first parameter
498
+ # (traditional name) if this exists, it should be first
499
+ # long_form_nomen ; this is a written form of the nomen name, e.g., Alpha Canis Majoris
500
+ # other_name, etc.
501
+
502
+ # this is where we put the lines to write out
503
+ outlines = []
504
+
505
+ # we go through the inlines manually so that we preserve the order of comments, etc.
506
+ n=0
507
+ for n in range(0,len(inlines)):
508
+ line=inlines[n]
509
+ if line.startswith("#") and not line.startswith("#0#"):
510
+ # a comment only
511
+ outlines.append(line)
512
+ n+=1
513
+ continue
514
+ if line.startswith("#0#"):
515
+ info_line = line
516
+ outlines.append(info_line)
517
+ n+=1
518
+ star_line_long_form_nomen = inlines[n]
519
+ # ready for the next loop
520
+ n+=1
521
+
522
+ # now append the correct lines into outlines
523
+ star_line_split = star_line_long_form_nomen.split(",")[1:]
524
+ nomen = star_line_split[0]
525
+ # append nomen line first, then long_form, the eac name on the info line in order
526
+ outlines.append(",".join([nomen]+star_line_split))
527
+ outlines.append(star_line_long_form_nomen)
528
+ for name in info_line.split(",")[1:]:
529
+ # sometimes there are no more names, which appears as either empty string or a string of spaces, which .strip() converts to empty string, essentially
530
+ if name.strip() == "":
531
+ continue
532
+ if name.strip() == "no hip id":
533
+ continue
534
+ outlines.append(",".join([name.strip()]+star_line_split))
535
+
536
+ with open(outfile,"a") as outfd:
537
+ outfd.writelines(outlines)
538
+
539
+ return 0