Commit 4622f176b41ac59c502f8c128e2e894f576d54db
1 parent
77e1bab8
Integrate code
Showing
3 changed files
with
108 additions
and
89 deletions
cscripts/Makefile.am
| ... | ... | @@ -157,38 +157,42 @@ testdata = $(top_srcdir)/test/data/crab.xml \ |
| 157 | 157 | $(top_srcdir)/test/data/model_mapcube.fits.gz \ |
| 158 | 158 | $(top_srcdir)/test/data/iact_runlist.dat \ |
| 159 | 159 | $(top_srcdir)/test/data/iact_runlist_1.dat \ |
| 160 | - $(top_srcdir)/test/data/iact_runlist_1.dat | |
| 160 | + $(top_srcdir)/test/data/iact_runlist_2.dat | |
| 161 | 161 | |
| 162 | 162 | # Test data to be distributed in $(pyexecdir)/cscripts/tests/data/iactdata |
| 163 | 163 | testiactdata = $(top_srcdir)/test/data/iactdata/hdu-index.fits.gz \ |
| 164 | 164 | $(top_srcdir)/test/data/iactdata/master.json \ |
| 165 | - $(top_srcdir)/test/data/iactdata/obs-index.fits.gz \ | |
| 166 | - $(top_srcdir)/test/data/iactdata/events/irf_file.fits.gz \ | |
| 167 | - $(top_srcdir)/test/data/iactdata/events/events_0.fits.gz \ | |
| 168 | - $(top_srcdir)/test/data/iactdata/events/events_1.fits.gz \ | |
| 169 | - $(top_srcdir)/test/data/iactdata/events/events_2.fits.gz \ | |
| 170 | - $(top_srcdir)/test/data/iactdata/events/events_3.fits.gz \ | |
| 171 | - $(top_srcdir)/test/data/iactdata/events/events_4.fits.gz \ | |
| 172 | - $(top_srcdir)/test/data/iactdata/events/events_5.fits.gz \ | |
| 173 | - $(top_srcdir)/test/data/iactdata/events/events_6.fits.gz \ | |
| 174 | - $(top_srcdir)/test/data/iactdata/events/events_7.fits.gz \ | |
| 175 | - $(top_srcdir)/test/data/iactdata/events/events_8.fits.gz | |
| 165 | + $(top_srcdir)/test/data/iactdata/obs-index.fits.gz | |
| 166 | + | |
| 167 | +# Test data to be distributed in $(pyexecdir)/cscripts/tests/data/iactdata/events | |
| 168 | +testiactevents = $(top_srcdir)/test/data/iactdata/events/irf_file.fits.gz \ | |
| 169 | + $(top_srcdir)/test/data/iactdata/events/events_0.fits.gz \ | |
| 170 | + $(top_srcdir)/test/data/iactdata/events/events_1.fits.gz \ | |
| 171 | + $(top_srcdir)/test/data/iactdata/events/events_2.fits.gz \ | |
| 172 | + $(top_srcdir)/test/data/iactdata/events/events_3.fits.gz \ | |
| 173 | + $(top_srcdir)/test/data/iactdata/events/events_4.fits.gz \ | |
| 174 | + $(top_srcdir)/test/data/iactdata/events/events_5.fits.gz \ | |
| 175 | + $(top_srcdir)/test/data/iactdata/events/events_6.fits.gz \ | |
| 176 | + $(top_srcdir)/test/data/iactdata/events/events_7.fits.gz \ | |
| 177 | + $(top_srcdir)/test/data/iactdata/events/events_8.fits.gz | |
| 176 | 178 | |
| 177 | 179 | # Install scripts, parfiles, test scripts and test data. Note that we don't |
| 178 | 180 | # need to prepend $(DESTDIR) here (not fully clear why, but that's the way |
| 179 | 181 | # it is) |
| 180 | -binscriptsdir = $(bindir) | |
| 181 | -binscripts_DATA = $(binscripts) | |
| 182 | -pythonscriptsdir = $(pyexecdir)/cscripts | |
| 183 | -pythonscripts_DATA = $(pythonscripts) | |
| 184 | -pfilesdir = $(prefix)/syspfiles | |
| 185 | -pfiles_DATA = $(parfiles) | |
| 186 | -testscriptsdir = $(pyexecdir)/cscripts/tests | |
| 187 | -testscripts_DATA = $(testscripts) | |
| 188 | -testdatadir = $(pyexecdir)/cscripts/tests/data | |
| 189 | -testdata_DATA = $(testdata) | |
| 190 | -testiactdatadir = $(pyexecdir)/cscripts/tests/data/iactdata | |
| 191 | -testiactdata_DATA = $(testiactdata) | |
| 182 | +binscriptsdir = $(bindir) | |
| 183 | +binscripts_DATA = $(binscripts) | |
| 184 | +pythonscriptsdir = $(pyexecdir)/cscripts | |
| 185 | +pythonscripts_DATA = $(pythonscripts) | |
| 186 | +pfilesdir = $(prefix)/syspfiles | |
| 187 | +pfiles_DATA = $(parfiles) | |
| 188 | +testscriptsdir = $(pyexecdir)/cscripts/tests | |
| 189 | +testscripts_DATA = $(testscripts) | |
| 190 | +testdatadir = $(pyexecdir)/cscripts/tests/data | |
| 191 | +testdata_DATA = $(testdata) | |
| 192 | +testiactdatadir = $(pyexecdir)/cscripts/tests/data/iactdata | |
| 193 | +testiactdata_DATA = $(testiactdata) | |
| 194 | +testiacteventsdir = $(pyexecdir)/cscripts/tests/data/iactdata/events | |
| 195 | +testiactevents_DATA = $(testiactdata) | |
| 192 | 196 | |
| 193 | 197 | # Files to be distributed in the tar file |
| 194 | 198 | EXTRA_DIST = $(binscripts) $(pythonscripts) $(parfiles) \ | ... | ... |
cscripts/csiactobs.py
| ... | ... | @@ -172,8 +172,10 @@ class csiactobs(ctools.cscript): |
| 172 | 172 | |
| 173 | 173 | # Check if prodname is present |
| 174 | 174 | if self._prodname == config['name']: |
| 175 | - self._hdu_index = str(os.path.join(self._datapath, config['hduindx'])) | |
| 176 | - self._obs_index = str(os.path.join(self._datapath, config['obsindx'])) | |
| 175 | + self._hdu_index = str(os.path.join(self._datapath, | |
| 176 | + config['hduindx'])) | |
| 177 | + self._obs_index = str(os.path.join(self._datapath, | |
| 178 | + config['obsindx'])) | |
| 177 | 179 | |
| 178 | 180 | # Leave loop if index file names were found |
| 179 | 181 | break |
| ... | ... | @@ -292,7 +294,9 @@ class csiactobs(ctools.cscript): |
| 292 | 294 | spec = gammalib.GModelSpectralNodes() |
| 293 | 295 | |
| 294 | 296 | # Create logarithmic energy nodes |
| 295 | - bounds = gammalib.GEbounds(self._bkgpars,gammalib.GEnergy(emin,'TeV'),gammalib.GEnergy(emax,'TeV'), True) | |
| 297 | + bounds = gammalib.GEbounds(self._bkgpars, | |
| 298 | + gammalib.GEnergy(emin,'TeV'), | |
| 299 | + gammalib.GEnergy(emax,'TeV'), True) | |
| 296 | 300 | |
| 297 | 301 | # Loop over bounds and set intensity value |
| 298 | 302 | for i in range(bounds.size()): |
| ... | ... | @@ -319,7 +323,8 @@ class csiactobs(ctools.cscript): |
| 319 | 323 | # Return spectrum |
| 320 | 324 | return spec |
| 321 | 325 | |
| 322 | - def _iact_background(self, telescope, obs_id, bkg_scale, bkgtype, emin=0.01, emax=100): | |
| 326 | + def _iact_background(self, telescope, obs_id, bkg_scale, bkgtype, | |
| 327 | + emin=0.01, emax=100): | |
| 323 | 328 | """ |
| 324 | 329 | Create an IACT background model |
| 325 | 330 | |
| ... | ... | @@ -348,27 +353,35 @@ class csiactobs(ctools.cscript): |
| 348 | 353 | prefactor *= bkg_scale |
| 349 | 354 | |
| 350 | 355 | # Create background spectrum |
| 351 | - spec = self._background_spectrum(prefactor, index, emin, emax) | |
| 356 | + spec = self._background_spectrum(prefactor, index, emin, emax) | |
| 352 | 357 | |
| 353 | - # Create background model instance | |
| 358 | + # Create background model | |
| 354 | 359 | bck = gammalib.GCTAModelIrfBackground(spec) |
| 355 | 360 | |
| 356 | 361 | # Set AeffBackground |
| 357 | 362 | elif bkgtype == 'aeff': |
| 363 | + | |
| 364 | + # Set background components | |
| 358 | 365 | prefactor = bkg_scale * self._bkg_aeff_norm |
| 359 | - spec = self._background_spectrum(prefactor, self._bkg_aeff_index, emin, emax) | |
| 366 | + spec = self._background_spectrum(prefactor, | |
| 367 | + self._bkg_aeff_index, | |
| 368 | + emin, emax) | |
| 360 | 369 | |
| 361 | - # Create background model instance | |
| 370 | + # Create background model | |
| 362 | 371 | bck = gammalib.GCTAModelAeffBackground(spec) |
| 363 | 372 | |
| 364 | 373 | # Set Gaussian Background |
| 365 | 374 | elif bkgtype == 'gauss': |
| 375 | + | |
| 376 | + # Set background components | |
| 366 | 377 | prefactor = bkg_scale * self._bkg_gauss_norm |
| 367 | - | |
| 368 | - # Create background spectrum | |
| 369 | - spec = self._background_spectrum(prefactor, self._bkg_gauss_index, emin, emax) | |
| 378 | + spec = self._background_spectrum(prefactor, | |
| 379 | + self._bkg_gauss_index, | |
| 380 | + emin, emax) | |
| 370 | 381 | radial = gammalib.GCTAModelRadialGauss(self._bkg_gauss_sigma) |
| 371 | - bck = gammalib.GCTAModelRadialAcceptance(radial, spec) | |
| 382 | + | |
| 383 | + # Create background model | |
| 384 | + bck = gammalib.GCTAModelRadialAcceptance(radial, spec) | |
| 372 | 385 | |
| 373 | 386 | else: |
| 374 | 387 | msg = 'Background type "'+bkgtype+'" unsupported' |
| ... | ... | @@ -422,7 +435,7 @@ class csiactobs(ctools.cscript): |
| 422 | 435 | Write observation summary |
| 423 | 436 | """ |
| 424 | 437 | # Log header |
| 425 | - self._log_header1(gammalib.TERSE, 'Observation summary') | |
| 438 | + self._log_header1(gammalib.NORMAL, 'Observation summary') | |
| 426 | 439 | |
| 427 | 440 | # Set energy range dependent on whether boundaries exist or |
| 428 | 441 | # not |
| ... | ... | @@ -444,16 +457,16 @@ class csiactobs(ctools.cscript): |
| 444 | 457 | |
| 445 | 458 | Parameters |
| 446 | 459 | ---------- |
| 447 | - hdu : `gammalib.GFitsTable` | |
| 460 | + hdu : `~gammalib.GFitsTable` | |
| 448 | 461 | HDU FITS table |
| 449 | - hierarchy : list of strings | |
| 462 | + hierarchy : list of str | |
| 450 | 463 | List of strings containing the hierarchy how to look for files |
| 451 | - formats : list of strings | |
| 464 | + formats : list of str | |
| 452 | 465 | File formats available for this observation |
| 453 | 466 | |
| 454 | 467 | Returns |
| 455 | 468 | ------- |
| 456 | - filename : string | |
| 469 | + filename : str | |
| 457 | 470 | Filename of requested file |
| 458 | 471 | """ |
| 459 | 472 | |
| ... | ... | @@ -477,8 +490,8 @@ class csiactobs(ctools.cscript): |
| 477 | 490 | # Build filename from information stored in hduindx_hdu |
| 478 | 491 | if index >= 0: |
| 479 | 492 | filename = os.path.join(self._subdir, |
| 480 | - hdu['FILE_DIR'][index], | |
| 481 | - hdu['FILE_NAME'][index]) | |
| 493 | + hdu['FILE_DIR'][index], | |
| 494 | + hdu['FILE_NAME'][index]) | |
| 482 | 495 | filehdu = hdu['HDU_NAME'][index] |
| 483 | 496 | filename += '['+filehdu+']' |
| 484 | 497 | |
| ... | ... | @@ -492,17 +505,17 @@ class csiactobs(ctools.cscript): |
| 492 | 505 | |
| 493 | 506 | Parameters |
| 494 | 507 | ---------- |
| 495 | - filename : string | |
| 508 | + filename : str | |
| 496 | 509 | Filename |
| 497 | 510 | obs_id : int |
| 498 | 511 | Observation ID |
| 499 | - filetype : string | |
| 512 | + filetype : str | |
| 500 | 513 | Type of file |
| 501 | 514 | |
| 502 | 515 | Returns |
| 503 | 516 | ------- |
| 504 | 517 | present : bool |
| 505 | - Flag signaling if file is present | |
| 518 | + True if filename is present, False otherwise | |
| 506 | 519 | """ |
| 507 | 520 | |
| 508 | 521 | # Initialise return value |
| ... | ... | @@ -513,17 +526,18 @@ class csiactobs(ctools.cscript): |
| 513 | 526 | |
| 514 | 527 | # Check if file is empty |
| 515 | 528 | if fname.is_empty(): |
| 516 | - self._log_string(gammalib.TERSE, 'Skipping observation '+str(obs_id)+ | |
| 517 | - ': No '+filetype+' found\n') | |
| 529 | + msg = 'Skipping observation "%s": No %s found' % (obs_id, filetype) | |
| 530 | + self._log_string(gammalib.NORMAL, msg) | |
| 518 | 531 | present = False |
| 519 | 532 | |
| 520 | 533 | # Check if file exists |
| 521 | 534 | elif not fname.exists(): |
| 522 | - self._log_string(gammalib.TERSE, 'Skipping observation '+str(obs_id)+ | |
| 523 | - ': '+filetype+' "'+filename+'" does not exist\n') | |
| 535 | + msg = ('Skipping observation "%s": %s "%s" does not exist' % | |
| 536 | + (obs_id, filetype, filename)) | |
| 537 | + self._log_string(gammalib.NORMAL, msg) | |
| 524 | 538 | present = False |
| 525 | 539 | |
| 526 | - # Return boolean | |
| 540 | + # Return present flag | |
| 527 | 541 | return present |
| 528 | 542 | |
| 529 | 543 | |
| ... | ... | @@ -548,9 +562,8 @@ class csiactobs(ctools.cscript): |
| 548 | 562 | lib = self._xml.element('observation_list', 0) |
| 549 | 563 | |
| 550 | 564 | # Log output |
| 551 | - if self._logTerse(): | |
| 552 | - self._log('\n') | |
| 553 | - self._log.header1('Looping over '+str(len(self._runlist))+' runs') | |
| 565 | + msg = 'Looping over %d runs' % len(self._runlist) | |
| 566 | + self._log_header1(gammalib.TERSE, msg) | |
| 554 | 567 | |
| 555 | 568 | # Initialise energy range values for logging |
| 556 | 569 | self._ebounds.clear() |
| ... | ... | @@ -562,7 +575,8 @@ class csiactobs(ctools.cscript): |
| 562 | 575 | obs_selection = '[OBS_ID=='+str(obs_id)+']' |
| 563 | 576 | |
| 564 | 577 | # Open HDU index file |
| 565 | - hduindx = gammalib.GFits(self._hdu_index+'[HDU_INDEX]'+obs_selection) | |
| 578 | + hduindx = gammalib.GFits(self._hdu_index+'[HDU_INDEX]'+ | |
| 579 | + obs_selection) | |
| 566 | 580 | hduindx_hdu = hduindx['HDU_INDEX'] |
| 567 | 581 | |
| 568 | 582 | # Initialise types and formats |
| ... | ... | @@ -593,8 +607,9 @@ class csiactobs(ctools.cscript): |
| 593 | 607 | if not gammalib.GFilename(edispfile).exists(): |
| 594 | 608 | |
| 595 | 609 | # Print warning that edisp cannot be used for this observation |
| 596 | - self._log_string(gammalib.TERSE, 'Warning: observation '+str(obs_id)+ | |
| 597 | - ' has no energy dispersion information\n') | |
| 610 | + msg = ('Warning: observation "%s" has no energy dispersion ' | |
| 611 | + 'information' % obs_id) | |
| 612 | + self._log_string(gammalib.NORMAL, msg) | |
| 598 | 613 | |
| 599 | 614 | # Set energy dispersion file as empty |
| 600 | 615 | edispfile = '' |
| ... | ... | @@ -615,23 +630,27 @@ class csiactobs(ctools.cscript): |
| 615 | 630 | # Remove IRF background if file doesnt exist |
| 616 | 631 | run_bkg_mod_hierarchy.remove('irf') |
| 617 | 632 | |
| 618 | - # Print warning that edisp cannot be used for this observation | |
| 619 | - self._log_string(gammalib.TERSE, 'Warning: observation '+str(obs_id)+ | |
| 620 | - ' has no background information (IRF background cannot be used)\n') | |
| 633 | + # Print warning that edisp cannot be used for this | |
| 634 | + # observation | |
| 635 | + msg = ('Warning: observation "%s" has no background ' | |
| 636 | + 'information (IRF background cannot be used)' % | |
| 637 | + obs_id) | |
| 638 | + self._log_string(gammalib.NORMAL, msg) | |
| 621 | 639 | |
| 622 | 640 | # Check if background model hierarchy is empty |
| 623 | 641 | if len(run_bkg_mod_hierarchy) == 0: |
| 624 | 642 | |
| 625 | 643 | # Skip observation if no background can be used |
| 626 | - self._log_string(gammalib.TERSE, 'Skipping observation '+str(obs_id)+ | |
| 627 | - ': No background can be used\n') | |
| 644 | + msg = ('Skipping observation "%s": No background can be ' | |
| 645 | + 'used' % obs_id) | |
| 646 | + self._log_string(gammalib.NORMAL, msg) | |
| 628 | 647 | continue |
| 629 | 648 | |
| 630 | 649 | else: |
| 631 | 650 | # Log if we fall back to next background approach |
| 632 | - self._log_string(gammalib.TERSE, 'Observation '+str(obs_id)+ | |
| 633 | - ': Falling back to background "'+ | |
| 634 | - run_bkg_mod_hierarchy[0]+'"\n') | |
| 651 | + msg = ('Observation "%s": Falling back to background "%s"' % | |
| 652 | + (obs_id, run_bkg_mod_hierarchy[0])) | |
| 653 | + self._log_string(gammalib.NORMAL, msg) | |
| 635 | 654 | |
| 636 | 655 | # Close hdu index file |
| 637 | 656 | hduindx.close() |
| ... | ... | @@ -643,7 +662,8 @@ class csiactobs(ctools.cscript): |
| 643 | 662 | if self._use_bkg_scale: |
| 644 | 663 | |
| 645 | 664 | # Read background scale from fits file |
| 646 | - obsindx = gammalib.GFits(self._obs_index+'[OBS_INDEX]'+obs_selection) | |
| 665 | + obsindx = gammalib.GFits(self._obs_index+'[OBS_INDEX]'+ | |
| 666 | + obs_selection) | |
| 647 | 667 | bkg_scale = obsindx['OBS_INDEX']['BKG_SCALE'][0] |
| 648 | 668 | obsindx.close() |
| 649 | 669 | |
| ... | ... | @@ -722,17 +742,20 @@ class csiactobs(ctools.cscript): |
| 722 | 742 | obs.append(bck) |
| 723 | 743 | |
| 724 | 744 | # Log the observation ID and object name that has been appended |
| 725 | - self._log_value(gammalib.TERSE, 'Append observation', '%s ("%s")' % | |
| 726 | - (obs_id, object_name)) | |
| 745 | + self._log_value(gammalib.NORMAL, 'Append observation', '%s ("%s")' % | |
| 746 | + (obs_id, object_name)) | |
| 727 | 747 | |
| 728 | 748 | # Log the file names of the event and response files |
| 729 | 749 | self._log_value(gammalib.EXPLICIT, ' Event file', eventfile) |
| 730 | 750 | self._log_value(gammalib.EXPLICIT, ' Effective area file', aefffile) |
| 731 | - self._log_value(gammalib.EXPLICIT, ' Point spread function file', psffile) | |
| 732 | - self._log_value(gammalib.EXPLICIT, ' Energy dispersion file', edispfile) | |
| 751 | + self._log_value(gammalib.EXPLICIT, ' Point spread function file', | |
| 752 | + psffile) | |
| 753 | + self._log_value(gammalib.EXPLICIT, ' Energy dispersion file', | |
| 754 | + edispfile) | |
| 733 | 755 | self._log_value(gammalib.EXPLICIT, ' Background file', bkgfile) |
| 734 | 756 | if self._use_bkg_scale: |
| 735 | - self._log_value(gammalib.EXPLICIT, ' Background scale', bkg_scale) | |
| 757 | + self._log_value(gammalib.EXPLICIT, ' Background scale', | |
| 758 | + bkg_scale) | |
| 736 | 759 | |
| 737 | 760 | # Append models provided by "inmodel" to the model container |
| 738 | 761 | self._append_inmodels() |
| ... | ... | @@ -742,8 +765,8 @@ class csiactobs(ctools.cscript): |
| 742 | 765 | |
| 743 | 766 | # Write warning in no observation could be used from runlist |
| 744 | 767 | if lib.size() == 0: |
| 745 | - self._log_string(gammalib.TERSE, 'WARNING: No observation was appended from specified ' | |
| 746 | - 'runlist\n') | |
| 768 | + self._log_string(gammalib.NORMAL, 'WARNING: No observation was ' | |
| 769 | + 'appended from specified runlist') | |
| 747 | 770 | |
| 748 | 771 | # Return |
| 749 | 772 | return |
| ... | ... | @@ -772,28 +795,22 @@ class csiactobs(ctools.cscript): |
| 772 | 795 | Save observation definition and model definition XML file |
| 773 | 796 | """ |
| 774 | 797 | # Write header |
| 775 | - if self._logTerse(): | |
| 776 | - self._log('\n') | |
| 777 | - self._log.header1('Save XML files') | |
| 798 | + self._log_header1(gammalib.TERSE, 'Save XML files') | |
| 778 | 799 | |
| 779 | 800 | # Get filenames |
| 780 | 801 | outobs = self['outobs'].filename() |
| 781 | 802 | outmodel = self['outmodel'].filename() |
| 782 | 803 | |
| 783 | - # Log file name | |
| 784 | - if self._logTerse(): | |
| 785 | - self._log(gammalib.parformat('Obs. definition XML file')) | |
| 786 | - self._log(outobs.url()) | |
| 787 | - self._log('\n') | |
| 804 | + # Log observation definition file name | |
| 805 | + self._log_value(gammalib.NORMAL, 'Obs. definition XML file', | |
| 806 | + outobs.url()) | |
| 788 | 807 | |
| 789 | 808 | # Save observation definition XML file |
| 790 | 809 | self._xml.save(outobs.url()) |
| 791 | 810 | |
| 792 | - # Log file name | |
| 793 | - if self._logTerse(): | |
| 794 | - self._log(gammalib.parformat('Model definiton XML file')) | |
| 795 | - self._log(outmodel.url()) | |
| 796 | - self._log('\n') | |
| 811 | + # Log model definition file name | |
| 812 | + self._log_value(gammalib.NORMAL, 'Model definiton XML file', | |
| 813 | + outmodel.url()) | |
| 797 | 814 | |
| 798 | 815 | # Save model XML file |
| 799 | 816 | self._models.save(outmodel.url()) | ... | ... |
cscripts/csobsdef.py
| ... | ... | @@ -336,7 +336,7 @@ class csobsdef(ctools.cscript): |
| 336 | 336 | # Write observation into logger |
| 337 | 337 | name = obs.instrument()+' observation' |
| 338 | 338 | value = 'Name="%s" ID="%s"' % (obs.name(), obs.id()) |
| 339 | - self._log_value(gammalib.TERSE, name, value) | |
| 339 | + self._log_value(gammalib.NORMAL, name, value) | |
| 340 | 340 | self._log_string(gammalib.EXPLICIT, str(obs)+'\n') |
| 341 | 341 | |
| 342 | 342 | # Append observation |
| ... | ... | @@ -394,11 +394,9 @@ class csobsdef(ctools.cscript): |
| 394 | 394 | obs : `~gammalib.GObservations` |
| 395 | 395 | Observation container |
| 396 | 396 | """ |
| 397 | - | |
| 398 | 397 | # Return container |
| 399 | 398 | return self._obs |
| 400 | 399 | |
| 401 | - | |
| 402 | 400 | def pntdef(self, csv): |
| 403 | 401 | """ |
| 404 | 402 | Set pointing definition from a CSV table | ... | ... |