akupunktuhr

Chrona Acupuncture Calculator
git clone git://arztpraxis-lohmann.de/akupunktuhr
Log | Files | Refs | README | LICENSE

akupunktuhr (9128B)


      1 #!/usr/bin/env python
      2 # coding=utf-8
      3 #
      4 # © 2023 Christoph Lohmann <20h@r-36.net>
      5 #
      6 # This file is published under the terms of the GPLv3.
      7 #
      8 
      9 import os
     10 import sys
     11 import getopt
     12 from datetime import datetime
     13 import ephem
     14 import lunarcalendar
     15 import calendar
     16 import math
     17 
     18 # Yuan Source Point.
     19 yuan_point = {
     20 	"lung": "LU-9",
     21 	"large intestine": "LI-4",
     22 	"stomach": "ST-42",
     23 	"spleen": "SP-3",
     24 	"heart": "HT-7",
     25 	"small intestine": "SI-4",
     26 	"urinary bladder": "BL-64",
     27 	"kidney": "KI-3",
     28 	"pericardium": "PC-7",
     29 	"triple burner": "TB-4",
     30 	"gall bladder": "GB-40",
     31 	"liver": "LR-3"
     32 }
     33 
     34 # Sedation Luo Point.
     35 sedation_luo_point = {
     36 	"lung": "BL-58",
     37 	"large intestine": "KI-4",
     38 	"stomach": "PC-6",
     39 	"spleen": "TB-5",
     40 	"heart": "GB-37",
     41 	"small intestine": "LR-5",
     42 	"urinary bladder": "LU-7",
     43 	"kidney": "LI-6",
     44 	"pericardium": "ST-40",
     45 	"triple burner": "SP-4",
     46 	"gall bladder": "HT-5",
     47 	"liver": "SI-7"
     48 }
     49 
     50 # Tonification Luo Point.
     51 tonification_luo_point = {
     52 	"lung": "LI-6",
     53 	"large intestine": "LU-7",
     54 	"stomach": "SP-4",
     55 	"spleen": "ST-40",
     56 	"heart": "SI-6",
     57 	"small intestine": "HT-5",
     58 	"urinary bladder": "KI-4",
     59 	"kidney": "BL-58",
     60 	"pericardium": "TB-5",
     61 	"triple burner": "PC-6",
     62 	"gall bladder": "LR-5",
     63 	"liver": "GB-37"
     64 }
     65 
     66 # Tonification point of meridian.
     67 tonification_point = {
     68 	"lung": "LU-8",
     69 	"large intestine": "LI-1",
     70 	"stomach": "ST-36",
     71 	"spleen": "SP-3",
     72 	"heart": "HT-8",
     73 	"small intestine": "SI-5",
     74 	"urinary bladder": "BL-66",
     75 	"kidney": "KI-10",
     76 	"pericardium": "PC-8",
     77 	"triple burner": "TB-6",
     78 	"gall bladder": "GB-41",
     79 	"liver": "LR-1"
     80 }
     81 
     82 # Element ancient point of meridian.
     83 element_point = {
     84 	"lung": "LU-11",
     85 	"large intestine": "LI-3",
     86 	"stomach": "ST-36",
     87 	"spleen": "SP-2",
     88 	"heart": "HT-8",
     89 	"small intestine": "SI-8",
     90 	"urinary bladder": "BL-67",
     91 	"kidney": "KI-7",
     92 	"pericardium": "PC-7",
     93 	"triple burner": "TB-2",
     94 	"gall bladder": "GB-43",
     95 	"liver": "LR-3"
     96 }
     97 
     98 # Acupuncture clock.
     99 na_zi_fa = {
    100 	"03:00-05:00": "lung",
    101 	"05:00-07:00": "large intestine",
    102 	"07:00-09:00": "stomach",
    103 	"09:00-11:00": "spleen",
    104 	"11:00-13:00": "heart",
    105 	"13:00-15:00": "small intestine",
    106 	"15:00-17:00": "urinary bladder",
    107 	"17:00-18:00": "kidney",
    108 	"19:00-21:00": "pericardium",
    109 	"21:00-23:00": "triple burner",
    110 	"23:00-01:00": "gall bladder",
    111 	"01:00-03:00": "liver"
    112 }
    113 
    114 def print_na_zi_fa(meridian):
    115 	print("Na Zi Fa: %s; element: %s; ton: %s; yuan: %s; ton luo: %s; sed luo: %s;" % (
    116 		meridian,
    117 		element_point[meridian],
    118 		tonification_point[meridian],
    119 		yuan_point[meridian],
    120 		tonification_luo_point[meridian],
    121 		sedation_luo_point[meridian]
    122 	))
    123 
    124 na_jia_fa = [
    125 ["GB-38", "SI-2", "ST-36", "LI-3, SI-4", "TB-1", "GB-38", "SI-2",
    126  "ST-36", "LI-3", "TB-1"],
    127 ["LR-2", "HT-3", "SP-3, LR-3", "PC-3", "KI-7", "LR-2", "HT-3", "SP-3",
    128  "PC-3", "KI-7"],
    129 ["SI-8", "ST-43, GB-40", "TB-10", "BL-60, BL-67", "", "SI-8", "ST-43",
    130  "TB-10", "BL-67, BL-60", ""],
    131 ["HT-7, PC-7, KI-3", "PC-5", "LU-8, LU-11", "", "LR-8", "HT-7", "PC-5",
    132  "LU-11, LU-8", "", "LR-8"],
    133 ["TB-6", "LI-5, LI-1", "", "GB-34, GB-43", "", "TB-6", "LI-1, LI-5", "",
    134  "GB-43, GB-34", ""],
    135 ["SP-5, SP-1", "", "KI-10, KI-2", "", "PC-7", "SP-1, SP-5", "",
    136  "KI-2, KI-10", "", "PC-7"],
    137 ["", "BL-40, BL-66", "", "TB-3, SI-4", "ST-45", "", "BL-66, BL-60", "",
    138  "SI-3, TB-4, BL-64, TB-3", "ST-45"],
    139 ["LU-5, LU-10", "", "PC-8, LR-3", "HT-9", "", "LU-10, LU-5", "",
    140  "LR-3, LU-9, PC-8", "HT-9", ""],
    141 ["", "TB-2, GB-41", "SI-1", "ST-41", "LI-2", "", "GB-41, LI-4, TB-2",
    142  "SI-1", "ST-41", "LI-2"],
    143 ["PC-9, KI-3", "LR-1", "HT-4", "SP-2", "", "KI-3, SP-3, PC-9",
    144  "LR-1", "HT-4", "SP-2", ""],
    145 ["GB-44", "SI-5", "ST-44", "LI-11", "BL-65, ST-42", "GB-44",
    146  "SI-5", "ST-44", "LI-11", "BL-65"],
    147 ["LR-4", "HT-8", "SP-9", "LU-9, HT-7", "KI-1", "LR-4", "HT-8",
    148  "SP-9", "LU-9", "KI-1"]
    149 ]
    150 
    151 def print_na_jia_fa(daystem, hourbranch):
    152 	print("Na Jia Fa: %s" % (
    153 		na_jia_fa[hourbranch-1][daystem-1]
    154 	))
    155 
    156 fei_teng_ba_fa_complex = [
    157 ["SP-4", "SP-4", "GB-41", "TB-5", "SP-4", "SP-4", "SP-4", "GB-41",
    158  "TB-5", "SP-4"],
    159 ["BL-62", "KI-6", "LU-7", "SI-3", "BL-62", "KI-6", "LU-7", "SI-3",
    160  "BL-62"],
    161 ["PC-6", "GB-41", "TB-5", "SP-4", "SP-4", "PC-6", "GB-41", "TB-5",
    162  "SP-4", "SP-5"],
    163 ["KI-6", "LU-7", "SI-3", "BL-62", "BL-62", "KI-6", "LU-7", "SI-3",
    164  "BL-62", "BL-62"],
    165 ["GB-41", "TB-5", "SP-4", "SP-4", "PC-6", "GB-41", "TB-5", "SP-4",
    166  "SP-4", "PC-6"],
    167 ["LU-7", "SI-3", "BL-62", "BL-62", "KI-6", "LU-7", "SI-3", "BL-62",
    168  "BL-62", "KI-6"],
    169 ["TB-5", "SP-4", "SP-4", "PC-6", "GB-41", "TB-5", "SP-4", "SP-4", "PC-6",
    170  "GB-41"],
    171 ["SI-3", "BL-62", "BL-62", "KI-6", "LU-7", "SI-3", "BL-62", "BL-62",
    172  "KI-6", "LU-7"],
    173 ["SP-4", "SP-4", "PC-6", "GB-41", "TB-5", "SP-4", "SP-4", "PC-6",
    174  "GB-41", "TB-5"],
    175 ["BL-62", "BL-62", "KI-6", "LU-7", "SI-3", "BL-62", "BL-62", "KI-6",
    176  "LU-7", "SI-3"],
    177 ["SP-4", "PC-6", "GB-41", "TB-5", "SP-4", "SP-4", "PC-6", "GB-41",
    178  "TB-5", "SP-4"],
    179 ["BL-62", "KI-6", "LU-7", "SI-3", "BL-62", "BL-62", "KI-6", "LU-7",
    180  "SI-3", "BL-62"]
    181 ]
    182 
    183 fei_teng_ba_fa_simple = \
    184 ["SP-4", "BL-62", "PC-6", "KI-6", "GB-41", "LU-7", "TB-5", "SI-3",
    185  "SP-4", "BL-62"]
    186 
    187 extraordinary_connectors = {
    188 	"TB-5": "GB-41",
    189 	"GB-41": "TB-5",
    190 	"SP-4": "PC-6",
    191 	"PC-6": "SP-4",
    192 	"KI-6": "LU-7",
    193 	"LU-7": "KI-6",
    194 	"BL-62": "SI-3",
    195 	"SI-3": "BL-62"
    196 }
    197 
    198 extraordinary_name = {
    199 	"TB-5": "Yang Wei Mai",
    200 	"GB-41": "Dai Mai",
    201 	"SP-4": "Chong Mai",
    202 	"PC-6": "Yin Wei Mai",
    203 	"KI-6": "Yin Qiao Mai",
    204 	"LU-7": "Control Vessel",
    205 	"SI-3": "Governor Vessel",
    206 	"BL-62": "Yang Qiao Mai"
    207 }
    208 
    209 def print_fei_teng_ba(hourstem, hourbranch):
    210 	ex0 = fei_teng_ba_fa_simple[hourstem-1]
    211 	ex0name = extraordinary_name[ex0]
    212 	ex1 = extraordinary_connectors[ex0]
    213 	ex1name = extraordinary_name[ex1]
    214 	print("Fei Teng Ba Fa simple: %s (%s) -> %s (%s)" % (
    215 		ex0, ex0name, ex1, ex1name
    216 	))
    217 
    218 	ex0 = fei_teng_ba_fa_complex[hourbranch-1][hourstem-1]
    219 	ex0name = extraordinary_name[ex0]
    220 	ex1 = extraordinary_connectors[ex0]
    221 	ex1name = extraordinary_name[ex1]
    222 	print("Fei Teng Ba Fa complex: %s (%s) -> %s (%s)" % (
    223 		ex0, ex0name, ex1, ex1name
    224 	))
    225 
    226 def solar_datetime(latitude, longitude):
    227 	now = datetime.now()
    228 	observer = ephem.Observer()
    229 	observer.date = now
    230 	observer.lat = latitude
    231 	observer.lon = longitude
    232 	sun = ephem.Sun()
    233 	sun.compute(observer)
    234 	hour_angle = observer.sidereal_time() - sun.ra
    235 	solarhours = ephem.hours(hour_angle + ephem.hours('12:00')).norm
    236 	(shour, sminute, ssecond) = str(solarhours).split(":", 2)
    237 	(ssecond, smillisecond) = ssecond.split(".", 1)
    238 	return now.replace(hour=int(shour), minute=int(sminute),
    239 		    second=int(ssecond), microsecond=int(smillisecond)*10000)
    240 
    241 def solar2lunar(solardt):
    242 	lunar = lunarcalendar.Lunar.from_date(solardt)
    243 	return solardt.replace(year=lunar.year, month=lunar.month,
    244 			day=lunar.day)
    245 
    246 def usage(app):
    247 	app = os.path.basename(app)
    248 	print("usage: %s [-h] [-p lat,lon]" % (app), file=sys.stderr)
    249 	sys.exit(1)
    250 
    251 def main(args):
    252 	try:
    253 		opts, largs = getopt.getopt(args[1:], "p:h")
    254 	except getopt.GetoptError as err:
    255 		print(str(err))
    256 		usage(args[0])
    257 
    258 	latitude = 50.8358334
    259 	longitude = 12.6975988
    260 	
    261 	for o, a in opts:
    262 		if o == "-h":
    263 			usage(args[0])
    264 		elif o == "-p":
    265 			(lats, lons) = a.split(",", 1)
    266 			latitude = float(lats)
    267 			longitude = float(lons)
    268 		else:
    269 			assert False, "unhandled option"
    270 
    271 	now = datetime.now()
    272 	utcnow = datetime.utcnow()
    273 
    274 	for timeframe in na_zi_fa.keys():
    275 		(beginstr, endstr) = timeframe.split("-", 1)
    276 		begindt = now.replace(minute=0, hour=int(beginstr.split(":", 1)[0]))
    277 		enddt = now.replace(minute=0, hour=int(endstr.split(":", 1)[0]))
    278 		if now.hour > 23:
    279 			enddt = enddt.replace(day=now.day+1)
    280 		if now > begindt and now < enddt:
    281 			print_na_zi_fa(na_zi_fa[timeframe])
    282 			break
    283 
    284 	solardt = solar_datetime(latitude, longitude)
    285 	lunardt = solar2lunar(solardt)
    286 
    287 	remainder = (lunardt.year - 3) % 60
    288 	yearstem = round(remainder / 10)
    289 	yearbranch = round(remainder / 12)
    290 
    291 	if yearbranch == 1 or yearbranch == 6:
    292 		monthstem1 = 3
    293 	elif yearbranch == 2 or yearbranch == 7:
    294 		monthstem1 = 5
    295 	elif yearbranch == 3 or yearbranch == 8:
    296 		monthstem1 = 7
    297 	elif yearbranch == 4 or yearbranch == 9:
    298 		monthstem1 = 9
    299 	elif yearbranch == 5 or yearbranch == 10:
    300 		monthstem1 = 1
    301 	monthstem = lunardt.month + monthstem1
    302 	if monthstem > 10:
    303 		monthstem = monthstem - 10
    304 	monthbranch = lunardt.month + 3
    305 	if monthbranch > 12:
    306 		monthbranch = monthbranch - 12
    307 
    308 	lunar0 = lunarcalendar.Lunar(solardt.year, 1, 1)
    309 	lunar0d = lunar0.to_date()
    310 	lunaryearday = (solardt.date() - lunar0d).days
    311 	daystem = lunaryearday % 10
    312 	if daystem == 0:
    313 		daystem = 10
    314 	daybranch = lunaryearday % 12
    315 	if daybranch == 0:
    316 		daybranch = 12
    317 
    318 	if daystem == 1 or daystem == 6:
    319 		hourstem1 = 1
    320 	elif daystem == 2 or daystem == 7:
    321 		hourstem1 = 3
    322 	elif daystem == 3 or daystem == 8:
    323 		hourstem1 = 5
    324 	elif daystem == 4 or daystem == 9:
    325 		hourstem1 = 7
    326 	elif daystem == 5 or daystem == 10:
    327 		hourstem1 = 9
    328 	doublehours = int((lunardt.hour - (lunardt.hour % 2)) / 2)
    329 	hourstem = hourstem1 + doublehours + 1
    330 	if hourstem > 10:
    331 		hourstem = hourstem - 10
    332 	hourbranch = doublehours + 1
    333 	if hourbranch > 12:
    334 		hourbranch = hourbranch - 12
    335 	print_fei_teng_ba(hourstem, hourbranch)
    336 	print_na_jia_fa(daystem, hourbranch)
    337 
    338 	return 0
    339 
    340 if __name__ == "__main__":
    341 	sys.exit(main(sys.argv))
    342