[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