File indexing completed on 2024-04-28 03:42:51

0001 /*
0002     SPDX-FileCopyrightText: 2008 Akarsh Simha <akarshsimha@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include <stdio.h>
0008 #include <stdlib.h>
0009 #include <math.h>
0010 #include <sys/types.h>
0011 #include <string.h>
0012 #include "byteorder.h"
0013 
0014 #define HTM_LEVEL        3
0015 #define INDEX_ENTRY_SIZE 12
0016 
0017 #include "binfile.h"
0018 
0019 /*
0020  * struct to store star data, to be written in this format, into the binary file.
0021  */
0022 
0023 typedef struct starData
0024 {
0025     int32_t RA;
0026     int32_t Dec;
0027     int32_t dRA;
0028     int32_t dDec;
0029     int32_t parallax;
0030     int32_t HD;
0031     int16_t mag;
0032     int16_t bv_index;
0033     char spec_type[2];
0034     char flags;
0035     char unused;
0036 } starData;
0037 
0038 dataElement de[100];
0039 u_int16_t nfields;
0040 long index_offset, data_offset;
0041 char byteswap;
0042 u_int32_t ntrixels;
0043 
0044 /*
0045  * Does byteswapping for starData structures
0046  */
0047 void bswap_stardata(starData *stardata)
0048 {
0049     stardata->RA       = bswap_32(stardata->RA);
0050     stardata->Dec      = bswap_32(stardata->Dec);
0051     stardata->dRA      = bswap_32(stardata->dRA);
0052     stardata->dDec     = bswap_32(stardata->dDec);
0053     stardata->parallax = bswap_32(stardata->parallax);
0054     stardata->HD       = bswap_32(stardata->HD);
0055     stardata->mag      = bswap_16(stardata->mag);
0056     stardata->bv_index = bswap_16(stardata->bv_index);
0057 }
0058 
0059 int verifyIndexValidity(FILE *f)
0060 {
0061     int i;
0062     u_int32_t trixel;
0063     u_int32_t offset;
0064     u_int32_t prev_offset;
0065     u_int32_t nrecs;
0066     u_int32_t prev_nrecs;
0067     unsigned int nerr;
0068 
0069     fprintf(stdout, "Performing Index Table Validity Check...\n");
0070     fprintf(stdout, "Assuming that index starts at %X\n", ftell(f));
0071     index_offset = ftell(f);
0072 
0073     prev_offset = 0;
0074     prev_nrecs  = 0;
0075     nerr        = 0;
0076 
0077     for (i = 0; i < ntrixels; ++i)
0078     {
0079         if (!fread(&trixel, 4, 1, f))
0080         {
0081             fprintf(stderr, "Table truncated before expected! Read i = %d records so far\n", i);
0082             +nerr;
0083             break;
0084         }
0085         if (byteswap)
0086             trixel = bswap_32(trixel);
0087         if (trixel >= ntrixels)
0088         {
0089             fprintf(stderr, "Trixel number %u is greater than the expected number of trixels %u\n", trixel, ntrixels);
0090             ++nerr;
0091         }
0092         if (trixel != i)
0093         {
0094             fprintf(stderr, "Found trixel = %d, while I expected number = %d\n", trixel, i);
0095             ++nerr;
0096         }
0097         fread(&offset, 4, 1, f);
0098         if (byteswap)
0099             offset = bswap_32(offset);
0100         fread(&nrecs, 4, 1, f);
0101         if (byteswap)
0102             nrecs = bswap_32(nrecs);
0103         if (prev_offset != 0 && prev_nrecs != (-prev_offset + offset) / sizeof(starData))
0104         {
0105             fprintf(stderr, "Expected %u  = (%X - %x) / %d records, but found %u, in trixel %d\n",
0106                     (offset - prev_offset) / sizeof(starData), offset, prev_offset, sizeof(starData), nrecs, trixel);
0107             ++nerr;
0108         }
0109         prev_offset = offset;
0110         prev_nrecs  = nrecs;
0111     }
0112 
0113     data_offset = ftell(f);
0114 
0115     if (nerr)
0116     {
0117         fprintf(stderr, "ERROR ;-): The index seems to have %u errors\n", nerr);
0118     }
0119     else
0120     {
0121         fprintf(stdout, "Index verified. PASSED.\n");
0122     }
0123 }
0124 
0125 /**
0126  *This method ensures that the data part of the file is sane. It ensures that there are no jumps in magnitude etc.
0127  */
0128 int verifyStarData(FILE *f)
0129 {
0130     int16_t faintMag;
0131     int8_t HTM_Level;
0132     u_int16_t MSpT;
0133     int16_t realFaintMag = -500;
0134     u_int16_t realMSpT;
0135     u_int32_t nstars;
0136     u_int32_t offset;
0137 
0138     int trixel, i;
0139     int nerr_trixel;
0140     int nerr;
0141 
0142     starData data;
0143     int16_t mag;
0144 
0145     fprintf(stdout, "Assuming that the data starts at %ld\n", ftell(f));
0146     fread(&faintMag, 2, 1, f);
0147     fprintf(stdout, "Faint Magnitude Limit: %f\n", faintMag / 100.0);
0148     fread(&HTM_Level, 1, 1, f);
0149     fprintf(stdout, "HTMesh Level: %d\n", HTM_Level);
0150     if (HTM_Level != HTM_LEVEL)
0151     {
0152         fprintf(stderr,
0153                 "ERROR: HTMesh Level in file (%d) and HTM_LEVEL in program (%d) differ. Please set the define "
0154                 "directive for HTM_LEVEL correctly and rebuild\n.",
0155                 HTM_Level, HTM_LEVEL);
0156         return 0;
0157     }
0158     fread(&MSpT, 2, 1, f);
0159 
0160     mag  = -500;
0161     nerr = 0;
0162 
0163     // Scan the file for magnitude jumps, etc.
0164     realMSpT = 0;
0165     for (trixel = 0; trixel < ntrixels; ++trixel)
0166     {
0167         mag         = -500;
0168         nerr_trixel = 0;
0169         fprintf(stdout, "Checking trixel #%d: ", trixel);
0170         fseek(f, index_offset + trixel * INDEX_ENTRY_SIZE + 4, SEEK_SET);
0171         fread(&offset, 4, 1, f);
0172         fread(&nstars, 4, 1, f);
0173         if (nstars > realMSpT)
0174             realMSpT = nstars;
0175         fseek(f, offset, SEEK_SET);
0176         for (i = 0; i < nstars; ++i)
0177         {
0178             fread(&data, sizeof(starData), 1, f);
0179             if (byteswap)
0180                 bswap_stardata(&data);
0181             if (mag != -500 && ((data.mag - mag) > 20 && mag < 1250) || data.mag < mag)
0182             { // TODO: Make sensible magnitude limit (1250) user specifiable
0183                 // TODO: Enable byteswapping
0184                 fprintf(stderr, "\n\tEncountered jump of %f at star #%d in trixel %d from %f to %f.",
0185                         (data.mag - mag) / 100.0, i, trixel, mag / 100.0, data.mag / 100.0);
0186                 ++nerr_trixel;
0187             }
0188             mag = data.mag;
0189             if (mag > realFaintMag)
0190             {
0191                 realFaintMag = mag;
0192             }
0193             if (mag > 1500)
0194                 fprintf(stderr, "Magnitude > 15.00 ( = %f ) in trixel %d\n", mag / 100.0, trixel);
0195         }
0196         if (nerr_trixel > 0)
0197             fprintf(stderr, "\n * Encountered %d magnitude jumps in trixel %d\n", nerr_trixel, trixel);
0198         else
0199             fprintf(stdout, "Successful\n");
0200         nerr += nerr_trixel;
0201     }
0202     if (MSpT != realMSpT)
0203     {
0204         fprintf(stderr, "ERROR: MSpT according to file = %d, but turned out to be %d\n", MSpT, realMSpT);
0205         nerr++;
0206     }
0207     if (realFaintMag != faintMag)
0208     {
0209         fprintf(stderr, "ERROR: Faint Magnitude according to file = %f, but turned out to be %f\n", faintMag / 100.0,
0210                 realFaintMag / 100.0);
0211         nerr++;
0212     }
0213     if (nerr > 0)
0214     {
0215         fprintf(stderr, "ERROR: Exiting with %d errors\n", nerr);
0216         return 0;
0217     }
0218     fprintf(stdout, "Data validation success!\n");
0219     return 1;
0220 }
0221 
0222 void readStarList(FILE *f, u_int32_t trixel, FILE *names)
0223 {
0224     long offset;
0225     long n;
0226     int i;
0227     u_int32_t nrecs;
0228     u_int32_t trix;
0229     char bayerName[8];
0230     char longName[32];
0231     starData data;
0232 
0233     printf("Reading star list for trixel %d\n", trixel);
0234     rewind(f);
0235     offset = index_offset +
0236              trixel * INDEX_ENTRY_SIZE; // CAUTION: Change if the size of each entry in the index table changes
0237     fseek(f, offset, SEEK_SET);
0238     fread(&trix, 4, 1, f);
0239     if (byteswap)
0240         trix = bswap_32(trix);
0241     if (trix != trixel)
0242     {
0243         fprintf(
0244             stderr,
0245             "ERROR: Something fishy in the index. I guessed that %d would be here, but instead I find %d. Aborting.\n",
0246             trixel, trix);
0247         return;
0248     }
0249     fread(&offset, 4, 1, f);
0250     if (byteswap)
0251         offset = bswap_32(offset);
0252     fread(&nrecs, 4, 1, f);
0253     if (byteswap)
0254         nrecs = bswap_32(nrecs);
0255 
0256     if (fseek(f, offset, SEEK_SET))
0257     {
0258         fprintf(stderr,
0259                 "ERROR: Could not seek to position %X in the file. The file is either truncated or the indexes are "
0260                 "bogus.\n",
0261                 offset);
0262         return;
0263     }
0264     printf("Data for trixel %d starts at offset 0x%X and has %d records\n", trixel, offset, nrecs);
0265 
0266     for (i = 0; i < nrecs; ++i)
0267     {
0268         offset = ftell(f);
0269         n      = (offset - data_offset) / sizeof(starData);
0270         fread(&data, sizeof(starData), 1, f);
0271         if (byteswap)
0272             bswap_stardata(&data);
0273         printf("Entry #%d\n", i);
0274         printf("\tRA = %f\n", data.RA / 1000000.0);
0275         printf("\tDec = %f\n", data.Dec / 100000.0);
0276         printf("\tdRA/dt = %f\n", data.dRA / 10.0);
0277         printf("\tdDec/dt = %f\n", data.dDec / 10.0);
0278         printf("\tParallax = %f\n", data.parallax / 10.0);
0279         printf("\tHD Catalog # = %lu\n", data.HD);
0280         printf("\tMagnitude = %f\n", data.mag / 100.0);
0281         printf("\tB-V Index = %f\n", data.bv_index / 100.0);
0282         printf("\tSpectral Type = %c%c\n", data.spec_type[0], data.spec_type[1]);
0283         printf("\tHas a name? %s\n", ((data.flags & 0x01) ? "Yes" : "No"));
0284         /*
0285           if(data.flags & 0x01 && names) {
0286           fseek(names, n * (32 + 8) + 0xA0, SEEK_SET);
0287           fread(bayerName, 8, 1, names);
0288           fread(longName, 32, 1, names);
0289           printf("\t\tBayer Designation = %s\n", bayerName);
0290           printf("\t\tLong Name = %s\n", longName);
0291           }
0292         */
0293         printf("\tMultiple Star? %s\n", ((data.flags & 0x02) ? "Yes" : "No"));
0294         printf("\tVariable Star? %s\n", ((data.flags & 0x04) ? "Yes" : "No"));
0295     }
0296 }
0297 
0298 /**
0299  *@short  Read the KStars binary file header and display its contents
0300  *@param f  Binary file to read from
0301  *@returns  non-zero if successful, zero if not
0302  */
0303 
0304 int readFileHeader(FILE *f)
0305 {
0306     int i;
0307     int16_t endian_id;
0308     char ASCII_text[125];
0309     u_int8_t version_no;
0310 
0311     if (f == NULL)
0312         return 0;
0313 
0314     fread(ASCII_text, 124, 1, f);
0315     ASCII_text[124] = '\0';
0316     printf("%s", ASCII_text);
0317 
0318     fread(&endian_id, 2, 1, f);
0319     if (endian_id != 0x4B53)
0320     {
0321         fprintf(stdout, "Byteswapping required\n");
0322         byteswap = 1;
0323     }
0324     else
0325     {
0326         fprintf(stdout, "Byteswapping not required\n");
0327         byteswap = 0;
0328     }
0329 
0330     fread(&version_no, 1, 1, f);
0331     fprintf(stdout, "File version number: %d\n", version_no);
0332     fread(&nfields, 2, 1, f);
0333     if (byteswap)
0334         nfields = bswap_16(nfields);
0335     fprintf(stdout, "%d fields reported\n", nfields);
0336 
0337     for (i = 0; i < nfields; ++i)
0338     {
0339         fread(&(de[i]), sizeof(struct dataElement), 1, f);
0340         if (byteswap)
0341             de->scale = bswap_32(de->scale);
0342         displayDataElementDescription(&(de[i]));
0343     }
0344 
0345     fread(&ntrixels, 4, 1, f);
0346     if (byteswap)
0347         ntrixels = bswap_32(ntrixels);
0348     fprintf(stdout, "Number of trixels reported = %d\n", ntrixels);
0349 
0350     return 1;
0351 }
0352 
0353 int main(int argc, char *argv[])
0354 {
0355     FILE *f, *names;
0356     int16_t maglim = -500;
0357     names          = NULL;
0358     if (argc <= 1)
0359     {
0360         fprintf(stderr, "USAGE: %s filename [trixel]\n", argv[0]);
0361         fprintf(stderr, "Designed for use only with KStars star data files\n");
0362         return 1;
0363     }
0364 
0365     f = fopen(argv[1], "rb");
0366 
0367     if (f == NULL)
0368     {
0369         fprintf(stderr, "ERROR: Could not open file %s for binary read.\n", argv[1]);
0370         return 1;
0371     }
0372 
0373     readFileHeader(f);
0374 
0375     verifyIndexValidity(f);
0376     verifyStarData(f);
0377 
0378     //    fread(&maglim, 2, 1, f);
0379     //    fprintf(stdout, "Limiting Magnitude of Catalog File: %f\n", maglim / 100.0);
0380 
0381     if (argc > 2)
0382     {
0383         /*
0384           if(argc > 3)
0385           names = fopen(argv[3], "rb");
0386           else
0387           names = NULL;
0388         
0389           fprintf(stderr, "Names = %s\n", ((names)?"Yes":"No"));
0390         */
0391         rewind(f);
0392         readStarList(f, atoi(argv[2]), names);
0393     }
0394 
0395     fclose(f);
0396     if (names)
0397         fclose(names);
0398 
0399     return 0;
0400 }