IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Apr 23, 2010, 11:33:14 AM (16 years ago)
Author:
bills
Message:

Enable the postage stamp server to generate stamps from cleaned up data.
"Works" for chip and warp stages. diff and maybe stack to do.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/pstamp/scripts/pstampparse.pl

    r27524 r27751  
    1717use Carp;
    1818use POSIX;
     19use DateTime;
    1920
    2021my $verbose;
     
    2627my $out_dir;
    2728my $product;
     29my $label;
    2830my $save_temps;
    2931my $no_update;
     
    3436    'out_dir=s' =>  \$out_dir,
    3537    'product=s' =>  \$product,
     38    'label=s'   =>  \$label,
    3639    'mode=s'    =>  \$mode,
    3740    'dbname=s'  =>  \$dbname,
     
    4245);
    4346
    44 die "invalid mode '$mode'" unless ($mode eq "list_uri") or ($mode eq "list_job") or ($mode eq "queue_job");
     47die "invalid mode '$mode'" unless ($mode eq "list_uri") or ($mode eq "queue_job");
    4548die "--file is required"     if !defined($request_file_name);
    4649
     
    6467my $pstamptool  = can_run('pstamptool')  or (warn "Can't find pstamptool"  and $missing_tools = 1);
    6568my $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);
    6769my $fields  = can_run('fields') or (warn "Can't find fields" and $missing_tools = 1);
    6870
     
    159161}
    160162
     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#
    161169my @rowList;
    162170my $num_jobs = 0;
     
    165173my $need_magic;
    166174foreach 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
    185178        $num_jobs++;
    186179        next;
    187180    }
     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
     206if (scalar @rowList > 0) {
     207    $num_jobs += processRows(\@rowList);
     208}
     209
     210if (($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
     215exit 0;
     216
     217sub 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   
    188236    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
    191245    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};
    193250
    194251    my $filter  = $row->{REQFILT};
     
    196253        if (length($filter) == 1) {
    197254            # allow single character filter cuts to work
    198             $filter .= '%';
     255            $row->{REQFILT} .= '%';
    199256        }
    200257    }
    201258    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    }
    202264    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    }
    203270    my $data_group = $row->{DATA_GROUP};
    204271    if (!defined $data_group) {
     
    209276    }
    210277       
    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;
    215279    $row->{OPTION_MASK} |= 1;
     280
    216281    my $option_mask= $row->{OPTION_MASK};
    217282    my $inverse = ($option_mask & $PSTAMP_SELECT_INVERSE) ? 1 : 0;
     
    222287    my $skycenter = $row->{skycenter} = ! ($row->{COORD_MASK} & $PSTAMP_CENTER_IN_PIXELS);
    223288
    224     my $search_component = (!defined($component) or ($component eq "null")) ? "" : $component;
    225    
    226     if (!$skycenter and !$search_component) {
     289    if (!$skycenter and !$component) {
    227290        print STDERR "COMPONENT must be specified for pixel coordinate ROI center\n" if $verbose;
    228291        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};
    236296    if (!check_image_type($stage)) {
    237297        print STDERR "invalid IMG_TYPE for row $rownum\n" if $verbose;
    238298        insertFakeJobForRow($row, 1, $PSTAMP_INVALID_REQUEST);
    239         $num_jobs++;
    240         next;
     299        return 0;
    241300    }
    242301
     
    244303        print STDERR "invalid ROI for row $rownum\n" if $verbose;
    245304        insertFakeJobForRow($row, 1, $PSTAMP_INVALID_REQUEST);
    246         $num_jobs++;
    247         next;
     305        return 0;
    248306    }
    249307
     
    251309        print STDERR "byexp not implemented for stack stage. row: $rownum\n" if $verbose;
    252310        insertFakeJobForRow($row, 1, $PSTAMP_NOT_IMPLEMENTED);
    253         $num_jobs++;
    254         next;
    255     }
    256 
    257    
     311        return 0;
     312    }
     313
    258314    # $mode list_uri is a debugging mode (it may used by the http interface)
    259315    # 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
    291319    if ($req_type eq "bycoord") {
    292320        if (!$skycenter) {
    293321            print STDERR "center must be specified in sky coordintes for bycoord" if $verbose;
    294322            insertFakeJobForRow($row, 1, $PSTAMP_INVALID_REQUEST);
    295             $num_jobs++;
    296             next;
    297         }
    298     }
     323            return 0;
     324        }
     325    }
     326
    299327    if (($req_type eq "byid") or ($req_type eq "bydiff")) {
    300         if (!validID($id)) {
     328        if (!validID($row->{ID})) {
    301329            print STDERR "ID must be a positive integer for req_type $req_type\n" if $verbose;
    302330            insertFakeJobForRow($row, 1, $PSTAMP_INVALID_REQUEST);
     331            return 0
     332        }
     333    }
     334
     335    return 1;
     336}
     337
     338sub 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);
    303354            $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   
    307393    # Call PS::IPP::PStamp::Job locate_images subroutine to get the images for this
    308394    # 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";
    311407
    312408    if (!$imageList or !@$imageList) {
     
    314410        # note in this case queueJobs inserts the fake job for these rows
    315411    }
     412    # handle this
    316413    $row->{need_magic} = $need_magic;
    317     push @rowList, $row;
    318 }
    319 
    320 if (@rowList) {
     414
    321415    $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
     431sub queueJobForImage
    335432{
    336433    my $row = shift;
    337434    my $stage = shift;
    338     my $imageList = shift;
    339     my $have_skycells = shift;
     435    my $image = shift;
    340436    my $need_magic = shift;
    341437    my $mode = shift;
    342438
    343     my $num_jobs = 0;
    344439    my $rownum = $row->{ROWNUM};
    345440    my $option_mask = $row->{OPTION_MASK};
     
    365460    }
    366461
     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
     602sub 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);
     661sub 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
    367681    # loop over images
    368     my $job_num = 0;
    369682    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});
    381693
    382694        my $imagefile = $image->{image};
    383695        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.
    387700            print STDERR "skipping non-magicked image $imagefile\n" if $verbose;
    388 
    389             # for now assume yes.
    390 
    391701            insertFakeJobForRow($row, $job_num, $PSTAMP_NOT_DESTREAKED);
    392702            $num_jobs++;
     
    396706        my $exp_id = $image->{exp_id};
    397707           
    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}";
    440709
    441710        write_params($output_base, $image);
     
    454723                $newState = 'stop';
    455724                $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))) {
    457726                # don't wait for update unless the caller asks us to
    458727                if (!($option_mask & $PSTAMP_WAIT_FOR_UPDATE)) {
     
    463732                    # set up to queue an update run
    464733                    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);
    466735                }
    467736            }
     
    475744        $command .= " -dep_id $dep_id" if $dep_id;
    476745
    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) {
    729747            # mode eq "queue_job"
    730748            my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
     
    776794                        . " -rownum $rownum -state stop -fault $fault";
    777795
    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) {
    783797        # mode eq "queue_job"
    784798        my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
     
    796810}
    797811
    798 sub get_run_id
    799 {
    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 list
    819 sub getOneRun {
    820     my $stage = shift;
    821     my $imageList = shift;
    822 
    823     # return if array is empty
    824     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 
    841812sub same_images_of_interest {
    842813    my $r1 = shift;
    843814    my $r2 = shift;
    844815
    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"));
    848818    return 0 if ($r1->{REQ_TYPE} ne $r2->{REQ_TYPE});
    849819    return 0 if ($r1->{IMG_TYPE} ne $r2->{IMG_TYPE});
    850820    return 0 if ($r1->{ID}       ne $r2->{ID});
    851821    return 0 if ($r1->{TESS_ID}  ne $r2->{TESS_ID});
     822    return 0 if ($r1->{COMPONENT}  ne $r2->{COMPONENT});
    852823    return 0 if ($r1->{REQFILT}  ne $r2->{REQFILT});
    853824    return 0 if ($r1->{DATA_GROUP}    ne $r2->{DATA_GROUP});
    854825    return 0 if ($r1->{MJD_MIN}  ne $r2->{MJD_MAX});
    855826    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});
    856829    return 0 if ($r1->{inverse}  ne $r2->{inverse});
    857830    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));
    868833
    869834    return 1;
     
    911876sub queue_update_run
    912877{
    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) = @_;
    914879
    915880    if (($state ne 'cleaned') and ($state ne 'update') and ($state ne 'goto_cleaned')) {
     
    918883
    919884    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
    922894    if (!$no_update) {
    923895        my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
     
    929901        chomp $output;
    930902        $dep_id = $output;
     903        #
     904        # XXX: need to fault the request or something
    931905        my_die("pstamptool -getdependent returned invalid dep_id", $PS_EXIT_PROG_ERROR) if !$dep_id;
    932906    } else {
     
    936910   
    937911    $$r_dep_id = $dep_id;
    938     $r_fault = 0;
    939     $r_jobState = 'blocked';
     912    $$r_fault = 0;
     913    $$r_jobState = 'run';
    940914}
    941915
     
    990964    # we don't fault the request here pstamp_parser_run.pl handles that if necessary
    991965
    992     return $fault;
    993 }
     966    exit $fault;
     967}
Note: See TracChangeset for help on using the changeset viewer.