Longitude মানে zodiac-এর zero point থেকে ecliptic বরাবর angular distance। সমস্যাটি হলো—zero point কোনটি? Vernal equinox-কে ০° মেষ ধরলে সায়ন বা tropical longitude; কোনো নির্বাচিত sidereal reference ধরে স্থির রাশিচক্র নির্মাণ করলে নিরয়ণ বা sidereal longitude।
দুটি zodiac reference
সায়ন বা tropical zodiac
সায়ন রাশিচক্রের ০° মেষ হলো date-এর vernal equinox point। পৃথিবীর equatorial orientation ও precession-এর কারণে এই reference stellar background-এর তুলনায় সরতে থাকে। ঋতু, equinox এবং solstice-এর সঙ্গে tropical zodiac-এর সরাসরি সম্পর্ক রয়েছে।
নিরয়ণ বা sidereal zodiac
নিরয়ণ রাশিচক্র stellar reference-এর তুলনায় একটি নির্বাচিত zero point ধরে। কিন্তু “sidereal” বললেই একটি একক universal zero পাওয়া যায় না। Lahiri, Raman, Fagan/Bradley, Krishnamurti বা traditional Sūrya-Siddhānta profile—প্রতিটির reference ও model আলাদা হতে পারে।
| বৈশিষ্ট্য | সায়ন | নিরয়ণ |
|---|---|---|
| ০° মেষ | Vernal equinox of date | Selected sidereal reference |
| ঋতুর সঙ্গে সম্পর্ক | Direct | ক্রমে সরে যায় |
| তারার সঙ্গে সম্পর্ক | Precession-এর কারণে পরিবর্তিত | নির্বাচিত model-এ fixed/defined |
| Panchanga ব্যবহার | Physical ephemeris ও seasonal reference | রাশি, নক্ষত্র, যোগ, সংক্রান্তি, sidereal lagna |
অয়নাংশ কী?
Ayanāṃśa হলো নির্বাচিত epoch/date-এ tropical longitude এবং sidereal longitude-এর angular difference। Swiss Ephemeris documentation-এর convention অনুযায়ী:
A = λtropical − λsidereal
অর্থাৎ বর্তমান যুগে সাধারণ positive ayanāṃśa convention-এ tropical longitude থেকে ayanāṃśa বাদ দিলে sidereal longitude পাওয়া যায়। তবে library বা historical text অন্য sign convention ব্যবহার করতে পারে; documentation না দেখে sign অনুমান করবেন না।
Ayanāṃśa সময়ের সঙ্গে পরিবর্তিত হয়। কিন্তু সেই পরিবর্তনকে একটি সর্বযুগে অপরিবর্তিত modern constant rate ধরে extrapolate করাও যথেষ্ট নয়। Traditional model, modern precession model এবং selected sidereal definition আলাদা profile হিসেবে রাখতে হবে।
Conversion formula ও normalization
λnirāyaṇa = normalize(λsāyana − A)
λsāyana = normalize(λnirāyaṇa + A)
normalize(x) = x modulo 360°, range 0° ≤ x < 360°
উদাহরণ: tropical longitude ৫° মেষ এবং ayanāṃśa ২৪° হলে sidereal result negative হয়। Normalize করার পরে সেটি ১১° মীন। শুধু subtraction করে −১৯° print করলে coordinate mathematically equivalent হলেও zodiac label ভুল হবে।
static double Normalize360(double value)
{
double result = value % 360.0;
if (result < 0.0) result += 360.0;
return result;
}
static double ToSidereal(double tropical, double ayanamsa)
{
return Normalize360(tropical - ayanamsa);
}
একাধিক ayanāṃśa profile কেন?
Sidereal zero কোথায় স্থাপন করা হবে, কোন epoch-এ তার value কত এবং precession কীভাবে propagate হবে—এই সিদ্ধান্তে বিভিন্ন school-এর পার্থক্য রয়েছে। তাই “নিরয়ণ longitude” label একা অসম্পূর্ণ। অন্তত profile name ও value-of-date প্রকাশ করতে হবে।
| Profile | প্রকৃতি | Project-এ সম্ভাব্য ব্যবহার |
|---|---|---|
| Sūrya-Siddhānta traditional | Classical/traditional motion model | ঐতিহ্যগত পঞ্জিকা ও research trace |
| Lahiri | Swiss sidereal mode-এর নির্দিষ্ট profile | Modern Drik comparison, sidereal lagna/chart |
| Tropical | Ayanāṃśa subtraction নেই | Modern physical ephemeris ও seasonal coordinates |
| User-selected research profile | Explicit alternate sidereal mode | Comparison only; default silently বদলাবে না |
Swiss Ephemeris-এ Lahiri ছাড়াও বহু sidereal mode রয়েছে। একই library ব্যবহার করলেই তাই একই sidereal result নিশ্চিত হয় না—swe_set_sid_mode() কোন mode-এ ডাকা হয়েছে এবং calculation flags-এ sidereal flag আছে কি না, দুটোই জানা দরকার।
Sūrya-Siddhānta profile: ৫৪″ এবং ৪৯৯ খ্রিস্টাব্দ
Kyoto Pancanga 3.14-এর implementation note অনুযায়ী তাদের Sūrya-Siddhānta profile-এ দুই longitude-এর difference ৪৯৯ খ্রিস্টাব্দে শূন্য এবং ayanāṃśa rate বছরে ৫৪ arcsecond হিসেবে ব্যবহৃত। একই note আধুনিক rate আনুমানিক ৫০.২৯ arcsecond/year বলে এবং এজন্য traditional output modern method-এর থেকে কিছুটা আলাদা হবে বলে সতর্ক করে।
ঐ profile-এর একটি সরল explanatory approximation:
ASS ≈ (yearFraction − 499) × 54″ ÷ 3600
এটি Kyoto implementation profile বোঝানোর formula—সব manuscript, সব interpretation বা সমস্ত historical span-এর universal modern-precession equation নয়। Production result-এর জন্য port-করা source code-এর epoch, calendar, year fraction, sign ও cyclic treatment হুবহু অনুসরণ করুন।
কোন calculation-এ কোন longitude?
| Calculation | প্রয়োজনীয় coordinate | Ayanāṃśa sensitivity |
|---|---|---|
| বাংলা সৌর রাশি ও সংক্রান্তি | Selected nirāyaṇa Sun | হ্যাঁ—boundary time বদলায় |
| নক্ষত্র | Nirāyaṇa Moon | হ্যাঁ—segment ও end time বদলায় |
| যোগ | Nirāyaṇa Sun + Moon | হ্যাঁ—দুই longitude-এ A প্রয়োগ |
| তিথি | Moon − Sun angular separation | একই A হলে cancel করে |
| করণ | Half-tithi separation | একই A হলে cancel করে |
| Sidereal lagna/rāśi chart | Tropical geometry → selected nirāyaṇa longitude | হ্যাঁ—rāśi/degree বদলায় |
| Sunrise ও sunset | Physical apparent/equatorial geometry | না—event-এ নয় |
| Moonrise ও moonset | Topocentric apparent geometry | না—event-এ নয় |
| Eclipse contact ও visibility | Physical Sun–Moon geometry | না—display label আলাদা হতে পারে |
| Equinox ও solstice | Tropical seasonal reference | Sidereal ayanāṃśa প্রযোজ্য নয় |
তিথিতে ayanāṃśa cancel করে, যোগে করে না কেন?
ধরি tropical Sun longitude S, tropical Moon longitude M এবং ayanāṃśa A। Sidereal values:
S′ = S − A
M′ = M − A
তিথির angular separation
M′ − S′ = (M − A) − (S − A) = M − S
একই instant ও একই ayanāṃśa দুই body-তে প্রয়োগ করলে difference অপরিবর্তিত। তাই modern engine-এ তিথির জন্য tropical বা একই-profile sidereal longitude—দুটির angular difference একই হওয়া উচিত।
যোগের sum
M′ + S′ = M + S − 2A
এখানে ayanāṃśa cancel করে না; দ্বিগুণভাবে sum-এ প্রবেশ করে। তাই যোগের ক্ষেত্রে tropical sum নিয়ে সরাসরি ২৭ ভাগ করলে ভুল হবে। Selected nirāyaṇa Sun ও Moon অথবা equivalent tropicalSum − 2A ব্যবহার করতে হবে।
Nuance: Traditional Sūrya-Siddhānta ও modern Swiss engine-এর Sun/Moon নিজস্ব orbital model আলাদা হলে তিথির result-ও আলাদা হতে পারে। “A cancel করে” মানে শুধু common frame rotation-এর প্রভাব cancel—planetary-model difference নয়।
Hybrid engine architecture
এই project-এ traditional এবং modern calculation পাশাপাশি থাকায় প্রতিটি result-এর provenance প্রকাশ করা দরকার। Recommended mapping:
| Output group | Engine | Coordinate profile |
|---|---|---|
| Traditional Bengali date/Saṅkrānti | Sūrya-Siddhānta + selected star fit | Traditional nirāyaṇa |
| Traditional tithi/nakṣatra/yoga/karaṇa | Sūrya-Siddhānta classical profile | Engine-native traditional frame |
| Sunrise/set, moonrise/set, eclipse | Swiss Ephemeris | Physical apparent/tropical geometry |
| Modern sidereal lagna/chart | Swiss Ephemeris | Lahiri—explicit |
| Research comparison | Both engines | Each profile named; no silent conversion |
Traditional Saṅkrānti এবং Swiss Lahiri Saṅkrānti দুটিই “nirāyaṇa Sun at 0° Meṣa” বলতে পারে, কিন্তু তাদের ayanāṃśa/precession ও solar model আলাদা। তাই difference-কে শুধু engine accuracy হিসেবে ব্যাখ্যা করলে ভুল হবে; coordinate profile difference-ও result-এর অংশ।
Swiss Ephemeris: C# workflow
Swiss Ephemeris-এ sidereal mode আগে নির্বাচন করতে হয় এবং calculation flags-এ sidereal flag দিতে হয়। নিচের code wrapper-specific নামের illustration; আপনার C# binding-এর exact constants ব্যবহার করুন।
public sealed class LongitudeResult
{
public double JulianDayUt { get; set; }
public double TropicalLongitude { get; set; }
public double SiderealLongitude { get; set; }
public double Ayanamsa { get; set; }
public string AyanamsaProfile { get; set; }
}
public LongitudeResult CalculateLahiriLongitude(
double julianDayUt,
int body)
{
lock (SwissEphemerisSync)
{
swiss.swe_set_sid_mode(SE_SIDM_LAHIRI, 0.0, 0.0);
double[] tropical = new double[6];
double[] sidereal = new double[6];
string error = String.Empty;
int baseFlags = SEFLG_SWIEPH | SEFLG_SPEED;
swiss.swe_calc_ut(julianDayUt, body, baseFlags,
tropical, ref error);
swiss.swe_calc_ut(julianDayUt, body,
baseFlags | SEFLG_SIDEREAL,
sidereal, ref error);
LongitudeResult result = new LongitudeResult();
result.JulianDayUt = julianDayUt;
result.TropicalLongitude = Normalize360(tropical[0]);
result.SiderealLongitude = Normalize360(sidereal[0]);
result.Ayanamsa = Normalize360(tropical[0] - sidereal[0]);
result.AyanamsaProfile = "Swiss Ephemeris Lahiri";
return result;
}
}
swe_set_sid_mode library-global state হলে concurrent requests-এ lock বা isolated context প্রয়োজন। একটি request Lahiri এবং আরেকটি অন্য sidereal mode চাইলে shared mutable mode leak করতে পারে। Cache key-তেও mode ও ephemeris version রাখতে হবে।
Result metadata
public sealed class CoordinateMetadata
{
public string Frame { get; set; } // tropical / sidereal
public string AyanamsaProfile { get; set; }
public double? AyanamsaDegrees { get; set; }
public string EphemerisEngine { get; set; }
public string EphemerisVersion { get; set; }
public string Origin { get; set; } // geocentric / topocentric
public string ApparentMode { get; set; } // true / apparent / mean
public string EpochOrEquinox { get; set; }
}
“Lahiri” বললেই metadata সম্পূর্ণ হয় না। Geocentric না topocentric, apparent না mean, ecliptic of date না fixed equinox—এগুলোও comparison-এর আগে মিলতে হবে।
দুটি result কীভাবে তুলনা করবেন?
- একই Julian Day/time scale নিন;
- একই body center ও origin—geocentric/topocentric—নিন;
- Mean, true বা apparent stage মিলিয়ে নিন;
- Tropical না sidereal তা নিশ্চিত করুন;
- Sidereal হলে exact ayanāṃśa profile ও value মিলান;
- Ecliptic/equinox reference মিলান;
- Longitude normalize করুন;
- Boundary-crossing comparison হলে unrounded raw value ব্যবহার করুন;
- তারপর shortest signed angular difference হিসাব করুন।
static double SignedAngularDifference(double first, double second)
{
double difference = Normalize360(first - second);
if (difference > 180.0) difference -= 360.0;
return difference;
}
৩৫৯.৯° এবং ০.১°-এর ordinary subtraction ৩৫৯.৮° দেখাতে পারে, অথচ প্রকৃত shortest difference মাত্র −০.২°। Saṅkrānti boundary test-এ এই normalization অপরিহার্য।
Validation checklist
- প্রতিটি longitude-এর frame labeled;
- Tropical zero = equinox of declared reference;
- Sidereal profile name published;
- Ayanāṃśa value-of-date published;
- Ayanāṃśa sign convention documented;
- λsid = normalize(λtrop − A) verified;
- Reverse conversion verified;
- Negative longitude normalized;
- 360° normalized to 0°;
- Traditional result not double-corrected;
- Lahiri mode explicitly selected;
- Sidereal calculation flag present;
- Tropical call omits sidereal flag;
- Swiss global mode protected by lock;
- Cache key includes ayanāṃśa mode;
- Cache key includes engine version;
- Traditional profile has separate cache;
- Modern Sankranti star fit remains separate;
- বাংলা solar month uses selected nirāyaṇa Sun;
- Saṅkrānti root uses unrounded longitude;
- Nakṣatra uses nirāyaṇa Moon;
- Yoga uses nirāyaṇa Sun + Moon;
- Tithi difference cancels common A;
- Karaṇa difference cancels common A;
- Different planetary models may still change tithi;
- Sidereal lagna profile named;
- House geometry and zodiac conversion separated;
- Sunrise does not receive ayanāṃśa offset;
- Moonrise does not receive ayanāṃśa offset;
- Eclipse contacts do not receive ayanāṃśa offset;
- Equinox/solstice remain tropical events;
- Mean-to-mean comparison only;
- True/apparent settings matched;
- Geocentric/topocentric settings matched;
- Same JD/time scale used;
- Shortest angular difference used;
- 0°/360° boundary regression tested;
- 13°20′ nakṣatra boundary tested;
- 12° tithi boundary tested;
- 13°20′ yoga boundary tested;
- Historical year 594 profile tested;
- Year 1946/1947 profile isolation tested;
- Daily, report ও XML metadata agree;
- API exposes coordinate profile;
- Regression snapshots retain raw decimals.
সাধারণ ভুল ও তার ফল
| ভুল | ফল | সমাধান |
|---|---|---|
| “Sidereal” লিখে profile না বলা | Result reproduce করা যায় না | Mode ও value-of-date প্রকাশ |
| Classical nirāyaṇa থেকে Lahiri আবার বাদ | Double correction | Engine-native frame metadata |
| Tropical Moon দিয়ে nakṣatra | ভুল segment/end time | Selected nirāyaṇa Moon |
| Tropical sum দিয়ে yoga | প্রায় 2A frame shift | দুই sidereal longitude যোগ |
| Sunrise-এ ayanāṃśa subtract | Physical event বিকৃত | Rise/set geometry আলাদা |
| Mean বনাম apparent longitude compare | Difference-এর ভুল ব্যাখ্যা | Calculation stage মিলান |
| ৩৫৯°−০° ordinary difference | Huge false error | Shortest signed difference |
| Shared Swiss mode unlocked | Concurrent profile leakage | Lock/isolated context |
উপসংহার
সায়ন ও নিরয়ণ longitude একই গ্রহের দুই coordinate reference। তাদের পার্থক্য ayanāṃśa; এটি কোনো body-specific orbital correction নয়। কোন sidereal zero ও precession model বেছে নেওয়া হয়েছে তার ওপর নিরয়ণ result নির্ভর করে।
বাংলা সৌর মাস, সংক্রান্তি, নক্ষত্র, যোগ ও sidereal lagna-য় selected nirāyaṇa profile গুরুত্বপূর্ণ। তিথি ও করণে common ayanāṃśa angular difference থেকে cancel করলেও underlying planetary engine difference থেকে যায়। Sunrise, moonrise ও eclipse geometry-তে ayanāṃśa দিয়ে event সরানো উচিত নয়।
এই project-এর জন্য Traditional Sūrya-Siddhānta এবং Swiss Lahiri দুটি স্বতন্ত্র profile। প্রতিটি output-এ engine, frame, ayanāṃśa, origin ও calculation stage প্রকাশ করলে historical research, printed Panjika comparison এবং modern chart—সবগুলো একই codebase-এ স্বচ্ছভাবে সহাবস্থান করতে পারে।
তথ্যসূত্র ও আরও পাঠ
- Kyoto Pancanga 3.14 Readme; Sūrya-Siddhānta ayanāṃśa profile, ৫৪″/year এবং AD 499 reference.
- Swiss Ephemeris Programmer’s Documentation; sidereal modes,
swe_set_sid_modeএবং ayanāṃśa convention. - Swiss Ephemeris General Documentation; tropical ও sidereal calculations.
- Official Swiss Ephemeris source repository; sidereal flags ও mode constants.
- Positional Astronomy Centre—Rashtriya Panchanga; published nirāyaṇa solar transition ও ayanāṃśa examples.
- Ebenezer Burgess—Translation of the Sūrya-Siddhānta.
মন্তব্য, আলোচনা ও প্রশ্ন