yade-dev team mailing list archive
-
yade-dev team
-
Mailing list archive
-
Message #01194
[svn] r1752 - in trunk: gui/py scripts scripts/test
Author: eudoxos
Date: 2009-04-09 12:15:52 +0200 (Thu, 09 Apr 2009)
New Revision: 1752
Modified:
trunk/gui/py/log.cpp
trunk/gui/py/plot.py
trunk/gui/py/yade-multi
trunk/scripts/multi.py
trunk/scripts/test/facet-topo.py
Log:
1. Add preliminary gnuplot plots merging facility to yade-multi
2. Fix yade.log module so that it also works without log4cxx (and gives 1 warning)
3. Switch to new syntax in scripts/plot.py
Modified: trunk/gui/py/log.cpp
===================================================================
--- trunk/gui/py/log.cpp 2009-04-08 20:31:20 UTC (rev 1751)
+++ trunk/gui/py/log.cpp 2009-04-09 10:15:52 UTC (rev 1752)
@@ -1,38 +1,48 @@
-
-#ifdef LOG4CXX
-
#include<boost/python.hpp>
+#include<string>
#include<yade/lib-base/Logging.hpp>
-#include<log4cxx/logmanager.h>
-#include<string>
using namespace boost;
-
enum{ll_TRACE,ll_DEBUG,ll_INFO,ll_WARN,ll_ERROR,ll_FATAL};
-void logSetLevel(std::string loggerName,int level){
- std::string fullName(loggerName.empty()?"yade":("yade."+loggerName));
- if(!log4cxx::LogManager::exists(fullName)) throw std::invalid_argument("No logger named `"+fullName+"'");
- log4cxx::LevelPtr l;
- switch(level){
- #ifdef LOG4CXX_TRACE
- case ll_TRACE: l=log4cxx::Level::getTrace(); break;
- case ll_DEBUG: l=log4cxx::Level::getDebug(); break;
- case ll_INFO: l=log4cxx::Level::getInfo(); break;
- case ll_WARN: l=log4cxx::Level::getWarn(); break;
- case ll_ERROR: l=log4cxx::Level::getError(); break;
- case ll_FATAL: l=log4cxx::Level::getFatal(); break;
- #else
- case ll_TRACE: l=log4cxx::Level::DEBUG; break;
- case ll_DEBUG: l=log4cxx::Level::DEBUG; break;
- case ll_INFO: l=log4cxx::Level::INFO; break;
- case ll_WARN: l=log4cxx::Level::WARN; break;
- case ll_ERROR: l=log4cxx::Level::ERROR; break;
- case ll_FATAL: l=log4cxx::Level::FATAL; break;
- #endif
- default: throw std::invalid_argument("Unrecognized logging level "+lexical_cast<std::string>(level));
+#ifdef LOG4CXX
+ #include<log4cxx/logmanager.h>
+
+ void logSetLevel(std::string loggerName,int level){
+ std::string fullName(loggerName.empty()?"yade":("yade."+loggerName));
+ if(!log4cxx::LogManager::exists(fullName)) throw std::invalid_argument("No logger named `"+fullName+"'");
+ log4cxx::LevelPtr l;
+ switch(level){
+ #ifdef LOG4CXX_TRACE
+ case ll_TRACE: l=log4cxx::Level::getTrace(); break;
+ case ll_DEBUG: l=log4cxx::Level::getDebug(); break;
+ case ll_INFO: l=log4cxx::Level::getInfo(); break;
+ case ll_WARN: l=log4cxx::Level::getWarn(); break;
+ case ll_ERROR: l=log4cxx::Level::getError(); break;
+ case ll_FATAL: l=log4cxx::Level::getFatal(); break;
+ #else
+ case ll_TRACE: l=log4cxx::Level::DEBUG; break;
+ case ll_DEBUG: l=log4cxx::Level::DEBUG; break;
+ case ll_INFO: l=log4cxx::Level::INFO; break;
+ case ll_WARN: l=log4cxx::Level::WARN; break;
+ case ll_ERROR: l=log4cxx::Level::ERROR; break;
+ case ll_FATAL: l=log4cxx::Level::FATAL; break;
+ #endif
+ default: throw std::invalid_argument("Unrecognized logging level "+lexical_cast<std::string>(level));
+ }
+ log4cxx::LogManager::getLogger("yade."+loggerName)->setLevel(l);
}
- log4cxx::LogManager::getLogger("yade."+loggerName)->setLevel(l);
-}
+#else
+ bool warnedOnce=false;
+ void logSetLevel(std::string loggerName, int level){
+ // better somehow python's raise RuntimeWarning, but not sure how to do that from c++
+ // it shouldn't be trapped by boost::python's exception translator, just print warning
+ // Do like this for now.
+ if(!warnedOnce){
+ LOG_WARN("Yade was compiled without log4cxx support. Setting log levels from python will have no effect (warn once).");
+ warnedOnce=true;
+ }
+ }
+#endif
BOOST_PYTHON_MODULE(log){
python::def("setLevel",logSetLevel,"Set minimum severity level (constants TRACE,DEBUG,INFO,WARN,ERROR,FATAL) for given logger\nleading 'yade.' will be appended automatically to the logger name; if logger is '', the root logger 'yade' will be operated on.");
@@ -43,5 +53,3 @@
python::scope().attr("ERROR")=(int)ll_ERROR;
python::scope().attr("FATAL")=(int)ll_FATAL;
}
-
-#endif
Modified: trunk/gui/py/plot.py
===================================================================
--- trunk/gui/py/plot.py 2009-04-08 20:31:20 UTC (rev 1751)
+++ trunk/gui/py/plot.py 2009-04-09 10:15:52 UTC (rev 1752)
@@ -122,6 +122,8 @@
timestamp: append numeric time to the basename
varData: whether file to plot will be declared as variable or be in-place in the plot expression
comment: a user comment (may be multiline) that will be embedded in the control file
+
+ Returns name fo the gnuplot file created.
"""
import time,bz2
vars=data.keys(); vars.sort()
@@ -153,6 +155,7 @@
fPlot.write("plot "+",".join([" %s using %d:%d title '%s(%s)' with lines"%(dataFile,vars.index(p)+1,vars.index(pp[0])+1,pp[0],p) for pp in plots_p])+"\n")
i+=1
fPlot.close()
+ return baseName+'.gnuplot'
Modified: trunk/gui/py/yade-multi
===================================================================
--- trunk/gui/py/yade-multi 2009-04-08 20:31:20 UTC (rev 1751)
+++ trunk/gui/py/yade-multi 2009-04-09 10:15:52 UTC (rev 1752)
@@ -3,7 +3,7 @@
#
# portions © 2008 Václav Šmilauer <eudoxos@xxxxxxxx>
-import os, sys, thread, time
+import os, sys, thread, time,logging
class JobInfo():
def __init__(self,num,id,command,log,nSlots):
@@ -67,8 +67,10 @@
parser.add_option('-l','--lines',dest='lineList',help='Lines of TABLE to use, in the format 2,3-5,8,11-13 (default: all available lines in TABLE)',metavar='LIST')
parser.add_option('--nice',dest='nice',type='int',help='Nice value of spawned jobs (default: 10)',default=10)
parser.add_option('--executable',dest='executable',help='Name of the program to run (default: %s)'%sys.argv[0][:-6],default=sys.argv[0][:-6],metavar='FILE') ## strip the '-multi' extension
+parser.add_option('--gnuplot',dest='gnuplotOut',help='Gnuplot file where gnuplot from all jobs should be put together',default=None,metavar='FILE')
+parser.add_option('--dry-run',dest='dryRun',help='Do not actually run (useful for getting gnuplot only, for instance)',default=False)
opts,args=parser.parse_args()
-logFormat,lineList,maxJobs,nice,executable=opts.logFormat,opts.lineList,opts.maxJobs,opts.nice,opts.executable
+logFormat,lineList,maxJobs,nice,executable,gnuplotOut,dryRun=opts.logFormat,opts.lineList,opts.maxJobs,opts.nice,opts.executable,opts.gnuplotOut,opts.dryRun
if len(args)!=2:
#print "Exactly two non-option arguments must be specified -- parameter table and script to be run.\n"
@@ -104,8 +106,8 @@
return ret
useLines0=numRange2List(lineList)
for l in useLines0:
- if l not in availableLines: print "WARNING: skipping unavailable line %d that was requested from the command line."%l
- elif l==1: print "WARNING: skipping line 1 that should contain variable labels"
+ if l not in availableLines: logging.warn('skipping unavailable line %d that was requested from the command line.'%l)
+ elif l==1: logging.warn("WARNING: skipping line 1 that should contain variable labels")
else: useLines+=[l]
else: useLines=availableLines
try:
@@ -131,7 +133,7 @@
if head=='!EXEC': executable=values[l][col]
if head=='!OMP_NUM_THREADS': nSlots=int(values[l][col])
if head[0]=='!': envVars+=['%s=%s'%(head[1:],values[l][col])]
- if nSlots>maxJobs: print 'WARNING: job #%d wants %d slots but only %d are available'%(i,nSlots,maxJobs)
+ if nSlots>maxJobs: logging.warning('WARNING: job #%d wants %d slots but only %d are available'%(i,nSlots,maxJobs))
jobs.append(JobInfo(i,idStrings[l] if idStrings else '#'+str(i),'PARAM_TABLE=%s:%d %s nice -n %d %s -N PythonUI -- -n -x %s > %s 2>&1'%(table,l,' '.join(envVars),nice,executable,simul,logFile),logFile,nSlots))
print "Job summary:"
@@ -139,5 +141,36 @@
print ' #%d (%s%s):'%(job.num,job.id,'' if job.nSlots==1 else '/%d'%job.nSlots),job.command
# OK, go now
-runJobs(jobs,maxJobs)
-print 'All jobs finished, bye.'
+if not dryRun: runJobs(jobs,maxJobs)
+
+print 'All jobs finished,',
+if not gnuplotOut:
+ print 'bye.'
+else:
+ print 'assembling gnuplot files…'
+ for job in jobs:
+ for l in file(job.log):
+ if l.startswith('gnuplot '):
+ job.plot=l.split()[1]
+ break
+ preamble,plots='',[]
+ for job in jobs:
+ if not job.plot:
+ # warn here
+ continue
+ for l in file(job.plot):
+ if l.startswith('plot'):
+ # attempt to parse the plot line
+ ll=l.split(' ',1)[1][:-1] # rest of the line, without newline
+ # replace title 'something' with title 'description: something'
+ ll,nn=re.subn(r'title\s+[\'"]([^\'"]*)[\'"]',r'title "'+job.id+r': \1"',ll)
+ if nn==0:
+ logging.error("Plot line in "+job.plot+" not parsed (skipping): "+ll)
+ plots.append(ll)
+ break
+ if not plots: # first plot, copy all preceding lines
+ preamble+=l
+ gp=file(gnuplotOut,'w')
+ gp.write(preamble)
+ gp.write('plot '+','.join(plots))
+ print "Finished writing "+gnuplotOut+", bye."
Modified: trunk/scripts/multi.py
===================================================================
--- trunk/scripts/multi.py 2009-04-08 20:31:20 UTC (rev 1751)
+++ trunk/scripts/multi.py 2009-04-09 10:15:52 UTC (rev 1752)
@@ -8,24 +8,23 @@
o=Omega()
o.initializers=[
- MetaEngine('BoundingVolumeMetaEngine',[EngineUnit('InteractingSphere2AABB'),EngineUnit('InteractingFacet2AABB'),EngineUnit('MetaInteractingGeometry2AABB')])
+ BoundingVolumeMetaEngine([InteractingSphere2AABB(),InteractingFacet2AABB(),MetaInteractingGeometry2AABB()])
]
o.engines=[
- StandAloneEngine('PhysicalActionContainerReseter'),
- MetaEngine('BoundingVolumeMetaEngine',[
- EngineUnit('InteractingSphere2AABB'),
- EngineUnit('InteractingBox2AABB'),
- EngineUnit('MetaInteractingGeometry2AABB')
+ PhysicalActionContainerReseter(),
+ BoundingVolumeMetaEngine([
+ InteractingSphere2AABB(),
+ InteractingBox2AABB(),
+ MetaInteractingGeometry2AABB()
]),
- StandAloneEngine('PersistentSAPCollider'),
- MetaEngine('InteractionGeometryMetaEngine',[
- EngineUnit('InteractingSphere2InteractingSphere4SpheresContactGeometry'),
- EngineUnit('InteractingBox2InteractingSphere4SpheresContactGeometry')
- ]),
- MetaEngine('InteractionPhysicsMetaEngine',[EngineUnit('SimpleElasticRelationships')]),
- StandAloneEngine('ElasticContactLaw'),
- DeusExMachina('GravityEngine',{'gravity':[0,0,gravity]}), ## here we use the 'gravity' parameter
- DeusExMachina('NewtonsDampedLaw',{'damping':0.4})
+ PersistentSAPCollider(),
+ InteractionDispatchers(
+ [InteractingSphere2InteractingSphere4SpheresContactGeometry(),InteractingBox2InteractingSphere4SpheresContactGeometry()],
+ [SimpleElasticRelationships(),],
+ [ef2_Spheres_Elastic_ElasticLaw(),]
+ )
+ GravityEngine(gravity=(0,0,gravity)), ## here we use the 'gravity' parameter
+ NewtonsDampedLaw(damping=0.4)
]
o.bodies.append(utils.box([0,50,0],extents=[1,50,1],dynamic=False,color=[1,0,0],young=30e9,poisson=.3,density=density)) ## here we use the density parameter
o.bodies.append(utils.sphere([0,0,10],1,color=[0,1,0],young=30e9,poisson=.3,density=density)) ## here again
Modified: trunk/scripts/test/facet-topo.py
===================================================================
--- trunk/scripts/test/facet-topo.py 2009-04-08 20:31:20 UTC (rev 1751)
+++ trunk/scripts/test/facet-topo.py 2009-04-09 10:15:52 UTC (rev 1752)
@@ -20,5 +20,5 @@
utils.facet([(1,1,0),(1,0,0),(0,1,0)]),
])
O.step()
- #assert(O.bodies[0].phys['edgeAdjIds'][1]==1 and O.bodies[1].phys['edgeAdjIds'][0]==1)
+ assert(O.bodies[0].phys['edgeAdjIds'][1]==1 and O.bodies[1].phys['edgeAdjIds'][0]==1)
assert(topo['commonEdgesFound']==1)