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

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