Warning, /education/kstars/kstars/skycomponents/stars.dox is written in an unsupported language. File is not indexed.
0001 /*! \page Stars Stars 0002 \tableofcontents 0003 Design document for the implementation of star catalog support in KStars. 0004 \section StarsClassInheritance Class Inheritance 0005 + StarComponent - Manages all stars 0006 - struct starName - Holds a star's names (defined within StarComponent) 0007 + DeepStarComponent - Manages unnamed stars (instances managed by StarComponent) 0008 + StarBlock - A block of many (usually 100) stars 0009 + StarBlockList - A list of StarBlocks; machinery to load data dynamically from catalog files 0010 + StarBlockFactory - Maintains a cache of recently used StarBlocks 0011 + BinFileHelper - A generic helper class used to deal with binary data files (See ../binfilehelper.h) 0012 + StarData - holds 32 bits of data describing a star (See ../skyobjects/stardata.h) 0013 + DeepStarData - holds 16 bits of data describing a (faint) star (See ../skyobjects/deepstardata.h) 0014 0015 \section Categorization Categorization of Stars 0016 Stars could be either named or unnamed. Named stars and unnamed stars 0017 are treated differently in KStars. Stars having names are handled by 0018 the methods defined in class StarComponent. Unnamed stars are handled 0019 by the methods defined in class DeepStarComponent, which are invoked 0020 via the methods of StarComponent. 0021 0022 A second categorization is "static" and "dynamic" stars. The 0023 StarObjects for "static" stars are always kept in memory. They are 0024 loaded into memory when KStars initializes. "Dynamic" stars are loaded 0025 into memory from the disk when required. When the sky map is slewed to 0026 a new region, or zoomed to a greater depth, dynamic stars are loaded 0027 "on-demand" into memory from the disk and drawn. Named stars are 0028 always static. Unnamed stars could be either static or 0029 dynamic. Naturally, StarComponent deals only with static stars whereas 0030 DeepStarComponent deals with both static and dynamic stars. 0031 0032 A third categorization is "shallow" and "deep" stars. Shallow stars 0033 are the brighter stars, which have enough catalog data to require a 0034 32-byte data structure (StarData) to hold them. Deep stars are the 0035 fainter ones, data for which can be fit into a 16-byte structure 0036 (DeepStarData). All named stars and all static stars are shallow. All 0037 deep stars are dynamic and unnamed. StarComponent manages only shallow 0038 stars. DeepStarComponent manages both shallow and deep stars. 0039 0040 Stars are indexed using \subpage HTMIndexing "multi-level Hierarchical Triangular Mesh" to speed 0041 up drawing and searching for stars in the skymap. 0042 0043 Stars are stored in a custom \ref BinaryFormat Binary Format to speed up reading and loading of data into memory. 0044 0045 \section Catalogs Catalogs 0046 As of this writing, KStars supports the following catalogs: 0047 1. Default named stars catalog ("namedstars.dat" in the data directory) 0048 [Together with default unnamed stars catalog, makes up all stars to mag 8] 0049 + Named 0050 + Static 0051 + Shallow 0052 + Managed by StarComponent's methods 0053 + Names of stars stored in "starnames.dat" in the data directory, 0054 in order of appearance in namedstars.dat 0055 0056 2. Default unnamed stars catalog ("unnamedstars.dat" in the data directory) 0057 [Together with default named stars catalog, makes up all stars to mag 8] 0058 + Unnamed 0059 + Static 0060 + Shallow 0061 + Managed by DeepStarComponent 0062 0063 3. Tycho-2 catalog (Downloadable add-on) 0064 Prerequisite: Default catalogs (namedstars.dat, unnamedstars.dat and starnames.dat) 0065 + Unnamed 0066 + Dynamic 0067 + Shallow 0068 + Managed by DeepStarComponent 0069 + Reside on a level-3 \subpage HTMIndexing HTMesh 0070 + Down to mag ~12 0071 0072 4. USNO NOMAD (part) 100 million star catalog (Downloadable add-on) 0073 Prerequisite: Tycho-2 catalog 0074 + Unnamed 0075 + Dynamic 0076 + Deep 0077 + Managed by DeepStarComponent 0078 + Reside on a level-6 \subpage HTMIndexing HTMesh 0079 + Down to mag ~16 0080 0081 \section NamedStars Named Stars 0082 Named Stars are dealt with by StarComponent. Their case is very simple 0083 because they are all static stars. The star names are stored in a 0084 separate file (starnames.dat), in which the names are maintained in 0085 the same order in which stars appear in the named star catalog 0086 (namedstars.dat). Both files are opened while reading (See 0087 StarComponent::loadStaticData()) and data is read off from the two 0088 files sequentially, side-by-side. 0089 0090 Each record in starnames.dat is 40 bytes long, containing a long name 0091 (32 bytes) and a Bayer designation (8 bytes). 0092 0093 Each record in namedstars.dat is 32 bytes long, and holds a direct 0094 memory dump of struct StarData, made on a little-endian system. (On 0095 big endian systems, byte order inversion is done at runtime) 0096 0097 Named stars are read off the disk at initialization time by 0098 StarComponent::loadStaticStars() and are drawn by the loops in 0099 StarComponent::draw(). All of them reside in the memory throughout 0100 KStars' life. 0101 0102 \section UnnamedStars Unnamed Stars 0103 Much of the machinery listed out above go into maintenance of unnamed 0104 stars. 0105 0106 Unnamed stars are dealt with by DeepStarComponent. 0107 0108 StarComponent has a QVector of DeepStarComponent objects, which are 0109 created for each unnamed-star catalog loaded. (See 0110 StarComponent::loadDeepStarCatalogs().) StarComponent takes 0111 responsibility to call methods of the DeepStarComponents when 0112 required. For instance, StarComponent::draw() calls 0113 DeepStarComponent::draw() on each catalog, after drawing the named 0114 stars. (StarComponent, on the other hand, is managed by 0115 SkyMapComposite) 0116 0117 \subsection MemoryMap Memory map 0118 Memory map of unnamed stars: 0119 + StarComponent 0120 + One DeepStarComponent for every catalog 0121 + One StarBlockList for each trixel 0122 + StarBlockFactory churns out StarBlocks 0123 + Several StarBlocks are attached / detached dynamically to a StarBlockList 0124 + Several StarObjects (usu. 100) in a StarBlock 0125 \subsection Loading Loading unnamed stars 0126 As mentioned earlier, unnamed stars may be both static and dynamic, 0127 and could be both deep and shallow. 0128 \subsubsection Creation Creation of unnamed StarObjects 0129 TODO: This is outdated. Stars are now created differently. 0130 0131 IMPORTANT: Unnamed stars, for fast loading, are not constructed!!! 0132 They are allocated in memory (using malloc) and data is 0133 copied directly (using memcpy) onto them. 0134 This can lead to very strange segfaults with misleading 0135 backtraces if not understood carefully. 0136 0137 For each record read off the data file, a StarObject instance 0138 (plainStarTemplate) is loaded with the data using 0139 StarObject::init(...) and then memcpy()'d and held in a StarBlock 0140 \subsubsection LoadingStatic Loading unnamed, static stars 0141 The method DeepStarComponent::loadStaticStars() (invoked from 0142 StarComponent) loads all static stars in an unnamed-star catalog. 0143 0144 The star data files are organized trixel by trixel. The method enters 0145 each trixel, creates a StarBlock of variable size, enough to hold all 0146 the unnamed stars in the current trixel, and then reads star-by-star 0147 into memory. 0148 0149 Static stars always occupy the first StarBlock in a StarBlockList. 0150 \subsubsection LoadingDynamic Loading unnamed, dynamic stars 0151 Dynamic stars are loaded on-demand (during the draw() call) in 0152 StarBlockList::fillToMag(). 0153 0154 NOTE: This can be a problem for objectNearest(). objectNearest() calls 0155 work correctly only when the sky map is centred on the required 0156 trixel(s). For extending this when required, one must call 0157 StarBlockList::fillToMag() from objectNearest() 0158 0159 fillToMag() is invoked by DeepStarComponent::draw(), for every trixel 0160 present on-screen, with the current magnitude limit (calculated from 0161 the zoom level) as an argument. fillToMag()'s job is to ensure that 0162 the StarBlockList is filled with stars up to that magnitude by loading 0163 more stars from disk if required. 0164 0165 An important point to note is that StarBlockList maintains stars 0166 sorted by magnitude - brightest first - to match the data 0167 file. StarBlocks at the "tail end" of the StarBlockList are the 0168 faintest. fillToMag() quickly checks the magnitude of the last star in 0169 the last StarBlock of the StarBlockList and starts filling into the 0170 last StarBlock. 0171 0172 Each StarBlockList maintains the current read offset in the data file, 0173 so that it can quickly seek to the point where it last loaded and 0174 continue loading fainter stars. When stars are removed from a 0175 StarBlockList, the read offset is decremented. 0176 0177 StarBlocks holding dynamic stars are always of fixed size 0178 (default=100). There could be half-filled StarBlocks. (We save 0179 allocation overhead by recycling StarBlocks using 0180 StarBlockFactory. More about this later.) StarBlockList::fillToMag() 0181 is aware of this fact and continues to fill half-filled StarBlocks 0182 when required. 0183 0184 \subsection Recycling Recycling of StarBlocks 0185 StarBlockFactory maintains a Least-Recently-Used cache of "dynamic" 0186 StarBlocks (which hold dynamic stars). 0187 0188 When StarBlockList::fillToMag() asks for new star blocks, 0189 StarBlockFactory sees if there are unused (trixel not-on-screen) 0190 StarBlocks lying around. If there are none, it allocates a new 0191 StarBlock and hands it over to StarBlockList. But if there are unused 0192 StarBlocks lying around, StarBlockFactory recycles them. 0193 0194 Imagine a situation where the map is panned. A trixel that was 0195 on-screen till now might no longer displayed on the screen, but a new 0196 trixel might come into focus. In this case, StarBlockFactory detaches 0197 the StarBlocks attached to the StarBlockList of the old trixel and 0198 gives them to the StarBlockList of the new trixel. The new data read 0199 off the disk is then StarObject::init()'ed into the StarBlock. 0200 0201 Each draw cycle in KStars has a drawID that is incremented upon every 0202 draw. This makes the drawID almost unique, since it has a very large 0203 period. StarBlockFactory has a local copy of this drawID that is 0204 maintained in sync with KStars' drawID. When stars are drawn in 0205 StarComponent::draw(), every dynamic StarBlock that's drawn is 0206 "touched" by calling StarBlockFactory::mark*(). 0207 0208 When drawing a trixel, markFirst() is called on the first StarBlock in 0209 every StarBlockList and markNext() is called on subsequent ones. The 0210 freshest StarBlocks are maintained at the beginning of the linked list 0211 inside StarBlockFactory and equally-fresh StarBlocks are ordered in 0212 the same order as they appear in StarBlockList. Thus, StarBlockFactory 0213 can safely pluck out the last StarBlock in the linked list and recycle 0214 it (provided it was last touched in an older draw) without affecting 0215 the ordering of stars in StarBlockList (i.e. we ensure that we don't 0216 pluck out a StarBlock from in-between a StarBlockList. Only the last 0217 StarBlock of a StarBlockList can be released at any time). Thus, the 0218 ordering of StarBlocks in the linked-list of StarBlockFactory, is: 0219 + First, by drawID 0220 + Then, by catalog (i.e. unnamedstars.dat / Tycho-2 / USNO-NOMAD-1e8) 0221 + Then, by trixel (only those trixels that are on-screen are considered) 0222 + Finally, by magnitude 0223 0224 When StarBlockFactory wants to re-use a StarBlock, it first verifies 0225 that the drawID is outdated. Then, it calls 0226 StarBlockList::releaseBlock() on the parent StarBlockList and thus 0227 orphans the StarBlock. The orphaned StarBlock is handed over to the 0228 new StarBlockList which adopts it. 0229 0230 Thus, KStars initially allocates new StarBlocks until a saturation 0231 point is reached, where there are enough StarBlocks to keep 0232 recycling. Sagittarius has the maximum number of stars, and setting 0233 the focus on Sagittarius will usually lead to saturation (where KStars 0234 consumes 200-odd MB of memory with USNO-NOMAD-1e8), and this memory is 0235 not freed till KStars exits. A possible extension would be to free 0236 StarBlocks lazily after their drawID's get really outdated, so that 0237 the memory surge is temporary. 0238 0239 \subsection Files Star Catalog Files 0240 Star catalogs are stored in the format described in \ref BinaryFormat Binary Format section. 0241 0242 Star catalog files were created by first taking ASCII data and putting 0243 them into MySQL database tables and then dumped in a sorted manner 0244 into the catalog files. The tools used are in ../data/tools. The ASCII 0245 originals from public domain sources are available with Akarsh Simha 0246 and Jason Harris, or with the US Naval Observatory itself. 0247 0248 Stars in the catalog files are first ordered by trixel (the "Index" 0249 parameter in binary file format) and then ordered by magnitude (brightest first) within each trixel. 0250 0251 KStars uses two HTM levels: 0252 + Level 3: 512 <a href="http://www.skyserver.org/htm/">trixels</a> are used for the following data files: 0253 -# default namedstars.dat 0254 -# default unnnamedstar.dat: Togeather with #1, they make up all stars up to ~8th magnitude 0255 -# Downloadable Tycho-2 deepstars.dat, all stars up to magnitude ~12th 0256 + Level 6: 8192 trixels 0257 -# Downloadable USNO Nomad USNO-NOMAD-1e8.dat, all stars up to magnitude ~16th 0258 0259 \subsection ProperMotion Proper Motion 0260 All star data in KStars has first order proper motion rates (called 0261 "dRA" and "dDec" or "pmRA" and "pmDec"), which are used to correct for 0262 proper motion. 0263 0264 This leads to a problem in the case of dynamic stars, as a star may 0265 cross over from one trixel to another trixel due to proper motion, in 0266 which case it might not be drawn despite its corrected coordinates 0267 being on-screen. 0268 0269 To solve this, stars are duplicated in all trixels that they will pass 0270 through in a span of +/-10,000 years from the epoch. StarObject has 0271 some commented code that can be used to track the position of a 0272 star. [Maybe this should be turned into a feature in future] 0273 0274 TODO: Describe details like the 25 arcminute "safety" margin. 0275 0276 \section HDCatalog Henry-Draper Catalog Numbers 0277 StarObject allows for a Henry-Draper catalog number to be associated 0278 with a star. KStars allows for both static and dynamic stars to have 0279 an associated catalog number. This is currently used for the 0280 Henry-Draper number, although it could be extended to other catalogs. 0281 0282 Both static and dynamic stars from Tycho-2 appear in the HD 0283 catalog. To find dynamic stars by HD number, a downloadable add-on 0284 "Henry Draper Index" is available. This file contains a list of 4-byte 0285 offsets in sequential order of HD number. These offsets tell KStars 0286 where to find the star in the Tycho-2 catalog binary data file. See 0287 StarComponent::findByHDIndex() for details. See \ref HDIndex HDIndex section for details about the format followed 0288 by the Henry-Draper index file. 0289 0290 FIXME: The information above is not entirely correct. Star catalogs also include 4-byte HD parameters. Needs update. 0291 0292 \section BinaryFormat Binary Format 0293 0294 Stars data are stored in binary format to speed up reading and loading data into memory. There are a number of tools in the data/tools directory that parses the original ASCII data files and convert them to a KStars compatible binary format. 0295 0296 \subsection Header The Header 0297 \subsubsection Preamble Preamble 0298 The preamble consists of the following: 0299 0300 * A 124 byte-long string containing human-readable information about 0301 the file 0302 0303 * A 2 byte-long endinanness indicator field, preinitialized to 'KS' 0304 (0x4B53) on the host machine 0305 0306 The purpose of the endianness indicator is to make the file portable 0307 across machines of different endianness. A machine on which the 0308 endianness indicator field is read as 'SK' instead of 'KS' is of 0309 different endinanness from the machine on which the file was 0310 generated, and hence byteswapping must be performed. 0311 0312 * A 1 byte-long unsigned integer for the version of the binary format structure. 0313 0314 The header section is therefore 127 bytes long. The header range in the binary file is from address 0x0000 to 0x007E 0315 0316 \subsubsection FieldDescriptor Field Descriptor 0317 The field descriptor describes the various fields used in the latter 0318 half of the data region. The field descriptor consists of the 0319 following: 0320 0321 * A 2 byte-long unsigned integer, indicating the number of fields per 0322 record 0323 0324 * A set of entries describing the fields, amounting to the number 0325 previously mentioned, each consisting of: 0326 0327 - A 10 byte-long character array, providing a human-readable name 0328 for the field 0329 0330 - A 1 byte-long integer carrying the size of the field in bytes 0331 0332 - A 1 byte-long unsigned integer carrying the data type (see 0333 Appendix A) 0334 0335 - A 4 byte-long integer storing a scale factor to divide the 0336 contents of the associated field by, to interpret it 0337 correctly. This is used for storing fixed-point fields. (Eg: A 0338 fixed-point number with 2 decimal places would have a scale 0339 factor of 100) 0340 0341 The set of entries is read directly into dataElement structure and byte swapping is performed if needed. 0342 0343 Most of KStars star binary files use 11 fields (0x0B), each is 16 bytes long (0x10). Therefore, the field descriptor 0344 total bytes count is 2 + 11 * 16 = 178 bytes. The field descriptor range in the binary file is 0x007F to 0x0130 0345 0346 \subsubsection IndexTable Index Table 0347 The format permits an index on one parameter. This index is the trixel ID. 0348 The parameter is to be represented by 4-bytes (eg: A running index from 0 to 4,294,967,295). The index table consists of the following: 0349 0350 * A 4 byte unsigned integer indicating the number of index entries: Usually 512 (0x0200) or 8192 (0x2000) 0351 0352 * Index table entries, each consisting of: 0353 0354 - A 4 byte-long unsigned integer parameter, which is the index: 0 to 511 for HTM level 3, and 0 to 8191 for HTM Level 6 0355 0356 - A 4 byte-long unsigned integer, storing the offset of the first record with this index parameter in the file 0357 0358 - A 4 byte-long unsigned integer, storing the number of records under this index parameter. 0359 0360 Since multiple stars can share the same trixel ID, the number of records refer to the number of the stars enclosed within the trixel. 0361 0362 The index table total byte count depends on the index entries: 0363 + HTM Level 3: Total bytes = 4 bytes + (512 indexes * 12 bytes) = 6148 bytes (0x1804) 0364 The index table range in the binary file is 0x0131 to 0x1934 0365 + HTM Level 6: Total bytes = 4 bytes + (8192 indexes * 12 bytes) = 98308 bytes (0x18004) 0366 The index table range in the binary file is 0x0131 to 0x18134 0367 0368 \subsection TheData The Data 0369 0370 \subsubsection ExpansionFields Expansion Fields 0371 Certain specific information about the contents of the field may be 0372 added here. The contents could be specific to each application, and 0373 could be empty. For KStars star data files, the entries in this 0374 region are: 0375 0376 + Faint magnitude limit * 100, stored as a 16-bit integer 0377 0378 + HTM Level for this file, stored as a 8-bit integer. The 0379 convention followed is that "N0000" would belong to a HTMesh of 0380 level 3. 0381 0382 + Maximum Stars per Trixel, stored as a 2-byte unsigned integer. 0383 0384 The expansion field total bytes are (2 + 1 + 2) 5 bytes long. 0385 0386 + HTM Level 3: The range is from 0x1935 to (0x1935 + 0x5) = 0x1939 0387 + HTM Level 3: The range is from 0x18135 to (0x18135 + 0x5) = 0x18139 0388 0389 \subsubsection DataRecords Data Records 0390 This region starts at the offset pointed out in the first entry of 0391 the index table. The data consists of a series of records, the 0392 details of whose fields (assumed to be placed continuously, without 0393 any gaps) are as described in the field descriptor in the header. 0394 0395 + HTM Level 3: Data starts at 0x193A 0396 + HTM Level 6: Data starts at 0x1813A 0397 0398 NOTE: KStars _overrides_ the above defined convention for performance 0399 gains and ease of programming in the star names file, where records 0400 are stored as single blocks of the 40 bytes long StarComponent::starName structure. 0401 0402 \section HDIndex Henry Draper Indexing 0403 The index file used to store the Henry Draper catalog indexes for KStars is just a list of 4-byte long offsets (to be treated as signed 32-bit 0404 integers ) describing the position of the Henry Draper stars' records in order, in the binary data files. 0405 0406 If the offset is negative, it indicates that the star is in the shallow star file and not in the Tycho-2 deep star add on. The actual 0407 offset in this case is just the absolute value of the offset. The first four bytes in the index file correspond to the offset of the 0408 star HD000001 in the data files, and so on. 0409 0410 \section Credits Credits 0411 Most of the memory layout and machinery outline described above was 0412 the brainchild of James Bowlin and it was implemented in code by 0413 Akarsh Simha. Jason Harris helped with the catalog data and also 0414 mentored Akarsh along with James. Some of the parsing tools in the 0415 kstars/data/tools directory have code due to James. 0416 0417 \author Akarsh Simha 0418 \author Jasem Mutlaq 0419 */