bool FileFormatInstance::Extract( FITSKeywordArray& keywords ) { try { keywords.Clear(); if ( (*API->FileFormat->BeginKeywordExtraction)( handle ) == api_false ) return false; for ( size_type i = 0, count = (*API->FileFormat->GetKeywordCount)( handle ); i < count; ++i ) { IsoString name, value, comment; name.Reserve( 96 ); value.Reserve( 96 ); comment.Reserve( 96 ); if ( (*API->FileFormat->GetNextKeyword)( handle, name.Begin(), value.Begin(), comment.Begin(), 81 ) == api_false ) throw APIFunctionError( "GetNextKeyword" ); name.ResizeToNullTerminated(); value.ResizeToNullTerminated(); comment.ResizeToNullTerminated(); keywords.Add( FITSHeaderKeyword( name, value, comment ) ); } (*API->FileFormat->EndKeywordExtraction)( handle ); return true; } catch ( ... ) { (*API->FileFormat->EndKeywordExtraction)( handle ); throw; } }
static void Apply( GenericImage<P>& img, const View& view, const FluxCalibrationInstance& instance ) { FITSKeywordArray inputKeywords; view.Window().GetKeywords( inputKeywords ); if ( KeywordExists( inputKeywords, "FLXMIN" ) || KeywordExists( inputKeywords, "FLXRANGE" ) || KeywordExists( inputKeywords, "FLX2DN" ) ) { throw Error( "Already calibrated image" ); } if ( img.IsColor() ) throw Error( "Can't calibrate a color image" ); float Wc = instance.p_wavelength.GetValue( inputKeywords ); float Tr = Max( 1.0F, instance.p_transmissivity.GetValue( inputKeywords ) ); float Delta = instance.p_filterWidth.GetValue( inputKeywords ); float Ap = instance.p_aperture.GetValue( inputKeywords ) / 10; // mm -> cm float Cobs = Max( 0.0F, instance.p_centralObstruction.GetValue( inputKeywords ) ) / 10; // mm -> cm float ExpT = instance.p_exposureTime.GetValue( inputKeywords ); float AtmE = Max( 0.0F, instance.p_atmosphericExtinction.GetValue( inputKeywords ) ); float G = Max( 1.0F, instance.p_sensorGain.GetValue( inputKeywords ) ); float QEff = Max( 1.0F, instance.p_quantumEfficiency.GetValue( inputKeywords ) ); if ( Wc <= 0 ) throw Error( "Invalid filter wavelength" ); if ( Tr <= 0 || Tr > 1 ) throw Error( "Invalid filter transmissivity" ); if ( Delta <= 0 ) throw Error( "Invalid filter width" ); if ( Ap <= 0 ) throw Error( "Invalid aperture" ); if ( Cobs < 0 || Cobs >= Ap ) throw Error( "Invalid central obstruction area" ); if ( ExpT <= 0 ) throw Error( "Invalid exposure time" ); if ( AtmE < 0 || AtmE >= 1 ) throw Error( "Invalid atmospheric extinction" ); if ( G <= 0 ) throw Error( "Invalid sensor gain" ); if ( QEff <= 0 || QEff > 1 ) throw Error( "Invalid quantum efficiency" ); FITSKeywordArray keywords; float pedestal = 0; bool foundPedestal = false; for ( FITSKeywordArray::const_iterator i = inputKeywords.Begin(); i != inputKeywords.End(); ++i ) if ( i->name == "PEDESTAL" ) { if ( i->value.TryToFloat( pedestal ) ) foundPedestal = true; pedestal /= 65535; // 2^16-1 maximum value of a 16bit CCD. } else keywords.Add( *i ); if ( foundPedestal ) Console().NoteLn( "<end><cbr><br>* FluxCalibration: PEDESTAL keyword found: " + view.FullId() ); // double F = Wc * inv_ch * (1 - Tr) * Delta * Ap * Cobs * ExpT * AtmE * G * QEff; double F = Wc * inv_ch * (1 - AtmE) * Delta * ( Const<double>::pi() / 4 * ( Ap*Ap - Cobs*Cobs ) ) * ExpT * Tr * G * QEff; size_type N = img.NumberOfPixels(); typename P::sample* f = img.PixelData( 0 ); const typename P::sample* fN = f + N; double flxMin = DBL_MAX; double flxMax = 0; for ( ; f < fN; ++f, ++img.Status() ) { double I; P::FromSample( I, *f ); I = (I - pedestal)/F; *f = P::ToSample( I ); if ( I < flxMin ) flxMin = I; if ( I > flxMax ) flxMax = I; } img.Rescale(); keywords.Add( FITSHeaderKeyword( "FLXMIN", IsoString().Format( "%.8e", flxMin ), "" ) ); keywords.Add( FITSHeaderKeyword( "FLXRANGE", IsoString().Format( "%.8e", flxMax - flxMin ), "FLXRANGE*pixel_value + FLXMIN = erg/cm^2/s/nm" ) ); keywords.Add( FITSHeaderKeyword( "FLX2DN", IsoString().Format( "%.8e", F*65535 ), "(FLXRANGE*pixel_value + FLXMIN)*FLX2DN = DN" ) ); view.Window().SetKeywords( keywords ); }