/******************************************************************************* * E.S.O. - VLT project * * "@(#) $Id: AP_mask.C,v 2.43 2004/06/17 23:04:27 vltsccm Exp $" * * who when what * -------- -------- ---------------------------------------------- * hummel 13/03/98 created * aaguayo 04/12/2002 APR2003 */ /************************************************************************ * NAME * AP_mask - Automatic Positioning mask functions * * SYNOPSIS * AP_mask(float scale,float focscale,float ra_min, * float ra_max,float dec_min,float dec_max); * AP_mask(float scale,float focscale,float ra_min, * float ra_max,float dec_min); * AP_mask(float scale,float focscale,float ra_min, * float ra_max,float dec_min,int x_flag); * AP_mask(); * * PARENT CLASS * AP_pixel * * DESCRIPTION * Creates a rectangle in cartesian coordinates. Input values ra_min, * ra_max, dec_min and dec_max determine the size of the rectangle * in arcsec. 'scale' is the fits header keyword CDELT1 in units of * pixel/arcsec. 'scale' is used to create the rectangle in cartesian * (pixel) coordinates and is used to convert arcsec to pixel coordinates. * In addition to the rectangle 19 slit blade * central lines are handled. This class is used to simulate the * size of the focal field and the 19 slit blades of the ESO-VLT-FORS1 * instrument (CCD-pixels), projected into the sky (arcsec). * * PUBLIC METHODS * void reset_mask(float px, float py, float PA); * The center of the rectangle is (px,py). * The rectangle is rotated anti-clock wise by PA degrees. * * void rot_mask(float rot_ang); * Rotate the mask (the rectangle and the 19 MOS blade center * lines by rot_ang degrees; keep the current position * * void shift_mask(float dx, float dy); * Shift the mask by a distance of (dx dy) * * void shift_mask_to(float px, float py); * Shift center of the mask to (px,py) * * int p_in_window(float px, float py); * Calls p_in_area of parent class * * float pr_on_slitlet(float px, float py, int slit); * Calls pr_on_line of parent class * * void p2m(float *x, float *y); * coord transformation from frame pixel units to * mask pixel units * * void m2p(float *x, float *y); * coord transformation from mask pixel units to * frame pixel units * * void print_mask(); * maintenance * * * void test(); * maintenance * * PUBLIC DATA MEMBERS * to understand the orogin of these numerical values * consult the useful section of the documentation * * const float dist=22.73 (for UT1) and 22.8087 for UT2 * Distance between two slitlets in arcsec, * hardcoded instrument property * const float width=10.0; * Half width of a slit blade in arcsec * * PROTECTED METHODS * * PROTECTED DATA MEMBERS * * PRIVATE METHODS * * PRIVATE DATA MEMBERS * float wx[5],wy[5]; // current window position 4 points 1..4 * // wx/y[0]=center * float xma,yma,xmi,ymi;/ initial rectangle size in pixels * float dist_pix_y,width_pix; * float pa; // position angle, the current rot_ang * float ax[21],ay[21],bx[21],by[21]; * // the 19 slit blades of the ESO-VLT-FORS1 * // Multi-Object-Spectrograph (MOS) * * * * + ax[5], ay[5], the central line of MOS blade #5A * + \ * \ \ * \ \ * \ \ * \ \ * \ \ * \ + bx[5], by[5], the central line of MOS blade #5B * + * bx[6], by[6], the central line of MOS blade #6B * * * int i_big,i_sma; // index for X-orientation * * FILES * AP_mask.C AP_mask.h * * ENVIRONMENT * * COMMANDS * * RETURN VALUES * * CAUTIONS * * EXAMPLES * * SEE ALSO * AP_mask * * BUGS * *------------------------------------------------------------------------ */ #define _POSIX_SOURCE 1 #include #include #include "AP_mask.h" using namespace std; static char *rcsId="@(#) $Id: AP_mask.C,v 2.43 2004/06/17 23:04:27 vltsccm Exp $"; static void *use_rcsId = ((void)&use_rcsId,(void *) &rcsId); // the following two values are dependent on the Telescope focus // we have to update this float AP_mask::width = 10.0; // half width of a single MOS slit in arcsec float AP_mask::dist = 22.8087; // distance between two MOS slits in arcsec // 22.74 (UT1), 22.8087 (UT2) //-------------------------------------------------------- void AP_mask::reset_mask(float px, float py, float PA) //-------------------------------------------------------- // create mask at pixel position px,py and position angle PA { // CCD window, corner points wx[0]=px; wy[0]=py; wx[1]=px+xmi; wy[1]=py+yma; // upper left rectangle corner pixel wx[2]=px+xma; wy[2]=py+yma; // upper right pixel wx[3]=px+xma; wy[3]=py+ymi; // lower rigth wx[4]=px+xmi; wy[4]=py+ymi; // lower left // 19 slitlet lines int i; for (i=2; i<19; i++) { ay[i]=py+(10-i)*dist_pix_y; // optical axis + offset by[i]=ay[i]; ax[i]=wx[i_sma]; bx[i]=wx[i_big]; } // 22.20.99 bug detected // the first and 19th MOS slit are only half as width as // all other MOS slits ay[1]=py+8.75*dist_pix_y; by[1]=ay[1]; ax[1]=wx[i_sma]; bx[1]=wx[i_big]; ay[19]=py-8.75*dist_pix_y; by[19]=ay[19]; ax[19]=wx[i_sma]; bx[19]=wx[i_big]; // rotate mask pa=0.0; rot_mask(PA); } //---------------------------------- void AP_mask::m2p(float *x, float *y) //---------------------------------- { // coordinate transformation // x,y CCD pixel input coordinate in the current mask // position // output position in CCD pixel of the underlying frame // in pixel units // first rot back, then shift back rot(x,y,0.0,0.0,pa); *x += wx[0]; *y += wy[0]; } //---------------------------------- void AP_mask::p2m(float *x, float *y) //---------------------------------- { // coordinate transformation // x,y CCD pixel input coordinate of underlying fits image // output position inside the rotated and shifted mask // in pixel units // first shift, then rot *x -= wx[0]; *y -= wy[0]; rot(x,y,0.0,0.0,-pa); } //---------------------------------- void AP_mask::rot_mask(float rot_ang) //---------------------------------- { // rotate the mask at the current position // wx[0], wy[0] by an amount of rot_ang degrees int i; for (i=1; i<=4; i++) { rot(&wx[i],&wy[i],wx[0],wy[0],rot_ang); } for (i=1; i<20; i++) { rot(&ax[i],&ay[i],wx[0],wy[0],rot_ang); rot(&bx[i],&by[i],wx[0],wy[0],rot_ang); } pa += rot_ang; // the current position angle } //--------------------------------------------- void AP_mask::shift_mask(float dx, float dy) //--------------------------------------------- { // shift the mask by an amount of // dx, dy from the current position // (relative shift) int i; for (i=0; i<=4; i++) { wx[i] += dx; wy[i] += dy; } for (i=1; i<20; i++) { ax[i] += dx; ay[i] += dy; bx[i] += dx; by[i] += dy; } } //--------------------------------------------- void AP_mask::shift_mask_to(float px, float py) //--------------------------------------------- { // shift the mask from the current position // to the absolute coords of px, py // (absolute shift) int i; float dx=px-wx[0],dy=py-wy[0]; for (i=0; i<=4; i++) { wx[i] += dx; wy[i] += dy; } for (i=1; i<20; i++) { ax[i] += dx; ay[i] += dy; bx[i] += dx; by[i] += dy; } // alternatively reset_mask(px,py,pa); } //--------------------------------------------- void AP_mask::print_mask() //--------------------------------------------- { // the peculiar sorting order is of // practical reasons. The two columns are // suitable to be used for plot programs // like sm or gnuplot int i; cout << "CCD-window \n"; cout << "xmi=" << xmi << " xma=" << xma << " ymi=" << ymi << " yma=" << yma << endl; cout << wx[4] << " " << wy[4] << endl; for (i=1; i<=4; i++) cout << wx[i] << " " << wy[i] << endl; cout << wx[0] << " " << wy[0] << endl; for (i=1; i<20; i++) { if (i/2 == (i*1.0/2.0)) { cout << ax[i] << " " << ay[i] << endl; cout << bx[i] << " " << by[i] << endl; } else { cout << bx[i] << " " << by[i] << endl; cout << ax[i] << " " << ay[i] << endl; } } } //--------------------------------------------- void AP_mask::test() //--------------------------------------------- { int i; float a,b; int debug=1; cout << "----------------------" << endl << " AP_MASK TEST " << endl << "----------------------" << endl; if (debug) { // ----- zero point cout << "reset_mask 0 0 0" << endl; reset_mask(0.0, 0.0, 0.0); // print_mask(); a=50; b=0.0; cout << " p2m (" << a << "," << b << ")="; p2m(&a,&b); cout << a << "," << b << endl; cout << " m2p (" << a << "," << b << ")="; m2p(&a,&b); cout << a << "," << b << endl; // ----- nur rot +5 cout << "reset_mask 000 0 5" << endl; reset_mask(0.0,0.0,5.0); // print_mask(); cout << " p2m (" << a << "," << b << ")="; p2m(&a,&b); cout << a << "," << b << endl; cout << " m2p (" << a << "," << b << ")="; m2p(&a,&b); cout << a << "," << b << endl; // ----- nur rot -5 cout << "reset_mask 000 0 -5" << endl; reset_mask(0.0,0.0,-5.0); // print_mask(); cout << " p2m (" << a << "," << b << ")="; p2m(&a,&b); cout << a << "," << b << endl; cout << " m2p (" << a << "," << b << ")="; m2p(&a,&b); cout << a << "," << b << endl; // --- nur offset x = +100, y=-100 cout << "reset_mask 100 -100 0" << endl; reset_mask(100.0,-100.0,0.0); // print_mask(); cout << " p2m (" << a << "," << b << ")="; p2m(&a,&b); cout << a << "," << b << endl; cout << " m2p (" << a << "," << b << ")="; m2p(&a,&b); cout << a << "," << b << endl; // --- nur offset x = +100, y= -50 cout << "reset_mask 100 -50 0" << endl; reset_mask(100.0,-50.0,0.0); // print_mask(); cout << " p2m (" << a << "," << b << ")="; p2m(&a,&b); cout << a << "," << b << endl; cout << " m2p (" << a << "," << b << ")="; m2p(&a,&b); cout << a << "," << b << endl; // --- reset at x=100,y=100, pa=-10 cout << "reset_mask 100 100 -10" << endl; reset_mask(100.0,100.0,-10.0); // print_mask(); cout << " p2m (" << a << "," << b << ")="; p2m(&a,&b); cout << a << "," << b << endl; cout << " m2p (" << a << "," << b << ")="; m2p(&a,&b); cout << a << "," << b << endl; cout << "rot_mask -85" << endl; rot_mask(-85.0); // print_mask(); cout << " p2m (" << a << "," << b << ")="; p2m(&a,&b); cout << a << "," << b << endl; cout << " m2p (" << a << "," << b << ")="; m2p(&a,&b); cout << a << "," << b << endl; cout << "shift_mask_to 1000 500" << endl; shift_mask_to(1000,500); print_mask(); cout << "shift_mask -1000 -500" << endl; shift_mask(-1000,-500); print_mask(); cout << " p_in_window(0,-200)=" << p_in_window(0,-200) << endl; cout << " p_in_window(0,-1 )=" << p_in_window(0,-1 ) << endl; cout << "rot_mask -45" << endl; cout << "reset_mask 0 0 -45" << endl; reset_mask(0.0, 0.0,-45.0); print_mask(); for (i=1; i<20; i++) cout << " pr_on_slitlet(3.0,3.0," << i << ")=" << pr_on_slitlet(3.0,3.0,i) << endl; // --- reset at x=100,y=100, pa=90 cout << "reset_mask 100 100 05" << endl; reset_mask(100.0,100.0,05.0); // print_mask(); a=0.0; b=0.0; cout << " p2m (" << a << "," << b << ")="; p2m(&a,&b); cout << a << "," << b << endl; cout << " m2p (" << a << "," << b << ")="; m2p(&a,&b); cout << a << "," << b << endl; a=100.0; b=0.0; cout << " p2m (" << a << "," << b << ")="; p2m(&a,&b); cout << a << "," << b << endl; cout << " m2p (" << a << "," << b << ")="; m2p(&a,&b); cout << a << "," << b << endl; a=0.0; b=100.0; cout << " p2m (" << a << "," << b << ")="; p2m(&a,&b); cout << a << "," << b << endl; cout << " m2p (" << a << "," << b << ")="; m2p(&a,&b); cout << a << "," << b << endl; // --- reset at x=100,y=100, pa=90 cout << "reset_mask 100 100 45" << endl; reset_mask(100.0,100.0,45.0); // print_mask(); a=0.0; b=0.0; cout << " p2m (" << a << "," << b << ")="; p2m(&a,&b); cout << a << "," << b << endl; cout << " m2p (" << a << "," << b << ")="; m2p(&a,&b); cout << a << "," << b << endl; a=100.0; b=0.0; cout << " p2m (" << a << "," << b << ")="; p2m(&a,&b); cout << a << "," << b << endl; cout << " m2p (" << a << "," << b << ")="; m2p(&a,&b); cout << a << "," << b << endl; a=0.0; b=100.0; cout << " p2m (" << a << "," << b << ")="; p2m(&a,&b); cout << a << "," << b << endl; cout << " m2p (" << a << "," << b << ")="; m2p(&a,&b); cout << a << "," << b << endl; // --- reset at x=100,y=100, pa=90 cout << "reset_mask 100 100 90" << endl; reset_mask(100.0,100.0,90.0); // print_mask(); a=0.0; b=0.0; cout << " p2m (" << a << "," << b << ")="; p2m(&a,&b); cout << a << "," << b << endl; cout << " m2p (" << a << "," << b << ")="; m2p(&a,&b); cout << a << "," << b << endl; a=100.0; b=0.0; cout << " p2m (" << a << "," << b << ")="; p2m(&a,&b); cout << a << "," << b << endl; cout << " m2p (" << a << "," << b << ")="; m2p(&a,&b); cout << a << "," << b << endl; a=0.0; b=100.0; cout << " p2m (" << a << "," << b << ")="; p2m(&a,&b); cout << a << "," << b << endl; cout << " m2p (" << a << "," << b << ")="; m2p(&a,&b); cout << a << "," << b << endl; } cout << "width = " << width << " arcsec" << endl; cout << "dist = " << dist << " arcsec" << endl; cout << "width_pix = " << width_pix << " pix " << endl; cout << "dist_pix_y= " << dist_pix_y << " pix " << endl; } //--------------------------------------------- int AP_mask::p_in_window(float px, float py) //--------------------------------------------- { return (p_in_area(4,px,py,wx,wy)); } //--------------------------------------------- float AP_mask::pr_on_slitlet(float px, float py, int slit) //--------------------------------------------- // return the distance of a point from the mid axis if a // slitlet arm in units of its total blade width=22.73'' // = total MOS slit length { return (pr_on_line(px,py,ax[slit],ay[slit],bx[slit],by[slit])/width_pix); } // constructors //-------------------------------------------------------------- AP_mask::AP_mask(float scale,float focscale,float ra_min, float ra_max,float dec_min,float dec_max) //-------------------------------------------------------------- { AP_mask::width=focscale*10.6; // (odd slit width = 11.8mm) AP_mask::dist =focscale*12.0; xmi = ra_min/scale; xma = ra_max/scale; ymi = -dec_min/scale; yma = dec_max/scale; // cout << "dist = " << dist << "\n"; dist_pix_y=dist/scale; if (yma