IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 27751


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.

Location:
trunk
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/PS-IPP-PStamp/lib/PS/IPP/PStamp/Job.pm

    r27589 r27751  
    2727use PS::IPP::Config qw( :standard );
    2828use Carp;
     29use DateTime;
     30use File::Temp qw(tempfile);
     31use File::Basename;
     32use POSIX;
     33
     34my $save_temps = 0;
    2935
    3036# caches of camProcessedExp objects.
     
    3440my %camRunByCamIDCache;
    3541
    36 ### my @images = locate_images($image_db, $req_type, $img_type, $id, $component,
    37 ###            $mjd_min, $mjd_max, $filter);
     42# cache of last project looked up
     43my $last_project = "";
     44
     45my ($regtool, $chiptool, $camtool, $warptool, $stacktool, $difftool);
     46my ($pstamptool, $dvoImagesAtCoords, $whichimage, $ppConfigDump);
    3847
    3948sub locate_images {
    4049    my $ipprc    = shift;   # required
    41     my $image_db = shift;   # required
     50    my $imagedb = shift;   # required
     51    my $rowList  = shift;   # required
    4252    my $req_type = shift;   # required
    4353    my $img_type = shift;   # required
     
    4757    my $option_mask  = shift;
    4858    my $need_magic = shift;
    49     my $x        = shift;
    50     my $y        = shift;
    5159    my $mjd_min  = shift;
    5260    my $mjd_max  = shift;
     
    5664
    5765    # we die in response to bad data in request files
    58     # The wrapper script is responsible for updating the database
    59     die "Unknown req_type: $req_type"
     66    # The caller is responsible for updating the database
     67    # pstampparse.pl error checks now so this shouldn't happen
     68    &my_die("Unknown req_type: $req_type", $PS_EXIT_PROG_ERROR)
    6069        if ($req_type ne "byid") and
    6170           ($req_type ne "byexp") and
     
    8493
    8594    if ($req_type eq "bycoord") {
    86         my $results = lookup_bycoord($ipprc, $image_db, $img_type, $tess_id, $component, $need_magic, $x, $y, $dateobs_begin, $dateobs_end, $filter, $data_group, $option_mask, $verbose);
     95        my $num_rows = scalar @$rowList;
     96        die "Unexpected number of rows found in rowList: $num_rows" if $num_rows != 1;
     97        my $row = $rowList->[0];
     98        my $x = $row->{CENTER_X};
     99        my $y = $row->{CENTER_Y};
     100        my $results = lookup_bycoord($ipprc, $rowList, $imagedb, $img_type, $tess_id, $component, $need_magic, $x, $y, $dateobs_begin, $dateobs_end, $filter, $data_group, $option_mask, $verbose);
    87101        return $results;
    88102    }
     
    93107        # in one place
    94108        $req_type = "bydiff";
    95         my $results = lookup_diff($ipprc, $image_db, $id, $component, 1, $option_mask, $img_type, $verbose);
     109        my $results = lookup_diff($ipprc, $rowList, $imagedb, $id, $component, 1, $option_mask, $img_type, $verbose);
    96110        return $results;
    97111    }
    98112
    99113    if ($req_type eq "bydiff") {
    100         my $results = lookup_diff($ipprc, $image_db, $id, $component, 0, $option_mask, $img_type, $verbose);
     114        # for bydiff reuqests we go look up the diffRun to obtain exp_id, chip_id, warp_id, stack_id, or
     115        # the image from the diffRun
     116        my $results = lookup_diff($ipprc, $rowList, $imagedb, $id, $component, 0, $option_mask, $img_type, $verbose);
    101117        if (!$results) {
    102118            return undef;
     
    130146            # fall though and lookup by stack_id
    131147        } else {
    132             # shouldn't I check this elsewhere?
     148            # This is checked this elsewhere?
    133149            print STDERR "Error: $img_type is an unknown image type\n";
    134150            return undef;
     
    145161    }
    146162
    147     my $results = lookup($ipprc, $image_db, $req_type, $img_type, $id, $tess_id, $component, $need_magic,
    148         $dateobs_begin, $dateobs_end, $filter, $data_group, $option_mask, $verbose);
     163    my $results = lookup($ipprc, $rowList, $imagedb, $req_type, $img_type, $id, $tess_id, $component,
     164        $need_magic, $dateobs_begin, $dateobs_end, $filter, $data_group, $option_mask, $verbose);
    149165
    150166    return $results;
    151167}
     168
     169# The subroutine lookup handles byexp, byid, and byskycell lookups including lookups that are
     170# triggered by a bydiff request
    152171
    153172sub lookup
    154173{
    155174    my $ipprc    = shift;
    156     my $image_db = shift;
     175    my $rowList    = shift;
     176    my $imagedb = shift;
    157177    my $req_type = shift;
    158     my $img_type = shift;
     178    my $stage = shift;
    159179    my $id       = shift;
    160180    my $tess_id  = shift;
     
    172192    my $use_imfile_id = ($req_type eq "byid") && ($option_mask & $PSTAMP_USE_IMFILE_ID);
    173193
    174     my $missing_tools;
    175     my $regtool = can_run('regtool') or (warn "Can't find regtool" and $missing_tools = 1);
    176     my $chiptool = can_run('chiptool') or (warn "Can't find chiptool" and $missing_tools = 1);
    177     my $warptool = can_run('warptool') or (warn "Can't find warptool" and $missing_tools = 1);
    178     my $difftool = can_run('difftool') or (warn "Can't find difftool" and $missing_tools = 1);
    179     my $stacktool = can_run('stacktool') or (warn "Can't find stacktool" and $missing_tools = 1);
    180     if ($missing_tools) {
    181         warn("Can't find required tools.");
    182         exit ($PS_EXIT_CONFIG_ERROR);
    183     }
    184194    my $command;
    185195    my $id_opt;     # option for the lookup
     
    203213    my $magic_arg = $need_magic ? " -destreaked" : "";
    204214
     215    # all rows have the same center type
     216    my $skycenter = ! ($rowList->[0]->{COORD_MASK} & $PSTAMP_CENTER_IN_PIXELS);
     217
    205218    my $component_args;
    206     if ($img_type eq "raw") {
     219    my $choose_components = 0;
     220    if ($stage eq "raw") {
    207221        $class_id = $component;
    208         $command = "$regtool -processedimfile -dbname $image_db";
     222        $command = "$regtool -processedimfile -dbname $imagedb";
    209223        # XXX: for now restrict lookups to type object
    210224        # are stamps of detrend exposures interesting?
     
    214228        $want_astrom = 1;
    215229        $set_class_id = 1;
    216     } elsif ($img_type eq "chip") {
     230    } elsif ($stage eq "chip") {
    217231        $class_id = $component;
    218         $command = "$chiptool -processedimfile -dbname $image_db";
    219         $component_args = " -class_id $class_id" if $class_id;
     232        # if the request is such that it will yield a single image per "run" or the
     233        # center is specified in pixel coordinates
     234        # use chiptool -processsedimfile. Otherwise use chiptool -listrun and then
     235        # choose the chips containing the center pixel by calling selectComponets() below
     236        if ($class_id or $use_imfile_id or !$skycenter) {
     237            $command = "$chiptool -processedimfile -dbname $imagedb";
     238            $component_args = " -class_id $class_id" if $class_id;
     239        } else {
     240            $command = "$chiptool -listrun -pstamp_order -dbname $imagedb";
     241            $choose_components = 1;
     242        }
    220243        $id_opt = $use_imfile_id ? "-chip_imfile_id" : "-chip_id";
     244        # XXX: perhaps we should stop resolving images to this level here and do it at job run time.
     245        # With the mdc file it has all of the information that it needs.
    221246        $image_name   = "PPIMAGE.CHIP";
    222247        $mask_name    = "PPIMAGE.CHIP.MASK";
     
    228253        $want_astrom  = 1;
    229254        $set_class_id = 1;
    230     } elsif ($img_type eq "warp") {
     255    } elsif ($stage eq "warp") {
    231256        $skycell_id = $component;
    232         $command = "$warptool -warped -dbname $image_db";
    233         $component_args = " -skycell_id $skycell_id" if $skycell_id;
     257        if ($skycell_id or $use_imfile_id or !$skycenter) {
     258            $command = "$warptool -warped -dbname $imagedb";
     259            $component_args = " -skycell_id $skycell_id" if $skycell_id;
     260        } else {
     261            $command = "$warptool -listrun -pstamp_order -dbname $imagedb";
     262            $choose_components = 1;
     263        }
    234264        $id_opt = $use_imfile_id ? "-warp_skyfile_id" : "-warp_id";
    235265        $image_name   = "PSWARP.OUTPUT";
     
    239269        $psf_name     = "PSPHOT.PSF.SKY.SAVE";
    240270        $base_name    = "path_base"; # name of the field for the warptool output
    241     } elsif ($img_type eq "diff") {
     271    } elsif ($stage eq "diff") {
    242272        $skycell_id = $component;
    243         $command = "$difftool -diffskyfile -dbname $image_db";
    244         $component_args = " -skycell_id $skycell_id" if $skycell_id;
     273        if ($skycell_id or $use_imfile_id or !$skycenter) {
     274            $command = "$difftool -diffskyfile -dbname $imagedb";
     275            $component_args = " -skycell_id $skycell_id" if $skycell_id;
     276        } else {
     277            $command = "$difftool -listrun -pstamp_order -dbname $imagedb";
     278            $choose_components = 1;
     279        }
    245280        $id_opt = $use_imfile_id ? "-diff_skyfile_id" : "-diff_id";
    246281        $image_name  = "PPSUB.OUTPUT";
     
    250285        $psf_name     = "PSPHOT.PSF.SKY.SAVE";
    251286        $base_name   = "path_base";
    252     } elsif ($img_type eq "stack") {
     287    } elsif ($stage eq "stack") {
    253288        $skycell_id = $component;
    254         $command = "$stacktool -sumskyfile -dbname $image_db";
     289        $command = "$stacktool -sumskyfile -dbname $imagedb";
    255290        $id_opt = "-stack_id";
    256291        $component_args = " -skycell_id $skycell_id" if $skycell_id;
     
    272307        $base_name   = "path_base";
    273308    } else {
    274         die "Unknown img_type supplied: $img_type";
    275     }
    276 
     309        die "Unknown IMG_TYPe supplied: $stage";
     310    }
     311
     312    my $filter_runs = 0;
    277313    if ($req_type eq "byid") {
    278314        $command .= " $id_opt $id";
     
    288324        # the reason as 'not destreaked'
    289325        $magic_arg = "";
     326        # remove duplicate runs for the same exposure.
     327        $filter_runs = 1;
    290328    } elsif ($req_type eq "byskycell") {
    291329        die "tess_id and component are required for byskycell" if !$tess_id or ! $skycell_id;
    292330        $command .= " -tess_id $tess_id -skycell_id $skycell_id";
    293331    } else {
    294         die "Unknown req_type supplied: $req_type";
    295     }
    296 
    297     if ($img_type ne "stack") {
     332        # this should be caught by caller
     333        &my_die("Unexpected req_type supplied: $req_type", $PS_EXIT_PROG_ERROR);
     334    }
     335
     336    if ($stage ne "stack") {
    298337        $command .= $magic_arg;
    299338        $command .= " -dateobs_begin $dateobs_begin" if $dateobs_begin;
     
    304343    $command .= " -data_group $data_group" if !isnull($data_group);
    305344
    306     # run the tool and parse the output
    307     my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
    308                 run(command => $command, verbose => $verbose);
    309     unless ($success) {
    310         # not sure if we should die here
    311         print STDERR @$stderr_buf;
     345    my $images = runToolAndParse($command, $verbose);
     346
     347    if (!$images or scalar @$images == 0) {
    312348        return undef;
    313349    }
    314350
    315     my $buf = join "", @$stdout_buf;
    316     if (!$buf) {
    317         return;
    318     }
    319 
    320     my $mdcParser = PS::IPP::Metadata::Config->new;
    321     my $images = parse_md_fast($mdcParser, $buf)
    322         or die ("Unable to parse metadata config doc");
    323 
     351    if ($filter_runs) {
     352        # The image selectors are such that multiple runs my have be returned for the same exposure.
     353        # Return only the latest one.
     354        $images = filterRuns($stage, $need_magic, $images, $verbose);
     355    }
     356    if ($choose_components) {
     357        # the list of "images" is actually a list of "Runs"
     358        # match the coords in the rows to the components in the runs
     359        # returns an actual list of images
     360        $images = selectComponents($ipprc, $imagedb, $req_type, $stage, $rowList, $images, $verbose);
     361    } else {
     362        # put each of the rows into all of the the images
     363        setRowRefs($rowList, $images);
     364    }
     365
     366    my $camera;
    324367    my $output = [];
    325 
    326     my $camera;
    327368    foreach my $image (@$images) {
    328369        my $base;
    329370
    330371        next if $image->{fault};
    331         next if ($img_type ne "raw") and $image->{quality};
     372        next if ($stage ne "raw") and $image->{quality};
    332373
    333374        if ($base_name) {
     
    361402        }
    362403        my $stage_id;
    363         if ($img_type eq "raw") {
     404        if ($stage eq "raw") {
    364405            $stage_id = $image->{exp_id};
    365         } elsif ($img_type eq "chip") {
     406        } elsif ($stage eq "chip") {
    366407            $stage_id = $image->{chip_id};
    367         } elsif ($img_type eq "warp") {
     408        } elsif ($stage eq "warp") {
    368409            $stage_id = $image->{warp_id};
    369         } elsif ($img_type eq "diff") {
     410        } elsif ($stage eq "diff") {
    370411            $stage_id = $image->{diff_id};
    371412            if ($inverse && $image->{bothways}) {
     
    375416                $cmf_name    = "PPSUB.INVERSE.SOURCES";
    376417            }
    377         } elsif ($img_type eq "stack") {
     418        } elsif ($stage eq "stack") {
    378419            $stage_id = $image->{stack_id};
    379420        }
    380421        $out->{stage_id} = $stage_id;
    381         $out->{stage}    = $img_type;
    382         $out->{image_db} = $image_db;
     422        $out->{stage}    = $stage;
     423        $out->{imagedb} = $imagedb;
    383424
    384425        if ($base) {
     
    390431            $out->{backmdl}= $ipprc->filename($backmdl_name, $base, $class_id) if $backmdl_name;
    391432        }
    392         $out->{astrom} = find_astrometry($ipprc, $image_db, $image, $verbose) if $want_astrom;
     433        if ($want_astrom and ! defined $out->{astrom}) {
     434            $out->{astrom} = find_astrometry($ipprc, $imagedb, $image, $verbose);
     435        }
    393436
    394437        push @$output, $out;
     
    397440    return $output;
    398441}
     442
    399443sub lookup_diff {
    400444    my $ipprc    = shift;
    401     my $image_db = shift;
     445    my $rowList  = shift;
     446    my $imagedb = shift;
    402447    my $id       = shift;
    403448    my $skycell_id = shift;
     
    409454    my $inverse = $option_mask & $PSTAMP_SELECT_INVERSE;
    410455
    411     my $missing_tools;
    412     my $difftool = can_run('difftool') or (warn "Can't find difftool" and $missing_tools = 1);
    413     if ($missing_tools) {
    414         warn("Can't find required tools.");
    415         exit ($PS_EXIT_CONFIG_ERROR);
    416     }
    417 
    418     my $command = "$difftool -diffskyfile -dbname $image_db";
     456    my $command = "$difftool -diffskyfile -dbname $imagedb";
    419457   
    420458    if ($byid) {
     
    425463    $command .= " -skycell_id $skycell_id" if $skycell_id;
    426464
    427     # run the tool and parse the output
    428     my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
    429                 run(command => $command, verbose => $verbose);
    430     unless ($success) {
    431         # not sure if we should die here
    432         print STDERR @$stderr_buf;
    433         return undef;
    434     }
    435 
    436     my $buf = join "", @$stdout_buf;
    437     if (!$buf) {
    438         return undef;
    439     }
    440 
    441     my $mdcParser = PS::IPP::Metadata::Config->new;
    442     my $images = parse_md_fast($mdcParser, $buf)
    443         or die ("Unable to parse metadata config doc");
     465    my $images = runToolAndParse($command, $verbose);
    444466
    445467    my $n = @$images;
     
    527549
    528550        if ($img_type eq "diff") {
     551            my @imageList = ($image);
     552
     553            setRowRefs($rowList, \@imageList);
    529554            # the $image is going to be returned directly in this case so we need to duplicate
    530555            # some of processing that lookup does for other img_types
     
    539564                $image->{stage_id} = $image->{diff_id};
    540565                $image->{stage}    = "diff";
    541                 $image->{image_db} = $image_db;
     566                $image->{imagedb} = $imagedb;
    542567                $image->{component} = $image->{skycell_id};
    543568            } else {
     
    554579sub lookup_bycoord {
    555580    my $ipprc      = shift;
    556     my $image_db   = shift;
     581    my $rowList    = shift;
     582    my $imagedb    = shift;
    557583    my $img_type   = shift;
    558584    my $tess_id    = shift;
     
    568594    my $verbose    = shift;
    569595
    570     my $missing_tools;
    571     my $regtool = can_run('regtool') or (warn "Can't find regtool" and $missing_tools = 1);
    572     my $camtool = can_run('camtool') or (warn "Can't find camtool" and $missing_tools = 1);
    573     my $dvoImagesAtCoords = can_run('dvoImagesAtCoords') or (warn "Can't find dvoImagesAtCoords" and $missing_tools = 1);
    574     my $whichimage = can_run('whichimage') or (warn "Can't find whichimage" and $missing_tools = 1);
    575     if ($missing_tools) {
    576         warn("Can't find required tools.");
    577         exit ($PS_EXIT_CONFIG_ERROR);
    578     }
    579 
    580596    my $results = ();
    581597    if (($img_type eq "raw") or ($img_type eq "chip")) {
    582598
    583         my $runs = lookup_runs_by_camid_and_coords($ipprc, $image_db, $img_type,
     599        my $runs = lookup_runs_by_cam_id_and_coords($ipprc, $imagedb, $img_type,
    584600            $ra, $dec, $need_magic, $dateobs_begin, $dateobs_end, $filter, $data_group, $verbose);
    585601
     602        # lookup is going to filter these we don't need to do it here
     603#        $runs = filterRuns($img_type, $need_magic, $runs, $verbose);
    586604        foreach my $run (@$runs) {
    587605            next if $component and ($run->{component} ne $component);
    588             my $these_results = lookup($ipprc, $image_db, "byid", $img_type, $run->{id},
     606            my $these_results = lookup($ipprc, $rowList, $imagedb, "byid", $img_type, $run->{id},
    589607                $tess_id, $run->{component}, $need_magic,
    590608                $dateobs_begin, $dateobs_end, $filter, $data_group, $option_mask, $verbose);
     
    602620
    603621        foreach my $skycell (@$skycells) {
    604             my $these_results = lookup($ipprc, $image_db, "byskycell", $img_type, undef,
     622            my $these_results = lookup($ipprc, $rowList, $imagedb, "byskycell", $img_type, undef,
    605623                $skycell->{tess_id}, $skycell->{component}, $need_magic,
    606624                $dateobs_begin, $dateobs_end, $filter, $data_group, $option_mask, $verbose);
     
    614632}
    615633
    616 # lookup_runs_by_camid_and_coords
     634# lookup_runs_by_cam_id_and_coords
    617635# given an ra, dec, and optionally other paramters, find camera runs for exposures
    618636# that are within some distance of the coordinates
    619 sub lookup_runs_by_camid_and_coords {
     637sub lookup_runs_by_cam_id_and_coords {
    620638    my $ipprc      = shift;
    621     my $image_db   = shift;
     639    my $imagedb   = shift;
    622640    my $img_type   = shift;
    623641    my $ra         = shift;
     
    631649
    632650    my $camruns;
    633     my $missing_tools;
    634     my $camtool = can_run('camtool') or (warn "Can't find camtool" and $missing_tools = 1);
    635     my $dvoImagesAtCoords = can_run('dvoImagesAtCoords') or (warn "Can't find dvoImagesAtCoords" and $missing_tools = 1);
    636     if ($missing_tools) {
    637         warn("Can't find required tools.");
    638         exit ($PS_EXIT_CONFIG_ERROR);
    639     }
    640651
    641652    {
    642         my $command = "$camtool -dbname $image_db -processedexp";
     653        my $command = "$camtool -dbname $imagedb -processedexp -pstamp_order";
    643654           $command .= " -ra $ra -decl $dec -radius 1.6";
    644655           $command .= " -dateobs_begin $dateobs_begin" if $dateobs_begin;
     
    652663           $command .= " -data_group $data_group" if $data_group;
    653664           $command .= " -destreaked" if $need_magic;
     665
    654666        # run the tool and parse the output
    655         my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
    656                     run(command => $command, verbose => $verbose);
    657         unless ($success) {
    658             print STDERR @$stderr_buf;
    659             return undef;
    660         }
    661         my $mdcParser = PS::IPP::Metadata::Config->new; # Parser for metadata config files
    662 
    663         my $output = join "", @$stdout_buf;
    664         if (!$output) {
    665             print STDERR "no output returned from $command\n" if $verbose;
    666             return undef;
    667         }
    668         $camruns = parse_md_fast($mdcParser, $output);
     667        $camruns = runToolAndParse($command, $verbose);
    669668    }
    670669    if (!$camruns) {
     
    672671    }
    673672    my $runs;
     673    my $last_exp_id = 0;
    674674    foreach my $camRun (@$camruns) {
    675675        my $cam_id = $camRun->{cam_id};
    676 
    677         updateCamRunCache($camRun);
     676        my $exp_id = $camRun->{exp_id};
     677
     678        next if $exp_id eq $last_exp_id;
    678679
    679680        next if $camRun->{quality};
    680681        next if $camRun->{fault};
     682
     683        updateCamRunCache($camRun);
     684
     685        $last_exp_id = $exp_id;
     686
    681687        # XXX Use file rule
    682688        my $astrom = $camRun->{path_base} . ".smf";
     
    684690        next if !$astrom_resolved;
    685691
     692        my $start_dvo = DateTime->now->mjd;
    686693        my $command = "$dvoImagesAtCoords -astrom $astrom_resolved $ra $dec";
    687694        # run the tool and parse the output
     695        my $dvo_verbose = 0;
    688696        my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
    689                     run(command => $command, verbose => $verbose);
     697                    run(command => $command, verbose => $dvo_verbose);
     698        my $dtime_dvo = (DateTime->now->mjd - $start_dvo)* 86400.;
     699#        print "Time to run dvoImagesAtCoords: $dtime_dvo\n";
    690700        unless ($success) {
    691701            my $result_code = $error_code >> 8;
    692702            if ($result_code == $PSTAMP_NO_OVERLAP) {
    693                 print STDERR "no overlap for $astrom\n" if $verbose;
     703                print "no overlap for $astrom\n" if $verbose;
    694704                next;
    695705            }
     
    721731            die "unexpected output from dvoImagesAtCoords: $lines[0]";
    722732        }
     733
     734        print "cam_id $cam_id exp_id $camRun->{exp_id} chip_id $camRun->{chip_id} $class_id\n";
     735
    723736        # build the hash to return
    724737        my $run = {
     
    732745        };
    733746        if ($img_type eq "chip") {
    734             $run->{id} = $run->{chip_id};
     747            $run->{id} = $camRun->{chip_id};
     748            $run->{state} = $camRun->{chip_state};
     749            $run->{magicked} = $camRun->{chip_magicked};
    735750        } else {
    736             $run->{id} = $run->{exp_id};
     751            $run->{id} = $camRun->{exp_id};
     752            $run->{state} = 'full';
     753            $run->{magicked} = $camRun->{raw_magicked};
    737754        }
    738755        push @$runs, $run;
     
    749766    my $dec        = shift;
    750767    my $verbose    = shift;
    751 
    752     my $missing_tools;
    753     my $whichimage = can_run('whichimage') or (warn "Can't find whichimage" and $missing_tools = 1);
    754     if ($missing_tools) {
    755         warn("Can't find required tools.");
    756         exit ($PS_EXIT_CONFIG_ERROR);
    757     }
    758768
    759769    $requested_tess_id = "" if isnull($requested_tess_id);
     
    817827sub find_astrometry {
    818828    my $ipprc = shift;
    819     my $image_db = shift;
     829    my $imagedb = shift;
    820830    my $image = shift;      # hashref to output of the lookup tool
    821831    my $verbose = shift;
     
    825835    my $exp_id = $image->{exp_id};
    826836    if (($exp_id eq $last_exp_id) and $lastAstromFile) {
    827         # running camtool 60 times is really expensive when the answer is the same
     837        # running camtool 60 times is really expensive when the answer is the same every time
    828838        return $lastAstromFile;
    829839    }
     
    831841    $lastAstromFile = undef;
    832842
    833     my $missing_tools;
    834     my $camtool = can_run("camtool") or (warn "Can't find camtool" and $missing_tools = 1);
    835     my $ppConfigDump = can_run('ppConfigDump') or (warn "Can't find ppConfigDump" and $missing_tools = 1);
    836     if ($missing_tools) {
    837         warn("Can't find required tools.");
    838         exit ($PS_EXIT_CONFIG_ERROR);
    839     }
    840 
    841843    my $camRun = getCamRunByExpID($exp_id);
    842844    if (!$camRun) {
    843         my $command = "$camtool -dbname $image_db -processedexp -exp_id $exp_id";
     845        my $command = "$camtool -dbname $imagedb -processedexp -exp_id $exp_id -pstamp_order";
    844846        # run the tool and parse the output
    845847        my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
     
    864866        # If there are multiple cam runs for this exposure, take the last completed one with good quality
    865867        # on the assumption that it has the best astrometry.
    866         while ($camRun = pop @$camruns) {
    867             last if (($camRun->{quality} eq 0) and ($camRun->{fault} eq 0));
     868        foreach $camRun (@$camruns) {
     869            last if (($camRun->{state} eq 'full') and ($camRun->{quality} eq 0) and ($camRun->{fault} eq 0));
    868870        }
    869871        # XXX: this looks like a bug at least if ASTROM.SOURCE eq PSASTRO.OUTPUT
     
    959961# resolve_project()
    960962# get project specific information
    961 my $last_project = "";
    962963sub resolve_project {
    963964    my $ipprc = shift;
    964965    my $project_name = shift;
    965966
     967    findTools();
     968
    966969    if (!$project_name) {
    967970        carp ("project is not defined");
     
    978981    my $verbose = 0;
    979982
    980     my $missing_tools;
    981     my $pstamptool = can_run("pstamptool") or (warn "Can't find pstamptool" and $missing_tools = 1);
    982     if ($missing_tools) {
    983         warn("Can't find required tools.");
    984         exit ($PS_EXIT_CONFIG_ERROR);
    985     }
    986 
    987983    my $command = "$pstamptool -project -name $project_name";
    988984    $command .= " -dbname $dbname" if defined $dbname;
    989985    $command .= " -dbserver $dbserver" if defined $dbserver;
    990     # run the tool and parse the output
    991     my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
    992                 run(command => $command, verbose => $verbose);
    993     unless ($success) {
    994         print STDERR @$stderr_buf;
     986
     987    my $proj_hash = runToolAndParse($command, $verbose);
     988    if (!$proj_hash or scalar @$proj_hash == 0) {
     989        print STDERR "Project $project_name not found\n";
    995990        return undef;
    996991    }
    997 
    998     my $mdcParser = PS::IPP::Metadata::Config->new; # Parser for metadata config files
    999 
    1000     my $output = join "", @$stdout_buf;
    1001     if (!$output) {
    1002         print STDERR "no output returned from $command\n" if $verbose;
    1003         return undef;
    1004     }
    1005     my $proj_hash = parse_md_fast($mdcParser, $output);
    1006992
    1007993    $last_project = $proj_hash->[0];
     
    10351021sub getCamRunByExpID {
    10361022    my $exp_id = shift;
    1037     die "getCamRun: exp_id is nil" if !$exp_id;
     1023    &my_die ("getCamRun: exp_id is nil", $PS_EXIT_PROG_ERROR) if !$exp_id;
    10381024
    10391025    return $camRunByExpIDCache{$exp_id};
    10401026}
     1027
    10411028sub getCamRunByCamID {
    10421029    my $cam_id = shift;
    1043     die "getCamRun: cam_id is nil" if !$cam_id;
     1030    &my_die ("getCamRun: cam_id is nil", $PS_EXIT_PROG_ERROR) if !$cam_id;
    10441031
    10451032    return $camRunByCamIDCache{$cam_id};
    10461033}
     1034
     1035sub selectComponents {
     1036    my $ipprc = shift;
     1037    my $imagedb = shift;
     1038    my $req_type = shift;
     1039    my $stage  = shift;
     1040    my $rowList = shift;
     1041    my $runList = shift;
     1042    my $verbose = shift;
     1043    my $results = [];
     1044   
     1045    my ($pointsList, $pointsListName) = tempfile ("/tmp/pointsList.XXXX", UNLINK => !$save_temps);
     1046    my $npoints = 0;
     1047    foreach my $row (@$rowList) {
     1048        print $pointsList "$npoints $row->{CENTER_X} $row->{CENTER_Y}\n";
     1049        $npoints++;
     1050    }
     1051    close $pointsList;
     1052
     1053    # XXX: need to loop over these
     1054    # my $run = $runList->[0];
     1055    if (($req_type eq "byid") or ($req_type eq "byexp")) {
     1056        my ($last_tess_id, $tess_dir_abs, $astrom_file) = ("", "", "");
     1057        foreach my $run (@$runList) {
     1058            my $command = "$dvoImagesAtCoords -coords $pointsListName";
     1059            if (($stage eq "chip") or ($stage eq "raw")) {
     1060                # XXX: use file rule and handle cameras where the astrometry is solved at
     1061                # the chip stage.
     1062                $astrom_file = $run->{cam_path_base} . ".smf";
     1063                my $astrom_file_resolved = $ipprc->file_resolve($astrom_file);
     1064                $command .= " -astrom $astrom_file_resolved";
     1065            } else {
     1066                my $tess_id = $run->{tess_id};
     1067                if ($tess_id ne $last_tess_id) {
     1068                    $tess_dir_abs = $ipprc->tessellation_catdir( $tess_id );
     1069                    $tess_dir_abs = $ipprc->convert_filename_absolute( $tess_dir_abs );
     1070                    $last_tess_id = $tess_id;
     1071                }
     1072                $command .= " -D CATDIR $tess_dir_abs"
     1073            }
     1074            my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
     1075                 run(command => $command, verbose => $verbose);
     1076            unless ($success) {
     1077                # don't fail if the program exited normally and exit status was PSTAMP_NO_OVERLAP
     1078                #                     # That just means that the coordinate didn't match any image/skycell
     1079                if (!WIFEXITED($error_code) || (WEXITSTATUS($error_code) ne $PSTAMP_NO_OVERLAP)) {
     1080                    print STDERR @$stderr_buf;
     1081                    my $rc = WIFEXITED($error_code) ? WEXITSTATUS($error_code) : $PS_EXIT_SYS_ERROR;
     1082                    &my_die( "dvoImagesAtCoords failed: $rc", $rc);
     1083                }
     1084            }
     1085            my %components;
     1086            my @lines = split "\n", join "", @$stdout_buf;
     1087            foreach my $line (@lines) {
     1088                my ($ptnum, undef, undef, $component) = split " ", $line;
     1089                my $ref = $components{$component};
     1090                if (!$ref) {
     1091                    $ref = $components{$component} = [];
     1092                }
     1093                push @$ref, $ptnum;
     1094            }
     1095            if ($verbose) {
     1096                foreach my $c (keys %components) {
     1097                    my $ref = $components{$c};
     1098                    print "component $c contains: ";
     1099                    foreach my $i (@$ref) {
     1100                        print "$i ";
     1101                    }
     1102                    print "\n";
     1103                }
     1104            }
     1105            # now find the images for this run
     1106            foreach my $c (keys %components) {
     1107                my $command;
     1108                my $stage_id;
     1109                if ($stage eq 'raw') {
     1110                    $stage_id = $run->{exp_id};
     1111                    $command = "$regtool -processedimfile -exp_id $stage_id -class_id $c";
     1112                } elsif ($stage eq 'chip') {
     1113                    $stage_id = $run->{chip_id};
     1114                    $command = "$chiptool -processedimfile -chip_id $stage_id -class_id $c";
     1115                } elsif ($stage eq 'warp') {
     1116                    $stage_id = $run->{warp_id};
     1117                    $command = "$warptool -warped -warp_id $stage_id -skycell_id $c";
     1118                } elsif ($stage eq 'diff') {
     1119                    $stage_id = $run->{diff_id};
     1120                    $command = "$difftool -diffskyfile -diff_id $stage_id -skycell_id $c";
     1121                }
     1122                $command .= " -dbname $imagedb";
     1123                my $images = runToolAndParse($command, $verbose);
     1124                if (!defined $images) {
     1125                    # XXX: need to get the set error_code to $PSTAMP_NO_OVERLAP
     1126                    print "No components containing coordinates found for ${stage}_id $stage_id\n";
     1127                    foreach my $row (@$rowList) {
     1128                        $row->{error_code} = $PSTAMP_NO_OVERLAP;
     1129                    }
     1130                    next;
     1131                }
     1132                if (scalar @$images != 1) {
     1133                    my $num_images = scalar @$images;
     1134                    &my_die ("unexpected number of images returned: $num_images\n", $PS_EXIT_PROG_ERROR);
     1135                }
     1136                my $image = $images->[0];
     1137                   
     1138                my $ref = $components{$c};
     1139                $image->{row_index} = $ref;
     1140                if (($stage eq "raw") or ($stage eq 'chip')) {
     1141                    $image->{astrom} = $astrom_file;
     1142                    $image->{cam_id} = $run->{cam_id};
     1143                    $image->{cam_path_base} = $run->{cam_path_base};
     1144                }
     1145                push @$results, $image;
     1146            }
     1147        }
     1148    } else {
     1149        &my_die ("sorry not done with $req_type\n", $PS_EXIT_PROG_ERROR);
     1150    }
     1151    return $results;
     1152}
     1153
     1154sub filterRuns {
     1155    my $stage      = shift;
     1156    my $need_magic = shift;
     1157    my $inputs     = shift;
     1158    my $verbose    = shift;
     1159
     1160    if ($inputs and (scalar @$inputs) == 1)  {
     1161        # one run nothing to do
     1162        return $inputs;
     1163    }
     1164
     1165    my $output = [];
     1166
     1167    return $output if (!$inputs or scalar @$inputs == 0);
     1168
     1169    my $id_name = $stage . "_id";
     1170
     1171    # input list is "order by exp_id, run_id DESC"   run_id is one of (chip_id, warp_id, diff_id)
     1172    print "Starting filterRuns\n";
     1173    my $last_exp_id = 0;
     1174    my $last_run_id = 0;
     1175    my $printed = 0;
     1176    foreach my $input (@$inputs) {
     1177        my $exp_id = $input->{exp_id};
     1178        my $run_id = $input->{$id_name};
     1179        my $magicked = $input->{magicked};  # this will be either stageRun.magicked or stage%file.magicked
     1180        my $state = $input->{state};
     1181
     1182        # can't process run in these states
     1183        if (($state eq 'new') or ($state eq 'purged') or ($state eq 'scrubbed')) {
     1184            print "skipping ${stage}Run $run_id for exp_id $exp_id in state $state\n";
     1185            next;
     1186        }
     1187
     1188        $printed = 1 if (($exp_id == $last_exp_id) and ($run_id == $last_run_id));
     1189
     1190        # skip if we need magicked run and this one has never been magicked
     1191        if ($need_magic and !$magicked) {
     1192            print "skipping ${stage}Run $run_id for exp_id $exp_id not magicked\n" if !$printed;
     1193            next;
     1194        }
     1195
     1196        if (($exp_id == $last_exp_id) and ($run_id != $last_run_id)) {
     1197            print "Skipping duplicate ${stage}Run $run_id for $exp_id\n" if !$printed;
     1198            next;
     1199        }
     1200        print "Keeping ${stage}Run $run_id for $exp_id\n";
     1201        push @$output, $input;
     1202        $last_exp_id = $exp_id;
     1203        $last_run_id = $run_id;
     1204        $printed = 0;
     1205    }
     1206
     1207    my $num_runs = scalar @$output;
     1208    print "filterRuns returning $num_runs ${stage}Run\n";
     1209
     1210    return $output;
     1211}
     1212
     1213# run a command that produces metadata output and parse the results into an array of objects
     1214sub runToolAndParse {
     1215    my $command = shift;
     1216    my $verbose = shift;
     1217
     1218    my ($program) = split " ", $command;
     1219    $program = basename($program);
     1220
     1221    print "Running $command\n" if !$verbose;
     1222    my $start_tool = DateTime->now->mjd;
     1223    # run the command and parse the output
     1224
     1225    my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
     1226                run(command => $command, verbose => $verbose);
     1227    unless ($success) {
     1228        # not sure if we should die here
     1229        print STDERR @$stderr_buf;
     1230        return undef;
     1231    }
     1232
     1233    my $now = DateTime->now->mjd;
     1234    my $dtime_tool = (DateTime->now->mjd - $start_tool) * 86400.;
     1235    print "Time to run $program: $dtime_tool\n";
     1236
     1237    my $buf = join "", @$stdout_buf;
     1238    if (!$buf) {
     1239        return undef;
     1240    }
     1241
     1242    my $start_parse = DateTime->now->mjd;
     1243
     1244    my $mdcParser = PS::IPP::Metadata::Config->new;
     1245    my $results = parse_md_fast($mdcParser, $buf)
     1246        or die ("Unable to parse metadata config doc");
     1247
     1248    my $dtime_parse = (DateTime->now->mjd - $start_parse) * 86400.;
     1249    print "Time to parse results from $program: $dtime_parse\n";
     1250
     1251    return $results;
     1252}
     1253
     1254sub findTools {
     1255    return if ($regtool);
     1256
     1257    my $missing_tools;
     1258    $regtool = can_run('regtool') or (warn "Can't find regtool" and $missing_tools = 1);
     1259    $chiptool = can_run('chiptool') or (warn "Can't find chiptool" and $missing_tools = 1);
     1260    $camtool = can_run('camtool') or (warn "Can't find camtool" and $missing_tools = 1);
     1261    $warptool = can_run('warptool') or (warn "Can't find warptool" and $missing_tools = 1);
     1262    $difftool = can_run('difftool') or (warn "Can't find difftool" and $missing_tools = 1);
     1263    $stacktool = can_run('stacktool') or (warn "Can't find stacktool" and $missing_tools = 1);
     1264    $pstamptool = can_run('pstamptool') or (warn "Can't find pstamptool" and $missing_tools = 1);
     1265    $dvoImagesAtCoords = can_run('dvoImagesAtCoords') or (warn "Can't find dvoImagesAtCoords"
     1266                                                                and $missing_tools = 1);
     1267    $whichimage = can_run('whichimage') or (warn "Can't find whichimage" and $missing_tools = 1);
     1268    $ppConfigDump = can_run('ppConfigDump') or (warn "Can't find ppConfigDump" and $missing_tools = 1);
     1269    if ($missing_tools) {
     1270        warn("Can't find required tools.");
     1271        exit ($PS_EXIT_CONFIG_ERROR);
     1272    }
     1273}
     1274
     1275# add a row_index array to a set of images with entries for each of the rows in a list
     1276sub setRowRefs {
     1277    my $rowList = shift;
     1278    my $images  = shift;
     1279
     1280    my $row_index = [];
     1281    for (my $i = 0; $i < scalar @$rowList; $i++) {
     1282        push @$row_index, $i;
     1283    }
     1284    foreach my $image (@$images) {
     1285        $image->{row_index} = $row_index;
     1286    }
     1287}
     1288
     1289sub my_die
     1290{
     1291    my $msg = shift;
     1292    my $fault = shift;
     1293
     1294    carp $msg;
     1295
     1296    # we don't fault the request here pstamp_parser_run.pl handles that if necessary
     1297
     1298    return $fault;
     1299}
    104713001;
  • trunk/ippTasks/pstamp.pro

    r27187 r27751  
    1313$pstampFin_DB = 0
    1414$pstampRev_DB = 0
     15$pstampDep_DB = 0
    1516
    1617# set PS_DBSERVER if postage stamp database host is not the same as the value for DBSERVER in site.config
     
    2829    book init pstampJob
    2930    book init pstampFinish
     31    book init pstampDependent
    3032end
    3133
    3234pstamp.reset
    33 
    3435
    3536macro pstamp.on
     
    6061        active true
    6162    end
     63    task pstamp.dependent.load
     64        active true
     65    end
    6266end
    6367
     
    8892    task pstamp.job.revert
    8993        active false
     94    end
     95    task pstamp.dependent.load
     96        active true
    9097    end
    9198end
     
    208215        book getword pstampRequest $pageName uri -var URI
    209216        book getword pstampRequest $pageName ds_outProduct -var PRODUCT
     217        book getword pstampRequest $pageName label -var LABEL
    210218
    211219        host anyhost
    212220
    213         $run = pstamp_parser_run.pl --req_id $REQ_ID --uri $URI --product $PRODUCT --redirect-output
     221        $run = pstamp_parser_run.pl --req_id $REQ_ID --uri $URI --product $PRODUCT --label $LABEL --redirect-output
    214222
    215223        add_standard_args run
     
    512520end
    513521
     522task pstamp.dependent.load
     523    host        local
     524
     525    periods     -poll $LOADPOLL
     526    # XXX: create a macro for this
     527    periods     -exec 30
     528#    periods     -exec $LOADEXEC
     529    periods     -timeout 30
     530    npending    1
     531
     532    task.exec
     533        stdout $LOGSUBDIR/pstamp.dependent.load.log
     534        stderr $LOGSUBDIR/pstamp.dependent.load.log
     535        $run = pstamptool -pendingdependent
     536        if ($DB:n == 0)
     537            option DEFAULT
     538        else
     539            option $DB:$pstampDep_DB
     540            $run = $run -dbname $DB:$pstampDep_DB $PS_DBSERVER
     541            $pstampDep_DB ++
     542            if ($pstampDep_DB >= $DB:n) set pstampDep_DB = 0
     543        end
     544        add_poll_args run
     545        add_poll_labels run
     546        command $run
     547    end
     548
     549    task.exit $EXIT_SUCCESS
     550        ipptool2book stdout pstampDependent -key dep_id -uniq -setword dbname $options:0 -setword pantaskState INIT
     551
     552        book npages pstampDependent -var N
     553        if ($VERBOSE > 2)
     554            book listbook pstampDependent
     555        end
     556
     557        # delete existing entries in the appropriate pantaskStates
     558        process_cleanup pstampDependent
     559    end
     560
     561    task.exit   crash
     562        showcommand crash
     563    end
     564
     565    task.exit   timeout
     566        showcommand timeout
     567    end
     568
     569    task.exit   default
     570        showcommand failure
     571    end
     572
     573end
     574
     575task pstamp.dependent.run
     576    periods     -poll $RUNPOLL
     577    periods     -exec $RUNEXEC
     578    periods     -timeout 300
     579
     580    task.exec
     581#        stdout $LOGSUBDIR/pstamp.dependent.run.log
     582#        stderr $LOGSUBDIR/pstamp.dependent.run.log
     583        book npages pstampDependent -var N
     584        if ($N == 0)
     585            periods -exec $RUNEXEC
     586            break
     587        end
     588        periods -exec 0.05
     589       
     590        book getpage pstampDependent 0 -var pageName -key pantaskState INIT
     591        if ("$pageName" == "NULL") break
     592
     593        #echo pageName: $pageName
     594
     595        book setword pstampDependent $pageName pantaskState RUN
     596        book getword pstampDependent $pageName dep_id     -var DEP_ID
     597        book getword pstampDependent $pageName state      -var STATE
     598        book getword pstampDependent $pageName stage      -var STAGE
     599        book getword pstampDependent $pageName stage_id   -var STAGE_ID
     600        book getword pstampDependent $pageName component  -var COMPONENT
     601        book getword pstampDependent $pageName imagedb    -var IMAGEDB
     602        book getword pstampDependent $pageName rlabel     -var RLABEL
     603#        book getword pstampDependent $pageName output_base -var OUTPUT_BASE
     604        book getword pstampDependent $pageName need_magic -var NEED_MAGIC
     605        book getword pstampDependent $pageName dbname     -var DBNAME
     606
     607        if ($VERBOSE > 1)
     608            book listpage pstampDependent $pageName
     609        end
     610
     611        host anyhost
     612
     613        if ("$NEED_MAGIC" == "T")
     614            $NEED_MAGIC="--need_magic"
     615        else
     616            $NEED_MAGIC=""
     617        end
     618
     619        # XXX: use OUTPUT_BASE for this
     620        $LOGFILE = /data/ipp053.0/home/bills/pstamp/logs/pstampdep.$DEP_ID.log
     621#        echo logfile is $LOGFILE
     622#        stdout $LOGFILE
     623#        stderr $LOGFILE
     624
     625        $run = pstamp_checkdependent.pl --dep_id $DEP_ID --stage_id $STAGE_ID --stage $STAGE --component $COMPONENT --imagedb $IMAGEDB --rlabel $RLABEL $NEED_MAGIC
     626        add_standard_args run
     627
     628        options $pageName
     629
     630        if ($VERBOSE > 1)
     631            echo command $run
     632        end
     633        command $run
     634    end
     635
     636
     637    task.exit $EXIT_SUCCESS
     638        if ($VERBOSE > 1)
     639            echo pstamp.dependent.run task.exit $DEP_ID status: $JOB_STATUS
     640        end
     641        process_exit pstampDependent $options:0 $JOB_STATUS
     642    end
     643    task.exit default
     644        if ($VERBOSE > 1)
     645            echo pstamp.job.run task.exit $DEP_ID status: $JOB_STATUS
     646        end
     647        showcommand failure
     648        process_exit pstampDependent $options:0 $JOB_STATUS
     649    end
     650
     651    task.exit crash
     652        echo pstamp.job.run task.crash $DEP_ID status: $JOB_STATUS
     653        process_exit pstampDependent $options:0 $JOB_STATUS
     654        showcommand crash
     655        book setword pstampDependent $options:0 pantaskState CRASH
     656    end
     657
     658    task.exit timeout
     659        echo pstamp.job.run task.timeout $DEP_ID status: $JOB_STATUS
     660        process_exit pstampDependent $options:0 $JOB_STATUS
     661        showcommand timeout
     662        book setword pstampDependent $options:0 pantaskState TIMEOUT
     663    end
     664end
     665
  • trunk/pstamp/scripts/pstamp_checkdependent.pl

    r27703 r27751  
    4848my $warptool = can_run('warptool') or (warn "Can't find warptool" and $missing_tools = 1);
    4949my $difftool = can_run('difftool') or (warn "Can't find difftool" and $missing_tools = 1);
     50my $stacktool = can_run('stacktool') or (warn "Can't find stacktool" and $missing_tools = 1);
    5051my $magicdstool = can_run('magicdstool') or (warn "Can't find magicdstool" and $missing_tools = 1);
    5152my $pstamptool = can_run('pstamptool') or (warn "Can't find pstamptool" and $missing_tools = 1);
     
    8687} else {
    8788    if ($stage eq "chip") {
    88         $cmd = "$chiptool -processedimfile -chip_id $stage_id -class_id $component";
     89        $cmd = "$chiptool -processedimfile -allfiles -chip_id $stage_id -class_id $component";
    8990    } elsif ($stage eq "warp") {
    9091        $cmd = "$warptool -warped -warp_id $stage_id -skycell_id $component";
     
    9697}
    9798
    98 my $components = runToolAndParse($cmd, $verbose);
    99 
    100 my $n = scalar @$components;
    101 my_die("Unexpected number of components found $n", $PS_EXIT_PROG_ERROR) if ($n != 1);
     99my $it = runToolAndParseExpectOne($cmd, $verbose);
     100
     101my_die("no components found", $PS_EXIT_PROG_ERROR) if ( !$it);
    102102
    103103# Got "it"
    104 my $it = $components->[0];
    105104
    106105my $status = 0;
     
    130129    # need to queue the updates
    131130    if ($stage eq 'chip') {
    132         # queue_update_chip takes an array so that queue_update_warp can pass a set of
    133         # chips to it
     131        # queue_update_chip takes an array so that queue_update_warp can pass it set of chips
    134132        my $chips = [$it];
    135133        $status = queue_update_chip($it->{chip_id}, $whole_run, $chips, $rlabel, $need_magic);
     
    145143
    146144    # detect states that cannot be updated and update the job state
    147     # XXX: we should be more assertive here and check for the specific states where we can continue
     145    # XXX: Perhaps I should be more assertive here and check for the specific states that we know
     146    # that we can continue.
     147
    148148    my $state = $it->{state};
    149149    my $job_fault = 0;
    150     if (($state =~ /scrub/) or ($state =~ /purge/)) {
     150
     151    # temporary hack to deal with data with old burntool tables. This check is now done by pstampparse.pl
     152    # so runs in this state will not get queued
     153    if ($stage eq 'chip') {
     154        my $burntool_state = $it->{burntool_state};
     155        if ($burntool_state and (abs($burntool_state) < 14)) {
     156            print STDERR "chip $it->{chip_id} $it->{class_id} has burntool_state $burntool_state. Not avaiable.\n";
     157            $job_fault = $PSTAMP_NOT_AVAILABLE;
     158        }
     159    }
     160    if ($state eq 'error_cleaned') {
     161        $job_fault = $PSTAMP_NOT_AVAILABLE;
     162    } elsif (($state =~ /scrub/) or ($state =~ /purge/)) {
    151163        # jobs must have changed state since depenency was made
    152164        print STDERR "Dependency cannot be satisfied\n";
     
    155167        # Dependency never should have been inserted
    156168        my_die ("Unexpected state for ${stage}Run $stage_id $state", $PS_EXIT_PROG_ERROR);
     169    }
     170    if (!$job_fault and ($stage eq 'chip')) {
     171        $job_fault = queue_update_magicDSRun($stage, $stage_id, $rlabel, $it->{raw_magicked}, $it->{dsRun_state});
    157172    }
    158173    if ($job_fault) {
     
    213228    }
    214229
     230    my $status = queue_update_magicDSRun('chip', $chip_id, $rlabel, $raw_all_magicked, $dsRun_state);
     231
     232    return $status;
     233}
     234
     235sub queue_update_warp {
     236    # check status of input chips. If state is not updatable set error code for job
     237
     238    # if chipProcessedImfile.state is cleaned call queue_update_chip
     239
     240    # need to code warptool -setskyfiletoupdate
     241    my $metadata = shift;
     242    my $whole_run = shift;  # if true queue entire run for update
     243    my $rlabel = shift;     # if defined a new label for the chipRun
     244    my $need_magic = shift;
     245
     246    my $raw_all_magicked = 1; # this gets cleared if any of the inputs aren't destreaked
     247
     248    my $warp_id = $metadata->{warp_id};
     249    if (!$whole_run) {
     250        my $skycell = $metadata;
     251        my $skycell_id = $skycell->{skycell_id};
     252
     253        my $command = "$warptool -scmap -warp_id $warp_id -skycell_id $skycell_id";
     254        my $data = runToolAndParse($command, $verbose);
     255        my_die("failed to find warpSkyCelllMap for warpRun $warp_id skycell_id $skycell_id", $PS_EXIT_UNKNOWN_ERROR)
     256            if !$data or scalar @$data == 0;
     257
     258        my $good_to_go = 1;
     259        my @chipsToUpdate;
     260        my $chip_id;
     261        foreach my $chip (@$data) {
     262            $chip_id = $chip->{chip_id};
     263            if (($chip->{data_state} ne 'full') or ($need_magic and ($chip->{magicked} <= 0))) {
     264                $good_to_go = 0;
     265                push @chipsToUpdate, $chip;
     266            } else {
     267                # this chip is good to go
     268            }
     269        }
     270
     271        if ($good_to_go) {
     272            my $command = "$warptool -setskyfiletoupdate -warp_id $warp_id -skycell_id $skycell->{skycell_id}";
     273            $command .= " -set_label $rlabel" if $rlabel;
     274
     275            if (!$no_update) {
     276                my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
     277                            run(command => $command, verbose => $verbose);
     278                unless ($success) {
     279                    my_die("failed to queue ${stage}Run $stage_id $component for update", $PS_EXIT_UNKNOWN_ERROR);
     280                }
     281            } else {
     282                print "skipping $command\n";
     283            }
     284        } elsif (scalar @chipsToUpdate > 0) {
     285            return queue_update_chip($chip_id, 0, \@chipsToUpdate, $rlabel, $need_magic);
     286        }
     287    } else {
     288        my $warpRun = $metadata;
     289        my $command = "$chiptool -listrun -chip_id $warpRun->{chip_id}";
     290        my $data = runToolAndParse($command, $verbose);
     291        my_die("failed to find chipRun $warpRun->{chip_id} for warpRun $warp_id", $PS_EXIT_UNKNOWN_ERROR)
     292            if !$data or scalar @$data != 1;
     293
     294        my $chipRun = $data->[0];
     295
     296        my $chipRunState = $chipRun->{state};
     297        if (($chipRunState =~ /purge/) or ($chipRunState =~ /scrub/)) {
     298            print STDERR "warpRun $warp_id depends on chipRun $chipRun->{chip_id} which is in state $chipRunState\n";
     299            faultJobs('stop', 'warp', $warp_id, $PSTAMP_GONE);
     300            return 0;
     301        }
     302        my $warpRunState = $warpRun->{state};
     303        if (($chipRunState eq 'full') and (! $need_magic or ($chipRun->{magicked} > 0)) and ($warpRunState eq 'cleaned')) {
     304            # The inputs and outputs are ready. Queue the warpRun for update.
     305
     306            # providing no -skycell_id arguments changes all skyfiles with data_state = 'cleaned' to 'update'
     307            my $command = "$warptool -setskyfiletoupdate -warp_id $warp_id";
     308            $command .= " -set_label $rlabel" if $rlabel;
     309
     310            if (!$no_update) {
     311                my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
     312                            run(command => $command, verbose => $verbose);
     313                unless ($success) {
     314                    my_die("failed to queue ${stage}Run $stage_id $component for update", $PS_EXIT_UNKNOWN_ERROR);
     315                }
     316            } else {
     317                print "skipping $command\n";
     318            }
     319        } elsif ($chipRunState eq 'cleaned' or
     320            (($chipRun->{state} eq 'full') and ($need_magic and ($chipRun->{magicked} < 0) and ($chipRun->{dsRun_state} ne 'new')))) {
     321            my $data = [$chipRun];
     322            return queue_update_chip($chipRun->{chip_id}, 1, $data, $rlabel, $need_magic);
     323        }
     324    }
     325
     326    # return value may be the return status of script so zero is good
     327    return 0;
     328}
     329sub queue_update_diff {
     330    my $metadata = shift;
     331    my $whole_run = shift;  # if true queue entire run for update
     332    my $rlabel = shift;     # if defined a new label for the chipRun
     333    my $need_magic = shift;
     334
     335# XXXX This is not ready to go yet XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXxx
     336
     337    my $diff_id   = $metadata->{diff_id};
     338    my $diff_mode = $metadata->{diff_mode};
     339    if (!$whole_run) {
     340        my $skycell = $metadata;
     341        my $skycell_id = $skycell->{skycell_id};
     342
     343        # put this in a module somewhere
     344        my $IPP_DIFF_MODE_WARP_WARP   = 1;
     345        my $IPP_DIFF_MODE_WARP_STACK  = 2;
     346        my $IPP_DIFF_MODE_STACK_WARP  = 2;
     347        my $IPP_DIFF_MODE_STACK_STACK = 4;
     348        if ($diff_mode == $IPP_DIFF_MODE_WARP_STACK ) {
     349            # check the state of the stack
     350            my $command = "$stacktool -sumkskyfile -stack_id $skycell->{stack2}";
     351            my $stack = runToolAndParseExpectOne($command, $verbose);
     352            my_die("failed to find stackSumSkyfile for stack_id $skycell->{stack2}", $PS_EXIT_UNKNOWN_ERROR) if !$stack;
     353
     354            if ($stack->{state} ne 'full') {
     355                print STDERR "template stack for diffRun $diff_id $skycell_id is not in full state faulting jobs\n";
     356                # this faults all jobs depending on this dep_id
     357                faultJobs('stop', 'diff', $diff_id, $PSTAMP_GONE);
     358                return $PSTAMP_GONE;
     359            }
     360
     361            # now check the warp
     362            $command = "$warptool -warped -warp_id $skycell->{warp1} -skycell_id $skycell_id";
     363            my $warp = runToolAndExpectOne($command, $verbose);
     364            my_die("failed to find warpSkyfile for warpRun $skycell->{warp_id} skycell_id $skycell_id", $PS_EXIT_UNKNOWN_ERROR)
     365                if !$warp;
     366        }
     367
     368        my $good_to_go = 1;
     369        my @chipsToUpdate;
     370        my $chip_id;
     371        my $warp_id;
     372        my $data ;  #XXXX
     373        foreach my $chip (@$data) {
     374            $chip_id = $chip->{chip_id};
     375            if (($chip->{data_state} ne 'full') or ($need_magic and ($chip->{magicked} <= 0))) {
     376                $good_to_go = 0;
     377                push @chipsToUpdate, $chip;
     378            } else {
     379                # this chip is good to go
     380            }
     381        }
     382
     383        if ($good_to_go) {
     384            my $command = "$warptool -setskyfiletoupdate -warp_id $warp_id -skycell_id $skycell->{skycell_id}";
     385            $command .= " -set_label $rlabel" if $rlabel;
     386
     387            if (!$no_update) {
     388                my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
     389                            run(command => $command, verbose => $verbose);
     390                unless ($success) {
     391                    my_die("failed to queue ${stage}Run $stage_id $component for update", $PS_EXIT_UNKNOWN_ERROR);
     392                }
     393            } else {
     394                print "skipping $command\n";
     395            }
     396        } elsif (scalar @chipsToUpdate > 0) {
     397            return queue_update_chip($chip_id, 0, \@chipsToUpdate, $rlabel, $need_magic);
     398        }
     399    } else {
     400        my $warpRun = $metadata;
     401        my $warp_id = $warpRun->{warp_id};
     402        my $command = "$chiptool -listrun -chip_id $warpRun->{chip_id}";
     403        my $data = runToolAndParse($command, $verbose);
     404        my_die("failed to find chipRun $warpRun->{chip_id} for warpRun $warp_id", $PS_EXIT_UNKNOWN_ERROR)
     405            if !$data or scalar @$data != 1;
     406
     407        my $chipRun = $data->[0];
     408
     409        my $chipRunState = $chipRun->{state};
     410        if (($chipRunState =~ /purge/) or ($chipRunState =~ /scrub/)) {
     411            print STDERR "warpRun $warp_id depends on chipRun $chipRun->{chip_id} which is in state $chipRunState\n";
     412            faultJobs('stop', 'warp', $warp_id, $PSTAMP_GONE);
     413            return 0;
     414        }
     415        my $warpRunState = $warpRun->{state};
     416        if (($chipRunState eq 'full') and (! $need_magic or ($chipRun->{magicked} > 0)) and ($warpRunState eq 'cleaned')) {
     417            # The inputs and outputs are ready. Queue the warpRun for update.
     418
     419            # providing no -skycell_id arguments changes all skyfiles with data_state = 'cleaned' to 'update'
     420            my $command = "$warptool -setskyfiletoupdate -warp_id $warp_id";
     421            $command .= " -set_label $rlabel" if $rlabel;
     422
     423            if (!$no_update) {
     424                my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
     425                            run(command => $command, verbose => $verbose);
     426                unless ($success) {
     427                    my_die("failed to queue ${stage}Run $stage_id $component for update", $PS_EXIT_UNKNOWN_ERROR);
     428                }
     429            } else {
     430                print "skipping $command\n";
     431            }
     432        } elsif ($chipRunState eq 'cleaned' or
     433            (($chipRun->{state} eq 'full') and ($need_magic and ($chipRun->{magicked} < 0) and ($chipRun->{dsRun_state} ne 'new')))) {
     434            my $data = [$chipRun];
     435            return queue_update_chip($chipRun->{chip_id}, 1, $data, $rlabel, $need_magic);
     436        }
     437    }
     438
     439    # return value may be the return status of script so zero is good
     440    return 0;
     441}
     442
     443
     444# run a command that produces metadata output and parse the results into an array of objects
     445sub runToolAndParse {
     446    my $command = shift;
     447    my $verbose = shift;
     448
     449    my ($program) = split " ", $command;
     450    $program = basename($program);
     451
     452    print "Running $command\n" if !$verbose;
     453    my $start_tool = DateTime->now->mjd;
     454    # run the command and parse the output
     455    my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
     456                run(command => $command, verbose => $verbose);
     457    unless ($success) {
     458        print STDERR @$stderr_buf if !$verbose;
     459        return undef;
     460    }
     461
     462    my $now = DateTime->now->mjd;
     463    my $dtime_tool = (DateTime->now->mjd - $start_tool) * 86400.;
     464    print "Time to run $program: $dtime_tool\n";
     465
     466    my $buf = join "", @$stdout_buf;
     467    if (!$buf) {
     468        return undef;
     469    }
     470
     471    my $start_parse = DateTime->now->mjd;
     472
     473    my $mdcParser = PS::IPP::Metadata::Config->new;
     474    my $results = parse_md_fast($mdcParser, $buf)
     475        or my_die ("Unable to parse metadata config doc", $PS_EXIT_UNKNOWN_ERROR);
     476
     477    my $dtime_parse = (DateTime->now->mjd - $start_parse) * 86400.;
     478    print "Time to parse results from $program: $dtime_parse\n";
     479
     480    return $results;
     481}
     482
     483# run an command returning metadata where we expect 1 entry
     484sub runToolAndParseExpectOne {
     485    my $command = shift;
     486    my $verbose = shift;
     487
     488    my $data = runToolAndParse($command, $verbose);
     489
     490    if (!$data) {
     491        return undef;
     492    }
     493
     494    my $n = scalar @$data;
     495    if ($n > 1) {
     496        my_die("Unexpected number of components $n returned by $command", $PS_EXIT_PROG_ERROR);
     497    }
     498
     499    return $data->[0];
     500}
     501
     502# splits meta data config input stream into single units to work around the pathalogically
     503# slow parser. This is similar to and adapted from code in various ippScripts.
     504sub parse_md_fast {
     505    my $mdcParser = shift;
     506    my $input = shift;
     507    my $output = ();
     508
     509    my @whole = split /\n/, $input;
     510    my @single = ();
     511
     512    my $n;
     513    while ( ($n = @whole) > 0) {
     514        my $value = shift @whole;
     515        push @single, $value;
     516        if ($value =~ /^\s*END\s*$/) {
     517            push @single, "\n";
     518
     519            my $list = parse_md_list( $mdcParser->parse( join("\n", @single ) ) ) or
     520                print STDERR "Unable to parse metdata config doc" and return undef;
     521            push @$output, $list->[0];
     522
     523            @single = ();
     524        }
     525    }
     526    return $output;
     527}
     528
     529sub faultJobs {
     530    my ($state, $stage, $stage_id, $job_fault) = @_;
     531
     532    my $command = "$pstamptool -updatejob -state stop -fault $job_fault -dep_id $dep_id";
     533    $command .= " -dbname $dbname" if $dbname;
     534    $command .= " -dbserver $dbserver" if $dbserver;
     535    if (!$no_update) {
     536        my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
     537                    run(command => $command, verbose => $verbose);
     538        unless ($success) {
     539            my_die("failed to set pstampJob.fault for dep_id: $dep_id",
     540                $PS_EXIT_UNKNOWN_ERROR);
     541        }
     542    } else {
     543        print "skipping $command\n";
     544    }
     545}
     546
     547sub queue_update_magicDSRun {
     548    my $stage = shift;
     549    my $stage_id = shift;
     550    my $rlabel  = shift;
     551    my $input_magicked = shift;
     552    my $dsRun_state = shift;
     553
     554    # XXX: this code is only fully coded and tested for chip stage
     555    my_die ("queue_update_magicDSRun only works for stage chip", $PS_EXIT_PROG_ERROR) if $stage ne 'chip';
     556
    215557    # if called from queue_update_warp dsRun_state is unknown. Go find it.
    216558    if (!$dsRun_state) {
    217         my $command = "$chiptool -listrun -chip_id $chip_id";
     559        my $command = "$chiptool -listrun -chip_id $stage_id";
    218560        my $data = runToolAndParse($command, $verbose);
    219561        my $chipRun = $data->[0];
     
    222564
    223565    # if the input file is already magicked no need to queue destreaking for this chipRun
    224     if ($need_magic and !$raw_all_magicked) {
     566    if ($need_magic and !$input_magicked) {
    225567        if ($dsRun_state eq 'cleaned') {
    226568            my $command = "$magicdstool -updaterun -set_state new -stage $stage -stage_id $stage_id";
     
    242584        }
    243585    }
    244 
    245     # return value may be the return status of script so zero is good
    246586    return 0;
    247587}
    248588
    249 sub queue_update_warp {
    250     # check status of input chips. If state is not updatable set error code for job
    251 
    252     # if chipProcessedImfile.state is cleaned call queue_update_chip
    253 
    254     # need to code warptool -setskyfiletoupdate
    255     my $metadata = shift;
    256     my $whole_run = shift;  # if true queue entire run for update
    257     my $rlabel = shift;     # if defined a new label for the chipRun
    258     my $need_magic = shift;
    259 
    260     my $raw_all_magicked = 1; # this gets cleared if any of the inputs aren't destreaked
    261 
    262     my $warp_id = $metadata->{warp_id};
    263     if (!$whole_run) {
    264         my $skycell = $metadata;
    265         my $skycell_id = $skycell->{skycell_id};
    266 
    267         my $command = "$warptool -scmap -warp_id $warp_id -skycell_id $skycell_id";
    268         my $data = runToolAndParse($command, $verbose);
    269         my_die("failed to find warpSkyCelllMap for warpRun $warp_id skycell_id $skycell_id", $PS_EXIT_UNKNOWN_ERROR)
    270             if !$data or scalar @$data == 0;
    271 
    272         my $good_to_go = 1;
    273         my @chipsToUpdate;
    274         my $chip_id;
    275         foreach my $chip (@$data) {
    276             $chip_id = $chip->{chip_id};
    277             if (($chip->{data_state} ne 'full') or ($need_magic and ($chip->{magicked} <= 0))) {
    278                 $good_to_go = 0;
    279                 push @chipsToUpdate, $chip;
    280             } else {
    281                 # this chip is good to go
    282             }
    283         }
    284 
    285         if ($good_to_go) {
    286             my $command = "$warptool -setskyfiletoupdate -warp_id $warp_id -skycell_id $skycell->{skycell_id}";
    287             $command .= " -set_label $rlabel" if $rlabel;
    288 
    289             if (!$no_update) {
    290                 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
    291                             run(command => $command, verbose => $verbose);
    292                 unless ($success) {
    293                     my_die("failed to queue ${stage}Run $stage_id $component for update", $PS_EXIT_UNKNOWN_ERROR);
    294                 }
    295             } else {
    296                 print "skipping $command\n";
    297             }
    298         } elsif (scalar @chipsToUpdate > 0) {
    299             return queue_update_chip($chip_id, 0, \@chipsToUpdate, $rlabel, $need_magic);
    300         }
    301     } else {
    302         my $warpRun = $metadata;
    303         my $command = "$chiptool -listrun -chip_id $warpRun->{chip_id}";
    304         my $data = runToolAndParse($command, $verbose);
    305         my_die("failed to find chipRun $warpRun->{chip_id} for warpRun $warp_id", $PS_EXIT_UNKNOWN_ERROR)
    306             if !$data or scalar @$data != 1;
    307 
    308         my $chipRun = $data->[0];
    309 
    310         my $chipRunState = $chipRun->{state};
    311         if (($chipRunState =~ /purge/) or ($chipRunState =~ /scrub/)) {
    312             print STDERR "warpRun $warp_id depends on chipRun $chipRun->{chip_id} which is in state $chipRunState\n";
    313             faultJobs('stop', 'warp', $warp_id, $PSTAMP_GONE);
    314             return 0;
    315         }
    316         my $warpRunState = $warpRun->{state};
    317         if (($chipRunState eq 'full') and (! $need_magic or ($chipRun->{magicked} > 0)) and ($warpRunState eq 'cleaned')) {
    318             # The inputs and outputs are ready. Queue the warpRun for update.
    319 
    320             # providing no -skycell_id arguments changes all skyfiles with data_state = 'cleaned' to 'update'
    321             my $command = "$warptool -setskyfiletoupdate -warp_id $warp_id";
    322             $command .= " -set_label $rlabel" if $rlabel;
    323 
    324             if (!$no_update) {
    325                 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
    326                             run(command => $command, verbose => $verbose);
    327                 unless ($success) {
    328                     my_die("failed to queue ${stage}Run $stage_id $component for update", $PS_EXIT_UNKNOWN_ERROR);
    329                 }
    330             } else {
    331                 print "skipping $command\n";
    332             }
    333         } elsif ($chipRunState eq 'cleaned' or
    334             (($chipRun->{state} eq 'full') and ($need_magic and ($chipRun->{magicked} < 0) and ($chipRun->{dsRun_state} ne 'new')))) {
    335             my $data = [$chipRun];
    336             return queue_update_chip($chipRun->{chip_id}, 1, $data, $rlabel, $need_magic);
    337         }
    338     }
    339 
    340     # return value may be the return status of script so zero is good
    341     return 0;
    342 }
    343 sub queue_update_diff {
    344     return 0;
    345 }
    346 
    347 
    348 # run a command that produces metadata output and parse the results into an array of objects
    349 sub runToolAndParse {
    350     my $command = shift;
    351     my $verbose = shift;
    352 
    353     my ($program) = split " ", $command;
    354     $program = basename($program);
    355 
    356     print "Running $command\n" if !$verbose;
    357     my $start_tool = DateTime->now->mjd;
    358     # run the command and parse the output
    359     my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
    360                 run(command => $command, verbose => $verbose);
    361     unless ($success) {
    362         print STDERR @$stderr_buf if !$verbose;
    363         return undef;
    364     }
    365 
    366     my $now = DateTime->now->mjd;
    367     my $dtime_tool = (DateTime->now->mjd - $start_tool) * 86400.;
    368     print "Time to run $program: $dtime_tool\n";
    369 
    370     my $buf = join "", @$stdout_buf;
    371     if (!$buf) {
    372         return undef;
    373     }
    374 
    375     my $start_parse = DateTime->now->mjd;
    376 
    377     my $mdcParser = PS::IPP::Metadata::Config->new;
    378     my $results = parse_md_fast($mdcParser, $buf)
    379         or my_die ("Unable to parse metadata config doc", $PS_EXIT_UNKNOWN_ERROR);
    380 
    381     my $dtime_parse = (DateTime->now->mjd - $start_parse) * 86400.;
    382     print "Time to parse results from $program: $dtime_parse\n";
    383 
    384     return $results;
    385 }
    386 
    387 # splits meta data config input stream into single units to work around the pathalogically
    388 # slow parser. This is similar to and adapted from code in various ippScripts.
    389 sub parse_md_fast {
    390     my $mdcParser = shift;
    391     my $input = shift;
    392     my $output = ();
    393 
    394     my @whole = split /\n/, $input;
    395     my @single = ();
    396 
    397     my $n;
    398     while ( ($n = @whole) > 0) {
    399         my $value = shift @whole;
    400         push @single, $value;
    401         if ($value =~ /^\s*END\s*$/) {
    402             push @single, "\n";
    403 
    404             my $list = parse_md_list( $mdcParser->parse( join("\n", @single ) ) ) or
    405                 print STDERR "Unable to parse metdata config doc" and return undef;
    406             push @$output, $list->[0];
    407 
    408             @single = ();
    409         }
    410     }
    411     return $output;
    412 }
    413 sub faultJobs {
    414     my ($state, $stage, $stage_id, $job_fault) = @_;
    415 
    416     my $command = "$pstamptool -updatejob -state stop -fault $job_fault -dep_id $dep_id";
     589sub my_die
     590{
     591    my $msg = shift;
     592    my $fault = shift;
     593    carp $msg;
     594
     595    my $command = "$pstamptool -updatedepedent -fault $fault -dep_id $dep_id";
    417596    $command .= " -dbname $dbname" if $dbname;
    418597    $command .= " -dbserver $dbserver" if $dbserver;
     
    421600                    run(command => $command, verbose => $verbose);
    422601        unless ($success) {
    423             my_die("failed to set pstamJob.fault for dep_id: $dep_id",
     602            my_die("failed to set pstampDependent.fault for dep_id: $dep_id",
    424603                $PS_EXIT_UNKNOWN_ERROR);
    425604        }
     
    427606        print "skipping $command\n";
    428607    }
    429 }
    430 
    431 sub my_die
    432 {
    433     my $msg = shift;
    434     my $fault = shift;
    435 
    436     carp $msg;
    437 
    438     return $fault;
    439 }
     608
     609    exit $fault;
     610}
  • trunk/pstamp/scripts/pstamp_finish.pl

    r27670 r27751  
    124124    my ($rlf, $reglist_name) = tempfile ("$out_dir/reglist.XXXX", UNLINK => !$save_temps);
    125125    print $rlf "results.fits|||table|\n";
    126     print $rlf "results.mdc|||txt|\n";
     126    print $rlf "results.mdc|||text|\n";
    127127
    128128    my $err_file = "parse_error.txt";
     
    171171        my $exp_id = $job->{exp_id};
    172172
     173
    173174        if (($fault eq $PSTAMP_DUP_REQUEST) and ($req_name eq "NULL")) {
    174175            # this request had a duplicate request name. We can't put the results
     
    188189        }
    189190
    190         if ($exp_id ne $last_exp_id) {
     191        my $job_params = get_job_parameters($job);
     192        my $stage = "";
     193        if ($job_params) {
     194            $stage = $job_params->{stage};
     195        }
     196
     197        if ($stage ne 'stack') {
    191198            # get the metadata for the exposure (if any i.e. stack)
    192199            # returns an appropriate string if !$exp_id
    193200            $exp_info = get_exposure_info($image_db, $exp_id);
    194201            $last_exp_id = $exp_id;
     202        } else {
     203            my $filter = $job_params->{filter};
     204            $filter = "0" if !$filter;
     205            $exp_info = "0|0|0|$filter|0|0";
     206            $last_exp_id = -1;
    195207        }
    196208
     
    344356}
    345357
     358sub get_job_parameters {
     359    my $job = shift;
     360    if (!$job->{outputBase}) {
     361        print "get_job_parameters: $job->{job_id} has no outputBase\n";
     362        return undef;
     363    }
     364    my $params_file = $job->{outputBase} . '.mdc';
     365    if (! -e $params_file ) {
     366        print "get_job_parameters: $job->{job_id} has no parameters file\n";
     367        return undef;
     368    }
     369    open IN, "<$params_file" or die "unable to open $params_file";
     370    my $data = join "", (<IN>);
     371    close IN;
     372    if (! $data ) {
     373        print "get_job_parameters: parameters file is empty\n";
     374        return undef;
     375    }
     376    my $metadata = $mdcParser->parse($data) or die("Unable to parse metdata config doc");
     377
     378    my $results = parse_md_list($metadata);
     379    if (scalar @$results != 1) {
     380        print STDERR "get_job_params: failed to parse_md_list\n";
     381        return undef;
     382    }
     383    return $results->[0];
     384}
     385
    346386sub get_exposure_info {
    347387    my $image_db= shift;
  • trunk/pstamp/scripts/pstamp_job_run.pl

    r27577 r27751  
    250250            copy_and_register_file($f, $backmdl_file, $outdir, $prefix);
    251251        }
    252         if (0) {
     252       if (0) {
    253253        # don't enable this yet
    254254        if ($pattern_file) {
     
    256256            copy_and_register_file($f, $pattern_file, $outdir, $prefix);
    257257        }
    258         }
     258       }
    259259    }
    260260}
  • trunk/pstamp/scripts/pstamp_parser_run.pl

    r26151 r27751  
    2828my $redirect_output;
    2929my $product;
     30my $label;
    3031my $verbose;
    3132my $dbname;
     
    3637    'uri=s'             =>  \$uri,
    3738    'product=s'         =>  \$product,
     39    'label=s'           =>  \$label,
    3840    'redirect-output'   =>  \$redirect_output,
    3941    'verbose'           =>  \$verbose,
     
    146148        if ($request_type eq "PS1_PS_REQUEST") {
    147149            $reqType = 'pstamp';
    148             $parse_cmd = $pstampparse;
     150            $parse_cmd = "$pstampparse";
     151            $parse_cmd .= " --label $label" if $label;
    149152        } elsif ($request_type eq "MOPS_DETECTABILITY_QUERY") {
    150153            $reqType = 'dquery';
  • trunk/pstamp/scripts/pstamp_request_file

    r26289 r27751  
    187187        for (my $i = 0; $i < scalar @colNames; $i++) {
    188188            my $writeType = $colWriteType[$i];
    189             $outFits->write_col( $writeType, $i + 1, 1, 1, $numRows, $colData->[$i], $status );
     189            my $data = $colData->[$i];
     190            if ($writeType == TULONG) {
     191                die "invalid integer data found in column $i\n" unless validIntegers($data);
     192            } elsif ($writeType == TDOUBLE) {
     193                die "invalid numeric data found in column $i\n" unless validNumbers($data);
     194            }
     195            $outFits->write_col( $writeType, $i + 1, 1, 1, $numRows, $data, $status );
    190196            check_fitsio( $status );
    191197        }
     
    312318}
    313319
     320sub checkValid {
     321    my $aref = shift;
     322    my $float = shift;
     323
     324    return 0 if !defined $aref;
     325
     326    my $valid = 0;
     327    my $row = 0;
     328    foreach my $val (@$aref) {
     329        $row++;
     330        if ($float) {
     331            if (!($val =~  /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/)) {
     332                $valid = 0;
     333                print STDERR "Error on row $row: '$val' is not a valid number\n";
     334                last;
     335            }
     336        } else {
     337            if ($val =~ /\D/) {
     338                $valid = 0;
     339                print STDERR "Error on row $row: '$val' is not a valid integer\n";
     340                last;
     341            }
     342        }
     343        $valid = 1;
     344    }
     345
     346    return $valid;
     347}
     348sub validIntegers {
     349    return checkValid(@_, 0);
     350}
     351
     352sub validNumbers
     353{
     354    return checkValid(@_, 1);
     355}
     356
     357
    314358sub printhelp
    315359{
  • 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.