Merge lp:~i-martividal/stellarium/Observability-newHeli into lp:stellarium

Proposed by Ivan Marti-Vidal
Status: Merged
Merged at revision: 7173
Proposed branch: lp:~i-martividal/stellarium/Observability-newHeli
Merge into: lp:stellarium
Diff against target: 239 lines (+99/-15)
4 files modified
plugins/Observability/src/Observability.cpp (+86/-11)
plugins/Observability/src/Observability.hpp (+11/-2)
plugins/Observability/src/gui/ObservabilityDialog.cpp (+1/-1)
plugins/Observability/src/gui/ObservabilityDialog.ui (+1/-1)
To merge this branch: bzr merge lp:~i-martividal/stellarium/Observability-newHeli
Reviewer Review Type Date Requested Status
gzotti Approve
Alexander Wolf Approve
Review via email: mp+242650@code.launchpad.net

Description of the change

Dear all,

I have to give a talk about Archaeoastronomy this afternoon, and wanted to use Stellarium for a nice real-time exercise. Then I realized that the outputs for "Acronycal" and "Cosmical" are swapped in the screen. Apart from this bug, these quantities are computed with respect to the Sun's rise/set at the horizon, and not with respect to the astronomical twilight (which should give better estimates for the Heliacal and Acronycal events).

So:

1.- I have corrected the swap. Now the output agrees with what the documentation says.

2.- The Heliacal and Acronycal ephemeris are now computed with respect to the astronomical twilight. Since the Sun's altitude at this twilight can be fine-tunned in the config window (together with the effective altitude of the horizon for the star to be visibile), this gives the user a lot of flexibility to study the Heliacal rise and set of stars.

3.- I've also changed the documentation, to reflect the new way Observability estimates these ephemeris.

Now, the matching between the Heliacal rise of Sirius at 2500 bC and the beginning of the old Egyptian calendar is perfect, as well as the Heliacal rise of eta-Uma, as seen from the Cochasqui pyramids in Ecuador (for this heliacal rise, the star is only visible above ~10 degrees from the pyramids, so the option of increasing the horizon's altitude was quite useful here!).

   Best Wishes,

          Ivan

To post a comment you must log in.
Revision history for this message
Alexander Wolf (alexwolf) :
review: Approve
Revision history for this message
gzotti (georg-zotti) wrote :

Hi Ivan!

The terms "acronychal" and "cosmical" relate to geometry, not observability. And these events relate always to mathematical horizon, not any twilight phase, solar or horizon altitude or practical observability. Think about renaissance scholars doing this simple analysis on an astrolabe (planisphere precursor). Please fix that to adhere to these definitions for these particular terms.

Of course, real observability is of greater concern to most of our users out under the sky (or indoors planning an observing session or their next astro travel). So adding a line "object visible for sun lower than (settable: e.g.-12) degrees" or similar may be more helpful to those users.

Your plugin can become superbly important when the heliacal predictions become more accurate. There are two known families of procedures I am aware of: One goes back to early 20th century research around Mesopotamian clay tablet records. Carl Schoch has written table-based procedures (based on the arcus visionis in the Almagest), but his work may be hard to find (at least online.)

A more modern approach was worked out by Brad Schaefer, e.g. in JHA
http://adsabs.harvard.edu/full/1987JHAS...18...19S

There is also an article by him with (a bit rough) BASIC code in some Sky&Telescope of that period. The algorithm includes some approximations of solar positions etc, these need to be replaced by calls to StelCore methods.

Although his method claims superiority, it is according to observers not yet fully clear which is the better approach, so I'd like to have even both models implemented sooner or later.

Maybe you can follow Schaefer's steps for a first more thorough solution of heliacal phenomena. See also http://www.iol.ie/~geniet/eng/vislimitassump.htm for more related work. Putting these various methods in Stellarium would be very fine! (Some parts occur in various places of sky brightness already.)

Another thing is the landscape horizon height. You don't need your switch any longer: I have added functionality in 0.13.0 to make landscapes more intelligent: You can test opacity at a given direction. Opacity==0 means "landscape is transparent, i.e., no mountain in the way". This would be very nice to see used for true-landscape analysis. Just make sure to get the lowest appearance of an object, in case something rises along a valley, hides behind a mountain and becomes visible again...

review: Needs Fixing
7172. By Ivan Marti-Vidal

Corrected Acronyc/Cosmic/Heliacal rise/set.

Revision history for this message
Ivan Marti-Vidal (i-martividal) wrote :

Hi all,

I've just uploaded a revised version, putting back the Acronycal/Cosmical rise/sets back to their estimates using the horizon. I've added a new line to the printed output, with the estimate of the Heliacal rise/set, which now is based on a new function "computeHeli". The idea would be to complicate this function with better models in a near future.

    Best Wishes,

          Ivan

Revision history for this message
gzotti (georg-zotti) wrote :

OK, that's fine for now.

Of course it's your plugin and you are free to show what you feel important, but the hints given remain valid. Some terminology is very clearly defined, and if those numbers come out wrongly, this is problematic.

Kind regards,
Georg

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'plugins/Observability/src/Observability.cpp'
2--- plugins/Observability/src/Observability.cpp 2014-11-24 11:24:05 +0000
3+++ plugins/Observability/src/Observability.cpp 2014-11-25 10:36:11 +0000
4@@ -195,16 +195,18 @@
5 msgCulminatesAt = q_("Culminates at %1 (in %2) at %3 deg.");
6 msgCulminatedAt = q_("Culminated at %1 (%2 ago) at %3 deg.");
7 msgSrcNotObs = q_("Source is not observable.");
8- msgNoACRise = q_("No Acronychal nor Heliacal rise/set.");
9+ msgNoACRise = q_("No Acronychal nor Cosmical rise/set.");
10 msgGreatElong = q_("Greatest elongation: %1 (at %2 deg.)");
11 msgLargSSep = q_("Largest Sun separation: %1 (at %2 deg.)");
12 msgNone = q_("None");
13 // TRANSLATORS: The space at the end is significant - another sentence may follow.
14- msgAcroRise = q_("Heliacal rise/set: %1/%2. ");
15+ msgAcroRise = q_("Acronycal rise/set: %1/%2. ");
16+ msgHeliRise = q_("Heliacal rise/set: %1/%2. ");
17+ msgNoHeliRise = q_("No Heliacal rise/set. ");
18 // TRANSLATORS: The space at the end is significant - another sentence may follow.
19- msgNoAcroRise = q_("No Heliacal rise/set. ");
20- msgCosmRise = q_("Acronycal rise/set: %1/%2.");
21- msgNoCosmRise = q_("No Acronycal rise/set.");
22+ msgNoAcroRise = q_("No Acronycal rise/set. ");
23+ msgCosmRise = q_("Cosmical rise/set: %1/%2.");
24+ msgNoCosmRise = q_("No Cosmical rise/set.");
25 msgWholeYear = q_("Observable during the whole year.");
26 msgNotObs = q_("Not observable at dark night.");
27 msgAboveHoriz = q_("Nights above horizon: %1");
28@@ -665,6 +667,7 @@
29 //AcroCos = q_("No Acronychal nor Cosmical rise/set.");
30 lineObservableRange = msgSrcNotObs;
31 lineAcroCos = msgNoACRise;
32+ lineHeli = msgNoHeliRise;
33 }
34 else
35 { // Source can be seen.
36@@ -706,16 +709,23 @@
37
38 if (show_AcroCos)
39 {
40- int acroRise, acroSet, cosRise, cosSet;
41+ int acroRise, acroSet, cosRise, cosSet, heliRise, heliSet;
42+
43 int result = calculateAcroCos(acroRise, acroSet,
44 cosRise, cosSet);
45+ int resultHeli = calculateHeli(0,heliRise,heliSet);
46+
47 QString acroRiseStr, acroSetStr;
48 QString cosRiseStr, cosSetStr;
49+ QString heliRiseStr, heliSetStr;
50 // TODO: Possible error? Day 0 is 1 Jan.
51 acroRiseStr = (acroRise>0)?formatAsDate(acroRise):msgNone;
52 acroSetStr = (acroSet>0)?formatAsDate(acroSet):msgNone;
53 cosRiseStr = (cosRise>0)?formatAsDate(cosRise):msgNone;
54 cosSetStr = (cosSet>0)?formatAsDate(cosSet):msgNone;
55+ heliRiseStr = (heliRise>0)?formatAsDate(heliRise):msgNone;
56+ heliSetStr = (heliSet>0)?formatAsDate(heliSet):msgNone;
57+
58
59 if (result==3 || result==1)
60 lineAcroCos = msgAcroRise
61@@ -730,6 +740,13 @@
62 .arg(cosSetStr);
63 else
64 lineAcroCos += msgNoCosmRise;
65+
66+ if (resultHeli==1)
67+ lineHeli = msgHeliRise.arg(heliRiseStr).arg(heliSetStr);
68+ else
69+ lineHeli = msgNoHeliRise;
70+
71+
72 }
73
74
75@@ -840,6 +857,8 @@
76 {
77 yLine -= lineSpacing;
78 painter.drawText(xLine + fontSize, yLine, lineAcroCos);
79+ yLine -= lineSpacing;
80+ painter.drawText(xLine + fontSize, yLine, lineHeli);
81 }
82 }
83 }
84@@ -1092,6 +1111,62 @@
85 ///////////////////////////////////////////
86
87
88+
89+
90+///////////////////////////////////////////
91+// Finds the dates of Acronichal (Rise, Set) and Cosmical (Rise2, Set2) dates.
92+int Observability::calculateHeli(int imethod, int &heliRise, int &heliSet)
93+{
94+
95+ heliRise = -1;
96+ heliSet = -1;
97+
98+ double bestDiffHeliRise = 12.0;
99+ double bestDiffHeliSet = 12.0;
100+
101+ double hourDiffHeliRise, hourDiffHeliSet;
102+ bool success = false;
103+
104+ for (int i=0; i<366; i++)
105+ {
106+ if (objectH0[i]>0.0 && sunSidT[0][i]>0.0 && sunSidT[1][i]>0.0)
107+ {
108+ success = true;
109+ hourDiffHeliRise = toUnsignedRA(objectRA[i] - objectH0[i]);
110+ // hourDiffCosRise = hourDiffAcroRise-sunSidT[0][i];
111+ hourDiffHeliRise -= sunSidT[0][i];
112+
113+ hourDiffHeliSet = toUnsignedRA(objectRA[i] + objectH0[i]);
114+ // hourCosDiffSet = hourDiffAcroSet - sunSidT[1][i];
115+ hourDiffHeliSet -= sunSidT[1][i];
116+
117+ // Heliacal rise/set:
118+ if (qAbs(hourDiffHeliRise) < bestDiffHeliRise)
119+ {
120+ bestDiffHeliRise = qAbs(hourDiffHeliRise);
121+ heliRise = i;
122+ };
123+ if (qAbs(hourDiffHeliSet) < bestDiffHeliSet)
124+ {
125+ bestDiffHeliSet = qAbs(hourDiffHeliSet);
126+ heliSet = i;
127+ };
128+
129+ };
130+ };
131+
132+ heliRise *= (bestDiffHeliRise > 0.083)?-1:1; // Check that difference is lower than 5 minutes.
133+ heliSet *= (bestDiffHeliSet > 0.083)?-1:1; // Check that difference is lower than 5 minutes.
134+ int result = (heliRise>0 || heliSet>0) ? 1 : 0;
135+ return (success) ? result : 0;
136+
137+
138+};
139+
140+
141+
142+
143+
144 ///////////////////////////////////////////
145 // Finds the dates of Acronichal (Rise, Set) and Cosmical (Rise2, Set2) dates.
146 int Observability::calculateAcroCos(int &acroRise, int &acroSet,
147@@ -1112,16 +1187,16 @@
148
149 for (int i=0; i<366; i++)
150 {
151- if (objectH0[i]>0.0 && sunSidT[0][i]>0.0 && sunSidT[1][i]>0.0)
152+ if (objectH0[i]>0.0 && sunSidT[2][i]>0.0 && sunSidT[3][i]>0.0)
153 {
154 success = true;
155 hourDiffAcroRise = toUnsignedRA(objectRA[i] - objectH0[i]);
156- hourDiffCosRise = hourDiffAcroRise-sunSidT[1][i];
157- hourDiffAcroRise -= sunSidT[0][i];
158+ hourDiffCosRise = hourDiffAcroRise-sunSidT[3][i];
159+ hourDiffAcroRise -= sunSidT[2][i];
160
161 hourDiffAcroSet = toUnsignedRA(objectRA[i] + objectH0[i]);
162- hourCosDiffSet = hourDiffAcroSet - sunSidT[0][i];
163- hourDiffAcroSet -= sunSidT[1][i];
164+ hourCosDiffSet = hourDiffAcroSet - sunSidT[2][i];
165+ hourDiffAcroSet -= sunSidT[3][i];
166
167 // Acronychal rise/set:
168 if (qAbs(hourDiffAcroRise) < bestDiffAcroRise)
169
170=== modified file 'plugins/Observability/src/Observability.hpp'
171--- plugins/Observability/src/Observability.hpp 2014-04-04 19:34:31 +0000
172+++ plugins/Observability/src/Observability.hpp 2014-11-25 10:36:11 +0000
173@@ -162,7 +162,7 @@
174 //! @param[in] bodyType is 1 for Sun, 2 for Moon, 3 for Solar System object.
175 bool calculateSolarSystemEvents(StelCore* core, int bodyType);
176
177-//! Finds the heliacal rise/set dates of the year for the currently-selected object.
178+//! Finds the acronycal and cosmical rise/set dates of the year for the currently-selected object.
179 //! @param[out] acroRise day of year of the Acronycal rise.
180 //! @param[out] acroSet day of year of the Acronycal set.
181 //! @param[out] cosRise day of year of the Cosmical rise.
182@@ -173,6 +173,14 @@
183 int& cosRise, int& cosSet);
184
185
186+//! Finds the Heliacal rise/set dates of the year for the currently-selected object.
187+//! @param imethod Determines the algorithm to use (not yet implemented).
188+//! @param[out] heliRise day of year of the Heliacal rise.
189+//! @param[out] heliSet day of year of the Heliacal set.
190+//! @returns 0 if no dates found and 1 otherwise.
191+ int calculateHeli(int imethod, int& heliRise, int& heliSet);
192+
193+
194 //! Computes the Sun or Moon coordinates at a given Julian date.
195 //! @param core the stellarium core.
196 //! @param JD double for the Julian date.
197@@ -323,7 +331,7 @@
198 //! Cached copy of the line reporting when the target is observable.
199 QString lineObservableRange;
200 //! Cached copy of the line reporting the acronical/cosmical rise and set.
201- QString lineAcroCos;
202+ QString lineAcroCos, lineHeli;
203
204 //! Strings to save ephemeris Times:
205 QString RiseTime, SetTime, CulmTime;
206@@ -367,6 +375,7 @@
207 //! @{
208 QString msgSetsAt, msgRoseAt, msgSetAt, msgRisesAt, msgCircumpolar, msgNoRise, msgCulminatesAt, msgCulminatedAt, msgH, msgM, msgS;
209 QString msgSrcNotObs, msgNoACRise, msgGreatElong, msgLargSSep, msgNone, msgAcroRise, msgNoAcroRise, msgCosmRise, msgNoCosmRise;
210+ QString msgHeliRise, msgHeliSet, msgNoHeliRise;
211 QString msgWholeYear, msgNotObs, msgAboveHoriz, msgToday, msgThisYear, msgPrevFullMoon, msgNextFullMoon;
212 //! @}
213
214
215=== modified file 'plugins/Observability/src/gui/ObservabilityDialog.cpp'
216--- plugins/Observability/src/gui/ObservabilityDialog.cpp 2014-11-24 11:24:05 +0000
217+++ plugins/Observability/src/gui/ObservabilityDialog.cpp 2014-11-25 10:36:11 +0000
218@@ -141,7 +141,7 @@
219 html += QString("<tr><td>%1</td><td>%2</td></tr>").arg(q_("Horizon altitude:")).arg(q_("Minimum observable altitude (due to mountains, buildings, or just a limited telescope mount)."));
220
221 html += QString("<tr><td>%1</td><td>%2</td></tr>").arg(q_("Today ephemeris:")).arg(q_("Self-explanatory. The program will show the rise, set, and culmination (transit) times. The exact times for these ephemeris are given in two ways: as time spans (referred to the current time) and as clock hours (in local time)."));
222- html += QString("<tr><td>%1</td><td>%2</td></tr>").arg(q_("Acronychal/Cosmical rise/set:")).arg(q_("The days of Heliacal rise and Cosmical set of an object are estimated as the days when the object rises (or sets) together with the Sun's astronomical rise/set (i.e., at the astronomical twilight). The exact dates of these ephemeris depend on the Observer's location. On the contrary, the Acronycal rise (or set) happens when the star rises/sets with the setting/rising of the Sun (i.e., opposite to the Sun). On the one hand, it is obvious that the source is hardly observable (or not observable at all) in the dates between Cosmical set and Heliacal rise. On the other hand, the dates around the Acronychal set and rise are those when the altitude of the celestial object uses to be high when the Sun is well below the horizon (hence the object can be well observed)."));
223+ html += QString("<tr><td>%1</td><td>%2</td></tr>").arg(q_("Acronychal/Cosmical/Heliacal rise/set:")).arg(q_("The days of Cosmical rise/set of an object are estimated as the days when the object rises (or sets) together with the rise/set of the Sun. The exact dates of these ephemeris depend on the Observer's location. On the contrary, the Acronycal rise (or set) happens when the star rises/sets with the setting/rising of the Sun (i.e., opposite to the Sun). On the one hand, it is obvious that the source is hardly observable (or not observable at all) in the dates between Cosmical set and Cosmical rise. On the other hand, the dates around the Acronychal set and rise are those when the altitude of the celestial object uses to be high when the Sun is well below the horizon (hence the object can be well observed). The date of Heliacal rise is the first day of the year when a star becomes visible. It happens when the star is close to the eastern horizon roughly before the end of the astronomical night (i.e., at the astronomical twilight). In the following nights, the star will be visibile during longer periods of time, until it reaches its Heliacal set (i.e., the last night of the year when the star is still visible). At the Heliacal set, the star sets roughly after the beginning of the astronomical night."));
224 html += QString("<tr><td>%1</td><td>%2</td></tr>").arg(q_("Largest Sun separation:")).arg(q_("Happens when the angular separation between the Sun and the celestial object are maximum. In most cases, this is equivalent to say that the Equatorial longitudes of the Sun and the object differ by 180 degrees, so the Sun is in opposition to the object. When an object is at its maximum possible angular separation from the Sun (no matter if it is a planet or a star), it culminates roughly at midnight, and on the darkest possible area of the Sky at that declination. Hence, that is the 'best' night to observe a particular object."));
225 html += QString("<tr><td>%1</td><td>%2</td></tr>").arg(q_("Nights with source above horizon:")).arg(q_("The program computes the range of dates when the celestial object is above the horizon at least during one moment of the night. By 'night', the program considers the time span when the Sun altitude is below that of the twilight (which can be set by the user; see above). When the objects are fixed on the sky (or are exterior planets), the range of observable epochs for the current year can have two possible forms: either a range from one date to another (e.g., 20 Jan to 15 Sep) or in two steps (from 1 Jan to a given date and from another date to 31 Dec). In the first case, the first date (20 Jan in our example) shall be close to the so-called 'Heliacal rise of a star' and the second date (15 Sep in our example) shall be close to the 'Heliacal set'. In the second case (e.g., a range in the form 1 Jan to 20 May and 21 Sep to 31 Dec), the first date (20 May in our example) would be close to the Heliacal set and the second one (21 Sep in our example) to the Heliacal rise. More exact equations to estimate the Heliacal rise/set of stars and planets (which will not depend on the mere input of a twilight Sun elevation by the user) will be implemented in future versions of this plugin."));
226 html += QString("<tr><td>%1</td><td>%2</td></tr>").arg(q_("Full Moon:")).arg(q_("When the Moon is selected, the program can compute the exact closest dates of the Moon's opposition to the Sun."));
227
228=== modified file 'plugins/Observability/src/gui/ObservabilityDialog.ui'
229--- plugins/Observability/src/gui/ObservabilityDialog.ui 2013-08-11 11:41:30 +0000
230+++ plugins/Observability/src/gui/ObservabilityDialog.ui 2014-11-25 10:36:11 +0000
231@@ -316,7 +316,7 @@
232 <item>
233 <widget class="QCheckBox" name="acroCosCheckBox">
234 <property name="text">
235- <string>Dates of Acronychal and Cosmical rise/set</string>
236+ <string>Dates of Acronychal/Cosmical/Heliacal rise/set</string>
237 </property>
238 </widget>
239 </item>