Changeset 27751
- Timestamp:
- Apr 23, 2010, 11:33:14 AM (16 years ago)
- Location:
- trunk
- Files:
-
- 8 edited
-
PS-IPP-PStamp/lib/PS/IPP/PStamp/Job.pm (modified) (43 diffs)
-
ippTasks/pstamp.pro (modified) (6 diffs)
-
pstamp/scripts/pstamp_checkdependent.pl (modified) (11 diffs)
-
pstamp/scripts/pstamp_finish.pl (modified) (4 diffs)
-
pstamp/scripts/pstamp_job_run.pl (modified) (2 diffs)
-
pstamp/scripts/pstamp_parser_run.pl (modified) (3 diffs)
-
pstamp/scripts/pstamp_request_file (modified) (2 diffs)
-
pstamp/scripts/pstampparse.pl (modified) (25 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/PS-IPP-PStamp/lib/PS/IPP/PStamp/Job.pm
r27589 r27751 27 27 use PS::IPP::Config qw( :standard ); 28 28 use Carp; 29 use DateTime; 30 use File::Temp qw(tempfile); 31 use File::Basename; 32 use POSIX; 33 34 my $save_temps = 0; 29 35 30 36 # caches of camProcessedExp objects. … … 34 40 my %camRunByCamIDCache; 35 41 36 ### my @images = locate_images($image_db, $req_type, $img_type, $id, $component, 37 ### $mjd_min, $mjd_max, $filter); 42 # cache of last project looked up 43 my $last_project = ""; 44 45 my ($regtool, $chiptool, $camtool, $warptool, $stacktool, $difftool); 46 my ($pstamptool, $dvoImagesAtCoords, $whichimage, $ppConfigDump); 38 47 39 48 sub locate_images { 40 49 my $ipprc = shift; # required 41 my $image_db = shift; # required 50 my $imagedb = shift; # required 51 my $rowList = shift; # required 42 52 my $req_type = shift; # required 43 53 my $img_type = shift; # required … … 47 57 my $option_mask = shift; 48 58 my $need_magic = shift; 49 my $x = shift;50 my $y = shift;51 59 my $mjd_min = shift; 52 60 my $mjd_max = shift; … … 56 64 57 65 # we die in response to bad data in request files 58 # The wrapper script is responsible for updating the database 59 die "Unknown req_type: $req_type" 66 # The caller is responsible for updating the database 67 # pstampparse.pl error checks now so this shouldn't happen 68 &my_die("Unknown req_type: $req_type", $PS_EXIT_PROG_ERROR) 60 69 if ($req_type ne "byid") and 61 70 ($req_type ne "byexp") and … … 84 93 85 94 if ($req_type eq "bycoord") { 86 my $results = lookup_bycoord($ipprc, $image_db, $img_type, $tess_id, $component, $need_magic, $x, $y, $dateobs_begin, $dateobs_end, $filter, $data_group, $option_mask, $verbose); 95 my $num_rows = scalar @$rowList; 96 die "Unexpected number of rows found in rowList: $num_rows" if $num_rows != 1; 97 my $row = $rowList->[0]; 98 my $x = $row->{CENTER_X}; 99 my $y = $row->{CENTER_Y}; 100 my $results = lookup_bycoord($ipprc, $rowList, $imagedb, $img_type, $tess_id, $component, $need_magic, $x, $y, $dateobs_begin, $dateobs_end, $filter, $data_group, $option_mask, $verbose); 87 101 return $results; 88 102 } … … 93 107 # in one place 94 108 $req_type = "bydiff"; 95 my $results = lookup_diff($ipprc, $ image_db, $id, $component, 1, $option_mask, $img_type, $verbose);109 my $results = lookup_diff($ipprc, $rowList, $imagedb, $id, $component, 1, $option_mask, $img_type, $verbose); 96 110 return $results; 97 111 } 98 112 99 113 if ($req_type eq "bydiff") { 100 my $results = lookup_diff($ipprc, $image_db, $id, $component, 0, $option_mask, $img_type, $verbose); 114 # for bydiff reuqests we go look up the diffRun to obtain exp_id, chip_id, warp_id, stack_id, or 115 # the image from the diffRun 116 my $results = lookup_diff($ipprc, $rowList, $imagedb, $id, $component, 0, $option_mask, $img_type, $verbose); 101 117 if (!$results) { 102 118 return undef; … … 130 146 # fall though and lookup by stack_id 131 147 } else { 132 # shouldn't I checkthis elsewhere?148 # This is checked this elsewhere? 133 149 print STDERR "Error: $img_type is an unknown image type\n"; 134 150 return undef; … … 145 161 } 146 162 147 my $results = lookup($ipprc, $ image_db, $req_type, $img_type, $id, $tess_id, $component, $need_magic,148 $ dateobs_begin, $dateobs_end, $filter, $data_group, $option_mask, $verbose);163 my $results = lookup($ipprc, $rowList, $imagedb, $req_type, $img_type, $id, $tess_id, $component, 164 $need_magic, $dateobs_begin, $dateobs_end, $filter, $data_group, $option_mask, $verbose); 149 165 150 166 return $results; 151 167 } 168 169 # The subroutine lookup handles byexp, byid, and byskycell lookups including lookups that are 170 # triggered by a bydiff request 152 171 153 172 sub lookup 154 173 { 155 174 my $ipprc = shift; 156 my $image_db = shift; 175 my $rowList = shift; 176 my $imagedb = shift; 157 177 my $req_type = shift; 158 my $ img_type = shift;178 my $stage = shift; 159 179 my $id = shift; 160 180 my $tess_id = shift; … … 172 192 my $use_imfile_id = ($req_type eq "byid") && ($option_mask & $PSTAMP_USE_IMFILE_ID); 173 193 174 my $missing_tools;175 my $regtool = can_run('regtool') or (warn "Can't find regtool" and $missing_tools = 1);176 my $chiptool = can_run('chiptool') or (warn "Can't find chiptool" and $missing_tools = 1);177 my $warptool = can_run('warptool') or (warn "Can't find warptool" and $missing_tools = 1);178 my $difftool = can_run('difftool') or (warn "Can't find difftool" and $missing_tools = 1);179 my $stacktool = can_run('stacktool') or (warn "Can't find stacktool" and $missing_tools = 1);180 if ($missing_tools) {181 warn("Can't find required tools.");182 exit ($PS_EXIT_CONFIG_ERROR);183 }184 194 my $command; 185 195 my $id_opt; # option for the lookup … … 203 213 my $magic_arg = $need_magic ? " -destreaked" : ""; 204 214 215 # all rows have the same center type 216 my $skycenter = ! ($rowList->[0]->{COORD_MASK} & $PSTAMP_CENTER_IN_PIXELS); 217 205 218 my $component_args; 206 if ($img_type eq "raw") { 219 my $choose_components = 0; 220 if ($stage eq "raw") { 207 221 $class_id = $component; 208 $command = "$regtool -processedimfile -dbname $image _db";222 $command = "$regtool -processedimfile -dbname $imagedb"; 209 223 # XXX: for now restrict lookups to type object 210 224 # are stamps of detrend exposures interesting? … … 214 228 $want_astrom = 1; 215 229 $set_class_id = 1; 216 } elsif ($ img_type eq "chip") {230 } elsif ($stage eq "chip") { 217 231 $class_id = $component; 218 $command = "$chiptool -processedimfile -dbname $image_db"; 219 $component_args = " -class_id $class_id" if $class_id; 232 # if the request is such that it will yield a single image per "run" or the 233 # center is specified in pixel coordinates 234 # use chiptool -processsedimfile. Otherwise use chiptool -listrun and then 235 # choose the chips containing the center pixel by calling selectComponets() below 236 if ($class_id or $use_imfile_id or !$skycenter) { 237 $command = "$chiptool -processedimfile -dbname $imagedb"; 238 $component_args = " -class_id $class_id" if $class_id; 239 } else { 240 $command = "$chiptool -listrun -pstamp_order -dbname $imagedb"; 241 $choose_components = 1; 242 } 220 243 $id_opt = $use_imfile_id ? "-chip_imfile_id" : "-chip_id"; 244 # XXX: perhaps we should stop resolving images to this level here and do it at job run time. 245 # With the mdc file it has all of the information that it needs. 221 246 $image_name = "PPIMAGE.CHIP"; 222 247 $mask_name = "PPIMAGE.CHIP.MASK"; … … 228 253 $want_astrom = 1; 229 254 $set_class_id = 1; 230 } elsif ($ img_type eq "warp") {255 } elsif ($stage eq "warp") { 231 256 $skycell_id = $component; 232 $command = "$warptool -warped -dbname $image_db"; 233 $component_args = " -skycell_id $skycell_id" if $skycell_id; 257 if ($skycell_id or $use_imfile_id or !$skycenter) { 258 $command = "$warptool -warped -dbname $imagedb"; 259 $component_args = " -skycell_id $skycell_id" if $skycell_id; 260 } else { 261 $command = "$warptool -listrun -pstamp_order -dbname $imagedb"; 262 $choose_components = 1; 263 } 234 264 $id_opt = $use_imfile_id ? "-warp_skyfile_id" : "-warp_id"; 235 265 $image_name = "PSWARP.OUTPUT"; … … 239 269 $psf_name = "PSPHOT.PSF.SKY.SAVE"; 240 270 $base_name = "path_base"; # name of the field for the warptool output 241 } elsif ($ img_type eq "diff") {271 } elsif ($stage eq "diff") { 242 272 $skycell_id = $component; 243 $command = "$difftool -diffskyfile -dbname $image_db"; 244 $component_args = " -skycell_id $skycell_id" if $skycell_id; 273 if ($skycell_id or $use_imfile_id or !$skycenter) { 274 $command = "$difftool -diffskyfile -dbname $imagedb"; 275 $component_args = " -skycell_id $skycell_id" if $skycell_id; 276 } else { 277 $command = "$difftool -listrun -pstamp_order -dbname $imagedb"; 278 $choose_components = 1; 279 } 245 280 $id_opt = $use_imfile_id ? "-diff_skyfile_id" : "-diff_id"; 246 281 $image_name = "PPSUB.OUTPUT"; … … 250 285 $psf_name = "PSPHOT.PSF.SKY.SAVE"; 251 286 $base_name = "path_base"; 252 } elsif ($ img_type eq "stack") {287 } elsif ($stage eq "stack") { 253 288 $skycell_id = $component; 254 $command = "$stacktool -sumskyfile -dbname $image _db";289 $command = "$stacktool -sumskyfile -dbname $imagedb"; 255 290 $id_opt = "-stack_id"; 256 291 $component_args = " -skycell_id $skycell_id" if $skycell_id; … … 272 307 $base_name = "path_base"; 273 308 } else { 274 die "Unknown img_type supplied: $img_type"; 275 } 276 309 die "Unknown IMG_TYPe supplied: $stage"; 310 } 311 312 my $filter_runs = 0; 277 313 if ($req_type eq "byid") { 278 314 $command .= " $id_opt $id"; … … 288 324 # the reason as 'not destreaked' 289 325 $magic_arg = ""; 326 # remove duplicate runs for the same exposure. 327 $filter_runs = 1; 290 328 } elsif ($req_type eq "byskycell") { 291 329 die "tess_id and component are required for byskycell" if !$tess_id or ! $skycell_id; 292 330 $command .= " -tess_id $tess_id -skycell_id $skycell_id"; 293 331 } else { 294 die "Unknown req_type supplied: $req_type"; 295 } 296 297 if ($img_type ne "stack") { 332 # this should be caught by caller 333 &my_die("Unexpected req_type supplied: $req_type", $PS_EXIT_PROG_ERROR); 334 } 335 336 if ($stage ne "stack") { 298 337 $command .= $magic_arg; 299 338 $command .= " -dateobs_begin $dateobs_begin" if $dateobs_begin; … … 304 343 $command .= " -data_group $data_group" if !isnull($data_group); 305 344 306 # run the tool and parse the output 307 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = 308 run(command => $command, verbose => $verbose); 309 unless ($success) { 310 # not sure if we should die here 311 print STDERR @$stderr_buf; 345 my $images = runToolAndParse($command, $verbose); 346 347 if (!$images or scalar @$images == 0) { 312 348 return undef; 313 349 } 314 350 315 my $buf = join "", @$stdout_buf; 316 if (!$buf) { 317 return; 318 } 319 320 my $mdcParser = PS::IPP::Metadata::Config->new; 321 my $images = parse_md_fast($mdcParser, $buf) 322 or die ("Unable to parse metadata config doc"); 323 351 if ($filter_runs) { 352 # The image selectors are such that multiple runs my have be returned for the same exposure. 353 # Return only the latest one. 354 $images = filterRuns($stage, $need_magic, $images, $verbose); 355 } 356 if ($choose_components) { 357 # the list of "images" is actually a list of "Runs" 358 # match the coords in the rows to the components in the runs 359 # returns an actual list of images 360 $images = selectComponents($ipprc, $imagedb, $req_type, $stage, $rowList, $images, $verbose); 361 } else { 362 # put each of the rows into all of the the images 363 setRowRefs($rowList, $images); 364 } 365 366 my $camera; 324 367 my $output = []; 325 326 my $camera;327 368 foreach my $image (@$images) { 328 369 my $base; 329 370 330 371 next if $image->{fault}; 331 next if ($ img_type ne "raw") and $image->{quality};372 next if ($stage ne "raw") and $image->{quality}; 332 373 333 374 if ($base_name) { … … 361 402 } 362 403 my $stage_id; 363 if ($ img_type eq "raw") {404 if ($stage eq "raw") { 364 405 $stage_id = $image->{exp_id}; 365 } elsif ($ img_type eq "chip") {406 } elsif ($stage eq "chip") { 366 407 $stage_id = $image->{chip_id}; 367 } elsif ($ img_type eq "warp") {408 } elsif ($stage eq "warp") { 368 409 $stage_id = $image->{warp_id}; 369 } elsif ($ img_type eq "diff") {410 } elsif ($stage eq "diff") { 370 411 $stage_id = $image->{diff_id}; 371 412 if ($inverse && $image->{bothways}) { … … 375 416 $cmf_name = "PPSUB.INVERSE.SOURCES"; 376 417 } 377 } elsif ($ img_type eq "stack") {418 } elsif ($stage eq "stack") { 378 419 $stage_id = $image->{stack_id}; 379 420 } 380 421 $out->{stage_id} = $stage_id; 381 $out->{stage} = $ img_type;382 $out->{image _db} = $image_db;422 $out->{stage} = $stage; 423 $out->{imagedb} = $imagedb; 383 424 384 425 if ($base) { … … 390 431 $out->{backmdl}= $ipprc->filename($backmdl_name, $base, $class_id) if $backmdl_name; 391 432 } 392 $out->{astrom} = find_astrometry($ipprc, $image_db, $image, $verbose) if $want_astrom; 433 if ($want_astrom and ! defined $out->{astrom}) { 434 $out->{astrom} = find_astrometry($ipprc, $imagedb, $image, $verbose); 435 } 393 436 394 437 push @$output, $out; … … 397 440 return $output; 398 441 } 442 399 443 sub lookup_diff { 400 444 my $ipprc = shift; 401 my $image_db = shift; 445 my $rowList = shift; 446 my $imagedb = shift; 402 447 my $id = shift; 403 448 my $skycell_id = shift; … … 409 454 my $inverse = $option_mask & $PSTAMP_SELECT_INVERSE; 410 455 411 my $missing_tools; 412 my $difftool = can_run('difftool') or (warn "Can't find difftool" and $missing_tools = 1); 413 if ($missing_tools) { 414 warn("Can't find required tools."); 415 exit ($PS_EXIT_CONFIG_ERROR); 416 } 417 418 my $command = "$difftool -diffskyfile -dbname $image_db"; 456 my $command = "$difftool -diffskyfile -dbname $imagedb"; 419 457 420 458 if ($byid) { … … 425 463 $command .= " -skycell_id $skycell_id" if $skycell_id; 426 464 427 # run the tool and parse the output 428 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = 429 run(command => $command, verbose => $verbose); 430 unless ($success) { 431 # not sure if we should die here 432 print STDERR @$stderr_buf; 433 return undef; 434 } 435 436 my $buf = join "", @$stdout_buf; 437 if (!$buf) { 438 return undef; 439 } 440 441 my $mdcParser = PS::IPP::Metadata::Config->new; 442 my $images = parse_md_fast($mdcParser, $buf) 443 or die ("Unable to parse metadata config doc"); 465 my $images = runToolAndParse($command, $verbose); 444 466 445 467 my $n = @$images; … … 527 549 528 550 if ($img_type eq "diff") { 551 my @imageList = ($image); 552 553 setRowRefs($rowList, \@imageList); 529 554 # the $image is going to be returned directly in this case so we need to duplicate 530 555 # some of processing that lookup does for other img_types … … 539 564 $image->{stage_id} = $image->{diff_id}; 540 565 $image->{stage} = "diff"; 541 $image->{image _db} = $image_db;566 $image->{imagedb} = $imagedb; 542 567 $image->{component} = $image->{skycell_id}; 543 568 } else { … … 554 579 sub lookup_bycoord { 555 580 my $ipprc = shift; 556 my $image_db = shift; 581 my $rowList = shift; 582 my $imagedb = shift; 557 583 my $img_type = shift; 558 584 my $tess_id = shift; … … 568 594 my $verbose = shift; 569 595 570 my $missing_tools;571 my $regtool = can_run('regtool') or (warn "Can't find regtool" and $missing_tools = 1);572 my $camtool = can_run('camtool') or (warn "Can't find camtool" and $missing_tools = 1);573 my $dvoImagesAtCoords = can_run('dvoImagesAtCoords') or (warn "Can't find dvoImagesAtCoords" and $missing_tools = 1);574 my $whichimage = can_run('whichimage') or (warn "Can't find whichimage" and $missing_tools = 1);575 if ($missing_tools) {576 warn("Can't find required tools.");577 exit ($PS_EXIT_CONFIG_ERROR);578 }579 580 596 my $results = (); 581 597 if (($img_type eq "raw") or ($img_type eq "chip")) { 582 598 583 my $runs = lookup_runs_by_cam id_and_coords($ipprc, $image_db, $img_type,599 my $runs = lookup_runs_by_cam_id_and_coords($ipprc, $imagedb, $img_type, 584 600 $ra, $dec, $need_magic, $dateobs_begin, $dateobs_end, $filter, $data_group, $verbose); 585 601 602 # lookup is going to filter these we don't need to do it here 603 # $runs = filterRuns($img_type, $need_magic, $runs, $verbose); 586 604 foreach my $run (@$runs) { 587 605 next if $component and ($run->{component} ne $component); 588 my $these_results = lookup($ipprc, $ image_db, "byid", $img_type, $run->{id},606 my $these_results = lookup($ipprc, $rowList, $imagedb, "byid", $img_type, $run->{id}, 589 607 $tess_id, $run->{component}, $need_magic, 590 608 $dateobs_begin, $dateobs_end, $filter, $data_group, $option_mask, $verbose); … … 602 620 603 621 foreach my $skycell (@$skycells) { 604 my $these_results = lookup($ipprc, $ image_db, "byskycell", $img_type, undef,622 my $these_results = lookup($ipprc, $rowList, $imagedb, "byskycell", $img_type, undef, 605 623 $skycell->{tess_id}, $skycell->{component}, $need_magic, 606 624 $dateobs_begin, $dateobs_end, $filter, $data_group, $option_mask, $verbose); … … 614 632 } 615 633 616 # lookup_runs_by_cam id_and_coords634 # lookup_runs_by_cam_id_and_coords 617 635 # given an ra, dec, and optionally other paramters, find camera runs for exposures 618 636 # that are within some distance of the coordinates 619 sub lookup_runs_by_cam id_and_coords {637 sub lookup_runs_by_cam_id_and_coords { 620 638 my $ipprc = shift; 621 my $image _db = shift;639 my $imagedb = shift; 622 640 my $img_type = shift; 623 641 my $ra = shift; … … 631 649 632 650 my $camruns; 633 my $missing_tools;634 my $camtool = can_run('camtool') or (warn "Can't find camtool" and $missing_tools = 1);635 my $dvoImagesAtCoords = can_run('dvoImagesAtCoords') or (warn "Can't find dvoImagesAtCoords" and $missing_tools = 1);636 if ($missing_tools) {637 warn("Can't find required tools.");638 exit ($PS_EXIT_CONFIG_ERROR);639 }640 651 641 652 { 642 my $command = "$camtool -dbname $image _db -processedexp";653 my $command = "$camtool -dbname $imagedb -processedexp -pstamp_order"; 643 654 $command .= " -ra $ra -decl $dec -radius 1.6"; 644 655 $command .= " -dateobs_begin $dateobs_begin" if $dateobs_begin; … … 652 663 $command .= " -data_group $data_group" if $data_group; 653 664 $command .= " -destreaked" if $need_magic; 665 654 666 # run the tool and parse the output 655 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = 656 run(command => $command, verbose => $verbose); 657 unless ($success) { 658 print STDERR @$stderr_buf; 659 return undef; 660 } 661 my $mdcParser = PS::IPP::Metadata::Config->new; # Parser for metadata config files 662 663 my $output = join "", @$stdout_buf; 664 if (!$output) { 665 print STDERR "no output returned from $command\n" if $verbose; 666 return undef; 667 } 668 $camruns = parse_md_fast($mdcParser, $output); 667 $camruns = runToolAndParse($command, $verbose); 669 668 } 670 669 if (!$camruns) { … … 672 671 } 673 672 my $runs; 673 my $last_exp_id = 0; 674 674 foreach my $camRun (@$camruns) { 675 675 my $cam_id = $camRun->{cam_id}; 676 677 updateCamRunCache($camRun); 676 my $exp_id = $camRun->{exp_id}; 677 678 next if $exp_id eq $last_exp_id; 678 679 679 680 next if $camRun->{quality}; 680 681 next if $camRun->{fault}; 682 683 updateCamRunCache($camRun); 684 685 $last_exp_id = $exp_id; 686 681 687 # XXX Use file rule 682 688 my $astrom = $camRun->{path_base} . ".smf"; … … 684 690 next if !$astrom_resolved; 685 691 692 my $start_dvo = DateTime->now->mjd; 686 693 my $command = "$dvoImagesAtCoords -astrom $astrom_resolved $ra $dec"; 687 694 # run the tool and parse the output 695 my $dvo_verbose = 0; 688 696 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = 689 run(command => $command, verbose => $verbose); 697 run(command => $command, verbose => $dvo_verbose); 698 my $dtime_dvo = (DateTime->now->mjd - $start_dvo)* 86400.; 699 # print "Time to run dvoImagesAtCoords: $dtime_dvo\n"; 690 700 unless ($success) { 691 701 my $result_code = $error_code >> 8; 692 702 if ($result_code == $PSTAMP_NO_OVERLAP) { 693 print STDERR"no overlap for $astrom\n" if $verbose;703 print "no overlap for $astrom\n" if $verbose; 694 704 next; 695 705 } … … 721 731 die "unexpected output from dvoImagesAtCoords: $lines[0]"; 722 732 } 733 734 print "cam_id $cam_id exp_id $camRun->{exp_id} chip_id $camRun->{chip_id} $class_id\n"; 735 723 736 # build the hash to return 724 737 my $run = { … … 732 745 }; 733 746 if ($img_type eq "chip") { 734 $run->{id} = $run->{chip_id}; 747 $run->{id} = $camRun->{chip_id}; 748 $run->{state} = $camRun->{chip_state}; 749 $run->{magicked} = $camRun->{chip_magicked}; 735 750 } else { 736 $run->{id} = $run->{exp_id}; 751 $run->{id} = $camRun->{exp_id}; 752 $run->{state} = 'full'; 753 $run->{magicked} = $camRun->{raw_magicked}; 737 754 } 738 755 push @$runs, $run; … … 749 766 my $dec = shift; 750 767 my $verbose = shift; 751 752 my $missing_tools;753 my $whichimage = can_run('whichimage') or (warn "Can't find whichimage" and $missing_tools = 1);754 if ($missing_tools) {755 warn("Can't find required tools.");756 exit ($PS_EXIT_CONFIG_ERROR);757 }758 768 759 769 $requested_tess_id = "" if isnull($requested_tess_id); … … 817 827 sub find_astrometry { 818 828 my $ipprc = shift; 819 my $image _db = shift;829 my $imagedb = shift; 820 830 my $image = shift; # hashref to output of the lookup tool 821 831 my $verbose = shift; … … 825 835 my $exp_id = $image->{exp_id}; 826 836 if (($exp_id eq $last_exp_id) and $lastAstromFile) { 827 # running camtool 60 times is really expensive when the answer is the same 837 # running camtool 60 times is really expensive when the answer is the same every time 828 838 return $lastAstromFile; 829 839 } … … 831 841 $lastAstromFile = undef; 832 842 833 my $missing_tools;834 my $camtool = can_run("camtool") or (warn "Can't find camtool" and $missing_tools = 1);835 my $ppConfigDump = can_run('ppConfigDump') or (warn "Can't find ppConfigDump" and $missing_tools = 1);836 if ($missing_tools) {837 warn("Can't find required tools.");838 exit ($PS_EXIT_CONFIG_ERROR);839 }840 841 843 my $camRun = getCamRunByExpID($exp_id); 842 844 if (!$camRun) { 843 my $command = "$camtool -dbname $image _db -processedexp -exp_id $exp_id";845 my $command = "$camtool -dbname $imagedb -processedexp -exp_id $exp_id -pstamp_order"; 844 846 # run the tool and parse the output 845 847 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = … … 864 866 # If there are multiple cam runs for this exposure, take the last completed one with good quality 865 867 # on the assumption that it has the best astrometry. 866 while ($camRun = pop@$camruns) {867 last if (($camRun->{ quality} eq 0) and ($camRun->{fault} eq 0));868 foreach $camRun (@$camruns) { 869 last if (($camRun->{state} eq 'full') and ($camRun->{quality} eq 0) and ($camRun->{fault} eq 0)); 868 870 } 869 871 # XXX: this looks like a bug at least if ASTROM.SOURCE eq PSASTRO.OUTPUT … … 959 961 # resolve_project() 960 962 # get project specific information 961 my $last_project = "";962 963 sub resolve_project { 963 964 my $ipprc = shift; 964 965 my $project_name = shift; 965 966 967 findTools(); 968 966 969 if (!$project_name) { 967 970 carp ("project is not defined"); … … 978 981 my $verbose = 0; 979 982 980 my $missing_tools;981 my $pstamptool = can_run("pstamptool") or (warn "Can't find pstamptool" and $missing_tools = 1);982 if ($missing_tools) {983 warn("Can't find required tools.");984 exit ($PS_EXIT_CONFIG_ERROR);985 }986 987 983 my $command = "$pstamptool -project -name $project_name"; 988 984 $command .= " -dbname $dbname" if defined $dbname; 989 985 $command .= " -dbserver $dbserver" if defined $dbserver; 990 # run the tool and parse the output 991 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = 992 run(command => $command, verbose => $verbose); 993 unless ($success) { 994 print STDERR @$stderr_buf; 986 987 my $proj_hash = runToolAndParse($command, $verbose); 988 if (!$proj_hash or scalar @$proj_hash == 0) { 989 print STDERR "Project $project_name not found\n"; 995 990 return undef; 996 991 } 997 998 my $mdcParser = PS::IPP::Metadata::Config->new; # Parser for metadata config files999 1000 my $output = join "", @$stdout_buf;1001 if (!$output) {1002 print STDERR "no output returned from $command\n" if $verbose;1003 return undef;1004 }1005 my $proj_hash = parse_md_fast($mdcParser, $output);1006 992 1007 993 $last_project = $proj_hash->[0]; … … 1035 1021 sub getCamRunByExpID { 1036 1022 my $exp_id = shift; 1037 die "getCamRun: exp_id is nil"if !$exp_id;1023 &my_die ("getCamRun: exp_id is nil", $PS_EXIT_PROG_ERROR) if !$exp_id; 1038 1024 1039 1025 return $camRunByExpIDCache{$exp_id}; 1040 1026 } 1027 1041 1028 sub getCamRunByCamID { 1042 1029 my $cam_id = shift; 1043 die "getCamRun: cam_id is nil"if !$cam_id;1030 &my_die ("getCamRun: cam_id is nil", $PS_EXIT_PROG_ERROR) if !$cam_id; 1044 1031 1045 1032 return $camRunByCamIDCache{$cam_id}; 1046 1033 } 1034 1035 sub selectComponents { 1036 my $ipprc = shift; 1037 my $imagedb = shift; 1038 my $req_type = shift; 1039 my $stage = shift; 1040 my $rowList = shift; 1041 my $runList = shift; 1042 my $verbose = shift; 1043 my $results = []; 1044 1045 my ($pointsList, $pointsListName) = tempfile ("/tmp/pointsList.XXXX", UNLINK => !$save_temps); 1046 my $npoints = 0; 1047 foreach my $row (@$rowList) { 1048 print $pointsList "$npoints $row->{CENTER_X} $row->{CENTER_Y}\n"; 1049 $npoints++; 1050 } 1051 close $pointsList; 1052 1053 # XXX: need to loop over these 1054 # my $run = $runList->[0]; 1055 if (($req_type eq "byid") or ($req_type eq "byexp")) { 1056 my ($last_tess_id, $tess_dir_abs, $astrom_file) = ("", "", ""); 1057 foreach my $run (@$runList) { 1058 my $command = "$dvoImagesAtCoords -coords $pointsListName"; 1059 if (($stage eq "chip") or ($stage eq "raw")) { 1060 # XXX: use file rule and handle cameras where the astrometry is solved at 1061 # the chip stage. 1062 $astrom_file = $run->{cam_path_base} . ".smf"; 1063 my $astrom_file_resolved = $ipprc->file_resolve($astrom_file); 1064 $command .= " -astrom $astrom_file_resolved"; 1065 } else { 1066 my $tess_id = $run->{tess_id}; 1067 if ($tess_id ne $last_tess_id) { 1068 $tess_dir_abs = $ipprc->tessellation_catdir( $tess_id ); 1069 $tess_dir_abs = $ipprc->convert_filename_absolute( $tess_dir_abs ); 1070 $last_tess_id = $tess_id; 1071 } 1072 $command .= " -D CATDIR $tess_dir_abs" 1073 } 1074 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = 1075 run(command => $command, verbose => $verbose); 1076 unless ($success) { 1077 # don't fail if the program exited normally and exit status was PSTAMP_NO_OVERLAP 1078 # # That just means that the coordinate didn't match any image/skycell 1079 if (!WIFEXITED($error_code) || (WEXITSTATUS($error_code) ne $PSTAMP_NO_OVERLAP)) { 1080 print STDERR @$stderr_buf; 1081 my $rc = WIFEXITED($error_code) ? WEXITSTATUS($error_code) : $PS_EXIT_SYS_ERROR; 1082 &my_die( "dvoImagesAtCoords failed: $rc", $rc); 1083 } 1084 } 1085 my %components; 1086 my @lines = split "\n", join "", @$stdout_buf; 1087 foreach my $line (@lines) { 1088 my ($ptnum, undef, undef, $component) = split " ", $line; 1089 my $ref = $components{$component}; 1090 if (!$ref) { 1091 $ref = $components{$component} = []; 1092 } 1093 push @$ref, $ptnum; 1094 } 1095 if ($verbose) { 1096 foreach my $c (keys %components) { 1097 my $ref = $components{$c}; 1098 print "component $c contains: "; 1099 foreach my $i (@$ref) { 1100 print "$i "; 1101 } 1102 print "\n"; 1103 } 1104 } 1105 # now find the images for this run 1106 foreach my $c (keys %components) { 1107 my $command; 1108 my $stage_id; 1109 if ($stage eq 'raw') { 1110 $stage_id = $run->{exp_id}; 1111 $command = "$regtool -processedimfile -exp_id $stage_id -class_id $c"; 1112 } elsif ($stage eq 'chip') { 1113 $stage_id = $run->{chip_id}; 1114 $command = "$chiptool -processedimfile -chip_id $stage_id -class_id $c"; 1115 } elsif ($stage eq 'warp') { 1116 $stage_id = $run->{warp_id}; 1117 $command = "$warptool -warped -warp_id $stage_id -skycell_id $c"; 1118 } elsif ($stage eq 'diff') { 1119 $stage_id = $run->{diff_id}; 1120 $command = "$difftool -diffskyfile -diff_id $stage_id -skycell_id $c"; 1121 } 1122 $command .= " -dbname $imagedb"; 1123 my $images = runToolAndParse($command, $verbose); 1124 if (!defined $images) { 1125 # XXX: need to get the set error_code to $PSTAMP_NO_OVERLAP 1126 print "No components containing coordinates found for ${stage}_id $stage_id\n"; 1127 foreach my $row (@$rowList) { 1128 $row->{error_code} = $PSTAMP_NO_OVERLAP; 1129 } 1130 next; 1131 } 1132 if (scalar @$images != 1) { 1133 my $num_images = scalar @$images; 1134 &my_die ("unexpected number of images returned: $num_images\n", $PS_EXIT_PROG_ERROR); 1135 } 1136 my $image = $images->[0]; 1137 1138 my $ref = $components{$c}; 1139 $image->{row_index} = $ref; 1140 if (($stage eq "raw") or ($stage eq 'chip')) { 1141 $image->{astrom} = $astrom_file; 1142 $image->{cam_id} = $run->{cam_id}; 1143 $image->{cam_path_base} = $run->{cam_path_base}; 1144 } 1145 push @$results, $image; 1146 } 1147 } 1148 } else { 1149 &my_die ("sorry not done with $req_type\n", $PS_EXIT_PROG_ERROR); 1150 } 1151 return $results; 1152 } 1153 1154 sub filterRuns { 1155 my $stage = shift; 1156 my $need_magic = shift; 1157 my $inputs = shift; 1158 my $verbose = shift; 1159 1160 if ($inputs and (scalar @$inputs) == 1) { 1161 # one run nothing to do 1162 return $inputs; 1163 } 1164 1165 my $output = []; 1166 1167 return $output if (!$inputs or scalar @$inputs == 0); 1168 1169 my $id_name = $stage . "_id"; 1170 1171 # input list is "order by exp_id, run_id DESC" run_id is one of (chip_id, warp_id, diff_id) 1172 print "Starting filterRuns\n"; 1173 my $last_exp_id = 0; 1174 my $last_run_id = 0; 1175 my $printed = 0; 1176 foreach my $input (@$inputs) { 1177 my $exp_id = $input->{exp_id}; 1178 my $run_id = $input->{$id_name}; 1179 my $magicked = $input->{magicked}; # this will be either stageRun.magicked or stage%file.magicked 1180 my $state = $input->{state}; 1181 1182 # can't process run in these states 1183 if (($state eq 'new') or ($state eq 'purged') or ($state eq 'scrubbed')) { 1184 print "skipping ${stage}Run $run_id for exp_id $exp_id in state $state\n"; 1185 next; 1186 } 1187 1188 $printed = 1 if (($exp_id == $last_exp_id) and ($run_id == $last_run_id)); 1189 1190 # skip if we need magicked run and this one has never been magicked 1191 if ($need_magic and !$magicked) { 1192 print "skipping ${stage}Run $run_id for exp_id $exp_id not magicked\n" if !$printed; 1193 next; 1194 } 1195 1196 if (($exp_id == $last_exp_id) and ($run_id != $last_run_id)) { 1197 print "Skipping duplicate ${stage}Run $run_id for $exp_id\n" if !$printed; 1198 next; 1199 } 1200 print "Keeping ${stage}Run $run_id for $exp_id\n"; 1201 push @$output, $input; 1202 $last_exp_id = $exp_id; 1203 $last_run_id = $run_id; 1204 $printed = 0; 1205 } 1206 1207 my $num_runs = scalar @$output; 1208 print "filterRuns returning $num_runs ${stage}Run\n"; 1209 1210 return $output; 1211 } 1212 1213 # run a command that produces metadata output and parse the results into an array of objects 1214 sub runToolAndParse { 1215 my $command = shift; 1216 my $verbose = shift; 1217 1218 my ($program) = split " ", $command; 1219 $program = basename($program); 1220 1221 print "Running $command\n" if !$verbose; 1222 my $start_tool = DateTime->now->mjd; 1223 # run the command and parse the output 1224 1225 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = 1226 run(command => $command, verbose => $verbose); 1227 unless ($success) { 1228 # not sure if we should die here 1229 print STDERR @$stderr_buf; 1230 return undef; 1231 } 1232 1233 my $now = DateTime->now->mjd; 1234 my $dtime_tool = (DateTime->now->mjd - $start_tool) * 86400.; 1235 print "Time to run $program: $dtime_tool\n"; 1236 1237 my $buf = join "", @$stdout_buf; 1238 if (!$buf) { 1239 return undef; 1240 } 1241 1242 my $start_parse = DateTime->now->mjd; 1243 1244 my $mdcParser = PS::IPP::Metadata::Config->new; 1245 my $results = parse_md_fast($mdcParser, $buf) 1246 or die ("Unable to parse metadata config doc"); 1247 1248 my $dtime_parse = (DateTime->now->mjd - $start_parse) * 86400.; 1249 print "Time to parse results from $program: $dtime_parse\n"; 1250 1251 return $results; 1252 } 1253 1254 sub findTools { 1255 return if ($regtool); 1256 1257 my $missing_tools; 1258 $regtool = can_run('regtool') or (warn "Can't find regtool" and $missing_tools = 1); 1259 $chiptool = can_run('chiptool') or (warn "Can't find chiptool" and $missing_tools = 1); 1260 $camtool = can_run('camtool') or (warn "Can't find camtool" and $missing_tools = 1); 1261 $warptool = can_run('warptool') or (warn "Can't find warptool" and $missing_tools = 1); 1262 $difftool = can_run('difftool') or (warn "Can't find difftool" and $missing_tools = 1); 1263 $stacktool = can_run('stacktool') or (warn "Can't find stacktool" and $missing_tools = 1); 1264 $pstamptool = can_run('pstamptool') or (warn "Can't find pstamptool" and $missing_tools = 1); 1265 $dvoImagesAtCoords = can_run('dvoImagesAtCoords') or (warn "Can't find dvoImagesAtCoords" 1266 and $missing_tools = 1); 1267 $whichimage = can_run('whichimage') or (warn "Can't find whichimage" and $missing_tools = 1); 1268 $ppConfigDump = can_run('ppConfigDump') or (warn "Can't find ppConfigDump" and $missing_tools = 1); 1269 if ($missing_tools) { 1270 warn("Can't find required tools."); 1271 exit ($PS_EXIT_CONFIG_ERROR); 1272 } 1273 } 1274 1275 # add a row_index array to a set of images with entries for each of the rows in a list 1276 sub setRowRefs { 1277 my $rowList = shift; 1278 my $images = shift; 1279 1280 my $row_index = []; 1281 for (my $i = 0; $i < scalar @$rowList; $i++) { 1282 push @$row_index, $i; 1283 } 1284 foreach my $image (@$images) { 1285 $image->{row_index} = $row_index; 1286 } 1287 } 1288 1289 sub my_die 1290 { 1291 my $msg = shift; 1292 my $fault = shift; 1293 1294 carp $msg; 1295 1296 # we don't fault the request here pstamp_parser_run.pl handles that if necessary 1297 1298 return $fault; 1299 } 1047 1300 1; -
trunk/ippTasks/pstamp.pro
r27187 r27751 13 13 $pstampFin_DB = 0 14 14 $pstampRev_DB = 0 15 $pstampDep_DB = 0 15 16 16 17 # set PS_DBSERVER if postage stamp database host is not the same as the value for DBSERVER in site.config … … 28 29 book init pstampJob 29 30 book init pstampFinish 31 book init pstampDependent 30 32 end 31 33 32 34 pstamp.reset 33 34 35 35 36 macro pstamp.on … … 60 61 active true 61 62 end 63 task pstamp.dependent.load 64 active true 65 end 62 66 end 63 67 … … 88 92 task pstamp.job.revert 89 93 active false 94 end 95 task pstamp.dependent.load 96 active true 90 97 end 91 98 end … … 208 215 book getword pstampRequest $pageName uri -var URI 209 216 book getword pstampRequest $pageName ds_outProduct -var PRODUCT 217 book getword pstampRequest $pageName label -var LABEL 210 218 211 219 host anyhost 212 220 213 $run = pstamp_parser_run.pl --req_id $REQ_ID --uri $URI --product $PRODUCT -- redirect-output221 $run = pstamp_parser_run.pl --req_id $REQ_ID --uri $URI --product $PRODUCT --label $LABEL --redirect-output 214 222 215 223 add_standard_args run … … 512 520 end 513 521 522 task pstamp.dependent.load 523 host local 524 525 periods -poll $LOADPOLL 526 # XXX: create a macro for this 527 periods -exec 30 528 # periods -exec $LOADEXEC 529 periods -timeout 30 530 npending 1 531 532 task.exec 533 stdout $LOGSUBDIR/pstamp.dependent.load.log 534 stderr $LOGSUBDIR/pstamp.dependent.load.log 535 $run = pstamptool -pendingdependent 536 if ($DB:n == 0) 537 option DEFAULT 538 else 539 option $DB:$pstampDep_DB 540 $run = $run -dbname $DB:$pstampDep_DB $PS_DBSERVER 541 $pstampDep_DB ++ 542 if ($pstampDep_DB >= $DB:n) set pstampDep_DB = 0 543 end 544 add_poll_args run 545 add_poll_labels run 546 command $run 547 end 548 549 task.exit $EXIT_SUCCESS 550 ipptool2book stdout pstampDependent -key dep_id -uniq -setword dbname $options:0 -setword pantaskState INIT 551 552 book npages pstampDependent -var N 553 if ($VERBOSE > 2) 554 book listbook pstampDependent 555 end 556 557 # delete existing entries in the appropriate pantaskStates 558 process_cleanup pstampDependent 559 end 560 561 task.exit crash 562 showcommand crash 563 end 564 565 task.exit timeout 566 showcommand timeout 567 end 568 569 task.exit default 570 showcommand failure 571 end 572 573 end 574 575 task pstamp.dependent.run 576 periods -poll $RUNPOLL 577 periods -exec $RUNEXEC 578 periods -timeout 300 579 580 task.exec 581 # stdout $LOGSUBDIR/pstamp.dependent.run.log 582 # stderr $LOGSUBDIR/pstamp.dependent.run.log 583 book npages pstampDependent -var N 584 if ($N == 0) 585 periods -exec $RUNEXEC 586 break 587 end 588 periods -exec 0.05 589 590 book getpage pstampDependent 0 -var pageName -key pantaskState INIT 591 if ("$pageName" == "NULL") break 592 593 #echo pageName: $pageName 594 595 book setword pstampDependent $pageName pantaskState RUN 596 book getword pstampDependent $pageName dep_id -var DEP_ID 597 book getword pstampDependent $pageName state -var STATE 598 book getword pstampDependent $pageName stage -var STAGE 599 book getword pstampDependent $pageName stage_id -var STAGE_ID 600 book getword pstampDependent $pageName component -var COMPONENT 601 book getword pstampDependent $pageName imagedb -var IMAGEDB 602 book getword pstampDependent $pageName rlabel -var RLABEL 603 # book getword pstampDependent $pageName output_base -var OUTPUT_BASE 604 book getword pstampDependent $pageName need_magic -var NEED_MAGIC 605 book getword pstampDependent $pageName dbname -var DBNAME 606 607 if ($VERBOSE > 1) 608 book listpage pstampDependent $pageName 609 end 610 611 host anyhost 612 613 if ("$NEED_MAGIC" == "T") 614 $NEED_MAGIC="--need_magic" 615 else 616 $NEED_MAGIC="" 617 end 618 619 # XXX: use OUTPUT_BASE for this 620 $LOGFILE = /data/ipp053.0/home/bills/pstamp/logs/pstampdep.$DEP_ID.log 621 # echo logfile is $LOGFILE 622 # stdout $LOGFILE 623 # stderr $LOGFILE 624 625 $run = pstamp_checkdependent.pl --dep_id $DEP_ID --stage_id $STAGE_ID --stage $STAGE --component $COMPONENT --imagedb $IMAGEDB --rlabel $RLABEL $NEED_MAGIC 626 add_standard_args run 627 628 options $pageName 629 630 if ($VERBOSE > 1) 631 echo command $run 632 end 633 command $run 634 end 635 636 637 task.exit $EXIT_SUCCESS 638 if ($VERBOSE > 1) 639 echo pstamp.dependent.run task.exit $DEP_ID status: $JOB_STATUS 640 end 641 process_exit pstampDependent $options:0 $JOB_STATUS 642 end 643 task.exit default 644 if ($VERBOSE > 1) 645 echo pstamp.job.run task.exit $DEP_ID status: $JOB_STATUS 646 end 647 showcommand failure 648 process_exit pstampDependent $options:0 $JOB_STATUS 649 end 650 651 task.exit crash 652 echo pstamp.job.run task.crash $DEP_ID status: $JOB_STATUS 653 process_exit pstampDependent $options:0 $JOB_STATUS 654 showcommand crash 655 book setword pstampDependent $options:0 pantaskState CRASH 656 end 657 658 task.exit timeout 659 echo pstamp.job.run task.timeout $DEP_ID status: $JOB_STATUS 660 process_exit pstampDependent $options:0 $JOB_STATUS 661 showcommand timeout 662 book setword pstampDependent $options:0 pantaskState TIMEOUT 663 end 664 end 665 -
trunk/pstamp/scripts/pstamp_checkdependent.pl
r27703 r27751 48 48 my $warptool = can_run('warptool') or (warn "Can't find warptool" and $missing_tools = 1); 49 49 my $difftool = can_run('difftool') or (warn "Can't find difftool" and $missing_tools = 1); 50 my $stacktool = can_run('stacktool') or (warn "Can't find stacktool" and $missing_tools = 1); 50 51 my $magicdstool = can_run('magicdstool') or (warn "Can't find magicdstool" and $missing_tools = 1); 51 52 my $pstamptool = can_run('pstamptool') or (warn "Can't find pstamptool" and $missing_tools = 1); … … 86 87 } else { 87 88 if ($stage eq "chip") { 88 $cmd = "$chiptool -processedimfile - chip_id $stage_id -class_id $component";89 $cmd = "$chiptool -processedimfile -allfiles -chip_id $stage_id -class_id $component"; 89 90 } elsif ($stage eq "warp") { 90 91 $cmd = "$warptool -warped -warp_id $stage_id -skycell_id $component"; … … 96 97 } 97 98 98 my $components = runToolAndParse($cmd, $verbose); 99 100 my $n = scalar @$components; 101 my_die("Unexpected number of components found $n", $PS_EXIT_PROG_ERROR) if ($n != 1); 99 my $it = runToolAndParseExpectOne($cmd, $verbose); 100 101 my_die("no components found", $PS_EXIT_PROG_ERROR) if ( !$it); 102 102 103 103 # Got "it" 104 my $it = $components->[0];105 104 106 105 my $status = 0; … … 130 129 # need to queue the updates 131 130 if ($stage eq 'chip') { 132 # queue_update_chip takes an array so that queue_update_warp can pass a set of 133 # chips to it 131 # queue_update_chip takes an array so that queue_update_warp can pass it set of chips 134 132 my $chips = [$it]; 135 133 $status = queue_update_chip($it->{chip_id}, $whole_run, $chips, $rlabel, $need_magic); … … 145 143 146 144 # detect states that cannot be updated and update the job state 147 # XXX: we should be more assertive here and check for the specific states where we can continue 145 # XXX: Perhaps I should be more assertive here and check for the specific states that we know 146 # that we can continue. 147 148 148 my $state = $it->{state}; 149 149 my $job_fault = 0; 150 if (($state =~ /scrub/) or ($state =~ /purge/)) { 150 151 # temporary hack to deal with data with old burntool tables. This check is now done by pstampparse.pl 152 # so runs in this state will not get queued 153 if ($stage eq 'chip') { 154 my $burntool_state = $it->{burntool_state}; 155 if ($burntool_state and (abs($burntool_state) < 14)) { 156 print STDERR "chip $it->{chip_id} $it->{class_id} has burntool_state $burntool_state. Not avaiable.\n"; 157 $job_fault = $PSTAMP_NOT_AVAILABLE; 158 } 159 } 160 if ($state eq 'error_cleaned') { 161 $job_fault = $PSTAMP_NOT_AVAILABLE; 162 } elsif (($state =~ /scrub/) or ($state =~ /purge/)) { 151 163 # jobs must have changed state since depenency was made 152 164 print STDERR "Dependency cannot be satisfied\n"; … … 155 167 # Dependency never should have been inserted 156 168 my_die ("Unexpected state for ${stage}Run $stage_id $state", $PS_EXIT_PROG_ERROR); 169 } 170 if (!$job_fault and ($stage eq 'chip')) { 171 $job_fault = queue_update_magicDSRun($stage, $stage_id, $rlabel, $it->{raw_magicked}, $it->{dsRun_state}); 157 172 } 158 173 if ($job_fault) { … … 213 228 } 214 229 230 my $status = queue_update_magicDSRun('chip', $chip_id, $rlabel, $raw_all_magicked, $dsRun_state); 231 232 return $status; 233 } 234 235 sub queue_update_warp { 236 # check status of input chips. If state is not updatable set error code for job 237 238 # if chipProcessedImfile.state is cleaned call queue_update_chip 239 240 # need to code warptool -setskyfiletoupdate 241 my $metadata = shift; 242 my $whole_run = shift; # if true queue entire run for update 243 my $rlabel = shift; # if defined a new label for the chipRun 244 my $need_magic = shift; 245 246 my $raw_all_magicked = 1; # this gets cleared if any of the inputs aren't destreaked 247 248 my $warp_id = $metadata->{warp_id}; 249 if (!$whole_run) { 250 my $skycell = $metadata; 251 my $skycell_id = $skycell->{skycell_id}; 252 253 my $command = "$warptool -scmap -warp_id $warp_id -skycell_id $skycell_id"; 254 my $data = runToolAndParse($command, $verbose); 255 my_die("failed to find warpSkyCelllMap for warpRun $warp_id skycell_id $skycell_id", $PS_EXIT_UNKNOWN_ERROR) 256 if !$data or scalar @$data == 0; 257 258 my $good_to_go = 1; 259 my @chipsToUpdate; 260 my $chip_id; 261 foreach my $chip (@$data) { 262 $chip_id = $chip->{chip_id}; 263 if (($chip->{data_state} ne 'full') or ($need_magic and ($chip->{magicked} <= 0))) { 264 $good_to_go = 0; 265 push @chipsToUpdate, $chip; 266 } else { 267 # this chip is good to go 268 } 269 } 270 271 if ($good_to_go) { 272 my $command = "$warptool -setskyfiletoupdate -warp_id $warp_id -skycell_id $skycell->{skycell_id}"; 273 $command .= " -set_label $rlabel" if $rlabel; 274 275 if (!$no_update) { 276 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = 277 run(command => $command, verbose => $verbose); 278 unless ($success) { 279 my_die("failed to queue ${stage}Run $stage_id $component for update", $PS_EXIT_UNKNOWN_ERROR); 280 } 281 } else { 282 print "skipping $command\n"; 283 } 284 } elsif (scalar @chipsToUpdate > 0) { 285 return queue_update_chip($chip_id, 0, \@chipsToUpdate, $rlabel, $need_magic); 286 } 287 } else { 288 my $warpRun = $metadata; 289 my $command = "$chiptool -listrun -chip_id $warpRun->{chip_id}"; 290 my $data = runToolAndParse($command, $verbose); 291 my_die("failed to find chipRun $warpRun->{chip_id} for warpRun $warp_id", $PS_EXIT_UNKNOWN_ERROR) 292 if !$data or scalar @$data != 1; 293 294 my $chipRun = $data->[0]; 295 296 my $chipRunState = $chipRun->{state}; 297 if (($chipRunState =~ /purge/) or ($chipRunState =~ /scrub/)) { 298 print STDERR "warpRun $warp_id depends on chipRun $chipRun->{chip_id} which is in state $chipRunState\n"; 299 faultJobs('stop', 'warp', $warp_id, $PSTAMP_GONE); 300 return 0; 301 } 302 my $warpRunState = $warpRun->{state}; 303 if (($chipRunState eq 'full') and (! $need_magic or ($chipRun->{magicked} > 0)) and ($warpRunState eq 'cleaned')) { 304 # The inputs and outputs are ready. Queue the warpRun for update. 305 306 # providing no -skycell_id arguments changes all skyfiles with data_state = 'cleaned' to 'update' 307 my $command = "$warptool -setskyfiletoupdate -warp_id $warp_id"; 308 $command .= " -set_label $rlabel" if $rlabel; 309 310 if (!$no_update) { 311 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = 312 run(command => $command, verbose => $verbose); 313 unless ($success) { 314 my_die("failed to queue ${stage}Run $stage_id $component for update", $PS_EXIT_UNKNOWN_ERROR); 315 } 316 } else { 317 print "skipping $command\n"; 318 } 319 } elsif ($chipRunState eq 'cleaned' or 320 (($chipRun->{state} eq 'full') and ($need_magic and ($chipRun->{magicked} < 0) and ($chipRun->{dsRun_state} ne 'new')))) { 321 my $data = [$chipRun]; 322 return queue_update_chip($chipRun->{chip_id}, 1, $data, $rlabel, $need_magic); 323 } 324 } 325 326 # return value may be the return status of script so zero is good 327 return 0; 328 } 329 sub queue_update_diff { 330 my $metadata = shift; 331 my $whole_run = shift; # if true queue entire run for update 332 my $rlabel = shift; # if defined a new label for the chipRun 333 my $need_magic = shift; 334 335 # XXXX This is not ready to go yet XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXxx 336 337 my $diff_id = $metadata->{diff_id}; 338 my $diff_mode = $metadata->{diff_mode}; 339 if (!$whole_run) { 340 my $skycell = $metadata; 341 my $skycell_id = $skycell->{skycell_id}; 342 343 # put this in a module somewhere 344 my $IPP_DIFF_MODE_WARP_WARP = 1; 345 my $IPP_DIFF_MODE_WARP_STACK = 2; 346 my $IPP_DIFF_MODE_STACK_WARP = 2; 347 my $IPP_DIFF_MODE_STACK_STACK = 4; 348 if ($diff_mode == $IPP_DIFF_MODE_WARP_STACK ) { 349 # check the state of the stack 350 my $command = "$stacktool -sumkskyfile -stack_id $skycell->{stack2}"; 351 my $stack = runToolAndParseExpectOne($command, $verbose); 352 my_die("failed to find stackSumSkyfile for stack_id $skycell->{stack2}", $PS_EXIT_UNKNOWN_ERROR) if !$stack; 353 354 if ($stack->{state} ne 'full') { 355 print STDERR "template stack for diffRun $diff_id $skycell_id is not in full state faulting jobs\n"; 356 # this faults all jobs depending on this dep_id 357 faultJobs('stop', 'diff', $diff_id, $PSTAMP_GONE); 358 return $PSTAMP_GONE; 359 } 360 361 # now check the warp 362 $command = "$warptool -warped -warp_id $skycell->{warp1} -skycell_id $skycell_id"; 363 my $warp = runToolAndExpectOne($command, $verbose); 364 my_die("failed to find warpSkyfile for warpRun $skycell->{warp_id} skycell_id $skycell_id", $PS_EXIT_UNKNOWN_ERROR) 365 if !$warp; 366 } 367 368 my $good_to_go = 1; 369 my @chipsToUpdate; 370 my $chip_id; 371 my $warp_id; 372 my $data ; #XXXX 373 foreach my $chip (@$data) { 374 $chip_id = $chip->{chip_id}; 375 if (($chip->{data_state} ne 'full') or ($need_magic and ($chip->{magicked} <= 0))) { 376 $good_to_go = 0; 377 push @chipsToUpdate, $chip; 378 } else { 379 # this chip is good to go 380 } 381 } 382 383 if ($good_to_go) { 384 my $command = "$warptool -setskyfiletoupdate -warp_id $warp_id -skycell_id $skycell->{skycell_id}"; 385 $command .= " -set_label $rlabel" if $rlabel; 386 387 if (!$no_update) { 388 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = 389 run(command => $command, verbose => $verbose); 390 unless ($success) { 391 my_die("failed to queue ${stage}Run $stage_id $component for update", $PS_EXIT_UNKNOWN_ERROR); 392 } 393 } else { 394 print "skipping $command\n"; 395 } 396 } elsif (scalar @chipsToUpdate > 0) { 397 return queue_update_chip($chip_id, 0, \@chipsToUpdate, $rlabel, $need_magic); 398 } 399 } else { 400 my $warpRun = $metadata; 401 my $warp_id = $warpRun->{warp_id}; 402 my $command = "$chiptool -listrun -chip_id $warpRun->{chip_id}"; 403 my $data = runToolAndParse($command, $verbose); 404 my_die("failed to find chipRun $warpRun->{chip_id} for warpRun $warp_id", $PS_EXIT_UNKNOWN_ERROR) 405 if !$data or scalar @$data != 1; 406 407 my $chipRun = $data->[0]; 408 409 my $chipRunState = $chipRun->{state}; 410 if (($chipRunState =~ /purge/) or ($chipRunState =~ /scrub/)) { 411 print STDERR "warpRun $warp_id depends on chipRun $chipRun->{chip_id} which is in state $chipRunState\n"; 412 faultJobs('stop', 'warp', $warp_id, $PSTAMP_GONE); 413 return 0; 414 } 415 my $warpRunState = $warpRun->{state}; 416 if (($chipRunState eq 'full') and (! $need_magic or ($chipRun->{magicked} > 0)) and ($warpRunState eq 'cleaned')) { 417 # The inputs and outputs are ready. Queue the warpRun for update. 418 419 # providing no -skycell_id arguments changes all skyfiles with data_state = 'cleaned' to 'update' 420 my $command = "$warptool -setskyfiletoupdate -warp_id $warp_id"; 421 $command .= " -set_label $rlabel" if $rlabel; 422 423 if (!$no_update) { 424 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = 425 run(command => $command, verbose => $verbose); 426 unless ($success) { 427 my_die("failed to queue ${stage}Run $stage_id $component for update", $PS_EXIT_UNKNOWN_ERROR); 428 } 429 } else { 430 print "skipping $command\n"; 431 } 432 } elsif ($chipRunState eq 'cleaned' or 433 (($chipRun->{state} eq 'full') and ($need_magic and ($chipRun->{magicked} < 0) and ($chipRun->{dsRun_state} ne 'new')))) { 434 my $data = [$chipRun]; 435 return queue_update_chip($chipRun->{chip_id}, 1, $data, $rlabel, $need_magic); 436 } 437 } 438 439 # return value may be the return status of script so zero is good 440 return 0; 441 } 442 443 444 # run a command that produces metadata output and parse the results into an array of objects 445 sub runToolAndParse { 446 my $command = shift; 447 my $verbose = shift; 448 449 my ($program) = split " ", $command; 450 $program = basename($program); 451 452 print "Running $command\n" if !$verbose; 453 my $start_tool = DateTime->now->mjd; 454 # run the command and parse the output 455 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = 456 run(command => $command, verbose => $verbose); 457 unless ($success) { 458 print STDERR @$stderr_buf if !$verbose; 459 return undef; 460 } 461 462 my $now = DateTime->now->mjd; 463 my $dtime_tool = (DateTime->now->mjd - $start_tool) * 86400.; 464 print "Time to run $program: $dtime_tool\n"; 465 466 my $buf = join "", @$stdout_buf; 467 if (!$buf) { 468 return undef; 469 } 470 471 my $start_parse = DateTime->now->mjd; 472 473 my $mdcParser = PS::IPP::Metadata::Config->new; 474 my $results = parse_md_fast($mdcParser, $buf) 475 or my_die ("Unable to parse metadata config doc", $PS_EXIT_UNKNOWN_ERROR); 476 477 my $dtime_parse = (DateTime->now->mjd - $start_parse) * 86400.; 478 print "Time to parse results from $program: $dtime_parse\n"; 479 480 return $results; 481 } 482 483 # run an command returning metadata where we expect 1 entry 484 sub runToolAndParseExpectOne { 485 my $command = shift; 486 my $verbose = shift; 487 488 my $data = runToolAndParse($command, $verbose); 489 490 if (!$data) { 491 return undef; 492 } 493 494 my $n = scalar @$data; 495 if ($n > 1) { 496 my_die("Unexpected number of components $n returned by $command", $PS_EXIT_PROG_ERROR); 497 } 498 499 return $data->[0]; 500 } 501 502 # splits meta data config input stream into single units to work around the pathalogically 503 # slow parser. This is similar to and adapted from code in various ippScripts. 504 sub parse_md_fast { 505 my $mdcParser = shift; 506 my $input = shift; 507 my $output = (); 508 509 my @whole = split /\n/, $input; 510 my @single = (); 511 512 my $n; 513 while ( ($n = @whole) > 0) { 514 my $value = shift @whole; 515 push @single, $value; 516 if ($value =~ /^\s*END\s*$/) { 517 push @single, "\n"; 518 519 my $list = parse_md_list( $mdcParser->parse( join("\n", @single ) ) ) or 520 print STDERR "Unable to parse metdata config doc" and return undef; 521 push @$output, $list->[0]; 522 523 @single = (); 524 } 525 } 526 return $output; 527 } 528 529 sub faultJobs { 530 my ($state, $stage, $stage_id, $job_fault) = @_; 531 532 my $command = "$pstamptool -updatejob -state stop -fault $job_fault -dep_id $dep_id"; 533 $command .= " -dbname $dbname" if $dbname; 534 $command .= " -dbserver $dbserver" if $dbserver; 535 if (!$no_update) { 536 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = 537 run(command => $command, verbose => $verbose); 538 unless ($success) { 539 my_die("failed to set pstampJob.fault for dep_id: $dep_id", 540 $PS_EXIT_UNKNOWN_ERROR); 541 } 542 } else { 543 print "skipping $command\n"; 544 } 545 } 546 547 sub queue_update_magicDSRun { 548 my $stage = shift; 549 my $stage_id = shift; 550 my $rlabel = shift; 551 my $input_magicked = shift; 552 my $dsRun_state = shift; 553 554 # XXX: this code is only fully coded and tested for chip stage 555 my_die ("queue_update_magicDSRun only works for stage chip", $PS_EXIT_PROG_ERROR) if $stage ne 'chip'; 556 215 557 # if called from queue_update_warp dsRun_state is unknown. Go find it. 216 558 if (!$dsRun_state) { 217 my $command = "$chiptool -listrun -chip_id $ chip_id";559 my $command = "$chiptool -listrun -chip_id $stage_id"; 218 560 my $data = runToolAndParse($command, $verbose); 219 561 my $chipRun = $data->[0]; … … 222 564 223 565 # if the input file is already magicked no need to queue destreaking for this chipRun 224 if ($need_magic and !$ raw_all_magicked) {566 if ($need_magic and !$input_magicked) { 225 567 if ($dsRun_state eq 'cleaned') { 226 568 my $command = "$magicdstool -updaterun -set_state new -stage $stage -stage_id $stage_id"; … … 242 584 } 243 585 } 244 245 # return value may be the return status of script so zero is good246 586 return 0; 247 587 } 248 588 249 sub queue_update_warp { 250 # check status of input chips. If state is not updatable set error code for job 251 252 # if chipProcessedImfile.state is cleaned call queue_update_chip 253 254 # need to code warptool -setskyfiletoupdate 255 my $metadata = shift; 256 my $whole_run = shift; # if true queue entire run for update 257 my $rlabel = shift; # if defined a new label for the chipRun 258 my $need_magic = shift; 259 260 my $raw_all_magicked = 1; # this gets cleared if any of the inputs aren't destreaked 261 262 my $warp_id = $metadata->{warp_id}; 263 if (!$whole_run) { 264 my $skycell = $metadata; 265 my $skycell_id = $skycell->{skycell_id}; 266 267 my $command = "$warptool -scmap -warp_id $warp_id -skycell_id $skycell_id"; 268 my $data = runToolAndParse($command, $verbose); 269 my_die("failed to find warpSkyCelllMap for warpRun $warp_id skycell_id $skycell_id", $PS_EXIT_UNKNOWN_ERROR) 270 if !$data or scalar @$data == 0; 271 272 my $good_to_go = 1; 273 my @chipsToUpdate; 274 my $chip_id; 275 foreach my $chip (@$data) { 276 $chip_id = $chip->{chip_id}; 277 if (($chip->{data_state} ne 'full') or ($need_magic and ($chip->{magicked} <= 0))) { 278 $good_to_go = 0; 279 push @chipsToUpdate, $chip; 280 } else { 281 # this chip is good to go 282 } 283 } 284 285 if ($good_to_go) { 286 my $command = "$warptool -setskyfiletoupdate -warp_id $warp_id -skycell_id $skycell->{skycell_id}"; 287 $command .= " -set_label $rlabel" if $rlabel; 288 289 if (!$no_update) { 290 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = 291 run(command => $command, verbose => $verbose); 292 unless ($success) { 293 my_die("failed to queue ${stage}Run $stage_id $component for update", $PS_EXIT_UNKNOWN_ERROR); 294 } 295 } else { 296 print "skipping $command\n"; 297 } 298 } elsif (scalar @chipsToUpdate > 0) { 299 return queue_update_chip($chip_id, 0, \@chipsToUpdate, $rlabel, $need_magic); 300 } 301 } else { 302 my $warpRun = $metadata; 303 my $command = "$chiptool -listrun -chip_id $warpRun->{chip_id}"; 304 my $data = runToolAndParse($command, $verbose); 305 my_die("failed to find chipRun $warpRun->{chip_id} for warpRun $warp_id", $PS_EXIT_UNKNOWN_ERROR) 306 if !$data or scalar @$data != 1; 307 308 my $chipRun = $data->[0]; 309 310 my $chipRunState = $chipRun->{state}; 311 if (($chipRunState =~ /purge/) or ($chipRunState =~ /scrub/)) { 312 print STDERR "warpRun $warp_id depends on chipRun $chipRun->{chip_id} which is in state $chipRunState\n"; 313 faultJobs('stop', 'warp', $warp_id, $PSTAMP_GONE); 314 return 0; 315 } 316 my $warpRunState = $warpRun->{state}; 317 if (($chipRunState eq 'full') and (! $need_magic or ($chipRun->{magicked} > 0)) and ($warpRunState eq 'cleaned')) { 318 # The inputs and outputs are ready. Queue the warpRun for update. 319 320 # providing no -skycell_id arguments changes all skyfiles with data_state = 'cleaned' to 'update' 321 my $command = "$warptool -setskyfiletoupdate -warp_id $warp_id"; 322 $command .= " -set_label $rlabel" if $rlabel; 323 324 if (!$no_update) { 325 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = 326 run(command => $command, verbose => $verbose); 327 unless ($success) { 328 my_die("failed to queue ${stage}Run $stage_id $component for update", $PS_EXIT_UNKNOWN_ERROR); 329 } 330 } else { 331 print "skipping $command\n"; 332 } 333 } elsif ($chipRunState eq 'cleaned' or 334 (($chipRun->{state} eq 'full') and ($need_magic and ($chipRun->{magicked} < 0) and ($chipRun->{dsRun_state} ne 'new')))) { 335 my $data = [$chipRun]; 336 return queue_update_chip($chipRun->{chip_id}, 1, $data, $rlabel, $need_magic); 337 } 338 } 339 340 # return value may be the return status of script so zero is good 341 return 0; 342 } 343 sub queue_update_diff { 344 return 0; 345 } 346 347 348 # run a command that produces metadata output and parse the results into an array of objects 349 sub runToolAndParse { 350 my $command = shift; 351 my $verbose = shift; 352 353 my ($program) = split " ", $command; 354 $program = basename($program); 355 356 print "Running $command\n" if !$verbose; 357 my $start_tool = DateTime->now->mjd; 358 # run the command and parse the output 359 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = 360 run(command => $command, verbose => $verbose); 361 unless ($success) { 362 print STDERR @$stderr_buf if !$verbose; 363 return undef; 364 } 365 366 my $now = DateTime->now->mjd; 367 my $dtime_tool = (DateTime->now->mjd - $start_tool) * 86400.; 368 print "Time to run $program: $dtime_tool\n"; 369 370 my $buf = join "", @$stdout_buf; 371 if (!$buf) { 372 return undef; 373 } 374 375 my $start_parse = DateTime->now->mjd; 376 377 my $mdcParser = PS::IPP::Metadata::Config->new; 378 my $results = parse_md_fast($mdcParser, $buf) 379 or my_die ("Unable to parse metadata config doc", $PS_EXIT_UNKNOWN_ERROR); 380 381 my $dtime_parse = (DateTime->now->mjd - $start_parse) * 86400.; 382 print "Time to parse results from $program: $dtime_parse\n"; 383 384 return $results; 385 } 386 387 # splits meta data config input stream into single units to work around the pathalogically 388 # slow parser. This is similar to and adapted from code in various ippScripts. 389 sub parse_md_fast { 390 my $mdcParser = shift; 391 my $input = shift; 392 my $output = (); 393 394 my @whole = split /\n/, $input; 395 my @single = (); 396 397 my $n; 398 while ( ($n = @whole) > 0) { 399 my $value = shift @whole; 400 push @single, $value; 401 if ($value =~ /^\s*END\s*$/) { 402 push @single, "\n"; 403 404 my $list = parse_md_list( $mdcParser->parse( join("\n", @single ) ) ) or 405 print STDERR "Unable to parse metdata config doc" and return undef; 406 push @$output, $list->[0]; 407 408 @single = (); 409 } 410 } 411 return $output; 412 } 413 sub faultJobs { 414 my ($state, $stage, $stage_id, $job_fault) = @_; 415 416 my $command = "$pstamptool -updatejob -state stop -fault $job_fault -dep_id $dep_id"; 589 sub my_die 590 { 591 my $msg = shift; 592 my $fault = shift; 593 carp $msg; 594 595 my $command = "$pstamptool -updatedepedent -fault $fault -dep_id $dep_id"; 417 596 $command .= " -dbname $dbname" if $dbname; 418 597 $command .= " -dbserver $dbserver" if $dbserver; … … 421 600 run(command => $command, verbose => $verbose); 422 601 unless ($success) { 423 my_die("failed to set pstam Job.fault for dep_id: $dep_id",602 my_die("failed to set pstampDependent.fault for dep_id: $dep_id", 424 603 $PS_EXIT_UNKNOWN_ERROR); 425 604 } … … 427 606 print "skipping $command\n"; 428 607 } 429 } 430 431 sub my_die 432 { 433 my $msg = shift; 434 my $fault = shift; 435 436 carp $msg; 437 438 return $fault; 439 } 608 609 exit $fault; 610 } -
trunk/pstamp/scripts/pstamp_finish.pl
r27670 r27751 124 124 my ($rlf, $reglist_name) = tempfile ("$out_dir/reglist.XXXX", UNLINK => !$save_temps); 125 125 print $rlf "results.fits|||table|\n"; 126 print $rlf "results.mdc|||t xt|\n";126 print $rlf "results.mdc|||text|\n"; 127 127 128 128 my $err_file = "parse_error.txt"; … … 171 171 my $exp_id = $job->{exp_id}; 172 172 173 173 174 if (($fault eq $PSTAMP_DUP_REQUEST) and ($req_name eq "NULL")) { 174 175 # this request had a duplicate request name. We can't put the results … … 188 189 } 189 190 190 if ($exp_id ne $last_exp_id) { 191 my $job_params = get_job_parameters($job); 192 my $stage = ""; 193 if ($job_params) { 194 $stage = $job_params->{stage}; 195 } 196 197 if ($stage ne 'stack') { 191 198 # get the metadata for the exposure (if any i.e. stack) 192 199 # returns an appropriate string if !$exp_id 193 200 $exp_info = get_exposure_info($image_db, $exp_id); 194 201 $last_exp_id = $exp_id; 202 } else { 203 my $filter = $job_params->{filter}; 204 $filter = "0" if !$filter; 205 $exp_info = "0|0|0|$filter|0|0"; 206 $last_exp_id = -1; 195 207 } 196 208 … … 344 356 } 345 357 358 sub get_job_parameters { 359 my $job = shift; 360 if (!$job->{outputBase}) { 361 print "get_job_parameters: $job->{job_id} has no outputBase\n"; 362 return undef; 363 } 364 my $params_file = $job->{outputBase} . '.mdc'; 365 if (! -e $params_file ) { 366 print "get_job_parameters: $job->{job_id} has no parameters file\n"; 367 return undef; 368 } 369 open IN, "<$params_file" or die "unable to open $params_file"; 370 my $data = join "", (<IN>); 371 close IN; 372 if (! $data ) { 373 print "get_job_parameters: parameters file is empty\n"; 374 return undef; 375 } 376 my $metadata = $mdcParser->parse($data) or die("Unable to parse metdata config doc"); 377 378 my $results = parse_md_list($metadata); 379 if (scalar @$results != 1) { 380 print STDERR "get_job_params: failed to parse_md_list\n"; 381 return undef; 382 } 383 return $results->[0]; 384 } 385 346 386 sub get_exposure_info { 347 387 my $image_db= shift; -
trunk/pstamp/scripts/pstamp_job_run.pl
r27577 r27751 250 250 copy_and_register_file($f, $backmdl_file, $outdir, $prefix); 251 251 } 252 if (0) {252 if (0) { 253 253 # don't enable this yet 254 254 if ($pattern_file) { … … 256 256 copy_and_register_file($f, $pattern_file, $outdir, $prefix); 257 257 } 258 }258 } 259 259 } 260 260 } -
trunk/pstamp/scripts/pstamp_parser_run.pl
r26151 r27751 28 28 my $redirect_output; 29 29 my $product; 30 my $label; 30 31 my $verbose; 31 32 my $dbname; … … 36 37 'uri=s' => \$uri, 37 38 'product=s' => \$product, 39 'label=s' => \$label, 38 40 'redirect-output' => \$redirect_output, 39 41 'verbose' => \$verbose, … … 146 148 if ($request_type eq "PS1_PS_REQUEST") { 147 149 $reqType = 'pstamp'; 148 $parse_cmd = $pstampparse; 150 $parse_cmd = "$pstampparse"; 151 $parse_cmd .= " --label $label" if $label; 149 152 } elsif ($request_type eq "MOPS_DETECTABILITY_QUERY") { 150 153 $reqType = 'dquery'; -
trunk/pstamp/scripts/pstamp_request_file
r26289 r27751 187 187 for (my $i = 0; $i < scalar @colNames; $i++) { 188 188 my $writeType = $colWriteType[$i]; 189 $outFits->write_col( $writeType, $i + 1, 1, 1, $numRows, $colData->[$i], $status ); 189 my $data = $colData->[$i]; 190 if ($writeType == TULONG) { 191 die "invalid integer data found in column $i\n" unless validIntegers($data); 192 } elsif ($writeType == TDOUBLE) { 193 die "invalid numeric data found in column $i\n" unless validNumbers($data); 194 } 195 $outFits->write_col( $writeType, $i + 1, 1, 1, $numRows, $data, $status ); 190 196 check_fitsio( $status ); 191 197 } … … 312 318 } 313 319 320 sub checkValid { 321 my $aref = shift; 322 my $float = shift; 323 324 return 0 if !defined $aref; 325 326 my $valid = 0; 327 my $row = 0; 328 foreach my $val (@$aref) { 329 $row++; 330 if ($float) { 331 if (!($val =~ /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/)) { 332 $valid = 0; 333 print STDERR "Error on row $row: '$val' is not a valid number\n"; 334 last; 335 } 336 } else { 337 if ($val =~ /\D/) { 338 $valid = 0; 339 print STDERR "Error on row $row: '$val' is not a valid integer\n"; 340 last; 341 } 342 } 343 $valid = 1; 344 } 345 346 return $valid; 347 } 348 sub validIntegers { 349 return checkValid(@_, 0); 350 } 351 352 sub validNumbers 353 { 354 return checkValid(@_, 1); 355 } 356 357 314 358 sub printhelp 315 359 { -
trunk/pstamp/scripts/pstampparse.pl
r27524 r27751 17 17 use Carp; 18 18 use POSIX; 19 use DateTime; 19 20 20 21 my $verbose; … … 26 27 my $out_dir; 27 28 my $product; 29 my $label; 28 30 my $save_temps; 29 31 my $no_update; … … 34 36 'out_dir=s' => \$out_dir, 35 37 'product=s' => \$product, 38 'label=s' => \$label, 36 39 'mode=s' => \$mode, 37 40 'dbname=s' => \$dbname, … … 42 45 ); 43 46 44 die "invalid mode '$mode'" unless ($mode eq "list_uri") or ($mode eq " list_job") or ($mode eq "queue_job");47 die "invalid mode '$mode'" unless ($mode eq "list_uri") or ($mode eq "queue_job"); 45 48 die "--file is required" if !defined($request_file_name); 46 49 … … 64 67 my $pstamptool = can_run('pstamptool') or (warn "Can't find pstamptool" and $missing_tools = 1); 65 68 my $pstampdump = can_run('pstampdump') or (warn "Can't find pstampdump" and $missing_tools = 1); 66 my $dvoImagesAtCoords = can_run('dvoImagesAtCoords') or (warn "Can't find dvoImagesAtCoords" and $missing_tools = 1);67 69 my $fields = can_run('fields') or (warn "Can't find fields" and $missing_tools = 1); 68 70 … … 159 161 } 160 162 163 # 164 # Loop over rows in the request file collecting consecutive rows that have the "same images of interest" 165 # in the sense that their selection parameters will yield the same "Runs". 166 # Process the groups of rows together to reduce lookup time and to potentially make multiple 167 # stamps from the same ppstamp process. 168 # 161 169 my @rowList; 162 170 my $num_jobs = 0; … … 165 173 my $need_magic; 166 174 foreach my $row (@$rows) { 167 # XXX: TODO: sanity check all parameters 168 169 # If we encounter an error for a particular row add a job with the proper fault code. 170 # If we encounter an error in this loop we shouldn't really just die. 171 # We only do that now in the case of I/O or DB errors or the like. 172 173 my $rownum = $row->{ROWNUM}; 174 my $job_type = $row->{JOB_TYPE}; 175 176 # parameters that select the images of interest 177 my $project = $row->{PROJECT}; 178 179 # note: resolve_project avoids running pstamptool every time by remembering the 180 # last project resolved 181 my $proj_hash = resolve_project($ipprc, $project, $dbname, $dbserver); 182 if (!$proj_hash) { 183 print STDERR "project $project not found\n" if $verbose; 184 insertFakeJobForRow($row, 1, $PSTAMP_UNKNOWN_PRODUCT); 175 # santiy check the paramaters 176 if (!checkRow($row)) { 177 # when it enconters an error checkRow adds a fake job with an appropriate error code to the database 185 178 $num_jobs++; 186 179 next; 187 180 } 181 # initialize counter for "job number" 182 $row->{job_num} = 0; 183 $row->{error_code} = 0; 184 185 if (scalar @rowList == 0) { 186 push @rowList, $row; 187 next; 188 } 189 190 my $firstRow = $rowList[0]; 191 if (same_images_of_interest($firstRow, $row)) { 192 # add this row to the list and move on 193 push @rowList, $row; 194 next; 195 } 196 197 # the images of interest for this new row doesn't match the list. 198 # process the list ... 199 $num_jobs += processRows(\@rowList); 200 201 # and reset the list to contain just the new row 202 @rowList = ($row); 203 } 204 205 # out of rows process the list 206 if (scalar @rowList > 0) { 207 $num_jobs += processRows(\@rowList); 208 } 209 210 if (($mode eq "queue_job") and ($num_jobs eq 0)) { 211 print STDERR "no jobs created for $req_name\n" if $verbose; 212 insertFakeJobForRow(undef, 0, $PSTAMP_INVALID_REQUEST); 213 } 214 215 exit 0; 216 217 sub checkRow { 218 219 my $row = shift; 220 221 # If we encounter an error for a particular row add a job with the proper fault code. 222 223 my $rownum = $row->{ROWNUM}; 224 if (!validID($rownum)) { 225 print STDERR "$rownum is not a valid ROWNUM\n" if $verbose; 226 insertFakeJobForRow($row, 1, $PSTAMP_INVALID_REQUEST); 227 return 0; 228 } 229 my $job_type = $row->{JOB_TYPE}; 230 if (($job_type ne "stamp") and ($job_type ne "get_image")) { 231 print STDERR "$job_type is not a valid JOB_TYPE\n" if $verbose; 232 insertFakeJobForRow($row, 1, $PSTAMP_INVALID_REQUEST); 233 return 0; 234 } 235 188 236 my $req_type = $row->{REQ_TYPE}; 189 $stage = $row->{IMG_TYPE}; 190 my $id = $row->{ID}; 237 if (($req_type ne "byid") and ($req_type ne "bycoord") and ($req_type ne "byexp") and 238 ($req_type ne "byskycell") and ($req_type ne "bydiff")) { 239 print STDERR "$req_type is not a valid REQ_TYPE\n" if $verbose; 240 insertFakeJobForRow($row, 1, $PSTAMP_INVALID_REQUEST); 241 return 0; 242 } 243 244 191 245 my $component = $row->{COMPONENT}; 192 my $tess_id = $row->{TESS_ID}; 246 if (!defined $component or (lc($component) eq "null") or (lc($component) eq "all")) { 247 $row->{COMPONENT} = $component = ""; 248 } 249 $row->{TESS_ID} = "" if !defined $row->{TESS_ID}; 193 250 194 251 my $filter = $row->{REQFILT}; … … 196 253 if (length($filter) == 1) { 197 254 # allow single character filter cuts to work 198 $ filter.= '%';255 $row->{REQFILT} .= '%'; 199 256 } 200 257 } 201 258 my $mjd_min = $row->{MJD_MIN}; 259 if (defined($mjd_min) and !validNumber($mjd_min)) { 260 print STDERR "$mjd_min is not a valid MJD_MIN\n" if $verbose; 261 insertFakeJobForRow($row, 1, $PSTAMP_INVALID_REQUEST); 262 return 0; 263 } 202 264 my $mjd_max = $row->{MJD_MAX}; 265 if (defined($mjd_max) and !validNumber($mjd_max)) { 266 print STDERR "$mjd_max is not a valid MJD_MAX\n" if $verbose; 267 insertFakeJobForRow($row, 1, $PSTAMP_INVALID_REQUEST); 268 return 0; 269 } 203 270 my $data_group = $row->{DATA_GROUP}; 204 271 if (!defined $data_group) { … … 209 276 } 210 277 211 my $x = $row->{CENTER_X}; 212 my $y = $row->{CENTER_Y}; 213 214 # XXX things don't work if bit zero of option mask is not set; 278 # req_finish doesn't work if bit zero of option mask is not set; 215 279 $row->{OPTION_MASK} |= 1; 280 216 281 my $option_mask= $row->{OPTION_MASK}; 217 282 my $inverse = ($option_mask & $PSTAMP_SELECT_INVERSE) ? 1 : 0; … … 222 287 my $skycenter = $row->{skycenter} = ! ($row->{COORD_MASK} & $PSTAMP_CENTER_IN_PIXELS); 223 288 224 my $search_component = (!defined($component) or ($component eq "null")) ? "" : $component; 225 226 if (!$skycenter and !$search_component) { 289 if (!$skycenter and !$component) { 227 290 print STDERR "COMPONENT must be specified for pixel coordinate ROI center\n" if $verbose; 228 291 insertFakeJobForRow($row, 1, $PSTAMP_INVALID_REQUEST); 229 $num_jobs++; 230 next; 231 } 232 233 # user requested us to search all components. Set to "" 234 $search_component = "" if $search_component eq "all"; 235 292 return 0; 293 } 294 295 my $stage = $row->{IMG_TYPE}; 236 296 if (!check_image_type($stage)) { 237 297 print STDERR "invalid IMG_TYPE for row $rownum\n" if $verbose; 238 298 insertFakeJobForRow($row, 1, $PSTAMP_INVALID_REQUEST); 239 $num_jobs++; 240 next; 299 return 0; 241 300 } 242 301 … … 244 303 print STDERR "invalid ROI for row $rownum\n" if $verbose; 245 304 insertFakeJobForRow($row, 1, $PSTAMP_INVALID_REQUEST); 246 $num_jobs++; 247 next; 305 return 0; 248 306 } 249 307 … … 251 309 print STDERR "byexp not implemented for stack stage. row: $rownum\n" if $verbose; 252 310 insertFakeJobForRow($row, 1, $PSTAMP_NOT_IMPLEMENTED); 253 $num_jobs++; 254 next; 255 } 256 257 311 return 0; 312 } 313 258 314 # $mode list_uri is a debugging mode (it may used by the http interface) 259 315 # if this happens just croak 260 my_die("job_type is list_uri but mode is $mode", $PS_EXIT_PROG_ERROR) if ($job_type eq "list_uri") and ($mode ne "list_uri"); 261 262 my $image_db = $proj_hash->{dbname}; 263 my $camera = $proj_hash->{camera}; 264 $need_magic = $proj_hash->{need_magic}; 265 266 # Temporary hack so that MOPS can get at non-magicked data 267 # if ($product and ($product eq "mops-pstamp-results")) { 268 # $need_magic = 0; 269 # } 270 271 # For "stamp" and "list_uri" jobs collect rows with the same images of interest in a list so that they 272 # can be looked up together. 273 if (@rowList) { 274 my $firstRow = $rowList[0]; 275 if (($firstRow->{JOB_TYPE} ne "get_image") and same_images_of_interest($firstRow, $row)) { 276 277 # add this row to the list and move on 278 push @rowList, $row; 279 280 next; 281 282 } else { 283 # this row has different selectors 284 # queue the jobs for the ones we've collected 285 $num_jobs += queueJobs($mode, \@rowList, $imageList); 286 @rowList = (); 287 } 288 } 289 290 # look up images for the current row 316 # my_die("job_type is list_uri but mode is $mode", $PS_EXIT_PROG_ERROR) if ($job_type eq "list_uri") and ($mode ne "list_uri"); 317 318 291 319 if ($req_type eq "bycoord") { 292 320 if (!$skycenter) { 293 321 print STDERR "center must be specified in sky coordintes for bycoord" if $verbose; 294 322 insertFakeJobForRow($row, 1, $PSTAMP_INVALID_REQUEST); 295 $num_jobs++;296 next;297 }298 } 323 return 0; 324 } 325 } 326 299 327 if (($req_type eq "byid") or ($req_type eq "bydiff")) { 300 if (!validID($ id)) {328 if (!validID($row->{ID})) { 301 329 print STDERR "ID must be a positive integer for req_type $req_type\n" if $verbose; 302 330 insertFakeJobForRow($row, 1, $PSTAMP_INVALID_REQUEST); 331 return 0 332 } 333 } 334 335 return 1; 336 } 337 338 sub processRows { 339 my $rowList = shift; 340 my $num_jobs = 0; 341 342 # all rows in the list are compatible 343 my $row = $rowList->[0]; 344 345 my $project = $row->{PROJECT}; 346 347 # note: resolve_project avoids running pstamptool every time by remembering the 348 # last project resolved 349 my $proj_hash = resolve_project($ipprc, $project, $dbname, $dbserver); 350 if (!$proj_hash) { 351 print STDERR "project $project not found\n" if $verbose; 352 foreach $row (@$rowList) { 353 insertFakeJobForRow($row, 1, $PSTAMP_UNKNOWN_PRODUCT); 303 354 $num_jobs++; 304 next; 305 } 306 } 355 } 356 return $num_jobs; 357 } 358 my $req_type = $row->{REQ_TYPE}; 359 $stage = $row->{IMG_TYPE}; 360 my $id = $row->{ID}; 361 my $component = $row->{COMPONENT}; 362 my $tess_id = $row->{TESS_ID}; 363 364 my $filter = $row->{REQFILT}; 365 my $mjd_min = $row->{MJD_MIN}; 366 my $mjd_max = $row->{MJD_MAX}; 367 my $data_group = $row->{DATA_GROUP}; 368 369 my $rownum = $row->{ROWNUM}; 370 my $job_type = $row->{JOB_TYPE}; 371 my $option_mask= $row->{OPTION_MASK}; 372 373 my $image_db = $proj_hash->{dbname}; 374 my $camera = $proj_hash->{camera}; 375 $need_magic = $proj_hash->{need_magic}; 376 377 # Temporary hack so that MOPS can get at non-magicked data 378 my $allow_mops_unmagicked = 1; 379 if ($allow_mops_unmagicked) { 380 if ($product and (($product eq "mops-pstamp-results") or 381 ($product eq "mops-pstamp-results2"))) { 382 $need_magic = 0; 383 } 384 } 385 386 my $numRows = scalar @$rowList; 387 388 # $tess_id = "" if !defined $tess_id; 389 # $component = "" if !defined $component; 390 391 print "Collected $numRows rows beginning with row $rownum. $req_type $stage $id $tess_id $component\n"; 392 307 393 # Call PS::IPP::PStamp::Job locate_images subroutine to get the images for this 308 394 # request specification. An array reference is returned. 309 $imageList = locate_images($ipprc, $image_db, $req_type, $stage, $id, $tess_id, $search_component, 310 $option_mask, $need_magic, $x, $y, $mjd_min, $mjd_max, $filter, $data_group, $verbose); 395 my $start_locate = DateTime->now->mjd; 396 397 # XXX: perhaps we should get rid of most of this argument list. 398 # Now that we are passing down compatible rows all of the 399 # information required is contained there 400 401 $imageList = locate_images($ipprc, $image_db, \@rowList, $req_type, $stage, $id, $tess_id, $component, 402 $option_mask, $need_magic, $mjd_min, $mjd_max, $filter, $data_group, $verbose); 403 404 # XXX: why use mjd? It doesn't have great precision. 405 my $dtime_locate = (DateTime->now->mjd - $start_locate) * 86400.; 406 print "Time to locate_images for row $rownum $dtime_locate\n"; 311 407 312 408 if (!$imageList or !@$imageList) { … … 314 410 # note in this case queueJobs inserts the fake job for these rows 315 411 } 412 # handle this 316 413 $row->{need_magic} = $need_magic; 317 push @rowList, $row; 318 } 319 320 if (@rowList) { 414 321 415 $num_jobs += queueJobs($mode, \@rowList, $imageList); 322 } 323 324 if (($mode eq "queue_job") and ($num_jobs eq 0)) { 325 print STDERR "no jobs created for $req_name\n" if $verbose; 326 insertFakeJobForRow(undef, 0, $PSTAMP_INVALID_REQUEST); 327 } 328 329 # PAU 330 331 exit 0; 332 333 334 sub queueJobsForRow 416 417 # if a row slipped through with no jobs add one 418 foreach my $row (@rowList) { 419 if ($row->{job_num} == 0) { 420 print "row $row->{ROWNUM} produced no jobs\n"; 421 print STDERR "row $row->{ROWNUM} produced no jobs\n"; 422 my $error_code = $row->{error_code}; 423 $error_code = $PSTAMP_NO_IMAGE_MATCH if !$error_code; 424 insertFakeJobForRow($row, ++$row->{job_num}, $error_code); 425 } 426 } 427 428 return $num_jobs; 429 } 430 431 sub queueJobForImage 335 432 { 336 433 my $row = shift; 337 434 my $stage = shift; 338 my $imageList = shift; 339 my $have_skycells = shift; 435 my $image = shift; 340 436 my $need_magic = shift; 341 437 my $mode = shift; 342 438 343 my $num_jobs = 0;344 439 my $rownum = $row->{ROWNUM}; 345 440 my $option_mask = $row->{OPTION_MASK}; … … 365 460 } 366 461 462 my $component = $image->{component}; 463 464 my $job_num = ++($row->{job_num}); 465 466 my $imagefile = $image->{image}; 467 if (($stage ne "stack") and ($need_magic and !$image->{magicked})) { 468 # XXX: should we add a faulted job so the client can know what happened if no images come back? 469 # The test for destreaked is made in locate_images now so this code never runs. This leads to no feedback 470 # to users, but speeds up processing significantly 471 print STDERR "skipping non-magicked image $imagefile\n" if $verbose; 472 473 # for now assume yes. 474 475 insertFakeJobForRow($row, $job_num, $PSTAMP_NOT_DESTREAKED); 476 return 1; 477 } elsif ($stage eq "stack") { 478 # unconvolved stack images weren't available prior to some point in time. 479 # XXX: handle this more correctly by examining the stack run's config dump file. 480 # It looks like # the feature was turned on sometime around November 11, 2009. stackRun 30067 is the lowest 481 # one that I found with an unconvolved image. 482 my $MIN_GPC1_STACK_ID_WITH_UNCONVOLVED_IMAGES = 30067; 483 if ($row->{unconvolved} and ($row->{PROJECT} eq 'gpc1') and 484 ($image->{stack_id} < $MIN_GPC1_STACK_ID_WITH_UNCONVOLVED_IMAGES)) { 485 print STDERR "Unconvolved stack image is not available for stackRun.stack_id: $image->{stack_id}\n"; 486 insertFakeJobForRow($row, $job_num, $PSTAMP_NOT_AVAILABLE); 487 return 1; 488 } 489 } 490 my $exp_id = $image->{exp_id}; 491 492 my $args = $roi_string ? $roi_string : ""; 493 if ($stage eq "raw" or $stage eq "chip") { 494 $args .= " -class_id $component" if $component; 495 } 496 497 # add astrometry file for raw and chip images if one is available 498 if (($stage eq "chip") || ($stage eq "raw")) { 499 $args .= " -astrom $image->{astrom}" if $image->{astrom}; 500 } 501 502 $image->{job_args} = $args; 503 504 # XXX: we can get rid of the following everything that we need is 505 # in the params file 506 507 $args .= " -file $imagefile"; 508 509 if (($option_mask & $PSTAMP_SELECT_MASK) && $image->{mask} ) { 510 $args .= " -mask $image->{mask}"; 511 } 512 if (($option_mask & $PSTAMP_SELECT_WEIGHT) and $image->{weight} ) { 513 $args .= " -variance $image->{weight}"; 514 } 515 516 my $base = basename($image->{image}); 517 if (! $base =~ /.fits$/ ) { 518 my_die("unexpected image file name found $image->{image}", $PS_EXIT_PROG_ERROR); 519 } 520 $base =~ s/.fits$//; 521 522 my $output_base = "$out_dir/${rownum}_${job_num}_${base}"; 523 my $argslist = "${output_base}.args"; 524 525 # copy the argument list to a file 526 open ARGSLIST, ">$argslist" or my_die("failed to open $argslist", $PS_EXIT_UNKNOWN_ERROR); 527 print ARGSLIST "$args\n"; 528 close ARGSLIST or my_die("failed to close $argslist", $PS_EXIT_UNKNOWN_ERROR); 529 530 write_params($output_base, $image); 531 532 my $newState = "run"; 533 my $fault = 0; 534 my $dep_id; 535 536 # XXX: this code is repeated in queueGetImageJobs we should encapsulate it in a subroutine and share it 537 if ($stage ne 'raw') { 538 # not ready to handle diff update yet. May never support stack 539 my $allow_wait_for_update = (($stage ne 'stack') and ($stage ne 'diff')); 540 my $run_state = $image->{state}; 541 my $data_state = $image->{data_state}; 542 $data_state = $run_state if $stage eq 'stack'; 543 if (($run_state eq 'goto_purged') or ($data_state eq 'purged') or 544 ($run_state eq 'drop') or 545 ($run_state eq 'error_cleaned') or ($data_state eq 'error_cleaned') or 546 ($run_state eq 'goto_scrubbed') or ($data_state eq 'scrubbed')) { 547 # image is gone and it's not coming back 548 $newState = 'stop'; 549 $fault = $PSTAMP_GONE; 550 } elsif ($allow_wait_for_update and 551 (($data_state ne 'full') or ($need_magic and ($image->{magicked} < 0)))) { 552 if ($stage eq 'chip') { 553 my $burntool_state = $image->{burntool_state}; 554 if ($burntool_state and (abs($burntool_state) < 14)) { 555 $newState = 'stop'; 556 $fault = $PSTAMP_NOT_AVAILABLE; 557 } 558 } 559 if (!$fault) { 560 # don't wait for update unless the caller asks us to 561 if (!($option_mask & $PSTAMP_WAIT_FOR_UPDATE)) { 562 $newState = 'stop'; 563 $fault = $PSTAMP_NOT_AVAILABLE; 564 } elsif (!$image->{magicked}) { 565 $newState = 'stop'; 566 $fault = $PSTAMP_NOT_DESTREAKED; 567 } else { 568 # cause the image to be re-made 569 # set up to queue an update run 570 queue_update_run(\$newState, \$fault, \$dep_id, $image->{imagedb}, 571 $run_state, $stage, $image->{stage_id}, $image->{component}, $need_magic); 572 } 573 } 574 } 575 } 576 577 my $command = "$pstamptool -addjob -req_id $req_id -job_type $row->{JOB_TYPE}" 578 . " -outputBase $output_base -rownum $rownum -state $newState -options $option_mask"; 579 $command .= " -fault $fault" if $fault; 580 $command .= " -exp_id $exp_id" if $exp_id; 581 $command .= " -dep_id $dep_id" if $dep_id; 582 583 if (!$no_update) { 584 # mode eq "queue_job" 585 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = 586 run(command => $command, verbose => $verbose); 587 unless ($success) { 588 print STDERR @$stderr_buf; 589 # XXX TODO: now what? Should we mark the error state for the request? 590 # should we keep going for other uris? If so how do we report that some 591 # of the work that the request wanted isn't going to get done 592 my_die("failed to queue job for request $req_id", $PS_EXIT_UNKNOWN_ERROR); 593 } 594 } else { 595 print "skipping command: $command\n"; 596 } 597 598 return 1; 599 } 600 601 # queue jobs for a collection of request specifications that have the same Images of Interest 602 sub queueJobs 603 { 604 my $mode = shift; 605 my $rowList = shift; 606 my $imageList = shift; 607 608 my $firstRow = $rowList[0]; 609 my $stage = $firstRow->{IMG_TYPE}; 610 my $job_type = $firstRow->{JOB_TYPE}; 611 my $need_magic = $firstRow->{need_magic}; 612 613 my $num_jobs = 0; 614 615 if ($mode eq "list_uri") { 616 foreach my $image (@$imageList) { 617 print "$image->{image}\n"; 618 } 619 } elsif ($job_type eq "get_image") { 620 my $n = scalar @$rowList; 621 622 my_die( "error: unexpected number of rows for get_image request: $n", $PS_EXIT_PROG_ERROR) if $n != 1; 623 624 $num_jobs = queueGetImageJobs($firstRow, $imageList, $stage, $need_magic, $mode); 625 626 } else { 627 if (!$imageList or (scalar @$imageList eq 0)) { 628 # We didn't find any images for this set of rows. Insert a fake job to carry 629 # the status back to the requestor. 630 foreach my $row (@$rowList) { 631 my $error_code = $row->{error_code}; 632 $error_code = $PSTAMP_NO_IMAGE_MATCH if !$error_code; 633 insertFakeJobForRow($row, ++$row->{job_num}, $error_code); 634 $num_jobs++; 635 } 636 return $num_jobs; 637 } 638 639 foreach my $image (@$imageList) { 640 # get the array of row indices that touch this image 641 my $row_index = $image->{row_index}; 642 if (!$row_index or scalar @$row_index == 0) { 643 # XXX should this happen? Why did something get returned. 644 print "image ${stage}_id: $image->{stage_id} component: $image->{component} matched no rows\n"; 645 next; 646 } 647 # XXX: TODO: eventually we may change ppstamp to be able to make multiple stamps per invocation 648 649 foreach my $i (@$row_index) { 650 my $row = $rowList->[$i]; 651 652 $num_jobs += queueJobForImage($row, $stage, $image, $need_magic, $mode); 653 } 654 } 655 } 656 657 return $num_jobs; 658 } 659 660 # $num_jobs = queueGetImageJobs($firstRow, $imageList, $stage, $need_magic, $mode); 661 sub queueGetImageJobs 662 { 663 my $row = shift; 664 my $imageList = shift; 665 my $stage = shift; 666 my $need_magic = shift; 667 my $mode = shift; 668 669 my $num_jobs = 0; 670 my $rownum = $row->{ROWNUM}; 671 my $option_mask = $row->{OPTION_MASK}; 672 673 # For dist_bundle we need 674 # --camera from $image 675 # --stage 676 # --stage_id from $image 677 # --component from $image 678 # --path_base 679 # --outdir global to this script 680 367 681 # loop over images 368 my $job_num = 0;369 682 foreach my $image (@$imageList) { 370 my $component; 371 if ($have_skycells) { 372 $component = $image->{skycell_id}; 373 } else { 374 $component = $image->{class_id}; 375 } 376 377 # skip this component if it is not in the list for this row 378 next if ! $components->{$component}; 379 380 $job_num++; 683 my $stage_id = $image->{stage_id}; 684 my $component = $image->{component}; 685 686 # skip faulted components for now. Should we even be here? 687 if ($image->{fault} > 0) { 688 printf STDERR "skipping faulted component for $stage $stage_id $component\n" if $verbose; 689 next; 690 } 691 692 my $job_num = ++($row->{job_num}); 381 693 382 694 my $imagefile = $image->{image}; 383 695 if (($stage ne "stack") and ($need_magic and !$image->{magicked})) { 384 # XXX: should we add a faulted job so the client can know what happened if no images come back? 385 # The test for destreaked is made in locate_images now so this code never runs. This leads to no feedback 386 # to users, but speeds up processing significantly 696 # we only get here if req_type is (byid or byexp). For other types the test for magicked is performed 697 # in locate_images because it's much more efficient to do the test in the database. 698 # For these two modes we fall through to here in order to give feedback to the requestor as 699 # to why the request failed to queue jobs. 387 700 print STDERR "skipping non-magicked image $imagefile\n" if $verbose; 388 389 # for now assume yes.390 391 701 insertFakeJobForRow($row, $job_num, $PSTAMP_NOT_DESTREAKED); 392 702 $num_jobs++; … … 396 706 my $exp_id = $image->{exp_id}; 397 707 398 my $args = $roi_string ? $roi_string : ""; 399 if ($stage eq "raw" or $stage eq "chip") { 400 $args .= " -class_id $component" if $component; 401 } 402 403 # add astrometry file for raw and chip images if one is available 404 if (($stage eq "chip") || ($stage eq "raw")) { 405 $args .= " -astrom $image->{astrom}" if $image->{astrom}; 406 } 407 408 $image->{job_args} = $args; 409 410 # XXX: we can get rid of the following everything that we need is 411 # in the params file 412 413 $args .= " -file $imagefile"; 414 415 if (($option_mask & $PSTAMP_SELECT_MASK) && $image->{mask} ) { 416 $args .= " -mask $image->{mask}"; 417 } 418 if (($option_mask & $PSTAMP_SELECT_WEIGHT) and $image->{weight} ) { 419 $args .= " -variance $image->{weight}"; 420 } 421 422 my $base = basename($image->{image}); 423 if (! $base =~ /.fits$/ ) { 424 my_die("unexpected image file name found $image->{image}", $PS_EXIT_PROG_ERROR); 425 } 426 $base =~ s/.fits$//; 427 428 # XXX: TODO use filerule for this. I don't have a camera defined here 429 if (($stage eq 'chip') and ($image->{camera} eq 'GPC1')) { 430 $base = "${base}.${component}"; 431 } 432 433 my $output_base = "$out_dir/${rownum}_${job_num}_${base}"; 434 my $argslist = "${output_base}.args"; 435 436 # copy the argument list to a file 437 open ARGSLIST, ">$argslist" or my_die("failed to open $argslist", $PS_EXIT_UNKNOWN_ERROR); 438 print ARGSLIST "$args\n"; 439 close ARGSLIST or my_die("failed to close $argslist", $PS_EXIT_UNKNOWN_ERROR); 708 my $output_base = "$out_dir/${rownum}_${job_num}"; 440 709 441 710 write_params($output_base, $image); … … 454 723 $newState = 'stop'; 455 724 $fault = $PSTAMP_GONE; 456 } elsif (($data_state ne 'full') or ($ run_state ne 'full')) {725 } elsif (($data_state ne 'full') or ($need_magic and ($image->{magicked} < 0))) { 457 726 # don't wait for update unless the caller asks us to 458 727 if (!($option_mask & $PSTAMP_WAIT_FOR_UPDATE)) { … … 463 732 # set up to queue an update run 464 733 queue_update_run(\$newState, \$fault, \$dep_id, $image->{image_db}, 465 $run_state, $stage, $image->{stage_id}, $ need_magic);734 $run_state, $stage, $image->{stage_id}, $image->{component}, $need_magic); 466 735 } 467 736 } … … 475 744 $command .= " -dep_id $dep_id" if $dep_id; 476 745 477 if ($mode eq "list_job") { 478 # this is a debugging mode, just print the pstamptool that would have run 479 # this is sort of like the mode -noupdate that some other tools support 480 print "$command\n"; 481 } elsif (!$no_update) { 482 # mode eq "queue_job" 483 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = 484 run(command => $command, verbose => $verbose); 485 unless ($success) { 486 print STDERR @$stderr_buf; 487 # XXX TODO: now what? Should we mark the error state for the request? 488 # should we keep going for other uris? If so how do we report that some 489 # of the work that the request wanted isn't going to get done 490 my_die("failed to queue job for request $req_id", $PS_EXIT_UNKNOWN_ERROR); 491 } 492 } else { 493 print "skipping command: $command\n"; 494 } 495 } 496 if ( $num_jobs == 0 ) { 497 print STDERR "no jobs for row $rownum\n" if $verbose; 498 insertFakeJobForRow($row, 1, $PSTAMP_NO_OVERLAP); 499 $num_jobs = 1; 500 } 501 return $num_jobs; 502 } 503 504 # queue jobs for a collection of request specifications that have the same Images of Interest 505 sub queueJobs 506 { 507 my $mode = shift; 508 my $rowList = shift; 509 my $imageList = shift; 510 511 my $firstRow = $rowList[0]; 512 my $stage = $firstRow->{IMG_TYPE}; 513 my $job_type = $firstRow->{JOB_TYPE}; 514 my $need_magic = $firstRow->{need_magic}; 515 516 my $num_jobs = 0; 517 518 if ($mode eq "list_uri") { 519 foreach my $image (@$imageList) { 520 print "$image->{image}\n"; 521 } 522 } elsif ($job_type eq "get_image") { 523 my $n = scalar @$rowList; 524 525 my_die( "error: unexpected number of rows for get_image request: $n", $PS_EXIT_PROG_ERROR) if $n != 1; 526 527 $num_jobs = queueGetImageJobs($firstRow, $imageList, $stage, $need_magic, $mode); 528 529 } else { 530 if (!$imageList or (scalar @$imageList eq 0)) { 531 # we didn't find any images for this set of rows. Insert a fake job to carry 532 # the status back to the requestor 533 foreach my $row (@$rowList) { 534 insertFakeJobForRow($row, 1, $PSTAMP_NO_IMAGE_MATCH); 535 $num_jobs++; 536 } 537 return $num_jobs; 538 } 539 540 my $have_skycells; 541 if (($stage eq "raw") or ($stage eq "chip")) { 542 $have_skycells = 0; 543 } else { 544 $have_skycells = 1; 545 } 546 547 my $thisRun; 548 549 my $npoints = 0; 550 my ($pointsList, $pointsListName); 551 if (scalar @$imageList > 1) { 552 ($pointsList, $pointsListName) = tempfile ("/tmp/pointsList.XXXX", UNLINK => !$save_temps); 553 foreach my $row (@$rowList) { 554 $row->{components} = {}; 555 if ($row->{skycenter}) { 556 print $pointsList "$row->{ROWNUM} $row->{CENTER_X} $row->{CENTER_Y}\n"; 557 $npoints++; 558 } else { 559 # this row's center is in pixel coordinates add all images to the component list for this row 560 foreach my $i (@$imageList) { 561 my $component = $have_skycells ? $i->{skycell_id} : $i->{class_id}; 562 my_die( "image found with no value for component", $PS_EXIT_UNKNOWN_ERROR) 563 if !$component; 564 $row->{components}->{$component} = 1; 565 } 566 } 567 } 568 close $pointsList; 569 } else { 570 # only one image. Avoid the expense of dvoImagesAtCoords. 571 # queue the job and let ppstamp figure out if the center is valid for the image 572 # the resulting result code will be the same. 573 foreach my $row (@$rowList) { 574 $row->{components} = {}; 575 my $i = $imageList->[0]; 576 my $component = $have_skycells ? $i->{skycell_id} : $i->{class_id}; 577 my_die( "image found with no value for component", $PS_EXIT_UNKNOWN_ERROR) if !$component; 578 $row->{components}->{$component} = 1; 579 } 580 } 581 582 my $tess_dir_abs; 583 my $last_tess_id = ""; 584 while ($thisRun = getOneRun($stage, $imageList)) { 585 if ($npoints) { 586 my_die( "pointsListName is not defined", $PS_EXIT_PROG_ERROR) if !$pointsListName; 587 # we collected a set of sky coordinates above. 588 # filter the images so that only those that contain the centers of the ROIs are processed 589 my $command = "$dvoImagesAtCoords -coords $pointsListName"; 590 if ($have_skycells) { 591 my $tess_id = $thisRun->[0]->{tess_id}; 592 if ($tess_id ne $last_tess_id) { 593 $tess_dir_abs = $ipprc->tessellation_catdir( $tess_id ); 594 $tess_dir_abs = $ipprc->convert_filename_absolute( $tess_dir_abs ); 595 $last_tess_id = $tess_id; 596 } 597 $command .= " -D CATDIR $tess_dir_abs"; 598 } else { 599 my $astrom = $thisRun->[0]->{astrom}; 600 my_die( "no astrometry file found", $PS_EXIT_UNKNOWN_ERROR) if !$astrom; 601 my $astrom_resolved = $ipprc->file_resolve($astrom); 602 $command .= " -astrom $astrom_resolved"; 603 } 604 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = 605 run(command => $command, verbose => $verbose); 606 unless ($success) { 607 # don't fail if the program exited normally and exit status was PSTAMP_NO_OVERLAP 608 # That just means that the coordinate didn't match any image/skycell 609 if (!WIFEXITED($error_code) || (WEXITSTATUS($error_code) ne $PSTAMP_NO_OVERLAP)) { 610 print STDERR @$stderr_buf; 611 my $rc = WIFEXITED($error_code) ? WEXITSTATUS($error_code) : $PS_EXIT_SYS_ERROR; 612 my_die( "dvoImagesAtCoords failed: $rc", $rc); 613 } 614 } 615 # now we have a list of row numbers and components 616 # eventually we might want to multiple stamp requests for the same image 617 # into the same ppstamp job but not yet. For now we will queue a new 618 my @lines = split "\n", join "", @$stdout_buf; 619 foreach my $line (@lines) { 620 # parse the line, ignoring the ra and dec 621 my ($rownum, undef, undef, $component) = split " ", $line; 622 623 # I guess since we need this function we should be using a hash for rowList 624 my $row = findRow($rownum, $rowList); 625 $row->{components}->{$component} = 1; 626 } 627 } 628 629 foreach my $row (@$rowList) { 630 $num_jobs += queueJobsForRow($row, $stage, $thisRun, $have_skycells, $need_magic, $mode); 631 } 632 } 633 } 634 return $num_jobs; 635 } 636 637 # $num_jobs = queueGetImageJobs($firstRow, $imageList, $stage, $need_magic, $mode); 638 sub queueGetImageJobs 639 { 640 my $row = shift; 641 my $imageList = shift; 642 my $stage = shift; 643 my $need_magic = shift; 644 my $mode = shift; 645 646 my $num_jobs = 0; 647 my $rownum = $row->{ROWNUM}; 648 my $option_mask = $row->{OPTION_MASK}; 649 650 # For dist_bundle we need 651 # --camera from $image 652 # --stage 653 # --stage_id from $image 654 # --component from $image 655 # --path_base 656 # --outdir global to this script 657 658 # loop over images 659 my $job_num = 0; 660 foreach my $image (@$imageList) { 661 my $stage_id = $image->{stage_id}; 662 my $component = $image->{component}; 663 664 # skip faulted components for now. Should we even be here? 665 if ($image->{fault} > 0) { 666 printf STDERR "skipping faulted component for $stage $stage_id $component\n" if $verbose; 667 next; 668 } 669 670 $job_num++; 671 672 my $imagefile = $image->{image}; 673 if (($stage ne "stack") and ($need_magic and !$image->{magicked})) { 674 # we only get here if req_type is (byid or byexp). For other types the test for magicked is performed 675 # in locate_images because it's much more efficient to do the test in the database. 676 # For these two modes we fall through to here in order to give feedback to the requestor as 677 # to why the request failed to queue jobs. 678 print STDERR "skipping non-magicked image $imagefile\n" if $verbose; 679 insertFakeJobForRow($row, $job_num, $PSTAMP_NOT_DESTREAKED); 680 $num_jobs++; 681 682 next; 683 } 684 my $exp_id = $image->{exp_id}; 685 686 my $output_base = "$out_dir/${rownum}_${job_num}"; 687 688 write_params($output_base, $image); 689 690 my $newState = "run"; 691 my $fault = 0; 692 my $dep_id; 693 694 if ($stage ne 'raw') { 695 my $run_state = $image->{state}; 696 my $data_state = $image->{data_state}; 697 $data_state = $run_state if $stage eq "stack"; 698 if (($run_state eq 'goto_purged') or ($data_state eq 'purged') or 699 ($run_state eq 'goto_scrubbed') or ($data_state eq 'scrubbed')) { 700 # image is gone and it's not coming back 701 $newState = 'stop'; 702 $fault = $PSTAMP_GONE; 703 } elsif (($data_state ne 'full') or ($run_state ne 'full' )) { 704 # don't wait for update unless the caller asks us to 705 if (!($option_mask & $PSTAMP_WAIT_FOR_UPDATE)) { 706 $newState = 'stop'; 707 $fault = $PSTAMP_NOT_AVAILABLE; 708 } else { 709 # cause the image to be re-made 710 # set up to queue an update run 711 queue_update_run(\$newState, \$fault, \$dep_id, $image->{image_db}, 712 $run_state, $stage, $image->{stage_id}, $need_magic); 713 } 714 } 715 } 716 717 $num_jobs++; 718 my $command = "$pstamptool -addjob -req_id $req_id -job_type $row->{JOB_TYPE}" 719 . " -outputBase $output_base -rownum $rownum -state $newState -options $option_mask"; 720 $command .= " -fault $fault" if $fault; 721 $command .= " -exp_id $exp_id" if $exp_id; 722 $command .= " -dep_id $dep_id" if $dep_id; 723 724 if ($mode eq "list_job") { 725 # this is a debugging mode, just print the pstamptool that would have run 726 # this is sort of like the mode -noupdate that some other tools support 727 print "$command\n"; 728 } elsif (!$no_update) { 746 if (!$no_update) { 729 747 # mode eq "queue_job" 730 748 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = … … 776 794 . " -rownum $rownum -state stop -fault $fault"; 777 795 778 if ($mode eq "list_job") { 779 # this is a debugging mode, just print the pstamptool that would have run 780 # this is sort of like the mode -noupdate that some other tools support 781 print "$command\n"; 782 } elsif (!$no_update) { 796 if (!$no_update) { 783 797 # mode eq "queue_job" 784 798 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = … … 796 810 } 797 811 798 sub get_run_id799 {800 my $stage = shift;801 my $image = shift;802 803 if ($stage eq "raw") {804 return $image->{exp_id};805 } elsif ($stage eq "chip") {806 return $image->{chip_id};807 } elsif ($stage eq "warp") {808 return $image->{warp_id};809 } elsif ($stage eq "stack") {810 return $image->{stack_id};811 } elsif ($stage eq "diff") {812 return $image->{diff_id};813 } else {814 my_die("unenexpected stage: $stage found", $PS_EXIT_PROG_ERROR);815 }816 }817 818 # extract components from the imageList that have the same run id and return the list819 sub getOneRun {820 my $stage = shift;821 my $imageList = shift;822 823 # return if array is empty824 return undef if ! @$imageList;825 826 my $last_run_id = 0;827 my @runList;828 while ($imageList->[0]) {829 my $run_id = get_run_id($stage, $imageList->[0]);830 831 last if ($last_run_id and ($run_id ne $last_run_id));832 833 my $image = shift @$imageList;834 $image->{stage} = $stage;835 push @runList, $image;836 $last_run_id = $run_id;837 }838 return \@runList;839 }840 841 812 sub same_images_of_interest { 842 813 my $r1 = shift; 843 814 my $r2 = shift; 844 815 845 return 0 if (($r1->{REQ_TYPE} eq "bycoord") or ($r2->{REQ_TYPE} eq "bycoord")); 846 return 0 if ($r1->{PROJECT} ne $r2->{PROJECT}); 847 return 0 if ($r1->{JOB_TYPE} ne $r2->{JOB_TYPE}); 816 return 0 if (($r1->{REQ_TYPE} eq "bycoord") or ($r2->{REQ_TYPE} eq "bycoord")); 817 return 0 if (($r1->{JOB_TYPE} eq "get_image") or ($r2->{JOB_TYPE} eq "get_image")); 848 818 return 0 if ($r1->{REQ_TYPE} ne $r2->{REQ_TYPE}); 849 819 return 0 if ($r1->{IMG_TYPE} ne $r2->{IMG_TYPE}); 850 820 return 0 if ($r1->{ID} ne $r2->{ID}); 851 821 return 0 if ($r1->{TESS_ID} ne $r2->{TESS_ID}); 822 return 0 if ($r1->{COMPONENT} ne $r2->{COMPONENT}); 852 823 return 0 if ($r1->{REQFILT} ne $r2->{REQFILT}); 853 824 return 0 if ($r1->{DATA_GROUP} ne $r2->{DATA_GROUP}); 854 825 return 0 if ($r1->{MJD_MIN} ne $r2->{MJD_MAX}); 855 826 return 0 if ($r1->{MJD_MAX} ne $r2->{MJD_MAX}); 827 return 0 if ($r1->{OPTION_MASK} ne $r2->{OPTION_MASK}); 828 return 0 if ($r1->{PROJECT} ne $r2->{PROJECT}); 856 829 return 0 if ($r1->{inverse} ne $r2->{inverse}); 857 830 return 0 if ($r1->{unconvolved} ne $r2->{unconvolved}); 858 859 if (defined($r1->{COMPONENT})) { 860 return 0 if !defined $r2->{COMPONENT} or ($r1->{COMPONENT} ne $r2->{COMPONENT}); 861 } elsif (defined($r2->{COMPONENT})) { 862 # if first row has no component all of the images will be retrieved, so 863 # the fact that this row has a component is ok. Fall through to return 1 864 # XXX Nope this doesn't work. It is consistent with the other logic in some way 865 # that i haven't fully thought through 866 return 0; 867 } 831 # don't combine requests in pixel coordinates 832 return 0 if (($r1->{COORD_MASK} & $PSTAMP_CENTER_IN_PIXELS) || ($r2->{COORD_MASK} & $PSTAMP_CENTER_IN_PIXELS)); 868 833 869 834 return 1; … … 911 876 sub queue_update_run 912 877 { 913 my ($r_jobState, $r_fault, $r_dep_id, $imagedb, $state, $stage, $stage_id, $ need_magic) = @_;878 my ($r_jobState, $r_fault, $r_dep_id, $imagedb, $state, $stage, $stage_id, $component, $need_magic) = @_; 914 879 915 880 if (($state ne 'cleaned') and ($state ne 'update') and ($state ne 'goto_cleaned')) { … … 918 883 919 884 my $dep_id; 920 my $command = "$pstamptool -getdependent -stage $stage -stage_id $stage_id -imagedb $imagedb"; 921 $command .= " -no_magic" if !$need_magic; 885 my $command = "$pstamptool -getdependent -stage $stage -stage_id $stage_id -imagedb $imagedb -component $component"; 886 $command .= " -need_magic" if $need_magic; 887 888 # compute rlabel for the run. 889 # XXX: This bit of policy shouldn't be buried so deeply in the code 890 # For now use one that implies 'postage stamp server' 'update' 'request_label" 891 my $rlabel = "ps_ud_" . $label if $label; 892 $command .= " -rlabel $rlabel" if $rlabel; 893 922 894 if (!$no_update) { 923 895 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = … … 929 901 chomp $output; 930 902 $dep_id = $output; 903 # 904 # XXX: need to fault the request or something 931 905 my_die("pstamptool -getdependent returned invalid dep_id", $PS_EXIT_PROG_ERROR) if !$dep_id; 932 906 } else { … … 936 910 937 911 $$r_dep_id = $dep_id; 938 $ r_fault = 0;939 $ r_jobState = 'blocked';912 $$r_fault = 0; 913 $$r_jobState = 'run'; 940 914 } 941 915 … … 990 964 # we don't fault the request here pstamp_parser_run.pl handles that if necessary 991 965 992 return$fault;993 } 966 exit $fault; 967 }
Note:
See TracChangeset
for help on using the changeset viewer.
