[APBeta] Global observations script
Jeff Young
jey at adobe.com
Tue Mar 17 13:20:19 PDT 2009
I have a script I use to print out a PDF of all my observations. (It also has a mode that generates a simple list of all observed objects and the date/times for each observation.) It's based on an old script (that I think Paul wrote), but it's been through some major metamorphisis.
I'd upload it to the general area, but it contains a couple of sections of hard-coded stuff that's probably only useful with my plans. (These include the format of the transparency field and the location of a plan containing all the planets and comets.)
However, for those of you who write script and want to customize it (or simply change the hard-coded parts to your liking), I've appended it to this message.
Cheers,
-- Jeff.
//----------------------------------------------------------------------------------------------
sub PageNumbering(c as Canvas, title as string, doPrint as boolean)
// Handle page numbering
dim dateStr, page as string, x as integer
c.TextItalic = true
c.ForeColor(64, 64, 64)
dim now as Date
now = new Date
dateStr = now.ShortDate + " " + now.ShortTime
page = "Page " + str(c.PageNumber)
if doPrint then
c.DrawText(title, 0, c.TextHeight)
c.DrawText(dateStr, c.Width - c.TextWidth(dateStr), c.TextHeight)
c.DrawText(page, c.Width - c.TextWidth(page), c.Height)
else
c.DrawText(dateStr, 0, c.TextHeight)
c.DrawText(title, c.TextWidth(dateStr) + 20, c.TextHeight)
c.DrawText(page, c.Width - c.TextWidth(page), c.TextHeight)
end
c.TextItalic = false
c.ForeColor(0, 0, 0)
end sub
//----------------------------------------------------------------------------------------------
//
function FormatDateTime(dateTime as double) as string
dim obsDate as Date
obsDate = new Date(dateTime)
dim s as string
s = obsDate.ShortDate + " " + DoubleToTime(dateTime, false) + " UT"
return s
end function
//----------------------------------------------------------------------------------------------
//
function FormatConditions(seeing as string, trans as string) as string
dim s as string
// Seeing should be either "Seeing 2/5" or "Pickering 6":
//
if InStr(seeing, "/") > 0 then
s = "Seeing " + seeing
elseif InStr(seeing, ".") > 0 then
s = "Pickering " + NthField(seeing, ".", 1)
elseif Len(seeing) > 0 then
s = seeing
end if
// See if we have NELM and/or SQM readings:
//
dim nelm, sqm as string
nelm = Trim(NthField(trans, " ", 1))
sqm = Trim(NthField(trans, " ", 2))
if Left(sqm, 1) = "(" then
sqm = Mid(sqm, 2, sqm.len - 2)
end if
// Format them into "NELM 5.5, SQM 20.7":
//
if Len(nelm) > 0 then
if Len(s) > 0 then
s = s + ", "
end if
s = s + "NELM " + nelm
end if
if Len(sqm) > 0 then
if Len(s) > 0 then
s = s + ", "
end if
s = s + "SQM " + sqm
end if
return s
end function
//----------------------------------------------------------------------------------------------
//
function FormatEquipment(scope as string, ep as string, filter as string, aid as string) as string
dim s as string
s = scope
if Len(ep) > 0 AND ep <> "None" then
s = s + ", " + Trim(ep)
end if
if Len(filter) > 0 AND filter <> "None" then
s = s + ", " + filter
end if
if Len(aid) > 0 AND aid <> "None" then
s = s + ", " + aid
end if
return s
end function
//----------------------------------------------------------------------------------------------
// Support function which calculates magnification and performs optional rounding.
//
function GetMagnification(scopeName as string, epName as string, aidName as string, doRound as boolean) as string
dim scope as TelescopeResource, ep as EyepieceResource, aid as VisualAidResource
scope = TelescopeResource.Get(scopeName)
ep = EyepieceResource.Get(epName)
aid = VisualAidResource.Get(aidName)
dim mag as double
if scope.IsBinocular then
mag = scope.Magnification
else
mag = APResource.Magnification(scope, ep, aid)
end if
if doRound AND scope.IsTelescope then
if mag < 200 then
dim dime, dimeFit, quarter, quarterFit as double
dime = Round(mag / 10) * 10
dimeFit = Abs(mag - dime)
quarter = Round(mag / 25) * 25
quarterFit = Abs(mag - quarter)
if quarterFit < dimeFit then
mag = quarter
else
mag = dime
end if
else
mag = Round(mag / 25) * 25
end if
end if
if mag > 0 then
return str(mag) + "X"
else
return "--"
end if
end function
//----------------------------------------------------------------------------------------------
// A couple of routines to convert names to indicies.
//
function CurrentTelescopeIndex(scopes() as string) as integer
dim target as TelescopeResource
target = TelescopeResource.Current
if target = nil then
target = TelescopeResource.Default
end if
if target <> nil then
dim i as integer
for i = 0 to Ubound(scopes)
if scopes(i) = target.Name then
return i
end if
next
end if
return 1
end function
function CurrentSiteIndex(sites() as string) as integer
dim target as SiteResource
target = SiteResource.Current
if target = nil then
target = SiteResource.Default
end if
if target <> nil then
dim i as integer
for i = 0 to Ubound(sites)
if sites(i) = target.Name then
return i
end if
next
end if
return 1
end function
//----------------------------------------------------------------------------------------------
// Searches the open plans for a particular ID. Useful for comets and planets where we can't
// use RA/Dec to fetch images, etc.
//
function GetPlanObject(id as string) as APPlanObject
dim ssPlan as APPlan
ssPlan = APPlan.Plan("Solar_System.apd")
if ssPlan = nil then
ssPlan = APPlan.OpenPlan("C:\Documents and Settings\jey\My Documents\AstroPlanner\Plans\Solar_System.apd")
end if
if ssPlan <> nil then
dim i as integer
for i = 1 to ssPlan.nObjects
if ssPlan.Obj(i).ID = id then
return ssPlan.Obj(i)
end if
next
end if
end function
//----------------------------------------------------------------------------------------------
// Collect a list of all observers, telescopes and sites mentioned in global observations.
//
sub AddToList(s as string, list() as string)
dim i as integer, found as boolean
if Len(s) = 0 then
exit
end if
found = false
for i = 0 to Ubound(list)
if list(i) = s then
found = true
exit
end if
next
if NOT found then
list.Append(s)
end if
end sub
sub CollectResources(observerList() as string, scopeList() as string, siteList() as string)
dim i as integer
dim obs as APObservation
dim session as APSession
for i = 1 to APObservation.Count
obs = APObservation.Observation(i)
AddToList(obs.Telescope(1), scopeList)
next
for i = 1 to APSession.Count
session = APSession.Session(i)
AddToList(session.Observer, observerList)
AddToList(session.Site, siteList)
next
end sub
//----------------------------------------------------------------------------------------------
// Sort "M8" before "M71", not after it (ie: a string compare won't quite do).
//
function CompareIDs(id1 as string, id2 as string) as integer
dim i, cmp as integer
i = 1
while i <= len(id1) AND i <= len(id2)
// If we've gotten to numbers, proceed with numeric compare
dim c1, c2 as string
dim v1, v2 as double
c1 = mid(id1, i, 1)
c2 = mid(id2, i, 1)
if IsNumeric(c1) AND IsNumeric(c2) then
dim j1 as integer
j1 = i + 1
while j1 <= len(id1) AND IsNumeric(mid(id1, j1, 1))
j1 = j1 + 1
wend
dim j2 as integer
j2 = i + 1
while j2 <= len(id2) AND IsNumeric(mid(id2, j2, 1))
j2 = j2 + 1
wend
v1 = val(mid(id1, i))
v2 = val(mid(id2, i))
if v1 < v2 then
return -1
elseif v1 > v2 then
return 1
else // Numbers equal, continue compare after them
if j1 <= len(id1) AND j2 <= len(id2) then
return CompareIDs(mid(id1, j1), mid(id2, j2))
else
return 0
end if
end if
end if
// Continue with single-character string compares
cmp = strcomp(c1, c2, 0)
if cmp < 0 then
return -1
elseif cmp > 0 then
return 1
else
i = i + 1
end if
wend
if len(id1) < len(id2) then
return -1
elseif len(id1) > len(id2) then
return 1
else
return 0
end if
end function
//----------------------------------------------------------------------------------------------
// My first REALBasic class. And dang, am I proud of it.
//
class target
dim ID as string
dim obs(-1) as integer
end class
//----------------------------------------------------------------------------------------------
// Short form constants and table routines.
//
const ID_width = 16.0
const Obs_width = 84.0
function NewShortFormTable() as Table
dim t as table
t = new Table(1, 2)
t.ColumnTitle(1) = "ID"
t.ColumnTitle(2) = "Observations"
t.ColumnWidth(1) = ID_width
return t
end function
//----------------------------------------------------------------------------------------------
// Long form table routines.
//
function ConstructObservationTable() as Table
dim t as Table
t = new Table(3, 1)
dim row as integer
for row = 1 to t.RowCount
t.RowHeight(row) = 100.0
next
return t
end function
function PopulateObservationTable(t as Table, session as APSession, obs as APObservation, _
doRound as boolean, c as Canvas, cellmargin as integer) as integer
t.Cell(1, 1) = FormatDateTime(obs.LocalDateTime) + ", " + session.Site + "; " _
+ FormatConditions(session.Seeing, session.Transparency)
t.Cell(2, 1) = FormatEquipment(obs.Telescope(1), obs.Eyepiece(1), obs.Filter(1), obs.VisualAid(1)) + "; " _
+ GetMagnification(obs.Telescope(1), obs.Eyepiece(1), obs.VisualAid(1), doRound)
dim paras() as string
dim i, nLines, colWidth as integer
colWidth = c.Width - cellmargin
nLines = 0
paras = Split(obs.Notes, Chr(13))
for i = 0 to Ubound(paras)
nLines = nLines + Round((c.TextWidth(paras(i)) * 1.05 / colWidth) + 0.5)
next
t.RowHeight(3) = 20.0 + (nLines * 80.0)
t.Cell(3, 1) = LTrim(obs.Notes)
return nLines - 1
end function
//----------------------------------------------------------------------------------------------
// Main script.
//
sub main()
try // Be a good citizen
dim observerList(-1), scopeList(-1), siteList(-1) as string
CollectResources(observerList, scopeList, siteList)
//
// Throw up a dialog to see if user wants to limit to specific telescopes/sites.
//
const observerCheckbox = "For Specific Observer:"
const observerPopup = ".0"
const telescopeCheckbox = "For Specific Telescope:"
const telescopePopup = ".1"
const siteCheckbox = "At Specific Site:"
const sitePopup = ".2"
const longFormCheckbox = "Include Observation Details"
const pageBreaksCheckbox = "Start Objects at Top of Page"
const roundMagsCheckbox = "Round Magnifications"
const imagesCheckbox = "Include User Images:"
const imagesPerLinePopup = ".3"
const printCheckbox = "Print Report"
dim imagesPerLine(4) as string
imagesPerLine(0) = "2 Images Per Line"
imagesPerLine(1) = "3 Images Per Line"
imagesPerLine(2) = "4 Images Per Line"
imagesPerLine(3) = "5 Images Per Line"
imagesPerLine(4) = "6 Images Per Line"
dim forObserver, forScope, forSite as string
dim doPrint, doLong, doBreaks, doRound, doImages as boolean
dim imagewidth as double
dim dlg as Dialog
dlg = new Dialog
dlg.BooleanParameter(observerCheckbox, Ubound(observerList) >= 0)
dlg.PopupParameter(true, observerPopup, 0, observerList)
dlg.ParameterDependency(observerPopup, observerCheckbox)
dlg.BooleanParameter(telescopeCheckbox, Ubound(scopeList) >= 0)
dlg.PopupParameter(true, telescopePopup, CurrentTelescopeIndex(scopeList), scopeList)
dlg.ParameterDependency(telescopePopup, telescopeCheckbox)
dlg.BooleanParameter(siteCheckbox, Ubound(siteList) >= 0)
dlg.PopupParameter(true, sitePopup, CurrentSiteIndex(siteList), siteList)
dlg.ParameterDependency(sitePopup, siteCheckbox)
dlg.CaptionParameter("If options are not checked, report will include all observers, telescopes and/or sites.", _
3, true, false, false, false, true)
dlg.BooleanParameter(longFormCheckbox, true)
dlg.BooleanParameter(pageBreaksCheckbox, false)
dlg.BooleanParameter(true, roundMagsCheckbox, true)
dlg.BooleanParameter(imagesCheckbox, true)
dlg.PopupParameter(true, imagesPerLinePopup, 0, imagesPerLine)
dlg.ParameterDependency(pageBreaksCheckbox, longFormCheckbox)
dlg.ParameterDependency(roundMagsCheckbox, longFormCheckbox)
dlg.ParameterDependency(imagesCheckbox, longFormCheckbox)
dlg.ParameterDependency(imagesPerLinePopup, imagesCheckbox)
dlg.CaptionParameter("", 1, true, false, false, false, true) // spacer
dlg.BooleanParameter(printCheckbox, true)
if NOT dlg.Show("Observing Report") then
return
end if
if dlg.BooleanParameter(observerCheckbox) then
forObserver = dlg.PopupParameterAsString(observerPopup)
else
forObserver = "All Observers"
end if
if dlg.BooleanParameter(telescopeCheckbox) then
forScope = dlg.PopupParameterAsString(telescopePopup)
else
forScope = "All Telescopes"
end if
if dlg.BooleanParameter(siteCheckbox) then
forSite = dlg.PopupParameterAsString(sitePopup)
else
forSite = "All Sites"
end if
doLong = dlg.BooleanParameter(longFormCheckbox)
doBreaks = dlg.BooleanParameter(pageBreaksCheckbox)
doRound = dlg.BooleanParameter(roundMagsCheckbox)
doImages = dlg.BooleanParameter(imagesCheckbox)
if doImages then
dim i as integer
i = dlg.PopupParameter(imagesPerLinePopup) + 2
imagewidth = (1 / i) * 100.0
end if
doPrint = dlg.BooleanParameter(printCheckbox)
//
// Go through all global observations which match the criteria, building a sorted list of
// unique targets.
//
dim i, j as integer, session as APSession, obs as APObservation
dim targets(-1) as target, nTargets as integer
nTargets = 0
// Our sort is actually n log n, but we report progress exponentailly so that it speeds
// up at the end.
Dialog.StartProgress("Collecting Observations...", true, APSession.Count * APSession.Count)
for i = 1 to APObservation.Count
if i MOD 100 = 0 AND Dialog.UpdateProgress(i * i) then
return
end if
obs = APObservation.Observation(i)
session = APSession.Session(obs)
if forObserver = "All Observers" OR forObserver = session.Observer then
if forSite = "All Sites" OR forSite = session.Site then
if forScope = "All Telescopes" OR forScope = obs.Telescope(1) then
dim upper, lower, middle, cmp as integer
dim found as boolean, t as target
found = false
lower = 0
upper = nTargets
while NOT found AND upper > lower
middle = (lower + upper) / 2
cmp = CompareIDs(obs.ID, targets(middle).ID)
if cmp < 0 then
upper = middle
elseif cmp > 0 then
lower = middle + 1
middle = middle + 1
else
found = true
targets(middle).obs.Append(i)
exit
end if
wend
if NOT found then
t = new target
t.ID = obs.ID
t.obs.Append(i)
targets.Insert(middle, t)
nTargets = nTargets + 1
end if
end if
end if
end if
next
Dialog.StopProgress()
//
// Open a new printer document (or display window)
//
dim reportTitle as string
reportTitle = "Observing Report for " + forObserver + " using " + forScope + " at " + forSite
dim c as Canvas
if doPrint then
c = new Canvas(true)
c.TextFont("Times", 10)
else
c = new Canvas(800, 1000, nil, "Observing Report")
c.TextFont("Times", 12)
end if
if c.Cancelled then
return
end if
dim cellmargin as integer
cellmargin = 0.33 * c.TextHeight
PageNumbering(c, reportTitle, doPrint)
if doLong then
//
// Long-form table (in three parts).
//
dim w, h, x, y, y1, theight, imw, margin as integer
dim tbl as Table, s as string, brk as boolean
tbl = ConstructObservationTable()
theight = 0
margin = 3 * c.TextHeight
y = margin
imw = floor(c.Width * imagewidth * 0.01)
dim t as target
for i = 0 to nTargets - 1
t = targets(i)
for j = 0 to Ubound(t.obs)
obs = APObservation.Observation(t.obs(j))
session = APSession.Session(obs)
// Populate the observation table with values
dim extraLines, extraHeight as integer
extraLines = PopulateObservationTable(tbl, session, obs, doRound, c, cellmargin)
extraHeight = extraLines * c.textHeight
// New page?
brk = (j = 0 AND y > margin AND doBreaks)
if brk OR y + theight + extraHeight > c.Height - margin then
c.NewPage()
PageNumbering(c, reportTitle, doPrint)
y = margin
end if
if j = 0 then
// Display the object ID/Name, etc. before the first observation
if obs.ID = obs.Name then
s = obs.ID
else
s = obs.ID + " " + obs.Name
end if
c.TextBold = true
c.DrawText s, 0, y + c.TextHeight
if obs.RA <> 0 OR obs.Dec <> 0 then
s = "RA: " + FormatRA(obs.RA) + " Dec: " + FormatDec(obs.Dec)
c.DrawText s, c.Width - c.TextWidth(s), y + c.TextHeight
end if
c.TextBold = false
y = y + 1.6 * c.TextHeight
end if
// Display/print the table
if theight = 0 then
// Measure the height of the first table to be printed/displayed
y1 = c.DrawTable(tbl, 0, y, c.Width, c.Height, Canvas.grid_Thin)
theight = y1 - y
theight = theight - (extraLines * c.textHeight)
y = y1
else
y = c.DrawTable(tbl, 0, y, c.Width, c.Height, Canvas.grid_Thin)
end if
y = y + 0.5 * c.TextHeight
next
if doImages then
// Draw user images, if available
y = y + c.TextHeight
x = 0
obs = APObservation.Observation(t.obs(0))
if obs.Type = "Planet" OR obs.Type = "Comet" OR obs.Type = "Sun" then
dim planObj as APPlanObject
planObj = GetPlanObject(obs.ID)
if planObj = nil then
goto skipImages
else
c.Target(planObj)
end if
else
c.Target(obs.RA, obs.Dec)
end if
for j = 1 to c.ImageCount
if c.IsUserImage(j) then
if x + imw > c.Width then
// New row required
x = 0
y = y + imw + margin
end if
if y + imw + margin > c.Height then
// New page required
c.NewPage()
PageNumbering(c, reportTitle, doPrint)
y = margin
end if
c.DrawImage(j, x, y, imw, obs.Type <> "Planet")
x = x + imw
end if
next
skipImages:
if x > 0 then
y = y + imw + margin
end if
else
y = y + c.TextHeight
end if
next
else
//
// Short-form table.
//
dim lineHeight, header, footer, colWidth as integer
lineHeight = c.TextHeight + cellmargin
header = 1.5 * lineHeight
if doPrint then
footer = 1.5 * lineHeight
else
footer = 0
end if
colWidth = (c.Width * (Obs_width / 100)) - cellmargin
dim linesPerPage, linesOnPage as integer
linesPerPage = (c.Height - (header + footer)) / lineHeight
linesOnPage = 1
dim tbl as Table, y as integer
tbl = NewShortFormTable()
tbl.RowStyle(0) = Table.style_Bold + Table.style_Inverted + Table.style_Gray
dim t as target, dates as string
for i = 0 to nTargets - 1
t = targets(i)
dates = ""
for j = 0 to Ubound(t.obs)
if j > 0 then dates = dates + ", "
obs = APObservation.Observation(t.obs(j))
dates = dates + FormatDateTime(obs.LocalDateTime)
next
dim nLines as integer
nLines = Round((c.TextWidth(dates) * 1.05 / colWidth) + 0.5)
linesOnPage = linesOnPage + nLines
if linesOnPage > linesPerPage then
// Create a new page
y = c.DrawTable(tbl, 0, header, c.Width, c.Height, Canvas.grid_Thin)
tbl.Close()
c.NewPage()
PageNumbering(c, reportTitle, doPrint)
linesOnPage = 1 + nLines
tbl = NewShortFormTable()
tbl.RowStyle(0) = Table.style_Bold + Table.style_Inverted + Table.style_Gray
end if
if linesOnPage > 1 + nLines then
tbl.AddRow()
end if
tbl.RowHeight(tbl.RowCount()) = (nLines * 80.0) + 20.0
tbl.Cell(tbl.RowCount(), 1) = t.ID
tbl.Cell(tbl.RowCount(), 2) = dates
next
y = c.DrawTable(tbl, 0, header, c.Width, c.Height, Canvas.grid_Thin)
tbl.Close()
end if
c.Close()
catch
print "My bad. Observing Report script generated an exception."
end try
end sub
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.astroplanner.net/pipermail/apbeta-astroplanner.net/attachments/20090317/cd69f3e9/attachment-0003.htm>
More information about the APBeta
mailing list