bool Hero::setSkyCS(Hero::SKYCS skyCS) { if( m_currentSkyCs == skyCS) { // nothing to do return true; } if( m_ast.origWcsInfo == AST__NULL) { addError( "No wcsinfo from astlib"); return false; } AstErrorGuard guard( this); // intercept errors AstGCGuard gcguard; // make a clone void * newWcsInfo = AST__NULL; if( m_originalSkyCs == skyCS) { // original skycs is the same as requested skycs, so // clone only a pointer to the original frame newWcsInfo = astClone( m_ast.origWcsInfo); } else { // otherwise make a full clone of the frame and set it's system newWcsInfo = astCopy( m_ast.origWcsInfo); if( ! astOK) { addError( "Could not clone the original astFrameSet"); return false; } // set the new system for the clone AstWrappers::set( newWcsInfo, QString( "System=%1").arg( skycs2string(skyCS))); if( ! astOK) { addError( "Could not convert to this coordinate system " + skycs2string( skyCS)); return false; } astClear( newWcsInfo, "Epoch,Equinox"); } // free up the old ast pointer if( m_ast.currWcsInfo != AST__NULL) { astAnnul( m_ast.currWcsInfo); m_ast.currWcsInfo = AST__NULL; } m_ast.currWcsInfo = newWcsInfo; astExempt( m_ast.currWcsInfo); m_currentSkyCs = skyCS; parseAxesInfo(); QString title = AstWrappers::getC( m_ast.currWcsInfo, "Title(1)"); dbg(1) << "Title = " << title << "[" << AstWrappers::getC( m_ast.currWcsInfo, "LonAxis") << "," << AstWrappers::getC( m_ast.currWcsInfo, "LatAxis") << "]"; // clear up ast errors if any astClearStatus; return true; }
Hero * Hero::constructFromFitsFile(const QString &fname) { FitsParser parser; bool parsedOk = parser.loadFile( FitsFileLocation::fromLocal( fname)); if( ! parsedOk) { dbg(1) << "Parser failed to load " << fname; Hero * heroPtr = new Hero; heroPtr-> addError( "FitsParser failed to load the file"); return heroPtr; } // alias hdr auto & hdr = parser.getHeaderInfo().headerLines; Hero * heroPtr = new Hero; Hero & hero = * heroPtr; AstErrorGuard guard( heroPtr); AstGCGuard gcGuard; // set naxes in case AST fails to read this file hero.m_ast.naxes = parser.getHeaderInfo().naxis; // set up bunit { hero.m_bunit = parser.getHeaderInfo().bunit; } // and the nicer version of bunit { QString u = hero.m_bunit.simplified(); if( u.toLower() == "kelvin") { hero.m_bunitNiceHtml = "K"; } else { hero.m_bunitNiceHtml = u; } } // Create a FitsChan and feed it the fits header AstFitsChan *fitschan; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wformat-zero-length" fitschan = astFitsChan( NULL, NULL, "" ); #pragma GCC diagnostic pop std::cout << "astOK = " << astOK << "\n"; // feed the header lines one by one and check for errors for( const QString & s : hdr) { std::string stdstr = s.toStdString(); astPutFits( fitschan, stdstr.c_str(), 1); if( ! astOK) { astClearStatus; QString ss = s.trimmed(); std::cout << "Skipping bad card: " << ss << "\n"; hero.addError( "Skipping card: " + ss); } } // reposition to the beginning of the channel (ast thing, it's required, hmmmkey) astClear( fitschan, "Card" ); std::cout << "astOK = " << astOK << "\n"; std::cout << "Here\n"; auto encoding = AstWrappers::getC( fitschan, "Encoding" ); std::cout << "Encoding = " << encoding << "\n"; // do we have warnings? AstKeyMap * warnings = static_cast<AstKeyMap *>( astWarnings( fitschan)); if( warnings && astOK ) { std::cout << "Warnings:\n"; int iwarn = 1; while( astOK ) { std::string key = QString("Warning_%1").arg( iwarn).toStdString(); const char * message = nullptr; if( astMapGet0C( warnings, key.c_str(), & message ) ) { printf( "\n- %s\n", message ); hero.addError( QString( "Warning: %1").arg( message)); } else { break; } } } else { std::cout << "No warnings\n"; } // create a frameset for this file AstFrameSet * wcsinfo = static_cast<AstFrameSet *> ( astRead( fitschan )); std::cout << "astOK = " << astOK << "\n"; if ( ! astOK ) { std::cout << "astOK is not ok\n"; hero.addError( "astRead failed"); astClearStatus; return heroPtr; } else if ( wcsinfo == AST__NULL ) { hero.addError( "No WCS found in the fits file"); std::cout << "No WCS found\n"; return heroPtr; } else if ( AstWrappers::getC( wcsinfo, "Class" ) != "FrameSet") { std::cout << "Some other weird error occured\n"; hero.addError( "AstLib returned non-frame-set"); return heroPtr; } // frame was read in OK, save it hero.m_ast.origWcsInfo = wcsinfo; astExempt( hero.m_ast.origWcsInfo); hero.m_ast.currWcsInfo = astClone( hero.m_ast.origWcsInfo); astExempt( hero.m_ast.currWcsInfo); astShow( wcsinfo); // extract the current sky system // TODO: this assumes axis1 is a skycs QString skysys = AstWrappers::getC( wcsinfo, "System(1)"); hero.m_currentSkyCs = string2skycs( skysys); hero.m_originalSkyCs = hero.m_currentSkyCs; // extract the labels/etc for axes hero.m_ast.naxes = AstWrappers::getI( wcsinfo, "Naxes" ); hero.parseAxesInfo(); return heroPtr; }
smfDetposWcsCache *smf_detpos_wcs( smfHead *hdr, int index, double dut1, const double telpos[3], AstFrameSet **fset, smfDetposWcsCache *cache, int *status ) { /* Local Variables: */ AstCmpMap *cmap1 = NULL; /* Parallel CmpMap holding both LutMaps */ AstLutMap *latmap = NULL; /* LutMap holding latitude values */ AstLutMap *lonmap = NULL; /* LutMap holding longitude values */ AstMapping *map = NULL; /* GRID->SKY Mapping */ AstSkyFrame *csky = NULL; /* SkyFrame to put in returned FrameSet */ const double *p1; /* Pointer to next lon or lat value to copy */ double *p2; /* Pointer to next lon value */ double *p3; /* Pointer to next lat value */ int i; /* Index of current detector */ int nrec; /* Number of detectors */ int outperm[ 2 ]; /* Axis permutation */ smfDetposWcsCache *result; /* Pointer to returned cache structure */ /* If a negative index was supplied just free the allocated resources and return. */ if( index < 0 && cache ) { if( cache->latlut ) cache->latlut = astFree( cache->latlut ); if( cache->lonlut ) cache->lonlut = astFree( cache->lonlut ); if( cache->pmap ) cache->pmap = astAnnul( cache->pmap ); if( cache->grid ) cache->grid = astAnnul( cache->grid ); if( cache->sky ) cache->sky = astAnnul( cache->sky ); cache = astFree( cache ); return NULL; } /* Check inherited status */ result = cache; if( *status != SAI__OK) return result; /* If no cache structure was supplied, allocate and initialise one now. */ if( !cache ) { cache = astMalloc( sizeof( *cache ) ); if( cache ) { cache->latlut = NULL; cache->lonlut = NULL; cache->pmap = NULL; cache->grid = NULL; cache->sky = NULL; result = cache; } else { *status = SAI__ERROR; errRep( FUNC_NAME, FUNC_NAME": Can't allocate memory for cache.", status); return NULL; } } /* Get the number of detectors. */ nrec = hdr->ndet; /* Get a pointer to the start of the detpos values for the requested time slice. */ p1 = hdr->detpos + 2*nrec*index; /* Check there is more than 1 detector. */ if( nrec > 1 ) { /* It is possible that we have not allocated enough memory since this memory is allocated for the first file but subsequent files may have more receptors. So we use astGrow. */ /* If required, allocate memory to hold the individual look up tables for lon and lat vaues. */ cache->lonlut = astGrow( cache->lonlut, nrec, sizeof( double ) ); cache->latlut = astGrow( cache->latlut, nrec, sizeof( double ) ); /* Check the memory was allocated succesfully. */ if( cache->lonlut && cache->latlut ) { /* Copy the lon and lat values for the requested time slice from the smfHead structure to the local lut arrays. */ p2 = cache->lonlut; p3 = cache->latlut; for( i = 0; i < nrec; i++ ) { *(p2++) = *(p1++); *(p3++) = *(p1++); } /* Create the Mapping from GRID to SKY positions. This is a PermMap to duplicate the detector index, followed by 2 LutMaps in parallel to generate the lon and lat values. Set the LutInterpattribute in these LutMaps so that they use nearest neighbour interpolation. */ lonmap = astLutMap( nrec, cache->lonlut, 1.0, 1.0, "LutInterp=1" ); latmap = astLutMap( nrec, cache->latlut, 1.0, 1.0, "LutInterp=1" ); cmap1 = astCmpMap( lonmap, latmap, 0, " " ); latmap = astAnnul( latmap ); lonmap = astAnnul( lonmap ); if( !cache->pmap ) { outperm[ 0 ] = 1; outperm[ 1 ] = 1; cache->pmap = astPermMap( 2, NULL, 2, outperm, NULL, " " ); astExempt( cache->pmap ); } map = (AstMapping *) astCmpMap( cache->pmap, cmap1, 1, " " ); cache->pmap = astAnnul( cache->pmap ); cmap1 = astAnnul( cmap1 ); } /* If thre is only one detector, use a PermMap to describe this one position. rather than a LutMap (LutMaps cannot describe a single position). */ } else { outperm[ 0 ] = -1; outperm[ 1 ] = -2; map = (AstMapping *) astPermMap( 2, NULL, 2, outperm, p1, " " ); } /* Create two Frames to put in the FrameSet. */ if( !cache->grid ) { cache->grid = astFrame( 2, "Domain=GRID" ); astExempt( cache->grid ); } if( !cache->sky ) { cache->sky = astSkyFrame( "System=AzEl" ); astSetD( cache->sky, "ObsLon", -telpos[ 0 ] ); astSetD( cache->sky, "ObsLat", telpos[ 1 ] ); astExempt( cache->sky ); /* If the detpos positions are referred to the TRACKING frame, change the SkyFrame from AZEL to the AST equivalent of the TRACKING Frame. */ if( !hdr->dpazel ) { astSetC( cache->sky, "System", sc2ast_convert_system( hdr->state->tcs_tr_sys, status ) ); } } /* Take a copy of the skyframe, and then modify its Epoch attribute. We take a copy since otherwise all FrameSets returned by this function would share the same current Frame, and so the attribute change would affect them all. Always use TCS_TAI. smf_open_file corrects the JCMTState structure if TCS_TAI is missing. Remember to convert from TAI to TDB (as required by the Epoch attribute). */ csky = astClone( cache->sky ); astSet( csky, "Epoch=MJD %.*g, dut1=%.*g", DBL_DIG, hdr->state->tcs_tai + 32.184/SPD, DBL_DIG, dut1 ); /* Create the FrameSet */ *fset = astFrameSet( cache->grid, " " ); astAddFrame( *fset, AST__BASE, map, csky ); /* Free resources */ map =astAnnul( map ); csky =astAnnul( csky ); /* Exempt the FrameSet pointer from the AST context system rather because we do not know when, or in which context, it will be used. It will be annulled either in smf_tslice_ast or in smf_close_file. */ astExempt( *fset ); return result; }