diff --git a/.gitattributes b/.gitattributes index bb4c77520ee86bc87430f9a5c454fb3477208235..8f36f63767cdda3b82e97ec6cfc5c84950f3fa35 100644 --- a/.gitattributes +++ b/.gitattributes @@ -71,6 +71,7 @@ CEP/BB/BBSKernel/test/tParmMerge.in_mep2/table.f0 -text svneol=unset#unset CEP/BB/BBSKernel/test/tParmMerge.in_mep2/table.f0i -text svneol=unset#unset CEP/BB/BBSKernel/test/tParmMerge.in_mep2/table.lock -text svneol=unset#unset CEP/BB/BB_GUI/make_jar.sh -text svneol=native#application/octet-stream +CEP/BB/SourceDB/bootstrap -text CEP/CPA/PSS3/CAL/src/TEST.MEP/InitialValues/table.dat -text svneol=unset#unset CEP/CPA/PSS3/CAL/src/TEST.MEP/InitialValues/table.f0 -text svneol=unset#unset CEP/CPA/PSS3/CAL/src/TEST.MEP/InitialValues/table.f0i -text svneol=unset#unset diff --git a/CEP/BB/SourceDB/Makefile.am b/CEP/BB/SourceDB/Makefile.am new file mode 100644 index 0000000000000000000000000000000000000000..8e2f1e0543eedb242a0edf52e7b6fcf029c58fb8 --- /dev/null +++ b/CEP/BB/SourceDB/Makefile.am @@ -0,0 +1,14 @@ +SUBDIRS=src test include + +pkgextdir = $(prefix)/config/$(PACKAGE) +pkgext_DATA = pkgext pkgextcppflags pkgextcxxflags pkgextldflags + +DISTCHECK_CONFIGURE_FLAGS=\ + --with-common=$(prefix) + +EXTRA_DIST = \ + Makefile.common \ + SourceDB.spec \ + autoconf_share/compiletool + +include $(top_srcdir)/Makefile.common diff --git a/CEP/BB/SourceDB/bootstrap b/CEP/BB/SourceDB/bootstrap new file mode 100755 index 0000000000000000000000000000000000000000..06f18cde1dbfd6912ef7d927c4d35d25c7137a62 --- /dev/null +++ b/CEP/BB/SourceDB/bootstrap @@ -0,0 +1,3 @@ +#!/bin/sh + +../../../autoconf_share/bootstrap ../../../autoconf_share diff --git a/CEP/BB/SourceDB/configure.in b/CEP/BB/SourceDB/configure.in new file mode 100644 index 0000000000000000000000000000000000000000..9c5337f52ed9a53cffd1506355a306c29a0a9a1f --- /dev/null +++ b/CEP/BB/SourceDB/configure.in @@ -0,0 +1,72 @@ +dnl +dnl Process this file with autoconf to produce a configure script. +dnl +AC_INIT +dnl AC_CONFIG_AUX_DIR(config) +dnl AM_CONFIG_HEADER(config/config.h) +AM_CONFIG_HEADER(config.h) +AM_INIT_AUTOMAKE(SourceDB, 1.0, no-define) + +dnl Initialize for LOFAR (may set compilers) +lofar_INIT + +dnl Checks for programs. +AC_PROG_AWK +AC_PROG_YACC +AC_PROG_CC +AC_PROG_CXX +AM_PROG_LEX +AC_PROG_INSTALL +AC_PROG_LN_S +AC_DISABLE_SHARED +AC_PROG_LIBTOOL + +dnl Checks for libraries. + +dnl dnl Replace `main' with a function in -lfl: +dnl AC_CHECK_LIB(fl, main) +dnl dnl Replace `main' with a function in -lcosev_r: +dnl AC_CHECK_LIB(cosev_r, main) +dnl dnl Replace `main' with a function in -lcosnm_r: +dnl AC_CHECK_LIB(cosnm_r, main) +dnl dnl Replace `main' with a function in -lorb_r: +dnl AC_CHECK_LIB(orb_r, main) +dnl dnl Replace `main' with a function in -lpthread: +dnl AC_CHECK_LIB(pthread, main) +dnl dnl Replace `main' with a function in -lvport_r: +dnl AC_CHECK_LIB(vport_r, main) + +dnl Checks for header files. +AC_HEADER_STDC +AC_CHECK_HEADERS(unistd.h) + +dnl Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_TYPE_SIZE_T + +dnl Checks for library functions. +AC_FUNC_VPRINTF + +dnl +dnl Check for LOFAR specific things +dnl +lofar_GENERAL +lofar_INTERNAL(LCS/Blob,Blob,,1,Blob/BlobHeader.h) +lofar_INTERNAL(LCS/Common,Common,,1,Common/LofarTypedefs.h,,) +lofar_INTERNAL(CEP/BB/ParmDB,ParmDB,,1,ParmDB/ParmDB.h,,) +lofar_AIPSPP(1,"-lmeasures -ltables -lscimath -lscimath_f -lcasa") + +lofar_EXTERNAL(pgsql,0,libpq-fe.h,pq) +lofar_EXTERNAL(pqxx,0,pqxx/pqxx, pqxx) + +dnl +dnl Output Makefiles +dnl +AC_OUTPUT( +include/Makefile +include/SourceDB/Makefile +src/Makefile +test/Makefile +Makefile +SourceDB.spec +) diff --git a/CEP/BB/SourceDB/include/Makefile.am b/CEP/BB/SourceDB/include/Makefile.am new file mode 100644 index 0000000000000000000000000000000000000000..42f6a78d4d49b930e5702bfaf30efcaeebe9ac62 --- /dev/null +++ b/CEP/BB/SourceDB/include/Makefile.am @@ -0,0 +1,3 @@ +SUBDIRS = SourceDB + +include $(top_srcdir)/Makefile.common diff --git a/CEP/BB/SourceDB/include/SourceDB/Makefile.am b/CEP/BB/SourceDB/include/SourceDB/Makefile.am new file mode 100644 index 0000000000000000000000000000000000000000..2d670f71e99e3cf3c9fb596d222a6d2d3ea47819 --- /dev/null +++ b/CEP/BB/SourceDB/include/SourceDB/Makefile.am @@ -0,0 +1,15 @@ +INSTHDRS = \ +SourceValue.h SourceDBMeta.h \ +SourceDB.h SourceDBAIPS.h + +NOINSTHDRS = + +TCCHDRS = + +pkginclude_HEADERS = Package__Version.h $(INSTHDRS) $(TCCHDRS) + +noinst_HEADERS = $(NOINSTHDRS) + +DOCHDRS = $(INSTHDRS) $(NOINSTHDRS) + +include $(top_srcdir)/Makefile.common diff --git a/CEP/BB/SourceDB/include/SourceDB/SourceDB.h b/CEP/BB/SourceDB/include/SourceDB/SourceDB.h new file mode 100644 index 0000000000000000000000000000000000000000..82254c07e1e6918f8e5f81653515fc078b618a63 --- /dev/null +++ b/CEP/BB/SourceDB/include/SourceDB/SourceDB.h @@ -0,0 +1,253 @@ +//# SourceDB.h: Abstract base class to hold sources in a data base. +//# +//# Copyright (C) 2008 +//# ASTRON (Netherlands Foundation for Research in Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.nl +//# +//# This program is free software; you can redistribute it and/or modify +//# it under the terms of the GNU General Public License as published by +//# the Free Software Foundation; either version 2 of the License, or +//# (at your option) any later version. +//# +//# This program is distributed in the hope that it will be useful, +//# but WITHOUT ANY WARRANTY; without even the implied warranty of +//# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//# GNU General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License +//# along with this program; if not, write to the Free Software +//# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +//# +//# $Id$ + +#ifndef LOFAR_SOURCEDB_SOURCEDB_H +#define LOFAR_SOURCEDB_SOURCEDB_H + +// \file +// Abstract base class to hold sources in a table. + +//# Includes +#include <SourceDB/SourceValue.h> +#include <SourceDB/SourceDBMeta.h> +#include <ParmDB/ParmDB.h> +#include <list> +#include <vector> + + +namespace LOFAR { +namespace SourceDB { + +//# Forward Declarations. +class SourceDB; + +// \ingroup SourceDB +// @{ + +class SourceDBRep +{ +public: + SourceDBRep() + : itsCount(0) + {} + + virtual ~SourceDBRep(); + + // Link to the DBRep by incrementing the count. + void link() + { itsCount++; } + + // Unlink by decrementing the count. + int unlink() + { return --itsCount; } + + // Writelock and unlock the database tables. + // The user does not need to lock/unlock, but it can increase performance + // if many small accesses have to be done. + // The default implementation does nothing. + // <group> + virtual void lock (bool lockForWrite); + virtual void unlock(); + // </group> + + // Get the sources with the given names. + // If the vector is empty, all names are retrieved. + virtual std::list<SourceValue> getSources + (const std::vector<std::string>& sourceNames, + const ParmDB::ParmDomain&) = 0; + + // Get the sources in a circle around the given position. + // The position and radius have to be given in radians. + virtual std::list<SourceValue> getSources (double ra, double dec, + double radius, + const ParmDB::ParmDomain&) = 0; + + // Add the given sources. + virtual void addSources (const std::list<SourceValue>& values) = 0; + + // Update the values of the given source. + // It will check that it already exists. + virtual void updateSource (const SourceValue& value) = 0; + + // Delete the given source record. + virtual void deleteSource (const SourceValue&) = 0; + + // Delete the sources matching the given (filename like) pattern. + virtual void deleteSources (const std::string& sourceNamePattern, + const ParmDB::ParmDomain&) = 0; + + // Get the names of all sources matching the given (filename like) pattern. + virtual std::vector<std::string> getNames (const std::string& pattern) = 0; + + // Clear the source data base tables. + virtual void clearTables() = 0; + + // Find matching records from the other data base in this one. + // The records of other are written into the appropriate result data base. + // Also the matching records of this are written. + // This is useful to merge an LSM back into the GSM. + // Before doing the actual merge, the matches and non-matches can be + // inspected and possibly moved from match to non-match or vice-versa. + virtual void match (const SourceDB& other, + SourceDB& match, SourceDB& nonMatch) = 0; + + // Merge the other source data base into this one. + virtual void merge (const SourceDB& otherMatch, + const SourceDB& otherNonMatch) = 0; + + // Set or get the name and type. + // <group> + void setSourceDBMeta (const SourceDBMeta& ptm) + { itsPTM = ptm; } + const SourceDBMeta& getSourceDBMeta() const + { return itsPTM; } + // </group> + +private: + int itsCount; + SourceDBMeta itsPTM; +}; + + + // Actions to perform on source DB: + // get one or more sources based on name or cone + // get A-team + // match 2 catalogs + // extract LSM from GSM + // merge LSM back into GSM + // generate ParmDB from LSM + // update LSM from ParmDB + // add/delete/update sources in LSM +class SourceDB +{ +public: + // Create or open the SourceDB object for the given database type. + // It is created if not existing or if forceNew=true. + explicit SourceDB (const SourceDBMeta& ptm, bool forceNew=false); + + // Copy contructor has reference semantics. + SourceDB (const SourceDB&); + + // Delete underlying object if no more references to it. + ~SourceDB() + { decrCount(); } + + // Assignment has reference semantics. + SourceDB& operator= (const SourceDB&); + + // Lock and unlock the database tables. + // The user does not need to lock/unlock, but it can increase performance + // if many small accesses have to be done. + // <group> + void lock (bool lockForWrite = true) + { itsRep->lock (lockForWrite); } + void unlock() + { itsRep->unlock(); } + + // Get the sources with the given names. + // If the vector is empty, all names are retrieved. + std::list<SourceValue> getSources + (const std::vector<std::string>& sourceNames, + const ParmDB::ParmDomain& domain) + { return itsRep->getSources (sourceNames, domain); } + + // Get the sources in a circle around the given position. + // The position and radius have to be given in radians. + std::list<SourceValue> getSources (double ra, double dec, double radius, + const ParmDB::ParmDomain& domain) + { return itsRep->getSources (ra, dec, radius, domain); } + + // Add the given sources. + void addSources (std::list<SourceValue> values) + { itsRep->addSources (values); } + + // Add a single given source. + void addSource (const SourceValue& value); + + // Update the values of the given source. + // It will check that it already exists. + void updateSource (const SourceValue& value) + { itsRep->updateSource (value); } + + // Delete the given source record. + // Nothing is done if not found. + void deleteSource (const SourceValue& sourceValue) + { itsRep->deleteSource (sourceValue); } + + // Delete the sources matching the given (filename like) pattern. + // Nothing is done if none found. + void deleteSources (const std::string& sourceNamePattern, + const ParmDB::ParmDomain& domain) + { itsRep->deleteSources (sourceNamePattern, domain); } + + // Get the names of all sources matching the given (filename like) pattern. + std::vector<std::string> getNames (const std::string& pattern) + { return itsRep->getNames (pattern); } + + // Clear the source data base tables. + void clearTables() + { itsRep->clearTables(); } + + // Find matching records from the other data base in this one. + // The records of other are written into the appropriate result data base. + // Also the matching records of this are written. + // This is useful to merge an LSM back into the GSM. + // Before doing the actual merge, the matches and non-matches can be + // inspected and possibly moved from match to non-match or vice-versa. + void match (const SourceDB& other, SourceDB& match, SourceDB& nonMatch) + { itsRep->match (other, match, nonMatch); } + + // Merge the other source data base into this one. + void merge (const SourceDB& otherMatch, const SourceDB& otherNonMatch) + { itsRep->merge (otherMatch, otherNonMatch); } + + // Create a parm data base from the source data base. + void createParmDB (ParmDB::ParmDB&); + + // Merge a parm data base back into this source data base. + // It updates possibly changed parameters and adds new sources. + void mergeParmDB (const ParmDB::ParmDB&); + +private: + // Create a SourceDB object for an existing SourceDBRep. + SourceDB (SourceDBRep*); + + // Decrement the refcount and delete if zero. + void decrCount(); + + // Put a single parameter. + void putParm (ParmDB::ParmDB& parmdb, ParmDB::ParmValue& pv, + const std::string& sourceName, + const std::string& parm, + const ParmDB::ParmDomain& domain, + double value, bool relativePert); + + //# Data Members + SourceDBRep* itsRep; +}; + +// @} + +} // namespace SourceDB +} // namespace LOFAR + +#endif diff --git a/CEP/BB/SourceDB/include/SourceDB/SourceDBAIPS.h b/CEP/BB/SourceDB/include/SourceDB/SourceDBAIPS.h new file mode 100644 index 0000000000000000000000000000000000000000..280c87a38c8604111be164ea6d3d6f0f65130ac6 --- /dev/null +++ b/CEP/BB/SourceDB/include/SourceDB/SourceDBAIPS.h @@ -0,0 +1,136 @@ +//# SourceDBAIPS.h: Class to hold sources in an AIPS++ table. +//# +//# Copyright (C) 2008 +//# ASTRON (Netherlands Foundation for Research in Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.nl +//# +//# This program is free software; you can redistribute it and/or modify +//# it under the terms of the GNU General Public License as published by +//# the Free Software Foundation; either version 2 of the License, or +//# (at your option) any later version. +//# +//# This program is distributed in the hope that it will be useful, +//# but WITHOUT ANY WARRANTY; without even the implied warranty of +//# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//# GNU General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License +//# along with this program; if not, write to the Free Software +//# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +//# +//# $Id$ + +#ifndef LOFAR_SOURCEDB_SOURCEDBAIPS_H +#define LOFAR_SOURCEDB_SOURCEDBAIPS_H + +// \file +// Class to hold sources in an AIPS++ table. + +//# Includes +#include <SourceDB/SourceDB.h> +#include <tables/Tables/Table.h> + +namespace LOFAR { +namespace SourceDB { + + +// \ingroup SourceDB +// @{ + +class SourceDBAIPS: public SourceDBRep +{ +public: + SourceDBAIPS (const std::string& tableName, bool forceNew); + + virtual ~SourceDBAIPS(); + + // Writelock and unlock the database tables. + // The user does not need to lock/unlock, but it can increase performance + // if many small accesses have to be done. + // The default implementation does nothing. + // <group> + virtual void lock (bool lockForWrite); + virtual void unlock(); + // </group> + + // Get the sources with the given names. + // If the vector is empty, all names are retrieved. + virtual std::list<SourceValue> getSources + (const std::vector<std::string>& sourceNames, + const ParmDB::ParmDomain&) ; + + // Get the sources in a circle around the given position. + // The position and radius have to be given in radians. + virtual std::list<SourceValue> getSources (double ra, double dec, + double radius, + const ParmDB::ParmDomain&); + + // Add the given sources. + virtual void addSources (const std::list<SourceValue>& values); + + // Update the values of the given source. + // It will check that it already exists. + virtual void updateSource (const SourceValue& value); + + // Delete the given source record. + virtual void deleteSource (const SourceValue&); + + // Delete the sources matching the given (filename like) pattern. + virtual void deleteSources (const std::string& sourceNamePattern, + const ParmDB::ParmDomain&); + + // Get the names of all sources matching the given (filename like) pattern. + virtual std::vector<std::string> getNames (const std::string& pattern); + + // Clear the source data base tables. + virtual void clearTables(); + + // Find matching records from the other data base in this one. + // The records of other are written into the appropriate result data base. + // Also the matching records of this are written. + // This is useful to merge an LSM back into the GSM. + // Before doing the actual merge, the matches and non-matches can be + // inspected and possibly moved from match to non-match or vice-versa. + virtual void match (const SourceDB& other, + SourceDB& match, SourceDB& nonMatch); + + // Merge the other source data base into this one. + virtual void merge (const SourceDB& otherMatch, + const SourceDB& otherNonMatch); + +private: + // Create the tables. + void createTables (const std::string& tableName); + + // Set the quantum units for a column. + void setQuant (casa::TableDesc& td, const casa::String& name, + const casa::String& unit); + + // Set the quantum units and measure Epoch for a column. + void setEpoch (casa::TableDesc& td, const casa::String& name); + + // Append the source values from all rows in the table to the list. + void extractValues (std::list<SourceValue>& result, const casa::Table& tab); + + // Put the source value into the given table row. + void putValue (casa::Table& tab, unsigned rownr, const SourceValue& pvalue); + + // Create a select expression node on domain and parent id. + casa::TableExprNode makeExpr (const casa::Table& table, + const ParmDB::ParmDomain&) const; + + // And two table select expressions, where the first one can be null. + void andExpr (casa::TableExprNode& expr, + const casa::TableExprNode& right) const; + + + //# Data members + casa::Table itsTable; +}; + +// @} + +} // namespace SourceDB +} // namespace LOFAR + +#endif diff --git a/CEP/BB/SourceDB/include/SourceDB/SourceDBMeta.h b/CEP/BB/SourceDB/include/SourceDB/SourceDBMeta.h new file mode 100644 index 0000000000000000000000000000000000000000..14a6d770477e70171cfa346c02c054078435f982 --- /dev/null +++ b/CEP/BB/SourceDB/include/SourceDB/SourceDBMeta.h @@ -0,0 +1,92 @@ +//# SourceDBMeta.h: one line description +//# +//# Copyright (C) 2008 +//# ASTRON (Netherlands Foundation for Research in Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.nl +//# +//# This program is free software; you can redistribute it and/or modify +//# it under the terms of the GNU General Public License as published by +//# the Free Software Foundation; either version 2 of the License, or +//# (at your option) any later version. +//# +//# This program is distributed in the hope that it will be useful, +//# but WITHOUT ANY WARRANTY; without even the implied warranty of +//# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//# GNU General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License +//# along with this program; if not, write to the Free Software +//# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +//# +//# $Id$ + +#ifndef LOFAR_SOURCEDB_SOURCEDBMETA_H +#define LOFAR_SOURCEDB_SOURCEDBMETA_H + +// \file +// one line description. + +#include <Common/lofar_string.h> + +namespace LOFAR { +//# Forward Declarations. +class BlobOStream; +class BlobIStream; + +namespace SourceDB { + + // \addtogroup SourceDB + // @{ + + // Description of class. + class SourceDBMeta + { + public: + SourceDBMeta(); + + SourceDBMeta (const std::string& type, const std::string& tableName); + + void setSQLMeta (const std::string& dbName, const std::string& userName, + const std::string& dbPwd, const std::string& hostName); + + const std::string& getType() const + { return itsType; } + + const std::string& getTableName() const + { return itsTableName; } + + const std::string& getDBName() const + { return itsDBName; } + + const std::string& getUserName() const + { return itsUserName; } + + const std::string& getDBPwd() const + { return itsDBPwd; } + + const std::string& getHostName() const + { return itsHostName; } + + // Write the object into a blob. + friend BlobOStream& operator<< (BlobOStream&, const SourceDBMeta&); + + // Read the object from a blob. + friend BlobIStream& operator>> (BlobIStream&, SourceDBMeta&); + + private: + //# Datamembers + std::string itsType; + std::string itsTableName; + // these options are used for sql databases + std::string itsDBName; + std::string itsUserName; + std::string itsDBPwd; + std::string itsHostName; + }; + + // @} + +} // namespace SourceDB +} // namespace LOFAR + +#endif diff --git a/CEP/BB/SourceDB/include/SourceDB/SourceValue.h b/CEP/BB/SourceDB/include/SourceDB/SourceValue.h new file mode 100644 index 0000000000000000000000000000000000000000..4203ee4eb988955fe376a1370128b017e28861da --- /dev/null +++ b/CEP/BB/SourceDB/include/SourceDB/SourceValue.h @@ -0,0 +1,131 @@ +//# SourceValue.h: The parameters of a single source +//# +//# Copyright (C) 2008 +//# ASTRON (Netherlands Foundation for Research in Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.nl +//# +//# This program is free software; you can redistribute it and/or modify +//# it under the terms of the GNU General Public License as published by +//# the Free Software Foundation; either version 2 of the License, or +//# (at your option) any later version. +//# +//# This program is distributed in the hope that it will be useful, +//# but WITHOUT ANY WARRANTY; without even the implied warranty of +//# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//# GNU General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License +//# along with this program; if not, write to the Free Software +//# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +//# +//# $Id$ + +#ifndef LOFAR_SOURCEDB_SOURCEVALUE_H +#define LOFAR_SOURCEDB_SOURCEVALUE_H + +// \file +// The parameters of a single source. + +//# Includes +#include <ParmDB/ParmDomain.h> +#include <string> +#include <vector> + +namespace LOFAR { +namespace SourceDB { + +// \ingroup SourceDB +// @{ + +// This class defines the parameters of a source. +// The parameters can be frequency and time dependent. +// By default the time and frequency range are infinite. + +class SourceValue +{ +public: + // Create a default SourceValue object. + SourceValue(); + + // Set the various source parameters. + // <group> + void setPointSource (const std::string& name, double ra, double dec, + double flux[4], double spectralIndex); + /// void setGaussianSource (); + void setPos (double ra, double dec); + // </group> + + // Set the domain. + // The domain can have 0, 1, or 2 axes (freq (Hz) and time (MJD seconds)). + void setDomain (const ParmDB::ParmDomain&); + + // Set the frequency domain (in Hz) for which the parameters are valid. + void setFreqDomain (double startHz, double endHz); + + // Set the time domain (in MJD seconds) for which the parameters are valid. + void setTimeDomain (double startMJD, double endMJD); + + // Get the various source parameters. + // <group> + const std::string& getName() const + { return itsName; } + const std::string& getType() const + { return itsType; } + double getRA() const + { return itsRA; } + double getDEC() const + { return itsDEC; } + double getSpectralIndex() const + { return itsSpIndex; } + const double* getFlux() const + { return itsFlux; } + // </group> + + // Get source parameters. + // <group> + void setRA (double ra) + { itsRA = ra; } + void setDEC (double dec) + { itsDEC = dec; } + void setFluxI (double flux) + { itsFlux[0] = flux; } + void setFluxQ (double flux) + { itsFlux[1] = flux; } + void setFluxU (double flux) + { itsFlux[2] = flux; } + void setFluxV (double flux) + { itsFlux[3] = flux; } + void setSpectralIndex (double spectralIndex) + { itsSpIndex = spectralIndex; } + // </group> + + // Get the domain. + // <group> + const ParmDB::ParmDomain& getDomain() const + { return itsDomain; } + double getStartFreq() const + { return itsDomain.getStart()[0]; } + double getEndFreq() const + { return itsDomain.getEnd()[0]; } + double getStartTime() const + { return itsDomain.getStart()[1]; } + double getEndTime() const + { return itsDomain.getEnd()[1]; } + // </group> + +private: + std::string itsName; + std::string itsType; + double itsRA; + double itsDEC; + double itsFlux[4]; + double itsSpIndex; + ParmDB::ParmDomain itsDomain; +}; + +// @} + +} // namespace SourceDB +} // namespace LOFAR + +#endif diff --git a/CEP/BB/SourceDB/src/Makefile.am b/CEP/BB/SourceDB/src/Makefile.am new file mode 100644 index 0000000000000000000000000000000000000000..680a3471dfe33b2097417a321f8d27ec802b1fe8 --- /dev/null +++ b/CEP/BB/SourceDB/src/Makefile.am @@ -0,0 +1,27 @@ +lib_LTLIBRARIES = libsourcedb.la + +libsourcedb_la_SOURCES = Package__Version.cc \ +SourceValue.cc SourceDBMeta.cc \ +SourceDB.cc SourceDBAIPS.cc + + +bin_PROGRAMS = versionsourcedb sourcedb + +versionsourcedb_SOURCES = versionsourcedb.cc +versionsourcedb_LDADD = libsourcedb.la +versionsourcedb_DEPENDENCIES = libsourcedb.la $(LOFAR_DEPEND) + +sourcedb_SOURCES = sourcedb_main.cc +sourcedb_LDADD = libsourcedb.la +sourcedb_DEPENDENCIES = libsourcedb.la $(LOFAR_DEPEND) + +glishdir = $(libexecdir)/glish +dist_glish_SCRIPTS = + +pythondir = $(bindir) +dist_python_SCRIPTS = + +scriptdir = $(bindir) +dist_script_SCRIPTS = + +include $(top_srcdir)/Makefile.common diff --git a/CEP/BB/SourceDB/src/SourceDB.cc b/CEP/BB/SourceDB/src/SourceDB.cc new file mode 100644 index 0000000000000000000000000000000000000000..9b930e7a2e70ae1779f6ffcf34b04f67fe1fd968 --- /dev/null +++ b/CEP/BB/SourceDB/src/SourceDB.cc @@ -0,0 +1,161 @@ +//# SourceDB.cc: Class to hold source in a table. +//# +//# Copyright (C) 2008 +//# ASTRON (Netherlands Foundation for Research in Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.nl +//# +//# This program is free software; you can redistribute it and/or modify +//# it under the terms of the GNU General Public License as published by +//# the Free Software Foundation; either version 2 of the License, or +//# (at your option) any later version. +//# +//# This program is distributed in the hope that it will be useful, +//# but WITHOUT ANY WARRANTY; without even the implied warranty of +//# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//# GNU General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License +//# along with this program; if not, write to the Free Software +//# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +//# +//# $Id$ + +#include <lofar_config.h> + +#include <SourceDB/SourceDB.h> +#include <SourceDB/SourceDBAIPS.h> +#include <Common/LofarLogger.h> +#include <casa/Utilities/Regex.h> +#include <casa/Utilities/GenSort.h> + +using namespace std; +using namespace casa; + +namespace LOFAR { +namespace SourceDB { + + +SourceDBRep::~SourceDBRep() +{} + +void SourceDBRep::lock (bool) +{} + +void SourceDBRep::unlock() +{} + + + +SourceDB::SourceDB (const SourceDBMeta& ptm, bool forceNew) +{ + // Open the correct SourceDB. + if (ptm.getType() == "aips") { + itsRep = new SourceDBAIPS (ptm.getTableName(), forceNew); + } else if (ptm.getType() == "postgres") { +#if defined(HAVE_PGSQL) + itsRep = new SourceDBPostgres(ptm.getDBName(), + ptm.getUserName(), + ptm.getDBPwd(), + ptm.getHostName(), + ""); +#else + ASSERTSTR(false, "unsupported sourceTableType: "<<ptm.getType()); +#endif + } else { + ASSERTSTR(false, "unknown sourceTableType: "<<ptm.getType()); + } + itsRep->link(); + itsRep->setSourceDBMeta (ptm); +} + +SourceDB::SourceDB (SourceDBRep* rep) +: itsRep (rep) +{ + itsRep->link(); +} + +SourceDB::SourceDB (const SourceDB& that) +: itsRep (that.itsRep) +{ + itsRep->link(); +} + +SourceDB& SourceDB::operator= (const SourceDB& that) +{ + if (this != &that) { + decrCount(); + itsRep = that.itsRep; + itsRep->link(); + } + return *this; +} + +void SourceDB::decrCount() +{ + if (itsRep->unlink() == 0) { + delete itsRep; + itsRep = 0; + } +} + +void SourceDB::addSource (const SourceValue& value) +{ + list<SourceValue> values; + values.push_back (value); + addSources (values); +} + +void SourceDB::createParmDB (ParmDB::ParmDB& parmdb) +{ + // Get all sources. + list<SourceValue> sources = getSources(vector<string>(), + ParmDB::ParmDomain()); + // Lock the ParmDB for the bulk update. + parmdb.lock (true); + // Create the parm object once. + ParmDB::ParmValue pv; + pv.setNewParm(); + // Write them into the parameter database. + // So far, only point sources are handled. + for (list<SourceValue>::const_iterator iter = sources.begin(); + iter != sources.end(); + ++iter) { + vector<int> shape; // empty shape is scalar + ASSERT (iter->getType() == "point"); + putParm (parmdb, pv, iter->getName(), "RA", iter->getDomain(), + iter->getRA(), false); + putParm (parmdb, pv, iter->getName(), "DEC", iter->getDomain(), + iter->getDEC(), false); + putParm (parmdb, pv, iter->getName(), "SPINX", iter->getDomain(), + iter->getSpectralIndex(), false); + putParm (parmdb, pv, iter->getName(), "FLUXI", iter->getDomain(), + iter->getFlux()[0], false); + putParm (parmdb, pv, iter->getName(), "FLUXQ", iter->getDomain(), + iter->getFlux()[1], false); + putParm (parmdb, pv, iter->getName(), "FLUXU", iter->getDomain(), + iter->getFlux()[2], false); + putParm (parmdb, pv, iter->getName(), "FLUXV", iter->getDomain(), + iter->getFlux()[3], false); + } + parmdb.unlock(); +} + +void SourceDB::putParm (ParmDB::ParmDB& parmdb, ParmDB::ParmValue& pv, + const string& sourceName, + const string& parm, + const ParmDB::ParmDomain& domain, + double value, bool relativePert) +{ + pv.rep().setPerturbation (1e-6, relativePert); + pv.rep().setCoeff (&value, vector<int>()); + pv.rep().setDomain (domain); + parmdb.putValue (sourceName+':'+parm, pv); +} + +void SourceDB::mergeParmDB (const ParmDB::ParmDB&) +{ + ASSERTSTR (false, "SourceDB::mergeParmDB not implemented yet"); +} + +} // namespace SourceDB +} // namespace LOFAR diff --git a/CEP/BB/SourceDB/src/SourceDBAIPS.cc b/CEP/BB/SourceDB/src/SourceDBAIPS.cc new file mode 100644 index 0000000000000000000000000000000000000000..a470919525f1cfd31eec0498a42293028db5a49e --- /dev/null +++ b/CEP/BB/SourceDB/src/SourceDBAIPS.cc @@ -0,0 +1,361 @@ +//# SourceDBAIPS.cc: Class to hold sources in an AIPS++ table. +//# +//# Copyright (C) 2008 +//# ASTRON (Netherlands Foundation for Research in Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.nl +//# +//# This program is free software; you can redistribute it and/or modify +//# it under the terms of the GNU General Public License as published by +//# the Free Software Foundation; either version 2 of the License, or +//# (at your option) any later version. +//# +//# This program is distributed in the hope that it will be useful, +//# but WITHOUT ANY WARRANTY; without even the implied warranty of +//# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//# GNU General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License +//# along with this program; if not, write to the Free Software +//# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +//# +//# $Id$ + +#include <lofar_config.h> +#include <SourceDB/SourceDBAIPS.h> +#include <Common/LofarLogger.h> + +#include <tables/Tables/TableDesc.h> +#include <tables/Tables/SetupNewTab.h> +#include <tables/Tables/ExprNode.h> +#include <tables/Tables/ExprNodeSet.h> +#include <tables/Tables/ScalarColumn.h> +#include <tables/Tables/ScaColDesc.h> +#include <tables/Tables/ArrColDesc.h> +#include <tables/Tables/ColumnDesc.h> +#include <tables/Tables/TableIter.h> +#include <tables/Tables/TableRecord.h> +#include <tables/Tables/TableLocker.h> +#include <measures/TableMeasures/TableQuantumDesc.h> +#include <measures/TableMeasures/TableMeasDesc.h> +#include <measures/Measures/MEpoch.h> +#include <measures/Measures/MDirection.h> +#include <casa/Arrays/Vector.h> +#include <casa/Utilities/Regex.h> +#include <casa/BasicMath/Math.h> +#include <casa/OS/Time.h> +#include <casa/Quanta/MVTime.h> + +using namespace casa; +using namespace std; + +namespace LOFAR { +namespace SourceDB { + +SourceDBAIPS::SourceDBAIPS (const string& tableName, bool forceNew) +{ + // Create the table if needed or if it does not exist yet. + if (forceNew || !Table::isReadable (tableName)) { + createTables (tableName); + } + // Open the main table. + itsTable = Table(tableName, TableLock::UserLocking); +} + +SourceDBAIPS::~SourceDBAIPS() +{} + +void SourceDBAIPS::lock (bool lockForWrite) +{ + itsTable.lock (lockForWrite); +} + +void SourceDBAIPS::unlock() +{ + itsTable.unlock(); +} + +void SourceDBAIPS::createTables (const string& tableName) +{ + TableDesc td("Source parameter table", TableDesc::Scratch); + td.comment() = String("Table containing parameters for sources"); + td.addColumn (ScalarColumnDesc<String>("NAME")); + td.addColumn (ScalarColumnDesc<String>("TYPE")); + td.addColumn (ArrayColumnDesc<double> ("RADEC", IPosition(1,2), + ColumnDesc::Direct)); + td.addColumn (ScalarColumnDesc<double>("FLUXI")); + td.addColumn (ScalarColumnDesc<double>("FLUXQ")); + td.addColumn (ScalarColumnDesc<double>("FLUXU")); + td.addColumn (ScalarColumnDesc<double>("FLUXV")); + td.addColumn (ScalarColumnDesc<double>("SPINDEX")); + td.addColumn (ScalarColumnDesc<double>("STARTFREQ", 1)); + td.addColumn (ScalarColumnDesc<double>("ENDFREQ", 1)); + td.addColumn (ScalarColumnDesc<double>("STARTTIME", 1)); + td.addColumn (ScalarColumnDesc<double>("ENDTIME", 1)); + // Define units and measures. + setQuant (td, "FLUXI", "Jy"); + setQuant (td, "FLUXQ", "Jy"); + setQuant (td, "FLUXU", "Jy"); + setQuant (td, "FLUXV", "Jy"); + setQuant (td, "STARTFREQ", "Hz"); + setQuant (td, "ENDFREQ", "Hz"); + setEpoch (td, "STARTTIME"); + setEpoch (td, "ENDTIME"); + setQuant (td, "RADEC", "rad"); + TableMeasRefDesc measRef(MDirection::J2000); + TableMeasValueDesc measVal(td, "RADEC"); + TableMeasDesc<MDirection> tmd(measVal, measRef); + tmd.write(td); + + SetupNewTable newtab(tableName, td, Table::New); + Table tab(newtab); + + tab.tableInfo().setType ("SOURCES"); + tab.tableInfo().readmeAddLine ("Source Parameter values"); +} + +void SourceDBAIPS::setQuant (TableDesc& td, const String& name, + const String& unit) +{ + TableQuantumDesc tqd(td, name, Unit(unit)); + tqd.write (td); +} + +void SourceDBAIPS::setEpoch (TableDesc& td, const String& name) +{ + setQuant (td, name, "s"); + TableMeasRefDesc measRef(MEpoch::UTC); + TableMeasValueDesc measVal(td, name); + TableMeasDesc<MEpoch> tmd(measVal, measRef); + tmd.write(td); +} + + +void SourceDBAIPS::clearTables() +{ + TableLocker locker(itsTable, FileLocker::Write); + Vector<uInt> rows = itsTable.rowNumbers(); + itsTable.removeRow(rows); +} + +list<SourceValue> SourceDBAIPS::getSources (const vector<string>& sourceNames, + const ParmDB::ParmDomain& domain) +{ + TableLocker locker(itsTable, FileLocker::Read); + // Find all rows overlapping the requested domain. + TableExprNode expr = makeExpr (itsTable, domain); + if (sourceNames.size() > 0) { + Vector<String> nams(sourceNames.size()); + for (unsigned i=0; i<sourceNames.size(); ++i) { + nams[i] = sourceNames[i]; + } + andExpr (expr, itsTable.col("NAME").in (nams)); + } + Table sel; + if (expr.isNull()) { + sel = itsTable; + } else { + sel = itsTable(expr); + } + list<SourceValue> result; + extractValues (result, sel); + return result; +} + +list<SourceValue> SourceDBAIPS::getSources (double ra, double dec, + double radius, + const ParmDB::ParmDomain& domain) +{ + TableLocker locker(itsTable, FileLocker::Read); + // Find all rows overlapping the requested domain. + TableExprNode expr = makeExpr (itsTable, domain); + Vector<Double> rdr(3); + rdr[0] = ra; + rdr[1] = dec; + rdr[2] = radius; + andExpr (expr, anyCone(itsTable.col("RADEC"), rdr)); + list<SourceValue> result; + extractValues (result, itsTable(expr)); + return result; +} + +void SourceDBAIPS::addSources (const list<SourceValue>& values) +{ + itsTable.reopenRW(); + TableLocker locker(itsTable, FileLocker::Write); + for (list<SourceValue>::const_iterator iter = values.begin(); + iter != values.end(); + ++iter) { + itsTable.addRow(); + putValue (itsTable, itsTable.nrow()-1, *iter); + } +} + +void SourceDBAIPS::updateSource (const SourceValue& value) +{ + itsTable.reopenRW(); + TableLocker locker(itsTable, FileLocker::Write); + Table sel = itsTable(itsTable.col("NAME") == String(value.getName()) + && itsTable.col("STARTFREQ") == value.getStartFreq() + && itsTable.col("ENDFREQ") == value.getEndFreq() + && itsTable.col("STARTTIME") == value.getStartTime() + && itsTable.col("ENDTIME") == value.getEndTime()); + ASSERT (sel.nrow() == 1); + putValue (sel, 0, value); +} + +void SourceDBAIPS::deleteSource (const SourceValue& value) +{ + itsTable.reopenRW(); + TableLocker locker(itsTable, FileLocker::Write); + // Find all rows. + Table sel = itsTable(itsTable.col("NAME") == String(value.getName()) + && itsTable.col("STARTFREQ") == value.getStartFreq() + && itsTable.col("ENDFREQ") == value.getEndFreq() + && itsTable.col("STARTTIME") == value.getStartTime() + && itsTable.col("ENDTIME") == value.getEndTime()); + // Delete all rows found. + itsTable.removeRow (sel.rowNumbers (itsTable)); +} + +void SourceDBAIPS::deleteSources (const string& sourceNamePattern, + const ParmDB::ParmDomain& domain) +{ + itsTable.reopenRW(); + TableLocker locker(itsTable, FileLocker::Write); + // Find all rows. + TableExprNode expr = makeExpr (itsTable, domain); + Regex regex(Regex::fromPattern(sourceNamePattern)); + andExpr (expr, itsTable.col("NAME") == regex); + Table sel = itsTable(expr); + // Delete all rows found. + itsTable.removeRow (sel.rowNumbers (itsTable)); +} + +vector<string> SourceDBAIPS::getNames (const string& pattern) +{ + TableLocker locker(itsTable, FileLocker::Read); + vector<string> result; + // Find all rows. + Regex regex(Regex::fromPattern(pattern)); + Table sel = itsTable(itsTable.col("NAME") == regex); + if (sel.nrow() > 0) { + // Sort them uniquely on name. + Table sor = sel.sort("NAME", Sort::Ascending, + Sort::QuickSort | Sort::NoDuplicates); + ROScalarColumn<String> nameCol (sor, "NAME"); + Vector<String> names = nameCol.getColumn(); + result.resize (sor.nrow()); + for (unsigned i=0; i<names.nelements(); ++i) { + result[i] = names[i]; + } + } + return result; +} + +void SourceDBAIPS::match (const SourceDB& other, + SourceDB& match, SourceDB& nonMatch) +{ + ASSERTSTR (false, "SourceDBAIPS::match not implemented yet"); +} + +void SourceDBAIPS::merge (const SourceDB& otherMatch, + const SourceDB& otherNonMatch) +{ + ASSERTSTR (false, "SourceDBAIPS::merge not implemented yet"); +} + + +void SourceDBAIPS::extractValues (list<SourceValue>& result, + const Table& tab) +{ + ROScalarColumn<String> nameCol (tab, "NAME"); + ROScalarColumn<String> typeCol (tab, "TYPE"); + ROArrayColumn <double> radecCol(tab, "RADEC"); + ROScalarColumn<double> spCol (tab, "SPINDEX"); + ROScalarColumn<double> fiCol (tab, "FLUXI"); + ROScalarColumn<double> fqCol (tab, "FLUXQ"); + ROScalarColumn<double> fuCol (tab, "FLUXU"); + ROScalarColumn<double> fvCol (tab, "FLUXV"); + ROScalarColumn<double> sfCol (tab, "STARTFREQ"); + ROScalarColumn<double> efCol (tab, "ENDFREQ"); + ROScalarColumn<double> stCol (tab, "STARTTIME"); + ROScalarColumn<double> etCol (tab, "ENDTIME"); + double flux[4]; + for (unsigned int i=0; i<tab.nrow(); i++) { + SourceValue pvalue; + flux[0] = fiCol(i); + flux[1] = fqCol(i); + flux[2] = fuCol(i); + flux[3] = fvCol(i); + Array<double> radec = radecCol(i); + pvalue.setPointSource (nameCol(i), radec.data()[0], radec.data()[1], + flux, spCol(i)); + pvalue.setDomain (ParmDB::ParmDomain(sfCol(i), efCol(i), + stCol(i), etCol(i))); + result.push_back (pvalue); + } +} + +void SourceDBAIPS::putValue (Table& tab, + unsigned rownr, + const SourceValue& pvalue) +{ + ScalarColumn<String> nameCol (tab, "NAME"); + ScalarColumn<String> typeCol (tab, "TYPE"); + ArrayColumn <double> radecCol(tab, "RADEC"); + ScalarColumn<double> spCol (tab, "SPINDEX"); + ScalarColumn<double> fiCol (tab, "FLUXI"); + ScalarColumn<double> fqCol (tab, "FLUXQ"); + ScalarColumn<double> fuCol (tab, "FLUXU"); + ScalarColumn<double> fvCol (tab, "FLUXV"); + ScalarColumn<double> sfCol (tab, "STARTFREQ"); + ScalarColumn<double> efCol (tab, "ENDFREQ"); + ScalarColumn<double> stCol (tab, "STARTTIME"); + ScalarColumn<double> etCol (tab, "ENDTIME"); + Vector<double> radec(2); + radec(0) = pvalue.getRA(); + radec(1) = pvalue.getDEC(); + nameCol.put (rownr, pvalue.getName()); + typeCol.put (rownr, pvalue.getType()); + radecCol.put(rownr, radec); + spCol.put (rownr, pvalue.getSpectralIndex()); + fiCol.put (rownr, pvalue.getFlux()[0]); + fqCol.put (rownr, pvalue.getFlux()[1]); + fuCol.put (rownr, pvalue.getFlux()[2]); + fvCol.put (rownr, pvalue.getFlux()[3]); + sfCol.put (rownr, pvalue.getStartFreq()); + efCol.put (rownr, pvalue.getEndFreq()); + stCol.put (rownr, pvalue.getStartTime()); + etCol.put (rownr, pvalue.getEndTime()); +} + +TableExprNode SourceDBAIPS::makeExpr (const Table& table, + const ParmDB::ParmDomain& domain) const +{ + TableExprNode expr; + if (domain.getStart().size() > 0) { + andExpr (expr, + domain.getStart()[0] < table.col("ENDFREQ") && + domain.getEnd()[0] > table.col("STARTFREQ")); + if (domain.getStart().size() > 1) { + andExpr (expr, + domain.getStart()[1] < table.col("ENDTIME") && + domain.getEnd()[1] > table.col("STARTTIME")); + } + } + return expr; +} + +void SourceDBAIPS::andExpr (TableExprNode& expr, + const TableExprNode& right) const +{ + if (expr.isNull()) { + expr = right; + } else { + expr = expr && right; + } +} + + +} // namespace SourceDB +} // namespace LOFAR diff --git a/CEP/BB/SourceDB/src/SourceDBMeta.cc b/CEP/BB/SourceDB/src/SourceDBMeta.cc new file mode 100644 index 0000000000000000000000000000000000000000..5f4899d713630d9cb9cd39af27f2e2946ae88040 --- /dev/null +++ b/CEP/BB/SourceDB/src/SourceDBMeta.cc @@ -0,0 +1,70 @@ +//# SourceDBMeta.cc: one line description +//# +//# Copyright (C) 2008 +//# ASTRON (Netherlands Foundation for Research in Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.nl +//# +//# This program is free software; you can redistribute it and/or modify +//# it under the terms of the GNU General Public License as published by +//# the Free Software Foundation; either version 2 of the License, or +//# (at your option) any later version. +//# +//# This program is distributed in the hope that it will be useful, +//# but WITHOUT ANY WARRANTY; without even the implied warranty of +//# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//# GNU General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License +//# along with this program; if not, write to the Free Software +//# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +//# +//# $Id$ + +#include <lofar_config.h> + +#include <SourceDB/SourceDBMeta.h> +#include <Blob/BlobOStream.h> +#include <Blob/BlobIStream.h> + + +namespace LOFAR { +namespace SourceDB { + + SourceDBMeta::SourceDBMeta() + {} + + SourceDBMeta::SourceDBMeta (const std::string& type, + const std::string& tableName) + : itsType (type), + itsTableName (tableName) + {} + + void SourceDBMeta::setSQLMeta (const std::string& dbName, + const std::string& userName, + const std::string& dbPwd, + const std::string& hostName) + { + itsDBName = dbName; + itsUserName = userName; + itsDBPwd = dbPwd; + itsHostName = hostName; + } + + BlobOStream& operator<< (BlobOStream& bos, const SourceDBMeta& pdm) + { + bos << pdm.itsType << pdm.itsTableName + << pdm.itsDBName << pdm.itsUserName + << pdm.itsDBPwd << pdm.itsHostName; + return bos; + } + + BlobIStream& operator>> (BlobIStream& bis, SourceDBMeta& pdm) + { + bis >> pdm.itsType >> pdm.itsTableName + >> pdm.itsDBName >> pdm.itsUserName + >> pdm.itsDBPwd >> pdm.itsHostName; + return bis; + } + +} // namespace SourceDB +} // namespace LOFAR diff --git a/CEP/BB/SourceDB/src/SourceValue.cc b/CEP/BB/SourceDB/src/SourceValue.cc new file mode 100644 index 0000000000000000000000000000000000000000..fb8487d22aeab59710cee2485a756b3f260a4fa5 --- /dev/null +++ b/CEP/BB/SourceDB/src/SourceValue.cc @@ -0,0 +1,93 @@ +//# SourceValue.cc: The parameters of a single source +//# +//# Copyright (C) 2008 +//# ASTRON (Netherlands Foundation for Research in Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.nl +//# +//# This program is free software; you can redistribute it and/or modify +//# it under the terms of the GNU General Public License as published by +//# the Free Software Foundation; either version 2 of the License, or +//# (at your option) any later version. +//# +//# This program is distributed in the hope that it will be useful, +//# but WITHOUT ANY WARRANTY; without even the implied warranty of +//# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//# GNU General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License +//# along with this program; if not, write to the Free Software +//# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +//# +//# $Id$ + +#include <SourceDB/SourceValue.h> +#include <Common/LofarLogger.h> + +namespace LOFAR { +namespace SourceDB { + + SourceValue::SourceValue() + : itsRA (0), + itsDEC (0), + itsSpIndex (0), + itsDomain (-1e30, 1e30, -1e30, 1e30) + { + itsFlux[0] = 1; + itsFlux[1] = 0; + itsFlux[2] = 0; + itsFlux[3] = 0; + } + + void SourceValue::setPointSource (const std::string& name, + double RA, double DEC, + double flux[4], double spectralIndex) + { + itsName = name; + itsType = "point"; + itsRA = RA; + itsDEC = DEC; + itsSpIndex = spectralIndex; + itsFlux[0] = flux[0]; + itsFlux[1] = flux[1]; + itsFlux[2] = flux[2]; + itsFlux[3] = flux[3]; + } + + void SourceValue::setPos (double RA, double DEC) + { + itsRA = RA; + itsDEC = DEC; + } + + void SourceValue::setDomain (const ParmDB::ParmDomain& domain) + { + ASSERTSTR (domain.getStart().size() <= 2, "Domain has max. 2 axes"); + if (domain.getStart().size() == 2) { + itsDomain = domain; + } else if (domain.getStart().size() == 1) { + itsDomain = ParmDB::ParmDomain (domain.getStart()[0], + domain.getEnd()[0], + -1e30, 1e30); + } else { + itsDomain = ParmDB::ParmDomain (-1e30, 1e30, -1e30, 1e30); + } + } + + void SourceValue::setFreqDomain (double startHz, double endHz) + { + // Keep current time. + itsDomain = ParmDB::ParmDomain (startHz, endHz, + itsDomain.getStart()[1], + itsDomain.getEnd()[1]); + } + + void SourceValue::setTimeDomain (double startMJD, double endMJD) + { + // Keep current freq. + itsDomain = ParmDB::ParmDomain (itsDomain.getStart()[0], + itsDomain.getEnd()[0], + startMJD, endMJD); + } + +} // namespace SourceDB +} // namespace LOFAR diff --git a/CEP/BB/SourceDB/src/sourcedb_main.cc b/CEP/BB/SourceDB/src/sourcedb_main.cc new file mode 100644 index 0000000000000000000000000000000000000000..5e3b56ae09ac71f5052b7a013ceee9e3cc186c84 --- /dev/null +++ b/CEP/BB/SourceDB/src/sourcedb_main.cc @@ -0,0 +1,566 @@ +//# sourcedb.cc: put values in the database used for MNS +//# +//# Copyright (C) 2004 +//# ASTRON (Netherlands Foundation for Research in Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.nl +//# +//# This program is free software; you can redistribute it and/or modify +//# it under the terms of the GNU General Public License as published by +//# the Free Software Foundation; either version 2 of the License, or +//# (at your option) any later version. +//# +//# This program is distributed in the hope that it will be useful, +//# but WITHOUT ANY WARRANTY; without even the implied warranty of +//# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//# GNU General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License +//# along with this program; if not, write to the Free Software +//# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +//# +//# $Id$ + + +#include <lofar_config.h> + +#include <SourceDB/SourceDB.h> +#include <ParmDB/ParmDomain.h> +#include <Blob/KeyValueMap.h> +#include <Blob/KeyParser.h> +#include <Common/StreamUtil.h> +#include <Common/LofarLogger.h> + +#include <casa/Quanta/MVTime.h> +#include <casa/Quanta/MVAngle.h> +#include <casa/Utilities/MUString.h> +#include <casa/Containers/Block.h> +#include <iostream> +#include <string> +#include <pwd.h> +#include <unistd.h> +#include <libgen.h> + +using namespace std; +using namespace casa; +using namespace LOFAR; +using namespace SourceDB; +using namespace ParmDB; + +LOFAR::SourceDB::SourceDB* sourcetab; + +enum PTCommand { + NOCMD, + OPEN, + CREATE, + CLOSE, + CLEAR, + RANGE, + SHOW, + NAMES, + NEW, + UPD, + DEL, + QUIT +}; + +char bool2char (bool val) +{ + return (val ? 'y' : 'n'); +} + +void showValues (std::ostream& os, const vector<double>& values, + const vector<int>& shape) +{ + int n = values.size(); + if (n > 0) { + os << values[0]; + for (int i=1; i<n; i++) { + os << ',' << values[i]; + } + } + os << " shape=" << shape; +} + +void showHelp() +{ + cerr << endl; + cerr << "Show and update contents of source tables containing the" << endl; + cerr << "source parameters." << endl; + cerr << " create db='username' dbtype='aips' tablename='sourcedb'" << endl; + cerr << " open db='username' dbtype='aips' tablename='sourcedb'" << endl; + cerr << " quit (or exit or stop)" << endl; + cerr << endl; + cerr << " show [sourcename_pattern] [domain=spec,] [ra=, dec=, radius=1 (in arcsec)]" << endl; + cerr << " names [sourcename_pattern]" << endl; + cerr << " add sourcename domain=spec, valuespec" << endl; + cerr << " update sourcename_pattern [domain=spec,] valuespec" << endl; + cerr << " remove sourcename_pattern [domain=spec,]" << endl; + cerr << endl; + cerr << " domain gives a 1-dim or 2-dim domain as:" << endl; + cerr << " domain=[stfreq,endfreq,sttime,endtime]" << endl; + cerr << " or domain=[st=[stf,stt],end=[endf,endt] or size=[sizef,sizet]]" << endl; + cerr << " valuespec gives the values of the source attributes as" << endl; + cerr << " key=value pairs separated by commas." << endl; + cerr << " Attributes not given are not changed. Values shown are defaults when adding." << endl; + cerr << " type='point' (source type; default is point)" << endl; + cerr << " ra=12:2:34.1 (ra in J2000)" << endl; + cerr << " dec=12.2.34.1 (dec in J2000)" << endl; + cerr << " flux=[1,0,0,0] (flux I,Q,U,V; default of each is 0)" << endl; + cerr << endl; +} + +PTCommand getCommand (char*& str) +{ + PTCommand cmd = NOCMD; + while (*str == ' ') { + str++; + } + const char* sstr = str; + while (*str != ' ' && *str != '\0') { + str++; + } + string sc(sstr, str-sstr); + if (sc == "show" || sc == "list") { + cmd = SHOW; + } else if (sc == "names") { + cmd = NAMES; + } else if (sc == "new" || sc == "insert" || sc == "add") { + cmd = NEW; + } else if (sc == "update") { + cmd = UPD; + } else if (sc == "delete" || sc == "remove" || sc == "erase") { + cmd = DEL; + } else if (sc == "open") { + cmd = OPEN; + } else if (sc == "close") { + cmd = CLOSE; + } else if (sc == "clear") { + cmd = CLEAR; + } else if (sc == "create") { + cmd = CREATE; + } else if (sc == "stop" || sc == "quit" || sc == "exit") { + cmd = QUIT; + } + return cmd; +} + +std::string getUserName() +{ + // On Cray XT3 getpwuid is unavailable. +#ifndef USE_NOSOCKETS + passwd* aPwd; + if ((aPwd = getpwuid(getuid())) != 0) { + return aPwd->pw_name; + } +#endif + return "test"; +} + + +std::string getSourceName (char*& str) +{ + while (*str == ' ') { + str++; + } + if (*str == '\0') { + return ""; + } + char* sstr = str; + bool foundeq = false; + while (*str != ' ' && *str != '\0') { + if (*str == '=') { + foundeq = true; + break; + } + str++; + } + // If an = was found, no source is given. + if (foundeq) { + str = sstr; + return ""; + } + return std::string(sstr, str-sstr); +} + +vector<double> getArray (const KeyValueMap& kvmap, const std::string& arrName, + uint size=0, double defaultValue = 1) +{ + vector<double> res(size, 0.); + KeyValueMap::const_iterator value = kvmap.find(arrName); + if (value == kvmap.end()) { + if (size > 0) res[0] = defaultValue; + return res; + } + vector<double> vec; + if (value->second.dataType() == KeyValue::DTValueVector) { + const vector<KeyValue>& vvec = value->second.getVector(); + for (uint i=0; i<vvec.size(); i++) { + vec.push_back (vvec[i].getDouble()); + } + } else { + value->second.get (vec); + } + if (size == 0) { + return vec; + } + ASSERTSTR (vec.size() <= size, "More than "<<size<<" values are given"); + for (uint i=0; i<vec.size(); ++i) { + res[i] = vec[i]; + } + return res; +} + +bool getDomainVector (vector<double>& vec, const vector<KeyValue>& vals) +{ + vec.reserve (vals.size()); + for (vector<KeyValue>::const_iterator iter = vals.begin(); + iter != vals.end(); + iter++) { + if (iter->dataType() == KeyValue::DTString) { + MUString str (iter->getString()); + Quantity res; + if (MVTime::read (res, str)) { + vec.push_back (res.getValue("s")); + } else { + cout << "Error in interpreting " << iter->getString() << endl; + return false; + } + } else { + vec.push_back (iter->getDouble()); + } + } + return true; +} + +ParmDomain getDomain (const KeyValueMap& kvmap, int size=0) +{ + KeyValueMap::const_iterator value = kvmap.find("domain"); + vector<double> st; + vector<double> end; + if (value != kvmap.end()) { + bool ok = false; + // See if given as domain=[start=[],end=[] or size=[]]. + if (value->second.dataType() == KeyValue::DTValueMap) { + const KeyValueMap& kvm = value->second.getValueMap(); + KeyValueMap::const_iterator key = kvm.find("st"); + if (key != kvm.end()) { + bool okv = getDomainVector (st, key->second.getVector()); + key = kvm.find("end"); + bool hasend = (key != kvm.end()); + if (hasend) okv = okv && getDomainVector (end, key->second.getVector()); + key = kvm.find("size"); + bool hassize = (key != kvm.end()); + if (hassize) end = key->second.getVecDouble(); + // end and size cannot be given both. + if (hasend != hassize) { + if (st.size() == end.size()) { + ok = okv; + if (hassize) { + for (uint i=0; i<end.size(); ++i) { + end[i] += st[i]; + } + } + } + } + } + } else { + // Given as a vector of values (as stx,endx,sty,endy,...). + vector<double> vec; + ok = getDomainVector (vec, value->second.getVector()); + if (ok) { + if (vec.size() % 2 != 0) { + ok = false; + } else { + int nr = vec.size() / 2; + st.resize(nr); + end.resize(nr); + for (int i=0; i<nr; ++i) { + st[i] = vec[2*i]; + end[i] = vec[2*i + 1]; + } + } + } + } + ASSERTSTR (ok, + "domain must be given as [[stf,endf],[stt,endt],...]\n" + "or as [st=[stf,...],end=[endf,...] or size=[sizef,...]]"); + } + if (size > 0) { + ASSERTSTR (int(st.size()) <= size, "Domain has too many axes"); + int nr = size - st.size(); + for (int i=0; i<nr; ++i) { + st.push_back (0); + end.push_back (1); + } + } + return ParmDomain(st, end); +} + +void showDomain (const ParmDomain& domain) +{ + const vector<double>& st = domain.getStart(); + const vector<double>& end = domain.getEnd(); + if (st.size() == 2) { + cout << " freq="; + if (st[0] == -1e30 && end[0] == 1e30) { + cout << "all"; + } else { + cout <<'[' << st[0]/1e6 << " MHz " << (end[0] - st[0] < 0 ? "-" : "+") + << (end[0]-st[0])/1e3 << " KHz]"; + } + cout << " time="; + if (st[1] == -1e30 && end[1] == 1e30) { + cout << "all"; + } else { + cout << '[' << MVTime::Format(MVTime::YMD, 6) + << MVTime(Quantity(st[1], "s")) << " " + << (end[1] - st[1] < 0 ? "-" : "+") << (end[1] - st[1]) << " sec]"; + } + } else { + for (uint i=0; i<st.size(); ++i) { + if (i != 0) cout << ','; + cout << '[' << st[i] << ',' << end[i] << ']'; + } + } +} + +// IMPLEMENTATION OF THE COMMANDS +void showSource (const SourceValue& source, bool showAll) +{ + cout << source.getName(); + cout << " type=" << source.getType(); + cout << " ra=" << MVAngle::Format(MVAngle::TIME, 9) + << MVAngle(Quantity(source.getRA(), "rad")); + cout << " dec=" << MVAngle::Format(MVAngle::ANGLE, 9) + << MVAngle(Quantity(source.getDEC(), "rad")); + cout << endl; + if (showAll) { + cout << " spectralindex=" << source.getSpectralIndex(); + cout << " domain:"; + showDomain (source.getDomain()); + cout << endl; + } +} + +void showSources (const list<SourceValue>& sourceSet, bool showAll) +{ + int nr=0; + for (list<SourceValue>::const_iterator iter = sourceSet.begin(); + iter != sourceSet.end(); + iter++) { + showSource (*iter, showAll); + ++nr; + } + if (nr != 1) { + cout << nr << " source records found" << endl; + } +} + +void newSource (const std::string& sourceName, const ParmDomain& domain, + const KeyValueMap& kvmap) +{ + SourceValue pvalue; + string type = kvmap.getString("type", "point"); + ASSERTSTR (type=="point", "Currently only point surces can be given"); + ASSERTSTR (kvmap.isDefined("ra"), "Keyword 'ra' not given"); + ASSERTSTR (kvmap.isDefined("dec"), "Keyword 'dec' not given"); + double ra = kvmap.getDouble("ra", 0); + double dec = kvmap.getDouble("dec", 0); + double spindex = kvmap.getDouble ("spindex", 1); + vector<double> vflux = getArray (kvmap, "flux", 4); + double flux[4] = {1,0,0,0}; + if (vflux.size() > 0) flux[0] = vflux[0]; + if (vflux.size() > 1) flux[1] = vflux[1]; + if (vflux.size() > 2) flux[2] = vflux[2]; + if (vflux.size() > 3) flux[3] = vflux[3]; + pvalue.setPointSource (sourceName, ra, dec, flux, spindex); + pvalue.setDomain (domain); + showSource (pvalue, true); + sourcetab->addSource (pvalue); + cout << "Wrote new record for source " << sourceName << endl; +} + +void updateSource (SourceValue& pvalue, const KeyValueMap& kvmap) +{ + if (kvmap.isDefined("ra")) { + pvalue.setRA (kvmap.getDouble("ra", 0)); + } + if (kvmap.isDefined("dec")) { + pvalue.setDEC (kvmap.getDouble("dec", 0)); + } + if (kvmap.isDefined("spindex")) { + pvalue.setSpectralIndex (kvmap.getDouble("spindex", 0)); + } + if (kvmap.isDefined("flux")) { + vector<double> vflux = getArray (kvmap, "flux", 4); + if (vflux.size() > 0) pvalue.setFluxI (vflux[0]); + if (vflux.size() > 1) pvalue.setFluxQ (vflux[1]); + if (vflux.size() > 2) pvalue.setFluxU (vflux[2]); + if (vflux.size() > 3) pvalue.setFluxV (vflux[3]); + } + showSource (pvalue, true); +} + +void updateSources (list<SourceValue>& sourceSet, KeyValueMap& kvmap) +{ + for (list<SourceValue>::iterator iter = sourceSet.begin(); + iter != sourceSet.end(); + iter++) { + updateSource (*iter, kvmap); + } + sourcetab->lock(); + for (list<SourceValue>::iterator iter = sourceSet.begin(); + iter != sourceSet.end(); + iter++) { + sourcetab->updateSource (*iter); + } + sourcetab->unlock(); +} + + +void doIt (bool noPrompt) +{ + sourcetab = 0; + const int buffersize = 1024000; + char cstra[buffersize]; + // Loop until stop is given. + while (true) { + try { + if (!noPrompt) { + cerr << "Command: "; + } + char* cstr = cstra; + if (! cin.getline (cstr, buffersize)) { + cerr << "Error while reading command" << endl; + break; + } + while (*cstr == ' ') { + cstr++; + } + // Skip empty lines and comment lines. + if (cstr[0] == 0 || cstr[0] == '#') { + continue; + } + if (cstr[0] == '?') { + showHelp(); + } else { + PTCommand cmd = getCommand (cstr); + ASSERTSTR(cmd!=NOCMD, "invalid command given: " << cstr); + if (cmd == QUIT) { + break; + } + string sourceName; + if (cmd == OPEN) { + ASSERTSTR(sourcetab==0, "OPEN or CREATE already done"); + // Connect to database. + KeyValueMap kvmap = KeyParser::parse (cstr); + string dbUser = kvmap.getString ("user", getUserName()); + string dbHost = kvmap.getString ("host", "dop50.astron.nl"); + string dbName = kvmap.getString ("db", dbUser); + string dbType = kvmap.getString ("dbtype", "aips"); + string tableName = kvmap.getString ("tablename", "MeqSource"); + SourceDBMeta meta (dbType, tableName); + meta.setSQLMeta (dbName, dbUser, "", dbHost); + sourcetab = new LOFAR::SourceDB::SourceDB (meta); + } else if (cmd == CREATE) { + ASSERTSTR(sourcetab==0, "OPEN or CREATE already done"); + // create dataBase + KeyValueMap kvmap = KeyParser::parse (cstr); + string dbUser = kvmap.getString ("user", getUserName()); + string dbHost = kvmap.getString ("host", "dop50.astron.nl"); + string dbName = kvmap.getString ("db", dbUser); + string dbType = kvmap.getString ("dbtype", "aips"); + string tableName = kvmap.getString ("tablename", "MeqSource"); + SourceDBMeta meta (dbType, tableName); + meta.setSQLMeta (dbName, dbUser, "", dbHost); + sourcetab = new LOFAR::SourceDB::SourceDB (meta, true); + } else { + ASSERTSTR(sourcetab!=0, "OPEN or CREATE not done yet"); + if (cmd == CLOSE) { + delete sourcetab; + sourcetab = 0; + } else if (cmd == CLEAR) { + // clear database tables + sourcetab->clearTables(); + } else { + // Other commands expect a possible sourcename and keywords + sourceName = getSourceName (cstr); + KeyValueMap kvmap = KeyParser::parse (cstr); + // For list functions the sourcename defaults to *. + // Otherwise a sourcename or pattern must be given. + if (cmd!=SHOW && cmd!=NAMES) { + ASSERTSTR (!sourceName.empty(), "No source name given"); + } else if (sourceName.empty()) { + sourceName = "*"; + } + if (cmd==NEW || cmd==UPD || cmd==DEL) { + // Read the given parameters and domains. + ParmDomain domain = getDomain(kvmap); + list<SourceValue> sourceset; + vector<string> names (sourcetab->getNames(sourceName)); + if (!names.empty()) { + sourceset = sourcetab->getSources (names, domain); + } + int nrsource = sourceset.size(); + if (cmd == NEW) { + ASSERTSTR (sourceset.empty(), + "the source/domain already exists"); + newSource (sourceName, domain, kvmap); + } else if (cmd == UPD) { + ASSERTSTR (! sourceset.empty(), "source/domain not found"); + updateSources (sourceset, kvmap); + cout << "Updated " << nrsource << " source record(s)" << endl; + } else if (cmd == DEL) { + ASSERTSTR (! sourceset.empty(), "parameter/domain not found"); + sourcetab->deleteSources (sourceName, domain); + cout << "Deleted " << nrsource << " source record(s)" << endl; + } + } else if (cmd == SHOW) { + ParmDomain domain = getDomain(kvmap); + list<SourceValue> sourceset; + if (kvmap.isDefined("ra") && kvmap.isDefined("dec")) { + double ra = kvmap.getDouble("ra", 0); + double dec = kvmap.getDouble("dec", 0); + double radius = kvmap.getDouble("radius", 1); + radius = Quantity(radius, "arcsec").getValue("rad"); + sourceset = sourcetab->getSources (ra, dec, radius, domain); + } else { + // Read the given parameters and domains. + vector<string> names (sourcetab->getNames(sourceName)); + if (!names.empty()) { + sourceset = sourcetab->getSources (names, domain); + } + } + showSources (sourceset, true); + } else if (cmd==NAMES) { + // show names matching the pattern. + cout << "names: " + << sourcetab->getNames(sourceName) << endl; + } else { + cerr << "Unknown command given (type ? for help)" << endl; + } + } + } + } + } catch (std::exception& x) { + cerr << "Exception: " << x.what() << endl; + } + } + delete sourcetab; + sourcetab = 0; +} + +int main (int argc, char *argv[]) +{ + const char* progName = basename(argv[0]); + INIT_LOGGER(progName); + + try { + doIt (argc > 1); + } catch (std::exception& x) { + std::cerr << "Caught exception: " << x.what() << std::endl; + return 1; + } + + return 0; +} diff --git a/CEP/BB/SourceDB/src/versionsourcedb.cc b/CEP/BB/SourceDB/src/versionsourcedb.cc new file mode 100644 index 0000000000000000000000000000000000000000..b5450496b5cdd0c89acaacf0a34ca7ee239f50b9 --- /dev/null +++ b/CEP/BB/SourceDB/src/versionsourcedb.cc @@ -0,0 +1,17 @@ +//# Print revision info; generated by autoconf_share/makeversion + +#include <SourceDB/Package__Version.h> +#include <Common/Version.h> +#include <iostream> + +using namespace LOFAR; + +int main (int argc, const char* argv[]) +{ + std::string type = "brief"; + if (argc > 1) { + type = argv[1]; + } + Version::show<SourceDBVersion> (std::cout, "SourceDB", type); + return 0; +}