File indexing completed on 2024-09-08 03:28:59
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 }