Algorithm for Orthogonal Scan Mapping ===================================== I have written the algorithm in pseudo-C, which I hope is reasonably clear. The structure is quite linear, just running from top to bottom. It assumes that the scheduler has checked the input file keywords and parameters for basic errors and inconsistencies, and has done basic hardware checks and locks. I am not sure I know where the dividing line comes between the scheduler and the observing procedure, and what the observing program gets given and is expected to return. The procedure for doing the map scan is quite trivial, what is important is the way coordinates and data are handled. In what follows I have assumed that the observing program will have access to all of the parameters in the input file, and that it writes its own data to the FITS output file. It assumes the FITS file is created by the scheduler and that the scheduler also ensures that the primary array header is populated with housekeeping information (as seen in the output file example) from the input file and SYPARM. Commands to Steer are assumed to be via a pseudo-structure: typedef struct { char Identifier[9]; double Expires; short Coordsys; short Pointing; short Dichroic; char Feedsys[25]; short Secondary; double Longitude[2]; double Latitude[2]; double psi, phi, theta, double Parallax } SteerComdStruc; and returned information from Steer is assumed to be in the form of an array of this pseudo-structure: typedef struct { double X; /* projected coordinate of beam */ double Y; double Longitude; /* celestial coordinate of beam */ double Latitude; double Azimuth; /* horizon coordinate of beam */ double Elevation; long Count1; /* counts from up to 4 v/f's */ long Count2; long Count3; long Count4 } SteerRetStruct; void Mapping_Scan (OBJECT, RESTFREQ, INSTRUME, MODE, COORDTYP, EQUINOX, (RA et al), (DEC et al), LONPOLE, PROJTYPE, fitsfile *FitsFilePointer); /* local variables */ struct SteerComdStruc SteerCommand; /* Steer command structure */ struct SteerRetStruct *SteerDataPointer; /* Steer return array */ int NumberOfSamples; /* returned size of Steer array */ /* binary table header info */ char *ttype[] = {"X","Y","xxxx","yyyy","AZ","EL","LCPcount","RCPcount"}; char *tform[] = {"1E", "1E", "1E", "1E", "1E", "1E", "1J", "1J"}; char *tunit[] = { "DEG", "DEG", "DEG", "DEG", "DEG", "DEG", "COUNTS", "COUNTS" }; int status; /* returned CFITSIO status */ /* error returns should be trapped appropriately in code */ /* some startup stuff */ Set_up_radiometer_and_counters (RESTFREQ, INSTRUME, MODE); SteerCommand.Identifier = OBJECT; /* this chunk of code may be common to other observing modes too */ switch (COORDTYP) EQUATORIAL: CRVAL1 = RA; CRVAL2 = DEC; switch (EQUINOX) B1950: SteerCommand.Coordsys = B1950; break; J2000: SteerCommand.Coordsys = J2000; break; MEAN: SteerCommand.Coordsys = MEAN; break; APPARENT: SteerCommand.Coordsys = APPARENT; break; default: SteerCommand.Coordsys = J2000; GeneralPrecession (EQUINOX, 2000.0, CRVAL1, CRVAL2); break; break; GALACTIC: SteerCommand.Coordsys = GALACTIC; CRVAL1 = GLON; CRVAL2 = GLAT; break; ECLIPTIC: SteerCommand.Coordsys = ECLIPTIC; CRVAL1 = ELON; CRVAL2 = ELAT; break; HORIZON: SteerCommand.Coordsys = HORIZON; CRVAL1 = AZ; CRVAL2 = ALT; break; TOPOCENTRIC: SteerCommand.Coordsys = TOPOCENTRIC; CRVAL1 = HA; CRVAL2 = DEC; break; SteerCommand.Pointing = True; SteerCommand.Dichroic = False; /* for now */ SteerCommand.Feed = Some_Function_Of (RESTFREQ, INSTRUME, MODE); SteerCommand.Secondary = False /* for now*/ switch (PROJTYPE) NONE: SteerCommand.theta = 0.0; SteerCommand.phi = 0.0; SteerCommand.psi = 0.0; SteerCommand.Projection = CAR; /* what steer currently uses */ break; CAR: SteerCommand.theta = 0.0; SteerCommand.phi = - CRVAL2; SteerCommand.psi = + CRVAL1; SteerCommand.Projection = CAR; /* what steer currently uses */ break; SIN: SteerCommand.theta = +LONPOLE; SteerCommand.phi = 90 - CRVAL2; SteerCommand.psi = + CRVAL1; SteerCommand.Projection = SIN; /* not implemented in steer yet */ break; TAN: SteerCommand.theta = +LONPOLE; SteerCommand.phi = 90 - CRVAL2; SteerCommand.psi = + CRVAL1; SteerCommand.Projection = TAN; /* not implemented in steer yet */ break; SteerCommand.Parallax = 0.0; /* drive to start of scan */ if (PROJTYPE == NONE) /* not a proper coordinate projection */ SteerCommand.Longitude[0] = CRVAL1 + SCANSTRT.X; SteerCommand.Longitude[1] = 0.0; SteerCommand.Latitude[0] = CRVAL2 + SCANSTRT.Y; SteerCommand.Latitude[1] = 0.0; else /* do projection properly */ SteerCommand.Longitude[0] = SCANSTRT.X; SteerCommand.Longitude[1] = 0.0; SteerCommand.Latitude[0] = SCANSTRT.Y; SteerCommand.Latitude[1] = 0.0; SteerCommand.Expires = Now + 1 hour; Slew_Antenna_and_Wait_till_tracking (SteerCommand); /* calibration while tracking start of scan */ Do_Antenna_Temperature_Calibration_and_Write_to_FITS_file; /* calculate scan rates for both x and y */ SteerCommand.Longitude[1] = (SCANSTOP.X - SCANSTRT.X) / SCANTIME; SteerCommand.Latitude[1] = (SCANSTOP.Y - SCANSTRT.Y) / SCANTIME; /* allocate an array of appropriate size */ SteerDataPointer = malloc (sizeof(SteerRetStruct) * (SCANTIME / 0.1 + 1)); /* go off and do scan */ Scan_Antenna_and_Log_Counters (SteerCommand, SteerDataPointer, &NumberOfSamples); /* set up some FITS keywords and open binary table */ switch (SteerCommand.Coordsys) TOPOCENTRIC: ttype[2] = "HA"; ttype[3] = "DEC"; break; HORIZON: ttype[2] = "AZ"; ttype[3] = "EL"; break; APPARENT, MEAN, B1950, J2000: ttype[2] = "RA"; ttype[3] = "DEC"; break; GALACTIC: ttype[2] = "GLON"; ttype[3] = "GLAT"; break; ECLIPTIC: ttype[2] = "ELON"; ttype[3] = "ELAT"; break; status = 0; fits_create_tbl (FitsFilePointer, BINARY_TBL, 0, 8, ttype, tform, tunit, "SCAN_TABLE", &status); fits_write_key (FitsFilePointer, TSTRING, "TDISP1", "F8.3", "recommended display format", &status); fits_write_key (FitsFilePointer, TSTRING, "TDISP2", "F8.3", "recommended display format", &status); fits_write_key (FitsFilePointer, TSTRING, "TDISP3", "F8.3", "recommended display format", &status); fits_write_key (FitsFilePointer, TSTRING, "TDISP4", "F8.3", "recommended display format", &status); fits_write_key (FitsFilePointer, TSTRING, "TDISP5", "F8.3", "recommended display format", &status); fits_write_key (FitsFilePointer, TSTRING, "TDISP6", "F8.3", "recommended display format", &status); fits_write_key (FitsFilePointer, TSTRING, "TDISP7", "I12", "recommended display format", &status); fits_write_key (FitsFilePointer, TSTRING, "TDISP8", "I12", "recommended display format", &status); /* stuff data one row at a time into a binary table in the FITS file */ /* Count3 and Count4 ignored */ for (row = 1; row <= NumberOfSamples; row++, SteerDataPointer++) fits_write_col (FitsFilePointer, TFLOAT, 1, row, 1, 1, &(SteerDataPointer->X), &status); fits_write_col (FitsFilePointer, TFLOAT, 2, row, 1, 1, &(SteerDataPointer->Y), &status); fits_write_col (FitsFilePointer, TFLOAT, 3, row, 1, 1, &(SteerDataPointer->Longitude), &status); fits_write_col (FitsFilePointer, TFLOAT, 4, row, 1, 1, &(SteerDataPointer->Latitude), &status); fits_write_col (FitsFilePointer, TFLOAT, 5, row, 1, 1, &(SteerDataPointer->Azimuth), &status); fits_write_col (FitsFilePointer, TFLOAT, 6, row, 1, 1, &(SteerDataPointer->Elevation), &status); fits_write_col (FitsFilePointer, TLONG, 7, row, 1, 1, &(SteerDataPointer->Count1), &status); fits_write_col (FitsFilePointer, TLONG, 8, row, 1, 1, &(SteerDataPointer->Count2), &status); /* leave scheduler to close FITS file */