def decide_puurvaviddha(p0, p1, target_anga, kaala): (d0_angas, d1_angas) = get_2_day_interval_boundary_angas( kaala=kaala, anga_type=target_anga.get_type(), p0=p0, p1=p1) kaala = d0_angas.interval.name prev_anga = target_anga - 1 next_anga = target_anga + 1 if d0_angas.start >= target_anga or d0_angas.end >= target_anga: fday = 0 elif d1_angas.start == target_anga or d1_angas.end == target_anga: fday = 0 + 1 else: # This means that the correct anga did not # touch the kaala on either day! if d0_angas.end == prev_anga and d1_angas.start == next_anga: # d_offset = {'sunrise': 0, 'aparaahna': 1, 'moonrise': 0, 'madhyaahna': 1, 'sunset': 1}[kaala] d_offset = 0 if kaala in ['sunrise', 'moonrise'] else 1 # Need to assign a day to the festival here # since the anga did not touch kaala on either day # BUT ONLY IF YESTERDAY WASN'T ALREADY ASSIGNED, # THIS BEING PURVAVIDDHA # Perhaps just need better checking of # conditions instead of this fix fday = 0 + d_offset else: # Expected example: (25, 25), (25, 25), 26 # logging.debug("puurvaviddha: %s, %s, %s - Not assigning a festival this day. Likely the next then.", str(d0_angas.to_tuple()), str(d1_angas.to_tuple()), str(target_anga.index)) fday = None return FestivalDecision.from_details( boundary_angas_list=[d0_angas, d1_angas], fday=fday, panchaangas=[p0, p1])
def decide_paraviddha(p0, p1, target_anga, kaala): (d0_angas, d1_angas) = get_2_day_interval_boundary_angas( kaala=kaala, anga_type=target_anga.get_type(), p0=p0, p1=p1) prev_anga = target_anga - 1 next_anga = target_anga + 1 if (d0_angas.end == target_anga and d1_angas.end == target_anga) or ( d1_angas.start == target_anga and d1_angas.end == target_anga): # Incident at kaala on two consecutive days; so take second fday = 1 elif d0_angas.start == target_anga and d0_angas.end == target_anga: # Incident only on day 1, maybe just touching day 2 fday = 0 elif d0_angas.end == target_anga: fday = 0 elif d1_angas.start == target_anga: fday = 0 elif d0_angas.start == target_anga and d0_angas.end == next_anga: if d0_angas.interval.name in ['aparaahna']: fday = 0 else: # Example when this branch is active: 2019 'madhurakavi AzhvAr tirunakSattiram': sidereal_solar_month 1, nakshatra 14 paraviddha praatah. # Instead of setting fday = 0 - 1 , we set it to None - since we only care about deciding between p0 and p1. Assignments to the previous day will have happened in the previous invocation (deciding between p(-1) and p0.) fday = None elif d0_angas.end == prev_anga and d1_angas.start == next_anga: fday = 0 else: fday = None # Expected example: (19, 19), (19, 20), 20 # logging.debug("paraviddha: %s, %s, %s - Not assigning a festival this day. Likely checking on the wrong day pair.", str(d0_angas.to_tuple()), str(d1_angas.to_tuple()), str(target_anga.index)) return FestivalDecision.from_details( boundary_angas_list=[d0_angas, d1_angas], fday=fday, panchaangas=[p0, p1])
def decide_paraviddha(p0, p1, target_anga, kaala): (d0_angas, d1_angas) = get_2_day_interval_boundary_angas( kaala=kaala, anga_type=target_anga.get_type(), p0=p0, p1=p1) prev_anga = target_anga - 1 next_anga = target_anga + 1 if (d0_angas.end == target_anga and d1_angas.end == target_anga) or ( d1_angas.start == target_anga and d1_angas.end == target_anga): # Incident at kaala on two consecutive days; so take second fday = 1 elif d0_angas.start == target_anga and d0_angas.end == target_anga: # Incident only on day 1, maybe just touching day 2 fday = 0 elif d0_angas.end == target_anga: fday = 0 elif d1_angas.start == target_anga: fday = 0 elif d0_angas.start == target_anga and d0_angas.end == next_anga: if d0_angas.interval.name in ['aparaahna', 'aparaahna_muhuurta']: fday = 0 else: fday = 0 - 1 elif d0_angas.end == prev_anga and d1_angas.start == next_anga: fday = 0 else: fday = None # Expected example: (19, 19), (19, 20), 20 logging.debug( "paraviddha: %s, %s, %s - Not assigning a festival this day. Likely checking on the wrong day pair.", str(d0_angas.to_tuple()), str(d1_angas.to_tuple()), str(target_anga.index)) return fday
def assign_shasthi_vratam(self): if 'SaSThI-vratam' not in self.rules_collection.name_to_rule: return for d in range( self.panchaanga.duration_prior_padding, self.panchaanga.duration + self.panchaanga.duration_prior_padding): day_panchaanga = self.daily_panchaangas[d] # # SHASHTHI Vratam # Check only for Adhika maasa here... festival_name = 'SaSThI-vratam' if day_panchaanga.lunar_month_sunrise.index == 8: festival_name = 'skanda' + festival_name elif day_panchaanga.lunar_month_sunrise.index == 4: festival_name = 'kumAra-' + festival_name elif day_panchaanga.lunar_month_sunrise.index == 6: festival_name = 'SaSThIdEvI-' + festival_name elif day_panchaanga.lunar_month_sunrise.index == 9: festival_name = 'subrahmaNya-' + festival_name if day_panchaanga.sunrise_day_angas.tithi_at_sunrise.index == 5 or day_panchaanga.sunrise_day_angas.tithi_at_sunrise.index == 6: (d0_angas, d1_angas) = get_2_day_interval_boundary_angas( kaala="madhyaahna", anga_type=AngaType.TITHI, p0=day_panchaanga, p1=self.daily_panchaangas[d + 1]) if d0_angas.start.index == 6 or d0_angas.end.index == 6: if festival_name in self.panchaanga.festival_id_to_days: # Check if yesterday was assigned already # to this puurvaviddha festival! if self.daily_panchaangas[ d - 1].date not in self.panchaanga.festival_id_to_days[ festival_name]: self.panchaanga.add_festival( fest_id=festival_name, date=day_panchaanga.date) else: self.panchaanga.add_festival(fest_id=festival_name, date=day_panchaanga.date) elif d1_angas.start.index == 6 or d1_angas.end.index == 6: self.panchaanga.add_festival( fest_id=festival_name, date=self.daily_panchaangas[d + 1].date) else: # This means that the correct anga did not # touch the kaala on either day! # sys.stderr.write('Could not assign puurvaviddha day for %s!\ # Please check for unusual cases.\n' % festival_name) if d1_angas.start.index == 6 + 1 or d1_angas.end.index == 6 + 1: # Need to assign a day to the festival here # since the anga did not touch kaala on either day # BUT ONLY IF YESTERDAY WASN'T ALREADY ASSIGNED, # THIS BEING PURVAVIDDHA # Perhaps just need better checking of # conditions instead of this fix if festival_name in self.panchaanga.festival_id_to_days: if self.daily_panchaangas[ d - 1].date not in self.panchaanga.festival_id_to_days[ festival_name]: self.panchaanga.add_festival( fest_id=festival_name, date=day_panchaanga.date) else: self.panchaanga.add_festival( fest_id=festival_name, date=day_panchaanga.date)
def decide_aparaahna_vyaapti(p0, p1, target_anga, ayanaamsha_id, kaala): (d0_angas, d1_angas) = get_2_day_interval_boundary_angas( kaala=kaala, anga_type=target_anga.get_type(), p0=p0, p1=p1) if kaala not in ['अपराह्णः']: raise ValueError(kaala) prev_anga = target_anga - 1 next_anga = target_anga + 1 p, q, r = prev_anga, target_anga, next_anga # short-hand # Combinations # (p:0, q:1, r:2) # <a> r ? ? ?: None # <a> ? ? q q: d + 1 # <b> ? p ? ?: d + 1 # <e> p q q r: vyApti # <h> q q ? r: d # <i> ? q r ?: d # <j> q r ? ?: d if d0_angas.start > q: # One of the cases covered here: Anga might have been between end of previous day's interval and beginning of this day's interval. Then we would have: r r for d1_angas. Could potentially lead to a missed festival. # logging.debug("vyaapti: %s, %s, %s - Not assigning a festival this day. Likely checking on the wrong day pair.", str(d0_angas.to_tuple()), str(d1_angas.to_tuple()), str(target_anga.index)) return None # Easy cases where d0 has greater vyApti elif d0_angas.end > q: # d0_angas.start <= q fday = 0 elif d0_angas.start == q and d0_angas.end == q and d1_angas.end > q: fday = 0 elif d0_angas.end == q and d1_angas.start > q: fday = 0 # Easy cases where d1 has greater vyApti elif d1_angas.start == q and d1_angas.end == q: # d0_angas <= q # This is a potential tie-breaker where both d1 and d2 are fully covered. fday = 1 elif d0_angas.end < q and d1_angas.start >= q: # Covers p p r r, [p, p, q, r], [p, p, q, q] fday = 1 elif d0_angas.end == q and d1_angas.start == q: # The <e> p q q r: vyApti case anga_span = zodiac.AngaSpanFinder( ayanaamsha_id=ayanaamsha_id, anga_type=target_anga.get_type()).find( jd1=d0_angas.interval.jd_start, jd2=d1_angas.interval.jd_end, target_anga_id=target_anga) vyapti_0 = max(d0_angas.interval.jd_end - anga_span.jd_start, 0) vyapti_1 = max(anga_span.jd_end - d1_angas.interval.jd_start, 0) if vyapti_1 > vyapti_0: fday = 0 + 1 else: fday = 0 else: # logging.info("vyaapti: %s, %s, %s. Some weird case", str(d0_angas.to_tuple()), str(d1_angas.to_tuple()), str(target_anga.index)) fday = None return FestivalDecision.from_details( boundary_angas_list=[d0_angas, d1_angas], fday=fday, panchaangas=[p0, p1])
def assign_shraaddha_tithi(self, debug_shraaddha_tithi=False): tithi_days = [{z: [] for z in range(0, 32)} for _x in range(13)] lunar_tithi_days = {} daily_panchaangas = self.daily_panchaangas def _assign(self, fday, tithi): if daily_panchaangas[ fday].shraaddha_tithi == [] or daily_panchaangas[ fday].shraaddha_tithi == [tithi]: daily_panchaangas[fday].shraaddha_tithi = [tithi] else: daily_panchaangas[fday].shraaddha_tithi.append(tithi) if daily_panchaangas[fday - 1].shraaddha_tithi.count(tithi) == 1: daily_panchaangas[fday - 1].shraaddha_tithi.remove(tithi) for d in range(self.panchaanga.duration_prior_padding, self.panchaanga.duration + 1): [y, m, dt, t] = time.jd_to_utc_gregorian(self.panchaanga.jd_start + d - 1).to_date_fractional_hour_tuple() (d0_angas, d1_angas) = get_2_day_interval_boundary_angas( kaala="aparaahna", anga_type=AngaType.TITHI, p0=self.daily_panchaangas[d], p1=self.daily_panchaangas[d + 1]) angam_start = d0_angas.start next_anga = angam_start + 1 nnext_anga = next_anga + 1 # Calc vyaaptis t_start_d, t_end_d = interval.get_interval( daily_panchaangas[d].jd_sunrise, daily_panchaangas[d].jd_sunset, 3, 5).to_tuple() span_1 = t_end_d - t_start_d span_2 = 0 for tithi_span in daily_panchaangas[ d].sunrise_day_angas.tithis_with_ends: tithi_end = tithi_span.jd_end if tithi_end is None: pass elif t_start_d < tithi_end < t_end_d: span_1 = tithi_end - t_start_d span_2 = t_end_d - tithi_end t_start_d1, t_end_d1 = interval.get_interval( daily_panchaangas[d + 1].jd_sunrise, daily_panchaangas[d + 1].jd_sunset, 3, 5).to_tuple() vyapti_3 = t_end_d1 - t_start_d1 for tithi_span in daily_panchaangas[ d + 1].sunrise_day_angas.tithis_with_ends: tithi_end = tithi_span.jd_end if tithi_end is None: pass elif t_start_d1 < tithi_end < t_end_d1: vyapti_3 = tithi_end - t_start_d1 # Combinations # <a> 1 1 1 1 - d + 1: 1 # <b> 1 1 2 2 - d: 1 # <f> 1 1 2 3 - d: 1, d+1: 2 # <e> 1 1 1 2 - d, or vyApti (just in case next day aparaahna is slightly longer): 1 # <d> 1 1 3 3 - d: 1, 2 # <h> 1 2 3 3 - d: 2 # <c> 1 2 2 2 - d + 1: 2 # <g> 1 2 2 3 - vyApti: 2 fday = -1 reason = '?' # if sunrise_day_angas[1] == angam_start: # logging.debug('Pre-emptively assign %2d to %3d, can be removed tomorrow if need be.' % (angam_start, d)) # _assign(self, d, angam_start) if d1_angas.end == angam_start: # <a> # Full aparaahnas on both days, so second day fday = d + 1 s_tithi = angam_start reason = '%2d incident on consecutive days; paraviddhA' % s_tithi.index elif (d0_angas.end == angam_start) and (d1_angas.start == next_anga): # <b>/<f> fday = d s_tithi = d0_angas.start reason = '%2d not incident on %3d' % (s_tithi.index, d + 1) if d1_angas.end == nnext_anga: # <f> if debug_shraaddha_tithi: logging.debug('%03d [%4d-%02d-%02d]: %s' % ( d, y, m, dt, 'Need to assign %2d to %3d as it is present only at start of aparAhna tomorrow!)' % (next_anga.index, d + 1))) _assign(self, d + 1, next_anga) elif d1_angas.start == angam_start: # <e> if span_1 > vyapti_3: # Most likely fday = d s_tithi = d1_angas.start reason = '%2d has more vyApti on day %3d (%f ghatikAs; full?) compared to day %3d (%f ghatikAs)' % ( s_tithi.index, d, span_1 * 60, d + 1, vyapti_3 * 60) else: fday = d + 1 s_tithi = d1_angas.start reason = '%2d has more vyApti on day %3d (%f ghatikAs) compared to day %3d (%f ghatikAs) --- unusual!' % ( s_tithi.index, d + 1, vyapti_3 * 60, d, span_1 * 60) elif d1_angas.start == nnext_anga: # <d>/<h> if d0_angas.end == next_anga: # <h> fday = d s_tithi = d0_angas.end reason = '%2d has some vyApti on day %3d; not incident on day %3d at all' % ( s_tithi.index, d, d + 1) else: # <d> s_tithi = angam_start fday = d reason = '%2d is incident fully at aparAhna today (%3d), and not incident tomorrow (%3d)!' % ( s_tithi.index, d, d + 1) # Need to check vyApti of next_anga in sAyaMkAla: if it's nearly entire sAyaMkAla ie 5-59-30 or more! if debug_shraaddha_tithi: logging.debug('%03d [%4d-%02d-%02d]: %s' % ( d, y, m, dt, '%2d not incident at aparAhna on either day (%3d/%3d); picking second day %3d!' % (next_anga, d, d + 1, d + 1))) _assign(self, d + 1, next_anga) # logging.debug(reason) elif d0_angas.end == d1_angas.start == d1_angas.end == next_anga: # <c> s_tithi = next_anga fday = d + 1 reason = '%2d has more vyApti on %3d (full) compared to %3d (part)' % ( s_tithi.index, d + 1, d) elif d0_angas.end == d1_angas.start == next_anga: # <g> s_tithi = d1_angas.start if span_2 > vyapti_3: # Most likely fday = d reason = '%2d has more vyApti on day %3d (%f ghatikAs) compared to day %3d (%f ghatikAs)' % ( s_tithi.index, d, span_2 * 60, d + 1, vyapti_3 * 60) else: fday = d + 1 reason = '%2d has more vyApti on day %3d (%f ghatikAs) compared to day %3d (%f ghatikAs)' % ( s_tithi.index, d + 1, vyapti_3 * 60, d, span_2 * 60 ) # Examine for greater vyApti else: logging.error('Should not reach here ever! %s %s', d0_angas.to_tuple(), d1_angas.to_tuple()) reason = '?' if debug_shraaddha_tithi: logging.debug( '%03d [%4d-%02d-%02d]: Assigning tithi %2d to %3d (%s).' % (d, y, m, dt, s_tithi.index, fday, reason)) _assign(self, fday, s_tithi) if debug_shraaddha_tithi: logging.debug(self.panchaanga.shraaddha_tithi) for z in set([x.lunar_month_sunrise for x in self.daily_panchaangas]): lunar_tithi_days[z] = {} for d in range(self.panchaanga.duration_prior_padding, self.panchaanga.duration + 1): for t in daily_panchaangas[d].shraaddha_tithi: lunar_tithi_days[daily_panchaangas[d].lunar_month_sunrise][ t.index] = d # Following this primary assignment, we must now "clean" for Sankranti, and repetitions # If there are two tithis, take second. However, if the second has sankrAnti dushtam, take # first. If both have sankrAnti dushtam, take second. for d in range(self.panchaanga.duration_prior_padding, self.panchaanga.duration + 1): if daily_panchaangas[d].shraaddha_tithi != []: if daily_panchaangas[ d].solar_sidereal_date_sunset.month_transition is not None: if debug_shraaddha_tithi: logging.debug( (d, daily_panchaangas[d]. solar_sidereal_date_sunset.month_transition)) aparaahna_start, aparaahna_end = interval.get_interval( daily_panchaangas[d].jd_sunrise, daily_panchaangas[d].jd_sunset, 3, 5).to_tuple() m1 = daily_panchaangas[ d - 1].solar_sidereal_date_sunset.month # Previous month m2 = daily_panchaangas[ d].solar_sidereal_date_sunset.month # Current month if aparaahna_start < daily_panchaangas[ d].solar_sidereal_date_sunset.month_transition < aparaahna_end: if debug_shraaddha_tithi: logging.debug( 'Sankranti in aparaahna! Assigning to both months!' ) assert daily_panchaangas[ d].solar_sidereal_date_sunset.day == 1 for t in daily_panchaangas[d].shraaddha_tithi: # Assigning to both months --- should get eliminated because of a second occurrence tithi_days[m1][t.index].extend([d, '*']) tithi_days[m2][t.index].extend([d, '*']) if daily_panchaangas[ d].solar_sidereal_date_sunset.month_transition < aparaahna_start: if debug_shraaddha_tithi: logging.debug('Sankranti before aparaahna!') assert daily_panchaangas[ d].solar_sidereal_date_sunset.day == 1 for t in daily_panchaangas[d].shraaddha_tithi: tithi_days[m2][t.index].extend([d, '*']) if aparaahna_end < daily_panchaangas[ d].solar_sidereal_date_sunset.month_transition: if debug_shraaddha_tithi: logging.debug('Sankranti after aparaahna!') # Depending on whether sankranti is before or after sunset, m2 may or may not be equal to m1 # In any case, we wish to assign this tithi to the previous month, where it really occurs. for t in daily_panchaangas[d].shraaddha_tithi: tithi_days[m1][t.index].extend([d, '*']) else: for t in daily_panchaangas[d].shraaddha_tithi: tithi_days[daily_panchaangas[d]. solar_sidereal_date_sunset.month][ t.index].append(d) # We have now assigned all tithis. Now, remove duplicates based on the above-mentioned rules. # TODO: This is not the best way to clean. Need to examine one month at a time. for m in range(1, 13): for t in range(1, 31): if len(tithi_days[m][t]) == 1: continue elif len(tithi_days[m][t]) == 2: if tithi_days[m][t][1] == '*': # Only one tithi available! if debug_shraaddha_tithi: logging.debug( 'Only one %2d tithi in month %2d, on day %3d, despite sankrAnti dushtam!' % (t, m, tithi_days[m][t][0])) del tithi_days[m][t][1] tithi_days[m][t][0] = '%d::%d' % (tithi_days[m][t][0], m) if debug_shraaddha_tithi: logging.debug('Note %s' % str(tithi_days[m][t])) else: daily_panchaangas[ tithi_days[m][t][0]].shraaddha_tithi = [ Anga.get_cached( index=0, anga_type_id=AngaType.TITHI.name) ] # Shunya if debug_shraaddha_tithi: logging.debug('Removed %d' % tithi_days[m][t][0]) del tithi_days[m][t][0] if debug_shraaddha_tithi: logging.debug( 'Two %2d tithis in month %2d: retaining second on %2d!' % (t, m, tithi_days[m][t][0])) elif len(tithi_days[m][t]) == 3: if debug_shraaddha_tithi: logging.debug('Two %2d tithis in month %2d: %s' % (t, m, str(tithi_days[m][t]))) if tithi_days[m][t][1] == '*': daily_panchaangas[ tithi_days[m][t][0]].shraaddha_tithi = [ Anga.get_cached( index=0, anga_type_id=AngaType.TITHI.name) ] # Shunya if debug_shraaddha_tithi: logging.debug('Removed %d' % tithi_days[m][t][0]) del tithi_days[m][t][:2] elif tithi_days[m][t][2] == '*': daily_panchaangas[ tithi_days[m][t][1]].shraaddha_tithi = [ Anga.get_cached( index=0, anga_type_id=AngaType.TITHI.name) ] # Shunya if debug_shraaddha_tithi: logging.debug('Removed %d' % tithi_days[m][t][1]) del tithi_days[m][t][1:] if debug_shraaddha_tithi: logging.debug(' Retaining non-dushta: %s' % (str(tithi_days[m][t]))) elif len(tithi_days[m][t]) == 4: if debug_shraaddha_tithi: logging.debug( 'Two dushta %2d tithis in month %2d: %s' % (t, m, str(tithi_days[m][t]))) daily_panchaangas[tithi_days[m][t][0]].shraaddha_tithi = [ Anga.get_cached(index=0, anga_type_id=AngaType.TITHI.name) ] # Shunya if debug_shraaddha_tithi: logging.debug('Removed %d' % tithi_days[m][t][0]) tithi_days[m][t][3] = str(m) del tithi_days[m][t][:2] if debug_shraaddha_tithi: logging.debug(' Retaining: %s' % (str(tithi_days[m][t]))) tithi_days[m][t][0] = '%d::%d' % (tithi_days[m][t][0], m) if debug_shraaddha_tithi: logging.debug('Note %s' % str(tithi_days[m][t])) elif len(tithi_days[m][t]) == 0: logging.warning( 'Rare issue. No tithi %d in this solar month (%d). Therefore use lunar tithi.' % (t, m)) # सौरमासे तिथ्यलाभे चान्द्रमानेन कारयेत् # tithi_days[m][t] = lunar_tithi_days[m][t] else: logging.error( 'Something weird. len(tithi_days[m][t]) is not in 1:4!! : %s (m=%d, t=%d)', str(tithi_days[m][t]), m, t) if debug_shraaddha_tithi: logging.debug(tithi_days)