- Timestamp:
- May 3, 2010, 8:50:52 AM (16 years ago)
- Location:
- branches/simtest_nebulous_branches
- Files:
-
- 2 edited
-
. (modified) (1 prop)
-
PS-IPP-PStamp/lib/PS/IPP/PStamp/Job.pm (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
branches/simtest_nebulous_branches
- Property svn:mergeinfo changed
-
branches/simtest_nebulous_branches/PS-IPP-PStamp/lib/PS/IPP/PStamp/Job.pm
r24968 r27840 16 16 locate_images 17 17 resolve_project 18 getCamRunByCamID 18 19 ); 19 20 our %EXPORT_TAGS = (standard => [@EXPORT_OK]); 20 21 21 22 23 use PS::IPP::PStamp::RequestFile qw( :standard ); 24 22 25 use IPC::Cmd 0.36 qw( can_run run ); 23 24 26 use PS::IPP::Metadata::List qw( parse_md_list ); 25 27 use PS::IPP::Config qw( :standard ); 26 28 use Carp; 27 28 ### my @images = locate_images($image_db, $req_type, $img_type, $id, $component, 29 ### $mjd_min, $mjd_max, $filter); 29 use DateTime; 30 use File::Temp qw(tempfile); 31 use File::Basename; 32 use POSIX; 33 34 my $dvo_verbose = 0; 35 my $save_temps = 0; 36 37 # caches of camProcessedExp objects. 38 # Key is $exp_id 39 my %camRunByExpIDCache; 40 # Key is $cam_id 41 my %camRunByCamIDCache; 42 43 # cache of last project looked up 44 my $last_project = ""; 45 46 my ($regtool, $chiptool, $camtool, $warptool, $stacktool, $difftool); 47 my ($pstamptool, $dvoImagesAtCoords, $whichimage, $ppConfigDump); 30 48 31 49 sub locate_images { 32 50 my $ipprc = shift; # required 33 my $image_db = shift; # required 51 my $imagedb = shift; # required 52 my $rowList = shift; # required 34 53 my $req_type = shift; # required 35 54 my $img_type = shift; # required 36 my $id = shift; # required unless req_type eq bycoord 55 my $id = shift; # required unless req_type eq bycoord or byskycell 56 my $tess_id = shift; 37 57 my $component= shift; # class_id or skycell_id 38 my $ x= shift;39 my $ y= shift;58 my $option_mask = shift; 59 my $need_magic = shift; 40 60 my $mjd_min = shift; 41 61 my $mjd_max = shift; 42 62 my $filter = shift; 63 my $data_group = shift; 43 64 my $verbose = shift; 44 65 45 66 # we die in response to bad data in request files 46 die "Unknown req_type: $req_type" if ($req_type ne "byid") and ($req_type ne "byexp") 47 and ($req_type ne "bycoord") and ($req_type ne "bydiff"); 67 # The caller is responsible for updating the database 68 # pstampparse.pl error checks now so this shouldn't happen 69 &my_die("Unknown req_type: $req_type", $PS_EXIT_PROG_ERROR) 70 if ($req_type ne "byid") and 71 ($req_type ne "byexp") and 72 ($req_type ne "bycoord") and 73 ($req_type ne "bydiff") and 74 ($req_type ne "byskycell"); 75 76 77 my $dateobs_begin; 78 my $dateobs_end; 79 if (!iszero($mjd_min)) { 80 $dateobs_begin = mjd_to_dateobs($mjd_min); 81 } 82 if (!iszero($mjd_max)) { 83 $dateobs_end = mjd_to_dateobs($mjd_max); 84 } 85 if (isnull($tess_id)) { 86 $tess_id = undef; 87 } 88 if (isnull($data_group)) { 89 $data_group = undef; 90 } 91 if (isnull($filter)) { 92 $filter = undef; 93 } 94 95 if ($req_type eq "bycoord") { 96 my $num_rows = scalar @$rowList; 97 die "Unexpected number of rows found in rowList: $num_rows" if $num_rows != 1; 98 my $row = $rowList->[0]; 99 my $x = $row->{CENTER_X}; 100 my $y = $row->{CENTER_Y}; 101 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); 102 return $results; 103 } 104 48 105 if (($req_type eq "byid") and ($img_type eq "diff")) { 49 106 # lookups of all of the information for diff images requires a two level lookup to … … 51 108 # in one place 52 109 $req_type = "bydiff"; 53 } 110 my $results = lookup_diff($ipprc, $rowList, $imagedb, $id, $component, 1, $option_mask, $img_type, $verbose); 111 return $results; 112 } 113 54 114 if ($req_type eq "bydiff") { 55 my $results = lookup_bydiff($ipprc, $image_db, $id, $img_type, $verbose); 115 # for bydiff reuqests we go look up the diffRun to obtain exp_id, chip_id, warp_id, stack_id, or 116 # the image from the diffRun 117 my $results = lookup_diff($ipprc, $rowList, $imagedb, $id, $component, 0, $option_mask, $img_type, $verbose); 56 118 if (!$results) { 57 119 return undef; 58 120 } 59 if (($img_type eq "warp") or ($img_type eq "diff")) { 60 # lookup_bydiff has done all of the work 61 return [$results]; 62 } elsif (($img_type eq "raw") or ($img_type eq "chip")) { 63 $req_type = "byexp"; 64 $id = $results->{exp_name}; 121 if ($img_type eq "diff") { 122 # lookup_diff has done all of the work 123 return $results; 124 } 125 126 my $image = $results->[0]; 127 if ($img_type eq "raw") { 128 $req_type = "byid"; 129 $id = $image->{exp_id}; 65 130 return undef if !$id; 66 # fall through and lookup byexp 67 # } elsif ($img_type eq "warp") { 68 # $req_type = "byid"; 69 # $id = $results->{warp_id}; 70 # $component = $results->{skycell_id}; 71 # return undef if !$id; 72 # # fall through and lookup by warp_id 131 # fall through and lookup byid 132 } elsif ($img_type eq "chip") { 133 $req_type = "byid"; 134 $id = $image->{chip_id}; 135 return undef if !$id; 136 # fall through and lookup byid 137 } elsif ($img_type eq "warp") { 138 $req_type = "byid"; 139 $id = $image->{warp_id}; 140 $component = $image->{skycell_id}; 141 return undef if !$id; 142 # fall through and lookup by warp_id 73 143 } elsif ($img_type eq "stack") { 74 144 $req_type = "byid"; 75 $id = $ results->{stack_id};145 $id = $image->{stack_id}; 76 146 return undef if !$id; 77 # fall though and lookup by stack id147 # fall though and lookup by stack_id 78 148 } else { 79 # shouldn't I checkthis elsewhere?149 # This is checked this elsewhere? 80 150 print STDERR "Error: $img_type is an unknown image type\n"; 81 151 return undef; 82 152 } 83 84 } elsif ($req_type eq "bycoord") { 85 86 # run 87 # regtool -dbname $image_db -processedimfile -time_begin $mjd_min -time_end = $mjd_max -filter $filter 88 # 89 my $results = lookup_bycoord($ipprc, $image_db, $x, $y, $mjd_min, $mjd_max, $filter, $verbose); 90 91 # now take the results and lookup byexp 92 # XXX: This needs work. What stops results from returning multiple images???? 93 # We should loop over the set of images returned building up the full results array 94 $req_type = "byexp"; 95 $id = $results->{exp_name}; 96 } 97 98 my $results = lookup($ipprc, $image_db, $req_type, $img_type, $id, $component, $verbose); 153 } elsif ($req_type eq "byskycell") { 154 if (($img_type eq "raw") or ($img_type eq "chip")) { 155 print STDERR "REQ_TYPE byskycell not supported for IMG_TYPE raw or chip\n"; 156 return undef; 157 } 158 if (!$tess_id or !$component) { 159 print STDERR "component and tess_id are required for REQ_TYPE byskycell\n"; 160 return undef; 161 } 162 } 163 164 my $results = lookup($ipprc, $rowList, $imagedb, $req_type, $img_type, $id, $tess_id, $component, 165 $need_magic, $dateobs_begin, $dateobs_end, $filter, $data_group, $option_mask, $verbose); 99 166 100 167 return $results; 101 168 } 102 169 103 sub lookup { 170 # The subroutine lookup handles byexp, byid, and byskycell lookups including lookups that are 171 # triggered by a bydiff request 172 173 sub lookup 174 { 104 175 my $ipprc = shift; 105 my $image_db = shift; 176 my $rowList = shift; 177 my $imagedb = shift; 106 178 my $req_type = shift; 107 my $ img_type = shift;179 my $stage = shift; 108 180 my $id = shift; 181 my $tess_id = shift; 109 182 my $component= shift; 183 my $need_magic = shift; 184 my $dateobs_begin = shift; 185 my $dateobs_end = shift; 186 my $filter = shift; 187 my $data_group = shift; 188 my $option_mask = shift; 110 189 my $verbose = shift; 111 190 112 my $missing_tools; 113 my $regtool = can_run('regtool') or (warn "Can't find regtool" and $missing_tools = 1); 114 my $chiptool = can_run('chiptool') or (warn "Can't find chiptool" and $missing_tools = 1); 115 my $warptool = can_run('warptool') or (warn "Can't find warptool" and $missing_tools = 1); 116 my $difftool = can_run('difftool') or (warn "Can't find difftool" and $missing_tools = 1); 117 my $stacktool = can_run('stacktool') or (warn "Can't find stacktool" and $missing_tools = 1); 118 if ($missing_tools) { 119 warn("Can't find required tools."); 120 exit ($PS_EXIT_CONFIG_ERROR); 121 } 191 my $inverse = $option_mask & $PSTAMP_SELECT_INVERSE; 192 my $unconvolved = $option_mask & $PSTAMP_SELECT_UNCONV; 193 my $use_imfile_id = ($req_type eq "byid") && ($option_mask & $PSTAMP_USE_IMFILE_ID); 194 122 195 my $command; 123 196 my $id_opt; # option for the lookup … … 125 198 my $mask_name; 126 199 my $weight_name; 200 my $cmf_name; 201 my $psf_name; 202 my $backmdl_name; 127 203 my $base_name; 128 204 my $want_astrom; … … 131 207 my $skycell_id; 132 208 133 # special class_id value "null" means ignore 134 if ($component and ($component eq "null")) { 209 if (isnull($component)) { 135 210 $component = undef; 136 211 } 137 212 138 if ($img_type eq "raw") { 213 # note $magic_arg may be cleared below depending on $req_type 214 my $magic_arg = $need_magic ? " -destreaked" : ""; 215 216 # all rows have the same center type 217 my $skycenter = ! ($rowList->[0]->{COORD_MASK} & $PSTAMP_CENTER_IN_PIXELS); 218 219 my $component_args; 220 my $choose_components = 0; 221 if ($stage eq "raw") { 139 222 $class_id = $component; 140 $command = "$regtool -processedimfile -dbname $image_db"; 141 $id_opt = "-exp_id"; 142 $command .= " -class_id $class_id" if $component; 223 $command = "$regtool -processedimfile -dbname $imagedb"; 224 # XXX: for now restrict lookups to type object 225 # are stamps of detrend exposures interesting? 226 $command .= " -exp_type object"; 227 $id_opt = $use_imfile_id ? "-raw_imfile_id" : "-exp_id"; 228 $component_args = " -class_id $class_id" if $component; 143 229 $want_astrom = 1; 144 230 $set_class_id = 1; 145 } elsif ($ img_type eq "chip") {231 } elsif ($stage eq "chip") { 146 232 $class_id = $component; 147 $command = "$chiptool -processedimfile -dbname $image_db"; 148 $command .= " -class_id $class_id" if $class_id; 149 $id_opt = "-chip_id"; 233 # if the request is such that it will yield a single image per "run" or the 234 # center is specified in pixel coordinates 235 # use chiptool -processsedimfile. Otherwise use chiptool -listrun and then 236 # choose the chips containing the center pixel by calling selectComponets() below 237 if ($class_id or $use_imfile_id or !$skycenter) { 238 $command = "$chiptool -processedimfile -dbname $imagedb"; 239 $component_args = " -class_id $class_id" if $class_id; 240 } else { 241 $command = "$chiptool -listrun -pstamp_order -dbname $imagedb"; 242 $choose_components = 1; 243 } 244 $id_opt = $use_imfile_id ? "-chip_imfile_id" : "-chip_id"; 245 # XXX: perhaps we should stop resolving images to this level here and do it at job run time. 246 # With the mdc file it has all of the information that it needs. 150 247 $image_name = "PPIMAGE.CHIP"; 151 248 $mask_name = "PPIMAGE.CHIP.MASK"; 152 249 $weight_name = "PPIMAGE.CHIP.VARIANCE"; 250 $cmf_name = "PSPHOT.OUTPUT"; 251 $psf_name = "PSPHOT.PSF.SAVE"; 252 $backmdl_name = "PSPHOT.BACKMDL"; 153 253 $base_name = "path_base"; # name of the field for the chiptool output 154 254 $want_astrom = 1; 155 255 $set_class_id = 1; 156 } elsif ($ img_type eq "warp") {256 } elsif ($stage eq "warp") { 157 257 $skycell_id = $component; 158 $command = "$warptool -warped -dbname $image_db"; 159 $command .= " -skycell_id $skycell_id" if $skycell_id; 160 $id_opt = "-warp_id"; 258 if ($skycell_id or $use_imfile_id or !$skycenter) { 259 $command = "$warptool -warped -dbname $imagedb"; 260 $component_args = " -skycell_id $skycell_id" if $skycell_id; 261 } else { 262 $command = "$warptool -listrun -pstamp_order -dbname $imagedb"; 263 $choose_components = 1; 264 } 265 $id_opt = $use_imfile_id ? "-warp_skyfile_id" : "-warp_id"; 161 266 $image_name = "PSWARP.OUTPUT"; 162 267 $mask_name = "PSWARP.OUTPUT.MASK"; 163 268 $weight_name = "PSWARP.OUTPUT.VARIANCE"; 269 $cmf_name = "PSWARP.OUTPUT.SOURCES"; 270 $psf_name = "PSPHOT.PSF.SKY.SAVE"; 164 271 $base_name = "path_base"; # name of the field for the warptool output 165 } elsif ($ img_type eq "diff") {272 } elsif ($stage eq "diff") { 166 273 $skycell_id = $component; 167 $command = "$difftool -diffskyfile -dbname $image_db"; 168 $command .= " -skycell_id $skycell_id" if $skycell_id; 169 $id_opt = "-diff_id"; 274 if ($skycell_id or $use_imfile_id or !$skycenter) { 275 $command = "$difftool -diffskyfile -dbname $imagedb"; 276 $component_args = " -skycell_id $skycell_id" if $skycell_id; 277 } else { 278 $command = "$difftool -listrun -pstamp_order -dbname $imagedb"; 279 $choose_components = 1; 280 } 281 $id_opt = $use_imfile_id ? "-diff_skyfile_id" : "-diff_id"; 170 282 $image_name = "PPSUB.OUTPUT"; 171 283 $mask_name = "PPSUB.OUTPUT.MASK"; 172 284 $weight_name = "PPSUB.OUTPUT.VARIANCE"; 285 $cmf_name = "PPSUB.OUTPUT.SOURCES"; 286 $psf_name = "PSPHOT.PSF.SKY.SAVE"; 173 287 $base_name = "path_base"; 174 } elsif ($img_type eq "stack") { 175 $command = "$stacktool -sumskyfile -dbname $image_db"; 288 } elsif ($stage eq "stack") { 289 $skycell_id = $component; 290 $command = "$stacktool -sumskyfile -dbname $imagedb"; 176 291 $id_opt = "-stack_id"; 177 178 $image_name = "PPSTACK.OUTPUT"; 179 $mask_name = "PPSTACK.OUTPUT.MASK"; 180 $weight_name = "PPSTACK.OUTPUT.VARIANCE"; 292 $component_args = " -skycell_id $skycell_id" if $skycell_id; 293 294 if (!$unconvolved) { 295 $image_name = "PPSTACK.OUTPUT"; 296 $mask_name = "PPSTACK.OUTPUT.MASK"; 297 $weight_name = "PPSTACK.OUTPUT.VARIANCE"; 298 } else { 299 $image_name = "PPSTACK.UNCONV"; 300 $mask_name = "PPSTACK.UNCONV.MASK"; 301 $weight_name = "PPSTACK.UNCONV.VARIANCE"; 302 } 303 # this is wrong but gets the right answer. Need to figure out how to find the 304 # rule properly 305 #$cmf_name = "PSPHOT.OUTPUT"; # this puts .fpa. in the name 306 $cmf_name = "PSWARP.OUTPUT.SOURCES"; 307 $psf_name = "PPSTACK.TARGET.PSF"; 181 308 $base_name = "path_base"; 182 309 } else { 183 die "Unknown img_type supplied: $img_type"; 184 } 185 310 die "Unknown IMG_TYPe supplied: $stage"; 311 } 312 313 my $filter_runs = 0; 186 314 if ($req_type eq "byid") { 187 315 $command .= " $id_opt $id"; 316 $command .= $component_args if $component_args; 317 # don't include -destreaked if lookup is byid. Let pstampparse check so that the 318 # error code returned to the client for a given component is 'not destreaked' 319 # instead of 'not found' 320 $magic_arg = ""; 188 321 } elsif ($req_type eq "byexp") { 189 322 $command .= " -exp_name $id"; 323 $command .= $component_args if $component_args; 324 # don't include -destreaked if lookup is byexp. Let pstampparse check so that the error code gives 325 # the reason as 'not destreaked' 326 $magic_arg = ""; 327 # remove duplicate runs for the same exposure. 328 $filter_runs = 1; 329 } elsif ($req_type eq "byskycell") { 330 die "tess_id and component are required for byskycell" if !$tess_id or ! $skycell_id; 331 $command .= " -tess_id $tess_id -skycell_id $skycell_id"; 190 332 } else { 191 die "Unknown req_type supplied: $req_type"; 192 } 193 194 # run the tool and parse the output 333 # this should be caught by caller 334 &my_die("Unexpected req_type supplied: $req_type", $PS_EXIT_PROG_ERROR); 335 } 336 337 if ($stage ne "stack") { 338 $command .= $magic_arg; 339 $command .= " -dateobs_begin $dateobs_begin" if $dateobs_begin; 340 $command .= " -dateobs_end $dateobs_end" if $dateobs_end; 341 } 342 343 $command .= " -filter $filter" if !isnull($filter); 344 $command .= " -data_group $data_group" if !isnull($data_group); 345 346 my $images = runToolAndParse($command, $verbose); 347 348 if (!$images or scalar @$images == 0) { 349 return undef; 350 } 351 352 if ($filter_runs) { 353 # The image selectors are such that multiple runs my have be returned for the same exposure. 354 # Return only the latest one. 355 $images = filterRuns($stage, $need_magic, $images, $verbose); 356 } 357 if ($choose_components) { 358 # the list of "images" is actually a list of "Runs" 359 # match the coords in the rows to the components in the runs 360 # returns an actual list of images 361 $images = selectComponents($ipprc, $imagedb, $req_type, $stage, $rowList, $images, $verbose); 362 } else { 363 # put each of the rows into all of the the images 364 setRowRefs($rowList, $images); 365 } 366 367 my $camera; 368 my $output = []; 369 foreach my $image (@$images) { 370 my $base; 371 372 next if $image->{fault}; 373 next if ($stage ne "raw") and $image->{quality}; 374 375 if ($base_name) { 376 $base = $image->{$base_name}; 377 # if base is undef then the output pruducts for this image are incomplete 378 # This may only happen for warps. (Actually the test for ignored that I added 379 # just above probably solved the problem I was trying to solve with this test) 380 next if !$base; 381 } else { 382 # raw images don't have path_base yet. Manufacture one 383 my $uri = $image->{uri}; 384 my $path_base = $uri =~ s/\.fits//g; 385 $image->{$path_base} = $path_base; 386 } 387 if (!$camera) { 388 # This assumes that all images have the same camera 389 $camera = $image->{camera}; 390 $ipprc->define_camera($camera); 391 } 392 my $out = $image; 393 394 # if uri is nil this will get overridded below 395 # (we do this here for raw stage) 396 $out->{image} = $image->{uri}; 397 398 if ($set_class_id) { 399 $class_id = $image->{class_id}; 400 $out->{component} = $class_id; 401 } else { 402 $out->{component} = $image->{skycell_id}; 403 } 404 my $stage_id; 405 if ($stage eq "raw") { 406 $stage_id = $image->{exp_id}; 407 } elsif ($stage eq "chip") { 408 $stage_id = $image->{chip_id}; 409 } elsif ($stage eq "warp") { 410 $stage_id = $image->{warp_id}; 411 } elsif ($stage eq "diff") { 412 $stage_id = $image->{diff_id}; 413 if ($inverse && $image->{bothways}) { 414 $image_name = "PPSUB.INVERSE"; 415 $mask_name = "PPSUB.INVERSE.MASK"; 416 $weight_name = "PPSUB.INVERSE.VARIANCE"; 417 $cmf_name = "PPSUB.INVERSE.SOURCES"; 418 } 419 } elsif ($stage eq "stack") { 420 $stage_id = $image->{stack_id}; 421 } 422 $out->{stage_id} = $stage_id; 423 $out->{stage} = $stage; 424 $out->{imagedb} = $imagedb; 425 426 if ($base) { 427 $out->{image} = $ipprc->filename($image_name, $base, $class_id) if $image_name; 428 $out->{mask} = $ipprc->filename($mask_name, $base, $class_id) if $mask_name; 429 $out->{weight} = $ipprc->filename($weight_name, $base, $class_id) if $weight_name; 430 $out->{cmf} = $ipprc->filename($cmf_name, $base, $class_id) if $cmf_name; 431 $out->{psf} = $ipprc->filename($psf_name, $base, $class_id) if $psf_name; 432 $out->{backmdl}= $ipprc->filename($backmdl_name, $base, $class_id) if $backmdl_name; 433 } 434 if ($want_astrom and ! defined $out->{astrom}) { 435 $out->{astrom} = find_astrometry($ipprc, $imagedb, $image, $verbose); 436 } 437 438 push @$output, $out; 439 } 440 441 return $output; 442 } 443 444 sub lookup_diff { 445 my $ipprc = shift; 446 my $rowList = shift; 447 my $imagedb = shift; 448 my $id = shift; 449 my $skycell_id = shift; 450 my $byid = shift; 451 my $option_mask = shift; 452 my $img_type = shift; 453 my $verbose = shift; 454 455 my $inverse = $option_mask & $PSTAMP_SELECT_INVERSE; 456 457 my $command = "$difftool -dbname $imagedb"; 458 459 if ($byid) { 460 $command .= " -listrun -diff_id $id"; 461 } else { 462 $command .= " -diffskyfile -diff_skyfile_id $id"; 463 } 464 $command .= " -skycell_id $skycell_id" if $skycell_id; 465 466 my $output = runToolAndParse($command, $verbose); 467 468 my $n = @$output; 469 if (!$byid && ($n > 1)) { 470 die ("difftool returned an unexpected number of diffskyfiles: $n"); 471 } elsif ($n == 0) { 472 return undef; 473 } 474 475 my $images; 476 if ($byid) { 477 $images = selectComponents($ipprc, $imagedb, 'byid', 'diff', $rowList, $output, $verbose); 478 } else { 479 $images = $output; 480 } 481 482 my @results; 483 foreach my $image (@$images) { 484 my $skycell_id = $image->{skycell_id}; 485 486 if ($image->{fault}) { 487 print STDERR "selected difference image $id $image->{diff_id} $skycell_id has fault: $image->{fault}\n"; 488 next; 489 } 490 491 # The standard way to do a diff is warp - stack 492 # so we interpret the requested image in that way 493 494 # XXX difftool currently returns max long long for null 495 # these checks are ready if we switch the code to return zero for null 496 my $stack1 = $image->{stack1}; 497 if (($stack1 == 0) or ($stack1 == 9223372036854775807)) { 498 $stack1 = undef 499 } 500 my $stack2 = $image->{stack2}; 501 if (($stack2 == 0) or ($stack2 == 9223372036854775807)) { 502 $stack2 = undef 503 } 504 my $stack_id; 505 if ($stack1 and $stack2) { 506 # we have a stack - stack diff (well it might be stack - warp....) 507 # but at any rate we only handle image type diff and stack 508 if (($img_type ne "diff") and ($img_type ne "stack")) { 509 print STDERR "lookup_diff: cannot lookup IMG_TYPE $img_type bydiff from a stack stack diff run\n"; 510 next; 511 } 512 # stack-stack diff 513 # XXX: define another flag for this 514 if (! $inverse) { 515 $stack_id = $stack1; 516 } else { 517 $stack_id = $stack2; 518 } 519 $image->{stack_id} = $stack_id; 520 } else { 521 my ($warp_id, $exp_id, $exp_name, $chip_id, $cam_id); 522 if ($inverse and !$image->{bothways}) { 523 print STDERR "Inverse images requested for diffRun that is not bothways. Ignoring inverse.\n"; 524 $inverse = 0; 525 } 526 if ($inverse) { 527 $warp_id = $image->{warp2}; 528 $exp_id = $image->{exp_id_2}; 529 $exp_name = $image->{exp_name_2}; 530 $chip_id = $image->{chip_id_2}; 531 $cam_id = $image->{cam_id_2}; 532 } else { 533 $warp_id = $image->{warp1}; 534 $exp_id = $image->{exp_id_1}; 535 $exp_name = $image->{exp_name_1}; 536 $chip_id = $image->{chip_id_1}; 537 $cam_id = $image->{cam_id_1}; 538 } 539 # XXX difftool currently returns max long long for null 540 # this line is ready if we switch the code to return zero for null 541 if ($warp_id and ($warp_id != 9223372036854775807)) { 542 $image->{warp_id} = $warp_id; 543 $image->{exp_id} = $exp_id; 544 $image->{exp_name} = $exp_name; 545 $image->{chip_id} = $chip_id; 546 $image->{cam_id} = $cam_id; 547 } 548 } 549 550 # XXX: If difftool doesn't return a camera insert it here 551 if (!$image->{camera}) { 552 $image->{camera} = "GPC1"; 553 # lie about the magicked status since stack stack diffs don't require destreaking 554 # we can remove this once diff_mode gets included 555 $image->{magicked} = 42; 556 } 557 558 if ($img_type eq "diff") { 559 my @imageList = ($image); 560 561 setRowRefs($rowList, \@imageList); 562 # the $image is going to be returned directly in this case so we need to duplicate 563 # some of processing that lookup does for other img_types 564 if ($image->{camera}) { 565 $ipprc->define_camera($image->{camera}); 566 my $filerule_base = $inverse ? "PPSUB.INVERSE" : "PPSUB.OUTPUT"; 567 $image->{image} = $ipprc->filename($filerule_base, $image->{path_base}); 568 $image->{mask} = $ipprc->filename($filerule_base . ".MASK", $image->{path_base}); 569 $image->{weight} = $ipprc->filename($filerule_base . ".VARIANCE", $image->{path_base}); 570 $image->{cmf} = $ipprc->filename($filerule_base . ".SOURCES", $image->{path_base}); 571 $image->{psf} = $ipprc->filename("PSPHOT.PSF.SKY.SAVE", $image->{path_base}); 572 $image->{stage_id} = $image->{diff_id}; 573 $image->{stage} = "diff"; 574 $image->{imagedb} = $imagedb; 575 $image->{component} = $image->{skycell_id}; 576 } else { 577 # XXX this will only happen if the minuend is not a warp. See hack above 578 print STDERR "WARNING: cannot resolve camera so cannot get resolve file rules\n"; 579 next; 580 } 581 } 582 push @results, $image; 583 } 584 return \@results; 585 } 586 587 sub lookup_bycoord { 588 my $ipprc = shift; 589 my $rowList = shift; 590 my $imagedb = shift; 591 my $img_type = shift; 592 my $tess_id = shift; 593 my $component = shift; 594 my $need_magic = shift; 595 my $ra = shift; 596 my $dec = shift; 597 my $dateobs_begin = shift; 598 my $dateobs_end = shift; 599 my $filter = shift; 600 my $data_group = shift; 601 my $option_mask = shift; 602 my $verbose = shift; 603 604 my $results = (); 605 if (($img_type eq "raw") or ($img_type eq "chip")) { 606 607 my $runs = lookup_runs_by_cam_id_and_coords($ipprc, $imagedb, $img_type, 608 $ra, $dec, $need_magic, $dateobs_begin, $dateobs_end, $filter, $data_group, $verbose); 609 610 # lookup is going to filter these we don't need to do it here 611 # $runs = filterRuns($img_type, $need_magic, $runs, $verbose); 612 foreach my $run (@$runs) { 613 next if $component and ($run->{component} ne $component); 614 my $these_results = lookup($ipprc, $rowList, $imagedb, "byid", $img_type, $run->{id}, 615 $tess_id, $run->{component}, $need_magic, 616 $dateobs_begin, $dateobs_end, $filter, $data_group, $option_mask, $verbose); 617 618 next if !$these_results; 619 push @$results, @$these_results; 620 } 621 622 } else { 623 # this should be checked elsewhere 624 die "unexpected image type $img_type" if ($img_type ne "warp") 625 and ($img_type ne "stack") and ($img_type ne "diff"); 626 627 my $skycells = lookup_skycell_by_coords($ipprc, $tess_id, $component, $ra, $dec, $verbose); 628 629 foreach my $skycell (@$skycells) { 630 my $these_results = lookup($ipprc, $rowList, $imagedb, "byskycell", $img_type, undef, 631 $skycell->{tess_id}, $skycell->{component}, $need_magic, 632 $dateobs_begin, $dateobs_end, $filter, $data_group, $option_mask, $verbose); 633 634 next if !$these_results; 635 push @$results, @$these_results; 636 } 637 } 638 639 return $results; 640 } 641 642 # lookup_runs_by_cam_id_and_coords 643 # given an ra, dec, and optionally other paramters, find camera runs for exposures 644 # that are within some distance of the coordinates 645 sub lookup_runs_by_cam_id_and_coords { 646 my $ipprc = shift; 647 my $imagedb = shift; 648 my $img_type = shift; 649 my $ra = shift; 650 my $dec = shift; 651 my $need_magic = shift; 652 my $dateobs_begin = shift; 653 my $dateobs_end = shift; 654 my $filter = shift; 655 my $data_group = shift; 656 my $verbose = shift; 657 658 my $camruns; 659 660 { 661 my $command = "$camtool -dbname $imagedb -processedexp -pstamp_order"; 662 $command .= " -ra $ra -decl $dec -radius 1.6"; 663 $command .= " -dateobs_begin $dateobs_begin" if $dateobs_begin; 664 $command .= " -dateobs_end $dateobs_end" if $dateobs_end ; 665 $command .= " -filter $filter" if $filter; 666 # NOTE: we are applying the data_group to the camera run. 667 # If we're looking for chip stage images there is no guarentee that 668 # chipRun.data_group = camRun.data_group. In practice this is almost 669 # always the case. If this turns out to be a problem we can defer 670 # the data_group test to when we look up the chipProcessedImfiles 671 $command .= " -data_group $data_group" if $data_group; 672 $command .= " -destreaked" if $need_magic; 673 674 # run the tool and parse the output 675 $camruns = runToolAndParse($command, $verbose); 676 } 677 if (!$camruns) { 678 return undef; 679 } 680 my $runs; 681 my $last_exp_id = 0; 682 foreach my $camRun (@$camruns) { 683 my $cam_id = $camRun->{cam_id}; 684 my $exp_id = $camRun->{exp_id}; 685 686 next if $exp_id eq $last_exp_id; 687 688 next if $camRun->{quality}; 689 next if $camRun->{fault}; 690 691 updateCamRunCache($camRun); 692 693 $last_exp_id = $exp_id; 694 695 # XXX Use file rule 696 my $astrom = $camRun->{path_base} . ".smf"; 697 my $astrom_resolved = $ipprc->file_resolve($astrom); 698 next if !$astrom_resolved; 699 700 my $start_dvo = DateTime->now->mjd; 701 my $command = "$dvoImagesAtCoords -astrom $astrom_resolved $ra $dec"; 702 # run the tool and parse the output 703 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = 704 run(command => $command, verbose => $dvo_verbose); 705 my $dtime_dvo = (DateTime->now->mjd - $start_dvo)* 86400.; 706 # print "Time to run dvoImagesAtCoords: $dtime_dvo\n"; 707 unless ($success) { 708 my $result_code = $error_code >> 8; 709 if ($result_code == $PSTAMP_NO_OVERLAP) { 710 print "no overlap for $astrom\n" if $verbose; 711 next; 712 } 713 # unexpected result code 714 die "unexpected result code: $result_code from $command\n"; 715 } 716 717 my $output = join "", @$stdout_buf; 718 if (!$output) { 719 # this shouldn't happen when dvoImagesAtCoord exits with zero status 720 die "no output returned from $command\n"; 721 } 722 723 # dvoImagesAtCoords should return a single line 724 # rownum ra dec class_id 725 my @lines = split "\n", $output; 726 my $n = scalar @lines; 727 if ($n != 1) { 728 print STDERR "unexpected number of lines returned by dvoImagesAtCoords: $n\n"; 729 730 # XXX: There is a bug in dvo where each component is listed twice 731 # When that gets fixed remove the conditional and just die 732 die "unexpected number lines returned by dvoImagesAtCoords: $n" 733 if ($n != 2) or ($lines[0] ne $lines[1]); 734 } 735 736 my (undef, $ra_out, $dec_out, $class_id) = split " ", $lines[0]; 737 if (!$class_id) { 738 die "unexpected output from dvoImagesAtCoords: $lines[0]"; 739 } 740 741 print "cam_id $cam_id exp_id $camRun->{exp_id} chip_id $camRun->{chip_id} $class_id\n"; 742 743 # build the hash to return 744 my $run = { 745 exp_id => $camRun->{exp_id}, 746 exp_name => $camRun->{exp_name}, 747 chip_id => $camRun->{chip_id}, 748 cam_id => $camRun->{cam_id}, 749 astrom => $astrom_resolved, 750 class_id => $class_id, 751 component => $class_id 752 }; 753 if ($img_type eq "chip") { 754 $run->{id} = $camRun->{chip_id}; 755 $run->{state} = $camRun->{chip_state}; 756 $run->{magicked} = $camRun->{chip_magicked}; 757 } else { 758 $run->{id} = $camRun->{exp_id}; 759 $run->{state} = 'full'; 760 $run->{magicked} = $camRun->{raw_magicked}; 761 } 762 push @$runs, $run; 763 } 764 765 return $runs; 766 } 767 768 sub lookup_skycell_by_coords { 769 my $ipprc = shift; 770 my $requested_tess_id = shift; 771 my $requested_skycell = shift; 772 my $ra = shift; 773 my $dec = shift; 774 my $verbose = shift; 775 776 $requested_tess_id = "" if isnull($requested_tess_id); 777 $requested_skycell = "" if isnull($requested_skycell); 778 779 my @lines; 780 { 781 my $command = "$whichimage $ra $dec"; 782 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = 783 run(command => $command, verbose => $verbose); 784 unless ($success) { 785 print STDERR @$stderr_buf; 786 return undef; 787 } 788 789 my $output = join "", @$stdout_buf; 790 if (!$output) { 791 print STDERR "no output returned from $command\n" if $verbose; 792 return undef; 793 } 794 @lines = split "\n", $output; 795 if (!scalar @lines) { 796 # can this happen? if $output is not null? 797 print STDERR "no output returned from $command\n" if $verbose; 798 return undef; 799 } 800 } 801 my $runs; 802 foreach my $line (@lines) { 803 my ($ra_out, $dec_out, $tess_id, $skycell_id) = split " ", $line; 804 die "unexpected output from whichimage" if !$tess_id or !$skycell_id; 805 806 if ($requested_tess_id) { 807 next if ($requested_tess_id ne $tess_id); 808 } else { 809 # skip these obsolete tesselations unless they were explicitly asked for 810 # should I do this? 811 next if $tess_id eq "FIXNS"; 812 next if $tess_id eq "ALLSKY"; 813 } 814 next if $requested_skycell and ($skycell_id ne $requested_skycell); 815 816 # build the hash to return 817 my $run = { 818 tess_id => $tess_id, 819 component => $skycell_id, 820 }; 821 push @$runs, $run; 822 } 823 824 return $runs; 825 } 826 827 # cache of results of ppConfigDump 828 my %astromSources; 829 my $last_exp_id = 0; 830 my $lastAstromFile; 831 832 # find the astrometry file for a given exposure 833 # return undef if no completed camRun exists 834 sub find_astrometry { 835 my $ipprc = shift; 836 my $imagedb = shift; 837 my $image = shift; # hashref to output of the lookup tool 838 my $verbose = shift; 839 840 my $mdcParser; 841 842 my $exp_id = $image->{exp_id}; 843 if (($exp_id eq $last_exp_id) and $lastAstromFile) { 844 # running camtool 60 times is really expensive when the answer is the same every time 845 return $lastAstromFile; 846 } 847 $last_exp_id = 0; 848 $lastAstromFile = undef; 849 850 my $camRun = getCamRunByExpID($exp_id); 851 if (!$camRun) { 852 my $command = "$camtool -dbname $imagedb -processedexp -exp_id $exp_id -pstamp_order"; 853 # run the tool and parse the output 854 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = 855 run(command => $command, verbose => $verbose); 856 unless ($success) { 857 print STDERR @$stderr_buf; 858 return undef; 859 } 860 861 $mdcParser = PS::IPP::Metadata::Config->new; # Parser for metadata config files 862 863 my $output = join "", @$stdout_buf; 864 if (!$output) { 865 print STDERR "no output returned from $command\n" if $verbose; 866 return undef; 867 } 868 my $camruns = parse_md_fast($mdcParser, $output); 869 if (!$camruns) { 870 return undef; 871 } 872 873 # If there are multiple cam runs for this exposure, take the last completed one with good quality 874 # on the assumption that it has the best astrometry. 875 foreach $camRun (@$camruns) { 876 last if (($camRun->{state} eq 'full') and ($camRun->{quality} eq 0) and ($camRun->{fault} eq 0)); 877 } 878 # XXX: this looks like a bug at least if ASTROM.SOURCE eq PSASTRO.OUTPUT 879 if (!$camRun) { 880 # no cam runs for this exposure id therefore best astrometry is whatever is in the header 881 return undef; 882 } 883 updateCamRunCache($camRun); 884 } 885 my $camRoot = $camRun->{path_base}; 886 my $camera = $image->{camera}; 887 my $astromSource = $astromSources{$camera}; 888 if (!$astromSource) { 889 if ($camera eq "GPC1") { 890 # CHEATER ! 891 $astromSource = "PSASTRO.OUTPUT"; 892 } else { 893 my $command = "$ppConfigDump -camera $camera -dump-recipe PSWARP -"; 894 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = 895 run(command => $command, verbose => $verbose); 896 unless ($success) { 897 $error_code = (($error_code >> 8) or $PS_EXIT_PROG_ERROR); 898 die("Unable to perform ppConfigDump: $error_code"); 899 } 900 $mdcParser = PS::IPP::Metadata::Config->new if !$mdcParser; # Parser for metadata config files 901 my $metadata = $mdcParser->parse(join "", @$stdout_buf) or 902 die("Unable to parse metadata config doc"); 903 $astromSource = metadataLookupStr($metadata, 'ASTROM.SOURCE'); 904 } 905 $astromSources{$camera} = $astromSource; 906 } 907 908 # XXX: Is this code correct if ASTROM.SOURCE ne "PSASTRO.OUTPUT" 909 my $astromFile = $ipprc->filename($astromSource, $camRoot); 910 if ($astromFile) { 911 $lastAstromFile = $astromFile; 912 $last_exp_id = $exp_id; 913 } 914 915 return $astromFile; 916 } 917 918 # splits meta data config input stream into single units to work around the pathalogically 919 # slow parser. This is similar to and adapted from code in various ippScripts. 920 sub parse_md_fast { 921 my $mdcParser = shift; 922 my $input = shift; 923 my $output = (); 924 925 my @whole = split /\n/, $input; 926 my @single = (); 927 928 my $n; 929 while ( ($n = @whole) > 0) { 930 my $value = shift @whole; 931 push @single, $value; 932 if ($value =~ /^\s*END\s*$/) { 933 push @single, "\n"; 934 935 my $list = parse_md_list( $mdcParser->parse( join("\n", @single ) ) ) or 936 print STDERR "Unable to parse metdata config doc" and return undef; 937 # my $num = @$list; 938 # print STDERR "list has $num elments\n"; 939 push @$output, $list->[0]; 940 941 @single = (); 942 } 943 } 944 return $output; 945 } 946 947 sub mjd_to_dateobs { 948 my $mjd = shift; 949 950 my $ticks = ($mjd - 40587.0) * 86400; 951 952 my ($sec, $min, $hr, $day, $mon, $year) = gmtime($ticks); 953 954 return sprintf "'%4d-%02d-%02dT%02d:%02d:%02dZ'", $year+1900, $mon+1, $day, $hr, $min, $sec; 955 } 956 957 sub isnull { 958 my $val = shift; 959 960 return (!defined($val) or ($val eq "") or (lc($val) eq "null")); 961 } 962 963 sub iszero { 964 my $val = shift; 965 return (!defined($val) or ($val == 0)); 966 } 967 968 # resolve_project() 969 # get project specific information 970 sub resolve_project { 971 my $ipprc = shift; 972 my $project_name = shift; 973 974 findTools(); 975 976 if (!$project_name) { 977 carp ("project is not defined"); 978 return undef; 979 } 980 981 if ($last_project and ($project_name eq ($last_project->{name}))) { 982 return $last_project; 983 } 984 985 my $dbname = shift; 986 my $dbserver = shift; 987 988 my $verbose = 0; 989 990 my $command = "$pstamptool -project -name $project_name"; 991 $command .= " -dbname $dbname" if defined $dbname; 992 $command .= " -dbserver $dbserver" if defined $dbserver; 993 994 my $proj_hash = runToolAndParse($command, $verbose); 995 if (!$proj_hash or scalar @$proj_hash == 0) { 996 print STDERR "Project $project_name not found\n"; 997 return undef; 998 } 999 1000 $last_project = $proj_hash->[0]; 1001 1002 return $last_project; 1003 } 1004 1005 sub updateCamRunCache { 1006 my $camRun = shift; 1007 die "updateCamRunCache: camRun is nil" if !$camRun; 1008 1009 my $exp_id = $camRun->{exp_id}; 1010 die "updateCamRunCache: exp_id is nil" if !$exp_id; 1011 1012 my $cam_id = $camRun->{cam_id}; 1013 die "updateCamRunCache: cam_id is nil" if !$cam_id; 1014 1015 $camRunByCamIDCache{$cam_id} = $camRun; 1016 1017 # if this camRun is newer than previous update the cache. 1018 # This assumes that the newest has the "best" astrometry 1019 my $previous = $camRunByExpIDCache{$exp_id}; 1020 if ($previous) { 1021 my $previous_cam_id = $previous->{cam_id}; 1022 return if $cam_id < $previous_cam_id; 1023 } 1024 1025 $camRunByExpIDCache{$exp_id} = $camRun; 1026 } 1027 1028 sub getCamRunByExpID { 1029 my $exp_id = shift; 1030 &my_die ("getCamRun: exp_id is nil", $PS_EXIT_PROG_ERROR) if !$exp_id; 1031 1032 return $camRunByExpIDCache{$exp_id}; 1033 } 1034 1035 sub getCamRunByCamID { 1036 my $cam_id = shift; 1037 &my_die ("getCamRun: cam_id is nil", $PS_EXIT_PROG_ERROR) if !$cam_id; 1038 1039 return $camRunByCamIDCache{$cam_id}; 1040 } 1041 1042 sub selectComponents { 1043 my $ipprc = shift; 1044 my $imagedb = shift; 1045 my $req_type = shift; 1046 my $stage = shift; 1047 my $rowList = shift; 1048 my $runList = shift; 1049 my $verbose = shift; 1050 my $results = []; 1051 1052 my ($pointsList, $pointsListName) = tempfile ("/tmp/pointsList.XXXX", UNLINK => !$save_temps); 1053 my $npoints = 0; 1054 foreach my $row (@$rowList) { 1055 print $pointsList "$npoints $row->{CENTER_X} $row->{CENTER_Y}\n"; 1056 $npoints++; 1057 } 1058 close $pointsList; 1059 1060 # XXX: need to loop over these 1061 # my $run = $runList->[0]; 1062 if (($req_type eq "byid") or ($req_type eq "byexp")) { 1063 my ($last_tess_id, $tess_dir_abs, $astrom_file) = ("", "", ""); 1064 foreach my $run (@$runList) { 1065 my $command = "$dvoImagesAtCoords -coords $pointsListName"; 1066 if (($stage eq "chip") or ($stage eq "raw")) { 1067 # XXX: use file rule and handle cameras where the astrometry is solved at 1068 # the chip stage. 1069 $astrom_file = $run->{cam_path_base} . ".smf"; 1070 my $astrom_file_resolved = $ipprc->file_resolve($astrom_file); 1071 $command .= " -astrom $astrom_file_resolved"; 1072 } else { 1073 my $tess_id = $run->{tess_id}; 1074 if ($tess_id ne $last_tess_id) { 1075 $tess_dir_abs = $ipprc->tessellation_catdir( $tess_id ); 1076 $tess_dir_abs = $ipprc->convert_filename_absolute( $tess_dir_abs ); 1077 $last_tess_id = $tess_id; 1078 } 1079 $command .= " -D CATDIR $tess_dir_abs" 1080 } 1081 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = 1082 run(command => $command, verbose => $dvo_verbose); 1083 unless ($success) { 1084 # don't fail if the program exited normally and exit status was PSTAMP_NO_OVERLAP 1085 # # That just means that the coordinate didn't match any image/skycell 1086 if (!WIFEXITED($error_code) || (WEXITSTATUS($error_code) ne $PSTAMP_NO_OVERLAP)) { 1087 print STDERR @$stderr_buf; 1088 my $rc = WIFEXITED($error_code) ? WEXITSTATUS($error_code) : $PS_EXIT_SYS_ERROR; 1089 &my_die( "dvoImagesAtCoords failed: $rc", $rc); 1090 } 1091 } 1092 my %components; 1093 my @lines = split "\n", join "", @$stdout_buf; 1094 foreach my $line (@lines) { 1095 my ($ptnum, undef, undef, $component) = split " ", $line; 1096 my $ref = $components{$component}; 1097 if (!$ref) { 1098 $ref = $components{$component} = []; 1099 } 1100 push @$ref, $ptnum; 1101 } 1102 if ($verbose) { 1103 foreach my $c (keys %components) { 1104 my $ref = $components{$c}; 1105 print "component $c contains: "; 1106 foreach my $i (@$ref) { 1107 print "$i "; 1108 } 1109 print "\n"; 1110 } 1111 } 1112 # now find the images for this run 1113 foreach my $c (keys %components) { 1114 my $command; 1115 my $stage_id; 1116 if ($stage eq 'raw') { 1117 $stage_id = $run->{exp_id}; 1118 $command = "$regtool -processedimfile -exp_id $stage_id -class_id $c"; 1119 } elsif ($stage eq 'chip') { 1120 $stage_id = $run->{chip_id}; 1121 $command = "$chiptool -processedimfile -chip_id $stage_id -class_id $c"; 1122 } elsif ($stage eq 'warp') { 1123 $stage_id = $run->{warp_id}; 1124 $command = "$warptool -warped -warp_id $stage_id -skycell_id $c"; 1125 } elsif ($stage eq 'diff') { 1126 $stage_id = $run->{diff_id}; 1127 $command = "$difftool -diffskyfile -diff_id $stage_id -skycell_id $c"; 1128 } 1129 $command .= " -dbname $imagedb"; 1130 my $images = runToolAndParse($command, $verbose); 1131 if (!defined $images) { 1132 # XXX: need to get the set error_code to $PSTAMP_NO_OVERLAP 1133 print "No components containing coordinates found for ${stage}_id $stage_id\n"; 1134 foreach my $row (@$rowList) { 1135 $row->{error_code} = $PSTAMP_NO_OVERLAP; 1136 } 1137 next; 1138 } 1139 if (scalar @$images != 1) { 1140 my $num_images = scalar @$images; 1141 &my_die ("unexpected number of images returned: $num_images\n", $PS_EXIT_PROG_ERROR); 1142 } 1143 my $image = $images->[0]; 1144 1145 my $ref = $components{$c}; 1146 $image->{row_index} = $ref; 1147 if (($stage eq "raw") or ($stage eq 'chip')) { 1148 $image->{astrom} = $astrom_file; 1149 $image->{cam_id} = $run->{cam_id}; 1150 $image->{cam_path_base} = $run->{cam_path_base}; 1151 } 1152 push @$results, $image; 1153 } 1154 } 1155 } else { 1156 &my_die ("sorry not done with $req_type\n", $PS_EXIT_PROG_ERROR); 1157 } 1158 return $results; 1159 } 1160 1161 sub filterRuns { 1162 my $stage = shift; 1163 my $need_magic = shift; 1164 my $inputs = shift; 1165 my $verbose = shift; 1166 1167 if ($inputs and (scalar @$inputs) == 1) { 1168 # one run nothing to do 1169 return $inputs; 1170 } 1171 1172 my $output = []; 1173 1174 return $output if (!$inputs or scalar @$inputs == 0); 1175 1176 my $id_name = $stage . "_id"; 1177 1178 # input list is "order by exp_id, run_id DESC" run_id is one of (chip_id, warp_id, diff_id) 1179 print "Starting filterRuns\n"; 1180 my $last_exp_id = 0; 1181 my $last_run_id = 0; 1182 my $printed = 0; 1183 foreach my $input (@$inputs) { 1184 my $exp_id = $input->{exp_id}; 1185 my $run_id = $input->{$id_name}; 1186 my $magicked = $input->{magicked}; # this will be either stageRun.magicked or stage%file.magicked 1187 my $state = $input->{state}; 1188 1189 # can't process run in these states 1190 if (($state eq 'new') or ($state eq 'purged') or ($state eq 'scrubbed')) { 1191 print "skipping ${stage}Run $run_id for exp_id $exp_id in state $state\n"; 1192 next; 1193 } 1194 1195 $printed = 1 if (($exp_id == $last_exp_id) and ($run_id == $last_run_id)); 1196 1197 # skip if we need magicked run and this one has never been magicked 1198 if ($need_magic and !$magicked) { 1199 print "skipping ${stage}Run $run_id for exp_id $exp_id not magicked\n" if !$printed; 1200 next; 1201 } 1202 1203 if (($exp_id == $last_exp_id) and ($run_id != $last_run_id)) { 1204 print "Skipping duplicate ${stage}Run $run_id for $exp_id\n" if !$printed; 1205 next; 1206 } 1207 print "Keeping ${stage}Run $run_id for $exp_id\n"; 1208 push @$output, $input; 1209 $last_exp_id = $exp_id; 1210 $last_run_id = $run_id; 1211 $printed = 0; 1212 } 1213 1214 my $num_runs = scalar @$output; 1215 print "filterRuns returning $num_runs ${stage}Run\n"; 1216 1217 return $output; 1218 } 1219 1220 # run a command that produces metadata output and parse the results into an array of objects 1221 sub runToolAndParse { 1222 my $command = shift; 1223 my $verbose = shift; 1224 1225 my ($program) = split " ", $command; 1226 $program = basename($program); 1227 1228 print "Running $command\n" if !$verbose; 1229 my $start_tool = DateTime->now->mjd; 1230 # run the command and parse the output 1231 195 1232 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = 196 1233 run(command => $command, verbose => $verbose); … … 201 1238 } 202 1239 1240 my $now = DateTime->now->mjd; 1241 my $dtime_tool = (DateTime->now->mjd - $start_tool) * 86400.; 1242 print "Time to run $program: $dtime_tool\n"; 1243 203 1244 my $buf = join "", @$stdout_buf; 204 1245 if (!$buf) { 205 return; 206 } 1246 return undef; 1247 } 1248 1249 my $start_parse = DateTime->now->mjd; 207 1250 208 1251 my $mdcParser = PS::IPP::Metadata::Config->new; 209 my $ images = parse_md_fast($mdcParser, $buf)1252 my $results = parse_md_fast($mdcParser, $buf) 210 1253 or die ("Unable to parse metadata config doc"); 211 1254 212 my $output = []; 213 214 my $camera; 215 foreach my $image (@$images) { 216 my $base; 217 218 next if $image->{fault}; 219 next if ($img_type ne "raw") and $image->{quality}; 220 221 if ($base_name) { 222 $base = $image->{$base_name}; 223 # if base is undef then the output pruducts for this image are incomplete 224 # This may only happen for warps. (Actually the test for ignored that I added 225 # just above probably solved the problem I was trying to solve with this test) 226 next if !$base; 227 } 228 if (!$camera) { 229 # This assumes that all images have the same camera 230 $camera = $image->{camera}; 231 $ipprc->define_camera($camera); 232 } 233 my $out = $image; 234 235 # if uri is nil this will get overridded below 236 # (this is for raw stage) 237 $out->{image} = $image->{uri}; 238 if ($set_class_id) { 239 $class_id = $image->{class_id}; 240 $out->{component} = $class_id; 241 } 242 243 # find the mask and weight images 244 if ($base) { 245 $out->{image} = $ipprc->filename($image_name, $base, $class_id) if $image_name; 246 $out->{mask} = $ipprc->filename($mask_name, $base, $class_id) if $mask_name; 247 $out->{weight} = $ipprc->filename($weight_name, $base, $class_id) if $weight_name; 248 } 249 $out->{astrom} = find_astrometry($ipprc, $image_db, $image, $verbose) if $want_astrom; 250 251 push @$output, $out; 252 } 253 254 return $output; 255 } 256 sub lookup_bydiff { 257 my $ipprc = shift; 258 my $image_db = shift; 259 my $id = shift; 260 my $img_type = shift; 261 my $verbose = shift; 1255 my $dtime_parse = (DateTime->now->mjd - $start_parse) * 86400.; 1256 print "Time to parse results from $program: $dtime_parse\n"; 1257 1258 return $results; 1259 } 1260 1261 sub findTools { 1262 return if ($regtool); 262 1263 263 1264 my $missing_tools; 264 my $difftool = can_run('difftool') or (warn "Can't find difftool" and $missing_tools = 1); 1265 $regtool = can_run('regtool') or (warn "Can't find regtool" and $missing_tools = 1); 1266 $chiptool = can_run('chiptool') or (warn "Can't find chiptool" and $missing_tools = 1); 1267 $camtool = can_run('camtool') or (warn "Can't find camtool" and $missing_tools = 1); 1268 $warptool = can_run('warptool') or (warn "Can't find warptool" and $missing_tools = 1); 1269 $difftool = can_run('difftool') or (warn "Can't find difftool" and $missing_tools = 1); 1270 $stacktool = can_run('stacktool') or (warn "Can't find stacktool" and $missing_tools = 1); 1271 $pstamptool = can_run('pstamptool') or (warn "Can't find pstamptool" and $missing_tools = 1); 1272 $dvoImagesAtCoords = can_run('dvoImagesAtCoords') or (warn "Can't find dvoImagesAtCoords" 1273 and $missing_tools = 1); 1274 $whichimage = can_run('whichimage') or (warn "Can't find whichimage" and $missing_tools = 1); 1275 $ppConfigDump = can_run('ppConfigDump') or (warn "Can't find ppConfigDump" and $missing_tools = 1); 265 1276 if ($missing_tools) { 266 1277 warn("Can't find required tools."); 267 1278 exit ($PS_EXIT_CONFIG_ERROR); 268 1279 } 269 270 my $command = "$difftool -diffskyfile -diff_image_id $id -dbname $image_db"; 271 272 # run the tool and parse the output 273 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = 274 run(command => $command, verbose => $verbose); 275 unless ($success) { 276 # not sure if we should die here 277 print STDERR @$stderr_buf; 278 return undef; 279 } 280 281 my $buf = join "", @$stdout_buf; 282 if (!$buf) { 283 return undef; 284 } 285 286 my $mdcParser = PS::IPP::Metadata::Config->new; 287 my $images = parse_md_fast($mdcParser, $buf) 288 or die ("Unable to parse metadata config doc"); 289 290 my $n = @$images; 291 if ($n > 1) { 292 die ("difftool returned an unexpected number of diffskyfiles: $n"); 293 } elsif ($n == 0) { 294 return undef; 295 } 296 297 my $image = $images->[0]; 298 299 my $skycell_id = $image->{skycell_id}; 300 301 if ($image->{fault}) { 302 print STDERR "selected difference image $id $image->{diff_id} $skycell_id has fault: $image->{fault}\n"; 303 return undef; 304 } 305 306 # The standard way to do a diff is warp - stack 307 # so we interpret the requested image in that way 308 309 my $stack_id = $image->{stack2}; 310 # XXX difftool currently returns max long long for null 311 # this line is ready if we switch the code to return zero for null 312 if ($stack_id and ($stack_id != 9223372036854775807)) { 313 $image->{stack_id} = $stack_id; 314 } 315 316 my $warp_id = $image->{warp1}; 317 # XXX difftool currently returns max long long for null 318 # this line is ready if we switch the code to return zero for null 319 if ($warp_id and ($warp_id != 9223372036854775807)) { 320 $image->{warp_id} = $warp_id; 321 322 ## now use the warp and go get the exposure information 323 $command = "warptool -warped -warp_id $warp_id -skycell_id $skycell_id -dbname $image_db -limit 1"; 324 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = 325 run(command => $command, verbose => $verbose); 326 unless ($success) { 327 # not sure if we should die here 328 print STDERR @$stderr_buf; 329 return undef; 330 } 331 332 my $buf = join "", @$stdout_buf; 333 if (!$buf) { 334 return undef; 335 } 336 337 my $mdcParser = PS::IPP::Metadata::Config->new; 338 my $warps = parse_md_fast($mdcParser, $buf) 339 or die ("Unable to parse metadata config doc"); 340 my $warp = $warps->[0]; 341 342 if ($img_type eq "warp") { 343 $image = $warp; 344 } else { 345 $image->{exp_id} = $warp->{exp_id}; 346 $image->{exp_name} = $warp->{exp_name}; 347 $image->{camera} = $warp->{camera}; 348 } 349 } 350 351 if (($img_type eq "diff") or ($img_type eq "warp")) { 352 # the $image is going to be returned directly in this case so we need to duplicate 353 # some of processing that lookup does for other img_types 354 $image->{image} = $image->{uri}; 355 if ($image->{camera}) { 356 $ipprc->define_camera($image->{camera}); 357 if ($img_type eq "diff") { 358 $image->{mask} = $ipprc->filename("PPSUB.OUTPUT.MASK", $image->{path_base}); 359 $image->{weight} = $ipprc->filename("PPSUB.OUTPUT.VARIANCE", $image->{path_base}); 360 } else { 361 $image->{mask} = $ipprc->filename("PSWARP.OUTPUT.MASK", $image->{path_base}); 362 $image->{weight} = $ipprc->filename("PSWARP.OUTPUT.VARIANCE", $image->{path_base}); 363 } 364 } else { 365 # XXX this will only happen if the minuend is not a warp 366 print STDERR "WARNING: cannot resolve camera so cannot get weight and mask images\n"; 367 } 368 } 369 370 return $image; 371 } 372 373 sub lookup_bycoord { 374 my $ipprc = shift; 375 my $image_db = shift; 376 my $x = shift; 377 my $y = shift; 378 my $mjd_min = shift; 379 my $mjd_max = shift; 380 my $filter = shift; 381 my $verbose = shift; 382 383 my $missing_tools; 384 my $regtool = can_run('regtool') or (warn "Can't find regtool" and $missing_tools = 1); 385 if ($missing_tools) { 386 warn("Can't find required tools."); 387 exit ($PS_EXIT_CONFIG_ERROR); 388 } 389 390 # XXX TODO: 391 # Full lookups by coordinate require looking at the DVO database. However, 392 # dateobs and filter which is all that MOPS has asked for. 393 394 my $args; 395 if ($mjd_min) { 396 my $dateobs_min = mjd_to_dateobs($mjd_min); 397 $args .= " -dateobs_begin $dateobs_min"; 398 } 399 if ($mjd_max) { 400 my $dateobs_max = mjd_to_dateobs($mjd_max); 401 $args .= " -dateobs_end $dateobs_max"; 402 } 403 if ($filter) { 404 $args .= " -filter $filter"; 405 } 406 407 if (!$args) { 408 # avoid returning every exposure in the DB 409 print STDERR "no query arguments provided for bycoord\n"; 410 return undef; 411 } 412 413 # XXX TODO: This query doesn't work Something appears to be out of 414 # sync about the times I'm passing and what regtool and or the DB expect 415 # the query I used in the C version of locateimages used 416 # WHERE dateobs >= FROM_UNIXTIME(%ld) AND dateobs <= FROM_UNIXTIME(%ld + exp_time) 417 418 my $command = "$regtool -processedexp -dbname $image_db $args"; 419 420 # run the tool and parse the output 421 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = 422 run(command => $command, verbose => $verbose); 423 unless ($success) { 424 # not sure if we should die here 425 print STDERR @$stderr_buf; 426 return undef; 427 } 428 my $mdcParser = PS::IPP::Metadata::Config->new; # Parser for metadata config files 429 430 my $output = join "", @$stdout_buf; 431 if (!$output) { 432 print STDERR "no output returned from $command\n" if $verbose; 433 return undef; 434 } 435 my $images = parse_md_fast($mdcParser, $output) or die ("Unable to parse metadata config doc"); 436 437 return $images; 438 } 439 440 # cache of results of ppConfigDump 441 my %astromSources; 442 my $last_exp_id = 0; 443 my $lastAstromFile; 444 445 # find the astrometry file for a given exposure 446 # return undef if no completed camRun exists 447 sub find_astrometry { 448 my $ipprc = shift; 449 my $image_db = shift; 450 my $image = shift; # hashref to output of the lookup tool 451 my $verbose = shift; 452 453 my $exp_id = $image->{exp_id}; 454 if (($exp_id eq $last_exp_id) and $lastAstromFile) { 455 # running camtool 60 times is really expensive when the answer is the same 456 return $lastAstromFile; 457 } 458 $last_exp_id = 0; 459 $lastAstromFile = undef; 460 461 my $missing_tools; 462 my $camtool = can_run("camtool") or (warn "Can't find camtool" and $missing_tools = 1); 463 my $ppConfigDump = can_run('ppConfigDump') or (warn "Can't find ppConfigDump" and $missing_tools = 1); 464 if ($missing_tools) { 465 warn("Can't find required tools."); 466 exit ($PS_EXIT_CONFIG_ERROR); 467 } 468 469 my $command = "$camtool -dbname $image_db -processedexp -exp_id $exp_id"; 470 # run the tool and parse the output 471 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = 472 run(command => $command, verbose => $verbose); 473 unless ($success) { 474 print STDERR @$stderr_buf; 475 return undef; 476 } 477 478 my $mdcParser = PS::IPP::Metadata::Config->new; # Parser for metadata config files 479 480 my $output = join "", @$stdout_buf; 481 if (!$output) { 482 print STDERR "no output returned from $command\n" if $verbose; 483 return undef; 484 } 485 my $camruns = parse_md_fast($mdcParser, $output); 486 if (!$camruns) { 487 return undef; 488 } 489 490 # If there are multiple cam runs for this exposure, take the last one 491 # assuming that it has the best astrometry 492 my $camdata = pop @$camruns; 493 if (!$camdata) { 494 # no cam runs for this exposure id therefore best astrometry is whatever is in the header 495 return undef; 496 } 497 my $camRoot = $camdata->{path_base}; 498 my $camera = $image->{camera}; 499 my $astromSource = $astromSources{$camera}; 500 if (!$astromSource) { 501 my $command = "$ppConfigDump -camera $camera -dump-recipe PSWARP -"; 502 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = 503 run(command => $command, verbose => $verbose); 504 unless ($success) { 505 $error_code = (($error_code >> 8) or $PS_EXIT_PROG_ERROR); 506 die("Unable to perform ppConfigDump: $error_code"); 507 } 508 my $metadata = $mdcParser->parse(join "", @$stdout_buf) or 509 die("Unable to parse metadata config doc"); 510 $astromSource = metadataLookupStr($metadata, 'ASTROM.SOURCE'); 511 $astromSources{$camera} = $astromSource; 512 } 513 514 my $astromFile = $ipprc->filename($astromSource, $camRoot); 515 if ($astromFile) { 516 $lastAstromFile = $astromFile; 517 $last_exp_id = $exp_id; 518 } 519 520 return $astromFile; 521 } 522 523 # splits meta data config input stream into single units to work around the pathalogically 524 # slow parser. This is similar to and adapted from code in various ippScripts. 525 sub parse_md_fast { 526 my $mdcParser = shift; 527 my $input = shift; 528 my $output = (); 529 530 my @whole = split /\n/, $input; 531 my @single = (); 532 533 my $n; 534 while ( ($n = @whole) > 0) { 535 my $value = shift @whole; 536 push @single, $value; 537 if ($value =~ /^\s*END\s*$/) { 538 push @single, "\n"; 539 540 my $list = parse_md_list( $mdcParser->parse( join("\n", @single ) ) ) or 541 print STDERR "Unable to parse metdata config doc" and return undef; 542 # my $num = @$list; 543 # print STDERR "list has $num elments\n"; 544 push @$output, $list->[0]; 545 546 @single = (); 547 } 548 } 549 return $output; 550 } 551 552 sub mjd_to_dateobs { 553 my $mjd = shift; 554 555 my $ticks = ($mjd - 40587.0) * 86400; 556 557 my ($sec, $min, $hr, $day, $mon, $year) = gmtime($ticks); 558 559 return sprintf "'%4d-%02d-%02d %02d:%02d:%02d'", $year+1900, $mon+1, $day, $hr, $min, $sec; 560 } 561 562 # resolve_project() 563 # get project specific information 564 my $last_project = ""; 565 sub resolve_project { 566 my $ipprc = shift; 567 my $project_name = shift; 568 569 if (!$project_name) { 570 carp ("project is not defined"); 571 return undef; 572 } 573 574 if ($project_name eq $last_project) { 575 return $last_project; 576 } 577 578 my $dbname = shift; 579 my $dbserver = shift; 580 581 my $verbose = 0; 582 583 my $missing_tools; 584 my $pstamptool = can_run("pstamptool") or (warn "Can't find pstamptool" and $missing_tools = 1); 585 if ($missing_tools) { 586 warn("Can't find required tools."); 587 exit ($PS_EXIT_CONFIG_ERROR); 588 } 589 590 my $command = "$pstamptool -project -name $project_name"; 591 $command .= " -dbname $dbname" if defined $dbname; 592 $command .= " -dbserver $dbserver" if defined $dbserver; 593 # run the tool and parse the output 594 my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = 595 run(command => $command, verbose => $verbose); 596 unless ($success) { 597 print STDERR @$stderr_buf; 598 return undef; 599 } 600 601 my $mdcParser = PS::IPP::Metadata::Config->new; # Parser for metadata config files 602 603 my $output = join "", @$stdout_buf; 604 if (!$output) { 605 print STDERR "no output returned from $command\n" if $verbose; 606 return undef; 607 } 608 my $proj_hash = parse_md_fast($mdcParser, $output); 609 610 $last_project = $proj_hash->[0]; 611 612 return $last_project; 1280 } 1281 1282 # add a row_index array to a set of images with entries for each of the rows in a list 1283 sub setRowRefs { 1284 my $rowList = shift; 1285 my $images = shift; 1286 1287 my $row_index = []; 1288 for (my $i = 0; $i < scalar @$rowList; $i++) { 1289 push @$row_index, $i; 1290 } 1291 foreach my $image (@$images) { 1292 $image->{row_index} = $row_index; 1293 } 1294 } 1295 1296 sub my_die 1297 { 1298 my $msg = shift; 1299 my $fault = shift; 1300 1301 carp $msg; 1302 1303 # we don't fault the request here pstamp_parser_run.pl handles that if necessary 1304 1305 return $fault; 613 1306 } 614 1307 1;
Note:
See TracChangeset
for help on using the changeset viewer.
