PCL
GaiaDatabaseFile.h
Go to the documentation of this file.
1 // ____ ______ __
2 // / __ \ / ____// /
3 // / /_/ // / / /
4 // / ____// /___ / /___ PixInsight Class Library
5 // /_/ \____//_____/ PCL 2.7.0
6 // ----------------------------------------------------------------------------
7 // pcl/GaiaDatabaseFile.h - Released 2024-06-18T15:48:54Z
8 // ----------------------------------------------------------------------------
9 // This file is part of the PixInsight Class Library (PCL).
10 // PCL is a multiplatform C++ framework for development of PixInsight modules.
11 //
12 // Copyright (c) 2003-2024 Pleiades Astrophoto S.L. All Rights Reserved.
13 //
14 // Redistribution and use in both source and binary forms, with or without
15 // modification, is permitted provided that the following conditions are met:
16 //
17 // 1. All redistributions of source code must retain the above copyright
18 // notice, this list of conditions and the following disclaimer.
19 //
20 // 2. All redistributions in binary form must reproduce the above copyright
21 // notice, this list of conditions and the following disclaimer in the
22 // documentation and/or other materials provided with the distribution.
23 //
24 // 3. Neither the names "PixInsight" and "Pleiades Astrophoto", nor the names
25 // of their contributors, may be used to endorse or promote products derived
26 // from this software without specific prior written permission. For written
27 // permission, please contact info@pixinsight.com.
28 //
29 // 4. All products derived from this software, in any form whatsoever, must
30 // reproduce the following acknowledgment in the end-user documentation
31 // and/or other materials provided with the product:
32 //
33 // "This product is based on software from the PixInsight project, developed
34 // by Pleiades Astrophoto and its contributors (https://pixinsight.com/)."
35 //
36 // Alternatively, if that is where third-party acknowledgments normally
37 // appear, this acknowledgment must be reproduced in the product itself.
38 //
39 // THIS SOFTWARE IS PROVIDED BY PLEIADES ASTROPHOTO AND ITS CONTRIBUTORS
40 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
41 // TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PLEIADES ASTROPHOTO OR ITS
43 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
44 // EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, BUSINESS
45 // INTERRUPTION; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; AND LOSS OF USE,
46 // DATA OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
47 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
49 // POSSIBILITY OF SUCH DAMAGE.
50 // ----------------------------------------------------------------------------
51 
52 #ifndef __PCL_GaiaDatabaseFile_h
53 #define __PCL_GaiaDatabaseFile_h
54 
56 
57 #include <pcl/Defs.h>
58 
59 #include <pcl/Flags.h>
60 #include <pcl/MetaParameter.h> // pcl_bool
61 #include <pcl/StarDatabaseFile.h>
62 
63 namespace pcl
64 {
65 
66 // ----------------------------------------------------------------------------
67 
125 namespace GaiaStarFlag
126 {
127  enum mask_type
128  {
129  NoPM = 0x00000001,
130  NoGBPMag = 0x00000002,
131  NoGRPMag = 0x00000004,
132  LackingData = 0x00000007,
133 
134  GoldRA = 0x00000010,
135  GoldDec = 0x00000020,
136  GoldPMRA = 0x00000040,
137  GoldPMDec = 0x00000080,
138 
139  SilverRA = 0x00000100,
140  SilverDec = 0x00000200,
141  SilverPMRA = 0x00000400,
142  SilverPMDec = 0x00000800,
143 
144  BronzeRA = 0x00001000,
145  BronzeDec = 0x00002000,
146  BronzePMRA = 0x00004000,
147  BronzePMDec = 0x00008000,
148 
149  GoldGMag = 0x00010000,
150  GoldGBPMag = 0x00020000,
151  GoldGRPMag = 0x00040000,
152  GoldParx = 0x00080000,
153 
154  SilverGMag = 0x00100000,
155  SilverGBPMag = 0x00200000,
156  SilverGRPMag = 0x00400000,
157  SilverParx = 0x00800000,
158 
159  BronzeGMag = 0x01000000,
160  BronzeGBPMag = 0x02000000,
161  BronzeGRPMag = 0x04000000,
162  BronzeParx = 0x08000000,
163 
164  BPRPExcess = 0x10000008,
165  BPRPExcessHigh = 0x20000000,
166 
167  GoldAstrometry = 0x000800F0,
168  SilverAstrometry = 0x00800F00,
169  BronzeAstrometry = 0x0800F000,
170 
171  GoldPhotometry = 0x00070000,
172  SilverPhotometry = 0x00700000,
173  BronzePhotometry = 0x07000000
174  };
175 }
176 
177 // ----------------------------------------------------------------------------
178 
186 struct PCL_CLASS GaiaStarDataBase
187 {
188  double ra = 0;
189  double dec = 0;
190  float parx = 0;
191  float pmra = 0;
192  float pmdec = 0;
193  float magG = 0;
194  float magBP = 0;
195  float magRP = 0;
196  uint32 flags = 0u;
197 };
198 
206 struct PCL_CLASS GaiaStarData : public GaiaStarDataBase
207 {
213 };
214 
215 // ----------------------------------------------------------------------------
216 
223 struct GaiaSearchData : public XPSD::SearchData<GaiaStarData>
224 {
239 };
240 
241 // ----------------------------------------------------------------------------
242 
314 {
315 public:
316 
323  GaiaDatabaseFile() = default;
324 
335  GaiaDatabaseFile( const String& filePath )
336  : StarDatabaseFile( filePath )
337  {
338  static_assert( sizeof( EncodedStarData ) == 32, "Invalid sizeof( GaiaDatabaseFile::EncodedStarData )" );
339  static_assert( sizeof( EncodedStarSPData ) == 41, "Invalid sizeof( GaiaDatabaseFile::EncodedStarSPData )" );
340  if ( Metadata().databaseIdentifier == "GaiaDR3" )
341  m_dr = "DR3";
342  else if ( Metadata().databaseIdentifier == "GaiaDR3SP" )
343  {
344  m_dr = "DR3";
345  m_hasSpectrumData = true;
346  // spectrumStart=<f>,spectrumStep=<f>,spectrumCount=<n>,spectrumBits=<n>
347  if ( m_parameters.IsEmpty() )
348  throw Error( "Missing parameters Data element attribute: " + filePath );
349  StringList tokens;
350  m_parameters.Break( tokens, ',' );
351  for ( const String& token : tokens )
352  {
353  StringList items;
354  token.Break( items, '=' );
355  if ( items.Length() != 2 )
356  throw Error( "Invalid parameter specification '" + token + "': " + filePath );
357  if ( items[0] == "spectrumStart" )
358  m_spectrumStart = items[1].ToFloat();
359  else if ( items[0] == "spectrumStep" )
360  m_spectrumStep = items[1].ToFloat();
361  else if ( items[0] == "spectrumCount" )
362  m_spectrumCount = items[1].ToInt();
363  else if ( items[0] == "spectrumBits" )
364  m_spectrumBits = items[1].ToInt();
365  }
366  if ( m_spectrumStart <= 0 || m_spectrumStep <= 0 || m_spectrumCount <= 0 ||
367  m_spectrumBits != 8 && m_spectrumBits != 16 )
368  throw Error( "Invalid parameters attribute value '" + m_parameters + "': " + filePath );
369  m_spectrumRange = (1 << m_spectrumBits) - 1;
370  }
371  else if ( Metadata().databaseIdentifier == "GaiaEDR3" )
372  m_dr = "EDR3";
373  else if ( Metadata().databaseIdentifier == "GaiaDR2" )
374  {
375  m_dr = "DR2";
376  StringList tokens;
377  Metadata().databaseVersion.Break( tokens, '.' );
378  // Make sure we reject an unsupported DR2 version older than 1.0.2
379  if ( tokens.Length() < 3 || tokens[0].ToInt() < 1 || tokens[1].ToInt() < 0 || tokens[2].ToInt() < 2 )
380  throw Error( "Unsupported Gaia DR2 database version '"
381  + Metadata().databaseVersion + "': " + filePath );
382  }
383  else
384  throw Error( "Invalid or unsupported Gaia database file with unknown identifier '"
385  + Metadata().databaseIdentifier + "': " + filePath );
386  }
387 
392 
397  GaiaDatabaseFile( const GaiaDatabaseFile& ) = delete;
398 
404 
410  const IsoString& DataRelease() const
411  {
412  return m_dr;
413  }
414 
419  bool HasMeanSpectrumData() const
420  {
421  return m_hasSpectrumData;
422  }
423 
431  float SpectrumStart() const
432  {
433  return m_spectrumStart;
434  }
435 
443  float SpectrumStep() const
444  {
445  return m_spectrumStep;
446  }
447 
455  int SpectrumCount() const
456  {
457  return m_spectrumCount;
458  }
459 
467  int SpectrumBits() const
468  {
469  return m_spectrumBits;
470  }
471 
504  void Search( GaiaSearchData& data ) const
505  {
506  ElapsedTime T;
507  for ( const XPSD::IndexTree& tree : m_index )
508  tree.Search( data.centerRA, data.centerDec, data.radius, &data );
509  data.timeTotal += T();
510  }
511 
512 private:
513 
514  IsoString m_dr; // data release, one of "DR2", "EDR3", "DR3"
515  bool m_hasSpectrumData = false; // with BP/RP mean spectrum data?
516  float m_spectrumStart = 0; // nm
517  float m_spectrumStep = 0; // nm
518  int m_spectrumCount = 0;
519  int m_spectrumBits = 0; // 8 | 16
520  float m_spectrumRange = 0; // (1 << m_spectrumBits) - 1
521 
522 #pragma pack(push, 1)
523 
524  /*
525  * Encoded star record (32 bytes uncompressed).
526  */
527  struct EncodedStarData
528  {
529  // Projected coordinates relative to the origin of the parent quadtree
530  // node, in 0.002 mas units.
531  uint32 dx;
532  uint32 dy;
533  // Parallax in mas units.
534  float parx;
535  // Proper motions, mas/yr.
536  float pmra;
537  float pmdec;
538  // Mean magnitudes in 0.001 mag units, encoded as (mag + 1.5)*1000.
539  uint16 magG;
540  uint16 magBP;
541  uint16 magRP;
542  // Right ascension correction for high declinations, in 0.01 mas units.
543  int16 dra;
544  // Data availability and quality flags.
545  uint32 flags;
546  };
547 
548  /*
549  * Encoded star record with mean spectrum data.
550  * Uncompressed size in bytes: 40 + (m_spectrumBits/8)*(m_spectrumCount + (m_spectrumCount & 1)).
551  */
552  struct EncodedStarSPData : public EncodedStarData
553  {
554  float fluxMin;
555  float fluxMul; // (fluxMax - fluxMin)/(2**m_spectrumBits - 1)
556  uint8 flux[ 1 ];
557  };
558 
559  constexpr size_type EncodedStarSPDataSize() const
560  {
561  return sizeof( EncodedStarSPData ) - 1 + (m_spectrumBits >> 3)*(m_spectrumCount + (m_spectrumCount & 1));
562  }
563 
564 #pragma pack(pop)
565 
566  void GetEncodedData( const ByteArray& data, const XPSD::IndexTree& tree, const XPSD::IndexNode& node, void* searchData ) const override
567  {
568  ElapsedTime T;
569  GaiaSearchData* search = reinterpret_cast<GaiaSearchData*>( searchData );
570  double searchRadius = Rad( search->radius );
571  int itemSize = m_hasSpectrumData ? EncodedStarSPDataSize() : sizeof( EncodedStarData );
572  int count = int( data.Size() / itemSize );
573  int matchCount = 0;
574  for ( int i = 0; i < count; ++i )
575  {
576  const EncodedStarData* S = reinterpret_cast<const EncodedStarData*>( data.Begin() + i*itemSize );
577  if ( search->requiredFlags == 0 || (S->flags & search->requiredFlags) == search->requiredFlags )
578  if ( search->inclusionFlags == 0 || (S->flags & search->inclusionFlags) != 0 )
579  if ( search->exclusionFlags == 0 || (S->flags & search->exclusionFlags) == 0 )
580  {
581  float magG = 0.001*S->magG - 1.5;
582  if ( magG >= search->magnitudeLow )
583  if ( magG <= search->magnitudeHigh )
584  {
585  double x = node.x0 + double( S->dx )/3600/1000/500;
586  double y = node.y0 + double( S->dy )/3600/1000/500;
587  GaiaStarData star;
588  tree.Unproject( star.ra, star.dec, x, y );
589  if ( unlikely( S->dra != 0 ) )
590  {
591  star.ra += double( S->dra )/3600/1000/100;
592  if ( star.ra < 0 )
593  star.ra += 360;
594  else if ( star.ra >= 360 )
595  star.ra -= 360;
596  }
597  if ( Distance( search->centerRA, search->centerDec, star.ra, star.dec ) < searchRadius )
598  {
599  ++matchCount;
600 
601  if ( search->stars.Length() < size_type( search->sourceLimit ) )
602  {
603  star.parx = S->parx;
604  star.pmra = S->pmra;
605  star.pmdec = S->pmdec;
606  star.magG = magG;
607  star.magBP = 0.001*S->magBP - 1.5;
608  star.magRP = 0.001*S->magRP - 1.5;
609  star.flags = S->flags;
610 
611  if ( m_hasSpectrumData )
612  {
613  const EncodedStarSPData* SS = static_cast<const EncodedStarSPData*>( S );
614  star.flux = FVector( m_spectrumCount );
615  if ( search->photonFluxUnits )
616  {
617  for ( int j = 0; j < m_spectrumCount; ++j )
618  star.flux[j] = (SS->flux[j]*SS->fluxMul + SS->fluxMin) * (m_spectrumStart + j*m_spectrumStep)/1.602e-19/1.239979e-3;
619  if ( search->normalizeSpectrum )
620  star.flux /= star.flux.MaxComponent();
621  }
622  else
623  {
624  if ( search->normalizeSpectrum )
625  for ( int j = 0; j < m_spectrumCount; ++j )
626  star.flux[j] = SS->flux[j]/m_spectrumRange;
627  else
628  for ( int j = 0; j < m_spectrumCount; ++j )
629  star.flux[j] = SS->flux[j]*SS->fluxMul + SS->fluxMin;
630  }
631  }
632 
633  search->stars << star;
634  }
635  else
636  ++search->excessCount;
637  }
638  }
639  }
640  }
641 
642  search->rejectCount += count - matchCount;
643  search->timeDecode += T();
644  }
645 
646  friend class GaiaDR2DatabaseFileGenerator;
647  friend class GaiaEDR3DatabaseFileGenerator;
648  friend class GaiaDR3DatabaseFileGenerator;
649  friend class GaiaDR3SPDatabaseFileGenerator;
650 };
651 
652 // ----------------------------------------------------------------------------
653 
654 } // pcl
655 
656 #endif // __PCL_GaiaDatabaseFile_h
657 
658 // ----------------------------------------------------------------------------
659 // EOF pcl/GaiaDatabaseFile.h - Released 2024-06-18T15:48:54Z
size_type Length() const noexcept
Definition: Array.h:266
Dynamic array of 8-bit unsigned integers.
High-resolution time stamp.
Definition: ElapsedTime.h:131
A simple exception with an associated error message.
Definition: Exception.h:239
32-bit floating point real vector.
Gaia catalog star database file (XPSD format).
GaiaDatabaseFile(const GaiaDatabaseFile &)=delete
bool HasMeanSpectrumData() const
float SpectrumStart() const
GaiaDatabaseFile(const String &filePath)
GaiaDatabaseFile()=default
float SpectrumStep() const
GaiaDatabaseFile & operator=(GaiaDatabaseFile &&)=default
const IsoString & DataRelease() const
void Search(GaiaSearchData &data) const
bool IsEmpty() const noexcept
Definition: String.h:818
Generic vector of arbitrary length.
Definition: Vector.h:107
Eight-bit string (ISO/IEC-8859-1 or UTF-8 string)
Definition: String.h:5425
Point source and star catalog database files (XPSD format).
const XPSD::Metadata & Metadata() const
Unicode (UTF-16) string.
Definition: String.h:8113
A first-class data type that can be safely used to implement Boolean process parameters on all suppor...
constexpr T Rad(T x) noexcept
Definition: Math.h:1894
unsigned short uint16
Definition: Defs.h:654
unsigned char uint8
Definition: Defs.h:642
signed short int16
Definition: Defs.h:648
unsigned int uint32
Definition: Defs.h:666
size_t size_type
Definition: Defs.h:609
PCL root namespace.
Definition: AbstractImage.h:77
Data items and parameters for Gaia catalog search operations.
Star data base structure for Gaia catalog search operations.
Star data structure for Gaia catalog search operations.
String databaseIdentifier
The unique identifier of the database this file belongs to.
String databaseVersion
The version of the database this file belongs to.
double radius
Field radius in degrees (search parameter).
double centerDec
Field center declination coordinate in degrees (search parameter).
double centerRA
Field center right ascension coordinate in degrees (search parameter).
double timeTotal
Total search time in seconds (output data).
Data items and parameters for catalog search operations.