Changeset 28003 for branches/pap/pstamp/scripts/pstampparse.pl
- Timestamp:
- May 18, 2010, 12:49:05 PM (16 years ago)
- Location:
- branches/pap
- Files:
-
- 2 edited
-
. (modified) (1 prop)
-
pstamp/scripts/pstampparse.pl (modified) (24 diffs)
Legend:
- Unmodified
- Added
- Removed
-
branches/pap
- Property svn:mergeinfo changed
-
branches/pap/pstamp/scripts/pstampparse.pl
r27524 r28003 17 17 use Carp; 18 18 use POSIX; 19 use Time::HiRes qw(gettimeofday); 19 20 20 21 my $verbose; … … 24 25 my $request_file_name; 25 26 my $mode = "list_uri"; 26 my $out _dir;27 my $outdir; 27 28 my $product; 29 my $label; 28 30 my $save_temps; 29 31 my $no_update; … … 32 34 'file=s' => \$request_file_name, 33 35 'req_id=s' => \$req_id, 34 'out _dir=s' => \$out_dir,36 'outdir=s' => \$outdir, 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 47 50 if ($mode ne "list_uri") { 48 51 die "req_id is required" if !$req_id; 49 die "out _dir is required" if !$out_dir;52 die "outdir is required" if !$outdir; 50 53 die "product is required" if !$product; 51 54 } … … 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 … … 127 129 # update the database with the request name. This will be used as the 128 130 # the output data store's product name 129 my $command = "$pstamptool -updatereq -req_id $req_id - name $req_name";130 $command .= " - outProduct $product";131 my $command = "$pstamptool -updatereq -req_id $req_id -set_name $req_name"; 132 $command .= " -set_outProduct $product"; 131 133 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = 132 134 run(command => $command, verbose => $verbose); … … 145 147 my $rows; 146 148 { 149 my $start_request_file = gettimeofday(); 147 150 my $command = "$pstampdump $request_file_name"; 148 151 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = … … 152 155 } 153 156 if (@$stdout_buf) { 154 my $table = $mdcParser->parse(join "", @$stdout_buf) or 155 my_die("Unable to parse metdata config doc", $PS_EXIT_UNKNOWN_ERROR); 156 $rows = parse_md_list($table); 157 } 158 159 } 160 157 $rows = parse_md_fast($mdcParser, join "", @$stdout_buf); 158 } 159 my $dtime_request_file = gettimeofday() - $start_request_file; 160 print "Time to read and parse request file: $dtime_request_file\n"; 161 162 } 163 164 # 165 # Loop over rows in the request file collecting consecutive rows that have the "same images of interest" 166 # in the sense that their selection parameters will yield the same "Runs". 167 # Process the groups of rows together to reduce lookup time and to potentially make multiple 168 # stamps from the same ppstamp process. 169 # 161 170 my @rowList; 162 171 my $num_jobs = 0; … … 165 174 my $need_magic; 166 175 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); 176 # santiy check the paramaters 177 if (!checkRow($row)) { 178 # when it enconters an error checkRow adds a fake job with an appropriate error code to the database 185 179 $num_jobs++; 186 180 next; 187 181 } 182 # initialize counter for "job number" 183 $row->{job_num} = 0; 184 $row->{error_code} = 0; 185 186 if (scalar @rowList == 0) { 187 push @rowList, $row; 188 next; 189 } 190 191 my $firstRow = $rowList[0]; 192 if (same_images_of_interest($firstRow, $row)) { 193 # add this row to the list and move on 194 push @rowList, $row; 195 next; 196 } 197 198 # the images of interest for this new row doesn't match the list. 199 # process the list ... 200 $num_jobs += processRows(\@rowList); 201 202 # and reset the list to contain just the new row 203 @rowList = ($row); 204 } 205 206 # out of rows process the list 207 if (scalar @rowList > 0) { 208 $num_jobs += processRows(\@rowList); 209 } 210 211 if (($mode eq "queue_job") and ($num_jobs eq 0)) { 212 print STDERR "no jobs created for $req_name\n" if $verbose; 213 insertFakeJobForRow(undef, 0, $PSTAMP_INVALID_REQUEST); 214 } 215 216 exit 0; 217 218 sub checkRow { 219 220 my $row = shift; 221 222 # If we encounter an error for a particular row add a job with the proper fault code. 223 224 my $rownum = $row->{ROWNUM}; 225 if (!validID($rownum)) { 226 print STDERR "$rownum is not a valid ROWNUM\n"; 227 insertFakeJobForRow($row, 1, $PSTAMP_INVALID_REQUEST); 228 return 0; 229 } 230 my $job_type = $row->{JOB_TYPE}; 231 if (($job_type ne "stamp") and ($job_type ne "get_image")) { 232 print STDERR "$job_type is not a valid JOB_TYPE\n"; 233 insertFakeJobForRow($row, 1, $PSTAMP_INVALID_REQUEST); 234 return 0; 235 } 236 188 237 my $req_type = $row->{REQ_TYPE}; 189 $stage = $row->{IMG_TYPE}; 190 my $id = $row->{ID}; 238 if (($req_type ne "byid") and ($req_type ne "bycoord") and ($req_type ne "byexp") and 239 ($req_type ne "byskycell") and ($req_type ne "bydiff")) { 240 print STDERR "$req_type is not a valid REQ_TYPE\n"; 241 insertFakeJobForRow($row, 1, $PSTAMP_INVALID_REQUEST); 242 return 0; 243 } 244 if ($job_type eq 'get_image') { 245 unless ($req_type eq 'byid' or $req_type eq 'byexp') { 246 print STDERR "REQ_TYPE must be 'byid' or 'byexp' for JOB_TYPE 'get_image'\n"; 247 insertFakeJobForRow($row, 1, $PSTAMP_INVALID_REQUEST); 248 return 0; 249 } 250 } 251 252 191 253 my $component = $row->{COMPONENT}; 192 my $tess_id = $row->{TESS_ID}; 254 if (!defined $component or (lc($component) eq "null") or (lc($component) eq "all")) { 255 if ($job_type eq 'get_image') { 256 $row->{COMPONENT} = 'all'; 257 } else { 258 $row->{COMPONENT} = $component = ""; 259 } 260 } 261 $row->{TESS_ID} = "" if !defined $row->{TESS_ID}; 193 262 194 263 my $filter = $row->{REQFILT}; … … 196 265 if (length($filter) == 1) { 197 266 # allow single character filter cuts to work 198 $ filter.= '%';267 $row->{REQFILT} .= '%'; 199 268 } 200 269 } 201 270 my $mjd_min = $row->{MJD_MIN}; 271 if (defined($mjd_min) and !validNumber($mjd_min)) { 272 print STDERR "$mjd_min is not a valid MJD_MIN\n"; 273 insertFakeJobForRow($row, 1, $PSTAMP_INVALID_REQUEST); 274 return 0; 275 } 202 276 my $mjd_max = $row->{MJD_MAX}; 277 if (defined($mjd_max) and !validNumber($mjd_max)) { 278 print STDERR "$mjd_max is not a valid MJD_MAX\n"; 279 insertFakeJobForRow($row, 1, $PSTAMP_INVALID_REQUEST); 280 return 0; 281 } 203 282 my $data_group = $row->{DATA_GROUP}; 204 283 if (!defined $data_group) { … … 209 288 } 210 289 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; 290 # req_finish doesn't work if bit zero of option mask is not set; 215 291 $row->{OPTION_MASK} |= 1; 292 216 293 my $option_mask= $row->{OPTION_MASK}; 217 294 my $inverse = ($option_mask & $PSTAMP_SELECT_INVERSE) ? 1 : 0; … … 222 299 my $skycenter = $row->{skycenter} = ! ($row->{COORD_MASK} & $PSTAMP_CENTER_IN_PIXELS); 223 300 224 my $search_component = (!defined($component) or ($component eq "null")) ? "" : $component; 225 226 if (!$skycenter and !$search_component) { 227 print STDERR "COMPONENT must be specified for pixel coordinate ROI center\n" if $verbose; 301 if (!$skycenter and !$component) { 302 print STDERR "COMPONENT must be specified for pixel coordinate ROI center\n"; 228 303 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 304 return 0; 305 } 306 307 my $stage = $row->{IMG_TYPE}; 236 308 if (!check_image_type($stage)) { 237 print STDERR "invalid IMG_TYPE for row $rownum\n" if $verbose;309 print STDERR "invalid IMG_TYPE for row $rownum\n"; 238 310 insertFakeJobForRow($row, 1, $PSTAMP_INVALID_REQUEST); 239 $num_jobs++; 240 next; 311 return 0; 241 312 } 242 313 243 314 if ((($job_type eq "stamp") or ($req_type eq "bycoord")) and ! validROI($row)) { 244 print STDERR "invalid ROI for row $rownum\n" if $verbose;315 print STDERR "invalid ROI for row $rownum\n"; 245 316 insertFakeJobForRow($row, 1, $PSTAMP_INVALID_REQUEST); 246 $num_jobs++; 247 next; 317 return 0; 248 318 } 249 319 250 320 if (($req_type eq "byexp") and ($stage eq "stack")) { 251 print STDERR "byexp not implemented for stack stage. row: $rownum\n" if $verbose;321 print STDERR "byexp not implemented for stack stage. row: $rownum\n"; 252 322 insertFakeJobForRow($row, 1, $PSTAMP_NOT_IMPLEMENTED); 253 $num_jobs++; 254 next; 255 } 256 257 323 return 0; 324 } 325 258 326 # $mode list_uri is a debugging mode (it may used by the http interface) 259 327 # 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 328 # 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"); 329 330 331 if ($req_type eq "bycoord") { 332 if (!$skycenter) { 333 print STDERR "center must be specified in sky coordintes for bycoord"; 334 insertFakeJobForRow($row, 1, $PSTAMP_INVALID_REQUEST); 335 return 0; 336 } 337 } 338 339 if (($req_type eq "byid") or ($req_type eq "bydiff")) { 340 if (!validID($row->{ID})) { 341 print STDERR "ID must be a positive integer for req_type $req_type\n"; 342 insertFakeJobForRow($row, 1, $PSTAMP_INVALID_REQUEST); 343 return 0 344 } 345 } 346 347 return 1; 348 } 349 350 sub processRows { 351 my $rowList = shift; 352 my $num_jobs = 0; 353 354 # all rows in the list are compatible 355 my $row = $rowList->[0]; 356 357 my $project = $row->{PROJECT}; 358 359 # note: resolve_project avoids running pstamptool every time by remembering the 360 # last project resolved 361 my $proj_hash = resolve_project($ipprc, $project, $dbname, $dbserver); 362 if (!$proj_hash) { 363 print STDERR "project $project not found\n" ; 364 foreach $row (@$rowList) { 365 insertFakeJobForRow($row, 1, $PSTAMP_UNKNOWN_PRODUCT); 366 $num_jobs++; 367 } 368 return $num_jobs; 369 } 370 my $req_type = $row->{REQ_TYPE}; 371 $stage = $row->{IMG_TYPE}; 372 my $id = $row->{ID}; 373 my $component = $row->{COMPONENT}; 374 my $tess_id = $row->{TESS_ID}; 375 376 my $filter = $row->{REQFILT}; 377 my $mjd_min = $row->{MJD_MIN}; 378 my $mjd_max = $row->{MJD_MAX}; 379 my $data_group = $row->{DATA_GROUP}; 380 381 my $rownum = $row->{ROWNUM}; 382 my $job_type = $row->{JOB_TYPE}; 383 my $option_mask= $row->{OPTION_MASK}; 384 262 385 my $image_db = $proj_hash->{dbname}; 263 386 my $camera = $proj_hash->{camera}; 264 $need_magic = $proj_hash->{need_magic};387 $need_magic = $proj_hash->{need_magic}; 265 388 266 389 # 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 291 if ($req_type eq "bycoord") { 292 if (!$skycenter) { 293 print STDERR "center must be specified in sky coordintes for bycoord" if $verbose; 294 insertFakeJobForRow($row, 1, $PSTAMP_INVALID_REQUEST); 295 $num_jobs++; 296 next; 297 } 298 } 299 if (($req_type eq "byid") or ($req_type eq "bydiff")) { 300 if (!validID($id)) { 301 print STDERR "ID must be a positive integer for req_type $req_type\n" if $verbose; 302 insertFakeJobForRow($row, 1, $PSTAMP_INVALID_REQUEST); 303 $num_jobs++; 304 next; 305 } 306 } 390 my $allow_mops_unmagicked = 1; 391 if ($allow_mops_unmagicked) { 392 if ($product and (($product eq "mops-pstamp-results") or 393 ($product eq "mops-pstamp-results2"))) { 394 $need_magic = 0; 395 } 396 } 397 398 $need_magic = 0 if $stage eq 'stack'; 399 400 my $numRows = scalar @$rowList; 401 402 print "Collected $numRows rows beginning with row $rownum. $req_type $stage $id $tess_id $component\n"; 403 307 404 # Call PS::IPP::PStamp::Job locate_images subroutine to get the images for this 308 405 # 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); 311 312 if (!$imageList or !@$imageList) { 313 print STDERR "no matching images found for row $rownum\n" if $verbose; 314 # note in this case queueJobs inserts the fake job for these rows 315 } 406 my $start_locate = gettimeofday(); 407 408 # XXX: perhaps we should get rid of most of this argument list. 409 # Now that we are passing down compatible rows all of the 410 # information required is contained there 411 412 $imageList = locate_images($ipprc, $image_db, \@rowList, $req_type, $stage, $id, $tess_id, $component, 413 $option_mask, $need_magic, $mjd_min, $mjd_max, $filter, $data_group, $verbose); 414 415 my $dtime_locate = gettimeofday() - $start_locate; 416 print "Time to locate_images for row $rownum $dtime_locate\n"; 417 418 # handle this XXX: what did I mean by this comment 316 419 $row->{need_magic} = $need_magic; 317 push @rowList, $row; 318 } 319 320 if (@rowList) { 420 321 421 $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 422 423 # if a row slipped through with no jobs add one 424 foreach my $row (@rowList) { 425 if ($row->{job_num} == 0) { 426 print "row $row->{ROWNUM} produced no jobs\n"; 427 print STDERR "row $row->{ROWNUM} produced no jobs\n"; 428 my $error_code = $row->{error_code}; 429 $error_code = $PSTAMP_NO_IMAGE_MATCH if !$error_code; 430 insertFakeJobForRow($row, ++$row->{job_num}, $error_code); 431 } 432 } 433 434 return $num_jobs; 435 } 436 437 sub queueJobForImage 335 438 { 336 439 my $row = shift; 337 440 my $stage = shift; 338 my $imageList = shift; 339 my $have_skycells = shift; 441 my $image = shift; 340 442 my $need_magic = shift; 341 443 my $mode = shift; 342 444 343 my $num_jobs = 0;344 445 my $rownum = $row->{ROWNUM}; 345 446 my $option_mask = $row->{OPTION_MASK}; … … 365 466 } 366 467 468 my $component = $image->{component}; 469 470 my $job_num = ++($row->{job_num}); 471 472 my $imagefile = $image->{image}; 473 if (($stage ne "stack") and ($need_magic and !$image->{magicked})) { 474 # XXX: should we add a faulted job so the client can know what happened if no images come back? 475 # The test for destreaked is made in locate_images now so this code never runs. This leads to no feedback 476 # to users, but speeds up processing significantly 477 print STDERR "skipping non-magicked image $imagefile\n" if $verbose; 478 479 # for now assume yes. 480 481 insertFakeJobForRow($row, $job_num, $PSTAMP_NOT_DESTREAKED); 482 return 1; 483 } elsif ($stage eq "stack") { 484 # unconvolved stack images weren't available prior to some point in time. 485 # XXX: handle this more correctly by examining the stack run's config dump file. 486 # It looks like # the feature was turned on sometime around November 11, 2009. stackRun 30067 is the lowest 487 # one that I found with an unconvolved image. 488 my $MIN_GPC1_STACK_ID_WITH_UNCONVOLVED_IMAGES = 30067; 489 if ($row->{unconvolved} and ($row->{PROJECT} eq 'gpc1') and 490 ($image->{stack_id} < $MIN_GPC1_STACK_ID_WITH_UNCONVOLVED_IMAGES)) { 491 print STDERR "Unconvolved stack image is not available for stackRun.stack_id: $image->{stack_id}\n"; 492 insertFakeJobForRow($row, $job_num, $PSTAMP_NOT_AVAILABLE); 493 return 1; 494 } 495 } 496 my $exp_id = $image->{exp_id}; 497 498 my $args = $roi_string ? $roi_string : ""; 499 if ($stage eq "raw" or $stage eq "chip") { 500 $args .= " -class_id $component" if $component; 501 } 502 503 # add astrometry file for raw and chip images if one is available 504 if (($stage eq "chip") || ($stage eq "raw")) { 505 $args .= " -astrom $image->{astrom}" if $image->{astrom}; 506 } 507 508 $image->{job_args} = $args; 509 510 my $base = basename($image->{image}); 511 if (! $base =~ /.fits$/ ) { 512 my_die("unexpected image file name found $image->{image}", $PS_EXIT_PROG_ERROR); 513 } 514 $base =~ s/.fits$//; 515 516 my $output_base = "$outdir/${rownum}_${job_num}_${base}"; 517 write_params($output_base, $image); 518 519 my $newState = "run"; 520 my $fault = 0; 521 my $dep_id; 522 523 # XXX: this code is repeated in queueGetImageJobs we should encapsulate it in a subroutine and share it 524 if ($stage ne 'raw') { 525 # updates for stack stage not supported yet 526 my $allow_wait_for_update = ($stage ne 'stack'); 527 my $run_state = $image->{state}; 528 my $data_state = $image->{data_state}; 529 $data_state = $run_state if $stage eq 'stack'; 530 if (($run_state eq 'goto_purged') or ($data_state eq 'purged') or 531 ($run_state eq 'drop') or 532 ($run_state eq 'error_cleaned') or ($data_state eq 'error_cleaned') or 533 ($run_state eq 'goto_scrubbed') or ($data_state eq 'scrubbed')) { 534 # image is gone and it's not coming back 535 $newState = 'stop'; 536 $fault = $PSTAMP_GONE; 537 } elsif (($data_state ne 'full') or ($need_magic and ($image->{magicked} < 0))) { 538 if ($stage eq 'chip') { 539 my $burntool_state = $image->{burntool_state}; 540 if ($burntool_state and (abs($burntool_state) < 14)) { 541 $newState = 'stop'; 542 $fault = $PSTAMP_NOT_AVAILABLE; 543 } 544 } 545 if (!$allow_wait_for_update) { 546 print STDERR "wait for update not supported for stage $stage yet\n"; 547 $newState = 'stop'; 548 $fault = $PSTAMP_NOT_AVAILABLE; 549 } 550 if (!$fault) { 551 # wait for update unless the customer asks us not to 552 if (($option_mask & $PSTAMP_NO_WAIT_FOR_UPDATE)) { 553 $newState = 'stop'; 554 $fault = $PSTAMP_NOT_AVAILABLE; 555 } elsif (!$image->{magicked}) { 556 $newState = 'stop'; 557 $fault = $PSTAMP_NOT_DESTREAKED; 558 } else { 559 # cause the image to be re-made 560 # set up to queue an update run 561 queue_update_run(\$newState, \$fault, \$dep_id, $image->{imagedb}, 562 $run_state, $stage, $image->{stage_id}, $image->{component}, $need_magic); 563 } 564 } 565 } 566 } 567 568 my $command = "$pstamptool -addjob -req_id $req_id -job_type $row->{JOB_TYPE}" 569 . " -outputBase $output_base -rownum $rownum -state $newState -options $option_mask"; 570 $command .= " -fault $fault" if $fault; 571 $command .= " -exp_id $exp_id" if $exp_id; 572 $command .= " -dep_id $dep_id" if $dep_id; 573 574 if (!$no_update) { 575 # mode eq "queue_job" 576 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = 577 run(command => $command, verbose => $verbose); 578 unless ($success) { 579 print STDERR @$stderr_buf; 580 # XXX TODO: now what? Should we mark the error state for the request? 581 # should we keep going for other uris? If so how do we report that some 582 # of the work that the request wanted isn't going to get done 583 my_die("failed to queue job for request $req_id", $PS_EXIT_UNKNOWN_ERROR); 584 } 585 } else { 586 print "skipping command: $command\n"; 587 } 588 589 return 1; 590 } 591 592 # queue jobs for a collection of request specifications that have the same Images of Interest 593 sub queueJobs 594 { 595 my $mode = shift; 596 my $rowList = shift; 597 my $imageList = shift; 598 599 my $firstRow = $rowList[0]; 600 my $stage = $firstRow->{IMG_TYPE}; 601 my $job_type = $firstRow->{JOB_TYPE}; 602 my $need_magic = $firstRow->{need_magic}; 603 604 my $num_jobs = 0; 605 606 if ($mode eq "list_uri") { 607 foreach my $image (@$imageList) { 608 print "$image->{image}\n"; 609 } 610 } elsif ($job_type eq "get_image") { 611 my $n = scalar @$rowList; 612 613 my_die( "error: unexpected number of rows for get_image request: $n", $PS_EXIT_PROG_ERROR) if $n != 1; 614 615 $num_jobs = queueGetImageJobs($firstRow, $imageList, $stage, $need_magic, $mode); 616 617 } else { 618 if (!$imageList or (scalar @$imageList eq 0)) { 619 # We didn't find any images for this set of rows. Insert a fake job to carry 620 # the status back to the requestor. 621 foreach my $row (@$rowList) { 622 my $error_code = $row->{error_code}; 623 $error_code = $PSTAMP_NO_IMAGE_MATCH if !$error_code; 624 insertFakeJobForRow($row, ++$row->{job_num}, $error_code); 625 $num_jobs++; 626 } 627 return $num_jobs; 628 } 629 630 foreach my $image (@$imageList) { 631 # get the array of row indices that touch this image 632 my $row_index = $image->{row_index}; 633 if (!$row_index or scalar @$row_index == 0) { 634 # XXX should this happen? Why did something get returned. 635 print "image ${stage}_id: $image->{stage_id} component: $image->{component} matched no rows\n"; 636 next; 637 } 638 # XXX: TODO: eventually we may change ppstamp to be able to make multiple stamps per invocation 639 640 foreach my $i (@$row_index) { 641 my $row = $rowList->[$i]; 642 643 $num_jobs += queueJobForImage($row, $stage, $image, $need_magic, $mode); 644 } 645 } 646 } 647 648 return $num_jobs; 649 } 650 651 sub queueGetImageJobs 652 { 653 my $row = shift; 654 my $imageList = shift; 655 my $stage = shift; 656 my $need_magic = shift; 657 my $mode = shift; 658 659 my $num_jobs = 0; 660 my $rownum = $row->{ROWNUM}; 661 my $option_mask = $row->{OPTION_MASK}; 662 663 # For dist_bundle we need 664 # --camera from $image 665 # --stage 666 # --stage_id from $image 667 # --component from $image 668 # --path_base 669 # --outdir global to this script 670 367 671 # loop over images 368 my $job_num = 0;369 672 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++; 673 my $stage_id = $image->{stage_id}; 674 my $component = $image->{component}; 675 676 # skip faulted components for now. Should we even be here? 677 if ($image->{fault} > 0) { 678 printf STDERR "skipping faulted component for $stage $stage_id $component\n" if $verbose; 679 next; 680 } 681 682 my $job_num = ++($row->{job_num}); 381 683 382 684 my $imagefile = $image->{image}; 383 685 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 686 # we only get here if req_type is (byid or byexp). For other types the test for magicked is performed 687 # in locate_images because it's much more efficient to do the test in the database. 688 # For these two modes we fall through to here in order to give feedback to the requestor as 689 # to why the request failed to queue jobs. 387 690 print STDERR "skipping non-magicked image $imagefile\n" if $verbose; 388 389 # for now assume yes.390 391 691 insertFakeJobForRow($row, $job_num, $PSTAMP_NOT_DESTREAKED); 392 692 $num_jobs++; … … 396 696 my $exp_id = $image->{exp_id}; 397 697 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); 698 my $output_base = "$outdir/${rownum}_${job_num}"; 440 699 441 700 write_params($output_base, $image); … … 454 713 $newState = 'stop'; 455 714 $fault = $PSTAMP_GONE; 456 } elsif (($data_state ne 'full') or ($ run_state ne 'full')) {457 # don't wait for update unless the caller asks usto458 if ( !($option_mask & $PSTAMP_WAIT_FOR_UPDATE)) {715 } elsif (($data_state ne 'full') or ($need_magic and ($image->{magicked} < 0))) { 716 # wait for update unless the customer asks us to not to 717 if ($option_mask & $PSTAMP_NO_WAIT_FOR_UPDATE) { 459 718 $newState = 'stop'; 460 719 $fault = $PSTAMP_NOT_AVAILABLE; … … 462 721 # cause the image to be re-made 463 722 # set up to queue an update run 464 queue_update_run(\$newState, \$fault, \$dep_id, $image->{image _db},465 $run_state, $stage, $image->{stage_id}, $ need_magic);723 queue_update_run(\$newState, \$fault, \$dep_id, $image->{imagedb}, 724 $run_state, $stage, $image->{stage_id}, $image->{component}, $need_magic); 466 725 } 467 726 } … … 475 734 $command .= " -dep_id $dep_id" if $dep_id; 476 735 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) { 736 if (!$no_update) { 729 737 # mode eq "queue_job" 730 738 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = … … 776 784 . " -rownum $rownum -state stop -fault $fault"; 777 785 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) { 786 if (!$no_update) { 783 787 # mode eq "queue_job" 784 788 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = … … 796 800 } 797 801 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 802 sub same_images_of_interest { 842 803 my $r1 = shift; 843 804 my $r2 = shift; 844 805 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}); 806 return 0 if (($r1->{REQ_TYPE} eq "bycoord") or ($r2->{REQ_TYPE} eq "bycoord")); 807 return 0 if (($r1->{JOB_TYPE} eq "get_image") or ($r2->{JOB_TYPE} eq "get_image")); 848 808 return 0 if ($r1->{REQ_TYPE} ne $r2->{REQ_TYPE}); 849 809 return 0 if ($r1->{IMG_TYPE} ne $r2->{IMG_TYPE}); 850 810 return 0 if ($r1->{ID} ne $r2->{ID}); 851 811 return 0 if ($r1->{TESS_ID} ne $r2->{TESS_ID}); 812 return 0 if ($r1->{COMPONENT} ne $r2->{COMPONENT}); 852 813 return 0 if ($r1->{REQFILT} ne $r2->{REQFILT}); 853 814 return 0 if ($r1->{DATA_GROUP} ne $r2->{DATA_GROUP}); 854 815 return 0 if ($r1->{MJD_MIN} ne $r2->{MJD_MAX}); 855 816 return 0 if ($r1->{MJD_MAX} ne $r2->{MJD_MAX}); 817 return 0 if ($r1->{OPTION_MASK} ne $r2->{OPTION_MASK}); 818 return 0 if ($r1->{PROJECT} ne $r2->{PROJECT}); 856 819 return 0 if ($r1->{inverse} ne $r2->{inverse}); 857 820 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 } 821 # don't combine requests in pixel coordinates 822 return 0 if (($r1->{COORD_MASK} & $PSTAMP_CENTER_IN_PIXELS) || ($r2->{COORD_MASK} & $PSTAMP_CENTER_IN_PIXELS)); 868 823 869 824 return 1; … … 911 866 sub queue_update_run 912 867 { 913 my ($r_jobState, $r_fault, $r_dep_id, $imagedb, $state, $stage, $stage_id, $need_magic) = @_; 868 my ($r_jobState, $r_fault, $r_dep_id, $imagedb, $state, $stage, $stage_id, $component, $need_magic) = @_; 869 870 # XXX: The update process for warp and subsequent stages requires 871 # destreaking to run because the -pending queries require it when magicked > 0 872 # queries. 873 # The case of stack-stack diffs is taken care of in pstamp_checkdependent 874 $need_magic = 1 if $imagedb eq 'gpc1'; 914 875 915 876 if (($state ne 'cleaned') and ($state ne 'update') and ($state ne 'goto_cleaned')) { … … 918 879 919 880 my $dep_id; 920 my $command = "$pstamptool -getdependent -stage $stage -stage_id $stage_id -imagedb $imagedb"; 921 $command .= " -no_magic" if !$need_magic; 881 my $command = "$pstamptool -getdependent -stage $stage -stage_id $stage_id -imagedb $imagedb -component $component -outdir $outdir"; 882 $command .= " -need_magic" if $need_magic; 883 884 # compute rlabel for the run. 885 # XXX: This bit of policy shouldn't be buried so deeply in the code 886 # For now use one that implies 'postage stamp server' 'update' 'request_label" 887 my $rlabel = "ps_ud_" . $label if $label; 888 $command .= " -rlabel $rlabel" if $rlabel; 889 922 890 if (!$no_update) { 923 891 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = … … 929 897 chomp $output; 930 898 $dep_id = $output; 899 # 900 # XXX: need to fault the request or something 931 901 my_die("pstamptool -getdependent returned invalid dep_id", $PS_EXIT_PROG_ERROR) if !$dep_id; 932 902 } else { … … 936 906 937 907 $$r_dep_id = $dep_id; 938 $ r_fault = 0;939 $ r_jobState = 'blocked';908 $$r_fault = 0; 909 $$r_jobState = 'run'; 940 910 } 941 911 … … 990 960 # we don't fault the request here pstamp_parser_run.pl handles that if necessary 991 961 992 return$fault;993 } 962 exit $fault; 963 }
Note:
See TracChangeset
for help on using the changeset viewer.
