IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
May 3, 2010, 8:45:22 AM (16 years ago)
Author:
eugene
Message:

updates from trunk

Location:
branches/simmosaic_branches
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/simmosaic_branches

  • branches/simmosaic_branches/pstamp/scripts/pstampparse.pl

    r24855 r27839  
    1313use PS::IPP::PStamp::RequestFile qw( :standard );
    1414use PS::IPP::PStamp::Job qw( :standard );
     15use File::Temp qw(tempfile);
     16use File::Basename qw(basename);
     17use Carp;
     18use POSIX;
     19use DateTime;
    1520
    1621my $verbose;
     
    2227my $out_dir;
    2328my $product;
     29my $label;
     30my $save_temps;
     31my $no_update;
    2432
    2533GetOptions(
     
    2836    'out_dir=s' =>  \$out_dir,
    2937    'product=s' =>  \$product,
     38    'label=s'   =>  \$label,
    3039    'mode=s'    =>  \$mode,
    3140    'dbname=s'  =>  \$dbname,
    3241    'dbserver=s'=>  \$dbserver,
    3342    'verbose'   =>  \$verbose,
     43    'save-temps'=>  \$save_temps,
     44    'no-update' =>  \$no_update,
    3445);
    3546
    36 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");
    3748die "--file is required"     if !defined($request_file_name);
    3849
     
    6273    exit ($PS_EXIT_CONFIG_ERROR);
    6374}
     75
     76# just deal with these arguments once and for all
     77$pstamptool .= " -dbname $dbname" if $dbname;
     78$pstamptool .= " -dbserver $dbserver" if $dbserver;
     79
     80# list_job is a deugging mode
     81$no_update = 1 if $mode eq "list_job";
    6482
    6583my $mdcParser = PS::IPP::Metadata::Config->new; # Parser for metadata config files
     
    82100
    83101# make sure the file contains what we are expecting
    84 
    85 die "$request_file_name is not a PS1_PS_REQEST" if $extname ne "PS1_PS_REQUEST";
    86 die "REQ_NAME not found in $request_file_name"  if (!$req_name);
    87 die "wrong EXTVER $extver found in $request_file_name" if ($extver ne "1");
    88 
    89 if ($req_id) {
     102# This program shouldn't have been run if the request file is bogus.
     103# No need to notify the client
     104my_die("$request_file_name is not a PS1_PS_REQEST", $PS_EXIT_PROG_ERROR) if $extname ne "PS1_PS_REQUEST";
     105my_die("REQ_NAME not found in $request_file_name", $PS_EXIT_PROG_ERROR)  if (!$req_name);
     106my_die("wrong EXTVER $extver found in $request_file_name", $PS_EXIT_PROG_ERROR) if ($extver ne "1");
     107
     108
     109# check for duplicate request name
     110my $duplicate_req_name = 0;
     111if ($req_id and !$no_update) {
     112    my $command = "$pstamptool -listreq  -name $req_name -not_req_id $req_id";
     113    # no verbose so that error message about request not found doesn't appear in parse_error.txt
     114    my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
     115        run(command => $command, verbose => 0);
     116    my $exitStatus = $error_code >> 8;
     117    if ($success) {
     118        # -listreq succeeded duplicate request name
     119        print STDERR "REQ_NAME $req_name has already been used\n";
     120        insertFakeJobForRow(undef, 0, $PSTAMP_DUP_REQUEST);
     121        $duplicate_req_name = 1;
     122        my $datestr = strftime "%Y%m%d%H%M%S.$req_id", gmtime;
     123        $req_name = "ERROR.$datestr";
     124        #exit 0;
     125    }
     126}
     127
     128if ($req_id and !$no_update) {
     129    # update the database with the request name. This will be used as the
     130    # the output data store's product name
    90131    my $command = "$pstamptool -updatereq -req_id $req_id  -name $req_name";
    91132    $command .= " -outProduct $product";
    92     $command .= " -dbname $dbname" if $dbname;
    93     $command .= " -dbserver $dbserver" if $dbserver;
    94133    my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
    95134        run(command => $command, verbose => $verbose);
    96135    unless ($success) {
    97         die "$command failed";
    98     }
     136        my_die("$command failed", $PS_EXIT_UNKNOWN_ERROR);
     137    }
     138}
     139if ($duplicate_req_name) {
     140    exit 0;
    99141}
    100142
     
    111153        print STDERR @$stderr_buf;
    112154    }
    113     my $table =  $mdcParser->parse(join "", @$stdout_buf) or
    114         die("Unable to parse metdata config doc");
    115 
    116     $rows = parse_md_list($table);
    117 }
    118 
     155    if (@$stdout_buf) {
     156        my $table =  $mdcParser->parse(join "", @$stdout_buf) or
     157            my_die("Unable to parse metdata config doc", $PS_EXIT_UNKNOWN_ERROR);
     158        $rows = parse_md_list($table);
     159    }
     160
     161}
     162
     163#
     164# Loop over rows in the request file collecting consecutive rows that have the "same images of interest"
     165# in the sense that their selection parameters will yield the same "Runs".
     166# Process the groups of rows together to reduce lookup time and to potentially make multiple
     167# stamps from the same ppstamp process.
     168#
     169my @rowList;
    119170my $num_jobs = 0;
     171my $imageList;
     172my $stage;
     173my $need_magic;
    120174foreach my $row (@$rows) {
     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
     178        $num_jobs++;
     179        next;
     180    }
     181    # initialize counter for "job number"
     182    $row->{job_num} = 0;
     183    $row->{error_code} = 0;
     184
     185    if (scalar @rowList == 0) {
     186        push @rowList, $row;
     187        next;
     188    }
     189
     190    my $firstRow = $rowList[0];
     191    if (same_images_of_interest($firstRow, $row)) {
     192        # add this row to the list and move on
     193        push @rowList, $row;
     194        next;
     195    }
     196
     197    # the images of interest for this new row doesn't match the list.
     198    # process the list ...
     199    $num_jobs += processRows(\@rowList);
     200
     201    # and reset the list to contain just the new row
     202    @rowList = ($row);
     203}
     204
     205# out of rows process the list
     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
    121223    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    }
    122229    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   
     236    my $req_type = $row->{REQ_TYPE};
     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
     245    my $component = $row->{COMPONENT};
     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};
     250
     251    my $filter  = $row->{REQFILT};
     252    if ($filter) {
     253        if (length($filter) == 1) {
     254            # allow single character filter cuts to work
     255            $row->{REQFILT} .= '%';
     256        }
     257    }
     258    my $mjd_min = $row->{MJD_MIN};
     259    if (defined($mjd_min) and !validNumber($mjd_min)) {
     260        print STDERR "$mjd_min is not a valid MJD_MIN\n"  if $verbose;
     261        insertFakeJobForRow($row, 1, $PSTAMP_INVALID_REQUEST);
     262        return 0;
     263    }
     264    my $mjd_max = $row->{MJD_MAX};
     265    if (defined($mjd_max) and !validNumber($mjd_max)) {
     266        print STDERR "$mjd_max is not a valid MJD_MAX\n"  if $verbose;
     267        insertFakeJobForRow($row, 1, $PSTAMP_INVALID_REQUEST);
     268        return 0;
     269    }
     270    my $data_group = $row->{DATA_GROUP};
     271    if (!defined $data_group) {
     272        # backwards compatability hook
     273        $data_group = $row->{LABEL};
     274        $data_group = "null" if !defined $data_group;
     275        $row->{DATA_GROUP} = $data_group;
     276    }
     277       
     278    # req_finish doesn't work if bit zero of option mask is not set;
     279    $row->{OPTION_MASK} |= 1;
     280
     281    my $option_mask= $row->{OPTION_MASK};
     282    my $inverse = ($option_mask & $PSTAMP_SELECT_INVERSE) ? 1 : 0;
     283    $row->{inverse} = $inverse;
     284    my $unconvolved = ($option_mask & $PSTAMP_SELECT_UNCONV) ? 1 : 0;
     285    $row->{unconvolved} = $unconvolved;
     286
     287    my $skycenter = $row->{skycenter} = ! ($row->{COORD_MASK} & $PSTAMP_CENTER_IN_PIXELS);
     288
     289    if (!$skycenter and !$component) {
     290        print STDERR "COMPONENT must be specified for pixel coordinate ROI center\n" if $verbose;
     291        insertFakeJobForRow($row, 1, $PSTAMP_INVALID_REQUEST);
     292        return 0;
     293    }
     294
     295    my $stage = $row->{IMG_TYPE};
     296    if (!check_image_type($stage)) {
     297        print STDERR "invalid IMG_TYPE for row $rownum\n" if $verbose;
     298        insertFakeJobForRow($row, 1, $PSTAMP_INVALID_REQUEST);
     299        return 0;
     300    }
     301
     302    if ((($job_type eq "stamp") or ($req_type eq "bycoord")) and ! validROI($row)) {
     303        print STDERR "invalid ROI for row $rownum\n" if $verbose;
     304        insertFakeJobForRow($row, 1, $PSTAMP_INVALID_REQUEST);
     305        return 0;
     306    }
     307
     308    if (($req_type eq "byexp") and ($stage eq "stack")) {
     309        print STDERR "byexp not implemented for stack stage. row: $rownum\n" if $verbose;
     310        insertFakeJobForRow($row, 1, $PSTAMP_NOT_IMPLEMENTED);
     311        return 0;
     312    }
     313
     314    # $mode list_uri is a debugging mode (it may used by the http interface)
     315    # if this happens just croak
     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
     319    if ($req_type eq "bycoord") {
     320        if (!$skycenter) {
     321            print STDERR "center must be specified in sky coordintes for bycoord" if $verbose;
     322            insertFakeJobForRow($row, 1, $PSTAMP_INVALID_REQUEST);
     323            return 0;
     324        }
     325    }
     326
     327    if (($req_type eq "byid") or ($req_type eq "bydiff")) {
     328        if (!validID($row->{ID})) {
     329            print STDERR "ID must be a positive integer for req_type $req_type\n" if $verbose;
     330            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
    123345    my $project  = $row->{PROJECT};
    124     my $req_type = $row->{REQ_TYPE};
    125     my $img_type = $row->{IMG_TYPE};
    126     my $id       = $row->{ID};
    127     my $class_id = $row->{CLASS_ID};
    128     my $filter   = $row->{REQFILT};
    129     my $mjd_min = $row->{MJD_MIN};
    130     my $mjd_max = $row->{MJD_MAX};
     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);
     354            $num_jobs++;
     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   
     393    # Call PS::IPP::PStamp::Job locate_images subroutine to get the images for this
     394    # request specification. An array reference is returned.
     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";
     407
     408    if (!$imageList or !@$imageList) {
     409        print STDERR "no matching images found for row $rownum\n" if $verbose;
     410        # note in this case queueJobs inserts the fake job for these rows
     411    }
     412    # handle this
     413    $row->{need_magic} = $need_magic;
     414
     415    $num_jobs += queueJobs($mode, \@rowList, $imageList);
     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
     432{
     433    my $row = shift;
     434    my $stage = shift;
     435    my $image = shift;
     436    my $need_magic = shift;
     437    my $mode = shift;
     438
     439    my $rownum = $row->{ROWNUM};
     440    my $option_mask = $row->{OPTION_MASK};
     441    my $components = $row->{components};
     442
     443    my $roi_string;
     444
     445    # note values were checked by the function validROI()
    131446    my $x = $row->{CENTER_X};
    132447    my $y = $row->{CENTER_Y};
     
    134449    my $h = $row->{HEIGHT};
    135450    my $coord_mask = $row->{COORD_MASK};
    136     my $option_mask= $row->{OPTION_MASK};
    137 
    138     $class_id = "" if ($class_id eq "null" or $class_id eq "all");
    139    
    140     # XXX: TODO: sanity check all parameters
    141 
    142     # XXX: TODO: We shouldn't just die in this loop.
    143     # If we encounter an error for a particular row
    144     # add a job with the proper fault code. If there is a db or config error we should probably just
    145     # trash the request.
    146     die "job_type is list_uri but mode is $mode" if ($job_type eq "list_uri") and ($mode ne "list_uri");
    147 
    148     my $proj_hash = resolve_project($ipprc, $project, $dbname, $dbserver);
    149     die "project $project not found\n" unless $proj_hash;
    150 
    151     my $image_db = $proj_hash->{dbname};
    152     my $camera = $proj_hash->{camera};
    153     my $need_magic = $proj_hash->{need_magic};
    154 
    155     my $roi_string;
    156     # XXX we're depending on other code to insure valid values for roi components
    157     # this is checked in and ppstamp but I should check here so that we don't get that far,
    158     # but not today
    159     if ($x && ($x ne "null") && $y && ($y ne "null") && $w && ($w ne "null") && $h && ($h ne "null")) {
    160         if ($coord_mask & $PSTAMP_CENTER_IN_PIXELS) {
    161             $roi_string = "-pixcenter $x $y";
    162         } else {
    163             $roi_string = "-skycenter $x $y";
    164         }
    165         if ($coord_mask & $PSTAMP_RANGE_IN_PIXELS) {
    166             $roi_string .= " -pixrange $w $h";
    167         } else {
    168             $roi_string .= " -arcrange $w $h";
    169         }
    170     }
    171 
    172     die "region of interest is required to make postage stamps"
    173         if (($job_type eq "stamp") && !defined($roi_string));
    174 
    175     # find the uris for this request
    176 
    177     if ($req_type eq "bycoord") {
    178         die "region of interest is required for request type bycoord" if !defined($roi_string) ;
    179         die "center must be specified in sky coordintes for bycoord"
    180             if ($coord_mask & $PSTAMP_CENTER_IN_PIXELS);
    181     }
    182 
    183     # Call PS::IPP::PStamp::Job's locate_images routine to get the parameters for this request specification
    184     my $images = locate_images($ipprc, $image_db, $req_type, $img_type, $id, $class_id,
    185             $x, $y, $mjd_min, $mjd_max, $filter, $verbose);
    186 
    187     if (!$images) {
    188         print STDERR "no matching images found for row $rownum\n";
    189         next;
    190     }
     451    if ($coord_mask & $PSTAMP_CENTER_IN_PIXELS) {
     452        $roi_string = "-pixcenter $x $y";
     453    } else {
     454        $roi_string = "-skycenter $x $y";
     455    }
     456    if ($coord_mask & $PSTAMP_RANGE_IN_PIXELS) {
     457        $roi_string .= " -pixrange $w $h";
     458    } else {
     459        $roi_string .= " -arcrange $w $h";
     460    }
     461
     462    my $component = $image->{component};
     463
     464    my $job_num = ++($row->{job_num});
     465
     466    my $imagefile = $image->{image};
     467    if (($stage ne "stack") and ($need_magic and !$image->{magicked})) {
     468        # XXX: should we add a faulted job so the client can know what happened if no images come back?
     469        # The test for destreaked is made in locate_images now so this code never runs. This leads to no feedback
     470        # to users, but speeds up processing significantly
     471        print STDERR "skipping non-magicked image $imagefile\n" if $verbose;
     472
     473        # for now assume yes.
     474
     475        insertFakeJobForRow($row, $job_num, $PSTAMP_NOT_DESTREAKED);
     476        return 1;
     477    } elsif ($stage eq "stack") {
     478        # unconvolved stack images weren't available prior to some point in time.
     479        # XXX: handle this more correctly by examining the stack run's config dump file.
     480        # It looks like # the feature was turned on sometime around November 11, 2009. stackRun 30067 is the lowest
     481        # one that I found with an unconvolved image.
     482        my $MIN_GPC1_STACK_ID_WITH_UNCONVOLVED_IMAGES = 30067;
     483        if ($row->{unconvolved} and ($row->{PROJECT} eq 'gpc1') and
     484            ($image->{stack_id} < $MIN_GPC1_STACK_ID_WITH_UNCONVOLVED_IMAGES)) {
     485            print STDERR "Unconvolved stack image is not available for stackRun.stack_id: $image->{stack_id}\n";
     486            insertFakeJobForRow($row, $job_num, $PSTAMP_NOT_AVAILABLE);
     487            return 1;
     488        }
     489    }
     490    my $exp_id = $image->{exp_id};
     491           
     492    my $args = $roi_string ? $roi_string : "";
     493    if ($stage eq "raw" or $stage eq "chip") {
     494        $args .= " -class_id $component" if $component;
     495    }
     496
     497    # add astrometry file for raw and chip images if one is available
     498    if (($stage eq "chip") || ($stage eq "raw")) {
     499        $args .= " -astrom $image->{astrom}" if $image->{astrom};
     500    }
     501
     502    $image->{job_args} = $args;
     503
     504    # XXX: we can get rid of the following everything that we need is
     505    # in the params file
     506
     507    $args .= " -file $imagefile";
     508
     509    if (($option_mask & $PSTAMP_SELECT_MASK) &&  $image->{mask} ) {
     510        $args .= " -mask $image->{mask}";
     511    }
     512    if (($option_mask & $PSTAMP_SELECT_WEIGHT) and $image->{weight} ) {
     513        $args .= " -variance $image->{weight}";
     514    }
     515
     516    my $base = basename($image->{image});
     517    if (! $base =~ /.fits$/ ) {
     518        my_die("unexpected image file name found $image->{image}", $PS_EXIT_PROG_ERROR);
     519    }
     520    $base =~ s/.fits$//;
     521           
     522    my $output_base = "$out_dir/${rownum}_${job_num}_${base}";
     523    my $argslist = "${output_base}.args";
     524
     525    # copy the argument list to a file
     526    open ARGSLIST, ">$argslist" or my_die("failed to open $argslist", $PS_EXIT_UNKNOWN_ERROR);
     527    print ARGSLIST "$args\n";
     528    close ARGSLIST or my_die("failed to close $argslist", $PS_EXIT_UNKNOWN_ERROR);
     529
     530    write_params($output_base, $image);
     531
     532    my $newState = "run";
     533    my $fault = 0;
     534    my $dep_id;
     535
     536    # XXX: this code is repeated in queueGetImageJobs we should encapsulate it in a subroutine and share it
     537    if ($stage ne 'raw') {
     538        # updates for stack stage not supported yet
     539        my $allow_wait_for_update = ($stage ne 'stack');
     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 (($data_state ne 'full') or ($need_magic and ($image->{magicked} < 0))) {
     551            if ($stage eq 'chip') {
     552                my $burntool_state = $image->{burntool_state};
     553                if ($burntool_state and (abs($burntool_state) < 14)) {
     554                    $newState = 'stop';
     555                    $fault = $PSTAMP_NOT_AVAILABLE;
     556                }
     557            }
     558            if (!$allow_wait_for_update) {
     559                print STDERR "wait for update not supported for stage $stage yet\n";
     560                $newState = 'stop';
     561                $fault = $PSTAMP_NOT_AVAILABLE;
     562            }
     563            if (!$fault) {
     564                # wait for update unless the customer asks us not to
     565                if (($option_mask & $PSTAMP_NO_WAIT_FOR_UPDATE)) {
     566                    $newState = 'stop';
     567                    $fault = $PSTAMP_NOT_AVAILABLE;
     568                } elsif (!$image->{magicked}) {
     569                    $newState = 'stop';
     570                    $fault = $PSTAMP_NOT_DESTREAKED;
     571                } else {
     572                    # cause the image to be re-made
     573                    # set up to queue an update run
     574                    queue_update_run(\$newState, \$fault, \$dep_id, $image->{imagedb},
     575                        $run_state, $stage, $image->{stage_id}, $image->{component}, $need_magic);
     576                }
     577            }
     578        }
     579    }
     580
     581    my $command = "$pstamptool -addjob  -req_id $req_id -job_type $row->{JOB_TYPE}"
     582                    . " -outputBase $output_base -rownum $rownum -state $newState -options $option_mask";
     583    $command .= " -fault $fault" if $fault;
     584    $command .= " -exp_id $exp_id" if $exp_id;
     585    $command .= " -dep_id $dep_id" if $dep_id;
     586
     587    if (!$no_update) {
     588        # mode eq "queue_job"
     589        my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
     590            run(command => $command, verbose => $verbose);
     591        unless ($success) {
     592            print STDERR @$stderr_buf;
     593            # XXX TODO: now what? Should we mark the error state for the request?
     594            # should we keep going for other uris? If so how do we report that some
     595            # of the work that the request wanted isn't going to get done
     596            my_die("failed to queue job for request $req_id", $PS_EXIT_UNKNOWN_ERROR);
     597        }
     598    } else {
     599        print "skipping command: $command\n";
     600    }
     601
     602    return 1;
     603}
     604
     605# queue jobs for a collection of request specifications that have the same Images of Interest
     606sub queueJobs
     607{
     608    my $mode = shift;
     609    my $rowList = shift;
     610    my $imageList = shift;
     611
     612    my $firstRow = $rowList[0];
     613    my $stage    = $firstRow->{IMG_TYPE};
     614    my $job_type = $firstRow->{JOB_TYPE};
     615    my $need_magic = $firstRow->{need_magic};
     616
     617    my $num_jobs = 0;
     618
    191619    if ($mode eq "list_uri") {
    192         foreach my $image (@$images) {
     620        foreach my $image (@$imageList) {
    193621            print "$image->{image}\n";
    194622        }
    195623    } elsif ($job_type eq "get_image") {
    196         # XXX TODO: Get rid of this block and use the same code as the stamp jobs
    197         # XXX This doesn't work to get the mask and weight images
    198         my $listfile = "$out_dir/filelist";
    199 
    200 
    201         # map our img_type to the Data Store file types.
    202         my %filelist_img_types = ( "raw" => "chip",
    203                                    "chip" => "chipproc",
    204                                    "warp" => "warp",
    205                                    "stack"=>"stack",
    206                                    "diff" => "diff");
    207 
    208         my $filelist_img_type = $filelist_img_types{$img_type};
    209 
    210         open LISTFILE, ">$listfile"
    211             or die "failed to open file list: $listfile while parsing get_image request $req_id";
    212 
    213         foreach my $image (@$images) {
    214             my $class_id = $image->{class_id} ? $image->{class_id} : "";
    215             print LISTFILE "$image->{image}|$filelist_img_type|$class_id|\n";
    216         }
    217         close LISTFILE;
     624        my $n = scalar @$rowList;
     625
     626        my_die( "error: unexpected number of rows for get_image request: $n", $PS_EXIT_PROG_ERROR) if $n != 1;
     627
     628        $num_jobs = queueGetImageJobs($firstRow, $imageList, $stage, $need_magic, $mode);
     629
     630    } else {
     631        if (!$imageList or (scalar @$imageList eq 0)) {
     632            # We didn't find any images for this set of rows. Insert a fake job to carry
     633            # the status back to the requestor.
     634            foreach my $row (@$rowList) {
     635                my $error_code = $row->{error_code};
     636                $error_code = $PSTAMP_NO_IMAGE_MATCH if !$error_code;
     637                insertFakeJobForRow($row, ++$row->{job_num}, $error_code);
     638                $num_jobs++;
     639            }
     640            return $num_jobs;
     641        }
     642
     643        foreach my $image (@$imageList) {
     644            # get the array of row indices that touch this image
     645            my $row_index = $image->{row_index};
     646            if (!$row_index or scalar @$row_index == 0) {
     647                # XXX should this happen? Why did something get returned.
     648                print "image ${stage}_id: $image->{stage_id} component: $image->{component} matched no rows\n";
     649                next;
     650            }
     651            # XXX: TODO: eventually we may change ppstamp to be able to make multiple stamps per invocation
     652
     653            foreach my $i (@$row_index) {
     654                my $row = $rowList->[$i];
     655
     656                $num_jobs += queueJobForImage($row, $stage, $image, $need_magic, $mode);
     657            }
     658        }
     659    }
     660
     661    return $num_jobs;
     662}
     663
     664#        $num_jobs = queueGetImageJobs($firstRow, $imageList, $stage, $need_magic, $mode);
     665sub queueGetImageJobs
     666{
     667    my $row = shift;
     668    my $imageList = shift;
     669    my $stage = shift;
     670    my $need_magic = shift;
     671    my $mode = shift;
     672
     673    my $num_jobs = 0;
     674    my $rownum = $row->{ROWNUM};
     675    my $option_mask = $row->{OPTION_MASK};
     676
     677    # For dist_bundle we need
     678    #  --camera from $image
     679    #  --stage
     680    #  --stage_id from $image
     681    #  --component from $image
     682    #  --path_base
     683    #  --outdir global to this script
     684
     685    # loop over images
     686    foreach my $image (@$imageList) {
     687        my $stage_id = $image->{stage_id};
     688        my $component = $image->{component};
     689
     690        # skip faulted components for now. Should we even be here?
     691        if ($image->{fault} > 0) {
     692            printf STDERR "skipping faulted component for $stage $stage_id $component\n" if $verbose;
     693            next;
     694        }
     695
     696        my $job_num = ++($row->{job_num});
     697
     698        my $imagefile = $image->{image};
     699        if (($stage ne "stack") and ($need_magic and !$image->{magicked})) {
     700            # we only get here if req_type is (byid or byexp). For other types the test for magicked is performed
     701            # in locate_images because it's much more efficient to do the test in the database.
     702            # For these two modes we fall through to here in order to give feedback to the requestor as
     703            # to why the request failed to queue jobs.
     704            print STDERR "skipping non-magicked image $imagefile\n" if $verbose;
     705            insertFakeJobForRow($row, $job_num, $PSTAMP_NOT_DESTREAKED);
     706            $num_jobs++;
     707
     708            next;
     709        }
     710        my $exp_id = $image->{exp_id};
     711           
     712        my $output_base = "$out_dir/${rownum}_${job_num}";
     713
     714        write_params($output_base, $image);
     715
     716        my $newState = "run";
     717        my $fault = 0;
     718        my $dep_id;
     719
     720        if ($stage ne 'raw') {
     721            my $run_state = $image->{state};
     722            my $data_state = $image->{data_state};
     723            $data_state = $run_state if $stage eq "stack";
     724            if (($run_state eq 'goto_purged') or ($data_state eq 'purged') or
     725                ($run_state eq 'goto_scrubbed') or ($data_state eq 'scrubbed')) {
     726                # image is gone and it's not coming back
     727                $newState = 'stop';
     728                $fault = $PSTAMP_GONE;
     729            } elsif (($data_state ne 'full') or ($need_magic and ($image->{magicked} < 0))) {
     730                # wait for update unless the customer asks us to not to
     731                if ($option_mask & $PSTAMP_NO_WAIT_FOR_UPDATE) {
     732                    $newState = 'stop';
     733                    $fault = $PSTAMP_NOT_AVAILABLE;
     734                } else {
     735                    # cause the image to be re-made
     736                    # set up to queue an update run
     737                    queue_update_run(\$newState, \$fault, \$dep_id, $image->{image_db},
     738                        $run_state, $stage, $image->{stage_id}, $image->{component}, $need_magic);
     739                }
     740            }
     741        }
     742
    218743        $num_jobs++;
    219         my $command = "$pstamptool -addjob -req_id $req_id -job_type get_image"
    220                     . " -uri $listfile -outputBase $out_dir -rownum $rownum";
    221         $command .= " -dbname $dbname" if $dbname;
    222         $command .= " -dbserver $dbserver" if $dbserver;
    223         if ($mode eq "list_job") {
    224             print "$command\n";
    225         } else {
     744        my $command = "$pstamptool -addjob  -req_id $req_id -job_type $row->{JOB_TYPE}"
     745                        . " -outputBase $output_base -rownum $rownum -state $newState -options $option_mask";
     746        $command .= " -fault $fault" if $fault;
     747        $command .= " -exp_id $exp_id" if $exp_id;
     748        $command .= " -dep_id $dep_id" if $dep_id;
     749
     750        if (!$no_update) {
     751            # mode eq "queue_job"
    226752            my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
    227753                run(command => $command, verbose => $verbose);
     
    229755                print STDERR @$stderr_buf;
    230756                # XXX TODO: now what? Should we mark the error state for the request?
    231                 die "failed to queue job for request $req_id: rownum: $rownum";
     757                # should we keep going for other uris? If so how do we report that some
     758                # of the work that the request wanted isn't going to get done
     759                my_die("failed to queue job for request $req_id", $PS_EXIT_UNKNOWN_ERROR);
    232760            }
     761        } else {
     762            print "skipping command: $command\n";
     763        }
     764    }
     765    if ( $num_jobs == 0 ) {
     766        print STDERR "no jobs for row $rownum\n" if $verbose;
     767        insertFakeJobForRow($row, 1, $PSTAMP_NO_JOBS_QUEUED);
     768        $num_jobs = 1;
     769    }
     770    return $num_jobs;
     771}
     772sub insertFakeJobForRow
     773{
     774    my $row = shift;
     775    my $job_num = shift;
     776    my $fault = shift;
     777
     778    my ($job_type, $rownum);
     779    if ($row) {
     780        $job_type = $row->{JOB_TYPE};
     781        $rownum = $row->{ROWNUM};
     782        $rownum = 0 if !defined $rownum;
     783        if ($job_type) {
     784            if (($job_type ne "stamp") and ($job_type ne "get_image")) {
     785                print STDERR "invalid job type: $job_type found in row $rownum\n";
     786                $job_type = "none";
     787            }
     788        } else {
     789            print STDERR "undefined job type found in row $rownum\n";
     790            $job_type = "none";
    233791        }
    234792    } else {
    235         # sequence number for the the job for a request spec. Not to be confused with job_id
    236         my $job_num = 0;
    237 
    238         # XXX TODO: for raw and chip level images and class_id "null" if there are multiple images
    239         # use -list instead of -file
    240         foreach my $image (@$images) {
    241             my $uri = $image->{image};
    242             if (($img_type ne "stack") and ($need_magic and !$image->{magicked})) {
    243                 print STDERR "skippping non-magicked image $uri\n" if $verbose;
    244                 next;
    245             }
    246             my $exp_id = $image->{exp_id};
    247            
    248             my $args = $roi_string ? $roi_string : "";
    249             $args .= " -class_id $class_id" if $class_id;
    250 
    251             $job_num++;
    252 
    253             my $output_base = "$out_dir/${rownum}_${job_num}";
    254 
    255             # add astrometry file for raw and chip images if one is available
    256             if (($img_type eq "chip") || ($img_type eq "raw")) {
    257                 $args .= " -astrom $image->{astrom}" if $image->{astrom};
    258             }
    259 
    260             if (($option_mask & $PSTAMP_SELECT_MASK) &&  $image->{mask} ) {
    261                 $args .= " -mask $image->{mask}";
    262             }
    263             if (($option_mask & $PSTAMP_SELECT_WEIGHT) and $image->{weight} ) {
    264                 $args .= " -weight $image->{weight}";
    265             }
    266 
    267             # XXX: TODO: here is where we need to check whether or not the source inputs still exist
    268             # and if not, queue an update job and set the job state appropriately.
    269 
    270             my $newState = "run";
    271 
    272             $num_jobs++;
    273             my $command = "$pstamptool -addjob -req_id $req_id -job_type $job_type"
    274                 . " -uri $uri -outputBase $output_base -args '$args' -rownum $rownum"
    275                 . " -state $newState";
    276             $command .= " -exp_id $exp_id" if $exp_id;
    277             $command .= " -dbname $dbname" if $dbname;
    278             $command .= " -dbserver $dbserver" if $dbserver;
    279 
    280             if ($mode eq "list_job") {
    281                 # this is a debugging mode, just print the pstamptool that would have run
    282                 # this is sort of like the mode -noupdate that some other tools support
    283                 print "$command\n";
    284             } else {
    285                 # mode eq "queue_job"
    286                 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
    287                     run(command => $command, verbose => $verbose);
    288                 unless ($success) {
    289                     print STDERR @$stderr_buf;
    290                     # XXX TODO: now what? Should we mark the error state for the request?
    291                     # should we keep going for other uris? If so how do we report that some
    292                     # of the work that the request wanted isn't going to get done
    293                     die "failed to queue job for request $req_id";
    294                 }
    295             }
    296         }
    297     }
    298 }
    299 
    300 if ($mode eq "queue_jobs") {
    301     if ($num_jobs) {
    302         exit 0;
     793        $job_type = "none";
     794        $rownum = 0;
     795    }
     796
     797    my $command = "$pstamptool -addjob  -req_id $req_id -job_type $job_type"
     798                        . " -rownum $rownum -state stop -fault $fault";
     799
     800    if (!$no_update) {
     801        # mode eq "queue_job"
     802        my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
     803            run(command => $command, verbose => $verbose);
     804        unless ($success) {
     805            print STDERR @$stderr_buf;
     806            # XXX TODO: now what? Should we mark the error state for the request?
     807            # should we keep going for other uris? If so how do we report that some
     808            # of the work that the request wanted isn't going to get done
     809            my_die("failed to queue job for request $req_id", $PS_EXIT_UNKNOWN_ERROR);
     810        }
    303811    } else {
    304         # no jobs queued return error to get the request stopped
    305         # TODO: need to define meaningful error codes
    306         exit $PS_EXIT_UNKNOWN_ERROR;
    307     }
    308 } else {
    309     exit 0;
    310 }
     812        print "skipping command: $command\n";
     813    }
     814}
     815
     816sub same_images_of_interest {
     817    my $r1 = shift;
     818    my $r2 = shift;
     819
     820    return 0 if (($r1->{REQ_TYPE} eq "bycoord")   or ($r2->{REQ_TYPE} eq "bycoord"));
     821    return 0 if (($r1->{JOB_TYPE} eq "get_image") or ($r2->{JOB_TYPE} eq "get_image"));
     822    return 0 if ($r1->{REQ_TYPE} ne $r2->{REQ_TYPE});
     823    return 0 if ($r1->{IMG_TYPE} ne $r2->{IMG_TYPE});
     824    return 0 if ($r1->{ID}       ne $r2->{ID});
     825    return 0 if ($r1->{TESS_ID}  ne $r2->{TESS_ID});
     826    return 0 if ($r1->{COMPONENT}  ne $r2->{COMPONENT});
     827    return 0 if ($r1->{REQFILT}  ne $r2->{REQFILT});
     828    return 0 if ($r1->{DATA_GROUP}    ne $r2->{DATA_GROUP});
     829    return 0 if ($r1->{MJD_MIN}  ne $r2->{MJD_MAX});
     830    return 0 if ($r1->{MJD_MAX}  ne $r2->{MJD_MAX});
     831    return 0 if ($r1->{OPTION_MASK}  ne $r2->{OPTION_MASK});
     832    return 0 if ($r1->{PROJECT}  ne $r2->{PROJECT});
     833    return 0 if ($r1->{inverse}  ne $r2->{inverse});
     834    return 0 if ($r1->{unconvolved}  ne $r2->{unconvolved});
     835    # don't combine requests in pixel coordinates
     836    return 0 if (($r1->{COORD_MASK} & $PSTAMP_CENTER_IN_PIXELS) || ($r2->{COORD_MASK} & $PSTAMP_CENTER_IN_PIXELS));
     837
     838    return 1;
     839}
     840
     841sub validNumber
     842{
     843    my $val = shift;
     844
     845    return 0 if !defined $val;
     846
     847    return ($val =~ /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/);
     848}
     849sub validID
     850{
     851    my $val = shift;
     852
     853    return 0 if !$val;
     854
     855    return  ! ($val =~ /\D/);
     856}
     857
     858sub validROI
     859{
     860    my $row = shift;
     861    return 0 if !validNumber($row->{CENTER_X});
     862    return 0 if !validNumber($row->{CENTER_Y});
     863    return 0 if !validNumber($row->{WIDTH});
     864    return 0 if !validNumber($row->{HEIGHT});
     865
     866    return 1;
     867}
     868
     869sub findRow
     870{
     871    my $rownum = shift;
     872    my $rowList = shift;
     873
     874    foreach my $row (@$rowList) {
     875        return $row if $row->{ROWNUM} eq $rownum;
     876    }
     877    return undef;
     878}
     879
     880sub queue_update_run
     881{
     882    my ($r_jobState, $r_fault, $r_dep_id, $imagedb, $state, $stage, $stage_id, $component, $need_magic) = @_;
     883
     884    if (($state ne 'cleaned') and ($state ne 'update') and ($state ne 'goto_cleaned')) {
     885        my_die("$stage $stage_id is in unexpected state $state", $PS_EXIT_PROG_ERROR);
     886    }
     887
     888    my $dep_id;
     889    my $command = "$pstamptool -getdependent -stage $stage -stage_id $stage_id -imagedb $imagedb -component $component";
     890    $command .= " -need_magic" if $need_magic;
     891
     892    # compute rlabel for the run.
     893    # XXX: This bit of policy shouldn't be buried so deeply in the code
     894    # For now use one that implies 'postage stamp server' 'update' 'request_label"
     895    my $rlabel = "ps_ud_" . $label if $label;
     896    $command .= " -rlabel $rlabel" if $rlabel;
     897
     898    if (!$no_update) {
     899        my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
     900            run(command => $command, verbose => $verbose);
     901        unless ($success) {
     902            my_die("$command failed", $PS_EXIT_UNKNOWN_ERROR);
     903        }
     904        my $output = join "", @$stdout_buf;
     905        chomp $output;
     906        $dep_id = $output;
     907        #
     908        # XXX: need to fault the request or something
     909        my_die("pstamptool -getdependent returned invalid dep_id", $PS_EXIT_PROG_ERROR) if !$dep_id;
     910    } else {
     911        print STDERR "skipping $command\n";
     912        $dep_id = 42;
     913    }
     914   
     915    $$r_dep_id = $dep_id;
     916    $$r_fault = 0;
     917    $$r_jobState = 'run';
     918}
     919
     920sub write_params {
     921    my $output_base = shift;
     922    my $image = shift;
     923
     924    # write the contents of this "image" as a metadata config doc
     925    # Simply treat all values as strings. This is ok since we are only going to
     926    # read it from another perl script
     927    my $mdc_file = "${output_base}.mdc";
     928    open P, ">$mdc_file" or my_die("failed to open $mdc_file", $PS_EXIT_UNKNOWN_ERROR);
     929
     930    print P "params METADATA\n";
     931
     932    foreach my $key (keys %$image) {
     933        my $value = $image->{$key};
     934        if (defined $value) {
     935            printf P "  %-20s STR     %s\n", $key, $value;
     936        } else {
     937            printf P "  %-20s STR     NULL\n", $key;
     938        }
     939    }
     940
     941    print P "END\n";
     942    close P or my_die("failed to close $mdc_file", $PS_EXIT_UNKNOWN_ERROR);
     943}
     944
     945sub check_image_type
     946{
     947    my $img_type = shift;
     948    if (!$img_type) {
     949            print STDERR "NULL IMG_TYPE supplied\n";
     950            return 0;
     951    }
     952    if (($img_type eq "raw") or ($img_type eq "chip") or ($img_type eq "warp") or
     953        ($img_type eq "stack") or ($img_type eq "diff")) {
     954        return 1;
     955    } else {
     956        print STDERR "$img_type is not a valid IMG_TYPE\n";
     957        return 0;
     958    }
     959}
     960
     961sub my_die
     962{
     963    my $msg = shift;
     964    my $fault = shift;
     965
     966    carp $msg;
     967
     968    # we don't fault the request here pstamp_parser_run.pl handles that if necessary
     969
     970    exit $fault;
     971}
Note: See TracChangeset for help on using the changeset viewer.