program event_display c c ********************************************************************** c c this is an event display routine for CERN h8 testbeam data for the c pixel detector tests. c c The purpose of this routine is to allow people on shift to see whether or c not most events are "sensible": strip detectors show hits that lie c roughly on a line, and pixel detectors show activity in the expected c regions. It is NOT the purpose of this to generate online calibration and c alignment information while writing data. c c program takes arguments; first is which display to draw on. See comments c in event_display_get_args for a more complete description. c c There are several different coordinate systems which come into play: c c the "telescope frame" or "lab frame" has its z axis parallel to the c beam, and its x,y axes parallel to the coordinates determined by the c first strip plane. The origin of the lab frame is at the c (xstrip, ystrip) = (0,0) corner of the first strip plane. units: mm c c "raw coordinates" from a detector, also in millimeters, have c (xraw, yraw, zraw) calculated from the number of the strip, column, or c row that's struck, and the appropriate pitch. zraw=0. c c "screen pixels," "xpixels," "ypixels" refer to dots on the X11 display. c The X11 origin puts (0,0) at the upper left corner of the screen. c x increases as one moves to the right, while y increases as one moves c DOWN the screen. This can cause a certain amount of confusion, since c the telescope frame is displayed with its z axis moving to the right on c the screen (positive X11 x), and with the positive x (or y) direction c moving towards the top of the screen (negative X11 y direction). c c see http://marpix1.in2p3.fr/gollin/event_display/ c event_display_documentation.html c for WWW documentation of the event display. c c George Gollin, CPPM (Marseille) and University of Illinois (Urbana-Champaign) c g-gollin@uiuc.edu, 1999 c c ********************************************************************** c c include files holding common blocks and parameter statements go here: c note that they're in the same directory as this file. c #include "event_display.inc" #include "event_display_data.inc" c c ********************************************************************** c c non-common type definitions and array definitions go here: c character*100 text c c first time this routine is called: logical first_time c c debug flag: logical debug c c got-a-good-event flag: logical good_event c c file existence flag: logical file_exists c c c ********************************************************************** c c data statements go here: c c first time we're entering the routine: data first_time /.true./ c c no graphic window has been opened yet... data window_is_open /.false./ c c initial x,y position for X11 window 1; in pixels: note that X coordinates c have increasing x moving to the right on the screen, increasing y c moving down. origin is upper left corner of screen. data ix11window1_x0, ix11window1_y0 /1, 1/ c c width and height, in pixels, for X11 window 1: data ix11window1_width_default, ix11window1_height_default . /800, 700/ c c pixels_clearance is the number of pixels of white space I want to use in c various places... data pixels_clearance /50./ c c shift_right is an extra distance to shift stuff to the right so that I c gave space for some labels to the left of the first plane if desired. data shift_right /50./ c c itext_pixels is the approximate height, in pixels, of text I'll write. data itext_pixels /12/ c c factor_dem_z_exaggerate is a scale factor to exaggerate how much I show c the change in z position of the corners of the pixel planes in order to c make it easier to see the rotations. ccc data factor_dem_z_exaggerate /5./ data factor_dem_z_exaggerate /1./ c c message_height is the height (in pixels) of a status message window. data message_height /125./ c c button_row_height is the number of pixels high I'll use to make a set c of buttons for users to click. It gets updated after I see how much room c I really need. data button_row_height /75./ c c number_of_buttons is the number of buttons to put in this row. data number_of_buttons /9/ c c map for buttons, initially assumes no marebo. Number in this list says c which button, if any, to fill with the corresponding label. data map_button /1, 2, 3, 4, 5, 6, 7, 0, 0, 0, . 0, 0, 0, 8, 9, 0, 0, 0, 0, 0 / c c labels for the clickable buttons: data button_labels / 1 'Next event', 2 'dem1 phi=', 3 'dem1 psi=', 4 'dem1 theta=', 5 'dem2 phi=', 6 'dem2 psi=', 7 'dem2 theta=', 8 'Marebo phi=', 9 'Marebo psi=', . 'Marebo theta=', 1 'Module phi=', 2 'Module psi=', 3 'Module theta=', 4 'Zoom', 5 'STOP', . 5*'empty' / c c which button is which: indices need to agree with my labels. data next_event_button /1/ data new_dem1_phi_button /2/ data new_dem1_psi_button /3/ data new_dem1_theta_button /4/ data new_dem2_phi_button /5/ data new_dem2_psi_button /6/ data new_dem2_theta_button /7/ data new_demm_phi_button /8/ data new_demm_psi_button /9/ data new_demm_theta_button /10/ data new_demd_phi_button /11/ data new_demd_psi_button /12/ data new_demd_theta_button /13/ data izoom_button /14/ data istop_button /15/ c c title for window 1: data ix11window1_title . /'-ATLAS h8 pixel test beam event display..'/ c c expected number of strips, columns, rows,... (these are also read in from c data file) data number_strips /384/ data number_rows_dem1, number_cols_dem1 /160, 18/ data number_rows_dem2, number_cols_dem2 /160, 10/ data number_rows_demm, number_cols_demm /63, 12/ data number_rows_demd, number_cols_demd /328, 144/ c with module: there are 164 detector rows, but only 160 readout rows. c mapping is like so: c detector readout c 163 159 c 162 157 c 161 155 c 160 153 c 159 159 c etc. etc. data number_shared_rows /4/ c the module has "interior" edge columns that are wider. data number_fatcols_dem1, number_fatcols_dem2, . number_fatcols_demm, number_fatcols_demd /0, 0, 0, 14/ c columns, rows on the DETECTOR looked at by one chip in a module: data number_cols_per_modchip, number_rows_per_modchip /18, 164/ c c z positions for detectors, in millimeters: these are from 8/98. c nominal ones were 0., 192., 1216., 1408. for the siroccos, and c 944., 433. for the dem1, dem2 stations. c planes here are siroccos 1-4, dem1, dem2, marebo, module. data xplane_z0 /0., 192., 1216., 1408., 944., 0., 0., . 0. / data yplane_z0 /3., 195., 1219., 1411., 944., 0., 0., . 0. / data xplane_z0_default /0., 192., 1216., 1408., 944., 0., 0., . 0. / data yplane_z0_default /3., 195., 1219., 1411., 944., 0., 0., . 0. / c c some x,y positions too... data xplane_x0 /max_planes*0./ data yplane_y0 /max_planes*0./ data xplane_x0_default /max_planes*0./ data yplane_y0_default /max_planes*0./ c c pitch for various detectors, in millimeters: data strip_pitch /0.050/ data dem1_pitch_fine, dem1_pitch_coarse /0.050, 0.400/ data dem2_pitch_fine, dem2_pitch_coarse /0.050, 0.400/ data demm_pitch_fine, demm_pitch_coarse /0.050, 0.432/ data demd_pitch_fine, demd_pitch_coarse /0.050, 0.400/ data demd_pitch_coarse2 /0.600/ c c plane index numbers for the two pixel planes: data ipldem1, ipldem2, ipldemm, ipldemd /5, 6, 7, 8/ c c max_strip_pulseheight, max_dem1_pulseheight, max_dem2_pulseheight are c only used to give me an idea how large the signals migh be so I can c calculate the scaling required to keep the tickmarks from bumping into c the next plane. data max_strip_pulseheight /500./ data max_dem1_pulseheight, max_dem2_pulseheight /2*50./ data max_demm_pulseheight /50./ data max_demd_pulseheight /50./ c c default values for pixel angles, in degrees: data phidem1, psidem1, thetadem1 /0., 0., 0./ data phidem2, psidem2, thetadem2 /0., 0., 0./ data phidemm, psidemm, thetademm /0., 0., 0./ data phidemd, psidemd, thetademd /0., 0., 0./ c c delta_angle_per_click is the number of degrees per mouse button click to c change the phi, psi, theta angles. data delta_angle_per_click /5./ c c icurrent_mouse_button, icurrent_button are numbers of most recently c detected mouse button that was clicked (1=left, 2=middle, 3=right) and c window button that was clicked. data icurrent_mouse_button, icurrent_button /0, 0/ c c iprevious_mouse_button,iprevious_button are similar, but for next-most- c recently detected button clicks. data iprevious_mouse_button,iprevious_button /0, 0/ c c index_color_white, index_color_black, index_color_red, index_color_green, c and index_color_blue are color indices to use with the X11 routines. c data index_color_white, index_color_black / 1, 2 / data index_color_red, index_color_green / 3, 4 / data index_color_blue / 5 / data index_color1 / 6 / data index_color2 / 7 / data index_color3 / 8 / data index_color_button /9/ data index_color_message /10/ data index_color_xview /11/ data index_color_yview /12/ c c c cursor indices for ordinary, and use-when-zooming cursors: data idefault_cursor, irubber_cursor /1, 5/ c c unit number for a control file: data lun_control /19/ c c unit number for event data: data lun_data /20/ c c unit number for a file holding parameters like detector z positions: data lun_parameters /21/ c c unit number for a file holding default parameter values: data lun_default_parameters /22/ c c file names for use when running at CERN: c raw data for one event; filename from Thierry Mouthuy, 1 April 1999. data file_data_cern / . '/PixData/event_dump' . / c data file_default_parameters_cern / . '/PixData/event_params' . / c data file_control_cern / . '/PixData/event_display' . / c c file names for use when running at cppm: c raw data for one event; data file_data_cppm / . '/user2/gollin/testbeam/sep98/analysis/event_dump' . / c data file_default_parameters_cppm / . '/user2/gollin/testbeam/sep98/analysis/event_params' . / c data file_control_cppm / . '/user2/gollin/testbeam/sep98/analysis/event_display' . / c data web_document_url_IP / . 'http://marpix1.in2p3.fr' / data web_document_url_path / . '/gollin/event_display/event_display_documentation.html' / c c delete_file_when_finished is true when I want to delete the event data c file when I think I'm through with it. This'll be used in the handshaking c between the calling program and this program. data delete_file_when_finished /.true./ c c Set run_at_cern .true. if I want to run the job as a standalone c program which reads data from a file. Set it .false. if the data is to c be loaded into arrays by the calling program (probably h8). data run_at_cern /.true./ c c font names I'd like to try using, if I can find them, in order of c preference: use the unix command xlsfonts to get a list of what exists. data font_name / . '6x10' , . '6x9' , . '5x8' , . '5x7' , . '6x12' , . '7x13' , . '8x13' , . '7x14' , . '9x15' , . '8x16' / c c number_for_control_file is the number written to the control file: it is c the periodicity with which to write events to the buffeering file. make c it 1 to get the next available event, larger to skip a bunch of events. data number_for_control_file /10/ c c i_want_to_stop set to true means end program at the next possible moment. data i_want_to_stop /.false./ c c debug on/off: data debug /.false./ c c c ************************************************************************* c c c c ******************* (construct URL name for WWW documentation) c c c Build the URL name for the event display documentation by concatenating c the IP address and pathname for the file... c web_document_url= . web_document_url_IP(1:lenocc(web_document_url_IP)) // . web_document_url_path(1:lenocc(web_document_url_path)) c c ... and include it in window title: ix11window1_title=ix11window1_title(1:lenocc(ix11window1_title)) . // web_document_url(1:lenocc(web_document_url)) c c ******************* (read arguments) c c c Read arguments used when launching the program, if there are any. Possible c args must be presented in order, though they do not all need to be present. c c 1. hostname for display c 2. CERN or CPPM to indicate at which site the program is executing c 3. x offset for strip plane 2 (positive means center is displaced in +x) c 4. y offset for strip plane 2 (positive means center is displaced in +y) c 5. x offset for strip plane 3 c 6. y offset for strip plane 3 c 7. x offset for strip plane 4 c 8. y offset for strip plane 4 c 9. x offset for pixel dem1 c 10. y offset for pixel dem1 c 11. x offset for pixel dem2 c 12. y offset for pixel dem2 c 13. x offset for pixel Marebo c 14. y offset for pixel Marebo c 15. x offset for pixel modeule c 16. y offset for pixel module c call event_display_get_args(ireturn_code) c if(ireturn_code .ne. 0) then print *,' event_display.exe had problem reading arguments!' print *,' continue, anyway...' else end if c c c ******************* (initialize some file names) c c c initialize some filenames, which depend on whether we're running this c at CPPM, or at CERN. if(run_at_cern) then c c cern... file_data=file_data_cern file_default_parameters=file_default_parameters_cern file_control=file_control_cern c else c c cppm... file_data=file_data_cppm file_default_parameters=file_default_parameters_cppm file_control=file_control_cppm c end if c c c ******************* (open graphics window) c c c open a graphics window if necessary: if(.not.window_is_open) then c call event_display_open_window(ireturn_code) c c window open OK? if(ireturn_code .ne. 0) then print *,' event_display failed to open graphics window!' print *,' return code was ', ireturn_code stop else window_is_open=.true. end if c end if c c c ******************* (calculate some geometry) c c c Now do the geometry calculations: call event_display_initialize_geometry c c c ******************* (draw detector elements) c c c now draw the elements in the telescope, ignoring the presence (or absence) c of hits... this routine clears the window before doing its drawing. By c doing this, we'll have a message area available on the screen. call event_display_draw_detector c c c ******************* (see what fonts are available) c c ifont_use=0 c c c since I have listed the fonts in order of preference, run through the c list backwards, so I am left with the existing font I'd most prefer. do ifont=10,1,-1 c c ixsettf returns 1 if the font doesn't exist, 0 if it does. c first argument is 0 to report on existence, 1 to load font if it exists. iexist=ixsettf(1, lenocc(font_name(ifont)), font_name(ifont)) c c now load the font... if(iexist_flag .eq. 0) then text='font ' // font_name(ifont)(1:lenocc(font_name(ifont))) . // 'exists.' ifont_use=ifont else text='font ' // font_name(ifont)(1:lenocc(font_name(ifont))) . // 'does not exist.' end if c ccc call event_display_write_message(text) c end do c c c Now report what I'm doing: if(ifont_use .eq. 0) then c call event_display_write_message( . 'No fonts on my list were found. Use default font.') c else c call event_display_write_message('Using font ' . // font_name(ifont_use)(1:lenocc(font_name(ifont_use))) ) c end if c c c ******************* (create a handshaking control file) c c call event_display_write_message( . 'about to create handshaking control file') c c call event_display_write_control_file(ireturn_code) c c c did we have problems? If so, bug out.. if(ireturn_code .ne. 0) then c call event_display_write_message( . '...problems writing handshaking control file!') c call event_display_write_message( . '...abnormal termination STOP!') c c ...force an update of the screen... mode_synchronize=10 call ixupdwi(mode_synchronize) c c also print to the log file if desired: if(debug) then print *,' oops, we had problems writing control file!' print *,' event_display_write_control_file return code: ', . ireturn_code print *,' abnormal termination...' end if c c wait a few seconds so user can read the bad news, then stop... call system('sleep 2') stop c end if c c c ******************* (message concerning resizing) c c call event_display_write_message('-') call event_display_write_message( . '>>=-> If you resize the window, click on it to refresh <-=<<') call event_display_write_message( . ' See '//web_document_url(1:lenocc(web_document_url))// . '.') call event_display_write_message('-') c c force an update of the screen... mode_synchronize=10 call ixupdwi(mode_synchronize) c c c ******************* (start of the event loop) c 100 continue c c handshaking with DAQ: if the DAQ deletes my control file, take this as c a sign that I should stop the event display program. Check for this now: call event_display_control_exists(file_exists) c if(.not. file_exists) then c c write message... call event_display_write_message( . 'Just received request from DAQ to stop. Good bye!') c c force an update of the screen... mode_synchronize=10 call ixupdwi(mode_synchronize) c c pause a bit, so there's time for the user to read the message: call system('sleep 2') c c set the stop-now flag, then return: i_want_to_stop=.true. c c head for the bottom of this module: go to 999 c end if c c c now get data for an event. When I am done with the event, delete the file c so that Thierry's code will realize that it is time to create a new file. c There is some information included in the file which specifies the angles c of the detectors, so redo my geometry calculations later. call event_display_get_event(ireturn_code) c c time to quit? if(i_want_to_stop) go to 999 c c here are the error codes returned by event_display_get_event (these are c copied from comments there; only the last error is reported): c 0 if everything's fine, and we have good event data. c 1 if we couldn't open the file c 2 if we hit the end-of-file before encountering "EOD" c 3 if we had a problem reading strip data header line c 4 if we had a problem reading dem1 data header line c 5 if we had a problem reading dem2 data header line c 6 if we had a problem reading marebo data header line c 7 if we couldn't delete the event data file after reading it c 8 if we tried reading detector data before encountering a header c -9 encountered bad strip detector data c -10 encountered bad run number, event number header line c -11 encountered bad dem1 detector data c -12 encountered bad dem2 detector data c -13 found fewer lines of strip hit data than expected c -14 found fewer lines of dem1 hit data than expected c -15 found fewer lines of dem2 hit data than expected c -16 found fewer lines of marebo hit data than expected c -17 encountered bad marebo detector data c c negative return codes are non-fatal errors... good_event=ireturn_code .le. 0 c c c ******************* (delete data file if fatal error) c if(.not. good_event) then c c see if the file exists inquire(file=file_data(1:lenocc(file_data)), . exist=file_exists) c c now delete it: if(file_exists) then c call event_display_write_message( . 'fatal error in data file, so attempting to delete it') c close(lun_data, iostat=io_err) call system('rm '//file_data) c else c call event_display_write_message( . 'fatal error in data file, which doesn.t seem to exist!') c end if c end if c c c ******************* (calculate some geometry) c 120 continue c c Now do the geometry calculations if we had a good event, since z's might c be different from my defaults, or the user might have resized the window. if(good_event) call event_display_initialize_geometry c c time to quit? if(i_want_to_stop) go to 999 c c c ******************* (draw detector elements) c c c now draw the elements in the telescope, ignoring the presence (or absence) c of hits... this routine clears the window before doing its drawing. call event_display_draw_detector c c time to quit? if(i_want_to_stop) go to 999 c c c ******************* (draw hits) c c c now draw hits in the telescope if we managed to read an event properly: if(good_event) then c call event_display_draw_hits c else c call event_display_write_message( . 'couldn.t draw hits since we had bad event data') end if c c time to quit? if(i_want_to_stop) go to 999 c c c ******************* (wait for user instructions via mouse event) c c c Now wait for the user to click on the window... call event_display_mouse_request(in_a_button,mouse_button) c c c ******************* (respond to the mouse event) c c c Figure out what to do in response to the mouse button click: call event_display_handle_mouse_event(in_a_button,mouse_button) c c time to quit? if(i_want_to_stop) go to 999 c c time to read the next event? if(i_want_new_event) go to 100 c c neither of these: user fooled around with angle or zoom buttons, so c redisplay the same event: go to 120 c c c ******************* (program termination phase starts here) c c c come down to here when the user wants to quit: 999 continue call event_display_write_message('time to clean up our toys...') c c c ******************* (delete the control file if so desired) c c c since we're stopping, delete the control file so that Thierry won't c keep writing events to disk for me. Also delete the data file in case it c didn't happen successfully in event_display_get_event. if(delete_file_when_finished) then c c c check that the control file exists: inquire(file=file_control(1:lenocc(file_control)), . exist=file_exists) c c c now delete it: if(file_exists) then close(lun_control, iostat=io_err) call system('rm '//file_control) call event_display_write_message( . 'just deleted control file '//file_control) end if c c c the data file should already have been deleted, but check anyway: inquire(file=file_data(1:lenocc(file_data)), . exist=file_exists) c c c now delete it: if(file_exists) then close(lun_data, iostat=io_err) call system('rm '//file_data) call event_display_write_message( . 'just deleted data file '//file_data) end if c else c c here if we DON'T want to delete the control file when quitting: c call event_display_write_message( . ' I am NOT deleting the control file '//file_control) call event_display_write_message( . ' I am NOT deleting the data file '//file_data) c end if c c c ******************* (time to quit) c c c say goodbye... call event_display_write_message('Au revoir!') c c ...force an update of the screen... mode_synchronize=10 call ixupdwi(mode_synchronize) c c ...pause, so user can read how friendly we are... call system('sleep 2') c c ...close all opened X11 windows (just being neat)... call ixclsds c c c ...and quit. stop end